vite-plugin-dts 2.0.0-beta.1 → 2.0.0-beta.2

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
@@ -112,6 +112,7 @@ This is a exist issue when TypeScript inferring types from packages which under
112
112
 
113
113
  ```ts
114
114
  import type { ts, Diagnostic } from 'ts-morph'
115
+ import type { LogLevel } from 'vite'
115
116
 
116
117
  interface TransformWriteFile {
117
118
  filePath?: string
@@ -122,7 +123,7 @@ export interface PluginOptions {
122
123
  /**
123
124
  * Depends on the root directory
124
125
  *
125
- * Defaults base on your vite config root options
126
+ * By Default it base on 'root' option of your vite config
126
127
  */
127
128
  root?: string
128
129
 
@@ -131,16 +132,16 @@ export interface PluginOptions {
131
132
  *
132
133
  * Can be specified a array to output to multiple directories
133
134
  *
134
- * Defaults base on your vite config output options
135
+ * By Default it base on 'build.outDir' option of your vite config
135
136
  */
136
137
  outputDir?: string | string[]
137
138
 
138
139
  /**
139
140
  * Manually set the root path of the entry files
140
141
  *
141
- * The output path of each file will be caculated base on it
142
+ * The output path of each file will be calculated base on it
142
143
  *
143
- * Defaults is the smallest public path for all files
144
+ * By Default it is the smallest public path for all files
144
145
  */
145
146
  entryRoot?: string
146
147
 
@@ -154,7 +155,7 @@ export interface PluginOptions {
154
155
  /**
155
156
  * Project init tsconfig.json file path by ts-morph
156
157
  *
157
- * Plugin also resolve incldue and exclude files from tsconfig.json
158
+ * Plugin also resolve include and exclude files from tsconfig.json
158
159
  *
159
160
  * @default 'tsconfig.json'
160
161
  */
@@ -190,14 +191,14 @@ export interface PluginOptions {
190
191
  /**
191
192
  * Manual set include glob
192
193
  *
193
- * Defaults base on your tsconfig.json include option
194
+ * By Default it base on 'include' option of the tsconfig.json
194
195
  */
195
196
  include?: string | string[]
196
197
 
197
198
  /**
198
199
  * Manual set exclude glob
199
200
  *
200
- * Defaults base on your tsconfig.json exclude option, be 'node_modules/**' when empty
201
+ * By Default it base on 'exclude' option of the tsconfig.json, be 'node_module/**' when empty
201
202
  */
202
203
  exclude?: string | string[]
203
204
 
@@ -253,16 +254,6 @@ export interface PluginOptions {
253
254
  */
254
255
  skipDiagnostics?: boolean
255
256
 
256
- /**
257
- * Whether log diagnostic informations
258
- *
259
- * Not effective when `skipDiagnostics` is true
260
- *
261
- * @deprecated
262
- * @default false
263
- */
264
- logDiagnostics?: boolean
265
-
266
257
  /**
267
258
  * Customize typescript lib folder path
268
259
  *
@@ -272,6 +263,13 @@ export interface PluginOptions {
272
263
  */
273
264
  libFolderPath?: string
274
265
 
266
+ /**
267
+ * Specify the log level of plugin
268
+ *
269
+ * By Default it base on 'logLevel' option of your vite config
270
+ */
271
+ logLevel?: LogLevel
272
+
275
273
  /**
276
274
  * After emit diagnostic hook
277
275
  *
package/README.zh-CN.md CHANGED
@@ -111,6 +111,7 @@ const props = defineProps<{
111
111
 
112
112
  ```ts
113
113
  import type { ts, Diagnostic } from 'ts-morph'
114
+ import type { LogLevel } from 'vite'
114
115
 
115
116
  interface TransformWriteFile {
116
117
  filePath?: string
@@ -121,7 +122,7 @@ export interface PluginOptions {
121
122
  /**
122
123
  * 执行的根目录
123
124
  *
124
- * 默认基于 vite 配置的 root 选项
125
+ * 默认基于 vite 配置的 'root' 选项
125
126
  */
126
127
  root?: string
127
128
 
@@ -130,7 +131,7 @@ export interface PluginOptions {
130
131
  *
131
132
  * 可以指定一个数组来输出到多个目录中
132
133
  *
133
- * 默认基于 vite 配置的输出目录
134
+ * 默认基于 vite 配置的 'build.outDir' 选项
134
135
  */
135
136
  outputDir?: string | string[]
136
137
 
@@ -189,14 +190,14 @@ export interface PluginOptions {
189
190
  /**
190
191
  * 手动设置包含路径的 glob
191
192
  *
192
- * 默认基于 tsconfig.json 的 include 选项
193
+ * 默认基于 tsconfig.json 的 'include' 选项
193
194
  */
194
195
  include?: string | string[]
195
196
 
196
197
  /**
197
198
  * 手动设置排除路径的 glob
198
199
  *
199
- * 默认基于 tsconfig.json 的 exclude 选线,未设置时为 'node_module/**'
200
+ * 默认基于 tsconfig.json 的 'exclude' 选线,未设置时为 'node_module/**'
200
201
  */
201
202
  exclude?: string | string[]
202
203
 
@@ -252,16 +253,6 @@ export interface PluginOptions {
252
253
  */
253
254
  skipDiagnostics?: boolean
254
255
 
255
- /**
256
- * 是否打印类型诊断信息
257
- *
258
- * 当跳过类型诊断时该属性将不会生效
259
- *
260
- * @deprecated
261
- * @default false
262
- */
263
- logDiagnostics?: boolean
264
-
265
256
  /**
266
257
  * 定制 typescript 的 lib 文件夹路径
267
258
  *
@@ -271,6 +262,13 @@ export interface PluginOptions {
271
262
  */
272
263
  libFolderPath?: string
273
264
 
265
+ /**
266
+ * 指定插件的输出等级
267
+ *
268
+ * 默认基于 vite 配置的 'logLevel' 选项
269
+ */
270
+ logLevel?: LogLevel
271
+
274
272
  /**
275
273
  * 获取诊断信息后的钩子
276
274
  *
package/dist/index.cjs CHANGED
@@ -360,62 +360,90 @@ function preprocessVueCode(code, setupScript) {
360
360
  }
361
361
  }
362
362
  }
363
+ const declRecord = /* @__PURE__ */ new Map();
364
+ let defaultExport;
365
+ let options;
363
366
  for (const node of scriptAst) {
367
+ if (node.type === "VariableDeclaration") {
368
+ for (const decl of node.declarations) {
369
+ if (decl.id.type === "Identifier" && decl.init) {
370
+ let properties;
371
+ if (decl.init.type === "ObjectExpression") {
372
+ properties = decl.init.properties;
373
+ } else if (decl.init.type === "CallExpression" && decl.init.arguments[0].type === "ObjectExpression") {
374
+ properties = decl.init.arguments[0].properties;
375
+ }
376
+ if (!properties)
377
+ continue;
378
+ if (defaultExport && decl.id.name === defaultExport) {
379
+ options = properties;
380
+ break;
381
+ } else {
382
+ declRecord.set(decl.id.name, properties);
383
+ }
384
+ }
385
+ }
386
+ }
364
387
  if (node.type === "ExportDefaultDeclaration") {
365
- let options;
366
388
  if (node.declaration.type === "ObjectExpression") {
367
389
  options = node.declaration.properties;
368
390
  } else if (node.declaration.type === "CallExpression" && node.declaration.arguments[0].type === "ObjectExpression") {
369
391
  options = node.declaration.arguments[0].properties;
392
+ } else if (node.declaration.type === "Identifier") {
393
+ if (declRecord.has(node.declaration.name)) {
394
+ options = declRecord.get(node.declaration.name);
395
+ } else {
396
+ defaultExport = node.declaration.name;
397
+ }
370
398
  }
371
- if (options) {
372
- for (const option of options) {
373
- if (propsTypeName && option.type === "ObjectProperty" && option.key.type === "Identifier" && option.key.name === "props" && option.value.type === "ObjectExpression") {
374
- for (const prop of option.value.properties) {
375
- if (prop.type === "ObjectProperty" && prop.key.type === "Identifier") {
376
- if (prop.value.type === "ObjectExpression") {
377
- for (const propDef of prop.value.properties) {
378
- if (propDef.type === "ObjectProperty" && propDef.key.type === "Identifier" && propDef.key.name === "type") {
379
- source.prependLeft(
380
- propDef.end,
381
- ` as unknown as __PropType<${propsTypeName}['${prop.key.name}']>`
382
- );
383
- }
399
+ }
400
+ if (options) {
401
+ for (const option of options) {
402
+ if (propsTypeName && option.type === "ObjectProperty" && option.key.type === "Identifier" && option.key.name === "props" && option.value.type === "ObjectExpression") {
403
+ for (const prop of option.value.properties) {
404
+ if (prop.type === "ObjectProperty" && prop.key.type === "Identifier") {
405
+ if (prop.value.type === "ObjectExpression") {
406
+ for (const propDef of prop.value.properties) {
407
+ if (propDef.type === "ObjectProperty" && propDef.key.type === "Identifier" && propDef.key.name === "type") {
408
+ source.prependLeft(
409
+ propDef.end,
410
+ ` as unknown as __PropType<${propsTypeName}['${prop.key.name}']>`
411
+ );
384
412
  }
385
- } else {
386
- source.prependLeft(
387
- prop.end,
388
- ` as unknown as __PropType<${propsTypeName}['${prop.key.name}']>`
389
- );
390
413
  }
414
+ } else {
415
+ source.prependLeft(
416
+ prop.end,
417
+ ` as unknown as __PropType<${propsTypeName}['${prop.key.name}']>`
418
+ );
391
419
  }
392
420
  }
393
421
  }
394
- if (option.type === "ObjectProperty" && option.key.type === "Identifier" && option.key.name === "components") {
395
- source.remove(option.start, option.end);
396
- }
397
- if (option.type === "ObjectMethod" && option.key.type === "Identifier" && option.key.name === "setup") {
398
- let exposed;
399
- let returned;
400
- for (const node2 of option.body.body) {
401
- if (!exposed && node2.type === "ExpressionStatement" && node2.expression.type === "CallExpression" && node2.expression.callee.type === "Identifier" && node2.expression.callee.name === "expose") {
402
- exposed = node2.expression.arguments[0];
403
- continue;
404
- }
405
- if (node2.type === "ReturnStatement") {
406
- returned = node2;
407
- break;
408
- }
422
+ }
423
+ if (option.type === "ObjectProperty" && option.key.type === "Identifier" && option.key.name === "components") {
424
+ source.remove(option.start, option.end);
425
+ }
426
+ if (option.type === "ObjectMethod" && option.key.type === "Identifier" && option.key.name === "setup") {
427
+ let exposed;
428
+ let returned;
429
+ for (const node2 of option.body.body) {
430
+ if (!exposed && node2.type === "ExpressionStatement" && node2.expression.type === "CallExpression" && node2.expression.callee.type === "Identifier" && node2.expression.callee.name === "expose") {
431
+ exposed = node2.expression.arguments[0];
432
+ continue;
433
+ }
434
+ if (node2.type === "ReturnStatement") {
435
+ returned = node2;
436
+ break;
409
437
  }
410
- const newReturned = exposed && exposed.type === "ObjectExpression" ? `return ${code.substring(exposed.start, exposed.end)}` : setupScript ? "return {}" : "";
411
- if (newReturned) {
412
- if (returned) {
413
- source.overwrite(returned.start, returned.end, newReturned);
414
- } else if (option.body.body.length) {
415
- source.appendRight(option.body.body.at(-1).end, `
438
+ }
439
+ const newReturned = exposed && exposed.type === "ObjectExpression" ? `return ${code.substring(exposed.start, exposed.end)}` : setupScript ? "return {}" : "";
440
+ if (newReturned) {
441
+ if (returned) {
442
+ source.overwrite(returned.start, returned.end, newReturned);
443
+ } else if (option.body.body.length) {
444
+ source.appendRight(option.body.body.at(-1).end, `
416
445
  ${newReturned}
417
446
  `);
418
- }
419
447
  }
420
448
  }
421
449
  }
@@ -475,10 +503,11 @@ function compileVueCode(code) {
475
503
  const dtsRE$1 = /\.d\.tsx?$/;
476
504
  function rollupDeclarationFiles({
477
505
  root,
506
+ compilerOptions,
478
507
  outputDir,
479
508
  entryPath,
480
509
  fileName,
481
- compilerOptions
510
+ libFolder
482
511
  }) {
483
512
  const configObjectFullPath = node_path.resolve(root, "api-extractor.json");
484
513
  const packageJsonLookup = new nodeCoreLibrary.PackageJsonLookup();
@@ -527,8 +556,9 @@ function rollupDeclarationFiles({
527
556
  packageJsonFullPath
528
557
  });
529
558
  const compilerState = apiExtractor.CompilerState.create(extractorConfig, {
530
- localBuild: true,
531
- showVerboseMessages: false
559
+ localBuild: false,
560
+ showVerboseMessages: false,
561
+ typescriptCompilerFolder: libFolder ? node_path.resolve(libFolder, "..") : void 0
532
562
  });
533
563
  const sourceMapper = new SourceMapper_js.SourceMapper();
534
564
  const messageRouter = new MessageRouter_js.MessageRouter({
@@ -582,9 +612,8 @@ function dtsPlugin(options = {}) {
582
612
  rollupTypes = false,
583
613
  noEmitOnError = false,
584
614
  skipDiagnostics = false,
585
- logDiagnostics = void 0,
586
615
  copyDtsFiles = true,
587
- libFolderPath = void 0,
616
+ logLevel = void 0,
588
617
  afterDiagnostic = noop,
589
618
  beforeWriteFile = noop,
590
619
  afterBuild = noop
@@ -604,10 +633,39 @@ function dtsPlugin(options = {}) {
604
633
  let include;
605
634
  let exclude;
606
635
  let filter;
636
+ let libFolderPath = options.libFolderPath;
607
637
  const sourceDtsFiles = /* @__PURE__ */ new Set();
638
+ const emittedFiles = /* @__PURE__ */ new Map();
608
639
  let hasJsVue = false;
609
640
  let allowJs = false;
610
641
  let transformError = false;
642
+ function internalTransform(code, id) {
643
+ if (!filter(id)) {
644
+ return;
645
+ }
646
+ if (vueRE.test(id)) {
647
+ const { error, content, ext } = compileVueCode(code);
648
+ if (!transformError && error) {
649
+ logger.error(
650
+ kolorist.red(
651
+ `
652
+ ${kolorist.cyan(
653
+ "[vite:dts]"
654
+ )} A error occurred when transform code, maybe there are some inertnal bugs.
655
+ `
656
+ )
657
+ );
658
+ transformError = true;
659
+ }
660
+ if (content) {
661
+ if (ext === "js" || ext === "jsx")
662
+ hasJsVue = true;
663
+ project.createSourceFile(`${id}.${ext || "js"}`, content, { overwrite: true });
664
+ }
665
+ } else if (!id.includes(".vue?vue") && (tsRE.test(id) || allowJs && jsRE.test(id))) {
666
+ project.createSourceFile(id, code, { overwrite: true });
667
+ }
668
+ }
611
669
  return {
612
670
  name: "vite:dts",
613
671
  apply: "build",
@@ -634,18 +692,7 @@ function dtsPlugin(options = {}) {
634
692
  configResolved(config) {
635
693
  if (isBundle)
636
694
  return;
637
- logger = config.logger;
638
- if (logDiagnostics != null) {
639
- logger.warn(
640
- kolorist.yellow(
641
- `
642
- ${kolorist.cyan(
643
- "[vite:dts]"
644
- )} 'logDiagnostics' has been deprecated, the original feature now following 'skipDiagnostics'.
645
- `
646
- )
647
- );
648
- }
695
+ logger = logLevel ? vite.createLogger(logLevel, { allowClearScreen: config.clearScreen }) : config.logger;
649
696
  if (!config.build.lib) {
650
697
  logger.warn(
651
698
  kolorist.yellow(
@@ -669,6 +716,7 @@ ${kolorist.cyan(
669
716
  }
670
717
  root = ensureAbsolute(options.root ?? "", config.root);
671
718
  tsConfigPath = ensureAbsolute(tsConfigFilePath, root);
719
+ libFolderPath = libFolderPath && ensureAbsolute(libFolderPath, root);
672
720
  outputDirs = options.outputDir ? ensureArray(options.outputDir).map((d) => ensureAbsolute(d, root)) : [ensureAbsolute(config.build.outDir, root)];
673
721
  if (!outputDirs[0]) {
674
722
  logger.error(
@@ -697,7 +745,7 @@ ${kolorist.cyan(
697
745
  }),
698
746
  tsConfigFilePath: tsConfigPath,
699
747
  skipAddingFilesFromTsConfig: true,
700
- libFolderPath: libFolderPath ? ensureAbsolute(libFolderPath, root) : void 0
748
+ libFolderPath
701
749
  });
702
750
  allowJs = project.getCompilerOptions().allowJs ?? false;
703
751
  const tsConfig = { compilerOptions: {} };
@@ -732,39 +780,16 @@ ${kolorist.cyan(
732
780
  }
733
781
  },
734
782
  transform(code, id) {
735
- if (!filter(id)) {
736
- return null;
737
- }
738
- if (vueRE.test(id)) {
739
- const { error, content, ext } = compileVueCode(code);
740
- if (!transformError && error) {
741
- logger.error(
742
- kolorist.red(
743
- `
744
- ${kolorist.cyan(
745
- "[vite:dts]"
746
- )} A error occurred when transform code, maybe there are some inertnal bugs.
747
- `
748
- )
749
- );
750
- transformError = true;
751
- }
752
- if (content) {
753
- if (ext === "js" || ext === "jsx")
754
- hasJsVue = true;
755
- project.createSourceFile(`${id}.${ext || "js"}`, content, { overwrite: true });
756
- }
757
- } else if (!id.includes(".vue?vue") && (tsRE.test(id) || allowJs && jsRE.test(id))) {
758
- project.createSourceFile(id, code, { overwrite: true });
759
- }
783
+ internalTransform(code, id);
760
784
  return null;
761
785
  },
762
- watchChange(id) {
786
+ async watchChange(id) {
763
787
  if (watchExtensionRE.test(id)) {
764
788
  isBundle = false;
765
789
  if (project) {
766
790
  const sourceFile = project.getSourceFile(vite.normalizePath(id));
767
791
  sourceFile && project.removeSourceFile(sourceFile);
792
+ internalTransform(await fs.readFile(id, "utf-8"), id);
768
793
  }
769
794
  }
770
795
  },
@@ -776,6 +801,7 @@ ${logPrefix} Start generate declaration files...`));
776
801
  bundleDebug("start");
777
802
  isBundle = true;
778
803
  sourceDtsFiles.clear();
804
+ emittedFiles.clear();
779
805
  const startTime = Date.now();
780
806
  const includedFileSet = /* @__PURE__ */ new Set();
781
807
  if (include && include.length) {
@@ -838,7 +864,6 @@ ${logPrefix} Start generate declaration files...`));
838
864
  entryRoot = queryPublicPath(outputFiles.map((file) => file.path));
839
865
  }
840
866
  entryRoot = ensureAbsolute(entryRoot, root);
841
- const wroteFiles = /* @__PURE__ */ new Set();
842
867
  const outputDir = outputDirs[0];
843
868
  await runParallel(os.cpus().length, outputFiles, async (outputFile) => {
844
869
  let filePath = outputFile.path;
@@ -871,7 +896,10 @@ ${logPrefix} Start generate declaration files...`));
871
896
  cleanVueFileName ? content.replace(/['"](.+)\.vue['"]/g, '"$1"') : content,
872
897
  "utf-8"
873
898
  );
874
- wroteFiles.add(vite.normalizePath(filePath));
899
+ emittedFiles.set(
900
+ vite.normalizePath(filePath),
901
+ cleanVueFileName ? content.replace(/['"](.+)\.vue['"]/g, '"$1"') : content
902
+ );
875
903
  });
876
904
  bundleDebug("output");
877
905
  if (insertTypesEntry || rollupTypes) {
@@ -912,13 +940,16 @@ export default ${libName}
912
940
  }
913
941
  if (result !== false) {
914
942
  await fs.writeFile(filePath, content, "utf-8");
915
- wroteFiles.add(vite.normalizePath(filePath));
943
+ emittedFiles.set(vite.normalizePath(filePath), content);
916
944
  }
917
945
  }
918
946
  bundleDebug("insert index");
919
947
  if (rollupTypes) {
920
948
  logger.info(kolorist.green(`${logPrefix} Start rollup declaration files...`));
921
949
  const rollupFiles = /* @__PURE__ */ new Set();
950
+ for (const [filePath, content] of emittedFiles) {
951
+ project.createSourceFile(filePath, content, { overwrite: true });
952
+ }
922
953
  if (multiple) {
923
954
  for (const name of entryNames) {
924
955
  const path = node_path.resolve(outputDir, `${name.replace(tsRE, "")}.d.ts`);
@@ -927,10 +958,11 @@ export default ${libName}
927
958
  compilerOptions,
928
959
  outputDir,
929
960
  entryPath: path,
930
- fileName: node_path.basename(path)
961
+ fileName: node_path.basename(path),
962
+ libFolder: libFolderPath
931
963
  });
932
964
  const wroteFile = vite.normalizePath(path);
933
- wroteFiles.delete(wroteFile);
965
+ emittedFiles.delete(wroteFile);
934
966
  rollupFiles.add(wroteFile);
935
967
  }
936
968
  } else {
@@ -939,23 +971,24 @@ export default ${libName}
939
971
  compilerOptions,
940
972
  outputDir,
941
973
  entryPath: typesPath,
942
- fileName: node_path.basename(typesPath)
974
+ fileName: node_path.basename(typesPath),
975
+ libFolder: libFolderPath
943
976
  });
944
977
  const wroteFile = vite.normalizePath(typesPath);
945
- wroteFiles.delete(wroteFile);
978
+ emittedFiles.delete(wroteFile);
946
979
  rollupFiles.add(wroteFile);
947
980
  }
948
- await runParallel(os.cpus().length, Array.from(wroteFiles), (f) => fs.unlink(f));
981
+ await runParallel(os.cpus().length, Array.from(emittedFiles.keys()), (f) => fs.unlink(f));
949
982
  removeDirIfEmpty(outputDir);
950
- wroteFiles.clear();
983
+ emittedFiles.clear();
951
984
  for (const file of rollupFiles) {
952
- wroteFiles.add(file);
985
+ emittedFiles.set(file, await fs.readFile(file, "utf-8"));
953
986
  }
954
987
  if (copyDtsFiles) {
955
988
  await runParallel(os.cpus().length, dtsOutputFiles, async ({ path, content }) => {
956
989
  const filePath = node_path.resolve(outputDir, node_path.basename(path));
957
990
  await fs.writeFile(filePath, content, "utf-8");
958
- wroteFiles.add(vite.normalizePath(filePath));
991
+ emittedFiles.set(vite.normalizePath(filePath), content);
959
992
  });
960
993
  }
961
994
  bundleDebug("rollup");
@@ -963,17 +996,20 @@ export default ${libName}
963
996
  }
964
997
  if (outputDirs.length > 1) {
965
998
  const dirs = outputDirs.slice(1);
966
- await runParallel(os.cpus().length, Array.from(wroteFiles), async (wroteFile) => {
967
- const relativePath = node_path.relative(outputDir, wroteFile);
968
- const content = await fs.readFile(wroteFile, "utf-8");
969
- await Promise.all(
970
- dirs.map(async (dir) => {
971
- const filePath = node_path.resolve(dir, relativePath);
972
- await fs.mkdir(node_path.dirname(filePath), { recursive: true });
973
- await fs.writeFile(filePath, content, "utf-8");
974
- })
975
- );
976
- });
999
+ await runParallel(
1000
+ os.cpus().length,
1001
+ Array.from(emittedFiles),
1002
+ async ([wroteFile, content]) => {
1003
+ const relativePath = node_path.relative(outputDir, wroteFile);
1004
+ await Promise.all(
1005
+ dirs.map(async (dir) => {
1006
+ const filePath = node_path.resolve(dir, relativePath);
1007
+ await fs.mkdir(node_path.dirname(filePath), { recursive: true });
1008
+ await fs.writeFile(filePath, content, "utf-8");
1009
+ })
1010
+ );
1011
+ }
1012
+ );
977
1013
  }
978
1014
  if (typeof afterBuild === "function") {
979
1015
  const result = afterBuild();
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as vite from 'vite';
2
+ import { LogLevel } from 'vite';
2
3
  import { ts, Diagnostic } from 'ts-morph';
3
4
 
4
5
  interface TransformWriteFile {
@@ -9,7 +10,7 @@ interface PluginOptions {
9
10
  /**
10
11
  * Depends on the root directory
11
12
  *
12
- * Defaults base on your vite config root options
13
+ * By Default it base on 'root' option of your vite config
13
14
  */
14
15
  root?: string;
15
16
  /**
@@ -17,7 +18,7 @@ interface PluginOptions {
17
18
  *
18
19
  * Can be specified a array to output to multiple directories
19
20
  *
20
- * Defaults base on your vite config output options
21
+ * By Default it base on 'build.outDir' option of your vite config
21
22
  */
22
23
  outputDir?: string | string[];
23
24
  /**
@@ -25,7 +26,7 @@ interface PluginOptions {
25
26
  *
26
27
  * The output path of each file will be calculated base on it
27
28
  *
28
- * Defaults is the smallest public path for all files
29
+ * By Default it is the smallest public path for all files
29
30
  */
30
31
  entryRoot?: string;
31
32
  /**
@@ -69,13 +70,13 @@ interface PluginOptions {
69
70
  /**
70
71
  * Manual set include glob
71
72
  *
72
- * Defaults base on your tsconfig.json include option
73
+ * By Default it base on 'include' option of the tsconfig.json
73
74
  */
74
75
  include?: string | string[];
75
76
  /**
76
77
  * Manual set exclude glob
77
78
  *
78
- * Defaults base on your tsconfig.json exclude option, be 'node_module/**' when empty
79
+ * By Default it base on 'exclude' option of the tsconfig.json, be 'node_module/**' when empty
79
80
  */
80
81
  exclude?: string | string[];
81
82
  /**
@@ -124,15 +125,6 @@ interface PluginOptions {
124
125
  * @default false
125
126
  */
126
127
  skipDiagnostics?: boolean;
127
- /**
128
- * Whether log diagnostic informations
129
- *
130
- * Not effective when `skipDiagnostics` is true
131
- *
132
- * @deprecated
133
- * @default false
134
- */
135
- logDiagnostics?: boolean;
136
128
  /**
137
129
  * Customize typescript lib folder path
138
130
  *
@@ -141,6 +133,12 @@ interface PluginOptions {
141
133
  * @default undefined
142
134
  */
143
135
  libFolderPath?: string;
136
+ /**
137
+ * Specify the log level of plugin
138
+ *
139
+ * By Default it base on 'logLevel' option of your vite config
140
+ */
141
+ logLevel?: LogLevel;
144
142
  /**
145
143
  * After emit diagnostic hook
146
144
  *
package/dist/index.mjs CHANGED
@@ -12,7 +12,7 @@ import { cyan, yellow, red, green } from 'kolorist';
12
12
  import glob from 'fast-glob';
13
13
  import debug from 'debug';
14
14
  import { Project } from 'ts-morph';
15
- import { normalizePath } from 'vite';
15
+ import { normalizePath, createLogger } from 'vite';
16
16
  import typescript from 'typescript';
17
17
  import { createFilter } from '@rollup/pluginutils';
18
18
  import { existsSync, readdirSync, lstatSync, rmdirSync } from 'node:fs';
@@ -365,62 +365,90 @@ function preprocessVueCode(code, setupScript) {
365
365
  }
366
366
  }
367
367
  }
368
+ const declRecord = /* @__PURE__ */ new Map();
369
+ let defaultExport;
370
+ let options;
368
371
  for (const node of scriptAst) {
372
+ if (node.type === "VariableDeclaration") {
373
+ for (const decl of node.declarations) {
374
+ if (decl.id.type === "Identifier" && decl.init) {
375
+ let properties;
376
+ if (decl.init.type === "ObjectExpression") {
377
+ properties = decl.init.properties;
378
+ } else if (decl.init.type === "CallExpression" && decl.init.arguments[0].type === "ObjectExpression") {
379
+ properties = decl.init.arguments[0].properties;
380
+ }
381
+ if (!properties)
382
+ continue;
383
+ if (defaultExport && decl.id.name === defaultExport) {
384
+ options = properties;
385
+ break;
386
+ } else {
387
+ declRecord.set(decl.id.name, properties);
388
+ }
389
+ }
390
+ }
391
+ }
369
392
  if (node.type === "ExportDefaultDeclaration") {
370
- let options;
371
393
  if (node.declaration.type === "ObjectExpression") {
372
394
  options = node.declaration.properties;
373
395
  } else if (node.declaration.type === "CallExpression" && node.declaration.arguments[0].type === "ObjectExpression") {
374
396
  options = node.declaration.arguments[0].properties;
397
+ } else if (node.declaration.type === "Identifier") {
398
+ if (declRecord.has(node.declaration.name)) {
399
+ options = declRecord.get(node.declaration.name);
400
+ } else {
401
+ defaultExport = node.declaration.name;
402
+ }
375
403
  }
376
- if (options) {
377
- for (const option of options) {
378
- if (propsTypeName && option.type === "ObjectProperty" && option.key.type === "Identifier" && option.key.name === "props" && option.value.type === "ObjectExpression") {
379
- for (const prop of option.value.properties) {
380
- if (prop.type === "ObjectProperty" && prop.key.type === "Identifier") {
381
- if (prop.value.type === "ObjectExpression") {
382
- for (const propDef of prop.value.properties) {
383
- if (propDef.type === "ObjectProperty" && propDef.key.type === "Identifier" && propDef.key.name === "type") {
384
- source.prependLeft(
385
- propDef.end,
386
- ` as unknown as __PropType<${propsTypeName}['${prop.key.name}']>`
387
- );
388
- }
404
+ }
405
+ if (options) {
406
+ for (const option of options) {
407
+ if (propsTypeName && option.type === "ObjectProperty" && option.key.type === "Identifier" && option.key.name === "props" && option.value.type === "ObjectExpression") {
408
+ for (const prop of option.value.properties) {
409
+ if (prop.type === "ObjectProperty" && prop.key.type === "Identifier") {
410
+ if (prop.value.type === "ObjectExpression") {
411
+ for (const propDef of prop.value.properties) {
412
+ if (propDef.type === "ObjectProperty" && propDef.key.type === "Identifier" && propDef.key.name === "type") {
413
+ source.prependLeft(
414
+ propDef.end,
415
+ ` as unknown as __PropType<${propsTypeName}['${prop.key.name}']>`
416
+ );
389
417
  }
390
- } else {
391
- source.prependLeft(
392
- prop.end,
393
- ` as unknown as __PropType<${propsTypeName}['${prop.key.name}']>`
394
- );
395
418
  }
419
+ } else {
420
+ source.prependLeft(
421
+ prop.end,
422
+ ` as unknown as __PropType<${propsTypeName}['${prop.key.name}']>`
423
+ );
396
424
  }
397
425
  }
398
426
  }
399
- if (option.type === "ObjectProperty" && option.key.type === "Identifier" && option.key.name === "components") {
400
- source.remove(option.start, option.end);
401
- }
402
- if (option.type === "ObjectMethod" && option.key.type === "Identifier" && option.key.name === "setup") {
403
- let exposed;
404
- let returned;
405
- for (const node2 of option.body.body) {
406
- if (!exposed && node2.type === "ExpressionStatement" && node2.expression.type === "CallExpression" && node2.expression.callee.type === "Identifier" && node2.expression.callee.name === "expose") {
407
- exposed = node2.expression.arguments[0];
408
- continue;
409
- }
410
- if (node2.type === "ReturnStatement") {
411
- returned = node2;
412
- break;
413
- }
427
+ }
428
+ if (option.type === "ObjectProperty" && option.key.type === "Identifier" && option.key.name === "components") {
429
+ source.remove(option.start, option.end);
430
+ }
431
+ if (option.type === "ObjectMethod" && option.key.type === "Identifier" && option.key.name === "setup") {
432
+ let exposed;
433
+ let returned;
434
+ for (const node2 of option.body.body) {
435
+ if (!exposed && node2.type === "ExpressionStatement" && node2.expression.type === "CallExpression" && node2.expression.callee.type === "Identifier" && node2.expression.callee.name === "expose") {
436
+ exposed = node2.expression.arguments[0];
437
+ continue;
438
+ }
439
+ if (node2.type === "ReturnStatement") {
440
+ returned = node2;
441
+ break;
414
442
  }
415
- const newReturned = exposed && exposed.type === "ObjectExpression" ? `return ${code.substring(exposed.start, exposed.end)}` : setupScript ? "return {}" : "";
416
- if (newReturned) {
417
- if (returned) {
418
- source.overwrite(returned.start, returned.end, newReturned);
419
- } else if (option.body.body.length) {
420
- source.appendRight(option.body.body.at(-1).end, `
443
+ }
444
+ const newReturned = exposed && exposed.type === "ObjectExpression" ? `return ${code.substring(exposed.start, exposed.end)}` : setupScript ? "return {}" : "";
445
+ if (newReturned) {
446
+ if (returned) {
447
+ source.overwrite(returned.start, returned.end, newReturned);
448
+ } else if (option.body.body.length) {
449
+ source.appendRight(option.body.body.at(-1).end, `
421
450
  ${newReturned}
422
451
  `);
423
- }
424
452
  }
425
453
  }
426
454
  }
@@ -480,10 +508,11 @@ function compileVueCode(code) {
480
508
  const dtsRE$1 = /\.d\.tsx?$/;
481
509
  function rollupDeclarationFiles({
482
510
  root,
511
+ compilerOptions,
483
512
  outputDir,
484
513
  entryPath,
485
514
  fileName,
486
- compilerOptions
515
+ libFolder
487
516
  }) {
488
517
  const configObjectFullPath = resolve(root, "api-extractor.json");
489
518
  const packageJsonLookup = new PackageJsonLookup();
@@ -532,8 +561,9 @@ function rollupDeclarationFiles({
532
561
  packageJsonFullPath
533
562
  });
534
563
  const compilerState = CompilerState.create(extractorConfig, {
535
- localBuild: true,
536
- showVerboseMessages: false
564
+ localBuild: false,
565
+ showVerboseMessages: false,
566
+ typescriptCompilerFolder: libFolder ? resolve(libFolder, "..") : void 0
537
567
  });
538
568
  const sourceMapper = new SourceMapper();
539
569
  const messageRouter = new MessageRouter({
@@ -587,9 +617,8 @@ function dtsPlugin(options = {}) {
587
617
  rollupTypes = false,
588
618
  noEmitOnError = false,
589
619
  skipDiagnostics = false,
590
- logDiagnostics = void 0,
591
620
  copyDtsFiles = true,
592
- libFolderPath = void 0,
621
+ logLevel = void 0,
593
622
  afterDiagnostic = noop,
594
623
  beforeWriteFile = noop,
595
624
  afterBuild = noop
@@ -609,10 +638,39 @@ function dtsPlugin(options = {}) {
609
638
  let include;
610
639
  let exclude;
611
640
  let filter;
641
+ let libFolderPath = options.libFolderPath;
612
642
  const sourceDtsFiles = /* @__PURE__ */ new Set();
643
+ const emittedFiles = /* @__PURE__ */ new Map();
613
644
  let hasJsVue = false;
614
645
  let allowJs = false;
615
646
  let transformError = false;
647
+ function internalTransform(code, id) {
648
+ if (!filter(id)) {
649
+ return;
650
+ }
651
+ if (vueRE.test(id)) {
652
+ const { error, content, ext } = compileVueCode(code);
653
+ if (!transformError && error) {
654
+ logger.error(
655
+ red(
656
+ `
657
+ ${cyan(
658
+ "[vite:dts]"
659
+ )} A error occurred when transform code, maybe there are some inertnal bugs.
660
+ `
661
+ )
662
+ );
663
+ transformError = true;
664
+ }
665
+ if (content) {
666
+ if (ext === "js" || ext === "jsx")
667
+ hasJsVue = true;
668
+ project.createSourceFile(`${id}.${ext || "js"}`, content, { overwrite: true });
669
+ }
670
+ } else if (!id.includes(".vue?vue") && (tsRE.test(id) || allowJs && jsRE.test(id))) {
671
+ project.createSourceFile(id, code, { overwrite: true });
672
+ }
673
+ }
616
674
  return {
617
675
  name: "vite:dts",
618
676
  apply: "build",
@@ -639,18 +697,7 @@ function dtsPlugin(options = {}) {
639
697
  configResolved(config) {
640
698
  if (isBundle)
641
699
  return;
642
- logger = config.logger;
643
- if (logDiagnostics != null) {
644
- logger.warn(
645
- yellow(
646
- `
647
- ${cyan(
648
- "[vite:dts]"
649
- )} 'logDiagnostics' has been deprecated, the original feature now following 'skipDiagnostics'.
650
- `
651
- )
652
- );
653
- }
700
+ logger = logLevel ? createLogger(logLevel, { allowClearScreen: config.clearScreen }) : config.logger;
654
701
  if (!config.build.lib) {
655
702
  logger.warn(
656
703
  yellow(
@@ -674,6 +721,7 @@ ${cyan(
674
721
  }
675
722
  root = ensureAbsolute(options.root ?? "", config.root);
676
723
  tsConfigPath = ensureAbsolute(tsConfigFilePath, root);
724
+ libFolderPath = libFolderPath && ensureAbsolute(libFolderPath, root);
677
725
  outputDirs = options.outputDir ? ensureArray(options.outputDir).map((d) => ensureAbsolute(d, root)) : [ensureAbsolute(config.build.outDir, root)];
678
726
  if (!outputDirs[0]) {
679
727
  logger.error(
@@ -702,7 +750,7 @@ ${cyan(
702
750
  }),
703
751
  tsConfigFilePath: tsConfigPath,
704
752
  skipAddingFilesFromTsConfig: true,
705
- libFolderPath: libFolderPath ? ensureAbsolute(libFolderPath, root) : void 0
753
+ libFolderPath
706
754
  });
707
755
  allowJs = project.getCompilerOptions().allowJs ?? false;
708
756
  const tsConfig = { compilerOptions: {} };
@@ -737,39 +785,16 @@ ${cyan(
737
785
  }
738
786
  },
739
787
  transform(code, id) {
740
- if (!filter(id)) {
741
- return null;
742
- }
743
- if (vueRE.test(id)) {
744
- const { error, content, ext } = compileVueCode(code);
745
- if (!transformError && error) {
746
- logger.error(
747
- red(
748
- `
749
- ${cyan(
750
- "[vite:dts]"
751
- )} A error occurred when transform code, maybe there are some inertnal bugs.
752
- `
753
- )
754
- );
755
- transformError = true;
756
- }
757
- if (content) {
758
- if (ext === "js" || ext === "jsx")
759
- hasJsVue = true;
760
- project.createSourceFile(`${id}.${ext || "js"}`, content, { overwrite: true });
761
- }
762
- } else if (!id.includes(".vue?vue") && (tsRE.test(id) || allowJs && jsRE.test(id))) {
763
- project.createSourceFile(id, code, { overwrite: true });
764
- }
788
+ internalTransform(code, id);
765
789
  return null;
766
790
  },
767
- watchChange(id) {
791
+ async watchChange(id) {
768
792
  if (watchExtensionRE.test(id)) {
769
793
  isBundle = false;
770
794
  if (project) {
771
795
  const sourceFile = project.getSourceFile(normalizePath(id));
772
796
  sourceFile && project.removeSourceFile(sourceFile);
797
+ internalTransform(await fs.readFile(id, "utf-8"), id);
773
798
  }
774
799
  }
775
800
  },
@@ -781,6 +806,7 @@ ${logPrefix} Start generate declaration files...`));
781
806
  bundleDebug("start");
782
807
  isBundle = true;
783
808
  sourceDtsFiles.clear();
809
+ emittedFiles.clear();
784
810
  const startTime = Date.now();
785
811
  const includedFileSet = /* @__PURE__ */ new Set();
786
812
  if (include && include.length) {
@@ -843,7 +869,6 @@ ${logPrefix} Start generate declaration files...`));
843
869
  entryRoot = queryPublicPath(outputFiles.map((file) => file.path));
844
870
  }
845
871
  entryRoot = ensureAbsolute(entryRoot, root);
846
- const wroteFiles = /* @__PURE__ */ new Set();
847
872
  const outputDir = outputDirs[0];
848
873
  await runParallel(os.cpus().length, outputFiles, async (outputFile) => {
849
874
  let filePath = outputFile.path;
@@ -876,7 +901,10 @@ ${logPrefix} Start generate declaration files...`));
876
901
  cleanVueFileName ? content.replace(/['"](.+)\.vue['"]/g, '"$1"') : content,
877
902
  "utf-8"
878
903
  );
879
- wroteFiles.add(normalizePath(filePath));
904
+ emittedFiles.set(
905
+ normalizePath(filePath),
906
+ cleanVueFileName ? content.replace(/['"](.+)\.vue['"]/g, '"$1"') : content
907
+ );
880
908
  });
881
909
  bundleDebug("output");
882
910
  if (insertTypesEntry || rollupTypes) {
@@ -917,13 +945,16 @@ export default ${libName}
917
945
  }
918
946
  if (result !== false) {
919
947
  await fs.writeFile(filePath, content, "utf-8");
920
- wroteFiles.add(normalizePath(filePath));
948
+ emittedFiles.set(normalizePath(filePath), content);
921
949
  }
922
950
  }
923
951
  bundleDebug("insert index");
924
952
  if (rollupTypes) {
925
953
  logger.info(green(`${logPrefix} Start rollup declaration files...`));
926
954
  const rollupFiles = /* @__PURE__ */ new Set();
955
+ for (const [filePath, content] of emittedFiles) {
956
+ project.createSourceFile(filePath, content, { overwrite: true });
957
+ }
927
958
  if (multiple) {
928
959
  for (const name of entryNames) {
929
960
  const path = resolve(outputDir, `${name.replace(tsRE, "")}.d.ts`);
@@ -932,10 +963,11 @@ export default ${libName}
932
963
  compilerOptions,
933
964
  outputDir,
934
965
  entryPath: path,
935
- fileName: basename(path)
966
+ fileName: basename(path),
967
+ libFolder: libFolderPath
936
968
  });
937
969
  const wroteFile = normalizePath(path);
938
- wroteFiles.delete(wroteFile);
970
+ emittedFiles.delete(wroteFile);
939
971
  rollupFiles.add(wroteFile);
940
972
  }
941
973
  } else {
@@ -944,23 +976,24 @@ export default ${libName}
944
976
  compilerOptions,
945
977
  outputDir,
946
978
  entryPath: typesPath,
947
- fileName: basename(typesPath)
979
+ fileName: basename(typesPath),
980
+ libFolder: libFolderPath
948
981
  });
949
982
  const wroteFile = normalizePath(typesPath);
950
- wroteFiles.delete(wroteFile);
983
+ emittedFiles.delete(wroteFile);
951
984
  rollupFiles.add(wroteFile);
952
985
  }
953
- await runParallel(os.cpus().length, Array.from(wroteFiles), (f) => fs.unlink(f));
986
+ await runParallel(os.cpus().length, Array.from(emittedFiles.keys()), (f) => fs.unlink(f));
954
987
  removeDirIfEmpty(outputDir);
955
- wroteFiles.clear();
988
+ emittedFiles.clear();
956
989
  for (const file of rollupFiles) {
957
- wroteFiles.add(file);
990
+ emittedFiles.set(file, await fs.readFile(file, "utf-8"));
958
991
  }
959
992
  if (copyDtsFiles) {
960
993
  await runParallel(os.cpus().length, dtsOutputFiles, async ({ path, content }) => {
961
994
  const filePath = resolve(outputDir, basename(path));
962
995
  await fs.writeFile(filePath, content, "utf-8");
963
- wroteFiles.add(normalizePath(filePath));
996
+ emittedFiles.set(normalizePath(filePath), content);
964
997
  });
965
998
  }
966
999
  bundleDebug("rollup");
@@ -968,17 +1001,20 @@ export default ${libName}
968
1001
  }
969
1002
  if (outputDirs.length > 1) {
970
1003
  const dirs = outputDirs.slice(1);
971
- await runParallel(os.cpus().length, Array.from(wroteFiles), async (wroteFile) => {
972
- const relativePath = relative(outputDir, wroteFile);
973
- const content = await fs.readFile(wroteFile, "utf-8");
974
- await Promise.all(
975
- dirs.map(async (dir) => {
976
- const filePath = resolve(dir, relativePath);
977
- await fs.mkdir(dirname(filePath), { recursive: true });
978
- await fs.writeFile(filePath, content, "utf-8");
979
- })
980
- );
981
- });
1004
+ await runParallel(
1005
+ os.cpus().length,
1006
+ Array.from(emittedFiles),
1007
+ async ([wroteFile, content]) => {
1008
+ const relativePath = relative(outputDir, wroteFile);
1009
+ await Promise.all(
1010
+ dirs.map(async (dir) => {
1011
+ const filePath = resolve(dir, relativePath);
1012
+ await fs.mkdir(dirname(filePath), { recursive: true });
1013
+ await fs.writeFile(filePath, content, "utf-8");
1014
+ })
1015
+ );
1016
+ }
1017
+ );
982
1018
  }
983
1019
  if (typeof afterBuild === "function") {
984
1020
  const result = afterBuild();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-dts",
3
- "version": "2.0.0-beta.1",
3
+ "version": "2.0.0-beta.2",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "qmhc",
@@ -29,6 +29,7 @@
29
29
  "prettier": "pretty-quick --staged",
30
30
  "release": "tsx scripts/release.ts",
31
31
  "test": "vitest run",
32
+ "test:react": "pnpm -C examples/react build",
32
33
  "test:ts": "pnpm -C examples/ts build",
33
34
  "test:vue": "pnpm -C examples/vue build"
34
35
  },