2.7 KiB
manifest-loader
Purpose
Loads and validates the bundled assets/skills/manifest.json produced by
scripts/build-skills-bundle.ts. The loader is the runtime equivalent of
the plugin's manifest schema — every entry must have a string id,
semver version, non-empty dir, and array of relative files.
Validation failures surface as
InstallSkillsError(INSTALL_SKILLS.MANIFEST_INVALID) with the underlying
Zod error attached as cause.
Features
- Zod-validated
BundledManifestSchema—{ schemaVersion: 1, skills: [...] }. - Per-skill validation:
id, semverversion,dir,files. - Not memoised — every call re-reads the file so the testing harness
can swap in alternate manifests by passing
manifestPath. - Defaults to the bundled file shipped inside the package
(
<pkg-root>/assets/skills/manifest.json). - Distinguishes parse, read, and schema failures only by
messageKey; the surfaced code is alwaysINSTALL_SKILLS.MANIFEST_INVALID.
Basic Example
import { loadBundledManifest } from "@suaveplan/install-agent-skills";
const manifest = await loadBundledManifest();
console.log(`bundled ${manifest.skills.length} skills`);
Advanced Example
import {
InstallSkillsError,
loadBundledManifest,
} from "@suaveplan/install-agent-skills";
try {
const manifest = await loadBundledManifest({
manifestPath: "/tmp/test-fixture-manifest.json",
});
for (const skill of manifest.skills) {
console.log(`${skill.id}@${skill.version} (${skill.files.length} files)`);
}
} catch (err) {
if (
err instanceof InstallSkillsError &&
err.code === "INSTALL_SKILLS.MANIFEST_INVALID"
) {
console.error("Bundle is broken — rebuild via build-skills-bundle.ts");
process.exit(2);
}
throw err;
}
API Reference
loadBundledManifest(options?: LoadOptions): Promise<BundledManifest>interface LoadOptions—{ manifestPath?: string }.BundledManifest—{ schemaVersion: 1, skills: SkillEntry[] }.SkillEntry—{ id, version, dir, files }.BundledManifestSchema— Zod schema, exported for advanced reuse.
Implementation Notes
The default manifest path is resolved via import.meta.url so the loader
works correctly under ESM with no fallback to __dirname — the package
ships ESM-only and import.meta.url is always available. Schema
violations carry context.issues (the Zod issue list) plus
context.path so error reporters can show field-level breakdowns.
Read failures (file missing, permission denied) and parse failures
(truncated/garbage JSON) get distinct messageKey values
(unreadable, unparseable, invalid) but share the same code so
consumers don't need three handlers.