@imksh/create 1.0.24 → 1.0.26

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 (415) hide show
  1. package/package.json +1 -1
  2. package/src/commands/create.js +2 -1
  3. package/src/index.js +1 -1
  4. package/src/utils/askTemplate.js +1 -0
  5. package/templates/mern-react-native/client/src/vite-env.d.ts +1 -0
  6. package/templates/mern-react-native/mobile/_gitignore +43 -0
  7. package/templates/mern-react-native/mobile/babel.config.js +1 -0
  8. package/templates/mern-react-native/mobile/drizzle.config.ts +8 -0
  9. package/templates/mern-react-native/mobile/expo-env.d.ts +3 -0
  10. package/templates/mern-react-native/mobile/package.json +8 -1
  11. package/templates/mern-react-native/mobile/src/app/(auth)/_layout.tsx +12 -0
  12. package/templates/mern-react-native/mobile/src/app/(auth)/change-password.tsx +112 -0
  13. package/templates/mern-react-native/mobile/src/app/(auth)/edit-profile.tsx +156 -0
  14. package/templates/mern-react-native/mobile/src/app/(auth)/forgot-password.tsx +191 -0
  15. package/templates/mern-react-native/mobile/src/app/{login.tsx → (auth)/login.tsx} +69 -21
  16. package/templates/mern-react-native/mobile/src/app/(tabs)/dashboard.tsx +2 -2
  17. package/templates/mern-react-native/mobile/src/app/(tabs)/index.tsx +18 -17
  18. package/templates/mern-react-native/mobile/src/app/(tabs)/profile.tsx +23 -60
  19. package/templates/mern-react-native/mobile/src/app/(tabs)/search.tsx +2 -2
  20. package/templates/mern-react-native/mobile/src/app/_layout.tsx +22 -4
  21. package/templates/mern-react-native/mobile/src/components/common/AnimatedHeader.tsx +328 -0
  22. package/templates/mern-react-native/mobile/src/components/common/LocationLoader.tsx +591 -0
  23. package/templates/mern-react-native/mobile/src/components/common/ScreenHeader.tsx +41 -17
  24. package/templates/mern-react-native/mobile/src/components/common/TabHeader.tsx +58 -0
  25. package/templates/mern-react-native/mobile/src/components/common/Typography.tsx +49 -30
  26. package/templates/mern-react-native/mobile/src/components/common/Welcome.tsx +2 -2
  27. package/templates/mern-react-native/mobile/src/components/ui/BottomModal.tsx +31 -20
  28. package/templates/mern-react-native/mobile/src/components/ui/ClassicTabBar.tsx +4 -3
  29. package/templates/mern-react-native/mobile/src/components/ui/CustomTabBar.tsx +108 -71
  30. package/templates/mern-react-native/mobile/src/components/ui/Sidebar.tsx +81 -56
  31. package/templates/mern-react-native/mobile/src/components/ui/buttons/Button.tsx +106 -37
  32. package/templates/mern-react-native/mobile/src/components/ui/buttons/IconButton.tsx +4 -2
  33. package/templates/mern-react-native/mobile/src/components/ui/data-display/Accordion.tsx +3 -2
  34. package/templates/mern-react-native/mobile/src/components/ui/data-display/Avatar.tsx +4 -3
  35. package/templates/mern-react-native/mobile/src/components/ui/data-display/Badge.tsx +45 -17
  36. package/templates/mern-react-native/mobile/src/components/ui/data-display/ImageViewer.tsx +19 -9
  37. package/templates/mern-react-native/mobile/src/components/ui/feedback/CircularProgress.tsx +5 -4
  38. package/templates/mern-react-native/mobile/src/components/ui/feedback/ProgressBar.tsx +4 -3
  39. package/templates/mern-react-native/mobile/src/components/ui/feedback/Skeleton.tsx +3 -0
  40. package/templates/mern-react-native/mobile/src/components/ui/feedback/Spinner.tsx +11 -3
  41. package/templates/mern-react-native/mobile/src/components/ui/inputs/Checkbox.tsx +3 -2
  42. package/templates/mern-react-native/mobile/src/components/ui/inputs/DatePicker.tsx +186 -0
  43. package/templates/mern-react-native/mobile/src/components/ui/inputs/ImagePickerModal.tsx +129 -0
  44. package/templates/mern-react-native/mobile/src/components/ui/inputs/Input.tsx +54 -14
  45. package/templates/mern-react-native/mobile/src/components/ui/inputs/LocationPicker.tsx +211 -0
  46. package/templates/mern-react-native/mobile/src/components/ui/inputs/OTPInput.tsx +32 -9
  47. package/templates/mern-react-native/mobile/src/components/ui/inputs/PasswordInput.tsx +2 -1
  48. package/templates/mern-react-native/mobile/src/components/ui/inputs/Radio.tsx +3 -2
  49. package/templates/mern-react-native/mobile/src/components/ui/inputs/SearchBar.tsx +41 -4
  50. package/templates/mern-react-native/mobile/src/components/ui/inputs/Slider.tsx +4 -3
  51. package/templates/mern-react-native/mobile/src/components/ui/inputs/Switch.tsx +3 -2
  52. package/templates/mern-react-native/mobile/src/components/ui/inputs/TextArea.tsx +2 -1
  53. package/templates/mern-react-native/mobile/src/components/ui/inputs/WebLocationPicker.tsx +321 -0
  54. package/templates/mern-react-native/mobile/src/components/ui/layout/Grid.tsx +52 -10
  55. package/templates/mern-react-native/mobile/src/components/ui/layout/Section.tsx +7 -8
  56. package/templates/mern-react-native/mobile/src/components/ui/navigation/Pagination.tsx +4 -3
  57. package/templates/mern-react-native/mobile/src/components/ui/navigation/ProgressStepper.tsx +6 -5
  58. package/templates/mern-react-native/mobile/src/components/ui/navigation/Tabs.tsx +30 -4
  59. package/templates/mern-react-native/mobile/src/config/api.ts +12 -1
  60. package/templates/mern-react-native/mobile/src/config/sidebar.config.ts +12 -0
  61. package/templates/mern-react-native/mobile/src/config/tabNavigation.ts +1 -1
  62. package/templates/mern-react-native/mobile/src/db/index.ts +9 -0
  63. package/templates/mern-react-native/mobile/src/db/schema.ts +14 -0
  64. package/templates/mern-react-native/mobile/src/hooks/useDebounce.ts +17 -0
  65. package/templates/mern-react-native/mobile/src/services/notification.service.ts +22 -0
  66. package/templates/mern-react-native/mobile/src/services/socket.service.ts +36 -0
  67. package/templates/mern-react-native/mobile/src/store/useAuthStore.ts +122 -27
  68. package/templates/mern-react-native/mobile/src/store/useNotificationStore.ts +178 -0
  69. package/templates/mern-react-native/mobile/src/types/auth.type.ts +14 -0
  70. package/templates/mern-react-native/mobile/tsconfig.json +1 -0
  71. package/templates/mern-ts/client/src/vite-env.d.ts +1 -0
  72. package/templates/next/next.config.mjs +1 -0
  73. package/templates/next/package.json +10 -9
  74. package/templates/next/postcss.config.js +5 -0
  75. package/templates/next/src/app/layout.js +1 -0
  76. package/templates/next/src/app/page.js +1 -1
  77. package/templates/next/src/components/layout/ProtectedRoute.jsx +3 -3
  78. package/templates/next/src/index.css +1 -0
  79. package/templates/next/src/store/useUiStore.js +13 -7
  80. package/templates/next-ts/.env.example +0 -0
  81. package/templates/next-ts/AGENTS.md +37 -0
  82. package/templates/next-ts/CLAUDE.md +1 -0
  83. package/templates/next-ts/_gitignore +0 -24
  84. package/templates/next-ts/next-env.d.ts +3 -1
  85. package/templates/next-ts/next.config.mjs +1 -0
  86. package/templates/next-ts/package.json +13 -12
  87. package/templates/next-ts/postcss.config.js +5 -0
  88. package/templates/next-ts/public/logo.png +0 -0
  89. package/templates/next-ts/src/app/error.tsx +41 -0
  90. package/templates/next-ts/src/app/layout.tsx +2 -1
  91. package/templates/next-ts/src/app/not-found.tsx +5 -0
  92. package/templates/next-ts/src/app/page.tsx +1 -1
  93. package/templates/next-ts/src/components/layout/ProtectedRoute.tsx +3 -3
  94. package/templates/next-ts/src/components/ui/Button.tsx +63 -0
  95. package/templates/next-ts/src/components/ui/Input.tsx +79 -0
  96. package/templates/next-ts/src/index.css +1 -0
  97. package/templates/next-ts/src/store/useUiStore.ts +13 -7
  98. package/templates/next-ts/tsconfig.json +19 -5
  99. package/templates/production-fullstack/client/index.html +14 -0
  100. package/templates/production-fullstack/client/package.json +47 -0
  101. package/templates/production-fullstack/client/public/_redirects +1 -0
  102. package/templates/production-fullstack/client/public/favicon.ico +0 -0
  103. package/templates/production-fullstack/client/public/favicon.svg +1 -0
  104. package/templates/production-fullstack/client/public/logo.png +0 -0
  105. package/templates/production-fullstack/client/public/manifest.json +24 -0
  106. package/templates/production-fullstack/client/public/sw.js +56 -0
  107. package/templates/production-fullstack/client/src/App.tsx +68 -0
  108. package/templates/production-fullstack/client/src/assets/animations/loading.json +1 -0
  109. package/templates/production-fullstack/client/src/assets/data/navigation.ts +29 -0
  110. package/templates/production-fullstack/client/src/assets/images/logo.png +0 -0
  111. package/templates/production-fullstack/client/src/components/layout/ProtectedRoute.tsx +23 -0
  112. package/templates/production-fullstack/client/src/components/layout/PublicLayout.tsx +13 -0
  113. package/templates/production-fullstack/client/src/components/layout/SidebarLayout.tsx +37 -0
  114. package/templates/production-fullstack/client/src/components/shared/Breadcrumbs.tsx +27 -0
  115. package/templates/production-fullstack/client/src/components/shared/LottieIcon.tsx +36 -0
  116. package/templates/production-fullstack/client/src/components/shared/NotFound.tsx +78 -0
  117. package/templates/production-fullstack/client/src/components/shared/PwaInstallPrompt.tsx +72 -0
  118. package/templates/production-fullstack/client/src/components/shared/SEO.tsx +67 -0
  119. package/templates/production-fullstack/client/src/components/shared/Scroll.tsx +25 -0
  120. package/templates/production-fullstack/client/src/components/shared/Unauthorized.tsx +76 -0
  121. package/templates/production-fullstack/client/src/components/shared/skeletons/common/CardSkeleton.tsx +23 -0
  122. package/templates/production-fullstack/client/src/components/shared/skeletons/common/DashboardSkeleton.tsx +19 -0
  123. package/templates/production-fullstack/client/src/components/shared/skeletons/common/ListSkeleton.tsx +24 -0
  124. package/templates/production-fullstack/client/src/components/shared/skeletons/common/PageSkeleton.tsx +26 -0
  125. package/templates/production-fullstack/client/src/components/shared/skeletons/common/ProfileSkeleton.tsx +23 -0
  126. package/templates/production-fullstack/client/src/components/shared/skeletons/common/Skeleton.tsx +18 -0
  127. package/templates/production-fullstack/client/src/components/shared/skeletons/common/TableSkeleton.tsx +33 -0
  128. package/templates/production-fullstack/client/src/components/ui/ConfirmModal.tsx +152 -0
  129. package/templates/production-fullstack/client/src/components/ui/Header.tsx +230 -0
  130. package/templates/production-fullstack/client/src/components/ui/Loading.tsx +19 -0
  131. package/templates/production-fullstack/client/src/components/ui/Modal.tsx +106 -0
  132. package/templates/production-fullstack/client/src/components/ui/SidebarHeader.tsx +34 -0
  133. package/templates/production-fullstack/client/src/components/ui/Table.tsx +118 -0
  134. package/templates/production-fullstack/client/src/components/ui/ToggleSwitch.tsx +38 -0
  135. package/templates/production-fullstack/client/src/components/ui/sidebar.tsx +152 -0
  136. package/templates/production-fullstack/client/src/config/index.ts +44 -0
  137. package/templates/production-fullstack/client/src/constants/navigation.ts +14 -0
  138. package/templates/production-fullstack/client/src/features/auth/api/authService.ts +19 -0
  139. package/templates/production-fullstack/client/src/features/auth/pages/Login.tsx +233 -0
  140. package/templates/production-fullstack/client/src/features/auth/store/useAuthStore.ts +143 -0
  141. package/templates/production-fullstack/client/src/features/core/pages/Home.tsx +150 -0
  142. package/templates/production-fullstack/client/src/features/core/pages/Profile.tsx +9 -0
  143. package/templates/production-fullstack/client/src/hooks/useLenis.ts +28 -0
  144. package/templates/production-fullstack/client/src/hooks/usePwaInstall.ts +45 -0
  145. package/templates/production-fullstack/client/src/hooks/useWindowSize.ts +25 -0
  146. package/templates/production-fullstack/client/src/index.css +158 -0
  147. package/templates/production-fullstack/client/src/lib/axios.ts +22 -0
  148. package/templates/production-fullstack/client/src/lib/dayjs.ts +12 -0
  149. package/templates/production-fullstack/client/src/lib/query-client.ts +11 -0
  150. package/templates/production-fullstack/client/src/lib/socket.ts +6 -0
  151. package/templates/production-fullstack/client/src/main.tsx +28 -0
  152. package/templates/production-fullstack/client/src/store/useUiStore.ts +74 -0
  153. package/templates/production-fullstack/client/src/utils/formatDate.ts +19 -0
  154. package/templates/production-fullstack/client/src/utils/getInitials.ts +10 -0
  155. package/templates/production-fullstack/client/src/vite-env.d.ts +1 -0
  156. package/templates/production-fullstack/client/tsconfig.json +25 -0
  157. package/templates/production-fullstack/client/tsconfig.node.json +10 -0
  158. package/templates/production-fullstack/client/vite.config.ts +8 -0
  159. package/templates/production-fullstack/mobile/LICENSE +21 -0
  160. package/templates/production-fullstack/mobile/app.json +84 -0
  161. package/templates/production-fullstack/mobile/assets/animations/celebrate.json +1 -0
  162. package/templates/production-fullstack/mobile/assets/animations/infinity.json +1 -0
  163. package/templates/production-fullstack/mobile/assets/animations/loading.json +1 -0
  164. package/templates/production-fullstack/mobile/assets/fonts/Inter_Bold.ttf +0 -0
  165. package/templates/production-fullstack/mobile/assets/fonts/Inter_ExtraBold.ttf +0 -0
  166. package/templates/production-fullstack/mobile/assets/fonts/Inter_Medium.ttf +0 -0
  167. package/templates/production-fullstack/mobile/assets/fonts/Inter_Regular.ttf +0 -0
  168. package/templates/production-fullstack/mobile/assets/fonts/Inter_SemiBold.ttf +0 -0
  169. package/templates/production-fullstack/mobile/assets/images/logo/logo.png +0 -0
  170. package/templates/production-fullstack/mobile/assets/images/logo/logo.svg +1 -0
  171. package/templates/production-fullstack/mobile/assets/images/logo/logoWithBg.png +0 -0
  172. package/templates/production-fullstack/mobile/babel.config.js +13 -0
  173. package/templates/production-fullstack/mobile/drizzle.config.ts +8 -0
  174. package/templates/production-fullstack/mobile/eas.json +24 -0
  175. package/templates/production-fullstack/mobile/eslint.config.js +10 -0
  176. package/templates/production-fullstack/mobile/expo-env.d.ts +3 -0
  177. package/templates/production-fullstack/mobile/metro.config.js +6 -0
  178. package/templates/production-fullstack/mobile/nativewind-env.d.ts +3 -0
  179. package/templates/production-fullstack/mobile/package.json +89 -0
  180. package/templates/production-fullstack/mobile/src/app/(auth)/_layout.tsx +12 -0
  181. package/templates/production-fullstack/mobile/src/app/(auth)/change-password.tsx +112 -0
  182. package/templates/production-fullstack/mobile/src/app/(auth)/edit-profile.tsx +160 -0
  183. package/templates/production-fullstack/mobile/src/app/(auth)/forgot-password.tsx +191 -0
  184. package/templates/production-fullstack/mobile/src/app/(auth)/login.tsx +253 -0
  185. package/templates/production-fullstack/mobile/src/app/_layout.tsx +102 -0
  186. package/templates/production-fullstack/mobile/src/app/global.css +82 -0
  187. package/templates/production-fullstack/mobile/src/components/common/AnimatedHeader.tsx +328 -0
  188. package/templates/production-fullstack/mobile/src/components/common/ConfirmationToast.tsx +67 -0
  189. package/templates/production-fullstack/mobile/src/components/common/Loading.tsx +26 -0
  190. package/templates/production-fullstack/mobile/src/components/common/LocationLoader.tsx +591 -0
  191. package/templates/production-fullstack/mobile/src/components/common/ScreenHeader.tsx +68 -0
  192. package/templates/production-fullstack/mobile/src/components/common/TabHeader.tsx +58 -0
  193. package/templates/production-fullstack/mobile/src/components/common/Typography.tsx +113 -0
  194. package/templates/production-fullstack/mobile/src/components/common/Welcome.tsx +55 -0
  195. package/templates/production-fullstack/mobile/src/components/ui/BottomModal.tsx +159 -0
  196. package/templates/production-fullstack/mobile/src/components/ui/ClassicTabBar.tsx +129 -0
  197. package/templates/production-fullstack/mobile/src/components/ui/CustomTabBar.tsx +238 -0
  198. package/templates/production-fullstack/mobile/src/components/ui/Sidebar.tsx +258 -0
  199. package/templates/production-fullstack/mobile/src/components/ui/buttons/Button.tsx +180 -0
  200. package/templates/production-fullstack/mobile/src/components/ui/buttons/ButtonGroup.tsx +32 -0
  201. package/templates/production-fullstack/mobile/src/components/ui/buttons/FloatingActionButton.tsx +72 -0
  202. package/templates/production-fullstack/mobile/src/components/ui/buttons/IconButton.tsx +84 -0
  203. package/templates/production-fullstack/mobile/src/components/ui/data-display/Accordion.tsx +82 -0
  204. package/templates/production-fullstack/mobile/src/components/ui/data-display/Avatar.tsx +47 -0
  205. package/templates/production-fullstack/mobile/src/components/ui/data-display/Badge.tsx +104 -0
  206. package/templates/production-fullstack/mobile/src/components/ui/data-display/Card.tsx +36 -0
  207. package/templates/production-fullstack/mobile/src/components/ui/data-display/Image.tsx +43 -0
  208. package/templates/production-fullstack/mobile/src/components/ui/data-display/ImageViewer.tsx +33 -0
  209. package/templates/production-fullstack/mobile/src/components/ui/data-display/SwipeableRow.tsx +94 -0
  210. package/templates/production-fullstack/mobile/src/components/ui/feedback/CircularProgress.tsx +38 -0
  211. package/templates/production-fullstack/mobile/src/components/ui/feedback/GestureWrapper.tsx +114 -0
  212. package/templates/production-fullstack/mobile/src/components/ui/feedback/ProgressBar.tsx +51 -0
  213. package/templates/production-fullstack/mobile/src/components/ui/feedback/Skeleton.tsx +84 -0
  214. package/templates/production-fullstack/mobile/src/components/ui/feedback/Spinner.tsx +50 -0
  215. package/templates/production-fullstack/mobile/src/components/ui/inputs/Checkbox.tsx +54 -0
  216. package/templates/production-fullstack/mobile/src/components/ui/inputs/DatePicker.tsx +186 -0
  217. package/templates/production-fullstack/mobile/src/components/ui/inputs/ImagePickerModal.tsx +129 -0
  218. package/templates/production-fullstack/mobile/src/components/ui/inputs/Input.tsx +158 -0
  219. package/templates/production-fullstack/mobile/src/components/ui/inputs/LocationPicker.tsx +211 -0
  220. package/templates/production-fullstack/mobile/src/components/ui/inputs/OTPInput.tsx +83 -0
  221. package/templates/production-fullstack/mobile/src/components/ui/inputs/PasswordInput.tsx +16 -0
  222. package/templates/production-fullstack/mobile/src/components/ui/inputs/Radio.tsx +54 -0
  223. package/templates/production-fullstack/mobile/src/components/ui/inputs/SearchBar.tsx +53 -0
  224. package/templates/production-fullstack/mobile/src/components/ui/inputs/Slider.tsx +49 -0
  225. package/templates/production-fullstack/mobile/src/components/ui/inputs/Switch.tsx +75 -0
  226. package/templates/production-fullstack/mobile/src/components/ui/inputs/TextArea.tsx +15 -0
  227. package/templates/production-fullstack/mobile/src/components/ui/inputs/WebLocationPicker.tsx +321 -0
  228. package/templates/production-fullstack/mobile/src/components/ui/layout/Container.tsx +23 -0
  229. package/templates/production-fullstack/mobile/src/components/ui/layout/Divider.tsx +20 -0
  230. package/templates/production-fullstack/mobile/src/components/ui/layout/Grid.tsx +62 -0
  231. package/templates/production-fullstack/mobile/src/components/ui/layout/KeyboardAvoidingViewWrapper.tsx +16 -0
  232. package/templates/production-fullstack/mobile/src/components/ui/layout/ScrollContainer.tsx +21 -0
  233. package/templates/production-fullstack/mobile/src/components/ui/layout/Section.tsx +51 -0
  234. package/templates/production-fullstack/mobile/src/components/ui/layout/Spacer.tsx +6 -0
  235. package/templates/production-fullstack/mobile/src/components/ui/layout/Stack.tsx +34 -0
  236. package/templates/production-fullstack/mobile/src/components/ui/navigation/Pagination.tsx +61 -0
  237. package/templates/production-fullstack/mobile/src/components/ui/navigation/ProgressStepper.tsx +66 -0
  238. package/templates/production-fullstack/mobile/src/components/ui/navigation/Tabs.tsx +173 -0
  239. package/templates/production-fullstack/mobile/src/config/sidebar.config.ts +72 -0
  240. package/templates/production-fullstack/mobile/src/config/tabNavigation.ts +64 -0
  241. package/templates/production-fullstack/mobile/src/constants/Colors.ts +71 -0
  242. package/templates/production-fullstack/mobile/src/db/index.ts +9 -0
  243. package/templates/production-fullstack/mobile/src/db/schema.ts +14 -0
  244. package/templates/production-fullstack/mobile/src/features/auth/api/auth.service.ts +35 -0
  245. package/templates/production-fullstack/mobile/src/features/auth/store/useAuthStore.ts +273 -0
  246. package/templates/production-fullstack/mobile/src/features/auth/types/auth.type.ts +14 -0
  247. package/templates/production-fullstack/mobile/src/hooks/useDebounce.ts +17 -0
  248. package/templates/production-fullstack/mobile/src/lib/axios.ts +27 -0
  249. package/templates/production-fullstack/mobile/src/lib/query-client.ts +11 -0
  250. package/templates/production-fullstack/mobile/src/lib/socket.ts +36 -0
  251. package/templates/production-fullstack/mobile/src/lib/storage.ts +55 -0
  252. package/templates/production-fullstack/mobile/src/services/permission.service.ts +214 -0
  253. package/templates/production-fullstack/mobile/src/store/localStore.ts +7 -0
  254. package/templates/production-fullstack/mobile/src/store/useNotificationStore.ts +53 -0
  255. package/templates/production-fullstack/mobile/src/types/common.type.ts +6 -0
  256. package/templates/production-fullstack/mobile/src/types/images.d.ts +24 -0
  257. package/templates/production-fullstack/mobile/src/utils/toast.ts +26 -0
  258. package/templates/production-fullstack/mobile/tailwind.config.js +71 -0
  259. package/templates/production-fullstack/mobile/tsconfig.json +23 -0
  260. package/templates/production-fullstack/server/.env.example +63 -0
  261. package/templates/production-fullstack/server/README.md +75 -0
  262. package/templates/production-fullstack/server/eslint.config.js +13 -0
  263. package/templates/production-fullstack/server/package.json +58 -0
  264. package/templates/production-fullstack/server/prisma/schema/core/attachment.prisma +14 -0
  265. package/templates/production-fullstack/server/prisma/schema/core/notification.prisma +18 -0
  266. package/templates/production-fullstack/server/prisma/schema/core/permission.prisma +26 -0
  267. package/templates/production-fullstack/server/prisma/schema/core/role.prisma +25 -0
  268. package/templates/production-fullstack/server/prisma/schema/core/user.prisma +56 -0
  269. package/templates/production-fullstack/server/prisma/schema/enums/common.prisma +13 -0
  270. package/templates/production-fullstack/server/prisma/schema/enums/notification.prisma +6 -0
  271. package/templates/production-fullstack/server/prisma/schema/enums/user.prisma +11 -0
  272. package/templates/production-fullstack/server/prisma/schema/schema.prisma +7 -0
  273. package/templates/production-fullstack/server/prisma.config.ts +14 -0
  274. package/templates/production-fullstack/server/src/app.ts +36 -0
  275. package/templates/production-fullstack/server/src/common/middlewares/auth.middleware.ts +45 -0
  276. package/templates/production-fullstack/server/src/common/middlewares/errorHandler.ts +16 -0
  277. package/templates/production-fullstack/server/src/common/middlewares/multer.ts +20 -0
  278. package/templates/production-fullstack/server/src/common/middlewares/rateLimiter.ts +53 -0
  279. package/templates/production-fullstack/server/src/common/services/email.service.ts +28 -0
  280. package/templates/production-fullstack/server/src/common/services/push.service.ts +65 -0
  281. package/templates/production-fullstack/server/src/common/services/storage.service.ts +9 -0
  282. package/templates/production-fullstack/server/src/common/types/express.d.ts +10 -0
  283. package/templates/production-fullstack/server/src/common/utils/cloudinaryUpload.ts +44 -0
  284. package/templates/production-fullstack/server/src/common/utils/emailOtp.ts +30 -0
  285. package/templates/production-fullstack/server/src/common/utils/genOtpToken.ts +22 -0
  286. package/templates/production-fullstack/server/src/common/utils/generateVapidKeys.ts +12 -0
  287. package/templates/production-fullstack/server/src/common/utils/jwt.ts +27 -0
  288. package/templates/production-fullstack/server/src/common/utils/pushHelper.ts +22 -0
  289. package/templates/production-fullstack/server/src/config/env.ts +2 -0
  290. package/templates/production-fullstack/server/src/config/logger.ts +58 -0
  291. package/templates/production-fullstack/server/src/config/prisma.ts +26 -0
  292. package/templates/production-fullstack/server/src/features/attachments/upload.controller.ts +22 -0
  293. package/templates/production-fullstack/server/src/features/attachments/upload.routes.ts +11 -0
  294. package/templates/production-fullstack/server/src/features/auth/auth.controller.ts +124 -0
  295. package/templates/production-fullstack/server/src/features/auth/auth.routes.ts +22 -0
  296. package/templates/production-fullstack/server/src/features/auth/auth.service.ts +155 -0
  297. package/templates/production-fullstack/server/src/features/notifications/push.controller.ts +55 -0
  298. package/templates/production-fullstack/server/src/features/notifications/push.routes.ts +11 -0
  299. package/templates/production-fullstack/server/src/index.ts +17 -0
  300. package/templates/production-fullstack/server/src/routes/index.ts +12 -0
  301. package/templates/production-fullstack/server/src/sockets/auth.ts +0 -0
  302. package/templates/production-fullstack/server/src/sockets/connection.ts +31 -0
  303. package/templates/production-fullstack/server/src/sockets/emitters/assignment.emitter.ts +0 -0
  304. package/templates/production-fullstack/server/src/sockets/emitters/attendance.emitter.ts +0 -0
  305. package/templates/production-fullstack/server/src/sockets/emitters/exam.emitter.ts +0 -0
  306. package/templates/production-fullstack/server/src/sockets/emitters/notification.emitter.ts +17 -0
  307. package/templates/production-fullstack/server/src/sockets/events.ts +27 -0
  308. package/templates/production-fullstack/server/src/sockets/handlers/attendance.handler.ts +0 -0
  309. package/templates/production-fullstack/server/src/sockets/handlers/chat.handler.ts +0 -0
  310. package/templates/production-fullstack/server/src/sockets/handlers/index.ts +15 -0
  311. package/templates/production-fullstack/server/src/sockets/handlers/lms.handler.ts +0 -0
  312. package/templates/production-fullstack/server/src/sockets/handlers/notification.handler.ts +39 -0
  313. package/templates/production-fullstack/server/src/sockets/index.ts +39 -0
  314. package/templates/production-fullstack/server/src/sockets/middleware.ts +54 -0
  315. package/templates/production-fullstack/server/src/sockets/rooms.ts +11 -0
  316. package/templates/production-fullstack/server/src/sockets/types.ts +32 -0
  317. package/templates/production-fullstack/server/tsconfig.json +14 -0
  318. package/templates/react-native/babel.config.js +1 -0
  319. package/templates/react-native/drizzle.config.ts +8 -0
  320. package/templates/react-native/package.json +8 -1
  321. package/templates/react-native/src/app/(auth)/_layout.tsx +12 -0
  322. package/templates/react-native/src/app/(auth)/change-password.tsx +112 -0
  323. package/templates/react-native/src/app/(auth)/edit-profile.tsx +156 -0
  324. package/templates/react-native/src/app/(auth)/forgot-password.tsx +191 -0
  325. package/templates/react-native/src/app/{login.tsx → (auth)/login.tsx} +69 -21
  326. package/templates/react-native/src/app/(tabs)/dashboard.tsx +2 -2
  327. package/templates/react-native/src/app/(tabs)/index.tsx +18 -17
  328. package/templates/react-native/src/app/(tabs)/profile.tsx +23 -60
  329. package/templates/react-native/src/app/(tabs)/search.tsx +2 -2
  330. package/templates/react-native/src/app/_layout.tsx +22 -4
  331. package/templates/react-native/src/components/common/AnimatedHeader.tsx +328 -0
  332. package/templates/react-native/src/components/common/LocationLoader.tsx +591 -0
  333. package/templates/react-native/src/components/common/ScreenHeader.tsx +41 -17
  334. package/templates/react-native/src/components/common/TabHeader.tsx +58 -0
  335. package/templates/react-native/src/components/common/Typography.tsx +49 -30
  336. package/templates/react-native/src/components/common/Welcome.tsx +2 -2
  337. package/templates/react-native/src/components/ui/BottomModal.tsx +31 -20
  338. package/templates/react-native/src/components/ui/ClassicTabBar.tsx +4 -3
  339. package/templates/react-native/src/components/ui/CustomTabBar.tsx +108 -71
  340. package/templates/react-native/src/components/ui/Sidebar.tsx +81 -56
  341. package/templates/react-native/src/components/ui/buttons/Button.tsx +106 -37
  342. package/templates/react-native/src/components/ui/buttons/IconButton.tsx +4 -2
  343. package/templates/react-native/src/components/ui/data-display/Accordion.tsx +3 -2
  344. package/templates/react-native/src/components/ui/data-display/Avatar.tsx +4 -3
  345. package/templates/react-native/src/components/ui/data-display/Badge.tsx +45 -17
  346. package/templates/react-native/src/components/ui/data-display/ImageViewer.tsx +19 -9
  347. package/templates/react-native/src/components/ui/feedback/CircularProgress.tsx +5 -4
  348. package/templates/react-native/src/components/ui/feedback/ProgressBar.tsx +4 -3
  349. package/templates/react-native/src/components/ui/feedback/Skeleton.tsx +3 -0
  350. package/templates/react-native/src/components/ui/feedback/Spinner.tsx +11 -3
  351. package/templates/react-native/src/components/ui/inputs/Checkbox.tsx +3 -2
  352. package/templates/react-native/src/components/ui/inputs/DatePicker.tsx +186 -0
  353. package/templates/react-native/src/components/ui/inputs/ImagePickerModal.tsx +129 -0
  354. package/templates/react-native/src/components/ui/inputs/Input.tsx +54 -14
  355. package/templates/react-native/src/components/ui/inputs/LocationPicker.tsx +211 -0
  356. package/templates/react-native/src/components/ui/inputs/OTPInput.tsx +32 -9
  357. package/templates/react-native/src/components/ui/inputs/PasswordInput.tsx +2 -1
  358. package/templates/react-native/src/components/ui/inputs/Radio.tsx +3 -2
  359. package/templates/react-native/src/components/ui/inputs/SearchBar.tsx +41 -4
  360. package/templates/react-native/src/components/ui/inputs/Slider.tsx +4 -3
  361. package/templates/react-native/src/components/ui/inputs/Switch.tsx +3 -2
  362. package/templates/react-native/src/components/ui/inputs/TextArea.tsx +2 -1
  363. package/templates/react-native/src/components/ui/inputs/WebLocationPicker.tsx +321 -0
  364. package/templates/react-native/src/components/ui/layout/Grid.tsx +52 -10
  365. package/templates/react-native/src/components/ui/layout/Section.tsx +7 -8
  366. package/templates/react-native/src/components/ui/navigation/Pagination.tsx +4 -3
  367. package/templates/react-native/src/components/ui/navigation/ProgressStepper.tsx +6 -5
  368. package/templates/react-native/src/components/ui/navigation/Tabs.tsx +30 -4
  369. package/templates/react-native/src/config/api.ts +12 -1
  370. package/templates/react-native/src/config/sidebar.config.ts +12 -0
  371. package/templates/react-native/src/config/tabNavigation.ts +1 -1
  372. package/templates/react-native/src/db/index.ts +9 -0
  373. package/templates/react-native/src/db/schema.ts +14 -0
  374. package/templates/react-native/src/hooks/useDebounce.ts +17 -0
  375. package/templates/react-native/src/services/notification.service.ts +22 -0
  376. package/templates/react-native/src/services/socket.service.ts +36 -0
  377. package/templates/react-native/src/store/useAuthStore.ts +122 -27
  378. package/templates/react-native/src/store/useNotificationStore.ts +178 -0
  379. package/templates/react-native/src/types/auth.type.ts +14 -0
  380. package/templates/react-native/tsconfig.json +1 -0
  381. package/templates/react-ts/src/vite-env.d.ts +1 -0
  382. package/templates/mern-react-native/mobile/.env.example +0 -2
  383. package/templates/mern-react-native/mobile/.vscode/extensions.json +0 -1
  384. package/templates/mern-react-native/mobile/.vscode/settings.json +0 -7
  385. package/templates/mern-react-native/mobile/README.md +0 -159
  386. package/templates/mern-react-native/mobile/docs/README.md +0 -17
  387. package/templates/mern-react-native/mobile/docs/components/buttons.md +0 -40
  388. package/templates/mern-react-native/mobile/docs/components/data-display.md +0 -44
  389. package/templates/mern-react-native/mobile/docs/components/feedback.md +0 -36
  390. package/templates/mern-react-native/mobile/docs/components/gestures.md +0 -60
  391. package/templates/mern-react-native/mobile/docs/components/inputs.md +0 -41
  392. package/templates/mern-react-native/mobile/docs/components/layout.md +0 -34
  393. package/templates/mern-react-native/mobile/docs/components/navigation.md +0 -31
  394. package/templates/mern-react-native/mobile/docs/features.md +0 -85
  395. package/templates/mern-react-native/mobile/docs/getting-started.md +0 -47
  396. package/templates/mern-react-native/mobile/src/components/common/HomeHeader.tsx +0 -43
  397. package/templates/mern-react-native/mobile/src/components/settings/SettingToggle.tsx +0 -26
  398. package/templates/mern-react-native/mobile/src/components/settings/SettingsOptions.tsx +0 -47
  399. package/templates/react-native/.env.example +0 -2
  400. package/templates/react-native/.vscode/extensions.json +0 -1
  401. package/templates/react-native/.vscode/settings.json +0 -7
  402. package/templates/react-native/README.md +0 -159
  403. package/templates/react-native/docs/README.md +0 -17
  404. package/templates/react-native/docs/components/buttons.md +0 -40
  405. package/templates/react-native/docs/components/data-display.md +0 -44
  406. package/templates/react-native/docs/components/feedback.md +0 -36
  407. package/templates/react-native/docs/components/gestures.md +0 -60
  408. package/templates/react-native/docs/components/inputs.md +0 -41
  409. package/templates/react-native/docs/components/layout.md +0 -34
  410. package/templates/react-native/docs/components/navigation.md +0 -31
  411. package/templates/react-native/docs/features.md +0 -85
  412. package/templates/react-native/docs/getting-started.md +0 -47
  413. package/templates/react-native/src/components/common/HomeHeader.tsx +0 -43
  414. package/templates/react-native/src/components/settings/SettingToggle.tsx +0 -26
  415. package/templates/react-native/src/components/settings/SettingsOptions.tsx +0 -47
@@ -0,0 +1,53 @@
1
+ import { create } from 'zustand';
2
+ import { getSocket } from '../lib/socket';
3
+ import * as Notifications from 'expo-notifications';
4
+
5
+ export interface NotificationState {
6
+ notifications: any[];
7
+ pushToken: string | null;
8
+ listenForSocketEvents: () => void;
9
+ registerForPushNotificationsAsync: () => Promise<void>;
10
+ fetchNotifications: () => Promise<void>;
11
+ }
12
+
13
+ export const useNotificationStore = create<NotificationState>((set, get) => ({
14
+ notifications: [],
15
+ pushToken: null,
16
+
17
+ listenForSocketEvents: () => {
18
+ const socket = getSocket();
19
+ if (!socket) return;
20
+
21
+ socket.on('new_notification', (data) => {
22
+ set((state) => ({ notifications: [data, ...state.notifications] }));
23
+ });
24
+ },
25
+
26
+ registerForPushNotificationsAsync: async () => {
27
+ try {
28
+ const { status: existingStatus } = await Notifications.getPermissionsAsync();
29
+ let finalStatus = existingStatus;
30
+ if (existingStatus !== 'granted') {
31
+ const { status } = await Notifications.requestPermissionsAsync();
32
+ finalStatus = status;
33
+ }
34
+ if (finalStatus !== 'granted') {
35
+ console.log('Failed to get push token for push notification!');
36
+ return;
37
+ }
38
+ // Note: projectId is required for Expo Go and EAS.
39
+ const token = (await Notifications.getExpoPushTokenAsync()).data;
40
+ set({ pushToken: token });
41
+
42
+ // Here you would typically send the pushToken to your backend
43
+ } catch (e) {
44
+ console.warn("Failed to register for push notifications", e);
45
+ }
46
+ },
47
+
48
+ fetchNotifications: async () => {
49
+ // API call to fetch notifications could go here
50
+ // e.g., const data = await api.get('/notifications');
51
+ set({ notifications: [] });
52
+ }
53
+ }));
@@ -0,0 +1,6 @@
1
+ export interface ApiResponse<T = any> {
2
+ data: T;
3
+ message?: string;
4
+ success?: boolean;
5
+ token?: string;
6
+ }
@@ -0,0 +1,24 @@
1
+ declare module "*.png" {
2
+ const value: any;
3
+ export default value;
4
+ }
5
+
6
+ declare module "*.jpg" {
7
+ const value: any;
8
+ export default value;
9
+ }
10
+
11
+ declare module "*.jpeg" {
12
+ const value: any;
13
+ export default value;
14
+ }
15
+
16
+ declare module "*.gif" {
17
+ const value: any;
18
+ export default value;
19
+ }
20
+
21
+ declare module "*.svg" {
22
+ const value: any;
23
+ export default value;
24
+ }
@@ -0,0 +1,26 @@
1
+ // utils/toast.ts
2
+
3
+ import Toast from "react-native-toast-message";
4
+
5
+ export const toast = {
6
+ success: (title: string, message?: string) =>
7
+ Toast.show({
8
+ type: "success",
9
+ text1: title,
10
+ text2: message,
11
+ }),
12
+
13
+ error: (title: string, message?: string) =>
14
+ Toast.show({
15
+ type: "error",
16
+ text1: title,
17
+ text2: message,
18
+ }),
19
+
20
+ info: (title: string, message?: string) =>
21
+ Toast.show({
22
+ type: "info",
23
+ text1: title,
24
+ text2: message,
25
+ }),
26
+ };
@@ -0,0 +1,71 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ module.exports = {
3
+ darkMode: "class",
4
+ content: ["./src/app/**/*.{js,jsx,ts,tsx}", "./src/components/**/*.{js,jsx,ts,tsx}"],
5
+ presets: [require("nativewind/preset")],
6
+ theme: {
7
+ extend: {
8
+ keyframes: {
9
+ bounce: {
10
+ "0%, 100%": {
11
+ transform: "translateY(-25%)",
12
+ animationTimingFunction: "cubic-bezier(0.8,0,1,1)",
13
+ },
14
+ "50%": {
15
+ transform: "translateY(0)",
16
+ animationTimingFunction: "cubic-bezier(0,0,0.2,1)",
17
+ },
18
+ },
19
+ floatUp: {
20
+ "0%": { transform: "translateY(50%)", opacity: "0" },
21
+ "50%": { transform: "translateY(-50%)", opacity: "1" },
22
+ "100%": { transform: "translateY(-100%)", opacity: "0" },
23
+ },
24
+ dice: {
25
+ "0%": { transform: "rotate(0deg)"},
26
+ "100%": { transform: "rotate(360deg)" },
27
+ },
28
+ flip: {
29
+ "0%": { transform: "rotatey(0deg)"},
30
+ "100%": { transform: "rotatey(360deg)" },
31
+ },
32
+ },
33
+ animation: {
34
+ bounce: "bounce 1s infinite",
35
+ "float-up": "floatUp 2s ease-in-out forwards",
36
+ "dice1": "dice 0.3s ease-in-out forwards infinite",
37
+ "dice2": "dice 0.3s ease-in-out forwards infinite",
38
+ "flip": "dice 0.8s ease-in-out forwards infinite",
39
+ },
40
+ colors: {
41
+ base: {
42
+ 100: "rgb(var(--color-base-100) / <alpha-value>)",
43
+ 200: "rgb(var(--color-base-200) / <alpha-value>)",
44
+ 300: "rgb(var(--color-base-300) / <alpha-value>)",
45
+ content: "rgb(var(--color-base-content) / <alpha-value>)",
46
+ },
47
+ primary: {
48
+ DEFAULT: "rgb(var(--color-primary) / <alpha-value>)",
49
+ content: "rgb(var(--color-primary-content) / <alpha-value>)",
50
+ },
51
+ secondary: {
52
+ DEFAULT: "rgb(var(--color-secondary) / <alpha-value>)",
53
+ content: "rgb(var(--color-secondary-content) / <alpha-value>)",
54
+ },
55
+ accent: {
56
+ DEFAULT: "rgb(var(--color-accent) / <alpha-value>)",
57
+ content: "rgb(var(--color-accent-content) / <alpha-value>)",
58
+ },
59
+ neutral: {
60
+ DEFAULT: "rgb(var(--color-neutral) / <alpha-value>)",
61
+ content: "rgb(var(--color-neutral-content) / <alpha-value>)",
62
+ },
63
+ info: "rgb(var(--color-info) / <alpha-value>)",
64
+ success: "rgb(var(--color-success) / <alpha-value>)",
65
+ warning: "rgb(var(--color-warning) / <alpha-value>)",
66
+ error: "rgb(var(--color-error) / <alpha-value>)",
67
+ },
68
+ },
69
+ },
70
+ plugins: [],
71
+ };
@@ -0,0 +1,23 @@
1
+ {
2
+ "extends": "expo/tsconfig.base",
3
+ "compilerOptions": {
4
+ "jsx": "react-jsx",
5
+ "strict": true,
6
+ "noImplicitAny": false,
7
+ "paths": {
8
+ "@/*": [
9
+ "./src/*"
10
+ ],
11
+ "@/assets/*": [
12
+ "./assets/*"
13
+ ]
14
+ }
15
+ },
16
+ "include": [
17
+ "**/*.ts",
18
+ "**/*.tsx",
19
+ ".expo/types/**/*.ts",
20
+ "expo-env.d.ts",
21
+ "nativewind-env.d.ts"
22
+ ]
23
+ }
@@ -0,0 +1,63 @@
1
+ # ==========================
2
+ # Application
3
+ # ==========================
4
+ NODE_ENV=development
5
+ PORT=5000
6
+
7
+ APP_NAME=My App
8
+ APP_URL=http://localhost:5173
9
+ APP_EMAIL=noreply@example.com
10
+ APP_PRIMARY_COLOR=#2563eb
11
+
12
+ # ==========================
13
+ # Database
14
+ # ==========================
15
+
16
+ DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
17
+
18
+ # ==========================
19
+ # JWT
20
+ # ==========================
21
+ JWT_SECRET=
22
+ JWT_EXPIRES_IN=7d
23
+
24
+ # ==========================
25
+ # Cloudinary
26
+ # ==========================
27
+ CLOUDINARY_CLOUD_NAME=
28
+ CLOUDINARY_API_KEY=
29
+ CLOUDINARY_API_SECRET=
30
+
31
+ # ==========================
32
+ # Email (SMTP)
33
+ # ==========================
34
+ SMTP_HOST=smtp.gmail.com
35
+ SMTP_PORT=587
36
+ SMTP_SECURE=false
37
+ SMTP_USER=
38
+ SMTP_PASS=
39
+ SMTP_FROM="My App <noreply@example.com>"
40
+
41
+ # ==========================
42
+ # CORS
43
+ # ==========================
44
+ CLIENT_URL=http://localhost:5173
45
+
46
+ # ==========================
47
+ # Cookie
48
+ # ==========================
49
+ COOKIE_NAME=token
50
+ COOKIE_EXPIRES_IN=7d
51
+
52
+ # ==========================
53
+ # Rate Limiting
54
+ # ==========================
55
+ RATE_LIMIT_WINDOW=15
56
+ RATE_LIMIT_MAX=100
57
+
58
+ # ==========================
59
+ # Rate Limiting
60
+ # ==========================
61
+ VAPID_PRIVATE_KEY=
62
+ VAPID_PUBLIC_KEY=
63
+ VAPID_SUBJECT=mailto:noreply@example.com
@@ -0,0 +1,75 @@
1
+ # Node.js TypeScript Prisma Backend Boilerplate
2
+
3
+ A production-ready, strongly-typed Node.js & Express boilerplate project with best-practice architectures, modular routing, Prisma ORM, and TSX engine compilation.
4
+
5
+ ## Features
6
+
7
+ - ⚙️ **Modular Architecture:** Express application setup decoupled into `app.ts` (middleware + router wiring) and `index.ts` (server initialization & db connection).
8
+ - 🗄️ **Prisma ORM:** Built-in PostgreSQL datasource configuration and schema mapping for `User`, `Otp`, and `PushSubscription` models.
9
+ - 📝 **Colorized Logging:** Zero-dependency custom logger with timestamped success, warning, info, and error layouts.
10
+ - 🛡️ **Security Out-of-the-Box:** Pre-configured with Helmet headers, CORS policies, and global rate limiters (`apiLimiter`, `authLimiter`, `uploadLimiter`).
11
+ - 🔑 **Authentication & JWT:** Custom middlewares for route protection, sign-ups, and log-ins with HTTP-only cookie-based tokens.
12
+ - 📧 **SMTP Mailer & OTP:** Standard mailer transport using Gmail NodeMailer wrapper, integrated with an OTP generator and email template.
13
+ - 🖼️ **File Uploads:** Cloudinary integration utilizing Multer memory buffers for secure, single or multi-file uploads.
14
+ - 🔌 **Socket.io Setup:** Pre-installed Socket.io hooks mapping connected user sessions to active sockets.
15
+ - ✉️ **Web Push:** Push notifications integration powered by VAPID key generators and web-push subscriptions.
16
+ - 📦 **TSX Engine:** Fast TS runner with native ESM specifier resolution support.
17
+
18
+ ## Getting Started
19
+
20
+ ### 1. Configure Environment Variables
21
+
22
+ Create a `.env` file in the root directory (based on `.env.example`):
23
+
24
+ ```env
25
+ PORT=5002
26
+ JWT_SECRET=your_super_secret_jwt_key
27
+ DATABASE_URL=postgresql://user:password@localhost:5432/db_name
28
+
29
+ # Cloudinary
30
+ CLOUDINARY_CLOUD_NAME=your_cloud_name
31
+ CLOUDINARY_API_KEY=your_api_key
32
+ CLOUDINARY_API_SECRET=your_api_secret
33
+
34
+ # SMTP Settings
35
+ SMTP_USER=your_email@gmail.com
36
+ SMTP_PASS=your_app_password
37
+
38
+ # Web Push
39
+ VAPID_SUBJECT=mailto:your_email@example.com
40
+ VAPID_PUBLIC_KEY=your_vapid_public_key
41
+ VAPID_PRIVATE_KEY=your_vapid_private_key
42
+ ```
43
+
44
+ ### 2. Install & Sync Schema
45
+
46
+ ```bash
47
+ # Install dependencies
48
+ npm install
49
+
50
+ # Push database schema changes locally
51
+ npm run db:push
52
+
53
+ # Generate Prisma Client types
54
+ npm run db:generate
55
+
56
+ # Start development server with reload (via tsx)
57
+ npm run dev
58
+
59
+ # Build the project to JS
60
+ npm run build
61
+ ```
62
+
63
+ ## API Endpoints
64
+
65
+ ### Auth Routes (`/api/auth`)
66
+
67
+ - `POST /signup` - Registers a new user session
68
+ - `POST /login` - Log in user and write token cookie
69
+ - `POST /logout` - Clear token session cookies
70
+ - `GET /me` - Returns logged-in user profile (requires auth)
71
+ - `PUT /me` - Edit profile info and upload avatars (requires auth)
72
+
73
+ ### Upload Routes (`/api/upload`)
74
+
75
+ - `POST /` - Securely uploads image/file to Cloudinary (requires auth)
@@ -0,0 +1,13 @@
1
+ import eslint from '@eslint/js';
2
+ import tseslint from 'typescript-eslint';
3
+
4
+ export default tseslint.config(
5
+ eslint.configs.recommended,
6
+ ...tseslint.configs.recommended,
7
+ {
8
+ rules: {
9
+ 'no-console': 'error',
10
+ '@typescript-eslint/no-explicit-any': 'error',
11
+ },
12
+ }
13
+ );
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "server",
3
+ "version": "1.0.0",
4
+ "main": "src/index.ts",
5
+ "type": "module",
6
+ "scripts": {
7
+ "start": "tsx src/index.ts",
8
+ "dev": "tsx watch src/index.ts",
9
+ "build": "tsc",
10
+ "db:push": "prisma db push",
11
+ "db:generate": "prisma generate",
12
+ "generate:vapid": "node ./src/utils/generateVapidKeys.js",
13
+ "lint": "eslint src/**/*.ts"
14
+ },
15
+ "dependencies": {
16
+ "@prisma/adapter-pg": "^7.9.1",
17
+ "@prisma/client": "^7.9.1",
18
+ "@prisma/config": "^7.9.1",
19
+ "bcrypt": "^5.1.1",
20
+ "cloudinary": "^2.0.0",
21
+ "compression": "^1.7.4",
22
+ "cookie-parser": "^1.4.6",
23
+ "cors": "^2.8.5",
24
+ "dotenv": "^16.3.1",
25
+ "expo-server-sdk": "^3.11.0",
26
+ "express": "^4.18.2",
27
+ "express-rate-limit": "^7.1.4",
28
+ "helmet": "^7.1.0",
29
+ "jsonwebtoken": "^9.0.2",
30
+ "morgan": "^1.10.0",
31
+ "multer": "^1.4.5-lts.1",
32
+ "nodemailer": "^6.9.7",
33
+ "pg": "^8.22.0",
34
+ "socket.io": "^4.7.2",
35
+ "web-push": "^3.6.6"
36
+ },
37
+ "devDependencies": {
38
+ "@eslint/js": "^10.0.1",
39
+ "@types/bcrypt": "^5.0.2",
40
+ "@types/compression": "^1.7.5",
41
+ "@types/cookie-parser": "^1.4.6",
42
+ "@types/cors": "^2.8.17",
43
+ "@types/express": "^4.17.21",
44
+ "@types/jsonwebtoken": "^9.0.5",
45
+ "@types/morgan": "^1.9.9",
46
+ "@types/multer": "^1.4.11",
47
+ "@types/node": "^20.9.0",
48
+ "@types/nodemailer": "^6.4.14",
49
+ "@types/web-push": "^3.6.3",
50
+ "@typescript-eslint/eslint-plugin": "^8.66.0",
51
+ "@typescript-eslint/parser": "^8.66.0",
52
+ "eslint": "^10.8.0",
53
+ "prisma": "^7.9.1",
54
+ "tsx": "^4.23.1",
55
+ "typescript": "^5.2.2",
56
+ "typescript-eslint": "^8.66.0"
57
+ }
58
+ }
@@ -0,0 +1,14 @@
1
+ model Attachment {
2
+ id String @id @default(uuid())
3
+ provider StorageProvider
4
+ publicId String // Cloudinary public_id, S3 key, or local path
5
+ url String
6
+ fileName String
7
+ mimeType String
8
+ extension String
9
+ size Int // File size in bytes
10
+ type AttachmentType
11
+ createdAt DateTime @default(now())
12
+ updatedAt DateTime @updatedAt
13
+ deletedAt DateTime?
14
+ }
@@ -0,0 +1,18 @@
1
+ model Notification {
2
+ id String @id @default(uuid())
3
+ userId String
4
+ title String
5
+ message String
6
+ type NotificationType
7
+ actionUrl String?
8
+ metadata Json?
9
+ isRead Boolean @default(false)
10
+ createdAt DateTime @default(now())
11
+ updatedAt DateTime @updatedAt
12
+ deletedAt DateTime?
13
+
14
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
15
+
16
+ @@index([userId])
17
+ @@index([isRead])
18
+ }
@@ -0,0 +1,26 @@
1
+ model Permission {
2
+ id String @id @default(uuid())
3
+ action String // e.g., "CREATE_USER", "VIEW_REPORTS"
4
+ module String // e.g., "USER_MANAGEMENT", "FINANCE"
5
+ description String?
6
+ createdAt DateTime @default(now())
7
+ updatedAt DateTime @updatedAt
8
+
9
+ roles RolePermission[]
10
+
11
+ @@unique([action])
12
+ }
13
+
14
+ model RolePermission {
15
+ id String @id @default(uuid())
16
+ roleId String
17
+ permissionId String
18
+ createdAt DateTime @default(now())
19
+
20
+ role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
21
+ permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
22
+
23
+ @@unique([roleId, permissionId])
24
+ @@index([roleId])
25
+ @@index([permissionId])
26
+ }
@@ -0,0 +1,25 @@
1
+ model Role {
2
+ id String @id @default(uuid())
3
+ name String @unique
4
+ description String?
5
+ createdAt DateTime @default(now())
6
+ updatedAt DateTime @updatedAt
7
+ deletedAt DateTime?
8
+
9
+ permissions RolePermission[]
10
+ users UserRole[]
11
+ }
12
+
13
+ model UserRole {
14
+ id String @id @default(uuid())
15
+ userId String
16
+ roleId String
17
+ createdAt DateTime @default(now())
18
+
19
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
20
+ role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
21
+
22
+ @@unique([userId, roleId])
23
+ @@index([userId])
24
+ @@index([roleId])
25
+ }
@@ -0,0 +1,56 @@
1
+ model User {
2
+ id String @id @default(uuid())
3
+ email String @unique
4
+ password String
5
+ phone String?
6
+ firstName String
7
+ lastName String
8
+ avatar String?
9
+ status UserStatus @default(ACTIVE)
10
+ emailVerified Boolean @default(false)
11
+ lastLogin DateTime?
12
+ createdAt DateTime @default(now())
13
+ updatedAt DateTime @updatedAt
14
+ deletedAt DateTime?
15
+
16
+ // Relations
17
+ roles UserRole[]
18
+ pushSubscriptions PushSubscription[]
19
+ notifications Notification[]
20
+
21
+ @@index([email])
22
+ @@index([status])
23
+ }
24
+
25
+ model Otp {
26
+ id String @id @default(uuid())
27
+ identifier String // Can be email or phone
28
+ otp String
29
+ expiresAt DateTime
30
+ createdAt DateTime @default(now())
31
+
32
+ @@index([identifier])
33
+ }
34
+
35
+ model PushSubscription {
36
+ id String @id @default(uuid())
37
+ type PushSubscriptionType @default(WEB)
38
+
39
+ // For Web Push
40
+ endpoint String?
41
+ keys Json?
42
+
43
+ // For Expo
44
+ token String?
45
+
46
+ userId String
47
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
48
+
49
+ createdAt DateTime @default(now())
50
+ updatedAt DateTime @updatedAt
51
+ deletedAt DateTime?
52
+
53
+ @@index([userId])
54
+ @@index([token])
55
+ @@index([endpoint])
56
+ }
@@ -0,0 +1,13 @@
1
+ enum StorageProvider {
2
+ LOCAL
3
+ S3
4
+ CLOUDINARY
5
+ }
6
+
7
+ enum AttachmentType {
8
+ IMAGE
9
+ DOCUMENT
10
+ VIDEO
11
+ AUDIO
12
+ OTHER
13
+ }
@@ -0,0 +1,6 @@
1
+ enum NotificationType {
2
+ ALERT
3
+ REMINDER
4
+ MESSAGE
5
+ SYSTEM
6
+ }
@@ -0,0 +1,11 @@
1
+ enum UserStatus {
2
+ ACTIVE
3
+ INACTIVE
4
+ SUSPENDED
5
+ DELETED
6
+ }
7
+
8
+ enum PushSubscriptionType {
9
+ WEB
10
+ EXPO
11
+ }
@@ -0,0 +1,7 @@
1
+ generator client {
2
+ provider = "prisma-client-js"
3
+ }
4
+
5
+ datasource db {
6
+ provider = "postgresql"
7
+ }
@@ -0,0 +1,14 @@
1
+ /// <reference types="node" />
2
+ import { defineConfig } from '@prisma/config'
3
+ import 'dotenv/config'
4
+
5
+ export default defineConfig({
6
+ schema: 'prisma/schema',
7
+ migrations: {
8
+ path: 'prisma/migrations',
9
+ seed: 'npx tsx prisma/seed.ts',
10
+ },
11
+ datasource: {
12
+ url: process.env.DATABASE_URL,
13
+ },
14
+ })
@@ -0,0 +1,36 @@
1
+ import express, { Request, Response, NextFunction } from "express";
2
+ import helmet from "helmet";
3
+ import cors from "cors";
4
+ import compression from "compression";
5
+ import cookieParser from "cookie-parser";
6
+ import morgan from "morgan";
7
+ import apiRoutes from "./routes/index.js";
8
+ import { notFound, errorHandler } from "./common/middlewares/errorHandler.js";
9
+ import { apiLimiter } from "./common/middlewares/rateLimiter.js";
10
+
11
+ const app = express();
12
+
13
+ app.use(helmet());
14
+ app.use(
15
+ cors({
16
+ origin: process.env.CLIENT_URL || "http://localhost:5173",
17
+ credentials: true,
18
+ })
19
+ );
20
+ app.use(compression());
21
+ app.use(express.json());
22
+ app.use(express.urlencoded({ extended: true }));
23
+ app.use(cookieParser());
24
+ app.use(morgan("dev"));
25
+
26
+ app.use(apiLimiter);
27
+ app.use("/api/v1", apiRoutes);
28
+
29
+ app.get("/api/health", (req: Request, res: Response) => {
30
+ res.status(200).json({ success: true, message: "API is running" });
31
+ });
32
+
33
+ app.use(notFound);
34
+ app.use(errorHandler);
35
+
36
+ export default app;