Add exported query fragments and scoped coverage observations

This commit is contained in:
Timothy J. Aveni
2026-09-22 16:18:57 -07:00
parent eba85ba158
commit a8869e4545
13 changed files with 2503 additions and 1715 deletions
+64 -3
View File
@@ -1380,6 +1380,14 @@ const lowerPackage = (
if (exportContext.packageQuerySpecialization()) return [];
const query = exportContext.packageQuery();
if (query) {
const isFragment = query.FRAGMENT().length > 0;
if (isFragment && (query.FRAGMENT().length !== 2 || query.typeParameters() || query.WORKSPACE()))
loweringIssue(
state,
query,
"invalid-query-fragment",
"Export a fragment on an exact object interface; generic fragments and workspace fragment roots are not supported",
);
const previousParameters = state.types.parameters;
state.types.parameters = new Map();
try {
@@ -1403,7 +1411,19 @@ const lowerPackage = (
displayName: identifier(query.identifier()),
root: { kind: query.WORKSPACE() ? "workspace-interface" : "object", interface: close(query.interfaceType()) },
document: stringValue(query.stringLiteral(1)),
operation: stringValue(query.stringLiteral(2)),
operation: isFragment
? query.stringLiteral(3)
? stringValue(query.stringLiteral(3))
: "QuixosFragment"
: stringValue(query.stringLiteral(2)),
...(isFragment
? {
fragment: {
name: stringValue(query.stringLiteral(2)),
...(query.stringLiteral(3) ? { operation: stringValue(query.stringLiteral(3)) } : {}),
},
}
: {}),
fragments: [],
views: [],
allowances: [],
@@ -1436,8 +1456,32 @@ const lowerPackage = (
);
if (sourceQueryId) declaration.placement = { kind: "local", sourceQueryId };
}
} else if (clause.FRAGMENTS()) declaration.fragments.push(stringValue(clause.stringLiteral()!));
else if (clause.VIEW()) {
} else if (clause.FRAGMENTS()) {
if (clause.stringLiteral()) declaration.fragments.push(stringValue(clause.stringLiteral()!));
else {
const imported = lowerQueryReference(
state,
identifier(clause.identifier(0)),
identifier(clause.identifier(1)),
clause,
);
if (imported) {
const variables: Record<string, string> = {};
for (const mapping of clause.fragmentVariable()) {
const name = identifier(mapping.identifier(0));
if (Object.hasOwn(variables, name))
loweringIssue(state, mapping, "duplicate-fragment-variable", `Repeated fragment variable ${name}`);
variables[name] = identifier(mapping.identifier(1));
}
(declaration.importedFragments ??= []).push({
packageRevisionId: imported.packageRevisionId,
packageAlias: identifier(clause.identifier(0)),
fragmentId: imported.queryId,
variables,
});
}
}
} else if (clause.VIEW()) {
const name = identifier(clause.identifier(0));
if (parameters.length) {
const parameter = state.types.parameters.get(name);
@@ -1548,6 +1592,23 @@ const lowerPackage = (
views: templateViews,
allowances: templateAllowances,
});
} else if (isFragment) {
if (declaration.placement || declaration.polling || declaration.allowances.length)
loweringIssue(
state,
query,
"invalid-query-fragment",
"Fragments are local projections with generated admission; remote allowances, polling and explicit placement are not supported",
);
const sourceQueryId = `${declaration.id}:fragment-inputs`;
queries.push({
...structuredClone(declaration),
id: sourceQueryId,
displayName: `${declaration.displayName}$inputs`,
placement: { kind: "replica" },
fragment: { ...declaration.fragment!, admission: true },
});
queries.push({ ...declaration, placement: { kind: "local", sourceQueryId } });
} else queries.push(declaration);
return [];
} finally {