nextworks 0.0.1 → 0.1.0-alpha.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 (277) hide show
  1. package/README.md +209 -30
  2. package/dist/.gitkeep +0 -0
  3. package/dist/cli_manifests/auth_manifest.json +86 -0
  4. package/dist/cli_manifests/blocks_manifest.json +185 -0
  5. package/dist/cli_manifests/data_manifest.json +51 -0
  6. package/dist/cli_manifests/forms_manifest.json +61 -0
  7. package/dist/commands/admin-posts.d.ts +2 -0
  8. package/dist/commands/admin-posts.d.ts.map +1 -0
  9. package/dist/commands/admin-posts.js +15 -0
  10. package/dist/commands/admin-posts.js.map +1 -0
  11. package/dist/commands/admin-users.d.ts +2 -0
  12. package/dist/commands/admin-users.d.ts.map +1 -0
  13. package/dist/commands/admin-users.js +15 -0
  14. package/dist/commands/admin-users.js.map +1 -0
  15. package/dist/commands/auth-core.d.ts +2 -0
  16. package/dist/commands/auth-core.d.ts.map +1 -0
  17. package/dist/commands/auth-core.js +83 -0
  18. package/dist/commands/auth-core.js.map +1 -0
  19. package/dist/commands/auth-forms.d.ts +2 -0
  20. package/dist/commands/auth-forms.d.ts.map +1 -0
  21. package/dist/commands/auth-forms.js +15 -0
  22. package/dist/commands/auth-forms.js.map +1 -0
  23. package/dist/commands/blocks-options.d.ts +7 -0
  24. package/dist/commands/blocks-options.d.ts.map +1 -0
  25. package/dist/commands/blocks-options.js +19 -0
  26. package/dist/commands/blocks-options.js.map +1 -0
  27. package/dist/commands/blocks.d.ts +7 -0
  28. package/dist/commands/blocks.d.ts.map +1 -0
  29. package/dist/commands/blocks.js +140 -0
  30. package/dist/commands/blocks.js.map +1 -0
  31. package/dist/commands/data.d.ts +3 -0
  32. package/dist/commands/data.d.ts.map +1 -0
  33. package/dist/commands/data.js +88 -0
  34. package/dist/commands/data.js.map +1 -0
  35. package/dist/commands/forms.d.ts +6 -0
  36. package/dist/commands/forms.d.ts.map +1 -0
  37. package/dist/commands/forms.js +107 -0
  38. package/dist/commands/forms.js.map +1 -0
  39. package/dist/commands/remove-auth-core.d.ts +2 -0
  40. package/dist/commands/remove-auth-core.d.ts.map +1 -0
  41. package/dist/commands/remove-auth-core.js +69 -0
  42. package/dist/commands/remove-auth-core.js.map +1 -0
  43. package/dist/commands/remove-blocks.d.ts +2 -0
  44. package/dist/commands/remove-blocks.d.ts.map +1 -0
  45. package/dist/commands/remove-blocks.js +36 -0
  46. package/dist/commands/remove-blocks.js.map +1 -0
  47. package/dist/index.d.ts +3 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +109 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/kits/auth-core/README.md +82 -0
  52. package/dist/kits/auth-core/app/(protected)/dashboard/page.tsx +8 -0
  53. package/dist/kits/auth-core/app/(protected)/layout.tsx +18 -0
  54. package/dist/kits/auth-core/app/(protected)/settings/profile/page.tsx +15 -0
  55. package/dist/kits/auth-core/app/(protected)/settings/profile/profile-form.tsx +114 -0
  56. package/dist/kits/auth-core/app/api/auth/[...nextauth]/route.ts +1 -0
  57. package/dist/kits/auth-core/app/api/auth/forgot-password/route.ts +114 -0
  58. package/dist/kits/auth-core/app/api/auth/providers/route.ts +6 -0
  59. package/dist/kits/auth-core/app/api/auth/reset-password/route.ts +63 -0
  60. package/dist/kits/auth-core/app/api/auth/send-verify-email/route.ts +6 -0
  61. package/dist/kits/auth-core/app/api/signup/route.ts +41 -0
  62. package/dist/kits/auth-core/app/auth/forgot-password/page.tsx +21 -0
  63. package/dist/kits/auth-core/app/auth/login/page.tsx +5 -0
  64. package/dist/kits/auth-core/app/auth/reset-password/page.tsx +187 -0
  65. package/dist/kits/auth-core/app/auth/signup/page.tsx +5 -0
  66. package/dist/kits/auth-core/app/auth/verify-email/page.tsx +11 -0
  67. package/dist/kits/auth-core/components/admin/admin-header.tsx +57 -0
  68. package/dist/kits/auth-core/components/auth/dashboard.tsx +237 -0
  69. package/dist/kits/auth-core/components/auth/forgot-password-form.tsx +90 -0
  70. package/dist/kits/auth-core/components/auth/login-form.tsx +467 -0
  71. package/dist/kits/auth-core/components/auth/logout-button.tsx +50 -0
  72. package/dist/kits/auth-core/components/auth/minimal-logout-button.tsx +40 -0
  73. package/dist/kits/auth-core/components/auth/signup-form.tsx +468 -0
  74. package/dist/kits/auth-core/components/require-auth.tsx +59 -0
  75. package/dist/kits/auth-core/components/session-provider.tsx +11 -0
  76. package/dist/kits/auth-core/components/ui/README.txt +1 -0
  77. package/dist/kits/auth-core/components/ui/button.tsx +55 -0
  78. package/dist/kits/auth-core/components/ui/input.tsx +25 -0
  79. package/dist/kits/auth-core/components/ui/label.tsx +23 -0
  80. package/dist/kits/auth-core/lib/api/errors.ts +14 -0
  81. package/dist/kits/auth-core/lib/auth-helpers.ts +29 -0
  82. package/dist/kits/auth-core/lib/auth.ts +142 -0
  83. package/dist/kits/auth-core/lib/email/dev-transport.ts +42 -0
  84. package/dist/kits/auth-core/lib/email/index.ts +28 -0
  85. package/dist/kits/auth-core/lib/email/provider-smtp.ts +36 -0
  86. package/dist/kits/auth-core/lib/forms/map-errors.ts +11 -0
  87. package/dist/kits/auth-core/lib/hash.ts +6 -0
  88. package/dist/kits/auth-core/lib/prisma.ts +15 -0
  89. package/dist/kits/auth-core/lib/server/result.ts +45 -0
  90. package/dist/kits/auth-core/lib/utils.ts +6 -0
  91. package/dist/kits/auth-core/lib/validation/forms.ts +88 -0
  92. package/dist/kits/auth-core/package-deps.json +19 -0
  93. package/dist/kits/auth-core/prisma/auth-models.prisma +81 -0
  94. package/dist/kits/auth-core/prisma/schema.prisma +81 -0
  95. package/dist/kits/auth-core/scripts/populate-tokenhash.mjs +26 -0
  96. package/dist/kits/auth-core/scripts/promote-admin.mjs +33 -0
  97. package/dist/kits/auth-core/scripts/seed-demo.mjs +40 -0
  98. package/dist/kits/auth-core/types/next-auth.d.ts +25 -0
  99. package/dist/kits/blocks/README.md +53 -0
  100. package/dist/kits/blocks/app/globals.css +175 -0
  101. package/dist/kits/blocks/app/templates/digitalagency/PresetThemeVars.tsx +80 -0
  102. package/dist/kits/blocks/app/templates/digitalagency/README.md +36 -0
  103. package/dist/kits/blocks/app/templates/digitalagency/components/About.tsx +99 -0
  104. package/dist/kits/blocks/app/templates/digitalagency/components/CTA.tsx +74 -0
  105. package/dist/kits/blocks/app/templates/digitalagency/components/Contact.tsx +227 -0
  106. package/dist/kits/blocks/app/templates/digitalagency/components/Footer.tsx +89 -0
  107. package/dist/kits/blocks/app/templates/digitalagency/components/Hero.tsx +90 -0
  108. package/dist/kits/blocks/app/templates/digitalagency/components/Navbar.tsx +168 -0
  109. package/dist/kits/blocks/app/templates/digitalagency/components/NetworkPattern.tsx +297 -0
  110. package/dist/kits/blocks/app/templates/digitalagency/components/Portfolio.tsx +157 -0
  111. package/dist/kits/blocks/app/templates/digitalagency/components/Pricing.tsx +114 -0
  112. package/dist/kits/blocks/app/templates/digitalagency/components/Process.tsx +59 -0
  113. package/dist/kits/blocks/app/templates/digitalagency/components/Services.tsx +55 -0
  114. package/dist/kits/blocks/app/templates/digitalagency/components/Team.tsx +28 -0
  115. package/dist/kits/blocks/app/templates/digitalagency/components/Testimonials.tsx +65 -0
  116. package/dist/kits/blocks/app/templates/digitalagency/page.tsx +38 -0
  117. package/dist/kits/blocks/app/templates/gallery/PresetThemeVars.tsx +85 -0
  118. package/dist/kits/blocks/app/templates/gallery/page.tsx +303 -0
  119. package/dist/kits/blocks/app/templates/productlaunch/PresetThemeVars.tsx +74 -0
  120. package/dist/kits/blocks/app/templates/productlaunch/README.md +55 -0
  121. package/dist/kits/blocks/app/templates/productlaunch/components/About.tsx +178 -0
  122. package/dist/kits/blocks/app/templates/productlaunch/components/CTA.tsx +93 -0
  123. package/dist/kits/blocks/app/templates/productlaunch/components/Contact.tsx +231 -0
  124. package/dist/kits/blocks/app/templates/productlaunch/components/FAQ.tsx +93 -0
  125. package/dist/kits/blocks/app/templates/productlaunch/components/Features.tsx +84 -0
  126. package/dist/kits/blocks/app/templates/productlaunch/components/Footer.tsx +132 -0
  127. package/dist/kits/blocks/app/templates/productlaunch/components/Hero.tsx +89 -0
  128. package/dist/kits/blocks/app/templates/productlaunch/components/Navbar.tsx +162 -0
  129. package/dist/kits/blocks/app/templates/productlaunch/components/Pricing.tsx +106 -0
  130. package/dist/kits/blocks/app/templates/productlaunch/components/ProcessTimeline.tsx +110 -0
  131. package/dist/kits/blocks/app/templates/productlaunch/components/ServicesGrid.tsx +68 -0
  132. package/dist/kits/blocks/app/templates/productlaunch/components/Team.tsx +104 -0
  133. package/dist/kits/blocks/app/templates/productlaunch/components/Testimonials.tsx +89 -0
  134. package/dist/kits/blocks/app/templates/productlaunch/components/TrustBadges.tsx +76 -0
  135. package/dist/kits/blocks/app/templates/productlaunch/page.tsx +45 -0
  136. package/dist/kits/blocks/app/templates/saasdashboard/PresetThemeVars.tsx +80 -0
  137. package/dist/kits/blocks/app/templates/saasdashboard/README.md +38 -0
  138. package/dist/kits/blocks/app/templates/saasdashboard/components/Contact.tsx +176 -0
  139. package/dist/kits/blocks/app/templates/saasdashboard/components/Dashboard.tsx +293 -0
  140. package/dist/kits/blocks/app/templates/saasdashboard/components/FAQ.tsx +55 -0
  141. package/dist/kits/blocks/app/templates/saasdashboard/components/Features.tsx +91 -0
  142. package/dist/kits/blocks/app/templates/saasdashboard/components/Footer.tsx +77 -0
  143. package/dist/kits/blocks/app/templates/saasdashboard/components/Hero.tsx +105 -0
  144. package/dist/kits/blocks/app/templates/saasdashboard/components/Hero_mask.tsx +127 -0
  145. package/dist/kits/blocks/app/templates/saasdashboard/components/Navbar.tsx +159 -0
  146. package/dist/kits/blocks/app/templates/saasdashboard/components/Pricing.tsx +90 -0
  147. package/dist/kits/blocks/app/templates/saasdashboard/components/SmoothScroll.tsx +97 -0
  148. package/dist/kits/blocks/app/templates/saasdashboard/components/Testimonials.tsx +72 -0
  149. package/dist/kits/blocks/app/templates/saasdashboard/components/TrustBadges.tsx +53 -0
  150. package/dist/kits/blocks/app/templates/saasdashboard/page.tsx +39 -0
  151. package/dist/kits/blocks/components/app-providers.tsx +1 -0
  152. package/dist/kits/blocks/components/enhanced-theme-provider.tsx +195 -0
  153. package/dist/kits/blocks/components/sections/About.tsx +291 -0
  154. package/dist/kits/blocks/components/sections/CTA.tsx +258 -0
  155. package/dist/kits/blocks/components/sections/Contact.tsx +267 -0
  156. package/dist/kits/blocks/components/sections/FAQ.tsx +226 -0
  157. package/dist/kits/blocks/components/sections/Features.tsx +269 -0
  158. package/dist/kits/blocks/components/sections/Footer.tsx +302 -0
  159. package/dist/kits/blocks/components/sections/HeroMotion.tsx +307 -0
  160. package/dist/kits/blocks/components/sections/HeroOverlay.tsx +358 -0
  161. package/dist/kits/blocks/components/sections/HeroSplit.tsx +352 -0
  162. package/dist/kits/blocks/components/sections/Navbar.tsx +353 -0
  163. package/dist/kits/blocks/components/sections/Newsletter.tsx +156 -0
  164. package/dist/kits/blocks/components/sections/PortfolioSimple.tsx +550 -0
  165. package/dist/kits/blocks/components/sections/Pricing.tsx +264 -0
  166. package/dist/kits/blocks/components/sections/ProcessTimeline.tsx +325 -0
  167. package/dist/kits/blocks/components/sections/ServicesGrid.tsx +210 -0
  168. package/dist/kits/blocks/components/sections/Team.tsx +309 -0
  169. package/dist/kits/blocks/components/sections/Testimonials.tsx +158 -0
  170. package/dist/kits/blocks/components/sections/TrustBadges.tsx +162 -0
  171. package/dist/kits/blocks/components/theme-provider.tsx +34 -0
  172. package/dist/kits/blocks/components/ui/alert-dialog.tsx +134 -0
  173. package/dist/kits/blocks/components/ui/brand-node.tsx +121 -0
  174. package/dist/kits/blocks/components/ui/button.tsx +122 -0
  175. package/dist/kits/blocks/components/ui/button_bck.tsx +93 -0
  176. package/dist/kits/blocks/components/ui/card.tsx +95 -0
  177. package/dist/kits/blocks/components/ui/checkbox.tsx +30 -0
  178. package/dist/kits/blocks/components/ui/cta-button.tsx +125 -0
  179. package/dist/kits/blocks/components/ui/dropdown-menu.tsx +201 -0
  180. package/dist/kits/blocks/components/ui/feature-card.tsx +91 -0
  181. package/dist/kits/blocks/components/ui/input.tsx +27 -0
  182. package/dist/kits/blocks/components/ui/label.tsx +29 -0
  183. package/dist/kits/blocks/components/ui/pricing-card.tsx +120 -0
  184. package/dist/kits/blocks/components/ui/select.tsx +25 -0
  185. package/dist/kits/blocks/components/ui/skeleton.tsx +13 -0
  186. package/dist/kits/blocks/components/ui/switch.tsx +78 -0
  187. package/dist/kits/blocks/components/ui/table.tsx +98 -0
  188. package/dist/kits/blocks/components/ui/testimonial-card.tsx +108 -0
  189. package/dist/kits/blocks/components/ui/textarea.tsx +26 -0
  190. package/dist/kits/blocks/components/ui/theme-selector.tsx +247 -0
  191. package/dist/kits/blocks/components/ui/theme-toggle.tsx +74 -0
  192. package/dist/kits/blocks/components/ui/toaster.tsx +7 -0
  193. package/dist/kits/blocks/lib/themes.ts +399 -0
  194. package/dist/kits/blocks/lib/themes_old.ts +37 -0
  195. package/dist/kits/blocks/lib/utils.ts +9 -0
  196. package/dist/kits/blocks/next.config.ts +11 -0
  197. package/dist/kits/blocks/notes/THEME_GUIDE.md +29 -0
  198. package/dist/kits/blocks/notes/THEMING_CONVERSION_SUMMARY.md +14 -0
  199. package/dist/kits/blocks/package-deps.json +22 -0
  200. package/dist/kits/blocks/public/placeholders/gallery/hero-pexels-broken-9945014.avif +0 -0
  201. package/dist/kits/blocks/public/placeholders/gallery/pexels-googledeepmind-25626431.jpg +0 -0
  202. package/dist/kits/blocks/public/placeholders/gallery/pexels-googledeepmind-25626432.jpg +0 -0
  203. package/dist/kits/blocks/public/placeholders/gallery/pexels-googledeepmind-25626434.jpg +0 -0
  204. package/dist/kits/blocks/public/placeholders/gallery/pexels-googledeepmind-25626436.jpg +0 -0
  205. package/dist/kits/blocks/public/placeholders/product_launch/feature_1.png +0 -0
  206. package/dist/kits/blocks/public/placeholders/product_launch/feature_2.png +0 -0
  207. package/dist/kits/blocks/public/placeholders/product_launch/feature_3.png +0 -0
  208. package/dist/kits/blocks/public/placeholders/product_launch/feature_4.png +0 -0
  209. package/dist/kits/blocks/public/placeholders/product_launch/hero.png +0 -0
  210. package/dist/kits/blocks/public/placeholders/saas_dashboard/analytics.png +0 -0
  211. package/dist/kits/blocks/public/placeholders/saas_dashboard/chat.png +0 -0
  212. package/dist/kits/blocks/public/placeholders/saas_dashboard/projectBoard.png +0 -0
  213. package/dist/kits/data/.gitkeep +0 -0
  214. package/dist/kits/data/README.md +80 -0
  215. package/dist/kits/data/app/(protected)/admin/posts/page.tsx +5 -0
  216. package/dist/kits/data/app/(protected)/admin/users/page.tsx +5 -0
  217. package/dist/kits/data/app/api/posts/[id]/route.ts +83 -0
  218. package/dist/kits/data/app/api/posts/route.ts +138 -0
  219. package/dist/kits/data/app/api/seed-demo/route.ts +45 -0
  220. package/dist/kits/data/app/api/users/[id]/route.ts +127 -0
  221. package/dist/kits/data/app/api/users/check-email/route.ts +18 -0
  222. package/dist/kits/data/app/api/users/check-unique/route.ts +27 -0
  223. package/dist/kits/data/app/api/users/route.ts +79 -0
  224. package/dist/kits/data/app/examples/demo/README.md +4 -0
  225. package/dist/kits/data/app/examples/demo/create-post-form.tsx +106 -0
  226. package/dist/kits/data/app/examples/demo/page.tsx +118 -0
  227. package/dist/kits/data/app/examples/demo/seed-demo-button.tsx +37 -0
  228. package/dist/kits/data/components/admin/posts-manager.tsx +719 -0
  229. package/dist/kits/data/components/admin/users-manager.tsx +432 -0
  230. package/dist/kits/data/lib/prisma.ts +15 -0
  231. package/dist/kits/data/lib/server/result.ts +90 -0
  232. package/dist/kits/data/package-deps.json +11 -0
  233. package/dist/kits/data/scripts/seed-demo.mjs +41 -0
  234. package/dist/kits/forms/.gitkeep +0 -0
  235. package/dist/kits/forms/README.md +49 -0
  236. package/dist/kits/forms/app/.gitkeep +0 -0
  237. package/dist/kits/forms/app/api/wizard/route.ts +71 -0
  238. package/dist/kits/forms/app/examples/forms/basic/page.tsx +124 -0
  239. package/dist/kits/forms/app/examples/forms/server-action/form-client.tsx +28 -0
  240. package/dist/kits/forms/app/examples/forms/server-action/page.tsx +71 -0
  241. package/dist/kits/forms/app/examples/forms/wizard/page.tsx +15 -0
  242. package/dist/kits/forms/app/examples/forms/wizard/wizard-client.tsx +2 -0
  243. package/dist/kits/forms/components/.gitkeep +0 -0
  244. package/dist/kits/forms/components/examples/wizard-client.tsx +231 -0
  245. package/dist/kits/forms/components/hooks/useCheckUnique.ts +79 -0
  246. package/dist/kits/forms/components/ui/button.tsx +122 -0
  247. package/dist/kits/forms/components/ui/checkbox.tsx +30 -0
  248. package/dist/kits/forms/components/ui/form/context.ts +33 -0
  249. package/dist/kits/forms/components/ui/form/form-control.tsx +28 -0
  250. package/dist/kits/forms/components/ui/form/form-description.tsx +22 -0
  251. package/dist/kits/forms/components/ui/form/form-field.tsx +36 -0
  252. package/dist/kits/forms/components/ui/form/form-item.tsx +21 -0
  253. package/dist/kits/forms/components/ui/form/form-label.tsx +24 -0
  254. package/dist/kits/forms/components/ui/form/form-message.tsx +29 -0
  255. package/dist/kits/forms/components/ui/form/form.tsx +26 -0
  256. package/dist/kits/forms/components/ui/input.tsx +27 -0
  257. package/dist/kits/forms/components/ui/label.tsx +29 -0
  258. package/dist/kits/forms/components/ui/select.tsx +25 -0
  259. package/dist/kits/forms/components/ui/switch.tsx +78 -0
  260. package/dist/kits/forms/components/ui/textarea.tsx +26 -0
  261. package/dist/kits/forms/lib/.gitkeep +0 -0
  262. package/dist/kits/forms/lib/forms/map-errors.ts +29 -0
  263. package/dist/kits/forms/lib/prisma.ts +16 -0
  264. package/dist/kits/forms/lib/utils.ts +9 -0
  265. package/dist/kits/forms/lib/validation/forms.ts +88 -0
  266. package/dist/kits/forms/lib/validation/wizard.ts +32 -0
  267. package/dist/kits/forms/package-deps.json +17 -0
  268. package/dist/utils/file-operations.d.ts +18 -0
  269. package/dist/utils/file-operations.d.ts.map +1 -0
  270. package/dist/utils/file-operations.js +327 -0
  271. package/dist/utils/file-operations.js.map +1 -0
  272. package/dist/utils/installation-tracker.d.ts +26 -0
  273. package/dist/utils/installation-tracker.d.ts.map +1 -0
  274. package/dist/utils/installation-tracker.js +98 -0
  275. package/dist/utils/installation-tracker.js.map +1 -0
  276. package/package.json +51 -21
  277. package/index.js +0 -1
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.removeAuthCore = removeAuthCore;
4
+ const file_operations_1 = require("../utils/file-operations");
5
+ const installation_tracker_1 = require("../utils/installation-tracker");
6
+ async function removeAuthCore() {
7
+ console.log("Removing auth-core kit...");
8
+ try {
9
+ // Files to remove (same as what was installed)
10
+ const files = [
11
+ "lib/auth.ts",
12
+ "app/api/auth/[...nextauth]/route.ts",
13
+ "types/next-auth.d.ts",
14
+ "components/session-provider.tsx",
15
+ "lib/prisma.ts",
16
+ "prisma/auth-models.prisma",
17
+ // lib/validation/forms.ts is provided by the Forms kit; do not remove here
18
+ "lib/utils.ts",
19
+ "components/auth/login-form.tsx",
20
+ "components/auth/signup-form.tsx",
21
+ "components/auth/signup-form.tsx",
22
+ "components/require-auth.tsx",
23
+ "components/ui/button.tsx",
24
+ "components/ui/input.tsx",
25
+ "components/ui/label.tsx",
26
+ "app/auth/login/page.tsx",
27
+ "app/auth/signup/page.tsx",
28
+ "app/api/signup/route.ts",
29
+ "app/(protected)/layout.tsx",
30
+ "app/(protected)/dashboard/page.tsx",
31
+ ];
32
+ // Get safe-to-remove dependencies (not shared with other kits)
33
+ const safeToRemove = await (0, installation_tracker_1.getSafeToRemoveDependencies)("auth-core");
34
+ // Remove files
35
+ await (0, file_operations_1.removeFiles)(files);
36
+ // Remove empty folders (only if they're empty)
37
+ await (0, file_operations_1.removeEmptyFolders)(files);
38
+ // Remove only safe dependencies (not shared with other kits)
39
+ if (safeToRemove.dependencies.length > 0 ||
40
+ safeToRemove.devDependencies.length > 0) {
41
+ await (0, file_operations_1.removePackageDepsSmart)(safeToRemove.dependencies, safeToRemove.devDependencies);
42
+ }
43
+ else {
44
+ console.log("ℹ️ No dependencies to remove (shared with other kits)");
45
+ }
46
+ // Revert layout.tsx changes
47
+ await (0, file_operations_1.revertLayoutFile)();
48
+ // Remove from installation tracker
49
+ await (0, installation_tracker_1.removeInstalledKit)("auth-core");
50
+ console.log("✓ auth-core kit removed successfully!");
51
+ console.log("\n📋 Cleanup completed:");
52
+ console.log("• Removed all auth-core files");
53
+ console.log("• Removed empty folders (if any)");
54
+ if (safeToRemove.dependencies.length > 0 ||
55
+ safeToRemove.devDependencies.length > 0) {
56
+ console.log("• Removed unshared dependencies from package.json");
57
+ }
58
+ else {
59
+ console.log("• Kept shared dependencies in package.json");
60
+ }
61
+ console.log("• Reverted app/layout.tsx changes");
62
+ console.log("\n💡 You may want to run 'npm install' to clean up node_modules");
63
+ }
64
+ catch (error) {
65
+ console.log("❌ Failed to remove auth-core kit");
66
+ throw error;
67
+ }
68
+ }
69
+ //# sourceMappingURL=remove-auth-core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-auth-core.js","sourceRoot":"","sources":["../../src/commands/remove-auth-core.ts"],"names":[],"mappings":";;AAWA,wCA6EC;AAxFD,8DAKkC;AAClC,wEAGuC;AAEhC,KAAK,UAAU,cAAc;IAClC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IAEzC,IAAI,CAAC;QACH,+CAA+C;QAC/C,MAAM,KAAK,GAAG;YACZ,aAAa;YACb,qCAAqC;YACrC,sBAAsB;YACtB,iCAAiC;YACjC,eAAe;YACf,2BAA2B;YAC3B,2EAA2E;YAC3E,cAAc;YACd,gCAAgC;YAChC,iCAAiC;YACjC,iCAAiC;YACjC,6BAA6B;YAC7B,0BAA0B;YAC1B,yBAAyB;YACzB,yBAAyB;YACzB,yBAAyB;YACzB,0BAA0B;YAC1B,yBAAyB;YACzB,4BAA4B;YAC5B,oCAAoC;SACrC,CAAC;QAEF,+DAA+D;QAC/D,MAAM,YAAY,GAAG,MAAM,IAAA,kDAA2B,EAAC,WAAW,CAAC,CAAC;QAEpE,eAAe;QACf,MAAM,IAAA,6BAAW,EAAC,KAAK,CAAC,CAAC;QAEzB,+CAA+C;QAC/C,MAAM,IAAA,oCAAkB,EAAC,KAAK,CAAC,CAAC;QAEhC,6DAA6D;QAC7D,IACE,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;YACpC,YAAY,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EACvC,CAAC;YACD,MAAM,IAAA,wCAAsB,EAC1B,YAAY,CAAC,YAAY,EACzB,YAAY,CAAC,eAAe,CAC7B,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;QACxE,CAAC;QAED,4BAA4B;QAC5B,MAAM,IAAA,kCAAgB,GAAE,CAAC;QAEzB,mCAAmC;QACnC,MAAM,IAAA,yCAAkB,EAAC,WAAW,CAAC,CAAC;QAEtC,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;QAErD,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QAChD,IACE,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;YACpC,YAAY,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EACvC,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACnE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CACT,iEAAiE,CAClE,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QAChD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function removeBlocks(): Promise<void>;
2
+ //# sourceMappingURL=remove-blocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-blocks.d.ts","sourceRoot":"","sources":["../../src/commands/remove-blocks.ts"],"names":[],"mappings":"AAaA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CA4ClD"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.removeBlocks = removeBlocks;
4
+ const file_operations_1 = require("../utils/file-operations");
5
+ const installation_tracker_1 = require("../utils/installation-tracker");
6
+ async function removeBlocks() {
7
+ console.log("Removing blocks kit...");
8
+ try {
9
+ const manifestPath = (0, file_operations_1.resolveAssetPath)("cli_manifests", "blocks_manifest.json");
10
+ const manifest = await (0, file_operations_1.readJsonFile)(manifestPath);
11
+ const files = manifest.files || [];
12
+ // Get safe-to-remove dependencies (not shared with other kits)
13
+ const safeToRemove = await (0, installation_tracker_1.getSafeToRemoveDependencies)("blocks");
14
+ // Remove files
15
+ await (0, file_operations_1.removeFiles)(files);
16
+ // Remove empty folders
17
+ await (0, file_operations_1.removeEmptyFolders)(files);
18
+ // Remove only safe dependencies
19
+ if (safeToRemove.dependencies.length > 0 ||
20
+ safeToRemove.devDependencies.length > 0) {
21
+ await (0, file_operations_1.removePackageDepsSmart)(safeToRemove.dependencies, safeToRemove.devDependencies);
22
+ }
23
+ else {
24
+ console.log("ℹ️ No dependencies to remove (shared with other kits)");
25
+ }
26
+ // Remove from installation tracker
27
+ await (0, installation_tracker_1.removeInstalledKit)("blocks");
28
+ console.log("✓ blocks kit removed successfully!");
29
+ console.log("\n💡 You may want to run 'npm install' to clean up node_modules");
30
+ }
31
+ catch (error) {
32
+ console.log("❌ Failed to remove blocks kit");
33
+ throw error;
34
+ }
35
+ }
36
+ //# sourceMappingURL=remove-blocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-blocks.js","sourceRoot":"","sources":["../../src/commands/remove-blocks.ts"],"names":[],"mappings":";;AAaA,oCA4CC;AAzDD,8DAMkC;AAClC,wEAGuC;AAGhC,KAAK,UAAU,YAAY;IAChC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IAEtC,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,IAAA,kCAAgB,EACnC,eAAe,EACf,sBAAsB,CACvB,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,IAAA,8BAAY,EAAC,YAAY,CAAC,CAAC;QAClD,MAAM,KAAK,GAAa,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;QAE7C,+DAA+D;QAC/D,MAAM,YAAY,GAAG,MAAM,IAAA,kDAA2B,EAAC,QAAQ,CAAC,CAAC;QAEjE,eAAe;QACf,MAAM,IAAA,6BAAW,EAAC,KAAK,CAAC,CAAC;QAEzB,uBAAuB;QACvB,MAAM,IAAA,oCAAkB,EAAC,KAAK,CAAC,CAAC;QAEhC,gCAAgC;QAChC,IACE,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;YACpC,YAAY,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EACvC,CAAC;YACD,MAAM,IAAA,wCAAsB,EAC1B,YAAY,CAAC,YAAY,EACzB,YAAY,CAAC,eAAe,CAC7B,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;QACxE,CAAC;QAED,mCAAmC;QACnC,MAAM,IAAA,yCAAkB,EAAC,QAAQ,CAAC,CAAC;QAEnC,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CACT,iEAAiE,CAClE,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC7C,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ // Copyright (c) 2025 Jakob Bro Liebe Hansen
4
+ // SPDX-License-Identifier: MIT
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ const commander_1 = require("commander");
10
+ const auth_core_1 = require("./commands/auth-core");
11
+ const blocks_1 = require("./commands/blocks");
12
+ const forms_1 = __importDefault(require("./commands/forms"));
13
+ // NOTE: auth-forms, admin-users, and admin-posts are planned but not yet implemented as real kits.
14
+ // We temporarily remove them from the public CLI surface to avoid advertising non-existent kits.
15
+ const data_1 = __importDefault(require("./commands/data"));
16
+ const remove_auth_core_1 = require("./commands/remove-auth-core");
17
+ const remove_blocks_1 = require("./commands/remove-blocks");
18
+ const installation_tracker_1 = require("./utils/installation-tracker");
19
+ const program = new commander_1.Command();
20
+ program
21
+ .name("nextworks")
22
+ .description("Nextworks CLI - Feature kits installer for Next.js apps")
23
+ .version("0.1.0");
24
+ program
25
+ .command("add <kit>")
26
+ .description("Add a feature kit to your project")
27
+ .option("--sections", "Include standalone sections (Hero, CTA, Pricing, etc.)")
28
+ .option("--templates", "Include full page templates (Product Launch, SaaS Dashboard, Digital Agency, Gallery)")
29
+ .option("--gallery", "Include gallery/demo template and assets")
30
+ .action(async (kit, options) => {
31
+ try {
32
+ switch (kit) {
33
+ case "auth-core":
34
+ await (0, auth_core_1.addAuthCore)();
35
+ break;
36
+ case "forms":
37
+ await (0, forms_1.default)();
38
+ break;
39
+ case "data":
40
+ await (0, data_1.default)();
41
+ break;
42
+ case "blocks":
43
+ await (0, blocks_1.addBlocks)({
44
+ sections: options.sections,
45
+ templates: options.templates,
46
+ gallery: options.gallery,
47
+ });
48
+ break;
49
+ default:
50
+ console.log(`❌ Unknown kit: ${kit}`);
51
+ console.log("Available kits:");
52
+ console.log(" • auth-core - NextAuth + Prisma + session wrapper");
53
+ console.log(" • forms - Form primitives, validation, and examples");
54
+ console.log(" • data - Posts + Users CRUD, API routes, admin panels (depends on auth + forms)");
55
+ console.log(" • blocks - Frontend UI sections & templates (Blocks kit)");
56
+ process.exit(1);
57
+ }
58
+ }
59
+ catch (error) {
60
+ console.error("❌ Error:", error);
61
+ process.exit(1);
62
+ }
63
+ });
64
+ program
65
+ .command("remove <kit>")
66
+ .description("Remove a feature kit from your project")
67
+ .action(async (kit) => {
68
+ try {
69
+ switch (kit) {
70
+ case "auth-core":
71
+ await (0, remove_auth_core_1.removeAuthCore)();
72
+ break;
73
+ case "blocks":
74
+ await (0, remove_blocks_1.removeBlocks)();
75
+ break;
76
+ default:
77
+ console.log(`❌ Unknown kit: ${kit}`);
78
+ console.log("Available kits to remove:");
79
+ console.log(" • auth-core - NextAuth + Prisma + session wrapper");
80
+ process.exit(1);
81
+ }
82
+ }
83
+ catch (error) {
84
+ console.error("❌ Error:", error);
85
+ process.exit(1);
86
+ }
87
+ });
88
+ program
89
+ .command("list")
90
+ .description("List installed kits")
91
+ .action(async () => {
92
+ try {
93
+ const installedKits = await (0, installation_tracker_1.getInstalledKits)();
94
+ if (installedKits.length === 0) {
95
+ console.log("No kits installed.");
96
+ return;
97
+ }
98
+ console.log("Installed kits:");
99
+ installedKits.forEach((kit) => {
100
+ console.log(` • ${kit}`);
101
+ });
102
+ }
103
+ catch (error) {
104
+ console.error("❌ Error:", error);
105
+ process.exit(1);
106
+ }
107
+ });
108
+ program.parse();
109
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ Auth core kit (cli/kits/auth-core)
2
+
3
+ This folder contains the files that the `nextworks` CLI copies into a target Next.js project when you run:
4
+
5
+ ```bash
6
+ npx nextworks add auth-core
7
+ ```
8
+
9
+ What the kit includes
10
+
11
+ - NextAuth configuration and handler: lib/auth.ts
12
+ - Prisma client helper: lib/prisma.ts
13
+ - Validation schemas: lib/validation/forms.ts
14
+ - ApiResult helpers: lib/server/result.ts
15
+ - Email helpers for dev and SMTP: lib/email/\*
16
+ - Signup API: app/api/signup/route.ts
17
+ - NextAuth API: app/api/auth/[...nextauth]/route.ts
18
+ - Login/Signup UI components: components/auth/\*
19
+ - SessionProvider and RequireAuth utilities
20
+ - Prisma snippet: prisma/auth-models.prisma
21
+
22
+ Environment variables
23
+
24
+ The kit relies on the following environment variables. Document these in post-install output or in your project's README:
25
+
26
+ Required (for core auth):
27
+
28
+ - DATABASE_URL
29
+ - NEXTAUTH_URL (e.g. http://localhost:3000)
30
+ - NEXTAUTH_SECRET
31
+
32
+ Optional / password reset & email:
33
+
34
+ - NEXTWORKS_ENABLE_PASSWORD_RESET=1 (enable password reset scaffold)
35
+ - NEXTWORKS_USE_DEV_EMAIL=1 (enable Ethereal dev email transport)
36
+ - SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, NOREPLY_EMAIL (when using real SMTP provider)
37
+ - GITHUB_ID, GITHUB_SECRET (optional) — the GitHub provider is enabled only when both are present
38
+ - NODE_ENV
39
+
40
+ Post-install steps (recommended)
41
+
42
+ 1. Install dependencies copied by the kit (the CLI will merge `package-deps.json` into your `package.json`). Ensure `nodemailer` is installed if you will enable dev email:
43
+
44
+ ```bash
45
+ npm install
46
+ ```
47
+
48
+ 2. Copy or merge `prisma/auth-models.prisma` into your Prisma schema (`prisma/schema.prisma`) and run:
49
+
50
+ ```bash
51
+ npx prisma generate
52
+ npx prisma migrate dev -n init
53
+ ```
54
+
55
+ 3. (Optional) Seed demo data for testing:
56
+
57
+ ```bash
58
+ SEED_ADMIN_EMAIL=admin@example.com SEED_ADMIN_PASSWORD=password123 node ./scripts/seed-demo.mjs
59
+ ```
60
+
61
+ 4. Start your dev server:
62
+
63
+ ```bash
64
+ npm run dev
65
+ ```
66
+
67
+ 5. Verify the basic flows:
68
+
69
+ - Signup: /auth/signup
70
+ - Login: /auth/login
71
+ - Protected dashboard: /dashboard (requires sign in)
72
+ - If enabled, forgot password POST to /api/auth/forgot-password and reset flows at /api/auth/reset-password
73
+
74
+ Notes & security
75
+
76
+ - Password reset is intentionally opt-in. Do not enable NEXTWORKS_ENABLE_PASSWORD_RESET in production unless you have configured a real mail provider and replaced the in-memory rate limiter.
77
+ - NEXTWORKS_USE_DEV_EMAIL=1 uses Ethereal (nodemailer) and prints a preview URL to server logs for development testing.
78
+ - Email verification on signup is **not yet implemented**. Stub endpoints and UI are in place at `/api/auth/send-verify-email` and `/auth/verify-email`. The Prisma `VerificationToken` model is already included so a future implementation can be added as a non-breaking enhancement.
79
+
80
+ CLI behavior (for maintainers)
81
+
82
+ - In the Nextworks repo, the CLI copies the files listed in `cli/cli_manifests/auth_manifest.json`. Keep that manifest and this kit folder in sync when editing the repo.
@@ -0,0 +1,8 @@
1
+ import { requireAuth } from "@/lib/auth-helpers";
2
+ import Dashboard from "@/components/auth/dashboard";
3
+
4
+ export default async function DashboardPage() {
5
+ const session = await requireAuth("/dashboard");
6
+
7
+ return <Dashboard session={session} />;
8
+ }
@@ -0,0 +1,18 @@
1
+ import RequireAuth from "@/components/require-auth";
2
+
3
+ /**
4
+ * ProtectedLayout wraps all routes under /app/(protected).
5
+ * We delegate the optional admin header to RequireAuth via a prop, keeping
6
+ * the control in shared components instead of env flags.
7
+ */
8
+ export default async function ProtectedLayout({
9
+ children,
10
+ }: {
11
+ children: React.ReactNode;
12
+ }) {
13
+ return (
14
+ <RequireAuth showAdminHeader>
15
+ <div className="mx-auto max-w-6xl px-4">{children}</div>
16
+ </RequireAuth>
17
+ );
18
+ }
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+ import ProfileForm from "./profile-form";
3
+
4
+ export default function ProfilePage() {
5
+ return (
6
+ <div className="mx-auto max-w-3xl p-6">
7
+ <h1 className="mb-4 text-2xl font-bold">Profile Settings</h1>
8
+ <p className="text-muted-foreground mb-4 text-sm">
9
+ Update your name and email. Changes are persisted via the
10
+ /api/users/[id] API.
11
+ </p>
12
+ <ProfileForm />
13
+ </div>
14
+ );
15
+ }
@@ -0,0 +1,114 @@
1
+ "use client";
2
+
3
+ import React, { useEffect, useState } from "react";
4
+ import { useForm } from "react-hook-form";
5
+ import { zodResolver } from "@hookform/resolvers/zod";
6
+ import { userSchema } from "@/lib/validation/forms";
7
+ import { Form } from "@/components/ui/form/form";
8
+ import { FormField } from "@/components/ui/form/form-field";
9
+ import { FormItem } from "@/components/ui/form/form-item";
10
+ import { FormLabel } from "@/components/ui/form/form-label";
11
+ import { FormControl } from "@/components/ui/form/form-control";
12
+ import { FormMessage } from "@/components/ui/form/form-message";
13
+ import { Input } from "@/components/ui/input";
14
+ import { Button } from "@/components/ui/button";
15
+ import { useSession } from "next-auth/react";
16
+ import { mapApiErrorsToForm } from "@/lib/forms/map-errors";
17
+ import { toast } from "sonner";
18
+
19
+ export default function ProfileForm() {
20
+ const { data: session, update } = useSession();
21
+
22
+ const methods = useForm({
23
+ resolver: zodResolver(userSchema),
24
+ defaultValues: { name: "", email: "" },
25
+ });
26
+ const { control, handleSubmit, reset } = methods;
27
+ const [isSaving, setIsSaving] = useState(false);
28
+
29
+ useEffect(() => {
30
+ if (session?.user) {
31
+ reset({ name: session.user.name ?? "", email: session.user.email ?? "" });
32
+ }
33
+ }, [session, reset]);
34
+
35
+ const onSubmit = async (values: any) => {
36
+ if (!session?.user?.id) {
37
+ toast.error("You must be signed in to update your profile");
38
+ return;
39
+ }
40
+
41
+ setIsSaving(true);
42
+ try {
43
+ const res = await fetch(`/api/users/${session.user.id}`, {
44
+ method: "PUT",
45
+ headers: { "Content-Type": "application/json" },
46
+ body: JSON.stringify(values),
47
+ });
48
+
49
+ const payload = await res.json();
50
+
51
+ const globalMessage = mapApiErrorsToForm(methods, payload);
52
+
53
+ if (payload?.success) {
54
+ toast.success(payload.message ?? "Profile updated");
55
+ // update local form values to reflect saved state
56
+ reset(values);
57
+ // Patch the NextAuth session so UI reflects the change immediately
58
+ await update({ name: values.name, email: values.email });
59
+ } else {
60
+ if (globalMessage) {
61
+ toast.error(globalMessage);
62
+ } else {
63
+ toast.error(payload?.message ?? "Failed to update profile");
64
+ }
65
+ }
66
+ } catch (e) {
67
+ console.error("Failed to update profile", e);
68
+ toast.error("Network error while updating profile");
69
+ } finally {
70
+ setIsSaving(false);
71
+ }
72
+ };
73
+
74
+ return (
75
+ <div className="bg-card rounded-md p-6">
76
+ <h2 className="mb-3 text-lg font-semibold">Profile settings</h2>
77
+ <Form methods={methods}>
78
+ <form onSubmit={handleSubmit(onSubmit)} className="space-y-3">
79
+ <FormField
80
+ control={control}
81
+ name="name"
82
+ render={({ field }) => (
83
+ <FormItem>
84
+ <FormLabel>Name</FormLabel>
85
+ <FormControl>
86
+ <Input {...field} />
87
+ </FormControl>
88
+ <FormMessage />
89
+ </FormItem>
90
+ )}
91
+ />
92
+
93
+ <FormField
94
+ control={control}
95
+ name="email"
96
+ render={({ field }) => (
97
+ <FormItem>
98
+ <FormLabel>Email</FormLabel>
99
+ <FormControl>
100
+ <Input {...field} />
101
+ </FormControl>
102
+ <FormMessage />
103
+ </FormItem>
104
+ )}
105
+ />
106
+
107
+ <Button type="submit" disabled={isSaving}>
108
+ {isSaving ? "Saving..." : "Save"}
109
+ </Button>
110
+ </form>
111
+ </Form>
112
+ </div>
113
+ );
114
+ }
@@ -0,0 +1 @@
1
+ export { GET, POST } from "@/lib/auth";
@@ -0,0 +1,114 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { Prisma } from "@prisma/client";
4
+ import { prisma } from "@/lib/prisma";
5
+ import { forgotPasswordSchema } from "@/lib/validation/forms";
6
+ import { randomBytes, createHash } from "crypto";
7
+ import { sendDevEmail } from "@/lib/email/dev-transport";
8
+ import { sendEmail, isEmailProviderConfigured } from "@/lib/email";
9
+
10
+ const RATE_LIMIT_WINDOW_MS = 60 * 60 * 1000; // 1 hour
11
+ const MAX_PER_WINDOW = 5;
12
+ const ipMap = new Map<string, number[]>();
13
+
14
+ function rateLimit(ip: string) {
15
+ const now = Date.now();
16
+ const arr = ipMap.get(ip) ?? [];
17
+ const pruned = arr.filter((t) => now - t < RATE_LIMIT_WINDOW_MS);
18
+ pruned.push(now);
19
+ ipMap.set(ip, pruned);
20
+ return pruned.length <= MAX_PER_WINDOW;
21
+ }
22
+
23
+ export async function POST(req: Request) {
24
+ if (process.env.NEXTWORKS_ENABLE_PASSWORD_RESET !== "1") {
25
+ return NextResponse.json({ message: "Not found" }, { status: 404 });
26
+ }
27
+ const ip = req.headers.get("x-forwarded-for") || "local";
28
+ if (!rateLimit(ip)) {
29
+ return NextResponse.json({ message: "Too many requests" }, { status: 429 });
30
+ }
31
+
32
+ let body: unknown;
33
+ try {
34
+ body = await req.json();
35
+ } catch {
36
+ return NextResponse.json({ message: "Invalid request" }, { status: 400 });
37
+ }
38
+
39
+ try {
40
+ const parsed = forgotPasswordSchema.parse(body);
41
+ const { email } = parsed;
42
+
43
+ const user = await prisma.user.findUnique({ where: { email } });
44
+ if (user) {
45
+ const token = randomBytes(24).toString("hex");
46
+ const tokenHash = createHash("sha256").update(token).digest("hex");
47
+ const expires = new Date(Date.now() + 1000 * 60 * 60); // 1 hour
48
+ await prisma.passwordReset.create({
49
+ data: {
50
+ tokenHash,
51
+ expires,
52
+ user: { connect: { id: user.id } },
53
+ },
54
+ });
55
+
56
+ const mailConfigured = isEmailProviderConfigured();
57
+ const isProd = process.env.NODE_ENV === "production";
58
+
59
+ if (
60
+ isProd &&
61
+ process.env.NEXTWORKS_ENABLE_PASSWORD_RESET === "1" &&
62
+ !mailConfigured
63
+ ) {
64
+ return NextResponse.json({ message: "Not found" }, { status: 404 });
65
+ }
66
+
67
+ try {
68
+ const base = process.env.NEXTAUTH_URL ?? "http://localhost:3000";
69
+ const resetUrl = `${base.replace(/\/$/, "")}/auth/reset-password?token=${token}`;
70
+
71
+ if (mailConfigured) {
72
+ try {
73
+ await sendEmail({
74
+ to: email,
75
+ subject: "Password reset",
76
+ text: `Reset your password: ${resetUrl}`,
77
+ html: `<p>Reset your password: <a href="${resetUrl}">Reset password</a></p>`,
78
+ });
79
+ console.info(`Password reset email queued for ${email}`);
80
+ } catch (e) {
81
+ console.error("Failed to send password reset email");
82
+ }
83
+ } else if (process.env.NEXTWORKS_USE_DEV_EMAIL === "1") {
84
+ try {
85
+ const { previewUrl } = await sendDevEmail({
86
+ to: email,
87
+ subject: "Password reset",
88
+ text: `Reset your password: ${resetUrl}`,
89
+ html: `<p>Reset your password: <a href="${resetUrl}">Reset password</a></p>`,
90
+ });
91
+ if (previewUrl) {
92
+ console.info(`Password reset email (dev preview): ${previewUrl}`);
93
+ } else {
94
+ console.info(`Password reset email queued for ${email}`);
95
+ }
96
+ } catch (e) {
97
+ console.error("Failed to send dev password reset email");
98
+ }
99
+ } else {
100
+ console.info(`Password reset requested for ${email}`);
101
+ }
102
+ } catch (e) {
103
+ console.error("Failed to handle password reset email");
104
+ }
105
+ }
106
+
107
+ return NextResponse.json({ message: "If an account exists, a reset link was sent." });
108
+ } catch (err: any) {
109
+ if (err instanceof z.ZodError) {
110
+ return NextResponse.json({ message: "Validation failed", errors: (err as z.ZodError).issues }, { status: 400 });
111
+ }
112
+ return NextResponse.json({ message: "Failed" }, { status: 400 });
113
+ }
114
+ }
@@ -0,0 +1,6 @@
1
+ import { NextResponse } from "next/server";
2
+
3
+ export async function GET() {
4
+ const enabled = Boolean(process.env.GITHUB_ID && process.env.GITHUB_SECRET);
5
+ return NextResponse.json({ github: enabled });
6
+ }