info
This commit is contained in:
@@ -4,30 +4,135 @@ import type { InvalidResponse } from "../../apiStructure/defs";
|
|||||||
type MayBePromise<T> = T | Promise<T>;
|
type MayBePromise<T> = T | Promise<T>;
|
||||||
|
|
||||||
export type Empty = Record<string, never>;
|
export type Empty = Record<string, never>;
|
||||||
export type InvalidProc = InvalidResponse & {
|
export type DecoratorStack = {
|
||||||
invalidProcSymbol: unknown;
|
result: boolean,
|
||||||
alreadyProcessed?: boolean;
|
type: string,
|
||||||
};
|
info: string,
|
||||||
|
}[];
|
||||||
|
|
||||||
|
|
||||||
export interface ProcDecorator<Out extends object, In extends object = Record<string, never>> {
|
export interface ProcDecorator<Out extends object, In extends object = Record<string, never>> {
|
||||||
(inCtx: In, req: Request, res: Response, isValidRoute: boolean): MayBePromise<Out | InvalidProc>;
|
(inCtx: In & Partial<Out>, req: Request, res: Response): MayBePromise<[Out, DecoratorStack]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PostProcDecorator<T extends object>{
|
||||||
|
(ctx: T, stack: DecoratorStack, req: Request, res: Response, isValidRoute: boolean): MayBePromise<[T, DecoratorStack]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
type PlainDecorator = ProcDecorator<any, any>;
|
||||||
|
type PlainPostDecorator = PostProcDecorator<any>;
|
||||||
|
|
||||||
|
|
||||||
export type ProcDecoratorGenerator<B extends object, A extends object> = ProcDecorator<B & A, A>;
|
export type ProcDecoratorGenerator<B extends object, A extends object> = ProcDecorator<B & A, A>;
|
||||||
export type ProcDecoratorPrePostGenerator<B extends object, A extends object> = [ProcDecorator<B & A, A>, ProcDecorator<B & object, B & object>];
|
export type ProcDecoratorPrePostGenerator<B extends object, A extends object> = [ProcDecorator<B & A, A>, PostProcDecorator<B & A>];
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export type ProcDecoratorChain = undefined | readonly ((() => ProcDecorator<any, any>) | (() => [ProcDecorator<any, any>, ProcDecorator<any, any>]))[];
|
export type ProcDecoratorChain = undefined | readonly ((() => PlainDecorator) | (() => [PlainDecorator, PlainPostDecorator]))[];
|
||||||
|
|
||||||
export type ResolveChain<T> = T extends undefined ? Empty : T extends ProcDecoratorChain ? Resolve<PackChain<T>> : never;
|
export type ResolveChain<T> = T extends undefined ? Empty : T extends ProcDecoratorChain ? Resolve<PackChain<T>> : never;
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
|
||||||
|
type ParseInType<T> = T extends ProcDecorator<infer B, infer A> ? A : never;
|
||||||
|
type ParseOutType<T> = T extends ProcDecorator<infer B, infer A> ? B : never;
|
||||||
|
|
||||||
|
export function declProcDecorators<T extends ProcDecoratorChain>(decorators: T) {
|
||||||
|
type InType = ParseInType<PackChain<T>>;
|
||||||
|
type OutType = ParseOutType<PackChain<T>>;
|
||||||
|
|
||||||
|
const preDecorator: PlainDecorator[] = [];
|
||||||
|
const postDecorator: (PlainDecorator | undefined)[] = [];
|
||||||
|
if (decorators) {
|
||||||
|
for (const procGen of decorators) {
|
||||||
|
const proc = procGen();
|
||||||
|
if (Array.isArray(proc)) {
|
||||||
|
preDecorator.push(proc[0]);
|
||||||
|
postDecorator.push(undefined);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
preDecorator.push(proc);
|
||||||
|
postDecorator.push(proc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const packedDecorators: readonly [ProcDecorator<OutType, InType>, PostProcDecorator<OutType>] = [
|
||||||
|
async (ctx, req, res) => {
|
||||||
|
let rctx = ctx as unknown as OutType;
|
||||||
|
const decoratorStack: DecoratorStack = [];
|
||||||
|
if (!preDecorator) {
|
||||||
|
return [rctx, decoratorStack];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [idx, proc] of preDecorator.entries()) {
|
||||||
|
try {
|
||||||
|
const [newCtx, [stackResult]] = await proc(rctx, req, res);
|
||||||
|
decoratorStack.push(stackResult);
|
||||||
|
|
||||||
|
if(stackResult.result){
|
||||||
|
rctx = newCtx;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [newCtx, decoratorStack];
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
|
||||||
|
return [{
|
||||||
|
result: false,
|
||||||
|
reason: `internal error[${idx}]: ${e}`,
|
||||||
|
invalidProcInfo: [['PreThrow', idx]],
|
||||||
|
}, rctx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [rctx, decoratorStack];
|
||||||
|
},
|
||||||
|
async (ctx, stack, req, res) => {
|
||||||
|
|
||||||
|
return [ctx, stack];
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
return packedDecorators;
|
||||||
|
|
||||||
|
return [
|
||||||
|
async (ctx: InType & Partial<OutType>, req: Request, res: Response) => {
|
||||||
|
return ctx as unknown as OutType;
|
||||||
|
/*if (!preDecorator) {
|
||||||
|
return ctx as Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [idx, proc] of preDecorator.entries()) {
|
||||||
|
try {
|
||||||
|
const result = await proc(ctx, req, res, true) as Result | [InvalidProc, object];
|
||||||
|
if (Array.isArray(result)) {
|
||||||
|
const [invalidProc, erroredCtx] = result;
|
||||||
|
invalidProc.invalidProcInfo.push(['Pre', idx]);
|
||||||
|
throw [invalidProc, erroredCtx as Partial<Result>]
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
ctx = result;
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return [{
|
||||||
|
result: false,
|
||||||
|
reason: `internal error[${idx}]: ${e}`,
|
||||||
|
invalidProcSymbol: ['preCtx', idx],
|
||||||
|
}, ctx, idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ctx as ResolveChain<T>;*/
|
||||||
|
},
|
||||||
|
async (ctx, req, res) => ctx
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
type Compose2<B extends object, A extends object, D, C> = D & B extends A & C ? B extends C ? ProcDecorator<D & B, A> : never : never;
|
type Compose2<B extends object, A extends object, D, C> = D & B extends A & C ? B extends C ? ProcDecorator<D & B, A> : never : never;
|
||||||
|
|
||||||
type PD1<B extends object, A extends object> = () => ProcDecorator<B, A>;
|
type PD1<B extends object, A extends object> = () => ProcDecorator<B, A>;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
type PD2<B extends object, A extends object> = () => [ProcDecorator<B, A>, ProcDecorator<any, any>];
|
type PD2<B extends object, A extends object> = () => [ProcDecorator<B, A>, PostProcDecorator<any>];
|
||||||
|
|
||||||
type PackChain<T> =
|
type PackChain<T> =
|
||||||
T extends readonly [] ? ProcDecorator<Empty, Empty> :
|
T extends readonly [] ? ProcDecorator<Empty, Empty> :
|
||||||
|
|||||||
Reference in New Issue
Block a user