Seed Protocol
@seedprotocol/sdk

Types

The TypeScript types and error classes from @seedprotocol/sdk that app code uses, grouped by area, with their gaps and the page that covers each.

The SDK ships its own type definitions. This page lists the types you're likely to write in your own code: config, schema and property definitions, items, the change feed and publish graph, and errors. Event payload types are on Events. The main entry exports many more, mostly for @seedprotocol/react and @seedprotocol/publish; those aren't listed here.

import type { SeedConfig, SchemaFileFormat, IItem } from '@seedprotocol/sdk'

Everything on this page is exported from the main entry, except JsonImportSchema. @seedprotocol/sdk/node re-exports the config, schema and property types, ItemData, IItem, IItemProperty, MultiTabMode, SyncFromEasOptions and HtmlEmbeddedDataUriPolicy, and the error classes below, apart from FileSystemLockedError, UnsupportedBrowserError and DatabaseNotPersistentError (browser only), with the ItemCreateProblem, ItemCreateErrorCode, PublishValidationError and ConflictResult types. It doesn't re-export the event payload types, the change-feed and publish types or PropertyConflict.

Configuration

TypeShapeUsed by
SeedConfig{ filesDir?, endpoints?, schema?, schemaFile?, arweaveDomain?, uploadApiBaseUrl?, gateway?, eas?, models?, dbConfig?, entityCache? }client.init. Every field
SeedConstructorOptions{ config: SeedConfig; addresses?: AddressConfiguration; syncFromEasOnAddressChange?: boolean; multiTab?: MultiTabMode }client.init, SeedClientGate's initConfig
Endpoints{ filePaths: string; files: string }SeedConfig.endpoints
DbConfig{ dbUrl?: string; schemaDir?: string; outDir?: string }SeedConfig.dbConfig. Node only: dbUrl is the database file or libSQL URL (default <filesDir>/db/seed.db) and outDir is where migrations are copied and run from (default <filesDir>/db). schemaDir is unused
AddressConfiguration{ owned: string[]; watched?: string[] } | string[]client.init, client.setAddresses. A plain array means owned only
MultiTabMode'coordinate' | 'off'SeedConstructorOptions.multiTab. See Multiple tabs
SeedGatewayConfig{ transport?, proxyBaseUrl?, preferredReadBaseUrls?, arweaveDomain?, uploadApiBaseUrl?, hyper?, … }SeedConfig.gateway. See Gateway settings
SeedGatewayTransportMode'http-gateway' | 'hyper' | 'hybrid'SeedGatewayConfig.transport
SeedGatewayHyperConfig{ gatewayHyperKey?, localSidecarHost?, localSidecarPort?, probeSidecar? }SeedGatewayConfig.hyper
SyncFromEasOptions{ addresses?: string[] }client.syncFromEas
ResetLocalDataOptions{ otherTabsTimeoutMs?: number; filesDir?: string }client.resetLocalData, browser only
ResetLocalDataResult{ deleted: string[]; failed: { path: string; error: string }[] }What client.resetLocalData removed, and the entries it couldn't
ClientStopReason'stop' | 'reset'stopReason on the client's snapshot once it has stopped. See Stopping the client
CreateWaitOptions{ waitForReady?: boolean; readyTimeout?: number }The create methods of Schema, Model and the other entity classes
ItemCreateOptionsCreateWaitOptions & { validate?: boolean; hold?: boolean }Item.create. validate: false skips the input checks; hold: false creates the item without a cache hold

Schemas and properties

TypeShapeUsed by
SchemaFileInput{ $schema?, version?, id?, nameMatch?, metadata: { name, createdAt?, updatedAt? }, models, enums?, migrations? }SeedConfig.schema and SeedClientGate's schema. See The schema file format
SchemaFileFormat{ $schema, version, id?, nameMatch?, metadata: { name, createdAt, updatedAt }, models, enums, migrations }The full format the SDK writes when it saves a version
SchemaNameMatch'exact' | 'normalized' | 'fuzzy'nameMatch on the schema, a model or a property: how loosely names from EAS match it. See Schema
JsonImportSchema{ name, nameMatch?, models: { [model]: { description?, nameMatch?, properties, indexes? } } }The short schema form. Only exported from @seedprotocol/sdk/node
PropertyDataType'Text' | 'Number' | 'Boolean' | 'Date' | 'Json' | 'Html' | 'Image' | 'File' | 'Relation' | 'List'PropertyType.dataType and refValueType
StorageType'ItemStorage' | 'PropertyStorage'PropertyType.storageType
PropertyType{ dataType, name?, ref?, refValueType?, required?, validation?, storageType?, localStorageDir?, filenameSuffix?, htmlEmbeddedDataUriPolicy?, … }A property definition in code. See ModelProperty
HtmlEmbeddedDataUriPolicy'materialize' | 'preserve'PropertyType.htmlEmbeddedDataUriPolicy, on Html properties

validation takes { pattern?, minLength?, maxLength?, enum?, custom? }; Validation says what each rule does.

SchemaFileInput requires only metadata.name and models. TypeScript rejects the short { name, models } form for config.schema, which has no metadata, although the SDK accepts it at runtime; see The schema file format.

PropertyDataType is a union of string literals, so plain strings type-check. The members of the ModelPropertyDataTypes enum (exported from the main entry only) fit it too:

import type { PropertyType } from '@seedprotocol/sdk'

const authors: PropertyType = {
  dataType: 'List',
  refValueType: 'Relation',
  ref: 'Author',
}

Items

TypeWhat it describesUsed by
IItem<T>An item instance: seedLocalId, seedUid, modelName, publisher, createdAt, isRevoked, status, properties, conflicts(), publish(), destroy() and the restReturned by Item.find. See Item
IItemProperty<T>One property of an item: propertyName, value, status, valueStatus, missingFile, conflict, localStoragePath, save(), clear(), subscribe() and the restitem.properties. See ItemProperty
ItemDataThe built-in fields every item has: seedLocalId, seedUid, modelName, schemaName, schemaUid, publisher, createdAt, updatedAt, revokedAt, version fields and so onItem.create, model.create
PropertyValuestring | number | boolean | null | Record<string, unknown> | Record<string, unknown>[]The value type for model fields
PropertyConflict{ seedLocalId, propertyName, baseValue, remoteValue, localValue, remoteUid, opId }property.conflict and item.conflicts(). See Conflicts

Item is also a class, and Item<any> works as a type for the values Item.create and model.create return.

None of these types know your model's fields, so item.title is a type error although it works at runtime. Item.create and model.create(values) accept any keys besides the built-in fields, so an object literal with property values type-checks. Typing items in TypeScript shows how to describe them yourself.

Change feed and publishing

These types go with read helpers on Querying.

TypeShapeUsed by
EntityChangeTable'seeds' | 'versions' | 'metadata'ChangeWatch.tables
ChangeWatch{ seedLocalId?, seedUid?, tables: EntityChangeTable[], propertyNames? }watchEntityChanges and watchEntityRows, browser only
PendingRetraction{ propertyName: string; attestations: { uid: string; schemaUid: string }[] }getPendingRetractions: properties cleared with retract: true whose attestations the next publish revokes
PublishGraph{ root, nodes, forceFullSnapshot, republishRevokedSeed, unpublishedRelatedItems, relatedRefUids, brokenRefs, missingEmbeddedImages }getPublishGraph: what a publish of one item would attest and upload
PublishGraphNode, PublishGraphProperty, PublishGraphRef, PublishPropertyKindOne seed in the graph, one of its properties, a seed a value names, and how a property is published ('basic', 'relation', 'list', 'storageSeed', 'storageTransaction', 'itemStorage')PublishGraph.nodes
GetPublishGraphOptions{ publishMode?: 'patch' | 'new_version'; backReferences?: PublishBackReferences }getPublishGraph
PublishBackReferences'link' | 'defer'What a publish read does with a back reference: getPublishGraph and item.getPublishPayload
PublishUploadSummary{ uploadCount, uploadBytes, uploadSizes, unpublishedRelatedItems }summarizePublishUploads

Errors

The SDK's own error classes. Each sets name to the class name, so instanceof and error.name both work.

ClassThrown whenExtra fields
FileSystemLockedErrorclient.init can't mount the browser file system because another tab or worker holds itcode: 'OPFS_LOCKED', cause. See Client and configuration
UnsupportedBrowserErrorBrowser client.init finds the browser lacks a file system feature the SDK needs, before it loads or stores anything. Its message names the supported browsers: Chrome and Edge 102, Firefox 114 and Safari 26 or latercode: 'BROWSER_UNSUPPORTED', missing: BrowserFeature[] ('opfs', 'opfs-writable', 'web-locks'). See UnsupportedBrowserError
DatabaseNotPersistentErrorBrowser client.init can't keep the database in the origin private file system: SharedArrayBuffer is missing because the page isn't cross-origin isolated, or SQLite opened another kind of database. Retrying doesn't help until the page is served with the COOP/COEP headers in Headers in productioncode: 'DB_NOT_PERSISTENT'. See DatabaseNotPersistentError
ClientNotInitializedErrorA call that needs the client before client.init has finished, after client.stop() or client.unload(), or after a failed init: the client's methods, and Item.find once its readyTimeout passes. Message ClientManager is not initialized. Please call init() first.code: 'CLIENT_NOT_INITIALIZED'. See Stopping the client
ResetLocalDataBrowserOnlyErrorclient.resetLocalData() outside a browsercode: 'RESET_LOCAL_DATA_BROWSER_ONLY'. See Deleting local data
TabLockTimeoutErrorWaiting more than 60 seconds for a lock that another tab, or other code in the same process, holds: a database step or an ItemStorage file. Item writes from the outbox don't wait for a held ItemStorage lock; they're tried again latercode: 'TAB_LOCK_TIMEOUT', lockName
AmbiguousModelErrorA model name exists in more than one schema and you didn't say whichmodelName, schemaNames. See Model
OwnershipErrorA write on an item none of the client's owned addresses own: assertItemOwned, item.destroy(), item.publish(), item.unpublish(), itemProperty.save() and itemProperty.destroy(). A refused assignment (item.title = 'x') doesn't throw; it records the error on the property's actor as _saveErrorMessage Item is read-only: you do not own this item. See Item: ownership
ConflictErrorschema.saveNewVersion() finds the schema changed in the database since it was loaded. Schemas only: a conflict on an item property is a PropertyConflict, not an errorconflict: ConflictResult. See Saving and conflicts
EntityUnloadedErrorA write on an instance that has stopped. On an Item or ItemProperty (unloaded after its grace period, destroyed, or dropped by client.stop()): assigning a property, setValue(), save(), clear(), publish() or unpublish(). On a destroyed or evicted Schema, Model or ModelProperty: assigning a field, schema.saveNewVersion(), reload(), model.create(values) or modelProperty.save(). Reads still return the last valuesMessage names the instance and the write. See Item: unload
UnknownModelErrorItem.create (or model.create) with a modelName no loaded schema defines, in schemaName if given, or getPublishModels with such a name. Nothing is writtenmodelName, schemaName?. See Item
ItemCreateValidationErrorItem.create (or model.create) with keys the model doesn't have, or values that fail their property's type or rules, including File, Image, Html and ItemStorage values, which are checked as they're saved. Nothing is left writtenmodelName, problems: ItemCreateProblem[] ({ property, message, code }). For a File, Image, Html or ItemStorage value, cause is the ItemPropertySaveValidationError. See Item
ItemCreateErrorItem.create (or model.create) can't save a File, Image, Html or ItemStorage value for a reason other than its rules, or that property doesn't load. The draft is removedcode: 'save_failed' | 'property_not_loaded' (the ItemCreateErrorCode type), modelName, property, seedLocalId (the removed draft), cause (the save's error). See Item.create
ItemPropertySaveValidationErroritemProperty.save() with a value that fails validation: the wrong type, enum, pattern, minLength or maxLengthvalidationErrors. See ItemProperty
OutboxSaveTimeoutErroritemProperty.save({ timeoutMs }) when the write isn't applied in time. The write stays queued and is applied latercode: 'OUTBOX_SAVE_TIMEOUT', opId: string | undefined. See save
ClearNotSupportedErroritemProperty.clear() without retract on a Boolean or Date property, which have no empty valuepropertyName, dataType. See clear
PublishValidationFailedErrorBuilding a publish payload finds missing or invalid valuesvalidationErrors: { field, message, code? }[]
RelatedItemUnpublishedErrorA publish would reference an item whose attestation was revoked. A subclass of PublishValidationFailedErrorunpublishedRelatedItems, plus validationErrors with code 'related_item_unpublished'

validationErrors on ItemPropertySaveValidationError holds objects shaped { field: string; message: string; code: string; severity: 'error' | 'warning' }. That's the ValidationError type, a type-only export: import type { ValidationError } from '@seedprotocol/sdk'.

import { FileSystemLockedError, ItemPropertySaveValidationError } from '@seedprotocol/sdk'

function describe(error: unknown): string {
  if (error instanceof FileSystemLockedError) return 'Close other tabs of this app and retry.'
  if (error instanceof ItemPropertySaveValidationError) {
    return error.validationErrors.map((e) => `${e.field}: ${e.message}`).join('\n')
  }
  return String(error)
}

Two more, HtmlEmbeddedDataUriLimitError and HtmlSeedPropertyRefError, come from preparing Html properties for publishing. Most errors elsewhere in the SDK are plain Errors.

A write that fails in the outbox rejects save(), Item.create or destroy() with OutboxOpFailedError (code: 'OUTBOX_OP_FAILED'). Its errorName names the original error's class. For 'RelationTargetError' and 'StagedValueMissingError', cause is an instance of that class (with targets or path), so error.cause instanceof RelationTargetError works; other classes survive only as errorName. All three classes are exported from both entries; see save.

On this page