@soda-gql/swc 0.11.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/README.md +79 -0
- package/dist/index.cjs +915 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +91 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +91 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +913 -0
- package/dist/index.mjs.map +1 -0
- package/dist/native/index.d.ts +42 -0
- package/dist/native/index.js +316 -0
- package/dist/native/swc.linux-x64-gnu.node +0 -0
- package/dist/native.cjs +254 -0
- package/dist/native.cjs.map +1 -0
- package/dist/native.d.cts +46 -0
- package/dist/native.d.cts.map +1 -0
- package/dist/native.d.mts +46 -0
- package/dist/native.d.mts.map +1 -0
- package/dist/native.mjs +256 -0
- package/dist/native.mjs.map +1 -0
- package/package.json +80 -0
- package/src/index.ts +290 -0
- package/src/lib.rs +87 -0
- package/src/native/index.d.ts +42 -0
- package/src/native/index.js +316 -0
- package/src/native/swc.linux-x64-gnu.node +0 -0
- package/src/transform/analysis.rs +240 -0
- package/src/transform/imports.rs +285 -0
- package/src/transform/metadata.rs +371 -0
- package/src/transform/mod.rs +7 -0
- package/src/transform/runtime.rs +197 -0
- package/src/transform/transformer.rs +438 -0
- package/src/transformer.test.ts +209 -0
- package/src/types/artifact.rs +107 -0
- package/src/types/config.rs +72 -0
- package/src/types/error.rs +132 -0
- package/src/types/mod.rs +12 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native.mjs","names":[],"sources":["../src/native/index.js"],"sourcesContent":["/* tslint:disable */\n/* eslint-disable */\n/* prettier-ignore */\n\n/* auto-generated by NAPI-RS */\n\nconst { existsSync, readFileSync } = require('fs')\nconst { join } = require('path')\n\nconst { platform, arch } = process\n\nlet nativeBinding = null\nlet localFileExisted = false\nlet loadError = null\n\nfunction isMusl() {\n // For Node 10\n if (!process.report || typeof process.report.getReport !== 'function') {\n try {\n const lddPath = require('child_process').execSync('which ldd').toString().trim()\n return readFileSync(lddPath, 'utf8').includes('musl')\n } catch (e) {\n return true\n }\n } else {\n const { glibcVersionRuntime } = process.report.getReport().header\n return !glibcVersionRuntime\n }\n}\n\nswitch (platform) {\n case 'android':\n switch (arch) {\n case 'arm64':\n localFileExisted = existsSync(join(__dirname, 'swc.android-arm64.node'))\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'android-arm64.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'android-arm64')\n }\n } catch (e) {\n loadError = e\n }\n break\n case 'arm':\n localFileExisted = existsSync(join(__dirname, 'swc.android-arm-eabi.node'))\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'android-arm-eabi.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'android-arm-eabi')\n }\n } catch (e) {\n loadError = e\n }\n break\n default:\n throw new Error(`Unsupported architecture on Android ${arch}`)\n }\n break\n case 'win32':\n switch (arch) {\n case 'x64':\n localFileExisted = existsSync(\n join(__dirname, 'swc.win32-x64-msvc.node')\n )\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'win32-x64-msvc.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'win32-x64-msvc')\n }\n } catch (e) {\n loadError = e\n }\n break\n case 'ia32':\n localFileExisted = existsSync(\n join(__dirname, 'swc.win32-ia32-msvc.node')\n )\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'win32-ia32-msvc.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'win32-ia32-msvc')\n }\n } catch (e) {\n loadError = e\n }\n break\n case 'arm64':\n localFileExisted = existsSync(\n join(__dirname, 'swc.win32-arm64-msvc.node')\n )\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'win32-arm64-msvc.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'win32-arm64-msvc')\n }\n } catch (e) {\n loadError = e\n }\n break\n default:\n throw new Error(`Unsupported architecture on Windows: ${arch}`)\n }\n break\n case 'darwin':\n localFileExisted = existsSync(join(__dirname, 'swc.darwin-universal.node'))\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'darwin-universal.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'darwin-universal')\n }\n break\n } catch {}\n switch (arch) {\n case 'x64':\n localFileExisted = existsSync(join(__dirname, 'swc.darwin-x64.node'))\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'darwin-x64.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'darwin-x64')\n }\n } catch (e) {\n loadError = e\n }\n break\n case 'arm64':\n localFileExisted = existsSync(\n join(__dirname, 'swc.darwin-arm64.node')\n )\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'darwin-arm64.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'darwin-arm64')\n }\n } catch (e) {\n loadError = e\n }\n break\n default:\n throw new Error(`Unsupported architecture on macOS: ${arch}`)\n }\n break\n case 'freebsd':\n if (arch !== 'x64') {\n throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)\n }\n localFileExisted = existsSync(join(__dirname, 'swc.freebsd-x64.node'))\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'freebsd-x64.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'freebsd-x64')\n }\n } catch (e) {\n loadError = e\n }\n break\n case 'linux':\n switch (arch) {\n case 'x64':\n if (isMusl()) {\n localFileExisted = existsSync(\n join(__dirname, 'swc.linux-x64-musl.node')\n )\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'linux-x64-musl.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'linux-x64-musl')\n }\n } catch (e) {\n loadError = e\n }\n } else {\n localFileExisted = existsSync(\n join(__dirname, 'swc.linux-x64-gnu.node')\n )\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'linux-x64-gnu.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'linux-x64-gnu')\n }\n } catch (e) {\n loadError = e\n }\n }\n break\n case 'arm64':\n if (isMusl()) {\n localFileExisted = existsSync(\n join(__dirname, 'swc.linux-arm64-musl.node')\n )\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'linux-arm64-musl.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'linux-arm64-musl')\n }\n } catch (e) {\n loadError = e\n }\n } else {\n localFileExisted = existsSync(\n join(__dirname, 'swc.linux-arm64-gnu.node')\n )\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'linux-arm64-gnu.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'linux-arm64-gnu')\n }\n } catch (e) {\n loadError = e\n }\n }\n break\n case 'arm':\n if (isMusl()) {\n localFileExisted = existsSync(\n join(__dirname, 'swc.linux-arm-musleabihf.node')\n )\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'linux-arm-musleabihf.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'linux-arm-musleabihf')\n }\n } catch (e) {\n loadError = e\n }\n } else {\n localFileExisted = existsSync(\n join(__dirname, 'swc.linux-arm-gnueabihf.node')\n )\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'linux-arm-gnueabihf.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'linux-arm-gnueabihf')\n }\n } catch (e) {\n loadError = e\n }\n }\n break\n case 'riscv64':\n if (isMusl()) {\n localFileExisted = existsSync(\n join(__dirname, 'swc.linux-riscv64-musl.node')\n )\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'linux-riscv64-musl.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'linux-riscv64-musl')\n }\n } catch (e) {\n loadError = e\n }\n } else {\n localFileExisted = existsSync(\n join(__dirname, 'swc.linux-riscv64-gnu.node')\n )\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'linux-riscv64-gnu.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'linux-riscv64-gnu')\n }\n } catch (e) {\n loadError = e\n }\n }\n break\n case 's390x':\n localFileExisted = existsSync(\n join(__dirname, 'swc.linux-s390x-gnu.node')\n )\n try {\n if (localFileExisted) {\n nativeBinding = require('./swc.'.slice(0) + 'linux-s390x-gnu.node')\n } else {\n nativeBinding = require('@soda-gql/swc-'.slice(0) + 'linux-s390x-gnu')\n }\n } catch (e) {\n loadError = e\n }\n break\n default:\n throw new Error(`Unsupported architecture on Linux: ${arch}`)\n }\n break\n default:\n throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)\n}\n\nif (!nativeBinding) {\n if (loadError) {\n throw loadError\n }\n throw new Error(`Failed to load native binding`)\n}\n\nconst { transform, SwcTransformer } = nativeBinding\n\nmodule.exports.transform = transform\nmodule.exports.SwcTransformer = SwcTransformer\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@soda-gql/swc",
|
|
3
|
+
"version": "0.11.0",
|
|
4
|
+
"description": "SWC-based native transformer for soda-gql",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"private": false,
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"src"
|
|
11
|
+
],
|
|
12
|
+
"author": {
|
|
13
|
+
"name": "Shota Hatada",
|
|
14
|
+
"email": "shota.hatada@whatasoda.me",
|
|
15
|
+
"url": "https://github.com/whatasoda"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"graphql",
|
|
19
|
+
"codegen",
|
|
20
|
+
"zero-runtime",
|
|
21
|
+
"typescript",
|
|
22
|
+
"swc",
|
|
23
|
+
"transformer",
|
|
24
|
+
"native"
|
|
25
|
+
],
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/whatasoda/soda-gql.git",
|
|
29
|
+
"directory": "packages/swc"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/whatasoda/soda-gql#readme",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/whatasoda/soda-gql/issues"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18"
|
|
37
|
+
},
|
|
38
|
+
"main": "./dist/index.mjs",
|
|
39
|
+
"module": "./dist/index.mjs",
|
|
40
|
+
"types": "./dist/index.d.mts",
|
|
41
|
+
"exports": {
|
|
42
|
+
"./native": {
|
|
43
|
+
"@soda-gql": "./@x-native.ts",
|
|
44
|
+
"types": "./dist/native.d.mts",
|
|
45
|
+
"import": "./dist/native.mjs",
|
|
46
|
+
"require": "./dist/native.cjs",
|
|
47
|
+
"default": "./dist/native.mjs"
|
|
48
|
+
},
|
|
49
|
+
".": {
|
|
50
|
+
"@soda-gql": "./@x-index.ts",
|
|
51
|
+
"types": "./dist/index.d.mts",
|
|
52
|
+
"import": "./dist/index.mjs",
|
|
53
|
+
"require": "./dist/index.cjs",
|
|
54
|
+
"default": "./dist/index.mjs"
|
|
55
|
+
},
|
|
56
|
+
"./package.json": "./package.json"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@ampproject/remapping": "^2.3.0",
|
|
60
|
+
"@soda-gql/builder": "0.11.0",
|
|
61
|
+
"@soda-gql/common": "0.11.0",
|
|
62
|
+
"@soda-gql/config": "0.11.0",
|
|
63
|
+
"@soda-gql/core": "0.11.0"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@napi-rs/cli": "^2.18.4",
|
|
67
|
+
"@soda-gql/tsc": "0.11.0",
|
|
68
|
+
"prettier": "^3.4.2"
|
|
69
|
+
},
|
|
70
|
+
"peerDependencies": {
|
|
71
|
+
"@swc/core": "^1.0.0"
|
|
72
|
+
},
|
|
73
|
+
"optionalDependencies": {
|
|
74
|
+
"@soda-gql/swc-darwin-x64": "0.11.0",
|
|
75
|
+
"@soda-gql/swc-darwin-arm64": "0.11.0",
|
|
76
|
+
"@soda-gql/swc-linux-x64-musl": "0.11.0",
|
|
77
|
+
"@soda-gql/swc-win32-x64-msvc": "0.11.0",
|
|
78
|
+
"@soda-gql/swc-linux-x64-gnu": "0.11.0"
|
|
79
|
+
}
|
|
80
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SWC-based transformer for soda-gql GraphQL code generation.
|
|
3
|
+
*
|
|
4
|
+
* This module provides a TypeScript wrapper around the native Rust transformer.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { realpathSync } from "node:fs";
|
|
8
|
+
import { resolve } from "node:path";
|
|
9
|
+
import remapping from "@ampproject/remapping";
|
|
10
|
+
import type { BuilderArtifact } from "@soda-gql/builder";
|
|
11
|
+
import type { ResolvedSodaGqlConfig } from "@soda-gql/config";
|
|
12
|
+
|
|
13
|
+
// The native module will be loaded at runtime via the napi-rs generated loader
|
|
14
|
+
let nativeModule: NativeModule | null = null;
|
|
15
|
+
|
|
16
|
+
interface NativeModule {
|
|
17
|
+
transform(inputJson: string): string;
|
|
18
|
+
SwcTransformer: new (artifactJson: string, configJson: string) => NativeTransformer;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface NativeTransformer {
|
|
22
|
+
transform(sourceCode: string, sourcePath: string): string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Plugin error from the SWC transformer.
|
|
27
|
+
* This matches the Rust PluginError structure for consistent error reporting.
|
|
28
|
+
*/
|
|
29
|
+
export type SwcPluginError = {
|
|
30
|
+
/** Always "PluginError" for type discrimination */
|
|
31
|
+
readonly type: "PluginError";
|
|
32
|
+
/** Error code for programmatic handling (e.g., "SODA_GQL_METADATA_NOT_FOUND") */
|
|
33
|
+
readonly code: string;
|
|
34
|
+
/** Human-readable error message */
|
|
35
|
+
readonly message: string;
|
|
36
|
+
/** Stage where the error occurred */
|
|
37
|
+
readonly stage: "analysis" | "transform";
|
|
38
|
+
/** Source filename if applicable */
|
|
39
|
+
readonly filename?: string;
|
|
40
|
+
/** Canonical ID if applicable */
|
|
41
|
+
readonly canonicalId?: string;
|
|
42
|
+
/** Artifact type if applicable */
|
|
43
|
+
readonly artifactType?: string;
|
|
44
|
+
/** Builder type if applicable */
|
|
45
|
+
readonly builderType?: string;
|
|
46
|
+
/** Argument name if applicable */
|
|
47
|
+
readonly argName?: string;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
interface TransformResult {
|
|
51
|
+
outputCode: string;
|
|
52
|
+
transformed: boolean;
|
|
53
|
+
sourceMap?: string;
|
|
54
|
+
errors?: SwcPluginError[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Load the native module.
|
|
59
|
+
* Uses the napi-rs generated loader which handles platform detection.
|
|
60
|
+
*/
|
|
61
|
+
const loadNativeModule = async (): Promise<NativeModule> => {
|
|
62
|
+
if (nativeModule) {
|
|
63
|
+
return nativeModule;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
// Use require() for the napi-rs generated loader (CommonJS)
|
|
68
|
+
const { createRequire } = await import("node:module");
|
|
69
|
+
const require = createRequire(import.meta.url);
|
|
70
|
+
nativeModule = require("./native/index.js") as NativeModule;
|
|
71
|
+
return nativeModule;
|
|
72
|
+
} catch (error) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
"Failed to load @soda-gql/swc native module. " +
|
|
75
|
+
"Make sure the native module is built for your platform. " +
|
|
76
|
+
`Run 'bun run build' in the packages/swc directory. (${error})`,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export type ModuleFormat = "esm" | "cjs";
|
|
82
|
+
|
|
83
|
+
export type TransformOptions = {
|
|
84
|
+
/** Compiler options for output format */
|
|
85
|
+
compilerOptions?: {
|
|
86
|
+
/** Module format: CommonJS or ESNext */
|
|
87
|
+
module?: "CommonJS" | "ESNext";
|
|
88
|
+
};
|
|
89
|
+
/** Resolved soda-gql configuration */
|
|
90
|
+
config: ResolvedSodaGqlConfig;
|
|
91
|
+
/** Pre-built artifact from the builder */
|
|
92
|
+
artifact: BuilderArtifact;
|
|
93
|
+
/** Whether to generate source maps */
|
|
94
|
+
sourceMap?: boolean;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export type TransformInput = {
|
|
98
|
+
/** Source code to transform */
|
|
99
|
+
sourceCode: string;
|
|
100
|
+
/** Path to the source file */
|
|
101
|
+
sourcePath: string;
|
|
102
|
+
/** Input source map from previous transformer (JSON string) */
|
|
103
|
+
inputSourceMap?: string;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Normalize path separators to forward slashes (cross-platform).
|
|
108
|
+
* This matches the behavior of @soda-gql/common normalizePath.
|
|
109
|
+
*/
|
|
110
|
+
const normalizePath = (value: string): string => value.replace(/\\/g, "/");
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Filter artifact to only include elements for the given source file.
|
|
114
|
+
* This significantly reduces JSON serialization overhead for large codebases.
|
|
115
|
+
*
|
|
116
|
+
* Canonical IDs have the format: "filepath::astPath"
|
|
117
|
+
* We filter by matching the filepath prefix.
|
|
118
|
+
*/
|
|
119
|
+
const filterArtifactForFile = (artifact: BuilderArtifact, sourcePath: string): BuilderArtifact => {
|
|
120
|
+
const prefix = `${sourcePath}::`;
|
|
121
|
+
|
|
122
|
+
const filteredElements: BuilderArtifact["elements"] = {};
|
|
123
|
+
for (const [id, element] of Object.entries(artifact.elements)) {
|
|
124
|
+
if (id.startsWith(prefix)) {
|
|
125
|
+
(filteredElements as Record<string, typeof element>)[id] = element;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
elements: filteredElements,
|
|
131
|
+
report: { stats: { hits: 0, misses: 0, skips: 0 }, durationMs: 0, warnings: [] },
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Resolve the canonical path to the graphql-system file.
|
|
137
|
+
* Uses realpath to resolve symlinks for accurate comparison.
|
|
138
|
+
*/
|
|
139
|
+
const resolveGraphqlSystemPath = (config: ResolvedSodaGqlConfig): string => {
|
|
140
|
+
const graphqlSystemPath = resolve(config.outdir, "index.ts");
|
|
141
|
+
try {
|
|
142
|
+
return normalizePath(realpathSync(graphqlSystemPath));
|
|
143
|
+
} catch {
|
|
144
|
+
// If realpath fails (file doesn't exist yet), fall back to resolved path
|
|
145
|
+
return normalizePath(resolve(graphqlSystemPath));
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export type TransformOutput = {
|
|
150
|
+
/** Whether any transformation was performed */
|
|
151
|
+
transformed: boolean;
|
|
152
|
+
/** The transformed source code (or original if no transformation) */
|
|
153
|
+
sourceCode: string;
|
|
154
|
+
/** Source map JSON, if source map generation was enabled */
|
|
155
|
+
sourceMap?: string;
|
|
156
|
+
/** Errors encountered during transformation (non-fatal) */
|
|
157
|
+
errors: SwcPluginError[];
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Transformer interface.
|
|
162
|
+
*/
|
|
163
|
+
export interface Transformer {
|
|
164
|
+
transform(input: TransformInput): TransformOutput;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Create a transformer instance.
|
|
169
|
+
*
|
|
170
|
+
* @param options - Transform options including config and artifact
|
|
171
|
+
* @returns A transformer that can transform source files
|
|
172
|
+
*/
|
|
173
|
+
export const createTransformer = async (options: TransformOptions): Promise<Transformer> => {
|
|
174
|
+
const native = await loadNativeModule();
|
|
175
|
+
|
|
176
|
+
const isCJS = options.compilerOptions?.module === "CommonJS";
|
|
177
|
+
|
|
178
|
+
// Resolve the graphql-system file path for stubbing
|
|
179
|
+
const graphqlSystemPath = resolveGraphqlSystemPath(options.config);
|
|
180
|
+
|
|
181
|
+
const configJson = JSON.stringify({
|
|
182
|
+
graphqlSystemAliases: options.config.graphqlSystemAliases,
|
|
183
|
+
isCjs: isCJS,
|
|
184
|
+
graphqlSystemPath,
|
|
185
|
+
sourceMap: options.sourceMap ?? false,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Store full artifact for per-file filtering
|
|
189
|
+
const fullArtifact = options.artifact;
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
transform: ({ sourceCode, sourcePath, inputSourceMap }: TransformInput): TransformOutput => {
|
|
193
|
+
// Resolve to absolute path and normalize for canonical ID consistency
|
|
194
|
+
// This ensures bundlers can pass relative paths safely
|
|
195
|
+
const normalizedPath = normalizePath(resolve(sourcePath));
|
|
196
|
+
|
|
197
|
+
// Filter artifact to only include elements for this file
|
|
198
|
+
// This significantly reduces JSON serialization overhead for large codebases
|
|
199
|
+
const filteredArtifact = filterArtifactForFile(fullArtifact, normalizedPath);
|
|
200
|
+
const filteredArtifactJson = JSON.stringify(filteredArtifact);
|
|
201
|
+
|
|
202
|
+
// Create per-file transformer with filtered artifact
|
|
203
|
+
const fileTransformer = new native.SwcTransformer(filteredArtifactJson, configJson);
|
|
204
|
+
const resultJson = fileTransformer.transform(sourceCode, normalizedPath);
|
|
205
|
+
const result: TransformResult = JSON.parse(resultJson);
|
|
206
|
+
|
|
207
|
+
// Handle source map chaining
|
|
208
|
+
let finalSourceMap: string | undefined;
|
|
209
|
+
if (result.sourceMap) {
|
|
210
|
+
if (inputSourceMap) {
|
|
211
|
+
// Chain source maps: our map -> input map -> original source
|
|
212
|
+
const merged = remapping([JSON.parse(result.sourceMap), JSON.parse(inputSourceMap)], () => null);
|
|
213
|
+
finalSourceMap = JSON.stringify(merged);
|
|
214
|
+
} else {
|
|
215
|
+
finalSourceMap = result.sourceMap;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
transformed: result.transformed,
|
|
221
|
+
sourceCode: result.outputCode,
|
|
222
|
+
sourceMap: finalSourceMap,
|
|
223
|
+
errors: result.errors ?? [],
|
|
224
|
+
};
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Transform a single source file (one-shot).
|
|
231
|
+
*
|
|
232
|
+
* For transforming multiple files, use createTransformer() to reuse the artifact.
|
|
233
|
+
*
|
|
234
|
+
* @param input - Transform input including source, path, artifact, and config
|
|
235
|
+
* @returns Transform output
|
|
236
|
+
*/
|
|
237
|
+
export const transform = async (
|
|
238
|
+
input: TransformInput & {
|
|
239
|
+
artifact: BuilderArtifact;
|
|
240
|
+
config: ResolvedSodaGqlConfig;
|
|
241
|
+
isCjs?: boolean;
|
|
242
|
+
sourceMap?: boolean;
|
|
243
|
+
},
|
|
244
|
+
): Promise<TransformOutput> => {
|
|
245
|
+
const native = await loadNativeModule();
|
|
246
|
+
|
|
247
|
+
// Resolve to absolute path and normalize for canonical ID consistency
|
|
248
|
+
// This ensures bundlers can pass relative paths safely
|
|
249
|
+
const normalizedPath = normalizePath(resolve(input.sourcePath));
|
|
250
|
+
|
|
251
|
+
// Filter artifact to only include elements for this file
|
|
252
|
+
const filteredArtifact = filterArtifactForFile(input.artifact, normalizedPath);
|
|
253
|
+
|
|
254
|
+
// Resolve the graphql-system file path for stubbing
|
|
255
|
+
const graphqlSystemPath = resolveGraphqlSystemPath(input.config);
|
|
256
|
+
|
|
257
|
+
const inputJson = JSON.stringify({
|
|
258
|
+
sourceCode: input.sourceCode,
|
|
259
|
+
sourcePath: normalizedPath,
|
|
260
|
+
artifactJson: JSON.stringify(filteredArtifact),
|
|
261
|
+
config: {
|
|
262
|
+
graphqlSystemAliases: input.config.graphqlSystemAliases,
|
|
263
|
+
isCjs: input.isCjs ?? false,
|
|
264
|
+
graphqlSystemPath,
|
|
265
|
+
sourceMap: input.sourceMap ?? false,
|
|
266
|
+
},
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
const resultJson = native.transform(inputJson);
|
|
270
|
+
const result: TransformResult = JSON.parse(resultJson);
|
|
271
|
+
|
|
272
|
+
// Handle source map chaining
|
|
273
|
+
let finalSourceMap: string | undefined;
|
|
274
|
+
if (result.sourceMap) {
|
|
275
|
+
if (input.inputSourceMap) {
|
|
276
|
+
// Chain source maps: our map -> input map -> original source
|
|
277
|
+
const merged = remapping([JSON.parse(result.sourceMap), JSON.parse(input.inputSourceMap)], () => null);
|
|
278
|
+
finalSourceMap = JSON.stringify(merged);
|
|
279
|
+
} else {
|
|
280
|
+
finalSourceMap = result.sourceMap;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return {
|
|
285
|
+
transformed: result.transformed,
|
|
286
|
+
sourceCode: result.outputCode,
|
|
287
|
+
sourceMap: finalSourceMap,
|
|
288
|
+
errors: result.errors ?? [],
|
|
289
|
+
};
|
|
290
|
+
};
|
package/src/lib.rs
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
//! SWC-based transformer for soda-gql GraphQL code generation.
|
|
2
|
+
//!
|
|
3
|
+
//! This crate provides a native Node.js module using napi-rs that transforms
|
|
4
|
+
//! `gql.default()` calls into `gqlRuntime.*` calls at build time.
|
|
5
|
+
|
|
6
|
+
mod transform;
|
|
7
|
+
mod types;
|
|
8
|
+
|
|
9
|
+
use napi::bindgen_prelude::*;
|
|
10
|
+
use napi_derive::napi;
|
|
11
|
+
use types::config::{TransformConfig, TransformInput, TransformInputRef};
|
|
12
|
+
use types::BuilderArtifact;
|
|
13
|
+
|
|
14
|
+
/// Transform a single source file.
|
|
15
|
+
///
|
|
16
|
+
/// # Arguments
|
|
17
|
+
/// * `input_json` - JSON-serialized TransformInput containing source code, file path, artifact, and config
|
|
18
|
+
///
|
|
19
|
+
/// # Returns
|
|
20
|
+
/// JSON-serialized TransformResult containing the transformed code
|
|
21
|
+
#[napi]
|
|
22
|
+
pub fn transform(input_json: String) -> Result<String> {
|
|
23
|
+
let input: TransformInput = serde_json::from_str(&input_json)
|
|
24
|
+
.map_err(|e| Error::from_reason(format!("Failed to parse input: {}", e)))?;
|
|
25
|
+
|
|
26
|
+
let result = transform::transformer::transform_source(&input)
|
|
27
|
+
.map_err(|e| Error::from_reason(e))?;
|
|
28
|
+
|
|
29
|
+
serde_json::to_string(&result)
|
|
30
|
+
.map_err(|e| Error::from_reason(format!("Failed to serialize result: {}", e)))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// Stateful transformer that caches artifact and config for multiple file transformations.
|
|
34
|
+
///
|
|
35
|
+
/// The artifact is parsed once in the constructor and reused for all subsequent
|
|
36
|
+
/// transform calls, avoiding repeated JSON parsing overhead.
|
|
37
|
+
#[napi]
|
|
38
|
+
pub struct SwcTransformer {
|
|
39
|
+
/// Pre-parsed BuilderArtifact (parsed once in constructor)
|
|
40
|
+
artifact: BuilderArtifact,
|
|
41
|
+
config: TransformConfig,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#[napi]
|
|
45
|
+
impl SwcTransformer {
|
|
46
|
+
/// Create a new transformer instance.
|
|
47
|
+
///
|
|
48
|
+
/// # Arguments
|
|
49
|
+
/// * `artifact_json` - JSON-serialized BuilderArtifact
|
|
50
|
+
/// * `config_json` - JSON-serialized TransformConfig
|
|
51
|
+
#[napi(constructor)]
|
|
52
|
+
pub fn new(artifact_json: String, config_json: String) -> Result<Self> {
|
|
53
|
+
let config: TransformConfig = serde_json::from_str(&config_json)
|
|
54
|
+
.map_err(|e| Error::from_reason(format!("Failed to parse config: {}", e)))?;
|
|
55
|
+
|
|
56
|
+
// Parse artifact once in constructor to avoid repeated parsing
|
|
57
|
+
let artifact: BuilderArtifact = serde_json::from_str(&artifact_json)
|
|
58
|
+
.map_err(|e| Error::from_reason(format!("Failed to parse artifact: {}", e)))?;
|
|
59
|
+
|
|
60
|
+
Ok(SwcTransformer { artifact, config })
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// Transform a single source file.
|
|
64
|
+
///
|
|
65
|
+
/// # Arguments
|
|
66
|
+
/// * `source_code` - The source code to transform
|
|
67
|
+
/// * `source_path` - The file path of the source
|
|
68
|
+
///
|
|
69
|
+
/// # Returns
|
|
70
|
+
/// JSON-serialized TransformResult
|
|
71
|
+
#[napi]
|
|
72
|
+
pub fn transform(&self, source_code: String, source_path: String) -> Result<String> {
|
|
73
|
+
// Use pre-parsed artifact reference instead of re-parsing JSON
|
|
74
|
+
let input = TransformInputRef {
|
|
75
|
+
source_code,
|
|
76
|
+
source_path,
|
|
77
|
+
artifact: &self.artifact,
|
|
78
|
+
config: self.config.clone(),
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
let result = transform::transformer::transform_source_ref(&input)
|
|
82
|
+
.map_err(|e| Error::from_reason(e))?;
|
|
83
|
+
|
|
84
|
+
serde_json::to_string(&result)
|
|
85
|
+
.map_err(|e| Error::from_reason(format!("Failed to serialize result: {}", e)))
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/* auto-generated by NAPI-RS */
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Transform a single source file.
|
|
8
|
+
*
|
|
9
|
+
* # Arguments
|
|
10
|
+
* * `input_json` - JSON-serialized TransformInput containing source code, file path, artifact, and config
|
|
11
|
+
*
|
|
12
|
+
* # Returns
|
|
13
|
+
* JSON-serialized TransformResult containing the transformed code
|
|
14
|
+
*/
|
|
15
|
+
export declare function transform(inputJson: string): string
|
|
16
|
+
/**
|
|
17
|
+
* Stateful transformer that caches artifact and config for multiple file transformations.
|
|
18
|
+
*
|
|
19
|
+
* The artifact is parsed once in the constructor and reused for all subsequent
|
|
20
|
+
* transform calls, avoiding repeated JSON parsing overhead.
|
|
21
|
+
*/
|
|
22
|
+
export declare class SwcTransformer {
|
|
23
|
+
/**
|
|
24
|
+
* Create a new transformer instance.
|
|
25
|
+
*
|
|
26
|
+
* # Arguments
|
|
27
|
+
* * `artifact_json` - JSON-serialized BuilderArtifact
|
|
28
|
+
* * `config_json` - JSON-serialized TransformConfig
|
|
29
|
+
*/
|
|
30
|
+
constructor(artifactJson: string, configJson: string)
|
|
31
|
+
/**
|
|
32
|
+
* Transform a single source file.
|
|
33
|
+
*
|
|
34
|
+
* # Arguments
|
|
35
|
+
* * `source_code` - The source code to transform
|
|
36
|
+
* * `source_path` - The file path of the source
|
|
37
|
+
*
|
|
38
|
+
* # Returns
|
|
39
|
+
* JSON-serialized TransformResult
|
|
40
|
+
*/
|
|
41
|
+
transform(sourceCode: string, sourcePath: string): string
|
|
42
|
+
}
|