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,159 @@
1
+ "use client";
2
+ import React, { useState } from "react";
3
+ import { generateIcon } from "@/utils/icons";
4
+ import { useProjectSettings } from "@/context/ProjectSettingsContext";
5
+ import { projectsApi } from "@/lib/api";
6
+ import { useToast } from "@/context/ToastContext";
7
+
8
+ export const ProjectIdentity: React.FC = () => {
9
+ const { projectData, updateProjectData } = useProjectSettings();
10
+ const [isEditingName, setIsEditingName] = useState(false);
11
+ const [isEditingDescription, setIsEditingDescription] = useState(false);
12
+
13
+ const [tempData, setTempData] = useState({
14
+ name: projectData.name || '',
15
+ description: projectData.description || '',
16
+ framework: projectData.framework || ''
17
+ });
18
+
19
+ const [loading, setLoading] = useState({
20
+ name: false,
21
+ description: false,
22
+ });
23
+
24
+ const { showToast } = useToast();
25
+
26
+ const handleSaveName = async () => {
27
+ setLoading({ ...loading, name: true });
28
+ const response = await projectsApi.update(projectData.id, 'name', tempData.name);
29
+ if (response.success) {
30
+ updateProjectData({ name: tempData.name });
31
+ setIsEditingName(false);
32
+ } else {
33
+ showToast(response.message, 'error', 'Failed to update project name');
34
+ }
35
+ setLoading({ ...loading, name: false });
36
+ };
37
+
38
+ const handleSaveDescription = async () => {
39
+ const response = await projectsApi.update(projectData.id, 'description', tempData.description);
40
+ if (response.success) {
41
+ updateProjectData({ description: tempData.description });
42
+ setIsEditingDescription(false);
43
+ } else {
44
+ showToast(response.message, 'error', 'Failed to update project description');
45
+ }
46
+ setLoading({ ...loading, description: false });
47
+ };
48
+
49
+ const handleCancelName = () => {
50
+ setTempData((prev) => ({ ...prev, name: projectData.name || '' }));
51
+ setIsEditingName(false);
52
+ setLoading({ ...loading, name: false });
53
+ };
54
+
55
+ const handleCancelDescription = () => {
56
+ setTempData((prev) => ({ ...prev, description: projectData.description || '' }));
57
+ setIsEditingDescription(false);
58
+ setLoading({ ...loading, description: false });
59
+ };
60
+
61
+
62
+ return (
63
+ <div className="bg-white rounded-[20px] border border-black/5 p-6">
64
+ {/* Header */}
65
+ <div className="flex items-center gap-3 mb-6">
66
+ {generateIcon('layers-363-1658238246.png', 28, 'rgb(79, 70, 229)')}
67
+ <h3 className="text-lg font-semibold text-black">Project Identity</h3>
68
+ </div>
69
+
70
+ <div className="flex flex-col lg:flex-row gap-5 lg:gap-6">
71
+ {/* Project Name */}
72
+ <div className="flex-1">
73
+ <label className="text-sm font-medium text-black/70 mb-2 block">Project Name</label>
74
+
75
+ {isEditingName ? (
76
+ <div className="space-y-3">
77
+ <input
78
+ type="text"
79
+ value={tempData.name}
80
+ onChange={(e) => setTempData((prev) => ({ ...prev, name: e.target.value }))}
81
+ placeholder="my-awesome-project"
82
+ className="w-full px-4 py-2.5 bg-black/5 border border-transparent rounded-xl focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500/20 focus:bg-white outline-none text-sm transition-all"
83
+ autoFocus
84
+ />
85
+ <div className="flex gap-2">
86
+ <button
87
+ onClick={handleSaveName}
88
+ className="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 text-white rounded-full transition-all text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed"
89
+ >
90
+ Save
91
+ </button>
92
+ <button
93
+ onClick={handleCancelName}
94
+ className="px-4 py-2 bg-black/5 hover:bg-black/10 text-black rounded-full transition-all text-sm font-medium"
95
+ >
96
+ Cancel
97
+ </button>
98
+ </div>
99
+ </div>
100
+ ) : (
101
+ <div className="relative p-4 bg-black/5 rounded-xl group hover:bg-black/10 transition-all">
102
+ <p className="text-sm font-medium text-black pr-8">{projectData.name || 'Unnamed Project'}</p>
103
+ <button
104
+ onClick={() => setIsEditingName(true)}
105
+ className="absolute right-3 top-1/2 -translate-y-1/2 p-1.5 text-black/40 hover:text-indigo-600 transition-colors"
106
+ >
107
+ {generateIcon("pen-411-1658238246.png", 18, "currentColor")}
108
+ </button>
109
+ </div>
110
+ )}
111
+ </div>
112
+
113
+ {/* Description */}
114
+ <div className="flex-1">
115
+ <label className="text-sm font-medium text-black/70 mb-2 block">Description</label>
116
+
117
+ {isEditingDescription ? (
118
+ <div className="space-y-3">
119
+ <textarea
120
+ value={tempData.description}
121
+ onChange={(e) => setTempData((prev) => ({ ...prev, description: e.target.value }))}
122
+ rows={3}
123
+ placeholder="A modern web application built with..."
124
+ className="w-full px-4 py-2.5 bg-black/5 border border-transparent rounded-xl focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500/20 focus:bg-white outline-none resize-none text-sm transition-all"
125
+ autoFocus
126
+ />
127
+ <div className="flex gap-2">
128
+ <button
129
+ onClick={handleSaveDescription}
130
+ className="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 text-white rounded-full transition-all text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed"
131
+ >
132
+ Save
133
+ </button>
134
+ <button
135
+ onClick={handleCancelDescription}
136
+ className="px-4 py-2 bg-black/5 hover:bg-black/10 text-black rounded-full transition-all text-sm font-medium"
137
+ >
138
+ Cancel
139
+ </button>
140
+ </div>
141
+ </div>
142
+ ) : (
143
+ <div className="relative p-4 bg-black/5 rounded-xl group hover:bg-black/10 transition-all">
144
+ <p className="text-sm text-black/70 pr-8">
145
+ {projectData.description || 'No description provided'}
146
+ </p>
147
+ <button
148
+ onClick={() => setIsEditingDescription(true)}
149
+ className="absolute right-3 top-3 p-1.5 text-black/40 hover:text-indigo-600 transition-colors"
150
+ >
151
+ {generateIcon("pen-411-1658238246.png", 18, "currentColor")}
152
+ </button>
153
+ </div>
154
+ )}
155
+ </div>
156
+ </div>
157
+ </div>
158
+ );
159
+ };
@@ -0,0 +1,58 @@
1
+
2
+ import React from "react";
3
+ import { Activity, GitBranch, Calendar, Hash, Sparkles, Info } from "lucide-react";
4
+ import { generateIcon } from "@/utils/icons";
5
+ import { useProjectSettings } from "@/context/ProjectSettingsContext";
6
+ import { formatDate } from "@/utils/date";
7
+ import { useToast } from "@/context/ToastContext";
8
+
9
+ export const ProjectInfo: React.FC = () => {
10
+ const { projectData } = useProjectSettings();
11
+ const { showToast } = useToast();
12
+ const handleEditWithBlurs = () => {
13
+ showToast('Editing with Blurs is not available yet', 'success', 'Coming Soon');
14
+ };
15
+
16
+ return (
17
+ <>
18
+ {/* Project Metadata - Compact */}
19
+ <div className="bg-white rounded-[20px] border border-black/5 p-5">
20
+ <div className="flex items-center gap-2 mb-4">
21
+ {generateIcon('qr%20scan-120-1658435460.png', 24, 'rgb(79, 70, 229)')}
22
+ <h3 className="text-base font-semibold text-black">Project Info</h3>
23
+ </div>
24
+ <div className="space-y-3">
25
+ <div className="flex items-center justify-between">
26
+ <p className="text-xs text-black/50">Project ID</p>
27
+ <p className="text-xs text-black font-medium font-mono">{projectData.id?.substring(0, 8)}</p>
28
+ </div>
29
+ <div className="flex items-center justify-between">
30
+ <p className="text-xs text-black/50">Branch</p>
31
+ <p className="text-xs text-black font-medium">{projectData.branch || 'main'}</p>
32
+ </div>
33
+ <div className="flex items-center justify-between">
34
+ <p className="text-xs text-black/50">Last Deploy</p>
35
+ <p className="text-xs text-black font-medium">{formatDate(projectData.last_deployed)}</p>
36
+ </div>
37
+ <div className="flex items-center justify-between">
38
+ <p className="text-xs text-black/50">Framework</p>
39
+ <p className="text-xs text-black font-medium">{projectData.framework || 'Unknown'}</p>
40
+ </div>
41
+ </div>
42
+ </div>
43
+
44
+ {/* AI Assistant - Simplified */}
45
+ <div className="bg-white rounded-[20px] border border-black/5 p-5">
46
+ <div className="flex items-center gap-2 mb-4">
47
+ {generateIcon('star-103-1687505465.png', 24, 'rgb(79, 70, 229)')}
48
+ <h3 className="text-base font-semibold text-black">AI Assistant</h3>
49
+ </div>
50
+ <p className="text-xs text-black/40 mb-4">Powered by Blurs</p>
51
+ <button onClick={handleEditWithBlurs} className="w-full px-4 py-2.5 bg-black text-white rounded-full font-medium text-sm hover:bg-gray-900 transition-all hover:shadow-md flex items-center justify-center gap-2">
52
+ <Sparkles className="w-4 h-4" />
53
+ Edit with Blurs
54
+ </button>
55
+ </div>
56
+ </>
57
+ );
58
+ };
@@ -0,0 +1,170 @@
1
+ import React from "react";
2
+
3
+ // Fixed heights for skeleton bars to avoid hydration mismatches
4
+ const SKELETON_BAR_HEIGHTS = [
5
+ 45, 62, 38, 71, 55, 42, 68, 49, 75, 33,
6
+ 58, 44, 66, 52, 39, 73, 47, 61, 35, 69,
7
+ 51, 43, 64, 56
8
+ ];
9
+
10
+ export const TrafficChartSkeleton = () => {
11
+ return (
12
+ <div className="bg-white rounded-2xl border border-gray-200 p-6 h-[320px] flex flex-col animate-pulse">
13
+ <div className="flex items-center justify-between mb-6">
14
+ <div className="flex items-center gap-3">
15
+ <div className="w-12 h-12 rounded-2xl bg-gray-200/50"></div>
16
+ <div>
17
+ <div className="h-6 w-40 bg-gray-200/50 rounded-2xl mb-2"></div>
18
+ <div className="h-4 w-32 bg-gray-200/30 rounded-2xl"></div>
19
+ </div>
20
+ </div>
21
+ <div className="flex items-center gap-4">
22
+ <div className="h-10 w-40 bg-gray-200/50 rounded-2xl"></div>
23
+ <div className="h-5 w-20 bg-gray-200/30 rounded-2xl"></div>
24
+ </div>
25
+ </div>
26
+ <div className="flex-1 flex items-end gap-1.5">
27
+ {SKELETON_BAR_HEIGHTS.map((height, i) => (
28
+ <div
29
+ key={i}
30
+ className="flex-1 bg-gray-200/50 rounded-t-2xl"
31
+ style={{ height: `${height}%` }}
32
+ ></div>
33
+ ))}
34
+ </div>
35
+ <div className="flex justify-between mt-3">
36
+ {Array.from({ length: 6 }).map((_, i) => (
37
+ <div key={i} className="h-3 w-10 bg-gray-200/30 rounded-2xl"></div>
38
+ ))}
39
+ </div>
40
+ </div>
41
+ );
42
+ };
43
+
44
+ export const TopPathsSkeleton = () => {
45
+ return (
46
+ <div className="bg-white rounded-2xl border border-gray-200 p-6 h-[320px] flex flex-col animate-pulse">
47
+ <div className="flex items-center justify-between mb-5">
48
+ <div className="flex items-center gap-3">
49
+ <div className="w-12 h-12 rounded-2xl bg-gray-200/50"></div>
50
+ <div className="h-6 w-32 bg-gray-200/50 rounded-2xl"></div>
51
+ </div>
52
+ <div className="h-5 w-20 bg-gray-200/30 rounded-2xl"></div>
53
+ </div>
54
+ <div className="space-y-5 flex-1">
55
+ {Array.from({ length: 3 }).map((_, i) => (
56
+ <div key={i} className="space-y-2">
57
+ <div className="flex items-center justify-between mb-2">
58
+ <div className="h-4 w-32 bg-gray-200/50 rounded-2xl"></div>
59
+ <div className="h-4 w-16 bg-gray-200/30 rounded-2xl"></div>
60
+ </div>
61
+ <div className="w-full h-2.5 bg-gray-200/50 rounded-2xl"></div>
62
+ <div className="h-3 w-20 bg-gray-200/30 rounded-2xl"></div>
63
+ </div>
64
+ ))}
65
+ </div>
66
+ </div>
67
+ );
68
+ };
69
+
70
+ export const StatsCardsSkeleton = () => {
71
+ return (
72
+ <div className="grid grid-cols-4 gap-4 h-[100px]">
73
+ {Array.from({ length: 4 }).map((_, i) => (
74
+ <div
75
+ key={i}
76
+ className="bg-white border border-gray-200 rounded-2xl p-4 h-full flex items-center animate-pulse"
77
+ >
78
+ <div className="flex items-center gap-3 w-full">
79
+ <div className="w-12 h-12 rounded-2xl bg-gray-200/50 flex-shrink-0"></div>
80
+ <div className="flex-1 min-w-0">
81
+ <div className="h-6 w-20 bg-gray-200/50 rounded-2xl mb-2"></div>
82
+ <div className="h-4 w-24 bg-gray-200/30 rounded-2xl mb-1"></div>
83
+ <div className="h-3 w-20 bg-gray-200/30 rounded-2xl"></div>
84
+ </div>
85
+ </div>
86
+ </div>
87
+ ))}
88
+ </div>
89
+ );
90
+ };
91
+
92
+ export const ProductionUrlSkeleton = () => {
93
+ return (
94
+ <div className="bg-gradient-to-br from-gray-50 to-gray-100 rounded-2xl border border-gray-200 p-6 h-[100px] flex items-center animate-pulse">
95
+ <div className="flex items-center gap-4 flex-1">
96
+ <div className="w-12 h-12 bg-gray-200/50 rounded-2xl flex-shrink-0"></div>
97
+ <div className="flex-1 min-w-0">
98
+ <div className="h-4 w-32 bg-gray-200/30 rounded-2xl mb-2"></div>
99
+ <div className="h-5 w-40 bg-gray-200/50 rounded-2xl"></div>
100
+ </div>
101
+ </div>
102
+ </div>
103
+ );
104
+ };
105
+
106
+ export const ProjectIdentitySkeleton = () => {
107
+ return (
108
+ <div className="bg-white rounded-2xl border border-gray-200 overflow-hidden animate-pulse">
109
+ <div className="bg-gray-50 px-6 py-5 border-b border-gray-200 flex items-center gap-3">
110
+ <div className="w-12 h-12 rounded-2xl bg-gray-200/50"></div>
111
+ <div>
112
+ <div className="h-6 w-40 bg-gray-200/50 rounded-2xl mb-2"></div>
113
+ <div className="h-4 w-48 bg-gray-200/30 rounded-2xl"></div>
114
+ </div>
115
+ </div>
116
+
117
+ <div className="p-6 space-y-5">
118
+ {Array.from({ length: 3 }).map((_, i) => (
119
+ <div key={i}>
120
+ <div className="flex items-center justify-between mb-3">
121
+ <div className="h-5 w-32 bg-gray-200/50 rounded-2xl"></div>
122
+ <div className="h-4 w-16 bg-gray-200/30 rounded-2xl"></div>
123
+ </div>
124
+ <div className="p-4 bg-gray-50 rounded-2xl">
125
+ <div className="h-5 w-full bg-gray-200/50 rounded-2xl"></div>
126
+ </div>
127
+ </div>
128
+ ))}
129
+ </div>
130
+ </div>
131
+ );
132
+ };
133
+
134
+ export const ProjectInfoSkeleton = () => {
135
+ return (
136
+ <>
137
+ <div className="bg-white rounded-2xl border border-gray-200 p-6 animate-pulse">
138
+ <div className="flex items-center gap-3 mb-5">
139
+ <div className="w-12 h-12 rounded-2xl bg-gray-200/50"></div>
140
+ <div className="h-6 w-36 bg-gray-200/50 rounded-2xl"></div>
141
+ </div>
142
+ <div className="space-y-4">
143
+ {Array.from({ length: 4 }).map((_, i) => (
144
+ <div key={i} className="flex items-center gap-4">
145
+ <div className="w-5 h-5 rounded-xl bg-gray-200/50"></div>
146
+ <div className="flex-1">
147
+ <div className="h-4 w-20 bg-gray-200/50 rounded-2xl mb-2"></div>
148
+ <div className="h-4 w-32 bg-gray-200/30 rounded-2xl"></div>
149
+ </div>
150
+ </div>
151
+ ))}
152
+ </div>
153
+ </div>
154
+
155
+ <div className="bg-gradient-to-br from-gray-50 to-gray-100 rounded-2xl border border-gray-200 p-6 animate-pulse">
156
+ <div className="flex items-start justify-between mb-4">
157
+ <div className="flex items-center gap-3">
158
+ <div className="w-12 h-12 bg-gray-200/50 rounded-2xl"></div>
159
+ <div>
160
+ <div className="h-5 w-32 bg-gray-200/50 rounded-2xl mb-2"></div>
161
+ <div className="h-4 w-36 bg-gray-200/30 rounded-2xl"></div>
162
+ </div>
163
+ </div>
164
+ </div>
165
+ <div className="w-full h-12 bg-gray-200/50 rounded-2xl"></div>
166
+ <div className="h-4 w-40 bg-gray-200/30 rounded-2xl mt-4 mx-auto"></div>
167
+ </div>
168
+ </>
169
+ );
170
+ };
@@ -0,0 +1,33 @@
1
+ import React from "react";
2
+ import { generateIcon } from "@/utils/icons";
3
+
4
+ interface Props {
5
+ stats: any[];
6
+ }
7
+
8
+ export const StatsCards: React.FC<Props> = ({ stats }) => {
9
+ return (
10
+ <div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
11
+ {stats.map((stat) => {
12
+ return (
13
+ <div key={stat.label} className="bg-white border border-black/5 rounded-[20px] hover:shadow-md transition-all p-4">
14
+ <div className="flex flex-col">
15
+ <div className="flex items-center gap-2 mb-3">
16
+ {generateIcon(stat.icon, 24, 'rgb(79, 70, 229)')}
17
+ <p className="text-xs font-medium text-black/50">{stat.label}</p>
18
+ </div>
19
+ <p className="text-2xl font-semibold text-black mb-1">
20
+ {stat.value}
21
+ </p>
22
+ {stat.subtext && (
23
+ <p className="text-xs text-black/40 font-normal">
24
+ {stat.subtext}
25
+ </p>
26
+ )}
27
+ </div>
28
+ </div>
29
+ );
30
+ })}
31
+ </div>
32
+ );
33
+ };
@@ -0,0 +1,56 @@
1
+ "use client";
2
+ import React, { useState } from "react";
3
+ import { generateIcon } from "@/utils/icons";
4
+
5
+ interface PathData {
6
+ path: string;
7
+ count: number;
8
+ percentage: string;
9
+ }
10
+
11
+ interface Props {
12
+ paths: PathData[];
13
+ }
14
+
15
+ export const TopPaths: React.FC<Props> = ({ paths }) => {
16
+ const [showAll, setShowAll] = useState(false);
17
+
18
+ const displayedPaths = showAll ? paths : paths.slice(0, 5);
19
+ const hasMorePaths = paths.length > 5;
20
+
21
+ return (
22
+ <div className="bg-white rounded-[20px] border border-black/5 p-5">
23
+ <div className="flex items-center justify-between mb-5">
24
+ <div className="flex items-center gap-2">
25
+ {generateIcon('trend%20up-79-1681196106.png', 24, 'rgb(79, 70, 229)')}
26
+ <h3 className="text-base font-semibold text-black">Top Paths</h3>
27
+ </div>
28
+ {hasMorePaths && (
29
+ <button
30
+ onClick={() => setShowAll(!showAll)}
31
+ className="text-xs font-medium text-indigo-600 hover:text-indigo-700 transition-colors"
32
+ >
33
+ {showAll ? 'Show Less' : `+${paths.length - 5}`}
34
+ </button>
35
+ )}
36
+ </div>
37
+ <div className="space-y-4">
38
+ {displayedPaths.map((path, idx) => (
39
+ <div key={idx}>
40
+ <div className="flex items-center justify-between mb-2">
41
+ <span className="text-xs text-black/70 font-medium truncate pr-2">{path.path}</span>
42
+ <span className="text-xs font-medium text-indigo-600">{path.percentage}%</span>
43
+ </div>
44
+ <div className="w-full bg-black/5 rounded-full h-2 overflow-hidden">
45
+ <div
46
+ className="h-full bg-indigo-600 rounded-full transition-all"
47
+ style={{ width: `${path.percentage}%` }}
48
+ ></div>
49
+ </div>
50
+ <p className="text-xs text-black/40 mt-1">{path.count} requests</p>
51
+ </div>
52
+ ))}
53
+ </div>
54
+ </div>
55
+ );
56
+ };
@@ -0,0 +1,157 @@
1
+ "use client";
2
+ import React, { useState } from "react";
3
+ import { BarChart3, TrendingUp } from "lucide-react";
4
+ import { generateIcon } from "@/utils/icons";
5
+ import { SlidingToggle } from "@/components/ui/SlidingToggle";
6
+
7
+ interface TrafficData {
8
+ hour: number;
9
+ requests: number;
10
+ }
11
+
12
+ interface Props {
13
+ trafficData: TrafficData[];
14
+ isLoading: boolean;
15
+ dateRange?: string;
16
+ totalRequests?: number;
17
+ }
18
+
19
+ export const TrafficChart: React.FC<Props> = ({
20
+ trafficData,
21
+ isLoading,
22
+ dateRange,
23
+ totalRequests,
24
+ }) => {
25
+ const [chartType, setChartType] = useState<'bar' | 'area'>('area');
26
+ const maxRequests = Math.max(...trafficData.map(d => d.requests), 1);
27
+ if(trafficData.length === 0) {
28
+ trafficData = Array.from({ length: 24 }, (_, i) => ({
29
+ hour: i,
30
+ requests: 0,
31
+ }));
32
+ }
33
+
34
+ return (
35
+ <div className="bg-white rounded-[20px] border border-black/5 p-4 sm:p-6 h-[280px] sm:h-[320px] flex flex-col">
36
+ <div className="flex items-center justify-between gap-2 sm:gap-0 mb-4 sm:mb-5">
37
+ <div className="flex items-center gap-2 sm:gap-3 flex-1 min-w-0">
38
+ {generateIcon('chart%204%20line-5-1666004410.png', 24, 'rgb(79, 70, 229)')}
39
+ <div className="min-w-0">
40
+ <h3 className="text-sm sm:text-lg font-semibold text-black truncate">Traffic Overview</h3>
41
+ <p className="text-[10px] sm:text-sm text-black/40 truncate">{dateRange || 'Last 24 hours'}</p>
42
+ </div>
43
+ </div>
44
+ <div className="flex items-center gap-3 flex-shrink-0">
45
+ {/* Chart Type Selector */}
46
+ <SlidingToggle
47
+ options={[
48
+ {
49
+ value: 'bar',
50
+ icon: <BarChart3 className="w-3.5 h-3.5 sm:w-4 sm:h-4" />,
51
+ label: 'Bar',
52
+ },
53
+ {
54
+ value: 'area',
55
+ icon: <TrendingUp className="w-3.5 h-3.5 sm:w-4 sm:h-4" />,
56
+ label: 'Area',
57
+ },
58
+ ]}
59
+ value={chartType}
60
+ onChange={(value) => setChartType(value as 'bar' | 'area')}
61
+ variant="rounded"
62
+ selectedBg="bg-indigo-600"
63
+ selectedTextColor="text-white"
64
+ unselectedTextColor="text-black/60"
65
+ backgroundColor="bg-white"
66
+ size="sm"
67
+ />
68
+
69
+ </div>
70
+ </div>
71
+
72
+ {/* Traffic Chart */}
73
+ {isLoading ? (
74
+ <div className="flex items-center justify-center flex-1">
75
+ <div className="text-sm text-gray-400">Loading analytics...</div>
76
+ </div>
77
+ ) : (
78
+ <div className="flex-1 flex flex-col">
79
+ <div className="relative flex-1">
80
+ <svg className="absolute inset-0 w-full h-full" viewBox="0 0 1000 160" preserveAspectRatio="none">
81
+ <defs>
82
+ <linearGradient id="trafficGradient" x1="0%" y1="0%" x2="0%" y2="100%">
83
+ <stop offset={`${chartType == 'bar' ? 100 : 20}%`} stopColor="rgb(99, 102, 241)" stopOpacity="0.3" />
84
+ <stop offset="100%" stopColor="rgb(99, 102, 241)" stopOpacity="0.1" />
85
+ </linearGradient>
86
+ </defs>
87
+
88
+ {chartType === 'bar' && (
89
+ /* Bar Chart */
90
+ <>
91
+ {trafficData.map((d, i) => {
92
+ const containerWidth = 1000;
93
+ const containerHeight = 160;
94
+ const barWidth = containerWidth / trafficData.length * 0.8;
95
+ const x = (i / trafficData.length) * containerWidth + barWidth * 0.1;
96
+ const height = (d.requests / maxRequests) * 140;
97
+ const y = containerHeight - height;
98
+
99
+ return (
100
+ <rect
101
+ key={i}
102
+ x={x}
103
+ y={y}
104
+ width={barWidth}
105
+ height={height}
106
+ fill="url(#trafficGradient)"
107
+ rx="4"
108
+ ry="4"
109
+ />
110
+ );
111
+ })}
112
+ </>
113
+ )}
114
+
115
+ {chartType === 'area' && (
116
+ /* Area Chart with Border Line */
117
+ <>
118
+ {/* Area Fill */}
119
+ <path
120
+ d={`M 0 150 ${trafficData.map((d, i) => {
121
+ const x = (i / (trafficData.length - 1)) * 1000;
122
+ const baseHeight = 110; // Raised baseline for zero state
123
+ const maxHeight = 110; // Maximum height for visualization
124
+ const y = baseHeight - (d.requests / maxRequests) * maxHeight;
125
+ return `L ${x} ${y}`;
126
+ }).join(' ')} L 1000 150 Z`}
127
+ fill="url(#trafficGradient)"
128
+ />
129
+ {/* Top Border Line - More Visible */}
130
+ <path
131
+ d={`M ${trafficData.map((d, i) => {
132
+ const x = (i / (trafficData.length - 1)) * 1000;
133
+ const baseHeight = 0;
134
+ const maxHeight = 130;
135
+ const y = baseHeight - (d.requests / maxRequests) * maxHeight;
136
+ return `${i === 0 ? 'M' : 'L'} ${x} ${y}`;
137
+ }).join(' ')}`}
138
+ fill="none"
139
+ stroke="rgb(99, 102, 241)"
140
+ strokeWidth="0.5"
141
+ />
142
+ </>
143
+ )}
144
+ </svg>
145
+ </div>
146
+
147
+ {/* Hour Labels */}
148
+ <div className="flex items-center justify-between mt-2 text-[9px] sm:text-[10px] text-gray-500">
149
+ {trafficData.filter((_, i) => i % 4 === 0).map((d, i) => (
150
+ <span key={i}>{d.hour}:00</span>
151
+ ))}
152
+ </div>
153
+ </div>
154
+ )}
155
+ </div>
156
+ );
157
+ };
@@ -0,0 +1,14 @@
1
+ export { TrafficChart } from './TrafficChart';
2
+ export { TopPaths } from './TopPaths';
3
+ export { StatsCards } from './StatsCards';
4
+ export { ProductionUrl } from './ProductionUrl';
5
+ export { ProjectIdentity } from './ProjectIdentity';
6
+ export { ProjectInfo } from './ProjectInfo';
7
+ export {
8
+ TrafficChartSkeleton,
9
+ TopPathsSkeleton,
10
+ StatsCardsSkeleton,
11
+ ProductionUrlSkeleton,
12
+ ProjectIdentitySkeleton,
13
+ ProjectInfoSkeleton,
14
+ } from './SkeletonLoader';