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,376 @@
1
+ import React, { useState } from "react";
2
+ import { Terminal, FolderOutput, Server, Package, Play, Hash, Settings2, ChevronDown, ChevronUp, Pencil, Hammer, BoxSelect, ShieldCheck } from "lucide-react";
3
+ import { Toggle } from "@/components/project-settings/ServerSideSwitch";
4
+ import { useDeployment } from "@/context/DeploymentContext";
5
+
6
+ interface InputField {
7
+ key: string;
8
+ label: string;
9
+ placeholder: string;
10
+ description: string;
11
+ type: 'text' | 'number';
12
+ min?: number;
13
+ max?: number;
14
+ optional?: boolean;
15
+ icon: React.ReactNode;
16
+ }
17
+
18
+ interface BuildSettingsProps {
19
+ variant?: 'deploy' | 'import';
20
+ mode?: 'simple' | 'advanced';
21
+ buildData?: any;
22
+ onSave?: (field: string, value: string) => Promise<void>;
23
+ loading?: { [key: string]: boolean };
24
+ buildConfig?: any;
25
+ updateOptions?: (options: any) => void;
26
+ }
27
+
28
+ const BuildSettings: React.FC<BuildSettingsProps> = ({
29
+ mode = 'simple',
30
+ buildData: externalBuildData,
31
+ onSave,
32
+ loading = {},
33
+ buildConfig,
34
+ updateOptions: externalUpdateOptions
35
+ }) => {
36
+ const deploymentContext = mode === 'simple' ? useDeployment() : { config: buildConfig || {}, updateOptions: () => { }, updateConfig: () => {} };
37
+ const { config, updateOptions, updateConfig } = deploymentContext || { config: buildConfig || {}, updateOptions: externalUpdateOptions, updateConfig: () => {} };
38
+
39
+ const [isEditing] = useState(mode === 'simple');
40
+
41
+ const [editingField, setEditingField] = useState<string | null>(null);
42
+ const [tempValues, setTempValues] = useState<{ [key: string]: string }>({});
43
+ const [expanded, setExpanded] = useState(true);
44
+ const [advancedOpen, setAdvancedOpen] = useState(false);
45
+
46
+ const buildData = mode === 'advanced' ? externalBuildData : config?.options;
47
+ const needsBuild = config?.framework !== "node" && config?.framework !== "static";
48
+
49
+ const hasBuild = buildData?.hasBuild !== false;
50
+ const hasServer = !!buildData?.hasServer;
51
+
52
+ // ── Build-group fields (shown when Build is ON) ──────────────────
53
+ const buildFields: InputField[] = [
54
+ {
55
+ key: 'installCommand',
56
+ label: 'Install Command',
57
+ placeholder: 'bun install',
58
+ description: 'Command to install dependencies',
59
+ type: 'text',
60
+ icon: <Package className="size-4" />
61
+ },
62
+ ...(needsBuild ? [
63
+ {
64
+ key: 'buildCommand',
65
+ label: 'Build Command',
66
+ placeholder: 'npm run build',
67
+ description: 'Command to build your project',
68
+ type: 'text' as const,
69
+ icon: <Terminal className="size-4" />
70
+ },
71
+ {
72
+ key: 'outputDirectory',
73
+ label: 'Output Directory',
74
+ placeholder: '.next',
75
+ description: 'Directory with build output',
76
+ type: 'text' as const,
77
+ icon: <FolderOutput className="size-4" />
78
+ },
79
+ ] : []),
80
+ ];
81
+
82
+ // ── Advanced fields (hidden behind toggle) ───────────────────────
83
+ const advancedFields: InputField[] = needsBuild ? [
84
+ {
85
+ key: 'productionPaths',
86
+ label: 'Production Paths',
87
+ placeholder: 'dist, node_modules, package.json',
88
+ description: 'Only deploy these files/dirs after build — hides source code from runtime. Leave empty to run in-place.',
89
+ type: 'text',
90
+ optional: true,
91
+ icon: <ShieldCheck className="size-4" />
92
+ },
93
+ ] : [];
94
+
95
+ // ── Start-group fields (shown when Start is ON) ──────────────────
96
+ const startFields: InputField[] = [
97
+ {
98
+ key: 'startCommand',
99
+ label: 'Start Command',
100
+ placeholder: 'npm start',
101
+ description: 'Command to start your application',
102
+ type: 'text',
103
+ icon: <Play className="size-4" />
104
+ },
105
+ {
106
+ key: 'productionPort',
107
+ label: 'Production Port',
108
+ placeholder: '3000',
109
+ description: 'Production port for your application',
110
+ type: 'number',
111
+ min: 1,
112
+ max: 65535,
113
+ optional: true,
114
+ icon: <Hash className="size-4" />
115
+ },
116
+ ];
117
+
118
+ // ── General fields (always visible) ──────────────────────────────
119
+ const generalFields: InputField[] = [
120
+ {
121
+ key: 'rootDirectory',
122
+ label: 'Root Directory',
123
+ placeholder: './',
124
+ description: 'Deploy a subdirectory of your repository',
125
+ type: 'text',
126
+ optional: true,
127
+ icon: <FolderOutput className="size-4" />
128
+ },
129
+ ];
130
+
131
+ const handleEdit = (field: string, currentValue: string) => {
132
+ setEditingField(field);
133
+ setTempValues({ ...tempValues, [field]: currentValue || '' });
134
+ };
135
+
136
+ const handleSave = async (field: string) => {
137
+ if (mode === 'advanced' && onSave) {
138
+ await onSave(field, tempValues[field]);
139
+ setEditingField(null);
140
+ }
141
+ };
142
+
143
+ const handleCancel = (field: string, originalValue: string) => {
144
+ setEditingField(null);
145
+ setTempValues({ ...tempValues, [field]: originalValue });
146
+ };
147
+
148
+ const handleChange = (field: string, value: string) => {
149
+ if (mode === 'simple' && updateOptions) {
150
+ updateOptions({ [field]: value } as any);
151
+ } else {
152
+ setTempValues({ ...tempValues, [field]: value });
153
+ }
154
+ };
155
+
156
+ const renderInput = (field: InputField) => {
157
+ const value = mode === 'simple' ? (config?.options as any)?.[field.key] : buildData?.[field.key];
158
+ const isCurrentlyEditing = mode === 'advanced' && editingField === field.key;
159
+ const displayValue = isCurrentlyEditing ? tempValues[field.key] : value;
160
+
161
+ if (mode === 'simple') {
162
+ return (
163
+ <div key={field.key}>
164
+ <label className="text-xs font-medium text-muted-foreground mb-1.5 block">
165
+ {field.label}
166
+ {field.optional && (
167
+ <span className="text-muted-foreground/50 ml-1">(Optional)</span>
168
+ )}
169
+ </label>
170
+ <input
171
+ type={field.type}
172
+ min={field.min}
173
+ max={field.max}
174
+ value={displayValue || ''}
175
+ onChange={(e) => handleChange(field.key, e.target.value)}
176
+ readOnly={!isEditing}
177
+ placeholder={field.placeholder}
178
+ className={`w-full px-3.5 py-2.5 border border-border/50 rounded-lg text-sm text-foreground transition-all ${isEditing
179
+ ? 'bg-muted/30 focus:outline-none focus:ring-2 focus:ring-primary/20 cursor-text'
180
+ : 'bg-muted/20 cursor-not-allowed text-muted-foreground'
181
+ }`}
182
+ />
183
+ </div>
184
+ );
185
+ }
186
+
187
+ // Advanced mode
188
+ return (
189
+ <div key={field.key}>
190
+ <div className="mb-3">
191
+ <h3 className="text-sm font-medium text-foreground">{field.label}</h3>
192
+ <p className="text-xs text-muted-foreground mt-1">{field.description}</p>
193
+ </div>
194
+
195
+ {isCurrentlyEditing ? (
196
+ <div className="space-y-3">
197
+ <div className="flex items-center gap-3 p-3 bg-muted/50 rounded-xl border border-border/50">
198
+ {field.icon}
199
+ <input
200
+ type={field.type}
201
+ min={field.min}
202
+ max={field.max}
203
+ value={displayValue || ''}
204
+ onChange={(e) => setTempValues({ ...tempValues, [field.key]: e.target.value })}
205
+ placeholder={field.placeholder}
206
+ className="flex-1 text-sm bg-transparent border-0 outline-none text-foreground placeholder:text-muted-foreground/50"
207
+ autoFocus
208
+ />
209
+ </div>
210
+ <div className="flex gap-2">
211
+ <button
212
+ onClick={() => handleSave(field.key)}
213
+ disabled={loading[field.key]}
214
+ className="px-4 py-2 bg-primary text-primary-foreground rounded-xl text-sm font-medium hover:bg-primary/90 transition-all disabled:opacity-50 disabled:cursor-not-allowed"
215
+ >
216
+ Save
217
+ </button>
218
+ <button
219
+ onClick={() => handleCancel(field.key, value)}
220
+ className="px-4 py-2 bg-muted hover:bg-muted/80 text-foreground rounded-xl text-sm font-medium transition-all"
221
+ >
222
+ Cancel
223
+ </button>
224
+ </div>
225
+ </div>
226
+ ) : (
227
+ <div className="relative p-3 bg-muted/30 rounded-xl group hover:bg-muted/50 transition-all">
228
+ <div className="flex items-center gap-3">
229
+ {field.icon}
230
+ <p className="text-sm font-medium text-foreground flex-1">{displayValue || field.placeholder}</p>
231
+ </div>
232
+ <button
233
+ onClick={() => handleEdit(field.key, value)}
234
+ className="absolute right-3 top-1/2 -translate-y-1/2 p-1.5 text-muted-foreground/50 hover:text-primary transition-colors"
235
+ >
236
+ <Pencil className="size-4" />
237
+ </button>
238
+ </div>
239
+ )}
240
+ </div>
241
+ );
242
+ };
243
+
244
+ const visibleBuildFields = hasBuild ? buildFields : [];
245
+ const visibleStartFields = hasServer ? startFields : [];
246
+
247
+ if (mode === 'simple') {
248
+ return (
249
+ <div className="bg-card rounded-2xl border border-border/50">
250
+ <button
251
+ onClick={() => setExpanded(!expanded)}
252
+ className="w-full flex items-center justify-between px-5 py-4 text-left"
253
+ >
254
+ <div className="flex items-center gap-3">
255
+ <div className="w-9 h-9 rounded-xl bg-orange-500/10 flex items-center justify-center">
256
+ <Settings2 className="size-[18px] text-orange-500" />
257
+ </div>
258
+ <div>
259
+ <p className="text-[15px] font-semibold text-foreground">Deploy Configuration</p>
260
+ <p className="text-sm text-muted-foreground">
261
+ {config?.framework ? `${config.framework} defaults applied` : 'Configure build options'}
262
+ </p>
263
+ </div>
264
+ </div>
265
+ {expanded ? (
266
+ <ChevronUp className="size-4 text-muted-foreground" />
267
+ ) : (
268
+ <ChevronDown className="size-4 text-muted-foreground" />
269
+ )}
270
+ </button>
271
+
272
+ {expanded && (
273
+ <div className="px-5 pb-5 border-t border-border/50 pt-4">
274
+ <div className="grid md:grid-cols-2 gap-4">
275
+ {/* ── Build column ──────────────────────────────── */}
276
+ <div className="space-y-3">
277
+ <div className="flex items-center justify-between p-2.5 bg-muted/30 rounded-lg border border-border/50">
278
+ <div className="flex items-center gap-2">
279
+ <Hammer className="w-3.5 h-3.5 text-muted-foreground" />
280
+ <div>
281
+ <p className="text-sm font-medium text-foreground">Build</p>
282
+ <p className="text-[11px] text-muted-foreground leading-tight">
283
+ {hasBuild ? 'Install & build commands' : 'Deploy source directly'}
284
+ </p>
285
+ </div>
286
+ </div>
287
+ <Toggle checked={hasBuild} onChange={(v: boolean) => updateOptions?.({ hasBuild: v })} />
288
+ </div>
289
+ {visibleBuildFields.map(renderInput)}
290
+ {generalFields.map(renderInput)}
291
+
292
+ {/* ── Advanced (collapsible) ──────────────────── */}
293
+ {advancedFields.length > 0 && (
294
+ <div className="border border-border/30 rounded-lg overflow-hidden">
295
+ <button
296
+ onClick={() => setAdvancedOpen(!advancedOpen)}
297
+ className="w-full flex items-center justify-between px-3 py-2 text-left hover:bg-muted/30 transition-colors"
298
+ >
299
+ <div className="flex items-center gap-2">
300
+ <ShieldCheck className="w-3.5 h-3.5 text-muted-foreground" />
301
+ <span className="text-xs font-medium text-muted-foreground">Advanced</span>
302
+ </div>
303
+ {advancedOpen ? (
304
+ <ChevronUp className="size-3 text-muted-foreground" />
305
+ ) : (
306
+ <ChevronDown className="size-3 text-muted-foreground" />
307
+ )}
308
+ </button>
309
+ {advancedOpen && (
310
+ <div className="px-3 pb-3 space-y-3">
311
+ {advancedFields.map(renderInput)}
312
+ </div>
313
+ )}
314
+ </div>
315
+ )}
316
+ </div>
317
+
318
+ {/* ── Start column ──────────────────────────────── */}
319
+ <div className="space-y-3">
320
+ <div className="flex items-center justify-between p-2.5 bg-muted/30 rounded-lg border border-border/50">
321
+ <div className="flex items-center gap-2">
322
+ <Play className="w-3.5 h-3.5 text-muted-foreground" />
323
+ <div>
324
+ <p className="text-sm font-medium text-foreground">Start</p>
325
+ <p className="text-[11px] text-muted-foreground leading-tight">
326
+ {hasServer ? `Server on port ${buildData?.productionPort || '3000'}` : 'Static from edge'}
327
+ </p>
328
+ </div>
329
+ </div>
330
+ <Toggle checked={hasServer} onChange={(v: boolean) => updateOptions?.({ hasServer: v })} />
331
+ </div>
332
+ {visibleStartFields.map(renderInput)}
333
+ </div>
334
+ </div>
335
+ </div>
336
+ )}
337
+ </div>
338
+ );
339
+ }
340
+
341
+ // Advanced mode
342
+ const allVisibleFields = [...visibleBuildFields, ...visibleStartFields, ...generalFields];
343
+ return (
344
+ <div className="bg-card rounded-2xl border border-border/50 p-6">
345
+ <h2 className="text-lg font-semibold text-foreground mb-6">
346
+ Build Settings
347
+ </h2>
348
+ <div className="grid gap-5 mb-6">
349
+ <div className="grid md:grid-cols-2 gap-5">
350
+ {allVisibleFields.map(renderInput)}
351
+ </div>
352
+ </div>
353
+
354
+ {/* ── Advanced section ──────────────────────────── */}
355
+ {advancedFields.length > 0 && (
356
+ <div className="border-t border-border/50 pt-4">
357
+ <button
358
+ onClick={() => setAdvancedOpen(!advancedOpen)}
359
+ className="flex items-center gap-2 mb-4 text-sm text-muted-foreground hover:text-foreground transition-colors"
360
+ >
361
+ <ShieldCheck className="size-4" />
362
+ <span className="font-medium">Advanced</span>
363
+ {advancedOpen ? <ChevronUp className="size-3.5" /> : <ChevronDown className="size-3.5" />}
364
+ </button>
365
+ {advancedOpen && (
366
+ <div className="grid md:grid-cols-2 gap-5">
367
+ {advancedFields.map(renderInput)}
368
+ </div>
369
+ )}
370
+ </div>
371
+ )}
372
+ </div>
373
+ );
374
+ };
375
+
376
+ export default React.memo(BuildSettings);
@@ -0,0 +1,161 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+
5
+ /**
6
+ * BuildSkeleton - Loading state for build page
7
+ * Matches the layout of DeploymentProcessing
8
+ */
9
+ const BuildSkeleton: React.FC = () => {
10
+ return (
11
+ <div className="min-h-screen mx-auto md:px-12 bg-background">
12
+ {/* Header Skeleton */}
13
+ <div className="bg-background">
14
+ <div className="py-5 relative">
15
+ <div className="flex items-center justify-between">
16
+ <div className="flex items-center gap-4">
17
+ <div>
18
+ {/* Title skeleton */}
19
+ <div className="h-7 w-48 bg-gradient-to-r from-muted via-muted/50 to-muted rounded-lg mb-2 animate-pulse" />
20
+ {/* Subtitle skeleton */}
21
+ <div className="h-4 w-32 bg-gradient-to-r from-muted via-muted/50 to-muted rounded-lg animate-pulse" />
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ </div>
27
+
28
+ <div className="w-full">
29
+ <div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
30
+ {/* Main Content - Left Side (2/3) */}
31
+ <div className="lg:col-span-2 space-y-6">
32
+ {/* Progress Steps Skeleton */}
33
+ <div className="bg-card rounded-2xl border border-border/50 p-8">
34
+ {/* Title */}
35
+ <div className="h-5 w-40 bg-gradient-to-r from-muted via-muted/50 to-muted rounded-lg mb-6 animate-pulse" />
36
+
37
+ {/* Steps */}
38
+ <div className="relative">
39
+ {/* Progress Line */}
40
+ <div className="absolute top-6 left-0 right-0 z-0 h-0.5 bg-border/50">
41
+ <div className="h-full w-1/4 bg-gradient-to-r from-muted-foreground/30 via-muted-foreground/20 to-muted/50 animate-pulse" />
42
+ </div>
43
+
44
+ {/* Step Items */}
45
+ <div className="relative flex justify-between z-10">
46
+ {[0, 1, 2, 3, 4].map((index) => (
47
+ <div key={index} className="flex flex-col items-center bg-card z-10 px-2">
48
+ {/* Circle skeleton */}
49
+ <div
50
+ className={`w-12 h-12 rounded-full flex items-center justify-center transition-all duration-300 animate-pulse ${
51
+ index === 0 ? 'bg-muted' : 'bg-card border-2 border-border'
52
+ }`}
53
+ />
54
+ {/* Label skeleton */}
55
+ <div className="h-3 w-16 bg-gradient-to-r from-muted via-muted/50 to-muted rounded mt-3 animate-pulse" />
56
+ </div>
57
+ ))}
58
+ </div>
59
+ </div>
60
+ </div>
61
+
62
+ {/* Terminal Skeleton */}
63
+ <div className="bg-card rounded-2xl border border-border/50 overflow-hidden">
64
+ {/* Terminal Header */}
65
+ <div className="flex items-center justify-between px-6 py-3 border-b border-border/50 bg-muted/50">
66
+ <div className="flex items-center gap-3">
67
+ <div className="flex gap-2">
68
+ <div className="w-3 h-3 rounded-full bg-destructive/40 animate-pulse"></div>
69
+ <div className="w-3 h-3 rounded-full bg-yellow-400/50 animate-pulse"></div>
70
+ <div className="w-3 h-3 rounded-full bg-green-400/50 animate-pulse"></div>
71
+ </div>
72
+ <div className="h-4 w-24 bg-gradient-to-r from-muted via-muted/50 to-muted rounded animate-pulse" />
73
+ </div>
74
+ <div className="h-4 w-16 bg-gradient-to-r from-muted via-muted/50 to-muted rounded animate-pulse" />
75
+ </div>
76
+
77
+ {/* Terminal Body */}
78
+ <div className="bg-card p-6 min-h-[400px] space-y-3">
79
+ {/* Log line skeletons */}
80
+ {[...Array(8)].map((_, i) => {
81
+ const widths = [98, 97, 92, 93, 73, 71, 62, 85];
82
+ return (
83
+ <div
84
+ key={i}
85
+ className="h-4 bg-gradient-to-r from-muted via-muted/50 to-muted rounded animate-pulse"
86
+ style={{
87
+ width: `${widths[i] || 80}%`,
88
+ animationDelay: `${i * 0.1}s`,
89
+ }}
90
+ />
91
+ );
92
+ })}
93
+ </div>
94
+ </div>
95
+ </div>
96
+
97
+ {/* Sidebar - Right Side (1/3) */}
98
+ <div className="space-y-6">
99
+ {/* Project Info Skeleton */}
100
+ <div className="bg-card rounded-2xl border border-border/50 p-6">
101
+ {/* Title */}
102
+ <div className="h-5 w-32 bg-gradient-to-r from-muted via-muted/50 to-muted rounded-lg mb-4 animate-pulse" />
103
+
104
+ {/* Info rows */}
105
+ <div className="space-y-4">
106
+ {[...Array(4)].map((_, i) => (
107
+ <div key={i} className="flex items-center justify-between">
108
+ <div className="h-4 w-24 bg-gradient-to-r from-muted via-muted/50 to-muted rounded animate-pulse" />
109
+ <div className="h-4 w-32 bg-gradient-to-r from-muted via-muted/50 to-muted rounded animate-pulse" />
110
+ </div>
111
+ ))}
112
+ </div>
113
+ </div>
114
+
115
+ {/* Domain Skeleton */}
116
+ <div className="bg-card rounded-2xl border border-border/50 p-6">
117
+ {/* Title */}
118
+ <div className="h-5 w-28 bg-gradient-to-r from-muted via-muted/50 to-muted rounded-lg mb-4 animate-pulse" />
119
+
120
+ {/* Domain box */}
121
+ <div className="h-12 w-full bg-gradient-to-r from-muted via-muted/50 to-muted rounded-xl animate-pulse" />
122
+
123
+ {/* Copy button */}
124
+ <div className="h-10 w-full bg-gradient-to-r from-muted via-muted/50 to-muted rounded-full mt-3 animate-pulse" />
125
+ </div>
126
+
127
+ {/* Build Time Skeleton */}
128
+ <div className="bg-card rounded-2xl border border-border/50 p-6">
129
+ <div className="h-5 w-24 bg-gradient-to-r from-muted via-muted/50 to-muted rounded-lg mb-4 animate-pulse" />
130
+ <div className="h-8 w-20 bg-gradient-to-r from-muted via-muted/50 to-muted rounded-lg animate-pulse" />
131
+ </div>
132
+
133
+ {/* Actions Skeleton */}
134
+ <div className="bg-card rounded-2xl border border-border/50 p-6">
135
+ <div className="h-5 w-20 bg-gradient-to-r from-muted via-muted/50 to-muted rounded-lg mb-4 animate-pulse" />
136
+ <div className="space-y-3">
137
+ <div className="h-10 w-full bg-gradient-to-r from-muted via-muted/50 to-muted rounded-xl animate-pulse" />
138
+ <div className="h-10 w-full bg-gradient-to-r from-muted via-muted/50 to-muted rounded-xl animate-pulse" />
139
+ </div>
140
+ </div>
141
+ </div>
142
+ </div>
143
+ </div>
144
+
145
+ {/* Loading Indicator Overlay */}
146
+ <div className="fixed bottom-8 right-8 bg-card rounded-2xl border border-border/50 px-6 py-4 shadow-2xl">
147
+ <div className="flex items-center gap-3">
148
+ <div className="relative">
149
+ <div className="w-5 h-5 border-3 border-foreground/10 border-t-foreground rounded-full animate-spin"></div>
150
+ </div>
151
+ <div>
152
+ <span className="text-sm text-muted-foreground">Loading build session...</span>
153
+ </div>
154
+ </div>
155
+ </div>
156
+ </div>
157
+ );
158
+ };
159
+
160
+ export default BuildSkeleton;
161
+