대충이런느낌

This commit is contained in:
2023-08-08 17:10:15 +00:00
parent c7d0702e66
commit e381dd5a7e
10 changed files with 296 additions and 94 deletions
+16
View File
@@ -0,0 +1,16 @@
import { ngGET } from "../defs";
import type { structure } from "../../apiStructure/sammoRootAPI";
import type { ExtractError, ExtractQuery, ExtractResponse } from "../../apiStructure/defs";
type BaseAPI = typeof structure.Login.ReqNonce;
type RType = ExtractResponse<BaseAPI>;
type EType = ExtractError<BaseAPI>;
type QType = ExtractQuery<BaseAPI>;
const argValidator = undefined;
const procDecorator = [] as const;
export const ReqNonce = ngGET<RType, EType, QType>(argValidator)(procDecorator)(
(query, ctx, req, res) => {
throw new Error("Method not implemented.");
}
);
+42 -11
View File
@@ -1,24 +1,55 @@
import { POST } from "../defs"; import { POST, ngPOST } from "../defs";
import type { structure } from "../../apiStructure/sammoRootAPI"; import type { structure } from "../../apiStructure/sammoRootAPI";
import type { ExtractError, ExtractQuery, ExtractResponse } from "../../apiStructure/defs"; import type { ExtractError, ExtractQuery, ExtractResponse } from "../../apiStructure/defs";
import { StartSession } from "../ProcDecorator/StartSession";
import { IsString } from "class-validator";
import { delay } from "../../util/delay";
type BaseAPI = typeof structure.Login.LoginByID; type BaseAPI = typeof structure.Login.LoginByID;
type RType = ExtractResponse<BaseAPI>; type RType = ExtractResponse<BaseAPI>;
type EType = ExtractError<BaseAPI>; type EType = ExtractError<BaseAPI>;
type QType = ExtractQuery<BaseAPI>; type QType = ExtractQuery<BaseAPI>;
class ArgValidator implements QType {
class Q implements QType { @IsString()
username!: string; username!: string;
@IsString()
password!: string; password!: string;
} }
const procDecorator = [
StartSession,
] as const;
const procDecorator = [] as const; export const LoginByID = ngPOST<RType, EType, QType>(ArgValidator)(procDecorator)(
async (query, ctx, req, res) => {
const username = query.username;
const password = query.password;
export class LoginByID extends POST<RType, EType, QType, typeof procDecorator>{ //TODO: DB에서 뭔가 가져와야 함
readonly argValidator = Q; await delay(1);
readonly procDecorator = procDecorator;
protected LoginByID = Symbol("LoginByID");//TODO: remove this if(Math.random() < 0.3){
protected override async api(query: QType, ctx,): Promise<RType | EType | true> { return {
throw new Error("Method not implemented."); result: false,
reason: "로그인 실패",
reqOTP: false,
}
}
if(Math.random() < 0.5){
return {
result: false,
reason: "OTP 인증 필요",
reqOTP: true,
}
}
const userID = 1;
const nextToken: [number, string] = [1, "1234567890"];
await ctx.setValue("userID", userID);
return {
result: true,
nextToken,
}
} }
} );
+34 -8
View File
@@ -1,16 +1,42 @@
import { POST } from "../defs"; import { ngPOST } from "../defs";
import type { structure } from "../../apiStructure/sammoRootAPI"; import type { structure } from "../../apiStructure/sammoRootAPI";
import type { ExtractError, ExtractQuery, ExtractResponse } from "../../apiStructure/defs"; import type { ExtractError, ExtractQuery, ExtractResponse } from "../../apiStructure/defs";
import { StartSession } from "../ProcDecorator/StartSession";
import { IsNumber, IsString } from "class-validator";
import { delay } from "../../util/delay";
type BaseAPI = typeof structure.Login.LoginByToken; type BaseAPI = typeof structure.Login.LoginByToken;
type RType = ExtractResponse<BaseAPI>; type RType = ExtractResponse<BaseAPI>;
type EType = ExtractError<BaseAPI>; type EType = ExtractError<BaseAPI>;
type QType = ExtractQuery<BaseAPI>; type QType = ExtractQuery<BaseAPI>;
class ArgValidator implements QType {
@IsNumber()
token_id!: number;
@IsString()
hashedToken!: string;
}
const procDecorator = [
StartSession,
] as const;
export const LoginByToken = ngPOST<RType, EType, QType>(ArgValidator)(procDecorator)(
async (query, ctx) => {
query.hashedToken;
ctx.clearSession();
await delay(1);
//무언가 로그인
//TODO: DB는 어디서 들고옴?
const userID = 1;
const nextToken: [number, string] = [1, "1234567890"];
await ctx.setValue("userID", userID);
//throw new Error("Method not implemented.");
return {
result: true,
nextToken,
}
export class LoginByToken extends POST<RType, EType, QType>{
readonly argValidator = undefined;
protected LoginByToken = Symbol("LoginByToken");//TODO: remove this
protected override async api(query: QType): Promise<RType | EType | true> {
throw new Error("Method not implemented.");
} }
} );
+26 -14
View File
@@ -1,23 +1,35 @@
import { ngGET } from "../defs"; import { APINamespace, APINamespaceType, ngGET } from "../defs";
import type { structure } from "../../apiStructure/sammoRootAPI"; import type { structure } from "../../apiStructure/sammoRootAPI";
import type { ExtractError, ExtractQuery, ExtractResponse } from "../../apiStructure/defs"; import type { DefAPINamespace, ExtractError, ExtractQuery, ExtractResponse } from "../../apiStructure/defs";
import { StartSession } from "../ProcDecorator/StartSession";
type BaseAPI = typeof structure.Login.ReqNonce; type BaseAPI = typeof structure.Login.ReqNonce;
type RType = ExtractResponse<BaseAPI>; type RType = ExtractResponse<BaseAPI>;
type EType = ExtractError<BaseAPI>; type EType = ExtractError<BaseAPI>;
type QType = ExtractQuery<BaseAPI>; type QType = ExtractQuery<BaseAPI>;
const argValidator = undefined;
const procDecorator = [
StartSession,
] as const;
/*export class ReqNonce extends GET<RType, EType, QType>{ export const ReqNonce = ngGET<RType, EType, QType>(argValidator)(procDecorator)(
readonly argValidator = undefined; async (query, ctx) => {
readonly procDecorator = [] as const; const nonce = await ctx.getValue<string>("nonce");
protected ReqNonce = Symbol("ReqNonce");//TODO: remove this if(nonce !== undefined){
protected override async api(query: QType): Promise<RType | EType | true> { return {
throw new Error("Method not implemented."); loginNonce: nonce,
} result: true,
}*/ }
}
export const ReqNonce = ngGET<RType, EType, QType>(undefined)([] as const)( const newNonce = "1234567890";
(query, ctx, req, res) => { await ctx.setValue("nonce", newNonce);
throw new Error("Method not implemented."); return {
loginNonce: newNonce,
result: true,
}
} }
); );
type BaseAPI2 = APINamespaceType<typeof structure.Login>['ReqNonce'];
type A = typeof ReqNonce;
+5 -10
View File
@@ -1,4 +1,4 @@
import { GET } from "../defs"; import { GET, ngGET } from "../defs";
import type { structure } from "../../apiStructure/sammoRootAPI"; import type { structure } from "../../apiStructure/sammoRootAPI";
import type { ExtractError, ExtractQuery, ExtractResponse } from "../../apiStructure/defs"; import type { ExtractError, ExtractQuery, ExtractResponse } from "../../apiStructure/defs";
@@ -7,13 +7,8 @@ type RType = ExtractResponse<BaseAPI>;
type EType = ExtractError<BaseAPI>; type EType = ExtractError<BaseAPI>;
type QType = ExtractQuery<BaseAPI>; type QType = ExtractQuery<BaseAPI>;
export class test extends GET<RType, EType, QType>{ export const test = ngGET<RType, EType, QType>(undefined)(undefined)(
readonly argValidator = undefined; (query, ctx, req, res) => {
protected ReqNonce = Symbol("ReqNonce");//TODO: remove this throw new Error("Method not implemented.");
protected override async api(query: QType): Promise<RType | EType | true> {
return {
hello: "world",
result: true,
}
} }
} );
+5 -2
View File
@@ -1,4 +1,5 @@
import { LoginCtx } from "./ReqLogin"; import { LoginCtx } from "./ReqLogin";
import { SessionCtx } from "./StartSession";
import type { ProcDecoratorGenerator } from "./base"; import type { ProcDecoratorGenerator } from "./base";
import type { Request, Response } from "express"; import type { Request, Response } from "express";
@@ -7,10 +8,12 @@ export interface UserLevelCtx {
userLevel: number; userLevel: number;
} }
export function ParseUserLevel<Q extends LoginCtx>(): ProcDecoratorGenerator<UserLevelCtx, Q> { export function ParseUserLevel<Q extends LoginCtx & SessionCtx>(): ProcDecoratorGenerator<UserLevelCtx, Q> {
return (inCtx) => { return (inCtx) => {
const userLevel = 123;
inCtx.setValue('userLevel', userLevel);
return { return {
userLevel: 123, userLevel,
...inCtx, ...inCtx,
} }
} }
+18 -3
View File
@@ -1,15 +1,30 @@
import { LoginCtx } from "./ReqLogin"; import { LoginCtx } from "./ReqLogin";
import { SessionCtx } from "./StartSession";
import type { ProcDecoratorGenerator } from "./base"; import type { ProcDecoratorGenerator } from "./base";
import type { Request, Response } from "express"; import type { Request, Response } from "express";
import { delay } from "../../util/delay.js";
export type GameLoginCtx = { export type GameLoginCtx = {
generalID: number; generalID: number;
} }
export function ReqGameLogin<Q extends LoginCtx>(): ProcDecoratorGenerator<GameLoginCtx, Q> { export function ReqGameLogin<Q extends LoginCtx & SessionCtx>(): ProcDecoratorGenerator<GameLoginCtx, Q> {
return (inCtx) => { return async (inCtx) => {
const ctx: Q & Partial<GameLoginCtx> = inCtx;
if (ctx.generalID !== undefined) {
return {
generalID: ctx.generalID,
...inCtx,
};
}
console.log('Something GameLogin');
await delay(0);
inCtx.setValue('generalID', ctx.userID * 4);
return { return {
generalID: inCtx.userID * 4, generalID: ctx.userID * 4,
...inCtx, ...inCtx,
} }
} }
+15 -12
View File
@@ -1,20 +1,23 @@
import type { Empty, ProcDecoratorPrePostGenerator } from "./base"; import { SessionCtx } from "./StartSession";
import type { InvalidProc, ProcDecoratorGenerator } from "./base";
export type LoginCtx = { export type LoginCtx = {
userID: number; userID: number;
} }
export function ReqLogin<Q extends object = Empty>(): ProcDecoratorPrePostGenerator<LoginCtx, Q> { export function ReqLogin<Q extends SessionCtx>(): ProcDecoratorGenerator<LoginCtx, Q> {
return [ return (inCtx) => {
(inCtx) => { const ctx: Q & Partial<LoginCtx> = inCtx;
const userID = ctx.userID;
if (userID === undefined) {
return { return {
userID: 999, result: false,
...inCtx, reason: 'Required Login',
}; invalidProcSymbol: 'ReqLogin'
}, } satisfies InvalidProc;
(inCtx) => {
console.log('ReqLogin post');
return inCtx;
} }
]
return ctx as LoginCtx & Q;
}
} }
+39
View File
@@ -0,0 +1,39 @@
import type { Empty, ProcDecoratorGenerator } from "./base";
export type SessionCtx = {
clearSession: () => Promise<void>;
deleteValue: (key: string) => Promise<void>;
getValue: <T>(key: string) => Promise<T | undefined>;
setValue: (key: string, value: unknown) => Promise<void>;
sessionRaw: {
raw: object;
changed: boolean;
};
}
export function StartSession<Q extends object = Empty>(): ProcDecoratorGenerator<SessionCtx, Q> {
return (inCtx) => {
const raw: object = {};
return {
clearSession: () => Promise.resolve(),
deleteValue: async (key: string) => {
console.log('deleteValue', key);
if (raw[key] !== undefined) {
delete raw[key];
}
},
getValue: async <T>(key: string) => {
return raw[key] as T | undefined;
},
setValue: async (key: string, value: unknown) => {
console.log('setValue', key, value);
raw[key] = value;
},
sessionRaw: {
raw,
changed: false,
},
...inCtx,
};
}
}
+96 -34
View File
@@ -94,14 +94,14 @@ export abstract class APIExecuter<R extends ValidResponse, E extends InvalidResp
} }
let isValidRoute = true; let isValidRoute = true;
if(index !== -1 && index !== this.postDecorator.length){ if (index !== -1 && index !== this.postDecorator.length) {
isValidRoute = false; isValidRoute = false;
index = clamp(index, 0, this.postDecorator.length); index = clamp(index, 0, this.postDecorator.length);
} }
for (let i = index - 1; i >= 0; i--) { for (let i = index - 1; i >= 0; i--) {
const proc = this.postDecorator[i]; const proc = this.postDecorator[i];
if(!proc){ if (!proc) {
continue; continue;
} }
@@ -131,7 +131,7 @@ export abstract class APIExecuter<R extends ValidResponse, E extends InvalidResp
const ctx = await this.preCtx(expressReq, expressRes); const ctx = await this.preCtx(expressReq, expressRes);
if (Array.isArray(ctx)) { if (Array.isArray(ctx)) {
const [invalidProc, errCtx, idx] = ctx; const [invalidProc, errCtx, idx] = ctx;
if (idx == 0){ if (idx == 0) {
expressRes.json(invalidProc); expressRes.json(invalidProc);
return; return;
} }
@@ -147,7 +147,7 @@ export abstract class APIExecuter<R extends ValidResponse, E extends InvalidResp
const result = await this.api(query, ctx, expressReq, expressRes); const result = await this.api(query, ctx, expressReq, expressRes);
const postResult = await this.postCtx(ctx, expressReq, expressRes); const postResult = await this.postCtx(ctx, expressReq, expressRes);
if (postResult !== undefined) { if (postResult !== undefined) {
if(result === true){ if (result === true) {
//NOTE: 이미 api에서 response를 보낸 특이 케이스. //NOTE: 이미 api에서 response를 보낸 특이 케이스.
return; return;
} }
@@ -163,7 +163,7 @@ export abstract class APIExecuter<R extends ValidResponse, E extends InvalidResp
} }
} }
interface ngAPIExecuter<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain>{ interface ngAPIExecuter<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> {
(query: Q, ctx: ResolveChain<PD>, expressReq: Request, expressRes: Response): Promise<R | E | true>; (query: Q, ctx: ResolveChain<PD>, expressReq: Request, expressRes: Response): Promise<R | E | true>;
httpMethod: HttpMethod; httpMethod: HttpMethod;
argValidator?: ValidatorType<Q>; argValidator?: ValidatorType<Q>;
@@ -171,19 +171,38 @@ interface ngAPIExecuter<R extends ValidResponse, E extends InvalidResponse, Q ex
postDecorator: (ProcDecorator<any, any> | undefined)[]; postDecorator: (ProcDecorator<any, any> | undefined)[];
} }
interface ngAPIGenerator<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType>{ export interface iAPI_GET<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> extends ngAPIExecuter<R, E, Q, PD> {
<PD extends ProcDecoratorChain>(procDecoratorChain: PD): ngAPIExecuter<R, E, Q, PD>; httpMethod: 'get';
} }
function ngGenerateAPI<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain>(httpMethod: HttpMethod, args: { export interface iAPI_POST<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> extends ngAPIExecuter<R, E, Q, PD> {
argValidator?: ValidatorType<Q>, httpMethod: 'post';
}
export interface iAPI_PUT<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> extends ngAPIExecuter<R, E, Q, PD> {
httpMethod: 'put';
}
export interface iAPI_DELETE<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> extends ngAPIExecuter<R, E, Q, PD> {
httpMethod: 'delete';
}
export interface iAPI_PATCH<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> extends ngAPIExecuter<R, E, Q, PD> {
httpMethod: 'patch';
}
export interface iAPI_HEAD<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> extends ngAPIExecuter<R, E, Q, PD> {
httpMethod: 'head';
}
function ngGenerateAPI<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain>(httpMethod: HttpMethod,
argValidator: ValidatorType<Q> | undefined,
procDecoratorChain: PD, procDecoratorChain: PD,
callback: (query: Q, ctx: ResolveChain<PD>, expressReq: Request, expressRes: Response) => Promise<R | E | true>, callback: (query: Q, ctx: ResolveChain<PD>, expressReq: Request, expressRes: Response) => Promise<R | E | true>,
}): ngAPIExecuter<R, E, Q, PD>{ ): ngAPIExecuter<R, E, Q, PD> {
const { argValidator, procDecoratorChain, callback } = args;
const preDecorator: ProcDecorator<any, any>[] = []; const preDecorator: ProcDecorator<any, any>[] = [];
const postDecorator: (ProcDecorator<any, any> | undefined)[] = []; const postDecorator: (ProcDecorator<any, any> | undefined)[] = [];
if(procDecoratorChain){ if (procDecoratorChain) {
for (const procGen of procDecoratorChain) { for (const procGen of procDecoratorChain) {
const proc = procGen(); const proc = procGen();
if (Array.isArray(proc)) { if (Array.isArray(proc)) {
@@ -208,41 +227,84 @@ function ngGenerateAPI<R extends ValidResponse, E extends InvalidResponse, Q ext
); );
} }
export function ngGET<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType>(argValidator?: ValidatorType<Q>){ export function ngGET<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType>(argValidator?: ValidatorType<Q>) {
return <PD extends ProcDecoratorChain>(procDecoratorChain: PD) => { return <PD extends ProcDecoratorChain>(procDecoratorChain: PD) => {
return (callback: (query: Q, ctx: ResolveChain<PD>, expressReq: Request, expressRes: Response) => Promise<R | E | true>) => { return (callback: (query: Q, ctx: ResolveChain<PD>, expressReq: Request, expressRes: Response) => Promise<R | E | true>) => {
return ngGenerateAPI<R, E, Q, PD>('get', { return ngGenerateAPI<R, E, Q, PD>(
'get',
argValidator, argValidator,
procDecoratorChain, procDecoratorChain,
callback, callback,
}); ) as iAPI_GET<R, E, Q, PD>;
} }
} }
} }
interface ngGET<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> extends ngAPIExecuter<R, E, Q, PD>{ export function ngPOST<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType>(argValidator?: ValidatorType<Q>) {
httpMethod: 'get'; return <PD extends ProcDecoratorChain>(procDecoratorChain: PD) => {
return (callback: (query: Q, ctx: ResolveChain<PD>, expressReq: Request, expressRes: Response) => Promise<R | E | true>) => {
return ngGenerateAPI<R, E, Q, PD>(
'post',
argValidator,
procDecoratorChain,
callback,
) as iAPI_POST<R, E, Q, PD>;
}
}
} }
interface ngPOST<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> extends ngAPIExecuter<R, E, Q, PD>{ export function ngPUT<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType>(argValidator?: ValidatorType<Q>) {
httpMethod: 'post'; return <PD extends ProcDecoratorChain>(procDecoratorChain: PD) => {
return (callback: (query: Q, ctx: ResolveChain<PD>, expressReq: Request, expressRes: Response) => Promise<R | E | true>) => {
return ngGenerateAPI<R, E, Q, PD>(
'put',
argValidator,
procDecoratorChain,
callback,
) as iAPI_PUT<R, E, Q, PD>;
}
}
} }
interface ngPUT<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> extends ngAPIExecuter<R, E, Q, PD>{ export function ngDELETE<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType>(argValidator?: ValidatorType<Q>) {
httpMethod: 'put'; return <PD extends ProcDecoratorChain>(procDecoratorChain: PD) => {
return (callback: (query: Q, ctx: ResolveChain<PD>, expressReq: Request, expressRes: Response) => Promise<R | E | true>) => {
return ngGenerateAPI<R, E, Q, PD>(
'delete',
argValidator,
procDecoratorChain,
callback,
) as iAPI_DELETE<R, E, Q, PD>;
}
}
} }
interface ngDELETE<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> extends ngAPIExecuter<R, E, Q, PD>{ export function ngPATCH<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType>(argValidator?: ValidatorType<Q>) {
httpMethod: 'delete'; return <PD extends ProcDecoratorChain>(procDecoratorChain: PD) => {
return (callback: (query: Q, ctx: ResolveChain<PD>, expressReq: Request, expressRes: Response) => Promise<R | E | true>) => {
return ngGenerateAPI<R, E, Q, PD>(
'patch',
argValidator,
procDecoratorChain,
callback,
) as iAPI_PATCH<R, E, Q, PD>;
}
}
} }
interface ngPATCH<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> extends ngAPIExecuter<R, E, Q, PD>{ export function ngHEAD<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType>(argValidator?: ValidatorType<Q>) {
httpMethod: 'patch'; return <PD extends ProcDecoratorChain>(procDecoratorChain: PD) => {
return (callback: (query: Q, ctx: ResolveChain<PD>, expressReq: Request, expressRes: Response) => Promise<R | E | true>) => {
return ngGenerateAPI<R, E, Q, PD>(
'head',
argValidator,
procDecoratorChain,
callback,
) as iAPI_HEAD<R, E, Q, PD>;
}
}
} }
interface ngHEAD<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> extends ngAPIExecuter<R, E, Q, PD>{
httpMethod: 'head';
}
export abstract class APIBodyParseExecuter<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> extends APIExecuter<R, E, Q, PD>{ export abstract class APIBodyParseExecuter<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, PD extends ProcDecoratorChain> extends APIExecuter<R, E, Q, PD>{
@@ -321,17 +383,17 @@ export type ClassType<T> = new (...args: any[]) => T;
export type APIServerType<T extends Callable> = export type APIServerType<T extends Callable> =
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
T extends GetAPICallT<infer Q, infer R, infer E> ? ClassType<GET<R, E, Q, any>> : T extends GetAPICallT<infer Q, infer R, infer E> ? iAPI_GET<R, E, Q, any> :
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
T extends PostAPICallT<infer Q, infer R, infer E> ? ClassType<POST<R, E, Q, any>> : T extends PostAPICallT<infer Q, infer R, infer E> ? iAPI_POST<R, E, Q, any> :
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
T extends PutAPICallT<infer Q, infer R, infer E> ? ClassType<PUT<R, E, Q, any>> : T extends PutAPICallT<infer Q, infer R, infer E> ? iAPI_PUT<R, E, Q, any> :
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
T extends DeleteAPICallT<infer Q, infer R, infer E> ? ClassType<DELETE<R, E, Q, any>> : T extends DeleteAPICallT<infer Q, infer R, infer E> ? iAPI_DELETE<R, E, Q, any> :
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
T extends PatchAPICallT<infer Q, infer R, infer E> ? ClassType<PATCH<R, E, Q, any>> : T extends PatchAPICallT<infer Q, infer R, infer E> ? iAPI_PATCH<R, E, Q, any> :
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
T extends HeadAPICallT<infer Q, infer R, infer E> ? ClassType<HEAD<R, E, Q, any>> : T extends HeadAPICallT<infer Q, infer R, infer E> ? iAPI_HEAD<R, E, Q, any> :
never; never;
export type APINamespaceType<T extends DefAPINamespace> = { export type APINamespaceType<T extends DefAPINamespace> = {
[K in keyof T]: [K in keyof T]: