From 691f5e79ce5de3e9307590b04c0d9043307c569d Mon Sep 17 00:00:00 2001 From: Hide_D Date: Sun, 6 Aug 2023 13:39:22 +0000 Subject: [PATCH] =?UTF-8?q?ArgType=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/api/defs.ts | 58 +++++++++++++++++++++++++++---------- server/apiStructure/defs.ts | 4 ++- server/index.ts | 1 + 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/server/api/defs.ts b/server/api/defs.ts index 24f2ef5..042f451 100644 --- a/server/api/defs.ts +++ b/server/api/defs.ts @@ -1,8 +1,14 @@ import type { Request, Response } from 'express'; import type { Callable, DefAPINamespace, DeleteAPICallT, GetAPICallT, HeadAPICallT, HttpMethod, InvalidResponse, PatchAPICallT, PostAPICallT, PutAPICallT, RawArgType, ValidResponse, recoveryMethod } from '../apiStructure/defs'; +import { + validate, + validateSync, + validateOrReject, + ValidatorOptions, + } from "class-validator"; +import { ClassTransformOptions, plainToInstance } from "class-transformer"; -export const treatedSpecial = Symbol('treatedSpecial'); export type APINamespace = { [key: string]: APINamespace | GET @@ -14,8 +20,11 @@ export type APINamespace = { ; } +type ValidatorType = T extends undefined ? undefined : ClassType; + export abstract class APIExecuter{ readonly abstract reqType: HttpMethod; + readonly abstract argValidator?: ValidatorType; protected abstract parseQuery(expressReq: Request): Promise; protected abstract api(query: Q, expressReq: Request, expressRes: Response): Promise; public async run(expressReq: Request, expressRes: Response): Promise { @@ -31,17 +40,37 @@ export abstract class APIExecuter extends APIExecuter{ protected async parseQuery(expressReq: Request): Promise { - throw new Error('Not implemented'); - return expressReq.body; + + if(!this.argValidator){ + return expressReq.body as Q; + } + + const query = expressReq.body; + const classObject = plainToInstance(this.argValidator, query); + const errors = await validate(classObject); + if (errors.length) { + throw errors; + } + + return classObject as Q; } } export abstract class GET extends APIExecuter{ override readonly reqType = 'get'; protected async parseQuery(expressReq: Request): Promise { - expressReq.query; - throw new Error('Not implemented'); - return expressReq.query as unknown as Q; + if(!this.argValidator){ + return expressReq.query as Q; + } + + const query = expressReq.query; + const classObject = plainToInstance(this.argValidator, query); + const errors = await validate(classObject); + if (errors.length) { + throw errors; + } + + return classObject as Q; } } @@ -79,16 +108,15 @@ export function raiseError(reason: string, recovery?: recoveryMethod): InvalidRe }; } -export type GetClassGenerator = { - prototype: T -}; +export type ClassType = new (...args: any[]) => T; + export type APIServerType = - T extends GetAPICallT ? GetClassGenerator> : - T extends PostAPICallT ? GetClassGenerator> : - T extends PutAPICallT ? GetClassGenerator> : - T extends DeleteAPICallT ? GetClassGenerator> : - T extends PatchAPICallT ? GetClassGenerator> : - T extends HeadAPICallT ? GetClassGenerator> : + T extends GetAPICallT ? ClassType> : + T extends PostAPICallT ? ClassType> : + T extends PutAPICallT ? ClassType> : + T extends DeleteAPICallT ? ClassType> : + T extends PatchAPICallT ? ClassType> : + T extends HeadAPICallT ? ClassType> : never; export type APINamespaceType = { [K in keyof T]: diff --git a/server/apiStructure/defs.ts b/server/apiStructure/defs.ts index d91f6b2..7257156 100644 --- a/server/apiStructure/defs.ts +++ b/server/apiStructure/defs.ts @@ -1,5 +1,7 @@ export type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head'; -export type RawArgType = Record | Record[] | undefined; +export type RawArgType = { + [key: string]: unknown; +} | undefined; export interface BasicAPICallT< diff --git a/server/index.ts b/server/index.ts index 31f7588..d5161a0 100644 --- a/server/index.ts +++ b/server/index.ts @@ -34,6 +34,7 @@ const ownConfig = { AppDataSource.initialize().then(async () => { // create express app const app = express() + app.use(express.json()); app.use(session({ secret: ownConfig.sessionSecret, resave: false,