rolldown-plugin-dts 0.5.1 → 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.d.ts +1 -1
- package/dist/index.js +86 -41
- 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.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IsolatedDeclarationsOptions } from "oxc-transform";
|
|
2
|
-
import { CompilerOptions } from "typescript";
|
|
3
2
|
import { Plugin } from "rolldown";
|
|
3
|
+
import { CompilerOptions } from "typescript";
|
|
4
4
|
|
|
5
5
|
//#region src/fake-js.d.ts
|
|
6
6
|
declare function createFakeJsPlugin({ dtsInput }: Pick<Options, "dtsInput">): Plugin;
|
package/dist/index.js
CHANGED
|
@@ -4,8 +4,8 @@ import path, { basename, extname } from "node:path";
|
|
|
4
4
|
import { createResolver } from "dts-resolver";
|
|
5
5
|
import { getTsconfig } from "get-tsconfig";
|
|
6
6
|
import { isolatedDeclaration } from "oxc-transform";
|
|
7
|
-
import * as ts from "typescript";
|
|
8
7
|
import { createRequire } from "node:module";
|
|
8
|
+
import Debug from "debug";
|
|
9
9
|
|
|
10
10
|
//#region node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/walker.js
|
|
11
11
|
var WalkerBase = class {
|
|
@@ -257,7 +257,6 @@ function createFakeJsPlugin({ dtsInput }) {
|
|
|
257
257
|
preserveMap.set(id, preserved);
|
|
258
258
|
const s = new MagicStringAST(code);
|
|
259
259
|
for (let node of program.body) {
|
|
260
|
-
if (node.type === "ExportAllDeclaration" && node.exported && isRelative(node.source.value)) throw new Error("`export * as foo from './...'` is not supported");
|
|
261
260
|
if (rewriteImportExport(s, node)) continue;
|
|
262
261
|
const sideEffect = node.type === "TSModuleDeclaration" && node.kind !== "namespace";
|
|
263
262
|
const stmt = node;
|
|
@@ -316,17 +315,19 @@ function createFakeJsPlugin({ dtsInput }) {
|
|
|
316
315
|
}
|
|
317
316
|
}
|
|
318
317
|
if (comments.size) s.prepend(`${[...comments].join("\n")}\n`);
|
|
318
|
+
const removedNodes = patchTsNamespace(s, program.body);
|
|
319
319
|
for (const node of program.body) {
|
|
320
|
+
if (removedNodes.has(node)) continue;
|
|
320
321
|
if (patchImportSource(s, node)) continue;
|
|
321
322
|
if (node.type !== "VariableDeclaration" || node.declarations.length !== 1) continue;
|
|
322
323
|
const [decl] = node.declarations;
|
|
323
324
|
if (decl.init?.type !== "ArrayExpression" || !decl.init.elements[0]) {
|
|
324
|
-
|
|
325
|
+
s.removeNode(node);
|
|
325
326
|
continue;
|
|
326
327
|
}
|
|
327
328
|
const [symbolIdNode, ...depsNodes] = decl.init.elements;
|
|
328
329
|
if (symbolIdNode?.type !== "Literal" || typeof symbolIdNode.value !== "number") {
|
|
329
|
-
|
|
330
|
+
s.removeNode(node);
|
|
330
331
|
continue;
|
|
331
332
|
}
|
|
332
333
|
const symbolId = symbolIdNode.value;
|
|
@@ -343,7 +344,7 @@ function createFakeJsPlugin({ dtsInput }) {
|
|
|
343
344
|
s.overwriteNode(node, ss.toString());
|
|
344
345
|
}
|
|
345
346
|
const str = s.toString();
|
|
346
|
-
if (str.trim().length === 0) return "export {}";
|
|
347
|
+
if (str.trim().length === 0) return "export { };";
|
|
347
348
|
return str;
|
|
348
349
|
}
|
|
349
350
|
};
|
|
@@ -375,15 +376,14 @@ function collectDependencies(s, node, getIdentifierIndex) {
|
|
|
375
376
|
else if (node$1.type === "TSTypeQuery") addDependency(node$1.exprName);
|
|
376
377
|
else if (node$1.type === "TSImportType") {
|
|
377
378
|
if (node$1.argument.type !== "TSLiteralType" || node$1.argument.literal.type !== "Literal" || typeof node$1.argument.literal.value !== "string") return;
|
|
378
|
-
if (!node$1.qualifier) throw new Error("Import namespace is not supported");
|
|
379
379
|
const source = node$1.argument.literal.value;
|
|
380
|
-
const imported = s.sliceNode(node$1.qualifier);
|
|
380
|
+
const imported = node$1.qualifier && s.sliceNode(node$1.qualifier);
|
|
381
381
|
const local = importNamespace(s, source, imported, getIdentifierIndex);
|
|
382
382
|
addDependency({
|
|
383
383
|
type: "Identifier",
|
|
384
384
|
name: local,
|
|
385
385
|
start: node$1.start + (node$1.isTypeOf ? 7 : 0),
|
|
386
|
-
end: node$1.qualifier.end
|
|
386
|
+
end: node$1.qualifier ? node$1.qualifier.end : node$1.end
|
|
387
387
|
});
|
|
388
388
|
}
|
|
389
389
|
} });
|
|
@@ -399,16 +399,40 @@ function isReferenceId(node) {
|
|
|
399
399
|
function stringifyDependencies(s, deps) {
|
|
400
400
|
return deps.map((node) => `() => ${node.type === "Identifier" ? node.name : s.sliceNode(node)}`).join(", ");
|
|
401
401
|
}
|
|
402
|
-
function patchVariableDeclarator(s, node, decl) {
|
|
403
|
-
if (decl.init && !decl.id.typeAnnotation) s.overwriteNode(node, `type ${s.sliceNode(decl.id)} = ${s.sliceNode(decl.init)}`);
|
|
404
|
-
else if (!node.declare) s.prependLeft(node.start, "declare ");
|
|
405
|
-
}
|
|
406
402
|
function patchImportSource(s, node) {
|
|
407
403
|
if ((node.type === "ImportDeclaration" || node.type === "ExportAllDeclaration" || node.type === "ExportNamedDeclaration") && node.source?.value && RE_DTS.test(node.source.value)) {
|
|
408
404
|
s.overwriteNode(node.source, JSON.stringify(filename_dts_to(node.source.value, "js")));
|
|
409
405
|
return true;
|
|
410
406
|
}
|
|
411
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
|
+
}
|
|
412
436
|
function rewriteImportExport(s, node) {
|
|
413
437
|
if (node.type === "ImportDeclaration" || node.type === "ExportNamedDeclaration" && !node.declaration) {
|
|
414
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, ""));
|
|
@@ -423,7 +447,7 @@ function rewriteImportExport(s, node) {
|
|
|
423
447
|
if (node.moduleReference.type === "TSExternalModuleReference") s.overwriteNode(node, `import ${s.sliceNode(node.id)} from ${s.sliceNode(node.moduleReference.expression)}`);
|
|
424
448
|
return true;
|
|
425
449
|
} else if (node.type === "TSExportAssignment") {
|
|
426
|
-
s.overwriteNode(node, `export
|
|
450
|
+
s.overwriteNode(node, `export { ${s.sliceNode(node.expression)} as default }`);
|
|
427
451
|
return true;
|
|
428
452
|
} else if (node.type === "ExportDefaultDeclaration" && node.declaration.type === "Identifier") {
|
|
429
453
|
s.overwriteNode(node, `export { ${s.sliceNode(node.declaration)} as default }`);
|
|
@@ -432,22 +456,26 @@ function rewriteImportExport(s, node) {
|
|
|
432
456
|
}
|
|
433
457
|
function importNamespace(s, source, imported, getIdentifierIndex) {
|
|
434
458
|
const local = `_${getIdentifierIndex()}`;
|
|
435
|
-
|
|
459
|
+
const specifiers = imported ? `{ ${imported} as ${local} }` : `* as ${local}`;
|
|
460
|
+
s.prepend(`import ${specifiers} from ${JSON.stringify(source)};\n`);
|
|
436
461
|
return local;
|
|
437
462
|
}
|
|
438
463
|
|
|
439
464
|
//#endregion
|
|
440
465
|
//#region src/utils/tsc.ts
|
|
441
|
-
|
|
466
|
+
const debug = Debug("rolldown-plugin-dts:tsc");
|
|
467
|
+
let ts;
|
|
442
468
|
let formatHost;
|
|
443
469
|
function initTs() {
|
|
470
|
+
debug("loading typescript");
|
|
444
471
|
const require = createRequire(import.meta.url);
|
|
445
|
-
ts
|
|
472
|
+
ts = require("typescript");
|
|
446
473
|
formatHost = {
|
|
447
|
-
getCurrentDirectory: () => ts
|
|
448
|
-
getNewLine: () => ts
|
|
449
|
-
getCanonicalFileName: ts
|
|
474
|
+
getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
|
|
475
|
+
getNewLine: () => ts.sys.newLine,
|
|
476
|
+
getCanonicalFileName: ts.sys.useCaseSensitiveFileNames ? (f) => f : (f) => f.toLowerCase()
|
|
450
477
|
};
|
|
478
|
+
debug(`loaded typescript: ${ts.version}`);
|
|
451
479
|
}
|
|
452
480
|
const defaultCompilerOptions = {
|
|
453
481
|
declaration: true,
|
|
@@ -473,7 +501,9 @@ function createOrGetTsModule(programs, compilerOptions, id, code, isEntry) {
|
|
|
473
501
|
file: sourceFile
|
|
474
502
|
};
|
|
475
503
|
}
|
|
504
|
+
debug(`create program for module: ${id}`);
|
|
476
505
|
const module = createTsProgram(compilerOptions, id, code);
|
|
506
|
+
debug(`created program for module: ${id}`);
|
|
477
507
|
programs.push(module.program);
|
|
478
508
|
return module;
|
|
479
509
|
}
|
|
@@ -484,7 +514,7 @@ function createTsProgram(compilerOptions, id, code) {
|
|
|
484
514
|
...loadTsconfig(id),
|
|
485
515
|
...compilerOptions
|
|
486
516
|
};
|
|
487
|
-
const host = ts
|
|
517
|
+
const host = ts.createCompilerHost(options, true);
|
|
488
518
|
const { readFile: _readFile, fileExists: _fileExists } = host;
|
|
489
519
|
host.fileExists = (fileName) => {
|
|
490
520
|
if (files.has(fileName)) return true;
|
|
@@ -494,9 +524,9 @@ function createTsProgram(compilerOptions, id, code) {
|
|
|
494
524
|
if (files.has(fileName)) return files.get(fileName);
|
|
495
525
|
return _readFile(fileName);
|
|
496
526
|
};
|
|
497
|
-
const program = ts
|
|
527
|
+
const program = ts.createProgram([id], {
|
|
498
528
|
...compilerOptions,
|
|
499
|
-
moduleResolution: ts
|
|
529
|
+
moduleResolution: ts.ModuleResolutionKind.Node10,
|
|
500
530
|
declaration: true,
|
|
501
531
|
emitDeclarationOnly: true,
|
|
502
532
|
outDir: void 0,
|
|
@@ -512,15 +542,33 @@ function createTsProgram(compilerOptions, id, code) {
|
|
|
512
542
|
file: sourceFile
|
|
513
543
|
};
|
|
514
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
|
+
}
|
|
515
563
|
const tsconfigCache = new Map();
|
|
516
564
|
function loadTsconfig(id) {
|
|
517
|
-
const configPath = ts
|
|
565
|
+
const configPath = ts.findConfigFile(path.dirname(id), ts.sys.fileExists);
|
|
518
566
|
if (!configPath) return {};
|
|
519
567
|
if (tsconfigCache.has(configPath)) return tsconfigCache.get(configPath);
|
|
520
|
-
const { config, error } = ts
|
|
521
|
-
if (error) throw ts
|
|
522
|
-
const configContents = ts
|
|
523
|
-
if (configContents.errors.length) throw ts
|
|
568
|
+
const { config, error } = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
569
|
+
if (error) throw ts.formatDiagnostic(error, formatHost);
|
|
570
|
+
const configContents = ts.parseJsonConfigFileContent(config, ts.sys, path.dirname(configPath));
|
|
571
|
+
if (configContents.errors.length) throw ts.formatDiagnostics(configContents.errors, formatHost);
|
|
524
572
|
tsconfigCache.set(configPath, configContents.options);
|
|
525
573
|
return configContents.options;
|
|
526
574
|
}
|
|
@@ -568,22 +616,19 @@ function createGeneratePlugin({ compilerOptions, isolatedDeclaration: isolatedDe
|
|
|
568
616
|
const isEntry = mod?.isEntry;
|
|
569
617
|
if (isolatedDeclaration$1) {
|
|
570
618
|
const result = isolatedDeclaration(id, code, isolatedDeclaration$1 === true ? {} : isolatedDeclaration$1);
|
|
571
|
-
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
|
+
}
|
|
572
626
|
dtsCode = result.code;
|
|
573
627
|
} else {
|
|
574
|
-
const
|
|
575
|
-
const
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
dtsCode = code$1;
|
|
579
|
-
},
|
|
580
|
-
void 0,
|
|
581
|
-
true,
|
|
582
|
-
void 0,
|
|
583
|
-
// @ts-expect-error private API: forceDtsEmit
|
|
584
|
-
true
|
|
585
|
-
);
|
|
586
|
-
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;
|
|
587
632
|
}
|
|
588
633
|
if (!dtsCode) return this.error(new Error(`Failed to generate dts for ${id}`));
|
|
589
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",
|