# Manifest

> Parse and check storeware.app.toml as the platform does.

Source: https://storeware.ai/docs/sdk/manifest

```ts
import { ... } from '@storeware/plugin-sdk';
```

### isIndexAction

Whether a point is a list's action, and so carries a selection.

```ts
function isIndexAction(point: string): boolean
```

### hostedAppOrigin

The address a hosted app is served from.

```ts
function hostedAppOrigin(slug: string, domain?: string): string
```

### parseManifest

Parses and structurally validates a manifest.

```ts
function parseManifest(source: string): PluginManifest
```

### manifestUrls

Every address Storeware sends a shop's data to or frames for an app.

```ts
function manifestUrls(manifest: PluginManifest): string[]
```

### settingAccepts

Whether a value fits a setting. The same rule the admin form and the API apply to what a merchant saves, so a default that parses always saves.

```ts
function settingAccepts(field: SettingField, value: unknown): boolean
```

### validateScopes

Checks scope names against the platform's live vocabulary.

```ts
function validateScopes(manifest: PluginManifest, knownScopes: readonly string[]): void
```

### validateEvents

Checks declared events against the platform's catalogue and the app's scopes.

```ts
function validateEvents(manifest: PluginManifest, catalogue: readonly EventAccess[]): void
```

### validateRelations

Checks declared relations against the platform's graph vocabulary.

```ts
function validateRelations(manifest: PluginManifest, knownRelations: readonly string[]): void
```

### ManifestError

```ts
new ManifestError(message: string, issues?: string[])
```

### AdminExtensionPoint

```ts
type AdminExtensionPoint = (typeof ADMIN_EXTENSION_POINTS)[number];
```

### StorefrontBlock

```ts
type StorefrontBlock = (typeof STOREFRONT_BLOCKS)[number];
```

### SettingType

```ts
type SettingType = (typeof SETTING_TYPES)[number];
```

### SettingField

```ts
type SettingField = z.infer<typeof settingField>;
```

### BlockFormat

```ts
type BlockFormat = (typeof BLOCK_FORMATS)[number];
```

### AutomationTrigger

```ts
type AutomationTrigger = z.infer<typeof automationTrigger>;
```

### AutomationAction

```ts
type AutomationAction = z.infer<typeof automationAction>;
```

### PluginManifest

```ts
type PluginManifest = z.infer<typeof manifestSchema>;
```

### BillingPlan

One plan from `[[billing.plans]]`.

```ts
type BillingPlan = z.infer<typeof billingPlan>;
```

### EventAccess

One topic the platform emits, and the scopes any one of which lets an app hear it.

| Name | Type | Description |
| --- | --- | --- |
| `topic` | `string` |  |
| `anyOf` | `readonly string[]` |  |

### ADMIN_EXTENSION_POINTS

Where a plugin may render inside the admin.

```ts
const ADMIN_EXTENSION_POINTS: readonly ['admin.product.detail.sidebar', 'admin.product.detail.action', 'admin.product.index.action', 'admin.collection.detail.sidebar', 'admin.collection.detail.action', 'admin.order.detail.sidebar', 'admin.order.detail.action', 'admin.orders.index.action', 'admin.customer.detail.sidebar', 'admin.customer.detail.action', 'admin.customers.index.action', 'admin.settings.block']
```

### INDEX_ACTION_POINTS

The points on a list, which act on the rows a merchant ticked.

```ts
const INDEX_ACTION_POINTS: readonly ['admin.product.index.action', 'admin.orders.index.action', 'admin.customers.index.action']
```

### STOREFRONT_BLOCKS

Named slots a storefront theme renders plugin blocks into.

```ts
const STOREFRONT_BLOCKS: readonly ['storefront.product.below_description', 'storefront.product.above_add_to_cart', 'storefront.cart.summary', 'storefront.collection.header']
```

### HOSTED_APPS_DOMAIN

Where Storeware runs apps it hosts: each app at `&lt;slug&gt;.storewareapps.com`.

```ts
const HOSTED_APPS_DOMAIN: 'storewareapps.com'
```

### MAX_EGRESS_HOSTS

The most hosts a hosted app may send requests to, besides Storeware's API.

```ts
const MAX_EGRESS_HOSTS: 20
```

### MAX_BUNDLE_BYTES

The largest bundle `storeware app deploy` uploads, in bytes.

```ts
const MAX_BUNDLE_BYTES: number
```

### SETTING_TYPES

What a merchant can type into an app's settings.

```ts
const SETTING_TYPES: readonly ['single_line_text', 'multi_line_text', 'integer', 'decimal', 'boolean', 'url', 'color', 'select', 'secret']
```

### BLOCK_FORMATS

What an app's block or section answers with.

```ts
const BLOCK_FORMATS: readonly ['html', 'components']
```

### TRIGGER_FIELD_TYPES

The kinds of value an app's trigger carries, which a condition can test.

```ts
const TRIGGER_FIELD_TYPES: readonly ['text', 'number', 'boolean', 'date', 'url']
```

### ACTION_FIELD_TYPES

The kinds of value a merchant fills in for an app's action.

```ts
const ACTION_FIELD_TYPES: readonly ['text', 'multi_line_text', 'number', 'boolean', 'url', 'select']
```

### manifestSchema

The manifest's shape. Exported for `manifest-schema.ts`, which publishes it as JSON Schema; everything else parses through `parseManifest`.

```ts
const manifestSchema: z.ZodObject<{ manifest_version: z.ZodOptional<z.ZodNumber>; app: z.ZodObject<{ slug: z.ZodString; name: z.ZodString; description: z.ZodOptional<z.ZodString>; homepage_url: z.ZodOptional<z.ZodString>; url: z.ZodOptional<z.ZodString>; navigation: z.ZodOptional<z.ZodArray<z.ZodObject<{ label: z.ZodString; path: z.ZodString; }, z.core.$strip>>>; privacy_policy_url: z.ZodOptional<z.ZodString>; support_url: z.ZodOptional<z.ZodString>; }, z.core.$strip>; oauth: z.ZodObject<{ redirect_uris: z.ZodDefault<z.ZodArray<z.ZodString>>; scopes: z.ZodArray<z.ZodString>; }, z.core.$strip>; privacy: z.ZodOptional<z.ZodObject<{ url: z.ZodString; }, z.core.$strip>>; billing: z.ZodOptional<z.ZodObject<{ mode: z.ZodEnum<{ managed: 'managed'; api: 'api'; }>; plans: z.ZodDefault<z.ZodArray<z.ZodObject<{ key: z.ZodString; name: z.ZodString; description: z.ZodOptional<z.ZodString>; interval: z.ZodDefault<z.ZodEnum<{ month: 'month'; year: 'year'; }>>; prices: z.ZodOptional<z.ZodObject<{ usd: z.ZodNumber; gbp: z.ZodNumber; eur: z.ZodNumber; inr: z.ZodNumber; }, z.core.$strict>>; trial_days: z.ZodDefault<z.ZodNumber>; features: z.ZodDefault<z.ZodArray<z.ZodString>>; usage: z.ZodOptional<z.ZodObject<{ cap: z.ZodObject<{ usd: z.ZodNumber; gbp: z.ZodNumber; eur: z.ZodNumber; inr: z.ZodNumber; }, z.core.$strict>; terms: z.ZodString; }, z.core.$strict>>; }, z.core.$strict>>>; }, z.core.$strict>>; webhooks: z.ZodOptional<z.ZodObject<{ url: z.ZodString; events: z.ZodArray<z.ZodString>; }, z.core.$strip>>; extensions: z.ZodOptional<z.ZodObject<{ admin: z.ZodOptional<z.ZodArray<z.ZodObject<{ point: z.ZodEnum<{ "admin.product.detail.sidebar": 'admin.product.detail.sidebar'; "admin.product.detail.action": 'admin.product.detail.action'; "admin.product.index.action": 'admin.product.index.action'; "admin.collection.detail.sidebar": 'admin.collection.detail.sidebar'; "admin.collection.detail.action": 'admin.collection.detail.action'; "admin.order.detail.sidebar": 'admin.order.detail.sidebar'; "admin.order.detail.action": 'admin.order.detail.action'; "admin.orders.index.action": 'admin.orders.index.action'; "admin.customer.detail.sidebar": 'admin.customer.detail.sidebar'; "admin.customer.detail.action": 'admin.customer.detail.action'; "admin.customers.index.action": 'admin.customers.index.action'; "admin.settings.block": 'admin.settings.block'; }>; url: z.ZodString; title: z.ZodString; }, z.core.$strip>>>; storefront: z.ZodOptional<z.ZodArray<z.ZodObject<{ block: z.ZodEnum<{ "storefront.product.below_description": 'storefront.product.below_description'; "storefront.product.above_add_to_cart": 'storefront.product.above_add_to_cart'; "storefront.cart.summary": 'storefront.cart.summary'; "storefront.collection.header": 'storefront.collection.header'; }>; url: z.ZodString; format: z.ZodDefault<z.ZodEnum<{ components: 'components'; html: 'html'; }>>; }, z.core.$strip>>>; sections: z.ZodOptional<z.ZodArray<z.ZodObject<{ handle: z.ZodString; name: z.ZodString; description: z.ZodOptional<z.ZodString>; url: z.ZodString; format: z.ZodDefault<z.ZodEnum<{ components: 'components'; html: 'html'; }>>; }, z.core.$strict>>>; }, z.core.$strip>>; settings: z.ZodOptional<z.ZodArray<z.ZodObject<{ key: z.ZodString; label: z.ZodString; help: z.ZodOptional<z.ZodString>; type: z.ZodEnum<{ boolean: 'boolean'; secret: 'secret'; url: 'url'; single_line_text: 'single_line_text'; multi_line_text: 'multi_line_text'; integer: 'integer'; decimal: 'decimal'; color: 'color'; select: 'select'; }>; required: z.ZodDefault<z.ZodBoolean>; default: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>; options: z.ZodOptional<z.ZodArray<z.ZodObject<{ value: z.ZodString; label: z.ZodString; }, z.core.$strict>>>; }, z.core.$strict>>>; app_proxy: z.ZodOptional<z.ZodObject<{ url: z.ZodString; }, z.core.$strict>>; automations: z.ZodOptional<z.ZodObject<{ triggers: z.ZodDefault<z.ZodArray<z.ZodObject<{ key: z.ZodString; label: z.ZodString; description: z.ZodOptional<z.ZodString>; fields: z.ZodDefault<z.ZodArray<z.ZodObject<{ key: z.ZodString; label: z.ZodString; type: z.ZodEnum<{ number: 'number'; boolean: 'boolean'; text: 'text'; date: 'date'; url: 'url'; }>; }, z.core.$strict>>>; }, z.core.$strict>>>; actions: z.ZodDefault<z.ZodArray<z.ZodObject<{ key: z.ZodString; label: z.ZodString; description: z.ZodOptional<z.ZodString>; url: z.ZodString; fields: z.ZodDefault<z.ZodArray<z.ZodObject<{ key: z.ZodString; label: z.ZodString; type: z.ZodEnum<{ number: 'number'; boolean: 'boolean'; text: 'text'; url: 'url'; multi_line_text: 'multi_line_text'; select: 'select'; }>; required: z.ZodDefault<z.ZodBoolean>; options: z.ZodOptional<z.ZodArray<z.ZodObject<{ value: z.ZodString; label: z.ZodString; }, z.core.$strict>>>; }, z.core.$strict>>>; }, z.core.$strict>>>; }, z.core.$strict>>; checkout: z.ZodOptional<z.ZodObject<{ delivery_rates: z.ZodOptional<z.ZodObject<{ url: z.ZodString; }, z.core.$strict>>; }, z.core.$strict>>; runtime: z.ZodOptional<z.ZodObject<{ main: z.ZodDefault<z.ZodString>; egress: z.ZodDefault<z.ZodArray<z.ZodString>>; bundle: z.ZodOptional<z.ZodString>; }, z.core.$strict>>; knowledge: z.ZodOptional<z.ZodObject<{ url: z.ZodString; attributes: z.ZodDefault<z.ZodArray<z.ZodString>>; relations: z.ZodDefault<z.ZodArray<z.ZodString>>; scopes: z.ZodDefault<z.ZodArray<z.ZodString>>; }, z.core.$strip>>; metafields: z.ZodOptional<z.ZodObject<{ definitions: z.ZodArray<z.ZodObject<{ owner_type: z.ZodEnum<{ product: 'product'; variant: 'variant'; collection: 'collection'; customer: 'customer'; order: 'order'; store: 'store'; }>; key: z.ZodString; name: z.ZodString; description: z.ZodOptional<z.ZodString>; type: z.ZodEnum<{ boolean: 'boolean'; date: 'date'; url: 'url'; single_line_text: 'single_line_text'; multi_line_text: 'multi_line_text'; integer: 'integer'; decimal: 'decimal'; }>; is_list: z.ZodDefault<z.ZodBoolean>; storefront_visible: z.ZodDefault<z.ZodBoolean>; }, z.core.$strip>>; scopes: z.ZodDefault<z.ZodArray<z.ZodString>>; }, z.core.$strip>>; mcp: z.ZodOptional<z.ZodObject<{ tools: z.ZodOptional<z.ZodArray<z.ZodObject<{ name: z.ZodString; description: z.ZodString; url: z.ZodString; scopes: z.ZodDefault<z.ZodArray<z.ZodString>>; input_schema: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>; }, z.core.$strip>>>; }, z.core.$strip>>; }, z.core.$strict>
```

### WITHHELD_FROM_APPS

Scopes no app may hold, whatever it asks for.

```ts
const WITHHELD_FROM_APPS: readonly string[]
```
