diff --git a/e2e/cases/dts/bundle-false/__fixtures__/tsconfig.json b/e2e/cases/dts/bundle-false/__fixtures__/tsconfig.json index 0fccc577..888d3e46 100644 --- a/e2e/cases/dts/bundle-false/__fixtures__/tsconfig.json +++ b/e2e/cases/dts/bundle-false/__fixtures__/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "@rslib/tsconfig/base", "compilerOptions": { - "baseUrl": "./", - "rootDir": "src" + "baseUrl": "./" }, "include": ["src"] } diff --git a/e2e/cases/dts/bundle-false/abort-on-error/tsconfig.json b/e2e/cases/dts/bundle-false/abort-on-error/tsconfig.json index 0fccc577..888d3e46 100644 --- a/e2e/cases/dts/bundle-false/abort-on-error/tsconfig.json +++ b/e2e/cases/dts/bundle-false/abort-on-error/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "@rslib/tsconfig/base", "compilerOptions": { - "baseUrl": "./", - "rootDir": "src" + "baseUrl": "./" }, "include": ["src"] } diff --git a/e2e/cases/dts/bundle/__fixtures__/tsconfig.json b/e2e/cases/dts/bundle/__fixtures__/tsconfig.json index 0fccc577..888d3e46 100644 --- a/e2e/cases/dts/bundle/__fixtures__/tsconfig.json +++ b/e2e/cases/dts/bundle/__fixtures__/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "@rslib/tsconfig/base", "compilerOptions": { - "baseUrl": "./", - "rootDir": "src" + "baseUrl": "./" }, "include": ["src"] } diff --git a/e2e/cases/dts/bundle/abort-on-error/tsconfig.json b/e2e/cases/dts/bundle/abort-on-error/tsconfig.json index 0fccc577..888d3e46 100644 --- a/e2e/cases/dts/bundle/abort-on-error/tsconfig.json +++ b/e2e/cases/dts/bundle/abort-on-error/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "@rslib/tsconfig/base", "compilerOptions": { - "baseUrl": "./", - "rootDir": "src" + "baseUrl": "./" }, "include": ["src"] } diff --git a/packages/plugin-dts/src/apiExtractor.ts b/packages/plugin-dts/src/apiExtractor.ts index 32660fc0..0ebeb59a 100644 --- a/packages/plugin-dts/src/apiExtractor.ts +++ b/packages/plugin-dts/src/apiExtractor.ts @@ -73,7 +73,7 @@ export async function bundleDts(options: BundleOptions): Promise { `API Extractor bundle DTS succeeded: ${color.cyan(untrimmedFilePath)} in ${getTimeCost(start)} ${color.gray(`(${name})`)}`, ); } catch (e) { - logger.error('API Extractor', e); - throw new Error('API Extractor rollup error'); + logger.error('API Extractor Error'); + throw new Error(`${e}`); } } diff --git a/packages/plugin-dts/src/dts.ts b/packages/plugin-dts/src/dts.ts index 13717f6f..6ceb4af4 100644 --- a/packages/plugin-dts/src/dts.ts +++ b/packages/plugin-dts/src/dts.ts @@ -5,7 +5,11 @@ import color from 'picocolors'; import type { DtsGenOptions } from 'src'; import * as ts from 'typescript'; import { emitDts } from './tsc'; -import { ensureTempDeclarationDir, loadTsconfig } from './utils'; +import { + calcLongestCommonPath, + ensureTempDeclarationDir, + loadTsconfig, +} from './utils'; const isObject = (obj: unknown): obj is Record => Object.prototype.toString.call(obj) === '[object Object]'; @@ -115,8 +119,12 @@ export async function generateDts(data: DtsGenOptions): Promise { logger.error(`tsconfig.json not found in ${cwd}`); throw new Error(); } - const { options: rawCompilerOptions } = loadTsconfig(configPath); - const rootDir = rawCompilerOptions.rootDir ?? 'src'; + const { options: rawCompilerOptions, fileNames } = loadTsconfig(configPath); + const rootDir = + rawCompilerOptions.rootDir ?? + (await calcLongestCommonPath(fileNames)) ?? + dirname(configPath); + const outDir = distPath ? distPath : rawCompilerOptions.declarationDir || './dist'; @@ -178,7 +186,6 @@ export async function generateDts(data: DtsGenOptions): Promise { name, cwd, configPath, - rootDir, declarationDir, dtsExtension, }, diff --git a/packages/plugin-dts/src/index.ts b/packages/plugin-dts/src/index.ts index b47fa2ce..64f256a0 100644 --- a/packages/plugin-dts/src/index.ts +++ b/packages/plugin-dts/src/index.ts @@ -41,7 +41,6 @@ export const PLUGIN_DTS_NAME = 'rsbuild:dts'; // use ts compiler API to generate bundleless dts // use ts compiler API and api-extractor to generate dts bundle // TODO: support incremental build, to build one or more projects and their dependencies -// TODO: support autoExtension for dts files // TODO: deal alias in dts export const pluginDts = (options: PluginDtsOptions): RsbuildPlugin => ({ name: PLUGIN_DTS_NAME, diff --git a/packages/plugin-dts/src/tsc.ts b/packages/plugin-dts/src/tsc.ts index 957635f3..79dc3983 100644 --- a/packages/plugin-dts/src/tsc.ts +++ b/packages/plugin-dts/src/tsc.ts @@ -12,7 +12,6 @@ export type EmitDtsOptions = { name: string; cwd: string; configPath: string; - rootDir: string; declarationDir: string; dtsExtension: string; }; diff --git a/packages/plugin-dts/src/utils.ts b/packages/plugin-dts/src/utils.ts index 94200655..cba3bc1d 100644 --- a/packages/plugin-dts/src/utils.ts +++ b/packages/plugin-dts/src/utils.ts @@ -1,4 +1,5 @@ import fs from 'node:fs'; +import fsP from 'node:fs/promises'; import path from 'node:path'; import { type RsbuildConfig, logger } from '@rsbuild/core'; import fg from 'fast-glob'; @@ -97,3 +98,35 @@ export function processSourceEntry( '@microsoft/api-extractor only support single entry of Record type to bundle DTS, please check your entry config.', ); } + +// same as @rslib/core, we should extract into a single published package to share +export async function calcLongestCommonPath( + absPaths: string[], +): Promise { + if (absPaths.length === 0) { + return null; + } + + const splitPaths = absPaths.map((p) => p.split(path.sep)); + let lcaFragments = splitPaths[0]!; + for (let i = 1; i < splitPaths.length; i++) { + const currentPath = splitPaths[i]!; + const minLength = Math.min(lcaFragments.length, currentPath.length); + + let j = 0; + while (j < minLength && lcaFragments[j] === currentPath[j]) { + j++; + } + + lcaFragments = lcaFragments.slice(0, j); + } + + let lca = lcaFragments.length > 0 ? lcaFragments.join(path.sep) : '/'; + + const stats = await fsP.stat(lca); + if (stats?.isFile()) { + lca = path.dirname(lca); + } + + return lca; +}