feat(cli): Add emitcheck command to validate TS file emission without generating output
This commit is contained in:
parent
5d32ac85e0
commit
6cc9f41bd2
@ -1,5 +1,12 @@
|
||||
# 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
|
||||
|
||||
|
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.7',
|
||||
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.'
|
||||
}
|
||||
|
@ -149,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 };
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user