diff --git a/packages/plugin-dts/src/apiExtractor.ts b/packages/plugin-dts/src/apiExtractor.ts index 0032d7a1a..3ca45697e 100644 --- a/packages/plugin-dts/src/apiExtractor.ts +++ b/packages/plugin-dts/src/apiExtractor.ts @@ -2,6 +2,7 @@ import { join, relative } from 'node:path'; import { Extractor, ExtractorConfig, + ExtractorLogLevel, type ExtractorResult, } from '@microsoft/api-extractor'; import { logger } from '@rsbuild/core'; @@ -9,6 +10,8 @@ import color from 'picocolors'; import type { DtsEntry } from './index'; import { addBannerAndFooter, getTimeCost } from './utils'; +const logPrefixApiExtractor = color.dim('[api-extractor]'); + export type BundleOptions = { name: string; cwd: string; @@ -66,6 +69,20 @@ export async function bundleDts(options: BundleOptions): Promise { extractorConfig, { localBuild: true, + messageCallback(message) { + /** + * message.text is readonly, we can not add prefix + * do not log below two cases + * 1. Analysis will use the bundled TypeScript version 5.7.3 + * 2. The target project appears to use TypeScript 5.8.2 which is newer than the bundled compiler engine; consider upgrading API Extractor. + */ + if ( + message.messageId === 'console-compiler-version-notice' || + message.messageId === 'console-preamble' + ) { + message.logLevel = ExtractorLogLevel.None; + } + }, }, ); @@ -75,12 +92,12 @@ export async function bundleDts(options: BundleOptions): Promise { await addBannerAndFooter(untrimmedFilePath, banner, footer); - logger.info( - `bundle declaration files succeeded: ${color.cyan(untrimmedFilePath)} in ${getTimeCost(start)} ${color.gray(`(${name})`)}`, + logger.ready( + `declaration files bundled successfully: ${color.cyan(relative(cwd, untrimmedFilePath))} in ${getTimeCost(start)} ${color.gray(`(${name})`)}`, ); }), ); } catch (e) { - throw new Error(`API Extractor Error:\n ${e}`); + throw new Error(`${logPrefixApiExtractor} ${e}`); } } diff --git a/packages/plugin-dts/src/dts.ts b/packages/plugin-dts/src/dts.ts index f7579a9f0..5d9a0398f 100644 --- a/packages/plugin-dts/src/dts.ts +++ b/packages/plugin-dts/src/dts.ts @@ -126,7 +126,9 @@ export async function generateDts(data: DtsGenOptions): Promise { extension: false, }, } = data; - logger.start(`generating declaration files... ${color.gray(`(${name})`)}`); + if (!isWatch) { + logger.start(`generating declaration files... ${color.gray(`(${name})`)}`); + } const { options: rawCompilerOptions, fileNames } = tsConfigResult; diff --git a/packages/plugin-dts/src/tsc.ts b/packages/plugin-dts/src/tsc.ts index f404fbc95..6baa04334 100644 --- a/packages/plugin-dts/src/tsc.ts +++ b/packages/plugin-dts/src/tsc.ts @@ -2,9 +2,15 @@ import { logger } from '@rsbuild/core'; import color from 'picocolors'; import ts from 'typescript'; import type { DtsRedirect } from './index'; -import { getFileLoc, getTimeCost, processDtsFiles } from './utils'; +import { getTimeCost, processDtsFiles } from './utils'; -const logPrefix = color.dim('[tsc]'); +const logPrefixTsc = color.dim('[tsc]'); + +const formatHost: ts.FormatDiagnosticsHost = { + getCanonicalFileName: (path) => path, + getCurrentDirectory: ts.sys.getCurrentDirectory, + getNewLine: () => ts.sys.newLine, +}; export type EmitDtsOptions = { name: string; @@ -22,7 +28,6 @@ export type EmitDtsOptions = { async function handleDiagnosticsAndProcessFiles( diagnostics: readonly ts.Diagnostic[], configPath: string, - host: ts.CompilerHost, bundle: boolean, declarationDir: string, dtsExtension: string, @@ -35,11 +40,10 @@ async function handleDiagnosticsAndProcessFiles( const diagnosticMessages: string[] = []; for (const diagnostic of diagnostics) { - const fileLoc = getFileLoc(diagnostic, configPath); - const message = `${fileLoc} - ${color.red('error')} ${color.gray(`TS${diagnostic.code}:`)} ${ts.flattenDiagnosticMessageText( - diagnostic.messageText, - host.getNewLine(), - )}`; + const message = ts.formatDiagnosticsWithColorAndContext( + [diagnostic], + formatHost, + ); diagnosticMessages.push(message); } @@ -56,7 +60,7 @@ async function handleDiagnosticsAndProcessFiles( if (diagnosticMessages.length) { for (const message of diagnosticMessages) { - logger.error(logPrefix, message); + logger.error(logPrefixTsc, message); } throw new Error( @@ -100,22 +104,11 @@ export async function emitDts( }; const createProgram = ts.createSemanticDiagnosticsBuilderProgram; - const formatHost: ts.FormatDiagnosticsHost = { - getCanonicalFileName: (path) => path, - getCurrentDirectory: ts.sys.getCurrentDirectory, - getNewLine: () => ts.sys.newLine, - }; const reportDiagnostic = (diagnostic: ts.Diagnostic) => { - const fileLoc = getFileLoc(diagnostic, configPath); - logger.error( - logPrefix, - `${fileLoc} - ${color.red('error')} ${color.gray(`TS${diagnostic.code}:`)}`, - ts.flattenDiagnosticMessageText( - diagnostic.messageText, - formatHost.getNewLine(), - ), + logPrefixTsc, + ts.formatDiagnosticsWithColorAndContext([diagnostic], formatHost), ); }; @@ -133,16 +126,16 @@ export async function emitDts( // 6031: File change detected. Starting incremental compilation... // 6032: Starting compilation in watch mode... if (diagnostic.code === 6031 || diagnostic.code === 6032) { - logger.info(logPrefix, message); + logger.info(logPrefixTsc, message); } // 6194: 0 errors or 2+ errors! if (diagnostic.code === 6194) { if (errorCount === 0 || !errorCount) { - logger.info(logPrefix, message); + logger.info(logPrefixTsc, message); onComplete(true); } else { - logger.error(logPrefix, message); + logger.error(logPrefixTsc, message); } await processDtsFiles( bundle, @@ -158,7 +151,7 @@ export async function emitDts( // 6193: 1 error if (diagnostic.code === 6193) { - logger.error(logPrefix, message); + logger.error(logPrefixTsc, message); await processDtsFiles( bundle, declarationDir, @@ -198,7 +191,6 @@ export async function emitDts( await handleDiagnosticsAndProcessFiles( allDiagnostics, configPath, - host, bundle, declarationDir, dtsExtension, @@ -232,7 +224,6 @@ export async function emitDts( await handleDiagnosticsAndProcessFiles( allDiagnostics, configPath, - host, bundle, declarationDir, dtsExtension, @@ -284,9 +275,15 @@ export async function emitDts( } } - logger.ready( - `declaration files generated in ${getTimeCost(start)} ${color.gray(`(${name})`)}`, - ); + if (bundle) { + logger.info( + `declaration files prepared in ${getTimeCost(start)} ${color.gray(`(${name})`)}`, + ); + } else { + logger.ready( + `declaration files generated in ${getTimeCost(start)} ${color.gray(`(${name})`)}`, + ); + } } else { // watch mode, can also deal with incremental build if (!build) {