nestia란 nest helper 라이브러리이다.
데코레이터는 @Decorator
와 같이 작성을 하며
보통 reflect-metadata
를 라이브러리를 사용하여 class를 리플렉션한다.
typia는 class-validator와 같은 런타임 타입 검증 라이브러리이다.
const createMappingDecorator: (method: RequestMethod) => (path?: string | string[]) => MethodDecorator
function Generator(method: "Get" | "Post" | "Put" | "Patch" | "Delete"): {
(path?: string | string[]): MethodDecorator;
<T>(stringify?: IResponseBodyStringifier<T> | undefined): MethodDecorator;
<T>(path: string | string[], stringify?: IResponseBodyStringifier<T> | undefined): MethodDecorator;
}
타입스크립트 내장 타입인 MethodDecorator
를 반환한다.
nestjs/common의 메소드 데코레이터를 인터셉터로 감싸고 applyDecorators로 감싼다.
applyDecorators는 파라미터로 받은 데코레이터 배열을 모두 적용한 하나의 데코레이터를 반환한다.
여러 데코레이터를 캡슐화하는 경우 유용하다.
UseInterceptors는 컨텍스트에 따라 인터셉터를 컨트롤러 또는 메서드의 범위에 바인딩하는 데코레이터입니다.
컨트롤러 수준에서 @UseInterceptors를 사용하면 컨트롤러의 모든 핸들러(메서드)에 인터셉터가 적용됩니다.
개별 핸들러 수준에서 @UseInterceptors를 사용하면 인터셉터가 해당 특정 메서드에만 적용됩니다.
https://docs.nestjs.com/interceptors
https://docs.nestjs.com/interceptors#binding-interceptors
const take =
(method: string) =>
<T>(functor?: IResponseBodyStringifier<T> | null) => {
if (functor === undefined) throw TransformError(method);
else if (functor === null) return JSON.stringify;
else if (functor.type === "stringify") return functor.stringify;
else if (functor.type === "assert") return assert(functor.assert);
else if (functor.type === "is") return is(functor.is);
else if (functor.type === "validate") return validate(functor.validate);
throw new Error(
`Error on nestia.core.${method}(): invalid typed stringify function.`,
);
};
기본적인 nestjs의 내장 라우터 데코레이터는 동일.
nestia의 내장인 typia
의 assert, is, validate를 사용한다.
const validate =
<T>(closure: (data: T) => IValidation<string>) =>
(data: T) => {
const result: IValidation<string> = closure(data);
if (result.success === false)
throw new InternalServerErrorException({
errors: result.errors,
message: MESSAGE,
});
return result.data;
};
typia를 사용해본 유저라면 알겠지만 메소드를 직접 사용하면 되는데
함수(closure)로 감싸 사용하는 모습에 의아할 수 있다.
왜 그러하냐면 타입스크립트는 컴파일 언어인데
nestia(typia)에서는 AOT를 사용해서 TS 타입검증을 JS트랜스파일 하기 때문이다.
export type CreatePostBody = {
title: string;
};
const validateBody = <T>(x: unknown) => {
return TSON.validateEquals<T>(x);
};
const body = {
title: "this is title"
};
validateBody<CreatePostBody>(body);
예를들어 위와 같은 코드는 컴파일 타임에 에러가 발생하지 않지만 nestia의 AOT과정(빌드)에서 에러를 일으킨다. 왜냐하면 제네릭 T가 런타임에는 사라지기 때문에 알수 없다는 것 알기 때문이다.
그래서 typia에서는 createValiteEquals
와 같은 런타임에도 사용할수 있도록
Reusable functions
를 제공하는데 위의 클로져가 이놈이다.