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.
- package/.env.example +19 -3
- package/CONTRIBUTING.md +69 -19
- package/LICENSE +661 -0
- package/README.md +304 -108
- package/apps/api/Dockerfile +6 -8
- package/apps/api/package.json +25 -21
- package/apps/api/src/app.ts +46 -3
- package/apps/api/src/config/env.ts +81 -7
- package/apps/api/src/lib/auth-mode.ts +42 -0
- package/apps/api/src/lib/auth.ts +105 -0
- package/apps/api/src/lib/cache.ts +128 -0
- package/apps/api/src/lib/cloud-auth-proxy.ts +310 -0
- package/apps/api/src/lib/cloud-client.ts +103 -0
- package/apps/api/src/lib/compose-parser.ts +138 -0
- package/apps/api/src/lib/controller-helpers.ts +90 -0
- package/apps/api/src/lib/email-templates.ts +94 -0
- package/apps/api/src/lib/encryption.ts +102 -0
- package/apps/api/src/lib/local-user.ts +65 -0
- package/apps/api/src/lib/mail.ts +48 -0
- package/apps/api/src/lib/notifications.ts +195 -0
- package/apps/api/src/lib/openship-cloud.ts +101 -0
- package/apps/api/src/lib/resources.ts +96 -0
- package/apps/api/src/lib/screenshots.ts +189 -0
- package/apps/api/src/lib/ssh-manager.ts +369 -0
- package/apps/api/src/lib/ssl-scheduler.ts +109 -0
- package/apps/api/src/lib/stack-detector.ts +708 -0
- package/apps/api/src/lib/system-debug.ts +10 -0
- package/apps/api/src/middleware/auth.ts +49 -13
- package/apps/api/src/middleware/error-handler.ts +23 -3
- package/apps/api/src/middleware/index.ts +2 -0
- package/apps/api/src/middleware/internal-auth.ts +40 -0
- package/apps/api/src/middleware/local-only.ts +20 -0
- package/apps/api/src/middleware/rate-limiter.ts +9 -0
- package/apps/api/src/modules/analytics/analytics.controller.ts +111 -0
- package/apps/api/src/modules/analytics/analytics.routes.ts +29 -0
- package/apps/api/src/modules/analytics/analytics.schema.ts +37 -0
- package/apps/api/src/modules/analytics/analytics.service.ts +264 -0
- package/apps/api/src/modules/auth/auth.routes.ts +233 -6
- package/apps/api/src/modules/billing/billing.routes.ts +8 -0
- package/apps/api/src/modules/cloud/cloud.controller.ts +225 -0
- package/apps/api/src/modules/cloud/cloud.routes.ts +40 -0
- package/apps/api/src/modules/deployments/build.service.ts +791 -0
- package/apps/api/src/modules/deployments/deployment-lifecycle.ts +138 -0
- package/apps/api/src/modules/deployments/deployment.controller.ts +324 -16
- package/apps/api/src/modules/deployments/deployment.routes.ts +33 -7
- package/apps/api/src/modules/deployments/deployment.schema.ts +37 -5
- package/apps/api/src/modules/deployments/deployment.service.ts +178 -11
- package/apps/api/src/modules/deployments/preflight.ts +280 -0
- package/apps/api/src/modules/deployments/prepare.service.ts +252 -0
- package/apps/api/src/modules/deployments/session-manager.ts +283 -0
- package/apps/api/src/modules/deployments/ssl.service.ts +73 -0
- package/apps/api/src/modules/domains/domain.controller.ts +59 -7
- package/apps/api/src/modules/domains/domain.routes.ts +20 -5
- package/apps/api/src/modules/domains/domain.schema.ts +35 -0
- package/apps/api/src/modules/domains/domain.service.ts +375 -9
- package/apps/api/src/modules/github/github.auth.ts +397 -0
- package/apps/api/src/modules/github/github.controller.ts +387 -0
- package/apps/api/src/modules/github/github.local-auth.ts +251 -0
- package/apps/api/src/modules/github/github.routes.ts +50 -0
- package/apps/api/src/modules/github/github.schema.ts +52 -0
- package/apps/api/src/modules/github/github.service.ts +592 -0
- package/apps/api/src/modules/github/github.types.ts +158 -0
- package/apps/api/src/modules/github/github.webhook.ts +186 -0
- package/apps/api/src/modules/github/index.ts +16 -0
- package/apps/api/src/modules/health/health.routes.ts +35 -0
- package/apps/api/src/modules/projects/project.controller.ts +481 -12
- package/apps/api/src/modules/projects/project.routes.ts +63 -6
- package/apps/api/src/modules/projects/project.schema.ts +104 -6
- package/apps/api/src/modules/projects/project.service.ts +502 -11
- package/apps/api/src/modules/settings/settings.controller.ts +55 -0
- package/apps/api/src/modules/settings/settings.routes.ts +25 -0
- package/apps/api/src/modules/settings/settings.service.ts +49 -0
- package/apps/api/src/modules/system/filesystem.controller.ts +66 -0
- package/apps/api/src/modules/system/index.ts +1 -0
- package/apps/api/src/modules/system/server-check.controller.ts +475 -0
- package/apps/api/src/modules/system/setup-session.ts +255 -0
- package/apps/api/src/modules/system/setup.controller.ts +128 -0
- package/apps/api/src/modules/system/system.routes.ts +42 -0
- package/apps/api/src/modules/webhooks/webhook.controller.ts +57 -15
- package/apps/api/src/modules/webhooks/webhook.routes.ts +11 -8
- package/apps/api/src/modules/webhooks/webhook.service.ts +46 -5
- package/apps/api/src/modules/webhooks/webhook.types.ts +35 -0
- package/apps/api/tsconfig.json +3 -1
- package/apps/cli/package.json +8 -10
- package/apps/cli/tsconfig.json +2 -1
- package/apps/dashboard/Dockerfile +4 -6
- package/apps/dashboard/components.json +20 -0
- package/apps/dashboard/next-env.d.ts +6 -0
- package/apps/dashboard/next.config.mjs +11 -1
- package/apps/dashboard/package.json +25 -13
- package/apps/dashboard/postcss.config.mjs +5 -0
- package/apps/dashboard/public/android-chrome-192x192.png +0 -0
- package/apps/dashboard/public/android-chrome-512x512.png +0 -0
- package/apps/dashboard/public/apple-touch-icon.png +0 -0
- package/apps/dashboard/public/favicon-16x16.png +0 -0
- package/apps/dashboard/public/favicon-32x32.png +0 -0
- package/apps/dashboard/public/favicon.ico +0 -0
- package/apps/dashboard/public/site.webmanifest +19 -0
- package/apps/dashboard/src/app/(auth)/forgot-password/page.tsx +114 -0
- package/apps/dashboard/src/app/(auth)/layout.tsx +18 -3
- package/apps/dashboard/src/app/(auth)/login/page.tsx +215 -6
- package/apps/dashboard/src/app/(auth)/providers.tsx +34 -0
- package/apps/dashboard/src/app/(auth)/register/page.tsx +171 -5
- package/apps/dashboard/src/app/(auth)/reset-password/page.tsx +172 -0
- package/apps/dashboard/src/app/(auth)/verify-email/page.tsx +190 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/build/[id]/page.tsx +162 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/BuildSummary.tsx +166 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/DnsConfiguration.tsx +119 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/DomainSettings.tsx +291 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/Header.tsx +71 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/Sidebar.tsx +270 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/SkeletonLoader.tsx +87 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/page.tsx +169 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/layout.tsx +7 -0
- package/apps/dashboard/src/app/(dashboard)/billing/page.tsx +1 -8
- package/apps/dashboard/src/app/(dashboard)/deployments/components/CommitDetailsModal.tsx +240 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentCard.tsx +121 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentHeader.tsx +89 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentMenu.tsx +182 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsContent.tsx +324 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsFilters.tsx +99 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsList.tsx +31 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/EmptyState.tsx +101 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/LoadingSkeleton.tsx +57 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/ProjectFilter.tsx +109 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/index.ts +9 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/page.tsx +9 -3
- package/apps/dashboard/src/app/(dashboard)/deployments/types.ts +44 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/utils.ts +176 -0
- package/apps/dashboard/src/app/(dashboard)/domains/page.tsx +1 -6
- package/apps/dashboard/src/app/(dashboard)/integrations/page.tsx +321 -0
- package/apps/dashboard/src/app/(dashboard)/layout.tsx +22 -32
- package/apps/dashboard/src/app/(dashboard)/library/components/ConnectPrompt.tsx +187 -0
- package/apps/dashboard/src/app/(dashboard)/library/components/LibrarySidebar.tsx +147 -0
- package/apps/dashboard/src/app/(dashboard)/library/components/LoadingSkeleton.tsx +39 -0
- package/apps/dashboard/src/app/(dashboard)/library/components/LocalProjects.tsx +548 -0
- package/apps/dashboard/src/app/(dashboard)/library/components/RepositoryList.tsx +292 -0
- package/apps/dashboard/src/app/(dashboard)/library/components/TemplateGrid.tsx +36 -0
- package/apps/dashboard/src/app/(dashboard)/library/components/UrlImport.tsx +74 -0
- package/apps/dashboard/src/app/(dashboard)/library/page.tsx +121 -0
- package/apps/dashboard/src/app/(dashboard)/library/types.ts +26 -0
- package/apps/dashboard/src/app/(dashboard)/monitoring/page.tsx +1 -6
- package/apps/dashboard/src/app/(dashboard)/page.tsx +485 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/[[...slug]]/layout.tsx +22 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/[[...slug]]/page.tsx +286 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/AdvancedSettings.tsx +235 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/BuildSettings.tsx +174 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DeleteConfirmationDialog.tsx +45 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DeletionModal.tsx +95 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/Deployments.tsx +11 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DomainSettings.tsx +523 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/EnvironmentSettings.tsx +246 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GeneralSettings.tsx +93 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GitInfo.tsx +261 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GitSettings.tsx +391 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/LogsSettings.tsx +133 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ProjectNotFound.tsx +95 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ProjectsBottomNavigation.tsx +62 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ResourceSettings.tsx +333 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SettingSection.tsx +66 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SettingsNavigation.tsx +27 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SleepModeSettings.tsx +134 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProductionUrl.tsx +25 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProjectIdentity.tsx +159 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProjectInfo.tsx +58 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/SkeletonLoader.tsx +170 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/StatsCards.tsx +33 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/TopPaths.tsx +56 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/TrafficChart.tsx +157 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/index.ts +14 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/LogsActions.tsx +52 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/ServerLogs.tsx +249 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/TerminalLogs.tsx +682 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/logs.css +127 -0
- package/apps/dashboard/src/app/(dashboard)/projects/components/DeploymentCard.tsx +73 -0
- package/apps/dashboard/src/app/(dashboard)/projects/components/ProjectCard.tsx +330 -0
- package/apps/dashboard/src/app/(dashboard)/projects/page.tsx +326 -4
- package/apps/dashboard/src/app/(dashboard)/providers.tsx +23 -0
- package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/components-tab.tsx +329 -0
- package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/overview-tab.tsx +229 -0
- package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/terminal-tab.tsx +38 -0
- package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/page.tsx +437 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/checking-state.tsx +15 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/choose-mode.tsx +54 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/component-row.tsx +65 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/error-banner.tsx +13 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/installing-panel.tsx +227 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/results-panel.tsx +90 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/setup-header.tsx +56 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/types.ts +13 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/page.tsx +666 -0
- package/apps/dashboard/src/app/(dashboard)/servers/page.tsx +283 -0
- package/apps/dashboard/src/app/(dashboard)/settings/_components/BuildPreferences.tsx +110 -0
- package/apps/dashboard/src/app/(dashboard)/settings/_components/CloudConnection.tsx +147 -0
- package/apps/dashboard/src/app/(dashboard)/settings/_components/InstanceInfo.tsx +54 -0
- package/apps/dashboard/src/app/(dashboard)/settings/_components/ServerConnection.tsx +407 -0
- package/apps/dashboard/src/app/(dashboard)/settings/_components/SettingsSection.tsx +32 -0
- package/apps/dashboard/src/app/(dashboard)/settings/page.tsx +62 -3
- package/apps/dashboard/src/app/auth/callback/close/page.tsx +23 -0
- package/apps/dashboard/src/app/auth/callback/install/page.tsx +40 -0
- package/apps/dashboard/src/app/authorize/page.tsx +137 -0
- package/apps/dashboard/src/app/globals.css +57 -3
- package/apps/dashboard/src/app/layout.tsx +43 -3
- package/apps/dashboard/src/components/auth-shell.tsx +66 -0
- package/apps/dashboard/src/components/deployments/types.ts +44 -0
- package/apps/dashboard/src/components/global-deployments/index.ts +17 -0
- package/apps/dashboard/src/components/i18n-provider.tsx +100 -0
- package/apps/dashboard/src/components/import-project/BuildSettings.tsx +376 -0
- package/apps/dashboard/src/components/import-project/BuildSkeleton.tsx +161 -0
- package/apps/dashboard/src/components/import-project/BuildTerminal.tsx +358 -0
- package/apps/dashboard/src/components/import-project/ComposeServices.tsx +455 -0
- package/apps/dashboard/src/components/import-project/DeploymentProcessing.tsx +510 -0
- package/apps/dashboard/src/components/import-project/DockerSettings.tsx +64 -0
- package/apps/dashboard/src/components/import-project/EnvironmentVariables.tsx +481 -0
- package/apps/dashboard/src/components/import-project/Frameworks.tsx +90 -0
- package/apps/dashboard/src/components/import-project/ProjectSettings.tsx +160 -0
- package/apps/dashboard/src/components/import-project/types.ts +82 -0
- package/apps/dashboard/src/components/integrations/GithubPermissionModal.tsx +173 -0
- package/apps/dashboard/src/components/language-switcher.tsx +36 -0
- package/apps/dashboard/src/components/logo.tsx +13 -0
- package/apps/dashboard/src/components/network-error-handler.tsx +27 -0
- package/apps/dashboard/src/components/oauth-buttons.tsx +81 -0
- package/apps/dashboard/src/components/overview/ActivityChart.tsx +247 -0
- package/apps/dashboard/src/components/overview/ApiRequestsCard.tsx +111 -0
- package/apps/dashboard/src/components/overview/CreditsCard.tsx +137 -0
- package/apps/dashboard/src/components/overview/DeploymentsChart.tsx +195 -0
- package/apps/dashboard/src/components/overview/EmptyState.tsx +126 -0
- package/apps/dashboard/src/components/overview/LoadingSkeleton.tsx +92 -0
- package/apps/dashboard/src/components/overview/OverviewHeader.tsx +74 -0
- package/apps/dashboard/src/components/overview/OverviewHeroChart.tsx +344 -0
- package/apps/dashboard/src/components/overview/ProjectsCard.tsx +134 -0
- package/apps/dashboard/src/components/overview/QuickLinks.tsx +119 -0
- package/apps/dashboard/src/components/overview/SandboxesCard.tsx +150 -0
- package/apps/dashboard/src/components/overview/StatsGrid.tsx +166 -0
- package/apps/dashboard/src/components/overview/TokenUsageChart.tsx +206 -0
- package/apps/dashboard/src/components/overview/UsageStats.tsx +79 -0
- package/apps/dashboard/src/components/overview/index.ts +30 -0
- package/apps/dashboard/src/components/overview/types.ts +116 -0
- package/apps/dashboard/src/components/page-header.tsx +25 -0
- package/apps/dashboard/src/components/project-settings/ServerSideSwitch.jsx +60 -0
- package/apps/dashboard/src/components/shared/AlertBox.tsx +39 -0
- package/apps/dashboard/src/components/shared/CTASection.tsx +45 -0
- package/apps/dashboard/src/components/shared/ErrorState.tsx +176 -0
- package/apps/dashboard/src/components/shared/FeatureCard.tsx +20 -0
- package/apps/dashboard/src/components/shared/MDXComponents.tsx +24 -0
- package/apps/dashboard/src/components/shared/MachineSettingsModal.tsx +286 -0
- package/apps/dashboard/src/components/shared/Modal.tsx +39 -0
- package/apps/dashboard/src/components/shared/OTPInput.tsx +122 -0
- package/apps/dashboard/src/components/shared/PageHero.tsx +21 -0
- package/apps/dashboard/src/components/shared/PlatformFeatureCard.tsx +27 -0
- package/apps/dashboard/src/components/shared/StatCard.tsx +14 -0
- package/apps/dashboard/src/components/shared/ValueCard.tsx +20 -0
- package/apps/dashboard/src/components/shared/index.ts +8 -0
- package/apps/dashboard/src/components/sidebar.tsx +282 -0
- package/apps/dashboard/src/components/theme-provider.tsx +96 -0
- package/apps/dashboard/src/components/toast.tsx +106 -0
- package/apps/dashboard/src/components/ui/CustomCursor.tsx +107 -0
- package/apps/dashboard/src/components/ui/CustomSelect.tsx +126 -0
- package/apps/dashboard/src/components/ui/DropdownMenu.tsx +174 -0
- package/apps/dashboard/src/components/ui/FileIcon.jsx +59 -0
- package/apps/dashboard/src/components/ui/IconPickerModal.tsx +273 -0
- package/apps/dashboard/src/components/ui/InfoBanner.jsx +39 -0
- package/apps/dashboard/src/components/ui/Logo.tsx +14 -0
- package/apps/dashboard/src/components/ui/Modal.tsx +117 -0
- package/apps/dashboard/src/components/ui/PageContainer.tsx +12 -0
- package/apps/dashboard/src/components/ui/SectionContainer.jsx +7 -0
- package/apps/dashboard/src/components/ui/SlidingToggle.tsx +128 -0
- package/apps/dashboard/src/components/ui/Toast.tsx +29 -0
- package/apps/dashboard/src/components/ui/button.tsx +58 -0
- package/apps/dashboard/src/components/ui/card.tsx +60 -0
- package/apps/dashboard/src/components/ui/input.tsx +20 -0
- package/apps/dashboard/src/components/ui/label.tsx +19 -0
- package/apps/dashboard/src/components/ui/select.tsx +10 -0
- package/apps/dashboard/src/components/ui/textarea.tsx +9 -0
- package/apps/dashboard/src/constants/lang-colors.ts +25 -0
- package/apps/dashboard/src/constants/mock.ts +38 -0
- package/apps/dashboard/src/context/AuthContext.tsx +91 -0
- package/apps/dashboard/src/context/CloudContext.tsx +275 -0
- package/apps/dashboard/src/context/DeploymentContext.tsx +71 -0
- package/apps/dashboard/src/context/GitHubContext.tsx +288 -0
- package/apps/dashboard/src/context/ModalContext.tsx +300 -0
- package/apps/dashboard/src/context/NetworkContext.tsx +32 -0
- package/apps/dashboard/src/context/ProjectSettingsContext.tsx +727 -0
- package/apps/dashboard/src/context/ToastContext.tsx +129 -0
- package/apps/dashboard/src/context/deployment/index.ts +3 -0
- package/apps/dashboard/src/context/deployment/types.ts +183 -0
- package/apps/dashboard/src/context/deployment/useDeploymentBuild.ts +547 -0
- package/apps/dashboard/src/context/deployment/useDeploymentConfig.ts +176 -0
- package/apps/dashboard/src/hooks/useBuildConnection.ts +334 -0
- package/apps/dashboard/src/hooks/useMonitorStream.ts +146 -0
- package/apps/dashboard/src/hooks/useProjectData.ts +110 -0
- package/apps/dashboard/src/hooks/useSSEConnection.ts +465 -0
- package/apps/dashboard/src/hooks/useSSEStream.ts +309 -0
- package/apps/dashboard/src/hooks/useSessions.ts +104 -0
- package/apps/dashboard/src/hooks/useSetupStream.ts +223 -0
- package/apps/dashboard/src/i18n/dictionaries/ar.json +218 -0
- package/apps/dashboard/src/i18n/dictionaries/en.json +218 -0
- package/apps/dashboard/src/i18n/index.ts +16 -0
- package/apps/dashboard/src/lib/api/ai.ts +22 -0
- package/apps/dashboard/src/lib/api/auth.ts +13 -0
- package/apps/dashboard/src/lib/api/client.ts +199 -0
- package/apps/dashboard/src/lib/api/cloud.ts +15 -0
- package/apps/dashboard/src/lib/api/deploy.ts +58 -0
- package/apps/dashboard/src/lib/api/domains.ts +13 -0
- package/apps/dashboard/src/lib/api/endpoints.ts +129 -0
- package/apps/dashboard/src/lib/api/github.ts +31 -0
- package/apps/dashboard/src/lib/api/icons.ts +12 -0
- package/apps/dashboard/src/lib/api/index.ts +41 -0
- package/apps/dashboard/src/lib/api/projects.ts +153 -0
- package/apps/dashboard/src/lib/api/sandbox.ts +14 -0
- package/apps/dashboard/src/lib/api/settings.ts +21 -0
- package/apps/dashboard/src/lib/api/system.ts +159 -0
- package/apps/dashboard/src/lib/auth-client.ts +54 -0
- package/apps/dashboard/src/lib/country.ts +25 -0
- package/apps/dashboard/src/lib/server/api.ts +140 -0
- package/apps/dashboard/src/lib/server/session.ts +103 -0
- package/apps/dashboard/src/lib/sseClient.ts +241 -0
- package/apps/dashboard/src/lib/sseMessageProcessors.ts +323 -0
- package/apps/dashboard/src/lib/utils.ts +6 -0
- package/apps/dashboard/src/proxy.ts +46 -0
- package/apps/dashboard/src/styles/Toast.module.css +92 -0
- package/apps/dashboard/src/styles/fonts.css +93 -0
- package/apps/dashboard/src/styles/theme.css +336 -0
- package/apps/dashboard/src/types/research.ts +42 -0
- package/apps/dashboard/src/utils/SSEParser.js +150 -0
- package/apps/dashboard/src/utils/authWindow.ts +143 -0
- package/apps/dashboard/src/utils/codeTheme.ts +127 -0
- package/apps/dashboard/src/utils/colors.json +2810 -0
- package/apps/dashboard/src/utils/date.ts +121 -0
- package/apps/dashboard/src/utils/deployment.ts +128 -0
- package/apps/dashboard/src/utils/deploymentPhaseDetector.ts +232 -0
- package/apps/dashboard/src/utils/extToLang.js +103 -0
- package/apps/dashboard/src/utils/github.ts +62 -0
- package/apps/dashboard/src/utils/icons.js +46 -0
- package/apps/dashboard/src/utils/repoSlug.ts +110 -0
- package/apps/dashboard/src/utils/research-api.ts +163 -0
- package/apps/dashboard/src/utils/suggestions.ts +84 -0
- package/apps/dashboard/src/utils/theme.js +1 -0
- package/apps/dashboard/src/utils/ui-helpers.tsx +30 -0
- package/apps/dashboard/src/utils/upload.js +12 -0
- package/apps/dashboard/tsconfig.json +27 -5
- package/apps/desktop/forge.config.json +36 -0
- package/apps/desktop/package.json +26 -0
- package/apps/desktop/scripts/dev.mjs +58 -0
- package/apps/desktop/src/main/index.ts +675 -0
- package/apps/desktop/src/main/types/desktop.d.ts +33 -0
- package/apps/desktop/src/preload/index.ts +88 -0
- package/apps/desktop/src/renderer/index.html +462 -0
- package/apps/desktop/src/renderer/onboarding.js +511 -0
- package/apps/desktop/src/renderer/styles.css +1139 -0
- package/apps/desktop/tsconfig.json +17 -0
- package/apps/web/.source/browser.ts +13 -0
- package/apps/web/.source/dynamic.ts +8 -0
- package/apps/web/.source/server.ts +22 -0
- package/apps/web/.source/source.config.mjs +20 -0
- package/apps/web/Dockerfile +4 -6
- package/apps/web/content/blog/how-ai-builds-work.mdx +55 -0
- package/apps/web/content/blog/introducing-openship.mdx +46 -0
- package/apps/web/content/blog/self-hosting-cost-breakdown.mdx +59 -0
- package/apps/web/content/docs/_meta.json +14 -0
- package/apps/web/content/docs/api.mdx +98 -0
- package/apps/web/content/docs/cli.mdx +80 -0
- package/apps/web/content/docs/first-deployment.mdx +56 -0
- package/apps/web/content/docs/index.mdx +27 -0
- package/apps/web/content/docs/installation.mdx +65 -0
- package/apps/web/content/docs/quickstart.mdx +45 -0
- package/apps/web/next-env.d.ts +6 -0
- package/apps/web/next.config.mjs +16 -2
- package/apps/web/package.json +19 -12
- package/apps/web/postcss.config.mjs +5 -0
- package/apps/web/public/android-chrome-192x192.png +0 -0
- package/apps/web/public/android-chrome-512x512.png +0 -0
- package/apps/web/public/apple-touch-icon.png +0 -0
- package/apps/web/public/favicon-16x16.png +0 -0
- package/apps/web/public/favicon-32x32.png +0 -0
- package/apps/web/public/favicon.ico +0 -0
- package/apps/web/public/site.webmanifest +1 -0
- package/apps/web/source.config.ts +17 -0
- package/apps/web/src/app/(marketing)/layout.tsx +7 -22
- package/apps/web/src/app/blog/[...slug]/page.tsx +247 -0
- package/apps/web/src/app/blog/blog.css +575 -0
- package/apps/web/src/app/blog/layout.tsx +50 -0
- package/apps/web/src/app/blog/page.tsx +235 -0
- package/apps/web/src/app/docs/[[...slug]]/page.tsx +67 -0
- package/apps/web/src/app/docs/layout.tsx +62 -0
- package/apps/web/src/app/docs/toc-theme.css +71 -0
- package/apps/web/src/app/download/page.tsx +396 -0
- package/apps/web/src/app/globals.css +20 -3
- package/apps/web/src/app/layout.tsx +57 -3
- package/apps/web/src/app/page.tsx +47 -6
- package/apps/web/src/app/robots.ts +15 -0
- package/apps/web/src/app/sitemap.ts +35 -0
- package/apps/web/src/components/blog/share-sidebar.tsx +81 -0
- package/apps/web/src/components/blog/writer-sidebar.tsx +81 -0
- package/apps/web/src/components/landing/ai-native.tsx +169 -0
- package/apps/web/src/components/landing/backups.tsx +139 -0
- package/apps/web/src/components/landing/cdn.tsx +109 -0
- package/apps/web/src/components/landing/coming-soon.tsx +180 -0
- package/apps/web/src/components/landing/dark-section.tsx +166 -0
- package/apps/web/src/components/landing/dashboard.tsx +407 -0
- package/apps/web/src/components/landing/developer-experience.tsx +224 -0
- package/apps/web/src/components/landing/dns-domains.tsx +146 -0
- package/apps/web/src/components/landing/download-button.tsx +151 -0
- package/apps/web/src/components/landing/features/ai-visual.tsx +48 -0
- package/apps/web/src/components/landing/features/cloud-visual.tsx +44 -0
- package/apps/web/src/components/landing/features/git-visual.tsx +61 -0
- package/apps/web/src/components/landing/features/index.tsx +642 -0
- package/apps/web/src/components/landing/features/infra-visual.tsx +69 -0
- package/apps/web/src/components/landing/features/rollback-visual.tsx +42 -0
- package/apps/web/src/components/landing/features/ssl-visual.tsx +41 -0
- package/apps/web/src/components/landing/features/stacks-visual.tsx +54 -0
- package/apps/web/src/components/landing/final-cta.tsx +116 -0
- package/apps/web/src/components/landing/footer.tsx +145 -0
- package/apps/web/src/components/landing/hero.tsx +110 -0
- package/apps/web/src/components/landing/how-it-works.tsx +210 -0
- package/apps/web/src/components/landing/index.ts +21 -0
- package/apps/web/src/components/landing/mail-server.tsx +122 -0
- package/apps/web/src/components/landing/navbar.tsx +199 -0
- package/apps/web/src/components/landing/no-lockin.tsx +185 -0
- package/apps/web/src/components/landing/open-source-cta.tsx +151 -0
- package/apps/web/src/components/landing/portability.tsx +190 -0
- package/apps/web/src/components/landing/pricing.tsx +263 -0
- package/apps/web/src/components/landing/scaling.tsx +209 -0
- package/apps/web/src/components/landing/why-openship.tsx +291 -0
- package/apps/web/src/hooks/use-gsap-scroll.ts +158 -0
- package/apps/web/src/hooks/use-platform.ts +86 -0
- package/apps/web/src/lib/source.ts +12 -0
- package/apps/web/src/styles/fonts.css +84 -0
- package/apps/web/src/styles/landing.css +951 -0
- package/apps/web/src/styles/theme.css +227 -0
- package/apps/web/tsconfig.json +8 -3
- package/bun.lock +3260 -0
- package/docker-compose.yml +3 -0
- package/docs/screenshots/.gitkeep +0 -0
- package/docs/screenshots/screen.png +0 -0
- package/openship.code-workspace +7 -0
- package/package.json +23 -9
- package/packages/adapters/docs/ARCHITECTURE.md +160 -0
- package/packages/adapters/docs/BUILD-PIPELINE.md +171 -0
- package/packages/adapters/docs/CLOUD.md +239 -0
- package/packages/adapters/docs/EXECUTOR.md +174 -0
- package/packages/adapters/docs/LOG-STREAMING.md +175 -0
- package/packages/adapters/docs/SYSTEM.md +191 -0
- package/packages/adapters/package.json +14 -9
- package/packages/adapters/src/index.ts +144 -4
- package/packages/adapters/src/infra/cloud.ts +42 -0
- package/packages/adapters/src/infra/index.ts +9 -0
- package/packages/adapters/src/infra/noop.ts +27 -0
- package/packages/adapters/src/infra/traefik.ts +297 -0
- package/packages/adapters/src/infra/types.ts +36 -0
- package/packages/adapters/src/platform.ts +255 -0
- package/packages/adapters/src/runtime/bare.ts +567 -0
- package/packages/adapters/src/runtime/build-pipeline.ts +237 -0
- package/packages/adapters/src/runtime/cloud.ts +791 -0
- package/packages/adapters/src/runtime/deploy-pipeline.ts +146 -0
- package/packages/adapters/src/runtime/docker.ts +443 -0
- package/packages/adapters/src/runtime/index.ts +69 -0
- package/packages/adapters/src/runtime/local-build.ts +112 -0
- package/packages/adapters/src/runtime/transfer.ts +82 -0
- package/packages/adapters/src/runtime/types.ts +138 -0
- package/packages/adapters/src/system/catalog.ts +188 -0
- package/packages/adapters/src/system/checks.ts +228 -0
- package/packages/adapters/src/system/components.ts +45 -0
- package/packages/adapters/src/system/debug.ts +18 -0
- package/packages/adapters/src/system/environment.ts +168 -0
- package/packages/adapters/src/system/errors.ts +34 -0
- package/packages/adapters/src/system/executor.ts +600 -0
- package/packages/adapters/src/system/index.ts +58 -0
- package/packages/adapters/src/system/installer.ts +310 -0
- package/packages/adapters/src/system/setup.ts +442 -0
- package/packages/adapters/src/system/state.ts +96 -0
- package/packages/adapters/src/system/types.ts +116 -0
- package/packages/adapters/src/toolchain/catalog.ts +439 -0
- package/packages/adapters/src/toolchain/checks.ts +181 -0
- package/packages/adapters/src/toolchain/index.ts +38 -0
- package/packages/adapters/src/toolchain/installer.ts +189 -0
- package/packages/adapters/src/toolchain/types.ts +84 -0
- package/packages/adapters/src/types.ts +277 -0
- package/packages/adapters/tsconfig.json +3 -1
- package/packages/core/package.json +9 -9
- package/packages/core/src/constants.ts +44 -1
- package/packages/core/src/index.ts +2 -0
- package/packages/core/src/stacks.ts +778 -0
- package/packages/core/src/system.ts +111 -0
- package/packages/core/src/types.ts +22 -1
- package/packages/core/src/utils.ts +8 -0
- package/packages/core/tsconfig.json +3 -1
- package/packages/db/drizzle/0000_init.sql +231 -0
- package/packages/db/drizzle/0001_add_server_name.sql +1 -0
- package/packages/db/drizzle/meta/_journal.json +20 -0
- package/packages/db/drizzle.config.ts +10 -0
- package/packages/db/package.json +26 -14
- package/packages/db/src/client.ts +119 -0
- package/packages/db/src/index.ts +57 -8
- package/packages/db/src/repos/account.repo.ts +92 -0
- package/packages/db/src/repos/deployment.repo.ts +168 -0
- package/packages/db/src/repos/domain.repo.ts +102 -0
- package/packages/db/src/repos/git-installation.repo.ts +95 -0
- package/packages/db/src/repos/index.ts +43 -0
- package/packages/db/src/repos/instance-settings.repo.ts +43 -0
- package/packages/db/src/repos/project.repo.ts +159 -0
- package/packages/db/src/repos/session.repo.ts +82 -0
- package/packages/db/src/repos/settings.repo.ts +51 -0
- package/packages/db/src/repos/user.repo.ts +94 -0
- package/packages/db/src/schema/auth.ts +56 -0
- package/packages/db/src/schema/deployment.ts +87 -0
- package/packages/db/src/schema/domain.ts +46 -0
- package/packages/db/src/schema/github.ts +24 -0
- package/packages/db/src/schema/index.ts +6 -0
- package/packages/db/src/schema/project.ts +117 -0
- package/packages/db/src/schema/settings.ts +103 -0
- package/packages/db/tsconfig.json +3 -1
- package/packages/ui/package.json +17 -17
- package/packages/ui/src/components/status-dot.tsx +1 -1
- package/packages/ui/tsconfig.json +7 -2
- package/pnpm-workspace.yaml +0 -1
- package/{tooling/tsconfig/base.json → tsconfig.base.json} +0 -1
- package/turbo.json +4 -0
- package/apps/api/src/modules/auth/auth.controller.ts +0 -26
- package/apps/api/src/modules/auth/auth.schema.ts +0 -12
- package/apps/api/src/modules/auth/auth.service.ts +0 -23
- package/apps/dashboard/src/app/page.tsx +0 -6
- package/apps/web/src/app/(marketing)/docs/page.tsx +0 -10
- package/packages/adapters/src/base-adapter.ts +0 -49
- package/packages/adapters/src/docker-adapter.ts +0 -43
- package/packages/adapters/src/oblien-adapter.ts +0 -46
- package/packages/adapters/src/registry.ts +0 -22
- package/packages/db/prisma/schema.prisma +0 -160
- package/tooling/tsconfig/nextjs.json +0 -10
- package/tooling/tsconfig/node.json +0 -10
- package/tooling/tsconfig/package.json +0 -7
|
@@ -1,4 +1,144 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @repo/adapters — platform abstraction layer.
|
|
3
|
+
*
|
|
4
|
+
* Three layers, one entry point:
|
|
5
|
+
* 1. Runtime → build/deploy/stop/start lifecycle (Docker, Bare, Cloud)
|
|
6
|
+
* 2. Infra → routing (Traefik) + SSL (ACME) — separate from runtime
|
|
7
|
+
* 3. System → prerequisite checks + setup validation (self-hosted only)
|
|
8
|
+
*
|
|
9
|
+
* The Platform ties them together:
|
|
10
|
+
* const { runtime, routing, ssl, system } = getPlatform();
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// ─── Shared types ────────────────────────────────────────────────────────────
|
|
14
|
+
export type {
|
|
15
|
+
ResourceConfig,
|
|
16
|
+
ContainerStatus,
|
|
17
|
+
BuildStrategy,
|
|
18
|
+
BuildConfig,
|
|
19
|
+
DeployConfig,
|
|
20
|
+
BuildResult,
|
|
21
|
+
DeploymentResult,
|
|
22
|
+
BuildStep,
|
|
23
|
+
LogEntry,
|
|
24
|
+
LogCallback,
|
|
25
|
+
ContainerInfo,
|
|
26
|
+
ResourceUsage,
|
|
27
|
+
RouteConfig,
|
|
28
|
+
SslResult,
|
|
29
|
+
SshConfig,
|
|
30
|
+
CommandExecutor,
|
|
31
|
+
} from "./types";
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
BUILD_STEPS,
|
|
35
|
+
} from "./types";
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
DEFAULT_RESOURCE_CONFIG,
|
|
39
|
+
DEFAULT_BUILD_RESOURCE_CONFIG,
|
|
40
|
+
} from "./types";
|
|
41
|
+
|
|
42
|
+
// ─── Runtime layer ───────────────────────────────────────────────────────────
|
|
43
|
+
export type { RuntimeAdapter, RuntimeCapability } from "./runtime/types";
|
|
44
|
+
export { assertCapability } from "./runtime/types";
|
|
45
|
+
export { DockerRuntime, type DockerConnectionOptions } from "./runtime/docker";
|
|
46
|
+
export { BareRuntime, type BareRuntimeOptions } from "./runtime/bare";
|
|
47
|
+
export { CloudRuntime } from "./runtime/cloud";
|
|
48
|
+
export { BuildLogger } from "./runtime/build-pipeline";
|
|
49
|
+
export {
|
|
50
|
+
type DeployEnvironment,
|
|
51
|
+
type DeployRouting,
|
|
52
|
+
type DeployPipelineInput,
|
|
53
|
+
type DeployPipelineResult,
|
|
54
|
+
runDeployPipeline,
|
|
55
|
+
} from "./runtime/deploy-pipeline";
|
|
56
|
+
export {
|
|
57
|
+
type RuntimeMode,
|
|
58
|
+
type CreateRuntimeOptions,
|
|
59
|
+
createRuntime,
|
|
60
|
+
} from "./runtime/index";
|
|
61
|
+
|
|
62
|
+
// ─── Infrastructure layer ────────────────────────────────────────────────────
|
|
63
|
+
export type { RoutingProvider, SslProvider } from "./infra/types";
|
|
64
|
+
export { TraefikProvider, type TraefikProviderOptions } from "./infra/traefik";
|
|
65
|
+
export { CloudInfraProvider } from "./infra/cloud";
|
|
66
|
+
export { NoopInfraProvider } from "./infra/noop";
|
|
67
|
+
|
|
68
|
+
// ─── System layer ────────────────────────────────────────────────────────────
|
|
69
|
+
export type {
|
|
70
|
+
ComponentStatus,
|
|
71
|
+
Feature,
|
|
72
|
+
FeatureReadiness,
|
|
73
|
+
InstallerConfig,
|
|
74
|
+
InstallResult,
|
|
75
|
+
PrerequisiteRule,
|
|
76
|
+
RuntimeMode as SystemRuntimeMode,
|
|
77
|
+
SystemComponentDefinition,
|
|
78
|
+
SetupResult,
|
|
79
|
+
SystemCheckResult,
|
|
80
|
+
SystemLog,
|
|
81
|
+
SystemLogCallback,
|
|
82
|
+
} from "./system/types";
|
|
83
|
+
|
|
84
|
+
export type { SetupState, SetupStateStore, ComponentState } from "./system/state";
|
|
85
|
+
export { FileStateStore } from "./system/state";
|
|
86
|
+
|
|
87
|
+
export type {
|
|
88
|
+
EnvironmentProfile,
|
|
89
|
+
LinuxDistro,
|
|
90
|
+
SystemArch,
|
|
91
|
+
SystemOs,
|
|
92
|
+
SystemPackageManager,
|
|
93
|
+
SystemServiceManager,
|
|
94
|
+
} from "./system/environment";
|
|
95
|
+
export { resolveEnvironment } from "./system/environment";
|
|
96
|
+
export { systemCatalog } from "./system/catalog";
|
|
97
|
+
export { SYSTEM_COMPONENTS, getSystemComponentDefinition } from "./system/components";
|
|
98
|
+
export {
|
|
99
|
+
isRemoteConnectionError,
|
|
100
|
+
isRetryableRemoteConnectionError,
|
|
101
|
+
isSshAuthError,
|
|
102
|
+
} from "./system/errors";
|
|
103
|
+
|
|
104
|
+
export { LocalExecutor, SshExecutor, createExecutor } from "./system/executor";
|
|
105
|
+
|
|
106
|
+
export {
|
|
107
|
+
checkAll as checkAllComponents,
|
|
108
|
+
checkComponents,
|
|
109
|
+
checkDocker,
|
|
110
|
+
checkGit,
|
|
111
|
+
checkNode,
|
|
112
|
+
checkTraefik,
|
|
113
|
+
COMPONENT_CHECKS,
|
|
114
|
+
} from "./system/checks";
|
|
115
|
+
export {
|
|
116
|
+
COMPONENT_INSTALLERS,
|
|
117
|
+
installDocker,
|
|
118
|
+
installGit,
|
|
119
|
+
installNode,
|
|
120
|
+
installTraefik,
|
|
121
|
+
} from "./system/installer";
|
|
122
|
+
export { SystemManager, type SystemManagerOptions } from "./system/setup";
|
|
123
|
+
|
|
124
|
+
// ─── Toolchain layer ────────────────────────────────────────────────────────
|
|
125
|
+
export type {
|
|
126
|
+
ToolchainStatus,
|
|
127
|
+
ToolchainCheckResult,
|
|
128
|
+
ToolchainCheckEntry,
|
|
129
|
+
ToolchainInstallPlan,
|
|
130
|
+
ToolchainInstallResult,
|
|
131
|
+
} from "./toolchain";
|
|
132
|
+
|
|
133
|
+
export { toolchainCatalog } from "./toolchain";
|
|
134
|
+
export {
|
|
135
|
+
checkTool,
|
|
136
|
+
checkTools,
|
|
137
|
+
checkToolchain,
|
|
138
|
+
checkToolchainForStack,
|
|
139
|
+
} from "./toolchain";
|
|
140
|
+
export { installTool, installTools } from "./toolchain";
|
|
141
|
+
|
|
142
|
+
// ─── Platform (top-level entry point) ────────────────────────────────────────
|
|
143
|
+
export type { PlatformTarget, PlatformConfig, Platform } from "./platform";
|
|
144
|
+
export { createPlatform, initPlatform, getPlatform, resetPlatform } from "./platform";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud infrastructure provider — routing + SSL via Oblien API.
|
|
3
|
+
*
|
|
4
|
+
* All operations are API calls to the Oblien platform. No local reverse
|
|
5
|
+
* proxy or ACME configuration needed.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Oblien } from "oblien";
|
|
9
|
+
import type { RouteConfig, SslResult } from "../types";
|
|
10
|
+
import type { RoutingProvider, SslProvider } from "./types";
|
|
11
|
+
|
|
12
|
+
export class CloudInfraProvider implements RoutingProvider, SslProvider {
|
|
13
|
+
private readonly client: Oblien;
|
|
14
|
+
|
|
15
|
+
constructor(client: Oblien) {
|
|
16
|
+
this.client = client;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// ── Routing ──────────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
async registerRoute(route: RouteConfig): Promise<void> {
|
|
22
|
+
// TODO: POST /routes to Oblien API
|
|
23
|
+
void route;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async removeRoute(domain: string): Promise<void> {
|
|
27
|
+
// TODO: DELETE /routes/:domain
|
|
28
|
+
void domain;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ── SSL ──────────────────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
async provisionCert(domain: string): Promise<SslResult> {
|
|
34
|
+
// TODO: POST /ssl/provision — Oblien manages certs
|
|
35
|
+
return { domain, expiresAt: "", issuer: "oblien" };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async renewCert(domain: string): Promise<SslResult> {
|
|
39
|
+
// TODO: POST /ssl/renew
|
|
40
|
+
return { domain, expiresAt: "", issuer: "oblien" };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infrastructure layer barrel exports.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type { RoutingProvider, SslProvider } from "./types";
|
|
6
|
+
|
|
7
|
+
export { TraefikProvider, type TraefikProviderOptions } from "./traefik";
|
|
8
|
+
export { CloudInfraProvider } from "./cloud";
|
|
9
|
+
export { NoopInfraProvider } from "./noop";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* No-op infrastructure provider — for desktop and development.
|
|
3
|
+
*
|
|
4
|
+
* Desktop apps and local dev environments don't need reverse proxies
|
|
5
|
+
* or SSL certificates. This provider silently accepts all calls.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { RouteConfig, SslResult } from "../types";
|
|
9
|
+
import type { RoutingProvider, SslProvider } from "./types";
|
|
10
|
+
|
|
11
|
+
export class NoopInfraProvider implements RoutingProvider, SslProvider {
|
|
12
|
+
async registerRoute(_route: RouteConfig): Promise<void> {
|
|
13
|
+
// Desktop/dev — no reverse proxy
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async removeRoute(_domain: string): Promise<void> {
|
|
17
|
+
// No-op
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async provisionCert(domain: string): Promise<SslResult> {
|
|
21
|
+
return { domain, expiresAt: "", issuer: "none" };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async renewCert(domain: string): Promise<SslResult> {
|
|
25
|
+
return { domain, expiresAt: "", issuer: "none" };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Traefik infrastructure provider — routing + SSL for self-hosted deployments.
|
|
3
|
+
*
|
|
4
|
+
* Uses Traefik's dynamic file provider: writes YAML config files to a watched
|
|
5
|
+
* directory. Traefik detects changes automatically — no reload needed.
|
|
6
|
+
*
|
|
7
|
+
* SSL is handled by Traefik's built-in ACME resolver (Let's Encrypt). When a
|
|
8
|
+
* route is configured with `tls.certResolver`, Traefik auto-provisions and
|
|
9
|
+
* auto-renews certificates.
|
|
10
|
+
*
|
|
11
|
+
* This provider works with BOTH Docker and Bare runtimes — it's independent
|
|
12
|
+
* of how the application process is managed.
|
|
13
|
+
*
|
|
14
|
+
* Typical Traefik static config (traefik.yml):
|
|
15
|
+
* ```yaml
|
|
16
|
+
* providers:
|
|
17
|
+
* file:
|
|
18
|
+
* directory: /etc/traefik/dynamic
|
|
19
|
+
* watch: true
|
|
20
|
+
*
|
|
21
|
+
* certificatesResolvers:
|
|
22
|
+
* letsencrypt:
|
|
23
|
+
* acme:
|
|
24
|
+
* email: admin@example.com
|
|
25
|
+
* storage: /etc/traefik/acme.json
|
|
26
|
+
* httpChallenge:
|
|
27
|
+
* entryPoint: web
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import {
|
|
32
|
+
writeFile as fsWriteFile,
|
|
33
|
+
rm as fsRm,
|
|
34
|
+
mkdir as fsMkdir,
|
|
35
|
+
readFile as fsReadFile,
|
|
36
|
+
} from "node:fs/promises";
|
|
37
|
+
import { dirname, join } from "node:path";
|
|
38
|
+
|
|
39
|
+
import type { CommandExecutor, RouteConfig, SslResult } from "../types";
|
|
40
|
+
import type { RoutingProvider, SslProvider } from "./types";
|
|
41
|
+
|
|
42
|
+
// ─── Config ──────────────────────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
export interface TraefikProviderOptions {
|
|
45
|
+
/**
|
|
46
|
+
* Directory where Traefik watches for dynamic config files.
|
|
47
|
+
* Default: /etc/traefik/dynamic
|
|
48
|
+
*/
|
|
49
|
+
configDir?: string;
|
|
50
|
+
/**
|
|
51
|
+
* ACME certificate resolver name (must match Traefik static config).
|
|
52
|
+
* Default: "letsencrypt"
|
|
53
|
+
*/
|
|
54
|
+
certResolver?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Path to Traefik's ACME storage file (for reading cert info).
|
|
57
|
+
* Default: /etc/traefik/acme.json
|
|
58
|
+
*/
|
|
59
|
+
acmeStoragePath?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Command executor for file operations.
|
|
62
|
+
*
|
|
63
|
+
* When provided, all file reads/writes go through the executor
|
|
64
|
+
* (supporting remote servers via SSH). When omitted, uses node:fs
|
|
65
|
+
* directly (local server).
|
|
66
|
+
*
|
|
67
|
+
* This is what enables the dual-path: same TraefikProvider, same
|
|
68
|
+
* config format, works both locally and remotely.
|
|
69
|
+
*/
|
|
70
|
+
executor?: CommandExecutor;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const DEFAULT_CONFIG_DIR = "/etc/traefik/dynamic";
|
|
74
|
+
const DEFAULT_CERT_RESOLVER = "letsencrypt";
|
|
75
|
+
const DEFAULT_ACME_STORAGE = "/etc/traefik/acme.json";
|
|
76
|
+
|
|
77
|
+
// ─── Implementation ──────────────────────────────────────────────────────────
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Traefik-based routing and SSL provider.
|
|
81
|
+
*
|
|
82
|
+
* Implements both RoutingProvider and SslProvider since Traefik handles
|
|
83
|
+
* both concerns through its dynamic configuration.
|
|
84
|
+
*/
|
|
85
|
+
export class TraefikProvider implements RoutingProvider, SslProvider {
|
|
86
|
+
private readonly configDir: string;
|
|
87
|
+
private readonly certResolver: string;
|
|
88
|
+
private readonly acmeStoragePath: string;
|
|
89
|
+
private readonly executor: CommandExecutor | null;
|
|
90
|
+
|
|
91
|
+
constructor(opts?: TraefikProviderOptions) {
|
|
92
|
+
this.configDir = opts?.configDir ?? DEFAULT_CONFIG_DIR;
|
|
93
|
+
this.certResolver = opts?.certResolver ?? DEFAULT_CERT_RESOLVER;
|
|
94
|
+
this.acmeStoragePath = opts?.acmeStoragePath ?? DEFAULT_ACME_STORAGE;
|
|
95
|
+
this.executor = opts?.executor ?? null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ── File operation helpers (dual-path: local or remote) ──────────────
|
|
99
|
+
|
|
100
|
+
private async _writeFile(path: string, content: string): Promise<void> {
|
|
101
|
+
if (this.executor) {
|
|
102
|
+
await this.executor.writeFile(path, content);
|
|
103
|
+
} else {
|
|
104
|
+
await fsMkdir(dirname(path), { recursive: true });
|
|
105
|
+
await fsWriteFile(path, content, "utf-8");
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private async _readFile(path: string): Promise<string> {
|
|
110
|
+
if (this.executor) {
|
|
111
|
+
return this.executor.readFile(path);
|
|
112
|
+
}
|
|
113
|
+
return fsReadFile(path, "utf-8");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private async _rm(path: string): Promise<void> {
|
|
117
|
+
if (this.executor) {
|
|
118
|
+
await this.executor.rm(path);
|
|
119
|
+
} else {
|
|
120
|
+
try {
|
|
121
|
+
await fsRm(path);
|
|
122
|
+
} catch {
|
|
123
|
+
// Already gone
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private async _mkdir(path: string): Promise<void> {
|
|
129
|
+
if (this.executor) {
|
|
130
|
+
await this.executor.mkdir(path);
|
|
131
|
+
} else {
|
|
132
|
+
await fsMkdir(path, { recursive: true });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ── Routing ──────────────────────────────────────────────────────────
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Register a route by writing a Traefik dynamic config file.
|
|
140
|
+
*
|
|
141
|
+
* Creates a YAML file in the watched directory. Traefik picks it up
|
|
142
|
+
* automatically within seconds.
|
|
143
|
+
*/
|
|
144
|
+
async registerRoute(route: RouteConfig): Promise<void> {
|
|
145
|
+
await this._mkdir(this.configDir);
|
|
146
|
+
|
|
147
|
+
const slug = this.domainSlug(route.domain);
|
|
148
|
+
const configPath = join(this.configDir, `${slug}.yml`);
|
|
149
|
+
|
|
150
|
+
// Build Traefik dynamic configuration YAML
|
|
151
|
+
const tlsBlock = route.tls
|
|
152
|
+
? `\n tls:\n certResolver: ${this.certResolver}`
|
|
153
|
+
: "";
|
|
154
|
+
|
|
155
|
+
const yaml = `# Auto-generated by Openship — do not edit manually
|
|
156
|
+
http:
|
|
157
|
+
routers:
|
|
158
|
+
${slug}:
|
|
159
|
+
rule: "Host(\`${route.domain}\`)"
|
|
160
|
+
service: ${slug}
|
|
161
|
+
entryPoints:
|
|
162
|
+
- websecure${tlsBlock}
|
|
163
|
+
services:
|
|
164
|
+
${slug}:
|
|
165
|
+
loadBalancer:
|
|
166
|
+
servers:
|
|
167
|
+
- url: "${route.targetUrl}"
|
|
168
|
+
`;
|
|
169
|
+
|
|
170
|
+
await this._writeFile(configPath, yaml);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Remove a route by deleting its config file.
|
|
175
|
+
* Traefik detects the removal and drops the route.
|
|
176
|
+
*/
|
|
177
|
+
async removeRoute(domain: string): Promise<void> {
|
|
178
|
+
const slug = this.domainSlug(domain);
|
|
179
|
+
const configPath = join(this.configDir, `${slug}.yml`);
|
|
180
|
+
await this._rm(configPath);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ── SSL ──────────────────────────────────────────────────────────────
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Provision a TLS certificate for a domain.
|
|
187
|
+
*
|
|
188
|
+
* With Traefik + ACME, certificate provisioning is automatic when a route
|
|
189
|
+
* has `tls.certResolver` configured. This method ensures the route exists
|
|
190
|
+
* with TLS enabled and returns cert info from ACME storage.
|
|
191
|
+
*/
|
|
192
|
+
async provisionCert(domain: string): Promise<SslResult> {
|
|
193
|
+
// The route should already have TLS enabled via registerRoute().
|
|
194
|
+
// Traefik handles ACME challenge + cert issuance automatically.
|
|
195
|
+
// We check the ACME storage for cert info.
|
|
196
|
+
const certInfo = await this.readCertInfo(domain);
|
|
197
|
+
|
|
198
|
+
if (certInfo) {
|
|
199
|
+
return certInfo;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Cert not yet available — Traefik is still provisioning.
|
|
203
|
+
// Return a pending result; the caller can poll.
|
|
204
|
+
return {
|
|
205
|
+
domain,
|
|
206
|
+
expiresAt: "",
|
|
207
|
+
issuer: this.certResolver,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Renew a TLS certificate.
|
|
213
|
+
*
|
|
214
|
+
* Traefik auto-renews certificates 30 days before expiry. This method
|
|
215
|
+
* is effectively a check + trigger: it touches the route config to ensure
|
|
216
|
+
* Traefik re-evaluates the cert.
|
|
217
|
+
*/
|
|
218
|
+
async renewCert(domain: string): Promise<SslResult> {
|
|
219
|
+
// Touch the config file to trigger Traefik re-evaluation
|
|
220
|
+
const slug = this.domainSlug(domain);
|
|
221
|
+
const configPath = join(this.configDir, `${slug}.yml`);
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
const content = await this._readFile(configPath);
|
|
225
|
+
const updated = content.replace(
|
|
226
|
+
/^# Auto-generated by Openship.*/,
|
|
227
|
+
`# Auto-generated by Openship — renewed ${new Date().toISOString()}`,
|
|
228
|
+
);
|
|
229
|
+
await this._writeFile(configPath, updated);
|
|
230
|
+
} catch {
|
|
231
|
+
// Config file doesn't exist — nothing to renew
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return this.provisionCert(domain);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Convert a domain to a safe slug for file names and Traefik identifiers.
|
|
241
|
+
* "my-app.example.com" → "my-app-example-com"
|
|
242
|
+
*/
|
|
243
|
+
private domainSlug(domain: string): string {
|
|
244
|
+
return domain.replace(/[^a-zA-Z0-9-]/g, "-").replace(/-+/g, "-");
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Read certificate info from Traefik's ACME storage file.
|
|
249
|
+
*
|
|
250
|
+
* The acme.json file contains all managed certificates. We look for
|
|
251
|
+
* the one matching the given domain.
|
|
252
|
+
*/
|
|
253
|
+
private async readCertInfo(domain: string): Promise<SslResult | null> {
|
|
254
|
+
try {
|
|
255
|
+
const raw = await this._readFile(this.acmeStoragePath);
|
|
256
|
+
const storage = JSON.parse(raw);
|
|
257
|
+
|
|
258
|
+
// ACME storage structure: { [resolverName]: { Certificates: [...] } }
|
|
259
|
+
const resolver = storage[this.certResolver];
|
|
260
|
+
if (!resolver?.Certificates) return null;
|
|
261
|
+
|
|
262
|
+
for (const cert of resolver.Certificates) {
|
|
263
|
+
if (cert.domain?.main === domain || cert.domain?.sans?.includes(domain)) {
|
|
264
|
+
// Parse the certificate to get expiry
|
|
265
|
+
// Certificate is base64-encoded PEM
|
|
266
|
+
const certPem = Buffer.from(cert.certificate, "base64").toString("utf-8");
|
|
267
|
+
const expiresAt = await this.parseCertExpiry(certPem);
|
|
268
|
+
|
|
269
|
+
return {
|
|
270
|
+
domain,
|
|
271
|
+
expiresAt: expiresAt ?? "",
|
|
272
|
+
issuer: this.certResolver,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return null;
|
|
278
|
+
} catch {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Extract the expiry date from a PEM certificate.
|
|
285
|
+
* Uses a simple regex on the date field — avoids heavy crypto deps.
|
|
286
|
+
*/
|
|
287
|
+
private async parseCertExpiry(pem: string): Promise<string | null> {
|
|
288
|
+
// For a proper implementation, use node:crypto X509Certificate
|
|
289
|
+
try {
|
|
290
|
+
const { X509Certificate } = await import("node:crypto");
|
|
291
|
+
const cert = new X509Certificate(pem);
|
|
292
|
+
return new Date(cert.validTo).toISOString();
|
|
293
|
+
} catch {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infrastructure provider interfaces — routing and SSL.
|
|
3
|
+
*
|
|
4
|
+
* Routing and SSL are separate from the runtime because:
|
|
5
|
+
* - Docker is a runtime, not a reverse proxy. Traefik/Caddy/Nginx handle routing.
|
|
6
|
+
* - SSL is managed by ACME resolvers (Traefik, certbot), not by Docker.
|
|
7
|
+
* - Cloud routing uses a completely different mechanism (API calls).
|
|
8
|
+
* - Desktop/dev doesn't need routing or SSL at all.
|
|
9
|
+
*
|
|
10
|
+
* Implementations:
|
|
11
|
+
* - TraefikProvider → Traefik file provider + ACME (self-hosted)
|
|
12
|
+
* - CloudInfra → Oblien API (cloud)
|
|
13
|
+
* - NoopInfra → No-op (desktop/dev)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { RouteConfig, SslResult } from "../types";
|
|
17
|
+
|
|
18
|
+
// ─── Routing ─────────────────────────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
export interface RoutingProvider {
|
|
21
|
+
/** Register a reverse-proxy route (domain → container/process) */
|
|
22
|
+
registerRoute(route: RouteConfig): Promise<void>;
|
|
23
|
+
|
|
24
|
+
/** Remove a reverse-proxy route */
|
|
25
|
+
removeRoute(domain: string): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// ─── SSL ─────────────────────────────────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
export interface SslProvider {
|
|
31
|
+
/** Provision a new TLS certificate for a domain */
|
|
32
|
+
provisionCert(domain: string): Promise<SslResult>;
|
|
33
|
+
|
|
34
|
+
/** Renew an existing TLS certificate */
|
|
35
|
+
renewCert(domain: string): Promise<SslResult>;
|
|
36
|
+
}
|