@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.
@@ -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 linearize = (elements) => {
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 list = children.get(element.after);
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(element.after, [element]);
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) => linearize(state.elements).filter((element) => !element.deleted).map((element) => element.value).join("");
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 = () => linearize([...elements.values()]).filter((element) => !element.deleted);
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=17AE25481DC98CA064756E2164756E21
1698
+ //# debugId=CD9E6DE1205D7F3664756E2164756E21
1477
1699
  //# sourceMappingURL=index.js.map