@ttsc/unplugin 0.28.5 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -11
- package/lib/api.js +10 -0
- package/lib/api.js.map +1 -1
- package/lib/api.mjs +3 -2
- package/lib/api.mjs.map +1 -1
- package/lib/bun-register.d.cts +10 -7
- package/lib/bun-register.d.mts +10 -7
- package/lib/bun-register.d.ts +10 -7
- package/lib/bun-register.js +90 -24
- package/lib/bun-register.js.map +1 -1
- package/lib/bun-register.mjs +90 -24
- package/lib/bun-register.mjs.map +1 -1
- package/lib/bun.d.cts +10 -8
- package/lib/bun.d.mts +10 -8
- package/lib/bun.d.ts +10 -8
- package/lib/bun.js +19 -17
- package/lib/bun.js.map +1 -1
- package/lib/bun.mjs +20 -18
- package/lib/bun.mjs.map +1 -1
- package/lib/core/index.d.cts +10 -8
- package/lib/core/index.d.mts +10 -8
- package/lib/core/index.d.ts +10 -8
- package/lib/core/index.js +88 -16
- package/lib/core/index.js.map +1 -1
- package/lib/core/index.mjs +81 -18
- package/lib/core/index.mjs.map +1 -1
- package/lib/core/projectDiscovery.d.cts +55 -0
- package/lib/core/projectDiscovery.d.mts +55 -0
- package/lib/core/projectDiscovery.d.ts +55 -0
- package/lib/core/projectDiscovery.js +187 -0
- package/lib/core/projectDiscovery.js.map +1 -0
- package/lib/core/projectDiscovery.mjs +182 -0
- package/lib/core/projectDiscovery.mjs.map +1 -0
- package/lib/core/sourceExtensions.d.cts +10 -0
- package/lib/core/sourceExtensions.d.mts +10 -0
- package/lib/core/sourceExtensions.d.ts +10 -0
- package/lib/core/sourceExtensions.js +38 -0
- package/lib/core/sourceExtensions.js.map +1 -0
- package/lib/core/sourceExtensions.mjs +32 -0
- package/lib/core/sourceExtensions.mjs.map +1 -0
- package/lib/core/transform.d.cts +96 -16
- package/lib/core/transform.d.mts +96 -16
- package/lib/core/transform.d.ts +96 -16
- package/lib/core/transform.js +1295 -309
- package/lib/core/transform.js.map +1 -1
- package/lib/core/transform.mjs +1290 -310
- package/lib/core/transform.mjs.map +1 -1
- package/lib/core/tsconfigPaths.d.cts +55 -3
- package/lib/core/tsconfigPaths.d.mts +55 -3
- package/lib/core/tsconfigPaths.d.ts +55 -3
- package/lib/core/tsconfigPaths.js +260 -46
- package/lib/core/tsconfigPaths.js.map +1 -1
- package/lib/core/tsconfigPaths.mjs +255 -47
- package/lib/core/tsconfigPaths.mjs.map +1 -1
- package/lib/core/viteServe.d.cts +18 -21
- package/lib/core/viteServe.d.mts +18 -21
- package/lib/core/viteServe.d.ts +18 -21
- package/lib/core/viteServe.js +88 -47
- package/lib/core/viteServe.js.map +1 -1
- package/lib/core/viteServe.mjs +89 -49
- package/lib/core/viteServe.mjs.map +1 -1
- package/lib/next.d.cts +7 -0
- package/lib/next.d.mts +7 -0
- package/lib/next.d.ts +7 -0
- package/lib/next.js +186 -54
- package/lib/next.js.map +1 -1
- package/lib/next.mjs +186 -55
- package/lib/next.mjs.map +1 -1
- package/lib/turbopack.d.cts +6 -4
- package/lib/turbopack.d.mts +6 -4
- package/lib/turbopack.d.ts +6 -4
- package/lib/turbopack.js +11 -10
- package/lib/turbopack.js.map +1 -1
- package/lib/turbopack.mjs +11 -10
- package/lib/turbopack.mjs.map +1 -1
- package/package.json +7 -4
- package/src/bun-register.ts +112 -25
- package/src/bun.ts +60 -50
- package/src/core/index.ts +114 -19
- package/src/core/projectDiscovery.ts +256 -0
- package/src/core/sourceExtensions.ts +47 -0
- package/src/core/transform.ts +1671 -361
- package/src/core/tsconfigPaths.ts +406 -46
- package/src/core/viteServe.ts +125 -74
- package/src/next.ts +230 -54
- package/src/turbopack.ts +11 -10
package/src/bun-register.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from "node:util";
|
|
2
|
+
|
|
1
3
|
import bun, { type BunLikePlugin } from "./bun";
|
|
2
4
|
import type { TtscUnpluginOptions } from "./core/options";
|
|
3
5
|
|
|
@@ -12,20 +14,29 @@ interface BunRuntimeGlobal {
|
|
|
12
14
|
plugin(plugin: BunLikePlugin): void;
|
|
13
15
|
}
|
|
14
16
|
|
|
17
|
+
interface BunRegistrationState {
|
|
18
|
+
activeOptions: TtscUnpluginOptions | undefined;
|
|
19
|
+
lockedOptions: TtscUnpluginOptions | undefined;
|
|
20
|
+
optionsLocked: boolean;
|
|
21
|
+
registered: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
15
24
|
/**
|
|
16
|
-
*
|
|
25
|
+
* Pending and locked options for the single runtime loader.
|
|
17
26
|
*
|
|
18
27
|
* Bun uses the first matching `onLoad` hook and does not fall through to a
|
|
19
28
|
* later overlapping plugin (oven-sh/bun#20583). Registering twice — once
|
|
20
29
|
* implicitly on import, once explicitly — would let the default loader shadow
|
|
21
|
-
* the configured one. Instead exactly one Bun plugin is registered
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* the
|
|
30
|
+
* the configured one. Instead exactly one Bun plugin is registered. Calls made
|
|
31
|
+
* before its first load replace this detached snapshot; entering the first
|
|
32
|
+
* transformable load locks that value synchronously for the process's immutable
|
|
33
|
+
* module-loading session. State is keyed by the Bun runtime in a global weak
|
|
34
|
+
* map so loading both emitted module conditions cannot install two overlapping
|
|
35
|
+
* loaders.
|
|
25
36
|
*/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
const BUN_REGISTRATION_STATES = Symbol.for(
|
|
38
|
+
"@ttsc/unplugin/bun-register/states/v1",
|
|
39
|
+
);
|
|
29
40
|
|
|
30
41
|
/**
|
|
31
42
|
* Register the ttsc transform as a Bun **runtime** plugin.
|
|
@@ -39,14 +50,17 @@ let registered = false;
|
|
|
39
50
|
* "@ttsc/unplugin/bun-register"`. Options are read from the nearest
|
|
40
51
|
* `tsconfig.json`, identical to the bundler adapters.
|
|
41
52
|
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
53
|
+
* The first call registers one loader. Calls before its first transformable
|
|
54
|
+
* TypeScript load use last-call-wins and capture options by value, so an
|
|
55
|
+
* explicit call right after importing this module replaces the preload defaults
|
|
56
|
+
* without installing a shadowing loader. Entering the first such load locks
|
|
57
|
+
* that snapshot synchronously. Later calls with a structurally identical value
|
|
58
|
+
* are idempotent; a different value throws rather than pretending a resolved
|
|
59
|
+
* loader changed configuration.
|
|
47
60
|
*
|
|
48
|
-
* @throws When called explicitly off the Bun runtime
|
|
49
|
-
*
|
|
61
|
+
* @throws When called explicitly off the Bun runtime, when options are not
|
|
62
|
+
* structured-cloneable, or when a different option value is supplied after
|
|
63
|
+
* the first load. The auto-registration below stays silent off Bun so the
|
|
50
64
|
* module is harmless to import from Node (tests, tooling).
|
|
51
65
|
*/
|
|
52
66
|
export function register(options?: TtscUnpluginOptions): void {
|
|
@@ -58,15 +72,61 @@ export function register(options?: TtscUnpluginOptions): void {
|
|
|
58
72
|
"@ttsc/unplugin/vite for non-Bun toolchains.",
|
|
59
73
|
);
|
|
60
74
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
75
|
+
const state = registrationState(runtime);
|
|
76
|
+
const snapshot = snapshotOptions(options);
|
|
77
|
+
if (state.optionsLocked) {
|
|
78
|
+
if (isDeepStrictEqual(snapshot, state.lockedOptions)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
throw new Error(
|
|
82
|
+
"@ttsc/unplugin/bun-register options are locked because the runtime " +
|
|
83
|
+
"loader has started handling a TypeScript module. Restart the Bun " +
|
|
84
|
+
"process to use different compiler or plugin options.",
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
state.activeOptions = snapshot;
|
|
88
|
+
ensureRegistered(runtime, state);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Install the runtime's one loader without changing its pending options. */
|
|
92
|
+
function ensureRegistered(
|
|
93
|
+
runtime: BunRuntimeGlobal,
|
|
94
|
+
state: BunRegistrationState,
|
|
95
|
+
): void {
|
|
96
|
+
if (state.registered) return;
|
|
97
|
+
state.registered = true;
|
|
98
|
+
try {
|
|
99
|
+
runtime.plugin(bun(() => lockOptions(state)));
|
|
100
|
+
} catch (error) {
|
|
101
|
+
state.registered = false;
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Lock and return the detached option snapshot at first load-handler entry. */
|
|
107
|
+
function lockOptions(
|
|
108
|
+
state: BunRegistrationState,
|
|
109
|
+
): TtscUnpluginOptions | undefined {
|
|
110
|
+
if (!state.optionsLocked) {
|
|
111
|
+
state.lockedOptions = state.activeOptions;
|
|
112
|
+
state.optionsLocked = true;
|
|
113
|
+
}
|
|
114
|
+
return state.lockedOptions;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Detach JSON-shaped options from mutations made after `register` returns. */
|
|
118
|
+
function snapshotOptions(
|
|
119
|
+
options: TtscUnpluginOptions | undefined,
|
|
120
|
+
): TtscUnpluginOptions | undefined {
|
|
121
|
+
if (options === undefined) return undefined;
|
|
122
|
+
try {
|
|
123
|
+
return structuredClone(options);
|
|
124
|
+
} catch (cause) {
|
|
125
|
+
throw new TypeError(
|
|
126
|
+
"@ttsc/unplugin/bun-register options must contain structured-cloneable values.",
|
|
127
|
+
{ cause },
|
|
128
|
+
);
|
|
64
129
|
}
|
|
65
|
-
registered = true;
|
|
66
|
-
// Register a single loader whose options are read from `activeOptions` on
|
|
67
|
-
// first load, so an explicit call made after the import-time auto-register
|
|
68
|
-
// still wins.
|
|
69
|
-
runtime.plugin(bun(() => activeOptions));
|
|
70
130
|
}
|
|
71
131
|
|
|
72
132
|
function bunRuntime(): BunRuntimeGlobal | undefined {
|
|
@@ -76,11 +136,38 @@ function bunRuntime(): BunRuntimeGlobal | undefined {
|
|
|
76
136
|
: undefined;
|
|
77
137
|
}
|
|
78
138
|
|
|
139
|
+
/** Resolve the shared state owned by one concrete Bun runtime object. */
|
|
140
|
+
function registrationState(runtime: BunRuntimeGlobal): BunRegistrationState {
|
|
141
|
+
const holder = globalThis as unknown as Record<PropertyKey, unknown>;
|
|
142
|
+
let states = holder[BUN_REGISTRATION_STATES];
|
|
143
|
+
if (!(states instanceof WeakMap)) {
|
|
144
|
+
states = new WeakMap<object, BunRegistrationState>();
|
|
145
|
+
Object.defineProperty(holder, BUN_REGISTRATION_STATES, {
|
|
146
|
+
configurable: false,
|
|
147
|
+
enumerable: false,
|
|
148
|
+
value: states,
|
|
149
|
+
writable: false,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
const registrations = states as WeakMap<object, BunRegistrationState>;
|
|
153
|
+
const existing = registrations.get(runtime);
|
|
154
|
+
if (existing !== undefined) return existing;
|
|
155
|
+
const created: BunRegistrationState = {
|
|
156
|
+
activeOptions: undefined,
|
|
157
|
+
lockedOptions: undefined,
|
|
158
|
+
optionsLocked: false,
|
|
159
|
+
registered: false,
|
|
160
|
+
};
|
|
161
|
+
registrations.set(runtime, created);
|
|
162
|
+
return created;
|
|
163
|
+
}
|
|
164
|
+
|
|
79
165
|
// Auto-register on import so a `bunfig.toml` `preload` entry — which only
|
|
80
166
|
// imports the module — takes effect. Guarded so importing from Node (a stray
|
|
81
167
|
// import, or a unit test) is a harmless no-op rather than a throw.
|
|
82
|
-
|
|
83
|
-
|
|
168
|
+
const runtime = bunRuntime();
|
|
169
|
+
if (runtime !== undefined) {
|
|
170
|
+
ensureRegistered(runtime, registrationState(runtime));
|
|
84
171
|
}
|
|
85
172
|
|
|
86
173
|
export default register;
|
package/src/bun.ts
CHANGED
|
@@ -4,18 +4,15 @@ import {
|
|
|
4
4
|
beginTtscTransformBuild,
|
|
5
5
|
createTtscTransformCache,
|
|
6
6
|
isTransformTarget,
|
|
7
|
+
resetTtscTransformCache,
|
|
7
8
|
resolveOptions,
|
|
8
9
|
transformTtsc,
|
|
9
10
|
} from "./core/index";
|
|
10
11
|
import type { TtscUnpluginOptions } from "./core/options";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* created it: claiming it here and trying to read it from disk prevents that
|
|
16
|
-
* plugin's later loader from running.
|
|
17
|
-
*/
|
|
18
|
-
const bunSourceFilePattern = /^[^\x00]*\.[cm]?tsx?$/;
|
|
12
|
+
import {
|
|
13
|
+
bunTypeScriptTransformSourcePattern,
|
|
14
|
+
typescriptTransformBunLoader,
|
|
15
|
+
} from "./core/sourceExtensions";
|
|
19
16
|
|
|
20
17
|
/**
|
|
21
18
|
* Minimal subset of the Bun plugin API consumed by this adapter.
|
|
@@ -40,10 +37,10 @@ export type BunLoader = "ts" | "tsx";
|
|
|
40
37
|
*
|
|
41
38
|
* The provider form exists for the runtime registration path (`bun-register`),
|
|
42
39
|
* where a single Bun plugin is registered on import but its effective options
|
|
43
|
-
* may be overridden by
|
|
44
|
-
*
|
|
45
|
-
* at registration, lets
|
|
46
|
-
* shadowing loader.
|
|
40
|
+
* may be overridden by explicit `register(options)` calls made before the first
|
|
41
|
+
* transformable TypeScript load. Resolving through the provider on that first
|
|
42
|
+
* load, rather than at registration, lets the last pending call win without Bun
|
|
43
|
+
* ever seeing a second shadowing loader.
|
|
47
44
|
*/
|
|
48
45
|
export type TtscBunOptions =
|
|
49
46
|
| TtscUnpluginOptions
|
|
@@ -75,10 +72,10 @@ function resolveBunOptions(
|
|
|
75
72
|
/**
|
|
76
73
|
* Minimal subset of the Bun `BuildConfig` plugin build object.
|
|
77
74
|
*
|
|
78
|
-
* `onLoad` drives the source transform. Bun's bundler also exposes `onStart
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
75
|
+
* `onLoad` drives the source transform. Bun's bundler also exposes `onStart`
|
|
76
|
+
* and `onEnd`, which bracket the shared plugin's build lifecycle. The runtime
|
|
77
|
+
* plugin API omits those hooks, so plugin setup itself starts its one
|
|
78
|
+
* process-scoped module-loading session.
|
|
82
79
|
*/
|
|
83
80
|
export interface BunLikeBuild {
|
|
84
81
|
/**
|
|
@@ -97,6 +94,8 @@ export interface BunLikeBuild {
|
|
|
97
94
|
* Optional because `Bun.plugin()` runtime builders do not expose this hook.
|
|
98
95
|
*/
|
|
99
96
|
onStart?(callback: () => void | Promise<void>): void;
|
|
97
|
+
/** Register a callback for deterministic bundler-session teardown. */
|
|
98
|
+
onEnd?(callback: () => void | Promise<void>): void;
|
|
100
99
|
/**
|
|
101
100
|
* Register a loader callback for files matching `filter`.
|
|
102
101
|
*
|
|
@@ -141,10 +140,10 @@ export default function bun(options?: TtscBunOptions): BunLikePlugin {
|
|
|
141
140
|
return {
|
|
142
141
|
name: "ttsc-unplugin",
|
|
143
142
|
setup(build) {
|
|
144
|
-
// Resolve options lazily on first load.
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
//
|
|
143
|
+
// Resolve options lazily on the first transformable TypeScript load.
|
|
144
|
+
// Runtime registration may replace its pending configuration at any time
|
|
145
|
+
// before then; the provider form must observe that last update without
|
|
146
|
+
// installing a second shadowing loader.
|
|
148
147
|
let resolved: ReturnType<typeof resolveOptions> | undefined;
|
|
149
148
|
const getOptions = () =>
|
|
150
149
|
(resolved ??= resolveOptions(resolveBunOptions(options)));
|
|
@@ -159,43 +158,54 @@ export default function bun(options?: TtscBunOptions): BunLikePlugin {
|
|
|
159
158
|
// repeats it for subsequent builds.
|
|
160
159
|
beginTtscTransformBuild(cache);
|
|
161
160
|
build.onStart?.(() => beginTtscTransformBuild(cache));
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
161
|
+
if (!runtime) {
|
|
162
|
+
build.onEnd?.(() => resetTtscTransformCache(cache));
|
|
163
|
+
}
|
|
164
|
+
build.onLoad(
|
|
165
|
+
{ filter: bunTypeScriptTransformSourcePattern },
|
|
166
|
+
async (args) => {
|
|
167
|
+
if (!runtime && ownsInMemoryFile(args.path)) {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
if (!isTransformTarget(args.path)) {
|
|
171
|
+
if (!runtime) return undefined;
|
|
172
|
+
return {
|
|
173
|
+
contents: await fs.readFile(args.path, "utf8"),
|
|
174
|
+
loader: bunLoaderFor(args.path),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
const loader = bunLoaderFor(args.path);
|
|
178
|
+
const transformOptions = getOptions();
|
|
179
|
+
const source = await fs.readFile(args.path, "utf8");
|
|
180
|
+
const result = await transformTtsc(
|
|
181
|
+
args.path,
|
|
182
|
+
source,
|
|
183
|
+
transformOptions,
|
|
184
|
+
undefined,
|
|
185
|
+
cache,
|
|
186
|
+
bunTransformHooks,
|
|
187
|
+
);
|
|
188
|
+
if (result !== undefined) {
|
|
189
|
+
return { contents: result.code, loader };
|
|
190
|
+
}
|
|
191
|
+
return runtime ? { contents: source, loader } : undefined;
|
|
192
|
+
},
|
|
193
|
+
);
|
|
188
194
|
},
|
|
189
195
|
};
|
|
190
196
|
}
|
|
191
197
|
|
|
192
198
|
/**
|
|
193
|
-
* Pick the Bun loader
|
|
194
|
-
*
|
|
195
|
-
*
|
|
199
|
+
* Pick the Bun loader recorded beside the matched extension in the shared
|
|
200
|
+
* source table. Reaching this function without a table entry would mean Bun
|
|
201
|
+
* invoked a callback whose registration filter did not match.
|
|
196
202
|
*/
|
|
197
203
|
function bunLoaderFor(filePath: string): BunLoader {
|
|
198
|
-
|
|
204
|
+
const loader = typescriptTransformBunLoader(filePath);
|
|
205
|
+
if (loader === undefined) {
|
|
206
|
+
throw new Error(`Bun delivered an unsupported source path: ${filePath}`);
|
|
207
|
+
}
|
|
208
|
+
return loader;
|
|
199
209
|
}
|
|
200
210
|
|
|
201
211
|
/**
|
package/src/core/index.ts
CHANGED
|
@@ -5,30 +5,36 @@ import { createUnplugin } from "unplugin";
|
|
|
5
5
|
|
|
6
6
|
import type { TtscUnpluginOptions } from "./options";
|
|
7
7
|
import { resolveOptions } from "./options";
|
|
8
|
+
import { typescriptTransformSourcePattern } from "./sourceExtensions";
|
|
8
9
|
import {
|
|
9
10
|
beginTtscTransformBuild,
|
|
11
|
+
captureWatchInputBaseline,
|
|
12
|
+
captureWatchInputFileBaseline,
|
|
10
13
|
collectExternalInputHashes,
|
|
14
|
+
collectProjectInputHashSnapshot,
|
|
11
15
|
collectProjectInputHashes,
|
|
12
16
|
createTtscTransformCache,
|
|
13
17
|
isDeclarationFile,
|
|
14
18
|
isProjectWalkPath,
|
|
19
|
+
isWatchInputKeyBaseline,
|
|
15
20
|
resetTtscTransformCache,
|
|
16
21
|
stripQuery,
|
|
17
22
|
transformTtsc,
|
|
23
|
+
watchInputEvidenceMatchesBaseline,
|
|
18
24
|
} from "./transform";
|
|
19
25
|
import { createViteServeMissingInputWatch } from "./viteServe";
|
|
20
26
|
|
|
21
27
|
const name = "ttsc-unplugin";
|
|
22
28
|
/**
|
|
23
|
-
* Matches the TypeScript source extensions the ttsc transform handles:
|
|
24
|
-
* `.tsx`, `.mts`, `.cts
|
|
25
|
-
*
|
|
29
|
+
* Matches the exact TypeScript source extensions the ttsc transform handles:
|
|
30
|
+
* `.ts`, `.tsx`, `.mts`, and `.cts`. JavaScript and invented extension forms
|
|
31
|
+
* such as `.mtsx` are deliberately excluded.
|
|
26
32
|
*
|
|
27
33
|
* Shared with the Bun adapter (`bun.ts`) and the standalone Turbopack loader
|
|
28
34
|
* (`turbopack.ts`) through {@link isTransformTarget}, so the filter is defined
|
|
29
35
|
* once and every adapter answers the same way.
|
|
30
36
|
*/
|
|
31
|
-
export const sourceFilePattern =
|
|
37
|
+
export const sourceFilePattern = typescriptTransformSourcePattern;
|
|
32
38
|
/** Matches any path segment that is a `node_modules` directory (cross-platform). */
|
|
33
39
|
const nodeModulesPattern = /(?:^|[/\\])node_modules(?:[/\\]|$)/;
|
|
34
40
|
/**
|
|
@@ -72,6 +78,13 @@ const unpluginFactory: UnpluginFactory<
|
|
|
72
78
|
// old containers cannot dispose a replacement's freshly initialized cache.
|
|
73
79
|
let viteBuildOwners = new WeakSet<object>();
|
|
74
80
|
let viteBuildLifecycles = 0;
|
|
81
|
+
// esbuild schedules one-shot onDispose callbacks after it settles the build
|
|
82
|
+
// Promise. Acquire ownership only at onStart: plugin setup runs before build
|
|
83
|
+
// option validation, and a validation failure has no onDispose callback with
|
|
84
|
+
// which to release a setup-time owner. Once a build has actually started, the
|
|
85
|
+
// count keeps an older delayed callback from disposing its active generation.
|
|
86
|
+
const esbuildOwners = new WeakSet<object>();
|
|
87
|
+
let esbuildLifecycles = 0;
|
|
75
88
|
|
|
76
89
|
return {
|
|
77
90
|
name,
|
|
@@ -128,15 +141,14 @@ const unpluginFactory: UnpluginFactory<
|
|
|
128
141
|
// project per edit (samchon/ttsc#1301). The watching build hands its
|
|
129
142
|
// teardown to `closeWatcher` below instead.
|
|
130
143
|
buildEnd() {
|
|
131
|
-
missingInputs.dispose();
|
|
132
144
|
if (viteBuildOwners.delete(this)) {
|
|
133
145
|
viteBuildLifecycles -= 1;
|
|
134
146
|
}
|
|
135
|
-
if (
|
|
136
|
-
|
|
137
|
-
(viteCommand === "serve" || !viteBuildWatching)
|
|
138
|
-
|
|
139
|
-
|
|
147
|
+
if (viteBuildLifecycles === 0) {
|
|
148
|
+
missingInputs.dispose();
|
|
149
|
+
if (viteCommand === "serve" || !viteBuildWatching) {
|
|
150
|
+
resetTtscTransformCache(transformCache);
|
|
151
|
+
}
|
|
140
152
|
}
|
|
141
153
|
},
|
|
142
154
|
// The watching build's real teardown, and the only hook in a
|
|
@@ -156,6 +168,7 @@ const unpluginFactory: UnpluginFactory<
|
|
|
156
168
|
closeWatcher() {
|
|
157
169
|
viteBuildOwners = new WeakSet<object>();
|
|
158
170
|
viteBuildLifecycles = 0;
|
|
171
|
+
missingInputs.dispose();
|
|
159
172
|
resetTtscTransformCache(transformCache);
|
|
160
173
|
},
|
|
161
174
|
},
|
|
@@ -195,6 +208,39 @@ const unpluginFactory: UnpluginFactory<
|
|
|
195
208
|
},
|
|
196
209
|
},
|
|
197
210
|
|
|
211
|
+
// These hosts map a top-level buildEnd to a per-compilation hook, so use
|
|
212
|
+
// their true compiler or context teardown instead. The custom callbacks
|
|
213
|
+
// are installed by unplugin alongside its ordinary transform wiring.
|
|
214
|
+
webpack(compiler) {
|
|
215
|
+
compiler.hooks.shutdown.tap(name, () => {
|
|
216
|
+
resetTtscTransformCache(transformCache);
|
|
217
|
+
});
|
|
218
|
+
},
|
|
219
|
+
rspack(compiler) {
|
|
220
|
+
compiler.hooks.shutdown.tap(name, () => {
|
|
221
|
+
resetTtscTransformCache(transformCache);
|
|
222
|
+
});
|
|
223
|
+
},
|
|
224
|
+
esbuild: {
|
|
225
|
+
setup(build) {
|
|
226
|
+
build.onStart(() => {
|
|
227
|
+
if (!esbuildOwners.has(build)) {
|
|
228
|
+
esbuildOwners.add(build);
|
|
229
|
+
esbuildLifecycles += 1;
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
build.onDispose(() => {
|
|
233
|
+
if (!esbuildOwners.delete(build)) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
esbuildLifecycles -= 1;
|
|
237
|
+
if (esbuildLifecycles === 0) {
|
|
238
|
+
resetTtscTransformCache(transformCache);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
|
|
198
244
|
buildStart() {
|
|
199
245
|
if (viteCommand !== undefined && !viteBuildOwners.has(this as object)) {
|
|
200
246
|
viteBuildOwners.add(this as object);
|
|
@@ -242,22 +288,45 @@ const unpluginFactory: UnpluginFactory<
|
|
|
242
288
|
// invalidate this module in watch mode and persistent caches;
|
|
243
289
|
// bundlers erase type-only imports from their own module graph and
|
|
244
290
|
// would otherwise serve stale generated code. Under Vite serve a
|
|
245
|
-
//
|
|
246
|
-
// resolves added imports and 500s on
|
|
247
|
-
//
|
|
248
|
-
//
|
|
249
|
-
//
|
|
291
|
+
// resolver input that is not proven to be a file must not enter
|
|
292
|
+
// `addWatchFile`: import-analysis resolves added imports and 500s on
|
|
293
|
+
// missing paths and directories, so those are watched against their
|
|
294
|
+
// compiler predicates instead and invalidate this module when the
|
|
295
|
+
// observation changes.
|
|
250
296
|
addWatchFile: (watched, evidence) => {
|
|
251
297
|
if (viteCommand === "serve" && missingInputs.serving()) {
|
|
298
|
+
const observation =
|
|
299
|
+
evidence?.state?.codec === "predicates"
|
|
300
|
+
? evidence.state.observation
|
|
301
|
+
: undefined;
|
|
302
|
+
const unsafePredicate =
|
|
303
|
+
observation !== undefined &&
|
|
304
|
+
observation.fileExists !== true &&
|
|
305
|
+
observation.stat !== "file" &&
|
|
306
|
+
observation.readFile?.ok !== true
|
|
307
|
+
? observation
|
|
308
|
+
: undefined;
|
|
309
|
+
if (unsafePredicate !== undefined) {
|
|
310
|
+
missingInputs.watch(watched, path.resolve(file), unsafePredicate);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
252
313
|
// Trust the generation's recorded existence when it supplied one:
|
|
253
314
|
// every cache hit revalidates it, and probing each input again
|
|
254
315
|
// costs one `existsSync` per input per delivered module.
|
|
255
|
-
const
|
|
256
|
-
|
|
316
|
+
const unavailable =
|
|
317
|
+
evidence?.unavailable ??
|
|
318
|
+
(evidence === undefined
|
|
319
|
+
? !fs.existsSync(watched)
|
|
320
|
+
? "missing"
|
|
321
|
+
: undefined
|
|
322
|
+
: evidence.missing
|
|
323
|
+
? "missing"
|
|
324
|
+
: undefined);
|
|
325
|
+
if (unavailable !== undefined) {
|
|
257
326
|
missingInputs.watch(
|
|
258
327
|
watched,
|
|
259
328
|
path.resolve(file),
|
|
260
|
-
|
|
329
|
+
unavailable === "not-file" ? "file" : "exists",
|
|
261
330
|
);
|
|
262
331
|
return;
|
|
263
332
|
}
|
|
@@ -298,26 +367,52 @@ export type {
|
|
|
298
367
|
TtscUnpluginOptions,
|
|
299
368
|
} from "./options";
|
|
300
369
|
export type {
|
|
370
|
+
TtscProjectDiscoveryFilesystem,
|
|
371
|
+
TtscProjectTreeDiscoveryFilesystem,
|
|
372
|
+
TtscProjectTsconfigCandidate,
|
|
373
|
+
TtscProjectTsconfigDiscovery,
|
|
374
|
+
} from "./projectDiscovery";
|
|
375
|
+
export type {
|
|
376
|
+
TtscProjectInputHashSnapshot,
|
|
301
377
|
TtscTransformFilesystemOperations,
|
|
302
378
|
TtscTransformHooks,
|
|
379
|
+
TtscWatchInput,
|
|
380
|
+
TtscWatchInputBaseline,
|
|
303
381
|
TtscWatchInputEvidence,
|
|
382
|
+
TtscWatchInputFileBaseline,
|
|
383
|
+
TtscWatchInputKeyBaseline,
|
|
384
|
+
TtscWatchInputState,
|
|
304
385
|
} from "./transform";
|
|
305
|
-
export type {
|
|
386
|
+
export type {
|
|
387
|
+
ITsconfigSourceSnapshotEntry,
|
|
388
|
+
ITtscProjectMembershipPolicy,
|
|
389
|
+
} from "./tsconfigPaths";
|
|
306
390
|
export {
|
|
307
391
|
mergeMembershipPolicyOverlay,
|
|
308
392
|
readProjectMembershipPolicy,
|
|
393
|
+
readTsconfigSourceSnapshot,
|
|
309
394
|
} from "./tsconfigPaths";
|
|
310
395
|
export {
|
|
311
396
|
beginTtscTransformBuild,
|
|
397
|
+
captureWatchInputBaseline,
|
|
398
|
+
captureWatchInputFileBaseline,
|
|
312
399
|
collectExternalInputHashes,
|
|
400
|
+
collectProjectInputHashSnapshot,
|
|
313
401
|
collectProjectInputHashes,
|
|
314
402
|
createTtscTransformCache,
|
|
315
403
|
isProjectWalkPath,
|
|
404
|
+
isWatchInputKeyBaseline,
|
|
316
405
|
resetTtscTransformCache,
|
|
317
406
|
resolveOptions,
|
|
318
407
|
transformTtsc,
|
|
319
408
|
unplugin,
|
|
409
|
+
watchInputEvidenceMatchesBaseline,
|
|
320
410
|
};
|
|
411
|
+
export {
|
|
412
|
+
discoverNearestProjectTsconfig,
|
|
413
|
+
findNearestProjectTsconfig,
|
|
414
|
+
findProjectTsconfigs,
|
|
415
|
+
} from "./projectDiscovery";
|
|
321
416
|
|
|
322
417
|
export default unplugin;
|
|
323
418
|
|