CRDT LF Drift

crdt_lf_drift_badge pub points pub likes codecov ci_badge License: MIT pub publisher

docs_badge

A drift storage implementation for CRDT LF objects, providing efficient persistence for Change and Snapshot objects with document-scoped organization in a single drift database.

Features

  • Compact Binary Storage: Change and Snapshot are persisted as the self-describing binary blobs produced by crdt_lf's native toBytes() / fromBytes() methods
  • Single Database, Many Documents: one database holds changes and snapshots tables;
  • Document-Scoped Storage: utilities that organize data by document ID for better isolation and querying

Quick Start

1. Open a database

import 'dart:io';

import 'package:crdt_lf_drift/crdt_lf_drift.dart';

Future<void> main() async {
  // Open (or create) a database file...
  final storage = CRDTDrift.open(File('./my_app_data.db'));

  // ...or an in-memory database (useful for tests):
  final memory = CRDTDrift.memory();

  // Your app code here...

  await storage.close();
}

2. Document-scoped storage

import 'dart:io';

import 'package:crdt_lf/crdt_lf.dart';
import 'package:crdt_lf_drift/crdt_lf_drift.dart';

const documentId = 'my-document-id';

final storage = CRDTDrift.open(File('./my_app_data.db'));

// Open storage for a specific document
final changeStorage = storage.changeStorageForDocument(documentId);
final snapshotStorage = storage.snapshotStorageForDocument(documentId);

// Or open both at once
final documentStorage = storage.storageForDocument(documentId);

Document-Scoped Storage

Data for different documents lives in the same tables and is isolated through the document_id column.

CRDTDriftChangeStorage

Manages Change objects for a specific document:

final changeStorage = storage.changeStorageForDocument('doc-123');

// Save individual changes
await changeStorage.saveChange(change);

// Batch save multiple changes
await changeStorage.saveChanges([change1, change2, change3]);

// Load all changes for the document
final changes = await changeStorage.getChanges();

// Delete changes
await changeStorage.deleteChange(change);
await changeStorage.deleteChanges([change1, change2]);

// Storage info
print('Total changes: ${await changeStorage.count}');
print('Is empty: ${await changeStorage.isEmpty}');

CRDTDriftSnapshotStorage

Manages Snapshot objects for a specific document:

final snapshotStorage = storage.snapshotStorageForDocument('doc-123');

// Save snapshots
await snapshotStorage.saveSnapshot(snapshot);
await snapshotStorage.saveSnapshots([snapshot1, snapshot2]);

// Retrieve snapshots
final snapshot = await snapshotStorage.getSnapshot('snapshot-id');
final allSnapshots = await snapshotStorage.getSnapshots();

// Check existence
if (await snapshotStorage.containsSnapshot('snapshot-id')) {
  // Snapshot exists
}

How Data Is Stored

Both Change and Snapshot are stored as opaque binary blobs using the self-describing format provided by crdt_lf (toBytes() / fromBytes()). The schema is two tables, changes and snapshots, each with a document_id column, an id column (change_id / snapshot_id) and a bytes blob column. Changes are keyed by change.id, snapshots by snapshot.id.

Examples

A complete example is available here.

Storage Management

// Delete all data for a specific document
await storage.deleteDocumentData('doc-123');

// Close the database and release resources
await storage.close();

Roadmap

A roadmap is available in the project page. The roadmap provides a high-level overview of the project's goals and the current status of the project.

Apps

Packages

Other bricks of the crdt "system" are:

Libraries

crdt_lf_drift
A drift storage implementation for CRDT (Conflict-free Replicated Data Type) objects.