src / utils / manifest.ts
import fs from "node:fs/promises";
import path from "node:path";
import { resolveInside } from "./path.js";
export async function validateManifest(baseDir: string): Promise<{ ok: true; data: unknown } | { ok: false; error: string }> {
const file = resolveInside(baseDir, "manifest.json");
try {
const raw = await fs.readFile(file, "utf8");
const json = JSON.parse(raw);
const errors: string[] = [];
if (typeof json !== "object" || json === null) errors.push("manifest.json must be an object");
if (!json.name || typeof json.name !== "string") errors.push("manifest.name must be a string");
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(json.name)) errors.push("manifest.name should be kebab-case");
if (!json.version || typeof json.version !== "string") errors.push("manifest.version must be a string");
if (!json.main || typeof json.main !== "string") errors.push("manifest.main must be a string");
return errors.length ? { ok: false, error: errors.join("; ") } : { ok: true, data: json };
} catch (err: any) {
return { ok: false, error: `Invalid manifest: ${err?.message ?? String(err)}` };
}
}
export async function writeManifest(baseDir: string, manifest: Record<string, unknown>): Promise<void> {
const file = resolveInside(baseDir, "manifest.json");
await fs.writeFile(file, JSON.stringify(manifest, null, 2) + "\n", "utf8");
}