rolldown-plugin-dts 0.15.9 → 0.16.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
@@ -83,10 +83,13 @@ If `true`, the plugin will generate declaration maps (`.d.ts.map`) for `.d.ts` f
83
83
 
84
84
  #### `resolve`
85
85
 
86
- Resolve external types used in `.d.ts` files from `node_modules`.
86
+ Controls whether type definitions from `node_modules` are bundled into your final `.d.ts` file or kept as external `import` statements.
87
87
 
88
- - If `true`, all external types are resolved.
89
- - If an array, only types matching the provided strings or regular expressions are resolved.
88
+ By default, dependencies are external, resulting in `import { Type } from 'some-package'`. When bundled, this `import` is removed, and the type definitions from `some-package` are copied directly into your file.
89
+
90
+ - `true`: Bundles all dependencies.
91
+ - `false`: (Default) Keeps all dependencies external.
92
+ - `(string | RegExp)[]`: Bundles only dependencies matching the provided strings or regular expressions (e.g. `['pkg-a', /^@scope\//]`).
90
93
 
91
94
  #### `cjsDefault`
92
95
 
@@ -1,12 +1,18 @@
1
1
  import ts from "typescript";
2
2
 
3
3
  //#region src/tsc/context.d.ts
4
+ interface ParsedProject {
5
+ tsconfigPath: string;
6
+ parsedConfig: ts.ParsedCommandLine;
7
+ }
8
+ type SourceFileToProjectMap = Map<string, ParsedProject>;
4
9
  interface TscContext {
5
10
  programs: ts.Program[];
6
11
  files: Map<string, string>;
12
+ projects: Map<string, SourceFileToProjectMap>;
7
13
  }
8
14
  declare function createContext(): TscContext;
9
15
  declare function invalidateContextFile(context: TscContext, file: string): void;
10
16
  declare const globalContext: TscContext;
11
17
  //#endregion
12
- export { TscContext, createContext, globalContext, invalidateContextFile };
18
+ export { ParsedProject, SourceFileToProjectMap, TscContext, createContext, globalContext, invalidateContextFile };
@@ -5,9 +5,11 @@ const debug = Debug("rolldown-plugin-dts:tsc-context");
5
5
  function createContext() {
6
6
  const programs = [];
7
7
  const files = /* @__PURE__ */ new Map();
8
+ const projects = /* @__PURE__ */ new Map();
8
9
  return {
9
10
  programs,
10
- files
11
+ files,
12
+ projects
11
13
  };
12
14
  }
13
15
  function invalidateContextFile(context, file) {
@@ -16,6 +18,7 @@ function invalidateContextFile(context, file) {
16
18
  context.programs = context.programs.filter((program) => {
17
19
  return !program.getSourceFiles().some((sourceFile) => sourceFile.fileName === file);
18
20
  });
21
+ context.projects.clear();
19
22
  }
20
23
  const globalContext = createContext();
21
24
 
@@ -1,9 +1,9 @@
1
- import { TscContext } from "./context-DIRjVfC4.js";
1
+ import { TscContext } from "./context-DXNtAHtR.js";
2
2
  import { TsConfigJson } from "get-tsconfig";
3
3
  import ts from "typescript";
4
4
  import { SourceMapInput } from "rolldown";
5
5
 
6
- //#region src/tsc/index.d.ts
6
+ //#region src/tsc/types.d.ts
7
7
  interface TscModule {
8
8
  program: ts.Program;
9
9
  file: ts.SourceFile;
@@ -16,6 +16,7 @@ interface TscOptions {
16
16
  incremental: boolean;
17
17
  entries?: string[];
18
18
  id: string;
19
+ sourcemap: boolean;
19
20
  vue?: boolean;
20
21
  context?: TscContext;
21
22
  }
@@ -24,6 +25,8 @@ interface TscResult {
24
25
  map?: SourceMapInput;
25
26
  error?: string;
26
27
  }
28
+ //#endregion
29
+ //#region src/tsc/index.d.ts
27
30
  declare function tscEmit(tscOptions: TscOptions): TscResult;
28
31
  //#endregion
29
- export { TscModule, TscOptions, TscResult, tscEmit };
32
+ export { type TscModule, type TscOptions, type TscResult, tscEmit };
package/dist/index.d.ts CHANGED
@@ -47,7 +47,13 @@ interface GeneralOptions {
47
47
  */
48
48
  sourcemap?: boolean;
49
49
  /**
50
- * Resolve external types used in `.d.ts` files from `node_modules`.
50
+ * Controls whether type definitions from `node_modules` are bundled into your final `.d.ts` file or kept as external `import` statements.
51
+ *
52
+ * By default, dependencies are external, resulting in `import { Type } from 'some-package'`. When bundled, this `import` is removed, and the type definitions from `some-package` are copied directly into your file.
53
+
54
+ * - `true`: Bundles all dependencies.
55
+ * - `false`: (Default) Keeps all dependencies external.
56
+ * - `(string | RegExp)[]`: Bundles only dependencies matching the provided strings or regular expressions (e.g. `['pkg-a', /^@scope\//]`).
51
57
  */
52
58
  resolve?: boolean | (string | RegExp)[];
53
59
  /**
@@ -200,8 +206,9 @@ declare function createGeneratePlugin({
200
206
  eager,
201
207
  tsgo,
202
208
  newContext,
203
- emitJs
204
- }: Pick<OptionsResolved, "cwd" | "tsconfig" | "tsconfigRaw" | "build" | "incremental" | "oxc" | "emitDtsOnly" | "vue" | "parallel" | "eager" | "tsgo" | "newContext" | "emitJs">): Plugin;
209
+ emitJs,
210
+ sourcemap
211
+ }: Pick<OptionsResolved, "cwd" | "tsconfig" | "tsconfigRaw" | "build" | "incremental" | "oxc" | "emitDtsOnly" | "vue" | "parallel" | "eager" | "tsgo" | "newContext" | "emitJs" | "sourcemap">): Plugin;
205
212
  //#endregion
206
213
  //#region src/index.d.ts
207
214
  declare function dts(options?: Options): Plugin[];
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { RE_CSS, RE_DTS, RE_DTS_MAP, RE_JS, RE_NODE_MODULES, RE_TS, RE_VUE, filename_dts_to, filename_js_to_dts, filename_to_dts, replaceTemplateName, resolveTemplateFn } from "./filename-Dd76wOJT.js";
2
- import { createContext, globalContext, invalidateContextFile } from "./context-BG0dlajy.js";
2
+ import { createContext, globalContext, invalidateContextFile } from "./context-b9aW37YD.js";
3
3
  import Debug from "debug";
4
4
  import _generate from "@babel/generator";
5
5
  import { parse } from "@babel/parser";
@@ -385,6 +385,7 @@ function createFakeJsPlugin({ sourcemap, cjsDefault }) {
385
385
  program.body = patchTsNamespace(program.body);
386
386
  program.body = program.body.map((node) => {
387
387
  if (isHelperImport(node)) return null;
388
+ if (node.type === "ExpressionStatement") return null;
388
389
  const newNode = patchImportExport(node, typeOnlyIds, cjsDefault);
389
390
  if (newNode) return newNode;
390
391
  if (node.type !== "VariableDeclaration") return node;
@@ -662,7 +663,7 @@ const spawnAsync = (...args) => new Promise((resolve, reject) => {
662
663
  child.on("close", () => resolve());
663
664
  child.on("error", (error) => reject(error));
664
665
  });
665
- function createGeneratePlugin({ tsconfig, tsconfigRaw, build, incremental, cwd, oxc, emitDtsOnly, vue, parallel, eager, tsgo, newContext, emitJs }) {
666
+ function createGeneratePlugin({ tsconfig, tsconfigRaw, build, incremental, cwd, oxc, emitDtsOnly, vue, parallel, eager, tsgo, newContext, emitJs, sourcemap }) {
666
667
  const dtsMap = /* @__PURE__ */ new Map();
667
668
  /**
668
669
  * A map of input id to output file name
@@ -799,6 +800,7 @@ function createGeneratePlugin({ tsconfig, tsconfigRaw, build, incremental, cwd,
799
800
  cwd,
800
801
  entries,
801
802
  id,
803
+ sourcemap,
802
804
  vue,
803
805
  context: tscContext
804
806
  };
@@ -919,11 +921,25 @@ function resolveOptions({ cwd = process.cwd(), dtsInput = false, emitDtsOnly = f
919
921
  //#endregion
920
922
  //#region src/resolver.ts
921
923
  function createDtsResolvePlugin({ tsconfig, resolve }) {
922
- const resolver = createResolver({
924
+ const isSourceFile = (p) => RE_TS.test(p) || RE_VUE.test(p);
925
+ const shouldBundleNodeModule = (id) => {
926
+ if (typeof resolve === "boolean") return resolve;
927
+ return resolve.some((pattern) => typeof pattern === "string" ? id === pattern : pattern.test(id));
928
+ };
929
+ const baseDtsResolver = createResolver({
923
930
  tsconfig,
924
931
  resolveNodeModules: !!resolve,
925
932
  ResolverFactory
926
933
  });
934
+ const resolveDtsPath = (id, importer, rolldownResolution) => {
935
+ let dtsPath = baseDtsResolver(id, importer);
936
+ if (dtsPath) dtsPath = path.normalize(dtsPath);
937
+ if (!dtsPath || !isSourceFile(dtsPath)) {
938
+ if (rolldownResolution && isSourceFile(rolldownResolution.id)) return rolldownResolution.id;
939
+ return null;
940
+ }
941
+ return dtsPath;
942
+ };
927
943
  return {
928
944
  name: "rolldown-plugin-dts:resolver",
929
945
  resolveId: {
@@ -937,30 +953,17 @@ function createDtsResolvePlugin({ tsconfig, resolve }) {
937
953
  if (!importer || !RE_DTS.test(importer)) return;
938
954
  if (RE_CSS.test(id)) return external;
939
955
  const rolldownResolution = await this.resolve(id, importer, options);
940
- let dtsResolution = resolver(id, importer);
941
- dtsResolution &&= path.normalize(dtsResolution);
942
- if (!dtsResolution || !RE_TS.test(dtsResolution) && !RE_VUE.test(dtsResolution)) {
943
- const unresolved = !rolldownResolution || !RE_TS.test(rolldownResolution.id) && !RE_VUE.test(rolldownResolution.id);
944
- if (unresolved) {
945
- const isRelativeOrAbsolute = id.startsWith(".") || path.isAbsolute(id);
946
- if (isRelativeOrAbsolute) return this.error(`Cannot resolve import '${id}' from '${importer}'`);
947
- return external;
948
- }
949
- dtsResolution = rolldownResolution.id;
956
+ const dtsResolution = resolveDtsPath(id, importer, rolldownResolution);
957
+ if (!dtsResolution) {
958
+ const isFileImport = id.startsWith(".") || path.isAbsolute(id);
959
+ return isFileImport ? null : external;
950
960
  }
951
- if (RE_NODE_MODULES.test(dtsResolution)) {
952
- let shouldResolve;
953
- if (typeof resolve === "boolean") shouldResolve = resolve;
954
- else shouldResolve = resolve.some((pattern) => typeof pattern === "string" ? id === pattern : pattern.test(id));
955
- if (!shouldResolve) if (RE_NODE_MODULES.test(importer)) {
956
- if (rolldownResolution?.external) return external;
957
- } else return external;
958
- }
959
- if (RE_TS.test(dtsResolution) && !RE_DTS.test(dtsResolution) || RE_VUE.test(dtsResolution)) {
961
+ if (RE_NODE_MODULES.test(dtsResolution) && !shouldBundleNodeModule(id) && (!RE_NODE_MODULES.test(importer) || rolldownResolution?.external)) return external;
962
+ if (RE_DTS.test(dtsResolution)) return dtsResolution;
963
+ if (isSourceFile(dtsResolution)) {
960
964
  await this.load({ id: dtsResolution });
961
- dtsResolution = filename_to_dts(dtsResolution);
965
+ return filename_to_dts(dtsResolution);
962
966
  }
963
- if (RE_DTS.test(dtsResolution)) return dtsResolution;
964
967
  }
965
968
  }
966
969
  };
@@ -0,0 +1,390 @@
1
+ import { globalContext } from "./context-b9aW37YD.js";
2
+ import { createRequire } from "node:module";
3
+ import Debug from "debug";
4
+ import path from "node:path";
5
+ import ts from "typescript";
6
+ import { pathToFileURL } from "node:url";
7
+
8
+ //#region src/tsc/system.ts
9
+ const debug$4 = Debug("rolldown-plugin-dts:tsc-system");
10
+ /**
11
+ * A system that writes files to both memory and disk. It will try read files
12
+ * from memory firstly and fallback to disk if not found.
13
+ */
14
+ function createFsSystem(files) {
15
+ return {
16
+ ...ts.sys,
17
+ write(message) {
18
+ debug$4(message);
19
+ },
20
+ resolvePath(path$1) {
21
+ if (files.has(path$1)) return path$1;
22
+ return ts.sys.resolvePath(path$1);
23
+ },
24
+ directoryExists(directory) {
25
+ if (Array.from(files.keys()).some((path$1) => path$1.startsWith(directory))) return true;
26
+ return ts.sys.directoryExists(directory);
27
+ },
28
+ fileExists(fileName) {
29
+ if (files.has(fileName)) return true;
30
+ return ts.sys.fileExists(fileName);
31
+ },
32
+ readFile(fileName, ...args) {
33
+ if (files.has(fileName)) return files.get(fileName);
34
+ return ts.sys.readFile(fileName, ...args);
35
+ },
36
+ writeFile(path$1, data, ...args) {
37
+ files.set(path$1, data);
38
+ ts.sys.writeFile(path$1, data, ...args);
39
+ },
40
+ deleteFile(fileName, ...args) {
41
+ files.delete(fileName);
42
+ ts.sys.deleteFile?.(fileName, ...args);
43
+ }
44
+ };
45
+ }
46
+ function createMemorySystem(files) {
47
+ return {
48
+ ...createFsSystem(files),
49
+ writeFile(path$1, data) {
50
+ files.set(path$1, data);
51
+ },
52
+ deleteFile(fileName) {
53
+ files.delete(fileName);
54
+ }
55
+ };
56
+ }
57
+
58
+ //#endregion
59
+ //#region src/tsc/utils.ts
60
+ const formatHost = {
61
+ getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
62
+ getNewLine: () => ts.sys.newLine,
63
+ getCanonicalFileName: ts.sys.useCaseSensitiveFileNames ? (f) => f : (f) => f.toLowerCase()
64
+ };
65
+ const stripPrivateFields = (ctx) => {
66
+ const visitor = (node) => {
67
+ if (ts.isPropertySignature(node) && ts.isPrivateIdentifier(node.name)) return ctx.factory.updatePropertySignature(node, node.modifiers, ctx.factory.createStringLiteral(node.name.text), node.questionToken, node.type);
68
+ return ts.visitEachChild(node, visitor, ctx);
69
+ };
70
+ return (sourceFile) => ts.visitNode(sourceFile, visitor, ts.isSourceFile) ?? sourceFile;
71
+ };
72
+ const customTransformers = { afterDeclarations: [stripPrivateFields] };
73
+
74
+ //#endregion
75
+ //#region src/tsc/emit-build.ts
76
+ const debug$3 = Debug("rolldown-plugin-dts:tsc-build");
77
+ function tscEmitBuild(tscOptions) {
78
+ const { id, tsconfig, incremental, context = globalContext, sourcemap } = tscOptions;
79
+ debug$3(`running tscEmitBuild id: ${id}, tsconfig: ${tsconfig}, incremental: ${incremental}`);
80
+ if (!tsconfig) return { error: "[rolldown-plugin-dts] build mode requires a tsconfig path" };
81
+ const fsSystem = (incremental ? createFsSystem : createMemorySystem)(context.files);
82
+ const resolvedId = fsSystem.resolvePath(id);
83
+ if (resolvedId !== id) debug$3(`resolved id from ${id} to ${resolvedId}`);
84
+ const sourceFileToProjectMap = getOrBuildProjects(context, fsSystem, tsconfig, !incremental, sourcemap);
85
+ const project = sourceFileToProjectMap.get(resolvedId);
86
+ if (!project) {
87
+ debug$3(`unable to locate a project containing ${resolvedId}`);
88
+ return { error: `Unable to locate ${id} from the given tsconfig file ${tsconfig}` };
89
+ }
90
+ debug$3(`loaded project ${project.tsconfigPath} for ${id}`);
91
+ const ignoreCase = !fsSystem.useCaseSensitiveFileNames;
92
+ const outputFiles = ts.getOutputFileNames(project.parsedConfig, resolvedId, ignoreCase);
93
+ let code;
94
+ let map;
95
+ for (const outputFile of outputFiles) {
96
+ if (outputFile.endsWith(".d.ts")) {
97
+ if (!fsSystem.fileExists(outputFile)) {
98
+ console.warn(`[rolldown-plugin-dts] Unable to read file ${outputFile}`);
99
+ continue;
100
+ }
101
+ code = fsSystem.readFile(outputFile);
102
+ continue;
103
+ }
104
+ if (outputFile.endsWith(".d.ts.map")) {
105
+ if (!fsSystem.fileExists(outputFile)) continue;
106
+ const text = fsSystem.readFile(outputFile);
107
+ if (!text) {
108
+ console.warn(`[rolldown-plugin-dts] Unexpected sourcemap ${outputFile}`);
109
+ continue;
110
+ }
111
+ map = JSON.parse(text);
112
+ if (!map || map.sourceRoot) continue;
113
+ const outputFileDir = path.posix.dirname(pathToFileURL(outputFile).pathname);
114
+ const resolvedIdDir = path.posix.dirname(pathToFileURL(resolvedId).pathname);
115
+ if (outputFileDir !== resolvedIdDir) map.sourceRoot = path.posix.relative(resolvedIdDir, outputFileDir);
116
+ }
117
+ }
118
+ if (code) return {
119
+ code,
120
+ map
121
+ };
122
+ if (incremental) {
123
+ debug$3(`incremental build failed`);
124
+ return tscEmitBuild({
125
+ ...tscOptions,
126
+ incremental: false
127
+ });
128
+ }
129
+ debug$3(`unable to build .d.ts file for ${id}`);
130
+ if (project.parsedConfig.options.declaration !== true) return { error: `Unable to build .d.ts file for ${id}; Make sure the "declaration" option is set to true in ${project.tsconfigPath}` };
131
+ return { error: `Unable to build .d.ts file for ${id}; This seems like a bug of rolldown-plugin-dts. Please report this issue to https://github.com/sxzz/rolldown-plugin-dts/issues` };
132
+ }
133
+ function getOrBuildProjects(context, fsSystem, tsconfig, force, sourcemap) {
134
+ let projectMap = context.projects.get(tsconfig);
135
+ if (projectMap) {
136
+ debug$3(`skip building projects for ${tsconfig}`);
137
+ return projectMap;
138
+ }
139
+ projectMap = buildProjects(fsSystem, tsconfig, force, sourcemap);
140
+ context.projects.set(tsconfig, projectMap);
141
+ return projectMap;
142
+ }
143
+ /**
144
+ * Use TypeScript compiler to build all projects referenced
145
+ */
146
+ function buildProjects(fsSystem, tsconfig, force, sourcemap) {
147
+ debug$3(`start building projects for ${tsconfig}`);
148
+ const projects = collectProjectGraph(tsconfig, fsSystem, force, sourcemap);
149
+ debug$3("collected %d projects: %j", projects.length, projects.map((project) => project.tsconfigPath));
150
+ const host = ts.createSolutionBuilderHost(fsSystem, createProgramWithPatchedCompilerOptions);
151
+ const builder = ts.createSolutionBuilder(host, [tsconfig], {
152
+ force,
153
+ verbose: true
154
+ });
155
+ const exitStatus = builder.build(void 0, void 0, void 0, (project) => {
156
+ debug$3(`transforming project ${project}`);
157
+ return customTransformers;
158
+ });
159
+ debug$3(`built solution for ${tsconfig} with exit status ${exitStatus}`);
160
+ const sourceFileToProjectMap = /* @__PURE__ */ new Map();
161
+ for (const project of projects) for (const fileName of project.parsedConfig.fileNames) sourceFileToProjectMap.set(fsSystem.resolvePath(fileName), project);
162
+ return sourceFileToProjectMap;
163
+ }
164
+ /**
165
+ * Collects all referenced projects from the given entry tsconfig file.
166
+ */
167
+ function collectProjectGraph(rootTsconfigPath, fsSystem, force, sourcemap) {
168
+ const seen = /* @__PURE__ */ new Set();
169
+ const projects = [];
170
+ const stack = [fsSystem.resolvePath(rootTsconfigPath)];
171
+ while (true) {
172
+ const tsconfigPath = stack.pop();
173
+ if (!tsconfigPath) break;
174
+ if (seen.has(tsconfigPath)) continue;
175
+ seen.add(tsconfigPath);
176
+ const parsedConfig = parseTsconfig(tsconfigPath, fsSystem);
177
+ if (!parsedConfig) continue;
178
+ parsedConfig.options = patchCompilerOptions(parsedConfig.options, {
179
+ tsconfigPath,
180
+ force,
181
+ sourcemap
182
+ });
183
+ projects.push({
184
+ tsconfigPath,
185
+ parsedConfig
186
+ });
187
+ for (const ref of parsedConfig.projectReferences ?? []) stack.push(ts.resolveProjectReferencePath(ref));
188
+ }
189
+ return projects;
190
+ }
191
+ function parseTsconfig(tsconfigPath, fsSystem) {
192
+ const diagnostics = [];
193
+ const parsedConfig = ts.getParsedCommandLineOfConfigFile(tsconfigPath, void 0, {
194
+ ...fsSystem,
195
+ onUnRecoverableConfigFileDiagnostic: (diagnostic) => {
196
+ diagnostics.push(diagnostic);
197
+ }
198
+ });
199
+ if (diagnostics.length) throw new Error(`[rolldown-plugin-dts] Unable to read ${tsconfigPath}: ${ts.formatDiagnostics(diagnostics, formatHost)}`);
200
+ return parsedConfig;
201
+ }
202
+ function patchCompilerOptions(options, extraOptions) {
203
+ const noEmit = options.noEmit ?? false;
204
+ const declaration = options.declaration ?? (options.composite ? true : false);
205
+ const declarationMap = options.declarationMap ?? false;
206
+ const shouldPrintWarning = extraOptions?.tsconfigPath && !extraOptions.force;
207
+ if (noEmit === true) {
208
+ options = {
209
+ ...options,
210
+ noEmit: false
211
+ };
212
+ if (shouldPrintWarning) console.warn(`[rolldown-plugin-dts] ${extraOptions.tsconfigPath} has "noEmit" set to true. Please set it to false to generate declaration files.`);
213
+ }
214
+ if (declaration === false) {
215
+ options = {
216
+ ...options,
217
+ declaration: true
218
+ };
219
+ if (shouldPrintWarning) console.warn(`[rolldown-plugin-dts] ${extraOptions.tsconfigPath} has "declaration" set to false. Please set it to true to generate declaration files.`);
220
+ }
221
+ if (declarationMap === false && extraOptions?.sourcemap) {
222
+ options = {
223
+ ...options,
224
+ declarationMap: true
225
+ };
226
+ if (shouldPrintWarning) console.warn(`[rolldown-plugin-dts] ${extraOptions.tsconfigPath} has "declarationMap" set to false. Please set it to true if you want to generate source maps for declaration files.`);
227
+ }
228
+ return options;
229
+ }
230
+ const createProgramWithPatchedCompilerOptions = (rootNames, options, ...args) => {
231
+ return ts.createEmitAndSemanticDiagnosticsBuilderProgram(rootNames, patchCompilerOptions(options ?? {}, null), ...args);
232
+ };
233
+
234
+ //#endregion
235
+ //#region src/tsc/vue.ts
236
+ const debug$2 = Debug("rolldown-plugin-dts:vue");
237
+ let createVueProgram;
238
+ const require = createRequire(import.meta.url);
239
+ function loadVueLanguageTools() {
240
+ try {
241
+ const vueTscPath = require.resolve("vue-tsc");
242
+ const { proxyCreateProgram } = require(require.resolve("@volar/typescript", { paths: [vueTscPath] }));
243
+ const vue = require(require.resolve("@vue/language-core", { paths: [vueTscPath] }));
244
+ return {
245
+ proxyCreateProgram,
246
+ vue
247
+ };
248
+ } catch (error) {
249
+ debug$2("vue language tools not found", error);
250
+ throw new Error("Failed to load vue language tools. Please manually install vue-tsc.");
251
+ }
252
+ }
253
+ function createVueProgramFactory(ts$1) {
254
+ if (createVueProgram) return createVueProgram;
255
+ debug$2("loading vue language tools");
256
+ const { proxyCreateProgram, vue } = loadVueLanguageTools();
257
+ return createVueProgram = proxyCreateProgram(ts$1, ts$1.createProgram, (ts$2, options) => {
258
+ const $rootDir = options.options.$rootDir;
259
+ const $configRaw = options.options.$configRaw;
260
+ const resolver = new vue.CompilerOptionsResolver(ts$2.sys.fileExists);
261
+ resolver.addConfig($configRaw?.vueCompilerOptions ?? {}, $rootDir);
262
+ const vueOptions = resolver.build();
263
+ vue.writeGlobalTypes(vueOptions, ts$2.sys.writeFile);
264
+ const vueLanguagePlugin = vue.createVueLanguagePlugin(ts$2, options.options, vueOptions, (id) => id);
265
+ return { languagePlugins: [vueLanguagePlugin] };
266
+ });
267
+ }
268
+
269
+ //#endregion
270
+ //#region src/tsc/emit-compiler.ts
271
+ const debug$1 = Debug("rolldown-plugin-dts:tsc-compiler");
272
+ const defaultCompilerOptions = {
273
+ declaration: true,
274
+ noEmit: false,
275
+ emitDeclarationOnly: true,
276
+ noEmitOnError: true,
277
+ checkJs: false,
278
+ declarationMap: false,
279
+ skipLibCheck: true,
280
+ target: 99,
281
+ resolveJsonModule: true,
282
+ moduleResolution: ts.ModuleResolutionKind.Bundler
283
+ };
284
+ function createOrGetTsModule(options) {
285
+ const { id, entries, context = globalContext } = options;
286
+ const program = context.programs.find((program$1) => {
287
+ const roots = program$1.getRootFileNames();
288
+ if (entries) return entries.every((entry) => roots.includes(entry));
289
+ return roots.includes(id);
290
+ });
291
+ if (program) {
292
+ const sourceFile = program.getSourceFile(id);
293
+ if (sourceFile) return {
294
+ program,
295
+ file: sourceFile
296
+ };
297
+ }
298
+ debug$1(`create program for module: ${id}`);
299
+ const module = createTsProgram(options);
300
+ debug$1(`created program for module: ${id}`);
301
+ context.programs.push(module.program);
302
+ return module;
303
+ }
304
+ function createTsProgram({ entries, id, tsconfig, tsconfigRaw, vue, cwd, context = globalContext }) {
305
+ const fsSystem = createFsSystem(context.files);
306
+ const baseDir = tsconfig ? path.dirname(tsconfig) : cwd;
307
+ const parsedConfig = ts.parseJsonConfigFileContent(tsconfigRaw, fsSystem, baseDir);
308
+ debug$1(`Creating program for root project: ${baseDir}`);
309
+ return createTsProgramFromParsedConfig({
310
+ parsedConfig,
311
+ fsSystem,
312
+ baseDir,
313
+ id,
314
+ entries,
315
+ vue
316
+ });
317
+ }
318
+ function createTsProgramFromParsedConfig({ parsedConfig, fsSystem, baseDir, id, entries, vue }) {
319
+ const compilerOptions = {
320
+ ...defaultCompilerOptions,
321
+ ...parsedConfig.options,
322
+ $configRaw: parsedConfig.raw,
323
+ $rootDir: baseDir
324
+ };
325
+ const rootNames = [...new Set([id, ...entries || parsedConfig.fileNames].map((f) => fsSystem.resolvePath(f)))];
326
+ const host = ts.createCompilerHost(compilerOptions, true);
327
+ const createProgram = vue ? createVueProgramFactory(ts) : ts.createProgram;
328
+ const program = createProgram({
329
+ rootNames,
330
+ options: compilerOptions,
331
+ host,
332
+ projectReferences: parsedConfig.projectReferences
333
+ });
334
+ const sourceFile = program.getSourceFile(id);
335
+ if (!sourceFile) {
336
+ debug$1(`source file not found in program: ${id}`);
337
+ const hasReferences = !!parsedConfig.projectReferences?.length;
338
+ if (hasReferences) throw new Error(`[rolldown-plugin-dts] Unable to load ${id}; You have "references" in your tsconfig file. Perhaps you want to add \`dts: { build: true }\` in your config?`);
339
+ if (!fsSystem.fileExists(id)) {
340
+ debug$1(`File ${id} does not exist on disk.`);
341
+ throw new Error(`Source file not found: ${id}`);
342
+ } else {
343
+ debug$1(`File ${id} exists on disk.`);
344
+ throw new Error(`Unable to load file ${id} from the program. This seems like a bug of rolldown-plugin-dts. Please report this issue to https://github.com/sxzz/rolldown-plugin-dts/issues`);
345
+ }
346
+ }
347
+ return {
348
+ program,
349
+ file: sourceFile
350
+ };
351
+ }
352
+ function tscEmitCompiler(tscOptions) {
353
+ debug$1(`running tscEmitCompiler ${tscOptions.id}`);
354
+ const module = createOrGetTsModule(tscOptions);
355
+ const { program, file } = module;
356
+ debug$1(`got source file: ${file.fileName}`);
357
+ let dtsCode;
358
+ let map;
359
+ const { emitSkipped, diagnostics } = program.emit(file, (fileName, code) => {
360
+ if (fileName.endsWith(".map")) {
361
+ debug$1(`emit dts sourcemap: ${fileName}`);
362
+ map = JSON.parse(code);
363
+ } else {
364
+ debug$1(`emit dts: ${fileName}`);
365
+ dtsCode = code;
366
+ }
367
+ }, void 0, true, customTransformers, true);
368
+ if (emitSkipped && diagnostics.length) return { error: ts.formatDiagnostics(diagnostics, formatHost) };
369
+ if (!dtsCode && file.isDeclarationFile) {
370
+ debug$1("nothing was emitted. fallback to sourceFile text.");
371
+ dtsCode = file.getFullText();
372
+ }
373
+ return {
374
+ code: dtsCode,
375
+ map
376
+ };
377
+ }
378
+
379
+ //#endregion
380
+ //#region src/tsc/index.ts
381
+ const debug = Debug("rolldown-plugin-dts:tsc");
382
+ debug(`loaded typescript: ${ts.version}`);
383
+ function tscEmit(tscOptions) {
384
+ debug(`running tscEmit ${tscOptions.id}`);
385
+ if (tscOptions.build) return tscEmitBuild(tscOptions);
386
+ else return tscEmitCompiler(tscOptions);
387
+ }
388
+
389
+ //#endregion
390
+ export { tscEmit };
@@ -1,2 +1,2 @@
1
- import { TscContext, createContext, globalContext, invalidateContextFile } from "./context-DIRjVfC4.js";
2
- export { TscContext, createContext, globalContext, invalidateContextFile };
1
+ import { ParsedProject, SourceFileToProjectMap, TscContext, createContext, globalContext, invalidateContextFile } from "./context-DXNtAHtR.js";
2
+ export { ParsedProject, SourceFileToProjectMap, TscContext, createContext, globalContext, invalidateContextFile };
@@ -1,3 +1,3 @@
1
- import { createContext, globalContext, invalidateContextFile } from "./context-BG0dlajy.js";
1
+ import { createContext, globalContext, invalidateContextFile } from "./context-b9aW37YD.js";
2
2
 
3
3
  export { createContext, globalContext, invalidateContextFile };
@@ -1,5 +1,5 @@
1
- import "./context-DIRjVfC4.js";
2
- import { tscEmit } from "./index-BPD4iQBs.js";
1
+ import "./context-DXNtAHtR.js";
2
+ import { tscEmit } from "./index-Cbz-60ZO.js";
3
3
 
4
4
  //#region src/tsc/worker.d.ts
5
5
  declare const functions: {
@@ -1,5 +1,5 @@
1
- import "./context-BG0dlajy.js";
2
- import { tscEmit } from "./tsc-BJW5IMTs.js";
1
+ import "./context-b9aW37YD.js";
2
+ import { tscEmit } from "./tsc-B1sK0Lli.js";
3
3
  import process from "node:process";
4
4
  import { createBirpc } from "birpc";
5
5
 
package/dist/tsc.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import "./context-DIRjVfC4.js";
2
- import { TscModule, TscOptions, TscResult, tscEmit } from "./index-BPD4iQBs.js";
1
+ import "./context-DXNtAHtR.js";
2
+ import { TscModule, TscOptions, TscResult, tscEmit } from "./index-Cbz-60ZO.js";
3
3
  export { TscModule, TscOptions, TscResult, tscEmit };
package/dist/tsc.js CHANGED
@@ -1,4 +1,4 @@
1
- import "./context-BG0dlajy.js";
2
- import { tscEmit } from "./tsc-BJW5IMTs.js";
1
+ import "./context-b9aW37YD.js";
2
+ import { tscEmit } from "./tsc-B1sK0Lli.js";
3
3
 
4
4
  export { tscEmit };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rolldown-plugin-dts",
3
- "version": "0.15.9",
3
+ "version": "0.16.0",
4
4
  "description": "A Rolldown plugin to generate and bundle dts files.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -73,7 +73,7 @@
73
73
  "@types/babel__generator": "^7.27.0",
74
74
  "@types/debug": "^4.1.12",
75
75
  "@types/node": "^24.3.0",
76
- "@typescript/native-preview": "7.0.0-dev.20250824.1",
76
+ "@typescript/native-preview": "7.0.0-dev.20250904.1",
77
77
  "@volar/typescript": "^2.4.23",
78
78
  "@vue/language-core": "^3.0.6",
79
79
  "bumpp": "^10.2.3",
@@ -81,13 +81,13 @@
81
81
  "eslint": "^9.34.0",
82
82
  "estree-walker": "^3.0.3",
83
83
  "prettier": "^3.6.2",
84
- "rolldown": "^1.0.0-beta.33",
84
+ "rolldown": "^1.0.0-beta.34",
85
85
  "rollup-plugin-dts": "^6.2.3",
86
86
  "tinyglobby": "^0.2.14",
87
- "tsdown": "^0.14.1",
87
+ "tsdown": "^0.14.2",
88
88
  "typescript": "^5.9.2",
89
89
  "vitest": "^3.2.4",
90
- "vue": "^3.5.19",
90
+ "vue": "^3.5.21",
91
91
  "vue-tsc": "^3.0.6"
92
92
  },
93
93
  "engines": {
@@ -1,279 +0,0 @@
1
- import { globalContext } from "./context-BG0dlajy.js";
2
- import { createRequire } from "node:module";
3
- import Debug from "debug";
4
- import path from "node:path";
5
- import ts from "typescript";
6
-
7
- //#region src/tsc/system.ts
8
- const debug$2 = Debug("rolldown-plugin-dts:tsc-system");
9
- /**
10
- * A system that writes files to both memory and disk. It will try read files
11
- * from memory firstly and fallback to disk if not found.
12
- */
13
- function createFsSystem(files) {
14
- return {
15
- ...ts.sys,
16
- write(message) {
17
- debug$2(message);
18
- },
19
- resolvePath(path$1) {
20
- if (files.has(path$1)) return path$1;
21
- return ts.sys.resolvePath(path$1);
22
- },
23
- directoryExists(directory) {
24
- if (Array.from(files.keys()).some((path$1) => path$1.startsWith(directory))) return true;
25
- return ts.sys.directoryExists(directory);
26
- },
27
- fileExists(fileName) {
28
- if (files.has(fileName)) return true;
29
- return ts.sys.fileExists(fileName);
30
- },
31
- readFile(fileName, ...args) {
32
- if (files.has(fileName)) return files.get(fileName);
33
- return ts.sys.readFile(fileName, ...args);
34
- },
35
- writeFile(path$1, data, ...args) {
36
- files.set(path$1, data);
37
- ts.sys.writeFile(path$1, data, ...args);
38
- },
39
- deleteFile(fileName, ...args) {
40
- files.delete(fileName);
41
- ts.sys.deleteFile?.(fileName, ...args);
42
- }
43
- };
44
- }
45
- function createMemorySystem(files) {
46
- return {
47
- ...createFsSystem(files),
48
- writeFile(path$1, data) {
49
- files.set(path$1, data);
50
- },
51
- deleteFile(fileName) {
52
- files.delete(fileName);
53
- }
54
- };
55
- }
56
-
57
- //#endregion
58
- //#region src/tsc/vue.ts
59
- const debug$1 = Debug("rolldown-plugin-dts:vue");
60
- let createVueProgram;
61
- const require = createRequire(import.meta.url);
62
- function loadVueLanguageTools() {
63
- try {
64
- const vueTscPath = require.resolve("vue-tsc");
65
- const { proxyCreateProgram } = require(require.resolve("@volar/typescript", { paths: [vueTscPath] }));
66
- const vue = require(require.resolve("@vue/language-core", { paths: [vueTscPath] }));
67
- return {
68
- proxyCreateProgram,
69
- vue
70
- };
71
- } catch (error) {
72
- debug$1("vue language tools not found", error);
73
- throw new Error("Failed to load vue language tools. Please manually install vue-tsc.");
74
- }
75
- }
76
- function createVueProgramFactory(ts$1) {
77
- if (createVueProgram) return createVueProgram;
78
- debug$1("loading vue language tools");
79
- const { proxyCreateProgram, vue } = loadVueLanguageTools();
80
- return createVueProgram = proxyCreateProgram(ts$1, ts$1.createProgram, (ts$2, options) => {
81
- const $rootDir = options.options.$rootDir;
82
- const $configRaw = options.options.$configRaw;
83
- const resolver = new vue.CompilerOptionsResolver(ts$2.sys.fileExists);
84
- resolver.addConfig($configRaw?.vueCompilerOptions ?? {}, $rootDir);
85
- const vueOptions = resolver.build();
86
- vue.writeGlobalTypes(vueOptions, ts$2.sys.writeFile);
87
- const vueLanguagePlugin = vue.createVueLanguagePlugin(ts$2, options.options, vueOptions, (id) => id);
88
- return { languagePlugins: [vueLanguagePlugin] };
89
- });
90
- }
91
-
92
- //#endregion
93
- //#region src/tsc/index.ts
94
- const debug = Debug("rolldown-plugin-dts:tsc");
95
- debug(`loaded typescript: ${ts.version}`);
96
- const formatHost = {
97
- getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
98
- getNewLine: () => ts.sys.newLine,
99
- getCanonicalFileName: ts.sys.useCaseSensitiveFileNames ? (f) => f : (f) => f.toLowerCase()
100
- };
101
- const defaultCompilerOptions = {
102
- declaration: true,
103
- noEmit: false,
104
- emitDeclarationOnly: true,
105
- noEmitOnError: true,
106
- checkJs: false,
107
- declarationMap: false,
108
- skipLibCheck: true,
109
- target: 99,
110
- resolveJsonModule: true,
111
- moduleResolution: ts.ModuleResolutionKind.Bundler
112
- };
113
- function createOrGetTsModule(options) {
114
- const { id, entries, context = globalContext } = options;
115
- const program = context.programs.find((program$1) => {
116
- const roots = program$1.getRootFileNames();
117
- if (entries) return entries.every((entry) => roots.includes(entry));
118
- return roots.includes(id);
119
- });
120
- if (program) {
121
- const sourceFile = program.getSourceFile(id);
122
- if (sourceFile) return {
123
- program,
124
- file: sourceFile
125
- };
126
- }
127
- debug(`create program for module: ${id}`);
128
- const module = createTsProgram(options);
129
- debug(`created program for module: ${id}`);
130
- context.programs.push(module.program);
131
- return module;
132
- }
133
- /**
134
- * Build the root project and all its dependencies projects.
135
- * This is designed for a project (e.g. tsconfig.json) that has "references" to
136
- * other composite projects (e.g., tsconfig.node.json and tsconfig.app.json).
137
- * If `incremental` is `true`, the build result will be cached in the
138
- * `.tsbuildinfo` file so that the next time the project is built (without
139
- * changes) the build will be super fast. If `incremental` is `false`, the
140
- * `.tsbuildinfo` file will only be written to the memory.
141
- */
142
- function buildSolution(tsconfig, incremental, context) {
143
- debug(`building projects for ${tsconfig} with incremental: ${incremental}`);
144
- const system = (incremental ? createFsSystem : createMemorySystem)(context.files);
145
- const host = ts.createSolutionBuilderHost(system);
146
- const builder = ts.createSolutionBuilder(host, [tsconfig], {
147
- force: !incremental,
148
- verbose: true
149
- });
150
- const projects = [];
151
- const getCustomTransformers = (project) => {
152
- projects.push(project);
153
- return {};
154
- };
155
- const exitStatus = builder.build(void 0, void 0, void 0, getCustomTransformers);
156
- debug(`built solution for ${tsconfig} with exit status ${exitStatus}`);
157
- return Array.from(new Set(projects));
158
- }
159
- function findProjectContainingFile(projects, targetFile, fsSystem) {
160
- const resolvedTargetFile = fsSystem.resolvePath(targetFile);
161
- for (const tsconfigPath of projects) {
162
- const parsedConfig = parseTsconfig(tsconfigPath, fsSystem);
163
- if (parsedConfig && parsedConfig.fileNames.some((fileName) => fsSystem.resolvePath(fileName) === resolvedTargetFile)) return {
164
- parsedConfig,
165
- tsconfigPath
166
- };
167
- }
168
- }
169
- function parseTsconfig(tsconfigPath, fsSystem) {
170
- const diagnostics = [];
171
- const parsedConfig = ts.getParsedCommandLineOfConfigFile(tsconfigPath, void 0, {
172
- ...fsSystem,
173
- onUnRecoverableConfigFileDiagnostic: (diagnostic) => {
174
- diagnostics.push(diagnostic);
175
- }
176
- });
177
- if (diagnostics.length) throw new Error(`[rolldown-plugin-dts] Unable to read ${tsconfigPath}: ${ts.formatDiagnostics(diagnostics, formatHost)}`);
178
- return parsedConfig;
179
- }
180
- function createTsProgram({ entries, id, tsconfig, tsconfigRaw, build, incremental, vue, cwd, context = globalContext }) {
181
- const fsSystem = createFsSystem(context.files);
182
- const baseDir = tsconfig ? path.dirname(tsconfig) : cwd;
183
- const parsedConfig = ts.parseJsonConfigFileContent(tsconfigRaw, fsSystem, baseDir);
184
- if (tsconfig && build) {
185
- const projectPaths = buildSolution(tsconfig, incremental, context);
186
- debug(`collected projects: ${JSON.stringify(projectPaths)}`);
187
- const project = findProjectContainingFile(projectPaths, id, fsSystem);
188
- if (project) {
189
- debug(`Creating program for project: ${project.tsconfigPath}`);
190
- return createTsProgramFromParsedConfig({
191
- parsedConfig: project.parsedConfig,
192
- fsSystem,
193
- baseDir: path.dirname(project.tsconfigPath),
194
- id,
195
- entries,
196
- vue
197
- });
198
- }
199
- }
200
- return createTsProgramFromParsedConfig({
201
- parsedConfig,
202
- fsSystem,
203
- baseDir,
204
- id,
205
- entries,
206
- vue
207
- });
208
- }
209
- function createTsProgramFromParsedConfig({ parsedConfig, fsSystem, baseDir, id, entries, vue }) {
210
- const compilerOptions = {
211
- ...defaultCompilerOptions,
212
- ...parsedConfig.options,
213
- $configRaw: parsedConfig.raw,
214
- $rootDir: baseDir
215
- };
216
- const rootNames = [...new Set([id, ...entries || parsedConfig.fileNames].map((f) => fsSystem.resolvePath(f)))];
217
- const host = ts.createCompilerHost(compilerOptions, true);
218
- host.readFile = fsSystem.readFile;
219
- host.fileExists = fsSystem.fileExists;
220
- host.directoryExists = fsSystem.directoryExists;
221
- const createProgram = vue ? createVueProgramFactory(ts) : ts.createProgram;
222
- const program = createProgram({
223
- rootNames,
224
- options: compilerOptions,
225
- host,
226
- projectReferences: parsedConfig.projectReferences
227
- });
228
- const sourceFile = program.getSourceFile(id);
229
- if (!sourceFile) {
230
- debug(`source file not found in program: ${id}`);
231
- if (!fsSystem.fileExists(id)) {
232
- debug(`File ${id} does not exist on disk.`);
233
- throw new Error(`Source file not found: ${id}`);
234
- } else {
235
- debug(`File ${id} exists on disk.`);
236
- throw new Error(`Unable to load file ${id} from the program. This seems like a bug of rolldown-plugin-dts. Please report this issue to https://github.com/sxzz/rolldown-plugin-dts/issues`);
237
- }
238
- }
239
- return {
240
- program,
241
- file: sourceFile
242
- };
243
- }
244
- function tscEmit(tscOptions) {
245
- debug(`running tscEmit ${tscOptions.id}`);
246
- const module = createOrGetTsModule(tscOptions);
247
- const { program, file } = module;
248
- debug(`got source file: ${file.fileName}`);
249
- let dtsCode;
250
- let map;
251
- const stripPrivateFields = (ctx) => {
252
- const visitor = (node) => {
253
- if (ts.isPropertySignature(node) && ts.isPrivateIdentifier(node.name)) return ctx.factory.updatePropertySignature(node, node.modifiers, ctx.factory.createStringLiteral(node.name.text), node.questionToken, node.type);
254
- return ts.visitEachChild(node, visitor, ctx);
255
- };
256
- return (sourceFile) => ts.visitNode(sourceFile, visitor, ts.isSourceFile) ?? sourceFile;
257
- };
258
- const { emitSkipped, diagnostics } = program.emit(file, (fileName, code) => {
259
- if (fileName.endsWith(".map")) {
260
- debug(`emit dts sourcemap: ${fileName}`);
261
- map = JSON.parse(code);
262
- } else {
263
- debug(`emit dts: ${fileName}`);
264
- dtsCode = code;
265
- }
266
- }, void 0, true, { afterDeclarations: [stripPrivateFields] }, true);
267
- if (emitSkipped && diagnostics.length) return { error: ts.formatDiagnostics(diagnostics, formatHost) };
268
- if (!dtsCode && file.isDeclarationFile) {
269
- debug("nothing was emitted. fallback to sourceFile text.");
270
- dtsCode = file.getFullText();
271
- }
272
- return {
273
- code: dtsCode,
274
- map
275
- };
276
- }
277
-
278
- //#endregion
279
- export { tscEmit };