Add exported query fragments and scoped coverage observations
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user