rolldown-plugin-dts 0.27.9 → 0.27.11

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,6 +1,6 @@
1
- import { t as __require } from "./rolldown-runtime-CMgrfpPY.mjs";
2
- 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";
3
2
  import { createContext, globalContext, invalidateContextFile } from "./tsc-context.mjs";
3
+ import { t as requireTS } from "./load-tsc-BKULZsrs.mjs";
4
4
  import { createRequire } from "node:module";
5
5
  import { createDebug } from "obug";
6
6
  import { importerId, include } from "rolldown/filter";
@@ -53,52 +53,393 @@ function createDtsInputPlugin({ sideEffects }) {
53
53
  };
54
54
  }
55
55
  //#endregion
56
- //#region src/fake-js.ts
57
- function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
58
- let declarationIdx = 0;
59
- const declarationMap = /* @__PURE__ */ new Map();
60
- const commentsMap = /* @__PURE__ */ new Map();
61
- const moduleExportsMap = /* @__PURE__ */ new Map();
62
- 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" });
63
109
  return {
64
- 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
+ },
65
166
  outputOptions(options) {
66
- if (options.format === "cjs" || options.format === "commonjs") throw new Error("[rolldown-plugin-dts] Cannot bundle dts files with `cjs` format.");
67
- const { chunkFileNames, entryFileNames } = options;
68
167
  return {
69
168
  ...options,
70
- sourcemap: options.sourcemap || sourcemap,
71
- chunkFileNames(chunk) {
72
- 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);
73
172
  if (chunk.name.endsWith(".d")) {
74
- const renderedNameWithoutD = filename_js_to_dts(replaceTemplateName(nameTemplate, chunk.name.slice(0, -2)));
75
- if (RE_DTS.test(renderedNameWithoutD)) return renderedNameWithoutD;
76
- const renderedName = filename_js_to_dts(replaceTemplateName(nameTemplate, chunk.name));
77
- 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");
78
175
  }
79
176
  return nameTemplate;
80
177
  }
81
178
  };
82
179
  },
180
+ resolveId(id) {
181
+ if (dtsMap.has(id)) {
182
+ debug$4("resolve dts id %s", id);
183
+ return { id };
184
+ }
185
+ },
83
186
  transform: {
84
- filter: { id: RE_DTS },
85
- 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
+ }
86
228
  },
87
- renderChunk,
88
- generateBundle(options, bundle) {
89
- for (const chunk of Object.values(bundle)) {
90
- if (!RE_DTS_MAP.test(chunk.fileName)) continue;
91
- if (sourcemap) {
92
- if (chunk.type === "chunk" || typeof chunk.source !== "string") continue;
93
- const map = JSON.parse(chunk.source);
94
- map.sourcesContent = void 0;
95
- chunk.source = JSON.stringify(map);
96
- } 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
+ };
97
317
  }
98
- }
99
- };
100
- async function transform(code, id) {
101
- let file;
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;
102
443
  try {
103
444
  file = parse(code, {
104
445
  lang: "dts",
@@ -124,7 +465,6 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
124
465
  if (rewriteImportExport(stmt, setStmt)) continue;
125
466
  const sideEffect = stmt.type === "TSModuleDeclaration" && stmt.kind !== "namespace";
126
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}.`);
127
- if (sideEffect && id.endsWith(".vue.d.ts") && code.slice(stmt.start, stmt.end).includes("__VLS_")) continue;
128
468
  const isDefaultExport = stmt.type === "ExportDefaultDeclaration";
129
469
  const isExportDecl = is.oneOf(stmt, ["ExportNamedDeclaration", "ExportDefaultDeclaration"]) && !!stmt.declaration;
130
470
  const decl = isExportDecl ? stmt.declaration : stmt;
@@ -268,7 +608,7 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
268
608
  return inheritNodeComments(node, declaration.decl);
269
609
  }).filter((node) => !!node);
270
610
  if (program.body.length === 0) return {
271
- code: "export { };",
611
+ code: EMPTY_STUB,
272
612
  map: null
273
613
  };
274
614
  const comments = /* @__PURE__ */ new Set();
@@ -560,556 +900,300 @@ function importNamespace(node, imported, source, namespaceStmts, identifierMap,
560
900
  stmt: b.importDeclaration([b.importNamespaceSpecifier(local)], source),
561
901
  local
562
902
  });
563
- if (imported) {
564
- const importedLeft = getIdFromTSEntityName(imported);
565
- if (imported.type === "ThisExpression" || importedLeft.type === "ThisExpression") throw new Error("Cannot import `this` from module.");
566
- overwriteNode(importedLeft, b.tsQualifiedName(local, { ...importedLeft }));
567
- local = imported;
568
- }
569
- let replacement = node;
570
- if (node.typeArguments) {
571
- overwriteNode(node, b.tsTypeReference(local, node.typeArguments));
572
- replacement = local;
573
- } else overwriteNode(node, local);
574
- return {
575
- ...TSEntityNameToRuntime(local),
576
- replace(newNode) {
577
- overwriteNode(replacement, newNode);
578
- }
579
- };
580
- }
581
- function isChildSymbol(node, parent) {
582
- if (node.type === "Identifier") return true;
583
- if (is.oneOf(parent, ["TSPropertySignature", "TSMethodSignature"]) && parent.key === node) return true;
584
- return false;
585
- }
586
- function collectInferredNames(node) {
587
- const inferred = [];
588
- walk(node, { enter(node) {
589
- if (node.type === "TSInferType" && node.typeParameter) inferred.push(node.typeParameter.name.name);
590
- } });
591
- return inferred;
592
- }
593
- const REFERENCE_RE = /\/\s*<reference\s+(?:path|types)=/;
594
- function collectReferenceDirectives(comment, negative = false) {
595
- return comment.filter((c) => REFERENCE_RE.test(c.value) !== negative);
596
- }
597
- const SOURCE_MAP_PRAGMA_RE = /^#\s*source(?:Mapping)?URL=/;
598
- function isSourceMapPragma(comment) {
599
- return SOURCE_MAP_PRAGMA_RE.test(comment.value);
600
- }
601
- function isCjsDtsInputSyntax(node) {
602
- return node.type === "TSExportAssignment" || node.type === "TSImportEqualsDeclaration" && node.moduleReference.type === "TSExternalModuleReference";
603
- }
604
- /**
605
- * Check if the given node is a {@link RuntimeBindingVariableDeclration}
606
- */
607
- function isRuntimeBindingVariableDeclaration(node) {
608
- return node?.type === "VariableDeclaration" && node.declarations.length === 1 && node.declarations[0].type === "VariableDeclarator" && node.declarations[0].id.type === "ArrayPattern" && isRuntimeBindingArrayExpression(node.declarations[0].init);
609
- }
610
- /**
611
- * Check if the given node is a {@link RuntimeBindingArrayExpression}
612
- */
613
- function isRuntimeBindingArrayExpression(node) {
614
- return node?.type === "ArrayExpression" && isRuntimeBindingArrayElements(node.elements);
615
- }
616
- /**
617
- * Check if the given array is a {@link RuntimeBindingArrayElements}
618
- */
619
- function isRuntimeBindingArrayElements(elements) {
620
- const [declarationId, deps, children, effect] = elements;
621
- return is.NumericLiteral(declarationId) && deps?.type === "ArrowFunctionExpression" && children?.type === "ArrayExpression" && (!effect || effect.type === "CallExpression");
622
- }
623
- function runtimeBindingArrayExpression(elements) {
624
- return b.arrayExpression([...elements]);
625
- }
626
- function isThisExpression(node) {
627
- return is.Identifier(node, "this") || node.type === "ThisExpression" || node.type === "MemberExpression" && isThisExpression(node.object);
628
- }
629
- function isInfer(node) {
630
- return is.Identifier(node, "infer");
631
- }
632
- function TSEntityNameToRuntime(node) {
633
- if (node.type === "Identifier" || node.type === "ThisExpression") return node;
634
- const left = TSEntityNameToRuntime(node.left);
635
- return Object.assign(node, {
636
- type: "MemberExpression",
637
- object: left,
638
- property: node.right,
639
- computed: false
640
- });
641
- }
642
- function getIdFromTSEntityName(node) {
643
- if (node.type === "Identifier" || node.type === "ThisExpression") return node;
644
- return getIdFromTSEntityName(node.left);
645
- }
646
- function isReferenceId(node) {
647
- return is.oneOf(node, ["Identifier", "MemberExpression"]);
648
- }
649
- function isHelperImport(node) {
650
- return node.type === "ImportDeclaration" && node.specifiers.length && node.specifiers.every((spec) => spec.type === "ImportSpecifier" && spec.imported.type === "Identifier" && ["__exportAll", "__reExport"].includes(spec.local.name));
651
- }
652
- /**
653
- * patch `.d.ts` suffix in import source to `.js`
654
- */
655
- function patchImportExport(node, exportInfo, cjsDefault) {
656
- if (node.type === "ExportNamedDeclaration" && !node.declaration && !node.source && !node.specifiers.length && !node.attributes?.length) return false;
657
- if (node.type === "ImportDeclaration" && node.specifiers.length) {
658
- for (const specifier of node.specifiers) if (isInfer(specifier.local)) specifier.local.name = "__Infer";
659
- }
660
- if (is.oneOf(node, [
661
- "ImportDeclaration",
662
- "ExportAllDeclaration",
663
- "ExportNamedDeclaration"
664
- ])) {
665
- if (node.type === "ExportAllDeclaration" && node.source && exportInfo.typeOnlyExportAllSources.has(node.source.value)) node.exportKind = "type";
666
- if (node.type === "ExportNamedDeclaration" && exportInfo.typeOnlyNames.size) {
667
- for (const spec of node.specifiers) {
668
- const name = nameOf(spec.exported);
669
- if (exportInfo.typeOnlyNames.has(name)) if (spec.type === "ExportSpecifier") spec.exportKind = "type";
670
- else node.exportKind = "type";
671
- }
672
- normalizeTypeOnlyExport(node);
673
- }
674
- if (node.source?.value && RE_DTS.test(node.source.value)) {
675
- node.source.value = filename_dts_to(node.source.value, "js");
676
- return node;
677
- }
678
- if (cjsDefault && node.type === "ExportNamedDeclaration" && !node.source && node.specifiers.length === 1 && node.specifiers[0].type === "ExportSpecifier" && nameOf(node.specifiers[0].exported) === "default") {
679
- const defaultExport = node.specifiers[0];
680
- return b.tsExportAssignment(defaultExport.local);
681
- }
682
- }
683
- }
684
- function normalizeTypeOnlyExport(node) {
685
- if (node.declaration || !node.specifiers.length) return;
686
- for (const specifier of node.specifiers) if (specifier.type !== "ExportSpecifier" || specifier.exportKind !== "type") return;
687
- node.exportKind = "type";
688
- for (const specifier of node.specifiers) if (specifier.type === "ExportSpecifier") specifier.exportKind = "value";
689
- }
690
- /**
691
- * Handle `__exportAll` call
692
- */
693
- function patchTsNamespace(nodes) {
694
- const removed = /* @__PURE__ */ new Set();
695
- for (const [i, node] of nodes.entries()) {
696
- const result = getExportAllNamespace(node);
697
- if (!result) continue;
698
- const [binding, exports] = result;
699
- if (!exports.properties.length) continue;
700
- const namespaceExport = b.exportNamedDeclaration(null, exports.properties.filter((property) => property.type === "Property").map((property) => {
701
- const local = property.value.body;
702
- const exported = property.key;
703
- return b.exportSpecifier(local, exported);
704
- }));
705
- nodes[i] = b.tsModuleDeclaration(binding, b.tsModuleBlock([namespaceExport]), {
706
- kind: "namespace",
707
- declare: true
708
- });
709
- }
710
- return nodes.filter((node) => !removed.has(node));
711
- }
712
- function getExportAllNamespace(node) {
713
- 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;
714
- return [node.declarations[0].id, node.declarations[0].init.arguments[0]];
715
- }
716
- /**
717
- * Handle `__reExport` call
718
- */
719
- function patchReExport(nodes) {
720
- const exportsNames = /* @__PURE__ */ new Map();
721
- 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);
722
- else if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && is.Identifier(node.expression.callee, "__reExport")) {
723
- const args = node.expression.arguments;
724
- exportsNames.set(args[0].name, args[1].name);
725
- } 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))));
726
- 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);
727
- return nodes;
728
- }
729
- function rewriteImportExport(node, set) {
730
- if (node.type === "ImportDeclaration" || node.type === "ExportNamedDeclaration" && !node.declaration) {
731
- for (const specifier of node.specifiers) if (specifier.type === "ImportSpecifier") specifier.importKind = "value";
732
- else if (specifier.type === "ExportSpecifier") specifier.exportKind = "value";
733
- if (node.type === "ImportDeclaration") node.importKind = "value";
734
- else if (node.type === "ExportNamedDeclaration") node.exportKind = "value";
735
- return true;
736
- } else if (node.type === "ExportAllDeclaration") {
737
- node.exportKind = "value";
738
- return true;
739
- } else if (node.type === "TSImportEqualsDeclaration") {
740
- if (node.moduleReference.type === "TSExternalModuleReference") set(b.importDeclaration([b.importDefaultSpecifier(node.id)], node.moduleReference.expression));
741
- return true;
742
- } else if (node.type === "TSExportAssignment" && node.expression.type === "Identifier") {
743
- set(b.exportNamedDeclaration(null, [b.exportSpecifier(node.expression, b.identifier("default"))]));
744
- return true;
745
- } else if (node.type === "ExportDefaultDeclaration" && node.declaration.type === "Identifier") {
746
- set(b.exportNamedDeclaration(null, [b.exportSpecifier(node.declaration, b.identifier("default"))]));
747
- return true;
748
- }
749
- return false;
750
- }
751
- function overwriteNode(node, newNode) {
752
- for (const key of Object.keys(node)) Reflect.deleteProperty(node, key);
753
- Object.assign(node, newNode);
754
- return node;
755
- }
756
- function inheritNodeComments(oldNode, newNode) {
757
- newNode.comments ||= [];
758
- const pragmas = oldNode.comments?.filter((comment) => comment.position === "before" && comment.value.startsWith("#") && !isSourceMapPragma(comment));
759
- if (pragmas) newNode.comments.unshift(...pragmas);
760
- newNode.comments = newNode.comments.filter((comment) => !REFERENCE_RE.test(comment.value) && !isSourceMapPragma(comment));
761
- return newNode;
762
- }
763
- function getIdentifierIndex(identifierMap, name) {
764
- if (name in identifierMap) return ++identifierMap[name];
765
- return identifierMap[name] = 0;
766
- }
767
- //#endregion
768
- //#region src/tsgo.ts
769
- const require$1 = createRequire(import.meta.url);
770
- const debug$4 = createDebug("rolldown-plugin-dts:tsgo");
771
- function isTS70Installed() {
772
- try {
773
- const { versionMajorMinor } = require$1("typescript");
774
- return versionMajorMinor === "7.0";
775
- } catch {}
776
- return false;
777
- }
778
- const spawnAsync = (...args) => new Promise((resolve, reject) => {
779
- const child = spawn(...args);
780
- child.on("close", () => resolve());
781
- child.on("error", (error) => reject(error));
782
- });
783
- let tsgoPathCache;
784
- async function getTsgoPathFromNodeModules(logger) {
785
- if (tsgoPathCache) return tsgoPathCache;
786
- const pkgName = isTS70Installed() ? "typescript" : "@typescript/native-preview";
787
- const tsgoPkg = import.meta.resolve(`${pkgName}/package.json`);
788
- const { default: { version } } = await import(tsgoPkg, { with: { type: "json" } });
789
- logger.info(`Emit types with ${styleText("underline", `${pkgName}@${version}`)}`);
790
- const { default: getExePath } = await import(new URL("lib/getExePath.js", tsgoPkg).href);
791
- return tsgoPathCache = getExePath();
792
- }
793
- async function runTsgo(logger, rootDir, tsconfig, sourcemap, tsgoPath) {
794
- debug$4("[tsgo] rootDir", rootDir);
795
- let tsgo;
796
- if (tsgoPath) {
797
- tsgo = tsgoPath;
798
- debug$4("[tsgo] using custom path", tsgo);
799
- } else {
800
- tsgo = await getTsgoPathFromNodeModules(logger);
801
- debug$4("[tsgo] using tsgo from node_modules", tsgo);
802
- }
803
- const tsgoDist = await mkdtemp(path.join(tmpdir(), "rolldown-plugin-dts-"));
804
- debug$4("[tsgo] tsgoDist", tsgoDist);
805
- const args = [
806
- "--noEmit",
807
- "false",
808
- "--declaration",
809
- "--emitDeclarationOnly",
810
- "-p",
811
- tsconfig,
812
- "--outDir",
813
- tsgoDist,
814
- "--rootDir",
815
- rootDir,
816
- "--noCheck",
817
- ...sourcemap ? ["--declarationMap"] : []
818
- ];
819
- debug$4("[tsgo] args %o", args);
820
- await spawnAsync(tsgo, args, { stdio: "inherit" });
821
- return {
822
- path: tsgoDist,
823
- async dispose() {
824
- if (debug$4.enabled) debug$4("[tsgo] skip cleanup of tsgoDist", tsgoDist);
825
- else {
826
- debug$4("[tsgo] disposing tsgoDist", tsgoDist);
827
- await rm(tsgoDist, {
828
- recursive: true,
829
- force: true
830
- }).catch(() => {});
831
- }
832
- }
833
- };
834
- }
835
- //#endregion
836
- //#region src/generate.ts
837
- const debug$3 = createDebug("rolldown-plugin-dts:generate");
838
- const WORKER_URL = "./tsc-worker.mjs";
839
- function createGeneratePlugin({ generator, entry, tsconfig, tsconfigRaw, build, incremental, cwd, oxc, emitDtsOnly, vue, tsMacro, parallel, eager, tsgo, newContext, emitJs, sourcemap, logger }) {
840
- const entryIncludes = entry?.filter((p) => p[0] !== "!");
841
- const entryIgnores = entry?.filter((p) => p[0] === "!").map((p) => p.slice(1));
842
- const entryMatcher = entry ? (file) => entryIncludes.some((p) => path.matchesGlob(file, p)) && !entryIgnores.some((p) => path.matchesGlob(file, p)) : void 0;
843
- const dtsMap = /* @__PURE__ */ new Map();
844
- /**
845
- * A map of input id to output file name
846
- *
847
- * @example
848
- *
849
- * inputAlias = new Map([
850
- * ['/absolute/path/to/src/source_file.ts', 'dist/foo/index'],
851
- * ])
852
- */
853
- const inputAliasMap = /* @__PURE__ */ new Map();
854
- let tscWorker;
855
- let tscModule;
856
- let tscContext;
857
- let tsgoContext;
858
- const rootDir = tsconfig ? path.dirname(tsconfig) : cwd;
859
- return {
860
- name: "rolldown-plugin-dts:generate",
861
- async buildStart(options) {
862
- if (generator === "tsgo") tsgoContext = await runTsgo(logger, rootDir, tsconfig, sourcemap, tsgo.path);
863
- else if (generator === "tsc") if (parallel) tscWorker = createTscWorker();
864
- else {
865
- tscModule = await import("./tsc.mjs");
866
- if (newContext) tscContext = createContext();
867
- }
868
- if (!Array.isArray(options.input)) for (const [name, id] of Object.entries(options.input)) {
869
- debug$3("resolving input alias %s -> %s", name, id);
870
- let resolved = await this.resolve(id);
871
- if (!id.startsWith("./")) resolved ||= await this.resolve(`./${id}`);
872
- const resolvedId = resolved?.id || id;
873
- debug$3("resolved input alias %s -> %s", id, resolvedId);
874
- inputAliasMap.set(resolvedId, name);
875
- }
876
- },
877
- outputOptions(options) {
878
- return {
879
- ...options,
880
- entryFileNames(chunk) {
881
- const { entryFileNames } = options;
882
- const nameTemplate = resolveTemplateFn(entryFileNames || "[name].js", chunk);
883
- if (chunk.name.endsWith(".d")) {
884
- if (RE_DTS.test(nameTemplate)) return replaceTemplateName(nameTemplate, chunk.name.slice(0, -2));
885
- if (RE_JS.test(nameTemplate)) return nameTemplate.replace(RE_JS, ".$1ts");
886
- }
887
- return nameTemplate;
888
- }
889
- };
890
- },
891
- resolveId(id) {
892
- if (dtsMap.has(id)) {
893
- debug$3("resolve dts id %s", id);
894
- return { id };
895
- }
896
- },
897
- transform: {
898
- order: "pre",
899
- filter: { id: {
900
- include: [
901
- RE_JS,
902
- RE_TS,
903
- RE_VUE,
904
- RE_JSON
905
- ],
906
- exclude: [
907
- RE_DTS,
908
- RE_NODE_MODULES,
909
- RE_ROLLDOWN_RUNTIME
910
- ]
911
- } },
912
- handler(code, id) {
913
- const jsFile = RE_JS.test(id);
914
- if (!jsFile || emitJs) {
915
- const mod = this.getModuleInfo(id);
916
- const isEntry = entryMatcher ? entryMatcher(path.relative(cwd, id)) : !!mod?.isEntry;
917
- const dtsId = filename_to_dts(id);
918
- dtsMap.set(dtsId, {
919
- code,
920
- id,
921
- isEntry,
922
- jsFile
923
- });
924
- debug$3("register dts source: %s", id);
925
- if (isEntry) {
926
- const name = inputAliasMap.get(id);
927
- this.emitFile({
928
- type: "chunk",
929
- id: dtsId,
930
- name: name ? `${name}.d` : void 0
931
- });
932
- }
933
- }
934
- if (emitDtsOnly) {
935
- if (RE_JSON.test(id)) return "{}";
936
- return "export { }";
937
- }
938
- }
939
- },
940
- load: {
941
- filter: { id: {
942
- include: [RE_DTS],
943
- exclude: [RE_NODE_MODULES]
944
- } },
945
- async handler(dtsId) {
946
- const module = dtsMap.get(dtsId);
947
- if (!module) return;
948
- const { code, id, jsFile } = module;
949
- if (jsFile && await access(dtsId).then(() => true).catch(() => false)) {
950
- debug$3("dts file already exists for %s, skipping generation", id);
951
- return;
952
- }
953
- let dtsCode;
954
- let map;
955
- debug$3("generate dts %s from %s", dtsId, id);
956
- if (generator === "tsgo") {
957
- if (RE_VUE.test(id)) throw new Error("tsgo does not support Vue files.");
958
- const dtsPath = path.resolve(tsgoContext.path, path.relative(path.resolve(rootDir), filename_to_dts(id)));
959
- if (!existsSync(dtsPath)) {
960
- debug$3("[tsgo]", dtsPath, "is missing");
961
- throw new Error(`tsgo did not generate dts file for ${id}, please check your tsconfig.`);
962
- }
963
- dtsCode = await readFile(dtsPath, "utf8");
964
- const mapPath = `${dtsPath}.map`;
965
- if (existsSync(mapPath)) {
966
- const mapRaw = await readFile(mapPath, "utf8");
967
- map = {
968
- ...JSON.parse(mapRaw),
969
- sources: [id]
970
- };
971
- }
972
- } else if (generator === "oxc" && !RE_VUE.test(id)) {
973
- const result = isolatedDeclarationSync(id, code, oxc);
974
- if (result.errors.length) {
975
- const [error] = result.errors;
976
- return this.error({
977
- message: error.message,
978
- frame: error.codeframe || void 0
979
- });
980
- }
981
- dtsCode = result.code;
982
- if (result.map) {
983
- map = result.map;
984
- map.sourcesContent = void 0;
985
- }
986
- } else {
987
- const options = {
988
- tsconfig,
989
- tsconfigRaw,
990
- build,
991
- incremental,
992
- cwd,
993
- entries: eager ? void 0 : Array.from(dtsMap.values()).filter((v) => v.isEntry).map((v) => v.id),
994
- id,
995
- sourcemap,
996
- vue,
997
- tsMacro,
998
- context: tscContext
999
- };
1000
- let result;
1001
- if (parallel) result = await tscWorker.emit(options);
1002
- else result = tscModule.tscEmit(options);
1003
- if (result.error) return this.error(result.error);
1004
- dtsCode = result.code;
1005
- map = result.map;
1006
- if (dtsCode && RE_JSON.test(id)) if (dtsCode.includes("declare const _exports")) {
1007
- if (dtsCode.includes("declare const _exports: {") && !dtsCode.includes("\n}[];")) {
1008
- const exports = collectJsonExports(dtsCode);
1009
- let i = 0;
1010
- dtsCode += exports.map((e) => {
1011
- const valid = `_${e.replaceAll(/[^\w$]/g, "_")}${i++}`;
1012
- const jsonKey = JSON.stringify(e);
1013
- return `declare let ${valid}: typeof _exports[${jsonKey}]\nexport { ${valid} as ${jsonKey} }`;
1014
- }).join("\n");
1015
- }
1016
- } else {
1017
- const exportMap = collectJsonExportMap(dtsCode);
1018
- dtsCode += `
1019
- declare namespace __json_default_export {
1020
- export { ${Array.from(exportMap.entries()).map(([exported, local]) => exported === local ? exported : `${local} as ${exported}`).join(", ")} }
1021
- }
1022
- export { __json_default_export as default }`;
1023
- }
1024
- }
1025
- return {
1026
- code: dtsCode || "",
1027
- map
1028
- };
1029
- }
1030
- },
1031
- generateBundle: emitDtsOnly ? (options, bundle) => {
1032
- for (const fileName of Object.keys(bundle)) if (bundle[fileName].type === "chunk" && !RE_DTS.test(fileName) && !RE_DTS_MAP.test(fileName)) delete bundle[fileName];
1033
- } : void 0,
1034
- async buildEnd() {
1035
- tscWorker?.kill();
1036
- tscWorker = void 0;
1037
- await tsgoContext?.dispose();
1038
- tsgoContext = void 0;
1039
- if (newContext) tscContext = void 0;
1040
- },
1041
- watchChange(id) {
1042
- if (tscModule) invalidateContextFile(tscContext || globalContext, id);
1043
- }
1044
- };
1045
- }
1046
- function createTscWorker() {
1047
- const childProcess = fork(new URL(WORKER_URL, import.meta.url), {
1048
- stdio: "inherit",
1049
- serialization: "advanced"
1050
- });
1051
- const pending = /* @__PURE__ */ new Map();
1052
- let nextId = 0;
1053
- childProcess.on("message", (response) => {
1054
- const handler = pending.get(response.id);
1055
- if (!handler) return;
1056
- pending.delete(response.id);
1057
- if (response.error) handler.reject(response.error);
1058
- else handler.resolve(response.result);
1059
- });
1060
- childProcess.on("exit", (code) => {
1061
- for (const handler of pending.values()) handler.reject(/* @__PURE__ */ new Error(`tsc worker exited with code ${code}`));
1062
- pending.clear();
1063
- });
903
+ if (imported) {
904
+ const importedLeft = getIdFromTSEntityName(imported);
905
+ if (imported.type === "ThisExpression" || importedLeft.type === "ThisExpression") throw new Error("Cannot import `this` from module.");
906
+ overwriteNode(importedLeft, b.tsQualifiedName(local, { ...importedLeft }));
907
+ local = imported;
908
+ }
909
+ let replacement = node;
910
+ if (node.typeArguments) {
911
+ overwriteNode(node, b.tsTypeReference(local, node.typeArguments));
912
+ replacement = local;
913
+ } else overwriteNode(node, local);
1064
914
  return {
1065
- emit: (options) => new Promise((resolve, reject) => {
1066
- const id = nextId++;
1067
- pending.set(id, {
1068
- resolve,
1069
- reject
1070
- });
1071
- childProcess.send({
1072
- id,
1073
- options
1074
- });
1075
- }),
1076
- kill: () => childProcess.kill()
915
+ ...TSEntityNameToRuntime(local),
916
+ replace(newNode) {
917
+ overwriteNode(replacement, newNode);
918
+ }
1077
919
  };
1078
920
  }
1079
- function collectJsonExportMap(code) {
1080
- const exportMap = /* @__PURE__ */ new Map();
1081
- const { program } = parse(code, {
1082
- sourceType: "module",
1083
- lang: "dts"
921
+ function isChildSymbol(node, parent) {
922
+ if (node.type === "Identifier") return true;
923
+ if (is.oneOf(parent, ["TSPropertySignature", "TSMethodSignature"]) && parent.key === node) return true;
924
+ return false;
925
+ }
926
+ function collectInferredNames(node) {
927
+ const inferred = [];
928
+ walk(node, { enter(node) {
929
+ if (node.type === "TSInferType" && node.typeParameter) inferred.push(node.typeParameter.name.name);
930
+ } });
931
+ return inferred;
932
+ }
933
+ const REFERENCE_RE = /\/\s*<reference\s+(?:path|types)=/;
934
+ function collectReferenceDirectives(comment, negative = false) {
935
+ return comment.filter((c) => REFERENCE_RE.test(c.value) !== negative);
936
+ }
937
+ const SOURCE_MAP_PRAGMA_RE = /^#\s*source(?:Mapping)?URL=/;
938
+ function isSourceMapPragma(comment) {
939
+ return SOURCE_MAP_PRAGMA_RE.test(comment.value);
940
+ }
941
+ function isCjsDtsInputSyntax(node) {
942
+ return node.type === "TSExportAssignment" || node.type === "TSImportEqualsDeclaration" && node.moduleReference.type === "TSExternalModuleReference";
943
+ }
944
+ /**
945
+ * Check if the given node is a {@link RuntimeBindingVariableDeclration}
946
+ */
947
+ function isRuntimeBindingVariableDeclaration(node) {
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);
949
+ }
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
1084
980
  });
1085
- for (const decl of program.body) if (decl.type === "ExportNamedDeclaration") {
1086
- if (decl.declaration) {
1087
- if (decl.declaration.type === "VariableDeclaration") {
1088
- for (const vdecl of decl.declaration.declarations) if (vdecl.id.type === "Identifier") exportMap.set(vdecl.id.name, vdecl.id.name);
1089
- } else if (decl.declaration.type === "TSModuleDeclaration" && decl.declaration.id.type === "Identifier") exportMap.set(decl.declaration.id.name, decl.declaration.id.name);
1090
- } else if (decl.specifiers.length) {
1091
- 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);
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";
1011
+ }
1012
+ normalizeTypeOnlyExport(node);
1013
+ }
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);
1092
1021
  }
1093
1022
  }
1094
- return exportMap;
1095
1023
  }
1096
- /** `declare const _exports` mode */
1097
- function collectJsonExports(code) {
1098
- const exports = [];
1099
- const { program } = parse(code, {
1100
- sourceType: "module",
1101
- lang: "dts"
1102
- });
1103
- const members = program.body[0].declarations[0].id.typeAnnotation.typeAnnotation.members;
1104
- for (const member of members) if (member.key.type === "Identifier") exports.push(member.key.name);
1105
- else if (is.StringLiteral(member.key)) exports.push(member.key.value);
1106
- return exports;
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
+ };
1123
+ return {
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
+ }
1137
+ };
1138
+ }
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 });
1147
+ }
1107
1148
  }
1108
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
1109
1193
  //#region src/options.ts
1110
1194
  const debug$2 = createDebug("rolldown-plugin-dts:options");
1111
1195
  let warnedTsgo = false;
1112
- 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 }) {
1113
1197
  let resolvedTsconfig;
1114
1198
  if (tsconfig === true || tsconfig == null) {
1115
1199
  const { config, path } = getTsconfig(cwd) || {};
@@ -1131,20 +1215,19 @@ function resolveOptions({ generator, entry, cwd = process.cwd(), dtsInput = fals
1131
1215
  ...overriddenTsconfigRaw,
1132
1216
  compilerOptions
1133
1217
  };
1134
- if (vue || tsMacro) {
1135
- if (isTS70Installed()) throw new Error("TypeScript 7.0 does not yet have a stable API and is experimental. The `vue` and `tsMacro` options are not yet supported with TypeScript 7.0.");
1136
- if (generator && generator !== "tsc") logger.warn("The `vue` and `tsMacro` options are enabled, which requires the `tsc` generator. The `generator` option is ignored.");
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.");
1137
1223
  generator = "tsc";
1138
1224
  }
1225
+ const volarContext = new VolarContext(volarPlugins);
1139
1226
  if (!generator) if (tsgo) generator = "tsgo";
1140
1227
  else if (oxc || compilerOptions?.isolatedDeclarations) generator = "oxc";
1141
1228
  else if (isTS70Installed()) generator = "tsgo";
1142
1229
  else generator = "tsc";
1143
- if (generator === "tsc") try {
1144
- __require.resolve("typescript");
1145
- } catch {
1146
- throw new Error("TypeScript is not installed. You can install `typescript` package, or enable `isolatedDeclarations` in your `tsconfig.json` to use Oxc instead.");
1147
- }
1230
+ if (generator === "tsc") requireTS("Or enable `isolatedDeclarations` in your `tsconfig.json` to use Oxc instead.");
1148
1231
  else if (generator === "tsgo") {
1149
1232
  if (!tsconfig) throw new Error("tsgo generator requires a tsconfig file to be specified.");
1150
1233
  if (!warnedTsgo) {
@@ -1173,12 +1256,11 @@ function resolveOptions({ generator, entry, cwd = process.cwd(), dtsInput = fals
1173
1256
  sideEffects,
1174
1257
  build,
1175
1258
  incremental,
1176
- vue,
1177
- tsMacro,
1178
1259
  parallel,
1179
1260
  eager,
1180
1261
  newContext,
1181
1262
  emitJs,
1263
+ volarContext,
1182
1264
  oxc,
1183
1265
  tsgo,
1184
1266
  logger
@@ -1189,10 +1271,10 @@ function resolveOptions({ generator, entry, cwd = process.cwd(), dtsInput = fals
1189
1271
  //#endregion
1190
1272
  //#region src/resolver.ts
1191
1273
  const debug$1 = createDebug("rolldown-plugin-dts:resolver");
1192
- function isSourceFile(id) {
1193
- return RE_TS.test(id) || RE_VUE.test(id) || RE_JSON.test(id);
1194
- }
1195
- 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
+ }
1196
1278
  const baseDtsResolver = createResolver({
1197
1279
  tsconfig,
1198
1280
  resolveNodeModules: true,
@@ -1238,7 +1320,7 @@ function createDtsResolvePlugin({ cwd, tsconfig, tsconfigRaw, resolver, sideEffe
1238
1320
  debug$1("Resolving dts import to source file:", id);
1239
1321
  await this.load({ id: dtsResolution });
1240
1322
  return {
1241
- id: filename_to_dts(dtsResolution),
1323
+ id: filename_to_dts(dtsResolution, volarContext),
1242
1324
  moduleSideEffects
1243
1325
  };
1244
1326
  }
@@ -1248,7 +1330,7 @@ function createDtsResolvePlugin({ cwd, tsconfig, tsconfigRaw, resolver, sideEffe
1248
1330
  async function resolveDtsPath(id, importer, rolldownResolution) {
1249
1331
  let dtsPath;
1250
1332
  if (resolver === "tsc") {
1251
- const { tscResolve } = await import("./resolver-DtsKFXi2.mjs");
1333
+ const { tscResolve } = await import("./resolver-cwLsPb2o.mjs");
1252
1334
  dtsPath = tscResolve(id, importer, cwd, tsconfig, tsconfigRaw);
1253
1335
  } else dtsPath = baseDtsResolver(id, importer);
1254
1336
  debug$1("Using %s for dts import: %O -> %O", resolver, id, dtsPath);