Compare commits
	
		
			12 Commits
		
	
	
		
			v2.2.3
			...
			5ecf4b7125
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 5ecf4b7125 | |||
| 2aa6348cdd | |||
| 9f42670865 | |||
| 6cc9f41bd2 | |||
| 5d32ac85e0 | |||
| 4f2ac6922a | |||
| 31834e0b3e | |||
| c6c94866bb | |||
| 09a648b435 | |||
| 065e0baaf7 | |||
| 89d32617ce | |||
| 094702b917 | 
							
								
								
									
										37
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								changelog.md
									
									
									
									
									
								
							@@ -1,5 +1,42 @@
 | 
				
			|||||||
# Changelog
 | 
					# Changelog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 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)
 | 
				
			||||||
 | 
					Update repository URLs in package metadata.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Corrected the 'bugs.url' and 'homepage' fields with the accurate URLs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2025-03-04 - 2.2.4 - fix(core)
 | 
				
			||||||
 | 
					Fix compiler logic to remove duplicate compiled files and improve glob pattern handling.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Resolved an issue causing duplicate file compilations when using compileGlobStringObject.
 | 
				
			||||||
 | 
					- Improved handling of glob patterns to ensure accurate compilation paths.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 2025-03-04 - 2.2.3 - fix(exports)
 | 
					## 2025-03-04 - 2.2.3 - fix(exports)
 | 
				
			||||||
Fixed duplicate file compilation in compileGlobStringObject
 | 
					Fixed duplicate file compilation in compileGlobStringObject
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "@git.zone/tsbuild",
 | 
					  "name": "@git.zone/tsbuild",
 | 
				
			||||||
  "version": "2.2.3",
 | 
					  "version": "2.3.1",
 | 
				
			||||||
  "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",
 | 
				
			||||||
@@ -32,9 +32,9 @@
 | 
				
			|||||||
  "author": "Lossless GmbH",
 | 
					  "author": "Lossless GmbH",
 | 
				
			||||||
  "license": "MIT",
 | 
					  "license": "MIT",
 | 
				
			||||||
  "bugs": {
 | 
					  "bugs": {
 | 
				
			||||||
    "url": "https://gitlab.com/pushrocks/tsn/issues"
 | 
					    "url": "https://code.foss.global/git.zone/tsbuild/issues"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "homepage": "https://gitlab.com/pushrocks/tsn#README",
 | 
					  "homepage": "https://code.foss.global/git.zone/tsbuild#README",
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "@git.zone/tspublish": "^1.9.1",
 | 
					    "@git.zone/tspublish": "^1.9.1",
 | 
				
			||||||
    "@push.rocks/early": "^4.0.4",
 | 
					    "@push.rocks/early": "^4.0.4",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										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.3',
 | 
					  version: '2.3.1',
 | 
				
			||||||
  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
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user