diff --git a/main/hooks/src/hooks.ts b/main/hooks/src/hooks.ts index c2b5f08..6797891 100644 --- a/main/hooks/src/hooks.ts +++ b/main/hooks/src/hooks.ts @@ -1,5 +1,12 @@ import { AsyncMiddleware, compose } from './compose.ts'; -import { convertOptions, HookContext, HookContextData, HookOptions, setManager, setMiddleware } from './base.ts'; +import { + convertOptions, + HookContext, + HookContextData, + HookOptions, + setManager, + setMiddleware +} from './base.ts'; import { copyFnProperties, copyProperties } from './utils.ts'; export function getOriginal(fn: any): any { @@ -23,7 +30,7 @@ export function functionHooks(fn: F, managerOrMiddleware: HookOptions) { // Assemble the hook chain const hookChain: AsyncMiddleware[] = [ // Return `ctx.result` or the context - (ctx, next) => next().then(() => returnContext ? ctx : ctx.result), + (ctx, next) => next().then(() => (returnContext ? ctx : ctx.result)) ]; // Create the hook chain by calling the `collectMiddleware function @@ -41,7 +48,7 @@ export function functionHooks(fn: F, managerOrMiddleware: HookOptions) { ctx.result = result; return next(); - }, + } ); } @@ -60,7 +67,7 @@ export function functionHooks(fn: F, managerOrMiddleware: HookOptions) { Context: manager.getContextClass(), createContext: (data: HookContextData = {}) => { return new wrapper.Context(data); - }, + } }); } @@ -90,10 +97,26 @@ export function objectHooks(obj: any, hooks: HookMap | AsyncMiddleware[]) { } export const hookDecorator = (managerOrMiddleware?: HookOptions) => { + return (target: any, context: DecoratorContext) => { + const manager = convertOptions(managerOrMiddleware); + + if (context.kind === 'class') { + setManager(target.prototype, manager); + return target; + } else if (context.kind === 'method') { + const method = String(context.name); + return functionHooks(target, manager.props({ method })); + } + + throw new Error('Can not apply hooks.'); + }; +}; + +export const legacyDecorator = (managerOrMiddleware?: HookOptions) => { const wrapper: any = ( _target: any, method: string, - descriptor: TypedPropertyDescriptor, + descriptor: TypedPropertyDescriptor ): TypedPropertyDescriptor => { const manager = convertOptions(managerOrMiddleware); diff --git a/main/hooks/test/decorator.test.ts b/main/hooks/test/decorator.test.ts index 235a11e..19f2d50 100644 --- a/main/hooks/test/decorator.test.ts +++ b/main/hooks/test/decorator.test.ts @@ -15,13 +15,15 @@ it('hook decorator on method and classes with inheritance', async () => { ]) class TopLevel {} - @hooks([async (ctx, next) => { - ctx.arguments[0] += ' NameFromDummyClass'; + @hooks([ + async (ctx, next) => { + ctx.arguments[0] += ' NameFromDummyClass'; - await next(); + await next(); - ctx.result += ' ResultFromDummyClass'; - }]) + ctx.result += ' ResultFromDummyClass'; + }, + ]) class DummyClass extends TopLevel { @hooks( middleware([ @@ -63,6 +65,6 @@ it('error cases', () => { assertThrows( () => hooks([])({}, 'test', { value: 'not a function' }), undefined, - `Can not apply hooks. 'test' is not a function`, + `Can not apply hooks.`, ); });