51 lines
1.6 KiB
TypeScript
51 lines
1.6 KiB
TypeScript
import type z from "zod";
|
|
import { MANIFEST_CODES, ManifestError } from "../error-codes/error-codes.js";
|
|
import {
|
|
type PluginManifest,
|
|
pluginManifestSchema,
|
|
} from "../schema/plugin-manifest.js";
|
|
|
|
/**
|
|
* Discriminated result for the safe parse path. `data` is present on
|
|
* success, `error` on failure — never both.
|
|
*/
|
|
export type ParseResult =
|
|
| { readonly ok: true; readonly data: PluginManifest }
|
|
| { readonly ok: false; readonly error: ManifestError };
|
|
|
|
/**
|
|
* Strict-parse a plugin manifest. Throws `ManifestError` with code
|
|
* `MANIFEST.PARSE_FAILED` on any Zod issue; the underlying Zod issues
|
|
* array is preserved on `error.cause` so callers can render granular
|
|
* field-level diagnostics.
|
|
*
|
|
* @throws {ManifestError} `MANIFEST.PARSE_FAILED`
|
|
*/
|
|
export function parseManifest(input: unknown): PluginManifest {
|
|
const result = pluginManifestSchema.safeParse(input);
|
|
if (result.success) return result.data;
|
|
throw makeError(result.error);
|
|
}
|
|
|
|
/**
|
|
* Non-throwing variant. Returns a discriminated `ParseResult`. The
|
|
* error carries the same code + cause as the throw path so consumers
|
|
* can render diagnostics without try/catch.
|
|
*/
|
|
export function parseManifestSafe(input: unknown): ParseResult {
|
|
const result = pluginManifestSchema.safeParse(input);
|
|
if (result.success) return { ok: true, data: result.data };
|
|
return { ok: false, error: makeError(result.error) };
|
|
}
|
|
|
|
function makeError(zodError: z.ZodError): ManifestError {
|
|
return new ManifestError(
|
|
MANIFEST_CODES.PARSE_FAILED,
|
|
"manifest.parse_failed",
|
|
{
|
|
cause: zodError,
|
|
context: { issues: zodError.issues },
|
|
}
|
|
);
|
|
}
|