Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
6d68f35a9a | |||
0378b9feca | |||
5ecf4b7125 | |||
2aa6348cdd | |||
9f42670865 | |||
6cc9f41bd2 | |||
5d32ac85e0 | |||
4f2ac6922a | |||
31834e0b3e | |||
c6c94866bb |
32
changelog.md
32
changelog.md
@ -1,5 +1,37 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-03-20 - 2.3.2 - fix(compileGlobStringObject)
|
||||||
|
Fix duplicate file outputs in glob pattern processing
|
||||||
|
|
||||||
|
- Removed duplicate concatenation of compiled files in compileGlobStringObject
|
||||||
|
- Ensured unique file paths are used during TypeScript compilation
|
||||||
|
|
||||||
|
## 2025-03-20 - 2.3.1 - fix(compiler)
|
||||||
|
Refactor compiler implementation with consolidated TsBuild class and improved diagnostics handling
|
||||||
|
|
||||||
|
- Removed legacy tsbuild.classes.compiler.ts and introduced tsbuild.classes.tsbuild.ts
|
||||||
|
- Unified compiler options merging, reading tsconfig.json, and diagnostics reporting within the TsBuild class
|
||||||
|
- Updated exports to reference the new compiler class implementation for backward compatibility
|
||||||
|
|
||||||
|
## 2025-03-20 - 2.3.0 - feat(cli)
|
||||||
|
Add emitcheck command to validate TS file emission without generating output
|
||||||
|
|
||||||
|
- Implemented the emitcheck CLI command to allow checking if TypeScript files can be emitted without producing files
|
||||||
|
- Updated tsbuild.classes.compiler.ts to include the emitCheck function
|
||||||
|
- Enhanced documentation in readme.md to describe the new emitcheck usage with examples
|
||||||
|
|
||||||
|
## 2025-03-17 - 2.2.7 - fix(compiler)
|
||||||
|
Improve diagnostic checking and error handling in the TypeScript compiler integration
|
||||||
|
|
||||||
|
- Added pre-emit diagnostics check to log errors before emitting
|
||||||
|
- Process exits on encountering pre-emit errors to ensure build correctness
|
||||||
|
- Enhanced logging for emit diagnostics to aid debugging
|
||||||
|
|
||||||
|
## 2025-03-04 - 2.2.6 - fix(package)
|
||||||
|
Fix repository URL in package.json
|
||||||
|
|
||||||
|
- Updated repository URL in package.json to point to the correct Git repository.
|
||||||
|
|
||||||
## 2025-03-04 - 2.2.5 - fix(package.json)
|
## 2025-03-04 - 2.2.5 - fix(package.json)
|
||||||
Update repository URLs in package metadata.
|
Update repository URLs in package metadata.
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@git.zone/tsbuild",
|
"name": "@git.zone/tsbuild",
|
||||||
"version": "2.2.5",
|
"version": "2.3.2",
|
||||||
"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",
|
||||||
@ -16,7 +16,7 @@
|
|||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+ssh://git@gitlab.com/pushrocks/tsn.git"
|
"url": "https://code.foss.global/git.zone/tsbuild.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"TypeScript",
|
"TypeScript",
|
||||||
|
25
readme.md
25
readme.md
@ -121,6 +121,31 @@ compiling in this order:
|
|||||||
[ 'ts_interfaces', 'ts_shared', 'ts_core', 'ts_utils', 'ts_modules' ]
|
[ 'ts_interfaces', 'ts_shared', 'ts_core', 'ts_utils', 'ts_modules' ]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### EmitCheck Command
|
||||||
|
|
||||||
|
Checks if TypeScript files can be emitted without actually emitting them:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx tsbuild emitcheck <file_or_glob_pattern> [additional_patterns ...]
|
||||||
|
```
|
||||||
|
|
||||||
|
This command:
|
||||||
|
1. Performs type checking on the specified TypeScript file(s)
|
||||||
|
2. Supports both direct file paths and glob patterns
|
||||||
|
3. Reports any errors that would prevent successful compilation
|
||||||
|
4. Exits with code 0 if all files can be emitted, or 1 if any cannot
|
||||||
|
5. Doesn't produce any output files
|
||||||
|
|
||||||
|
Example usage with specific files:
|
||||||
|
```bash
|
||||||
|
npx tsbuild emitcheck src/main.ts src/utils.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
Example usage with glob patterns:
|
||||||
|
```bash
|
||||||
|
npx tsbuild emitcheck "src/**/*.ts" "test/**/*.ts"
|
||||||
|
```
|
||||||
|
|
||||||
## Compiler Options
|
## Compiler Options
|
||||||
|
|
||||||
Additional flags can be passed to any command to modify the compilation behavior:
|
Additional flags can be passed to any command to modify the compilation behavior:
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@git.zone/tsbuild',
|
name: '@git.zone/tsbuild',
|
||||||
version: '2.2.5',
|
version: '2.3.2',
|
||||||
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.'
|
||||||
}
|
}
|
||||||
|
@ -1,128 +0,0 @@
|
|||||||
// import all the stuff we need
|
|
||||||
import * as plugins from './plugins.js';
|
|
||||||
import * as paths from './paths.js';
|
|
||||||
import type { CompilerOptions, ScriptTarget, ModuleKind } from './tsbuild.exports.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the default typescript compilerOptions
|
|
||||||
*/
|
|
||||||
export const compilerOptionsDefault: CompilerOptions = {
|
|
||||||
declaration: true,
|
|
||||||
emitDecoratorMetadata: true,
|
|
||||||
experimentalDecorators: true,
|
|
||||||
inlineSourceMap: true,
|
|
||||||
noEmitOnError: true,
|
|
||||||
outDir: 'dist_ts/',
|
|
||||||
module: plugins.typescript.ModuleKind.NodeNext,
|
|
||||||
target: plugins.typescript.ScriptTarget.ESNext,
|
|
||||||
moduleResolution: plugins.typescript.ModuleResolutionKind.NodeNext,
|
|
||||||
lib: ['lib.dom.d.ts', 'lib.es2022.d.ts'],
|
|
||||||
noImplicitAny: true,
|
|
||||||
esModuleInterop: true,
|
|
||||||
useDefineForClassFields: false,
|
|
||||||
verbatimModuleSyntax: true,
|
|
||||||
baseUrl: './',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* merges compilerOptions with the default compiler options
|
|
||||||
*/
|
|
||||||
export const mergeCompilerOptions = (
|
|
||||||
customTsOptions: CompilerOptions,
|
|
||||||
argvArg?: any
|
|
||||||
): CompilerOptions => {
|
|
||||||
// create merged options
|
|
||||||
const mergedOptions: CompilerOptions = {
|
|
||||||
...compilerOptionsDefault,
|
|
||||||
...customTsOptions,
|
|
||||||
...(argvArg && argvArg.skiplibcheck
|
|
||||||
? {
|
|
||||||
skipLibCheck: true,
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
...(argvArg && argvArg.allowimplicitany
|
|
||||||
? {
|
|
||||||
noImplicitAny: false,
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
...(argvArg && argvArg.commonjs
|
|
||||||
? {
|
|
||||||
module: plugins.typescript.ModuleKind.CommonJS,
|
|
||||||
moduleResolution: plugins.typescript.ModuleResolutionKind.NodeJs,
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
...(() => {
|
|
||||||
const returnObject: CompilerOptions = {};
|
|
||||||
console.log(`looking at tsconfig.json at ${paths.cwd}`);
|
|
||||||
const tsconfig = plugins.smartfile.fs.toObjectSync(plugins.path.join(paths.cwd, 'tsconfig.json'));
|
|
||||||
if (tsconfig && tsconfig.compilerOptions && tsconfig.compilerOptions.baseUrl) {
|
|
||||||
console.log('baseUrl found in tsconfig.json');
|
|
||||||
returnObject.baseUrl = tsconfig.compilerOptions.baseUrl;
|
|
||||||
}
|
|
||||||
if (tsconfig && tsconfig.compilerOptions && tsconfig.compilerOptions.paths) {
|
|
||||||
console.log('paths found in tsconfig.json');
|
|
||||||
returnObject.paths = tsconfig.compilerOptions.paths;
|
|
||||||
for (const path of Object.keys(tsconfig.compilerOptions.paths)) {
|
|
||||||
returnObject.paths[path][0] = returnObject.paths[path][0].replace('./ts_', './dist_ts_');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnObject;
|
|
||||||
})(),
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log(mergedOptions);
|
|
||||||
|
|
||||||
return mergedOptions;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the internal main compiler function that compiles the files
|
|
||||||
*/
|
|
||||||
export const compiler = async (
|
|
||||||
fileNames: string[],
|
|
||||||
options: plugins.typescript.CompilerOptions,
|
|
||||||
argvArg?: any
|
|
||||||
): Promise<any[]> => {
|
|
||||||
if (options.skipLibCheck) {
|
|
||||||
console.log('? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?');
|
|
||||||
console.log('You are skipping libcheck... Is that really wanted?');
|
|
||||||
console.log('continuing in 5 seconds...');
|
|
||||||
console.log('? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?');
|
|
||||||
await plugins.smartdelay.delayFor(5000);
|
|
||||||
}
|
|
||||||
console.log(`Compiling ${fileNames.length} files...`);
|
|
||||||
const done = plugins.smartpromise.defer<any[]>();
|
|
||||||
const program = plugins.typescript.createProgram(fileNames, options);
|
|
||||||
const emitResult = program.emit();
|
|
||||||
|
|
||||||
// implement check only
|
|
||||||
/*let emitResult = program.emit(undefined,(args) => {
|
|
||||||
console.log(args)
|
|
||||||
});*/
|
|
||||||
|
|
||||||
const allDiagnostics = plugins.typescript
|
|
||||||
.getPreEmitDiagnostics(program)
|
|
||||||
.concat(emitResult.diagnostics);
|
|
||||||
allDiagnostics.forEach((diagnostic) => {
|
|
||||||
if (diagnostic.file) {
|
|
||||||
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!);
|
|
||||||
const message = plugins.typescript.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
|
||||||
console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
|
|
||||||
} else {
|
|
||||||
console.log(
|
|
||||||
`${plugins.typescript.flattenDiagnosticMessageText(diagnostic.messageText, '\n')}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const exitCode = emitResult.emitSkipped ? 1 : 0;
|
|
||||||
if (exitCode === 0) {
|
|
||||||
console.log('TypeScript emit succeeded!');
|
|
||||||
done.resolve(emitResult.emittedFiles);
|
|
||||||
} else {
|
|
||||||
console.error('TypeScript emit failed. Please investigate!');
|
|
||||||
process.exit(exitCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return done.promise;
|
|
||||||
};
|
|
271
ts/tsbuild.classes.tsbuild.ts
Normal file
271
ts/tsbuild.classes.tsbuild.ts
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
// import all the stuff we need
|
||||||
|
import * as plugins from './plugins.js';
|
||||||
|
import * as paths from './paths.js';
|
||||||
|
import type { CompilerOptions, ScriptTarget, ModuleKind } from './tsbuild.exports.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default compiler options for TypeScript compilation
|
||||||
|
*/
|
||||||
|
export const compilerOptionsDefault: CompilerOptions = {
|
||||||
|
declaration: true,
|
||||||
|
emitDecoratorMetadata: true,
|
||||||
|
experimentalDecorators: true,
|
||||||
|
inlineSourceMap: true,
|
||||||
|
noEmitOnError: true,
|
||||||
|
outDir: 'dist_ts/',
|
||||||
|
module: plugins.typescript.ModuleKind.NodeNext,
|
||||||
|
target: plugins.typescript.ScriptTarget.ESNext,
|
||||||
|
moduleResolution: plugins.typescript.ModuleResolutionKind.NodeNext,
|
||||||
|
lib: ['lib.dom.d.ts', 'lib.es2022.d.ts'],
|
||||||
|
noImplicitAny: true,
|
||||||
|
esModuleInterop: true,
|
||||||
|
useDefineForClassFields: false,
|
||||||
|
verbatimModuleSyntax: true,
|
||||||
|
baseUrl: './',
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TsBuild class for handling TypeScript compilation
|
||||||
|
*/
|
||||||
|
export class TsBuild {
|
||||||
|
private fileNames: string[] = [];
|
||||||
|
private options: plugins.typescript.CompilerOptions;
|
||||||
|
private argvArg?: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new TsBuild instance
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
fileNames: string[] = [],
|
||||||
|
customOptions: CompilerOptions = {},
|
||||||
|
argvArg?: any
|
||||||
|
) {
|
||||||
|
this.fileNames = fileNames;
|
||||||
|
this.argvArg = argvArg;
|
||||||
|
this.options = this.mergeCompilerOptions(customOptions, argvArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to read and process tsconfig.json
|
||||||
|
*/
|
||||||
|
private getTsConfigOptions(): CompilerOptions {
|
||||||
|
console.log(`looking at tsconfig.json at ${paths.cwd}`);
|
||||||
|
const tsconfig = plugins.smartfile.fs.toObjectSync(plugins.path.join(paths.cwd, 'tsconfig.json'));
|
||||||
|
const returnObject: CompilerOptions = {};
|
||||||
|
|
||||||
|
if (!tsconfig || !tsconfig.compilerOptions) {
|
||||||
|
return returnObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tsconfig.compilerOptions.baseUrl) {
|
||||||
|
console.log('baseUrl found in tsconfig.json');
|
||||||
|
returnObject.baseUrl = tsconfig.compilerOptions.baseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tsconfig.compilerOptions.paths) {
|
||||||
|
console.log('paths found in tsconfig.json');
|
||||||
|
returnObject.paths = tsconfig.compilerOptions.paths;
|
||||||
|
for (const path of Object.keys(tsconfig.compilerOptions.paths)) {
|
||||||
|
returnObject.paths[path][0] = returnObject.paths[path][0].replace('./ts_', './dist_ts_');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process command line arguments and return applicable compiler options
|
||||||
|
*/
|
||||||
|
private getCommandLineOptions(argvArg?: any): CompilerOptions {
|
||||||
|
if (!argvArg) return {};
|
||||||
|
|
||||||
|
const options: CompilerOptions = {};
|
||||||
|
|
||||||
|
if (argvArg.skiplibcheck) {
|
||||||
|
options.skipLibCheck = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argvArg.allowimplicitany) {
|
||||||
|
options.noImplicitAny = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argvArg.commonjs) {
|
||||||
|
options.module = plugins.typescript.ModuleKind.CommonJS;
|
||||||
|
options.moduleResolution = plugins.typescript.ModuleResolutionKind.NodeJs;
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges compilerOptions with the default compiler options
|
||||||
|
*/
|
||||||
|
public mergeCompilerOptions(
|
||||||
|
customTsOptions: CompilerOptions = {},
|
||||||
|
argvArg?: any
|
||||||
|
): CompilerOptions {
|
||||||
|
// create merged options
|
||||||
|
const mergedOptions: CompilerOptions = {
|
||||||
|
...compilerOptionsDefault,
|
||||||
|
...customTsOptions,
|
||||||
|
...this.getCommandLineOptions(argvArg),
|
||||||
|
...this.getTsConfigOptions(),
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(mergedOptions);
|
||||||
|
return mergedOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to handle and log TypeScript diagnostics
|
||||||
|
*/
|
||||||
|
private handleDiagnostics(diagnostics: readonly plugins.typescript.Diagnostic[]): boolean {
|
||||||
|
let hasErrors = false;
|
||||||
|
|
||||||
|
diagnostics.forEach((diagnostic) => {
|
||||||
|
hasErrors = true;
|
||||||
|
if (diagnostic.file) {
|
||||||
|
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!);
|
||||||
|
const message = plugins.typescript.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||||
|
console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
`${plugins.typescript.flattenDiagnosticMessageText(diagnostic.messageText, '\n')}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return hasErrors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a TypeScript program from file names and options
|
||||||
|
*/
|
||||||
|
private createProgram(
|
||||||
|
options: plugins.typescript.CompilerOptions = this.options
|
||||||
|
): plugins.typescript.Program {
|
||||||
|
return plugins.typescript.createProgram(this.fileNames, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set file names to be compiled
|
||||||
|
*/
|
||||||
|
public setFileNames(fileNames: string[]): void {
|
||||||
|
this.fileNames = fileNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set compiler options
|
||||||
|
*/
|
||||||
|
public setOptions(options: CompilerOptions): void {
|
||||||
|
this.options = { ...this.options, ...options };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main compiler function that compiles the files
|
||||||
|
*/
|
||||||
|
public async compile(): Promise<any[]> {
|
||||||
|
if (this.options.skipLibCheck) {
|
||||||
|
console.log('? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?');
|
||||||
|
console.log('You are skipping libcheck... Is that really wanted?');
|
||||||
|
console.log('continuing in 5 seconds...');
|
||||||
|
console.log('? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?');
|
||||||
|
await plugins.smartdelay.delayFor(5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Compiling ${this.fileNames.length} files...`);
|
||||||
|
const done = plugins.smartpromise.defer<any[]>();
|
||||||
|
const program = this.createProgram();
|
||||||
|
|
||||||
|
// Check for pre-emit diagnostics first
|
||||||
|
const preEmitDiagnostics = plugins.typescript.getPreEmitDiagnostics(program);
|
||||||
|
const hasPreEmitErrors = this.handleDiagnostics(preEmitDiagnostics);
|
||||||
|
|
||||||
|
// Only continue to emit phase if no pre-emit errors
|
||||||
|
if (hasPreEmitErrors) {
|
||||||
|
console.error('TypeScript pre-emit checks failed. Please fix the issues above.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no pre-emit errors, proceed with emit
|
||||||
|
const emitResult = program.emit();
|
||||||
|
const hasEmitErrors = this.handleDiagnostics(emitResult.diagnostics);
|
||||||
|
|
||||||
|
const exitCode = emitResult.emitSkipped ? 1 : 0;
|
||||||
|
if (exitCode === 0) {
|
||||||
|
console.log('TypeScript emit succeeded!');
|
||||||
|
done.resolve(emitResult.emittedFiles);
|
||||||
|
} else {
|
||||||
|
console.error('TypeScript emit failed. Please investigate!');
|
||||||
|
process.exit(exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return done.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to check if files can be emitted without actually emitting them
|
||||||
|
*/
|
||||||
|
public async checkEmit(): Promise<boolean> {
|
||||||
|
console.log(`Checking if ${this.fileNames.length} files can be emitted...`);
|
||||||
|
|
||||||
|
// Create a program with noEmit option
|
||||||
|
const program = this.createProgram({
|
||||||
|
...this.options,
|
||||||
|
noEmit: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check for pre-emit diagnostics
|
||||||
|
const preEmitDiagnostics = plugins.typescript.getPreEmitDiagnostics(program);
|
||||||
|
const hasPreEmitErrors = this.handleDiagnostics(preEmitDiagnostics);
|
||||||
|
|
||||||
|
// Run the emit phase but with noEmit: true to check for emit errors without producing files
|
||||||
|
const emitResult = program.emit(undefined, undefined, undefined, true);
|
||||||
|
const hasEmitErrors = this.handleDiagnostics(emitResult.diagnostics);
|
||||||
|
|
||||||
|
const success = !hasPreEmitErrors && !hasEmitErrors && !emitResult.emitSkipped;
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
console.log('TypeScript emit check passed! File can be emitted successfully.');
|
||||||
|
} else {
|
||||||
|
console.error('TypeScript emit check failed. Please fix the issues above.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges compilerOptions with the default compiler options (backward compatibility)
|
||||||
|
*/
|
||||||
|
export const mergeCompilerOptions = (
|
||||||
|
customTsOptions: CompilerOptions,
|
||||||
|
argvArg?: any
|
||||||
|
): CompilerOptions => {
|
||||||
|
const tsBuild = new TsBuild();
|
||||||
|
return tsBuild.mergeCompilerOptions(customTsOptions, argvArg);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The internal main compiler function that compiles the files (backward compatibility)
|
||||||
|
*/
|
||||||
|
export const compiler = async (
|
||||||
|
fileNames: string[],
|
||||||
|
options: plugins.typescript.CompilerOptions,
|
||||||
|
argvArg?: any
|
||||||
|
): Promise<any[]> => {
|
||||||
|
const tsBuild = new TsBuild(fileNames, options, argvArg);
|
||||||
|
return tsBuild.compile();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to check if a TypeScript file can be emitted without actually emitting it (backward compatibility)
|
||||||
|
*/
|
||||||
|
export const emitCheck = async (
|
||||||
|
fileNames: string[],
|
||||||
|
options: plugins.typescript.CompilerOptions = {},
|
||||||
|
argvArg?: any
|
||||||
|
): Promise<boolean> => {
|
||||||
|
const tsBuild = new TsBuild(fileNames, options, argvArg);
|
||||||
|
return tsBuild.checkEmit();
|
||||||
|
};
|
@ -32,6 +32,87 @@ export const runCli = async () => {
|
|||||||
await tsbuild.compileGlobStringObject(compilationCommandObject, {}, process.cwd(), argvArg);
|
await tsbuild.compileGlobStringObject(compilationCommandObject, {}, process.cwd(), argvArg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the emitcheck command checks if a TypeScript file can be emitted without actually emitting it
|
||||||
|
*/
|
||||||
|
tsbuildCli.addCommand('emitcheck').subscribe(async (argvArg) => {
|
||||||
|
const patterns = argvArg._.slice(1); // Remove the first element which is 'emitcheck'
|
||||||
|
|
||||||
|
if (patterns.length === 0) {
|
||||||
|
console.error('Error: Please provide at least one TypeScript file path or glob pattern');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cwd = process.cwd();
|
||||||
|
let allFiles: string[] = [];
|
||||||
|
|
||||||
|
// Process each pattern - could be a direct file path or a glob pattern
|
||||||
|
for (const pattern of patterns) {
|
||||||
|
// Check if the pattern looks like a glob pattern
|
||||||
|
if (pattern.includes('*') || pattern.includes('{') || pattern.includes('?')) {
|
||||||
|
// Handle as glob pattern
|
||||||
|
console.log(`Processing glob pattern: ${pattern}`);
|
||||||
|
try {
|
||||||
|
const matchedFiles = await plugins.smartfile.fs.listFileTree(cwd, pattern);
|
||||||
|
|
||||||
|
// Ensure matchedFiles contains only strings
|
||||||
|
const stringMatchedFiles = Array.isArray(matchedFiles)
|
||||||
|
? matchedFiles.filter((item): item is string => typeof item === 'string')
|
||||||
|
: [];
|
||||||
|
|
||||||
|
if (stringMatchedFiles.length === 0) {
|
||||||
|
console.warn(`Warning: No files matched the pattern '${pattern}'`);
|
||||||
|
} else {
|
||||||
|
console.log(`Found ${stringMatchedFiles.length} files matching pattern '${pattern}'`);
|
||||||
|
|
||||||
|
// Transform to absolute paths
|
||||||
|
const absoluteMatchedFiles = plugins.smartpath.transform.toAbsolute(
|
||||||
|
stringMatchedFiles,
|
||||||
|
cwd
|
||||||
|
) as string[];
|
||||||
|
|
||||||
|
// Add to the list of all files to check
|
||||||
|
allFiles = allFiles.concat(absoluteMatchedFiles);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error processing glob pattern '${pattern}': ${err}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Handle as direct file path
|
||||||
|
const filePath = plugins.path.isAbsolute(pattern)
|
||||||
|
? pattern
|
||||||
|
: plugins.path.join(cwd, pattern);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await plugins.smartfile.fs.fileExists(filePath);
|
||||||
|
allFiles.push(filePath);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error: File not found: ${filePath}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter to only TypeScript files
|
||||||
|
allFiles = allFiles.filter(file => file.endsWith('.ts') || file.endsWith('.tsx'));
|
||||||
|
|
||||||
|
if (allFiles.length === 0) {
|
||||||
|
console.error('Error: No TypeScript files found to check');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Found ${allFiles.length} TypeScript files to check`);
|
||||||
|
|
||||||
|
// Process compiler options
|
||||||
|
const compilerOptions = tsbuild.mergeCompilerOptions({}, argvArg);
|
||||||
|
|
||||||
|
// Run emit check
|
||||||
|
const success = await tsbuild.emitCheck(allFiles, compilerOptions, argvArg);
|
||||||
|
|
||||||
|
// Exit with appropriate code
|
||||||
|
process.exit(success ? 0 : 1);
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the custom command compiles any customDir to dist_customDir
|
* the custom command compiles any customDir to dist_customDir
|
||||||
*/
|
*/
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import * as plugins from './plugins.js';
|
import * as plugins from './plugins.js';
|
||||||
import type { CompilerOptions, ScriptTarget, ModuleKind } from 'typescript';
|
import type { CompilerOptions, ScriptTarget, ModuleKind } from 'typescript';
|
||||||
import { compiler, mergeCompilerOptions } from './tsbuild.classes.compiler.js';
|
import { compiler, mergeCompilerOptions, emitCheck } from './tsbuild.classes.tsbuild.js';
|
||||||
|
|
||||||
export type { CompilerOptions, ScriptTarget, ModuleKind };
|
export type { CompilerOptions, ScriptTarget, ModuleKind };
|
||||||
|
|
||||||
export * from './tsbuild.classes.compiler.js';
|
export * from './tsbuild.classes.tsbuild.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* compile am array of absolute file paths
|
* compile am array of absolute file paths
|
||||||
|
Loading…
x
Reference in New Issue
Block a user