rolldown-plugin-dts 0.17.1 → 0.17.3

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
@@ -107,6 +107,15 @@ Content to be added at the top of each generated `.d.ts` file.
107
107
 
108
108
  Content to be added at the bottom of each generated `.d.ts` file.
109
109
 
110
+ #### `sideEffects`
111
+
112
+ Indicates whether the generated `.d.ts` files have side effects.
113
+
114
+ - If set to `true`, Rolldown will treat the `.d.ts` files as having side effects during tree-shaking.
115
+ - If set to `false`, Rolldown may consider the `.d.ts` files as side-effect-free, potentially removing them if they are not imported.
116
+
117
+ **Default:** false
118
+
110
119
  ### `tsc` Options
111
120
 
112
121
  > [!NOTE]
package/dist/index.d.ts CHANGED
@@ -64,6 +64,14 @@ interface GeneralOptions {
64
64
  * This is useful for compatibility with CommonJS.
65
65
  */
66
66
  cjsDefault?: boolean;
67
+ /**
68
+ * Indicates whether the generated `.d.ts` files have side effects.
69
+ * - If set to `true`, Rolldown will treat the `.d.ts` files as having side effects during tree-shaking.
70
+ * - If set to `false`, Rolldown may consider the `.d.ts` files as side-effect-free, potentially removing them if they are not imported.
71
+ *
72
+ * @default false
73
+ */
74
+ sideEffects?: boolean;
67
75
  }
68
76
  interface TscOptions {
69
77
  /**
@@ -190,6 +198,7 @@ declare function resolveOptions({
190
198
  cjsDefault,
191
199
  banner,
192
200
  footer,
201
+ sideEffects,
193
202
  build,
194
203
  incremental,
195
204
  vue,
@@ -205,8 +214,9 @@ declare function resolveOptions({
205
214
  //#region src/fake-js.d.ts
206
215
  declare function createFakeJsPlugin({
207
216
  sourcemap,
208
- cjsDefault
209
- }: Pick<OptionsResolved, "sourcemap" | "cjsDefault">): Plugin;
217
+ cjsDefault,
218
+ sideEffects
219
+ }: Pick<OptionsResolved, "sourcemap" | "cjsDefault" | "sideEffects">): Plugin;
210
220
  //#endregion
211
221
  //#region src/generate.d.ts
212
222
  declare function createGeneratePlugin({
package/dist/index.js CHANGED
@@ -63,10 +63,10 @@ function createBannerPlugin({ banner, footer }) {
63
63
 
64
64
  //#endregion
65
65
  //#region src/dts-input.ts
66
- function createDtsInputPlugin() {
66
+ function createDtsInputPlugin({ sideEffects }) {
67
67
  return {
68
68
  name: "rolldown-plugin-dts:dts-input",
69
- options(options) {
69
+ options: sideEffects === false ? (options) => {
70
70
  return {
71
71
  treeshake: options.treeshake === false ? false : {
72
72
  ...options.treeshake === true ? {} : options.treeshake,
@@ -74,7 +74,7 @@ function createDtsInputPlugin() {
74
74
  },
75
75
  ...options
76
76
  };
77
- },
77
+ } : void 0,
78
78
  outputOptions(options) {
79
79
  return {
80
80
  ...options,
@@ -284,7 +284,7 @@ function walk(ast, { enter, leave }) {
284
284
 
285
285
  //#endregion
286
286
  //#region src/fake-js.ts
287
- function createFakeJsPlugin({ sourcemap, cjsDefault }) {
287
+ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
288
288
  let symbolIdx = 0;
289
289
  const identifierMap = Object.create(null);
290
290
  const symbolMap = /* @__PURE__ */ new Map();
@@ -325,7 +325,8 @@ function createFakeJsPlugin({ sourcemap, cjsDefault }) {
325
325
  function transform(code, id) {
326
326
  const file = parse(code, {
327
327
  plugins: [["typescript", { dts: true }]],
328
- sourceType: "module"
328
+ sourceType: "module",
329
+ errorRecovery: true
329
330
  });
330
331
  const { program, comments } = file;
331
332
  const typeOnlyIds = [];
@@ -404,6 +405,7 @@ function createFakeJsPlugin({ sourcemap, cjsDefault }) {
404
405
  setStmt(runtimeAssignment);
405
406
  } else setDecl(runtimeAssignment);
406
407
  }
408
+ if (sideEffects) appendStmts.push(t.expressionStatement(t.callExpression(t.identifier("sideEffect"), [])));
407
409
  program.body = [
408
410
  ...Array.from(namespaceStmts.values()).map(({ stmt }) => stmt),
409
411
  ...program.body,
@@ -628,7 +630,7 @@ function isReferenceId(node) {
628
630
  return !!node && (node.type === "Identifier" || node.type === "MemberExpression");
629
631
  }
630
632
  function isHelperImport(node) {
631
- return node.type === "ImportDeclaration" && node.specifiers.length === 1 && node.specifiers.every((spec) => spec.type === "ImportSpecifier" && spec.imported.type === "Identifier" && ["__export", "__reExport"].includes(spec.imported.name));
633
+ return node.type === "ImportDeclaration" && node.specifiers.length === 1 && node.specifiers.every((spec) => spec.type === "ImportSpecifier" && spec.imported.type === "Identifier" && ["__export", "__reExport"].includes(spec.local.name));
632
634
  }
633
635
  /**
634
636
  * patch `.d.ts` suffix in import source to `.js`
@@ -943,10 +945,27 @@ function createGeneratePlugin({ tsconfig, tsconfigRaw, build, incremental, cwd,
943
945
  if (result.error) return this.error(result.error);
944
946
  dtsCode = result.code;
945
947
  map = result.map;
948
+ if (dtsCode && RE_JSON.test(id)) if (dtsCode.includes("declare const _exports")) {
949
+ if (dtsCode.includes("declare const _exports: {")) {
950
+ const exports = collectJsonExports(dtsCode);
951
+ let i = 0;
952
+ dtsCode += exports.map((e) => {
953
+ const valid = `_${e.replaceAll(/[^\w$]/g, "_")}${i++}`;
954
+ const jsonKey = JSON.stringify(e);
955
+ return `declare let ${valid}: typeof _exports[${jsonKey}]\nexport { ${valid} as ${jsonKey} }`;
956
+ }).join("\n");
957
+ }
958
+ } else {
959
+ const exportMap = collectJsonExportMap(dtsCode);
960
+ dtsCode += `
961
+ declare namespace __json_default_export {
962
+ export { ${Array.from(exportMap.entries()).map(([exported, local]) => exported === local ? exported : `${local} as ${exported}`).join(", ")} }
963
+ }
964
+ export { __json_default_export as default }`;
965
+ }
946
966
  }
947
967
  return {
948
968
  code: dtsCode || "",
949
- moduleSideEffects: false,
950
969
  map
951
970
  };
952
971
  }
@@ -988,11 +1007,41 @@ async function runTsgo(root, tsconfig) {
988
1007
  ], { stdio: "inherit" });
989
1008
  return tsgoDist;
990
1009
  }
1010
+ function collectJsonExportMap(code) {
1011
+ const exportMap = /* @__PURE__ */ new Map();
1012
+ const { program } = parse(code, {
1013
+ sourceType: "module",
1014
+ plugins: [["typescript", { dts: true }]],
1015
+ errorRecovery: true
1016
+ });
1017
+ for (const decl of program.body) if (decl.type === "ExportNamedDeclaration") {
1018
+ if (decl.declaration) {
1019
+ if (decl.declaration.type === "VariableDeclaration") {
1020
+ for (const vdecl of decl.declaration.declarations) if (vdecl.id.type === "Identifier") exportMap.set(vdecl.id.name, vdecl.id.name);
1021
+ } else if (decl.declaration.type === "TSModuleDeclaration" && decl.declaration.id.type === "Identifier") exportMap.set(decl.declaration.id.name, decl.declaration.id.name);
1022
+ } else if (decl.specifiers.length) {
1023
+ 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);
1024
+ }
1025
+ }
1026
+ return exportMap;
1027
+ }
1028
+ /** `declare const _exports` mode */
1029
+ function collectJsonExports(code) {
1030
+ const exports = [];
1031
+ const { program } = parse(code, {
1032
+ sourceType: "module",
1033
+ plugins: [["typescript", { dts: true }]]
1034
+ });
1035
+ const members = program.body[0].declarations[0].id.typeAnnotation.typeAnnotation.members;
1036
+ for (const member of members) if (member.key.type === "Identifier") exports.push(member.key.name);
1037
+ else if (member.key.type === "StringLiteral") exports.push(member.key.value);
1038
+ return exports;
1039
+ }
991
1040
 
992
1041
  //#endregion
993
1042
  //#region src/options.ts
994
1043
  let warnedTsgo = false;
995
- function resolveOptions({ cwd = process.cwd(), dtsInput = false, emitDtsOnly = false, tsconfig, tsconfigRaw: overriddenTsconfigRaw = {}, compilerOptions = {}, sourcemap, resolve = false, cjsDefault = false, banner, footer, build = false, incremental = false, vue = false, tsMacro = false, parallel = false, eager = false, newContext = false, emitJs, oxc, tsgo = false }) {
1044
+ function resolveOptions({ cwd = process.cwd(), dtsInput = false, emitDtsOnly = false, tsconfig, tsconfigRaw: overriddenTsconfigRaw = {}, compilerOptions = {}, sourcemap, resolve = false, cjsDefault = false, banner, footer, sideEffects = false, build = false, incremental = false, vue = false, tsMacro = false, parallel = false, eager = false, newContext = false, emitJs, oxc, tsgo = false }) {
996
1045
  let resolvedTsconfig;
997
1046
  if (tsconfig === true || tsconfig == null) {
998
1047
  const { config, path: path$1 } = getTsconfig(cwd) || {};
@@ -1043,6 +1092,7 @@ function resolveOptions({ cwd = process.cwd(), dtsInput = false, emitDtsOnly = f
1043
1092
  cjsDefault,
1044
1093
  banner,
1045
1094
  footer,
1095
+ sideEffects,
1046
1096
  build,
1047
1097
  incremental,
1048
1098
  vue,
@@ -1061,12 +1111,13 @@ function resolveOptions({ cwd = process.cwd(), dtsInput = false, emitDtsOnly = f
1061
1111
  function isSourceFile(id) {
1062
1112
  return RE_TS.test(id) || RE_VUE.test(id) || RE_JSON.test(id);
1063
1113
  }
1064
- function createDtsResolvePlugin({ tsconfig, resolve }) {
1114
+ function createDtsResolvePlugin({ tsconfig, resolve, sideEffects }) {
1065
1115
  const baseDtsResolver = createResolver({
1066
1116
  tsconfig,
1067
1117
  resolveNodeModules: !!resolve,
1068
1118
  ResolverFactory
1069
1119
  });
1120
+ const moduleSideEffects = sideEffects ? true : null;
1070
1121
  return {
1071
1122
  name: "rolldown-plugin-dts:resolver",
1072
1123
  resolveId: {
@@ -1076,17 +1127,23 @@ function createDtsResolvePlugin({ tsconfig, resolve }) {
1076
1127
  const external = {
1077
1128
  id,
1078
1129
  external: true,
1079
- moduleSideEffects: false
1130
+ moduleSideEffects: sideEffects
1080
1131
  };
1081
1132
  if (RE_CSS.test(id)) return external;
1082
1133
  const rolldownResolution = await this.resolve(id, importer, options);
1083
1134
  const dtsResolution = resolveDtsPath(id, importer, rolldownResolution);
1084
1135
  if (!dtsResolution) return isFilePath(id) ? null : external;
1085
1136
  if (RE_NODE_MODULES.test(dtsResolution) && !shouldBundleNodeModule(id) && (!RE_NODE_MODULES.test(importer) || rolldownResolution?.external)) return external;
1086
- if (RE_DTS.test(dtsResolution)) return dtsResolution;
1137
+ if (RE_DTS.test(dtsResolution)) return {
1138
+ id: dtsResolution,
1139
+ moduleSideEffects
1140
+ };
1087
1141
  if (isSourceFile(dtsResolution)) {
1088
1142
  await this.load({ id: dtsResolution });
1089
- return filename_to_dts(dtsResolution);
1143
+ return {
1144
+ id: filename_to_dts(dtsResolution),
1145
+ moduleSideEffects
1146
+ };
1090
1147
  }
1091
1148
  }
1092
1149
  }
@@ -1117,7 +1174,7 @@ function dts(options = {}) {
1117
1174
  const resolved = resolveOptions(options);
1118
1175
  debug("resolved dts options %o", resolved);
1119
1176
  const plugins = [];
1120
- if (options.dtsInput) plugins.push(createDtsInputPlugin());
1177
+ if (options.dtsInput) plugins.push(createDtsInputPlugin(resolved));
1121
1178
  else plugins.push(createGeneratePlugin(resolved));
1122
1179
  plugins.push(createDtsResolvePlugin(resolved), createFakeJsPlugin(resolved));
1123
1180
  if (options.banner || options.footer) plugins.push(createBannerPlugin(resolved));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rolldown-plugin-dts",
3
- "version": "0.17.1",
3
+ "version": "0.17.3",
4
4
  "description": "A Rolldown plugin to generate and bundle dts files.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -78,24 +78,24 @@
78
78
  "@types/babel__generator": "^7.27.0",
79
79
  "@types/debug": "^4.1.12",
80
80
  "@types/node": "^24.9.1",
81
- "@typescript/native-preview": "7.0.0-dev.20251024.1",
81
+ "@typescript/native-preview": "7.0.0-dev.20251027.1",
82
82
  "@volar/typescript": "^2.4.23",
83
- "@vue/language-core": "^3.1.1",
83
+ "@vue/language-core": "^3.1.2",
84
84
  "arktype": "^2.1.23",
85
85
  "bumpp": "^10.3.1",
86
86
  "diff": "^8.0.2",
87
87
  "eslint": "^9.38.0",
88
88
  "estree-walker": "^3.0.3",
89
89
  "prettier": "^3.6.2",
90
- "rolldown": "^1.0.0-beta.44",
90
+ "rolldown": "^1.0.0-beta.45",
91
91
  "rolldown-plugin-require-cjs": "^0.3.1",
92
92
  "rollup-plugin-dts": "^6.2.3",
93
93
  "tinyglobby": "^0.2.15",
94
- "tsdown": "^0.15.9",
94
+ "tsdown": "^0.15.11",
95
95
  "typescript": "^5.9.3",
96
- "vitest": "^4.0.3",
96
+ "vitest": "^4.0.4",
97
97
  "vue": "^3.5.22",
98
- "vue-tsc": "^3.1.1"
98
+ "vue-tsc": "^3.1.2"
99
99
  },
100
100
  "engines": {
101
101
  "node": ">=20.18.0"