resig.js
Version:
Universal reactive signal library with complete platform features: signals, animations, CRDTs, scheduling, DOM integration. Works identically across React, SolidJS, Svelte, Vue, and Qwik.
301 lines • 27.6 kB
JavaScript
;
/**
* Event Sourcing with CRDTs
* Complete state reconstruction with event replay, snapshots, and compaction
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.indexedDBEventStore = exports.eventSourcedGCounter = exports.eventSourcedORSet = exports.createEventSourcedCRDT = exports.IndexedDBEventStore = exports.MemoryEventStore = void 0;
const crdt_1 = require("../crdt");
const coalgebra_1 = require("./coalgebra");
// In-memory event store implementation
class MemoryEventStore {
constructor() {
this.events = [];
this.snapshots = [];
}
async append(events) {
this.events.push(...events);
this.events.sort((a, b) => a.version - b.version);
}
async getEvents(fromVersion = 0, toVersion = Infinity) {
return this.events.filter((e) => e.version >= fromVersion && e.version <= toVersion);
}
async getSnapshot(beforeVersion = Infinity) {
const validSnapshots = this.snapshots.filter((s) => s.version < beforeVersion);
return validSnapshots.length > 0
? validSnapshots[validSnapshots.length - 1]
: null;
}
async saveSnapshot(snapshot) {
this.snapshots.push(snapshot);
this.snapshots.sort((a, b) => a.version - b.version);
}
async compact(beforeVersion) {
this.events = this.events.filter((e) => e.version >= beforeVersion);
this.snapshots = this.snapshots.filter((s) => s.version >= beforeVersion);
}
}
exports.MemoryEventStore = MemoryEventStore;
// IndexedDB event store for browser persistence
class IndexedDBEventStore {
constructor(dbName) {
this.db = null;
this.dbName = dbName;
}
async getDB() {
if (this.db)
return this.db;
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.dbName, 1);
request.onerror = () => reject(request.error);
request.onsuccess = () => {
this.db = request.result;
resolve(this.db);
};
request.onupgradeneeded = () => {
const db = request.result;
if (!db.objectStoreNames.contains('events')) {
const eventStore = db.createObjectStore('events', { keyPath: 'id' });
eventStore.createIndex('version', 'version', { unique: false });
eventStore.createIndex('timestamp', 'timestamp', { unique: false });
}
if (!db.objectStoreNames.contains('snapshots')) {
const snapshotStore = db.createObjectStore('snapshots', {
keyPath: 'version',
});
snapshotStore.createIndex('timestamp', 'timestamp', {
unique: false,
});
}
};
});
}
async append(events) {
const db = await this.getDB();
const transaction = db.transaction(['events'], 'readwrite');
const store = transaction.objectStore('events');
for (const event of events) {
store.add(event);
}
return new Promise((resolve, reject) => {
transaction.oncomplete = () => resolve();
transaction.onerror = () => reject(transaction.error);
});
}
async getEvents(fromVersion = 0, toVersion = Infinity) {
const db = await this.getDB();
const transaction = db.transaction(['events'], 'readonly');
const store = transaction.objectStore('events');
const index = store.index('version');
const range = IDBKeyRange.bound(fromVersion, toVersion);
const request = index.getAll(range);
return new Promise((resolve, reject) => {
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
async getSnapshot(beforeVersion = Infinity) {
const db = await this.getDB();
const transaction = db.transaction(['snapshots'], 'readonly');
const store = transaction.objectStore('snapshots');
const range = IDBKeyRange.upperBound(beforeVersion, true);
const request = store.openCursor(range, 'prev');
return new Promise((resolve, reject) => {
request.onsuccess = () => {
const cursor = request.result;
resolve(cursor ? cursor.value : null);
};
request.onerror = () => reject(request.error);
});
}
async saveSnapshot(snapshot) {
const db = await this.getDB();
const transaction = db.transaction(['snapshots'], 'readwrite');
const store = transaction.objectStore('snapshots');
store.put(snapshot);
return new Promise((resolve, reject) => {
transaction.oncomplete = () => resolve();
transaction.onerror = () => reject(transaction.error);
});
}
async compact(beforeVersion) {
const db = await this.getDB();
const transaction = db.transaction(['events', 'snapshots'], 'readwrite');
// Remove old events
const eventStore = transaction.objectStore('events');
const eventIndex = eventStore.index('version');
const eventRange = IDBKeyRange.upperBound(beforeVersion, true);
const eventRequest = eventIndex.openCursor(eventRange);
eventRequest.onsuccess = () => {
const cursor = eventRequest.result;
if (cursor) {
cursor.delete();
cursor.continue();
}
};
// Remove old snapshots
const snapshotStore = transaction.objectStore('snapshots');
const snapshotRange = IDBKeyRange.upperBound(beforeVersion, true);
const snapshotRequest = snapshotStore.openCursor(snapshotRange);
snapshotRequest.onsuccess = () => {
const cursor = snapshotRequest.result;
if (cursor) {
cursor.delete();
cursor.continue();
}
};
return new Promise((resolve, reject) => {
transaction.oncomplete = () => resolve();
transaction.onerror = () => reject(transaction.error);
});
}
}
exports.IndexedDBEventStore = IndexedDBEventStore;
// Create event sourced CRDT wrapper
const createEventSourcedCRDT = (baseCRDT, config, nodeId = Math.random().toString(36)) => {
let version = 0;
let eventCount = 0;
const eventStream = (0, coalgebra_1.createStreamingSignal)(null);
// Track pending events for batching
const pendingEvents = [];
let flushTimeout = null;
const flushEvents = async () => {
if (pendingEvents.length === 0)
return;
const eventsToFlush = [...pendingEvents];
pendingEvents.length = 0;
await config.eventStore.append(eventsToFlush);
// Check if we need to create a snapshot
if (eventCount % config.snapshotInterval === 0) {
await createSnapshot();
}
// Check if we need to compact
await checkCompaction();
};
const createSnapshot = async () => {
const snapshot = {
timestamp: Date.now(),
version,
state: baseCRDT.value(),
eventCount,
checksum: generateChecksum(baseCRDT.value()),
};
await config.eventStore.saveSnapshot(snapshot);
return snapshot;
};
const checkCompaction = async () => {
const { compactionStrategy, maxEvents, maxAge } = config;
switch (compactionStrategy) {
case 'event-count':
if (maxEvents && eventCount > maxEvents) {
const compactBefore = version - Math.floor(maxEvents / 2);
await config.eventStore.compact(compactBefore);
}
break;
case 'time-based':
if (maxAge) {
const cutoffTime = Date.now() - maxAge;
const events = await config.eventStore.getEvents();
const cutoffVersion = events.find((e) => e.timestamp > cutoffTime)?.version || version;
await config.eventStore.compact(cutoffVersion);
}
break;
case 'sliding-window':
if (maxEvents && eventCount > maxEvents) {
await config.eventStore.compact(version - maxEvents);
}
break;
}
};
const generateChecksum = (state) => {
return btoa(JSON.stringify(state)).slice(0, 16);
};
const addEvent = (event) => {
const fullEvent = {
...event,
id: `${nodeId}-${Date.now()}-${Math.random().toString(36)}`,
version: ++version,
nodeId,
timestamp: Date.now(),
};
pendingEvents.push(fullEvent);
eventCount++;
// Emit event immediately
eventStream._set(fullEvent);
// Batch flush events
if (flushTimeout)
clearTimeout(flushTimeout);
flushTimeout = (typeof window !== 'undefined' ? window.setTimeout : setTimeout)(flushEvents, 10);
};
const eventSourcedCRDT = {
value: baseCRDT.value,
merge: (other) => {
const merged = baseCRDT.merge(other);
addEvent({ type: 'merge', data: other.value() });
return merged;
},
events: () => eventStream,
replayFrom: async (timestamp) => {
// Get the latest snapshot before the timestamp
const snapshot = await config.eventStore.getSnapshot();
const state = snapshot ? snapshot.state : baseCRDT.value();
// Get events from snapshot version or beginning
const fromVersion = snapshot ? snapshot.version : 0;
const events = await config.eventStore.getEvents(fromVersion);
// Filter events by timestamp and replay
events.filter((e) => e.timestamp >= timestamp);
// This is a simplified replay - in practice, you'd need to apply events to recreate state
// For now, we return the current state
return state;
},
snapshot: createSnapshot,
compact: async () => {
await createSnapshot();
await config.eventStore.compact(version - config.snapshotInterval);
},
getEventCount: () => eventCount,
getVersion: () => version,
clone: () => {
return (0, exports.createEventSourcedCRDT)(baseCRDT, config, nodeId);
},
toJSON: () => {
return {
value: baseCRDT.value(),
version,
eventCount,
nodeId,
};
},
fromJSON: (data) => {
return (0, exports.createEventSourcedCRDT)(baseCRDT, config, data.nodeId || nodeId);
},
};
// Wrap original CRDT methods to emit events
const originalMethods = Object.getOwnPropertyNames(Object.getPrototypeOf(baseCRDT));
originalMethods.forEach((methodName) => {
if (typeof baseCRDT[methodName] === 'function' &&
methodName !== 'value' &&
methodName !== 'merge') {
const originalMethod = baseCRDT[methodName];
eventSourcedCRDT[methodName] = (...args) => {
const result = originalMethod.apply(baseCRDT, args);
addEvent({ type: methodName, data: args });
return result;
};
}
});
return eventSourcedCRDT;
};
exports.createEventSourcedCRDT = createEventSourcedCRDT;
// Convenience functions for common CRDT types
const eventSourcedORSet = (nodeId, config) => {
return (0, exports.createEventSourcedCRDT)((0, crdt_1.orSet)(nodeId), config, nodeId);
};
exports.eventSourcedORSet = eventSourcedORSet;
const eventSourcedGCounter = (nodeId, config) => {
return (0, exports.createEventSourcedCRDT)((0, crdt_1.gCounter)(nodeId), config, nodeId);
};
exports.eventSourcedGCounter = eventSourcedGCounter;
const indexedDBEventStore = (dbName) => new IndexedDBEventStore(dbName);
exports.indexedDBEventStore = indexedDBEventStore;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnQtc291cmNpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3RyZWFtaW5nL2V2ZW50LXNvdXJjaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0c7OztBQUVILGtDQUFnRDtBQUVoRCwyQ0FBcUU7QUEyRHJFLHVDQUF1QztBQUN2QyxNQUFhLGdCQUFnQjtJQUE3QjtRQUNVLFdBQU0sR0FBWSxFQUFFLENBQUM7UUFDckIsY0FBUyxHQUF3QixFQUFFLENBQUM7SUFpQzlDLENBQUM7SUEvQkMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFlO1FBQzFCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQsS0FBSyxDQUFDLFNBQVMsQ0FBQyxXQUFXLEdBQUcsQ0FBQyxFQUFFLFNBQVMsR0FBRyxRQUFRO1FBQ25ELE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQ3ZCLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxJQUFJLFdBQVcsSUFBSSxDQUFDLENBQUMsT0FBTyxJQUFJLFNBQVMsQ0FDMUQsQ0FBQztJQUNKLENBQUM7SUFFRCxLQUFLLENBQUMsV0FBVyxDQUNmLGFBQWEsR0FBRyxRQUFRO1FBRXhCLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUMxQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxhQUFhLENBQ2pDLENBQUM7UUFDRixPQUFPLGNBQWMsQ0FBQyxNQUFNLEdBQUcsQ0FBQztZQUM5QixDQUFDLENBQUMsY0FB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