import assert from "node:assert/strict"; import test from "node:test"; import { compileCapabilityResourceSource } from "../src/capability-language/parser.js"; import { compileQuery } from "../src/query/compile.js"; import type { PackageRevision } from "../src/capability-model/types.js"; const source = { repository: "https://example.test/fragments", commit: "a".repeat(40) }; const compiled = compileCapabilityResourceSource( `interface Item id "item" revision "item@1" { queryable value title id "title" : string {get id "title:get" execution snapshot;} queryable rpc value remote id "remote" : string {get id "remote:get";} }`, { source }, ); if (!compiled.ok || compiled.resource.kind !== "interface") throw Error(JSON.stringify(compiled.diagnostics)); const item = compiled.resource.revision; function pkg(body: string, imports: PackageRevision[] = [], name = "Views") { const result = compileCapabilityResourceSource( `import interface Item; ${imports.map((p) => `import package ${p.displayName};`).join(" ")} package ${name} id "${name}" revision "${name}@1" {${body}}`, { source, environment: { interfaces: new Map([["Item", item]]), interfaceClosure: [item], packages: new Map(imports.map((p) => [p.displayName, p])), }, }, ); assert.ok(result.ok, JSON.stringify(result.diagnostics)); if (result.resource.kind !== "package") throw Error("package required"); return result.resource.revision; } test("exported fragments generate local projection and direct admission", async () => { const p = pkg('query fragment Row id "row" root Item document "row.graphql" fragment "Row";'); assert.equal(p.queries!.length, 2); const local = p.queries!.find((q) => !q.fragment?.admission)!; assert.equal(local.placement?.kind, "local"); const checked = await compileQuery(local, [item], async () => "fragment Row on Item {title}"); assert.equal(checked.output.kind, "record"); assert.match(checked.document, /query QuixosFragment/); await assert.rejects( compileQuery(local, [item], async () => "fragment Row on Item {remote}"), /QUERY_LOCAL_DEPENDENCY/, ); }); test("imported fragments retain checked occurrences and require exact roots", async () => { const provider = pkg('query fragment Row id "row" root Item document "row.graphql" fragment "Row";', [], "Provider"); const checked = await compileQuery( provider.queries!.find((q) => !q.fragment?.admission)!, [item], async () => "fragment Row on Item {title}", ); const consumer = pkg( 'query Screen id "screen" root Item document "screen.graphql" operation "Screen" {replica; fragments Provider.Row;}', [provider], ); const result = await compileQuery( consumer.queries![0]!, [item], async () => "query Screen {root {...Row}}", async () => checked, ); assert.equal(result.selection[0]!.selection[0]!.fragmentSpread?.digest, checked.definitionDigest); assert.equal(result.selection[0]!.selection[0]!.fragmentSpread?.root, item.revisionId); assert.ok(result.effects.some((e) => e.memberId === "title")); const bound = await compileQuery( { ...consumer.queries![0]!, importedFragments: consumer.queries![0]!.importedFragments!.map((entry) => ({ ...entry, mode: "reference" })), }, [item], async () => "query Screen {root {...Row}}", async () => checked, ); assert.equal(bound.selection[0]!.selection.find((entry) => entry.fragmentSpread)?.fragmentSpread?.mode, "reference"); assert( !bound.selection[0]!.selection.some((entry) => entry.memberId === "title"), "A fragment binding does not evaluate its fields in the parent", ); assert(!JSON.stringify(bound.output).includes('"title"'), "Parent output excludes separately observed fields"); const wrong = { ...checked, declaration: { ...checked.declaration, root: { ...checked.declaration.root, interface: "different@1" as typeof item.revisionId }, }, }; await assert.rejects( compileQuery( consumer.queries![0]!, [item], async () => "query Screen {root {...Row}}", async () => wrong, ), /FRAGMENT_ROOT_MISMATCH/, ); }); test("fragment variable mappings are explicit and checked", async () => { const provider = pkg( 'query fragment Row id "row" root Item document "row.graphql" fragment "Row" operation "Inputs";', [], "Provider", ); const checked = await compileQuery( provider.queries!.find((q) => !q.fragment?.admission)!, [item], async () => "query Inputs($show: Boolean!) {root {...Row}} fragment Row on Item {_camino {ref} title @include(if:$show)}", ); const build = (mapping: string) => pkg( `query Screen id "screen" root Item document "screen.graphql" operation "Screen" {replica; fragments Provider.Row ${mapping};}`, [provider], ).queries![0]!; const document = "query Screen($visible: Boolean!) {root {...Row}}"; await assert.rejects( compileQuery( build(""), [item], async () => document, async () => checked, ), /FRAGMENT_VARIABLE_MAPPING/, ); const result = await compileQuery( build("with {show to visible;}"), [item], async () => document, async () => checked, ); assert.deepEqual(result.selection[0]!.selection[0]!.fragmentSpread?.variables, { show: "visible" }); const referenceDeclaration = build("with {show to visible;}"); referenceDeclaration.importedFragments = referenceDeclaration.importedFragments!.map((entry) => ({ ...entry, mode: "reference", })); const binding = await compileQuery( referenceDeclaration, [item], async () => document, async () => checked, ); assert.deepEqual(binding.selection[0]!.selection[0]!.fragmentSpread?.variables, { show: "visible" }); assert.notEqual(binding.definitionDigest, result.definitionDigest); await assert.rejects( compileQuery( referenceDeclaration, [item], async () => document.replace("$visible: Boolean!", "$visible: Boolean!, $unused: Boolean!"), async () => checked, ), /never used/, ); const changedDigest = await compileQuery( referenceDeclaration, [item], async () => document, async () => ({ ...checked, definitionDigest: "b".repeat(64) }), ); assert.notEqual( changedDigest.definitionDigest, binding.definitionDigest, "A bound fragment's identity remains in the parent contract digest", ); await assert.rejects( compileQuery( build("with {show to visible;}"), [item], async () => document.replace("Boolean!", "Boolean"), async () => checked, ), /FRAGMENT_VARIABLE_TYPE/, ); }); test("independent fragment package survives execution lowering and typed client generation", async () => { const { loadReaderWorkspace, readReaderFixture } = await import("./reader-fixture.js"); const { compileExecutionPlan } = await import("../src/execution-world/plan.js"); const { compileQueryProgram } = await import("../src/execution-world/queries.js"); const { generatePackageQueryClientBindings } = await import("../src/execution-world/client-contracts.js"); const workspace = await loadReaderWorkspace(); const comment = workspace.interfaceImports.find((i) => i.displayName === "CommentData")!; const parsed = compileCapabilityResourceSource( `import interface CommentData; package CommentRows id "comment-rows" revision "comment-rows@1" { query fragment Row id "row" root CommentData document "row.graphql" fragment "CommentRow"; }`, { source, environment: { interfaces: new Map([["CommentData", comment]]), interfaceClosure: [comment] } }, ); assert.ok(parsed.ok, JSON.stringify(parsed.diagnostics)); if (parsed.resource.kind !== "package") throw Error("expected package"); const provider = parsed.resource.revision; provider.checkedQueries = await Promise.all( provider.queries!.map((q) => compileQuery( q, workspace.interfaceImports, async () => "fragment CommentRow on CommentData {content {text tags}}", ), ), ); workspace.packageImports.push(provider); const consumer = workspace.packageImports.find((p) => p.displayName === "ReaderRuntime")!; const declaration = consumer.queries!.find((q) => q.displayName === "ReaderScreen")!; declaration.importedFragments = [ { packageRevisionId: provider.revisionId, packageAlias: "CommentRows", fragmentId: "row", variables: {} }, ]; const document = (await readReaderFixture("queries/reader-screen.graphql")).replace( "_camino { ref } content { text tags }", "...CommentRow", ); const checked = await compileQuery( declaration, workspace.interfaceImports, async () => document, async () => provider.checkedQueries!.find((q) => q.declaration.id === "row")!, ); consumer.checkedQueries = consumer.checkedQueries!.map((q) => (q.declaration.id === declaration.id ? checked : q)); const plan = compileExecutionPlan(workspace); const program = compileQueryProgram(plan) as { queries: { id: string; fragment?: { package: string; id: string }; selection: unknown }[]; }; assert.deepEqual(program.queries.find((q) => q.fragment)?.fragment, { package: provider.revisionId, id: "row", digest: provider.checkedQueries!.find((q) => q.declaration.id === "row")!.definitionDigest, }); const screen = program.queries.find((q) => q.id === JSON.stringify([consumer.revisionId, declaration.id]))!; assert.match(JSON.stringify(screen.selection), /fragmentSpread/); const generated = generatePackageQueryClientBindings(consumer, undefined, workspace.packageImports); assert.match(generated, /"CommentRows": \{"Row": definePackageFragment/); assert.ok(generated.includes(JSON.stringify(comment.revisionId))); assert.ok(!generated.includes('"Row$inputs": definePackageQuery')); });