# `manifest` _(no submodules)_ ## 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`, 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 { 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` — reads `/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.