rolldown-plugin-dts 0.27.8 → 0.27.10

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/dist/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
- import { a as RE_JSON, c as RE_TS, d as filename_js_to_dts, f as filename_to_dts, i as RE_JS, l as RE_VUE, m as resolveTemplateFn, n as RE_DTS, o as RE_NODE_MODULES, p as replaceTemplateName, r as RE_DTS_MAP, s as RE_ROLLDOWN_RUNTIME, t as RE_CSS, u as filename_dts_to } from "./filename-BR9JpwkC.mjs";
1
+ import { a as RE_JSON, c as RE_TS, d as filename_to_dts, f as replaceTemplateName, i as RE_JS, l as filename_dts_to, n as RE_DTS, o as RE_NODE_MODULES, p as resolveTemplateFn, r as RE_DTS_MAP, s as RE_ROLLDOWN_RUNTIME, t as RE_CSS, u as filename_js_to_dts } from "./filename-BrNNypc2.mjs";
2
2
  import { createContext, globalContext, invalidateContextFile } from "./tsc-context.mjs";
3
+ import { t as requireTS } from "./load-tsc-BKULZsrs.mjs";
3
4
  import { createRequire } from "node:module";
4
5
  import { createDebug } from "obug";
5
6
  import { importerId, include } from "rolldown/filter";
@@ -52,59 +53,400 @@ function createDtsInputPlugin({ sideEffects }) {
52
53
  };
53
54
  }
54
55
  //#endregion
55
- //#region src/fake-js.ts
56
- function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
57
- let declarationIdx = 0;
58
- const declarationMap = /* @__PURE__ */ new Map();
59
- const commentsMap = /* @__PURE__ */ new Map();
60
- const moduleExportsMap = /* @__PURE__ */ new Map();
61
- const warnedCjsDtsInputs = /* @__PURE__ */ new Set();
56
+ //#region src/tsgo.ts
57
+ const require$1 = createRequire(import.meta.url);
58
+ const debug$5 = createDebug("rolldown-plugin-dts:tsgo");
59
+ function isTS70Installed() {
60
+ try {
61
+ const { versionMajorMinor } = require$1("typescript");
62
+ return versionMajorMinor === "7.0";
63
+ } catch {}
64
+ return false;
65
+ }
66
+ const spawnAsync = (...args) => new Promise((resolve, reject) => {
67
+ const child = spawn(...args);
68
+ child.on("close", () => resolve());
69
+ child.on("error", (error) => reject(error));
70
+ });
71
+ let tsgoPathCache;
72
+ async function getTsgoPathFromNodeModules(logger) {
73
+ if (tsgoPathCache) return tsgoPathCache;
74
+ const pkgName = isTS70Installed() ? "typescript" : "@typescript/native-preview";
75
+ const tsgoPkg = import.meta.resolve(`${pkgName}/package.json`);
76
+ const { default: { version } } = await import(tsgoPkg, { with: { type: "json" } });
77
+ logger.info(`Emit types with ${styleText("underline", `${pkgName}@${version}`)}`);
78
+ const { default: getExePath } = await import(new URL("lib/getExePath.js", tsgoPkg).href);
79
+ return tsgoPathCache = getExePath();
80
+ }
81
+ async function runTsgo(logger, rootDir, tsconfig, sourcemap, tsgoPath) {
82
+ debug$5("[tsgo] rootDir", rootDir);
83
+ let tsgo;
84
+ if (tsgoPath) {
85
+ tsgo = tsgoPath;
86
+ debug$5("[tsgo] using custom path", tsgo);
87
+ } else {
88
+ tsgo = await getTsgoPathFromNodeModules(logger);
89
+ debug$5("[tsgo] using tsgo from node_modules", tsgo);
90
+ }
91
+ const tsgoDist = await mkdtemp(path.join(tmpdir(), "rolldown-plugin-dts-"));
92
+ debug$5("[tsgo] tsgoDist", tsgoDist);
93
+ const args = [
94
+ "--noEmit",
95
+ "false",
96
+ "--declaration",
97
+ "--emitDeclarationOnly",
98
+ "-p",
99
+ tsconfig,
100
+ "--outDir",
101
+ tsgoDist,
102
+ "--rootDir",
103
+ rootDir,
104
+ "--noCheck",
105
+ ...sourcemap ? ["--declarationMap"] : []
106
+ ];
107
+ debug$5("[tsgo] args %o", args);
108
+ await spawnAsync(tsgo, args, { stdio: "inherit" });
62
109
  return {
63
- name: "rolldown-plugin-dts:fake-js",
110
+ path: tsgoDist,
111
+ async dispose() {
112
+ if (debug$5.enabled) debug$5("[tsgo] skip cleanup of tsgoDist", tsgoDist);
113
+ else {
114
+ debug$5("[tsgo] disposing tsgoDist", tsgoDist);
115
+ await rm(tsgoDist, {
116
+ recursive: true,
117
+ force: true
118
+ }).catch(() => {});
119
+ }
120
+ }
121
+ };
122
+ }
123
+ //#endregion
124
+ //#region src/generate.ts
125
+ const debug$4 = createDebug("rolldown-plugin-dts:generate");
126
+ const WORKER_URL = "./tsc-worker.mjs";
127
+ const EMPTY_STUB = `export {}`;
128
+ function createGeneratePlugin({ generator, entry, tsconfig, tsconfigRaw, build, incremental, cwd, oxc, emitDtsOnly, volarContext, parallel, eager, tsgo, newContext, emitJs, sourcemap, logger }) {
129
+ const entryIncludes = entry?.filter((p) => p[0] !== "!");
130
+ const entryIgnores = entry?.filter((p) => p[0] === "!").map((p) => p.slice(1));
131
+ const entryMatcher = entry ? (file) => entryIncludes.some((p) => path.matchesGlob(file, p)) && !entryIgnores.some((p) => path.matchesGlob(file, p)) : void 0;
132
+ const dtsMap = /* @__PURE__ */ new Map();
133
+ /**
134
+ * A map of input id to output file name
135
+ *
136
+ * @example
137
+ *
138
+ * inputAlias = new Map([
139
+ * ['/absolute/path/to/src/source_file.ts', 'dist/foo/index'],
140
+ * ])
141
+ */
142
+ const inputAliasMap = /* @__PURE__ */ new Map();
143
+ let tscWorker;
144
+ let tscModule;
145
+ let tscContext;
146
+ let tsgoContext;
147
+ const rootDir = tsconfig ? path.dirname(tsconfig) : cwd;
148
+ return {
149
+ name: "rolldown-plugin-dts:generate",
150
+ async buildStart(options) {
151
+ if (generator === "tsgo") tsgoContext = await runTsgo(logger, rootDir, tsconfig, sourcemap, tsgo.path);
152
+ else if (generator === "tsc") if (parallel) tscWorker = createTscWorker();
153
+ else {
154
+ tscModule = await import("./tsc.mjs");
155
+ if (newContext) tscContext = createContext();
156
+ }
157
+ if (!Array.isArray(options.input)) for (const [name, id] of Object.entries(options.input)) {
158
+ debug$4("resolving input alias %s -> %s", name, id);
159
+ let resolved = await this.resolve(id);
160
+ if (!id.startsWith("./")) resolved ||= await this.resolve(`./${id}`);
161
+ const resolvedId = resolved?.id || id;
162
+ debug$4("resolved input alias %s -> %s", id, resolvedId);
163
+ inputAliasMap.set(resolvedId, name);
164
+ }
165
+ },
64
166
  outputOptions(options) {
65
- if (options.format === "cjs" || options.format === "commonjs") throw new Error("[rolldown-plugin-dts] Cannot bundle dts files with `cjs` format.");
66
- const { chunkFileNames, entryFileNames } = options;
67
167
  return {
68
168
  ...options,
69
- sourcemap: options.sourcemap || sourcemap,
70
- chunkFileNames(chunk) {
71
- const nameTemplate = resolveTemplateFn(chunk.isEntry ? entryFileNames || "[name].js" : chunkFileNames || "[name]-[hash].js", chunk);
169
+ entryFileNames(chunk) {
170
+ const { entryFileNames } = options;
171
+ const nameTemplate = resolveTemplateFn(entryFileNames || "[name].js", chunk);
72
172
  if (chunk.name.endsWith(".d")) {
73
- const renderedNameWithoutD = filename_js_to_dts(replaceTemplateName(nameTemplate, chunk.name.slice(0, -2)));
74
- if (RE_DTS.test(renderedNameWithoutD)) return renderedNameWithoutD;
75
- const renderedName = filename_js_to_dts(replaceTemplateName(nameTemplate, chunk.name));
76
- if (RE_DTS.test(renderedName)) return renderedName;
173
+ if (RE_DTS.test(nameTemplate)) return replaceTemplateName(nameTemplate, chunk.name.slice(0, -2));
174
+ if (RE_JS.test(nameTemplate)) return nameTemplate.replace(RE_JS, ".$1ts");
77
175
  }
78
176
  return nameTemplate;
79
177
  }
80
178
  };
81
179
  },
180
+ resolveId(id) {
181
+ if (dtsMap.has(id)) {
182
+ debug$4("resolve dts id %s", id);
183
+ return { id };
184
+ }
185
+ },
82
186
  transform: {
83
- filter: { id: RE_DTS },
84
- handler: transform
187
+ order: "pre",
188
+ filter: { id: {
189
+ include: [
190
+ RE_JS,
191
+ RE_TS,
192
+ RE_JSON,
193
+ ...volarContext.patterns
194
+ ],
195
+ exclude: [
196
+ RE_DTS,
197
+ RE_NODE_MODULES,
198
+ RE_ROLLDOWN_RUNTIME
199
+ ]
200
+ } },
201
+ handler(code, id) {
202
+ const jsFile = RE_JS.test(id);
203
+ if (!jsFile || emitJs) {
204
+ const mod = this.getModuleInfo(id);
205
+ const isEntry = entryMatcher ? entryMatcher(path.relative(cwd, id)) : !!mod?.isEntry;
206
+ const dtsId = filename_to_dts(id, volarContext);
207
+ dtsMap.set(dtsId, {
208
+ code,
209
+ id,
210
+ isEntry,
211
+ jsFile
212
+ });
213
+ debug$4("register dts source: %s", id);
214
+ if (isEntry) {
215
+ const name = inputAliasMap.get(id);
216
+ this.emitFile({
217
+ type: "chunk",
218
+ id: dtsId,
219
+ name: name ? `${name}.d` : void 0
220
+ });
221
+ }
222
+ }
223
+ if (emitDtsOnly) {
224
+ if (RE_JSON.test(id)) return "{}";
225
+ return EMPTY_STUB;
226
+ }
227
+ }
85
228
  },
86
- renderChunk,
87
- generateBundle(options, bundle) {
88
- for (const chunk of Object.values(bundle)) {
89
- if (!RE_DTS_MAP.test(chunk.fileName)) continue;
90
- if (sourcemap) {
91
- if (chunk.type === "chunk" || typeof chunk.source !== "string") continue;
92
- const map = JSON.parse(chunk.source);
93
- map.sourcesContent = void 0;
94
- chunk.source = JSON.stringify(map);
95
- } else delete bundle[chunk.fileName];
229
+ load: {
230
+ filter: { id: {
231
+ include: [RE_DTS],
232
+ exclude: [RE_NODE_MODULES]
233
+ } },
234
+ async handler(dtsId) {
235
+ const module = dtsMap.get(dtsId);
236
+ if (!module) return;
237
+ const { code, id, jsFile } = module;
238
+ if (jsFile && await access(dtsId).then(() => true).catch(() => false)) {
239
+ debug$4("dts file already exists for %s, skipping generation", id);
240
+ return;
241
+ }
242
+ let dtsCode;
243
+ let map;
244
+ debug$4("generate dts %s from %s", dtsId, id);
245
+ if (generator === "tsgo") {
246
+ if (volarContext.isVolarFile(id)) throw new Error(`tsgo does not support .${path.extname(id)} file.`);
247
+ const dtsPath = path.resolve(tsgoContext.path, path.relative(path.resolve(rootDir), filename_to_dts(id, volarContext)));
248
+ if (!existsSync(dtsPath)) {
249
+ debug$4("[tsgo]", dtsPath, "is missing");
250
+ throw new Error(`tsgo did not generate dts file for ${id}, please check your tsconfig.`);
251
+ }
252
+ dtsCode = await readFile(dtsPath, "utf8");
253
+ const mapPath = `${dtsPath}.map`;
254
+ if (existsSync(mapPath)) {
255
+ const mapRaw = await readFile(mapPath, "utf8");
256
+ map = {
257
+ ...JSON.parse(mapRaw),
258
+ sources: [id]
259
+ };
260
+ }
261
+ } else if (generator === "oxc" && !volarContext.isVolarFile(id)) {
262
+ const result = isolatedDeclarationSync(id, code, oxc);
263
+ if (result.errors.length) {
264
+ const [error] = result.errors;
265
+ return this.error({
266
+ message: error.message,
267
+ frame: error.codeframe || void 0
268
+ });
269
+ }
270
+ dtsCode = result.code;
271
+ if (result.map) {
272
+ map = result.map;
273
+ map.sourcesContent = void 0;
274
+ }
275
+ } else {
276
+ const options = {
277
+ tsconfig,
278
+ tsconfigRaw,
279
+ build,
280
+ incremental,
281
+ cwd,
282
+ entries: eager ? void 0 : Array.from(dtsMap.values()).filter((v) => v.isEntry).map((v) => v.id),
283
+ id,
284
+ sourcemap,
285
+ volarContext,
286
+ context: tscContext
287
+ };
288
+ let result;
289
+ if (parallel) result = await tscWorker.emit(options);
290
+ else result = tscModule.tscEmit(options);
291
+ if (result.error) return this.error(result.error);
292
+ dtsCode = result.code;
293
+ map = result.map;
294
+ if (dtsCode && RE_JSON.test(id)) if (dtsCode.includes("declare const _exports")) {
295
+ if (dtsCode.includes("declare const _exports: {") && !dtsCode.includes("\n}[];")) {
296
+ const exports = collectJsonExports(dtsCode);
297
+ let i = 0;
298
+ dtsCode += exports.map((e) => {
299
+ const valid = `_${e.replaceAll(/[^\w$]/g, "_")}${i++}`;
300
+ const jsonKey = JSON.stringify(e);
301
+ return `declare let ${valid}: typeof _exports[${jsonKey}]\nexport { ${valid} as ${jsonKey} }`;
302
+ }).join("\n");
303
+ }
304
+ } else {
305
+ const exportMap = collectJsonExportMap(dtsCode);
306
+ dtsCode += `
307
+ declare namespace __json_default_export {
308
+ export { ${Array.from(exportMap.entries()).map(([exported, local]) => exported === local ? exported : `${local} as ${exported}`).join(", ")} }
309
+ }
310
+ export { __json_default_export as default }`;
311
+ }
312
+ }
313
+ return {
314
+ code: dtsCode || "",
315
+ map
316
+ };
96
317
  }
97
- }
98
- };
99
- async function transform(code, id) {
100
- let file;
101
- try {
102
- file = parse(code, {
103
- lang: "dts",
104
- sourceType: "module",
105
- attachComments: true
106
- });
107
- } catch (error) {
318
+ },
319
+ generateBundle: emitDtsOnly ? (options, bundle) => {
320
+ for (const fileName of Object.keys(bundle)) if (bundle[fileName].type === "chunk" && !RE_DTS.test(fileName) && !RE_DTS_MAP.test(fileName)) delete bundle[fileName];
321
+ } : void 0,
322
+ async buildEnd() {
323
+ tscWorker?.kill();
324
+ tscWorker = void 0;
325
+ await tsgoContext?.dispose();
326
+ tsgoContext = void 0;
327
+ if (newContext) tscContext = void 0;
328
+ },
329
+ watchChange(id) {
330
+ if (tscModule) invalidateContextFile(tscContext || globalContext, id);
331
+ }
332
+ };
333
+ }
334
+ function createTscWorker() {
335
+ const childProcess = fork(new URL(WORKER_URL, import.meta.url), {
336
+ stdio: "inherit",
337
+ serialization: "advanced"
338
+ });
339
+ const pending = /* @__PURE__ */ new Map();
340
+ let nextId = 0;
341
+ childProcess.on("message", (response) => {
342
+ const handler = pending.get(response.id);
343
+ if (!handler) return;
344
+ pending.delete(response.id);
345
+ if (response.error) handler.reject(response.error);
346
+ else handler.resolve(response.result);
347
+ });
348
+ childProcess.on("exit", (code) => {
349
+ for (const handler of pending.values()) handler.reject(/* @__PURE__ */ new Error(`tsc worker exited with code ${code}`));
350
+ pending.clear();
351
+ });
352
+ return {
353
+ emit: (options) => new Promise((resolve, reject) => {
354
+ const id = nextId++;
355
+ pending.set(id, {
356
+ resolve,
357
+ reject
358
+ });
359
+ childProcess.send({
360
+ id,
361
+ options
362
+ });
363
+ }),
364
+ kill: () => childProcess.kill()
365
+ };
366
+ }
367
+ function collectJsonExportMap(code) {
368
+ const exportMap = /* @__PURE__ */ new Map();
369
+ const { program } = parse(code, {
370
+ sourceType: "module",
371
+ lang: "dts"
372
+ });
373
+ for (const decl of program.body) if (decl.type === "ExportNamedDeclaration") {
374
+ if (decl.declaration) {
375
+ if (decl.declaration.type === "VariableDeclaration") {
376
+ for (const vdecl of decl.declaration.declarations) if (vdecl.id.type === "Identifier") exportMap.set(vdecl.id.name, vdecl.id.name);
377
+ } else if (decl.declaration.type === "TSModuleDeclaration" && decl.declaration.id.type === "Identifier") exportMap.set(decl.declaration.id.name, decl.declaration.id.name);
378
+ } else if (decl.specifiers.length) {
379
+ for (const spec of decl.specifiers) if (spec.type === "ExportSpecifier" && spec.exported.type === "Identifier") exportMap.set(spec.exported.name, spec.local.type === "Identifier" ? spec.local.name : spec.exported.name);
380
+ }
381
+ }
382
+ return exportMap;
383
+ }
384
+ /** `declare const _exports` mode */
385
+ function collectJsonExports(code) {
386
+ const exports = [];
387
+ const { program } = parse(code, {
388
+ sourceType: "module",
389
+ lang: "dts"
390
+ });
391
+ const members = program.body[0].declarations[0].id.typeAnnotation.typeAnnotation.members;
392
+ for (const member of members) if (member.key.type === "Identifier") exports.push(member.key.name);
393
+ else if (is.StringLiteral(member.key)) exports.push(member.key.value);
394
+ return exports;
395
+ }
396
+ //#endregion
397
+ //#region src/fake-js.ts
398
+ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
399
+ let declarationIdx = 0;
400
+ const declarationMap = /* @__PURE__ */ new Map();
401
+ const commentsMap = /* @__PURE__ */ new Map();
402
+ const moduleExportsMap = /* @__PURE__ */ new Map();
403
+ const warnedCjsDtsInputs = /* @__PURE__ */ new Set();
404
+ return {
405
+ name: "rolldown-plugin-dts:fake-js",
406
+ outputOptions(options) {
407
+ if (options.format === "cjs" || options.format === "commonjs") throw new Error("[rolldown-plugin-dts] Cannot bundle dts files with `cjs` format.");
408
+ const { chunkFileNames, entryFileNames } = options;
409
+ return {
410
+ ...options,
411
+ sourcemap: options.sourcemap || sourcemap,
412
+ chunkFileNames(chunk) {
413
+ const nameTemplate = resolveTemplateFn(chunk.isEntry ? entryFileNames || "[name].js" : chunkFileNames || "[name]-[hash].js", chunk);
414
+ if (chunk.name.endsWith(".d")) {
415
+ const renderedNameWithoutD = filename_js_to_dts(replaceTemplateName(nameTemplate, chunk.name.slice(0, -2)));
416
+ if (RE_DTS.test(renderedNameWithoutD)) return renderedNameWithoutD;
417
+ const renderedName = filename_js_to_dts(replaceTemplateName(nameTemplate, chunk.name));
418
+ if (RE_DTS.test(renderedName)) return renderedName;
419
+ }
420
+ return nameTemplate;
421
+ }
422
+ };
423
+ },
424
+ transform: {
425
+ filter: { id: RE_DTS },
426
+ handler: transform
427
+ },
428
+ renderChunk,
429
+ generateBundle(options, bundle) {
430
+ for (const chunk of Object.values(bundle)) {
431
+ if (!RE_DTS_MAP.test(chunk.fileName)) continue;
432
+ if (sourcemap) {
433
+ if (chunk.type === "chunk" || typeof chunk.source !== "string") continue;
434
+ const map = JSON.parse(chunk.source);
435
+ map.sourcesContent = void 0;
436
+ chunk.source = JSON.stringify(map);
437
+ } else delete bundle[chunk.fileName];
438
+ }
439
+ }
440
+ };
441
+ async function transform(code, id) {
442
+ let file;
443
+ try {
444
+ file = parse(code, {
445
+ lang: "dts",
446
+ sourceType: "module",
447
+ attachComments: true
448
+ });
449
+ } catch (error) {
108
450
  throw new Error(`Failed to parse ${id}. This may be caused by a syntax error in the declaration file or a bug in the plugin. Please report this issue to https://github.com/sxzz/rolldown-plugin-dts\n${error}`, { cause: error });
109
451
  }
110
452
  const { program } = file;
@@ -123,7 +465,6 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
123
465
  if (rewriteImportExport(stmt, setStmt)) continue;
124
466
  const sideEffect = stmt.type === "TSModuleDeclaration" && stmt.kind !== "namespace";
125
467
  if (sideEffect && stmt.type === "TSModuleDeclaration" && is.StringLiteral(stmt.id) && stmt.id.value[0] === ".") this.warn(`\`declare module ${JSON.stringify(stmt.id.value)}\` will be kept as-is in the output. Relative module declaration may cause unexpected issues. Found in ${id}.`);
126
- if (sideEffect && id.endsWith(".vue.d.ts") && code.slice(stmt.start, stmt.end).includes("__VLS_")) continue;
127
468
  const isDefaultExport = stmt.type === "ExportDefaultDeclaration";
128
469
  const isExportDecl = is.oneOf(stmt, ["ExportNamedDeclaration", "ExportDefaultDeclaration"]) && !!stmt.declaration;
129
470
  const decl = isExportDecl ? stmt.declaration : stmt;
@@ -267,7 +608,7 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
267
608
  return inheritNodeComments(node, declaration.decl);
268
609
  }).filter((node) => !!node);
269
610
  if (program.body.length === 0) return {
270
- code: "export { };",
611
+ code: EMPTY_STUB,
271
612
  map: null
272
613
  };
273
614
  const comments = /* @__PURE__ */ new Set();
@@ -604,516 +945,255 @@ function isCjsDtsInputSyntax(node) {
604
945
  * Check if the given node is a {@link RuntimeBindingVariableDeclration}
605
946
  */
606
947
  function isRuntimeBindingVariableDeclaration(node) {
607
- return node?.type === "VariableDeclaration" && node.declarations.length === 1 && node.declarations[0].type === "VariableDeclarator" && node.declarations[0].id.type === "ArrayPattern" && isRuntimeBindingArrayExpression(node.declarations[0].init);
608
- }
609
- /**
610
- * Check if the given node is a {@link RuntimeBindingArrayExpression}
611
- */
612
- function isRuntimeBindingArrayExpression(node) {
613
- return node?.type === "ArrayExpression" && isRuntimeBindingArrayElements(node.elements);
614
- }
615
- /**
616
- * Check if the given array is a {@link RuntimeBindingArrayElements}
617
- */
618
- function isRuntimeBindingArrayElements(elements) {
619
- const [declarationId, deps, children, effect] = elements;
620
- return is.NumericLiteral(declarationId) && deps?.type === "ArrowFunctionExpression" && children?.type === "ArrayExpression" && (!effect || effect.type === "CallExpression");
621
- }
622
- function runtimeBindingArrayExpression(elements) {
623
- return b.arrayExpression([...elements]);
624
- }
625
- function isThisExpression(node) {
626
- return is.Identifier(node, "this") || node.type === "ThisExpression" || node.type === "MemberExpression" && isThisExpression(node.object);
627
- }
628
- function isInfer(node) {
629
- return is.Identifier(node, "infer");
630
- }
631
- function TSEntityNameToRuntime(node) {
632
- if (node.type === "Identifier" || node.type === "ThisExpression") return node;
633
- const left = TSEntityNameToRuntime(node.left);
634
- return Object.assign(node, {
635
- type: "MemberExpression",
636
- object: left,
637
- property: node.right,
638
- computed: false
639
- });
640
- }
641
- function getIdFromTSEntityName(node) {
642
- if (node.type === "Identifier" || node.type === "ThisExpression") return node;
643
- return getIdFromTSEntityName(node.left);
644
- }
645
- function isReferenceId(node) {
646
- return is.oneOf(node, ["Identifier", "MemberExpression"]);
647
- }
648
- function isHelperImport(node) {
649
- return node.type === "ImportDeclaration" && node.specifiers.length && node.specifiers.every((spec) => spec.type === "ImportSpecifier" && spec.imported.type === "Identifier" && ["__exportAll", "__reExport"].includes(spec.local.name));
650
- }
651
- /**
652
- * patch `.d.ts` suffix in import source to `.js`
653
- */
654
- function patchImportExport(node, exportInfo, cjsDefault) {
655
- if (node.type === "ExportNamedDeclaration" && !node.declaration && !node.source && !node.specifiers.length && !node.attributes?.length) return false;
656
- if (node.type === "ImportDeclaration" && node.specifiers.length) {
657
- for (const specifier of node.specifiers) if (isInfer(specifier.local)) specifier.local.name = "__Infer";
658
- }
659
- if (is.oneOf(node, [
660
- "ImportDeclaration",
661
- "ExportAllDeclaration",
662
- "ExportNamedDeclaration"
663
- ])) {
664
- if (node.type === "ExportAllDeclaration" && node.source && exportInfo.typeOnlyExportAllSources.has(node.source.value)) node.exportKind = "type";
665
- if (node.type === "ExportNamedDeclaration" && exportInfo.typeOnlyNames.size) {
666
- for (const spec of node.specifiers) {
667
- const name = nameOf(spec.exported);
668
- if (exportInfo.typeOnlyNames.has(name)) if (spec.type === "ExportSpecifier") spec.exportKind = "type";
669
- else node.exportKind = "type";
670
- }
671
- normalizeTypeOnlyExport(node);
672
- }
673
- if (node.source?.value && RE_DTS.test(node.source.value)) {
674
- node.source.value = filename_dts_to(node.source.value, "js");
675
- return node;
676
- }
677
- if (cjsDefault && node.type === "ExportNamedDeclaration" && !node.source && node.specifiers.length === 1 && node.specifiers[0].type === "ExportSpecifier" && nameOf(node.specifiers[0].exported) === "default") {
678
- const defaultExport = node.specifiers[0];
679
- return b.tsExportAssignment(defaultExport.local);
680
- }
681
- }
682
- }
683
- function normalizeTypeOnlyExport(node) {
684
- if (node.declaration || !node.specifiers.length) return;
685
- for (const specifier of node.specifiers) if (specifier.type !== "ExportSpecifier" || specifier.exportKind !== "type") return;
686
- node.exportKind = "type";
687
- for (const specifier of node.specifiers) if (specifier.type === "ExportSpecifier") specifier.exportKind = "value";
688
- }
689
- /**
690
- * Handle `__exportAll` call
691
- */
692
- function patchTsNamespace(nodes) {
693
- const removed = /* @__PURE__ */ new Set();
694
- for (const [i, node] of nodes.entries()) {
695
- const result = getExportAllNamespace(node);
696
- if (!result) continue;
697
- const [binding, exports] = result;
698
- if (!exports.properties.length) continue;
699
- const namespaceExport = b.exportNamedDeclaration(null, exports.properties.filter((property) => property.type === "Property").map((property) => {
700
- const local = property.value.body;
701
- const exported = property.key;
702
- return b.exportSpecifier(local, exported);
703
- }));
704
- nodes[i] = b.tsModuleDeclaration(binding, b.tsModuleBlock([namespaceExport]), {
705
- kind: "namespace",
706
- declare: true
707
- });
708
- }
709
- return nodes.filter((node) => !removed.has(node));
710
- }
711
- function getExportAllNamespace(node) {
712
- if (node.type !== "VariableDeclaration" || node.declarations.length !== 1 || node.declarations[0].id.type !== "Identifier" || node.declarations[0].init?.type !== "CallExpression" || node.declarations[0].init.callee.type !== "Identifier" || node.declarations[0].init.callee.name !== "__exportAll" || node.declarations[0].init.arguments.length !== 1 || node.declarations[0].init.arguments[0].type !== "ObjectExpression") return false;
713
- return [node.declarations[0].id, node.declarations[0].init.arguments[0]];
714
- }
715
- /**
716
- * Handle `__reExport` call
717
- */
718
- function patchReExport(nodes) {
719
- const exportsNames = /* @__PURE__ */ new Map();
720
- for (const [i, node] of nodes.entries()) if (node.type === "ImportDeclaration" && node.specifiers.length === 1 && node.specifiers[0].type === "ImportSpecifier" && node.specifiers[0].local.type === "Identifier" && node.specifiers[0].local.name.endsWith("_exports")) exportsNames.set(node.specifiers[0].local.name, node.specifiers[0].local.name);
721
- else if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && is.Identifier(node.expression.callee, "__reExport")) {
722
- const args = node.expression.arguments;
723
- exportsNames.set(args[0].name, args[1].name);
724
- } else if (node.type === "VariableDeclaration" && node.declarations.length === 1 && node.declarations[0].init?.type === "MemberExpression" && node.declarations[0].init.object.type === "Identifier" && exportsNames.has(node.declarations[0].init.object.name)) nodes[i] = b.tsTypeAliasDeclaration(b.identifier(node.declarations[0].id.name), b.tsTypeReference(b.tsQualifiedName(b.identifier(exportsNames.get(node.declarations[0].init.object.name)), b.identifier(node.declarations[0].init.property.name))));
725
- else if (node.type === "ExportNamedDeclaration" && node.specifiers.length === 1 && node.specifiers[0].type === "ExportSpecifier" && node.specifiers[0].local.type === "Identifier" && exportsNames.has(node.specifiers[0].local.name)) node.specifiers[0].local.name = exportsNames.get(node.specifiers[0].local.name);
726
- return nodes;
727
- }
728
- function rewriteImportExport(node, set) {
729
- if (node.type === "ImportDeclaration" || node.type === "ExportNamedDeclaration" && !node.declaration) {
730
- for (const specifier of node.specifiers) if (specifier.type === "ImportSpecifier") specifier.importKind = "value";
731
- else if (specifier.type === "ExportSpecifier") specifier.exportKind = "value";
732
- if (node.type === "ImportDeclaration") node.importKind = "value";
733
- else if (node.type === "ExportNamedDeclaration") node.exportKind = "value";
734
- return true;
735
- } else if (node.type === "ExportAllDeclaration") {
736
- node.exportKind = "value";
737
- return true;
738
- } else if (node.type === "TSImportEqualsDeclaration") {
739
- if (node.moduleReference.type === "TSExternalModuleReference") set(b.importDeclaration([b.importDefaultSpecifier(node.id)], node.moduleReference.expression));
740
- return true;
741
- } else if (node.type === "TSExportAssignment" && node.expression.type === "Identifier") {
742
- set(b.exportNamedDeclaration(null, [b.exportSpecifier(node.expression, b.identifier("default"))]));
743
- return true;
744
- } else if (node.type === "ExportDefaultDeclaration" && node.declaration.type === "Identifier") {
745
- set(b.exportNamedDeclaration(null, [b.exportSpecifier(node.declaration, b.identifier("default"))]));
746
- return true;
747
- }
748
- return false;
749
- }
750
- function overwriteNode(node, newNode) {
751
- for (const key of Object.keys(node)) Reflect.deleteProperty(node, key);
752
- Object.assign(node, newNode);
753
- return node;
754
- }
755
- function inheritNodeComments(oldNode, newNode) {
756
- newNode.comments ||= [];
757
- const pragmas = oldNode.comments?.filter((comment) => comment.position === "before" && comment.value.startsWith("#") && !isSourceMapPragma(comment));
758
- if (pragmas) newNode.comments.unshift(...pragmas);
759
- newNode.comments = newNode.comments.filter((comment) => !REFERENCE_RE.test(comment.value) && !isSourceMapPragma(comment));
760
- return newNode;
761
- }
762
- function getIdentifierIndex(identifierMap, name) {
763
- if (name in identifierMap) return ++identifierMap[name];
764
- return identifierMap[name] = 0;
765
- }
766
- //#endregion
767
- //#region src/tsgo.ts
768
- const require = createRequire(import.meta.url);
769
- const debug$4 = createDebug("rolldown-plugin-dts:tsgo");
770
- function getTypeScriptMajor() {
771
- try {
772
- const { version } = require("typescript/package.json");
773
- const major = +version.split(".", 1)[0];
774
- return Number.isNaN(major) ? void 0 : major;
775
- } catch {
776
- return;
777
- }
778
- }
779
- function isTS7Installed() {
780
- const major = getTypeScriptMajor();
781
- return major != null && major >= 7;
782
- }
783
- const spawnAsync = (...args) => new Promise((resolve, reject) => {
784
- const child = spawn(...args);
785
- child.on("close", () => resolve());
786
- child.on("error", (error) => reject(error));
787
- });
788
- let tsgoPathCache;
789
- async function getTsgoPathFromNodeModules(logger) {
790
- if (tsgoPathCache) return tsgoPathCache;
791
- const pkgName = isTS7Installed() ? "typescript" : "@typescript/native-preview";
792
- const tsgoPkg = import.meta.resolve(`${pkgName}/package.json`);
793
- const { default: { version } } = await import(tsgoPkg, { with: { type: "json" } });
794
- logger.info(`Emit types with ${styleText("underline", `${pkgName}@${version}`)}`);
795
- const { default: getExePath } = await import(new URL("lib/getExePath.js", tsgoPkg).href);
796
- return tsgoPathCache = getExePath();
797
- }
798
- async function runTsgo(logger, rootDir, tsconfig, sourcemap, tsgoPath) {
799
- debug$4("[tsgo] rootDir", rootDir);
800
- let tsgo;
801
- if (tsgoPath) {
802
- tsgo = tsgoPath;
803
- debug$4("[tsgo] using custom path", tsgo);
804
- } else {
805
- tsgo = await getTsgoPathFromNodeModules(logger);
806
- debug$4("[tsgo] using tsgo from node_modules", tsgo);
807
- }
808
- const tsgoDist = await mkdtemp(path.join(tmpdir(), "rolldown-plugin-dts-"));
809
- debug$4("[tsgo] tsgoDist", tsgoDist);
810
- const args = [
811
- "--noEmit",
812
- "false",
813
- "--declaration",
814
- "--emitDeclarationOnly",
815
- ...tsconfig ? ["-p", tsconfig] : [],
816
- "--outDir",
817
- tsgoDist,
818
- "--rootDir",
819
- rootDir,
820
- "--noCheck",
821
- ...sourcemap ? ["--declarationMap"] : []
822
- ];
823
- debug$4("[tsgo] args %o", args);
824
- await spawnAsync(tsgo, args, { stdio: "inherit" });
825
- return {
826
- path: tsgoDist,
827
- async dispose() {
828
- if (debug$4.enabled) debug$4("[tsgo] skip cleanup of tsgoDist", tsgoDist);
829
- else {
830
- debug$4("[tsgo] disposing tsgoDist", tsgoDist);
831
- await rm(tsgoDist, {
832
- recursive: true,
833
- force: true
834
- }).catch(() => {});
835
- }
836
- }
837
- };
838
- }
839
- //#endregion
840
- //#region src/generate.ts
841
- const debug$3 = createDebug("rolldown-plugin-dts:generate");
842
- const WORKER_URL = "./tsc-worker.mjs";
843
- function createGeneratePlugin({ generator, entry, tsconfig, tsconfigRaw, build, incremental, cwd, oxc, emitDtsOnly, vue, tsMacro, parallel, eager, tsgo, newContext, emitJs, sourcemap, logger }) {
844
- const entryIncludes = entry?.filter((p) => p[0] !== "!");
845
- const entryIgnores = entry?.filter((p) => p[0] === "!").map((p) => p.slice(1));
846
- const entryMatcher = entry ? (file) => entryIncludes.some((p) => path.matchesGlob(file, p)) && !entryIgnores.some((p) => path.matchesGlob(file, p)) : void 0;
847
- const dtsMap = /* @__PURE__ */ new Map();
848
- /**
849
- * A map of input id to output file name
850
- *
851
- * @example
852
- *
853
- * inputAlias = new Map([
854
- * ['/absolute/path/to/src/source_file.ts', 'dist/foo/index'],
855
- * ])
856
- */
857
- const inputAliasMap = /* @__PURE__ */ new Map();
858
- let tscWorker;
859
- let tscModule;
860
- let tscContext;
861
- let tsgoContext;
862
- const rootDir = tsconfig ? path.dirname(tsconfig) : cwd;
863
- return {
864
- name: "rolldown-plugin-dts:generate",
865
- async buildStart(options) {
866
- if (generator === "tsgo") tsgoContext = await runTsgo(logger, rootDir, tsconfig, sourcemap, tsgo.path);
867
- else if (generator === "tsc") if (parallel) tscWorker = createTscWorker();
868
- else {
869
- tscModule = await import("./tsc.mjs");
870
- if (newContext) tscContext = createContext();
871
- }
872
- if (!Array.isArray(options.input)) for (const [name, id] of Object.entries(options.input)) {
873
- debug$3("resolving input alias %s -> %s", name, id);
874
- let resolved = await this.resolve(id);
875
- if (!id.startsWith("./")) resolved ||= await this.resolve(`./${id}`);
876
- const resolvedId = resolved?.id || id;
877
- debug$3("resolved input alias %s -> %s", id, resolvedId);
878
- inputAliasMap.set(resolvedId, name);
879
- }
880
- },
881
- outputOptions(options) {
882
- return {
883
- ...options,
884
- entryFileNames(chunk) {
885
- const { entryFileNames } = options;
886
- const nameTemplate = resolveTemplateFn(entryFileNames || "[name].js", chunk);
887
- if (chunk.name.endsWith(".d")) {
888
- if (RE_DTS.test(nameTemplate)) return replaceTemplateName(nameTemplate, chunk.name.slice(0, -2));
889
- if (RE_JS.test(nameTemplate)) return nameTemplate.replace(RE_JS, ".$1ts");
890
- }
891
- return nameTemplate;
892
- }
893
- };
894
- },
895
- resolveId(id) {
896
- if (dtsMap.has(id)) {
897
- debug$3("resolve dts id %s", id);
898
- return { id };
899
- }
900
- },
901
- transform: {
902
- order: "pre",
903
- filter: { id: {
904
- include: [
905
- RE_JS,
906
- RE_TS,
907
- RE_VUE,
908
- RE_JSON
909
- ],
910
- exclude: [
911
- RE_DTS,
912
- RE_NODE_MODULES,
913
- RE_ROLLDOWN_RUNTIME
914
- ]
915
- } },
916
- handler(code, id) {
917
- const jsFile = RE_JS.test(id);
918
- if (!jsFile || emitJs) {
919
- const mod = this.getModuleInfo(id);
920
- const isEntry = entryMatcher ? entryMatcher(path.relative(cwd, id)) : !!mod?.isEntry;
921
- const dtsId = filename_to_dts(id);
922
- dtsMap.set(dtsId, {
923
- code,
924
- id,
925
- isEntry,
926
- jsFile
927
- });
928
- debug$3("register dts source: %s", id);
929
- if (isEntry) {
930
- const name = inputAliasMap.get(id);
931
- this.emitFile({
932
- type: "chunk",
933
- id: dtsId,
934
- name: name ? `${name}.d` : void 0
935
- });
936
- }
937
- }
938
- if (emitDtsOnly) {
939
- if (RE_JSON.test(id)) return "{}";
940
- return "export { }";
941
- }
942
- }
943
- },
944
- load: {
945
- filter: { id: {
946
- include: [RE_DTS],
947
- exclude: [RE_NODE_MODULES]
948
- } },
949
- async handler(dtsId) {
950
- const module = dtsMap.get(dtsId);
951
- if (!module) return;
952
- const { code, id, jsFile } = module;
953
- if (jsFile && await access(dtsId).then(() => true).catch(() => false)) {
954
- debug$3("dts file already exists for %s, skipping generation", id);
955
- return;
956
- }
957
- let dtsCode;
958
- let map;
959
- debug$3("generate dts %s from %s", dtsId, id);
960
- if (generator === "tsgo") {
961
- if (RE_VUE.test(id)) throw new Error("tsgo does not support Vue files.");
962
- const dtsPath = path.resolve(tsgoContext.path, path.relative(path.resolve(rootDir), filename_to_dts(id)));
963
- if (!existsSync(dtsPath)) {
964
- debug$3("[tsgo]", dtsPath, "is missing");
965
- throw new Error(`tsgo did not generate dts file for ${id}, please check your tsconfig.`);
966
- }
967
- dtsCode = await readFile(dtsPath, "utf8");
968
- const mapPath = `${dtsPath}.map`;
969
- if (existsSync(mapPath)) {
970
- const mapRaw = await readFile(mapPath, "utf8");
971
- map = {
972
- ...JSON.parse(mapRaw),
973
- sources: [id]
974
- };
975
- }
976
- } else if (generator === "oxc" && !RE_VUE.test(id)) {
977
- const result = isolatedDeclarationSync(id, code, oxc);
978
- if (result.errors.length) {
979
- const [error] = result.errors;
980
- return this.error({
981
- message: error.message,
982
- frame: error.codeframe || void 0
983
- });
984
- }
985
- dtsCode = result.code;
986
- if (result.map) {
987
- map = result.map;
988
- map.sourcesContent = void 0;
989
- }
990
- } else {
991
- const options = {
992
- tsconfig,
993
- tsconfigRaw,
994
- build,
995
- incremental,
996
- cwd,
997
- entries: eager ? void 0 : Array.from(dtsMap.values()).filter((v) => v.isEntry).map((v) => v.id),
998
- id,
999
- sourcemap,
1000
- vue,
1001
- tsMacro,
1002
- context: tscContext
1003
- };
1004
- let result;
1005
- if (parallel) result = await tscWorker.emit(options);
1006
- else result = tscModule.tscEmit(options);
1007
- if (result.error) return this.error(result.error);
1008
- dtsCode = result.code;
1009
- map = result.map;
1010
- if (dtsCode && RE_JSON.test(id)) if (dtsCode.includes("declare const _exports")) {
1011
- if (dtsCode.includes("declare const _exports: {") && !dtsCode.includes("\n}[];")) {
1012
- const exports = collectJsonExports(dtsCode);
1013
- let i = 0;
1014
- dtsCode += exports.map((e) => {
1015
- const valid = `_${e.replaceAll(/[^\w$]/g, "_")}${i++}`;
1016
- const jsonKey = JSON.stringify(e);
1017
- return `declare let ${valid}: typeof _exports[${jsonKey}]\nexport { ${valid} as ${jsonKey} }`;
1018
- }).join("\n");
1019
- }
1020
- } else {
1021
- const exportMap = collectJsonExportMap(dtsCode);
1022
- dtsCode += `
1023
- declare namespace __json_default_export {
1024
- export { ${Array.from(exportMap.entries()).map(([exported, local]) => exported === local ? exported : `${local} as ${exported}`).join(", ")} }
948
+ return node?.type === "VariableDeclaration" && node.declarations.length === 1 && node.declarations[0].type === "VariableDeclarator" && node.declarations[0].id.type === "ArrayPattern" && isRuntimeBindingArrayExpression(node.declarations[0].init);
1025
949
  }
1026
- export { __json_default_export as default }`;
1027
- }
1028
- }
1029
- return {
1030
- code: dtsCode || "",
1031
- map
1032
- };
950
+ /**
951
+ * Check if the given node is a {@link RuntimeBindingArrayExpression}
952
+ */
953
+ function isRuntimeBindingArrayExpression(node) {
954
+ return node?.type === "ArrayExpression" && isRuntimeBindingArrayElements(node.elements);
955
+ }
956
+ /**
957
+ * Check if the given array is a {@link RuntimeBindingArrayElements}
958
+ */
959
+ function isRuntimeBindingArrayElements(elements) {
960
+ const [declarationId, deps, children, effect] = elements;
961
+ return is.NumericLiteral(declarationId) && deps?.type === "ArrowFunctionExpression" && children?.type === "ArrayExpression" && (!effect || effect.type === "CallExpression");
962
+ }
963
+ function runtimeBindingArrayExpression(elements) {
964
+ return b.arrayExpression([...elements]);
965
+ }
966
+ function isThisExpression(node) {
967
+ return is.Identifier(node, "this") || node.type === "ThisExpression" || node.type === "MemberExpression" && isThisExpression(node.object);
968
+ }
969
+ function isInfer(node) {
970
+ return is.Identifier(node, "infer");
971
+ }
972
+ function TSEntityNameToRuntime(node) {
973
+ if (node.type === "Identifier" || node.type === "ThisExpression") return node;
974
+ const left = TSEntityNameToRuntime(node.left);
975
+ return Object.assign(node, {
976
+ type: "MemberExpression",
977
+ object: left,
978
+ property: node.right,
979
+ computed: false
980
+ });
981
+ }
982
+ function getIdFromTSEntityName(node) {
983
+ if (node.type === "Identifier" || node.type === "ThisExpression") return node;
984
+ return getIdFromTSEntityName(node.left);
985
+ }
986
+ function isReferenceId(node) {
987
+ return is.oneOf(node, ["Identifier", "MemberExpression"]);
988
+ }
989
+ function isHelperImport(node) {
990
+ return node.type === "ImportDeclaration" && node.specifiers.length && node.specifiers.every((spec) => spec.type === "ImportSpecifier" && spec.imported.type === "Identifier" && ["__exportAll", "__reExport"].includes(spec.local.name));
991
+ }
992
+ /**
993
+ * patch `.d.ts` suffix in import source to `.js`
994
+ */
995
+ function patchImportExport(node, exportInfo, cjsDefault) {
996
+ if (node.type === "ExportNamedDeclaration" && !node.declaration && !node.source && !node.specifiers.length && !node.attributes?.length) return false;
997
+ if (node.type === "ImportDeclaration" && node.specifiers.length) {
998
+ for (const specifier of node.specifiers) if (isInfer(specifier.local)) specifier.local.name = "__Infer";
999
+ }
1000
+ if (is.oneOf(node, [
1001
+ "ImportDeclaration",
1002
+ "ExportAllDeclaration",
1003
+ "ExportNamedDeclaration"
1004
+ ])) {
1005
+ if (node.type === "ExportAllDeclaration" && node.source && exportInfo.typeOnlyExportAllSources.has(node.source.value)) node.exportKind = "type";
1006
+ if (node.type === "ExportNamedDeclaration" && exportInfo.typeOnlyNames.size) {
1007
+ for (const spec of node.specifiers) {
1008
+ const name = nameOf(spec.exported);
1009
+ if (exportInfo.typeOnlyNames.has(name)) if (spec.type === "ExportSpecifier") spec.exportKind = "type";
1010
+ else node.exportKind = "type";
1033
1011
  }
1034
- },
1035
- generateBundle: emitDtsOnly ? (options, bundle) => {
1036
- for (const fileName of Object.keys(bundle)) if (bundle[fileName].type === "chunk" && !RE_DTS.test(fileName) && !RE_DTS_MAP.test(fileName)) delete bundle[fileName];
1037
- } : void 0,
1038
- async buildEnd() {
1039
- tscWorker?.kill();
1040
- tscWorker = void 0;
1041
- await tsgoContext?.dispose();
1042
- tsgoContext = void 0;
1043
- if (newContext) tscContext = void 0;
1044
- },
1045
- watchChange(id) {
1046
- if (tscModule) invalidateContextFile(tscContext || globalContext, id);
1012
+ normalizeTypeOnlyExport(node);
1047
1013
  }
1048
- };
1014
+ if (node.source?.value && RE_DTS.test(node.source.value)) {
1015
+ node.source.value = filename_dts_to(node.source.value, "js");
1016
+ return node;
1017
+ }
1018
+ if (cjsDefault && node.type === "ExportNamedDeclaration" && !node.source && node.specifiers.length === 1 && node.specifiers[0].type === "ExportSpecifier" && nameOf(node.specifiers[0].exported) === "default") {
1019
+ const defaultExport = node.specifiers[0];
1020
+ return b.tsExportAssignment(defaultExport.local);
1021
+ }
1022
+ }
1049
1023
  }
1050
- function createTscWorker() {
1051
- const childProcess = fork(new URL(WORKER_URL, import.meta.url), {
1052
- stdio: "inherit",
1053
- serialization: "advanced"
1054
- });
1055
- const pending = /* @__PURE__ */ new Map();
1056
- let nextId = 0;
1057
- childProcess.on("message", (response) => {
1058
- const handler = pending.get(response.id);
1059
- if (!handler) return;
1060
- pending.delete(response.id);
1061
- if (response.error) handler.reject(response.error);
1062
- else handler.resolve(response.result);
1063
- });
1064
- childProcess.on("exit", (code) => {
1065
- for (const handler of pending.values()) handler.reject(/* @__PURE__ */ new Error(`tsc worker exited with code ${code}`));
1066
- pending.clear();
1067
- });
1024
+ function normalizeTypeOnlyExport(node) {
1025
+ if (node.declaration || !node.specifiers.length) return;
1026
+ for (const specifier of node.specifiers) if (specifier.type !== "ExportSpecifier" || specifier.exportKind !== "type") return;
1027
+ node.exportKind = "type";
1028
+ for (const specifier of node.specifiers) if (specifier.type === "ExportSpecifier") specifier.exportKind = "value";
1029
+ }
1030
+ /**
1031
+ * Handle `__exportAll` call
1032
+ */
1033
+ function patchTsNamespace(nodes) {
1034
+ const removed = /* @__PURE__ */ new Set();
1035
+ for (const [i, node] of nodes.entries()) {
1036
+ const result = getExportAllNamespace(node);
1037
+ if (!result) continue;
1038
+ const [binding, exports] = result;
1039
+ if (!exports.properties.length) continue;
1040
+ const namespaceExport = b.exportNamedDeclaration(null, exports.properties.filter((property) => property.type === "Property").map((property) => {
1041
+ const local = property.value.body;
1042
+ const exported = property.key;
1043
+ return b.exportSpecifier(local, exported);
1044
+ }));
1045
+ nodes[i] = b.tsModuleDeclaration(binding, b.tsModuleBlock([namespaceExport]), {
1046
+ kind: "namespace",
1047
+ declare: true
1048
+ });
1049
+ }
1050
+ return nodes.filter((node) => !removed.has(node));
1051
+ }
1052
+ function getExportAllNamespace(node) {
1053
+ if (node.type !== "VariableDeclaration" || node.declarations.length !== 1 || node.declarations[0].id.type !== "Identifier" || node.declarations[0].init?.type !== "CallExpression" || node.declarations[0].init.callee.type !== "Identifier" || node.declarations[0].init.callee.name !== "__exportAll" || node.declarations[0].init.arguments.length !== 1 || node.declarations[0].init.arguments[0].type !== "ObjectExpression") return false;
1054
+ return [node.declarations[0].id, node.declarations[0].init.arguments[0]];
1055
+ }
1056
+ /**
1057
+ * Handle `__reExport` call
1058
+ */
1059
+ function patchReExport(nodes) {
1060
+ const exportsNames = /* @__PURE__ */ new Map();
1061
+ for (const [i, node] of nodes.entries()) if (node.type === "ImportDeclaration" && node.specifiers.length === 1 && node.specifiers[0].type === "ImportSpecifier" && node.specifiers[0].local.type === "Identifier" && node.specifiers[0].local.name.endsWith("_exports")) exportsNames.set(node.specifiers[0].local.name, node.specifiers[0].local.name);
1062
+ else if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && is.Identifier(node.expression.callee, "__reExport")) {
1063
+ const args = node.expression.arguments;
1064
+ exportsNames.set(args[0].name, args[1].name);
1065
+ } else if (node.type === "VariableDeclaration" && node.declarations.length === 1 && node.declarations[0].init?.type === "MemberExpression" && node.declarations[0].init.object.type === "Identifier" && exportsNames.has(node.declarations[0].init.object.name)) nodes[i] = b.tsTypeAliasDeclaration(b.identifier(node.declarations[0].id.name), b.tsTypeReference(b.tsQualifiedName(b.identifier(exportsNames.get(node.declarations[0].init.object.name)), b.identifier(node.declarations[0].init.property.name))));
1066
+ else if (node.type === "ExportNamedDeclaration" && node.specifiers.length === 1 && node.specifiers[0].type === "ExportSpecifier" && node.specifiers[0].local.type === "Identifier" && exportsNames.has(node.specifiers[0].local.name)) node.specifiers[0].local.name = exportsNames.get(node.specifiers[0].local.name);
1067
+ return nodes;
1068
+ }
1069
+ function rewriteImportExport(node, set) {
1070
+ if (node.type === "ImportDeclaration" || node.type === "ExportNamedDeclaration" && !node.declaration) {
1071
+ for (const specifier of node.specifiers) if (specifier.type === "ImportSpecifier") specifier.importKind = "value";
1072
+ else if (specifier.type === "ExportSpecifier") specifier.exportKind = "value";
1073
+ if (node.type === "ImportDeclaration") node.importKind = "value";
1074
+ else if (node.type === "ExportNamedDeclaration") node.exportKind = "value";
1075
+ return true;
1076
+ } else if (node.type === "ExportAllDeclaration") {
1077
+ node.exportKind = "value";
1078
+ return true;
1079
+ } else if (node.type === "TSImportEqualsDeclaration") {
1080
+ if (node.moduleReference.type === "TSExternalModuleReference") set(b.importDeclaration([b.importDefaultSpecifier(node.id)], node.moduleReference.expression));
1081
+ return true;
1082
+ } else if (node.type === "TSExportAssignment" && node.expression.type === "Identifier") {
1083
+ set(b.exportNamedDeclaration(null, [b.exportSpecifier(node.expression, b.identifier("default"))]));
1084
+ return true;
1085
+ } else if (node.type === "ExportDefaultDeclaration" && node.declaration.type === "Identifier") {
1086
+ set(b.exportNamedDeclaration(null, [b.exportSpecifier(node.declaration, b.identifier("default"))]));
1087
+ return true;
1088
+ }
1089
+ return false;
1090
+ }
1091
+ function overwriteNode(node, newNode) {
1092
+ for (const key of Object.keys(node)) Reflect.deleteProperty(node, key);
1093
+ Object.assign(node, newNode);
1094
+ return node;
1095
+ }
1096
+ function inheritNodeComments(oldNode, newNode) {
1097
+ newNode.comments ||= [];
1098
+ const pragmas = oldNode.comments?.filter((comment) => comment.position === "before" && comment.value.startsWith("#") && !isSourceMapPragma(comment));
1099
+ if (pragmas) newNode.comments.unshift(...pragmas);
1100
+ newNode.comments = newNode.comments.filter((comment) => !REFERENCE_RE.test(comment.value) && !isSourceMapPragma(comment));
1101
+ return newNode;
1102
+ }
1103
+ function getIdentifierIndex(identifierMap, name) {
1104
+ if (name in identifierMap) return ++identifierMap[name];
1105
+ return identifierMap[name] = 0;
1106
+ }
1107
+ //#endregion
1108
+ //#region src/tsc/vue.ts
1109
+ const require = createRequire(import.meta.url);
1110
+ const debug$3 = createDebug("rolldown-plugin-dts:vue");
1111
+ const RE_VUE = /\.vue$/;
1112
+ function getVueVolarPlugin() {
1113
+ const ts = requireTS(`Vue support requires TypeScript to be installed. Please install \`typescript\` package.`);
1114
+ const [volarTypeScript, vue] = loadVueLanguageTools();
1115
+ const getLanguagePlugin = (ts, options) => {
1116
+ const $rootDir = options.options.$rootDir;
1117
+ const $configRaw = options.options.$configRaw;
1118
+ const resolver = new vue.CompilerOptionsResolver(ts, ts.sys.readFile);
1119
+ resolver.addConfig($configRaw?.vueCompilerOptions ?? {}, $rootDir);
1120
+ const vueOptions = resolver.build();
1121
+ return vue.createVueLanguagePlugin(ts, options.options, vueOptions, (id) => id);
1122
+ };
1068
1123
  return {
1069
- emit: (options) => new Promise((resolve, reject) => {
1070
- const id = nextId++;
1071
- pending.set(id, {
1072
- resolve,
1073
- reject
1074
- });
1075
- childProcess.send({
1076
- id,
1077
- options
1078
- });
1079
- }),
1080
- kill: () => childProcess.kill()
1124
+ extensionPatterns: [RE_VUE],
1125
+ tsFileExtensionInfos: [{
1126
+ extension: "vue",
1127
+ isMixedContent: true,
1128
+ scriptKind: ts.ScriptKind.Deferred
1129
+ }],
1130
+ volarTypeScript,
1131
+ create(ts, options) {
1132
+ return [getLanguagePlugin(ts, options)];
1133
+ },
1134
+ toTsFilename(id) {
1135
+ return id.replace(RE_VUE, ".vue.ts");
1136
+ }
1081
1137
  };
1082
1138
  }
1083
- function collectJsonExportMap(code) {
1084
- const exportMap = /* @__PURE__ */ new Map();
1085
- const { program } = parse(code, {
1086
- sourceType: "module",
1087
- lang: "dts"
1088
- });
1089
- for (const decl of program.body) if (decl.type === "ExportNamedDeclaration") {
1090
- if (decl.declaration) {
1091
- if (decl.declaration.type === "VariableDeclaration") {
1092
- for (const vdecl of decl.declaration.declarations) if (vdecl.id.type === "Identifier") exportMap.set(vdecl.id.name, vdecl.id.name);
1093
- } else if (decl.declaration.type === "TSModuleDeclaration" && decl.declaration.id.type === "Identifier") exportMap.set(decl.declaration.id.name, decl.declaration.id.name);
1094
- } else if (decl.specifiers.length) {
1095
- for (const spec of decl.specifiers) if (spec.type === "ExportSpecifier" && spec.exported.type === "Identifier") exportMap.set(spec.exported.name, spec.local.type === "Identifier" ? spec.local.name : spec.exported.name);
1096
- }
1139
+ function loadVueLanguageTools() {
1140
+ debug$3("loading vue language tools");
1141
+ try {
1142
+ const vueTscPath = require.resolve("vue-tsc");
1143
+ return [require(require.resolve("@volar/typescript", { paths: [vueTscPath] })), require(require.resolve("@vue/language-core", { paths: [vueTscPath] }))];
1144
+ } catch (cause) {
1145
+ debug$3("vue language tools not found", cause);
1146
+ throw new Error("Failed to load vue language tools. Please manually install vue-tsc.", { cause });
1097
1147
  }
1098
- return exportMap;
1099
- }
1100
- /** `declare const _exports` mode */
1101
- function collectJsonExports(code) {
1102
- const exports = [];
1103
- const { program } = parse(code, {
1104
- sourceType: "module",
1105
- lang: "dts"
1106
- });
1107
- const members = program.body[0].declarations[0].id.typeAnnotation.typeAnnotation.members;
1108
- for (const member of members) if (member.key.type === "Identifier") exports.push(member.key.name);
1109
- else if (is.StringLiteral(member.key)) exports.push(member.key.value);
1110
- return exports;
1111
1148
  }
1112
1149
  //#endregion
1150
+ //#region src/volar.ts
1151
+ var VolarContext = class {
1152
+ plugins;
1153
+ patterns;
1154
+ constructor(plugins) {
1155
+ this.plugins = plugins;
1156
+ this.patterns = plugins.flatMap((plugin) => plugin.extensionPatterns);
1157
+ }
1158
+ isVolarFile(id) {
1159
+ return this.plugins.some((plugin) => plugin.extensionPatterns.some((pattern) => pattern.test(id)));
1160
+ }
1161
+ getExtraFileExtensions() {
1162
+ if (!this.plugins.length) return;
1163
+ return this.plugins.flatMap((plugin) => plugin.tsFileExtensionInfos);
1164
+ }
1165
+ getCreateProgram(ts) {
1166
+ if (!this.plugins.length) return ts.createProgram;
1167
+ const { proxyCreateProgram } = this.plugins[0].volarTypeScript;
1168
+ return proxyCreateProgram(ts, ts.createProgram, (ts, options) => {
1169
+ const setups = [];
1170
+ const plugins = [];
1171
+ for (const plugin of this.plugins) {
1172
+ const result = plugin.create(ts, options);
1173
+ if (Array.isArray(result)) plugins.push(...result);
1174
+ else {
1175
+ if (result.setup) setups.push(result.setup);
1176
+ plugins.push(...result.languagePlugins);
1177
+ }
1178
+ }
1179
+ return {
1180
+ setup: setups.length ? (language) => {
1181
+ for (const setup of setups) setup(language);
1182
+ } : void 0,
1183
+ languagePlugins: plugins
1184
+ };
1185
+ });
1186
+ }
1187
+ toTsFilename(id) {
1188
+ for (const plugin of this.plugins) if (plugin.toTsFilename && plugin.extensionPatterns.some((pattern) => pattern.test(id))) return plugin.toTsFilename(id);
1189
+ return id;
1190
+ }
1191
+ };
1192
+ //#endregion
1113
1193
  //#region src/options.ts
1114
1194
  const debug$2 = createDebug("rolldown-plugin-dts:options");
1115
1195
  let warnedTsgo = false;
1116
- function resolveOptions({ generator, entry, cwd = process.cwd(), dtsInput = false, emitDtsOnly = false, tsconfig, tsconfigRaw: overriddenTsconfigRaw = {}, compilerOptions = {}, sourcemap, resolver = "oxc", cjsDefault = false, sideEffects = false, logger = console, build = false, incremental = false, vue = false, tsMacro = false, parallel = false, eager = false, newContext = false, emitJs, oxc, tsgo }) {
1196
+ function resolveOptions({ generator, entry, cwd = process.cwd(), dtsInput = false, emitDtsOnly = false, tsconfig, tsconfigRaw: overriddenTsconfigRaw = {}, compilerOptions = {}, sourcemap, resolver = "oxc", cjsDefault = false, sideEffects = false, logger = console, volarPlugins, build = false, incremental = false, vue = false, parallel = false, eager = false, newContext = false, emitJs, oxc, tsgo }) {
1117
1197
  let resolvedTsconfig;
1118
1198
  if (tsconfig === true || tsconfig == null) {
1119
1199
  const { config, path } = getTsconfig(cwd) || {};
@@ -1135,11 +1215,26 @@ function resolveOptions({ generator, entry, cwd = process.cwd(), dtsInput = fals
1135
1215
  ...overriddenTsconfigRaw,
1136
1216
  compilerOptions
1137
1217
  };
1138
- if (!generator) if (vue || tsMacro) generator = "tsc";
1139
- else if (tsgo) generator = "tsgo";
1218
+ volarPlugins ||= [];
1219
+ if (vue) volarPlugins.push(getVueVolarPlugin());
1220
+ if (volarPlugins.length) {
1221
+ if (isTS70Installed()) throw new Error("TypeScript 7.0 does not yet have a stable API and is experimental. The `vue` and `volarPlugins` options are not yet supported with TypeScript 7.0.");
1222
+ if (generator && generator !== "tsc") logger.warn("The `vue` and `volarPlugins` options are enabled, which requires the `tsc` generator. The `generator` option is ignored.");
1223
+ generator = "tsc";
1224
+ }
1225
+ const volarContext = new VolarContext(volarPlugins);
1226
+ if (!generator) if (tsgo) generator = "tsgo";
1140
1227
  else if (oxc || compilerOptions?.isolatedDeclarations) generator = "oxc";
1141
- else if (isTS7Installed()) generator = "tsgo";
1228
+ else if (isTS70Installed()) generator = "tsgo";
1142
1229
  else generator = "tsc";
1230
+ if (generator === "tsc") requireTS("Or enable `isolatedDeclarations` in your `tsconfig.json` to use Oxc instead.");
1231
+ else if (generator === "tsgo") {
1232
+ if (!tsconfig) throw new Error("tsgo generator requires a tsconfig file to be specified.");
1233
+ if (!warnedTsgo) {
1234
+ warnedTsgo = true;
1235
+ logger.warn("TypeScript 7.0 does not yet have a stable API and is experimental. Some options will be unavailable.");
1236
+ }
1237
+ }
1143
1238
  if (oxc === true || !oxc) oxc = {};
1144
1239
  if (oxc) {
1145
1240
  oxc.stripInternal ??= !!compilerOptions?.stripInternal;
@@ -1147,10 +1242,6 @@ function resolveOptions({ generator, entry, cwd = process.cwd(), dtsInput = fals
1147
1242
  }
1148
1243
  if (tsgo === true || !tsgo) tsgo = {};
1149
1244
  emitJs ??= !!(compilerOptions.checkJs || compilerOptions.allowJs);
1150
- if (generator === "tsgo" && !warnedTsgo) {
1151
- logger.warn("TypeScript 7.0 does not yet have a stable API and is experimental. Some options will be unavailable.");
1152
- warnedTsgo = true;
1153
- }
1154
1245
  const resolved = {
1155
1246
  generator,
1156
1247
  entry: entry ? Array.isArray(entry) ? entry : [entry] : void 0,
@@ -1165,12 +1256,11 @@ function resolveOptions({ generator, entry, cwd = process.cwd(), dtsInput = fals
1165
1256
  sideEffects,
1166
1257
  build,
1167
1258
  incremental,
1168
- vue,
1169
- tsMacro,
1170
1259
  parallel,
1171
1260
  eager,
1172
1261
  newContext,
1173
1262
  emitJs,
1263
+ volarContext,
1174
1264
  oxc,
1175
1265
  tsgo,
1176
1266
  logger
@@ -1181,10 +1271,10 @@ function resolveOptions({ generator, entry, cwd = process.cwd(), dtsInput = fals
1181
1271
  //#endregion
1182
1272
  //#region src/resolver.ts
1183
1273
  const debug$1 = createDebug("rolldown-plugin-dts:resolver");
1184
- function isSourceFile(id) {
1185
- return RE_TS.test(id) || RE_VUE.test(id) || RE_JSON.test(id);
1186
- }
1187
- function createDtsResolvePlugin({ cwd, tsconfig, tsconfigRaw, resolver, sideEffects }) {
1274
+ function createDtsResolvePlugin({ cwd, tsconfig, tsconfigRaw, resolver, sideEffects, volarContext }) {
1275
+ function isSourceFile(id) {
1276
+ return RE_TS.test(id) || RE_JSON.test(id) || volarContext.isVolarFile(id);
1277
+ }
1188
1278
  const baseDtsResolver = createResolver({
1189
1279
  tsconfig,
1190
1280
  resolveNodeModules: true,
@@ -1230,7 +1320,7 @@ function createDtsResolvePlugin({ cwd, tsconfig, tsconfigRaw, resolver, sideEffe
1230
1320
  debug$1("Resolving dts import to source file:", id);
1231
1321
  await this.load({ id: dtsResolution });
1232
1322
  return {
1233
- id: filename_to_dts(dtsResolution),
1323
+ id: filename_to_dts(dtsResolution, volarContext),
1234
1324
  moduleSideEffects
1235
1325
  };
1236
1326
  }
@@ -1240,7 +1330,7 @@ function createDtsResolvePlugin({ cwd, tsconfig, tsconfigRaw, resolver, sideEffe
1240
1330
  async function resolveDtsPath(id, importer, rolldownResolution) {
1241
1331
  let dtsPath;
1242
1332
  if (resolver === "tsc") {
1243
- const { tscResolve } = await import("./resolver-DtsKFXi2.mjs");
1333
+ const { tscResolve } = await import("./resolver-cwLsPb2o.mjs");
1244
1334
  dtsPath = tscResolve(id, importer, cwd, tsconfig, tsconfigRaw);
1245
1335
  } else dtsPath = baseDtsResolver(id, importer);
1246
1336
  debug$1("Using %s for dts import: %O -> %O", resolver, id, dtsPath);