rolldown-plugin-dts 0.5.2 → 0.6.0
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 +5 -8
- package/dist/index.js +73 -27
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -74,17 +74,14 @@ interface Options {
|
|
|
74
74
|
}
|
|
75
75
|
````
|
|
76
76
|
|
|
77
|
-
##
|
|
77
|
+
## Differences from `rollup-plugin-dts`
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
offering significantly faster performance compared to the `typescript` compiler.
|
|
79
|
+
### Isolated Declarations
|
|
81
80
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
- `import * as ns from './ns'` and then `export { ns }`
|
|
85
|
-
- `type ns = import('./ns')`
|
|
81
|
+
The plugin leverages Oxc's `isolatedDeclarations` to generate `.d.ts` files when `isolatedDeclaration` is enabled,
|
|
82
|
+
offering significantly faster performance compared to the `typescript` compiler.
|
|
86
83
|
|
|
87
|
-
|
|
84
|
+
### Single Build for ESM
|
|
88
85
|
|
|
89
86
|
`rolldown-plugin-dts` generates separate chunks for `.d.ts` files, enabling both source code (`.js`)
|
|
90
87
|
and type definition files (`.d.ts`) to be produced in a single build process.
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { createResolver } from "dts-resolver";
|
|
|
5
5
|
import { getTsconfig } from "get-tsconfig";
|
|
6
6
|
import { isolatedDeclaration } from "oxc-transform";
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
|
+
import Debug from "debug";
|
|
8
9
|
|
|
9
10
|
//#region node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/walker.js
|
|
10
11
|
var WalkerBase = class {
|
|
@@ -256,7 +257,6 @@ function createFakeJsPlugin({ dtsInput }) {
|
|
|
256
257
|
preserveMap.set(id, preserved);
|
|
257
258
|
const s = new MagicStringAST(code);
|
|
258
259
|
for (let node of program.body) {
|
|
259
|
-
if (node.type === "ExportAllDeclaration" && node.exported && isRelative(node.source.value)) throw new Error("`export * as foo from './...'` is not supported");
|
|
260
260
|
if (rewriteImportExport(s, node)) continue;
|
|
261
261
|
const sideEffect = node.type === "TSModuleDeclaration" && node.kind !== "namespace";
|
|
262
262
|
const stmt = node;
|
|
@@ -315,17 +315,19 @@ function createFakeJsPlugin({ dtsInput }) {
|
|
|
315
315
|
}
|
|
316
316
|
}
|
|
317
317
|
if (comments.size) s.prepend(`${[...comments].join("\n")}\n`);
|
|
318
|
+
const removedNodes = patchTsNamespace(s, program.body);
|
|
318
319
|
for (const node of program.body) {
|
|
320
|
+
if (removedNodes.has(node)) continue;
|
|
319
321
|
if (patchImportSource(s, node)) continue;
|
|
320
322
|
if (node.type !== "VariableDeclaration" || node.declarations.length !== 1) continue;
|
|
321
323
|
const [decl] = node.declarations;
|
|
322
324
|
if (decl.init?.type !== "ArrayExpression" || !decl.init.elements[0]) {
|
|
323
|
-
|
|
325
|
+
s.removeNode(node);
|
|
324
326
|
continue;
|
|
325
327
|
}
|
|
326
328
|
const [symbolIdNode, ...depsNodes] = decl.init.elements;
|
|
327
329
|
if (symbolIdNode?.type !== "Literal" || typeof symbolIdNode.value !== "number") {
|
|
328
|
-
|
|
330
|
+
s.removeNode(node);
|
|
329
331
|
continue;
|
|
330
332
|
}
|
|
331
333
|
const symbolId = symbolIdNode.value;
|
|
@@ -342,7 +344,7 @@ function createFakeJsPlugin({ dtsInput }) {
|
|
|
342
344
|
s.overwriteNode(node, ss.toString());
|
|
343
345
|
}
|
|
344
346
|
const str = s.toString();
|
|
345
|
-
if (str.trim().length === 0) return "export {}";
|
|
347
|
+
if (str.trim().length === 0) return "export { };";
|
|
346
348
|
return str;
|
|
347
349
|
}
|
|
348
350
|
};
|
|
@@ -374,15 +376,14 @@ function collectDependencies(s, node, getIdentifierIndex) {
|
|
|
374
376
|
else if (node$1.type === "TSTypeQuery") addDependency(node$1.exprName);
|
|
375
377
|
else if (node$1.type === "TSImportType") {
|
|
376
378
|
if (node$1.argument.type !== "TSLiteralType" || node$1.argument.literal.type !== "Literal" || typeof node$1.argument.literal.value !== "string") return;
|
|
377
|
-
if (!node$1.qualifier) throw new Error("Import namespace is not supported");
|
|
378
379
|
const source = node$1.argument.literal.value;
|
|
379
|
-
const imported = s.sliceNode(node$1.qualifier);
|
|
380
|
+
const imported = node$1.qualifier && s.sliceNode(node$1.qualifier);
|
|
380
381
|
const local = importNamespace(s, source, imported, getIdentifierIndex);
|
|
381
382
|
addDependency({
|
|
382
383
|
type: "Identifier",
|
|
383
384
|
name: local,
|
|
384
385
|
start: node$1.start + (node$1.isTypeOf ? 7 : 0),
|
|
385
|
-
end: node$1.qualifier.end
|
|
386
|
+
end: node$1.qualifier ? node$1.qualifier.end : node$1.end
|
|
386
387
|
});
|
|
387
388
|
}
|
|
388
389
|
} });
|
|
@@ -398,16 +399,40 @@ function isReferenceId(node) {
|
|
|
398
399
|
function stringifyDependencies(s, deps) {
|
|
399
400
|
return deps.map((node) => `() => ${node.type === "Identifier" ? node.name : s.sliceNode(node)}`).join(", ");
|
|
400
401
|
}
|
|
401
|
-
function patchVariableDeclarator(s, node, decl) {
|
|
402
|
-
if (decl.init && !decl.id.typeAnnotation) s.overwriteNode(node, `type ${s.sliceNode(decl.id)} = ${s.sliceNode(decl.init)}`);
|
|
403
|
-
else if (!node.declare) s.prependLeft(node.start, "declare ");
|
|
404
|
-
}
|
|
405
402
|
function patchImportSource(s, node) {
|
|
406
403
|
if ((node.type === "ImportDeclaration" || node.type === "ExportAllDeclaration" || node.type === "ExportNamedDeclaration") && node.source?.value && RE_DTS.test(node.source.value)) {
|
|
407
404
|
s.overwriteNode(node.source, JSON.stringify(filename_dts_to(node.source.value, "js")));
|
|
408
405
|
return true;
|
|
409
406
|
}
|
|
410
407
|
}
|
|
408
|
+
function patchTsNamespace(s, nodes) {
|
|
409
|
+
const emptyObjectAssignments = new Map();
|
|
410
|
+
const removed = new Set();
|
|
411
|
+
for (const node of nodes) {
|
|
412
|
+
if (node.type === "VariableDeclaration" && node.declarations.length === 1 && node.declarations[0].init?.type === "ObjectExpression" && node.declarations[0].init.properties.length === 0) emptyObjectAssignments.set(s.sliceNode(node.declarations[0].id), node);
|
|
413
|
+
if (node.type !== "ExpressionStatement" || node.expression.type !== "CallExpression" || node.expression.callee.type !== "Identifier" || !node.expression.callee.name.startsWith("__export")) continue;
|
|
414
|
+
const [binding, exports] = node.expression.arguments;
|
|
415
|
+
const bindingText = s.sliceNode(binding);
|
|
416
|
+
if (emptyObjectAssignments.has(bindingText)) {
|
|
417
|
+
const emptyNode = emptyObjectAssignments.get(bindingText);
|
|
418
|
+
s.removeNode(emptyNode);
|
|
419
|
+
emptyObjectAssignments.delete(bindingText);
|
|
420
|
+
removed.add(emptyNode);
|
|
421
|
+
}
|
|
422
|
+
let code = `declare namespace ${bindingText} {
|
|
423
|
+
export { `;
|
|
424
|
+
for (const properties of exports.properties) {
|
|
425
|
+
if (properties.type !== "Property") continue;
|
|
426
|
+
const exported = s.sliceNode(properties.key);
|
|
427
|
+
const local = s.sliceNode(properties.value.body);
|
|
428
|
+
const suffix = exported !== local ? ` as ${exported}` : "";
|
|
429
|
+
code += `${local}${suffix}, `;
|
|
430
|
+
}
|
|
431
|
+
code += `}\n}`;
|
|
432
|
+
s.overwriteNode(node, code);
|
|
433
|
+
}
|
|
434
|
+
return removed;
|
|
435
|
+
}
|
|
411
436
|
function rewriteImportExport(s, node) {
|
|
412
437
|
if (node.type === "ImportDeclaration" || node.type === "ExportNamedDeclaration" && !node.declaration) {
|
|
413
438
|
for (const specifier of node.specifiers) if (specifier.type === "ImportSpecifier" && specifier.importKind === "type" || specifier.type === "ExportSpecifier" && specifier.exportKind === "type") s.overwriteNode(specifier, s.sliceNode(specifier).replace(RE_TYPE, ""));
|
|
@@ -422,7 +447,7 @@ function rewriteImportExport(s, node) {
|
|
|
422
447
|
if (node.moduleReference.type === "TSExternalModuleReference") s.overwriteNode(node, `import ${s.sliceNode(node.id)} from ${s.sliceNode(node.moduleReference.expression)}`);
|
|
423
448
|
return true;
|
|
424
449
|
} else if (node.type === "TSExportAssignment") {
|
|
425
|
-
s.overwriteNode(node, `export
|
|
450
|
+
s.overwriteNode(node, `export { ${s.sliceNode(node.expression)} as default }`);
|
|
426
451
|
return true;
|
|
427
452
|
} else if (node.type === "ExportDefaultDeclaration" && node.declaration.type === "Identifier") {
|
|
428
453
|
s.overwriteNode(node, `export { ${s.sliceNode(node.declaration)} as default }`);
|
|
@@ -431,15 +456,18 @@ function rewriteImportExport(s, node) {
|
|
|
431
456
|
}
|
|
432
457
|
function importNamespace(s, source, imported, getIdentifierIndex) {
|
|
433
458
|
const local = `_${getIdentifierIndex()}`;
|
|
434
|
-
|
|
459
|
+
const specifiers = imported ? `{ ${imported} as ${local} }` : `* as ${local}`;
|
|
460
|
+
s.prepend(`import ${specifiers} from ${JSON.stringify(source)};\n`);
|
|
435
461
|
return local;
|
|
436
462
|
}
|
|
437
463
|
|
|
438
464
|
//#endregion
|
|
439
465
|
//#region src/utils/tsc.ts
|
|
466
|
+
const debug = Debug("rolldown-plugin-dts:tsc");
|
|
440
467
|
let ts;
|
|
441
468
|
let formatHost;
|
|
442
469
|
function initTs() {
|
|
470
|
+
debug("loading typescript");
|
|
443
471
|
const require = createRequire(import.meta.url);
|
|
444
472
|
ts = require("typescript");
|
|
445
473
|
formatHost = {
|
|
@@ -447,6 +475,7 @@ function initTs() {
|
|
|
447
475
|
getNewLine: () => ts.sys.newLine,
|
|
448
476
|
getCanonicalFileName: ts.sys.useCaseSensitiveFileNames ? (f) => f : (f) => f.toLowerCase()
|
|
449
477
|
};
|
|
478
|
+
debug(`loaded typescript: ${ts.version}`);
|
|
450
479
|
}
|
|
451
480
|
const defaultCompilerOptions = {
|
|
452
481
|
declaration: true,
|
|
@@ -472,7 +501,9 @@ function createOrGetTsModule(programs, compilerOptions, id, code, isEntry) {
|
|
|
472
501
|
file: sourceFile
|
|
473
502
|
};
|
|
474
503
|
}
|
|
504
|
+
debug(`create program for module: ${id}`);
|
|
475
505
|
const module = createTsProgram(compilerOptions, id, code);
|
|
506
|
+
debug(`created program for module: ${id}`);
|
|
476
507
|
programs.push(module.program);
|
|
477
508
|
return module;
|
|
478
509
|
}
|
|
@@ -511,6 +542,24 @@ function createTsProgram(compilerOptions, id, code) {
|
|
|
511
542
|
file: sourceFile
|
|
512
543
|
};
|
|
513
544
|
}
|
|
545
|
+
function tscEmit(module) {
|
|
546
|
+
const { program: { program }, file } = module;
|
|
547
|
+
let dtsCode;
|
|
548
|
+
const { emitSkipped, diagnostics } = program.emit(
|
|
549
|
+
file,
|
|
550
|
+
(_, code) => {
|
|
551
|
+
debug(`emit dts: ${file.fileName}`);
|
|
552
|
+
dtsCode = code;
|
|
553
|
+
},
|
|
554
|
+
void 0,
|
|
555
|
+
true,
|
|
556
|
+
void 0,
|
|
557
|
+
// @ts-expect-error private API: forceDtsEmit
|
|
558
|
+
true
|
|
559
|
+
);
|
|
560
|
+
if (emitSkipped && diagnostics.length) return { error: ts.formatDiagnostics(diagnostics, formatHost) };
|
|
561
|
+
return { code: dtsCode };
|
|
562
|
+
}
|
|
514
563
|
const tsconfigCache = new Map();
|
|
515
564
|
function loadTsconfig(id) {
|
|
516
565
|
const configPath = ts.findConfigFile(path.dirname(id), ts.sys.fileExists);
|
|
@@ -567,22 +616,19 @@ function createGeneratePlugin({ compilerOptions, isolatedDeclaration: isolatedDe
|
|
|
567
616
|
const isEntry = mod?.isEntry;
|
|
568
617
|
if (isolatedDeclaration$1) {
|
|
569
618
|
const result = isolatedDeclaration(id, code, isolatedDeclaration$1 === true ? {} : isolatedDeclaration$1);
|
|
570
|
-
if (result.errors.length)
|
|
619
|
+
if (result.errors.length) {
|
|
620
|
+
const [error] = result.errors;
|
|
621
|
+
return this.error({
|
|
622
|
+
message: error.message,
|
|
623
|
+
frame: error.codeframe
|
|
624
|
+
});
|
|
625
|
+
}
|
|
571
626
|
dtsCode = result.code;
|
|
572
627
|
} else {
|
|
573
|
-
const
|
|
574
|
-
const
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
dtsCode = code$1;
|
|
578
|
-
},
|
|
579
|
-
void 0,
|
|
580
|
-
true,
|
|
581
|
-
void 0,
|
|
582
|
-
// @ts-expect-error private API: forceDtsEmit
|
|
583
|
-
true
|
|
584
|
-
);
|
|
585
|
-
if (emitSkipped && diagnostics.length) return this.error(ts.formatDiagnostics(diagnostics, formatHost));
|
|
628
|
+
const module = createOrGetTsModule(programs, compilerOptions, id, code, isEntry);
|
|
629
|
+
const result = tscEmit(module);
|
|
630
|
+
if (result.error) return this.error(result.error);
|
|
631
|
+
dtsCode = result.code;
|
|
586
632
|
}
|
|
587
633
|
if (!dtsCode) return this.error(new Error(`Failed to generate dts for ${id}`));
|
|
588
634
|
const dtsId = filename_ts_to_dts(id);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rolldown-plugin-dts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "A Rolldown plugin to bundle dts files",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
+
"debug": "^4.4.0",
|
|
40
41
|
"dts-resolver": "^0.1.0",
|
|
41
42
|
"get-tsconfig": "^4.10.0",
|
|
42
43
|
"magic-string-ast": "^0.9.1",
|
|
@@ -47,6 +48,7 @@
|
|
|
47
48
|
"@sxzz/eslint-config": "^6.1.1",
|
|
48
49
|
"@sxzz/prettier-config": "^2.2.1",
|
|
49
50
|
"@sxzz/test-utils": "^0.5.4",
|
|
51
|
+
"@types/debug": "^4.1.12",
|
|
50
52
|
"@types/diff": "^7.0.2",
|
|
51
53
|
"@types/node": "^22.14.0",
|
|
52
54
|
"bumpp": "^10.1.0",
|