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,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,81 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { PassportModule } from '@nestjs/passport';
3
+ import { APP_GUARD } from '@nestjs/core';
4
+
5
+ // nestforge:feature:auth:token
6
+ import { JwtModule } from '@nestjs/jwt';
7
+ import { TokenService } from './token.service';
8
+ import { JwtStrategy } from './strategies/jwt.strategy';
9
+ import { JwtAuthGuard } from './guards/jwt-auth.guard';
10
+ // nestforge:feature:auth:token:end
11
+
12
+ // nestforge:feature:redis
13
+ import { MailModule } from '../mail/mail.module';
14
+ // nestforge:feature:redis:end
15
+
16
+ import { AuthService } from './auth.service';
17
+ import { AuthController } from './auth.controller';
18
+ import { GoogleStrategy } from './strategies/google.strategy';
19
+ import { GithubStrategy } from './strategies/github.strategy';
20
+
21
+ // nestforge:feature:rbac
22
+ import { RolesGuard } from '../common/guards/roles.guard';
23
+ import { PermissionsGuard } from '../common/guards/permissions.guard';
24
+ // nestforge:feature:rbac:end
25
+
26
+ // nestforge:feature:auth:session
27
+ import { SessionAuthGuard } from './guards/session-auth.guard';
28
+ import { SessionService } from './session.service';
29
+ import { DrizzleSessionStore } from './drizzle-session.store';
30
+ // nestforge:feature:auth:session:end
31
+
32
+ @Module({
33
+ imports: [
34
+ PassportModule,
35
+ // nestforge:feature:auth:token
36
+ JwtModule.register({}),
37
+ // nestforge:feature:auth:token:end
38
+ // nestforge:feature:redis
39
+ MailModule,
40
+ // nestforge:feature:redis:end
41
+ ],
42
+ controllers: [AuthController],
43
+ providers: [
44
+ AuthService,
45
+ // nestforge:feature:auth:token
46
+ TokenService,
47
+ JwtStrategy,
48
+ {
49
+ provide: APP_GUARD,
50
+ useClass: JwtAuthGuard,
51
+ },
52
+ // nestforge:feature:auth:token:end
53
+ // nestforge:feature:auth:session
54
+ DrizzleSessionStore,
55
+ SessionService,
56
+ {
57
+ provide: APP_GUARD,
58
+ useClass: SessionAuthGuard,
59
+ },
60
+ // nestforge:feature:auth:session:end
61
+ GoogleStrategy,
62
+ GithubStrategy,
63
+ // nestforge:feature:rbac
64
+ {
65
+ provide: APP_GUARD,
66
+ useClass: RolesGuard,
67
+ },
68
+ {
69
+ provide: APP_GUARD,
70
+ useClass: PermissionsGuard,
71
+ },
72
+ // nestforge:feature:rbac:end
73
+ ],
74
+ exports: [
75
+ AuthService,
76
+ // nestforge:feature:auth:session
77
+ DrizzleSessionStore,
78
+ // nestforge:feature:auth:session:end
79
+ ],
80
+ })
81
+ export class AuthModule { }
@@ -0,0 +1,111 @@
1
+ // nestforge:feature-file:auth:password
2
+ import {
3
+ beforeEach,
4
+ describe,
5
+ expect,
6
+ it,
7
+ vi,
8
+ } from 'vitest';
9
+ import {
10
+ ConflictException,
11
+ UnauthorizedException,
12
+ } from '@nestjs/common';
13
+ import type { DrizzleDatabase } from '../database/database.types';
14
+ import { AuthService } from './auth.service';
15
+
16
+ // nestforge:feature:redis
17
+ import { MailService } from '../mail/mail.service';
18
+ // nestforge:feature:redis:end
19
+
20
+ function createSelectBuilder<T>(result: T[]) {
21
+ const builder: any = {};
22
+
23
+ builder.from = vi.fn(() => builder);
24
+ builder.innerJoin = vi.fn(() => builder);
25
+ builder.where = vi.fn(() => builder);
26
+ builder.limit = vi.fn(() => builder);
27
+
28
+ builder.then = (
29
+ resolve: (value: T[]) => unknown,
30
+ reject?: (reason: unknown) => unknown,
31
+ ) => Promise.resolve(result).then(resolve, reject);
32
+
33
+ return builder;
34
+ }
35
+
36
+ describe('AuthService', () => {
37
+ let authService: AuthService;
38
+ let database: any;
39
+
40
+ // nestforge:feature:redis
41
+ let mailService: MailService;
42
+ // nestforge:feature:redis:end
43
+
44
+ beforeEach(() => {
45
+ database = {
46
+ select: vi.fn(),
47
+ insert: vi.fn(),
48
+ update: vi.fn(),
49
+ transaction: vi.fn(),
50
+ };
51
+
52
+ // nestforge:feature:redis
53
+ mailService = {
54
+ queueVerificationEmail: vi.fn(),
55
+ queuePasswordResetEmail: vi.fn(),
56
+ } as unknown as MailService;
57
+ // nestforge:feature:redis:end
58
+
59
+ authService = new AuthService(
60
+ database as unknown as DrizzleDatabase,
61
+ // nestforge:feature:redis
62
+ mailService,
63
+ // nestforge:feature:redis:end
64
+ );
65
+ });
66
+
67
+ it('deve lançar ConflictException se o e-mail já existir', async () => {
68
+ database.select.mockReturnValueOnce(
69
+ createSelectBuilder([
70
+ {
71
+ id: 'user-1',
72
+ name: 'Jeiel',
73
+ email: 'jeiel@example.com',
74
+ passwordHash: 'hash-secreto',
75
+ role: 'USER',
76
+ avatarUrl: null,
77
+ emailVerifiedAt: null,
78
+ createdAt: new Date(),
79
+ updatedAt: new Date(),
80
+ },
81
+ ]),
82
+ );
83
+
84
+ await expect(
85
+ authService.register({
86
+ name: 'Jeiel',
87
+ email: 'jeiel@example.com',
88
+ password: 'senhaForte123',
89
+ }),
90
+ ).rejects.toBeInstanceOf(
91
+ ConflictException,
92
+ );
93
+
94
+ expect(database.insert).not.toHaveBeenCalled();
95
+ });
96
+
97
+ it('deve lançar UnauthorizedException com credenciais inválidas', async () => {
98
+ database.select.mockReturnValueOnce(
99
+ createSelectBuilder([]),
100
+ );
101
+
102
+ await expect(
103
+ authService.login({
104
+ email: 'naoexiste@example.com',
105
+ password: 'qualquer123',
106
+ }),
107
+ ).rejects.toBeInstanceOf(
108
+ UnauthorizedException,
109
+ );
110
+ });
111
+ });