Use explicit navigation projections for React presentation readiness (#339)

This commit is contained in:
Quixos Development Agent 5ffdc2ce-2936-4c70-8208-3a9da53f4aa9
2026-10-24 06:39:33 +00:00
parent bc9a7ef2cf
commit ee84025322
6 changed files with 109 additions and 42 deletions
+8 -2
View File
@@ -520,7 +520,7 @@ test("React tooling generates checked owner queries from imported closed navigat
if (parsed.resource.kind !== "package") throw Error("package required");
const contracts = [...dependencies, ...(parsed.resource.specializations ?? [])];
const documents = presentationQueries(parsed.resource.revision, contracts);
assert.equal(documents.size, 2);
assert.equal(documents.size, 4);
const checked = await Promise.all(
parsed.resource.revision.queries!.map((query) =>
compileQuery(query, contracts, async (name) => documents.get(name)!),
@@ -528,10 +528,16 @@ test("React tooling generates checked owner queries from imported closed navigat
);
assert.deepEqual(
checked.map((query) => query.declaration.placement?.kind),
["replica", "local"],
["replica", "local", "replica", "local"],
);
assert.match(JSON.stringify(checked[0]!.output), /"custom":\{"kind":"record","fields":\{"label"/);
assert.match(JSON.stringify(checked[0]!.selection), /"kind":"as"/);
for (const identity of checked.slice(2)) {
assert.match(identity.declaration.id, /:identity-(inputs|view)$/);
assert.doesNotMatch(JSON.stringify(identity.output), /"custom"/);
assert.match(JSON.stringify(identity.output), /_presentationOccurrence/);
assert.match(JSON.stringify(identity.output), /_presentationSource/);
}
assert(
checked.every((query) =>
query.effects.some((effect) => effect.memberId === "mount" && effect.uses.includes("predicate")),
+43 -2
View File
@@ -29,12 +29,15 @@ const navigation = iface(
}`,
[item],
);
function declaration(root: InterfaceRevision = item) {
function declaration(root: InterfaceRevision = item, dependencies: InterfaceRevision[] = []) {
const result = compileCapabilityResourceSource(
`import interface ${root.displayName}; package Views id "views" revision "views@1" {
query Open id "open" root ${root.displayName} document "open.graphql" operation "Open" {replica; max rows 10;}
}`,
{ source, environment: { interfaces: new Map([[root.displayName, root]]), interfaceClosure: [root, item] } },
{
source,
environment: { interfaces: new Map([[root.displayName, root]]), interfaceClosure: [root, item, ...dependencies] },
},
);
assert.ok(result.ok, JSON.stringify(result.diagnostics));
if (result.resource.kind !== "package") throw Error("Expected Package");
@@ -103,6 +106,44 @@ test("bounded list bindings preserve entry identity without requesting details",
assert(!JSON.stringify(projection.selection).includes('"name":"body"'));
assert(tree.maxOccurrences <= 256);
});
test("literal collection windows bound handles independently of detail row budgets", async () => {
const source = { ...declaration(navigation), budgets: { ...declaration(navigation).budgets, rows: 20000 } };
const query = (limit: string, variables = "") => `query Open${variables} {root {
items(first: ${limit}) {entries {node {...Body @boundary(name:"body")}}}
}} fragment Body on Item {body}`;
const checked = await compileQuery(source, [item, navigation], async () => query("3"));
assert.equal(checked.tree!.maxOccurrences, 7);
await assert.rejects(
compileQuery(source, [item, navigation], async () => query("200")),
/QUERY_TREE_LIMIT/,
);
await assert.rejects(
compileQuery(source, [item, navigation], async () => query("$first", "($first:Int!)")),
/QUERY_TREE_LIMIT/,
);
const group = iface(
`import interface Item; interface Group id "group" revision "group@1" {
queryable relation items id "group:items" : many interface Item ordered {resolve id "group:items:resolve" execution snapshot;}
}`,
[item],
);
const groups = iface(
`import interface Group; interface Groups id "groups" revision "groups@1" {
queryable relation groups id "groups:groups" : many interface Group ordered {resolve id "groups:groups:resolve" execution snapshot;}
}`,
[item, group],
);
const nested = { ...declaration(groups, [group]), budgets: source.budgets };
const nestedQuery = (outer: number, inner: number) => `query Open {root {
groups(first:${outer}) {entries {node {items(first:${inner}) {entries {node {...Body @boundary(name:"body")}}}}}}
}} fragment Body on Item {body}`;
const bounded = await compileQuery(nested, [item, group, groups], async () => nestedQuery(2, 3));
assert.equal(bounded.tree!.maxOccurrences, 15, "Nested windows multiply instead of reusing the outer bound");
await assert.rejects(
compileQuery(nested, [item, group, groups], async () => nestedQuery(20, 20)),
/QUERY_TREE_LIMIT/,
);
});
test("guards control boundary participation and invalid syntax fails checking", async () => {
const checked = await compileQuery(
declaration(),