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
|
@@ -1,535 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for run-scripts.ts
|
|
3
|
-
* Specifically testing the nonInteractive mode that prevents script blocking
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
|
|
7
|
-
import { runScriptsInTerminal, discoverScripts } from '../run-scripts';
|
|
8
|
-
import { mkdirSync, writeFileSync, chmodSync, rmSync, existsSync } from 'fs';
|
|
9
|
-
import { join } from 'path';
|
|
10
|
-
import { tmpdir } from 'os';
|
|
11
|
-
|
|
12
|
-
describe('runScriptsInTerminal', () => {
|
|
13
|
-
let testDir: string;
|
|
14
|
-
let scriptsDir: string;
|
|
15
|
-
let workspacePath: string;
|
|
16
|
-
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
testDir = join(tmpdir(), `run-scripts-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
19
|
-
scriptsDir = join(testDir, 'scripts');
|
|
20
|
-
workspacePath = join(testDir, 'workspace');
|
|
21
|
-
mkdirSync(scriptsDir, { recursive: true });
|
|
22
|
-
mkdirSync(workspacePath, { recursive: true });
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
afterEach(() => {
|
|
26
|
-
if (existsSync(testDir)) {
|
|
27
|
-
rmSync(testDir, { recursive: true, force: true });
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
describe('discoverScripts', () => {
|
|
32
|
-
it('should discover executable scripts in directory', () => {
|
|
33
|
-
const script1 = join(scriptsDir, '01-first.sh');
|
|
34
|
-
const script2 = join(scriptsDir, '02-second.sh');
|
|
35
|
-
const nonExec = join(scriptsDir, 'readme.txt');
|
|
36
|
-
|
|
37
|
-
writeFileSync(script1, '#!/bin/bash\necho "first"');
|
|
38
|
-
writeFileSync(script2, '#!/bin/bash\necho "second"');
|
|
39
|
-
writeFileSync(nonExec, 'not executable');
|
|
40
|
-
|
|
41
|
-
chmodSync(script1, 0o755);
|
|
42
|
-
chmodSync(script2, 0o755);
|
|
43
|
-
// nonExec stays non-executable
|
|
44
|
-
|
|
45
|
-
const scripts = discoverScripts(scriptsDir);
|
|
46
|
-
expect(scripts).toHaveLength(2);
|
|
47
|
-
expect(scripts[0]).toContain('01-first.sh');
|
|
48
|
-
expect(scripts[1]).toContain('02-second.sh');
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('should return empty array for non-existent directory', () => {
|
|
52
|
-
const scripts = discoverScripts('/non/existent/path');
|
|
53
|
-
expect(scripts).toEqual([]);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('should return scripts in alphabetical order', () => {
|
|
57
|
-
const scriptZ = join(scriptsDir, 'z-last.sh');
|
|
58
|
-
const scriptA = join(scriptsDir, 'a-first.sh');
|
|
59
|
-
const scriptM = join(scriptsDir, 'm-middle.sh');
|
|
60
|
-
|
|
61
|
-
writeFileSync(scriptZ, '#!/bin/bash\necho "z"');
|
|
62
|
-
writeFileSync(scriptA, '#!/bin/bash\necho "a"');
|
|
63
|
-
writeFileSync(scriptM, '#!/bin/bash\necho "m"');
|
|
64
|
-
|
|
65
|
-
chmodSync(scriptZ, 0o755);
|
|
66
|
-
chmodSync(scriptA, 0o755);
|
|
67
|
-
chmodSync(scriptM, 0o755);
|
|
68
|
-
|
|
69
|
-
const scripts = discoverScripts(scriptsDir);
|
|
70
|
-
expect(scripts[0]).toContain('a-first.sh');
|
|
71
|
-
expect(scripts[1]).toContain('m-middle.sh');
|
|
72
|
-
expect(scripts[2]).toContain('z-last.sh');
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
describe('nonInteractive mode', () => {
|
|
77
|
-
it('should not block when script tries to read stdin', async () => {
|
|
78
|
-
// Create a script that tries to read from stdin with a timeout
|
|
79
|
-
// In interactive mode with no input, this would wait for the timeout
|
|
80
|
-
// In non-interactive mode, stdin is closed so read gets EOF immediately
|
|
81
|
-
const scriptPath = join(scriptsDir, '01-read-stdin.sh');
|
|
82
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
83
|
-
# Try to read from stdin - should get EOF immediately in non-interactive mode
|
|
84
|
-
if read -t 5 input 2>/dev/null; then
|
|
85
|
-
echo "Got input: $input"
|
|
86
|
-
else
|
|
87
|
-
echo "No input (stdin closed or timeout)"
|
|
88
|
-
fi
|
|
89
|
-
exit 0
|
|
90
|
-
`);
|
|
91
|
-
chmodSync(scriptPath, 0o755);
|
|
92
|
-
|
|
93
|
-
// This should complete quickly without blocking for 5 seconds
|
|
94
|
-
const startTime = Date.now();
|
|
95
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
96
|
-
nonInteractive: true,
|
|
97
|
-
});
|
|
98
|
-
const elapsed = Date.now() - startTime;
|
|
99
|
-
|
|
100
|
-
// Should complete in well under 5 seconds (the read timeout)
|
|
101
|
-
// Give it 2 seconds max for script startup overhead
|
|
102
|
-
expect(elapsed).toBeLessThan(2000);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('should complete successfully for simple scripts', async () => {
|
|
106
|
-
const scriptPath = join(scriptsDir, '01-simple.sh');
|
|
107
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
108
|
-
echo "Running cleanup for $1 in $2"
|
|
109
|
-
exit 0
|
|
110
|
-
`);
|
|
111
|
-
chmodSync(scriptPath, 0o755);
|
|
112
|
-
|
|
113
|
-
// Should not throw
|
|
114
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
115
|
-
nonInteractive: true,
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('should throw on script failure', async () => {
|
|
120
|
-
const scriptPath = join(scriptsDir, '01-fail.sh');
|
|
121
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
122
|
-
echo "About to fail"
|
|
123
|
-
exit 1
|
|
124
|
-
`);
|
|
125
|
-
chmodSync(scriptPath, 0o755);
|
|
126
|
-
|
|
127
|
-
await expect(
|
|
128
|
-
runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
129
|
-
nonInteractive: true,
|
|
130
|
-
})
|
|
131
|
-
).rejects.toThrow(/Script failed with exit code 1/);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it('should include script output tail in failure message', async () => {
|
|
135
|
-
const scriptPath = join(scriptsDir, '01-fail-with-output.sh');
|
|
136
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
137
|
-
echo "before fail stdout"
|
|
138
|
-
echo "before fail stderr" >&2
|
|
139
|
-
exit 1
|
|
140
|
-
`);
|
|
141
|
-
chmodSync(scriptPath, 0o755);
|
|
142
|
-
|
|
143
|
-
try {
|
|
144
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
145
|
-
nonInteractive: true,
|
|
146
|
-
});
|
|
147
|
-
throw new Error('Expected script failure');
|
|
148
|
-
} catch (error) {
|
|
149
|
-
expect(error).toBeInstanceOf(Error);
|
|
150
|
-
const message = (error as Error).message;
|
|
151
|
-
expect(message).toContain('Script failed with exit code 1: 01-fail-with-output.sh');
|
|
152
|
-
expect(message).toContain('Last output:');
|
|
153
|
-
expect(message).toContain('before fail stdout');
|
|
154
|
-
expect(message).toContain('before fail stderr');
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it('should truncate large failure output to a bounded tail', async () => {
|
|
159
|
-
const scriptPath = join(scriptsDir, '01-fail-large-output.sh');
|
|
160
|
-
const lines = Array.from({ length: 80 }, (_, idx) => `line-${String(idx + 1).padStart(3, '0')}`).join('\n');
|
|
161
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
162
|
-
cat <<'EOF'
|
|
163
|
-
${lines}
|
|
164
|
-
EOF
|
|
165
|
-
exit 1
|
|
166
|
-
`);
|
|
167
|
-
chmodSync(scriptPath, 0o755);
|
|
168
|
-
|
|
169
|
-
try {
|
|
170
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
171
|
-
nonInteractive: true,
|
|
172
|
-
});
|
|
173
|
-
throw new Error('Expected script failure');
|
|
174
|
-
} catch (error) {
|
|
175
|
-
const message = (error as Error).message;
|
|
176
|
-
expect(message).toContain('Last output (truncated):');
|
|
177
|
-
expect(message).toContain('line-080');
|
|
178
|
-
expect(message).not.toContain('line-001');
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it('should pass workspace name and repository as arguments', async () => {
|
|
183
|
-
// Create a script that writes its arguments to a file
|
|
184
|
-
const outputFile = join(testDir, 'args.txt');
|
|
185
|
-
const scriptPath = join(scriptsDir, '01-check-args.sh');
|
|
186
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
187
|
-
echo "$1" > "${outputFile}"
|
|
188
|
-
echo "$2" >> "${outputFile}"
|
|
189
|
-
`);
|
|
190
|
-
chmodSync(scriptPath, 0o755);
|
|
191
|
-
|
|
192
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'my-workspace', 'owner/repo', {
|
|
193
|
-
nonInteractive: true,
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
const output = await Bun.file(outputFile).text();
|
|
197
|
-
const lines = output.trim().split('\n');
|
|
198
|
-
expect(lines[0]).toBe('my-workspace');
|
|
199
|
-
expect(lines[1]).toBe('owner/repo');
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it('should set working directory to workspace path', async () => {
|
|
203
|
-
const outputFile = join(testDir, 'cwd.txt');
|
|
204
|
-
const scriptPath = join(scriptsDir, '01-check-cwd.sh');
|
|
205
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
206
|
-
pwd > "${outputFile}"
|
|
207
|
-
`);
|
|
208
|
-
chmodSync(scriptPath, 0o755);
|
|
209
|
-
|
|
210
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
211
|
-
nonInteractive: true,
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
const output = await Bun.file(outputFile).text();
|
|
215
|
-
// On macOS, /var is a symlink to /private/var, so we need to handle both
|
|
216
|
-
const actualCwd = output.trim();
|
|
217
|
-
const expectedCwd = workspacePath;
|
|
218
|
-
// Either direct match or with /private prefix (macOS symlink)
|
|
219
|
-
expect(
|
|
220
|
-
actualCwd === expectedCwd ||
|
|
221
|
-
actualCwd === `/private${expectedCwd}` ||
|
|
222
|
-
expectedCwd === `/private${actualCwd}`
|
|
223
|
-
).toBe(true);
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
it('should run scripts in alphabetical order', async () => {
|
|
227
|
-
const outputFile = join(testDir, 'order.txt');
|
|
228
|
-
|
|
229
|
-
// Create scripts out of order
|
|
230
|
-
const script3 = join(scriptsDir, '03-third.sh');
|
|
231
|
-
const script1 = join(scriptsDir, '01-first.sh');
|
|
232
|
-
const script2 = join(scriptsDir, '02-second.sh');
|
|
233
|
-
|
|
234
|
-
writeFileSync(script3, `#!/bin/bash\necho "third" >> "${outputFile}"`);
|
|
235
|
-
writeFileSync(script1, `#!/bin/bash\necho "first" >> "${outputFile}"`);
|
|
236
|
-
writeFileSync(script2, `#!/bin/bash\necho "second" >> "${outputFile}"`);
|
|
237
|
-
|
|
238
|
-
chmodSync(script3, 0o755);
|
|
239
|
-
chmodSync(script1, 0o755);
|
|
240
|
-
chmodSync(script2, 0o755);
|
|
241
|
-
|
|
242
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
243
|
-
nonInteractive: true,
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
const output = await Bun.file(outputFile).text();
|
|
247
|
-
const lines = output.trim().split('\n');
|
|
248
|
-
expect(lines).toEqual(['first', 'second', 'third']);
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
it('should stop on first script failure', async () => {
|
|
252
|
-
const outputFile = join(testDir, 'stopped.txt');
|
|
253
|
-
|
|
254
|
-
const script1 = join(scriptsDir, '01-success.sh');
|
|
255
|
-
const script2 = join(scriptsDir, '02-fail.sh');
|
|
256
|
-
const script3 = join(scriptsDir, '03-never-runs.sh');
|
|
257
|
-
|
|
258
|
-
writeFileSync(script1, `#!/bin/bash\necho "1" >> "${outputFile}"`);
|
|
259
|
-
writeFileSync(script2, `#!/bin/bash\necho "2" >> "${outputFile}"\nexit 1`);
|
|
260
|
-
writeFileSync(script3, `#!/bin/bash\necho "3" >> "${outputFile}"`);
|
|
261
|
-
|
|
262
|
-
chmodSync(script1, 0o755);
|
|
263
|
-
chmodSync(script2, 0o755);
|
|
264
|
-
chmodSync(script3, 0o755);
|
|
265
|
-
|
|
266
|
-
await expect(
|
|
267
|
-
runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
268
|
-
nonInteractive: true,
|
|
269
|
-
})
|
|
270
|
-
).rejects.toThrow();
|
|
271
|
-
|
|
272
|
-
const output = await Bun.file(outputFile).text();
|
|
273
|
-
const lines = output.trim().split('\n');
|
|
274
|
-
// Script 3 should never have run
|
|
275
|
-
expect(lines).toEqual(['1', '2']);
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
describe('interactive mode (default)', () => {
|
|
280
|
-
it('should run scripts successfully', async () => {
|
|
281
|
-
const scriptPath = join(scriptsDir, '01-simple.sh');
|
|
282
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
283
|
-
echo "Running in interactive mode"
|
|
284
|
-
exit 0
|
|
285
|
-
`);
|
|
286
|
-
chmodSync(scriptPath, 0o755);
|
|
287
|
-
|
|
288
|
-
// Should not throw - default is interactive mode
|
|
289
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo');
|
|
290
|
-
});
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
describe('environment variables', () => {
|
|
294
|
-
it('passes bundle values using configured key names', async () => {
|
|
295
|
-
const outputFile = join(testDir, 'env.txt');
|
|
296
|
-
const scriptPath = join(scriptsDir, '01-env.sh');
|
|
297
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
298
|
-
echo "$API_KEY" >> "${outputFile}"
|
|
299
|
-
echo "$DATABASE_URL" >> "${outputFile}"
|
|
300
|
-
`);
|
|
301
|
-
chmodSync(scriptPath, 0o755);
|
|
302
|
-
|
|
303
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
304
|
-
nonInteractive: true,
|
|
305
|
-
bundleValues: {
|
|
306
|
-
API_KEY: 'my-api-key',
|
|
307
|
-
DATABASE_URL: 'postgres://localhost/db',
|
|
308
|
-
},
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
const output = await Bun.file(outputFile).text();
|
|
312
|
-
const lines = output.trim().split('\n');
|
|
313
|
-
expect(lines[0]).toBe('my-api-key');
|
|
314
|
-
expect(lines[1]).toBe('postgres://localhost/db');
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
it('passes bundle secrets using configured key names', async () => {
|
|
318
|
-
const outputFile = join(testDir, 'secrets.txt');
|
|
319
|
-
const scriptPath = join(scriptsDir, '01-secrets.sh');
|
|
320
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
321
|
-
echo "$TOKEN" >> "${outputFile}"
|
|
322
|
-
`);
|
|
323
|
-
chmodSync(scriptPath, 0o755);
|
|
324
|
-
|
|
325
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
326
|
-
nonInteractive: true,
|
|
327
|
-
bundleSecrets: {
|
|
328
|
-
'token': 'super-secret-token',
|
|
329
|
-
},
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
const output = await Bun.file(outputFile).text();
|
|
333
|
-
expect(output.trim()).toBe('super-secret-token');
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
it('provides uppercase snake-case aliases for camelCase keys', async () => {
|
|
337
|
-
const outputFile = join(testDir, 'aliases.txt');
|
|
338
|
-
const scriptPath = join(scriptsDir, '01-aliases.sh');
|
|
339
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
340
|
-
echo "$TEAM_NAME" >> "${outputFile}"
|
|
341
|
-
echo "$API_TOKEN" >> "${outputFile}"
|
|
342
|
-
`);
|
|
343
|
-
chmodSync(scriptPath, 0o755);
|
|
344
|
-
|
|
345
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
346
|
-
nonInteractive: true,
|
|
347
|
-
bundleValues: {
|
|
348
|
-
teamName: 'platform',
|
|
349
|
-
},
|
|
350
|
-
bundleSecrets: {
|
|
351
|
-
apiToken: 'shh',
|
|
352
|
-
},
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
const output = await Bun.file(outputFile).text();
|
|
356
|
-
const lines = output.trim().split('\n');
|
|
357
|
-
expect(lines[0]).toBe('platform');
|
|
358
|
-
expect(lines[1]).toBe('shh');
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
it('splits acronym boundaries when normalizing aliases', async () => {
|
|
362
|
-
const outputFile = join(testDir, 'acronyms.txt');
|
|
363
|
-
const scriptPath = join(scriptsDir, '01-acronyms.sh');
|
|
364
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
365
|
-
echo "$MY_HTTP_CLIENT" >> "${outputFile}"
|
|
366
|
-
echo "$XML_PARSER" >> "${outputFile}"
|
|
367
|
-
`);
|
|
368
|
-
chmodSync(scriptPath, 0o755);
|
|
369
|
-
|
|
370
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
371
|
-
nonInteractive: true,
|
|
372
|
-
bundleValues: {
|
|
373
|
-
myHTTPClient: 'client-a',
|
|
374
|
-
XMLParser: 'parser-b',
|
|
375
|
-
},
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
const output = await Bun.file(outputFile).text();
|
|
379
|
-
const lines = output.trim().split('\n');
|
|
380
|
-
expect(lines[0]).toBe('client-a');
|
|
381
|
-
expect(lines[1]).toBe('parser-b');
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
it('throws helpful error when normalized alias is not shell-safe', async () => {
|
|
385
|
-
const scriptPath = join(scriptsDir, '01-noop.sh');
|
|
386
|
-
writeFileSync(scriptPath, '#!/bin/bash\necho "ok"');
|
|
387
|
-
chmodSync(scriptPath, 0o755);
|
|
388
|
-
|
|
389
|
-
await expect(
|
|
390
|
-
runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
391
|
-
nonInteractive: true,
|
|
392
|
-
bundleValues: {
|
|
393
|
-
'2faToken': 'secret',
|
|
394
|
-
},
|
|
395
|
-
})
|
|
396
|
-
).rejects.toThrow(/not shell-safe/);
|
|
397
|
-
|
|
398
|
-
await expect(
|
|
399
|
-
runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
400
|
-
nonInteractive: true,
|
|
401
|
-
bundleValues: {
|
|
402
|
-
'2faToken': 'secret',
|
|
403
|
-
},
|
|
404
|
-
})
|
|
405
|
-
).rejects.toThrow(/2FA_TOKEN/);
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
it('throws a helpful error when normalized aliases collide', async () => {
|
|
409
|
-
const scriptPath = join(scriptsDir, '01-noop.sh');
|
|
410
|
-
writeFileSync(scriptPath, '#!/bin/bash\necho "ok"');
|
|
411
|
-
chmodSync(scriptPath, 0o755);
|
|
412
|
-
|
|
413
|
-
await expect(
|
|
414
|
-
runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
415
|
-
nonInteractive: true,
|
|
416
|
-
bundleValues: {
|
|
417
|
-
apiToken: 'a',
|
|
418
|
-
'api-token': 'b',
|
|
419
|
-
},
|
|
420
|
-
})
|
|
421
|
-
).rejects.toThrow(/Bundle script env collision/);
|
|
422
|
-
|
|
423
|
-
await expect(
|
|
424
|
-
runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
425
|
-
nonInteractive: true,
|
|
426
|
-
bundleValues: {
|
|
427
|
-
apiToken: 'a',
|
|
428
|
-
'api-token': 'b',
|
|
429
|
-
},
|
|
430
|
-
})
|
|
431
|
-
).rejects.toThrow(/apiToken/);
|
|
432
|
-
|
|
433
|
-
await expect(
|
|
434
|
-
runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
435
|
-
nonInteractive: true,
|
|
436
|
-
bundleValues: {
|
|
437
|
-
apiToken: 'a',
|
|
438
|
-
'api-token': 'b',
|
|
439
|
-
},
|
|
440
|
-
})
|
|
441
|
-
).rejects.toThrow(/API_TOKEN/);
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
it('throws when same key is exported with conflicting values', async () => {
|
|
445
|
-
const scriptPath = join(scriptsDir, '01-noop.sh');
|
|
446
|
-
writeFileSync(scriptPath, '#!/bin/bash\necho "ok"');
|
|
447
|
-
chmodSync(scriptPath, 0o755);
|
|
448
|
-
|
|
449
|
-
await expect(
|
|
450
|
-
runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
451
|
-
nonInteractive: true,
|
|
452
|
-
bundleValues: {
|
|
453
|
-
sharedKey: 'from-value',
|
|
454
|
-
},
|
|
455
|
-
bundleSecrets: {
|
|
456
|
-
sharedKey: 'from-secret',
|
|
457
|
-
},
|
|
458
|
-
})
|
|
459
|
-
).rejects.toThrow(/Bundle script env conflict/);
|
|
460
|
-
});
|
|
461
|
-
});
|
|
462
|
-
|
|
463
|
-
describe('no scripts', () => {
|
|
464
|
-
it('should complete successfully when no scripts exist', async () => {
|
|
465
|
-
// scriptsDir exists but is empty
|
|
466
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
467
|
-
nonInteractive: true,
|
|
468
|
-
});
|
|
469
|
-
// Should not throw
|
|
470
|
-
});
|
|
471
|
-
|
|
472
|
-
it('should complete successfully when scripts dir does not exist', async () => {
|
|
473
|
-
const nonExistentDir = join(testDir, 'non-existent-scripts');
|
|
474
|
-
await runScriptsInTerminal(nonExistentDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
475
|
-
nonInteractive: true,
|
|
476
|
-
});
|
|
477
|
-
// Should not throw
|
|
478
|
-
});
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
describe('onOutput callback', () => {
|
|
482
|
-
it('should call onOutput with script stdout in nonInteractive mode', async () => {
|
|
483
|
-
const scriptPath = join(scriptsDir, '01-output.sh');
|
|
484
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
485
|
-
echo "Hello from script"
|
|
486
|
-
echo "Line 2"
|
|
487
|
-
`);
|
|
488
|
-
chmodSync(scriptPath, 0o755);
|
|
489
|
-
|
|
490
|
-
const chunks: Buffer[] = [];
|
|
491
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
492
|
-
nonInteractive: true,
|
|
493
|
-
onOutput: (data) => chunks.push(data),
|
|
494
|
-
});
|
|
495
|
-
|
|
496
|
-
const output = Buffer.concat(chunks).toString();
|
|
497
|
-
expect(output).toContain('Hello from script');
|
|
498
|
-
expect(output).toContain('Line 2');
|
|
499
|
-
});
|
|
500
|
-
|
|
501
|
-
it('should call onOutput with script stderr in nonInteractive mode', async () => {
|
|
502
|
-
const scriptPath = join(scriptsDir, '01-stderr.sh');
|
|
503
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
504
|
-
echo "Error message" >&2
|
|
505
|
-
`);
|
|
506
|
-
chmodSync(scriptPath, 0o755);
|
|
507
|
-
|
|
508
|
-
const chunks: Buffer[] = [];
|
|
509
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
510
|
-
nonInteractive: true,
|
|
511
|
-
onOutput: (data) => chunks.push(data),
|
|
512
|
-
});
|
|
513
|
-
|
|
514
|
-
const output = Buffer.concat(chunks).toString();
|
|
515
|
-
expect(output).toContain('Error message');
|
|
516
|
-
});
|
|
517
|
-
|
|
518
|
-
it('should not call onOutput in interactive mode (stdio: inherit)', async () => {
|
|
519
|
-
const scriptPath = join(scriptsDir, '01-simple.sh');
|
|
520
|
-
writeFileSync(scriptPath, `#!/bin/bash
|
|
521
|
-
echo "Output"
|
|
522
|
-
`);
|
|
523
|
-
chmodSync(scriptPath, 0o755);
|
|
524
|
-
|
|
525
|
-
const chunks: Buffer[] = [];
|
|
526
|
-
await runScriptsInTerminal(scriptsDir, workspacePath, 'test-workspace', 'test/repo', {
|
|
527
|
-
nonInteractive: false, // Interactive mode
|
|
528
|
-
onOutput: (data) => chunks.push(data),
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
// In interactive mode, stdio is inherited, so onOutput won't be called
|
|
532
|
-
expect(chunks).toHaveLength(0);
|
|
533
|
-
});
|
|
534
|
-
});
|
|
535
|
-
});
|