first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,171 @@
# @suaveplan/installer - Plugin host + lifecycle for project boilerplating and asset installation: detect → prompts → plan → apply → postInstall, transactional apply with rollback, conflict policies, manifest discovery.
## Summary
Plugin host for project boilerplating and asset installation. Pipelines
plugins through `detect → prompts → plan → apply → postInstall` with
transactional rollback, conflict resolution, and dry-run support.
<!-- begin:auto-docs -->
## Documentation tree
- [bin](./src/bin/suaveplan-install.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [suaveplan-install](./src/bin/suaveplan-install.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [disk-fs](./src/fs/disk-fs.md) — Disk-backed implementation of `MutableInstallerFs` used by the `suaveplan-install` bin and any host-side code that want…
- [installer-fs](./src/fs/installer-fs.md) — Re-exports the read-only `InstallerFs` interface from the types module and declares its mutating extension `MutableInst…
- [memory-fs](./src/fs/memory-fs.md) — In-memory implementation of `MutableInstallerFs`. Used by the testing harness (`runPlugin` constructs one if the caller…
- [host](./src/host/host.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs --> - conflict — Resolves the per-op `conflict` policy on…
- [apply](./src/host/apply/apply.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs --> - conflict — Resolves the per-op `conflict` policy on…
- [apply](./src/host/apply/apply.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs --> - conflict — Resolves the per-op `conflict` policy on…
- [conflict](./src/host/apply/conflict.md) — Resolves the per-op `conflict` policy on a target that already exists. Five policies are supported: `error` (raise `APP…
- [json-merge](./src/host/apply/json-merge.md) — Implements the deep-merge semantics used by `patch-json` ops with `conflict: "merge"`. Match the conventions of `@suave…
- [text-patch](./src/host/apply/text-patch.md) — Applies an ordered sequence of `TextEdit`s to a string. Used by `patch-text` ops to make targeted insertions/deletions/…
- [detect](./src/host/detect.md) — Runs a plugin's optional `detect` stage inside an OpenTelemetry span. The plugin reports what is already present in the…
- [host](./src/host/host.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs --> - conflict — Resolves the per-op `conflict` policy on…
- [plan](./src/host/plan.md) — Invokes `plugin.plan(answers, ctx)` and validates the returned `FileOp[]` against `FileOpsSchema` before letting them f…
- [post-install](./src/host/post-install.md) — Runs the plugin's optional `postInstall` stage with abort propagation. This is where plugins do follow-up work that doe…
- [prompts](./src/host/prompts.md) — Runs the plugin's optional `prompts` stage and validates the answers against the schema the plugin returns. This is whe…
- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [discover](./src/manifest/discover.md) — Walks the consumer's `node_modules` tree and returns every installer plugin matching the naming conventions: first-part…
- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [installer-fs.test-helpers](./src/testing/installer-fs.test-helpers.md) — Convenience helpers for assertions against the in-memory installer fs in plugin tests. `createMemoryFs(seed)` is a thin…
- [run-plugin](./src/testing/run-plugin.md) — End-to-end test harness for plugins. `runPlugin(plugin, options)` wires up an in-memory filesystem, a scripted CLI, a n…
- [script-cli](./src/testing/script-cli.md) — Non-TTY `InstallerCli` driven by pre-recorded answers. `ScriptCli` is the default CLI used by `runPlugin` — tests scrip…
- [error-codes](./src/error-codes.md) — Defines the canonical error-code registry for `@suaveplan/installer` and the `InstallerError` class that carries those…
<!-- end:auto-docs --> - [suaveplan-install](./src/bin/suaveplan-install.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [disk-fs](./src/fs/disk-fs.md) — Disk-backed implementation of `MutableInstallerFs` used by the `suaveplan-install` bin and any host-side code that want…
- [installer-fs](./src/fs/installer-fs.md) — Re-exports the read-only `InstallerFs` interface from the types module and declares its mutating extension `MutableInst…
- [memory-fs](./src/fs/memory-fs.md) — In-memory implementation of `MutableInstallerFs`. Used by the testing harness (`runPlugin` constructs one if the caller…
- [host](./src/host/host.md) — <!-- begin:auto-docs --> _(no submodules)_- conflict — Resolves the per-op `conflict` policy on…
- [apply](./src/host/apply/apply.md) — <!-- begin:auto-docs --> _(no submodules)_- conflict — Resolves the per-op `conflict` policy on…
- [apply](./src/host/apply/apply.md) — <!-- begin:auto-docs --> _(no submodules)_- conflict — Resolves the per-op `conflict` policy on…
- [conflict](./src/host/apply/conflict.md) — Resolves the per-op `conflict` policy on a target that already exists. Five policies are supported: `error` (raise `APP…
- [json-merge](./src/host/apply/json-merge.md) — Implements the deep-merge semantics used by `patch-json` ops with `conflict: "merge"`. Match the conventions of `@suave…
- [text-patch](./src/host/apply/text-patch.md) — Applies an ordered sequence of `TextEdit`s to a string. Used by `patch-text` ops to make targeted insertions/deletions/…
- [detect](./src/host/detect.md) — Runs a plugin's optional `detect` stage inside an OpenTelemetry span. The plugin reports what is already present in the…
- [host](./src/host/host.md) — <!-- begin:auto-docs --> _(no submodules)_- conflict — Resolves the per-op `conflict` policy on…
- [plan](./src/host/plan.md) — Invokes `plugin.plan(answers, ctx)` and validates the returned `FileOp[]` against `FileOpsSchema` before letting them f…
- [post-install](./src/host/post-install.md) — Runs the plugin's optional `postInstall` stage with abort propagation. This is where plugins do follow-up work that doe…
- [prompts](./src/host/prompts.md) — Runs the plugin's optional `prompts` stage and validates the answers against the schema the plugin returns. This is whe…
- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_- [discover](./src/manifest/discover.md) — Walks the consumer's `node_modules` tree and returns every installer plugin matching the naming conventions: first-part…
- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_- [installer-fs.test-helpers](./src/testing/installer-fs.test-helpers.md) — Convenience helpers for assertions against the in-memory installer fs in plugin tests. `createMemoryFs(seed)` is a thin…
- [run-plugin](./src/testing/run-plugin.md) — End-to-end test harness for plugins. `runPlugin(plugin, options)` wires up an in-memory filesystem, a scripted CLI, a n…
- [script-cli](./src/testing/script-cli.md) — Non-TTY `InstallerCli` driven by pre-recorded answers. `ScriptCli` is the default CLI used by `runPlugin` — tests scrip…
- [error-codes](./src/error-codes.md) — Defines the canonical error-code registry for `@suaveplan/installer` and the `InstallerError` class that carries those…
- [suaveplan-install](./src/bin/suaveplan-install.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [disk-fs](./src/fs/disk-fs.md) — Disk-backed implementation of `MutableInstallerFs` used by the `suaveplan-install` bin and any host-side code that want…
- [installer-fs](./src/fs/installer-fs.md) — Re-exports the read-only `InstallerFs` interface from the types module and declares its mutating extension `MutableInst…
- [memory-fs](./src/fs/memory-fs.md) — In-memory implementation of `MutableInstallerFs`. Used by the testing harness (`runPlugin` constructs one if the caller…
- [host](./src/host/host.md) — <!-- begin:auto-docs --> _(no submodules)_- conflict — Resolves the per-op `conflict` policy on…
- [apply](./src/host/apply/apply.md) — <!-- begin:auto-docs --> _(no submodules)_- conflict — Resolves the per-op `conflict` policy on…
- [apply](./src/host/apply/apply.md) — <!-- begin:auto-docs --> _(no submodules)_- conflict — Resolves the per-op `conflict` policy on…
- [conflict](./src/host/apply/conflict.md) — Resolves the per-op `conflict` policy on a target that already exists. Five policies are supported: `error` (raise `APP…
- [json-merge](./src/host/apply/json-merge.md) — Implements the deep-merge semantics used by `patch-json` ops with `conflict: "merge"`. Match the conventions of `@suave…
- [text-patch](./src/host/apply/text-patch.md) — Applies an ordered sequence of `TextEdit`s to a string. Used by `patch-text` ops to make targeted insertions/deletions/…
- [detect](./src/host/detect.md) — Runs a plugin's optional `detect` stage inside an OpenTelemetry span. The plugin reports what is already present in the…
- [host](./src/host/host.md) — <!-- begin:auto-docs --> _(no submodules)_- conflict — Resolves the per-op `conflict` policy on…
- [plan](./src/host/plan.md) — Invokes `plugin.plan(answers, ctx)` and validates the returned `FileOp[]` against `FileOpsSchema` before letting them f…
- [post-install](./src/host/post-install.md) — Runs the plugin's optional `postInstall` stage with abort propagation. This is where plugins do follow-up work that doe…
- [prompts](./src/host/prompts.md) — Runs the plugin's optional `prompts` stage and validates the answers against the schema the plugin returns. This is whe…
- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_- [discover](./src/manifest/discover.md) — Walks the consumer's `node_modules` tree and returns every installer plugin matching the naming conventions: first-part…
- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_- [installer-fs.test-helpers](./src/testing/installer-fs.test-helpers.md) — Convenience helpers for assertions against the in-memory installer fs in plugin tests. `createMemoryFs(seed)` is a thin…
- [run-plugin](./src/testing/run-plugin.md) — End-to-end test harness for plugins. `runPlugin(plugin, options)` wires up an in-memory filesystem, a scripted CLI, a n…
- [script-cli](./src/testing/script-cli.md) — Non-TTY `InstallerCli` driven by pre-recorded answers. `ScriptCli` is the default CLI used by `runPlugin` — tests scrip…
- [error-codes](./src/error-codes.md) — Defines the canonical error-code registry for `@suaveplan/installer` and the `InstallerError` class that carries those…
- [suaveplan-install](./src/bin/suaveplan-install.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [disk-fs](./src/fs/disk-fs.md) — Disk-backed implementation of `MutableInstallerFs` used by the `suaveplan-install` bin and any host-side code that want…
- [installer-fs](./src/fs/installer-fs.md) — Re-exports the read-only `InstallerFs` interface from the types module and declares its mutating extension `MutableInst…
- [memory-fs](./src/fs/memory-fs.md) — In-memory implementation of `MutableInstallerFs`. Used by the testing harness (`runPlugin` constructs one if the caller…
- [host](./src/host/host.md) — <!-- begin:auto-docs --> _(no submodules)_- apply — <!-- begin:auto-docs --> _(no submodules)_…
- [apply](./src/host/apply/apply.md) — <!-- begin:auto-docs --> _(no submodules)_- conflict — Resolves the per-op `conflict` policy on…
- [apply](./src/host/apply/apply.md) — <!-- begin:auto-docs --> _(no submodules)_- conflict — Resolves the per-op `conflict` policy on…
- [conflict](./src/host/apply/conflict.md) — Resolves the per-op `conflict` policy on a target that already exists. Five policies are supported: `error` (raise `APP…
- [json-merge](./src/host/apply/json-merge.md) — Implements the deep-merge semantics used by `patch-json` ops with `conflict: "merge"`. Match the conventions of `@suave…
- [text-patch](./src/host/apply/text-patch.md) — Applies an ordered sequence of `TextEdit`s to a string. Used by `patch-text` ops to make targeted insertions/deletions/…
- [detect](./src/host/detect.md) — Runs a plugin's optional `detect` stage inside an OpenTelemetry span. The plugin reports what is already present in the…
- [host](./src/host/host.md) — <!-- begin:auto-docs --> _(no submodules)_- apply — <!-- begin:auto-docs --> _(no submodules)_…
- [plan](./src/host/plan.md) — Invokes `plugin.plan(answers, ctx)` and validates the returned `FileOp[]` against `FileOpsSchema` before letting them f…
- [post-install](./src/host/post-install.md) — Runs the plugin's optional `postInstall` stage with abort propagation. This is where plugins do follow-up work that doe…
- [prompts](./src/host/prompts.md) — Runs the plugin's optional `prompts` stage and validates the answers against the schema the plugin returns. This is whe…
- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_- [discover](./src/manifest/discover.md) — Walks the consumer's `node_modules` tree and returns every installer plugin matching the naming conventions: first-part…
- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_- [installer-fs.test-helpers](./src/testing/installer-fs.test-helpers.md) — Convenience helpers for assertions against the in-memory installer fs in plugin tests. `createMemoryFs(seed)` is a thin…
- [run-plugin](./src/testing/run-plugin.md) — End-to-end test harness for plugins. `runPlugin(plugin, options)` wires up an in-memory filesystem, a scripted CLI, a n…
- [script-cli](./src/testing/script-cli.md) — Non-TTY `InstallerCli` driven by pre-recorded answers. `ScriptCli` is the default CLI used by `runPlugin` — tests scrip…
- [error-codes](./src/error-codes.md) — Defines the canonical error-code registry for `@suaveplan/installer` and the `InstallerError` class that carries those…
- [suaveplan-install](./src/bin/suaveplan-install.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_ - [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [disk-fs](./src/fs/disk-fs.md) — Disk-backed implementation of `MutableInstallerFs` used by the `suaveplan-install` bin and any host-side code that want…
- [installer-fs](./src/fs/installer-fs.md) — Re-exports the read-only `InstallerFs` interface from the types module and declares its mutating extension `MutableInst…
- [memory-fs](./src/fs/memory-fs.md) — In-memory implementation of `MutableInstallerFs`. Used by the testing harness (`runPlugin` constructs one if the caller…
- [host](./src/host/host.md) — <!-- begin:auto-docs --> _(no submodules)_ - [apply](./src/host/apply/apply.md) — <!-- begin:auto-docs --> _(no submodules)_ - [apply](./src/host/apply/apply.md) — <!-- begin:auto-docs --> _(no submodules)_ - [conflict](./src/host/apply/conflict.md) — Resolves the per-op `conflict` policy on a target that already exists. Five policies are supported: `error` (raise `APP…
- [json-merge](./src/host/apply/json-merge.md) — Implements the deep-merge semantics used by `patch-json` ops with `conflict: "merge"`. Match the conventions of `@suave…
- [text-patch](./src/host/apply/text-patch.md) — Applies an ordered sequence of `TextEdit`s to a string. Used by `patch-text` ops to make targeted insertions/deletions/…
- [detect](./src/host/detect.md) — Runs a plugin's optional `detect` stage inside an OpenTelemetry span. The plugin reports what is already present in the…
- [host](./src/host/host.md) — <!-- begin:auto-docs --> _(no submodules)_ - [plan](./src/host/plan.md) — Invokes `plugin.plan(answers, ctx)` and validates the returned `FileOp[]` against `FileOpsSchema` before letting them f…
- [post-install](./src/host/post-install.md) — Runs the plugin's optional `postInstall` stage with abort propagation. This is where plugins do follow-up work that doe…
- [prompts](./src/host/prompts.md) — Runs the plugin's optional `prompts` stage and validates the answers against the schema the plugin returns. This is whe…
- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_ - [discover](./src/manifest/discover.md) — Walks the consumer's `node_modules` tree and returns every installer plugin matching the naming conventions: first-part…
- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_- [installer-fs.test-helpers](./src/testing/installer-fs.test-helpers.md) — Convenience helpers for assertions against the in-memory installer fs in plugin tests. `createMemoryFs(seed)` is a thin…
- [run-plugin](./src/testing/run-plugin.md) — End-to-end test harness for plugins. `runPlugin(plugin, options)` wires up an in-memory filesystem, a scripted CLI, a n…
- [script-cli](./src/testing/script-cli.md) — Non-TTY `InstallerCli` driven by pre-recorded answers. `ScriptCli` is the default CLI used by `runPlugin` — tests scrip…
- [error-codes](./src/error-codes.md) — Defines the canonical error-code registry for `@suaveplan/installer` and the `InstallerError` class that carries those…
## Quickstart
```bash
# Add a plugin to your project as a dev dep, then run the installer
bun add -D @suaveplan/install-agent-skills
npx @suaveplan/installer add agent-skills
```
## Programmatic use
```ts
import {
Host,
DiskFs,
type InstallerContext,
} from "@suaveplan/installer";
const fs = new DiskFs({ cwd: process.cwd() });
const host = new Host(ctx, fs);
const result = await host.run(myPlugin, {
dryRun: false,
force: false,
noInteractive: true,
});
console.log(result.summary);
```
## Testing harness
```ts
import { runPlugin, ScriptCli } from "@suaveplan/installer";
const result = await runPlugin(myPlugin, {
answers: { name: "agent-skills" },
});
expect(result.summary.written).toBeGreaterThan(0);
```
## Subpath exports
- `@suaveplan/installer` — main barrel.
- `@suaveplan/installer/types` — types-only.
- `@suaveplan/installer/errors` — `INSTALLER_CODES`, `InstallerError`.
- `@suaveplan/installer/host` — `Host`, stage runners, apply/conflict
helpers.
- `@suaveplan/installer/fs` — `DiskFs`, `MemoryFs`, `MutableInstallerFs`.
- `@suaveplan/installer/manifest` — `discoverPlugins`, `findPlugin`,
`loadManifest`, `validateManifest`.
- `@suaveplan/installer/testing` — `runPlugin`, `ScriptCli`,
`assertWrote`, `createMemoryFs`.
## Module documentation
Every implementation file ships with a sibling `.md` covering Purpose,
Features, Usage examples, API Reference, and Implementation Notes. See
`src/host/host.md`, `src/host/apply/apply.md`, `src/manifest/discover.md`
for the load-bearing modules.
## License
MIT