3.4 KiB
MANIFEST_CODES and ManifestError
(no submodules)
Purpose
Frozen MANIFEST.* error-code registry plus the concrete SuaveplanError subclass thrown by every public path in this package. The registry is built with defineCodes so every entry is a literal-typed MANIFEST.<REASON> string, surviving tree-shaking and minification. ManifestError narrows the base class's TCode parameter to that union so instanceof ManifestError plus error.code is a discriminated union at the consumer site.
Features
- Eleven stable codes covering parse, dep-graph, capability, and validator failures
- Literal-typed
ManifestCodeunion derived from the registry ManifestErrorsubclass preserving the base cause-chain, context, OTel adapter, and i18n message-key resolution- Every code has at least one production-path reference enforced by a spec-conformance test
Basic Example
import { MANIFEST_CODES, ManifestError } from "@suaveplan/api-manifest/error-codes";
throw new ManifestError(
MANIFEST_CODES.PARSE_FAILED,
"manifest.parse_failed",
{ context: { issues: [] } },
);
Advanced Example
import {
MANIFEST_CODES,
type ManifestCode,
ManifestError,
} from "@suaveplan/api-manifest/error-codes";
function handle(err: unknown): ManifestCode | null {
if (err instanceof ManifestError) return err.code;
return null;
}
const code: ManifestCode = MANIFEST_CODES.DEPENDENCY_CYCLE;
API Reference
MANIFEST_CODES—Readonly<Record<Reason, \MANIFEST.${Reason}`>>`.ManifestCode— string-literal union of every registered code.ManifestError—class ManifestError extends SuaveplanError<ManifestCode>.
Implementation Notes
defineCodes("MANIFEST", [...]) returns a frozen object so consumers cannot accidentally mutate it at runtime; combined with as const on the reason array the type system pins every key + value. The eleven codes are: PARSE_FAILED, DEPENDENCY_CYCLE, MISSING_DEPENDENCY, DEPENDENCY_VERSION_MISMATCH, CAPABILITY_REQUIRED_MISSING, CAPABILITY_VERSION_MISMATCH, OPTIONAL_CAPABILITY_MISSING, INVALID_SAGA_OWNERSHIP, SANDBOX_REQUIRES_BUDGETS, INVALID_ERROR_STATUS_MAP, OPENAPI_REQUIRES_GRAPHQL_OR_ROUTES. Adding a new code is an spec change because every reachable code is pinned by the spec-conformance test.
Cross-package Notes
This module is part of the @suaveplan/api-manifest Stage-1 contract package. It sits beneath every Stage-2 consumer (api-host, api-loader, the admin CLI, the IDE plugin) and above the foundation packages (@suaveplan/error, @suaveplan/types). The strict-mode top-level rejection of unknown keys means upgrading from manifest v1 to v2 is an OpenSpec-driven event: a new key landing in a consumer manifest is a parse failure rather than a silent drift, which is exactly the contract this stage exists to guarantee.
When the host reloads a plugin without a full restart, every manifest field this module validates is compared against the install-time manifestHash. A mismatch triggers a hard rollback via the RollbackJournal because the host's invariants (route mounts, registered capabilities, declared scopes) are derived from these exact bytes. Treat the schemas and validators here as the contract surface, not just an input filter — downstream code reads manifest.foo.bar and relies on those keys being present, well-typed, and non-undefined in the documented optionality regions.