import { assertMethodDecorator } from "../common/decorators.js"; import type { Method } from "../common/types.js"; import { isPromise, resolveCallable, } from "../common/utils.js"; export type AfterFunc = (params: AfterParams) => unknown; export interface AfterConfig { func: AfterFunc | keyof This; wait?: boolean; } export interface AfterParams { args: Args; response: Return; } export function createAfterMethod( originalMethod: Method, config: AfterConfig, ): Method { const resolvedConfig = { wait: false, ...config, }; return function(this: This, ...args: Args): Return { const afterFunc = resolveCallable(this, resolvedConfig.func); const response = originalMethod.apply(this, args); if (!resolvedConfig.wait) { afterFunc({ args, response: response as unknown as Response, }); return response; } if (isPromise(response)) { return Promise.resolve(response).then((resolvedResponse) => { afterFunc({ args, response: resolvedResponse as Response, }); return resolvedResponse; }) as Return; } afterFunc({ args, response: response as unknown as Response, }); return response; } as Method; } export function after( config: AfterConfig, ) { return function( value: Method, context: ClassMethodDecoratorContext>, ): Method { assertMethodDecorator("after", value, context); return createAfterMethod(value, config); }; }