diff --git a/server/api/ProcDecorator/base.ts b/server/api/ProcDecorator/base.ts index 3541eaf..2e9e1cb 100644 --- a/server/api/ProcDecorator/base.ts +++ b/server/api/ProcDecorator/base.ts @@ -4,30 +4,135 @@ import type { InvalidResponse } from "../../apiStructure/defs"; type MayBePromise = T | Promise; export type Empty = Record; -export type InvalidProc = InvalidResponse & { - invalidProcSymbol: unknown; - alreadyProcessed?: boolean; -}; +export type DecoratorStack = { + result: boolean, + type: string, + info: string, +}[]; + export interface ProcDecorator> { - (inCtx: In, req: Request, res: Response, isValidRoute: boolean): MayBePromise; + (inCtx: In & Partial, req: Request, res: Response): MayBePromise<[Out, DecoratorStack]>; } +export interface PostProcDecorator{ + (ctx: T, stack: DecoratorStack, req: Request, res: Response, isValidRoute: boolean): MayBePromise<[T, DecoratorStack]>; +} + +type PlainDecorator = ProcDecorator; +type PlainPostDecorator = PostProcDecorator; + + export type ProcDecoratorGenerator = ProcDecorator; -export type ProcDecoratorPrePostGenerator = [ProcDecorator, ProcDecorator]; +export type ProcDecoratorPrePostGenerator = [ProcDecorator, PostProcDecorator]; // eslint-disable-next-line @typescript-eslint/no-explicit-any -export type ProcDecoratorChain = undefined | readonly ((() => ProcDecorator) | (() => [ProcDecorator, ProcDecorator]))[]; +export type ProcDecoratorChain = undefined | readonly ((() => PlainDecorator) | (() => [PlainDecorator, PlainPostDecorator]))[]; export type ResolveChain = T extends undefined ? Empty : T extends ProcDecoratorChain ? Resolve> : never; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type ParseInType = T extends ProcDecorator ? A : never; +type ParseOutType = T extends ProcDecorator ? B : never; + +export function declProcDecorators(decorators: T) { + type InType = ParseInType>; + type OutType = ParseOutType>; + + 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, PostProcDecorator] = [ + 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, 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] + return ; + } + ctx = result; + } + catch (e) { + return [{ + result: false, + reason: `internal error[${idx}]: ${e}`, + invalidProcSymbol: ['preCtx', idx], + }, ctx, idx]; + } + } + return ctx as ResolveChain;*/ + }, + async (ctx, req, res) => ctx + ] +} type Compose2 = D & B extends A & C ? B extends C ? ProcDecorator : never : never; type PD1 = () => ProcDecorator; // eslint-disable-next-line @typescript-eslint/no-explicit-any -type PD2 = () => [ProcDecorator, ProcDecorator]; +type PD2 = () => [ProcDecorator, PostProcDecorator]; type PackChain = T extends readonly [] ? ProcDecorator :