monorepo 버전 준비
## @strpc 기존 RPC를 package화 ### @strpc/express express의 middleware + router 결함 ## @sammo 게임 전체 - server, client - gateway_server, gateway_client
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
export function clientAPIPathGen<T extends object, V>(
|
||||
obj: T,
|
||||
callback: (path: string[], tail: V) => unknown,
|
||||
path: string[] = [],
|
||||
): T {
|
||||
const map = new Map<string, unknown>();
|
||||
return new Proxy(obj, {
|
||||
get(target, key) {
|
||||
if(typeof key === 'symbol'){
|
||||
throw new Error('Symbol is not supported');
|
||||
}
|
||||
|
||||
const cachedResult = map.get(key);
|
||||
if(cachedResult !== undefined){
|
||||
return cachedResult;
|
||||
}
|
||||
|
||||
const nextPath = [...path, key];
|
||||
|
||||
let next;
|
||||
if (key in target) {
|
||||
next = target[key as keyof typeof target];
|
||||
}
|
||||
else {
|
||||
throw `${nextPath} is not exists`;
|
||||
}
|
||||
|
||||
if (typeof (next) === 'function') {
|
||||
const result = callback(nextPath, next as V);
|
||||
map.set(key, result);
|
||||
return result;
|
||||
}
|
||||
const result = clientAPIPathGen<object, V>(next as object, callback, nextPath);
|
||||
map.set(key, result);
|
||||
return result;
|
||||
}
|
||||
}) as T;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
export type {
|
||||
HttpMethod,
|
||||
RawArgType,
|
||||
DefAPINamespace,
|
||||
APICompatType,
|
||||
ValidResponse,
|
||||
InvalidResponse,
|
||||
recoveryMethod,
|
||||
InferResponse,
|
||||
InferError,
|
||||
InferQuery,
|
||||
} from './types.js';
|
||||
|
||||
export {
|
||||
type APITail,
|
||||
GET,
|
||||
POST,
|
||||
PUT,
|
||||
DELETE,
|
||||
PATCH,
|
||||
HEAD,
|
||||
} from './tail.js';
|
||||
export { clientAPIPathGen } from './clientAPIPathGen.js';
|
||||
@@ -0,0 +1,177 @@
|
||||
import type { ArgDeleteAPI, ArgGetAPI, ArgHeadAPI, ArgPatchAPI, ArgPostAPI, ArgPutAPI, EmptyDeleteAPI, EmptyGetAPI, EmptyHeadAPI, EmptyPatchAPI, EmptyPostAPI, EmptyPutAPI, InvalidResponse, RawArgType, ValidResponse } from "./types.js";
|
||||
|
||||
export type APITail = ReturnType<typeof GET> | ReturnType<typeof POST> | ReturnType<typeof PUT> | ReturnType<typeof DELETE> | ReturnType<typeof PATCH> | ReturnType<typeof HEAD>;
|
||||
|
||||
export function GET(): EmptyGetAPI<ValidResponse, InvalidResponse>;
|
||||
export function GET<
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): EmptyGetAPI<ResultType, ErrorType>;
|
||||
export function GET<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgGetAPI<ArgType, ResultType, ErrorType>;
|
||||
export function GET<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgGetAPI<ArgType, ResultType, ErrorType> | EmptyGetAPI<ResultType, ErrorType> {
|
||||
return Object.assign(
|
||||
fakeGET,
|
||||
{ reqType: 'get' } as const
|
||||
)
|
||||
}
|
||||
|
||||
export function POST(): EmptyPostAPI<ValidResponse, InvalidResponse>;
|
||||
export function POST<
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): EmptyPostAPI<ResultType, ErrorType>;
|
||||
export function POST<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgPostAPI<ArgType, ResultType, ErrorType>;
|
||||
export function POST<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgPostAPI<ArgType, ResultType, ErrorType> | EmptyPostAPI<ResultType, ErrorType> {
|
||||
return Object.assign(
|
||||
fakePOST,
|
||||
{ reqType: 'post' } as const
|
||||
)
|
||||
}
|
||||
|
||||
export function PUT(): EmptyPutAPI<ValidResponse, InvalidResponse>;
|
||||
export function PUT<
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): EmptyPutAPI<ResultType, ErrorType>;
|
||||
export function PUT<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgPutAPI<ArgType, ResultType, ErrorType>;
|
||||
export function PUT<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgPutAPI<ArgType, ResultType, ErrorType> | EmptyPutAPI<ResultType, ErrorType> {
|
||||
return Object.assign(
|
||||
fakePUT,
|
||||
{ reqType: 'put' } as const
|
||||
)
|
||||
}
|
||||
|
||||
export function DELETE(): EmptyDeleteAPI<ValidResponse, InvalidResponse>;
|
||||
export function DELETE<
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): EmptyDeleteAPI<ResultType, ErrorType>;
|
||||
export function DELETE<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgDeleteAPI<ArgType, ResultType, ErrorType>;
|
||||
export function DELETE<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgDeleteAPI<ArgType, ResultType, ErrorType> | EmptyDeleteAPI<ResultType, ErrorType> {
|
||||
return Object.assign(
|
||||
fakeDELETE,
|
||||
{ reqType: 'delete' } as const
|
||||
)
|
||||
}
|
||||
|
||||
export function PATCH(): EmptyPatchAPI<ValidResponse, InvalidResponse>;
|
||||
export function PATCH<
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): EmptyPatchAPI<ResultType, ErrorType>;
|
||||
export function PATCH<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgPatchAPI<ArgType, ResultType, ErrorType>;
|
||||
export function PATCH<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgPatchAPI<ArgType, ResultType, ErrorType> | EmptyPatchAPI<ResultType, ErrorType> {
|
||||
return Object.assign(
|
||||
fakePATCH,
|
||||
{ reqType: 'patch' } as const
|
||||
)
|
||||
}
|
||||
|
||||
export function HEAD(): EmptyHeadAPI<ValidResponse, InvalidResponse>;
|
||||
export function HEAD<
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): EmptyHeadAPI<ResultType, ErrorType>;
|
||||
export function HEAD<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgHeadAPI<ArgType, ResultType, ErrorType>;
|
||||
export function HEAD<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgHeadAPI<ArgType, ResultType, ErrorType> | EmptyHeadAPI<ResultType, ErrorType> {
|
||||
return Object.assign(
|
||||
fakeHEAD,
|
||||
{ reqType: 'head' } as const
|
||||
)
|
||||
}
|
||||
|
||||
async function fakeGET<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse,
|
||||
ArgType extends undefined = undefined
|
||||
>(args?: ArgType, returnError = false): Promise<ResultType | ErrorType> {
|
||||
throw `Can't directly call GET. ${args}, ${returnError}. Use auto-generated path API.`
|
||||
}
|
||||
|
||||
async function fakePOST<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse,
|
||||
ArgType extends RawArgType = undefined
|
||||
>(args: ArgType, returnError = false): Promise<ResultType | ErrorType> {
|
||||
throw `Can't directly call POST. ${args}, ${returnError}. Use auto-generated path API.`
|
||||
}
|
||||
|
||||
async function fakePUT<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse,
|
||||
ArgType extends RawArgType = undefined
|
||||
>(args: ArgType, returnError = false): Promise<ResultType | ErrorType> {
|
||||
throw `Can't directly call PUT. ${args}, ${returnError}. Use auto-generated path API.`;
|
||||
}
|
||||
|
||||
async function fakeDELETE<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse,
|
||||
ArgType extends RawArgType = undefined
|
||||
>(args: ArgType, returnError = false): Promise<ResultType | ErrorType> {
|
||||
throw `Can't directly call DELETE. ${args}, ${returnError}. Use auto-generated path API.`;
|
||||
}
|
||||
|
||||
async function fakePATCH<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse,
|
||||
ArgType extends RawArgType = undefined
|
||||
>(args: ArgType, returnError = false): Promise<ResultType | ErrorType> {
|
||||
throw `Can't directly call PATCH. ${args}, ${returnError}. Use auto-generated path API.`
|
||||
}
|
||||
|
||||
async function fakeHEAD<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse,
|
||||
ArgType extends RawArgType = undefined
|
||||
>(args?: ArgType, returnError = false): Promise<ResultType | ErrorType> {
|
||||
throw `Can't directly call HEAD. ${args}, ${returnError}. Use auto-generated path API.`;
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
export type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head';
|
||||
export type RawArgType = {
|
||||
[key: string]: unknown;
|
||||
} | undefined;
|
||||
|
||||
|
||||
export interface ArgAnyAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse,
|
||||
Method extends HttpMethod
|
||||
> {
|
||||
(args: ArgType): Promise<ResultType>;
|
||||
(args: ArgType, returnError: false): Promise<ResultType>;
|
||||
(args: ArgType, returnError: true): Promise<ResultType | ErrorType>;
|
||||
readonly reqType: Method;
|
||||
}
|
||||
|
||||
export type ArgGetAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = ArgAnyAPI<ArgType, ResultType, ErrorType, 'get'>;
|
||||
|
||||
export type ArgPostAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = ArgAnyAPI<ArgType, ResultType, ErrorType, 'post'>;
|
||||
|
||||
export type ArgPutAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = ArgAnyAPI<ArgType, ResultType, ErrorType, 'put'>;
|
||||
|
||||
export type ArgDeleteAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = ArgAnyAPI<ArgType, ResultType, ErrorType, 'delete'>;
|
||||
|
||||
export type ArgPatchAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = ArgAnyAPI<ArgType, ResultType, ErrorType, 'patch'>;
|
||||
|
||||
export type ArgHeadAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = ArgAnyAPI<ArgType, ResultType, ErrorType, 'head'>;
|
||||
|
||||
export interface EmptyAnyAPI<ResultType extends ValidResponse, ErrorType extends InvalidResponse, Method extends HttpMethod> {
|
||||
(): Promise<ResultType>;
|
||||
(args?: undefined): Promise<ResultType>;
|
||||
(args: undefined, returnError: false): Promise<ResultType>;
|
||||
(args: undefined, returnError: true): Promise<ResultType | ErrorType>;
|
||||
readonly reqType: Method;
|
||||
}
|
||||
|
||||
export type EmptyGetAPI<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = EmptyAnyAPI<ResultType, ErrorType, 'get'>;
|
||||
|
||||
export type EmptyPostAPI<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = EmptyAnyAPI<ResultType, ErrorType, 'post'>;
|
||||
|
||||
export type EmptyPutAPI<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = EmptyAnyAPI<ResultType, ErrorType, 'put'>;
|
||||
|
||||
export type EmptyDeleteAPI<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = EmptyAnyAPI<ResultType, ErrorType, 'delete'>;
|
||||
|
||||
export type EmptyPatchAPI<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = EmptyAnyAPI<ResultType, ErrorType, 'patch'>;
|
||||
|
||||
export type EmptyHeadAPI<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = EmptyAnyAPI<ResultType, ErrorType, 'head'>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type ArgTypeOf<T> = T extends AnyAPI<infer A, any, any> ? A : never;
|
||||
|
||||
|
||||
export type AnyAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse
|
||||
> = ArgType extends undefined ? EmptyAnyAPI<ResultType, ErrorType, HttpMethod> : ArgAnyAPI<ArgType, ResultType, ErrorType, HttpMethod>;
|
||||
|
||||
export type GetAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse
|
||||
> = ArgType extends undefined ? EmptyGetAPI<ResultType, ErrorType> : ArgGetAPI<ArgType, ResultType, ErrorType>;
|
||||
|
||||
export type PostAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse
|
||||
> = ArgType extends undefined ? EmptyPostAPI<ResultType, ErrorType> : ArgPostAPI<ArgType, ResultType, ErrorType>;
|
||||
|
||||
export type PutAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse
|
||||
> = ArgType extends undefined ? EmptyPutAPI<ResultType, ErrorType> : ArgPutAPI<ArgType, ResultType, ErrorType>;
|
||||
|
||||
export type DeleteAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse
|
||||
> = ArgType extends undefined ? EmptyDeleteAPI<ResultType, ErrorType> : ArgDeleteAPI<ArgType, ResultType, ErrorType>;
|
||||
|
||||
export type PatchAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse
|
||||
> = ArgType extends undefined ? EmptyPatchAPI<ResultType, ErrorType> : ArgPatchAPI<ArgType, ResultType, ErrorType>;
|
||||
|
||||
export type HeadAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse
|
||||
> = ArgType extends undefined ? EmptyHeadAPI<ResultType, ErrorType> : ArgHeadAPI<ArgType, ResultType, ErrorType>;
|
||||
|
||||
export interface ValidResponse {
|
||||
result: true;
|
||||
}
|
||||
|
||||
export type recoveryMethod = 'hardRefresh' | 'refreshEntireProcess' | 'retryAPI' | 'login';
|
||||
export interface InvalidResponse {
|
||||
result: false;
|
||||
reason: string;
|
||||
recovery?: recoveryMethod;
|
||||
detail?: string | string[] | Record<string, string | string[]>;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type Callable = (...args: any) => any;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type InferQuery<T extends AnyAPI<any, any, any>> = T extends EmptyAnyAPI<any, any, HttpMethod> ? undefined : T extends ArgAnyAPI<infer Q, any, any, HttpMethod> ? Q : never;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type InferResponse<T extends AnyAPI<any, any, any>> = T extends EmptyAnyAPI<infer R, any, HttpMethod> ? R : T extends ArgAnyAPI<any, infer R, any, HttpMethod> ? R : never;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type InferError<T extends AnyAPI<any, any, any>> = T extends EmptyAnyAPI<any, infer E, HttpMethod> ? E : T extends ArgAnyAPI<any, any, infer E, HttpMethod> ? E : never;
|
||||
|
||||
|
||||
export type DefAPINamespace = {
|
||||
[key: string]: DefAPINamespace
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| ArgGetAPI<any, any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| ArgPostAPI<any, any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| ArgPutAPI<any, any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| ArgDeleteAPI<any, any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| ArgPatchAPI<any, any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| ArgHeadAPI<any, any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| EmptyGetAPI<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| EmptyPostAPI<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| EmptyPutAPI<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| EmptyDeleteAPI<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| EmptyPatchAPI<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| EmptyHeadAPI<any, any>
|
||||
;
|
||||
}
|
||||
|
||||
export type APICompatType<T extends Callable> = T extends AnyAPI<infer A, infer R, infer E> ? AnyAPI<A, R, E> : never;
|
||||
Reference in New Issue
Block a user