@korajs/merge 1.0.0-beta.11 → 1.0.0-beta.13
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 +30 -48
- package/dist/index.cjs +17 -77
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -11
- package/dist/index.d.ts +25 -11
- package/dist/index.js +2 -62
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -209,22 +209,31 @@ interface LWWResult {
|
|
|
209
209
|
declare function lastWriteWins(localValue: unknown, remoteValue: unknown, localTimestamp: HLCTimestamp, remoteTimestamp: HLCTimestamp): LWWResult;
|
|
210
210
|
|
|
211
211
|
/**
|
|
212
|
-
* Add-wins set merge strategy for array fields.
|
|
212
|
+
* Add-wins set merge strategy for array fields (three-way, base-relative).
|
|
213
213
|
*
|
|
214
|
-
* When two sides concurrently modify an array,
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
* are preserved.
|
|
214
|
+
* When two sides concurrently modify an array, every element either side ADDED
|
|
215
|
+
* survives, and every base element either side REMOVED is removed. An element
|
|
216
|
+
* one side left unchanged never resurrects an element the other side removed
|
|
217
|
+
* (MERGE-1, NEW-MERGE-1): "unchanged" is not a vote to keep it.
|
|
219
218
|
*
|
|
220
219
|
* Algorithm:
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
220
|
+
* result = (local ∩ remote) ∪ (local − base) ∪ (remote − base)
|
|
221
|
+
*
|
|
222
|
+
* Equivalently: a base element is kept only if BOTH sides kept it; a non-base
|
|
223
|
+
* element is kept if EITHER side added it.
|
|
224
|
+
*
|
|
225
|
+
* Ordering is role-independent (the two devices performing this merge call
|
|
226
|
+
* opposite sides "local"): kept base elements first, in base order, then every
|
|
227
|
+
* other element sorted by its serialized form.
|
|
226
228
|
*
|
|
227
229
|
* Uses JSON.stringify for element comparison to handle primitives and objects.
|
|
230
|
+
* Delegates to `mergeArraySet` in `@korajs/core`.
|
|
231
|
+
*
|
|
232
|
+
* Interim (S1): this is still a pairwise merge. W7 replaces it with a per-element
|
|
233
|
+
* LWW set whose result is independent of merge order.
|
|
234
|
+
*
|
|
235
|
+
* @deprecated W7 (beta.13): arrays fold as an occurrence-indexed LWW element
|
|
236
|
+
* multiset in `@korajs/core`. Kept for `experimental.legacyMerge` (one beta).
|
|
228
237
|
*
|
|
229
238
|
* @param localArray - The local array after local modifications
|
|
230
239
|
* @param remoteArray - The remote array after remote modifications
|
|
@@ -442,6 +451,11 @@ declare function resolveConstraintViolation(violation: ConstraintViolation, merg
|
|
|
442
451
|
/**
|
|
443
452
|
* Three-tier merge engine for resolving concurrent operations.
|
|
444
453
|
*
|
|
454
|
+
* @deprecated W7 (beta.13): records are materialized by the per-field CRDT fold in
|
|
455
|
+
* `@korajs/core` (`mergeOp` / `foldRecord`), which produces the MergeTraces. This
|
|
456
|
+
* pairwise engine only backs `experimental.legacyMerge` for one beta and is
|
|
457
|
+
* removed afterwards. Constraint and referential checks stay in this package.
|
|
458
|
+
*
|
|
445
459
|
* Tier 1: Auto-merge per field kind (LWW, add-wins set, CRDT)
|
|
446
460
|
* Tier 3: Custom resolvers override Tier 1 for specific fields
|
|
447
461
|
* Tier 2: Constraint validation against the candidate merged state
|
package/dist/index.d.ts
CHANGED
|
@@ -209,22 +209,31 @@ interface LWWResult {
|
|
|
209
209
|
declare function lastWriteWins(localValue: unknown, remoteValue: unknown, localTimestamp: HLCTimestamp, remoteTimestamp: HLCTimestamp): LWWResult;
|
|
210
210
|
|
|
211
211
|
/**
|
|
212
|
-
* Add-wins set merge strategy for array fields.
|
|
212
|
+
* Add-wins set merge strategy for array fields (three-way, base-relative).
|
|
213
213
|
*
|
|
214
|
-
* When two sides concurrently modify an array,
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
* are preserved.
|
|
214
|
+
* When two sides concurrently modify an array, every element either side ADDED
|
|
215
|
+
* survives, and every base element either side REMOVED is removed. An element
|
|
216
|
+
* one side left unchanged never resurrects an element the other side removed
|
|
217
|
+
* (MERGE-1, NEW-MERGE-1): "unchanged" is not a vote to keep it.
|
|
219
218
|
*
|
|
220
219
|
* Algorithm:
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
220
|
+
* result = (local ∩ remote) ∪ (local − base) ∪ (remote − base)
|
|
221
|
+
*
|
|
222
|
+
* Equivalently: a base element is kept only if BOTH sides kept it; a non-base
|
|
223
|
+
* element is kept if EITHER side added it.
|
|
224
|
+
*
|
|
225
|
+
* Ordering is role-independent (the two devices performing this merge call
|
|
226
|
+
* opposite sides "local"): kept base elements first, in base order, then every
|
|
227
|
+
* other element sorted by its serialized form.
|
|
226
228
|
*
|
|
227
229
|
* Uses JSON.stringify for element comparison to handle primitives and objects.
|
|
230
|
+
* Delegates to `mergeArraySet` in `@korajs/core`.
|
|
231
|
+
*
|
|
232
|
+
* Interim (S1): this is still a pairwise merge. W7 replaces it with a per-element
|
|
233
|
+
* LWW set whose result is independent of merge order.
|
|
234
|
+
*
|
|
235
|
+
* @deprecated W7 (beta.13): arrays fold as an occurrence-indexed LWW element
|
|
236
|
+
* multiset in `@korajs/core`. Kept for `experimental.legacyMerge` (one beta).
|
|
228
237
|
*
|
|
229
238
|
* @param localArray - The local array after local modifications
|
|
230
239
|
* @param remoteArray - The remote array after remote modifications
|
|
@@ -442,6 +451,11 @@ declare function resolveConstraintViolation(violation: ConstraintViolation, merg
|
|
|
442
451
|
/**
|
|
443
452
|
* Three-tier merge engine for resolving concurrent operations.
|
|
444
453
|
*
|
|
454
|
+
* @deprecated W7 (beta.13): records are materialized by the per-field CRDT fold in
|
|
455
|
+
* `@korajs/core` (`mergeOp` / `foldRecord`), which produces the MergeTraces. This
|
|
456
|
+
* pairwise engine only backs `experimental.legacyMerge` for one beta and is
|
|
457
|
+
* removed afterwards. Constraint and referential checks stay in this package.
|
|
458
|
+
*
|
|
445
459
|
* Tier 1: Auto-merge per field kind (LWW, add-wins set, CRDT)
|
|
446
460
|
* Tier 3: Custom resolvers override Tier 1 for specific fields
|
|
447
461
|
* Tier 2: Constraint validation against the candidate merged state
|
package/dist/index.js
CHANGED
|
@@ -9,69 +9,9 @@ function lastWriteWins(localValue, remoteValue, localTimestamp, remoteTimestamp)
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
// src/strategies/add-wins-set.ts
|
|
12
|
+
import { mergeArraySet } from "@korajs/core";
|
|
12
13
|
function addWinsSet(localArray, remoteArray, baseArray) {
|
|
13
|
-
|
|
14
|
-
const baseSet = new Set(baseArray.map(serialize));
|
|
15
|
-
const localSet = new Set(localArray.map(serialize));
|
|
16
|
-
const remoteSet = new Set(remoteArray.map(serialize));
|
|
17
|
-
const addedLocal = /* @__PURE__ */ new Set();
|
|
18
|
-
for (const s of localSet) {
|
|
19
|
-
if (!baseSet.has(s)) {
|
|
20
|
-
addedLocal.add(s);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
const addedRemote = /* @__PURE__ */ new Set();
|
|
24
|
-
for (const s of remoteSet) {
|
|
25
|
-
if (!baseSet.has(s)) {
|
|
26
|
-
addedRemote.add(s);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
const removedLocal = /* @__PURE__ */ new Set();
|
|
30
|
-
for (const s of baseSet) {
|
|
31
|
-
if (!localSet.has(s)) {
|
|
32
|
-
removedLocal.add(s);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
const removedRemote = /* @__PURE__ */ new Set();
|
|
36
|
-
for (const s of baseSet) {
|
|
37
|
-
if (!remoteSet.has(s)) {
|
|
38
|
-
removedRemote.add(s);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
const removedByBoth = /* @__PURE__ */ new Set();
|
|
42
|
-
for (const s of removedLocal) {
|
|
43
|
-
if (removedRemote.has(s)) {
|
|
44
|
-
removedByBoth.add(s);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
const resultSerialized = /* @__PURE__ */ new Set();
|
|
48
|
-
const result = [];
|
|
49
|
-
const addIfNew = (serialized, value) => {
|
|
50
|
-
if (!resultSerialized.has(serialized) && !removedByBoth.has(serialized)) {
|
|
51
|
-
resultSerialized.add(serialized);
|
|
52
|
-
result.push(value);
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
for (const item of baseArray) {
|
|
56
|
-
addIfNew(serialize(item), item);
|
|
57
|
-
}
|
|
58
|
-
const additions = /* @__PURE__ */ new Map();
|
|
59
|
-
for (const item of localArray) {
|
|
60
|
-
const s = serialize(item);
|
|
61
|
-
if (addedLocal.has(s) && !additions.has(s)) {
|
|
62
|
-
additions.set(s, item);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
for (const item of remoteArray) {
|
|
66
|
-
const s = serialize(item);
|
|
67
|
-
if (addedRemote.has(s) && !additions.has(s)) {
|
|
68
|
-
additions.set(s, item);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
for (const s of [...additions.keys()].sort()) {
|
|
72
|
-
addIfNew(s, additions.get(s));
|
|
73
|
-
}
|
|
74
|
-
return result;
|
|
14
|
+
return mergeArraySet(localArray, remoteArray, baseArray);
|
|
75
15
|
}
|
|
76
16
|
|
|
77
17
|
// src/strategies/object-merge.ts
|