vite-plugin-dts 3.0.2 → 3.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/README.md CHANGED
@@ -15,7 +15,7 @@
15
15
  ## Install
16
16
 
17
17
  ```sh
18
- pnpm add vite-plugin-dts -D
18
+ pnpm i vite-plugin-dts -D
19
19
  ```
20
20
 
21
21
  ## Usage
@@ -59,9 +59,7 @@ export default defineComponent({
59
59
 
60
60
  ```vue
61
61
  <script setup lang="ts">
62
- // Need to access the defineProps returned value to
63
- // infer types although you never use the props directly
64
- const props = defineProps<{
62
+ defineProps<{
65
63
  color: 'blue' | 'red'
66
64
  }>()
67
65
  </script>
@@ -108,9 +106,30 @@ This is an existing issue when TypeScript infers types from packages located in
108
106
  import type ts from 'typescript'
109
107
  import type { LogLevel } from 'vite'
110
108
 
111
- interface TransformWriteFile {
112
- filePath?: string
113
- content?: string
109
+ type MaybePromise<T> = T | Promise<T>
110
+
111
+ export interface Resolver {
112
+ /**
113
+ * The name of the resolver
114
+ *
115
+ * The later resolver with the same name will overwrite the earlier
116
+ */
117
+ name: string,
118
+ /**
119
+ * Determine whether the resolve supports the file
120
+ */
121
+ supports: (id: string) => void | boolean,
122
+ /**
123
+ * Transform the source file to declaration files
124
+ */
125
+ transform: (payload: {
126
+ id: string,
127
+ code: string,
128
+ root: string,
129
+ host: ts.CompilerHost,
130
+ program: ts.Program,
131
+ service: ts.LanguageService
132
+ }) => MaybePromise<{ path: string, content: string }[]>
114
133
  }
115
134
 
116
135
  export interface PluginOptions {
@@ -119,7 +138,7 @@ export interface PluginOptions {
119
138
  *
120
139
  * By Default it base on 'root' of your Vite config, or `process.cwd()` if using Rollup
121
140
  */
122
- root?: string
141
+ root?: string,
123
142
 
124
143
  /**
125
144
  * Specify declaration files output directory
@@ -128,7 +147,7 @@ export interface PluginOptions {
128
147
  *
129
148
  * By Default it base on 'build.outDir' of your Vite config, or `outDir` of tsconfig.json if using Rollup
130
149
  */
131
- outDir?: string | string[]
150
+ outDir?: string | string[],
132
151
 
133
152
  /**
134
153
  * Manually set the root path of the entry files, useful in monorepo
@@ -137,7 +156,7 @@ export interface PluginOptions {
137
156
  *
138
157
  * By Default it is the smallest public path for all files
139
158
  */
140
- entryRoot?: string
159
+ entryRoot?: string,
141
160
 
142
161
  /**
143
162
  * Strictly restrict declaration files output inside `outDir`
@@ -146,14 +165,14 @@ export interface PluginOptions {
146
165
  *
147
166
  * @default true
148
167
  */
149
- strictOutput?: boolean
168
+ strictOutput?: boolean,
150
169
 
151
170
  /**
152
171
  * Specify a CompilerOptions to override
153
172
  *
154
173
  * @default null
155
174
  */
156
- compilerOptions?: ts.CompilerOptions | null
175
+ compilerOptions?: ts.CompilerOptions | null,
157
176
 
158
177
  /**
159
178
  * Specify tsconfig.json path
@@ -162,7 +181,14 @@ export interface PluginOptions {
162
181
  *
163
182
  * By default plugin will find config form root if not specify
164
183
  */
165
- tsconfigPath?: string
184
+ tsconfigPath?: string,
185
+
186
+ /**
187
+ * Specify custom resolvers
188
+ *
189
+ * @default []
190
+ */
191
+ resolvers?: Resolver[],
166
192
 
167
193
  /**
168
194
  * Set which paths should exclude when transform aliases
@@ -171,14 +197,14 @@ export interface PluginOptions {
171
197
  *
172
198
  * @default []
173
199
  */
174
- aliasesExclude?: (string | RegExp)[]
200
+ aliasesExclude?: (string | RegExp)[],
175
201
 
176
202
  /**
177
203
  * Whether transform file name '.vue.d.ts' to '.d.ts'
178
204
  *
179
205
  * @default false
180
206
  */
181
- cleanVueFileName?: boolean
207
+ cleanVueFileName?: boolean,
182
208
 
183
209
  /**
184
210
  * Whether transform dynamic import to static
@@ -189,28 +215,28 @@ export interface PluginOptions {
189
215
  *
190
216
  * @default false
191
217
  */
192
- staticImport?: boolean
218
+ staticImport?: boolean,
193
219
 
194
220
  /**
195
221
  * Manual set include glob
196
222
  *
197
223
  * By Default it base on `include` option of the tsconfig.json
198
224
  */
199
- include?: string | string[]
225
+ include?: string | string[],
200
226
 
201
227
  /**
202
228
  * Manual set exclude glob
203
229
  *
204
230
  * By Default it base on `exclude` option of the tsconfig.json, be `'node_module/**'` when empty
205
231
  */
206
- exclude?: string | string[]
232
+ exclude?: string | string[],
207
233
 
208
234
  /**
209
235
  * Whether remove those `import 'xxx'`
210
236
  *
211
237
  * @default true
212
238
  */
213
- clearPureImport?: boolean
239
+ clearPureImport?: boolean,
214
240
 
215
241
  /**
216
242
  * Whether generate types entry file
@@ -221,7 +247,7 @@ export interface PluginOptions {
221
247
  *
222
248
  * @default false
223
249
  */
224
- insertTypesEntry?: boolean
250
+ insertTypesEntry?: boolean,
225
251
 
226
252
  /**
227
253
  * Set whether rollup declaration files after emit
@@ -230,7 +256,7 @@ export interface PluginOptions {
230
256
  *
231
257
  * @default false
232
258
  */
233
- rollupTypes?: boolean
259
+ rollupTypes?: boolean,
234
260
 
235
261
  /**
236
262
  * Bundled packages for `@microsoft/api-extractor`
@@ -238,7 +264,7 @@ export interface PluginOptions {
238
264
  * @default []
239
265
  * @see https://api-extractor.com/pages/configs/api-extractor_json/#bundledpackages
240
266
  */
241
- bundledPackages?: string[]
267
+ bundledPackages?: string[],
242
268
 
243
269
  /**
244
270
  * Whether copy .d.ts source files into `outDir`
@@ -246,14 +272,14 @@ export interface PluginOptions {
246
272
  * @default false
247
273
  * @remarks Before 2.0 it defaults to true
248
274
  */
249
- copyDtsFiles?: boolean
275
+ copyDtsFiles?: boolean,
250
276
 
251
277
  /**
252
278
  * Specify the log level of plugin
253
279
  *
254
280
  * By Default it base on 'logLevel' option of your Vite config
255
281
  */
256
- logLevel?: LogLevel
282
+ logLevel?: LogLevel,
257
283
 
258
284
  /**
259
285
  * Hook after diagnostic emitted
@@ -262,7 +288,7 @@ export interface PluginOptions {
262
288
  *
263
289
  * @default () => {}
264
290
  */
265
- afterDiagnostic?: (diagnostics: readonly ts.Diagnostic[]) => void | Promise<void>
291
+ afterDiagnostic?: (diagnostics: readonly ts.Diagnostic[]) => MaybePromise<void>,
266
292
 
267
293
  /**
268
294
  * Hook before each declaration file is written
@@ -273,7 +299,16 @@ export interface PluginOptions {
273
299
  *
274
300
  * @default () => {}
275
301
  */
276
- beforeWriteFile?: (filePath: string, content: string) => void | false | TransformWriteFile
302
+ beforeWriteFile?: (
303
+ filePath: string,
304
+ content: string
305
+ ) =>
306
+ | void
307
+ | false
308
+ | {
309
+ filePath?: string,
310
+ content?: string
311
+ },
277
312
 
278
313
  /**
279
314
  * Hook after built
@@ -282,7 +317,7 @@ export interface PluginOptions {
282
317
  *
283
318
  * @default () => {}
284
319
  */
285
- afterBuild?: () => void | Promise<void>
320
+ afterBuild?: () => MaybePromise<void>
286
321
  }
287
322
  ```
288
323
 
package/README.zh-CN.md CHANGED
@@ -15,7 +15,7 @@
15
15
  ## 安装
16
16
 
17
17
  ```sh
18
- pnpm add vite-plugin-dts -D
18
+ pnpm i vite-plugin-dts -D
19
19
  ```
20
20
 
21
21
  ## 使用
@@ -59,8 +59,7 @@ export default defineComponent({
59
59
 
60
60
  ```vue
61
61
  <script setup lang="ts">
62
- // 尽管没有直接使用 props,你仍需要接收 defineProps 的返回值
63
- const props = defineProps<{
62
+ defineProps<{
64
63
  color: 'blue' | 'red'
65
64
  }>()
66
65
  </script>
@@ -107,9 +106,30 @@ const props = defineProps<{
107
106
  import type ts from 'typescript'
108
107
  import type { LogLevel } from 'vite'
109
108
 
110
- interface TransformWriteFile {
111
- filePath?: string
112
- content?: string
109
+ type MaybePromise<T> = T | Promise<T>
110
+
111
+ export interface Resolver {
112
+ /**
113
+ * 解析器的名称
114
+ *
115
+ * 靠后的同名解析器将会覆盖靠前的
116
+ */
117
+ name: string,
118
+ /**
119
+ * 决定是否要解析文件
120
+ */
121
+ supports: (id: string) => void | boolean,
122
+ /**
123
+ * 将源文件转换为类型文件
124
+ */
125
+ transform: (payload: {
126
+ id: string,
127
+ code: string,
128
+ root: string,
129
+ host: ts.CompilerHost,
130
+ program: ts.Program,
131
+ service: ts.LanguageService
132
+ }) => MaybePromise<{ path: string, content: string }[]>
113
133
  }
114
134
 
115
135
  export interface PluginOptions {
@@ -118,7 +138,7 @@ export interface PluginOptions {
118
138
  *
119
139
  * 默认基于 Vite 配置的 'root',使用 Rollup 时基于 `process.cwd()`
120
140
  */
121
- root?: string
141
+ root?: string,
122
142
 
123
143
  /**
124
144
  * 指定输出目录
@@ -127,7 +147,7 @@ export interface PluginOptions {
127
147
  *
128
148
  * 默认基于 Vite 配置的 'build.outDir',使用 Rollup 时基于 tsconfig.json 的 `outDir`
129
149
  */
130
- outDir?: string | string[]
150
+ outDir?: string | string[],
131
151
 
132
152
  /**
133
153
  * 用于手动设置入口文件的根路径,通常用在 monorepo
@@ -136,7 +156,7 @@ export interface PluginOptions {
136
156
  *
137
157
  * 默认为所有文件的最小公共路径
138
158
  */
139
- entryRoot?: string
159
+ entryRoot?: string,
140
160
 
141
161
  /**
142
162
  * 严格限制类型文件生产在 `outDir` 内
@@ -145,14 +165,14 @@ export interface PluginOptions {
145
165
  *
146
166
  * @default true
147
167
  */
148
- strictOutput?: boolean
168
+ strictOutput?: boolean,
149
169
 
150
170
  /**
151
171
  * 指定一个用于覆写的 CompilerOptions
152
172
  *
153
173
  * @default null
154
174
  */
155
- compilerOptions?: ts.CompilerOptions | null
175
+ compilerOptions?: ts.CompilerOptions | null,
156
176
 
157
177
  /**
158
178
  * 指定 tsconfig.json 的路径
@@ -161,21 +181,28 @@ export interface PluginOptions {
161
181
  *
162
182
  * 未指定时插件默认从根目录寻找配置
163
183
  */
164
- tsconfigPath?: string
184
+ tsconfigPath?: string,
185
+
186
+ /**
187
+ * 指定自定义的解析器
188
+ *
189
+ * @default []
190
+ */
191
+ resolvers?: Resolver[],
165
192
 
166
193
  /**
167
194
  * 设置在转换别名时哪些路径需要排除
168
195
  *
169
196
  * @default []
170
197
  */
171
- aliasesExclude?: (string | RegExp)[]
198
+ aliasesExclude?: (string | RegExp)[],
172
199
 
173
200
  /**
174
201
  * 是否将 '.vue.d.ts' 文件名转换为 '.d.ts'
175
202
  *
176
203
  * @default false
177
204
  */
178
- cleanVueFileName?: boolean
205
+ cleanVueFileName?: boolean,
179
206
 
180
207
  /**
181
208
  * 是否将动态引入转换为静态
@@ -186,28 +213,28 @@ export interface PluginOptions {
186
213
  *
187
214
  * @default false
188
215
  */
189
- staticImport?: boolean
216
+ staticImport?: boolean,
190
217
 
191
218
  /**
192
219
  * 手动设置包含路径的 glob
193
220
  *
194
221
  * 默认基于 tsconfig.json 的 `include` 选项
195
222
  */
196
- include?: string | string[]
223
+ include?: string | string[],
197
224
 
198
225
  /**
199
226
  * 手动设置排除路径的 glob
200
227
  *
201
228
  * 默认基于 tsconfig.json 的 `exclude` 选线,未设置时为 `'node_module/**'`
202
229
  */
203
- exclude?: string | string[]
230
+ exclude?: string | string[],
204
231
 
205
232
  /**
206
233
  * 是否移除那些 `import 'xxx'`
207
234
  *
208
235
  * @default true
209
236
  */
210
- clearPureImport?: boolean
237
+ clearPureImport?: boolean,
211
238
 
212
239
  /**
213
240
  * 是否生成类型声明入口
@@ -218,7 +245,7 @@ export interface PluginOptions {
218
245
  *
219
246
  * @default false
220
247
  */
221
- insertTypesEntry?: boolean
248
+ insertTypesEntry?: boolean,
222
249
 
223
250
  /**
224
251
  * 设置是否在发出类型文件后将其打包
@@ -227,7 +254,7 @@ export interface PluginOptions {
227
254
  *
228
255
  * @default false
229
256
  */
230
- rollupTypes?: boolean
257
+ rollupTypes?: boolean,
231
258
 
232
259
  /**
233
260
  * 设置 `@microsoft/api-extractor` 的 `bundledPackages` 选项
@@ -235,7 +262,7 @@ export interface PluginOptions {
235
262
  * @default []
236
263
  * @see https://api-extractor.com/pages/configs/api-extractor_json/#bundledpackages
237
264
  */
238
- bundledPackages?: string[]
265
+ bundledPackages?: string[],
239
266
 
240
267
  /**
241
268
  * 是否将源码里的 .d.ts 文件复制到 `outDir`
@@ -243,14 +270,14 @@ export interface PluginOptions {
243
270
  * @default false
244
271
  * @remarks 在 2.0 之前它默认为 true
245
272
  */
246
- copyDtsFiles?: boolean
273
+ copyDtsFiles?: boolean,
247
274
 
248
275
  /**
249
276
  * 指定插件的输出等级
250
277
  *
251
278
  * 默认基于 Vite 配置的 'logLevel' 选项
252
279
  */
253
- logLevel?: LogLevel
280
+ logLevel?: LogLevel,
254
281
 
255
282
  /**
256
283
  * 获取诊断信息后的钩子
@@ -259,7 +286,7 @@ export interface PluginOptions {
259
286
  *
260
287
  * @default () => {}
261
288
  */
262
- afterDiagnostic?: (diagnostics: Diagnostic[]) => void | Promise<void>
289
+ afterDiagnostic?: (diagnostics: readonly ts.Diagnostic[]) => MaybePromise<void>,
263
290
 
264
291
  /**
265
292
  * 类型声明文件被写入前的钩子
@@ -270,7 +297,16 @@ export interface PluginOptions {
270
297
  *
271
298
  * @default () => {}
272
299
  */
273
- beforeWriteFile?: (filePath: string, content: string) => void | false | TransformWriteFile
300
+ beforeWriteFile?: (
301
+ filePath: string,
302
+ content: string
303
+ ) =>
304
+ | void
305
+ | false
306
+ | {
307
+ filePath?: string,
308
+ content?: string
309
+ },
274
310
 
275
311
  /**
276
312
  * 构建后回调钩子
@@ -279,7 +315,7 @@ export interface PluginOptions {
279
315
  *
280
316
  * @default () => {}
281
317
  */
282
- afterBuild?: () => void | Promise<void>
318
+ afterBuild?: () => MaybePromise<void>
283
319
  }
284
320
  ```
285
321
 
package/dist/index.cjs CHANGED
@@ -4,9 +4,9 @@ const node_path = require('node:path');
4
4
  const node_fs = require('node:fs');
5
5
  const promises = require('node:fs/promises');
6
6
  const node_os = require('node:os');
7
+ const languageCore = require('@vue/language-core');
7
8
  const ts = require('typescript');
8
9
  const pluginutils = require('@rollup/pluginutils');
9
- const languageCore = require('@vue/language-core');
10
10
  const vueTsc = require('vue-tsc');
11
11
  const debug = require('debug');
12
12
  const kolorist = require('kolorist');
@@ -25,6 +25,7 @@ const debug__default = /*#__PURE__*/_interopDefaultCompat(debug);
25
25
  const dtsRE$1 = /\.d\.tsx?$/;
26
26
  function rollupDeclarationFiles({
27
27
  root,
28
+ configPath,
28
29
  compilerOptions,
29
30
  outDir,
30
31
  entryPath,
@@ -44,7 +45,7 @@ function rollupDeclarationFiles({
44
45
  mainEntryPointFilePath: entryPath,
45
46
  bundledPackages,
46
47
  compiler: {
47
- // tsconfigFilePath: tsConfigPath,
48
+ tsconfigFilePath: configPath,
48
49
  overrideTsconfig: {
49
50
  $schema: "http://json.schemastore.org/tsconfig",
50
51
  compilerOptions: {
@@ -86,7 +87,7 @@ function rollupDeclarationFiles({
86
87
  const compilerState = apiExtractor.CompilerState.create(extractorConfig, {
87
88
  localBuild: false,
88
89
  showVerboseMessages: false,
89
- typescriptCompilerFolder: libFolder ? node_path.resolve(libFolder, "..") : void 0
90
+ typescriptCompilerFolder: libFolder ? node_path.resolve(libFolder) : void 0
90
91
  });
91
92
  const sourceMapper = new SourceMapper_js.SourceMapper();
92
93
  const messageRouter = new MessageRouter_js.MessageRouter({
@@ -113,13 +114,33 @@ function rollupDeclarationFiles({
113
114
  );
114
115
  }
115
116
 
116
- const windowsSlashRE = /\\/g;
117
+ const svelteRE = /\.svelte$/;
118
+ function SvelteResolver() {
119
+ return {
120
+ name: "svelte",
121
+ supports(id) {
122
+ return svelteRE.test(id);
123
+ },
124
+ transform({ id }) {
125
+ return [
126
+ {
127
+ path: `${id}.d.ts`,
128
+ content: "export { SvelteComponentTyped as default } from 'svelte';"
129
+ }
130
+ ];
131
+ }
132
+ };
133
+ }
134
+
135
+ const windowsSlashRE = /\\+/g;
117
136
  function slash(p) {
118
137
  return p.replace(windowsSlashRE, "/");
119
138
  }
120
- const isWindows = node_os.platform() === "win32";
121
139
  function normalizePath(id) {
122
- return node_path.posix.normalize(isWindows ? slash(id) : id);
140
+ return node_path.posix.normalize(slash(id));
141
+ }
142
+ function resolve(...paths) {
143
+ return normalizePath(node_path.resolve(...paths));
123
144
  }
124
145
  function isNativeObj(value) {
125
146
  return Object.prototype.toString.call(value) === "[object Object]";
@@ -131,7 +152,7 @@ function isPromise(value) {
131
152
  return !!value && (typeof value === "function" || typeof value === "object") && typeof value.then === "function";
132
153
  }
133
154
  function ensureAbsolute(path, root) {
134
- return normalizePath(path ? node_path.isAbsolute(path) ? path : node_path.resolve(root, path) : root);
155
+ return normalizePath(path ? node_path.isAbsolute(path) ? path : resolve(root, path) : root);
135
156
  }
136
157
  function ensureArray(value) {
137
158
  return Array.isArray(value) ? value : value ? [value] : [];
@@ -196,7 +217,7 @@ function removeDirIfEmpty(dir) {
196
217
  }
197
218
  let onlyHasDir = true;
198
219
  for (const file of node_fs.readdirSync(dir)) {
199
- const abs = node_path.resolve(dir, file);
220
+ const abs = resolve(dir, file);
200
221
  if (node_fs.lstatSync(abs).isDirectory()) {
201
222
  if (!removeDirIfEmpty(abs)) {
202
223
  onlyHasDir = false;
@@ -211,6 +232,38 @@ function removeDirIfEmpty(dir) {
211
232
  return onlyHasDir;
212
233
  }
213
234
 
235
+ const vueRE = /\.vue$/;
236
+ function VueResolver() {
237
+ return {
238
+ name: "vue",
239
+ supports(id) {
240
+ return vueRE.test(id);
241
+ },
242
+ transform({ id, root, program, service }) {
243
+ let sourceFile = program.getSourceFile(id);
244
+ if (!sourceFile && vueRE.test(id)) {
245
+ sourceFile = program.getSourceFile(id + ".ts") || program.getSourceFile(id + ".js") || program.getSourceFile(id + ".tsx") || program.getSourceFile(id + ".jsx");
246
+ }
247
+ if (!sourceFile)
248
+ return [];
249
+ return service.getEmitOutput(sourceFile.fileName, true).outputFiles.map((file) => {
250
+ return {
251
+ path: resolve(root, file.name),
252
+ content: file.text
253
+ };
254
+ });
255
+ }
256
+ };
257
+ }
258
+
259
+ function parseResolvers(resolvers) {
260
+ const nameMap = /* @__PURE__ */ new Map();
261
+ for (const resolver of resolvers) {
262
+ resolver.name && nameMap.set(resolver.name, resolver);
263
+ }
264
+ return Array.from(nameMap.values());
265
+ }
266
+
214
267
  const globSuffixRE = /^((?:.*\.[^.]+)|(?:\*+))$/;
215
268
  function normalizeGlob(path) {
216
269
  if (/[\\/]$/.test(path)) {
@@ -309,7 +362,6 @@ function removePureImport(content) {
309
362
  return content.replace(pureImportRE, "");
310
363
  }
311
364
 
312
- const vueRE = /\.vue$/;
313
365
  const jsRE = /\.(m|c)?jsx?$/;
314
366
  const tsRE = /\.(m|c)?tsx?$/;
315
367
  const dtsRE = /\.d\.(m|c)?tsx?$/;
@@ -317,7 +369,6 @@ const tjsRE = /\.(m|c)?(t|j)sx?$/;
317
369
  const mtjsRE = /\.m(t|j)sx?$/;
318
370
  const ctjsRE = /\.c(t|j)sx?$/;
319
371
  const fullRelativeRE = /^\.\.?\//;
320
- const watchExtensionRE = /\.(vue|(m|c)?(t|j)sx?)$/;
321
372
  const defaultIndex = "index.d.ts";
322
373
  const logPrefix = kolorist.cyan("[vite:dts]");
323
374
  const bundleDebug = debug__default("vite-plugin-dts:bundle");
@@ -335,7 +386,6 @@ const fixedCompilerOptions = {
335
386
  const noop = () => {
336
387
  };
337
388
  const extPrefix = (file) => mtjsRE.test(file) ? "m" : ctjsRE.test(file) ? "c" : "";
338
- const resolve = (...paths) => normalizePath(node_path.resolve(...paths));
339
389
  function dtsPlugin(options = {}) {
340
390
  const {
341
391
  tsconfigPath,
@@ -356,6 +406,7 @@ function dtsPlugin(options = {}) {
356
406
  let root = ensureAbsolute(options.root ?? "", process.cwd());
357
407
  let publicRoot = "";
358
408
  let entryRoot = options.entryRoot ?? "";
409
+ let configPath;
359
410
  let compilerOptions;
360
411
  let rawCompilerOptions;
361
412
  let outDirs;
@@ -371,6 +422,7 @@ function dtsPlugin(options = {}) {
371
422
  let filter;
372
423
  let bundled = false;
373
424
  let timeRecord = 0;
425
+ const resolvers = parseResolvers([VueResolver(), SvelteResolver(), ...options.resolvers || []]);
374
426
  const rootFiles = /* @__PURE__ */ new Set();
375
427
  const outputFiles = /* @__PURE__ */ new Map();
376
428
  return {
@@ -455,7 +507,7 @@ ${kolorist.cyan(
455
507
  bundleDebug("begin buildStart");
456
508
  timeRecord = 0;
457
509
  const startTime = Date.now();
458
- const configPath = tsconfigPath ? ensureAbsolute(tsconfigPath, root) : ts__default.findConfigFile(root, ts__default.sys.fileExists);
510
+ configPath = tsconfigPath ? ensureAbsolute(tsconfigPath, root) : ts__default.findConfigFile(root, ts__default.sys.fileExists);
459
511
  const content = configPath ? languageCore.createParsedCommandLine(ts__default, ts__default.sys, configPath) : void 0;
460
512
  compilerOptions = {
461
513
  ...content?.options || {},
@@ -501,37 +553,51 @@ ${kolorist.cyan(
501
553
  bundleDebug("create ts program");
502
554
  timeRecord += Date.now() - startTime;
503
555
  },
504
- transform(_, id) {
505
- if (!program || !filter(id) || id.includes(".vue?vue") || !tjsRE.test(id) && !vueRE.test(id)) {
556
+ async transform(code, id) {
557
+ let resolver;
558
+ id = normalizePath(id).split("?")[0];
559
+ if (!host || !program || !filter(id) || !(resolver = resolvers.find((r) => r.supports(id))) && !tjsRE.test(id)) {
506
560
  return;
507
561
  }
508
562
  const startTime = Date.now();
509
- id = normalizePath(id);
510
- rootFiles.delete(id);
511
- let sourceFile = program.getSourceFile(normalizePath(id));
512
- if (!sourceFile && vueRE.test(id)) {
513
- sourceFile = program.getSourceFile(id + ".ts") || program.getSourceFile(id + ".js") || program.getSourceFile(id + ".tsx") || program.getSourceFile(id + ".jsx");
514
- }
515
- if (!sourceFile)
516
- return;
517
563
  const service = program.__vue.languageService;
518
- for (const outputFile of service.getEmitOutput(sourceFile.fileName, true).outputFiles) {
519
- outputFiles.set(resolve(publicRoot, outputFile.name), outputFile.text);
564
+ rootFiles.delete(id);
565
+ if (resolver) {
566
+ const result = await resolver.transform({
567
+ id,
568
+ code,
569
+ root: publicRoot,
570
+ host,
571
+ program,
572
+ service
573
+ });
574
+ for (const { path, content } of result) {
575
+ outputFiles.set(ensureAbsolute(path, publicRoot), content);
576
+ }
577
+ } else {
578
+ const sourceFile = program.getSourceFile(id);
579
+ if (sourceFile) {
580
+ for (const outputFile of service.getEmitOutput(sourceFile.fileName, true).outputFiles) {
581
+ outputFiles.set(resolve(publicRoot, outputFile.name), outputFile.text);
582
+ }
583
+ }
520
584
  }
521
- const dtsId = id.replace(tjsRE, ".d.ts");
585
+ const dtsId = id.replace(tjsRE, "") + ".d.ts";
522
586
  const dtsSourceFile = program.getSourceFile(dtsId);
523
587
  dtsSourceFile && filter(dtsSourceFile.fileName) && outputFiles.set(normalizePath(dtsSourceFile.fileName), dtsSourceFile.getFullText());
524
588
  timeRecord += Date.now() - startTime;
525
589
  },
526
590
  watchChange(id) {
527
- if (host && program && watchExtensionRE.test(id)) {
528
- const sourceFile = host.getSourceFile(normalizePath(id), ts__default.ScriptTarget.ESNext);
529
- if (sourceFile && filter(sourceFile.fileName)) {
530
- !vueRE.test(id) && rootFiles.add(sourceFile.fileName);
531
- program.__vue.projectVersion++;
532
- bundled = false;
533
- timeRecord = 0;
534
- }
591
+ id = normalizePath(id).split("?")[0];
592
+ if (!host || !program || !filter(id) || !resolvers.find((r) => r.supports(id)) && !tjsRE.test(id)) {
593
+ return;
594
+ }
595
+ const sourceFile = host.getSourceFile(normalizePath(id), ts__default.ScriptTarget.ESNext);
596
+ if (sourceFile) {
597
+ rootFiles.add(sourceFile.fileName);
598
+ program.__vue.projectVersion++;
599
+ bundled = false;
600
+ timeRecord = 0;
535
601
  }
536
602
  },
537
603
  async writeBundle() {
@@ -658,6 +724,7 @@ export default ${libName}
658
724
  const path = resolve(outDir, `${name.replace(tsRE, "")}.d.ts`);
659
725
  rollupDeclarationFiles({
660
726
  root,
727
+ configPath,
661
728
  compilerOptions: rawCompilerOptions,
662
729
  outDir,
663
730
  entryPath: path,
@@ -671,6 +738,7 @@ export default ${libName}
671
738
  } else {
672
739
  rollupDeclarationFiles({
673
740
  root,
741
+ configPath,
674
742
  compilerOptions: rawCompilerOptions,
675
743
  outDir,
676
744
  entryPath: typesPath,
package/dist/index.d.ts CHANGED
@@ -2,9 +2,32 @@ import * as vite from 'vite';
2
2
  import { LogLevel } from 'vite';
3
3
  import ts from 'typescript';
4
4
 
5
- interface TransformWriteFile {
6
- filePath?: string;
7
- content?: string;
5
+ type MaybePromise<T> = T | Promise<T>;
6
+ interface Resolver {
7
+ /**
8
+ * The name of the resolver
9
+ *
10
+ * The later resolver with the same name will overwrite the earlier
11
+ */
12
+ name: string;
13
+ /**
14
+ * Determine whether the resolve supports the file
15
+ */
16
+ supports: (id: string) => void | boolean;
17
+ /**
18
+ * Transform the source file to declaration files
19
+ */
20
+ transform: (payload: {
21
+ id: string;
22
+ code: string;
23
+ root: string;
24
+ host: ts.CompilerHost;
25
+ program: ts.Program;
26
+ service: ts.LanguageService;
27
+ }) => MaybePromise<{
28
+ path: string;
29
+ content: string;
30
+ }[]>;
8
31
  }
9
32
  interface PluginOptions {
10
33
  /**
@@ -51,6 +74,12 @@ interface PluginOptions {
51
74
  * By default plugin will find config form root if not specify
52
75
  */
53
76
  tsconfigPath?: string;
77
+ /**
78
+ * Specify custom resolvers
79
+ *
80
+ * @default []
81
+ */
82
+ resolvers?: Resolver[];
54
83
  /**
55
84
  * Set which paths should exclude when transform aliases
56
85
  *
@@ -138,7 +167,7 @@ interface PluginOptions {
138
167
  *
139
168
  * @default () => {}
140
169
  */
141
- afterDiagnostic?: (diagnostics: readonly ts.Diagnostic[]) => void | Promise<void>;
170
+ afterDiagnostic?: (diagnostics: readonly ts.Diagnostic[]) => MaybePromise<void>;
142
171
  /**
143
172
  * Hook before each declaration file is written
144
173
  *
@@ -148,7 +177,10 @@ interface PluginOptions {
148
177
  *
149
178
  * @default () => {}
150
179
  */
151
- beforeWriteFile?: (filePath: string, content: string) => void | false | TransformWriteFile;
180
+ beforeWriteFile?: (filePath: string, content: string) => void | false | {
181
+ filePath?: string;
182
+ content?: string;
183
+ };
152
184
  /**
153
185
  * Hook after built
154
186
  *
@@ -156,7 +188,7 @@ interface PluginOptions {
156
188
  *
157
189
  * @default () => {}
158
190
  */
159
- afterBuild?: () => void | Promise<void>;
191
+ afterBuild?: () => MaybePromise<void>;
160
192
  }
161
193
 
162
194
  declare function dtsPlugin(options?: PluginOptions): vite.Plugin;
package/dist/index.mjs CHANGED
@@ -8,10 +8,10 @@ const require = __cjs_mod__.createRequire(import.meta.url);
8
8
  import { resolve as resolve$1, posix, isAbsolute, dirname, normalize, sep, relative, basename } from 'node:path';
9
9
  import { existsSync, readdirSync, lstatSync, rmdirSync } from 'node:fs';
10
10
  import { readFile, mkdir, writeFile, unlink } from 'node:fs/promises';
11
- import { platform, cpus } from 'node:os';
11
+ import { cpus } from 'node:os';
12
+ import { createParsedCommandLine } from '@vue/language-core';
12
13
  import ts from 'typescript';
13
14
  import { createFilter } from '@rollup/pluginutils';
14
- import { createParsedCommandLine } from '@vue/language-core';
15
15
  import { createProgram } from 'vue-tsc';
16
16
  import debug from 'debug';
17
17
  import { cyan, yellow, green } from 'kolorist';
@@ -25,6 +25,7 @@ import { PackageJsonLookup } from '@rushstack/node-core-library';
25
25
  const dtsRE$1 = /\.d\.tsx?$/;
26
26
  function rollupDeclarationFiles({
27
27
  root,
28
+ configPath,
28
29
  compilerOptions,
29
30
  outDir,
30
31
  entryPath,
@@ -44,7 +45,7 @@ function rollupDeclarationFiles({
44
45
  mainEntryPointFilePath: entryPath,
45
46
  bundledPackages,
46
47
  compiler: {
47
- // tsconfigFilePath: tsConfigPath,
48
+ tsconfigFilePath: configPath,
48
49
  overrideTsconfig: {
49
50
  $schema: "http://json.schemastore.org/tsconfig",
50
51
  compilerOptions: {
@@ -86,7 +87,7 @@ function rollupDeclarationFiles({
86
87
  const compilerState = CompilerState.create(extractorConfig, {
87
88
  localBuild: false,
88
89
  showVerboseMessages: false,
89
- typescriptCompilerFolder: libFolder ? resolve$1(libFolder, "..") : void 0
90
+ typescriptCompilerFolder: libFolder ? resolve$1(libFolder) : void 0
90
91
  });
91
92
  const sourceMapper = new SourceMapper();
92
93
  const messageRouter = new MessageRouter({
@@ -113,13 +114,33 @@ function rollupDeclarationFiles({
113
114
  );
114
115
  }
115
116
 
116
- const windowsSlashRE = /\\/g;
117
+ const svelteRE = /\.svelte$/;
118
+ function SvelteResolver() {
119
+ return {
120
+ name: "svelte",
121
+ supports(id) {
122
+ return svelteRE.test(id);
123
+ },
124
+ transform({ id }) {
125
+ return [
126
+ {
127
+ path: `${id}.d.ts`,
128
+ content: "export { SvelteComponentTyped as default } from 'svelte';"
129
+ }
130
+ ];
131
+ }
132
+ };
133
+ }
134
+
135
+ const windowsSlashRE = /\\+/g;
117
136
  function slash(p) {
118
137
  return p.replace(windowsSlashRE, "/");
119
138
  }
120
- const isWindows = platform() === "win32";
121
139
  function normalizePath(id) {
122
- return posix.normalize(isWindows ? slash(id) : id);
140
+ return posix.normalize(slash(id));
141
+ }
142
+ function resolve(...paths) {
143
+ return normalizePath(resolve$1(...paths));
123
144
  }
124
145
  function isNativeObj(value) {
125
146
  return Object.prototype.toString.call(value) === "[object Object]";
@@ -131,7 +152,7 @@ function isPromise(value) {
131
152
  return !!value && (typeof value === "function" || typeof value === "object") && typeof value.then === "function";
132
153
  }
133
154
  function ensureAbsolute(path, root) {
134
- return normalizePath(path ? isAbsolute(path) ? path : resolve$1(root, path) : root);
155
+ return normalizePath(path ? isAbsolute(path) ? path : resolve(root, path) : root);
135
156
  }
136
157
  function ensureArray(value) {
137
158
  return Array.isArray(value) ? value : value ? [value] : [];
@@ -196,7 +217,7 @@ function removeDirIfEmpty(dir) {
196
217
  }
197
218
  let onlyHasDir = true;
198
219
  for (const file of readdirSync(dir)) {
199
- const abs = resolve$1(dir, file);
220
+ const abs = resolve(dir, file);
200
221
  if (lstatSync(abs).isDirectory()) {
201
222
  if (!removeDirIfEmpty(abs)) {
202
223
  onlyHasDir = false;
@@ -211,6 +232,38 @@ function removeDirIfEmpty(dir) {
211
232
  return onlyHasDir;
212
233
  }
213
234
 
235
+ const vueRE = /\.vue$/;
236
+ function VueResolver() {
237
+ return {
238
+ name: "vue",
239
+ supports(id) {
240
+ return vueRE.test(id);
241
+ },
242
+ transform({ id, root, program, service }) {
243
+ let sourceFile = program.getSourceFile(id);
244
+ if (!sourceFile && vueRE.test(id)) {
245
+ sourceFile = program.getSourceFile(id + ".ts") || program.getSourceFile(id + ".js") || program.getSourceFile(id + ".tsx") || program.getSourceFile(id + ".jsx");
246
+ }
247
+ if (!sourceFile)
248
+ return [];
249
+ return service.getEmitOutput(sourceFile.fileName, true).outputFiles.map((file) => {
250
+ return {
251
+ path: resolve(root, file.name),
252
+ content: file.text
253
+ };
254
+ });
255
+ }
256
+ };
257
+ }
258
+
259
+ function parseResolvers(resolvers) {
260
+ const nameMap = /* @__PURE__ */ new Map();
261
+ for (const resolver of resolvers) {
262
+ resolver.name && nameMap.set(resolver.name, resolver);
263
+ }
264
+ return Array.from(nameMap.values());
265
+ }
266
+
214
267
  const globSuffixRE = /^((?:.*\.[^.]+)|(?:\*+))$/;
215
268
  function normalizeGlob(path) {
216
269
  if (/[\\/]$/.test(path)) {
@@ -309,7 +362,6 @@ function removePureImport(content) {
309
362
  return content.replace(pureImportRE, "");
310
363
  }
311
364
 
312
- const vueRE = /\.vue$/;
313
365
  const jsRE = /\.(m|c)?jsx?$/;
314
366
  const tsRE = /\.(m|c)?tsx?$/;
315
367
  const dtsRE = /\.d\.(m|c)?tsx?$/;
@@ -317,7 +369,6 @@ const tjsRE = /\.(m|c)?(t|j)sx?$/;
317
369
  const mtjsRE = /\.m(t|j)sx?$/;
318
370
  const ctjsRE = /\.c(t|j)sx?$/;
319
371
  const fullRelativeRE = /^\.\.?\//;
320
- const watchExtensionRE = /\.(vue|(m|c)?(t|j)sx?)$/;
321
372
  const defaultIndex = "index.d.ts";
322
373
  const logPrefix = cyan("[vite:dts]");
323
374
  const bundleDebug = debug("vite-plugin-dts:bundle");
@@ -335,7 +386,6 @@ const fixedCompilerOptions = {
335
386
  const noop = () => {
336
387
  };
337
388
  const extPrefix = (file) => mtjsRE.test(file) ? "m" : ctjsRE.test(file) ? "c" : "";
338
- const resolve = (...paths) => normalizePath(resolve$1(...paths));
339
389
  function dtsPlugin(options = {}) {
340
390
  const {
341
391
  tsconfigPath,
@@ -356,6 +406,7 @@ function dtsPlugin(options = {}) {
356
406
  let root = ensureAbsolute(options.root ?? "", process.cwd());
357
407
  let publicRoot = "";
358
408
  let entryRoot = options.entryRoot ?? "";
409
+ let configPath;
359
410
  let compilerOptions;
360
411
  let rawCompilerOptions;
361
412
  let outDirs;
@@ -371,6 +422,7 @@ function dtsPlugin(options = {}) {
371
422
  let filter;
372
423
  let bundled = false;
373
424
  let timeRecord = 0;
425
+ const resolvers = parseResolvers([VueResolver(), SvelteResolver(), ...options.resolvers || []]);
374
426
  const rootFiles = /* @__PURE__ */ new Set();
375
427
  const outputFiles = /* @__PURE__ */ new Map();
376
428
  return {
@@ -455,7 +507,7 @@ ${cyan(
455
507
  bundleDebug("begin buildStart");
456
508
  timeRecord = 0;
457
509
  const startTime = Date.now();
458
- const configPath = tsconfigPath ? ensureAbsolute(tsconfigPath, root) : ts.findConfigFile(root, ts.sys.fileExists);
510
+ configPath = tsconfigPath ? ensureAbsolute(tsconfigPath, root) : ts.findConfigFile(root, ts.sys.fileExists);
459
511
  const content = configPath ? createParsedCommandLine(ts, ts.sys, configPath) : void 0;
460
512
  compilerOptions = {
461
513
  ...content?.options || {},
@@ -501,37 +553,51 @@ ${cyan(
501
553
  bundleDebug("create ts program");
502
554
  timeRecord += Date.now() - startTime;
503
555
  },
504
- transform(_, id) {
505
- if (!program || !filter(id) || id.includes(".vue?vue") || !tjsRE.test(id) && !vueRE.test(id)) {
556
+ async transform(code, id) {
557
+ let resolver;
558
+ id = normalizePath(id).split("?")[0];
559
+ if (!host || !program || !filter(id) || !(resolver = resolvers.find((r) => r.supports(id))) && !tjsRE.test(id)) {
506
560
  return;
507
561
  }
508
562
  const startTime = Date.now();
509
- id = normalizePath(id);
510
- rootFiles.delete(id);
511
- let sourceFile = program.getSourceFile(normalizePath(id));
512
- if (!sourceFile && vueRE.test(id)) {
513
- sourceFile = program.getSourceFile(id + ".ts") || program.getSourceFile(id + ".js") || program.getSourceFile(id + ".tsx") || program.getSourceFile(id + ".jsx");
514
- }
515
- if (!sourceFile)
516
- return;
517
563
  const service = program.__vue.languageService;
518
- for (const outputFile of service.getEmitOutput(sourceFile.fileName, true).outputFiles) {
519
- outputFiles.set(resolve(publicRoot, outputFile.name), outputFile.text);
564
+ rootFiles.delete(id);
565
+ if (resolver) {
566
+ const result = await resolver.transform({
567
+ id,
568
+ code,
569
+ root: publicRoot,
570
+ host,
571
+ program,
572
+ service
573
+ });
574
+ for (const { path, content } of result) {
575
+ outputFiles.set(ensureAbsolute(path, publicRoot), content);
576
+ }
577
+ } else {
578
+ const sourceFile = program.getSourceFile(id);
579
+ if (sourceFile) {
580
+ for (const outputFile of service.getEmitOutput(sourceFile.fileName, true).outputFiles) {
581
+ outputFiles.set(resolve(publicRoot, outputFile.name), outputFile.text);
582
+ }
583
+ }
520
584
  }
521
- const dtsId = id.replace(tjsRE, ".d.ts");
585
+ const dtsId = id.replace(tjsRE, "") + ".d.ts";
522
586
  const dtsSourceFile = program.getSourceFile(dtsId);
523
587
  dtsSourceFile && filter(dtsSourceFile.fileName) && outputFiles.set(normalizePath(dtsSourceFile.fileName), dtsSourceFile.getFullText());
524
588
  timeRecord += Date.now() - startTime;
525
589
  },
526
590
  watchChange(id) {
527
- if (host && program && watchExtensionRE.test(id)) {
528
- const sourceFile = host.getSourceFile(normalizePath(id), ts.ScriptTarget.ESNext);
529
- if (sourceFile && filter(sourceFile.fileName)) {
530
- !vueRE.test(id) && rootFiles.add(sourceFile.fileName);
531
- program.__vue.projectVersion++;
532
- bundled = false;
533
- timeRecord = 0;
534
- }
591
+ id = normalizePath(id).split("?")[0];
592
+ if (!host || !program || !filter(id) || !resolvers.find((r) => r.supports(id)) && !tjsRE.test(id)) {
593
+ return;
594
+ }
595
+ const sourceFile = host.getSourceFile(normalizePath(id), ts.ScriptTarget.ESNext);
596
+ if (sourceFile) {
597
+ rootFiles.add(sourceFile.fileName);
598
+ program.__vue.projectVersion++;
599
+ bundled = false;
600
+ timeRecord = 0;
535
601
  }
536
602
  },
537
603
  async writeBundle() {
@@ -658,6 +724,7 @@ export default ${libName}
658
724
  const path = resolve(outDir, `${name.replace(tsRE, "")}.d.ts`);
659
725
  rollupDeclarationFiles({
660
726
  root,
727
+ configPath,
661
728
  compilerOptions: rawCompilerOptions,
662
729
  outDir,
663
730
  entryPath: path,
@@ -671,6 +738,7 @@ export default ${libName}
671
738
  } else {
672
739
  rollupDeclarationFiles({
673
740
  root,
741
+ configPath,
674
742
  compilerOptions: rawCompilerOptions,
675
743
  outDir,
676
744
  entryPath: typesPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-dts",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "qmhc",
@@ -9,17 +9,16 @@
9
9
  "build": "tsx scripts/build.ts",
10
10
  "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s --commit-path .",
11
11
  "dev": "unbuild --stub",
12
- "lint": "pnpm run lint:src && pnpm run lint:example",
13
- "lint:src": "eslint --fix --ext .js,.jsx,.ts,.tsx,.vue src/**",
14
- "lint:example": "eslint --fix --ext .js,.jsx,.ts,.tsx,.vue example/{src,components}/**",
12
+ "lint": "eslint --ext .js,.jsx,.ts,.tsx \"{src,tests}/**\"",
15
13
  "_postinstall": "is-ci || husky install",
16
14
  "postpublish": "pinst --enable",
17
15
  "precommit": "lint-staged -c ./.husky/.lintstagedrc -q",
18
16
  "prepublishOnly": "pinst --disable",
19
- "prettier": "pretty-quick --staged",
17
+ "prettier": "pretty-quick --staged && pnpm run lint",
20
18
  "release": "tsx scripts/release.ts",
21
19
  "test": "vitest run",
22
20
  "test:react": "pnpm -C examples/react build",
21
+ "test:svelte": "pnpm -C examples/svelte build",
23
22
  "test:ts": "pnpm -C examples/ts build",
24
23
  "test:vue": "pnpm -C examples/vue build"
25
24
  },
@@ -72,15 +71,14 @@
72
71
  "@types/semver": "^7.5.0",
73
72
  "@typescript-eslint/eslint-plugin": "^5.60.0",
74
73
  "@typescript-eslint/parser": "^5.60.0",
74
+ "@vexip-ui/commitlint-config": "^0.1.0",
75
+ "@vexip-ui/eslint-config": "^0.6.3",
76
+ "@vexip-ui/prettier-config": "^0.2.0",
75
77
  "@vue/eslint-config-standard": "^8.0.1",
76
78
  "@vue/eslint-config-typescript": "^11.0.3",
77
79
  "conventional-changelog-cli": "^3.0.0",
78
80
  "cross-env": "^7.0.3",
79
81
  "eslint": "^8.43.0",
80
- "eslint-plugin-import": "^2.27.5",
81
- "eslint-plugin-node": "^11.1.0",
82
- "eslint-plugin-promise": "^6.1.1",
83
- "eslint-plugin-vue": "^9.15.1",
84
82
  "execa": "^7.1.1",
85
83
  "husky": "^8.0.3",
86
84
  "is-ci": "^3.0.1",
@@ -93,7 +91,7 @@
93
91
  "rimraf": "^5.0.1",
94
92
  "semver": "^7.5.3",
95
93
  "tsx": "^3.12.7",
96
- "typescript": "^5.1.3",
94
+ "typescript": "5.0.4",
97
95
  "unbuild": "^1.2.1",
98
96
  "vite": "^4.3.9",
99
97
  "vitest": "^0.32.2"