@wovin/storage-fs
v0.0.26
Published
Local filesystem storage backend for wovin using LMDB (Lightning Memory-Mapped Database).
Readme
@wovin/storage-fs
Local filesystem storage backend for wovin using LMDB (Lightning Memory-Mapped Database).
Persists wovin threads (applogs/blocks) to the local filesystem.
Features
- Applog storage - Store and retrieve applogs by CID
- Thread management - Track which applogs belong to which threads (many-to-many)
- Block storage - Store raw bytes (for binary content referenced by applogs)
- Deduplication - Applogs stored once, referenced by multiple threads
- ACID transactions - Atomic writes via LMDB transactions
Installation
pnpm add @wovin/storage-fsUsage
Basic Example
import { StorageFs } from '@wovin/storage-fs'
import type { Applog } from '@wovin/core/applog'
// Initialize storage
const storage = await StorageFs.init('./data/wovin-storage')
// Create applogs (CID must be pre-computed)
const applogs: Applog[] = [
{ cid: 'bafyrei...', en: 'entity-1', at: 'text', vl: 'Hello', ts: '2024-01-01T00:00:00Z', ag: 'alice', pv: null },
{ cid: 'bafyrei...', en: 'entity-1', at: 'text', vl: 'World', ts: '2024-01-01T00:00:01Z', ag: 'alice', pv: null },
]
// Store applogs in a thread
const stored = await storage.storeApplogs('my-thread', applogs)
console.log(`Stored ${stored} new applogs`)
// Retrieve applogs from thread
const retrieved = storage.getApplogs('my-thread')
// Get specific applog by CID
const applog = storage.getApplogByCid('bafyrei...')
// Check membership
storage.isApplogInThread('my-thread', 'bafyrei...') // true
// Clean up
storage.close()Multi-Thread Example
Applogs are deduplicated - the same applog can exist in multiple threads:
// Store in first thread
await storage.storeApplogs('thread-a', [applog1, applog2])
// Store same applogs in second thread (no duplication)
await storage.storeApplogs('thread-b', [applog1, applog2])
// Applog exists in both threads
storage.isApplogInThread('thread-a', applog1.cid) // true
storage.isApplogInThread('thread-b', applog1.cid) // true
// Delete thread-b (applogs remain, still in thread-a)
await storage.deleteThread('thread-b')
storage.hasApplog(applog1.cid) // still trueBlock Storage
For binary content referenced by applogs:
// Store a block
await storage.storeBlock('bafyrei...', new Uint8Array([1, 2, 3, 4]))
// Retrieve block
const bytes = storage.getBlock('bafyrei...')
// Check existence
storage.hasBlock('bafyrei...')API
Initialization
StorageFs.init(path: string): Promise<StorageFs>
Initialize storage at the specified path.
Applog Methods
storeApplogs(threadId: string, applogs: Applog[]): Promise<number>
Store applogs in a thread. Returns count of newly stored applogs (excludes duplicates).
getApplogs(threadId: string): Applog[]
Get all applogs in a thread.
getApplogByCid(cid: CID | string): Applog | null
Get a specific applog by CID.
hasApplog(cid: CID | string): boolean
Check if an applog exists.
Block Methods
storeBlock(cid: CID | string, bytes: Uint8Array): Promise<void>
Store raw bytes by CID.
getBlock(cid: CID | string): Uint8Array | null
Get block bytes by CID.
hasBlock(cid: CID | string): boolean
Check if a block exists.
Thread Methods
listThreads(): string[]
List all thread IDs.
deleteThread(threadId: string): Promise<void>
Delete a thread (removes membership, keeps applogs).
getThreadApplogCount(threadId: string): number
Get count of applogs in a thread.
isApplogInThread(threadId: string, cid: CID | string): boolean
Check if an applog is in a thread.
Utilities
close(): void
Close the storage and release resources.
LMDB Structure
storage-fs/data.mdb
├── applogs # cidString → Applog JSON
├── thread_index # threadId → [cidString...] (dupSort)
└── blocks # cidString → Uint8ArrayRelated Packages
@wovin/core- Core wovin types and utilities@wovin/daemon-utils- Daemon utilities
License
Same as wovin monorepo
