@soda-gql/tsc-transformer 0.1.0 → 0.3.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.mjs ADDED
@@ -0,0 +1,570 @@
1
+ import { createGraphqlSystemIdentifyHelper } from "@soda-gql/builder";
2
+ import { formatPluginError, resolveCanonicalId } from "@soda-gql/plugin-common";
3
+ import * as ts$1 from "typescript";
4
+ import ts from "typescript";
5
+ import { createCanonicalTracker } from "@soda-gql/common";
6
+ import { err, ok } from "neverthrow";
7
+
8
+ //#region packages/tsc-transformer/src/ast/imports.ts
9
+ const RUNTIME_MODULE = "@soda-gql/runtime";
10
+ /**
11
+ * Ensure that the gqlRuntime require exists in the source file for CJS output.
12
+ * Injects: const __soda_gql_runtime = require("@soda-gql/runtime");
13
+ * Returns an updated source file with the require added if needed.
14
+ */
15
+ const ensureGqlRuntimeRequire = ({ sourceFile, factory }) => {
16
+ if (sourceFile.statements.find((statement) => ts.isVariableStatement(statement) && statement.declarationList.declarations.some((decl) => {
17
+ if (!ts.isIdentifier(decl.name) || decl.name.text !== "__soda_gql_runtime") return false;
18
+ if (!decl.initializer || !ts.isCallExpression(decl.initializer)) return false;
19
+ const callExpr = decl.initializer;
20
+ if (!ts.isIdentifier(callExpr.expression) || callExpr.expression.text !== "require") return false;
21
+ const arg = callExpr.arguments[0];
22
+ return arg && ts.isStringLiteral(arg) && arg.text === RUNTIME_MODULE;
23
+ }))) return sourceFile;
24
+ const requireCall = factory.createCallExpression(factory.createIdentifier("require"), void 0, [factory.createStringLiteral(RUNTIME_MODULE)]);
25
+ const variableDeclaration = factory.createVariableDeclaration(factory.createIdentifier("__soda_gql_runtime"), void 0, void 0, requireCall);
26
+ const newStatements = [factory.createVariableStatement(void 0, factory.createVariableDeclarationList([variableDeclaration], ts.NodeFlags.Const)), ...sourceFile.statements];
27
+ return factory.updateSourceFile(sourceFile, newStatements);
28
+ };
29
+ /**
30
+ * Ensure that the gqlRuntime import exists in the source file.
31
+ * gqlRuntime is always imported from @soda-gql/runtime.
32
+ * Returns an updated source file with the import added or merged.
33
+ */
34
+ const ensureGqlRuntimeImport = ({ sourceFile, factory }) => {
35
+ const existing = sourceFile.statements.find((statement) => ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier) && statement.moduleSpecifier.text === RUNTIME_MODULE);
36
+ if (existing?.importClause?.namedBindings && ts.isNamedImports(existing.importClause.namedBindings)) {
37
+ if (existing.importClause.namedBindings.elements.some((element) => ts.isIdentifier(element.name) && element.name.text === "gqlRuntime")) return sourceFile;
38
+ const newElements = [...existing.importClause.namedBindings.elements, factory.createImportSpecifier(false, void 0, factory.createIdentifier("gqlRuntime"))];
39
+ const newNamedBindings = factory.createNamedImports(newElements);
40
+ const newImportClause = factory.createImportClause(false, void 0, newNamedBindings);
41
+ const newImportDeclaration = factory.createImportDeclaration(void 0, newImportClause, factory.createStringLiteral(RUNTIME_MODULE), void 0);
42
+ const newStatements$1 = sourceFile.statements.map((stmt) => stmt === existing ? newImportDeclaration : stmt);
43
+ return factory.updateSourceFile(sourceFile, newStatements$1);
44
+ }
45
+ const newStatements = [factory.createImportDeclaration(void 0, factory.createImportClause(false, void 0, factory.createNamedImports([factory.createImportSpecifier(false, void 0, factory.createIdentifier("gqlRuntime"))])), factory.createStringLiteral(RUNTIME_MODULE), void 0), ...sourceFile.statements];
46
+ return factory.updateSourceFile(sourceFile, newStatements);
47
+ };
48
+ /**
49
+ * Remove the graphql-system import (runtimeModule) and gql-related exports from the source file.
50
+ * After transformation, gqlRuntime is imported from @soda-gql/runtime instead,
51
+ * so the original graphql-system import should be completely removed.
52
+ *
53
+ * This handles both ESM imports and CommonJS require() statements (including interop helpers).
54
+ */
55
+ const removeGraphqlSystemImports = ({ sourceFile, factory, graphqlSystemIdentifyHelper }) => {
56
+ const updatedStatements = Array.from(sourceFile.statements).filter((statement) => {
57
+ if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) return !graphqlSystemIdentifyHelper.isGraphqlSystemImportSpecifier({
58
+ filePath: sourceFile.fileName,
59
+ specifier: statement.moduleSpecifier.text
60
+ });
61
+ if (ts.isVariableStatement(statement)) return !statement.declarationList.declarations.every((decl) => {
62
+ const specifier = extractRequireTargetSpecifier(decl.initializer);
63
+ if (!specifier) return false;
64
+ return graphqlSystemIdentifyHelper.isGraphqlSystemImportSpecifier({
65
+ filePath: sourceFile.fileName,
66
+ specifier
67
+ });
68
+ });
69
+ return true;
70
+ });
71
+ if (updatedStatements.length === sourceFile.statements.length) return sourceFile;
72
+ return factory.updateSourceFile(sourceFile, updatedStatements);
73
+ };
74
+ /**
75
+ * Create an "after" transformer that stubs out require() calls for the runtimeModule.
76
+ * This runs after TypeScript's own transformers (including CommonJS down-leveling),
77
+ * so we can replace `const X = require("@/graphql-system")` with a lightweight stub.
78
+ *
79
+ * This prevents the heavy graphql-system module from being loaded at runtime.
80
+ */
81
+ const createAfterStubTransformer = ({ sourceFile, graphqlSystemIdentifyHelper }) => {
82
+ return (context) => {
83
+ const factory = context.factory;
84
+ const visitor = (node) => {
85
+ if (ts.isVariableStatement(node)) {
86
+ let transformed = false;
87
+ const newDeclarations = node.declarationList.declarations.map((decl) => {
88
+ const specifier = extractRequireTargetSpecifier(decl.initializer);
89
+ if (!specifier) return decl;
90
+ if (!graphqlSystemIdentifyHelper.isGraphqlSystemImportSpecifier({
91
+ filePath: sourceFile.fileName,
92
+ specifier
93
+ })) return decl;
94
+ const stub = factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("Object"), "create"), void 0, [factory.createNull()]);
95
+ ts.addSyntheticLeadingComment(stub, ts.SyntaxKind.MultiLineCommentTrivia, "#__PURE__", false);
96
+ transformed = true;
97
+ return factory.updateVariableDeclaration(decl, decl.name, decl.exclamationToken, decl.type, stub);
98
+ });
99
+ if (transformed) return factory.updateVariableStatement(node, node.modifiers, factory.updateVariableDeclarationList(node.declarationList, newDeclarations));
100
+ }
101
+ return ts.visitEachChild(node, visitor, context);
102
+ };
103
+ return (sourceFile$1) => ts.visitNode(sourceFile$1, visitor);
104
+ };
105
+ };
106
+ /**
107
+ * Check if an expression is a require() call for the runtimeModule.
108
+ * Handles multiple patterns:
109
+ * - require("@/graphql-system")
110
+ * - __importDefault(require("@/graphql-system"))
111
+ * - __importStar(require("@/graphql-system"))
112
+ */
113
+ const extractRequireTargetSpecifier = (expr) => {
114
+ if (!expr) return;
115
+ if (ts.isCallExpression(expr)) {
116
+ if (ts.isIdentifier(expr.expression) && expr.expression.text === "require") {
117
+ const arg = expr.arguments[0];
118
+ if (arg && ts.isStringLiteral(arg)) return arg.text;
119
+ }
120
+ if (ts.isIdentifier(expr.expression)) {
121
+ const helperName = expr.expression.text;
122
+ if (helperName === "__importDefault" || helperName === "__importStar") {
123
+ const arg = expr.arguments[0];
124
+ if (arg && ts.isCallExpression(arg)) {
125
+ if (ts.isIdentifier(arg.expression) && arg.expression.text === "require") {
126
+ const requireArg = arg.arguments[0];
127
+ if (requireArg && ts.isStringLiteral(requireArg)) return requireArg.text;
128
+ }
129
+ }
130
+ }
131
+ }
132
+ }
133
+ };
134
+
135
+ //#endregion
136
+ //#region packages/tsc-transformer/src/ast/metadata.ts
137
+ const collectGqlDefinitionMetadata = ({ sourceFile, filename, createTracker }) => {
138
+ const exportBindings = collectExportBindings(sourceFile);
139
+ const tracker = (createTracker ?? createCanonicalTracker)({
140
+ filePath: filename,
141
+ getExportName: (localName) => exportBindings.get(localName)
142
+ });
143
+ const getAnonymousName = createAnonymousNameFactory();
144
+ const scopeHandles = /* @__PURE__ */ new WeakMap();
145
+ const metadata = /* @__PURE__ */ new WeakMap();
146
+ const visit = (node) => {
147
+ if (ts$1.isCallExpression(node) && isGqlDefinitionCall(node, ts$1)) {
148
+ const depthBeforeRegister = tracker.currentDepth();
149
+ const { astPath } = tracker.registerDefinition();
150
+ const isTopLevel = depthBeforeRegister <= 1;
151
+ const exportInfo = isTopLevel ? resolveTopLevelExport(node, exportBindings, ts$1) : null;
152
+ metadata.set(node, {
153
+ astPath,
154
+ isTopLevel,
155
+ isExported: exportInfo?.isExported ?? false,
156
+ exportBinding: exportInfo?.exportBinding
157
+ });
158
+ return;
159
+ }
160
+ const handle = maybeEnterScope(node, tracker, getAnonymousName, ts$1);
161
+ if (handle) scopeHandles.set(node, handle);
162
+ ts$1.forEachChild(node, visit);
163
+ const scopeHandle = scopeHandles.get(node);
164
+ if (scopeHandle) {
165
+ tracker.exitScope(scopeHandle);
166
+ scopeHandles.delete(node);
167
+ }
168
+ };
169
+ visit(sourceFile);
170
+ return metadata;
171
+ };
172
+ const collectExportBindings = (sourceFile) => {
173
+ const bindings = /* @__PURE__ */ new Map();
174
+ for (const statement of sourceFile.statements) {
175
+ if (ts$1.isExportDeclaration(statement) && statement.exportClause && ts$1.isNamedExports(statement.exportClause)) {
176
+ for (const element of statement.exportClause.elements) {
177
+ const name = element.name.text;
178
+ bindings.set(name, name);
179
+ }
180
+ continue;
181
+ }
182
+ if (ts$1.isVariableStatement(statement) && statement.modifiers?.some((m) => m.kind === ts$1.SyntaxKind.ExportKeyword)) {
183
+ for (const declaration of statement.declarationList.declarations) if (ts$1.isIdentifier(declaration.name)) bindings.set(declaration.name.text, declaration.name.text);
184
+ continue;
185
+ }
186
+ if ((ts$1.isFunctionDeclaration(statement) || ts$1.isClassDeclaration(statement)) && statement.modifiers?.some((m) => m.kind === ts$1.SyntaxKind.ExportKeyword) && statement.name) {
187
+ bindings.set(statement.name.text, statement.name.text);
188
+ continue;
189
+ }
190
+ if (ts$1.isExpressionStatement(statement) && ts$1.isBinaryExpression(statement.expression)) {
191
+ const exportName = getCommonJsExportName(statement.expression.left);
192
+ if (exportName) bindings.set(exportName, exportName);
193
+ }
194
+ }
195
+ return bindings;
196
+ };
197
+ const getCommonJsExportName = (node) => {
198
+ if (!ts$1.isPropertyAccessExpression(node)) return null;
199
+ const isExports = ts$1.isIdentifier(node.expression) && node.expression.text === "exports";
200
+ const isModuleExports = ts$1.isPropertyAccessExpression(node.expression) && ts$1.isIdentifier(node.expression.expression) && node.expression.expression.text === "module" && ts$1.isIdentifier(node.expression.name) && node.expression.name.text === "exports";
201
+ if (!isExports && !isModuleExports) return null;
202
+ if (ts$1.isIdentifier(node.name)) return node.name.text;
203
+ return null;
204
+ };
205
+ const createAnonymousNameFactory = () => {
206
+ const counters = /* @__PURE__ */ new Map();
207
+ return (kind) => {
208
+ const count = counters.get(kind) ?? 0;
209
+ counters.set(kind, count + 1);
210
+ return `${kind}#${count}`;
211
+ };
212
+ };
213
+ const isGqlDefinitionCall = (node, typescript) => {
214
+ if (!typescript.isCallExpression(node)) return false;
215
+ if (!typescript.isPropertyAccessExpression(node.expression)) return false;
216
+ if (!isGqlReference(node.expression.expression, typescript)) return false;
217
+ if (node.arguments.length === 0) return false;
218
+ const firstArg = node.arguments[0];
219
+ if (firstArg === void 0) return false;
220
+ return typescript.isArrowFunction(firstArg);
221
+ };
222
+ const isGqlReference = (expr, typescript) => {
223
+ if (typescript.isIdentifier(expr) && expr.text === "gql") return true;
224
+ if (!typescript.isPropertyAccessExpression(expr)) return false;
225
+ if (typescript.isIdentifier(expr.name) && expr.name.text === "gql") return true;
226
+ return isGqlReference(expr.expression, typescript);
227
+ };
228
+ const resolveTopLevelExport = (callNode, exportBindings, typescript) => {
229
+ const parent = callNode.parent;
230
+ if (!parent) return null;
231
+ if (typescript.isVariableDeclaration(parent)) {
232
+ const { name } = parent;
233
+ if (typescript.isIdentifier(name)) {
234
+ const exportBinding = exportBindings.get(name.text);
235
+ if (exportBinding) return {
236
+ isExported: true,
237
+ exportBinding
238
+ };
239
+ }
240
+ }
241
+ if (typescript.isBinaryExpression(parent)) {
242
+ const exportName = getCommonJsExportName(parent.left);
243
+ if (exportName && exportBindings.has(exportName)) return {
244
+ isExported: true,
245
+ exportBinding: exportName
246
+ };
247
+ }
248
+ return null;
249
+ };
250
+ const maybeEnterScope = (node, tracker, getAnonymousName, typescript) => {
251
+ if (typescript.isBinaryExpression(node)) {
252
+ const exportName = getCommonJsExportName(node.left);
253
+ if (exportName) return tracker.enterScope({
254
+ segment: exportName,
255
+ kind: "variable",
256
+ stableKey: `var:${exportName}`
257
+ });
258
+ }
259
+ if (typescript.isVariableDeclaration(node) && typescript.isIdentifier(node.name)) {
260
+ const name = node.name.text;
261
+ return tracker.enterScope({
262
+ segment: name,
263
+ kind: "variable",
264
+ stableKey: `var:${name}`
265
+ });
266
+ }
267
+ if (typescript.isArrowFunction(node)) {
268
+ const name = getAnonymousName("arrow");
269
+ return tracker.enterScope({
270
+ segment: name,
271
+ kind: "function",
272
+ stableKey: "arrow"
273
+ });
274
+ }
275
+ if (typescript.isFunctionDeclaration(node) || typescript.isFunctionExpression(node)) {
276
+ const name = node.name?.text ?? getAnonymousName("function");
277
+ return tracker.enterScope({
278
+ segment: name,
279
+ kind: "function",
280
+ stableKey: `func:${name}`
281
+ });
282
+ }
283
+ if (typescript.isClassDeclaration(node)) {
284
+ const name = node.name?.text ?? getAnonymousName("class");
285
+ return tracker.enterScope({
286
+ segment: name,
287
+ kind: "class",
288
+ stableKey: `class:${name}`
289
+ });
290
+ }
291
+ if (typescript.isMethodDeclaration(node) && typescript.isIdentifier(node.name)) {
292
+ const name = node.name.text;
293
+ return tracker.enterScope({
294
+ segment: name,
295
+ kind: "method",
296
+ stableKey: `member:${name}`
297
+ });
298
+ }
299
+ if (typescript.isPropertyDeclaration(node) && typescript.isIdentifier(node.name)) {
300
+ const name = node.name.text;
301
+ return tracker.enterScope({
302
+ segment: name,
303
+ kind: "property",
304
+ stableKey: `member:${name}`
305
+ });
306
+ }
307
+ if (typescript.isPropertyAssignment(node)) {
308
+ const key = node.name;
309
+ const name = typescript.isIdentifier(key) ? key.text : typescript.isStringLiteral(key) ? key.text : null;
310
+ if (name) return tracker.enterScope({
311
+ segment: name,
312
+ kind: "property",
313
+ stableKey: `prop:${name}`
314
+ });
315
+ }
316
+ return null;
317
+ };
318
+
319
+ //#endregion
320
+ //#region packages/tsc-transformer/src/ast/analysis.ts
321
+ const extractGqlCall = ({ callNode, filename, metadata, getArtifact }) => {
322
+ const meta = metadata.get(callNode);
323
+ if (!meta) return err(createMetadataMissingError({ filename }));
324
+ const canonicalId = resolveCanonicalId(filename, meta.astPath);
325
+ const artifact = getArtifact(canonicalId);
326
+ if (!artifact) return err(createArtifactMissingError({
327
+ filename,
328
+ canonicalId
329
+ }));
330
+ if (artifact.type === "fragment") return ok({
331
+ callNode,
332
+ canonicalId,
333
+ type: "fragment",
334
+ artifact
335
+ });
336
+ if (artifact.type === "operation") return ok({
337
+ callNode,
338
+ canonicalId,
339
+ type: "operation",
340
+ artifact
341
+ });
342
+ return err(createUnsupportedArtifactTypeError({
343
+ filename,
344
+ canonicalId,
345
+ artifactType: artifact.type
346
+ }));
347
+ };
348
+ const createMetadataMissingError = ({ filename }) => ({
349
+ type: "PluginError",
350
+ stage: "analysis",
351
+ code: "SODA_GQL_METADATA_NOT_FOUND",
352
+ message: `No GraphQL metadata found for ${filename}`,
353
+ cause: { filename },
354
+ filename
355
+ });
356
+ const createArtifactMissingError = ({ filename, canonicalId }) => ({
357
+ type: "PluginError",
358
+ stage: "analysis",
359
+ code: "SODA_GQL_ANALYSIS_ARTIFACT_NOT_FOUND",
360
+ message: `No builder artifact found for canonical ID ${canonicalId}`,
361
+ cause: {
362
+ filename,
363
+ canonicalId
364
+ },
365
+ filename,
366
+ canonicalId
367
+ });
368
+ const createUnsupportedArtifactTypeError = ({ filename, canonicalId, artifactType }) => ({
369
+ type: "PluginError",
370
+ stage: "analysis",
371
+ code: "SODA_GQL_UNSUPPORTED_ARTIFACT_TYPE",
372
+ message: `Unsupported builder artifact type "${artifactType}" for canonical ID ${canonicalId}`,
373
+ cause: {
374
+ filename,
375
+ canonicalId,
376
+ artifactType
377
+ },
378
+ filename,
379
+ canonicalId,
380
+ artifactType
381
+ });
382
+
383
+ //#endregion
384
+ //#region packages/tsc-transformer/src/ast/ast.ts
385
+ /**
386
+ * Build an object literal expression from a record of properties.
387
+ */
388
+ const buildObjectExpression = (factory, properties) => {
389
+ const propertyAssignments = Object.entries(properties).map(([key, value]) => factory.createPropertyAssignment(factory.createIdentifier(key), value));
390
+ return factory.createObjectLiteralExpression(propertyAssignments);
391
+ };
392
+ /**
393
+ * Build a JSON.parse expression from an object value.
394
+ * This is used to emit large objects as JSON strings to reduce the calculation cost of both the compiler and the runtime.
395
+ */
396
+ const buildJsonParseExpression = (factory, value) => factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("JSON"), factory.createIdentifier("parse")), void 0, [factory.createStringLiteral(JSON.stringify(value))]);
397
+
398
+ //#endregion
399
+ //#region packages/tsc-transformer/src/ast/runtime.ts
400
+ const createRuntimeAccessor = ({ isCJS, factory }) => isCJS ? factory.createPropertyAccessExpression(factory.createIdentifier("__soda_gql_runtime"), factory.createIdentifier("gqlRuntime")) : factory.createIdentifier("gqlRuntime");
401
+ const buildFragmentRuntimeCall = ({ gqlCall, factory, isCJS }) => {
402
+ return ok(factory.createCallExpression(factory.createPropertyAccessExpression(createRuntimeAccessor({
403
+ isCJS,
404
+ factory
405
+ }), factory.createIdentifier("fragment")), void 0, [buildObjectExpression(factory, { prebuild: buildObjectExpression(factory, { typename: factory.createStringLiteral(gqlCall.artifact.prebuild.typename) }) })]));
406
+ };
407
+ const buildOperationRuntimeComponents = ({ gqlCall, factory, isCJS }) => {
408
+ const runtimeCall = factory.createCallExpression(factory.createPropertyAccessExpression(createRuntimeAccessor({
409
+ isCJS,
410
+ factory
411
+ }), factory.createIdentifier("operation")), void 0, [buildObjectExpression(factory, {
412
+ prebuild: buildJsonParseExpression(factory, gqlCall.artifact.prebuild),
413
+ runtime: buildObjectExpression(factory, {})
414
+ })]);
415
+ return ok({
416
+ referenceCall: factory.createCallExpression(factory.createPropertyAccessExpression(createRuntimeAccessor({
417
+ isCJS,
418
+ factory
419
+ }), factory.createIdentifier("getOperation")), void 0, [factory.createStringLiteral(gqlCall.artifact.prebuild.operationName)]),
420
+ runtimeCall
421
+ });
422
+ };
423
+
424
+ //#endregion
425
+ //#region packages/tsc-transformer/src/ast/transformer.ts
426
+ const transformCallExpression = ({ callNode, filename, metadata, getArtifact, factory, isCJS }) => {
427
+ if (!metadata.has(callNode)) return ok({ transformed: false });
428
+ const gqlCallResult = extractGqlCall({
429
+ callNode,
430
+ filename,
431
+ metadata,
432
+ getArtifact
433
+ });
434
+ if (gqlCallResult.isErr()) return err(gqlCallResult.error);
435
+ const gqlCall = gqlCallResult.value;
436
+ return replaceWithRuntimeCall({
437
+ gqlCall,
438
+ factory,
439
+ isCJS,
440
+ filename
441
+ });
442
+ };
443
+ const replaceWithRuntimeCall = ({ gqlCall, factory, isCJS, filename }) => {
444
+ if (gqlCall.type === "fragment") {
445
+ const result = buildFragmentRuntimeCall({
446
+ gqlCall,
447
+ factory,
448
+ isCJS,
449
+ filename
450
+ });
451
+ if (result.isErr()) return err(result.error);
452
+ return ok({
453
+ transformed: true,
454
+ replacement: result.value
455
+ });
456
+ }
457
+ if (gqlCall.type === "operation") {
458
+ const result = buildOperationRuntimeComponents({
459
+ gqlCall,
460
+ factory,
461
+ isCJS
462
+ });
463
+ if (result.isErr()) return err(result.error);
464
+ const { referenceCall, runtimeCall } = result.value;
465
+ return ok({
466
+ transformed: true,
467
+ replacement: referenceCall,
468
+ runtimeCall
469
+ });
470
+ }
471
+ return ok({ transformed: false });
472
+ };
473
+
474
+ //#endregion
475
+ //#region packages/tsc-transformer/src/transformer.ts
476
+ const findLastImportIndex = ({ sourceFile }) => {
477
+ let lastIndex = -1;
478
+ const statements = sourceFile.statements;
479
+ for (let i = 0; i < statements.length; i++) {
480
+ const statement = statements[i];
481
+ if (statement && ts$1.isImportDeclaration(statement)) lastIndex = i;
482
+ }
483
+ return lastIndex;
484
+ };
485
+ const createTransformer = ({ compilerOptions, config, artifact }) => {
486
+ const isCJS = compilerOptions.module === ts$1.ModuleKind.CommonJS || compilerOptions.target === ts$1.ScriptTarget.ES5;
487
+ const graphqlSystemIdentifyHelper = createGraphqlSystemIdentifyHelper(config);
488
+ const makeSourceFileEmpty = ({ factory, sourceFile }) => {
489
+ return factory.updateSourceFile(sourceFile, [factory.createExportDeclaration(void 0, false, factory.createNamedExports([]), void 0)]);
490
+ };
491
+ const transformGqlCalls = ({ sourceFile, context }) => {
492
+ let transformed = false;
493
+ const metadata = collectGqlDefinitionMetadata({
494
+ sourceFile,
495
+ filename: sourceFile.fileName
496
+ });
497
+ const runtimeCallsFromLastTransform = [];
498
+ const visitor = (node) => {
499
+ if (ts$1.isCallExpression(node)) {
500
+ const result = transformCallExpression({
501
+ callNode: node,
502
+ filename: sourceFile.fileName,
503
+ metadata,
504
+ getArtifact: (canonicalId) => artifact.elements[canonicalId],
505
+ factory: context.factory,
506
+ isCJS
507
+ });
508
+ if (result.isErr()) {
509
+ console.error(`[@soda-gql/tsc-plugin] ${formatPluginError(result.error)}`);
510
+ return node;
511
+ }
512
+ const transformResult = result.value;
513
+ if (transformResult.transformed) {
514
+ transformed = true;
515
+ if (transformResult.runtimeCall) runtimeCallsFromLastTransform.push(transformResult.runtimeCall);
516
+ return transformResult.replacement;
517
+ }
518
+ }
519
+ return ts$1.visitEachChild(node, visitor, context);
520
+ };
521
+ const visitedNode = ts$1.visitNode(sourceFile, visitor);
522
+ if (!visitedNode || !ts$1.isSourceFile(visitedNode)) {
523
+ console.error(`[@soda-gql/tsc-plugin] Failed to transform source file: ${sourceFile.fileName}`);
524
+ return sourceFile;
525
+ }
526
+ if (!transformed) return sourceFile;
527
+ if (runtimeCallsFromLastTransform.length === 0) return visitedNode;
528
+ const lastImportIndex = findLastImportIndex({ sourceFile });
529
+ return context.factory.updateSourceFile(visitedNode, [
530
+ ...visitedNode.statements.slice(0, lastImportIndex + 1),
531
+ ...runtimeCallsFromLastTransform.map((expr) => context.factory.createExpressionStatement(expr)),
532
+ ...visitedNode.statements.slice(lastImportIndex + 1)
533
+ ]);
534
+ };
535
+ return { transform: ({ sourceFile, context }) => {
536
+ if (graphqlSystemIdentifyHelper.isGraphqlSystemFile({ filePath: sourceFile.fileName })) return {
537
+ transformed: true,
538
+ sourceFile: makeSourceFileEmpty({
539
+ factory: context.factory,
540
+ sourceFile
541
+ })
542
+ };
543
+ const original = sourceFile;
544
+ let current = sourceFile;
545
+ current = transformGqlCalls({
546
+ sourceFile: current,
547
+ context
548
+ });
549
+ if (current !== sourceFile) current = isCJS ? ensureGqlRuntimeRequire({
550
+ sourceFile: current,
551
+ factory: context.factory
552
+ }) : ensureGqlRuntimeImport({
553
+ sourceFile: current,
554
+ factory: context.factory
555
+ });
556
+ current = removeGraphqlSystemImports({
557
+ sourceFile: current,
558
+ factory: context.factory,
559
+ graphqlSystemIdentifyHelper
560
+ });
561
+ return {
562
+ transformed: current !== original,
563
+ sourceFile: current
564
+ };
565
+ } };
566
+ };
567
+
568
+ //#endregion
569
+ export { createAfterStubTransformer, createTransformer };
570
+ //# sourceMappingURL=index.mjs.map