Support complete public relationship observations for optimistic presentation hosting

This commit is contained in:
Timothy J. Aveni
2026-09-25 12:09:10 -07:00
parent 1bc3c69de3
commit 76d5cff6fb
2 changed files with 29 additions and 14 deletions
+26 -12
View File
@@ -22,6 +22,8 @@ export interface InspectionTemplate {
inputs?: PublicQueryContract;
view?: PublicQueryContract;
server?: PublicQueryContract;
completeInputs?: PublicQueryContract;
completeView?: PublicQueryContract;
}
/** A finite installed template per interface/lane, not a per-client query compiler.
* Flags select public cache boundaries; normal scope identity bounds specialization. */
@@ -54,7 +56,9 @@ export function compileInspectionTemplates(plan: ExecutionPlan) {
.sort((a, b) => (a.id < b.id ? -1 : 1));
if (!members.length || members.length > 128) continue;
const template: InspectionTemplate = { interface: iface.revisionId, members: [] };
for (const lane of ["local", "server"] as const) {
for (const mode of ["local", "complete", "server"] as const) {
const lane = mode === "server" ? "server" : "local";
const complete = mode === "complete";
const fields: unknown[] = [],
selections: unknown[] = [],
inputFields: Record<string, unknown> = {},
@@ -76,7 +80,7 @@ export function compileInspectionTemplates(plan: ExecutionPlan) {
const many = member.kind === "relationship" && ["many", "many-unique"].includes(member.cardinality);
// Only native edges promise the relationship traversal used by the interpreter.
if (member.kind === "relationship" && providers.some((op) => op!.binding.kind !== "edge")) continue;
if (lane === "local" || !portable)
if (!complete && (lane === "local" || !portable))
template.members.push({ id: member.id, name: member.displayName, key, flag, lane, many });
inputFields[flag] = scalar("bool");
const field = selection(member.displayName, {
@@ -95,18 +99,27 @@ export function compileInspectionTemplates(plan: ExecutionPlan) {
if (member.target.kind === "interface")
Object.assign(field, { targetInterfaceRevisionId: member.target.interfaceRevisionId });
if (many) {
inputFields[key + "First"] = scalar("int32");
inputFields[key + "After"] = optional(scalar("string"));
const bound = key + (complete ? "All" : "First");
inputFields[bound] = scalar("int32");
if (!complete) inputFields[key + "After"] = optional(scalar("string"));
const keyFields = { key: scalar("string"), ...(member.keyType ? { mapKey: scalar(member.keyType) } : {}) };
const keySelections = [selection("key"), ...(member.keyType ? [selection("mapKey")] : [])];
Object.assign(field, {
arguments: { first: variable(key + "First"), after: variable(key + "After") },
arguments: complete
? { all: variable(bound) }
: { first: variable(bound), after: variable(key + "After") },
selection: [
selection("entries", { selection: [selection("key"), selection("node", { selection: [meta()] })] }),
selection("pageInfo", { selection: [selection("hasNextPage"), selection("endCursor")] }),
selection("entries", { selection: [...keySelections, selection("node", { selection: [meta()] })] }),
...(complete
? []
: [selection("pageInfo", { selection: [selection("hasNextPage"), selection("endCursor")] })]),
],
});
output = record({
entries: { kind: "list", value: record({ key: scalar("string"), node }) },
pageInfo: record({ hasNextPage: scalar("bool"), endCursor: optional(scalar("string")) }),
entries: { kind: "list", value: record({ ...keyFields, node }) },
...(complete
? {}
: { pageInfo: record({ hasNextPage: scalar("bool"), endCursor: optional(scalar("string")) }) }),
});
} else {
Object.assign(field, { selection: [meta()] });
@@ -147,8 +160,9 @@ export function compileInspectionTemplates(plan: ExecutionPlan) {
},
};
for (const kind of lane === "local" ? (["inputs", "view"] as const) : (["server"] as const)) {
const query = JSON.stringify([iface.revisionId, kind]);
const sourceQuery = JSON.stringify([iface.revisionId, "inputs"]);
const templateKey = complete ? (kind === "inputs" ? "completeInputs" : "completeView") : kind;
const query = JSON.stringify([iface.revisionId, templateKey]);
const sourceQuery = JSON.stringify([iface.revisionId, complete ? "completeInputs" : "inputs"]);
const program = {
...base,
id: JSON.stringify([inspectionPackage, query]),
@@ -167,7 +181,7 @@ export function compileInspectionTemplates(plan: ExecutionPlan) {
};
queries.push(program);
contracts.push(contract);
template[kind] = contract;
template[templateKey] = contract;
}
}
if (template.members.length) templates.push(template);
+3 -2
View File
@@ -12,7 +12,8 @@ test("public member inspection installs a finite set of typed lazy templates", a
template.members.some((member) => member.name === "content") &&
template.members.some((member) => member.name === "highlights"),
)!;
assert.ok(document.inputs && document.view && document.server);
assert.ok(document.inputs && document.view && document.server && document.completeInputs && document.completeView);
assert.equal(document.completeView.sourceQuery, document.completeInputs.query);
assert.equal(document.view.sourceQuery, document.inputs.query);
assert.ok(document.members.find((member) => member.name === "highlights")?.many);
assert.ok(!document.members.some((member) => member.name === "revise"));
@@ -31,5 +32,5 @@ test("public member inspection installs a finite set of typed lazy templates", a
}
assert.ok(!JSON.stringify(result.templates).includes("slot:"));
assert.equal(result.queries.length, result.contracts.length);
assert.ok(result.queries.length <= plan.definition.workspace.interfaceImports.length * 3);
assert.ok(result.queries.length <= plan.definition.workspace.interfaceImports.length * 5);
});