Files
skills/docs/devtools/tooling/installer/src/host/host.md
2026-05-29 08:20:56 +01:00

10 KiB

host

(no submodules)

- conflict — Resolves the per-op `conflict` policy on…
  • apply — (no submodules)- conflict — Resolves the per-op conflict policy on…

  • conflict — Resolves the per-op conflict policy on a target that already exists. Five policies are supported: error (raise `APP…

  • json-merge — Implements the deep-merge semantics used by patch-json ops with conflict: "merge". Match the conventions of `@suave…

  • text-patch — Applies an ordered sequence of TextEdits to a string. Used by patch-text ops to make targeted insertions/deletions/…

  • detect — Runs a plugin's optional detect stage inside an OpenTelemetry span. The plugin reports what is already present in the…

  • host — (no submodules)- conflict — Resolves the per-op conflict policy on…

  • plan — Invokes plugin.plan(answers, ctx) and validates the returned FileOp[] against FileOpsSchema before letting them f…

  • post-install — Runs the plugin's optional postInstall stage with abort propagation. This is where plugins do follow-up work that doe…

  • prompts — Runs the plugin's optional prompts stage and validates the answers against the schema the plugin returns. This is whe…

  • conflict — Resolves the per-op conflict policy on…

  • apply — (no submodules)- conflict — Resolves the per-op conflict policy on…

  • conflict — Resolves the per-op conflict policy on a target that already exists. Five policies are supported: error (raise `APP…

  • json-merge — Implements the deep-merge semantics used by patch-json ops with conflict: "merge". Match the conventions of `@suave…

  • text-patch — Applies an ordered sequence of TextEdits to a string. Used by patch-text ops to make targeted insertions/deletions/…

  • detect — Runs a plugin's optional detect stage inside an OpenTelemetry span. The plugin reports what is already present in the…

  • host — (no submodules)- conflict — Resolves the per-op conflict policy on…

  • plan — Invokes plugin.plan(answers, ctx) and validates the returned FileOp[] against FileOpsSchema before letting them f…

  • post-install — Runs the plugin's optional postInstall stage with abort propagation. This is where plugins do follow-up work that doe…

  • prompts — Runs the plugin's optional prompts stage and validates the answers against the schema the plugin returns. This is whe…

  • conflict — Resolves the per-op conflict policy on…

  • apply — (no submodules)- conflict — Resolves the per-op conflict policy on…

  • conflict — Resolves the per-op conflict policy on a target that already exists. Five policies are supported: error (raise `APP…

  • json-merge — Implements the deep-merge semantics used by patch-json ops with conflict: "merge". Match the conventions of `@suave…

  • text-patch — Applies an ordered sequence of TextEdits to a string. Used by patch-text ops to make targeted insertions/deletions/…

  • detect — Runs a plugin's optional detect stage inside an OpenTelemetry span. The plugin reports what is already present in the…

  • host — (no submodules)- conflict — Resolves the per-op conflict policy on…

  • plan — Invokes plugin.plan(answers, ctx) and validates the returned FileOp[] against FileOpsSchema before letting them f…

  • post-install — Runs the plugin's optional postInstall stage with abort propagation. This is where plugins do follow-up work that doe…

  • prompts — Runs the plugin's optional prompts stage and validates the answers against the schema the plugin returns. This is whe…

  • conflict — Resolves the per-op conflict policy on…

  • apply — (no submodules)- conflict — Resolves the per-op conflict policy on…

  • conflict — Resolves the per-op conflict policy on a target that already exists. Five policies are supported: error (raise `APP…

  • json-merge — Implements the deep-merge semantics used by patch-json ops with conflict: "merge". Match the conventions of `@suave…

  • text-patch — Applies an ordered sequence of TextEdits to a string. Used by patch-text ops to make targeted insertions/deletions/…

  • detect — Runs a plugin's optional detect stage inside an OpenTelemetry span. The plugin reports what is already present in the…

  • host — (no submodules)- apply — (no submodules)…

  • plan — Invokes plugin.plan(answers, ctx) and validates the returned FileOp[] against FileOpsSchema before letting them f…

  • post-install — Runs the plugin's optional postInstall stage with abort propagation. This is where plugins do follow-up work that doe…

  • prompts — Runs the plugin's optional prompts stage and validates the answers against the schema the plugin returns. This is whe…

  • apply — (no submodules)- conflict — Resolves the per-op conflict policy on a target that already exists. Five policies are supported: error (raise `APP…

  • json-merge — Implements the deep-merge semantics used by patch-json ops with conflict: "merge". Match the conventions of `@suave…

  • text-patch — Applies an ordered sequence of TextEdits to a string. Used by patch-text ops to make targeted insertions/deletions/…

  • detect — Runs a plugin's optional detect stage inside an OpenTelemetry span. The plugin reports what is already present in the…

  • host — (no submodules)- plan — Invokes plugin.plan(answers, ctx) and validates the returned FileOp[] against FileOpsSchema before letting them f…

  • post-install — Runs the plugin's optional postInstall stage with abort propagation. This is where plugins do follow-up work that doe…

  • prompts — Runs the plugin's optional prompts stage and validates the answers against the schema the plugin returns. This is whe…

Purpose

The plugin host. Host.run(plugin, options) executes the strict pipeline detect → prompts → plan → apply → postInstall, with abort propagation, --dry-run short-circuiting, and only/exclude filtering. Each stage is wrapped in an OpenTelemetry span (installer.<stage>) carrying plugin.id, plugin.version, and dry_run attributes — that instrumentation is what lets operators correlate apply failures with the specific plugin and version that produced them.

Features

  • Strict ordering — optional stages (detect, prompts, postInstall) are skipped without affecting the order of mandatory stages (plan, apply).
  • Abort checks at every stage boundary — if the signal aborts mid-run, the host raises INSTALLER.ABORTED and apply rolls back any partial work.
  • --dry-run — when set, the host returns the plan ops without invoking apply or postInstall.
  • only/exclude — substring filters applied to the op target path (op.to for renames, op.path otherwise) before apply runs.
  • answersFromFile channel — used by the bin's --answers <file> flag to feed pre-recorded answers into prompt validation without going interactive.

Basic Example

import { Host, MemoryFs } from "@suaveplan/installer";

const fs = new MemoryFs();
const host = new Host(
    {
        cwd: "/",
        fs,
        cli: { confirm: async () => false, prompt: async () => "", write: () => undefined },
        signal: new AbortController().signal,
        logger: {
            debug: () => undefined,
            info: () => undefined,
            warn: () => undefined,
            error: () => undefined,
        },
        templates: { render: (s) => s },
        dryRun: false,
        force: false,
        noInteractive: true,
    },
    fs
);
const result = await host.run(myPlugin);
console.log(result.summary);

Advanced Example

import { Host } from "@suaveplan/installer";

const ac = new AbortController();
const host = new Host({ ...ctx, signal: ac.signal, dryRun: true }, fs);

setTimeout(() => ac.abort(), 5_000);

const dryResult = await host.run(myPlugin, {
    only: ["crypto", "events"],
    exclude: ["legacy"],
});
console.log(`would apply ${dryResult.ops.length} ops`);

API Reference

  • class Host — constructed with (ctx: InstallerContext, fs: MutableInstallerFs).
  • Host.run<TAnswers, THandle>(plugin, options): Promise<HostRunResult<THandle>>
  • interface HostRunOptions<TAnswers> extends RunOptions<TAnswers> — adds answersFromFile?: unknown for the bin.
  • interface HostRunResult<THandle> — { detect, ops, summary, handle, dryRun }.

Implementation Notes

filterOps runs after plan but before apply, so the conformance guarantee that "every emitted op respects its conflict policy on re-run" applies to the post-filter set. --dry-run returns a synthetic summary (skipped = ops.length) so dashboards see a coherent counter even on hypothetical runs. Abort checks are placed at every awaitable boundary (after detect, after prompts, before apply) so a long-running prompt schema can be cancelled cleanly. applyOps itself owns the rollback journal — the host's only responsibility post-apply is to wire up postInstall with the resulting handle.