@ttsc/metro 0.19.0 → 0.19.2

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.
@@ -0,0 +1,441 @@
1
+ import { isProjectWalkPath, collectProjectInputHashes, collectExternalInputHashes } from '@ttsc/unplugin/api';
2
+ import { randomBytes, createHash } from 'node:crypto';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+
6
+ /**
7
+ * Project fingerprint and reference-graph snapshot for `@ttsc/metro`.
8
+ *
9
+ * Metro's transform cache keys each file on its own content plus one static
10
+ * transformer key computed once per run (`getCacheKey`, called on the main
11
+ * process at `Transformer` construction). A ttsc transform's output can depend
12
+ * on inputs Metro never keys: other project sources reached through type-only
13
+ * edges, `node_modules` declarations, monorepo sibling sources, and the
14
+ * tsconfig `extends` ancestry. This module folds all of them into the static
15
+ * key so the cache key incorporates every input that can influence a
16
+ * transform's output:
17
+ *
18
+ * - **Project walk.** Every input file under the fingerprint roots (Metro's
19
+ * `projectRoot` plus the resolved tsconfig's directory when it lies outside),
20
+ * hashed with the exact walk universe the `@ttsc/unplugin` transform core
21
+ * validates its own cache against.
22
+ * - **Recorded out-of-walk inputs.** The transform core cannot walk files outside
23
+ * the roots or under ignored directories, but the host-owned reference graph
24
+ * (samchon/ttsc#718) reports them per transform. Workers record them into a
25
+ * snapshot under `node_modules/.cache/ttsc-metro`; the next run's
26
+ * `getCacheKey` re-hashes the recorded set.
27
+ *
28
+ * Snapshot layout: one main file carrying a random epoch id plus per-worker
29
+ * files with unique names, so concurrent workers never race a shared write.
30
+ * `withTtsc` (the single config process, before workers exist) compacts worker
31
+ * files into the main file. Readers take the union of every file, reading the
32
+ * worker files strictly before the main file: the compactor renames the merged
33
+ * main into place strictly before deleting a worker file, so a worker file that
34
+ * disappears mid-read is always already merged into the main the reader loads
35
+ * afterwards.
36
+ *
37
+ * Sound degradations, by design:
38
+ *
39
+ * - No readable snapshot (first run, wiped cache dir, unwritable filesystem)
40
+ * folds a random nonce: that run shares no cache entries with any other run.
41
+ * - A recreated snapshot carries a fresh epoch id, so it can never alias a key
42
+ * from an older epoch whose recorded set is unknown.
43
+ * - A plugin-declared volatile output (non-file inputs; unrepresentable in any
44
+ * file fingerprint) marks the snapshot volatile, which also folds a nonce
45
+ * until a later run records the volatile declaration gone.
46
+ * - A recorded input that disappears hashes as a stable `missing` marker, so
47
+ * deletion and reappearance both move the key.
48
+ */
49
+ /** Bumped when the snapshot JSON shape changes; mismatches read as corrupt. */
50
+ const SNAPSHOT_VERSION = 1;
51
+ /** Snapshot directory segments under the fingerprint base directory. */
52
+ const SNAPSHOT_DIRECTORY = ["node_modules", ".cache", "ttsc-metro"];
53
+ /** Main snapshot file name (epoch id + compacted recorded inputs). */
54
+ const MAIN_SNAPSHOT = "graph-inputs.json";
55
+ /** Worker snapshot file prefix; each worker appends a unique suffix. */
56
+ const WORKER_SNAPSHOT_PREFIX = "graph-inputs.worker-";
57
+ /**
58
+ * Resolve the base directory both fingerprint sides agree on: Metro's
59
+ * `projectRoot` when known (`withTtsc` reads it from the config, `getCacheKey`
60
+ * from Metro's cache-key options, the transformer from each file's transform
61
+ * options — all the same value in a real Metro run), else the working directory
62
+ * Metro was launched from.
63
+ */
64
+ function resolveFingerprintBase(projectRoot) {
65
+ return path.resolve(typeof projectRoot === "string" && projectRoot.length !== 0
66
+ ? projectRoot
67
+ : process.cwd());
68
+ }
69
+ /**
70
+ * The directories whose walk universes the fingerprint hashes: the base
71
+ * directory, plus the resolved tsconfig's directory when the tsconfig is not
72
+ * already inside the base walk (an explicit out-of-root `project`, or a
73
+ * monorepo-root tsconfig discovered above the app). Matching the transform
74
+ * core's own validation universe keeps the invariant simple: everything the
75
+ * core treats as an input is fingerprinted, either by a walk here or by the
76
+ * recorded out-of-walk snapshot.
77
+ */
78
+ function fingerprintRoots(base, explicitProject) {
79
+ const tsconfig = resolveProjectTsconfig(base, explicitProject);
80
+ if (isProjectWalkPath(base, tsconfig)) {
81
+ return [base];
82
+ }
83
+ return [base, path.dirname(tsconfig)];
84
+ }
85
+ /**
86
+ * Locate the tsconfig governing the project, mirroring the transform core's
87
+ * discovery: an explicit `project` resolves against the working directory;
88
+ * otherwise ancestor directories starting at `base` are searched for a
89
+ * `tsconfig.json`, falling back to `<base>/tsconfig.json`.
90
+ */
91
+ function resolveProjectTsconfig(base, explicitProject) {
92
+ if (explicitProject !== undefined && explicitProject.length !== 0) {
93
+ return path.isAbsolute(explicitProject)
94
+ ? explicitProject
95
+ : path.resolve(process.cwd(), explicitProject);
96
+ }
97
+ let current = base;
98
+ while (true) {
99
+ const candidate = path.join(current, "tsconfig.json");
100
+ if (fs.existsSync(candidate)) {
101
+ return candidate;
102
+ }
103
+ const parent = path.dirname(current);
104
+ if (parent === current) {
105
+ break;
106
+ }
107
+ current = parent;
108
+ }
109
+ return path.resolve(base, "tsconfig.json");
110
+ }
111
+ /**
112
+ * Compute the fingerprint `getCacheKey` folds into Metro's static transformer
113
+ * key. Never throws: any failure degrades to a nonce, which soundly disables
114
+ * cross-run cache reuse for this run instead of serving stale output.
115
+ */
116
+ function computeProjectFingerprint(props) {
117
+ try {
118
+ const base = resolveFingerprintBase(props.projectRoot);
119
+ const hash = createHash("sha256");
120
+ for (const root of fingerprintRoots(base, props.explicitProject)) {
121
+ hash.update(stableStringify(collectProjectInputHashes(root)));
122
+ }
123
+ const snapshot = readSnapshotState(base);
124
+ if (snapshot === undefined || snapshot.volatile) {
125
+ hash.update(nonce());
126
+ }
127
+ else {
128
+ hash.update(`snapshot:${snapshot.id}`);
129
+ hash.update(stableStringify(collectExternalInputHashes(snapshot.files)));
130
+ }
131
+ return hash.digest("hex");
132
+ }
133
+ catch {
134
+ return nonce();
135
+ }
136
+ }
137
+ /**
138
+ * A value no other run can reproduce. Folding it means this run's cache entries
139
+ * are written but never reused by later runs, and this run reuses nothing from
140
+ * earlier ones — the sound fallback whenever the recorded out-of-walk input set
141
+ * is unknown or unrepresentable.
142
+ */
143
+ function nonce() {
144
+ return `nonce:${randomBytes(32).toString("hex")}`;
145
+ }
146
+ /**
147
+ * Prepare the snapshot for a new run. Called from `withTtsc` in the single
148
+ * Metro config process, before any worker exists: creates the main snapshot
149
+ * (fresh epoch id) when missing or corrupt, compacts leftover worker files into
150
+ * it, and sweeps unparseable worker files plus crash-leftover temp files. An
151
+ * unparseable worker file's recordings are unrecoverable, so its removal mints
152
+ * a fresh epoch id — every key that might have depended on the lost recordings
153
+ * is soundly orphaned, and later runs stabilize instead of degrading to a nonce
154
+ * forever. Never throws — an unwritable cache directory leaves the snapshot
155
+ * unreadable and `getCacheKey` degrades to a nonce.
156
+ */
157
+ function prepareSnapshot(projectRoot) {
158
+ try {
159
+ const base = resolveFingerprintBase(projectRoot);
160
+ // A nonexistent base can never be a working Metro setup (Metro verifies
161
+ // the project root exists), so preparing a snapshot there would only
162
+ // materialize directory trees at arbitrary paths.
163
+ if (!fs.existsSync(base)) {
164
+ return;
165
+ }
166
+ const directory = snapshotDirectory(base);
167
+ fs.mkdirSync(directory, { recursive: true });
168
+ // Read the worker files strictly before the main file (see the module doc
169
+ // comment): a concurrent compactor deletes a worker file only after the
170
+ // merged main is renamed into place, so whatever this enumeration misses
171
+ // is already inside the main read below.
172
+ const workers = readWorkerFiles(directory);
173
+ const main = readMainDocument(directory);
174
+ const files = new Set(main?.files ?? []);
175
+ const volatile = workers.entries.length === 0
176
+ ? (main?.volatile ?? false)
177
+ : // Worker files carry the previous run's fresh observations, so they
178
+ // own the volatile verdict: a removed volatile declaration must be
179
+ // able to clear the sticky flag.
180
+ workers.entries.some((entry) => entry.volatile);
181
+ for (const entry of workers.entries) {
182
+ for (const file of entry.files) {
183
+ files.add(file);
184
+ }
185
+ }
186
+ writeSnapshotDocument(path.join(directory, MAIN_SNAPSHOT), {
187
+ files: [...files].sort(),
188
+ id: workers.corruptPaths.length === 0
189
+ ? (main?.id ?? randomBytes(16).toString("hex"))
190
+ : randomBytes(16).toString("hex"),
191
+ version: SNAPSHOT_VERSION,
192
+ volatile,
193
+ });
194
+ for (const file of [
195
+ ...workers.paths,
196
+ ...workers.corruptPaths,
197
+ ...listTemporaryFiles(directory),
198
+ ]) {
199
+ try {
200
+ fs.rmSync(file, { force: true });
201
+ }
202
+ catch {
203
+ // A locked worker file stays behind; readers union it, so nothing is
204
+ // lost, and the next compaction retries.
205
+ }
206
+ }
207
+ }
208
+ catch {
209
+ // Snapshot maintenance must never break the Metro config process.
210
+ }
211
+ }
212
+ /**
213
+ * Crash-leftover temp files from the atomic writer, swept at compaction. Only
214
+ * files older than a day qualify: a young temp file may belong to a live writer
215
+ * in a concurrently running Metro instance, and deleting it mid-write would
216
+ * silently drop that writer's recordings.
217
+ */
218
+ function listTemporaryFiles(directory) {
219
+ const horizon = Date.now() - 24 * 60 * 60 * 1000;
220
+ try {
221
+ return fs
222
+ .readdirSync(directory)
223
+ .filter((name) => name.endsWith(".tmp"))
224
+ .map((name) => path.join(directory, name))
225
+ .filter((file) => {
226
+ try {
227
+ return fs.statSync(file).mtimeMs < horizon;
228
+ }
229
+ catch {
230
+ return false;
231
+ }
232
+ });
233
+ }
234
+ catch {
235
+ return [];
236
+ }
237
+ }
238
+ /**
239
+ * Read the unioned snapshot state, or `undefined` when the main snapshot is
240
+ * missing or any snapshot file is corrupt (a torn or foreign write means the
241
+ * recorded set cannot be trusted, so the caller degrades to a nonce).
242
+ */
243
+ function readSnapshotState(base) {
244
+ const directory = snapshotDirectory(base);
245
+ // Worker files strictly before the main file — see the module doc comment.
246
+ const workers = readWorkerFiles(directory);
247
+ if (workers.corruptPaths.length !== 0) {
248
+ return undefined;
249
+ }
250
+ const main = readMainDocument(directory);
251
+ if (main === undefined || typeof main.id !== "string") {
252
+ return undefined;
253
+ }
254
+ const files = new Set(main.files);
255
+ let volatile = main.volatile;
256
+ for (const entry of workers.entries) {
257
+ for (const file of entry.files) {
258
+ files.add(file);
259
+ }
260
+ volatile ||= entry.volatile;
261
+ }
262
+ return { files: [...files].sort(), id: main.id, volatile };
263
+ }
264
+ /**
265
+ * Recorder held by each Metro worker. Collects the out-of-walk inputs derived
266
+ * for every transformed file (the plugin-reported dependencies unioned with the
267
+ * reference graph's reach, globals, and configs — delivered through the
268
+ * transform core's `addWatchFile` hook) plus any volatile declaration, and
269
+ * persists them to this worker's uniquely named snapshot file whenever the
270
+ * observed state grows. The unique name makes worker writes race-free;
271
+ * `withTtsc` compacts the files on the next run.
272
+ */
273
+ function createSnapshotRecorder() {
274
+ const suffix = `${process.pid.toString(36)}-${randomBytes(6).toString("hex")}`;
275
+ const states = new Map();
276
+ function stateFor(projectRoot, explicitProject) {
277
+ const base = resolveFingerprintBase(projectRoot);
278
+ let state = states.get(base);
279
+ if (state === undefined) {
280
+ state = {
281
+ dirty: false,
282
+ files: new Set(),
283
+ roots: fingerprintRoots(base, explicitProject),
284
+ volatile: false,
285
+ };
286
+ states.set(base, state);
287
+ }
288
+ return state;
289
+ }
290
+ function flush(base, state) {
291
+ if (!state.dirty) {
292
+ return;
293
+ }
294
+ try {
295
+ const directory = snapshotDirectory(base);
296
+ fs.mkdirSync(directory, { recursive: true });
297
+ writeSnapshotDocument(path.join(directory, `${WORKER_SNAPSHOT_PREFIX}${suffix}.json`), {
298
+ files: [...state.files].sort(),
299
+ version: SNAPSHOT_VERSION,
300
+ volatile: state.volatile,
301
+ });
302
+ // Cleared only on success so a transient write failure retries on the
303
+ // next recording instead of silently dropping the observed state.
304
+ state.dirty = false;
305
+ }
306
+ catch {
307
+ // An unwritable snapshot leaves the main snapshot unreadable or stale;
308
+ // getCacheKey degrades to a nonce rather than serving stale output.
309
+ }
310
+ }
311
+ return {
312
+ record(props) {
313
+ const base = resolveFingerprintBase(props.projectRoot);
314
+ const state = stateFor(props.projectRoot, props.explicitProject);
315
+ const input = path.resolve(props.input);
316
+ if (state.files.has(input) ||
317
+ state.roots.some((root) => isProjectWalkPath(root, input))) {
318
+ return;
319
+ }
320
+ state.files.add(input);
321
+ state.dirty = true;
322
+ flush(base, state);
323
+ },
324
+ recordVolatile(props) {
325
+ const base = resolveFingerprintBase(props.projectRoot);
326
+ const state = stateFor(props.projectRoot, props.explicitProject);
327
+ if (state.volatile) {
328
+ return;
329
+ }
330
+ state.volatile = true;
331
+ state.dirty = true;
332
+ flush(base, state);
333
+ },
334
+ };
335
+ }
336
+ function snapshotDirectory(base) {
337
+ return path.join(base, ...SNAPSHOT_DIRECTORY);
338
+ }
339
+ /**
340
+ * Read every worker snapshot file in `directory`. A file that disappears
341
+ * mid-read was compacted (merged into the main snapshot first) and is skipped;
342
+ * a file that exists but does not parse is reported in `corruptPaths` so
343
+ * readers can degrade to a nonce and the compactor can sweep it.
344
+ */
345
+ function readWorkerFiles(directory) {
346
+ let names;
347
+ try {
348
+ names = fs.readdirSync(directory);
349
+ }
350
+ catch {
351
+ return { corruptPaths: [], entries: [], paths: [] };
352
+ }
353
+ const entries = [];
354
+ const paths = [];
355
+ const corruptPaths = [];
356
+ for (const name of names) {
357
+ if (!name.startsWith(WORKER_SNAPSHOT_PREFIX) || !name.endsWith(".json")) {
358
+ continue;
359
+ }
360
+ const file = path.join(directory, name);
361
+ let text;
362
+ try {
363
+ text = fs.readFileSync(file, "utf8");
364
+ }
365
+ catch {
366
+ continue;
367
+ }
368
+ const parsed = parseSnapshotDocument(text);
369
+ if (parsed === undefined) {
370
+ corruptPaths.push(file);
371
+ continue;
372
+ }
373
+ entries.push(parsed);
374
+ paths.push(file);
375
+ }
376
+ return { corruptPaths, entries, paths };
377
+ }
378
+ function readMainDocument(directory) {
379
+ let text;
380
+ try {
381
+ text = fs.readFileSync(path.join(directory, MAIN_SNAPSHOT), "utf8");
382
+ }
383
+ catch {
384
+ return undefined;
385
+ }
386
+ return parseSnapshotDocument(text);
387
+ }
388
+ function parseSnapshotDocument(text) {
389
+ let value;
390
+ try {
391
+ value = JSON.parse(text);
392
+ }
393
+ catch {
394
+ return undefined;
395
+ }
396
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
397
+ return undefined;
398
+ }
399
+ const document = value;
400
+ if (document.version !== SNAPSHOT_VERSION || !Array.isArray(document.files)) {
401
+ return undefined;
402
+ }
403
+ return {
404
+ files: document.files.filter((entry) => typeof entry === "string"),
405
+ ...(typeof document.id === "string" ? { id: document.id } : {}),
406
+ version: SNAPSHOT_VERSION,
407
+ volatile: document.volatile === true,
408
+ };
409
+ }
410
+ /** Write a snapshot document atomically (unique temp file, then rename). */
411
+ function writeSnapshotDocument(file, document) {
412
+ const temp = `${file}.${randomBytes(6).toString("hex")}.tmp`;
413
+ fs.writeFileSync(temp, JSON.stringify(document), "utf8");
414
+ try {
415
+ fs.renameSync(temp, file);
416
+ }
417
+ catch (error) {
418
+ fs.rmSync(temp, { force: true });
419
+ throw error;
420
+ }
421
+ }
422
+ /**
423
+ * JSON-serialise with object keys sorted recursively, so two semantically equal
424
+ * records always hash to the same fingerprint regardless of property order.
425
+ * Shared with the transformer's option digest.
426
+ */
427
+ function stableStringify(value) {
428
+ if (Array.isArray(value)) {
429
+ return `[${value.map(stableStringify).join(",")}]`;
430
+ }
431
+ if (value !== null && typeof value === "object") {
432
+ return `{${Object.entries(value)
433
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
434
+ .map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`)
435
+ .join(",")}}`;
436
+ }
437
+ return JSON.stringify(value);
438
+ }
439
+
440
+ export { computeProjectFingerprint, createSnapshotRecorder, fingerprintRoots, prepareSnapshot, readSnapshotState, resolveFingerprintBase, stableStringify };
441
+ //# sourceMappingURL=fingerprint.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint.mjs","sources":["../../src/core/fingerprint.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
package/lib/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  var path = require('node:path');
4
4
  var node_url = require('node:url');
5
+ var fingerprint = require('./core/fingerprint.js');
5
6
  var options = require('./core/options.js');
6
7
 
7
8
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
@@ -49,6 +50,11 @@ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentS
49
50
  */
50
51
  function withTtsc(config, options$1 = {}) {
51
52
  process.env[options.ENV_KEY] = options.serializeOptions(options$1);
53
+ // Prepare the reference-graph snapshot backing the transformer's cache-key
54
+ // fingerprint (see `core/fingerprint.ts`). This runs in the single Metro
55
+ // config process before any worker exists, so it is the race-free moment to
56
+ // mint the snapshot epoch and compact the previous run's worker files.
57
+ fingerprint.prepareSnapshot(typeof config.projectRoot === "string" ? config.projectRoot : undefined);
52
58
  return {
53
59
  ...config,
54
60
  transformer: {
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":[null],"names":["options","ENV_KEY","serializeOptions","join","dirname","fileURLToPath"],"mappings":";;;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BG;AAyBH;;;;;;;;;;;;AAYG;SACa,QAAQ,CACtB,MAAS,EACTA,YAA4B,EAAE,EAAA;IAE9B,OAAO,CAAC,GAAG,CAACC,eAAO,CAAC,GAAGC,wBAAgB,CAACF,SAAO,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,OAAOG,SAAI,CAACC,YAAO,CAACC,sBAAa,CAAC,0PAAe,CAAC,CAAC,EAAE,gBAAgB,CAAC;AACxE;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":[null],"names":["options","ENV_KEY","serializeOptions","prepareSnapshot","join","dirname","fileURLToPath"],"mappings":";;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BG;AA0BH;;;;;;;;;;;;AAYG;SACa,QAAQ,CACtB,MAAS,EACTA,YAA4B,EAAE,EAAA;IAE9B,OAAO,CAAC,GAAG,CAACC,eAAO,CAAC,GAAGC,wBAAgB,CAACF,SAAO,CAAC;;;;;AAKhD,IAAAG,2BAAe,CACb,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,GAAG,MAAM,CAAC,WAAW,GAAG,SAAS,CACxE;IACD,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,OAAOC,SAAI,CAACC,YAAO,CAACC,sBAAa,CAAC,0PAAe,CAAC,CAAC,EAAE,gBAAgB,CAAC;AACxE;;;;"}
package/lib/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import { join, dirname } from 'node:path';
2
2
  import { fileURLToPath } from 'node:url';
3
+ import { prepareSnapshot } from './core/fingerprint.mjs';
3
4
  import { ENV_KEY, serializeOptions } from './core/options.mjs';
4
5
 
5
6
  /**
@@ -46,6 +47,11 @@ import { ENV_KEY, serializeOptions } from './core/options.mjs';
46
47
  */
47
48
  function withTtsc(config, options = {}) {
48
49
  process.env[ENV_KEY] = serializeOptions(options);
50
+ // Prepare the reference-graph snapshot backing the transformer's cache-key
51
+ // fingerprint (see `core/fingerprint.ts`). This runs in the single Metro
52
+ // config process before any worker exists, so it is the race-free moment to
53
+ // mint the snapshot epoch and compact the previous run's worker files.
54
+ prepareSnapshot(typeof config.projectRoot === "string" ? config.projectRoot : undefined);
49
55
  return {
50
56
  ...config,
51
57
  transformer: {
package/lib/index.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BG;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;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BG;AA0BH;;;;;;;;;;;;AAYG;SACa,QAAQ,CACtB,MAAS,EACT,UAA4B,EAAE,EAAA;IAE9B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC;;;;;AAKhD,IAAA,eAAe,CACb,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,GAAG,MAAM,CAAC,WAAW,GAAG,SAAS,CACxE;IACD,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;;;;"}
@@ -32,15 +32,25 @@ export declare function transform(params: {
32
32
  /**
33
33
  * Metro transform-cache key.
34
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.
35
+ * Metro calls this once per run (dev-server start or cold `metro bundle`), on
36
+ * the main process, and folds the result into every file's per-content cache
37
+ * key. It must therefore incorporate every input that can influence a
38
+ * transform's output beyond the file's own content:
39
+ *
40
+ * - The transformer identity: package version + resolved options + the upstream
41
+ * transformer's own key (forwarded Metro's args, e.g. `projectRoot`, so a
42
+ * `babel.config.js` change still busts the cache);
43
+ * - The project fingerprint (see `core/fingerprint.ts`): every input file under
44
+ * the project walk (tsconfig, plugin configs, type-only siblings) plus the
45
+ * recorded out-of-walk reference-graph members from previous transforms
46
+ * (`node_modules` declarations, monorepo sibling sources, out-of-root config
47
+ * ancestry).
48
+ *
49
+ * A change to any fingerprinted input re-keys every transformed file —
50
+ * project-level granularity, forced by Metro's single static key — replacing
51
+ * the former manual `--reset-cache` step. Resolving the upstream is
52
+ * deliberately non-fatal here: a missing peer must not crash cache-key
53
+ * computation. See the README "Caveats" and samchon/ttsc#721.
44
54
  */
45
55
  export declare function getCacheKey(...args: unknown[]): string;
46
56
  /**