Skip to content

Commit 4ad5a76

Browse files
committed
fix: should dynamic load api-extractor when bundling
fix #435
1 parent ffc88c2 commit 4ad5a76

File tree

4 files changed

+72
-54
lines changed

4 files changed

+72
-54
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ await build({
222222
</details>
223223

224224
<br />
225+
225226
By default, the generated declaration files are following the source structure.
226227

227228
Fortunately, with the help of [API Extractor](https://api-extractor.com/), the plugin can bundle all types into a single file. You just need to install `@microsoft/api-extractor` and set `bundleTypes: true`:

README.zh-CN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ await build({
222222
</details>
223223

224224
<br />
225+
225226
默认情况,生成的类型文件会跟随源文件的结构。
226227

227228
好在插件借助 [API Extractor](https://api-extractor.com/) 提供了汇总所有类型到一个文件的能力,只需安装 `@microsoft/api-extractor` 并指定 `bundleTypes: true`

packages/unplugin-dts/src/core/bundle.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { Extractor, ExtractorConfig } from '@microsoft/api-extractor'
2-
import { resolve, tryGetPkgPath } from './utils'
1+
import { resolve, tryGetPackageInfo, tryGetPkgPath } from './utils'
32

43
import type { ExtractorLogLevel, IExtractorInvokeOptions } from '@microsoft/api-extractor'
54
import type { BundleConfig } from './types'
@@ -17,9 +16,15 @@ export interface BundleDtsOptions {
1716
invokeOptions?: IExtractorInvokeOptions
1817
}
1918

19+
let hasExtractor: boolean | undefined
20+
21+
export function getHasExtractor() {
22+
return typeof hasExtractor !== 'undefined' ? hasExtractor : (hasExtractor = !!tryGetPackageInfo('@microsoft/api-extractor'))
23+
}
24+
2025
const dtsRE = /\.d\.(m|c)?tsx?$/
2126

22-
export function bundleDtsFiles({
27+
export async function bundleDtsFiles({
2328
root,
2429
configPath,
2530
compilerOptions,
@@ -31,6 +36,8 @@ export function bundleDtsFiles({
3136
bundledPackages,
3237
invokeOptions = {},
3338
}: BundleDtsOptions) {
39+
const { Extractor, ExtractorConfig } = await import('@microsoft/api-extractor')
40+
3441
const configObjectFullPath = resolve(root, 'api-extractor.json')
3542

3643
if (!dtsRE.test(fileName)) {

packages/unplugin-dts/src/core/runtime.ts

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import { cpus } from 'node:os'
55

66
import ts from 'typescript'
77
import { createFilter } from '@rollup/pluginutils'
8-
import { green, yellow } from 'kolorist'
8+
import { green, red, yellow } from 'kolorist'
99
import { loadProgramProcesses } from './program'
1010
import { JsonResolver, SvelteResolver, VueResolver, parseResolvers } from './resolvers'
1111
import { hasExportDefault, hasNormalExport, normalizeGlob, transformCode } from './transform'
12-
import { bundleDtsFiles } from './bundle'
12+
import { bundleDtsFiles, getHasExtractor } from './bundle'
1313
import {
1414
defaultIndex,
1515
dtsRE,
@@ -657,58 +657,67 @@ export class Runtime {
657657
handleDebug('insert index')
658658

659659
if (bundleTypes) {
660-
logger.info(green(`${logPrefix} Start rollup declaration files...`))
661-
662-
const rollupFiles = new Set<string>()
663-
const compilerOptions = configPath
664-
? getTsConfig(configPath, this.host.readFile).compilerOptions
665-
: rawCompilerOptions
666-
667-
const rollup = async (path: string) => {
668-
const result = bundleDtsFiles({
669-
root,
670-
configPath,
671-
compilerOptions,
672-
outDir,
673-
entryPath: path,
674-
fileName: basename(path),
675-
libFolder: getTsLibFolder(),
676-
extractorConfig,
677-
bundledPackages,
678-
invokeOptions,
679-
})
680-
681-
emittedFiles.delete(path)
682-
rollupFiles.add(path)
683-
684-
if (typeof afterRollup === 'function') {
685-
await unwrapPromise(afterRollup(result))
660+
logger.info(green(`${logPrefix} Start bundling declaration files...`))
661+
662+
if (!getHasExtractor()) {
663+
logger.error(
664+
`\n${logPrefix} ${red("Failed to load '@microsoft/api-extractor', have you installed it?")}\n`,
665+
)
666+
logger.warn(
667+
`\n${logPrefix} ${yellow('Error occurred, skip bundle declaration files.')}\n`,
668+
)
669+
} else {
670+
const rollupFiles = new Set<string>()
671+
const compilerOptions = configPath
672+
? getTsConfig(configPath, this.host.readFile).compilerOptions
673+
: rawCompilerOptions
674+
675+
const rollup = async (path: string) => {
676+
const result = await bundleDtsFiles({
677+
root,
678+
configPath,
679+
compilerOptions,
680+
outDir,
681+
entryPath: path,
682+
fileName: basename(path),
683+
libFolder: getTsLibFolder(),
684+
extractorConfig,
685+
bundledPackages,
686+
invokeOptions,
687+
})
688+
689+
emittedFiles.delete(path)
690+
rollupFiles.add(path)
691+
692+
if (typeof afterRollup === 'function') {
693+
await unwrapPromise(afterRollup(result))
694+
}
686695
}
687-
}
688-
689-
if (multiple) {
690-
await runParallel(cpus().length, entryNames, async name => {
691-
await rollup(cleanPath(resolve(outDir, tsToDts(name)), emittedFiles))
696+
697+
if (multiple) {
698+
await runParallel(cpus().length, entryNames, async name => {
699+
await rollup(cleanPath(resolve(outDir, tsToDts(name)), emittedFiles))
700+
})
701+
} else {
702+
await rollup(typesPath)
703+
}
704+
705+
await runParallel(cpus().length, Array.from(emittedFiles.keys()), f => unlink(f))
706+
removeDirIfEmpty(outDir)
707+
emittedFiles.clear()
708+
709+
const declared = declareModules.join('\n')
710+
711+
await runParallel(cpus().length, [...rollupFiles], async filePath => {
712+
await writeOutput(
713+
filePath,
714+
(await readFile(filePath, 'utf-8')) + (declared ? `\n${declared}` : ''),
715+
dirname(filePath),
716+
)
692717
})
693-
} else {
694-
await rollup(typesPath)
718+
719+
handleDebug('rollup output')
695720
}
696-
697-
await runParallel(cpus().length, Array.from(emittedFiles.keys()), f => unlink(f))
698-
removeDirIfEmpty(outDir)
699-
emittedFiles.clear()
700-
701-
const declared = declareModules.join('\n')
702-
703-
await runParallel(cpus().length, [...rollupFiles], async filePath => {
704-
await writeOutput(
705-
filePath,
706-
(await readFile(filePath, 'utf-8')) + (declared ? `\n${declared}` : ''),
707-
dirname(filePath),
708-
)
709-
})
710-
711-
handleDebug('rollup output')
712721
}
713722
}
714723

0 commit comments

Comments
 (0)