@ttsc/unplugin 0.28.2 → 0.28.4

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.
Files changed (46) hide show
  1. package/README.md +71 -7
  2. package/lib/api.js +3 -0
  3. package/lib/api.js.map +1 -1
  4. package/lib/api.mjs +1 -0
  5. package/lib/api.mjs.map +1 -1
  6. package/lib/core/index.d.cts +17 -6
  7. package/lib/core/index.d.mts +17 -6
  8. package/lib/core/index.d.ts +17 -6
  9. package/lib/core/index.js +131 -18
  10. package/lib/core/index.js.map +1 -1
  11. package/lib/core/index.mjs +130 -19
  12. package/lib/core/index.mjs.map +1 -1
  13. package/lib/core/transform.d.cts +116 -29
  14. package/lib/core/transform.d.mts +116 -29
  15. package/lib/core/transform.d.ts +116 -29
  16. package/lib/core/transform.js +1502 -222
  17. package/lib/core/transform.js.map +1 -1
  18. package/lib/core/transform.mjs +1503 -223
  19. package/lib/core/transform.mjs.map +1 -1
  20. package/lib/core/tsconfigPaths.d.cts +61 -0
  21. package/lib/core/tsconfigPaths.d.mts +61 -0
  22. package/lib/core/tsconfigPaths.d.ts +61 -0
  23. package/lib/core/tsconfigPaths.js +190 -7
  24. package/lib/core/tsconfigPaths.js.map +1 -1
  25. package/lib/core/tsconfigPaths.mjs +188 -8
  26. package/lib/core/tsconfigPaths.mjs.map +1 -1
  27. package/lib/next.d.cts +27 -10
  28. package/lib/next.d.mts +27 -10
  29. package/lib/next.d.ts +27 -10
  30. package/lib/next.js +229 -8
  31. package/lib/next.js.map +1 -1
  32. package/lib/next.mjs +229 -8
  33. package/lib/next.mjs.map +1 -1
  34. package/lib/turbopack.d.cts +5 -4
  35. package/lib/turbopack.d.mts +5 -4
  36. package/lib/turbopack.d.ts +5 -4
  37. package/lib/turbopack.js +13 -7
  38. package/lib/turbopack.js.map +1 -1
  39. package/lib/turbopack.mjs +14 -8
  40. package/lib/turbopack.mjs.map +1 -1
  41. package/package.json +3 -3
  42. package/src/core/index.ts +136 -18
  43. package/src/core/transform.ts +2070 -254
  44. package/src/core/tsconfigPaths.ts +254 -8
  45. package/src/next.ts +262 -10
  46. package/src/turbopack.ts +13 -9
@@ -2,15 +2,20 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { createUnplugin } from 'unplugin';
4
4
  import { resolveOptions } from './options.mjs';
5
- import { createTtscTransformCache, stripQuery, transformTtsc, beginTtscTransformBuild, isDeclarationFile, resetTtscTransformCache } from './transform.mjs';
5
+ import { createTtscTransformCache, stripQuery, transformTtsc, beginTtscTransformBuild, resetTtscTransformCache, isDeclarationFile } from './transform.mjs';
6
6
  export { collectExternalInputHashes, collectProjectInputHashes, isProjectWalkPath } from './transform.mjs';
7
7
  import { createViteServeMissingInputWatch } from './viteServe.mjs';
8
+ export { mergeMembershipPolicyOverlay, readProjectMembershipPolicy } from './tsconfigPaths.mjs';
8
9
 
9
10
  const name = "ttsc-unplugin";
10
11
  /**
11
- * Matches any TypeScript or JavaScript source extension (.ts, .tsx, .mts, .cts,
12
- * etc.). Shared with the Bun adapter (`bun.ts`) so the filter is defined once
13
- * and both adapters stay in sync.
12
+ * Matches the TypeScript source extensions the ttsc transform handles: `.ts`,
13
+ * `.tsx`, `.mts`, `.cts` and their `x` forms. JavaScript is deliberately not
14
+ * among them, so a `.js` module reaches no adapter's transform.
15
+ *
16
+ * Shared with the Bun adapter (`bun.ts`) and the standalone Turbopack loader
17
+ * (`turbopack.ts`) through {@link isTransformTarget}, so the filter is defined
18
+ * once and every adapter answers the same way.
14
19
  */
15
20
  const sourceFilePattern = /\.[cm]?tsx?$/;
16
21
  /** Matches any path segment that is a `node_modules` directory (cross-platform). */
@@ -24,13 +29,15 @@ const virtualModulePattern = /\0/;
24
29
  * Unplugin factory that wires the ttsc transform pipeline into any supported
25
30
  * bundler (Vite, Rollup, Rolldown, webpack, Rspack, esbuild, Farm).
26
31
  *
27
- * The factory resolves raw options once, creates a per-build transform cache,
28
- * and captures Vite alias configuration via the `vite.configResolved` hook so
29
- * that path aliases are forwarded to the generated tsconfig overlay. Real build
30
- * lifecycles use a per-build cache; a watching Vite development server keeps
31
- * persistent validation because its one `buildStart` spans later HMR edits,
32
- * while a dev server configured without a watcher takes the build-scoped path
33
- * with them, having declared it will observe no edit at all.
32
+ * The factory resolves raw options once, creates one transform cache for the
33
+ * whole plugin instance, and captures Vite alias configuration via the
34
+ * `vite.configResolved` hook so that path aliases are forwarded to the
35
+ * generated tsconfig overlay. A host with a real `buildStart` opens a delivery
36
+ * pass there and keeps its generation across passes; a watching Vite
37
+ * development server keeps persistent validation instead, because its one
38
+ * `buildStart` spans later HMR edits and so cannot mark a pass, while a dev
39
+ * server configured without a watcher takes the pass lifecycle with them,
40
+ * having declared it will observe no edit at all.
34
41
  */
35
42
  const unpluginFactory = (rawOptions = {}) => {
36
43
  const options = resolveOptions(rawOptions);
@@ -39,6 +46,17 @@ const unpluginFactory = (rawOptions = {}) => {
39
46
  let aliases;
40
47
  let viteCommand;
41
48
  let viteWatching = true;
49
+ // Whether a build-mode session is driven by Rollup's watcher. `build.watch`
50
+ // is `null` for an ordinary build and an object under `--watch`, which is the
51
+ // axis the disposal boundary actually turns on: only a watching build repeats
52
+ // its build phase, and only a watching build ends at `closeWatcher`.
53
+ let viteBuildWatching = false;
54
+ // A restart can start the replacement plugin container before closing the
55
+ // old one, and Vite calls buildEnd even for a container that never started.
56
+ // Track the stable per-container PluginContext identity so that unstarted
57
+ // old containers cannot dispose a replacement's freshly initialized cache.
58
+ let viteBuildOwners = new WeakSet();
59
+ let viteBuildLifecycles = 0;
42
60
  return {
43
61
  name,
44
62
  enforce: "pre",
@@ -60,6 +78,13 @@ const unpluginFactory = (rawOptions = {}) => {
60
78
  // (samchon/ttsc#1246).
61
79
  viteWatching =
62
80
  config.server?.watch !== null;
81
+ // Read on the same principle as the line above, from the half of the
82
+ // config that governs a build rather than a server. The comparison is
83
+ // loose where the server's is strict because the two defaults differ:
84
+ // `server.watch` is an object unless explicitly `null`, while
85
+ // `build.watch` is absent or `null` unless `--watch` supplies one.
86
+ viteBuildWatching =
87
+ config.build?.watch != null;
63
88
  },
64
89
  // Vite serve funnels every transform-context `addWatchFile()` into the
65
90
  // module's added-import graph (`_addedImports`), which import-analysis
@@ -70,13 +95,90 @@ const unpluginFactory = (rawOptions = {}) => {
70
95
  configureServer(server) {
71
96
  missingInputs.attach(server);
72
97
  },
73
- // Vite calls buildEnd when the dev server (or build) closes; drop every
74
- // poller so a stopped server leaks no watch state.
98
+ // Vite calls buildEnd when the dev server closes, and Rollup calls it at
99
+ // the end of every build phase; drop every poller and, once the last
100
+ // overlapping container has closed, every generation-owned filesystem
101
+ // tracker as well.
102
+ //
103
+ // Disposing here is right wherever the end of a build phase is also the
104
+ // end of the session: a dev server, and an ordinary one-shot build. It is
105
+ // wrong for a watching build, whose watcher repeats build phases, so it
106
+ // means "this pass ended" there — measured as
107
+ // `buildStart -> buildEnd -> ... -> buildStart -> buildEnd` across
108
+ // `vite build --watch` rebuilds. Disposing on that repeat discarded the
109
+ // generation once per rebuild independently of the `buildStart` clear, so
110
+ // fixing one of the two sites alone left this host recompiling the whole
111
+ // project per edit (samchon/ttsc#1301). The watching build hands its
112
+ // teardown to `closeWatcher` below instead.
75
113
  buildEnd() {
76
114
  missingInputs.dispose();
115
+ if (viteBuildOwners.delete(this)) {
116
+ viteBuildLifecycles -= 1;
117
+ }
118
+ if (viteBuildLifecycles === 0 &&
119
+ (viteCommand === "serve" || !viteBuildWatching)) {
120
+ resetTtscTransformCache(transformCache);
121
+ }
122
+ },
123
+ // The watching build's real teardown, and the only hook in a
124
+ // `vite build --watch` trace that fires exactly once: buildEnd,
125
+ // writeBundle and closeBundle all repeat per rebuild there. A generation
126
+ // retained across passes owns directory watchers, so this is where they
127
+ // are released. Vite's dev server drives no Rollup watcher and an
128
+ // ordinary build closes its bundle instead, so neither reaches here;
129
+ // a host that fired both would simply reset twice, which is idempotent.
130
+ //
131
+ // The container bookkeeping is cleared with the cache, and the owner set
132
+ // is replaced rather than merely zeroed alongside it. A watcher closed
133
+ // mid-rebuild leaves a container still registered, and its later
134
+ // `buildEnd` would then decrement a counter that is already zero and
135
+ // strand it below zero, after which the disposal above could never fire
136
+ // again for this plugin instance.
137
+ closeWatcher() {
138
+ viteBuildOwners = new WeakSet();
139
+ viteBuildLifecycles = 0;
140
+ resetTtscTransformCache(transformCache);
141
+ },
142
+ },
143
+ // Rollup and Rolldown carry none of the Vite block's hooks, so before this
144
+ // they had no disposal site at all. They get both halves of the same
145
+ // boundary: a watching session ends at `closeWatcher`, and a one-shot build
146
+ // ends when its build phase does. `this.meta.watchMode` separates the two
147
+ // there, the way `build.watch` does for Vite, so a one-shot build is not
148
+ // left without a site the way `vite build` was (samchon/ttsc#1301).
149
+ // unplugin merges each of these blocks only into its own adapter, so the
150
+ // Vite adapter never receives them.
151
+ //
152
+ // A `buildEnd` at the top level instead of inside a block would be a
153
+ // regression rather than a shorthand: unplugin forwards a top-level one to
154
+ // esbuild's `onEnd` and to webpack's and Rspack's `hooks.emit`, each of
155
+ // which repeats per rebuild, so those hosts would start discarding a valid
156
+ // generation on every edit, which is samchon/ttsc#1300 again.
157
+ rollup: {
158
+ buildEnd() {
159
+ if (this.meta?.watchMode !== true) {
160
+ resetTtscTransformCache(transformCache);
161
+ }
162
+ },
163
+ closeWatcher() {
164
+ resetTtscTransformCache(transformCache);
165
+ },
166
+ },
167
+ rolldown: {
168
+ buildEnd() {
169
+ if (this.meta?.watchMode !== true) {
170
+ resetTtscTransformCache(transformCache);
171
+ }
172
+ },
173
+ closeWatcher() {
174
+ resetTtscTransformCache(transformCache);
77
175
  },
78
176
  },
79
177
  buildStart() {
178
+ if (viteCommand !== undefined && !viteBuildOwners.has(this)) {
179
+ viteBuildOwners.add(this);
180
+ viteBuildLifecycles += 1;
181
+ }
80
182
  // Persistent validation exists for a session that spans edits it can
81
183
  // observe, and a dev server told to open no watcher is not one:
82
184
  // `server.watch: null` leaves Vite with no change channel at all, so no
@@ -84,14 +186,18 @@ const unpluginFactory = (rawOptions = {}) => {
84
186
  // no client is hot-updated. Validating each delivery there does not buy
85
187
  // freshness, it buys incoherence — modules delivered before an edit and
86
188
  // after it would come from two different compilations of one program —
87
- // while costing a full derived-input proof per delivered module. The
88
- // build-scoped lifecycle settles each module's first delivery against the
89
- // generation the session started from, exactly as a build does, and still
189
+ // while costing a full derived-input proof per delivered module. The pass
190
+ // lifecycle settles each module's first delivery against the generation
191
+ // the session started from, exactly as a build does, and still
90
192
  // revalidates a module this session already delivered. A one-shot suite
91
193
  // configures precisely this server (`vitest --run` sets `server.watch =
92
194
  // null`) and is the workload behind samchon/ttsc#970
93
195
  // (samchon/ttsc#1260). The neighbouring watch-registration decision reads
94
196
  // the same two properties for the same reason.
197
+ //
198
+ // Opening a pass no longer discards the generation, so the `else` branch
199
+ // is what every host with a repeating `buildStart` takes without paying a
200
+ // whole-project transform per rebuild (samchon/ttsc#1300).
95
201
  if (viteCommand === "serve" && viteWatching) {
96
202
  resetTtscTransformCache(transformCache);
97
203
  }
@@ -157,10 +263,15 @@ const unpluginFactory = (rawOptions = {}) => {
157
263
  };
158
264
  const unplugin = createUnplugin(unpluginFactory);
159
265
  /**
160
- * Returns `true` when the module id refers to a real TypeScript/JavaScript
161
- * source file that should be processed by the ttsc transform.
266
+ * Returns `true` when the module id refers to a real TypeScript source file
267
+ * that should be processed by the ttsc transform.
268
+ *
269
+ * TypeScript only. {@link sourceFilePattern} deliberately excludes JavaScript,
270
+ * so a `.js` module reaches no adapter's transform, and this docstring used to
271
+ * say otherwise while the pattern it is built from said the truth
272
+ * (samchon/ttsc#1309).
162
273
  *
163
- * Excluded ids: virtual modules (NUL prefix), `.d.ts` declaration files, and
274
+ * Also excluded: virtual modules (NUL prefix), `.d.ts` declaration files, and
164
275
  * anything inside `node_modules`.
165
276
  */
166
277
  function isTransformTarget(id) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../src/core/index.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../../src/core/index.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ import type { ITtscCompilerTransformation } from "ttsc";
3
3
  import { type FilesystemPathIdentityContext, type FilesystemPathIdentityOperations } from "ttsc/path-identity";
4
4
  import type { TransformResult } from "unplugin";
5
5
  import type { ResolvedTtscUnpluginOptions } from "./options.cjs";
6
+ import { type ITtscProjectMembershipPolicy } from "./tsconfigPaths.cjs";
6
7
  /**
7
8
  * The normalised transform result type that this module produces.
8
9
  *
@@ -11,26 +12,39 @@ import type { ResolvedTtscUnpluginOptions } from "./options.cjs";
11
12
  * `undefined`.
12
13
  */
13
14
  export type TtscTransformResult = Exclude<TransformResult, string | null | undefined>;
14
- /**
15
- * Normalised alias entry used when building the `paths` overlay for the
16
- * generated tsconfig. Derived from either a Vite array alias or a webpack/
17
- * Rspack object alias.
18
- */
19
- export interface TtscTransformAlias {
20
- /** The alias key (module specifier prefix). */
21
- find: string;
22
- /** Absolute or cwd-relative path that the alias points to. */
23
- replacement: string;
24
- }
25
- /** One directory's cheap project-membership identity at generation time. */
15
+ /** One directory's project-membership identity at generation time. */
26
16
  interface TtscProjectDirectorySnapshot {
27
17
  /** Absolute directory spelling used by the project walk. */
28
18
  path: string;
29
- /** Metadata signature that changes when its immediate membership changes. */
19
+ /**
20
+ * Whether this directory's subtree can hold a program input.
21
+ *
22
+ * A directory that cannot is still walked and still watched, so a source
23
+ * appearing in it later is noticed, but it takes no part in the membership
24
+ * comparison. That is what lets a bundler create its output directory and
25
+ * fill it without voiding a generation no compiler input touched, for any
26
+ * output directory rather than for fifteen names (samchon/ttsc#1307).
27
+ */
28
+ relevant: boolean;
29
+ /**
30
+ * Digest of the entries the walk itself considers: every immediate child the
31
+ * ignore list does not drop, with its kind.
32
+ *
33
+ * Deliberately not the directory's own metadata. A directory's stamp moves
34
+ * whenever _any_ entry is added or removed, including the ones the walk
35
+ * exists to ignore, so a bundler emitting into `dist/` — or merely creating
36
+ * that directory for the first time — moved the project root's stamp and
37
+ * voided a generation that no compiler input had touched. The ignore list
38
+ * only protects the generation if the membership proof honours it too.
39
+ */
30
40
  signature: string;
31
41
  }
32
42
  /** Generation-scoped directory watchers used to detect membership changes. */
33
43
  interface TtscProjectMutationTracker {
44
+ /** Absolute paths named by generation-time mutation events. */
45
+ changes: Set<string>;
46
+ /** Whether additional event paths were discarded after the witness bound. */
47
+ changesOmitted: boolean;
34
48
  close: () => void;
35
49
  /**
36
50
  * Absolute spellings whose creation, change or removal this tracker would
@@ -113,6 +127,28 @@ export interface TtscCachedProjectTransform {
113
127
  * transform.
114
128
  */
115
129
  inputHashes: Record<string, string>;
130
+ /**
131
+ * What the resolved configuration admitted into this generation's program.
132
+ *
133
+ * Recorded per generation rather than read per validation because it is a
134
+ * property of the configuration the compile ran under, so a later delivery
135
+ * must judge membership by the same rule the compile did. A tsconfig edit
136
+ * that changes the rule also changes a declared input, which replaces the
137
+ * generation and its policy together.
138
+ */
139
+ membershipPolicy: ITtscProjectMembershipPolicy;
140
+ /**
141
+ * Files already reported as absent from the program, and the pass that
142
+ * reporting belongs to, so the notice is one per file per pass rather than
143
+ * one per delivery.
144
+ */
145
+ missingOutputReported?: Set<string>;
146
+ missingOutputEpoch?: number;
147
+ /**
148
+ * The project config this generation compiled, so a module the program does
149
+ * not contain can be told which program that was.
150
+ */
151
+ tsconfig: string;
116
152
  /**
117
153
  * Metadata signature of each {@link inputHashes} entry whose hash was proven
118
154
  * against an unracing read of the file on disk, in a tick the observed
@@ -124,6 +160,13 @@ export interface TtscCachedProjectTransform {
124
160
  * disk bytes against the recorded hash, and may record a signature then.
125
161
  */
126
162
  inputSignatures?: Record<string, string>;
163
+ /**
164
+ * Raw source hash of every readable key in the transform output, keyed by
165
+ * filesystem identity. Unlike {@link inputHashes}, this includes source
166
+ * outputs outside the project walk without adding arbitrary output keys to
167
+ * the complete project snapshot.
168
+ */
169
+ sourceHashes?: Record<string, string>;
127
170
  /** Metadata snapshot of every directory in the stable generation walk. */
128
171
  projectDirectories?: TtscProjectDirectorySnapshot[];
129
172
  /** Live notification state for universal host-input changes. */
@@ -168,19 +211,50 @@ export interface TtscCachedProjectTransform {
168
211
  projectRoot: string;
169
212
  /** Raw compiler output returned by {@link TtscCompiler.transform}. */
170
213
  result: ITtscCompilerTransformation;
214
+ /**
215
+ * The delivery epoch this generation is currently settled against, or
216
+ * `undefined` for a generation no epoch has proven.
217
+ *
218
+ * Set when the generation is compiled, and again whenever a later epoch's
219
+ * first delivery proves the whole generation still matches the filesystem.
220
+ * While it equals the cache's current epoch, each module's first delivery is
221
+ * settled by the supplied source alone, exactly as it was when every pass
222
+ * compiled its own generation (samchon/ttsc#1300).
223
+ */
224
+ deliveryEpoch?: number;
225
+ /**
226
+ * Whether this generation's non-error diagnostics have been surfaced at all,
227
+ * and the epoch they were last surfaced in.
228
+ *
229
+ * The diagnostics describe one compile of one program, so they belong to the
230
+ * generation rather than to a delivery; a pass that reuses a retained
231
+ * generation still surfaces them once, because a build's warnings are part of
232
+ * what that build reports (samchon/ttsc#1304). The two fields are separate so
233
+ * a persistent host, whose epoch is `undefined`, still reports the first
234
+ * time.
235
+ */
236
+ diagnosticsReported?: boolean;
237
+ diagnosticsEpoch?: number;
171
238
  /**
172
239
  * Files already delivered from this generation, keyed by filesystem identity.
173
- * Build-scoped caches use this to skip persistent validation only for a
174
- * module's first delivery inside the current build.
240
+ * A cache with a delivery epoch uses this to skip persistent validation only
241
+ * for a module's first delivery inside the current pass; the set is cleared
242
+ * whenever a new epoch's gate re-proves the generation.
175
243
  */
176
244
  servedFiles?: Set<string>;
245
+ /**
246
+ * Absolute path of the adapter-owned scratch directory used for this
247
+ * generation. It is disposed after compilation, so none of its compiler,
248
+ * resolver, or plugin artifacts can be a persistent cache or watch input.
249
+ */
250
+ scratchDirectory?: string;
177
251
  /**
178
252
  * Absolute path of the generated temp-dir tsconfig this compile ran against,
179
253
  * when an alias/compiler-options overlay required one. The compiler reports
180
254
  * it in the envelope's `graph.configs` chain, but it is disposed right after
181
255
  * the compile, so registering it as a watch input would invalidate every
182
- * bundler cache snapshot on the next build; watch derivation must skip
183
- * exactly this path.
256
+ * bundler cache snapshot on the next build; watch derivation must skip this
257
+ * path. {@link scratchDirectory} owns the wider disposable-input bound.
184
258
  */
185
259
  temporaryTsconfig?: string;
186
260
  }
@@ -234,20 +308,31 @@ export declare function normalizeHostInputName(name: string, caseSensitive: bool
234
308
  /** Create an empty persistent transform cache with isolated filesystem reads. */
235
309
  export declare function createTtscTransformCache(operations?: Partial<TtscTransformFilesystemOperations>): TtscTransformCache;
236
310
  /**
237
- * Start a host build, clearing its prior generation and enabling constant-time
238
- * first delivery for modules compiled during this build.
311
+ * Open a new delivery pass, enabling constant-time first delivery for every
312
+ * module this pass asks for.
313
+ *
314
+ * This deliberately retains the cached generation. The pass boundary is a
315
+ * statement about _deliveries_ — each module is requested at most once inside
316
+ * it — not about whether the compiled program is still correct, which the
317
+ * generation's own recorded snapshot answers and which
318
+ * {@link matchesCachedSource} proves once at the pass's first delivery. Clearing
319
+ * here instead made a host whose `buildStart` repeats recompile the whole
320
+ * project on every rebuild even when no compiler input had changed
321
+ * (samchon/ttsc#1300). Use {@link resetTtscTransformCache} to actually discard a
322
+ * generation and its watchers.
239
323
  *
240
- * Hosts without a guaranteed build-start callback use persistent validation
241
- * unless they have another immutable lifecycle. Bun runtime setup, for example,
324
+ * Hosts without a guaranteed pass boundary use persistent validation unless
325
+ * they have another immutable lifecycle. Bun runtime setup, for example,
242
326
  * defines one process-scoped module-loading session.
243
327
  */
244
328
  export declare function beginTtscTransformBuild(cache: TtscTransformCache): void;
245
329
  /**
246
- * Clear a cache and return it to persistent validation mode.
330
+ * Discard every generation, dispose its watchers, and return the cache to
331
+ * persistent validation mode.
247
332
  *
248
- * This is distinct from {@link beginTtscTransformBuild}: hosts such as Vite's
249
- * development server may invoke `buildStart` only once for a process that spans
250
- * many edits, so that callback cannot authorize build-scoped shortcuts.
333
+ * This is the unconditional lifecycle boundary, and it is distinct from
334
+ * {@link beginTtscTransformBuild}: a pass ending is not a reason to throw a
335
+ * proven compile away, while a session ending is.
251
336
  */
252
337
  export declare function resetTtscTransformCache(cache: TtscTransformCache): void;
253
338
  /**
@@ -365,8 +450,10 @@ interface TtscHostInputValidation {
365
450
  */
366
451
  export declare function stripQuery(id: string): string;
367
452
  /**
368
- * Returns `true` for TypeScript declaration files (`.d.ts`, `.d.mts`,
369
- * `.d.cts`).
453
+ * Returns `true` for every declaration-file spelling TypeScript-Go accepts.
454
+ * Besides the standard `.d.ts`, `.d.mts`, and `.d.cts` forms, TypeScript-Go
455
+ * treats an arbitrary-extension source such as `styles.d.css.ts` as a
456
+ * declaration file too.
370
457
  */
371
458
  export declare function isDeclarationFile(id: string): boolean;
372
459
  /**
@@ -383,7 +470,7 @@ export declare function createTransformResult(source: string, code: string): Tts
383
470
  * slash path. Exported so hosts without a per-build boundary (`@ttsc/metro`)
384
471
  * can fold the identical input universe into their own cache fingerprints.
385
472
  */
386
- export declare function collectProjectInputHashes(projectRoot: string, identities?: FilesystemPathIdentityContext, filesystem?: TtscTransformFilesystemOperations): Record<string, string>;
473
+ export declare function collectProjectInputHashes(projectRoot: string, identities?: FilesystemPathIdentityContext, filesystem?: TtscTransformFilesystemOperations, policy?: ITtscProjectMembershipPolicy): Record<string, string>;
387
474
  /**
388
475
  * Report whether an absolute `file` belongs to the project walk universe of
389
476
  * `root`: it lies under `root`, every component exists without traversing a
@@ -393,7 +480,7 @@ export declare function collectProjectInputHashes(projectRoot: string, identitie
393
480
  * Missing paths and files reached through symlinks or Windows junctions are
394
481
  * out-of-walk inputs that only the reference graph can prove relevant.
395
482
  */
396
- export declare function isProjectWalkPath(root: string, file: string, _identities?: FilesystemPathIdentityContext, filesystem?: TtscTransformFilesystemOperations): boolean;
483
+ export declare function isProjectWalkPath(root: string, file: string, _identities?: FilesystemPathIdentityContext, filesystem?: TtscTransformFilesystemOperations, policy?: ITtscProjectMembershipPolicy): boolean;
397
484
  /**
398
485
  * Hash a list of absolute out-of-walk input paths: content SHA-256 for a
399
486
  * readable file, a stable directory-kind digest for a directory candidate, and