It can take time to create a new nestjs project and make all settings and install the packages. That's why I made this starter kit.
- Authentication
- Role based authorization
- Refresh token operations
- Session verify and token management from database
- Logout function for killing session
- Mysql connection (another driver can be used easily)
- Auto load & sync entities
- Eslint
- Swagger (persistAuthorization)
- Env settings (local and dev)
- Debug settings
- Validation setted up and contains sample codes
- Response Format
- Access token, username are indexed for quick access
The project is using the current lts version node.js 18.12.1 and nestjs 9.1.5. First of all, if you have nvm, let's make sure you are using version 18.12.1
nvm install 18.12.1
nvm use 18.12.1
To install all packages
npm install
To upgrade all packages to current versions
npm update
npm i -g npm-check-updates && ncu -u && npm i
To enable bearer token sending with Swagger, you must put the following tag at the beginning of the controller
@ApiBearerAuth()
Using the Roles decorator, you can specify the user roles that can access those controls.
@Roles(Role.Admin, Role.User)
@Get('me')
async getProfile(@Req() req) {
const response = await this.usersService.findMeById(req.user.id);
return new ResponseDto(response);
}
All remaining functions are public. You don't need to use @public decorator.
You can return responseDto when returning data in the controller to have a uniform response format
const response = await this.authService.getAccessToken(
req.params['refreshToken'],
);
return new ResponseDto(response, 'Access token retrieved');
return new ResponseDto(response);
// returns 'ok' message and statusCode:200
return new ResponseDto(response, 'Access token retrieved');
// returns custom message and statusCode:200
return new ResponseDto(null, 'Access token cannot retrieved', HttpStatus.BAD_REQUEST);
// returns custom message and
statusCode:400
Response Example:
{
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InN0cmluZyIsInN1YiI6MSwiY3JlYXRlZEF0IjoiMjAyMi0xMS0xMFQxMDo1MDo1MS41MzBaIiwiaWF0IjoxNjY4MTU1MTQ0LCJleHAiOjE2NjgyNDUxNDR9.Xf6AKBTgx6NPXtP7WsqvUJMYdvpUZ_9zZvTTfZpxJyA",
"refreshToken": "c1cb305691112804f045af444fc39a41876bfec25aa544d4cb1ab4e94b05693f743d9c2548afc9c92a8e555777c6bbc50a97fe3bf8fab30eac581e8c42031b0f",
"expiresAt": "2022-11-12T09:25:44.918Z",
"expiresRefreshAt": "2022-12-11T08:25:44.918Z"
},
"message": "Login informations are retrived",
"statusCode": 200
}
Sometimes you may not need to return all objects of a data (Ex. password). In such a case, create a response object and use '?' for allow null.
const result: User = await this.usersRepository.findOne({ where: { id: id } });
return new MeResponseDto(result);
export class MeResponseDto {
constructor(payload: any) {
this.id = payload?.id;
this.username = payload?.username;
this.role = payload?.role;
}
id: number;
username: string;
role: string;
}
More info: https://github.com/typestack/class-validator
It is not efficient to constantly call up data that is not always needed (Eager loading). In such cases lazy loading can be used
More info: https://orkhan.gitbook.io/typeorm/docs/eager-and-lazy-relations#lazy-relations