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 // eslint-disable-next-line @typescript-eslint/no-explicit-any | iAPI_POST // eslint-disable-next-line @typescript-eslint/no-explicit-any | iAPI_PUT // eslint-disable-next-line @typescript-eslint/no-explicit-any | iAPI_DELETE // eslint-disable-next-line @typescript-eslint/no-explicit-any | iAPI_PATCH // eslint-disable-next-line @typescript-eslint/no-explicit-any | iAPI_HEAD ; } // eslint-disable-next-line @typescript-eslint/no-explicit-any export type AnyAPIExecuter = APIExecuter; // eslint-disable-next-line @typescript-eslint/no-explicit-any type AnyAnyAPI = AnyAPI; // eslint-disable-next-line @typescript-eslint/no-explicit-any interface APIExecuter { (query: InferQuery, ctx: CTX, expressReq: Request, expressRes: Response): Promise | InferError | true>; httpMethod: HttpMethod; // eslint-disable-next-line @typescript-eslint/no-explicit-any argValidator?: ZodType>; preDecorator: ProcDecoratorRunner; postDecorator: PostProcDecoratorRunner; } export interface iAPI_GET extends APIExecuter { httpMethod: 'get'; } export interface iAPI_POST extends APIExecuter { httpMethod: 'post'; } export interface iAPI_PUT extends APIExecuter { httpMethod: 'put'; } export interface iAPI_DELETE extends APIExecuter { httpMethod: 'delete'; } export interface iAPI_PATCH extends APIExecuter { httpMethod: 'patch'; } export interface iAPI_HEAD extends APIExecuter { httpMethod: 'head'; } /** API의 반환형. ValidResponse | InvalidResponse | true */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export type APIReturnType = Promise | InferError | true>; // eslint-disable-next-line @typescript-eslint/no-explicit-any function generateAPI(httpMethod: HttpMethod, // eslint-disable-next-line @typescript-eslint/no-explicit-any argValidator: ZodType> | undefined, preDecorator: ProcDecoratorRunner, postDecorator: PostProcDecoratorRunner, callback: (query: InferQuery, ctx: CTX, expressReq: Request, expressRes: Response) => Promise | InferError | true>, ): APIExecuter { return Object.assign( callback, { httpMethod, argValidator, preDecorator, postDecorator, } ); } // eslint-disable-next-line @typescript-eslint/no-explicit-any export function GET>(argValidator?: ZodType>) { return ([preDecorator, postDecorator]: readonly [ProcDecoratorRunner, PostProcDecoratorRunner]) => { return (callback: (query: InferQuery, ctx: CTX, expressReq: Request, expressRes: Response) => Promise | InferError | true>) => { return generateAPI( 'get', argValidator, preDecorator, postDecorator, callback, ) as iAPI_GET; } } } // eslint-disable-next-line @typescript-eslint/no-explicit-any export function POST>(argValidator?: ZodType>) { return ([preDecorator, postDecorator]: readonly [ProcDecoratorRunner, PostProcDecoratorRunner]) => { return (callback: (query: InferQuery, ctx: CTX, expressReq: Request, expressRes: Response) => Promise | InferError | true>) => { return generateAPI( 'post', argValidator, preDecorator, postDecorator, callback, ) as iAPI_POST; } } } // eslint-disable-next-line @typescript-eslint/no-explicit-any export function PUT>(argValidator?: ZodType>) { return ([preDecorator, postDecorator]: readonly [ProcDecoratorRunner, PostProcDecoratorRunner]) => { return (callback: (query: InferQuery, ctx: CTX, expressReq: Request, expressRes: Response) => Promise | InferError | true>) => { return generateAPI( 'put', argValidator, preDecorator, postDecorator, callback, ) as iAPI_PUT; } } } // eslint-disable-next-line @typescript-eslint/no-explicit-any export function DELETE, Z extends ZodType>>(argValidator?: Z) { return ([preDecorator, postDecorator]: readonly [ProcDecoratorRunner, PostProcDecoratorRunner]) => { return (callback: (query: InferQuery, ctx: CTX, expressReq: Request, expressRes: Response) => Promise | InferError | true>) => { return generateAPI( 'delete', argValidator, preDecorator, postDecorator, callback, ) as iAPI_DELETE; } } } // eslint-disable-next-line @typescript-eslint/no-explicit-any export function PATCH>(argValidator?: ZodType>) { return ([preDecorator, postDecorator]: readonly [ProcDecoratorRunner, PostProcDecoratorRunner]) => { return (callback: (query: InferQuery, ctx: CTX, expressReq: Request, expressRes: Response) => Promise | InferError | true>) => { return generateAPI( 'patch', argValidator, preDecorator, postDecorator, callback, ) as iAPI_PATCH; } } } // eslint-disable-next-line @typescript-eslint/no-explicit-any export function HEAD>(argValidator?: ZodType>) { return ([preDecorator, postDecorator]: readonly [ProcDecoratorRunner, PostProcDecoratorRunner]) => { return (callback: (query: InferQuery, ctx: CTX, expressReq: Request, expressRes: Response) => Promise | InferError | true>) => { return generateAPI( 'head', argValidator, preDecorator, postDecorator, callback, ) as iAPI_HEAD; } } } export function raiseError(reason: string, recovery?: recoveryMethod): InvalidResponse { if (recovery) { return { result: false, reason, recovery, }; } return { result: false, reason, }; } export type APIServerType = // eslint-disable-next-line @typescript-eslint/no-explicit-any T extends GetAPI ? iAPI_GET, any> : // eslint-disable-next-line @typescript-eslint/no-explicit-any T extends PostAPI ? iAPI_POST, any> : // eslint-disable-next-line @typescript-eslint/no-explicit-any T extends PutAPI ? iAPI_PUT, any> : // eslint-disable-next-line @typescript-eslint/no-explicit-any T extends DeleteAPI ? iAPI_DELETE, any> : // eslint-disable-next-line @typescript-eslint/no-explicit-any T extends PatchAPI ? iAPI_PATCH, any> : // eslint-disable-next-line @typescript-eslint/no-explicit-any T extends HeadAPI ? iAPI_HEAD, any> : never; export type APINamespaceType = { [K in keyof T]: T[K] extends Callable ? APIServerType : T[K] extends DefAPINamespace ? APINamespaceType : never; };