opensip-cli 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 +202 -0
- package/NOTICE +8 -0
- package/README.md +51 -0
- package/dist/api.d.ts +17 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +16 -0
- package/dist/api.js.map +1 -0
- package/dist/bootstrap/admit-tool-package.d.ts +117 -0
- package/dist/bootstrap/admit-tool-package.d.ts.map +1 -0
- package/dist/bootstrap/admit-tool-package.js +170 -0
- package/dist/bootstrap/admit-tool-package.js.map +1 -0
- package/dist/bootstrap/baseline-seams.d.ts +30 -0
- package/dist/bootstrap/baseline-seams.d.ts.map +1 -0
- package/dist/bootstrap/baseline-seams.js +156 -0
- package/dist/bootstrap/baseline-seams.js.map +1 -0
- package/dist/bootstrap/bootstrap-error.d.ts +41 -0
- package/dist/bootstrap/bootstrap-error.d.ts.map +1 -0
- package/dist/bootstrap/bootstrap-error.js +33 -0
- package/dist/bootstrap/bootstrap-error.js.map +1 -0
- package/dist/bootstrap/build-command-registration-input.d.ts +34 -0
- package/dist/bootstrap/build-command-registration-input.d.ts.map +1 -0
- package/dist/bootstrap/build-command-registration-input.js +73 -0
- package/dist/bootstrap/build-command-registration-input.js.map +1 -0
- package/dist/bootstrap/build-per-run-scope.d.ts +62 -0
- package/dist/bootstrap/build-per-run-scope.d.ts.map +1 -0
- package/dist/bootstrap/build-per-run-scope.js +152 -0
- package/dist/bootstrap/build-per-run-scope.js.map +1 -0
- package/dist/bootstrap/build-targets.d.ts +42 -0
- package/dist/bootstrap/build-targets.d.ts.map +1 -0
- package/dist/bootstrap/build-targets.js +117 -0
- package/dist/bootstrap/build-targets.js.map +1 -0
- package/dist/bootstrap/cli-defaults.d.ts +35 -0
- package/dist/bootstrap/cli-defaults.d.ts.map +1 -0
- package/dist/bootstrap/cli-defaults.js +65 -0
- package/dist/bootstrap/cli-defaults.js.map +1 -0
- package/dist/bootstrap/config-and-capabilities.d.ts +74 -0
- package/dist/bootstrap/config-and-capabilities.d.ts.map +1 -0
- package/dist/bootstrap/config-and-capabilities.js +224 -0
- package/dist/bootstrap/config-and-capabilities.js.map +1 -0
- package/dist/bootstrap/deliver-envelope.d.ts +80 -0
- package/dist/bootstrap/deliver-envelope.d.ts.map +1 -0
- package/dist/bootstrap/deliver-envelope.js +195 -0
- package/dist/bootstrap/deliver-envelope.js.map +1 -0
- package/dist/bootstrap/egress-plane.d.ts +22 -0
- package/dist/bootstrap/egress-plane.d.ts.map +1 -0
- package/dist/bootstrap/egress-plane.js +37 -0
- package/dist/bootstrap/egress-plane.js.map +1 -0
- package/dist/bootstrap/host-planes.d.ts +28 -0
- package/dist/bootstrap/host-planes.d.ts.map +1 -0
- package/dist/bootstrap/host-planes.js +152 -0
- package/dist/bootstrap/host-planes.js.map +1 -0
- package/dist/bootstrap/index.d.ts +76 -0
- package/dist/bootstrap/index.d.ts.map +1 -0
- package/dist/bootstrap/index.js +109 -0
- package/dist/bootstrap/index.js.map +1 -0
- package/dist/bootstrap/live-plane.d.ts +51 -0
- package/dist/bootstrap/live-plane.d.ts.map +1 -0
- package/dist/bootstrap/live-plane.js +72 -0
- package/dist/bootstrap/live-plane.js.map +1 -0
- package/dist/bootstrap/load-tool-capabilities.d.ts +42 -0
- package/dist/bootstrap/load-tool-capabilities.d.ts.map +1 -0
- package/dist/bootstrap/load-tool-capabilities.js +76 -0
- package/dist/bootstrap/load-tool-capabilities.js.map +1 -0
- package/dist/bootstrap/output-plane.d.ts +37 -0
- package/dist/bootstrap/output-plane.d.ts.map +1 -0
- package/dist/bootstrap/output-plane.js +114 -0
- package/dist/bootstrap/output-plane.js.map +1 -0
- package/dist/bootstrap/owning-tool-init.d.ts +32 -0
- package/dist/bootstrap/owning-tool-init.d.ts.map +1 -0
- package/dist/bootstrap/owning-tool-init.js +69 -0
- package/dist/bootstrap/owning-tool-init.js.map +1 -0
- package/dist/bootstrap/pre-action-guards.d.ts +44 -0
- package/dist/bootstrap/pre-action-guards.d.ts.map +1 -0
- package/dist/bootstrap/pre-action-guards.js +136 -0
- package/dist/bootstrap/pre-action-guards.js.map +1 -0
- package/dist/bootstrap/pre-action-hook.d.ts +68 -0
- package/dist/bootstrap/pre-action-hook.d.ts.map +1 -0
- package/dist/bootstrap/pre-action-hook.js +289 -0
- package/dist/bootstrap/pre-action-hook.js.map +1 -0
- package/dist/bootstrap/pre-action-messages.d.ts +32 -0
- package/dist/bootstrap/pre-action-messages.d.ts.map +1 -0
- package/dist/bootstrap/pre-action-messages.js +49 -0
- package/dist/bootstrap/pre-action-messages.js.map +1 -0
- package/dist/bootstrap/process-idempotency.d.ts +17 -0
- package/dist/bootstrap/process-idempotency.d.ts.map +1 -0
- package/dist/bootstrap/process-idempotency.js +20 -0
- package/dist/bootstrap/process-idempotency.js.map +1 -0
- package/dist/bootstrap/register-language-adapters.d.ts +23 -0
- package/dist/bootstrap/register-language-adapters.d.ts.map +1 -0
- package/dist/bootstrap/register-language-adapters.js +35 -0
- package/dist/bootstrap/register-language-adapters.js.map +1 -0
- package/dist/bootstrap/register-tools.d.ts +228 -0
- package/dist/bootstrap/register-tools.d.ts.map +1 -0
- package/dist/bootstrap/register-tools.js +696 -0
- package/dist/bootstrap/register-tools.js.map +1 -0
- package/dist/bootstrap/render.d.ts +27 -0
- package/dist/bootstrap/render.d.ts.map +1 -0
- package/dist/bootstrap/render.js +53 -0
- package/dist/bootstrap/render.js.map +1 -0
- package/dist/bootstrap/report.d.ts +34 -0
- package/dist/bootstrap/report.d.ts.map +1 -0
- package/dist/bootstrap/report.js +47 -0
- package/dist/bootstrap/report.js.map +1 -0
- package/dist/bootstrap/run-plane.d.ts +105 -0
- package/dist/bootstrap/run-plane.d.ts.map +1 -0
- package/dist/bootstrap/run-plane.js +190 -0
- package/dist/bootstrap/run-plane.js.map +1 -0
- package/dist/bootstrap/scope-access.d.ts +68 -0
- package/dist/bootstrap/scope-access.d.ts.map +1 -0
- package/dist/bootstrap/scope-access.js +115 -0
- package/dist/bootstrap/scope-access.js.map +1 -0
- package/dist/bootstrap/state-seams.d.ts +14 -0
- package/dist/bootstrap/state-seams.d.ts.map +1 -0
- package/dist/bootstrap/state-seams.js +26 -0
- package/dist/bootstrap/state-seams.js.map +1 -0
- package/dist/bootstrap/tool-lifecycle.d.ts +102 -0
- package/dist/bootstrap/tool-lifecycle.d.ts.map +1 -0
- package/dist/bootstrap/tool-lifecycle.js +103 -0
- package/dist/bootstrap/tool-lifecycle.js.map +1 -0
- package/dist/bootstrap/tool-trust.d.ts +49 -0
- package/dist/bootstrap/tool-trust.d.ts.map +1 -0
- package/dist/bootstrap/tool-trust.js +65 -0
- package/dist/bootstrap/tool-trust.js.map +1 -0
- package/dist/bootstrap/validate-tool.d.ts +22 -0
- package/dist/bootstrap/validate-tool.d.ts.map +1 -0
- package/dist/bootstrap/validate-tool.js +38 -0
- package/dist/bootstrap/validate-tool.js.map +1 -0
- package/dist/cli-context.d.ts +38 -0
- package/dist/cli-context.d.ts.map +1 -0
- package/dist/cli-context.js +134 -0
- package/dist/cli-context.js.map +1 -0
- package/dist/commands/agent-catalog.d.ts +45 -0
- package/dist/commands/agent-catalog.d.ts.map +1 -0
- package/dist/commands/agent-catalog.js +115 -0
- package/dist/commands/agent-catalog.js.map +1 -0
- package/dist/commands/assemble-outcome.d.ts +69 -0
- package/dist/commands/assemble-outcome.d.ts.map +1 -0
- package/dist/commands/assemble-outcome.js +121 -0
- package/dist/commands/assemble-outcome.js.map +1 -0
- package/dist/commands/clear.d.ts +32 -0
- package/dist/commands/clear.d.ts.map +1 -0
- package/dist/commands/clear.js +73 -0
- package/dist/commands/clear.js.map +1 -0
- package/dist/commands/completion.d.ts +90 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +233 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/configure.d.ts +32 -0
- package/dist/commands/configure.d.ts.map +1 -0
- package/dist/commands/configure.js +94 -0
- package/dist/commands/configure.js.map +1 -0
- package/dist/commands/history.d.ts +18 -0
- package/dist/commands/history.d.ts.map +1 -0
- package/dist/commands/history.js +48 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/host-command-specs.d.ts +49 -0
- package/dist/commands/host-command-specs.d.ts.map +1 -0
- package/dist/commands/host-command-specs.js +331 -0
- package/dist/commands/host-command-specs.js.map +1 -0
- package/dist/commands/host-subcommand-groups.d.ts +69 -0
- package/dist/commands/host-subcommand-groups.d.ts.map +1 -0
- package/dist/commands/host-subcommand-groups.js +374 -0
- package/dist/commands/host-subcommand-groups.js.map +1 -0
- package/dist/commands/index.d.ts +36 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +36 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init/config-templates.d.ts +16 -0
- package/dist/commands/init/config-templates.d.ts.map +1 -0
- package/dist/commands/init/config-templates.js +108 -0
- package/dist/commands/init/config-templates.js.map +1 -0
- package/dist/commands/init/file-classifier.d.ts +40 -0
- package/dist/commands/init/file-classifier.d.ts.map +1 -0
- package/dist/commands/init/file-classifier.js +155 -0
- package/dist/commands/init/file-classifier.js.map +1 -0
- package/dist/commands/init/language-detection.d.ts +44 -0
- package/dist/commands/init/language-detection.d.ts.map +1 -0
- package/dist/commands/init/language-detection.js +124 -0
- package/dist/commands/init/language-detection.js.map +1 -0
- package/dist/commands/init/scaffold-writer.d.ts +26 -0
- package/dist/commands/init/scaffold-writer.d.ts.map +1 -0
- package/dist/commands/init/scaffold-writer.js +102 -0
- package/dist/commands/init/scaffold-writer.js.map +1 -0
- package/dist/commands/init/state-machine.d.ts +32 -0
- package/dist/commands/init/state-machine.d.ts.map +1 -0
- package/dist/commands/init/state-machine.js +105 -0
- package/dist/commands/init/state-machine.js.map +1 -0
- package/dist/commands/init.d.ts +95 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +209 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/mount-command-spec.d.ts +106 -0
- package/dist/commands/mount-command-spec.d.ts.map +1 -0
- package/dist/commands/mount-command-spec.js +313 -0
- package/dist/commands/mount-command-spec.js.map +1 -0
- package/dist/commands/mount-result-command.d.ts +71 -0
- package/dist/commands/mount-result-command.d.ts.map +1 -0
- package/dist/commands/mount-result-command.js +76 -0
- package/dist/commands/mount-result-command.js.map +1 -0
- package/dist/commands/plugin/config-edit.d.ts +20 -0
- package/dist/commands/plugin/config-edit.d.ts.map +1 -0
- package/dist/commands/plugin/config-edit.js +102 -0
- package/dist/commands/plugin/config-edit.js.map +1 -0
- package/dist/commands/plugin/domain-resolution.d.ts +38 -0
- package/dist/commands/plugin/domain-resolution.d.ts.map +1 -0
- package/dist/commands/plugin/domain-resolution.js +98 -0
- package/dist/commands/plugin/domain-resolution.js.map +1 -0
- package/dist/commands/plugin/host-dir.d.ts +42 -0
- package/dist/commands/plugin/host-dir.d.ts.map +1 -0
- package/dist/commands/plugin/host-dir.js +168 -0
- package/dist/commands/plugin/host-dir.js.map +1 -0
- package/dist/commands/plugin-host-ops.d.ts +41 -0
- package/dist/commands/plugin-host-ops.d.ts.map +1 -0
- package/dist/commands/plugin-host-ops.js +114 -0
- package/dist/commands/plugin-host-ops.js.map +1 -0
- package/dist/commands/plugin.d.ts +81 -0
- package/dist/commands/plugin.d.ts.map +1 -0
- package/dist/commands/plugin.js +287 -0
- package/dist/commands/plugin.js.map +1 -0
- package/dist/commands/render-outcome.d.ts +52 -0
- package/dist/commands/render-outcome.d.ts.map +1 -0
- package/dist/commands/render-outcome.js +55 -0
- package/dist/commands/render-outcome.js.map +1 -0
- package/dist/commands/session-show.d.ts +27 -0
- package/dist/commands/session-show.d.ts.map +1 -0
- package/dist/commands/session-show.js +166 -0
- package/dist/commands/session-show.js.map +1 -0
- package/dist/commands/shared.d.ts +107 -0
- package/dist/commands/shared.d.ts.map +1 -0
- package/dist/commands/shared.js +13 -0
- package/dist/commands/shared.js.map +1 -0
- package/dist/commands/tools/data-purge.d.ts +20 -0
- package/dist/commands/tools/data-purge.d.ts.map +1 -0
- package/dist/commands/tools/data-purge.js +59 -0
- package/dist/commands/tools/data-purge.js.map +1 -0
- package/dist/commands/tools/index.d.ts +16 -0
- package/dist/commands/tools/index.d.ts.map +1 -0
- package/dist/commands/tools/index.js +213 -0
- package/dist/commands/tools/index.js.map +1 -0
- package/dist/commands/tools/install.d.ts +24 -0
- package/dist/commands/tools/install.d.ts.map +1 -0
- package/dist/commands/tools/install.js +83 -0
- package/dist/commands/tools/install.js.map +1 -0
- package/dist/commands/tools/list.d.ts +41 -0
- package/dist/commands/tools/list.d.ts.map +1 -0
- package/dist/commands/tools/list.js +103 -0
- package/dist/commands/tools/list.js.map +1 -0
- package/dist/commands/tools/runtime-probe-entry.d.ts +14 -0
- package/dist/commands/tools/runtime-probe-entry.d.ts.map +1 -0
- package/dist/commands/tools/runtime-probe-entry.js +36 -0
- package/dist/commands/tools/runtime-probe-entry.js.map +1 -0
- package/dist/commands/tools/runtime-probe.d.ts +29 -0
- package/dist/commands/tools/runtime-probe.d.ts.map +1 -0
- package/dist/commands/tools/runtime-probe.js +66 -0
- package/dist/commands/tools/runtime-probe.js.map +1 -0
- package/dist/commands/tools/storage-contract-checks.d.ts +37 -0
- package/dist/commands/tools/storage-contract-checks.d.ts.map +1 -0
- package/dist/commands/tools/storage-contract-checks.js +91 -0
- package/dist/commands/tools/storage-contract-checks.js.map +1 -0
- package/dist/commands/tools/uninstall.d.ts +29 -0
- package/dist/commands/tools/uninstall.d.ts.map +1 -0
- package/dist/commands/tools/uninstall.js +77 -0
- package/dist/commands/tools/uninstall.js.map +1 -0
- package/dist/commands/tools/validate.d.ts +44 -0
- package/dist/commands/tools/validate.d.ts.map +1 -0
- package/dist/commands/tools/validate.js +202 -0
- package/dist/commands/tools/validate.js.map +1 -0
- package/dist/commands/uninstall/targets.d.ts +53 -0
- package/dist/commands/uninstall/targets.d.ts.map +1 -0
- package/dist/commands/uninstall/targets.js +205 -0
- package/dist/commands/uninstall/targets.js.map +1 -0
- package/dist/commands/uninstall.d.ts +88 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +184 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/env/host-env-specs.d.ts +52 -0
- package/dist/env/host-env-specs.d.ts.map +1 -0
- package/dist/env/host-env-specs.js +129 -0
- package/dist/env/host-env-specs.js.map +1 -0
- package/dist/error-handler.d.ts +64 -0
- package/dist/error-handler.d.ts.map +1 -0
- package/dist/error-handler.js +180 -0
- package/dist/error-handler.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +154 -0
- package/dist/index.js.map +1 -0
- package/dist/open-report.d.ts +40 -0
- package/dist/open-report.d.ts.map +1 -0
- package/dist/open-report.js +54 -0
- package/dist/open-report.js.map +1 -0
- package/dist/report-compose.d.ts +35 -0
- package/dist/report-compose.d.ts.map +1 -0
- package/dist/report-compose.js +103 -0
- package/dist/report-compose.js.map +1 -0
- package/dist/session-replay-registry.d.ts +20 -0
- package/dist/session-replay-registry.d.ts.map +1 -0
- package/dist/session-replay-registry.js +38 -0
- package/dist/session-replay-registry.js.map +1 -0
- package/dist/telemetry/profiling.d.ts +42 -0
- package/dist/telemetry/profiling.d.ts.map +1 -0
- package/dist/telemetry/profiling.js +160 -0
- package/dist/telemetry/profiling.js.map +1 -0
- package/dist/telemetry/sdk-init.d.ts +87 -0
- package/dist/telemetry/sdk-init.d.ts.map +1 -0
- package/dist/telemetry/sdk-init.js +235 -0
- package/dist/telemetry/sdk-init.js.map +1 -0
- package/dist/ui/App.d.ts +32 -0
- package/dist/ui/App.d.ts.map +1 -0
- package/dist/ui/App.js +35 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/render.d.ts +15 -0
- package/dist/ui/render.d.ts.map +1 -0
- package/dist/ui/render.js +21 -0
- package/dist/ui/render.js.map +1 -0
- package/dist/ui/result-to-view.d.ts +40 -0
- package/dist/ui/result-to-view.d.ts.map +1 -0
- package/dist/ui/result-to-view.js +389 -0
- package/dist/ui/result-to-view.js.map +1 -0
- package/dist/ui/views/init-view.d.ts +9 -0
- package/dist/ui/views/init-view.d.ts.map +1 -0
- package/dist/ui/views/init-view.js +119 -0
- package/dist/ui/views/init-view.js.map +1 -0
- package/dist/ui/views/misc-views.d.ts +18 -0
- package/dist/ui/views/misc-views.d.ts.map +1 -0
- package/dist/ui/views/misc-views.js +244 -0
- package/dist/ui/views/misc-views.js.map +1 -0
- package/dist/ui/views/plugin-view.d.ts +8 -0
- package/dist/ui/views/plugin-view.d.ts.map +1 -0
- package/dist/ui/views/plugin-view.js +135 -0
- package/dist/ui/views/plugin-view.js.map +1 -0
- package/dist/ui/views/tools-views.d.ts +12 -0
- package/dist/ui/views/tools-views.d.ts.map +1 -0
- package/dist/ui/views/tools-views.js +152 -0
- package/dist/ui/views/tools-views.js.map +1 -0
- package/dist/update-notifier.d.ts +108 -0
- package/dist/update-notifier.d.ts.map +1 -0
- package/dist/update-notifier.js +188 -0
- package/dist/update-notifier.js.map +1 -0
- package/dist/update-state.d.ts +40 -0
- package/dist/update-state.d.ts.map +1 -0
- package/dist/update-state.js +81 -0
- package/dist/update-state.js.map +1 -0
- package/dist/welcome.d.ts +53 -0
- package/dist/welcome.d.ts.map +1 -0
- package/dist/welcome.js +89 -0
- package/dist/welcome.js.map +1 -0
- package/package.json +100 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mount-command-spec — the host-owned layer that turns a declarative
|
|
3
|
+
* {@link CommandSpec} (core, Phase 0) into a wired Commander command.
|
|
4
|
+
*
|
|
5
|
+
* Generalizes {@link mountResultCommand}: it mounts ANY command (tool or host)
|
|
6
|
+
* from its typed spec — translating each `OptionSpec`/`ArgSpec` into Commander
|
|
7
|
+
* wiring, applying the shared common flags (ADR-0021), and owning the uniform
|
|
8
|
+
* `parse → handler → dispatch output → map error → exit` pipeline. Tools never
|
|
9
|
+
* touch Commander; they export specs and the host mounts them (north-star §5.4).
|
|
10
|
+
*
|
|
11
|
+
* The single output-dispatch seam — {@link dispatchOutput} — wraps every machine
|
|
12
|
+
* output in a `CommandOutcome` serialized through the one `renderOutcome` seam.
|
|
13
|
+
* The wrap lives in the host emit seams this delegates to (`emitCommandResult`,
|
|
14
|
+
* `ctx.emitEnvelope`), so the handler contract stayed byte-identical (§5.5).
|
|
15
|
+
*/
|
|
16
|
+
import { applyCommonFlags, mapToolErrorToExitCode, } from '@opensip-cli/contracts';
|
|
17
|
+
import { ToolError, currentScope, } from '@opensip-cli/core';
|
|
18
|
+
import { Option } from 'commander';
|
|
19
|
+
import { emitCommandResult } from './mount-result-command.js';
|
|
20
|
+
/**
|
|
21
|
+
* Mount a declarative {@link CommandSpec} onto `program` as a fully wired
|
|
22
|
+
* Commander command.
|
|
23
|
+
*
|
|
24
|
+
* Steps (mirroring each tool's former hand-rolled `register()` body, now
|
|
25
|
+
* host-owned and uniform):
|
|
26
|
+
* 1. `program.command(name)` + description + aliases.
|
|
27
|
+
* 2. `applyCommonFlags(cmd, spec.commonFlags)` — the ADR-0021 registry flags.
|
|
28
|
+
* `cwd` (the only computed default) is seeded with `process.cwd()`.
|
|
29
|
+
* 3. Each {@link OptionSpec} → a Commander `Option` (value vs boolean,
|
|
30
|
+
* `negatable` `--no-` form, `default` / `arrayDefault`, `choices`,
|
|
31
|
+
* `parse` argParser, `variadic`, `required` mandatory).
|
|
32
|
+
* 4. Each {@link ArgSpec} → `cmd.argument(...)` (variadic / optional bracketing).
|
|
33
|
+
* 5. `cmd.action(...)` → run `spec.handler(opts, ctx)` → {@link dispatchOutput}
|
|
34
|
+
* → on a thrown {@link ToolError}, `mapToolErrorToExitCode` → `ctx.setExitCode`.
|
|
35
|
+
*
|
|
36
|
+
* @param program The root Commander program (the entry layer's `CliProgram`).
|
|
37
|
+
* @param spec The declarative command surface the tool/host exported.
|
|
38
|
+
* @param ctx The per-invocation host context (render/envelope/live-view
|
|
39
|
+
* emitters, exit-code setter) — today's `ToolCliContext`.
|
|
40
|
+
*/
|
|
41
|
+
export function mountCommandSpec(program, spec, ctx) {
|
|
42
|
+
const cmd = program.command(spec.name).description(spec.description);
|
|
43
|
+
if (spec.aliases !== undefined && spec.aliases.length > 0) {
|
|
44
|
+
cmd.aliases([...spec.aliases]);
|
|
45
|
+
}
|
|
46
|
+
// ADR-0021 common flags. `cwd` is the only flag with a computed (per-
|
|
47
|
+
// invocation) default; the registry leaves it to the caller, so seed it here.
|
|
48
|
+
const seedsCwd = spec.commonFlags.includes('cwd');
|
|
49
|
+
applyCommonFlags(cmd, spec.commonFlags, seedsCwd ? { cwd: process.cwd() } : undefined);
|
|
50
|
+
for (const optionSpec of spec.options ?? []) {
|
|
51
|
+
cmd.addOption(buildOption(optionSpec, spec.name));
|
|
52
|
+
}
|
|
53
|
+
for (const argSpec of spec.args ?? []) {
|
|
54
|
+
cmd.argument(formatArgUsage(argSpec), argSpec.description);
|
|
55
|
+
}
|
|
56
|
+
// Action body: parse → handler → dispatch → map error → exit. Commander
|
|
57
|
+
// passes positional args first, then the parsed-opts object, then the
|
|
58
|
+
// Command. We forward the parsed opts (which carry both common + spec flags)
|
|
59
|
+
// and the trailing positional args to the handler and the dispatch seam.
|
|
60
|
+
//
|
|
61
|
+
// Positionals ride on the opts object under the `_args` key — the same
|
|
62
|
+
// convention the `live-view` dispatch arm already uses (`{ ...opts, _args }`).
|
|
63
|
+
// This lets a `raw-stream`/`signal-envelope`/`command-result` handler that
|
|
64
|
+
// declares `args` read its positionals (`opts._args`) without a separate
|
|
65
|
+
// handler-arity contract: graph's `[paths...]`, `<name>`, `<specPath>` all
|
|
66
|
+
// flow through here. Commands with no declared `args` get an empty array.
|
|
67
|
+
cmd.action(async (...actionArgs) => {
|
|
68
|
+
const { opts, positionals } = splitActionArgs(actionArgs);
|
|
69
|
+
const optsWithArgs = { ...opts, _args: positionals };
|
|
70
|
+
// Lifecycle diagnostics (§5.10): bracket the handler with `execute` events so
|
|
71
|
+
// every CommandOutcome carries a record that this command ran. Scope-bound via
|
|
72
|
+
// the pre-action hook's enterScope; a no-op when no scope is present (tests).
|
|
73
|
+
const diagnostics = currentScope()?.diagnostics;
|
|
74
|
+
diagnostics?.event('execute', 'debug', `command '${spec.name}' started`);
|
|
75
|
+
// Host run lifecycle (host-owned-run-timing): mark the start boundary at the
|
|
76
|
+
// command-action entry — after RunScope is entered, before the tool handler
|
|
77
|
+
// runs. The hooks ride on the host ctx (not the public ToolCliContext type);
|
|
78
|
+
// read via cast, like `runSession` below. No-op for host commands whose
|
|
79
|
+
// leaner context carries no run plane.
|
|
80
|
+
const runHooks = ctx;
|
|
81
|
+
runHooks.beginRun?.();
|
|
82
|
+
try {
|
|
83
|
+
const result = await spec.handler(optsWithArgs, ctx);
|
|
84
|
+
diagnostics?.event('execute', 'debug', `command '${spec.name}' completed`);
|
|
85
|
+
// Static-path completion: if the handler returned a ToolRunCompletion with
|
|
86
|
+
// a session contribution, the host freezes the lifecycle and persists it.
|
|
87
|
+
// A plain CommandResult (no session) is a no-op — there is no tool-side
|
|
88
|
+
// generic-session writer. The live-view path persists after renderLive.
|
|
89
|
+
runHooks.completeRun?.(result);
|
|
90
|
+
await dispatchOutput(result, spec, optsWithArgs, positionals, ctx);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
if (error instanceof ToolError) {
|
|
94
|
+
diagnostics?.event('execute', 'error', `command '${spec.name}' failed: ${error.message}`);
|
|
95
|
+
ctx.setExitCode(mapToolErrorToExitCode(error));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The SINGLE output-dispatch seam. The launch `CommandOutcome` wrap is LANDED:
|
|
104
|
+
* the host emit seams this delegates to (`emitCommandResult`, `ctx.emitEnvelope`)
|
|
105
|
+
* now build a `CommandOutcome` and serialize it through the one `renderOutcome`
|
|
106
|
+
* seam. The handler contract and the mounter above stayed byte-identical — all
|
|
107
|
+
* the outer-shape change landed in those seams (north-star §5.5), so the handler
|
|
108
|
+
* keeps returning its pure-domain `CommandResult` / `SignalEnvelope`.
|
|
109
|
+
*
|
|
110
|
+
* Routes the handler's return value by the command's declared
|
|
111
|
+
* {@link CommandSpec.output} mode:
|
|
112
|
+
* - `command-result` — the existing `emitCommandResult` seam (json
|
|
113
|
+
* short-circuit / `ctx.render`), shared verbatim with
|
|
114
|
+
* {@link mountResultCommand}.
|
|
115
|
+
* - `signal-envelope` — the run-envelope machine-output path: `--json` emits
|
|
116
|
+
* through `ctx.emitEnvelope` (the shared ADR-0011
|
|
117
|
+
* formatter), otherwise `ctx.render`.
|
|
118
|
+
* - `raw-stream` — explicit raw output (no Ink): the handler already
|
|
119
|
+
* wrote its file + line; the host renders nothing.
|
|
120
|
+
* - `live-view` — the interactive Ink path: `ctx.renderLive(key, args)`
|
|
121
|
+
* against the tool's registered renderer.
|
|
122
|
+
*
|
|
123
|
+
* @throws {Error} When a command declares `signal-envelope` / `live-view` output
|
|
124
|
+
* but the mount context provides no `emitEnvelope` / `renderLive` emitter — a
|
|
125
|
+
* mis-declared host spec fails loudly here rather than silently no-op'ing.
|
|
126
|
+
*/
|
|
127
|
+
export async function dispatchOutput(result, spec, opts, positionals, ctx) {
|
|
128
|
+
const jsonRequested = opts.json === true;
|
|
129
|
+
switch (spec.output) {
|
|
130
|
+
case 'command-result': {
|
|
131
|
+
await emitCommandResult(result, {
|
|
132
|
+
render: (r) => ctx.render(r),
|
|
133
|
+
jsonRequested,
|
|
134
|
+
});
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
case 'signal-envelope': {
|
|
138
|
+
if (jsonRequested) {
|
|
139
|
+
if (ctx.emitEnvelope === undefined) {
|
|
140
|
+
throw new Error(`mountCommandSpec: command '${spec.name}' declares output 'signal-envelope' ` +
|
|
141
|
+
'but the mount context provides no emitEnvelope (host commands are ' +
|
|
142
|
+
"'command-result' / 'raw-stream' only).");
|
|
143
|
+
}
|
|
144
|
+
ctx.emitEnvelope(result);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
await ctx.render(result);
|
|
148
|
+
}
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
case 'raw-stream': {
|
|
152
|
+
// The handler is responsible for its own stdout / file IO (a documented
|
|
153
|
+
// exception: completion scripts, baseline/SARIF exports). Nothing to
|
|
154
|
+
// render — the host does not touch the stream.
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
case 'live-view': {
|
|
158
|
+
// Dispatch to the tool's registered Ink renderer, keyed by the command
|
|
159
|
+
// NAME (the tool registers its renderer under that key in its setup
|
|
160
|
+
// hook — sim under 'sim', graph under 'graph'). The host forwards the
|
|
161
|
+
// parsed opts + trailing positionals as the args payload; the handler's
|
|
162
|
+
// return value is unused for this mode (the Ink app owns rendering).
|
|
163
|
+
if (ctx.renderLive === undefined) {
|
|
164
|
+
throw new Error(`mountCommandSpec: command '${spec.name}' declares output 'live-view' ` +
|
|
165
|
+
'but the mount context provides no renderLive (host commands are ' +
|
|
166
|
+
"'command-result' / 'raw-stream' only).");
|
|
167
|
+
}
|
|
168
|
+
// Thread the host-owned runSession (via LiveViewContext) so the live
|
|
169
|
+
// renderer receives the *same* timer the static path used. Only full
|
|
170
|
+
// ToolCliContext (tool live-view commands) will have runSession; lean
|
|
171
|
+
// host contexts won't reach here.
|
|
172
|
+
const liveContext = ctx.runSession
|
|
173
|
+
? { runSession: ctx.runSession }
|
|
174
|
+
: undefined;
|
|
175
|
+
await ctx.renderLive(spec.name, { ...opts, _args: positionals }, liveContext);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Build a Commander {@link Option} from an {@link OptionSpec}, covering every
|
|
182
|
+
* shape in the first-party flag corpus: boolean / value, negatable `--no-`,
|
|
183
|
+
* literal `default` and repeatable `arrayDefault`, `choices`, the pure `parse`
|
|
184
|
+
* argParser, variadic, and `required` (mandatory).
|
|
185
|
+
*
|
|
186
|
+
* @throws {Error} When the spec marks a boolean (valueless) option `required`
|
|
187
|
+
* — only value options can be made mandatory.
|
|
188
|
+
*/
|
|
189
|
+
function buildOption(spec, commandName) {
|
|
190
|
+
const valuePlaceholder = resolveValuePlaceholder(spec);
|
|
191
|
+
const flags = valuePlaceholder === undefined ? spec.flag : `${spec.flag} ${valuePlaceholder}`;
|
|
192
|
+
const option = new Option(flags, spec.description);
|
|
193
|
+
if (spec.choices !== undefined && spec.choices.length > 0) {
|
|
194
|
+
option.choices([...spec.choices]);
|
|
195
|
+
}
|
|
196
|
+
if (spec.parse !== undefined) {
|
|
197
|
+
// Commander's argParser is `(value, previous) => next` — exactly the
|
|
198
|
+
// declared `OptionSpec.parse` reducer shape (Number coercion, repeatable
|
|
199
|
+
// accumulation, validated ints).
|
|
200
|
+
option.argParser(spec.parse);
|
|
201
|
+
}
|
|
202
|
+
// `arrayDefault` (repeatable accumulators) wins over a scalar `default`;
|
|
203
|
+
// Commander uses it as the seed the `parse` reducer accumulates onto.
|
|
204
|
+
if (spec.arrayDefault !== undefined) {
|
|
205
|
+
option.default([...spec.arrayDefault]);
|
|
206
|
+
}
|
|
207
|
+
else if (spec.default !== undefined) {
|
|
208
|
+
option.default(spec.default);
|
|
209
|
+
}
|
|
210
|
+
if (spec.required === true) {
|
|
211
|
+
if (valuePlaceholder === undefined) {
|
|
212
|
+
throw new Error(`mountCommandSpec: command '${commandName}' option '${spec.flag}' is required but takes no value; ` +
|
|
213
|
+
'only value options can be required.');
|
|
214
|
+
}
|
|
215
|
+
option.makeOptionMandatory(true);
|
|
216
|
+
}
|
|
217
|
+
return option;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Resolve the value placeholder for an option, applying variadic `...` when
|
|
221
|
+
* declared. Returns `undefined` for a boolean / negatable flag (no value).
|
|
222
|
+
*/
|
|
223
|
+
function resolveValuePlaceholder(spec) {
|
|
224
|
+
if (spec.negatable === true)
|
|
225
|
+
return undefined;
|
|
226
|
+
if (spec.value === undefined)
|
|
227
|
+
return undefined;
|
|
228
|
+
if (spec.variadic === true && !spec.value.includes('...')) {
|
|
229
|
+
// Inject the variadic ellipsis inside the existing bracket pair, e.g.
|
|
230
|
+
// `<slug>` → `<slug...>`, `[path]` → `[path...]`.
|
|
231
|
+
return spec.value.replace(/([>\]])$/, '...$1');
|
|
232
|
+
}
|
|
233
|
+
return spec.value;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Format an {@link ArgSpec} into Commander argument-usage syntax: `<name>`
|
|
237
|
+
* (required), `[name]` (optional), with `...` appended for variadic.
|
|
238
|
+
*/
|
|
239
|
+
function formatArgUsage(spec) {
|
|
240
|
+
const inner = spec.variadic === true ? `${spec.name}...` : spec.name;
|
|
241
|
+
return spec.optional === true ? `[${inner}]` : `<${inner}>`;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Best-effort guard: does `x` look like a Commander `Command` instance?
|
|
245
|
+
* Used defensively in splitActionArgs so we never treat the Command object
|
|
246
|
+
* as the parsed opts (which would silently give every handler a weird
|
|
247
|
+
* `opts` bag containing Commander internals and produce very confusing bugs).
|
|
248
|
+
*/
|
|
249
|
+
function isLikelyCommanderCommand(x) {
|
|
250
|
+
if (!x || typeof x !== 'object')
|
|
251
|
+
return false;
|
|
252
|
+
const c = x;
|
|
253
|
+
// Commander Command instances have these characteristic members.
|
|
254
|
+
return (typeof c.name === 'function' ||
|
|
255
|
+
typeof c.opts === 'function' ||
|
|
256
|
+
typeof c.command === 'function' ||
|
|
257
|
+
(typeof c.constructor === 'function' && /Command/i.test(c.constructor.name || '')));
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Split a Commander action callback's variadic arguments into the parsed-opts
|
|
261
|
+
* object and the trailing positional args.
|
|
262
|
+
*
|
|
263
|
+
* Commander calls `action((...positionalArgs, optsObject, command))`: the
|
|
264
|
+
* declared positionals come first, then the parsed-options object, then the
|
|
265
|
+
* `Command` instance. We locate the opts object by scanning left from the
|
|
266
|
+
* slot before the final Command for the rightmost plain (non-array, non-Command)
|
|
267
|
+
* object. Everything before that index is treated as positionals.
|
|
268
|
+
*
|
|
269
|
+
* This scan is robust: positionals (typically strings/paths for variadics) are
|
|
270
|
+
* never inspected for "object-ness" during the search, so a defensive walk
|
|
271
|
+
* cannot accidentally eat legitimate leading positionals when an intermediate
|
|
272
|
+
* value looks unusual (future Commander arity change, wrappers, etc.).
|
|
273
|
+
*
|
|
274
|
+
* If no plausible opts object is found, we treat the entire prefix before the
|
|
275
|
+
* Command as positionals and opts as {} (fail-closed paranoia below still applies).
|
|
276
|
+
*
|
|
277
|
+
* @throws {Error} On the defensive, normally-unreachable path where no opts object
|
|
278
|
+
* can be located among the action arguments (surfaced loudly so tests/CI catch it).
|
|
279
|
+
*/
|
|
280
|
+
function splitActionArgs(actionArgs) {
|
|
281
|
+
if (actionArgs.length === 0) {
|
|
282
|
+
return { opts: {}, positionals: [] };
|
|
283
|
+
}
|
|
284
|
+
const lastIdx = actionArgs.length - 1;
|
|
285
|
+
// The final argument is (per Commander contract) the Command instance.
|
|
286
|
+
if (!isLikelyCommanderCommand(actionArgs[lastIdx])) {
|
|
287
|
+
// Extremely unexpected — log via throw so tests/CI surface it loudly.
|
|
288
|
+
throw new Error('mountCommandSpec: splitActionArgs could not locate Commander Command as the final action argument. ' +
|
|
289
|
+
'This indicates an incompatible Commander version or a wrapped dispatch. ' +
|
|
290
|
+
'Please report this with your Commander version.');
|
|
291
|
+
}
|
|
292
|
+
// Scan left from the slot immediately before the Command. The first (rightmost)
|
|
293
|
+
// plain non-array non-Command object we encounter is the parsed opts.
|
|
294
|
+
for (let i = lastIdx - 1; i >= 0; i--) {
|
|
295
|
+
const v = actionArgs[i];
|
|
296
|
+
if (v && typeof v === 'object' && !Array.isArray(v) && !isLikelyCommanderCommand(v)) {
|
|
297
|
+
const opts = v;
|
|
298
|
+
const positionals = actionArgs.slice(0, i);
|
|
299
|
+
// Extra paranoia: if what we selected smells like Command, refuse.
|
|
300
|
+
if (isLikelyCommanderCommand(opts)) {
|
|
301
|
+
throw new Error('mountCommandSpec: splitActionArgs selected a Commander Command as the parsed opts. ' +
|
|
302
|
+
'Refusing to dispatch — this is a bug in argument splitting.');
|
|
303
|
+
}
|
|
304
|
+
return { opts, positionals };
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// No plain opts object found before the Command (defensive). All prior args
|
|
308
|
+
// become positionals; the handler will see a bare {} for opts (still better
|
|
309
|
+
// than handing it a Command or corrupting _args).
|
|
310
|
+
const positionals = actionArgs.slice(0, lastIdx);
|
|
311
|
+
return { opts: {}, positionals };
|
|
312
|
+
}
|
|
313
|
+
//# sourceMappingURL=mount-command-spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount-command-spec.js","sourceRoot":"","sources":["../../src/commands/mount-command-spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mount-result-command — action-body helper for CLI-owned subcommands
|
|
3
|
+
* that produce a `CommandResult`.
|
|
4
|
+
*
|
|
5
|
+
* Centralizes the per-subcommand boilerplate every result-producing
|
|
6
|
+
* action body would otherwise repeat:
|
|
7
|
+
*
|
|
8
|
+
* - Run the supplied handler (sync or async).
|
|
9
|
+
* - If `--json` was set, emit the result as JSON to stdout and bail
|
|
10
|
+
* before Ink starts. Bypassing the renderer keeps `--json`
|
|
11
|
+
* contract-faithful: machine consumers should never see ANSI
|
|
12
|
+
* escapes or Ink's whitespace adjustments.
|
|
13
|
+
* - Otherwise route the result through the renderer the dispatcher
|
|
14
|
+
* wired into the context.
|
|
15
|
+
*
|
|
16
|
+
* Two shapes are exposed:
|
|
17
|
+
*
|
|
18
|
+
* - `mountResultCommand(cmd, handler)` — opts-only handler. Used by
|
|
19
|
+
* `init`, `sessions list`, `plugin list`, `plugin sync`.
|
|
20
|
+
* - `mountResultCommandWithArg(cmd, handler)` — single-positional-arg
|
|
21
|
+
* handler. Used by `plugin add` / `plugin remove`.
|
|
22
|
+
*
|
|
23
|
+
* Phase 5 of the Layer 5 plan introduces this helper; Phase 6 routes
|
|
24
|
+
* `clear` and `configure` through it (eliminating the last raw-ANSI
|
|
25
|
+
* bypasses).
|
|
26
|
+
*/
|
|
27
|
+
import type { CliCommandsContext } from './shared.js';
|
|
28
|
+
import type { CommandResult } from '@opensip-cli/contracts';
|
|
29
|
+
import type { Command } from 'commander';
|
|
30
|
+
export type CommandHandler<TOpts> = (opts: TOpts) => CommandResult | Promise<CommandResult>;
|
|
31
|
+
export interface MountResultCommandOptions<TOpts> {
|
|
32
|
+
readonly ctx: CliCommandsContext;
|
|
33
|
+
/**
|
|
34
|
+
* Pull the `--json` flag value out of the parsed Commander options.
|
|
35
|
+
* The `--json` flag itself is the caller's responsibility — they
|
|
36
|
+
* declare it on their `Command` before mounting. The mount helper
|
|
37
|
+
* doesn't add the flag so each subcommand can keep its own help text.
|
|
38
|
+
*/
|
|
39
|
+
readonly jsonFlag?: (opts: TOpts) => boolean | undefined;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Mount a result-producing handler as the action body of `cmd`.
|
|
43
|
+
* The handler returns a `CommandResult`; `mountResultCommand` handles
|
|
44
|
+
* the `--json` short-circuit and the Ink render dispatch.
|
|
45
|
+
*/
|
|
46
|
+
export declare function mountResultCommand<TOpts>(cmd: Command, handler: CommandHandler<TOpts>, opts: MountResultCommandOptions<TOpts>): void;
|
|
47
|
+
export type CommandHandlerWithArg<TArg, TOpts> = (arg: TArg, opts: TOpts) => CommandResult | Promise<CommandResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Same as `mountResultCommand` but for commands that take exactly one
|
|
50
|
+
* positional argument (e.g. `plugin add <package>`). Commander passes
|
|
51
|
+
* the positional arg before the parsed opts.
|
|
52
|
+
*/
|
|
53
|
+
export declare function mountResultCommandWithArg<TArg, TOpts>(cmd: Command, handler: CommandHandlerWithArg<TArg, TOpts>, opts: MountResultCommandOptions<TOpts>): void;
|
|
54
|
+
/**
|
|
55
|
+
* The shared `command-result` dispatch seam, extracted so the declarative
|
|
56
|
+
* `mountCommandSpec` (the `output: 'command-result'` arm of `dispatchOutput`) and
|
|
57
|
+
* the imperative `mountResultCommand` route a `CommandResult` through ONE point
|
|
58
|
+
* instead of duplicating the json-short-circuit / `render` decision.
|
|
59
|
+
*
|
|
60
|
+
* launch (§5.5): the result is wrapped in a `CommandOutcome` (`.data`, or
|
|
61
|
+
* `.errors` for an `ErrorResult`) and serialized through the single
|
|
62
|
+
* `renderOutcome` seam. `--json` emits the whole outcome; human mode renders the
|
|
63
|
+
* inner result through the supplied renderer — byte-identical to the prior human
|
|
64
|
+
* output. Machine consumers must never see ANSI escapes, so the JSON path never
|
|
65
|
+
* renders.
|
|
66
|
+
*/
|
|
67
|
+
export declare function emitCommandResult(result: CommandResult, opts: {
|
|
68
|
+
readonly render: (result: CommandResult) => Promise<void>;
|
|
69
|
+
readonly jsonRequested: boolean;
|
|
70
|
+
}): Promise<void>;
|
|
71
|
+
//# sourceMappingURL=mount-result-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount-result-command.d.ts","sourceRoot":"","sources":["../../src/commands/mount-result-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,MAAM,cAAc,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5F,MAAM,WAAW,yBAAyB,CAAC,KAAK;IAC9C,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAC;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,GAAG,SAAS,CAAC;CAC1D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EACtC,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,EAC9B,IAAI,EAAE,yBAAyB,CAAC,KAAK,CAAC,GACrC,IAAI,CAKN;AAED,MAAM,MAAM,qBAAqB,CAAC,IAAI,EAAE,KAAK,IAAI,CAC/C,GAAG,EAAE,IAAI,EACT,IAAI,EAAE,KAAK,KACR,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5C;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,KAAK,EACnD,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,qBAAqB,CAAC,IAAI,EAAE,KAAK,CAAC,EAC3C,IAAI,EAAE,yBAAyB,CAAC,KAAK,CAAC,GACrC,IAAI,CAKN;AAaD;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE;IACJ,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC,GACA,OAAO,CAAC,IAAI,CAAC,CAKf"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mount-result-command — action-body helper for CLI-owned subcommands
|
|
3
|
+
* that produce a `CommandResult`.
|
|
4
|
+
*
|
|
5
|
+
* Centralizes the per-subcommand boilerplate every result-producing
|
|
6
|
+
* action body would otherwise repeat:
|
|
7
|
+
*
|
|
8
|
+
* - Run the supplied handler (sync or async).
|
|
9
|
+
* - If `--json` was set, emit the result as JSON to stdout and bail
|
|
10
|
+
* before Ink starts. Bypassing the renderer keeps `--json`
|
|
11
|
+
* contract-faithful: machine consumers should never see ANSI
|
|
12
|
+
* escapes or Ink's whitespace adjustments.
|
|
13
|
+
* - Otherwise route the result through the renderer the dispatcher
|
|
14
|
+
* wired into the context.
|
|
15
|
+
*
|
|
16
|
+
* Two shapes are exposed:
|
|
17
|
+
*
|
|
18
|
+
* - `mountResultCommand(cmd, handler)` — opts-only handler. Used by
|
|
19
|
+
* `init`, `sessions list`, `plugin list`, `plugin sync`.
|
|
20
|
+
* - `mountResultCommandWithArg(cmd, handler)` — single-positional-arg
|
|
21
|
+
* handler. Used by `plugin add` / `plugin remove`.
|
|
22
|
+
*
|
|
23
|
+
* Phase 5 of the Layer 5 plan introduces this helper; Phase 6 routes
|
|
24
|
+
* `clear` and `configure` through it (eliminating the last raw-ANSI
|
|
25
|
+
* bypasses).
|
|
26
|
+
*/
|
|
27
|
+
import { outcomeFromResult } from './assemble-outcome.js';
|
|
28
|
+
import { renderOutcome } from './render-outcome.js';
|
|
29
|
+
/**
|
|
30
|
+
* Mount a result-producing handler as the action body of `cmd`.
|
|
31
|
+
* The handler returns a `CommandResult`; `mountResultCommand` handles
|
|
32
|
+
* the `--json` short-circuit and the Ink render dispatch.
|
|
33
|
+
*/
|
|
34
|
+
export function mountResultCommand(cmd, handler, opts) {
|
|
35
|
+
cmd.action(async (parsedOpts) => {
|
|
36
|
+
const result = await handler(parsedOpts);
|
|
37
|
+
await emit(result, opts, parsedOpts);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Same as `mountResultCommand` but for commands that take exactly one
|
|
42
|
+
* positional argument (e.g. `plugin add <package>`). Commander passes
|
|
43
|
+
* the positional arg before the parsed opts.
|
|
44
|
+
*/
|
|
45
|
+
export function mountResultCommandWithArg(cmd, handler, opts) {
|
|
46
|
+
cmd.action(async (arg, parsedOpts) => {
|
|
47
|
+
const result = await handler(arg, parsedOpts);
|
|
48
|
+
await emit(result, opts, parsedOpts);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async function emit(result, opts, parsedOpts) {
|
|
52
|
+
await emitCommandResult(result, {
|
|
53
|
+
render: opts.ctx.render,
|
|
54
|
+
jsonRequested: opts.jsonFlag?.(parsedOpts) ?? false,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The shared `command-result` dispatch seam, extracted so the declarative
|
|
59
|
+
* `mountCommandSpec` (the `output: 'command-result'` arm of `dispatchOutput`) and
|
|
60
|
+
* the imperative `mountResultCommand` route a `CommandResult` through ONE point
|
|
61
|
+
* instead of duplicating the json-short-circuit / `render` decision.
|
|
62
|
+
*
|
|
63
|
+
* launch (§5.5): the result is wrapped in a `CommandOutcome` (`.data`, or
|
|
64
|
+
* `.errors` for an `ErrorResult`) and serialized through the single
|
|
65
|
+
* `renderOutcome` seam. `--json` emits the whole outcome; human mode renders the
|
|
66
|
+
* inner result through the supplied renderer — byte-identical to the prior human
|
|
67
|
+
* output. Machine consumers must never see ANSI escapes, so the JSON path never
|
|
68
|
+
* renders.
|
|
69
|
+
*/
|
|
70
|
+
export async function emitCommandResult(result, opts) {
|
|
71
|
+
await renderOutcome(outcomeFromResult(result, 0), {
|
|
72
|
+
jsonRequested: opts.jsonRequested,
|
|
73
|
+
render: opts.render,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=mount-result-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount-result-command.js","sourceRoot":"","sources":["../../src/commands/mount-result-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAmBpD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,GAAY,EACZ,OAA8B,EAC9B,IAAsC;IAEtC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,UAAiB,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;QACzC,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC;AAOD;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CACvC,GAAY,EACZ,OAA2C,EAC3C,IAAsC;IAEtC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,GAAS,EAAE,UAAiB,EAAE,EAAE;QAChD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAC9C,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,IAAI,CACjB,MAAqB,EACrB,IAAsC,EACtC,UAAiB;IAEjB,MAAM,iBAAiB,CAAC,MAAM,EAAE;QAC9B,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM;QACvB,aAAa,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,IAAI,KAAK;KACpD,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAqB,EACrB,IAGC;IAED,MAAM,aAAa,CAAC,iBAAiB,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE;QAChD,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview YAML-driven edits to `plugins.<domain>` in
|
|
3
|
+
* `opensip-cli.config.yml`.
|
|
4
|
+
*
|
|
5
|
+
* Extracted from `commands/plugin.ts` to keep that module focused on
|
|
6
|
+
* Commander wiring + the npm install/uninstall flows. The Document API
|
|
7
|
+
* round-trips comments, ordering, and whitespace; a malformed document
|
|
8
|
+
* fails closed so the caller surfaces a clear error.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Edit the project's `plugins.<domain>` list. Returns true when the
|
|
12
|
+
* file was changed.
|
|
13
|
+
*
|
|
14
|
+
* @throws Error when the YAML document is malformed or its root is not
|
|
15
|
+
* a mapping. The caller surfaces a "your config is broken" message.
|
|
16
|
+
*/
|
|
17
|
+
export declare function editPluginList(configPath: string, domain: string, name: string, op: 'add' | 'remove'): boolean;
|
|
18
|
+
export declare function addToConfigPluginList(configPath: string, domain: string, name: string): boolean;
|
|
19
|
+
export declare function removeFromConfigPluginList(configPath: string, domain: string, name: string): boolean;
|
|
20
|
+
//# sourceMappingURL=config-edit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-edit.d.ts","sourceRoot":"","sources":["../../../src/commands/plugin/config-edit.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAcH;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,KAAK,GAAG,QAAQ,GACnB,OAAO,CAwCT;AAuDD,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE/F;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAET"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// @fitness-ignore-file silent-early-returns -- config-edit helpers (editPluginList/appendToPluginList/removeFromPluginList) return boolean as their documented "did I modify?" contract: false means "no-op / idempotent (already present, already absent, nothing to remove)"; explicit idempotency signals, not silent failures.
|
|
2
|
+
// @fitness-ignore-file unbounded-memory -- reads opensip-cli.config.yml; bounded by configuration shape.
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview YAML-driven edits to `plugins.<domain>` in
|
|
5
|
+
* `opensip-cli.config.yml`.
|
|
6
|
+
*
|
|
7
|
+
* Extracted from `commands/plugin.ts` to keep that module focused on
|
|
8
|
+
* Commander wiring + the npm install/uninstall flows. The Document API
|
|
9
|
+
* round-trips comments, ordering, and whitespace; a malformed document
|
|
10
|
+
* fails closed so the caller surfaces a clear error.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { parseDocument, isMap, isScalar, isSeq, } from 'yaml';
|
|
14
|
+
/**
|
|
15
|
+
* Edit the project's `plugins.<domain>` list. Returns true when the
|
|
16
|
+
* file was changed.
|
|
17
|
+
*
|
|
18
|
+
* @throws Error when the YAML document is malformed or its root is not
|
|
19
|
+
* a mapping. The caller surfaces a "your config is broken" message.
|
|
20
|
+
*/
|
|
21
|
+
export function editPluginList(configPath, domain, name, op) {
|
|
22
|
+
if (!existsSync(configPath)) {
|
|
23
|
+
if (op === 'remove')
|
|
24
|
+
return false;
|
|
25
|
+
// No config to edit — write a minimal one.
|
|
26
|
+
writeFileSync(configPath, `plugins:\n ${domain}:\n - "${name}"\n`, 'utf8');
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
const text = readFileSync(configPath, 'utf8');
|
|
30
|
+
const doc = parseDocument(text);
|
|
31
|
+
if (doc.errors.length > 0) {
|
|
32
|
+
const first = doc.errors[0]?.message ?? 'unknown YAML error';
|
|
33
|
+
throw new Error(`Cannot edit plugins.${domain} in ${configPath}: ${first}. ` +
|
|
34
|
+
`Fix the syntax error and re-run.`);
|
|
35
|
+
}
|
|
36
|
+
const root = doc.contents;
|
|
37
|
+
if (root === null) {
|
|
38
|
+
if (op === 'remove')
|
|
39
|
+
return false;
|
|
40
|
+
// Empty doc — write a fresh `plugins:` map.
|
|
41
|
+
writeFileSync(configPath, `plugins:\n ${domain}:\n - "${name}"\n`, 'utf8');
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
// The top-level node must be a YAML map. A scalar / sequence at
|
|
45
|
+
// the root means the file isn't an opensip-cli config — refuse
|
|
46
|
+
// to edit rather than reformat the whole thing.
|
|
47
|
+
if (!isMap(root)) {
|
|
48
|
+
throw new Error(`Cannot edit plugins.${domain} in ${configPath}: top-level node is not a mapping. ` +
|
|
49
|
+
`opensip-cli.config.yml must start with a YAML map.`);
|
|
50
|
+
}
|
|
51
|
+
if (op === 'add') {
|
|
52
|
+
return appendToPluginList(doc, root, domain, name, configPath);
|
|
53
|
+
}
|
|
54
|
+
return removeFromPluginList(doc, root, domain, name, configPath);
|
|
55
|
+
}
|
|
56
|
+
function appendToPluginList(doc, root, domain, name, configPath) {
|
|
57
|
+
let plugins = root.get('plugins');
|
|
58
|
+
if (!isMap(plugins)) {
|
|
59
|
+
plugins = doc.createNode({});
|
|
60
|
+
root.set('plugins', plugins);
|
|
61
|
+
}
|
|
62
|
+
const pluginsMap = plugins;
|
|
63
|
+
let list = pluginsMap.get(domain);
|
|
64
|
+
if (!isSeq(list)) {
|
|
65
|
+
list = doc.createNode([]);
|
|
66
|
+
pluginsMap.set(domain, list);
|
|
67
|
+
}
|
|
68
|
+
const seq = list;
|
|
69
|
+
// Idempotent — first occurrence wins.
|
|
70
|
+
for (const item of seq.items) {
|
|
71
|
+
const value = isScalar(item) ? item.value : item;
|
|
72
|
+
if (value === name)
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
seq.add(name);
|
|
76
|
+
writeFileSync(configPath, doc.toString(), 'utf8');
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
function removeFromPluginList(doc, root, domain, name, configPath) {
|
|
80
|
+
const plugins = root.get('plugins');
|
|
81
|
+
if (!isMap(plugins))
|
|
82
|
+
return false;
|
|
83
|
+
const list = plugins.get(domain);
|
|
84
|
+
if (!isSeq(list))
|
|
85
|
+
return false;
|
|
86
|
+
const before = list.items.length;
|
|
87
|
+
list.items = list.items.filter((item) => {
|
|
88
|
+
const value = isScalar(item) ? item.value : item;
|
|
89
|
+
return value !== name;
|
|
90
|
+
});
|
|
91
|
+
if (list.items.length === before)
|
|
92
|
+
return false;
|
|
93
|
+
writeFileSync(configPath, doc.toString(), 'utf8');
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
export function addToConfigPluginList(configPath, domain, name) {
|
|
97
|
+
return editPluginList(configPath, domain, name, 'add');
|
|
98
|
+
}
|
|
99
|
+
export function removeFromConfigPluginList(configPath, domain, name) {
|
|
100
|
+
return editPluginList(configPath, domain, name, 'remove');
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=config-edit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-edit.js","sourceRoot":"","sources":["../../../src/commands/plugin/config-edit.ts"],"names":[],"mappings":"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"}
|