dtsroll 1.6.0 → 1.7.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
@@ -134,9 +134,24 @@ If no entry files are provided, _dtsroll_ reads `package.json` to determine them
134
134
  | Flag | Alias | Description |
135
135
  | -------------- | ----- | ------------------------------------------------- |
136
136
  | `--dry-run` | `-d` | Show what would be bundled without writing files |
137
+ | `--sourcemap` | `-s` | Generate source maps (`.d.ts.map` files) |
137
138
  | `--conditions` | `-C` | Resolution conditions for [subpath exports](https://nodejs.org/api/packages.html#subpath-exports) (e.g. `production`) |
138
139
  | `--external` | `-e` | *(Only when no `package.json`)* Packages to externalize |
139
140
 
141
+ #### Why use `--sourcemap`?
142
+
143
+ Without source maps, "Go to Definition" in VS Code lands you in bundled `.d.ts` files—often a flattened wall of generated types that's hard to navigate.
144
+
145
+ With `--sourcemap`, _dtsroll_ generates `.d.ts.map` files that map positions in the bundled output back to your original source files. This lets VS Code jump directly to the actual TypeScript implementation instead of the generated declarations.
146
+
147
+ This is especially useful for:
148
+ - **Monorepos** — Navigate seamlessly across packages to real source
149
+ - **Library authors** — Give consumers a better DX when exploring your types
150
+ - **Anyone debugging types** — Understand types at their origin, not the emitted output
151
+
152
+ > [!NOTE]
153
+ > For source navigation to work, the original `.ts` source files must be available (either shipped with your package or present locally). If they're not, VS Code falls back to the `.d.ts` file.
154
+
140
155
  ### Vite plugin
141
156
 
142
157
  If you use `vite-plugin-dts`, _dtsroll_ will automatically bundle the emitted types immediately after generation:
@@ -161,7 +176,8 @@ import { dtsroll } from 'dtsroll'
161
176
 
162
177
  await dtsroll({
163
178
  cwd: process.cwd(),
164
- dryRun: false
179
+ dryRun: false,
180
+ sourcemap: true // generates .d.ts.map files
165
181
  })
166
182
  ```
167
183
 
package/dist/cli.mjs CHANGED
@@ -1,17 +1,19 @@
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, D as DtsrollBuildError } from './index-Du7Kzot4.mjs';
3
+ import { b as bgYellow, a as black, d as dtsroll, l as logOutput, D as DtsrollBuildError } from './index-D25w_e6R.mjs';
4
4
  import 'node:path';
5
5
  import 'node:fs/promises';
6
6
  import 'rollup';
7
7
  import 'rollup-plugin-dts';
8
8
  import '@rollup/plugin-node-resolve';
9
+ import 'node:fs';
10
+ import 'convert-source-map';
9
11
  import 'empathic/find';
10
12
  import 'resolve-pkg-maps';
11
13
  import 'byte-size';
12
14
 
13
15
  var name = "dtsroll";
14
- var version = "1.6.0";
16
+ var version = "1.7.1";
15
17
  var description = "Bundle dts files";
16
18
 
17
19
  const argv = cli({
@@ -3,6 +3,8 @@ import fs from 'node:fs/promises';
3
3
  import { rollup } from 'rollup';
4
4
  import { dts } from 'rollup-plugin-dts';
5
5
  import nodeResolve from '@rollup/plugin-node-resolve';
6
+ import fs$1 from 'node:fs';
7
+ import convert from 'convert-source-map';
6
8
  import { up } from 'empathic/find';
7
9
  import { resolveImports } from 'resolve-pkg-maps';
8
10
  import byteSize from 'byte-size';
@@ -71,10 +73,10 @@ const bgYellow = kolorist(43, 49);
71
73
  const cwd = process.cwd();
72
74
 
73
75
  const isPath = (filePath) => filePath[0] === "." || path.isAbsolute(filePath);
74
- const normalizePath$1 = (filepath) => filepath.replaceAll("\\", "/");
76
+ const normalizePath = (filepath) => filepath.replaceAll("\\", "/");
75
77
  const getDisplayPath = (fullPath) => {
76
78
  const relativePath = path.relative(cwd, fullPath);
77
- return normalizePath$1(
79
+ return normalizePath(
78
80
  relativePath.length < fullPath.length ? relativePath : fullPath
79
81
  );
80
82
  };
@@ -276,7 +278,6 @@ const getPackageName = (id) => {
276
278
  return id.slice(0, indexOfSlash);
277
279
  };
278
280
 
279
- const normalizePath = (filePath) => filePath.replaceAll("\\", "/");
280
281
  const getAllFiles = async (directoryPath, dontShortenPath) => {
281
282
  const directoryFiles = await fs.readdir(directoryPath, { withFileTypes: true });
282
283
  const fileTree = await Promise.all(
@@ -514,6 +515,139 @@ const createImportChainPlugin = () => {
514
515
  };
515
516
  };
516
517
 
518
+ const tryReadFile = async (filePath) => {
519
+ try {
520
+ return await fs$1.promises.readFile(filePath, "utf8");
521
+ } catch {
522
+ return null;
523
+ }
524
+ };
525
+ const loadSourceMap = async (codePath, code) => {
526
+ const adjacentMapPath = `${codePath}.map`;
527
+ const adjacentMapContent = await tryReadFile(adjacentMapPath);
528
+ if (adjacentMapContent) {
529
+ try {
530
+ const converter = convert.fromJSON(adjacentMapContent);
531
+ return {
532
+ map: converter.toObject(),
533
+ mapPath: adjacentMapPath
534
+ };
535
+ } catch {
536
+ }
537
+ }
538
+ try {
539
+ const inlineConverter = convert.fromSource(code);
540
+ if (inlineConverter) {
541
+ return {
542
+ map: inlineConverter.toObject(),
543
+ mapPath: codePath
544
+ };
545
+ }
546
+ } catch {
547
+ }
548
+ try {
549
+ const regex = new RegExp(convert.mapFileCommentRegex.source);
550
+ const commentMatch = regex.exec(code);
551
+ const referencedPath = commentMatch?.[1] ?? commentMatch?.[2];
552
+ if (!referencedPath) {
553
+ return;
554
+ }
555
+ const mapFilePath = path.join(path.dirname(codePath), referencedPath);
556
+ const mapContent = await tryReadFile(mapFilePath);
557
+ if (!mapContent) {
558
+ return;
559
+ }
560
+ const converter = convert.fromJSON(mapContent);
561
+ return {
562
+ map: converter.toObject(),
563
+ mapPath: mapFilePath
564
+ };
565
+ } catch {
566
+ }
567
+ };
568
+ const loadInputSourcemapsPlugin = () => {
569
+ const inputSourcemaps = /* @__PURE__ */ new Map();
570
+ return {
571
+ name: "load-input-sourcemaps",
572
+ async load(id) {
573
+ const isDts = dtsExtensions.some((extension) => id.endsWith(extension));
574
+ if (!isDts) {
575
+ return null;
576
+ }
577
+ const code = await tryReadFile(id);
578
+ if (!code) {
579
+ return null;
580
+ }
581
+ const result = await loadSourceMap(id, code);
582
+ if (!result) {
583
+ return { code };
584
+ }
585
+ const { map: inputMap, mapPath } = result;
586
+ const sourceRoot = path.resolve(path.dirname(mapPath), inputMap.sourceRoot ?? ".");
587
+ const sources = inputMap.sources.map(
588
+ (source) => path.isAbsolute(source) ? source : path.resolve(sourceRoot, source)
589
+ );
590
+ const sourcesContentRaw = await Promise.all(
591
+ sources.map(
592
+ async (source, index) => inputMap.sourcesContent?.[index] ?? tryReadFile(source)
593
+ )
594
+ );
595
+ const sourcesContent = sourcesContentRaw.filter(
596
+ (content) => content !== null
597
+ );
598
+ inputSourcemaps.set(id, {
599
+ sources,
600
+ sourcesContent
601
+ });
602
+ return {
603
+ code,
604
+ map: {
605
+ version: inputMap.version,
606
+ names: inputMap.names,
607
+ sources,
608
+ mappings: inputMap.mappings,
609
+ ...sourcesContent.length > 0 ? { sourcesContent } : {},
610
+ ...inputMap.file ? { file: inputMap.file } : {}
611
+ }
612
+ };
613
+ },
614
+ async writeBundle(options, bundle) {
615
+ const outputDir = options.dir ?? path.dirname(options.file ?? "");
616
+ if (!outputDir) {
617
+ return;
618
+ }
619
+ for (const [fileName, chunk] of Object.entries(bundle)) {
620
+ if (chunk.type !== "chunk" || !chunk.map) {
621
+ continue;
622
+ }
623
+ if (chunk.map.sources.length > 0) {
624
+ continue;
625
+ }
626
+ const entryModule = chunk.facadeModuleId;
627
+ if (!entryModule) {
628
+ continue;
629
+ }
630
+ const inputSourcemap = inputSourcemaps.get(entryModule);
631
+ if (!inputSourcemap || inputSourcemap.sources.length === 0) {
632
+ continue;
633
+ }
634
+ const mapFileName = `${fileName}.map`;
635
+ const mapPath = path.join(outputDir, mapFileName);
636
+ const outputFileDir = path.dirname(path.join(outputDir, fileName));
637
+ const relativeSources = inputSourcemap.sources.map(
638
+ (source) => normalizePath(path.relative(outputFileDir, source))
639
+ );
640
+ const fixedMap = {
641
+ ...chunk.map,
642
+ sources: relativeSources,
643
+ sourcesContent: inputSourcemap.sourcesContent.length > 0 ? inputSourcemap.sourcesContent : void 0
644
+ };
645
+ await fs$1.promises.writeFile(mapPath, JSON.stringify(fixedMap));
646
+ }
647
+ }
648
+ };
649
+ };
650
+
517
651
  const nodeModules = `${path.sep}node_modules${path.sep}`;
518
652
  const removeBundledModulesPlugin = (outputDirectory, sizeRef) => {
519
653
  let deleteFiles = [];
@@ -545,7 +679,11 @@ const removeBundledModulesPlugin = (outputDirectory, sizeRef) => {
545
679
  },
546
680
  writeBundle: async () => {
547
681
  await Promise.all(
548
- deleteFiles.map((moduleId) => fs.rm(moduleId))
682
+ deleteFiles.flatMap((moduleId) => [
683
+ fs.rm(moduleId),
684
+ // Also delete orphaned sourcemap files
685
+ fs.rm(`${moduleId}.map`, { force: true })
686
+ ])
549
687
  );
550
688
  }
551
689
  };
@@ -630,6 +768,8 @@ const build = async (input, outputDirectory, externals, mode, conditions, source
630
768
  externalizePlugin,
631
769
  removeBundledModulesPlugin(outputDirectory, sizeRef),
632
770
  resolveSubpathImportsPlugin(),
771
+ // Load existing .d.ts.map files to chain sourcemaps back to original .ts sources
772
+ sourcemap && loadInputSourcemapsPlugin(),
633
773
  nodeResolve({
634
774
  extensions: [".ts", ...dtsExtensions],
635
775
  exportConditions: conditions
package/dist/index.mjs CHANGED
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import 'node:path';
3
- export { d as dtsroll } from './index-Du7Kzot4.mjs';
3
+ export { d as dtsroll } from './index-D25w_e6R.mjs';
4
4
  import 'node:fs/promises';
5
5
  import 'rollup';
6
6
  import 'rollup-plugin-dts';
7
7
  import '@rollup/plugin-node-resolve';
8
+ import 'node:fs';
9
+ import 'convert-source-map';
8
10
  import 'empathic/find';
9
11
  import 'resolve-pkg-maps';
10
12
  import 'byte-size';
package/dist/vite.mjs CHANGED
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { d as dtsroll, l as logOutput } from './index-Du7Kzot4.mjs';
2
+ import { d as dtsroll, l as logOutput } from './index-D25w_e6R.mjs';
3
3
  import 'node:path';
4
4
  import 'node:fs/promises';
5
5
  import 'rollup';
6
6
  import 'rollup-plugin-dts';
7
7
  import '@rollup/plugin-node-resolve';
8
+ import 'node:fs';
9
+ import 'convert-source-map';
8
10
  import 'empathic/find';
9
11
  import 'resolve-pkg-maps';
10
12
  import 'byte-size';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dtsroll",
3
- "version": "1.6.0",
3
+ "version": "1.7.1",
4
4
  "description": "Bundle dts files",
5
5
  "keywords": [
6
6
  "bundle",
@@ -40,6 +40,7 @@
40
40
  "@rollup/plugin-node-resolve": "^16.0.3",
41
41
  "byte-size": "^9.0.1",
42
42
  "cleye": "^2.2.1",
43
+ "convert-source-map": "^2.0.0",
43
44
  "empathic": "^2.0.0",
44
45
  "resolve-pkg-maps": "^1.0.0",
45
46
  "rollup": "^4.55.1",