Expose confirmed server projections through the typed replica client

This commit is contained in:
Timothy J. Aveni
2026-09-21 00:27:39 -07:00
parent 08e322e59f
commit b4ac9700c6
5 changed files with 77 additions and 10 deletions
+48 -9
View File
@@ -53,29 +53,68 @@ export function generatePortableClientBindings(
}
const queries = new Map<string, string[]>();
const views = new Map<string, string[]>();
const serverProjections = new Map<string, string[]>();
const results = new Map<string, string[]>();
for (const query of plan.definition.queries) {
const declaration = query.query.checked.declaration;
if (!declaration.placement) continue;
const pkg = workspace.packageImports.find((p) => p.revisionId === query.query.packageRevisionId)!;
const alias = JSON.stringify([pkg.displayName, declaration.displayName]);
if (seen.has(`query:${alias}`)) throw new PortableBindingError(alias, "Ambiguous query alias");
seen.add(`query:${alias}`);
if (declaration.placement.kind === "local") {
const list = views.get(pkg.displayName) ?? [];
list.push(
`${JSON.stringify(declaration.displayName)}: ${JSON.stringify({ id: query.id, plan: plan.digest, source: JSON.stringify([query.query.packageRevisionId, declaration.placement.sourceQueryId]) })} as const satisfies LocalQueryDescriptor`,
);
views.set(pkg.displayName, list);
const addResult = () => {
if (conditional(query.query.checked.selection)) {
unavailable.push({ key: query.id, reason: "CONDITIONAL_RESULT_DECODER_UNSUPPORTED" });
continue;
return;
}
const decoders = results.get(pkg.displayName) ?? [];
decoders.push(
`${JSON.stringify(declaration.displayName)}: (data: Json): ${tsType(query.query.checked.output)} => decodeArgument(${JSON.stringify(portableValueSchema(query.query.checked.output))}, { codec: "camino-value-v1", usage: "argument", value: data }, { workspace: workspaceId(${JSON.stringify(workspace.workspaceId)}), limits: { bytes: ${declaration.budgets.resultBytes + 128}, nodes: 100000, depth: 64 } }) as ${tsType(query.query.checked.output)}`,
);
results.set(pkg.displayName, decoders);
};
if (!declaration.placement) {
const operations = query.operations.map(
(key) => plan.definition.operations.find((operation) => operation.key === key)!,
);
const live = (selections: readonly QuerySelection[]): boolean =>
selections.some((selection) => !!selection.liveSelectionId || live(selection.selection));
if (
operations.some(
(operation) => operation.execution.kind !== "snapshot" || !operation.execution.targets.includes("server"),
) ||
live(query.query.checked.selection)
) {
unavailable.push({ key: query.id, reason: "QUERY_NOT_SNAPSHOT_PROJECTION" });
continue;
}
const list = serverProjections.get(pkg.displayName) ?? [];
list.push(
JSON.stringify(declaration.displayName) +
": " +
JSON.stringify({
kind: "server-projection",
id: query.id,
plan: plan.digest,
root: declaration.root.interface,
rootKind: declaration.root.kind,
}) +
" as const satisfies ServerProjection<" +
JSON.stringify(declaration.root.interface) +
", " +
JSON.stringify(declaration.root.kind) +
">",
);
serverProjections.set(pkg.displayName, list);
addResult();
continue;
}
if (declaration.placement.kind === "local") {
const list = views.get(pkg.displayName) ?? [];
list.push(
`${JSON.stringify(declaration.displayName)}: ${JSON.stringify({ id: query.id, plan: plan.digest, source: JSON.stringify([query.query.packageRevisionId, declaration.placement.sourceQueryId]) })} as const satisfies LocalQueryDescriptor`,
);
views.set(pkg.displayName, list);
addResult();
continue;
}
const list = queries.get(pkg.displayName) ?? [];
@@ -86,5 +125,5 @@ export function generatePortableClientBindings(
}
const groups = (entries: Map<string, string[]>) =>
[...entries].map(([name, values]) => `${JSON.stringify(name)}: {${values.join(",\n")}}`).join(",\n");
return `// Generated application descriptors. Regenerate; do not edit.\nimport { defineOperationDescriptor, decodeArgument, workspaceId, type Json, type PreparedChange, type ManagedReference, type ReplicaProjection, type LocalQueryDescriptor } from ${JSON.stringify(options.runtimeModule ?? "@quixos/camino-replica-core")};\nexport const planDigest = ${JSON.stringify(plan.digest)};\nexport const operations = {${groups(atoms)}} as const;\nexport const queries = {${groups(queries)}} as const;\nexport const views = {${groups(views)}} as const;\nexport const results = {${groups(results)}} as const;\nexport const unavailable = ${JSON.stringify(unavailable)} as const;\n`;
return `// Generated application descriptors. Regenerate; do not edit.\nimport { defineOperationDescriptor, decodeArgument, workspaceId, type Json, type PreparedChange, type ManagedReference, type ReplicaProjection, type ServerProjection, type LocalQueryDescriptor } from ${JSON.stringify(options.runtimeModule ?? "@quixos/camino-replica-core")};\nexport const planDigest = ${JSON.stringify(plan.digest)};\nexport const operations = {${groups(atoms)}} as const;\nexport const queries = {${groups(queries)}} as const;\nexport const views = {${groups(views)}} as const;\nexport const serverProjections = {${groups(serverProjections)}} as const;\nexport const results = {${groups(results)}} as const;\nexport const unavailable = ${JSON.stringify(unavailable)} as const;\n`;
}