monorepo 버전 준비

## @strpc
기존 RPC를 package화

### @strpc/express
express의 middleware + router 결함

## @sammo
게임 전체
- server, client
- gateway_server, gateway_client
This commit is contained in:
2023-09-23 16:29:18 +00:00
parent 734e0cb7bf
commit e59f9a9659
197 changed files with 15458 additions and 3 deletions
+38
View File
@@ -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;
}
+23
View File
@@ -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';
+177
View File
@@ -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.`;
}
+191
View File
@@ -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;