@absolutejs/sync 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/angular/index.js +228 -6
- package/dist/angular/index.js.map +7 -4
- package/dist/client/index.js +228 -6
- package/dist/client/index.js.map +7 -4
- package/dist/crdt/index.d.ts +24 -0
- package/dist/crdt/index.js +236 -7
- package/dist/crdt/index.js.map +7 -4
- package/dist/crdt/list.d.ts +37 -0
- package/dist/crdt/lwwMap.d.ts +24 -0
- package/dist/crdt/orSet.d.ts +26 -0
- package/dist/react/index.js +228 -6
- package/dist/react/index.js.map +7 -4
- package/dist/svelte/index.js +228 -6
- package/dist/svelte/index.js.map +7 -4
- package/dist/vue/index.js +228 -6
- package/dist/vue/index.js.map +7 -4
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -68,6 +68,203 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
|
|
|
68
68
|
return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
// src/crdt/orSet.ts
|
|
72
|
+
var newTag = () => globalThis.crypto.randomUUID();
|
|
73
|
+
var defaultEquals = (a, b) => Object.is(a, b);
|
|
74
|
+
var orSet = {
|
|
75
|
+
create: () => ({ adds: [], removed: [] }),
|
|
76
|
+
add: (state, value, tag = newTag()) => ({
|
|
77
|
+
adds: [...state.adds, { value, tag }],
|
|
78
|
+
removed: state.removed
|
|
79
|
+
}),
|
|
80
|
+
remove: (state, value, equals = defaultEquals) => {
|
|
81
|
+
const tags = state.adds.filter((entry) => equals(entry.value, value)).map((entry) => entry.tag);
|
|
82
|
+
return {
|
|
83
|
+
adds: state.adds,
|
|
84
|
+
removed: [...new Set([...state.removed, ...tags])]
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
has: (state, value, equals = defaultEquals) => {
|
|
88
|
+
const removed = new Set(state.removed);
|
|
89
|
+
return state.adds.some((entry) => equals(entry.value, value) && !removed.has(entry.tag));
|
|
90
|
+
},
|
|
91
|
+
values: (state, equals = defaultEquals) => {
|
|
92
|
+
const removed = new Set(state.removed);
|
|
93
|
+
const out = [];
|
|
94
|
+
for (const entry of state.adds) {
|
|
95
|
+
if (!removed.has(entry.tag) && !out.some((value) => equals(value, entry.value))) {
|
|
96
|
+
out.push(entry.value);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
},
|
|
101
|
+
merge: (a, b) => {
|
|
102
|
+
const byTag = new Map;
|
|
103
|
+
for (const entry of [...a.adds, ...b.adds]) {
|
|
104
|
+
byTag.set(entry.tag, entry);
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
adds: [...byTag.values()],
|
|
108
|
+
removed: [...new Set([...a.removed, ...b.removed])]
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
// src/crdt/lwwMap.ts
|
|
113
|
+
var pick = (a, b) => {
|
|
114
|
+
if (b.timestamp > a.timestamp) {
|
|
115
|
+
return b;
|
|
116
|
+
}
|
|
117
|
+
if (b.timestamp < a.timestamp) {
|
|
118
|
+
return a;
|
|
119
|
+
}
|
|
120
|
+
return b.replica > a.replica ? b : a;
|
|
121
|
+
};
|
|
122
|
+
var lwwMap = {
|
|
123
|
+
create: () => ({}),
|
|
124
|
+
set: (state, key, value, replica, timestamp = Date.now()) => ({
|
|
125
|
+
...state,
|
|
126
|
+
[key]: { value, deleted: false, timestamp, replica }
|
|
127
|
+
}),
|
|
128
|
+
delete: (state, key, replica, timestamp = Date.now()) => ({
|
|
129
|
+
...state,
|
|
130
|
+
[key]: { value: state[key]?.value, deleted: true, timestamp, replica }
|
|
131
|
+
}),
|
|
132
|
+
get: (state, key) => {
|
|
133
|
+
const entry = state[key];
|
|
134
|
+
return entry !== undefined && !entry.deleted ? entry.value : undefined;
|
|
135
|
+
},
|
|
136
|
+
has: (state, key) => {
|
|
137
|
+
const entry = state[key];
|
|
138
|
+
return entry !== undefined && !entry.deleted;
|
|
139
|
+
},
|
|
140
|
+
keys: (state) => Object.keys(state).filter((key) => !state[key]?.deleted),
|
|
141
|
+
entries: (state) => {
|
|
142
|
+
const out = [];
|
|
143
|
+
for (const [key, entry] of Object.entries(state)) {
|
|
144
|
+
if (!entry.deleted && entry.value !== undefined) {
|
|
145
|
+
out.push([key, entry.value]);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return out;
|
|
149
|
+
},
|
|
150
|
+
merge: (a, b) => {
|
|
151
|
+
const out = { ...a };
|
|
152
|
+
for (const [key, entry] of Object.entries(b)) {
|
|
153
|
+
const existing = out[key];
|
|
154
|
+
out[key] = existing === undefined ? entry : pick(existing, entry);
|
|
155
|
+
}
|
|
156
|
+
return out;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
// src/crdt/list.ts
|
|
160
|
+
var order = (a, b) => {
|
|
161
|
+
if (a.clock !== b.clock) {
|
|
162
|
+
return b.clock - a.clock;
|
|
163
|
+
}
|
|
164
|
+
if (a.replica === b.replica) {
|
|
165
|
+
return 0;
|
|
166
|
+
}
|
|
167
|
+
return a.replica > b.replica ? -1 : 1;
|
|
168
|
+
};
|
|
169
|
+
var linearize = (elements) => {
|
|
170
|
+
const present = new Set(elements.map((element) => element.id));
|
|
171
|
+
const children = new Map;
|
|
172
|
+
for (const element of elements) {
|
|
173
|
+
const anchor = element.after !== null && !present.has(element.after) ? null : element.after;
|
|
174
|
+
const list = children.get(anchor);
|
|
175
|
+
if (list === undefined) {
|
|
176
|
+
children.set(anchor, [element]);
|
|
177
|
+
} else {
|
|
178
|
+
list.push(element);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
for (const list of children.values()) {
|
|
182
|
+
list.sort(order);
|
|
183
|
+
}
|
|
184
|
+
const ordered = [];
|
|
185
|
+
const stack = [...children.get(null) ?? []].reverse();
|
|
186
|
+
while (stack.length > 0) {
|
|
187
|
+
const element = stack.pop();
|
|
188
|
+
ordered.push(element);
|
|
189
|
+
const kids = children.get(element.id);
|
|
190
|
+
if (kids !== undefined) {
|
|
191
|
+
for (let index = kids.length - 1;index >= 0; index -= 1) {
|
|
192
|
+
stack.push(kids[index]);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return ordered;
|
|
197
|
+
};
|
|
198
|
+
var listOf = (state) => linearize(state.elements).filter((element) => !element.deleted).map((element) => element.value);
|
|
199
|
+
var mergeListState = (a, b) => {
|
|
200
|
+
const byId = new Map;
|
|
201
|
+
for (const element of [...a.elements, ...b.elements]) {
|
|
202
|
+
const existing = byId.get(element.id);
|
|
203
|
+
byId.set(element.id, existing === undefined ? element : { ...existing, deleted: existing.deleted || element.deleted });
|
|
204
|
+
}
|
|
205
|
+
return { elements: [...byId.values()] };
|
|
206
|
+
};
|
|
207
|
+
var createList = (replica, initial) => {
|
|
208
|
+
const elements = new Map;
|
|
209
|
+
const pending = new Map;
|
|
210
|
+
let clock = 0;
|
|
211
|
+
if (initial !== undefined) {
|
|
212
|
+
for (const element of initial.elements) {
|
|
213
|
+
elements.set(element.id, element);
|
|
214
|
+
clock = Math.max(clock, element.clock);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const visible = () => linearize([...elements.values()]).filter((element) => !element.deleted);
|
|
218
|
+
return {
|
|
219
|
+
list: () => listOf({ elements: [...elements.values()] }),
|
|
220
|
+
insert: (index, items) => {
|
|
221
|
+
const seen = visible();
|
|
222
|
+
let after = index <= 0 ? null : seen[index - 1]?.id ?? null;
|
|
223
|
+
for (const value of items) {
|
|
224
|
+
clock += 1;
|
|
225
|
+
const element = {
|
|
226
|
+
id: `${replica}:${clock}`,
|
|
227
|
+
replica,
|
|
228
|
+
clock,
|
|
229
|
+
after,
|
|
230
|
+
value,
|
|
231
|
+
deleted: false
|
|
232
|
+
};
|
|
233
|
+
elements.set(element.id, element);
|
|
234
|
+
pending.set(element.id, element);
|
|
235
|
+
after = element.id;
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
delete: (index, count) => {
|
|
239
|
+
const seen = visible();
|
|
240
|
+
for (let offset = 0;offset < count; offset += 1) {
|
|
241
|
+
const target = seen[index + offset];
|
|
242
|
+
if (target !== undefined) {
|
|
243
|
+
const tombstoned = { ...target, deleted: true };
|
|
244
|
+
elements.set(target.id, tombstoned);
|
|
245
|
+
pending.set(target.id, tombstoned);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
merge: (state) => {
|
|
250
|
+
for (const element of state.elements) {
|
|
251
|
+
const existing = elements.get(element.id);
|
|
252
|
+
elements.set(element.id, existing === undefined ? element : {
|
|
253
|
+
...existing,
|
|
254
|
+
deleted: existing.deleted || element.deleted
|
|
255
|
+
});
|
|
256
|
+
clock = Math.max(clock, element.clock);
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
state: () => ({ elements: [...elements.values()] }),
|
|
260
|
+
takeDelta: () => {
|
|
261
|
+
const delta = { elements: [...pending.values()] };
|
|
262
|
+
pending.clear();
|
|
263
|
+
return delta;
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
};
|
|
267
|
+
|
|
71
268
|
// src/crdt/index.ts
|
|
72
269
|
var sumValues = (counts) => Object.values(counts).reduce((total, value) => total + value, 0);
|
|
73
270
|
var mergeMax = (a, b) => {
|
|
@@ -125,12 +322,14 @@ var compare = (a, b) => {
|
|
|
125
322
|
}
|
|
126
323
|
return a.replica > b.replica ? -1 : 1;
|
|
127
324
|
};
|
|
128
|
-
var
|
|
325
|
+
var linearize2 = (elements) => {
|
|
326
|
+
const present = new Set(elements.map((element) => element.id));
|
|
129
327
|
const children = new Map;
|
|
130
328
|
for (const element of elements) {
|
|
131
|
-
const
|
|
329
|
+
const anchor = element.after !== null && !present.has(element.after) ? null : element.after;
|
|
330
|
+
const list = children.get(anchor);
|
|
132
331
|
if (list === undefined) {
|
|
133
|
-
children.set(
|
|
332
|
+
children.set(anchor, [element]);
|
|
134
333
|
} else {
|
|
135
334
|
list.push(element);
|
|
136
335
|
}
|
|
@@ -152,7 +351,7 @@ var linearize = (elements) => {
|
|
|
152
351
|
}
|
|
153
352
|
return ordered;
|
|
154
353
|
};
|
|
155
|
-
var textOf = (state) =>
|
|
354
|
+
var textOf = (state) => linearize2(state.elements).filter((element) => !element.deleted).map((element) => element.value).join("");
|
|
156
355
|
var mergeTextState = (a, b) => {
|
|
157
356
|
const byId = new Map;
|
|
158
357
|
for (const element of [...a.elements, ...b.elements]) {
|
|
@@ -161,6 +360,28 @@ var mergeTextState = (a, b) => {
|
|
|
161
360
|
}
|
|
162
361
|
return { elements: [...byId.values()] };
|
|
163
362
|
};
|
|
363
|
+
var tombstoneCount = (state) => state.elements.reduce((total, element) => element.deleted ? total + 1 : total, 0);
|
|
364
|
+
var compact = (state) => {
|
|
365
|
+
const byId = new Map(state.elements.map((element) => [element.id, element]));
|
|
366
|
+
const keep = new Set;
|
|
367
|
+
for (const element of state.elements) {
|
|
368
|
+
if (element.deleted) {
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
let anchor = element.after;
|
|
372
|
+
while (anchor !== null && !keep.has(anchor)) {
|
|
373
|
+
const target = byId.get(anchor);
|
|
374
|
+
if (target === undefined || !target.deleted) {
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
keep.add(anchor);
|
|
378
|
+
anchor = target.after;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return {
|
|
382
|
+
elements: state.elements.filter((element) => !element.deleted || keep.has(element.id))
|
|
383
|
+
};
|
|
384
|
+
};
|
|
164
385
|
var createTextCrdt = (replica, initial) => {
|
|
165
386
|
const elements = new Map;
|
|
166
387
|
const pending = new Map;
|
|
@@ -171,7 +392,7 @@ var createTextCrdt = (replica, initial) => {
|
|
|
171
392
|
clock = Math.max(clock, element.clock);
|
|
172
393
|
}
|
|
173
394
|
}
|
|
174
|
-
const visible = () =>
|
|
395
|
+
const visible = () => linearize2([...elements.values()]).filter((element) => !element.deleted);
|
|
175
396
|
const insert = (index, value) => {
|
|
176
397
|
const seen = visible();
|
|
177
398
|
let after = index <= 0 ? null : seen[index - 1]?.id ?? null;
|
|
@@ -247,6 +468,7 @@ var createTextCrdt = (replica, initial) => {
|
|
|
247
468
|
};
|
|
248
469
|
};
|
|
249
470
|
var rgaText = {
|
|
471
|
+
compact,
|
|
250
472
|
create: createTextCrdt,
|
|
251
473
|
empty: () => ({ elements: [] }),
|
|
252
474
|
merge: mergeTextState,
|
|
@@ -1473,5 +1695,5 @@ export {
|
|
|
1473
1695
|
createCollaborativeText
|
|
1474
1696
|
};
|
|
1475
1697
|
|
|
1476
|
-
//# debugId=
|
|
1698
|
+
//# debugId=CD9E6DE1205D7F3664756E2164756E21
|
|
1477
1699
|
//# sourceMappingURL=index.js.map
|