fix(tsbuild): Avoid process.exit in library, add confirmskiplibcheck flag, improve CLI exit handling and JSON/quiet modes, update test script
This commit is contained in:
@@ -1,5 +1,14 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-08-29 - 2.6.8 - fix(tsbuild)
|
||||||
|
Avoid process.exit in library, add confirmskiplibcheck flag, improve CLI exit handling and JSON/quiet modes, update test script
|
||||||
|
|
||||||
|
- Changed package.json test script from "tsrun test/test.ts --verbose" to "tstest test/test.ts --verbose".
|
||||||
|
- Library no longer calls process.exit from compile and compileWithErrorTracking; errors are returned or thrown so callers can decide process termination.
|
||||||
|
- skipLibCheck behavior updated: delay/warning only happens when --confirmskiplibcheck is present; otherwise a short informational note is printed (suppressed in --quiet/--json).
|
||||||
|
- CLI now awaits compileGlobStringObject calls and inspects a final error summary attached to argv to decide process.exit(1) when errors occurred.
|
||||||
|
- compileGlobStringObject/exports now respect --quiet and --json modes, emit a JSON summary when --json is used, and attach the final error summary to argv so the CLI can determine exit behavior.
|
||||||
|
|
||||||
## 2025-08-18 - 2.6.7 - fix(tspublish)
|
## 2025-08-18 - 2.6.7 - fix(tspublish)
|
||||||
Bump @git.zone/tspublish dependency to ^1.10.3
|
Bump @git.zone/tspublish dependency to ^1.10.3
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
"tsbuild": "./cli.js"
|
"tsbuild": "./cli.js"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "tsrun test/test.ts --verbose",
|
"test": "tstest test/test.ts --verbose",
|
||||||
"build": "node cli.ts.js --web",
|
"build": "node cli.ts.js --web",
|
||||||
"buildDocs": "tsdoc"
|
"buildDocs": "tsdoc"
|
||||||
},
|
},
|
||||||
|
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@git.zone/tsbuild',
|
name: '@git.zone/tsbuild',
|
||||||
version: '2.6.7',
|
version: '2.6.8',
|
||||||
description: 'A tool for compiling TypeScript files using the latest nightly features, offering flexible APIs and a CLI for streamlined development.'
|
description: 'A tool for compiling TypeScript files using the latest nightly features, offering flexible APIs and a CLI for streamlined development.'
|
||||||
}
|
}
|
||||||
|
@@ -309,10 +309,17 @@ export class TsBuild {
|
|||||||
*/
|
*/
|
||||||
public async compileWithErrorTracking(): Promise<{ emittedFiles: any[], errorSummary: IErrorSummary }> {
|
public async compileWithErrorTracking(): Promise<{ emittedFiles: any[], errorSummary: IErrorSummary }> {
|
||||||
if (this.options.skipLibCheck) {
|
if (this.options.skipLibCheck) {
|
||||||
|
if (this.argvArg?.confirmskiplibcheck) {
|
||||||
console.log('\n⚠️ WARNING ⚠️');
|
console.log('\n⚠️ WARNING ⚠️');
|
||||||
console.log('You are skipping libcheck... Is that really wanted?');
|
console.log('You are skipping libcheck... Is that really wanted?');
|
||||||
console.log('Continuing in 5 seconds...\n');
|
console.log('Continuing in 5 seconds...\n');
|
||||||
await plugins.smartdelay.delayFor(5000);
|
await plugins.smartdelay.delayFor(5000);
|
||||||
|
} else {
|
||||||
|
// No delay by default; keep a short note unless in quiet/json modes
|
||||||
|
if (!this.argvArg?.quiet && !this.argvArg?.json) {
|
||||||
|
console.log('⚠️ skipLibCheck enabled; use --confirmskiplibcheck to pause with warning.');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enhanced logging with task info
|
// Enhanced logging with task info
|
||||||
@@ -382,7 +389,9 @@ export class TsBuild {
|
|||||||
this.displayErrorSummary(combinedErrorSummary);
|
this.displayErrorSummary(combinedErrorSummary);
|
||||||
console.error('\n❌ TypeScript emit failed. Please investigate the errors listed above!');
|
console.error('\n❌ TypeScript emit failed. Please investigate the errors listed above!');
|
||||||
console.error(' No output files have been generated.\n');
|
console.error(' No output files have been generated.\n');
|
||||||
process.exit(exitCode);
|
// Do not exit here; return error summary so caller can decide
|
||||||
|
done.resolve({ emittedFiles: [], errorSummary: combinedErrorSummary });
|
||||||
|
return done.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
return done.promise;
|
return done.promise;
|
||||||
@@ -393,10 +402,16 @@ export class TsBuild {
|
|||||||
*/
|
*/
|
||||||
public async compile(): Promise<any[]> {
|
public async compile(): Promise<any[]> {
|
||||||
if (this.options.skipLibCheck) {
|
if (this.options.skipLibCheck) {
|
||||||
|
if (this.argvArg?.confirmskiplibcheck) {
|
||||||
console.log('\n⚠️ WARNING ⚠️');
|
console.log('\n⚠️ WARNING ⚠️');
|
||||||
console.log('You are skipping libcheck... Is that really wanted?');
|
console.log('You are skipping libcheck... Is that really wanted?');
|
||||||
console.log('Continuing in 5 seconds...\n');
|
console.log('Continuing in 5 seconds...\n');
|
||||||
await plugins.smartdelay.delayFor(5000);
|
await plugins.smartdelay.delayFor(5000);
|
||||||
|
} else {
|
||||||
|
if (!this.argvArg?.quiet && !this.argvArg?.json) {
|
||||||
|
console.log('⚠️ skipLibCheck enabled; use --confirmskiplibcheck to pause with warning.');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`🔨 Compiling ${this.fileNames.length} files...`);
|
console.log(`🔨 Compiling ${this.fileNames.length} files...`);
|
||||||
@@ -412,7 +427,8 @@ export class TsBuild {
|
|||||||
this.displayErrorSummary(preEmitErrorSummary);
|
this.displayErrorSummary(preEmitErrorSummary);
|
||||||
console.error('\n❌ TypeScript pre-emit checks failed. Please fix the issues listed above before proceeding.');
|
console.error('\n❌ TypeScript pre-emit checks failed. Please fix the issues listed above before proceeding.');
|
||||||
console.error(' Type errors must be resolved before the compiler can emit output files.\n');
|
console.error(' Type errors must be resolved before the compiler can emit output files.\n');
|
||||||
process.exit(1);
|
// Throw instead of exiting to keep library pure
|
||||||
|
throw new Error('TypeScript pre-emit checks failed.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no pre-emit errors, proceed with emit
|
// If no pre-emit errors, proceed with emit
|
||||||
@@ -438,7 +454,8 @@ export class TsBuild {
|
|||||||
this.displayErrorSummary(emitErrorSummary);
|
this.displayErrorSummary(emitErrorSummary);
|
||||||
console.error('\n❌ TypeScript emit failed. Please investigate the errors listed above!');
|
console.error('\n❌ TypeScript emit failed. Please investigate the errors listed above!');
|
||||||
console.error(' No output files have been generated.\n');
|
console.error(' No output files have been generated.\n');
|
||||||
process.exit(exitCode);
|
// Throw instead of exiting to keep library pure
|
||||||
|
throw new Error('TypeScript emit failed.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return done.promise;
|
return done.promise;
|
||||||
|
@@ -9,7 +9,7 @@ export const runCli = async () => {
|
|||||||
* the standard task compiles anything in ts/ directory to dist directory
|
* the standard task compiles anything in ts/ directory to dist directory
|
||||||
*/
|
*/
|
||||||
tsbuildCli.standardCommand().subscribe(async (argvArg) => {
|
tsbuildCli.standardCommand().subscribe(async (argvArg) => {
|
||||||
tsbuild.compileGlobStringObject(
|
await tsbuild.compileGlobStringObject(
|
||||||
{
|
{
|
||||||
'./ts/**/*.ts': './dist_ts',
|
'./ts/**/*.ts': './dist_ts',
|
||||||
},
|
},
|
||||||
@@ -17,6 +17,10 @@ export const runCli = async () => {
|
|||||||
process.cwd(),
|
process.cwd(),
|
||||||
argvArg
|
argvArg
|
||||||
);
|
);
|
||||||
|
const summary = (argvArg as any)?.__tsbuildFinalErrorSummary;
|
||||||
|
if (summary && summary.totalErrors > 0) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,6 +34,10 @@ export const runCli = async () => {
|
|||||||
compilationCommandObject[`./${directory}/**/*.ts`] = `./dist_${directory}`;
|
compilationCommandObject[`./${directory}/**/*.ts`] = `./dist_${directory}`;
|
||||||
}
|
}
|
||||||
await tsbuild.compileGlobStringObject(compilationCommandObject, {}, process.cwd(), argvArg);
|
await tsbuild.compileGlobStringObject(compilationCommandObject, {}, process.cwd(), argvArg);
|
||||||
|
const summary = (argvArg as any)?.__tsbuildFinalErrorSummary;
|
||||||
|
if (summary && summary.totalErrors > 0) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -182,6 +190,10 @@ export const runCli = async () => {
|
|||||||
compilationCommandObject[`./${tsFolder}/**/*.ts`] = `./dist_${tsFolder}`;
|
compilationCommandObject[`./${tsFolder}/**/*.ts`] = `./dist_${tsFolder}`;
|
||||||
}
|
}
|
||||||
await tsbuild.compileGlobStringObject(compilationCommandObject, {}, process.cwd(), argvArg);
|
await tsbuild.compileGlobStringObject(compilationCommandObject, {}, process.cwd(), argvArg);
|
||||||
|
const summary = (argvArg as any)?.__tsbuildFinalErrorSummary;
|
||||||
|
if (summary && summary.totalErrors > 0) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -130,12 +130,16 @@ export let compileGlobStringObject = async (
|
|||||||
const totalTasks = Object.keys(globStringObjectArg).length;
|
const totalTasks = Object.keys(globStringObjectArg).length;
|
||||||
let currentTask = 0;
|
let currentTask = 0;
|
||||||
|
|
||||||
// Log the compilation tasks in a nice format
|
// Log the compilation tasks in a nice format (skip for --quiet or --json)
|
||||||
|
const isQuiet = argvArg?.quiet === true;
|
||||||
|
const isJson = argvArg?.json === true;
|
||||||
|
if (!isQuiet && !isJson) {
|
||||||
console.log(`\n👷 TypeScript Compilation Tasks (${totalTasks} task${totalTasks !== 1 ? 's' : ''}):`);
|
console.log(`\n👷 TypeScript Compilation Tasks (${totalTasks} task${totalTasks !== 1 ? 's' : ''}):`);
|
||||||
Object.entries(globStringObjectArg).forEach(([source, dest]) => {
|
Object.entries(globStringObjectArg).forEach(([source, dest]) => {
|
||||||
console.log(` 📂 ${source} → ${dest}`);
|
console.log(` 📂 ${source} → ${dest}`);
|
||||||
});
|
});
|
||||||
console.log('');
|
console.log('');
|
||||||
|
}
|
||||||
|
|
||||||
for (const keyArg in globStringObjectArg) {
|
for (const keyArg in globStringObjectArg) {
|
||||||
// Type safety check for key
|
// Type safety check for key
|
||||||
@@ -185,7 +189,35 @@ export let compileGlobStringObject = async (
|
|||||||
|
|
||||||
// Display final error summary after all compilation tasks
|
// Display final error summary after all compilation tasks
|
||||||
const finalErrorSummary = mergeErrorSummaries(errorSummaries);
|
const finalErrorSummary = mergeErrorSummaries(errorSummaries);
|
||||||
|
|
||||||
|
// Output summary based on mode
|
||||||
|
if (isJson) {
|
||||||
|
const result = {
|
||||||
|
success: finalErrorSummary.totalErrors === 0,
|
||||||
|
totals: {
|
||||||
|
errors: finalErrorSummary.totalErrors,
|
||||||
|
filesWithErrors: finalErrorSummary.totalFiles,
|
||||||
|
tasks: totalTasks,
|
||||||
|
},
|
||||||
|
errorsByFile: Object.fromEntries(
|
||||||
|
Object.entries(finalErrorSummary.errorsByFile).map(([file, diags]) => [
|
||||||
|
file,
|
||||||
|
diags.map(d => ({
|
||||||
|
code: d.code,
|
||||||
|
message: plugins.typescript.flattenDiagnosticMessageText(d.messageText as any, '\n'),
|
||||||
|
}))
|
||||||
|
])
|
||||||
|
),
|
||||||
|
};
|
||||||
|
console.log(JSON.stringify(result));
|
||||||
|
} else if (!isQuiet) {
|
||||||
displayFinalErrorSummary(finalErrorSummary);
|
displayFinalErrorSummary(finalErrorSummary);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach summary to argvArg so CLI can decide exit behavior
|
||||||
|
if (argvArg && typeof argvArg === 'object') {
|
||||||
|
(argvArg as any).__tsbuildFinalErrorSummary = finalErrorSummary;
|
||||||
|
}
|
||||||
|
|
||||||
return compiledFiles;
|
return compiledFiles;
|
||||||
};
|
};
|
Reference in New Issue
Block a user