Support complete public relationship observations for optimistic presentation hosting
This commit is contained in:
@@ -22,6 +22,8 @@ export interface InspectionTemplate {
|
|||||||
inputs?: PublicQueryContract;
|
inputs?: PublicQueryContract;
|
||||||
view?: PublicQueryContract;
|
view?: PublicQueryContract;
|
||||||
server?: PublicQueryContract;
|
server?: PublicQueryContract;
|
||||||
|
completeInputs?: PublicQueryContract;
|
||||||
|
completeView?: PublicQueryContract;
|
||||||
}
|
}
|
||||||
/** A finite installed template per interface/lane, not a per-client query compiler.
|
/** A finite installed template per interface/lane, not a per-client query compiler.
|
||||||
* Flags select public cache boundaries; normal scope identity bounds specialization. */
|
* 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));
|
.sort((a, b) => (a.id < b.id ? -1 : 1));
|
||||||
if (!members.length || members.length > 128) continue;
|
if (!members.length || members.length > 128) continue;
|
||||||
const template: InspectionTemplate = { interface: iface.revisionId, members: [] };
|
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[] = [],
|
const fields: unknown[] = [],
|
||||||
selections: unknown[] = [],
|
selections: unknown[] = [],
|
||||||
inputFields: Record<string, 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);
|
const many = member.kind === "relationship" && ["many", "many-unique"].includes(member.cardinality);
|
||||||
// Only native edges promise the relationship traversal used by the interpreter.
|
// Only native edges promise the relationship traversal used by the interpreter.
|
||||||
if (member.kind === "relationship" && providers.some((op) => op!.binding.kind !== "edge")) continue;
|
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 });
|
template.members.push({ id: member.id, name: member.displayName, key, flag, lane, many });
|
||||||
inputFields[flag] = scalar("bool");
|
inputFields[flag] = scalar("bool");
|
||||||
const field = selection(member.displayName, {
|
const field = selection(member.displayName, {
|
||||||
@@ -95,18 +99,27 @@ export function compileInspectionTemplates(plan: ExecutionPlan) {
|
|||||||
if (member.target.kind === "interface")
|
if (member.target.kind === "interface")
|
||||||
Object.assign(field, { targetInterfaceRevisionId: member.target.interfaceRevisionId });
|
Object.assign(field, { targetInterfaceRevisionId: member.target.interfaceRevisionId });
|
||||||
if (many) {
|
if (many) {
|
||||||
inputFields[key + "First"] = scalar("int32");
|
const bound = key + (complete ? "All" : "First");
|
||||||
inputFields[key + "After"] = optional(scalar("string"));
|
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, {
|
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: [
|
||||||
selection("entries", { selection: [selection("key"), selection("node", { selection: [meta()] })] }),
|
selection("entries", { selection: [...keySelections, selection("node", { selection: [meta()] })] }),
|
||||||
selection("pageInfo", { selection: [selection("hasNextPage"), selection("endCursor")] }),
|
...(complete
|
||||||
|
? []
|
||||||
|
: [selection("pageInfo", { selection: [selection("hasNextPage"), selection("endCursor")] })]),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
output = record({
|
output = record({
|
||||||
entries: { kind: "list", value: record({ key: scalar("string"), node }) },
|
entries: { kind: "list", value: record({ ...keyFields, node }) },
|
||||||
pageInfo: record({ hasNextPage: scalar("bool"), endCursor: optional(scalar("string")) }),
|
...(complete
|
||||||
|
? {}
|
||||||
|
: { pageInfo: record({ hasNextPage: scalar("bool"), endCursor: optional(scalar("string")) }) }),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Object.assign(field, { selection: [meta()] });
|
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)) {
|
for (const kind of lane === "local" ? (["inputs", "view"] as const) : (["server"] as const)) {
|
||||||
const query = JSON.stringify([iface.revisionId, kind]);
|
const templateKey = complete ? (kind === "inputs" ? "completeInputs" : "completeView") : kind;
|
||||||
const sourceQuery = JSON.stringify([iface.revisionId, "inputs"]);
|
const query = JSON.stringify([iface.revisionId, templateKey]);
|
||||||
|
const sourceQuery = JSON.stringify([iface.revisionId, complete ? "completeInputs" : "inputs"]);
|
||||||
const program = {
|
const program = {
|
||||||
...base,
|
...base,
|
||||||
id: JSON.stringify([inspectionPackage, query]),
|
id: JSON.stringify([inspectionPackage, query]),
|
||||||
@@ -167,7 +181,7 @@ export function compileInspectionTemplates(plan: ExecutionPlan) {
|
|||||||
};
|
};
|
||||||
queries.push(program);
|
queries.push(program);
|
||||||
contracts.push(contract);
|
contracts.push(contract);
|
||||||
template[kind] = contract;
|
template[templateKey] = contract;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (template.members.length) templates.push(template);
|
if (template.members.length) templates.push(template);
|
||||||
|
|||||||
@@ -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 === "content") &&
|
||||||
template.members.some((member) => member.name === "highlights"),
|
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.equal(document.view.sourceQuery, document.inputs.query);
|
||||||
assert.ok(document.members.find((member) => member.name === "highlights")?.many);
|
assert.ok(document.members.find((member) => member.name === "highlights")?.many);
|
||||||
assert.ok(!document.members.some((member) => member.name === "revise"));
|
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.ok(!JSON.stringify(result.templates).includes("slot:"));
|
||||||
assert.equal(result.queries.length, result.contracts.length);
|
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);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user