UNPKG

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.

350 lines 29.3 kB
/** * CRDT (Conflict-free Replicated Data Types) Core Primitives * Following categorical design principles with commutative monoid laws */ import { signal } from '../core/signal'; export const timestamp = (nodeId = Math.random().toString(36)) => ({ time: Date.now(), nodeId, }); export const compareTimestamps = (a, b) => { if (a.time !== b.time) return a.time - b.time; return a.nodeId.localeCompare(b.nodeId); }; export const gCounter = (nodeId = Math.random().toString(36)) => { const counters = new Map(); counters.set(nodeId, 0); const instance = { value: () => Array.from(counters.values()).reduce((sum, val) => sum + val, 0), increment: (amount = 1) => { const current = counters.get(nodeId) || 0; counters.set(nodeId, current + amount); }, merge: (other) => { if (other && typeof other === 'object' && other.counters) { for (const [id, value] of Object.entries(other.counters)) { const current = counters.get(id) || 0; counters.set(id, Math.max(current, value)); } } }, clone: () => { const cloned = gCounter(nodeId); cloned.merge({ counters: Object.fromEntries(counters) }); return cloned; }, toJSON: () => ({ type: 'GCounter', counters: Object.fromEntries(counters), }), fromJSON: (json) => { if (json.type === 'GCounter' && json.counters) { counters.clear(); for (const [id, value] of Object.entries(json.counters)) { counters.set(id, value); } } }, }; return instance; }; export const pnCounter = (nodeId = Math.random().toString(36)) => { const positive = gCounter(nodeId); const negative = gCounter(nodeId); const instance = { value: () => positive.value() - negative.value(), increment: (amount = 1) => positive.increment(amount), decrement: (amount = 1) => negative.increment(amount), merge: (other) => { if (other && typeof other === 'object') { if (other.positive) positive.merge(other.positive); if (other.negative) negative.merge(other.negative); } }, clone: () => { const cloned = pnCounter(nodeId); cloned.merge({ positive: positive.toJSON(), negative: negative.toJSON(), }); return cloned; }, toJSON: () => ({ type: 'PNCounter', positive: positive.toJSON(), negative: negative.toJSON(), }), fromJSON: (json) => { if (json.type === 'PNCounter') { if (json.positive) positive.fromJSON(json.positive); if (json.negative) negative.fromJSON(json.negative); } }, }; return instance; }; export const gSet = () => { const elements = new Set(); const instance = { value: () => new Set(elements), add: (element) => elements.add(element), has: (element) => elements.has(element), merge: (other) => { if (other && typeof other === 'object' && other.elements) { for (const element of other.elements) { elements.add(element); } } }, clone: () => { const cloned = gSet(); cloned.merge({ elements: Array.from(elements) }); return cloned; }, toJSON: () => ({ type: 'GSet', elements: Array.from(elements) }), fromJSON: (json) => { if (json.type === 'GSet' && Array.isArray(json.elements)) { elements.clear(); for (const element of json.elements) { elements.add(element); } } }, }; return instance; }; export const lwwRegister = (nodeId = Math.random().toString(36), initialValue) => { let value = initialValue; let ts = initialValue !== undefined ? timestamp(nodeId) : undefined; const instance = { value: () => value, getTimestamp: () => ts, set: (newValue) => { value = newValue; ts = timestamp(nodeId); }, merge: (other) => { if (other && typeof other === 'object' && other.timestamp) { const otherTs = other.timestamp; if (!ts || compareTimestamps(otherTs, ts) > 0) { value = other.value; ts = otherTs; } } }, clone: () => { const cloned = lwwRegister(nodeId); if (ts) { cloned.merge({ value, timestamp: ts }); } return cloned; }, toJSON: () => ({ type: 'LWWRegister', value, timestamp: ts }), fromJSON: (json) => { if (json.type === 'LWWRegister') { value = json.value; ts = json.timestamp; } }, }; return instance; }; export const orSet = (nodeId = Math.random().toString(36)) => { const added = new Map(); const removed = new Map(); const generateTag = () => `${nodeId}-${Date.now()}-${Math.random()}`; const instance = { value: () => { const result = new Set(); const addedEntries = Array.from(added.entries()); for (const [element, addTags] of addedEntries) { const removeTags = removed.get(element) || new Set(); // Element is in the set if it has add tags not in remove tags if (Array.from(addTags).some((tag) => !removeTags.has(tag))) { result.add(element); } } return result; }, add: (element) => { if (!added.has(element)) { added.set(element, new Set()); } added.get(element).add(generateTag()); }, remove: (element) => { const addTags = added.get(element); if (addTags) { if (!removed.has(element)) { removed.set(element, new Set()); } const removeTags = removed.get(element); const addTagsArray = Array.from(addTags); for (const tag of addTagsArray) { removeTags.add(tag); } } }, has: (element) => instance.value().has(element), merge: (other) => { if (other && typeof other === 'object') { // Merge added tags if (other.added) { for (const [element, tags] of Object.entries(other.added)) { if (!added.has(element)) { added.set(element, new Set()); } const currentTags = added.get(element); for (const tag of tags) { currentTags.add(tag); } } } // Merge removed tags if (other.removed) { for (const [element, tags] of Object.entries(other.removed)) { if (!removed.has(element)) { removed.set(element, new Set()); } const currentTags = removed.get(element); for (const tag of tags) { currentTags.add(tag); } } } } }, clone: () => { const cloned = orSet(nodeId); cloned.merge({ added: Object.fromEntries(Array.from(added.entries()).map(([k, v]) => [k, Array.from(v)])), removed: Object.fromEntries(Array.from(removed.entries()).map(([k, v]) => [k, Array.from(v)])), }); return cloned; }, toJSON: () => ({ type: 'ORSet', added: Object.fromEntries(Array.from(added.entries()).map(([k, v]) => [k, Array.from(v)])), removed: Object.fromEntries(Array.from(removed.entries()).map(([k, v]) => [k, Array.from(v)])), }), fromJSON: (json) => { if (json.type === 'ORSet') { if (json.added) { added.clear(); for (const [element, tags] of Object.entries(json.added)) { added.set(element, new Set(tags)); } } if (json.removed) { removed.clear(); for (const [element, tags] of Object.entries(json.removed)) { removed.set(element, new Set(tags)); } } } }, }; return instance; }; // Reactive G-Counter export const reactiveGCounter = (nodeId) => { const crdt = gCounter(nodeId); const sig = signal(crdt.value()); // Create wrapper with reactive methods const reactiveWrapper = { ...crdt, increment: (amount) => { crdt.increment(amount); sig._set(crdt.value()); }, merge: (other) => { crdt.merge(other); sig._set(crdt.value()); }, }; return { crdt: reactiveWrapper, signal: sig, subscribe: sig.subscribe, }; }; // Reactive PN-Counter export const reactivePNCounter = (nodeId) => { const crdt = pnCounter(nodeId); const sig = signal(crdt.value()); // Create wrapper with reactive methods const reactiveWrapper = { ...crdt, increment: (amount) => { crdt.increment(amount); sig._set(crdt.value()); }, decrement: (amount) => { crdt.decrement(amount); sig._set(crdt.value()); }, merge: (other) => { crdt.merge(other); sig._set(crdt.value()); }, }; return { crdt: reactiveWrapper, signal: sig, subscribe: sig.subscribe, }; }; // Reactive OR-Set export const reactiveORSet = (nodeId) => { const crdt = orSet(nodeId); const sig = signal(crdt.value()); // Create wrapper with reactive methods const reactiveWrapper = { ...crdt, add: (element) => { crdt.add(element); sig._set(crdt.value()); }, remove: (element) => { crdt.remove(element); sig._set(crdt.value()); }, merge: (other) => { crdt.merge(other); sig._set(crdt.value()); }, }; return { crdt: reactiveWrapper, signal: sig, subscribe: sig.subscribe, }; }; // Reactive LWW-Register export const reactiveLWWRegister = (nodeId, initialValue) => { const crdt = lwwRegister(nodeId, initialValue); const sig = signal(crdt.value()); // Create wrapper with reactive methods const reactiveWrapper = { ...crdt, set: (value) => { crdt.set(value); sig._set(crdt.value()); }, merge: (other) => { crdt.merge(other); sig._set(crdt.value()); }, }; return { crdt: reactiveWrapper, signal: sig, subscribe: sig.subscribe, }; }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY3JkdC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxPQUFPLEVBQUUsTUFBTSxFQUFVLE1BQU0sZ0JBQWdCLENBQUM7QUFpQmhELE1BQU0sQ0FBQyxNQUFNLFNBQVMsR0FBRyxDQUN2QixTQUFpQixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxFQUNoQyxFQUFFLENBQUMsQ0FBQztJQUNmLElBQUksRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO0lBQ2hCLE1BQU07Q0FDUCxDQUFDLENBQUM7QUFFSCxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLENBQVksRUFBRSxDQUFZLEVBQVUsRUFBRTtJQUN0RSxJQUFJLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLElBQUk7UUFBRSxPQUFPLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUM5QyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUMxQyxDQUFDLENBQUM7QUFlRixNQUFNLENBQUMsTUFBTSxRQUFRLEdBQUcsQ0FDdEIsU0FBaUIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsRUFDakMsRUFBRTtJQUNaLE1BQU0sUUFBUSxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO0lBQzNDLFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRXhCLE1BQU0sUUFBUSxHQUFhO1FBQ3pCLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FDVixLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVB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