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,159 @@
1
+ // nestforge:feature-file:auth:password,auth:session
2
+ import { INestApplication } from '@nestjs/common';
3
+ import { DataSource } from 'typeorm';
4
+ import request from 'supertest';
5
+ import { createTestApp } from './utils/e2e-setup';
6
+ import { cleanDatabase } from './utils/clean-database';
7
+
8
+ describe('Session auth (e2e)', () => {
9
+ let app: INestApplication;
10
+ let dataSource: DataSource;
11
+
12
+ beforeAll(async () => {
13
+ app = await createTestApp();
14
+ dataSource = app.get(DataSource);
15
+ })
16
+
17
+ beforeEach(async () => {
18
+ await cleanDatabase(dataSource);
19
+ });
20
+
21
+ afterAll(async () => {
22
+ if (app) {
23
+ await app.close();
24
+ }
25
+ });
26
+
27
+ it('registra, autentica e encerra uma sessão protegida por CSRF', async () => {
28
+ const agent = request.agent(app.getHttpServer());
29
+
30
+ await agent
31
+ .get('/users/me')
32
+ .expect(401);
33
+
34
+ const csrfResponse = await agent
35
+ .get('/auth/csrf-token')
36
+ .expect(200);
37
+
38
+ const csrfToken = csrfResponse.body.csrfToken as string;
39
+
40
+ expect(csrfToken).toMatch(/^[a-f0-9]{64}$/);
41
+
42
+ // Requisições que alteram estado devem ser rejeitadas sem o token.
43
+ await agent
44
+ .post('/auth/register')
45
+ .send({
46
+ name: 'Jeiel',
47
+ email: 'jeiel.session@example.com',
48
+ password: 'senhaForte123',
49
+ })
50
+ .expect(403);
51
+
52
+ const registerResponse = await agent
53
+ .post('/auth/register')
54
+ .set('x-csrf-token', csrfToken)
55
+ .send({
56
+ name: 'Jeiel',
57
+ email: 'jeiel.session@example.com',
58
+ password: 'senhaForte123',
59
+ })
60
+ .expect(201);
61
+
62
+ expect(registerResponse.body.user).toMatchObject({
63
+ email: 'jeiel.session@example.com',
64
+ });
65
+
66
+ expect(registerResponse.headers['set-cookie']).toEqual(
67
+ expect.arrayContaining([
68
+ expect.stringContaining('nestforge.sid='),
69
+ ]),
70
+ );
71
+
72
+ const authenticatedCsrfToken =
73
+ registerResponse.body.csrfToken as string;
74
+
75
+ expect(authenticatedCsrfToken).toMatch(/^[a-f0-9]{64}$/);
76
+ expect(authenticatedCsrfToken).not.toBe(csrfToken);
77
+
78
+ const authenticatedResponse = await agent
79
+ .get('/users/me')
80
+ .expect(200);
81
+
82
+ expect(authenticatedResponse.body.email).toBe(
83
+ 'jeiel.session@example.com',
84
+ );
85
+
86
+ await agent
87
+ .post('/auth/logout')
88
+ .set('x-csrf-token', authenticatedCsrfToken)
89
+ .expect(200);
90
+
91
+ await agent
92
+ .get('/users/me')
93
+ .expect(401);
94
+ });
95
+
96
+ it('realiza login e renova o token CSRF da sessão', async () => {
97
+ const registrationAgent = request.agent(
98
+ app.getHttpServer(),
99
+ );
100
+
101
+ const registrationCsrfResponse = await registrationAgent
102
+ .get('/auth/csrf-token')
103
+ .expect(200);
104
+
105
+ const registrationCsrfToken =
106
+ registrationCsrfResponse.body.csrfToken as string;
107
+
108
+ const registrationResponse = await registrationAgent
109
+ .post('/auth/register')
110
+ .set('x-csrf-token', registrationCsrfToken)
111
+ .send({
112
+ name: 'Usuário de sessão',
113
+ email: 'login.session@example.com',
114
+ password: 'senhaForte123',
115
+ })
116
+ .expect(201);
117
+
118
+ await registrationAgent
119
+ .post('/auth/logout')
120
+ .set(
121
+ 'x-csrf-token',
122
+ registrationResponse.body.csrfToken,
123
+ )
124
+ .expect(200);
125
+
126
+ const loginAgent = request.agent(app.getHttpServer());
127
+
128
+ const loginCsrfResponse = await loginAgent
129
+ .get('/auth/csrf-token')
130
+ .expect(200);
131
+
132
+ const loginCsrfToken =
133
+ loginCsrfResponse.body.csrfToken as string;
134
+
135
+ const loginResponse = await loginAgent
136
+ .post('/auth/login')
137
+ .set('x-csrf-token', loginCsrfToken)
138
+ .send({
139
+ email: 'login.session@example.com',
140
+ password: 'senhaForte123',
141
+ })
142
+ .expect(200);
143
+
144
+ expect(loginResponse.body.user.email).toBe(
145
+ 'login.session@example.com',
146
+ );
147
+
148
+ expect(loginResponse.body.csrfToken).toMatch(
149
+ /^[a-f0-9]{64}$/,
150
+ );
151
+ expect(loginResponse.body.csrfToken).not.toBe(
152
+ loginCsrfToken,
153
+ );
154
+
155
+ await loginAgent
156
+ .get('/users/me')
157
+ .expect(200);
158
+ });
159
+ });
@@ -0,0 +1,183 @@
1
+ // nestforge:feature-file:auth:password,auth:token
2
+ import { INestApplication } from '@nestjs/common';
3
+ import {
4
+ DataSource,
5
+ Repository,
6
+ } from 'typeorm';
7
+ import * as bcrypt from 'bcryptjs';
8
+ import request from 'supertest';
9
+ import { Role } from '../src/common/constants/role.enum';
10
+ import { UserEntity } from '../src/users/entities/user.entity';
11
+ import { createTestApp } from './utils/e2e-setup';
12
+ import { cleanDatabase } from './utils/clean-database';
13
+
14
+ describe('Users (e2e)', () => {
15
+ let app: INestApplication;
16
+ let dataSource: DataSource;
17
+ let usersRepository: Repository<UserEntity>;
18
+
19
+ async function createUserWithRole(
20
+ email: string,
21
+ password: string,
22
+ role: Role,
23
+ ) {
24
+ const passwordHash = await bcrypt.hash(
25
+ password,
26
+ 10,
27
+ );
28
+
29
+ const user = usersRepository.create({
30
+ name: 'Usuário de teste',
31
+ email,
32
+ passwordHash,
33
+ role,
34
+ emailVerifiedAt: new Date(),
35
+ });
36
+
37
+ await usersRepository.save(user);
38
+ }
39
+
40
+ async function loginAndGetToken(
41
+ email: string,
42
+ password: string,
43
+ ) {
44
+ const response = await request(
45
+ app.getHttpServer(),
46
+ )
47
+ .post('/auth/login')
48
+ .send({ email, password })
49
+ .expect(200);
50
+
51
+ return response.body.accessToken as string;
52
+ }
53
+
54
+ beforeAll(async () => {
55
+ app = await createTestApp();
56
+ dataSource = app.get(DataSource);
57
+ usersRepository =
58
+ dataSource.getRepository(UserEntity);
59
+ });
60
+
61
+ beforeEach(async () => {
62
+ await cleanDatabase(dataSource);
63
+ });
64
+
65
+ afterAll(async () => {
66
+ await app.close();
67
+ });
68
+
69
+ it('rejeita acesso sem token', async () => {
70
+ await request(app.getHttpServer())
71
+ .get('/users')
72
+ .expect(401);
73
+ });
74
+
75
+ it('ADMIN consegue criar, listar, atualizar e remover um usuário', async () => {
76
+ await createUserWithRole(
77
+ 'admin.e2e@example.com',
78
+ 'senhaForte123',
79
+ Role.ADMIN,
80
+ );
81
+
82
+ const token = await loginAndGetToken(
83
+ 'admin.e2e@example.com',
84
+ 'senhaForte123',
85
+ );
86
+
87
+ const server = app.getHttpServer();
88
+
89
+ const createResponse = await request(server)
90
+ .post('/users')
91
+ .set('Authorization', `Bearer ${token}`)
92
+ .send({
93
+ name: 'Novo Usuário',
94
+ email: 'novo.e2e@example.com',
95
+ password: 'senhaForte123',
96
+ })
97
+ .expect(201);
98
+
99
+ expect(createResponse.body).not.toHaveProperty(
100
+ 'passwordHash',
101
+ );
102
+
103
+ const userId = createResponse.body.id;
104
+
105
+ const listResponse = await request(server)
106
+ .get('/users')
107
+ .set('Authorization', `Bearer ${token}`)
108
+ .expect(200);
109
+
110
+ expect(
111
+ listResponse.body.meta.total,
112
+ ).toBeGreaterThanOrEqual(1);
113
+
114
+ await request(server)
115
+ .patch(`/users/${userId}`)
116
+ .set('Authorization', `Bearer ${token}`)
117
+ .send({
118
+ name: 'Nome Atualizado',
119
+ })
120
+ .expect(200);
121
+
122
+ await request(server)
123
+ .delete(`/users/${userId}`)
124
+ .set('Authorization', `Bearer ${token}`)
125
+ .expect(200);
126
+ });
127
+
128
+ // nestforge:feature:rbac
129
+ it('USER consegue ler mas não consegue criar usuário', async () => {
130
+ await createUserWithRole(
131
+ 'user.e2e@example.com',
132
+ 'senhaForte123',
133
+ Role.USER,
134
+ );
135
+
136
+ const token = await loginAndGetToken(
137
+ 'user.e2e@example.com',
138
+ 'senhaForte123',
139
+ );
140
+
141
+ const server = app.getHttpServer();
142
+
143
+ await request(server)
144
+ .get('/users')
145
+ .set('Authorization', `Bearer ${token}`)
146
+ .expect(200);
147
+
148
+ await request(server)
149
+ .post('/users')
150
+ .set('Authorization', `Bearer ${token}`)
151
+ .send({
152
+ name: 'Não deveria criar',
153
+ email: 'bloqueado.e2e@example.com',
154
+ password: 'senhaForte123',
155
+ })
156
+ .expect(403);
157
+ });
158
+ // nestforge:feature:rbac:end
159
+
160
+ it('GET /users/me retorna o usuário autenticado', async () => {
161
+ await createUserWithRole(
162
+ 'me.e2e@example.com',
163
+ 'senhaForte123',
164
+ Role.USER,
165
+ );
166
+
167
+ const token = await loginAndGetToken(
168
+ 'me.e2e@example.com',
169
+ 'senhaForte123',
170
+ );
171
+
172
+ const response = await request(
173
+ app.getHttpServer(),
174
+ )
175
+ .get('/users/me')
176
+ .set('Authorization', `Bearer ${token}`)
177
+ .expect(200);
178
+
179
+ expect(response.body.email).toBe(
180
+ 'me.e2e@example.com',
181
+ );
182
+ });
183
+ });
@@ -0,0 +1,65 @@
1
+ // nestforge:feature-file:auth:enabled
2
+ import { DataSource } from 'typeorm';
3
+ import { UserEntity } from '../../src/users/entities/user.entity';
4
+ import { OAuthAccountEntity } from '../../src/auth/entities/oauth-account.entity';
5
+
6
+ // nestforge:feature:auth:token
7
+ import { RefreshTokenEntity } from '../../src/auth/entities/refresh-token.entity';
8
+ // nestforge:feature:auth:token:end
9
+
10
+ // nestforge:feature:redis,auth:password
11
+ import { PasswordResetTokenEntity } from '../../src/auth/entities/password-reset-token.entity';
12
+ import { EmailVerificationTokenEntity } from '../../src/auth/entities/email-verification-token.entity';
13
+ // nestforge:feature:redis,auth:password:end
14
+
15
+ // nestforge:feature:auth:session
16
+ import { SessionEntity } from '../../src/auth/entities/session.entity';
17
+ // nestforge:feature:auth:session:end
18
+
19
+ export async function cleanDatabase(
20
+ dataSource: DataSource,
21
+ ) {
22
+ await dataSource.transaction(async (manager) => {
23
+ // nestforge:feature:auth:session
24
+ await manager
25
+ .createQueryBuilder()
26
+ .delete()
27
+ .from(SessionEntity)
28
+ .execute();
29
+ // nestforge:feature:auth:session:end
30
+
31
+ // nestforge:feature:auth:token
32
+ await manager
33
+ .createQueryBuilder()
34
+ .delete()
35
+ .from(RefreshTokenEntity)
36
+ .execute();
37
+ // nestforge:feature:auth:token:end
38
+
39
+ // nestforge:feature:redis,auth:password
40
+ await manager
41
+ .createQueryBuilder()
42
+ .delete()
43
+ .from(PasswordResetTokenEntity)
44
+ .execute();
45
+
46
+ await manager
47
+ .createQueryBuilder()
48
+ .delete()
49
+ .from(EmailVerificationTokenEntity)
50
+ .execute();
51
+ // nestforge:feature:redis,auth:password:end
52
+
53
+ await manager
54
+ .createQueryBuilder()
55
+ .delete()
56
+ .from(OAuthAccountEntity)
57
+ .execute();
58
+
59
+ await manager
60
+ .createQueryBuilder()
61
+ .delete()
62
+ .from(UserEntity)
63
+ .execute();
64
+ });
65
+ }
@@ -0,0 +1,77 @@
1
+ import {
2
+ ClassSerializerInterceptor,
3
+ INestApplication,
4
+ } from '@nestjs/common';
5
+ import { Reflector } from '@nestjs/core';
6
+ import { Test } from '@nestjs/testing';
7
+ import { NestExpressApplication } from '@nestjs/platform-express';
8
+
9
+ // nestforge:feature:validation
10
+ import { ZodValidationPipe } from 'nestjs-zod';
11
+ // nestforge:feature:validation:end
12
+
13
+ import { AppModule } from '../../src/app.module';
14
+ import { HttpExceptionFilter } from '../../src/common/filters/http-exception.filter';
15
+
16
+ // nestforge:feature:auth:session
17
+ import session from 'express-session';
18
+ import { TypeormStore } from 'connect-typeorm';
19
+ import { DataSource } from 'typeorm';
20
+ import { SessionEntity } from '../../src/auth/entities/session.entity';
21
+ // nestforge:feature:auth:session:end
22
+
23
+ export async function createTestApp(): Promise<INestApplication> {
24
+ const moduleRef = await Test.createTestingModule({
25
+ imports: [AppModule],
26
+ }).compile();
27
+
28
+ const app =
29
+ moduleRef.createNestApplication<NestExpressApplication>();
30
+
31
+ // nestforge:feature:auth:session
32
+ const dataSource = app.get(DataSource);
33
+ const sessionsRepository =
34
+ dataSource.getRepository(SessionEntity);
35
+
36
+ const sessionMaxAge = Number(
37
+ process.env.SESSION_MAX_AGE ??
38
+ 7 * 24 * 60 * 60 * 1000,
39
+ );
40
+
41
+ app.use(
42
+ session({
43
+ name: 'nestforge.sid',
44
+ secret: process.env.SESSION_SECRET as string,
45
+ resave: false,
46
+ saveUninitialized: false,
47
+ store: new TypeormStore({
48
+ cleanupLimit: 2,
49
+ limitSubquery: false,
50
+ ttl: Math.floor(sessionMaxAge / 1000),
51
+ }).connect(sessionsRepository),
52
+ cookie: {
53
+ httpOnly: true,
54
+ secure: false,
55
+ sameSite: 'lax',
56
+ maxAge: sessionMaxAge,
57
+ },
58
+ }),
59
+ );
60
+ // nestforge:feature:auth:session:end
61
+
62
+ // nestforge:feature:validation
63
+ app.useGlobalPipes(new ZodValidationPipe());
64
+ // nestforge:feature:validation:end
65
+
66
+ app.useGlobalFilters(new HttpExceptionFilter());
67
+
68
+ app.useGlobalInterceptors(
69
+ new ClassSerializerInterceptor(
70
+ app.get(Reflector),
71
+ ),
72
+ );
73
+
74
+ await app.init();
75
+
76
+ return app;
77
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "commonjs",
4
+ "declaration": true,
5
+ "removeComments": true,
6
+ "emitDecoratorMetadata": true,
7
+ "experimentalDecorators": true,
8
+ "allowSyntheticDefaultImports": true,
9
+ "target": "ES2022",
10
+ "sourceMap": true,
11
+ "outDir": "./dist",
12
+ "baseUrl": "./",
13
+ "incremental": true,
14
+ "skipLibCheck": true,
15
+ "strict": true,
16
+ "strictNullChecks": true,
17
+ "noImplicitAny": true,
18
+ "forceConsistentCasingInFileNames": true,
19
+ "moduleResolution": "node",
20
+ "esModuleInterop": true,
21
+ "paths": {
22
+ "@/*": ["src/*"]
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,20 @@
1
+ import { defineConfig } from 'vitest/config';
2
+ import swc from 'unplugin-swc';
3
+
4
+ export default defineConfig({
5
+ plugins: [
6
+ swc.vite({
7
+ module: { type: 'es6' },
8
+ }),
9
+ ],
10
+ test: {
11
+ globals: true,
12
+ root: './',
13
+ environment: 'node',
14
+ include: ['src/**/*.spec.ts'],
15
+ coverage: {
16
+ reporter: ['text', 'html'],
17
+ exclude: ['**/*.module.ts', '**/main.ts'],
18
+ },
19
+ },
20
+ });
@@ -0,0 +1,19 @@
1
+ import swc from 'unplugin-swc';
2
+ import { defineConfig } from 'vitest/config';
3
+
4
+ export default defineConfig({
5
+ plugins: [
6
+ swc.vite({
7
+ module: { type: 'es6' },
8
+ }),
9
+ ],
10
+ test: {
11
+ globals: true,
12
+ root: './',
13
+ environment: 'node',
14
+ include: ['test/**/*.e2e-spec.ts'],
15
+ testTimeout: 30000,
16
+ hookTimeout: 30000,
17
+ fileParallelism: false,
18
+ },
19
+ });