UNPKG

@autobe/agent

Version:

AI backend server code generator

188 lines (175 loc) 6.87 kB
import { AutoBeDatabase, AutoBeOpenApi, AutoBeProgressEventBase, AutoBeRealizeTransformerFunction, } from "@autobe/interface"; import { AutoBeOpenApiTypeChecker } from "@autobe/utils"; import typia, { ILlmApplication, IValidation } from "typia"; import { AutoBeContext } from "../../context/AutoBeContext"; import { AutoBePreliminaryController } from "../common/AutoBePreliminaryController"; import { orchestrateRealizeCorrectOverall } from "./correct/orchestrateRealizeCorrectOverall"; import { transformRealizeTransformerCorrectHistory } from "./histories/transformRealizeTransformerCorrectHistory"; import { AutoBeRealizeTransformerProgrammer } from "./programmers/AutoBeRealizeTransformerProgrammer"; import { IAutoBeRealizeFunctionResult } from "./structures/IAutoBeRealizeFunctionResult"; import { IAutoBeRealizeTransformerCorrectApplication } from "./structures/IAutoBeRealizeTransformerCorrectApplication"; export const orchestrateRealizeTransformerCorrectOverall = async ( ctx: AutoBeContext, props: { functions: AutoBeRealizeTransformerFunction[]; progress: AutoBeProgressEventBase; }, ): Promise< IAutoBeRealizeFunctionResult<AutoBeRealizeTransformerFunction>[] > => { const prismaApplication: AutoBeDatabase.IApplication = ctx.state().database!.result.data; const document: AutoBeOpenApi.IDocument = ctx.state().interface!.document; const getNeighbors = ( func: AutoBeRealizeTransformerFunction, ): AutoBeRealizeTransformerFunction[] => { const visited: Set<string> = new Set(); AutoBeOpenApiTypeChecker.visit({ components: document.components, schema: { $ref: `#/components/schemas/${func.plan.dtoTypeName}` }, closure: (next) => { if (AutoBeOpenApiTypeChecker.isReference(next)) { const key: string = next.$ref.split("/").pop()!; visited.add(key); } }, }); return props.functions.filter( (y) => y.plan.dtoTypeName !== func.plan.dtoTypeName && visited.has(y.plan.dtoTypeName), ); }; return await orchestrateRealizeCorrectOverall(ctx, { programmer: { location: "src/transformers", // Recalculate template for corrected transformer function template: (func) => { const model: AutoBeDatabase.IModel = prismaApplication.files .map((f) => f.models) .flat() .find((m) => m.name === func.plan.databaseSchemaName)!; return AutoBeRealizeTransformerProgrammer.writeTemplate({ plan: func.plan, schema: document.components.schemas[ func.plan.dtoTypeName ] as AutoBeOpenApi.IJsonSchemaDescriptive.IObject, schemas: document.components.schemas, neighbors: getNeighbors(func).map((n) => n.plan), relations: AutoBeRealizeTransformerProgrammer.getRelationMappingTable( { application: prismaApplication, model, }, ), model, }); }, // Replace import statements using Transformer-specific programmer replaceImportStatements: async (next) => { return await AutoBeRealizeTransformerProgrammer.replaceImportStatements( ctx, { dtoTypeName: next.function.plan.dtoTypeName, schemas: document.components.schemas, code: next.code, }, ); }, // No additional files needed for transformers (unlike operations) additional: (_functions) => ({}), // Create preliminary controller with only databaseSchemas support preliminary: (next) => new AutoBePreliminaryController<"databaseSchemas">({ source: next.source, application: typia.json.application<IAutoBeRealizeTransformerCorrectApplication>(), kinds: ["databaseSchemas"], dispatch: (e) => ctx.dispatch(e), state: ctx.state(), local: { databaseSchemas: ctx .state() .database!.result.data.files.map((f) => f.models) .flat() .filter((m) => m.name === next.function.plan.databaseSchemaName), }, }), // Transform history using Transformer-specific transformer histories: (next) => transformRealizeTransformerCorrectHistory(ctx, { function: next.function, neighbors: getNeighbors(next.function), failures: next.failures, preliminary: next.preliminary, }), // Create controller with Transformer-specific validation controller: (next) => { const validate: Validator = (input) => { const result: IValidation<IAutoBeRealizeTransformerCorrectApplication.IProps> = typia.validate<IAutoBeRealizeTransformerCorrectApplication.IProps>( input, ); if (result.success === false) return result; else if (result.data.request.type !== "write") return next.preliminary.validate({ thinking: result.data.thinking, request: result.data.request, }); // Validate transformer-specific constraints const errors: IValidation.IError[] = AutoBeRealizeTransformerProgrammer.validate({ application: prismaApplication, document, plan: next.function.plan, neighbors: props.functions.map((f) => f.plan), transformMappings: result.data.request.transformMappings, selectMappings: result.data.request.selectMappings, draft: result.data.request.draft, revise: result.data.request.revise, }); return errors.length ? { success: false, errors, data: result.data, } : result; }; const application: ILlmApplication = next.preliminary.fixApplication( typia.llm.application<IAutoBeRealizeTransformerCorrectApplication>({ validate: { process: validate, }, }), ); AutoBeRealizeTransformerProgrammer.fixApplication({ definition: application, application: prismaApplication, document, plan: next.function.plan, }); return { protocol: "class", name: next.source, application, execute: { process: (v) => { if (v.request.type === "write") next.build(v.request); }, } satisfies IAutoBeRealizeTransformerCorrectApplication, }; }, }, functions: props.functions, progress: props.progress, }); }; type Validator = ( input: unknown, ) => IValidation<IAutoBeRealizeTransformerCorrectApplication.IProps>;