@ttsc/unplugin 0.8.1 → 0.9.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 CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
  Bundler adapter for `ttsc` plugins.
13
13
 
14
- Use it when Vite, Rollup, esbuild, Webpack, Rspack, Next.js, Farm, or Bun should run the same `compilerOptions.plugins` entries that `ttsc` and `ttsx` use.
14
+ Use it when Vite, Rollup, esbuild, Webpack, Rspack, Next.js, Farm, or Bun owns the build but the project still needs `ttsc` plugins.
15
15
 
16
16
  ## Setup
17
17
 
@@ -150,7 +150,7 @@ await Bun.build({
150
150
 
151
151
  ## Configuration
152
152
 
153
- By default, `@ttsc/unplugin` finds the nearest `tsconfig.json` from the file being transformed and reads its existing `compilerOptions.plugins`.
153
+ By default, `@ttsc/unplugin` finds the nearest `tsconfig.json` from the file being transformed and uses that project's plugin settings, including directly installed plugin packages.
154
154
 
155
155
  If that is already the config you want, `ttsc()` is enough.
156
156
 
@@ -188,7 +188,10 @@ export default {
188
188
  transform: "@ttsc/lint",
189
189
  config: { "no-var": "error" },
190
190
  },
191
- { transform: "typia/lib/transform" },
191
+ {
192
+ transform: "typia/lib/transform",
193
+ finite: true,
194
+ },
192
195
  ],
193
196
  },
194
197
  }),
@@ -200,7 +203,7 @@ export default {
200
203
 
201
204
  ### Plugin Overrides
202
205
 
203
- Use the top-level `plugins` option inside `ttsc(...)` when the bundler should ignore the plugin list from `tsconfig.json`:
206
+ Use the top-level `plugins` option inside `ttsc(...)` when the bundler should use a different plugin list from `tsconfig.json`:
204
207
 
205
208
  ```ts
206
209
  import ttsc from "@ttsc/unplugin/vite";
@@ -217,11 +220,7 @@ export default {
217
220
  };
218
221
  ```
219
222
 
220
- Plugin resolution order:
221
-
222
- 1. `plugins` option.
223
- 2. `compilerOptions.plugins` option.
224
- 3. `compilerOptions.plugins` from `project` / discovered `tsconfig.json`.
223
+ Explicit adapter options override the plugin list read from the selected project config.
225
224
 
226
225
  Set `plugins: false` to run the adapter without loading project plugins.
227
226
 
package/lib/api.js CHANGED
@@ -1,12 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  var index = require('./core/index.js');
4
- var options = require('./core/options.js');
5
4
  var transform = require('./core/transform.js');
5
+ var options = require('./core/options.js');
6
6
 
7
7
 
8
8
 
9
9
  exports.unplugin = index.default;
10
- exports.resolveOptions = options.resolveOptions;
10
+ exports.createTtscTransformCache = transform.createTtscTransformCache;
11
11
  exports.transformTtsc = transform.transformTtsc;
12
+ exports.resolveOptions = options.resolveOptions;
12
13
  //# sourceMappingURL=api.js.map
package/lib/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
1
+ {"version":3,"file":"api.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;"}
package/lib/api.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  export { default as unplugin } from './core/index.mjs';
2
+ export { createTtscTransformCache, transformTtsc } from './core/transform.mjs';
2
3
  export { resolveOptions } from './core/options.mjs';
3
- export { transformTtsc } from './core/transform.mjs';
4
4
  //# sourceMappingURL=api.mjs.map
package/lib/bun.js CHANGED
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var fs = require('node:fs/promises');
6
6
  var index = require('./core/index.js');
7
7
 
8
- const sourceFilePattern = /\.[cm]?[jt]sx?$/;
8
+ const sourceFilePattern = /\.[cm]?tsx?$/;
9
9
  function bun(options) {
10
10
  return {
11
11
  name: "ttsc-unplugin",
package/lib/bun.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bun.js","sources":["../src/bun.ts"],"sourcesContent":[null],"names":["unplugin"],"mappings":";;;;;;;AAkBA,MAAM,iBAAiB,GAAG,iBAAiB;AAE7B,SAAU,GAAG,CAAC,OAA6B,EAAA;IACvD,OAAO;AACL,QAAA,IAAI,EAAE,eAAe;AACrB,QAAA,KAAK,CAAC,KAAK,EAAA;YACT,MAAM,GAAG,GAAGA,aAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,EAAyB,CAAC;AAC5D,YAAA,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,EAAE,OAAO,IAAI,KAAI;AACzD,gBAAA,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;AACnD,gBAAA,MAAM,MAAM,GACV,OAAO,GAAG,CAAC,SAAS,KAAK;AACvB,sBAAE,MAAM,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAW,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI;sBACvD,SAAS;AACf,gBAAA,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC9B,oBAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;gBAC7B;gBACA,IACE,OAAO,MAAM,KAAK,QAAQ;AAC1B,oBAAA,MAAM,KAAK,IAAI;AACf,oBAAA,MAAM,IAAI,MAAM;AAChB,oBAAA,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAC/B;AACA,oBAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE;gBAClC;AACA,gBAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;AAC7B,YAAA,CAAC,CAAC;QACJ,CAAC;KACF;AACH;;;;"}
1
+ {"version":3,"file":"bun.js","sources":["../src/bun.ts"],"sourcesContent":[null],"names":["unplugin"],"mappings":";;;;;;;AAkBA,MAAM,iBAAiB,GAAG,cAAc;AAE1B,SAAU,GAAG,CAAC,OAA6B,EAAA;IACvD,OAAO;AACL,QAAA,IAAI,EAAE,eAAe;AACrB,QAAA,KAAK,CAAC,KAAK,EAAA;YACT,MAAM,GAAG,GAAGA,aAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,EAAyB,CAAC;AAC5D,YAAA,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,EAAE,OAAO,IAAI,KAAI;AACzD,gBAAA,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;AACnD,gBAAA,MAAM,MAAM,GACV,OAAO,GAAG,CAAC,SAAS,KAAK;AACvB,sBAAE,MAAM,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAW,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI;sBACvD,SAAS;AACf,gBAAA,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC9B,oBAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;gBAC7B;gBACA,IACE,OAAO,MAAM,KAAK,QAAQ;AAC1B,oBAAA,MAAM,KAAK,IAAI;AACf,oBAAA,MAAM,IAAI,MAAM;AAChB,oBAAA,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAC/B;AACA,oBAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE;gBAClC;AACA,gBAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;AAC7B,YAAA,CAAC,CAAC;QACJ,CAAC;KACF;AACH;;;;"}
package/lib/bun.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import unplugin from './core/index.mjs';
3
3
 
4
- const sourceFilePattern = /\.[cm]?[jt]sx?$/;
4
+ const sourceFilePattern = /\.[cm]?tsx?$/;
5
5
  function bun(options) {
6
6
  return {
7
7
  name: "ttsc-unplugin",
package/lib/bun.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bun.mjs","sources":["../src/bun.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAkBA,MAAM,iBAAiB,GAAG,iBAAiB;AAE7B,SAAU,GAAG,CAAC,OAA6B,EAAA;IACvD,OAAO;AACL,QAAA,IAAI,EAAE,eAAe;AACrB,QAAA,KAAK,CAAC,KAAK,EAAA;YACT,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,EAAyB,CAAC;AAC5D,YAAA,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,EAAE,OAAO,IAAI,KAAI;AACzD,gBAAA,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;AACnD,gBAAA,MAAM,MAAM,GACV,OAAO,GAAG,CAAC,SAAS,KAAK;AACvB,sBAAE,MAAM,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAW,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI;sBACvD,SAAS;AACf,gBAAA,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC9B,oBAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;gBAC7B;gBACA,IACE,OAAO,MAAM,KAAK,QAAQ;AAC1B,oBAAA,MAAM,KAAK,IAAI;AACf,oBAAA,MAAM,IAAI,MAAM;AAChB,oBAAA,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAC/B;AACA,oBAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE;gBAClC;AACA,gBAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;AAC7B,YAAA,CAAC,CAAC;QACJ,CAAC;KACF;AACH;;;;"}
1
+ {"version":3,"file":"bun.mjs","sources":["../src/bun.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAkBA,MAAM,iBAAiB,GAAG,cAAc;AAE1B,SAAU,GAAG,CAAC,OAA6B,EAAA;IACvD,OAAO;AACL,QAAA,IAAI,EAAE,eAAe;AACrB,QAAA,KAAK,CAAC,KAAK,EAAA;YACT,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,EAAyB,CAAC;AAC5D,YAAA,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,EAAE,OAAO,IAAI,KAAI;AACzD,gBAAA,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;AACnD,gBAAA,MAAM,MAAM,GACV,OAAO,GAAG,CAAC,SAAS,KAAK;AACvB,sBAAE,MAAM,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAW,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI;sBACvD,SAAS;AACf,gBAAA,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC9B,oBAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;gBAC7B;gBACA,IACE,OAAO,MAAM,KAAK,QAAQ;AAC1B,oBAAA,MAAM,KAAK,IAAI;AACf,oBAAA,MAAM,IAAI,MAAM;AAChB,oBAAA,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAC/B;AACA,oBAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE;gBAClC;AACA,gBAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;AAC7B,YAAA,CAAC,CAAC;QACJ,CAAC;KACF;AACH;;;;"}
@@ -1,8 +1,8 @@
1
1
  import type { UnpluginInstance } from "unplugin";
2
2
  import type { TtscUnpluginOptions } from "./options";
3
3
  import { resolveOptions } from "./options";
4
- import { transformTtsc } from "./transform";
4
+ import { createTtscTransformCache, transformTtsc } from "./transform";
5
5
  declare const unplugin: UnpluginInstance<TtscUnpluginOptions | undefined, false>;
6
6
  export type { TtscUnpluginCompilerOptionsJson, TtscUnpluginOptions, } from "./options";
7
- export { resolveOptions, transformTtsc, unplugin };
7
+ export { createTtscTransformCache, resolveOptions, transformTtsc, unplugin };
8
8
  export default unplugin;
package/lib/core/index.js CHANGED
@@ -7,11 +7,12 @@ var options = require('./options.js');
7
7
  var transform = require('./transform.js');
8
8
 
9
9
  const name = "ttsc-unplugin";
10
- const sourceFilePattern = /\.[cm]?[jt]sx?$/;
10
+ const sourceFilePattern = /\.[cm]?tsx?$/;
11
11
  const nodeModulesPattern = /(?:^|[/\\])node_modules(?:[/\\]|$)/;
12
12
  const virtualModulePattern = /\0/;
13
13
  const unpluginFactory = (rawOptions = {}) => {
14
14
  const options$1 = options.resolveOptions(rawOptions);
15
+ const transformCache = transform.createTtscTransformCache();
15
16
  let aliases;
16
17
  return {
17
18
  name,
@@ -21,6 +22,9 @@ const unpluginFactory = (rawOptions = {}) => {
21
22
  aliases = config.resolve.alias;
22
23
  },
23
24
  },
25
+ buildStart() {
26
+ transformCache.clear();
27
+ },
24
28
  transformInclude(id) {
25
29
  const file = transform.stripQuery(id);
26
30
  return isTransformTarget(file);
@@ -30,7 +34,7 @@ const unpluginFactory = (rawOptions = {}) => {
30
34
  if (!isTransformTarget(file)) {
31
35
  return undefined;
32
36
  }
33
- return transform.transformTtsc(file, source, options$1, aliases);
37
+ return transform.transformTtsc(file, source, options$1, aliases, transformCache);
34
38
  },
35
39
  };
36
40
  };
@@ -43,6 +47,7 @@ function isTransformTarget(id) {
43
47
  }
44
48
 
45
49
  exports.resolveOptions = options.resolveOptions;
50
+ exports.createTtscTransformCache = transform.createTtscTransformCache;
46
51
  exports.transformTtsc = transform.transformTtsc;
47
52
  exports.default = unplugin;
48
53
  exports.unplugin = unplugin;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/core/index.ts"],"sourcesContent":[null],"names":["options","resolveOptions","stripQuery","transformTtsc","createUnplugin","isDeclarationFile"],"mappings":";;;;;;;;AAOA,MAAM,IAAI,GAAG,eAAe;AAC5B,MAAM,iBAAiB,GAAG,iBAAiB;AAC3C,MAAM,kBAAkB,GAAG,oCAAoC;AAC/D,MAAM,oBAAoB,GAAG,IAAI;AAEjC,MAAM,eAAe,GAGjB,CAAC,UAAU,GAAG,EAAE,KAAI;AACtB,IAAA,MAAMA,SAAO,GAAGC,sBAAc,CAAC,UAAU,CAAC;AAC1C,IAAA,IAAI,OAAgB;IAEpB,OAAO;QACL,IAAI;AACJ,QAAA,OAAO,EAAE,KAAK;AAEd,QAAA,IAAI,EAAE;AACJ,YAAA,cAAc,CAAC,MAAM,EAAA;AACnB,gBAAA,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK;YAChC,CAAC;AACF,SAAA;AAED,QAAA,gBAAgB,CAAC,EAAE,EAAA;AACjB,YAAA,MAAM,IAAI,GAAGC,oBAAU,CAAC,EAAE,CAAC;AAC3B,YAAA,OAAO,iBAAiB,CAAC,IAAI,CAAC;QAChC,CAAC;AAED,QAAA,MAAM,SAAS,CAAC,MAAM,EAAE,EAAE,EAAA;AACxB,YAAA,MAAM,IAAI,GAAGA,oBAAU,CAAC,EAAE,CAAC;AAC3B,YAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE;AAC5B,gBAAA,OAAO,SAAS;YAClB;YACA,OAAOC,uBAAa,CAAC,IAAI,EAAE,MAAM,EAAEH,SAAO,EAAE,OAAO,CAAC;QACtD,CAAC;KACF;AACH,CAAC;AAED,MAAM,QAAQ,GACZI,yBAAc,CAAC,eAAe;AAUhC,SAAS,iBAAiB,CAAC,EAAU,EAAA;AACnC,IAAA,QACE,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1B,QAAA,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,CAACC,2BAAiB,CAAC,EAAE,CAAC;AACtB,QAAA,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;AAEhC;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/core/index.ts"],"sourcesContent":[null],"names":["options","resolveOptions","createTtscTransformCache","stripQuery","transformTtsc","createUnplugin","isDeclarationFile"],"mappings":";;;;;;;;AAYA,MAAM,IAAI,GAAG,eAAe;AAC5B,MAAM,iBAAiB,GAAG,cAAc;AACxC,MAAM,kBAAkB,GAAG,oCAAoC;AAC/D,MAAM,oBAAoB,GAAG,IAAI;AAEjC,MAAM,eAAe,GAGjB,CAAC,UAAU,GAAG,EAAE,KAAI;AACtB,IAAA,MAAMA,SAAO,GAAGC,sBAAc,CAAC,UAAU,CAAC;AAC1C,IAAA,MAAM,cAAc,GAAGC,kCAAwB,EAAE;AACjD,IAAA,IAAI,OAAgB;IAEpB,OAAO;QACL,IAAI;AACJ,QAAA,OAAO,EAAE,KAAK;AAEd,QAAA,IAAI,EAAE;AACJ,YAAA,cAAc,CAAC,MAAM,EAAA;AACnB,gBAAA,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK;YAChC,CAAC;AACF,SAAA;QAED,UAAU,GAAA;YACR,cAAc,CAAC,KAAK,EAAE;QACxB,CAAC;AAED,QAAA,gBAAgB,CAAC,EAAE,EAAA;AACjB,YAAA,MAAM,IAAI,GAAGC,oBAAU,CAAC,EAAE,CAAC;AAC3B,YAAA,OAAO,iBAAiB,CAAC,IAAI,CAAC;QAChC,CAAC;AAED,QAAA,MAAM,SAAS,CAAC,MAAM,EAAE,EAAE,EAAA;AACxB,YAAA,MAAM,IAAI,GAAGA,oBAAU,CAAC,EAAE,CAAC;AAC3B,YAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE;AAC5B,gBAAA,OAAO,SAAS;YAClB;AACA,YAAA,OAAOC,uBAAa,CAAC,IAAI,EAAE,MAAM,EAAEJ,SAAO,EAAE,OAAO,EAAE,cAAc,CAAC;QACtE,CAAC;KACF;AACH,CAAC;AAED,MAAM,QAAQ,GACZK,yBAAc,CAAC,eAAe;AAUhC,SAAS,iBAAiB,CAAC,EAAU,EAAA;AACnC,IAAA,QACE,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1B,QAAA,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,CAACC,2BAAiB,CAAC,EAAE,CAAC;AACtB,QAAA,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;AAEhC;;;;;;;;"}
@@ -1,13 +1,14 @@
1
1
  import { createUnplugin } from 'unplugin';
2
2
  import { resolveOptions } from './options.mjs';
3
- import { stripQuery, transformTtsc, isDeclarationFile } from './transform.mjs';
3
+ import { stripQuery, transformTtsc, isDeclarationFile, createTtscTransformCache } from './transform.mjs';
4
4
 
5
5
  const name = "ttsc-unplugin";
6
- const sourceFilePattern = /\.[cm]?[jt]sx?$/;
6
+ const sourceFilePattern = /\.[cm]?tsx?$/;
7
7
  const nodeModulesPattern = /(?:^|[/\\])node_modules(?:[/\\]|$)/;
8
8
  const virtualModulePattern = /\0/;
9
9
  const unpluginFactory = (rawOptions = {}) => {
10
10
  const options = resolveOptions(rawOptions);
11
+ const transformCache = createTtscTransformCache();
11
12
  let aliases;
12
13
  return {
13
14
  name,
@@ -17,6 +18,9 @@ const unpluginFactory = (rawOptions = {}) => {
17
18
  aliases = config.resolve.alias;
18
19
  },
19
20
  },
21
+ buildStart() {
22
+ transformCache.clear();
23
+ },
20
24
  transformInclude(id) {
21
25
  const file = stripQuery(id);
22
26
  return isTransformTarget(file);
@@ -26,7 +30,7 @@ const unpluginFactory = (rawOptions = {}) => {
26
30
  if (!isTransformTarget(file)) {
27
31
  return undefined;
28
32
  }
29
- return transformTtsc(file, source, options, aliases);
33
+ return transformTtsc(file, source, options, aliases, transformCache);
30
34
  },
31
35
  };
32
36
  };
@@ -38,5 +42,5 @@ function isTransformTarget(id) {
38
42
  !nodeModulesPattern.test(id));
39
43
  }
40
44
 
41
- export { unplugin as default, resolveOptions, transformTtsc, unplugin };
45
+ export { createTtscTransformCache, unplugin as default, resolveOptions, transformTtsc, unplugin };
42
46
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../src/core/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAOA,MAAM,IAAI,GAAG,eAAe;AAC5B,MAAM,iBAAiB,GAAG,iBAAiB;AAC3C,MAAM,kBAAkB,GAAG,oCAAoC;AAC/D,MAAM,oBAAoB,GAAG,IAAI;AAEjC,MAAM,eAAe,GAGjB,CAAC,UAAU,GAAG,EAAE,KAAI;AACtB,IAAA,MAAM,OAAO,GAAG,cAAc,CAAC,UAAU,CAAC;AAC1C,IAAA,IAAI,OAAgB;IAEpB,OAAO;QACL,IAAI;AACJ,QAAA,OAAO,EAAE,KAAK;AAEd,QAAA,IAAI,EAAE;AACJ,YAAA,cAAc,CAAC,MAAM,EAAA;AACnB,gBAAA,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK;YAChC,CAAC;AACF,SAAA;AAED,QAAA,gBAAgB,CAAC,EAAE,EAAA;AACjB,YAAA,MAAM,IAAI,GAAG,UAAU,CAAC,EAAE,CAAC;AAC3B,YAAA,OAAO,iBAAiB,CAAC,IAAI,CAAC;QAChC,CAAC;AAED,QAAA,MAAM,SAAS,CAAC,MAAM,EAAE,EAAE,EAAA;AACxB,YAAA,MAAM,IAAI,GAAG,UAAU,CAAC,EAAE,CAAC;AAC3B,YAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE;AAC5B,gBAAA,OAAO,SAAS;YAClB;YACA,OAAO,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;QACtD,CAAC;KACF;AACH,CAAC;AAED,MAAM,QAAQ,GACZ,cAAc,CAAC,eAAe;AAUhC,SAAS,iBAAiB,CAAC,EAAU,EAAA;AACnC,IAAA,QACE,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1B,QAAA,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,CAAC,iBAAiB,CAAC,EAAE,CAAC;AACtB,QAAA,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;AAEhC;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":["../../src/core/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAYA,MAAM,IAAI,GAAG,eAAe;AAC5B,MAAM,iBAAiB,GAAG,cAAc;AACxC,MAAM,kBAAkB,GAAG,oCAAoC;AAC/D,MAAM,oBAAoB,GAAG,IAAI;AAEjC,MAAM,eAAe,GAGjB,CAAC,UAAU,GAAG,EAAE,KAAI;AACtB,IAAA,MAAM,OAAO,GAAG,cAAc,CAAC,UAAU,CAAC;AAC1C,IAAA,MAAM,cAAc,GAAG,wBAAwB,EAAE;AACjD,IAAA,IAAI,OAAgB;IAEpB,OAAO;QACL,IAAI;AACJ,QAAA,OAAO,EAAE,KAAK;AAEd,QAAA,IAAI,EAAE;AACJ,YAAA,cAAc,CAAC,MAAM,EAAA;AACnB,gBAAA,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK;YAChC,CAAC;AACF,SAAA;QAED,UAAU,GAAA;YACR,cAAc,CAAC,KAAK,EAAE;QACxB,CAAC;AAED,QAAA,gBAAgB,CAAC,EAAE,EAAA;AACjB,YAAA,MAAM,IAAI,GAAG,UAAU,CAAC,EAAE,CAAC;AAC3B,YAAA,OAAO,iBAAiB,CAAC,IAAI,CAAC;QAChC,CAAC;AAED,QAAA,MAAM,SAAS,CAAC,MAAM,EAAE,EAAE,EAAA;AACxB,YAAA,MAAM,IAAI,GAAG,UAAU,CAAC,EAAE,CAAC;AAC3B,YAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE;AAC5B,gBAAA,OAAO,SAAS;YAClB;AACA,YAAA,OAAO,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC;QACtE,CAAC;KACF;AACH,CAAC;AAED,MAAM,QAAQ,GACZ,cAAc,CAAC,eAAe;AAUhC,SAAS,iBAAiB,CAAC,EAAU,EAAA;AACnC,IAAA,QACE,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1B,QAAA,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,CAAC,iBAAiB,CAAC,EAAE,CAAC;AACtB,QAAA,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;AAEhC;;;;"}
@@ -18,9 +18,9 @@ export interface TtscUnpluginOptions {
18
18
  /**
19
19
  * `ttsc` plugin entries.
20
20
  *
21
- * `undefined` reads `compilerOptions.plugins` from the project config,
22
- * `false` disables project plugins, and an array overrides the project
23
- * plugin list.
21
+ * `undefined` reads project plugins from `compilerOptions.plugins` and
22
+ * directly installed package markers, `false` disables project plugins, and
23
+ * an array overrides the project plugin list.
24
24
  */
25
25
  plugins?: readonly ITtscProjectPluginConfig[] | false;
26
26
  }
@@ -1,3 +1,4 @@
1
+ import type { ITtscCompilerTransformation } from "ttsc";
1
2
  import type { TransformResult } from "unplugin";
2
3
  import type { ResolvedTtscUnpluginOptions } from "./options";
3
4
  export type TtscTransformResult = Exclude<TransformResult, string | null | undefined>;
@@ -5,7 +6,14 @@ export interface TtscTransformAlias {
5
6
  find: string | RegExp;
6
7
  replacement: string;
7
8
  }
8
- export declare function transformTtsc(id: string, source: string, options: ResolvedTtscUnpluginOptions, aliases?: unknown): Promise<TtscTransformResult | undefined>;
9
+ export interface TtscCachedProjectTransform {
10
+ inputHashes: Record<string, string>;
11
+ projectRoot: string;
12
+ result: ITtscCompilerTransformation;
13
+ }
14
+ export type TtscTransformCache = Map<string, Promise<TtscCachedProjectTransform>>;
15
+ export declare function createTtscTransformCache(): TtscTransformCache;
16
+ export declare function transformTtsc(id: string, source: string, options: ResolvedTtscUnpluginOptions, aliases?: unknown, cache?: TtscTransformCache): Promise<TtscTransformResult | undefined>;
9
17
  export declare function stripQuery(id: string): string;
10
18
  export declare function isDeclarationFile(id: string): boolean;
11
- export declare function createTransformResult(source: string, code: string, id: string): TtscTransformResult | undefined;
19
+ export declare function createTransformResult(source: string, code: string): TtscTransformResult | undefined;
@@ -1,31 +1,15 @@
1
1
  'use strict';
2
2
 
3
- var Diff = require('diff-match-patch-es');
4
3
  var fs = require('node:fs');
4
+ var crypto = require('node:crypto');
5
+ var os = require('node:os');
5
6
  var path = require('node:path');
6
- var MagicString = require('magic-string');
7
7
  var ttsc = require('ttsc');
8
8
 
9
- function _interopNamespaceDefault(e) {
10
- var n = Object.create(null);
11
- if (e) {
12
- Object.keys(e).forEach(function (k) {
13
- if (k !== 'default') {
14
- var d = Object.getOwnPropertyDescriptor(e, k);
15
- Object.defineProperty(n, k, d.get ? d : {
16
- enumerable: true,
17
- get: function () { return e[k]; }
18
- });
19
- }
20
- });
21
- }
22
- n.default = e;
23
- return Object.freeze(n);
9
+ function createTtscTransformCache() {
10
+ return new Map();
24
11
  }
25
-
26
- var Diff__namespace = /*#__PURE__*/_interopNamespaceDefault(Diff);
27
-
28
- async function transformTtsc(id, source, options, aliases) {
12
+ async function transformTtsc(id, source, options, aliases, cache) {
29
13
  const clean = stripQuery(id);
30
14
  if (clean.includes("\0")) {
31
15
  return undefined;
@@ -38,29 +22,43 @@ async function transformTtsc(id, source, options, aliases) {
38
22
  const tsconfigDir = path.dirname(tsconfig);
39
23
  const baseUrl = resolveBaseUrl(tsconfigDir, options.compilerOptions);
40
24
  const aliasPaths = createAliasPaths(baseUrl, aliases);
41
- const configured = createTransformTsconfig({
25
+ const key = createTransformCacheKey({
42
26
  aliasPaths,
43
- baseUrl,
44
27
  compilerOptions: options.compilerOptions,
28
+ plugins: options.plugins,
45
29
  tsconfig,
46
30
  });
47
- try {
48
- const effectiveTsconfig = configured.path;
49
- const result = new ttsc.TtscCompiler({
50
- cwd: path.dirname(effectiveTsconfig),
31
+ let transformed = cache?.get(key);
32
+ if (transformed !== undefined) {
33
+ const cached = await transformed;
34
+ if (matchesCachedSource(cached, file, source)) {
35
+ reportSuccessDiagnostics(cached.result);
36
+ const code = selectTransformedSource({
37
+ file,
38
+ projectRoot: cached.projectRoot,
39
+ result: cached.result,
40
+ });
41
+ return createTransformResult(source, code);
42
+ }
43
+ cache?.delete(key);
44
+ transformed = undefined;
45
+ }
46
+ if (transformed === undefined) {
47
+ transformed = transformProject({
48
+ aliasPaths,
49
+ baseUrl,
50
+ compilerOptions: options.compilerOptions,
51
+ currentFile: file,
52
+ currentSource: source,
51
53
  plugins: options.plugins,
52
- tsconfig: effectiveTsconfig,
53
- }).transform();
54
- const code = selectTransformedSource({
55
- file,
56
- projectRoot: path.dirname(effectiveTsconfig),
57
- result,
54
+ tsconfig,
58
55
  });
59
- return createTransformResult(source, code, file);
60
- }
61
- finally {
62
- configured.dispose();
56
+ cache?.set(key, transformed);
63
57
  }
58
+ const { projectRoot, result } = await transformed;
59
+ reportSuccessDiagnostics(result);
60
+ const code = selectTransformedSource({ file, projectRoot, result });
61
+ return createTransformResult(source, code);
64
62
  }
65
63
  function stripQuery(id) {
66
64
  const query = id.search(/[?#]/);
@@ -72,70 +70,184 @@ function stripQuery(id) {
72
70
  function isDeclarationFile(id) {
73
71
  return id.endsWith(".d.ts") || id.endsWith(".d.mts") || id.endsWith(".d.cts");
74
72
  }
75
- function createTransformResult(source, code, id) {
73
+ function createTransformResult(source, code) {
76
74
  if (source === code) {
77
75
  return undefined;
78
76
  }
79
- const magic = new MagicString(source);
80
- const diff = Diff__namespace.diff(source, code);
81
- Diff__namespace.diffCleanupSemantic(diff);
82
- let offset = 0;
83
- for (let index = 0; index < diff.length; index += 1) {
84
- const [type, text] = diff[index];
85
- if (type === 0) {
86
- offset += text.length;
87
- continue;
77
+ return { code };
78
+ }
79
+ function matchesCachedSource(cached, file, source) {
80
+ const currentKey = toProjectKey(cached.projectRoot, file);
81
+ const currentHashes = collectProjectInputHashes(cached.projectRoot);
82
+ currentHashes[currentKey] = hashText(source);
83
+ return sameHashes(cached.inputHashes, currentHashes);
84
+ }
85
+ function collectInputHashes(props) {
86
+ const hashes = collectProjectInputHashes(props.projectRoot);
87
+ if (props.result.type !== "exception") {
88
+ for (const key of Object.keys(props.result.typescript)) {
89
+ const file = path.resolve(props.projectRoot, key);
90
+ try {
91
+ hashes[key] = hashText(fs.readFileSync(file, "utf8"));
92
+ }
93
+ catch {
94
+ // A plugin may synthesize a virtual TypeScript file. It should not
95
+ // decide cache reuse for real source files.
96
+ }
88
97
  }
89
- if (type === 1) {
90
- magic.prependLeft(offset, text);
91
- continue;
98
+ }
99
+ hashes[toProjectKey(props.projectRoot, props.currentFile)] = hashText(props.currentSource);
100
+ return hashes;
101
+ }
102
+ function collectProjectInputHashes(projectRoot) {
103
+ const hashes = {};
104
+ for (const file of listProjectInputFiles(projectRoot)) {
105
+ try {
106
+ hashes[toProjectKey(projectRoot, file)] = hashText(fs.readFileSync(file));
92
107
  }
93
- const next = diff[index + 1];
94
- if (next?.[0] === 1) {
95
- magic.update(offset, offset + text.length, next[1]);
96
- index += 1;
108
+ catch {
109
+ // File watchers may observe a transform while another process is moving
110
+ // or deleting files. The missing key invalidates older cache entries.
97
111
  }
98
- else {
99
- magic.remove(offset, offset + text.length);
112
+ }
113
+ return hashes;
114
+ }
115
+ function listProjectInputFiles(root) {
116
+ const out = [];
117
+ const stack = [root];
118
+ while (stack.length !== 0) {
119
+ const current = stack.pop();
120
+ let entries;
121
+ try {
122
+ entries = fs.readdirSync(current, { withFileTypes: true });
123
+ }
124
+ catch {
125
+ continue;
126
+ }
127
+ for (const entry of entries) {
128
+ if (isIgnoredProjectDirectory(entry.name)) {
129
+ continue;
130
+ }
131
+ const file = path.join(current, entry.name);
132
+ if (entry.isDirectory()) {
133
+ stack.push(file);
134
+ }
135
+ else if (entry.isFile()) {
136
+ out.push(file);
137
+ }
100
138
  }
101
- offset += text.length;
102
139
  }
103
- if (!magic.hasChanged()) {
104
- return undefined;
140
+ out.sort();
141
+ return out;
142
+ }
143
+ function isIgnoredProjectDirectory(name) {
144
+ return (name === ".git" ||
145
+ name === ".ttsc" ||
146
+ name === ".cache" ||
147
+ name === ".next" ||
148
+ name === ".nuxt" ||
149
+ name === ".svelte-kit" ||
150
+ name === ".turbo" ||
151
+ name === ".vite" ||
152
+ name === "build" ||
153
+ name === "coverage" ||
154
+ name === "dist" ||
155
+ name === "node_modules" ||
156
+ name === "out" ||
157
+ name === "temp" ||
158
+ name === "tmp");
159
+ }
160
+ function sameHashes(left, right) {
161
+ const leftKeys = Object.keys(left);
162
+ const rightKeys = Object.keys(right);
163
+ if (leftKeys.length !== rightKeys.length) {
164
+ return false;
165
+ }
166
+ return leftKeys.every((key) => right[key] === left[key]);
167
+ }
168
+ function hashText(input) {
169
+ return crypto.createHash("sha256").update(input).digest("hex");
170
+ }
171
+ async function transformProject(props) {
172
+ const configured = createTransformTsconfig(props);
173
+ const projectRoot = path.dirname(props.tsconfig);
174
+ try {
175
+ const result = new ttsc.TtscCompiler({
176
+ cwd: projectRoot,
177
+ plugins: props.plugins,
178
+ projectRoot,
179
+ tsconfig: configured.path,
180
+ }).transform();
181
+ return {
182
+ inputHashes: collectInputHashes({
183
+ currentFile: props.currentFile,
184
+ currentSource: props.currentSource,
185
+ projectRoot,
186
+ result,
187
+ }),
188
+ projectRoot,
189
+ result,
190
+ };
191
+ }
192
+ finally {
193
+ configured.dispose();
105
194
  }
106
- return {
107
- code: magic.toString(),
108
- map: magic.generateMap({
109
- file: `${id}.map`,
110
- includeContent: true,
111
- source: id,
112
- }),
113
- };
114
195
  }
115
196
  function createTransformTsconfig(props) {
116
- const compilerOptions = {
197
+ const compilerOptions = normalizeCompilerOptionsForGeneratedTsconfig({
117
198
  ...props.compilerOptions,
118
199
  ...createAliasCompilerOptions(props),
119
- };
200
+ }, path.dirname(props.tsconfig));
120
201
  if (Object.keys(compilerOptions).length === 0) {
121
202
  return {
122
203
  path: props.tsconfig,
123
204
  dispose: () => undefined,
124
205
  };
125
206
  }
126
- const directory = path.dirname(props.tsconfig);
127
- const file = path.join(directory, `.ttsc-unplugin-${process.pid}-${Date.now()}-${Math.random()
128
- .toString(36)
129
- .slice(2)}.json`);
207
+ const directory = fs.mkdtempSync(path.join(os.tmpdir(), "ttsc-unplugin-"));
208
+ const file = path.join(directory, "tsconfig.json");
130
209
  fs.writeFileSync(file, JSON.stringify({
131
- extends: `./${path.basename(props.tsconfig)}`,
210
+ extends: normalizePath(props.tsconfig),
132
211
  compilerOptions,
133
212
  }, null, 2), "utf8");
134
213
  return {
135
214
  path: file,
136
- dispose: () => fs.rmSync(file, { force: true }),
215
+ dispose: () => fs.rmSync(directory, { force: true, recursive: true }),
137
216
  };
138
217
  }
218
+ function normalizeCompilerOptionsForGeneratedTsconfig(compilerOptions, tsconfigDir) {
219
+ const output = { ...compilerOptions };
220
+ for (const key of ["baseUrl", "declarationDir", "outDir", "rootDir"]) {
221
+ if (typeof output[key] === "string") {
222
+ output[key] = path.resolve(tsconfigDir, output[key]);
223
+ }
224
+ }
225
+ for (const key of ["rootDirs", "typeRoots"]) {
226
+ if (Array.isArray(output[key])) {
227
+ output[key] = output[key].map((entry) => typeof entry === "string" ? path.resolve(tsconfigDir, entry) : entry);
228
+ }
229
+ }
230
+ if (hasPaths(output.paths) && typeof output.baseUrl !== "string") {
231
+ output.baseUrl = tsconfigDir;
232
+ }
233
+ if (Array.isArray(output.plugins)) {
234
+ output.plugins = output.plugins.map((entry) => normalizePluginConfigForGeneratedTsconfig(entry, tsconfigDir));
235
+ }
236
+ return output;
237
+ }
238
+ function normalizePluginConfigForGeneratedTsconfig(entry, tsconfigDir) {
239
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
240
+ return entry;
241
+ }
242
+ const output = { ...entry };
243
+ for (const key of ["config", "source", "transform"]) {
244
+ const value = output[key];
245
+ if (typeof value === "string" && isRelativeSpecifier(value)) {
246
+ output[key] = path.resolve(tsconfigDir, value);
247
+ }
248
+ }
249
+ return output;
250
+ }
139
251
  function createAliasCompilerOptions(props) {
140
252
  if (Object.keys(props.aliasPaths).length === 0) {
141
253
  return {};
@@ -148,6 +260,12 @@ function createAliasCompilerOptions(props) {
148
260
  },
149
261
  };
150
262
  }
263
+ function hasPaths(value) {
264
+ return (typeof value === "object" &&
265
+ value !== null &&
266
+ !Array.isArray(value) &&
267
+ Object.keys(value).length !== 0);
268
+ }
151
269
  function readPaths(value) {
152
270
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
153
271
  return {};
@@ -207,6 +325,34 @@ function normalizeAliases(aliases) {
207
325
  }
208
326
  return [];
209
327
  }
328
+ function createTransformCacheKey(props) {
329
+ return stableStringify({
330
+ aliasPaths: props.aliasPaths,
331
+ compilerOptions: props.compilerOptions,
332
+ plugins: props.plugins,
333
+ tsconfig: path.resolve(props.tsconfig),
334
+ });
335
+ }
336
+ function stableStringify(value) {
337
+ if (Array.isArray(value)) {
338
+ return `[${value.map(stableStringify).join(",")}]`;
339
+ }
340
+ if (value && typeof value === "object") {
341
+ return `{${Object.entries(value)
342
+ .sort(([a], [b]) => a.localeCompare(b))
343
+ .map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`)
344
+ .join(",")}}`;
345
+ }
346
+ return JSON.stringify(value);
347
+ }
348
+ function isRelativeSpecifier(value) {
349
+ return (value === "." ||
350
+ value === ".." ||
351
+ value.startsWith("./") ||
352
+ value.startsWith("../") ||
353
+ value.startsWith(".\\") ||
354
+ value.startsWith("..\\"));
355
+ }
210
356
  function isAlias(value) {
211
357
  return (typeof value === "object" &&
212
358
  value !== null &&
@@ -234,6 +380,15 @@ function selectTransformedSource(props) {
234
380
  }
235
381
  throw new Error(`ttsc transform did not return output for ${props.file}`);
236
382
  }
383
+ function reportSuccessDiagnostics(result) {
384
+ if (result.type !== "success" || result.diagnostics === undefined) {
385
+ return;
386
+ }
387
+ const text = formatDiagnostics(result.diagnostics);
388
+ if (text.length !== 0) {
389
+ process.stderr.write(`${text}\n`);
390
+ }
391
+ }
237
392
  function formatDiagnostics(diagnostics) {
238
393
  if (diagnostics.length === 0) {
239
394
  return "ttsc transform failed";
@@ -290,6 +445,7 @@ function normalizePath(file) {
290
445
  }
291
446
 
292
447
  exports.createTransformResult = createTransformResult;
448
+ exports.createTtscTransformCache = createTtscTransformCache;
293
449
  exports.isDeclarationFile = isDeclarationFile;
294
450
  exports.stripQuery = stripQuery;
295
451
  exports.transformTtsc = transformTtsc;