import { IAutoBeTypeScriptCompileProps, IAutoBeTypeScriptCompileResult, IAutoBeTypeScriptCompiler, } from "@autobe/interface"; import nestiaCoreTransform from "@nestia/core/lib/transform"; import { EmbedEsLint } from "embed-eslint"; import { Pair } from "tstl"; // import { Pair } from "tstl"; import ts from "typescript"; import typiaTransform from "typia/lib/transform"; import NestJSExternal from "./raw/nestjs.json"; import { FilePrinter } from "./utils/FilePrinter"; import { shrinkCompileResult } from "./utils/shrinkCompileResult"; /** * Official TypeScript compiler for final code validation and quality assurance. * * This compiler provides the ultimate validation layer that ensures all * generated code meets production standards and integrates seamlessly with the * TypeScript ecosystem. While the AST-based approach eliminates most potential * errors before code generation, the AutoBeTypeScriptCompiler serves as the * final quality gate for perfect integration verification throughout the vibe * coding pipeline. * * The implementation validates framework integration with NestJS APIs, type * system integrity for complex relationships, dependency resolution across * modules, and build system compatibility with standard toolchains. It provides * comprehensive IDE support including intelligent autocomplete, real-time error * detection, sophisticated refactoring capabilities, and complete navigation * features. * * The compiler enables critical feedback loops necessary for AI self-correction * when implementation or test code contains compilation errors requiring * iterative refinement. This ensures that generated applications are * immediately deployable without manual debugging cycles while maintaining the * reliability of the automated development process. * * @author Samchon */ export class AutoBeTypeScriptCompiler implements IAutoBeTypeScriptCompiler { public async compile( props: IAutoBeTypeScriptCompileProps, ): Promise { const alias: string = props.package ?? "@ORGANIZATION/PROJECT-api"; const compiler: EmbedEsLint = new EmbedEsLint({ external: NestJSExternal as Record, compilerOptions: { target: ts.ScriptTarget.ESNext, module: ts.ModuleKind.CommonJS, downlevelIteration: true, baseUrl: "./", paths: { [alias]: ["./src/api"], [`${alias}/lib/*`]: ["./src/api/*"], ["@prisma/sdk"]: ["./src/prisma/client.ts"], }, strict: true, skipLibCheck: true, esModuleInterop: true, experimentalDecorators: true, emitDecoratorMetadata: true, noErrorTruncation: true, }, transformers: (program, diagnostics) => ({ before: [ typiaTransform( program, {}, { addDiagnostic: (input) => diagnostics.push(input), }, ), nestiaCoreTransform( program, {}, { addDiagnostic: (input) => diagnostics.push(input), }, ), ], }), rules: { "no-floating-promises": "error", }, }); return shrinkCompileResult( compiler.compile({ ...props.files, ...(props.prisma ?? {}), }), ); } public async getExternal(location: string): Promise { return (NestJSExternal as Record)[location] ?? undefined; } public beautify(script: string): Promise { return FilePrinter.beautify(script); } public async removeImportStatements(script: string): Promise { try { const sourceFile: ts.SourceFile = ts.createSourceFile( "module.ts", script, ts.ScriptTarget.ESNext, true, ); const statements: ts.Statement[] = sourceFile.statements.filter( (stmt) => stmt.kind !== ts.SyntaxKind.ImportDeclaration, ); const printer: ts.Printer = ts.createPrinter(); return statements .map((stmt) => printer.printNode(ts.EmitHint.Unspecified, stmt, sourceFile), ) .join("\n"); } catch { script = await this.beautify(script); const lines: string[] = script.replaceAll("\r\n", "\n").split("\n"); const indexes: Pair[] = lines .map((s, i) => s.startsWith("import ") ? new Pair(i, lines.slice(i).findIndex((s) => s.endsWith(";")) + i) : null, ) .filter((p) => p !== null); for (const index of indexes.reverse()) lines.splice(index.first, index.second - index.first + 1); return lines.join("\n"); } } }