UNPKG

@autobe/compiler

Version:

AI backend server code generator

177 lines (170 loc) 6.22 kB
import { AutoBeOpenApi, AutoBeRealizeAuthorization, AutoBeRealizeFunction, IAutoBeRealizeControllerProps, } from "@autobe/interface"; import { transformOpenApiDocument } from "@autobe/utils"; import { NestiaMigrateApplication } from "@nestia/migrate"; import { NestiaMigrateNestMethodProgrammer } from "@nestia/migrate/lib/programmers/NestiaMigrateNestMethodProgrammer"; import path from "path"; import ts from "typescript"; import { ArrayUtil } from "../utils/ArrayUtil"; import { FilePrinter } from "../utils/FilePrinter"; export const writeRealizeControllers = async ( props: IAutoBeRealizeControllerProps, ): Promise<Record<string, string>> => { const app: NestiaMigrateApplication = new NestiaMigrateApplication( transformOpenApiDocument(props.document), ); const result: Record<string, string> = app.nest({ simulate: false, e2e: false, programmer: { controllerMethod: (ctx) => { const method = NestiaMigrateNestMethodProgrammer.write(ctx); const operate: AutoBeOpenApi.IOperation | undefined = props.document.operations.find( (o) => o.method === ctx.route.method && o.path === ctx.route.path, ); const func: AutoBeRealizeFunction | undefined = props.functions.find( (f) => f.endpoint.method === ctx.route.method && f.endpoint.path === ctx.route.path, ); if (func === undefined || operate === undefined) return method; // unreachable const auth: AutoBeRealizeAuthorization | undefined = operate.authorizationRole ? props.authorizations.find( (d) => d.role.name === operate.authorizationRole, ) : undefined; if (operate.authorizationRole && auth === undefined) return method; // unreachable ctx.importer.external({ type: "instance", library: path .relative(ctx.controller.location, func.location) .replaceAll(path.sep, "/") .split(".ts")[0], name: func.name, }); const inputArguments: string[] = [ ...(operate.authorizationRole ? [operate.authorizationRole] : []), ...ctx.route.parameters.map((p) => p.name), ...(ctx.route.query ? [ctx.route.query.name] : []), ...(ctx.route.body ? [ctx.route.body.name] : []), ]; const call: ts.Expression = ts.factory.createCallExpression( ts.factory.createIdentifier(func.name), undefined, inputArguments.length === 0 ? undefined : [ ts.factory.createObjectLiteralExpression( inputArguments.map((name) => ts.factory.createShorthandPropertyAssignment(name), ), true, ), ], ); const tryCatch = ts.factory.createTryStatement( ts.factory.createBlock( [ ts.factory.createReturnStatement( ts.factory.createAwaitExpression(call), ), ], true, ), ts.factory.createCatchClause( ts.factory.createVariableDeclaration( ts.factory.createIdentifier("error"), undefined, undefined, undefined, ), ts.factory.createBlock( [ ts.factory.createExpressionStatement( ts.factory.createCallExpression( ts.factory.createIdentifier("console.log"), undefined, [ts.factory.createIdentifier("error")], ), ), ts.factory.createThrowStatement( ts.factory.createIdentifier("error"), ), ], true, ), ), undefined, ); return ts.factory.updateMethodDeclaration( method, method.modifiers, method.asteriskToken, method.name, method.questionToken, method.typeParameters, auth ? [ ts.factory.createParameterDeclaration( [ ts.factory.createDecorator( ts.factory.createCallExpression( ts.factory.createIdentifier( ctx.importer.external({ type: "instance", library: path .relative( ctx.controller.location, auth.decorator.location, ) .replaceAll(path.sep, "/") .split(".ts")[0], name: auth.decorator.name, }), ), undefined, [], ), ), ], undefined, auth.role.name, undefined, ts.factory.createTypeReferenceNode( ctx.importer.external({ type: "instance", library: path .relative( ctx.controller.location, auth.payload.location, ) .replaceAll(path.sep, "/") .split(".ts")[0], name: auth.payload.name, }), ), undefined, ), ...method.parameters, ] : method.parameters, method.type, ts.factory.createBlock([tryCatch]), ); }, }, }); const entries: [string, string][] = await ArrayUtil.asyncMap( Object.entries(result).filter(([key]) => key.startsWith("src/controllers/"), ), async ([key, value]) => [key, await FilePrinter.beautify(value)], ); return Object.fromEntries(entries); };