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:
		| @@ -3,6 +3,6 @@ | ||||
|  */ | ||||
| export const commitinfo = { | ||||
|   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.' | ||||
| } | ||||
|   | ||||
| @@ -309,10 +309,17 @@ export class TsBuild { | ||||
|    */ | ||||
|   public async compileWithErrorTracking(): Promise<{ emittedFiles: any[], errorSummary: IErrorSummary }> { | ||||
|     if (this.options.skipLibCheck) { | ||||
|       console.log('\n⚠️  WARNING ⚠️'); | ||||
|       console.log('You are skipping libcheck... Is that really wanted?'); | ||||
|       console.log('Continuing in 5 seconds...\n'); | ||||
|       await plugins.smartdelay.delayFor(5000); | ||||
|       if (this.argvArg?.confirmskiplibcheck) { | ||||
|         console.log('\n⚠️  WARNING ⚠️'); | ||||
|         console.log('You are skipping libcheck... Is that really wanted?'); | ||||
|         console.log('Continuing in 5 seconds...\n'); | ||||
|         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 | ||||
| @@ -382,7 +389,9 @@ export class TsBuild { | ||||
|       this.displayErrorSummary(combinedErrorSummary); | ||||
|       console.error('\n❌ TypeScript emit failed. Please investigate the errors listed above!'); | ||||
|       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; | ||||
| @@ -393,10 +402,16 @@ export class TsBuild { | ||||
|    */ | ||||
|   public async compile(): Promise<any[]> { | ||||
|     if (this.options.skipLibCheck) { | ||||
|       console.log('\n⚠️  WARNING ⚠️'); | ||||
|       console.log('You are skipping libcheck... Is that really wanted?'); | ||||
|       console.log('Continuing in 5 seconds...\n'); | ||||
|       await plugins.smartdelay.delayFor(5000); | ||||
|       if (this.argvArg?.confirmskiplibcheck) { | ||||
|         console.log('\n⚠️  WARNING ⚠️'); | ||||
|         console.log('You are skipping libcheck... Is that really wanted?'); | ||||
|         console.log('Continuing in 5 seconds...\n'); | ||||
|         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...`); | ||||
| @@ -412,7 +427,8 @@ export class TsBuild { | ||||
|       this.displayErrorSummary(preEmitErrorSummary); | ||||
|       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'); | ||||
|       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 | ||||
| @@ -438,7 +454,8 @@ export class TsBuild { | ||||
|       this.displayErrorSummary(emitErrorSummary); | ||||
|       console.error('\n❌ TypeScript emit failed. Please investigate the errors listed above!'); | ||||
|       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; | ||||
| @@ -565,4 +582,4 @@ export const checkTypes = async ( | ||||
| ): Promise<boolean> => { | ||||
|   const tsBuild = new TsBuild(fileNames, options, argvArg); | ||||
|   return tsBuild.checkTypes(); | ||||
| }; | ||||
| }; | ||||
|   | ||||
| @@ -9,7 +9,7 @@ export const runCli = async () => { | ||||
|    * the standard task compiles anything in ts/ directory to dist directory | ||||
|    */ | ||||
|   tsbuildCli.standardCommand().subscribe(async (argvArg) => { | ||||
|     tsbuild.compileGlobStringObject( | ||||
|     await tsbuild.compileGlobStringObject( | ||||
|       { | ||||
|         './ts/**/*.ts': './dist_ts', | ||||
|       }, | ||||
| @@ -17,6 +17,10 @@ export const runCli = async () => { | ||||
|       process.cwd(), | ||||
|       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}`; | ||||
|     } | ||||
|     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}`; | ||||
|     } | ||||
|     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; | ||||
|   let currentTask = 0; | ||||
|    | ||||
|   // Log the compilation tasks in a nice format | ||||
|   console.log(`\n👷 TypeScript Compilation Tasks (${totalTasks} task${totalTasks !== 1 ? 's' : ''}):`); | ||||
|   Object.entries(globStringObjectArg).forEach(([source, dest]) => { | ||||
|     console.log(`  📂 ${source} → ${dest}`); | ||||
|   }); | ||||
|   console.log(''); | ||||
|   // 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' : ''}):`); | ||||
|     Object.entries(globStringObjectArg).forEach(([source, dest]) => { | ||||
|       console.log(`  📂 ${source} → ${dest}`); | ||||
|     }); | ||||
|     console.log(''); | ||||
|   } | ||||
|    | ||||
|   for (const keyArg in globStringObjectArg) { | ||||
|     // Type safety check for key | ||||
| @@ -185,7 +189,35 @@ export let compileGlobStringObject = async ( | ||||
|    | ||||
|   // Display final error summary after all compilation tasks | ||||
|   const finalErrorSummary = mergeErrorSummaries(errorSummaries); | ||||
|   displayFinalErrorSummary(finalErrorSummary); | ||||
|    | ||||
|  | ||||
|   // 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); | ||||
|   } | ||||
|  | ||||
|   // Attach summary to argvArg so CLI can decide exit behavior | ||||
|   if (argvArg && typeof argvArg === 'object') { | ||||
|     (argvArg as any).__tsbuildFinalErrorSummary = finalErrorSummary; | ||||
|   } | ||||
|  | ||||
|   return compiledFiles; | ||||
| }; | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user