gitspace 0.2.0-rc.20 → 0.2.0-rc.21
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/package.json +11 -6
- package/.claude/settings.local.json +0 -10
- package/.gitspace/bundle.json +0 -50
- package/.gitspace/events.json +0 -11
- package/.gitspace/processes.json +0 -23
- package/.gitspace/scripts/select/01-status.sh +0 -39
- package/.gitspace/scripts/setup/01-install-deps.sh +0 -12
- package/.gitspace/scripts/setup/02-typecheck.sh +0 -16
- package/AGENTS.md +0 -469
- package/CLAUDE.md +0 -1
- package/bun.lock +0 -794
- package/docs/CONNECTION.md +0 -623
- package/docs/GATEWAY-WORKER.md +0 -319
- package/docs/GETTING-STARTED.md +0 -448
- package/docs/GITSPACE-PLATFORM.md +0 -1819
- package/docs/INFRASTRUCTURE.md +0 -1347
- package/docs/PROTOCOL.md +0 -619
- package/docs/QUICKSTART.md +0 -183
- package/docs/RELAY.md +0 -327
- package/docs/REMOTE-DESIGN.md +0 -554
- package/docs/ROADMAP.md +0 -564
- package/docs/SITE_DOCS_FIGMA_MAKE.md +0 -1176
- package/docs/STACK-DESIGN.md +0 -588
- package/docs/UNIFIED_ARCHITECTURE.md +0 -138
- package/experiments/pty-benchmark.ts +0 -148
- package/experiments/pty-latency.ts +0 -100
- package/experiments/router/client.ts +0 -199
- package/experiments/router/protocol.ts +0 -74
- package/experiments/router/router.ts +0 -217
- package/experiments/router/session.ts +0 -180
- package/experiments/router/test.ts +0 -133
- package/experiments/socket-bandwidth.ts +0 -77
- package/homebrew/gitspace.rb +0 -45
- package/landing-page/ATTRIBUTIONS.md +0 -3
- package/landing-page/README.md +0 -11
- package/landing-page/bun.lock +0 -801
- package/landing-page/guidelines/Guidelines.md +0 -61
- package/landing-page/index.html +0 -37
- package/landing-page/package.json +0 -90
- package/landing-page/postcss.config.mjs +0 -15
- package/landing-page/public/_redirects +0 -1
- package/landing-page/public/favicon.png +0 -0
- package/landing-page/src/app/App.tsx +0 -53
- package/landing-page/src/app/components/figma/ImageWithFallback.tsx +0 -27
- package/landing-page/src/app/components/ui/accordion.tsx +0 -66
- package/landing-page/src/app/components/ui/alert-dialog.tsx +0 -157
- package/landing-page/src/app/components/ui/alert.tsx +0 -66
- package/landing-page/src/app/components/ui/aspect-ratio.tsx +0 -11
- package/landing-page/src/app/components/ui/avatar.tsx +0 -53
- package/landing-page/src/app/components/ui/badge.tsx +0 -46
- package/landing-page/src/app/components/ui/breadcrumb.tsx +0 -109
- package/landing-page/src/app/components/ui/button.tsx +0 -57
- package/landing-page/src/app/components/ui/calendar.tsx +0 -75
- package/landing-page/src/app/components/ui/card.tsx +0 -92
- package/landing-page/src/app/components/ui/carousel.tsx +0 -241
- package/landing-page/src/app/components/ui/chart.tsx +0 -353
- package/landing-page/src/app/components/ui/checkbox.tsx +0 -32
- package/landing-page/src/app/components/ui/collapsible.tsx +0 -33
- package/landing-page/src/app/components/ui/command.tsx +0 -177
- package/landing-page/src/app/components/ui/context-menu.tsx +0 -252
- package/landing-page/src/app/components/ui/dialog.tsx +0 -135
- package/landing-page/src/app/components/ui/drawer.tsx +0 -132
- package/landing-page/src/app/components/ui/dropdown-menu.tsx +0 -257
- package/landing-page/src/app/components/ui/form.tsx +0 -168
- package/landing-page/src/app/components/ui/hover-card.tsx +0 -44
- package/landing-page/src/app/components/ui/input-otp.tsx +0 -77
- package/landing-page/src/app/components/ui/input.tsx +0 -21
- package/landing-page/src/app/components/ui/label.tsx +0 -24
- package/landing-page/src/app/components/ui/menubar.tsx +0 -276
- package/landing-page/src/app/components/ui/navigation-menu.tsx +0 -168
- package/landing-page/src/app/components/ui/pagination.tsx +0 -127
- package/landing-page/src/app/components/ui/popover.tsx +0 -48
- package/landing-page/src/app/components/ui/progress.tsx +0 -31
- package/landing-page/src/app/components/ui/radio-group.tsx +0 -45
- package/landing-page/src/app/components/ui/resizable.tsx +0 -56
- package/landing-page/src/app/components/ui/scroll-area.tsx +0 -58
- package/landing-page/src/app/components/ui/select.tsx +0 -189
- package/landing-page/src/app/components/ui/separator.tsx +0 -28
- package/landing-page/src/app/components/ui/sheet.tsx +0 -139
- package/landing-page/src/app/components/ui/sidebar.tsx +0 -726
- package/landing-page/src/app/components/ui/skeleton.tsx +0 -13
- package/landing-page/src/app/components/ui/slider.tsx +0 -63
- package/landing-page/src/app/components/ui/sonner.tsx +0 -25
- package/landing-page/src/app/components/ui/switch.tsx +0 -31
- package/landing-page/src/app/components/ui/table.tsx +0 -116
- package/landing-page/src/app/components/ui/tabs.tsx +0 -66
- package/landing-page/src/app/components/ui/textarea.tsx +0 -18
- package/landing-page/src/app/components/ui/toggle-group.tsx +0 -73
- package/landing-page/src/app/components/ui/toggle.tsx +0 -47
- package/landing-page/src/app/components/ui/tooltip.tsx +0 -61
- package/landing-page/src/app/components/ui/use-mobile.ts +0 -21
- package/landing-page/src/app/components/ui/utils.ts +0 -6
- package/landing-page/src/components/docs/DocsContent.tsx +0 -801
- package/landing-page/src/components/docs/DocsSidebar.tsx +0 -90
- package/landing-page/src/components/landing/CTA.tsx +0 -59
- package/landing-page/src/components/landing/Comparison.tsx +0 -84
- package/landing-page/src/components/landing/FaultyTerminal.tsx +0 -424
- package/landing-page/src/components/landing/Features.tsx +0 -201
- package/landing-page/src/components/landing/Hero.tsx +0 -142
- package/landing-page/src/components/landing/Pricing.tsx +0 -140
- package/landing-page/src/components/landing/Roadmap.tsx +0 -86
- package/landing-page/src/components/landing/Security.tsx +0 -81
- package/landing-page/src/components/landing/TerminalWindow.tsx +0 -27
- package/landing-page/src/components/landing/UseCases.tsx +0 -55
- package/landing-page/src/components/landing/Workflow.tsx +0 -101
- package/landing-page/src/components/layout/DashboardNavbar.tsx +0 -37
- package/landing-page/src/components/layout/Footer.tsx +0 -55
- package/landing-page/src/components/layout/LandingNavbar.tsx +0 -82
- package/landing-page/src/components/ui/badge.tsx +0 -39
- package/landing-page/src/components/ui/breadcrumb.tsx +0 -115
- package/landing-page/src/components/ui/button.tsx +0 -57
- package/landing-page/src/components/ui/card.tsx +0 -79
- package/landing-page/src/components/ui/mock-terminal.tsx +0 -68
- package/landing-page/src/components/ui/separator.tsx +0 -28
- package/landing-page/src/lib/utils.ts +0 -6
- package/landing-page/src/main.tsx +0 -10
- package/landing-page/src/pages/Dashboard.tsx +0 -133
- package/landing-page/src/pages/DocsPage.tsx +0 -79
- package/landing-page/src/pages/LandingPage.tsx +0 -31
- package/landing-page/src/pages/TerminalView.tsx +0 -106
- package/landing-page/src/styles/fonts.css +0 -0
- package/landing-page/src/styles/index.css +0 -3
- package/landing-page/src/styles/tailwind.css +0 -4
- package/landing-page/src/styles/theme.css +0 -181
- package/landing-page/vite.config.ts +0 -19
- package/scripts/GHOSTTY_TAB_BUG.md +0 -106
- package/scripts/build.ts +0 -298
- package/scripts/migrate-secrets.ts +0 -77
- package/scripts/release.ts +0 -140
- package/scripts/sample-events.ts +0 -263
- package/scripts/test-tabs-minimal.ts +0 -68
- package/scripts/test-tabs-workaround.ts +0 -95
- package/scripts/test-tabs.ts +0 -171
- package/src/__tests__/test-utils.ts +0 -298
- package/src/app/input/__tests__/sessionCommands.test.ts +0 -40
- package/src/app/input/sessionCommands.ts +0 -94
- package/src/app/session/__tests__/useAttachController.test.ts +0 -229
- package/src/app/session/createSessionBackend.bun.ts +0 -76
- package/src/app/session/createSessionBackend.web.ts +0 -104
- package/src/app/session/types.ts +0 -16
- package/src/app/session/useAttachController.ts +0 -220
- package/src/app/session/useProcessActions.ts +0 -201
- package/src/app/session/useSessionClient.ts +0 -35
- package/src/app/session/useWorkspaceDeleteFlow.ts +0 -170
- package/src/app.tui.tsx +0 -2929
- package/src/app.web.tsx +0 -1454
- package/src/commands/__tests__/connect-key.test.ts +0 -10
- package/src/commands/__tests__/events.test.ts +0 -201
- package/src/commands/__tests__/notifications.test.ts +0 -349
- package/src/commands/__tests__/process.test.ts +0 -251
- package/src/commands/__tests__/serve-messages.test.ts +0 -190
- package/src/commands/__tests__/serve-process-hosting.test.ts +0 -63
- package/src/commands/access.ts +0 -298
- package/src/commands/add.ts +0 -455
- package/src/commands/auth.ts +0 -369
- package/src/commands/bundle.ts +0 -232
- package/src/commands/config.ts +0 -242
- package/src/commands/connect-key.ts +0 -1
- package/src/commands/connect.ts +0 -576
- package/src/commands/directory.ts +0 -16
- package/src/commands/events.ts +0 -157
- package/src/commands/host.ts +0 -566
- package/src/commands/identity.ts +0 -184
- package/src/commands/linear.ts +0 -717
- package/src/commands/list.ts +0 -181
- package/src/commands/migrate.ts +0 -52
- package/src/commands/notifications.ts +0 -351
- package/src/commands/process.ts +0 -104
- package/src/commands/relay.ts +0 -315
- package/src/commands/remove.ts +0 -279
- package/src/commands/review.ts +0 -787
- package/src/commands/serve.ts +0 -1946
- package/src/commands/share.ts +0 -451
- package/src/commands/status.ts +0 -125
- package/src/commands/switch.ts +0 -361
- package/src/commands/tmux.ts +0 -317
- package/src/components/DPad.web.tsx +0 -343
- package/src/components/DiffViewer.web.tsx +0 -1192
- package/src/components/Events.tsx +0 -137
- package/src/components/Events.tui.tsx +0 -129
- package/src/components/Events.web.tsx +0 -386
- package/src/components/FloatingControls.web.tsx +0 -112
- package/src/components/FloatingJogWheel.web.tsx +0 -240
- package/src/components/Flow.tsx +0 -458
- package/src/components/Flow.tui.tsx +0 -343
- package/src/components/Flow.web.tsx +0 -442
- package/src/components/Inbox.tsx +0 -448
- package/src/components/Inbox.tui.tsx +0 -262
- package/src/components/Inbox.web.tsx +0 -329
- package/src/components/MachineList.tsx +0 -187
- package/src/components/MachineList.tui.tsx +0 -161
- package/src/components/MachineList.web.tsx +0 -210
- package/src/components/NumPad.web.tsx +0 -270
- package/src/components/ProjectList.tsx +0 -175
- package/src/components/ProjectList.tui.tsx +0 -109
- package/src/components/ProjectList.web.tsx +0 -143
- package/src/components/ProjectOnboardingStep.ts +0 -23
- package/src/components/ProjectOnboardingStep.tui.tsx +0 -88
- package/src/components/ProjectOnboardingStep.web.tsx +0 -59
- package/src/components/RemoteMachineScreen.tui.tsx +0 -690
- package/src/components/ScriptTerminal.tui.tsx +0 -160
- package/src/components/ScriptTerminal.web.tsx +0 -89
- package/src/components/SessionTerminal.tui.tsx +0 -406
- package/src/components/SessionTerminal.web.tsx +0 -467
- package/src/components/SpacesBrowser.tsx +0 -540
- package/src/components/SpacesBrowser.tui.tsx +0 -258
- package/src/components/SpacesBrowser.web.tsx +0 -332
- package/src/components/TerminalControls.web.tsx +0 -464
- package/src/components/ThreadPanel.web.tsx +0 -798
- package/src/components/__tests__/SpacesBrowser.test.ts +0 -541
- package/src/components/__tests__/SpacesBrowser.tui.test.tsx +0 -249
- package/src/components/__tests__/script-terminal-buffer.tui.test.ts +0 -72
- package/src/components/index.ts +0 -105
- package/src/components/review-decision-colors.ts +0 -11
- package/src/components/script-terminal-buffer.tui.ts +0 -37
- package/src/components/session-terminal-page-navigation.ts +0 -48
- package/src/components/terminal-bracketed-paste.tui.test.ts +0 -43
- package/src/components/terminal-bracketed-paste.tui.ts +0 -46
- package/src/core/__tests__/access.test.ts +0 -240
- package/src/core/__tests__/bundle-refresh.test.ts +0 -567
- package/src/core/__tests__/bundle.test.ts +0 -209
- package/src/core/__tests__/github-review.test.ts +0 -781
- package/src/core/__tests__/project-lifecycle.test.ts +0 -137
- package/src/core/__tests__/workspace-lifecycle.test.ts +0 -159
- package/src/core/__tests__/workspace.test.ts +0 -149
- package/src/core/access.ts +0 -277
- package/src/core/bundle-refresh.ts +0 -1064
- package/src/core/bundle.ts +0 -326
- package/src/core/config.ts +0 -405
- package/src/core/git.ts +0 -768
- package/src/core/github-review.ts +0 -761
- package/src/core/github.ts +0 -151
- package/src/core/identity.ts +0 -631
- package/src/core/linear.ts +0 -403
- package/src/core/preferences-service.ts +0 -17
- package/src/core/project-catalog.ts +0 -52
- package/src/core/project-lifecycle.ts +0 -163
- package/src/core/review-executor.ts +0 -316
- package/src/core/review.ts +0 -407
- package/src/core/secret-runtime.ts +0 -167
- package/src/core/shell.ts +0 -117
- package/src/core/trusted-relays.ts +0 -315
- package/src/core/workspace-lifecycle.ts +0 -216
- package/src/core/workspace.ts +0 -363
- package/src/hooks/__tests__/useLocalSession.tui.test.ts +0 -557
- package/src/hooks/index.ts +0 -8
- package/src/hooks/index.tui.ts +0 -32
- package/src/hooks/useDaemonStatus.tui.ts +0 -174
- package/src/hooks/useLocalSession.tui.ts +0 -395
- package/src/hooks/useRelayConnection.web.ts +0 -54
- package/src/hooks/useRemoteMachines.tui.ts +0 -166
- package/src/hooks/useRemoteTerminal.tui.ts +0 -22
- package/src/hooks/useReview.web.ts +0 -248
- package/src/hooks/useTerminal.web.ts +0 -36
- package/src/hooks/useUserActivity.ts +0 -61
- package/src/hooks/useVisualViewport.web.ts +0 -104
- package/src/index.ts +0 -1376
- package/src/lib/events/__tests__/collector-filter.test.ts +0 -105
- package/src/lib/events/__tests__/store-query.test.ts +0 -103
- package/src/lib/events/collector.ts +0 -494
- package/src/lib/events/filters.ts +0 -26
- package/src/lib/events/index.ts +0 -11
- package/src/lib/events/indexer.ts +0 -14
- package/src/lib/events/paths.ts +0 -69
- package/src/lib/events/reader.ts +0 -212
- package/src/lib/events/store.ts +0 -141
- package/src/lib/invite.web.ts +0 -58
- package/src/lib/preferences-service.web.ts +0 -41
- package/src/lib/processes/__tests__/config.test.ts +0 -83
- package/src/lib/processes/__tests__/names.test.ts +0 -125
- package/src/lib/processes/__tests__/schema.test.ts +0 -208
- package/src/lib/processes/__tests__/watchdog.test.ts +0 -210
- package/src/lib/processes/autostart.ts +0 -16
- package/src/lib/processes/config.ts +0 -187
- package/src/lib/processes/control.ts +0 -53
- package/src/lib/processes/editor.ts +0 -32
- package/src/lib/processes/events-config.ts +0 -37
- package/src/lib/processes/index.ts +0 -14
- package/src/lib/processes/instances.ts +0 -20
- package/src/lib/processes/manager.ts +0 -131
- package/src/lib/processes/names.ts +0 -71
- package/src/lib/processes/registry.ts +0 -26
- package/src/lib/processes/runner.ts +0 -211
- package/src/lib/processes/scheduler.ts +0 -17
- package/src/lib/processes/schema.ts +0 -74
- package/src/lib/processes/session-list.ts +0 -15
- package/src/lib/processes/state.ts +0 -82
- package/src/lib/processes/watchdog.test.ts +0 -79
- package/src/lib/processes/watchdog.ts +0 -106
- package/src/lib/remote-session/__tests__/protocol.test.ts +0 -291
- package/src/lib/remote-session/index.ts +0 -7
- package/src/lib/remote-session/protocol.ts +0 -443
- package/src/lib/remote-session/session-handler.ts +0 -1298
- package/src/lib/remote-session/workspace-scanner.ts +0 -161
- package/src/lib/sonner.web.ts +0 -1
- package/src/lib/storage/identity-store.web.ts +0 -94
- package/src/lib/tmux-lite/README.md +0 -81
- package/src/lib/tmux-lite/cli.ts +0 -855
- package/src/lib/tmux-lite/crypto/__tests__/helpers/handshake-runner.ts +0 -349
- package/src/lib/tmux-lite/crypto/__tests__/helpers/mock-relay.ts +0 -291
- package/src/lib/tmux-lite/crypto/__tests__/helpers/test-identities.ts +0 -142
- package/src/lib/tmux-lite/crypto/__tests__/integration/authorization.integration.test.ts +0 -339
- package/src/lib/tmux-lite/crypto/__tests__/integration/e2e-communication.integration.test.ts +0 -477
- package/src/lib/tmux-lite/crypto/__tests__/integration/error-handling.integration.test.ts +0 -499
- package/src/lib/tmux-lite/crypto/__tests__/integration/handshake.integration.test.ts +0 -371
- package/src/lib/tmux-lite/crypto/__tests__/integration/security.integration.test.ts +0 -573
- package/src/lib/tmux-lite/crypto/access-control.test.ts +0 -512
- package/src/lib/tmux-lite/crypto/access-control.ts +0 -320
- package/src/lib/tmux-lite/crypto/frames.test.ts +0 -262
- package/src/lib/tmux-lite/crypto/frames.ts +0 -141
- package/src/lib/tmux-lite/crypto/handshake.ts +0 -894
- package/src/lib/tmux-lite/crypto/identity.test.ts +0 -220
- package/src/lib/tmux-lite/crypto/identity.ts +0 -286
- package/src/lib/tmux-lite/crypto/index.ts +0 -51
- package/src/lib/tmux-lite/crypto/invites.test.ts +0 -381
- package/src/lib/tmux-lite/crypto/invites.ts +0 -215
- package/src/lib/tmux-lite/crypto/keyexchange.ts +0 -435
- package/src/lib/tmux-lite/crypto/keys.test.ts +0 -58
- package/src/lib/tmux-lite/crypto/keys.ts +0 -47
- package/src/lib/tmux-lite/crypto/secretbox.test.ts +0 -169
- package/src/lib/tmux-lite/crypto/secretbox.ts +0 -124
- package/src/lib/tmux-lite/handshake-handler.ts +0 -451
- package/src/lib/tmux-lite/process-run.integration.test.ts +0 -266
- package/src/lib/tmux-lite/protocol.test.ts +0 -307
- package/src/lib/tmux-lite/protocol.ts +0 -291
- package/src/lib/tmux-lite/relay-client.ts +0 -506
- package/src/lib/tmux-lite/server-lifecycle.test.ts +0 -212
- package/src/lib/tmux-lite/server.ts +0 -1412
- package/src/lib/tmux-lite/shell-integration.sh +0 -37
- package/src/lib/tmux-lite/terminal-queries.test.ts +0 -54
- package/src/lib/tmux-lite/terminal-queries.ts +0 -49
- package/src/notifications/__tests__/useNotifications.test.ts +0 -739
- package/src/notifications/index.ts +0 -32
- package/src/notifications/policy.test.ts +0 -424
- package/src/notifications/policy.ts +0 -139
- package/src/notifications/types.ts +0 -82
- package/src/notifications/useNotifications.ts +0 -350
- package/src/pages/ReviewPage.web.tsx +0 -511
- package/src/preferences/index.ts +0 -1
- package/src/preferences/types.ts +0 -9
- package/src/relay/__tests__/e2e-flow.test.ts +0 -1284
- package/src/relay/__tests__/helpers/auth.ts +0 -354
- package/src/relay/__tests__/helpers/ports.ts +0 -51
- package/src/relay/__tests__/protocol-validation.test.ts +0 -265
- package/src/relay/authorization.ts +0 -303
- package/src/relay/embedded-assets.generated.d.ts +0 -15
- package/src/relay/identity.ts +0 -352
- package/src/relay/index.ts +0 -57
- package/src/relay/pipes.test.ts +0 -427
- package/src/relay/pipes.ts +0 -195
- package/src/relay/protocol.ts +0 -804
- package/src/relay/registries.test.ts +0 -437
- package/src/relay/registries.ts +0 -593
- package/src/relay/server.test.ts +0 -1323
- package/src/relay/server.ts +0 -1128
- package/src/relay/signing.ts +0 -238
- package/src/relay/types.ts +0 -69
- package/src/relay-client/__tests__/machine-directory-client.test.ts +0 -152
- package/src/relay-client/__tests__/useMachineDirectory.test.ts +0 -172
- package/src/relay-client/adapters/browser.ts +0 -27
- package/src/relay-client/adapters/node.ts +0 -29
- package/src/relay-client/index.ts +0 -33
- package/src/relay-client/machine-directory-client.ts +0 -244
- package/src/relay-client/useMachineDirectory.ts +0 -175
- package/src/serve/client-session-manager.ts +0 -635
- package/src/serve/daemon.ts +0 -497
- package/src/serve/pty-session.ts +0 -236
- package/src/serve/types.ts +0 -174
- package/src/session/__tests__/backend-manager.test.ts +0 -101
- package/src/session/__tests__/local-session-backend.test.ts +0 -1129
- package/src/session/__tests__/reducer.test.ts +0 -80
- package/src/session/__tests__/remote-session-backend.test.ts +0 -995
- package/src/session/__tests__/session-name.test.ts +0 -35
- package/src/session/__tests__/useBundleRefreshAttachFlow.test.ts +0 -431
- package/src/session/__tests__/useRemoteSessionClient.test.ts +0 -424
- package/src/session/__tests__/workspace-shell-hooks.integration.test.ts +0 -268
- package/src/session/__tests__/workspace-shell-hooks.test.ts +0 -24
- package/src/session/adapters/browser-remote.ts +0 -101
- package/src/session/adapters/node-remote.ts +0 -135
- package/src/session/backend-key.ts +0 -5
- package/src/session/backend-manager.ts +0 -80
- package/src/session/backend.ts +0 -93
- package/src/session/backends/local-session-backend.ts +0 -1119
- package/src/session/backends/remote-session-backend.ts +0 -1378
- package/src/session/crypto/__tests__/web-terminal.test.ts +0 -1158
- package/src/session/crypto/frames.web.ts +0 -205
- package/src/session/crypto/handshake.web.ts +0 -396
- package/src/session/crypto/identity.web.ts +0 -133
- package/src/session/crypto/keyexchange.web.ts +0 -246
- package/src/session/crypto/relay-signing.web.ts +0 -53
- package/src/session/events.ts +0 -38
- package/src/session/index.ts +0 -116
- package/src/session/reducer.ts +0 -274
- package/src/session/selectors.ts +0 -28
- package/src/session/session-name.ts +0 -50
- package/src/session/types.ts +0 -101
- package/src/session/useBundleRefreshAttachFlow.ts +0 -608
- package/src/session/useRemoteSessionClient.ts +0 -424
- package/src/session/useSessionEngine.ts +0 -432
- package/src/session/workspace-shell-hooks.ts +0 -35
- package/src/tui/__tests__/input-text.test.ts +0 -24
- package/src/tui/__tests__/local-terminal-sync.test.ts +0 -82
- package/src/tui/__tests__/session-terminal-page-navigation.test.ts +0 -94
- package/src/tui/app.tsx +0 -2
- package/src/tui/index.ts +0 -18
- package/src/tui/input-text.ts +0 -38
- package/src/tui/local-terminal-sync.ts +0 -41
- package/src/types/bundle-refresh.ts +0 -42
- package/src/types/bundle.ts +0 -130
- package/src/types/config.ts +0 -287
- package/src/types/errors.ts +0 -292
- package/src/types/events.ts +0 -91
- package/src/types/identity.ts +0 -284
- package/src/types/processes.ts +0 -45
- package/src/types/review.ts +0 -349
- package/src/types/script-phase.ts +0 -3
- package/src/types/workspace-fuzzy.ts +0 -49
- package/src/types/workspace.ts +0 -151
- package/src/utils/__tests__/onboarding.test.ts +0 -358
- package/src/utils/__tests__/run-scripts.test.ts +0 -535
- package/src/utils/__tests__/run-workspace-scripts.test.ts +0 -406
- package/src/utils/__tests__/workspace-setup.integration.test.ts +0 -633
- package/src/utils/__tests__/workspace-state.test.ts +0 -78
- package/src/utils/bun-socket-writer.ts +0 -80
- package/src/utils/clipboard.ts +0 -53
- package/src/utils/deps.test.ts +0 -31
- package/src/utils/deps.ts +0 -145
- package/src/utils/device.web.ts +0 -163
- package/src/utils/fuzzy-match.ts +0 -125
- package/src/utils/hostnames.ts +0 -43
- package/src/utils/hunk-header.ts +0 -17
- package/src/utils/id.ts +0 -9
- package/src/utils/logger.ts +0 -127
- package/src/utils/markdown.ts +0 -254
- package/src/utils/normalize-env-key.ts +0 -13
- package/src/utils/onboarding.ts +0 -279
- package/src/utils/prompts.ts +0 -176
- package/src/utils/run-commands.ts +0 -112
- package/src/utils/run-scripts.ts +0 -337
- package/src/utils/run-workspace-scripts.ts +0 -355
- package/src/utils/sanitize.test.ts +0 -149
- package/src/utils/sanitize.ts +0 -162
- package/src/utils/secrets.ts +0 -836
- package/src/utils/shell-escape.ts +0 -40
- package/src/utils/utf8.ts +0 -79
- package/src/utils/workspace-id.ts +0 -55
- package/src/utils/workspace-state.ts +0 -427
- package/src/version.generated.d.ts +0 -2
- package/todo-security.md +0 -92
- package/tsconfig.json +0 -29
- package/web/README.md +0 -73
- package/web/bun.lock +0 -675
- package/web/eslint.config.js +0 -23
- package/web/index.css +0 -249
- package/web/index.html +0 -16
- package/web/main.tsx +0 -10
- package/web/package.json +0 -39
- package/web/public/vite.svg +0 -1
- package/web/tsconfig.app.json +0 -35
- package/web/tsconfig.json +0 -7
- package/web/tsconfig.node.json +0 -26
- package/web/vite.config.ts +0 -39
- package/worker/bun.lock +0 -237
- package/worker/package.json +0 -22
- package/worker/schema.sql +0 -96
- package/worker/src/handlers/auth.ts +0 -451
- package/worker/src/handlers/subdomains.ts +0 -376
- package/worker/src/handlers/user.ts +0 -98
- package/worker/src/index.ts +0 -70
- package/worker/src/middleware/auth.ts +0 -152
- package/worker/src/services/cloudflare.ts +0 -609
- package/worker/src/types.ts +0 -96
- package/worker/tsconfig.json +0 -15
- package/worker/wrangler.toml +0 -26
package/src/commands/host.ts
DELETED
|
@@ -1,566 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Host commands for gitspace.sh hosting
|
|
3
|
-
*
|
|
4
|
-
* Handles subdomain management: reserve, release, list, set-primary, status
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { existsSync, writeFileSync, readFileSync } from 'fs';
|
|
8
|
-
import { join } from 'path';
|
|
9
|
-
import { getSecret, setSecret, deleteSecret } from '../utils/secrets.js';
|
|
10
|
-
import { getSpacesDir } from '../core/config.js';
|
|
11
|
-
import { getPublicKeyWithoutPassword } from '../core/identity.js';
|
|
12
|
-
import { logger } from '../utils/logger.js';
|
|
13
|
-
import { SpacesError } from '../types/errors.js';
|
|
14
|
-
|
|
15
|
-
// API Configuration
|
|
16
|
-
const API_BASE = process.env.GITSPACE_API_URL || 'https://api.gitspace.sh';
|
|
17
|
-
|
|
18
|
-
// ============================================================================
|
|
19
|
-
// Types
|
|
20
|
-
// ============================================================================
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Host configuration stored in ~/.gitspace/host.json
|
|
24
|
-
* Non-sensitive data only - tunnel tokens are in keychain
|
|
25
|
-
*/
|
|
26
|
-
export interface HostConfig {
|
|
27
|
-
subdomain: string;
|
|
28
|
-
serveSubdomain?: string;
|
|
29
|
-
subdomains?: string[];
|
|
30
|
-
createdAt: number;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
interface SubdomainInfo {
|
|
34
|
-
id: string;
|
|
35
|
-
subdomain: string;
|
|
36
|
-
status: string;
|
|
37
|
-
is_primary: number;
|
|
38
|
-
created_at: number;
|
|
39
|
-
updated_at: number;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
interface SubdomainCreateResponse {
|
|
43
|
-
id: string;
|
|
44
|
-
subdomain: string;
|
|
45
|
-
tunnelToken?: string;
|
|
46
|
-
serveSubdomain?: string;
|
|
47
|
-
serveTunnelToken?: string;
|
|
48
|
-
hosts: string[];
|
|
49
|
-
isPrimary: boolean;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function getServeTokenKey(subdomain: string): string {
|
|
53
|
-
return `TUNNEL_TOKEN_${subdomain}_serve`;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// ============================================================================
|
|
57
|
-
// Host Config Management
|
|
58
|
-
// ============================================================================
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Get the host config file path
|
|
62
|
-
*/
|
|
63
|
-
function getHostConfigPath(): string {
|
|
64
|
-
return join(getSpacesDir(), 'host.json');
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Read host config from disk
|
|
69
|
-
*/
|
|
70
|
-
export function readHostConfig(): HostConfig | null {
|
|
71
|
-
const configPath = getHostConfigPath();
|
|
72
|
-
if (!existsSync(configPath)) {
|
|
73
|
-
return null;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
try {
|
|
77
|
-
const content = readFileSync(configPath, 'utf-8');
|
|
78
|
-
return JSON.parse(content) as HostConfig;
|
|
79
|
-
} catch {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Write host config to disk
|
|
86
|
-
*/
|
|
87
|
-
function writeHostConfig(config: HostConfig): void {
|
|
88
|
-
const configPath = getHostConfigPath();
|
|
89
|
-
writeFileSync(configPath, JSON.stringify(config, null, 2), {
|
|
90
|
-
encoding: 'utf-8',
|
|
91
|
-
mode: 0o600,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Sync host config from gitspace.sh API
|
|
97
|
-
* Called after login and subdomain changes to keep local config in sync
|
|
98
|
-
* @param interactive - If true, prompt user to select primary if needed
|
|
99
|
-
*/
|
|
100
|
-
export async function syncHostConfig(interactive: boolean = false): Promise<void> {
|
|
101
|
-
const token = await getSecret('GITSPACE_TOKEN');
|
|
102
|
-
if (!token) return;
|
|
103
|
-
|
|
104
|
-
try {
|
|
105
|
-
const headers = await getAuthHeaders();
|
|
106
|
-
const res = await fetch(`${API_BASE}/subdomains`, { headers });
|
|
107
|
-
|
|
108
|
-
if (!res.ok) return;
|
|
109
|
-
|
|
110
|
-
const subdomains: SubdomainInfo[] = await res.json();
|
|
111
|
-
const activeSubdomains = subdomains.filter((s) => s.status === 'active');
|
|
112
|
-
|
|
113
|
-
// No subdomains - tell user to reserve one
|
|
114
|
-
if (activeSubdomains.length === 0) {
|
|
115
|
-
if (interactive) {
|
|
116
|
-
logger.log('');
|
|
117
|
-
logger.dim('No subdomains reserved yet.');
|
|
118
|
-
logger.dim('To enable remote access, reserve a subdomain:');
|
|
119
|
-
logger.command(' gssh host reserve <name>');
|
|
120
|
-
}
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Check for primary
|
|
125
|
-
let primary = activeSubdomains.find((s) => s.is_primary);
|
|
126
|
-
|
|
127
|
-
// If no primary set and interactive, ask user to pick one
|
|
128
|
-
if (!primary && interactive && activeSubdomains.length > 0) {
|
|
129
|
-
logger.log('');
|
|
130
|
-
logger.log('Your subdomains:');
|
|
131
|
-
activeSubdomains.forEach((s, i) => {
|
|
132
|
-
logger.log(` ${i + 1}. ${s.subdomain}.gitspace.sh`);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
if (activeSubdomains.length === 1) {
|
|
136
|
-
// Auto-set the only one as primary
|
|
137
|
-
primary = activeSubdomains[0];
|
|
138
|
-
logger.dim(`Setting ${primary.subdomain}.gitspace.sh as primary...`);
|
|
139
|
-
await hostSetPrimary(primary.subdomain);
|
|
140
|
-
} else {
|
|
141
|
-
logger.log('');
|
|
142
|
-
logger.dim('Select a primary subdomain for this machine:');
|
|
143
|
-
logger.command(' gssh host set-primary <name>');
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (primary) {
|
|
148
|
-
const serveSubdomain = activeSubdomains.find(
|
|
149
|
-
(s) => s.subdomain === `${primary.subdomain}.serve`
|
|
150
|
-
);
|
|
151
|
-
const resolvedServeSubdomain = serveSubdomain?.subdomain ?? `${primary.subdomain}.serve`;
|
|
152
|
-
writeHostConfig({
|
|
153
|
-
subdomain: primary.subdomain,
|
|
154
|
-
serveSubdomain: resolvedServeSubdomain,
|
|
155
|
-
subdomains: activeSubdomains.map((s) => s.subdomain),
|
|
156
|
-
createdAt: primary.created_at,
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
// Sync tunnel token if not present (e.g., new machine with existing account)
|
|
160
|
-
const existingToken = await getSecret(`TUNNEL_TOKEN_${primary.subdomain}`);
|
|
161
|
-
if (!existingToken) {
|
|
162
|
-
if (interactive) {
|
|
163
|
-
logger.dim(`Fetching tunnel credentials for ${primary.subdomain}.gitspace.sh...`);
|
|
164
|
-
}
|
|
165
|
-
try {
|
|
166
|
-
const tokenRes = await fetch(`${API_BASE}/subdomains/${primary.subdomain}/token`, { headers });
|
|
167
|
-
if (tokenRes.ok) {
|
|
168
|
-
const { tunnelToken } = await tokenRes.json();
|
|
169
|
-
await setSecret(`TUNNEL_TOKEN_${primary.subdomain}`, tunnelToken);
|
|
170
|
-
if (interactive) {
|
|
171
|
-
logger.success('Tunnel credentials saved');
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
} catch {
|
|
175
|
-
// Ignore token fetch errors
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const serveTokenKey = getServeTokenKey(primary.subdomain);
|
|
180
|
-
const existingServeToken = await getSecret(serveTokenKey);
|
|
181
|
-
if (!existingServeToken) {
|
|
182
|
-
if (interactive) {
|
|
183
|
-
logger.dim(`Fetching tunnel credentials for ${resolvedServeSubdomain}.gitspace.sh...`);
|
|
184
|
-
}
|
|
185
|
-
try {
|
|
186
|
-
const tokenRes = await fetch(`${API_BASE}/subdomains/${resolvedServeSubdomain}/token`, { headers });
|
|
187
|
-
if (tokenRes.ok) {
|
|
188
|
-
const { tunnelToken } = await tokenRes.json();
|
|
189
|
-
await setSecret(serveTokenKey, tunnelToken);
|
|
190
|
-
if (interactive) {
|
|
191
|
-
logger.success('Serve tunnel credentials saved');
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
} catch {
|
|
195
|
-
// Ignore token fetch errors
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
} catch {
|
|
200
|
-
// Ignore sync errors
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// ============================================================================
|
|
205
|
-
// Helper: Get Auth Token
|
|
206
|
-
// ============================================================================
|
|
207
|
-
|
|
208
|
-
async function getAuthToken(): Promise<string> {
|
|
209
|
-
const token = await getSecret('GITSPACE_TOKEN');
|
|
210
|
-
if (!token) {
|
|
211
|
-
throw new SpacesError(
|
|
212
|
-
'Not logged in.\n\nRun: gssh auth login',
|
|
213
|
-
'USER_ERROR'
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
return token;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
async function getAuthHeaders(
|
|
220
|
-
extra: Record<string, string> = {}
|
|
221
|
-
): Promise<Record<string, string>> {
|
|
222
|
-
const token = await getAuthToken();
|
|
223
|
-
const identity = getPublicKeyWithoutPassword();
|
|
224
|
-
if (!identity) {
|
|
225
|
-
throw new SpacesError(
|
|
226
|
-
'Identity not found.\n\nRun: gssh identity init',
|
|
227
|
-
'USER_ERROR',
|
|
228
|
-
1
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
return {
|
|
232
|
-
Authorization: `Bearer ${token}`,
|
|
233
|
-
'X-Device-Fingerprint': identity.signingPublicKey,
|
|
234
|
-
...extra,
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// ============================================================================
|
|
239
|
-
// Reserve Subdomain
|
|
240
|
-
// ============================================================================
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Reserve a subdomain on gitspace.sh
|
|
244
|
-
*/
|
|
245
|
-
export async function hostReserve(subdomain: string): Promise<void> {
|
|
246
|
-
const headers = await getAuthHeaders();
|
|
247
|
-
const jsonHeaders = { ...headers, 'Content-Type': 'application/json' };
|
|
248
|
-
|
|
249
|
-
// Normalize subdomain
|
|
250
|
-
subdomain = subdomain.toLowerCase().trim();
|
|
251
|
-
|
|
252
|
-
// Check availability
|
|
253
|
-
logger.info('Checking availability...');
|
|
254
|
-
const checkRes = await fetch(
|
|
255
|
-
`${API_BASE}/subdomains/check?name=${encodeURIComponent(subdomain)}`,
|
|
256
|
-
{
|
|
257
|
-
headers,
|
|
258
|
-
}
|
|
259
|
-
);
|
|
260
|
-
|
|
261
|
-
if (!checkRes.ok) {
|
|
262
|
-
throw new SpacesError(
|
|
263
|
-
`Failed to check availability: ${checkRes.statusText}`,
|
|
264
|
-
'SYSTEM_ERROR'
|
|
265
|
-
);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
const { available, reason } = await checkRes.json();
|
|
269
|
-
if (!available) {
|
|
270
|
-
throw new SpacesError(
|
|
271
|
-
`Subdomain "${subdomain}" is not available: ${reason}`,
|
|
272
|
-
'USER_ERROR'
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// Reserve
|
|
277
|
-
logger.info('Creating tunnel...');
|
|
278
|
-
const res = await fetch(`${API_BASE}/subdomains`, {
|
|
279
|
-
method: 'POST',
|
|
280
|
-
headers: jsonHeaders,
|
|
281
|
-
body: JSON.stringify({ subdomain }),
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
if (!res.ok) {
|
|
285
|
-
const error = await res.json().catch(() => ({ error: res.statusText }));
|
|
286
|
-
throw new SpacesError(`Failed to reserve: ${error.error}`, 'USER_ERROR');
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const data: SubdomainCreateResponse = await res.json();
|
|
290
|
-
|
|
291
|
-
logger.info('Configuring DNS...');
|
|
292
|
-
|
|
293
|
-
// Fetch and store tunnel token in keychain
|
|
294
|
-
logger.info('Saving credentials...');
|
|
295
|
-
let tunnelToken = data.tunnelToken;
|
|
296
|
-
if (!tunnelToken) {
|
|
297
|
-
const tokenRes = await fetch(
|
|
298
|
-
`${API_BASE}/subdomains/${subdomain}/token`,
|
|
299
|
-
{
|
|
300
|
-
headers,
|
|
301
|
-
}
|
|
302
|
-
);
|
|
303
|
-
|
|
304
|
-
if (!tokenRes.ok) {
|
|
305
|
-
throw new SpacesError('Failed to get tunnel token', 'SYSTEM_ERROR');
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
const tokenData = await tokenRes.json();
|
|
309
|
-
tunnelToken = tokenData.tunnelToken;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
if (!tunnelToken) {
|
|
313
|
-
throw new SpacesError('Failed to get tunnel token', 'SYSTEM_ERROR');
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
const serveSubdomain = data.serveSubdomain ?? `${subdomain}.serve`;
|
|
317
|
-
let serveTunnelToken = data.serveTunnelToken;
|
|
318
|
-
if (!serveTunnelToken) {
|
|
319
|
-
const serveTokenRes = await fetch(
|
|
320
|
-
`${API_BASE}/subdomains/${serveSubdomain}/token`,
|
|
321
|
-
{
|
|
322
|
-
headers,
|
|
323
|
-
}
|
|
324
|
-
);
|
|
325
|
-
|
|
326
|
-
if (!serveTokenRes.ok) {
|
|
327
|
-
throw new SpacesError('Failed to get serve tunnel token', 'SYSTEM_ERROR');
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
const serveTokenData = await serveTokenRes.json();
|
|
331
|
-
serveTunnelToken = serveTokenData.tunnelToken;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
if (!serveTunnelToken) {
|
|
335
|
-
throw new SpacesError('Failed to get serve tunnel token', 'SYSTEM_ERROR');
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
await setSecret(`TUNNEL_TOKEN_${subdomain}`, tunnelToken);
|
|
339
|
-
await setSecret(getServeTokenKey(subdomain), serveTunnelToken);
|
|
340
|
-
|
|
341
|
-
// Update local host config
|
|
342
|
-
await syncHostConfig();
|
|
343
|
-
|
|
344
|
-
logger.log('');
|
|
345
|
-
logger.success(`Reserved: ${data.subdomain}.gitspace.sh`);
|
|
346
|
-
logger.log(` Wildcard: *.${data.subdomain}.gitspace.sh`);
|
|
347
|
-
logger.log(`Serve: ${serveSubdomain}.gitspace.sh`);
|
|
348
|
-
logger.log(` Wildcard: *.${serveSubdomain}.gitspace.sh`);
|
|
349
|
-
if (data.isPrimary) {
|
|
350
|
-
logger.dim(' (set as primary)');
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
logger.log('');
|
|
354
|
-
logger.log("Run 'spaces' to start hosting.");
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
// ============================================================================
|
|
358
|
-
// Release Subdomain
|
|
359
|
-
// ============================================================================
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Release a subdomain
|
|
363
|
-
*/
|
|
364
|
-
export async function hostRelease(subdomain?: string): Promise<void> {
|
|
365
|
-
const headers = await getAuthHeaders();
|
|
366
|
-
|
|
367
|
-
// If no subdomain specified, show list and exit
|
|
368
|
-
if (!subdomain) {
|
|
369
|
-
logger.log('Please specify a subdomain to release:');
|
|
370
|
-
logger.command(' gssh host release <subdomain>');
|
|
371
|
-
logger.log('');
|
|
372
|
-
logger.log('To see your subdomains:');
|
|
373
|
-
logger.command(' gssh host list');
|
|
374
|
-
return;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
subdomain = subdomain.toLowerCase().trim();
|
|
378
|
-
|
|
379
|
-
const res = await fetch(`${API_BASE}/subdomains/${subdomain}`, {
|
|
380
|
-
method: 'DELETE',
|
|
381
|
-
headers,
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
if (!res.ok) {
|
|
385
|
-
const error = await res.json().catch(() => ({ error: res.statusText }));
|
|
386
|
-
throw new SpacesError(`Failed to release: ${error.error}`, 'USER_ERROR');
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// Clear local tunnel token
|
|
390
|
-
await deleteSecret(`TUNNEL_TOKEN_${subdomain}`);
|
|
391
|
-
if (!subdomain.endsWith('.serve')) {
|
|
392
|
-
await deleteSecret(getServeTokenKey(subdomain));
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
// Update local host config
|
|
396
|
-
await syncHostConfig();
|
|
397
|
-
|
|
398
|
-
logger.success(`Released: ${subdomain}.gitspace.sh`);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
// ============================================================================
|
|
402
|
-
// List Subdomains
|
|
403
|
-
// ============================================================================
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* List user's subdomains
|
|
407
|
-
*/
|
|
408
|
-
export async function hostList(): Promise<void> {
|
|
409
|
-
const headers = await getAuthHeaders();
|
|
410
|
-
|
|
411
|
-
const res = await fetch(`${API_BASE}/subdomains`, { headers });
|
|
412
|
-
|
|
413
|
-
if (!res.ok) {
|
|
414
|
-
throw new SpacesError(
|
|
415
|
-
`Failed to list subdomains: ${res.statusText}`,
|
|
416
|
-
'SYSTEM_ERROR'
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
const subdomains: SubdomainInfo[] = await res.json();
|
|
421
|
-
|
|
422
|
-
if (subdomains.length === 0) {
|
|
423
|
-
logger.log('No subdomains reserved.');
|
|
424
|
-
logger.log('');
|
|
425
|
-
logger.log('Reserve one with:');
|
|
426
|
-
logger.command(' gssh host reserve <name>');
|
|
427
|
-
return;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
logger.log('Your subdomains:\n');
|
|
431
|
-
for (const sub of subdomains) {
|
|
432
|
-
const primary = sub.is_primary ? ' (primary)' : '';
|
|
433
|
-
const status = sub.status === 'active' ? '\u2713' : '\u2717';
|
|
434
|
-
logger.log(` ${status} ${sub.subdomain}.gitspace.sh${primary}`);
|
|
435
|
-
logger.dim(` Created: ${new Date(sub.created_at).toLocaleDateString()}`);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
logger.log(`\n${subdomains.length}/3 subdomains used (free tier)`);
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
// ============================================================================
|
|
442
|
-
// Set Primary
|
|
443
|
-
// ============================================================================
|
|
444
|
-
|
|
445
|
-
/**
|
|
446
|
-
* Set a subdomain as primary for `gssh serve`
|
|
447
|
-
*/
|
|
448
|
-
export async function hostSetPrimary(subdomain: string): Promise<void> {
|
|
449
|
-
const headers = await getAuthHeaders();
|
|
450
|
-
subdomain = subdomain.toLowerCase().trim();
|
|
451
|
-
|
|
452
|
-
const res = await fetch(`${API_BASE}/subdomains/${subdomain}/set-primary`, {
|
|
453
|
-
method: 'POST',
|
|
454
|
-
headers,
|
|
455
|
-
});
|
|
456
|
-
|
|
457
|
-
if (!res.ok) {
|
|
458
|
-
const error = await res.json().catch(() => ({ error: res.statusText }));
|
|
459
|
-
throw new SpacesError(`Failed: ${error.error}`, 'USER_ERROR');
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
// Update local host config
|
|
463
|
-
await syncHostConfig();
|
|
464
|
-
|
|
465
|
-
logger.success(`${subdomain}.gitspace.sh is now your primary subdomain`);
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
// ============================================================================
|
|
469
|
-
// Status
|
|
470
|
-
// ============================================================================
|
|
471
|
-
|
|
472
|
-
/**
|
|
473
|
-
* Show hosting status
|
|
474
|
-
*/
|
|
475
|
-
export async function hostStatus(): Promise<void> {
|
|
476
|
-
let headers: Record<string, string>;
|
|
477
|
-
try {
|
|
478
|
-
headers = await getAuthHeaders();
|
|
479
|
-
} catch {
|
|
480
|
-
logger.log('Not logged in or identity not found');
|
|
481
|
-
logger.dim('Run: gssh auth login');
|
|
482
|
-
return;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
try {
|
|
486
|
-
const res = await fetch(`${API_BASE}/subdomains`, { headers });
|
|
487
|
-
|
|
488
|
-
if (!res.ok) {
|
|
489
|
-
logger.log('Could not fetch subdomains');
|
|
490
|
-
return;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
const subdomains: SubdomainInfo[] = await res.json();
|
|
494
|
-
const primary = subdomains.find((s) => s.is_primary && s.status === 'active');
|
|
495
|
-
if (!primary) {
|
|
496
|
-
logger.log('No primary subdomain set.');
|
|
497
|
-
logger.dim('Run: gssh host reserve <name>');
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
const primarySubdomain = primary.subdomain;
|
|
502
|
-
const serveSubdomain = subdomains.find(
|
|
503
|
-
(s) => s.subdomain === `${primarySubdomain}.serve` && s.status === 'active'
|
|
504
|
-
)?.subdomain ?? `${primarySubdomain}.serve`;
|
|
505
|
-
|
|
506
|
-
logger.log(`Primary: ${primary.subdomain}.gitspace.sh`);
|
|
507
|
-
logger.log(`Status: ${primary.status}`);
|
|
508
|
-
logger.log(`Serve: ${serveSubdomain}.gitspace.sh`);
|
|
509
|
-
|
|
510
|
-
// Check if tunnel token exists locally
|
|
511
|
-
let tunnelToken = await getSecret(`TUNNEL_TOKEN_${primary.subdomain}`);
|
|
512
|
-
let serveTunnelToken = await getSecret(getServeTokenKey(primary.subdomain));
|
|
513
|
-
|
|
514
|
-
// Auto-fetch token if missing
|
|
515
|
-
if (!tunnelToken) {
|
|
516
|
-
logger.dim('Tunnel credentials missing, fetching...');
|
|
517
|
-
try {
|
|
518
|
-
const tokenRes = await fetch(`${API_BASE}/subdomains/${primary.subdomain}/token`, { headers });
|
|
519
|
-
if (tokenRes.ok) {
|
|
520
|
-
const { tunnelToken: newToken } = await tokenRes.json();
|
|
521
|
-
await setSecret(`TUNNEL_TOKEN_${primary.subdomain}`, newToken);
|
|
522
|
-
tunnelToken = newToken;
|
|
523
|
-
logger.success('Tunnel credentials synced');
|
|
524
|
-
}
|
|
525
|
-
} catch {
|
|
526
|
-
// Ignore
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
if (!serveTunnelToken) {
|
|
531
|
-
logger.dim('Serve tunnel credentials missing, fetching...');
|
|
532
|
-
try {
|
|
533
|
-
const tokenRes = await fetch(`${API_BASE}/subdomains/${serveSubdomain}/token`, { headers });
|
|
534
|
-
if (tokenRes.ok) {
|
|
535
|
-
const { tunnelToken: newToken } = await tokenRes.json();
|
|
536
|
-
await setSecret(getServeTokenKey(primary.subdomain), newToken);
|
|
537
|
-
serveTunnelToken = newToken;
|
|
538
|
-
logger.success('Serve tunnel credentials synced');
|
|
539
|
-
}
|
|
540
|
-
} catch {
|
|
541
|
-
// Ignore
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
logger.log(`Tunnel token: ${tunnelToken ? 'configured' : 'missing'}`);
|
|
546
|
-
logger.log(`Serve tunnel token: ${serveTunnelToken ? 'configured' : 'missing'}`);
|
|
547
|
-
|
|
548
|
-
if (!tunnelToken) {
|
|
549
|
-
logger.warning('Could not fetch tunnel credentials');
|
|
550
|
-
}
|
|
551
|
-
if (!serveTunnelToken) {
|
|
552
|
-
logger.warning('Could not fetch serve tunnel credentials');
|
|
553
|
-
}
|
|
554
|
-
} catch {
|
|
555
|
-
logger.log('Could not verify status (API unreachable)');
|
|
556
|
-
|
|
557
|
-
// Show local config
|
|
558
|
-
const hostConfig = readHostConfig();
|
|
559
|
-
if (hostConfig) {
|
|
560
|
-
logger.log(`Local config: ${hostConfig.subdomain}.gitspace.sh`);
|
|
561
|
-
if (hostConfig.serveSubdomain) {
|
|
562
|
-
logger.log(`Local serve: ${hostConfig.serveSubdomain}.gitspace.sh`);
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
}
|