parasor 0.1.0
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/LICENSE +21 -0
- package/README.md +208 -0
- package/THIRD-PARTY-NOTICES.md +138 -0
- package/bin/parasor.mjs +3 -0
- package/node_modules/@parasor/shared/dist/client.d.ts +8 -0
- package/node_modules/@parasor/shared/dist/client.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/client.js +2 -0
- package/node_modules/@parasor/shared/dist/client.js.map +1 -0
- package/node_modules/@parasor/shared/dist/drops.d.ts +24 -0
- package/node_modules/@parasor/shared/dist/drops.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/drops.js +2 -0
- package/node_modules/@parasor/shared/dist/drops.js.map +1 -0
- package/node_modules/@parasor/shared/dist/file-uploads.d.ts +56 -0
- package/node_modules/@parasor/shared/dist/file-uploads.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/file-uploads.js +13 -0
- package/node_modules/@parasor/shared/dist/file-uploads.js.map +1 -0
- package/node_modules/@parasor/shared/dist/ide-commands.d.ts +8 -0
- package/node_modules/@parasor/shared/dist/ide-commands.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/ide-commands.js +59 -0
- package/node_modules/@parasor/shared/dist/ide-commands.js.map +1 -0
- package/node_modules/@parasor/shared/dist/pane-commands.d.ts +7 -0
- package/node_modules/@parasor/shared/dist/pane-commands.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/pane-commands.js +47 -0
- package/node_modules/@parasor/shared/dist/pane-commands.js.map +1 -0
- package/node_modules/@parasor/shared/dist/pane-model.d.ts +63 -0
- package/node_modules/@parasor/shared/dist/pane-model.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/pane-model.js +89 -0
- package/node_modules/@parasor/shared/dist/pane-model.js.map +1 -0
- package/node_modules/@parasor/shared/dist/panes.d.ts +33 -0
- package/node_modules/@parasor/shared/dist/panes.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/panes.js +2 -0
- package/node_modules/@parasor/shared/dist/panes.js.map +1 -0
- package/node_modules/@parasor/shared/dist/runtime.d.ts +180 -0
- package/node_modules/@parasor/shared/dist/runtime.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/runtime.js +2 -0
- package/node_modules/@parasor/shared/dist/runtime.js.map +1 -0
- package/node_modules/@parasor/shared/dist/state.d.ts +192 -0
- package/node_modules/@parasor/shared/dist/state.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/state.js +10 -0
- package/node_modules/@parasor/shared/dist/state.js.map +1 -0
- package/node_modules/@parasor/shared/dist/terminal.d.ts +191 -0
- package/node_modules/@parasor/shared/dist/terminal.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/terminal.js +174 -0
- package/node_modules/@parasor/shared/dist/terminal.js.map +1 -0
- package/node_modules/@parasor/shared/dist/types.d.ts +13 -0
- package/node_modules/@parasor/shared/dist/types.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/types.js +13 -0
- package/node_modules/@parasor/shared/dist/types.js.map +1 -0
- package/node_modules/@parasor/shared/dist/worktree-local-files.d.ts +14 -0
- package/node_modules/@parasor/shared/dist/worktree-local-files.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/worktree-local-files.js +41 -0
- package/node_modules/@parasor/shared/dist/worktree-local-files.js.map +1 -0
- package/node_modules/@parasor/shared/dist/ws-events.d.ts +152 -0
- package/node_modules/@parasor/shared/dist/ws-events.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/ws-events.js +2 -0
- package/node_modules/@parasor/shared/dist/ws-events.js.map +1 -0
- package/node_modules/@parasor/shared/package.json +13 -0
- package/package.json +61 -0
- package/server/agent-detector/agent-state-store.d.ts +23 -0
- package/server/agent-detector/agent-state-store.d.ts.map +1 -0
- package/server/agent-detector/agent-state-store.js +110 -0
- package/server/agent-detector/agent-state-store.js.map +1 -0
- package/server/agent-detector/detector.d.ts +80 -0
- package/server/agent-detector/detector.d.ts.map +1 -0
- package/server/agent-detector/detector.js +219 -0
- package/server/agent-detector/detector.js.map +1 -0
- package/server/agent-detector/event-map.d.ts +25 -0
- package/server/agent-detector/event-map.d.ts.map +1 -0
- package/server/agent-detector/event-map.js +136 -0
- package/server/agent-detector/event-map.js.map +1 -0
- package/server/agent-detector/manual-agent-tracker.d.ts +19 -0
- package/server/agent-detector/manual-agent-tracker.d.ts.map +1 -0
- package/server/agent-detector/manual-agent-tracker.js +123 -0
- package/server/agent-detector/manual-agent-tracker.js.map +1 -0
- package/server/agent-detector/output-eligibility.d.ts +3 -0
- package/server/agent-detector/output-eligibility.d.ts.map +1 -0
- package/server/agent-detector/output-eligibility.js +39 -0
- package/server/agent-detector/output-eligibility.js.map +1 -0
- package/server/application/files/errors.d.ts +28 -0
- package/server/application/files/errors.d.ts.map +1 -0
- package/server/application/files/errors.js +55 -0
- package/server/application/files/errors.js.map +1 -0
- package/server/application/files/local-filesystem.d.ts +36 -0
- package/server/application/files/local-filesystem.d.ts.map +1 -0
- package/server/application/files/local-filesystem.js +171 -0
- package/server/application/files/local-filesystem.js.map +1 -0
- package/server/application/files/project-file-queries.d.ts +16 -0
- package/server/application/files/project-file-queries.d.ts.map +1 -0
- package/server/application/files/project-file-queries.js +126 -0
- package/server/application/files/project-file-queries.js.map +1 -0
- package/server/application/integrations/errors.d.ts +16 -0
- package/server/application/integrations/errors.d.ts.map +1 -0
- package/server/application/integrations/errors.js +31 -0
- package/server/application/integrations/errors.js.map +1 -0
- package/server/application/integrations/hook-notify.d.ts +32 -0
- package/server/application/integrations/hook-notify.d.ts.map +1 -0
- package/server/application/integrations/hook-notify.js +118 -0
- package/server/application/integrations/hook-notify.js.map +1 -0
- package/server/application/integrations/open-url.d.ts +11 -0
- package/server/application/integrations/open-url.d.ts.map +1 -0
- package/server/application/integrations/open-url.js +23 -0
- package/server/application/integrations/open-url.js.map +1 -0
- package/server/application/ports.d.ts +11 -0
- package/server/application/ports.d.ts.map +1 -0
- package/server/application/ports.js +2 -0
- package/server/application/ports.js.map +1 -0
- package/server/application/workspace/errors.d.ts +21 -0
- package/server/application/workspace/errors.d.ts.map +1 -0
- package/server/application/workspace/errors.js +21 -0
- package/server/application/workspace/errors.js.map +1 -0
- package/server/application/workspace/pane-commands.d.ts +47 -0
- package/server/application/workspace/pane-commands.d.ts.map +1 -0
- package/server/application/workspace/pane-commands.js +193 -0
- package/server/application/workspace/pane-commands.js.map +1 -0
- package/server/application/workspace/project-commands.d.ts +34 -0
- package/server/application/workspace/project-commands.d.ts.map +1 -0
- package/server/application/workspace/project-commands.js +81 -0
- package/server/application/workspace/project-commands.js.map +1 -0
- package/server/application/workspace/project-queries.d.ts +21 -0
- package/server/application/workspace/project-queries.d.ts.map +1 -0
- package/server/application/workspace/project-queries.js +216 -0
- package/server/application/workspace/project-queries.js.map +1 -0
- package/server/application/workspace/session-commands.d.ts +24 -0
- package/server/application/workspace/session-commands.d.ts.map +1 -0
- package/server/application/workspace/session-commands.js +123 -0
- package/server/application/workspace/session-commands.js.map +1 -0
- package/server/application/workspace/session-queries.d.ts +14 -0
- package/server/application/workspace/session-queries.d.ts.map +1 -0
- package/server/application/workspace/session-queries.js +47 -0
- package/server/application/workspace/session-queries.js.map +1 -0
- package/server/application/workspace/worktree-commands.d.ts +98 -0
- package/server/application/workspace/worktree-commands.d.ts.map +1 -0
- package/server/application/workspace/worktree-commands.js +323 -0
- package/server/application/workspace/worktree-commands.js.map +1 -0
- package/server/application/workspace/worktree-local-files.d.ts +11 -0
- package/server/application/workspace/worktree-local-files.d.ts.map +1 -0
- package/server/application/workspace/worktree-local-files.js +223 -0
- package/server/application/workspace/worktree-local-files.js.map +1 -0
- package/server/application/workspace/worktree-reconcile.d.ts +21 -0
- package/server/application/workspace/worktree-reconcile.d.ts.map +1 -0
- package/server/application/workspace/worktree-reconcile.js +49 -0
- package/server/application/workspace/worktree-reconcile.js.map +1 -0
- package/server/auth/origin.d.ts +17 -0
- package/server/auth/origin.d.ts.map +1 -0
- package/server/auth/origin.js +93 -0
- package/server/auth/origin.js.map +1 -0
- package/server/auth/pairing-token.d.ts +28 -0
- package/server/auth/pairing-token.d.ts.map +1 -0
- package/server/auth/pairing-token.js +46 -0
- package/server/auth/pairing-token.js.map +1 -0
- package/server/auth/token-exchange.d.ts +11 -0
- package/server/auth/token-exchange.d.ts.map +1 -0
- package/server/auth/token-exchange.js +27 -0
- package/server/auth/token-exchange.js.map +1 -0
- package/server/auth/token.d.ts +18 -0
- package/server/auth/token.d.ts.map +1 -0
- package/server/auth/token.js +115 -0
- package/server/auth/token.js.map +1 -0
- package/server/bootstrap/create-app-server.d.ts +49 -0
- package/server/bootstrap/create-app-server.d.ts.map +1 -0
- package/server/bootstrap/create-app-server.js +154 -0
- package/server/bootstrap/create-app-server.js.map +1 -0
- package/server/bootstrap/project-runtime.d.ts +29 -0
- package/server/bootstrap/project-runtime.d.ts.map +1 -0
- package/server/bootstrap/project-runtime.js +253 -0
- package/server/bootstrap/project-runtime.js.map +1 -0
- package/server/bootstrap/pty-env.d.ts +3 -0
- package/server/bootstrap/pty-env.d.ts.map +1 -0
- package/server/bootstrap/pty-env.js +15 -0
- package/server/bootstrap/pty-env.js.map +1 -0
- package/server/bootstrap/reconcile-state.d.ts +16 -0
- package/server/bootstrap/reconcile-state.d.ts.map +1 -0
- package/server/bootstrap/reconcile-state.js +73 -0
- package/server/bootstrap/reconcile-state.js.map +1 -0
- package/server/bootstrap/runtime-loops.d.ts +51 -0
- package/server/bootstrap/runtime-loops.d.ts.map +1 -0
- package/server/bootstrap/runtime-loops.js +189 -0
- package/server/bootstrap/runtime-loops.js.map +1 -0
- package/server/bootstrap/runtime-port.d.ts +4 -0
- package/server/bootstrap/runtime-port.d.ts.map +1 -0
- package/server/bootstrap/runtime-port.js +52 -0
- package/server/bootstrap/runtime-port.js.map +1 -0
- package/server/bootstrap/safety-gate.d.ts +22 -0
- package/server/bootstrap/safety-gate.d.ts.map +1 -0
- package/server/bootstrap/safety-gate.js +43 -0
- package/server/bootstrap/safety-gate.js.map +1 -0
- package/server/bootstrap/shutdown-marker.d.ts +35 -0
- package/server/bootstrap/shutdown-marker.d.ts.map +1 -0
- package/server/bootstrap/shutdown-marker.js +100 -0
- package/server/bootstrap/shutdown-marker.js.map +1 -0
- package/server/bootstrap/shutdown-runtime.d.ts +62 -0
- package/server/bootstrap/shutdown-runtime.d.ts.map +1 -0
- package/server/bootstrap/shutdown-runtime.js +66 -0
- package/server/bootstrap/shutdown-runtime.js.map +1 -0
- package/server/bootstrap/startup-banner.d.ts +34 -0
- package/server/bootstrap/startup-banner.d.ts.map +1 -0
- package/server/bootstrap/startup-banner.js +114 -0
- package/server/bootstrap/startup-banner.js.map +1 -0
- package/server/bootstrap/wire-runtime.d.ts +42 -0
- package/server/bootstrap/wire-runtime.d.ts.map +1 -0
- package/server/bootstrap/wire-runtime.js +205 -0
- package/server/bootstrap/wire-runtime.js.map +1 -0
- package/server/cli/help.d.ts +3 -0
- package/server/cli/help.d.ts.map +1 -0
- package/server/cli/help.js +39 -0
- package/server/cli/help.js.map +1 -0
- package/server/cli/hook-client.d.ts +12 -0
- package/server/cli/hook-client.d.ts.map +1 -0
- package/server/cli/hook-client.js +81 -0
- package/server/cli/hook-client.js.map +1 -0
- package/server/cli/hook.d.ts +3 -0
- package/server/cli/hook.d.ts.map +1 -0
- package/server/cli/hook.js +152 -0
- package/server/cli/hook.js.map +1 -0
- package/server/cli/main.d.ts +2 -0
- package/server/cli/main.d.ts.map +1 -0
- package/server/cli/main.js +133 -0
- package/server/cli/main.js.map +1 -0
- package/server/cli/notify.d.ts +19 -0
- package/server/cli/notify.d.ts.map +1 -0
- package/server/cli/notify.js +77 -0
- package/server/cli/notify.js.map +1 -0
- package/server/cli/open.d.ts +2 -0
- package/server/cli/open.d.ts.map +1 -0
- package/server/cli/open.js +47 -0
- package/server/cli/open.js.map +1 -0
- package/server/cli/probe-daemon-version.d.ts +46 -0
- package/server/cli/probe-daemon-version.d.ts.map +1 -0
- package/server/cli/probe-daemon-version.js +167 -0
- package/server/cli/probe-daemon-version.js.map +1 -0
- package/server/cli/pty-host.d.ts +36 -0
- package/server/cli/pty-host.d.ts.map +1 -0
- package/server/cli/pty-host.js +390 -0
- package/server/cli/pty-host.js.map +1 -0
- package/server/cli/qr.d.ts +2 -0
- package/server/cli/qr.d.ts.map +1 -0
- package/server/cli/qr.js +70 -0
- package/server/cli/qr.js.map +1 -0
- package/server/cli/restart-confirm.d.ts +33 -0
- package/server/cli/restart-confirm.d.ts.map +1 -0
- package/server/cli/restart-confirm.js +107 -0
- package/server/cli/restart-confirm.js.map +1 -0
- package/server/cli/restart.d.ts +17 -0
- package/server/cli/restart.d.ts.map +1 -0
- package/server/cli/restart.js +145 -0
- package/server/cli/restart.js.map +1 -0
- package/server/cli/service-darwin.d.ts +70 -0
- package/server/cli/service-darwin.d.ts.map +1 -0
- package/server/cli/service-darwin.js +562 -0
- package/server/cli/service-darwin.js.map +1 -0
- package/server/cli/service-linux.d.ts +81 -0
- package/server/cli/service-linux.d.ts.map +1 -0
- package/server/cli/service-linux.js +412 -0
- package/server/cli/service-linux.js.map +1 -0
- package/server/cli/service.d.ts +33 -0
- package/server/cli/service.d.ts.map +1 -0
- package/server/cli/service.js +133 -0
- package/server/cli/service.js.map +1 -0
- package/server/cli/shim-installer.d.ts +35 -0
- package/server/cli/shim-installer.d.ts.map +1 -0
- package/server/cli/shim-installer.js +662 -0
- package/server/cli/shim-installer.js.map +1 -0
- package/server/cli/shim-open.d.ts +2 -0
- package/server/cli/shim-open.d.ts.map +1 -0
- package/server/cli/shim-open.js +128 -0
- package/server/cli/shim-open.js.map +1 -0
- package/server/cli/shutdown-deps.d.ts +41 -0
- package/server/cli/shutdown-deps.d.ts.map +1 -0
- package/server/cli/shutdown-deps.js +158 -0
- package/server/cli/shutdown-deps.js.map +1 -0
- package/server/cli/stop.d.ts +11 -0
- package/server/cli/stop.d.ts.map +1 -0
- package/server/cli/stop.js +123 -0
- package/server/cli/stop.js.map +1 -0
- package/server/cli/unknown-command.d.ts +8 -0
- package/server/cli/unknown-command.d.ts.map +1 -0
- package/server/cli/unknown-command.js +14 -0
- package/server/cli/unknown-command.js.map +1 -0
- package/server/debug/agent-status-recorder.d.ts +57 -0
- package/server/debug/agent-status-recorder.d.ts.map +1 -0
- package/server/debug/agent-status-recorder.js +209 -0
- package/server/debug/agent-status-recorder.js.map +1 -0
- package/server/debug/terminal-trace-recorder.d.ts +41 -0
- package/server/debug/terminal-trace-recorder.d.ts.map +1 -0
- package/server/debug/terminal-trace-recorder.js +112 -0
- package/server/debug/terminal-trace-recorder.js.map +1 -0
- package/server/fonts/catalog.d.ts +35 -0
- package/server/fonts/catalog.d.ts.map +1 -0
- package/server/fonts/catalog.js +76 -0
- package/server/fonts/catalog.js.map +1 -0
- package/server/fonts/installer.d.ts +45 -0
- package/server/fonts/installer.d.ts.map +1 -0
- package/server/fonts/installer.js +201 -0
- package/server/fonts/installer.js.map +1 -0
- package/server/fonts/routes.d.ts +4 -0
- package/server/fonts/routes.d.ts.map +1 -0
- package/server/fonts/routes.js +91 -0
- package/server/fonts/routes.js.map +1 -0
- package/server/fs/drops.d.ts +50 -0
- package/server/fs/drops.d.ts.map +1 -0
- package/server/fs/drops.js +137 -0
- package/server/fs/drops.js.map +1 -0
- package/server/fs/file-uploads.d.ts +57 -0
- package/server/fs/file-uploads.d.ts.map +1 -0
- package/server/fs/file-uploads.js +214 -0
- package/server/fs/file-uploads.js.map +1 -0
- package/server/fs/file-watcher.d.ts +22 -0
- package/server/fs/file-watcher.d.ts.map +1 -0
- package/server/fs/file-watcher.js +105 -0
- package/server/fs/file-watcher.js.map +1 -0
- package/server/fs/git-watcher.d.ts +76 -0
- package/server/fs/git-watcher.d.ts.map +1 -0
- package/server/fs/git-watcher.js +356 -0
- package/server/fs/git-watcher.js.map +1 -0
- package/server/fs/media.d.ts +35 -0
- package/server/fs/media.d.ts.map +1 -0
- package/server/fs/media.js +271 -0
- package/server/fs/media.js.map +1 -0
- package/server/fs/service.d.ts +97 -0
- package/server/fs/service.d.ts.map +1 -0
- package/server/fs/service.js +306 -0
- package/server/fs/service.js.map +1 -0
- package/server/fs/upload-staging.d.ts +76 -0
- package/server/fs/upload-staging.d.ts.map +1 -0
- package/server/fs/upload-staging.js +283 -0
- package/server/fs/upload-staging.js.map +1 -0
- package/server/fs/watcher-lifecycle.d.ts +24 -0
- package/server/fs/watcher-lifecycle.d.ts.map +1 -0
- package/server/fs/watcher-lifecycle.js +105 -0
- package/server/fs/watcher-lifecycle.js.map +1 -0
- package/server/index.d.ts +17 -0
- package/server/index.d.ts.map +1 -0
- package/server/index.js +510 -0
- package/server/index.js.map +1 -0
- package/server/ipc/socket-server.d.ts +28 -0
- package/server/ipc/socket-server.d.ts.map +1 -0
- package/server/ipc/socket-server.js +206 -0
- package/server/ipc/socket-server.js.map +1 -0
- package/server/lib/git-exec.d.ts +38 -0
- package/server/lib/git-exec.d.ts.map +1 -0
- package/server/lib/git-exec.js +96 -0
- package/server/lib/git-exec.js.map +1 -0
- package/server/lib/open-in-ide.d.ts +22 -0
- package/server/lib/open-in-ide.d.ts.map +1 -0
- package/server/lib/open-in-ide.js +90 -0
- package/server/lib/open-in-ide.js.map +1 -0
- package/server/lib/open-in-os.d.ts +20 -0
- package/server/lib/open-in-os.d.ts.map +1 -0
- package/server/lib/open-in-os.js +51 -0
- package/server/lib/open-in-os.js.map +1 -0
- package/server/lib/path.d.ts +2 -0
- package/server/lib/path.d.ts.map +1 -0
- package/server/lib/path.js +10 -0
- package/server/lib/path.js.map +1 -0
- package/server/lib/promise-mutex.d.ts +7 -0
- package/server/lib/promise-mutex.d.ts.map +1 -0
- package/server/lib/promise-mutex.js +26 -0
- package/server/lib/promise-mutex.js.map +1 -0
- package/server/lib/sd-notify.d.ts +8 -0
- package/server/lib/sd-notify.d.ts.map +1 -0
- package/server/lib/sd-notify.js +27 -0
- package/server/lib/sd-notify.js.map +1 -0
- package/server/net/local-machine.d.ts +7 -0
- package/server/net/local-machine.d.ts.map +1 -0
- package/server/net/local-machine.js +79 -0
- package/server/net/local-machine.js.map +1 -0
- package/server/net/reachable-host.d.ts +12 -0
- package/server/net/reachable-host.d.ts.map +1 -0
- package/server/net/reachable-host.js +25 -0
- package/server/net/reachable-host.js.map +1 -0
- package/server/network/endpoints.d.ts +14 -0
- package/server/network/endpoints.d.ts.map +1 -0
- package/server/network/endpoints.js +104 -0
- package/server/network/endpoints.js.map +1 -0
- package/server/network/qr.d.ts +16 -0
- package/server/network/qr.d.ts.map +1 -0
- package/server/network/qr.js +89 -0
- package/server/network/qr.js.map +1 -0
- package/server/port-forwarder/forwarder.d.ts +47 -0
- package/server/port-forwarder/forwarder.d.ts.map +1 -0
- package/server/port-forwarder/forwarder.js +159 -0
- package/server/port-forwarder/forwarder.js.map +1 -0
- package/server/port-scanner/scanner.d.ts +24 -0
- package/server/port-scanner/scanner.d.ts.map +1 -0
- package/server/port-scanner/scanner.js +193 -0
- package/server/port-scanner/scanner.js.map +1 -0
- package/server/pty/connection-lifecycle.d.ts +50 -0
- package/server/pty/connection-lifecycle.d.ts.map +1 -0
- package/server/pty/connection-lifecycle.js +113 -0
- package/server/pty/connection-lifecycle.js.map +1 -0
- package/server/pty/daemon-connect.d.ts +52 -0
- package/server/pty/daemon-connect.d.ts.map +1 -0
- package/server/pty/daemon-connect.js +62 -0
- package/server/pty/daemon-connect.js.map +1 -0
- package/server/pty/handshake-timeout-race.d.ts +22 -0
- package/server/pty/handshake-timeout-race.d.ts.map +1 -0
- package/server/pty/handshake-timeout-race.js +23 -0
- package/server/pty/handshake-timeout-race.js.map +1 -0
- package/server/pty/headless-replay-snapshot.d.ts +28 -0
- package/server/pty/headless-replay-snapshot.d.ts.map +1 -0
- package/server/pty/headless-replay-snapshot.js +285 -0
- package/server/pty/headless-replay-snapshot.js.map +1 -0
- package/server/pty/headless-terminal-state-cache.d.ts +31 -0
- package/server/pty/headless-terminal-state-cache.d.ts.map +1 -0
- package/server/pty/headless-terminal-state-cache.js +119 -0
- package/server/pty/headless-terminal-state-cache.js.map +1 -0
- package/server/pty/hello-ack-validator.d.ts +15 -0
- package/server/pty/hello-ack-validator.d.ts.map +1 -0
- package/server/pty/hello-ack-validator.js +30 -0
- package/server/pty/hello-ack-validator.js.map +1 -0
- package/server/pty/host-daemon/bootstrap.d.ts +100 -0
- package/server/pty/host-daemon/bootstrap.d.ts.map +1 -0
- package/server/pty/host-daemon/bootstrap.js +611 -0
- package/server/pty/host-daemon/bootstrap.js.map +1 -0
- package/server/pty/host-daemon/daemon.d.ts +111 -0
- package/server/pty/host-daemon/daemon.d.ts.map +1 -0
- package/server/pty/host-daemon/daemon.js +648 -0
- package/server/pty/host-daemon/daemon.js.map +1 -0
- package/server/pty/host-daemon/entry.d.ts +3 -0
- package/server/pty/host-daemon/entry.d.ts.map +1 -0
- package/server/pty/host-daemon/entry.js +72 -0
- package/server/pty/host-daemon/entry.js.map +1 -0
- package/server/pty/host-daemon/lockfile.d.ts +12 -0
- package/server/pty/host-daemon/lockfile.d.ts.map +1 -0
- package/server/pty/host-daemon/lockfile.js +120 -0
- package/server/pty/host-daemon/lockfile.js.map +1 -0
- package/server/pty/host-daemon/mode-marker.d.ts +77 -0
- package/server/pty/host-daemon/mode-marker.d.ts.map +1 -0
- package/server/pty/host-daemon/mode-marker.js +228 -0
- package/server/pty/host-daemon/mode-marker.js.map +1 -0
- package/server/pty/host-daemon/orphan-cleanup.d.ts +42 -0
- package/server/pty/host-daemon/orphan-cleanup.d.ts.map +1 -0
- package/server/pty/host-daemon/orphan-cleanup.js +84 -0
- package/server/pty/host-daemon/orphan-cleanup.js.map +1 -0
- package/server/pty/host-daemon/paths.d.ts +10 -0
- package/server/pty/host-daemon/paths.d.ts.map +1 -0
- package/server/pty/host-daemon/paths.js +56 -0
- package/server/pty/host-daemon/paths.js.map +1 -0
- package/server/pty/host-daemon/server-connection.d.ts +44 -0
- package/server/pty/host-daemon/server-connection.d.ts.map +1 -0
- package/server/pty/host-daemon/server-connection.js +100 -0
- package/server/pty/host-daemon/server-connection.js.map +1 -0
- package/server/pty/host-daemon/service-detection.d.ts +24 -0
- package/server/pty/host-daemon/service-detection.d.ts.map +1 -0
- package/server/pty/host-daemon/service-detection.js +16 -0
- package/server/pty/host-daemon/service-detection.js.map +1 -0
- package/server/pty/host-daemon/socket-ready.d.ts +22 -0
- package/server/pty/host-daemon/socket-ready.d.ts.map +1 -0
- package/server/pty/host-daemon/socket-ready.js +33 -0
- package/server/pty/host-daemon/socket-ready.js.map +1 -0
- package/server/pty/host-daemon/spawn-daemon.d.ts +45 -0
- package/server/pty/host-daemon/spawn-daemon.d.ts.map +1 -0
- package/server/pty/host-daemon/spawn-daemon.js +155 -0
- package/server/pty/host-daemon/spawn-daemon.js.map +1 -0
- package/server/pty/host-daemon/terminate-daemon.d.ts +16 -0
- package/server/pty/host-daemon/terminate-daemon.d.ts.map +1 -0
- package/server/pty/host-daemon/terminate-daemon.js +128 -0
- package/server/pty/host-daemon/terminate-daemon.js.map +1 -0
- package/server/pty/host-protocol/frames.d.ts +110 -0
- package/server/pty/host-protocol/frames.d.ts.map +1 -0
- package/server/pty/host-protocol/frames.js +255 -0
- package/server/pty/host-protocol/frames.js.map +1 -0
- package/server/pty/host-protocol/messages.d.ts +140 -0
- package/server/pty/host-protocol/messages.d.ts.map +1 -0
- package/server/pty/host-protocol/messages.js +117 -0
- package/server/pty/host-protocol/messages.js.map +1 -0
- package/server/pty/host.d.ts +273 -0
- package/server/pty/host.d.ts.map +1 -0
- package/server/pty/host.js +184 -0
- package/server/pty/host.js.map +1 -0
- package/server/pty/in-process-host.d.ts +224 -0
- package/server/pty/in-process-host.d.ts.map +1 -0
- package/server/pty/in-process-host.js +1183 -0
- package/server/pty/in-process-host.js.map +1 -0
- package/server/pty/osc7-lifecycle.d.ts +8 -0
- package/server/pty/osc7-lifecycle.d.ts.map +1 -0
- package/server/pty/osc7-lifecycle.js +22 -0
- package/server/pty/osc7-lifecycle.js.map +1 -0
- package/server/pty/osc7-parser.d.ts +23 -0
- package/server/pty/osc7-parser.d.ts.map +1 -0
- package/server/pty/osc7-parser.js +91 -0
- package/server/pty/osc7-parser.js.map +1 -0
- package/server/pty/remote-host.d.ts +188 -0
- package/server/pty/remote-host.d.ts.map +1 -0
- package/server/pty/remote-host.js +810 -0
- package/server/pty/remote-host.js.map +1 -0
- package/server/pty/request-correlator.d.ts +59 -0
- package/server/pty/request-correlator.d.ts.map +1 -0
- package/server/pty/request-correlator.js +75 -0
- package/server/pty/request-correlator.js.map +1 -0
- package/server/pty/scrollback-log.d.ts +130 -0
- package/server/pty/scrollback-log.d.ts.map +1 -0
- package/server/pty/scrollback-log.js +344 -0
- package/server/pty/scrollback-log.js.map +1 -0
- package/server/pty/scrollback-sanitize.d.ts +2 -0
- package/server/pty/scrollback-sanitize.d.ts.map +1 -0
- package/server/pty/scrollback-sanitize.js +54 -0
- package/server/pty/scrollback-sanitize.js.map +1 -0
- package/server/pty/session-mirror.d.ts +67 -0
- package/server/pty/session-mirror.d.ts.map +1 -0
- package/server/pty/session-mirror.js +112 -0
- package/server/pty/session-mirror.js.map +1 -0
- package/server/pty/session-policy.d.ts +85 -0
- package/server/pty/session-policy.d.ts.map +1 -0
- package/server/pty/session-policy.js +186 -0
- package/server/pty/session-policy.js.map +1 -0
- package/server/pty/version-mismatch-recovery.d.ts +71 -0
- package/server/pty/version-mismatch-recovery.d.ts.map +1 -0
- package/server/pty/version-mismatch-recovery.js +63 -0
- package/server/pty/version-mismatch-recovery.js.map +1 -0
- package/server/routes/debug-agent-status.d.ts +5 -0
- package/server/routes/debug-agent-status.d.ts.map +1 -0
- package/server/routes/debug-agent-status.js +22 -0
- package/server/routes/debug-agent-status.js.map +1 -0
- package/server/routes/debug-diagnostics.d.ts +8 -0
- package/server/routes/debug-diagnostics.d.ts.map +1 -0
- package/server/routes/debug-diagnostics.js +34 -0
- package/server/routes/debug-diagnostics.js.map +1 -0
- package/server/routes/debug-terminal-trace.d.ts +16 -0
- package/server/routes/debug-terminal-trace.d.ts.map +1 -0
- package/server/routes/debug-terminal-trace.js +545 -0
- package/server/routes/debug-terminal-trace.js.map +1 -0
- package/server/routes/drops.d.ts +13 -0
- package/server/routes/drops.d.ts.map +1 -0
- package/server/routes/drops.js +126 -0
- package/server/routes/drops.js.map +1 -0
- package/server/routes/file-uploads.d.ts +9 -0
- package/server/routes/file-uploads.d.ts.map +1 -0
- package/server/routes/file-uploads.js +119 -0
- package/server/routes/file-uploads.js.map +1 -0
- package/server/routes/files.d.ts +9 -0
- package/server/routes/files.d.ts.map +1 -0
- package/server/routes/files.js +441 -0
- package/server/routes/files.js.map +1 -0
- package/server/routes/filesystem.d.ts +6 -0
- package/server/routes/filesystem.d.ts.map +1 -0
- package/server/routes/filesystem.js +76 -0
- package/server/routes/filesystem.js.map +1 -0
- package/server/routes/git.d.ts +38 -0
- package/server/routes/git.d.ts.map +1 -0
- package/server/routes/git.js +585 -0
- package/server/routes/git.js.map +1 -0
- package/server/routes/healthz.d.ts +8 -0
- package/server/routes/healthz.d.ts.map +1 -0
- package/server/routes/healthz.js +24 -0
- package/server/routes/healthz.js.map +1 -0
- package/server/routes/hook.d.ts +14 -0
- package/server/routes/hook.d.ts.map +1 -0
- package/server/routes/hook.js +86 -0
- package/server/routes/hook.js.map +1 -0
- package/server/routes/ide-commands.d.ts +9 -0
- package/server/routes/ide-commands.d.ts.map +1 -0
- package/server/routes/ide-commands.js +23 -0
- package/server/routes/ide-commands.js.map +1 -0
- package/server/routes/lib/resolve-worktree.d.ts +30 -0
- package/server/routes/lib/resolve-worktree.d.ts.map +1 -0
- package/server/routes/lib/resolve-worktree.js +35 -0
- package/server/routes/lib/resolve-worktree.js.map +1 -0
- package/server/routes/open.d.ts +4 -0
- package/server/routes/open.d.ts.map +1 -0
- package/server/routes/open.js +21 -0
- package/server/routes/open.js.map +1 -0
- package/server/routes/pane-commands.d.ts +9 -0
- package/server/routes/pane-commands.d.ts.map +1 -0
- package/server/routes/pane-commands.js +23 -0
- package/server/routes/pane-commands.js.map +1 -0
- package/server/routes/projects.d.ts +15 -0
- package/server/routes/projects.d.ts.map +1 -0
- package/server/routes/projects.js +363 -0
- package/server/routes/projects.js.map +1 -0
- package/server/routes/server-notices.d.ts +4 -0
- package/server/routes/server-notices.d.ts.map +1 -0
- package/server/routes/server-notices.js +29 -0
- package/server/routes/server-notices.js.map +1 -0
- package/server/routes/service-config.d.ts +11 -0
- package/server/routes/service-config.d.ts.map +1 -0
- package/server/routes/service-config.js +64 -0
- package/server/routes/service-config.js.map +1 -0
- package/server/routes/sessions.d.ts +7 -0
- package/server/routes/sessions.d.ts.map +1 -0
- package/server/routes/sessions.js +218 -0
- package/server/routes/sessions.js.map +1 -0
- package/server/service/caffeinate.d.ts +33 -0
- package/server/service/caffeinate.d.ts.map +1 -0
- package/server/service/caffeinate.js +72 -0
- package/server/service/caffeinate.js.map +1 -0
- package/server/state/app-state.d.ts +167 -0
- package/server/state/app-state.d.ts.map +1 -0
- package/server/state/app-state.js +335 -0
- package/server/state/app-state.js.map +1 -0
- package/server/state/project-manager.d.ts +30 -0
- package/server/state/project-manager.d.ts.map +1 -0
- package/server/state/project-manager.js +128 -0
- package/server/state/project-manager.js.map +1 -0
- package/server/state/server-notices.d.ts +12 -0
- package/server/state/server-notices.d.ts.map +1 -0
- package/server/state/server-notices.js +32 -0
- package/server/state/server-notices.js.map +1 -0
- package/server/state/worktree-cache.d.ts +25 -0
- package/server/state/worktree-cache.d.ts.map +1 -0
- package/server/state/worktree-cache.js +53 -0
- package/server/state/worktree-cache.js.map +1 -0
- package/server/ws/events.d.ts +45 -0
- package/server/ws/events.d.ts.map +1 -0
- package/server/ws/events.js +134 -0
- package/server/ws/events.js.map +1 -0
- package/server/ws/keepalive.d.ts +27 -0
- package/server/ws/keepalive.d.ts.map +1 -0
- package/server/ws/keepalive.js +63 -0
- package/server/ws/keepalive.js.map +1 -0
- package/server/ws/terminal-attach.d.ts +13 -0
- package/server/ws/terminal-attach.d.ts.map +1 -0
- package/server/ws/terminal-attach.js +233 -0
- package/server/ws/terminal-attach.js.map +1 -0
- package/server/ws/terminal-flow.d.ts +17 -0
- package/server/ws/terminal-flow.d.ts.map +1 -0
- package/server/ws/terminal-flow.js +64 -0
- package/server/ws/terminal-flow.js.map +1 -0
- package/server/ws/terminal.d.ts +69 -0
- package/server/ws/terminal.d.ts.map +1 -0
- package/server/ws/terminal.js +311 -0
- package/server/ws/terminal.js.map +1 -0
- package/web/assets/EditorPane-CzzT3iYY.js +123 -0
- package/web/assets/SymbolsNerdFontMono-Regular-CwEZqMeU.woff2 +0 -0
- package/web/assets/TerminalPane-CjbYzePr.js +68 -0
- package/web/assets/TerminalPane-DkTCHfhq.css +1 -0
- package/web/assets/file-icons-JBi09j0r.js +6 -0
- package/web/assets/index-CTTkRpnn.css +2 -0
- package/web/assets/index-CmhewzMp.js +34 -0
- package/web/assets/session-resume-7f-tB-ZU.js +2 -0
- package/web/assets/terminal-trace-PuuFRybC.js +2803 -0
- package/web/assets/useVirtualKeyboard-DgJb9u9d.js +1 -0
- package/web/index.html +52 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
const defaultSpawn = (cmd, args) => {
|
|
3
|
+
spawnSync(cmd, args, { stdio: "ignore" });
|
|
4
|
+
};
|
|
5
|
+
function notify(payload, deps) {
|
|
6
|
+
if (!process.env.NOTIFY_SOCKET)
|
|
7
|
+
return;
|
|
8
|
+
const spawn = deps?.spawn ?? defaultSpawn;
|
|
9
|
+
try {
|
|
10
|
+
spawn("systemd-notify", [payload]);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
/*
|
|
14
|
+
* systemd-notify missing (e.g. NOTIFY_SOCKET leaked from an unusual env
|
|
15
|
+
* without systemd installed) must not crash the server -- the watchdog
|
|
16
|
+
* will still fire via systemd's own timeout and the operator will see
|
|
17
|
+
* the restart in journalctl.
|
|
18
|
+
*/
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function notifyReady(deps) {
|
|
22
|
+
notify("READY=1", deps);
|
|
23
|
+
}
|
|
24
|
+
export function notifyWatchdog(deps) {
|
|
25
|
+
notify("WATCHDOG=1", deps);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=sd-notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sd-notify.js","sourceRoot":"","sources":["../../src/lib/sd-notify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAoB/C,MAAM,YAAY,GAAY,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;IAC1C,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC5C,CAAC,CAAC;AAEF,SAAS,MAAM,CAAC,OAAe,EAAE,IAAmB;IAClD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa;QAAE,OAAO;IACvC,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI,YAAY,CAAC;IAC1C,IAAI,CAAC;QACH,KAAK,CAAC,gBAAgB,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP;;;;;WAKG;IACL,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAmB;IAC7C,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAmB;IAChD,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface LocalMachineAddressOptions {
|
|
2
|
+
interfaceAddresses?: Iterable<string>;
|
|
3
|
+
}
|
|
4
|
+
export declare function isLocalMachineAddress(remoteAddress: string | null, options?: LocalMachineAddressOptions): boolean;
|
|
5
|
+
export declare function collectHostInterfaceAddresses(): string[];
|
|
6
|
+
export declare function normalizeAddress(address: string | null): string | null;
|
|
7
|
+
//# sourceMappingURL=local-machine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-machine.d.ts","sourceRoot":"","sources":["../../src/net/local-machine.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,0BAA0B;IACzC,kBAAkB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CACvC;AAED,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAWT;AAED,wBAAgB,6BAA6B,IAAI,MAAM,EAAE,CAUxD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CA6BtE"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { isIP } from "node:net";
|
|
2
|
+
import { networkInterfaces } from "node:os";
|
|
3
|
+
const LOOPBACK_LITERALS = new Set(["localhost", "::1"]);
|
|
4
|
+
export function isLocalMachineAddress(remoteAddress, options = {}) {
|
|
5
|
+
const normalized = normalizeAddress(remoteAddress);
|
|
6
|
+
if (!normalized)
|
|
7
|
+
return false;
|
|
8
|
+
if (isLoopbackAddress(normalized))
|
|
9
|
+
return true;
|
|
10
|
+
const localAddresses = options.interfaceAddresses ?? collectHostInterfaceAddresses();
|
|
11
|
+
for (const address of localAddresses) {
|
|
12
|
+
if (normalizeAddress(address) === normalized)
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
export function collectHostInterfaceAddresses() {
|
|
18
|
+
const result = [];
|
|
19
|
+
for (const entries of Object.values(networkInterfaces())) {
|
|
20
|
+
if (!entries)
|
|
21
|
+
continue;
|
|
22
|
+
for (const entry of entries) {
|
|
23
|
+
const normalized = normalizeAddress(entry.address);
|
|
24
|
+
if (normalized)
|
|
25
|
+
result.push(normalized);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
export function normalizeAddress(address) {
|
|
31
|
+
if (!address)
|
|
32
|
+
return null;
|
|
33
|
+
let value = address.trim().toLowerCase();
|
|
34
|
+
if (!value)
|
|
35
|
+
return null;
|
|
36
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
37
|
+
value = value.slice(1, -1);
|
|
38
|
+
}
|
|
39
|
+
const zoneIndex = value.indexOf("%");
|
|
40
|
+
if (zoneIndex >= 0)
|
|
41
|
+
value = value.slice(0, zoneIndex);
|
|
42
|
+
const dottedMapped = /^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/i.exec(value);
|
|
43
|
+
if (dottedMapped)
|
|
44
|
+
return normalizeIpv4(dottedMapped[1]);
|
|
45
|
+
const hexMapped = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i.exec(value);
|
|
46
|
+
if (hexMapped) {
|
|
47
|
+
const high = parseInt(hexMapped[1], 16);
|
|
48
|
+
const low = parseInt(hexMapped[2], 16);
|
|
49
|
+
return [
|
|
50
|
+
(high >>> 8) & 0xff,
|
|
51
|
+
high & 0xff,
|
|
52
|
+
(low >>> 8) & 0xff,
|
|
53
|
+
low & 0xff,
|
|
54
|
+
].join(".");
|
|
55
|
+
}
|
|
56
|
+
const ipv4 = normalizeIpv4(value);
|
|
57
|
+
if (ipv4)
|
|
58
|
+
return ipv4;
|
|
59
|
+
if (isIP(value) === 6 || value === "localhost")
|
|
60
|
+
return value;
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
function normalizeIpv4(value) {
|
|
64
|
+
const parts = value.split(".");
|
|
65
|
+
if (parts.length !== 4)
|
|
66
|
+
return null;
|
|
67
|
+
const numbers = parts.map((part) => Number(part));
|
|
68
|
+
if (numbers.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
return numbers.join(".");
|
|
72
|
+
}
|
|
73
|
+
function isLoopbackAddress(address) {
|
|
74
|
+
if (LOOPBACK_LITERALS.has(address))
|
|
75
|
+
return true;
|
|
76
|
+
const ipv4 = normalizeIpv4(address);
|
|
77
|
+
return ipv4 !== null && ipv4.split(".")[0] === "127";
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=local-machine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-machine.js","sourceRoot":"","sources":["../../src/net/local-machine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;AAMxD,MAAM,UAAU,qBAAqB,CACnC,aAA4B,EAC5B,UAAsC,EAAE;IAExC,MAAM,UAAU,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9B,IAAI,iBAAiB,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAE/C,MAAM,cAAc,GAClB,OAAO,CAAC,kBAAkB,IAAI,6BAA6B,EAAE,CAAC;IAChE,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;QACrC,IAAI,gBAAgB,CAAC,OAAO,CAAC,KAAK,UAAU;YAAE,OAAO,IAAI,CAAC;IAC5D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,6BAA6B;IAC3C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC,EAAE,CAAC;QACzD,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACnD,IAAI,UAAU;gBAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAsB;IACrD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACzC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACjD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,SAAS,IAAI,CAAC;QAAE,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAEtD,MAAM,YAAY,GAAG,qCAAqC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvE,IAAI,YAAY;QAAE,OAAO,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAExD,MAAM,SAAS,GAAG,2CAA2C,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1E,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACvC,OAAO;YACL,CAAC,IAAI,KAAK,CAAC,CAAC,GAAG,IAAI;YACnB,IAAI,GAAG,IAAI;YACX,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI;YAClB,GAAG,GAAG,IAAI;SACX,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IAC7D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAClD,IACE,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,GAAG,CAAC,EACzE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe;IACxC,IAAI,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAChD,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IACpC,OAAO,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the address a per-port TCP forwarder should bind on, given the
|
|
3
|
+
* address parasor's own HTTP server is bound to:
|
|
4
|
+
* - loopback (`127.0.0.0/8` / `::1` / `localhost`) ⇒ `null` -- the viewer is on
|
|
5
|
+
* this machine, `localhost:<port>` already works, so no forwarder.
|
|
6
|
+
* - anything else (a specific address, or `0.0.0.0` / `::`) ⇒ that host
|
|
7
|
+
* verbatim. The forwarder listens on an OS-assigned free port so binding
|
|
8
|
+
* `0.0.0.0` does not collide with the dev server's own `127.0.0.1:<port>`.
|
|
9
|
+
* Exposure is ≤ parasor's own, which the viewer already reached it through.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveForwarderBindHost(parasorBindHost: string): string | null;
|
|
12
|
+
//# sourceMappingURL=reachable-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reachable-host.d.ts","sourceRoot":"","sources":["../../src/net/reachable-host.ts"],"names":[],"mappings":"AAYA;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,eAAe,EAAE,MAAM,GACtB,MAAM,GAAG,IAAI,CAGf"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const LOOPBACK_HOSTS = new Set(["localhost", "::1"]);
|
|
2
|
+
function isLoopbackHost(host) {
|
|
3
|
+
if (LOOPBACK_HOSTS.has(host))
|
|
4
|
+
return true;
|
|
5
|
+
const parts = host.split(".").map(Number);
|
|
6
|
+
return (parts.length === 4 &&
|
|
7
|
+
parts.every((n) => Number.isInteger(n) && n >= 0 && n <= 255) &&
|
|
8
|
+
parts[0] === 127);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the address a per-port TCP forwarder should bind on, given the
|
|
12
|
+
* address parasor's own HTTP server is bound to:
|
|
13
|
+
* - loopback (`127.0.0.0/8` / `::1` / `localhost`) ⇒ `null` -- the viewer is on
|
|
14
|
+
* this machine, `localhost:<port>` already works, so no forwarder.
|
|
15
|
+
* - anything else (a specific address, or `0.0.0.0` / `::`) ⇒ that host
|
|
16
|
+
* verbatim. The forwarder listens on an OS-assigned free port so binding
|
|
17
|
+
* `0.0.0.0` does not collide with the dev server's own `127.0.0.1:<port>`.
|
|
18
|
+
* Exposure is ≤ parasor's own, which the viewer already reached it through.
|
|
19
|
+
*/
|
|
20
|
+
export function resolveForwarderBindHost(parasorBindHost) {
|
|
21
|
+
if (isLoopbackHost(parasorBindHost))
|
|
22
|
+
return null;
|
|
23
|
+
return parasorBindHost;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=reachable-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reachable-host.js","sourceRoot":"","sources":["../../src/net/reachable-host.ts"],"names":[],"mappings":"AAAA,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;AAErD,SAAS,cAAc,CAAC,IAAY;IAClC,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1C,OAAO,CACL,KAAK,CAAC,MAAM,KAAK,CAAC;QAClB,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;QAC7D,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CACjB,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,wBAAwB,CACtC,eAAuB;IAEvB,IAAI,cAAc,CAAC,eAAe,CAAC;QAAE,OAAO,IAAI,CAAC;IACjD,OAAO,eAAe,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { NetworkInterfaceInfo } from "node:os";
|
|
2
|
+
export interface NetworkEndpoint {
|
|
3
|
+
category: "Local" | "LAN" | "Tailscale" | "VPN";
|
|
4
|
+
address: string;
|
|
5
|
+
iface?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface TailscaleStatus {
|
|
8
|
+
state: "running" | "stopped" | "not-installed";
|
|
9
|
+
magicDNS?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function classifyInterfaces(ifaces?: Record<string, NetworkInterfaceInfo[]>): NetworkEndpoint[];
|
|
12
|
+
export declare function checkTailscale(): Promise<TailscaleStatus>;
|
|
13
|
+
export declare function withMagicDNS(endpoints: NetworkEndpoint[], magicDNS: string | undefined): NetworkEndpoint[];
|
|
14
|
+
//# sourceMappingURL=endpoints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoints.d.ts","sourceRoot":"","sources":["../../src/network/endpoints.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAMpD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,GAAG,KAAK,GAAG,WAAW,GAAG,KAAK,CAAC;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,eAAe,CAAC;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAiBD,wBAAgB,kBAAkB,CAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,EAAE,CAAC,GAC9C,eAAe,EAAE,CAmCnB;AAUD,wBAAsB,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC,CAkB/D;AAED,wBAAgB,YAAY,CAC1B,SAAS,EAAE,eAAe,EAAE,EAC5B,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,eAAe,EAAE,CAkBnB"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { networkInterfaces } from "node:os";
|
|
3
|
+
import { promisify } from "node:util";
|
|
4
|
+
const execFileAsync = promisify(execFile);
|
|
5
|
+
const VPN_IFACE_RE = /^(utun|tun|ppp|ipsec|wg)/;
|
|
6
|
+
function isCGNAT(addr) {
|
|
7
|
+
const parts = addr.split(".").map(Number);
|
|
8
|
+
return parts[0] === 100 && parts[1] >= 64 && parts[1] <= 127;
|
|
9
|
+
}
|
|
10
|
+
function isRFC1918(addr) {
|
|
11
|
+
const parts = addr.split(".").map(Number);
|
|
12
|
+
if (parts[0] === 10)
|
|
13
|
+
return true;
|
|
14
|
+
if (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31)
|
|
15
|
+
return true;
|
|
16
|
+
if (parts[0] === 192 && parts[1] === 168)
|
|
17
|
+
return true;
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
export function classifyInterfaces(ifaces) {
|
|
21
|
+
const raw = ifaces ?? networkInterfaces();
|
|
22
|
+
const endpoints = [
|
|
23
|
+
{ category: "Local", address: "127.0.0.1" },
|
|
24
|
+
];
|
|
25
|
+
for (const [name, addrs] of Object.entries(raw)) {
|
|
26
|
+
if (!addrs)
|
|
27
|
+
continue;
|
|
28
|
+
for (const info of addrs) {
|
|
29
|
+
if (info.internal || info.family !== "IPv4")
|
|
30
|
+
continue;
|
|
31
|
+
// Tailscale: CGNAT range or tailscale0 interface
|
|
32
|
+
if (isCGNAT(info.address) || name === "tailscale0") {
|
|
33
|
+
endpoints.push({
|
|
34
|
+
category: "Tailscale",
|
|
35
|
+
address: info.address,
|
|
36
|
+
iface: name,
|
|
37
|
+
});
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
// VPN: utun/tun/ppp/ipsec/wg interface with non-CGNAT address
|
|
41
|
+
if (VPN_IFACE_RE.test(name)) {
|
|
42
|
+
endpoints.push({ category: "VPN", address: info.address, iface: name });
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
// LAN: RFC1918
|
|
46
|
+
if (isRFC1918(info.address)) {
|
|
47
|
+
endpoints.push({ category: "LAN", address: info.address, iface: name });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return endpoints;
|
|
52
|
+
}
|
|
53
|
+
function extractMagicDNS(data) {
|
|
54
|
+
if (!data || typeof data !== "object")
|
|
55
|
+
return undefined;
|
|
56
|
+
const self = data.Self;
|
|
57
|
+
const dnsName = self?.DNSName;
|
|
58
|
+
if (typeof dnsName !== "string" || dnsName.length === 0)
|
|
59
|
+
return undefined;
|
|
60
|
+
return dnsName.replace(/\.$/, "");
|
|
61
|
+
}
|
|
62
|
+
export async function checkTailscale() {
|
|
63
|
+
try {
|
|
64
|
+
const { stdout } = await execFileAsync("tailscale", ["status", "--json"], {
|
|
65
|
+
timeout: 3000,
|
|
66
|
+
});
|
|
67
|
+
const data = JSON.parse(stdout);
|
|
68
|
+
if (data.BackendState !== "Running")
|
|
69
|
+
return { state: "stopped" };
|
|
70
|
+
const magicDNS = extractMagicDNS(data);
|
|
71
|
+
return magicDNS ? { state: "running", magicDNS } : { state: "running" };
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
const isNotFound = err instanceof Error &&
|
|
75
|
+
("code" in err
|
|
76
|
+
? err.code === "ENOENT"
|
|
77
|
+
: false);
|
|
78
|
+
if (isNotFound)
|
|
79
|
+
return { state: "not-installed" };
|
|
80
|
+
return { state: "stopped" };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function withMagicDNS(endpoints, magicDNS) {
|
|
84
|
+
if (!magicDNS)
|
|
85
|
+
return endpoints;
|
|
86
|
+
const entry = {
|
|
87
|
+
category: "Tailscale",
|
|
88
|
+
address: magicDNS,
|
|
89
|
+
iface: "MagicDNS",
|
|
90
|
+
};
|
|
91
|
+
const result = [];
|
|
92
|
+
let inserted = false;
|
|
93
|
+
for (const e of endpoints) {
|
|
94
|
+
result.push(e);
|
|
95
|
+
if (!inserted && e.category === "Tailscale" && e.iface !== "MagicDNS") {
|
|
96
|
+
result.push(entry);
|
|
97
|
+
inserted = true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!inserted)
|
|
101
|
+
result.push(entry);
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=endpoints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoints.js","sourceRoot":"","sources":["../../src/network/endpoints.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { NetworkEndpoint } from "./endpoints.js";
|
|
2
|
+
export declare function selectQrEndpoint(endpoints: NetworkEndpoint[], iface?: string): NetworkEndpoint | undefined;
|
|
3
|
+
export declare function buildAuthUrl(address: string, port: number, authMode: "token" | "allowlist" | "none", token: string): string;
|
|
4
|
+
export declare function buildPairingUrl(address: string, port: number, token: string, path?: string): string;
|
|
5
|
+
export declare function renderQrLines(url: string): string[];
|
|
6
|
+
export interface QrSectionOptions {
|
|
7
|
+
endpoints: NetworkEndpoint[];
|
|
8
|
+
port: number;
|
|
9
|
+
authMode: "token" | "allowlist" | "none";
|
|
10
|
+
token?: string;
|
|
11
|
+
makeAccessUrl?: (endpoint: NetworkEndpoint) => string;
|
|
12
|
+
iface?: string;
|
|
13
|
+
clickable?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function buildQrSection({ endpoints, port, authMode, token, makeAccessUrl, iface, clickable, }: QrSectionOptions): string[];
|
|
16
|
+
//# sourceMappingURL=qr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr.d.ts","sourceRoot":"","sources":["../../src/network/qr.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKtD,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,eAAe,EAAE,EAC5B,KAAK,CAAC,EAAE,MAAM,GACb,eAAe,GAAG,SAAS,CAU7B;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,GAAG,WAAW,GAAG,MAAM,EACxC,KAAK,EAAE,MAAM,GACZ,MAAM,CAGR;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,SAAM,GACT,MAAM,CAIR;AA6BD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAMnD;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,GAAG,WAAW,GAAG,MAAM,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,MAAM,CAAC;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAiBD,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,aAAa,EACb,KAAK,EACL,SAAiB,GAClB,EAAE,gBAAgB,GAAG,MAAM,EAAE,CA6B7B"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import qrcodeTerminal from "qrcode-terminal";
|
|
2
|
+
// macOS virtual / ephemeral interfaces we never want to surface to a phone.
|
|
3
|
+
const VIRTUAL_IFACE_RE = /^(bridge|awdl|llw|anpi|ap|pktap|gif|stf)/;
|
|
4
|
+
export function selectQrEndpoint(endpoints, iface) {
|
|
5
|
+
if (iface) {
|
|
6
|
+
return endpoints.find((e) => e.iface === iface);
|
|
7
|
+
}
|
|
8
|
+
const tailscale = endpoints.find((e) => e.category === "Tailscale");
|
|
9
|
+
if (tailscale)
|
|
10
|
+
return tailscale;
|
|
11
|
+
return endpoints.find((e) => e.category === "LAN" && (!e.iface || !VIRTUAL_IFACE_RE.test(e.iface)));
|
|
12
|
+
}
|
|
13
|
+
export function buildAuthUrl(address, port, authMode, token) {
|
|
14
|
+
const base = `http://${address}:${port}`;
|
|
15
|
+
return authMode === "token" ? `${base}/?t=${token}` : base;
|
|
16
|
+
}
|
|
17
|
+
export function buildPairingUrl(address, port, token, path = "/") {
|
|
18
|
+
const url = new URL(`http://${address}:${port}${normalizeAccessPath(path)}`);
|
|
19
|
+
url.searchParams.set("t", token);
|
|
20
|
+
return url.toString();
|
|
21
|
+
}
|
|
22
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: access paths must reject terminal/header control bytes.
|
|
23
|
+
const CONTROL_CHAR_RE = /[\x00-\x1f\x7f]/;
|
|
24
|
+
function normalizeAccessPath(path) {
|
|
25
|
+
if (!path.startsWith("/") ||
|
|
26
|
+
path.startsWith("//") ||
|
|
27
|
+
path.includes("\\") ||
|
|
28
|
+
CONTROL_CHAR_RE.test(path)) {
|
|
29
|
+
throw new Error("access URL path must be same-origin relative");
|
|
30
|
+
}
|
|
31
|
+
return path;
|
|
32
|
+
}
|
|
33
|
+
function buildDefaultAccessUrl(address, port, authMode, token) {
|
|
34
|
+
if (authMode === "token" && !token) {
|
|
35
|
+
throw new Error("token or makeAccessUrl is required for token auth URLs");
|
|
36
|
+
}
|
|
37
|
+
return buildAuthUrl(address, port, authMode, token ?? "");
|
|
38
|
+
}
|
|
39
|
+
export function renderQrLines(url) {
|
|
40
|
+
let output = "";
|
|
41
|
+
qrcodeTerminal.generate(url, { small: true }, (rendered) => {
|
|
42
|
+
output = rendered;
|
|
43
|
+
});
|
|
44
|
+
return output.replace(/\n$/, "").split("\n");
|
|
45
|
+
}
|
|
46
|
+
/*
|
|
47
|
+
* OSC 8 hyperlink. Refuse to wrap when the URL or label contains a
|
|
48
|
+
* terminal control character, since those would break the escape
|
|
49
|
+
* sequence (and could be used to inject other escapes if the input is
|
|
50
|
+
* untrusted).
|
|
51
|
+
*/
|
|
52
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: OSC8 labels/URLs must reject terminal control bytes.
|
|
53
|
+
const TERMINAL_CONTROL_RE = /[\x00-\x1f\x7f]/;
|
|
54
|
+
const OSC8_HYPERLINK = (url, label) => {
|
|
55
|
+
if (TERMINAL_CONTROL_RE.test(url) || TERMINAL_CONTROL_RE.test(label)) {
|
|
56
|
+
return label;
|
|
57
|
+
}
|
|
58
|
+
return `\x1b]8;;${url}\x1b\\${label}\x1b]8;;\x1b\\`;
|
|
59
|
+
};
|
|
60
|
+
export function buildQrSection({ endpoints, port, authMode, token, makeAccessUrl, iface, clickable = false, }) {
|
|
61
|
+
const target = selectQrEndpoint(endpoints, iface);
|
|
62
|
+
if (!target) {
|
|
63
|
+
if (iface) {
|
|
64
|
+
const candidates = endpoints
|
|
65
|
+
.map((e) => e.iface)
|
|
66
|
+
.filter(Boolean)
|
|
67
|
+
.join(", ");
|
|
68
|
+
return [
|
|
69
|
+
`QR: interface "${iface}" not found. Available: ${candidates || "(none)"}`,
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
return [
|
|
73
|
+
"QR: no remote endpoint detected. Run `tailscale up` or connect to a LAN.",
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
const url = makeAccessUrl?.(target) ??
|
|
77
|
+
buildDefaultAccessUrl(target.address, port, authMode, token);
|
|
78
|
+
const label = target.iface
|
|
79
|
+
? `${target.category} (${target.iface})`
|
|
80
|
+
: target.category;
|
|
81
|
+
const linkedUrl = clickable ? OSC8_HYPERLINK(url, url) : url;
|
|
82
|
+
return [
|
|
83
|
+
`Scan to open on mobile -- ${label}`,
|
|
84
|
+
` ${linkedUrl}`,
|
|
85
|
+
"",
|
|
86
|
+
...renderQrLines(url),
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=qr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr.js","sourceRoot":"","sources":["../../src/network/qr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface ForwardedPortSpec {
|
|
2
|
+
port: number;
|
|
3
|
+
bindsAll: boolean;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Per-port raw TCP forwarder (Tier A .). For each detected
|
|
7
|
+
* dev-server port that is *not* already bound to all interfaces, a
|
|
8
|
+
* `net.Server` listens on `<bindHost>:0` (an OS-assigned free port) and pipes
|
|
9
|
+
* every connection byte-for-byte to `localhost:<devPort>` (both loopback
|
|
10
|
+
* families -- a `localhost` dev server often binds only `::1`). No HTTP parsing
|
|
11
|
+
* -- HMR/WebSocket pass through transparently because it is L4. Using a free
|
|
12
|
+
* listen port means binding `0.0.0.0` does not collide with the dev server's
|
|
13
|
+
* own `localhost:<devPort>`.
|
|
14
|
+
*
|
|
15
|
+
* `bindHost === null` ⇒ the forwarder is inert: parasor is loopback-bound so
|
|
16
|
+
* the viewer is on this machine and `localhost:<port>` already works. `sync`
|
|
17
|
+
* is a no-op and `getReachablePort` always returns `null`.
|
|
18
|
+
*
|
|
19
|
+
* Forwarders are keyed by `projectId` -> `devPort` so a project going inactive
|
|
20
|
+
* (next `sync` with `[]`) tears its forwarders down.
|
|
21
|
+
*/
|
|
22
|
+
export declare class PortForwarder {
|
|
23
|
+
private readonly bindHost;
|
|
24
|
+
private readonly byProject;
|
|
25
|
+
private onChange;
|
|
26
|
+
constructor(bindHost: string | null);
|
|
27
|
+
isInert(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Register a callback invoked whenever a forwarder finishes binding (its
|
|
30
|
+
* `reachablePort` becomes available) or its bind errors (it is torn down).
|
|
31
|
+
* `PortForwarder`'s state changes out-of-band of `sync` here -- `listen` is
|
|
32
|
+
* async -- so callers that mirror `getReachablePort` results (e.g. the
|
|
33
|
+
* runtime's `ports-updated` broadcast) must re-read on this signal.
|
|
34
|
+
*/
|
|
35
|
+
setOnChange(cb: (projectId: string) => void): void;
|
|
36
|
+
sync(projectId: string, ports: ForwardedPortSpec[]): void;
|
|
37
|
+
/**
|
|
38
|
+
* The OS-assigned listen port for `devPort` in `projectId`, or `null` if no
|
|
39
|
+
* forwarder exists, it has not finished binding, or its bind errored.
|
|
40
|
+
*/
|
|
41
|
+
getReachablePort(projectId: string, devPort: number): number | null;
|
|
42
|
+
stop(): void;
|
|
43
|
+
private teardownForwarder;
|
|
44
|
+
private createForwarder;
|
|
45
|
+
private wirePair;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=forwarder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forwarder.d.ts","sourceRoot":"","sources":["../../src/port-forwarder/forwarder.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CACnB;AAYD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,aAAa;IAIZ,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAHrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiD;IAC3E,OAAO,CAAC,QAAQ,CAA8C;gBAEjC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAEpD,OAAO,IAAI,OAAO;IAIlB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAIlD,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,GAAG,IAAI;IAqBzD;;;OAGG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAOnE,IAAI,IAAI,IAAI;IASZ,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,eAAe;IAsDvB,OAAO,CAAC,QAAQ;CAuBjB"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import net from "node:net";
|
|
2
|
+
/**
|
|
3
|
+
* Per-port raw TCP forwarder (Tier A .). For each detected
|
|
4
|
+
* dev-server port that is *not* already bound to all interfaces, a
|
|
5
|
+
* `net.Server` listens on `<bindHost>:0` (an OS-assigned free port) and pipes
|
|
6
|
+
* every connection byte-for-byte to `localhost:<devPort>` (both loopback
|
|
7
|
+
* families -- a `localhost` dev server often binds only `::1`). No HTTP parsing
|
|
8
|
+
* -- HMR/WebSocket pass through transparently because it is L4. Using a free
|
|
9
|
+
* listen port means binding `0.0.0.0` does not collide with the dev server's
|
|
10
|
+
* own `localhost:<devPort>`.
|
|
11
|
+
*
|
|
12
|
+
* `bindHost === null` ⇒ the forwarder is inert: parasor is loopback-bound so
|
|
13
|
+
* the viewer is on this machine and `localhost:<port>` already works. `sync`
|
|
14
|
+
* is a no-op and `getReachablePort` always returns `null`.
|
|
15
|
+
*
|
|
16
|
+
* Forwarders are keyed by `projectId` -> `devPort` so a project going inactive
|
|
17
|
+
* (next `sync` with `[]`) tears its forwarders down.
|
|
18
|
+
*/
|
|
19
|
+
export class PortForwarder {
|
|
20
|
+
bindHost;
|
|
21
|
+
byProject = new Map();
|
|
22
|
+
onChange = null;
|
|
23
|
+
constructor(bindHost) {
|
|
24
|
+
this.bindHost = bindHost;
|
|
25
|
+
}
|
|
26
|
+
isInert() {
|
|
27
|
+
return this.bindHost === null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Register a callback invoked whenever a forwarder finishes binding (its
|
|
31
|
+
* `reachablePort` becomes available) or its bind errors (it is torn down).
|
|
32
|
+
* `PortForwarder`'s state changes out-of-band of `sync` here -- `listen` is
|
|
33
|
+
* async -- so callers that mirror `getReachablePort` results (e.g. the
|
|
34
|
+
* runtime's `ports-updated` broadcast) must re-read on this signal.
|
|
35
|
+
*/
|
|
36
|
+
setOnChange(cb) {
|
|
37
|
+
this.onChange = cb;
|
|
38
|
+
}
|
|
39
|
+
sync(projectId, ports) {
|
|
40
|
+
if (this.bindHost === null)
|
|
41
|
+
return;
|
|
42
|
+
const wanted = new Set(ports.filter((p) => !p.bindsAll).map((p) => p.port));
|
|
43
|
+
const current = this.byProject.get(projectId) ?? new Map();
|
|
44
|
+
for (const [devPort, forwarder] of current) {
|
|
45
|
+
if (!wanted.has(devPort)) {
|
|
46
|
+
this.teardownForwarder(forwarder);
|
|
47
|
+
current.delete(devPort);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
for (const devPort of wanted) {
|
|
51
|
+
if (current.has(devPort))
|
|
52
|
+
continue;
|
|
53
|
+
const forwarder = this.createForwarder(projectId, devPort);
|
|
54
|
+
if (forwarder)
|
|
55
|
+
current.set(devPort, forwarder);
|
|
56
|
+
}
|
|
57
|
+
if (current.size === 0)
|
|
58
|
+
this.byProject.delete(projectId);
|
|
59
|
+
else
|
|
60
|
+
this.byProject.set(projectId, current);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The OS-assigned listen port for `devPort` in `projectId`, or `null` if no
|
|
64
|
+
* forwarder exists, it has not finished binding, or its bind errored.
|
|
65
|
+
*/
|
|
66
|
+
getReachablePort(projectId, devPort) {
|
|
67
|
+
if (this.bindHost === null)
|
|
68
|
+
return null;
|
|
69
|
+
const forwarder = this.byProject.get(projectId)?.get(devPort);
|
|
70
|
+
if (!forwarder?.server.listening)
|
|
71
|
+
return null;
|
|
72
|
+
return forwarder.reachablePort;
|
|
73
|
+
}
|
|
74
|
+
stop() {
|
|
75
|
+
for (const forwarders of this.byProject.values()) {
|
|
76
|
+
for (const forwarder of forwarders.values()) {
|
|
77
|
+
this.teardownForwarder(forwarder);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
this.byProject.clear();
|
|
81
|
+
}
|
|
82
|
+
teardownForwarder(forwarder) {
|
|
83
|
+
forwarder.server.close();
|
|
84
|
+
for (const socket of forwarder.sockets)
|
|
85
|
+
socket.destroy();
|
|
86
|
+
forwarder.sockets.clear();
|
|
87
|
+
}
|
|
88
|
+
createForwarder(projectId, devPort) {
|
|
89
|
+
const bindHost = this.bindHost;
|
|
90
|
+
if (bindHost === null)
|
|
91
|
+
return null;
|
|
92
|
+
const sockets = new Set();
|
|
93
|
+
const server = net.createServer((clientSocket) => {
|
|
94
|
+
// `localhost`, not `127.0.0.1`: a dev server started on `localhost` often
|
|
95
|
+
// binds only `::1` (Node's default resolution order on macOS), so an
|
|
96
|
+
// IPv4-only upstream would `ECONNREFUSED`. Node ≥18 `autoSelectFamily`
|
|
97
|
+
// tries both loopback families.
|
|
98
|
+
const upstream = net.connect(devPort, "localhost");
|
|
99
|
+
this.wirePair(sockets, clientSocket, upstream);
|
|
100
|
+
});
|
|
101
|
+
const forwarder = {
|
|
102
|
+
server,
|
|
103
|
+
devPort,
|
|
104
|
+
reachablePort: null,
|
|
105
|
+
sockets,
|
|
106
|
+
};
|
|
107
|
+
server.on("listening", () => {
|
|
108
|
+
const addr = server.address();
|
|
109
|
+
forwarder.reachablePort =
|
|
110
|
+
addr && typeof addr === "object" ? addr.port : null;
|
|
111
|
+
// The listen completed asynchronously, after the `sync` tick -- signal
|
|
112
|
+
// upward so any mirrored reachability state is re-read and re-broadcast.
|
|
113
|
+
this.onChange?.(projectId);
|
|
114
|
+
});
|
|
115
|
+
server.on("error", (err) => {
|
|
116
|
+
// Best effort: a preview forwarder must never crash the server. On any
|
|
117
|
+
// listen error (EADDRINUSE is unlikely on a free port) drop this
|
|
118
|
+
// forwarder; the dev server stays loopback-only and the port is
|
|
119
|
+
// reported unreachable.
|
|
120
|
+
if (err.code !== "EADDRINUSE") {
|
|
121
|
+
console.warn(`[port-forwarder] failed to bind ${bindHost} for dev port ${devPort}: ${err.message}`);
|
|
122
|
+
}
|
|
123
|
+
let removed = false;
|
|
124
|
+
for (const [pid, forwarders] of this.byProject) {
|
|
125
|
+
if (forwarders.get(devPort) === forwarder) {
|
|
126
|
+
this.teardownForwarder(forwarder);
|
|
127
|
+
forwarders.delete(devPort);
|
|
128
|
+
if (forwarders.size === 0)
|
|
129
|
+
this.byProject.delete(pid);
|
|
130
|
+
removed = true;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (removed)
|
|
134
|
+
this.onChange?.(projectId);
|
|
135
|
+
});
|
|
136
|
+
server.listen(0, bindHost);
|
|
137
|
+
return forwarder;
|
|
138
|
+
}
|
|
139
|
+
wirePair(sockets, clientSocket, upstream) {
|
|
140
|
+
sockets.add(clientSocket);
|
|
141
|
+
sockets.add(upstream);
|
|
142
|
+
const closePeer = (peer) => {
|
|
143
|
+
peer.destroy();
|
|
144
|
+
};
|
|
145
|
+
clientSocket.on("error", () => closePeer(upstream));
|
|
146
|
+
upstream.on("error", () => closePeer(clientSocket));
|
|
147
|
+
clientSocket.on("close", () => {
|
|
148
|
+
sockets.delete(clientSocket);
|
|
149
|
+
closePeer(upstream);
|
|
150
|
+
});
|
|
151
|
+
upstream.on("close", () => {
|
|
152
|
+
sockets.delete(upstream);
|
|
153
|
+
closePeer(clientSocket);
|
|
154
|
+
});
|
|
155
|
+
clientSocket.pipe(upstream);
|
|
156
|
+
upstream.pipe(clientSocket);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=forwarder.js.map
|