rolldown-plugin-dts 0.8.6 → 0.9.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/dist/index.d.ts +68 -39
- package/dist/index.js +329 -202
- package/package.json +9 -5
package/dist/index.d.ts
CHANGED
|
@@ -3,53 +3,82 @@ import { IsolatedDeclarationsOptions } from "oxc-transform";
|
|
|
3
3
|
import { Plugin } from "rolldown";
|
|
4
4
|
|
|
5
5
|
//#region src/fake-js.d.ts
|
|
6
|
-
declare function createFakeJsPlugin({
|
|
6
|
+
declare function createFakeJsPlugin({
|
|
7
|
+
dtsInput,
|
|
8
|
+
sourcemap
|
|
9
|
+
}: OptionsResolved): Plugin;
|
|
7
10
|
|
|
8
11
|
//#endregion
|
|
9
12
|
//#region src/generate.d.ts
|
|
10
|
-
declare function createGeneratePlugin({
|
|
13
|
+
declare function createGeneratePlugin({
|
|
14
|
+
tsconfig,
|
|
15
|
+
compilerOptions,
|
|
16
|
+
isolatedDeclarations,
|
|
17
|
+
resolve,
|
|
18
|
+
emitDtsOnly
|
|
19
|
+
}: OptionsResolved): Plugin;
|
|
11
20
|
|
|
12
21
|
//#endregion
|
|
13
22
|
//#region src/index.d.ts
|
|
14
23
|
interface Options {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
24
|
+
cwd?: string;
|
|
25
|
+
/**
|
|
26
|
+
* When entries are `.d.ts` files (instead of `.ts` files), this option should be set to `true`.
|
|
27
|
+
*
|
|
28
|
+
* If enabled, the plugin will skip generating a `.d.ts` file for the entry point.
|
|
29
|
+
*/
|
|
30
|
+
dtsInput?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* When `true`, the plugin will only emit `.d.ts` files and remove all other chunks.
|
|
33
|
+
*
|
|
34
|
+
* This feature is particularly beneficial when you need to generate `d.ts` files for the CommonJS format as part of a separate build process.
|
|
35
|
+
*/
|
|
36
|
+
emitDtsOnly?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* The path to the `tsconfig.json` file.
|
|
39
|
+
*
|
|
40
|
+
* When set to `false`, the plugin will ignore any `tsconfig.json` file.
|
|
41
|
+
* However, `compilerOptions` can still be specified directly in the options.
|
|
42
|
+
*
|
|
43
|
+
* @default `tsconfig.json`
|
|
44
|
+
*/
|
|
45
|
+
tsconfig?: string | boolean;
|
|
46
|
+
/**
|
|
47
|
+
* The `compilerOptions` for the TypeScript compiler.
|
|
48
|
+
*
|
|
49
|
+
* @see https://www.typescriptlang.org/docs/handbook/compiler-options.html
|
|
50
|
+
*/
|
|
51
|
+
compilerOptions?: TsConfigJson.CompilerOptions;
|
|
52
|
+
/**
|
|
53
|
+
* When `true`, the plugin will generate `.d.ts` files using `oxc-transform`,
|
|
54
|
+
* which is blazingly faster than `typescript` compiler.
|
|
55
|
+
*
|
|
56
|
+
* This option is enabled when `isolatedDeclarations` in `compilerOptions` is set to `true`.
|
|
57
|
+
*/
|
|
58
|
+
isolatedDeclarations?: boolean | Omit<IsolatedDeclarationsOptions, "sourcemap">;
|
|
59
|
+
/**
|
|
60
|
+
* When `true`, the plugin will generate declaration maps for `.d.ts` files.
|
|
61
|
+
*/
|
|
62
|
+
sourcemap?: boolean;
|
|
63
|
+
/** Resolve external types used in dts files from `node_modules` */
|
|
64
|
+
resolve?: boolean | (string | RegExp)[];
|
|
51
65
|
}
|
|
66
|
+
type Overwrite<T, U> = Pick<T, Exclude<keyof T, keyof U>> & U;
|
|
67
|
+
type OptionsResolved = Overwrite<Required<Options>, {
|
|
68
|
+
tsconfig: string | undefined;
|
|
69
|
+
isolatedDeclarations: IsolatedDeclarationsOptions | false;
|
|
70
|
+
}>;
|
|
52
71
|
declare function dts(options?: Options): Plugin[];
|
|
72
|
+
declare function resolveOptions({
|
|
73
|
+
cwd,
|
|
74
|
+
tsconfig,
|
|
75
|
+
compilerOptions,
|
|
76
|
+
isolatedDeclarations,
|
|
77
|
+
sourcemap,
|
|
78
|
+
dtsInput,
|
|
79
|
+
emitDtsOnly,
|
|
80
|
+
resolve
|
|
81
|
+
}: Options): OptionsResolved;
|
|
53
82
|
|
|
54
83
|
//#endregion
|
|
55
|
-
export { Options, createFakeJsPlugin, createGeneratePlugin, dts };
|
|
84
|
+
export { Options, OptionsResolved, createFakeJsPlugin, createGeneratePlugin, dts, resolveOptions };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { MagicStringAST } from "magic-string-ast";
|
|
3
|
-
import { parseSync } from "oxc-parser";
|
|
4
2
|
import process from "node:process";
|
|
5
|
-
import { createResolver } from "dts-resolver";
|
|
6
3
|
import { getTsconfig, parseTsconfig } from "get-tsconfig";
|
|
4
|
+
import _generate from "@babel/generator";
|
|
5
|
+
import { parse } from "@babel/parser";
|
|
6
|
+
import * as t from "@babel/types";
|
|
7
|
+
import { isDeclarationType, isTypeOf } from "ast-kit";
|
|
8
|
+
import { createResolver } from "dts-resolver";
|
|
7
9
|
import { isolatedDeclaration } from "oxc-transform";
|
|
8
10
|
import { createRequire } from "node:module";
|
|
9
11
|
import Debug from "debug";
|
|
@@ -12,6 +14,7 @@ import Debug from "debug";
|
|
|
12
14
|
const RE_JS = /\.([cm]?)jsx?$/;
|
|
13
15
|
const RE_TS = /\.([cm]?)tsx?$/;
|
|
14
16
|
const RE_DTS = /\.d\.([cm]?)ts$/;
|
|
17
|
+
const RE_DTS_MAP = /\.d\.([cm]?)ts\.map$/;
|
|
15
18
|
const RE_NODE_MODULES = /[\\/]node_modules[\\/]/;
|
|
16
19
|
function filename_js_to_dts(id) {
|
|
17
20
|
return id.replace(RE_JS, ".d.$1ts");
|
|
@@ -43,7 +46,10 @@ function createDtsInputPlugin() {
|
|
|
43
46
|
outputOptions(options) {
|
|
44
47
|
return {
|
|
45
48
|
...options,
|
|
46
|
-
entryFileNames
|
|
49
|
+
entryFileNames(chunk) {
|
|
50
|
+
if (chunk.name.endsWith(".d")) return "[name].ts";
|
|
51
|
+
return "[name].d.ts";
|
|
52
|
+
}
|
|
47
53
|
};
|
|
48
54
|
},
|
|
49
55
|
resolveId: {
|
|
@@ -246,41 +252,23 @@ function walk(ast, { enter, leave }) {
|
|
|
246
252
|
return instance.visit(ast, null);
|
|
247
253
|
}
|
|
248
254
|
|
|
249
|
-
//#endregion
|
|
250
|
-
//#region src/utils/ast.ts
|
|
251
|
-
function getIdentifierRange(node, offset = 0) {
|
|
252
|
-
if ("typeAnnotation" in node && node.typeAnnotation) return [node.start + offset, node.typeAnnotation.start + offset];
|
|
253
|
-
return [node.start + offset, node.end + offset];
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
//#endregion
|
|
257
|
-
//#region src/utils/magic-string.ts
|
|
258
|
-
function overwriteOrAppend(s, range, replacement, suffix) {
|
|
259
|
-
if (range[0] === range[1]) {
|
|
260
|
-
s.appendLeft(range[0], ` ${replacement}`);
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
const original = s.slice(range[0], range[1]);
|
|
264
|
-
if (original !== replacement) s.overwrite(range[0], range[1], replacement + (suffix || ""));
|
|
265
|
-
}
|
|
266
|
-
|
|
267
255
|
//#endregion
|
|
268
256
|
//#region src/fake-js.ts
|
|
269
|
-
const
|
|
270
|
-
function createFakeJsPlugin({ dtsInput }) {
|
|
257
|
+
const generate = _generate.default || _generate;
|
|
258
|
+
function createFakeJsPlugin({ dtsInput, sourcemap }) {
|
|
271
259
|
let symbolIdx = 0;
|
|
272
260
|
let identifierIdx = 0;
|
|
273
261
|
const symbolMap = new Map();
|
|
274
|
-
const
|
|
262
|
+
const commentsMap = new Map();
|
|
275
263
|
function getIdentifierIndex() {
|
|
276
264
|
return identifierIdx++;
|
|
277
265
|
}
|
|
278
|
-
function
|
|
266
|
+
function registerSymbol(info) {
|
|
279
267
|
const symbolId = symbolIdx++;
|
|
280
268
|
symbolMap.set(symbolId, info);
|
|
281
269
|
return symbolId;
|
|
282
270
|
}
|
|
283
|
-
function
|
|
271
|
+
function getSymbol(symbolId) {
|
|
284
272
|
return symbolMap.get(symbolId);
|
|
285
273
|
}
|
|
286
274
|
return {
|
|
@@ -307,6 +295,7 @@ function createFakeJsPlugin({ dtsInput }) {
|
|
|
307
295
|
if (options.format === "cjs" || options.format === "commonjs") throw new Error("[rolldown-plugin-dts] Cannot bundle dts files with `cjs` format.");
|
|
308
296
|
return {
|
|
309
297
|
...options,
|
|
298
|
+
sourcemap: sourcemap ? true : options.sourcemap,
|
|
310
299
|
entryFileNames: options.entryFileNames ?? (dtsInput ? "[name].ts" : void 0),
|
|
311
300
|
chunkFileNames(chunk) {
|
|
312
301
|
const original = (typeof options.chunkFileNames === "function" ? options.chunkFileNames(chunk) : options.chunkFileNames) || "[name]-[hash].js";
|
|
@@ -318,137 +307,183 @@ function createFakeJsPlugin({ dtsInput }) {
|
|
|
318
307
|
transform: {
|
|
319
308
|
filter: { id: RE_DTS },
|
|
320
309
|
handler(code, id) {
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
const
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
needDeclare,
|
|
356
|
-
preserveName: sideEffect
|
|
357
|
-
});
|
|
358
|
-
const runtime = `[${symbolId}, ${depsString}${depsString && sideEffect ? ", " : ""}${sideEffect ? "sideEffect()" : ""}]`;
|
|
359
|
-
const bindingName = sideEffect ? `_${identifierIdx++}` : binding ? s.sliceNode(binding) : "export_default";
|
|
360
|
-
if (isDefaultExport) s.overwriteNode(stmt, `var ${bindingName} = ${runtime};export { ${bindingName} as default }`);
|
|
361
|
-
else s.overwriteNode(node, `var ${bindingName} = ${runtime};`);
|
|
310
|
+
const file = parse(code, {
|
|
311
|
+
plugins: [["typescript", { dts: true }]],
|
|
312
|
+
sourceType: "module"
|
|
313
|
+
});
|
|
314
|
+
const { program, comments } = file;
|
|
315
|
+
if (comments) {
|
|
316
|
+
const directives = collectReferenceDirectives(comments);
|
|
317
|
+
commentsMap.set(id, directives);
|
|
318
|
+
}
|
|
319
|
+
const prependStmts = [];
|
|
320
|
+
const appendStmts = [];
|
|
321
|
+
const prepend = (stmt) => prependStmts.push(stmt);
|
|
322
|
+
for (const [i, stmt] of program.body.entries()) {
|
|
323
|
+
const setStmt = (node) => program.body[i] = inheritNode(stmt, node);
|
|
324
|
+
if (rewriteImportExport(stmt, setStmt)) continue;
|
|
325
|
+
const sideEffect = stmt.type === "TSModuleDeclaration" && stmt.kind !== "namespace";
|
|
326
|
+
const isDefaultExport = stmt.type === "ExportDefaultDeclaration";
|
|
327
|
+
const isDecl = isTypeOf(stmt, ["ExportNamedDeclaration", "ExportDefaultDeclaration"]) && stmt.declaration;
|
|
328
|
+
const decl = isDecl ? stmt.declaration : stmt;
|
|
329
|
+
const setDecl = isDecl ? (node) => stmt.declaration = inheritNode(stmt.declaration, node) : setStmt;
|
|
330
|
+
if (decl.type === "VariableDeclaration" && decl.declarations.length !== 1) throw new Error("Only one declaration is supported");
|
|
331
|
+
if (decl.type !== "TSDeclareFunction" && !isDeclarationType(decl)) continue;
|
|
332
|
+
if (isTypeOf(decl, [
|
|
333
|
+
"TSEnumDeclaration",
|
|
334
|
+
"ClassDeclaration",
|
|
335
|
+
"FunctionDeclaration",
|
|
336
|
+
"TSDeclareFunction",
|
|
337
|
+
"TSModuleDeclaration",
|
|
338
|
+
"VariableDeclaration"
|
|
339
|
+
])) decl.declare = true;
|
|
340
|
+
let binding = decl.type === "VariableDeclaration" ? decl.declarations[0].id : "id" in decl ? decl.id : null;
|
|
341
|
+
if (!binding) {
|
|
342
|
+
binding = t.identifier("export_default");
|
|
343
|
+
decl.id = binding;
|
|
362
344
|
}
|
|
345
|
+
binding = sideEffect ? t.identifier(`_${identifierIdx++}`) : binding;
|
|
346
|
+
const deps = collectDependencies(decl, getIdentifierIndex, prepend);
|
|
347
|
+
const elements = [
|
|
348
|
+
t.numericLiteral(0),
|
|
349
|
+
...deps.map((dep) => t.arrowFunctionExpression([], dep)),
|
|
350
|
+
...sideEffect ? [t.callExpression(t.identifier("sideEffect"), [])] : []
|
|
351
|
+
];
|
|
352
|
+
const runtime = t.arrayExpression(elements);
|
|
353
|
+
const symbolId = registerSymbol({
|
|
354
|
+
decl,
|
|
355
|
+
deps,
|
|
356
|
+
binding
|
|
357
|
+
});
|
|
358
|
+
elements[0] = t.numericLiteral(symbolId);
|
|
359
|
+
const runtimeAssignment = {
|
|
360
|
+
type: "VariableDeclaration",
|
|
361
|
+
kind: "var",
|
|
362
|
+
declarations: [{
|
|
363
|
+
type: "VariableDeclarator",
|
|
364
|
+
id: {
|
|
365
|
+
...binding,
|
|
366
|
+
typeAnnotation: null
|
|
367
|
+
},
|
|
368
|
+
init: runtime
|
|
369
|
+
}]
|
|
370
|
+
};
|
|
371
|
+
if (isDefaultExport) {
|
|
372
|
+
appendStmts.push(t.exportNamedDeclaration(null, [t.exportSpecifier(binding, t.identifier("default"))]));
|
|
373
|
+
setStmt(runtimeAssignment);
|
|
374
|
+
} else setDecl(runtimeAssignment);
|
|
363
375
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
376
|
+
program.body = [
|
|
377
|
+
...prependStmts,
|
|
378
|
+
...program.body,
|
|
379
|
+
...appendStmts
|
|
380
|
+
];
|
|
381
|
+
const result = generate(file, {
|
|
382
|
+
comments: true,
|
|
383
|
+
sourceMaps: sourcemap,
|
|
384
|
+
sourceFileName: id
|
|
385
|
+
});
|
|
386
|
+
return result;
|
|
367
387
|
}
|
|
368
388
|
},
|
|
369
389
|
renderChunk(code, chunk) {
|
|
370
390
|
if (!RE_DTS.test(chunk.fileName)) return;
|
|
371
|
-
const
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
preserveComments
|
|
378
|
-
|
|
391
|
+
const file = parse(code, { sourceType: "module" });
|
|
392
|
+
const { program } = file;
|
|
393
|
+
if (program.body.length) {
|
|
394
|
+
const comments = new Set();
|
|
395
|
+
const commentsValue = new Set();
|
|
396
|
+
for (const id of chunk.moduleIds) {
|
|
397
|
+
const preserveComments = commentsMap.get(id);
|
|
398
|
+
if (preserveComments) {
|
|
399
|
+
preserveComments.forEach((c) => {
|
|
400
|
+
const id$1 = c.type + c.value;
|
|
401
|
+
if (commentsValue.has(id$1)) return;
|
|
402
|
+
commentsValue.add(id$1);
|
|
403
|
+
comments.add(c);
|
|
404
|
+
});
|
|
405
|
+
commentsMap.delete(id);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (comments.size) {
|
|
409
|
+
program.body[0].leadingComments ||= [];
|
|
410
|
+
program.body[0].leadingComments.push(...comments);
|
|
379
411
|
}
|
|
380
412
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
if (
|
|
385
|
-
if (patchImportSource(s, node)) continue;
|
|
386
|
-
if (node.type !== "VariableDeclaration" || node.declarations.length !== 1) continue;
|
|
413
|
+
program.body = patchTsNamespace(program.body);
|
|
414
|
+
program.body = program.body.map((node) => {
|
|
415
|
+
if (patchImportSource(node)) return node;
|
|
416
|
+
if (node.type !== "VariableDeclaration" || node.declarations.length !== 1) return node;
|
|
387
417
|
const [decl] = node.declarations;
|
|
388
|
-
if (decl.init?.type !== "ArrayExpression" || !decl.init.elements[0])
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
}
|
|
392
|
-
const [symbolIdNode, ...depsNodes] = decl.init.elements;
|
|
393
|
-
if (symbolIdNode?.type !== "Literal" || typeof symbolIdNode.value !== "number") {
|
|
394
|
-
s.removeNode(node);
|
|
395
|
-
continue;
|
|
396
|
-
}
|
|
418
|
+
if (decl.init?.type !== "ArrayExpression" || !decl.init.elements[0]) return null;
|
|
419
|
+
const [symbolIdNode, ...depsFns] = decl.init.elements;
|
|
420
|
+
if (symbolIdNode?.type !== "NumericLiteral") return null;
|
|
397
421
|
const symbolId = symbolIdNode.value;
|
|
398
|
-
const
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
422
|
+
const original = getSymbol(symbolId);
|
|
423
|
+
const transformedBinding = {
|
|
424
|
+
...decl.id,
|
|
425
|
+
typeAnnotation: original.binding.typeAnnotation
|
|
426
|
+
};
|
|
427
|
+
overwriteNode(original.binding, transformedBinding);
|
|
428
|
+
const transformedDeps = depsFns.filter((node$1) => node$1?.type === "ArrowFunctionExpression").map((node$1) => node$1.body);
|
|
429
|
+
if (original.deps.length) for (let i = 0; i < original.deps.length; i++) {
|
|
430
|
+
const originalDep = original.deps[i];
|
|
431
|
+
if (originalDep.replace) originalDep.replace(transformedDeps[i]);
|
|
432
|
+
else Object.assign(originalDep, transformedDeps[i]);
|
|
405
433
|
}
|
|
406
|
-
|
|
407
|
-
|
|
434
|
+
return inheritNode(node, original.decl);
|
|
435
|
+
}).filter((node) => !!node);
|
|
436
|
+
if (program.body.length === 0) return "export { };";
|
|
437
|
+
const result = generate(file, {
|
|
438
|
+
comments: true,
|
|
439
|
+
sourceMaps: sourcemap,
|
|
440
|
+
sourceFileName: chunk.fileName
|
|
441
|
+
});
|
|
442
|
+
return result;
|
|
443
|
+
},
|
|
444
|
+
generateBundle(options, bundle) {
|
|
445
|
+
for (const chunk of Object.values(bundle)) {
|
|
446
|
+
if (chunk.type !== "asset" || !RE_DTS_MAP.test(chunk.fileName) || typeof chunk.source !== "string") continue;
|
|
447
|
+
const maps = JSON.parse(chunk.source);
|
|
448
|
+
maps.sourcesContent = null;
|
|
449
|
+
chunk.source = JSON.stringify(maps);
|
|
408
450
|
}
|
|
409
|
-
const str = s.toString();
|
|
410
|
-
if (str.trim().length === 0) return "export { };";
|
|
411
|
-
return str;
|
|
412
451
|
}
|
|
413
452
|
};
|
|
414
453
|
}
|
|
415
454
|
const REFERENCE_RE = /\/\s*<reference\s+(?:path|types)=/;
|
|
416
455
|
function collectReferenceDirectives(comment) {
|
|
417
|
-
return comment.filter((c) => REFERENCE_RE.test(c.value))
|
|
456
|
+
return comment.filter((c) => REFERENCE_RE.test(c.value));
|
|
418
457
|
}
|
|
419
|
-
function collectDependencies(
|
|
458
|
+
function collectDependencies(node, getIdentifierIndex, prepend) {
|
|
420
459
|
const deps = new Set();
|
|
460
|
+
const seen = new Set();
|
|
421
461
|
walk(node, { leave(node$1) {
|
|
422
462
|
if (node$1.type === "ExportNamedDeclaration") {
|
|
423
|
-
for (const specifier of node$1.specifiers) if (specifier.type === "ExportSpecifier")
|
|
424
|
-
|
|
425
|
-
if (specifier.local.start === specifier.exported.start && specifier.local.end === specifier.exported.end) _suffix = ` as ${s.sliceNode(specifier.local)}`;
|
|
426
|
-
addDependency({
|
|
427
|
-
...specifier.local,
|
|
428
|
-
_suffix
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
} else if (node$1.type === "TSInterfaceDeclaration" && node$1.extends) for (const heritage of node$1.extends || []) addDependency(heritage.expression);
|
|
463
|
+
for (const specifier of node$1.specifiers) if (specifier.type === "ExportSpecifier") addDependency(specifier.local);
|
|
464
|
+
} else if (node$1.type === "TSInterfaceDeclaration" && node$1.extends) for (const heritage of node$1.extends || []) addDependency(TSEntityNameToRuntime(heritage.expression));
|
|
432
465
|
else if (node$1.type === "ClassDeclaration") {
|
|
433
466
|
if (node$1.superClass) addDependency(node$1.superClass);
|
|
434
|
-
if (node$1.implements) for (const implement of node$1.implements) addDependency(implement.expression);
|
|
435
|
-
} else if (node$1
|
|
467
|
+
if (node$1.implements) for (const implement of node$1.implements) addDependency(TSEntityNameToRuntime(implement.expression));
|
|
468
|
+
} else if (isTypeOf(node$1, [
|
|
469
|
+
"ObjectMethod",
|
|
470
|
+
"ObjectProperty",
|
|
471
|
+
"ClassProperty",
|
|
472
|
+
"TSPropertySignature",
|
|
473
|
+
"TSDeclareMethod"
|
|
474
|
+
])) {
|
|
436
475
|
if (node$1.computed && isReferenceId(node$1.key)) addDependency(node$1.key);
|
|
437
476
|
if ("value" in node$1 && isReferenceId(node$1.value)) addDependency(node$1.value);
|
|
438
|
-
} else if (node$1.type === "TSTypeReference") addDependency(node$1.typeName);
|
|
477
|
+
} else if (node$1.type === "TSTypeReference") addDependency(TSEntityNameToRuntime(node$1.typeName));
|
|
439
478
|
else if (node$1.type === "TSTypeQuery") {
|
|
440
|
-
if (
|
|
479
|
+
if (seen.has(node$1.exprName)) return;
|
|
480
|
+
if (node$1.exprName.type !== "TSImportType") addDependency(TSEntityNameToRuntime(node$1.exprName));
|
|
441
481
|
} else if (node$1.type === "TSImportType") {
|
|
442
|
-
|
|
443
|
-
const source = node$1.argument
|
|
444
|
-
const imported = node$1.qualifier
|
|
445
|
-
const
|
|
446
|
-
addDependency(
|
|
447
|
-
type: "Identifier",
|
|
448
|
-
name: local,
|
|
449
|
-
start: node$1.start,
|
|
450
|
-
end: imported ? imported.end : node$1.end
|
|
451
|
-
});
|
|
482
|
+
seen.add(node$1);
|
|
483
|
+
const source = node$1.argument;
|
|
484
|
+
const imported = node$1.qualifier;
|
|
485
|
+
const dep = importNamespace(node$1, imported, source, getIdentifierIndex, prepend);
|
|
486
|
+
addDependency(dep);
|
|
452
487
|
}
|
|
453
488
|
} });
|
|
454
489
|
return Array.from(deps);
|
|
@@ -457,76 +492,151 @@ function collectDependencies(s, node, getIdentifierIndex) {
|
|
|
457
492
|
deps.add(node$1);
|
|
458
493
|
}
|
|
459
494
|
}
|
|
460
|
-
function
|
|
495
|
+
function TSEntityNameToRuntime(node) {
|
|
496
|
+
if (node.type === "Identifier") return node;
|
|
497
|
+
const left = TSEntityNameToRuntime(node.left);
|
|
498
|
+
return Object.assign(node, t.memberExpression(left, node.right));
|
|
499
|
+
}
|
|
500
|
+
function getIdFromTSEntityName(node) {
|
|
461
501
|
if (node.type === "Identifier") return node;
|
|
462
|
-
return
|
|
502
|
+
return getIdFromTSEntityName(node.left);
|
|
463
503
|
}
|
|
464
504
|
function isReferenceId(node) {
|
|
465
505
|
return !!node && (node.type === "Identifier" || node.type === "MemberExpression");
|
|
466
506
|
}
|
|
467
|
-
function
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
507
|
+
function patchImportSource(node) {
|
|
508
|
+
if (isTypeOf(node, [
|
|
509
|
+
"ImportDeclaration",
|
|
510
|
+
"ExportAllDeclaration",
|
|
511
|
+
"ExportNamedDeclaration"
|
|
512
|
+
]) && node.source?.value && RE_DTS.test(node.source.value)) {
|
|
513
|
+
node.source.value = filename_dts_to(node.source.value, "js");
|
|
473
514
|
return true;
|
|
474
515
|
}
|
|
475
516
|
}
|
|
476
|
-
function patchTsNamespace(
|
|
517
|
+
function patchTsNamespace(nodes) {
|
|
477
518
|
const emptyObjectAssignments = new Map();
|
|
478
519
|
const removed = new Set();
|
|
479
|
-
for (const node of nodes) {
|
|
480
|
-
if (node.type === "VariableDeclaration" && node.declarations.length === 1 && node.declarations[0].init?.type === "ObjectExpression" && node.declarations[0].init.properties.length === 0) emptyObjectAssignments.set(
|
|
520
|
+
for (const [i, node] of nodes.entries()) {
|
|
521
|
+
if (node.type === "VariableDeclaration" && node.declarations.length === 1 && node.declarations[0].id.type === "Identifier" && node.declarations[0].init?.type === "ObjectExpression" && node.declarations[0].init.properties.length === 0) emptyObjectAssignments.set(node.declarations[0].id.name, node);
|
|
481
522
|
if (node.type !== "ExpressionStatement" || node.expression.type !== "CallExpression" || node.expression.callee.type !== "Identifier" || !node.expression.callee.name.startsWith("__export")) continue;
|
|
482
523
|
const [binding, exports] = node.expression.arguments;
|
|
483
|
-
|
|
524
|
+
if (binding.type !== "Identifier") continue;
|
|
525
|
+
const bindingText = binding.name;
|
|
484
526
|
if (emptyObjectAssignments.has(bindingText)) {
|
|
485
527
|
const emptyNode = emptyObjectAssignments.get(bindingText);
|
|
486
|
-
s.removeNode(emptyNode);
|
|
487
528
|
emptyObjectAssignments.delete(bindingText);
|
|
488
529
|
removed.add(emptyNode);
|
|
489
530
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
531
|
+
nodes[i] = {
|
|
532
|
+
type: "TSModuleDeclaration",
|
|
533
|
+
id: binding,
|
|
534
|
+
kind: "namespace",
|
|
535
|
+
declare: true,
|
|
536
|
+
body: {
|
|
537
|
+
type: "TSModuleBlock",
|
|
538
|
+
body: [{
|
|
539
|
+
type: "ExportNamedDeclaration",
|
|
540
|
+
specifiers: exports.properties.filter((property) => property.type === "ObjectProperty").map((property) => {
|
|
541
|
+
const local = property.value.body;
|
|
542
|
+
const exported = property.key;
|
|
543
|
+
return t.exportSpecifier(local, exported);
|
|
544
|
+
}),
|
|
545
|
+
source: null,
|
|
546
|
+
declaration: null
|
|
547
|
+
}]
|
|
548
|
+
}
|
|
549
|
+
};
|
|
501
550
|
}
|
|
502
|
-
return removed;
|
|
551
|
+
return nodes.filter((node) => !removed.has(node));
|
|
503
552
|
}
|
|
504
|
-
function rewriteImportExport(
|
|
553
|
+
function rewriteImportExport(node, set) {
|
|
505
554
|
if (node.type === "ImportDeclaration" || node.type === "ExportNamedDeclaration" && !node.declaration) {
|
|
506
|
-
for (const specifier of node.specifiers) if (specifier.type === "ImportSpecifier"
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
if (
|
|
555
|
+
for (const specifier of node.specifiers) if (specifier.type === "ImportSpecifier") specifier.importKind = "value";
|
|
556
|
+
else if (specifier.type === "ExportSpecifier") specifier.exportKind = "value";
|
|
557
|
+
if (node.type === "ImportDeclaration") node.importKind = "value";
|
|
558
|
+
else if (node.type === "ExportNamedDeclaration") node.exportKind = "value";
|
|
510
559
|
return true;
|
|
511
560
|
} else if (node.type === "ExportAllDeclaration") {
|
|
512
|
-
|
|
561
|
+
node.exportKind = "value";
|
|
513
562
|
return true;
|
|
514
563
|
} else if (node.type === "TSImportEqualsDeclaration") {
|
|
515
|
-
if (node.moduleReference.type === "TSExternalModuleReference")
|
|
564
|
+
if (node.moduleReference.type === "TSExternalModuleReference") set({
|
|
565
|
+
type: "ImportDeclaration",
|
|
566
|
+
specifiers: [{
|
|
567
|
+
type: "ImportDefaultSpecifier",
|
|
568
|
+
local: node.id
|
|
569
|
+
}],
|
|
570
|
+
source: node.moduleReference.expression
|
|
571
|
+
});
|
|
516
572
|
return true;
|
|
517
|
-
} else if (node.type === "TSExportAssignment") {
|
|
518
|
-
|
|
573
|
+
} else if (node.type === "TSExportAssignment" && node.expression.type === "Identifier") {
|
|
574
|
+
set({
|
|
575
|
+
type: "ExportNamedDeclaration",
|
|
576
|
+
specifiers: [{
|
|
577
|
+
type: "ExportSpecifier",
|
|
578
|
+
local: node.expression,
|
|
579
|
+
exported: {
|
|
580
|
+
type: "Identifier",
|
|
581
|
+
name: "default"
|
|
582
|
+
}
|
|
583
|
+
}]
|
|
584
|
+
});
|
|
519
585
|
return true;
|
|
520
586
|
} else if (node.type === "ExportDefaultDeclaration" && node.declaration.type === "Identifier") {
|
|
521
|
-
|
|
587
|
+
set({
|
|
588
|
+
type: "ExportNamedDeclaration",
|
|
589
|
+
specifiers: [{
|
|
590
|
+
type: "ExportSpecifier",
|
|
591
|
+
local: node.declaration,
|
|
592
|
+
exported: t.identifier("default")
|
|
593
|
+
}]
|
|
594
|
+
});
|
|
522
595
|
return true;
|
|
523
596
|
}
|
|
597
|
+
return false;
|
|
524
598
|
}
|
|
525
|
-
function importNamespace(
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
599
|
+
function importNamespace(node, imported, source, getIdentifierIndex, prepend) {
|
|
600
|
+
let local = t.identifier(`_${getIdentifierIndex()}`);
|
|
601
|
+
prepend(t.importDeclaration([t.importNamespaceSpecifier(local)], source));
|
|
602
|
+
if (imported) {
|
|
603
|
+
const importedLeft = getIdFromTSEntityName(imported);
|
|
604
|
+
overwriteNode(importedLeft, t.tsQualifiedName(local, { ...importedLeft }));
|
|
605
|
+
local = imported;
|
|
606
|
+
}
|
|
607
|
+
let replacement = node;
|
|
608
|
+
if (node.typeParameters) {
|
|
609
|
+
overwriteNode(node, t.tsTypeReference(local, node.typeParameters));
|
|
610
|
+
replacement = local;
|
|
611
|
+
} else overwriteNode(node, local);
|
|
612
|
+
const dep = {
|
|
613
|
+
...TSEntityNameToRuntime(local),
|
|
614
|
+
replace(newNode) {
|
|
615
|
+
overwriteNode(replacement, newNode);
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
return dep;
|
|
619
|
+
}
|
|
620
|
+
function inheritNode(oldValue, newValue) {
|
|
621
|
+
return {
|
|
622
|
+
...newValue,
|
|
623
|
+
leadingComments: oldValue.leadingComments,
|
|
624
|
+
innerComments: oldValue.innerComments,
|
|
625
|
+
trailingComments: oldValue.trailingComments
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
function overwriteNode(node, newNode) {
|
|
629
|
+
const preserve = [
|
|
630
|
+
"leadingComments",
|
|
631
|
+
"innerComments",
|
|
632
|
+
"trailingComments"
|
|
633
|
+
];
|
|
634
|
+
for (const key of Object.keys(node)) {
|
|
635
|
+
if (preserve.includes(key)) continue;
|
|
636
|
+
delete node[key];
|
|
637
|
+
}
|
|
638
|
+
Object.assign(node, newNode, { ...node });
|
|
639
|
+
return node;
|
|
530
640
|
}
|
|
531
641
|
|
|
532
642
|
//#endregion
|
|
@@ -631,28 +741,8 @@ function getTsModule(dtsMap, tsId) {
|
|
|
631
741
|
//#endregion
|
|
632
742
|
//#region src/generate.ts
|
|
633
743
|
const meta = { dtsFile: true };
|
|
634
|
-
function createGeneratePlugin({ tsconfig, compilerOptions, isolatedDeclarations, resolve = false, emitDtsOnly = false }) {
|
|
744
|
+
function createGeneratePlugin({ tsconfig, compilerOptions = {}, isolatedDeclarations, resolve = false, emitDtsOnly = false }) {
|
|
635
745
|
const dtsMap = new Map();
|
|
636
|
-
function resolveOptions(cwd) {
|
|
637
|
-
if (tsconfig === true || tsconfig == null) {
|
|
638
|
-
const { config, path: path$1 } = getTsconfig(cwd) || {};
|
|
639
|
-
tsconfig = path$1;
|
|
640
|
-
compilerOptions = {
|
|
641
|
-
...config?.compilerOptions,
|
|
642
|
-
...compilerOptions
|
|
643
|
-
};
|
|
644
|
-
} else if (typeof tsconfig === "string") {
|
|
645
|
-
tsconfig = path.resolve(cwd || process.cwd(), tsconfig);
|
|
646
|
-
const config = parseTsconfig(tsconfig);
|
|
647
|
-
compilerOptions = {
|
|
648
|
-
...config.compilerOptions,
|
|
649
|
-
...compilerOptions
|
|
650
|
-
};
|
|
651
|
-
}
|
|
652
|
-
if (isolatedDeclarations == null) isolatedDeclarations = !!compilerOptions?.isolatedDeclarations;
|
|
653
|
-
if (isolatedDeclarations === true) isolatedDeclarations = {};
|
|
654
|
-
if (isolatedDeclarations && isolatedDeclarations.stripInternal == null) isolatedDeclarations.stripInternal = !!compilerOptions?.stripInternal;
|
|
655
|
-
}
|
|
656
746
|
/**
|
|
657
747
|
* A map of input id to output file name
|
|
658
748
|
*
|
|
@@ -663,14 +753,12 @@ function createGeneratePlugin({ tsconfig, compilerOptions, isolatedDeclarations,
|
|
|
663
753
|
* ])
|
|
664
754
|
*/
|
|
665
755
|
const inputAliasMap = new Map();
|
|
666
|
-
let resolver;
|
|
667
756
|
let programs = [];
|
|
757
|
+
const resolver = createResolver({ tsconfig: tsconfig ? tsconfig : void 0 });
|
|
758
|
+
if (!isolatedDeclarations) initTs();
|
|
668
759
|
return {
|
|
669
760
|
name: "rolldown-plugin-dts:generate",
|
|
670
761
|
async buildStart(options) {
|
|
671
|
-
resolveOptions(options.cwd);
|
|
672
|
-
resolver = createResolver({ tsconfig: tsconfig ? tsconfig : void 0 });
|
|
673
|
-
if (!isolatedDeclarations) initTs();
|
|
674
762
|
if (!Array.isArray(options.input)) for (const [name, id] of Object.entries(options.input)) {
|
|
675
763
|
let resolved = await this.resolve(id, void 0, { skipSelf: true });
|
|
676
764
|
resolved ||= await this.resolve(`./${id}`, void 0, { skipSelf: true });
|
|
@@ -784,8 +872,9 @@ function createGeneratePlugin({ tsconfig, compilerOptions, isolatedDeclarations,
|
|
|
784
872
|
if (!dtsMap.has(dtsId)) return;
|
|
785
873
|
const { code, id, isEntry } = dtsMap.get(dtsId);
|
|
786
874
|
let dtsCode;
|
|
875
|
+
let map;
|
|
787
876
|
if (isolatedDeclarations) {
|
|
788
|
-
const result = isolatedDeclaration(id, code, isolatedDeclarations
|
|
877
|
+
const result = isolatedDeclaration(id, code, isolatedDeclarations);
|
|
789
878
|
if (result.errors.length) {
|
|
790
879
|
const [error] = result.errors;
|
|
791
880
|
return this.error({
|
|
@@ -794,6 +883,7 @@ function createGeneratePlugin({ tsconfig, compilerOptions, isolatedDeclarations,
|
|
|
794
883
|
});
|
|
795
884
|
}
|
|
796
885
|
dtsCode = result.code;
|
|
886
|
+
if (result.map) map = result.map;
|
|
797
887
|
} else {
|
|
798
888
|
const module = createOrGetTsModule(programs, compilerOptions, id, isEntry, dtsMap);
|
|
799
889
|
const result = tscEmit(module);
|
|
@@ -803,12 +893,13 @@ function createGeneratePlugin({ tsconfig, compilerOptions, isolatedDeclarations,
|
|
|
803
893
|
if (!dtsCode) return this.error(new Error(`Failed to generate dts for ${id}`));
|
|
804
894
|
return {
|
|
805
895
|
code: dtsCode,
|
|
806
|
-
moduleSideEffects: false
|
|
896
|
+
moduleSideEffects: false,
|
|
897
|
+
map
|
|
807
898
|
};
|
|
808
899
|
}
|
|
809
900
|
},
|
|
810
901
|
generateBundle: emitDtsOnly ? (options, bundle) => {
|
|
811
|
-
for (const fileName of Object.keys(bundle)) if (!RE_DTS.test(fileName)) delete bundle[fileName];
|
|
902
|
+
for (const fileName of Object.keys(bundle)) if (bundle[fileName].type === "chunk" && !RE_DTS.test(fileName) && !RE_DTS_MAP.test(fileName)) delete bundle[fileName];
|
|
812
903
|
} : void 0,
|
|
813
904
|
buildEnd() {
|
|
814
905
|
programs = [];
|
|
@@ -819,12 +910,48 @@ function createGeneratePlugin({ tsconfig, compilerOptions, isolatedDeclarations,
|
|
|
819
910
|
//#endregion
|
|
820
911
|
//#region src/index.ts
|
|
821
912
|
function dts(options = {}) {
|
|
913
|
+
const resolved = resolveOptions(options);
|
|
822
914
|
const plugins = [];
|
|
823
915
|
if (options.dtsInput) plugins.push(createDtsInputPlugin());
|
|
824
|
-
else plugins.push(createGeneratePlugin(
|
|
825
|
-
plugins.push(createFakeJsPlugin(
|
|
916
|
+
else plugins.push(createGeneratePlugin(resolved));
|
|
917
|
+
plugins.push(createFakeJsPlugin(resolved));
|
|
826
918
|
return plugins;
|
|
827
919
|
}
|
|
920
|
+
function resolveOptions({ cwd = process.cwd(), tsconfig, compilerOptions = {}, isolatedDeclarations, sourcemap, dtsInput = false, emitDtsOnly = false, resolve = false }) {
|
|
921
|
+
if (tsconfig === true || tsconfig == null) {
|
|
922
|
+
const { config, path: path$1 } = getTsconfig(cwd) || {};
|
|
923
|
+
tsconfig = path$1;
|
|
924
|
+
compilerOptions = {
|
|
925
|
+
...config?.compilerOptions,
|
|
926
|
+
...compilerOptions
|
|
927
|
+
};
|
|
928
|
+
} else if (typeof tsconfig === "string") {
|
|
929
|
+
tsconfig = path.resolve(cwd || process.cwd(), tsconfig);
|
|
930
|
+
const config = parseTsconfig(tsconfig);
|
|
931
|
+
compilerOptions = {
|
|
932
|
+
...config.compilerOptions,
|
|
933
|
+
...compilerOptions
|
|
934
|
+
};
|
|
935
|
+
} else tsconfig = void 0;
|
|
936
|
+
sourcemap ??= !!compilerOptions.declarationMap;
|
|
937
|
+
compilerOptions.declarationMap = sourcemap;
|
|
938
|
+
if (isolatedDeclarations == null) isolatedDeclarations = !!compilerOptions?.isolatedDeclarations;
|
|
939
|
+
if (isolatedDeclarations === true) isolatedDeclarations = {};
|
|
940
|
+
if (isolatedDeclarations) {
|
|
941
|
+
isolatedDeclarations.stripInternal ??= !!compilerOptions?.stripInternal;
|
|
942
|
+
isolatedDeclarations.sourcemap = !!compilerOptions.declarationMap;
|
|
943
|
+
}
|
|
944
|
+
return {
|
|
945
|
+
cwd,
|
|
946
|
+
tsconfig,
|
|
947
|
+
compilerOptions,
|
|
948
|
+
isolatedDeclarations,
|
|
949
|
+
sourcemap,
|
|
950
|
+
dtsInput,
|
|
951
|
+
emitDtsOnly,
|
|
952
|
+
resolve
|
|
953
|
+
};
|
|
954
|
+
}
|
|
828
955
|
|
|
829
956
|
//#endregion
|
|
830
|
-
export { createFakeJsPlugin, createGeneratePlugin, dts };
|
|
957
|
+
export { createFakeJsPlugin, createGeneratePlugin, dts, resolveOptions };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rolldown-plugin-dts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "A Rolldown plugin to bundle dts files",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -37,20 +37,23 @@
|
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
+
"@babel/generator": "^7.27.0",
|
|
41
|
+
"@babel/parser": "^7.27.0",
|
|
42
|
+
"@babel/types": "^7.27.0",
|
|
43
|
+
"ast-kit": "^1.4.3",
|
|
40
44
|
"debug": "^4.4.0",
|
|
41
45
|
"dts-resolver": "^1.0.1",
|
|
42
46
|
"get-tsconfig": "^4.10.0",
|
|
43
|
-
"magic-string-ast": "^0.9.1",
|
|
44
|
-
"oxc-parser": "^0.66.0",
|
|
45
47
|
"oxc-transform": "^0.66.0"
|
|
46
48
|
},
|
|
47
49
|
"devDependencies": {
|
|
48
50
|
"@sxzz/eslint-config": "^6.1.2",
|
|
49
51
|
"@sxzz/prettier-config": "^2.2.1",
|
|
50
52
|
"@sxzz/test-utils": "^0.5.5",
|
|
53
|
+
"@types/babel__generator": "^7.27.0",
|
|
51
54
|
"@types/debug": "^4.1.12",
|
|
52
55
|
"@types/diff": "^7.0.2",
|
|
53
|
-
"@types/node": "^22.
|
|
56
|
+
"@types/node": "^22.15.2",
|
|
54
57
|
"bumpp": "^10.1.0",
|
|
55
58
|
"diff": "^7.0.0",
|
|
56
59
|
"eslint": "^9.25.1",
|
|
@@ -58,7 +61,8 @@
|
|
|
58
61
|
"prettier": "^3.5.3",
|
|
59
62
|
"rolldown": "1.0.0-beta.8-commit.6aca0ce",
|
|
60
63
|
"rollup-plugin-dts": "^6.2.1",
|
|
61
|
-
"
|
|
64
|
+
"tinyglobby": "^0.2.13",
|
|
65
|
+
"tsdown": "^0.9.8",
|
|
62
66
|
"tsx": "^4.19.3",
|
|
63
67
|
"typescript": "^5.8.3",
|
|
64
68
|
"vitest": "^3.1.2"
|