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
@@ -1,46 +1,46 @@
1
- import { PrismaClient, Role } from '@prisma/client';
2
- import * as bcrypt from 'bcryptjs';
3
-
4
- const prisma = new PrismaClient();
5
-
6
- interface SeedUser {
7
- name: string;
8
- email: string;
9
- password: string;
10
- role: Role;
11
- }
12
-
13
- const SEED_USERS: SeedUser[] = [
14
- { name: 'Admin', email: 'admin@nestforge.dev', password: 'admin123', role: Role.ADMIN },
15
- { name: 'Manager', email: 'manager@nestforge.dev', password: 'manager123', role: Role.MANAGER },
16
- { name: 'Usuário', email: 'user@nestforge.dev', password: 'user1234', role: Role.USER },
17
- ];
18
-
19
- async function main() {
20
- for (const seedUser of SEED_USERS) {
21
- const passwordHash = await bcrypt.hash(seedUser.password, 10);
22
-
23
- await prisma.user.upsert({
24
- where: { email: seedUser.email },
25
- update: {},
26
- create: {
27
- name: seedUser.name,
28
- email: seedUser.email,
29
- passwordHash,
30
- role: seedUser.role,
31
- emailVerifiedAt: new Date(),
32
- },
33
- });
34
-
35
- console.log(`Seed: ${seedUser.email} / ${seedUser.password} (${seedUser.role})`);
36
- }
37
- }
38
-
39
- main()
40
- .catch((error) => {
41
- console.error(error);
42
- process.exit(1);
43
- })
44
- .finally(async () => {
45
- await prisma.$disconnect();
46
- });
1
+ import { PrismaClient, Role } from '@prisma/client';
2
+ import * as bcrypt from 'bcryptjs';
3
+
4
+ const prisma = new PrismaClient();
5
+
6
+ interface SeedUser {
7
+ name: string;
8
+ email: string;
9
+ password: string;
10
+ role: Role;
11
+ }
12
+
13
+ const SEED_USERS: SeedUser[] = [
14
+ { name: 'Admin', email: 'admin@nestforge.dev', password: 'admin123', role: Role.ADMIN },
15
+ { name: 'Manager', email: 'manager@nestforge.dev', password: 'manager123', role: Role.MANAGER },
16
+ { name: 'User', email: 'user@nestforge.dev', password: 'user1234', role: Role.USER },
17
+ ];
18
+
19
+ async function main() {
20
+ for (const seedUser of SEED_USERS) {
21
+ const passwordHash = await bcrypt.hash(seedUser.password, 10);
22
+
23
+ await prisma.user.upsert({
24
+ where: { email: seedUser.email },
25
+ update: {},
26
+ create: {
27
+ name: seedUser.name,
28
+ email: seedUser.email,
29
+ passwordHash,
30
+ role: seedUser.role,
31
+ emailVerifiedAt: new Date(),
32
+ },
33
+ });
34
+
35
+ console.log(`Seed: ${seedUser.email} / ${seedUser.password} (${seedUser.role})`);
36
+ }
37
+ }
38
+
39
+ main()
40
+ .catch((error) => {
41
+ console.error(error);
42
+ process.exit(1);
43
+ })
44
+ .finally(async () => {
45
+ await prisma.$disconnect();
46
+ });
@@ -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
+ }
@@ -35,15 +35,15 @@ describe('AuthService', () => {
35
35
  );
36
36
  });
37
37
 
38
- it('deve lançar ConflictException se o e-mail já existir', async () => {
38
+ it('throws ConflictException when the email already exists', async () => {
39
39
  prisma.user.findUnique.mockResolvedValue({ id: '1', email: 'jeiel@example.com' });
40
40
 
41
41
  await expect(
42
- authService.register({ name: 'Jeiel', email: 'jeiel@example.com', password: 'senhaForte123' }),
42
+ authService.register({ name: 'Jeiel', email: 'jeiel@example.com', password: 'strongPassword123' }),
43
43
  ).rejects.toBeInstanceOf(ConflictException);
44
44
  });
45
45
 
46
- it('deve lançar UnauthorizedException com credenciais inválidas', async () => {
46
+ it('throws UnauthorizedException for invalid credentials', async () => {
47
47
  prisma.user.findUnique.mockResolvedValue(null);
48
48
 
49
49
  await expect(
@@ -31,7 +31,7 @@ export class AuthService {
31
31
  });
32
32
 
33
33
  if (existing) {
34
- throw new ConflictException('E-mail já cadastrado');
34
+ throw new ConflictException('Email already registered');
35
35
  }
36
36
 
37
37
  const passwordHash = await bcrypt.hash(dto.password, 10);
@@ -53,11 +53,11 @@ export class AuthService {
53
53
  });
54
54
 
55
55
  if (!user || !user.passwordHash) {
56
- throw new UnauthorizedException('Credenciais inválidas');
56
+ throw new UnauthorizedException('Invalid credentials');
57
57
  }
58
58
 
59
59
  if (!(await bcrypt.compare(dto.password, user.passwordHash))) {
60
- throw new UnauthorizedException('Credenciais inválidas');
60
+ throw new UnauthorizedException('Invalid credentials');
61
61
  }
62
62
 
63
63
  return this.toAuthenticatedUser(user);
@@ -106,9 +106,9 @@ export class AuthService {
106
106
  async forgotPassword(email: string) {
107
107
  const user = await this.prisma.user.findUnique({ where: { email } });
108
108
 
109
- // resposta genérica sempre, pra não revelar se o e-mail existe na base
109
+ // Always return a generic response to avoid revealing whether the email exists.
110
110
  const genericResponse = {
111
- message: 'Se o e-mail existir, enviaremos instruções de redefinição de senha',
111
+ message: 'If the email exists, password reset instructions will be sent',
112
112
  };
113
113
 
114
114
  if (!user) {
@@ -140,7 +140,7 @@ export class AuthService {
140
140
  });
141
141
 
142
142
  if (!stored || stored.usedAt || stored.expiresAt < new Date()) {
143
- throw new UnauthorizedException('Token de redefinição inválido ou expirado');
143
+ throw new UnauthorizedException('Invalid or expired password reset token');
144
144
  }
145
145
 
146
146
  const passwordHash = await bcrypt.hash(newPassword, 10);
@@ -154,14 +154,14 @@ export class AuthService {
154
154
  where: { id: stored.id },
155
155
  data: { usedAt: new Date() },
156
156
  }),
157
- // por segurança, revoga todas as sessões ativas ao trocar a senha
157
+ // Revoke every active session after a password change for security.
158
158
  this.prisma.refreshToken.updateMany({
159
159
  where: { userId: stored.userId, revokedAt: null },
160
160
  data: { revokedAt: new Date() },
161
161
  }),
162
162
  ]);
163
163
 
164
- return { message: 'Senha redefinida com sucesso' };
164
+ return { message: 'Password reset successfully' };
165
165
  }
166
166
 
167
167
  async verifyEmail(rawToken: string) {
@@ -172,7 +172,7 @@ export class AuthService {
172
172
  });
173
173
 
174
174
  if (!stored || stored.usedAt || stored.expiresAt < new Date()) {
175
- throw new UnauthorizedException('Token de verificação inválido ou expirado');
175
+ throw new UnauthorizedException('Invalid or expired verification token');
176
176
  }
177
177
 
178
178
  await this.prisma.$transaction([
@@ -186,7 +186,7 @@ export class AuthService {
186
186
  }),
187
187
  ]);
188
188
 
189
- return { message: 'E-mail verificado com sucesso' };
189
+ return { message: 'Email verified successfully' };
190
190
  }
191
191
 
192
192
  private async sendEmailVerification(userId: string, email: string, name: string) {
@@ -221,4 +221,4 @@ export class AuthService {
221
221
  private hashToken(token: string): string {
222
222
  return createHash('sha256').update(token).digest('hex');
223
223
  }
224
- }
224
+ }
@@ -3,7 +3,7 @@ import { z } from 'zod';
3
3
  import { createZodDto } from 'nestjs-zod';
4
4
 
5
5
  export const forgotPasswordSchema = z.object({
6
- email: z.string().email().describe('E-mail da conta a ser recuperada'),
6
+ email: z.string().email().describe('Email of the account to recover'),
7
7
  });
8
8
 
9
- export class ForgotPasswordDto extends createZodDto(forgotPasswordSchema) { }
9
+ export class ForgotPasswordDto extends createZodDto(forgotPasswordSchema) { }
@@ -3,8 +3,8 @@ import { z } from 'zod';
3
3
  import { createZodDto } from 'nestjs-zod';
4
4
 
5
5
  export const loginSchema = z.object({
6
- email: z.string().email().describe('E-mail do usuário'),
7
- password: z.string().min(8).describe('Senha'),
6
+ email: z.string().email().describe('User email'),
7
+ password: z.string().min(8).describe('Password'),
8
8
  });
9
9
 
10
- export class LoginDto extends createZodDto(loginSchema) { }
10
+ export class LoginDto extends createZodDto(loginSchema) { }
@@ -3,9 +3,9 @@ import { z } from 'zod';
3
3
  import { createZodDto } from 'nestjs-zod';
4
4
 
5
5
  export const registerSchema = z.object({
6
- name: z.string().min(2).describe('Nome completo do usuário'),
7
- email: z.string().email().describe('E-mail do usuário'),
8
- password: z.string().min(8).describe('Senha (mínimo 8 caracteres)'),
6
+ name: z.string().min(2).describe('User full name'),
7
+ email: z.string().email().describe('User email'),
8
+ password: z.string().min(8).describe('Password (minimum 8 characters)'),
9
9
  });
10
10
 
11
- export class RegisterDto extends createZodDto(registerSchema) { }
11
+ export class RegisterDto extends createZodDto(registerSchema) { }
@@ -3,8 +3,8 @@ import { z } from 'zod';
3
3
  import { createZodDto } from 'nestjs-zod';
4
4
 
5
5
  export const resetPasswordSchema = z.object({
6
- token: z.string().describe('Token recebido por e-mail'),
7
- password: z.string().min(8).describe('Nova senha (mínimo 8 caracteres)'),
6
+ token: z.string().describe('Token received by email'),
7
+ password: z.string().min(8).describe('New password (minimum 8 characters)'),
8
8
  });
9
9
 
10
- export class ResetPasswordDto extends createZodDto(resetPasswordSchema) { }
10
+ export class ResetPasswordDto extends createZodDto(resetPasswordSchema) { }
@@ -1,10 +1,10 @@
1
- import { Injectable } from '@nestjs/common';
2
- import { AuthGuard } from '@nestjs/passport';
3
-
4
- @Injectable()
5
- export class GithubAuthGuard extends AuthGuard('github') {
6
- constructor() {
7
- // API stateless (Bearer token) — não usamos sessão do Passport/Express
8
- super({ session: false });
9
- }
10
- }
1
+ import { Injectable } from '@nestjs/common';
2
+ import { AuthGuard } from '@nestjs/passport';
3
+
4
+ @Injectable()
5
+ export class GithubAuthGuard extends AuthGuard('github') {
6
+ constructor() {
7
+ // Stateless API (Bearer token) — Passport/Express sessions are not used.
8
+ super({ session: false });
9
+ }
10
+ }
@@ -1,10 +1,10 @@
1
- import { Injectable } from '@nestjs/common';
2
- import { AuthGuard } from '@nestjs/passport';
3
-
4
- @Injectable()
5
- export class GoogleAuthGuard extends AuthGuard('google') {
6
- constructor() {
7
- // API stateless (Bearer token) — não usamos sessão do Passport/Express
8
- super({ session: false });
9
- }
10
- }
1
+ import { Injectable } from '@nestjs/common';
2
+ import { AuthGuard } from '@nestjs/passport';
3
+
4
+ @Injectable()
5
+ export class GoogleAuthGuard extends AuthGuard('google') {
6
+ constructor() {
7
+ // Stateless API (Bearer token) — Passport/Express sessions are not used.
8
+ super({ session: false });
9
+ }
10
+ }
@@ -44,14 +44,14 @@ describe('SessionAuthGuard', () => {
44
44
  return { context, request };
45
45
  }
46
46
 
47
- it('permite acesso a rotas públicas sem sessão', () => {
47
+ it('allows access to public routes without a session', () => {
48
48
  reflector.getAllAndOverride.mockReturnValue(true);
49
49
  const { context } = createContext();
50
50
 
51
51
  expect(guard.canActivate(context)).toBe(true);
52
52
  });
53
53
 
54
- it('rejeita acesso quando não existe usuário na sessão', () => {
54
+ it('rejects access when the session has no user', () => {
55
55
  reflector.getAllAndOverride.mockReturnValue(false);
56
56
  const { context } = createContext();
57
57
 
@@ -60,7 +60,7 @@ describe('SessionAuthGuard', () => {
60
60
  );
61
61
  });
62
62
 
63
- it('permite acesso e disponibiliza o usuário autenticado', () => {
63
+ it('allows access and exposes the authenticated user', () => {
64
64
  reflector.getAllAndOverride.mockReturnValue(false);
65
65
 
66
66
  const user = {
@@ -74,4 +74,4 @@ describe('SessionAuthGuard', () => {
74
74
  expect(guard.canActivate(context)).toBe(true);
75
75
  expect(request.user).toEqual(user);
76
76
  });
77
- });
77
+ });
@@ -27,11 +27,11 @@ export class SessionAuthGuard implements CanActivate {
27
27
  const user = request.session?.user;
28
28
 
29
29
  if (!user) {
30
- throw new UnauthorizedException('Sessão inválida ou expirada');
30
+ throw new UnauthorizedException('Invalid or expired session');
31
31
  }
32
32
 
33
33
  request.user = user;
34
34
 
35
35
  return true;
36
36
  }
37
- }
37
+ }
@@ -31,7 +31,7 @@ describe('SessionService', () => {
31
31
  };
32
32
  }
33
33
 
34
- it('regenera, preenche e salva a sessão', async () => {
34
+ it('regenerates, populates, and saves the session', async () => {
35
35
  const { request, session } = createRequest();
36
36
  const user: SessionUser = {
37
37
  id: 'user-1',
@@ -51,7 +51,7 @@ describe('SessionService', () => {
51
51
  });
52
52
  });
53
53
 
54
- it('emite e salva um novo token CSRF', async () => {
54
+ it('issues and saves a new CSRF token', async () => {
55
55
  const { request, session } = createRequest();
56
56
 
57
57
  const result = await sessionService.issueCsrfToken(request);
@@ -61,14 +61,14 @@ describe('SessionService', () => {
61
61
  expect(session.save).toHaveBeenCalledOnce();
62
62
  });
63
63
 
64
- it('destrói a sessão atual', async () => {
64
+ it('destroys the current session', async () => {
65
65
  const { request, session } = createRequest();
66
66
 
67
67
  const result = await sessionService.destroy(request);
68
68
 
69
69
  expect(session.destroy).toHaveBeenCalledOnce();
70
70
  expect(result).toEqual({
71
- message: 'Logout realizado com sucesso',
71
+ message: 'Logout completed successfully',
72
72
  });
73
73
  });
74
- });
74
+ });
@@ -47,7 +47,7 @@ export class SessionService {
47
47
  if (error) {
48
48
  reject(
49
49
  new InternalServerErrorException(
50
- 'Não foi possível encerrar a sessão',
50
+ 'Unable to end the session',
51
51
  ),
52
52
  );
53
53
  return;
@@ -57,7 +57,7 @@ export class SessionService {
57
57
  });
58
58
  });
59
59
 
60
- return { message: 'Logout realizado com sucesso' };
60
+ return { message: 'Logout completed successfully' };
61
61
  }
62
62
 
63
63
  private async regenerate(request: Request): Promise<void> {
@@ -66,7 +66,7 @@ export class SessionService {
66
66
  if (error) {
67
67
  reject(
68
68
  new InternalServerErrorException(
69
- 'Não foi possível iniciar a sessão',
69
+ 'Unable to start the session',
70
70
  ),
71
71
  );
72
72
  return;
@@ -83,7 +83,7 @@ export class SessionService {
83
83
  if (error) {
84
84
  reject(
85
85
  new InternalServerErrorException(
86
- 'Não foi possível salvar a sessão',
86
+ 'Unable to save the session',
87
87
  ),
88
88
  );
89
89
  return;
@@ -93,4 +93,4 @@ export class SessionService {
93
93
  });
94
94
  });
95
95
  }
96
- }
96
+ }
@@ -25,7 +25,7 @@ export class GithubStrategy extends PassportStrategy(Strategy, 'github') {
25
25
  profile: Profile,
26
26
  done: (error: unknown, user?: OAuthProfile) => void,
27
27
  ) {
28
- // o e-mail pode vir vazio se o usuário deixou o e-mail privado no GitHub
28
+ // The email may be missing when the user keeps it private on GitHub.
29
29
  const email =
30
30
  profile.emails?.[0]?.value ?? `${profile.username}@users.noreply.github.com`;
31
31
 
@@ -33,9 +33,9 @@ export class GithubStrategy extends PassportStrategy(Strategy, 'github') {
33
33
  provider: 'github',
34
34
  providerUserId: profile.id,
35
35
  email,
36
- name: profile.displayName || profile.username || 'Usuário GitHub',
36
+ name: profile.displayName || profile.username || 'GitHub User',
37
37
  };
38
38
 
39
39
  done(null, oauthProfile);
40
40
  }
41
- }
41
+ }
@@ -56,7 +56,7 @@ export class TokenService {
56
56
  });
57
57
 
58
58
  if (!stored || stored.revokedAt || stored.expiresAt < new Date()) {
59
- throw new UnauthorizedException('Refresh token inválido ou expirado');
59
+ throw new UnauthorizedException('Invalid or expired refresh token');
60
60
  }
61
61
 
62
62
  await this.prisma.refreshToken.update({
@@ -84,7 +84,7 @@ export class TokenService {
84
84
  },
85
85
  });
86
86
 
87
- return { message: 'Logout realizado com sucesso' };
87
+ return { message: 'Logout completed successfully' };
88
88
  }
89
89
 
90
90
  private hashToken(token: string): string {