Last active
March 24, 2022 06:13
-
-
Save aleksandar-b/279fbf30fd4127882bd2dac4b9b87eb2 to your computer and use it in GitHub Desktop.
Interceptor wrapper for NestJs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
CallHandler, | |
ExecutionContext, | |
Injectable, | |
Logger, | |
NestInterceptor, | |
} from "@nestjs/common"; | |
import { Observable } from "rxjs"; | |
import { catchError, tap } from "rxjs/operators"; | |
import { isFunction } from "../utils"; | |
@Injectable() | |
export class BaseInterceptor implements NestInterceptor { | |
public before: Record< | |
string, | |
(args: { | |
nestContext: ExecutionContext; | |
args: unknown[]; | |
methodName: string; | |
className: string; | |
}) => void | |
>; | |
public after: Record< | |
string, | |
(args: { | |
nestContext: ExecutionContext; | |
args: unknown[]; | |
result: unknown; | |
}) => void | |
>; | |
public onError: (args: { | |
nestContext: ExecutionContext; | |
args: unknown[]; | |
error: unknown; | |
methodName: string; | |
className: string; | |
}) => void; | |
async intercept( | |
context: ExecutionContext, | |
next: CallHandler | |
): Promise<Observable<unknown>> { | |
const methodName = context.getHandler().name; | |
const className = context.getClass().name; | |
const beforeCallback = this.before?.[methodName] || this.before?.["*"]; | |
if (isFunction(beforeCallback)) { | |
await beforeCallback({ | |
nestContext: context, | |
args: context.getArgs(), | |
methodName: methodName, | |
className: className, | |
}); | |
} | |
return next.handle().pipe( | |
tap((result: unknown) => { | |
const afterCallback = this.after?.[methodName] || this.after?.["*"]; | |
if (isFunction(afterCallback)) { | |
afterCallback({ | |
nestContext: context, | |
args: context.getArgs(), | |
result, | |
}); | |
} | |
}), | |
catchError((err) => { | |
const callback = this.onError; | |
const metadata = { | |
nestContext: context, | |
args: context.getArgs(), | |
error: err, | |
methodName, | |
className, | |
}; | |
Logger.error( | |
{ | |
methodName, | |
className, | |
errorMessage: err?.message, | |
args_received: metadata.args[0], | |
}, | |
null, | |
`error_interceptor#${className}:${methodName}` | |
); | |
if (isFunction(callback)) { | |
callback(metadata); | |
} | |
throw err; | |
}) | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable, Logger } from "@nestjs/common"; | |
import { BaseInterceptor } from "@connector"; | |
@Injectable() | |
export class Interceptor extends BaseInterceptor { | |
constructor(private readonly messageBus: MessageBus) { | |
super(); | |
} | |
before = { | |
createUser: async ({ args }): Promise<void> => { | |
const isAuthorized = await this.onlyUserAuthorized(args); | |
if (!isAuthorized) throwError(Errors.NOT_AUTHORIZED); | |
} | |
}; | |
after = { | |
createUser: async ({result}) => { | |
this.messageBus.publish(new UserCreated(result.id)) | |
} | |
} | |
onError = ({ error, methodName }): void => { | |
const { code, description, details, message } = error ?? {}; | |
Logger.error({ code, description, details, message }, null, methodName); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment