@vuer-ai/vuer-rtc 0.7.0 → 0.8.2
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/CLAUDE.md +3 -2
- package/dist/client/EditBuffer.d.ts +4 -4
- package/dist/client/EditBuffer.d.ts.map +1 -1
- package/dist/client/EditBuffer.js +26 -25
- package/dist/client/EditBuffer.js.map +1 -1
- package/dist/client/actions.d.ts +3 -3
- package/dist/client/actions.d.ts.map +1 -1
- package/dist/client/actions.js +71 -70
- package/dist/client/actions.js.map +1 -1
- package/dist/client/coalesceGraphOps.d.ts +4 -4
- package/dist/client/coalesceGraphOps.js +4 -4
- package/dist/client/coalesceTextOperations.d.ts.map +1 -1
- package/dist/client/coalesceTextOperations.js +23 -20
- package/dist/client/coalesceTextOperations.js.map +1 -1
- package/dist/client/coalescence/lwwOperations.js +3 -3
- package/dist/client/coalescence/lwwOperations.js.map +1 -1
- package/dist/client/coalescence/numberOperations.js +2 -2
- package/dist/client/coalescence/numberOperations.js.map +1 -1
- package/dist/client/coalescence/registry.d.ts +3 -3
- package/dist/client/coalescence/registry.d.ts.map +1 -1
- package/dist/client/coalescence/registry.js +11 -11
- package/dist/client/coalescence/registry.js.map +1 -1
- package/dist/client/coalescence/textDeletes.d.ts +8 -7
- package/dist/client/coalescence/textDeletes.d.ts.map +1 -1
- package/dist/client/coalescence/textDeletes.js +11 -11
- package/dist/client/coalescence/textDeletes.js.map +1 -1
- package/dist/client/coalescence/textInserts.d.ts +8 -5
- package/dist/client/coalescence/textInserts.d.ts.map +1 -1
- package/dist/client/coalescence/textInserts.js +32 -12
- package/dist/client/coalescence/textInserts.js.map +1 -1
- package/dist/client/coalescence/utils.d.ts +3 -9
- package/dist/client/coalescence/utils.d.ts.map +1 -1
- package/dist/client/coalescence/utils.js +10 -8
- package/dist/client/coalescence/utils.js.map +1 -1
- package/dist/client/coalescence/vector3Operations.js +2 -2
- package/dist/client/coalescence/vector3Operations.js.map +1 -1
- package/dist/client/createGraph.d.ts +2 -2
- package/dist/client/createGraph.js +4 -4
- package/dist/client/createGraph.js.map +1 -1
- package/dist/client/createTextDocument.d.ts +1 -1
- package/dist/client/createTextDocument.js +3 -3
- package/dist/client/createTextDocument.js.map +1 -1
- package/dist/client/hooks.d.ts +3 -3
- package/dist/client/hooks.d.ts.map +1 -1
- package/dist/client/hooks.js +4 -4
- package/dist/client/hooks.js.map +1 -1
- package/dist/client/textActions.d.ts +2 -2
- package/dist/client/textActions.d.ts.map +1 -1
- package/dist/client/textActions.js +47 -47
- package/dist/client/textActions.js.map +1 -1
- package/dist/client/textTypes.d.ts +8 -8
- package/dist/client/textTypes.d.ts.map +1 -1
- package/dist/client/types.d.ts +4 -4
- package/dist/client/types.d.ts.map +1 -1
- package/dist/crdt/GraphTextCRDT.d.ts +2 -2
- package/dist/crdt/GraphTextCRDT.d.ts.map +1 -1
- package/dist/crdt/GraphTextCRDT.js +6 -6
- package/dist/crdt/GraphTextCRDT.js.map +1 -1
- package/dist/crdt/Rope.d.ts +13 -14
- package/dist/crdt/Rope.d.ts.map +1 -1
- package/dist/crdt/Rope.js +130 -59
- package/dist/crdt/Rope.js.map +1 -1
- package/dist/crdt/index.d.ts +1 -1
- package/dist/crdt/index.d.ts.map +1 -1
- package/dist/crdt/index.js +1 -1
- package/dist/crdt/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/operations/OperationTypes.d.ts +45 -48
- package/dist/operations/OperationTypes.d.ts.map +1 -1
- package/dist/operations/OperationValidator.js +11 -11
- package/dist/operations/OperationValidator.js.map +1 -1
- package/dist/operations/apply/node.js +3 -3
- package/dist/operations/apply/node.js.map +1 -1
- package/dist/operations/apply/text.d.ts.map +1 -1
- package/dist/operations/apply/text.js +35 -32
- package/dist/operations/apply/text.js.map +1 -1
- package/dist/operations/apply/types.d.ts +4 -4
- package/dist/operations/apply/types.d.ts.map +1 -1
- package/dist/operations/apply/types.js +8 -8
- package/dist/operations/apply/types.js.map +1 -1
- package/dist/operations/dispatcher.d.ts.map +1 -1
- package/dist/operations/dispatcher.js +52 -13
- package/dist/operations/dispatcher.js.map +1 -1
- package/dist/serdes.d.ts +1 -1
- package/dist/serdes.d.ts.map +1 -1
- package/dist/state/ConflictResolver.d.ts +9 -9
- package/dist/state/ConflictResolver.d.ts.map +1 -1
- package/dist/state/ConflictResolver.js +20 -20
- package/dist/state/ConflictResolver.js.map +1 -1
- package/dist/state/DType.d.ts +2 -2
- package/dist/state/DType.d.ts.map +1 -1
- package/dist/state/DType.js +14 -14
- package/dist/state/DType.js.map +1 -1
- package/dist/state/VectorClock.d.ts +6 -6
- package/dist/state/VectorClock.d.ts.map +1 -1
- package/dist/state/VectorClock.js +14 -14
- package/dist/state/VectorClock.js.map +1 -1
- package/dist/state/index.d.ts +1 -1
- package/dist/state/index.js +1 -1
- package/examples/01-basic-usage.ts +16 -16
- package/examples/02-concurrent-edits.ts +29 -29
- package/examples/03-scene-building.ts +28 -28
- package/examples/04-conflict-resolution.ts +56 -56
- package/examples/05-coalescence-usage.ts +23 -23
- package/examples/README.md +12 -12
- package/package.json +1 -1
- package/src/client/EditBuffer.ts +28 -27
- package/src/client/TEXT_DOCUMENT_API.md +9 -9
- package/src/client/actions.ts +74 -70
- package/src/client/coalesceGraphOps.ts +4 -4
- package/src/client/coalesceTextOperations.ts +26 -22
- package/src/client/coalescence/lwwOperations.ts +3 -3
- package/src/client/coalescence/numberOperations.ts +2 -2
- package/src/client/coalescence/registry.ts +13 -12
- package/src/client/coalescence/textDeletes.ts +22 -18
- package/src/client/coalescence/textInserts.ts +49 -25
- package/src/client/coalescence/utils.ts +14 -11
- package/src/client/coalescence/vector3Operations.ts +2 -2
- package/src/client/createGraph.ts +4 -4
- package/src/client/createTextDocument.ts +3 -3
- package/src/client/hooks.tsx +5 -5
- package/src/client/textActions.ts +47 -47
- package/src/client/textTypes.ts +8 -8
- package/src/client/types.ts +4 -4
- package/src/crdt/GraphTextCRDT.ts +6 -6
- package/src/crdt/Rope.ts +156 -71
- package/src/crdt/index.ts +2 -0
- package/src/index.ts +2 -0
- package/src/operations/OperationTypes.ts +47 -47
- package/src/operations/OperationValidator.ts +11 -11
- package/src/operations/apply/node.ts +3 -3
- package/src/operations/apply/text.ts +38 -32
- package/src/operations/apply/types.ts +11 -11
- package/src/operations/dispatcher.ts +57 -13
- package/src/serdes.ts +1 -1
- package/src/state/ConflictResolver.ts +23 -23
- package/src/state/DType.ts +16 -16
- package/src/state/VectorClock.ts +14 -14
- package/src/state/index.ts +1 -1
- package/tests/client/actions.test.ts +76 -76
- package/tests/client/coalesce-graph-operations.test.ts +84 -84
- package/tests/client/coalesce-text-operations.test.ts +91 -114
- package/tests/client/compaction.test.ts +18 -18
- package/tests/client/delete-coalescence-bug.test.ts +34 -34
- package/tests/client/edit-buffer.test.ts +27 -30
- package/tests/client/graph-coalescence-phase1.test.ts +66 -66
- package/tests/client/graph-coalescence.test.ts +50 -50
- package/tests/client/journal-benchmark.test.ts +5 -5
- package/tests/crdt/graph-text-crdt.test.ts +60 -64
- package/tests/crdt/rope.test.ts +9 -8
- package/tests/crdt/text-operations.test.ts +28 -28
- package/tests/fixtures/array-ops.jsonl +6 -6
- package/tests/fixtures/boolean-ops.jsonl +6 -6
- package/tests/fixtures/color-ops.jsonl +4 -4
- package/tests/fixtures/edit-buffer.jsonl +3 -3
- package/tests/fixtures/node-ops.jsonl +6 -6
- package/tests/fixtures/number-ops.jsonl +7 -7
- package/tests/fixtures/object-ops.jsonl +4 -4
- package/tests/fixtures/operations.jsonl +7 -7
- package/tests/fixtures/string-ops.jsonl +4 -4
- package/tests/fixtures/undo-redo.jsonl +3 -3
- package/tests/fixtures/vector-ops.jsonl +17 -17
- package/tests/operations/collections.test.ts +4 -4
- package/tests/operations/nodes.test.ts +5 -5
- package/tests/operations/operation-ordering.test.ts +406 -0
- package/tests/operations/primitives.test.ts +4 -4
- package/tests/operations/unified-schema.test.ts +27 -27
- package/tests/operations/vectors.test.ts +4 -4
- package/tests/sync/digest.test.ts +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coalesceTextOperations.js","sourceRoot":"","sources":["../../src/client/coalesceTextOperations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"coalesceTextOperations.js","sourceRoot":"","sources":["../../src/client/coalesceTextOperations.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Check if an operation is a *.set operation
|
|
14
14
|
*/
|
|
15
15
|
export function isLWWSetOp(op) {
|
|
16
|
-
return (typeof op.
|
|
17
|
-
op.
|
|
16
|
+
return (typeof op.ot === 'string' &&
|
|
17
|
+
op.ot.endsWith('.set') &&
|
|
18
18
|
op.value !== undefined);
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
@@ -48,7 +48,7 @@ export function coalesceLWWSets(ops, options = {}) {
|
|
|
48
48
|
// Check if operations target the same property AND same operation type
|
|
49
49
|
const sameTarget = pending.key === op.key &&
|
|
50
50
|
pending.path === op.path &&
|
|
51
|
-
pending.
|
|
51
|
+
pending.ot === op.ot;
|
|
52
52
|
if (sameTarget) {
|
|
53
53
|
// LWW: Replace with newer value
|
|
54
54
|
pending = { ...op };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lwwOperations.js","sourceRoot":"","sources":["../../../src/client/coalescence/lwwOperations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA4BH;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,EAAa;IACtC,OAAO,CACL,OAAO,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"lwwOperations.js","sourceRoot":"","sources":["../../../src/client/coalescence/lwwOperations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA4BH;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,EAAa;IACtC,OAAO,CACL,OAAO,EAAE,CAAC,EAAE,KAAK,QAAQ;QACzB,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;QACrB,EAAU,CAAC,KAAK,KAAK,SAAS,CAChC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,eAAe,CAC7B,GAAe,EACf,UAA2B,EAAE;IAE7B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAEjC,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,IAAI,OAAO,GAAoB,IAAI,CAAC;IAEpC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,wBAAwB;YACxB,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,uEAAuE;YACvE,MAAM,UAAU,GACd,OAAO,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG;gBACtB,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI;gBACxB,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YAEvB,IAAI,UAAU,EAAE,CAAC;gBACf,gCAAgC;gBAChC,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACN,yDAAyD;gBACzD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrB,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Check if an operation is a number.add operation
|
|
9
9
|
*/
|
|
10
10
|
export function isNumberAddOp(op) {
|
|
11
|
-
return (op.
|
|
11
|
+
return (op.ot === 'number.add' &&
|
|
12
12
|
typeof op.value === 'number');
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
@@ -44,7 +44,7 @@ export function coalesceNumberAdds(ops, options = {}) {
|
|
|
44
44
|
if (sameTarget) {
|
|
45
45
|
// Merge operations by summing values
|
|
46
46
|
pending = {
|
|
47
|
-
|
|
47
|
+
ot: 'number.add',
|
|
48
48
|
key: pending.key,
|
|
49
49
|
path: pending.path,
|
|
50
50
|
value: pending.value + op.value,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"numberOperations.js","sourceRoot":"","sources":["../../../src/client/coalescence/numberOperations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,EAAa;IACzC,OAAO,CACL,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"numberOperations.js","sourceRoot":"","sources":["../../../src/client/coalescence/numberOperations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,EAAa;IACzC,OAAO,CACL,EAAE,CAAC,EAAE,KAAK,YAAY;QACtB,OAAQ,EAAU,CAAC,KAAK,KAAK,QAAQ,CACtC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,kBAAkB,CAChC,GAAkB,EAClB,UAA2B,EAAE;IAE7B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAEjC,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,IAAI,OAAO,GAAuB,IAAI,CAAC;IAEvC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,wBAAwB;YACxB,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,+CAA+C;YAC/C,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,CAAC;YAEtE,IAAI,UAAU,EAAE,CAAC;gBACf,qCAAqC;gBACrC,OAAO,GAAG;oBACR,EAAE,EAAE,YAAY;oBAChB,GAAG,EAAE,OAAO,CAAC,GAAG;oBAChB,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK;iBAChC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,iDAAiD;gBACjD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrB,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -27,15 +27,15 @@ interface RegistryEntry<T extends Operation = Operation> {
|
|
|
27
27
|
/**
|
|
28
28
|
* Register a coalescence handler for an operation type
|
|
29
29
|
*/
|
|
30
|
-
export declare function registerCoalescer<T extends Operation>(
|
|
30
|
+
export declare function registerCoalescer<T extends Operation>(ot: string, guard: TypeGuard<T>, handler: CoalesceHandler<T>): void;
|
|
31
31
|
/**
|
|
32
32
|
* Get coalescence handler for an operation type
|
|
33
33
|
*/
|
|
34
|
-
export declare function getCoalescer(
|
|
34
|
+
export declare function getCoalescer(ot: string): RegistryEntry | undefined;
|
|
35
35
|
/**
|
|
36
36
|
* Check if an operation type has a registered coalescer
|
|
37
37
|
*/
|
|
38
|
-
export declare function hasCoalescer(
|
|
38
|
+
export declare function hasCoalescer(ot: string): boolean;
|
|
39
39
|
/**
|
|
40
40
|
* Coalesce operations by grouping by type and applying registered handlers
|
|
41
41
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAmF,MAAM,oCAAoC,CAAC;AAQrJ,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,IAAI,CAC7D,GAAG,EAAE,CAAC,EAAE,EACR,OAAO,EAAE,eAAe,KACrB,CAAC,EAAE,CAAC;AAET;;GAEG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,IAAI,CAAC,EAAE,EAAE,SAAS,KAAK,EAAE,IAAI,CAAC,CAAC;AAEpF;;GAEG;AACH,UAAU,aAAa,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS;IACrD,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;CAC7B;AAOD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,SAAS,EACnD,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,EACnB,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,GAC1B,IAAI,CAKN;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAElE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,SAAS,EAAE,EAChB,OAAO,GAAE,eAAoB,GAC5B,SAAS,EAAE,CAoDb"}
|
|
@@ -16,8 +16,8 @@ const registry = new Map();
|
|
|
16
16
|
/**
|
|
17
17
|
* Register a coalescence handler for an operation type
|
|
18
18
|
*/
|
|
19
|
-
export function registerCoalescer(
|
|
20
|
-
registry.set(
|
|
19
|
+
export function registerCoalescer(ot, guard, handler) {
|
|
20
|
+
registry.set(ot, {
|
|
21
21
|
guard: guard,
|
|
22
22
|
handler: handler
|
|
23
23
|
});
|
|
@@ -25,14 +25,14 @@ export function registerCoalescer(otype, guard, handler) {
|
|
|
25
25
|
/**
|
|
26
26
|
* Get coalescence handler for an operation type
|
|
27
27
|
*/
|
|
28
|
-
export function getCoalescer(
|
|
29
|
-
return registry.get(
|
|
28
|
+
export function getCoalescer(ot) {
|
|
29
|
+
return registry.get(ot);
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* Check if an operation type has a registered coalescer
|
|
33
33
|
*/
|
|
34
|
-
export function hasCoalescer(
|
|
35
|
-
return registry.has(
|
|
34
|
+
export function hasCoalescer(ot) {
|
|
35
|
+
return registry.has(ot);
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
38
|
* Coalesce operations by grouping by type and applying registered handlers
|
|
@@ -48,10 +48,10 @@ export function coalesceOperations(ops, options = {}) {
|
|
|
48
48
|
let pendingGroup = [];
|
|
49
49
|
let currentType = null;
|
|
50
50
|
for (const op of ops) {
|
|
51
|
-
const entry = registry.get(op.
|
|
51
|
+
const entry = registry.get(op.ot);
|
|
52
52
|
if (entry && entry.guard(op)) {
|
|
53
53
|
// Operation has a coalescer
|
|
54
|
-
if (currentType === op.
|
|
54
|
+
if (currentType === op.ot) {
|
|
55
55
|
// Same type - add to pending group
|
|
56
56
|
pendingGroup.push(op);
|
|
57
57
|
}
|
|
@@ -64,7 +64,7 @@ export function coalesceOperations(ops, options = {}) {
|
|
|
64
64
|
result.push(...coalesced);
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
-
currentType = op.
|
|
67
|
+
currentType = op.ot;
|
|
68
68
|
pendingGroup = [op];
|
|
69
69
|
}
|
|
70
70
|
}
|
|
@@ -109,7 +109,7 @@ const LWW_SET_OPERATIONS = [
|
|
|
109
109
|
'array.set',
|
|
110
110
|
'object.set',
|
|
111
111
|
];
|
|
112
|
-
for (const
|
|
113
|
-
registerCoalescer(
|
|
112
|
+
for (const ot of LWW_SET_OPERATIONS) {
|
|
113
|
+
registerCoalescer(ot, isLWWSetOp, coalesceLWWSets);
|
|
114
114
|
}
|
|
115
115
|
//# sourceMappingURL=registry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/client/coalescence/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAqB,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAqB,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/client/coalescence/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,15 +3,16 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Merges consecutive text delete operations.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Text delete operation for graph coalescence.
|
|
8
|
+
* This is the wire format for text.delete operations (with key/path context).
|
|
9
|
+
* Uses compressed schema with tuple-based fields.
|
|
10
|
+
*/
|
|
7
11
|
export interface TextDeleteOp {
|
|
8
|
-
|
|
12
|
+
ot: 'text.delete';
|
|
9
13
|
key: string;
|
|
10
14
|
path: string;
|
|
11
|
-
|
|
12
|
-
id: string;
|
|
13
|
-
length: number;
|
|
14
|
-
}>;
|
|
15
|
+
rm: Array<[string, number]>;
|
|
15
16
|
}
|
|
16
17
|
export interface CoalesceOptions {
|
|
17
18
|
/** Time threshold in milliseconds (default: 1000ms = 1 second) */
|
|
@@ -20,7 +21,7 @@ export interface CoalesceOptions {
|
|
|
20
21
|
/**
|
|
21
22
|
* Check if an operation is a text delete with CRDT metadata
|
|
22
23
|
*/
|
|
23
|
-
export declare function isTextDeleteOp(op:
|
|
24
|
+
export declare function isTextDeleteOp(op: any): op is TextDeleteOp;
|
|
24
25
|
/**
|
|
25
26
|
* Coalesce consecutive text delete operations.
|
|
26
27
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textDeletes.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/textDeletes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"textDeletes.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/textDeletes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,aAAa,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAG7B;AAED,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAsBD;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,GAAG,GAAG,EAAE,IAAI,YAAY,CAM1D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,YAAY,EAAE,EACnB,OAAO,GAAE,eAAoB,GAC5B,YAAY,EAAE,CAgDhB"}
|
|
@@ -13,8 +13,8 @@ function sortAndOptimizeDeletions(deletions) {
|
|
|
13
13
|
return deletions;
|
|
14
14
|
// Sort deletions by agent, then by sequence number (ascending)
|
|
15
15
|
const sorted = [...deletions].sort((a, b) => {
|
|
16
|
-
const aId = parseItemId(a
|
|
17
|
-
const bId = parseItemId(b
|
|
16
|
+
const aId = parseItemId(a[0]); // id is at [0]
|
|
17
|
+
const bId = parseItemId(b[0]); // id is at [0]
|
|
18
18
|
if (aId.agent !== bId.agent) {
|
|
19
19
|
return aId.agent.localeCompare(bId.agent);
|
|
20
20
|
}
|
|
@@ -26,9 +26,9 @@ function sortAndOptimizeDeletions(deletions) {
|
|
|
26
26
|
* Check if an operation is a text delete with CRDT metadata
|
|
27
27
|
*/
|
|
28
28
|
export function isTextDeleteOp(op) {
|
|
29
|
-
return (op.
|
|
30
|
-
Array.isArray(op.
|
|
31
|
-
op.
|
|
29
|
+
return (op.ot === 'text.delete' &&
|
|
30
|
+
Array.isArray(op.rm) &&
|
|
31
|
+
op.rm.length > 0);
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* Coalesce consecutive text delete operations.
|
|
@@ -50,7 +50,7 @@ export function coalesceTextDeletes(ops, options = {}) {
|
|
|
50
50
|
for (const op of ops) {
|
|
51
51
|
if (pending === null) {
|
|
52
52
|
// Start new pending delete
|
|
53
|
-
pending = { ...op,
|
|
53
|
+
pending = { ...op, rm: [...op.rm] };
|
|
54
54
|
}
|
|
55
55
|
else {
|
|
56
56
|
// Check merge conditions
|
|
@@ -60,29 +60,29 @@ export function coalesceTextDeletes(ops, options = {}) {
|
|
|
60
60
|
if (sameTarget) {
|
|
61
61
|
// Merge operations - combine deletion lists
|
|
62
62
|
const merged = {
|
|
63
|
-
|
|
63
|
+
ot: 'text.delete',
|
|
64
64
|
key: pending.key,
|
|
65
65
|
path: pending.path,
|
|
66
|
-
|
|
66
|
+
rm: [...pending.rm, ...op.rm],
|
|
67
67
|
};
|
|
68
68
|
pending = merged;
|
|
69
69
|
}
|
|
70
70
|
else {
|
|
71
71
|
// Can't merge - flush pending and start new
|
|
72
72
|
result.push(pending);
|
|
73
|
-
pending = { ...op,
|
|
73
|
+
pending = { ...op, rm: [...op.rm] };
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
// Flush any remaining pending delete
|
|
78
78
|
if (pending !== null) {
|
|
79
79
|
// Sort and optimize deletions array before pushing
|
|
80
|
-
pending.
|
|
80
|
+
pending.rm = sortAndOptimizeDeletions(pending.rm);
|
|
81
81
|
result.push(pending);
|
|
82
82
|
}
|
|
83
83
|
// Also sort and optimize deletions in all previously pushed operations
|
|
84
84
|
for (const op of result) {
|
|
85
|
-
op.
|
|
85
|
+
op.rm = sortAndOptimizeDeletions(op.rm);
|
|
86
86
|
}
|
|
87
87
|
return result;
|
|
88
88
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textDeletes.js","sourceRoot":"","sources":["../../../src/client/coalescence/textDeletes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"textDeletes.js","sourceRoot":"","sources":["../../../src/client/coalescence/textDeletes.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,14 +11,17 @@
|
|
|
11
11
|
* 4. Within time threshold (ts difference)
|
|
12
12
|
* 5. Compatible YATA structure (forms a chain)
|
|
13
13
|
*/
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Text insert operation for graph coalescence.
|
|
16
|
+
* This is the wire format for text.insert operations (with key/path context).
|
|
17
|
+
* Uses compressed schema with tuple-based fields.
|
|
18
|
+
*/
|
|
15
19
|
export interface TextInsertOp {
|
|
16
|
-
|
|
20
|
+
ot: 'text.insert';
|
|
17
21
|
key: string;
|
|
18
22
|
path: string;
|
|
19
23
|
id: string;
|
|
20
|
-
|
|
21
|
-
parentId: string | null;
|
|
24
|
+
value: [string | null, string];
|
|
22
25
|
seq: number;
|
|
23
26
|
ts: number;
|
|
24
27
|
}
|
|
@@ -29,7 +32,7 @@ export interface CoalesceOptions {
|
|
|
29
32
|
/**
|
|
30
33
|
* Check if an operation is a text insert with CRDT metadata
|
|
31
34
|
*/
|
|
32
|
-
export declare function isTextInsertOp(op:
|
|
35
|
+
export declare function isTextInsertOp(op: any): op is TextInsertOp;
|
|
33
36
|
/**
|
|
34
37
|
* Coalesce consecutive text insert operations.
|
|
35
38
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textInserts.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/textInserts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"textInserts.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/textInserts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,aAAa,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,CAAC,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;CACZ;AAmBD,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,GAAG,GAAG,EAAE,IAAI,YAAY,CAS1D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,YAAY,EAAE,EACnB,OAAO,GAAE,eAAoB,GAC5B,YAAY,EAAE,CAsEhB"}
|
|
@@ -12,13 +12,30 @@
|
|
|
12
12
|
* 5. Compatible YATA structure (forms a chain)
|
|
13
13
|
*/
|
|
14
14
|
import { parseItemId } from '../../crdt/Rope.js';
|
|
15
|
+
/**
|
|
16
|
+
* Calculate the last character ID for an insert operation.
|
|
17
|
+
* If the operation has _lastCharId metadata, use it. Otherwise calculate from id + content length.
|
|
18
|
+
*/
|
|
19
|
+
function getLastCharId(op) {
|
|
20
|
+
// Check if operation has _lastCharId metadata (from previous coalescence)
|
|
21
|
+
const lastCharId = op._lastCharId;
|
|
22
|
+
if (lastCharId)
|
|
23
|
+
return lastCharId;
|
|
24
|
+
// Calculate from id + content length
|
|
25
|
+
const content = op.value[1];
|
|
26
|
+
if (content.length === 0)
|
|
27
|
+
return op.id;
|
|
28
|
+
const parsed = parseItemId(op.id);
|
|
29
|
+
return `${parsed.agent}:${parsed.seq + content.length - 1}`;
|
|
30
|
+
}
|
|
15
31
|
/**
|
|
16
32
|
* Check if an operation is a text insert with CRDT metadata
|
|
17
33
|
*/
|
|
18
34
|
export function isTextInsertOp(op) {
|
|
19
|
-
return (op.
|
|
35
|
+
return (op.ot === 'text.insert' &&
|
|
20
36
|
typeof op.id === 'string' &&
|
|
21
|
-
|
|
37
|
+
Array.isArray(op.value) &&
|
|
38
|
+
op.value.length === 2 &&
|
|
22
39
|
typeof op.seq === 'number' &&
|
|
23
40
|
typeof op.ts === 'number');
|
|
24
41
|
}
|
|
@@ -51,9 +68,10 @@ export function coalesceTextInserts(ops, options = {}) {
|
|
|
51
68
|
// Check merge conditions
|
|
52
69
|
const sameAgent = prevId.agent === currId.agent;
|
|
53
70
|
const sameTarget = pending.key === op.key && pending.path === op.path;
|
|
54
|
-
// IDs must be sequential: next ID = prev ID + prev content length
|
|
55
|
-
// Example: prev="alice:5"
|
|
56
|
-
const
|
|
71
|
+
// IDs must be sequential: next ID = prev ID + prev value/content length
|
|
72
|
+
// Example: prev="alice:5" value="hel"(3 chars) → next="alice:8"
|
|
73
|
+
const pendingContent = pending.value[1]; // content is value[1]
|
|
74
|
+
const sequentialIds = currId.seq === prevId.seq + pendingContent.length;
|
|
57
75
|
// Time threshold: operations must be close in time (ts is in seconds)
|
|
58
76
|
const timeDiffMs = (op.ts - pending.ts) * 1000;
|
|
59
77
|
const withinThreshold = timeDiffMs <= thresholdMs;
|
|
@@ -61,22 +79,24 @@ export function coalesceTextInserts(ops, options = {}) {
|
|
|
61
79
|
// Current op's parent should be the last character ID in the merged content
|
|
62
80
|
// (not the first ID, which is what pending.id contains after merging)
|
|
63
81
|
// OR both should have the same parent (inserting at same position)
|
|
64
|
-
const prevLastId = pending
|
|
65
|
-
const
|
|
66
|
-
|
|
82
|
+
const prevLastId = getLastCharId(pending);
|
|
83
|
+
const opAnchor = op.value[0]; // anchor is value[0] (can be null)
|
|
84
|
+
const pendingAnchor = pending.value[0]; // anchor is value[0] (can be null)
|
|
85
|
+
const formsChain = opAnchor === prevLastId ||
|
|
86
|
+
(pendingAnchor === opAnchor && pendingAnchor !== null);
|
|
67
87
|
if (sameAgent && sameTarget && sequentialIds && withinThreshold && formsChain) {
|
|
68
88
|
// Merge operations
|
|
89
|
+
const opContent = op.value[1]; // content is value[1]
|
|
69
90
|
const merged = {
|
|
70
|
-
|
|
91
|
+
ot: 'text.insert',
|
|
71
92
|
key: pending.key,
|
|
72
93
|
path: pending.path,
|
|
73
94
|
id: pending.id, // Keep first ID (anchor point)
|
|
74
|
-
|
|
75
|
-
parentId: pending.parentId, // Keep first parentId
|
|
95
|
+
value: [pendingAnchor, pendingContent + opContent], // [anchor, merged content]
|
|
76
96
|
seq: Math.max(pending.seq, op.seq), // Use max Lamport clock for ordering
|
|
77
97
|
ts: pending.ts, // Keep first timestamp (when sequence started)
|
|
78
98
|
// Track the last character ID for chain validation in next merge
|
|
79
|
-
_lastCharId: op
|
|
99
|
+
_lastCharId: getLastCharId(op),
|
|
80
100
|
};
|
|
81
101
|
pending = merged;
|
|
82
102
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textInserts.js","sourceRoot":"","sources":["../../../src/client/coalescence/textInserts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"textInserts.js","sourceRoot":"","sources":["../../../src/client/coalescence/textInserts.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,16 +14,10 @@ export declare function parseItemId(id: ItemId): {
|
|
|
14
14
|
* Optimize a deletions array by merging consecutive deletions from the same agent.
|
|
15
15
|
*
|
|
16
16
|
* Example:
|
|
17
|
-
* Input: [
|
|
18
|
-
* Output: [
|
|
17
|
+
* Input: [["alice:1", 1], ["alice:2", 1], ["alice:3", 1]]
|
|
18
|
+
* Output: [["alice:1", 3]]
|
|
19
19
|
*
|
|
20
20
|
* This reduces the size of deletion arrays when consecutive items are deleted.
|
|
21
21
|
*/
|
|
22
|
-
export declare function optimizeDeletions(deletions: Array<
|
|
23
|
-
id: ItemId;
|
|
24
|
-
length: number;
|
|
25
|
-
}>): Array<{
|
|
26
|
-
id: ItemId;
|
|
27
|
-
length: number;
|
|
28
|
-
}>;
|
|
22
|
+
export declare function optimizeDeletions(deletions: Array<[ItemId, number]>): Array<[ItemId, number]>;
|
|
29
23
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAStE;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,KAAK,CAAC
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/client/coalescence/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAStE;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACjC,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA8BzB"}
|
|
@@ -19,8 +19,8 @@ export function parseItemId(id) {
|
|
|
19
19
|
* Optimize a deletions array by merging consecutive deletions from the same agent.
|
|
20
20
|
*
|
|
21
21
|
* Example:
|
|
22
|
-
* Input: [
|
|
23
|
-
* Output: [
|
|
22
|
+
* Input: [["alice:1", 1], ["alice:2", 1], ["alice:3", 1]]
|
|
23
|
+
* Output: [["alice:1", 3]]
|
|
24
24
|
*
|
|
25
25
|
* This reduces the size of deletion arrays when consecutive items are deleted.
|
|
26
26
|
*/
|
|
@@ -28,21 +28,23 @@ export function optimizeDeletions(deletions) {
|
|
|
28
28
|
if (deletions.length === 0)
|
|
29
29
|
return deletions;
|
|
30
30
|
const result = [];
|
|
31
|
-
let current =
|
|
31
|
+
let current = [...deletions[0]]; // Clone the tuple
|
|
32
32
|
for (let i = 1; i < deletions.length; i++) {
|
|
33
33
|
const deletion = deletions[i];
|
|
34
|
-
const
|
|
35
|
-
const
|
|
34
|
+
const currentId = current[0]; // id is at [0]
|
|
35
|
+
const deletionId = deletion[0]; // id is at [0]
|
|
36
|
+
const currParsed = parseItemId(currentId);
|
|
37
|
+
const delParsed = parseItemId(deletionId);
|
|
36
38
|
// Can merge if: same agent AND current deletion ends where next starts
|
|
37
39
|
if (currParsed.agent === delParsed.agent &&
|
|
38
|
-
currParsed.seq + current
|
|
40
|
+
currParsed.seq + current[1] === delParsed.seq) {
|
|
39
41
|
// Merge: extend current deletion
|
|
40
|
-
current
|
|
42
|
+
current[1] += deletion[1]; // length is at [1]
|
|
41
43
|
}
|
|
42
44
|
else {
|
|
43
45
|
// Cannot merge: push current and start new
|
|
44
46
|
result.push(current);
|
|
45
|
-
current =
|
|
47
|
+
current = [...deletion]; // Clone the tuple
|
|
46
48
|
}
|
|
47
49
|
}
|
|
48
50
|
// Push final deletion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/client/coalescence/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,EAAU;IACpC,MAAM,UAAU,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;QACtB,8BAA8B;QAC9B,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IAC/B,CAAC;IACD,MAAM,KAAK,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,QAAQ,CAAC,EAAE,CAAC,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AAC9C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/client/coalescence/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,EAAU;IACpC,MAAM,UAAU,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;QACtB,8BAA8B;QAC9B,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IAC/B,CAAC;IACD,MAAM,KAAK,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,QAAQ,CAAC,EAAE,CAAC,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AAC9C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,SAAkC;IAElC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAE7C,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,IAAI,OAAO,GAAqB,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB;IAErE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe;QAC7C,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe;QAE/C,MAAM,UAAU,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,SAAS,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;QAE1C,uEAAuE;QACvE,IAAI,UAAU,CAAC,KAAK,KAAK,SAAS,CAAC,KAAK;YACpC,UAAU,CAAC,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,GAAG,EAAE,CAAC;YAClD,iCAAiC;YACjC,OAAO,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB;QAChD,CAAC;aAAM,CAAC;YACN,2CAA2C;YAC3C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrB,OAAO,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,kBAAkB;QAC7C,CAAC;IACH,CAAC;IAED,sBAAsB;IACtB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAErB,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Check if an operation is a vector3.add operation
|
|
9
9
|
*/
|
|
10
10
|
export function isVector3AddOp(op) {
|
|
11
|
-
return (op.
|
|
11
|
+
return (op.ot === 'vector3.add' &&
|
|
12
12
|
Array.isArray(op.value) &&
|
|
13
13
|
op.value.length === 3);
|
|
14
14
|
}
|
|
@@ -45,7 +45,7 @@ export function coalesceVector3Adds(ops, options = {}) {
|
|
|
45
45
|
if (sameTarget) {
|
|
46
46
|
// Merge operations by summing vectors component-wise
|
|
47
47
|
pending = {
|
|
48
|
-
|
|
48
|
+
ot: 'vector3.add',
|
|
49
49
|
key: pending.key,
|
|
50
50
|
path: pending.path,
|
|
51
51
|
value: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vector3Operations.js","sourceRoot":"","sources":["../../../src/client/coalescence/vector3Operations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAAa;IAC1C,OAAO,CACL,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"vector3Operations.js","sourceRoot":"","sources":["../../../src/client/coalescence/vector3Operations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAAa;IAC1C,OAAO,CACL,EAAE,CAAC,EAAE,KAAK,aAAa;QACvB,KAAK,CAAC,OAAO,CAAE,EAAU,CAAC,KAAK,CAAC;QAC/B,EAAU,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAC/B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAAmB,EACnB,UAA2B,EAAE;IAE7B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAEjC,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,IAAI,OAAO,GAAwB,IAAI,CAAC;IAExC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,8DAA8D;YAC9D,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAA6B,EAAE,CAAC;QACxE,CAAC;aAAM,CAAC;YACN,+CAA+C;YAC/C,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,CAAC;YAEtE,IAAI,UAAU,EAAE,CAAC;gBACf,qDAAqD;gBACrD,OAAO,GAAG;oBACR,EAAE,EAAE,aAAa;oBACjB,GAAG,EAAE,OAAO,CAAC,GAAG;oBAChB,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,KAAK,EAAE;wBACL,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;wBAC9B,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;wBAC9B,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;qBAC/B;iBACF,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,iDAAiD;gBACjD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrB,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAA6B,EAAE,CAAC;YACxE,CAAC;QACH,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* Usage:
|
|
5
5
|
* ```typescript
|
|
6
6
|
* const store = createGraph({
|
|
7
|
-
*
|
|
7
|
+
* client: 'my-session',
|
|
8
8
|
* onSend: (msg) => websocket.send(msg),
|
|
9
9
|
* });
|
|
10
10
|
*
|
|
11
|
-
* store.edit({
|
|
11
|
+
* store.edit({ ot: 'vector3.add', key: 'cube', path: 'position', value: [1, 0, 0] });
|
|
12
12
|
* store.commit('Move cube');
|
|
13
13
|
* store.undo();
|
|
14
14
|
* ```
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* Usage:
|
|
5
5
|
* ```typescript
|
|
6
6
|
* const store = createGraph({
|
|
7
|
-
*
|
|
7
|
+
* client: 'my-session',
|
|
8
8
|
* onSend: (msg) => websocket.send(msg),
|
|
9
9
|
* });
|
|
10
10
|
*
|
|
11
|
-
* store.edit({
|
|
11
|
+
* store.edit({ ot: 'vector3.add', key: 'cube', path: 'position', value: [1, 0, 0] });
|
|
12
12
|
* store.commit('Move cube');
|
|
13
13
|
* store.undo();
|
|
14
14
|
* ```
|
|
@@ -18,7 +18,7 @@ import { createInitialState, onEdit, commitEdits, onServerAck, onRemoteMessage,
|
|
|
18
18
|
* Create a graph store
|
|
19
19
|
*/
|
|
20
20
|
export function createGraph(options) {
|
|
21
|
-
let state = createInitialState(options.
|
|
21
|
+
let state = createInitialState(options.client, options.initialSnapshot);
|
|
22
22
|
const listeners = new Set();
|
|
23
23
|
let coalescingTimer = null;
|
|
24
24
|
let coalescingEnabled = options.coalescingEnabled ?? false;
|
|
@@ -101,7 +101,7 @@ export function createGraph(options) {
|
|
|
101
101
|
dispatch(s => onServerAck(s, msgId));
|
|
102
102
|
},
|
|
103
103
|
loadServerState: (snapshot, journal) => {
|
|
104
|
-
dispatch(() => initFromServer(options.
|
|
104
|
+
dispatch(() => initFromServer(options.client, snapshot, journal));
|
|
105
105
|
},
|
|
106
106
|
// Undo/redo
|
|
107
107
|
undo: () => {
|