@soda-gql/builder 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +382 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +122 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +122 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +384 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -42,6 +42,7 @@ __soda_gql_core_runtime = __toESM(__soda_gql_core_runtime);
|
|
|
42
42
|
let __soda_gql_runtime = require("@soda-gql/runtime");
|
|
43
43
|
__soda_gql_runtime = __toESM(__soda_gql_runtime);
|
|
44
44
|
let __swc_core = require("@swc/core");
|
|
45
|
+
let graphql = require("graphql");
|
|
45
46
|
let typescript = require("typescript");
|
|
46
47
|
typescript = __toESM(typescript);
|
|
47
48
|
let fast_glob = require("fast-glob");
|
|
@@ -63,6 +64,7 @@ const BuilderArtifactOperationSchema = zod.z.object({
|
|
|
63
64
|
"subscription"
|
|
64
65
|
]),
|
|
65
66
|
operationName: zod.z.string(),
|
|
67
|
+
schemaLabel: zod.z.string(),
|
|
66
68
|
document: zod.z.unknown(),
|
|
67
69
|
variableNames: zod.z.array(zod.z.string())
|
|
68
70
|
})
|
|
@@ -71,7 +73,11 @@ const BuilderArtifactFragmentSchema = zod.z.object({
|
|
|
71
73
|
id: zod.z.string(),
|
|
72
74
|
type: zod.z.literal("fragment"),
|
|
73
75
|
metadata: BuilderArtifactElementMetadataSchema,
|
|
74
|
-
prebuild: zod.z.object({
|
|
76
|
+
prebuild: zod.z.object({
|
|
77
|
+
typename: zod.z.string(),
|
|
78
|
+
key: zod.z.string().optional(),
|
|
79
|
+
schemaLabel: zod.z.string()
|
|
80
|
+
})
|
|
75
81
|
});
|
|
76
82
|
const BuilderArtifactElementSchema = zod.z.discriminatedUnion("type", [BuilderArtifactOperationSchema, BuilderArtifactFragmentSchema]);
|
|
77
83
|
const BuilderArtifactMetaSchema = zod.z.object({
|
|
@@ -387,6 +393,12 @@ const builderErrors = {
|
|
|
387
393
|
message: `Internal invariant violated: ${message}`,
|
|
388
394
|
context,
|
|
389
395
|
cause
|
|
396
|
+
}),
|
|
397
|
+
schemaNotFound: (schemaLabel, canonicalId) => ({
|
|
398
|
+
code: "SCHEMA_NOT_FOUND",
|
|
399
|
+
message: `Schema not found for label "${schemaLabel}" (element: ${canonicalId})`,
|
|
400
|
+
schemaLabel,
|
|
401
|
+
canonicalId
|
|
390
402
|
})
|
|
391
403
|
};
|
|
392
404
|
/**
|
|
@@ -473,6 +485,10 @@ const formatBuilderError = (error) => {
|
|
|
473
485
|
lines.push(` Context: ${error.context}`);
|
|
474
486
|
}
|
|
475
487
|
break;
|
|
488
|
+
case "SCHEMA_NOT_FOUND":
|
|
489
|
+
lines.push(` Schema label: ${error.schemaLabel}`);
|
|
490
|
+
lines.push(` Element: ${error.canonicalId}`);
|
|
491
|
+
break;
|
|
476
492
|
}
|
|
477
493
|
if ("cause" in error && error.cause && !["CONFIG_INVALID"].includes(error.code)) {
|
|
478
494
|
lines.push(` Caused by: ${error.cause}`);
|
|
@@ -1378,6 +1394,363 @@ const createGraphqlSystemIdentifyHelper = (config) => {
|
|
|
1378
1394
|
};
|
|
1379
1395
|
};
|
|
1380
1396
|
|
|
1397
|
+
//#endregion
|
|
1398
|
+
//#region packages/builder/src/prebuilt/emitter.ts
|
|
1399
|
+
/**
|
|
1400
|
+
* Prebuilt types emitter.
|
|
1401
|
+
*
|
|
1402
|
+
* Generates TypeScript type definitions for PrebuiltTypes registry
|
|
1403
|
+
* from field selection data and schema.
|
|
1404
|
+
*
|
|
1405
|
+
* ## Error Handling Strategy
|
|
1406
|
+
*
|
|
1407
|
+
* The emitter uses a partial failure approach for type calculation errors:
|
|
1408
|
+
*
|
|
1409
|
+
* **Recoverable errors** (result in warnings, element skipped):
|
|
1410
|
+
* - Type calculation failures (e.g., `calculateFieldsType` throws)
|
|
1411
|
+
* - Input type generation failures (e.g., `generateInputType` throws)
|
|
1412
|
+
* - These are caught per-element, logged as warnings, and the element is omitted
|
|
1413
|
+
*
|
|
1414
|
+
* **Fatal errors** (result in error result):
|
|
1415
|
+
* - `SCHEMA_NOT_FOUND`: Selection references non-existent schema
|
|
1416
|
+
* - `WRITE_FAILED`: Cannot write output file to disk
|
|
1417
|
+
*
|
|
1418
|
+
* This allows builds to succeed with partial type coverage when some elements
|
|
1419
|
+
* have issues, while providing visibility into problems via warnings.
|
|
1420
|
+
*
|
|
1421
|
+
* @module
|
|
1422
|
+
*/
|
|
1423
|
+
/**
|
|
1424
|
+
* Group field selections by schema.
|
|
1425
|
+
* Uses the schemaLabel from each selection to group them correctly.
|
|
1426
|
+
*
|
|
1427
|
+
* @returns Result containing grouped selections and warnings, or error if schema not found
|
|
1428
|
+
*/
|
|
1429
|
+
const groupBySchema = (fieldSelections, schemas) => {
|
|
1430
|
+
const grouped = new Map();
|
|
1431
|
+
const warnings = [];
|
|
1432
|
+
for (const schemaName of Object.keys(schemas)) {
|
|
1433
|
+
grouped.set(schemaName, {
|
|
1434
|
+
fragments: [],
|
|
1435
|
+
operations: [],
|
|
1436
|
+
inputObjects: new Set()
|
|
1437
|
+
});
|
|
1438
|
+
}
|
|
1439
|
+
for (const [canonicalId, selection] of fieldSelections) {
|
|
1440
|
+
const schemaName = selection.schemaLabel;
|
|
1441
|
+
const schema = schemas[schemaName];
|
|
1442
|
+
const group = grouped.get(schemaName);
|
|
1443
|
+
if (!schema || !group) {
|
|
1444
|
+
return (0, neverthrow.err)(builderErrors.schemaNotFound(schemaName, canonicalId));
|
|
1445
|
+
}
|
|
1446
|
+
const outputFormatters = { scalarOutput: (name) => `ScalarOutput_${schemaName}<"${name}">` };
|
|
1447
|
+
const inputFormatters = {
|
|
1448
|
+
scalarInput: (name) => `ScalarInput_${schemaName}<"${name}">`,
|
|
1449
|
+
inputObject: (name) => `Input_${schemaName}_${name}`
|
|
1450
|
+
};
|
|
1451
|
+
if (selection.type === "fragment") {
|
|
1452
|
+
if (!selection.key) {
|
|
1453
|
+
continue;
|
|
1454
|
+
}
|
|
1455
|
+
try {
|
|
1456
|
+
const usedInputObjects = collectUsedInputObjectsFromSpecifiers(schema, selection.variableDefinitions);
|
|
1457
|
+
for (const inputName of usedInputObjects) {
|
|
1458
|
+
group.inputObjects.add(inputName);
|
|
1459
|
+
}
|
|
1460
|
+
const outputType = (0, __soda_gql_core.calculateFieldsType)(schema, selection.fields, outputFormatters);
|
|
1461
|
+
const hasVariables = Object.keys(selection.variableDefinitions).length > 0;
|
|
1462
|
+
const inputType = hasVariables ? (0, __soda_gql_core.generateInputTypeFromSpecifiers)(schema, selection.variableDefinitions, { formatters: inputFormatters }) : "void";
|
|
1463
|
+
group.fragments.push({
|
|
1464
|
+
key: selection.key,
|
|
1465
|
+
inputType,
|
|
1466
|
+
outputType
|
|
1467
|
+
});
|
|
1468
|
+
} catch (error) {
|
|
1469
|
+
warnings.push(`[prebuilt] Failed to calculate type for fragment "${selection.key}": ${error instanceof Error ? error.message : String(error)}`);
|
|
1470
|
+
}
|
|
1471
|
+
} else if (selection.type === "operation") {
|
|
1472
|
+
try {
|
|
1473
|
+
const usedInputObjects = collectUsedInputObjects(schema, selection.variableDefinitions);
|
|
1474
|
+
for (const inputName of usedInputObjects) {
|
|
1475
|
+
group.inputObjects.add(inputName);
|
|
1476
|
+
}
|
|
1477
|
+
const outputType = (0, __soda_gql_core.calculateFieldsType)(schema, selection.fields, outputFormatters);
|
|
1478
|
+
const inputType = (0, __soda_gql_core.generateInputType)(schema, selection.variableDefinitions, inputFormatters);
|
|
1479
|
+
group.operations.push({
|
|
1480
|
+
key: selection.operationName,
|
|
1481
|
+
inputType,
|
|
1482
|
+
outputType
|
|
1483
|
+
});
|
|
1484
|
+
} catch (error) {
|
|
1485
|
+
warnings.push(`[prebuilt] Failed to calculate type for operation "${selection.operationName}": ${error instanceof Error ? error.message : String(error)}`);
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
return (0, neverthrow.ok)({
|
|
1490
|
+
grouped,
|
|
1491
|
+
warnings
|
|
1492
|
+
});
|
|
1493
|
+
};
|
|
1494
|
+
/**
|
|
1495
|
+
* Calculate relative import path from one file to another.
|
|
1496
|
+
*/
|
|
1497
|
+
const toImportSpecifier = (from, to) => {
|
|
1498
|
+
const fromDir = (0, node_path.dirname)(from);
|
|
1499
|
+
let relativePath = (0, node_path.relative)(fromDir, to);
|
|
1500
|
+
if (!relativePath.startsWith(".")) {
|
|
1501
|
+
relativePath = `./${relativePath}`;
|
|
1502
|
+
}
|
|
1503
|
+
return relativePath.replace(/\.ts$/, "");
|
|
1504
|
+
};
|
|
1505
|
+
/**
|
|
1506
|
+
* Extract input object names from a GraphQL TypeNode.
|
|
1507
|
+
*/
|
|
1508
|
+
const extractInputObjectsFromType = (schema, typeNode, inputObjects) => {
|
|
1509
|
+
switch (typeNode.kind) {
|
|
1510
|
+
case graphql.Kind.NON_NULL_TYPE:
|
|
1511
|
+
extractInputObjectsFromType(schema, typeNode.type, inputObjects);
|
|
1512
|
+
break;
|
|
1513
|
+
case graphql.Kind.LIST_TYPE:
|
|
1514
|
+
extractInputObjectsFromType(schema, typeNode.type, inputObjects);
|
|
1515
|
+
break;
|
|
1516
|
+
case graphql.Kind.NAMED_TYPE: {
|
|
1517
|
+
const name = typeNode.name.value;
|
|
1518
|
+
if (!schema.scalar[name] && !schema.enum[name] && schema.input[name]) {
|
|
1519
|
+
inputObjects.add(name);
|
|
1520
|
+
}
|
|
1521
|
+
break;
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
};
|
|
1525
|
+
/**
|
|
1526
|
+
* Recursively collect nested input objects from schema definitions.
|
|
1527
|
+
* Takes a set of initial input names and expands to include all nested inputs.
|
|
1528
|
+
*/
|
|
1529
|
+
const collectNestedInputObjects = (schema, initialInputNames) => {
|
|
1530
|
+
const inputObjects = new Set(initialInputNames);
|
|
1531
|
+
const collectNested = (inputName, seen) => {
|
|
1532
|
+
if (seen.has(inputName)) {
|
|
1533
|
+
return;
|
|
1534
|
+
}
|
|
1535
|
+
seen.add(inputName);
|
|
1536
|
+
const inputDef = schema.input[inputName];
|
|
1537
|
+
if (!inputDef) {
|
|
1538
|
+
return;
|
|
1539
|
+
}
|
|
1540
|
+
for (const field of Object.values(inputDef.fields)) {
|
|
1541
|
+
if (field.kind === "input" && !inputObjects.has(field.name)) {
|
|
1542
|
+
inputObjects.add(field.name);
|
|
1543
|
+
collectNested(field.name, seen);
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1547
|
+
for (const inputName of Array.from(initialInputNames)) {
|
|
1548
|
+
collectNested(inputName, new Set());
|
|
1549
|
+
}
|
|
1550
|
+
return inputObjects;
|
|
1551
|
+
};
|
|
1552
|
+
/**
|
|
1553
|
+
* Collect all input object types used in variable definitions.
|
|
1554
|
+
* Recursively collects nested input objects from the schema.
|
|
1555
|
+
*/
|
|
1556
|
+
const collectUsedInputObjects = (schema, variableDefinitions) => {
|
|
1557
|
+
const directInputs = new Set();
|
|
1558
|
+
for (const varDef of variableDefinitions) {
|
|
1559
|
+
extractInputObjectsFromType(schema, varDef.type, directInputs);
|
|
1560
|
+
}
|
|
1561
|
+
return collectNestedInputObjects(schema, directInputs);
|
|
1562
|
+
};
|
|
1563
|
+
/**
|
|
1564
|
+
* Collect all input object types used in InputTypeSpecifiers.
|
|
1565
|
+
* Recursively collects nested input objects from the schema.
|
|
1566
|
+
*/
|
|
1567
|
+
const collectUsedInputObjectsFromSpecifiers = (schema, specifiers) => {
|
|
1568
|
+
const directInputs = new Set();
|
|
1569
|
+
for (const specifier of Object.values(specifiers)) {
|
|
1570
|
+
if (specifier.kind === "input" && schema.input[specifier.name]) {
|
|
1571
|
+
directInputs.add(specifier.name);
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
return collectNestedInputObjects(schema, directInputs);
|
|
1575
|
+
};
|
|
1576
|
+
/**
|
|
1577
|
+
* Generate type definitions for input objects.
|
|
1578
|
+
*/
|
|
1579
|
+
const generateInputObjectTypeDefinitions = (schema, schemaName, inputNames) => {
|
|
1580
|
+
const lines = [];
|
|
1581
|
+
const defaultDepth = schema.__defaultInputDepth ?? 3;
|
|
1582
|
+
const depthOverrides = schema.__inputDepthOverrides ?? {};
|
|
1583
|
+
const formatters = {
|
|
1584
|
+
scalarInput: (name) => `ScalarInput_${schemaName}<"${name}">`,
|
|
1585
|
+
inputObject: (name) => `Input_${schemaName}_${name}`
|
|
1586
|
+
};
|
|
1587
|
+
const sortedNames = Array.from(inputNames).sort();
|
|
1588
|
+
for (const inputName of sortedNames) {
|
|
1589
|
+
const typeString = (0, __soda_gql_core.generateInputObjectType)(schema, inputName, {
|
|
1590
|
+
defaultDepth,
|
|
1591
|
+
depthOverrides,
|
|
1592
|
+
formatters
|
|
1593
|
+
});
|
|
1594
|
+
lines.push(`type Input_${schemaName}_${inputName} = ${typeString};`);
|
|
1595
|
+
}
|
|
1596
|
+
return lines;
|
|
1597
|
+
};
|
|
1598
|
+
/**
|
|
1599
|
+
* Generate the TypeScript code for prebuilt types.
|
|
1600
|
+
*/
|
|
1601
|
+
const generateTypesCode = (grouped, schemas, injects, outdir) => {
|
|
1602
|
+
const typesFilePath = (0, node_path.join)(outdir, "prebuilt", "types.ts");
|
|
1603
|
+
const lines = [
|
|
1604
|
+
"/**",
|
|
1605
|
+
" * Prebuilt type registry.",
|
|
1606
|
+
" *",
|
|
1607
|
+
" * This file is auto-generated by @soda-gql/builder.",
|
|
1608
|
+
" * Do not edit manually.",
|
|
1609
|
+
" *",
|
|
1610
|
+
" * @module",
|
|
1611
|
+
" * @generated",
|
|
1612
|
+
" */",
|
|
1613
|
+
"",
|
|
1614
|
+
"import type { PrebuiltTypeRegistry } from \"@soda-gql/core\";"
|
|
1615
|
+
];
|
|
1616
|
+
for (const [schemaName, inject] of Object.entries(injects)) {
|
|
1617
|
+
const relativePath = toImportSpecifier(typesFilePath, inject.scalars);
|
|
1618
|
+
lines.push(`import type { scalar as scalar_${schemaName} } from "${relativePath}";`);
|
|
1619
|
+
}
|
|
1620
|
+
lines.push("");
|
|
1621
|
+
for (const schemaName of Object.keys(injects)) {
|
|
1622
|
+
lines.push(`type ScalarInput_${schemaName}<T extends keyof typeof scalar_${schemaName}> = ` + `typeof scalar_${schemaName}[T]["$type"]["input"];`);
|
|
1623
|
+
lines.push(`type ScalarOutput_${schemaName}<T extends keyof typeof scalar_${schemaName}> = ` + `typeof scalar_${schemaName}[T]["$type"]["output"];`);
|
|
1624
|
+
}
|
|
1625
|
+
lines.push("");
|
|
1626
|
+
for (const [schemaName, { fragments, operations, inputObjects }] of grouped) {
|
|
1627
|
+
const schema = schemas[schemaName];
|
|
1628
|
+
if (inputObjects.size > 0 && schema) {
|
|
1629
|
+
lines.push("// Input object types");
|
|
1630
|
+
const inputTypeLines = generateInputObjectTypeDefinitions(schema, schemaName, inputObjects);
|
|
1631
|
+
lines.push(...inputTypeLines);
|
|
1632
|
+
lines.push("");
|
|
1633
|
+
}
|
|
1634
|
+
const fragmentEntries = fragments.sort((a, b) => a.key.localeCompare(b.key)).map((f) => ` readonly "${f.key}": { readonly input: ${f.inputType}; readonly output: ${f.outputType} };`);
|
|
1635
|
+
const operationEntries = operations.sort((a, b) => a.key.localeCompare(b.key)).map((o) => ` readonly "${o.key}": { readonly input: ${o.inputType}; readonly output: ${o.outputType} };`);
|
|
1636
|
+
lines.push(`export type PrebuiltTypes_${schemaName} = {`);
|
|
1637
|
+
lines.push(" readonly fragments: {");
|
|
1638
|
+
if (fragmentEntries.length > 0) {
|
|
1639
|
+
lines.push(...fragmentEntries);
|
|
1640
|
+
}
|
|
1641
|
+
lines.push(" };");
|
|
1642
|
+
lines.push(" readonly operations: {");
|
|
1643
|
+
if (operationEntries.length > 0) {
|
|
1644
|
+
lines.push(...operationEntries);
|
|
1645
|
+
}
|
|
1646
|
+
lines.push(" };");
|
|
1647
|
+
lines.push("} satisfies PrebuiltTypeRegistry;");
|
|
1648
|
+
lines.push("");
|
|
1649
|
+
}
|
|
1650
|
+
return lines.join("\n");
|
|
1651
|
+
};
|
|
1652
|
+
/**
|
|
1653
|
+
* Emit prebuilt types to the prebuilt/types.ts file.
|
|
1654
|
+
*
|
|
1655
|
+
* This function uses a partial failure strategy: if type calculation fails for
|
|
1656
|
+
* individual elements (e.g., due to invalid field selections or missing schema
|
|
1657
|
+
* types), those elements are skipped and warnings are collected rather than
|
|
1658
|
+
* failing the entire emission. This allows builds to succeed even when some
|
|
1659
|
+
* elements have issues, while still reporting problems via warnings.
|
|
1660
|
+
*
|
|
1661
|
+
* @param options - Emitter options including schemas, field selections, and output directory
|
|
1662
|
+
* @returns Result containing output path and warnings, or error if a hard failure occurs
|
|
1663
|
+
*
|
|
1664
|
+
* @example
|
|
1665
|
+
* ```typescript
|
|
1666
|
+
* const result = await emitPrebuiltTypes({
|
|
1667
|
+
* schemas: { mySchema: schema },
|
|
1668
|
+
* fieldSelections,
|
|
1669
|
+
* outdir: "./generated",
|
|
1670
|
+
* injects: { mySchema: { scalars: "./scalars.ts" } },
|
|
1671
|
+
* });
|
|
1672
|
+
*
|
|
1673
|
+
* if (result.isOk()) {
|
|
1674
|
+
* console.log(`Generated: ${result.value.path}`);
|
|
1675
|
+
* if (result.value.warnings.length > 0) {
|
|
1676
|
+
* console.warn("Warnings:", result.value.warnings);
|
|
1677
|
+
* }
|
|
1678
|
+
* }
|
|
1679
|
+
* ```
|
|
1680
|
+
*/
|
|
1681
|
+
const emitPrebuiltTypes = async (options) => {
|
|
1682
|
+
const { schemas, fieldSelections, outdir, injects } = options;
|
|
1683
|
+
const groupResult = groupBySchema(fieldSelections, schemas);
|
|
1684
|
+
if (groupResult.isErr()) {
|
|
1685
|
+
return (0, neverthrow.err)(groupResult.error);
|
|
1686
|
+
}
|
|
1687
|
+
const { grouped, warnings } = groupResult.value;
|
|
1688
|
+
const code = generateTypesCode(grouped, schemas, injects, outdir);
|
|
1689
|
+
const typesPath = (0, node_path.join)(outdir, "prebuilt", "types.ts");
|
|
1690
|
+
try {
|
|
1691
|
+
await (0, node_fs_promises.writeFile)(typesPath, code, "utf-8");
|
|
1692
|
+
return (0, neverthrow.ok)({
|
|
1693
|
+
path: typesPath,
|
|
1694
|
+
warnings
|
|
1695
|
+
});
|
|
1696
|
+
} catch (error) {
|
|
1697
|
+
return (0, neverthrow.err)(builderErrors.writeFailed(typesPath, `Failed to write prebuilt types: ${error instanceof Error ? error.message : String(error)}`, error));
|
|
1698
|
+
}
|
|
1699
|
+
};
|
|
1700
|
+
|
|
1701
|
+
//#endregion
|
|
1702
|
+
//#region packages/builder/src/prebuilt/extractor.ts
|
|
1703
|
+
/**
|
|
1704
|
+
* Extract field selections from evaluated intermediate elements.
|
|
1705
|
+
*
|
|
1706
|
+
* For fragments, calls `spread()` with empty/default variables to get field selections.
|
|
1707
|
+
* For operations, calls `documentSource()` to get field selections.
|
|
1708
|
+
*
|
|
1709
|
+
* @param elements - Record of canonical ID to intermediate artifact element
|
|
1710
|
+
* @returns Object containing selections map and any warnings encountered
|
|
1711
|
+
*/
|
|
1712
|
+
const extractFieldSelections = (elements) => {
|
|
1713
|
+
const selections = new Map();
|
|
1714
|
+
const warnings = [];
|
|
1715
|
+
for (const [id, element] of Object.entries(elements)) {
|
|
1716
|
+
const canonicalId = id;
|
|
1717
|
+
try {
|
|
1718
|
+
if (element.type === "fragment") {
|
|
1719
|
+
const variableDefinitions = element.element.variableDefinitions;
|
|
1720
|
+
const varRefs = Object.fromEntries(Object.keys(variableDefinitions).map((k) => [k, (0, __soda_gql_core.createVarRefFromVariable)(k)]));
|
|
1721
|
+
const fields = element.element.spread(varRefs);
|
|
1722
|
+
selections.set(canonicalId, {
|
|
1723
|
+
type: "fragment",
|
|
1724
|
+
schemaLabel: element.element.schemaLabel,
|
|
1725
|
+
key: element.element.key,
|
|
1726
|
+
typename: element.element.typename,
|
|
1727
|
+
fields,
|
|
1728
|
+
variableDefinitions
|
|
1729
|
+
});
|
|
1730
|
+
} else if (element.type === "operation") {
|
|
1731
|
+
const fields = element.element.documentSource();
|
|
1732
|
+
const document = element.element.document;
|
|
1733
|
+
const operationDef = document.definitions.find((def) => def.kind === graphql.Kind.OPERATION_DEFINITION);
|
|
1734
|
+
const variableDefinitions = operationDef?.variableDefinitions ?? [];
|
|
1735
|
+
selections.set(canonicalId, {
|
|
1736
|
+
type: "operation",
|
|
1737
|
+
schemaLabel: element.element.schemaLabel,
|
|
1738
|
+
operationName: element.element.operationName,
|
|
1739
|
+
operationType: element.element.operationType,
|
|
1740
|
+
fields,
|
|
1741
|
+
variableDefinitions
|
|
1742
|
+
});
|
|
1743
|
+
}
|
|
1744
|
+
} catch (error) {
|
|
1745
|
+
warnings.push(`[prebuilt] Failed to extract field selections for ${canonicalId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
return {
|
|
1749
|
+
selections,
|
|
1750
|
+
warnings
|
|
1751
|
+
};
|
|
1752
|
+
};
|
|
1753
|
+
|
|
1381
1754
|
//#endregion
|
|
1382
1755
|
//#region packages/builder/src/artifact/aggregate.ts
|
|
1383
1756
|
const canonicalToFilePath$1 = (canonicalId) => canonicalId.split("::")[0] ?? canonicalId;
|
|
@@ -1410,7 +1783,11 @@ const aggregate = ({ analyses, elements }) => {
|
|
|
1410
1783
|
contentHash: ""
|
|
1411
1784
|
};
|
|
1412
1785
|
if (element.type === "fragment") {
|
|
1413
|
-
const prebuild = {
|
|
1786
|
+
const prebuild = {
|
|
1787
|
+
typename: element.element.typename,
|
|
1788
|
+
key: element.element.key,
|
|
1789
|
+
schemaLabel: element.element.schemaLabel
|
|
1790
|
+
};
|
|
1414
1791
|
registry.set(definition.canonicalId, {
|
|
1415
1792
|
id: definition.canonicalId,
|
|
1416
1793
|
type: "fragment",
|
|
@@ -1426,6 +1803,7 @@ const aggregate = ({ analyses, elements }) => {
|
|
|
1426
1803
|
const prebuild = {
|
|
1427
1804
|
operationType: element.element.operationType,
|
|
1428
1805
|
operationName: element.element.operationName,
|
|
1806
|
+
schemaLabel: element.element.schemaLabel,
|
|
1429
1807
|
document: element.element.document,
|
|
1430
1808
|
variableNames: element.element.variableNames,
|
|
1431
1809
|
metadata: element.element.metadata
|
|
@@ -3662,6 +4040,8 @@ exports.collectAffectedFiles = collectAffectedFiles;
|
|
|
3662
4040
|
exports.createBuilderService = createBuilderService;
|
|
3663
4041
|
exports.createBuilderSession = createBuilderSession;
|
|
3664
4042
|
exports.createGraphqlSystemIdentifyHelper = createGraphqlSystemIdentifyHelper;
|
|
4043
|
+
exports.emitPrebuiltTypes = emitPrebuiltTypes;
|
|
4044
|
+
exports.extractFieldSelections = extractFieldSelections;
|
|
3665
4045
|
exports.extractModuleAdjacency = extractModuleAdjacency;
|
|
3666
4046
|
exports.formatBuilderErrorForCLI = formatBuilderErrorForCLI;
|
|
3667
4047
|
exports.formatBuilderErrorStructured = formatBuilderErrorStructured;
|