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.
- package/README.md +1 -1
- package/bin/index.js +0 -0
- package/package.json +3 -3
- package/templates/monorepo-starter/apps/dashboard/components.json +20 -0
- package/templates/monorepo-starter/apps/dashboard/eslint.config.js +1 -0
- package/templates/monorepo-starter/apps/dashboard/next-env.d.ts +6 -0
- package/templates/monorepo-starter/apps/dashboard/next.config.mjs +30 -0
- package/templates/monorepo-starter/apps/dashboard/package.json +43 -0
- package/templates/monorepo-starter/apps/dashboard/postcss.config.mjs +1 -0
- package/templates/monorepo-starter/apps/dashboard/src/app/(root)/admin/users/[id]/edit/page.tsx +8 -0
- package/templates/monorepo-starter/apps/dashboard/src/app/(root)/admin/users/[id]/page.tsx +104 -0
- package/templates/monorepo-starter/apps/dashboard/src/app/(root)/admin/users/new/page.tsx +7 -0
- package/templates/monorepo-starter/apps/dashboard/src/app/(root)/admin/users/page.tsx +88 -0
- package/templates/monorepo-starter/apps/dashboard/src/app/(root)/dashboard/data.json +614 -0
- package/templates/monorepo-starter/apps/dashboard/src/app/(root)/dashboard/page.tsx +21 -0
- package/templates/monorepo-starter/apps/dashboard/src/app/(root)/layout.tsx +40 -0
- package/templates/monorepo-starter/apps/dashboard/src/app/(root)/media/page.tsx +7 -0
- package/templates/monorepo-starter/apps/dashboard/src/app/(root)/users/account/page.tsx +75 -0
- package/templates/monorepo-starter/apps/dashboard/src/app/auth/[type]/page.tsx +19 -0
- package/templates/monorepo-starter/apps/dashboard/src/app/auth/layout.tsx +11 -0
- package/templates/monorepo-starter/apps/dashboard/src/app/auth/verify/page.tsx +11 -0
- package/templates/monorepo-starter/apps/dashboard/src/app/favicon.ico +0 -0
- package/templates/monorepo-starter/apps/dashboard/src/app/layout.tsx +28 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/forms/AuthForm.tsx +345 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/forms/CUUserForm.tsx +223 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/forms/MediaForm.tsx +35 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/forms/SocialAuthField.tsx +56 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/layout/AppSidebar.tsx +141 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/layout/DashboardChart.tsx +293 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/layout/DashboardStats.tsx +104 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/layout/Header.tsx +21 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/layout/NavMain.tsx +99 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/media/LibraryPopup.tsx +25 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/media/MediaCard.tsx +175 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/media/MediaDetails.tsx +58 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/media/MediaGrid.tsx +51 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/media/MediaUploader.tsx +182 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/media/index.tsx +96 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/shared/DateWrapper.tsx +43 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/shared/GenericArrayField.tsx +189 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/shared/GenericCUForm.tsx +124 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/shared/GenericDetailsPage.tsx +291 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/shared/GenericFormTable.tsx +189 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/shared/GenericTable.tsx +244 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/shared/ListPage.tsx +134 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/shared/Pagination.tsx +120 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/shared/SearchToolbar.tsx +133 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/shared/ThemeSwitch.tsx +41 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/shared/VerifyAuthPage.tsx +109 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/skeleton/CUFormSkeleton.tsx +31 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/skeleton/DashboardSke1eton.tsx +135 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/skeleton/DetailsPageSkeleton.tsx +64 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/skeleton/RootLayoutSkeleton.tsx +106 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/skeleton/TableSkeleton.tsx +77 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/user/UserAccountSection.tsx +530 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/user/UserCard.tsx +54 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/user/UserProfileSection.tsx +239 -0
- package/templates/monorepo-starter/apps/dashboard/src/components/user/UserSessions.tsx +154 -0
- package/templates/monorepo-starter/apps/dashboard/src/hooks/admin.ts +100 -0
- package/templates/monorepo-starter/apps/dashboard/src/hooks/auth.ts +59 -0
- package/templates/monorepo-starter/apps/dashboard/src/hooks/crud.ts +275 -0
- package/templates/monorepo-starter/apps/dashboard/src/hooks/lookup.ts +38 -0
- package/templates/monorepo-starter/apps/dashboard/src/hooks/media.ts +34 -0
- package/templates/monorepo-starter/apps/dashboard/src/hooks/user.ts +58 -0
- package/templates/monorepo-starter/apps/dashboard/src/lib/constants.ts +61 -0
- package/templates/monorepo-starter/apps/dashboard/src/providers/index.tsx +15 -0
- package/templates/monorepo-starter/apps/dashboard/src/providers/media-library.tsx +48 -0
- package/templates/monorepo-starter/apps/dashboard/tsconfig.json +20 -0
- package/templates/monorepo-starter/apps/web/components.json +20 -20
- package/templates/monorepo-starter/apps/web/eslint.config.js +1 -0
- package/templates/monorepo-starter/apps/web/next-env.d.ts +6 -6
- package/templates/monorepo-starter/apps/web/next.config.mjs +20 -6
- package/templates/monorepo-starter/apps/web/package.json +36 -31
- package/templates/monorepo-starter/apps/web/postcss.config.mjs +1 -1
- package/templates/monorepo-starter/apps/web/src/app/(root)/layout.tsx +2 -2
- package/templates/monorepo-starter/apps/web/src/app/favicon.ico +0 -0
- package/templates/monorepo-starter/apps/web/src/app/layout.tsx +13 -9
- package/templates/monorepo-starter/apps/web/src/components/Footer.tsx +5 -7
- package/templates/monorepo-starter/apps/web/src/components/Header.tsx +5 -9
- package/templates/monorepo-starter/apps/web/tsconfig.json +20 -20
- package/templates/monorepo-starter/eslint.config.mjs +1 -1
- package/templates/monorepo-starter/gitignore +13 -4
- package/templates/monorepo-starter/package.json +49 -23
- package/templates/monorepo-starter/packages/config/eslint/next.mjs +18 -0
- package/templates/monorepo-starter/packages/config/eslint/node.mjs +44 -0
- package/templates/monorepo-starter/packages/config/eslint/react.mjs +68 -0
- package/templates/monorepo-starter/packages/config/package.json +23 -32
- package/templates/monorepo-starter/packages/config/typescript/node.json +25 -0
- package/templates/monorepo-starter/packages/config/typescript/react.json +20 -3
- package/templates/monorepo-starter/packages/contracts/eslint.config.mjs +1 -0
- package/templates/monorepo-starter/packages/contracts/package.json +51 -0
- package/templates/monorepo-starter/packages/contracts/src/admin/dto.ts +6 -0
- package/templates/monorepo-starter/packages/contracts/src/admin/index.ts +2 -0
- package/templates/monorepo-starter/packages/contracts/src/admin/schema.ts +28 -0
- package/templates/monorepo-starter/packages/contracts/src/admin/types.d.ts +27 -0
- package/templates/monorepo-starter/packages/contracts/src/auth/dto.ts +24 -0
- package/templates/monorepo-starter/packages/contracts/src/auth/index.ts +2 -0
- package/templates/monorepo-starter/packages/contracts/src/auth/schema.ts +35 -0
- package/templates/monorepo-starter/packages/contracts/src/auth/types.d.ts +73 -0
- package/templates/monorepo-starter/packages/contracts/src/lib/enums.ts +55 -0
- package/templates/monorepo-starter/packages/contracts/src/lib/index.ts +4 -0
- package/templates/monorepo-starter/packages/contracts/src/lib/prisma.ts +2 -0
- package/templates/monorepo-starter/packages/contracts/src/lib/schema.ts +61 -0
- package/templates/monorepo-starter/packages/contracts/src/lib/types.d.ts +149 -0
- package/templates/monorepo-starter/packages/contracts/src/lib/utils.ts +8 -0
- package/templates/monorepo-starter/packages/contracts/src/media/dto.ts +12 -0
- package/templates/monorepo-starter/packages/contracts/src/media/index.ts +2 -0
- package/templates/monorepo-starter/packages/contracts/src/media/schema.ts +27 -0
- package/templates/monorepo-starter/packages/contracts/src/media/types.d.ts +36 -0
- package/templates/monorepo-starter/packages/contracts/src/notification/dto.ts +6 -0
- package/templates/monorepo-starter/packages/contracts/src/notification/index.ts +2 -0
- package/templates/monorepo-starter/packages/contracts/src/notification/schema.ts +7 -0
- package/templates/monorepo-starter/packages/contracts/src/notification/types.d.ts +22 -0
- package/templates/monorepo-starter/packages/contracts/src/user/dto.ts +4 -0
- package/templates/monorepo-starter/packages/contracts/src/user/index.ts +2 -0
- package/templates/monorepo-starter/packages/contracts/src/user/schema.ts +16 -0
- package/templates/monorepo-starter/packages/contracts/src/user/types.d.ts +36 -0
- package/templates/monorepo-starter/packages/contracts/tsconfig.json +12 -0
- package/templates/monorepo-starter/packages/contracts/tsup.config.ts +20 -0
- package/templates/monorepo-starter/packages/sdk/eslint.config.mjs +1 -0
- package/templates/monorepo-starter/packages/sdk/package.json +31 -0
- package/templates/monorepo-starter/packages/sdk/src/admin/index.ts +31 -0
- package/templates/monorepo-starter/packages/sdk/src/auth/index.ts +71 -0
- package/templates/monorepo-starter/packages/sdk/src/lib/api-client.ts +71 -0
- package/templates/monorepo-starter/packages/sdk/src/lib/index.ts +2 -0
- package/templates/monorepo-starter/packages/sdk/src/lib/types.ts +40 -0
- package/templates/monorepo-starter/packages/sdk/src/media/index.ts +27 -0
- package/templates/monorepo-starter/packages/sdk/src/notification/index.ts +10 -0
- package/templates/monorepo-starter/packages/sdk/src/public/index.ts +6 -0
- package/templates/monorepo-starter/packages/sdk/src/user/index.ts +7 -0
- package/templates/monorepo-starter/packages/sdk/tsconfig.json +12 -0
- package/templates/monorepo-starter/packages/shared/eslint.config.mjs +1 -0
- package/templates/monorepo-starter/packages/shared/package.json +36 -0
- package/templates/monorepo-starter/packages/shared/src/constants/app.ts +4 -0
- package/templates/monorepo-starter/packages/shared/src/constants/index.ts +1 -0
- package/templates/monorepo-starter/packages/shared/src/utils/date.ts +137 -0
- package/templates/monorepo-starter/packages/shared/src/utils/identifier.ts +11 -0
- package/templates/monorepo-starter/packages/shared/src/utils/index.ts +2 -0
- package/templates/monorepo-starter/packages/shared/tsconfig.json +12 -0
- package/templates/monorepo-starter/packages/shared/tsup.config.ts +16 -0
- package/templates/monorepo-starter/packages/templates/eslint.config.mjs +1 -0
- package/templates/monorepo-starter/packages/templates/package.json +38 -0
- package/templates/monorepo-starter/packages/templates/src/email/auth/disableMfa.tsx +40 -0
- package/templates/monorepo-starter/packages/templates/src/email/auth/index.ts +10 -0
- package/templates/monorepo-starter/packages/templates/src/email/auth/resetPassword.tsx +41 -0
- package/templates/monorepo-starter/packages/templates/src/email/auth/securityAlert.tsx +21 -0
- package/templates/monorepo-starter/packages/templates/src/email/auth/setPassword.tsx +42 -0
- package/templates/monorepo-starter/packages/templates/src/email/auth/signin.tsx +19 -0
- package/templates/monorepo-starter/packages/templates/src/email/auth/signup.tsx +24 -0
- package/templates/monorepo-starter/packages/templates/src/email/auth/updateIdentifier.tsx +79 -0
- package/templates/monorepo-starter/packages/templates/src/email/auth/updateMfa.tsx +40 -0
- package/templates/monorepo-starter/packages/templates/src/email/auth/verifyIdentifier.tsx +42 -0
- package/templates/monorepo-starter/packages/templates/src/email/auth/verifyMfa.tsx +23 -0
- package/templates/monorepo-starter/packages/templates/src/email/components/actionBlock.tsx +39 -0
- package/templates/monorepo-starter/packages/templates/src/email/components/footer.tsx +0 -0
- package/templates/monorepo-starter/packages/templates/src/email/components/greeting.tsx +11 -0
- package/templates/monorepo-starter/packages/templates/src/email/components/header.tsx +15 -0
- package/templates/monorepo-starter/packages/templates/src/email/components/layout.tsx +33 -0
- package/templates/monorepo-starter/packages/templates/src/email/components/numericCode.tsx +16 -0
- package/templates/monorepo-starter/packages/templates/src/email/index.ts +2 -0
- package/templates/monorepo-starter/packages/templates/src/email/service/accountReactivated.tsx +31 -0
- package/templates/monorepo-starter/packages/templates/src/email/service/accountSuspended.tsx +37 -0
- package/templates/monorepo-starter/packages/templates/src/email/service/index.ts +2 -0
- package/templates/monorepo-starter/packages/templates/src/email/test.tsx +141 -0
- package/templates/monorepo-starter/packages/templates/src/index.ts +1 -0
- package/templates/monorepo-starter/packages/templates/src/lib/constants.ts +22 -0
- package/templates/monorepo-starter/packages/templates/src/lib/utils.ts +19 -0
- package/templates/monorepo-starter/packages/templates/src/types/global.d.ts +37 -0
- package/templates/monorepo-starter/packages/templates/tsconfig.json +13 -0
- package/templates/monorepo-starter/packages/templates/tsup.config.ts +23 -0
- package/templates/monorepo-starter/packages/ui/components.json +1 -1
- package/templates/monorepo-starter/packages/ui/eslint.config.mjs +1 -4
- package/templates/monorepo-starter/packages/ui/package.json +81 -38
- package/templates/monorepo-starter/packages/ui/src/components/accordion.tsx +66 -0
- package/templates/monorepo-starter/packages/ui/src/components/airport-search-field.tsx +203 -0
- package/templates/monorepo-starter/packages/ui/src/components/alert-dialog.tsx +157 -0
- package/templates/monorepo-starter/packages/ui/src/components/alert.tsx +66 -0
- package/templates/monorepo-starter/packages/ui/src/components/aspect-ratio.tsx +11 -0
- package/templates/monorepo-starter/packages/ui/src/components/avatar.tsx +53 -0
- package/templates/monorepo-starter/packages/ui/src/components/badge.tsx +46 -0
- package/templates/monorepo-starter/packages/ui/src/components/breadcrumb.tsx +109 -0
- package/templates/monorepo-starter/packages/ui/src/components/button-group.tsx +83 -0
- package/templates/monorepo-starter/packages/ui/src/components/button.tsx +2 -1
- package/templates/monorepo-starter/packages/ui/src/components/calendar.tsx +220 -0
- package/templates/monorepo-starter/packages/ui/src/components/card.tsx +92 -0
- package/templates/monorepo-starter/packages/ui/src/components/carousel.tsx +241 -0
- package/templates/monorepo-starter/packages/ui/src/components/chart.tsx +357 -0
- package/templates/monorepo-starter/packages/ui/src/components/checkbox.tsx +32 -0
- package/templates/monorepo-starter/packages/ui/src/components/collapsible.tsx +33 -0
- package/templates/monorepo-starter/packages/ui/src/components/combobox-field.tsx +181 -0
- package/templates/monorepo-starter/packages/ui/src/components/combobox.tsx +309 -0
- package/templates/monorepo-starter/packages/ui/src/components/command.tsx +184 -0
- package/templates/monorepo-starter/packages/ui/src/components/context-menu.tsx +252 -0
- package/templates/monorepo-starter/packages/ui/src/components/date-field.tsx +65 -0
- package/templates/monorepo-starter/packages/ui/src/components/dialog.tsx +143 -0
- package/templates/monorepo-starter/packages/ui/src/components/direction.tsx +22 -0
- package/templates/monorepo-starter/packages/ui/src/components/drawer.tsx +135 -0
- package/templates/monorepo-starter/packages/ui/src/components/dropdown-menu.tsx +257 -0
- package/templates/monorepo-starter/packages/ui/src/components/empty.tsx +104 -0
- package/templates/monorepo-starter/packages/ui/src/components/field.tsx +248 -0
- package/templates/monorepo-starter/packages/ui/src/components/form.tsx +197 -0
- package/templates/monorepo-starter/packages/ui/src/components/hover-card.tsx +44 -0
- package/templates/monorepo-starter/packages/ui/src/components/input-field.tsx +116 -0
- package/templates/monorepo-starter/packages/ui/src/components/input-group.tsx +170 -0
- package/templates/monorepo-starter/packages/ui/src/components/input-otp.tsx +77 -0
- package/templates/monorepo-starter/packages/ui/src/components/input.tsx +44 -0
- package/templates/monorepo-starter/packages/ui/src/components/item.tsx +193 -0
- package/templates/monorepo-starter/packages/ui/src/components/kbd.tsx +28 -0
- package/templates/monorepo-starter/packages/ui/src/components/label.tsx +24 -0
- package/templates/monorepo-starter/packages/ui/src/components/menubar.tsx +276 -0
- package/templates/monorepo-starter/packages/ui/src/components/native-select.tsx +53 -0
- package/templates/monorepo-starter/packages/ui/src/components/navigation-menu.tsx +168 -0
- package/templates/monorepo-starter/packages/ui/src/components/otp-modal.tsx +125 -0
- package/templates/monorepo-starter/packages/ui/src/components/pagination.tsx +127 -0
- package/templates/monorepo-starter/packages/ui/src/components/popover.tsx +48 -0
- package/templates/monorepo-starter/packages/ui/src/components/progress.tsx +31 -0
- package/templates/monorepo-starter/packages/ui/src/components/radio-group.tsx +45 -0
- package/templates/monorepo-starter/packages/ui/src/components/resizable.tsx +53 -0
- package/templates/monorepo-starter/packages/ui/src/components/scroll-area.tsx +58 -0
- package/templates/monorepo-starter/packages/ui/src/components/select-field.tsx +165 -0
- package/templates/monorepo-starter/packages/ui/src/components/select.tsx +190 -0
- package/templates/monorepo-starter/packages/ui/src/components/separator.tsx +28 -0
- package/templates/monorepo-starter/packages/ui/src/components/sheet.tsx +139 -0
- package/templates/monorepo-starter/packages/ui/src/components/sidebar.tsx +728 -0
- package/templates/monorepo-starter/packages/ui/src/components/skeleton.tsx +13 -0
- package/templates/monorepo-starter/packages/ui/src/components/slider.tsx +63 -0
- package/templates/monorepo-starter/packages/ui/src/components/sonner.tsx +57 -0
- package/templates/monorepo-starter/packages/ui/src/components/spinner.tsx +16 -0
- package/templates/monorepo-starter/packages/ui/src/components/switch-field.tsx +22 -0
- package/templates/monorepo-starter/packages/ui/src/components/switch.tsx +35 -0
- package/templates/monorepo-starter/packages/ui/src/components/table.tsx +120 -0
- package/templates/monorepo-starter/packages/ui/src/components/tabs.tsx +66 -0
- package/templates/monorepo-starter/packages/ui/src/components/textarea.tsx +18 -0
- package/templates/monorepo-starter/packages/ui/src/components/toggle-group.tsx +83 -0
- package/templates/monorepo-starter/packages/ui/src/components/toggle.tsx +47 -0
- package/templates/monorepo-starter/packages/ui/src/components/tooltip.tsx +61 -0
- package/templates/monorepo-starter/packages/ui/src/hooks/use-confirm.ts +12 -0
- package/templates/monorepo-starter/packages/ui/src/hooks/use-dialog.ts +12 -0
- package/templates/monorepo-starter/packages/ui/src/hooks/use-mobile.ts +21 -0
- package/templates/monorepo-starter/packages/ui/src/lib/utils.ts +38 -3
- package/templates/monorepo-starter/packages/ui/src/provider/confirm-dialog.tsx +99 -0
- package/templates/monorepo-starter/packages/ui/src/provider/dialog.tsx +62 -0
- package/templates/monorepo-starter/packages/ui/src/provider/index.tsx +30 -0
- package/templates/monorepo-starter/packages/ui/src/provider/react-query.tsx +11 -0
- package/templates/monorepo-starter/{apps/web/src/providers → packages/ui/src/provider}/theme.tsx +5 -7
- package/templates/monorepo-starter/packages/ui/src/styles/globals.css +109 -61
- package/templates/monorepo-starter/packages/ui/src/types/airports-data.d.ts +21 -0
- package/templates/monorepo-starter/packages/ui/tsconfig.json +1 -3
- package/templates/monorepo-starter/pnpm-lock.yaml +17765 -12441
- package/templates/monorepo-starter/pnpm-workspace.yaml +3 -16
- package/templates/monorepo-starter/server/.env.example +7 -5
- package/templates/monorepo-starter/server/eslint.config.mjs +1 -4
- package/templates/monorepo-starter/server/package.json +129 -97
- package/templates/monorepo-starter/server/prisma/schema.prisma +170 -92
- package/templates/monorepo-starter/server/prisma/seed-functions.ts +0 -0
- package/templates/monorepo-starter/server/prisma/seed.ts +0 -0
- package/templates/monorepo-starter/server/prisma.config.ts +9 -9
- package/templates/monorepo-starter/server/scripts/admin-bootstrap.ts +61 -0
- package/templates/monorepo-starter/server/scripts/gen-module.sh +20 -0
- package/templates/monorepo-starter/server/scripts/gen-soft-delete.ts +52 -0
- package/templates/monorepo-starter/server/src/app.module.ts +35 -28
- package/templates/monorepo-starter/server/src/lib/constants/index.ts +59 -0
- package/templates/monorepo-starter/server/src/lib/decorators/boolean-query.decorator.ts +18 -0
- package/templates/monorepo-starter/server/src/lib/decorators/logger.decorator.ts +1 -1
- package/templates/monorepo-starter/server/src/lib/decorators/oauth.decorator.ts +7 -0
- package/templates/monorepo-starter/server/src/lib/decorators/user.decorator.ts +10 -0
- package/templates/monorepo-starter/server/src/lib/filters/exceptions.filter.ts +169 -24
- package/templates/monorepo-starter/server/src/lib/guards/auth.guard.ts +29 -65
- package/templates/monorepo-starter/server/src/lib/guards/oauth.guard.ts +28 -0
- package/templates/monorepo-starter/server/src/lib/interceptors/response.interceptor.ts +42 -5
- package/templates/monorepo-starter/server/src/lib/middleware/cache.middleware.ts +24 -0
- package/templates/monorepo-starter/server/src/lib/schemas/env.schema.ts +25 -5
- package/templates/monorepo-starter/server/src/lib/utils/client.utils.ts +95 -0
- package/templates/monorepo-starter/server/src/lib/utils/cookie.util.ts +4 -3
- package/templates/monorepo-starter/server/src/main.ts +20 -10
- package/templates/monorepo-starter/server/src/modules/admin/admin.controller.ts +54 -0
- package/templates/monorepo-starter/server/src/modules/admin/admin.module.ts +13 -0
- package/templates/monorepo-starter/server/src/modules/admin/admin.service.ts +134 -0
- package/templates/monorepo-starter/server/src/modules/auth/auth.controller.ts +60 -18
- package/templates/monorepo-starter/server/src/modules/auth/auth.module.ts +3 -2
- package/templates/monorepo-starter/server/src/modules/auth/auth.service.ts +354 -307
- package/templates/monorepo-starter/server/src/modules/auth/oauth.controller.ts +50 -28
- package/templates/monorepo-starter/server/src/modules/auth/oauth.service.ts +59 -34
- package/templates/monorepo-starter/server/src/modules/auth/otp.service.ts +29 -36
- package/templates/monorepo-starter/server/src/modules/cache/cache.module.ts +28 -0
- package/templates/monorepo-starter/server/src/modules/cache/cache.service.ts +33 -0
- package/templates/monorepo-starter/server/src/modules/env/env.service.ts +4 -3
- package/templates/monorepo-starter/server/src/modules/logger/logger.module.ts +1 -0
- package/templates/monorepo-starter/server/src/modules/logger/logger.service.ts +1 -1
- package/templates/monorepo-starter/server/src/modules/logger/winston.config.ts +15 -1
- package/templates/monorepo-starter/server/src/modules/media/cloudinary.provider.ts +14 -0
- package/templates/monorepo-starter/server/src/modules/media/cloudinary.service.ts +62 -0
- package/templates/monorepo-starter/server/src/modules/media/media.controller.ts +72 -0
- package/templates/monorepo-starter/server/src/modules/media/media.module.ts +13 -0
- package/templates/monorepo-starter/server/src/modules/media/media.service.ts +146 -0
- package/templates/monorepo-starter/server/src/modules/notification/email.service.ts +30 -0
- package/templates/monorepo-starter/server/src/modules/notification/messaging.service.ts +50 -0
- package/templates/monorepo-starter/server/src/modules/notification/notification.controller.ts +44 -0
- package/templates/monorepo-starter/server/src/modules/notification/notification.module.ts +7 -3
- package/templates/monorepo-starter/server/src/modules/notification/notification.service.ts +121 -78
- package/templates/monorepo-starter/server/src/modules/notification/push.service.ts +92 -0
- package/templates/monorepo-starter/server/src/modules/prisma/prisma.extension.ts +84 -56
- package/templates/monorepo-starter/server/src/modules/prisma/prisma.service.ts +10 -9
- package/templates/monorepo-starter/server/src/modules/prisma/soft-delete.models.ts +7 -0
- package/templates/monorepo-starter/server/src/modules/public/public.controller.ts +3 -2
- package/templates/monorepo-starter/server/src/modules/public/public.module.ts +5 -4
- package/templates/monorepo-starter/server/src/modules/public/public.service.ts +7 -4
- package/templates/monorepo-starter/server/src/modules/scheduler/cleanup.service.ts +15 -7
- package/templates/monorepo-starter/server/src/modules/scheduler/scheduler.module.ts +2 -0
- package/templates/monorepo-starter/server/src/modules/token/token.module.ts +3 -4
- package/templates/monorepo-starter/server/src/modules/token/token.service.ts +205 -76
- package/templates/monorepo-starter/server/src/modules/user/user.controller.ts +21 -0
- package/templates/monorepo-starter/server/src/modules/user/user.module.ts +12 -0
- package/templates/monorepo-starter/server/src/modules/user/user.service.ts +38 -0
- package/templates/monorepo-starter/server/src/types/express.d.ts +6 -2
- package/templates/monorepo-starter/server/src/types/index.ts +5 -0
- package/templates/monorepo-starter/server/tsconfig.json +17 -12
- package/templates/monorepo-starter/server/tsup.config.ts +7 -2
- package/templates/monorepo-starter/tsconfig.json +1 -1
- package/templates/monorepo-starter/turbo.json +1 -1
- package/templates/monorepo-starter/apps/web/eslint.config.mjs +0 -4
- package/templates/monorepo-starter/apps/web/src/app/(auth)/layout.tsx +0 -7
- package/templates/monorepo-starter/apps/web/src/app/globals.css +0 -1
- package/templates/monorepo-starter/apps/web/src/components/ThemeSwitch.tsx +0 -34
- package/templates/monorepo-starter/apps/web/src/providers/index.tsx +0 -10
- package/templates/monorepo-starter/apps/web/src/types/index.d.ts +0 -16
- package/templates/monorepo-starter/packages/config/eslint/base.js +0 -31
- package/templates/monorepo-starter/packages/config/eslint/nest.js +0 -26
- package/templates/monorepo-starter/packages/config/eslint/next.js +0 -39
- package/templates/monorepo-starter/packages/config/eslint/react.js +0 -30
- package/templates/monorepo-starter/packages/config/typescript/base.json +0 -31
- package/templates/monorepo-starter/packages/config/typescript/nest.json +0 -14
- package/templates/monorepo-starter/packages/config/typescript/next.json +0 -10
- package/templates/monorepo-starter/packages/ui/tsconfig.lint.json +0 -8
- package/templates/monorepo-starter/server/README.md +0 -63
- package/templates/monorepo-starter/server/scripts/generate.sh +0 -14
- package/templates/monorepo-starter/server/src/lib/dto/auth.dto.ts +0 -64
- package/templates/monorepo-starter/server/src/lib/dto/security-setting.dto.ts +0 -21
- package/templates/monorepo-starter/server/src/lib/pipes/validation.pipe.ts +0 -7
- package/templates/monorepo-starter/server/src/lib/templates/notification.templates.ts +0 -243
- package/templates/monorepo-starter/server/src/lib/utils/general.util.ts +0 -24
- package/templates/monorepo-starter/server/src/modules/auth/role.service.ts +0 -99
- package/templates/monorepo-starter/server/src/modules/auth/security-setting.service.ts +0 -102
- package/templates/monorepo-starter/server/src/modules/template/template.module.ts +0 -8
- package/templates/monorepo-starter/server/src/modules/template/template.service.ts +0 -33
- package/templates/monorepo-starter/server/src/types/index.d.ts +0 -13
- package/templates/monorepo-starter/server/test/app.e2e-spec.ts +0 -25
- package/templates/monorepo-starter/server/test/jest-e2e.json +0 -9
- /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,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,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
|
-
}
|