61 lines
2.4 KiB
TypeScript
61 lines
2.4 KiB
TypeScript
import { portableValueSchema } from "../bindings/portable.js";
|
|
import { ExecutionPlanError, hexDigest, type ExecutionPlan } from "./plan.js";
|
|
import type { ValueType } from "../capability-model/types.js";
|
|
|
|
const lowerTypes = (value: unknown): unknown =>
|
|
JSON.parse(
|
|
JSON.stringify(value, (key, value: unknown) => {
|
|
if (
|
|
key === "type" &&
|
|
value &&
|
|
typeof value === "object" &&
|
|
"kind" in value &&
|
|
["scalar", "builtin", "optional", "list", "record", "object-ref"].includes(String(value.kind))
|
|
)
|
|
return portableValueSchema(value as ValueType);
|
|
return value;
|
|
}),
|
|
);
|
|
|
|
/** Checked query IR and installed getter identities, without GraphQL schemas/parsers or SQL adapters.
|
|
* Keep authored selection names only for output paths; field access uses resolved interface/member IDs. */
|
|
export function compileQueryProgram(plan: ExecutionPlan): unknown {
|
|
if (hexDigest(plan.definition) !== plan.digest)
|
|
throw new ExecutionPlanError("INVALID_PLAN", "queries", "Plan digest mismatch");
|
|
const interfaces = plan.definition.workspace.interfaceImports;
|
|
return {
|
|
codec: "camino-query-program-v1",
|
|
plan: plan.digest,
|
|
queries: plan.definition.queries.map(({ id, query, admittedOperations }) => {
|
|
const checked = query.checked;
|
|
return {
|
|
id,
|
|
placement: checked.declaration.placement?.kind ?? "remote",
|
|
source:
|
|
checked.declaration.placement?.kind === "local"
|
|
? JSON.stringify([query.packageRevisionId, checked.declaration.placement.sourceQueryId])
|
|
: null,
|
|
root: checked.declaration.root,
|
|
atoms: query.rootAtoms,
|
|
variables: portableValueSchema(checked.variables),
|
|
defaults: checked.variableDefaults,
|
|
selection: lowerTypes(checked.selection),
|
|
budgets: checked.declaration.budgets,
|
|
fields: query.fields.map((field) => {
|
|
const member = interfaces
|
|
.find((i) => i.revisionId === field.interfaceRevisionId)!
|
|
.members.find((m) => m.id === field.memberId)!;
|
|
return {
|
|
atom: field.atomId,
|
|
interface: field.interfaceRevisionId,
|
|
member: field.memberId,
|
|
name: member.displayName,
|
|
operation: JSON.stringify([field.atomId, field.interfaceRevisionId, field.getter]),
|
|
};
|
|
}),
|
|
admittedOperations,
|
|
};
|
|
}),
|
|
};
|
|
}
|