Compare commits

...

16 Commits

Author SHA1 Message Date
c6ab493efc 2.7.0 2025-11-02 05:31:55 +00:00
82ae8a0e4a feat(tsbuild): Add tsconfig.json support and safer compiler option merging; protect critical options; apply path and enum transforms; bump dependencies. 2025-11-02 05:31:55 +00:00
787becc4d3 2.6.8 2025-08-29 17:14:58 +00:00
746ca8767a fix(tsbuild): Avoid process.exit in library, add confirmskiplibcheck flag, improve CLI exit handling and JSON/quiet modes, update test script 2025-08-29 17:14:58 +00:00
55c1a2953a 2.6.7 2025-08-18 02:19:15 +00:00
8e9fcb8135 fix(tspublish): Bump @git.zone/tspublish dependency to ^1.10.3 2025-08-18 02:19:15 +00:00
18573c777d 2.6.6 2025-08-18 00:32:26 +00:00
fa654b83e3 fix(dependencies): Update dependency @git.zone/tspublish to ^1.10.2 2025-08-18 00:32:26 +00:00
aa3c83cd95 2.6.5 2025-08-18 00:29:51 +00:00
20ed41df42 fix(dependencies): Bump dependencies and add pnpm-workspace configuration 2025-08-18 00:29:51 +00:00
7162476f7f 2.6.4 2025-05-24 00:30:16 +00:00
1b012628eb fix(dependencies): Add .npmrc and update dependency versions for smartfile and tstest 2025-05-24 00:30:16 +00:00
4081086621 2.6.3 2025-05-21 18:06:46 +00:00
b9cf09ccba fix(tsbuild): minor maintenance updates and documentation improvements 2025-05-21 18:06:46 +00:00
8463fbc78a 2.6.2 2025-05-21 17:59:28 +00:00
0164eb51a1 fix(npm configuration): Remove .npmrc file to default npm registry behavior 2025-05-21 17:59:28 +00:00
10 changed files with 3855 additions and 3391 deletions

1
.npmrc
View File

@@ -1 +0,0 @@
registry=https://registry.npmjs.org/

View File

@@ -1,5 +1,66 @@
# Changelog # Changelog
## 2025-11-02 - 2.7.0 - feat(tsbuild)
Add tsconfig.json support and safer compiler option merging; protect critical options; apply path and enum transforms; bump dependencies.
- Add robust tsconfig.json reading with graceful fallback when no tsconfig is present or it is invalid
- Merge compiler options in a clear priority order (defaults -> tsconfig -> protected defaults -> programmatic -> CLI flags)
- Introduce protected (critical) compiler options that cannot be overridden by tsconfig.json: outDir, noEmitOnError, declaration, emitDecoratorMetadata, inlineSourceMap
- Convert string values from tsconfig (target, module, moduleResolution) to TypeScript enum values where applicable; special-case NodeNext
- Transform tsconfig path mappings by replacing './ts_' with './dist_ts_' to keep runtime path resolution consistent with compiled output
- Expose getCriticalDefaults helper and adjust mergeCompilerOptions to apply protected defaults before programmatic and CLI overrides
- Update README with documentation for tsconfig support, merge order, protected compiler options, and example tsconfig
- Bump dependencies/devDependencies: @push.rocks/smartcli ^4.0.19, @push.rocks/smartlog ^3.1.10, typescript 5.9.3, @git.zone/tsrun ^1.6.2, @git.zone/tstest ^2.7.0
## 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)
Bump @git.zone/tspublish dependency to ^1.10.3
- Updated dependency @git.zone/tspublish from ^1.10.2 to ^1.10.3 in package.json
## 2025-08-18 - 2.6.6 - fix(dependencies)
Update dependency @git.zone/tspublish to ^1.10.2
- Bumped @git.zone/tspublish in package.json from ^1.10.1 to ^1.10.2
## 2025-08-18 - 2.6.5 - fix(dependencies)
Bump dependencies and add pnpm-workspace configuration
- Updated @git.zone/tspublish from ^1.9.1 to ^1.10.1
- Updated @push.rocks/smartfile from ^11.2.4 to ^11.2.7
- Updated @push.rocks/smartpath from ^5.0.18 to ^6.0.0
- Updated typescript from 5.8.3 to 5.9.2
- Updated devDependency @git.zone/tstest from ^1.10.1 to ^2.3.4
- Added pnpm-workspace.yaml with onlyBuiltDependencies list (esbuild, mongodb-memory-server, puppeteer)
## 2025-05-24 - 2.6.4 - fix(dependencies)
Add .npmrc and update dependency versions for smartfile and tstest
- Add .npmrc with registry configuration for npm
- Bump @push.rocks/smartfile version from ^11.2.3 to ^11.2.4
- Bump @git.zone/tstest version from ^1.9.0 to ^1.10.1
## 2025-05-21 - 2.6.3 - fix(tsbuild)
minor maintenance updates and documentation improvements
- Updated commit metadata to align with project version
- Refined CLI command parsing and diagnostics logging for better clarity
- Improved code readability in compiler options merging
## 2025-05-21 - 2.6.2 - fix(npm configuration)
Remove .npmrc file to default npm registry behavior
- Deleted .npmrc file that hard-coded the npm registry URL to https://registry.npmjs.org/
- This change leverages npm's default registry settings and reduces configuration clutter
## 2025-05-21 - 2.6.1 - fix(tsbuild.classes) ## 2025-05-21 - 2.6.1 - fix(tsbuild.classes)
Improve error diagnostics handling by removing legacy helper and integrating more robust error summaries in the compilation process Improve error diagnostics handling by removing legacy helper and integrating more robust error summaries in the compilation process

View File

@@ -1,6 +1,6 @@
{ {
"name": "@git.zone/tsbuild", "name": "@git.zone/tsbuild",
"version": "2.6.1", "version": "2.7.0",
"private": false, "private": false,
"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.",
"main": "dist_ts/index.js", "main": "dist_ts/index.js",
@@ -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"
}, },
@@ -36,19 +36,19 @@
}, },
"homepage": "https://code.foss.global/git.zone/tsbuild#README", "homepage": "https://code.foss.global/git.zone/tsbuild#README",
"dependencies": { "dependencies": {
"@git.zone/tspublish": "^1.9.1", "@git.zone/tspublish": "^1.10.3",
"@push.rocks/early": "^4.0.4", "@push.rocks/early": "^4.0.4",
"@push.rocks/smartcli": "^4.0.11", "@push.rocks/smartcli": "^4.0.19",
"@push.rocks/smartdelay": "^3.0.5", "@push.rocks/smartdelay": "^3.0.5",
"@push.rocks/smartfile": "^11.2.3", "@push.rocks/smartfile": "^11.2.7",
"@push.rocks/smartlog": "^3.1.8", "@push.rocks/smartlog": "^3.1.10",
"@push.rocks/smartpath": "^5.0.18", "@push.rocks/smartpath": "^6.0.0",
"@push.rocks/smartpromise": "^4.2.3", "@push.rocks/smartpromise": "^4.2.3",
"typescript": "5.8.3" "typescript": "5.9.3"
}, },
"devDependencies": { "devDependencies": {
"@git.zone/tsrun": "^1.2.47", "@git.zone/tsrun": "^1.6.2",
"@git.zone/tstest": "^1.9.0", "@git.zone/tstest": "^2.7.0",
"@types/node": "^22.15.21" "@types/node": "^22.15.21"
}, },
"files": [ "files": [

6869
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

4
pnpm-workspace.yaml Normal file
View File

@@ -0,0 +1,4 @@
onlyBuiltDependencies:
- esbuild
- mongodb-memory-server
- puppeteer

View File

@@ -184,6 +184,49 @@ Example:
npx tsbuild --skiplibcheck --disallowimplicitany npx tsbuild --skiplibcheck --disallowimplicitany
``` ```
## Configuration with tsconfig.json
`@git.zone/tsbuild` fully supports `tsconfig.json` for compiler configuration. All compiler options from your `tsconfig.json` will be respected and merged with tsbuild's defaults.
### Option Priority (Merge Order)
When multiple configuration sources are present, they are merged in the following order (later sources override earlier ones):
1. **Default compiler options** - Base defaults for all options
2. **tsconfig.json** - All compiler options from your project's `tsconfig.json` (if present)
3. **Protected defaults** - Critical options for build integrity (see below)
4. **Programmatic options** - Options passed to API functions
5. **CLI flags** - Command-line arguments (highest priority)
### Protected Compiler Options
To ensure build integrity and correct functionality, the following options are protected and cannot be overridden by `tsconfig.json` alone (but can be overridden programmatically or via CLI):
- `outDir: 'dist_ts/'` - Required for path transformation logic
- `noEmitOnError: true` - Prevents broken builds from being emitted
- `declaration: true` - Ensures .d.ts files for library consumers
- `emitDecoratorMetadata: true` - Required for dependency injection frameworks
- `inlineSourceMap: true` - Provides consistent debugging experience
### Working Without tsconfig.json
`@git.zone/tsbuild` works perfectly fine without a `tsconfig.json` file. If no `tsconfig.json` is found, it will gracefully fall back to sensible defaults without errors.
Example `tsconfig.json`:
```json
{
"compilerOptions": {
"experimentalDecorators": true,
"useDefineForClassFields": false,
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"verbatimModuleSyntax": true
}
}
```
## Default Compiler Options ## Default Compiler Options
By default, `@git.zone/tsbuild` uses the following compiler options: By default, `@git.zone/tsbuild` uses the following compiler options:
@@ -200,7 +243,7 @@ By default, `@git.zone/tsbuild` uses the following compiler options:
target: ScriptTarget.ESNext, target: ScriptTarget.ESNext,
moduleResolution: ModuleResolutionKind.NodeNext, moduleResolution: ModuleResolutionKind.NodeNext,
lib: ['lib.dom.d.ts', 'lib.es2022.d.ts'], lib: ['lib.dom.d.ts', 'lib.es2022.d.ts'],
noImplicitAny: false, // Now allowing implicit any by default noImplicitAny: false,
esModuleInterop: true, esModuleInterop: true,
useDefineForClassFields: false, useDefineForClassFields: false,
verbatimModuleSyntax: true, verbatimModuleSyntax: true,
@@ -208,7 +251,7 @@ By default, `@git.zone/tsbuild` uses the following compiler options:
} }
``` ```
These options can be overridden by providing a custom `CompilerOptions` object. These defaults are merged with your `tsconfig.json` options (if present), programmatic options, and CLI flags according to the priority order described above.
## Path Resolution ## Path Resolution

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@git.zone/tsbuild', name: '@git.zone/tsbuild',
version: '2.6.1', version: '2.7.0',
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.'
} }

View File

@@ -62,19 +62,56 @@ export class TsBuild {
* Helper function to read and process tsconfig.json * Helper function to read and process tsconfig.json
*/ */
private getTsConfigOptions(): CompilerOptions { private getTsConfigOptions(): CompilerOptions {
const tsconfig = plugins.smartfile.fs.toObjectSync(plugins.path.join(paths.cwd, 'tsconfig.json')); let tsconfig: any;
const returnObject: CompilerOptions = {};
// Try to read tsconfig.json, but don't fail if it doesn't exist
try {
tsconfig = plugins.smartfile.fs.toObjectSync(plugins.path.join(paths.cwd, 'tsconfig.json'));
} catch (error) {
// tsconfig.json doesn't exist or is invalid - use defaults
return {};
}
if (!tsconfig || !tsconfig.compilerOptions) { if (!tsconfig || !tsconfig.compilerOptions) {
return returnObject; return {};
} }
// Process baseUrl // Start by copying ALL compiler options from tsconfig.json
if (tsconfig.compilerOptions.baseUrl) { const returnObject: CompilerOptions = { ...tsconfig.compilerOptions };
returnObject.baseUrl = tsconfig.compilerOptions.baseUrl;
// Apply special transformations for string-to-enum conversions
// Process target (convert string to enum)
if (tsconfig.compilerOptions.target && typeof tsconfig.compilerOptions.target === 'string') {
const targetKey = tsconfig.compilerOptions.target.toUpperCase();
if (targetKey in plugins.typescript.ScriptTarget) {
returnObject.target = plugins.typescript.ScriptTarget[targetKey as keyof typeof plugins.typescript.ScriptTarget];
}
} }
// Process paths // Process module (convert string to enum)
if (tsconfig.compilerOptions.module && typeof tsconfig.compilerOptions.module === 'string') {
const moduleKey = tsconfig.compilerOptions.module.toUpperCase();
if (moduleKey in plugins.typescript.ModuleKind) {
returnObject.module = plugins.typescript.ModuleKind[moduleKey as keyof typeof plugins.typescript.ModuleKind];
} else if (moduleKey === 'NODENEXT') {
returnObject.module = plugins.typescript.ModuleKind.NodeNext;
}
}
// Process moduleResolution (convert string to enum)
if (tsconfig.compilerOptions.moduleResolution && typeof tsconfig.compilerOptions.moduleResolution === 'string') {
const moduleResolutionKey = tsconfig.compilerOptions.moduleResolution.toUpperCase();
if (moduleResolutionKey in plugins.typescript.ModuleResolutionKind) {
returnObject.moduleResolution = plugins.typescript.ModuleResolutionKind[
moduleResolutionKey as keyof typeof plugins.typescript.ModuleResolutionKind
];
} else if (moduleResolutionKey === 'NODENEXT') {
returnObject.moduleResolution = plugins.typescript.ModuleResolutionKind.NodeNext;
}
}
// Apply path transformations (ts_ → dist_ts_)
if (tsconfig.compilerOptions.paths) { if (tsconfig.compilerOptions.paths) {
returnObject.paths = { ...tsconfig.compilerOptions.paths }; returnObject.paths = { ...tsconfig.compilerOptions.paths };
for (const path of Object.keys(returnObject.paths)) { for (const path of Object.keys(returnObject.paths)) {
@@ -83,58 +120,24 @@ export class TsBuild {
} }
} }
} }
// Process target
if (tsconfig.compilerOptions.target) {
if (typeof tsconfig.compilerOptions.target === 'string') {
const targetKey = tsconfig.compilerOptions.target.toUpperCase();
if (targetKey in plugins.typescript.ScriptTarget) {
returnObject.target = plugins.typescript.ScriptTarget[targetKey as keyof typeof plugins.typescript.ScriptTarget];
}
}
}
// Process module
if (tsconfig.compilerOptions.module) {
if (typeof tsconfig.compilerOptions.module === 'string') {
const moduleKey = tsconfig.compilerOptions.module.toUpperCase();
if (moduleKey in plugins.typescript.ModuleKind) {
returnObject.module = plugins.typescript.ModuleKind[moduleKey as keyof typeof plugins.typescript.ModuleKind];
} else if (moduleKey === 'NODENEXT') {
returnObject.module = plugins.typescript.ModuleKind.NodeNext;
}
}
}
// Process moduleResolution
if (tsconfig.compilerOptions.moduleResolution) {
if (typeof tsconfig.compilerOptions.moduleResolution === 'string') {
const moduleResolutionKey = tsconfig.compilerOptions.moduleResolution.toUpperCase();
if (moduleResolutionKey in plugins.typescript.ModuleResolutionKind) {
returnObject.moduleResolution = plugins.typescript.ModuleResolutionKind[
moduleResolutionKey as keyof typeof plugins.typescript.ModuleResolutionKind
];
} else if (moduleResolutionKey === 'NODENEXT') {
returnObject.moduleResolution = plugins.typescript.ModuleResolutionKind.NodeNext;
}
}
}
// Copy boolean options directly
const booleanOptions = [
'experimentalDecorators', 'useDefineForClassFields',
'esModuleInterop', 'verbatimModuleSyntax'
];
for (const option of booleanOptions) {
if (option in tsconfig.compilerOptions) {
(returnObject as any)[option] = (tsconfig.compilerOptions as any)[option];
}
}
return returnObject; return returnObject;
} }
/**
* Returns critical default options that should not be overridden by tsconfig.json
* These options are essential for tsbuild's functionality and build integrity
*/
private getCriticalDefaults(): CompilerOptions {
return {
outDir: 'dist_ts/', // Required for path transformation logic
noEmitOnError: true, // Build integrity - prevent broken builds
declaration: true, // Library consumers depend on .d.ts files
emitDecoratorMetadata: true, // Required for dependency injection frameworks
inlineSourceMap: true, // Consistent debugging experience
};
}
/** /**
* Process command line arguments and return applicable compiler options * Process command line arguments and return applicable compiler options
*/ */
@@ -162,6 +165,13 @@ export class TsBuild {
/** /**
* Merges compilerOptions with the default compiler options * Merges compilerOptions with the default compiler options
*
* Merge order (later overwrites earlier):
* 1. compilerOptionsDefault - Base defaults for all options
* 2. getTsConfigOptions() - User's tsconfig.json (all options)
* 3. getCriticalDefaults() - Protected options that shouldn't be overridden by tsconfig.json
* 4. customTsOptions - Programmatic options (can override critical defaults)
* 5. getCommandLineOptions() - CLI flags (highest priority)
*/ */
public mergeCompilerOptions( public mergeCompilerOptions(
customTsOptions: CompilerOptions = {}, customTsOptions: CompilerOptions = {},
@@ -169,10 +179,11 @@ export class TsBuild {
): CompilerOptions { ): CompilerOptions {
// create merged options // create merged options
const mergedOptions: CompilerOptions = { const mergedOptions: CompilerOptions = {
...compilerOptionsDefault, ...compilerOptionsDefault, // 1. All defaults
...customTsOptions, ...this.getTsConfigOptions(), // 2. User's tsconfig.json (all options)
...this.getCommandLineOptions(argvArg), ...this.getCriticalDefaults(), // 3. Protected overrides
...this.getTsConfigOptions(), ...customTsOptions, // 4. Programmatic options
...this.getCommandLineOptions(argvArg), // 5. CLI flags (highest priority)
}; };
return mergedOptions; return mergedOptions;
@@ -309,10 +320,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) {
console.log('\n⚠ WARNING ⚠️'); if (this.argvArg?.confirmskiplibcheck) {
console.log('You are skipping libcheck... Is that really wanted?'); console.log('\n⚠ WARNING ⚠️');
console.log('Continuing in 5 seconds...\n'); console.log('You are skipping libcheck... Is that really wanted?');
await plugins.smartdelay.delayFor(5000); 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 // Enhanced logging with task info
@@ -382,7 +400,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 +413,16 @@ export class TsBuild {
*/ */
public async compile(): Promise<any[]> { public async compile(): Promise<any[]> {
if (this.options.skipLibCheck) { if (this.options.skipLibCheck) {
console.log('\n⚠ WARNING ⚠️'); if (this.argvArg?.confirmskiplibcheck) {
console.log('You are skipping libcheck... Is that really wanted?'); console.log('\n⚠ WARNING ⚠️');
console.log('Continuing in 5 seconds...\n'); console.log('You are skipping libcheck... Is that really wanted?');
await plugins.smartdelay.delayFor(5000); 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...`); console.log(`🔨 Compiling ${this.fileNames.length} files...`);
@@ -412,7 +438,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 +465,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;
@@ -565,4 +593,4 @@ export const checkTypes = async (
): Promise<boolean> => { ): Promise<boolean> => {
const tsBuild = new TsBuild(fileNames, options, argvArg); const tsBuild = new TsBuild(fileNames, options, argvArg);
return tsBuild.checkTypes(); return tsBuild.checkTypes();
}; };

View File

@@ -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);
}
}); });
/** /**

View File

@@ -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)
console.log(`\n👷 TypeScript Compilation Tasks (${totalTasks} task${totalTasks !== 1 ? 's' : ''}):`); const isQuiet = argvArg?.quiet === true;
Object.entries(globStringObjectArg).forEach(([source, dest]) => { const isJson = argvArg?.json === true;
console.log(` 📂 ${source}${dest}`); if (!isQuiet && !isJson) {
}); console.log(`\n👷 TypeScript Compilation Tasks (${totalTasks} task${totalTasks !== 1 ? 's' : ''}):`);
console.log(''); Object.entries(globStringObjectArg).forEach(([source, dest]) => {
console.log(` 📂 ${source}${dest}`);
});
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);
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; return compiledFiles;
}; };