rolldown-plugin-dts 0.1.0 → 0.3.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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Unit Test](https://github.com/sxzz/rolldown-plugin-dts/actions/workflows/unit-test.yml/badge.svg)](https://github.com/sxzz/rolldown-plugin-dts/actions/workflows/unit-test.yml)
4
4
 
5
- A Rolldown plugin to bundle dts files.
5
+ A Rolldown plugin to generate and bundle dts files.
6
6
 
7
7
  ## Install
8
8
 
@@ -18,24 +18,53 @@ Add the plugin to your `rolldown.config.js`:
18
18
  // rolldown.config.js
19
19
  import { dts } from 'rolldown-plugin-dts'
20
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
21
+ export default {
22
+ input: './src/index.ts',
23
+ plugins: [dts()],
24
+ output: [{ dir: 'dist', format: 'es' }],
25
+ }
35
26
  ```
36
27
 
37
- > [!NOTE]
38
- > Namespaces are not supported yet.
28
+ You can find a real demo in [here](./rolldown.config.ts).
29
+
30
+ ## Options
31
+
32
+ ````ts
33
+ interface Options {
34
+ /**
35
+ * When entries are `.d.ts` files (instead of `.ts` files), this option should be set to `true`.
36
+ *
37
+ * If enabled, the plugin will skip generating a `.d.ts` file for the entry point.
38
+ */
39
+ dtsInput?: boolean
40
+
41
+ isolatedDeclaration?: Omit<IsolatedDeclarationsOptions, 'sourcemap'>
42
+
43
+ /**
44
+ * dts file name alias `{ [filename]: path }`
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * inputAlias: {
49
+ * 'foo.d.ts': 'foo/index.d.ts',
50
+ * }
51
+ */
52
+ inputAlias?: Record<string, string>
53
+
54
+ /** Resolve external types used in dts files from `node_modules` */
55
+ resolve?: boolean | (string | RegExp)[]
56
+ }
57
+ ````
58
+
59
+ ## Caveats
60
+
61
+ - The plugin uses Oxc's `isolatedDeclarations` to generate `.d.ts` files,
62
+ which means you need to set `isolatedDeclarations: true` in your `tsconfig.json` and ensure there are no errors.
63
+
64
+ - Namespaces are not supported yet.
65
+ - `export * as ns from './ns'`
66
+ - `import * as ns from './ns'` and then `export { ns }`
67
+ - `type ns = import('./ns')`
39
68
 
40
69
  ## Credits
41
70
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,37 @@
1
+ import { IsolatedDeclarationsOptions } from "oxc-transform";
1
2
  import { Plugin } from "rolldown";
2
3
 
3
- //#region dist/.tsdown-types-es/index.d.ts
4
- declare function dts(): Plugin;
4
+ //#region src/fake-js.d.ts
5
+ declare function createFakeJsPlugin({ dtsInput }: Pick<Options, "dtsInput">): Plugin;
5
6
 
6
7
  //#endregion
7
- export { dts };
8
+ //#region src/generate.d.ts
9
+ declare function createGeneratePlugin({ isolatedDeclaration, inputAlias, resolve }: Pick<Options, "isolatedDeclaration" | "inputAlias" | "resolve">): Plugin;
10
+
11
+ //#endregion
12
+ //#region src/index.d.ts
13
+ interface Options {
14
+ /**
15
+ * When entries are `.d.ts` files (instead of `.ts` files), this option should be set to `true`.
16
+ *
17
+ * If enabled, the plugin will skip generating a `.d.ts` file for the entry point.
18
+ */
19
+ dtsInput?: boolean;
20
+ isolatedDeclaration?: Omit<IsolatedDeclarationsOptions, "sourcemap">;
21
+ /**
22
+ * dts file name alias `{ [filename]: path }`
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * inputAlias: {
27
+ * 'foo.d.ts': 'foo/index.d.ts',
28
+ * }
29
+ */
30
+ inputAlias?: Record<string, string>;
31
+ /** Resolve external types used in dts files from `node_modules` */
32
+ resolve?: boolean | (string | RegExp)[];
33
+ }
34
+ declare function dts(options?: Options): Plugin[];
35
+
36
+ //#endregion
37
+ export { Options, createFakeJsPlugin, createGeneratePlugin, dts };
package/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
- import path from "node:path";
2
1
  import { MagicStringAST } from "magic-string-ast";
3
2
  import { parseAsync } from "oxc-parser";
3
+ import path, { basename } from "node:path";
4
+ import { createResolver } from "dts-resolver";
5
+ import { isolatedDeclaration } from "oxc-transform";
4
6
 
5
7
  //#region node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/walker.js
6
8
  var WalkerBase = class {
@@ -110,10 +112,10 @@ var SyncWalker = class extends WalkerBase {
110
112
  if (value && typeof value === "object") {
111
113
  if (Array.isArray(value)) {
112
114
  const nodes = value;
113
- for (let i$1 = 0; i$1 < nodes.length; i$1 += 1) {
114
- const item = nodes[i$1];
115
+ for (let i = 0; i < nodes.length; i += 1) {
116
+ const item = nodes[i];
115
117
  if (isNode(item)) {
116
- if (!this.visit(item, node, key, i$1)) i$1--;
118
+ if (!this.visit(item, node, key, i)) i--;
117
119
  }
118
120
  }
119
121
  } else if (isNode(value)) this.visit(value, node, key, null);
@@ -163,25 +165,49 @@ function getIdentifierRange(node, offset = 0) {
163
165
  return [node.start + offset, node.end + offset];
164
166
  }
165
167
 
168
+ //#endregion
169
+ //#region src/utils/filename.ts
170
+ const RE_JS = /\.([cm]?)js$/;
171
+ const RE_TS = /\.([cm]?)ts$/;
172
+ const RE_DTS = /\.d\.([cm]?)ts$/;
173
+ const RE_NODE_MODULES = /node_modules/;
174
+ function filename_js_to_dts(id) {
175
+ return id.replace(RE_JS, ".d.$1ts");
176
+ }
177
+ function filename_ts_to_dts(id) {
178
+ return id.replace(RE_TS, ".d.$1ts");
179
+ }
180
+ function filename_dts_to(id, ext) {
181
+ return id.replace(RE_DTS, `.$1${ext}`);
182
+ }
183
+ function isRelative(id) {
184
+ return path.isAbsolute(id) || id[0] === ".";
185
+ }
186
+
166
187
  //#endregion
167
188
  //#region src/utils/magic-string.ts
168
- function overwriteOrAppend(s, range, replacement) {
189
+ function overwriteOrAppend(s, range, replacement, suffix) {
169
190
  if (range[0] === range[1]) {
170
191
  s.appendLeft(range[0], ` ${replacement}`);
171
192
  return;
172
193
  }
173
- s.overwrite(range[0], range[1], replacement);
194
+ const original = s.slice(range[0], range[1]);
195
+ if (original !== replacement) s.overwrite(range[0], range[1], replacement + (suffix || ""));
174
196
  }
175
197
 
176
198
  //#endregion
177
- //#region src/index.ts
199
+ //#region src/fake-js.ts
178
200
  const RE_TYPE = /\btype\b/;
179
- function dts() {
180
- let i$1 = 0;
201
+ function createFakeJsPlugin({ dtsInput }) {
202
+ let symbolIdx = 0;
203
+ let identifierIdx = 0;
181
204
  const symbolMap = new Map();
182
- const commentMap = new Map();
205
+ const preserveMap = new Map();
206
+ function getIdentifierIndex() {
207
+ return identifierIdx++;
208
+ }
183
209
  function register(info) {
184
- const symbolId = i$1++;
210
+ const symbolId = symbolIdx++;
185
211
  symbolMap.set(symbolId, info);
186
212
  return symbolId;
187
213
  }
@@ -189,8 +215,8 @@ function dts() {
189
215
  return symbolMap.get(symbolId);
190
216
  }
191
217
  return {
192
- name: "rolldown-plugin-dts",
193
- options({ onLog,...options }) {
218
+ name: "rolldown-plugin-dts:fake-js",
219
+ options: dtsInput ? (options) => {
194
220
  return {
195
221
  ...options,
196
222
  resolve: {
@@ -205,85 +231,85 @@ function dts() {
205
231
  ".cjs": [".d.cts"]
206
232
  },
207
233
  ...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
234
  }
218
235
  };
219
- },
236
+ } : void 0,
220
237
  outputOptions(options) {
238
+ if (options.format === "cjs" || options.format === "commonjs") throw new Error("[rolldown-plugin-dts] Cannot bundle dts files with `cjs` format.");
221
239
  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
240
+ ...options,
241
+ entryFileNames: options.entryFileNames ?? (dtsInput ? "[name].ts" : void 0),
242
+ chunkFileNames(chunk) {
243
+ const original = (typeof options.chunkFileNames === "function" ? options.chunkFileNames(chunk) : options.chunkFileNames) || "[name]-[hash].js";
244
+ if (chunk.name.endsWith(".d")) return filename_js_to_dts(original);
245
+ return original;
246
+ }
233
247
  };
234
248
  },
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}]`);
249
+ transform: {
250
+ filter: { id: RE_DTS },
251
+ async handler(code, id) {
252
+ const { program, comments } = await parseAsync(id, code);
253
+ const preserved = collectReferenceDirectives(comments);
254
+ preserveMap.set(id, preserved);
255
+ const s = new MagicStringAST(code);
256
+ for (let node of program.body) {
257
+ if (node.type === "ExportAllDeclaration" && node.exported && isRelative(node.source.value)) throw new Error("`export * as foo from './...'` is not supported");
258
+ if (rewriteImportExport(s, node)) continue;
259
+ const sideEffect = node.type === "TSModuleDeclaration" && node.kind !== "namespace";
260
+ const stmt = node;
261
+ const isDefaultExport = node.type === "ExportDefaultDeclaration";
262
+ if ((node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration") && node.declaration) node = node.declaration;
263
+ if (node.type === "VariableDeclaration" && node.declarations.length !== 1) throw new Error("Only one declaration is supported");
264
+ if (node.type === "TSDeclareFunction" || node.type.endsWith("Declaration")) {
265
+ const binding = node.type === "VariableDeclaration" ? node.declarations[0].id : node.id;
266
+ const code$1 = s.sliceNode(node);
267
+ const jsdoc = comments.find((c) => c.type === "Block" && c.value[0] === "*" && c.start < node.start && stmt.start - c.end <= 1);
268
+ const offset = node.start;
269
+ let bindingRange;
270
+ if (sideEffect) bindingRange = [0, 0];
271
+ else if (binding) bindingRange = getIdentifierRange(binding, -offset);
272
+ else if (isDefaultExport) {
273
+ const idx = s.sliceNode(node).indexOf("function") + 8;
274
+ bindingRange = [idx, idx];
275
+ } else continue;
276
+ const depsNodes = collectDependencies(s, node, getIdentifierIndex);
277
+ const depsString = stringifyDependencies(s, depsNodes);
278
+ const depsSymbols = depsNodes.map((dep) => [
279
+ dep.start - offset,
280
+ dep.end - offset,
281
+ dep._suffix
282
+ ]);
283
+ const needDeclare = (node.type === "TSEnumDeclaration" || node.type === "ClassDeclaration" || node.type === "FunctionDeclaration" || node.type === "TSDeclareFunction" || node.type === "TSModuleDeclaration" || node.type === "VariableDeclaration") && !node.declare;
284
+ const symbolId = register({
285
+ code: code$1,
286
+ binding: bindingRange,
287
+ deps: depsSymbols,
288
+ needDeclare,
289
+ jsdoc: jsdoc ? s.sliceNode(jsdoc) : void 0,
290
+ preserveName: sideEffect
291
+ });
292
+ const runtime = `[${symbolId}, ${depsString}${depsString && sideEffect ? ", " : ""}${sideEffect ? "sideEffect()" : ""}]`;
293
+ const bindingName = sideEffect ? `_${identifierIdx++}` : binding ? s.sliceNode(binding) : "export_default";
294
+ if (isDefaultExport) s.overwriteNode(stmt, `var ${bindingName} = ${runtime};export { ${bindingName} as default }`);
295
+ else s.overwriteNode(node, `var ${bindingName} = ${runtime};`);
296
+ }
272
297
  }
298
+ if (!s.hasChanged()) return;
299
+ const str = s.toString();
300
+ return str;
273
301
  }
274
- if (!s.hasChanged()) return;
275
- const str = s.toString();
276
- return str;
277
302
  },
278
303
  async renderChunk(code, chunk) {
304
+ if (!RE_DTS.test(chunk.fileName)) return;
279
305
  const { program } = await parseAsync(chunk.fileName, code);
280
306
  const s = new MagicStringAST(code);
281
307
  const comments = new Set();
282
308
  for (const id of chunk.moduleIds) {
283
- const preserveComments = commentMap.get(id);
309
+ const preserveComments = preserveMap.get(id);
284
310
  if (preserveComments) {
285
311
  preserveComments.forEach((c) => comments.add(c));
286
- commentMap.delete(id);
312
+ preserveMap.delete(id);
287
313
  }
288
314
  }
289
315
  if (comments.size) s.prepend(`${[...comments].join("\n")}\n`);
@@ -301,14 +327,14 @@ function dts() {
301
327
  continue;
302
328
  }
303
329
  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
- });
330
+ const { code: code$1, binding, deps, needDeclare, jsdoc, preserveName } = retrieve(symbolId);
331
+ const depsRaw = depsNodes.filter((node$1) => node$1?.type === "ArrowFunctionExpression").map((dep) => s.sliceNode(dep.body));
309
332
  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());
333
+ if (!preserveName) overwriteOrAppend(ss, binding, s.sliceNode(decl.id));
334
+ for (const dep of deps) {
335
+ const [start, end, suffix] = dep;
336
+ overwriteOrAppend(ss, [start, end], depsRaw.shift(), suffix);
337
+ }
312
338
  if (needDeclare) ss.prepend("declare ");
313
339
  if (jsdoc) ss.prepend(`${jsdoc}\n`);
314
340
  s.overwriteNode(node, ss.toString());
@@ -323,10 +349,19 @@ const REFERENCE_RE = /\/\s*<reference\s+(?:path|types)=/;
323
349
  function collectReferenceDirectives(comment) {
324
350
  return comment.filter((c) => REFERENCE_RE.test(c.value)).map((c) => `//${c.value}`);
325
351
  }
326
- function collectDependencies(s, node) {
352
+ function collectDependencies(s, node, getIdentifierIndex) {
327
353
  const deps = new Set();
328
354
  walk(node, { leave(node$1) {
329
- if (node$1.type === "TSInterfaceDeclaration" && node$1.extends) for (const heritage of node$1.extends || []) addDependency(heritage.expression);
355
+ if (node$1.type === "ExportNamedDeclaration") {
356
+ for (const specifier of node$1.specifiers) if (specifier.type === "ExportSpecifier") {
357
+ let _suffix;
358
+ if (specifier.local.start === specifier.exported.start && specifier.local.end === specifier.exported.end) _suffix = ` as ${s.sliceNode(specifier.local)}`;
359
+ addDependency({
360
+ ...specifier.local,
361
+ _suffix
362
+ });
363
+ }
364
+ } else if (node$1.type === "TSInterfaceDeclaration" && node$1.extends) for (const heritage of node$1.extends || []) addDependency(heritage.expression);
330
365
  else if (node$1.type === "ClassDeclaration") {
331
366
  if (node$1.superClass) addDependency(node$1.superClass);
332
367
  if (node$1.implements) for (const implement of node$1.implements) addDependency(implement.expression);
@@ -340,7 +375,7 @@ function collectDependencies(s, node) {
340
375
  if (!node$1.qualifier) throw new Error("Import namespace is not supported");
341
376
  const source = node$1.argument.literal.value;
342
377
  const imported = s.sliceNode(node$1.qualifier);
343
- const local = importNamespace(s, source, imported);
378
+ const local = importNamespace(s, source, imported, getIdentifierIndex);
344
379
  addDependency({
345
380
  type: "Identifier",
346
381
  name: local,
@@ -365,10 +400,9 @@ function patchVariableDeclarator(s, node, decl) {
365
400
  if (decl.init && !decl.id.typeAnnotation) s.overwriteNode(node, `type ${s.sliceNode(decl.id)} = ${s.sliceNode(decl.init)}`);
366
401
  else if (!node.declare) s.prependLeft(node.start, "declare ");
367
402
  }
368
- const RE_D_TS = /\.d\.([cm]?)ts$/;
369
403
  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")));
404
+ if ((node.type === "ImportDeclaration" || node.type === "ExportAllDeclaration" || node.type === "ExportNamedDeclaration") && node.source?.value && RE_DTS.test(node.source.value)) {
405
+ s.overwriteNode(node.source, JSON.stringify(filename_dts_to(node.source.value, "js")));
372
406
  return true;
373
407
  }
374
408
  }
@@ -393,12 +427,123 @@ function rewriteImportExport(s, node) {
393
427
  return true;
394
428
  }
395
429
  }
396
- let i = 0;
397
- function importNamespace(s, source, imported) {
398
- const local = `_${i++}`;
430
+ function importNamespace(s, source, imported, getIdentifierIndex) {
431
+ const local = `_${getIdentifierIndex()}`;
399
432
  s.prepend(`import { ${imported} as ${local} } from ${JSON.stringify(source)};\n`);
400
433
  return local;
401
434
  }
402
435
 
403
436
  //#endregion
404
- export { dts };
437
+ //#region src/generate.ts
438
+ const meta = { dtsFile: true };
439
+ function createGeneratePlugin({ isolatedDeclaration: isolatedDeclaration$1, inputAlias = {}, resolve = false }) {
440
+ const dtsMap = new Map();
441
+ const inputAliasMap = new Map(Object.entries(inputAlias));
442
+ const resolver = createResolver();
443
+ let inputOption;
444
+ return {
445
+ name: "rolldown-plugin-dts:generate",
446
+ options({ input }) {
447
+ if (isPlainObject(input)) inputOption = { ...input };
448
+ },
449
+ transform: {
450
+ order: "pre",
451
+ filter: { id: {
452
+ include: [RE_TS],
453
+ exclude: [RE_DTS, RE_NODE_MODULES]
454
+ } },
455
+ handler(code, id) {
456
+ const { code: dtsCode, errors } = isolatedDeclaration(id, code, isolatedDeclaration$1);
457
+ if (errors.length) return this.error(errors[0]);
458
+ const dtsId = filename_ts_to_dts(id);
459
+ dtsMap.set(dtsId, dtsCode);
460
+ const mod = this.getModuleInfo(id);
461
+ if (mod?.isEntry) {
462
+ let fileName = basename(dtsId);
463
+ if (inputAliasMap.has(fileName)) fileName = inputAliasMap.get(fileName);
464
+ else if (inputAliasMap.has(dtsId)) fileName = inputAliasMap.get(dtsId);
465
+ this.emitFile({
466
+ type: "chunk",
467
+ id: dtsId,
468
+ fileName
469
+ });
470
+ }
471
+ }
472
+ },
473
+ async resolveId(id, importer, extraOptions) {
474
+ if (dtsMap.has(id)) return {
475
+ id,
476
+ meta
477
+ };
478
+ if (importer && this.getModuleInfo(importer)?.meta.dtsFile) {
479
+ if (!isRelative(id)) {
480
+ let shouldResolve;
481
+ if (typeof resolve === "boolean") shouldResolve = resolve;
482
+ else shouldResolve = resolve.some((pattern) => typeof pattern === "string" ? id === pattern : pattern.test(id));
483
+ if (shouldResolve) {
484
+ const resolution$1 = resolver(id, importer);
485
+ if (resolution$1) return {
486
+ id: resolution$1,
487
+ meta
488
+ };
489
+ } else return {
490
+ id,
491
+ external: true,
492
+ meta
493
+ };
494
+ }
495
+ const resolution = await this.resolve(id, filename_dts_to(importer, "ts"));
496
+ if (!resolution || resolution.external) return;
497
+ const dtsId = filename_ts_to_dts(resolution.id);
498
+ if (dtsMap.has(dtsId)) return {
499
+ id: dtsId,
500
+ meta
501
+ };
502
+ await this.load(resolution);
503
+ if (dtsMap.has(dtsId)) return {
504
+ id: dtsId,
505
+ meta
506
+ };
507
+ } else if (extraOptions.isEntry && inputOption) {
508
+ const resolution = await this.resolve(id, importer, extraOptions);
509
+ if (!resolution) return;
510
+ const dtsId = filename_ts_to_dts(resolution.id);
511
+ if (inputAliasMap.has(dtsId)) return resolution;
512
+ for (const [name, entry] of Object.entries(inputOption)) if (entry === id) {
513
+ inputAliasMap.set(dtsId, `${name}.d.ts`);
514
+ break;
515
+ }
516
+ return resolution;
517
+ }
518
+ },
519
+ load: {
520
+ filter: { id: {
521
+ include: [RE_DTS],
522
+ exclude: [RE_NODE_MODULES]
523
+ } },
524
+ handler(id) {
525
+ if (dtsMap.has(id)) return {
526
+ code: dtsMap.get(id),
527
+ moduleSideEffects: false
528
+ };
529
+ }
530
+ }
531
+ };
532
+ }
533
+ function isPlainObject(data) {
534
+ if (typeof data !== "object" || data === null) return false;
535
+ const proto = Object.getPrototypeOf(data);
536
+ return proto === null || proto === Object.prototype;
537
+ }
538
+
539
+ //#endregion
540
+ //#region src/index.ts
541
+ function dts(options = {}) {
542
+ const plugins = [];
543
+ if (!options.dtsInput) plugins.push(createGeneratePlugin(options));
544
+ plugins.push(createFakeJsPlugin(options));
545
+ return plugins;
546
+ }
547
+
548
+ //#endregion
549
+ export { createFakeJsPlugin, createGeneratePlugin, dts };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rolldown-plugin-dts",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "A Rolldown plugin to bundle dts files",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -27,26 +27,31 @@
27
27
  "publishConfig": {
28
28
  "access": "public"
29
29
  },
30
+ "peerDependencies": {
31
+ "rolldown": "^1.0.0-beta.7"
32
+ },
30
33
  "dependencies": {
34
+ "dts-resolver": "^0.1.0",
31
35
  "magic-string-ast": "^0.9.1",
32
- "oxc-parser": "^0.62.0"
36
+ "oxc-parser": "^0.62.0",
37
+ "oxc-transform": "^0.62.0"
33
38
  },
34
39
  "devDependencies": {
35
40
  "@sxzz/eslint-config": "^6.1.1",
36
41
  "@sxzz/prettier-config": "^2.2.1",
37
42
  "@sxzz/test-utils": "^0.5.4",
38
43
  "@types/diff": "^7.0.2",
39
- "@types/node": "^22.13.17",
44
+ "@types/node": "^22.14.0",
40
45
  "bumpp": "^10.1.0",
41
46
  "diff": "^7.0.0",
42
- "eslint": "^9.23.0",
47
+ "eslint": "^9.24.0",
43
48
  "estree-walker": "^3.0.3",
44
49
  "prettier": "^3.5.3",
45
- "rolldown": "1.0.0-beta.7",
50
+ "rolldown": "^1.0.0-beta.7",
46
51
  "rollup-plugin-dts": "^6.2.1",
47
- "tsdown": "^0.7.3",
52
+ "tsdown": "^0.8.0-beta.1",
48
53
  "tsx": "^4.19.3",
49
- "typescript": "^5.8.2",
54
+ "typescript": "^5.8.3",
50
55
  "vitest": "^3.1.1"
51
56
  },
52
57
  "engines": {