openship 0.1.1 → 0.1.7
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/dist/index.d.ts +1 -0
- package/dist/index.js +5786 -0
- package/dist/server/index.js +324319 -0
- package/dist/server/migrations/0000_init.sql +666 -0
- package/dist/server/migrations/0001_brief_tomorrow_man.sql +47 -0
- package/dist/server/migrations/0002_funny_dazzler.sql +2 -0
- package/dist/server/migrations/0003_third_killer_shrike.sql +1 -0
- package/dist/server/migrations/0004_session_active_org_not_null.sql +10 -0
- package/dist/server/migrations/0005_warm_amazoness.sql +3 -0
- package/dist/server/migrations/0006_lumpy_joystick.sql +1 -0
- package/dist/server/migrations/0007_outgoing_maginty.sql +2 -0
- package/dist/server/migrations/0008_frozen_cutover.sql +3 -0
- package/dist/server/migrations/0009_credits_billing.sql +142 -0
- package/dist/server/migrations/0010_credit_grant_dedupe.sql +14 -0
- package/dist/server/migrations/0011_remove_credit_ledger.sql +23 -0
- package/dist/server/migrations/0012_smart_deploys_and_git_rollback.sql +81 -0
- package/dist/server/migrations/0013_fix_check_run_rollup_unique.sql +38 -0
- package/dist/server/migrations/0014_default_rollback_git.sql +9 -0
- package/dist/server/migrations/0015_billing_idempotency_grants.sql +41 -0
- package/dist/server/migrations/0016_github_auth_high_findings.sql +30 -0
- package/dist/server/migrations/0017_spooky_rumiko_fujikawa.sql +6 -0
- package/dist/server/migrations/0018_calm_shatterstar.sql +1 -0
- package/dist/server/migrations/0019_rename_workspace_install_to_prepare.sql +1 -0
- package/dist/server/migrations/0020_uneven_the_renegades.sql +13 -0
- package/dist/server/migrations/0021_shiny_firestar.sql +2 -0
- package/dist/server/migrations/0022_version_on_success_backfill.sql +6 -0
- package/dist/server/migrations/0023_productive_gorilla_man.sql +17 -0
- package/dist/server/migrations/0024_sleepy_peter_quill.sql +2 -0
- package/dist/server/migrations/0025_smooth_blue_shield.sql +1 -0
- package/dist/server/migrations/0026_mail_backup_source.sql +11 -0
- package/dist/server/migrations/0027_opposite_anthem.sql +6 -0
- package/dist/server/migrations/0028_stale_rogue.sql +18 -0
- package/dist/server/migrations/0029_bouncy_loners.sql +16 -0
- package/dist/server/migrations/0030_bright_darkstar.sql +6 -0
- package/dist/server/migrations/0031_conscious_catseye.sql +13 -0
- package/dist/server/migrations/0032_wet_mimic.sql +51 -0
- package/dist/server/migrations/0033_eminent_molly_hayes.sql +2 -0
- package/dist/server/migrations/meta/0000_snapshot.json +5110 -0
- package/dist/server/migrations/meta/0001_snapshot.json +5257 -0
- package/dist/server/migrations/meta/0002_snapshot.json +5279 -0
- package/dist/server/migrations/meta/0003_snapshot.json +5286 -0
- package/dist/server/migrations/meta/0004_snapshot.json +5286 -0
- package/dist/server/migrations/meta/0005_snapshot.json +5305 -0
- package/dist/server/migrations/meta/0006_snapshot.json +5311 -0
- package/dist/server/migrations/meta/0007_snapshot.json +5323 -0
- package/dist/server/migrations/meta/0016_snapshot.json +6345 -0
- package/dist/server/migrations/meta/0017_snapshot.json +6383 -0
- package/dist/server/migrations/meta/0018_snapshot.json +6390 -0
- package/dist/server/migrations/meta/0019_snapshot.json +6390 -0
- package/dist/server/migrations/meta/0020_snapshot.json +6497 -0
- package/dist/server/migrations/meta/0021_snapshot.json +6509 -0
- package/dist/server/migrations/meta/0022_snapshot.json +6509 -0
- package/dist/server/migrations/meta/0023_snapshot.json +6629 -0
- package/dist/server/migrations/meta/0024_snapshot.json +6641 -0
- package/dist/server/migrations/meta/0025_snapshot.json +6648 -0
- package/dist/server/migrations/meta/0026_snapshot.json +6750 -0
- package/dist/server/migrations/meta/0027_snapshot.json +6757 -0
- package/dist/server/migrations/meta/0028_snapshot.json +6895 -0
- package/dist/server/migrations/meta/0029_snapshot.json +7028 -0
- package/dist/server/migrations/meta/0030_snapshot.json +7066 -0
- package/dist/server/migrations/meta/0031_snapshot.json +7181 -0
- package/dist/server/migrations/meta/0032_snapshot.json +7570 -0
- package/dist/server/migrations/meta/0033_snapshot.json +7597 -0
- package/dist/server/migrations/meta/_journal.json +244 -0
- package/dist/server/pglite/pglite.data +0 -0
- package/dist/server/pglite/pglite.wasm +0 -0
- package/package.json +31 -33
- package/.env.example +0 -38
- package/.nvmrc +0 -1
- package/.prettierrc +0 -7
- package/CONTRIBUTING.md +0 -90
- package/LICENSE +0 -661
- package/README.md +0 -360
- package/apps/api/.env.example +0 -30
- package/apps/api/Dockerfile +0 -22
- package/apps/api/package.json +0 -41
- package/apps/api/src/app.ts +0 -69
- package/apps/api/src/config/env.ts +0 -113
- package/apps/api/src/config/index.ts +0 -1
- package/apps/api/src/index.ts +0 -8
- package/apps/api/src/lib/auth-mode.ts +0 -42
- package/apps/api/src/lib/auth.ts +0 -105
- package/apps/api/src/lib/cache.ts +0 -128
- package/apps/api/src/lib/cloud-auth-proxy.ts +0 -310
- package/apps/api/src/lib/cloud-client.ts +0 -103
- package/apps/api/src/lib/compose-parser.ts +0 -138
- package/apps/api/src/lib/controller-helpers.ts +0 -90
- package/apps/api/src/lib/email-templates.ts +0 -94
- package/apps/api/src/lib/encryption.ts +0 -102
- package/apps/api/src/lib/local-user.ts +0 -65
- package/apps/api/src/lib/mail.ts +0 -48
- package/apps/api/src/lib/notifications.ts +0 -195
- package/apps/api/src/lib/openship-cloud.ts +0 -101
- package/apps/api/src/lib/resources.ts +0 -96
- package/apps/api/src/lib/screenshots.ts +0 -189
- package/apps/api/src/lib/ssh-manager.ts +0 -369
- package/apps/api/src/lib/ssl-scheduler.ts +0 -109
- package/apps/api/src/lib/stack-detector.ts +0 -708
- package/apps/api/src/lib/system-debug.ts +0 -10
- package/apps/api/src/middleware/auth.ts +0 -60
- package/apps/api/src/middleware/error-handler.ts +0 -41
- package/apps/api/src/middleware/index.ts +0 -5
- package/apps/api/src/middleware/internal-auth.ts +0 -40
- package/apps/api/src/middleware/local-only.ts +0 -20
- package/apps/api/src/middleware/rate-limiter.ts +0 -35
- package/apps/api/src/modules/analytics/analytics.controller.ts +0 -111
- package/apps/api/src/modules/analytics/analytics.routes.ts +0 -29
- package/apps/api/src/modules/analytics/analytics.schema.ts +0 -37
- package/apps/api/src/modules/analytics/analytics.service.ts +0 -264
- package/apps/api/src/modules/auth/auth.routes.ts +0 -237
- package/apps/api/src/modules/billing/billing.controller.ts +0 -60
- package/apps/api/src/modules/billing/billing.routes.ts +0 -34
- package/apps/api/src/modules/billing/billing.schema.ts +0 -9
- package/apps/api/src/modules/billing/billing.service.ts +0 -33
- package/apps/api/src/modules/cloud/cloud.controller.ts +0 -225
- package/apps/api/src/modules/cloud/cloud.routes.ts +0 -40
- package/apps/api/src/modules/deployments/build.service.ts +0 -791
- package/apps/api/src/modules/deployments/deployment-lifecycle.ts +0 -138
- package/apps/api/src/modules/deployments/deployment.controller.ts +0 -343
- package/apps/api/src/modules/deployments/deployment.routes.ts +0 -37
- package/apps/api/src/modules/deployments/deployment.schema.ts +0 -39
- package/apps/api/src/modules/deployments/deployment.service.ts +0 -190
- package/apps/api/src/modules/deployments/preflight.ts +0 -280
- package/apps/api/src/modules/deployments/prepare.service.ts +0 -252
- package/apps/api/src/modules/deployments/session-manager.ts +0 -283
- package/apps/api/src/modules/deployments/ssl.service.ts +0 -73
- package/apps/api/src/modules/domains/domain.controller.ts +0 -73
- package/apps/api/src/modules/domains/domain.routes.ts +0 -24
- package/apps/api/src/modules/domains/domain.schema.ts +0 -35
- package/apps/api/src/modules/domains/domain.service.ts +0 -385
- package/apps/api/src/modules/github/github.auth.ts +0 -397
- package/apps/api/src/modules/github/github.controller.ts +0 -387
- package/apps/api/src/modules/github/github.local-auth.ts +0 -251
- package/apps/api/src/modules/github/github.routes.ts +0 -50
- package/apps/api/src/modules/github/github.schema.ts +0 -52
- package/apps/api/src/modules/github/github.service.ts +0 -592
- package/apps/api/src/modules/github/github.types.ts +0 -158
- package/apps/api/src/modules/github/github.webhook.ts +0 -186
- package/apps/api/src/modules/github/index.ts +0 -16
- package/apps/api/src/modules/health/health.routes.ts +0 -45
- package/apps/api/src/modules/projects/project.controller.ts +0 -498
- package/apps/api/src/modules/projects/project.routes.ts +0 -67
- package/apps/api/src/modules/projects/project.schema.ts +0 -107
- package/apps/api/src/modules/projects/project.service.ts +0 -514
- package/apps/api/src/modules/settings/settings.controller.ts +0 -55
- package/apps/api/src/modules/settings/settings.routes.ts +0 -25
- package/apps/api/src/modules/settings/settings.service.ts +0 -49
- package/apps/api/src/modules/system/filesystem.controller.ts +0 -66
- package/apps/api/src/modules/system/index.ts +0 -1
- package/apps/api/src/modules/system/server-check.controller.ts +0 -475
- package/apps/api/src/modules/system/setup-session.ts +0 -255
- package/apps/api/src/modules/system/setup.controller.ts +0 -128
- package/apps/api/src/modules/system/system.routes.ts +0 -42
- package/apps/api/src/modules/webhooks/webhook.controller.ts +0 -64
- package/apps/api/src/modules/webhooks/webhook.routes.ts +0 -15
- package/apps/api/src/modules/webhooks/webhook.service.ts +0 -52
- package/apps/api/src/modules/webhooks/webhook.types.ts +0 -35
- package/apps/api/tsconfig.json +0 -14
- package/apps/cli/package.json +0 -26
- package/apps/cli/src/commands/deploy.ts +0 -11
- package/apps/cli/src/commands/init.ts +0 -8
- package/apps/cli/src/commands/login.ts +0 -8
- package/apps/cli/src/commands/logs.ts +0 -9
- package/apps/cli/src/index.ts +0 -21
- package/apps/cli/src/lib/api-client.ts +0 -35
- package/apps/cli/tsconfig.json +0 -13
- package/apps/dashboard/Dockerfile +0 -22
- package/apps/dashboard/components.json +0 -20
- package/apps/dashboard/next-env.d.ts +0 -6
- package/apps/dashboard/next.config.mjs +0 -16
- package/apps/dashboard/package.json +0 -40
- package/apps/dashboard/postcss.config.mjs +0 -5
- 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 +0 -19
- package/apps/dashboard/src/app/(auth)/forgot-password/page.tsx +0 -114
- package/apps/dashboard/src/app/(auth)/layout.tsx +0 -21
- package/apps/dashboard/src/app/(auth)/login/page.tsx +0 -220
- package/apps/dashboard/src/app/(auth)/providers.tsx +0 -34
- package/apps/dashboard/src/app/(auth)/register/page.tsx +0 -176
- package/apps/dashboard/src/app/(auth)/reset-password/page.tsx +0 -172
- package/apps/dashboard/src/app/(auth)/verify-email/page.tsx +0 -190
- package/apps/dashboard/src/app/(dashboard)/(deployment)/build/[id]/page.tsx +0 -162
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/BuildSummary.tsx +0 -166
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/DnsConfiguration.tsx +0 -119
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/DomainSettings.tsx +0 -291
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/Header.tsx +0 -71
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/Sidebar.tsx +0 -270
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/SkeletonLoader.tsx +0 -87
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/page.tsx +0 -169
- package/apps/dashboard/src/app/(dashboard)/(deployment)/layout.tsx +0 -7
- package/apps/dashboard/src/app/(dashboard)/billing/page.tsx +0 -3
- package/apps/dashboard/src/app/(dashboard)/deployments/components/CommitDetailsModal.tsx +0 -240
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentCard.tsx +0 -121
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentHeader.tsx +0 -89
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentMenu.tsx +0 -182
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsContent.tsx +0 -324
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsFilters.tsx +0 -99
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsList.tsx +0 -31
- package/apps/dashboard/src/app/(dashboard)/deployments/components/EmptyState.tsx +0 -101
- package/apps/dashboard/src/app/(dashboard)/deployments/components/LoadingSkeleton.tsx +0 -57
- package/apps/dashboard/src/app/(dashboard)/deployments/components/ProjectFilter.tsx +0 -109
- package/apps/dashboard/src/app/(dashboard)/deployments/components/index.ts +0 -9
- package/apps/dashboard/src/app/(dashboard)/deployments/page.tsx +0 -14
- package/apps/dashboard/src/app/(dashboard)/deployments/types.ts +0 -44
- package/apps/dashboard/src/app/(dashboard)/deployments/utils.ts +0 -176
- package/apps/dashboard/src/app/(dashboard)/domains/page.tsx +0 -3
- package/apps/dashboard/src/app/(dashboard)/integrations/page.tsx +0 -321
- package/apps/dashboard/src/app/(dashboard)/layout.tsx +0 -27
- package/apps/dashboard/src/app/(dashboard)/library/components/ConnectPrompt.tsx +0 -187
- package/apps/dashboard/src/app/(dashboard)/library/components/LibrarySidebar.tsx +0 -147
- package/apps/dashboard/src/app/(dashboard)/library/components/LoadingSkeleton.tsx +0 -39
- package/apps/dashboard/src/app/(dashboard)/library/components/LocalProjects.tsx +0 -548
- package/apps/dashboard/src/app/(dashboard)/library/components/RepositoryList.tsx +0 -292
- package/apps/dashboard/src/app/(dashboard)/library/components/TemplateGrid.tsx +0 -36
- package/apps/dashboard/src/app/(dashboard)/library/components/UrlImport.tsx +0 -74
- package/apps/dashboard/src/app/(dashboard)/library/page.tsx +0 -121
- package/apps/dashboard/src/app/(dashboard)/library/types.ts +0 -26
- package/apps/dashboard/src/app/(dashboard)/monitoring/page.tsx +0 -3
- package/apps/dashboard/src/app/(dashboard)/page.tsx +0 -485
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/[[...slug]]/layout.tsx +0 -22
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/[[...slug]]/page.tsx +0 -286
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/AdvancedSettings.tsx +0 -235
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/BuildSettings.tsx +0 -174
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DeleteConfirmationDialog.tsx +0 -45
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DeletionModal.tsx +0 -95
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/Deployments.tsx +0 -11
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DomainSettings.tsx +0 -523
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/EnvironmentSettings.tsx +0 -246
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GeneralSettings.tsx +0 -93
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GitInfo.tsx +0 -261
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GitSettings.tsx +0 -391
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/LogsSettings.tsx +0 -133
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ProjectNotFound.tsx +0 -95
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ProjectsBottomNavigation.tsx +0 -62
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ResourceSettings.tsx +0 -333
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SettingSection.tsx +0 -66
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SettingsNavigation.tsx +0 -27
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SleepModeSettings.tsx +0 -134
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProductionUrl.tsx +0 -25
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProjectIdentity.tsx +0 -159
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProjectInfo.tsx +0 -58
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/SkeletonLoader.tsx +0 -170
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/StatsCards.tsx +0 -33
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/TopPaths.tsx +0 -56
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/TrafficChart.tsx +0 -157
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/index.ts +0 -14
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/LogsActions.tsx +0 -52
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/ServerLogs.tsx +0 -249
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/TerminalLogs.tsx +0 -682
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/logs.css +0 -127
- package/apps/dashboard/src/app/(dashboard)/projects/components/DeploymentCard.tsx +0 -73
- package/apps/dashboard/src/app/(dashboard)/projects/components/ProjectCard.tsx +0 -330
- package/apps/dashboard/src/app/(dashboard)/projects/page.tsx +0 -330
- package/apps/dashboard/src/app/(dashboard)/providers.tsx +0 -23
- package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/components-tab.tsx +0 -329
- package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/overview-tab.tsx +0 -229
- package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/terminal-tab.tsx +0 -38
- package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/page.tsx +0 -437
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/checking-state.tsx +0 -15
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/choose-mode.tsx +0 -54
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/component-row.tsx +0 -65
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/error-banner.tsx +0 -13
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/installing-panel.tsx +0 -227
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/results-panel.tsx +0 -90
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/setup-header.tsx +0 -56
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/types.ts +0 -13
- package/apps/dashboard/src/app/(dashboard)/servers/new/page.tsx +0 -666
- package/apps/dashboard/src/app/(dashboard)/servers/page.tsx +0 -283
- package/apps/dashboard/src/app/(dashboard)/settings/_components/BuildPreferences.tsx +0 -110
- package/apps/dashboard/src/app/(dashboard)/settings/_components/CloudConnection.tsx +0 -147
- package/apps/dashboard/src/app/(dashboard)/settings/_components/InstanceInfo.tsx +0 -54
- package/apps/dashboard/src/app/(dashboard)/settings/_components/ServerConnection.tsx +0 -407
- package/apps/dashboard/src/app/(dashboard)/settings/_components/SettingsSection.tsx +0 -32
- package/apps/dashboard/src/app/(dashboard)/settings/page.tsx +0 -67
- package/apps/dashboard/src/app/auth/callback/close/page.tsx +0 -23
- package/apps/dashboard/src/app/auth/callback/install/page.tsx +0 -40
- package/apps/dashboard/src/app/authorize/page.tsx +0 -137
- package/apps/dashboard/src/app/globals.css +0 -57
- package/apps/dashboard/src/app/layout.tsx +0 -55
- package/apps/dashboard/src/components/auth-shell.tsx +0 -66
- package/apps/dashboard/src/components/deployments/types.ts +0 -44
- package/apps/dashboard/src/components/global-deployments/index.ts +0 -17
- package/apps/dashboard/src/components/i18n-provider.tsx +0 -100
- package/apps/dashboard/src/components/import-project/BuildSettings.tsx +0 -376
- package/apps/dashboard/src/components/import-project/BuildSkeleton.tsx +0 -161
- package/apps/dashboard/src/components/import-project/BuildTerminal.tsx +0 -358
- package/apps/dashboard/src/components/import-project/ComposeServices.tsx +0 -455
- package/apps/dashboard/src/components/import-project/DeploymentProcessing.tsx +0 -510
- package/apps/dashboard/src/components/import-project/DockerSettings.tsx +0 -64
- package/apps/dashboard/src/components/import-project/EnvironmentVariables.tsx +0 -481
- package/apps/dashboard/src/components/import-project/Frameworks.tsx +0 -90
- package/apps/dashboard/src/components/import-project/ProjectSettings.tsx +0 -160
- package/apps/dashboard/src/components/import-project/types.ts +0 -82
- package/apps/dashboard/src/components/integrations/GithubPermissionModal.tsx +0 -173
- package/apps/dashboard/src/components/language-switcher.tsx +0 -36
- package/apps/dashboard/src/components/logo.tsx +0 -13
- package/apps/dashboard/src/components/network-error-handler.tsx +0 -27
- package/apps/dashboard/src/components/oauth-buttons.tsx +0 -81
- package/apps/dashboard/src/components/overview/ActivityChart.tsx +0 -247
- package/apps/dashboard/src/components/overview/ApiRequestsCard.tsx +0 -111
- package/apps/dashboard/src/components/overview/CreditsCard.tsx +0 -137
- package/apps/dashboard/src/components/overview/DeploymentsChart.tsx +0 -195
- package/apps/dashboard/src/components/overview/EmptyState.tsx +0 -126
- package/apps/dashboard/src/components/overview/LoadingSkeleton.tsx +0 -92
- package/apps/dashboard/src/components/overview/OverviewHeader.tsx +0 -74
- package/apps/dashboard/src/components/overview/OverviewHeroChart.tsx +0 -344
- package/apps/dashboard/src/components/overview/ProjectsCard.tsx +0 -134
- package/apps/dashboard/src/components/overview/QuickLinks.tsx +0 -119
- package/apps/dashboard/src/components/overview/SandboxesCard.tsx +0 -150
- package/apps/dashboard/src/components/overview/StatsGrid.tsx +0 -166
- package/apps/dashboard/src/components/overview/TokenUsageChart.tsx +0 -206
- package/apps/dashboard/src/components/overview/UsageStats.tsx +0 -79
- package/apps/dashboard/src/components/overview/index.ts +0 -30
- package/apps/dashboard/src/components/overview/types.ts +0 -116
- package/apps/dashboard/src/components/page-header.tsx +0 -25
- package/apps/dashboard/src/components/project-settings/ServerSideSwitch.jsx +0 -60
- package/apps/dashboard/src/components/shared/AlertBox.tsx +0 -39
- package/apps/dashboard/src/components/shared/CTASection.tsx +0 -45
- package/apps/dashboard/src/components/shared/ErrorState.tsx +0 -176
- package/apps/dashboard/src/components/shared/FeatureCard.tsx +0 -20
- package/apps/dashboard/src/components/shared/MDXComponents.tsx +0 -24
- package/apps/dashboard/src/components/shared/MachineSettingsModal.tsx +0 -286
- package/apps/dashboard/src/components/shared/Modal.tsx +0 -39
- package/apps/dashboard/src/components/shared/OTPInput.tsx +0 -122
- package/apps/dashboard/src/components/shared/PageHero.tsx +0 -21
- package/apps/dashboard/src/components/shared/PlatformFeatureCard.tsx +0 -27
- package/apps/dashboard/src/components/shared/StatCard.tsx +0 -14
- package/apps/dashboard/src/components/shared/ValueCard.tsx +0 -20
- package/apps/dashboard/src/components/shared/index.ts +0 -8
- package/apps/dashboard/src/components/sidebar.tsx +0 -282
- package/apps/dashboard/src/components/theme-provider.tsx +0 -96
- package/apps/dashboard/src/components/toast.tsx +0 -106
- package/apps/dashboard/src/components/ui/CustomCursor.tsx +0 -107
- package/apps/dashboard/src/components/ui/CustomSelect.tsx +0 -126
- package/apps/dashboard/src/components/ui/DropdownMenu.tsx +0 -174
- package/apps/dashboard/src/components/ui/FileIcon.jsx +0 -59
- package/apps/dashboard/src/components/ui/IconPickerModal.tsx +0 -273
- package/apps/dashboard/src/components/ui/InfoBanner.jsx +0 -39
- package/apps/dashboard/src/components/ui/Logo.tsx +0 -14
- package/apps/dashboard/src/components/ui/Modal.tsx +0 -117
- package/apps/dashboard/src/components/ui/PageContainer.tsx +0 -12
- package/apps/dashboard/src/components/ui/SectionContainer.jsx +0 -7
- package/apps/dashboard/src/components/ui/SlidingToggle.tsx +0 -128
- package/apps/dashboard/src/components/ui/Toast.tsx +0 -29
- package/apps/dashboard/src/components/ui/button.tsx +0 -58
- package/apps/dashboard/src/components/ui/card.tsx +0 -60
- package/apps/dashboard/src/components/ui/input.tsx +0 -20
- package/apps/dashboard/src/components/ui/label.tsx +0 -19
- package/apps/dashboard/src/components/ui/select.tsx +0 -10
- package/apps/dashboard/src/components/ui/textarea.tsx +0 -9
- package/apps/dashboard/src/constants/lang-colors.ts +0 -25
- package/apps/dashboard/src/constants/mock.ts +0 -38
- package/apps/dashboard/src/context/AuthContext.tsx +0 -91
- package/apps/dashboard/src/context/CloudContext.tsx +0 -275
- package/apps/dashboard/src/context/DeploymentContext.tsx +0 -71
- package/apps/dashboard/src/context/GitHubContext.tsx +0 -288
- package/apps/dashboard/src/context/ModalContext.tsx +0 -300
- package/apps/dashboard/src/context/NetworkContext.tsx +0 -32
- package/apps/dashboard/src/context/ProjectSettingsContext.tsx +0 -727
- package/apps/dashboard/src/context/ToastContext.tsx +0 -129
- package/apps/dashboard/src/context/deployment/index.ts +0 -3
- package/apps/dashboard/src/context/deployment/types.ts +0 -183
- package/apps/dashboard/src/context/deployment/useDeploymentBuild.ts +0 -547
- package/apps/dashboard/src/context/deployment/useDeploymentConfig.ts +0 -176
- package/apps/dashboard/src/hooks/useBuildConnection.ts +0 -334
- package/apps/dashboard/src/hooks/useMonitorStream.ts +0 -146
- package/apps/dashboard/src/hooks/useProjectData.ts +0 -110
- package/apps/dashboard/src/hooks/useSSEConnection.ts +0 -465
- package/apps/dashboard/src/hooks/useSSEStream.ts +0 -309
- package/apps/dashboard/src/hooks/useSessions.ts +0 -104
- package/apps/dashboard/src/hooks/useSetupStream.ts +0 -223
- package/apps/dashboard/src/i18n/dictionaries/ar.json +0 -218
- package/apps/dashboard/src/i18n/dictionaries/en.json +0 -218
- package/apps/dashboard/src/i18n/index.ts +0 -16
- package/apps/dashboard/src/lib/api/ai.ts +0 -22
- package/apps/dashboard/src/lib/api/auth.ts +0 -13
- package/apps/dashboard/src/lib/api/client.ts +0 -199
- package/apps/dashboard/src/lib/api/cloud.ts +0 -15
- package/apps/dashboard/src/lib/api/deploy.ts +0 -58
- package/apps/dashboard/src/lib/api/domains.ts +0 -13
- package/apps/dashboard/src/lib/api/endpoints.ts +0 -129
- package/apps/dashboard/src/lib/api/github.ts +0 -31
- package/apps/dashboard/src/lib/api/icons.ts +0 -12
- package/apps/dashboard/src/lib/api/index.ts +0 -41
- package/apps/dashboard/src/lib/api/projects.ts +0 -153
- package/apps/dashboard/src/lib/api/sandbox.ts +0 -14
- package/apps/dashboard/src/lib/api/settings.ts +0 -21
- package/apps/dashboard/src/lib/api/system.ts +0 -159
- package/apps/dashboard/src/lib/auth-client.ts +0 -54
- package/apps/dashboard/src/lib/country.ts +0 -25
- package/apps/dashboard/src/lib/server/api.ts +0 -140
- package/apps/dashboard/src/lib/server/session.ts +0 -103
- package/apps/dashboard/src/lib/sseClient.ts +0 -241
- package/apps/dashboard/src/lib/sseMessageProcessors.ts +0 -323
- package/apps/dashboard/src/lib/utils.ts +0 -6
- package/apps/dashboard/src/proxy.ts +0 -46
- package/apps/dashboard/src/styles/Toast.module.css +0 -92
- package/apps/dashboard/src/styles/fonts.css +0 -93
- package/apps/dashboard/src/styles/theme.css +0 -336
- package/apps/dashboard/src/types/research.ts +0 -42
- package/apps/dashboard/src/utils/SSEParser.js +0 -150
- package/apps/dashboard/src/utils/authWindow.ts +0 -143
- package/apps/dashboard/src/utils/codeTheme.ts +0 -127
- package/apps/dashboard/src/utils/colors.json +0 -2810
- package/apps/dashboard/src/utils/date.ts +0 -121
- package/apps/dashboard/src/utils/deployment.ts +0 -128
- package/apps/dashboard/src/utils/deploymentPhaseDetector.ts +0 -232
- package/apps/dashboard/src/utils/extToLang.js +0 -103
- package/apps/dashboard/src/utils/github.ts +0 -62
- package/apps/dashboard/src/utils/icons.js +0 -46
- package/apps/dashboard/src/utils/repoSlug.ts +0 -110
- package/apps/dashboard/src/utils/research-api.ts +0 -163
- package/apps/dashboard/src/utils/suggestions.ts +0 -84
- package/apps/dashboard/src/utils/theme.js +0 -1
- package/apps/dashboard/src/utils/ui-helpers.tsx +0 -30
- package/apps/dashboard/src/utils/upload.js +0 -12
- package/apps/dashboard/tsconfig.json +0 -33
- package/apps/desktop/forge.config.json +0 -36
- package/apps/desktop/package.json +0 -26
- package/apps/desktop/scripts/dev.mjs +0 -58
- package/apps/desktop/src/main/index.ts +0 -675
- package/apps/desktop/src/main/types/desktop.d.ts +0 -33
- package/apps/desktop/src/preload/index.ts +0 -88
- package/apps/desktop/src/renderer/index.html +0 -462
- package/apps/desktop/src/renderer/onboarding.js +0 -511
- package/apps/desktop/src/renderer/styles.css +0 -1139
- package/apps/desktop/tsconfig.json +0 -17
- package/apps/web/.source/browser.ts +0 -13
- package/apps/web/.source/dynamic.ts +0 -8
- package/apps/web/.source/server.ts +0 -22
- package/apps/web/.source/source.config.mjs +0 -20
- package/apps/web/Dockerfile +0 -22
- package/apps/web/content/blog/how-ai-builds-work.mdx +0 -55
- package/apps/web/content/blog/introducing-openship.mdx +0 -46
- package/apps/web/content/blog/self-hosting-cost-breakdown.mdx +0 -59
- package/apps/web/content/docs/_meta.json +0 -14
- package/apps/web/content/docs/api.mdx +0 -98
- package/apps/web/content/docs/cli.mdx +0 -80
- package/apps/web/content/docs/first-deployment.mdx +0 -56
- package/apps/web/content/docs/index.mdx +0 -27
- package/apps/web/content/docs/installation.mdx +0 -65
- package/apps/web/content/docs/quickstart.mdx +0 -45
- package/apps/web/next-env.d.ts +0 -6
- package/apps/web/next.config.mjs +0 -20
- package/apps/web/package.json +0 -33
- package/apps/web/postcss.config.mjs +0 -5
- 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 +0 -1
- package/apps/web/source.config.ts +0 -17
- package/apps/web/src/app/(marketing)/layout.tsx +0 -9
- package/apps/web/src/app/(marketing)/page.tsx +0 -2
- package/apps/web/src/app/(marketing)/pricing/page.tsx +0 -10
- package/apps/web/src/app/blog/[...slug]/page.tsx +0 -247
- package/apps/web/src/app/blog/blog.css +0 -575
- package/apps/web/src/app/blog/layout.tsx +0 -50
- package/apps/web/src/app/blog/page.tsx +0 -235
- package/apps/web/src/app/docs/[[...slug]]/page.tsx +0 -67
- package/apps/web/src/app/docs/layout.tsx +0 -62
- package/apps/web/src/app/docs/toc-theme.css +0 -71
- package/apps/web/src/app/download/page.tsx +0 -396
- package/apps/web/src/app/globals.css +0 -20
- package/apps/web/src/app/layout.tsx +0 -70
- package/apps/web/src/app/page.tsx +0 -51
- package/apps/web/src/app/robots.ts +0 -15
- package/apps/web/src/app/sitemap.ts +0 -35
- package/apps/web/src/components/blog/share-sidebar.tsx +0 -81
- package/apps/web/src/components/blog/writer-sidebar.tsx +0 -81
- package/apps/web/src/components/landing/ai-native.tsx +0 -169
- package/apps/web/src/components/landing/backups.tsx +0 -139
- package/apps/web/src/components/landing/cdn.tsx +0 -109
- package/apps/web/src/components/landing/coming-soon.tsx +0 -180
- package/apps/web/src/components/landing/dark-section.tsx +0 -166
- package/apps/web/src/components/landing/dashboard.tsx +0 -407
- package/apps/web/src/components/landing/developer-experience.tsx +0 -224
- package/apps/web/src/components/landing/dns-domains.tsx +0 -146
- package/apps/web/src/components/landing/download-button.tsx +0 -151
- package/apps/web/src/components/landing/features/ai-visual.tsx +0 -48
- package/apps/web/src/components/landing/features/cloud-visual.tsx +0 -44
- package/apps/web/src/components/landing/features/git-visual.tsx +0 -61
- package/apps/web/src/components/landing/features/index.tsx +0 -642
- package/apps/web/src/components/landing/features/infra-visual.tsx +0 -69
- package/apps/web/src/components/landing/features/rollback-visual.tsx +0 -42
- package/apps/web/src/components/landing/features/ssl-visual.tsx +0 -41
- package/apps/web/src/components/landing/features/stacks-visual.tsx +0 -54
- package/apps/web/src/components/landing/final-cta.tsx +0 -116
- package/apps/web/src/components/landing/footer.tsx +0 -145
- package/apps/web/src/components/landing/hero.tsx +0 -110
- package/apps/web/src/components/landing/how-it-works.tsx +0 -210
- package/apps/web/src/components/landing/index.ts +0 -21
- package/apps/web/src/components/landing/mail-server.tsx +0 -122
- package/apps/web/src/components/landing/navbar.tsx +0 -199
- package/apps/web/src/components/landing/no-lockin.tsx +0 -185
- package/apps/web/src/components/landing/open-source-cta.tsx +0 -151
- package/apps/web/src/components/landing/portability.tsx +0 -190
- package/apps/web/src/components/landing/pricing.tsx +0 -263
- package/apps/web/src/components/landing/scaling.tsx +0 -209
- package/apps/web/src/components/landing/why-openship.tsx +0 -291
- package/apps/web/src/hooks/use-gsap-scroll.ts +0 -158
- package/apps/web/src/hooks/use-platform.ts +0 -86
- package/apps/web/src/lib/source.ts +0 -12
- package/apps/web/src/styles/fonts.css +0 -84
- package/apps/web/src/styles/landing.css +0 -951
- package/apps/web/src/styles/theme.css +0 -227
- package/apps/web/tsconfig.json +0 -16
- package/bun.lock +0 -3260
- package/docker-compose.yml +0 -90
- package/docs/screenshots/.gitkeep +0 -0
- package/docs/screenshots/screen.png +0 -0
- package/openship.code-workspace +0 -7
- package/packages/adapters/docs/ARCHITECTURE.md +0 -160
- package/packages/adapters/docs/BUILD-PIPELINE.md +0 -171
- package/packages/adapters/docs/CLOUD.md +0 -239
- package/packages/adapters/docs/EXECUTOR.md +0 -174
- package/packages/adapters/docs/LOG-STREAMING.md +0 -175
- package/packages/adapters/docs/SYSTEM.md +0 -191
- package/packages/adapters/package.json +0 -32
- package/packages/adapters/src/index.ts +0 -144
- package/packages/adapters/src/infra/cloud.ts +0 -42
- package/packages/adapters/src/infra/index.ts +0 -9
- package/packages/adapters/src/infra/noop.ts +0 -27
- package/packages/adapters/src/infra/traefik.ts +0 -297
- package/packages/adapters/src/infra/types.ts +0 -36
- package/packages/adapters/src/platform.ts +0 -255
- package/packages/adapters/src/runtime/bare.ts +0 -567
- package/packages/adapters/src/runtime/build-pipeline.ts +0 -237
- package/packages/adapters/src/runtime/cloud.ts +0 -791
- package/packages/adapters/src/runtime/deploy-pipeline.ts +0 -146
- package/packages/adapters/src/runtime/docker.ts +0 -443
- package/packages/adapters/src/runtime/index.ts +0 -69
- package/packages/adapters/src/runtime/local-build.ts +0 -112
- package/packages/adapters/src/runtime/transfer.ts +0 -82
- package/packages/adapters/src/runtime/types.ts +0 -138
- package/packages/adapters/src/system/catalog.ts +0 -188
- package/packages/adapters/src/system/checks.ts +0 -228
- package/packages/adapters/src/system/components.ts +0 -45
- package/packages/adapters/src/system/debug.ts +0 -18
- package/packages/adapters/src/system/environment.ts +0 -168
- package/packages/adapters/src/system/errors.ts +0 -34
- package/packages/adapters/src/system/executor.ts +0 -600
- package/packages/adapters/src/system/index.ts +0 -58
- package/packages/adapters/src/system/installer.ts +0 -310
- package/packages/adapters/src/system/setup.ts +0 -442
- package/packages/adapters/src/system/state.ts +0 -96
- package/packages/adapters/src/system/types.ts +0 -116
- package/packages/adapters/src/toolchain/catalog.ts +0 -439
- package/packages/adapters/src/toolchain/checks.ts +0 -181
- package/packages/adapters/src/toolchain/index.ts +0 -38
- package/packages/adapters/src/toolchain/installer.ts +0 -189
- package/packages/adapters/src/toolchain/types.ts +0 -84
- package/packages/adapters/src/types.ts +0 -277
- package/packages/adapters/tsconfig.json +0 -11
- package/packages/core/package.json +0 -27
- package/packages/core/src/constants.ts +0 -71
- package/packages/core/src/errors.ts +0 -49
- package/packages/core/src/index.ts +0 -6
- package/packages/core/src/stacks.ts +0 -778
- package/packages/core/src/system.ts +0 -111
- package/packages/core/src/types.ts +0 -68
- package/packages/core/src/utils.ts +0 -43
- package/packages/core/tsconfig.json +0 -11
- package/packages/db/drizzle/0000_init.sql +0 -231
- package/packages/db/drizzle/0001_add_server_name.sql +0 -1
- package/packages/db/drizzle/meta/_journal.json +0 -20
- package/packages/db/drizzle.config.ts +0 -10
- package/packages/db/package.json +0 -44
- package/packages/db/src/client.ts +0 -119
- package/packages/db/src/index.ts +0 -60
- package/packages/db/src/repos/account.repo.ts +0 -92
- package/packages/db/src/repos/deployment.repo.ts +0 -168
- package/packages/db/src/repos/domain.repo.ts +0 -102
- package/packages/db/src/repos/git-installation.repo.ts +0 -95
- package/packages/db/src/repos/index.ts +0 -43
- package/packages/db/src/repos/instance-settings.repo.ts +0 -43
- package/packages/db/src/repos/project.repo.ts +0 -159
- package/packages/db/src/repos/session.repo.ts +0 -82
- package/packages/db/src/repos/settings.repo.ts +0 -51
- package/packages/db/src/repos/user.repo.ts +0 -94
- package/packages/db/src/schema/auth.ts +0 -56
- package/packages/db/src/schema/deployment.ts +0 -87
- package/packages/db/src/schema/domain.ts +0 -46
- package/packages/db/src/schema/github.ts +0 -24
- package/packages/db/src/schema/index.ts +0 -6
- package/packages/db/src/schema/project.ts +0 -117
- package/packages/db/src/schema/settings.ts +0 -103
- package/packages/db/tsconfig.json +0 -11
- package/packages/ui/package.json +0 -38
- package/packages/ui/src/components/badge.tsx +0 -29
- package/packages/ui/src/components/button.tsx +0 -44
- package/packages/ui/src/components/card.tsx +0 -26
- package/packages/ui/src/components/status-dot.tsx +0 -25
- package/packages/ui/src/globals.css +0 -18
- package/packages/ui/src/index.tsx +0 -8
- package/packages/ui/src/lib/cn.ts +0 -7
- package/packages/ui/tsconfig.json +0 -14
- package/pnpm-workspace.yaml +0 -3
- package/tsconfig.base.json +0 -18
- package/turbo.json +0 -36
|
@@ -1,791 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cloud runtime — delegates build/deploy to Oblien cloud infrastructure.
|
|
3
|
-
*
|
|
4
|
-
* Strategy: single workspace per deployment.
|
|
5
|
-
* 1. Build: create temp workspace (high resources) → shared pipeline (clone → install → build)
|
|
6
|
-
* 2. Deploy: makePermanent → resize down → create workload → expose port
|
|
7
|
-
* 3. Redeploy: new workspace, build, swap routing, delete old
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { Oblien } from "oblien";
|
|
11
|
-
import type { WorkspaceHandle } from "oblien";
|
|
12
|
-
import type { ExecStreamEvent } from "oblien";
|
|
13
|
-
|
|
14
|
-
import type {
|
|
15
|
-
BuildConfig,
|
|
16
|
-
DeployConfig,
|
|
17
|
-
BuildResult,
|
|
18
|
-
DeploymentResult,
|
|
19
|
-
LogEntry,
|
|
20
|
-
LogCallback,
|
|
21
|
-
ContainerInfo,
|
|
22
|
-
ResourceUsage,
|
|
23
|
-
ContainerStatus,
|
|
24
|
-
} from "../types";
|
|
25
|
-
|
|
26
|
-
import type { RuntimeAdapter, RuntimeCapability } from "./types";
|
|
27
|
-
import { BuildLogger, runBuildPipeline, type BuildEnvironment } from "./build-pipeline";
|
|
28
|
-
import { runLocalBuild } from "./local-build";
|
|
29
|
-
import { transferLocalDirectory } from "./transfer";
|
|
30
|
-
|
|
31
|
-
function now(): string {
|
|
32
|
-
return new Date().toISOString();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// ─── CloudRuntime ────────────────────────────────────────────────────────────
|
|
36
|
-
|
|
37
|
-
export class CloudRuntime implements RuntimeAdapter {
|
|
38
|
-
readonly name = "cloud";
|
|
39
|
-
readonly capabilities: ReadonlySet<RuntimeCapability> = new Set<RuntimeCapability>([
|
|
40
|
-
"build",
|
|
41
|
-
"deploy",
|
|
42
|
-
"stop",
|
|
43
|
-
"start",
|
|
44
|
-
"restart",
|
|
45
|
-
"destroy",
|
|
46
|
-
"containerInfo",
|
|
47
|
-
"runtimeLogs",
|
|
48
|
-
"streamLogs",
|
|
49
|
-
"usage",
|
|
50
|
-
"containerIp",
|
|
51
|
-
]);
|
|
52
|
-
|
|
53
|
-
private readonly client: Oblien;
|
|
54
|
-
|
|
55
|
-
constructor(client: Oblien) {
|
|
56
|
-
this.client = client;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
supports(cap: RuntimeCapability): boolean {
|
|
60
|
-
return this.capabilities.has(cap);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async dispose(): Promise<void> {
|
|
64
|
-
// No persistent connections to clean up
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/** Get a scoped workspace handle. */
|
|
68
|
-
private ws(workspaceId: string): WorkspaceHandle {
|
|
69
|
-
return this.client.workspace(workspaceId);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// ── Build lifecycle ────────────────────────────────────────────────────
|
|
73
|
-
|
|
74
|
-
async build(config: BuildConfig, logger?: BuildLogger): Promise<BuildResult> {
|
|
75
|
-
const log = logger ?? new BuildLogger();
|
|
76
|
-
|
|
77
|
-
// "local" = build on the API host, then upload output to cloud workspace.
|
|
78
|
-
// "server" (default) = build inside the cloud workspace.
|
|
79
|
-
const buildLocally = config.buildStrategy === "local";
|
|
80
|
-
|
|
81
|
-
// 1. Provision workspace + acquire runtime token (logs to terminal)
|
|
82
|
-
let wsId: string;
|
|
83
|
-
let rt: Awaited<ReturnType<WorkspaceHandle["runtime"]>>;
|
|
84
|
-
try {
|
|
85
|
-
const provisioned = await this.provisionBuildWorkspace(config, log);
|
|
86
|
-
wsId = provisioned.workspaceId;
|
|
87
|
-
rt = provisioned.runtime;
|
|
88
|
-
} catch (err) {
|
|
89
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
90
|
-
log.log(`Failed to provision build environment: ${msg}`, "error");
|
|
91
|
-
return {
|
|
92
|
-
sessionId: config.sessionId,
|
|
93
|
-
status: "failed" as const,
|
|
94
|
-
durationMs: 0,
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (buildLocally) {
|
|
99
|
-
log.log("Build strategy: local (build on API host, upload to cloud)\n");
|
|
100
|
-
|
|
101
|
-
const result = await runLocalBuild({
|
|
102
|
-
config,
|
|
103
|
-
logger: log,
|
|
104
|
-
transferOutput: async (buildDir) => {
|
|
105
|
-
await transferLocalDirectory(
|
|
106
|
-
buildDir,
|
|
107
|
-
{
|
|
108
|
-
kind: "cloud-runtime",
|
|
109
|
-
runtime: rt,
|
|
110
|
-
path: "/app",
|
|
111
|
-
},
|
|
112
|
-
log,
|
|
113
|
-
{ excludes: [] },
|
|
114
|
-
);
|
|
115
|
-
},
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
return {
|
|
119
|
-
sessionId: config.sessionId,
|
|
120
|
-
status: result.status,
|
|
121
|
-
imageRef: wsId,
|
|
122
|
-
durationMs: result.durationMs,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// ── Server build: exec delegates to cloud runtime API ──
|
|
127
|
-
log.log("Build strategy: server (build in cloud workspace)\n");
|
|
128
|
-
|
|
129
|
-
const buildEnv: BuildEnvironment = {
|
|
130
|
-
projectDir: "/app",
|
|
131
|
-
hasNativeEnv: true,
|
|
132
|
-
exec: async (command, logCb) => {
|
|
133
|
-
await this.execAndStream(rt, ["sh", "-c", command], logCb);
|
|
134
|
-
},
|
|
135
|
-
preflight: async (cfg, plog) => {
|
|
136
|
-
if (!cfg.localPath) return;
|
|
137
|
-
await transferLocalDirectory(
|
|
138
|
-
cfg.localPath,
|
|
139
|
-
{
|
|
140
|
-
kind: "cloud-runtime",
|
|
141
|
-
runtime: rt,
|
|
142
|
-
path: "/app",
|
|
143
|
-
},
|
|
144
|
-
plog,
|
|
145
|
-
);
|
|
146
|
-
},
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
// 3. Run shared build pipeline (clone → install → build)
|
|
150
|
-
const result = await runBuildPipeline(buildEnv, config, log);
|
|
151
|
-
|
|
152
|
-
return {
|
|
153
|
-
sessionId: config.sessionId,
|
|
154
|
-
status: result.status,
|
|
155
|
-
imageRef: wsId,
|
|
156
|
-
durationMs: result.durationMs,
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Provision a temporary cloud workspace for a build.
|
|
162
|
-
*
|
|
163
|
-
* This is the cloud-specific "prepare" phase:
|
|
164
|
-
* 1. Create workspace (image + resources + env vars)
|
|
165
|
-
* 2. Set TTL for auto-cleanup
|
|
166
|
-
* 3. Acquire runtime token (enable API server + get JWT)
|
|
167
|
-
*
|
|
168
|
-
* Output streams to the terminal via logger so the user sees
|
|
169
|
-
* progress before the numbered build steps begin.
|
|
170
|
-
*/
|
|
171
|
-
private async provisionBuildWorkspace(
|
|
172
|
-
config: BuildConfig,
|
|
173
|
-
logger: BuildLogger,
|
|
174
|
-
): Promise<{ workspaceId: string; runtime: Awaited<ReturnType<WorkspaceHandle["runtime"]>> }> {
|
|
175
|
-
logger.log("Provisioning build environment...\n");
|
|
176
|
-
|
|
177
|
-
// Create temporary workspace with build resources
|
|
178
|
-
const envArray = Object.entries(config.envVars).map(
|
|
179
|
-
([k, v]) => `${k}=${v}`,
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
const wsData = await this.client.workspaces.create({
|
|
183
|
-
name: config.slug ?? `build-${config.projectId.slice(0, 20)}`,
|
|
184
|
-
image: config.buildImage,
|
|
185
|
-
mode: "temporary",
|
|
186
|
-
config: {
|
|
187
|
-
cpus: config.resources.cpuCores,
|
|
188
|
-
memory_mb: config.resources.memoryMb,
|
|
189
|
-
disk_size_mb: config.resources.diskMb,
|
|
190
|
-
env: envArray,
|
|
191
|
-
},
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
const ws = this.ws(wsData.id);
|
|
195
|
-
|
|
196
|
-
try {
|
|
197
|
-
// Set TTL via dedicated lifecycle API (config.ttl during create is unreliable)
|
|
198
|
-
try {
|
|
199
|
-
await ws.lifecycle.makeTemporary({ ttl: "15m", ttl_action: "remove", remove_on_exit: true });
|
|
200
|
-
} catch {
|
|
201
|
-
// TTL failure is non-fatal — workspace will be cleaned up eventually
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Acquire runtime handle (enables API server + gets JWT)
|
|
205
|
-
logger.log("Connecting to build environment...\n");
|
|
206
|
-
let rt: Awaited<ReturnType<WorkspaceHandle["runtime"]>> | undefined;
|
|
207
|
-
for (let attempt = 0; attempt < 3; attempt++) {
|
|
208
|
-
try {
|
|
209
|
-
rt = await ws.runtime();
|
|
210
|
-
break;
|
|
211
|
-
} catch (err) {
|
|
212
|
-
if (attempt < 2) {
|
|
213
|
-
await new Promise((r) => setTimeout(r, 2000));
|
|
214
|
-
} else {
|
|
215
|
-
throw err;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
if (!rt) throw new Error("Failed to connect to build environment");
|
|
220
|
-
|
|
221
|
-
logger.log("Build environment ready\n");
|
|
222
|
-
|
|
223
|
-
return { workspaceId: wsData.id, runtime: rt };
|
|
224
|
-
} catch (err) {
|
|
225
|
-
// Workspace was created but setup failed — clean it up
|
|
226
|
-
await ws.delete().catch(() => {});
|
|
227
|
-
throw err;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
async cancelBuild(sessionId: string): Promise<void> {
|
|
232
|
-
// The workspace ID is stored as imageRef — build.service.ts calls destroy() directly
|
|
233
|
-
void sessionId;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
async getBuildLogs(sessionId: string): Promise<LogEntry[]> {
|
|
237
|
-
// Build logs are streamed in real-time via onLog callback
|
|
238
|
-
// Historical logs are stored in the database by build.service.ts
|
|
239
|
-
void sessionId;
|
|
240
|
-
return [];
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// ── Deploy lifecycle ───────────────────────────────────────────────────
|
|
244
|
-
|
|
245
|
-
async deploy(config: DeployConfig, onLog?: LogCallback): Promise<DeploymentResult> {
|
|
246
|
-
const workspaceId = config.imageRef;
|
|
247
|
-
if (!workspaceId) {
|
|
248
|
-
return {
|
|
249
|
-
deploymentId: config.deploymentId,
|
|
250
|
-
status: "failed",
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
const ws = this.ws(workspaceId);
|
|
255
|
-
|
|
256
|
-
try {
|
|
257
|
-
// 1. Make workspace permanent (it was temporary during build)
|
|
258
|
-
await ws.lifecycle.makePermanent();
|
|
259
|
-
} catch (err) {
|
|
260
|
-
throw new Error(`Failed to make workspace permanent: ${err instanceof Error ? err.message : err}`);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// TODO: temporarily disabled — testing without resource shrink
|
|
264
|
-
// try {
|
|
265
|
-
// // 2. Resize CPU/memory to production levels
|
|
266
|
-
// // Disk is NOT resized down — VMs don't support disk shrink.
|
|
267
|
-
// // The build disk size carries over (harmless, just extra space).
|
|
268
|
-
// await ws.resources.update({
|
|
269
|
-
// cpus: config.resources.cpuCores,
|
|
270
|
-
// memory_mb: config.resources.memoryMb,
|
|
271
|
-
// apply: true,
|
|
272
|
-
// });
|
|
273
|
-
// } catch (err) {
|
|
274
|
-
// throw new Error(`Failed to resize workspace: ${err instanceof Error ? err.message : err}`);
|
|
275
|
-
// }
|
|
276
|
-
|
|
277
|
-
// 2. Prepare production directory — copy only what's needed at runtime
|
|
278
|
-
const prodPaths = config.productionPaths;
|
|
279
|
-
const workDir = prodPaths?.length ? "/app/production" : "/app";
|
|
280
|
-
|
|
281
|
-
if (prodPaths?.length) {
|
|
282
|
-
try {
|
|
283
|
-
const rt = await ws.runtime();
|
|
284
|
-
const logCb: LogCallback = onLog ?? (() => {});
|
|
285
|
-
|
|
286
|
-
// Sanitize paths — reject anything that could escape /app/
|
|
287
|
-
const safePaths = prodPaths.filter((p) => {
|
|
288
|
-
const normalized = p.replace(/\/+/g, "/").replace(/^\/|\/$/g, "");
|
|
289
|
-
return normalized.length > 0
|
|
290
|
-
&& normalized !== ".."
|
|
291
|
-
&& !normalized.startsWith("../")
|
|
292
|
-
&& !normalized.includes("/../")
|
|
293
|
-
&& !normalized.includes("\\");
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
if (safePaths.length === 0) {
|
|
297
|
-
throw new Error("No valid production paths after sanitization");
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// Shell-escape a string for use inside single quotes
|
|
301
|
-
const sq = (s: string) => s.replace(/'/g, "'\\''");
|
|
302
|
-
|
|
303
|
-
// Build an atomic shell script:
|
|
304
|
-
// 1. Create staging dir
|
|
305
|
-
// 2. Move each path (skip missing with warning)
|
|
306
|
-
// 3. Rename staging → production (atomic on same filesystem)
|
|
307
|
-
// 4. On any error, clean up staging dir
|
|
308
|
-
const moveLines = safePaths.map((p) => {
|
|
309
|
-
const e = sq(p);
|
|
310
|
-
return `if [ -e '/app/${e}' ]; then
|
|
311
|
-
d=$(dirname '${e}')
|
|
312
|
-
mkdir -p "/app/.staging/$d"
|
|
313
|
-
mv '/app/${e}' '/app/.staging/${e}'
|
|
314
|
-
echo " moved ${e}"
|
|
315
|
-
else
|
|
316
|
-
echo " skip ${e} (not found)"
|
|
317
|
-
fi`;
|
|
318
|
-
}).join("\n");
|
|
319
|
-
|
|
320
|
-
const script = `set -e
|
|
321
|
-
cleanup() { echo "Cleaning up staging dir"; rm -rf /app/.staging; }
|
|
322
|
-
echo "Preparing production directory..."
|
|
323
|
-
rm -rf /app/.staging
|
|
324
|
-
mkdir -p /app/.staging
|
|
325
|
-
${moveLines}
|
|
326
|
-
if [ "$(ls -A /app/.staging)" ]; then
|
|
327
|
-
rm -rf /app/production
|
|
328
|
-
mv /app/.staging /app/production
|
|
329
|
-
echo "Production directory ready"
|
|
330
|
-
else
|
|
331
|
-
cleanup
|
|
332
|
-
echo "ERROR: no files were moved — check production paths"
|
|
333
|
-
exit 1
|
|
334
|
-
fi`;
|
|
335
|
-
|
|
336
|
-
await this.execAndStream(rt, ["sh", "-c", script], logCb);
|
|
337
|
-
} catch (err) {
|
|
338
|
-
throw new Error(`Failed to prepare production directory: ${err instanceof Error ? err.message : err}`);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// 3. Create a workload for the application process
|
|
343
|
-
const startCommand = config.startCommand || "npm start";
|
|
344
|
-
const envArray = Object.entries(config.envVars).map(
|
|
345
|
-
([k, v]) => `${k}=${v}`,
|
|
346
|
-
);
|
|
347
|
-
|
|
348
|
-
const restartPolicy = config.restartPolicy === "no" ? "never" as const
|
|
349
|
-
: (config.restartPolicy ?? "always") as "always" | "on-failure" | "never";
|
|
350
|
-
|
|
351
|
-
try {
|
|
352
|
-
await ws.workloads.create({
|
|
353
|
-
name: "app",
|
|
354
|
-
cmd: ["sh", "-c", `cd ${workDir} && ${startCommand}`],
|
|
355
|
-
working_dir: workDir,
|
|
356
|
-
env: [
|
|
357
|
-
...envArray,
|
|
358
|
-
`PORT=${config.port}`,
|
|
359
|
-
],
|
|
360
|
-
restart_policy: restartPolicy,
|
|
361
|
-
max_restarts: 10,
|
|
362
|
-
});
|
|
363
|
-
} catch (err) {
|
|
364
|
-
throw new Error(`Failed to create workload: ${err instanceof Error ? err.message : err}`);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// 4. Expose via custom domain OR free subdomain — not both
|
|
368
|
-
let url: string | undefined;
|
|
369
|
-
|
|
370
|
-
if (config.customDomain) {
|
|
371
|
-
try {
|
|
372
|
-
// publicAccess.expose() opens the firewall implicitly, but with
|
|
373
|
-
// custom domain we skip it — so allow the port via network instead
|
|
374
|
-
await ws.network.update({ ingress_ports: [config.port] });
|
|
375
|
-
|
|
376
|
-
await ws.domains.connect({
|
|
377
|
-
domain: config.customDomain,
|
|
378
|
-
port: config.port,
|
|
379
|
-
});
|
|
380
|
-
url = `https://${config.customDomain}`;
|
|
381
|
-
} catch (err) {
|
|
382
|
-
// Fall back to free subdomain if custom domain fails
|
|
383
|
-
console.error(`Failed to connect custom domain ${config.customDomain}: ${err instanceof Error ? err.message : err}`);
|
|
384
|
-
const exposeResult = await ws.publicAccess.expose({
|
|
385
|
-
port: config.port,
|
|
386
|
-
domain: "opsh.io",
|
|
387
|
-
slug: config.slug,
|
|
388
|
-
});
|
|
389
|
-
url = exposeResult.url as string | undefined;
|
|
390
|
-
}
|
|
391
|
-
} else {
|
|
392
|
-
try {
|
|
393
|
-
const exposeResult = await ws.publicAccess.expose({
|
|
394
|
-
port: config.port,
|
|
395
|
-
domain: "opsh.io",
|
|
396
|
-
slug: config.slug,
|
|
397
|
-
});
|
|
398
|
-
url = exposeResult.url as string | undefined;
|
|
399
|
-
} catch (err) {
|
|
400
|
-
throw new Error(`Failed to expose port ${config.port}: ${err instanceof Error ? err.message : err}`);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
return {
|
|
405
|
-
deploymentId: config.deploymentId,
|
|
406
|
-
containerId: workspaceId,
|
|
407
|
-
url: url ?? undefined,
|
|
408
|
-
status: "running",
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Deploy a static site via Oblien Pages.
|
|
414
|
-
*
|
|
415
|
-
* Flow:
|
|
416
|
-
* 1. Create a page from the workspace build output → files copied to edge
|
|
417
|
-
* 2. Page goes live immediately on CDN
|
|
418
|
-
* 3. Delete the workspace — page is independent, no VM needed
|
|
419
|
-
*
|
|
420
|
-
* The "containerId" in the result is the page ID (for future updates/teardown).
|
|
421
|
-
*/
|
|
422
|
-
async deployStatic(config: DeployConfig & { outputDirectory: string; projectName?: string }): Promise<DeploymentResult> {
|
|
423
|
-
const workspaceId = config.imageRef;
|
|
424
|
-
if (!workspaceId) {
|
|
425
|
-
return { deploymentId: config.deploymentId, status: "failed" };
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
// 1. Create page via Pages API — export build output from workspace
|
|
429
|
-
const outputPath = config.outputDirectory.startsWith("/")
|
|
430
|
-
? config.outputDirectory
|
|
431
|
-
: `/app/${config.outputDirectory}`;
|
|
432
|
-
|
|
433
|
-
console.log(`Deploying static site from workspace ${workspaceId}, output path ${outputPath}...`);
|
|
434
|
-
|
|
435
|
-
const slug = config.slug
|
|
436
|
-
?? `${config.projectId.slice(0, 20)}-${config.deploymentId.slice(0, 8)}`
|
|
437
|
-
.toLowerCase()
|
|
438
|
-
.replace(/[^a-z0-9-]/g, "-");
|
|
439
|
-
|
|
440
|
-
let page: { slug: string; url?: string | null };
|
|
441
|
-
|
|
442
|
-
if (config.customDomain) {
|
|
443
|
-
// Deploy with custom domain only — no free subdomain
|
|
444
|
-
const { page: pg } = await this.client.pages.create({
|
|
445
|
-
workspace_id: workspaceId,
|
|
446
|
-
path: outputPath,
|
|
447
|
-
name: config.projectName ?? slug,
|
|
448
|
-
slug,
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
await this.client.pages.connectDomain(pg.slug, {
|
|
452
|
-
domain: config.customDomain,
|
|
453
|
-
}).catch(() => {
|
|
454
|
-
// Non-fatal: page can still be accessed via slug if domain isn't verified yet
|
|
455
|
-
});
|
|
456
|
-
|
|
457
|
-
page = { ...pg, url: pg.url ?? `https://${config.customDomain}` };
|
|
458
|
-
} else {
|
|
459
|
-
// Deploy with free subdomain (slug.opsh.io)
|
|
460
|
-
const { page: pg } = await this.client.pages.create({
|
|
461
|
-
workspace_id: workspaceId,
|
|
462
|
-
path: outputPath,
|
|
463
|
-
name: config.projectName ?? slug,
|
|
464
|
-
slug,
|
|
465
|
-
domain: 'opsh.io',
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
page = pg;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// // 3. Delete the workspace — page lives independently on the edge
|
|
472
|
-
await this.ws(workspaceId).delete().catch(() => {
|
|
473
|
-
// Non-fatal: workspace has TTL and will auto-cleanup
|
|
474
|
-
});
|
|
475
|
-
|
|
476
|
-
return {
|
|
477
|
-
deploymentId: config.deploymentId,
|
|
478
|
-
containerId: `page:${page.slug}`,
|
|
479
|
-
url: page.url ?? undefined,
|
|
480
|
-
status: "running",
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
async stop(containerId: string): Promise<void> {
|
|
485
|
-
if (containerId.startsWith("page:")) {
|
|
486
|
-
await this.client.pages.disable(containerId.slice(5));
|
|
487
|
-
} else {
|
|
488
|
-
await this.ws(containerId).stop();
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
async start(containerId: string): Promise<void> {
|
|
493
|
-
if (containerId.startsWith("page:")) {
|
|
494
|
-
await this.client.pages.enable(containerId.slice(5));
|
|
495
|
-
} else {
|
|
496
|
-
await this.ws(containerId).start();
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
async restart(containerId: string): Promise<void> {
|
|
501
|
-
if (containerId.startsWith("page:")) {
|
|
502
|
-
// Pages are static — no process to restart
|
|
503
|
-
return;
|
|
504
|
-
}
|
|
505
|
-
await this.ws(containerId).restart();
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
async destroy(containerId: string): Promise<void> {
|
|
509
|
-
if (containerId.startsWith("page:")) {
|
|
510
|
-
await this.client.pages.delete(containerId.slice(5));
|
|
511
|
-
} else {
|
|
512
|
-
await this.ws(containerId).delete();
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
// ── Observability ──────────────────────────────────────────────────────
|
|
517
|
-
|
|
518
|
-
async getContainerInfo(containerId: string): Promise<ContainerInfo> {
|
|
519
|
-
const data = await this.ws(containerId).get();
|
|
520
|
-
|
|
521
|
-
const statusMap: Record<string, ContainerStatus> = {
|
|
522
|
-
running: "running",
|
|
523
|
-
stopped: "stopped",
|
|
524
|
-
starting: "deploying",
|
|
525
|
-
stopping: "stopped",
|
|
526
|
-
creating: "building",
|
|
527
|
-
error: "failed",
|
|
528
|
-
};
|
|
529
|
-
|
|
530
|
-
return {
|
|
531
|
-
containerId,
|
|
532
|
-
status: statusMap[data.status] ?? "stopped",
|
|
533
|
-
ip: (data as Record<string, unknown>).ip as string | undefined,
|
|
534
|
-
};
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
async getRuntimeLogs(containerId: string, tail?: number): Promise<LogEntry[]> {
|
|
538
|
-
try {
|
|
539
|
-
const result = await this.ws(containerId).workloads.logs("app");
|
|
540
|
-
const raw = result as Record<string, unknown>;
|
|
541
|
-
|
|
542
|
-
// Oblien returns { logs: "<big string with newlines>" }
|
|
543
|
-
// Each line: [timestamp] stream: message
|
|
544
|
-
if (typeof raw.logs === "string") {
|
|
545
|
-
const logStr = raw.logs as string;
|
|
546
|
-
return logStr.split("\n").filter(Boolean).map((line) => {
|
|
547
|
-
// Parse "[2026-03-14T06:09:25Z] stdout: actual message"
|
|
548
|
-
const match = line.match(/^\[([^\]]+)\]\s+(stdout|stderr):\s?(.*)/);
|
|
549
|
-
if (match) {
|
|
550
|
-
return {
|
|
551
|
-
timestamp: match[1],
|
|
552
|
-
message: match[3],
|
|
553
|
-
level: match[2] === "stderr" ? "warn" as const : "info" as const,
|
|
554
|
-
};
|
|
555
|
-
}
|
|
556
|
-
return { timestamp: now(), message: line, level: "info" as const };
|
|
557
|
-
});
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
// Fallback: array shapes
|
|
561
|
-
const lines = Array.isArray(raw.logs) ? raw.logs
|
|
562
|
-
: Array.isArray(raw.entries) ? raw.entries
|
|
563
|
-
: Array.isArray(result) ? result as unknown[]
|
|
564
|
-
: [];
|
|
565
|
-
if (lines.length === 0) return [];
|
|
566
|
-
|
|
567
|
-
return lines.map((line: unknown) => {
|
|
568
|
-
if (typeof line === "string") {
|
|
569
|
-
return { timestamp: now(), message: line, level: "info" as const };
|
|
570
|
-
}
|
|
571
|
-
const entry = line as Record<string, unknown>;
|
|
572
|
-
const message = (entry.message as string) ?? (entry.data as string) ?? String(line);
|
|
573
|
-
return {
|
|
574
|
-
timestamp: (entry.timestamp as string) ?? now(),
|
|
575
|
-
message,
|
|
576
|
-
level: entry.stream === "stderr" ? "warn" as const : "info" as const,
|
|
577
|
-
};
|
|
578
|
-
}).filter(e => e.message);
|
|
579
|
-
} catch {
|
|
580
|
-
// Workload may not exist yet — fall back to workspace cmd logs
|
|
581
|
-
const result = await this.ws(containerId).logs.get({
|
|
582
|
-
source: "cmd",
|
|
583
|
-
tail_lines: tail ?? 100,
|
|
584
|
-
});
|
|
585
|
-
|
|
586
|
-
const lines = (result as Record<string, unknown>).logs;
|
|
587
|
-
if (!Array.isArray(lines)) return [];
|
|
588
|
-
|
|
589
|
-
return lines.map((line: unknown) => {
|
|
590
|
-
if (typeof line === "string") {
|
|
591
|
-
return { timestamp: now(), message: line, level: "info" as const };
|
|
592
|
-
}
|
|
593
|
-
const entry = line as Record<string, unknown>;
|
|
594
|
-
return {
|
|
595
|
-
timestamp: (entry.timestamp as string) ?? now(),
|
|
596
|
-
message: (entry.message as string) ?? String(line),
|
|
597
|
-
level: "info" as const,
|
|
598
|
-
};
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
async streamRuntimeLogs(
|
|
604
|
-
containerId: string,
|
|
605
|
-
onLog: LogCallback,
|
|
606
|
-
opts?: { tail?: number },
|
|
607
|
-
): Promise<() => void> {
|
|
608
|
-
let cancelled = false;
|
|
609
|
-
|
|
610
|
-
const emitText = (text: string, level: LogEntry["level"], timestamp?: string) => {
|
|
611
|
-
if (!text) return; // skip empty entries
|
|
612
|
-
const rawData = Buffer.from(text).toString("base64");
|
|
613
|
-
onLog({ timestamp: timestamp ?? now(), message: text, level, rawData });
|
|
614
|
-
};
|
|
615
|
-
|
|
616
|
-
const run = async () => {
|
|
617
|
-
try {
|
|
618
|
-
// 1. Replay existing logs so the terminal isn't blank
|
|
619
|
-
try {
|
|
620
|
-
const history = await this.getRuntimeLogs(containerId, opts?.tail ?? 100);
|
|
621
|
-
for (const entry of history) {
|
|
622
|
-
if (cancelled) return;
|
|
623
|
-
if (!entry.message) continue;
|
|
624
|
-
const rawData = entry.rawData ?? Buffer.from(entry.message).toString("base64");
|
|
625
|
-
onLog({ ...entry, rawData });
|
|
626
|
-
}
|
|
627
|
-
} catch {
|
|
628
|
-
// Historical fetch failed — non-fatal, continue to live stream
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
if (cancelled) return;
|
|
632
|
-
|
|
633
|
-
// 2. Follow new output from the workload process
|
|
634
|
-
try {
|
|
635
|
-
const stream = this.ws(containerId).workloads.logsStream("app");
|
|
636
|
-
|
|
637
|
-
for await (const event of stream) {
|
|
638
|
-
if (cancelled) break;
|
|
639
|
-
const ev = event as Record<string, unknown>;
|
|
640
|
-
const text = (ev.message as string) ?? event.data ?? "";
|
|
641
|
-
emitText(text, event.stream === "stderr" ? "warn" : "info", event.timestamp);
|
|
642
|
-
}
|
|
643
|
-
} catch {
|
|
644
|
-
// Workload stream unavailable — fall back to workspace cmd logs
|
|
645
|
-
if (cancelled) return;
|
|
646
|
-
try {
|
|
647
|
-
const stream = this.ws(containerId).logs.streamCmd({
|
|
648
|
-
tail_lines: opts?.tail ?? 100,
|
|
649
|
-
});
|
|
650
|
-
|
|
651
|
-
for await (const event of stream) {
|
|
652
|
-
if (cancelled) break;
|
|
653
|
-
emitText(event.message, "info", event.timestamp);
|
|
654
|
-
}
|
|
655
|
-
} catch {
|
|
656
|
-
// Stream ended or was cancelled
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
} catch {
|
|
660
|
-
// Stream ended or was cancelled
|
|
661
|
-
}
|
|
662
|
-
};
|
|
663
|
-
|
|
664
|
-
void run();
|
|
665
|
-
return () => { cancelled = true; };
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
async getUsage(containerId: string): Promise<ResourceUsage> {
|
|
669
|
-
const result = await this.ws(containerId).metrics.stats();
|
|
670
|
-
const stats = result as Record<string, unknown>;
|
|
671
|
-
return {
|
|
672
|
-
cpuPercent: (stats.cpu_usage as number) ?? 0,
|
|
673
|
-
memoryMb: (stats.memory_usage as number) ?? 0,
|
|
674
|
-
diskMb: (stats.disk_usage as number) ?? 0,
|
|
675
|
-
networkRxBytes: ((stats.network as Record<string, unknown>)?.rx as number) ?? 0,
|
|
676
|
-
networkTxBytes: ((stats.network as Record<string, unknown>)?.tx as number) ?? 0,
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
// ── Network ────────────────────────────────────────────────────────────
|
|
681
|
-
|
|
682
|
-
async getContainerIp(containerId: string): Promise<string | null> {
|
|
683
|
-
const data = await this.ws(containerId).get();
|
|
684
|
-
return (data as Record<string, unknown>).ip as string ?? null;
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
// ── Account ────────────────────────────────────────────────────────────
|
|
688
|
-
|
|
689
|
-
/** Check cloud credentials and account status. Throws on failure. */
|
|
690
|
-
async getQuota(): Promise<unknown> {
|
|
691
|
-
return this.client.workspaces.getQuota();
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
// ── Domain / Slug checks ───────────────────────────────────────────────
|
|
695
|
-
|
|
696
|
-
/**
|
|
697
|
-
* Check whether a subdomain slug is available on opsh.io.
|
|
698
|
-
* Uses Oblien's standalone `domain.checkSlug()` — no workspace needed.
|
|
699
|
-
*/
|
|
700
|
-
async checkSlug(slug: string, domain = "opsh.io"): Promise<{ available: boolean; url: string }> {
|
|
701
|
-
const result = await this.client.domain.checkSlug({ slug, domain });
|
|
702
|
-
console.log("Slug check result:", result);
|
|
703
|
-
return { available: result.available, url: result.url };
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
/**
|
|
707
|
-
* Verify DNS records for a custom domain.
|
|
708
|
-
* Uses Oblien's standalone `domain.verify()` — no workspace needed.
|
|
709
|
-
*/
|
|
710
|
-
async verifyDomain(domain: string, resourceId?: string): Promise<{
|
|
711
|
-
verified: boolean;
|
|
712
|
-
cname: boolean;
|
|
713
|
-
ownership: boolean | null;
|
|
714
|
-
errors: string[];
|
|
715
|
-
requiredRecords: {
|
|
716
|
-
cname: { host: string; target: string };
|
|
717
|
-
txt?: { host: string; value: string };
|
|
718
|
-
};
|
|
719
|
-
}> {
|
|
720
|
-
const result = await this.client.domain.verify({ domain, resource_id: resourceId });
|
|
721
|
-
return {
|
|
722
|
-
verified: result.verified,
|
|
723
|
-
cname: result.cname,
|
|
724
|
-
ownership: result.ownership,
|
|
725
|
-
errors: result.errors,
|
|
726
|
-
requiredRecords: {
|
|
727
|
-
cname: result.required_records.cname,
|
|
728
|
-
txt: result.required_records.txt,
|
|
729
|
-
},
|
|
730
|
-
};
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
// ── Private helpers ────────────────────────────────────────────────────
|
|
735
|
-
|
|
736
|
-
/**
|
|
737
|
-
* Execute a command via the runtime exec API and stream output to the log callback.
|
|
738
|
-
* Oblien returns stdout/stderr as native base64 — we pass it through directly
|
|
739
|
-
* via rawData so session-manager forwards it to the frontend without re-encoding.
|
|
740
|
-
* message is set to decoded text for DB storage / display.
|
|
741
|
-
* Throws on non-zero exit code.
|
|
742
|
-
*/
|
|
743
|
-
private async execAndStream(
|
|
744
|
-
rt: Awaited<ReturnType<WorkspaceHandle["runtime"]>>,
|
|
745
|
-
cmd: string[],
|
|
746
|
-
onLog: LogCallback,
|
|
747
|
-
timeoutSeconds?: number,
|
|
748
|
-
): Promise<void> {
|
|
749
|
-
const params = timeoutSeconds ? { timeoutSeconds } : undefined;
|
|
750
|
-
const stream: AsyncGenerator<ExecStreamEvent> = rt.exec.stream(cmd, params);
|
|
751
|
-
|
|
752
|
-
/** Collect recent output for error diagnostics */
|
|
753
|
-
const recentOutput: string[] = [];
|
|
754
|
-
const MAX_OUTPUT_LINES = 50;
|
|
755
|
-
|
|
756
|
-
/** Emit a chunk — raw base64 passes straight through to SSE/terminal. */
|
|
757
|
-
const emit = (b64: string, level: LogEntry["level"]) => {
|
|
758
|
-
const message = Buffer.from(b64, "base64").toString("utf-8");
|
|
759
|
-
onLog({ timestamp: now(), message, level, rawData: b64 });
|
|
760
|
-
// Keep tail of output for error messages
|
|
761
|
-
recentOutput.push(message);
|
|
762
|
-
if (recentOutput.length > MAX_OUTPUT_LINES) recentOutput.shift();
|
|
763
|
-
};
|
|
764
|
-
|
|
765
|
-
let exitCode: number | undefined;
|
|
766
|
-
|
|
767
|
-
for await (const event of stream) {
|
|
768
|
-
switch (event.event) {
|
|
769
|
-
case "stdout":
|
|
770
|
-
emit(event.data, "info");
|
|
771
|
-
break;
|
|
772
|
-
case "stderr":
|
|
773
|
-
emit(event.data, "warn");
|
|
774
|
-
break;
|
|
775
|
-
case "exit":
|
|
776
|
-
exitCode = event.exit_code;
|
|
777
|
-
break;
|
|
778
|
-
case "output":
|
|
779
|
-
if (event.stdout) emit(event.stdout, "info");
|
|
780
|
-
if (event.stderr) emit(event.stderr, "warn");
|
|
781
|
-
break;
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
if (exitCode !== undefined && exitCode !== 0) {
|
|
786
|
-
const output = recentOutput.join("").trim();
|
|
787
|
-
const detail = output ? `\n${output}` : "";
|
|
788
|
-
throw new Error(`Command failed with exit code ${exitCode}${detail}`);
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
}
|