rolldown-plugin-dts 0.25.0 → 0.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,6 +34,20 @@ export default {
34
34
 
35
35
  You can find an example in [here](./rolldown.config.ts).
36
36
 
37
+ ### Vite
38
+
39
+ When using this plugin with Vite, exclude declaration files from Oxc
40
+ transformation to avoid processing generated outputs. Since `oxc.exclude`
41
+ overrides the default exclude list, include JavaScript files as well:
42
+
43
+ ```ts
44
+ dts({
45
+ oxc: {
46
+ exclude: [/\.js$/, /\.d\.[cm]?ts$/],
47
+ },
48
+ })
49
+ ```
50
+
37
51
  ## Options
38
52
 
39
53
  Configuration options for the plugin.
@@ -109,6 +123,8 @@ Determines how the default export is emitted.
109
123
  If set to `true`, and you are only exporting a single item using `export default ...`,
110
124
  the output will use `export = ...` instead of the standard ES module syntax.
111
125
  This is useful for compatibility with CommonJS.
126
+ This option only controls the output format and does not enable support for
127
+ CommonJS-style `.d.ts` input.
112
128
 
113
129
  #### `sideEffects`
114
130
 
@@ -236,6 +252,11 @@ However, this functionality is limited to ESM output format. Consequently,
236
252
  and its corresponding type definition files (`.d.cts`).
237
253
  In such cases, the `emitDtsOnly` option can be particularly helpful.
238
254
 
255
+ The plugin expects ESM-style `.d.ts` input. CommonJS-style declaration syntax
256
+ such as `export =` or `import x = require("x")` will produce a warning and is
257
+ not guaranteed to bundle correctly. If this syntax comes from a dependency in
258
+ `node_modules`, mark that dependency as external in your Rolldown config.
259
+
239
260
  ## Credits
240
261
 
241
262
  The project is inspired by [rollup-plugin-dts](https://github.com/Swatinem/rollup-plugin-dts)
package/dist/index.d.mts CHANGED
@@ -74,6 +74,8 @@ interface GeneralOptions {
74
74
  * If set to `true`, and you are only exporting a single item using `export default ...`,
75
75
  * the output will use `export = ...` instead of the standard ES module syntax.
76
76
  * This is useful for compatibility with CommonJS.
77
+ * This only controls the output format and does not enable support for
78
+ * CommonJS-style `.d.ts` input.
77
79
  */
78
80
  cjsDefault?: boolean;
79
81
  /**
package/dist/index.mjs CHANGED
@@ -5,7 +5,7 @@ import { importerId, include } from "rolldown/filter";
5
5
  import { generate } from "@babel/generator";
6
6
  import { isIdentifierName } from "@babel/helper-validator-identifier";
7
7
  import { parse } from "@babel/parser";
8
- import { isDeclarationType, isIdentifierOf, isTypeOf, resolveString, walkAST } from "ast-kit";
8
+ import { isDeclarationType, isIdentifierOf, isTypeOf, resolveString, walkAST, walkASTAsync } from "ast-kit";
9
9
  import { fork, spawn } from "node:child_process";
10
10
  import { existsSync } from "node:fs";
11
11
  import { mkdtemp, readFile, rm } from "node:fs/promises";
@@ -54,7 +54,8 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
54
54
  let declarationIdx = 0;
55
55
  const declarationMap = /* @__PURE__ */ new Map();
56
56
  const commentsMap = /* @__PURE__ */ new Map();
57
- const typeOnlyMap = /* @__PURE__ */ new Map();
57
+ const moduleExportsMap = /* @__PURE__ */ new Map();
58
+ const warnedCjsDtsInputs = /* @__PURE__ */ new Set();
58
59
  return {
59
60
  name: "rolldown-plugin-dts:fake-js",
60
61
  outputOptions(options) {
@@ -92,7 +93,7 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
92
93
  }
93
94
  }
94
95
  };
95
- function transform(code, id) {
96
+ async function transform(code, id) {
96
97
  let file;
97
98
  try {
98
99
  file = parse(code, {
@@ -105,8 +106,12 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
105
106
  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 });
106
107
  }
107
108
  const { program, comments } = file;
108
- const typeOnlyIds = [];
109
+ moduleExportsMap.set(id, await collectModuleExports(this, program.body, id));
109
110
  const identifierMap = Object.create(null);
111
+ if (!warnedCjsDtsInputs.has(id) && program.body.some(isCjsDtsInputSyntax)) {
112
+ warnedCjsDtsInputs.add(id);
113
+ this.warn(RE_NODE_MODULES.test(id) ? `${id} uses CommonJS dts syntax. CommonJS dts modules cannot be reliably bundled by rolldown-plugin-dts. Please mark this module as external in your Rolldown config.` : `${id} uses CommonJS dts syntax. rolldown-plugin-dts does not support reliably bundling CommonJS dts input.`);
114
+ }
110
115
  if (comments) {
111
116
  const directives = collectReferenceDirectives(comments);
112
117
  commentsMap.set(id, directives);
@@ -115,7 +120,7 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
115
120
  const namespaceStmts = /* @__PURE__ */ new Map();
116
121
  for (const [i, stmt] of program.body.entries()) {
117
122
  const setStmt = (stmt) => program.body[i] = stmt;
118
- if (rewriteImportExport(stmt, setStmt, typeOnlyIds)) continue;
123
+ if (rewriteImportExport(stmt, setStmt)) continue;
119
124
  const sideEffect = stmt.type === "TSModuleDeclaration" && stmt.kind !== "namespace";
120
125
  if (sideEffect && stmt.id.type === "StringLiteral" && 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}.`);
121
126
  if (sideEffect && id.endsWith(".vue.d.ts") && code.slice(stmt.start, stmt.end).includes("__VLS_")) continue;
@@ -153,7 +158,7 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
153
158
  }
154
159
  const params = collectParams(decl);
155
160
  const childrenSet = /* @__PURE__ */ new Set();
156
- const deps = collectDependencies(decl, namespaceStmts, childrenSet, identifierMap);
161
+ const deps = await collectDependencies(this, decl, id, namespaceStmts, childrenSet, identifierMap);
157
162
  const children = Array.from(childrenSet).filter((child) => bindings.every((b) => child !== b));
158
163
  if (decl !== stmt) decl.leadingComments = stmt.leadingComments;
159
164
  const declarationIdNode = {
@@ -256,7 +261,6 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
256
261
  ...program.body,
257
262
  ...appendStmts
258
263
  ];
259
- typeOnlyMap.set(id, typeOnlyIds);
260
264
  const result = generate(file, {
261
265
  comments: false,
262
266
  sourceMaps: sourcemap,
@@ -269,11 +273,7 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
269
273
  }
270
274
  function renderChunk(code, chunk) {
271
275
  if (!RE_DTS.test(chunk.fileName)) return;
272
- const typeOnlyIds = [];
273
- for (const module of chunk.moduleIds) {
274
- const ids = typeOnlyMap.get(module);
275
- if (ids) typeOnlyIds.push(...ids);
276
- }
276
+ const exportInfo = collectChunkExportInfo(chunk, moduleExportsMap);
277
277
  let file;
278
278
  try {
279
279
  file = parse(code, { sourceType: "module" });
@@ -286,7 +286,7 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
286
286
  program.body = program.body.map((node) => {
287
287
  if (isHelperImport(node)) return null;
288
288
  if (node.type === "ExpressionStatement") return null;
289
- const newNode = patchImportExport(node, typeOnlyIds, cjsDefault);
289
+ const newNode = patchImportExport(node, exportInfo, cjsDefault);
290
290
  if (newNode || newNode === false) return newNode;
291
291
  if (node.type !== "VariableDeclaration") return node;
292
292
  if (!isRuntimeBindingVariableDeclaration(node)) return null;
@@ -354,10 +354,6 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
354
354
  map: result.map
355
355
  };
356
356
  }
357
- function getIdentifierIndex(identifierMap, name) {
358
- if (name in identifierMap) return ++identifierMap[name];
359
- return identifierMap[name] = 0;
360
- }
361
357
  function registerDeclaration(info) {
362
358
  const declarationId = declarationIdx++;
363
359
  declarationMap.set(declarationId, info);
@@ -366,141 +362,288 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
366
362
  function getDeclaration(declarationId) {
367
363
  return declarationMap.get(declarationId);
368
364
  }
369
- /**
370
- * Collects all TSTypeParameter nodes from the given node and groups them by
371
- * their name. One name can associate with one or more type parameters. These
372
- * names will be used as the parameter name in the generated JavaScript
373
- * dependency function.
374
- */
375
- function collectParams(node) {
376
- const typeParams = [];
377
- walkAST(node, { leave(node) {
378
- if ("typeParameters" in node && node.typeParameters?.type === "TSTypeParameterDeclaration") typeParams.push(...node.typeParameters.params.map(({ name }) => typeof name === "string" ? {
379
- type: "Identifier",
380
- name
381
- } : name));
382
- } });
383
- const paramMap = /* @__PURE__ */ new Map();
384
- for (const typeParam of typeParams) {
385
- const name = typeParam.name;
386
- const group = paramMap.get(name);
387
- if (group) group.push(typeParam);
388
- else paramMap.set(name, [typeParam]);
365
+ }
366
+ async function collectModuleExports(context, nodes, id) {
367
+ const info = {
368
+ typeOnlyLocals: /* @__PURE__ */ new Set(),
369
+ exports: /* @__PURE__ */ new Map(),
370
+ reExports: [],
371
+ exportAlls: []
372
+ };
373
+ for (const node of nodes) collectTypeOnlyLocals(node, info.typeOnlyLocals);
374
+ for (const node of nodes) await collectExportInfo(context, node, id, info);
375
+ return info;
376
+ }
377
+ function collectTypeOnlyLocals(node, typeOnlyLocals) {
378
+ if (node.type !== "ImportDeclaration") return;
379
+ for (const specifier of node.specifiers) if (node.importKind === "type" || "importKind" in specifier && specifier.importKind === "type") typeOnlyLocals.add(specifier.local.name);
380
+ }
381
+ function collectDeclarationNames(node) {
382
+ if (node.type === "VariableDeclaration") return node.declarations.flatMap((decl) => collectPatternNames(decl.id));
383
+ if ("id" in node && node.id) {
384
+ if (node.id.type !== "Identifier" && node.id.type !== "TSQualifiedName") return [];
385
+ const id = getIdFromTSEntityName(node.id);
386
+ return id.type === "Identifier" ? [id.name] : [];
387
+ }
388
+ return [];
389
+ }
390
+ function collectPatternNames(node) {
391
+ if (!node) return [];
392
+ if (node.type === "Identifier") return [node.name];
393
+ if (node.type === "RestElement") return collectPatternNames(node.argument);
394
+ if (node.type === "AssignmentPattern") return collectPatternNames(node.left);
395
+ if (node.type === "ArrayPattern") return node.elements.flatMap((element) => collectPatternNames(element));
396
+ if (node.type === "ObjectPattern") return node.properties.flatMap((property) => {
397
+ if (property.type === "RestElement") return collectPatternNames(property.argument);
398
+ return collectPatternNames(property.value);
399
+ });
400
+ return [];
401
+ }
402
+ function isTypeOnlyExport(node, specifier) {
403
+ return node.exportKind === "type" || "exportKind" in specifier && specifier.exportKind === "type";
404
+ }
405
+ async function collectExportInfo(context, node, id, info) {
406
+ if (node.type === "ExportNamedDeclaration") {
407
+ if (node.declaration) {
408
+ for (const name of collectDeclarationNames(node.declaration)) info.exports.set(name, false);
409
+ return;
410
+ }
411
+ const source = await resolveExportSource(context, node.source, id);
412
+ for (const specifier of node.specifiers) {
413
+ const typeOnly = isTypeOnlyExport(node, specifier);
414
+ if (specifier.type === "ExportSpecifier") {
415
+ const exported = resolveString(specifier.exported);
416
+ const local = resolveString(specifier.local);
417
+ if (source) info.reExports.push({
418
+ source,
419
+ local,
420
+ exported,
421
+ typeOnly
422
+ });
423
+ else info.exports.set(exported, typeOnly || info.typeOnlyLocals.has(local));
424
+ } else {
425
+ const exported = resolveString(specifier.exported);
426
+ info.exports.set(exported, typeOnly);
427
+ }
389
428
  }
390
- return Array.from(paramMap.entries()).map(([name, typeParams]) => ({
391
- name,
392
- typeParams
393
- }));
429
+ return;
430
+ }
431
+ if (node.type === "ExportDefaultDeclaration") {
432
+ info.exports.set("default", false);
433
+ return;
394
434
  }
395
- function collectDependencies(node, namespaceStmts, children, identifierMap) {
396
- const deps = /* @__PURE__ */ new Set();
397
- const seen = /* @__PURE__ */ new Set();
398
- const inferredStack = [];
399
- let currentInferred = /* @__PURE__ */ new Set();
400
- function isInferred(node) {
401
- return node.type === "Identifier" && currentInferred.has(node.name);
435
+ if (node.type === "ExportAllDeclaration") info.exportAlls.push({
436
+ source: await resolveExportSource(context, node.source, id),
437
+ rawSource: node.source.value,
438
+ typeOnly: node.exportKind === "type"
439
+ });
440
+ }
441
+ async function resolveExportSource(context, source, importer) {
442
+ if (!source) return;
443
+ const resolved = await context.resolve(source.value, importer);
444
+ if (!resolved || resolved.external) return;
445
+ return resolved.id;
446
+ }
447
+ function collectChunkExportInfo(chunk, moduleExportsMap) {
448
+ const exportsByModule = resolveAllModuleExports(moduleExportsMap);
449
+ const roots = chunk.facadeModuleId && moduleExportsMap.has(chunk.facadeModuleId) ? [chunk.facadeModuleId] : chunk.moduleIds;
450
+ const mergedExports = /* @__PURE__ */ new Map();
451
+ const typeOnlyExportAllSources = /* @__PURE__ */ new Set();
452
+ for (const root of roots) {
453
+ const exports = exportsByModule.get(root);
454
+ if (exports) for (const [name, typeOnly] of exports) setExportTypeOnly(mergedExports, name, typeOnly);
455
+ const moduleExports = moduleExportsMap.get(root);
456
+ if (!moduleExports) continue;
457
+ for (const exportAll of moduleExports.exportAlls) {
458
+ if (!exportAll.typeOnly || exportAll.source) continue;
459
+ typeOnlyExportAllSources.add(exportAll.rawSource);
402
460
  }
403
- walkAST(node, {
404
- enter(node) {
405
- if (node.type === "TSConditionalType") {
406
- const inferred = collectInferredNames(node.extendsType);
407
- inferredStack.push(inferred);
408
- }
409
- },
410
- leave(node, parent) {
411
- if (node.type === "TSConditionalType") inferredStack.pop();
412
- else if (parent?.type === "TSConditionalType") {
413
- const trueBranch = parent.trueType === node;
414
- currentInferred = new Set((trueBranch ? inferredStack : inferredStack.slice(0, -1)).flat());
415
- } else currentInferred = /* @__PURE__ */ new Set();
416
- if (node.type === "ExportNamedDeclaration") {
417
- for (const specifier of node.specifiers) if (specifier.type === "ExportSpecifier") addDependency(specifier.local);
418
- } else if (node.type === "TSInterfaceDeclaration" && node.extends) for (const heritage of node.extends || []) addDependency(heritage.expression);
419
- else if (node.type === "ClassDeclaration") {
420
- if (node.superClass) addDependency(node.superClass);
421
- if (node.implements) for (const implement of node.implements) {
422
- if (implement.type === "ClassImplements") throw new Error("Unexpected Flow syntax");
423
- addDependency(implement.expression);
424
- }
425
- } else if (isTypeOf(node, [
426
- "ObjectMethod",
427
- "ObjectProperty",
428
- "ClassProperty",
429
- "TSPropertySignature",
430
- "TSDeclareMethod"
431
- ])) {
432
- if (node.computed && isReferenceId(node.key)) addDependency(node.key);
433
- if ("value" in node && isReferenceId(node.value)) addDependency(node.value);
434
- } else switch (node.type) {
435
- case "TSTypeReference":
436
- addDependency(TSEntityNameToRuntime(node.typeName));
437
- break;
438
- case "TSTypeQuery":
439
- if (seen.has(node.exprName)) return;
440
- if (node.exprName.type === "TSImportType") break;
441
- addDependency(TSEntityNameToRuntime(node.exprName));
442
- break;
443
- case "TSImportType": {
444
- seen.add(node);
445
- const { source, qualifier } = node;
446
- addDependency(importNamespace(node, qualifier, source, namespaceStmts, identifierMap));
447
- break;
448
- }
461
+ }
462
+ const typeOnlyNames = /* @__PURE__ */ new Set();
463
+ for (const [name, typeOnly] of mergedExports) if (typeOnly) typeOnlyNames.add(name);
464
+ return {
465
+ typeOnlyNames,
466
+ typeOnlyExportAllSources
467
+ };
468
+ }
469
+ function resolveAllModuleExports(moduleExportsMap) {
470
+ const exportsByModule = /* @__PURE__ */ new Map();
471
+ for (const [id, info] of moduleExportsMap) exportsByModule.set(id, new Map(info.exports));
472
+ let changed = true;
473
+ while (changed) {
474
+ changed = false;
475
+ for (const [id, info] of moduleExportsMap) {
476
+ const exports = exportsByModule.get(id);
477
+ for (const reExport of info.reExports) {
478
+ const sourceTypeOnly = (reExport.source ? exportsByModule.get(reExport.source) : void 0)?.get(reExport.local) ?? false;
479
+ if (setExportTypeOnly(exports, reExport.exported, reExport.typeOnly || sourceTypeOnly)) changed = true;
480
+ }
481
+ for (const exportAll of info.exportAlls) {
482
+ if (!exportAll.source) continue;
483
+ const sourceExports = exportsByModule.get(exportAll.source);
484
+ if (!sourceExports) continue;
485
+ for (const [name, typeOnly] of sourceExports) {
486
+ if (name === "default") continue;
487
+ if (setExportTypeOnly(exports, name, exportAll.typeOnly || typeOnly)) changed = true;
449
488
  }
450
- if (parent && !deps.has(node) && isChildSymbol(node, parent)) children.add(node);
451
489
  }
452
- });
453
- return Array.from(deps);
454
- function addDependency(node) {
455
- if (isThisExpression(node) || isInferred(node)) return;
456
- deps.add(node);
457
490
  }
458
491
  }
459
- function importNamespace(node, imported, source, namespaceStmts, identifierMap) {
460
- const sourceText = source.value.replaceAll(/\W/g, "_");
461
- let local = {
492
+ return exportsByModule;
493
+ }
494
+ function setExportTypeOnly(exports, name, typeOnly) {
495
+ const current = exports.get(name);
496
+ if (current === false || current === typeOnly) return false;
497
+ if (current === void 0 || !typeOnly) {
498
+ exports.set(name, typeOnly);
499
+ return true;
500
+ }
501
+ return false;
502
+ }
503
+ /**
504
+ * Collects all TSTypeParameter nodes from the given node and groups them by
505
+ * their name. One name can associate with one or more type parameters. These
506
+ * names will be used as the parameter name in the generated JavaScript
507
+ * dependency function.
508
+ */
509
+ function collectParams(node) {
510
+ const typeParams = [];
511
+ walkAST(node, { leave(node) {
512
+ if ("typeParameters" in node && node.typeParameters?.type === "TSTypeParameterDeclaration") typeParams.push(...node.typeParameters.params.map(({ name }) => typeof name === "string" ? {
462
513
  type: "Identifier",
463
- name: `_$${isIdentifierName(source.value) ? source.value : `${sourceText}${getIdentifierIndex(identifierMap, sourceText)}`}`
464
- };
465
- if (namespaceStmts.has(source.value)) local = namespaceStmts.get(source.value).local;
466
- else namespaceStmts.set(source.value, {
467
- stmt: {
468
- type: "ImportDeclaration",
469
- specifiers: [{
470
- type: "ImportNamespaceSpecifier",
471
- local
472
- }],
473
- source,
474
- attributes: null
475
- },
476
- local
477
- });
478
- if (imported) {
479
- const importedLeft = getIdFromTSEntityName(imported);
480
- if (imported.type === "ThisExpression" || importedLeft.type === "ThisExpression") throw new Error("Cannot import `this` from module.");
481
- overwriteNode(importedLeft, {
482
- type: "TSQualifiedName",
483
- left: local,
484
- right: { ...importedLeft }
485
- });
486
- local = imported;
487
- }
488
- let replacement = node;
489
- if (node.typeArguments) {
490
- overwriteNode(node, {
491
- type: "TSTypeReference",
492
- typeName: local,
493
- typeArguments: node.typeArguments
494
- });
495
- replacement = local;
496
- } else overwriteNode(node, local);
497
- return {
498
- ...TSEntityNameToRuntime(local),
499
- replace(newNode) {
500
- overwriteNode(replacement, newNode);
514
+ name
515
+ } : name));
516
+ } });
517
+ const paramMap = /* @__PURE__ */ new Map();
518
+ for (const typeParam of typeParams) {
519
+ const name = typeParam.name;
520
+ const group = paramMap.get(name);
521
+ if (group) group.push(typeParam);
522
+ else paramMap.set(name, [typeParam]);
523
+ }
524
+ return Array.from(paramMap.entries()).map(([name, typeParams]) => ({
525
+ name,
526
+ typeParams
527
+ }));
528
+ }
529
+ async function collectDependencies(context, node, importer, namespaceStmts, children, identifierMap) {
530
+ const deps = /* @__PURE__ */ new Set();
531
+ const seen = /* @__PURE__ */ new Set();
532
+ const preserveImportTypeCache = /* @__PURE__ */ new Map();
533
+ const inferredStack = [];
534
+ let currentInferred = /* @__PURE__ */ new Set();
535
+ function isInferred(node) {
536
+ return node.type === "Identifier" && currentInferred.has(node.name);
537
+ }
538
+ await walkASTAsync(node, {
539
+ enter(node) {
540
+ if (node.type === "TSConditionalType") {
541
+ const inferred = collectInferredNames(node.extendsType);
542
+ inferredStack.push(inferred);
501
543
  }
502
- };
544
+ return Promise.resolve();
545
+ },
546
+ async leave(node, parent) {
547
+ if (node.type === "TSConditionalType") inferredStack.pop();
548
+ else if (parent?.type === "TSConditionalType") {
549
+ const trueBranch = parent.trueType === node;
550
+ currentInferred = new Set((trueBranch ? inferredStack : inferredStack.slice(0, -1)).flat());
551
+ } else currentInferred = /* @__PURE__ */ new Set();
552
+ if (node.type === "ExportNamedDeclaration") {
553
+ for (const specifier of node.specifiers) if (specifier.type === "ExportSpecifier") addDependency(specifier.local);
554
+ } else if (node.type === "TSInterfaceDeclaration" && node.extends) for (const heritage of node.extends || []) addDependency(heritage.expression);
555
+ else if (node.type === "ClassDeclaration") {
556
+ if (node.superClass) addDependency(node.superClass);
557
+ if (node.implements) for (const implement of node.implements) {
558
+ if (implement.type === "ClassImplements") throw new Error("Unexpected Flow syntax");
559
+ addDependency(implement.expression);
560
+ }
561
+ } else if (isTypeOf(node, [
562
+ "ObjectMethod",
563
+ "ObjectProperty",
564
+ "ClassProperty",
565
+ "TSPropertySignature",
566
+ "TSDeclareMethod"
567
+ ])) {
568
+ if (node.computed && isReferenceId(node.key)) addDependency(node.key);
569
+ if ("value" in node && isReferenceId(node.value)) addDependency(node.value);
570
+ } else switch (node.type) {
571
+ case "TSTypeReference":
572
+ addDependency(TSEntityNameToRuntime(node.typeName));
573
+ break;
574
+ case "TSTypeQuery":
575
+ if (seen.has(node.exprName)) return;
576
+ if (node.exprName.type === "TSImportType") break;
577
+ addDependency(TSEntityNameToRuntime(node.exprName));
578
+ break;
579
+ case "TSImportType": {
580
+ seen.add(node);
581
+ const { source, qualifier } = node;
582
+ const dep = await importNamespace(context, importer, node, qualifier, source, namespaceStmts, identifierMap, preserveImportTypeCache);
583
+ if (dep) addDependency(dep);
584
+ break;
585
+ }
586
+ }
587
+ if (parent && !deps.has(node) && isChildSymbol(node, parent)) children.add(node);
588
+ }
589
+ });
590
+ return Array.from(deps);
591
+ function addDependency(node) {
592
+ if (isThisExpression(node) || isInferred(node)) return;
593
+ deps.add(node);
594
+ }
595
+ }
596
+ async function importNamespace(context, importer, node, imported, source, namespaceStmts, identifierMap, preserveCache) {
597
+ let preserve = preserveCache.get(source.value);
598
+ if (preserve === void 0) {
599
+ const resolved = await context.resolve(source.value, importer);
600
+ preserve = !resolved || !!resolved.external;
601
+ preserveCache.set(source.value, preserve);
602
+ }
603
+ if (preserve) return;
604
+ const sourceText = source.value.replaceAll(/\W/g, "_");
605
+ let local = {
606
+ type: "Identifier",
607
+ name: `_$${isIdentifierName(source.value) ? source.value : `${sourceText}${getIdentifierIndex(identifierMap, sourceText)}`}`
608
+ };
609
+ if (namespaceStmts.has(source.value)) local = namespaceStmts.get(source.value).local;
610
+ else namespaceStmts.set(source.value, {
611
+ stmt: {
612
+ type: "ImportDeclaration",
613
+ specifiers: [{
614
+ type: "ImportNamespaceSpecifier",
615
+ local
616
+ }],
617
+ source,
618
+ attributes: null
619
+ },
620
+ local
621
+ });
622
+ if (imported) {
623
+ const importedLeft = getIdFromTSEntityName(imported);
624
+ if (imported.type === "ThisExpression" || importedLeft.type === "ThisExpression") throw new Error("Cannot import `this` from module.");
625
+ overwriteNode(importedLeft, {
626
+ type: "TSQualifiedName",
627
+ left: local,
628
+ right: { ...importedLeft }
629
+ });
630
+ local = imported;
503
631
  }
632
+ let replacement = node;
633
+ if (node.typeArguments) {
634
+ overwriteNode(node, {
635
+ type: "TSTypeReference",
636
+ typeName: local,
637
+ typeArguments: node.typeArguments
638
+ });
639
+ replacement = local;
640
+ } else overwriteNode(node, local);
641
+ return {
642
+ ...TSEntityNameToRuntime(local),
643
+ replace(newNode) {
644
+ overwriteNode(replacement, newNode);
645
+ }
646
+ };
504
647
  }
505
648
  function isChildSymbol(node, parent) {
506
649
  if (node.type === "Identifier") return true;
@@ -518,6 +661,9 @@ const REFERENCE_RE = /\/\s*<reference\s+(?:path|types)=/;
518
661
  function collectReferenceDirectives(comment, negative = false) {
519
662
  return comment.filter((c) => REFERENCE_RE.test(c.value) !== negative);
520
663
  }
664
+ function isCjsDtsInputSyntax(node) {
665
+ return node.type === "TSExportAssignment" || node.type === "TSImportEqualsDeclaration" && node.moduleReference.type === "TSExternalModuleReference";
666
+ }
521
667
  /**
522
668
  * Check if the given node is a {@link RuntimeBindingVariableDeclration}
523
669
  */
@@ -572,7 +718,7 @@ function isHelperImport(node) {
572
718
  /**
573
719
  * patch `.d.ts` suffix in import source to `.js`
574
720
  */
575
- function patchImportExport(node, typeOnlyIds, cjsDefault) {
721
+ function patchImportExport(node, exportInfo, cjsDefault) {
576
722
  if (node.type === "ExportNamedDeclaration" && !node.declaration && !node.source && !node.specifiers.length && !node.attributes?.length) return false;
577
723
  if (node.type === "ImportDeclaration" && node.specifiers.length) {
578
724
  for (const specifier of node.specifiers) if (isInfer(specifier.local)) specifier.local.name = "__Infer";
@@ -582,10 +728,14 @@ function patchImportExport(node, typeOnlyIds, cjsDefault) {
582
728
  "ExportAllDeclaration",
583
729
  "ExportNamedDeclaration"
584
730
  ])) {
585
- if (node.type === "ExportNamedDeclaration" && typeOnlyIds.length) for (const spec of node.specifiers) {
586
- const name = resolveString(spec.exported);
587
- if (typeOnlyIds.includes(name)) if (spec.type === "ExportSpecifier") spec.exportKind = "type";
588
- else node.exportKind = "type";
731
+ if (node.type === "ExportAllDeclaration" && node.source && exportInfo.typeOnlyExportAllSources.has(node.source.value)) node.exportKind = "type";
732
+ if (node.type === "ExportNamedDeclaration" && exportInfo.typeOnlyNames.size) {
733
+ for (const spec of node.specifiers) {
734
+ const name = resolveString(spec.exported);
735
+ if (exportInfo.typeOnlyNames.has(name)) if (spec.type === "ExportSpecifier") spec.exportKind = "type";
736
+ else node.exportKind = "type";
737
+ }
738
+ normalizeTypeOnlyExport(node);
589
739
  }
590
740
  if (node.source?.value && RE_DTS.test(node.source.value)) {
591
741
  node.source.value = filename_dts_to(node.source.value, "js");
@@ -597,13 +747,19 @@ function patchImportExport(node, typeOnlyIds, cjsDefault) {
597
747
  };
598
748
  }
599
749
  }
750
+ function normalizeTypeOnlyExport(node) {
751
+ if (node.declaration || !node.specifiers.length) return;
752
+ for (const specifier of node.specifiers) if (specifier.type !== "ExportSpecifier" || specifier.exportKind !== "type") return;
753
+ node.exportKind = "type";
754
+ for (const specifier of node.specifiers) if (specifier.type === "ExportSpecifier") specifier.exportKind = "value";
755
+ }
600
756
  /**
601
757
  * Handle `__exportAll` call
602
758
  */
603
759
  function patchTsNamespace(nodes) {
604
760
  const removed = /* @__PURE__ */ new Set();
605
761
  for (const [i, node] of nodes.entries()) {
606
- const result = handleExport(node);
762
+ const result = getExportAllNamespace(node);
607
763
  if (!result) continue;
608
764
  const [binding, exports] = result;
609
765
  if (!exports.properties.length) continue;
@@ -630,10 +786,10 @@ function patchTsNamespace(nodes) {
630
786
  };
631
787
  }
632
788
  return nodes.filter((node) => !removed.has(node));
633
- function handleExport(node) {
634
- 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;
635
- return [node.declarations[0].id, node.declarations[0].init.arguments[0]];
636
- }
789
+ }
790
+ function getExportAllNamespace(node) {
791
+ 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;
792
+ return [node.declarations[0].id, node.declarations[0].init.arguments[0]];
637
793
  }
638
794
  /**
639
795
  * Handle `__reExport` call
@@ -668,13 +824,10 @@ function patchReExport(nodes) {
668
824
  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);
669
825
  return nodes;
670
826
  }
671
- function rewriteImportExport(node, set, typeOnlyIds) {
827
+ function rewriteImportExport(node, set) {
672
828
  if (node.type === "ImportDeclaration" || node.type === "ExportNamedDeclaration" && !node.declaration) {
673
- for (const specifier of node.specifiers) {
674
- if ("exportKind" in specifier && specifier.exportKind === "type" || "exportKind" in node && node.exportKind === "type") typeOnlyIds.push(resolveString(specifier.exported));
675
- if (specifier.type === "ImportSpecifier") specifier.importKind = "value";
676
- else if (specifier.type === "ExportSpecifier") specifier.exportKind = "value";
677
- }
829
+ for (const specifier of node.specifiers) if (specifier.type === "ImportSpecifier") specifier.importKind = "value";
830
+ else if (specifier.type === "ExportSpecifier") specifier.exportKind = "value";
678
831
  if (node.type === "ImportDeclaration") node.importKind = "value";
679
832
  else if (node.type === "ExportNamedDeclaration") node.exportKind = "value";
680
833
  return true;
@@ -732,6 +885,10 @@ function inheritNodeComments(oldNode, newNode) {
732
885
  newNode.leadingComments = collectReferenceDirectives(newNode.leadingComments, true);
733
886
  return newNode;
734
887
  }
888
+ function getIdentifierIndex(identifierMap, name) {
889
+ if (name in identifierMap) return ++identifierMap[name];
890
+ return identifierMap[name] = 0;
891
+ }
735
892
  //#endregion
736
893
  //#region src/tsgo.ts
737
894
  const debug$3 = createDebug("rolldown-plugin-dts:tsgo");
package/dist/tsc.d.mts CHANGED
@@ -1,2 +1,2 @@
1
1
  import { i as TscResult, n as TscModule, r as TscOptions, t as tscEmit } from "./index-CJhxyVA1.mjs";
2
- export { TscModule, TscOptions, TscResult, tscEmit };
2
+ export { type TscModule, type TscOptions, type TscResult, tscEmit };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rolldown-plugin-dts",
3
3
  "type": "module",
4
- "version": "0.25.0",
4
+ "version": "0.25.1",
5
5
  "description": "A Rolldown plugin to generate and bundle dts files.",
6
6
  "author": "Kevin Deng <sxzz@sxzz.moe>",
7
7
  "license": "MIT",
@@ -44,7 +44,7 @@
44
44
  "@ts-macro/tsc": "^0.3.6",
45
45
  "@typescript/native-preview": ">=7.0.0-dev.20260325.1",
46
46
  "rolldown": "^1.0.0",
47
- "typescript": "^6.0.0",
47
+ "typescript": "^5.0.0 || ^6.0.0",
48
48
  "vue-tsc": "~3.2.0"
49
49
  },
50
50
  "peerDependenciesMeta": {
@@ -62,8 +62,8 @@
62
62
  }
63
63
  },
64
64
  "dependencies": {
65
- "@babel/generator": "8.0.0-rc.4",
66
- "@babel/helper-validator-identifier": "8.0.0-rc.4",
65
+ "@babel/generator": "8.0.0-rc.5",
66
+ "@babel/helper-validator-identifier": "8.0.0-rc.5",
67
67
  "@babel/parser": "8.0.0-rc.4",
68
68
  "ast-kit": "^3.0.0-beta.1",
69
69
  "birpc": "^4.0.0",
@@ -74,27 +74,27 @@
74
74
  "devDependencies": {
75
75
  "@babel/types": "^8.0.0-rc.4",
76
76
  "@jridgewell/source-map": "^0.3.11",
77
- "@sxzz/eslint-config": "^8.0.0",
77
+ "@sxzz/eslint-config": "^8.1.0",
78
78
  "@sxzz/prettier-config": "^2.3.1",
79
79
  "@sxzz/test-utils": "^0.5.18",
80
- "@types/node": "^25.6.0",
81
- "@typescript/native-preview": "7.0.0-dev.20260507.1",
80
+ "@types/node": "^25.8.0",
81
+ "@typescript/native-preview": "7.0.0-dev.20260515.1",
82
82
  "@volar/typescript": "^2.4.28",
83
- "@vue/language-core": "^3.2.8",
83
+ "@vue/language-core": "^3.2.9",
84
84
  "arktype": "^2.2.0",
85
85
  "bumpp": "^11.1.0",
86
86
  "diff": "^9.0.0",
87
- "eslint": "^10.3.0",
87
+ "eslint": "^10.4.0",
88
88
  "prettier": "^3.8.3",
89
- "rolldown": "^1.0.0",
89
+ "rolldown": "^1.0.1",
90
90
  "rolldown-plugin-require-cjs": "^0.4.0",
91
91
  "rollup-plugin-dts": "^6.4.1",
92
- "tsdown": "^0.22.0-beta.3",
93
- "tsnapi": "^0.3.2",
92
+ "tsdown": "^0.22.0",
93
+ "tsnapi": "^0.3.3",
94
94
  "typescript": "^6.0.3",
95
- "vitest": "^4.1.5",
95
+ "vitest": "^4.1.6",
96
96
  "vue": "^3.5.34",
97
- "vue-tsc": "^3.2.8",
97
+ "vue-tsc": "^3.2.9",
98
98
  "zod": "^4.4.3"
99
99
  },
100
100
  "prettier": "@sxzz/prettier-config",