create-zhx-monorepo 0.2.2 → 2.0.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 (349) hide show
  1. package/README.md +1 -1
  2. package/bin/index.js +0 -0
  3. package/package.json +3 -3
  4. package/templates/monorepo-starter/apps/dashboard/components.json +20 -0
  5. package/templates/monorepo-starter/apps/dashboard/eslint.config.js +1 -0
  6. package/templates/monorepo-starter/apps/dashboard/next-env.d.ts +6 -0
  7. package/templates/monorepo-starter/apps/dashboard/next.config.mjs +30 -0
  8. package/templates/monorepo-starter/apps/dashboard/package.json +43 -0
  9. package/templates/monorepo-starter/apps/dashboard/postcss.config.mjs +1 -0
  10. package/templates/monorepo-starter/apps/dashboard/src/app/(root)/admin/users/[id]/edit/page.tsx +8 -0
  11. package/templates/monorepo-starter/apps/dashboard/src/app/(root)/admin/users/[id]/page.tsx +104 -0
  12. package/templates/monorepo-starter/apps/dashboard/src/app/(root)/admin/users/new/page.tsx +7 -0
  13. package/templates/monorepo-starter/apps/dashboard/src/app/(root)/admin/users/page.tsx +88 -0
  14. package/templates/monorepo-starter/apps/dashboard/src/app/(root)/dashboard/data.json +614 -0
  15. package/templates/monorepo-starter/apps/dashboard/src/app/(root)/dashboard/page.tsx +21 -0
  16. package/templates/monorepo-starter/apps/dashboard/src/app/(root)/layout.tsx +40 -0
  17. package/templates/monorepo-starter/apps/dashboard/src/app/(root)/media/page.tsx +7 -0
  18. package/templates/monorepo-starter/apps/dashboard/src/app/(root)/users/account/page.tsx +75 -0
  19. package/templates/monorepo-starter/apps/dashboard/src/app/auth/[type]/page.tsx +19 -0
  20. package/templates/monorepo-starter/apps/dashboard/src/app/auth/layout.tsx +11 -0
  21. package/templates/monorepo-starter/apps/dashboard/src/app/auth/verify/page.tsx +11 -0
  22. package/templates/monorepo-starter/apps/dashboard/src/app/favicon.ico +0 -0
  23. package/templates/monorepo-starter/apps/dashboard/src/app/layout.tsx +28 -0
  24. package/templates/monorepo-starter/apps/dashboard/src/components/forms/AuthForm.tsx +345 -0
  25. package/templates/monorepo-starter/apps/dashboard/src/components/forms/CUUserForm.tsx +223 -0
  26. package/templates/monorepo-starter/apps/dashboard/src/components/forms/MediaForm.tsx +35 -0
  27. package/templates/monorepo-starter/apps/dashboard/src/components/forms/SocialAuthField.tsx +56 -0
  28. package/templates/monorepo-starter/apps/dashboard/src/components/layout/AppSidebar.tsx +141 -0
  29. package/templates/monorepo-starter/apps/dashboard/src/components/layout/DashboardChart.tsx +293 -0
  30. package/templates/monorepo-starter/apps/dashboard/src/components/layout/DashboardStats.tsx +104 -0
  31. package/templates/monorepo-starter/apps/dashboard/src/components/layout/Header.tsx +21 -0
  32. package/templates/monorepo-starter/apps/dashboard/src/components/layout/NavMain.tsx +99 -0
  33. package/templates/monorepo-starter/apps/dashboard/src/components/media/LibraryPopup.tsx +25 -0
  34. package/templates/monorepo-starter/apps/dashboard/src/components/media/MediaCard.tsx +175 -0
  35. package/templates/monorepo-starter/apps/dashboard/src/components/media/MediaDetails.tsx +58 -0
  36. package/templates/monorepo-starter/apps/dashboard/src/components/media/MediaGrid.tsx +51 -0
  37. package/templates/monorepo-starter/apps/dashboard/src/components/media/MediaUploader.tsx +182 -0
  38. package/templates/monorepo-starter/apps/dashboard/src/components/media/index.tsx +96 -0
  39. package/templates/monorepo-starter/apps/dashboard/src/components/shared/DateWrapper.tsx +43 -0
  40. package/templates/monorepo-starter/apps/dashboard/src/components/shared/GenericArrayField.tsx +189 -0
  41. package/templates/monorepo-starter/apps/dashboard/src/components/shared/GenericCUForm.tsx +124 -0
  42. package/templates/monorepo-starter/apps/dashboard/src/components/shared/GenericDetailsPage.tsx +291 -0
  43. package/templates/monorepo-starter/apps/dashboard/src/components/shared/GenericFormTable.tsx +189 -0
  44. package/templates/monorepo-starter/apps/dashboard/src/components/shared/GenericTable.tsx +244 -0
  45. package/templates/monorepo-starter/apps/dashboard/src/components/shared/ListPage.tsx +134 -0
  46. package/templates/monorepo-starter/apps/dashboard/src/components/shared/Pagination.tsx +120 -0
  47. package/templates/monorepo-starter/apps/dashboard/src/components/shared/SearchToolbar.tsx +133 -0
  48. package/templates/monorepo-starter/apps/dashboard/src/components/shared/ThemeSwitch.tsx +41 -0
  49. package/templates/monorepo-starter/apps/dashboard/src/components/shared/VerifyAuthPage.tsx +109 -0
  50. package/templates/monorepo-starter/apps/dashboard/src/components/skeleton/CUFormSkeleton.tsx +31 -0
  51. package/templates/monorepo-starter/apps/dashboard/src/components/skeleton/DashboardSke1eton.tsx +135 -0
  52. package/templates/monorepo-starter/apps/dashboard/src/components/skeleton/DetailsPageSkeleton.tsx +64 -0
  53. package/templates/monorepo-starter/apps/dashboard/src/components/skeleton/RootLayoutSkeleton.tsx +106 -0
  54. package/templates/monorepo-starter/apps/dashboard/src/components/skeleton/TableSkeleton.tsx +77 -0
  55. package/templates/monorepo-starter/apps/dashboard/src/components/user/UserAccountSection.tsx +530 -0
  56. package/templates/monorepo-starter/apps/dashboard/src/components/user/UserCard.tsx +54 -0
  57. package/templates/monorepo-starter/apps/dashboard/src/components/user/UserProfileSection.tsx +239 -0
  58. package/templates/monorepo-starter/apps/dashboard/src/components/user/UserSessions.tsx +154 -0
  59. package/templates/monorepo-starter/apps/dashboard/src/hooks/admin.ts +100 -0
  60. package/templates/monorepo-starter/apps/dashboard/src/hooks/auth.ts +59 -0
  61. package/templates/monorepo-starter/apps/dashboard/src/hooks/crud.ts +275 -0
  62. package/templates/monorepo-starter/apps/dashboard/src/hooks/lookup.ts +38 -0
  63. package/templates/monorepo-starter/apps/dashboard/src/hooks/media.ts +34 -0
  64. package/templates/monorepo-starter/apps/dashboard/src/hooks/user.ts +58 -0
  65. package/templates/monorepo-starter/apps/dashboard/src/lib/constants.ts +61 -0
  66. package/templates/monorepo-starter/apps/dashboard/src/providers/index.tsx +15 -0
  67. package/templates/monorepo-starter/apps/dashboard/src/providers/media-library.tsx +48 -0
  68. package/templates/monorepo-starter/apps/dashboard/tsconfig.json +20 -0
  69. package/templates/monorepo-starter/apps/web/components.json +20 -20
  70. package/templates/monorepo-starter/apps/web/eslint.config.js +1 -0
  71. package/templates/monorepo-starter/apps/web/next-env.d.ts +6 -6
  72. package/templates/monorepo-starter/apps/web/next.config.mjs +20 -6
  73. package/templates/monorepo-starter/apps/web/package.json +36 -31
  74. package/templates/monorepo-starter/apps/web/postcss.config.mjs +1 -1
  75. package/templates/monorepo-starter/apps/web/src/app/(root)/layout.tsx +2 -2
  76. package/templates/monorepo-starter/apps/web/src/app/favicon.ico +0 -0
  77. package/templates/monorepo-starter/apps/web/src/app/layout.tsx +13 -9
  78. package/templates/monorepo-starter/apps/web/src/components/Footer.tsx +5 -7
  79. package/templates/monorepo-starter/apps/web/src/components/Header.tsx +5 -9
  80. package/templates/monorepo-starter/apps/web/tsconfig.json +20 -20
  81. package/templates/monorepo-starter/eslint.config.mjs +1 -1
  82. package/templates/monorepo-starter/gitignore +13 -4
  83. package/templates/monorepo-starter/package.json +49 -23
  84. package/templates/monorepo-starter/packages/config/eslint/next.mjs +18 -0
  85. package/templates/monorepo-starter/packages/config/eslint/node.mjs +44 -0
  86. package/templates/monorepo-starter/packages/config/eslint/react.mjs +68 -0
  87. package/templates/monorepo-starter/packages/config/package.json +23 -32
  88. package/templates/monorepo-starter/packages/config/typescript/node.json +25 -0
  89. package/templates/monorepo-starter/packages/config/typescript/react.json +20 -3
  90. package/templates/monorepo-starter/packages/contracts/eslint.config.mjs +1 -0
  91. package/templates/monorepo-starter/packages/contracts/package.json +51 -0
  92. package/templates/monorepo-starter/packages/contracts/src/admin/dto.ts +6 -0
  93. package/templates/monorepo-starter/packages/contracts/src/admin/index.ts +2 -0
  94. package/templates/monorepo-starter/packages/contracts/src/admin/schema.ts +28 -0
  95. package/templates/monorepo-starter/packages/contracts/src/admin/types.d.ts +27 -0
  96. package/templates/monorepo-starter/packages/contracts/src/auth/dto.ts +24 -0
  97. package/templates/monorepo-starter/packages/contracts/src/auth/index.ts +2 -0
  98. package/templates/monorepo-starter/packages/contracts/src/auth/schema.ts +35 -0
  99. package/templates/monorepo-starter/packages/contracts/src/auth/types.d.ts +73 -0
  100. package/templates/monorepo-starter/packages/contracts/src/lib/enums.ts +55 -0
  101. package/templates/monorepo-starter/packages/contracts/src/lib/index.ts +4 -0
  102. package/templates/monorepo-starter/packages/contracts/src/lib/prisma.ts +2 -0
  103. package/templates/monorepo-starter/packages/contracts/src/lib/schema.ts +61 -0
  104. package/templates/monorepo-starter/packages/contracts/src/lib/types.d.ts +149 -0
  105. package/templates/monorepo-starter/packages/contracts/src/lib/utils.ts +8 -0
  106. package/templates/monorepo-starter/packages/contracts/src/media/dto.ts +12 -0
  107. package/templates/monorepo-starter/packages/contracts/src/media/index.ts +2 -0
  108. package/templates/monorepo-starter/packages/contracts/src/media/schema.ts +27 -0
  109. package/templates/monorepo-starter/packages/contracts/src/media/types.d.ts +36 -0
  110. package/templates/monorepo-starter/packages/contracts/src/notification/dto.ts +6 -0
  111. package/templates/monorepo-starter/packages/contracts/src/notification/index.ts +2 -0
  112. package/templates/monorepo-starter/packages/contracts/src/notification/schema.ts +7 -0
  113. package/templates/monorepo-starter/packages/contracts/src/notification/types.d.ts +22 -0
  114. package/templates/monorepo-starter/packages/contracts/src/user/dto.ts +4 -0
  115. package/templates/monorepo-starter/packages/contracts/src/user/index.ts +2 -0
  116. package/templates/monorepo-starter/packages/contracts/src/user/schema.ts +16 -0
  117. package/templates/monorepo-starter/packages/contracts/src/user/types.d.ts +36 -0
  118. package/templates/monorepo-starter/packages/contracts/tsconfig.json +12 -0
  119. package/templates/monorepo-starter/packages/contracts/tsup.config.ts +20 -0
  120. package/templates/monorepo-starter/packages/sdk/eslint.config.mjs +1 -0
  121. package/templates/monorepo-starter/packages/sdk/package.json +31 -0
  122. package/templates/monorepo-starter/packages/sdk/src/admin/index.ts +31 -0
  123. package/templates/monorepo-starter/packages/sdk/src/auth/index.ts +71 -0
  124. package/templates/monorepo-starter/packages/sdk/src/lib/api-client.ts +71 -0
  125. package/templates/monorepo-starter/packages/sdk/src/lib/index.ts +2 -0
  126. package/templates/monorepo-starter/packages/sdk/src/lib/types.ts +40 -0
  127. package/templates/monorepo-starter/packages/sdk/src/media/index.ts +27 -0
  128. package/templates/monorepo-starter/packages/sdk/src/notification/index.ts +10 -0
  129. package/templates/monorepo-starter/packages/sdk/src/public/index.ts +6 -0
  130. package/templates/monorepo-starter/packages/sdk/src/user/index.ts +7 -0
  131. package/templates/monorepo-starter/packages/sdk/tsconfig.json +12 -0
  132. package/templates/monorepo-starter/packages/shared/eslint.config.mjs +1 -0
  133. package/templates/monorepo-starter/packages/shared/package.json +36 -0
  134. package/templates/monorepo-starter/packages/shared/src/constants/app.ts +4 -0
  135. package/templates/monorepo-starter/packages/shared/src/constants/index.ts +1 -0
  136. package/templates/monorepo-starter/packages/shared/src/utils/date.ts +137 -0
  137. package/templates/monorepo-starter/packages/shared/src/utils/identifier.ts +11 -0
  138. package/templates/monorepo-starter/packages/shared/src/utils/index.ts +2 -0
  139. package/templates/monorepo-starter/packages/shared/tsconfig.json +12 -0
  140. package/templates/monorepo-starter/packages/shared/tsup.config.ts +16 -0
  141. package/templates/monorepo-starter/packages/templates/eslint.config.mjs +1 -0
  142. package/templates/monorepo-starter/packages/templates/package.json +38 -0
  143. package/templates/monorepo-starter/packages/templates/src/email/auth/disableMfa.tsx +40 -0
  144. package/templates/monorepo-starter/packages/templates/src/email/auth/index.ts +10 -0
  145. package/templates/monorepo-starter/packages/templates/src/email/auth/resetPassword.tsx +41 -0
  146. package/templates/monorepo-starter/packages/templates/src/email/auth/securityAlert.tsx +21 -0
  147. package/templates/monorepo-starter/packages/templates/src/email/auth/setPassword.tsx +42 -0
  148. package/templates/monorepo-starter/packages/templates/src/email/auth/signin.tsx +19 -0
  149. package/templates/monorepo-starter/packages/templates/src/email/auth/signup.tsx +24 -0
  150. package/templates/monorepo-starter/packages/templates/src/email/auth/updateIdentifier.tsx +79 -0
  151. package/templates/monorepo-starter/packages/templates/src/email/auth/updateMfa.tsx +40 -0
  152. package/templates/monorepo-starter/packages/templates/src/email/auth/verifyIdentifier.tsx +42 -0
  153. package/templates/monorepo-starter/packages/templates/src/email/auth/verifyMfa.tsx +23 -0
  154. package/templates/monorepo-starter/packages/templates/src/email/components/actionBlock.tsx +39 -0
  155. package/templates/monorepo-starter/packages/templates/src/email/components/footer.tsx +0 -0
  156. package/templates/monorepo-starter/packages/templates/src/email/components/greeting.tsx +11 -0
  157. package/templates/monorepo-starter/packages/templates/src/email/components/header.tsx +15 -0
  158. package/templates/monorepo-starter/packages/templates/src/email/components/layout.tsx +33 -0
  159. package/templates/monorepo-starter/packages/templates/src/email/components/numericCode.tsx +16 -0
  160. package/templates/monorepo-starter/packages/templates/src/email/index.ts +2 -0
  161. package/templates/monorepo-starter/packages/templates/src/email/service/accountReactivated.tsx +31 -0
  162. package/templates/monorepo-starter/packages/templates/src/email/service/accountSuspended.tsx +37 -0
  163. package/templates/monorepo-starter/packages/templates/src/email/service/index.ts +2 -0
  164. package/templates/monorepo-starter/packages/templates/src/email/test.tsx +141 -0
  165. package/templates/monorepo-starter/packages/templates/src/index.ts +1 -0
  166. package/templates/monorepo-starter/packages/templates/src/lib/constants.ts +22 -0
  167. package/templates/monorepo-starter/packages/templates/src/lib/utils.ts +19 -0
  168. package/templates/monorepo-starter/packages/templates/src/types/global.d.ts +37 -0
  169. package/templates/monorepo-starter/packages/templates/tsconfig.json +13 -0
  170. package/templates/monorepo-starter/packages/templates/tsup.config.ts +23 -0
  171. package/templates/monorepo-starter/packages/ui/components.json +1 -1
  172. package/templates/monorepo-starter/packages/ui/eslint.config.mjs +1 -4
  173. package/templates/monorepo-starter/packages/ui/package.json +81 -38
  174. package/templates/monorepo-starter/packages/ui/src/components/accordion.tsx +66 -0
  175. package/templates/monorepo-starter/packages/ui/src/components/airport-search-field.tsx +203 -0
  176. package/templates/monorepo-starter/packages/ui/src/components/alert-dialog.tsx +157 -0
  177. package/templates/monorepo-starter/packages/ui/src/components/alert.tsx +66 -0
  178. package/templates/monorepo-starter/packages/ui/src/components/aspect-ratio.tsx +11 -0
  179. package/templates/monorepo-starter/packages/ui/src/components/avatar.tsx +53 -0
  180. package/templates/monorepo-starter/packages/ui/src/components/badge.tsx +46 -0
  181. package/templates/monorepo-starter/packages/ui/src/components/breadcrumb.tsx +109 -0
  182. package/templates/monorepo-starter/packages/ui/src/components/button-group.tsx +83 -0
  183. package/templates/monorepo-starter/packages/ui/src/components/button.tsx +2 -1
  184. package/templates/monorepo-starter/packages/ui/src/components/calendar.tsx +220 -0
  185. package/templates/monorepo-starter/packages/ui/src/components/card.tsx +92 -0
  186. package/templates/monorepo-starter/packages/ui/src/components/carousel.tsx +241 -0
  187. package/templates/monorepo-starter/packages/ui/src/components/chart.tsx +357 -0
  188. package/templates/monorepo-starter/packages/ui/src/components/checkbox.tsx +32 -0
  189. package/templates/monorepo-starter/packages/ui/src/components/collapsible.tsx +33 -0
  190. package/templates/monorepo-starter/packages/ui/src/components/combobox-field.tsx +181 -0
  191. package/templates/monorepo-starter/packages/ui/src/components/combobox.tsx +309 -0
  192. package/templates/monorepo-starter/packages/ui/src/components/command.tsx +184 -0
  193. package/templates/monorepo-starter/packages/ui/src/components/context-menu.tsx +252 -0
  194. package/templates/monorepo-starter/packages/ui/src/components/date-field.tsx +65 -0
  195. package/templates/monorepo-starter/packages/ui/src/components/dialog.tsx +143 -0
  196. package/templates/monorepo-starter/packages/ui/src/components/direction.tsx +22 -0
  197. package/templates/monorepo-starter/packages/ui/src/components/drawer.tsx +135 -0
  198. package/templates/monorepo-starter/packages/ui/src/components/dropdown-menu.tsx +257 -0
  199. package/templates/monorepo-starter/packages/ui/src/components/empty.tsx +104 -0
  200. package/templates/monorepo-starter/packages/ui/src/components/field.tsx +248 -0
  201. package/templates/monorepo-starter/packages/ui/src/components/form.tsx +197 -0
  202. package/templates/monorepo-starter/packages/ui/src/components/hover-card.tsx +44 -0
  203. package/templates/monorepo-starter/packages/ui/src/components/input-field.tsx +116 -0
  204. package/templates/monorepo-starter/packages/ui/src/components/input-group.tsx +170 -0
  205. package/templates/monorepo-starter/packages/ui/src/components/input-otp.tsx +77 -0
  206. package/templates/monorepo-starter/packages/ui/src/components/input.tsx +44 -0
  207. package/templates/monorepo-starter/packages/ui/src/components/item.tsx +193 -0
  208. package/templates/monorepo-starter/packages/ui/src/components/kbd.tsx +28 -0
  209. package/templates/monorepo-starter/packages/ui/src/components/label.tsx +24 -0
  210. package/templates/monorepo-starter/packages/ui/src/components/menubar.tsx +276 -0
  211. package/templates/monorepo-starter/packages/ui/src/components/native-select.tsx +53 -0
  212. package/templates/monorepo-starter/packages/ui/src/components/navigation-menu.tsx +168 -0
  213. package/templates/monorepo-starter/packages/ui/src/components/otp-modal.tsx +125 -0
  214. package/templates/monorepo-starter/packages/ui/src/components/pagination.tsx +127 -0
  215. package/templates/monorepo-starter/packages/ui/src/components/popover.tsx +48 -0
  216. package/templates/monorepo-starter/packages/ui/src/components/progress.tsx +31 -0
  217. package/templates/monorepo-starter/packages/ui/src/components/radio-group.tsx +45 -0
  218. package/templates/monorepo-starter/packages/ui/src/components/resizable.tsx +53 -0
  219. package/templates/monorepo-starter/packages/ui/src/components/scroll-area.tsx +58 -0
  220. package/templates/monorepo-starter/packages/ui/src/components/select-field.tsx +165 -0
  221. package/templates/monorepo-starter/packages/ui/src/components/select.tsx +190 -0
  222. package/templates/monorepo-starter/packages/ui/src/components/separator.tsx +28 -0
  223. package/templates/monorepo-starter/packages/ui/src/components/sheet.tsx +139 -0
  224. package/templates/monorepo-starter/packages/ui/src/components/sidebar.tsx +728 -0
  225. package/templates/monorepo-starter/packages/ui/src/components/skeleton.tsx +13 -0
  226. package/templates/monorepo-starter/packages/ui/src/components/slider.tsx +63 -0
  227. package/templates/monorepo-starter/packages/ui/src/components/sonner.tsx +57 -0
  228. package/templates/monorepo-starter/packages/ui/src/components/spinner.tsx +16 -0
  229. package/templates/monorepo-starter/packages/ui/src/components/switch-field.tsx +22 -0
  230. package/templates/monorepo-starter/packages/ui/src/components/switch.tsx +35 -0
  231. package/templates/monorepo-starter/packages/ui/src/components/table.tsx +120 -0
  232. package/templates/monorepo-starter/packages/ui/src/components/tabs.tsx +66 -0
  233. package/templates/monorepo-starter/packages/ui/src/components/textarea.tsx +18 -0
  234. package/templates/monorepo-starter/packages/ui/src/components/toggle-group.tsx +83 -0
  235. package/templates/monorepo-starter/packages/ui/src/components/toggle.tsx +47 -0
  236. package/templates/monorepo-starter/packages/ui/src/components/tooltip.tsx +61 -0
  237. package/templates/monorepo-starter/packages/ui/src/hooks/use-confirm.ts +12 -0
  238. package/templates/monorepo-starter/packages/ui/src/hooks/use-dialog.ts +12 -0
  239. package/templates/monorepo-starter/packages/ui/src/hooks/use-mobile.ts +21 -0
  240. package/templates/monorepo-starter/packages/ui/src/lib/utils.ts +38 -3
  241. package/templates/monorepo-starter/packages/ui/src/provider/confirm-dialog.tsx +99 -0
  242. package/templates/monorepo-starter/packages/ui/src/provider/dialog.tsx +62 -0
  243. package/templates/monorepo-starter/packages/ui/src/provider/index.tsx +30 -0
  244. package/templates/monorepo-starter/packages/ui/src/provider/react-query.tsx +11 -0
  245. package/templates/monorepo-starter/{apps/web/src/providers → packages/ui/src/provider}/theme.tsx +5 -7
  246. package/templates/monorepo-starter/packages/ui/src/styles/globals.css +109 -61
  247. package/templates/monorepo-starter/packages/ui/src/types/airports-data.d.ts +21 -0
  248. package/templates/monorepo-starter/packages/ui/tsconfig.json +1 -3
  249. package/templates/monorepo-starter/pnpm-lock.yaml +17765 -12441
  250. package/templates/monorepo-starter/pnpm-workspace.yaml +3 -16
  251. package/templates/monorepo-starter/server/.env.example +7 -5
  252. package/templates/monorepo-starter/server/eslint.config.mjs +1 -4
  253. package/templates/monorepo-starter/server/package.json +129 -97
  254. package/templates/monorepo-starter/server/prisma/schema.prisma +170 -92
  255. package/templates/monorepo-starter/server/prisma/seed-functions.ts +0 -0
  256. package/templates/monorepo-starter/server/prisma/seed.ts +0 -0
  257. package/templates/monorepo-starter/server/prisma.config.ts +9 -9
  258. package/templates/monorepo-starter/server/scripts/admin-bootstrap.ts +61 -0
  259. package/templates/monorepo-starter/server/scripts/gen-module.sh +20 -0
  260. package/templates/monorepo-starter/server/scripts/gen-soft-delete.ts +52 -0
  261. package/templates/monorepo-starter/server/src/app.module.ts +35 -28
  262. package/templates/monorepo-starter/server/src/lib/constants/index.ts +59 -0
  263. package/templates/monorepo-starter/server/src/lib/decorators/boolean-query.decorator.ts +18 -0
  264. package/templates/monorepo-starter/server/src/lib/decorators/logger.decorator.ts +1 -1
  265. package/templates/monorepo-starter/server/src/lib/decorators/oauth.decorator.ts +7 -0
  266. package/templates/monorepo-starter/server/src/lib/decorators/user.decorator.ts +10 -0
  267. package/templates/monorepo-starter/server/src/lib/filters/exceptions.filter.ts +169 -24
  268. package/templates/monorepo-starter/server/src/lib/guards/auth.guard.ts +29 -65
  269. package/templates/monorepo-starter/server/src/lib/guards/oauth.guard.ts +28 -0
  270. package/templates/monorepo-starter/server/src/lib/interceptors/response.interceptor.ts +42 -5
  271. package/templates/monorepo-starter/server/src/lib/middleware/cache.middleware.ts +24 -0
  272. package/templates/monorepo-starter/server/src/lib/schemas/env.schema.ts +25 -5
  273. package/templates/monorepo-starter/server/src/lib/utils/client.utils.ts +95 -0
  274. package/templates/monorepo-starter/server/src/lib/utils/cookie.util.ts +4 -3
  275. package/templates/monorepo-starter/server/src/main.ts +20 -10
  276. package/templates/monorepo-starter/server/src/modules/admin/admin.controller.ts +54 -0
  277. package/templates/monorepo-starter/server/src/modules/admin/admin.module.ts +13 -0
  278. package/templates/monorepo-starter/server/src/modules/admin/admin.service.ts +134 -0
  279. package/templates/monorepo-starter/server/src/modules/auth/auth.controller.ts +60 -18
  280. package/templates/monorepo-starter/server/src/modules/auth/auth.module.ts +3 -2
  281. package/templates/monorepo-starter/server/src/modules/auth/auth.service.ts +354 -307
  282. package/templates/monorepo-starter/server/src/modules/auth/oauth.controller.ts +50 -28
  283. package/templates/monorepo-starter/server/src/modules/auth/oauth.service.ts +59 -34
  284. package/templates/monorepo-starter/server/src/modules/auth/otp.service.ts +29 -36
  285. package/templates/monorepo-starter/server/src/modules/cache/cache.module.ts +28 -0
  286. package/templates/monorepo-starter/server/src/modules/cache/cache.service.ts +33 -0
  287. package/templates/monorepo-starter/server/src/modules/env/env.service.ts +4 -3
  288. package/templates/monorepo-starter/server/src/modules/logger/logger.module.ts +1 -0
  289. package/templates/monorepo-starter/server/src/modules/logger/logger.service.ts +1 -1
  290. package/templates/monorepo-starter/server/src/modules/logger/winston.config.ts +15 -1
  291. package/templates/monorepo-starter/server/src/modules/media/cloudinary.provider.ts +14 -0
  292. package/templates/monorepo-starter/server/src/modules/media/cloudinary.service.ts +62 -0
  293. package/templates/monorepo-starter/server/src/modules/media/media.controller.ts +72 -0
  294. package/templates/monorepo-starter/server/src/modules/media/media.module.ts +13 -0
  295. package/templates/monorepo-starter/server/src/modules/media/media.service.ts +146 -0
  296. package/templates/monorepo-starter/server/src/modules/notification/email.service.ts +30 -0
  297. package/templates/monorepo-starter/server/src/modules/notification/messaging.service.ts +50 -0
  298. package/templates/monorepo-starter/server/src/modules/notification/notification.controller.ts +44 -0
  299. package/templates/monorepo-starter/server/src/modules/notification/notification.module.ts +7 -3
  300. package/templates/monorepo-starter/server/src/modules/notification/notification.service.ts +121 -78
  301. package/templates/monorepo-starter/server/src/modules/notification/push.service.ts +92 -0
  302. package/templates/monorepo-starter/server/src/modules/prisma/prisma.extension.ts +84 -56
  303. package/templates/monorepo-starter/server/src/modules/prisma/prisma.service.ts +10 -9
  304. package/templates/monorepo-starter/server/src/modules/prisma/soft-delete.models.ts +7 -0
  305. package/templates/monorepo-starter/server/src/modules/public/public.controller.ts +3 -2
  306. package/templates/monorepo-starter/server/src/modules/public/public.module.ts +5 -4
  307. package/templates/monorepo-starter/server/src/modules/public/public.service.ts +7 -4
  308. package/templates/monorepo-starter/server/src/modules/scheduler/cleanup.service.ts +15 -7
  309. package/templates/monorepo-starter/server/src/modules/scheduler/scheduler.module.ts +2 -0
  310. package/templates/monorepo-starter/server/src/modules/token/token.module.ts +3 -4
  311. package/templates/monorepo-starter/server/src/modules/token/token.service.ts +205 -76
  312. package/templates/monorepo-starter/server/src/modules/user/user.controller.ts +21 -0
  313. package/templates/monorepo-starter/server/src/modules/user/user.module.ts +12 -0
  314. package/templates/monorepo-starter/server/src/modules/user/user.service.ts +38 -0
  315. package/templates/monorepo-starter/server/src/types/express.d.ts +6 -2
  316. package/templates/monorepo-starter/server/src/types/index.ts +5 -0
  317. package/templates/monorepo-starter/server/tsconfig.json +17 -12
  318. package/templates/monorepo-starter/server/tsup.config.ts +7 -2
  319. package/templates/monorepo-starter/tsconfig.json +1 -1
  320. package/templates/monorepo-starter/turbo.json +1 -1
  321. package/templates/monorepo-starter/apps/web/eslint.config.mjs +0 -4
  322. package/templates/monorepo-starter/apps/web/src/app/(auth)/layout.tsx +0 -7
  323. package/templates/monorepo-starter/apps/web/src/app/globals.css +0 -1
  324. package/templates/monorepo-starter/apps/web/src/components/ThemeSwitch.tsx +0 -34
  325. package/templates/monorepo-starter/apps/web/src/providers/index.tsx +0 -10
  326. package/templates/monorepo-starter/apps/web/src/types/index.d.ts +0 -16
  327. package/templates/monorepo-starter/packages/config/eslint/base.js +0 -31
  328. package/templates/monorepo-starter/packages/config/eslint/nest.js +0 -26
  329. package/templates/monorepo-starter/packages/config/eslint/next.js +0 -39
  330. package/templates/monorepo-starter/packages/config/eslint/react.js +0 -30
  331. package/templates/monorepo-starter/packages/config/typescript/base.json +0 -31
  332. package/templates/monorepo-starter/packages/config/typescript/nest.json +0 -14
  333. package/templates/monorepo-starter/packages/config/typescript/next.json +0 -10
  334. package/templates/monorepo-starter/packages/ui/tsconfig.lint.json +0 -8
  335. package/templates/monorepo-starter/server/README.md +0 -63
  336. package/templates/monorepo-starter/server/scripts/generate.sh +0 -14
  337. package/templates/monorepo-starter/server/src/lib/dto/auth.dto.ts +0 -64
  338. package/templates/monorepo-starter/server/src/lib/dto/security-setting.dto.ts +0 -21
  339. package/templates/monorepo-starter/server/src/lib/pipes/validation.pipe.ts +0 -7
  340. package/templates/monorepo-starter/server/src/lib/templates/notification.templates.ts +0 -243
  341. package/templates/monorepo-starter/server/src/lib/utils/general.util.ts +0 -24
  342. package/templates/monorepo-starter/server/src/modules/auth/role.service.ts +0 -99
  343. package/templates/monorepo-starter/server/src/modules/auth/security-setting.service.ts +0 -102
  344. package/templates/monorepo-starter/server/src/modules/template/template.module.ts +0 -8
  345. package/templates/monorepo-starter/server/src/modules/template/template.service.ts +0 -33
  346. package/templates/monorepo-starter/server/src/types/index.d.ts +0 -13
  347. package/templates/monorepo-starter/server/test/app.e2e-spec.ts +0 -25
  348. package/templates/monorepo-starter/server/test/jest-e2e.json +0 -9
  349. /package/templates/monorepo-starter/{packages/ui/src/hooks → apps/dashboard/public}/.gitkeep +0 -0
@@ -1,39 +0,0 @@
1
- import pluginReact from "eslint-plugin-react";
2
- import pluginReactHooks from "eslint-plugin-react-hooks";
3
- import pluginNext from "@next/eslint-plugin-next";
4
- import globals from "globals";
5
- import { config as baseConfig } from "./base.js";
6
-
7
- /** @type {import("eslint").Linter.Config} */
8
- export const config = [
9
- ...baseConfig,
10
- pluginReact.configs.flat.recommended,
11
- {
12
- languageOptions: {
13
- ...pluginReact.configs.flat.recommended.languageOptions,
14
- globals: {
15
- ...globals.browser,
16
- ...globals.serviceworker,
17
- },
18
- },
19
- settings: {
20
- react: { version: "detect" },
21
- },
22
- },
23
- {
24
- plugins: {
25
- "@next/next": pluginNext,
26
- "react-hooks": pluginReactHooks,
27
- },
28
- rules: {
29
- ...pluginNext.configs.recommended.rules,
30
- ...pluginNext.configs["core-web-vitals"].rules,
31
- ...pluginReactHooks.configs.recommended.rules,
32
- "react/react-in-jsx-scope": "off",
33
- "react/prop-types": "off",
34
- },
35
- },
36
- {
37
- ignores: [".next/**"],
38
- },
39
- ];
@@ -1,30 +0,0 @@
1
- import pluginReact from "eslint-plugin-react";
2
- import pluginReactHooks from "eslint-plugin-react-hooks";
3
- import globals from "globals";
4
- import { config as baseConfig } from "./base.js";
5
-
6
- /** @type {import("eslint").Linter.Config} */
7
- export const config = [
8
- ...baseConfig,
9
- pluginReact.configs.flat.recommended,
10
- {
11
- languageOptions: {
12
- ...pluginReact.configs.flat.recommended.languageOptions,
13
- globals: {
14
- ...globals.serviceworker,
15
- ...globals.browser,
16
- },
17
- },
18
- settings: {
19
- react: { version: "detect" },
20
- },
21
- },
22
- {
23
- plugins: { "react-hooks": pluginReactHooks },
24
- rules: {
25
- ...pluginReactHooks.configs.recommended.rules,
26
- "react/react-in-jsx-scope": "off",
27
- "react/prop-types": "off",
28
- },
29
- },
30
- ];
@@ -1,31 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/tsconfig",
3
- "display": "Base Config",
4
- "compilerOptions": {
5
- "target": "es2024",
6
- "lib": ["ES2024"],
7
- "module": "ESNext",
8
- "moduleResolution": "bundler",
9
- "moduleDetection": "force",
10
- "allowJs": true,
11
- "allowSyntheticDefaultImports": true,
12
- "esModuleInterop": true,
13
- "forceConsistentCasingInFileNames": true,
14
- "incremental": true,
15
- "isolatedModules": true,
16
- "noEmit": true,
17
- "declaration": true,
18
- "declarationMap": true,
19
- "resolveJsonModule": true,
20
- "skipLibCheck": true,
21
- "strict": true,
22
- "sourceMap": true,
23
- "noUnusedLocals": true,
24
- "noUnusedParameters": true,
25
- "noFallthroughCasesInSwitch": true,
26
- "noUncheckedIndexedAccess": true,
27
- "verbatimModuleSyntax": true,
28
- "removeComments": true,
29
- "noImplicitAny": true
30
- }
31
- }
@@ -1,14 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/tsconfig",
3
- "display": "NestJS Config",
4
- "extends": "./base.json",
5
- "compilerOptions": {
6
- "emitDecoratorMetadata": true,
7
- "experimentalDecorators": true,
8
- "strictNullChecks": true,
9
- "noImplicitAny": false,
10
- "strictBindCallApply": false,
11
- "incremental": false,
12
- "noEmit": false
13
- }
14
- }
@@ -1,10 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/tsconfig",
3
- "display": "NextJS Config",
4
- "extends": "./base.json",
5
- "compilerOptions": {
6
- "lib": ["ES2024", "DOM", "DOM.Iterable"],
7
- "jsx": "preserve",
8
- "plugins": [{ "name": "next" }]
9
- }
10
- }
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "@workspace/config/typescript/react",
3
- "compilerOptions": {
4
- "outDir": "dist"
5
- },
6
- "include": ["src", "turbo"],
7
- "exclude": ["node_modules", "dist"]
8
- }
@@ -1,63 +0,0 @@
1
- # Monopero Server (NestJS)
2
-
3
- This is a customized NestJS server template for Monopero, featuring a modern TypeScript setup and fast builds with tsup.
4
-
5
- ## Features
6
-
7
- - NestJS with latest best practices
8
- - TypeScript-first development
9
- - Fast builds using tsup
10
- - Ready for monorepo integration
11
-
12
- ## Getting Started
13
-
14
- Install dependencies:
15
-
16
- ```bash
17
- pnpm install
18
- ```
19
-
20
- ## Development
21
-
22
- Start the server in development mode:
23
-
24
- ```bash
25
- pnpm dev
26
- ```
27
-
28
- ## Build & Production
29
-
30
- Build with tsup:
31
-
32
- ```bash
33
- pnpm build
34
- ```
35
-
36
- Run production build:
37
-
38
- ```bash
39
- pnpm start
40
- ```
41
-
42
- ## Testing
43
-
44
- Run unit and e2e tests:
45
-
46
- ```bash
47
- pnpm test
48
- pnpm test:e2e
49
- ```
50
-
51
- ## Structure
52
-
53
- - `src/` – Main source code
54
- - `test/` – E2E tests
55
- - `scripts/` – Utility scripts
56
-
57
- ## Customization
58
-
59
- This template is fully customizable. Adjust configs, add modules, and extend as needed for your project.
60
-
61
- ---
62
-
63
- Made with ❤️ using NestJS & Monopero
@@ -1,14 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Get the name (e.g., "auth") from the argument
4
- NAME=$1
5
-
6
- if [ -z "$NAME" ]; then
7
- echo "❌ Please provide a name (e.g., ./generate.sh auth)"
8
- exit 1
9
- fi
10
-
11
- # Run NestJS CLI commands
12
- nest g module $NAME
13
- nest g service $NAME
14
- nest g controller $NAME
@@ -1,64 +0,0 @@
1
- import { OtpPurpose, OtpType } from "@generated/prisma";
2
- import {
3
- IsEnum,
4
- IsNotEmpty,
5
- IsOptional,
6
- IsString,
7
- MinLength,
8
- } from "class-validator";
9
-
10
- export class SignInDto {
11
- @IsString()
12
- @IsNotEmpty()
13
- identifier!: string;
14
-
15
- @IsString()
16
- @IsNotEmpty()
17
- @MinLength(8)
18
- password!: string;
19
- }
20
-
21
- export class SignUpDto extends SignInDto {
22
- @IsOptional()
23
- @IsString()
24
- username?: string;
25
-
26
- @IsString()
27
- @IsNotEmpty()
28
- firstName!: string;
29
-
30
- @IsOptional()
31
- @IsString()
32
- lastName?: string;
33
- }
34
-
35
- export class RequestOtpDto {
36
- @IsString()
37
- @IsNotEmpty()
38
- identifier!: string;
39
-
40
- @IsEnum(OtpPurpose)
41
- purpose!: OtpPurpose;
42
- }
43
-
44
- export class ValidateOtpDto extends RequestOtpDto {
45
- @IsString()
46
- @IsNotEmpty()
47
- secret!: string;
48
-
49
- @IsOptional()
50
- @IsEnum(OtpType)
51
- type?: OtpType;
52
- }
53
-
54
- export class ResetPasswordDto extends ValidateOtpDto {
55
- @IsString()
56
- @IsNotEmpty()
57
- newPassword!: string;
58
- }
59
-
60
- export class ChangeIdentifierDto extends ValidateOtpDto {
61
- @IsString()
62
- @IsNotEmpty()
63
- newIdentifier!: string;
64
- }
@@ -1,21 +0,0 @@
1
- import { IsBoolean, IsNotEmpty, IsOptional, IsString } from "class-validator";
2
-
3
- export class VerifyBackupCodeDto {
4
- @IsNotEmpty()
5
- @IsString()
6
- code!: string;
7
- }
8
-
9
- export class UpdateSecuritySettingDto {
10
- @IsOptional()
11
- @IsString()
12
- recoveryEmail?: string;
13
-
14
- @IsOptional()
15
- @IsString()
16
- recoveryPhone?: string;
17
-
18
- @IsOptional()
19
- @IsBoolean()
20
- loginAlerts?: boolean;
21
- }
@@ -1,7 +0,0 @@
1
- import { ValidationPipe } from "@nestjs/common";
2
-
3
- export const GlobalValidationPipe = new ValidationPipe({
4
- whitelist: true,
5
- forbidNonWhitelisted: true,
6
- transform: true,
7
- });
@@ -1,243 +0,0 @@
1
- import type { EnvService } from "@modules/env/env.service";
2
- import type { Otp, User } from "@generated/prisma";
3
-
4
- const baseStyles = `
5
- font-family: Arial, sans-serif;
6
- color: #222;
7
- line-height: 1.6;
8
- `;
9
-
10
- const buttonStyles = `
11
- display:inline-block;
12
- padding:12px 20px;
13
- background-color:#000;
14
- color:#fff;
15
- text-decoration:none;
16
- border-radius:6px;
17
- font-weight:bold;
18
- `;
19
-
20
- const appName = "Evorii";
21
-
22
- export interface TemplateProps {
23
- user: User;
24
- otp?: Otp;
25
- identifier?: string;
26
- newIdentifier?: string;
27
- env?: EnvService;
28
- message?: string;
29
- }
30
-
31
- export const signupTemplate = ({ user }: TemplateProps) => ({
32
- subject: `🎉 Welcome to ${appName}, ${user.displayName}!`,
33
- html: `
34
- <div style="${baseStyles}">
35
- <h1>Welcome to ${appName}, ${user.displayName}!</h1>
36
- <p>We’re thrilled to have you join our creative community. Explore thoughtful, customizable gifts designed to express what truly matters.</p>
37
- <p>If you ever need assistance, our support team is just an email away.</p>
38
- <p>— The ${appName} Team</p>
39
- </div>
40
- `,
41
- text: `Welcome to ${appName}, ${user.displayName}! Let's create something meaningful together.`,
42
- });
43
-
44
- export const signinTemplate = ({ user }: TemplateProps) => ({
45
- subject: `🔐 Login Successful — ${appName}`,
46
- html: `
47
- <div style="${baseStyles}">
48
- <h2>Hi ${user.displayName},</h2>
49
- <p>You’ve successfully signed in to your ${appName} account.</p>
50
- <p>If this wasn’t you, please <strong>reset your password</strong> immediately from your account settings.</p>
51
- <p>Stay secure,<br/>The ${appName} Team</p>
52
- </div>
53
- `,
54
- text: `Hi ${user.displayName}, you’ve logged in to ${appName}. If this wasn’t you, reset your password right away.`,
55
- });
56
-
57
- export const setPasswordTemplate = ({
58
- user,
59
- otp,
60
- identifier,
61
- env,
62
- }: TemplateProps) => {
63
- const link = `${env?.get("CLIENT_ENDPOINT")}/set-password?identifier=${identifier}&purpose=${otp?.purpose}&secret=${otp?.secret}&type=${otp?.type}`;
64
- return {
65
- subject: `🔐 Set Up Your ${appName} Password`,
66
- html: `
67
- <div style="${baseStyles}">
68
- <h2>Welcome, ${user.displayName}!</h2>
69
- <p>Let’s get you set up. Click the button below to create your password and complete your account setup.</p>
70
- <a href="${link}" style="${buttonStyles}">Set Password</a>
71
- <p>If you didn’t request this, you can safely ignore this email.</p>
72
- </div>
73
- `,
74
- text: `Hi ${user.displayName}, set your ${appName} password here: ${link}`,
75
- };
76
- };
77
-
78
- export const resetPasswordTemplate = ({
79
- user,
80
- otp,
81
- identifier,
82
- env,
83
- }: TemplateProps) => {
84
- const link = `${env?.get("CLIENT_ENDPOINT")}/reset-password?identifier=${identifier}&purpose=${otp?.purpose}&secret=${otp?.secret}&type=${otp?.type}`;
85
- return {
86
- subject: `🔁 Reset Your ${appName} Password`,
87
- html: `
88
- <div style="${baseStyles}">
89
- <h2>Hi ${user.displayName},</h2>
90
- <p>We received a request to reset your ${appName} password for <strong>${identifier}</strong>.</p>
91
- <p>Your one-time code: <strong>${otp?.secret}</strong></p>
92
- <a href="${link}" style="${buttonStyles}">Reset Password</a>
93
- <p>If you didn’t request this change, please ignore this message.</p>
94
- </div>
95
- `,
96
- text: `Hi ${user.displayName}, your OTP: ${otp?.secret}. Reset your password here: ${link}`,
97
- };
98
- };
99
-
100
- export const verifyIdentifierTemplate = ({
101
- user,
102
- otp,
103
- identifier,
104
- env,
105
- }: TemplateProps) => {
106
- const link = `${env?.get("CLIENT_ENDPOINT")}/verify?identifier=${identifier}&purpose=${otp?.purpose}&secret=${otp?.secret}&type=${otp?.type}`;
107
- return {
108
- subject: `📧 Verify Your ${appName} Account`,
109
- html: `
110
- <div style="${baseStyles}">
111
- <h2>Hi ${user.displayName},</h2>
112
- <p>Welcome! Please verify your ${identifier?.includes("@") ? "email address" : "phone number"} to activate your ${appName} account.</p>
113
- <p>Your verification code: <strong>${otp?.secret}</strong></p>
114
- <a href="${link}" style="${buttonStyles}">Verify Now</a>
115
- </div>
116
- `,
117
- text: `Hi ${user.displayName}, your OTP is ${otp?.secret}. Verify here: ${link}`,
118
- };
119
- };
120
-
121
- export const changeIdentifierTemplate = ({
122
- user,
123
- otp,
124
- identifier,
125
- newIdentifier,
126
- env,
127
- }: TemplateProps) => {
128
- if (otp) {
129
- // OTP exists → request confirmation phase
130
- const link = `${env?.get("CLIENT_ENDPOINT")}/confirm-change?identifier=${newIdentifier}&purpose=${otp.purpose}&secret=${otp.secret}&type=${otp.type}`;
131
- return {
132
- subject: `📨 Confirm Change Request — ${appName}`,
133
- html: `
134
- <div style="${baseStyles}">
135
- <h2>Hi ${user.displayName},</h2>
136
- <p>We received a request to change your ${identifier?.includes("@") ? "email address" : "phone number"}.</p>
137
- <p>Your one-time code: <strong>${otp.secret}</strong></p>
138
- <a href="${link}" style="${buttonStyles}">Confirm Change</a>
139
- <p>If you didn’t make this request, please secure your account immediately.</p>
140
- </div>
141
- `,
142
- text: `Hi ${user.displayName}, OTP: ${otp.secret}. Confirm your change here: ${link}`,
143
- };
144
- } else {
145
- // No OTP → confirmation phase
146
- return {
147
- subject: `✅ ${identifier?.includes("@") ? "Email" : "Phone"} Changed Successfully — ${appName}`,
148
- html: `
149
- <div style="${baseStyles}">
150
- <h2>Hi ${user.displayName},</h2>
151
- <p>Your ${identifier?.includes("@") ? "email address" : "phone number"} has been successfully updated to <strong>${newIdentifier}</strong>.</p>
152
- <p>If this wasn’t you, please update your credentials immediately.</p>
153
- </div>
154
- `,
155
- text: `Hi ${user.displayName}, your ${identifier?.includes("@") ? "email" : "phone"} has been updated to ${newIdentifier}.`,
156
- };
157
- }
158
- };
159
-
160
- export const verifyMfaTemplate = ({ user, otp }: TemplateProps) => ({
161
- subject: `📲 Your ${appName} 2FA Code`,
162
- html: `
163
- <div style="${baseStyles}">
164
- <h2>Hi ${user.displayName},</h2>
165
- <p>Your ${appName} two-factor authentication code is:</p>
166
- <h3>${otp?.secret}</h3>
167
- <p>This code expires shortly — do not share it with anyone.</p>
168
- </div>
169
- `,
170
- text: `Hi ${user.displayName}, your 2FA code is ${otp?.secret}.`,
171
- });
172
-
173
- export const enableMfaTemplate = ({ user, otp }: TemplateProps) => {
174
- if (otp) {
175
- // OTP exists → request confirmation
176
- return {
177
- subject: `🔑 Enable 2FA — OTP Required (${appName})`,
178
- html: `
179
- <div style="${baseStyles}">
180
- <h2>Hi ${user.displayName},</h2>
181
- <p>Use the following code to enable 2FA for your ${appName} account:</p>
182
- <h3>${otp.secret}</h3>
183
- <p>It expires soon. Do not share this code.</p>
184
- </div>
185
- `,
186
- text: `Hi ${user.displayName}, use OTP ${otp.secret} to enable 2FA.`,
187
- };
188
- } else {
189
- // No OTP → success message
190
- return {
191
- subject: `✅ 2FA Enabled — ${appName}`,
192
- html: `
193
- <div style="${baseStyles}">
194
- <h2>Hi ${user.displayName},</h2>
195
- <p>You’ve successfully enabled two-factor authentication on your ${appName} account. Great job strengthening your security!</p>
196
- </div>
197
- `,
198
- text: `Hi ${user.displayName}, 2FA has been enabled on your account.`,
199
- };
200
- }
201
- };
202
-
203
- export const disableMfaTemplate = ({ user, otp }: TemplateProps) => {
204
- if (otp) {
205
- // OTP exists → confirmation needed
206
- return {
207
- subject: `🔑 Disable 2FA — OTP Required (${appName})`,
208
- html: `
209
- <div style="${baseStyles}">
210
- <h2>Hi ${user.displayName},</h2>
211
- <p>Use this code to disable 2FA on your ${appName} account:</p>
212
- <h3>${otp.secret}</h3>
213
- <p>If this wasn’t you, secure your account immediately.</p>
214
- </div>
215
- `,
216
- text: `Hi ${user.displayName}, your OTP to disable 2FA is ${otp.secret}.`,
217
- };
218
- } else {
219
- // No OTP → confirmation
220
- return {
221
- subject: `⚠️ 2FA Disabled — ${appName}`,
222
- html: `
223
- <div style="${baseStyles}">
224
- <h2>Hi ${user.displayName},</h2>
225
- <p>Two-factor authentication has been disabled on your ${appName} account. If this wasn’t you, please re-enable it immediately.</p>
226
- </div>
227
- `,
228
- text: `Hi ${user.displayName}, 2FA has been disabled. If this wasn’t you, secure your account.`,
229
- };
230
- }
231
- };
232
-
233
- export const securityAlertTemplate = ({ user, message }: TemplateProps) => ({
234
- subject: `⚠️ Security Alert — ${appName}`,
235
- html: `
236
- <div style="${baseStyles}">
237
- <h2>Hi ${user.displayName},</h2>
238
- <p>${message}</p>
239
- <p>If you suspect any suspicious activity, please change your password immediately.</p>
240
- </div>
241
- `,
242
- text: `Hi ${user.displayName}, ${message}`,
243
- });
@@ -1,24 +0,0 @@
1
- import ms, { type StringValue } from "ms";
2
-
3
- export const slugify = (str: string, slug?: string) => {
4
- const base = slug && slug.trim().length > 0 ? slug : str;
5
-
6
- return base
7
- .toLowerCase()
8
- .replace(/\s+/g, "-") // replace spaces with dashes
9
- .replace(/[^\w\-]+/g, "") // remove invalid chars
10
- .replace(/\-\-+/g, "-") // collapse multiple dashes
11
- .replace(/^-+/, "") // trim starting dash
12
- .replace(/-+$/, ""); // trim ending dash
13
- };
14
-
15
- export const parseExpiry = (exp: string, future = false): number => {
16
- const val = ms(exp as StringValue);
17
- if (future) return Date.now() + val;
18
- return val;
19
- };
20
-
21
- export const expiryDate = (exp: string, future = false): Date => {
22
- const val = parseExpiry(exp, future);
23
- return new Date(val);
24
- };
@@ -1,99 +0,0 @@
1
- import { BadRequestException, Injectable } from "@nestjs/common";
2
- import { PrismaService } from "@modules/prisma/prisma.service";
3
- import { LoggerService } from "@modules/logger/logger.service";
4
- import { InjectLogger } from "@decorators/logger.decorator";
5
- import { UserRole } from "@generated/prisma";
6
-
7
- @Injectable()
8
- export class RoleService {
9
- @InjectLogger()
10
- private readonly logger!: LoggerService;
11
-
12
- constructor(private readonly prisma: PrismaService) {}
13
-
14
- /** Assign a role to a user */
15
- async assignRole(userId: string, role: UserRole) {
16
- const existing = await this.prisma.roleAssignment.findFirst({
17
- where: { userId, role },
18
- });
19
-
20
- if (existing) {
21
- throw new BadRequestException(`User already has role '${role}'.`);
22
- }
23
-
24
- const newRole = await this.prisma.roleAssignment.create({
25
- data: { userId, role },
26
- });
27
-
28
- this.logger.log(`✅ Role '${role}' assigned to user ${userId}`, {
29
- userId,
30
- role,
31
- });
32
-
33
- return {
34
- message: `Role '${role}' assigned successfully.`,
35
- data: { newRole },
36
- };
37
- }
38
-
39
- /** Revoke a role from a user */
40
- async revokeRole(userId: string, role: UserRole) {
41
- const roleRecord = await this.prisma.roleAssignment.findFirst({
42
- where: { userId, role },
43
- });
44
-
45
- if (!roleRecord) {
46
- throw new BadRequestException(`User does not have role '${role}'.`);
47
- }
48
-
49
- await this.prisma.roleAssignment.delete({
50
- where: { id: roleRecord.id },
51
- });
52
-
53
- this.logger.log(`🚫 Role '${role}' revoked from user ${userId}`, {
54
- userId,
55
- role,
56
- });
57
-
58
- return { message: `Role '${role}' revoked successfully.` };
59
- }
60
-
61
- /** Get all roles for a user */
62
- async getUserRoles(userId: string) {
63
- const roles = await this.prisma.roleAssignment.findMany({
64
- where: { userId },
65
- select: { role: true },
66
- });
67
-
68
- const list = roles.map((r) => r.role);
69
-
70
- return {
71
- message: `Roles fetched successfully.`,
72
- data: { userId, roles: list },
73
- };
74
- }
75
-
76
- /** Check if user has specific role */
77
- async hasRole(userId: string, role: UserRole) {
78
- const existing = await this.prisma.roleAssignment.findFirst({
79
- where: { userId, role },
80
- });
81
- return !!existing;
82
- }
83
-
84
- /** Update user's roles in bulk (sync) */
85
- async syncRoles(userId: string, roles: UserRole[]) {
86
- await this.prisma.roleAssignment.deleteMany({ where: { userId } });
87
-
88
- await this.prisma.roleAssignment.createMany({
89
- data: roles.map((r) => ({ userId, role: r })),
90
- });
91
-
92
- this.logger.log(`🔄 Roles synced for user ${userId}`, {
93
- userId,
94
- roles,
95
- });
96
-
97
- return { message: "User roles synced successfully.", data: { roles } };
98
- }
99
- }