@digilogiclabs/create-saas-app 2.0.0 → 2.2.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 (348) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +975 -891
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/generators/template-generator.d.ts +11 -0
  5. package/dist/generators/template-generator.d.ts.map +1 -1
  6. package/dist/generators/template-generator.js +389 -18
  7. package/dist/generators/template-generator.js.map +1 -1
  8. package/dist/index.js +1837 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/templates/infrastructure/kubernetes/base/template/README.md +253 -0
  11. package/dist/templates/infrastructure/kubernetes/base/template/configmap.yaml +12 -0
  12. package/dist/templates/infrastructure/kubernetes/base/template/deployment.yaml +123 -0
  13. package/dist/templates/infrastructure/kubernetes/base/template/hpa.yaml +45 -0
  14. package/dist/templates/infrastructure/kubernetes/base/template/ingress.yaml +31 -0
  15. package/dist/templates/infrastructure/kubernetes/base/template/kustomization.yaml +25 -0
  16. package/dist/templates/infrastructure/kubernetes/base/template/namespace.yaml +8 -0
  17. package/dist/templates/infrastructure/kubernetes/base/template/networkpolicy.yaml +48 -0
  18. package/dist/templates/infrastructure/kubernetes/base/template/pdb.yaml +14 -0
  19. package/dist/templates/infrastructure/kubernetes/base/template/secret.yaml +17 -0
  20. package/dist/templates/infrastructure/kubernetes/base/template/service.yaml +19 -0
  21. package/dist/templates/infrastructure/kubernetes/base/template/serviceaccount.yaml +9 -0
  22. package/dist/templates/infrastructure/kubernetes/production/template/kustomization.yaml +92 -0
  23. package/dist/templates/infrastructure/terraform/aws/template/README.md +156 -0
  24. package/dist/templates/infrastructure/terraform/aws/template/main.tf +343 -0
  25. package/dist/templates/infrastructure/terraform/aws/template/outputs.tf +66 -0
  26. package/dist/templates/infrastructure/terraform/aws/template/terraform.tfvars.example +28 -0
  27. package/dist/templates/infrastructure/terraform/aws/template/variables.tf +110 -0
  28. package/dist/templates/infrastructure/terraform/gcp/template/README.md +165 -0
  29. package/dist/templates/infrastructure/terraform/gcp/template/main.tf +397 -0
  30. package/dist/templates/infrastructure/terraform/gcp/template/outputs.tf +51 -0
  31. package/dist/templates/infrastructure/terraform/gcp/template/terraform.tfvars.example +29 -0
  32. package/dist/templates/infrastructure/terraform/gcp/template/variables.tf +115 -0
  33. package/dist/templates/shared/admin/web/app/admin/layout.tsx +34 -0
  34. package/dist/templates/shared/admin/web/components/admin-nav.tsx +48 -0
  35. package/dist/templates/shared/audit/web/lib/audit.ts +24 -0
  36. package/dist/templates/shared/auth/keycloak/web/app/api/auth/federated-logout/route.ts +173 -0
  37. package/dist/templates/shared/auth/keycloak/web/auth.config.ts +84 -0
  38. package/dist/templates/shared/auth/keycloak/web/auth.ts +26 -0
  39. package/dist/templates/shared/beta/web/app/api/beta-settings/route.ts +25 -0
  40. package/dist/templates/shared/beta/web/app/api/validate-beta-code/route.ts +67 -0
  41. package/dist/templates/shared/beta/web/lib/beta/settings.ts +31 -0
  42. package/dist/templates/shared/cache/web/lib/cache.ts +44 -0
  43. package/dist/templates/shared/config/web/lib/config.ts +112 -0
  44. package/dist/templates/shared/config/web/next.config.mjs +62 -0
  45. package/dist/templates/shared/contact/web/app/api/contact/route.ts +113 -0
  46. package/dist/templates/shared/contact/web/app/contact/page.tsx +195 -0
  47. package/dist/templates/shared/cookie-consent/web/components/cookie-consent.tsx +54 -0
  48. package/dist/templates/shared/database/postgresql/web/drizzle.config.ts +16 -0
  49. package/dist/templates/shared/database/postgresql/web/lib/db/drizzle.ts +39 -0
  50. package/dist/templates/shared/database/postgresql/web/lib/db/schema.ts +33 -0
  51. package/dist/templates/shared/database/supabase/web/lib/supabase/client.ts +12 -0
  52. package/dist/templates/shared/database/supabase/web/lib/supabase/server.ts +31 -0
  53. package/dist/templates/shared/database/supabase/web/lib/supabase/service.ts +15 -0
  54. package/dist/templates/shared/email/web/lib/email/branding.ts +18 -0
  55. package/dist/templates/shared/email/web/lib/email/client.ts +96 -0
  56. package/dist/templates/shared/error-pages/web/app/error.tsx +70 -0
  57. package/dist/templates/shared/error-pages/web/app/global-error.tsx +102 -0
  58. package/dist/templates/shared/error-pages/web/app/not-found.tsx +39 -0
  59. package/dist/templates/shared/health/web/app/api/health/route.ts +68 -0
  60. package/dist/templates/shared/legal/web/app/(legal)/privacy/page.tsx +205 -0
  61. package/dist/templates/shared/legal/web/app/(legal)/terms/page.tsx +154 -0
  62. package/dist/templates/shared/legal/web/lib/legal-config.ts +50 -0
  63. package/dist/templates/shared/loading/web/app/loading.tsx +5 -0
  64. package/dist/templates/shared/loading/web/components/skeleton.tsx +95 -0
  65. package/dist/templates/shared/middleware/web/middleware.ts +68 -0
  66. package/dist/templates/shared/observability/web/lib/observability.ts +135 -0
  67. package/dist/templates/shared/payments/web/app/api/webhooks/stripe/route.ts +109 -0
  68. package/dist/templates/shared/platform/web/lib/platform.ts +37 -0
  69. package/dist/templates/shared/redis/web/lib/rate-limit-store.ts +18 -0
  70. package/dist/templates/shared/redis/web/lib/redis.ts +48 -0
  71. package/dist/templates/shared/security/web/lib/api-security.ts +318 -0
  72. package/dist/templates/shared/seo/web/app/api/og/route.tsx +97 -0
  73. package/dist/templates/shared/seo/web/app/robots.ts +53 -0
  74. package/dist/templates/shared/seo/web/app/sitemap.ts +53 -0
  75. package/dist/templates/shared/utils/web/lib/api-response.ts +71 -0
  76. package/dist/templates/shared/utils/web/lib/utils.ts +85 -0
  77. package/dist/templates/web/ai-platform/template/.env.example +16 -0
  78. package/dist/templates/web/ai-platform/template/README.md +84 -0
  79. package/dist/templates/web/ai-platform/template/middleware.ts +55 -0
  80. package/dist/templates/web/ai-platform/template/next.config.js +14 -0
  81. package/dist/templates/web/ai-platform/template/package.json +55 -0
  82. package/dist/templates/web/ai-platform/template/src/app/api/chat/route.ts +54 -0
  83. package/dist/templates/web/ai-platform/template/src/app/chat/page.tsx +235 -0
  84. package/dist/templates/web/ai-platform/template/src/app/dashboard/page.tsx +142 -0
  85. package/dist/templates/web/ai-platform/template/src/app/globals.css +34 -0
  86. package/dist/templates/web/ai-platform/template/src/app/layout.tsx +27 -0
  87. package/dist/templates/web/ai-platform/template/src/app/page.tsx +203 -0
  88. package/dist/templates/web/ai-platform/template/src/components/providers/app-providers.tsx +27 -0
  89. package/dist/templates/web/ai-platform/template/src/lib/auth-server.ts +33 -0
  90. package/dist/templates/web/ai-platform/template/src/lib/supabase/client.ts +8 -0
  91. package/dist/templates/web/ai-platform/template/src/lib/supabase/server.ts +27 -0
  92. package/dist/templates/web/ai-platform/template/src/lib/utils.ts +6 -0
  93. package/dist/templates/web/ai-platform/template/tsconfig.json +27 -0
  94. package/dist/templates/web/iot-dashboard/template/.env.example +12 -0
  95. package/dist/templates/web/iot-dashboard/template/README.md +101 -0
  96. package/dist/templates/web/iot-dashboard/template/middleware.ts +56 -0
  97. package/dist/templates/web/iot-dashboard/template/next.config.js +14 -0
  98. package/dist/templates/web/iot-dashboard/template/package.json +49 -0
  99. package/dist/templates/web/iot-dashboard/template/src/app/dashboard/page.tsx +229 -0
  100. package/dist/templates/web/iot-dashboard/template/src/app/globals.css +20 -0
  101. package/dist/templates/web/iot-dashboard/template/src/app/layout.tsx +27 -0
  102. package/dist/templates/web/iot-dashboard/template/src/app/page.tsx +191 -0
  103. package/dist/templates/web/iot-dashboard/template/src/components/providers/app-providers.tsx +24 -0
  104. package/dist/templates/web/iot-dashboard/template/src/lib/auth-server.ts +33 -0
  105. package/dist/templates/web/iot-dashboard/template/src/lib/supabase/client.ts +8 -0
  106. package/dist/templates/web/iot-dashboard/template/src/lib/supabase/server.ts +27 -0
  107. package/dist/templates/web/iot-dashboard/template/src/lib/utils.ts +25 -0
  108. package/dist/templates/web/iot-dashboard/template/tsconfig.json +27 -0
  109. package/dist/templates/web/marketplace/template/.env.example +12 -0
  110. package/dist/templates/web/marketplace/template/README.md +66 -0
  111. package/dist/templates/web/marketplace/template/middleware.ts +56 -0
  112. package/dist/templates/web/marketplace/template/next.config.js +14 -0
  113. package/dist/templates/web/marketplace/template/package.json +51 -0
  114. package/dist/templates/web/marketplace/template/src/app/cart/page.tsx +147 -0
  115. package/dist/templates/web/marketplace/template/src/app/dashboard/page.tsx +149 -0
  116. package/dist/templates/web/marketplace/template/src/app/globals.css +20 -0
  117. package/dist/templates/web/marketplace/template/src/app/layout.tsx +27 -0
  118. package/dist/templates/web/marketplace/template/src/app/page.tsx +167 -0
  119. package/dist/templates/web/marketplace/template/src/app/products/page.tsx +129 -0
  120. package/dist/templates/web/marketplace/template/src/components/providers/app-providers.tsx +27 -0
  121. package/dist/templates/web/marketplace/template/src/lib/auth-server.ts +33 -0
  122. package/dist/templates/web/marketplace/template/src/lib/supabase/client.ts +8 -0
  123. package/dist/templates/web/marketplace/template/src/lib/supabase/server.ts +27 -0
  124. package/dist/templates/web/marketplace/template/src/lib/utils.ts +19 -0
  125. package/dist/templates/web/marketplace/template/tsconfig.json +27 -0
  126. package/dist/templates/web/micro-saas/template/.env.example +10 -0
  127. package/dist/templates/web/micro-saas/template/README.md +63 -0
  128. package/dist/templates/web/micro-saas/template/middleware.ts +53 -0
  129. package/dist/templates/web/micro-saas/template/next.config.js +14 -0
  130. package/dist/templates/web/micro-saas/template/package.json +41 -0
  131. package/dist/templates/web/micro-saas/template/src/app/dashboard/page.tsx +117 -0
  132. package/dist/templates/web/micro-saas/template/src/app/globals.css +20 -0
  133. package/dist/templates/web/micro-saas/template/src/app/layout.tsx +27 -0
  134. package/dist/templates/web/micro-saas/template/src/app/login/page.tsx +87 -0
  135. package/dist/templates/web/micro-saas/template/src/app/page.tsx +137 -0
  136. package/dist/templates/web/micro-saas/template/src/app/signup/page.tsx +108 -0
  137. package/dist/templates/web/micro-saas/template/src/components/providers/app-providers.tsx +24 -0
  138. package/dist/templates/web/micro-saas/template/src/lib/auth-server.ts +33 -0
  139. package/dist/templates/web/micro-saas/template/src/lib/supabase/client.ts +8 -0
  140. package/dist/templates/web/micro-saas/template/src/lib/supabase/server.ts +29 -0
  141. package/dist/templates/web/micro-saas/template/src/lib/utils.ts +6 -0
  142. package/dist/templates/web/micro-saas/template/tsconfig.json +27 -0
  143. package/package.json +5 -4
  144. package/src/templates/infrastructure/kubernetes/base/template/README.md +253 -0
  145. package/src/templates/infrastructure/kubernetes/base/template/configmap.yaml +12 -0
  146. package/src/templates/infrastructure/kubernetes/base/template/deployment.yaml +123 -0
  147. package/src/templates/infrastructure/kubernetes/base/template/hpa.yaml +45 -0
  148. package/src/templates/infrastructure/kubernetes/base/template/ingress.yaml +31 -0
  149. package/src/templates/infrastructure/kubernetes/base/template/kustomization.yaml +25 -0
  150. package/src/templates/infrastructure/kubernetes/base/template/namespace.yaml +8 -0
  151. package/src/templates/infrastructure/kubernetes/base/template/networkpolicy.yaml +48 -0
  152. package/src/templates/infrastructure/kubernetes/base/template/pdb.yaml +14 -0
  153. package/src/templates/infrastructure/kubernetes/base/template/secret.yaml +17 -0
  154. package/src/templates/infrastructure/kubernetes/base/template/service.yaml +19 -0
  155. package/src/templates/infrastructure/kubernetes/base/template/serviceaccount.yaml +9 -0
  156. package/src/templates/infrastructure/kubernetes/production/template/kustomization.yaml +92 -0
  157. package/src/templates/infrastructure/terraform/aws/template/README.md +156 -0
  158. package/src/templates/infrastructure/terraform/aws/template/main.tf +343 -0
  159. package/src/templates/infrastructure/terraform/aws/template/outputs.tf +66 -0
  160. package/src/templates/infrastructure/terraform/aws/template/terraform.tfvars.example +28 -0
  161. package/src/templates/infrastructure/terraform/aws/template/variables.tf +110 -0
  162. package/src/templates/infrastructure/terraform/gcp/template/README.md +165 -0
  163. package/src/templates/infrastructure/terraform/gcp/template/main.tf +397 -0
  164. package/src/templates/infrastructure/terraform/gcp/template/outputs.tf +51 -0
  165. package/src/templates/infrastructure/terraform/gcp/template/terraform.tfvars.example +29 -0
  166. package/src/templates/infrastructure/terraform/gcp/template/variables.tf +115 -0
  167. package/src/templates/shared/admin/web/app/admin/layout.tsx +34 -0
  168. package/src/templates/shared/admin/web/components/admin-nav.tsx +48 -0
  169. package/src/templates/shared/audit/web/lib/audit.ts +24 -0
  170. package/src/templates/shared/auth/keycloak/web/app/api/auth/federated-logout/route.ts +173 -0
  171. package/src/templates/shared/auth/keycloak/web/auth.config.ts +84 -0
  172. package/src/templates/shared/auth/keycloak/web/auth.ts +26 -0
  173. package/src/templates/shared/beta/web/app/api/beta-settings/route.ts +25 -0
  174. package/src/templates/shared/beta/web/app/api/validate-beta-code/route.ts +67 -0
  175. package/src/templates/shared/beta/web/lib/beta/settings.ts +31 -0
  176. package/src/templates/shared/cache/web/lib/cache.ts +44 -0
  177. package/src/templates/shared/config/web/lib/config.ts +112 -0
  178. package/src/templates/shared/config/web/next.config.mjs +62 -0
  179. package/src/templates/shared/contact/web/app/api/contact/route.ts +113 -0
  180. package/src/templates/shared/contact/web/app/contact/page.tsx +195 -0
  181. package/src/templates/shared/cookie-consent/web/components/cookie-consent.tsx +54 -0
  182. package/src/templates/shared/database/postgresql/web/drizzle.config.ts +16 -0
  183. package/src/templates/shared/database/postgresql/web/lib/db/drizzle.ts +39 -0
  184. package/src/templates/shared/database/postgresql/web/lib/db/schema.ts +33 -0
  185. package/src/templates/shared/database/supabase/web/lib/supabase/client.ts +12 -0
  186. package/src/templates/shared/database/supabase/web/lib/supabase/server.ts +31 -0
  187. package/src/templates/shared/database/supabase/web/lib/supabase/service.ts +15 -0
  188. package/src/templates/shared/email/web/lib/email/branding.ts +18 -0
  189. package/src/templates/shared/email/web/lib/email/client.ts +96 -0
  190. package/src/templates/shared/error-pages/web/app/error.tsx +70 -0
  191. package/src/templates/shared/error-pages/web/app/global-error.tsx +102 -0
  192. package/src/templates/shared/error-pages/web/app/not-found.tsx +39 -0
  193. package/src/templates/shared/health/web/app/api/health/route.ts +68 -0
  194. package/src/templates/shared/legal/web/app/(legal)/privacy/page.tsx +205 -0
  195. package/src/templates/shared/legal/web/app/(legal)/terms/page.tsx +154 -0
  196. package/src/templates/shared/legal/web/lib/legal-config.ts +50 -0
  197. package/src/templates/shared/loading/web/app/loading.tsx +5 -0
  198. package/src/templates/shared/loading/web/components/skeleton.tsx +95 -0
  199. package/src/templates/shared/middleware/web/middleware.ts +68 -0
  200. package/src/templates/shared/observability/web/lib/observability.ts +135 -0
  201. package/src/templates/shared/payments/web/app/api/webhooks/stripe/route.ts +109 -0
  202. package/src/templates/shared/platform/web/lib/platform.ts +37 -0
  203. package/src/templates/shared/redis/web/lib/rate-limit-store.ts +18 -0
  204. package/src/templates/shared/redis/web/lib/redis.ts +48 -0
  205. package/src/templates/shared/security/web/lib/api-security.ts +318 -0
  206. package/src/templates/shared/seo/web/app/api/og/route.tsx +97 -0
  207. package/src/templates/shared/seo/web/app/robots.ts +53 -0
  208. package/src/templates/shared/seo/web/app/sitemap.ts +53 -0
  209. package/src/templates/shared/utils/web/lib/api-response.ts +71 -0
  210. package/src/templates/shared/utils/web/lib/utils.ts +85 -0
  211. package/src/templates/web/ai-platform/template/.env.example +16 -0
  212. package/src/templates/web/ai-platform/template/README.md +84 -0
  213. package/src/templates/web/ai-platform/template/middleware.ts +55 -0
  214. package/src/templates/web/ai-platform/template/next.config.js +14 -0
  215. package/src/templates/web/ai-platform/template/package.json +55 -0
  216. package/src/templates/web/ai-platform/template/src/app/api/chat/route.ts +54 -0
  217. package/src/templates/web/ai-platform/template/src/app/chat/page.tsx +235 -0
  218. package/src/templates/web/ai-platform/template/src/app/dashboard/page.tsx +142 -0
  219. package/src/templates/web/ai-platform/template/src/app/globals.css +34 -0
  220. package/src/templates/web/ai-platform/template/src/app/layout.tsx +27 -0
  221. package/src/templates/web/ai-platform/template/src/app/page.tsx +203 -0
  222. package/src/templates/web/ai-platform/template/src/components/providers/app-providers.tsx +27 -0
  223. package/src/templates/web/ai-platform/template/src/lib/auth-server.ts +33 -0
  224. package/src/templates/web/ai-platform/template/src/lib/supabase/client.ts +8 -0
  225. package/src/templates/web/ai-platform/template/src/lib/supabase/server.ts +27 -0
  226. package/src/templates/web/ai-platform/template/src/lib/utils.ts +6 -0
  227. package/src/templates/web/ai-platform/template/tsconfig.json +27 -0
  228. package/src/templates/web/iot-dashboard/template/.env.example +12 -0
  229. package/src/templates/web/iot-dashboard/template/README.md +101 -0
  230. package/src/templates/web/iot-dashboard/template/middleware.ts +56 -0
  231. package/src/templates/web/iot-dashboard/template/next.config.js +14 -0
  232. package/src/templates/web/iot-dashboard/template/package.json +49 -0
  233. package/src/templates/web/iot-dashboard/template/src/app/dashboard/page.tsx +229 -0
  234. package/src/templates/web/iot-dashboard/template/src/app/globals.css +20 -0
  235. package/src/templates/web/iot-dashboard/template/src/app/layout.tsx +27 -0
  236. package/src/templates/web/iot-dashboard/template/src/app/page.tsx +191 -0
  237. package/src/templates/web/iot-dashboard/template/src/components/providers/app-providers.tsx +24 -0
  238. package/src/templates/web/iot-dashboard/template/src/lib/auth-server.ts +33 -0
  239. package/src/templates/web/iot-dashboard/template/src/lib/supabase/client.ts +8 -0
  240. package/src/templates/web/iot-dashboard/template/src/lib/supabase/server.ts +27 -0
  241. package/src/templates/web/iot-dashboard/template/src/lib/utils.ts +25 -0
  242. package/src/templates/web/iot-dashboard/template/tsconfig.json +27 -0
  243. package/src/templates/web/marketplace/template/.env.example +12 -0
  244. package/src/templates/web/marketplace/template/README.md +66 -0
  245. package/src/templates/web/marketplace/template/middleware.ts +56 -0
  246. package/src/templates/web/marketplace/template/next.config.js +14 -0
  247. package/src/templates/web/marketplace/template/package.json +51 -0
  248. package/src/templates/web/marketplace/template/src/app/cart/page.tsx +147 -0
  249. package/src/templates/web/marketplace/template/src/app/dashboard/page.tsx +149 -0
  250. package/src/templates/web/marketplace/template/src/app/globals.css +20 -0
  251. package/src/templates/web/marketplace/template/src/app/layout.tsx +27 -0
  252. package/src/templates/web/marketplace/template/src/app/page.tsx +167 -0
  253. package/src/templates/web/marketplace/template/src/app/products/page.tsx +129 -0
  254. package/src/templates/web/marketplace/template/src/components/providers/app-providers.tsx +27 -0
  255. package/src/templates/web/marketplace/template/src/lib/auth-server.ts +33 -0
  256. package/src/templates/web/marketplace/template/src/lib/supabase/client.ts +8 -0
  257. package/src/templates/web/marketplace/template/src/lib/supabase/server.ts +27 -0
  258. package/src/templates/web/marketplace/template/src/lib/utils.ts +19 -0
  259. package/src/templates/web/marketplace/template/tsconfig.json +27 -0
  260. package/src/templates/web/micro-saas/template/.env.example +10 -0
  261. package/src/templates/web/micro-saas/template/README.md +63 -0
  262. package/src/templates/web/micro-saas/template/middleware.ts +53 -0
  263. package/src/templates/web/micro-saas/template/next.config.js +14 -0
  264. package/src/templates/web/micro-saas/template/package.json +41 -0
  265. package/src/templates/web/micro-saas/template/src/app/dashboard/page.tsx +117 -0
  266. package/src/templates/web/micro-saas/template/src/app/globals.css +20 -0
  267. package/src/templates/web/micro-saas/template/src/app/layout.tsx +27 -0
  268. package/src/templates/web/micro-saas/template/src/app/login/page.tsx +87 -0
  269. package/src/templates/web/micro-saas/template/src/app/page.tsx +137 -0
  270. package/src/templates/web/micro-saas/template/src/app/signup/page.tsx +108 -0
  271. package/src/templates/web/micro-saas/template/src/components/providers/app-providers.tsx +24 -0
  272. package/src/templates/web/micro-saas/template/src/lib/auth-server.ts +33 -0
  273. package/src/templates/web/micro-saas/template/src/lib/supabase/client.ts +8 -0
  274. package/src/templates/web/micro-saas/template/src/lib/supabase/server.ts +29 -0
  275. package/src/templates/web/micro-saas/template/src/lib/utils.ts +6 -0
  276. package/src/templates/web/micro-saas/template/tsconfig.json +27 -0
  277. package/dist/cli/commands/add.d.ts +0 -6
  278. package/dist/cli/commands/add.d.ts.map +0 -1
  279. package/dist/cli/commands/add.js +0 -39
  280. package/dist/cli/commands/add.js.map +0 -1
  281. package/dist/cli/commands/create.d.ts +0 -45
  282. package/dist/cli/commands/create.d.ts.map +0 -1
  283. package/dist/cli/commands/create.js +0 -175
  284. package/dist/cli/commands/create.js.map +0 -1
  285. package/dist/cli/commands/index.d.ts +0 -4
  286. package/dist/cli/commands/index.d.ts.map +0 -1
  287. package/dist/cli/commands/index.js +0 -20
  288. package/dist/cli/commands/index.js.map +0 -1
  289. package/dist/cli/commands/update.d.ts +0 -6
  290. package/dist/cli/commands/update.d.ts.map +0 -1
  291. package/dist/cli/commands/update.js +0 -68
  292. package/dist/cli/commands/update.js.map +0 -1
  293. package/dist/cli/index.d.ts +0 -4
  294. package/dist/cli/index.d.ts.map +0 -1
  295. package/dist/cli/index.js +0 -61
  296. package/dist/cli/index.js.map +0 -1
  297. package/dist/cli/prompts/index.d.ts +0 -2
  298. package/dist/cli/prompts/index.d.ts.map +0 -1
  299. package/dist/cli/prompts/index.js +0 -18
  300. package/dist/cli/prompts/index.js.map +0 -1
  301. package/dist/cli/prompts/project-setup.d.ts +0 -5
  302. package/dist/cli/prompts/project-setup.d.ts.map +0 -1
  303. package/dist/cli/prompts/project-setup.js +0 -316
  304. package/dist/cli/prompts/project-setup.js.map +0 -1
  305. package/dist/cli/utils/git.d.ts +0 -9
  306. package/dist/cli/utils/git.d.ts.map +0 -1
  307. package/dist/cli/utils/git.js +0 -77
  308. package/dist/cli/utils/git.js.map +0 -1
  309. package/dist/cli/utils/index.d.ts +0 -5
  310. package/dist/cli/utils/index.d.ts.map +0 -1
  311. package/dist/cli/utils/index.js +0 -21
  312. package/dist/cli/utils/index.js.map +0 -1
  313. package/dist/cli/utils/logger.d.ts +0 -16
  314. package/dist/cli/utils/logger.d.ts.map +0 -1
  315. package/dist/cli/utils/logger.js +0 -55
  316. package/dist/cli/utils/logger.js.map +0 -1
  317. package/dist/cli/utils/package-manager.d.ts +0 -8
  318. package/dist/cli/utils/package-manager.d.ts.map +0 -1
  319. package/dist/cli/utils/package-manager.js +0 -92
  320. package/dist/cli/utils/package-manager.js.map +0 -1
  321. package/dist/cli/utils/spinner.d.ts +0 -7
  322. package/dist/cli/utils/spinner.d.ts.map +0 -1
  323. package/dist/cli/utils/spinner.js +0 -48
  324. package/dist/cli/utils/spinner.js.map +0 -1
  325. package/dist/cli/validators/dependencies.d.ts +0 -15
  326. package/dist/cli/validators/dependencies.d.ts.map +0 -1
  327. package/dist/cli/validators/dependencies.js +0 -108
  328. package/dist/cli/validators/dependencies.js.map +0 -1
  329. package/dist/cli/validators/index.d.ts +0 -3
  330. package/dist/cli/validators/index.d.ts.map +0 -1
  331. package/dist/cli/validators/index.js +0 -19
  332. package/dist/cli/validators/index.js.map +0 -1
  333. package/dist/cli/validators/project-name.d.ts +0 -5
  334. package/dist/cli/validators/project-name.d.ts.map +0 -1
  335. package/dist/cli/validators/project-name.js +0 -151
  336. package/dist/cli/validators/project-name.js.map +0 -1
  337. package/dist/generators/file-processor.d.ts +0 -28
  338. package/dist/generators/file-processor.d.ts.map +0 -1
  339. package/dist/generators/file-processor.js +0 -224
  340. package/dist/generators/file-processor.js.map +0 -1
  341. package/dist/generators/index.d.ts +0 -4
  342. package/dist/generators/index.d.ts.map +0 -1
  343. package/dist/generators/index.js +0 -20
  344. package/dist/generators/index.js.map +0 -1
  345. package/dist/generators/package-installer.d.ts +0 -29
  346. package/dist/generators/package-installer.d.ts.map +0 -1
  347. package/dist/generators/package-installer.js +0 -177
  348. package/dist/generators/package-installer.js.map +0 -1
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Federated Logout Route
3
+ *
4
+ * Handles proper logout from both Auth.js and Keycloak.
5
+ * Ensures the Keycloak session is cleared so users aren't auto-logged-in
6
+ * when they try to sign in again.
7
+ *
8
+ * Flow:
9
+ * 1. Get the id_token from the Auth.js session
10
+ * 2. Return an HTML page with Set-Cookie headers to clear all auth cookies
11
+ * 3. The HTML page auto-redirects to Keycloak's logout endpoint
12
+ * 4. Keycloak clears its session and redirects back to the app
13
+ *
14
+ * Returns HTML (200) instead of 307 redirect because browsers may not
15
+ * reliably process Set-Cookie headers on redirect responses.
16
+ */
17
+
18
+ import { NextRequest, NextResponse } from 'next/server';
19
+ import { auth } from '@/auth';
20
+ import { getToken } from 'next-auth/jwt';
21
+
22
+ /** Serialize a Set-Cookie header string for cookie deletion. */
23
+ function expireCookie(
24
+ name: string,
25
+ options?: { domain?: string; secure?: boolean; hostPrefix?: boolean }
26
+ ): string {
27
+ const parts = [
28
+ `${name}=`,
29
+ 'Path=/',
30
+ 'Expires=Thu, 01 Jan 1970 00:00:00 GMT',
31
+ 'Max-Age=0',
32
+ 'SameSite=Lax',
33
+ ];
34
+ if (options?.hostPrefix) {
35
+ parts.push('Secure');
36
+ } else {
37
+ parts.push('HttpOnly');
38
+ if (options?.domain) parts.push(`Domain=${options.domain}`);
39
+ if (options?.secure) parts.push('Secure');
40
+ }
41
+ return parts.join('; ');
42
+ }
43
+
44
+ /** Validate callback URL to prevent open redirect attacks. */
45
+ function isAllowedCallbackUrl(url: string, baseUrl: string): boolean {
46
+ if (url.startsWith('/') && !url.startsWith('//')) return true;
47
+ try {
48
+ const parsed = new URL(url);
49
+ const base = new URL(baseUrl);
50
+ const allowedHosts = [base.hostname, `www.${base.hostname}`];
51
+ if (base.hostname.startsWith('www.')) {
52
+ allowedHosts.push(base.hostname.slice(4));
53
+ }
54
+ return allowedHosts.includes(parsed.hostname);
55
+ } catch {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ export async function GET(request: NextRequest) {
61
+ const session = await auth();
62
+ const searchParams = request.nextUrl.searchParams;
63
+ const rawCallbackUrl = searchParams.get('callbackUrl') || '/';
64
+ const queryIdToken = searchParams.get('id_token_hint');
65
+
66
+ const baseUrl = process.env.NEXTAUTH_URL || process.env.AUTH_URL || 'http://localhost:3000';
67
+ const callbackUrl = isAllowedCallbackUrl(rawCallbackUrl, baseUrl) ? rawCallbackUrl : '/';
68
+ const postLogoutRedirectUri = callbackUrl.startsWith('http')
69
+ ? callbackUrl
70
+ : `${baseUrl}${callbackUrl}`;
71
+
72
+ const keycloakIssuer = process.env.AUTH_KEYCLOAK_ISSUER;
73
+ if (!keycloakIssuer) {
74
+ console.error('[Federated Logout] Missing AUTH_KEYCLOAK_ISSUER');
75
+ return NextResponse.redirect(
76
+ new URL('/api/auth/signout?callbackUrl=' + encodeURIComponent(callbackUrl), request.url)
77
+ );
78
+ }
79
+
80
+ // Revoke refresh token (best-effort)
81
+ const jwtToken = await getToken({ req: request });
82
+ const refreshToken = jwtToken?.refreshToken as string | undefined;
83
+ if (refreshToken) {
84
+ try {
85
+ await fetch(`${keycloakIssuer}/protocol/openid-connect/revoke`, {
86
+ method: 'POST',
87
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
88
+ body: new URLSearchParams({
89
+ token: refreshToken,
90
+ token_type_hint: 'refresh_token',
91
+ ...(process.env.AUTH_KEYCLOAK_ID && { client_id: process.env.AUTH_KEYCLOAK_ID }),
92
+ ...(process.env.AUTH_KEYCLOAK_SECRET && {
93
+ client_secret: process.env.AUTH_KEYCLOAK_SECRET,
94
+ }),
95
+ }),
96
+ });
97
+ } catch {
98
+ // Best-effort — don't block logout
99
+ }
100
+ }
101
+
102
+ // Build Keycloak logout URL
103
+ const logoutUrl = new URL(`${keycloakIssuer}/protocol/openid-connect/logout`);
104
+ logoutUrl.searchParams.set('post_logout_redirect_uri', postLogoutRedirectUri);
105
+ if (process.env.AUTH_KEYCLOAK_ID) {
106
+ logoutUrl.searchParams.set('client_id', process.env.AUTH_KEYCLOAK_ID);
107
+ }
108
+ const idToken = session?.idToken || queryIdToken;
109
+ if (idToken) {
110
+ logoutUrl.searchParams.set('id_token_hint', idToken);
111
+ }
112
+
113
+ const escapedUrl = logoutUrl
114
+ .toString()
115
+ .replace(/&/g, '&')
116
+ .replace(/"/g, '"')
117
+ .replace(/</g, '&lt;')
118
+ .replace(/>/g, '&gt;');
119
+
120
+ const html = `<!DOCTYPE html>
121
+ <html><head>
122
+ <meta charset="utf-8">
123
+ <meta http-equiv="refresh" content="0;url=${escapedUrl}">
124
+ <title>Signing out...</title>
125
+ <style>body{display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;font-family:system-ui,sans-serif;background:#0a0a0a;color:#fff}p{font-size:1.1rem;opacity:0.7}</style>
126
+ </head><body>
127
+ <p>Signing out&hellip;</p>
128
+ <script>window.location.replace(${JSON.stringify(logoutUrl.toString()).replace(/</g, '\\u003c')});</script>
129
+ </body></html>`;
130
+
131
+ const response = new NextResponse(html, {
132
+ status: 200,
133
+ headers: {
134
+ 'Content-Type': 'text/html; charset=utf-8',
135
+ 'Cache-Control': 'no-store, no-cache, must-revalidate',
136
+ Pragma: 'no-cache',
137
+ },
138
+ });
139
+
140
+ // Clear ALL Auth.js cookie variants
141
+ const isProduction = process.env.NODE_ENV === 'production';
142
+ const cookieNames = [
143
+ 'authjs.session-token',
144
+ '__Secure-authjs.session-token',
145
+ 'authjs.callback-url',
146
+ '__Secure-authjs.callback-url',
147
+ 'authjs.csrf-token',
148
+ '__Secure-authjs.csrf-token',
149
+ 'authjs.pkce.code_verifier',
150
+ '__Secure-authjs.pkce.code_verifier',
151
+ 'authjs.state',
152
+ '__Secure-authjs.state',
153
+ // Legacy next-auth names
154
+ 'next-auth.session-token',
155
+ '__Secure-next-auth.session-token',
156
+ 'next-auth.callback-url',
157
+ '__Secure-next-auth.callback-url',
158
+ 'next-auth.csrf-token',
159
+ '__Secure-next-auth.csrf-token',
160
+ ];
161
+
162
+ for (const name of cookieNames) {
163
+ const needsSecure = isProduction || name.startsWith('__Secure-');
164
+ response.headers.append('Set-Cookie', expireCookie(name, { secure: needsSecure }));
165
+ }
166
+
167
+ // __Host- prefix cookies
168
+ for (const name of ['__Host-authjs.csrf-token', '__Host-next-auth.csrf-token']) {
169
+ response.headers.append('Set-Cookie', expireCookie(name, { hostPrefix: true }));
170
+ }
171
+
172
+ return response;
173
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Auth.js Base Configuration (Edge-compatible)
3
+ *
4
+ * This file contains ONLY Edge-runtime-compatible configuration.
5
+ * It is imported by middleware.ts for Edge middleware auth.
6
+ *
7
+ * Server-only code (database sync, events) lives in auth.ts which
8
+ * extends this config. API routes and server components use auth.ts.
9
+ *
10
+ * IMPORTANT: Do NOT add any imports of server-only modules here
11
+ * (ioredis, pg, nodemailer, platform-core barrel, etc.)
12
+ */
13
+
14
+ import Keycloak from 'next-auth/providers/keycloak';
15
+ import type { NextAuthConfig } from 'next-auth';
16
+ import {
17
+ buildKeycloakCallbacks,
18
+ buildAuthCookies,
19
+ buildRedirectCallback,
20
+ } from '@digilogiclabs/platform-core/auth';
21
+
22
+ // Extend the built-in session types
23
+ declare module 'next-auth' {
24
+ interface Session {
25
+ user: {
26
+ id: string;
27
+ email?: string | null;
28
+ name?: string | null;
29
+ image?: string | null;
30
+ roles?: string[]; // Keycloak realm roles
31
+ };
32
+ idToken?: string; // For federated logout
33
+ accessToken?: string; // For API calls
34
+ // refreshToken intentionally NOT exposed to client — used server-side only via getToken()
35
+ error?: string; // Token refresh error — client should re-authenticate
36
+ }
37
+ }
38
+
39
+ /** Keycloak callbacks — JWT token storage, role parsing, automatic refresh, session mapping */
40
+ const keycloakCallbacks = buildKeycloakCallbacks({
41
+ issuer: process.env.AUTH_KEYCLOAK_ISSUER!,
42
+ clientId: process.env.AUTH_KEYCLOAK_ID!,
43
+ clientSecret: process.env.AUTH_KEYCLOAK_SECRET!,
44
+ });
45
+
46
+ export const authConfig: NextAuthConfig = {
47
+ // Trust the host in production (required for Auth.js v5 behind reverse proxy)
48
+ trustHost: true,
49
+
50
+ // Cookie configuration for cross-domain OIDC (www/non-www compatibility).
51
+ // csrfToken uses __Host- prefix which CANNOT have a Domain attribute.
52
+ // The federated-logout route handles clearing all cookie variants.
53
+ cookies: buildAuthCookies(),
54
+
55
+ providers: [
56
+ Keycloak({
57
+ clientId: process.env.AUTH_KEYCLOAK_ID!,
58
+ clientSecret: process.env.AUTH_KEYCLOAK_SECRET!,
59
+ issuer: process.env.AUTH_KEYCLOAK_ISSUER!,
60
+ }),
61
+ ],
62
+
63
+ session: {
64
+ strategy: 'jwt',
65
+ maxAge: 30 * 24 * 60 * 60, // 30 days
66
+ },
67
+
68
+ callbacks: {
69
+ ...keycloakCallbacks,
70
+
71
+ async signIn() {
72
+ return true;
73
+ },
74
+
75
+ redirect: buildRedirectCallback(),
76
+ },
77
+
78
+ pages: {
79
+ signIn: '/auth/signin',
80
+ error: '/auth/signin',
81
+ },
82
+
83
+ debug: process.env.NODE_ENV === 'development',
84
+ };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Auth.js Server Configuration
3
+ *
4
+ * Extends the Edge-compatible auth.config.ts with server-only features
5
+ * (database sync, events, etc.). This file is used by API routes and
6
+ * server components.
7
+ *
8
+ * Middleware uses auth.config.ts directly (Edge-compatible).
9
+ */
10
+
11
+ import NextAuth from 'next-auth';
12
+ import { authConfig } from './auth.config';
13
+
14
+ export const { handlers, auth, signIn, signOut } = NextAuth({
15
+ ...authConfig,
16
+
17
+ // Server-only events — add database sync, audit logging, etc.
18
+ events: {
19
+ async signIn({ user }) {
20
+ // Optional: sync user to your database on sign-in
21
+ // const db = await getDatabase();
22
+ // await db.upsert('users', { id: user.id, email: user.email, name: user.name });
23
+ console.log(`[Auth] User signed in: ${user.email}`);
24
+ },
25
+ },
26
+ });
@@ -0,0 +1,25 @@
1
+ import { NextResponse } from 'next/server';
2
+
3
+ export const dynamic = 'force-dynamic';
4
+
5
+ /**
6
+ * GET /api/beta-settings
7
+ *
8
+ * Returns beta mode configuration. Controlled via environment variables:
9
+ * BETA_MODE - 'true'/'false' (default: true)
10
+ * REQUIRE_INVITE_CODE - 'true'/'false' (default: true)
11
+ * BETA_MESSAGE - Custom message shown to users
12
+ */
13
+ export async function GET() {
14
+ const betaMode = process.env.BETA_MODE !== 'false';
15
+ const requireInviteCode = process.env.REQUIRE_INVITE_CODE !== 'false';
16
+ const betaMessage =
17
+ process.env.BETA_MESSAGE ||
18
+ 'We are currently in private beta. Enter your invite code to continue.';
19
+
20
+ return NextResponse.json({
21
+ betaMode,
22
+ requireInviteCode,
23
+ betaMessage,
24
+ });
25
+ }
@@ -0,0 +1,67 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { enforceRateLimit, CommonRateLimits } from '@digilogiclabs/platform-core/auth';
3
+
4
+ export const dynamic = 'force-dynamic';
5
+
6
+ /**
7
+ * POST /api/validate-beta-code
8
+ *
9
+ * Validates a beta invite code against environment-defined codes.
10
+ * Rate limited to 5/min with 5-minute block to prevent brute force.
11
+ *
12
+ * Env vars:
13
+ * BETA_CODES - Comma-separated list of valid codes (e.g. "CODE1,CODE2")
14
+ */
15
+ export async function POST(request: NextRequest) {
16
+ // Rate limit: 5 attempts per minute, 5-minute block on exceed
17
+ const rateLimitResult = await enforceRateLimit(
18
+ request,
19
+ 'validate-beta-code',
20
+ CommonRateLimits.betaValidation
21
+ );
22
+ if (rateLimitResult) return rateLimitResult;
23
+
24
+ try {
25
+ const body = await request.json();
26
+ const { code } = body;
27
+
28
+ if (!code || typeof code !== 'string') {
29
+ return NextResponse.json({ valid: false, message: 'Invalid code format' });
30
+ }
31
+
32
+ const normalizedCode = code.trim().toUpperCase();
33
+
34
+ if (normalizedCode.length < 3) {
35
+ return NextResponse.json({
36
+ valid: false,
37
+ message: 'Code must be at least 3 characters',
38
+ });
39
+ }
40
+
41
+ // Get valid codes from environment
42
+ const validCodesEnv = process.env.BETA_CODES || '';
43
+ const validCodes = validCodesEnv
44
+ .split(',')
45
+ .map((c) => c.trim().toUpperCase())
46
+ .filter(Boolean);
47
+
48
+ const allValidCodes = new Set(validCodes);
49
+
50
+ if (allValidCodes.has(normalizedCode)) {
51
+ return NextResponse.json({
52
+ valid: true,
53
+ message: 'Welcome to the beta! You can now continue.',
54
+ });
55
+ }
56
+
57
+ return NextResponse.json({
58
+ valid: false,
59
+ message: 'Invalid invite code. Please check your code and try again.',
60
+ });
61
+ } catch {
62
+ return NextResponse.json(
63
+ { valid: false, message: 'Unable to validate code. Please try again.' },
64
+ { status: 500 }
65
+ );
66
+ }
67
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Beta Gate Client — thin wrapper over platform-core's createBetaClient.
3
+ *
4
+ * Pattern: each app provides its own config (endpoints, storage key,
5
+ * fail-safe defaults). The client handles all fetch/validate/store logic.
6
+ *
7
+ * Usage in components:
8
+ * import { fetchBetaSettings, validateInviteCode, storeBetaCode } from '@/lib/beta/settings'
9
+ */
10
+ import { createBetaClient, type BetaClientConfig } from '@digilogiclabs/platform-core/auth';
11
+
12
+ export type { BetaSettings } from '@digilogiclabs/platform-core';
13
+
14
+ const betaConfig: BetaClientConfig = {
15
+ storageKey: 'app_beta_code',
16
+ settingsEndpoint: '/api/beta-settings',
17
+ validateEndpoint: '/api/validate-beta-code',
18
+ failSafeDefaults: {
19
+ betaMode: true,
20
+ requireInviteCode: true,
21
+ betaMessage: 'We are currently in private beta. Enter your invite code to continue.',
22
+ },
23
+ };
24
+
25
+ const betaClient = createBetaClient(betaConfig);
26
+
27
+ export const fetchBetaSettings = betaClient.fetchSettings;
28
+ export const validateInviteCode = betaClient.validateCode;
29
+ export const storeBetaCode = betaClient.storeCode;
30
+ export const getStoredBetaCode = betaClient.getStoredCode;
31
+ export const clearStoredBetaCode = betaClient.clearStoredCode;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Cache utilities — TTL presets and HTTP cache header helpers.
3
+ *
4
+ * Provides standardized cache durations and response header generation
5
+ * for CDN and browser caching.
6
+ */
7
+
8
+ /** Standard cache TTL presets (in seconds) */
9
+ export const CacheTTL = {
10
+ /** 5 minutes — frequently changing data */
11
+ SHORT: 300,
12
+ /** 1 hour — moderately stable data */
13
+ MEDIUM: 3600,
14
+ /** 6 hours — mostly stable data */
15
+ LONG: 21600,
16
+ /** 24 hours — rarely changing data */
17
+ DAY: 86400,
18
+ /** 7 days — static content */
19
+ WEEK: 604800,
20
+ } as const;
21
+
22
+ /**
23
+ * Generate HTTP cache headers for API responses.
24
+ *
25
+ * Returns an object suitable for NextResponse headers or Response init.
26
+ * Supports CDN-specific headers for Cloudflare, Vercel, and standard proxies.
27
+ *
28
+ * @param ttl - Cache duration in seconds
29
+ * @param revalidate - Stale-while-revalidate window in seconds (default: ttl)
30
+ */
31
+ export function getCacheHeaders(ttl: number, revalidate?: number): Record<string, string> {
32
+ const swr = revalidate ?? ttl;
33
+ return {
34
+ 'Cache-Control': `public, s-maxage=${ttl}, stale-while-revalidate=${swr}`,
35
+ 'CDN-Cache-Control': `public, s-maxage=${ttl}, stale-while-revalidate=${swr}`,
36
+ 'Vercel-CDN-Cache-Control': `public, s-maxage=${ttl}, stale-while-revalidate=${swr}`,
37
+ };
38
+ }
39
+
40
+ /** No-cache headers — prevent all caching */
41
+ export const NO_CACHE_HEADERS: Record<string, string> = {
42
+ 'Cache-Control': 'no-store, no-cache, must-revalidate',
43
+ Pragma: 'no-cache',
44
+ };
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Centralized environment configuration — fail fast on missing secrets.
3
+ *
4
+ * Uses platform-core/auth helpers (getRequiredEnv, getOptionalEnv, checkEnvVars)
5
+ * so the app crashes immediately on deploy if critical env vars are missing,
6
+ * rather than failing silently at runtime when a request hits an unset secret.
7
+ *
8
+ * Skipped during build (NEXT_PHASE=phase-production-build) since env
9
+ * vars aren't available at build time in Docker/Nixpacks builds.
10
+ *
11
+ * Import this module from any server-side code to get validated, typed
12
+ * access to environment variables.
13
+ */
14
+ import 'server-only';
15
+ import { getRequiredEnv, getOptionalEnv, checkEnvVars } from '@digilogiclabs/platform-core/auth';
16
+
17
+ // ---------------------------------------------------------------------------
18
+ // Startup validation — runs once on first import
19
+ // ---------------------------------------------------------------------------
20
+
21
+ const isBuildPhase = process.env.NEXT_PHASE === 'phase-production-build';
22
+
23
+ if (!isBuildPhase) {
24
+ const envResult = checkEnvVars({
25
+ required: ['AUTH_KEYCLOAK_ID', 'AUTH_KEYCLOAK_SECRET', 'AUTH_KEYCLOAK_ISSUER', 'AUTH_SECRET'],
26
+ });
27
+
28
+ if (!envResult.valid) {
29
+ console.error('[App] Missing required environment variables:', envResult.missing);
30
+ if (process.env.NODE_ENV === 'production') {
31
+ throw new Error(`Missing required environment variables: ${envResult.missing.join(', ')}`);
32
+ }
33
+ }
34
+ }
35
+
36
+ // ---------------------------------------------------------------------------
37
+ // Centralized config — typed access to all env vars used across the app
38
+ // ---------------------------------------------------------------------------
39
+
40
+ /**
41
+ * Lazy config that reads env vars on first property access.
42
+ * Required vars use getRequiredEnv (throws if missing).
43
+ * Optional vars use getOptionalEnv (returns default).
44
+ *
45
+ * NOTE: Auth vars (AUTH_KEYCLOAK_*) are intentionally omitted here because
46
+ * auth.config.ts reads them at module scope for NextAuth configuration, and
47
+ * that file cannot import server-only modules.
48
+ */
49
+ export const config = {
50
+ /** Admin bearer token for protected API routes. */
51
+ get adminSecret(): string | undefined {
52
+ return process.env.ADMIN_SECRET;
53
+ },
54
+ /** Cron job bearer token. */
55
+ get cronSecret(): string | undefined {
56
+ return process.env.CRON_SECRET;
57
+ },
58
+ db: {
59
+ /** Database connection string. */
60
+ get url(): string {
61
+ return getRequiredEnv('DATABASE_URL');
62
+ },
63
+ },
64
+ redis: {
65
+ /** Redis connection URL. */
66
+ get url(): string | undefined {
67
+ return process.env.REDIS_URL;
68
+ },
69
+ /** Redis key prefix for namespace isolation. */
70
+ get keyPrefix(): string {
71
+ return getOptionalEnv('REDIS_KEY_PREFIX', 'app:');
72
+ },
73
+ },
74
+ email: {
75
+ /** Resend API key. */
76
+ get apiKey(): string | undefined {
77
+ return process.env.RESEND_API_KEY;
78
+ },
79
+ /** Sender address. */
80
+ get from(): string {
81
+ return getOptionalEnv('EMAIL_FROM', 'noreply@example.com');
82
+ },
83
+ },
84
+ stripe: {
85
+ /** Stripe secret key. */
86
+ get secretKey(): string {
87
+ return getRequiredEnv('STRIPE_SECRET_KEY');
88
+ },
89
+ /** Stripe webhook secret. */
90
+ get webhookSecret(): string {
91
+ return getRequiredEnv('STRIPE_WEBHOOK_SECRET');
92
+ },
93
+ },
94
+ /** Base URL for the app (used in email links, redirects). */
95
+ get baseUrl(): string {
96
+ return getOptionalEnv('NEXT_PUBLIC_APP_URL', 'http://localhost:3000');
97
+ },
98
+ /** App name. */
99
+ get appName(): string {
100
+ return getOptionalEnv('NEXT_PUBLIC_APP_NAME', 'My App');
101
+ },
102
+ beta: {
103
+ /** Master beta mode toggle. Default: true (closed beta). */
104
+ get mode(): boolean {
105
+ return process.env.BETA_MODE !== 'false';
106
+ },
107
+ /** Require invite code for signup. Default: true. */
108
+ get requireInviteCode(): boolean {
109
+ return process.env.REQUIRE_INVITE_CODE !== 'false';
110
+ },
111
+ },
112
+ } as const;
@@ -0,0 +1,62 @@
1
+ import { generateSecurityHeaders } from '@digilogiclabs/platform-core/security-headers';
2
+
3
+ /** @type {import('next').NextConfig} */
4
+ const nextConfig = {
5
+ output: 'standalone',
6
+
7
+ // Security headers — CSP, HSTS, X-Frame-Options, etc.
8
+ async headers() {
9
+ const keycloakIssuer = process.env.AUTH_KEYCLOAK_ISSUER || '';
10
+ const keycloakOrigin = keycloakIssuer ? new URL(keycloakIssuer).origin : '';
11
+
12
+ return generateSecurityHeaders({
13
+ cspConnectSrc: [
14
+ keycloakOrigin,
15
+ 'https://api.stripe.com',
16
+ ].filter(Boolean),
17
+ cspFrameSrc: [
18
+ keycloakOrigin,
19
+ 'https://js.stripe.com',
20
+ 'https://hooks.stripe.com',
21
+ ].filter(Boolean),
22
+ cspScriptSrc: ['https://js.stripe.com'],
23
+ cspImgSrc: ['https://lh3.googleusercontent.com'],
24
+ });
25
+ },
26
+
27
+ webpack: (config, { isServer }) => {
28
+ // Stub server-only packages for client bundles.
29
+ // Use $ anchor to match exact package name — preserves subpath imports
30
+ // like @digilogiclabs/platform-core/auth (Edge-safe).
31
+ if (!isServer) {
32
+ config.resolve.fallback = {
33
+ ...config.resolve.fallback,
34
+ fs: false,
35
+ net: false,
36
+ tls: false,
37
+ dns: false,
38
+ child_process: false,
39
+ 'node:stream': false,
40
+ 'node:buffer': false,
41
+ 'node:util': false,
42
+ 'node:events': false,
43
+ 'node:process': false,
44
+ };
45
+
46
+ config.resolve.alias = {
47
+ ...config.resolve.alias,
48
+ // Stub main barrel only — subpaths like /auth and /security-headers
49
+ // are Edge-safe and must NOT be stubbed.
50
+ '@digilogiclabs/platform-core$': false,
51
+ 'ioredis$': false,
52
+ 'pg$': false,
53
+ 'nodemailer$': false,
54
+ 'bullmq$': false,
55
+ };
56
+ }
57
+
58
+ return config;
59
+ },
60
+ };
61
+
62
+ export default nextConfig;