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
| Type | Shape | Used 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 |
ItemCreateOptions | CreateWaitOptions & { validate?: boolean; hold?: boolean } | Item.create. validate: false skips the input checks; hold: false creates the item without a cache hold |
Schemas and properties
| Type | Shape | Used 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
| Type | What it describes | Used by |
|---|---|---|
IItem<T> | An item instance: seedLocalId, seedUid, modelName, publisher, createdAt, isRevoked, status, properties, conflicts(), publish(), destroy() and the rest | Returned by Item.find. See Item |
IItemProperty<T> | One property of an item: propertyName, value, status, valueStatus, missingFile, conflict, localStoragePath, save(), clear(), subscribe() and the rest | item.properties. See ItemProperty |
ItemData | The built-in fields every item has: seedLocalId, seedUid, modelName, schemaName, schemaUid, publisher, createdAt, updatedAt, revokedAt, version fields and so on | Item.create, model.create |
PropertyValue | string | 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.
| Type | Shape | Used 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, PublishPropertyKind | One 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.
| Class | Thrown when | Extra fields |
|---|---|---|
FileSystemLockedError | client.init can't mount the browser file system because another tab or worker holds it | code: 'OPFS_LOCKED', cause. See Client and configuration |
UnsupportedBrowserError | Browser 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 later | code: 'BROWSER_UNSUPPORTED', missing: BrowserFeature[] ('opfs', 'opfs-writable', 'web-locks'). See UnsupportedBrowserError |
DatabaseNotPersistentError | Browser 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 production | code: 'DB_NOT_PERSISTENT'. See DatabaseNotPersistentError |
ClientNotInitializedError | A 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 |
ResetLocalDataBrowserOnlyError | client.resetLocalData() outside a browser | code: 'RESET_LOCAL_DATA_BROWSER_ONLY'. See Deleting local data |
TabLockTimeoutError | Waiting 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 later | code: 'TAB_LOCK_TIMEOUT', lockName |
AmbiguousModelError | A model name exists in more than one schema and you didn't say which | modelName, schemaNames. See Model |
OwnershipError | A 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 _saveError | Message Item is read-only: you do not own this item. See Item: ownership |
ConflictError | schema.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 error | conflict: ConflictResult. See Saving and conflicts |
EntityUnloadedError | A 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 values | Message names the instance and the write. See Item: unload |
UnknownModelError | Item.create (or model.create) with a modelName no loaded schema defines, in schemaName if given, or getPublishModels with such a name. Nothing is written | modelName, schemaName?. See Item |
ItemCreateValidationError | Item.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 written | modelName, problems: ItemCreateProblem[] ({ property, message, code }). For a File, Image, Html or ItemStorage value, cause is the ItemPropertySaveValidationError. See Item |
ItemCreateError | Item.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 removed | code: 'save_failed' | 'property_not_loaded' (the ItemCreateErrorCode type), modelName, property, seedLocalId (the removed draft), cause (the save's error). See Item.create |
ItemPropertySaveValidationError | itemProperty.save() with a value that fails validation: the wrong type, enum, pattern, minLength or maxLength | validationErrors. See ItemProperty |
OutboxSaveTimeoutError | itemProperty.save({ timeoutMs }) when the write isn't applied in time. The write stays queued and is applied later | code: 'OUTBOX_SAVE_TIMEOUT', opId: string | undefined. See save |
ClearNotSupportedError | itemProperty.clear() without retract on a Boolean or Date property, which have no empty value | propertyName, dataType. See clear |
PublishValidationFailedError | Building a publish payload finds missing or invalid values | validationErrors: { field, message, code? }[] |
RelatedItemUnpublishedError | A publish would reference an item whose attestation was revoked. A subclass of PublishValidationFailedError | unpublishedRelatedItems, 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.