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,76 @@
# `installer-fs`
## Purpose
Re-exports the read-only `InstallerFs` interface from the types module and
declares its mutating extension `MutableInstallerFs`. Plugins receive a
read-only `InstallerFs` through the context — they can describe writes via
`FileOp[]` but cannot perform them directly. The host uses
`MutableInstallerFs` internally to materialise ops with rollback. Keeping
the read/write split at the interface level is what makes `--dry-run`
trivially correct: a dry-run never resolves the mutating subset.
## Features
- Single source of truth for filesystem capability boundaries inside the
installer.
- `MutableInstallerFs` extends `InstallerFs` with `writeFile`, `deleteFile`,
`mkdir`, `rename`, and `writeJson`.
- Both `MemoryFs` and `DiskFs` implement `MutableInstallerFs`, but only the
read-only view is ever handed to plugin code.
## Basic Example
```ts
import { MemoryFs, type InstallerFs } from "@suaveplan/installer";
async function describe(fs: InstallerFs): Promise<number> {
const entries = await fs.listDir("/");
return entries.length;
}
const fs = new MemoryFs({ seed: { "/a.txt": "hi" } });
await describe(fs);
```
## Advanced Example
```ts
import {
type MutableInstallerFs,
MemoryFs,
} from "@suaveplan/installer";
async function backupThenWrite(
fs: MutableInstallerFs,
path: string,
next: Uint8Array
): Promise<void> {
if (await fs.exists(path)) {
const prior = await fs.readFile(path);
await fs.writeFile(`${path}.bak`, prior);
}
await fs.writeFile(path, next);
}
await backupThenWrite(new MemoryFs(), "/cfg.json", new Uint8Array([123, 125]));
```
## API Reference
- `interface InstallerFs` (re-export from `types/installer.types.ts`):
`exists`, `readFile`, `readJson`, `stat`, `listDir`, `pathOf`.
- `interface MutableInstallerFs extends InstallerFs`:
`writeFile(path, contents, mode?)`, `deleteFile(path)`, `mkdir(path)`,
`rename(from, to)`, `writeJson(path, value)`.
## Implementation Notes
`MutableInstallerFs` is exposed publicly through `./fs` so authors who want
to write a custom backing store (e.g. an S3-backed installer fs) have a
single contract to satisfy. Implementations must honour any `AbortSignal`
they were constructed with — both in-tree implementations call a shared
`ensureNotAborted(signal)` helper at the start of every async operation.
The interface deliberately has no `chmod` or `chown` operations: per-file
mode is carried on the `WriteOp` itself, and ownership is left to the
host filesystem.