@ttsc/unplugin 0.15.2 → 0.15.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.
- package/README.md +28 -1
- package/lib/core/index.d.ts +1 -0
- package/lib/core/index.js +7 -1
- package/lib/core/index.js.map +1 -1
- package/lib/core/index.mjs +7 -1
- package/lib/core/index.mjs.map +1 -1
- package/lib/core/transform.d.ts +18 -1
- package/lib/core/transform.js +108 -32
- package/lib/core/transform.js.map +1 -1
- package/lib/core/transform.mjs +108 -32
- package/lib/core/transform.mjs.map +1 -1
- package/lib/core/tsconfigPaths.d.ts +29 -0
- package/lib/core/tsconfigPaths.js +309 -0
- package/lib/core/tsconfigPaths.js.map +1 -0
- package/lib/core/tsconfigPaths.mjs +306 -0
- package/lib/core/tsconfigPaths.mjs.map +1 -0
- package/lib/turbopack.d.ts +43 -0
- package/lib/turbopack.js +55 -0
- package/lib/turbopack.js.map +1 -0
- package/lib/turbopack.mjs +51 -0
- package/lib/turbopack.mjs.map +1 -0
- package/package.json +8 -3
- package/src/core/index.ts +8 -1
- package/src/core/transform.ts +145 -49
- package/src/core/tsconfigPaths.ts +338 -0
- package/src/turbopack.ts +84 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Read the effective `compilerOptions.paths` of a tsconfig, following its
|
|
7
|
+
* `extends` chain, and absolutize every mapping target.
|
|
8
|
+
*
|
|
9
|
+
* TypeScript merges `compilerOptions` per option key, so the effective `paths`
|
|
10
|
+
* is the whole object from the nearest config in the chain that declares one
|
|
11
|
+
* (own config first, then `extends` entries in reverse priority order).
|
|
12
|
+
* Relative targets are anchored at the directory of the config that declares
|
|
13
|
+
* them — TypeScript-Go resolves inherited relative `paths` against the
|
|
14
|
+
* declaring file, not the extending one.
|
|
15
|
+
*
|
|
16
|
+
* The generated transform tsconfig replaces `paths` wholesale (standard
|
|
17
|
+
* `extends` semantics), so the alias overlay must re-state these base mappings
|
|
18
|
+
* or every tsconfig-only alias silently stops resolving. Absolutizing is
|
|
19
|
+
* required because the generated config lives in a system temp directory and
|
|
20
|
+
* TypeScript-Go rejects non-relative targets (TS5090) while accepting absolute
|
|
21
|
+
* ones.
|
|
22
|
+
*
|
|
23
|
+
* Best-effort by design: a missing or unparsable config in the chain yields
|
|
24
|
+
* `{}` here and a real config error from the compiler, which owns config
|
|
25
|
+
* diagnostics.
|
|
26
|
+
*/
|
|
27
|
+
function readEffectiveTsconfigPaths(tsconfig) {
|
|
28
|
+
const declared = findDeclaredPaths(path.resolve(tsconfig), new Set());
|
|
29
|
+
if (declared === null) {
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
const output = {};
|
|
33
|
+
for (const [key, targets] of Object.entries(declared.paths)) {
|
|
34
|
+
if (!Array.isArray(targets)) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const absolute = targets
|
|
38
|
+
.filter((target) => typeof target === "string")
|
|
39
|
+
.map((target) => absolutizePathsTarget(declared.baseDir, target));
|
|
40
|
+
if (absolute.length !== 0) {
|
|
41
|
+
output[key] = absolute;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return output;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Anchor a single `paths` target at `baseDir` unless it is already absolute,
|
|
48
|
+
* normalizing to forward slashes. The `*` wildcard survives `path.resolve` as a
|
|
49
|
+
* literal segment, so patterns like `./src/*` stay patterns.
|
|
50
|
+
*/
|
|
51
|
+
function absolutizePathsTarget(baseDir, target) {
|
|
52
|
+
const resolved = path.isAbsolute(target)
|
|
53
|
+
? target
|
|
54
|
+
: path.resolve(baseDir, target);
|
|
55
|
+
return resolved.replace(/\\/g, "/");
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Locate the nearest `compilerOptions.paths` declaration in the `extends` chain
|
|
59
|
+
* rooted at `tsconfig`. The own config wins over its bases; within an `extends`
|
|
60
|
+
* array, later entries win over earlier ones. `seen` breaks circular chains —
|
|
61
|
+
* the compiler reports the actual config error.
|
|
62
|
+
*/
|
|
63
|
+
function findDeclaredPaths(tsconfig, seen) {
|
|
64
|
+
const canonical = resolveRealPath(tsconfig);
|
|
65
|
+
if (seen.has(canonical)) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
seen.add(canonical);
|
|
69
|
+
let parsed;
|
|
70
|
+
try {
|
|
71
|
+
parsed = parseJsonc(fs.readFileSync(canonical, "utf8"));
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const own = parsed.compilerOptions?.paths;
|
|
80
|
+
if (typeof own === "object" && own !== null && !Array.isArray(own)) {
|
|
81
|
+
return {
|
|
82
|
+
baseDir: path.dirname(canonical),
|
|
83
|
+
paths: own,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
for (const specifier of extendsSpecifiers(parsed.extends).reverse()) {
|
|
87
|
+
const base = resolveExtendsConfig(canonical, specifier);
|
|
88
|
+
if (base === null) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const declared = findDeclaredPaths(base, seen);
|
|
92
|
+
if (declared !== null) {
|
|
93
|
+
return declared;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
/** Normalize the `extends` field into a list of string specifiers. */
|
|
99
|
+
function extendsSpecifiers(extended) {
|
|
100
|
+
if (typeof extended === "string") {
|
|
101
|
+
return [extended];
|
|
102
|
+
}
|
|
103
|
+
if (Array.isArray(extended)) {
|
|
104
|
+
return extended.filter((entry) => typeof entry === "string");
|
|
105
|
+
}
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Resolve an `extends` specifier to an absolute config path using TypeScript's
|
|
110
|
+
* rules: absolute paths and relative specifiers get `.json` /
|
|
111
|
+
* `tsconfig.json`-directory fallbacks; bare specifiers go through Node's module
|
|
112
|
+
* resolver scoped to the declaring config. Returns `null` instead of throwing —
|
|
113
|
+
* the compiler reports unresolvable `extends` itself.
|
|
114
|
+
*/
|
|
115
|
+
function resolveExtendsConfig(tsconfig, specifier) {
|
|
116
|
+
if (path.isAbsolute(specifier)) {
|
|
117
|
+
return resolveExistingExtendsPath(specifier);
|
|
118
|
+
}
|
|
119
|
+
if (isRelativeSpecifier(specifier)) {
|
|
120
|
+
return resolveExistingExtendsPath(path.resolve(path.dirname(tsconfig), specifier));
|
|
121
|
+
}
|
|
122
|
+
const resolver = createRequire(tsconfig);
|
|
123
|
+
try {
|
|
124
|
+
return resolveRealPath(resolver.resolve(specifier));
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
try {
|
|
128
|
+
return resolveRealPath(resolver.resolve(`${specifier}.json`));
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Try an on-disk `extends` location as-is, with `.json` appended, and as a
|
|
137
|
+
* directory containing `tsconfig.json`. Returns the first existing match.
|
|
138
|
+
*/
|
|
139
|
+
function resolveExistingExtendsPath(location) {
|
|
140
|
+
for (const candidate of new Set([
|
|
141
|
+
location,
|
|
142
|
+
`${location}.json`,
|
|
143
|
+
path.join(location, "tsconfig.json"),
|
|
144
|
+
])) {
|
|
145
|
+
if (fs.existsSync(candidate)) {
|
|
146
|
+
return resolveRealPath(candidate);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Return true when `specifier` is a relative path reference: `.`, `..`, or a
|
|
153
|
+
* string starting with `./`, `../`, `.\\`, or `..\\`.
|
|
154
|
+
*/
|
|
155
|
+
function isRelativeSpecifier(specifier) {
|
|
156
|
+
return (specifier === "." ||
|
|
157
|
+
specifier === ".." ||
|
|
158
|
+
specifier.startsWith("./") ||
|
|
159
|
+
specifier.startsWith("../") ||
|
|
160
|
+
specifier.startsWith(".\\") ||
|
|
161
|
+
specifier.startsWith("..\\"));
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Resolve symlinks on `location`, returning the original path when
|
|
165
|
+
* `realpathSync` fails (e.g. when the file does not exist).
|
|
166
|
+
*/
|
|
167
|
+
function resolveRealPath(location) {
|
|
168
|
+
try {
|
|
169
|
+
return fs.realpathSync(location);
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return location;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Parse a JSONC (JSON with Comments) string by stripping comments and trailing
|
|
177
|
+
* commas before handing off to `JSON.parse`. A leading UTF-8 BOM is dropped —
|
|
178
|
+
* `JSON.parse` rejects it, and this reader must not lose `paths` for a config
|
|
179
|
+
* the compiler accepts.
|
|
180
|
+
*/
|
|
181
|
+
function parseJsonc(input) {
|
|
182
|
+
const text = input.charCodeAt(0) === 0xfeff ? input.slice(1) : input;
|
|
183
|
+
return JSON.parse(stripTrailingCommas(stripComments(text)));
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Remove `//` line comments and `/* block comments *\/` from a JSONC string.
|
|
187
|
+
* Correctly handles strings that contain comment-like character sequences by
|
|
188
|
+
* tracking string boundaries and escape characters.
|
|
189
|
+
*/
|
|
190
|
+
function stripComments(input) {
|
|
191
|
+
let output = "";
|
|
192
|
+
let inBlockComment = false;
|
|
193
|
+
let inLineComment = false;
|
|
194
|
+
let inString = false;
|
|
195
|
+
let quote = "";
|
|
196
|
+
let escape = false;
|
|
197
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
198
|
+
const current = input[i];
|
|
199
|
+
const next = input[i + 1];
|
|
200
|
+
if (inBlockComment) {
|
|
201
|
+
if (current === "*" && next === "/") {
|
|
202
|
+
inBlockComment = false;
|
|
203
|
+
i += 1;
|
|
204
|
+
}
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (inLineComment) {
|
|
208
|
+
if (current === "\n") {
|
|
209
|
+
inLineComment = false;
|
|
210
|
+
output += current;
|
|
211
|
+
}
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (inString) {
|
|
215
|
+
output += current;
|
|
216
|
+
if (escape) {
|
|
217
|
+
escape = false;
|
|
218
|
+
}
|
|
219
|
+
else if (current === "\\") {
|
|
220
|
+
escape = true;
|
|
221
|
+
}
|
|
222
|
+
else if (current === quote) {
|
|
223
|
+
inString = false;
|
|
224
|
+
quote = "";
|
|
225
|
+
}
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
if (current === '"' || current === "'") {
|
|
229
|
+
inString = true;
|
|
230
|
+
quote = current;
|
|
231
|
+
output += current;
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
if (current === "/" && next === "/") {
|
|
235
|
+
inLineComment = true;
|
|
236
|
+
i += 1;
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
if (current === "/" && next === "*") {
|
|
240
|
+
inBlockComment = true;
|
|
241
|
+
i += 1;
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
output += current;
|
|
245
|
+
}
|
|
246
|
+
return output;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Remove trailing commas before `}` or `]` from a JSON string (after comments
|
|
250
|
+
* have already been stripped). Handles string boundaries and escape characters
|
|
251
|
+
* to avoid removing commas inside string values.
|
|
252
|
+
*/
|
|
253
|
+
function stripTrailingCommas(input) {
|
|
254
|
+
let output = "";
|
|
255
|
+
let inString = false;
|
|
256
|
+
let quote = "";
|
|
257
|
+
let escape = false;
|
|
258
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
259
|
+
const current = input[i];
|
|
260
|
+
if (inString) {
|
|
261
|
+
output += current;
|
|
262
|
+
if (escape) {
|
|
263
|
+
escape = false;
|
|
264
|
+
}
|
|
265
|
+
else if (current === "\\") {
|
|
266
|
+
escape = true;
|
|
267
|
+
}
|
|
268
|
+
else if (current === quote) {
|
|
269
|
+
inString = false;
|
|
270
|
+
quote = "";
|
|
271
|
+
}
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (current === '"' || current === "'") {
|
|
275
|
+
inString = true;
|
|
276
|
+
quote = current;
|
|
277
|
+
output += current;
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
if (current === ",") {
|
|
281
|
+
const next = nextNonWhitespace(input, i + 1);
|
|
282
|
+
if (next === "}" || next === "]") {
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
output += current;
|
|
287
|
+
}
|
|
288
|
+
return output;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Return the first non-whitespace character at or after position `from` in
|
|
292
|
+
* `input`, or `undefined` when only whitespace remains. Used by
|
|
293
|
+
* `stripTrailingCommas` to detect whether a comma is trailing.
|
|
294
|
+
*/
|
|
295
|
+
function nextNonWhitespace(input, from) {
|
|
296
|
+
for (let i = from; i < input.length; i += 1) {
|
|
297
|
+
const current = input[i];
|
|
298
|
+
if (/\s/.test(current) === false) {
|
|
299
|
+
return current;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return undefined;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export { absolutizePathsTarget, readEffectiveTsconfigPaths };
|
|
306
|
+
//# sourceMappingURL=tsconfigPaths.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tsconfigPaths.mjs","sources":["../../src/core/tsconfigPaths.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { TtscUnpluginOptions } from "./core/options";
|
|
2
|
+
/**
|
|
3
|
+
* Subset of the webpack loader context Turbopack provides to loaders wired
|
|
4
|
+
* through `turbopack.rules`. Turbopack has no JS plugin API, but it runs
|
|
5
|
+
* webpack-compatible loaders: source string in, source string out, with
|
|
6
|
+
* `async()` for asynchronous completion and `getOptions()` for the rule's
|
|
7
|
+
* `options` object.
|
|
8
|
+
*/
|
|
9
|
+
export interface TtscTurbopackLoaderContext {
|
|
10
|
+
/** Marks the loader asynchronous and returns the completion callback. */
|
|
11
|
+
async(): (error?: unknown, content?: string) => void;
|
|
12
|
+
/** Absolute path of the module being loaded. */
|
|
13
|
+
resourcePath: string;
|
|
14
|
+
/** The rule's `options` object, when one was configured. */
|
|
15
|
+
getOptions?(): TtscUnpluginOptions | undefined;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Standalone webpack-loader entrypoint for Turbopack.
|
|
19
|
+
*
|
|
20
|
+
* Turbopack cannot load unplugin-based plugins (no JS plugin API), but its
|
|
21
|
+
* `turbopack.rules` accept webpack loaders, and a ttsc transform is exactly
|
|
22
|
+
* loader-shaped: pure TypeScript source in, transformed source out. Wire it per
|
|
23
|
+
* extension:
|
|
24
|
+
*
|
|
25
|
+
* ```js
|
|
26
|
+
* // next.config.mjs
|
|
27
|
+
* const nextConfig = {
|
|
28
|
+
* turbopack: {
|
|
29
|
+
* rules: {
|
|
30
|
+
* "*.ts": { loaders: ["@ttsc/unplugin/turbopack"] },
|
|
31
|
+
* "*.tsx": { loaders: ["@ttsc/unplugin/turbopack"] },
|
|
32
|
+
* },
|
|
33
|
+
* },
|
|
34
|
+
* };
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* Pass {@link TtscUnpluginOptions} through the rule's `options` object. The
|
|
38
|
+
* loader returns the source unchanged for declaration files, `node_modules`
|
|
39
|
+
* paths, and transforms that produce no change — mirroring the unplugin
|
|
40
|
+
* adapters' `transformInclude` filter, since a broad rule glob routes
|
|
41
|
+
* everything matching the extension through the loader.
|
|
42
|
+
*/
|
|
43
|
+
export default function turbopack(this: TtscTurbopackLoaderContext, source: string): void;
|
package/lib/turbopack.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var options = require('./core/options.js');
|
|
6
|
+
var transform = require('./core/transform.js');
|
|
7
|
+
|
|
8
|
+
/** Matches any path segment that is a `node_modules` directory (cross-platform). */
|
|
9
|
+
const nodeModulesPattern = /(?:^|[/\\])node_modules(?:[/\\]|$)/;
|
|
10
|
+
/**
|
|
11
|
+
* Per-process transform cache. Turbopack runs loaders in a worker pool and
|
|
12
|
+
* never signals build boundaries to a loader, so the cache lives for the
|
|
13
|
+
* worker's lifetime; entries self-invalidate by re-hashing the project's input
|
|
14
|
+
* files on every request (see `transformTtsc`), which is the same freshness
|
|
15
|
+
* rule the bundler-plugin adapters rely on between watch rebuilds.
|
|
16
|
+
*/
|
|
17
|
+
const transformCache = transform.createTtscTransformCache();
|
|
18
|
+
/**
|
|
19
|
+
* Standalone webpack-loader entrypoint for Turbopack.
|
|
20
|
+
*
|
|
21
|
+
* Turbopack cannot load unplugin-based plugins (no JS plugin API), but its
|
|
22
|
+
* `turbopack.rules` accept webpack loaders, and a ttsc transform is exactly
|
|
23
|
+
* loader-shaped: pure TypeScript source in, transformed source out. Wire it per
|
|
24
|
+
* extension:
|
|
25
|
+
*
|
|
26
|
+
* ```js
|
|
27
|
+
* // next.config.mjs
|
|
28
|
+
* const nextConfig = {
|
|
29
|
+
* turbopack: {
|
|
30
|
+
* rules: {
|
|
31
|
+
* "*.ts": { loaders: ["@ttsc/unplugin/turbopack"] },
|
|
32
|
+
* "*.tsx": { loaders: ["@ttsc/unplugin/turbopack"] },
|
|
33
|
+
* },
|
|
34
|
+
* },
|
|
35
|
+
* };
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* Pass {@link TtscUnpluginOptions} through the rule's `options` object. The
|
|
39
|
+
* loader returns the source unchanged for declaration files, `node_modules`
|
|
40
|
+
* paths, and transforms that produce no change — mirroring the unplugin
|
|
41
|
+
* adapters' `transformInclude` filter, since a broad rule glob routes
|
|
42
|
+
* everything matching the extension through the loader.
|
|
43
|
+
*/
|
|
44
|
+
function turbopack(source) {
|
|
45
|
+
const callback = this.async();
|
|
46
|
+
const file = transform.stripQuery(this.resourcePath);
|
|
47
|
+
if (transform.isDeclarationFile(file) || nodeModulesPattern.test(file)) {
|
|
48
|
+
callback(undefined, source);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
transform.transformTtsc(file, source, options.resolveOptions(this.getOptions?.() ?? {}), undefined, transformCache).then((result) => callback(undefined, result?.code ?? source), (error) => callback(error));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
exports.default = turbopack;
|
|
55
|
+
//# sourceMappingURL=turbopack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turbopack.js","sources":["../src/turbopack.ts"],"sourcesContent":[null],"names":["createTtscTransformCache","stripQuery","isDeclarationFile","transformTtsc","resolveOptions"],"mappings":";;;;;;;AAyBA;AACA,MAAM,kBAAkB,GAAG,oCAAoC;AAE/D;;;;;;AAMG;AACH,MAAM,cAAc,GAAGA,kCAAwB,EAAE;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;AACW,SAAU,SAAS,CAE/B,MAAc,EAAA;AAEd,IAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,EAAE;IAC7B,MAAM,IAAI,GAAGC,oBAAU,CAAC,IAAI,CAAC,YAAY,CAAC;AAC1C,IAAA,IAAIC,2BAAiB,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;AAC5D,QAAA,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B;IACF;IACAC,uBAAa,CACX,IAAI,EACJ,MAAM,EACNC,sBAAc,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC,EACzC,SAAS,EACT,cAAc,CACf,CAAC,IAAI,CACJ,CAAC,MAAM,KAAK,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,IAAI,MAAM,CAAC,EACvD,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK,CAAC,CAC3B;AACH;;;;"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { resolveOptions } from './core/options.mjs';
|
|
2
|
+
import { stripQuery, isDeclarationFile, transformTtsc, createTtscTransformCache } from './core/transform.mjs';
|
|
3
|
+
|
|
4
|
+
/** Matches any path segment that is a `node_modules` directory (cross-platform). */
|
|
5
|
+
const nodeModulesPattern = /(?:^|[/\\])node_modules(?:[/\\]|$)/;
|
|
6
|
+
/**
|
|
7
|
+
* Per-process transform cache. Turbopack runs loaders in a worker pool and
|
|
8
|
+
* never signals build boundaries to a loader, so the cache lives for the
|
|
9
|
+
* worker's lifetime; entries self-invalidate by re-hashing the project's input
|
|
10
|
+
* files on every request (see `transformTtsc`), which is the same freshness
|
|
11
|
+
* rule the bundler-plugin adapters rely on between watch rebuilds.
|
|
12
|
+
*/
|
|
13
|
+
const transformCache = createTtscTransformCache();
|
|
14
|
+
/**
|
|
15
|
+
* Standalone webpack-loader entrypoint for Turbopack.
|
|
16
|
+
*
|
|
17
|
+
* Turbopack cannot load unplugin-based plugins (no JS plugin API), but its
|
|
18
|
+
* `turbopack.rules` accept webpack loaders, and a ttsc transform is exactly
|
|
19
|
+
* loader-shaped: pure TypeScript source in, transformed source out. Wire it per
|
|
20
|
+
* extension:
|
|
21
|
+
*
|
|
22
|
+
* ```js
|
|
23
|
+
* // next.config.mjs
|
|
24
|
+
* const nextConfig = {
|
|
25
|
+
* turbopack: {
|
|
26
|
+
* rules: {
|
|
27
|
+
* "*.ts": { loaders: ["@ttsc/unplugin/turbopack"] },
|
|
28
|
+
* "*.tsx": { loaders: ["@ttsc/unplugin/turbopack"] },
|
|
29
|
+
* },
|
|
30
|
+
* },
|
|
31
|
+
* };
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* Pass {@link TtscUnpluginOptions} through the rule's `options` object. The
|
|
35
|
+
* loader returns the source unchanged for declaration files, `node_modules`
|
|
36
|
+
* paths, and transforms that produce no change — mirroring the unplugin
|
|
37
|
+
* adapters' `transformInclude` filter, since a broad rule glob routes
|
|
38
|
+
* everything matching the extension through the loader.
|
|
39
|
+
*/
|
|
40
|
+
function turbopack(source) {
|
|
41
|
+
const callback = this.async();
|
|
42
|
+
const file = stripQuery(this.resourcePath);
|
|
43
|
+
if (isDeclarationFile(file) || nodeModulesPattern.test(file)) {
|
|
44
|
+
callback(undefined, source);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
transformTtsc(file, source, resolveOptions(this.getOptions?.() ?? {}), undefined, transformCache).then((result) => callback(undefined, result?.code ?? source), (error) => callback(error));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { turbopack as default };
|
|
51
|
+
//# sourceMappingURL=turbopack.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turbopack.mjs","sources":["../src/turbopack.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAyBA;AACA,MAAM,kBAAkB,GAAG,oCAAoC;AAE/D;;;;;;AAMG;AACH,MAAM,cAAc,GAAG,wBAAwB,EAAE;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;AACW,SAAU,SAAS,CAE/B,MAAc,EAAA;AAEd,IAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,EAAE;IAC7B,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC;AAC1C,IAAA,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;AAC5D,QAAA,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B;IACF;IACA,aAAa,CACX,IAAI,EACJ,MAAM,EACN,cAAc,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC,EACzC,SAAS,EACT,cAAc,CACf,CAAC,IAAI,CACJ,CAAC,MAAM,KAAK,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,IAAI,MAAM,CAAC,EACvD,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK,CAAC,CAC3B;AACH;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttsc/unplugin",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.4",
|
|
4
4
|
"description": "Bundler adapters for ttsc plugins.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/index.mjs",
|
|
@@ -51,6 +51,11 @@
|
|
|
51
51
|
"import": "./lib/rspack.mjs",
|
|
52
52
|
"default": "./lib/rspack.js"
|
|
53
53
|
},
|
|
54
|
+
"./turbopack": {
|
|
55
|
+
"types": "./lib/turbopack.d.ts",
|
|
56
|
+
"import": "./lib/turbopack.mjs",
|
|
57
|
+
"default": "./lib/turbopack.js"
|
|
58
|
+
},
|
|
54
59
|
"./vite": {
|
|
55
60
|
"types": "./lib/vite.d.ts",
|
|
56
61
|
"import": "./lib/vite.mjs",
|
|
@@ -89,7 +94,7 @@
|
|
|
89
94
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
90
95
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
91
96
|
"@types/node": "^25.3.0",
|
|
92
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
97
|
+
"@typescript/native-preview": "7.0.0-dev.20260615.1",
|
|
93
98
|
"esbuild": "^0.25.12",
|
|
94
99
|
"rimraf": "^6.1.2",
|
|
95
100
|
"rollup": "^4.60.3",
|
|
@@ -99,7 +104,7 @@
|
|
|
99
104
|
"tslib": "^2.8.1",
|
|
100
105
|
"typescript": "^6.0.3",
|
|
101
106
|
"vite": "^7.1.12",
|
|
102
|
-
"ttsc": "0.15.
|
|
107
|
+
"ttsc": "0.15.4"
|
|
103
108
|
},
|
|
104
109
|
"repository": {
|
|
105
110
|
"type": "git",
|
package/src/core/index.ts
CHANGED
|
@@ -67,7 +67,13 @@ const unpluginFactory: UnpluginFactory<
|
|
|
67
67
|
if (!isTransformTarget(file)) {
|
|
68
68
|
return undefined;
|
|
69
69
|
}
|
|
70
|
-
return transformTtsc(file, source, options, aliases, transformCache
|
|
70
|
+
return transformTtsc(file, source, options, aliases, transformCache, {
|
|
71
|
+
// Register plugin-reported dependencies (the transform envelope's
|
|
72
|
+
// `dependencies` lists) so type-only inputs invalidate this module
|
|
73
|
+
// in watch mode; bundlers erase type-only imports from their own
|
|
74
|
+
// module graph and would otherwise serve stale generated code.
|
|
75
|
+
addWatchFile: (watched) => this.addWatchFile(watched),
|
|
76
|
+
});
|
|
71
77
|
},
|
|
72
78
|
};
|
|
73
79
|
};
|
|
@@ -79,6 +85,7 @@ export type {
|
|
|
79
85
|
TtscUnpluginCompilerOptionsJson,
|
|
80
86
|
TtscUnpluginOptions,
|
|
81
87
|
} from "./options";
|
|
88
|
+
export type { TtscTransformHooks } from "./transform";
|
|
82
89
|
export { createTtscTransformCache, resolveOptions, transformTtsc, unplugin };
|
|
83
90
|
|
|
84
91
|
export default unplugin;
|