Skip to main content
When you pass a persist adapter to openComposition, the SDK subscribes to every change event and schedules an async write automatically. You never call a save method after each edit — the adapter handles it.

Options

persist
PersistAdapter
The storage adapter. The SDK calls adapter.write(persistPath, html) after every change. Omit to skip persistence (headless / agent use).
persistPath
string
The path key passed to the adapter on every write. Default: "composition.html". Immutable for the session lifetime — changing the path mid-session is not supported.

Flushing pending writes

The persist queue coalesces rapid edits, so the last write may be deferred when your application closes. Call flush() to drain any pending write before exit:
flush() resolves when the in-flight write completes. If there is nothing pending it resolves immediately. It is a no-op when no persist adapter was provided.

Handling write failures

Write errors are emitted as events rather than thrown exceptions — a failed autosave must not crash an interactive session. Subscribe with comp.on('persist:error', …) to handle them:
The event carries { error: { message: string; hint?: string; cause?: unknown } }. The SDK retries on the next change event, so transient errors recover automatically.

Shipped adapters

createMemoryAdapter() — tests and demos

An in-process store — no file I/O, no Node.js required. Use it in unit tests, demos, or browser sessions where you want version history without disk access.
createMemoryAdapter() also exposes injectFault(message) — a test helper that makes the next write fire persist:error instead of committing. This lets you exercise your error-handling path without real I/O failures.

createFsAdapter(opts) — Node.js local dev

Writes to the filesystem and keeps a rolling version history under .hf-versions/. Node.js only — do not use in browser builds.
createFsAdapter is imported from the @hyperframes/sdk/adapters/fs subpath, not the main barrel like createMemoryAdapter. The fs adapter pulls in Node’s fs module, so keeping it on a separate subpath lets browser bundles tree-shake it away — importing it from the root would drag node:fs into a browser build.
root
string
Root directory. The adapter writes {root}/{persistPath} and keeps version files under {root}/.hf-versions/{persistPath}/.
maxVersions
number
Maximum version snapshots to retain per file. Oldest are pruned automatically. Default: 20.
Listing and restoring versions:
Version keys are {timestamp}-{counter} strings. listVersions returns entries newest-first; timestamp is the Unix milliseconds at the time of the write.

Implementing a custom adapter

Any object that satisfies the PersistAdapter interface works as a drop-in. The interface is:
Contract:
  • read() returns undefined for a path that has never been written.
  • write() is idempotent — a second write to the same path overwrites.
  • flush() resolves when any queued writes are committed. Return Promise.resolve() if writes are synchronous.
  • listVersions() returns entries newest-first. Entries without stored content are valid — loadFrom is called lazily by the consumer.
  • loadFrom() returns undefined when the version key is not found.
  • on('persist:error', handler) registers an error listener. Errors must not propagate as thrown exceptions — surface them through the event instead. Returns an unsubscribe function.
Minimal example — an HTTP / S3-style adapter:
write() must never throw — catch errors and emit them through on('persist:error', …) instead. The SDK trusts that writes are fire-and-forget from its side; thrown exceptions break the internal persist queue.

Adapter reference

Full PersistAdapter, PersistVersionEntry, and PreviewAdapter type definitions.

openComposition reference

All OpenCompositionOptions fields including persist, persistPath, preview, and overrides.