Files
tsbuild/ts/mod_config/classes.tsconfig.ts

181 lines
5.3 KiB
TypeScript

import * as fs from 'fs';
import * as path from 'path';
import type { CompilerOptions } from 'typescript';
import typescript from 'typescript';
/**
* Default compiler options for TypeScript compilation
*/
export const compilerOptionsDefault: CompilerOptions = {
declaration: true,
inlineSourceMap: true,
noEmitOnError: true,
outDir: 'dist_ts/',
module: typescript.ModuleKind.NodeNext,
target: typescript.ScriptTarget.ESNext,
moduleResolution: typescript.ModuleResolutionKind.NodeNext,
lib: ['lib.dom.d.ts', 'lib.esnext.d.ts'],
noImplicitAny: false,
esModuleInterop: true,
verbatimModuleSyntax: true,
baseUrl: './',
};
/**
* TsConfig handles loading and merging TypeScript compiler configurations.
* It supports reading tsconfig.json and merging with defaults and custom options.
*/
export class TsConfig {
private cwd: string;
private cachedTsConfig: CompilerOptions | null = null;
constructor(cwd: string = process.cwd()) {
this.cwd = cwd;
}
/**
* Get the current working directory
*/
public getCwd(): string {
return this.cwd;
}
/**
* Load and parse tsconfig.json from the current directory
*/
public load(): CompilerOptions {
if (this.cachedTsConfig !== null) {
return this.cachedTsConfig;
}
let tsconfig: any;
try {
const tsconfigPath = path.join(this.cwd, 'tsconfig.json');
const tsconfigContent = fs.readFileSync(tsconfigPath, 'utf8');
tsconfig = JSON.parse(tsconfigContent);
} catch {
this.cachedTsConfig = {};
return {};
}
if (!tsconfig || !tsconfig.compilerOptions) {
this.cachedTsConfig = {};
return {};
}
const returnObject: CompilerOptions = { ...tsconfig.compilerOptions };
// Convert target string to enum
if (tsconfig.compilerOptions.target && typeof tsconfig.compilerOptions.target === 'string') {
const targetKey = tsconfig.compilerOptions.target.toUpperCase();
if (targetKey in typescript.ScriptTarget) {
returnObject.target = typescript.ScriptTarget[targetKey as keyof typeof typescript.ScriptTarget];
}
}
// Convert module string to enum
if (tsconfig.compilerOptions.module && typeof tsconfig.compilerOptions.module === 'string') {
const moduleKey = tsconfig.compilerOptions.module.toUpperCase();
if (moduleKey in typescript.ModuleKind) {
returnObject.module = typescript.ModuleKind[moduleKey as keyof typeof typescript.ModuleKind];
} else if (moduleKey === 'NODENEXT') {
returnObject.module = typescript.ModuleKind.NodeNext;
}
}
// Convert moduleResolution string to enum
if (tsconfig.compilerOptions.moduleResolution && typeof tsconfig.compilerOptions.moduleResolution === 'string') {
const moduleResolutionKey = tsconfig.compilerOptions.moduleResolution.toUpperCase();
if (moduleResolutionKey in typescript.ModuleResolutionKind) {
returnObject.moduleResolution = typescript.ModuleResolutionKind[
moduleResolutionKey as keyof typeof typescript.ModuleResolutionKind
];
} else if (moduleResolutionKey === 'NODENEXT') {
returnObject.moduleResolution = typescript.ModuleResolutionKind.NodeNext;
}
}
// Apply path transformations (ts_ → dist_ts_)
if (tsconfig.compilerOptions.paths) {
returnObject.paths = { ...tsconfig.compilerOptions.paths };
for (const pathKey of Object.keys(returnObject.paths)) {
if (Array.isArray(returnObject.paths[pathKey]) && returnObject.paths[pathKey].length > 0) {
returnObject.paths[pathKey][0] = returnObject.paths[pathKey][0].replace('./ts_', './dist_ts_');
}
}
}
this.cachedTsConfig = returnObject;
return returnObject;
}
/**
* Get default compiler options
*/
public getDefaultOptions(): CompilerOptions {
return { ...compilerOptionsDefault };
}
/**
* Get critical/protected default options that shouldn't be overridden by tsconfig.json
*/
public getProtectedDefaults(): CompilerOptions {
return {
outDir: 'dist_ts/',
noEmitOnError: true,
declaration: true,
inlineSourceMap: true,
};
}
/**
* Process command line arguments and return applicable compiler options
*/
public getCommandLineOptions(argvArg?: any): CompilerOptions {
if (!argvArg) return {};
const options: CompilerOptions = {};
if (argvArg.skiplibcheck) {
options.skipLibCheck = true;
}
if (argvArg.disallowimplicitany) {
options.noImplicitAny = true;
}
if (argvArg.commonjs) {
options.module = typescript.ModuleKind.CommonJS;
options.moduleResolution = typescript.ModuleResolutionKind.NodeJs;
}
return options;
}
/**
* Merge compiler options with proper priority order:
* 1. Default options
* 2. tsconfig.json options
* 3. Protected defaults (cannot be overridden by tsconfig)
* 4. Custom options (programmatic)
* 5. CLI options (highest priority)
*/
public merge(customOptions: CompilerOptions = {}, argvArg?: any): CompilerOptions {
return {
...this.getDefaultOptions(),
...this.load(),
...this.getProtectedDefaults(),
...customOptions,
...this.getCommandLineOptions(argvArg),
};
}
/**
* Clear the cached tsconfig (useful for reloading)
*/
public clearCache(): void {
this.cachedTsConfig = null;
}
}