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,106 @@
1
+ // nestforge:feature-file:auth:password,auth:token
2
+ import { INestApplication } from '@nestjs/common';
3
+ import { PrismaClient, Role } from '@prisma/client';
4
+ import * as bcrypt from 'bcryptjs';
5
+ import request from 'supertest';
6
+ import { createTestApp } from './utils/e2e-setup';
7
+ import { cleanDatabase } from './utils/clean-database';
8
+
9
+ describe('Users (e2e)', () => {
10
+ let app: INestApplication;
11
+ let prisma: PrismaClient;
12
+
13
+ async function createUserWithRole(email: string, password: string, role: Role) {
14
+ const passwordHash = await bcrypt.hash(password, 10);
15
+ await prisma.user.create({
16
+ data: { name: 'Usuário de teste', email, passwordHash, role, emailVerifiedAt: new Date() },
17
+ });
18
+ }
19
+
20
+ async function loginAndGetToken(email: string, password: string) {
21
+ const response = await request(app.getHttpServer())
22
+ .post('/auth/login')
23
+ .send({ email, password })
24
+ .expect(200);
25
+ return response.body.accessToken as string;
26
+ }
27
+
28
+ beforeAll(async () => {
29
+ app = await createTestApp();
30
+ prisma = new PrismaClient();
31
+ });
32
+
33
+ beforeEach(async () => {
34
+ await cleanDatabase(prisma);
35
+ });
36
+
37
+ afterAll(async () => {
38
+ await prisma.$disconnect();
39
+ await app.close();
40
+ });
41
+
42
+ it('rejeita acesso sem token', async () => {
43
+ await request(app.getHttpServer()).get('/users').expect(401);
44
+ });
45
+
46
+ it('ADMIN consegue criar, listar, atualizar e remover um usuário', async () => {
47
+ await createUserWithRole('admin.e2e@example.com', 'senhaForte123', Role.ADMIN);
48
+ const token = await loginAndGetToken('admin.e2e@example.com', 'senhaForte123');
49
+ const server = app.getHttpServer();
50
+
51
+ const createResponse = await request(server)
52
+ .post('/users')
53
+ .set('Authorization', `Bearer ${token}`)
54
+ .send({ name: 'Novo Usuário', email: 'novo.e2e@example.com', password: 'senhaForte123' })
55
+ .expect(201);
56
+
57
+ expect(createResponse.body).not.toHaveProperty('passwordHash');
58
+ const userId = createResponse.body.id;
59
+
60
+ const listResponse = await request(server)
61
+ .get('/users')
62
+ .set('Authorization', `Bearer ${token}`)
63
+ .expect(200);
64
+
65
+ expect(listResponse.body.meta.total).toBeGreaterThanOrEqual(1);
66
+
67
+ await request(server)
68
+ .patch(`/users/${userId}`)
69
+ .set('Authorization', `Bearer ${token}`)
70
+ .send({ name: 'Nome Atualizado' })
71
+ .expect(200);
72
+
73
+ await request(server)
74
+ .delete(`/users/${userId}`)
75
+ .set('Authorization', `Bearer ${token}`)
76
+ .expect(200);
77
+ });
78
+
79
+ // nestforge:feature:rbac
80
+ it('USER consegue ler mas não consegue criar usuário', async () => {
81
+ await createUserWithRole('user.e2e@example.com', 'senhaForte123', Role.USER);
82
+ const token = await loginAndGetToken('user.e2e@example.com', 'senhaForte123');
83
+ const server = app.getHttpServer();
84
+
85
+ await request(server).get('/users').set('Authorization', `Bearer ${token}`).expect(200);
86
+
87
+ await request(server)
88
+ .post('/users')
89
+ .set('Authorization', `Bearer ${token}`)
90
+ .send({ name: 'Não deveria criar', email: 'bloqueado.e2e@example.com', password: 'senhaForte123' })
91
+ .expect(403);
92
+ });
93
+ // nestforge:feature:rbac:end
94
+
95
+ it('GET /users/me retorna o usuário autenticado', async () => {
96
+ await createUserWithRole('me.e2e@example.com', 'senhaForte123', Role.USER);
97
+ const token = await loginAndGetToken('me.e2e@example.com', 'senhaForte123');
98
+
99
+ const response = await request(app.getHttpServer())
100
+ .get('/users/me')
101
+ .set('Authorization', `Bearer ${token}`)
102
+ .expect(200);
103
+
104
+ expect(response.body.email).toBe('me.e2e@example.com');
105
+ });
106
+ });
@@ -0,0 +1,14 @@
1
+ import { PrismaClient } from '@prisma/client';
2
+
3
+ export async function cleanDatabase(prisma: PrismaClient) {
4
+ await prisma.$transaction([
5
+ // nestforge:feature:auth:session
6
+ prisma.session.deleteMany(),
7
+ // nestforge:feature:auth:session:end
8
+ prisma.refreshToken.deleteMany(),
9
+ prisma.passwordResetToken.deleteMany(),
10
+ prisma.emailVerificationToken.deleteMany(),
11
+ prisma.oAuthAccount.deleteMany(),
12
+ prisma.user.deleteMany(),
13
+ ]);
14
+ }
@@ -0,0 +1,58 @@
1
+ import { ClassSerializerInterceptor, INestApplication } from '@nestjs/common';
2
+ import { Reflector } from '@nestjs/core';
3
+ import { Test } from '@nestjs/testing';
4
+ import { NestExpressApplication } from '@nestjs/platform-express';
5
+ // nestforge:feature:validation
6
+ import { ZodValidationPipe } from 'nestjs-zod';
7
+ // nestforge:feature:validation:end
8
+ import { AppModule } from '../../src/app.module';
9
+ import { HttpExceptionFilter } from '../../src/common/filters/http-exception.filter';
10
+ // nestforge:feature:auth:session
11
+ import session from 'express-session';
12
+ import { PrismaSessionStore } from '@quixo3/prisma-session-store';
13
+ import { PrismaService } from '../../src/database/prisma.service';
14
+ // nestforge:feature:auth:session:end
15
+
16
+ export async function createTestApp(): Promise<INestApplication> {
17
+ const moduleRef = await Test.createTestingModule({
18
+ imports: [AppModule],
19
+ }).compile();
20
+
21
+ const app = moduleRef.createNestApplication<NestExpressApplication>();
22
+
23
+ // nestforge:feature:auth:session
24
+ const prisma = app.get(PrismaService);
25
+
26
+ app.use(
27
+ session({
28
+ name: 'nestforge.sid',
29
+ secret: process.env.SESSION_SECRET as string,
30
+ resave: false,
31
+ saveUninitialized: false,
32
+ store: new PrismaSessionStore(prisma, {
33
+ checkPeriod: 2 * 60 * 1000,
34
+ dbRecordIdIsSessionId: true,
35
+ dbRecordIdFunction: undefined,
36
+ }),
37
+ cookie: {
38
+ httpOnly: true,
39
+ secure: false,
40
+ sameSite: 'lax',
41
+ maxAge: Number(
42
+ process.env.SESSION_MAX_AGE ?? 7 * 24 * 60 * 60 * 1000,
43
+ ),
44
+ },
45
+ }),
46
+ );
47
+ // nestforge:feature:auth:session:end
48
+
49
+ // mesmos pipes/filters/interceptors globais do main.ts, pra testar o comportamento real da API
50
+ // nestforge:feature:validation
51
+ app.useGlobalPipes(new ZodValidationPipe());
52
+ // nestforge:feature:validation:end
53
+ app.useGlobalFilters(new HttpExceptionFilter());
54
+ app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)));
55
+
56
+ await app.init();
57
+ return app;
58
+ }
@@ -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
+ });
@@ -0,0 +1,45 @@
1
+ # App
2
+ NODE_ENV=development
3
+ PORT=3000
4
+ APP_URL=http://localhost:3000
5
+ CORS_ORIGINS=http://localhost:5173
6
+
7
+ # Database
8
+ DB_TYPE=postgres
9
+ DATABASE_URL="postgresql://nestforge:nestforge@localhost:5432/nestforge"
10
+
11
+ # JWT
12
+ # nestforge:feature:auth:token
13
+ JWT_ACCESS_SECRET=troque-este-segredo-em-producao
14
+ JWT_ACCESS_EXPIRES_IN=15m
15
+ JWT_REFRESH_SECRET=troque-este-outro-segredo-em-producao
16
+ JWT_REFRESH_EXPIRES_IN=7d
17
+ # nestforge:feature:auth:token:end
18
+
19
+ # Redis
20
+ REDIS_HOST=localhost
21
+ REDIS_PORT=6379
22
+
23
+ # Mail (Mailpit em dev)
24
+ MAIL_HOST=localhost
25
+ MAIL_PORT=1025
26
+ MAIL_FROM="NestForge <no-reply@nestforge.dev>"
27
+
28
+ # OAuth (opcional)
29
+ GOOGLE_CLIENT_ID=
30
+ GOOGLE_CLIENT_SECRET=
31
+ GITHUB_CLIENT_ID=
32
+ GITHUB_CLIENT_SECRET=
33
+
34
+ # Rate limit
35
+ THROTTLE_TTL=60
36
+ THROTTLE_LIMIT=100
37
+
38
+ # nestforge:feature:auth:session
39
+ # Session
40
+ SESSION_SECRET=troque-este-segredo-de-sessao-em-producao
41
+ SESSION_MAX_AGE=604800000
42
+
43
+ # CSRF
44
+ ENABLE_CSRF=true
45
+ # nestforge:feature:auth:session:end
@@ -0,0 +1,38 @@
1
+ NODE_ENV=test
2
+ PORT=3000
3
+ APP_URL=http://localhost:3000
4
+ CORS_ORIGINS=http://localhost:5173
5
+
6
+ # Banco isolado, nunca o de desenvolvimento
7
+ DB_TYPE=postgres
8
+ DATABASE_URL="postgresql://nestforge:nestforge@localhost:5432/nestforge_test"
9
+
10
+ # nestforge:feature:auth:token
11
+ JWT_ACCESS_SECRET=test-access-secret-0123456789
12
+ JWT_ACCESS_EXPIRES_IN=15m
13
+ JWT_REFRESH_SECRET=test-refresh-secret-0123456789
14
+ JWT_REFRESH_EXPIRES_IN=7d
15
+ # nestforge:feature:auth:token:end
16
+
17
+ GOOGLE_CLIENT_ID=test-google-client-id
18
+ GOOGLE_CLIENT_SECRET=test-google-client-secret
19
+ GITHUB_CLIENT_ID=test-github-client-id
20
+ GITHUB_CLIENT_SECRET=test-github-client-secret
21
+
22
+ REDIS_HOST=localhost
23
+ REDIS_PORT=6379
24
+
25
+ MAIL_HOST=localhost
26
+ MAIL_PORT=1025
27
+ MAIL_FROM="NestForge <no-reply@nestforge.dev>"
28
+
29
+ # limite bem mais alto pra não interferir nos testes
30
+ THROTTLE_TTL=60
31
+ THROTTLE_LIMIT=1000
32
+
33
+ # nestforge:feature:auth:session
34
+ SESSION_SECRET=test-session-secret-01234567890123456789
35
+ SESSION_MAX_AGE=604800000
36
+
37
+ ENABLE_CSRF=true
38
+ # nestforge:feature:auth:session:end
@@ -0,0 +1,116 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ build-test-lint:
11
+ runs-on: ubuntu-latest
12
+
13
+ services:
14
+ # nestforge:feature:database:postgres
15
+ postgres:
16
+ image: postgres:16-alpine
17
+ env:
18
+ POSTGRES_USER: nestforge
19
+ POSTGRES_PASSWORD: nestforge
20
+ POSTGRES_DB: nestforge
21
+ ports:
22
+ - 5432:5432
23
+ options: >-
24
+ --health-cmd pg_isready
25
+ --health-interval 10s
26
+ --health-timeout 5s
27
+ --health-retries 5
28
+ # nestforge:feature:database:postgres:end
29
+
30
+ # nestforge:feature:database:mysql
31
+ mysql:
32
+ image: mysql:8
33
+ env:
34
+ MYSQL_USER: nestforge
35
+ MYSQL_PASSWORD: nestforge
36
+ MYSQL_ROOT_PASSWORD: nestforge
37
+ MYSQL_DATABASE: nestforge
38
+ ports:
39
+ - 3306:3306
40
+ options: >-
41
+ --health-cmd "mysqladmin ping -h localhost"
42
+ --health-interval 10s
43
+ --health-timeout 5s
44
+ --health-retries 5
45
+ # nestforge:feature:database:mysql:end
46
+
47
+ # nestforge:feature:redis
48
+ redis:
49
+ image: redis:7-alpine
50
+ ports:
51
+ - 6379:6379
52
+ options: >-
53
+ --health-cmd "redis-cli ping"
54
+ --health-interval 10s
55
+ --health-timeout 5s
56
+ --health-retries 5
57
+ # nestforge:feature:redis:end
58
+
59
+ env:
60
+ # nestforge:feature:database:postgres
61
+ DB_TYPE: postgres
62
+ DATABASE_URL: postgresql://nestforge:nestforge@localhost:5432/nestforge?schema=public
63
+ # nestforge:feature:database:postgres:end
64
+
65
+ # nestforge:feature:database:mysql
66
+ DB_TYPE: mysql
67
+ DATABASE_URL: mysql://nestforge:nestforge@localhost:3306/nestforge
68
+ # nestforge:feature:database:mysql:end
69
+
70
+ # nestforge:feature:database:sqlite
71
+ DB_TYPE: sqlite
72
+ DATABASE_URL: file:./ci-dev.db
73
+ # nestforge:feature:database:sqlite:end
74
+
75
+ # nestforge:feature:auth:token
76
+ JWT_ACCESS_SECRET: ci-access-secret-0123456789
77
+ JWT_REFRESH_SECRET: ci-refresh-secret-0123456789
78
+ # nestforge:feature:auth:token:end
79
+
80
+ steps:
81
+ - name: Checkout
82
+ uses: actions/checkout@v4
83
+
84
+ - name: Setup Node
85
+ uses: actions/setup-node@v4
86
+ with:
87
+ node-version: 20
88
+ cache: npm
89
+
90
+ - name: Instalar dependências
91
+ run: npm ci
92
+
93
+ - name: Rodar migrations
94
+ run: npx typeorm-ts-node-commonjs -d src/database/data-source.ts migration:run
95
+
96
+ - name: Lint
97
+ run: npm run lint
98
+
99
+ - name: Build
100
+ run: npm run build
101
+
102
+ - name: Testes
103
+ run: npm run test
104
+
105
+ # nestforge:feature:database:postgres
106
+ - name: Criar banco de teste
107
+ run: PGPASSWORD=nestforge psql -h localhost -U nestforge -d nestforge -c "CREATE DATABASE nestforge_test;"
108
+ # nestforge:feature:database:postgres:end
109
+
110
+ # nestforge:feature:database:mysql
111
+ - name: Criar banco de teste
112
+ run: mysql -h 127.0.0.1 -u root -pnestforge -e "CREATE DATABASE IF NOT EXISTS nestforge_test;"
113
+ # nestforge:feature:database:mysql:end
114
+
115
+ - name: Testes e2e
116
+ run: npm run test:e2e
@@ -0,0 +1,158 @@
1
+ # Architecture
2
+
3
+ **English** | [Português](ARCHITECTURE.pt-BR.md)
4
+
5
+ This document explains how NestForge with TypeORM is organized and why certain design decisions were made.
6
+
7
+ ## Overview
8
+
9
+ ```text
10
+ Request → main.ts (global pipes, filters, and interceptors)
11
+ → Authentication and authorization guards
12
+ → Controller (validates DTO and delegates)
13
+ → Service (business rules)
14
+ → TypeORM Repository
15
+ → PostgreSQL, MySQL, or SQLite
16
+ → ClassSerializerInterceptor
17
+ → Response
18
+ ```
19
+
20
+ Each domain module follows the same structure:
21
+
22
+ ```text
23
+ <module>/
24
+ ├── dto/ # Zod schemas and DTOs
25
+ ├── entities/ # entities persisted by TypeORM
26
+ ├── <module>.controller.ts # receives the request and calls the service
27
+ ├── <module>.service.ts # business rules
28
+ ├── <module>.service.spec.ts
29
+ └── <module>.module.ts # dependencies, repositories, and exports
30
+ ```
31
+
32
+ Controllers do not access repositories directly. Every operation goes through the service, keeping business rules centralized and testable.
33
+
34
+ Modules register their entities with:
35
+
36
+ TypeOrmModule.forFeature([
37
+ UserEntity,
38
+ ])
39
+
40
+ Services receive repositories with:
41
+
42
+ @InjectRepository(UserEntity) private readonly usersRepository: Repository<UserEntity>
43
+
44
+ The global connection is located in src/database/database.module.ts. PostgreSQL-, MySQL-, and SQLite-specific options are located in src/database/typeorm-options.ts.
45
+
46
+ ## Design decisions
47
+
48
+ ### Why Zod instead of class-validator?
49
+
50
+ With Zod, the schema is the primary source for validation and documentation. nestjs-zod transforms schemas into DTOs, while patchNestJsSwagger() allows Swagger to interpret these schemas.
51
+
52
+ This reduces duplication between validation and documentation decorators.
53
+
54
+ ### Why use TypeORM repositories directly?
55
+
56
+ Repository<Entity> already provides a testable, typed persistence abstraction. Creating another generic repository layer on top would add indirection without benefiting this starter.
57
+
58
+ Unit tests replace repositories with objects containing vi.fn(), without starting a database or the complete Nest application.
59
+
60
+ An additional layer can be created later if the project requires complex persistence rules or multiple data sources.
61
+
62
+ ### Why is synchronize disabled?
63
+
64
+ The template uses:
65
+
66
+ synchronize: false
67
+
68
+ Database changes must go through versioned migrations. This prevents automatic and potentially destructive schema changes, especially in production.
69
+
70
+ Migrations are generated and run with:
71
+
72
+ npm run migration:generate -- src/database/migrations/MigrationName
73
+ npm run migration:run
74
+
75
+ ### Why are permissions a map in code?
76
+
77
+ The ROLE_PERMISSIONS map is suitable for projects with a few fixed roles and makes permissions easy to audit.
78
+
79
+ If the project needs dynamically created roles, the map can be replaced with entities such as Role, Permission, and RolePermission.
80
+
81
+ ### Why BullMQ for email delivery?
82
+
83
+ SMTP is an external operation that can fail or take time. Putting delivery in a queue allows the request to respond after the work is queued, while MailProcessor handles delivery and subsequent retries.
84
+
85
+ ### Why store refresh token hashes?
86
+
87
+ A JWT cannot be revoked before it expires. Storing the hash enables:
88
+
89
+ - logout;
90
+ - refresh token rotation;
91
+ - invalidation after a password change;
92
+ - prevention of revoked token reuse.
93
+
94
+ The original token is not persisted.
95
+
96
+ ### Why does UserEntity use @Exclude()?
97
+
98
+ The repository needs to access passwordHash during operations such as login, but this field must never appear in an HTTP response.
99
+
100
+ @Exclude() combined with ClassSerializerInterceptor creates a serialization barrier that prevents the hash from leaking.
101
+
102
+ ### Why does Session/Cookies use persistent storage?
103
+
104
+ The Session/Cookies strategy uses express-session with connect-typeorm. Sessions are stored in the sessions table instead of process memory.
105
+
106
+ This allows the application to restart or scale without losing all active sessions.
107
+
108
+ ### How does CSRF protection work?
109
+
110
+ With Session/Cookies, the application uses a CSRF token associated with the session. Requests that change state must send this token through the header:
111
+
112
+ x-csrf-token
113
+
114
+ The middleware compares the received token with the token stored in the session.
115
+
116
+ With JWT and a Bearer token, the browser does not automatically send the credential in a cookie, so this CSRF flow is not required.
117
+
118
+ ## Authentication strategies
119
+
120
+ ### JWT
121
+
122
+ 1. Registration or login validates the user.
123
+ 2. TokenService issues access and refresh tokens.
124
+ 3. The refresh token hash is stored in the database.
125
+ 4. JwtAuthGuard validates the Bearer token.
126
+ 5. Refresh revokes the previous token and issues a new pair.
127
+ 6. Logout revokes the refresh token.
128
+
129
+ ### Session/Cookies
130
+
131
+ 1. Registration or login validates the user.
132
+ 2. The session is regenerated to prevent session fixation.
133
+ 3. The user and CSRF token are stored in the session.
134
+ 4. The browser receives the nestforge.sid cookie.
135
+ 5. SessionAuthGuard protects the routes.
136
+ 6. Logout destroys the session.
137
+
138
+ ### OAuth
139
+
140
+ Google and GitHub are linked through OAuthAccountEntity. If the email has not been registered yet, a user is created and associated with the provider.
141
+
142
+ ## Database and entities
143
+
144
+ The main entities are:
145
+
146
+ - UserEntity;
147
+ - OAuthAccountEntity;
148
+ - RefreshTokenEntity, when tokens are enabled;
149
+ - SessionEntity, when Session/Cookies is enabled;
150
+ - password recovery and email verification entities, when applicable.
151
+
152
+ Conditional entities use generator markers so that only the required files and relationships remain in the final project.
153
+
154
+ ## Where to add a module
155
+
156
+ To add a new domain, see docs/adding-a-module.md (docs/adding-a-module.md).
157
+
158
+ ---