The Conventional Commits specification should be followed using the following types:
Type | Related Changes |
---|---|
test |
Adding or updating unit tests |
feat |
Introducing new feature |
fix |
Fixing a bug |
refactor |
Code change that neither fixes a bug nor adds a feature |
ci |
Updating GitHub Actions workflow or adding new one |
chore |
Changes not related to application code, like updating README |
- The GitHub Workflow should be followed.
- PRs should be Squashed and Merged into master.
- It's preferred to enable auto merge on your PRs.
DTO stands for Data Transfer Object, keep in mind that they're the interface to the Api.
-
Request DTO: Make sure you to receive exactly what you expect, no more or less.
-
Response DTO: Expose only the set of attributes needed from persistence entities.
As we use Prisma, every model from Prisma schema is translated into a dedicated TypeScript type, so we can derive our DTOs from those types using Utility Types feature in Typescript
Example
import { User } from '@prisma/client';
export class LoginUserDto implements Pick<User, 'email' | 'password'> {}
export class RegisterUserDto implements Omit<User, 'id'> {}
- Annotate DTO class properties you want to validate with class-validator decorators.
- Extend DTOs from each other when it's possible; to minimize duplication of boilerplate code used for validation.
Example
import { IsString, Length, IsEmail, MinLength } from 'class-validator';
export class UserLoginDto {
@IsEmail()
email: string;
@MinLength(8)
password: string;
}
export class UserRegisterDto extends UserLoginDto {
@IsString()
@Length(10, 20) // match with database scheme
name: string;
@IsPhoneNumber()
phone_number: string;
}
OpenApi (Swagger) Guidelines
-
Follow the convention
.*.dto.ts
for DTO classes so they can be recognized by Swagger. -
Annotate controllers with
@ApiTags('CONTROLLER_NAME')
for better categorization. -
Annotate controller methods with:
@ApiOperation({ summary })
decorator describing the method's purpose.- Multiple
@ApiResponse({ status, description, type (if exist and not an exception response) })
decorators according to the possible responses. @ApiResponse({ status: HttpStatus.UNPROCESSABLE_ENTITY, description: 'Validation Failed' })
on all controller methods as we have a Pipe that validates all request bodies.- All Swagger decorators must be put after the HTTP request method decorator [e.g.
@Post()
]
Example
@Post()
@ApiOperation({ summary: 'Creates a new user' })
@ApiResponse({
status: HttpStatus.CREATED,
description: 'The user has been successfully created.',
type: UserDto,
})
@ApiResponse({
status: HttpStatus.UNPROCESSABLE_ENTITY,
description: 'Validation Failed',
})
async createUser(@Body() createUserRequestDto: CreateUserRequestDto): Promise<UserDto>