UNPKG

typia

Version:

Superfast runtime validators with only one line

127 lines (119 loc) 4.22 kB
import ts from "typescript"; import { ExpressionFactory } from "../../factories/ExpressionFactory"; import { StatementFactory } from "../../factories/StatementFactory"; import { IProject } from "../../transformers/IProject"; import { StringUtil } from "../../utils/StringUtil"; import { ValidateProgrammer } from "../ValidateProgrammer"; import { FunctionalValidateFunctionProgrammer } from "./FunctionalValidateFunctionProgrammer"; import { FunctionalGeneralProgrammer } from "./internal/FunctionalGeneralProgrammer"; export namespace FunctionalValidateReturnProgrammer { export const write = (project: IProject) => (modulo: ts.LeftHandSideExpression) => (equals: boolean) => ( expression: ts.Expression, declaration: ts.FunctionDeclaration, ): ts.CallExpression => { const result = decompose(project)(modulo)(equals)( expression, declaration, ); return ExpressionFactory.selfCall( ts.factory.createBlock( [ ...result.functions, ts.factory.createReturnStatement( ts.factory.createArrowFunction( result.async ? [ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword)] : undefined, undefined, declaration.parameters, FunctionalValidateFunctionProgrammer.getReturnTypeNode( declaration, result.async, ), undefined, ts.factory.createBlock(result.statements, true), ), ), ], true, ), ); }; export const decompose = (project: IProject) => (modulo: ts.LeftHandSideExpression) => (equals: boolean) => ( expression: ts.Expression, declaration: ts.FunctionDeclaration, ): { async: boolean; functions: ts.Statement[]; statements: ts.Statement[]; } => { const { type, async } = FunctionalGeneralProgrammer.getReturnType( project.checker, )(declaration); const caller: ts.CallExpression = ts.factory.createCallExpression( expression, undefined, declaration.parameters.map((p) => ts.factory.createIdentifier(p.name.getText()), ), ); const name: string = StringUtil.escapeDuplicate( declaration.parameters.map((p) => p.name.getText()), )("result"); return { async, functions: [ StatementFactory.constant( "__validate_return", ValidateProgrammer.write(project)(modulo)(equals)(type), ), ], statements: [ StatementFactory.constant( name, ts.factory.createCallExpression( ts.factory.createIdentifier("__validate_return"), undefined, [async ? ts.factory.createAwaitExpression(caller) : caller], ), ), ts.factory.createIfStatement( ts.factory.createStrictEquality( ts.factory.createFalse(), ts.factory.createPropertyAccessExpression( ts.factory.createIdentifier(name), ts.factory.createIdentifier("success"), ), ), ts.factory.createExpressionStatement( ts.factory.createBinaryExpression( ts.factory.createPropertyAccessExpression( ts.factory.createIdentifier(name), ts.factory.createIdentifier("errors"), ), ts.factory.createToken(ts.SyntaxKind.EqualsToken), FunctionalValidateFunctionProgrammer.hookErrors({ expression: ts.factory.createPropertyAccessExpression( ts.factory.createIdentifier(name), ts.factory.createIdentifier("errors"), ), replacer: ts.factory.createStringLiteral("$input.return"), }), ), ), ), ts.factory.createReturnStatement( ts.factory.createIdentifier("result"), ), ], }; }; }