Turso / libSQL Adapter
Turso / libSQL metadata manifest adapter for MemoFS remote-blob memory stores.
The @memofs/adapter-turso adapter implements MemoFS's MetadataStore contract over a Turso or libSQL SQLite database.
It manages the canonical file manifest (path → BlobEntry mapping) and provides transactional serialization (BEGIN IMMEDIATE) to prevent concurrent write hazards in distributed environments.
Installation
npm install @memofs/adapter-turso @libsql/clientRequires Node.js >= 22 or the Cloudflare Workers runtime.
Usage
Create a MetadataStore with createTursoMetadataStore() and pass it alongside a BlobClient to RemoteBlobMemoryStore:
import { MemoFS, RemoteBlobMemoryStore } from "@memofs/core";
import { createTursoMetadataStore } from "@memofs/adapter-turso";
import { createR2BlobClient } from "@memofs/adapter-r2";
import { createClient } from "@libsql/client";
// 1. Create a libSQL client instance
const dbClient = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
});
const projectId = "my-project-123";
// 2. Instantiate the Turso metadata store
const metadata = createTursoMetadataStore({
client: dbClient,
projectId,
});
// 3. Compose with an R2 blob client into a RemoteBlobMemoryStore
const store = new RemoteBlobMemoryStore({
blobClient: createR2BlobClient({ binding: env.BLOBS }),
metadata,
rootKey: projectId,
});
// 4. Initialize MemoFS
const memo = new MemoFS({
store,
projectId,
mode: "local",
});Schema & Manifest Architecture
@memofs/adapter-turso operates against the project_files table, matching the MemoFS cloud replication layout:
CREATE TABLE IF NOT EXISTS project_files (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
path TEXT NOT NULL,
sha256 TEXT NOT NULL,
r2_key TEXT NOT NULL,
size_bytes INTEGER NOT NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(project_id, path)
);Manifest Operations
getEntry(path): QueriesSELECT sha256, r2_key, size_bytes FROM project_files WHERE project_id = ? AND path = ?.upsertEntry(path, entry): PerformsINSERT ... ON CONFLICT (project_id, path) DO UPDATE SET sha256 = excluded.sha256, r2_key = excluded.r2_key, size_bytes = excluded.size_bytes, updated_at = current_timestamp.deleteEntry(path): RunsDELETE FROM project_files WHERE project_id = ? AND path = ?.listEntries(): Streams all registered canonical paths for the project viaSELECT path, sha256, r2_key, size_bytes FROM project_files WHERE project_id = ?.
Concurrency Control (withTransaction)
When multiple AI coding agents write to the same project concurrently, interleaving non-atomic file writes can cause file corruption.
@memofs/adapter-turso implements MetadataStore.withTransaction:
- Opens a serialized transaction using
BEGIN IMMEDIATE. - Guarantees that mutating operations (
write,append,delete) execute atomically. - Automatically commits on success (
COMMIT) or rolls back on exceptions (ROLLBACK).
Configuration API (CreateTursoMetadataStoreOptions)
The createTursoMetadataStore(options) factory accepts CreateTursoMetadataStoreOptions:
| Option | Type | Required | Description |
|---|---|---|---|
client | Client | Yes | An initialized @libsql/client instance (or Drizzle's db.$client). |
projectId | string | Yes | The project identifier scoping this manifest. |