API reference / @evolu/common / local-first / Storage
Interface: Storage
Defined in: packages/common/src/local-first/Storage.ts:91
Evolu Storage
Evolu protocol using Storage is agnostic to storage implementation details—any storage can be plugged in, as long as it implements this interface. Implementations must handle their own errors; return values only indicate overall success or failure.
The Storage API is synchronous because SQLite's synchronous API is the fastest way to use SQLite. Synchronous bindings (like better-sqlite3) call SQLite's C API directly with no context switching between the event loop and native code, and no promise microtasks or await overhead.
The only exception is Storage#writeMessages, which is async to allow for async validation logic before writing to storage. The write operation itself remains synchronous.
Extended by
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
deleteOwner | readonly | (ownerId) => boolean | Delete all data for the given Owner. Returns true on success, false on failure. | packages/common/src/local-first/Storage.ts:167 |
findLowerBound | readonly | (ownerId, begin, end, upperBound) => | number & Brand<"Int"> & Brand<"NonNegative"> | null | - | packages/common/src/local-first/Storage.ts:113 |
fingerprint | readonly | (ownerId, begin, end) => | Fingerprint | null | - | packages/common/src/local-first/Storage.ts:94 |
fingerprintRanges | readonly | (ownerId, buckets, upperBound?) => | readonly FingerprintRange[] | null | Computes fingerprints with their upper bounds in one call. This function can be replaced with many fingerprint/findLowerBound calls, but implementations can leverage it for batching and more efficient fingerprint computation. | packages/common/src/local-first/Storage.ts:107 |
getSize | readonly | (ownerId) => | number & Brand<"Int"> & Brand<"NonNegative"> | null | - | packages/common/src/local-first/Storage.ts:92 |
iterate | readonly | (ownerId, begin, end, callback) => void | - | packages/common/src/local-first/Storage.ts:120 |
readDbChange | readonly | (ownerId, timestamp) => | EncryptedDbChange | null | Read encrypted DbChanges from storage. | packages/common/src/local-first/Storage.ts:157 |
setWriteKey | readonly | (ownerId, writeKey) => boolean | Sets the OwnerWriteKey for the given Owner. | packages/common/src/local-first/Storage.ts:138 |
validateWriteKey | readonly | (ownerId, writeKey) => boolean | Validates the OwnerWriteKey for the given Owner. Returns true if the write key is valid, false otherwise. | packages/common/src/local-first/Storage.ts:132 |
writeMessages | readonly | (ownerIdBytes, messages) => MaybeAsync<Result<void, | StorageWriteError | StorageQuotaError>> | Write encrypted CrdtMessages to storage. Must use a mutex per ownerId to ensure sequential processing and proper protocol logic handling during sync operations. TODO: Use MaybeAsync | packages/common/src/local-first/Storage.ts:151 |