@ttsc/metro 0.19.1 → 0.19.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/README.md +10 -1
- package/lib/core/fingerprint.d.ts +81 -0
- package/lib/core/fingerprint.js +449 -0
- package/lib/core/fingerprint.js.map +1 -0
- package/lib/core/fingerprint.mjs +441 -0
- package/lib/core/fingerprint.mjs.map +1 -0
- package/lib/index.js +6 -0
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +6 -0
- package/lib/index.mjs.map +1 -1
- package/lib/transformer.d.ts +19 -9
- package/lib/transformer.js +64 -29
- package/lib/transformer.js.map +1 -1
- package/lib/transformer.mjs +63 -28
- package/lib/transformer.mjs.map +1 -1
- package/package.json +3 -3
- package/src/core/fingerprint.ts +514 -0
- package/src/index.ts +8 -0
- package/src/transformer.ts +75 -28
package/lib/transformer.js
CHANGED
|
@@ -4,6 +4,7 @@ var api = require('@ttsc/unplugin/api');
|
|
|
4
4
|
var node_crypto = require('node:crypto');
|
|
5
5
|
var node_module = require('node:module');
|
|
6
6
|
var path = require('node:path');
|
|
7
|
+
var fingerprint = require('./core/fingerprint.js');
|
|
7
8
|
var options$1 = require('./core/options.js');
|
|
8
9
|
var upstream = require('./core/upstream.js');
|
|
9
10
|
|
|
@@ -20,8 +21,10 @@ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentS
|
|
|
20
21
|
*
|
|
21
22
|
* The ttsc pass reuses `@ttsc/unplugin`'s `transformTtsc`, so the plugin
|
|
22
23
|
* contract, tsconfig discovery, and per-build cache are identical to every
|
|
23
|
-
* other bundler integration.
|
|
24
|
-
*
|
|
24
|
+
* other bundler integration. Cross-file cache invalidation rides the project
|
|
25
|
+
* fingerprint {@link getCacheKey} folds into Metro's static transformer key (see
|
|
26
|
+
* `core/fingerprint.ts`); the package README covers the v1 cost model and the
|
|
27
|
+
* remaining watch-session boundary.
|
|
25
28
|
*/
|
|
26
29
|
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
30
|
/**
|
|
@@ -40,6 +43,7 @@ const DECLARATION = /\.d\.[cm]?ts$/;
|
|
|
40
43
|
let resolved;
|
|
41
44
|
let unpluginOptions;
|
|
42
45
|
const cache = api.createTtscTransformCache();
|
|
46
|
+
const snapshotRecorder = fingerprint.createSnapshotRecorder();
|
|
43
47
|
/** Lazily resolve the worker-side options (from {@link resolveOptionsFromEnv}). */
|
|
44
48
|
function options() {
|
|
45
49
|
return (resolved ??= options$1.resolveOptionsFromEnv());
|
|
@@ -87,7 +91,23 @@ async function transform(params) {
|
|
|
87
91
|
let transformedSrc = params.src;
|
|
88
92
|
try {
|
|
89
93
|
unpluginOptions ??= api.resolveOptions(opts.ttsc);
|
|
90
|
-
const
|
|
94
|
+
const projectRoot = typeof params.options.projectRoot === "string"
|
|
95
|
+
? params.options.projectRoot
|
|
96
|
+
: undefined;
|
|
97
|
+
const explicitProject = typeof opts.ttsc.project === "string" ? opts.ttsc.project : undefined;
|
|
98
|
+
const result = await api.transformTtsc(resolveAbsoluteFilename(params.filename, params.options), params.src, unpluginOptions, undefined, cache, {
|
|
99
|
+
// Metro offers no per-file dependency registration, so the derived
|
|
100
|
+
// watch inputs (plugin-reported dependencies unioned with the
|
|
101
|
+
// reference graph's reach, globals, and configs) feed the snapshot
|
|
102
|
+
// that the next run's getCacheKey re-hashes instead. Fires on cache
|
|
103
|
+
// hits too, so a worker that never recompiled still records the
|
|
104
|
+
// inputs backing the outputs it serves.
|
|
105
|
+
addWatchFile: (input) => snapshotRecorder.record({ explicitProject, input, projectRoot }),
|
|
106
|
+
// A volatile declaration means the output depends on non-file inputs
|
|
107
|
+
// that no file fingerprint can represent; the snapshot marks it and
|
|
108
|
+
// getCacheKey degrades to a per-run nonce (no cross-run reuse).
|
|
109
|
+
markVolatile: () => snapshotRecorder.recordVolatile({ explicitProject, projectRoot }),
|
|
110
|
+
});
|
|
91
111
|
if (result !== undefined && typeof result.code === "string") {
|
|
92
112
|
transformedSrc = result.code;
|
|
93
113
|
}
|
|
@@ -105,21 +125,31 @@ async function transform(params) {
|
|
|
105
125
|
/**
|
|
106
126
|
* Metro transform-cache key.
|
|
107
127
|
*
|
|
108
|
-
* Metro
|
|
109
|
-
* the
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
128
|
+
* Metro calls this once per run (dev-server start or cold `metro bundle`), on
|
|
129
|
+
* the main process, and folds the result into every file's per-content cache
|
|
130
|
+
* key. It must therefore incorporate every input that can influence a
|
|
131
|
+
* transform's output beyond the file's own content:
|
|
132
|
+
*
|
|
133
|
+
* - The transformer identity: package version + resolved options + the upstream
|
|
134
|
+
* transformer's own key (forwarded Metro's args, e.g. `projectRoot`, so a
|
|
135
|
+
* `babel.config.js` change still busts the cache);
|
|
136
|
+
* - The project fingerprint (see `core/fingerprint.ts`): every input file under
|
|
137
|
+
* the project walk (tsconfig, plugin configs, type-only siblings) plus the
|
|
138
|
+
* recorded out-of-walk reference-graph members from previous transforms
|
|
139
|
+
* (`node_modules` declarations, monorepo sibling sources, out-of-root config
|
|
140
|
+
* ancestry).
|
|
141
|
+
*
|
|
142
|
+
* A change to any fingerprinted input re-keys every transformed file —
|
|
143
|
+
* project-level granularity, forced by Metro's single static key — replacing
|
|
144
|
+
* the former manual `--reset-cache` step. Resolving the upstream is
|
|
145
|
+
* deliberately non-fatal here: a missing peer must not crash cache-key
|
|
146
|
+
* computation. See the README "Caveats" and samchon/ttsc#721.
|
|
117
147
|
*/
|
|
118
148
|
function getCacheKey(...args) {
|
|
119
149
|
const opts = options();
|
|
120
150
|
const hash = node_crypto.createHash("sha256");
|
|
121
151
|
hash.update(`@ttsc/metro:${packageVersion()}`);
|
|
122
|
-
hash.update(stableStringify({
|
|
152
|
+
hash.update(fingerprint.stableStringify({
|
|
123
153
|
ttsc: opts.ttsc,
|
|
124
154
|
include: opts.include,
|
|
125
155
|
exclude: opts.exclude,
|
|
@@ -129,8 +159,29 @@ function getCacheKey(...args) {
|
|
|
129
159
|
if (upstreamKey.length !== 0) {
|
|
130
160
|
hash.update(upstreamKey);
|
|
131
161
|
}
|
|
162
|
+
hash.update(fingerprint.computeProjectFingerprint({
|
|
163
|
+
explicitProject: typeof opts.ttsc.project === "string" ? opts.ttsc.project : undefined,
|
|
164
|
+
projectRoot: cacheKeyProjectRoot(args),
|
|
165
|
+
}));
|
|
132
166
|
return hash.digest("hex");
|
|
133
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Extract Metro's `projectRoot` from the cache-key options
|
|
170
|
+
* (`metro-transform-worker` calls `getCacheKey({ projectRoot,
|
|
171
|
+
* enableBabelRCLookup })`). Defensive against foreign callers: anything but a
|
|
172
|
+
* non-empty string yields `undefined` and the fingerprint falls back to the
|
|
173
|
+
* working directory.
|
|
174
|
+
*/
|
|
175
|
+
function cacheKeyProjectRoot(args) {
|
|
176
|
+
const first = args[0];
|
|
177
|
+
if (typeof first !== "object" || first === null) {
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
const projectRoot = first.projectRoot;
|
|
181
|
+
return typeof projectRoot === "string" && projectRoot.length !== 0
|
|
182
|
+
? projectRoot
|
|
183
|
+
: undefined;
|
|
184
|
+
}
|
|
134
185
|
/**
|
|
135
186
|
* Fold the upstream transformer's cache key in, defensively. Forwards Metro's
|
|
136
187
|
* own `getCacheKey` arguments so the upstream's babelrc-derived key is
|
|
@@ -193,22 +244,6 @@ function packageVersion() {
|
|
|
193
244
|
return "0";
|
|
194
245
|
}
|
|
195
246
|
}
|
|
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
247
|
|
|
213
248
|
exports.getCacheKey = getCacheKey;
|
|
214
249
|
exports.resolveAbsoluteFilename = resolveAbsoluteFilename;
|
package/lib/transformer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformer.js","sources":["../src/transformer.ts"],"sourcesContent":[null],"names":["createRequire","createTtscTransformCache","resolveOptionsFromEnv","upstream","resolveUpstreamTransformer","resolveOptions","transformTtsc","createHash"],"mappings":"
|
|
1
|
+
{"version":3,"file":"transformer.js","sources":["../src/transformer.ts"],"sourcesContent":[null],"names":["createRequire","createTtscTransformCache","createSnapshotRecorder","resolveOptionsFromEnv","upstream","resolveUpstreamTransformer","resolveOptions","transformTtsc","createHash","stableStringify","computeProjectFingerprint"],"mappings":"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"}
|
package/lib/transformer.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { createTtscTransformCache, resolveOptions, transformTtsc } from '@ttsc/u
|
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
3
|
import { createRequire } from 'node:module';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
+
import { createSnapshotRecorder, stableStringify, computeProjectFingerprint } from './core/fingerprint.mjs';
|
|
5
6
|
import { resolveOptionsFromEnv } from './core/options.mjs';
|
|
6
7
|
import { resolveUpstreamTransformer } from './core/upstream.mjs';
|
|
7
8
|
|
|
@@ -17,8 +18,10 @@ import { resolveUpstreamTransformer } from './core/upstream.mjs';
|
|
|
17
18
|
*
|
|
18
19
|
* The ttsc pass reuses `@ttsc/unplugin`'s `transformTtsc`, so the plugin
|
|
19
20
|
* contract, tsconfig discovery, and per-build cache are identical to every
|
|
20
|
-
* other bundler integration.
|
|
21
|
-
*
|
|
21
|
+
* other bundler integration. Cross-file cache invalidation rides the project
|
|
22
|
+
* fingerprint {@link getCacheKey} folds into Metro's static transformer key (see
|
|
23
|
+
* `core/fingerprint.ts`); the package README covers the v1 cost model and the
|
|
24
|
+
* remaining watch-session boundary.
|
|
22
25
|
*/
|
|
23
26
|
const nodeRequire = createRequire(import.meta.url);
|
|
24
27
|
/**
|
|
@@ -37,6 +40,7 @@ const DECLARATION = /\.d\.[cm]?ts$/;
|
|
|
37
40
|
let resolved;
|
|
38
41
|
let unpluginOptions;
|
|
39
42
|
const cache = createTtscTransformCache();
|
|
43
|
+
const snapshotRecorder = createSnapshotRecorder();
|
|
40
44
|
/** Lazily resolve the worker-side options (from {@link resolveOptionsFromEnv}). */
|
|
41
45
|
function options() {
|
|
42
46
|
return (resolved ??= resolveOptionsFromEnv());
|
|
@@ -84,7 +88,23 @@ async function transform(params) {
|
|
|
84
88
|
let transformedSrc = params.src;
|
|
85
89
|
try {
|
|
86
90
|
unpluginOptions ??= resolveOptions(opts.ttsc);
|
|
87
|
-
const
|
|
91
|
+
const projectRoot = typeof params.options.projectRoot === "string"
|
|
92
|
+
? params.options.projectRoot
|
|
93
|
+
: undefined;
|
|
94
|
+
const explicitProject = typeof opts.ttsc.project === "string" ? opts.ttsc.project : undefined;
|
|
95
|
+
const result = await transformTtsc(resolveAbsoluteFilename(params.filename, params.options), params.src, unpluginOptions, undefined, cache, {
|
|
96
|
+
// Metro offers no per-file dependency registration, so the derived
|
|
97
|
+
// watch inputs (plugin-reported dependencies unioned with the
|
|
98
|
+
// reference graph's reach, globals, and configs) feed the snapshot
|
|
99
|
+
// that the next run's getCacheKey re-hashes instead. Fires on cache
|
|
100
|
+
// hits too, so a worker that never recompiled still records the
|
|
101
|
+
// inputs backing the outputs it serves.
|
|
102
|
+
addWatchFile: (input) => snapshotRecorder.record({ explicitProject, input, projectRoot }),
|
|
103
|
+
// A volatile declaration means the output depends on non-file inputs
|
|
104
|
+
// that no file fingerprint can represent; the snapshot marks it and
|
|
105
|
+
// getCacheKey degrades to a per-run nonce (no cross-run reuse).
|
|
106
|
+
markVolatile: () => snapshotRecorder.recordVolatile({ explicitProject, projectRoot }),
|
|
107
|
+
});
|
|
88
108
|
if (result !== undefined && typeof result.code === "string") {
|
|
89
109
|
transformedSrc = result.code;
|
|
90
110
|
}
|
|
@@ -102,15 +122,25 @@ async function transform(params) {
|
|
|
102
122
|
/**
|
|
103
123
|
* Metro transform-cache key.
|
|
104
124
|
*
|
|
105
|
-
* Metro
|
|
106
|
-
* the
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
125
|
+
* Metro calls this once per run (dev-server start or cold `metro bundle`), on
|
|
126
|
+
* the main process, and folds the result into every file's per-content cache
|
|
127
|
+
* key. It must therefore incorporate every input that can influence a
|
|
128
|
+
* transform's output beyond the file's own content:
|
|
129
|
+
*
|
|
130
|
+
* - The transformer identity: package version + resolved options + the upstream
|
|
131
|
+
* transformer's own key (forwarded Metro's args, e.g. `projectRoot`, so a
|
|
132
|
+
* `babel.config.js` change still busts the cache);
|
|
133
|
+
* - The project fingerprint (see `core/fingerprint.ts`): every input file under
|
|
134
|
+
* the project walk (tsconfig, plugin configs, type-only siblings) plus the
|
|
135
|
+
* recorded out-of-walk reference-graph members from previous transforms
|
|
136
|
+
* (`node_modules` declarations, monorepo sibling sources, out-of-root config
|
|
137
|
+
* ancestry).
|
|
138
|
+
*
|
|
139
|
+
* A change to any fingerprinted input re-keys every transformed file —
|
|
140
|
+
* project-level granularity, forced by Metro's single static key — replacing
|
|
141
|
+
* the former manual `--reset-cache` step. Resolving the upstream is
|
|
142
|
+
* deliberately non-fatal here: a missing peer must not crash cache-key
|
|
143
|
+
* computation. See the README "Caveats" and samchon/ttsc#721.
|
|
114
144
|
*/
|
|
115
145
|
function getCacheKey(...args) {
|
|
116
146
|
const opts = options();
|
|
@@ -126,8 +156,29 @@ function getCacheKey(...args) {
|
|
|
126
156
|
if (upstreamKey.length !== 0) {
|
|
127
157
|
hash.update(upstreamKey);
|
|
128
158
|
}
|
|
159
|
+
hash.update(computeProjectFingerprint({
|
|
160
|
+
explicitProject: typeof opts.ttsc.project === "string" ? opts.ttsc.project : undefined,
|
|
161
|
+
projectRoot: cacheKeyProjectRoot(args),
|
|
162
|
+
}));
|
|
129
163
|
return hash.digest("hex");
|
|
130
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Extract Metro's `projectRoot` from the cache-key options
|
|
167
|
+
* (`metro-transform-worker` calls `getCacheKey({ projectRoot,
|
|
168
|
+
* enableBabelRCLookup })`). Defensive against foreign callers: anything but a
|
|
169
|
+
* non-empty string yields `undefined` and the fingerprint falls back to the
|
|
170
|
+
* working directory.
|
|
171
|
+
*/
|
|
172
|
+
function cacheKeyProjectRoot(args) {
|
|
173
|
+
const first = args[0];
|
|
174
|
+
if (typeof first !== "object" || first === null) {
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
const projectRoot = first.projectRoot;
|
|
178
|
+
return typeof projectRoot === "string" && projectRoot.length !== 0
|
|
179
|
+
? projectRoot
|
|
180
|
+
: undefined;
|
|
181
|
+
}
|
|
131
182
|
/**
|
|
132
183
|
* Fold the upstream transformer's cache key in, defensively. Forwards Metro's
|
|
133
184
|
* own `getCacheKey` arguments so the upstream's babelrc-derived key is
|
|
@@ -190,22 +241,6 @@ function packageVersion() {
|
|
|
190
241
|
return "0";
|
|
191
242
|
}
|
|
192
243
|
}
|
|
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
244
|
|
|
210
245
|
export { getCacheKey, resolveAbsoluteFilename, shouldTransform, transform };
|
|
211
246
|
//# sourceMappingURL=transformer.mjs.map
|
package/lib/transformer.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformer.mjs","sources":["../src/transformer.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"transformer.mjs","sources":["../src/transformer.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttsc/metro",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.3",
|
|
4
4
|
"description": "Metro (React Native / Expo) adapter for ttsc plugins.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/index.mjs",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"src"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@ttsc/unplugin": "0.19.
|
|
38
|
+
"@ttsc/unplugin": "0.19.3"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@expo/metro-config": "*",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"tinyglobby": "^0.2.16",
|
|
63
63
|
"tslib": "^2.8.1",
|
|
64
64
|
"typescript": "^7.0.2",
|
|
65
|
-
"ttsc": "0.19.
|
|
65
|
+
"ttsc": "0.19.3"
|
|
66
66
|
},
|
|
67
67
|
"repository": {
|
|
68
68
|
"type": "git",
|