@ttsc/unplugin 0.28.3 → 0.28.5

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 +70 -8
  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 +117 -21
  10. package/lib/core/index.js.map +1 -1
  11. package/lib/core/index.mjs +115 -21
  12. package/lib/core/index.mjs.map +1 -1
  13. package/lib/core/transform.d.cts +93 -25
  14. package/lib/core/transform.d.mts +93 -25
  15. package/lib/core/transform.d.ts +93 -25
  16. package/lib/core/transform.js +803 -121
  17. package/lib/core/transform.js.map +1 -1
  18. package/lib/core/transform.mjs +804 -122
  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 +122 -21
  43. package/src/core/transform.ts +1073 -132
  44. package/src/core/tsconfigPaths.ts +254 -8
  45. package/src/next.ts +262 -10
  46. package/src/turbopack.ts +13 -9
package/lib/next.mjs CHANGED
@@ -1,21 +1,40 @@
1
1
  import webpack from './webpack.mjs';
2
2
 
3
+ /** The standalone loader entry Turbopack accepts through `turbopack.rules`. */
4
+ const TURBOPACK_LOADER = "@ttsc/unplugin/turbopack";
3
5
  /**
4
- * Wrap a Next.js config object so that the ttsc webpack plugin is injected into
5
- * every webpack build Next.js performs.
6
+ * The globs the loader is wired for.
6
7
  *
7
- * The adapter uses `unshift` to ensure the ttsc plugin runs before any other
8
- * plugins in the array (unplugin `enforce: "pre"` semantics). An existing
9
- * `nextConfig.webpack` hook is preserved and called after the plugin is
10
- * injected.
8
+ * The same two the manual wiring in the README uses. A wider glob would be
9
+ * harmless, since `isTransformTarget` declines everything else that reaches the
10
+ * loader, but it would also route files through a worker for nothing.
11
+ */
12
+ const TURBOPACK_RULE_GLOBS = ["*.ts", "*.tsx"];
13
+ /**
14
+ * Wrap a Next.js config object so that ttsc runs under whichever bundler
15
+ * Next.js uses.
16
+ *
17
+ * The webpack plugin is injected through the `webpack` hook, and the Turbopack
18
+ * loader is wired through `turbopack.rules`, with the same options reaching
19
+ * both. Covering only webpack meant that a project on Turbopack, which is the
20
+ * default bundler in current Next majors, silently got no transform at all: the
21
+ * build succeeded and every plugin-driven construct in it, a typia
22
+ * `assert<T>()` above all, survived untransformed into a runtime failure
23
+ * (samchon/ttsc#1310).
24
+ *
25
+ * Both halves are additive. An existing `webpack` hook is preserved and called
26
+ * after the plugin is injected, and an existing `turbopack` block keeps every
27
+ * setting and every rule it already had.
11
28
  *
12
29
  * @param nextConfig - The caller's existing Next.js config (spread into the
13
- * returned object unchanged, except for `webpack`).
14
- * @param options - Ttsc plugin options forwarded to the webpack adapter.
30
+ * returned object unchanged, except for `webpack` and `turbopack`).
31
+ * @param options - Ttsc plugin options forwarded to both bundlers.
15
32
  */
16
33
  function next(nextConfig = {}, options) {
34
+ warnAboutSuppressedWebpackConfig(nextConfig);
17
35
  return {
18
36
  ...nextConfig,
37
+ turbopack: withTtscTurbopackRules(nextConfig.turbopack, options),
19
38
  webpack(config, webpackOptions) {
20
39
  config.plugins = Array.isArray(config.plugins) ? config.plugins : [];
21
40
  // Prepend so ttsc runs before any user-added plugins.
@@ -27,6 +46,208 @@ function next(nextConfig = {}, options) {
27
46
  },
28
47
  };
29
48
  }
49
+ /**
50
+ * Say what Next.js can no longer say once this wrapper defines `turbopack`.
51
+ *
52
+ * Next stops the build when a config carries a `webpack` hook and no
53
+ * `turbopack` block, because the webpack hook is then silently ignored. Read
54
+ * from Next 16.3.2's own `dist/lib/turbopack-warning.js`, it is
55
+ * `log.error(...)` followed by `process.exit(1)` — a refusal, not a warning —
56
+ * and it is gated on `process.env.TURBOPACK === "auto"`, which
57
+ * `dist/lib/bundler.js` sets only when no bundler flag was passed. Next's
58
+ * comment there gives the reason: an explicit `--turbopack` means the user
59
+ * chose it and is assumed to have configured it. So the check fires on a plain
60
+ * `next build` or `next dev`, which is how Next 16 is normally run.
61
+ *
62
+ * `hasTurboConfig` is read from the raw exported config, which is this
63
+ * wrapper's return value, and this wrapper always defines `turbopack`. The
64
+ * check therefore can never fire again for anyone who uses `withTtsc`, and a
65
+ * caller's own webpack customisation would be dropped on a Turbopack build with
66
+ * nothing said. Wiring ttsc for Turbopack is worth exactly one line, not the
67
+ * loss of the refusal Next already gave.
68
+ *
69
+ * Verifying that gate is what this docstring exists for: measured with an
70
+ * explicit `--turbopack`, the check is silent, and a reading that stopped there
71
+ * would conclude Next says nothing and delete a true statement.
72
+ *
73
+ * Only for a caller who wrote a `webpack` hook and no `turbopack` block. A
74
+ * caller who configured Turbopack has already made that decision, and a caller
75
+ * with neither has no webpack-only configuration to lose.
76
+ */
77
+ function warnAboutSuppressedWebpackConfig(nextConfig) {
78
+ if (typeof nextConfig.webpack !== "function" ||
79
+ nextConfig.turbopack !== undefined) {
80
+ return;
81
+ }
82
+ process.stderr.write("@ttsc/unplugin: withTtsc now configures Turbopack as well as webpack, so " +
83
+ "Next.js will no longer stop the build to tell you that your own " +
84
+ "`webpack` hook is ignored on a Turbopack build. Port it to `turbopack`, " +
85
+ "or run the bundler you configured with `next build --webpack` / " +
86
+ "`next dev --webpack`." +
87
+ String.fromCharCode(10));
88
+ }
89
+ /**
90
+ * Merge the ttsc loader rules into a caller's Turbopack configuration.
91
+ *
92
+ * Additive in every direction: unrelated Turbopack settings and unrelated rules
93
+ * are carried through untouched, and a glob the caller already configured keeps
94
+ * its own loaders with ttsc placed where the chain runs it first. A caller who
95
+ * already wired this loader by hand is left exactly as they are, so following
96
+ * the README's manual instructions and then adopting the wrapper cannot
97
+ * register it twice.
98
+ */
99
+ function withTtscTurbopackRules(existing, options) {
100
+ const rules = { ...(existing?.rules ?? {}) };
101
+ for (const glob of TURBOPACK_RULE_GLOBS) {
102
+ const rule = rules[glob];
103
+ const loaders = selectTurbopackLoaders(rule);
104
+ if (loaders.some(referencesTtscLoader)) {
105
+ continue;
106
+ }
107
+ // The caller may have written the same file set under a different glob.
108
+ // Adding ours beside theirs makes every matching module run the loader
109
+ // twice, and the second pass receives the first pass's output, so the
110
+ // guard has to cover the spellings a caller plausibly uses rather than
111
+ // only the two this wrapper writes (samchon/ttsc#1314).
112
+ if (coveredByAnotherRule(rules, glob)) {
113
+ continue;
114
+ }
115
+ const entry = { loader: TURBOPACK_LOADER, options: options ?? {} };
116
+ // Appended, not prepended. Turbopack runs a rule's loaders right to left,
117
+ // so the last entry is the one that sees the original source. ttsc
118
+ // transforms TypeScript into TypeScript, so it has to be that one, which
119
+ // is the same position `enforce: "pre"` gives it on the webpack half.
120
+ //
121
+ // Measured rather than inferred from webpack's `loader-runner`: two
122
+ // loaders on one rule, each marking the source, came back marked in the
123
+ // order that only the last-runs-first chain produces (samchon/ttsc#1319).
124
+ rules[glob] =
125
+ rule === undefined || loaders.length === 0
126
+ ? { loaders: [entry] }
127
+ : Array.isArray(rule)
128
+ ? { loaders: [...loaders, entry] }
129
+ : { ...rule, loaders: [...loaders, entry] };
130
+ }
131
+ return { ...(existing ?? {}), rules };
132
+ }
133
+ /**
134
+ * Whether some other rule already routes this glob's files through the loader.
135
+ *
136
+ * Deciding glob equivalence in general means implementing Turbopack's matcher,
137
+ * which is not worth it here. What is recognised instead is the spellings a
138
+ * caller plausibly writes for "every file with this extension", since only a
139
+ * glob that means every file can make the wrapper's own rules redundant. That
140
+ * is narrower than every glob with those semantics, and narrow on purpose:
141
+ * anything unrecognised is left alone and the wrapper still adds its rules,
142
+ * while skipping on a scoped glob would leave every module outside that scope
143
+ * untransformed, which is samchon/ttsc#1310 again and the quieter of the two
144
+ * failures. {@link matchesExtension} owns the rule and names what it declines.
145
+ */
146
+ function coveredByAnotherRule(rules, glob) {
147
+ const extension = glob.slice(glob.lastIndexOf(".") + 1);
148
+ return Object.entries(rules).some(([candidate, rule]) => {
149
+ if (candidate === glob) {
150
+ return false;
151
+ }
152
+ if (!selectTurbopackLoaders(rule).some(referencesTtscLoader)) {
153
+ return false;
154
+ }
155
+ return matchesExtension(candidate, extension);
156
+ });
157
+ }
158
+ /**
159
+ * Whether one glob names this extension across the whole project.
160
+ *
161
+ * Unscoped only. A rule carrying a path segment says nothing about the rest of
162
+ * the project, so treating it as covering everything would leave every module
163
+ * outside it with no ttsc rule at all. That is the silent failure
164
+ * samchon/ttsc#1310 is about, and it is strictly worse than the double
165
+ * registration this guard exists to prevent: a module no loader ever sees fails
166
+ * at runtime, while a module transformed twice costs time.
167
+ *
168
+ * How little a scoped rule covers is worth stating from measurement rather than
169
+ * from the obvious guess, because the guess is wrong. Against Next.js 16.3.2,
170
+ * `src/*.ts` and `src/**` + `/*.ts` match **nothing at all** — not even the
171
+ * `src/` subtree they name — while `./src/*.ts`, `**` + `/src/*.ts` and a bare
172
+ * `nested-probe.ts` all match a file at `src/`. Declining every one of them is
173
+ * therefore even safer than "it only covers its subtree" implies
174
+ * (samchon/ttsc#1319).
175
+ *
176
+ * The answer comes from {@link PROJECT_WIDE_GLOBS}, an exact set of measured
177
+ * spellings, and that document explains why it is a set rather than a rule.
178
+ */
179
+ function matchesExtension(glob, extension) {
180
+ return PROJECT_WIDE_GLOBS.get(glob.trim())?.includes(extension) === true;
181
+ }
182
+ /**
183
+ * The exact glob spellings a real Turbopack build has shown to name every file
184
+ * with an extension, and which extensions each one covers.
185
+ *
186
+ * An allowlist rather than a predicate, because recognising a glob is a claim
187
+ * about Turbopack's matcher and every claim here has to be one somebody
188
+ * measured. A rule inferred from glob semantics kept being wrong in the silent
189
+ * direction: `{src/,}*.ts` contains a bare `*.ts` alternative and so must cover
190
+ * the project by any set-theoretic reading, yet Turbopack matches nothing with
191
+ * it, and recognising it suppressed this wrapper's rules in favour of a rule
192
+ * that transforms no file at all — samchon/ttsc#1310 caused by the guard meant
193
+ * to prevent it (samchon/ttsc#1319).
194
+ *
195
+ * The deeper problem was that a predicate is open-ended: it answers for every
196
+ * spelling anyone might write, including ones no build has ever driven.
197
+ * `*.{ts}` and `{,**` + `/}*.ts` were both accepted on that reasoning while
198
+ * nothing had checked whether Turbopack expands a single-alternative group or a
199
+ * leading empty one. An exact set cannot overreach, so an unmeasured spelling
200
+ * is simply not recognised, the wrapper adds its own rules, and the failure —
201
+ * if any — is a second registration rather than a module that no loader ever
202
+ * sees.
203
+ *
204
+ * `experimental/test-unplugin` drives every entry through `next build
205
+ * --turbopack` and asserts a nested `.ts`, a root-level `.ts` and a nested
206
+ * `.tsx` all came out transformed, and
207
+ * `test_next_adapter_does_not_double_register_across_globs` asserts these keys
208
+ * and that list are the same set, so an entry cannot be added here without a
209
+ * build proving it.
210
+ */
211
+ const PROJECT_WIDE_GLOBS = new Map([
212
+ ["*.ts", ["ts"]],
213
+ ["**/*.ts", ["ts"]],
214
+ ["{**/,}*.ts", ["ts"]],
215
+ ["*.tsx", ["tsx"]],
216
+ ["**/*.tsx", ["tsx"]],
217
+ ["*.{ts,tsx}", ["ts", "tsx"]],
218
+ ["{*.ts,*.tsx}", ["ts", "tsx"]],
219
+ ["**/*.{ts,tsx}", ["ts", "tsx"]],
220
+ ["**/{*.ts,*.tsx}", ["ts", "tsx"]],
221
+ ["**/**/*.{ts,tsx}", ["ts", "tsx"]],
222
+ ]);
223
+ /**
224
+ * Read the loader list out of one Turbopack rule.
225
+ *
226
+ * Turbopack accepts a bare array of loaders as well as the object form, and a
227
+ * loader is either a module name or a `{ loader, options }` pair, so this
228
+ * normalises only enough to answer "what is already here".
229
+ */
230
+ function selectTurbopackLoaders(rule) {
231
+ if (Array.isArray(rule)) {
232
+ return rule;
233
+ }
234
+ if (typeof rule === "object" && rule !== null) {
235
+ const loaders = rule.loaders;
236
+ if (Array.isArray(loaders)) {
237
+ return loaders;
238
+ }
239
+ }
240
+ return [];
241
+ }
242
+ /** Whether one Turbopack loader entry is already this package's loader. */
243
+ function referencesTtscLoader(loader) {
244
+ if (typeof loader === "string") {
245
+ return loader === TURBOPACK_LOADER;
246
+ }
247
+ return (typeof loader === "object" &&
248
+ loader !== null &&
249
+ loader.loader === TURBOPACK_LOADER);
250
+ }
30
251
 
31
252
  export { next as default };
32
253
  //# sourceMappingURL=next.mjs.map
package/lib/next.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"next.mjs","sources":["../src/next.ts"],"sourcesContent":[null],"names":[],"mappings":";;AA2BA;;;;;;;;;;;;AAYG;AACW,SAAU,IAAI,CAC1B,UAAA,GAA6B,EAAE,EAC/B,OAA6B,EAAA;IAE7B,OAAO;AACL,QAAA,GAAG,UAAU;QACb,OAAO,CAAC,MAAyB,EAAE,cAAuB,EAAA;YACxD,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,GAAG,EAAE;;YAEpE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AACxC,YAAA,IAAI,OAAO,UAAU,CAAC,OAAO,KAAK,UAAU,EAAE;gBAC5C,OAAO,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,cAAc,CAAC;YACnD;AACA,YAAA,OAAO,MAAM;QACf,CAAC;KACF;AACH;;;;"}
1
+ {"version":3,"file":"next.mjs","sources":["../src/next.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAGA;AACA,MAAM,gBAAgB,GAAG,0BAA0B;AACnD;;;;;;AAMG;AACH,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;AAqC9C;;;;;;;;;;;;;;;;;;;AAmBG;AACW,SAAU,IAAI,CAC1B,UAAA,GAA6B,EAAE,EAC/B,OAA6B,EAAA;IAE7B,gCAAgC,CAAC,UAAU,CAAC;IAC5C,OAAO;AACL,QAAA,GAAG,UAAU;QACb,SAAS,EAAE,sBAAsB,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,CAAC;QAChE,OAAO,CAAC,MAAyB,EAAE,cAAuB,EAAA;YACxD,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,GAAG,EAAE;;YAEpE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AACxC,YAAA,IAAI,OAAO,UAAU,CAAC,OAAO,KAAK,UAAU,EAAE;gBAC5C,OAAO,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,cAAc,CAAC;YACnD;AACA,YAAA,OAAO,MAAM;QACf,CAAC;KACF;AACH;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;AACH,SAAS,gCAAgC,CAAC,UAA0B,EAAA;AAClE,IAAA,IACE,OAAO,UAAU,CAAC,OAAO,KAAK,UAAU;AACxC,QAAA,UAAU,CAAC,SAAS,KAAK,SAAS,EAClC;QACA;IACF;AACA,IAAA,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,2EAA2E;QACzE,kEAAkE;QAClE,0EAA0E;QAC1E,kEAAkE;QAClE,uBAAuB;AACvB,QAAA,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAC1B;AACH;AAEA;;;;;;;;;AASG;AACH,SAAS,sBAAsB,CAC7B,QAAyC,EACzC,OAA6B,EAAA;AAE7B,IAAA,MAAM,KAAK,GAA4B,EAAE,IAAI,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE;AACrE,IAAA,KAAK,MAAM,IAAI,IAAI,oBAAoB,EAAE;AACvC,QAAA,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;AACxB,QAAA,MAAM,OAAO,GAAG,sBAAsB,CAAC,IAAI,CAAC;AAC5C,QAAA,IAAI,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE;YACtC;QACF;;;;;;AAMA,QAAA,IAAI,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE;YACrC;QACF;AACA,QAAA,MAAM,KAAK,GAAG,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE;;;;;;;;;QASlE,KAAK,CAAC,IAAI,CAAC;AACT,YAAA,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK;AACvC,kBAAE,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC;AACpB,kBAAE,KAAK,CAAC,OAAO,CAAC,IAAI;sBAChB,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC;AAChC,sBAAE,EAAE,GAAI,IAAe,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,EAAE;IAC/D;IACA,OAAO,EAAE,IAAI,QAAQ,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE;AACvC;AAEA;;;;;;;;;;;;AAYG;AACH,SAAS,oBAAoB,CAC3B,KAA8B,EAC9B,IAAY,EAAA;AAEZ,IAAA,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACvD,IAAA,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,KAAI;AACtD,QAAA,IAAI,SAAS,KAAK,IAAI,EAAE;AACtB,YAAA,OAAO,KAAK;QACd;QACA,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE;AAC5D,YAAA,OAAO,KAAK;QACd;AACA,QAAA,OAAO,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC;AAC/C,IAAA,CAAC,CAAC;AACJ;AAEA;;;;;;;;;;;;;;;;;;;;AAoBG;AACH,SAAS,gBAAgB,CAAC,IAAY,EAAE,SAAiB,EAAA;AACvD,IAAA,OAAO,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,KAAK,IAAI;AAC1E;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BG;AACH,MAAM,kBAAkB,GAA2C,IAAI,GAAG,CAAC;AACzE,IAAA,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;AAChB,IAAA,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC;AACnB,IAAA,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC;AACtB,IAAA,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;AAClB,IAAA,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC;AACrB,IAAA,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC7B,IAAA,CAAC,cAAc,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC/B,IAAA,CAAC,eAAe,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAChC,IAAA,CAAC,iBAAiB,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAClC,IAAA,CAAC,kBAAkB,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACpC,CAAA,CAAC;AAEF;;;;;;AAMG;AACH,SAAS,sBAAsB,CAAC,IAAa,EAAA;AAC3C,IAAA,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;AACvB,QAAA,OAAO,IAAI;IACb;IACA,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE;AAC7C,QAAA,MAAM,OAAO,GAAI,IAA8B,CAAC,OAAO;AACvD,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;AAC1B,YAAA,OAAO,OAAO;QAChB;IACF;AACA,IAAA,OAAO,EAAE;AACX;AAEA;AACA,SAAS,oBAAoB,CAAC,MAAe,EAAA;AAC3C,IAAA,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QAC9B,OAAO,MAAM,KAAK,gBAAgB;IACpC;AACA,IAAA,QACE,OAAO,MAAM,KAAK,QAAQ;AAC1B,QAAA,MAAM,KAAK,IAAI;AACd,QAAA,MAA+B,CAAC,MAAM,KAAK,gBAAgB;AAEhE;;;;"}
@@ -50,9 +50,10 @@ export interface TtscTurbopackLoaderContext {
50
50
  * ```
51
51
  *
52
52
  * Pass {@link TtscUnpluginOptions} through the rule's `options` object. The
53
- * loader returns the source unchanged for declaration files, `node_modules`
54
- * paths, and transforms that produce no change, mirroring the unplugin
55
- * adapters' `transformInclude` filter, since a broad rule glob routes
56
- * everything matching the extension through the loader.
53
+ * loader returns the source unchanged for anything {@link isTransformTarget}
54
+ * excludes declaration files, `node_modules` paths, non-TypeScript sources,
55
+ * and virtual ids and for transforms that produce no change. It applies that
56
+ * shared predicate itself rather than a local copy, because a broad rule glob
57
+ * routes everything matching the extension through the loader.
57
58
  */
58
59
  export default function turbopack(this: TtscTurbopackLoaderContext, source: string): void;
@@ -50,9 +50,10 @@ export interface TtscTurbopackLoaderContext {
50
50
  * ```
51
51
  *
52
52
  * Pass {@link TtscUnpluginOptions} through the rule's `options` object. The
53
- * loader returns the source unchanged for declaration files, `node_modules`
54
- * paths, and transforms that produce no change, mirroring the unplugin
55
- * adapters' `transformInclude` filter, since a broad rule glob routes
56
- * everything matching the extension through the loader.
53
+ * loader returns the source unchanged for anything {@link isTransformTarget}
54
+ * excludes declaration files, `node_modules` paths, non-TypeScript sources,
55
+ * and virtual ids and for transforms that produce no change. It applies that
56
+ * shared predicate itself rather than a local copy, because a broad rule glob
57
+ * routes everything matching the extension through the loader.
57
58
  */
58
59
  export default function turbopack(this: TtscTurbopackLoaderContext, source: string): void;
@@ -50,9 +50,10 @@ export interface TtscTurbopackLoaderContext {
50
50
  * ```
51
51
  *
52
52
  * Pass {@link TtscUnpluginOptions} through the rule's `options` object. The
53
- * loader returns the source unchanged for declaration files, `node_modules`
54
- * paths, and transforms that produce no change, mirroring the unplugin
55
- * adapters' `transformInclude` filter, since a broad rule glob routes
56
- * everything matching the extension through the loader.
53
+ * loader returns the source unchanged for anything {@link isTransformTarget}
54
+ * excludes declaration files, `node_modules` paths, non-TypeScript sources,
55
+ * and virtual ids and for transforms that produce no change. It applies that
56
+ * shared predicate itself rather than a local copy, because a broad rule glob
57
+ * routes everything matching the extension through the loader.
57
58
  */
58
59
  export default function turbopack(this: TtscTurbopackLoaderContext, source: string): void;
package/lib/turbopack.js CHANGED
@@ -2,11 +2,10 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var index = require('./core/index.js');
5
6
  var options = require('./core/options.js');
6
7
  var transform = require('./core/transform.js');
7
8
 
8
- /** Matches any path segment that is a `node_modules` directory (cross-platform). */
9
- const nodeModulesPattern = /(?:^|[/\\])node_modules(?:[/\\]|$)/;
10
9
  /**
11
10
  * Per-process transform cache. Turbopack runs loaders in a worker pool and
12
11
  * never signals build boundaries to a loader, so the cache lives for the
@@ -36,15 +35,22 @@ const transformCache = transform.createTtscTransformCache();
36
35
  * ```
37
36
  *
38
37
  * 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.
38
+ * loader returns the source unchanged for anything {@link isTransformTarget}
39
+ * excludes declaration files, `node_modules` paths, non-TypeScript sources,
40
+ * and virtual ids and for transforms that produce no change. It applies that
41
+ * shared predicate itself rather than a local copy, because a broad rule glob
42
+ * routes everything matching the extension through the loader.
43
43
  */
44
44
  function turbopack(source) {
45
45
  const callback = this.async();
46
46
  const file = transform.stripQuery(this.resourcePath);
47
- if (transform.isDeclarationFile(file) || nodeModulesPattern.test(file)) {
47
+ // The shared predicate itself, not a copy of part of it. A rule glob wider
48
+ // than `*.ts`/`*.tsx` — the natural thing to write for a project with mixed
49
+ // sources, and the reason a loader needs a filter at all — used to route
50
+ // JavaScript and virtual ids into the whole-project transform that every
51
+ // other adapter excludes, where the program has no entry for them and the
52
+ // delivery fails (samchon/ttsc#1305).
53
+ if (!index.isTransformTarget(file)) {
48
54
  callback(undefined, source);
49
55
  return;
50
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"turbopack.js","sources":["../src/turbopack.ts"],"sourcesContent":[null],"names":["createTtscTransformCache","stripQuery","isDeclarationFile","transformTtsc","resolveOptions"],"mappings":";;;;;;;AAyCA;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;;;;;;;;;IASA,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC;IACpD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;AAC5C,IAAA,MAAM,KAAK,GAAuB;AAChC,QAAA,IAAI,aAAa,KAAK,SAAS,GAAG,EAAE,GAAG,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;QACvE,IAAI,SAAS,KAAK;AAChB,cAAE;AACF,cAAE,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;KAC9C;AACD,IAAAC,uBAAa,CACX,IAAI,EACJ,MAAM,EACNC,sBAAc,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC,EACzC,SAAS,EACT,cAAc,EACd,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,SAAS,GAAG,KAAK,CACpD,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;;;;"}
1
+ {"version":3,"file":"turbopack.js","sources":["../src/turbopack.ts"],"sourcesContent":[null],"names":["createTtscTransformCache","stripQuery","isTransformTarget","transformTtsc","resolveOptions"],"mappings":";;;;;;;;AAyCA;;;;;;AAMG;AACH,MAAM,cAAc,GAAGA,kCAAwB,EAAE;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BG;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;;;;;;;AAO1C,IAAA,IAAI,CAACC,uBAAiB,CAAC,IAAI,CAAC,EAAE;AAC5B,QAAA,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B;IACF;;;;;;;;;IASA,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC;IACpD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;AAC5C,IAAA,MAAM,KAAK,GAAuB;AAChC,QAAA,IAAI,aAAa,KAAK,SAAS,GAAG,EAAE,GAAG,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;QACvE,IAAI,SAAS,KAAK;AAChB,cAAE;AACF,cAAE,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;KAC9C;AACD,IAAAC,uBAAa,CACX,IAAI,EACJ,MAAM,EACNC,sBAAc,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC,EACzC,SAAS,EACT,cAAc,EACd,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,SAAS,GAAG,KAAK,CACpD,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/lib/turbopack.mjs CHANGED
@@ -1,8 +1,7 @@
1
+ import { isTransformTarget } from './core/index.mjs';
1
2
  import { resolveOptions } from './core/options.mjs';
2
- import { createTtscTransformCache, stripQuery, isDeclarationFile, transformTtsc } from './core/transform.mjs';
3
+ import { createTtscTransformCache, stripQuery, transformTtsc } from './core/transform.mjs';
3
4
 
4
- /** Matches any path segment that is a `node_modules` directory (cross-platform). */
5
- const nodeModulesPattern = /(?:^|[/\\])node_modules(?:[/\\]|$)/;
6
5
  /**
7
6
  * Per-process transform cache. Turbopack runs loaders in a worker pool and
8
7
  * never signals build boundaries to a loader, so the cache lives for the
@@ -32,15 +31,22 @@ const transformCache = createTtscTransformCache();
32
31
  * ```
33
32
  *
34
33
  * 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.
34
+ * loader returns the source unchanged for anything {@link isTransformTarget}
35
+ * excludes declaration files, `node_modules` paths, non-TypeScript sources,
36
+ * and virtual ids and for transforms that produce no change. It applies that
37
+ * shared predicate itself rather than a local copy, because a broad rule glob
38
+ * routes everything matching the extension through the loader.
39
39
  */
40
40
  function turbopack(source) {
41
41
  const callback = this.async();
42
42
  const file = stripQuery(this.resourcePath);
43
- if (isDeclarationFile(file) || nodeModulesPattern.test(file)) {
43
+ // The shared predicate itself, not a copy of part of it. A rule glob wider
44
+ // than `*.ts`/`*.tsx` — the natural thing to write for a project with mixed
45
+ // sources, and the reason a loader needs a filter at all — used to route
46
+ // JavaScript and virtual ids into the whole-project transform that every
47
+ // other adapter excludes, where the program has no entry for them and the
48
+ // delivery fails (samchon/ttsc#1305).
49
+ if (!isTransformTarget(file)) {
44
50
  callback(undefined, source);
45
51
  return;
46
52
  }
@@ -1 +1 @@
1
- {"version":3,"file":"turbopack.mjs","sources":["../src/turbopack.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAyCA;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;;;;;;;;;IASA,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC;IACpD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;AAC5C,IAAA,MAAM,KAAK,GAAuB;AAChC,QAAA,IAAI,aAAa,KAAK,SAAS,GAAG,EAAE,GAAG,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;QACvE,IAAI,SAAS,KAAK;AAChB,cAAE;AACF,cAAE,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;KAC9C;AACD,IAAA,aAAa,CACX,IAAI,EACJ,MAAM,EACN,cAAc,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC,EACzC,SAAS,EACT,cAAc,EACd,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,SAAS,GAAG,KAAK,CACpD,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;;;;"}
1
+ {"version":3,"file":"turbopack.mjs","sources":["../src/turbopack.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAyCA;;;;;;AAMG;AACH,MAAM,cAAc,GAAG,wBAAwB,EAAE;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BG;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;;;;;;;AAO1C,IAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE;AAC5B,QAAA,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B;IACF;;;;;;;;;IASA,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC;IACpD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;AAC5C,IAAA,MAAM,KAAK,GAAuB;AAChC,QAAA,IAAI,aAAa,KAAK,SAAS,GAAG,EAAE,GAAG,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;QACvE,IAAI,SAAS,KAAK;AAChB,cAAE;AACF,cAAE,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;KAC9C;AACD,IAAA,aAAa,CACX,IAAI,EACJ,MAAM,EACN,cAAc,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC,EACzC,SAAS,EACT,cAAc,EACd,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,SAAS,GAAG,KAAK,CACpD,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.28.3",
3
+ "version": "0.28.5",
4
4
  "description": "Bundler adapters for ttsc plugins.",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/index.mjs",
@@ -199,7 +199,7 @@
199
199
  "unplugin": "^2.3.11"
200
200
  },
201
201
  "peerDependencies": {
202
- "ttsc": "^0.28.3"
202
+ "ttsc": "^0.28.5"
203
203
  },
204
204
  "devDependencies": {
205
205
  "@rollup/plugin-commonjs": "^29.0.2",
@@ -213,7 +213,7 @@
213
213
  "tslib": "^2.8.1",
214
214
  "typescript": "^7.0.2",
215
215
  "vite": "^7.3.5",
216
- "ttsc": "0.28.3"
216
+ "ttsc": "0.28.5"
217
217
  },
218
218
  "repository": {
219
219
  "type": "git",