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/utils/prompts.ts
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* User prompt utilities using @inquirer/prompts
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { search, input, confirm, password, checkbox, select } from '@inquirer/prompts';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Select an item from a searchable list
|
|
9
|
-
* @param items Array of items to select from
|
|
10
|
-
* @param message Prompt message
|
|
11
|
-
* @returns Selected item or null if cancelled
|
|
12
|
-
*/
|
|
13
|
-
export async function selectItem(
|
|
14
|
-
items: string[],
|
|
15
|
-
message: string
|
|
16
|
-
): Promise<string | null> {
|
|
17
|
-
if (items.length === 0) {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
const selected = await search({
|
|
23
|
-
message,
|
|
24
|
-
source: async (input) => {
|
|
25
|
-
if (!input) {
|
|
26
|
-
return items.map((item) => ({ name: item, value: item }));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Filter items based on input
|
|
30
|
-
const filtered = items.filter((item) =>
|
|
31
|
-
item.toLowerCase().includes(input.toLowerCase())
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
return filtered.map((item) => ({ name: item, value: item }));
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
return selected;
|
|
39
|
-
} catch (error) {
|
|
40
|
-
// User cancelled (Ctrl+C)
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Prompt for text input
|
|
47
|
-
* @param message Prompt message
|
|
48
|
-
* @param options Additional options
|
|
49
|
-
* @returns Input value or null if cancelled
|
|
50
|
-
*/
|
|
51
|
-
export async function promptInput(
|
|
52
|
-
message: string,
|
|
53
|
-
options: {
|
|
54
|
-
default?: string;
|
|
55
|
-
validate?: (value: string) => boolean | string;
|
|
56
|
-
} = {}
|
|
57
|
-
): Promise<string | null> {
|
|
58
|
-
try {
|
|
59
|
-
const value = await input({
|
|
60
|
-
message,
|
|
61
|
-
default: options.default,
|
|
62
|
-
validate: options.validate,
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
return value;
|
|
66
|
-
} catch (error) {
|
|
67
|
-
// User cancelled (Ctrl+C)
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Prompt for confirmation
|
|
74
|
-
* @param message Prompt message
|
|
75
|
-
* @param defaultValue Default value
|
|
76
|
-
* @returns Boolean response
|
|
77
|
-
*/
|
|
78
|
-
export async function promptConfirm(
|
|
79
|
-
message: string,
|
|
80
|
-
defaultValue = false
|
|
81
|
-
): Promise<boolean> {
|
|
82
|
-
try {
|
|
83
|
-
const value = await confirm({
|
|
84
|
-
message,
|
|
85
|
-
default: defaultValue,
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
return value;
|
|
89
|
-
} catch (error) {
|
|
90
|
-
// User cancelled (Ctrl+C), treat as false
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Prompt for password input
|
|
97
|
-
* @param message Prompt message
|
|
98
|
-
* @returns Password value or null if cancelled
|
|
99
|
-
*/
|
|
100
|
-
export async function promptPassword(
|
|
101
|
-
message: string
|
|
102
|
-
): Promise<string | null> {
|
|
103
|
-
try {
|
|
104
|
-
const value = await password({
|
|
105
|
-
message,
|
|
106
|
-
mask: true,
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
return value;
|
|
110
|
-
} catch (error) {
|
|
111
|
-
// User cancelled (Ctrl+C)
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Multi-select from a list of options
|
|
118
|
-
* @param options Array of options with label and value
|
|
119
|
-
* @param message Prompt message
|
|
120
|
-
* @returns Array of selected values or null if cancelled
|
|
121
|
-
*/
|
|
122
|
-
export async function selectMultiple<T>(
|
|
123
|
-
options: Array<{ label: string; value: T; checked?: boolean }>,
|
|
124
|
-
message: string
|
|
125
|
-
): Promise<T[] | null> {
|
|
126
|
-
if (options.length === 0) {
|
|
127
|
-
return [];
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
try {
|
|
131
|
-
const selected = await checkbox({
|
|
132
|
-
message,
|
|
133
|
-
choices: options.map((opt) => ({
|
|
134
|
-
name: opt.label,
|
|
135
|
-
value: opt.value,
|
|
136
|
-
checked: opt.checked ?? false,
|
|
137
|
-
})),
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
return selected;
|
|
141
|
-
} catch (error) {
|
|
142
|
-
// User cancelled (Ctrl+C)
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Select a single item from a list (non-searchable)
|
|
149
|
-
* @param options Array of options with label and value
|
|
150
|
-
* @param message Prompt message
|
|
151
|
-
* @returns Selected value or null if cancelled
|
|
152
|
-
*/
|
|
153
|
-
export async function selectOne<T>(
|
|
154
|
-
options: Array<{ label: string; value: T; description?: string }>,
|
|
155
|
-
message: string
|
|
156
|
-
): Promise<T | null> {
|
|
157
|
-
if (options.length === 0) {
|
|
158
|
-
return null;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
try {
|
|
162
|
-
const selected = await select({
|
|
163
|
-
message,
|
|
164
|
-
choices: options.map((opt) => ({
|
|
165
|
-
name: opt.label,
|
|
166
|
-
value: opt.value,
|
|
167
|
-
description: opt.description,
|
|
168
|
-
})),
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
return selected;
|
|
172
|
-
} catch (error) {
|
|
173
|
-
// User cancelled (Ctrl+C)
|
|
174
|
-
return null;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Run commands in the current terminal (not tmux)
|
|
3
|
-
* Intelligently runs setup commands only once, then select commands
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { spawn } from 'child_process';
|
|
7
|
-
import { SpacesError } from '../types/errors.js';
|
|
8
|
-
import { logger } from './logger.js';
|
|
9
|
-
import { hasSetupBeenRun, markSetupComplete } from './workspace-state.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Run a single command in the workspace directory
|
|
13
|
-
* Streams output to current terminal
|
|
14
|
-
*/
|
|
15
|
-
async function runCommand(
|
|
16
|
-
command: string,
|
|
17
|
-
workspacePath: string
|
|
18
|
-
): Promise<void> {
|
|
19
|
-
return new Promise((resolve, reject) => {
|
|
20
|
-
logger.dim(` $ ${command}`);
|
|
21
|
-
|
|
22
|
-
// Parse command and args
|
|
23
|
-
const [cmd, ...args] = command.split(' ');
|
|
24
|
-
|
|
25
|
-
const child = spawn(cmd, args, {
|
|
26
|
-
cwd: workspacePath,
|
|
27
|
-
stdio: 'inherit', // Stream output to current terminal
|
|
28
|
-
shell: true, // Use shell to handle complex commands
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
child.on('close', (code) => {
|
|
32
|
-
if (code !== 0) {
|
|
33
|
-
reject(
|
|
34
|
-
new SpacesError(
|
|
35
|
-
`Command failed with exit code ${code}: ${command}`,
|
|
36
|
-
'SYSTEM_ERROR',
|
|
37
|
-
2
|
|
38
|
-
)
|
|
39
|
-
);
|
|
40
|
-
} else {
|
|
41
|
-
resolve();
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
child.on('error', (error) => {
|
|
46
|
-
reject(
|
|
47
|
-
new SpacesError(
|
|
48
|
-
`Failed to run command: ${error.message}`,
|
|
49
|
-
'SYSTEM_ERROR',
|
|
50
|
-
2
|
|
51
|
-
)
|
|
52
|
-
);
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Run commands in terminal with smart setup tracking
|
|
59
|
-
* Runs setup commands only once (first time), then select commands on subsequent runs
|
|
60
|
-
*/
|
|
61
|
-
export async function runCommandsInTerminal(
|
|
62
|
-
workspacePath: string,
|
|
63
|
-
setupCommands: string[] = [],
|
|
64
|
-
selectCommands: string[] = []
|
|
65
|
-
): Promise<void> {
|
|
66
|
-
const setupAlreadyRun = hasSetupBeenRun(workspacePath);
|
|
67
|
-
|
|
68
|
-
let commandsToRun: string[] = [];
|
|
69
|
-
let commandType: string;
|
|
70
|
-
|
|
71
|
-
if (setupAlreadyRun) {
|
|
72
|
-
// Setup has been run before, use select commands
|
|
73
|
-
commandsToRun = selectCommands;
|
|
74
|
-
commandType = 'select';
|
|
75
|
-
} else {
|
|
76
|
-
// First time setup, run setup commands
|
|
77
|
-
commandsToRun = setupCommands;
|
|
78
|
-
commandType = 'setup';
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (commandsToRun.length === 0) {
|
|
82
|
-
logger.debug('No commands to run');
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
logger.info(`Running ${commandType} commands...`);
|
|
87
|
-
|
|
88
|
-
try {
|
|
89
|
-
// Run commands sequentially
|
|
90
|
-
for (const cmd of commandsToRun) {
|
|
91
|
-
await runCommand(cmd, workspacePath);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Mark setup as complete if we just ran setup commands
|
|
95
|
-
if (!setupAlreadyRun && setupCommands.length > 0) {
|
|
96
|
-
markSetupComplete(workspacePath);
|
|
97
|
-
logger.debug('Setup marked as complete');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
logger.success('Commands completed');
|
|
101
|
-
} catch (error) {
|
|
102
|
-
if (error instanceof SpacesError) {
|
|
103
|
-
throw error;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
throw new SpacesError(
|
|
107
|
-
`Failed to run commands: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
108
|
-
'SYSTEM_ERROR',
|
|
109
|
-
2
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
}
|
package/src/utils/run-scripts.ts
DELETED
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Convention-based script runner
|
|
3
|
-
* Discovers and runs executable scripts from project scripts/ directories
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { existsSync, readdirSync, statSync } from 'fs';
|
|
7
|
-
import { spawn } from 'child_process';
|
|
8
|
-
import { join } from 'path';
|
|
9
|
-
import { SpacesError } from '../types/errors.js';
|
|
10
|
-
import { logger } from './logger.js';
|
|
11
|
-
import { isShellEnvKey, normalizeEnvKey } from './normalize-env-key.js';
|
|
12
|
-
|
|
13
|
-
const FAILURE_OUTPUT_TAIL_MAX_LINES = 25;
|
|
14
|
-
const FAILURE_OUTPUT_TAIL_MAX_CHARS = 4000;
|
|
15
|
-
|
|
16
|
-
function truncateScriptOutputTail(output: string): { tail: string; truncated: boolean } {
|
|
17
|
-
if (!output) {
|
|
18
|
-
return { tail: '', truncated: false };
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const normalized = output.replace(/\r/g, '');
|
|
22
|
-
|
|
23
|
-
let tailByChars = normalized;
|
|
24
|
-
let truncated = false;
|
|
25
|
-
|
|
26
|
-
if (tailByChars.length > FAILURE_OUTPUT_TAIL_MAX_CHARS) {
|
|
27
|
-
tailByChars = tailByChars.slice(-FAILURE_OUTPUT_TAIL_MAX_CHARS);
|
|
28
|
-
truncated = true;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const lines = tailByChars.split('\n');
|
|
32
|
-
if (lines.length > FAILURE_OUTPUT_TAIL_MAX_LINES) {
|
|
33
|
-
tailByChars = lines.slice(-FAILURE_OUTPUT_TAIL_MAX_LINES).join('\n');
|
|
34
|
-
truncated = true;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return {
|
|
38
|
-
tail: tailByChars.trimEnd(),
|
|
39
|
-
truncated,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function formatScriptFailureMessage(scriptName: string, code: number | null, output: string): string {
|
|
44
|
-
const header = `Script failed with exit code ${code}: ${scriptName}`;
|
|
45
|
-
if (!output.trim()) {
|
|
46
|
-
return header;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const { tail, truncated } = truncateScriptOutputTail(output);
|
|
50
|
-
if (!tail) {
|
|
51
|
-
return header;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const intro = truncated ? 'Last output (truncated):' : 'Last output:';
|
|
55
|
-
return `${header}\n\n${intro}\n${tail}`;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Discover executable scripts in a directory
|
|
60
|
-
* Returns scripts sorted alphabetically for predictable execution order
|
|
61
|
-
*/
|
|
62
|
-
export function discoverScripts(scriptsDir: string): string[] {
|
|
63
|
-
if (!existsSync(scriptsDir)) {
|
|
64
|
-
logger.debug(`Scripts directory does not exist: ${scriptsDir}`);
|
|
65
|
-
return [];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
const files = readdirSync(scriptsDir);
|
|
70
|
-
const scripts: string[] = [];
|
|
71
|
-
|
|
72
|
-
for (const file of files) {
|
|
73
|
-
const filePath = join(scriptsDir, file);
|
|
74
|
-
const stats = statSync(filePath);
|
|
75
|
-
|
|
76
|
-
// Check if file is executable (has execute permission)
|
|
77
|
-
// On Unix: check if any execute bit is set
|
|
78
|
-
if (stats.isFile() && (stats.mode & 0o111) !== 0) {
|
|
79
|
-
scripts.push(filePath);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Sort alphabetically for predictable order
|
|
84
|
-
scripts.sort();
|
|
85
|
-
|
|
86
|
-
logger.debug(`Discovered ${scripts.length} executable scripts in ${scriptsDir}`);
|
|
87
|
-
return scripts;
|
|
88
|
-
} catch (error) {
|
|
89
|
-
logger.debug(`Error discovering scripts: ${error}`);
|
|
90
|
-
return [];
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Options for running scripts
|
|
96
|
-
*/
|
|
97
|
-
export interface RunScriptsOptions {
|
|
98
|
-
/** Bundle values to pass as environment variables */
|
|
99
|
-
bundleValues?: Record<string, string>;
|
|
100
|
-
/** Secret values to pass as environment variables */
|
|
101
|
-
bundleSecrets?: Record<string, string>;
|
|
102
|
-
/**
|
|
103
|
-
* Run scripts in non-interactive mode (for daemon/remote contexts).
|
|
104
|
-
* - stdin is closed immediately (scripts can't prompt for input)
|
|
105
|
-
* - stdout/stderr are captured and logged on failure
|
|
106
|
-
* - Prevents scripts from blocking indefinitely
|
|
107
|
-
*/
|
|
108
|
-
nonInteractive?: boolean;
|
|
109
|
-
/**
|
|
110
|
-
* Callback to receive ANSI output as it arrives (for TUI/Web terminal display).
|
|
111
|
-
* Called with raw output from stdout/stderr. Only works when nonInteractive is true.
|
|
112
|
-
*/
|
|
113
|
-
onOutput?: (data: Buffer) => void;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
type BundleValueKind = 'value' | 'secret';
|
|
117
|
-
|
|
118
|
-
interface EnvBinding {
|
|
119
|
-
envName: string;
|
|
120
|
-
configKey: string;
|
|
121
|
-
sourceKind: BundleValueKind;
|
|
122
|
-
exportKind: 'exact' | 'normalized';
|
|
123
|
-
value: string;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function describeBinding(binding: EnvBinding): string {
|
|
127
|
-
return `${binding.configKey} (${binding.exportKind} ${binding.sourceKind})`;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function describeValue(binding: EnvBinding): string {
|
|
131
|
-
return binding.sourceKind === 'secret' ? '[redacted]' : JSON.stringify(binding.value);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function formatEnvCollisionMessage(existing: EnvBinding, incoming: EnvBinding): string {
|
|
135
|
-
return [
|
|
136
|
-
'Bundle script env collision',
|
|
137
|
-
'',
|
|
138
|
-
`Multiple config keys resolve to the same environment variable: ${incoming.envName}`,
|
|
139
|
-
`- ${incoming.envName} <- ${describeBinding(existing)}`,
|
|
140
|
-
`- ${incoming.envName} <- ${describeBinding(incoming)}`,
|
|
141
|
-
'',
|
|
142
|
-
`Scripts would read an ambiguous value from $${incoming.envName}.`,
|
|
143
|
-
'Fix: rename one of the conflicting configKey values in .gitspace/bundle.json so each exported env var is unique.',
|
|
144
|
-
].join('\n');
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function formatDuplicateValueMessage(existing: EnvBinding, incoming: EnvBinding): string {
|
|
148
|
-
return [
|
|
149
|
-
'Bundle script env conflict',
|
|
150
|
-
'',
|
|
151
|
-
`The same configKey is exported with different values: ${incoming.configKey}`,
|
|
152
|
-
`- ${describeBinding(existing)} => ${describeValue(existing)}`,
|
|
153
|
-
`- ${describeBinding(incoming)} => ${describeValue(incoming)}`,
|
|
154
|
-
'',
|
|
155
|
-
`This would silently overwrite $${incoming.envName}.`,
|
|
156
|
-
`Fix: ensure configKey "${incoming.configKey}" is defined once with a single value.`,
|
|
157
|
-
].join('\n');
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function formatInvalidNormalizedAliasMessage(configKey: string, normalizedAlias: string): string {
|
|
161
|
-
return [
|
|
162
|
-
'Bundle script env alias is not shell-safe',
|
|
163
|
-
'',
|
|
164
|
-
`configKey "${configKey}" normalizes to "${normalizedAlias}".`,
|
|
165
|
-
`Scripts cannot access this via $${normalizedAlias}.`,
|
|
166
|
-
'',
|
|
167
|
-
'Shell variable names must match: [A-Za-z_][A-Za-z0-9_]*',
|
|
168
|
-
'Fix: rename the configKey so its normalized alias starts with a letter or underscore.',
|
|
169
|
-
].join('\n');
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function registerEnvBinding(
|
|
173
|
-
env: Record<string, string>,
|
|
174
|
-
bindings: Map<string, EnvBinding>,
|
|
175
|
-
binding: EnvBinding
|
|
176
|
-
): void {
|
|
177
|
-
const existing = bindings.get(binding.envName);
|
|
178
|
-
|
|
179
|
-
if (existing && existing.configKey !== binding.configKey) {
|
|
180
|
-
throw new SpacesError(formatEnvCollisionMessage(existing, binding), 'USER_ERROR', 1);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (existing && existing.configKey === binding.configKey && existing.value !== binding.value) {
|
|
184
|
-
throw new SpacesError(formatDuplicateValueMessage(existing, binding), 'USER_ERROR', 1);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
bindings.set(binding.envName, binding);
|
|
188
|
-
env[binding.envName] = binding.value;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function setScriptEnvVars(
|
|
192
|
-
env: Record<string, string>,
|
|
193
|
-
bindings: Map<string, EnvBinding>,
|
|
194
|
-
key: string,
|
|
195
|
-
value: string,
|
|
196
|
-
sourceKind: BundleValueKind
|
|
197
|
-
): void {
|
|
198
|
-
registerEnvBinding(env, bindings, {
|
|
199
|
-
envName: key,
|
|
200
|
-
configKey: key,
|
|
201
|
-
sourceKind,
|
|
202
|
-
exportKind: 'exact',
|
|
203
|
-
value,
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
const normalizedKey = normalizeEnvKey(key);
|
|
207
|
-
if (!normalizedKey) {
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (!isShellEnvKey(normalizedKey)) {
|
|
212
|
-
throw new SpacesError(formatInvalidNormalizedAliasMessage(key, normalizedKey), 'USER_ERROR', 1);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (normalizedKey === key) {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Uppercase snake-case alias for shell-friendly access when key uses
|
|
220
|
-
// camelCase or punctuation (for example, apiToken -> API_TOKEN).
|
|
221
|
-
registerEnvBinding(env, bindings, {
|
|
222
|
-
envName: normalizedKey,
|
|
223
|
-
configKey: key,
|
|
224
|
-
sourceKind,
|
|
225
|
-
exportKind: 'normalized',
|
|
226
|
-
value,
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Run scripts in the current terminal
|
|
232
|
-
* Used for pre-scripts that run before tmux session
|
|
233
|
-
*
|
|
234
|
-
* Bundle values are passed as environment variables:
|
|
235
|
-
* - <KEY> using the exact bundle config key name
|
|
236
|
-
* - <NORMALIZED_KEY> uppercase snake-case alias (for example, apiToken -> API_TOKEN)
|
|
237
|
-
* - Throws a user-facing error when multiple keys collide on the same env name
|
|
238
|
-
*/
|
|
239
|
-
export async function runScriptsInTerminal(
|
|
240
|
-
scriptsDir: string,
|
|
241
|
-
workspacePath: string,
|
|
242
|
-
workspaceName: string,
|
|
243
|
-
repository: string,
|
|
244
|
-
options?: RunScriptsOptions
|
|
245
|
-
): Promise<void> {
|
|
246
|
-
const scripts = discoverScripts(scriptsDir);
|
|
247
|
-
|
|
248
|
-
if (scripts.length === 0) {
|
|
249
|
-
logger.debug(`No scripts to run in ${scriptsDir}`);
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
const phaseName = scriptsDir.split('/').pop() || 'scripts';
|
|
254
|
-
logger.info(`Running ${phaseName} scripts...`);
|
|
255
|
-
|
|
256
|
-
// Build environment variables from bundle values
|
|
257
|
-
const scriptEnv: Record<string, string> = { ...process.env } as Record<string, string>;
|
|
258
|
-
const envBindings = new Map<string, EnvBinding>();
|
|
259
|
-
|
|
260
|
-
// Add bundle values using configured key names.
|
|
261
|
-
if (options?.bundleValues) {
|
|
262
|
-
for (const [key, value] of Object.entries(options.bundleValues)) {
|
|
263
|
-
setScriptEnvVars(scriptEnv, envBindings, key, value, 'value');
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// Add bundle secrets using configured key names.
|
|
268
|
-
if (options?.bundleSecrets) {
|
|
269
|
-
for (const [key, value] of Object.entries(options.bundleSecrets)) {
|
|
270
|
-
setScriptEnvVars(scriptEnv, envBindings, key, value, 'secret');
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
for (const scriptPath of scripts) {
|
|
275
|
-
await new Promise<void>((resolve, reject) => {
|
|
276
|
-
const scriptName = scriptPath.split('/').pop() || scriptPath;
|
|
277
|
-
logger.dim(` $ ${scriptName} ${workspaceName} ${repository}`);
|
|
278
|
-
|
|
279
|
-
// Non-interactive mode: stdin=ignore, capture stdout/stderr
|
|
280
|
-
// Interactive mode: inherit all stdio
|
|
281
|
-
const stdio: 'inherit' | ['ignore', 'pipe', 'pipe'] = options?.nonInteractive
|
|
282
|
-
? ['ignore', 'pipe', 'pipe']
|
|
283
|
-
: 'inherit';
|
|
284
|
-
|
|
285
|
-
const child = spawn(scriptPath, [workspaceName, repository], {
|
|
286
|
-
stdio,
|
|
287
|
-
shell: false,
|
|
288
|
-
cwd: workspacePath,
|
|
289
|
-
env: scriptEnv,
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
// Capture output in non-interactive mode for logging on failure
|
|
293
|
-
// Also stream to onOutput callback if provided (for TUI/Web terminal display)
|
|
294
|
-
let output = '';
|
|
295
|
-
if (options?.nonInteractive && child.stdout && child.stderr) {
|
|
296
|
-
child.stdout.on('data', (data: Buffer) => {
|
|
297
|
-
output += data.toString();
|
|
298
|
-
options?.onOutput?.(data);
|
|
299
|
-
});
|
|
300
|
-
child.stderr.on('data', (data: Buffer) => {
|
|
301
|
-
output += data.toString();
|
|
302
|
-
options?.onOutput?.(data);
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
child.on('close', (code: number | null) => {
|
|
307
|
-
if (code !== 0) {
|
|
308
|
-
// Log captured output on failure in non-interactive mode
|
|
309
|
-
if (options?.nonInteractive && output) {
|
|
310
|
-
logger.debug(`Script output:\n${output}`);
|
|
311
|
-
}
|
|
312
|
-
reject(
|
|
313
|
-
new SpacesError(
|
|
314
|
-
formatScriptFailureMessage(scriptName, code, output),
|
|
315
|
-
'SYSTEM_ERROR',
|
|
316
|
-
2
|
|
317
|
-
)
|
|
318
|
-
);
|
|
319
|
-
} else {
|
|
320
|
-
resolve();
|
|
321
|
-
}
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
child.on('error', (error: Error) => {
|
|
325
|
-
reject(
|
|
326
|
-
new SpacesError(
|
|
327
|
-
`Failed to run script: ${error.message}`,
|
|
328
|
-
'SYSTEM_ERROR',
|
|
329
|
-
2
|
|
330
|
-
)
|
|
331
|
-
);
|
|
332
|
-
});
|
|
333
|
-
});
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
logger.success(`${phaseName} scripts completed`);
|
|
337
|
-
}
|