I'm working on a backend using NestJS, (which is amazing btw). I have a 'standard get a single instance of an entity situation' similar to this example below.
@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) {}
..
..
..
@Get(':id')
async findOneById(@Param() params): Promise<User> {
return userService.findOneById(params.id);
}
This is incredibly simple and works - however, if the user does not exist, the service returns undefined and the controller returns a 200 status code and an empty response.
In order to make the controller return a 404, I came up with the following:
@Get(':id')
async findOneById(@Res() res, @Param() params): Promise<User> {
const user: User = await this.userService.findOneById(params.id);
if (user === undefined) {
res.status(HttpStatus.NOT_FOUND).send();
}
else {
res.status(HttpStatus.OK).json(user).send();
}
}
..
..
This works, but is a lot more code-y (yes it can be refactored).
This could really use a decorator to handle this situation:
@Get(':id')
@OnUndefined(404)
async findOneById(@Param() params): Promise<User> {
return userService.findOneById(params.id);
}
Anyone aware of a decorator that does this, or a better solution than the one above?
The shortest way to do this would be
There is no point in decorator here because it would have the same code.
Note:
BadRequestException
is imported from@nestjs/common
;Edit
After some time with, I came with another solution, which is a decorator in the DTO:
Then in your DTO:
Hope it helps someone.
There is no built-in decorator for this, but you can create an interceptor that checks the return value and throws a
NotFoundException
onundefined
:Interceptor
Then you can use the
Interceptor
by adding it to either a single endpoint:or all endpoints of your
Controller
:Dynamic Interceptor
You can also pass values to your interceptor to customize its behavior per endpoint.
Pass the parameters in the constructor:
and then create the interceptor with
new
: