hook-middleware-decorators
v1.0.2
Published
Add and remove pre, post, and "around" middleware hooks to class methods on a per class instance basis with the help of class and method decorators.
Downloads
10
Maintainers
Readme
Hook Middleware Decorators
Add and remove pre, post, and "around" middleware hooks to class methods on a per class instance basis with the help of class and method decorators.
How To Use
import { Hooks, Hook, HookAsync, hasHooks } from 'hook-middleware-decorators'
@Hooks()
class ClassWithHooks {
@Hook()
hello(person: string) {
const message = `Hello ${person}`;
console.log(message);
return message;
}
@HookAsync()
async helloAsync(person: string) {
const message = `Hello ${person} async`;
console.log(message);
return message;
}
noHook(person: string) {
const message = `No hook called with ${person}`
console.log(message);
return message;
}
}
function preHello(person: string){
console.log('pre', person)
}
function postHello(message: string, person: string){
console.log('post', message, person)
}
function aroundHello(func: (person: string)=>string, person: string): string {
console.log('before hello', person);
const result = func(person);
console.log('after hello', result);
return result;
}
const instance = new ClassWithHooks();
let helloUnsubscriber = () => {}
if(hasHooks<ClassWithHooks>(instance)) { // type-guard to ensure the class is decorated with @Hooks
helloUnsubscriber = instance.around('hello', aroundHello);
instance.pre('hello', preHello);
instance.post('hello', postHello);
instance.pre('helloAsync', preHello);
instance.post('helloAsync', postHello);
instance.pre('noHook', preHello);
instance.post('noHook', postHello);
}
(async () => {
instance.hello('world');
await instance.helloAsync('Earth');
instance.noHook('stuff')
helloUnsubscriber();
instance.hello('Mars');
})();
/**
* Result:
*
* before hello world
* pre world
* Hello world
* post Hello world world
* after hello Hello world
* pre Earth
* Hello Earth async
* post Hello Earth async Earth
* No hook called with stuff
* pre Mars
* Hello Mars
* post Hello Mars Mars
*/
Important
The @Hooks
class decorator adds pre
, post
, and around
methods to the decorated class. Any methods or properties with the same names in the class definition will be overridden.
If a pre
or around
function throws an error, the hooked method will throw the error as well. If a post
function throws an error, the hooked method will not throw the error.
Registering a pre
, post
, or around
function will result in an unsubscriber being returned. Invoking the unsubscriber will remove the function as a middleware.
Use Cases
- Put authorization and validation in
pre
functions - Put metrics in
around
functions where applicable - Put any side effects such as notifications in
post
functions
Best Practices
pre
,post
, andaround
functions should refrain from mutating any arguments in order to keep behavior predictable.- Use the
@Hook
decorator for synchronous methods. Make sure middleware functions for synchronous methods are also synchronous. - Use the
@HookAsync
decorator for asynchronous methods.pre
andpost
middleware functions for asynchronous methods can be synchronous or asynchronous.around
middleware functions must be asynchronous