2.9 KiB
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, semverversion, non-emptydescription, relativeentry,engines: Record<string, string>, andassets: 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
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
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.