@soda-gql/swc 0.11.9 → 0.11.11

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/src/index.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import { realpathSync } from "node:fs";
8
- import { resolve } from "node:path";
8
+ import { relative, resolve } from "node:path";
9
9
  import remapping from "@ampproject/remapping";
10
10
  import type { BuilderArtifact } from "@soda-gql/builder";
11
11
  import type { ResolvedSodaGqlConfig } from "@soda-gql/config";
@@ -109,20 +109,41 @@ export type TransformInput = {
109
109
  */
110
110
  const normalizePath = (value: string): string => value.replace(/\\/g, "/");
111
111
 
112
+ /**
113
+ * Compute the path prefix for filtering artifact elements.
114
+ * Uses relative path from baseDir if provided, otherwise absolute path.
115
+ */
116
+ const computeArtifactPathPrefix = (absolutePath: string, baseDir?: string): string => {
117
+ if (baseDir) {
118
+ const relativePath = normalizePath(relative(baseDir, absolutePath));
119
+ return `${relativePath}::`;
120
+ }
121
+ return `${absolutePath}::`;
122
+ };
123
+
112
124
  /**
113
125
  * Filter artifact to only include elements for the given source file.
114
126
  * This significantly reduces JSON serialization overhead for large codebases.
115
127
  *
116
128
  * Canonical IDs have the format: "filepath::astPath"
117
129
  * We filter by matching the filepath prefix.
130
+ *
131
+ * When baseDir is provided, the sourcePath is converted to a relative path
132
+ * for matching against relative canonical IDs in the artifact.
133
+ * The canonical IDs in the returned artifact are converted to absolute paths
134
+ * to match what the Rust code will generate.
118
135
  */
119
- const filterArtifactForFile = (artifact: BuilderArtifact, sourcePath: string): BuilderArtifact => {
120
- const prefix = `${sourcePath}::`;
136
+ const filterArtifactForFile = (artifact: BuilderArtifact, absoluteSourcePath: string, baseDir?: string): BuilderArtifact => {
137
+ const relativePrefix = computeArtifactPathPrefix(absoluteSourcePath, baseDir);
138
+ const absolutePrefix = `${absoluteSourcePath}::`;
121
139
 
122
140
  const filteredElements: BuilderArtifact["elements"] = {};
123
141
  for (const [id, element] of Object.entries(artifact.elements)) {
124
- if (id.startsWith(prefix)) {
125
- (filteredElements as Record<string, typeof element>)[id] = element;
142
+ if (id.startsWith(relativePrefix)) {
143
+ // Convert the canonical ID from relative to absolute path format
144
+ // so it matches what the Rust code will generate
145
+ const absoluteId = id.replace(relativePrefix, absolutePrefix);
146
+ (filteredElements as Record<string, typeof element>)[absoluteId] = element;
126
147
  }
127
148
  }
128
149
 
@@ -147,6 +168,7 @@ const resolveCanonicalPath = (filePath: string): string => {
147
168
 
148
169
  /**
149
170
  * Resolve the canonical path to the graphql-system file.
171
+ * Returns absolute path for use in internal module stubbing.
150
172
  */
151
173
  const resolveGraphqlSystemPath = (config: ResolvedSodaGqlConfig): string => {
152
174
  return resolveCanonicalPath(resolve(config.outdir, "index.ts"));
@@ -154,6 +176,7 @@ const resolveGraphqlSystemPath = (config: ResolvedSodaGqlConfig): string => {
154
176
 
155
177
  /**
156
178
  * Collect canonical paths to inject modules (scalars, adapter) from all schemas.
179
+ * Returns absolute paths for use in internal module stubbing.
157
180
  */
158
181
  const collectInjectPaths = (config: ResolvedSodaGqlConfig): string[] => {
159
182
  const paths: string[] = [];
@@ -209,21 +232,27 @@ export const createTransformer = async (options: TransformOptions): Promise<Tran
209
232
 
210
233
  // Store full artifact for per-file filtering
211
234
  const fullArtifact = options.artifact;
235
+ const baseDir = options.config.baseDir;
212
236
 
213
237
  return {
214
238
  transform: ({ sourceCode, sourcePath, inputSourceMap }: TransformInput): TransformOutput => {
215
239
  // Resolve to absolute path and normalize for canonical ID consistency
216
240
  // This ensures bundlers can pass relative paths safely
217
- const normalizedPath = normalizePath(resolve(sourcePath));
241
+ const absolutePath = normalizePath(resolve(sourcePath));
218
242
 
219
243
  // Filter artifact to only include elements for this file
220
244
  // This significantly reduces JSON serialization overhead for large codebases
221
- const filteredArtifact = filterArtifactForFile(fullArtifact, normalizedPath);
245
+ // The filter function converts relative canonical IDs to absolute paths
246
+ // to match what the Rust code will generate
247
+ const filteredArtifact = filterArtifactForFile(fullArtifact, absolutePath, baseDir);
222
248
  const filteredArtifactJson = JSON.stringify(filteredArtifact);
223
249
 
224
250
  // Create per-file transformer with filtered artifact
225
251
  const fileTransformer = new native.SwcTransformer(filteredArtifactJson, configJson);
226
- const resultJson = fileTransformer.transform(sourceCode, normalizedPath);
252
+
253
+ // Pass absolute path to native transformer for internal module stubbing detection
254
+ // and canonical ID computation (the filtered artifact has absolute canonical IDs)
255
+ const resultJson = fileTransformer.transform(sourceCode, absolutePath);
227
256
  const result: TransformResult = JSON.parse(resultJson);
228
257
 
229
258
  // Handle source map chaining
@@ -268,10 +297,12 @@ export const transform = async (
268
297
 
269
298
  // Resolve to absolute path and normalize for canonical ID consistency
270
299
  // This ensures bundlers can pass relative paths safely
271
- const normalizedPath = normalizePath(resolve(input.sourcePath));
300
+ const absolutePath = normalizePath(resolve(input.sourcePath));
301
+ const baseDir = input.config.baseDir;
272
302
 
273
303
  // Filter artifact to only include elements for this file
274
- const filteredArtifact = filterArtifactForFile(input.artifact, normalizedPath);
304
+ // The filter function converts relative canonical IDs to absolute paths
305
+ const filteredArtifact = filterArtifactForFile(input.artifact, absolutePath, baseDir);
275
306
 
276
307
  // Resolve paths for internal module stubbing
277
308
  const graphqlSystemPath = resolveGraphqlSystemPath(input.config);
@@ -279,7 +310,7 @@ export const transform = async (
279
310
 
280
311
  const inputJson = JSON.stringify({
281
312
  sourceCode: input.sourceCode,
282
- sourcePath: normalizedPath,
313
+ sourcePath: absolutePath,
283
314
  artifactJson: JSON.stringify(filteredArtifact),
284
315
  config: {
285
316
  graphqlSystemAliases: input.config.graphqlSystemAliases,
@@ -11,7 +11,7 @@ import { tmpdir } from "node:os";
11
11
  import { dirname, join } from "node:path";
12
12
  import type { BuilderArtifact } from "@soda-gql/builder";
13
13
  import type { ResolvedSodaGqlConfig } from "@soda-gql/config";
14
- import { loadTestCases, normalizeCode, type TransformTestCase } from "@soda-gql/tsc/test";
14
+ import { createTestConfig, loadTestCases, normalizeCode, type TransformTestCase } from "@soda-gql/tsc/test";
15
15
 
16
16
  // Check if native module is available before running tests
17
17
  // This needs to be evaluated synchronously at module load time
@@ -29,12 +29,14 @@ try {
29
29
  await createTransformer({
30
30
  config: {
31
31
  analyzer: "ts",
32
+ baseDir: "/tmp",
32
33
  outdir: "/tmp",
33
34
  graphqlSystemAliases: [],
34
35
  include: [],
35
36
  exclude: [],
36
37
  schemas: {},
37
38
  styles: { importExtension: false },
39
+ codegen: { chunkSize: 100 },
38
40
  plugins: {},
39
41
  },
40
42
  artifact: {
@@ -99,6 +101,7 @@ describe("swc", async () => {
99
101
  });
100
102
 
101
103
  const testCases = await loadTestCases();
104
+ const config = createTestConfig();
102
105
 
103
106
  for (const testCase of testCases) {
104
107
  describe(testCase.id, () => {
@@ -108,23 +111,7 @@ describe("swc", async () => {
108
111
  sourceCode: testCase.input.sourceCode,
109
112
  sourcePath: testCase.input.sourcePath,
110
113
  artifact: testCase.input.artifact,
111
- config: {
112
- analyzer: "ts",
113
- outdir: "/tmp",
114
- graphqlSystemAliases: ["@/graphql-system"],
115
- include: [],
116
- exclude: [],
117
- schemas: {
118
- default: {
119
- schema: ["/tmp/schema.graphql"],
120
- inject: { scalars: "/tmp/scalars.ts" },
121
- defaultInputDepth: 3,
122
- inputDepthOverrides: {},
123
- },
124
- },
125
- styles: { importExtension: false },
126
- plugins: {},
127
- },
114
+ config,
128
115
  moduleFormat: "esm",
129
116
  });
130
117
  const normalized = await normalizeCode(result);
@@ -148,23 +135,7 @@ describe("swc", async () => {
148
135
  sourceCode: testCase.input.sourceCode,
149
136
  sourcePath: testCase.input.sourcePath,
150
137
  artifact: testCase.input.artifact,
151
- config: {
152
- analyzer: "ts",
153
- outdir: "/tmp",
154
- graphqlSystemAliases: ["@/graphql-system"],
155
- include: [],
156
- exclude: [],
157
- schemas: {
158
- default: {
159
- schema: ["/tmp/schema.graphql"],
160
- inject: { scalars: "/tmp/scalars.ts" },
161
- defaultInputDepth: 3,
162
- inputDepthOverrides: {},
163
- },
164
- },
165
- styles: { importExtension: false },
166
- plugins: {},
167
- },
138
+ config,
168
139
  moduleFormat: "cjs",
169
140
  });
170
141
  const normalized = await normalizeCode(result);
@@ -183,23 +154,7 @@ describe("swc", async () => {
183
154
  sourceCode: testCase.input.sourceCode,
184
155
  sourcePath: testCase.input.sourcePath,
185
156
  artifact: testCase.input.artifact,
186
- config: {
187
- analyzer: "ts",
188
- outdir: "/tmp",
189
- graphqlSystemAliases: ["@/graphql-system"],
190
- include: [],
191
- exclude: [],
192
- schemas: {
193
- default: {
194
- schema: ["/tmp/schema.graphql"],
195
- inject: { scalars: "/tmp/scalars.ts" },
196
- defaultInputDepth: 3,
197
- inputDepthOverrides: {},
198
- },
199
- },
200
- styles: { importExtension: false },
201
- plugins: {},
202
- },
157
+ config,
203
158
  moduleFormat: "esm",
204
159
  });
205
160
 
@@ -226,6 +181,7 @@ const writeFile = (filePath: string, content: string): void => {
226
181
  */
227
182
  const createStubTestConfig = (options: { outdir: string; scalarsPath: string; adapterPath?: string }): ResolvedSodaGqlConfig => ({
228
183
  analyzer: "ts",
184
+ baseDir: dirname(options.outdir),
229
185
  outdir: options.outdir,
230
186
  graphqlSystemAliases: ["@/graphql-system"],
231
187
  include: [],
@@ -242,6 +198,7 @@ const createStubTestConfig = (options: { outdir: string; scalarsPath: string; ad
242
198
  },
243
199
  },
244
200
  styles: { importExtension: false },
201
+ codegen: { chunkSize: 100 },
245
202
  plugins: {},
246
203
  });
247
204
 
@@ -373,6 +330,7 @@ describe("swc internal module stubbing", () => {
373
330
 
374
331
  const config: ResolvedSodaGqlConfig = {
375
332
  analyzer: "ts",
333
+ baseDir: tmpDir,
376
334
  outdir,
377
335
  graphqlSystemAliases: ["@/graphql-system"],
378
336
  include: [],
@@ -392,6 +350,7 @@ describe("swc internal module stubbing", () => {
392
350
  },
393
351
  },
394
352
  styles: { importExtension: false },
353
+ codegen: { chunkSize: 100 },
395
354
  plugins: {},
396
355
  };
397
356