Skip to content

Instantly share code, notes, and snippets.

@moatorres
Created November 6, 2023 22:43
Show Gist options
  • Save moatorres/2fa97eb3c976b12ae2ac510cbcc2e51a to your computer and use it in GitHub Desktop.
Save moatorres/2fa97eb3c976b12ae2ac510cbcc2e51a to your computer and use it in GitHub Desktop.
Interceptor Decorator
/**
* Interceptor interface for intercepting method calls, requests, responses, process, and errors.
*/
export interface Interceptor {
before?(...args: any[]): Promise<void> | void
after?<T>(result: T, ...args: any[]): Promise<void> | void
error?(error: Error, ...args: any[]): Promise<void> | void
shouldThrow?: boolean
}
/**
* Decorator to intercept a method call.
* @param target The target object.
* @param propertyKey The property key.
* @param descriptor The property descriptor.
* @example
* ```ts
* class Service {
* @intercept({
* before: (a) => console.log('before:', a),
* after: (b) => console.log('after:', b),
* })
* public static create(name: string = '') {
* console.log('created')
* return name.toUpperCase()
* }
* }
* const s = Service.create('john doe')
* // before: john doe
* // created
* // after: JOHN DOE
* ```
* @see https://www.typescriptlang.org/docs/handbook/decorators.html#method-decorators
*/
export function interceptor(options: Interceptor) {
return function intercept<T = unknown>(
target: T,
propertyKey: PropertyKey,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value
descriptor.value = async function (...args: unknown[]) {
if (options.before) await options.before(...args)
try {
const result = await originalMethod.apply(this, args)
if (options.after) await options.after(result, ...args)
return result
} catch (error) {
if (options.error) await options.error(error as Error, ...args)
if (options?.shouldThrow) throw error
}
}
return descriptor
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment