nestforge-generator 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/README.md +13 -1
  2. package/README.pt-BR.md +13 -1
  3. package/dist/features/auth-strategy.js +7 -7
  4. package/dist/features/dependencies.js +3 -3
  5. package/dist/features/language.js +1 -1
  6. package/dist/features/language.js.map +1 -1
  7. package/dist/features/markers.js +11 -11
  8. package/dist/features/markers.js.map +1 -1
  9. package/dist/generator.js +7 -1
  10. package/dist/generator.js.map +1 -1
  11. package/dist/index.js +4 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/project-name.js +50 -0
  14. package/dist/project-name.js.map +1 -0
  15. package/dist/prompts.js +12 -10
  16. package/dist/prompts.js.map +1 -1
  17. package/package.json +1 -1
  18. package/templates/drizzle/drizzle.config.ts +2 -2
  19. package/templates/drizzle/src/auth/auth.controller.ts +35 -35
  20. package/templates/drizzle/src/auth/auth.service.spec.ts +4 -4
  21. package/templates/drizzle/src/auth/auth.service.ts +9 -9
  22. package/templates/drizzle/src/auth/dto/forgot-password.dto.ts +2 -2
  23. package/templates/drizzle/src/auth/dto/login.dto.ts +3 -3
  24. package/templates/drizzle/src/auth/dto/register.dto.ts +4 -4
  25. package/templates/drizzle/src/auth/dto/reset-password.dto.ts +3 -3
  26. package/templates/drizzle/src/auth/guards/github-auth.guard.ts +2 -2
  27. package/templates/drizzle/src/auth/guards/google-auth.guard.ts +2 -2
  28. package/templates/drizzle/src/auth/guards/session-auth.guard.spec.ts +4 -4
  29. package/templates/drizzle/src/auth/guards/session-auth.guard.ts +2 -2
  30. package/templates/drizzle/src/auth/session.service.spec.ts +5 -5
  31. package/templates/drizzle/src/auth/session.service.ts +5 -5
  32. package/templates/drizzle/src/auth/strategies/github.strategy.ts +3 -3
  33. package/templates/drizzle/src/auth/token.service.ts +3 -3
  34. package/templates/drizzle/src/common/filters/http-exception.filter.ts +1 -1
  35. package/templates/drizzle/src/common/guards/permissions.guard.spec.ts +7 -7
  36. package/templates/drizzle/src/common/guards/roles.guard.spec.ts +4 -4
  37. package/templates/drizzle/src/common/middleware/csrf.middleware.spec.ts +5 -5
  38. package/templates/drizzle/src/common/middleware/csrf.middleware.ts +2 -2
  39. package/templates/drizzle/src/common/utils/avatar-storage.util.ts +2 -2
  40. package/templates/drizzle/src/config/env.validation.ts +1 -1
  41. package/templates/drizzle/src/database/seed.ts +4 -4
  42. package/templates/drizzle/src/health/health.controller.ts +2 -2
  43. package/templates/drizzle/src/health/indicators/drizzle-health.indicator.spec.ts +5 -5
  44. package/templates/drizzle/src/health/indicators/drizzle-health.indicator.ts +2 -2
  45. package/templates/drizzle/src/health/indicators/redis-health.indicator.spec.ts +5 -5
  46. package/templates/drizzle/src/health/indicators/redis-health.indicator.ts +3 -3
  47. package/templates/drizzle/src/mail/mail.processor.ts +4 -4
  48. package/templates/drizzle/src/mail/templates/email-templates.ts +7 -7
  49. package/templates/drizzle/src/metrics/metrics.service.ts +3 -3
  50. package/templates/drizzle/src/users/dto/create-user.dto.ts +5 -5
  51. package/templates/drizzle/src/users/dto/find-users-query.dto.ts +3 -3
  52. package/templates/drizzle/src/users/users.controller.ts +21 -21
  53. package/templates/drizzle/src/users/users.service.spec.ts +12 -12
  54. package/templates/drizzle/src/users/users.service.ts +4 -4
  55. package/templates/drizzle/test/auth.e2e-spec.ts +8 -8
  56. package/templates/drizzle/test/session-auth.e2e-spec.ts +9 -9
  57. package/templates/drizzle/test/users.e2e-spec.ts +18 -18
  58. package/templates/prisma/prisma/seed.ts +46 -46
  59. package/templates/prisma/src/auth/auth.controller.ts +35 -35
  60. package/templates/prisma/src/auth/auth.service.spec.ts +3 -3
  61. package/templates/prisma/src/auth/auth.service.ts +11 -11
  62. package/templates/prisma/src/auth/dto/forgot-password.dto.ts +2 -2
  63. package/templates/prisma/src/auth/dto/login.dto.ts +3 -3
  64. package/templates/prisma/src/auth/dto/register.dto.ts +4 -4
  65. package/templates/prisma/src/auth/dto/reset-password.dto.ts +3 -3
  66. package/templates/prisma/src/auth/guards/github-auth.guard.ts +10 -10
  67. package/templates/prisma/src/auth/guards/google-auth.guard.ts +10 -10
  68. package/templates/prisma/src/auth/guards/session-auth.guard.spec.ts +4 -4
  69. package/templates/prisma/src/auth/guards/session-auth.guard.ts +2 -2
  70. package/templates/prisma/src/auth/session.service.spec.ts +5 -5
  71. package/templates/prisma/src/auth/session.service.ts +5 -5
  72. package/templates/prisma/src/auth/strategies/github.strategy.ts +3 -3
  73. package/templates/prisma/src/auth/token.service.ts +2 -2
  74. package/templates/prisma/src/common/filters/http-exception.filter.ts +34 -34
  75. package/templates/prisma/src/common/guards/permissions.guard.spec.ts +7 -7
  76. package/templates/prisma/src/common/guards/roles.guard.spec.ts +4 -4
  77. package/templates/prisma/src/common/middleware/csrf.middleware.spec.ts +5 -5
  78. package/templates/prisma/src/common/middleware/csrf.middleware.ts +2 -2
  79. package/templates/prisma/src/common/utils/avatar-storage.util.ts +32 -32
  80. package/templates/prisma/src/config/env.validation.ts +1 -1
  81. package/templates/prisma/src/health/health.controller.ts +2 -2
  82. package/templates/prisma/src/health/indicators/prisma-health.indicator.spec.ts +4 -4
  83. package/templates/prisma/src/health/indicators/prisma-health.indicator.ts +1 -1
  84. package/templates/prisma/src/health/indicators/redis-health.indicator.spec.ts +5 -5
  85. package/templates/prisma/src/health/indicators/redis-health.indicator.ts +3 -3
  86. package/templates/prisma/src/mail/mail.processor.ts +4 -4
  87. package/templates/prisma/src/mail/templates/email-templates.ts +7 -7
  88. package/templates/prisma/src/metrics/metrics.service.ts +34 -34
  89. package/templates/prisma/src/users/dto/create-user.dto.ts +12 -12
  90. package/templates/prisma/src/users/dto/find-users-query.dto.ts +12 -12
  91. package/templates/prisma/src/users/users.controller.ts +21 -21
  92. package/templates/prisma/src/users/users.service.spec.ts +11 -11
  93. package/templates/prisma/src/users/users.service.ts +4 -4
  94. package/templates/prisma/test/auth.e2e-spec.ts +8 -8
  95. package/templates/prisma/test/session-auth.e2e-spec.ts +9 -9
  96. package/templates/prisma/test/users.e2e-spec.ts +14 -14
  97. package/templates/typeorm/src/auth/auth.controller.ts +35 -35
  98. package/templates/typeorm/src/auth/auth.service.spec.ts +4 -4
  99. package/templates/typeorm/src/auth/auth.service.ts +9 -9
  100. package/templates/typeorm/src/auth/dto/forgot-password.dto.ts +2 -2
  101. package/templates/typeorm/src/auth/dto/login.dto.ts +3 -3
  102. package/templates/typeorm/src/auth/dto/register.dto.ts +4 -4
  103. package/templates/typeorm/src/auth/dto/reset-password.dto.ts +3 -3
  104. package/templates/typeorm/src/auth/guards/github-auth.guard.ts +2 -2
  105. package/templates/typeorm/src/auth/guards/google-auth.guard.ts +2 -2
  106. package/templates/typeorm/src/auth/guards/session-auth.guard.spec.ts +4 -4
  107. package/templates/typeorm/src/auth/guards/session-auth.guard.ts +2 -2
  108. package/templates/typeorm/src/auth/session.service.spec.ts +5 -5
  109. package/templates/typeorm/src/auth/session.service.ts +5 -5
  110. package/templates/typeorm/src/auth/strategies/github.strategy.ts +3 -3
  111. package/templates/typeorm/src/auth/token.service.ts +3 -3
  112. package/templates/typeorm/src/common/filters/http-exception.filter.ts +1 -1
  113. package/templates/typeorm/src/common/guards/permissions.guard.spec.ts +7 -7
  114. package/templates/typeorm/src/common/guards/roles.guard.spec.ts +4 -4
  115. package/templates/typeorm/src/common/middleware/csrf.middleware.spec.ts +5 -5
  116. package/templates/typeorm/src/common/middleware/csrf.middleware.ts +2 -2
  117. package/templates/typeorm/src/common/utils/avatar-storage.util.ts +2 -2
  118. package/templates/typeorm/src/config/env.validation.ts +1 -1
  119. package/templates/typeorm/src/database/data-source.ts +2 -2
  120. package/templates/typeorm/src/database/seed.ts +3 -3
  121. package/templates/typeorm/src/database/typeorm-options.ts +2 -2
  122. package/templates/typeorm/src/health/health.controller.ts +2 -2
  123. package/templates/typeorm/src/health/indicators/redis-health.indicator.spec.ts +5 -5
  124. package/templates/typeorm/src/health/indicators/redis-health.indicator.ts +3 -3
  125. package/templates/typeorm/src/health/indicators/typeorm-health.indicator.spec.ts +4 -4
  126. package/templates/typeorm/src/health/indicators/typeorm-health.indicator.ts +2 -2
  127. package/templates/typeorm/src/mail/mail.processor.ts +4 -4
  128. package/templates/typeorm/src/mail/templates/email-templates.ts +7 -7
  129. package/templates/typeorm/src/metrics/metrics.service.ts +3 -3
  130. package/templates/typeorm/src/users/dto/create-user.dto.ts +5 -5
  131. package/templates/typeorm/src/users/dto/find-users-query.dto.ts +3 -3
  132. package/templates/typeorm/src/users/users.controller.ts +21 -21
  133. package/templates/typeorm/src/users/users.service.spec.ts +12 -12
  134. package/templates/typeorm/src/users/users.service.ts +4 -4
  135. package/templates/typeorm/test/auth.e2e-spec.ts +8 -8
  136. package/templates/typeorm/test/session-auth.e2e-spec.ts +9 -9
  137. package/templates/typeorm/test/users.e2e-spec.ts +18 -18
@@ -57,9 +57,9 @@ export class UsersController {
57
57
  @Permissions(Permission.UserCreate)
58
58
  // nestforge:feature:rbac:end
59
59
  // nestforge:feature:swagger
60
- @ApiOperation({ summary: 'Cria um usuário (requer permissão user:create)' })
61
- @ApiResponse({ status: 201, description: 'Usuário criado', schema: { example: USER_EXAMPLE } })
62
- @ApiResponse({ status: 403, description: 'Sem a permissão user:create', schema: { example: FORBIDDEN_EXAMPLE } })
60
+ @ApiOperation({ summary: 'Creates a user (requires the user:create permission)' })
61
+ @ApiResponse({ status: 201, description: 'User created', schema: { example: USER_EXAMPLE } })
62
+ @ApiResponse({ status: 403, description: 'Missing the user:create permission', schema: { example: FORBIDDEN_EXAMPLE } })
63
63
  // nestforge:feature:swagger:end
64
64
  create(@Body() dto: CreateUserDto) {
65
65
  return this.usersService.create(dto);
@@ -70,10 +70,10 @@ export class UsersController {
70
70
  @Permissions(Permission.UserRead)
71
71
  // nestforge:feature:rbac:end
72
72
  // nestforge:feature:swagger
73
- @ApiOperation({ summary: 'Lista usuários com paginação e filtros (requer permissão user:read)' })
73
+ @ApiOperation({ summary: 'Lists users with pagination and filters (requires the user:read permission)' })
74
74
  @ApiResponse({
75
75
  status: 200,
76
- description: 'Lista paginada',
76
+ description: 'Paginated list',
77
77
  schema: {
78
78
  example: {
79
79
  data: [USER_EXAMPLE],
@@ -88,8 +88,8 @@ export class UsersController {
88
88
 
89
89
  @Get('me')
90
90
  // nestforge:feature:swagger
91
- @ApiOperation({ summary: 'Retorna o usuário autenticado' })
92
- @ApiResponse({ status: 200, description: 'Usuário autenticado', schema: { example: USER_EXAMPLE } })
91
+ @ApiOperation({ summary: 'Returns the authenticated user' })
92
+ @ApiResponse({ status: 200, description: 'Authenticated user', schema: { example: USER_EXAMPLE } })
93
93
  // nestforge:feature:swagger:end
94
94
  findMe(@CurrentUser() user: { id: string }) {
95
95
  return this.usersService.findOne(user.id);
@@ -97,17 +97,17 @@ export class UsersController {
97
97
 
98
98
  @Post('me/avatar')
99
99
  // nestforge:feature:swagger
100
- @ApiOperation({ summary: 'Faz upload do avatar do usuário autenticado' })
100
+ @ApiOperation({ summary: 'Uploads an avatar for the authenticated user' })
101
101
  @ApiConsumes('multipart/form-data')
102
102
  @ApiResponse({
103
103
  status: 201,
104
- description: 'Avatar atualizado',
104
+ description: 'Avatar updated',
105
105
  schema: { example: { ...USER_EXAMPLE, avatarUrl: '/uploads/avatars/f47ac10b.png' } },
106
106
  })
107
107
  @ApiResponse({
108
108
  status: 400,
109
- description: 'Formato de imagem não suportado ou arquivo maior que 2MB',
110
- schema: { example: { statusCode: 400, message: 'Formato de imagem não suportado (use PNG, JPEG ou WEBP)' } },
109
+ description: 'Unsupported image format or file larger than 2 MB',
110
+ schema: { example: { statusCode: 400, message: 'Unsupported image format (use PNG, JPEG, or WEBP)' } },
111
111
  })
112
112
  // nestforge:feature:swagger:end
113
113
  @UseInterceptors(
@@ -129,9 +129,9 @@ export class UsersController {
129
129
  @Permissions(Permission.UserRead)
130
130
  // nestforge:feature:rbac:end
131
131
  // nestforge:feature:swagger
132
- @ApiOperation({ summary: 'Busca um usuário por id (requer permissão user:read)' })
133
- @ApiResponse({ status: 200, description: 'Usuário encontrado', schema: { example: USER_EXAMPLE } })
134
- @ApiResponse({ status: 404, description: 'Usuário não encontrado', schema: { example: { statusCode: 404, message: 'Usuário não encontrado' } } })
132
+ @ApiOperation({ summary: 'Finds a user by ID (requires the user:read permission)' })
133
+ @ApiResponse({ status: 200, description: 'User found', schema: { example: USER_EXAMPLE } })
134
+ @ApiResponse({ status: 404, description: 'User not found', schema: { example: { statusCode: 404, message: 'User not found' } } })
135
135
  // nestforge:feature:swagger:end
136
136
  findOne(@Param('id') id: string) {
137
137
  return this.usersService.findOne(id);
@@ -142,9 +142,9 @@ export class UsersController {
142
142
  @Permissions(Permission.UserUpdate)
143
143
  // nestforge:feature:rbac:end
144
144
  // nestforge:feature:swagger
145
- @ApiOperation({ summary: 'Atualiza um usuário (requer permissão user:update)' })
146
- @ApiResponse({ status: 200, description: 'Usuário atualizado', schema: { example: USER_EXAMPLE } })
147
- @ApiResponse({ status: 403, description: 'Sem a permissão user:update', schema: { example: FORBIDDEN_EXAMPLE } })
145
+ @ApiOperation({ summary: 'Updates a user (requires the user:update permission)' })
146
+ @ApiResponse({ status: 200, description: 'User updated', schema: { example: USER_EXAMPLE } })
147
+ @ApiResponse({ status: 403, description: 'Missing the user:update permission', schema: { example: FORBIDDEN_EXAMPLE } })
148
148
  // nestforge:feature:swagger:end
149
149
  update(@Param('id') id: string, @Body() dto: UpdateUserDto) {
150
150
  return this.usersService.update(id, dto);
@@ -155,11 +155,11 @@ export class UsersController {
155
155
  @Permissions(Permission.UserDelete)
156
156
  // nestforge:feature:rbac:end
157
157
  // nestforge:feature:swagger
158
- @ApiOperation({ summary: 'Remove um usuário (requer permissão user:delete)' })
159
- @ApiResponse({ status: 200, description: 'Usuário removido', schema: { example: { message: 'Usuário removido com sucesso' } } })
160
- @ApiResponse({ status: 403, description: 'Sem a permissão user:delete', schema: { example: FORBIDDEN_EXAMPLE } })
158
+ @ApiOperation({ summary: 'Deletes a user (requires the user:delete permission)' })
159
+ @ApiResponse({ status: 200, description: 'User deleted', schema: { example: { message: 'User deleted successfully' } } })
160
+ @ApiResponse({ status: 403, description: 'Missing the user:delete permission', schema: { example: FORBIDDEN_EXAMPLE } })
161
161
  // nestforge:feature:swagger:end
162
162
  remove(@Param('id') id: string) {
163
163
  return this.usersService.remove(id);
164
164
  }
165
- }
165
+ }
@@ -37,35 +37,35 @@ describe('UsersService', () => {
37
37
  usersService = new UsersService(prisma as PrismaService);
38
38
  });
39
39
 
40
- it('deve lançar ConflictException se o e-mail já existir ao criar', async () => {
40
+ it('throws ConflictException when the email already exists during creation', async () => {
41
41
  prisma.user.findUnique.mockResolvedValue(mockUser);
42
42
 
43
43
  await expect(
44
- usersService.create({ name: 'Jeiel', email: 'jeiel@example.com', password: 'senhaForte123' }),
44
+ usersService.create({ name: 'Jeiel', email: 'jeiel@example.com', password: 'strongPassword123' }),
45
45
  ).rejects.toBeInstanceOf(ConflictException);
46
46
  });
47
47
 
48
- it('deve criar um usuário e esconder o passwordHash na serialização', async () => {
48
+ it('creates a user and hides passwordHash during serialization', async () => {
49
49
  prisma.user.findUnique.mockResolvedValue(null);
50
50
  prisma.user.create.mockResolvedValue(mockUser);
51
51
 
52
52
  const result = await usersService.create({
53
53
  name: 'Jeiel',
54
54
  email: 'jeiel@example.com',
55
- password: 'senhaForte123',
55
+ password: 'strongPassword123',
56
56
  });
57
57
 
58
58
  expect(result.email).toBe('jeiel@example.com');
59
59
  expect(instanceToPlain(result)).not.toHaveProperty('passwordHash');
60
60
  });
61
61
 
62
- it('deve lançar NotFoundException se o usuário não existir', async () => {
62
+ it('throws NotFoundException when the user does not exist', async () => {
63
63
  prisma.user.findUnique.mockResolvedValue(null);
64
64
 
65
65
  await expect(usersService.findOne('id-invalido')).rejects.toBeInstanceOf(NotFoundException);
66
66
  });
67
67
 
68
- it('deve retornar dados paginados em findAll', async () => {
68
+ it('returns paginated data from findAll', async () => {
69
69
  prisma.user.findMany.mockResolvedValue([mockUser]);
70
70
  prisma.user.count.mockResolvedValue(1);
71
71
 
@@ -75,7 +75,7 @@ describe('UsersService', () => {
75
75
  expect(result.data).toHaveLength(1);
76
76
  });
77
77
 
78
- it('deve atualizar um usuário existente', async () => {
78
+ it('updates an existing user', async () => {
79
79
  prisma.user.findUnique.mockResolvedValue(mockUser);
80
80
  prisma.user.update.mockResolvedValue({ ...mockUser, name: 'Novo Nome' });
81
81
 
@@ -84,16 +84,16 @@ describe('UsersService', () => {
84
84
  expect(result.name).toBe('Novo Nome');
85
85
  });
86
86
 
87
- it('deve remover um usuário existente', async () => {
87
+ it('deletes an existing user', async () => {
88
88
  prisma.user.findUnique.mockResolvedValue(mockUser);
89
89
  prisma.user.delete.mockResolvedValue(mockUser);
90
90
 
91
91
  const result = await usersService.remove('user-1');
92
92
 
93
- expect(result).toEqual({ message: 'Usuário removido com sucesso' });
93
+ expect(result).toEqual({ message: 'User deleted successfully' });
94
94
  });
95
95
 
96
- it('deve atualizar o avatar de um usuário', async () => {
96
+ it('updates a user avatar', async () => {
97
97
  prisma.user.findUnique.mockResolvedValue(mockUser);
98
98
  prisma.user.update.mockResolvedValue({ ...mockUser, avatarUrl: '/uploads/avatars/x.png' });
99
99
 
@@ -101,4 +101,4 @@ describe('UsersService', () => {
101
101
 
102
102
  expect(result.avatarUrl).toBe('/uploads/avatars/x.png');
103
103
  });
104
- });
104
+ });
@@ -14,7 +14,7 @@ export class UsersService {
14
14
  async create(dto: CreateUserDto) {
15
15
  const existing = await this.prisma.user.findUnique({ where: { email: dto.email } });
16
16
  if (existing) {
17
- throw new ConflictException('E-mail já cadastrado');
17
+ throw new ConflictException('Email already registered');
18
18
  }
19
19
 
20
20
  const passwordHash = await bcrypt.hash(dto.password, 10);
@@ -79,7 +79,7 @@ export class UsersService {
79
79
  async findOne(id: string) {
80
80
  const user = await this.prisma.user.findUnique({ where: { id } });
81
81
  if (!user) {
82
- throw new NotFoundException('Usuário não encontrado');
82
+ throw new NotFoundException('User not found');
83
83
  }
84
84
  return new UserEntity(user);
85
85
  }
@@ -100,7 +100,7 @@ export class UsersService {
100
100
  async remove(id: string) {
101
101
  await this.findOne(id);
102
102
  await this.prisma.user.delete({ where: { id } });
103
- return { message: 'Usuário removido com sucesso' };
103
+ return { message: 'User deleted successfully' };
104
104
  }
105
105
 
106
106
  async updateAvatar(id: string, avatarUrl: string) {
@@ -111,4 +111,4 @@ export class UsersService {
111
111
  });
112
112
  return new UserEntity(user);
113
113
  }
114
- }
114
+ }
@@ -23,12 +23,12 @@ describe('Auth (e2e)', () => {
23
23
  await app.close();
24
24
  });
25
25
 
26
- it('deve registrar, logar, renovar e revogar o token', async () => {
26
+ it('registers, logs in, refreshes, and revokes the token', async () => {
27
27
  const server = app.getHttpServer();
28
28
 
29
29
  const registerResponse = await request(server)
30
30
  .post('/auth/register')
31
- .send({ name: 'Jeiel', email: 'jeiel.e2e@example.com', password: 'senhaForte123' })
31
+ .send({ name: 'Jeiel', email: 'jeiel.e2e@example.com', password: 'strongPassword123' })
32
32
  .expect(201);
33
33
 
34
34
  expect(registerResponse.body).toHaveProperty('accessToken');
@@ -36,7 +36,7 @@ describe('Auth (e2e)', () => {
36
36
 
37
37
  const loginResponse = await request(server)
38
38
  .post('/auth/login')
39
- .send({ email: 'jeiel.e2e@example.com', password: 'senhaForte123' })
39
+ .send({ email: 'jeiel.e2e@example.com', password: 'strongPassword123' })
40
40
  .expect(200);
41
41
 
42
42
  const refreshResponse = await request(server)
@@ -51,25 +51,25 @@ describe('Auth (e2e)', () => {
51
51
  .send({ refreshToken: refreshResponse.body.refreshToken })
52
52
  .expect(200);
53
53
 
54
- // o refresh token já foi revogado no logout, então não pode ser reutilizado
54
+ // The refresh token was revoked during logout and cannot be reused.
55
55
  await request(server)
56
56
  .post('/auth/refresh')
57
57
  .send({ refreshToken: refreshResponse.body.refreshToken })
58
58
  .expect(401);
59
59
  });
60
60
 
61
- it('não deve permitir cadastro com e-mail duplicado', async () => {
61
+ it('rejects registration with a duplicate email', async () => {
62
62
  const server = app.getHttpServer();
63
- const payload = { name: 'Jeiel', email: 'duplicado.e2e@example.com', password: 'senhaForte123' };
63
+ const payload = { name: 'Jeiel', email: 'duplicate.e2e@example.com', password: 'strongPassword123' };
64
64
 
65
65
  await request(server).post('/auth/register').send(payload).expect(201);
66
66
  await request(server).post('/auth/register').send(payload).expect(409);
67
67
  });
68
68
 
69
- it('deve rejeitar login com credenciais inválidas', async () => {
69
+ it('rejects login with invalid credentials', async () => {
70
70
  await request(app.getHttpServer())
71
71
  .post('/auth/login')
72
72
  .send({ email: 'naoexiste.e2e@example.com', password: 'qualquerSenha123' })
73
73
  .expect(401);
74
74
  });
75
- });
75
+ });
@@ -28,7 +28,7 @@ describe('Session auth (e2e)', () => {
28
28
  }
29
29
  })
30
30
 
31
- it('registra, autentica e encerra uma sessão protegida por CSRF', async () => {
31
+ it('registers, authenticates, and closes a CSRF-protected session', async () => {
32
32
  const agent = request.agent(app.getHttpServer());
33
33
 
34
34
  await agent
@@ -43,13 +43,13 @@ describe('Session auth (e2e)', () => {
43
43
 
44
44
  expect(csrfToken).toMatch(/^[a-f0-9]{64}$/);
45
45
 
46
- // Requisições que alteram estado devem ser rejeitadas sem o token.
46
+ // State-changing requests must be rejected without the token.
47
47
  await agent
48
48
  .post('/auth/register')
49
49
  .send({
50
50
  name: 'Jeiel',
51
51
  email: 'jeiel.session@example.com',
52
- password: 'senhaForte123',
52
+ password: 'strongPassword123',
53
53
  })
54
54
  .expect(403);
55
55
 
@@ -59,7 +59,7 @@ describe('Session auth (e2e)', () => {
59
59
  .send({
60
60
  name: 'Jeiel',
61
61
  email: 'jeiel.session@example.com',
62
- password: 'senhaForte123',
62
+ password: 'strongPassword123',
63
63
  })
64
64
  .expect(201);
65
65
 
@@ -97,7 +97,7 @@ describe('Session auth (e2e)', () => {
97
97
  .expect(401);
98
98
  });
99
99
 
100
- it('realiza login e renova o token CSRF da sessão', async () => {
100
+ it('logs in and refreshes the session CSRF token', async () => {
101
101
  const registrationAgent = request.agent(
102
102
  app.getHttpServer(),
103
103
  );
@@ -113,9 +113,9 @@ describe('Session auth (e2e)', () => {
113
113
  .post('/auth/register')
114
114
  .set('x-csrf-token', registrationCsrfToken)
115
115
  .send({
116
- name: 'Usuário de sessão',
116
+ name: 'Session User',
117
117
  email: 'login.session@example.com',
118
- password: 'senhaForte123',
118
+ password: 'strongPassword123',
119
119
  })
120
120
  .expect(201);
121
121
 
@@ -141,7 +141,7 @@ describe('Session auth (e2e)', () => {
141
141
  .set('x-csrf-token', loginCsrfToken)
142
142
  .send({
143
143
  email: 'login.session@example.com',
144
- password: 'senhaForte123',
144
+ password: 'strongPassword123',
145
145
  })
146
146
  .expect(200);
147
147
 
@@ -160,4 +160,4 @@ describe('Session auth (e2e)', () => {
160
160
  .get('/users/me')
161
161
  .expect(200);
162
162
  });
163
- });
163
+ });
@@ -13,7 +13,7 @@ describe('Users (e2e)', () => {
13
13
  async function createUserWithRole(email: string, password: string, role: Role) {
14
14
  const passwordHash = await bcrypt.hash(password, 10);
15
15
  await prisma.user.create({
16
- data: { name: 'Usuário de teste', email, passwordHash, role, emailVerifiedAt: new Date() },
16
+ data: { name: 'Test User', email, passwordHash, role, emailVerifiedAt: new Date() },
17
17
  });
18
18
  }
19
19
 
@@ -39,19 +39,19 @@ describe('Users (e2e)', () => {
39
39
  await app.close();
40
40
  });
41
41
 
42
- it('rejeita acesso sem token', async () => {
42
+ it('rejects access without a token', async () => {
43
43
  await request(app.getHttpServer()).get('/users').expect(401);
44
44
  });
45
45
 
46
- it('ADMIN consegue criar, listar, atualizar e remover um usuário', async () => {
47
- await createUserWithRole('admin.e2e@example.com', 'senhaForte123', Role.ADMIN);
48
- const token = await loginAndGetToken('admin.e2e@example.com', 'senhaForte123');
46
+ it('allows ADMIN to create, list, update, and delete a user', async () => {
47
+ await createUserWithRole('admin.e2e@example.com', 'strongPassword123', Role.ADMIN);
48
+ const token = await loginAndGetToken('admin.e2e@example.com', 'strongPassword123');
49
49
  const server = app.getHttpServer();
50
50
 
51
51
  const createResponse = await request(server)
52
52
  .post('/users')
53
53
  .set('Authorization', `Bearer ${token}`)
54
- .send({ name: 'Novo Usuário', email: 'novo.e2e@example.com', password: 'senhaForte123' })
54
+ .send({ name: 'New User', email: 'new.e2e@example.com', password: 'strongPassword123' })
55
55
  .expect(201);
56
56
 
57
57
  expect(createResponse.body).not.toHaveProperty('passwordHash');
@@ -77,9 +77,9 @@ describe('Users (e2e)', () => {
77
77
  });
78
78
 
79
79
  // nestforge:feature:rbac
80
- it('USER consegue ler mas não consegue criar usuário', async () => {
81
- await createUserWithRole('user.e2e@example.com', 'senhaForte123', Role.USER);
82
- const token = await loginAndGetToken('user.e2e@example.com', 'senhaForte123');
80
+ it('allows USER to read but not create users', async () => {
81
+ await createUserWithRole('user.e2e@example.com', 'strongPassword123', Role.USER);
82
+ const token = await loginAndGetToken('user.e2e@example.com', 'strongPassword123');
83
83
  const server = app.getHttpServer();
84
84
 
85
85
  await request(server).get('/users').set('Authorization', `Bearer ${token}`).expect(200);
@@ -87,14 +87,14 @@ describe('Users (e2e)', () => {
87
87
  await request(server)
88
88
  .post('/users')
89
89
  .set('Authorization', `Bearer ${token}`)
90
- .send({ name: 'Não deveria criar', email: 'bloqueado.e2e@example.com', password: 'senhaForte123' })
90
+ .send({ name: 'Should Not Be Created', email: 'blocked.e2e@example.com', password: 'strongPassword123' })
91
91
  .expect(403);
92
92
  });
93
93
  // nestforge:feature:rbac:end
94
94
 
95
- it('GET /users/me retorna o usuário autenticado', async () => {
96
- await createUserWithRole('me.e2e@example.com', 'senhaForte123', Role.USER);
97
- const token = await loginAndGetToken('me.e2e@example.com', 'senhaForte123');
95
+ it('returns the authenticated user from GET /users/me', async () => {
96
+ await createUserWithRole('me.e2e@example.com', 'strongPassword123', Role.USER);
97
+ const token = await loginAndGetToken('me.e2e@example.com', 'strongPassword123');
98
98
 
99
99
  const response = await request(app.getHttpServer())
100
100
  .get('/users/me')
@@ -103,4 +103,4 @@ describe('Users (e2e)', () => {
103
103
 
104
104
  expect(response.body.email).toBe('me.e2e@example.com');
105
105
  });
106
- });
106
+ });
@@ -52,10 +52,10 @@ export class AuthController {
52
52
  @Public()
53
53
  @Get('csrf-token')
54
54
  // nestforge:feature:swagger
55
- @ApiOperation({ summary: 'Emite um token CSRF vinculado à sessão' })
55
+ @ApiOperation({ summary: 'Issues a CSRF token bound to the session' })
56
56
  @ApiResponse({
57
57
  status: 200,
58
- description: 'Token CSRF emitido',
58
+ description: 'CSRF token issued',
59
59
  schema: {
60
60
  example: {
61
61
  csrfToken: 'a1b2c3d4e5f6...',
@@ -72,9 +72,9 @@ export class AuthController {
72
72
  @Public()
73
73
  @Post('register')
74
74
  // nestforge:feature:swagger
75
- @ApiOperation({ summary: 'Cria uma nova conta' })
76
- @ApiResponse({ status: 201, description: 'Conta criada com sucesso', schema: { example: TOKENS_EXAMPLE } })
77
- @ApiResponse({ status: 409, description: 'E-mail já cadastrado', schema: { example: { statusCode: 409, message: 'E-mail já cadastrado' } } })
75
+ @ApiOperation({ summary: 'Creates a new account' })
76
+ @ApiResponse({ status: 201, description: 'Account created successfully', schema: { example: TOKENS_EXAMPLE } })
77
+ @ApiResponse({ status: 409, description: 'Email already registered', schema: { example: { statusCode: 409, message: 'Email already registered' } } })
78
78
  // nestforge:feature:swagger:end
79
79
  async register(@Body() dto: RegisterDto) {
80
80
  const user = await this.authService.register(dto);
@@ -85,9 +85,9 @@ export class AuthController {
85
85
  @Post('login')
86
86
  @HttpCode(HttpStatus.OK)
87
87
  // nestforge:feature:swagger
88
- @ApiOperation({ summary: 'Autentica e retorna access/refresh token' })
89
- @ApiResponse({ status: 200, description: 'Login realizado com sucesso', schema: { example: TOKENS_EXAMPLE } })
90
- @ApiResponse({ status: 401, description: 'Credenciais inválidas', schema: { example: { statusCode: 401, message: 'Credenciais inválidas' } } })
88
+ @ApiOperation({ summary: 'Authenticates and returns access and refresh tokens' })
89
+ @ApiResponse({ status: 200, description: 'Login completed successfully', schema: { example: TOKENS_EXAMPLE } })
90
+ @ApiResponse({ status: 401, description: 'Invalid credentials', schema: { example: { statusCode: 401, message: 'Invalid credentials' } } })
91
91
  // nestforge:feature:swagger:end
92
92
  async login(@Body() dto: LoginDto) {
93
93
  const user = await this.authService.login(dto);
@@ -99,9 +99,9 @@ export class AuthController {
99
99
  @Public()
100
100
  @Post('register')
101
101
  // nestforge:feature:swagger
102
- @ApiOperation({ summary: 'Cria uma conta e inicia uma sessão' })
103
- @ApiResponse({ status: 201, description: 'Conta criada e sessão iniciada' })
104
- @ApiResponse({ status: 409, description: 'E-mail já cadastrado' })
102
+ @ApiOperation({ summary: 'Creates an account and starts a session' })
103
+ @ApiResponse({ status: 201, description: 'Account created and session started' })
104
+ @ApiResponse({ status: 409, description: 'Email already registered' })
105
105
  // nestforge:feature:swagger:end
106
106
  async registerWithSession(
107
107
  @Body() dto: RegisterDto,
@@ -115,9 +115,9 @@ export class AuthController {
115
115
  @Post('login')
116
116
  @HttpCode(HttpStatus.OK)
117
117
  // nestforge:feature:swagger
118
- @ApiOperation({ summary: 'Autentica e inicia uma sessão por cookie' })
119
- @ApiResponse({ status: 200, description: 'Sessão iniciada com sucesso' })
120
- @ApiResponse({ status: 401, description: 'Credenciais inválidas' })
118
+ @ApiOperation({ summary: 'Authenticates and starts a cookie-based session' })
119
+ @ApiResponse({ status: 200, description: 'Session started successfully' })
120
+ @ApiResponse({ status: 401, description: 'Invalid credentials' })
121
121
  // nestforge:feature:swagger:end
122
122
  async loginWithSession(
123
123
  @Body() dto: LoginDto,
@@ -130,8 +130,8 @@ export class AuthController {
130
130
  @Post('logout')
131
131
  @HttpCode(HttpStatus.OK)
132
132
  // nestforge:feature:swagger
133
- @ApiOperation({ summary: 'Encerra a sessão atual' })
134
- @ApiResponse({ status: 200, description: 'Sessão encerrada com sucesso' })
133
+ @ApiOperation({ summary: 'Ends the current session' })
134
+ @ApiResponse({ status: 200, description: 'Session ended successfully' })
135
135
  // nestforge:feature:swagger:end
136
136
  logoutSession(@Req() request: Request) {
137
137
  return this.sessionService.destroy(request);
@@ -143,9 +143,9 @@ export class AuthController {
143
143
  @Post('refresh')
144
144
  @HttpCode(HttpStatus.OK)
145
145
  // nestforge:feature:swagger
146
- @ApiOperation({ summary: 'Renova o access token usando o refresh token' })
147
- @ApiResponse({ status: 200, description: 'Novo par de tokens emitido', schema: { example: TOKENS_EXAMPLE } })
148
- @ApiResponse({ status: 401, description: 'Refresh token inválido, expirado ou já usado', schema: { example: { statusCode: 401, message: 'Refresh token inválido ou expirado' } } })
146
+ @ApiOperation({ summary: 'Renews the access token using the refresh token' })
147
+ @ApiResponse({ status: 200, description: 'New token pair issued', schema: { example: TOKENS_EXAMPLE } })
148
+ @ApiResponse({ status: 401, description: 'Invalid, expired, or already used refresh token', schema: { example: { statusCode: 401, message: 'Invalid or expired refresh token' } } })
149
149
  // nestforge:feature:swagger:end
150
150
  refresh(@Body() dto: RefreshTokenDto) {
151
151
  return this.tokenService.refresh(dto.refreshToken);
@@ -155,8 +155,8 @@ export class AuthController {
155
155
  @Post('logout')
156
156
  @HttpCode(HttpStatus.OK)
157
157
  // nestforge:feature:swagger
158
- @ApiOperation({ summary: 'Revoga o refresh token informado' })
159
- @ApiResponse({ status: 200, description: 'Logout realizado', schema: { example: { message: 'Logout realizado com sucesso' } } })
158
+ @ApiOperation({ summary: 'Revokes the provided refresh token' })
159
+ @ApiResponse({ status: 200, description: 'Logout completed', schema: { example: { message: 'Logout completed successfully' } } })
160
160
  // nestforge:feature:swagger:end
161
161
  logout(@Body() dto: RefreshTokenDto) {
162
162
  return this.tokenService.logout(dto.refreshToken);
@@ -168,11 +168,11 @@ export class AuthController {
168
168
  @Post('forgot-password')
169
169
  @HttpCode(HttpStatus.OK)
170
170
  // nestforge:feature:swagger
171
- @ApiOperation({ summary: 'Envia um e-mail com instruções para redefinir a senha' })
171
+ @ApiOperation({ summary: 'Sends an email with password reset instructions' })
172
172
  @ApiResponse({
173
173
  status: 200,
174
- description: 'Resposta genérica — sempre a mesma, exista ou não o e-mail (evita enumeração de contas)',
175
- schema: { example: { message: 'Se o e-mail existir, enviaremos instruções de redefinição de senha' } },
174
+ description: 'Generic response — always the same whether the email exists or not (prevents account enumeration)',
175
+ schema: { example: { message: 'If the email exists, password reset instructions will be sent' } },
176
176
  })
177
177
  // nestforge:feature:swagger:end
178
178
  forgotPassword(@Body() dto: ForgotPasswordDto) {
@@ -183,9 +183,9 @@ export class AuthController {
183
183
  @Post('reset-password')
184
184
  @HttpCode(HttpStatus.OK)
185
185
  // nestforge:feature:swagger
186
- @ApiOperation({ summary: 'Redefine a senha usando o token recebido por e-mail' })
187
- @ApiResponse({ status: 200, description: 'Senha redefinida', schema: { example: { message: 'Senha redefinida com sucesso' } } })
188
- @ApiResponse({ status: 401, description: 'Token inválido, expirado ou já usado', schema: { example: { statusCode: 401, message: 'Token de redefinição inválido ou expirado' } } })
186
+ @ApiOperation({ summary: 'Resets the password using the token received by email' })
187
+ @ApiResponse({ status: 200, description: 'Password reset', schema: { example: { message: 'Password reset successfully' } } })
188
+ @ApiResponse({ status: 401, description: 'Invalid, expired, or already used token', schema: { example: { statusCode: 401, message: 'Invalid or expired password reset token' } } })
189
189
  // nestforge:feature:swagger:end
190
190
  resetPassword(@Body() dto: ResetPasswordDto) {
191
191
  return this.authService.resetPassword(dto.token, dto.password);
@@ -194,9 +194,9 @@ export class AuthController {
194
194
  @Public()
195
195
  @Get('verify-email')
196
196
  // nestforge:feature:swagger
197
- @ApiOperation({ summary: 'Confirma o e-mail usando o token recebido' })
198
- @ApiResponse({ status: 200, description: 'E-mail verificado', schema: { example: { message: 'E-mail verificado com sucesso' } } })
199
- @ApiResponse({ status: 401, description: 'Token inválido, expirado ou já usado', schema: { example: { statusCode: 401, message: 'Token de verificação inválido ou expirado' } } })
197
+ @ApiOperation({ summary: 'Verifies the email using the received token' })
198
+ @ApiResponse({ status: 200, description: 'Email verified', schema: { example: { message: 'Email verified successfully' } } })
199
+ @ApiResponse({ status: 401, description: 'Invalid, expired, or already used token', schema: { example: { statusCode: 401, message: 'Invalid or expired verification token' } } })
200
200
  // nestforge:feature:swagger:end
201
201
  verifyEmail(@Query('token') token: string) {
202
202
  return this.authService.verifyEmail(token);
@@ -207,10 +207,10 @@ export class AuthController {
207
207
  @Get('google')
208
208
  @UseGuards(GoogleAuthGuard)
209
209
  // nestforge:feature:swagger
210
- @ApiOperation({ summary: 'Inicia o login via Google (redireciona)' })
210
+ @ApiOperation({ summary: 'Starts Google login (redirects)' })
211
211
  // nestforge:feature:swagger:end
212
212
  googleLogin() {
213
- // o guard redireciona para o consentimento do Google; nada a fazer aqui
213
+ // The guard redirects to Google's consent screen; nothing to do here.
214
214
  }
215
215
 
216
216
  // nestforge:feature:auth:token
@@ -246,10 +246,10 @@ export class AuthController {
246
246
  @Get('github')
247
247
  @UseGuards(GithubAuthGuard)
248
248
  // nestforge:feature:swagger
249
- @ApiOperation({ summary: 'Inicia o login via GitHub (redireciona)' })
249
+ @ApiOperation({ summary: 'Starts GitHub login (redirects)' })
250
250
  // nestforge:feature:swagger:end
251
251
  githubLogin() {
252
- // o guard redireciona para o consentimento do GitHub; nada a fazer aqui
252
+ // The guard redirects to GitHub's consent screen; nothing to do here.
253
253
  }
254
254
 
255
255
  // nestforge:feature:auth:token
@@ -280,4 +280,4 @@ export class AuthController {
280
280
  return this.sessionService.establish(request, user);
281
281
  }
282
282
  // nestforge:feature:auth:session:end
283
- }
283
+ }
@@ -81,7 +81,7 @@ describe('AuthService', () => {
81
81
  );
82
82
  });
83
83
 
84
- it('deve lançar ConflictException se o e-mail já existir', async () => {
84
+ it('throws ConflictException when the email already exists', async () => {
85
85
  usersRepository.findOne.mockResolvedValue({
86
86
  id: 'user-1',
87
87
  email: 'jeiel@example.com',
@@ -91,12 +91,12 @@ describe('AuthService', () => {
91
91
  authService.register({
92
92
  name: 'Jeiel',
93
93
  email: 'jeiel@example.com',
94
- password: 'senhaForte123',
94
+ password: 'strongPassword123',
95
95
  }),
96
96
  ).rejects.toBeInstanceOf(ConflictException);
97
97
  });
98
98
 
99
- it('deve lançar UnauthorizedException com credenciais inválidas', async () => {
99
+ it('throws UnauthorizedException for invalid credentials', async () => {
100
100
  usersRepository.findOne.mockResolvedValue(null);
101
101
 
102
102
  await expect(
@@ -108,4 +108,4 @@ describe('AuthService', () => {
108
108
  UnauthorizedException,
109
109
  );
110
110
  });
111
- });
111
+ });