vite-plugin-dts 1.7.2 → 2.0.0-beta.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/dist/index.mjs CHANGED
@@ -17,6 +17,8 @@ import typescript from 'typescript';
17
17
  import { createFilter } from '@rollup/pluginutils';
18
18
  import { existsSync, readdirSync, lstatSync, rmdirSync } from 'node:fs';
19
19
  import { createRequire } from 'node:module';
20
+ import { parse } from '@babel/parser';
21
+ import MagicString from 'magic-string';
20
22
  import { ExtractorConfig, CompilerState } from '@microsoft/api-extractor';
21
23
  import { Collector } from '@microsoft/api-extractor/lib/collector/Collector.js';
22
24
  import { MessageRouter } from '@microsoft/api-extractor/lib/collector/MessageRouter.js';
@@ -245,8 +247,6 @@ function transferSetupPosition(content) {
245
247
  return content;
246
248
  }
247
249
 
248
- const exportDefaultRE = /export\s+default/;
249
- const exportDefaultClassRE = /(?:(?:^|\n|;)\s*)export\s+default\s+class\s+([\w$]+)/;
250
250
  const noScriptContent = "import { defineComponent } from 'vue'\nexport default defineComponent({})";
251
251
  const _require = createRequire(import.meta.url);
252
252
  let index = 1;
@@ -304,64 +304,179 @@ function setCompileRoot(root) {
304
304
  }
305
305
  }
306
306
  function parseCode(code) {
307
- const { parse } = requireCompiler();
307
+ const { parse: parseVueCode } = requireCompiler();
308
308
  let descriptor;
309
309
  if (isVue3()) {
310
- descriptor = parse(code).descriptor;
310
+ descriptor = parseVueCode(code).descriptor;
311
311
  } else {
312
- descriptor = parse({ source: code });
312
+ descriptor = parseVueCode({ source: code });
313
313
  }
314
314
  return descriptor;
315
315
  }
316
+ function transformJsToTs(script) {
317
+ if (!script)
318
+ return script;
319
+ const lang = !script.lang || script.lang === "js" ? "ts" : script.lang === "jsx" ? "tsx" : script.lang;
320
+ return { ...script, lang };
321
+ }
322
+ function preprocessVueCode(code, setupScript) {
323
+ const plugins = ["typescript", "decorators-legacy", "jsx"];
324
+ const scriptAst = parse(code, { sourceType: "module", plugins }).program.body;
325
+ const source = new MagicString(code);
326
+ let propsTypeName;
327
+ let propsTypeLiteral;
328
+ if (setupScript) {
329
+ let processDefineProps = function(node) {
330
+ if (node.type === "CallExpression" && node.callee.type === "Identifier") {
331
+ if (node.callee.name === "defineProps") {
332
+ defineProps = node;
333
+ return true;
334
+ } else if (node.callee.name === "withDefaults") {
335
+ const propsDef = node.arguments[0];
336
+ if (propsDef.type === "CallExpression" && propsDef.callee.type === "Identifier" && propsDef.callee.name === "defineProps") {
337
+ defineProps = propsDef;
338
+ return true;
339
+ }
340
+ }
341
+ }
342
+ return false;
343
+ };
344
+ const setupAst = parse(setupScript.content, { sourceType: "module", plugins }).program.body;
345
+ let defineProps;
346
+ for (const node of setupAst) {
347
+ if (node.type === "ExpressionStatement") {
348
+ processDefineProps(node.expression);
349
+ } else if (node.type === "VariableDeclaration" && !node.declare) {
350
+ for (const decl of node.declarations) {
351
+ if (decl.init && processDefineProps(decl.init)) {
352
+ break;
353
+ }
354
+ }
355
+ }
356
+ if (defineProps) {
357
+ const type = defineProps.typeParameters?.params[0];
358
+ if (type && type.type === "TSTypeReference" && type.typeName.type === "Identifier") {
359
+ propsTypeName = type.typeName.name;
360
+ } else if (type?.type === "TSTypeLiteral") {
361
+ propsTypeName = "__DTS_Props__";
362
+ propsTypeLiteral = setupScript.content.substring(type.start, type.end);
363
+ }
364
+ break;
365
+ }
366
+ }
367
+ }
368
+ for (const node of scriptAst) {
369
+ if (node.type === "ExportDefaultDeclaration") {
370
+ let options;
371
+ if (node.declaration.type === "ObjectExpression") {
372
+ options = node.declaration.properties;
373
+ } else if (node.declaration.type === "CallExpression" && node.declaration.arguments[0].type === "ObjectExpression") {
374
+ options = node.declaration.arguments[0].properties;
375
+ }
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 __PropType<${propsTypeName}['${prop.key.name}']>`
387
+ );
388
+ }
389
+ }
390
+ } else {
391
+ source.prependLeft(
392
+ prop.end,
393
+ ` as __PropType<${propsTypeName}['${prop.key.name}']>`
394
+ );
395
+ }
396
+ }
397
+ }
398
+ }
399
+ if (option.type === "ObjectMethod" && option.key.type === "Identifier" && option.key.name === "setup") {
400
+ let exposed;
401
+ let returned;
402
+ for (const node2 of option.body.body) {
403
+ if (!exposed && node2.type === "ExpressionStatement" && node2.expression.type === "CallExpression" && node2.expression.callee.type === "Identifier" && node2.expression.callee.name === "expose") {
404
+ exposed = node2.expression.arguments[0];
405
+ continue;
406
+ }
407
+ if (node2.type === "ReturnStatement") {
408
+ returned = node2;
409
+ break;
410
+ }
411
+ }
412
+ const newReturned = exposed && exposed.type === "ObjectExpression" ? `return ${code.substring(exposed.start, exposed.end)}` : setupScript ? "return {}" : "";
413
+ if (newReturned) {
414
+ if (returned) {
415
+ source.overwrite(returned.start, returned.end, newReturned);
416
+ } else if (option.body.body.length) {
417
+ source.appendRight(option.body.body.at(-1).end, `
418
+ ${newReturned}
419
+ `);
420
+ }
421
+ }
422
+ }
423
+ }
424
+ }
425
+ break;
426
+ }
427
+ }
428
+ if (propsTypeName) {
429
+ if (propsTypeLiteral) {
430
+ source.prepend(`
431
+ type ${propsTypeName} = ${propsTypeLiteral}
432
+
433
+ `);
434
+ }
435
+ source.prepend("import type { PropType as __PropType } from 'vue'\n");
436
+ }
437
+ return source.toString();
438
+ }
316
439
  function compileVueCode(code) {
317
440
  const { compileScript, rewriteDefault } = requireCompiler();
318
441
  const descriptor = parseCode(code);
319
442
  const { script, scriptSetup } = descriptor;
320
- let content = null;
321
- let ext = null;
443
+ let error;
444
+ let content;
445
+ let ext = "js";
322
446
  if (script || scriptSetup) {
447
+ const compiled = compileScript(
448
+ {
449
+ ...descriptor,
450
+ script: transformJsToTs(script),
451
+ scriptSetup: transformJsToTs(scriptSetup),
452
+ cssVars: []
453
+ },
454
+ { id: `${index++}` }
455
+ );
456
+ try {
457
+ content = preprocessVueCode(compiled.content, scriptSetup);
458
+ } catch (e) {
459
+ error = e;
460
+ content = compiled.content;
461
+ }
462
+ content = rewriteDefault(content, "_sfc_main", ["typescript", "decorators-legacy"]);
323
463
  if (scriptSetup) {
324
- const compiled = compileScript(descriptor, {
325
- id: `${index++}`
326
- });
327
- const classMatch = compiled.content.match(exportDefaultClassRE);
328
- const plugins = scriptSetup.lang === "ts" ? ["typescript", "decorators-legacy"] : void 0;
329
- if (classMatch) {
330
- content = compiled.content.replace(exportDefaultClassRE, "\nclass $1") + `
331
- const _sfc_main = ${classMatch[1]}`;
332
- if (exportDefaultRE.test(content)) {
333
- content = rewriteDefault(compiled.content, "_sfc_main", plugins);
334
- }
335
- } else {
336
- content = rewriteDefault(compiled.content, "_sfc_main", plugins);
337
- }
338
464
  content = transferSetupPosition(content);
339
- content = content.replace(/(const __returned__\s?=\s?\{[\s\S]+?)(props)(\s?\})/, "$1props: props as any$3").replace(
340
- /(const __returned__\s?=\s?\{[\s\S]+?)(props,)([\s\S]+?)/,
341
- "$1props: props as any,$3"
342
- );
343
- content += "\nexport default _sfc_main\n";
344
465
  ext = scriptSetup.lang || "js";
345
466
  } else if (script && script.content) {
346
- content = rewriteDefault(
347
- script.content,
348
- "_sfc_main",
349
- script.lang === "ts" ? ["typescript", "decorators-legacy"] : void 0
350
- );
351
- content += "\nexport default _sfc_main\n";
352
467
  ext = script.lang || "js";
353
468
  }
469
+ content += "\nexport default _sfc_main\n";
354
470
  } else {
355
471
  content = noScriptContent;
356
472
  ext = "ts";
357
473
  }
358
- return { content, ext };
474
+ return { error, content, ext };
359
475
  }
360
476
 
361
477
  const dtsRE$1 = /\.d\.tsx?$/;
362
478
  function rollupDeclarationFiles({
363
479
  root,
364
- tsConfigPath,
365
480
  outputDir,
366
481
  entryPath,
367
482
  fileName,
@@ -378,8 +493,10 @@ function rollupDeclarationFiles({
378
493
  projectFolder: root,
379
494
  mainEntryPointFilePath: entryPath,
380
495
  compiler: {
381
- tsconfigFilePath: tsConfigPath,
382
- overrideTsconfig: compilerOptions
496
+ overrideTsconfig: {
497
+ $schema: "http://json.schemastore.org/tsconfig",
498
+ compilerOptions
499
+ }
383
500
  },
384
501
  apiReport: {
385
502
  enabled: false,
@@ -444,13 +561,16 @@ const noneExport = "export {};\n";
444
561
  const vueRE = /\.vue$/;
445
562
  const tsRE = /\.(m|c)?tsx?$/;
446
563
  const jsRE = /\.(m|c)?jsx?$/;
447
- const dtsRE = /\.d\.tsx?$/;
564
+ const dtsRE = /\.d\.(m|c)?tsx?$/;
448
565
  const tjsRE = /\.(m|c)?(t|j)sx?$/;
566
+ const mtjsRE = /\.m(t|j)sx?$/;
567
+ const ctjsRE = /\.c(t|j)sx?$/;
449
568
  const watchExtensionRE = /\.(vue|(m|c)?(t|j)sx?)$/;
450
569
  const fullRelativeRE = /^\.\.?\//;
451
570
  const defaultIndex = "index.d.ts";
452
571
  const noop = () => {
453
572
  };
573
+ const extPrefix = (file) => mtjsRE.test(file) ? "m" : ctjsRE.test(file) ? "c" : "";
454
574
  const logPrefix = cyan("[vite:dts]");
455
575
  const bundleDebug = debug("vite-plugin-dts:bundle");
456
576
  function dtsPlugin(options = {}) {
@@ -471,7 +591,7 @@ function dtsPlugin(options = {}) {
471
591
  beforeWriteFile = noop,
472
592
  afterBuild = noop
473
593
  } = options;
474
- const compilerOptions = options.compilerOptions ?? {};
594
+ let compilerOptions = options.compilerOptions ?? {};
475
595
  let root;
476
596
  let entryRoot = options.entryRoot ?? "";
477
597
  let libName;
@@ -489,6 +609,7 @@ function dtsPlugin(options = {}) {
489
609
  const sourceDtsFiles = /* @__PURE__ */ new Set();
490
610
  let hasJsVue = false;
491
611
  let allowJs = false;
612
+ let transformError = false;
492
613
  return {
493
614
  name: "vite:dts",
494
615
  apply: "build",
@@ -545,7 +666,7 @@ ${cyan(
545
666
  libName = config.build.lib.name || "_default";
546
667
  indexName = typeof filename === "string" ? filename : filename("es", entry);
547
668
  if (!dtsRE.test(indexName)) {
548
- indexName = `${tjsRE.test(indexName) ? indexName.replace(tjsRE, "") : indexName}.d.ts`;
669
+ indexName = `${indexName.replace(tjsRE, "")}.d.${extPrefix(indexName)}ts`;
549
670
  }
550
671
  }
551
672
  root = ensureAbsolute(options.root ?? "", config.root);
@@ -564,32 +685,43 @@ ${cyan(
564
685
  return;
565
686
  }
566
687
  setCompileRoot(root);
567
- compilerOptions.rootDir || (compilerOptions.rootDir = root);
568
688
  project = new Project({
569
689
  compilerOptions: mergeObjects(compilerOptions, {
690
+ rootDir: compilerOptions.rootDir || root,
570
691
  noEmitOnError,
571
692
  outDir: ".",
572
- declarationDir: null,
693
+ declarationDir: void 0,
573
694
  noUnusedParameters: false,
574
695
  declaration: true,
575
696
  noEmit: false,
576
- emitDeclarationOnly: true
697
+ emitDeclarationOnly: true,
698
+ composite: false
577
699
  }),
578
700
  tsConfigFilePath: tsConfigPath,
579
701
  skipAddingFilesFromTsConfig: true,
580
702
  libFolderPath: libFolderPath ? ensureAbsolute(libFolderPath, root) : void 0
581
703
  });
582
704
  allowJs = project.getCompilerOptions().allowJs ?? false;
583
- const tsConfig = typescript.readConfigFile(tsConfigPath, project.getFileSystem().readFileSync).config ?? {};
584
- const parentTsConfigPath = tsConfig.extends && ensureAbsolute(tsConfig.extends, root);
585
- const parentTsConfig = parentTsConfigPath ? typescript.readConfigFile(parentTsConfigPath, project.getFileSystem().readFileSync).config : {};
586
- include = ensureArray(
587
- options.include ?? tsConfig.include ?? parentTsConfig.include ?? "**/*"
588
- ).map(normalizeGlob);
589
- exclude = ensureArray(
590
- options.exclude ?? tsConfig.exclude ?? parentTsConfig.exclude ?? "node_modules/**"
591
- ).map(normalizeGlob);
705
+ const tsConfig = { compilerOptions: {} };
706
+ const readFile = project.getFileSystem().readFileSync;
707
+ let currentConfigPath = tsConfigPath;
708
+ while (currentConfigPath) {
709
+ const currentConfig = typescript.readConfigFile(currentConfigPath, readFile).config ?? {};
710
+ Object.assign(tsConfig.compilerOptions, currentConfig.compilerOptions || {});
711
+ if (!tsConfig.include) {
712
+ tsConfig.include = currentConfig.include;
713
+ }
714
+ if (!tsConfig.exclude) {
715
+ tsConfig.exclude = currentConfig.exclude;
716
+ }
717
+ currentConfigPath = currentConfig.extends;
718
+ }
719
+ include = ensureArray(options.include ?? tsConfig.include ?? "**/*").map(normalizeGlob);
720
+ exclude = ensureArray(options.exclude ?? tsConfig.exclude ?? "node_modules/**").map(
721
+ normalizeGlob
722
+ );
592
723
  filter = createFilter(include, exclude, { resolve: root });
724
+ compilerOptions = tsConfig.compilerOptions;
593
725
  },
594
726
  buildStart(inputOptions) {
595
727
  if (Array.isArray(inputOptions.input)) {
@@ -606,7 +738,19 @@ ${cyan(
606
738
  return null;
607
739
  }
608
740
  if (vueRE.test(id)) {
609
- const { content, ext } = compileVueCode(code);
741
+ const { error, content, ext } = compileVueCode(code);
742
+ if (!transformError && error) {
743
+ logger.error(
744
+ red(
745
+ `
746
+ ${cyan(
747
+ "[vite:dts]"
748
+ )} A error occurred when transform code, maybe there are some inertnal bugs.
749
+ `
750
+ )
751
+ );
752
+ transformError = true;
753
+ }
610
754
  if (content) {
611
755
  if (ext === "js" || ext === "jsx")
612
756
  hasJsVue = true;
@@ -651,7 +795,7 @@ ${logPrefix} Start generate declaration files...`));
651
795
  includedFileSet.add(file);
652
796
  return;
653
797
  }
654
- includedFileSet.add(`${tjsRE.test(file) ? file.replace(tjsRE, "") : file}.d.ts`);
798
+ includedFileSet.add(`${file.replace(tjsRE, "")}.d.${extPrefix(file)}ts`);
655
799
  });
656
800
  if (hasJsVue) {
657
801
  if (!allowJs) {
@@ -782,7 +926,6 @@ export default ${libName}
782
926
  const path = resolve(outputDir, `${name.replace(tsRE, "")}.d.ts`);
783
927
  rollupDeclarationFiles({
784
928
  root,
785
- tsConfigPath,
786
929
  compilerOptions,
787
930
  outputDir,
788
931
  entryPath: path,
@@ -795,7 +938,6 @@ export default ${libName}
795
938
  } else {
796
939
  rollupDeclarationFiles({
797
940
  root,
798
- tsConfigPath,
799
941
  compilerOptions,
800
942
  outputDir,
801
943
  entryPath: typesPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-dts",
3
- "version": "1.7.2",
3
+ "version": "2.0.0-beta.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "qmhc",
@@ -53,6 +53,7 @@
53
53
  "typescript"
54
54
  ],
55
55
  "dependencies": {
56
+ "@babel/parser": "^7.20.15",
56
57
  "@microsoft/api-extractor": "^7.33.5",
57
58
  "@rollup/pluginutils": "^5.0.2",
58
59
  "@rushstack/node-core-library": "^3.53.2",
@@ -60,9 +61,11 @@
60
61
  "fast-glob": "^3.2.12",
61
62
  "fs-extra": "^10.1.0",
62
63
  "kolorist": "^1.6.0",
64
+ "magic-string": "^0.29.0",
63
65
  "ts-morph": "17.0.1"
64
66
  },
65
67
  "devDependencies": {
68
+ "@babel/types": "^7.20.7",
66
69
  "@commitlint/cli": "^17.1.2",
67
70
  "@commitlint/config-conventional": "^17.1.0",
68
71
  "@types/debug": "^4.1.7",