Add exported query fragments and scoped coverage observations
This commit is contained in:
@@ -124,12 +124,64 @@ export function generateInterfaceClientBindings(
|
||||
export function generatePackageQueryClientBindings(
|
||||
pkg: PackageRevision,
|
||||
runtimeModule = "@quixos/camino-replica-core",
|
||||
packages: readonly PackageRevision[] = [pkg],
|
||||
): string {
|
||||
const queries = (pkg.checkedQueries ?? []).map(
|
||||
(query) =>
|
||||
`${JSON.stringify(query.declaration.displayName)}: definePackageQuery<${tsType(query.variables)}, ${tsType(query.output)}, ${JSON.stringify(publicQueryContract(pkg, query.declaration.id).placement)}>(${JSON.stringify(publicQueryContract(pkg, query.declaration.id))})`,
|
||||
);
|
||||
return `// Generated from checked package query contracts. Regenerate; do not edit.\nimport { definePackageQuery, type ManagedReference } from ${JSON.stringify(runtimeModule)};\nexport const queries = {${queries.join(",\n")}} as const;\n`;
|
||||
const queries = (pkg.checkedQueries ?? [])
|
||||
.filter((query) => !query.declaration.fragment)
|
||||
.map(
|
||||
(query) =>
|
||||
`${JSON.stringify(query.declaration.displayName)}: definePackageQuery<${tsType(query.variables)}, ${tsType(query.output)}, ${JSON.stringify(publicQueryContract(pkg, query.declaration.id).placement)}>(${JSON.stringify(publicQueryContract(pkg, query.declaration.id))})`,
|
||||
);
|
||||
const emitFragment = (provider: PackageRevision, id: string) => {
|
||||
const query = provider.checkedQueries?.find((query) => query.declaration.id === id);
|
||||
if (
|
||||
!query?.declaration.fragment ||
|
||||
query.declaration.fragment.admission ||
|
||||
query.declaration.placement?.kind !== "local" ||
|
||||
query.output.kind !== "record" ||
|
||||
!query.output.fields.root
|
||||
)
|
||||
throw new ExecutionPlanError("UNCHECKED_FRAGMENT", id, "Expected a checked local fragment export");
|
||||
const output = query.output.fields.root;
|
||||
const descriptor = {
|
||||
package: provider.revisionId,
|
||||
fragment: id,
|
||||
digest: query.definitionDigest,
|
||||
subject: query.declaration.root.interface,
|
||||
input: portableValueSchema(query.variables),
|
||||
output: portableValueSchema(output),
|
||||
admission: publicQueryContract(provider, query.declaration.placement.sourceQueryId),
|
||||
view: publicQueryContract(provider, id),
|
||||
};
|
||||
return `definePackageFragment<${tsType(query.variables)}, ${tsType(output)}, ${JSON.stringify(query.declaration.root.interface)}>(${JSON.stringify(descriptor)})`;
|
||||
};
|
||||
const fragments = (pkg.checkedQueries ?? [])
|
||||
.filter((query) => query.declaration.fragment && !query.declaration.fragment.admission)
|
||||
.map((query) => `${JSON.stringify(query.declaration.displayName)}: ${emitFragment(pkg, query.declaration.id)}`);
|
||||
const imports = new Map<string, Map<string, string>>();
|
||||
for (const query of pkg.queries ?? [])
|
||||
for (const imported of query.importedFragments ?? []) {
|
||||
if (imported.packageRevisionId === pkg.revisionId) continue;
|
||||
const provider = packages.find((provider) => provider.revisionId === imported.packageRevisionId);
|
||||
const name = provider?.queries?.find((query) => query.id === imported.fragmentId)?.displayName;
|
||||
if (!provider || !name)
|
||||
throw new ExecutionPlanError("UNCHECKED_FRAGMENT", imported.fragmentId, "Missing imported fragment provider");
|
||||
const alias = imported.packageAlias ?? provider.displayName;
|
||||
if (pkg.queries?.some((query) => query.fragment && query.displayName === alias))
|
||||
throw new ExecutionPlanError(
|
||||
"FRAGMENT_ALIAS_COLLISION",
|
||||
alias,
|
||||
"Imported fragment namespace conflicts with a local fragment export",
|
||||
);
|
||||
const entries = imports.get(alias) ?? new Map<string, string>();
|
||||
entries.set(name, emitFragment(provider, imported.fragmentId));
|
||||
imports.set(alias, entries);
|
||||
}
|
||||
for (const [alias, entries] of imports)
|
||||
fragments.push(
|
||||
`${JSON.stringify(alias)}: {${[...entries].map(([name, value]) => `${JSON.stringify(name)}: ${value}`).join(",")}}`,
|
||||
);
|
||||
return `// Generated from checked package query contracts. Regenerate; do not edit.\nimport { definePackageQuery, definePackageFragment, type ManagedReference } from ${JSON.stringify(runtimeModule)};\nexport const queries = {${queries.join(",\n")}} as const;\nexport const fragments = {${fragments.join(",\n")}} as const;\n`;
|
||||
}
|
||||
|
||||
/** Receipt-covered bindings expose the package's imports, component subjects and
|
||||
@@ -157,13 +209,17 @@ export function generateComponentClientBindings(plan: ExecutionPlan, packageRevi
|
||||
.filter((line) => !line.startsWith("import "))
|
||||
.join("\n")
|
||||
.replace("export const interfaces =", "export const subjects =");
|
||||
const queries = generatePackageQueryClientBindings(pkg, "@quixos/camino-react")
|
||||
const queries = generatePackageQueryClientBindings(
|
||||
pkg,
|
||||
"@quixos/camino-react",
|
||||
plan.definition.workspace.packageImports,
|
||||
)
|
||||
.split("\n")
|
||||
.filter((line) => !line.startsWith("import "))
|
||||
.join("\n");
|
||||
return (
|
||||
interfaces +
|
||||
'\nimport {definePackageQuery,type ComponentType,type ComponentProps} from "@quixos/camino-react";\n' +
|
||||
'\nimport {definePackageQuery,definePackageFragment,type ComponentType,type ComponentProps} from "@quixos/camino-react";\n' +
|
||||
subjectBindings +
|
||||
"\n" +
|
||||
queries +
|
||||
|
||||
@@ -30,6 +30,15 @@ export function compileQueryProgram(plan: ExecutionPlan): unknown {
|
||||
const checked = query.checked;
|
||||
return {
|
||||
id,
|
||||
...(checked.declaration.fragment && !checked.declaration.fragment.admission
|
||||
? {
|
||||
fragment: {
|
||||
package: query.packageRevisionId,
|
||||
id: checked.declaration.id,
|
||||
digest: checked.definitionDigest,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
placement: checked.declaration.placement?.kind ?? "remote",
|
||||
source:
|
||||
checked.declaration.placement?.kind === "local"
|
||||
|
||||
Reference in New Issue
Block a user