dtsroll 1.7.9 → 1.8.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
@@ -157,11 +157,11 @@ This is especially useful for:
157
157
 
158
158
  ### Vite plugin
159
159
 
160
- If you use `vite-plugin-dts`, _dtsroll_ will automatically bundle the emitted types immediately after generation:
160
+ If you use [`unplugin-dts`](https://github.com/qmhc/unplugin-dts), _dtsroll_ will automatically bundle the emitted types immediately after generation:
161
161
 
162
162
  ```ts
163
163
  import { defineConfig } from 'vitest/config'
164
- import dts from 'vite-plugin-dts'
164
+ import dts from 'unplugin-dts/vite'
165
165
  import { dtsroll } from 'dtsroll/vite'
166
166
 
167
167
  export default defineConfig({
@@ -177,11 +177,20 @@ export default defineConfig({
177
177
  ```ts
178
178
  import { dtsroll } from 'dtsroll'
179
179
 
180
- await dtsroll({
180
+ const result = await dtsroll({
181
181
  cwd: process.cwd(),
182
182
  dryRun: false,
183
183
  sourcemap: true // generates .d.ts.map files
184
184
  })
185
+
186
+ if ('error' in result) {
187
+ console.error(result.error)
188
+ } else {
189
+ // Warnings about non-portable shared chunk types (TS2742)
190
+ for (const warning of result.warnings) {
191
+ console.warn(warning)
192
+ }
193
+ }
185
194
  ```
186
195
 
187
196
  ## Related
package/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { cli } from 'cleye';
3
- import { b as bgYellow, a as black, d as dtsroll, l as logOutput } from './index-CwhQAGPV.mjs';
3
+ import { b as bgYellow, a as black, d as dtsroll, l as logOutput } from './index-DPxVFBNC.mjs';
4
4
  import { patchErrorWithTrace } from 'rollup-plugin-import-trace';
5
5
  import 'node:path';
6
6
  import 'node:fs/promises';
@@ -14,7 +14,7 @@ import 'resolve-pkg-maps';
14
14
  import 'byte-size';
15
15
 
16
16
  var name = "dtsroll";
17
- var version = "1.7.9";
17
+ var version = "1.8.1";
18
18
  var description = "Bundle dts files";
19
19
 
20
20
  const argv = cli({
@@ -75,10 +75,10 @@ const bgYellow = kolorist(43, 49);
75
75
  const cwd = process.cwd();
76
76
 
77
77
  const isPath = (filePath) => filePath[0] === "." || path__default.isAbsolute(filePath);
78
- const normalizePath$1 = (filepath) => filepath.replaceAll("\\", "/");
78
+ const normalizePath$2 = (filepath) => filepath.replaceAll("\\", "/");
79
79
  const getDisplayPath = (fullPath) => {
80
80
  const relativePath = path__default.relative(cwd, fullPath);
81
- return normalizePath$1(
81
+ return normalizePath$2(
82
82
  relativePath.length < fullPath.length ? relativePath : fullPath
83
83
  );
84
84
  };
@@ -276,9 +276,9 @@ const getAllFiles = async (directoryPath, dontShortenPath) => {
276
276
  const filePath = path__default.join(directoryPath, entry.name);
277
277
  if (entry.isDirectory()) {
278
278
  const files = await getAllFiles(filePath, true);
279
- return dontShortenPath ? files : files.map((file) => `./${normalizePath$1(path__default.relative(directoryPath, file))}`);
279
+ return dontShortenPath ? files : files.map((file) => `./${normalizePath$2(path__default.relative(directoryPath, file))}`);
280
280
  }
281
- return dontShortenPath ? filePath : `./${normalizePath$1(path__default.relative(directoryPath, filePath))}`;
281
+ return dontShortenPath ? filePath : `./${normalizePath$2(path__default.relative(directoryPath, filePath))}`;
282
282
  })
283
283
  );
284
284
  return fileTree.flat();
@@ -652,14 +652,14 @@ function stripPathFilename(path) {
652
652
  return path.slice(0, index + 1);
653
653
  }
654
654
  function mergePaths(url, base) {
655
- normalizePath(base, base.type);
655
+ normalizePath$1(base, base.type);
656
656
  if (url.path === "/") {
657
657
  url.path = base.path;
658
658
  } else {
659
659
  url.path = stripPathFilename(base.path) + url.path;
660
660
  }
661
661
  }
662
- function normalizePath(url, type) {
662
+ function normalizePath$1(url, type) {
663
663
  const rel = type <= 4;
664
664
  const pieces = url.path.split("/");
665
665
  let pointer = 1;
@@ -726,7 +726,7 @@ function resolve(input, base) {
726
726
  if (baseType > inputType)
727
727
  inputType = baseType;
728
728
  }
729
- normalizePath(url, inputType);
729
+ normalizePath$1(url, inputType);
730
730
  const queryHash = url.query + url.hash;
731
731
  switch (inputType) {
732
732
  // This is impossible, because of the empty checks at the start of the function.
@@ -2750,7 +2750,6 @@ class LanguageService {
2750
2750
  }
2751
2751
  class TypeOnlyFixer {
2752
2752
  constructor(fileName, rawCode) {
2753
- this.DEBUG = !!process.env.DTS_EXPORTS_FIXER_DEBUG;
2754
2753
  this.types = /* @__PURE__ */ new Set();
2755
2754
  this.values = /* @__PURE__ */ new Set();
2756
2755
  this.typeHints = /* @__PURE__ */ new Map();
@@ -2872,7 +2871,6 @@ ${getNodeIndent(node)}`));
2872
2871
  }
2873
2872
  analyze(nodes) {
2874
2873
  for (const node of nodes) {
2875
- this.DEBUG && console.log(node.getText(), node.kind);
2876
2874
  if (ts.isImportDeclaration(node) && node.importClause) {
2877
2875
  this.importNodes.push(node);
2878
2876
  continue;
@@ -2882,13 +2880,11 @@ ${getNodeIndent(node)}`));
2882
2880
  continue;
2883
2881
  }
2884
2882
  if (ts.isInterfaceDeclaration(node)) {
2885
- this.DEBUG && console.log(`${node.name.getFullText()} is a type`);
2886
2883
  this.types.add(node.name.text);
2887
2884
  continue;
2888
2885
  }
2889
2886
  if (ts.isTypeAliasDeclaration(node)) {
2890
2887
  const alias = node.name.text;
2891
- this.DEBUG && console.log(`${node.name.getFullText()} is a type`);
2892
2888
  this.types.add(alias);
2893
2889
  continue;
2894
2890
  }
@@ -2896,13 +2892,11 @@ ${getNodeIndent(node)}`));
2896
2892
  if (ts.isVariableStatement(node)) {
2897
2893
  for (const declaration of node.declarationList.declarations) {
2898
2894
  if (ts.isIdentifier(declaration.name)) {
2899
- this.DEBUG && console.log(`${declaration.name.getFullText()} is a value (from var statement)`);
2900
2895
  this.values.add(declaration.name.text);
2901
2896
  }
2902
2897
  }
2903
2898
  } else {
2904
2899
  if (node.name) {
2905
- this.DEBUG && console.log(`${node.name.getFullText()} is a value (from declaration)`);
2906
2900
  this.values.add(node.name.text);
2907
2901
  }
2908
2902
  }
@@ -2914,13 +2908,11 @@ ${getNodeIndent(node)}`));
2914
2908
  }
2915
2909
  if (ts.isModuleDeclaration(node)) {
2916
2910
  if (node.name && ts.isIdentifier(node.name)) {
2917
- this.DEBUG && console.log(`${node.name.getFullText()} is a value (from module declaration)`);
2918
2911
  this.values.add(node.name.text);
2919
2912
  }
2920
2913
  this.analyze(node.getChildren());
2921
2914
  continue;
2922
2915
  }
2923
- this.DEBUG && console.log("unhandled statement", node.getFullText(), node.kind);
2924
2916
  }
2925
2917
  }
2926
2918
  // The type-hint statements may lead to redundant import statements.
@@ -2944,6 +2936,85 @@ function getNodeIndent(node) {
2944
2936
  const match = node.getFullText().match(/^(?:\n*)([ ]*)/);
2945
2937
  return " ".repeat(match?.[1]?.length || 0);
2946
2938
  }
2939
+ const RESOLVED_MODULE_PREFIX = "dts-resolved:";
2940
+ const RESOLVED_MODULE_COMMENT = new RegExp(`\\/\\*${RESOLVED_MODULE_PREFIX}(.+?)\\*\\/`);
2941
+ function encodeResolvedModule(absolutePath) {
2942
+ return `/*${RESOLVED_MODULE_PREFIX}${absolutePath}*/`;
2943
+ }
2944
+ function decodeResolvedModule(text) {
2945
+ return text.match(RESOLVED_MODULE_COMMENT)?.[1] ?? null;
2946
+ }
2947
+ function stripResolvedModuleComment(text) {
2948
+ return text.replace(RESOLVED_MODULE_COMMENT, "");
2949
+ }
2950
+ function normalizePath(p) {
2951
+ return p.split("\\").join("/");
2952
+ }
2953
+ class ModuleDeclarationFixer {
2954
+ constructor(chunk, code, sourcemap, moduleToChunk, warn) {
2955
+ this.code = code;
2956
+ this.sourcemap = sourcemap;
2957
+ this.source = parse(chunk.fileName, code.toString());
2958
+ this.chunkFileName = chunk.fileName;
2959
+ this.moduleToChunk = moduleToChunk;
2960
+ this.warn = warn;
2961
+ }
2962
+ fix() {
2963
+ let modified = false;
2964
+ for (const node of this.source.statements) {
2965
+ if (!ts.isModuleDeclaration(node) || !node.body || !ts.isModuleBlock(node.body)) {
2966
+ continue;
2967
+ }
2968
+ const sourceText = this.source.getFullText();
2969
+ const textBetween = sourceText.slice(node.name.getEnd(), node.body.getStart());
2970
+ const absolutePath = decodeResolvedModule(textBetween);
2971
+ if (!absolutePath) {
2972
+ continue;
2973
+ }
2974
+ const targetChunkName = this.getTargetChunkName(absolutePath);
2975
+ const quote = node.name.kind === ts.SyntaxKind.StringLiteral && "singleQuote" in node.name && node.name.singleQuote ? "'" : '"';
2976
+ const cleanedBetween = stripResolvedModuleComment(textBetween);
2977
+ this.code.overwrite(node.name.getStart(), node.body.getStart(), `${quote}${targetChunkName}${quote}${cleanedBetween}`);
2978
+ modified = true;
2979
+ }
2980
+ return {
2981
+ code: this.code.toString(),
2982
+ map: modified && this.sourcemap ? this.code.generateMap() : null
2983
+ };
2984
+ }
2985
+ /**
2986
+ * Get the output chunk name for an absolute module path.
2987
+ */
2988
+ getTargetChunkName(absolutePath) {
2989
+ const jsExtMatch = absolutePath.match(/\.[cm]?js$/);
2990
+ const basePath = jsExtMatch ? absolutePath.slice(0, -jsExtMatch[0].length) : absolutePath;
2991
+ const extensions = ["", ".d.ts", ".d.mts", ".d.cts", ".ts", ".mts", ".cts", ".js", ".mjs", ".cjs"];
2992
+ const possiblePaths = extensions.map((ext) => basePath + ext);
2993
+ for (const possiblePath of possiblePaths) {
2994
+ const chunkFileName = this.moduleToChunk.get(normalizePath(possiblePath));
2995
+ if (chunkFileName) {
2996
+ return this.formatChunkReference(chunkFileName, jsExtMatch?.[0]);
2997
+ }
2998
+ }
2999
+ this.warn(`declare module "${absolutePath}" could not be resolved to any output chunk, falling back to current chunk "${this.chunkFileName}"`);
3000
+ return this.formatChunkReference(this.chunkFileName, jsExtMatch?.[0]);
3001
+ }
3002
+ /**
3003
+ * Format a chunk filename as a relative path from the current chunk.
3004
+ */
3005
+ formatChunkReference(chunkFileName, jsExt) {
3006
+ const chunkDir = path.dirname(this.chunkFileName);
3007
+ let relativePath = normalizePath(path.relative(chunkDir, chunkFileName));
3008
+ relativePath = relativePath.replace(/\.d\.[cm]?tsx?$/, "");
3009
+ if (jsExt) {
3010
+ relativePath += jsExt;
3011
+ }
3012
+ if (!relativePath.startsWith(".")) {
3013
+ relativePath = "./" + relativePath;
3014
+ }
3015
+ return relativePath;
3016
+ }
3017
+ }
2947
3018
  function preProcessNamespaceBody(body, code, sourceFile) {
2948
3019
  if (ts.isModuleDeclaration(body)) {
2949
3020
  if (body.body && (ts.isModuleBlock(body.body) || ts.isModuleDeclaration(body.body))) {
@@ -3146,6 +3217,13 @@ declare const ${defaultExport}: {`,
3146
3217
  }
3147
3218
  code.remove(start, end);
3148
3219
  }
3220
+ const sourceDir = path.dirname(sourceFile.fileName);
3221
+ for (const node of sourceFile.statements) {
3222
+ if (ts.isModuleDeclaration(node) && node.body && ts.isModuleBlock(node.body) && ts.isStringLiteral(node.name) && /^\.\.?\//.test(node.name.text)) {
3223
+ const resolvedPath = path.resolve(sourceDir, node.name.text);
3224
+ code.appendRight(node.name.getEnd(), encodeResolvedModule(resolvedPath));
3225
+ }
3226
+ }
3149
3227
  const fullText = sourceFile.getFullText();
3150
3228
  const eofTrivia = ts.getLeadingCommentRanges(fullText, sourceFile.endOfFileToken.getFullStart());
3151
3229
  const lastStatement = sourceFile.statements[sourceFile.statements.length - 1];
@@ -3154,7 +3232,7 @@ declare const ${defaultExport}: {`,
3154
3232
  if (comment.kind !== ts.SyntaxKind.SingleLineCommentTrivia)
3155
3233
  continue;
3156
3234
  const text = fullText.slice(comment.pos, comment.end);
3157
- if (!/\/\/[#@]\s*sourceMappingURL=/.test(text))
3235
+ if (!/^\/\/[#@]\s*sourceMappingURL=/.test(text))
3158
3236
  continue;
3159
3237
  let start = comment.pos;
3160
3238
  if (start > 0 && fullText[start - 1] === "\n") {
@@ -3928,40 +4006,6 @@ class Transformer {
3928
4006
  };
3929
4007
  }
3930
4008
  }
3931
- class RelativeModuleDeclarationFixer {
3932
- constructor(fileName, code, sourcemap, name) {
3933
- this.sourcemap = sourcemap;
3934
- this.DEBUG = !!process.env.DTS_EXPORTS_FIXER_DEBUG;
3935
- this.relativeModuleDeclarations = [];
3936
- this.source = parse(fileName, code.toString());
3937
- this.code = code;
3938
- this.name = name || "./index";
3939
- }
3940
- fix() {
3941
- this.analyze(this.source.statements);
3942
- for (const node of this.relativeModuleDeclarations) {
3943
- const start = node.getStart();
3944
- const end = node.getEnd();
3945
- const quote = node.name.kind === ts.SyntaxKind.StringLiteral && "singleQuote" in node.name && node.name.singleQuote ? "'" : '"';
3946
- const code = `declare module ${quote}${this.name}${quote} ${node.body.getText()}`;
3947
- this.code.overwrite(start, end, code);
3948
- }
3949
- return {
3950
- code: this.code.toString(),
3951
- map: this.relativeModuleDeclarations.length && this.sourcemap ? this.code.generateMap() : null
3952
- };
3953
- }
3954
- analyze(nodes) {
3955
- for (const node of nodes) {
3956
- if (ts.isModuleDeclaration(node) && node.body && ts.isModuleBlock(node.body) && /^\.\.?\//.test(node.name.text)) {
3957
- if (this.DEBUG) {
3958
- console.log(`Found relative module declaration: ${node.name.text} in ${this.source.fileName}`);
3959
- }
3960
- this.relativeModuleDeclarations.push(node);
3961
- }
3962
- }
3963
- }
3964
- }
3965
4009
  function hydrateSourcemap(sparseMappings, inputMap, outputCode) {
3966
4010
  const sparseDecoded = decode(sparseMappings);
3967
4011
  const inputDecoded = decode(inputMap.mappings);
@@ -4042,6 +4086,281 @@ async function loadInputSourcemap(info) {
4042
4086
  return null;
4043
4087
  }
4044
4088
  }
4089
+ function rewritePortableSharedChunkImportsInBundle(bundle, warn) {
4090
+ const chunks = Object.values(bundle).filter(isOutputChunk);
4091
+ const sharedChunks = chunks.filter((chunk) => !chunk.isEntry);
4092
+ if (sharedChunks.length === 0)
4093
+ return;
4094
+ const entryChunks = chunks.filter((chunk) => chunk.isEntry);
4095
+ const chunkGraph = new Map(chunks.map((chunk) => [
4096
+ chunk.fileName,
4097
+ {
4098
+ exports: chunk.exports,
4099
+ isEntry: chunk.isEntry
4100
+ }
4101
+ ]));
4102
+ const analyses = new Map(chunks.map((chunk) => [chunk.fileName, analyzeChunk(chunk, chunkGraph)]));
4103
+ for (const chunk of entryChunks) {
4104
+ const analysis = analyses.get(chunk.fileName);
4105
+ const magicCode = new MagicString(chunk.code);
4106
+ let hasChanges = false;
4107
+ const unresolvedSymbols = /* @__PURE__ */ new Set();
4108
+ for (const statement of analysis.importStatements) {
4109
+ const sharedChunk = sharedChunks.find((candidate) => getChunkImportSpecifier(chunk.fileName, candidate.fileName) === statement.moduleSpecifier);
4110
+ if (!sharedChunk) {
4111
+ continue;
4112
+ }
4113
+ const keptSpecifiers = [];
4114
+ const rewrittenSpecifiers = /* @__PURE__ */ new Map();
4115
+ for (const specifier of statement.specifiers) {
4116
+ if (hasPublicHostRoute(analysis, statement.moduleSpecifier, specifier.importedName)) {
4117
+ keptSpecifiers.push(specifier);
4118
+ continue;
4119
+ }
4120
+ const hostCandidate = pickHostCandidate(entryChunks, analyses, chunk.fileName, sharedChunk.fileName, specifier);
4121
+ if (!hostCandidate) {
4122
+ keptSpecifiers.push(specifier);
4123
+ unresolvedSymbols.add(specifier.localName);
4124
+ continue;
4125
+ }
4126
+ const hostSpecifier = getChunkImportSpecifier(chunk.fileName, hostCandidate.chunk.fileName);
4127
+ const hostImportSpecifiers = rewrittenSpecifiers.get(hostSpecifier) || [];
4128
+ hostImportSpecifiers.push({
4129
+ importedName: hostCandidate.exportedName,
4130
+ isTypeOnly: specifier.isTypeOnly || hostCandidate.isTypeOnly,
4131
+ localName: specifier.localName
4132
+ });
4133
+ rewrittenSpecifiers.set(hostSpecifier, hostImportSpecifiers);
4134
+ }
4135
+ if (!rewrittenSpecifiers.size) {
4136
+ continue;
4137
+ }
4138
+ const replacementStatements = [];
4139
+ if (keptSpecifiers.length) {
4140
+ replacementStatements.push(buildImportStatement(statement, keptSpecifiers, statement.moduleSpecifier, statement.quote));
4141
+ }
4142
+ const hostSpecifiers = Array.from(rewrittenSpecifiers.keys()).sort(compareStrings);
4143
+ for (const hostSpecifier of hostSpecifiers) {
4144
+ replacementStatements.push(buildImportStatement(statement, rewrittenSpecifiers.get(hostSpecifier), hostSpecifier, statement.quote));
4145
+ }
4146
+ magicCode.overwrite(statement.statement.getStart(), statement.statement.getEnd(), replacementStatements.join("\n"));
4147
+ hasChanges = true;
4148
+ }
4149
+ if (hasChanges) {
4150
+ applyChunkEdits(chunk, magicCode);
4151
+ }
4152
+ if (unresolvedSymbols.size) {
4153
+ warn(formatUnresolvedSharedTypeWarning(chunk.fileName, unresolvedSymbols));
4154
+ }
4155
+ }
4156
+ }
4157
+ function analyzeChunk(chunk, chunkGraph) {
4158
+ const source = parse(chunk.fileName, chunk.code);
4159
+ const importStatements = [];
4160
+ const importedBindings = /* @__PURE__ */ new Map();
4161
+ const hostRoutesByModule = /* @__PURE__ */ new Map();
4162
+ const starExports = [];
4163
+ for (const statement of source.statements) {
4164
+ if (ts.isImportDeclaration(statement) && !statement.importClause?.name && ts.isStringLiteral(statement.moduleSpecifier) && statement.importClause?.namedBindings && ts.isNamedImports(statement.importClause.namedBindings)) {
4165
+ const moduleSpecifier = statement.moduleSpecifier.text;
4166
+ const quote = statement.moduleSpecifier.getText(source).startsWith('"') ? '"' : "'";
4167
+ const specifiers = statement.importClause.namedBindings.elements.map((element) => {
4168
+ const specifier = {
4169
+ importedName: element.propertyName?.text || element.name.text,
4170
+ isTypeOnly: element.isTypeOnly || statement.importClause?.isTypeOnly || false,
4171
+ localName: element.name.text
4172
+ };
4173
+ importedBindings.set(specifier.localName, {
4174
+ importedName: specifier.importedName,
4175
+ isTypeOnly: specifier.isTypeOnly,
4176
+ moduleSpecifier
4177
+ });
4178
+ return specifier;
4179
+ });
4180
+ importStatements.push({
4181
+ isTypeOnly: statement.importClause.isTypeOnly,
4182
+ moduleSpecifier,
4183
+ quote,
4184
+ specifiers,
4185
+ statement
4186
+ });
4187
+ continue;
4188
+ }
4189
+ if (!ts.isExportDeclaration(statement) || !statement.moduleSpecifier || !ts.isStringLiteral(statement.moduleSpecifier)) {
4190
+ continue;
4191
+ }
4192
+ if (!statement.exportClause) {
4193
+ starExports.push(statement.moduleSpecifier.text);
4194
+ continue;
4195
+ }
4196
+ if (!ts.isNamedExports(statement.exportClause)) {
4197
+ continue;
4198
+ }
4199
+ for (const element of statement.exportClause.elements) {
4200
+ addHostExportRoute(hostRoutesByModule, statement.moduleSpecifier.text, element.propertyName?.text || element.name.text, {
4201
+ exportedName: element.name.text,
4202
+ isTypeOnly: statement.isTypeOnly || element.isTypeOnly
4203
+ });
4204
+ }
4205
+ }
4206
+ for (const statement of source.statements) {
4207
+ if (!ts.isExportDeclaration(statement) || statement.moduleSpecifier || !statement.exportClause || !ts.isNamedExports(statement.exportClause)) {
4208
+ continue;
4209
+ }
4210
+ for (const element of statement.exportClause.elements) {
4211
+ const localName = element.propertyName?.text || element.name.text;
4212
+ const binding = importedBindings.get(localName);
4213
+ if (!binding) {
4214
+ continue;
4215
+ }
4216
+ addHostExportRoute(hostRoutesByModule, binding.moduleSpecifier, binding.importedName, {
4217
+ exportedName: element.name.text,
4218
+ isTypeOnly: binding.isTypeOnly || statement.isTypeOnly || element.isTypeOnly
4219
+ });
4220
+ }
4221
+ }
4222
+ for (const moduleSpecifier of starExports) {
4223
+ const sharedChunk = Array.from(chunkGraph.entries()).find(([candidateFileName, candidate]) => !candidate.isEntry && getChunkImportSpecifier(chunk.fileName, candidateFileName) === moduleSpecifier);
4224
+ if (!sharedChunk) {
4225
+ continue;
4226
+ }
4227
+ for (const exportedName of sharedChunk[1].exports) {
4228
+ if (exportedName === "default") {
4229
+ continue;
4230
+ }
4231
+ addHostExportRoute(hostRoutesByModule, moduleSpecifier, exportedName, {
4232
+ exportedName,
4233
+ isTypeOnly: false
4234
+ });
4235
+ }
4236
+ }
4237
+ return {
4238
+ hostRoutesByModule,
4239
+ importStatements
4240
+ };
4241
+ }
4242
+ const isOutputChunk = (chunk) => chunk.type === "chunk";
4243
+ function pickHostCandidate(entryChunks, analyses, currentChunkFileName, sharedChunkFileName, specifier) {
4244
+ const candidates = [];
4245
+ for (const hostChunk of entryChunks) {
4246
+ if (hostChunk.fileName === currentChunkFileName) {
4247
+ continue;
4248
+ }
4249
+ const hostAnalysis = analyses.get(hostChunk.fileName);
4250
+ const sharedSpecifier = getChunkImportSpecifier(hostChunk.fileName, sharedChunkFileName);
4251
+ const routes = getHostExportRoutes(hostAnalysis, sharedSpecifier, specifier.importedName);
4252
+ for (const route of routes) {
4253
+ candidates.push({
4254
+ ...route,
4255
+ chunk: hostChunk
4256
+ });
4257
+ }
4258
+ }
4259
+ candidates.sort((left, right) => {
4260
+ const leftMatchesLocal = left.exportedName === specifier.localName ? 0 : 1;
4261
+ const rightMatchesLocal = right.exportedName === specifier.localName ? 0 : 1;
4262
+ if (leftMatchesLocal !== rightMatchesLocal) {
4263
+ return leftMatchesLocal - rightMatchesLocal;
4264
+ }
4265
+ const fileNameOrder = compareStrings(left.chunk.fileName, right.chunk.fileName);
4266
+ if (fileNameOrder !== 0) {
4267
+ return fileNameOrder;
4268
+ }
4269
+ return compareStrings(left.exportedName, right.exportedName);
4270
+ });
4271
+ return candidates[0];
4272
+ }
4273
+ const getHostExportRoutes = (analysis, moduleSpecifier, importedName) => analysis.hostRoutesByModule.get(moduleSpecifier)?.get(importedName) || [];
4274
+ const hasPublicHostRoute = (analysis, moduleSpecifier, importedName) => getHostExportRoutes(analysis, moduleSpecifier, importedName).length > 0;
4275
+ const compareStrings = (left, right) => {
4276
+ if (left < right) {
4277
+ return -1;
4278
+ }
4279
+ if (left > right) {
4280
+ return 1;
4281
+ }
4282
+ return 0;
4283
+ };
4284
+ function addHostExportRoute(hostRoutesByModule, moduleSpecifier, importedName, route) {
4285
+ const routesByImportedName = hostRoutesByModule.get(moduleSpecifier) || /* @__PURE__ */ new Map();
4286
+ const routes = routesByImportedName.get(importedName) || [];
4287
+ if (!routes.some((existing) => existing.exportedName === route.exportedName && existing.isTypeOnly === route.isTypeOnly)) {
4288
+ routes.push(route);
4289
+ }
4290
+ routesByImportedName.set(importedName, routes);
4291
+ hostRoutesByModule.set(moduleSpecifier, routesByImportedName);
4292
+ }
4293
+ function buildImportStatement(statement, specifiers, moduleSpecifier, quote) {
4294
+ const useTypeOnlyImport = statement.isTypeOnly || specifiers.every((specifier) => specifier.isTypeOnly);
4295
+ const importKeyword = useTypeOnlyImport ? "import type" : "import";
4296
+ const namedImports = specifiers.map((specifier) => {
4297
+ const prefix = !useTypeOnlyImport && specifier.isTypeOnly ? "type " : "";
4298
+ if (specifier.importedName === specifier.localName) {
4299
+ return `${prefix}${specifier.importedName}`;
4300
+ }
4301
+ return `${prefix}${specifier.importedName} as ${specifier.localName}`;
4302
+ }).join(", ");
4303
+ return `${importKeyword} { ${namedImports} } from ${quote}${moduleSpecifier}${quote};`;
4304
+ }
4305
+ function applyChunkEdits(chunk, code) {
4306
+ const nextCode = code.toString();
4307
+ if (nextCode === chunk.code) {
4308
+ return;
4309
+ }
4310
+ if (chunk.map) {
4311
+ const chunkFileName = normalizeChunkPath(chunk.fileName);
4312
+ const rewriteMap = code.generateMap({
4313
+ file: chunkFileName,
4314
+ hires: true,
4315
+ includeContent: true,
4316
+ source: chunkFileName
4317
+ });
4318
+ const remapped = remapping(rewriteMap, (file) => {
4319
+ if (normalizeChunkPath(file) === chunkFileName) {
4320
+ return chunk.map;
4321
+ }
4322
+ return null;
4323
+ });
4324
+ chunk.map = {
4325
+ ...chunk.map,
4326
+ mappings: typeof remapped.mappings === "string" ? remapped.mappings : "",
4327
+ names: remapped.names || [],
4328
+ sources: remapped.sources
4329
+ };
4330
+ delete chunk.map.sourcesContent;
4331
+ }
4332
+ chunk.code = nextCode;
4333
+ }
4334
+ const formatUnresolvedSharedTypeWarning = (chunkFileName, symbols) => {
4335
+ const symbolList = Array.from(symbols).sort().join(", ");
4336
+ return [
4337
+ `Entry "${chunkFileName}" still references private shared type exports with no public re-export: ${symbolList}.`,
4338
+ "rollup-plugin-dts will not invent new public exports for these types.",
4339
+ "Re-export them from a public entry to avoid downstream TS2742 errors."
4340
+ ].join(" ");
4341
+ };
4342
+ const getChunkImportSpecifier = (fromChunkFileName, toChunkFileName) => {
4343
+ const fromDir = path.posix.dirname(normalizeChunkPath(fromChunkFileName));
4344
+ const toRuntimeFileName = getChunkRuntimeFileName(normalizeChunkPath(toChunkFileName));
4345
+ let relativePath = path.posix.relative(fromDir, toRuntimeFileName);
4346
+ if (!relativePath.startsWith(".")) {
4347
+ relativePath = `./${relativePath}`;
4348
+ }
4349
+ return relativePath;
4350
+ };
4351
+ const getChunkRuntimeFileName = (fileName) => {
4352
+ if (fileName.endsWith(".d.mts")) {
4353
+ return `${fileName.slice(0, -6)}.mjs`;
4354
+ }
4355
+ if (fileName.endsWith(".d.cts")) {
4356
+ return `${fileName.slice(0, -6)}.cjs`;
4357
+ }
4358
+ if (fileName.endsWith(".d.ts")) {
4359
+ return `${fileName.slice(0, -5)}.js`;
4360
+ }
4361
+ return `${fileName}.js`;
4362
+ };
4363
+ const normalizeChunkPath = (fileName) => fileName.replaceAll("\\", "/");
4045
4364
  const transform = (enableSourcemap) => {
4046
4365
  const allTypeReferences = /* @__PURE__ */ new Map();
4047
4366
  const allFileReferences = /* @__PURE__ */ new Map();
@@ -4087,12 +4406,13 @@ const transform = (enableSourcemap) => {
4087
4406
  strict: false
4088
4407
  };
4089
4408
  },
4090
- transform(code, fileName, inputMapText) {
4409
+ transform(code, fileName, inputMapTextOrOptions) {
4091
4410
  const name = trimExtension(fileName);
4092
4411
  const moduleIds = this.getModuleIds();
4093
4412
  const moduleId = Array.from(moduleIds).find((id) => trimExtension(id) === name);
4094
4413
  const isEntry = Boolean(moduleId && this.getModuleInfo(moduleId)?.isEntry);
4095
4414
  const isJSON = Boolean(moduleId && JSON_EXTENSIONS.test(moduleId));
4415
+ const inputMapText = typeof inputMapTextOrOptions === "string" ? inputMapTextOrOptions : void 0;
4096
4416
  const rawCode = code;
4097
4417
  let sourceFile = parse(fileName, code);
4098
4418
  const preprocessed = preProcess({ sourceFile, isEntry, isJSON });
@@ -4107,7 +4427,7 @@ const transform = (enableSourcemap) => {
4107
4427
  console.log(JSON.stringify(converted.ast.body, void 0, 2));
4108
4428
  }
4109
4429
  if (!enableSourcemap) {
4110
- return { code, ast: converted.ast };
4430
+ return { code, ast: converted.ast, map: null };
4111
4431
  }
4112
4432
  const map = preprocessed.code.generateMap({ hires: true, source: fileName });
4113
4433
  if (DTS_EXTENSIONS.test(fileName)) {
@@ -4119,7 +4439,7 @@ const transform = (enableSourcemap) => {
4119
4439
  }
4120
4440
  return { code, ast: converted.ast, map };
4121
4441
  },
4122
- renderChunk(inputCode, chunk, options) {
4442
+ renderChunk(inputCode, chunk, options, meta) {
4123
4443
  const source = parse(chunk.fileName, inputCode);
4124
4444
  const fixer = new NamespaceFixer(source);
4125
4445
  const typeReferences = /* @__PURE__ */ new Set();
@@ -4150,10 +4470,17 @@ const transform = (enableSourcemap) => {
4150
4470
  }
4151
4471
  const typeOnlyFixer = new TypeOnlyFixer(chunk.fileName, code);
4152
4472
  const typesFixed = typeOnlyFixer.fix();
4153
- const relativeModuleDeclarationFixed = new RelativeModuleDeclarationFixer(chunk.fileName, "magicCode" in typesFixed && typesFixed.magicCode ? typesFixed.magicCode : new MagicString(code), !!options.sourcemap, "./" + path.basename(chunk.fileName, ".d.ts"));
4154
- return relativeModuleDeclarationFixed.fix();
4473
+ const moduleToChunk = /* @__PURE__ */ new Map();
4474
+ for (const [chunkFileName, chunkInfo] of Object.entries(meta.chunks)) {
4475
+ for (const moduleId of Object.keys(chunkInfo.modules)) {
4476
+ moduleToChunk.set(moduleId.split("\\").join("/"), chunkFileName);
4477
+ }
4478
+ }
4479
+ const moduleDeclarationFixer = new ModuleDeclarationFixer(chunk, "magicCode" in typesFixed && typesFixed.magicCode ? typesFixed.magicCode : new MagicString(code), !!options.sourcemap, moduleToChunk, (message) => this.warn(message));
4480
+ return moduleDeclarationFixer.fix();
4155
4481
  },
4156
4482
  async generateBundle(options, bundle) {
4483
+ rewritePortableSharedChunkImportsInBundle(bundle, (message) => this.warn(message));
4157
4484
  if (!options.sourcemap)
4158
4485
  return;
4159
4486
  const inputSourcemaps = /* @__PURE__ */ new Map();
@@ -4453,7 +4780,13 @@ const plugin = (options = {}) => {
4453
4780
  const resolvedSource = source.startsWith(".") ? path.resolve(path.dirname(importer), source) : source;
4454
4781
  resolvedCompilerOptions = getCompilerOptions(resolvedSource, ctx.resolvedOptions.compilerOptions, ctx.resolvedOptions.tsconfig, ctx.resolvedOptions.sourcemap).compilerOptions;
4455
4782
  }
4456
- const { resolvedModule } = ts.resolveModuleName(source, importer, resolvedCompilerOptions, ts.sys);
4783
+ const { resolvedModule } = ts.resolveModuleName(source, importer, {
4784
+ // Default moduleResolution to node10 if not explicitly set. TS6 changed
4785
+ // the default from node10 to bundler, and bundler resolution picks .js
4786
+ // files over directories with .d.ts index files, breaking .d.ts bundling.
4787
+ moduleResolution: ts.ModuleResolutionKind.Node10,
4788
+ ...resolvedCompilerOptions
4789
+ }, ts.sys);
4457
4790
  if (!resolvedModule) {
4458
4791
  return;
4459
4792
  }
@@ -4632,6 +4965,7 @@ const build = async (input, outputDirectory, externals, mode, conditions, source
4632
4965
  getPackageEntryPoint
4633
4966
  } = createExternalizePlugin(externals);
4634
4967
  const sizeRef = {};
4968
+ const warnings = [];
4635
4969
  const rollupConfig = {
4636
4970
  input: createInputMap(input, outputDirectory),
4637
4971
  output: {
@@ -4640,6 +4974,9 @@ const build = async (input, outputDirectory, externals, mode, conditions, source
4640
4974
  entryFileNames: "[name]",
4641
4975
  chunkFileNames: "_dtsroll-chunks/[hash]-[name].ts"
4642
4976
  },
4977
+ onwarn(warning) {
4978
+ warnings.push(String(warning.message || warning));
4979
+ },
4643
4980
  plugins: [
4644
4981
  importTrace(),
4645
4982
  externalizePlugin,
@@ -4652,13 +4989,6 @@ const build = async (input, outputDirectory, externals, mode, conditions, source
4652
4989
  plugin({
4653
4990
  respectExternal: true,
4654
4991
  sourcemap
4655
- /**
4656
- * Setting a tsconfig or compilerOptions shouldn't be necessary since
4657
- * we're dealing with pre-compiled d.ts files
4658
- *
4659
- * But may be something we need to support if we want to support
4660
- * aliases in the future
4661
- */
4662
4992
  })
4663
4993
  ]
4664
4994
  };
@@ -4669,7 +4999,8 @@ const build = async (input, outputDirectory, externals, mode, conditions, source
4669
4999
  built,
4670
5000
  externalized,
4671
5001
  getPackageEntryPoint,
4672
- sourceSize: sizeRef.value ?? 0
5002
+ sourceSize: sizeRef.value ?? 0,
5003
+ warnings
4673
5004
  };
4674
5005
  };
4675
5006
 
@@ -4708,7 +5039,8 @@ const dtsroll = async ({
4708
5039
  built,
4709
5040
  externalized,
4710
5041
  getPackageEntryPoint,
4711
- sourceSize
5042
+ sourceSize,
5043
+ warnings
4712
5044
  } = await build(
4713
5045
  inputFiles,
4714
5046
  outputDirectory,
@@ -4763,7 +5095,8 @@ const dtsroll = async ({
4763
5095
  input: sourceSize,
4764
5096
  output: outputSize
4765
5097
  },
4766
- externals: externalPackages
5098
+ externals: externalPackages,
5099
+ warnings
4767
5100
  };
4768
5101
  };
4769
5102
 
package/dist/index.d.ts CHANGED
@@ -46,6 +46,8 @@ type DtsrollOutput = {
46
46
  output: number;
47
47
  };
48
48
  externals: Externals;
49
+ /** Warnings emitted during the build (e.g. non-portable shared chunk types). */
50
+ warnings: string[];
49
51
  };
50
52
 
51
53
  /**
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import 'node:path';
3
- export { d as dtsroll } from './index-CwhQAGPV.mjs';
3
+ export { d as dtsroll } from './index-DPxVFBNC.mjs';
4
4
  import 'node:fs/promises';
5
5
  import 'rollup';
6
6
  import 'typescript';
package/dist/vite.d.ts CHANGED
@@ -4,7 +4,7 @@ import 'rollup';
4
4
 
5
5
  /**
6
6
  * Vite plugin for bundling TypeScript declaration files.
7
- * Runs after vite-plugin-dts in the writeBundle hook.
7
+ * Runs after unplugin-dts in the writeBundle hook.
8
8
  *
9
9
  * @param options - Configuration options (same as dtsroll function)
10
10
  * @returns Vite plugin instance
package/dist/vite.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { d as dtsroll, l as logOutput } from './index-CwhQAGPV.mjs';
2
+ import { d as dtsroll, l as logOutput } from './index-DPxVFBNC.mjs';
3
3
  import 'node:path';
4
4
  import 'node:fs/promises';
5
5
  import 'rollup';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dtsroll",
3
- "version": "1.7.9",
3
+ "version": "1.8.1",
4
4
  "description": "Bundle dts files",
5
5
  "keywords": [
6
6
  "bundle",
@@ -18,6 +18,7 @@
18
18
  "files": [
19
19
  "dist"
20
20
  ],
21
+ "type": "module",
21
22
  "bin": "./dist/cli.mjs",
22
23
  "exports": {
23
24
  ".": {
@@ -30,8 +31,12 @@
30
31
  }
31
32
  },
32
33
  "imports": {
33
- "#dtsroll": "./src/index.ts",
34
- "#dtsroll/vite": "./src/vite.ts"
34
+ "typescript": {
35
+ "typescript4": "typescript4",
36
+ "typescript5": "typescript5",
37
+ "typescript6": "typescript6",
38
+ "default": "typescript"
39
+ }
35
40
  },
36
41
  "engines": {
37
42
  "node": ">=18"
@@ -39,15 +44,15 @@
39
44
  "dependencies": {
40
45
  "@rollup/plugin-node-resolve": "^16.0.3",
41
46
  "byte-size": "^9.0.1",
42
- "cleye": "^2.2.1",
47
+ "cleye": "^2.3.0",
43
48
  "convert-source-map": "^2.0.0",
44
49
  "empathic": "^2.0.0",
45
50
  "resolve-pkg-maps": "^1.0.0",
46
- "rollup": "^4.55.3",
51
+ "rollup": "^4.60.1",
47
52
  "rollup-plugin-import-trace": "^1.0.1"
48
53
  },
49
54
  "peerDependencies": {
50
- "typescript": "^4.5 || ^5.0",
55
+ "typescript": "^4.5 || ^5.0 || ^6.0",
51
56
  "vite": "5 || 6 || 7"
52
57
  },
53
58
  "peerDependenciesMeta": {