nestforge-generator 0.1.0

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 (326) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +371 -0
  3. package/README.pt-BR.md +370 -0
  4. package/dist/features/auth-strategy.js +19 -0
  5. package/dist/features/auth-strategy.js.map +1 -0
  6. package/dist/features/database.js +59 -0
  7. package/dist/features/database.js.map +1 -0
  8. package/dist/features/dependencies.js +57 -0
  9. package/dist/features/dependencies.js.map +1 -0
  10. package/dist/features/language.js +172 -0
  11. package/dist/features/language.js.map +1 -0
  12. package/dist/features/markers.js +116 -0
  13. package/dist/features/markers.js.map +1 -0
  14. package/dist/generator.js +120 -0
  15. package/dist/generator.js.map +1 -0
  16. package/dist/index.js +59 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/prompts.js +137 -0
  19. package/dist/prompts.js.map +1 -0
  20. package/package.json +76 -0
  21. package/templates/drizzle/.env.example +45 -0
  22. package/templates/drizzle/.env.test +38 -0
  23. package/templates/drizzle/.github/workflows/ci.yml +119 -0
  24. package/templates/drizzle/ARCHITECTURE.md +227 -0
  25. package/templates/drizzle/ARCHITECTURE.pt-BR.md +225 -0
  26. package/templates/drizzle/CODE_OF_CONDUCT.md +29 -0
  27. package/templates/drizzle/CODE_OF_CONDUCT.pt-BR.md +27 -0
  28. package/templates/drizzle/CONTRIBUTING.md +57 -0
  29. package/templates/drizzle/CONTRIBUTING.pt-BR.md +54 -0
  30. package/templates/drizzle/Dockerfile +43 -0
  31. package/templates/drizzle/LICENSE +21 -0
  32. package/templates/drizzle/README.md +257 -0
  33. package/templates/drizzle/README.pt-BR.md +257 -0
  34. package/templates/drizzle/ROADMAP.md +143 -0
  35. package/templates/drizzle/ROADMAP.pt-BR.md +143 -0
  36. package/templates/drizzle/TESTING.md +136 -0
  37. package/templates/drizzle/TESTING.pt-BR.md +136 -0
  38. package/templates/drizzle/docker-compose.yml +82 -0
  39. package/templates/drizzle/docs/adding-a-module.md +585 -0
  40. package/templates/drizzle/docs/features-markers.md +457 -0
  41. package/templates/drizzle/drizzle.config.ts +49 -0
  42. package/templates/drizzle/nest-cli.json +8 -0
  43. package/templates/drizzle/package.json +96 -0
  44. package/templates/drizzle/src/app.module.ts +72 -0
  45. package/templates/drizzle/src/auth/auth.controller.ts +283 -0
  46. package/templates/drizzle/src/auth/auth.module.ts +81 -0
  47. package/templates/drizzle/src/auth/auth.service.spec.ts +111 -0
  48. package/templates/drizzle/src/auth/auth.service.ts +631 -0
  49. package/templates/drizzle/src/auth/drizzle-session.store.ts +263 -0
  50. package/templates/drizzle/src/auth/dto/forgot-password.dto.ts +9 -0
  51. package/templates/drizzle/src/auth/dto/login.dto.ts +10 -0
  52. package/templates/drizzle/src/auth/dto/refresh-token.dto.ts +9 -0
  53. package/templates/drizzle/src/auth/dto/register.dto.ts +11 -0
  54. package/templates/drizzle/src/auth/dto/reset-password.dto.ts +10 -0
  55. package/templates/drizzle/src/auth/guards/github-auth.guard.ts +10 -0
  56. package/templates/drizzle/src/auth/guards/google-auth.guard.ts +10 -0
  57. package/templates/drizzle/src/auth/guards/jwt-auth.guard.ts +25 -0
  58. package/templates/drizzle/src/auth/guards/session-auth.guard.spec.ts +77 -0
  59. package/templates/drizzle/src/auth/guards/session-auth.guard.ts +37 -0
  60. package/templates/drizzle/src/auth/session.service.spec.ts +74 -0
  61. package/templates/drizzle/src/auth/session.service.ts +96 -0
  62. package/templates/drizzle/src/auth/strategies/github.strategy.ts +41 -0
  63. package/templates/drizzle/src/auth/strategies/google.strategy.ts +43 -0
  64. package/templates/drizzle/src/auth/strategies/jwt.strategy.ts +25 -0
  65. package/templates/drizzle/src/auth/token.service.ts +175 -0
  66. package/templates/drizzle/src/common/constants/permissions.ts +8 -0
  67. package/templates/drizzle/src/common/constants/role-permissions.ts +9 -0
  68. package/templates/drizzle/src/common/constants/role.enum.ts +5 -0
  69. package/templates/drizzle/src/common/decorators/current-user.decorator.ts +8 -0
  70. package/templates/drizzle/src/common/decorators/permissions.decorator.ts +7 -0
  71. package/templates/drizzle/src/common/decorators/public.decorator.ts +4 -0
  72. package/templates/drizzle/src/common/decorators/roles.decorator.ts +6 -0
  73. package/templates/drizzle/src/common/filters/http-exception.filter.ts +34 -0
  74. package/templates/drizzle/src/common/guards/permissions.guard.spec.ts +54 -0
  75. package/templates/drizzle/src/common/guards/permissions.guard.ts +28 -0
  76. package/templates/drizzle/src/common/guards/roles.guard.spec.ts +37 -0
  77. package/templates/drizzle/src/common/guards/roles.guard.ts +24 -0
  78. package/templates/drizzle/src/common/interceptors/logging.interceptor.ts +23 -0
  79. package/templates/drizzle/src/common/middleware/csrf.middleware.spec.ts +97 -0
  80. package/templates/drizzle/src/common/middleware/csrf.middleware.ts +46 -0
  81. package/templates/drizzle/src/common/utils/avatar-storage.util.ts +32 -0
  82. package/templates/drizzle/src/common/utils/hash.util.ts +5 -0
  83. package/templates/drizzle/src/config/env.validation.ts +50 -0
  84. package/templates/drizzle/src/database/database-lifecycle.service.ts +30 -0
  85. package/templates/drizzle/src/database/database.constants.ts +2 -0
  86. package/templates/drizzle/src/database/database.decorators.ts +5 -0
  87. package/templates/drizzle/src/database/database.module.ts +96 -0
  88. package/templates/drizzle/src/database/database.types.ts +28 -0
  89. package/templates/drizzle/src/database/schema/index.ts +11 -0
  90. package/templates/drizzle/src/database/schema/mysql.schema.ts +215 -0
  91. package/templates/drizzle/src/database/schema/postgres.schema.ts +218 -0
  92. package/templates/drizzle/src/database/schema/sqlite.schema.ts +190 -0
  93. package/templates/drizzle/src/database/seed.ts +152 -0
  94. package/templates/drizzle/src/health/health.controller.ts +49 -0
  95. package/templates/drizzle/src/health/health.module.ts +19 -0
  96. package/templates/drizzle/src/health/indicators/drizzle-health.indicator.spec.ts +71 -0
  97. package/templates/drizzle/src/health/indicators/drizzle-health.indicator.ts +52 -0
  98. package/templates/drizzle/src/health/indicators/redis-health.indicator.spec.ts +54 -0
  99. package/templates/drizzle/src/health/indicators/redis-health.indicator.ts +33 -0
  100. package/templates/drizzle/src/mail/mail.module.ts +12 -0
  101. package/templates/drizzle/src/mail/mail.processor.ts +48 -0
  102. package/templates/drizzle/src/mail/mail.service.ts +24 -0
  103. package/templates/drizzle/src/mail/templates/email-templates.ts +28 -0
  104. package/templates/drizzle/src/main.ts +145 -0
  105. package/templates/drizzle/src/metrics/metrics.controller.ts +22 -0
  106. package/templates/drizzle/src/metrics/metrics.interceptor.ts +30 -0
  107. package/templates/drizzle/src/metrics/metrics.module.ts +12 -0
  108. package/templates/drizzle/src/metrics/metrics.service.ts +34 -0
  109. package/templates/drizzle/src/types/express-session.d.ts +13 -0
  110. package/templates/drizzle/src/users/dto/create-user.dto.ts +12 -0
  111. package/templates/drizzle/src/users/dto/find-users-query.dto.ts +12 -0
  112. package/templates/drizzle/src/users/dto/update-user.dto.ts +6 -0
  113. package/templates/drizzle/src/users/entities/user.entity.ts +23 -0
  114. package/templates/drizzle/src/users/users.controller.ts +165 -0
  115. package/templates/drizzle/src/users/users.module.ts +10 -0
  116. package/templates/drizzle/src/users/users.service.spec.ts +301 -0
  117. package/templates/drizzle/src/users/users.service.ts +213 -0
  118. package/templates/drizzle/test/auth.e2e-spec.ts +114 -0
  119. package/templates/drizzle/test/session-auth.e2e-spec.ts +163 -0
  120. package/templates/drizzle/test/users.e2e-spec.ts +212 -0
  121. package/templates/drizzle/test/utils/clean-database.ts +104 -0
  122. package/templates/drizzle/test/utils/e2e-setup.ts +77 -0
  123. package/templates/drizzle/tsconfig.build.json +4 -0
  124. package/templates/drizzle/tsconfig.json +25 -0
  125. package/templates/drizzle/vitest.config.ts +20 -0
  126. package/templates/drizzle/vitest.e2e.config.ts +19 -0
  127. package/templates/prisma/.env.example +44 -0
  128. package/templates/prisma/.env.test +37 -0
  129. package/templates/prisma/.github/workflows/ci.yml +109 -0
  130. package/templates/prisma/ARCHITECTURE.md +70 -0
  131. package/templates/prisma/ARCHITECTURE.pt-BR.md +63 -0
  132. package/templates/prisma/CODE_OF_CONDUCT.md +29 -0
  133. package/templates/prisma/CODE_OF_CONDUCT.pt-BR.md +27 -0
  134. package/templates/prisma/CONTRIBUTING.md +57 -0
  135. package/templates/prisma/CONTRIBUTING.pt-BR.md +54 -0
  136. package/templates/prisma/Dockerfile +33 -0
  137. package/templates/prisma/LICENSE +21 -0
  138. package/templates/prisma/README.md +267 -0
  139. package/templates/prisma/README.pt-BR.md +267 -0
  140. package/templates/prisma/ROADMAP.md +75 -0
  141. package/templates/prisma/ROADMAP.pt-BR.md +65 -0
  142. package/templates/prisma/TESTING.md +123 -0
  143. package/templates/prisma/TESTING.pt-BR.md +123 -0
  144. package/templates/prisma/docker-compose.yml +78 -0
  145. package/templates/prisma/docs/adding-a-module.md +230 -0
  146. package/templates/prisma/docs/features-markers.md +50 -0
  147. package/templates/prisma/nest-cli.json +8 -0
  148. package/templates/prisma/package.json +95 -0
  149. package/templates/prisma/prisma/schema.prisma +105 -0
  150. package/templates/prisma/prisma/seed.ts +46 -0
  151. package/templates/prisma/src/app.module.ts +72 -0
  152. package/templates/prisma/src/auth/auth.controller.ts +283 -0
  153. package/templates/prisma/src/auth/auth.module.ts +59 -0
  154. package/templates/prisma/src/auth/auth.service.spec.ts +53 -0
  155. package/templates/prisma/src/auth/auth.service.ts +224 -0
  156. package/templates/prisma/src/auth/dto/forgot-password.dto.ts +9 -0
  157. package/templates/prisma/src/auth/dto/login.dto.ts +10 -0
  158. package/templates/prisma/src/auth/dto/refresh-token.dto.ts +9 -0
  159. package/templates/prisma/src/auth/dto/register.dto.ts +11 -0
  160. package/templates/prisma/src/auth/dto/reset-password.dto.ts +10 -0
  161. package/templates/prisma/src/auth/guards/github-auth.guard.ts +10 -0
  162. package/templates/prisma/src/auth/guards/google-auth.guard.ts +10 -0
  163. package/templates/prisma/src/auth/guards/jwt-auth.guard.ts +25 -0
  164. package/templates/prisma/src/auth/guards/session-auth.guard.spec.ts +77 -0
  165. package/templates/prisma/src/auth/guards/session-auth.guard.ts +37 -0
  166. package/templates/prisma/src/auth/session.service.spec.ts +74 -0
  167. package/templates/prisma/src/auth/session.service.ts +96 -0
  168. package/templates/prisma/src/auth/strategies/github.strategy.ts +41 -0
  169. package/templates/prisma/src/auth/strategies/google.strategy.ts +43 -0
  170. package/templates/prisma/src/auth/strategies/jwt.strategy.ts +25 -0
  171. package/templates/prisma/src/auth/token.service.ts +84 -0
  172. package/templates/prisma/src/common/constants/permissions.ts +8 -0
  173. package/templates/prisma/src/common/constants/role-permissions.ts +9 -0
  174. package/templates/prisma/src/common/decorators/current-user.decorator.ts +8 -0
  175. package/templates/prisma/src/common/decorators/permissions.decorator.ts +7 -0
  176. package/templates/prisma/src/common/decorators/public.decorator.ts +4 -0
  177. package/templates/prisma/src/common/decorators/roles.decorator.ts +6 -0
  178. package/templates/prisma/src/common/filters/http-exception.filter.ts +34 -0
  179. package/templates/prisma/src/common/guards/permissions.guard.spec.ts +54 -0
  180. package/templates/prisma/src/common/guards/permissions.guard.ts +28 -0
  181. package/templates/prisma/src/common/guards/roles.guard.spec.ts +37 -0
  182. package/templates/prisma/src/common/guards/roles.guard.ts +24 -0
  183. package/templates/prisma/src/common/interceptors/logging.interceptor.ts +23 -0
  184. package/templates/prisma/src/common/middleware/csrf.middleware.spec.ts +97 -0
  185. package/templates/prisma/src/common/middleware/csrf.middleware.ts +46 -0
  186. package/templates/prisma/src/common/utils/avatar-storage.util.ts +32 -0
  187. package/templates/prisma/src/common/utils/hash.util.ts +5 -0
  188. package/templates/prisma/src/config/env.validation.ts +49 -0
  189. package/templates/prisma/src/database/prisma.module.ts +9 -0
  190. package/templates/prisma/src/database/prisma.service.ts +13 -0
  191. package/templates/prisma/src/health/health.controller.ts +49 -0
  192. package/templates/prisma/src/health/health.module.ts +19 -0
  193. package/templates/prisma/src/health/indicators/prisma-health.indicator.spec.ts +22 -0
  194. package/templates/prisma/src/health/indicators/prisma-health.indicator.ts +19 -0
  195. package/templates/prisma/src/health/indicators/redis-health.indicator.spec.ts +54 -0
  196. package/templates/prisma/src/health/indicators/redis-health.indicator.ts +33 -0
  197. package/templates/prisma/src/mail/mail.module.ts +12 -0
  198. package/templates/prisma/src/mail/mail.processor.ts +48 -0
  199. package/templates/prisma/src/mail/mail.service.ts +24 -0
  200. package/templates/prisma/src/mail/templates/email-templates.ts +28 -0
  201. package/templates/prisma/src/main.ts +92 -0
  202. package/templates/prisma/src/metrics/metrics.controller.ts +22 -0
  203. package/templates/prisma/src/metrics/metrics.interceptor.ts +30 -0
  204. package/templates/prisma/src/metrics/metrics.module.ts +12 -0
  205. package/templates/prisma/src/metrics/metrics.service.ts +34 -0
  206. package/templates/prisma/src/types/express-session.d.ts +13 -0
  207. package/templates/prisma/src/users/dto/create-user.dto.ts +12 -0
  208. package/templates/prisma/src/users/dto/find-users-query.dto.ts +12 -0
  209. package/templates/prisma/src/users/dto/update-user.dto.ts +6 -0
  210. package/templates/prisma/src/users/entities/user.entity.ts +20 -0
  211. package/templates/prisma/src/users/users.controller.ts +165 -0
  212. package/templates/prisma/src/users/users.module.ts +10 -0
  213. package/templates/prisma/src/users/users.service.spec.ts +104 -0
  214. package/templates/prisma/src/users/users.service.ts +114 -0
  215. package/templates/prisma/test/auth.e2e-spec.ts +75 -0
  216. package/templates/prisma/test/session-auth.e2e-spec.ts +163 -0
  217. package/templates/prisma/test/users.e2e-spec.ts +106 -0
  218. package/templates/prisma/test/utils/clean-database.ts +14 -0
  219. package/templates/prisma/test/utils/e2e-setup.ts +58 -0
  220. package/templates/prisma/tsconfig.build.json +4 -0
  221. package/templates/prisma/tsconfig.json +25 -0
  222. package/templates/prisma/vitest.config.ts +20 -0
  223. package/templates/prisma/vitest.e2e.config.ts +19 -0
  224. package/templates/typeorm/.env.example +45 -0
  225. package/templates/typeorm/.env.test +38 -0
  226. package/templates/typeorm/.github/workflows/ci.yml +116 -0
  227. package/templates/typeorm/ARCHITECTURE.md +158 -0
  228. package/templates/typeorm/ARCHITECTURE.pt-BR.md +156 -0
  229. package/templates/typeorm/CODE_OF_CONDUCT.md +29 -0
  230. package/templates/typeorm/CODE_OF_CONDUCT.pt-BR.md +27 -0
  231. package/templates/typeorm/CONTRIBUTING.md +57 -0
  232. package/templates/typeorm/CONTRIBUTING.pt-BR.md +54 -0
  233. package/templates/typeorm/Dockerfile +43 -0
  234. package/templates/typeorm/LICENSE +21 -0
  235. package/templates/typeorm/README.md +266 -0
  236. package/templates/typeorm/README.pt-BR.md +266 -0
  237. package/templates/typeorm/ROADMAP.md +79 -0
  238. package/templates/typeorm/ROADMAP.pt-BR.md +67 -0
  239. package/templates/typeorm/TESTING.md +114 -0
  240. package/templates/typeorm/TESTING.pt-BR.md +114 -0
  241. package/templates/typeorm/docker-compose.yml +78 -0
  242. package/templates/typeorm/docs/adding-a-module.md +369 -0
  243. package/templates/typeorm/docs/features-markers.md +50 -0
  244. package/templates/typeorm/nest-cli.json +8 -0
  245. package/templates/typeorm/package.json +98 -0
  246. package/templates/typeorm/src/app.module.ts +72 -0
  247. package/templates/typeorm/src/auth/auth.controller.ts +283 -0
  248. package/templates/typeorm/src/auth/auth.module.ts +86 -0
  249. package/templates/typeorm/src/auth/auth.service.spec.ts +111 -0
  250. package/templates/typeorm/src/auth/auth.service.ts +346 -0
  251. package/templates/typeorm/src/auth/dto/forgot-password.dto.ts +9 -0
  252. package/templates/typeorm/src/auth/dto/login.dto.ts +10 -0
  253. package/templates/typeorm/src/auth/dto/refresh-token.dto.ts +9 -0
  254. package/templates/typeorm/src/auth/dto/register.dto.ts +11 -0
  255. package/templates/typeorm/src/auth/dto/reset-password.dto.ts +10 -0
  256. package/templates/typeorm/src/auth/entities/email-verification-token.entity.ts +69 -0
  257. package/templates/typeorm/src/auth/entities/oauth-account.entity.ts +50 -0
  258. package/templates/typeorm/src/auth/entities/password-reset-token.entity.ts +69 -0
  259. package/templates/typeorm/src/auth/entities/refresh-token.entity.ts +69 -0
  260. package/templates/typeorm/src/auth/entities/session.entity.ts +50 -0
  261. package/templates/typeorm/src/auth/guards/github-auth.guard.ts +10 -0
  262. package/templates/typeorm/src/auth/guards/google-auth.guard.ts +10 -0
  263. package/templates/typeorm/src/auth/guards/jwt-auth.guard.ts +25 -0
  264. package/templates/typeorm/src/auth/guards/session-auth.guard.spec.ts +77 -0
  265. package/templates/typeorm/src/auth/guards/session-auth.guard.ts +37 -0
  266. package/templates/typeorm/src/auth/session.service.spec.ts +74 -0
  267. package/templates/typeorm/src/auth/session.service.ts +96 -0
  268. package/templates/typeorm/src/auth/strategies/github.strategy.ts +41 -0
  269. package/templates/typeorm/src/auth/strategies/google.strategy.ts +43 -0
  270. package/templates/typeorm/src/auth/strategies/jwt.strategy.ts +25 -0
  271. package/templates/typeorm/src/auth/token.service.ts +115 -0
  272. package/templates/typeorm/src/common/constants/permissions.ts +8 -0
  273. package/templates/typeorm/src/common/constants/role-permissions.ts +9 -0
  274. package/templates/typeorm/src/common/constants/role.enum.ts +5 -0
  275. package/templates/typeorm/src/common/decorators/current-user.decorator.ts +8 -0
  276. package/templates/typeorm/src/common/decorators/permissions.decorator.ts +7 -0
  277. package/templates/typeorm/src/common/decorators/public.decorator.ts +4 -0
  278. package/templates/typeorm/src/common/decorators/roles.decorator.ts +6 -0
  279. package/templates/typeorm/src/common/filters/http-exception.filter.ts +34 -0
  280. package/templates/typeorm/src/common/guards/permissions.guard.spec.ts +54 -0
  281. package/templates/typeorm/src/common/guards/permissions.guard.ts +28 -0
  282. package/templates/typeorm/src/common/guards/roles.guard.spec.ts +37 -0
  283. package/templates/typeorm/src/common/guards/roles.guard.ts +24 -0
  284. package/templates/typeorm/src/common/interceptors/logging.interceptor.ts +23 -0
  285. package/templates/typeorm/src/common/middleware/csrf.middleware.spec.ts +97 -0
  286. package/templates/typeorm/src/common/middleware/csrf.middleware.ts +46 -0
  287. package/templates/typeorm/src/common/utils/avatar-storage.util.ts +32 -0
  288. package/templates/typeorm/src/common/utils/hash.util.ts +5 -0
  289. package/templates/typeorm/src/config/env.validation.ts +50 -0
  290. package/templates/typeorm/src/database/data-source.ts +20 -0
  291. package/templates/typeorm/src/database/database.module.ts +39 -0
  292. package/templates/typeorm/src/database/seed.ts +81 -0
  293. package/templates/typeorm/src/database/typeorm-options.ts +49 -0
  294. package/templates/typeorm/src/health/health.controller.ts +49 -0
  295. package/templates/typeorm/src/health/health.module.ts +19 -0
  296. package/templates/typeorm/src/health/indicators/redis-health.indicator.spec.ts +54 -0
  297. package/templates/typeorm/src/health/indicators/redis-health.indicator.ts +33 -0
  298. package/templates/typeorm/src/health/indicators/typeorm-health.indicator.spec.ts +49 -0
  299. package/templates/typeorm/src/health/indicators/typeorm-health.indicator.ts +37 -0
  300. package/templates/typeorm/src/mail/mail.module.ts +12 -0
  301. package/templates/typeorm/src/mail/mail.processor.ts +48 -0
  302. package/templates/typeorm/src/mail/mail.service.ts +24 -0
  303. package/templates/typeorm/src/mail/templates/email-templates.ts +28 -0
  304. package/templates/typeorm/src/main.ts +107 -0
  305. package/templates/typeorm/src/metrics/metrics.controller.ts +22 -0
  306. package/templates/typeorm/src/metrics/metrics.interceptor.ts +30 -0
  307. package/templates/typeorm/src/metrics/metrics.module.ts +12 -0
  308. package/templates/typeorm/src/metrics/metrics.service.ts +34 -0
  309. package/templates/typeorm/src/types/express-session.d.ts +13 -0
  310. package/templates/typeorm/src/users/dto/create-user.dto.ts +12 -0
  311. package/templates/typeorm/src/users/dto/find-users-query.dto.ts +12 -0
  312. package/templates/typeorm/src/users/dto/update-user.dto.ts +6 -0
  313. package/templates/typeorm/src/users/entities/user.entity.ts +113 -0
  314. package/templates/typeorm/src/users/users.controller.ts +165 -0
  315. package/templates/typeorm/src/users/users.module.ts +13 -0
  316. package/templates/typeorm/src/users/users.service.spec.ts +183 -0
  317. package/templates/typeorm/src/users/users.service.ts +124 -0
  318. package/templates/typeorm/test/auth.e2e-spec.ts +111 -0
  319. package/templates/typeorm/test/session-auth.e2e-spec.ts +159 -0
  320. package/templates/typeorm/test/users.e2e-spec.ts +183 -0
  321. package/templates/typeorm/test/utils/clean-database.ts +65 -0
  322. package/templates/typeorm/test/utils/e2e-setup.ts +77 -0
  323. package/templates/typeorm/tsconfig.build.json +4 -0
  324. package/templates/typeorm/tsconfig.json +25 -0
  325. package/templates/typeorm/vitest.config.ts +20 -0
  326. package/templates/typeorm/vitest.e2e.config.ts +19 -0
@@ -0,0 +1,105 @@
1
+ generator client {
2
+ provider = "prisma-client-js"
3
+ }
4
+
5
+ datasource db {
6
+ provider = "postgresql"
7
+ url = env("DATABASE_URL")
8
+ }
9
+
10
+ enum Role {
11
+ ADMIN
12
+ MANAGER
13
+ USER
14
+ }
15
+
16
+ model User {
17
+ id String @id @default(uuid())
18
+ name String
19
+ email String @unique
20
+ passwordHash String?
21
+ role Role @default(USER)
22
+ emailVerifiedAt DateTime?
23
+ avatarUrl String?
24
+ createdAt DateTime @default(now())
25
+ updatedAt DateTime @updatedAt
26
+
27
+ refreshTokens RefreshToken[]
28
+ oauthAccounts OAuthAccount[]
29
+ passwordResetTokens PasswordResetToken[]
30
+ emailVerificationTokens EmailVerificationToken[]
31
+
32
+ @@map("users")
33
+ }
34
+
35
+ model RefreshToken {
36
+ id String @id @default(uuid())
37
+ tokenHash String @unique
38
+ userId String
39
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
40
+ expiresAt DateTime
41
+ revokedAt DateTime?
42
+ createdAt DateTime @default(now())
43
+
44
+ @@map("refresh_tokens")
45
+ }
46
+
47
+ model OAuthAccount {
48
+ id String @id @default(uuid())
49
+ provider String // "google" | "github"
50
+ providerUserId String
51
+ userId String
52
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
53
+ createdAt DateTime @default(now())
54
+
55
+ @@unique([provider, providerUserId])
56
+ @@map("oauth_accounts")
57
+ }
58
+
59
+ model PasswordResetToken {
60
+ id String @id @default(uuid())
61
+ tokenHash String @unique
62
+ userId String
63
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
64
+ expiresAt DateTime
65
+ usedAt DateTime?
66
+ createdAt DateTime @default(now())
67
+
68
+ @@map("password_reset_tokens")
69
+ }
70
+
71
+ model EmailVerificationToken {
72
+ id String @id @default(uuid())
73
+ tokenHash String @unique
74
+ userId String
75
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
76
+ expiresAt DateTime
77
+ usedAt DateTime?
78
+ createdAt DateTime @default(now())
79
+
80
+ @@map("email_verification_tokens")
81
+ }
82
+
83
+ // nestforge:feature:auth:session
84
+ model Session {
85
+ id String @id
86
+ sid String @unique
87
+
88
+ // nestforge:feature:database:mysql
89
+ data String @db.Text
90
+ // nestforge:feature:database:mysql:end
91
+
92
+ // nestforge:feature:database:postgres
93
+ data String
94
+ // nestforge:feature:database:postgres:end
95
+
96
+ // nestforge:feature:database:sqlite
97
+ data String
98
+ // nestforge:feature:database:sqlite:end
99
+
100
+ expiresAt DateTime
101
+
102
+ @@map("sessions")
103
+ }
104
+
105
+ // nestforge:feature:auth:session:end
@@ -0,0 +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
+ });
@@ -0,0 +1,72 @@
1
+ import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
2
+ import { ConfigModule } from '@nestjs/config';
3
+ import { ThrottlerModule } from '@nestjs/throttler';
4
+ // nestforge:feature:redis
5
+ import { BullModule } from '@nestjs/bullmq';
6
+ // nestforge:feature:redis:end
7
+ import { LoggerModule } from 'nestjs-pino';
8
+ // nestforge:feature:auth:enabled
9
+ import { AuthModule } from './auth/auth.module';
10
+ import { UsersModule } from './users/users.module';
11
+ // nestforge:feature:auth:enabled:end
12
+ import { PrismaModule } from './database/prisma.module';
13
+ // nestforge:feature:redis
14
+ import { MailModule } from './mail/mail.module';
15
+ // nestforge:feature:redis:end
16
+ import { HealthModule } from './health/health.module';
17
+ import { MetricsModule } from './metrics/metrics.module';
18
+ // nestforge:feature:auth:session
19
+ import { CsrfMiddleware } from './common/middleware/csrf.middleware';
20
+ // nestforge:feature:auth:session:end
21
+ import { validateEnv } from './config/env.validation';
22
+
23
+ @Module({
24
+ imports: [
25
+ ConfigModule.forRoot({
26
+ isGlobal: true,
27
+ validate: validateEnv,
28
+ }),
29
+ LoggerModule.forRoot({
30
+ pinoHttp: {
31
+ level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
32
+ transport:
33
+ process.env.NODE_ENV === 'development'
34
+ ? { target: 'pino-pretty', options: { singleLine: true } }
35
+ : undefined,
36
+ },
37
+ }),
38
+ ThrottlerModule.forRoot([
39
+ {
40
+ ttl: Number(process.env.THROTTLE_TTL ?? 60) * 1000,
41
+ limit: Number(process.env.THROTTLE_LIMIT ?? 100),
42
+ },
43
+ ]),
44
+ // nestforge:feature:redis
45
+ BullModule.forRoot({
46
+ connection: {
47
+ host: process.env.REDIS_HOST ?? 'localhost',
48
+ port: Number(process.env.REDIS_PORT ?? 6379),
49
+ },
50
+ }),
51
+ // nestforge:feature:redis:end
52
+ PrismaModule,
53
+ // nestforge:feature:auth:enabled
54
+ AuthModule,
55
+ UsersModule,
56
+ // nestforge:feature:auth:enabled:end
57
+ // nestforge:feature:redis
58
+ MailModule,
59
+ // nestforge:feature:redis:end
60
+ HealthModule,
61
+ MetricsModule,
62
+ ],
63
+ })
64
+ export class AppModule implements NestModule {
65
+ configure(consumer: MiddlewareConsumer) {
66
+ // nestforge:feature:auth:session
67
+ if (process.env.ENABLE_CSRF === 'true') {
68
+ consumer.apply(CsrfMiddleware).forRoutes('*');
69
+ }
70
+ // nestforge:feature:auth:session:end
71
+ }
72
+ }
@@ -0,0 +1,283 @@
1
+ import { Body, Controller, Get, HttpCode, HttpStatus, Post, Query, Req, UseGuards } from '@nestjs/common';
2
+ // nestforge:feature:swagger
3
+ import { ApiExcludeEndpoint, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
4
+ // nestforge:feature:swagger:end
5
+ import { Request } from 'express';
6
+ import { AuthService } from './auth.service';
7
+ // nestforge:feature:auth:password
8
+ import { RegisterDto } from './dto/register.dto';
9
+ import { LoginDto } from './dto/login.dto';
10
+ // nestforge:feature:auth:password:end
11
+ // nestforge:feature:auth:token
12
+ import { RefreshTokenDto } from './dto/refresh-token.dto';
13
+ // nestforge:feature:auth:token:end
14
+ // nestforge:feature:redis,auth:password
15
+ import { ForgotPasswordDto } from './dto/forgot-password.dto';
16
+ import { ResetPasswordDto } from './dto/reset-password.dto';
17
+ // nestforge:feature:redis,auth:password:end
18
+ import { Public } from '../common/decorators/public.decorator';
19
+ import { GoogleAuthGuard } from './guards/google-auth.guard';
20
+ import { GithubAuthGuard } from './guards/github-auth.guard';
21
+ import { OAuthProfile } from './strategies/google.strategy';
22
+ // nestforge:feature:auth:token
23
+ import { TokenService } from './token.service';
24
+ // nestforge:feature:auth:token:end
25
+ // nestforge:feature:auth:session
26
+ import { SessionService } from './session.service';
27
+ // nestforge:feature:auth:session:end
28
+
29
+ // nestforge:feature:swagger,auth:token
30
+ const TOKENS_EXAMPLE = {
31
+ accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
32
+ refreshToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
33
+ };
34
+ // nestforge:feature:swagger,auth:token:end
35
+
36
+ // nestforge:feature:swagger
37
+ @ApiTags('auth')
38
+ // nestforge:feature:swagger:end
39
+ @Controller('auth')
40
+ export class AuthController {
41
+ constructor(
42
+ private readonly authService: AuthService,
43
+ // nestforge:feature:auth:token
44
+ private readonly tokenService: TokenService,
45
+ // nestforge:feature:auth:token:end
46
+ // nestforge:feature:auth:session
47
+ private readonly sessionService: SessionService,
48
+ // nestforge:feature:auth:session:end
49
+ ) { }
50
+
51
+ // nestforge:feature:auth:session
52
+ @Public()
53
+ @Get('csrf-token')
54
+ // nestforge:feature:swagger
55
+ @ApiOperation({ summary: 'Emite um token CSRF vinculado à sessão' })
56
+ @ApiResponse({
57
+ status: 200,
58
+ description: 'Token CSRF emitido',
59
+ schema: {
60
+ example: {
61
+ csrfToken: 'a1b2c3d4e5f6...',
62
+ },
63
+ },
64
+ })
65
+ // nestforge:feature:swagger:end
66
+ getCsrfToken(@Req() request: Request) {
67
+ return this.sessionService.issueCsrfToken(request);
68
+ }
69
+ // nestforge:feature:auth:session:end
70
+
71
+ // nestforge:feature:auth:token,auth:password
72
+ @Public()
73
+ @Post('register')
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' } } })
78
+ // nestforge:feature:swagger:end
79
+ async register(@Body() dto: RegisterDto) {
80
+ const user = await this.authService.register(dto);
81
+ return this.tokenService.issueTokens(user.id, user.email, user.role);
82
+ }
83
+
84
+ @Public()
85
+ @Post('login')
86
+ @HttpCode(HttpStatus.OK)
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' } } })
91
+ // nestforge:feature:swagger:end
92
+ async login(@Body() dto: LoginDto) {
93
+ const user = await this.authService.login(dto);
94
+ return this.tokenService.issueTokens(user.id, user.email, user.role);
95
+ }
96
+ // nestforge:feature:auth:token,auth:password:end
97
+
98
+ // nestforge:feature:auth:session
99
+ @Public()
100
+ @Post('register')
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' })
105
+ // nestforge:feature:swagger:end
106
+ async registerWithSession(
107
+ @Body() dto: RegisterDto,
108
+ @Req() request: Request,
109
+ ) {
110
+ const user = await this.authService.register(dto);
111
+ return this.sessionService.establish(request, user);
112
+ }
113
+
114
+ @Public()
115
+ @Post('login')
116
+ @HttpCode(HttpStatus.OK)
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' })
121
+ // nestforge:feature:swagger:end
122
+ async loginWithSession(
123
+ @Body() dto: LoginDto,
124
+ @Req() request: Request,
125
+ ) {
126
+ const user = await this.authService.login(dto);
127
+ return this.sessionService.establish(request, user);
128
+ }
129
+
130
+ @Post('logout')
131
+ @HttpCode(HttpStatus.OK)
132
+ // nestforge:feature:swagger
133
+ @ApiOperation({ summary: 'Encerra a sessão atual' })
134
+ @ApiResponse({ status: 200, description: 'Sessão encerrada com sucesso' })
135
+ // nestforge:feature:swagger:end
136
+ logoutSession(@Req() request: Request) {
137
+ return this.sessionService.destroy(request);
138
+ }
139
+ // nestforge:feature:auth:session:end
140
+
141
+ // nestforge:feature:auth:token
142
+ @Public()
143
+ @Post('refresh')
144
+ @HttpCode(HttpStatus.OK)
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' } } })
149
+ // nestforge:feature:swagger:end
150
+ refresh(@Body() dto: RefreshTokenDto) {
151
+ return this.tokenService.refresh(dto.refreshToken);
152
+ }
153
+
154
+ @Public()
155
+ @Post('logout')
156
+ @HttpCode(HttpStatus.OK)
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' } } })
160
+ // nestforge:feature:swagger:end
161
+ logout(@Body() dto: RefreshTokenDto) {
162
+ return this.tokenService.logout(dto.refreshToken);
163
+ }
164
+ // nestforge:feature:auth:token:end
165
+
166
+ // nestforge:feature:redis,auth:password
167
+ @Public()
168
+ @Post('forgot-password')
169
+ @HttpCode(HttpStatus.OK)
170
+ // nestforge:feature:swagger
171
+ @ApiOperation({ summary: 'Envia um e-mail com instruções para redefinir a senha' })
172
+ @ApiResponse({
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' } },
176
+ })
177
+ // nestforge:feature:swagger:end
178
+ forgotPassword(@Body() dto: ForgotPasswordDto) {
179
+ return this.authService.forgotPassword(dto.email);
180
+ }
181
+
182
+ @Public()
183
+ @Post('reset-password')
184
+ @HttpCode(HttpStatus.OK)
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' } } })
189
+ // nestforge:feature:swagger:end
190
+ resetPassword(@Body() dto: ResetPasswordDto) {
191
+ return this.authService.resetPassword(dto.token, dto.password);
192
+ }
193
+
194
+ @Public()
195
+ @Get('verify-email')
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' } } })
200
+ // nestforge:feature:swagger:end
201
+ verifyEmail(@Query('token') token: string) {
202
+ return this.authService.verifyEmail(token);
203
+ }
204
+ // nestforge:feature:redis,auth:password:end
205
+
206
+ @Public()
207
+ @Get('google')
208
+ @UseGuards(GoogleAuthGuard)
209
+ // nestforge:feature:swagger
210
+ @ApiOperation({ summary: 'Inicia o login via Google (redireciona)' })
211
+ // nestforge:feature:swagger:end
212
+ googleLogin() {
213
+ // o guard redireciona para o consentimento do Google; nada a fazer aqui
214
+ }
215
+
216
+ // nestforge:feature:auth:token
217
+ @Public()
218
+ @Get('google/callback')
219
+ @UseGuards(GoogleAuthGuard)
220
+ // nestforge:feature:swagger
221
+ @ApiExcludeEndpoint()
222
+ // nestforge:feature:swagger:end
223
+ async googleCallback(@Req() req: Request) {
224
+ const user = await this.authService.validateOAuthLogin(req.user as OAuthProfile);
225
+ return this.tokenService.issueTokens(user.id, user.email, user.role);
226
+ }
227
+ // nestforge:feature:auth:token:end
228
+
229
+ // nestforge:feature:auth:session
230
+ @Public()
231
+ @Get('google/callback')
232
+ @UseGuards(GoogleAuthGuard)
233
+ // nestforge:feature:swagger
234
+ @ApiExcludeEndpoint()
235
+ // nestforge:feature:swagger:end
236
+ async googleSessionCallback(@Req() request: Request) {
237
+ const user = await this.authService.validateOAuthLogin(
238
+ request.user as OAuthProfile,
239
+ );
240
+
241
+ return this.sessionService.establish(request, user);
242
+ }
243
+ // nestforge:feature:auth:session:end
244
+
245
+ @Public()
246
+ @Get('github')
247
+ @UseGuards(GithubAuthGuard)
248
+ // nestforge:feature:swagger
249
+ @ApiOperation({ summary: 'Inicia o login via GitHub (redireciona)' })
250
+ // nestforge:feature:swagger:end
251
+ githubLogin() {
252
+ // o guard redireciona para o consentimento do GitHub; nada a fazer aqui
253
+ }
254
+
255
+ // nestforge:feature:auth:token
256
+ @Public()
257
+ @Get('github/callback')
258
+ @UseGuards(GithubAuthGuard)
259
+ // nestforge:feature:swagger
260
+ @ApiExcludeEndpoint()
261
+ // nestforge:feature:swagger:end
262
+ async githubCallback(@Req() req: Request) {
263
+ const user = await this.authService.validateOAuthLogin(req.user as OAuthProfile);
264
+ return this.tokenService.issueTokens(user.id, user.email, user.role);
265
+ }
266
+ // nestforge:feature:auth:token:end
267
+
268
+ // nestforge:feature:auth:session
269
+ @Public()
270
+ @Get('github/callback')
271
+ @UseGuards(GithubAuthGuard)
272
+ // nestforge:feature:swagger
273
+ @ApiExcludeEndpoint()
274
+ // nestforge:feature:swagger:end
275
+ async githubSessionCallback(@Req() request: Request) {
276
+ const user = await this.authService.validateOAuthLogin(
277
+ request.user as OAuthProfile,
278
+ );
279
+
280
+ return this.sessionService.establish(request, user);
281
+ }
282
+ // nestforge:feature:auth:session:end
283
+ }
@@ -0,0 +1,59 @@
1
+ import { Module } from '@nestjs/common';
2
+ // nestforge:feature:auth:token
3
+ import { JwtModule } from '@nestjs/jwt';
4
+ import { TokenService } from './token.service';
5
+ // nestforge:feature:auth:token:end
6
+ import { PassportModule } from '@nestjs/passport';
7
+ import { APP_GUARD } from '@nestjs/core';
8
+ // nestforge:feature:redis
9
+ import { MailModule } from '../mail/mail.module';
10
+ // nestforge:feature:redis:end
11
+ import { AuthService } from './auth.service';
12
+ import { AuthController } from './auth.controller';
13
+ // nestforge:feature:auth:token
14
+ import { JwtStrategy } from './strategies/jwt.strategy';
15
+ import { JwtAuthGuard } from './guards/jwt-auth.guard';
16
+ // nestforge:feature:auth:token:end
17
+ import { GoogleStrategy } from './strategies/google.strategy';
18
+ import { GithubStrategy } from './strategies/github.strategy';
19
+ // nestforge:feature:rbac
20
+ import { RolesGuard } from '../common/guards/roles.guard';
21
+ import { PermissionsGuard } from '../common/guards/permissions.guard';
22
+ // nestforge:feature:rbac:end
23
+ // nestforge:feature:auth:session
24
+ import { SessionAuthGuard } from './guards/session-auth.guard';
25
+ import { SessionService } from './session.service';
26
+ // nestforge:feature:auth:session:end
27
+
28
+ @Module({
29
+ imports: [
30
+ PassportModule,
31
+ // nestforge:feature:auth:token
32
+ JwtModule.register({}),
33
+ // nestforge:feature:auth:token:end
34
+ // nestforge:feature:redis
35
+ MailModule,
36
+ // nestforge:feature:redis:end
37
+ ],
38
+ controllers: [AuthController],
39
+ providers: [
40
+ AuthService,
41
+ // nestforge:feature:auth:token
42
+ TokenService,
43
+ JwtStrategy,
44
+ { provide: APP_GUARD, useClass: JwtAuthGuard },
45
+ // nestforge:feature:auth:token:end
46
+ // nestforge:feature:auth:session
47
+ SessionService,
48
+ { provide: APP_GUARD, useClass: SessionAuthGuard },
49
+ // nestforge:feature:auth:session:end
50
+ GoogleStrategy,
51
+ GithubStrategy,
52
+ // nestforge:feature:rbac
53
+ { provide: APP_GUARD, useClass: RolesGuard },
54
+ { provide: APP_GUARD, useClass: PermissionsGuard },
55
+ // nestforge:feature:rbac:end
56
+ ],
57
+ exports: [AuthService],
58
+ })
59
+ export class AuthModule { }
@@ -0,0 +1,53 @@
1
+ // nestforge:feature-file:auth:password
2
+ import { describe, expect, it, vi, beforeEach } from 'vitest';
3
+ import { ConflictException, UnauthorizedException } from '@nestjs/common';
4
+ import { AuthService } from './auth.service';
5
+ import { PrismaService } from '../database/prisma.service';
6
+ // nestforge:feature:redis
7
+ import { MailService } from '../mail/mail.service';
8
+ // nestforge:feature:redis:end
9
+
10
+ describe('AuthService', () => {
11
+ let authService: AuthService;
12
+ let prisma: any;
13
+ // nestforge:feature:redis
14
+ let mailService: MailService;
15
+ // nestforge:feature:redis:end
16
+
17
+ beforeEach(() => {
18
+ prisma = {
19
+ user: { findUnique: vi.fn(), create: vi.fn() },
20
+ refreshToken: { create: vi.fn(), findUnique: vi.fn(), update: vi.fn(), updateMany: vi.fn() },
21
+ };
22
+
23
+ // nestforge:feature:redis
24
+ mailService = {
25
+ queueVerificationEmail: vi.fn(),
26
+ queuePasswordResetEmail: vi.fn(),
27
+ } as unknown as MailService;
28
+ // nestforge:feature:redis:end
29
+
30
+ authService = new AuthService(
31
+ prisma as PrismaService,
32
+ // nestforge:feature:redis
33
+ mailService,
34
+ // nestforge:feature:redis:end
35
+ );
36
+ });
37
+
38
+ it('deve lançar ConflictException se o e-mail já existir', async () => {
39
+ prisma.user.findUnique.mockResolvedValue({ id: '1', email: 'jeiel@example.com' });
40
+
41
+ await expect(
42
+ authService.register({ name: 'Jeiel', email: 'jeiel@example.com', password: 'senhaForte123' }),
43
+ ).rejects.toBeInstanceOf(ConflictException);
44
+ });
45
+
46
+ it('deve lançar UnauthorizedException com credenciais inválidas', async () => {
47
+ prisma.user.findUnique.mockResolvedValue(null);
48
+
49
+ await expect(
50
+ authService.login({ email: 'naoexiste@example.com', password: 'qualquer123' }),
51
+ ).rejects.toBeInstanceOf(UnauthorizedException);
52
+ });
53
+ });