@elie-laloum/outpost 11.1.2 → 11.2.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/CHANGELOG.md +34 -0
- package/README.md +2 -1
- package/SECURITY.md +5 -1
- package/dist/adapters/agents/antigravity/antigravity-adapter.js +9 -0
- package/dist/adapters/agents/antigravity/antigravity-adapter.js.map +1 -1
- package/dist/adapters/agents/antigravity/antigravity-hook-plan.d.ts +3 -0
- package/dist/adapters/agents/antigravity/antigravity-hook-plan.js +39 -0
- package/dist/adapters/agents/antigravity/antigravity-hook-plan.js.map +1 -0
- package/dist/adapters/agents/antigravity/antigravity-hooks.constants.d.ts +3 -0
- package/dist/adapters/agents/antigravity/antigravity-hooks.constants.js +394 -0
- package/dist/adapters/agents/antigravity/antigravity-hooks.constants.js.map +1 -0
- package/dist/adapters/agents/antigravity/antigravity-hooks.d.ts +2 -0
- package/dist/adapters/agents/antigravity/antigravity-hooks.js +6 -0
- package/dist/adapters/agents/antigravity/antigravity-hooks.js.map +1 -0
- package/dist/adapters/agents/antigravity/antigravity-hooks.types.d.ts +114 -0
- package/dist/adapters/agents/antigravity/antigravity-hooks.types.js +2 -0
- package/dist/adapters/agents/antigravity/antigravity-hooks.types.js.map +1 -0
- package/dist/adapters/agents/antigravity/antigravity.types.d.ts +1 -0
- package/dist/adapters/agents/antigravity/antigravity.types.js.map +1 -1
- package/dist/adapters/agents/authentication.js +1 -0
- package/dist/adapters/agents/authentication.js.map +1 -1
- package/dist/adapters/agents/claude/claude-adapter.js +15 -0
- package/dist/adapters/agents/claude/claude-adapter.js.map +1 -1
- package/dist/adapters/agents/claude/claude-hook-plan.constants.d.ts +1 -0
- package/dist/adapters/agents/claude/claude-hook-plan.constants.js +20 -0
- package/dist/adapters/agents/claude/claude-hook-plan.constants.js.map +1 -0
- package/dist/adapters/agents/claude/claude-hook-plan.d.ts +4 -0
- package/dist/adapters/agents/claude/claude-hook-plan.js +60 -0
- package/dist/adapters/agents/claude/claude-hook-plan.js.map +1 -0
- package/dist/adapters/agents/claude/claude-hooks.constants.d.ts +3 -0
- package/dist/adapters/agents/claude/claude-hooks.constants.js +2968 -0
- package/dist/adapters/agents/claude/claude-hooks.constants.js.map +1 -0
- package/dist/adapters/agents/claude/claude-hooks.d.ts +2 -0
- package/dist/adapters/agents/claude/claude-hooks.js +6 -0
- package/dist/adapters/agents/claude/claude-hooks.js.map +1 -0
- package/dist/adapters/agents/claude/claude-hooks.types.d.ts +900 -0
- package/dist/adapters/agents/claude/claude-hooks.types.js +2 -0
- package/dist/adapters/agents/claude/claude-hooks.types.js.map +1 -0
- package/dist/adapters/agents/claude/claude-profile.d.ts +1 -0
- package/dist/adapters/agents/claude/claude-profile.js +23 -11
- package/dist/adapters/agents/claude/claude-profile.js.map +1 -1
- package/dist/adapters/agents/codex/codex-adapter.js +17 -1
- package/dist/adapters/agents/codex/codex-adapter.js.map +1 -1
- package/dist/adapters/agents/codex/codex-authentication.js +1 -0
- package/dist/adapters/agents/codex/codex-authentication.js.map +1 -1
- package/dist/adapters/agents/codex/codex-conversations.constants.d.ts +1 -0
- package/dist/adapters/agents/codex/codex-conversations.constants.js +2 -0
- package/dist/adapters/agents/codex/codex-conversations.constants.js.map +1 -0
- package/dist/adapters/agents/codex/codex-conversations.js +8 -5
- package/dist/adapters/agents/codex/codex-conversations.js.map +1 -1
- package/dist/adapters/agents/codex/codex-hook-plan.d.ts +3 -0
- package/dist/adapters/agents/codex/codex-hook-plan.js +72 -0
- package/dist/adapters/agents/codex/codex-hook-plan.js.map +1 -0
- package/dist/adapters/agents/codex/codex-hooks.constants.d.ts +3 -0
- package/dist/adapters/agents/codex/codex-hooks.constants.js +942 -0
- package/dist/adapters/agents/codex/codex-hooks.constants.js.map +1 -0
- package/dist/adapters/agents/codex/codex-hooks.d.ts +2 -0
- package/dist/adapters/agents/codex/codex-hooks.js +6 -0
- package/dist/adapters/agents/codex/codex-hooks.js.map +1 -0
- package/dist/adapters/agents/codex/codex-hooks.types.d.ts +255 -0
- package/dist/adapters/agents/codex/codex-hooks.types.js +2 -0
- package/dist/adapters/agents/codex/codex-hooks.types.js.map +1 -0
- package/dist/adapters/agents/codex/codex-provider.js +2 -2
- package/dist/adapters/agents/codex/codex-provider.js.map +1 -1
- package/dist/adapters/agents/copilot/copilot-adapter.js +14 -0
- package/dist/adapters/agents/copilot/copilot-adapter.js.map +1 -1
- package/dist/adapters/agents/copilot/copilot-hook-plan.d.ts +3 -0
- package/dist/adapters/agents/copilot/copilot-hook-plan.js +26 -0
- package/dist/adapters/agents/copilot/copilot-hook-plan.js.map +1 -0
- package/dist/adapters/agents/copilot/copilot-hooks.constants.d.ts +3 -0
- package/dist/adapters/agents/copilot/copilot-hooks.constants.js +528 -0
- package/dist/adapters/agents/copilot/copilot-hooks.constants.js.map +1 -0
- package/dist/adapters/agents/copilot/copilot-hooks.d.ts +2 -0
- package/dist/adapters/agents/copilot/copilot-hooks.js +6 -0
- package/dist/adapters/agents/copilot/copilot-hooks.js.map +1 -0
- package/dist/adapters/agents/copilot/copilot-hooks.types.d.ts +166 -0
- package/dist/adapters/agents/copilot/copilot-hooks.types.js +2 -0
- package/dist/adapters/agents/copilot/copilot-hooks.types.js.map +1 -0
- package/dist/adapters/agents/copilot/copilot.types.d.ts +1 -0
- package/dist/adapters/agents/copilot/copilot.types.js.map +1 -1
- package/dist/adapters/agents/hook-groups.d.ts +2 -0
- package/dist/adapters/agents/hook-groups.js +17 -0
- package/dist/adapters/agents/hook-groups.js.map +1 -0
- package/dist/adapters/agents/kimi/kimi-adapter.js +16 -1
- package/dist/adapters/agents/kimi/kimi-adapter.js.map +1 -1
- package/dist/adapters/agents/kimi/kimi-hook-plan.d.ts +3 -0
- package/dist/adapters/agents/kimi/kimi-hook-plan.js +33 -0
- package/dist/adapters/agents/kimi/kimi-hook-plan.js.map +1 -0
- package/dist/adapters/agents/kimi/kimi-hooks.constants.d.ts +3 -0
- package/dist/adapters/agents/kimi/kimi-hooks.constants.js +747 -0
- package/dist/adapters/agents/kimi/kimi-hooks.constants.js.map +1 -0
- package/dist/adapters/agents/kimi/kimi-hooks.d.ts +2 -0
- package/dist/adapters/agents/kimi/kimi-hooks.js +6 -0
- package/dist/adapters/agents/kimi/kimi-hooks.js.map +1 -0
- package/dist/adapters/agents/kimi/kimi-hooks.types.d.ts +226 -0
- package/dist/adapters/agents/kimi/kimi-hooks.types.js +2 -0
- package/dist/adapters/agents/kimi/kimi-hooks.types.js.map +1 -0
- package/dist/adapters/agents/kimi/kimi-request.js +2 -0
- package/dist/adapters/agents/kimi/kimi-request.js.map +1 -1
- package/dist/adapters/agents/kimi/kimi.constants.d.ts +1 -0
- package/dist/adapters/agents/kimi/kimi.constants.js +1 -0
- package/dist/adapters/agents/kimi/kimi.constants.js.map +1 -1
- package/dist/adapters/agents/kimi/kimi.types.d.ts +1 -0
- package/dist/adapters/agents/kimi/kimi.types.js.map +1 -1
- package/dist/adapters/agents/native-hooks.d.ts +4 -0
- package/dist/adapters/agents/native-hooks.js +63 -0
- package/dist/adapters/agents/native-hooks.js.map +1 -0
- package/dist/adapters/agents/native-hooks.types.d.ts +22 -0
- package/dist/adapters/agents/native-hooks.types.js +2 -0
- package/dist/adapters/agents/native-hooks.types.js.map +1 -0
- package/dist/adapters/agents/settings.types.d.ts +2 -0
- package/dist/adapters/agents/settings.types.js.map +1 -1
- package/dist/adapters/decisions/system-one-provider.constants.d.ts +1 -1
- package/dist/adapters/decisions/system-one-provider.constants.js +1 -1
- package/dist/adapters/decisions/system-one-provider.constants.js.map +1 -1
- package/dist/adapters/decisions/system-one-provider.js +8 -21
- package/dist/adapters/decisions/system-one-provider.js.map +1 -1
- package/dist/adapters/models/anthropic-model-provider.constants.d.ts +1 -0
- package/dist/adapters/models/anthropic-model-provider.constants.js +4 -0
- package/dist/adapters/models/anthropic-model-provider.constants.js.map +1 -1
- package/dist/adapters/models/anthropic-model-provider.js +7 -1
- package/dist/adapters/models/anthropic-model-provider.js.map +1 -1
- package/dist/adapters/models/http-failure.d.ts +3 -0
- package/dist/adapters/models/http-failure.js +43 -0
- package/dist/adapters/models/http-failure.js.map +1 -0
- package/dist/adapters/models/http-provider.js +14 -20
- package/dist/adapters/models/http-provider.js.map +1 -1
- package/dist/adapters/models/model-protocol.types.d.ts +1 -0
- package/dist/adapters/models/model-protocol.types.js.map +1 -1
- package/dist/adapters/models/model.constants.d.ts +2 -0
- package/dist/adapters/models/model.constants.js +17 -0
- package/dist/adapters/models/model.constants.js.map +1 -1
- package/dist/adapters/models/openai-chat-stream.js +3 -1
- package/dist/adapters/models/openai-chat-stream.js.map +1 -1
- package/dist/adapters/models/openai-responses.js +4 -0
- package/dist/adapters/models/openai-responses.js.map +1 -1
- package/dist/adapters/secrets/aws.js +5 -4
- package/dist/adapters/secrets/aws.js.map +1 -1
- package/dist/adapters/secrets/azure.constants.d.ts +1 -0
- package/dist/adapters/secrets/azure.constants.js +2 -0
- package/dist/adapters/secrets/azure.constants.js.map +1 -0
- package/dist/adapters/secrets/azure.js +2 -1
- package/dist/adapters/secrets/azure.js.map +1 -1
- package/dist/adapters/secrets/gcp.constants.d.ts +1 -0
- package/dist/adapters/secrets/gcp.constants.js +2 -0
- package/dist/adapters/secrets/gcp.constants.js.map +1 -0
- package/dist/adapters/secrets/gcp.js +11 -9
- package/dist/adapters/secrets/gcp.js.map +1 -1
- package/dist/adapters/secrets/infisical.js +3 -2
- package/dist/adapters/secrets/infisical.js.map +1 -1
- package/dist/adapters/secrets/onepassword.constants.d.ts +1 -0
- package/dist/adapters/secrets/onepassword.constants.js +2 -0
- package/dist/adapters/secrets/onepassword.constants.js.map +1 -0
- package/dist/adapters/secrets/onepassword.js +2 -1
- package/dist/adapters/secrets/onepassword.js.map +1 -1
- package/dist/adapters/secrets/secret-source.js +3 -1
- package/dist/adapters/secrets/secret-source.js.map +1 -1
- package/dist/adapters/secrets/vault-response.js +5 -5
- package/dist/adapters/secrets/vault-response.js.map +1 -1
- package/dist/adapters/secrets/vault.js +4 -3
- package/dist/adapters/secrets/vault.js.map +1 -1
- package/dist/adapters/testing/scripted-agent.d.ts +3 -1
- package/dist/adapters/testing/scripted-agent.js +3 -1
- package/dist/adapters/testing/scripted-agent.js.map +1 -1
- package/dist/adapters/tools/edit-tools.js +3 -3
- package/dist/adapters/tools/edit-tools.js.map +1 -1
- package/dist/adapters/tools/git-tools.js +16 -1
- package/dist/adapters/tools/git-tools.js.map +1 -1
- package/dist/adapters/tools/mcp-launcher.constants.d.ts +1 -1
- package/dist/adapters/tools/mcp-launcher.constants.js +29 -7
- package/dist/adapters/tools/mcp-launcher.constants.js.map +1 -1
- package/dist/adapters/tools/mcp-resources.js +5 -1
- package/dist/adapters/tools/mcp-resources.js.map +1 -1
- package/dist/adapters/tools/mcp.constants.d.ts +0 -6
- package/dist/adapters/tools/mcp.constants.js +0 -6
- package/dist/adapters/tools/mcp.constants.js.map +1 -1
- package/dist/adapters/tools/mcp.js +1 -0
- package/dist/adapters/tools/mcp.js.map +1 -1
- package/dist/adapters/tools/sandbox-files.constants.d.ts +1 -0
- package/dist/adapters/tools/sandbox-files.constants.js +17 -0
- package/dist/adapters/tools/sandbox-files.constants.js.map +1 -0
- package/dist/adapters/tools/sandbox-files.d.ts +1 -0
- package/dist/adapters/tools/sandbox-files.js +14 -1
- package/dist/adapters/tools/sandbox-files.js.map +1 -1
- package/dist/adapters/tools/tools.constants.js +1 -0
- package/dist/adapters/tools/tools.constants.js.map +1 -1
- package/dist/adapters/triggers/github-webhook.js +14 -11
- package/dist/adapters/triggers/github-webhook.js.map +1 -1
- package/dist/adapters/triggers/gitlab-webhook.js +16 -13
- package/dist/adapters/triggers/gitlab-webhook.js.map +1 -1
- package/dist/adapters/triggers/slack-request.js +10 -7
- package/dist/adapters/triggers/slack-request.js.map +1 -1
- package/dist/adapters/triggers/standard-webhook.js +10 -7
- package/dist/adapters/triggers/standard-webhook.js.map +1 -1
- package/dist/application/agent-authentication.js +4 -1
- package/dist/application/agent-authentication.js.map +1 -1
- package/dist/application/agent-turn.js +20 -5
- package/dist/application/agent-turn.js.map +1 -1
- package/dist/application/cli-hooks.constants.d.ts +2 -0
- package/dist/application/cli-hooks.constants.js +69 -0
- package/dist/application/cli-hooks.constants.js.map +1 -0
- package/dist/application/cli-hooks.d.ts +3 -0
- package/dist/application/cli-hooks.js +168 -0
- package/dist/application/cli-hooks.js.map +1 -0
- package/dist/application/cli-steering.js +33 -2
- package/dist/application/cli-steering.js.map +1 -1
- package/dist/application/custom-turn.js +10 -1
- package/dist/application/custom-turn.js.map +1 -1
- package/dist/application/diagnostic-probe.d.ts +1 -1
- package/dist/application/diagnostic-probe.js +7 -3
- package/dist/application/diagnostic-probe.js.map +1 -1
- package/dist/application/dispatch-observation.js +4 -0
- package/dist/application/dispatch-observation.js.map +1 -1
- package/dist/application/doctor-agent.d.ts +1 -1
- package/dist/application/doctor-agent.js +2 -2
- package/dist/application/doctor-agent.js.map +1 -1
- package/dist/application/doctor-deadline.d.ts +1 -0
- package/dist/application/doctor-deadline.js +10 -0
- package/dist/application/doctor-deadline.js.map +1 -0
- package/dist/application/doctor-image.js +9 -7
- package/dist/application/doctor-image.js.map +1 -1
- package/dist/application/doctor-sandbox.js +4 -4
- package/dist/application/doctor-sandbox.js.map +1 -1
- package/dist/application/doctor.constants.d.ts +2 -0
- package/dist/application/doctor.constants.js +2 -0
- package/dist/application/doctor.constants.js.map +1 -1
- package/dist/application/doctor.js +12 -8
- package/dist/application/doctor.js.map +1 -1
- package/dist/application/doctor.types.d.ts +2 -0
- package/dist/application/doctor.types.js.map +1 -1
- package/dist/application/file-sandbox.js +49 -11
- package/dist/application/file-sandbox.js.map +1 -1
- package/dist/application/harness-context.js +4 -2
- package/dist/application/harness-context.js.map +1 -1
- package/dist/application/harness-hook-transforms.d.ts +8 -0
- package/dist/application/harness-hook-transforms.js +115 -0
- package/dist/application/harness-hook-transforms.js.map +1 -0
- package/dist/application/harness-hooks.d.ts +5 -3
- package/dist/application/harness-hooks.js +37 -50
- package/dist/application/harness-hooks.js.map +1 -1
- package/dist/application/harness-loop.d.ts +2 -1
- package/dist/application/harness-loop.js +95 -21
- package/dist/application/harness-loop.js.map +1 -1
- package/dist/application/harness-subagent.d.ts +1 -1
- package/dist/application/harness-subagent.js +63 -12
- package/dist/application/harness-subagent.js.map +1 -1
- package/dist/application/harness.types.d.ts +3 -0
- package/dist/application/harness.types.js.map +1 -1
- package/dist/application/hook-invocation.d.ts +4 -0
- package/dist/application/hook-invocation.js +59 -0
- package/dist/application/hook-invocation.js.map +1 -0
- package/dist/application/queue-worker.js +51 -9
- package/dist/application/queue-worker.js.map +1 -1
- package/dist/application/queue-worker.types.d.ts +1 -0
- package/dist/application/queue-worker.types.js.map +1 -1
- package/dist/application/recipes/native-schemas.constants.js +1439 -218
- package/dist/application/recipes/native-schemas.constants.js.map +1 -1
- package/dist/application/recovery-inspection.js +4 -1
- package/dist/application/recovery-inspection.js.map +1 -1
- package/dist/application/remote-download.js +15 -5
- package/dist/application/remote-download.js.map +1 -1
- package/dist/application/remote-paths.d.ts +1 -0
- package/dist/application/remote-paths.js +7 -0
- package/dist/application/remote-paths.js.map +1 -0
- package/dist/application/remote-validation.js +40 -9
- package/dist/application/remote-validation.js.map +1 -1
- package/dist/application/remote-workspace.js +17 -2
- package/dist/application/remote-workspace.js.map +1 -1
- package/dist/application/repetition-watchdog.js +3 -1
- package/dist/application/repetition-watchdog.js.map +1 -1
- package/dist/application/sandbox-attach.js +38 -9
- package/dist/application/sandbox-attach.js.map +1 -1
- package/dist/application/sandbox-dispatch.js +7 -1
- package/dist/application/sandbox-dispatch.js.map +1 -1
- package/dist/application/schedules.js +2 -0
- package/dist/application/schedules.js.map +1 -1
- package/dist/application/secrets.js +4 -0
- package/dist/application/secrets.js.map +1 -1
- package/dist/application/tool-execution.js +28 -8
- package/dist/application/tool-execution.js.map +1 -1
- package/dist/application/transport-retention.js +3 -3
- package/dist/application/transport-retention.js.map +1 -1
- package/dist/application/workspace-fingerprint.d.ts +1 -0
- package/dist/application/workspace-fingerprint.js +19 -4
- package/dist/application/workspace-fingerprint.js.map +1 -1
- package/dist/cli/doctor-command.js +12 -2
- package/dist/cli/doctor-command.js.map +1 -1
- package/dist/cli/image.js +2 -0
- package/dist/cli/image.js.map +1 -1
- package/dist/cli/main.constants.d.ts +14 -2
- package/dist/cli/main.constants.js +27 -1
- package/dist/cli/main.constants.js.map +1 -1
- package/dist/cli/project-settings.js +7 -1
- package/dist/cli/project-settings.js.map +1 -1
- package/dist/cli/recipe-yaml.js +8 -0
- package/dist/cli/recipe-yaml.js.map +1 -1
- package/dist/cli/recovery-command.js +3 -0
- package/dist/cli/recovery-command.js.map +1 -1
- package/dist/cli/recovery-unlock-command.d.ts +2 -0
- package/dist/cli/recovery-unlock-command.js +19 -0
- package/dist/cli/recovery-unlock-command.js.map +1 -0
- package/dist/cli/scaffold-files.js +4 -1
- package/dist/cli/scaffold-files.js.map +1 -1
- package/dist/cli/scaffold-validation.js +3 -0
- package/dist/cli/scaffold-validation.js.map +1 -1
- package/dist/cli/scaffold.js +2 -0
- package/dist/cli/scaffold.js.map +1 -1
- package/dist/domain/agent-hook.types.d.ts +28 -0
- package/dist/domain/agent-hook.types.js +2 -0
- package/dist/domain/agent-hook.types.js.map +1 -0
- package/dist/domain/agent-profile-hooks.d.ts +2 -0
- package/dist/domain/agent-profile-hooks.js +52 -0
- package/dist/domain/agent-profile-hooks.js.map +1 -0
- package/dist/domain/agent-profile-permissions.js +11 -1
- package/dist/domain/agent-profile-permissions.js.map +1 -1
- package/dist/domain/agent-profile.constants.d.ts +1 -0
- package/dist/domain/agent-profile.constants.js +9 -0
- package/dist/domain/agent-profile.constants.js.map +1 -1
- package/dist/domain/agent-profile.js +6 -1
- package/dist/domain/agent-profile.js.map +1 -1
- package/dist/domain/agent-profile.types.d.ts +11 -0
- package/dist/domain/agent-profile.types.js.map +1 -1
- package/dist/domain/agent.types.d.ts +2 -0
- package/dist/domain/agent.types.js.map +1 -1
- package/dist/domain/container-image.d.ts +1 -0
- package/dist/domain/container-image.js +8 -0
- package/dist/domain/container-image.js.map +1 -0
- package/dist/domain/context.constants.d.ts +1 -0
- package/dist/domain/context.constants.js +1 -0
- package/dist/domain/context.constants.js.map +1 -1
- package/dist/domain/context.js +6 -1
- package/dist/domain/context.js.map +1 -1
- package/dist/domain/egress.js +6 -1
- package/dist/domain/egress.js.map +1 -1
- package/dist/domain/glob.js +1 -1
- package/dist/domain/glob.js.map +1 -1
- package/dist/domain/harness.js +4 -1
- package/dist/domain/harness.js.map +1 -1
- package/dist/domain/hook-command.d.ts +2 -0
- package/dist/domain/hook-command.js +26 -0
- package/dist/domain/hook-command.js.map +1 -0
- package/dist/domain/hook-command.types.d.ts +7 -0
- package/dist/domain/hook-command.types.js +2 -0
- package/dist/domain/hook-command.types.js.map +1 -0
- package/dist/domain/hook-decision.d.ts +2 -0
- package/dist/domain/hook-decision.js +38 -0
- package/dist/domain/hook-decision.js.map +1 -0
- package/dist/domain/hook.constants.d.ts +3 -0
- package/dist/domain/hook.constants.js +31 -1
- package/dist/domain/hook.constants.js.map +1 -1
- package/dist/domain/hook.js +49 -5
- package/dist/domain/hook.js.map +1 -1
- package/dist/domain/hook.types.d.ts +82 -5
- package/dist/domain/hook.types.js.map +1 -1
- package/dist/domain/mcp-server.constants.d.ts +6 -0
- package/dist/domain/mcp-server.constants.js +6 -0
- package/dist/domain/mcp-server.constants.js.map +1 -1
- package/dist/domain/mcp-server.js +1 -0
- package/dist/domain/mcp-server.js.map +1 -1
- package/dist/domain/permissions.types.d.ts +1 -0
- package/dist/domain/permissions.types.js.map +1 -1
- package/dist/domain/pricing.js +4 -2
- package/dist/domain/pricing.js.map +1 -1
- package/dist/domain/redaction.js +6 -3
- package/dist/domain/redaction.js.map +1 -1
- package/dist/domain/secret-fault.d.ts +4 -0
- package/dist/domain/secret-fault.js +11 -0
- package/dist/domain/secret-fault.js.map +1 -0
- package/dist/domain/secrets.js +3 -2
- package/dist/domain/secrets.js.map +1 -1
- package/dist/domain/steering.js +2 -0
- package/dist/domain/steering.js.map +1 -1
- package/dist/domain/steering.types.d.ts +1 -1
- package/dist/domain/steering.types.js.map +1 -1
- package/dist/domain/transport.js +5 -1
- package/dist/domain/transport.js.map +1 -1
- package/dist/domain/trigger-payload.d.ts +4 -0
- package/dist/domain/trigger-payload.js +15 -0
- package/dist/domain/trigger-payload.js.map +1 -0
- package/dist/domain/workflow/checkpoint.js +19 -2
- package/dist/domain/workflow/checkpoint.js.map +1 -1
- package/dist/domain/workflow/retry.constants.d.ts +1 -0
- package/dist/domain/workflow/retry.constants.js +1 -0
- package/dist/domain/workflow/retry.constants.js.map +1 -1
- package/dist/domain/workflow/retry.js +6 -2
- package/dist/domain/workflow/retry.js.map +1 -1
- package/dist/domain/workflow/task-runner.js +5 -3
- package/dist/domain/workflow/task-runner.js.map +1 -1
- package/dist/domain/workflow/workflow-state.js +2 -1
- package/dist/domain/workflow/workflow-state.js.map +1 -1
- package/dist/domain/workflow.types.d.ts +1 -0
- package/dist/domain/workflow.types.js.map +1 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/conversations/transcript-store.js +32 -5
- package/dist/infrastructure/conversations/transcript-store.js.map +1 -1
- package/dist/infrastructure/files.d.ts +1 -0
- package/dist/infrastructure/files.js +8 -4
- package/dist/infrastructure/files.js.map +1 -1
- package/dist/infrastructure/git/integration-candidate.js +3 -2
- package/dist/infrastructure/git/integration-candidate.js.map +1 -1
- package/dist/infrastructure/git/lock-recovery.d.ts +3 -0
- package/dist/infrastructure/git/lock-recovery.js +58 -0
- package/dist/infrastructure/git/lock-recovery.js.map +1 -0
- package/dist/infrastructure/git/lock-recovery.types.d.ts +11 -0
- package/dist/infrastructure/git/lock-recovery.types.js +2 -0
- package/dist/infrastructure/git/lock-recovery.types.js.map +1 -0
- package/dist/infrastructure/git/managed-worktree.js +5 -8
- package/dist/infrastructure/git/managed-worktree.js.map +1 -1
- package/dist/infrastructure/git/verification-command.js +35 -30
- package/dist/infrastructure/git/verification-command.js.map +1 -1
- package/dist/infrastructure/git/workspace-lease.js +12 -5
- package/dist/infrastructure/git/workspace-lease.js.map +1 -1
- package/dist/infrastructure/hook-configuration.constants.d.ts +1 -0
- package/dist/infrastructure/hook-configuration.constants.js +59 -0
- package/dist/infrastructure/hook-configuration.constants.js.map +1 -0
- package/dist/infrastructure/hook-configuration.d.ts +3 -0
- package/dist/infrastructure/hook-configuration.js +16 -0
- package/dist/infrastructure/hook-configuration.js.map +1 -0
- package/dist/infrastructure/hook-configuration.types.d.ts +14 -0
- package/dist/infrastructure/hook-configuration.types.js +2 -0
- package/dist/infrastructure/hook-configuration.types.js.map +1 -0
- package/dist/infrastructure/http-transport.constants.d.ts +1 -0
- package/dist/infrastructure/http-transport.constants.js +14 -0
- package/dist/infrastructure/http-transport.constants.js.map +1 -0
- package/dist/infrastructure/http-transport.d.ts +7 -0
- package/dist/infrastructure/http-transport.js +19 -0
- package/dist/infrastructure/http-transport.js.map +1 -0
- package/dist/infrastructure/input-failure.d.ts +4 -0
- package/dist/infrastructure/input-failure.js +14 -0
- package/dist/infrastructure/input-failure.js.map +1 -0
- package/dist/infrastructure/inspection-file.d.ts +1 -0
- package/dist/infrastructure/inspection-file.js +8 -2
- package/dist/infrastructure/inspection-file.js.map +1 -1
- package/dist/infrastructure/local-transport.js +16 -11
- package/dist/infrastructure/local-transport.js.map +1 -1
- package/dist/infrastructure/process.constants.d.ts +1 -0
- package/dist/infrastructure/process.constants.js +1 -0
- package/dist/infrastructure/process.constants.js.map +1 -1
- package/dist/infrastructure/process.d.ts +1 -0
- package/dist/infrastructure/process.js +48 -8
- package/dist/infrastructure/process.js.map +1 -1
- package/dist/infrastructure/reservation-ledger.d.ts +2 -0
- package/dist/infrastructure/reservation-ledger.js +84 -0
- package/dist/infrastructure/reservation-ledger.js.map +1 -0
- package/dist/infrastructure/reservation-recovery.d.ts +4 -0
- package/dist/infrastructure/reservation-recovery.js +28 -0
- package/dist/infrastructure/reservation-recovery.js.map +1 -0
- package/dist/infrastructure/s3-tombstones.d.ts +3 -0
- package/dist/infrastructure/s3-tombstones.js +46 -0
- package/dist/infrastructure/s3-tombstones.js.map +1 -0
- package/dist/infrastructure/s3-tombstones.types.d.ts +6 -0
- package/dist/infrastructure/s3-tombstones.types.js +2 -0
- package/dist/infrastructure/s3-tombstones.types.js.map +1 -0
- package/dist/infrastructure/s3-transport.d.ts +2 -0
- package/dist/infrastructure/s3-transport.js +4 -2
- package/dist/infrastructure/s3-transport.js.map +1 -1
- package/dist/infrastructure/sse.js +6 -3
- package/dist/infrastructure/sse.js.map +1 -1
- package/dist/infrastructure/task-queue-bullmq-connection.d.ts +3 -0
- package/dist/infrastructure/task-queue-bullmq-connection.js +32 -0
- package/dist/infrastructure/task-queue-bullmq-connection.js.map +1 -0
- package/dist/infrastructure/task-queue-bullmq-connection.types.d.ts +8 -0
- package/dist/infrastructure/task-queue-bullmq-connection.types.js +2 -0
- package/dist/infrastructure/task-queue-bullmq-connection.types.js.map +1 -0
- package/dist/infrastructure/task-queue-bullmq-resources.js +21 -15
- package/dist/infrastructure/task-queue-bullmq-resources.js.map +1 -1
- package/dist/infrastructure/task-queue-bullmq-state.d.ts +1 -0
- package/dist/infrastructure/task-queue-bullmq-state.js +1 -0
- package/dist/infrastructure/task-queue-bullmq-state.js.map +1 -1
- package/dist/infrastructure/task-queue-bullmq.constants.d.ts +2 -1
- package/dist/infrastructure/task-queue-bullmq.constants.js +2 -1
- package/dist/infrastructure/task-queue-bullmq.constants.js.map +1 -1
- package/dist/infrastructure/task-queue-bullmq.js +10 -1
- package/dist/infrastructure/task-queue-bullmq.js.map +1 -1
- package/dist/infrastructure/task-queue.js +13 -4
- package/dist/infrastructure/task-queue.js.map +1 -1
- package/dist/infrastructure/transfer-copy.d.ts +1 -0
- package/dist/infrastructure/transfer-copy.js +16 -1
- package/dist/infrastructure/transfer-copy.js.map +1 -1
- package/dist/infrastructure/transport-archive.d.ts +3 -3
- package/dist/infrastructure/transport-archive.js +71 -48
- package/dist/infrastructure/transport-archive.js.map +1 -1
- package/dist/infrastructure/transport-archive.types.d.ts +3 -0
- package/dist/infrastructure/transport-archive.types.js.map +1 -1
- package/dist/infrastructure/transport-checkpoint.js +14 -4
- package/dist/infrastructure/transport-checkpoint.js.map +1 -1
- package/dist/infrastructure/transport-envelope.d.ts +1 -0
- package/dist/infrastructure/transport-envelope.js +22 -5
- package/dist/infrastructure/transport-envelope.js.map +1 -1
- package/dist/infrastructure/transport-reservations.constants.d.ts +2 -0
- package/dist/infrastructure/transport-reservations.constants.js +3 -0
- package/dist/infrastructure/transport-reservations.constants.js.map +1 -0
- package/dist/infrastructure/transport-reservations.d.ts +1 -2
- package/dist/infrastructure/transport-reservations.js +18 -22
- package/dist/infrastructure/transport-reservations.js.map +1 -1
- package/dist/infrastructure/transport-reservations.types.d.ts +23 -2
- package/dist/infrastructure/transport-reservations.types.js.map +1 -1
- package/dist/infrastructure/trigger-server.js +12 -9
- package/dist/infrastructure/trigger-server.js.map +1 -1
- package/dist/infrastructure/trigger-server.types.d.ts +1 -1
- package/dist/infrastructure/trigger-server.types.js.map +1 -1
- package/dist/infrastructure/workflow-checkpoint.constants.d.ts +1 -0
- package/dist/infrastructure/workflow-checkpoint.constants.js +1 -0
- package/dist/infrastructure/workflow-checkpoint.constants.js.map +1 -1
- package/dist/infrastructure/workspace-lock.constants.d.ts +2 -1
- package/dist/infrastructure/workspace-lock.constants.js +2 -1
- package/dist/infrastructure/workspace-lock.constants.js.map +1 -1
- package/dist/infrastructure/workspace-lock.js +48 -10
- package/dist/infrastructure/workspace-lock.js.map +1 -1
- package/dist/providers/cloud-cache.js +14 -9
- package/dist/providers/cloud-cache.js.map +1 -1
- package/dist/providers/cloud-cache.types.d.ts +1 -0
- package/dist/providers/cloud-cache.types.js.map +1 -1
- package/dist/providers/cloud-files.js +3 -4
- package/dist/providers/cloud-files.js.map +1 -1
- package/dist/providers/cloud-input.constants.d.ts +2 -2
- package/dist/providers/cloud-input.constants.js +2 -1
- package/dist/providers/cloud-input.constants.js.map +1 -1
- package/dist/providers/cloud-input.d.ts +2 -2
- package/dist/providers/cloud-input.js +14 -3
- package/dist/providers/cloud-input.js.map +1 -1
- package/dist/providers/container-command.js +30 -5
- package/dist/providers/container-command.js.map +1 -1
- package/dist/providers/container-egress.constants.d.ts +7 -0
- package/dist/providers/container-egress.constants.js +8 -0
- package/dist/providers/container-egress.constants.js.map +1 -0
- package/dist/providers/container-egress.d.ts +7 -0
- package/dist/providers/container-egress.js +101 -0
- package/dist/providers/container-egress.js.map +1 -0
- package/dist/providers/container-files.js +10 -11
- package/dist/providers/container-files.js.map +1 -1
- package/dist/providers/container-mounts.js +3 -0
- package/dist/providers/container-mounts.js.map +1 -1
- package/dist/providers/container-network.js +16 -1
- package/dist/providers/container-network.js.map +1 -1
- package/dist/providers/container-plan.js +7 -10
- package/dist/providers/container-plan.js.map +1 -1
- package/dist/providers/container-recovery.js +8 -3
- package/dist/providers/container-recovery.js.map +1 -1
- package/dist/providers/container.js +36 -5
- package/dist/providers/container.js.map +1 -1
- package/dist/providers/container.types.d.ts +1 -0
- package/dist/providers/container.types.js.map +1 -1
- package/dist/providers/daytona-command.constants.js +4 -1
- package/dist/providers/daytona-command.constants.js.map +1 -1
- package/dist/providers/daytona-command.js +39 -16
- package/dist/providers/daytona-command.js.map +1 -1
- package/dist/providers/daytona-files.js +5 -5
- package/dist/providers/daytona-files.js.map +1 -1
- package/dist/providers/daytona-output.js +11 -3
- package/dist/providers/daytona-output.js.map +1 -1
- package/dist/providers/daytona.js +11 -9
- package/dist/providers/daytona.js.map +1 -1
- package/dist/providers/egress/address.d.ts +3 -0
- package/dist/providers/egress/address.js +26 -0
- package/dist/providers/egress/address.js.map +1 -0
- package/dist/providers/egress/egress.constants.d.ts +22 -0
- package/dist/providers/egress/egress.constants.js +23 -0
- package/dist/providers/egress/egress.constants.js.map +1 -0
- package/dist/providers/egress/egress.types.d.ts +11 -0
- package/dist/providers/egress/egress.types.js +2 -0
- package/dist/providers/egress/egress.types.js.map +1 -0
- package/dist/providers/egress/firewall.d.ts +3 -0
- package/dist/providers/egress/firewall.js +29 -0
- package/dist/providers/egress/firewall.js.map +1 -0
- package/dist/providers/egress/main.d.ts +1 -0
- package/dist/providers/egress/main.js +90 -0
- package/dist/providers/egress/main.js.map +1 -0
- package/dist/providers/egress/policy.d.ts +5 -0
- package/dist/providers/egress/policy.js +54 -0
- package/dist/providers/egress/policy.js.map +1 -0
- package/dist/providers/egress/proxy.d.ts +2 -0
- package/dist/providers/egress/proxy.js +129 -0
- package/dist/providers/egress/proxy.js.map +1 -0
- package/dist/providers/egress/tls-hello.d.ts +1 -0
- package/dist/providers/egress/tls-hello.js +75 -0
- package/dist/providers/egress/tls-hello.js.map +1 -0
- package/dist/providers/firecracker-command.js +12 -6
- package/dist/providers/firecracker-command.js.map +1 -1
- package/dist/providers/local-files.d.ts +2 -0
- package/dist/providers/local-files.js +24 -0
- package/dist/providers/local-files.js.map +1 -0
- package/dist/providers/local.js +2 -20
- package/dist/providers/local.js.map +1 -1
- package/dist/providers/vercel-command.js +33 -9
- package/dist/providers/vercel-command.js.map +1 -1
- package/dist/providers/vercel.js +11 -9
- package/dist/providers/vercel.js.map +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/dist/testing.js.map +1 -1
- package/package.json +2 -2
- package/recipe-configuration.schema.json +2164 -35
- package/recipe.schema.json +2512 -404
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-configuration.js","sourceRoot":"","sources":["../../src/infrastructure/hook-configuration.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAE5E,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,OAAqB,EACrB,IAA2B,EAC3B,MAAmB;IAEnB,MAAM,OAAO,GAAG,KAAK,EAAE,MAAe,EAAE,MAAoB,EAAE,EAAE;QAC9D,MAAM,cAAc,CAClB;YACE,UAAU,EAAE,MAAM;YAClB,SAAS,EAAE,CAAC,IAAI,EAAE,uBAAuB,CAAC;YAC1C,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YAC3D,UAAU,EAAE,MAAM;YAClB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9B,EACD,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAC7B,CAAC;IACJ,CAAC,CAAC;IACF,MAAM,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["import type { SandboxLease } from \"../domain/sandbox.types.ts\";\nimport type { HookConfigurationEdit } from \"./hook-configuration.types.ts\";\nimport { requireSuccess } from \"./process.ts\";\nimport { hookConfigurationScript } from \"./hook-configuration.constants.ts\";\n\nexport async function installHookConfiguration(\n sandbox: SandboxLease,\n edit: HookConfigurationEdit,\n signal: AbortSignal,\n): Promise<() => Promise<void>> {\n const execute = async (remove: boolean, signal?: AbortSignal) => {\n await requireSuccess(\n {\n executable: \"node\",\n arguments: [\"-e\", hookConfigurationScript],\n stdin: JSON.stringify({ home: sandbox.home, edit, remove }),\n deadlineMs: 10_000,\n ...(signal ? { signal } : {}),\n },\n sandbox.invoke.bind(sandbox),\n );\n };\n await execute(false, signal);\n return () => execute(true);\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type HookConfigurationEdit = {
|
|
2
|
+
readonly path: string;
|
|
3
|
+
} & ({
|
|
4
|
+
readonly kind: "exclusive";
|
|
5
|
+
readonly content: string;
|
|
6
|
+
} | {
|
|
7
|
+
readonly kind: "append";
|
|
8
|
+
readonly content: string;
|
|
9
|
+
readonly rejectPattern?: string;
|
|
10
|
+
} | {
|
|
11
|
+
readonly kind: "entry";
|
|
12
|
+
readonly key: string;
|
|
13
|
+
readonly value: unknown;
|
|
14
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-configuration.types.js","sourceRoot":"","sources":["../../src/infrastructure/hook-configuration.types.ts"],"names":[],"mappings":"","sourcesContent":["export type HookConfigurationEdit = {\n readonly path: string;\n} & (\n | { readonly kind: \"exclusive\"; readonly content: string }\n | {\n readonly kind: \"append\";\n readonly content: string;\n readonly rejectPattern?: string;\n }\n | { readonly kind: \"entry\"; readonly key: string; readonly value: unknown }\n);\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const httpTransportCodes: ReadonlySet<string>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const httpTransportCodes = new Set([
|
|
2
|
+
"ENOTFOUND",
|
|
3
|
+
"EAI_AGAIN",
|
|
4
|
+
"ECONNREFUSED",
|
|
5
|
+
"ECONNRESET",
|
|
6
|
+
"ETIMEDOUT",
|
|
7
|
+
"CERT_HAS_EXPIRED",
|
|
8
|
+
"DEPTH_ZERO_SELF_SIGNED_CERT",
|
|
9
|
+
"UNABLE_TO_VERIFY_LEAF_SIGNATURE",
|
|
10
|
+
"UND_ERR_CONNECT_TIMEOUT",
|
|
11
|
+
"UND_ERR_SOCKET",
|
|
12
|
+
"UND_ERR_HEADERS_TIMEOUT",
|
|
13
|
+
]);
|
|
14
|
+
//# sourceMappingURL=http-transport.constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-transport.constants.js","sourceRoot":"","sources":["../../src/infrastructure/http-transport.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CAAC;IAC7D,WAAW;IACX,WAAW;IACX,cAAc;IACd,YAAY;IACZ,WAAW;IACX,kBAAkB;IAClB,6BAA6B;IAC7B,iCAAiC;IACjC,yBAAyB;IACzB,gBAAgB;IAChB,yBAAyB;CAC1B,CAAC,CAAC","sourcesContent":["export const httpTransportCodes: ReadonlySet<string> = new Set([\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n \"ECONNREFUSED\",\n \"ECONNRESET\",\n \"ETIMEDOUT\",\n \"CERT_HAS_EXPIRED\",\n \"DEPTH_ZERO_SELF_SIGNED_CERT\",\n \"UNABLE_TO_VERIFY_LEAF_SIGNATURE\",\n \"UND_ERR_CONNECT_TIMEOUT\",\n \"UND_ERR_SOCKET\",\n \"UND_ERR_HEADERS_TIMEOUT\",\n]);\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { httpTransportCodes } from "./http-transport.constants.js";
|
|
2
|
+
export function httpTransportFailure(error) {
|
|
3
|
+
for (const value of [
|
|
4
|
+
error,
|
|
5
|
+
error instanceof Error ? error.cause : undefined,
|
|
6
|
+
]) {
|
|
7
|
+
if (value &&
|
|
8
|
+
typeof value === "object" &&
|
|
9
|
+
"code" in value &&
|
|
10
|
+
typeof value.code === "string" &&
|
|
11
|
+
httpTransportCodes.has(value.code))
|
|
12
|
+
return {
|
|
13
|
+
unavailable: "HTTP transport failure",
|
|
14
|
+
transportCode: value.code,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return { unavailable: "HTTP transport failure" };
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=http-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-transport.js","sourceRoot":"","sources":["../../src/infrastructure/http-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,KAAK,MAAM,KAAK,IAAI;QAClB,KAAK;QACL,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;KACjD,EAAE,CAAC;QACF,IACE,KAAK;YACL,OAAO,KAAK,KAAK,QAAQ;YACzB,MAAM,IAAI,KAAK;YACf,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;YAC9B,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;YAElC,OAAO;gBACL,WAAW,EAAE,wBAAwB;gBACrC,aAAa,EAAE,KAAK,CAAC,IAAI;aAC1B,CAAC;IACN,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,CAAC;AACnD,CAAC","sourcesContent":["import { httpTransportCodes } from \"./http-transport.constants.ts\";\n\nexport function httpTransportFailure(error: unknown) {\n for (const value of [\n error,\n error instanceof Error ? error.cause : undefined,\n ]) {\n if (\n value &&\n typeof value === \"object\" &&\n \"code\" in value &&\n typeof value.code === \"string\" &&\n httpTransportCodes.has(value.code)\n )\n return {\n unavailable: \"HTTP transport failure\",\n transportCode: value.code,\n };\n }\n return { unavailable: \"HTTP transport failure\" };\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Readable } from "node:stream";
|
|
2
|
+
import { OutpostError } from "../domain/errors.ts";
|
|
3
|
+
export declare function observeInputFailure(input: Readable, handler: (error: OutpostError) => void): () => void;
|
|
4
|
+
export declare function reportInputFailure(input: Readable, cause: unknown): boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { OutpostError } from "../domain/errors.js";
|
|
2
|
+
const handlers = new WeakMap();
|
|
3
|
+
export function observeInputFailure(input, handler) {
|
|
4
|
+
handlers.set(input, handler);
|
|
5
|
+
return () => handlers.delete(input);
|
|
6
|
+
}
|
|
7
|
+
export function reportInputFailure(input, cause) {
|
|
8
|
+
const handler = handlers.get(input);
|
|
9
|
+
if (!handler)
|
|
10
|
+
return false;
|
|
11
|
+
handler(new OutpostError("steering", "Live input delivery could not be confirmed", {}, cause));
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=input-failure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-failure.js","sourceRoot":"","sources":["../../src/infrastructure/input-failure.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,QAAQ,GAAG,IAAI,OAAO,EAA2C,CAAC;AAExE,MAAM,UAAU,mBAAmB,CACjC,KAAe,EACf,OAAsC;IAEtC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC7B,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAe,EAAE,KAAc;IAChE,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,OAAO,CACL,IAAI,YAAY,CACd,UAAU,EACV,4CAA4C,EAC5C,EAAE,EACF,KAAK,CACN,CACF,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import type { Readable } from \"node:stream\";\nimport { OutpostError } from \"../domain/errors.ts\";\n\nconst handlers = new WeakMap<Readable, (error: OutpostError) => void>();\n\nexport function observeInputFailure(\n input: Readable,\n handler: (error: OutpostError) => void,\n): () => void {\n handlers.set(input, handler);\n return () => handlers.delete(input);\n}\n\nexport function reportInputFailure(input: Readable, cause: unknown): boolean {\n const handler = handlers.get(input);\n if (!handler) return false;\n handler(\n new OutpostError(\n \"steering\",\n \"Live input delivery could not be confirmed\",\n {},\n cause,\n ),\n );\n return true;\n}\n"]}
|
|
@@ -4,3 +4,4 @@ export declare class InspectionFileChanged extends Error {
|
|
|
4
4
|
constructor();
|
|
5
5
|
}
|
|
6
6
|
export declare function readInspectionFile(path: string, maxBytes: number, expected?: Stats): Promise<Buffer>;
|
|
7
|
+
export declare function readInspectionPrefix(path: string, maxBytes: number, expected: Stats): Promise<Buffer>;
|
|
@@ -17,20 +17,26 @@ function unchanged(before, after) {
|
|
|
17
17
|
before.ctimeMs === after.ctimeMs);
|
|
18
18
|
}
|
|
19
19
|
export async function readInspectionFile(path, maxBytes, expected) {
|
|
20
|
+
return inspectFile(path, maxBytes, false, expected);
|
|
21
|
+
}
|
|
22
|
+
export async function readInspectionPrefix(path, maxBytes, expected) {
|
|
23
|
+
return inspectFile(path, maxBytes, true, expected);
|
|
24
|
+
}
|
|
25
|
+
async function inspectFile(path, maxBytes, prefix, expected) {
|
|
20
26
|
positive(maxBytes, "maxBytes");
|
|
21
27
|
const before = await lstat(path);
|
|
22
28
|
if (expected && !unchanged(expected, before))
|
|
23
29
|
throw new InspectionFileChanged();
|
|
24
30
|
if (!before.isFile() || !(await isDirectInspectionPath(path)))
|
|
25
31
|
throw new Error("Inspection path changed");
|
|
26
|
-
if (before.size > maxBytes)
|
|
32
|
+
if (!prefix && before.size > maxBytes)
|
|
27
33
|
throw new Error("Inspection file is too large");
|
|
28
34
|
const file = await open(path, inspectionFileFlags);
|
|
29
35
|
try {
|
|
30
36
|
const opened = await file.stat();
|
|
31
37
|
if (!opened.isFile() || !unchanged(before, opened))
|
|
32
38
|
throw new InspectionFileChanged();
|
|
33
|
-
const buffer = Buffer.alloc(maxBytes + 1);
|
|
39
|
+
const buffer = Buffer.alloc(prefix ? maxBytes : maxBytes + 1);
|
|
34
40
|
let length = 0;
|
|
35
41
|
while (length < buffer.length) {
|
|
36
42
|
const { bytesRead } = await file.read(buffer, length, buffer.length - length, length);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspection-file.js","sourceRoot":"","sources":["../../src/infrastructure/inspection-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,+EAA+E;AAC/E,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C;QACE,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,SAAS,SAAS,CAAC,MAAa,EAAE,KAAY;IAC5C,OAAO,CACL,MAAM,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG;QACxB,MAAM,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG;QACxB,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI;QAC1B,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO;QAChC,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,CACjC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAY,EACZ,QAAgB,EAChB,QAAgB;IAEhB,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,QAAQ,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1C,MAAM,IAAI,qBAAqB,EAAE,CAAC;IACpC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,IAAI,MAAM,CAAC,IAAI,GAAG,QAAQ;
|
|
1
|
+
{"version":3,"file":"inspection-file.js","sourceRoot":"","sources":["../../src/infrastructure/inspection-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,+EAA+E;AAC/E,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C;QACE,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,SAAS,SAAS,CAAC,MAAa,EAAE,KAAY;IAC5C,OAAO,CACL,MAAM,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG;QACxB,MAAM,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG;QACxB,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI;QAC1B,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO;QAChC,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,CACjC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAY,EACZ,QAAgB,EAChB,QAAgB;IAEhB,OAAO,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAY,EACZ,QAAgB,EAChB,QAAe;IAEf,OAAO,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;AACrD,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,IAAY,EACZ,QAAgB,EAChB,MAAe,EACf,QAAgB;IAEhB,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,QAAQ,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1C,MAAM,IAAI,qBAAqB,EAAE,CAAC;IACpC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,GAAG,QAAQ;QACnC,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;YAChD,MAAM,IAAI,qBAAqB,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;QAC9D,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,OAAO,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC9B,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CACnC,MAAM,EACN,MAAM,EACN,MAAM,CAAC,MAAM,GAAG,MAAM,EACtB,MAAM,CACP,CAAC;YACF,IAAI,CAAC,SAAS;gBAAE,MAAM;YACtB,MAAM,IAAI,SAAS,CAAC;QACtB,CAAC;QACD,IAAI,MAAM,GAAG,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACvE,IACE,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YACrC,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;YAErC,MAAM,IAAI,qBAAqB,EAAE,CAAC;QACpC,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;YAAS,CAAC;QACT,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;AACH,CAAC","sourcesContent":["import { lstat, open } from \"node:fs/promises\";\nimport type { Stats } from \"node:fs\";\nimport { positive } from \"../domain/errors.ts\";\nimport { inspectionFileFlags } from \"./inspection-file.constants.ts\";\nimport { isDirectInspectionPath } from \"./inspection-path.ts\";\n\n/** Raised when the inspected path was replaced or modified during the read. */\nexport class InspectionFileChanged extends Error {\n constructor() {\n super(\"Inspection file changed\");\n this.name = \"InspectionFileChanged\";\n }\n}\n\nfunction unchanged(before: Stats, after: Stats): boolean {\n return (\n before.dev === after.dev &&\n before.ino === after.ino &&\n before.size === after.size &&\n before.mtimeMs === after.mtimeMs &&\n before.ctimeMs === after.ctimeMs\n );\n}\n\nexport async function readInspectionFile(\n path: string,\n maxBytes: number,\n expected?: Stats,\n): Promise<Buffer> {\n return inspectFile(path, maxBytes, false, expected);\n}\n\nexport async function readInspectionPrefix(\n path: string,\n maxBytes: number,\n expected: Stats,\n): Promise<Buffer> {\n return inspectFile(path, maxBytes, true, expected);\n}\n\nasync function inspectFile(\n path: string,\n maxBytes: number,\n prefix: boolean,\n expected?: Stats,\n): Promise<Buffer> {\n positive(maxBytes, \"maxBytes\");\n const before = await lstat(path);\n if (expected && !unchanged(expected, before))\n throw new InspectionFileChanged();\n if (!before.isFile() || !(await isDirectInspectionPath(path)))\n throw new Error(\"Inspection path changed\");\n if (!prefix && before.size > maxBytes)\n throw new Error(\"Inspection file is too large\");\n const file = await open(path, inspectionFileFlags);\n try {\n const opened = await file.stat();\n if (!opened.isFile() || !unchanged(before, opened))\n throw new InspectionFileChanged();\n const buffer = Buffer.alloc(prefix ? maxBytes : maxBytes + 1);\n let length = 0;\n while (length < buffer.length) {\n const { bytesRead } = await file.read(\n buffer,\n length,\n buffer.length - length,\n length,\n );\n if (!bytesRead) break;\n length += bytesRead;\n }\n if (length > maxBytes) throw new Error(\"Inspection file is too large\");\n if (\n !unchanged(opened, await file.stat()) ||\n !unchanged(opened, await lstat(path))\n )\n throw new InspectionFileChanged();\n return buffer.subarray(0, length);\n } finally {\n await file.close();\n }\n}\n"]}
|
|
@@ -5,8 +5,8 @@ import { setTimeout } from "node:timers/promises";
|
|
|
5
5
|
import { TransportConflict, transportKey, transportCondition, } from "../domain/transport.js";
|
|
6
6
|
import { lock } from "./git/lock.js";
|
|
7
7
|
import { OutpostError } from "../domain/errors.js";
|
|
8
|
-
import { InspectionFileChanged, readInspectionFile, } from "./inspection-file.js";
|
|
9
|
-
import { decodeObject, encodeObject, readLimit } from "./transport-envelope.js";
|
|
8
|
+
import { InspectionFileChanged, readInspectionFile, readInspectionPrefix, } from "./inspection-file.js";
|
|
9
|
+
import { decodeObject, decodeObjectEntry, encodeObject, readLimit, } from "./transport-envelope.js";
|
|
10
10
|
import { transportDefaults } from "./transport.constants.js";
|
|
11
11
|
async function privateDirectory(path, target = true) {
|
|
12
12
|
const parent = dirname(path);
|
|
@@ -41,17 +41,18 @@ async function replaceFile(source, target, signal) {
|
|
|
41
41
|
export function createLocalTransport(options) {
|
|
42
42
|
const root = resolve(options.directory), objects = join(root, "objects");
|
|
43
43
|
const path = (key) => join(objects, `${transportKey(key)}.object`);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const limit = readLimit(options.maxBytes);
|
|
44
|
+
async function inspect(key, limit, signal, headerOnly = false) {
|
|
45
|
+
signal?.throwIfAborted();
|
|
47
46
|
try {
|
|
48
47
|
const target = path(key);
|
|
49
48
|
for (let attempt = 1;; attempt++) {
|
|
50
49
|
const info = await lstat(target);
|
|
51
50
|
try {
|
|
52
|
-
const data = await
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
const data = await (headerOnly ? readInspectionPrefix : readInspectionFile)(target, headerOnly
|
|
52
|
+
? transportDefaults.headerBytes
|
|
53
|
+
: Math.min(info.size, limit + transportDefaults.headerBytes) || 1, info);
|
|
54
|
+
signal?.throwIfAborted();
|
|
55
|
+
return { data, size: info.size };
|
|
55
56
|
}
|
|
56
57
|
catch (error) {
|
|
57
58
|
// Writers replace objects atomically; read the replacement instead.
|
|
@@ -69,6 +70,11 @@ export function createLocalTransport(options) {
|
|
|
69
70
|
return undefined;
|
|
70
71
|
throw error;
|
|
71
72
|
}
|
|
73
|
+
}
|
|
74
|
+
const read = async (key, options = {}) => {
|
|
75
|
+
const limit = readLimit(options.maxBytes);
|
|
76
|
+
const object = await inspect(key, limit, options.signal);
|
|
77
|
+
return object ? decodeObject(object.data, key, limit) : undefined;
|
|
72
78
|
};
|
|
73
79
|
async function mutate(key, options, action) {
|
|
74
80
|
transportKey(key);
|
|
@@ -165,10 +171,9 @@ export function createLocalTransport(options) {
|
|
|
165
171
|
for await (const key of scan(objects, "")) {
|
|
166
172
|
if (!key.startsWith(prefix))
|
|
167
173
|
continue;
|
|
168
|
-
const object = await
|
|
174
|
+
const object = await inspect(key, transportDefaults.maxBytes, options.signal, true);
|
|
169
175
|
if (object) {
|
|
170
|
-
|
|
171
|
-
yield entry;
|
|
176
|
+
yield decodeObjectEntry(object.data, key, object.size, transportDefaults.maxBytes);
|
|
172
177
|
}
|
|
173
178
|
}
|
|
174
179
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-transport.js","sourceRoot":"","sources":["../../src/infrastructure/local-transport.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, lstat, open, rename, rm, readdir } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport { setTimeout } from \"node:timers/promises\";\nimport {\n TransportConflict,\n transportKey,\n transportCondition,\n} from \"../domain/transport.ts\";\nimport type {\n Transport,\n TransportWriteOptions,\n} from \"../domain/transport.types.ts\";\nimport type { LocalTransportOptions } from \"./local-transport.types.ts\";\nimport { lock } from \"./git/lock.ts\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport {\n InspectionFileChanged,\n readInspectionFile,\n} from \"./inspection-file.ts\";\nimport { decodeObject, encodeObject, readLimit } from \"./transport-envelope.ts\";\nimport { transportDefaults } from \"./transport.constants.ts\";\n\nasync function privateDirectory(path: string, target = true): Promise<void> {\n const parent = dirname(path);\n if (parent !== path) {\n await privateDirectory(parent, false);\n await mkdir(path, { recursive: true, mode: 0o700 });\n }\n const info = await lstat(path);\n if (info.isDirectory()) return;\n // Root-owned ancestor links belong to the system layout, such as /var on macOS.\n if (!target && info.isSymbolicLink() && info.uid === 0) return;\n throw new Error(\"Transport directories must not be symlinks\");\n}\n\nconst lockedReplacement = new Set([\"EPERM\", \"EACCES\", \"EBUSY\"]);\n\nasync function replaceFile(\n source: string,\n target: string,\n signal?: AbortSignal,\n): Promise<void> {\n for (let attempt = 1; ; attempt++) {\n try {\n return await rename(source, target);\n } catch (error) {\n // Windows refuses to replace a file while a concurrent reader holds it open.\n if (\n process.platform !== \"win32\" ||\n attempt >= transportDefaults.replaceAttempts ||\n !lockedReplacement.has((error as NodeJS.ErrnoException).code ?? \"\")\n )\n throw error;\n await setTimeout(transportDefaults.retryMs, undefined, { signal });\n }\n }\n}\n\nexport function createLocalTransport(\n options: LocalTransportOptions,\n): Transport {\n const root = resolve(options.directory),\n objects = join(root, \"objects\");\n const path = (key: string) => join(objects, `${transportKey(key)}.object`);\n const read: Transport[\"read\"] = async (key, options = {}) => {\n options.signal?.throwIfAborted();\n const limit = readLimit(options.maxBytes);\n try {\n const target = path(key);\n for (let attempt = 1; ; attempt++) {\n const info = await lstat(target);\n try {\n const data = await readInspectionFile(\n target,\n Math.min(info.size, limit + transportDefaults.headerBytes) || 1,\n info,\n );\n options.signal?.throwIfAborted();\n return decodeObject(data, key, limit);\n } catch (error) {\n // Writers replace objects atomically; read the replacement instead.\n if (\n !(error instanceof InspectionFileChanged) ||\n attempt >= transportDefaults.replacedReadAttempts\n )\n throw error;\n }\n }\n } catch (error) {\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n )\n return undefined;\n throw error;\n }\n };\n async function mutate<T>(\n key: string,\n options: TransportWriteOptions,\n action: () => Promise<T>,\n ): Promise<T> {\n transportKey(key);\n transportCondition(options.ifRevision);\n await privateDirectory(root);\n const signal = AbortSignal.any([\n AbortSignal.timeout(transportDefaults.lockMs),\n ...(options.signal ? [options.signal] : []),\n ]);\n let release: (() => Promise<void>) | undefined;\n while (!release) {\n signal.throwIfAborted();\n try {\n release = await lock(root, key);\n } catch (error) {\n if (!(error instanceof OutpostError) || error.code !== \"conflict\")\n throw error;\n await setTimeout(transportDefaults.retryMs, undefined, { signal });\n }\n }\n try {\n if ((await read(key))?.revision !== (options.ifRevision ?? undefined))\n throw new TransportConflict(key);\n options.signal?.throwIfAborted();\n return await action();\n } finally {\n await release();\n }\n }\n return {\n name: \"local\",\n read,\n write(key, input, options) {\n const bytes = Buffer.from(input);\n return mutate(key, options, async () => {\n const target = path(key);\n await privateDirectory(dirname(target));\n const { entry, data } = encodeObject(key, bytes);\n const temporary = `${target}.${randomUUID()}.tmp`;\n try {\n const file = await open(temporary, \"wx\", 0o600);\n try {\n await file.writeFile(data, { signal: options.signal });\n await file.sync();\n } finally {\n await file.close();\n }\n options.signal?.throwIfAborted();\n await replaceFile(temporary, target, options.signal);\n if (process.platform !== \"win32\") {\n const parent = await open(dirname(target), \"r\");\n try {\n await parent.sync();\n } finally {\n await parent.close();\n }\n }\n return entry;\n } finally {\n await rm(temporary, { force: true });\n }\n });\n },\n remove(key, options) {\n if (options.ifRevision === null)\n return Promise.reject(\n new Error(\"Transport removal requires an existing revision\"),\n );\n return mutate(key, options, () => rm(path(key), { force: true }));\n },\n async *list(prefix = \"\", options = {}) {\n if (prefix) transportKey(prefix.replace(/\\/$/, \"\"));\n async function* scan(\n directory: string,\n base: string,\n ): AsyncIterable<string> {\n const entries = await readdir(directory, { withFileTypes: true }).catch(\n (error) => {\n if (error.code === \"ENOENT\") return [];\n throw error;\n },\n );\n for (const entry of entries) {\n options.signal?.throwIfAborted();\n const name = `${base}${entry.name}`;\n if (entry.isDirectory())\n yield* scan(join(directory, entry.name), `${name}/`);\n if (entry.isFile() && name.endsWith(\".object\"))\n yield name.slice(0, -7);\n if (entry.isSymbolicLink())\n throw new Error(\"Transport objects must not be symlinks\");\n }\n }\n for await (const key of scan(objects, \"\")) {\n if (!key.startsWith(prefix)) continue;\n const object = await read(\n key,\n options.signal ? { signal: options.signal } : {},\n );\n if (object) {\n const { bytes: _bytes, ...entry } = object;\n yield entry;\n }\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"local-transport.js","sourceRoot":"","sources":["../../src/infrastructure/local-transport.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, lstat, open, rename, rm, readdir } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport { setTimeout } from \"node:timers/promises\";\nimport {\n TransportConflict,\n transportKey,\n transportCondition,\n} from \"../domain/transport.ts\";\nimport type {\n Transport,\n TransportWriteOptions,\n} from \"../domain/transport.types.ts\";\nimport type { LocalTransportOptions } from \"./local-transport.types.ts\";\nimport { lock } from \"./git/lock.ts\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport {\n InspectionFileChanged,\n readInspectionFile,\n readInspectionPrefix,\n} from \"./inspection-file.ts\";\nimport {\n decodeObject,\n decodeObjectEntry,\n encodeObject,\n readLimit,\n} from \"./transport-envelope.ts\";\nimport { transportDefaults } from \"./transport.constants.ts\";\n\nasync function privateDirectory(path: string, target = true): Promise<void> {\n const parent = dirname(path);\n if (parent !== path) {\n await privateDirectory(parent, false);\n await mkdir(path, { recursive: true, mode: 0o700 });\n }\n const info = await lstat(path);\n if (info.isDirectory()) return;\n // Root-owned ancestor links belong to the system layout, such as /var on macOS.\n if (!target && info.isSymbolicLink() && info.uid === 0) return;\n throw new Error(\"Transport directories must not be symlinks\");\n}\n\nconst lockedReplacement = new Set([\"EPERM\", \"EACCES\", \"EBUSY\"]);\n\nasync function replaceFile(\n source: string,\n target: string,\n signal?: AbortSignal,\n): Promise<void> {\n for (let attempt = 1; ; attempt++) {\n try {\n return await rename(source, target);\n } catch (error) {\n // Windows refuses to replace a file while a concurrent reader holds it open.\n if (\n process.platform !== \"win32\" ||\n attempt >= transportDefaults.replaceAttempts ||\n !lockedReplacement.has((error as NodeJS.ErrnoException).code ?? \"\")\n )\n throw error;\n await setTimeout(transportDefaults.retryMs, undefined, { signal });\n }\n }\n}\n\nexport function createLocalTransport(\n options: LocalTransportOptions,\n): Transport {\n const root = resolve(options.directory),\n objects = join(root, \"objects\");\n const path = (key: string) => join(objects, `${transportKey(key)}.object`);\n async function inspect(\n key: string,\n limit: number,\n signal?: AbortSignal,\n headerOnly = false,\n ) {\n signal?.throwIfAborted();\n try {\n const target = path(key);\n for (let attempt = 1; ; attempt++) {\n const info = await lstat(target);\n try {\n const data = await (\n headerOnly ? readInspectionPrefix : readInspectionFile\n )(\n target,\n headerOnly\n ? transportDefaults.headerBytes\n : Math.min(info.size, limit + transportDefaults.headerBytes) || 1,\n info,\n );\n signal?.throwIfAborted();\n return { data, size: info.size };\n } catch (error) {\n // Writers replace objects atomically; read the replacement instead.\n if (\n !(error instanceof InspectionFileChanged) ||\n attempt >= transportDefaults.replacedReadAttempts\n )\n throw error;\n }\n }\n } catch (error) {\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n )\n return undefined;\n throw error;\n }\n }\n const read: Transport[\"read\"] = async (key, options = {}) => {\n const limit = readLimit(options.maxBytes);\n const object = await inspect(key, limit, options.signal);\n return object ? decodeObject(object.data, key, limit) : undefined;\n };\n async function mutate<T>(\n key: string,\n options: TransportWriteOptions,\n action: () => Promise<T>,\n ): Promise<T> {\n transportKey(key);\n transportCondition(options.ifRevision);\n await privateDirectory(root);\n const signal = AbortSignal.any([\n AbortSignal.timeout(transportDefaults.lockMs),\n ...(options.signal ? [options.signal] : []),\n ]);\n let release: (() => Promise<void>) | undefined;\n while (!release) {\n signal.throwIfAborted();\n try {\n release = await lock(root, key);\n } catch (error) {\n if (!(error instanceof OutpostError) || error.code !== \"conflict\")\n throw error;\n await setTimeout(transportDefaults.retryMs, undefined, { signal });\n }\n }\n try {\n if ((await read(key))?.revision !== (options.ifRevision ?? undefined))\n throw new TransportConflict(key);\n options.signal?.throwIfAborted();\n return await action();\n } finally {\n await release();\n }\n }\n return {\n name: \"local\",\n read,\n write(key, input, options) {\n const bytes = Buffer.from(input);\n return mutate(key, options, async () => {\n const target = path(key);\n await privateDirectory(dirname(target));\n const { entry, data } = encodeObject(key, bytes);\n const temporary = `${target}.${randomUUID()}.tmp`;\n try {\n const file = await open(temporary, \"wx\", 0o600);\n try {\n await file.writeFile(data, { signal: options.signal });\n await file.sync();\n } finally {\n await file.close();\n }\n options.signal?.throwIfAborted();\n await replaceFile(temporary, target, options.signal);\n if (process.platform !== \"win32\") {\n const parent = await open(dirname(target), \"r\");\n try {\n await parent.sync();\n } finally {\n await parent.close();\n }\n }\n return entry;\n } finally {\n await rm(temporary, { force: true });\n }\n });\n },\n remove(key, options) {\n if (options.ifRevision === null)\n return Promise.reject(\n new Error(\"Transport removal requires an existing revision\"),\n );\n return mutate(key, options, () => rm(path(key), { force: true }));\n },\n async *list(prefix = \"\", options = {}) {\n if (prefix) transportKey(prefix.replace(/\\/$/, \"\"));\n async function* scan(\n directory: string,\n base: string,\n ): AsyncIterable<string> {\n const entries = await readdir(directory, { withFileTypes: true }).catch(\n (error) => {\n if (error.code === \"ENOENT\") return [];\n throw error;\n },\n );\n for (const entry of entries) {\n options.signal?.throwIfAborted();\n const name = `${base}${entry.name}`;\n if (entry.isDirectory())\n yield* scan(join(directory, entry.name), `${name}/`);\n if (entry.isFile() && name.endsWith(\".object\"))\n yield name.slice(0, -7);\n if (entry.isSymbolicLink())\n throw new Error(\"Transport objects must not be symlinks\");\n }\n }\n for await (const key of scan(objects, \"\")) {\n if (!key.startsWith(prefix)) continue;\n const object = await inspect(\n key,\n transportDefaults.maxBytes,\n options.signal,\n true,\n );\n if (object) {\n yield decodeObjectEntry(\n object.data,\n key,\n object.size,\n transportDefaults.maxBytes,\n );\n }\n }\n },\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.constants.js","sourceRoot":"","sources":["../../src/infrastructure/process.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3C,UAAU,EAAE,OAAO;IACnB,WAAW,EAAE,MAAM;IACnB,WAAW,EAAE,GAAG;
|
|
1
|
+
{"version":3,"file":"process.constants.js","sourceRoot":"","sources":["../../src/infrastructure/process.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3C,UAAU,EAAE,OAAO;IACnB,WAAW,EAAE,MAAM;IACnB,WAAW,EAAE,GAAG;IAChB,aAAa,EAAE,GAAG;CACnB,CAAC,CAAC;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAU,CAAC","sourcesContent":["export const processDefaults = Object.freeze({\n deadlineMs: 600_000,\n retainBytes: 65_536,\n killGraceMs: 500,\n outputDrainMs: 500,\n});\nexport const outputChannels = [\"stdout\", \"stderr\"] as const;\n"]}
|
|
@@ -2,6 +2,7 @@ import type { Command, CommandResult } from "../domain/command.types.ts";
|
|
|
2
2
|
import type { Executor } from "./process.types.ts";
|
|
3
3
|
export type { Executor } from "./process.types.ts";
|
|
4
4
|
export declare const executeProcess: Executor;
|
|
5
|
+
export declare const executeProcessWithEnvironment: (command: Command, environment: NodeJS.ProcessEnv) => Promise<CommandResult>;
|
|
5
6
|
export declare function requireSuccess(command: Command, executor?: Executor): Promise<CommandResult>;
|
|
6
7
|
export declare function shell(script: string): Pick<Command, "executable" | "arguments">;
|
|
7
8
|
export declare function quote(value: string): string;
|
|
@@ -3,7 +3,11 @@ import { StringDecoder } from "node:string_decoder";
|
|
|
3
3
|
import { OutpostError, positive } from "../domain/errors.js";
|
|
4
4
|
import { outputChannels, processDefaults } from "./process.constants.js";
|
|
5
5
|
import { restoreTerminal } from "./terminal.js";
|
|
6
|
-
export const executeProcess = (command) => {
|
|
6
|
+
export const executeProcess = (command) => executeProcessWithEnvironment(command, {
|
|
7
|
+
...process.env,
|
|
8
|
+
...command.variables,
|
|
9
|
+
});
|
|
10
|
+
export const executeProcessWithEnvironment = (command, environment) => {
|
|
7
11
|
command.signal?.throwIfAborted();
|
|
8
12
|
const deadline = command.deadlineMs ?? processDefaults.deadlineMs;
|
|
9
13
|
positive(deadline, "deadlineMs");
|
|
@@ -13,7 +17,7 @@ export const executeProcess = (command) => {
|
|
|
13
17
|
const interactive = command.interactive === true;
|
|
14
18
|
const child = spawn(command.executable, [...(command.arguments ?? [])], {
|
|
15
19
|
cwd: command.directory,
|
|
16
|
-
env:
|
|
20
|
+
env: environment,
|
|
17
21
|
shell: false,
|
|
18
22
|
windowsHide: true,
|
|
19
23
|
detached: !interactive && process.platform !== "win32",
|
|
@@ -24,6 +28,7 @@ export const executeProcess = (command) => {
|
|
|
24
28
|
stderr: new StringDecoder("utf8"),
|
|
25
29
|
};
|
|
26
30
|
const output = { stdout: "", stderr: "" };
|
|
31
|
+
let settled = false, exited = false, closed = false, status = null, drainage;
|
|
27
32
|
let failed = false, reason, escalation;
|
|
28
33
|
function kill(hard) {
|
|
29
34
|
if (!child.pid)
|
|
@@ -50,12 +55,17 @@ export const executeProcess = (command) => {
|
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
57
|
function interrupt(error) {
|
|
53
|
-
if (failed)
|
|
58
|
+
if (failed || settled)
|
|
54
59
|
return;
|
|
55
60
|
failed = true;
|
|
56
61
|
reason = error;
|
|
57
62
|
kill(false);
|
|
58
|
-
escalation = setTimeout(() =>
|
|
63
|
+
escalation = setTimeout(() => {
|
|
64
|
+
escalation = undefined;
|
|
65
|
+
kill(true);
|
|
66
|
+
if (closed)
|
|
67
|
+
finish();
|
|
68
|
+
}, processDefaults.killGraceMs);
|
|
59
69
|
}
|
|
60
70
|
const abort = () => interrupt(command.signal?.reason ??
|
|
61
71
|
new OutpostError("aborted", "Command cancelled"));
|
|
@@ -63,6 +73,8 @@ export const executeProcess = (command) => {
|
|
|
63
73
|
deadlineMs: deadline,
|
|
64
74
|
})), deadline);
|
|
65
75
|
const consume = (channel, text) => {
|
|
76
|
+
if (settled)
|
|
77
|
+
return;
|
|
66
78
|
output[channel] = (output[channel] + text).slice(-limit);
|
|
67
79
|
try {
|
|
68
80
|
command.observe?.(channel, text);
|
|
@@ -84,25 +96,53 @@ export const executeProcess = (command) => {
|
|
|
84
96
|
command.signal?.addEventListener("abort", abort, { once: true });
|
|
85
97
|
if (command.signal?.aborted)
|
|
86
98
|
abort();
|
|
87
|
-
|
|
88
|
-
if (interactive)
|
|
89
|
-
restoreTerminal();
|
|
99
|
+
function disconnectInput() {
|
|
90
100
|
if (child.stdin) {
|
|
91
101
|
command.terminal?.input?.unpipe(child.stdin);
|
|
92
102
|
command.input?.unpipe(child.stdin);
|
|
103
|
+
child.stdin.destroy();
|
|
93
104
|
}
|
|
105
|
+
}
|
|
106
|
+
function finish() {
|
|
107
|
+
if (settled || escalation)
|
|
108
|
+
return;
|
|
109
|
+
if (interactive)
|
|
110
|
+
restoreTerminal();
|
|
111
|
+
disconnectInput();
|
|
94
112
|
clearTimeout(timer);
|
|
95
|
-
clearTimeout(
|
|
113
|
+
clearTimeout(drainage);
|
|
96
114
|
command.signal?.removeEventListener("abort", abort);
|
|
97
115
|
for (const channel of outputChannels) {
|
|
98
116
|
const tail = decoder[channel].end();
|
|
99
117
|
if (tail)
|
|
100
118
|
consume(channel, tail);
|
|
101
119
|
}
|
|
120
|
+
if (escalation)
|
|
121
|
+
return;
|
|
122
|
+
settled = true;
|
|
123
|
+
child.stdout?.destroy();
|
|
124
|
+
child.stderr?.destroy();
|
|
102
125
|
if (failed)
|
|
103
126
|
reject(reason);
|
|
104
127
|
else
|
|
105
128
|
resolve({ status: status ?? 1, ...output });
|
|
129
|
+
}
|
|
130
|
+
child.on("exit", (code) => {
|
|
131
|
+
exited = true;
|
|
132
|
+
status = code;
|
|
133
|
+
clearTimeout(timer);
|
|
134
|
+
command.signal?.removeEventListener("abort", abort);
|
|
135
|
+
disconnectInput();
|
|
136
|
+
drainage = setTimeout(() => {
|
|
137
|
+
closed = true;
|
|
138
|
+
finish();
|
|
139
|
+
}, processDefaults.outputDrainMs);
|
|
140
|
+
});
|
|
141
|
+
child.on("close", (code) => {
|
|
142
|
+
closed = true;
|
|
143
|
+
if (!exited)
|
|
144
|
+
status = code;
|
|
145
|
+
finish();
|
|
106
146
|
});
|
|
107
147
|
connectStdin(child.stdin, command);
|
|
108
148
|
if (child.stdout && command.terminal?.output)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/infrastructure/process.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport type { Writable } from \"node:stream\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport type {\n Channel,\n Command,\n CommandResult,\n} from \"../domain/command.types.ts\";\nimport { OutpostError, positive } from \"../domain/errors.ts\";\nimport { outputChannels, processDefaults } from \"./process.constants.ts\";\nimport type { Executor } from \"./process.types.ts\";\nimport { restoreTerminal } from \"./terminal.ts\";\n\nexport type { Executor } from \"./process.types.ts\";\n\nexport const executeProcess: Executor = (command) => {\n command.signal?.throwIfAborted();\n const deadline = command.deadlineMs ?? processDefaults.deadlineMs;\n positive(deadline, \"deadlineMs\");\n const limit = command.retain ?? processDefaults.retainBytes;\n positive(limit, \"retain\");\n return new Promise((resolve, reject) => {\n const interactive = command.interactive === true;\n const child = spawn(command.executable, [...(command.arguments ?? [])], {\n cwd: command.directory,\n env: { ...process.env, ...command.variables },\n shell: false,\n windowsHide: true,\n detached: !interactive && process.platform !== \"win32\",\n stdio:\n interactive && !command.terminal ? \"inherit\" : [\"pipe\", \"pipe\", \"pipe\"],\n });\n const decoder = {\n stdout: new StringDecoder(\"utf8\"),\n stderr: new StringDecoder(\"utf8\"),\n };\n const output = { stdout: \"\", stderr: \"\" };\n let failed = false,\n reason: unknown,\n escalation: ReturnType<typeof setTimeout> | undefined;\n function kill(hard: boolean): void {\n if (!child.pid) return;\n if (process.platform === \"win32\") {\n const killer = spawn(\n \"taskkill\",\n [\"/PID\", String(child.pid), \"/T\", \"/F\"],\n { windowsHide: true, stdio: \"ignore\" },\n );\n killer.on(\"error\", () => {\n child.kill();\n });\n killer.on(\"exit\", (status) => {\n if (status !== 0) child.kill();\n });\n if (hard) child.kill();\n } else {\n try {\n process.kill(\n interactive ? child.pid : -child.pid,\n hard ? \"SIGKILL\" : \"SIGTERM\",\n );\n } catch {\n child.kill(hard ? \"SIGKILL\" : \"SIGTERM\");\n }\n }\n }\n function interrupt(error: unknown): void {\n if (failed) return;\n failed = true;\n reason = error;\n kill(false);\n escalation = setTimeout(() => kill(true), processDefaults.killGraceMs);\n }\n const abort = () =>\n interrupt(\n command.signal?.reason ??\n new OutpostError(\"aborted\", \"Command cancelled\"),\n );\n const timer = setTimeout(\n () =>\n interrupt(\n new OutpostError(\"timeout\", `Command exceeded ${deadline} ms`, {\n deadlineMs: deadline,\n }),\n ),\n deadline,\n );\n const consume = (channel: Channel, text: string) => {\n output[channel] = (output[channel] + text).slice(-limit);\n try {\n command.observe?.(channel, text);\n } catch (error) {\n interrupt(error);\n }\n };\n child.stdout?.on(\"data\", (data: Buffer) =>\n consume(\"stdout\", decoder.stdout.write(data)),\n );\n child.stderr?.on(\"data\", (data: Buffer) =>\n consume(\"stderr\", decoder.stderr.write(data)),\n );\n child.stdin?.on(\"error\", (error) => {\n if ((error as NodeJS.ErrnoException).code !== \"EPIPE\") interrupt(error);\n });\n child.on(\"error\", (error) => {\n failed = true;\n reason = error;\n });\n command.signal?.addEventListener(\"abort\", abort, { once: true });\n if (command.signal?.aborted) abort();\n child.on(\"close\", (status) => {\n if (interactive) restoreTerminal();\n if (child.stdin) {\n command.terminal?.input?.unpipe(child.stdin);\n command.input?.unpipe(child.stdin);\n }\n clearTimeout(timer);\n clearTimeout(escalation);\n command.signal?.removeEventListener(\"abort\", abort);\n for (const channel of outputChannels) {\n const tail = decoder[channel].end();\n if (tail) consume(channel, tail);\n }\n if (failed) reject(reason);\n else resolve({ status: status ?? 1, ...output });\n });\n connectStdin(child.stdin, command);\n if (child.stdout && command.terminal?.output)\n child.stdout.pipe(command.terminal.output, { end: false });\n if (child.stderr && command.terminal?.error)\n child.stderr.pipe(command.terminal.error, { end: false });\n });\n};\n\nfunction connectStdin(stdin: Writable | null, command: Command): void {\n if (!stdin) return;\n if (command.terminal?.input) {\n command.terminal.input.pipe(stdin);\n return;\n }\n if (!command.input) {\n stdin.end(command.stdin);\n return;\n }\n if (command.stdin) stdin.write(command.stdin);\n command.input.pipe(stdin);\n}\n\nexport async function requireSuccess(\n command: Command,\n executor = executeProcess,\n): Promise<CommandResult> {\n const result = await executor(command);\n if (result.status !== 0)\n throw new OutpostError(\n \"process\",\n `${command.executable} exited with status ${result.status}`,\n { ...result },\n );\n return result;\n}\n\nexport function shell(\n script: string,\n): Pick<Command, \"executable\" | \"arguments\"> {\n return process.platform === \"win32\"\n ? {\n executable: \"powershell.exe\",\n arguments: [\"-NoProfile\", \"-NonInteractive\", \"-Command\", script],\n }\n : { executable: \"sh\", arguments: [\"-c\", script] };\n}\n\nexport function quote(value: string): string {\n if (value.includes(\"\\0\"))\n throw new OutpostError(\n \"configuration\",\n \"A command argument cannot contain NUL\",\n );\n return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/infrastructure/process.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport type { Writable } from \"node:stream\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport type {\n Channel,\n Command,\n CommandResult,\n} from \"../domain/command.types.ts\";\nimport { OutpostError, positive } from \"../domain/errors.ts\";\nimport { outputChannels, processDefaults } from \"./process.constants.ts\";\nimport type { Executor } from \"./process.types.ts\";\nimport { restoreTerminal } from \"./terminal.ts\";\n\nexport type { Executor } from \"./process.types.ts\";\n\nexport const executeProcess: Executor = (command) =>\n executeProcessWithEnvironment(command, {\n ...process.env,\n ...command.variables,\n });\n\nexport const executeProcessWithEnvironment = (\n command: Command,\n environment: NodeJS.ProcessEnv,\n): Promise<CommandResult> => {\n command.signal?.throwIfAborted();\n const deadline = command.deadlineMs ?? processDefaults.deadlineMs;\n positive(deadline, \"deadlineMs\");\n const limit = command.retain ?? processDefaults.retainBytes;\n positive(limit, \"retain\");\n return new Promise((resolve, reject) => {\n const interactive = command.interactive === true;\n const child = spawn(command.executable, [...(command.arguments ?? [])], {\n cwd: command.directory,\n env: environment,\n shell: false,\n windowsHide: true,\n detached: !interactive && process.platform !== \"win32\",\n stdio:\n interactive && !command.terminal ? \"inherit\" : [\"pipe\", \"pipe\", \"pipe\"],\n });\n const decoder = {\n stdout: new StringDecoder(\"utf8\"),\n stderr: new StringDecoder(\"utf8\"),\n };\n const output = { stdout: \"\", stderr: \"\" };\n let settled = false,\n exited = false,\n closed = false,\n status: number | null = null,\n drainage: ReturnType<typeof setTimeout> | undefined;\n let failed = false,\n reason: unknown,\n escalation: ReturnType<typeof setTimeout> | undefined;\n function kill(hard: boolean): void {\n if (!child.pid) return;\n if (process.platform === \"win32\") {\n const killer = spawn(\n \"taskkill\",\n [\"/PID\", String(child.pid), \"/T\", \"/F\"],\n { windowsHide: true, stdio: \"ignore\" },\n );\n killer.on(\"error\", () => {\n child.kill();\n });\n killer.on(\"exit\", (status) => {\n if (status !== 0) child.kill();\n });\n if (hard) child.kill();\n } else {\n try {\n process.kill(\n interactive ? child.pid : -child.pid,\n hard ? \"SIGKILL\" : \"SIGTERM\",\n );\n } catch {\n child.kill(hard ? \"SIGKILL\" : \"SIGTERM\");\n }\n }\n }\n function interrupt(error: unknown): void {\n if (failed || settled) return;\n failed = true;\n reason = error;\n kill(false);\n escalation = setTimeout(() => {\n escalation = undefined;\n kill(true);\n if (closed) finish();\n }, processDefaults.killGraceMs);\n }\n const abort = () =>\n interrupt(\n command.signal?.reason ??\n new OutpostError(\"aborted\", \"Command cancelled\"),\n );\n const timer = setTimeout(\n () =>\n interrupt(\n new OutpostError(\"timeout\", `Command exceeded ${deadline} ms`, {\n deadlineMs: deadline,\n }),\n ),\n deadline,\n );\n const consume = (channel: Channel, text: string) => {\n if (settled) return;\n output[channel] = (output[channel] + text).slice(-limit);\n try {\n command.observe?.(channel, text);\n } catch (error) {\n interrupt(error);\n }\n };\n child.stdout?.on(\"data\", (data: Buffer) =>\n consume(\"stdout\", decoder.stdout.write(data)),\n );\n child.stderr?.on(\"data\", (data: Buffer) =>\n consume(\"stderr\", decoder.stderr.write(data)),\n );\n child.stdin?.on(\"error\", (error) => {\n if ((error as NodeJS.ErrnoException).code !== \"EPIPE\") interrupt(error);\n });\n child.on(\"error\", (error) => {\n failed = true;\n reason = error;\n });\n command.signal?.addEventListener(\"abort\", abort, { once: true });\n if (command.signal?.aborted) abort();\n function disconnectInput(): void {\n if (child.stdin) {\n command.terminal?.input?.unpipe(child.stdin);\n command.input?.unpipe(child.stdin);\n child.stdin.destroy();\n }\n }\n function finish(): void {\n if (settled || escalation) return;\n if (interactive) restoreTerminal();\n disconnectInput();\n clearTimeout(timer);\n clearTimeout(drainage);\n command.signal?.removeEventListener(\"abort\", abort);\n for (const channel of outputChannels) {\n const tail = decoder[channel].end();\n if (tail) consume(channel, tail);\n }\n if (escalation) return;\n settled = true;\n child.stdout?.destroy();\n child.stderr?.destroy();\n if (failed) reject(reason);\n else resolve({ status: status ?? 1, ...output });\n }\n child.on(\"exit\", (code) => {\n exited = true;\n status = code;\n clearTimeout(timer);\n command.signal?.removeEventListener(\"abort\", abort);\n disconnectInput();\n drainage = setTimeout(() => {\n closed = true;\n finish();\n }, processDefaults.outputDrainMs);\n });\n child.on(\"close\", (code) => {\n closed = true;\n if (!exited) status = code;\n finish();\n });\n connectStdin(child.stdin, command);\n if (child.stdout && command.terminal?.output)\n child.stdout.pipe(command.terminal.output, { end: false });\n if (child.stderr && command.terminal?.error)\n child.stderr.pipe(command.terminal.error, { end: false });\n });\n};\n\nfunction connectStdin(stdin: Writable | null, command: Command): void {\n if (!stdin) return;\n if (command.terminal?.input) {\n command.terminal.input.pipe(stdin);\n return;\n }\n if (!command.input) {\n stdin.end(command.stdin);\n return;\n }\n if (command.stdin) stdin.write(command.stdin);\n command.input.pipe(stdin);\n}\n\nexport async function requireSuccess(\n command: Command,\n executor = executeProcess,\n): Promise<CommandResult> {\n const result = await executor(command);\n if (result.status !== 0)\n throw new OutpostError(\n \"process\",\n `${command.executable} exited with status ${result.status}`,\n { ...result },\n );\n return result;\n}\n\nexport function shell(\n script: string,\n): Pick<Command, \"executable\" | \"arguments\"> {\n return process.platform === \"win32\"\n ? {\n executable: \"powershell.exe\",\n arguments: [\"-NoProfile\", \"-NonInteractive\", \"-Command\", script],\n }\n : { executable: \"sh\", arguments: [\"-c\", script] };\n}\n\nexport function quote(value: string): string {\n if (value.includes(\"\\0\"))\n throw new OutpostError(\n \"configuration\",\n \"A command argument cannot contain NUL\",\n );\n return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n"]}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { invariant } from "../domain/errors.js";
|
|
2
|
+
import { reservationIdPattern } from "./transport-reservations.constants.js";
|
|
3
|
+
function record(value) {
|
|
4
|
+
invariant(value &&
|
|
5
|
+
typeof value === "object" &&
|
|
6
|
+
"bytes" in value &&
|
|
7
|
+
typeof value.bytes === "number" &&
|
|
8
|
+
Number.isSafeInteger(value.bytes) &&
|
|
9
|
+
value.bytes >= 0, "Invalid reservation entry");
|
|
10
|
+
if (!("owner" in value))
|
|
11
|
+
return { bytes: value.bytes };
|
|
12
|
+
const owner = value.owner;
|
|
13
|
+
invariant(owner &&
|
|
14
|
+
typeof owner === "object" &&
|
|
15
|
+
"id" in owner &&
|
|
16
|
+
typeof owner.id === "string" &&
|
|
17
|
+
reservationIdPattern.test(owner.id) &&
|
|
18
|
+
"host" in owner &&
|
|
19
|
+
typeof owner.host === "string" &&
|
|
20
|
+
owner.host.length > 0 &&
|
|
21
|
+
"pid" in owner &&
|
|
22
|
+
typeof owner.pid === "number" &&
|
|
23
|
+
Number.isSafeInteger(owner.pid) &&
|
|
24
|
+
owner.pid > 0 &&
|
|
25
|
+
"createdAt" in owner &&
|
|
26
|
+
typeof owner.createdAt === "string" &&
|
|
27
|
+
Number.isFinite(Date.parse(owner.createdAt)) &&
|
|
28
|
+
"repository" in owner &&
|
|
29
|
+
typeof owner.repository === "string", "Invalid reservation owner");
|
|
30
|
+
let identity;
|
|
31
|
+
if ("identity" in owner) {
|
|
32
|
+
const value = owner.identity;
|
|
33
|
+
invariant(value &&
|
|
34
|
+
typeof value === "object" &&
|
|
35
|
+
"host" in value &&
|
|
36
|
+
typeof value.host === "string" &&
|
|
37
|
+
value.host.length > 0 &&
|
|
38
|
+
"boot" in value &&
|
|
39
|
+
typeof value.boot === "string" &&
|
|
40
|
+
value.boot.length > 0 &&
|
|
41
|
+
"namespace" in value &&
|
|
42
|
+
typeof value.namespace === "string" &&
|
|
43
|
+
value.namespace.length > 0 &&
|
|
44
|
+
"started" in value &&
|
|
45
|
+
typeof value.started === "string" &&
|
|
46
|
+
/^\d+$/.test(value.started), "Invalid reservation identity");
|
|
47
|
+
identity = {
|
|
48
|
+
host: value.host,
|
|
49
|
+
boot: value.boot,
|
|
50
|
+
namespace: value.namespace,
|
|
51
|
+
started: value.started,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
bytes: value.bytes,
|
|
56
|
+
owner: {
|
|
57
|
+
id: owner.id,
|
|
58
|
+
host: owner.host,
|
|
59
|
+
pid: owner.pid,
|
|
60
|
+
createdAt: owner.createdAt,
|
|
61
|
+
repository: owner.repository,
|
|
62
|
+
...(identity ? { identity } : {}),
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function reservationLedger(value) {
|
|
67
|
+
if (value === undefined)
|
|
68
|
+
return { format: 2, reservations: {} };
|
|
69
|
+
invariant(value &&
|
|
70
|
+
typeof value === "object" &&
|
|
71
|
+
"format" in value &&
|
|
72
|
+
(value.format === 1 || value.format === 2) &&
|
|
73
|
+
"reservations" in value &&
|
|
74
|
+
value.reservations &&
|
|
75
|
+
typeof value.reservations === "object" &&
|
|
76
|
+
!Array.isArray(value.reservations), "Invalid reservation ledger");
|
|
77
|
+
const legacy = value.format === 1;
|
|
78
|
+
const entries = Object.entries(value.reservations).map(([id, entry]) => {
|
|
79
|
+
invariant(reservationIdPattern.test(id), "Invalid reservation identifier");
|
|
80
|
+
return [id, record(legacy ? { bytes: entry } : entry)];
|
|
81
|
+
});
|
|
82
|
+
return { format: 2, reservations: Object.fromEntries(entries) };
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=reservation-ledger.js.map
|