Scope presentation associations to PresentationMount and retain navigation queries

Generate checked navigation query pairs from closed React contracts before
package checking. Retain per-type subscriptions under the logical
PresentationMount and resolve cold component metadata independently of code.

Keep scoped occurrence membership and idempotent local preparation in the
presentation library; copy directly through state contracts without reading
other PresentationMounts' source associations. Preserve normal transaction
creation, pending references, portal synchronization and detach.

Exercise automatic object refs in Reader queries, imported fragments and
structured/aggregate results. Add heterogeneous owner-index, live dependency,
cold metadata, browser ownership and latency coverage. Document measured
improvements, supported query limits and qualification evidence.
This commit is contained in:
Timothy J. Aveni
2026-09-26 12:32:47 -07:00
parent 3728612e8c
commit ad64ba532f
8 changed files with 260 additions and 24 deletions
+129 -4
View File
@@ -226,18 +226,33 @@ test("retired live syntax fails with migration guidance", async () => {
test("implicit references reject aliases which occupy the canonical metadata path", async () => {
for (const invalid of ["_camino: title", "_camino {ref: __typename}"])
await assert.rejects(compile(`query Upcoming {root {items(first: 3) {entries {node {...Row}}}}}`, `fragment Row on TaskFacts {${invalid}}`), /QUERY_VALIDATION|Introspection/);
await assert.rejects(
compile(
`query Upcoming {root {items(first: 3) {entries {node {...Row}}}}}`,
`fragment Row on TaskFacts {${invalid}}`,
),
/QUERY_VALIDATION|Introspection/,
);
});
test("implicit reference merges with conditional aggregate metadata", async () => {
const checked = await compileQuery({ ...fixture(""), fragments: [] }, [collection, facts], async () =>
`query Upcoming($show: Boolean!) {root {_camino @include(if: $show) {relations {items {aggregate {count}}}}}}`);
const checked = await compileQuery(
{ ...fixture(""), fragments: [] },
[collection, facts],
async () =>
`query Upcoming($show: Boolean!) {root {_camino @include(if: $show) {relations {items {aggregate {count}}}}}}`,
);
const metadata = checked.selection[0]!.selection.filter((field) => field.key === "_camino");
assert.equal(metadata.length, 1);
assert.deepEqual(metadata[0]!.conditions, []);
assert.equal(metadata[0]!.selection.find((field) => field.name === "relations")!.conditions.length, 1);
assert.deepEqual(metadata[0]!.selection.find((field) => field.name === "ref")!.conditions, []);
assert.equal(metadata[0]!.selection.find((field) => field.name === "relations")!.selection[0]!.selection[0]!.selection.some((field) => field.name === "_camino"), false);
assert.equal(
metadata[0]!.selection
.find((field) => field.name === "relations")!
.selection[0]!.selection[0]!.selection.some((field) => field.name === "_camino"),
false,
);
});
test("qualified interface predicates and guaranteed inline projections retain nominal reads", async () => {
@@ -280,6 +295,21 @@ test("qualified interface predicates and guaranteed inline projections retain no
const node = objects.selection[0]!.selection[0]!;
assert.equal(node.selection.find((s) => s.key === "ownerLabel")!.interfaceRevisionId, owned.revisionId);
assert.equal(node.selection.filter((s) => s.key === "_camino").length, 1);
await assert.rejects(
compileQuery(declaration, [item, owned, owner], async () =>
document.replace("ownerLabel: label", "ownerLabel: label _camino {ref}"),
),
/QUERY_VALIDATION/,
);
const explicitProjectionRef = await compileQuery(declaration, [item, owned, owner], async () =>
document.replace("ownerLabel: label", "ownerLabel: label ownedIdentity: _camino {ref}"),
);
const projectedNode = explicitProjectionRef.selection[0]!.selection[0]!.selection[0]!.selection[0]!;
assert.equal(
projectedNode.selection.find((field) => field.key === "_camino")!.selection.find((field) => field.key === "ref")!
.targetInterfaceRevisionId,
item.revisionId,
);
await assert.rejects(
compileQuery(declaration, [item, owned, owner], async () => document.replace("ownerLabel: label", "label")),
/QUERY_PROJECTION_CONFLICT|QUERY_VALIDATION/,
@@ -369,3 +399,98 @@ test("query allowlist and two-sided RPC effects fail during compilation", async
await rejects(compile(document.replace("...Row", "__typename ...Row")), "QUERY_UNSUPPORTED_FEATURE");
await rejects(compile(document, "fragment Row on TaskFacts { ...Row }"), "QUERY_VALIDATION");
});
test("unselected atom relationships do not require views on reference-only targets", async () => {
const target = iface(`external atom Detail id "detail";
interface Referenced id "referenced" revision "referenced@1" {
queryable relation details id "details" : many atom Detail {resolve id "details:resolve";}
}`);
const subject = iface(
`external atom Detail id "detail"; import interface Referenced;
interface Subject id "subject" revision "subject@1" {
queryable relation selected id "selected" : optional-one interface Referenced {resolve id "selected:resolve";}
}`,
[target],
);
const declaration = {
...fixture(""),
root: { kind: "object" as const, interface: subject.revisionId },
fragments: [],
};
const document = "query Upcoming {root {selected {_camino {ref}}}}";
const checked = await compileQuery(declaration, [subject, target], async () => document);
assert.match(JSON.stringify(checked.output), /referenced@1/);
await assert.rejects(
compileQuery(
declaration,
[subject, target],
async () => "query Upcoming {root {selected {details(all: 3) {entries {node {_camino {ref}}}}}}}",
),
/QUERY_VIEW_REQUIRED/,
);
});
test("React tooling generates checked owner queries from imported closed navigation fields", async () => {
const { presentationQueries } = await import("../src/bindings/presentation-queries.js");
const mount = iface('interface PresentationMount id "mount" revision "mount@1" {}');
const subject = iface('interface Subject id "subject" revision "subject@1" {}');
const state = iface(
`import interface PresentationMount; import interface Subject;
interface PresentationState id "state" revision "state@1" {
queryable value occurrence id "occurrence" : string {get id "occurrence:get" execution snapshot targets [browser,server];}
queryable relation presentationMount id "mount" : optional-one interface PresentationMount {resolve id "mount:resolve" execution snapshot targets [browser,server];}
queryable relation parent id "parent" : optional-one interface PresentationState {resolve id "parent:resolve" execution snapshot targets [browser,server];}
queryable relation source id "source" : exactly-one interface Subject {resolve id "source:resolve" execution snapshot targets [browser,server];}
}`,
[mount, subject],
);
const navigation = iface(
`import interface PresentationState;
interface Navigation<value T> id "navigation" revision "navigation@1" requires PresentationState {
queryable value custom id "custom" : T {get id "custom:get" execution snapshot targets [browser,server];}
}`,
[mount, subject, state],
);
const react = iface(
`import interface PresentationState;
interface ReactComponent<object Subject, object Navigation implements PresentationState> id "react" revision "react@1" {
module render id "render" contract "org.quixos.react.component/2" subject object Subject;
}`,
[mount, subject, state],
);
const dependencies = [mount, subject, state, navigation, react];
const parsed = compileCapabilityResourceSource(
`import interface ReactComponent; import interface Navigation; import interface Subject;
package Example id "example" revision "example@1" {
module Screen id "screen" implements ReactComponent<interface Subject,interface Navigation<record {label:string;count:int32;}>>.render;
}`,
{
source,
environment: {
interfaces: new Map(dependencies.map((entry) => [entry.displayName, entry])),
interfaceClosure: dependencies,
},
},
);
assert.ok(parsed.ok, JSON.stringify(parsed.diagnostics));
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);
const checked = await Promise.all(
parsed.resource.revision.queries!.map((query) =>
compileQuery(query, contracts, async (name) => documents.get(name)!),
),
);
assert.deepEqual(
checked.map((query) => query.declaration.placement?.kind),
["replica", "local"],
);
assert.match(JSON.stringify(checked[0]!.output), /"custom":\{"kind":"record","fields":\{"label"/);
assert.match(JSON.stringify(checked[0]!.selection), /"kind":"as"/);
assert(
checked.every((query) =>
query.effects.some((effect) => effect.memberId === "mount" && effect.uses.includes("predicate")),
),
);
});