10 KiB
host
(no submodules)
- conflict — Resolves the per-op `conflict` policy on…-
apply — (no submodules)- conflict — Resolves the per-op
conflictpolicy on… -
conflict — Resolves the per-op
conflictpolicy on a target that already exists. Five policies are supported:error(raise `APP… -
json-merge — Implements the deep-merge semantics used by
patch-jsonops withconflict: "merge". Match the conventions of `@suave… -
text-patch — Applies an ordered sequence of
TextEdits to a string. Used bypatch-textops to make targeted insertions/deletions/… -
detect — Runs a plugin's optional
detectstage inside an OpenTelemetry span. The plugin reports what is already present in the… -
host — (no submodules)- conflict — Resolves the per-op
conflictpolicy on… -
plan — Invokes
plugin.plan(answers, ctx)and validates the returnedFileOp[]againstFileOpsSchemabefore letting them f… -
post-install — Runs the plugin's optional
postInstallstage with abort propagation. This is where plugins do follow-up work that doe… -
prompts — Runs the plugin's optional
promptsstage and validates the answers against the schema the plugin returns. This is whe… -
conflict — Resolves the per-op
conflictpolicy on… -
apply — (no submodules)- conflict — Resolves the per-op
conflictpolicy on… -
conflict — Resolves the per-op
conflictpolicy on a target that already exists. Five policies are supported:error(raise `APP… -
json-merge — Implements the deep-merge semantics used by
patch-jsonops withconflict: "merge". Match the conventions of `@suave… -
text-patch — Applies an ordered sequence of
TextEdits to a string. Used bypatch-textops to make targeted insertions/deletions/… -
detect — Runs a plugin's optional
detectstage inside an OpenTelemetry span. The plugin reports what is already present in the… -
host — (no submodules)- conflict — Resolves the per-op
conflictpolicy on… -
plan — Invokes
plugin.plan(answers, ctx)and validates the returnedFileOp[]againstFileOpsSchemabefore letting them f… -
post-install — Runs the plugin's optional
postInstallstage with abort propagation. This is where plugins do follow-up work that doe… -
prompts — Runs the plugin's optional
promptsstage and validates the answers against the schema the plugin returns. This is whe… -
conflict — Resolves the per-op
conflictpolicy on… -
apply — (no submodules)- conflict — Resolves the per-op
conflictpolicy on… -
conflict — Resolves the per-op
conflictpolicy on a target that already exists. Five policies are supported:error(raise `APP… -
json-merge — Implements the deep-merge semantics used by
patch-jsonops withconflict: "merge". Match the conventions of `@suave… -
text-patch — Applies an ordered sequence of
TextEdits to a string. Used bypatch-textops to make targeted insertions/deletions/… -
detect — Runs a plugin's optional
detectstage inside an OpenTelemetry span. The plugin reports what is already present in the… -
host — (no submodules)- conflict — Resolves the per-op
conflictpolicy on… -
plan — Invokes
plugin.plan(answers, ctx)and validates the returnedFileOp[]againstFileOpsSchemabefore letting them f… -
post-install — Runs the plugin's optional
postInstallstage with abort propagation. This is where plugins do follow-up work that doe… -
prompts — Runs the plugin's optional
promptsstage and validates the answers against the schema the plugin returns. This is whe… -
conflict — Resolves the per-op
conflictpolicy on… -
apply — (no submodules)- conflict — Resolves the per-op
conflictpolicy on… -
conflict — Resolves the per-op
conflictpolicy on a target that already exists. Five policies are supported:error(raise `APP… -
json-merge — Implements the deep-merge semantics used by
patch-jsonops withconflict: "merge". Match the conventions of `@suave… -
text-patch — Applies an ordered sequence of
TextEdits to a string. Used bypatch-textops to make targeted insertions/deletions/… -
detect — Runs a plugin's optional
detectstage 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 returnedFileOp[]againstFileOpsSchemabefore letting them f… -
post-install — Runs the plugin's optional
postInstallstage with abort propagation. This is where plugins do follow-up work that doe… -
prompts — Runs the plugin's optional
promptsstage and validates the answers against the schema the plugin returns. This is whe… -
apply — (no submodules)- conflict — Resolves the per-op
conflictpolicy on a target that already exists. Five policies are supported:error(raise `APP… -
json-merge — Implements the deep-merge semantics used by
patch-jsonops withconflict: "merge". Match the conventions of `@suave… -
text-patch — Applies an ordered sequence of
TextEdits to a string. Used bypatch-textops to make targeted insertions/deletions/… -
detect — Runs a plugin's optional
detectstage 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 returnedFileOp[]againstFileOpsSchemabefore letting them f… -
post-install — Runs the plugin's optional
postInstallstage with abort propagation. This is where plugins do follow-up work that doe… -
prompts — Runs the plugin's optional
promptsstage 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.ABORTEDand 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.tofor renames,op.pathotherwise) before apply runs.answersFromFilechannel — 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>— addsanswersFromFile?: unknownfor 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.