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,510 @@
1
+ "use client";
2
+
3
+ import React, { useState, useEffect, useCallback, memo } from "react";
4
+ import Image from "next/image";
5
+ import {
6
+ CheckCircle2,
7
+ Loader2,
8
+ Clock,
9
+ } from "lucide-react";
10
+ import type { Terminal } from "@xterm/xterm";
11
+ import BuildTerminal from "./BuildTerminal";
12
+ import { generateIcon } from "@/utils/icons";
13
+ import { useRouter } from "next/navigation";
14
+ import { encodeRepoSlug } from "@/utils/repoSlug";
15
+ import { useDeployment } from "@/context/DeploymentContext";
16
+ import { useTheme } from "@/components/theme-provider";
17
+
18
+ interface DeploymentProcessingProps {
19
+ onRedeploy: () => void; // Keep this as it updates URL
20
+ }
21
+
22
+ const DeploymentProcessing: React.FC<DeploymentProcessingProps> = ({ onRedeploy }) => {
23
+ const { config, state, terminalRef, onTerminalReady, stopDeployment, steps, deploymentStatus } = useDeployment();
24
+ const { resolvedTheme } = useTheme();
25
+ const router = useRouter();
26
+
27
+ // Build domain for display
28
+ const domain = config.domainType === "free"
29
+ ? `${config.domain || config.projectName}.opsh.io`
30
+ : config.customDomain;
31
+
32
+ const handleTerminalReady = useCallback((terminal: Terminal) => {
33
+ if (terminalRef) {
34
+ terminalRef.current = terminal;
35
+ }
36
+ onTerminalReady();
37
+ }, [terminalRef, onTerminalReady]);
38
+
39
+ const handleFixWithAI = () => {
40
+ window.open('https://blurs.app', '_blank');
41
+ };
42
+
43
+ // Get medium variant screenshot URL
44
+ const getScreenshotUrl = () => {
45
+ if (!state.screenshots || state.screenshots.length === 0) return null;
46
+ const firstScreenshot = state.screenshots[0];
47
+ const mediumVariant = firstScreenshot?.variants?.find(v => v.variant === "medium");
48
+ return mediumVariant?.url || firstScreenshot?.url;
49
+ };
50
+
51
+ const screenshotUrl = getScreenshotUrl();
52
+
53
+ const handleViewDashboard = () => {
54
+ if (state.projectId) {
55
+ router.push(`/projects/${state.projectId}`);
56
+ }
57
+ };
58
+
59
+ return (
60
+ <div className="min-h-screen bg-background mx-auto md:px-12">
61
+ {/* Header */}
62
+ <div className="bg-background">
63
+ <div className="py-5 relative">
64
+ <div className="flex items-center justify-between">
65
+ <div className="flex items-center gap-4">
66
+ <div className="flex border border-border/50 bg-muted/50 rounded-lg w-12 h-12 justify-center items-center">
67
+ {generateIcon('space%20rocket-85-1687505546.png', 30, 'currentColor')}
68
+ </div>
69
+ <div>
70
+ <h1 className="text-xl font-semibold text-foreground">
71
+ {deploymentStatus === "cancelled"
72
+ ? "Deployment Cancelled"
73
+ : deploymentStatus === "failed"
74
+ ? "Deployment Failed"
75
+ : deploymentStatus === "ready"
76
+ ? "Deployment Successful"
77
+ : "Deploying..."}
78
+ </h1>
79
+ <div className="flex items-center gap-2 mb-1">
80
+ <p className="text-sm text-muted-foreground mt-0.5">
81
+ {config.owner}/{config.repo}
82
+ </p>
83
+ </div>
84
+ </div>
85
+ </div>
86
+
87
+ {deploymentStatus === "ready" && (
88
+ <div className="flex items-center gap-2">
89
+ <button
90
+ onClick={handleViewDashboard}
91
+ className="flex items-center gap-2 text-foreground font-medium transition-all duration-300 bg-card rounded-full px-4 py-2 text-sm border border-border hover:shadow-md"
92
+ >
93
+ View dashboard
94
+ </button>
95
+ <button
96
+ onClick={() => window.open(`https://${domain}`, "_blank")}
97
+ className="flex items-center gap-2 text-primary-foreground font-medium transition-all duration-300 bg-primary rounded-full px-4 py-2 text-sm hover:bg-primary/90 shadow-md hover:shadow-lg"
98
+ >
99
+ Visit Site
100
+ {generateIcon('External_link_HtLszLDBXqHilHK674zh2aKoSL7xUhyboAzP.png', 16, '#fff')}
101
+ </button>
102
+ </div>
103
+ )}
104
+
105
+ {(deploymentStatus === "failed" || deploymentStatus === "cancelled") && (
106
+ <button
107
+ onClick={handleFixWithAI}
108
+ className="flex items-center gap-2 px-5 py-2 bg-primary text-primary-foreground rounded-full transition-all font-medium text-sm shadow-md hover:shadow-lg hover:bg-primary/90"
109
+ >
110
+ {generateIcon('stars-123-1687505546.png', 20, 'var(--color-background)')}
111
+ Fix with Blurs AI
112
+ </button>
113
+ )}
114
+ </div>
115
+ </div>
116
+ </div>
117
+
118
+ <div className="w-full">
119
+ <div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
120
+ {/* Main Content */}
121
+ <div className="lg:col-span-2 space-y-6">
122
+ {/* Progress Steps */}
123
+ <div className="bg-card rounded-2xl border border-border/50 p-8 transition-all duration-300">
124
+ <h2 className="text-base font-normal text-foreground mb-6">Deployment Progress</h2>
125
+
126
+ {/* Steps */}
127
+ <div className="relative">
128
+ {/* Progress Line */}
129
+ <div className="absolute top-6 left-[24px] right-[24px] z-0 h-[2px] bg-border/50">
130
+ <div
131
+ className="h-full transition-all duration-500 bg-primary"
132
+ style={{
133
+ width: `${(state.currentStepIndex / (steps.length - 1)) * 100}%`,
134
+ }}
135
+ />
136
+ </div>
137
+
138
+ {/* Step Items */}
139
+ <div className="relative flex justify-between z-10">
140
+ {steps.map((step, index) => {
141
+ const isCompleted = index < state.currentStepIndex;
142
+ const isCurrent = index === state.currentStepIndex && !state.deploymentSuccess && !state.deploymentFailed && !state.deploymentCanceled;
143
+ const hasFailed = (state.deploymentFailed || state.deploymentCanceled) && index === state.currentStepIndex;
144
+ const isReady = state.deploymentSuccess && index === steps.length - 1;
145
+
146
+ return (
147
+ <div key={index} className="flex flex-col items-center z-10 px-2">
148
+ <div
149
+ style={{ boxShadow: '0 0 0 8px var(--th-card-bg-solid)' }}
150
+ className={`rounded-full flex items-center justify-center transition-all duration-300 relative w-12 h-12 ${
151
+ hasFailed
152
+ ? 'bg-destructive'
153
+ : isReady || isCompleted
154
+ ? 'bg-primary'
155
+ : isCurrent
156
+ ? 'bg-foreground'
157
+ : 'bg-card border-2 border-border'
158
+ }`}
159
+ >
160
+ {hasFailed ? (
161
+ generateIcon('error%20triangle-16-1662499385.png', 26, '#fff')
162
+ ) : isReady || isCompleted ? (
163
+ generateIcon('check%20circle-68-1658234612.png', 26, 'var(--primary-foreground)')
164
+ ) : isCurrent ? (
165
+ <Loader2 className="w-6 h-6 text-background animate-spin" />
166
+ ) : (
167
+ generateIcon(step.icon, 24, 'var(--th-text-muted)')
168
+ )}
169
+ </div>
170
+ <span
171
+ className={`text-sm font-normal mt-3 ${
172
+ hasFailed || isCompleted || isCurrent || isReady
173
+ ? 'text-foreground'
174
+ : 'text-muted-foreground'
175
+ }`}
176
+ >
177
+ {step.label}
178
+ </span>
179
+ </div>
180
+ );
181
+ })}
182
+ </div>
183
+ </div>
184
+
185
+ {/* Progress Bar */}
186
+ {deploymentStatus !== "ready" && deploymentStatus !== "failed" && deploymentStatus !== "cancelled" && (
187
+ <div className="mt-6">
188
+ <div className="flex items-center justify-between text-sm mb-2">
189
+ <span className="text-muted-foreground font-medium">Overall Progress</span>
190
+ <span className="font-bold text-foreground">{Math.round(state.currentProgress)}%</span>
191
+ </div>
192
+ <div className="h-1.5 rounded-full overflow-hidden bg-border/50">
193
+ <div
194
+ className="h-full transition-all duration-300 bg-primary"
195
+ style={{ width: `${state.currentProgress}%` }}
196
+ />
197
+ </div>
198
+ </div>
199
+ )}
200
+ </div>
201
+
202
+ {/* Build Terminal */}
203
+ <div className="bg-card rounded-2xl border border-border/50 p-6 mb-20">
204
+ <div className="flex items-center justify-between mb-4">
205
+ <div className="flex items-center gap-2">
206
+ {generateIcon('terminal-58-1658431404.png', 24, 'currentColor')}
207
+ <h2 className="text-base font-normal text-foreground">
208
+ {state.deploymentSuccess && config.options.hasServer ? "Production Logs" : "Build Terminal"}
209
+ </h2>
210
+ </div>
211
+ {deploymentStatus === "failed" && (
212
+ <span className="text-sm font-normal text-muted-foreground">See logs for issue details</span>
213
+ )}
214
+ </div>
215
+
216
+ <div className="bg-white dark:bg-black border border-border/50 rounded-xl overflow-hidden h-[400px]">
217
+ <BuildTerminal
218
+ onReady={handleTerminalReady}
219
+ mockData={false}
220
+ theme={resolvedTheme}
221
+ />
222
+ </div>
223
+ </div>
224
+ </div>
225
+
226
+ {/* Sidebar */}
227
+ <div className="lg:sticky lg:top-6 h-fit space-y-6">
228
+ {/* Preview Card */}
229
+ <div className="bg-card rounded-2xl border border-border/50 p-6">
230
+ <h3 className="text-base font-normal text-foreground mb-4">Preview</h3>
231
+
232
+ {deploymentStatus === "ready" ? (
233
+ <div className="space-y-4">
234
+ <button
235
+ onClick={() => window.open(`https://${domain}`, "_blank")}
236
+ className="w-full group cursor-pointer"
237
+ >
238
+ <div
239
+ className="aspect-video bg-muted/50 rounded-xl border border-border/50 flex items-center justify-center overflow-hidden relative transition-all duration-300"
240
+ >
241
+ {screenshotUrl ? (
242
+ <img
243
+ src={screenshotUrl}
244
+ alt="Site preview"
245
+ className="w-full h-full object-cover"
246
+ />
247
+ ) : (
248
+ <div className="relative w-full h-full flex items-center justify-center overflow-hidden bg-primary/5">
249
+ {/* Animated gradient orbs */}
250
+ <div className="absolute top-0 left-0 w-32 h-32 rounded-full blur-3xl opacity-30 animate-pulse" style={{ animationDuration: '3s' }}></div>
251
+ <div className="absolute bottom-0 right-0 w-40 h-40 rounded-full blur-3xl opacity-20 animate-pulse" style={{ animationDuration: '4s', animationDelay: '1s' }}></div>
252
+
253
+ {/* Subtle grid pattern */}
254
+ <div className="absolute inset-0 opacity-[0.04]" style={{ backgroundImage: 'linear-gradient(currentColor 1px, transparent 1px), linear-gradient(90deg, currentColor 1px, transparent 1px)', backgroundSize: '24px 24px' }}></div>
255
+
256
+ {/* Content */}
257
+ <div className="relative text-center space-y-4">
258
+ {/* Icon with glow effect */}
259
+ <div className="inline-flex items-center justify-center w-16 h-16 rounded-2xl border border-primary/30 shadow-lg shadow-primary/20">
260
+ <div className="relative">
261
+ {generateIcon('cloud%20connected-57-1658236831.png', 32, 'var(--color-primary)')}
262
+ {/* Ping animation */}
263
+ <span className="absolute inset-0 w-8 h-8 rounded-full border-2 border-primary/40 animate-ping opacity-75"></span>
264
+ </div>
265
+ </div>
266
+
267
+ <div>
268
+ <p className="text-base font-semibold text-foreground tracking-tight">Deployment Live</p>
269
+ <div className="flex items-center justify-center gap-1.5 mt-2">
270
+ <div className="w-1.5 h-1.5 rounded-full bg-primary animate-pulse"></div>
271
+ <p className="text-xs font-medium text-primary">Ready to visit</p>
272
+ </div>
273
+ </div>
274
+ </div>
275
+ </div>
276
+ )}
277
+ <div className="absolute inset-0 bg-foreground/0 group-hover:bg-foreground/10 transition-all flex items-center justify-center backdrop-blur-0 group-hover:backdrop-blur-sm">
278
+ <div className="opacity-0 group-hover:opacity-100 transition-all duration-300 transform scale-95 group-hover:scale-100">
279
+ <div className="bg-foreground/80 backdrop-blur-md text-background px-5 py-2.5 rounded-xl flex items-center gap-2.5 shadow-xl border border-background/10">
280
+ {generateIcon('earth-29-1687505545.png', 20, '#fff')}
281
+ <span className="font-medium text-sm">Visit Site</span>
282
+ {generateIcon('External_link_HtLszLDBXqHilHK674zh2aKoSL7xUhyboAzP.png', 18, '#fff')}
283
+ </div>
284
+ </div>
285
+ </div>
286
+ </div>
287
+ </button>
288
+ </div>
289
+ ) : (
290
+ <div className="aspect-video bg-muted/30 rounded-xl border-2 border-border overflow-hidden relative">
291
+ {/* Shimmer effect overlay */}
292
+ <div
293
+ className="absolute inset-0 -translate-x-full animate-[shimmer_2s_infinite]"
294
+ style={{
295
+ background: 'linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.8) 50%, transparent 100%)',
296
+ }}
297
+ />
298
+
299
+ {/* Mock browser chrome */}
300
+ <div className="h-8 bg-card/60 border-b border-border/50 flex items-center px-3 gap-2">
301
+ <div className="flex gap-1.5">
302
+ <div className="w-2.5 h-2.5 rounded-full bg-destructive/40 animate-pulse" />
303
+ <div className="w-2.5 h-2.5 rounded-full bg-yellow-400/40 animate-pulse" style={{ animationDelay: '0.1s' }} />
304
+ <div className="w-2.5 h-2.5 rounded-full bg-green-400/40 animate-pulse" style={{ animationDelay: '0.2s' }} />
305
+ </div>
306
+ <div className="flex-1 ml-4">
307
+ <div className="h-4 bg-muted/60 rounded-md w-3/4 animate-pulse" style={{ animationDelay: '0.3s' }} />
308
+ </div>
309
+ </div>
310
+
311
+ {/* Mock content */}
312
+ <div className="p-6 space-y-4">
313
+ <div className="h-6 bg-muted/60 rounded-lg w-1/3 animate-pulse" style={{ animationDelay: '0.1s' }} />
314
+ <div className="space-y-2">
315
+ <div className="h-4 bg-muted/60 rounded w-full animate-pulse" style={{ animationDelay: '0.2s' }} />
316
+ <div className="h-4 bg-muted/60 rounded w-5/6 animate-pulse" style={{ animationDelay: '0.3s' }} />
317
+ <div className="h-4 bg-muted/60 rounded w-4/6 animate-pulse" style={{ animationDelay: '0.4s' }} />
318
+ </div>
319
+ <div className="grid grid-cols-3 gap-3 mt-6">
320
+ <div className="h-20 bg-muted/60 rounded-lg animate-pulse" style={{ animationDelay: '0.2s' }} />
321
+ <div className="h-20 bg-muted/60 rounded-lg animate-pulse" style={{ animationDelay: '0.3s' }} />
322
+ <div className="h-20 bg-muted/60 rounded-lg animate-pulse" style={{ animationDelay: '0.4s' }} />
323
+ </div>
324
+ </div>
325
+
326
+ {/* Status text */}
327
+ <div className="absolute inset-0 flex items-center justify-center bg-card/5 backdrop-blur-[2px]">
328
+ <div className="text-center px-6 py-3 rounded-xl bg-card/90 backdrop-blur-sm border border-border/50 shadow-lg">
329
+ <div className="flex items-center gap-3">
330
+ <div className="relative">
331
+ {(deploymentStatus === "failed" || deploymentStatus === "cancelled") ? (
332
+ <>
333
+ {generateIcon('error%20triangle-16-1662499385.png', 20, 'currentColor')}
334
+ </>
335
+ ) : (
336
+ <>
337
+ <Loader2 className="w-5 h-5 text-primary animate-spin" />
338
+ <div className="absolute inset-0 w-5 h-5 border-2 border-primary/30 rounded-full animate-ping" />
339
+ </>
340
+ )}
341
+ </div>
342
+ <div>
343
+ <p className="text-sm font-normal text-foreground">
344
+ {deploymentStatus === "cancelled" ? "Deployment cancelled" : deploymentStatus === "failed" ? "Deployment failed" : "Building preview"}
345
+ </p>
346
+ {(deploymentStatus !== "failed" && deploymentStatus !== "cancelled") && (
347
+ <div className="flex gap-1 mt-1">
348
+ <span className="w-1.5 h-1.5 bg-primary rounded-full animate-bounce" />
349
+ <span className="w-1.5 h-1.5 bg-primary rounded-full animate-bounce" style={{ animationDelay: '0.1s' }} />
350
+ <span className="w-1.5 h-1.5 bg-primary rounded-full animate-bounce" style={{ animationDelay: '0.2s' }} />
351
+ </div>
352
+ )}
353
+ </div>
354
+ </div>
355
+ </div>
356
+ </div>
357
+ </div>
358
+ )}
359
+ </div>
360
+
361
+ {/* Deployment Info */}
362
+ <DeploymentDetails />
363
+
364
+ {/* Action Button */}
365
+ <div className="bg-card rounded-2xl border border-border/50 p-4">
366
+ {deploymentStatus === "deploying" || deploymentStatus === "building" ? (
367
+ <button
368
+ onClick={stopDeployment}
369
+ disabled={state.isStopping}
370
+ className={`w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-xl transition-all font-medium text-sm border ${state.isStopping
371
+ ? 'bg-muted text-muted-foreground border-border cursor-not-allowed'
372
+ : 'bg-destructive/10 text-destructive border-destructive/20 hover:bg-destructive/15 hover:border-destructive/30'
373
+ }`}
374
+ >
375
+ {state.isStopping ? (
376
+ <>
377
+ <svg className="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
378
+ <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
379
+ <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
380
+ </svg>
381
+ Stopping...
382
+ </>
383
+ ) : (
384
+ 'Stop Deployment'
385
+ )}
386
+ </button>
387
+ ) : (deploymentStatus === "failed" || deploymentStatus === "cancelled") ? (
388
+ <button
389
+ onClick={onRedeploy}
390
+ className="w-full flex items-center justify-center gap-2 px-4 py-2.5 bg-primary text-primary-foreground rounded-xl transition-all font-medium text-sm hover:bg-primary/90"
391
+ >
392
+ Redeploy
393
+ </button>
394
+ ) : (deploymentStatus === "ready") ? (
395
+ <button
396
+ onClick={handleViewDashboard}
397
+ className="w-full flex items-center justify-center gap-2 px-4 py-2.5 bg-primary text-primary-foreground rounded-xl transition-all font-medium text-sm hover:bg-primary/90"
398
+ >
399
+ Open Dashboard
400
+ </button>
401
+ ) : null}
402
+
403
+ </div>
404
+
405
+ </div>
406
+ </div>
407
+ </div>
408
+ </div>
409
+ );
410
+ };
411
+
412
+ const DeploymentDetails = memo(() => {
413
+ const { state, deploymentStatus, config } = useDeployment();
414
+ const [buildTime, setBuildTime] = useState<number>(() => {
415
+ // Initialize from persisted duration if available
416
+ if (state.buildDurationMs) return Math.round(state.buildDurationMs / 1000);
417
+ // For in-progress builds, calculate elapsed from startedAt
418
+ if (state.buildStartedAt) {
419
+ return Math.max(0, Math.round((Date.now() - new Date(state.buildStartedAt).getTime()) / 1000));
420
+ }
421
+ return 0;
422
+ });
423
+ const router = useRouter();
424
+
425
+ // Sync final duration when build completes
426
+ useEffect(() => {
427
+ if (state.buildDurationMs && (state.deploymentSuccess || state.deploymentFailed || state.deploymentCanceled)) {
428
+ setBuildTime(Math.round(state.buildDurationMs / 1000));
429
+ }
430
+ }, [state.buildDurationMs, state.deploymentSuccess, state.deploymentFailed, state.deploymentCanceled]);
431
+
432
+ useEffect(() => {
433
+ if (state.deploymentSuccess || state.deploymentFailed || state.deploymentCanceled) {
434
+ return;
435
+ }
436
+
437
+ const timerInterval = setInterval(() => {
438
+ setBuildTime((prev) => prev + 1);
439
+ }, 1000);
440
+
441
+ return () => clearInterval(timerInterval);
442
+ }, [state.deploymentSuccess, state.deploymentFailed, state.deploymentCanceled]);
443
+
444
+ const handleEdit = () => {
445
+ const slug = encodeRepoSlug(config.owner, config.repo);
446
+ router.push(`/deploy/${slug}?force=true`);
447
+ };
448
+
449
+ const formatTime = (seconds: number) => {
450
+ const mins = Math.floor(seconds / 60);
451
+ const secs = seconds % 60;
452
+ return `${mins}:${secs.toString().padStart(2, "0")}`;
453
+ };
454
+
455
+ return (
456
+ <div className="bg-card rounded-2xl border border-border/50 p-6">
457
+ <div className="flex items-center justify-between mb-3">
458
+ <h3 className="text-base font-normal text-foreground">Deployment Details</h3>
459
+ {(state.deploymentCanceled || state.deploymentFailed) && (
460
+ <button onClick={handleEdit} className="flex items-center gap-2 -mr-1 cursor-pointer opacity-50 hover:opacity-100 transition-all duration-300">
461
+ <span className="text-sm text-foreground">Edit</span>
462
+ {generateIcon('pen-404-1658238246.png', 18, 'currentColor')}
463
+ </button>
464
+ )}
465
+ </div>
466
+ <div className="space-y-0">
467
+ <div className="flex justify-between items-center py-1.5 border-b border-border/50">
468
+ <span className="text-sm text-muted-foreground">Status</span>
469
+ <span
470
+ className={`text-sm font-normal px-3 py-1 rounded-full border
471
+ ${deploymentStatus === "failed" || deploymentStatus === "cancelled"
472
+ ? "bg-destructive/10 text-destructive border-destructive/20"
473
+ : "bg-primary/10 text-primary border-primary/20"
474
+ }`}
475
+ >
476
+ {deploymentStatus === "cancelled" ? "Cancelled" : deploymentStatus === "failed" ? "Failed" : deploymentStatus === "ready" ? "Ready" : "Building"}
477
+ </span>
478
+ </div>
479
+ <div className="flex justify-between items-center py-1.5 border-b border-border/50">
480
+ <span className="text-sm text-muted-foreground">Build Time</span>
481
+ <span className="text-sm font-normal text-foreground flex items-center gap-1.5">
482
+ <Clock className="w-3.5 h-3.5 text-muted-foreground" />
483
+ {formatTime(buildTime)}
484
+ </span>
485
+ </div>
486
+ <div className="flex justify-between items-center py-1.5 border-b border-border/50">
487
+ <span className="text-sm text-muted-foreground">Domain</span>
488
+ <span className="text-sm font-normal text-foreground">{config.domainType === "free" ? `${config.domain || config.projectName}.opsh.io` : config.customDomain}</span>
489
+ </div>
490
+ <div className="flex justify-between items-center py-1.5 border-b border-border/50">
491
+ <span className="text-sm text-muted-foreground">Branch</span>
492
+ <span className="text-sm font-normal text-foreground flex items-center gap-1">
493
+ {generateIcon('git%20branch-159-1658431404.png', 16, 'currentColor')}
494
+ {config.branch}
495
+ </span>
496
+ </div>
497
+ <div className="flex justify-between items-center py-1.5">
498
+ <span className="text-sm text-muted-foreground">Framework</span>
499
+ <span className="text-sm font-normal text-foreground">{config.framework}</span>
500
+ </div>
501
+ </div>
502
+
503
+ </div>
504
+ );
505
+ });
506
+
507
+ DeploymentDetails.displayName = "DeploymentDetails";
508
+
509
+ export default DeploymentProcessing;
510
+
@@ -0,0 +1,64 @@
1
+ import React from "react";
2
+ import { Container, Hash } from "lucide-react";
3
+ import { useDeployment } from "@/context/DeploymentContext";
4
+ import { STACK_ICONS } from "@repo/core";
5
+
6
+ const DockerSettings: React.FC = () => {
7
+ const { config, updateOptions } = useDeployment();
8
+ const iconUrl = STACK_ICONS["docker"];
9
+
10
+ return (
11
+ <div className="bg-card rounded-2xl border border-border/50">
12
+ <div className="px-5 py-5 space-y-5">
13
+ {/* Header */}
14
+ <div className="flex items-center gap-3">
15
+ <div className="p-2.5 bg-primary/10 rounded-xl">
16
+ {iconUrl ? (
17
+ <img src={iconUrl} alt="Docker" className="w-6 h-6" />
18
+ ) : (
19
+ <Container className="w-6 h-6 text-primary" />
20
+ )}
21
+ </div>
22
+ <div>
23
+ <h3 className="text-[15px] font-semibold text-foreground">Dockerfile Detected</h3>
24
+ <p className="text-xs text-muted-foreground">
25
+ Your project will be built and deployed using its Dockerfile
26
+ </p>
27
+ </div>
28
+ </div>
29
+
30
+ {/* Info card */}
31
+ <div className="p-4 bg-muted/30 rounded-xl border border-border/50">
32
+ <p className="text-sm text-muted-foreground leading-relaxed">
33
+ No build settings needed — your Dockerfile defines the build process.
34
+ Just configure the port your application listens on.
35
+ </p>
36
+ </div>
37
+
38
+ {/* Port config */}
39
+ <div>
40
+ <label className="flex items-center gap-2 text-sm font-medium text-foreground mb-2">
41
+ <span className="text-muted-foreground">
42
+ <Hash className="size-4" />
43
+ </span>
44
+ Exposed Port
45
+ </label>
46
+ <input
47
+ type="number"
48
+ value={config.options.productionPort}
49
+ onChange={(e) => updateOptions({ productionPort: e.target.value })}
50
+ placeholder="3000"
51
+ min={1}
52
+ max={65535}
53
+ className="w-full px-4 py-2.5 bg-muted/30 border border-border/50 rounded-xl text-sm text-foreground placeholder:text-muted-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary/20 transition-all"
54
+ />
55
+ <p className="text-xs text-muted-foreground mt-1.5">
56
+ The port your container exposes (from EXPOSE or CMD)
57
+ </p>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ );
62
+ };
63
+
64
+ export default React.memo(DockerSettings);