Skip to content

Instantly share code, notes, and snippets.

@aleksandar-b
Last active March 24, 2022 06:13
Show Gist options
  • Save aleksandar-b/279fbf30fd4127882bd2dac4b9b87eb2 to your computer and use it in GitHub Desktop.
Save aleksandar-b/279fbf30fd4127882bd2dac4b9b87eb2 to your computer and use it in GitHub Desktop.
Interceptor wrapper for NestJs
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;
})
);
}
}
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