openship 0.1.0 → 0.1.1

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 (531) hide show
  1. package/.env.example +19 -3
  2. package/CONTRIBUTING.md +69 -19
  3. package/LICENSE +661 -0
  4. package/README.md +304 -108
  5. package/apps/api/Dockerfile +6 -8
  6. package/apps/api/package.json +25 -21
  7. package/apps/api/src/app.ts +46 -3
  8. package/apps/api/src/config/env.ts +81 -7
  9. package/apps/api/src/lib/auth-mode.ts +42 -0
  10. package/apps/api/src/lib/auth.ts +105 -0
  11. package/apps/api/src/lib/cache.ts +128 -0
  12. package/apps/api/src/lib/cloud-auth-proxy.ts +310 -0
  13. package/apps/api/src/lib/cloud-client.ts +103 -0
  14. package/apps/api/src/lib/compose-parser.ts +138 -0
  15. package/apps/api/src/lib/controller-helpers.ts +90 -0
  16. package/apps/api/src/lib/email-templates.ts +94 -0
  17. package/apps/api/src/lib/encryption.ts +102 -0
  18. package/apps/api/src/lib/local-user.ts +65 -0
  19. package/apps/api/src/lib/mail.ts +48 -0
  20. package/apps/api/src/lib/notifications.ts +195 -0
  21. package/apps/api/src/lib/openship-cloud.ts +101 -0
  22. package/apps/api/src/lib/resources.ts +96 -0
  23. package/apps/api/src/lib/screenshots.ts +189 -0
  24. package/apps/api/src/lib/ssh-manager.ts +369 -0
  25. package/apps/api/src/lib/ssl-scheduler.ts +109 -0
  26. package/apps/api/src/lib/stack-detector.ts +708 -0
  27. package/apps/api/src/lib/system-debug.ts +10 -0
  28. package/apps/api/src/middleware/auth.ts +49 -13
  29. package/apps/api/src/middleware/error-handler.ts +23 -3
  30. package/apps/api/src/middleware/index.ts +2 -0
  31. package/apps/api/src/middleware/internal-auth.ts +40 -0
  32. package/apps/api/src/middleware/local-only.ts +20 -0
  33. package/apps/api/src/middleware/rate-limiter.ts +9 -0
  34. package/apps/api/src/modules/analytics/analytics.controller.ts +111 -0
  35. package/apps/api/src/modules/analytics/analytics.routes.ts +29 -0
  36. package/apps/api/src/modules/analytics/analytics.schema.ts +37 -0
  37. package/apps/api/src/modules/analytics/analytics.service.ts +264 -0
  38. package/apps/api/src/modules/auth/auth.routes.ts +233 -6
  39. package/apps/api/src/modules/billing/billing.routes.ts +8 -0
  40. package/apps/api/src/modules/cloud/cloud.controller.ts +225 -0
  41. package/apps/api/src/modules/cloud/cloud.routes.ts +40 -0
  42. package/apps/api/src/modules/deployments/build.service.ts +791 -0
  43. package/apps/api/src/modules/deployments/deployment-lifecycle.ts +138 -0
  44. package/apps/api/src/modules/deployments/deployment.controller.ts +324 -16
  45. package/apps/api/src/modules/deployments/deployment.routes.ts +33 -7
  46. package/apps/api/src/modules/deployments/deployment.schema.ts +37 -5
  47. package/apps/api/src/modules/deployments/deployment.service.ts +178 -11
  48. package/apps/api/src/modules/deployments/preflight.ts +280 -0
  49. package/apps/api/src/modules/deployments/prepare.service.ts +252 -0
  50. package/apps/api/src/modules/deployments/session-manager.ts +283 -0
  51. package/apps/api/src/modules/deployments/ssl.service.ts +73 -0
  52. package/apps/api/src/modules/domains/domain.controller.ts +59 -7
  53. package/apps/api/src/modules/domains/domain.routes.ts +20 -5
  54. package/apps/api/src/modules/domains/domain.schema.ts +35 -0
  55. package/apps/api/src/modules/domains/domain.service.ts +375 -9
  56. package/apps/api/src/modules/github/github.auth.ts +397 -0
  57. package/apps/api/src/modules/github/github.controller.ts +387 -0
  58. package/apps/api/src/modules/github/github.local-auth.ts +251 -0
  59. package/apps/api/src/modules/github/github.routes.ts +50 -0
  60. package/apps/api/src/modules/github/github.schema.ts +52 -0
  61. package/apps/api/src/modules/github/github.service.ts +592 -0
  62. package/apps/api/src/modules/github/github.types.ts +158 -0
  63. package/apps/api/src/modules/github/github.webhook.ts +186 -0
  64. package/apps/api/src/modules/github/index.ts +16 -0
  65. package/apps/api/src/modules/health/health.routes.ts +35 -0
  66. package/apps/api/src/modules/projects/project.controller.ts +481 -12
  67. package/apps/api/src/modules/projects/project.routes.ts +63 -6
  68. package/apps/api/src/modules/projects/project.schema.ts +104 -6
  69. package/apps/api/src/modules/projects/project.service.ts +502 -11
  70. package/apps/api/src/modules/settings/settings.controller.ts +55 -0
  71. package/apps/api/src/modules/settings/settings.routes.ts +25 -0
  72. package/apps/api/src/modules/settings/settings.service.ts +49 -0
  73. package/apps/api/src/modules/system/filesystem.controller.ts +66 -0
  74. package/apps/api/src/modules/system/index.ts +1 -0
  75. package/apps/api/src/modules/system/server-check.controller.ts +475 -0
  76. package/apps/api/src/modules/system/setup-session.ts +255 -0
  77. package/apps/api/src/modules/system/setup.controller.ts +128 -0
  78. package/apps/api/src/modules/system/system.routes.ts +42 -0
  79. package/apps/api/src/modules/webhooks/webhook.controller.ts +57 -15
  80. package/apps/api/src/modules/webhooks/webhook.routes.ts +11 -8
  81. package/apps/api/src/modules/webhooks/webhook.service.ts +46 -5
  82. package/apps/api/src/modules/webhooks/webhook.types.ts +35 -0
  83. package/apps/api/tsconfig.json +3 -1
  84. package/apps/cli/package.json +8 -10
  85. package/apps/cli/tsconfig.json +2 -1
  86. package/apps/dashboard/Dockerfile +4 -6
  87. package/apps/dashboard/components.json +20 -0
  88. package/apps/dashboard/next-env.d.ts +6 -0
  89. package/apps/dashboard/next.config.mjs +11 -1
  90. package/apps/dashboard/package.json +25 -13
  91. package/apps/dashboard/postcss.config.mjs +5 -0
  92. package/apps/dashboard/public/android-chrome-192x192.png +0 -0
  93. package/apps/dashboard/public/android-chrome-512x512.png +0 -0
  94. package/apps/dashboard/public/apple-touch-icon.png +0 -0
  95. package/apps/dashboard/public/favicon-16x16.png +0 -0
  96. package/apps/dashboard/public/favicon-32x32.png +0 -0
  97. package/apps/dashboard/public/favicon.ico +0 -0
  98. package/apps/dashboard/public/site.webmanifest +19 -0
  99. package/apps/dashboard/src/app/(auth)/forgot-password/page.tsx +114 -0
  100. package/apps/dashboard/src/app/(auth)/layout.tsx +18 -3
  101. package/apps/dashboard/src/app/(auth)/login/page.tsx +215 -6
  102. package/apps/dashboard/src/app/(auth)/providers.tsx +34 -0
  103. package/apps/dashboard/src/app/(auth)/register/page.tsx +171 -5
  104. package/apps/dashboard/src/app/(auth)/reset-password/page.tsx +172 -0
  105. package/apps/dashboard/src/app/(auth)/verify-email/page.tsx +190 -0
  106. package/apps/dashboard/src/app/(dashboard)/(deployment)/build/[id]/page.tsx +162 -0
  107. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/BuildSummary.tsx +166 -0
  108. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/DnsConfiguration.tsx +119 -0
  109. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/DomainSettings.tsx +291 -0
  110. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/Header.tsx +71 -0
  111. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/Sidebar.tsx +270 -0
  112. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/SkeletonLoader.tsx +87 -0
  113. package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/page.tsx +169 -0
  114. package/apps/dashboard/src/app/(dashboard)/(deployment)/layout.tsx +7 -0
  115. package/apps/dashboard/src/app/(dashboard)/billing/page.tsx +1 -8
  116. package/apps/dashboard/src/app/(dashboard)/deployments/components/CommitDetailsModal.tsx +240 -0
  117. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentCard.tsx +121 -0
  118. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentHeader.tsx +89 -0
  119. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentMenu.tsx +182 -0
  120. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsContent.tsx +324 -0
  121. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsFilters.tsx +99 -0
  122. package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsList.tsx +31 -0
  123. package/apps/dashboard/src/app/(dashboard)/deployments/components/EmptyState.tsx +101 -0
  124. package/apps/dashboard/src/app/(dashboard)/deployments/components/LoadingSkeleton.tsx +57 -0
  125. package/apps/dashboard/src/app/(dashboard)/deployments/components/ProjectFilter.tsx +109 -0
  126. package/apps/dashboard/src/app/(dashboard)/deployments/components/index.ts +9 -0
  127. package/apps/dashboard/src/app/(dashboard)/deployments/page.tsx +9 -3
  128. package/apps/dashboard/src/app/(dashboard)/deployments/types.ts +44 -0
  129. package/apps/dashboard/src/app/(dashboard)/deployments/utils.ts +176 -0
  130. package/apps/dashboard/src/app/(dashboard)/domains/page.tsx +1 -6
  131. package/apps/dashboard/src/app/(dashboard)/integrations/page.tsx +321 -0
  132. package/apps/dashboard/src/app/(dashboard)/layout.tsx +22 -32
  133. package/apps/dashboard/src/app/(dashboard)/library/components/ConnectPrompt.tsx +187 -0
  134. package/apps/dashboard/src/app/(dashboard)/library/components/LibrarySidebar.tsx +147 -0
  135. package/apps/dashboard/src/app/(dashboard)/library/components/LoadingSkeleton.tsx +39 -0
  136. package/apps/dashboard/src/app/(dashboard)/library/components/LocalProjects.tsx +548 -0
  137. package/apps/dashboard/src/app/(dashboard)/library/components/RepositoryList.tsx +292 -0
  138. package/apps/dashboard/src/app/(dashboard)/library/components/TemplateGrid.tsx +36 -0
  139. package/apps/dashboard/src/app/(dashboard)/library/components/UrlImport.tsx +74 -0
  140. package/apps/dashboard/src/app/(dashboard)/library/page.tsx +121 -0
  141. package/apps/dashboard/src/app/(dashboard)/library/types.ts +26 -0
  142. package/apps/dashboard/src/app/(dashboard)/monitoring/page.tsx +1 -6
  143. package/apps/dashboard/src/app/(dashboard)/page.tsx +485 -0
  144. package/apps/dashboard/src/app/(dashboard)/projects/[id]/[[...slug]]/layout.tsx +22 -0
  145. package/apps/dashboard/src/app/(dashboard)/projects/[id]/[[...slug]]/page.tsx +286 -0
  146. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/AdvancedSettings.tsx +235 -0
  147. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/BuildSettings.tsx +174 -0
  148. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DeleteConfirmationDialog.tsx +45 -0
  149. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DeletionModal.tsx +95 -0
  150. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/Deployments.tsx +11 -0
  151. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DomainSettings.tsx +523 -0
  152. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/EnvironmentSettings.tsx +246 -0
  153. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GeneralSettings.tsx +93 -0
  154. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GitInfo.tsx +261 -0
  155. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GitSettings.tsx +391 -0
  156. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/LogsSettings.tsx +133 -0
  157. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ProjectNotFound.tsx +95 -0
  158. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ProjectsBottomNavigation.tsx +62 -0
  159. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ResourceSettings.tsx +333 -0
  160. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SettingSection.tsx +66 -0
  161. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SettingsNavigation.tsx +27 -0
  162. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SleepModeSettings.tsx +134 -0
  163. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProductionUrl.tsx +25 -0
  164. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProjectIdentity.tsx +159 -0
  165. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProjectInfo.tsx +58 -0
  166. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/SkeletonLoader.tsx +170 -0
  167. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/StatsCards.tsx +33 -0
  168. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/TopPaths.tsx +56 -0
  169. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/TrafficChart.tsx +157 -0
  170. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/index.ts +14 -0
  171. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/LogsActions.tsx +52 -0
  172. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/ServerLogs.tsx +249 -0
  173. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/TerminalLogs.tsx +682 -0
  174. package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/logs.css +127 -0
  175. package/apps/dashboard/src/app/(dashboard)/projects/components/DeploymentCard.tsx +73 -0
  176. package/apps/dashboard/src/app/(dashboard)/projects/components/ProjectCard.tsx +330 -0
  177. package/apps/dashboard/src/app/(dashboard)/projects/page.tsx +326 -4
  178. package/apps/dashboard/src/app/(dashboard)/providers.tsx +23 -0
  179. package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/components-tab.tsx +329 -0
  180. package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/overview-tab.tsx +229 -0
  181. package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/terminal-tab.tsx +38 -0
  182. package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/page.tsx +437 -0
  183. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/checking-state.tsx +15 -0
  184. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/choose-mode.tsx +54 -0
  185. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/component-row.tsx +65 -0
  186. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/error-banner.tsx +13 -0
  187. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/installing-panel.tsx +227 -0
  188. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/results-panel.tsx +90 -0
  189. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/setup-header.tsx +56 -0
  190. package/apps/dashboard/src/app/(dashboard)/servers/new/_components/types.ts +13 -0
  191. package/apps/dashboard/src/app/(dashboard)/servers/new/page.tsx +666 -0
  192. package/apps/dashboard/src/app/(dashboard)/servers/page.tsx +283 -0
  193. package/apps/dashboard/src/app/(dashboard)/settings/_components/BuildPreferences.tsx +110 -0
  194. package/apps/dashboard/src/app/(dashboard)/settings/_components/CloudConnection.tsx +147 -0
  195. package/apps/dashboard/src/app/(dashboard)/settings/_components/InstanceInfo.tsx +54 -0
  196. package/apps/dashboard/src/app/(dashboard)/settings/_components/ServerConnection.tsx +407 -0
  197. package/apps/dashboard/src/app/(dashboard)/settings/_components/SettingsSection.tsx +32 -0
  198. package/apps/dashboard/src/app/(dashboard)/settings/page.tsx +62 -3
  199. package/apps/dashboard/src/app/auth/callback/close/page.tsx +23 -0
  200. package/apps/dashboard/src/app/auth/callback/install/page.tsx +40 -0
  201. package/apps/dashboard/src/app/authorize/page.tsx +137 -0
  202. package/apps/dashboard/src/app/globals.css +57 -3
  203. package/apps/dashboard/src/app/layout.tsx +43 -3
  204. package/apps/dashboard/src/components/auth-shell.tsx +66 -0
  205. package/apps/dashboard/src/components/deployments/types.ts +44 -0
  206. package/apps/dashboard/src/components/global-deployments/index.ts +17 -0
  207. package/apps/dashboard/src/components/i18n-provider.tsx +100 -0
  208. package/apps/dashboard/src/components/import-project/BuildSettings.tsx +376 -0
  209. package/apps/dashboard/src/components/import-project/BuildSkeleton.tsx +161 -0
  210. package/apps/dashboard/src/components/import-project/BuildTerminal.tsx +358 -0
  211. package/apps/dashboard/src/components/import-project/ComposeServices.tsx +455 -0
  212. package/apps/dashboard/src/components/import-project/DeploymentProcessing.tsx +510 -0
  213. package/apps/dashboard/src/components/import-project/DockerSettings.tsx +64 -0
  214. package/apps/dashboard/src/components/import-project/EnvironmentVariables.tsx +481 -0
  215. package/apps/dashboard/src/components/import-project/Frameworks.tsx +90 -0
  216. package/apps/dashboard/src/components/import-project/ProjectSettings.tsx +160 -0
  217. package/apps/dashboard/src/components/import-project/types.ts +82 -0
  218. package/apps/dashboard/src/components/integrations/GithubPermissionModal.tsx +173 -0
  219. package/apps/dashboard/src/components/language-switcher.tsx +36 -0
  220. package/apps/dashboard/src/components/logo.tsx +13 -0
  221. package/apps/dashboard/src/components/network-error-handler.tsx +27 -0
  222. package/apps/dashboard/src/components/oauth-buttons.tsx +81 -0
  223. package/apps/dashboard/src/components/overview/ActivityChart.tsx +247 -0
  224. package/apps/dashboard/src/components/overview/ApiRequestsCard.tsx +111 -0
  225. package/apps/dashboard/src/components/overview/CreditsCard.tsx +137 -0
  226. package/apps/dashboard/src/components/overview/DeploymentsChart.tsx +195 -0
  227. package/apps/dashboard/src/components/overview/EmptyState.tsx +126 -0
  228. package/apps/dashboard/src/components/overview/LoadingSkeleton.tsx +92 -0
  229. package/apps/dashboard/src/components/overview/OverviewHeader.tsx +74 -0
  230. package/apps/dashboard/src/components/overview/OverviewHeroChart.tsx +344 -0
  231. package/apps/dashboard/src/components/overview/ProjectsCard.tsx +134 -0
  232. package/apps/dashboard/src/components/overview/QuickLinks.tsx +119 -0
  233. package/apps/dashboard/src/components/overview/SandboxesCard.tsx +150 -0
  234. package/apps/dashboard/src/components/overview/StatsGrid.tsx +166 -0
  235. package/apps/dashboard/src/components/overview/TokenUsageChart.tsx +206 -0
  236. package/apps/dashboard/src/components/overview/UsageStats.tsx +79 -0
  237. package/apps/dashboard/src/components/overview/index.ts +30 -0
  238. package/apps/dashboard/src/components/overview/types.ts +116 -0
  239. package/apps/dashboard/src/components/page-header.tsx +25 -0
  240. package/apps/dashboard/src/components/project-settings/ServerSideSwitch.jsx +60 -0
  241. package/apps/dashboard/src/components/shared/AlertBox.tsx +39 -0
  242. package/apps/dashboard/src/components/shared/CTASection.tsx +45 -0
  243. package/apps/dashboard/src/components/shared/ErrorState.tsx +176 -0
  244. package/apps/dashboard/src/components/shared/FeatureCard.tsx +20 -0
  245. package/apps/dashboard/src/components/shared/MDXComponents.tsx +24 -0
  246. package/apps/dashboard/src/components/shared/MachineSettingsModal.tsx +286 -0
  247. package/apps/dashboard/src/components/shared/Modal.tsx +39 -0
  248. package/apps/dashboard/src/components/shared/OTPInput.tsx +122 -0
  249. package/apps/dashboard/src/components/shared/PageHero.tsx +21 -0
  250. package/apps/dashboard/src/components/shared/PlatformFeatureCard.tsx +27 -0
  251. package/apps/dashboard/src/components/shared/StatCard.tsx +14 -0
  252. package/apps/dashboard/src/components/shared/ValueCard.tsx +20 -0
  253. package/apps/dashboard/src/components/shared/index.ts +8 -0
  254. package/apps/dashboard/src/components/sidebar.tsx +282 -0
  255. package/apps/dashboard/src/components/theme-provider.tsx +96 -0
  256. package/apps/dashboard/src/components/toast.tsx +106 -0
  257. package/apps/dashboard/src/components/ui/CustomCursor.tsx +107 -0
  258. package/apps/dashboard/src/components/ui/CustomSelect.tsx +126 -0
  259. package/apps/dashboard/src/components/ui/DropdownMenu.tsx +174 -0
  260. package/apps/dashboard/src/components/ui/FileIcon.jsx +59 -0
  261. package/apps/dashboard/src/components/ui/IconPickerModal.tsx +273 -0
  262. package/apps/dashboard/src/components/ui/InfoBanner.jsx +39 -0
  263. package/apps/dashboard/src/components/ui/Logo.tsx +14 -0
  264. package/apps/dashboard/src/components/ui/Modal.tsx +117 -0
  265. package/apps/dashboard/src/components/ui/PageContainer.tsx +12 -0
  266. package/apps/dashboard/src/components/ui/SectionContainer.jsx +7 -0
  267. package/apps/dashboard/src/components/ui/SlidingToggle.tsx +128 -0
  268. package/apps/dashboard/src/components/ui/Toast.tsx +29 -0
  269. package/apps/dashboard/src/components/ui/button.tsx +58 -0
  270. package/apps/dashboard/src/components/ui/card.tsx +60 -0
  271. package/apps/dashboard/src/components/ui/input.tsx +20 -0
  272. package/apps/dashboard/src/components/ui/label.tsx +19 -0
  273. package/apps/dashboard/src/components/ui/select.tsx +10 -0
  274. package/apps/dashboard/src/components/ui/textarea.tsx +9 -0
  275. package/apps/dashboard/src/constants/lang-colors.ts +25 -0
  276. package/apps/dashboard/src/constants/mock.ts +38 -0
  277. package/apps/dashboard/src/context/AuthContext.tsx +91 -0
  278. package/apps/dashboard/src/context/CloudContext.tsx +275 -0
  279. package/apps/dashboard/src/context/DeploymentContext.tsx +71 -0
  280. package/apps/dashboard/src/context/GitHubContext.tsx +288 -0
  281. package/apps/dashboard/src/context/ModalContext.tsx +300 -0
  282. package/apps/dashboard/src/context/NetworkContext.tsx +32 -0
  283. package/apps/dashboard/src/context/ProjectSettingsContext.tsx +727 -0
  284. package/apps/dashboard/src/context/ToastContext.tsx +129 -0
  285. package/apps/dashboard/src/context/deployment/index.ts +3 -0
  286. package/apps/dashboard/src/context/deployment/types.ts +183 -0
  287. package/apps/dashboard/src/context/deployment/useDeploymentBuild.ts +547 -0
  288. package/apps/dashboard/src/context/deployment/useDeploymentConfig.ts +176 -0
  289. package/apps/dashboard/src/hooks/useBuildConnection.ts +334 -0
  290. package/apps/dashboard/src/hooks/useMonitorStream.ts +146 -0
  291. package/apps/dashboard/src/hooks/useProjectData.ts +110 -0
  292. package/apps/dashboard/src/hooks/useSSEConnection.ts +465 -0
  293. package/apps/dashboard/src/hooks/useSSEStream.ts +309 -0
  294. package/apps/dashboard/src/hooks/useSessions.ts +104 -0
  295. package/apps/dashboard/src/hooks/useSetupStream.ts +223 -0
  296. package/apps/dashboard/src/i18n/dictionaries/ar.json +218 -0
  297. package/apps/dashboard/src/i18n/dictionaries/en.json +218 -0
  298. package/apps/dashboard/src/i18n/index.ts +16 -0
  299. package/apps/dashboard/src/lib/api/ai.ts +22 -0
  300. package/apps/dashboard/src/lib/api/auth.ts +13 -0
  301. package/apps/dashboard/src/lib/api/client.ts +199 -0
  302. package/apps/dashboard/src/lib/api/cloud.ts +15 -0
  303. package/apps/dashboard/src/lib/api/deploy.ts +58 -0
  304. package/apps/dashboard/src/lib/api/domains.ts +13 -0
  305. package/apps/dashboard/src/lib/api/endpoints.ts +129 -0
  306. package/apps/dashboard/src/lib/api/github.ts +31 -0
  307. package/apps/dashboard/src/lib/api/icons.ts +12 -0
  308. package/apps/dashboard/src/lib/api/index.ts +41 -0
  309. package/apps/dashboard/src/lib/api/projects.ts +153 -0
  310. package/apps/dashboard/src/lib/api/sandbox.ts +14 -0
  311. package/apps/dashboard/src/lib/api/settings.ts +21 -0
  312. package/apps/dashboard/src/lib/api/system.ts +159 -0
  313. package/apps/dashboard/src/lib/auth-client.ts +54 -0
  314. package/apps/dashboard/src/lib/country.ts +25 -0
  315. package/apps/dashboard/src/lib/server/api.ts +140 -0
  316. package/apps/dashboard/src/lib/server/session.ts +103 -0
  317. package/apps/dashboard/src/lib/sseClient.ts +241 -0
  318. package/apps/dashboard/src/lib/sseMessageProcessors.ts +323 -0
  319. package/apps/dashboard/src/lib/utils.ts +6 -0
  320. package/apps/dashboard/src/proxy.ts +46 -0
  321. package/apps/dashboard/src/styles/Toast.module.css +92 -0
  322. package/apps/dashboard/src/styles/fonts.css +93 -0
  323. package/apps/dashboard/src/styles/theme.css +336 -0
  324. package/apps/dashboard/src/types/research.ts +42 -0
  325. package/apps/dashboard/src/utils/SSEParser.js +150 -0
  326. package/apps/dashboard/src/utils/authWindow.ts +143 -0
  327. package/apps/dashboard/src/utils/codeTheme.ts +127 -0
  328. package/apps/dashboard/src/utils/colors.json +2810 -0
  329. package/apps/dashboard/src/utils/date.ts +121 -0
  330. package/apps/dashboard/src/utils/deployment.ts +128 -0
  331. package/apps/dashboard/src/utils/deploymentPhaseDetector.ts +232 -0
  332. package/apps/dashboard/src/utils/extToLang.js +103 -0
  333. package/apps/dashboard/src/utils/github.ts +62 -0
  334. package/apps/dashboard/src/utils/icons.js +46 -0
  335. package/apps/dashboard/src/utils/repoSlug.ts +110 -0
  336. package/apps/dashboard/src/utils/research-api.ts +163 -0
  337. package/apps/dashboard/src/utils/suggestions.ts +84 -0
  338. package/apps/dashboard/src/utils/theme.js +1 -0
  339. package/apps/dashboard/src/utils/ui-helpers.tsx +30 -0
  340. package/apps/dashboard/src/utils/upload.js +12 -0
  341. package/apps/dashboard/tsconfig.json +27 -5
  342. package/apps/desktop/forge.config.json +36 -0
  343. package/apps/desktop/package.json +26 -0
  344. package/apps/desktop/scripts/dev.mjs +58 -0
  345. package/apps/desktop/src/main/index.ts +675 -0
  346. package/apps/desktop/src/main/types/desktop.d.ts +33 -0
  347. package/apps/desktop/src/preload/index.ts +88 -0
  348. package/apps/desktop/src/renderer/index.html +462 -0
  349. package/apps/desktop/src/renderer/onboarding.js +511 -0
  350. package/apps/desktop/src/renderer/styles.css +1139 -0
  351. package/apps/desktop/tsconfig.json +17 -0
  352. package/apps/web/.source/browser.ts +13 -0
  353. package/apps/web/.source/dynamic.ts +8 -0
  354. package/apps/web/.source/server.ts +22 -0
  355. package/apps/web/.source/source.config.mjs +20 -0
  356. package/apps/web/Dockerfile +4 -6
  357. package/apps/web/content/blog/how-ai-builds-work.mdx +55 -0
  358. package/apps/web/content/blog/introducing-openship.mdx +46 -0
  359. package/apps/web/content/blog/self-hosting-cost-breakdown.mdx +59 -0
  360. package/apps/web/content/docs/_meta.json +14 -0
  361. package/apps/web/content/docs/api.mdx +98 -0
  362. package/apps/web/content/docs/cli.mdx +80 -0
  363. package/apps/web/content/docs/first-deployment.mdx +56 -0
  364. package/apps/web/content/docs/index.mdx +27 -0
  365. package/apps/web/content/docs/installation.mdx +65 -0
  366. package/apps/web/content/docs/quickstart.mdx +45 -0
  367. package/apps/web/next-env.d.ts +6 -0
  368. package/apps/web/next.config.mjs +16 -2
  369. package/apps/web/package.json +19 -12
  370. package/apps/web/postcss.config.mjs +5 -0
  371. package/apps/web/public/android-chrome-192x192.png +0 -0
  372. package/apps/web/public/android-chrome-512x512.png +0 -0
  373. package/apps/web/public/apple-touch-icon.png +0 -0
  374. package/apps/web/public/favicon-16x16.png +0 -0
  375. package/apps/web/public/favicon-32x32.png +0 -0
  376. package/apps/web/public/favicon.ico +0 -0
  377. package/apps/web/public/site.webmanifest +1 -0
  378. package/apps/web/source.config.ts +17 -0
  379. package/apps/web/src/app/(marketing)/layout.tsx +7 -22
  380. package/apps/web/src/app/blog/[...slug]/page.tsx +247 -0
  381. package/apps/web/src/app/blog/blog.css +575 -0
  382. package/apps/web/src/app/blog/layout.tsx +50 -0
  383. package/apps/web/src/app/blog/page.tsx +235 -0
  384. package/apps/web/src/app/docs/[[...slug]]/page.tsx +67 -0
  385. package/apps/web/src/app/docs/layout.tsx +62 -0
  386. package/apps/web/src/app/docs/toc-theme.css +71 -0
  387. package/apps/web/src/app/download/page.tsx +396 -0
  388. package/apps/web/src/app/globals.css +20 -3
  389. package/apps/web/src/app/layout.tsx +57 -3
  390. package/apps/web/src/app/page.tsx +47 -6
  391. package/apps/web/src/app/robots.ts +15 -0
  392. package/apps/web/src/app/sitemap.ts +35 -0
  393. package/apps/web/src/components/blog/share-sidebar.tsx +81 -0
  394. package/apps/web/src/components/blog/writer-sidebar.tsx +81 -0
  395. package/apps/web/src/components/landing/ai-native.tsx +169 -0
  396. package/apps/web/src/components/landing/backups.tsx +139 -0
  397. package/apps/web/src/components/landing/cdn.tsx +109 -0
  398. package/apps/web/src/components/landing/coming-soon.tsx +180 -0
  399. package/apps/web/src/components/landing/dark-section.tsx +166 -0
  400. package/apps/web/src/components/landing/dashboard.tsx +407 -0
  401. package/apps/web/src/components/landing/developer-experience.tsx +224 -0
  402. package/apps/web/src/components/landing/dns-domains.tsx +146 -0
  403. package/apps/web/src/components/landing/download-button.tsx +151 -0
  404. package/apps/web/src/components/landing/features/ai-visual.tsx +48 -0
  405. package/apps/web/src/components/landing/features/cloud-visual.tsx +44 -0
  406. package/apps/web/src/components/landing/features/git-visual.tsx +61 -0
  407. package/apps/web/src/components/landing/features/index.tsx +642 -0
  408. package/apps/web/src/components/landing/features/infra-visual.tsx +69 -0
  409. package/apps/web/src/components/landing/features/rollback-visual.tsx +42 -0
  410. package/apps/web/src/components/landing/features/ssl-visual.tsx +41 -0
  411. package/apps/web/src/components/landing/features/stacks-visual.tsx +54 -0
  412. package/apps/web/src/components/landing/final-cta.tsx +116 -0
  413. package/apps/web/src/components/landing/footer.tsx +145 -0
  414. package/apps/web/src/components/landing/hero.tsx +110 -0
  415. package/apps/web/src/components/landing/how-it-works.tsx +210 -0
  416. package/apps/web/src/components/landing/index.ts +21 -0
  417. package/apps/web/src/components/landing/mail-server.tsx +122 -0
  418. package/apps/web/src/components/landing/navbar.tsx +199 -0
  419. package/apps/web/src/components/landing/no-lockin.tsx +185 -0
  420. package/apps/web/src/components/landing/open-source-cta.tsx +151 -0
  421. package/apps/web/src/components/landing/portability.tsx +190 -0
  422. package/apps/web/src/components/landing/pricing.tsx +263 -0
  423. package/apps/web/src/components/landing/scaling.tsx +209 -0
  424. package/apps/web/src/components/landing/why-openship.tsx +291 -0
  425. package/apps/web/src/hooks/use-gsap-scroll.ts +158 -0
  426. package/apps/web/src/hooks/use-platform.ts +86 -0
  427. package/apps/web/src/lib/source.ts +12 -0
  428. package/apps/web/src/styles/fonts.css +84 -0
  429. package/apps/web/src/styles/landing.css +951 -0
  430. package/apps/web/src/styles/theme.css +227 -0
  431. package/apps/web/tsconfig.json +8 -3
  432. package/bun.lock +3260 -0
  433. package/docker-compose.yml +3 -0
  434. package/docs/screenshots/.gitkeep +0 -0
  435. package/docs/screenshots/screen.png +0 -0
  436. package/openship.code-workspace +7 -0
  437. package/package.json +23 -9
  438. package/packages/adapters/docs/ARCHITECTURE.md +160 -0
  439. package/packages/adapters/docs/BUILD-PIPELINE.md +171 -0
  440. package/packages/adapters/docs/CLOUD.md +239 -0
  441. package/packages/adapters/docs/EXECUTOR.md +174 -0
  442. package/packages/adapters/docs/LOG-STREAMING.md +175 -0
  443. package/packages/adapters/docs/SYSTEM.md +191 -0
  444. package/packages/adapters/package.json +14 -9
  445. package/packages/adapters/src/index.ts +144 -4
  446. package/packages/adapters/src/infra/cloud.ts +42 -0
  447. package/packages/adapters/src/infra/index.ts +9 -0
  448. package/packages/adapters/src/infra/noop.ts +27 -0
  449. package/packages/adapters/src/infra/traefik.ts +297 -0
  450. package/packages/adapters/src/infra/types.ts +36 -0
  451. package/packages/adapters/src/platform.ts +255 -0
  452. package/packages/adapters/src/runtime/bare.ts +567 -0
  453. package/packages/adapters/src/runtime/build-pipeline.ts +237 -0
  454. package/packages/adapters/src/runtime/cloud.ts +791 -0
  455. package/packages/adapters/src/runtime/deploy-pipeline.ts +146 -0
  456. package/packages/adapters/src/runtime/docker.ts +443 -0
  457. package/packages/adapters/src/runtime/index.ts +69 -0
  458. package/packages/adapters/src/runtime/local-build.ts +112 -0
  459. package/packages/adapters/src/runtime/transfer.ts +82 -0
  460. package/packages/adapters/src/runtime/types.ts +138 -0
  461. package/packages/adapters/src/system/catalog.ts +188 -0
  462. package/packages/adapters/src/system/checks.ts +228 -0
  463. package/packages/adapters/src/system/components.ts +45 -0
  464. package/packages/adapters/src/system/debug.ts +18 -0
  465. package/packages/adapters/src/system/environment.ts +168 -0
  466. package/packages/adapters/src/system/errors.ts +34 -0
  467. package/packages/adapters/src/system/executor.ts +600 -0
  468. package/packages/adapters/src/system/index.ts +58 -0
  469. package/packages/adapters/src/system/installer.ts +310 -0
  470. package/packages/adapters/src/system/setup.ts +442 -0
  471. package/packages/adapters/src/system/state.ts +96 -0
  472. package/packages/adapters/src/system/types.ts +116 -0
  473. package/packages/adapters/src/toolchain/catalog.ts +439 -0
  474. package/packages/adapters/src/toolchain/checks.ts +181 -0
  475. package/packages/adapters/src/toolchain/index.ts +38 -0
  476. package/packages/adapters/src/toolchain/installer.ts +189 -0
  477. package/packages/adapters/src/toolchain/types.ts +84 -0
  478. package/packages/adapters/src/types.ts +277 -0
  479. package/packages/adapters/tsconfig.json +3 -1
  480. package/packages/core/package.json +9 -9
  481. package/packages/core/src/constants.ts +44 -1
  482. package/packages/core/src/index.ts +2 -0
  483. package/packages/core/src/stacks.ts +778 -0
  484. package/packages/core/src/system.ts +111 -0
  485. package/packages/core/src/types.ts +22 -1
  486. package/packages/core/src/utils.ts +8 -0
  487. package/packages/core/tsconfig.json +3 -1
  488. package/packages/db/drizzle/0000_init.sql +231 -0
  489. package/packages/db/drizzle/0001_add_server_name.sql +1 -0
  490. package/packages/db/drizzle/meta/_journal.json +20 -0
  491. package/packages/db/drizzle.config.ts +10 -0
  492. package/packages/db/package.json +26 -14
  493. package/packages/db/src/client.ts +119 -0
  494. package/packages/db/src/index.ts +57 -8
  495. package/packages/db/src/repos/account.repo.ts +92 -0
  496. package/packages/db/src/repos/deployment.repo.ts +168 -0
  497. package/packages/db/src/repos/domain.repo.ts +102 -0
  498. package/packages/db/src/repos/git-installation.repo.ts +95 -0
  499. package/packages/db/src/repos/index.ts +43 -0
  500. package/packages/db/src/repos/instance-settings.repo.ts +43 -0
  501. package/packages/db/src/repos/project.repo.ts +159 -0
  502. package/packages/db/src/repos/session.repo.ts +82 -0
  503. package/packages/db/src/repos/settings.repo.ts +51 -0
  504. package/packages/db/src/repos/user.repo.ts +94 -0
  505. package/packages/db/src/schema/auth.ts +56 -0
  506. package/packages/db/src/schema/deployment.ts +87 -0
  507. package/packages/db/src/schema/domain.ts +46 -0
  508. package/packages/db/src/schema/github.ts +24 -0
  509. package/packages/db/src/schema/index.ts +6 -0
  510. package/packages/db/src/schema/project.ts +117 -0
  511. package/packages/db/src/schema/settings.ts +103 -0
  512. package/packages/db/tsconfig.json +3 -1
  513. package/packages/ui/package.json +17 -17
  514. package/packages/ui/src/components/status-dot.tsx +1 -1
  515. package/packages/ui/tsconfig.json +7 -2
  516. package/pnpm-workspace.yaml +0 -1
  517. package/{tooling/tsconfig/base.json → tsconfig.base.json} +0 -1
  518. package/turbo.json +4 -0
  519. package/apps/api/src/modules/auth/auth.controller.ts +0 -26
  520. package/apps/api/src/modules/auth/auth.schema.ts +0 -12
  521. package/apps/api/src/modules/auth/auth.service.ts +0 -23
  522. package/apps/dashboard/src/app/page.tsx +0 -6
  523. package/apps/web/src/app/(marketing)/docs/page.tsx +0 -10
  524. package/packages/adapters/src/base-adapter.ts +0 -49
  525. package/packages/adapters/src/docker-adapter.ts +0 -43
  526. package/packages/adapters/src/oblien-adapter.ts +0 -46
  527. package/packages/adapters/src/registry.ts +0 -22
  528. package/packages/db/prisma/schema.prisma +0 -160
  529. package/tooling/tsconfig/nextjs.json +0 -10
  530. package/tooling/tsconfig/node.json +0 -10
  531. package/tooling/tsconfig/package.json +0 -7
@@ -0,0 +1,246 @@
1
+ "use client";
2
+ import React, { useMemo, useState, useEffect, useRef } from "react";
3
+ import EnvironmentVariables from "@/components/import-project/EnvironmentVariables";
4
+ import { useProjectSettings } from "@/context/ProjectSettingsContext";
5
+ import { useToast } from "@/context/ToastContext";
6
+ import { projectsApi } from "@/lib/api";
7
+ import generateIcon from "@/utils/icons";
8
+
9
+ export const EnvironmentSettings: React.FC = () => {
10
+ const { environmentData, updateEnvironment, refreshEnvironment, id } = useProjectSettings();
11
+ const { showToast } = useToast();
12
+ // Convert environmentData.envVars format to EnvironmentVariables format
13
+ const savedEnvVars = useMemo(() => {
14
+ const allEnvs: Array<{ key: string; value: string; visible: boolean }> = [];
15
+
16
+ // Combine all environments into a single list
17
+ Object.entries(environmentData.envVars || {}).forEach(([env, vars]) => {
18
+ if (Array.isArray(vars)) {
19
+ vars.forEach((envVar: any) => {
20
+ allEnvs.push({
21
+ key: envVar.key,
22
+ value: envVar.value,
23
+ visible: false,
24
+ });
25
+ });
26
+ }
27
+ });
28
+
29
+ return allEnvs;
30
+ }, [environmentData.envVars]);
31
+
32
+ const [localEnvVars, setLocalEnvVars] = useState(savedEnvVars);
33
+ const [hasChanges, setHasChanges] = useState(false);
34
+ const [isEditingMode, setIsEditingMode] = useState(false);
35
+ const [isSaving, setIsSaving] = useState(false);
36
+
37
+ const localEnvVarsRef = useRef(localEnvVars);
38
+
39
+ useEffect(() => {
40
+ localEnvVarsRef.current = localEnvVars;
41
+ }, [localEnvVars]);
42
+
43
+ // Fetch environment variables when component mounts if not already loaded
44
+ useEffect(() => {
45
+ const shouldFetch =
46
+ !environmentData.isLoading &&
47
+ !environmentData.error &&
48
+ (!environmentData.envVars || Object.keys(environmentData.envVars).length === 0);
49
+
50
+ if (shouldFetch) {
51
+ refreshEnvironment();
52
+ }
53
+ }, []);
54
+
55
+ // Update local state when environment data changes
56
+ useEffect(() => {
57
+ if (!environmentData.isLoading && savedEnvVars.length > 0) {
58
+ setLocalEnvVars(savedEnvVars);
59
+ }
60
+ }, [savedEnvVars]);
61
+
62
+ const handleEnvVarsChange = (
63
+ value:
64
+ | Array<{ key: string; value: string; visible: boolean }>
65
+ | ((
66
+ prev: Array<{ key: string; value: string; visible: boolean }>
67
+ ) => Array<{ key: string; value: string; visible: boolean }>)
68
+ ) => {
69
+ const newEnvVars = typeof value === "function" ? value(localEnvVars) : value;
70
+ setLocalEnvVars(newEnvVars);
71
+ setHasChanges(true);
72
+ };
73
+
74
+ const handleSave = async () => {
75
+ // Filter out completely empty entries (both key and value empty)
76
+ const filteredEnvVars = localEnvVarsRef.current.filter(env =>
77
+ env.key.trim() !== '' || env.value.trim() !== ''
78
+ );
79
+
80
+ // Validate: check if any entry has key without value or value without key
81
+ const invalidEntry = filteredEnvVars.find(env =>
82
+ (env.key.trim() !== '' && env.value.trim() === '') ||
83
+ (env.key.trim() === '' && env.value.trim() !== '')
84
+ );
85
+
86
+ if (invalidEntry) {
87
+ if (invalidEntry.key.trim() !== '' && invalidEntry.value.trim() === '') {
88
+ showToast(`Environment variable "${invalidEntry.key}" is missing a value`, 'error', 'Validation Error');
89
+ } else {
90
+ showToast('Environment variable has a value but is missing a key name', 'error', 'Validation Error');
91
+ }
92
+ return;
93
+ }
94
+
95
+ // Prepare data for API
96
+ const envData = filteredEnvVars.map(env => ({
97
+ key: env.key.trim(),
98
+ value: env.value.trim(),
99
+ }));
100
+
101
+ setIsSaving(true);
102
+
103
+ try {
104
+ // Make API request to save environment variables
105
+ const response = await projectsApi.setEnv(id, envData);
106
+
107
+ if (response.success) {
108
+ showToast('Environment variables saved successfully', 'success', 'Saved');
109
+
110
+ // Update local state with cleaned data
111
+ const cleanedEnvVars = filteredEnvVars.map(env => ({
112
+ key: env.key.trim(),
113
+ value: env.value.trim(),
114
+ visible: env.visible,
115
+ }));
116
+
117
+ setLocalEnvVars(cleanedEnvVars);
118
+
119
+ // Update context
120
+ const envVars = {
121
+ development: cleanedEnvVars.map((env, index) => ({
122
+ id: Date.now() + index,
123
+ key: env.key,
124
+ value: env.value,
125
+ encrypted: true,
126
+ })),
127
+ preview: [],
128
+ production: [],
129
+ };
130
+
131
+ updateEnvironment(envVars);
132
+ setHasChanges(false);
133
+ setIsEditingMode(false);
134
+
135
+ } else {
136
+ showToast(response.message || 'Failed to save environment variables', 'error', 'Save Failed');
137
+ }
138
+ } catch (error) {
139
+ console.error('Error saving environment variables:', error);
140
+ showToast('An error occurred while saving. Please try again.', 'error', 'Error');
141
+ } finally {
142
+ setIsSaving(false);
143
+ }
144
+ };
145
+
146
+ const handleCancel = () => {
147
+ setLocalEnvVars(savedEnvVars);
148
+ setHasChanges(false);
149
+ setIsEditingMode(false);
150
+ };
151
+
152
+ // Show loading state with skeleton
153
+ if (environmentData.isLoading) {
154
+ return (
155
+ <div className="space-y-4">
156
+ {/* Security Notice Skeleton */}
157
+ <div className="bg-gradient-to-r from-gray-100 to-gray-50 border border-gray-200 rounded-xl p-4 flex items-start gap-3 animate-pulse">
158
+ <div className="h-5 w-5 bg-gray-300/30 rounded-full mt-0.5 flex-shrink-0"></div>
159
+ <div className="flex-1 space-y-2">
160
+ <div className="h-4 bg-gray-300/30 rounded-full w-40"></div>
161
+ <div className="h-3 bg-gray-200/30 rounded-full w-full"></div>
162
+ <div className="h-3 bg-gray-200/30 rounded-full w-3/4"></div>
163
+ </div>
164
+ </div>
165
+
166
+ {/* Environment Variables Container Skeleton */}
167
+ <div className="bg-white border border-gray-200 rounded-xl p-6 space-y-4">
168
+ {/* Header Skeleton */}
169
+ <div className="flex items-center justify-between pb-4 border-b border-gray-200">
170
+ <div className="h-6 bg-gray-300/30 rounded-full w-48 animate-pulse"></div>
171
+ <div className="h-10 bg-gray-300/30 rounded-full w-32 animate-pulse"></div>
172
+ </div>
173
+
174
+ {/* Environment Variable Items Skeleton */}
175
+ {[1, 2, 3].map((i) => (
176
+ <div key={i} className="flex items-center gap-3 p-4 bg-gray-50 rounded-lg animate-pulse">
177
+ <div className="flex-1 space-y-2">
178
+ <div className="h-4 bg-gray-300/30 rounded-full w-32"></div>
179
+ <div className="h-3 bg-gray-200/30 rounded-full w-48"></div>
180
+ </div>
181
+ <div className="flex gap-2">
182
+ <div className="h-8 w-8 bg-gray-300/30 rounded-full"></div>
183
+ <div className="h-8 w-8 bg-gray-300/30 rounded-full"></div>
184
+ </div>
185
+ </div>
186
+ ))}
187
+
188
+ {/* Add Button Skeleton */}
189
+ <div className="flex justify-center pt-4">
190
+ <div className="h-10 bg-gray-300/30 rounded-full w-48 animate-pulse"></div>
191
+ </div>
192
+ </div>
193
+ </div>
194
+ );
195
+ }
196
+
197
+ // Show error state
198
+ if (environmentData.error) {
199
+ return (
200
+ <div className="space-y-4">
201
+ <div className="bg-red-50 border border-red-200 rounded-xl p-4 flex items-start gap-3">
202
+ <div className="flex-1">
203
+ <h4 className="font-semibold text-red-900 mb-1">Error Loading Environment</h4>
204
+ <p className="text-sm text-red-800">{environmentData.error}</p>
205
+ <button
206
+ onClick={refreshEnvironment}
207
+ className="mt-3 px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors"
208
+ >
209
+ Retry
210
+ </button>
211
+ </div>
212
+ </div>
213
+ </div>
214
+ );
215
+ }
216
+
217
+ return (
218
+ <div className="space-y-4" style={{ opacity: isSaving ? 0.5 : 1, transition: 'opacity 0.3s', pointerEvents: isSaving ? 'none' : 'auto' }}>
219
+ {/* Security Notice */}
220
+ <div className="bg-gradient-to-r from-green-50 to-emerald-50 border relative border-green-200 rounded-xl p-4 flex items-start gap-3">
221
+ <div className="w-10 h-10 bg-green-100 rounded-xl absolute flex items-center justify-center border border-green-200">
222
+ {generateIcon('shield-123-1691989638.png', 24, 'var(--color-green-600)')}
223
+ </div>
224
+ <div className="ml-14">
225
+ <h4 className="font-semibold text-green-900 mb-1">Secure & Encrypted</h4>
226
+ <p className="text-sm text-green-800">
227
+ All environment variables are stored with end-to-end encryption. We don't have access to your environment variables, and no third party can access them.
228
+ </p>
229
+ </div>
230
+ </div>
231
+
232
+ {/* Environment Variables Component */}
233
+ <EnvironmentVariables
234
+ mode="settings"
235
+ envVars={localEnvVars}
236
+ onEnvVarsChange={handleEnvVarsChange}
237
+ isEditingMode={isEditingMode}
238
+ setIsEditingMode={setIsEditingMode}
239
+ onSave={handleSave}
240
+ onCancel={handleCancel}
241
+ hasChanges={hasChanges}
242
+ isSaving={isSaving}
243
+ />
244
+ </div>
245
+ );
246
+ };
@@ -0,0 +1,93 @@
1
+ import React from "react";
2
+ import {
3
+ TrafficChart,
4
+ TopPaths,
5
+ StatsCards,
6
+ ProductionUrl,
7
+ ProjectIdentity,
8
+ ProjectInfo,
9
+ } from "./general";
10
+ import { useProjectSettings } from "@/context/ProjectSettingsContext";
11
+
12
+ export const GeneralSettings = () => {
13
+ const {
14
+ analyticsData,
15
+ isLoadingAnalytics,
16
+ } = useProjectSettings();
17
+
18
+ // Format large numbers
19
+ const formatNumber = (num: number): string => {
20
+ if (num >= 1000000) return `${(num / 1000000).toFixed(1)}M`;
21
+ if (num >= 1000) return `${(num / 1000).toFixed(1)}K`;
22
+ return num?.toString() || '0';
23
+ };
24
+
25
+ // Analytics stats
26
+ const stats = analyticsData ? [
27
+ {
28
+ label: "Server Requests",
29
+ value: formatNumber(analyticsData.summary?.uniqueRequests),
30
+ icon: 'server%20transfer-55-1658435258.png',
31
+ subtext: `${formatNumber(analyticsData.summary?.totalRequests)} total, ${analyticsData.summary?.avgRequestsPerHour}/hr avg`
32
+ },
33
+ {
34
+ label: "Unique IPs",
35
+ value: formatNumber(analyticsData.summary?.uniqueIPs),
36
+ icon: '3%20users-246-1658436041.png',
37
+ subtext: `${analyticsData.summary?.uniqueIPsPercentage}% of total`
38
+ },
39
+ {
40
+ label: "Avg Response",
41
+ value: `${analyticsData.performance?.avgResponseTimeMs?.toFixed(2) || 'N/A '}ms`,
42
+ icon: 'flash-109-1689918656.png',
43
+ subtext: "Response time"
44
+ },
45
+ {
46
+ label: "Bandwidth Out",
47
+ value: analyticsData.bandwidth?.totalOutFormatted || 'N/A',
48
+ icon: 'servers%20connect%203-61-1658435258.png',
49
+ subtext: `${analyticsData.bandwidth?.totalInFormatted} in`
50
+ },
51
+ ] : [
52
+ { label: "Server Requests", value: "...", icon: 'trend%20up-79-1681196106.png', subtext: "Loading..." },
53
+ { label: "Unique IPs", value: "...", icon: '3%20users-246-1658436041.png', subtext: "Loading..." },
54
+ { label: "Avg Response", value: "...", icon: 'flash-109-1689918656.png', subtext: "Loading..." },
55
+ { label: "Bandwidth", value: "...", icon: 'servers%20connect%203-61-1658435258.png', subtext: "Loading..." },
56
+ ];
57
+
58
+ // Prepare data for components
59
+ const trafficData = analyticsData?.trafficByHour || [];
60
+ const topPaths = analyticsData?.topPaths || [];
61
+ const dateRange = analyticsData
62
+ ? `${new Date(analyticsData.summary.firstRequest).toLocaleDateString()} - ${new Date(analyticsData.summary.lastRequest).toLocaleDateString()}`
63
+ : undefined;
64
+
65
+
66
+ return (
67
+ <div className="space-y-5">
68
+ {/* Main Grid Layout */}
69
+ <div className="grid grid-cols-1 lg:grid-cols-3 gap-5">
70
+ {/* Left Column - 2 cols */}
71
+ <div className="lg:col-span-2 space-y-5">
72
+ <TrafficChart
73
+ trafficData={trafficData}
74
+ isLoading={isLoadingAnalytics}
75
+ dateRange={dateRange}
76
+ totalRequests={analyticsData?.summary.totalRequests}
77
+ />
78
+
79
+ <StatsCards stats={stats} />
80
+
81
+ <ProjectIdentity />
82
+ </div>
83
+
84
+ {/* Right Column - 1 col */}
85
+ <div className="space-y-5">
86
+ <ProductionUrl />
87
+ <ProjectInfo />
88
+ {topPaths.length > 0 && <TopPaths paths={topPaths} />}
89
+ </div>
90
+ </div>
91
+ </div>
92
+ );
93
+ };
@@ -0,0 +1,261 @@
1
+ import React, { useState } from "react";
2
+ import { Github, GitCommit, Zap, GitBranch, Check, X } from "lucide-react";
3
+ import { useProjectSettings } from "@/context/ProjectSettingsContext";
4
+ import { projectsApi } from "@/lib/api";
5
+ import { useToast } from "@/context/ToastContext";
6
+ import generateIcon from "@/utils/icons";
7
+ import { formatDate } from "@/utils/date";
8
+
9
+ export const GitInfo = () => {
10
+ const { projectData, id, updateProjectData } = useProjectSettings();
11
+ const { showToast } = useToast();
12
+
13
+ const [isEditingBranch, setIsEditingBranch] = useState(false);
14
+ const [tempBranch, setTempBranch] = useState(projectData?.branch || 'main');
15
+ const [branches, setBranches] = useState<string[]>([]);
16
+ const [loadingBranch, setLoadingBranch] = useState(false);
17
+ const [loadingAutoDeploy, setLoadingAutoDeploy] = useState(false);
18
+
19
+ const handleEditBranch = async () => {
20
+ if (!projectData?.id) return;
21
+
22
+ setLoadingBranch(true);
23
+ try {
24
+ // Fetch available branches
25
+ const response = await projectsApi.getBranches(projectData.id);
26
+ if (response.success) {
27
+ setBranches(response.branches || []);
28
+ setIsEditingBranch(true);
29
+ setTempBranch(projectData.branch || 'main');
30
+ } else {
31
+ showToast('Failed to fetch branches', 'error', 'Error');
32
+ }
33
+ } catch (error) {
34
+ console.error('Error fetching branches:', error);
35
+ showToast('Failed to fetch branches', 'error', 'Error');
36
+ } finally {
37
+ setLoadingBranch(false);
38
+ }
39
+ };
40
+
41
+ const handleSaveBranch = async () => {
42
+ if (!projectData?.id) return;
43
+
44
+ setLoadingBranch(true);
45
+ try {
46
+ const response = await projectsApi.setBranch(projectData.id, tempBranch);
47
+ if (response.success) {
48
+ setIsEditingBranch(false);
49
+ showToast('Branch updated successfully', 'success', 'Updated');
50
+ // You might need to refresh project data here
51
+ } else {
52
+ showToast(response.message || 'Failed to update branch', 'error', 'Error');
53
+ }
54
+ } catch (error) {
55
+ console.error('Error updating branch:', error);
56
+ showToast('Failed to update branch', 'error', 'Error');
57
+ } finally {
58
+ setLoadingBranch(false);
59
+ }
60
+ };
61
+
62
+ const handleCancelBranch = () => {
63
+ setIsEditingBranch(false);
64
+ setTempBranch(projectData?.branch || 'main');
65
+ };
66
+
67
+ const handleAutoDeployToggle = async () => {
68
+ if (!projectData?.id) return;
69
+
70
+ setLoadingAutoDeploy(true);
71
+ try {
72
+ const newAutoDeployState = !projectData.auto_deploy;
73
+ const response = await projectsApi.gitSwitch(projectData.id, newAutoDeployState);
74
+
75
+ if (response.success) {
76
+ showToast(
77
+ newAutoDeployState ? 'Auto-deploy enabled' : 'Auto-deploy disabled',
78
+ 'success',
79
+ 'Updated'
80
+ );
81
+ updateProjectData({ auto_deploy: newAutoDeployState });
82
+ } else {
83
+ showToast(response.message || 'Failed to update auto-deploy', 'error', 'Error');
84
+ }
85
+ } catch (error) {
86
+ console.error('Error updating auto-deploy:', error);
87
+ showToast('Failed to update auto-deploy', 'error', 'Error');
88
+ } finally {
89
+ setLoadingAutoDeploy(false);
90
+ }
91
+ };
92
+
93
+ return (
94
+ <div className="lg:sticky lg:top-6 h-fit space-y-4">
95
+ {/* Git Repository Card */}
96
+ <div className="bg-white rounded-[20px] border border-black/5 p-5">
97
+ <div className="flex items-center gap-3 mb-5">
98
+ {generateIcon('https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg', 24, 'white', {}, true)}
99
+ <div className="flex-1 min-w-0">
100
+ <p className="font-semibold text-base text-black truncate">{projectData?.owner + '/' + projectData?.repo || 'Repository'}</p>
101
+ <p className="text-sm text-black/50">{projectData?.branch || 'main'}</p>
102
+ </div>
103
+ </div>
104
+
105
+ {/* Auto-deploy Toggle */}
106
+ <div className="p-4 rounded-xl bg-black/5 mb-4">
107
+ <div className="flex items-center justify-between mb-2">
108
+ <div className="flex items-center gap-2">
109
+ <Zap className="h-4 w-4 text-indigo-600" />
110
+ <span className="text-sm font-medium text-black">Auto-deploy</span>
111
+ </div>
112
+ <button
113
+ type="button"
114
+ role="switch"
115
+ aria-checked={projectData?.auto_deploy || false}
116
+ onClick={handleAutoDeployToggle}
117
+ disabled={loadingAutoDeploy}
118
+ className={`
119
+ relative inline-flex h-6 w-11 items-center rounded-full transition-colors
120
+ ${projectData?.auto_deploy ? 'bg-indigo-600' : 'bg-black/20'}
121
+ ${loadingAutoDeploy ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'}
122
+ `}
123
+ >
124
+ {loadingAutoDeploy ? (
125
+ <div className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin mx-auto" />
126
+ ) : (
127
+ <span
128
+ className={`
129
+ inline-block h-4 w-4 transform rounded-full bg-white transition-transform
130
+ ${projectData?.auto_deploy ? 'translate-x-6' : 'translate-x-1'}
131
+ `}
132
+ />
133
+ )}
134
+ </button>
135
+ </div>
136
+ <p className="text-xs text-black/50">
137
+ {projectData?.auto_deploy
138
+ ? 'Deploys on every push'
139
+ : 'Manual deploys only'}
140
+ </p>
141
+ </div>
142
+
143
+ {/* Branch Selection */}
144
+ <div className="mb-4">
145
+ <div className="flex items-center justify-between mb-2">
146
+ <label className="block text-sm font-normal text-black">Branch to Deploy</label>
147
+ {!isEditingBranch && (
148
+ <button
149
+ onClick={handleEditBranch}
150
+ disabled={loadingBranch}
151
+ className="p-1.5 text-black/40 hover:text-indigo-600 transition-colors disabled:opacity-50"
152
+ >
153
+ {loadingBranch ? (
154
+ <div className="w-4 h-4 border-2 border-black/20 border-t-black/60 rounded-full animate-spin" />
155
+ ) : (
156
+ generateIcon('pen-411-1658238246.png', 16, 'rgb(0, 0, 0, 0.5)')
157
+ )}
158
+ </button>
159
+ )}
160
+ </div>
161
+
162
+ {isEditingBranch ? (
163
+ <div className="space-y-3">
164
+ <select
165
+ value={tempBranch}
166
+ onChange={(e) => setTempBranch(e.target.value)}
167
+ className="w-full px-5 py-3 border border-black/10 rounded-[15px] outline-none text-black bg-white focus:ring-2 focus:ring-black focus:border-transparent cursor-text"
168
+ >
169
+ {branches.map((branch) => (
170
+ <option key={branch} value={branch}>
171
+ {branch}
172
+ </option>
173
+ ))}
174
+ </select>
175
+ <p className="text-xs text-black/50 mt-2">
176
+ Choose which branch to deploy from your repository
177
+ </p>
178
+ <div className="flex gap-2">
179
+ <button
180
+ onClick={handleSaveBranch}
181
+ disabled={loadingBranch}
182
+ className="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 text-white rounded-full transition-all text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
183
+ >
184
+ <Check className="w-4 h-4" />
185
+ Save
186
+ </button>
187
+ <button
188
+ onClick={handleCancelBranch}
189
+ className="px-4 py-2 bg-black/5 hover:bg-black/10 text-black rounded-full transition-all text-sm font-medium flex items-center gap-2"
190
+ >
191
+ <X className="w-4 h-4" />
192
+ Cancel
193
+ </button>
194
+ </div>
195
+ </div>
196
+ ) : (
197
+ <div className="relative p-4 bg-white rounded-xl group hover:bg-black/5 transition-all border border-black/10">
198
+ <div className="flex items-center gap-3">
199
+ <GitBranch className="w-5 h-5 text-black/50" />
200
+ <p className="text-sm font-medium text-black flex-1 font-mono">{projectData?.branch || 'main'}</p>
201
+ </div>
202
+ </div>
203
+ )}
204
+ </div>
205
+
206
+ {/* Action Buttons */}
207
+ <div className="space-y-2">
208
+ <a
209
+ href={projectData?.repositoryUrl || 'https://github.com/' + projectData?.owner + '/' + projectData?.repo}
210
+ target="_blank"
211
+ rel="noopener noreferrer"
212
+ className="w-full px-4 py-2.5 bg-black/5 hover:bg-black/10 text-black rounded-full font-medium text-sm transition-all flex items-center justify-center gap-2"
213
+ >
214
+ {generateIcon('External_link_HtLszLDBXqHilHK674zh2aKoSL7xUhyboAzP.png', 16, 'currentColor')}
215
+ View on GitHub
216
+ </a>
217
+ </div>
218
+ </div>
219
+
220
+ {/* Recent Commits - Only show if there are commits */}
221
+ {(projectData?.commitCount || 0) > 0 && (
222
+ <div className="bg-white rounded-[20px] border border-black/5 p-5">
223
+ <div className="flex items-center justify-between mb-4">
224
+ <h3 className="text-sm font-semibold text-black flex items-center gap-2">
225
+ {generateIcon('commit%20git-24-1658431404.png', 20, 'black')}
226
+ Recent Commits
227
+ </h3>
228
+ <span className="text-xs text-black/50 bg-black/5 px-2 py-1 rounded-full">
229
+ {projectData?.commitCount || 0} total
230
+ </span>
231
+ </div>
232
+
233
+ {projectData?.recentCommits && projectData.recentCommits.length > 0 ? (
234
+ <div className="space-y-3">
235
+ {projectData.recentCommits.slice(0, 3).map((commit: any, i: number) => (
236
+ <div key={i} className="p-3 bg-black/5 rounded-lg border border-black/10">
237
+ <div className="flex items-start gap-2 mb-2">
238
+ <div className="w-2 h-2 bg-indigo-500 rounded-full mt-2 flex-shrink-0"></div>
239
+ <div className="flex-1 min-w-0">
240
+ <p className="text-xs font-medium text-black truncate">{commit.message}</p>
241
+ <div className="flex items-center gap-2 text-xs mt-1 text-black/50">
242
+ <span className="font-mono">{commit.id?.substring(0, 7)}</span>
243
+ <span>•</span>
244
+ <span>{formatDate(commit.time, undefined, undefined, true)}</span>
245
+ </div>
246
+ </div>
247
+ </div>
248
+ </div>
249
+ ))}
250
+ </div>
251
+ ) : (
252
+ <div className="text-center py-6">
253
+ <GitCommit className="h-8 w-8 text-black/20 mx-auto mb-2" />
254
+ <p className="text-xs text-black/50">No commits yet</p>
255
+ </div>
256
+ )}
257
+ </div>
258
+ )}
259
+ </div>
260
+ );
261
+ };