feat(tsbuild): Add tsconfig.json support and safer compiler option merging; protect critical options; apply path and enum transforms; bump dependencies.
This commit is contained in:
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@git.zone/tsbuild',
|
||||
version: '2.6.8',
|
||||
version: '2.7.0',
|
||||
description: 'A tool for compiling TypeScript files using the latest nightly features, offering flexible APIs and a CLI for streamlined development.'
|
||||
}
|
||||
|
||||
@@ -62,19 +62,56 @@ export class TsBuild {
|
||||
* Helper function to read and process tsconfig.json
|
||||
*/
|
||||
private getTsConfigOptions(): CompilerOptions {
|
||||
const tsconfig = plugins.smartfile.fs.toObjectSync(plugins.path.join(paths.cwd, 'tsconfig.json'));
|
||||
const returnObject: CompilerOptions = {};
|
||||
|
||||
let tsconfig: any;
|
||||
|
||||
// Try to read tsconfig.json, but don't fail if it doesn't exist
|
||||
try {
|
||||
tsconfig = plugins.smartfile.fs.toObjectSync(plugins.path.join(paths.cwd, 'tsconfig.json'));
|
||||
} catch (error) {
|
||||
// tsconfig.json doesn't exist or is invalid - use defaults
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!tsconfig || !tsconfig.compilerOptions) {
|
||||
return returnObject;
|
||||
return {};
|
||||
}
|
||||
|
||||
// Process baseUrl
|
||||
if (tsconfig.compilerOptions.baseUrl) {
|
||||
returnObject.baseUrl = tsconfig.compilerOptions.baseUrl;
|
||||
|
||||
// Start by copying ALL compiler options from tsconfig.json
|
||||
const returnObject: CompilerOptions = { ...tsconfig.compilerOptions };
|
||||
|
||||
// Apply special transformations for string-to-enum conversions
|
||||
|
||||
// Process target (convert string to enum)
|
||||
if (tsconfig.compilerOptions.target && typeof tsconfig.compilerOptions.target === 'string') {
|
||||
const targetKey = tsconfig.compilerOptions.target.toUpperCase();
|
||||
if (targetKey in plugins.typescript.ScriptTarget) {
|
||||
returnObject.target = plugins.typescript.ScriptTarget[targetKey as keyof typeof plugins.typescript.ScriptTarget];
|
||||
}
|
||||
}
|
||||
|
||||
// Process paths
|
||||
|
||||
// Process module (convert string to enum)
|
||||
if (tsconfig.compilerOptions.module && typeof tsconfig.compilerOptions.module === 'string') {
|
||||
const moduleKey = tsconfig.compilerOptions.module.toUpperCase();
|
||||
if (moduleKey in plugins.typescript.ModuleKind) {
|
||||
returnObject.module = plugins.typescript.ModuleKind[moduleKey as keyof typeof plugins.typescript.ModuleKind];
|
||||
} else if (moduleKey === 'NODENEXT') {
|
||||
returnObject.module = plugins.typescript.ModuleKind.NodeNext;
|
||||
}
|
||||
}
|
||||
|
||||
// Process moduleResolution (convert string to enum)
|
||||
if (tsconfig.compilerOptions.moduleResolution && typeof tsconfig.compilerOptions.moduleResolution === 'string') {
|
||||
const moduleResolutionKey = tsconfig.compilerOptions.moduleResolution.toUpperCase();
|
||||
if (moduleResolutionKey in plugins.typescript.ModuleResolutionKind) {
|
||||
returnObject.moduleResolution = plugins.typescript.ModuleResolutionKind[
|
||||
moduleResolutionKey as keyof typeof plugins.typescript.ModuleResolutionKind
|
||||
];
|
||||
} else if (moduleResolutionKey === 'NODENEXT') {
|
||||
returnObject.moduleResolution = plugins.typescript.ModuleResolutionKind.NodeNext;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply path transformations (ts_ → dist_ts_)
|
||||
if (tsconfig.compilerOptions.paths) {
|
||||
returnObject.paths = { ...tsconfig.compilerOptions.paths };
|
||||
for (const path of Object.keys(returnObject.paths)) {
|
||||
@@ -83,58 +120,24 @@ export class TsBuild {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process target
|
||||
if (tsconfig.compilerOptions.target) {
|
||||
if (typeof tsconfig.compilerOptions.target === 'string') {
|
||||
const targetKey = tsconfig.compilerOptions.target.toUpperCase();
|
||||
if (targetKey in plugins.typescript.ScriptTarget) {
|
||||
returnObject.target = plugins.typescript.ScriptTarget[targetKey as keyof typeof plugins.typescript.ScriptTarget];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process module
|
||||
if (tsconfig.compilerOptions.module) {
|
||||
if (typeof tsconfig.compilerOptions.module === 'string') {
|
||||
const moduleKey = tsconfig.compilerOptions.module.toUpperCase();
|
||||
if (moduleKey in plugins.typescript.ModuleKind) {
|
||||
returnObject.module = plugins.typescript.ModuleKind[moduleKey as keyof typeof plugins.typescript.ModuleKind];
|
||||
} else if (moduleKey === 'NODENEXT') {
|
||||
returnObject.module = plugins.typescript.ModuleKind.NodeNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process moduleResolution
|
||||
if (tsconfig.compilerOptions.moduleResolution) {
|
||||
if (typeof tsconfig.compilerOptions.moduleResolution === 'string') {
|
||||
const moduleResolutionKey = tsconfig.compilerOptions.moduleResolution.toUpperCase();
|
||||
if (moduleResolutionKey in plugins.typescript.ModuleResolutionKind) {
|
||||
returnObject.moduleResolution = plugins.typescript.ModuleResolutionKind[
|
||||
moduleResolutionKey as keyof typeof plugins.typescript.ModuleResolutionKind
|
||||
];
|
||||
} else if (moduleResolutionKey === 'NODENEXT') {
|
||||
returnObject.moduleResolution = plugins.typescript.ModuleResolutionKind.NodeNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy boolean options directly
|
||||
const booleanOptions = [
|
||||
'experimentalDecorators', 'useDefineForClassFields',
|
||||
'esModuleInterop', 'verbatimModuleSyntax'
|
||||
];
|
||||
|
||||
for (const option of booleanOptions) {
|
||||
if (option in tsconfig.compilerOptions) {
|
||||
(returnObject as any)[option] = (tsconfig.compilerOptions as any)[option];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return returnObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns critical default options that should not be overridden by tsconfig.json
|
||||
* These options are essential for tsbuild's functionality and build integrity
|
||||
*/
|
||||
private getCriticalDefaults(): CompilerOptions {
|
||||
return {
|
||||
outDir: 'dist_ts/', // Required for path transformation logic
|
||||
noEmitOnError: true, // Build integrity - prevent broken builds
|
||||
declaration: true, // Library consumers depend on .d.ts files
|
||||
emitDecoratorMetadata: true, // Required for dependency injection frameworks
|
||||
inlineSourceMap: true, // Consistent debugging experience
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Process command line arguments and return applicable compiler options
|
||||
*/
|
||||
@@ -162,6 +165,13 @@ export class TsBuild {
|
||||
|
||||
/**
|
||||
* Merges compilerOptions with the default compiler options
|
||||
*
|
||||
* Merge order (later overwrites earlier):
|
||||
* 1. compilerOptionsDefault - Base defaults for all options
|
||||
* 2. getTsConfigOptions() - User's tsconfig.json (all options)
|
||||
* 3. getCriticalDefaults() - Protected options that shouldn't be overridden by tsconfig.json
|
||||
* 4. customTsOptions - Programmatic options (can override critical defaults)
|
||||
* 5. getCommandLineOptions() - CLI flags (highest priority)
|
||||
*/
|
||||
public mergeCompilerOptions(
|
||||
customTsOptions: CompilerOptions = {},
|
||||
@@ -169,10 +179,11 @@ export class TsBuild {
|
||||
): CompilerOptions {
|
||||
// create merged options
|
||||
const mergedOptions: CompilerOptions = {
|
||||
...compilerOptionsDefault,
|
||||
...customTsOptions,
|
||||
...this.getCommandLineOptions(argvArg),
|
||||
...this.getTsConfigOptions(),
|
||||
...compilerOptionsDefault, // 1. All defaults
|
||||
...this.getTsConfigOptions(), // 2. User's tsconfig.json (all options)
|
||||
...this.getCriticalDefaults(), // 3. Protected overrides
|
||||
...customTsOptions, // 4. Programmatic options
|
||||
...this.getCommandLineOptions(argvArg), // 5. CLI flags (highest priority)
|
||||
};
|
||||
|
||||
return mergedOptions;
|
||||
|
||||
Reference in New Issue
Block a user