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, }; }), }; }