kist
Version:
Lightweight Package Pipeline Processor with Plugin Architecture
147 lines (127 loc) • 5.1 kB
text/typescript
// ============================================================================
// Imports
// ============================================================================
import path from "path";
import ts from "typescript";
import { Action } from "../../core/pipeline/Action.js";
import { ActionOptionsType } from "../../types/ActionOptionsType.js";
// ============================================================================
// Classes
// ============================================================================
/**
* TypeScriptCompilerAction compiles TypeScript files into JavaScript.
*/
export class TypeScriptCompilerAction extends Action {
/**
* Executes the TypeScript compilation process.
*
* @param options - The options specifying the tsconfig path and additional compiler options.
* @returns A Promise that resolves when compilation is completed successfully.
* @throws {Error} Throws an error if compilation fails.
*/
async execute(options: ActionOptionsType): Promise<void> {
// const { tsconfigPath = "tsconfig.json" } = options;
const {
tsconfigPath = "tsconfig.json",
filePaths,
outputDir,
compilerOptions = {},
} = options;
const resolvedTsconfigPath = path.resolve(tsconfigPath);
this.logInfo(
`Compiling TypeScript using configuration: ${resolvedTsconfigPath}`,
);
try {
// **Properly Parse tsconfig.json**
const parsedConfig = this.loadAndParseTsConfig(
resolvedTsconfigPath,
);
// Merge custom compiler options
const mergedCompilerOptions = ts.convertCompilerOptionsFromJson(
compilerOptions,
path.dirname(resolvedTsconfigPath),
).options;
const finalCompilerOptions = {
...parsedConfig.options,
...mergedCompilerOptions,
};
// Set output directory if specified
if (outputDir) {
mergedCompilerOptions.outDir = outputDir;
}
// **Create a TypeScript Program**
const program = ts.createProgram(
filePaths ?? parsedConfig.fileNames,
finalCompilerOptions,
);
// **Create a TypeScript Program**
// const program = ts.createProgram(
// parsedConfig.fileNames,
// parsedConfig.options,
// );
const emitResult = program.emit();
// **Collect Diagnostics**
const allDiagnostics = ts
.getPreEmitDiagnostics(program)
.concat(emitResult.diagnostics);
if (allDiagnostics.length > 0) {
allDiagnostics.forEach((diagnostic) => {
const message = ts.flattenDiagnosticMessageText(
diagnostic.messageText,
"\n",
);
this.logError(`TypeScript Error: ${message}`);
});
throw new Error(
"TypeScript compilation failed due to errors.",
);
}
this.logInfo("TypeScript compilation completed successfully.");
} catch (error: any) {
this.logError("Error during TypeScript compilation:", error);
throw new Error(`TypeScript compilation failed: ${error.message}`);
}
}
/**
* Loads and parses `tsconfig.json` properly before passing it to the compiler.
*
* @param tsconfigPath - The path to the tsconfig.json file.
* @returns Parsed TypeScript compiler options and source files.
*/
private loadAndParseTsConfig(tsconfigPath: string): ts.ParsedCommandLine {
// **Read and Parse tsconfig.json**
const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
if (configFile.error) {
throw new Error(
`Error reading tsconfig.json: ${ts.flattenDiagnosticMessageText(configFile.error.messageText, "\n")}`,
);
}
// **Parse the configuration content**
const parsedConfig = ts.parseJsonConfigFileContent(
configFile.config,
ts.sys,
path.dirname(tsconfigPath),
);
if (parsedConfig.errors.length > 0) {
throw new Error(
`Error parsing tsconfig.json: ${parsedConfig.errors
.map((diag) =>
ts.flattenDiagnosticMessageText(
diag.messageText,
"\n",
),
)
.join("\n")}`,
);
}
return parsedConfig;
}
/**
* Provides a description of the action.
*
* @returns A string description of the action.
*/
describe(): string {
return "Compiles TypeScript files using a given tsconfig.json configuration.";
}
}