@ttsc/metro 0.16.3
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/LICENSE +21 -0
- package/README.md +91 -0
- package/lib/core/options.d.ts +77 -0
- package/lib/core/options.js +76 -0
- package/lib/core/options.js.map +1 -0
- package/lib/core/options.mjs +72 -0
- package/lib/core/options.mjs.map +1 -0
- package/lib/core/upstream.d.ts +44 -0
- package/lib/core/upstream.js +64 -0
- package/lib/core/upstream.js.map +1 -0
- package/lib/core/upstream.mjs +60 -0
- package/lib/core/upstream.mjs.map +1 -0
- package/lib/index.d.ts +28 -0
- package/lib/index.js +73 -0
- package/lib/index.js.map +1 -0
- package/lib/index.mjs +70 -0
- package/lib/index.mjs.map +1 -0
- package/lib/transformer.d.ts +52 -0
- package/lib/transformer.js +217 -0
- package/lib/transformer.js.map +1 -0
- package/lib/transformer.mjs +211 -0
- package/lib/transformer.mjs.map +1 -0
- package/package.json +83 -0
- package/src/core/options.ts +130 -0
- package/src/core/upstream.ts +87 -0
- package/src/index.ts +92 -0
- package/src/transformer.ts +249 -0
package/lib/index.mjs
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { join, dirname } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { ENV_KEY, serializeOptions } from './core/options.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `@ttsc/metro` — Metro (React Native / Expo) adapter for ttsc plugins.
|
|
7
|
+
*
|
|
8
|
+
* Metro bundles with Babel, which strips TypeScript types and never runs ttsc
|
|
9
|
+
* plugins, so neither the `ttsc` CLI nor `@ttsc/unplugin` can reach an RN/Expo
|
|
10
|
+
* build. {@link withTtsc} wires a Metro custom transformer that runs the ttsc
|
|
11
|
+
* plugin pass on each TypeScript file before handing the result to the
|
|
12
|
+
* project's existing Expo/React-Native Babel transformer.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* Expo```js
|
|
16
|
+
* // metro.config.js
|
|
17
|
+
* const { getDefaultConfig } = require("expo/metro-config");
|
|
18
|
+
* const { withTtsc } = require("@ttsc/metro");
|
|
19
|
+
*
|
|
20
|
+
* module.exports = withTtsc(getDefaultConfig(__dirname));
|
|
21
|
+
* ```;
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* Bare React Native
|
|
25
|
+
* ```js
|
|
26
|
+
* // metro.config.js
|
|
27
|
+
* const { getDefaultConfig } = require("@react-native/metro-config");
|
|
28
|
+
* const { withTtsc } = require("@ttsc/metro");
|
|
29
|
+
*
|
|
30
|
+
* module.exports = withTtsc(getDefaultConfig(__dirname));
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Wrap a Metro config so ttsc plugins run on every TypeScript file.
|
|
35
|
+
*
|
|
36
|
+
* Sets `transformer.babelTransformerPath` to this package's transformer and
|
|
37
|
+
* publishes the resolved options to Metro's worker processes via the
|
|
38
|
+
* {@link ENV_KEY} environment variable (the workers never see this call, so env
|
|
39
|
+
* is the transport — see `core/options.ts`). Compatible with Expo's
|
|
40
|
+
* `getDefaultConfig()` and bare React Native alike.
|
|
41
|
+
*
|
|
42
|
+
* With no `options`, the transformer auto-discovers `tsconfig.json` and runs
|
|
43
|
+
* the plugins configured there — the standard ttsc model. Pass `options` only
|
|
44
|
+
* to override the project path, plugin list, or include/exclude filters.
|
|
45
|
+
*/
|
|
46
|
+
function withTtsc(config, options = {}) {
|
|
47
|
+
process.env[ENV_KEY] = serializeOptions(options);
|
|
48
|
+
return {
|
|
49
|
+
...config,
|
|
50
|
+
transformer: {
|
|
51
|
+
...config.transformer,
|
|
52
|
+
babelTransformerPath: transformerModulePath(),
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Absolute path to the built transformer module Metro will `require`.
|
|
58
|
+
*
|
|
59
|
+
* Always the CommonJS build (`transformer.js`) next to this module: Metro
|
|
60
|
+
* resolves `babelTransformerPath` with `require`, and `metro.config.js` is a
|
|
61
|
+
* CommonJS module. Rollup rewrites `import.meta.url` for both the CJS and ESM
|
|
62
|
+
* builds, so this resolves correctly regardless of how the config loaded this
|
|
63
|
+
* entry.
|
|
64
|
+
*/
|
|
65
|
+
function transformerModulePath() {
|
|
66
|
+
return join(dirname(fileURLToPath(import.meta.url)), "transformer.js");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { withTtsc };
|
|
70
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;AAyBH;;;;;;;;;;;;AAYG;SACa,QAAQ,CACtB,MAAS,EACT,UAA4B,EAAE,EAAA;IAE9B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC;IAChD,OAAO;AACL,QAAA,GAAG,MAAM;AACT,QAAA,WAAW,EAAE;YACX,GAAG,MAAM,CAAC,WAAW;YACrB,oBAAoB,EAAE,qBAAqB,EAAE;AAC9C,SAAA;KACG;AACR;AAEA;;;;;;;;AAQG;AACH,SAAS,qBAAqB,GAAA;AAC5B,IAAA,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,gBAAgB,CAAC;AACxE;;;;"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ResolvedTtscMetroOptions } from "./core/options";
|
|
2
|
+
/**
|
|
3
|
+
* Resolve Metro's per-file `filename` to an absolute path.
|
|
4
|
+
*
|
|
5
|
+
* Metro hands the babel transformer a path **relative to `projectRoot`** (it
|
|
6
|
+
* reads the file via `fs.readFileSync(path.resolve(projectRoot, filename))`)
|
|
7
|
+
* and passes `projectRoot` inside `options`. The ttsc pass needs an absolute
|
|
8
|
+
* path that matches a key in the compiled program, so resolve against
|
|
9
|
+
* `projectRoot` — never `process.cwd()`, which differs from `projectRoot` in
|
|
10
|
+
* monorepos and when Metro is launched from a parent directory. Getting this
|
|
11
|
+
* wrong makes every file look "outside the project" and silently skips the
|
|
12
|
+
* plugin pass.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveAbsoluteFilename(filename: string, options?: Record<string, unknown>): string;
|
|
15
|
+
/**
|
|
16
|
+
* Metro transform entry point.
|
|
17
|
+
*
|
|
18
|
+
* Runs the ttsc plugin pass on TypeScript files, then delegates to the upstream
|
|
19
|
+
* Expo/React-Native Babel transformer to produce the AST Metro expects. The
|
|
20
|
+
* upstream call receives Metro's original params (notably the project-relative
|
|
21
|
+
* `filename`, which Babel expects); only `src` is replaced with the
|
|
22
|
+
* ttsc-transformed source.
|
|
23
|
+
*/
|
|
24
|
+
export declare function transform(params: {
|
|
25
|
+
src: string;
|
|
26
|
+
filename: string;
|
|
27
|
+
options: Record<string, unknown>;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
ast: object;
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* Metro transform-cache key.
|
|
34
|
+
*
|
|
35
|
+
* Metro already content-hashes each file, so this only has to invalidate when
|
|
36
|
+
* the transformer itself changes: package version + resolved options + the
|
|
37
|
+
* upstream transformer's own key (forwarded Metro's args, e.g. `projectRoot`,
|
|
38
|
+
* so a `babel.config.js` change still busts the cache). Resolving the upstream
|
|
39
|
+
* is deliberately non-fatal here — a missing peer must not crash cache-key
|
|
40
|
+
* computation. NOTE: this does not encode the tsconfig / plugin configuration
|
|
41
|
+
* or cross-file type dependencies, so after editing those (or a depended-upon
|
|
42
|
+
* type) run Metro with `--reset-cache`. See the README "Caveats" and
|
|
43
|
+
* samchon/ttsc#255.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getCacheKey(...args: unknown[]): string;
|
|
46
|
+
/**
|
|
47
|
+
* Decide whether a file should run through the ttsc pass. Only TypeScript
|
|
48
|
+
* sources (`.ts`/`.tsx`/`.cts`/`.mts`, excluding `.d.ts`) qualify; `exclude`
|
|
49
|
+
* substrings win over `include`, and an empty `include` means "all TypeScript".
|
|
50
|
+
* Exported for unit testing.
|
|
51
|
+
*/
|
|
52
|
+
export declare function shouldTransform(filename: string, opts: ResolvedTtscMetroOptions): boolean;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var api = require('@ttsc/unplugin/api');
|
|
4
|
+
var node_crypto = require('node:crypto');
|
|
5
|
+
var node_module = require('node:module');
|
|
6
|
+
var path = require('node:path');
|
|
7
|
+
var options$1 = require('./core/options.js');
|
|
8
|
+
var upstream = require('./core/upstream.js');
|
|
9
|
+
|
|
10
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
11
|
+
/**
|
|
12
|
+
* Metro custom transformer for ttsc.
|
|
13
|
+
*
|
|
14
|
+
* Metro loads this module via `transformer.babelTransformerPath` (wired by
|
|
15
|
+
* {@link withTtsc}) and calls {@link transform} once per file. The flow is:
|
|
16
|
+
*
|
|
17
|
+
* TypeScript source -> ttsc plugin pass (typia, nestia, …) via @ttsc/unplugin's
|
|
18
|
+
* core -> transformed TypeScript source -> upstream Expo/RN Babel transformer
|
|
19
|
+
* (strips types, RN transforms) -> Babel AST (what Metro consumes)
|
|
20
|
+
*
|
|
21
|
+
* The ttsc pass reuses `@ttsc/unplugin`'s `transformTtsc`, so the plugin
|
|
22
|
+
* contract, tsconfig discovery, and per-build cache are identical to every
|
|
23
|
+
* other bundler integration. See the package README for the v1 cost model and
|
|
24
|
+
* the cross-file cache-invalidation caveat.
|
|
25
|
+
*/
|
|
26
|
+
const nodeRequire = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('transformer.js', document.baseURI).href)));
|
|
27
|
+
/**
|
|
28
|
+
* Matches the TypeScript source extensions the ttsc pass handles (`.ts`,
|
|
29
|
+
* `.tsx`, `.cts`, `.mts`). JavaScript and declaration files are passed straight
|
|
30
|
+
* through to the upstream transformer.
|
|
31
|
+
*/
|
|
32
|
+
const TS_EXTENSION = /\.[cm]?tsx?$/;
|
|
33
|
+
const DECLARATION = /\.d\.[cm]?ts$/;
|
|
34
|
+
/**
|
|
35
|
+
* Per-worker singletons. Metro loads this module once per worker process and
|
|
36
|
+
* reuses it across every file that worker handles, so the resolved options, the
|
|
37
|
+
* transform cache, and the memoised `@ttsc/unplugin` options are all scoped to
|
|
38
|
+
* the worker.
|
|
39
|
+
*/
|
|
40
|
+
let resolved;
|
|
41
|
+
let unpluginOptions;
|
|
42
|
+
const cache = api.createTtscTransformCache();
|
|
43
|
+
/** Lazily resolve the worker-side options (from {@link resolveOptionsFromEnv}). */
|
|
44
|
+
function options() {
|
|
45
|
+
return (resolved ??= options$1.resolveOptionsFromEnv());
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolve Metro's per-file `filename` to an absolute path.
|
|
49
|
+
*
|
|
50
|
+
* Metro hands the babel transformer a path **relative to `projectRoot`** (it
|
|
51
|
+
* reads the file via `fs.readFileSync(path.resolve(projectRoot, filename))`)
|
|
52
|
+
* and passes `projectRoot` inside `options`. The ttsc pass needs an absolute
|
|
53
|
+
* path that matches a key in the compiled program, so resolve against
|
|
54
|
+
* `projectRoot` — never `process.cwd()`, which differs from `projectRoot` in
|
|
55
|
+
* monorepos and when Metro is launched from a parent directory. Getting this
|
|
56
|
+
* wrong makes every file look "outside the project" and silently skips the
|
|
57
|
+
* plugin pass.
|
|
58
|
+
*/
|
|
59
|
+
function resolveAbsoluteFilename(filename, options) {
|
|
60
|
+
if (path.isAbsolute(filename)) {
|
|
61
|
+
return filename;
|
|
62
|
+
}
|
|
63
|
+
const projectRoot = options !== undefined && typeof options.projectRoot === "string"
|
|
64
|
+
? options.projectRoot
|
|
65
|
+
: process.cwd();
|
|
66
|
+
return path.resolve(projectRoot, filename);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Metro transform entry point.
|
|
70
|
+
*
|
|
71
|
+
* Runs the ttsc plugin pass on TypeScript files, then delegates to the upstream
|
|
72
|
+
* Expo/React-Native Babel transformer to produce the AST Metro expects. The
|
|
73
|
+
* upstream call receives Metro's original params (notably the project-relative
|
|
74
|
+
* `filename`, which Babel expects); only `src` is replaced with the
|
|
75
|
+
* ttsc-transformed source.
|
|
76
|
+
*/
|
|
77
|
+
async function transform(params) {
|
|
78
|
+
const opts = options();
|
|
79
|
+
const upstream$1 = upstream.resolveUpstreamTransformer(opts.upstreamTransformer);
|
|
80
|
+
// Gate on the project-relative path Metro supplies, so include/exclude
|
|
81
|
+
// substrings match what the user writes (e.g. "src/generated") and never
|
|
82
|
+
// collide with an absolute ancestor directory name. The absolute path is used
|
|
83
|
+
// only to address the file inside the compiled program.
|
|
84
|
+
if (!shouldTransform(params.filename, opts)) {
|
|
85
|
+
return upstream$1.transform(params);
|
|
86
|
+
}
|
|
87
|
+
let transformedSrc = params.src;
|
|
88
|
+
try {
|
|
89
|
+
unpluginOptions ??= api.resolveOptions(opts.ttsc);
|
|
90
|
+
const result = await api.transformTtsc(resolveAbsoluteFilename(params.filename, params.options), params.src, unpluginOptions, undefined, cache);
|
|
91
|
+
if (result !== undefined && typeof result.code === "string") {
|
|
92
|
+
transformedSrc = result.code;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
// A file that is not part of the tsconfig program is not a build error —
|
|
97
|
+
// pass it through untransformed. Genuine compile/type failures propagate so
|
|
98
|
+
// Metro surfaces them, matching the other ttsc bundler integrations.
|
|
99
|
+
if (!isFileOutsideProject(error)) {
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return upstream$1.transform({ ...params, src: transformedSrc });
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Metro transform-cache key.
|
|
107
|
+
*
|
|
108
|
+
* Metro already content-hashes each file, so this only has to invalidate when
|
|
109
|
+
* the transformer itself changes: package version + resolved options + the
|
|
110
|
+
* upstream transformer's own key (forwarded Metro's args, e.g. `projectRoot`,
|
|
111
|
+
* so a `babel.config.js` change still busts the cache). Resolving the upstream
|
|
112
|
+
* is deliberately non-fatal here — a missing peer must not crash cache-key
|
|
113
|
+
* computation. NOTE: this does not encode the tsconfig / plugin configuration
|
|
114
|
+
* or cross-file type dependencies, so after editing those (or a depended-upon
|
|
115
|
+
* type) run Metro with `--reset-cache`. See the README "Caveats" and
|
|
116
|
+
* samchon/ttsc#255.
|
|
117
|
+
*/
|
|
118
|
+
function getCacheKey(...args) {
|
|
119
|
+
const opts = options();
|
|
120
|
+
const hash = node_crypto.createHash("sha256");
|
|
121
|
+
hash.update(`@ttsc/metro:${packageVersion()}`);
|
|
122
|
+
hash.update(stableStringify({
|
|
123
|
+
ttsc: opts.ttsc,
|
|
124
|
+
include: opts.include,
|
|
125
|
+
exclude: opts.exclude,
|
|
126
|
+
upstreamTransformer: opts.upstreamTransformer ?? null,
|
|
127
|
+
}));
|
|
128
|
+
const upstreamKey = upstreamCacheKey(opts.upstreamTransformer, args);
|
|
129
|
+
if (upstreamKey.length !== 0) {
|
|
130
|
+
hash.update(upstreamKey);
|
|
131
|
+
}
|
|
132
|
+
return hash.digest("hex");
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Fold the upstream transformer's cache key in, defensively. Forwards Metro's
|
|
136
|
+
* own `getCacheKey` arguments so the upstream's babelrc-derived key is
|
|
137
|
+
* preserved, and never throws: a missing peer or a throwing upstream
|
|
138
|
+
* `getCacheKey` yields an empty contribution rather than failing the whole
|
|
139
|
+
* build's cache keying.
|
|
140
|
+
*/
|
|
141
|
+
function upstreamCacheKey(upstreamTransformer, args) {
|
|
142
|
+
let upstream$1;
|
|
143
|
+
try {
|
|
144
|
+
upstream$1 = upstream.resolveUpstreamTransformer(upstreamTransformer);
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return "";
|
|
148
|
+
}
|
|
149
|
+
if (upstream$1.getCacheKey === undefined) {
|
|
150
|
+
return "";
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
return String(upstream$1.getCacheKey(...args) ?? "");
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
return "";
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Decide whether a file should run through the ttsc pass. Only TypeScript
|
|
161
|
+
* sources (`.ts`/`.tsx`/`.cts`/`.mts`, excluding `.d.ts`) qualify; `exclude`
|
|
162
|
+
* substrings win over `include`, and an empty `include` means "all TypeScript".
|
|
163
|
+
* Exported for unit testing.
|
|
164
|
+
*/
|
|
165
|
+
function shouldTransform(filename, opts) {
|
|
166
|
+
if (!TS_EXTENSION.test(filename) || DECLARATION.test(filename)) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
if (opts.exclude.some((pattern) => filename.includes(pattern))) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
if (opts.include.length !== 0 &&
|
|
173
|
+
!opts.include.some((pattern) => filename.includes(pattern))) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* `transformTtsc` throws `"ttsc transform did not return output for <file>"`
|
|
180
|
+
* when the requested file is not part of the compiled program (e.g. excluded
|
|
181
|
+
* from the tsconfig). That case is non-fatal — the file should pass through.
|
|
182
|
+
*/
|
|
183
|
+
function isFileOutsideProject(error) {
|
|
184
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
185
|
+
return message.includes("did not return output");
|
|
186
|
+
}
|
|
187
|
+
function packageVersion() {
|
|
188
|
+
try {
|
|
189
|
+
const pkg = nodeRequire("@ttsc/metro/package.json");
|
|
190
|
+
return pkg.version ?? "0";
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
return "0";
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* JSON-serialise with object keys sorted recursively, so two semantically equal
|
|
198
|
+
* option sets always hash to the same cache key regardless of property order.
|
|
199
|
+
*/
|
|
200
|
+
function stableStringify(value) {
|
|
201
|
+
if (Array.isArray(value)) {
|
|
202
|
+
return `[${value.map(stableStringify).join(",")}]`;
|
|
203
|
+
}
|
|
204
|
+
if (value !== null && typeof value === "object") {
|
|
205
|
+
return `{${Object.entries(value)
|
|
206
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
207
|
+
.map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`)
|
|
208
|
+
.join(",")}}`;
|
|
209
|
+
}
|
|
210
|
+
return JSON.stringify(value);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
exports.getCacheKey = getCacheKey;
|
|
214
|
+
exports.resolveAbsoluteFilename = resolveAbsoluteFilename;
|
|
215
|
+
exports.shouldTransform = shouldTransform;
|
|
216
|
+
exports.transform = transform;
|
|
217
|
+
//# sourceMappingURL=transformer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transformer.js","sources":["../src/transformer.ts"],"sourcesContent":[null],"names":["createRequire","createTtscTransformCache","resolveOptionsFromEnv","upstream","resolveUpstreamTransformer","resolveOptions","transformTtsc","createHash"],"mappings":"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"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { createTtscTransformCache, resolveOptions, transformTtsc } from '@ttsc/unplugin/api';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { resolveOptionsFromEnv } from './core/options.mjs';
|
|
6
|
+
import { resolveUpstreamTransformer } from './core/upstream.mjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Metro custom transformer for ttsc.
|
|
10
|
+
*
|
|
11
|
+
* Metro loads this module via `transformer.babelTransformerPath` (wired by
|
|
12
|
+
* {@link withTtsc}) and calls {@link transform} once per file. The flow is:
|
|
13
|
+
*
|
|
14
|
+
* TypeScript source -> ttsc plugin pass (typia, nestia, …) via @ttsc/unplugin's
|
|
15
|
+
* core -> transformed TypeScript source -> upstream Expo/RN Babel transformer
|
|
16
|
+
* (strips types, RN transforms) -> Babel AST (what Metro consumes)
|
|
17
|
+
*
|
|
18
|
+
* The ttsc pass reuses `@ttsc/unplugin`'s `transformTtsc`, so the plugin
|
|
19
|
+
* contract, tsconfig discovery, and per-build cache are identical to every
|
|
20
|
+
* other bundler integration. See the package README for the v1 cost model and
|
|
21
|
+
* the cross-file cache-invalidation caveat.
|
|
22
|
+
*/
|
|
23
|
+
const nodeRequire = createRequire(import.meta.url);
|
|
24
|
+
/**
|
|
25
|
+
* Matches the TypeScript source extensions the ttsc pass handles (`.ts`,
|
|
26
|
+
* `.tsx`, `.cts`, `.mts`). JavaScript and declaration files are passed straight
|
|
27
|
+
* through to the upstream transformer.
|
|
28
|
+
*/
|
|
29
|
+
const TS_EXTENSION = /\.[cm]?tsx?$/;
|
|
30
|
+
const DECLARATION = /\.d\.[cm]?ts$/;
|
|
31
|
+
/**
|
|
32
|
+
* Per-worker singletons. Metro loads this module once per worker process and
|
|
33
|
+
* reuses it across every file that worker handles, so the resolved options, the
|
|
34
|
+
* transform cache, and the memoised `@ttsc/unplugin` options are all scoped to
|
|
35
|
+
* the worker.
|
|
36
|
+
*/
|
|
37
|
+
let resolved;
|
|
38
|
+
let unpluginOptions;
|
|
39
|
+
const cache = createTtscTransformCache();
|
|
40
|
+
/** Lazily resolve the worker-side options (from {@link resolveOptionsFromEnv}). */
|
|
41
|
+
function options() {
|
|
42
|
+
return (resolved ??= resolveOptionsFromEnv());
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolve Metro's per-file `filename` to an absolute path.
|
|
46
|
+
*
|
|
47
|
+
* Metro hands the babel transformer a path **relative to `projectRoot`** (it
|
|
48
|
+
* reads the file via `fs.readFileSync(path.resolve(projectRoot, filename))`)
|
|
49
|
+
* and passes `projectRoot` inside `options`. The ttsc pass needs an absolute
|
|
50
|
+
* path that matches a key in the compiled program, so resolve against
|
|
51
|
+
* `projectRoot` — never `process.cwd()`, which differs from `projectRoot` in
|
|
52
|
+
* monorepos and when Metro is launched from a parent directory. Getting this
|
|
53
|
+
* wrong makes every file look "outside the project" and silently skips the
|
|
54
|
+
* plugin pass.
|
|
55
|
+
*/
|
|
56
|
+
function resolveAbsoluteFilename(filename, options) {
|
|
57
|
+
if (path.isAbsolute(filename)) {
|
|
58
|
+
return filename;
|
|
59
|
+
}
|
|
60
|
+
const projectRoot = options !== undefined && typeof options.projectRoot === "string"
|
|
61
|
+
? options.projectRoot
|
|
62
|
+
: process.cwd();
|
|
63
|
+
return path.resolve(projectRoot, filename);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Metro transform entry point.
|
|
67
|
+
*
|
|
68
|
+
* Runs the ttsc plugin pass on TypeScript files, then delegates to the upstream
|
|
69
|
+
* Expo/React-Native Babel transformer to produce the AST Metro expects. The
|
|
70
|
+
* upstream call receives Metro's original params (notably the project-relative
|
|
71
|
+
* `filename`, which Babel expects); only `src` is replaced with the
|
|
72
|
+
* ttsc-transformed source.
|
|
73
|
+
*/
|
|
74
|
+
async function transform(params) {
|
|
75
|
+
const opts = options();
|
|
76
|
+
const upstream = resolveUpstreamTransformer(opts.upstreamTransformer);
|
|
77
|
+
// Gate on the project-relative path Metro supplies, so include/exclude
|
|
78
|
+
// substrings match what the user writes (e.g. "src/generated") and never
|
|
79
|
+
// collide with an absolute ancestor directory name. The absolute path is used
|
|
80
|
+
// only to address the file inside the compiled program.
|
|
81
|
+
if (!shouldTransform(params.filename, opts)) {
|
|
82
|
+
return upstream.transform(params);
|
|
83
|
+
}
|
|
84
|
+
let transformedSrc = params.src;
|
|
85
|
+
try {
|
|
86
|
+
unpluginOptions ??= resolveOptions(opts.ttsc);
|
|
87
|
+
const result = await transformTtsc(resolveAbsoluteFilename(params.filename, params.options), params.src, unpluginOptions, undefined, cache);
|
|
88
|
+
if (result !== undefined && typeof result.code === "string") {
|
|
89
|
+
transformedSrc = result.code;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
// A file that is not part of the tsconfig program is not a build error —
|
|
94
|
+
// pass it through untransformed. Genuine compile/type failures propagate so
|
|
95
|
+
// Metro surfaces them, matching the other ttsc bundler integrations.
|
|
96
|
+
if (!isFileOutsideProject(error)) {
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return upstream.transform({ ...params, src: transformedSrc });
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Metro transform-cache key.
|
|
104
|
+
*
|
|
105
|
+
* Metro already content-hashes each file, so this only has to invalidate when
|
|
106
|
+
* the transformer itself changes: package version + resolved options + the
|
|
107
|
+
* upstream transformer's own key (forwarded Metro's args, e.g. `projectRoot`,
|
|
108
|
+
* so a `babel.config.js` change still busts the cache). Resolving the upstream
|
|
109
|
+
* is deliberately non-fatal here — a missing peer must not crash cache-key
|
|
110
|
+
* computation. NOTE: this does not encode the tsconfig / plugin configuration
|
|
111
|
+
* or cross-file type dependencies, so after editing those (or a depended-upon
|
|
112
|
+
* type) run Metro with `--reset-cache`. See the README "Caveats" and
|
|
113
|
+
* samchon/ttsc#255.
|
|
114
|
+
*/
|
|
115
|
+
function getCacheKey(...args) {
|
|
116
|
+
const opts = options();
|
|
117
|
+
const hash = createHash("sha256");
|
|
118
|
+
hash.update(`@ttsc/metro:${packageVersion()}`);
|
|
119
|
+
hash.update(stableStringify({
|
|
120
|
+
ttsc: opts.ttsc,
|
|
121
|
+
include: opts.include,
|
|
122
|
+
exclude: opts.exclude,
|
|
123
|
+
upstreamTransformer: opts.upstreamTransformer ?? null,
|
|
124
|
+
}));
|
|
125
|
+
const upstreamKey = upstreamCacheKey(opts.upstreamTransformer, args);
|
|
126
|
+
if (upstreamKey.length !== 0) {
|
|
127
|
+
hash.update(upstreamKey);
|
|
128
|
+
}
|
|
129
|
+
return hash.digest("hex");
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Fold the upstream transformer's cache key in, defensively. Forwards Metro's
|
|
133
|
+
* own `getCacheKey` arguments so the upstream's babelrc-derived key is
|
|
134
|
+
* preserved, and never throws: a missing peer or a throwing upstream
|
|
135
|
+
* `getCacheKey` yields an empty contribution rather than failing the whole
|
|
136
|
+
* build's cache keying.
|
|
137
|
+
*/
|
|
138
|
+
function upstreamCacheKey(upstreamTransformer, args) {
|
|
139
|
+
let upstream;
|
|
140
|
+
try {
|
|
141
|
+
upstream = resolveUpstreamTransformer(upstreamTransformer);
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return "";
|
|
145
|
+
}
|
|
146
|
+
if (upstream.getCacheKey === undefined) {
|
|
147
|
+
return "";
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
return String(upstream.getCacheKey(...args) ?? "");
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return "";
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Decide whether a file should run through the ttsc pass. Only TypeScript
|
|
158
|
+
* sources (`.ts`/`.tsx`/`.cts`/`.mts`, excluding `.d.ts`) qualify; `exclude`
|
|
159
|
+
* substrings win over `include`, and an empty `include` means "all TypeScript".
|
|
160
|
+
* Exported for unit testing.
|
|
161
|
+
*/
|
|
162
|
+
function shouldTransform(filename, opts) {
|
|
163
|
+
if (!TS_EXTENSION.test(filename) || DECLARATION.test(filename)) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
if (opts.exclude.some((pattern) => filename.includes(pattern))) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
if (opts.include.length !== 0 &&
|
|
170
|
+
!opts.include.some((pattern) => filename.includes(pattern))) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* `transformTtsc` throws `"ttsc transform did not return output for <file>"`
|
|
177
|
+
* when the requested file is not part of the compiled program (e.g. excluded
|
|
178
|
+
* from the tsconfig). That case is non-fatal — the file should pass through.
|
|
179
|
+
*/
|
|
180
|
+
function isFileOutsideProject(error) {
|
|
181
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
182
|
+
return message.includes("did not return output");
|
|
183
|
+
}
|
|
184
|
+
function packageVersion() {
|
|
185
|
+
try {
|
|
186
|
+
const pkg = nodeRequire("@ttsc/metro/package.json");
|
|
187
|
+
return pkg.version ?? "0";
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
return "0";
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* JSON-serialise with object keys sorted recursively, so two semantically equal
|
|
195
|
+
* option sets always hash to the same cache key regardless of property order.
|
|
196
|
+
*/
|
|
197
|
+
function stableStringify(value) {
|
|
198
|
+
if (Array.isArray(value)) {
|
|
199
|
+
return `[${value.map(stableStringify).join(",")}]`;
|
|
200
|
+
}
|
|
201
|
+
if (value !== null && typeof value === "object") {
|
|
202
|
+
return `{${Object.entries(value)
|
|
203
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
204
|
+
.map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`)
|
|
205
|
+
.join(",")}}`;
|
|
206
|
+
}
|
|
207
|
+
return JSON.stringify(value);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export { getCacheKey, resolveAbsoluteFilename, shouldTransform, transform };
|
|
211
|
+
//# sourceMappingURL=transformer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transformer.mjs","sources":["../src/transformer.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ttsc/metro",
|
|
3
|
+
"version": "0.16.3",
|
|
4
|
+
"description": "Metro (React Native / Expo) adapter for ttsc plugins.",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"module": "lib/index.mjs",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"import": "./lib/index.mjs",
|
|
12
|
+
"default": "./lib/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./transformer": {
|
|
15
|
+
"types": "./lib/transformer.d.ts",
|
|
16
|
+
"import": "./lib/transformer.mjs",
|
|
17
|
+
"default": "./lib/transformer.js"
|
|
18
|
+
},
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"ttsc",
|
|
26
|
+
"metro",
|
|
27
|
+
"react-native",
|
|
28
|
+
"expo",
|
|
29
|
+
"typescript",
|
|
30
|
+
"tsgo"
|
|
31
|
+
],
|
|
32
|
+
"files": [
|
|
33
|
+
"README.md",
|
|
34
|
+
"lib",
|
|
35
|
+
"src"
|
|
36
|
+
],
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@ttsc/unplugin": "0.16.3"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@expo/metro-config": "*",
|
|
42
|
+
"@react-native/metro-babel-transformer": "*",
|
|
43
|
+
"metro-react-native-babel-transformer": "*"
|
|
44
|
+
},
|
|
45
|
+
"peerDependenciesMeta": {
|
|
46
|
+
"@expo/metro-config": {
|
|
47
|
+
"optional": true
|
|
48
|
+
},
|
|
49
|
+
"@react-native/metro-babel-transformer": {
|
|
50
|
+
"optional": true
|
|
51
|
+
},
|
|
52
|
+
"metro-react-native-babel-transformer": {
|
|
53
|
+
"optional": true
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@rollup/plugin-commonjs": "^29.0.2",
|
|
58
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
59
|
+
"@types/node": "^25.3.0",
|
|
60
|
+
"rimraf": "^6.1.2",
|
|
61
|
+
"rollup": "^4.60.3",
|
|
62
|
+
"rollup-plugin-auto-external": "^2.0.0",
|
|
63
|
+
"rollup-plugin-node-externals": "^9.0.1",
|
|
64
|
+
"tinyglobby": "^0.2.16",
|
|
65
|
+
"tslib": "^2.8.1",
|
|
66
|
+
"typescript": "7.0.1-rc",
|
|
67
|
+
"ttsc": "0.16.3"
|
|
68
|
+
},
|
|
69
|
+
"repository": {
|
|
70
|
+
"type": "git",
|
|
71
|
+
"url": "https://github.com/samchon/ttsc"
|
|
72
|
+
},
|
|
73
|
+
"author": "Jeongho Nam",
|
|
74
|
+
"license": "MIT",
|
|
75
|
+
"bugs": {
|
|
76
|
+
"url": "https://github.com/samchon/ttsc/issues"
|
|
77
|
+
},
|
|
78
|
+
"homepage": "https://ttsc.dev",
|
|
79
|
+
"sideEffects": false,
|
|
80
|
+
"scripts": {
|
|
81
|
+
"build": "rimraf lib && tsc --emitDeclarationOnly && rollup -c"
|
|
82
|
+
}
|
|
83
|
+
}
|