monorepo 버전 준비
## @strpc 기존 RPC를 package화 ### @strpc/express express의 middleware + router 결함 ## @sammo 게임 전체 - server, client - gateway_server, gateway_client
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
|
||||
import type { Request, Response } from 'express';
|
||||
import type { AnyAPI, Callable, DefAPINamespace, DeleteAPI, GetAPI, HeadAPI, HttpMethod, InferError, InferQuery, InferResponse, InvalidResponse, PatchAPI, PostAPI, PutAPI, recoveryMethod } from '@strpc/def/types';
|
||||
import type { Empty, PostProcDecoratorRunner, ProcDecoratorRunner } from './proc_decorator.js';
|
||||
import type { ZodType } from 'zod';
|
||||
|
||||
export type APINamespace = {
|
||||
[key: string]: APINamespace
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| iAPI_GET<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| iAPI_POST<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| iAPI_PUT<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| iAPI_DELETE<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| iAPI_PATCH<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| iAPI_HEAD<any, any>
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type AnyAPIExecuter = APIExecuter<any, any>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type AnyAnyAPI = AnyAPI<any, any, any>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
interface APIExecuter<T extends AnyAnyAPI, CTX extends object> {
|
||||
(query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response): Promise<InferResponse<T> | InferError<T> | true>;
|
||||
httpMethod: HttpMethod;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
argValidator?: ZodType<InferQuery<T>>;
|
||||
preDecorator: ProcDecoratorRunner<CTX, Empty>;
|
||||
postDecorator: PostProcDecoratorRunner<CTX>;
|
||||
}
|
||||
|
||||
export interface iAPI_GET<T extends AnyAnyAPI, CTX extends object> extends APIExecuter<T, CTX> {
|
||||
httpMethod: 'get';
|
||||
}
|
||||
|
||||
export interface iAPI_POST<T extends AnyAnyAPI, CTX extends object> extends APIExecuter<T, CTX> {
|
||||
httpMethod: 'post';
|
||||
}
|
||||
|
||||
export interface iAPI_PUT<T extends AnyAnyAPI, CTX extends object> extends APIExecuter<T, CTX> {
|
||||
httpMethod: 'put';
|
||||
}
|
||||
|
||||
export interface iAPI_DELETE<T extends AnyAnyAPI, CTX extends object> extends APIExecuter<T, CTX> {
|
||||
httpMethod: 'delete';
|
||||
}
|
||||
|
||||
export interface iAPI_PATCH<T extends AnyAnyAPI, CTX extends object> extends APIExecuter<T, CTX> {
|
||||
httpMethod: 'patch';
|
||||
}
|
||||
|
||||
export interface iAPI_HEAD<T extends AnyAnyAPI, CTX extends object> extends APIExecuter<T, CTX> {
|
||||
httpMethod: 'head';
|
||||
}
|
||||
|
||||
|
||||
/** API의 반환형. ValidResponse | InvalidResponse | true */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type APIReturnType<T extends AnyAnyAPI> = Promise<InferResponse<T> | InferError<T> | true>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function generateAPI<T extends AnyAnyAPI, CTX extends object>(httpMethod: HttpMethod,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
argValidator: ZodType<InferQuery<T>> | undefined,
|
||||
preDecorator: ProcDecoratorRunner<CTX, Empty>,
|
||||
postDecorator: PostProcDecoratorRunner<CTX>,
|
||||
callback: (query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<InferResponse<T> | InferError<T> | true>,
|
||||
): APIExecuter<T, CTX> {
|
||||
return Object.assign(
|
||||
callback,
|
||||
{
|
||||
httpMethod,
|
||||
argValidator,
|
||||
preDecorator,
|
||||
postDecorator,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function GET<T extends GetAPI<any, any, any>>(argValidator?: ZodType<InferQuery<T>>) {
|
||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
||||
return (callback: (query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<InferResponse<T> | InferError<T> | true>) => {
|
||||
return generateAPI<T, CTX>(
|
||||
'get',
|
||||
argValidator,
|
||||
preDecorator,
|
||||
postDecorator,
|
||||
callback,
|
||||
) as iAPI_GET<T, CTX>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function POST<T extends PostAPI<any, any, any>>(argValidator?: ZodType<InferQuery<T>>) {
|
||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
||||
return (callback: (query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<InferResponse<T> | InferError<T> | true>) => {
|
||||
return generateAPI<T, CTX>(
|
||||
'post',
|
||||
argValidator,
|
||||
preDecorator,
|
||||
postDecorator,
|
||||
callback,
|
||||
) as iAPI_POST<T, CTX>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function PUT<T extends PutAPI<any, any, any>>(argValidator?: ZodType<InferQuery<T>>) {
|
||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
||||
return (callback: (query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<InferResponse<T> | InferError<T> | true>) => {
|
||||
return generateAPI<T, CTX>(
|
||||
'put',
|
||||
argValidator,
|
||||
preDecorator,
|
||||
postDecorator,
|
||||
callback,
|
||||
) as iAPI_PUT<T, CTX>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function DELETE<T extends DeleteAPI<any, any, any>, Z extends ZodType<InferQuery<T>>>(argValidator?: Z) {
|
||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
||||
return (callback: (query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<InferResponse<T> | InferError<T> | true>) => {
|
||||
return generateAPI<T, CTX>(
|
||||
'delete',
|
||||
argValidator,
|
||||
preDecorator,
|
||||
postDecorator,
|
||||
callback,
|
||||
) as iAPI_DELETE<T, CTX>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function PATCH<T extends PatchAPI<any, any, any>>(argValidator?: ZodType<InferQuery<T>>) {
|
||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
||||
return (callback: (query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<InferResponse<T> | InferError<T> | true>) => {
|
||||
return generateAPI<T, CTX>(
|
||||
'patch',
|
||||
argValidator,
|
||||
preDecorator,
|
||||
postDecorator,
|
||||
callback,
|
||||
) as iAPI_PATCH<T, CTX>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function HEAD<T extends HeadAPI<any, any, any>>(argValidator?: ZodType<InferQuery<T>>) {
|
||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
||||
return (callback: (query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<InferResponse<T> | InferError<T> | true>) => {
|
||||
return generateAPI<T, CTX>(
|
||||
'head',
|
||||
argValidator,
|
||||
preDecorator,
|
||||
postDecorator,
|
||||
callback,
|
||||
) as iAPI_HEAD<T, CTX>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function raiseError(reason: string, recovery?: recoveryMethod): InvalidResponse {
|
||||
if (recovery) {
|
||||
return {
|
||||
result: false,
|
||||
reason,
|
||||
recovery,
|
||||
};
|
||||
}
|
||||
return {
|
||||
result: false,
|
||||
reason,
|
||||
};
|
||||
}
|
||||
|
||||
export type APIServerType<T extends Callable> =
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
T extends GetAPI<infer Q, infer R, infer E> ? iAPI_GET<GetAPI<Q, R, E>, any> :
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
T extends PostAPI<infer Q, infer R, infer E> ? iAPI_POST<PostAPI<Q, R, E>, any> :
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
T extends PutAPI<infer Q, infer R, infer E> ? iAPI_PUT<PutAPI<Q, R, E>, any> :
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
T extends DeleteAPI<infer Q, infer R, infer E> ? iAPI_DELETE<DeleteAPI<Q, R, E>, any> :
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
T extends PatchAPI<infer Q, infer R, infer E> ? iAPI_PATCH<PatchAPI<Q, R, E>, any> :
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
T extends HeadAPI<infer Q, infer R, infer E> ? iAPI_HEAD<HeadAPI<Q, R, E>, any> :
|
||||
|
||||
never;
|
||||
export type APINamespaceType<T extends DefAPINamespace> = {
|
||||
[K in keyof T]:
|
||||
T[K] extends Callable ? APIServerType<T[K]> :
|
||||
T[K] extends DefAPINamespace ? APINamespaceType<T[K]> :
|
||||
never;
|
||||
};
|
||||
Reference in New Issue
Block a user