create-stackr 0.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 (274) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +642 -0
  3. package/bin/cli.js +12 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +113 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/config/dependencies.d.ts +82 -0
  9. package/dist/config/dependencies.d.ts.map +1 -0
  10. package/dist/config/dependencies.js +82 -0
  11. package/dist/config/dependencies.js.map +1 -0
  12. package/dist/config/presets.d.ts +3 -0
  13. package/dist/config/presets.d.ts.map +1 -0
  14. package/dist/config/presets.js +174 -0
  15. package/dist/config/presets.js.map +1 -0
  16. package/dist/generators/index.d.ts +40 -0
  17. package/dist/generators/index.d.ts.map +1 -0
  18. package/dist/generators/index.js +130 -0
  19. package/dist/generators/index.js.map +1 -0
  20. package/dist/generators/onboarding.d.ts +8 -0
  21. package/dist/generators/onboarding.d.ts.map +1 -0
  22. package/dist/generators/onboarding.js +141 -0
  23. package/dist/generators/onboarding.js.map +1 -0
  24. package/dist/index.d.ts +3 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +65 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/prompts/features.d.ts +14 -0
  29. package/dist/prompts/features.d.ts.map +1 -0
  30. package/dist/prompts/features.js +96 -0
  31. package/dist/prompts/features.js.map +1 -0
  32. package/dist/prompts/index.d.ts +3 -0
  33. package/dist/prompts/index.d.ts.map +1 -0
  34. package/dist/prompts/index.js +93 -0
  35. package/dist/prompts/index.js.map +1 -0
  36. package/dist/prompts/onboarding.d.ts +6 -0
  37. package/dist/prompts/onboarding.d.ts.map +1 -0
  38. package/dist/prompts/onboarding.js +37 -0
  39. package/dist/prompts/onboarding.js.map +1 -0
  40. package/dist/prompts/orm.d.ts +3 -0
  41. package/dist/prompts/orm.d.ts.map +1 -0
  42. package/dist/prompts/orm.js +23 -0
  43. package/dist/prompts/orm.js.map +1 -0
  44. package/dist/prompts/packageManager.d.ts +2 -0
  45. package/dist/prompts/packageManager.d.ts.map +1 -0
  46. package/dist/prompts/packageManager.js +18 -0
  47. package/dist/prompts/packageManager.js.map +1 -0
  48. package/dist/prompts/platform.d.ts +3 -0
  49. package/dist/prompts/platform.d.ts.map +1 -0
  50. package/dist/prompts/platform.js +21 -0
  51. package/dist/prompts/platform.js.map +1 -0
  52. package/dist/prompts/preset.d.ts +4 -0
  53. package/dist/prompts/preset.d.ts.map +1 -0
  54. package/dist/prompts/preset.js +165 -0
  55. package/dist/prompts/preset.js.map +1 -0
  56. package/dist/prompts/project.d.ts +2 -0
  57. package/dist/prompts/project.d.ts.map +1 -0
  58. package/dist/prompts/project.js +27 -0
  59. package/dist/prompts/project.js.map +1 -0
  60. package/dist/prompts/sdks.d.ts +2 -0
  61. package/dist/prompts/sdks.d.ts.map +1 -0
  62. package/dist/prompts/sdks.js +46 -0
  63. package/dist/prompts/sdks.js.map +1 -0
  64. package/dist/types/index.d.ts +77 -0
  65. package/dist/types/index.d.ts.map +1 -0
  66. package/dist/types/index.js +25 -0
  67. package/dist/types/index.js.map +1 -0
  68. package/dist/utils/cleanup.d.ts +5 -0
  69. package/dist/utils/cleanup.d.ts.map +1 -0
  70. package/dist/utils/cleanup.js +38 -0
  71. package/dist/utils/cleanup.js.map +1 -0
  72. package/dist/utils/copy.d.ts +10 -0
  73. package/dist/utils/copy.d.ts.map +1 -0
  74. package/dist/utils/copy.js +53 -0
  75. package/dist/utils/copy.js.map +1 -0
  76. package/dist/utils/errors.d.ts +33 -0
  77. package/dist/utils/errors.d.ts.map +1 -0
  78. package/dist/utils/errors.js +136 -0
  79. package/dist/utils/errors.js.map +1 -0
  80. package/dist/utils/git.d.ts +5 -0
  81. package/dist/utils/git.d.ts.map +1 -0
  82. package/dist/utils/git.js +33 -0
  83. package/dist/utils/git.js.map +1 -0
  84. package/dist/utils/logger.d.ts +9 -0
  85. package/dist/utils/logger.d.ts.map +1 -0
  86. package/dist/utils/logger.js +22 -0
  87. package/dist/utils/logger.js.map +1 -0
  88. package/dist/utils/package.d.ts +16 -0
  89. package/dist/utils/package.d.ts.map +1 -0
  90. package/dist/utils/package.js +86 -0
  91. package/dist/utils/package.js.map +1 -0
  92. package/dist/utils/system-validation.d.ts +9 -0
  93. package/dist/utils/system-validation.d.ts.map +1 -0
  94. package/dist/utils/system-validation.js +31 -0
  95. package/dist/utils/system-validation.js.map +1 -0
  96. package/dist/utils/template.d.ts +20 -0
  97. package/dist/utils/template.d.ts.map +1 -0
  98. package/dist/utils/template.js +234 -0
  99. package/dist/utils/template.js.map +1 -0
  100. package/dist/utils/validation.d.ts +8 -0
  101. package/dist/utils/validation.d.ts.map +1 -0
  102. package/dist/utils/validation.js +94 -0
  103. package/dist/utils/validation.js.map +1 -0
  104. package/package.json +96 -0
  105. package/templates/base/backend/.dockerignore.ejs +62 -0
  106. package/templates/base/backend/.env.example.ejs +116 -0
  107. package/templates/base/backend/Dockerfile.ejs +142 -0
  108. package/templates/base/backend/controllers/event-queue/index.ts +20 -0
  109. package/templates/base/backend/controllers/event-queue/workers/user.ts +39 -0
  110. package/templates/base/backend/controllers/rest-api/index.ts +48 -0
  111. package/templates/base/backend/controllers/rest-api/plugins/auth.ts +152 -0
  112. package/templates/base/backend/controllers/rest-api/plugins/config.ts +64 -0
  113. package/templates/base/backend/controllers/rest-api/plugins/error-handler.ts +118 -0
  114. package/templates/base/backend/controllers/rest-api/routes/auth.ts.ejs +180 -0
  115. package/templates/base/backend/controllers/rest-api/routes/device-sessions.ts +197 -0
  116. package/templates/base/backend/controllers/rest-api/routes/oauth-web.ts.ejs +375 -0
  117. package/templates/base/backend/controllers/rest-api/server.ts.ejs +87 -0
  118. package/templates/base/backend/domain/device-session/repository.drizzle.ts +209 -0
  119. package/templates/base/backend/domain/device-session/repository.prisma.ts +248 -0
  120. package/templates/base/backend/domain/device-session/schema.ts +72 -0
  121. package/templates/base/backend/domain/session/repository.drizzle.ts +72 -0
  122. package/templates/base/backend/domain/session/repository.prisma.ts +72 -0
  123. package/templates/base/backend/domain/session/schema.ts +29 -0
  124. package/templates/base/backend/domain/user/repository.drizzle.ts +127 -0
  125. package/templates/base/backend/domain/user/repository.prisma.ts +115 -0
  126. package/templates/base/backend/domain/user/schema.ts +14 -0
  127. package/templates/base/backend/drizzle/schema.drizzle.ts +111 -0
  128. package/templates/base/backend/drizzle.config.drizzle.ts +13 -0
  129. package/templates/base/backend/lib/auth.drizzle.ts.ejs +104 -0
  130. package/templates/base/backend/lib/auth.prisma.ts.ejs +97 -0
  131. package/templates/base/backend/lib/constants.ts.ejs +29 -0
  132. package/templates/base/backend/package.json.ejs +50 -0
  133. package/templates/base/backend/prisma/schema.prisma.ejs +102 -0
  134. package/templates/base/backend/prisma.config.prisma.ts +12 -0
  135. package/templates/base/backend/tsconfig.json +39 -0
  136. package/templates/base/backend/utils/db.drizzle.ts +41 -0
  137. package/templates/base/backend/utils/db.prisma.ts +51 -0
  138. package/templates/base/backend/utils/email.ts.ejs +35 -0
  139. package/templates/base/backend/utils/errors.ts +348 -0
  140. package/templates/base/backend/utils/redis.ts.ejs +279 -0
  141. package/templates/base/mobile/.env.example.ejs +35 -0
  142. package/templates/base/mobile/.gitignore.ejs +167 -0
  143. package/templates/base/mobile/app/+not-found.tsx +85 -0
  144. package/templates/base/mobile/app/_layout.tsx.ejs +71 -0
  145. package/templates/base/mobile/app.json.ejs +88 -0
  146. package/templates/base/mobile/assets/images/adaptive-icon.png +0 -0
  147. package/templates/base/mobile/assets/images/favicon.png +0 -0
  148. package/templates/base/mobile/assets/images/icon.png +0 -0
  149. package/templates/base/mobile/assets/images/onboarding_page_1.png +0 -0
  150. package/templates/base/mobile/assets/images/onboarding_page_2.png +0 -0
  151. package/templates/base/mobile/assets/images/onboarding_page_3.png +0 -0
  152. package/templates/base/mobile/assets/images/paywall_image.png +0 -0
  153. package/templates/base/mobile/assets/images/splash.png +0 -0
  154. package/templates/base/mobile/eas.json.ejs +49 -0
  155. package/templates/base/mobile/metro.config.js +9 -0
  156. package/templates/base/mobile/package.json.ejs +53 -0
  157. package/templates/base/mobile/src/components/ui/Button.tsx +131 -0
  158. package/templates/base/mobile/src/components/ui/Card.tsx +68 -0
  159. package/templates/base/mobile/src/components/ui/IconSymbol.tsx +90 -0
  160. package/templates/base/mobile/src/components/ui/Input.tsx +142 -0
  161. package/templates/base/mobile/src/components/ui/LoadingSpinner.tsx +98 -0
  162. package/templates/base/mobile/src/components/ui/OnboardingLayout.tsx +356 -0
  163. package/templates/base/mobile/src/components/ui/PaywallLayout.tsx +311 -0
  164. package/templates/base/mobile/src/components/ui/Skeleton.tsx +58 -0
  165. package/templates/base/mobile/src/components/ui/index.ts +6 -0
  166. package/templates/base/mobile/src/constants/Theme.ts +163 -0
  167. package/templates/base/mobile/src/context/ThemeContext.tsx +157 -0
  168. package/templates/base/mobile/src/lib/auth-client.ts.ejs +51 -0
  169. package/templates/base/mobile/src/services/api.ts.ejs +71 -0
  170. package/templates/base/mobile/src/services/errorService.ts +179 -0
  171. package/templates/base/mobile/src/services/sdkInitializer.ts.ejs +36 -0
  172. package/templates/base/mobile/src/store/index.ts.ejs +18 -0
  173. package/templates/base/mobile/src/store/ui.store.ts +100 -0
  174. package/templates/base/mobile/src/utils/formatters.ts +105 -0
  175. package/templates/base/mobile/src/utils/logger.ts +73 -0
  176. package/templates/base/mobile/src/utils/responsive.ts +234 -0
  177. package/templates/base/mobile/tsconfig.json +32 -0
  178. package/templates/base/web/.env.example.ejs +26 -0
  179. package/templates/base/web/components.json +22 -0
  180. package/templates/base/web/eslint.config.mjs +18 -0
  181. package/templates/base/web/next.config.ts +7 -0
  182. package/templates/base/web/package.json.ejs +35 -0
  183. package/templates/base/web/postcss.config.mjs +7 -0
  184. package/templates/base/web/public/.gitkeep +0 -0
  185. package/templates/base/web/public/file.svg +1 -0
  186. package/templates/base/web/public/globe.svg +1 -0
  187. package/templates/base/web/public/next.svg +1 -0
  188. package/templates/base/web/public/vercel.svg +1 -0
  189. package/templates/base/web/public/window.svg +1 -0
  190. package/templates/base/web/src/app/favicon.ico +0 -0
  191. package/templates/base/web/src/app/globals.css +152 -0
  192. package/templates/base/web/src/app/layout.tsx.ejs +54 -0
  193. package/templates/base/web/src/app/page.tsx.ejs +92 -0
  194. package/templates/base/web/src/components/auth/auth-hydrator.tsx.ejs +19 -0
  195. package/templates/base/web/src/components/auth/protected-route.tsx.ejs +109 -0
  196. package/templates/base/web/src/components/providers/device-session-setup.tsx.ejs +56 -0
  197. package/templates/base/web/src/components/providers/theme-provider.tsx +17 -0
  198. package/templates/base/web/src/components/theme-toggle.tsx +34 -0
  199. package/templates/base/web/src/components/ui/button.tsx +62 -0
  200. package/templates/base/web/src/components/ui/card.tsx +92 -0
  201. package/templates/base/web/src/components/ui/input.tsx +21 -0
  202. package/templates/base/web/src/components/ui/label.tsx +24 -0
  203. package/templates/base/web/src/components/ui/skeleton.tsx +13 -0
  204. package/templates/base/web/src/components/ui/spinner.tsx +20 -0
  205. package/templates/base/web/src/hooks/use-device-session.ts.ejs +40 -0
  206. package/templates/base/web/src/hooks/use-session.ts.ejs +56 -0
  207. package/templates/base/web/src/lib/auth/actions.ts.ejs +334 -0
  208. package/templates/base/web/src/lib/auth/config.ts.ejs +65 -0
  209. package/templates/base/web/src/lib/auth/cookies.ts.ejs +74 -0
  210. package/templates/base/web/src/lib/auth/index.ts.ejs +40 -0
  211. package/templates/base/web/src/lib/auth/oauth.ts.ejs +72 -0
  212. package/templates/base/web/src/lib/auth/pkce.ts.ejs +48 -0
  213. package/templates/base/web/src/lib/auth/sessions.ts.ejs +135 -0
  214. package/templates/base/web/src/lib/auth/user-agent.ts.ejs +47 -0
  215. package/templates/base/web/src/lib/device/actions.ts.ejs +148 -0
  216. package/templates/base/web/src/lib/device/id.ts.ejs +74 -0
  217. package/templates/base/web/src/lib/utils.ts +6 -0
  218. package/templates/base/web/src/proxy.ts.ejs +66 -0
  219. package/templates/base/web/src/store/auth.store.ts.ejs +89 -0
  220. package/templates/base/web/src/store/deviceSession.store.ts.ejs +141 -0
  221. package/templates/base/web/tsconfig.json +34 -0
  222. package/templates/features/mobile/auth/app/(auth)/_layout.tsx +16 -0
  223. package/templates/features/mobile/auth/app/(auth)/login.tsx +86 -0
  224. package/templates/features/mobile/auth/app/(auth)/register.tsx +86 -0
  225. package/templates/features/mobile/auth/components/auth/LoginForm.tsx.ejs +349 -0
  226. package/templates/features/mobile/auth/components/auth/RegisterForm.tsx.ejs +407 -0
  227. package/templates/features/mobile/auth/components/auth/index.ts +2 -0
  228. package/templates/features/mobile/auth/hooks/index.ts.ejs +1 -0
  229. package/templates/features/mobile/auth/hooks/useAuth.ts.ejs +367 -0
  230. package/templates/features/mobile/auth/services/deviceSession.ts +370 -0
  231. package/templates/features/mobile/auth/store/deviceSession.store.ts +326 -0
  232. package/templates/features/mobile/onboarding/app/(onboarding)/_layout.tsx.ejs +11 -0
  233. package/templates/features/mobile/onboarding/app/(onboarding)/page-1.tsx.ejs +52 -0
  234. package/templates/features/mobile/onboarding/app/(onboarding)/page-2.tsx.ejs +52 -0
  235. package/templates/features/mobile/onboarding/app/(onboarding)/page-3.tsx.ejs +60 -0
  236. package/templates/features/mobile/paywall/app/paywall.tsx +550 -0
  237. package/templates/features/mobile/tabs/app/(tabs)/_layout.tsx +26 -0
  238. package/templates/features/mobile/tabs/app/(tabs)/index.tsx +565 -0
  239. package/templates/features/web/.gitkeep +0 -0
  240. package/templates/features/web/auth/app/(app)/dashboard/dashboard-client.tsx.ejs +166 -0
  241. package/templates/features/web/auth/app/(app)/dashboard/page.tsx.ejs +24 -0
  242. package/templates/features/web/auth/app/(app)/layout.tsx.ejs +43 -0
  243. package/templates/features/web/auth/app/(app)/settings/sessions/page.tsx.ejs +29 -0
  244. package/templates/features/web/auth/app/(app)/settings/sessions/sessions-client.tsx.ejs +77 -0
  245. package/templates/features/web/auth/app/(auth)/forgot-password/page.tsx.ejs +127 -0
  246. package/templates/features/web/auth/app/(auth)/layout.tsx.ejs +32 -0
  247. package/templates/features/web/auth/app/(auth)/login/page.tsx.ejs +35 -0
  248. package/templates/features/web/auth/app/(auth)/register/page.tsx.ejs +19 -0
  249. package/templates/features/web/auth/app/(auth)/reset-password/page.tsx.ejs +40 -0
  250. package/templates/features/web/auth/app/(auth)/verify-email/page.tsx.ejs +198 -0
  251. package/templates/features/web/auth/app/auth/callback/route.ts.ejs +152 -0
  252. package/templates/features/web/auth/components/auth/login-form.tsx.ejs +100 -0
  253. package/templates/features/web/auth/components/auth/oauth-buttons.tsx.ejs +126 -0
  254. package/templates/features/web/auth/components/auth/password-reset-form.tsx.ejs +103 -0
  255. package/templates/features/web/auth/components/auth/register-form.tsx.ejs +139 -0
  256. package/templates/features/web/auth/components/settings/session-card.tsx.ejs +132 -0
  257. package/templates/integrations/mobile/adjust/services/adjustService.ts.ejs +163 -0
  258. package/templates/integrations/mobile/adjust/store/adjust.store.ts +243 -0
  259. package/templates/integrations/mobile/att/services/attService.ts +84 -0
  260. package/templates/integrations/mobile/att/services/trackingPermissions.ts +208 -0
  261. package/templates/integrations/mobile/att/store/att.store.ts +162 -0
  262. package/templates/integrations/mobile/revenuecat/services/revenuecatService.ts.ejs +174 -0
  263. package/templates/integrations/mobile/revenuecat/store/revenuecat.store.ts +286 -0
  264. package/templates/integrations/mobile/scate/services/scateService.ts.ejs +85 -0
  265. package/templates/integrations/mobile/scate/store/scate.store.ts +125 -0
  266. package/templates/integrations/web/.gitkeep +0 -0
  267. package/templates/shared/.env.example.ejs +21 -0
  268. package/templates/shared/.gitignore.ejs +145 -0
  269. package/templates/shared/README.md.ejs +134 -0
  270. package/templates/shared/docker-compose.prod.yml.ejs +120 -0
  271. package/templates/shared/docker-compose.yml.ejs +129 -0
  272. package/templates/shared/scripts/docker-dev.sh.ejs +395 -0
  273. package/templates/shared/scripts/docker-prod.sh.ejs +542 -0
  274. package/templates/shared/scripts/setup.sh.ejs +979 -0
@@ -0,0 +1,542 @@
1
+ #!/bin/bash
2
+
3
+ # Production Environment Docker Script
4
+ # Manages the production Docker deployment
5
+
6
+ set -e
7
+
8
+ # Colors for output
9
+ RED='\033[0;31m'
10
+ GREEN='\033[0;32m'
11
+ YELLOW='\033[1;33m'
12
+ BLUE='\033[0;34m'
13
+ NC='\033[0m'
14
+
15
+ print_status() {
16
+ echo -e "${GREEN}✓${NC} $1"
17
+ }
18
+
19
+ print_info() {
20
+ echo -e "${BLUE}ℹ${NC} $1"
21
+ }
22
+
23
+ print_warning() {
24
+ echo -e "${YELLOW}⚠${NC} $1"
25
+ }
26
+
27
+ print_error() {
28
+ echo -e "${RED}✗${NC} $1"
29
+ }
30
+
31
+ # Function to show usage
32
+ usage() {
33
+ echo "Full-Stack Auth Boilerplate - Production Environment"
34
+ echo "================================================"
35
+ echo ""
36
+ echo "Usage: $0 [COMMAND] [OPTIONS]"
37
+ echo ""
38
+ echo "Commands:"
39
+ echo " deploy Deploy to production"
40
+ echo " stop Stop production environment"
41
+ echo " restart Restart production environment"
42
+ echo " logs Show logs (specify service)"
43
+ echo " status Show status of all services"
44
+ echo " backup Create database backup"
45
+ echo " restore Restore from database backup"
46
+ echo " update Update services (pull latest images)"
47
+ echo " scale Scale services (e.g., backend=3)"
48
+ echo ""
49
+ echo "Options:"
50
+ echo " --with-nginx Include Nginx reverse proxy"
51
+ <% if (backend.eventQueue) { %>
52
+ echo " --with-redis Include Redis service"
53
+ <% } %>
54
+ echo " --build Force rebuild containers"
55
+ echo " --no-backup Skip automatic backup before deploy"
56
+ echo " --only-rest-api Deploy only REST API service"
57
+ <% if (backend.eventQueue) { %>
58
+ echo " --only-event-queue Deploy only Event Queue service"
59
+ <% } %>
60
+ echo ""
61
+ echo "Examples:"
62
+ echo " $0 deploy # Deploy all services"
63
+ echo " $0 deploy --with-nginx # Deploy with Nginx"
64
+ echo " $0 deploy --only-rest-api # Deploy only REST API"
65
+ echo " $0 logs rest-api # Show REST API logs"
66
+ <% if (backend.eventQueue) { %>
67
+ echo " $0 logs event-queue # Show Event Queue logs"
68
+ <% } %>
69
+ echo " $0 backup # Create database backup"
70
+ <% if (backend.eventQueue) { %>
71
+ echo " $0 scale rest-api=2 event-queue=1 # Scale services independently"
72
+ <% } else { %>
73
+ echo " $0 scale rest-api=2 # Scale services"
74
+ <% } %>
75
+ echo ""
76
+ }
77
+
78
+ # Parse command line arguments
79
+ parse_args() {
80
+ COMMAND=""
81
+ SERVICE=""
82
+ SCALE_ARGS=""
83
+ WITH_NGINX=false
84
+ <% if (backend.eventQueue) { %>
85
+ WITH_REDIS=false
86
+ <% } %>
87
+ FORCE_BUILD=false
88
+ NO_BACKUP=false
89
+ ONLY_REST_API=false
90
+ <% if (backend.eventQueue) { %>
91
+ ONLY_EVENT_QUEUE=false
92
+ <% } %>
93
+
94
+ while [[ $# -gt 0 ]]; do
95
+ case $1 in
96
+ deploy|stop|restart|logs|status|backup|restore|update|scale)
97
+ COMMAND="$1"
98
+ shift
99
+ ;;
100
+ rest-api<% if (backend.eventQueue) { %>|event-queue<% } %>|database<% if (backend.eventQueue) { %>|redis<% } %>|nginx)
101
+ SERVICE="$1"
102
+ shift
103
+ ;;
104
+ *=*)
105
+ SCALE_ARGS="$1"
106
+ shift
107
+ ;;
108
+ --with-nginx)
109
+ WITH_NGINX=true
110
+ shift
111
+ ;;
112
+ <% if (backend.eventQueue) { %>
113
+ --with-redis)
114
+ WITH_REDIS=true
115
+ shift
116
+ ;;
117
+ <% } %>
118
+ --build)
119
+ FORCE_BUILD=true
120
+ shift
121
+ ;;
122
+ --no-backup)
123
+ NO_BACKUP=true
124
+ shift
125
+ ;;
126
+ --only-rest-api)
127
+ ONLY_REST_API=true
128
+ shift
129
+ ;;
130
+ <% if (backend.eventQueue) { %>
131
+ --only-event-queue)
132
+ ONLY_EVENT_QUEUE=true
133
+ shift
134
+ ;;
135
+ <% } %>
136
+ -h|--help)
137
+ usage
138
+ exit 0
139
+ ;;
140
+ *)
141
+ echo "Unknown option: $1"
142
+ usage
143
+ exit 1
144
+ ;;
145
+ esac
146
+ done
147
+
148
+ if [ -z "$COMMAND" ]; then
149
+ usage
150
+ exit 1
151
+ fi
152
+ }
153
+
154
+ # Check production requirements
155
+ check_production_requirements() {
156
+ print_info "Checking production requirements..."
157
+
158
+ # Check if .env file exists
159
+ if [ ! -f ".env" ]; then
160
+ print_error "Production .env file is missing!"
161
+ print_info "Create a .env file with production configuration"
162
+ exit 1
163
+ fi
164
+
165
+ # Check critical environment variables
166
+ source .env
167
+
168
+ if [ -z "$JWT_SECRET" ] || [ "$JWT_SECRET" = "dev-jwt-secret-change-in-production" ]; then
169
+ print_error "JWT_SECRET is not set or using default value!"
170
+ print_info "Set a strong JWT_SECRET in your .env file"
171
+ exit 1
172
+ fi
173
+
174
+ if [ -z "$DB_PASSWORD" ] || [ "$DB_PASSWORD" = "postgres" ]; then
175
+ print_error "DB_PASSWORD is not set or using default value!"
176
+ print_info "Set a strong DB_PASSWORD in your .env file"
177
+ exit 1
178
+ fi
179
+
180
+ print_status "Production requirements check passed"
181
+ }
182
+
183
+ # Build compose command with profiles
184
+ build_compose_cmd() {
185
+ local cmd="docker-compose -f docker-compose.prod.yml"
186
+
187
+ # Handle microservices profiles
188
+ if [ "$ONLY_REST_API" = true ]; then
189
+ cmd="$cmd --profile rest-api"
190
+ <% if (backend.eventQueue) { %>
191
+ elif [ "$ONLY_EVENT_QUEUE" = true ]; then
192
+ cmd="$cmd --profile event-queue"
193
+ <% } %>
194
+ else
195
+ cmd="$cmd --profile all"
196
+ fi
197
+
198
+ if [ "$WITH_NGINX" = true ]; then
199
+ cmd="$cmd --profile with-nginx"
200
+ fi
201
+
202
+ <% if (backend.eventQueue) { %>
203
+ if [ "$WITH_REDIS" = true ]; then
204
+ cmd="$cmd --profile with-redis"
205
+ fi
206
+
207
+ <% } %>
208
+ echo "$cmd"
209
+ }
210
+
211
+ # Create backup before deployment
212
+ create_backup() {
213
+ if [ "$NO_BACKUP" = true ]; then
214
+ print_info "Skipping backup (--no-backup flag used)"
215
+ return
216
+ fi
217
+
218
+ print_info "Creating pre-deployment backup..."
219
+
220
+ # Create backups directory
221
+ mkdir -p backups
222
+
223
+ # Run backup service
224
+ docker-compose -f docker-compose.prod.yml --profile backup run --rm backup
225
+
226
+ print_status "Backup created successfully"
227
+ }
228
+
229
+ # Deploy to production
230
+ deploy_production() {
231
+ check_production_requirements
232
+
233
+ local compose_cmd=$(build_compose_cmd)
234
+
235
+ print_info "Deploying to production environment..."
236
+
237
+ # Create backup if database is running
238
+ if docker ps | grep -q "auth_boilerplate_db_prod"; then
239
+ create_backup
240
+ fi
241
+
242
+ if [ "$FORCE_BUILD" = true ]; then
243
+ print_info "Force rebuilding containers..."
244
+ $compose_cmd build --no-cache
245
+ fi
246
+
247
+ # Pull latest images
248
+ $compose_cmd pull
249
+
250
+ # Deploy with zero-downtime strategy
251
+ $compose_cmd up -d --remove-orphans
252
+
253
+ # Wait for services to be healthy
254
+ print_info "Waiting for services to be healthy..."
255
+ sleep 30
256
+
257
+ # Check service health
258
+ if health_check_silent; then
259
+ print_status "Production deployment successful!"
260
+ show_production_info
261
+ else
262
+ print_error "Deployment health check failed!"
263
+ print_info "Check logs: $0 logs"
264
+ exit 1
265
+ fi
266
+ }
267
+
268
+ # Stop production services
269
+ stop_production() {
270
+ local compose_cmd=$(build_compose_cmd)
271
+
272
+ print_warning "Stopping production environment..."
273
+ read -p "Are you sure you want to stop production services? (y/N): " -n 1 -r
274
+ echo
275
+
276
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
277
+ $compose_cmd down
278
+ print_status "Production services stopped"
279
+ else
280
+ print_info "Operation cancelled"
281
+ fi
282
+ }
283
+
284
+ # Restart production services
285
+ restart_production() {
286
+ local compose_cmd=$(build_compose_cmd)
287
+
288
+ print_info "Restarting production environment..."
289
+
290
+ if [ "$FORCE_BUILD" = true ]; then
291
+ create_backup
292
+ $compose_cmd down
293
+ $compose_cmd build --no-cache
294
+ $compose_cmd up -d
295
+ else
296
+ $compose_cmd restart
297
+ fi
298
+
299
+ print_status "Production services restarted"
300
+ }
301
+
302
+ # Show logs
303
+ show_logs() {
304
+ local compose_cmd=$(build_compose_cmd)
305
+
306
+ if [ -n "$SERVICE" ]; then
307
+ print_info "Showing logs for $SERVICE..."
308
+ $compose_cmd logs -f --tail=100 "$SERVICE"
309
+ else
310
+ print_info "Showing logs for all services..."
311
+ $compose_cmd logs -f --tail=100
312
+ fi
313
+ }
314
+
315
+ # Show status
316
+ show_status() {
317
+ local compose_cmd=$(build_compose_cmd)
318
+
319
+ print_info "Production Service Status:"
320
+ $compose_cmd ps
321
+
322
+ echo ""
323
+ print_info "Container Health:"
324
+ docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep auth_boilerplate_.*_prod || echo "No production containers running"
325
+
326
+ echo ""
327
+ print_info "Resource Usage:"
328
+ docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}" | grep auth_boilerplate || echo "No containers running"
329
+ }
330
+
331
+ # Create database backup
332
+ create_database_backup() {
333
+ print_info "Creating database backup..."
334
+
335
+ # Ensure backups directory exists
336
+ mkdir -p backups
337
+
338
+ # Run backup service
339
+ docker-compose -f docker-compose.prod.yml --profile backup run --rm backup
340
+
341
+ print_status "Database backup completed"
342
+
343
+ # List recent backups
344
+ print_info "Recent backups:"
345
+ ls -la backups/backup_*.sql.gz 2>/dev/null | tail -5 || echo "No backups found"
346
+ }
347
+
348
+ # Restore from backup
349
+ restore_database() {
350
+ print_warning "This will restore the database from a backup!"
351
+ print_warning "ALL CURRENT DATA WILL BE LOST!"
352
+
353
+ # List available backups
354
+ echo ""
355
+ print_info "Available backups:"
356
+ ls -la backups/backup_*.sql.gz 2>/dev/null || {
357
+ print_error "No backups found!"
358
+ exit 1
359
+ }
360
+
361
+ echo ""
362
+ read -p "Enter backup filename: " backup_file
363
+
364
+ if [ ! -f "backups/$backup_file" ]; then
365
+ print_error "Backup file not found: $backup_file"
366
+ exit 1
367
+ fi
368
+
369
+ read -p "Are you sure you want to restore from $backup_file? (y/N): " -n 1 -r
370
+ echo
371
+
372
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
373
+ print_info "Restoring database from $backup_file..."
374
+
375
+ # Stop services to prevent connections
376
+ <% if (backend.eventQueue) { %>
377
+ docker-compose -f docker-compose.prod.yml stop rest-api event-queue 2>/dev/null || true
378
+ <% } else { %>
379
+ docker-compose -f docker-compose.prod.yml stop rest-api 2>/dev/null || true
380
+ <% } %>
381
+
382
+ # Restore database
383
+ gunzip -c "backups/$backup_file" | docker-compose -f docker-compose.prod.yml exec -T database psql -U postgres -d auth_boilerplate
384
+
385
+ # Start services
386
+ <% if (backend.eventQueue) { %>
387
+ docker-compose -f docker-compose.prod.yml start rest-api event-queue 2>/dev/null || true
388
+ <% } else { %>
389
+ docker-compose -f docker-compose.prod.yml start rest-api 2>/dev/null || true
390
+ <% } %>
391
+
392
+ print_status "Database restore completed"
393
+ else
394
+ print_info "Restore cancelled"
395
+ fi
396
+ }
397
+
398
+ # Update services
399
+ update_services() {
400
+ local compose_cmd=$(build_compose_cmd)
401
+
402
+ print_info "Updating production services..."
403
+
404
+ # Create backup first
405
+ create_backup
406
+
407
+ # Pull latest images
408
+ $compose_cmd pull
409
+
410
+ # Restart services with new images
411
+ $compose_cmd up -d --remove-orphans
412
+
413
+ print_status "Services updated successfully"
414
+ }
415
+
416
+ # Scale services
417
+ scale_services() {
418
+ if [ -z "$SCALE_ARGS" ]; then
419
+ print_error "No scale arguments provided!"
420
+ <% if (backend.eventQueue) { %>
421
+ print_info "Example: $0 scale rest-api=2 event-queue=1"
422
+ <% } else { %>
423
+ print_info "Example: $0 scale rest-api=2"
424
+ <% } %>
425
+ exit 1
426
+ fi
427
+
428
+ local compose_cmd=$(build_compose_cmd)
429
+
430
+ print_info "Scaling services: $SCALE_ARGS"
431
+ $compose_cmd up -d --scale $SCALE_ARGS
432
+
433
+ print_status "Services scaled successfully"
434
+ }
435
+
436
+ # Silent health check
437
+ health_check_silent() {
438
+ # Check REST API if it's running
439
+ if docker ps | grep -q "rest_api.*Up" && curl -sf http://localhost:8080/ > /dev/null 2>&1; then
440
+ return 0
441
+ <% if (backend.eventQueue) { %>
442
+ elif [ "$ONLY_EVENT_QUEUE" = true ]; then
443
+ # If only event queue is deployed, check if it's running
444
+ if docker ps | grep -q "event_queue.*Up"; then
445
+ return 0
446
+ fi
447
+ <% } %>
448
+ fi
449
+
450
+ return 1
451
+ }
452
+
453
+ # Show production info
454
+ show_production_info() {
455
+ echo ""
456
+ print_info "Production Services:"
457
+
458
+ if [ "$ONLY_REST_API" = true ]; then
459
+ echo " 🌐 REST API: http://localhost:8080"
460
+ <% if (backend.eventQueue) { %>
461
+ elif [ "$ONLY_EVENT_QUEUE" = true ]; then
462
+ echo " 📋 Event Queue: Running in background (no HTTP interface)"
463
+ <% } %>
464
+ else
465
+ echo " 🌐 REST API: http://localhost:8080"
466
+ <% if (backend.eventQueue) { %>
467
+ echo " 📋 Event Queue: Running in background (no HTTP interface)"
468
+ <% } %>
469
+ fi
470
+
471
+ echo " 🗄️ Database: localhost:5432"
472
+
473
+ if [ "$WITH_NGINX" = true ]; then
474
+ echo " 🔧 Nginx: http://localhost"
475
+ fi
476
+
477
+ <% if (backend.eventQueue) { %>
478
+ if [ "$WITH_REDIS" = true ]; then
479
+ echo " 🔄 Redis: localhost:6379"
480
+ fi
481
+
482
+ <% } %>
483
+ echo ""
484
+ print_info "Monitoring commands:"
485
+ echo " $0 logs # View all logs"
486
+ echo " $0 logs rest-api # View REST API logs"
487
+ <% if (backend.eventQueue) { %>
488
+ echo " $0 logs event-queue # View Event Queue logs"
489
+ <% } %>
490
+ echo " $0 status # Check service status"
491
+ echo " $0 backup # Create backup"
492
+ }
493
+
494
+ # Main execution
495
+ main() {
496
+ # Check if we're in the right directory
497
+ if [ ! -f "docker-compose.prod.yml" ]; then
498
+ print_error "docker-compose.prod.yml not found!"
499
+ print_info "Please run this script from the project root directory"
500
+ exit 1
501
+ fi
502
+
503
+ parse_args "$@"
504
+
505
+ case $COMMAND in
506
+ deploy)
507
+ deploy_production
508
+ ;;
509
+ stop)
510
+ stop_production
511
+ ;;
512
+ restart)
513
+ restart_production
514
+ ;;
515
+ logs)
516
+ show_logs
517
+ ;;
518
+ status)
519
+ show_status
520
+ ;;
521
+ backup)
522
+ create_database_backup
523
+ ;;
524
+ restore)
525
+ restore_database
526
+ ;;
527
+ update)
528
+ update_services
529
+ ;;
530
+ scale)
531
+ scale_services
532
+ ;;
533
+ *)
534
+ print_error "Unknown command: $COMMAND"
535
+ usage
536
+ exit 1
537
+ ;;
538
+ esac
539
+ }
540
+
541
+ # Run main function
542
+ main "$@"