Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,91 @@
# `manifest`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Loads and validates plugin manifest files. Every Suaveplan installer plugin
ships a `manifest.json` next to its entry module; this module exposes
`loadManifest(packagePath)` and `validateManifest(raw)` which both surface
schema violations as `InstallerError(INSTALLER.PLUGIN_INVALID_MANIFEST)`
with the underlying Zod error attached as `cause`. The host calls
`loadManifest` once per plugin during discovery; the result is cached on
the `DiscoveredPlugin` record returned to callers.
## Features
- Backed by `PluginManifestSchema` (Zod) which enforces required fields:
`id`, semver `version`, non-empty `description`, relative `entry`,
`engines: Record<string, string>`, and `assets: string[]`.
- Optional `peerInstallers: string[]` for plugins that depend on other
installers being present at runtime.
- Distinguishes parse errors from schema errors but emits the same code
(`PLUGIN_INVALID_MANIFEST`) so consumers don't have to handle three
variants.
- Pure validator — `validateManifest(raw)` is synchronous and side-effect
free, so plugins can be validated before any disk I/O happens.
## Basic Example
```ts
import { loadManifest } from "@suaveplan/installer";
const manifest = await loadManifest(
"/path/to/node_modules/@suaveplan/install-agent-skills"
);
console.log(manifest.id, manifest.version);
```
## Advanced Example
```ts
import {
InstallerError,
loadManifest,
validateManifest,
} from "@suaveplan/installer";
async function safeLoad(path: string): Promise<unknown> {
try {
return await loadManifest(path);
} catch (err) {
if (
err instanceof InstallerError &&
err.code === "INSTALLER.PLUGIN_INVALID_MANIFEST"
) {
console.warn(`skipping ${path}: bad manifest`);
return null;
}
throw err;
}
}
// Standalone validation — no disk I/O:
const valid = validateManifest({
id: "demo",
version: "0.1.0",
description: "demo plugin",
entry: "dist/index.js",
engines: { node: ">=20" },
assets: [],
});
```
## API Reference
- `loadManifest(packagePath: string): Promise<PluginManifest>` —
reads `<packagePath>/manifest.json`, parses, and validates.
- `validateManifest(raw: unknown): PluginManifest` — pure schema check.
- `PluginManifest` — inferred type:
`{ id, version, description, entry, engines, assets, peerInstallers? }`.
## Implementation Notes
The schema uses a strict semver regex (`MAJOR.MINOR.PATCH` with optional
`-prerelease+build`) rather than `z.string()` so prerelease ergonomics are
explicit. Failures from `JSON.parse` are caught and re-thrown as
`PLUGIN_INVALID_MANIFEST`, not as raw `SyntaxError`, so callers always
have a typed `InstallerError` to switch on. The Zod error issues are
attached via `context.issues` for downstream error reporters that want
field-level breakdowns without re-walking the cause chain.