Compare commits
	
		
			10 Commits
		
	
	
		
			v2.2.3
			...
			9f42670865
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9f42670865 | |||
| 6cc9f41bd2 | |||
| 5d32ac85e0 | |||
| 4f2ac6922a | |||
| 31834e0b3e | |||
| c6c94866bb | |||
| 09a648b435 | |||
| 065e0baaf7 | |||
| 89d32617ce | |||
| 094702b917 | 
							
								
								
									
										30
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								changelog.md
									
									
									
									
									
								
							@@ -1,5 +1,35 @@
 | 
			
		||||
# Changelog
 | 
			
		||||
 | 
			
		||||
## 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)
 | 
			
		||||
Fixed duplicate file compilation in compileGlobStringObject
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "@git.zone/tsbuild",
 | 
			
		||||
  "version": "2.2.3",
 | 
			
		||||
  "version": "2.3.0",
 | 
			
		||||
  "private": false,
 | 
			
		||||
  "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",
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
  },
 | 
			
		||||
  "repository": {
 | 
			
		||||
    "type": "git",
 | 
			
		||||
    "url": "git+ssh://git@gitlab.com/pushrocks/tsn.git"
 | 
			
		||||
    "url": "https://code.foss.global/git.zone/tsbuild.git"
 | 
			
		||||
  },
 | 
			
		||||
  "keywords": [
 | 
			
		||||
    "TypeScript",
 | 
			
		||||
@@ -32,9 +32,9 @@
 | 
			
		||||
  "author": "Lossless GmbH",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "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": {
 | 
			
		||||
    "@git.zone/tspublish": "^1.9.1",
 | 
			
		||||
    "@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' ]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 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
 | 
			
		||||
 | 
			
		||||
Additional flags can be passed to any command to modify the compilation behavior:
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,6 @@
 | 
			
		||||
 */
 | 
			
		||||
export const commitinfo = {
 | 
			
		||||
  name: '@git.zone/tsbuild',
 | 
			
		||||
  version: '2.2.3',
 | 
			
		||||
  version: '2.3.0',
 | 
			
		||||
  description: 'A tool for compiling TypeScript files using the latest nightly features, offering flexible APIs and a CLI for streamlined development.'
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -93,17 +93,15 @@ export const compiler = async (
 | 
			
		||||
  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)
 | 
			
		||||
  });*/
 | 
			
		||||
  // Check for pre-emit diagnostics first
 | 
			
		||||
  const preEmitDiagnostics = plugins.typescript.getPreEmitDiagnostics(program);
 | 
			
		||||
  let hasErrors = false;
 | 
			
		||||
  
 | 
			
		||||
  const allDiagnostics = plugins.typescript
 | 
			
		||||
    .getPreEmitDiagnostics(program)
 | 
			
		||||
    .concat(emitResult.diagnostics);
 | 
			
		||||
  allDiagnostics.forEach((diagnostic) => {
 | 
			
		||||
  // Log pre-emit diagnostics if any
 | 
			
		||||
  if (preEmitDiagnostics.length > 0) {
 | 
			
		||||
    preEmitDiagnostics.forEach((diagnostic) => {
 | 
			
		||||
      hasErrors = true;
 | 
			
		||||
      if (diagnostic.file) {
 | 
			
		||||
        const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!);
 | 
			
		||||
        const message = plugins.typescript.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
 | 
			
		||||
@@ -114,6 +112,31 @@ export const compiler = async (
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Only continue to emit phase if no pre-emit errors
 | 
			
		||||
  if (hasErrors) {
 | 
			
		||||
    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();
 | 
			
		||||
  
 | 
			
		||||
  // Check for emit diagnostics
 | 
			
		||||
  if (emitResult.diagnostics.length > 0) {
 | 
			
		||||
    emitResult.diagnostics.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) {
 | 
			
		||||
@@ -126,3 +149,67 @@ export const compiler = async (
 | 
			
		||||
 | 
			
		||||
  return done.promise;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Function to check if a TypeScript file can be emitted without actually emitting it
 | 
			
		||||
 */
 | 
			
		||||
export const emitCheck = async (
 | 
			
		||||
  fileNames: string[],
 | 
			
		||||
  options: plugins.typescript.CompilerOptions = {},
 | 
			
		||||
  argvArg?: any
 | 
			
		||||
): Promise<boolean> => {
 | 
			
		||||
  console.log(`Checking if ${fileNames.length} files can be emitted...`);
 | 
			
		||||
  
 | 
			
		||||
  // Create a program
 | 
			
		||||
  const program = plugins.typescript.createProgram(fileNames, {
 | 
			
		||||
    ...options,
 | 
			
		||||
    noEmit: true
 | 
			
		||||
  });
 | 
			
		||||
  
 | 
			
		||||
  // Check for pre-emit diagnostics
 | 
			
		||||
  const preEmitDiagnostics = plugins.typescript.getPreEmitDiagnostics(program);
 | 
			
		||||
  let hasErrors = false;
 | 
			
		||||
  
 | 
			
		||||
  // Log pre-emit diagnostics if any
 | 
			
		||||
  if (preEmitDiagnostics.length > 0) {
 | 
			
		||||
    preEmitDiagnostics.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')}`
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Run the emit phase but with noEmit: true to check for emit errors without producing files
 | 
			
		||||
  const emitResult = program.emit(undefined, undefined, undefined, true);
 | 
			
		||||
  
 | 
			
		||||
  // Check for emit diagnostics
 | 
			
		||||
  if (emitResult.diagnostics.length > 0) {
 | 
			
		||||
    emitResult.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')}`
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  if (!hasErrors && !emitResult.emitSkipped) {
 | 
			
		||||
    console.log('TypeScript emit check passed! File can be emitted successfully.');
 | 
			
		||||
    return true;
 | 
			
		||||
  } else {
 | 
			
		||||
    console.error('TypeScript emit check failed. Please fix the issues above.');
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,87 @@ export const runCli = async () => {
 | 
			
		||||
    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
 | 
			
		||||
   */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import * as plugins from './plugins.js';
 | 
			
		||||
import type { CompilerOptions, ScriptTarget, ModuleKind } from 'typescript';
 | 
			
		||||
import { compiler, mergeCompilerOptions } from './tsbuild.classes.compiler.js';
 | 
			
		||||
import { compiler, mergeCompilerOptions, emitCheck } from './tsbuild.classes.compiler.js';
 | 
			
		||||
 | 
			
		||||
export type { CompilerOptions, ScriptTarget, ModuleKind };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user