@shopkit/apps-manifest
v0.1.5
Published
Apps Platform manifest schema (Zod) + validator. Parses an app.json against the multi-surface manifest contract, cross-checks capabilities against @shopkit/apps-capabilities, returns rich error reports for CLI / dashboard / upload pipeline.
Readme
@shopkit/apps-manifest
Zod schema + validator for the Apps Platform manifest (app.json).
What's in here
| Export | Purpose |
| --- | --- |
| appManifestSchema | The Zod schema for the multi-surface manifest. |
| surfaceSchema / blockDeclSchema / settingDeclSchema | Nested schemas reusable from the CLI / dashboard. |
| AppManifest / SurfaceDecl / BlockDecl / SettingDecl | z.infer<>-derived TypeScript types. |
| parseManifest(input) | Parse + semantically validate. Returns { ok: true, manifest } or { ok: false, errors: ManifestError[] }. Never throws. |
| parseManifestOrThrow(input) | Strict variant — returns the manifest, throws ManifestValidationError on failure (carries .errors). |
| ManifestError / ManifestParseResult | Error report types. Paths are bracketed (e.g. surfaces[0].capabilities[2]). |
What it checks
Schema (shape):
manifestVersion === 1(literal —2will fail until the next major contract).appIdis lowercase kebab-case, 3–64 chars.versionis valid semver (1.2.3,1.0.0-beta.3, etc.).nameis 1–200 chars.surfacesis 1–5 entries (0or6+fails).- Each surface's
apiVersionmatchesYYYY-MM(rejectsYYYY-MM-DD, month00/13+). bundle.urlishttps://.bundle.integrityissha256-/sha384-/sha512-+ base64.networkOrigins[]entries arehttps://origins.
Semantics (cross-table):
- Every declared capability is in the
@shopkit/apps-capabilitiesSCOPEScatalog. - Every declared capability is in the per-surface
SURFACE_ALLOWLIST(e.g.settings:writeis illegal onembed). blocks[]is required on theblocksurface, forbidden on every other surface.- Each block's capabilities are a subset of the parent surface's capabilities.
- Surface types are unique within a manifest (can't declare
embedtwice).
Quick usage
import { parseManifest } from "@shopkit/apps-manifest";
const result = parseManifest(JSON.parse(fileContents));
if (!result.ok) {
for (const err of result.errors) {
console.error(` ${err.path}: ${err.message}`);
}
process.exit(1);
}
// result.manifest is the Zod-validated AppManifest, structurally compatible
// with @shopkit/apps-platform's HostAdapterManifest.
const adapter = new EmbedsHostAdapter({ manifest: result.manifest, ... });Why a separate package
@shopkit/apps-capabilities owns the catalog (scopes, methods, surface allowlist). This package owns the shape contract for the published manifest format. Splitting:
- Lets the App Ecosystem service (Node) validate manifests at upload time without pulling DOM types.
- Lets the CLI (
@shopkit/cli, RAP-27) reuse the same validator inapp lint. - Keeps
@shopkit/apps-platformruntime free of Zod (it accepts a structural subset viaHostAdapterManifest).
