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
JavaScript
/**
* 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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