@imksh/create 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (441) hide show
  1. package/README.md +88 -0
  2. package/bin/index.js +3 -0
  3. package/package.json +43 -0
  4. package/src/commands/create.js +90 -0
  5. package/src/index.js +41 -0
  6. package/src/utils/askTemplate.js +25 -0
  7. package/src/utils/copyTemplate.js +36 -0
  8. package/src/utils/installPackages.js +25 -0
  9. package/src/utils/logger.js +17 -0
  10. package/src/utils/runGit.js +11 -0
  11. package/templates/mern/_gitignore +2 -0
  12. package/templates/mern/client/_gitignore +24 -0
  13. package/templates/mern/client/index.html +14 -0
  14. package/templates/mern/client/package.json +39 -0
  15. package/templates/mern/client/public/_redirects +1 -0
  16. package/templates/mern/client/public/favicon.ico +0 -0
  17. package/templates/mern/client/public/favicon.svg +1 -0
  18. package/templates/mern/client/public/logo.png +0 -0
  19. package/templates/mern/client/public/manifest.json +24 -0
  20. package/templates/mern/client/public/sw.js +56 -0
  21. package/templates/mern/client/src/App.jsx +68 -0
  22. package/templates/mern/client/src/assets/animations/loading.json +1 -0
  23. package/templates/mern/client/src/assets/data/navigation.js +29 -0
  24. package/templates/mern/client/src/assets/images/logo.png +0 -0
  25. package/templates/mern/client/src/components/common/Breadcrumbs.jsx +27 -0
  26. package/templates/mern/client/src/components/common/Loading.jsx +19 -0
  27. package/templates/mern/client/src/components/common/LottieIcon.jsx +36 -0
  28. package/templates/mern/client/src/components/common/NotFound.jsx +78 -0
  29. package/templates/mern/client/src/components/common/PwaInstallPrompt.jsx +72 -0
  30. package/templates/mern/client/src/components/common/SEO.jsx +67 -0
  31. package/templates/mern/client/src/components/common/Scroll.jsx +25 -0
  32. package/templates/mern/client/src/components/common/Table.jsx +110 -0
  33. package/templates/mern/client/src/components/common/ToggleSwitch.jsx +38 -0
  34. package/templates/mern/client/src/components/common/Unauthorized.jsx +76 -0
  35. package/templates/mern/client/src/components/layout/ProtectedRoute.jsx +17 -0
  36. package/templates/mern/client/src/components/layout/PublicLayout.jsx +13 -0
  37. package/templates/mern/client/src/components/layout/SidebarLayout.jsx +37 -0
  38. package/templates/mern/client/src/components/modals/ConfirmModal.jsx +135 -0
  39. package/templates/mern/client/src/components/modals/Modal.jsx +94 -0
  40. package/templates/mern/client/src/components/skeletons/common/CardSkeleton.jsx +23 -0
  41. package/templates/mern/client/src/components/skeletons/common/DashboardSkeleton.jsx +19 -0
  42. package/templates/mern/client/src/components/skeletons/common/ListSkeleton.jsx +24 -0
  43. package/templates/mern/client/src/components/skeletons/common/PageSkeleton.jsx +26 -0
  44. package/templates/mern/client/src/components/skeletons/common/ProfileSkeleton.jsx +23 -0
  45. package/templates/mern/client/src/components/skeletons/common/Skeleton.jsx +18 -0
  46. package/templates/mern/client/src/components/skeletons/common/TableSkeleton.jsx +33 -0
  47. package/templates/mern/client/src/components/ui/Header.jsx +230 -0
  48. package/templates/mern/client/src/components/ui/SidebarHeader.jsx +27 -0
  49. package/templates/mern/client/src/components/ui/sidebar.jsx +152 -0
  50. package/templates/mern/client/src/config/api.js +22 -0
  51. package/templates/mern/client/src/config/appConfig.js +44 -0
  52. package/templates/mern/client/src/config/navigation.js +14 -0
  53. package/templates/mern/client/src/hooks/useLenis.js +28 -0
  54. package/templates/mern/client/src/hooks/usePwaInstall.js +45 -0
  55. package/templates/mern/client/src/hooks/useWindowSize.js +25 -0
  56. package/templates/mern/client/src/index.css +158 -0
  57. package/templates/mern/client/src/main.jsx +24 -0
  58. package/templates/mern/client/src/pages/Home.jsx +154 -0
  59. package/templates/mern/client/src/pages/Login.jsx +196 -0
  60. package/templates/mern/client/src/pages/Profile.jsx +9 -0
  61. package/templates/mern/client/src/services/authService.js +16 -0
  62. package/templates/mern/client/src/store/useAuthStore.js +98 -0
  63. package/templates/mern/client/src/store/useUiStore.js +54 -0
  64. package/templates/mern/client/src/utils/getInitials.js +10 -0
  65. package/templates/mern/client/vite.config.js +8 -0
  66. package/templates/mern/package.json +18 -0
  67. package/templates/mern/server/.env.example +62 -0
  68. package/templates/mern/server/README.md +65 -0
  69. package/templates/mern/server/_gitignore +24 -0
  70. package/templates/mern/server/package.json +32 -0
  71. package/templates/mern/server/src/app.js +42 -0
  72. package/templates/mern/server/src/config/cloudinary.js +9 -0
  73. package/templates/mern/server/src/config/db.js +14 -0
  74. package/templates/mern/server/src/config/dotenv.js +2 -0
  75. package/templates/mern/server/src/config/email.js +30 -0
  76. package/templates/mern/server/src/config/socket.js +54 -0
  77. package/templates/mern/server/src/config/webPush.js +9 -0
  78. package/templates/mern/server/src/controllers/auth.controller.js +153 -0
  79. package/templates/mern/server/src/controllers/upload.controller.js +26 -0
  80. package/templates/mern/server/src/index.js +24 -0
  81. package/templates/mern/server/src/middleware/auth.middleware.js +43 -0
  82. package/templates/mern/server/src/middleware/errorHandler.js +22 -0
  83. package/templates/mern/server/src/middleware/multer.js +21 -0
  84. package/templates/mern/server/src/middleware/rateLimiter.js +57 -0
  85. package/templates/mern/server/src/models/otp.model.js +21 -0
  86. package/templates/mern/server/src/models/pushSubscription.model.js +32 -0
  87. package/templates/mern/server/src/models/user.model.js +43 -0
  88. package/templates/mern/server/src/routes/auth.route.js +22 -0
  89. package/templates/mern/server/src/routes/index.js +10 -0
  90. package/templates/mern/server/src/routes/upload.route.js +12 -0
  91. package/templates/mern/server/src/services/auth.service.js +162 -0
  92. package/templates/mern/server/src/services/auth.service.ts +0 -0
  93. package/templates/mern/server/src/utils/authToken.js +26 -0
  94. package/templates/mern/server/src/utils/cloudinary.js +27 -0
  95. package/templates/mern/server/src/utils/cloudinaryUpload.js +87 -0
  96. package/templates/mern/server/src/utils/emailOtp.js +190 -0
  97. package/templates/mern/server/src/utils/genOtpToken.js +20 -0
  98. package/templates/mern/server/src/utils/generateVapidKeys.js +12 -0
  99. package/templates/mern/server/src/utils/jwt.js +25 -0
  100. package/templates/mern/server/src/utils/logger.js +25 -0
  101. package/templates/mern-ts/_gitignore +2 -0
  102. package/templates/mern-ts/client/_gitignore +24 -0
  103. package/templates/mern-ts/client/index.html +14 -0
  104. package/templates/mern-ts/client/package.json +45 -0
  105. package/templates/mern-ts/client/public/_redirects +1 -0
  106. package/templates/mern-ts/client/public/favicon.ico +0 -0
  107. package/templates/mern-ts/client/public/favicon.svg +1 -0
  108. package/templates/mern-ts/client/public/logo.png +0 -0
  109. package/templates/mern-ts/client/public/manifest.json +24 -0
  110. package/templates/mern-ts/client/public/sw.js +56 -0
  111. package/templates/mern-ts/client/src/App.tsx +68 -0
  112. package/templates/mern-ts/client/src/assets/animations/loading.json +1 -0
  113. package/templates/mern-ts/client/src/assets/data/navigation.ts +29 -0
  114. package/templates/mern-ts/client/src/assets/images/logo.png +0 -0
  115. package/templates/mern-ts/client/src/components/common/Breadcrumbs.tsx +27 -0
  116. package/templates/mern-ts/client/src/components/common/Loading.tsx +19 -0
  117. package/templates/mern-ts/client/src/components/common/LottieIcon.tsx +36 -0
  118. package/templates/mern-ts/client/src/components/common/NotFound.tsx +78 -0
  119. package/templates/mern-ts/client/src/components/common/PwaInstallPrompt.tsx +72 -0
  120. package/templates/mern-ts/client/src/components/common/SEO.tsx +67 -0
  121. package/templates/mern-ts/client/src/components/common/Scroll.tsx +25 -0
  122. package/templates/mern-ts/client/src/components/common/Table.tsx +118 -0
  123. package/templates/mern-ts/client/src/components/common/ToggleSwitch.tsx +38 -0
  124. package/templates/mern-ts/client/src/components/common/Unauthorized.tsx +76 -0
  125. package/templates/mern-ts/client/src/components/layout/ProtectedRoute.tsx +23 -0
  126. package/templates/mern-ts/client/src/components/layout/PublicLayout.tsx +13 -0
  127. package/templates/mern-ts/client/src/components/layout/SidebarLayout.tsx +37 -0
  128. package/templates/mern-ts/client/src/components/modals/ConfirmModal.tsx +135 -0
  129. package/templates/mern-ts/client/src/components/modals/Modal.tsx +94 -0
  130. package/templates/mern-ts/client/src/components/skeletons/common/CardSkeleton.tsx +23 -0
  131. package/templates/mern-ts/client/src/components/skeletons/common/DashboardSkeleton.tsx +19 -0
  132. package/templates/mern-ts/client/src/components/skeletons/common/ListSkeleton.tsx +24 -0
  133. package/templates/mern-ts/client/src/components/skeletons/common/PageSkeleton.tsx +26 -0
  134. package/templates/mern-ts/client/src/components/skeletons/common/ProfileSkeleton.tsx +23 -0
  135. package/templates/mern-ts/client/src/components/skeletons/common/Skeleton.tsx +18 -0
  136. package/templates/mern-ts/client/src/components/skeletons/common/TableSkeleton.tsx +33 -0
  137. package/templates/mern-ts/client/src/components/ui/Header.tsx +230 -0
  138. package/templates/mern-ts/client/src/components/ui/SidebarHeader.tsx +27 -0
  139. package/templates/mern-ts/client/src/components/ui/sidebar.tsx +152 -0
  140. package/templates/mern-ts/client/src/config/api.ts +22 -0
  141. package/templates/mern-ts/client/src/config/appConfig.ts +44 -0
  142. package/templates/mern-ts/client/src/config/navigation.ts +14 -0
  143. package/templates/mern-ts/client/src/hooks/useLenis.ts +28 -0
  144. package/templates/mern-ts/client/src/hooks/usePwaInstall.ts +45 -0
  145. package/templates/mern-ts/client/src/hooks/useWindowSize.ts +25 -0
  146. package/templates/mern-ts/client/src/index.css +158 -0
  147. package/templates/mern-ts/client/src/main.tsx +24 -0
  148. package/templates/mern-ts/client/src/pages/Home.tsx +154 -0
  149. package/templates/mern-ts/client/src/pages/Login.tsx +196 -0
  150. package/templates/mern-ts/client/src/pages/Profile.tsx +9 -0
  151. package/templates/mern-ts/client/src/services/authService.ts +16 -0
  152. package/templates/mern-ts/client/src/store/useAuthStore.ts +98 -0
  153. package/templates/mern-ts/client/src/store/useUiStore.ts +54 -0
  154. package/templates/mern-ts/client/src/utils/getInitials.ts +10 -0
  155. package/templates/mern-ts/client/tsconfig.json +25 -0
  156. package/templates/mern-ts/client/tsconfig.node.json +10 -0
  157. package/templates/mern-ts/client/vite.config.ts +8 -0
  158. package/templates/mern-ts/package.json +19 -0
  159. package/templates/mern-ts/server/.env.example +62 -0
  160. package/templates/mern-ts/server/README.md +69 -0
  161. package/templates/mern-ts/server/_gitignore +24 -0
  162. package/templates/mern-ts/server/package.json +47 -0
  163. package/templates/mern-ts/server/src/app.ts +36 -0
  164. package/templates/mern-ts/server/src/config/cloudinary.ts +9 -0
  165. package/templates/mern-ts/server/src/config/db.ts +15 -0
  166. package/templates/mern-ts/server/src/config/dotenv.ts +2 -0
  167. package/templates/mern-ts/server/src/config/email.ts +28 -0
  168. package/templates/mern-ts/server/src/config/socket.ts +54 -0
  169. package/templates/mern-ts/server/src/config/webPush.ts +9 -0
  170. package/templates/mern-ts/server/src/controllers/auth.controller.ts +126 -0
  171. package/templates/mern-ts/server/src/controllers/upload.controller.ts +22 -0
  172. package/templates/mern-ts/server/src/index.ts +17 -0
  173. package/templates/mern-ts/server/src/middleware/auth.middleware.ts +38 -0
  174. package/templates/mern-ts/server/src/middleware/errorHandler.ts +16 -0
  175. package/templates/mern-ts/server/src/middleware/multer.ts +20 -0
  176. package/templates/mern-ts/server/src/middleware/rateLimiter.ts +53 -0
  177. package/templates/mern-ts/server/src/models/otp.model.ts +21 -0
  178. package/templates/mern-ts/server/src/models/pushSubscription.model.ts +32 -0
  179. package/templates/mern-ts/server/src/models/user.model.ts +43 -0
  180. package/templates/mern-ts/server/src/routes/auth.route.ts +22 -0
  181. package/templates/mern-ts/server/src/routes/index.ts +10 -0
  182. package/templates/mern-ts/server/src/routes/upload.route.ts +11 -0
  183. package/templates/mern-ts/server/src/services/auth.service.ts +115 -0
  184. package/templates/mern-ts/server/src/types/express.d.ts +10 -0
  185. package/templates/mern-ts/server/src/utils/cloudinaryUpload.ts +44 -0
  186. package/templates/mern-ts/server/src/utils/emailOtp.ts +30 -0
  187. package/templates/mern-ts/server/src/utils/genOtpToken.ts +22 -0
  188. package/templates/mern-ts/server/src/utils/generateVapidKeys.ts +12 -0
  189. package/templates/mern-ts/server/src/utils/jwt.ts +27 -0
  190. package/templates/mern-ts/server/src/utils/logger.ts +27 -0
  191. package/templates/mern-ts/server/tsconfig.json +14 -0
  192. package/templates/next/_gitignore +24 -0
  193. package/templates/next/package.json +20 -0
  194. package/templates/next/src/app/layout.js +7 -0
  195. package/templates/next/src/app/page.js +218 -0
  196. package/templates/next-ts/_gitignore +24 -0
  197. package/templates/next-ts/package.json +24 -0
  198. package/templates/next-ts/src/app/layout.tsx +9 -0
  199. package/templates/next-ts/src/app/page.tsx +218 -0
  200. package/templates/next-ts/tsconfig.json +27 -0
  201. package/templates/node/.env.example +62 -0
  202. package/templates/node/README.md +65 -0
  203. package/templates/node/_gitignore +24 -0
  204. package/templates/node/package.json +32 -0
  205. package/templates/node/src/app.js +42 -0
  206. package/templates/node/src/config/cloudinary.js +9 -0
  207. package/templates/node/src/config/db.js +14 -0
  208. package/templates/node/src/config/dotenv.js +2 -0
  209. package/templates/node/src/config/email.js +30 -0
  210. package/templates/node/src/config/socket.js +54 -0
  211. package/templates/node/src/config/webPush.js +9 -0
  212. package/templates/node/src/controllers/auth.controller.js +153 -0
  213. package/templates/node/src/controllers/upload.controller.js +26 -0
  214. package/templates/node/src/index.js +24 -0
  215. package/templates/node/src/middleware/auth.middleware.js +43 -0
  216. package/templates/node/src/middleware/errorHandler.js +22 -0
  217. package/templates/node/src/middleware/multer.js +21 -0
  218. package/templates/node/src/middleware/rateLimiter.js +57 -0
  219. package/templates/node/src/models/otp.model.js +21 -0
  220. package/templates/node/src/models/pushSubscription.model.js +32 -0
  221. package/templates/node/src/models/user.model.js +43 -0
  222. package/templates/node/src/routes/auth.route.js +22 -0
  223. package/templates/node/src/routes/index.js +10 -0
  224. package/templates/node/src/routes/upload.route.js +12 -0
  225. package/templates/node/src/services/auth.service.js +162 -0
  226. package/templates/node/src/services/auth.service.ts +0 -0
  227. package/templates/node/src/utils/authToken.js +26 -0
  228. package/templates/node/src/utils/cloudinary.js +27 -0
  229. package/templates/node/src/utils/cloudinaryUpload.js +87 -0
  230. package/templates/node/src/utils/emailOtp.js +190 -0
  231. package/templates/node/src/utils/genOtpToken.js +20 -0
  232. package/templates/node/src/utils/generateVapidKeys.js +12 -0
  233. package/templates/node/src/utils/jwt.js +25 -0
  234. package/templates/node/src/utils/logger.js +25 -0
  235. package/templates/node-prisma/.env.example +63 -0
  236. package/templates/node-prisma/README.md +69 -0
  237. package/templates/node-prisma/_gitignore +24 -0
  238. package/templates/node-prisma/package.json +35 -0
  239. package/templates/node-prisma/prisma/schema.prisma +41 -0
  240. package/templates/node-prisma/src/app.js +42 -0
  241. package/templates/node-prisma/src/config/cloudinary.js +9 -0
  242. package/templates/node-prisma/src/config/db.js +16 -0
  243. package/templates/node-prisma/src/config/dotenv.js +2 -0
  244. package/templates/node-prisma/src/config/email.js +30 -0
  245. package/templates/node-prisma/src/config/socket.js +54 -0
  246. package/templates/node-prisma/src/config/webPush.js +9 -0
  247. package/templates/node-prisma/src/controllers/auth.controller.js +146 -0
  248. package/templates/node-prisma/src/controllers/upload.controller.js +26 -0
  249. package/templates/node-prisma/src/index.js +24 -0
  250. package/templates/node-prisma/src/middleware/auth.middleware.js +44 -0
  251. package/templates/node-prisma/src/middleware/errorHandler.js +22 -0
  252. package/templates/node-prisma/src/middleware/multer.js +21 -0
  253. package/templates/node-prisma/src/middleware/rateLimiter.js +57 -0
  254. package/templates/node-prisma/src/routes/auth.route.js +22 -0
  255. package/templates/node-prisma/src/routes/index.js +10 -0
  256. package/templates/node-prisma/src/routes/upload.route.js +12 -0
  257. package/templates/node-prisma/src/services/auth.service.js +163 -0
  258. package/templates/node-prisma/src/services/auth.service.ts +0 -0
  259. package/templates/node-prisma/src/utils/authToken.js +26 -0
  260. package/templates/node-prisma/src/utils/cloudinary.js +27 -0
  261. package/templates/node-prisma/src/utils/cloudinaryUpload.js +87 -0
  262. package/templates/node-prisma/src/utils/emailOtp.js +190 -0
  263. package/templates/node-prisma/src/utils/genOtpToken.js +20 -0
  264. package/templates/node-prisma/src/utils/generateVapidKeys.js +12 -0
  265. package/templates/node-prisma/src/utils/jwt.js +25 -0
  266. package/templates/node-prisma/src/utils/logger.js +25 -0
  267. package/templates/node-prisma-ts/.env.example +63 -0
  268. package/templates/node-prisma-ts/README.md +73 -0
  269. package/templates/node-prisma-ts/_gitignore +24 -0
  270. package/templates/node-prisma-ts/package.json +48 -0
  271. package/templates/node-prisma-ts/prisma/schema.prisma +41 -0
  272. package/templates/node-prisma-ts/src/app.ts +36 -0
  273. package/templates/node-prisma-ts/src/config/cloudinary.ts +9 -0
  274. package/templates/node-prisma-ts/src/config/db.ts +16 -0
  275. package/templates/node-prisma-ts/src/config/dotenv.ts +2 -0
  276. package/templates/node-prisma-ts/src/config/email.ts +28 -0
  277. package/templates/node-prisma-ts/src/config/socket.ts +54 -0
  278. package/templates/node-prisma-ts/src/config/webPush.ts +9 -0
  279. package/templates/node-prisma-ts/src/controllers/auth.controller.ts +124 -0
  280. package/templates/node-prisma-ts/src/controllers/upload.controller.ts +22 -0
  281. package/templates/node-prisma-ts/src/index.ts +17 -0
  282. package/templates/node-prisma-ts/src/middleware/auth.middleware.ts +45 -0
  283. package/templates/node-prisma-ts/src/middleware/errorHandler.ts +16 -0
  284. package/templates/node-prisma-ts/src/middleware/multer.ts +20 -0
  285. package/templates/node-prisma-ts/src/middleware/rateLimiter.ts +53 -0
  286. package/templates/node-prisma-ts/src/routes/auth.route.ts +22 -0
  287. package/templates/node-prisma-ts/src/routes/index.ts +10 -0
  288. package/templates/node-prisma-ts/src/routes/upload.route.ts +11 -0
  289. package/templates/node-prisma-ts/src/services/auth.service.ts +163 -0
  290. package/templates/node-prisma-ts/src/types/express.d.ts +10 -0
  291. package/templates/node-prisma-ts/src/utils/cloudinaryUpload.ts +44 -0
  292. package/templates/node-prisma-ts/src/utils/emailOtp.ts +30 -0
  293. package/templates/node-prisma-ts/src/utils/genOtpToken.ts +22 -0
  294. package/templates/node-prisma-ts/src/utils/generateVapidKeys.ts +12 -0
  295. package/templates/node-prisma-ts/src/utils/jwt.ts +27 -0
  296. package/templates/node-prisma-ts/src/utils/logger.ts +27 -0
  297. package/templates/node-prisma-ts/tsconfig.json +14 -0
  298. package/templates/node-ts/.env.example +62 -0
  299. package/templates/node-ts/README.md +69 -0
  300. package/templates/node-ts/_gitignore +24 -0
  301. package/templates/node-ts/package.json +47 -0
  302. package/templates/node-ts/src/app.ts +36 -0
  303. package/templates/node-ts/src/config/cloudinary.ts +9 -0
  304. package/templates/node-ts/src/config/db.ts +15 -0
  305. package/templates/node-ts/src/config/dotenv.ts +2 -0
  306. package/templates/node-ts/src/config/email.ts +28 -0
  307. package/templates/node-ts/src/config/socket.ts +54 -0
  308. package/templates/node-ts/src/config/webPush.ts +9 -0
  309. package/templates/node-ts/src/controllers/auth.controller.ts +126 -0
  310. package/templates/node-ts/src/controllers/upload.controller.ts +22 -0
  311. package/templates/node-ts/src/index.ts +17 -0
  312. package/templates/node-ts/src/middleware/auth.middleware.ts +38 -0
  313. package/templates/node-ts/src/middleware/errorHandler.ts +16 -0
  314. package/templates/node-ts/src/middleware/multer.ts +20 -0
  315. package/templates/node-ts/src/middleware/rateLimiter.ts +53 -0
  316. package/templates/node-ts/src/models/otp.model.ts +21 -0
  317. package/templates/node-ts/src/models/pushSubscription.model.ts +32 -0
  318. package/templates/node-ts/src/models/user.model.ts +43 -0
  319. package/templates/node-ts/src/routes/auth.route.ts +22 -0
  320. package/templates/node-ts/src/routes/index.ts +10 -0
  321. package/templates/node-ts/src/routes/upload.route.ts +11 -0
  322. package/templates/node-ts/src/services/auth.service.ts +115 -0
  323. package/templates/node-ts/src/types/express.d.ts +10 -0
  324. package/templates/node-ts/src/utils/cloudinaryUpload.ts +44 -0
  325. package/templates/node-ts/src/utils/emailOtp.ts +30 -0
  326. package/templates/node-ts/src/utils/genOtpToken.ts +22 -0
  327. package/templates/node-ts/src/utils/generateVapidKeys.ts +12 -0
  328. package/templates/node-ts/src/utils/jwt.ts +27 -0
  329. package/templates/node-ts/src/utils/logger.ts +27 -0
  330. package/templates/node-ts/tsconfig.json +18 -0
  331. package/templates/react/.env.example +1 -0
  332. package/templates/react/_gitignore +24 -0
  333. package/templates/react/index.html +14 -0
  334. package/templates/react/package.json +39 -0
  335. package/templates/react/public/_redirects +1 -0
  336. package/templates/react/public/favicon.ico +0 -0
  337. package/templates/react/public/favicon.svg +1 -0
  338. package/templates/react/public/logo.png +0 -0
  339. package/templates/react/public/manifest.json +24 -0
  340. package/templates/react/public/sw.js +56 -0
  341. package/templates/react/src/App.jsx +68 -0
  342. package/templates/react/src/assets/animations/loading.json +1 -0
  343. package/templates/react/src/assets/data/navigation.js +29 -0
  344. package/templates/react/src/assets/images/logo.png +0 -0
  345. package/templates/react/src/components/common/Breadcrumbs.jsx +27 -0
  346. package/templates/react/src/components/common/Loading.jsx +19 -0
  347. package/templates/react/src/components/common/LottieIcon.jsx +36 -0
  348. package/templates/react/src/components/common/NotFound.jsx +78 -0
  349. package/templates/react/src/components/common/PwaInstallPrompt.jsx +72 -0
  350. package/templates/react/src/components/common/SEO.jsx +67 -0
  351. package/templates/react/src/components/common/Scroll.jsx +25 -0
  352. package/templates/react/src/components/common/Table.jsx +110 -0
  353. package/templates/react/src/components/common/ToggleSwitch.jsx +38 -0
  354. package/templates/react/src/components/common/Unauthorized.jsx +76 -0
  355. package/templates/react/src/components/layout/ProtectedRoute.jsx +17 -0
  356. package/templates/react/src/components/layout/PublicLayout.jsx +13 -0
  357. package/templates/react/src/components/layout/SidebarLayout.jsx +37 -0
  358. package/templates/react/src/components/modals/ConfirmModal.jsx +135 -0
  359. package/templates/react/src/components/modals/Modal.jsx +94 -0
  360. package/templates/react/src/components/skeletons/common/CardSkeleton.jsx +23 -0
  361. package/templates/react/src/components/skeletons/common/DashboardSkeleton.jsx +19 -0
  362. package/templates/react/src/components/skeletons/common/ListSkeleton.jsx +24 -0
  363. package/templates/react/src/components/skeletons/common/PageSkeleton.jsx +26 -0
  364. package/templates/react/src/components/skeletons/common/ProfileSkeleton.jsx +23 -0
  365. package/templates/react/src/components/skeletons/common/Skeleton.jsx +18 -0
  366. package/templates/react/src/components/skeletons/common/TableSkeleton.jsx +33 -0
  367. package/templates/react/src/components/ui/Header.jsx +230 -0
  368. package/templates/react/src/components/ui/SidebarHeader.jsx +27 -0
  369. package/templates/react/src/components/ui/sidebar.jsx +152 -0
  370. package/templates/react/src/config/api.js +22 -0
  371. package/templates/react/src/config/appConfig.js +44 -0
  372. package/templates/react/src/config/navigation.js +14 -0
  373. package/templates/react/src/hooks/useLenis.js +28 -0
  374. package/templates/react/src/hooks/usePwaInstall.js +45 -0
  375. package/templates/react/src/hooks/useWindowSize.js +25 -0
  376. package/templates/react/src/index.css +158 -0
  377. package/templates/react/src/main.jsx +24 -0
  378. package/templates/react/src/pages/Home.jsx +154 -0
  379. package/templates/react/src/pages/Login.jsx +196 -0
  380. package/templates/react/src/pages/Profile.jsx +9 -0
  381. package/templates/react/src/services/authService.js +16 -0
  382. package/templates/react/src/store/useAuthStore.js +98 -0
  383. package/templates/react/src/store/useUiStore.js +54 -0
  384. package/templates/react/src/utils/getInitials.js +10 -0
  385. package/templates/react/vite.config.js +8 -0
  386. package/templates/react-ts/_gitignore +24 -0
  387. package/templates/react-ts/index.html +14 -0
  388. package/templates/react-ts/package.json +45 -0
  389. package/templates/react-ts/public/_redirects +1 -0
  390. package/templates/react-ts/public/favicon.ico +0 -0
  391. package/templates/react-ts/public/favicon.svg +1 -0
  392. package/templates/react-ts/public/logo.png +0 -0
  393. package/templates/react-ts/public/manifest.json +24 -0
  394. package/templates/react-ts/public/sw.js +56 -0
  395. package/templates/react-ts/src/App.tsx +68 -0
  396. package/templates/react-ts/src/assets/animations/loading.json +1 -0
  397. package/templates/react-ts/src/assets/data/navigation.ts +29 -0
  398. package/templates/react-ts/src/assets/images/logo.png +0 -0
  399. package/templates/react-ts/src/components/common/Breadcrumbs.tsx +27 -0
  400. package/templates/react-ts/src/components/common/Loading.tsx +19 -0
  401. package/templates/react-ts/src/components/common/LottieIcon.tsx +36 -0
  402. package/templates/react-ts/src/components/common/NotFound.tsx +78 -0
  403. package/templates/react-ts/src/components/common/PwaInstallPrompt.tsx +72 -0
  404. package/templates/react-ts/src/components/common/SEO.tsx +67 -0
  405. package/templates/react-ts/src/components/common/Scroll.tsx +25 -0
  406. package/templates/react-ts/src/components/common/Table.tsx +118 -0
  407. package/templates/react-ts/src/components/common/ToggleSwitch.tsx +38 -0
  408. package/templates/react-ts/src/components/common/Unauthorized.tsx +76 -0
  409. package/templates/react-ts/src/components/layout/ProtectedRoute.tsx +23 -0
  410. package/templates/react-ts/src/components/layout/PublicLayout.tsx +13 -0
  411. package/templates/react-ts/src/components/layout/SidebarLayout.tsx +37 -0
  412. package/templates/react-ts/src/components/modals/ConfirmModal.tsx +135 -0
  413. package/templates/react-ts/src/components/modals/Modal.tsx +94 -0
  414. package/templates/react-ts/src/components/skeletons/common/CardSkeleton.tsx +23 -0
  415. package/templates/react-ts/src/components/skeletons/common/DashboardSkeleton.tsx +19 -0
  416. package/templates/react-ts/src/components/skeletons/common/ListSkeleton.tsx +24 -0
  417. package/templates/react-ts/src/components/skeletons/common/PageSkeleton.tsx +26 -0
  418. package/templates/react-ts/src/components/skeletons/common/ProfileSkeleton.tsx +23 -0
  419. package/templates/react-ts/src/components/skeletons/common/Skeleton.tsx +18 -0
  420. package/templates/react-ts/src/components/skeletons/common/TableSkeleton.tsx +33 -0
  421. package/templates/react-ts/src/components/ui/Header.tsx +230 -0
  422. package/templates/react-ts/src/components/ui/SidebarHeader.tsx +27 -0
  423. package/templates/react-ts/src/components/ui/sidebar.tsx +152 -0
  424. package/templates/react-ts/src/config/api.ts +22 -0
  425. package/templates/react-ts/src/config/appConfig.ts +44 -0
  426. package/templates/react-ts/src/config/navigation.ts +14 -0
  427. package/templates/react-ts/src/hooks/useLenis.ts +28 -0
  428. package/templates/react-ts/src/hooks/usePwaInstall.ts +45 -0
  429. package/templates/react-ts/src/hooks/useWindowSize.ts +25 -0
  430. package/templates/react-ts/src/index.css +158 -0
  431. package/templates/react-ts/src/main.tsx +24 -0
  432. package/templates/react-ts/src/pages/Home.tsx +154 -0
  433. package/templates/react-ts/src/pages/Login.tsx +196 -0
  434. package/templates/react-ts/src/pages/Profile.tsx +9 -0
  435. package/templates/react-ts/src/services/authService.ts +16 -0
  436. package/templates/react-ts/src/store/useAuthStore.ts +98 -0
  437. package/templates/react-ts/src/store/useUiStore.ts +54 -0
  438. package/templates/react-ts/src/utils/getInitials.ts +10 -0
  439. package/templates/react-ts/tsconfig.json +25 -0
  440. package/templates/react-ts/tsconfig.node.json +10 -0
  441. package/templates/react-ts/vite.config.ts +8 -0
@@ -0,0 +1,54 @@
1
+ import { Server } from "socket.io";
2
+ import logger from "../utils/logger.js";
3
+
4
+ let io: Server;
5
+
6
+ const userSocketMap: { [key: string]: Set<string> } = {};
7
+
8
+ const initializeSocket = (server: any) => {
9
+ io = new Server(server, {
10
+ cors: {
11
+ origin: ["http://localhost:5173"],
12
+ credentials: true,
13
+ },
14
+ });
15
+
16
+ io.on("connection", (socket) => {
17
+ const userId = socket.handshake.auth.userId as string | undefined;
18
+
19
+ if (!userId) {
20
+ logger.warn("No userId, disconnecting socket");
21
+ socket.disconnect();
22
+ return;
23
+ }
24
+
25
+ logger.info(`Socket connected: ${socket.id} (User: ${userId})`);
26
+
27
+ if (!userSocketMap[userId]) {
28
+ userSocketMap[userId] = new Set<string>();
29
+ }
30
+ userSocketMap[userId].add(socket.id);
31
+
32
+ socket.on("disconnect", (reason) => {
33
+ if (!userId) return;
34
+ userSocketMap[userId].delete(socket.id);
35
+ logger.info(`Socket disconnected: ${socket.id} (Reason: ${reason})`);
36
+ });
37
+ });
38
+
39
+ return io;
40
+ };
41
+
42
+ export const getIO = () => {
43
+ if (!io) {
44
+ throw new Error("Socket.IO has not been initialized yet");
45
+ }
46
+ return io;
47
+ };
48
+
49
+ const getReceiverSocketIds = (userId: string) =>
50
+ userSocketMap[userId] ? Array.from(userSocketMap[userId]) : [];
51
+
52
+ export { io, getReceiverSocketIds, userSocketMap };
53
+
54
+ export default initializeSocket;
@@ -0,0 +1,9 @@
1
+ import webpush from "web-push";
2
+
3
+ webpush.setVapidDetails(
4
+ process.env.VAPID_SUBJECT as string || "",
5
+ process.env.VAPID_PUBLIC_KEY as string || "",
6
+ process.env.VAPID_PRIVATE_KEY as string || ""
7
+ );
8
+
9
+ export default webpush;
@@ -0,0 +1,126 @@
1
+ import { Request, Response, NextFunction } from "express";
2
+ import { authService } from "../services/auth.service.js";
3
+ import { generateToken } from "../utils/jwt.js";
4
+ import genOtpToken from "../utils/genOtpToken.js";
5
+ import logger from "../utils/logger.js";
6
+
7
+ export const signup = async (req: Request, res: Response, next: NextFunction) => {
8
+ try {
9
+ const { name, email, phone, password } = req.body;
10
+ if (!email || !password || !name) {
11
+ return next({ status: 400, message: "All fields are required." });
12
+ }
13
+ const newUser = await authService.signup({ name, email, phone, password });
14
+ const token = await generateToken(newUser, res);
15
+ const safeUser: any = newUser.toObject();
16
+ delete safeUser.password;
17
+ res.status(201).json({ message: "Registration Successful", data: safeUser, token });
18
+ } catch (error) {
19
+ logger.error("Error in signup controller", error);
20
+ next(error);
21
+ }
22
+ };
23
+
24
+ export const login = async (req: Request, res: Response, next: NextFunction) => {
25
+ try {
26
+ const { email, password } = req.body;
27
+ if (!email || !password) {
28
+ return next({ status: 400, message: "All fields are required." });
29
+ }
30
+ const user = await authService.login({ email, password });
31
+ const token = await generateToken(user, res);
32
+ const safeUser: any = user.toObject();
33
+ delete safeUser.password;
34
+ res.status(200).json({ message: "Login successfully", data: safeUser, token });
35
+ } catch (error) {
36
+ logger.error("Error in login controller", error);
37
+ next(error);
38
+ }
39
+ };
40
+
41
+ export const logout = async (req: Request, res: Response, next: NextFunction) => {
42
+ try {
43
+ res.clearCookie("token", {
44
+ httpOnly: true,
45
+ secure: process.env.NODE_ENV === "production",
46
+ sameSite: "strict",
47
+ path: "/",
48
+ });
49
+ res.status(200).json({ message: "Logout Successfully" });
50
+ } catch (error) {
51
+ logger.error("Error in logout controller", error);
52
+ next(error);
53
+ }
54
+ };
55
+
56
+ export const getMe = async (req: Request, res: Response, next: NextFunction) => {
57
+ try {
58
+ const safeUser: any = req.user.toObject();
59
+ delete safeUser.password;
60
+ res.status(200).json({ message: "User Authenticated", data: safeUser });
61
+ } catch (error) {
62
+ logger.error("Error in getMe controller", error);
63
+ next(error);
64
+ }
65
+ };
66
+
67
+ export const genOtp = async (req: Request, res: Response, next: NextFunction) => {
68
+ try {
69
+ const { email } = req.body;
70
+ if (!email) {
71
+ return next({ status: 400, message: "Email is required." });
72
+ }
73
+ await authService.generateOtp(email);
74
+ res.status(200).json({ message: "Otp sent successfully" });
75
+ } catch (error) {
76
+ logger.error("Error in genOtp", error);
77
+ next(error);
78
+ }
79
+ };
80
+
81
+ export const verifyOtp = async (req: Request, res: Response, next: NextFunction) => {
82
+ try {
83
+ const { email, otp } = req.body;
84
+ if (!email || !otp) {
85
+ return next({ status: 400, message: "All fields are required." });
86
+ }
87
+ const user = await authService.verifyOtp({ email, otp });
88
+ await genOtpToken(user, res);
89
+ res.status(200).json({ message: "Otp verified successfully" });
90
+ } catch (error) {
91
+ logger.error("Error in verifyOtp", error);
92
+ next(error);
93
+ }
94
+ };
95
+
96
+ export const resetPassword = async (req: Request, res: Response, next: NextFunction) => {
97
+ try {
98
+ const { newPassword } = req.body;
99
+ const currentUser = req.user;
100
+ if (!newPassword) {
101
+ return next({ status: 400, message: "All fields are required." });
102
+ }
103
+ await authService.resetPassword(currentUser, newPassword);
104
+ res.status(200).json({ message: "Password updated successfully" });
105
+ } catch (error) {
106
+ logger.error("Error in resetPassword", error);
107
+ next(error);
108
+ }
109
+ };
110
+
111
+ export const updateMe = async (req: Request, res: Response, next: NextFunction) => {
112
+ try {
113
+ const { name, phone } = req.body;
114
+ const user = await authService.updateProfile(req.user._id, {
115
+ name,
116
+ phone,
117
+ file: req.file,
118
+ });
119
+ const safeUser: any = user.toObject();
120
+ delete safeUser.password;
121
+ res.status(200).json({ success: true, data: safeUser });
122
+ } catch (error) {
123
+ logger.error("Error updating profile", error);
124
+ next(error);
125
+ }
126
+ };
@@ -0,0 +1,22 @@
1
+ import { Request, Response, NextFunction } from "express";
2
+ import { uploadSingleToCloudinary } from "../utils/cloudinaryUpload.js";
3
+ import logger from "../utils/logger.js";
4
+
5
+ export const uploadFile = async (req: Request, res: Response, next: NextFunction) => {
6
+ try {
7
+ if (!req.file) {
8
+ return res.status(400).json({ success: false, message: "No file uploaded" });
9
+ }
10
+ const result = await uploadSingleToCloudinary(req.file, {
11
+ folder: req.body.folder || "general_uploads",
12
+ });
13
+ res.status(200).json({
14
+ success: true,
15
+ message: "File uploaded successfully",
16
+ data: result,
17
+ });
18
+ } catch (error) {
19
+ logger.error("Upload controller error", error);
20
+ next(error);
21
+ }
22
+ };
@@ -0,0 +1,17 @@
1
+ import dotenv from "dotenv";
2
+ import http from "http";
3
+ import app from "./app.js";
4
+ import connectDB from "./config/db.js";
5
+ import logger from "./utils/logger.js";
6
+
7
+ dotenv.config();
8
+
9
+ const PORT = process.env.PORT || 5000;
10
+
11
+ connectDB();
12
+
13
+ const server = http.createServer(app);
14
+
15
+ server.listen(PORT, () => {
16
+ logger.success(`Server is running on port ${PORT}`);
17
+ });
@@ -0,0 +1,38 @@
1
+ import { Request, Response, NextFunction } from "express";
2
+ import User from "../models/user.model.js";
3
+ import { verifyToken } from "../utils/jwt.js";
4
+ import logger from "../utils/logger.js";
5
+
6
+ export const protect = async (req: Request, res: Response, next: NextFunction) => {
7
+ let token: string | undefined;
8
+
9
+ if (req.cookies?.token) {
10
+ token = req.cookies.token;
11
+ } else if (
12
+ req.headers.authorization &&
13
+ req.headers.authorization.startsWith("Bearer")
14
+ ) {
15
+ token = req.headers.authorization.split(" ")[1];
16
+ }
17
+
18
+ if (!token) {
19
+ return res.status(401).json({ message: "Not authorized, no token provided" });
20
+ }
21
+
22
+ try {
23
+ const decoded: any = verifyToken(token);
24
+ if (!decoded) {
25
+ return res.status(401).json({ message: "Not authorized, invalid token" });
26
+ }
27
+
28
+ req.user = await User.findById(decoded.id).select("-password");
29
+ if (!req.user) {
30
+ return res.status(401).json({ message: "Not authorized, user not found" });
31
+ }
32
+
33
+ return next();
34
+ } catch (error: any) {
35
+ logger.error("Auth middleware error", error);
36
+ return res.status(401).json({ message: "Not authorized, token verification failed" });
37
+ }
38
+ };
@@ -0,0 +1,16 @@
1
+ import { Request, Response, NextFunction } from "express";
2
+
3
+ export const notFound = (req: Request, res: Response, next: NextFunction) => {
4
+ const error = new Error(`Not Found - ${req.originalUrl}`);
5
+ res.status(404);
6
+ next(error);
7
+ };
8
+
9
+ export const errorHandler = (err: any, req: Request, res: Response, next: NextFunction) => {
10
+ const statusCode = err.status || err.statusCode || (res.statusCode === 200 ? 500 : res.statusCode);
11
+ res.status(statusCode).json({
12
+ success: false,
13
+ message: err.message || "An unexpected error occurred",
14
+ stack: process.env.NODE_ENV === "production" ? undefined : err.stack,
15
+ });
16
+ };
@@ -0,0 +1,20 @@
1
+ import multer, { FileFilterCallback } from "multer";
2
+ import { Request } from "express";
3
+
4
+ const storage = multer.memoryStorage();
5
+
6
+ const fileFilter = (req: Request, file: Express.Multer.File, cb: FileFilterCallback) => {
7
+ if (file.mimetype.startsWith("image/")) {
8
+ cb(null, true);
9
+ } else {
10
+ cb(new Error("Only image files are allowed!"));
11
+ }
12
+ };
13
+
14
+ export const upload = multer({
15
+ storage,
16
+ fileFilter,
17
+ limits: {
18
+ fileSize: 5 * 1024 * 1024, // 5MB limit
19
+ },
20
+ });
@@ -0,0 +1,53 @@
1
+ import rateLimit from "express-rate-limit";
2
+ import { Request, Response } from "express";
3
+
4
+ interface LimiterConfig {
5
+ windowMs: number;
6
+ max: number;
7
+ message: string;
8
+ skipSuccessfulRequests?: boolean;
9
+ }
10
+
11
+ const createLimiter = ({
12
+ windowMs,
13
+ max,
14
+ message,
15
+ skipSuccessfulRequests = false,
16
+ }: LimiterConfig) =>
17
+ rateLimit({
18
+ windowMs,
19
+ max,
20
+ standardHeaders: true,
21
+ legacyHeaders: false,
22
+ skipSuccessfulRequests,
23
+
24
+ keyGenerator: (req: any) => {
25
+ return req.user?.id || req.ip || req.headers["x-forwarded-for"] || req.socket.remoteAddress;
26
+ },
27
+
28
+ handler: (req: Request, res: Response) => {
29
+ res.status(429).json({
30
+ success: false,
31
+ message,
32
+ });
33
+ },
34
+ });
35
+
36
+ export const apiLimiter = createLimiter({
37
+ windowMs: 15 * 60 * 1000,
38
+ max: 100,
39
+ message: "Too many requests. Please try again later.",
40
+ });
41
+
42
+ export const authLimiter = createLimiter({
43
+ windowMs: 15 * 60 * 1000,
44
+ max: 10,
45
+ skipSuccessfulRequests: true,
46
+ message: "Too many login attempts. Please try again later.",
47
+ });
48
+
49
+ export const uploadLimiter = createLimiter({
50
+ windowMs: 60 * 60 * 1000,
51
+ max: 20,
52
+ message: "Upload limit reached. Please try again in an hour.",
53
+ });
@@ -0,0 +1,21 @@
1
+ import mongoose from "mongoose";
2
+
3
+ const otpSchema = new mongoose.Schema({
4
+ email: {
5
+ type: String,
6
+ required: true,
7
+ },
8
+ otp: {
9
+ type: String,
10
+ required: true,
11
+ },
12
+ createdAt: {
13
+ type: Date,
14
+ default: Date.now(),
15
+ expires: 300,
16
+ },
17
+ });
18
+
19
+ const Otp = mongoose.model("Otp", otpSchema);
20
+
21
+ export default Otp;
@@ -0,0 +1,32 @@
1
+ import mongoose from "mongoose";
2
+
3
+ const pushSubscriptionSchema = new mongoose.Schema(
4
+ {
5
+ endpoint: {
6
+ type: String,
7
+ required: true,
8
+ unique: true,
9
+ },
10
+ keys: {
11
+ p256dh: { type: String, required: true },
12
+ auth: { type: String, required: true },
13
+ },
14
+ user: {
15
+ type: mongoose.Schema.Types.ObjectId,
16
+ ref: "User",
17
+ },
18
+ role: {
19
+ type: String,
20
+ enum: ["admin", "user"],
21
+ default: "user",
22
+ },
23
+ expiresAt: {
24
+ type: Date,
25
+ default: () => new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
26
+ index: { expires: 0 },
27
+ },
28
+ },
29
+ { timestamps: true },
30
+ );
31
+
32
+ export default mongoose.model("PushSubscription", pushSubscriptionSchema);
@@ -0,0 +1,43 @@
1
+ import mongoose from "mongoose";
2
+
3
+ const userSchema = new mongoose.Schema(
4
+ {
5
+ name: {
6
+ type: String,
7
+ required: [true, "Name is required"],
8
+ trim: true,
9
+ },
10
+
11
+ email: {
12
+ type: String,
13
+ required: [true, "Email is required"],
14
+ unique: true,
15
+ lowercase: true,
16
+ trim: true,
17
+ },
18
+ phone: {
19
+ type: String,
20
+ },
21
+ avatar: {
22
+ publicId: {
23
+ type: String,
24
+ },
25
+ url: {
26
+ type: String,
27
+ },
28
+ },
29
+ password: {
30
+ type: String,
31
+ required: [true, "Password is required"],
32
+ },
33
+ role: {
34
+ type: String,
35
+ enum: ["user", "admin", "other"],
36
+ default: "user",
37
+ },
38
+ },
39
+ { timestamps: true },
40
+ );
41
+
42
+ const User = mongoose.model("User", userSchema);
43
+ export default User;
@@ -0,0 +1,22 @@
1
+ import express from "express";
2
+ import {
3
+ signup,
4
+ login,
5
+ getMe,
6
+ logout,
7
+ updateMe,
8
+ } from "../controllers/auth.controller.js";
9
+ import { protect } from "../middleware/auth.middleware.js";
10
+ import { apiLimiter } from "../middleware/rateLimiter.js";
11
+
12
+ const router = express.Router();
13
+
14
+ router.use(apiLimiter);
15
+
16
+ router.post("/signup", signup);
17
+ router.post("/login", login);
18
+ router.post("/logout", logout);
19
+ router.get("/me", protect, getMe);
20
+ router.put("/me", protect, updateMe);
21
+
22
+ export default router;
@@ -0,0 +1,10 @@
1
+ import express from "express";
2
+ import authRoutes from "./auth.route.js";
3
+ import uploadRoutes from "./upload.route.js";
4
+
5
+ const router = express.Router();
6
+
7
+ router.use("/auth", authRoutes);
8
+ router.use("/upload", uploadRoutes);
9
+
10
+ export default router;
@@ -0,0 +1,11 @@
1
+ import express from "express";
2
+ import { upload } from "../middleware/multer.js";
3
+ import { uploadFile } from "../controllers/upload.controller.js";
4
+ import { protect } from "../middleware/auth.middleware.js";
5
+ import { uploadLimiter } from "../middleware/rateLimiter.js";
6
+
7
+ const router = express.Router();
8
+
9
+ router.post("/", protect, uploadLimiter, upload.single("file"), uploadFile);
10
+
11
+ export default router;
@@ -0,0 +1,115 @@
1
+ import User from "../models/user.model.js";
2
+ import Otp from "../models/otp.model.js";
3
+ import bcrypt from "bcrypt";
4
+ import { generateToken } from "../utils/jwt.js";
5
+ import { sendOtpEmail } from "../utils/emailOtp.js";
6
+ import { uploadSingleToCloudinary, deleteFromCloudinary } from "../utils/cloudinaryUpload.js";
7
+ import logger from "../utils/logger.js";
8
+
9
+ export const authService = {
10
+ signup: async ({ name, email, phone, password }: any) => {
11
+ const existingUser = await User.findOne({ email });
12
+ if (existingUser) {
13
+ const err: any = new Error("User already exists");
14
+ err.status = 409;
15
+ throw err;
16
+ }
17
+ const salt = await bcrypt.genSalt(10);
18
+ const hashedPassword = await bcrypt.hash(password, salt);
19
+ const photoURL = `https://placehold.co/600x400?text=${name.charAt(0).toUpperCase()}`;
20
+ const newUser = await User.create({
21
+ name,
22
+ email: email.toLowerCase(),
23
+ phone,
24
+ role: "user",
25
+ password: hashedPassword,
26
+ avatar: { url: photoURL, publicId: "" },
27
+ });
28
+ return newUser;
29
+ },
30
+
31
+ login: async ({ email, password }: any) => {
32
+ const user = await User.findOne({ email });
33
+ if (!user) {
34
+ const err: any = new Error("User not found");
35
+ err.status = 404;
36
+ throw err;
37
+ }
38
+ const isValid = await bcrypt.compare(password, user.password);
39
+ if (!isValid) {
40
+ const err: any = new Error("Invalid Credentials");
41
+ err.status = 401;
42
+ throw err;
43
+ }
44
+ return user;
45
+ },
46
+
47
+ generateOtp: async (email: string) => {
48
+ const user = await User.findOne({ email });
49
+ if (!user) {
50
+ const err: any = new Error("User not found");
51
+ err.status = 404;
52
+ throw err;
53
+ }
54
+ const existingOtp = await Otp.findOne({ email });
55
+ if (existingOtp) {
56
+ await existingOtp.deleteOne();
57
+ }
58
+ const otp = Math.floor(100000 + Math.random() * 900000).toString();
59
+ const hashedOtp = await bcrypt.hash(otp, 10);
60
+ await Otp.create({ email, otp: hashedOtp });
61
+ await sendOtpEmail(email, otp);
62
+ return true;
63
+ },
64
+
65
+ verifyOtp: async ({ email, otp }: any) => {
66
+ const user = await User.findOne({ email });
67
+ if (!user) {
68
+ const err: any = new Error("User not found");
69
+ err.status = 404;
70
+ throw err;
71
+ }
72
+ const existingOtp = await Otp.findOne({ email });
73
+ if (!existingOtp) {
74
+ const err: any = new Error("OTP match failed");
75
+ err.status = 400;
76
+ throw err;
77
+ }
78
+ const isMatched = await bcrypt.compare(otp, existingOtp.otp);
79
+ if (!isMatched) {
80
+ const err: any = new Error("OTP match failed");
81
+ err.status = 400;
82
+ throw err;
83
+ }
84
+ return user;
85
+ },
86
+
87
+ resetPassword: async (user: any, newPassword: any) => {
88
+ const hashedPassword = await bcrypt.hash(newPassword, 10);
89
+ user.password = hashedPassword;
90
+ await user.save();
91
+ return true;
92
+ },
93
+
94
+ updateProfile: async (userId: any, { name, phone, file }: any) => {
95
+ const user = await User.findById(userId);
96
+ if (!user) {
97
+ const err: any = new Error("User not found");
98
+ err.status = 404;
99
+ throw err;
100
+ }
101
+ if (name) user.name = name;
102
+ if (phone) user.phone = phone;
103
+ if (file) {
104
+ const uploadResult = await uploadSingleToCloudinary(file, { folder: "codelab/avatars" });
105
+ if (user.avatar && user.avatar.publicId) {
106
+ await deleteFromCloudinary(user.avatar.publicId).catch((err) =>
107
+ logger.error("Old avatar delete error", err)
108
+ );
109
+ }
110
+ user.avatar = { url: uploadResult.url, publicId: uploadResult.publicId };
111
+ }
112
+ await user.save();
113
+ return user;
114
+ },
115
+ };
@@ -0,0 +1,10 @@
1
+ import { Express } from "express";
2
+
3
+ declare global {
4
+ namespace Express {
5
+ interface Request {
6
+ user?: any;
7
+ file?: any;
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,44 @@
1
+ import cloudinary from "../config/cloudinary.js";
2
+ import logger from "./logger.js";
3
+
4
+ const uploadToCloudinary = async (file: any, options: any = {}) => {
5
+ if (!file?.buffer) {
6
+ throw new Error("Invalid file.");
7
+ }
8
+ const dataURI = `data:${file.mimetype};base64,${file.buffer.toString("base64")}`;
9
+ const result = await cloudinary.uploader.upload(dataURI, {
10
+ folder: options.folder || "uploads",
11
+ ...options,
12
+ });
13
+ return {
14
+ url: result.secure_url,
15
+ publicId: result.public_id,
16
+ };
17
+ };
18
+
19
+ export const uploadSingleToCloudinary = async (file: any, options: any = {}) => {
20
+ try {
21
+ return await uploadToCloudinary(file, options);
22
+ } catch (error) {
23
+ logger.error("Cloudinary Upload Error", error);
24
+ throw new Error("Failed to upload image.");
25
+ }
26
+ };
27
+
28
+ export const uploadMultipleToCloudinary = async (files: any[] = [], options: any = {}) => {
29
+ try {
30
+ return await Promise.all(files.map((file) => uploadToCloudinary(file, options)));
31
+ } catch (error) {
32
+ logger.error("Cloudinary Upload Error", error);
33
+ throw new Error("Failed to upload images.");
34
+ }
35
+ };
36
+
37
+ export const deleteFromCloudinary = async (publicId: string) => {
38
+ try {
39
+ return await cloudinary.uploader.destroy(publicId);
40
+ } catch (error) {
41
+ logger.error("Cloudinary Delete Error", error);
42
+ throw new Error("Failed to delete image.");
43
+ }
44
+ };