rolldown-plugin-dts 0.0.0 → 0.1.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/LICENSE +21 -0
- package/README.md +57 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +404 -0
- package/package.json +61 -7
- package/.vscode/settings.json +0 -5
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright © 2025 三咲智子 Kevin Deng (https://github.com/sxzz)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# rolldown-plugin-dts [](https://npmjs.com/package/rolldown-plugin-dts)
|
|
2
|
+
|
|
3
|
+
[](https://github.com/sxzz/rolldown-plugin-dts/actions/workflows/unit-test.yml)
|
|
4
|
+
|
|
5
|
+
A Rolldown plugin to bundle dts files.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm i rolldown-plugin-dts
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
Add the plugin to your `rolldown.config.js`:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
// rolldown.config.js
|
|
19
|
+
import { dts } from 'rolldown-plugin-dts'
|
|
20
|
+
|
|
21
|
+
const config = [
|
|
22
|
+
{
|
|
23
|
+
input: './index.d.ts',
|
|
24
|
+
plugins: [dts()],
|
|
25
|
+
output: [
|
|
26
|
+
{
|
|
27
|
+
file: 'dist/index.d.ts',
|
|
28
|
+
format: 'es',
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
export default config
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
> [!NOTE]
|
|
38
|
+
> Namespaces are not supported yet.
|
|
39
|
+
|
|
40
|
+
## Credits
|
|
41
|
+
|
|
42
|
+
The project is inspired by [rollup-plugin-dts](https://github.com/Swatinem/rollup-plugin-dts)
|
|
43
|
+
but has been independently implemented.
|
|
44
|
+
We extend our gratitude to the original creators for their contributions.
|
|
45
|
+
Furthermore, the test suite is authorized by them and distributed under the MIT license.
|
|
46
|
+
|
|
47
|
+
## Sponsors
|
|
48
|
+
|
|
49
|
+
<p align="center">
|
|
50
|
+
<a href="https://cdn.jsdelivr.net/gh/sxzz/sponsors/sponsors.svg">
|
|
51
|
+
<img src='https://cdn.jsdelivr.net/gh/sxzz/sponsors/sponsors.svg'/>
|
|
52
|
+
</a>
|
|
53
|
+
</p>
|
|
54
|
+
|
|
55
|
+
## License
|
|
56
|
+
|
|
57
|
+
[MIT](./LICENSE) License © 2025 [三咲智子 Kevin Deng](https://github.com/sxzz)
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { MagicStringAST } from "magic-string-ast";
|
|
3
|
+
import { parseAsync } from "oxc-parser";
|
|
4
|
+
|
|
5
|
+
//#region node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/walker.js
|
|
6
|
+
var WalkerBase = class {
|
|
7
|
+
constructor() {
|
|
8
|
+
/** @type {boolean} */
|
|
9
|
+
this.should_skip = false;
|
|
10
|
+
/** @type {boolean} */
|
|
11
|
+
this.should_remove = false;
|
|
12
|
+
/** @type {Node | null} */
|
|
13
|
+
this.replacement = null;
|
|
14
|
+
/** @type {WalkerContext} */
|
|
15
|
+
this.context = {
|
|
16
|
+
skip: () => this.should_skip = true,
|
|
17
|
+
remove: () => this.should_remove = true,
|
|
18
|
+
replace: (node) => this.replacement = node
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* @template {Node} Parent
|
|
23
|
+
* @param {Parent | null | undefined} parent
|
|
24
|
+
* @param {keyof Parent | null | undefined} prop
|
|
25
|
+
* @param {number | null | undefined} index
|
|
26
|
+
* @param {Node} node
|
|
27
|
+
*/
|
|
28
|
+
replace(parent, prop, index, node) {
|
|
29
|
+
if (parent && prop) if (index != null)
|
|
30
|
+
/** @type {Array<Node>} */ parent[prop][index] = node;
|
|
31
|
+
else
|
|
32
|
+
/** @type {Node} */ parent[prop] = node;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* @template {Node} Parent
|
|
36
|
+
* @param {Parent | null | undefined} parent
|
|
37
|
+
* @param {keyof Parent | null | undefined} prop
|
|
38
|
+
* @param {number | null | undefined} index
|
|
39
|
+
*/
|
|
40
|
+
remove(parent, prop, index) {
|
|
41
|
+
if (parent && prop) if (index !== null && index !== void 0)
|
|
42
|
+
/** @type {Array<Node>} */ parent[prop].splice(index, 1);
|
|
43
|
+
else delete parent[prop];
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/sync.js
|
|
49
|
+
var SyncWalker = class extends WalkerBase {
|
|
50
|
+
/**
|
|
51
|
+
*
|
|
52
|
+
* @param {SyncHandler} [enter]
|
|
53
|
+
* @param {SyncHandler} [leave]
|
|
54
|
+
*/
|
|
55
|
+
constructor(enter, leave) {
|
|
56
|
+
super();
|
|
57
|
+
/** @type {boolean} */
|
|
58
|
+
this.should_skip = false;
|
|
59
|
+
/** @type {boolean} */
|
|
60
|
+
this.should_remove = false;
|
|
61
|
+
/** @type {Node | null} */
|
|
62
|
+
this.replacement = null;
|
|
63
|
+
/** @type {WalkerContext} */
|
|
64
|
+
this.context = {
|
|
65
|
+
skip: () => this.should_skip = true,
|
|
66
|
+
remove: () => this.should_remove = true,
|
|
67
|
+
replace: (node) => this.replacement = node
|
|
68
|
+
};
|
|
69
|
+
/** @type {SyncHandler | undefined} */
|
|
70
|
+
this.enter = enter;
|
|
71
|
+
/** @type {SyncHandler | undefined} */
|
|
72
|
+
this.leave = leave;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* @template {Node} Parent
|
|
76
|
+
* @param {Node} node
|
|
77
|
+
* @param {Parent | null} parent
|
|
78
|
+
* @param {keyof Parent} [prop]
|
|
79
|
+
* @param {number | null} [index]
|
|
80
|
+
* @returns {Node | null}
|
|
81
|
+
*/
|
|
82
|
+
visit(node, parent, prop, index) {
|
|
83
|
+
if (node) {
|
|
84
|
+
if (this.enter) {
|
|
85
|
+
const _should_skip = this.should_skip;
|
|
86
|
+
const _should_remove = this.should_remove;
|
|
87
|
+
const _replacement = this.replacement;
|
|
88
|
+
this.should_skip = false;
|
|
89
|
+
this.should_remove = false;
|
|
90
|
+
this.replacement = null;
|
|
91
|
+
this.enter.call(this.context, node, parent, prop, index);
|
|
92
|
+
if (this.replacement) {
|
|
93
|
+
node = this.replacement;
|
|
94
|
+
this.replace(parent, prop, index, node);
|
|
95
|
+
}
|
|
96
|
+
if (this.should_remove) this.remove(parent, prop, index);
|
|
97
|
+
const skipped = this.should_skip;
|
|
98
|
+
const removed = this.should_remove;
|
|
99
|
+
this.should_skip = _should_skip;
|
|
100
|
+
this.should_remove = _should_remove;
|
|
101
|
+
this.replacement = _replacement;
|
|
102
|
+
if (skipped) return node;
|
|
103
|
+
if (removed) return null;
|
|
104
|
+
}
|
|
105
|
+
/** @type {keyof Node} */
|
|
106
|
+
let key;
|
|
107
|
+
for (key in node) {
|
|
108
|
+
/** @type {unknown} */
|
|
109
|
+
const value = node[key];
|
|
110
|
+
if (value && typeof value === "object") {
|
|
111
|
+
if (Array.isArray(value)) {
|
|
112
|
+
const nodes = value;
|
|
113
|
+
for (let i$1 = 0; i$1 < nodes.length; i$1 += 1) {
|
|
114
|
+
const item = nodes[i$1];
|
|
115
|
+
if (isNode(item)) {
|
|
116
|
+
if (!this.visit(item, node, key, i$1)) i$1--;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
} else if (isNode(value)) this.visit(value, node, key, null);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (this.leave) {
|
|
123
|
+
const _replacement = this.replacement;
|
|
124
|
+
const _should_remove = this.should_remove;
|
|
125
|
+
this.replacement = null;
|
|
126
|
+
this.should_remove = false;
|
|
127
|
+
this.leave.call(this.context, node, parent, prop, index);
|
|
128
|
+
if (this.replacement) {
|
|
129
|
+
node = this.replacement;
|
|
130
|
+
this.replace(parent, prop, index, node);
|
|
131
|
+
}
|
|
132
|
+
if (this.should_remove) this.remove(parent, prop, index);
|
|
133
|
+
const removed = this.should_remove;
|
|
134
|
+
this.replacement = _replacement;
|
|
135
|
+
this.should_remove = _should_remove;
|
|
136
|
+
if (removed) return null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return node;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Ducktype a node.
|
|
144
|
+
*
|
|
145
|
+
* @param {unknown} value
|
|
146
|
+
* @returns {value is Node}
|
|
147
|
+
*/
|
|
148
|
+
function isNode(value) {
|
|
149
|
+
return value !== null && typeof value === "object" && "type" in value && typeof value.type === "string";
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
//#endregion
|
|
153
|
+
//#region node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/index.js
|
|
154
|
+
function walk(ast, { enter, leave }) {
|
|
155
|
+
const instance = new SyncWalker(enter, leave);
|
|
156
|
+
return instance.visit(ast, null);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
//#endregion
|
|
160
|
+
//#region src/utils/ast.ts
|
|
161
|
+
function getIdentifierRange(node, offset = 0) {
|
|
162
|
+
if ("typeAnnotation" in node && node.typeAnnotation) return [node.start + offset, node.typeAnnotation.start + offset];
|
|
163
|
+
return [node.start + offset, node.end + offset];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region src/utils/magic-string.ts
|
|
168
|
+
function overwriteOrAppend(s, range, replacement) {
|
|
169
|
+
if (range[0] === range[1]) {
|
|
170
|
+
s.appendLeft(range[0], ` ${replacement}`);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
s.overwrite(range[0], range[1], replacement);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region src/index.ts
|
|
178
|
+
const RE_TYPE = /\btype\b/;
|
|
179
|
+
function dts() {
|
|
180
|
+
let i$1 = 0;
|
|
181
|
+
const symbolMap = new Map();
|
|
182
|
+
const commentMap = new Map();
|
|
183
|
+
function register(info) {
|
|
184
|
+
const symbolId = i$1++;
|
|
185
|
+
symbolMap.set(symbolId, info);
|
|
186
|
+
return symbolId;
|
|
187
|
+
}
|
|
188
|
+
function retrieve(symbolId) {
|
|
189
|
+
return symbolMap.get(symbolId);
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
name: "rolldown-plugin-dts",
|
|
193
|
+
options({ onLog,...options }) {
|
|
194
|
+
return {
|
|
195
|
+
...options,
|
|
196
|
+
resolve: {
|
|
197
|
+
extensions: [
|
|
198
|
+
".d.ts",
|
|
199
|
+
".d.mts",
|
|
200
|
+
".d.cts"
|
|
201
|
+
],
|
|
202
|
+
extensionAlias: {
|
|
203
|
+
".js": [".d.ts"],
|
|
204
|
+
".mjs": [".d.mts"],
|
|
205
|
+
".cjs": [".d.cts"]
|
|
206
|
+
},
|
|
207
|
+
...options.resolve
|
|
208
|
+
},
|
|
209
|
+
onLog(level, log, defaultHandler) {
|
|
210
|
+
if (level === "warn" && log.code === "CIRCULAR_DEPENDENCY") return;
|
|
211
|
+
if (onLog) onLog(level, log, defaultHandler);
|
|
212
|
+
else defaultHandler(level, log);
|
|
213
|
+
},
|
|
214
|
+
treeshake: {
|
|
215
|
+
moduleSideEffects: "no-external",
|
|
216
|
+
unknownGlobalSideEffects: false
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
},
|
|
220
|
+
outputOptions(options) {
|
|
221
|
+
return {
|
|
222
|
+
chunkFileNames: "[name]-[hash].d.ts",
|
|
223
|
+
entryFileNames: "[name].ts",
|
|
224
|
+
format: "es",
|
|
225
|
+
exports: "named",
|
|
226
|
+
...options
|
|
227
|
+
};
|
|
228
|
+
},
|
|
229
|
+
resolveId(id, importer) {
|
|
230
|
+
if (importer && !path.isAbsolute(id) && id[0] !== ".") return {
|
|
231
|
+
id,
|
|
232
|
+
external: true
|
|
233
|
+
};
|
|
234
|
+
},
|
|
235
|
+
async transform(code, id) {
|
|
236
|
+
const { program, comments } = await parseAsync(id, code);
|
|
237
|
+
const preserveComments = collectReferenceDirectives(comments);
|
|
238
|
+
commentMap.set(id, preserveComments);
|
|
239
|
+
const s = new MagicStringAST(code);
|
|
240
|
+
for (let node of program.body) {
|
|
241
|
+
if (rewriteImportExport(s, node)) continue;
|
|
242
|
+
const stmt = node;
|
|
243
|
+
const isDefaultExport = node.type === "ExportDefaultDeclaration";
|
|
244
|
+
if ((node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration") && node.declaration) node = node.declaration;
|
|
245
|
+
if (node.type === "VariableDeclaration" && node.declarations.length !== 1) throw new Error("Only one declaration is supported");
|
|
246
|
+
if (node.type === "TSDeclareFunction" || node.type.endsWith("Declaration")) {
|
|
247
|
+
const binding = node.type === "VariableDeclaration" ? node.declarations[0].id : node.id;
|
|
248
|
+
const code$1 = s.sliceNode(node);
|
|
249
|
+
const jsdoc = comments.find((c) => c.type === "Block" && c.value[0] === "*" && stmt.start - c.end <= 1);
|
|
250
|
+
const offset = node.start;
|
|
251
|
+
let bindingRange;
|
|
252
|
+
if (binding) bindingRange = getIdentifierRange(binding, -offset);
|
|
253
|
+
else if (isDefaultExport) {
|
|
254
|
+
const idx = s.sliceNode(node).indexOf("function") + 8;
|
|
255
|
+
bindingRange = [idx, idx];
|
|
256
|
+
} else continue;
|
|
257
|
+
const deps = collectDependencies(s, node);
|
|
258
|
+
const depsString = stringifyDependencies(s, deps);
|
|
259
|
+
const depsRanges = deps.map((dep) => [dep.start - offset, dep.end - offset]);
|
|
260
|
+
const needDeclare = (node.type === "TSEnumDeclaration" || node.type === "ClassDeclaration" || node.type === "FunctionDeclaration" || node.type === "TSDeclareFunction" || node.type === "TSModuleDeclaration" || node.type === "VariableDeclaration") && !node.declare;
|
|
261
|
+
const symbolId = register({
|
|
262
|
+
code: code$1,
|
|
263
|
+
binding: bindingRange,
|
|
264
|
+
deps: depsRanges,
|
|
265
|
+
needDeclare,
|
|
266
|
+
jsdoc: jsdoc ? s.sliceNode(jsdoc) : void 0
|
|
267
|
+
});
|
|
268
|
+
const runtime = `[${symbolId}, ${depsString}]`;
|
|
269
|
+
const bindingName = binding ? s.sliceNode(binding) : "export_default";
|
|
270
|
+
if (isDefaultExport) s.overwriteNode(stmt, `var ${bindingName} = ${runtime};export { ${bindingName} as default }`);
|
|
271
|
+
else s.overwriteNode(node, `var ${bindingName} = [${symbolId}, ${depsString}]`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (!s.hasChanged()) return;
|
|
275
|
+
const str = s.toString();
|
|
276
|
+
return str;
|
|
277
|
+
},
|
|
278
|
+
async renderChunk(code, chunk) {
|
|
279
|
+
const { program } = await parseAsync(chunk.fileName, code);
|
|
280
|
+
const s = new MagicStringAST(code);
|
|
281
|
+
const comments = new Set();
|
|
282
|
+
for (const id of chunk.moduleIds) {
|
|
283
|
+
const preserveComments = commentMap.get(id);
|
|
284
|
+
if (preserveComments) {
|
|
285
|
+
preserveComments.forEach((c) => comments.add(c));
|
|
286
|
+
commentMap.delete(id);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (comments.size) s.prepend(`${[...comments].join("\n")}\n`);
|
|
290
|
+
for (const node of program.body) {
|
|
291
|
+
if (patchImportSource(s, node)) continue;
|
|
292
|
+
if (node.type !== "VariableDeclaration" || node.declarations.length !== 1) continue;
|
|
293
|
+
const [decl] = node.declarations;
|
|
294
|
+
if (decl.init?.type !== "ArrayExpression" || !decl.init.elements[0]) {
|
|
295
|
+
patchVariableDeclarator(s, node, decl);
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
const [symbolIdNode, ...depsNodes] = decl.init.elements;
|
|
299
|
+
if (symbolIdNode?.type !== "Literal" || typeof symbolIdNode.value !== "number") {
|
|
300
|
+
patchVariableDeclarator(s, node, decl);
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
const symbolId = symbolIdNode.value;
|
|
304
|
+
const { code: code$1, binding, deps, needDeclare, jsdoc } = retrieve(symbolId);
|
|
305
|
+
const depsRaw = depsNodes.map((dep) => {
|
|
306
|
+
if (dep.type !== "ArrowFunctionExpression") throw new Error("Expected ArrowFunctionExpression");
|
|
307
|
+
return s.sliceNode(dep.body);
|
|
308
|
+
});
|
|
309
|
+
const ss = new MagicStringAST(code$1);
|
|
310
|
+
overwriteOrAppend(ss, binding, s.sliceNode(decl.id));
|
|
311
|
+
for (const dep of deps) overwriteOrAppend(ss, dep, depsRaw.shift());
|
|
312
|
+
if (needDeclare) ss.prepend("declare ");
|
|
313
|
+
if (jsdoc) ss.prepend(`${jsdoc}\n`);
|
|
314
|
+
s.overwriteNode(node, ss.toString());
|
|
315
|
+
}
|
|
316
|
+
const str = s.toString();
|
|
317
|
+
if (str.trim().length === 0) return "export {}";
|
|
318
|
+
return str;
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
const REFERENCE_RE = /\/\s*<reference\s+(?:path|types)=/;
|
|
323
|
+
function collectReferenceDirectives(comment) {
|
|
324
|
+
return comment.filter((c) => REFERENCE_RE.test(c.value)).map((c) => `//${c.value}`);
|
|
325
|
+
}
|
|
326
|
+
function collectDependencies(s, node) {
|
|
327
|
+
const deps = new Set();
|
|
328
|
+
walk(node, { leave(node$1) {
|
|
329
|
+
if (node$1.type === "TSInterfaceDeclaration" && node$1.extends) for (const heritage of node$1.extends || []) addDependency(heritage.expression);
|
|
330
|
+
else if (node$1.type === "ClassDeclaration") {
|
|
331
|
+
if (node$1.superClass) addDependency(node$1.superClass);
|
|
332
|
+
if (node$1.implements) for (const implement of node$1.implements) addDependency(implement.expression);
|
|
333
|
+
} else if (node$1.type === "MethodDefinition" || node$1.type === "PropertyDefinition" || node$1.type === "TSPropertySignature") {
|
|
334
|
+
if (node$1.computed && isReferenceId(node$1.key)) addDependency(node$1.key);
|
|
335
|
+
if ("value" in node$1 && isReferenceId(node$1.value)) addDependency(node$1.value);
|
|
336
|
+
} else if (node$1.type === "TSTypeReference") addDependency(node$1.typeName);
|
|
337
|
+
else if (node$1.type === "TSTypeQuery") addDependency(node$1.exprName);
|
|
338
|
+
else if (node$1.type === "TSImportType") {
|
|
339
|
+
if (node$1.argument.type !== "TSLiteralType" || node$1.argument.literal.type !== "Literal" || typeof node$1.argument.literal.value !== "string") return;
|
|
340
|
+
if (!node$1.qualifier) throw new Error("Import namespace is not supported");
|
|
341
|
+
const source = node$1.argument.literal.value;
|
|
342
|
+
const imported = s.sliceNode(node$1.qualifier);
|
|
343
|
+
const local = importNamespace(s, source, imported);
|
|
344
|
+
addDependency({
|
|
345
|
+
type: "Identifier",
|
|
346
|
+
name: local,
|
|
347
|
+
start: node$1.start + (node$1.isTypeOf ? 7 : 0),
|
|
348
|
+
end: node$1.qualifier.end
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
} });
|
|
352
|
+
return Array.from(deps);
|
|
353
|
+
function addDependency(node$1) {
|
|
354
|
+
if (node$1.type === "Identifier" && node$1.name === "this") return;
|
|
355
|
+
deps.add(node$1);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
function isReferenceId(node) {
|
|
359
|
+
return !!node && (node.type === "Identifier" || node.type === "MemberExpression");
|
|
360
|
+
}
|
|
361
|
+
function stringifyDependencies(s, deps) {
|
|
362
|
+
return deps.map((node) => `() => ${node.type === "Identifier" ? node.name : s.sliceNode(node)}`).join(", ");
|
|
363
|
+
}
|
|
364
|
+
function patchVariableDeclarator(s, node, decl) {
|
|
365
|
+
if (decl.init && !decl.id.typeAnnotation) s.overwriteNode(node, `type ${s.sliceNode(decl.id)} = ${s.sliceNode(decl.init)}`);
|
|
366
|
+
else if (!node.declare) s.prependLeft(node.start, "declare ");
|
|
367
|
+
}
|
|
368
|
+
const RE_D_TS = /\.d\.([cm]?)ts$/;
|
|
369
|
+
function patchImportSource(s, node) {
|
|
370
|
+
if ((node.type === "ImportDeclaration" || node.type === "ExportAllDeclaration" || node.type === "ExportNamedDeclaration") && node.source?.value && RE_D_TS.test(node.source.value)) {
|
|
371
|
+
s.overwriteNode(node.source, JSON.stringify(node.source.value.replace(RE_D_TS, ".$1js")));
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
function rewriteImportExport(s, node) {
|
|
376
|
+
if (node.type === "ImportDeclaration" || node.type === "ExportNamedDeclaration" && !node.declaration) {
|
|
377
|
+
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, ""));
|
|
378
|
+
const firstSpecifier = node.specifiers[0];
|
|
379
|
+
const kind = node.type === "ImportDeclaration" ? node.importKind : node.exportKind;
|
|
380
|
+
if (kind === "type" && firstSpecifier) s.overwrite(node.start, firstSpecifier.start, s.slice(node.start, firstSpecifier.start).replace(RE_TYPE, ""));
|
|
381
|
+
return true;
|
|
382
|
+
} else if (node.type === "ExportAllDeclaration") {
|
|
383
|
+
if (node.exportKind === "type") s.overwrite(node.start, node.source.start, s.slice(node.start, node.source.start).replace(RE_TYPE, ""));
|
|
384
|
+
return true;
|
|
385
|
+
} else if (node.type === "TSImportEqualsDeclaration") {
|
|
386
|
+
if (node.moduleReference.type === "TSExternalModuleReference") s.overwriteNode(node, `import ${s.sliceNode(node.id)} from ${s.sliceNode(node.moduleReference.expression)}`);
|
|
387
|
+
return true;
|
|
388
|
+
} else if (node.type === "TSExportAssignment") {
|
|
389
|
+
s.overwriteNode(node, `export default ${s.sliceNode(node.expression)}`);
|
|
390
|
+
return true;
|
|
391
|
+
} else if (node.type === "ExportDefaultDeclaration" && node.declaration.type === "Identifier") {
|
|
392
|
+
s.overwriteNode(node, `export { ${s.sliceNode(node.declaration)} as default }`);
|
|
393
|
+
return true;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
let i = 0;
|
|
397
|
+
function importNamespace(s, source, imported) {
|
|
398
|
+
const local = `_${i++}`;
|
|
399
|
+
s.prepend(`import { ${imported} as ${local} } from ${JSON.stringify(source)};\n`);
|
|
400
|
+
return local;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
//#endregion
|
|
404
|
+
export { dts };
|
package/package.json
CHANGED
|
@@ -1,12 +1,66 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rolldown-plugin-dts",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A Rolldown plugin to bundle dts files",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://github.com/sxzz/rolldown-plugin-dts#readme",
|
|
8
|
+
"bugs": {
|
|
9
|
+
"url": "https://github.com/sxzz/rolldown-plugin-dts/issues"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/sxzz/rolldown-plugin-dts.git"
|
|
14
|
+
},
|
|
15
|
+
"author": "三咲智子 Kevin Deng <sxzz@sxzz.moe>",
|
|
16
|
+
"funding": "https://github.com/sponsors/sxzz",
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"main": "./dist/index.js",
|
|
21
|
+
"module": "./dist/index.js",
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": "./dist/index.js",
|
|
25
|
+
"./package.json": "./package.json"
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"magic-string-ast": "^0.9.1",
|
|
32
|
+
"oxc-parser": "^0.62.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@sxzz/eslint-config": "^6.1.1",
|
|
36
|
+
"@sxzz/prettier-config": "^2.2.1",
|
|
37
|
+
"@sxzz/test-utils": "^0.5.4",
|
|
38
|
+
"@types/diff": "^7.0.2",
|
|
39
|
+
"@types/node": "^22.13.17",
|
|
40
|
+
"bumpp": "^10.1.0",
|
|
41
|
+
"diff": "^7.0.0",
|
|
42
|
+
"eslint": "^9.23.0",
|
|
43
|
+
"estree-walker": "^3.0.3",
|
|
44
|
+
"prettier": "^3.5.3",
|
|
45
|
+
"rolldown": "1.0.0-beta.7",
|
|
46
|
+
"rollup-plugin-dts": "^6.2.1",
|
|
47
|
+
"tsdown": "^0.7.3",
|
|
48
|
+
"tsx": "^4.19.3",
|
|
49
|
+
"typescript": "^5.8.2",
|
|
50
|
+
"vitest": "^3.1.1"
|
|
51
|
+
},
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=20.18.0"
|
|
54
|
+
},
|
|
55
|
+
"prettier": "@sxzz/prettier-config",
|
|
9
56
|
"scripts": {
|
|
10
|
-
"
|
|
57
|
+
"lint": "eslint --cache .",
|
|
58
|
+
"lint:fix": "pnpm run lint --fix",
|
|
59
|
+
"build": "tsdown",
|
|
60
|
+
"dev": "tsdown --watch",
|
|
61
|
+
"test": "vitest",
|
|
62
|
+
"typecheck": "tsc --noEmit",
|
|
63
|
+
"format": "prettier --cache --write .",
|
|
64
|
+
"release": "bumpp && pnpm publish"
|
|
11
65
|
}
|
|
12
66
|
}
|