I want to handle exceptions properly in my NestJS app. I have watched videos, read blogs and found some answers on stackoverflow but it is too confusing for me to implement proper exception handling.
The login method in user microservice(controller):
@GrpcMethod('UserService', 'Login')
async login(@Payload() payload: Login): Promise<any> {
try {
const { email, password } = payload;
const { user, token, refreshToken } = await this.usersService.login(email, password);
return {
user: {
email: user.email,
userId: user.id,
name: user.name,
phone: user.phone,
},
token,
refreshToken,
};
} catch (error) {
throw new RpcException(error);
}
}
The login method in user microservice(service) along with find user by email:
async findByEmail(email: string): Promise<any> {
const user = this.userModel.findOne({ email }).exec();
if (!user) return 'User not found!!';
return user;
}
async login(email: string, password: string): Promise<any> {
try {
const user = (await this.findByEmail(email)) as User;
const comparePassword = await passwordService.comparePasswords(password, user.password);
if (user && comparePassword) {
const { token, refreshToken } = await this.sessionService.createSession(user._id, {
userId: user._id,
type: user.type,
});
return { user, token, refreshToken };
}
} catch (error) {
throw new Error(error);
}
}
The controller method in API gateway file:
@Post('login')
async login(@Body() loginData: Login): Promise<any> {
try {
const user = await firstValueFrom(this.userService.Login(loginData));
return sendSuccess(user, 'Log-in successful.');
} catch (error) {
return sendError(error.details, 404);
}
}
I want to handle all the exceptions and throw appropriate exception. like if email is not registered then throw "Email not found" if password is wrong then throw "invalid credentials" and so on. How can I do that?
the request-response utility code:
export function sendSuccess<T>(data: T, message: string = 'Success', statusCode: number = HttpStatus.OK): ApiResponse<T> {
return {
status: 'success',
statusCode,
message,
data,
};
}
export function sendError<T>(message: string, statusCode: number): ApiResponse<T> {
return {
status: 'error',
statusCode,
message,
data: null,
};
}
export interface ApiResponse<T> {
status: 'success' | 'error';
statusCode: number;
message: string;
data: T | null;
}
@Catch()
export class AllExceptionsFilter {
catch(exception: any, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const status = exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR;
const message = exception instanceof HttpException ? exception.message : 'Internal Server Error';
response.status(status).json(sendError(message, status));
}
}
I have registered AllExceptionsFilter in my main.ts file: app.useGlobalFilters(new AllExceptionsFilter());
but it never gets there.