import assert from "node:assert/strict"; import { mkdtemp, mkdir, writeFile, rm } from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import test from "node:test"; import { compileCapabilityResourceRepository, type PackageQueryGenerator, } from "../src/capability-language/assembly.js"; import { defaultQueryBudgets } from "../src/query/types.js"; test("an explicit non-React frontend emits checked queries for its own selection model", async (context) => { const directory = await mkdtemp(path.join(os.tmpdir(), "qx-query-generator-")); context.after(() => rm(directory, { recursive: true, force: true })); const commit = "a".repeat(40); const source = (name: string) => ({ resolver: "git" as const, repository: `https://example.test/${name}.git`, commit, }); const lock = (imports: string) => `quixos-lock version 1 { quixos source { repository "https://example.test/quixos.git"; commit "${commit}"; } ${imports} }`; const dependency = (name: string) => `interface ${name} source { repository "${source(name).repository}"; commit "${commit}"; }`; for (const name of ["Sensor", "DeviceSelection", "Device"]) await mkdir(path.join(directory, name)); await writeFile(path.join(directory, "Sensor", "quixos.lock"), lock("")); await writeFile( path.join(directory, "Sensor", "interface.qx"), ` interface Sensor id "sensor" revision "sensor@1" { queryable value reading id "reading" : int64 { get id "reading:get"; } } `, ); await writeFile(path.join(directory, "DeviceSelection", "quixos.lock"), lock(dependency("Sensor"))); await writeFile( path.join(directory, "DeviceSelection", "interface.qx"), ` import interface Sensor; interface DeviceSelection id "device-selection" revision "device-selection@1" { queryable relation selectedSensor id "selected-sensor" : optional-one interface Sensor { resolve id "selected-sensor:resolve"; } } `, ); await writeFile(path.join(directory, "Device", "quixos.lock"), lock(dependency("DeviceSelection"))); await writeFile( path.join(directory, "Device", "package.qx"), ` import interface DeviceSelection; package Device id "device" revision "device@1" {} `, ); await writeFile( path.join(directory, "Device", "inputs.graphql"), `query Selected { root { selectedSensor { reading } } }`, ); const options = { rootDirectory: path.join(directory, "Device"), kind: "package" as const, source: source("Device"), resolveResource: async (ref: { repository: string }) => ({ directory: path.join(directory, new URL(ref.repository).pathname.slice(1, -4)), }), }; const plain = await compileCapabilityResourceRepository(options); assert.equal(plain.resource.kind, "package"); if (plain.resource.kind !== "package") throw Error("Expected package"); assert.equal(plain.resource.revision.queries?.length ?? 0, 0); const generateQueries: PackageQueryGenerator = async ({ interfaces, readSource }) => ({ queries: [ { id: "selected-inputs", displayName: "SelectedInputs", root: { kind: "object", interface: interfaces.find((iface) => iface.displayName === "DeviceSelection")!.revisionId, }, document: "generated/selected.graphql", operation: "Selected", fragments: [], views: [], allowances: [], budgets: { ...defaultQueryBudgets }, watch: false, placement: { kind: "replica" }, }, ], documents: new Map([["generated/selected.graphql", await readSource("inputs.graphql")]]), compositions: [ { id: "display", maxQueries: 1, input: { kind: "record", fields: { device: { kind: "object-ref", expectation: { kind: "interface", interfaceRevisionId: interfaces.find((iface) => iface.displayName === "DeviceSelection")!.revisionId, }, }, }, }, steps: [ { name: "selection", query: "selected-inputs", root: { from: "input", path: ["device"] }, arguments: { record: {} }, }, ], }, ], }); const built = await compileCapabilityResourceRepository({ ...options, generateQueries }); assert.equal(built.resource.kind, "package"); if (built.resource.kind !== "package") throw Error("Expected package"); assert.equal(built.resource.revision.checkedQueries?.length, 1); const checked = built.resource.revision.checkedQueries![0]!; assert.equal(checked.declaration.root.interface, "device-selection@1"); assert.ok(checked.effects.some((effect) => effect.memberId === "reading")); assert.ok(checked.effects.some((effect) => effect.memberId === "selected-sensor")); assert.ok(checked.definitionDigest); assert.equal(built.resource.revision.queryCompositions?.[0]?.dependencies[0]?.digest, checked.definitionDigest); assert.equal( built.resources.some((resource) => /React|PresentationMount/.test(resource.key)), false, ); await assert.rejects( compileCapabilityResourceRepository({ ...options, generateQueries: async (input) => { const result = await generateQueries(input); return { ...result, documents: new Map([["generated/selected.graphql", "query Selected { root { invented } }"]]), }; }, }), /invented/, ); await assert.rejects( compileCapabilityResourceRepository({ ...options, generateQueries: async (input) => { const result = await generateQueries(input); return { ...result, queries: [...result.queries, ...result.queries] }; }, }), /Generated query conflicts/, ); });