rsbuild-plugin-dts 0.9.1 → 0.10.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/apiExtractor.js +16 -12
- package/dist/dts.js +19 -19
- package/dist/index.js +30 -25
- package/dist/tsc.js +45 -39
- package/dist/utils.js +73 -67
- package/package.json +3 -3
package/dist/apiExtractor.js
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
const logPrefixApiExtractor =
|
|
1
|
+
import { join, relative } from "node:path";
|
|
2
|
+
import { logger } from "@rsbuild/core";
|
|
3
|
+
import external_picocolors_default from "picocolors";
|
|
4
|
+
import { addBannerAndFooter, getTimeCost } from "./utils.js";
|
|
5
|
+
const logPrefixApiExtractor = external_picocolors_default.dim('[api-extractor]');
|
|
6
6
|
async function bundleDts(options) {
|
|
7
7
|
let apiExtractor;
|
|
8
8
|
try {
|
|
9
9
|
apiExtractor = await import("@microsoft/api-extractor");
|
|
10
10
|
} catch {
|
|
11
|
-
|
|
11
|
+
const error = new Error(`${external_picocolors_default.cyan('@microsoft/api-extractor')} is required when ${external_picocolors_default.cyan('dts.bundle')} is set to ${external_picocolors_default.cyan('true')}, please make sure it is installed. You could check https://rslib.rs/guide/advanced/dts#how-to-generate-declaration-files-in-rslib for more details.`);
|
|
12
|
+
error.stack = '';
|
|
13
|
+
throw error;
|
|
12
14
|
}
|
|
13
15
|
const { Extractor, ExtractorConfig, ExtractorLogLevel } = apiExtractor;
|
|
14
16
|
const { name, cwd, distPath, dtsExtension, banner, footer, dtsEntry, tsconfigPath = 'tsconfig.json', bundledPackages = [] } = options;
|
|
15
17
|
try {
|
|
16
18
|
await Promise.all(dtsEntry.map(async (entry)=>{
|
|
17
19
|
const start = Date.now();
|
|
18
|
-
const untrimmedFilePath =
|
|
20
|
+
const untrimmedFilePath = join(cwd, relative(cwd, distPath), `${entry.name}${dtsExtension}`);
|
|
19
21
|
const mainEntryPointFilePath = entry.path.replace(/\?.*$/, '');
|
|
20
22
|
const internalConfig = {
|
|
21
23
|
mainEntryPointFilePath,
|
|
@@ -32,7 +34,7 @@ async function bundleDts(options) {
|
|
|
32
34
|
const extractorConfig = ExtractorConfig.prepare({
|
|
33
35
|
configObject: internalConfig,
|
|
34
36
|
configObjectFullPath: void 0,
|
|
35
|
-
packageJsonFullPath:
|
|
37
|
+
packageJsonFullPath: join(cwd, 'package.json')
|
|
36
38
|
});
|
|
37
39
|
const extractorResult = Extractor.invoke(extractorConfig, {
|
|
38
40
|
localBuild: true,
|
|
@@ -40,12 +42,14 @@ async function bundleDts(options) {
|
|
|
40
42
|
if ('console-compiler-version-notice' === message.messageId || 'console-preamble' === message.messageId) message.logLevel = ExtractorLogLevel.None;
|
|
41
43
|
}
|
|
42
44
|
});
|
|
43
|
-
if (!extractorResult.succeeded) throw new Error(`API Extractor error. ${
|
|
44
|
-
await
|
|
45
|
-
|
|
45
|
+
if (!extractorResult.succeeded) throw new Error(`API Extractor error. ${external_picocolors_default.gray(`(${name})`)}`);
|
|
46
|
+
await addBannerAndFooter(untrimmedFilePath, banner, footer);
|
|
47
|
+
logger.ready(`declaration files bundled successfully: ${external_picocolors_default.cyan(relative(cwd, untrimmedFilePath))} in ${getTimeCost(start)} ${external_picocolors_default.gray(`(${name})`)}`);
|
|
46
48
|
}));
|
|
47
49
|
} catch (e) {
|
|
48
|
-
|
|
50
|
+
const error = new Error(`${logPrefixApiExtractor} ${e}`);
|
|
51
|
+
error.stack = '';
|
|
52
|
+
throw error;
|
|
49
53
|
}
|
|
50
54
|
}
|
|
51
55
|
export { bundleDts };
|
package/dist/dts.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
1
|
+
import external_node_fs_default from "node:fs";
|
|
2
|
+
import { basename, dirname, isAbsolute, join, normalize, relative, resolve } from "node:path";
|
|
3
|
+
import { logger } from "@rsbuild/core";
|
|
4
|
+
import external_picocolors_default from "picocolors";
|
|
5
|
+
import { emitDts } from "./tsc.js";
|
|
6
|
+
import { calcLongestCommonPath, ensureTempDeclarationDir } from "./utils.js";
|
|
7
7
|
const isObject = (obj)=>'[object Object]' === Object.prototype.toString.call(obj);
|
|
8
8
|
const calcBundledPackages = (options)=>{
|
|
9
9
|
const { cwd, autoExternal, userExternals, overrideBundledPackages } = options;
|
|
10
10
|
if (overrideBundledPackages) return overrideBundledPackages;
|
|
11
11
|
let pkgJson;
|
|
12
12
|
try {
|
|
13
|
-
const content =
|
|
13
|
+
const content = external_node_fs_default.readFileSync(join(cwd, 'package.json'), 'utf-8');
|
|
14
14
|
pkgJson = JSON.parse(content);
|
|
15
15
|
} catch (err) {
|
|
16
|
-
|
|
16
|
+
logger.warn('The type of third-party packages will not be bundled due to read package.json failed');
|
|
17
17
|
return [];
|
|
18
18
|
}
|
|
19
19
|
const externalOptions = autoExternal ? {
|
|
@@ -57,25 +57,25 @@ async function generateDts(data) {
|
|
|
57
57
|
path: true,
|
|
58
58
|
extension: false
|
|
59
59
|
} } = data;
|
|
60
|
-
if (!isWatch)
|
|
60
|
+
if (!isWatch) logger.start(`generating declaration files... ${external_picocolors_default.gray(`(${name})`)}`);
|
|
61
61
|
const { options: rawCompilerOptions, fileNames } = tsConfigResult;
|
|
62
|
-
const rootDir = rawCompilerOptions.rootDir ?? (rawCompilerOptions.composite ?
|
|
63
|
-
const resolvedDtsEmitPath =
|
|
62
|
+
const rootDir = rawCompilerOptions.rootDir ?? (rawCompilerOptions.composite ? dirname(tsconfigPath) : await calcLongestCommonPath(fileNames.filter((fileName)=>!/\.d\.(ts|mts|cts)$/.test(fileName)))) ?? dirname(tsconfigPath);
|
|
63
|
+
const resolvedDtsEmitPath = normalize(resolve(dirname(tsconfigPath), dtsEmitPath));
|
|
64
64
|
if (build) {
|
|
65
65
|
if (bundle) throw Error('Can not set "dts.bundle: true" when "dts.build: true"');
|
|
66
|
-
if ((!rawCompilerOptions.outDir ||
|
|
66
|
+
if ((!rawCompilerOptions.outDir || normalize(rawCompilerOptions.outDir) !== resolvedDtsEmitPath) && (!rawCompilerOptions.declarationDir || normalize(rawCompilerOptions.declarationDir) !== resolvedDtsEmitPath)) {
|
|
67
67
|
const info = rawCompilerOptions.outDir && !rawCompilerOptions.declarationDir ? 'outDir' : 'declarationDir';
|
|
68
|
-
throw Error(`Please set ${info}: "${dtsEmitPath}" in ${
|
|
68
|
+
throw Error(`Please set ${info}: "${dtsEmitPath}" in ${external_picocolors_default.underline(tsconfigPath)} to keep it same as "dts.distPath" or "output.distPath.root" field in lib config.`);
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
const declarationDir = bundle ?
|
|
71
|
+
const declarationDir = bundle ? ensureTempDeclarationDir(cwd, name) : dtsEmitPath;
|
|
72
72
|
let dtsEntries = [];
|
|
73
73
|
if (true === bundle) dtsEntries = dtsEntry.map((entryObj)=>{
|
|
74
74
|
const { name: entryName, path: entryPath } = entryObj;
|
|
75
75
|
if (!entryPath) return null;
|
|
76
|
-
const entrySourcePath =
|
|
77
|
-
const relativePath =
|
|
78
|
-
const newPath =
|
|
76
|
+
const entrySourcePath = isAbsolute(entryPath) ? entryPath : join(cwd, entryPath);
|
|
77
|
+
const relativePath = relative(rootDir, dirname(entrySourcePath));
|
|
78
|
+
const newPath = join(declarationDir, relativePath, basename(entrySourcePath)).replace(/\.(js|mjs|jsx|ts|mts|tsx|cjs|cts|cjsx|ctsx|mjsx|mtsx)$/, '.d.ts');
|
|
79
79
|
return {
|
|
80
80
|
name: entryName,
|
|
81
81
|
path: newPath
|
|
@@ -105,7 +105,7 @@ async function generateDts(data) {
|
|
|
105
105
|
const onComplete = async (isSuccess)=>{
|
|
106
106
|
if (isSuccess) await bundleDtsIfNeeded();
|
|
107
107
|
};
|
|
108
|
-
await
|
|
108
|
+
await emitDts({
|
|
109
109
|
name,
|
|
110
110
|
cwd,
|
|
111
111
|
configPath: tsconfigPath,
|
|
@@ -124,7 +124,7 @@ process.on('message', async (data)=>{
|
|
|
124
124
|
try {
|
|
125
125
|
await generateDts(data);
|
|
126
126
|
} catch (e) {
|
|
127
|
-
|
|
127
|
+
logger.error(e);
|
|
128
128
|
process.send('error');
|
|
129
129
|
process.exit(1);
|
|
130
130
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
const src_filename =
|
|
9
|
-
const src_dirname =
|
|
1
|
+
import { fork } from "node:child_process";
|
|
2
|
+
import { dirname, extname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { logger } from "@rsbuild/core";
|
|
5
|
+
import external_picocolors_default from "picocolors";
|
|
6
|
+
import external_typescript_default from "typescript";
|
|
7
|
+
import { cleanDtsFiles, cleanTsBuildInfoFile, clearTempDeclarationDir, getDtsEmitPath, loadTsconfig, processSourceEntry, warnIfOutside } from "./utils.js";
|
|
8
|
+
const src_filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const src_dirname = dirname(src_filename);
|
|
10
10
|
const PLUGIN_DTS_NAME = 'rsbuild:dts';
|
|
11
11
|
const pluginDts = (options = {})=>({
|
|
12
12
|
name: PLUGIN_DTS_NAME,
|
|
@@ -27,24 +27,25 @@ const pluginDts = (options = {})=>({
|
|
|
27
27
|
api.onBeforeEnvironmentCompile(async ({ isWatch, isFirstCompile, environment })=>{
|
|
28
28
|
if (!isFirstCompile) return;
|
|
29
29
|
const { config } = environment;
|
|
30
|
-
const dtsEntry =
|
|
30
|
+
const dtsEntry = processSourceEntry(bundle, config.source?.entry);
|
|
31
31
|
const cwd = api.context.rootPath;
|
|
32
|
-
const tsconfigPath =
|
|
32
|
+
const tsconfigPath = external_typescript_default.findConfigFile(cwd, external_typescript_default.sys.fileExists, config.source.tsconfigPath);
|
|
33
33
|
if (!tsconfigPath) {
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
const error = new Error(`Failed to resolve tsconfig file ${external_picocolors_default.cyan(`"${config.source.tsconfigPath}"`)} from ${external_picocolors_default.cyan(cwd)}. Please ensure that the file exists.`);
|
|
35
|
+
error.stack = '';
|
|
36
|
+
throw error;
|
|
36
37
|
}
|
|
37
|
-
const tsConfigResult =
|
|
38
|
+
const tsConfigResult = loadTsconfig(tsconfigPath);
|
|
38
39
|
const { options: rawCompilerOptions } = tsConfigResult;
|
|
39
40
|
const { declarationDir, outDir, composite, incremental } = rawCompilerOptions;
|
|
40
|
-
const dtsEmitPath =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (false !== config.output.cleanDistPath) await
|
|
44
|
-
if (bundle) await
|
|
45
|
-
if (composite || incremental || options.build) await
|
|
46
|
-
const jsExtension =
|
|
47
|
-
const childProcess =
|
|
41
|
+
const dtsEmitPath = getDtsEmitPath(options.distPath, declarationDir, config.output?.distPath?.root);
|
|
42
|
+
warnIfOutside(cwd, declarationDir, 'declarationDir');
|
|
43
|
+
warnIfOutside(cwd, outDir, 'outDir');
|
|
44
|
+
if (false !== config.output.cleanDistPath) await cleanDtsFiles(dtsEmitPath);
|
|
45
|
+
if (bundle) await clearTempDeclarationDir(cwd);
|
|
46
|
+
if (composite || incremental || options.build) await cleanTsBuildInfoFile(tsconfigPath, rawCompilerOptions);
|
|
47
|
+
const jsExtension = extname(src_filename);
|
|
48
|
+
const childProcess = fork(join(src_dirname, `./dts${jsExtension}`), [], {
|
|
48
49
|
stdio: 'inherit'
|
|
49
50
|
});
|
|
50
51
|
childProcesses.push(childProcess);
|
|
@@ -84,9 +85,13 @@ const pluginDts = (options = {})=>({
|
|
|
84
85
|
api.onAfterBuild(({ isFirstCompile })=>{
|
|
85
86
|
if (!isFirstCompile) return;
|
|
86
87
|
for (const result of promisesResult)if ('error' === result.status) {
|
|
87
|
-
if (options.abortOnError)
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
if (options.abortOnError) {
|
|
89
|
+
const error = new Error(result.errorMessage);
|
|
90
|
+
error.stack = '';
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
result.errorMessage && logger.error(result.errorMessage);
|
|
94
|
+
logger.warn('With `abortOnError` configuration currently disabled, type errors will not fail the build, but proper type declaration output cannot be guaranteed.');
|
|
90
95
|
}
|
|
91
96
|
});
|
|
92
97
|
const killProcesses = ()=>{
|
package/dist/tsc.js
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
const logPrefixTsc =
|
|
1
|
+
import { logger } from "@rsbuild/core";
|
|
2
|
+
import external_picocolors_default from "picocolors";
|
|
3
|
+
import external_typescript_default from "typescript";
|
|
4
|
+
import { getTimeCost, processDtsFiles } from "./utils.js";
|
|
5
|
+
const logPrefixTsc = external_picocolors_default.dim('[tsc]');
|
|
6
6
|
const formatHost = {
|
|
7
7
|
getCanonicalFileName: (path)=>path,
|
|
8
|
-
getCurrentDirectory:
|
|
9
|
-
getNewLine: ()=>
|
|
8
|
+
getCurrentDirectory: external_typescript_default.sys.getCurrentDirectory,
|
|
9
|
+
getNewLine: ()=>external_typescript_default.sys.newLine
|
|
10
10
|
};
|
|
11
11
|
async function handleDiagnosticsAndProcessFiles(diagnostics, configPath, bundle, declarationDir, dtsExtension, redirect, rootDir, banner, footer, name) {
|
|
12
12
|
const diagnosticMessages = [];
|
|
13
13
|
for (const diagnostic of diagnostics){
|
|
14
|
-
const message =
|
|
14
|
+
const message = external_typescript_default.formatDiagnosticsWithColorAndContext([
|
|
15
15
|
diagnostic
|
|
16
16
|
], formatHost);
|
|
17
17
|
diagnosticMessages.push(message);
|
|
18
18
|
}
|
|
19
|
-
await
|
|
19
|
+
await processDtsFiles(bundle, declarationDir, dtsExtension, redirect, configPath, rootDir, banner, footer);
|
|
20
20
|
if (diagnosticMessages.length) {
|
|
21
|
-
for (const message of diagnosticMessages)
|
|
22
|
-
|
|
21
|
+
for (const message of diagnosticMessages)logger.error(logPrefixTsc, message);
|
|
22
|
+
const error = new Error(`Failed to generate declaration files. ${external_picocolors_default.gray(`(${name})`)}`);
|
|
23
|
+
error.stack = '';
|
|
24
|
+
throw error;
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
27
|
async function emitDts(options, onComplete, bundle = false, isWatch = false, build = false) {
|
|
@@ -34,26 +36,26 @@ async function emitDts(options, onComplete, bundle = false, isWatch = false, bui
|
|
|
34
36
|
declarationDir,
|
|
35
37
|
emitDeclarationOnly: true
|
|
36
38
|
};
|
|
37
|
-
const createProgram =
|
|
39
|
+
const createProgram = external_typescript_default.createSemanticDiagnosticsBuilderProgram;
|
|
38
40
|
const reportDiagnostic = (diagnostic)=>{
|
|
39
|
-
|
|
41
|
+
logger.error(logPrefixTsc, external_typescript_default.formatDiagnosticsWithColorAndContext([
|
|
40
42
|
diagnostic
|
|
41
43
|
], formatHost));
|
|
42
44
|
};
|
|
43
45
|
const reportWatchStatusChanged = async (diagnostic, _newLine, _options, errorCount)=>{
|
|
44
|
-
const message = `${
|
|
45
|
-
if (6031 === diagnostic.code || 6032 === diagnostic.code)
|
|
46
|
+
const message = `${external_typescript_default.flattenDiagnosticMessageText(diagnostic.messageText, formatHost.getNewLine())} ${external_picocolors_default.gray(`(${name})`)}`;
|
|
47
|
+
if (6031 === diagnostic.code || 6032 === diagnostic.code) logger.info(logPrefixTsc, message);
|
|
46
48
|
if (6194 === diagnostic.code) {
|
|
47
|
-
if (0 !== errorCount && errorCount)
|
|
49
|
+
if (0 !== errorCount && errorCount) logger.error(logPrefixTsc, message);
|
|
48
50
|
else {
|
|
49
|
-
|
|
51
|
+
logger.info(logPrefixTsc, message);
|
|
50
52
|
onComplete(true);
|
|
51
53
|
}
|
|
52
|
-
await
|
|
54
|
+
await processDtsFiles(bundle, declarationDir, dtsExtension, redirect, configPath, rootDir, banner, footer);
|
|
53
55
|
}
|
|
54
56
|
if (6193 === diagnostic.code) {
|
|
55
|
-
|
|
56
|
-
await
|
|
57
|
+
logger.error(logPrefixTsc, message);
|
|
58
|
+
await processDtsFiles(bundle, declarationDir, dtsExtension, redirect, configPath, rootDir, banner, footer);
|
|
57
59
|
}
|
|
58
60
|
};
|
|
59
61
|
const renameDtsFile = (fileName)=>{
|
|
@@ -61,36 +63,36 @@ async function emitDts(options, onComplete, bundle = false, isWatch = false, bui
|
|
|
61
63
|
return fileName.replace(/\.d\.ts$/, dtsExtension);
|
|
62
64
|
};
|
|
63
65
|
const system = {
|
|
64
|
-
...
|
|
66
|
+
...external_typescript_default.sys,
|
|
65
67
|
writeFile: (fileName, contents, writeByteOrderMark)=>{
|
|
66
|
-
|
|
68
|
+
external_typescript_default.sys.writeFile(renameDtsFile(fileName), contents, writeByteOrderMark);
|
|
67
69
|
}
|
|
68
70
|
};
|
|
69
71
|
if (isWatch) if (build) {
|
|
70
|
-
const host =
|
|
71
|
-
const solutionBuilder =
|
|
72
|
+
const host = external_typescript_default.createSolutionBuilderWithWatchHost(system, createProgram, reportDiagnostic, void 0, reportWatchStatusChanged);
|
|
73
|
+
const solutionBuilder = external_typescript_default.createSolutionBuilderWithWatch(host, [
|
|
72
74
|
configPath
|
|
73
75
|
], compilerOptions, {
|
|
74
76
|
watch: true
|
|
75
77
|
});
|
|
76
78
|
solutionBuilder.build();
|
|
77
79
|
} else {
|
|
78
|
-
const host =
|
|
79
|
-
|
|
80
|
+
const host = external_typescript_default.createWatchCompilerHost(configPath, compilerOptions, system, createProgram, reportDiagnostic, reportWatchStatusChanged);
|
|
81
|
+
external_typescript_default.createWatchProgram(host);
|
|
80
82
|
}
|
|
81
83
|
else {
|
|
82
84
|
if (build || compilerOptions.composite) if (!build && compilerOptions.composite) {
|
|
83
|
-
const originHost =
|
|
85
|
+
const originHost = external_typescript_default.createIncrementalCompilerHost(compilerOptions);
|
|
84
86
|
const host = {
|
|
85
87
|
...originHost,
|
|
86
88
|
writeFile: (fileName, contents, writeByteOrderMark, onError, sourceFiles)=>{
|
|
87
89
|
originHost.writeFile(renameDtsFile(fileName), contents, writeByteOrderMark, onError, sourceFiles);
|
|
88
90
|
}
|
|
89
91
|
};
|
|
90
|
-
const program =
|
|
92
|
+
const program = external_typescript_default.createIncrementalProgram({
|
|
91
93
|
rootNames: fileNames,
|
|
92
94
|
options: compilerOptions,
|
|
93
|
-
configFileParsingDiagnostics:
|
|
95
|
+
configFileParsingDiagnostics: external_typescript_default.getConfigFileParsingDiagnostics(tsConfigResult),
|
|
94
96
|
projectReferences,
|
|
95
97
|
host,
|
|
96
98
|
createProgram
|
|
@@ -103,35 +105,39 @@ async function emitDts(options, onComplete, bundle = false, isWatch = false, bui
|
|
|
103
105
|
const reportErrorSummary = (errorCount)=>{
|
|
104
106
|
errorNumber = errorCount;
|
|
105
107
|
};
|
|
106
|
-
const host =
|
|
107
|
-
const solutionBuilder =
|
|
108
|
+
const host = external_typescript_default.createSolutionBuilderHost(system, createProgram, reportDiagnostic, void 0, reportErrorSummary);
|
|
109
|
+
const solutionBuilder = external_typescript_default.createSolutionBuilder(host, [
|
|
108
110
|
configPath
|
|
109
111
|
], compilerOptions);
|
|
110
112
|
solutionBuilder.build();
|
|
111
|
-
await
|
|
112
|
-
if (errorNumber > 0)
|
|
113
|
+
await processDtsFiles(bundle, declarationDir, dtsExtension, redirect, configPath, rootDir, banner, footer);
|
|
114
|
+
if (errorNumber > 0) {
|
|
115
|
+
const error = new Error(`Failed to generate declaration files. ${external_picocolors_default.gray(`(${name})`)}`);
|
|
116
|
+
error.stack = '';
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
113
119
|
}
|
|
114
120
|
else {
|
|
115
|
-
const originHost =
|
|
121
|
+
const originHost = external_typescript_default.createCompilerHost(compilerOptions);
|
|
116
122
|
const host = {
|
|
117
123
|
...originHost,
|
|
118
124
|
writeFile: (fileName, contents, writeByteOrderMark, onError, sourceFiles)=>{
|
|
119
125
|
originHost.writeFile(renameDtsFile(fileName), contents, writeByteOrderMark, onError, sourceFiles);
|
|
120
126
|
}
|
|
121
127
|
};
|
|
122
|
-
const program =
|
|
128
|
+
const program = external_typescript_default.createProgram({
|
|
123
129
|
rootNames: fileNames,
|
|
124
130
|
options: compilerOptions,
|
|
125
131
|
projectReferences,
|
|
126
132
|
host,
|
|
127
|
-
configFileParsingDiagnostics:
|
|
133
|
+
configFileParsingDiagnostics: external_typescript_default.getConfigFileParsingDiagnostics(tsConfigResult)
|
|
128
134
|
});
|
|
129
135
|
const emitResult = program.emit();
|
|
130
|
-
const allDiagnostics =
|
|
136
|
+
const allDiagnostics = external_typescript_default.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
|
|
131
137
|
await handleDiagnosticsAndProcessFiles(allDiagnostics, configPath, bundle, declarationDir, dtsExtension, redirect, rootDir, banner, footer, name);
|
|
132
138
|
}
|
|
133
|
-
if (bundle)
|
|
134
|
-
else
|
|
139
|
+
if (bundle) logger.info(`declaration files prepared in ${getTimeCost(start)} ${external_picocolors_default.gray(`(${name})`)}`);
|
|
140
|
+
else logger.ready(`declaration files generated in ${getTimeCost(start)} ${external_picocolors_default.gray(`(${name})`)}`);
|
|
135
141
|
}
|
|
136
142
|
}
|
|
137
143
|
export { emitDts };
|
package/dist/utils.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
1
|
+
import external_node_fs_default from "node:fs";
|
|
2
|
+
import promises_default from "node:fs/promises";
|
|
3
|
+
import { platform } from "node:os";
|
|
4
|
+
import external_node_path_default, { basename, dirname, extname, isAbsolute, join, normalize, relative, resolve } from "node:path";
|
|
5
|
+
import { parseAsync } from "@ast-grep/napi";
|
|
6
|
+
import { logger } from "@rsbuild/core";
|
|
7
|
+
import external_magic_string_default from "magic-string";
|
|
8
|
+
import external_picocolors_default from "picocolors";
|
|
9
|
+
import { convertPathToPattern, glob } from "tinyglobby";
|
|
10
|
+
import { createMatchPath, loadConfig } from "tsconfig-paths";
|
|
11
|
+
import external_typescript_default from "typescript";
|
|
12
12
|
const JS_EXTENSIONS = [
|
|
13
13
|
'js',
|
|
14
14
|
'mjs',
|
|
@@ -25,28 +25,28 @@ const JS_EXTENSIONS = [
|
|
|
25
25
|
];
|
|
26
26
|
const JS_EXTENSIONS_PATTERN = new RegExp(`\\.(${JS_EXTENSIONS.join('|')})$`);
|
|
27
27
|
function loadTsconfig(tsconfigPath) {
|
|
28
|
-
const configFile =
|
|
29
|
-
const configFileContent =
|
|
28
|
+
const configFile = external_typescript_default.readConfigFile(tsconfigPath, external_typescript_default.sys.readFile);
|
|
29
|
+
const configFileContent = external_typescript_default.parseJsonConfigFileContent(configFile.config, external_typescript_default.sys, external_node_path_default.dirname(tsconfigPath));
|
|
30
30
|
return configFileContent;
|
|
31
31
|
}
|
|
32
32
|
const TEMP_FOLDER = '.rslib';
|
|
33
33
|
const TEMP_DTS_DIR = `${TEMP_FOLDER}/declarations`;
|
|
34
34
|
function ensureTempDeclarationDir(cwd, name) {
|
|
35
|
-
const dirPath =
|
|
36
|
-
if (
|
|
37
|
-
|
|
35
|
+
const dirPath = external_node_path_default.join(cwd, TEMP_DTS_DIR, name);
|
|
36
|
+
if (external_node_fs_default.existsSync(dirPath)) return dirPath;
|
|
37
|
+
external_node_fs_default.mkdirSync(dirPath, {
|
|
38
38
|
recursive: true
|
|
39
39
|
});
|
|
40
|
-
const gitIgnorePath =
|
|
41
|
-
|
|
40
|
+
const gitIgnorePath = external_node_path_default.join(cwd, TEMP_FOLDER, '.gitignore');
|
|
41
|
+
external_node_fs_default.writeFileSync(gitIgnorePath, '**/*\n');
|
|
42
42
|
return dirPath;
|
|
43
43
|
}
|
|
44
44
|
async function pathExists(path) {
|
|
45
|
-
return
|
|
45
|
+
return external_node_fs_default.promises.access(path).then(()=>true).catch(()=>false);
|
|
46
46
|
}
|
|
47
47
|
async function isDirectory(filePath) {
|
|
48
48
|
try {
|
|
49
|
-
const stat = await
|
|
49
|
+
const stat = await promises_default.stat(filePath);
|
|
50
50
|
return stat.isDirectory();
|
|
51
51
|
} catch {
|
|
52
52
|
return false;
|
|
@@ -55,28 +55,28 @@ async function isDirectory(filePath) {
|
|
|
55
55
|
async function emptyDir(dir) {
|
|
56
56
|
if (!await pathExists(dir)) return;
|
|
57
57
|
try {
|
|
58
|
-
for (const file of (await
|
|
58
|
+
for (const file of (await external_node_fs_default.promises.readdir(dir)))await external_node_fs_default.promises.rm(external_node_path_default.resolve(dir, file), {
|
|
59
59
|
recursive: true,
|
|
60
60
|
force: true
|
|
61
61
|
});
|
|
62
62
|
} catch (err) {
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
logger.warn(`Failed to empty dir: ${dir}`);
|
|
64
|
+
logger.warn(err);
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
async function clearTempDeclarationDir(cwd) {
|
|
68
|
-
const dirPath =
|
|
68
|
+
const dirPath = external_node_path_default.join(cwd, TEMP_DTS_DIR);
|
|
69
69
|
await emptyDir(dirPath);
|
|
70
70
|
}
|
|
71
71
|
function getFileLoc(diagnostic, configPath) {
|
|
72
72
|
if (diagnostic.file) {
|
|
73
|
-
const { line, character } =
|
|
74
|
-
return `${
|
|
73
|
+
const { line, character } = external_typescript_default.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
|
|
74
|
+
return `${external_picocolors_default.cyan(diagnostic.file.fileName)}:${external_picocolors_default.yellow(line + 1)}:${external_picocolors_default.yellow(character + 1)}`;
|
|
75
75
|
}
|
|
76
|
-
return `${
|
|
76
|
+
return `${external_picocolors_default.cyan(configPath)}`;
|
|
77
77
|
}
|
|
78
78
|
const prettyTime = (seconds)=>{
|
|
79
|
-
const format = (time)=>
|
|
79
|
+
const format = (time)=>external_picocolors_default.bold(time);
|
|
80
80
|
if (seconds < 10) {
|
|
81
81
|
const digits = seconds >= 0.01 ? 2 : 3;
|
|
82
82
|
return `${format(seconds.toFixed(digits))} s`;
|
|
@@ -86,7 +86,7 @@ const prettyTime = (seconds)=>{
|
|
|
86
86
|
return `${format(minutes.toFixed(2))} m`;
|
|
87
87
|
};
|
|
88
88
|
const convertPath = (path)=>{
|
|
89
|
-
if ('win32' ===
|
|
89
|
+
if ('win32' === platform()) return convertPathToPattern(path);
|
|
90
90
|
return path;
|
|
91
91
|
};
|
|
92
92
|
function getTimeCost(start) {
|
|
@@ -94,23 +94,23 @@ function getTimeCost(start) {
|
|
|
94
94
|
return prettyTime(second);
|
|
95
95
|
}
|
|
96
96
|
async function addBannerAndFooter(dtsFile, banner, footer) {
|
|
97
|
-
const content = await
|
|
98
|
-
const code = new
|
|
97
|
+
const content = await promises_default.readFile(dtsFile, 'utf-8');
|
|
98
|
+
const code = new external_magic_string_default(content);
|
|
99
99
|
if (banner && !content.trimStart().startsWith(banner.trim())) code.prepend(`${banner}\n`);
|
|
100
100
|
if (footer && !content.trimEnd().endsWith(footer.trim())) code.append(`\n${footer}\n`);
|
|
101
|
-
if (code.hasChanged()) await
|
|
101
|
+
if (code.hasChanged()) await promises_default.writeFile(dtsFile, code.toString());
|
|
102
102
|
}
|
|
103
103
|
async function addExtension(redirect, dtsFile, path, extension) {
|
|
104
104
|
if (!redirect.extension) return path;
|
|
105
105
|
let redirectPath = path;
|
|
106
|
-
if (!
|
|
107
|
-
if (await isDirectory(
|
|
106
|
+
if (!isAbsolute(redirectPath) && !redirectPath.startsWith('.')) return redirectPath;
|
|
107
|
+
if (await isDirectory(join(dirname(dtsFile), redirectPath))) redirectPath = `${redirectPath.replace(/\/+$/, '')}/index`;
|
|
108
108
|
return `${redirectPath}${extension}`;
|
|
109
109
|
}
|
|
110
110
|
async function redirectDtsImports(dtsFile, dtsExtension, redirect, matchPath, outDir, rootDir) {
|
|
111
|
-
const content = await
|
|
112
|
-
const code = new
|
|
113
|
-
const sgNode = (await
|
|
111
|
+
const content = await promises_default.readFile(dtsFile, 'utf-8');
|
|
112
|
+
const code = new external_magic_string_default(content);
|
|
113
|
+
const sgNode = (await parseAsync("typescript", content)).root();
|
|
114
114
|
const matcher = {
|
|
115
115
|
rule: {
|
|
116
116
|
any: [
|
|
@@ -193,43 +193,43 @@ async function redirectDtsImports(dtsFile, dtsExtension, redirect, matchPath, ou
|
|
|
193
193
|
]);
|
|
194
194
|
let redirectImportPath = importPath;
|
|
195
195
|
if (absoluteImportPath && redirect.path) {
|
|
196
|
-
const relativeRootDir =
|
|
197
|
-
const isOutsideRootdir = relativeRootDir.startsWith('..') ||
|
|
196
|
+
const relativeRootDir = external_node_path_default.relative(normalize(rootDir), normalize(absoluteImportPath));
|
|
197
|
+
const isOutsideRootdir = relativeRootDir.startsWith('..') || external_node_path_default.isAbsolute(relativeRootDir);
|
|
198
198
|
if (isOutsideRootdir) {
|
|
199
|
-
const relativePath =
|
|
199
|
+
const relativePath = relative(dirname(dtsFile), absoluteImportPath);
|
|
200
200
|
redirectImportPath = relativePath.startsWith('..') ? relativePath : `./${relativePath}`;
|
|
201
201
|
} else {
|
|
202
|
-
const originalFilePath =
|
|
203
|
-
const originalSourceDir =
|
|
204
|
-
const relativePath =
|
|
202
|
+
const originalFilePath = resolve(rootDir, relative(outDir, dtsFile));
|
|
203
|
+
const originalSourceDir = dirname(originalFilePath);
|
|
204
|
+
const relativePath = relative(originalSourceDir, absoluteImportPath);
|
|
205
205
|
redirectImportPath = relativePath.startsWith('..') ? relativePath : `./${relativePath}`;
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
|
-
const ext =
|
|
208
|
+
const ext = extname(redirectImportPath);
|
|
209
209
|
if (ext) {
|
|
210
210
|
if (JS_EXTENSIONS_PATTERN.test(redirectImportPath)) {
|
|
211
211
|
if (redirect.extension) redirectImportPath = redirectImportPath.replace(/\.[^.]+$/, extension);
|
|
212
212
|
}
|
|
213
213
|
} else {
|
|
214
|
-
if (absoluteImportPath &&
|
|
214
|
+
if (absoluteImportPath && normalize(absoluteImportPath).startsWith(normalize(rootDir))) redirectImportPath = await addExtension(redirect, dtsFile, redirectImportPath, extension);
|
|
215
215
|
if (!absoluteImportPath && importPath.startsWith('.')) redirectImportPath = await addExtension(redirect, dtsFile, redirectImportPath, extension);
|
|
216
216
|
}
|
|
217
|
-
const normalizedRedirectImportPath = redirectImportPath.split(
|
|
217
|
+
const normalizedRedirectImportPath = redirectImportPath.split(external_node_path_default.sep).join('/');
|
|
218
218
|
code.overwrite(start, end, normalizedRedirectImportPath);
|
|
219
219
|
} catch (err) {
|
|
220
|
-
|
|
220
|
+
logger.warn(err);
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
|
-
if (code.hasChanged()) await
|
|
223
|
+
if (code.hasChanged()) await promises_default.writeFile(dtsFile, code.toString());
|
|
224
224
|
}
|
|
225
225
|
async function processDtsFiles(bundle, dir, dtsExtension, redirect, tsconfigPath, rootDir, banner, footer) {
|
|
226
226
|
if (bundle) return;
|
|
227
227
|
let matchPath;
|
|
228
228
|
if (redirect.path || redirect.extension) {
|
|
229
|
-
const result =
|
|
230
|
-
if ('failed' === result.resultType) return void
|
|
229
|
+
const result = loadConfig(tsconfigPath);
|
|
230
|
+
if ('failed' === result.resultType) return void logger.error(result.message);
|
|
231
231
|
const { absoluteBaseUrl, paths, mainFields, addMatchAll } = result;
|
|
232
|
-
matchPath =
|
|
232
|
+
matchPath = createMatchPath(absoluteBaseUrl, paths, mainFields, addMatchAll);
|
|
233
233
|
}
|
|
234
234
|
const dtsFiles = await globDtsFiles(dir, [
|
|
235
235
|
`/**/*${dtsExtension}`
|
|
@@ -239,7 +239,7 @@ async function processDtsFiles(bundle, dir, dtsExtension, redirect, tsconfigPath
|
|
|
239
239
|
if (banner || footer) await addBannerAndFooter(file, banner, footer);
|
|
240
240
|
if ((redirect.path || redirect.extension) && matchPath) await redirectDtsImports(file, dtsExtension, redirect, matchPath, dir, rootDir);
|
|
241
241
|
} catch (error) {
|
|
242
|
-
|
|
242
|
+
logger.error(`Failed to rename declaration file ${file}: ${error}`);
|
|
243
243
|
}
|
|
244
244
|
}));
|
|
245
245
|
}
|
|
@@ -250,14 +250,20 @@ function processSourceEntry(bundle, entryConfig) {
|
|
|
250
250
|
name,
|
|
251
251
|
path
|
|
252
252
|
}));
|
|
253
|
-
if (0 === entries.length)
|
|
253
|
+
if (0 === entries.length) {
|
|
254
|
+
const noValidEntryError = new Error(`Can not find a valid entry for ${external_picocolors_default.cyan('dts.bundle')} option, please check your entry config.`);
|
|
255
|
+
noValidEntryError.stack = '';
|
|
256
|
+
throw noValidEntryError;
|
|
257
|
+
}
|
|
254
258
|
return entries;
|
|
255
259
|
}
|
|
256
|
-
|
|
260
|
+
const error = new Error('@microsoft/api-extractor only support entry of Record<string, string> type to bundle declaration files, please check your entry config.');
|
|
261
|
+
error.stack = '';
|
|
262
|
+
throw error;
|
|
257
263
|
}
|
|
258
264
|
async function calcLongestCommonPath(absPaths) {
|
|
259
265
|
if (0 === absPaths.length) return null;
|
|
260
|
-
const sep =
|
|
266
|
+
const sep = external_node_path_default.posix.sep;
|
|
261
267
|
const splitPaths = absPaths.map((p)=>p.split(sep));
|
|
262
268
|
let lcaFragments = splitPaths[0];
|
|
263
269
|
for(let i = 1; i < splitPaths.length; i++){
|
|
@@ -268,12 +274,12 @@ async function calcLongestCommonPath(absPaths) {
|
|
|
268
274
|
lcaFragments = lcaFragments.slice(0, j);
|
|
269
275
|
}
|
|
270
276
|
let lca = lcaFragments.length > 0 ? lcaFragments.join(sep) : sep;
|
|
271
|
-
const stats = await
|
|
272
|
-
if (stats?.isFile()) lca =
|
|
277
|
+
const stats = await promises_default.stat(lca);
|
|
278
|
+
if (stats?.isFile()) lca = external_node_path_default.dirname(lca);
|
|
273
279
|
return lca;
|
|
274
280
|
}
|
|
275
281
|
const globDtsFiles = async (dir, patterns)=>{
|
|
276
|
-
const dtsFiles = await Promise.all(patterns.map((pattern)=>
|
|
282
|
+
const dtsFiles = await Promise.all(patterns.map((pattern)=>glob(convertPath(join(dir, pattern)), {
|
|
277
283
|
absolute: true
|
|
278
284
|
})));
|
|
279
285
|
return dtsFiles.flat();
|
|
@@ -285,16 +291,16 @@ async function cleanDtsFiles(dir) {
|
|
|
285
291
|
'/**/*.d.mts'
|
|
286
292
|
];
|
|
287
293
|
const allFiles = await globDtsFiles(dir, patterns);
|
|
288
|
-
await Promise.all(allFiles.map((file)=>
|
|
294
|
+
await Promise.all(allFiles.map((file)=>promises_default.rm(file, {
|
|
289
295
|
force: true
|
|
290
296
|
})));
|
|
291
297
|
}
|
|
292
298
|
async function cleanTsBuildInfoFile(tsconfigPath, compilerOptions) {
|
|
293
|
-
const tsconfigDir =
|
|
299
|
+
const tsconfigDir = dirname(tsconfigPath);
|
|
294
300
|
const { outDir, rootDir, tsBuildInfoFile } = compilerOptions;
|
|
295
|
-
let tsbuildInfoFilePath = `${
|
|
296
|
-
if (outDir) tsbuildInfoFilePath = rootDir ?
|
|
297
|
-
if (await pathExists(tsbuildInfoFilePath)) await
|
|
301
|
+
let tsbuildInfoFilePath = `${basename(tsconfigPath, '.json')}${tsBuildInfoFile ?? '.tsbuildinfo'}`;
|
|
302
|
+
if (outDir) tsbuildInfoFilePath = rootDir ? join(outDir, relative(resolve(tsconfigDir, rootDir), tsconfigDir), tsbuildInfoFilePath) : join(outDir, tsbuildInfoFilePath);
|
|
303
|
+
if (await pathExists(tsbuildInfoFilePath)) await promises_default.rm(tsbuildInfoFilePath, {
|
|
298
304
|
force: true
|
|
299
305
|
});
|
|
300
306
|
}
|
|
@@ -303,10 +309,10 @@ function getDtsEmitPath(pathFromPlugin, declarationDir, distPath) {
|
|
|
303
309
|
}
|
|
304
310
|
function warnIfOutside(cwd, dir, label) {
|
|
305
311
|
if (dir) {
|
|
306
|
-
const normalizedCwd =
|
|
307
|
-
const normalizedDir =
|
|
308
|
-
const relDir =
|
|
309
|
-
if (relDir.startsWith('..'))
|
|
312
|
+
const normalizedCwd = normalize(cwd);
|
|
313
|
+
const normalizedDir = normalize(dir);
|
|
314
|
+
const relDir = relative(normalizedCwd, normalizedDir);
|
|
315
|
+
if (relDir.startsWith('..')) logger.warn(`The resolved ${label} ${external_picocolors_default.cyan(normalizedDir)} is outside the project root ${external_picocolors_default.cyan(normalizedCwd)}, please check your tsconfig file.`);
|
|
310
316
|
}
|
|
311
317
|
}
|
|
312
318
|
export { JS_EXTENSIONS_PATTERN, TEMP_DTS_DIR, TEMP_FOLDER, addBannerAndFooter, calcLongestCommonPath, cleanDtsFiles, cleanTsBuildInfoFile, clearTempDeclarationDir, emptyDir, ensureTempDeclarationDir, getDtsEmitPath, getFileLoc, getTimeCost, globDtsFiles, isDirectory, loadTsconfig, pathExists, prettyTime, processDtsFiles, processSourceEntry, redirectDtsImports, warnIfOutside };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rsbuild-plugin-dts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Rsbuild plugin that supports emitting declaration files for TypeScript.",
|
|
5
5
|
"homepage": "https://rslib.rs",
|
|
6
6
|
"bugs": {
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@microsoft/api-extractor": "^7.52.8",
|
|
36
|
-
"@rsbuild/core": "
|
|
36
|
+
"@rsbuild/core": "1.4.0-beta.3",
|
|
37
37
|
"rsbuild-plugin-publint": "^0.3.2",
|
|
38
|
-
"rslib": "npm:@rslib/core@0.9.
|
|
38
|
+
"rslib": "npm:@rslib/core@0.9.2",
|
|
39
39
|
"typescript": "^5.8.3",
|
|
40
40
|
"@rslib/tsconfig": "0.0.1"
|
|
41
41
|
},
|