@cr_docs_t/dts 0.35.2 → 0.35.3
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/dist/dts/Serailizers/General.d.ts +2 -1
- package/dist/dts/Serailizers/General.d.ts.map +1 -1
- package/dist/dts/Serailizers/index.d.ts.map +1 -1
- package/dist/dts/Serailizers/index.js +0 -1
- package/dist/dts/index.d.ts +0 -3
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/index.js +0 -3
- package/dist/tests/unit/mocks/FugueTree-mocks.d.ts.map +1 -1
- package/dist/types/Message.d.ts +1 -0
- package/dist/types/Message.d.ts.map +1 -1
- package/dist/types/Presence.d.ts +7 -3
- package/dist/types/Presence.d.ts.map +1 -1
- package/dist/types/Presence.js +3 -0
- package/package.json +1 -1
- package/dist/dts/CausalTree/CTNode.d.ts +0 -7
- package/dist/dts/CausalTree/CTNode.d.ts.map +0 -1
- package/dist/dts/CausalTree/CTNode.js +0 -5
- package/dist/dts/CausalTree/CausalTree.d.ts +0 -6
- package/dist/dts/CausalTree/CausalTree.d.ts.map +0 -1
- package/dist/dts/CausalTree/CausalTree.js +0 -5
- package/dist/dts/CausalTree/index.d.ts +0 -3
- package/dist/dts/CausalTree/index.d.ts.map +0 -1
- package/dist/dts/CausalTree/index.js +0 -2
- package/dist/dts/Fugue/FNode.d.ts +0 -6
- package/dist/dts/Fugue/FNode.d.ts.map +0 -1
- package/dist/dts/Fugue/FNode.js +0 -6
- package/dist/dts/Fugue/FugueList.d.ts +0 -102
- package/dist/dts/Fugue/FugueList.d.ts.map +0 -1
- package/dist/dts/Fugue/FugueList.js +0 -432
- package/dist/dts/Fugue/index.d.ts +0 -2
- package/dist/dts/Fugue/index.d.ts.map +0 -1
- package/dist/dts/Fugue/index.js +0 -2
- package/dist/dts/Serailizers/Fugue/Message.d.ts +0 -9
- package/dist/dts/Serailizers/Fugue/Message.d.ts.map +0 -1
- package/dist/dts/Serailizers/Fugue/Message.js +0 -73
- package/dist/dts/Serailizers/Fugue/State.d.ts +0 -9
- package/dist/dts/Serailizers/Fugue/State.d.ts.map +0 -1
- package/dist/dts/Serailizers/Fugue/State.js +0 -16
- package/dist/dts/Serailizers/Fugue/index.d.ts +0 -3
- package/dist/dts/Serailizers/Fugue/index.d.ts.map +0 -1
- package/dist/dts/Serailizers/Fugue/index.js +0 -2
- package/dist/dts/TotalOrder/StringTotalOrder.d.ts +0 -11
- package/dist/dts/TotalOrder/StringTotalOrder.d.ts.map +0 -1
- package/dist/dts/TotalOrder/StringTotalOrder.js +0 -38
- package/dist/dts/TotalOrder/UniquelyDenseTotalOrder.d.ts +0 -27
- package/dist/dts/TotalOrder/UniquelyDenseTotalOrder.d.ts.map +0 -1
- package/dist/dts/TotalOrder/UniquelyDenseTotalOrder.js +0 -1
- package/dist/dts/TotalOrder/index.d.ts +0 -3
- package/dist/dts/TotalOrder/index.d.ts.map +0 -1
- package/dist/dts/TotalOrder/index.js +0 -2
- package/dist/types/Fugue/Fugue.d.ts +0 -3
- package/dist/types/Fugue/Fugue.d.ts.map +0 -1
- package/dist/types/Fugue/Fugue.js +0 -1
- package/dist/types/Fugue/Message.d.ts +0 -36
- package/dist/types/Fugue/Message.d.ts.map +0 -1
- package/dist/types/Fugue/Message.js +0 -8
- package/dist/types/Fugue/index.d.ts +0 -3
- package/dist/types/Fugue/index.d.ts.map +0 -1
- package/dist/types/Fugue/index.js +0 -2
|
@@ -2,8 +2,9 @@ import { BasePresenceMessage } from "../../types/Presence.js";
|
|
|
2
2
|
import { BaseMessage } from "../../types/Message.js";
|
|
3
3
|
import { BaseFugueMessage } from "../../types/index.js";
|
|
4
4
|
export type Message = BaseFugueMessage[] | BasePresenceMessage[];
|
|
5
|
+
type OutgoingMessage = BaseMessage | BasePresenceMessage;
|
|
5
6
|
export declare const COMP = true;
|
|
6
|
-
declare function serialize(msgs:
|
|
7
|
+
declare function serialize(msgs: OutgoingMessage | OutgoingMessage[]): Uint8Array;
|
|
7
8
|
declare function deserialize(bytes: Uint8Array): Message;
|
|
8
9
|
export declare const Serializer: {
|
|
9
10
|
serialize: typeof serialize;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"General.d.ts","sourceRoot":"","sources":["../../../src/dts/Serailizers/General.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAe,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAMxD,MAAM,MAAM,OAAO,GAAG,gBAAgB,EAAE,GAAG,mBAAmB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"General.d.ts","sourceRoot":"","sources":["../../../src/dts/Serailizers/General.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAe,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAMxD,MAAM,MAAM,OAAO,GAAG,gBAAgB,EAAE,GAAG,mBAAmB,EAAE,CAAC;AACjE,KAAK,eAAe,GAAG,WAAW,GAAG,mBAAmB,CAAC;AAEzD,eAAO,MAAM,IAAI,OAAO,CAAC;AAIzB,iBAAS,SAAS,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe,EAAE,GAAG,UAAU,CAyBxE;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAyB/C;AAED,eAAO,MAAM,UAAU;;;CAGtB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dts/Serailizers/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dts/Serailizers/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC"}
|
package/dist/dts/index.d.ts
CHANGED
package/dist/dts/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dts/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dts/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC"}
|
package/dist/dts/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FugueTree-mocks.d.ts","sourceRoot":"","sources":["../../../../src/tests/unit/mocks/FugueTree-mocks.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FugueTree-mocks.d.ts","sourceRoot":"","sources":["../../../../src/tests/unit/mocks/FugueTree-mocks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,YAAY,EAA0B,MAAM,yBAAyB,CAAC;AAE/E,eAAO,MAAM,MAAM,aAAa,CAAC;AACjC,eAAO,MAAM,OAAO,cAAc,CAAC;AAEnC;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAExE;AAED,eAAO,MAAM,cAAc,WAAkB,CAAC;AAE9C;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAOpD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAChC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,MAAe,GAC5B,YAAY,CAYd;AAED,wBAAgB,oBAAoB,CAChC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAC7C,UAAU,GAAE,MAAe,GAC5B,YAAY,CAWd"}
|
package/dist/types/Message.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../src/types/Message.ts"],"names":[],"mappings":"AAAA,oBAAY,WAAW;IACnB,KAAK,IAAA;IACL,QAAQ,IAAA;CACX;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW;IAC5D,OAAO,EAAE,CAAC,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../src/types/Message.ts"],"names":[],"mappings":"AAAA,oBAAY,WAAW;IACnB,KAAK,IAAA;IACL,QAAQ,IAAA;CACX;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW;IAC5D,OAAO,EAAE,CAAC,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB"}
|
package/dist/types/Presence.d.ts
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { BaseMessage, MessageType } from "./Message.js";
|
|
2
2
|
export declare enum PresenceMessageType {
|
|
3
3
|
CURSOR = 0,
|
|
4
|
-
UPDATE = 1
|
|
4
|
+
UPDATE = 1,
|
|
5
|
+
JOIN = 2
|
|
5
6
|
}
|
|
6
|
-
export interface BasePresenceMessage<T extends PresenceMessageType = PresenceMessageType> extends BaseMessage<MessageType.PRESENCE> {
|
|
7
|
+
export interface BasePresenceMessage<T extends PresenceMessageType = PresenceMessageType> extends Omit<BaseMessage<MessageType.PRESENCE>, "documentID"> {
|
|
7
8
|
type: T;
|
|
9
|
+
documentID?: string;
|
|
8
10
|
}
|
|
9
11
|
export interface PresenceCursorMessage extends BasePresenceMessage<PresenceMessageType.CURSOR> {
|
|
10
12
|
pos: number;
|
|
11
13
|
}
|
|
12
14
|
export interface PresenceUpdateMessage extends BasePresenceMessage<PresenceMessageType.UPDATE> {
|
|
13
15
|
}
|
|
14
|
-
export
|
|
16
|
+
export interface PresenceJoinMessage extends BasePresenceMessage<PresenceMessageType.JOIN> {
|
|
17
|
+
}
|
|
18
|
+
export type PresenceMessage = PresenceCursorMessage | PresenceUpdateMessage | PresenceJoinMessage;
|
|
15
19
|
export declare const makePresenceMsg: <T extends PresenceMessage>(msg: Omit<T, "msgType">) => BasePresenceMessage;
|
|
16
20
|
//# sourceMappingURL=Presence.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Presence.d.ts","sourceRoot":"","sources":["../../src/types/Presence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAExD,oBAAY,mBAAmB;IAC3B,MAAM,IAAA;IACN,MAAM,IAAA;
|
|
1
|
+
{"version":3,"file":"Presence.d.ts","sourceRoot":"","sources":["../../src/types/Presence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAExD,oBAAY,mBAAmB;IAC3B,MAAM,IAAA;IACN,MAAM,IAAA;IACN,IAAI,IAAA;CACP;AAED,MAAM,WAAW,mBAAmB,CAClC,CAAC,SAAS,mBAAmB,GAAG,mBAAmB,CACnD,SAAQ,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IAC7D,IAAI,EAAE,CAAC,CAAC;IACR,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,qBAAsB,SAAQ,mBAAmB,CAAC,mBAAmB,CAAC,MAAM,CAAC;IAC1F,GAAG,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAsB,SAAQ,mBAAmB,CAAC,mBAAmB,CAAC,MAAM,CAAC;CAAI;AAElG,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB,CAAC,mBAAmB,CAAC,IAAI,CAAC;CAAI;AAE9F,MAAM,MAAM,eAAe,GAAG,qBAAqB,GAAG,qBAAqB,GAAG,mBAAmB,CAAC;AAElG,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,eAAe,EAAE,KAAK,IAAI,CAAC,CAAC,EAAE,SAAS,CAAC,KAAG,mBAKpF,CAAC"}
|
package/dist/types/Presence.js
CHANGED
|
@@ -3,7 +3,10 @@ export var PresenceMessageType;
|
|
|
3
3
|
(function (PresenceMessageType) {
|
|
4
4
|
PresenceMessageType[PresenceMessageType["CURSOR"] = 0] = "CURSOR";
|
|
5
5
|
PresenceMessageType[PresenceMessageType["UPDATE"] = 1] = "UPDATE";
|
|
6
|
+
PresenceMessageType[PresenceMessageType["JOIN"] = 2] = "JOIN";
|
|
6
7
|
})(PresenceMessageType || (PresenceMessageType = {}));
|
|
8
|
+
;
|
|
9
|
+
;
|
|
7
10
|
export const makePresenceMsg = (msg) => {
|
|
8
11
|
return {
|
|
9
12
|
...msg,
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CTNode.d.ts","sourceRoot":"","sources":["../../../src/dts/CausalTree/CTNode.ts"],"names":[],"mappings":"AAAA,qBAAa,MAAM;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;gBAEH,GAAG,EAAE,MAAM;CAG1B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CausalTree.d.ts","sourceRoot":"","sources":["../../../src/dts/CausalTree/CausalTree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,qBAAa,UAAU;IAWnB,IAAI,EAAE,MAAM,CAAC;gBAED,IAAI,EAAE,MAAM;CAG3B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dts/CausalTree/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FNode.d.ts","sourceRoot":"","sources":["../../../src/dts/Fugue/FNode.ts"],"names":[],"mappings":"AAEA,qBAAa,SAAS,CAAC,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,CAAC,CAAC;gBAEA,QAAQ,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM;CAI1C"}
|
package/dist/dts/Fugue/FNode.js
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { FugueState, FugueMessage } from "../../types/Fugue/index.js";
|
|
2
|
-
import { UniquelyDenseTotalOrder } from "../TotalOrder/UniquelyDenseTotalOrder.js";
|
|
3
|
-
/**
|
|
4
|
-
* A Fugue List CRDT, with insert and delete operations
|
|
5
|
-
*/
|
|
6
|
-
export declare class FugueList<P> {
|
|
7
|
-
state: FugueState<P>;
|
|
8
|
-
totalOrder: UniquelyDenseTotalOrder<P>;
|
|
9
|
-
positionCounter: number;
|
|
10
|
-
ws: WebSocket | null;
|
|
11
|
-
documentID: string;
|
|
12
|
-
userIdentity: string | undefined;
|
|
13
|
-
readonly batchSize = 100;
|
|
14
|
-
constructor(totalOrder: UniquelyDenseTotalOrder<P>, ws: WebSocket | null, documentID: string, userIdentity?: string);
|
|
15
|
-
/**
|
|
16
|
-
* Propagates message or messages to replicas
|
|
17
|
-
* @param msg - Message or messages to propagate to replicas
|
|
18
|
-
*/
|
|
19
|
-
private propagate;
|
|
20
|
-
private binarySearchPosition;
|
|
21
|
-
/**
|
|
22
|
-
* Inserts a value at a given position
|
|
23
|
-
* @param position - Position to insert at
|
|
24
|
-
* @param value - Value to insert
|
|
25
|
-
*/
|
|
26
|
-
private insertAtPosition;
|
|
27
|
-
/**
|
|
28
|
-
* Generates unique position for new element at 'index'
|
|
29
|
-
* @param index - Index to generate position for
|
|
30
|
-
* @returns Generated position
|
|
31
|
-
*/
|
|
32
|
-
private generatePosition;
|
|
33
|
-
/**
|
|
34
|
-
* Inserts new element with 'value' at 'index' in the list
|
|
35
|
-
* @param index - Index to insert 'value' at
|
|
36
|
-
* @param value - Value to insert
|
|
37
|
-
*/
|
|
38
|
-
insert(index: number, value: string): void;
|
|
39
|
-
/**
|
|
40
|
-
* Inserts multiple characters at given index, this
|
|
41
|
-
* handles large insertions by batching messages
|
|
42
|
-
* @param index - Index to insert at
|
|
43
|
-
* @param value - Value to insert
|
|
44
|
-
*/
|
|
45
|
-
insertMultiple(index: number, value: string): void;
|
|
46
|
-
/**
|
|
47
|
-
* Deletes value at given position
|
|
48
|
-
* @param position - Position to delete at
|
|
49
|
-
*/
|
|
50
|
-
private deleteAtPosition;
|
|
51
|
-
/**
|
|
52
|
-
* Finds the position of the visible value at index
|
|
53
|
-
* this ignores tombstoned values
|
|
54
|
-
* @param index - Index of the visible value
|
|
55
|
-
*/
|
|
56
|
-
findVisiblePosition(index: number): P | undefined;
|
|
57
|
-
/**
|
|
58
|
-
* Finds the visible index of the value at position
|
|
59
|
-
* this ignores tombstoned values
|
|
60
|
-
* @param position - Position to find visible index for
|
|
61
|
-
* @returns
|
|
62
|
-
*/
|
|
63
|
-
findVisibleIndex(position: P): number | undefined;
|
|
64
|
-
/**
|
|
65
|
-
* Delete value in the list at index
|
|
66
|
-
* @param index - Index of the value to delete
|
|
67
|
-
*/
|
|
68
|
-
delete(index: number): void;
|
|
69
|
-
/**
|
|
70
|
-
* Deletes multiple values starting from index, this
|
|
71
|
-
* handles large deletions by batching messages
|
|
72
|
-
* @param index - Starting index to delete from
|
|
73
|
-
* @param count - Number of values to delete
|
|
74
|
-
*/
|
|
75
|
-
deleteMultiple(index: number, count: number): void;
|
|
76
|
-
/**
|
|
77
|
-
* Observes the current visible state of the list
|
|
78
|
-
* @returns The current visible state of the list as a string
|
|
79
|
-
*/
|
|
80
|
-
observe(): string;
|
|
81
|
-
/**
|
|
82
|
-
* Applies a single effect message to the list
|
|
83
|
-
* @param msg - Message to apply effect for
|
|
84
|
-
*/
|
|
85
|
-
private singleEffect;
|
|
86
|
-
/**
|
|
87
|
-
* Applies batched effect messages to the list
|
|
88
|
-
* @param msgs - Messages to apply effect for in batch
|
|
89
|
-
*/
|
|
90
|
-
private batchEffect;
|
|
91
|
-
/**
|
|
92
|
-
* Applies effect messages to the list
|
|
93
|
-
* @param msg - Message or messages to apply effect for, can be batched
|
|
94
|
-
*/
|
|
95
|
-
effect(msg: FugueMessage<P> | FugueMessage<P>[]): void;
|
|
96
|
-
replicaId(): string;
|
|
97
|
-
/**
|
|
98
|
-
* Performs garbage collection by removing tombstoned nodes from the state
|
|
99
|
-
*/
|
|
100
|
-
garbageCollect(): void;
|
|
101
|
-
}
|
|
102
|
-
//# sourceMappingURL=FugueList.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FugueList.d.ts","sourceRoot":"","sources":["../../../src/dts/Fugue/FugueList.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAa,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AAInF;;GAEG;AACH,qBAAa,SAAS,CAAC,CAAC;IACpB,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAM;IAC1B,UAAU,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC;IACvC,eAAe,SAAK;IACpB,EAAE,EAAE,SAAS,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,SAAS,OAAO;gBAGrB,UAAU,EAAE,uBAAuB,CAAC,CAAC,CAAC,EACtC,EAAE,EAAE,SAAS,GAAG,IAAI,EACpB,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM;IAQzB;;;OAGG;IACH,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,oBAAoB;IAmB5B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAqBxB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IASxB;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAenC;;;;;OAKG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAiD3C;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;;;OAIG;IACH,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAajD;;;;;OAKG;IACH,gBAAgB,CAAC,QAAQ,EAAE,CAAC,GAAG,MAAM,GAAG,SAAS;IAejD;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM;IAqBpB;;;;;OAKG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAqD3C;;;OAGG;IACH,OAAO,IAAI,MAAM;IAmBjB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAcpB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAqGnB;;;OAGG;IACH,MAAM,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE;IAW/C,SAAS,IAAI,MAAM;IAInB;;OAEG;IACH,cAAc;CAOjB"}
|
|
@@ -1,432 +0,0 @@
|
|
|
1
|
-
import { FListNode } from "./FNode.js";
|
|
2
|
-
import { Operation } from "../../types/Fugue/index.js";
|
|
3
|
-
import { FugueMessageSerialzier } from "../Serailizers/Fugue/index.js";
|
|
4
|
-
import { logger } from "../../utils/logging.js";
|
|
5
|
-
/**
|
|
6
|
-
* A Fugue List CRDT, with insert and delete operations
|
|
7
|
-
*/
|
|
8
|
-
export class FugueList {
|
|
9
|
-
constructor(totalOrder, ws, documentID, userIdentity) {
|
|
10
|
-
this.state = [];
|
|
11
|
-
this.positionCounter = 0;
|
|
12
|
-
this.batchSize = 100;
|
|
13
|
-
this.totalOrder = totalOrder;
|
|
14
|
-
this.ws = ws;
|
|
15
|
-
this.documentID = documentID;
|
|
16
|
-
this.userIdentity = userIdentity;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Propagates message or messages to replicas
|
|
20
|
-
* @param msg - Message or messages to propagate to replicas
|
|
21
|
-
*/
|
|
22
|
-
propagate(msg) {
|
|
23
|
-
if (!this.ws)
|
|
24
|
-
return;
|
|
25
|
-
const allMsgs = Array.isArray(msg) ? msg : [msg];
|
|
26
|
-
const serializedFugueMsg = FugueMessageSerialzier.serialize(allMsgs);
|
|
27
|
-
this.ws.send(serializedFugueMsg);
|
|
28
|
-
}
|
|
29
|
-
binarySearchPosition(position) {
|
|
30
|
-
let low = 0;
|
|
31
|
-
let high = this.state.length - 1;
|
|
32
|
-
while (low <= high) {
|
|
33
|
-
const mid = Math.floor((low + high) / 2);
|
|
34
|
-
const midPos = this.state[mid][0].position;
|
|
35
|
-
const cmp = this.totalOrder.compare(midPos, position);
|
|
36
|
-
if (cmp === 0) {
|
|
37
|
-
return mid;
|
|
38
|
-
}
|
|
39
|
-
else if (cmp < 0) {
|
|
40
|
-
low = mid + 1;
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
high = mid - 1;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
// If not found, return the position where it can be inserted
|
|
47
|
-
return low;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Inserts a value at a given position
|
|
51
|
-
* @param position - Position to insert at
|
|
52
|
-
* @param value - Value to insert
|
|
53
|
-
*/
|
|
54
|
-
insertAtPosition(position, value) {
|
|
55
|
-
let index = this.binarySearchPosition(position);
|
|
56
|
-
// Check if the position already exists at this index, i.e. there is a collision
|
|
57
|
-
if (index < this.state.length && this.totalOrder.compare(this.state[index][0].position, position) === 0) {
|
|
58
|
-
const cell = this.state[index];
|
|
59
|
-
const existing = cell.find((n) => this.totalOrder.compare(n.position, position) === 0);
|
|
60
|
-
// Don't insert if it already exists,
|
|
61
|
-
// TODO: ideally this should trigger a collision resolution
|
|
62
|
-
if (!existing) {
|
|
63
|
-
cell.push(new FListNode(position, value));
|
|
64
|
-
cell.sort((a, b) => this.totalOrder.compare(a.position, b.position));
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
// Insert new cell at index
|
|
68
|
-
else {
|
|
69
|
-
this.state.splice(index, 0, [new FListNode(position, value)]);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Generates unique position for new element at 'index'
|
|
74
|
-
* @param index - Index to generate position for
|
|
75
|
-
* @returns Generated position
|
|
76
|
-
*/
|
|
77
|
-
generatePosition(index) {
|
|
78
|
-
// If this is the first thing in the document
|
|
79
|
-
if (this.state.length === 0)
|
|
80
|
-
return this.totalOrder.createBetween();
|
|
81
|
-
const prev = index > 0 ? this.findVisiblePosition(index - 1) : undefined;
|
|
82
|
-
const next = this.findVisiblePosition(index);
|
|
83
|
-
return this.totalOrder.createBetween(prev, next);
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Inserts new element with 'value' at 'index' in the list
|
|
87
|
-
* @param index - Index to insert 'value' at
|
|
88
|
-
* @param value - Value to insert
|
|
89
|
-
*/
|
|
90
|
-
insert(index, value) {
|
|
91
|
-
const pos = this.generatePosition(index);
|
|
92
|
-
this.insertAtPosition(pos, value);
|
|
93
|
-
this.propagate({
|
|
94
|
-
documentID: this.documentID,
|
|
95
|
-
replicaId: this.totalOrder.getReplicaId(),
|
|
96
|
-
operation: Operation.INSERT,
|
|
97
|
-
position: pos,
|
|
98
|
-
userIdentity: this.userIdentity,
|
|
99
|
-
data: value,
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Inserts multiple characters at given index, this
|
|
104
|
-
* handles large insertions by batching messages
|
|
105
|
-
* @param index - Index to insert at
|
|
106
|
-
* @param value - Value to insert
|
|
107
|
-
*/
|
|
108
|
-
insertMultiple(index, value) {
|
|
109
|
-
if (value.length === 0)
|
|
110
|
-
return;
|
|
111
|
-
if (value.length === 1) {
|
|
112
|
-
this.insert(index, value);
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
// Find left and right anchors
|
|
116
|
-
const lA = index > 0 ? this.findVisiblePosition(index - 1) : undefined;
|
|
117
|
-
const rA = this.findVisiblePosition(index);
|
|
118
|
-
const newCells = [];
|
|
119
|
-
let cL = lA;
|
|
120
|
-
let msgs = [];
|
|
121
|
-
for (const c of value) {
|
|
122
|
-
const pos = this.totalOrder.createBetween(cL, rA);
|
|
123
|
-
// Collect new cells
|
|
124
|
-
newCells.push([new FListNode(pos, c)]);
|
|
125
|
-
// Batch propagate
|
|
126
|
-
msgs.push({
|
|
127
|
-
documentID: this.documentID,
|
|
128
|
-
replicaId: this.totalOrder.getReplicaId(),
|
|
129
|
-
operation: Operation.INSERT,
|
|
130
|
-
position: pos,
|
|
131
|
-
userIdentity: this.userIdentity,
|
|
132
|
-
data: c,
|
|
133
|
-
});
|
|
134
|
-
cL = pos;
|
|
135
|
-
if (msgs.length >= this.batchSize) {
|
|
136
|
-
this.propagate(msgs);
|
|
137
|
-
msgs = [];
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
// Single splice to insert all new cells
|
|
141
|
-
const firstPos = newCells[0][0].position;
|
|
142
|
-
const insertIndex = this.binarySearchPosition(firstPos);
|
|
143
|
-
this.state.splice(insertIndex, 0, ...newCells);
|
|
144
|
-
// Propagate remaining
|
|
145
|
-
if (msgs.length > 0) {
|
|
146
|
-
this.propagate(msgs);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Deletes value at given position
|
|
151
|
-
* @param position - Position to delete at
|
|
152
|
-
*/
|
|
153
|
-
deleteAtPosition(position) {
|
|
154
|
-
// Find the cell containing this position
|
|
155
|
-
for (let i = 0; i < this.state.length; ++i) {
|
|
156
|
-
const cell = this.state[i];
|
|
157
|
-
const node = cell.find((n) => this.totalOrder.compare(n.position, position) === 0);
|
|
158
|
-
if (node) {
|
|
159
|
-
// Tombstone the node, TODO: Implement garbage collection
|
|
160
|
-
node.value = undefined;
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Finds the position of the visible value at index
|
|
167
|
-
* this ignores tombstoned values
|
|
168
|
-
* @param index - Index of the visible value
|
|
169
|
-
*/
|
|
170
|
-
findVisiblePosition(index) {
|
|
171
|
-
let count = 0;
|
|
172
|
-
for (const cell of this.state) {
|
|
173
|
-
for (const n of cell) {
|
|
174
|
-
if (n.value !== undefined) {
|
|
175
|
-
if (count === index)
|
|
176
|
-
return n.position;
|
|
177
|
-
count++;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Finds the visible index of the value at position
|
|
184
|
-
* this ignores tombstoned values
|
|
185
|
-
* @param position - Position to find visible index for
|
|
186
|
-
* @returns
|
|
187
|
-
*/
|
|
188
|
-
findVisibleIndex(position) {
|
|
189
|
-
let count = 0;
|
|
190
|
-
for (const cell of this.state) {
|
|
191
|
-
for (const n of cell) {
|
|
192
|
-
if (n.value !== undefined) {
|
|
193
|
-
if (this.totalOrder.compare(n.position, position) === 0)
|
|
194
|
-
return count;
|
|
195
|
-
count++;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
return undefined;
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Delete value in the list at index
|
|
203
|
-
* @param index - Index of the value to delete
|
|
204
|
-
*/
|
|
205
|
-
delete(index) {
|
|
206
|
-
const position = this.findVisiblePosition(index);
|
|
207
|
-
if (!position) {
|
|
208
|
-
logger.warn(`No element at position -> ${position}`);
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
this.deleteAtPosition(position);
|
|
212
|
-
// Send to replicas
|
|
213
|
-
this.propagate({
|
|
214
|
-
documentID: this.documentID,
|
|
215
|
-
replicaId: this.totalOrder.getReplicaId(),
|
|
216
|
-
operation: Operation.DELETE,
|
|
217
|
-
position: position,
|
|
218
|
-
userIdentity: this.userIdentity,
|
|
219
|
-
data: null,
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
/**
|
|
223
|
-
* Deletes multiple values starting from index, this
|
|
224
|
-
* handles large deletions by batching messages
|
|
225
|
-
* @param index - Starting index to delete from
|
|
226
|
-
* @param count - Number of values to delete
|
|
227
|
-
*/
|
|
228
|
-
deleteMultiple(index, count) {
|
|
229
|
-
if (count <= 0)
|
|
230
|
-
return;
|
|
231
|
-
if (count === 1) {
|
|
232
|
-
this.delete(index);
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
let currentVisibleIndex = 0;
|
|
236
|
-
let deletedCount = 0;
|
|
237
|
-
let msgs = [];
|
|
238
|
-
outer: for (const c of this.state) {
|
|
239
|
-
for (const n of c) {
|
|
240
|
-
// Only consider visible nodes
|
|
241
|
-
if (n.value !== undefined) {
|
|
242
|
-
if (currentVisibleIndex >= index) {
|
|
243
|
-
const pos = n.position;
|
|
244
|
-
// Tombstone the node
|
|
245
|
-
n.value = undefined;
|
|
246
|
-
deletedCount++;
|
|
247
|
-
// Batch
|
|
248
|
-
msgs.push({
|
|
249
|
-
documentID: this.documentID,
|
|
250
|
-
replicaId: this.totalOrder.getReplicaId(),
|
|
251
|
-
operation: Operation.DELETE,
|
|
252
|
-
position: pos,
|
|
253
|
-
userIdentity: this.userIdentity,
|
|
254
|
-
data: null,
|
|
255
|
-
});
|
|
256
|
-
if (msgs.length >= this.batchSize) {
|
|
257
|
-
this.propagate(msgs);
|
|
258
|
-
msgs = [];
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
// Processed a visible node
|
|
262
|
-
currentVisibleIndex++;
|
|
263
|
-
// Check if we've deleted enough
|
|
264
|
-
if (deletedCount >= count) {
|
|
265
|
-
break outer;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
if (msgs.length > 0) {
|
|
271
|
-
this.propagate(msgs);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* Observes the current visible state of the list
|
|
276
|
-
* @returns The current visible state of the list as a string
|
|
277
|
-
*/
|
|
278
|
-
observe() {
|
|
279
|
-
let res = new String();
|
|
280
|
-
for (const idx of this.state) {
|
|
281
|
-
// Filter out tombstoned nodes and sort by unique position
|
|
282
|
-
const nodes = idx
|
|
283
|
-
.filter((n) => n.value !== undefined)
|
|
284
|
-
.sort((a, b) => this.totalOrder.compare(a.position, b.position));
|
|
285
|
-
// Then append to result jand if somehow
|
|
286
|
-
// a value is undefined append empty string
|
|
287
|
-
for (const n of nodes) {
|
|
288
|
-
res += n.value || "";
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
return res.toString();
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* Applies a single effect message to the list
|
|
295
|
-
* @param msg - Message to apply effect for
|
|
296
|
-
*/
|
|
297
|
-
singleEffect(msg) {
|
|
298
|
-
const { replicaId, operation, data, position } = msg;
|
|
299
|
-
if (replicaId === this.totalOrder.getReplicaId())
|
|
300
|
-
return;
|
|
301
|
-
switch (operation) {
|
|
302
|
-
case Operation.INSERT:
|
|
303
|
-
if (!data)
|
|
304
|
-
throw Error("Data is required for Operation.INSERT");
|
|
305
|
-
return this.insertAtPosition(position, data);
|
|
306
|
-
case Operation.DELETE:
|
|
307
|
-
return this.deleteAtPosition(position);
|
|
308
|
-
}
|
|
309
|
-
throw Error("Invalid operation");
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* Applies batched effect messages to the list
|
|
313
|
-
* @param msgs - Messages to apply effect for in batch
|
|
314
|
-
*/
|
|
315
|
-
batchEffect(msgs) {
|
|
316
|
-
const inserts = [];
|
|
317
|
-
const deletes = new Set();
|
|
318
|
-
// Separate operations
|
|
319
|
-
for (const msg of msgs) {
|
|
320
|
-
const { replicaId, operation, position, data } = msg;
|
|
321
|
-
if (replicaId === this.totalOrder.getReplicaId())
|
|
322
|
-
continue;
|
|
323
|
-
switch (operation) {
|
|
324
|
-
case Operation.INSERT:
|
|
325
|
-
if (!data)
|
|
326
|
-
continue;
|
|
327
|
-
inserts.push(msg);
|
|
328
|
-
break;
|
|
329
|
-
case Operation.DELETE:
|
|
330
|
-
deletes.add(JSON.stringify(position));
|
|
331
|
-
break;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
// Apply deletes first
|
|
335
|
-
if (deletes.size > 0) {
|
|
336
|
-
for (const posStr of deletes) {
|
|
337
|
-
// Parse the position back from the set
|
|
338
|
-
const pos = JSON.parse(posStr);
|
|
339
|
-
const idx = this.binarySearchPosition(pos);
|
|
340
|
-
// Check if we found the right cell
|
|
341
|
-
if (idx < this.state.length) {
|
|
342
|
-
const cell = this.state[idx];
|
|
343
|
-
// Find the specific node in the collision cell
|
|
344
|
-
const node = cell.find((n) => this.totalOrder.compare(n.position, pos) === 0);
|
|
345
|
-
if (node && node.value !== undefined) {
|
|
346
|
-
node.value = undefined; // Tombstone
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
// Then apply inserts
|
|
352
|
-
if (inserts.length > 0) {
|
|
353
|
-
inserts.sort((a, b) => this.totalOrder.compare(a.position, b.position));
|
|
354
|
-
// Group into chunks, of contiguous inserts
|
|
355
|
-
let batchCells = [];
|
|
356
|
-
let startIdx = -1;
|
|
357
|
-
for (const msg of inserts) {
|
|
358
|
-
const { position, data } = msg;
|
|
359
|
-
// Find the index to insert at
|
|
360
|
-
const idx = this.binarySearchPosition(position);
|
|
361
|
-
// Check for collision
|
|
362
|
-
//TODO: should trigger collision resolution
|
|
363
|
-
if (idx < this.state.length && this.totalOrder.compare(this.state[idx][0].position, position) === 0) {
|
|
364
|
-
const cell = this.state[idx];
|
|
365
|
-
const existing = cell.find((n) => this.totalOrder.compare(n.position, position) === 0);
|
|
366
|
-
// Don't insert if it already exists
|
|
367
|
-
if (!existing) {
|
|
368
|
-
cell.push(new FListNode(position, data ? data : undefined));
|
|
369
|
-
cell.sort((a, b) => this.totalOrder.compare(a.position, b.position));
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
else {
|
|
373
|
-
// Start a new batch if:
|
|
374
|
-
// - It's the first item
|
|
375
|
-
// - This index is not contiguous with the previous group
|
|
376
|
-
if (startIdx === -1) {
|
|
377
|
-
startIdx = idx;
|
|
378
|
-
batchCells = [[new FListNode(position, data ? data : undefined)]];
|
|
379
|
-
}
|
|
380
|
-
// If the index is the same as startIdx, continue the batch
|
|
381
|
-
else if (idx === startIdx) {
|
|
382
|
-
batchCells.push([new FListNode(position, data ? data : undefined)]);
|
|
383
|
-
}
|
|
384
|
-
// The index is different, i.e. not contiguous, so flush the current batch,
|
|
385
|
-
// commit it and start a new one
|
|
386
|
-
else {
|
|
387
|
-
// Commit batch
|
|
388
|
-
this.state.splice(startIdx, 0, ...batchCells);
|
|
389
|
-
// Start new batch
|
|
390
|
-
// Calculate the shift caused by the splice
|
|
391
|
-
// If the new idx (calculated on old state) is after the splice point,
|
|
392
|
-
// we must add the length of the batch we just inserted.
|
|
393
|
-
const shift = idx >= startIdx ? batchCells.length : 0;
|
|
394
|
-
startIdx = idx + shift;
|
|
395
|
-
batchCells = [[new FListNode(position, data ? data : undefined)]];
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
// Commit any remaining batch
|
|
400
|
-
if (batchCells.length > 0)
|
|
401
|
-
this.state.splice(startIdx, 0, ...batchCells);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
/**
|
|
405
|
-
* Applies effect messages to the list
|
|
406
|
-
* @param msg - Message or messages to apply effect for, can be batched
|
|
407
|
-
*/
|
|
408
|
-
effect(msg) {
|
|
409
|
-
if (Array.isArray(msg)) {
|
|
410
|
-
this.batchEffect(msg);
|
|
411
|
-
// for (const m of msg) {
|
|
412
|
-
// this.singleEffect(m);
|
|
413
|
-
// }
|
|
414
|
-
}
|
|
415
|
-
else {
|
|
416
|
-
this.singleEffect(msg);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
replicaId() {
|
|
420
|
-
return this.totalOrder.getReplicaId();
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* Performs garbage collection by removing tombstoned nodes from the state
|
|
424
|
-
*/
|
|
425
|
-
garbageCollect() {
|
|
426
|
-
this.state = this.state.filter((cell) => {
|
|
427
|
-
// Check if cell has any visible nodes
|
|
428
|
-
const hasVisible = cell.some((n) => n.value !== undefined);
|
|
429
|
-
return hasVisible;
|
|
430
|
-
});
|
|
431
|
-
}
|
|
432
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dts/Fugue/index.ts"],"names":[],"mappings":"AACA,cAAc,gBAAgB,CAAC"}
|
package/dist/dts/Fugue/index.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { FugueMessageType } from "../../../types/Fugue/index.js";
|
|
2
|
-
declare function serialize<P>(msgs: FugueMessageType<P>[]): Uint8Array<ArrayBuffer>;
|
|
3
|
-
declare function deserialize<P>(data: Uint8Array): FugueMessageType<P>[];
|
|
4
|
-
export declare const FugueMessageSerialzier: {
|
|
5
|
-
serialize: typeof serialize;
|
|
6
|
-
deserialize: typeof deserialize;
|
|
7
|
-
};
|
|
8
|
-
export {};
|
|
9
|
-
//# sourceMappingURL=Message.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../../../src/dts/Serailizers/Fugue/Message.ts"],"names":[],"mappings":"AACA,OAAO,EAGH,gBAAgB,EAInB,MAAM,+BAA+B,CAAC;AAEvC,iBAAS,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,2BAEhD;AAED,iBAAS,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,GAAG,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAM/D;AA6DD,eAAO,MAAM,sBAAsB;;;CAGlC,CAAC"}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { encode, decode } from "@msgpack/msgpack";
|
|
2
|
-
import { Operation, } from "../../../types/Fugue/index.js";
|
|
3
|
-
function serialize(msgs) {
|
|
4
|
-
return encode(msgs.map((m) => toTuple(m)));
|
|
5
|
-
}
|
|
6
|
-
function deserialize(data) {
|
|
7
|
-
const dec = decode(data);
|
|
8
|
-
if (Array.isArray(dec) && Array.isArray(dec[0])) {
|
|
9
|
-
return dec.map((t) => fromTuple(t));
|
|
10
|
-
}
|
|
11
|
-
return [fromTuple(dec)];
|
|
12
|
-
}
|
|
13
|
-
function toTuple(msg) {
|
|
14
|
-
// Check if msg is of FugueJoinMessage type
|
|
15
|
-
switch (msg.operation) {
|
|
16
|
-
case Operation.JOIN:
|
|
17
|
-
return [
|
|
18
|
-
msg.operation,
|
|
19
|
-
msg.documentID,
|
|
20
|
-
msg.state,
|
|
21
|
-
msg.userIdentity,
|
|
22
|
-
msg.collaborators,
|
|
23
|
-
msg.offlineChanges,
|
|
24
|
-
msg.replicaId,
|
|
25
|
-
];
|
|
26
|
-
case Operation.INSERT:
|
|
27
|
-
case Operation.DELETE:
|
|
28
|
-
return [msg.operation, msg.documentID, msg.replicaId, msg.position, msg.data, msg.userIdentity];
|
|
29
|
-
case Operation.REJECT:
|
|
30
|
-
return [msg.operation];
|
|
31
|
-
case Operation.LEAVE:
|
|
32
|
-
return [msg.operation, msg.userIdentity];
|
|
33
|
-
}
|
|
34
|
-
throw new Error("Unknown message type");
|
|
35
|
-
}
|
|
36
|
-
function fromTuple(tuple) {
|
|
37
|
-
switch (tuple[0]) {
|
|
38
|
-
case Operation.JOIN:
|
|
39
|
-
return {
|
|
40
|
-
operation: tuple[0],
|
|
41
|
-
documentID: tuple[1],
|
|
42
|
-
state: tuple[2],
|
|
43
|
-
userIdentity: tuple[3],
|
|
44
|
-
collaborators: tuple[4],
|
|
45
|
-
offlineChanges: tuple[5],
|
|
46
|
-
replicaId: tuple[6],
|
|
47
|
-
};
|
|
48
|
-
case Operation.INSERT:
|
|
49
|
-
case Operation.DELETE:
|
|
50
|
-
return {
|
|
51
|
-
operation: tuple[0],
|
|
52
|
-
documentID: tuple[1],
|
|
53
|
-
replicaId: tuple[2],
|
|
54
|
-
position: tuple[3],
|
|
55
|
-
data: tuple[4],
|
|
56
|
-
userIdentity: tuple[5],
|
|
57
|
-
};
|
|
58
|
-
case Operation.REJECT:
|
|
59
|
-
return {
|
|
60
|
-
operation: tuple[0],
|
|
61
|
-
};
|
|
62
|
-
case Operation.LEAVE:
|
|
63
|
-
return {
|
|
64
|
-
operation: tuple[0],
|
|
65
|
-
userIdentity: tuple[1],
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
throw new Error("Unknown tuple format");
|
|
69
|
-
}
|
|
70
|
-
export const FugueMessageSerialzier = {
|
|
71
|
-
serialize,
|
|
72
|
-
deserialize,
|
|
73
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { FugueState } from "../../../types/Fugue/index.js";
|
|
2
|
-
declare function serialize(state: FugueState<string>): Uint8Array<ArrayBufferLike>;
|
|
3
|
-
declare function deserialize(compressed: Uint8Array<ArrayBufferLike>): FugueState<string>;
|
|
4
|
-
export declare const FugueStateSerializer: {
|
|
5
|
-
serialize: typeof serialize;
|
|
6
|
-
deserialize: typeof deserialize;
|
|
7
|
-
};
|
|
8
|
-
export {};
|
|
9
|
-
//# sourceMappingURL=State.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"State.d.ts","sourceRoot":"","sources":["../../../../src/dts/Serailizers/Fugue/State.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,iBAAS,SAAS,CAAC,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,eAAe,CAAC,CAKzE;AAED,iBAAS,WAAW,CAAC,UAAU,EAAE,UAAU,CAAC,eAAe,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,CAIhF;AAED,eAAO,MAAM,oBAAoB;;;CAGhC,CAAC"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { encode, decode } from "@msgpack/msgpack";
|
|
2
|
-
function serialize(state) {
|
|
3
|
-
// const flat = state.flatMap((c) => c.map((n) => [n.position, n.value]));
|
|
4
|
-
const bin = encode(state);
|
|
5
|
-
// const com = compress(bin);
|
|
6
|
-
return bin;
|
|
7
|
-
}
|
|
8
|
-
function deserialize(compressed) {
|
|
9
|
-
// const raw = decompress(compressed);
|
|
10
|
-
const state = decode(compressed);
|
|
11
|
-
return state;
|
|
12
|
-
}
|
|
13
|
-
export const FugueStateSerializer = {
|
|
14
|
-
serialize,
|
|
15
|
-
deserialize,
|
|
16
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/dts/Serailizers/Fugue/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { UniquelyDenseTotalOrder } from "./UniquelyDenseTotalOrder.js";
|
|
2
|
-
export type StringPosition = string;
|
|
3
|
-
export declare class StringTotalOrder implements UniquelyDenseTotalOrder<StringPosition> {
|
|
4
|
-
readonly replicaID: string;
|
|
5
|
-
private counter;
|
|
6
|
-
getReplicaId(): string;
|
|
7
|
-
compare(a: StringPosition, b: StringPosition): number;
|
|
8
|
-
constructor(replicaID: string);
|
|
9
|
-
createBetween(a?: StringPosition, b?: StringPosition): string;
|
|
10
|
-
}
|
|
11
|
-
//# sourceMappingURL=StringTotalOrder.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"StringTotalOrder.d.ts","sourceRoot":"","sources":["../../../src/dts/TotalOrder/StringTotalOrder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC,qBAAa,gBAAiB,YAAW,uBAAuB,CAAC,cAAc,CAAC;IAC5E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,OAAO,CAAK;IAEpB,YAAY,IAAI,MAAM;IAItB,OAAO,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,cAAc,GAAG,MAAM;gBAIzC,SAAS,EAAE,MAAM;IAI7B,aAAa,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM;CA6BhE"}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
export class StringTotalOrder {
|
|
2
|
-
getReplicaId() {
|
|
3
|
-
return this.replicaID;
|
|
4
|
-
}
|
|
5
|
-
compare(a, b) {
|
|
6
|
-
return a.localeCompare(b);
|
|
7
|
-
}
|
|
8
|
-
constructor(replicaID) {
|
|
9
|
-
this.counter = 0;
|
|
10
|
-
this.replicaID = replicaID;
|
|
11
|
-
}
|
|
12
|
-
createBetween(a, b) {
|
|
13
|
-
// Create a wholly unique string using a causal dot, i.e. (replicaID, counter)
|
|
14
|
-
const uniqueStr = `${this.replicaID}${this.counter++}`;
|
|
15
|
-
// If node is the first ever position in the document
|
|
16
|
-
if (!a && !b) {
|
|
17
|
-
return uniqueStr + "R";
|
|
18
|
-
}
|
|
19
|
-
// If node is the first position at that index
|
|
20
|
-
if (!a) {
|
|
21
|
-
return b.slice(0, -1) + "L" + uniqueStr + "R";
|
|
22
|
-
}
|
|
23
|
-
// If node is the last position at that index
|
|
24
|
-
if (!b) {
|
|
25
|
-
return a + uniqueStr + "R";
|
|
26
|
-
}
|
|
27
|
-
const isAPrefixOfB = b.startsWith(a);
|
|
28
|
-
// If a is not a prefix of b append a globally unique new string to a and return that +R
|
|
29
|
-
if (!isAPrefixOfB) {
|
|
30
|
-
return a + uniqueStr + "R";
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
// If a is a prefix of b replace the R at the end of b with L.
|
|
34
|
-
// Then append a globally unique string to it and return it +R.
|
|
35
|
-
return b.slice(0, -1) + "L" + uniqueStr + "R";
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Helper interface for sorting and creating unique immutable positions,
|
|
3
|
-
* suitable for use in a List CRDT. Taken from mattweidner.com/2022/10/21/basic-list-crdt.html
|
|
4
|
-
*
|
|
5
|
-
* @type P The type of positions. Treated as immutable.
|
|
6
|
-
*/
|
|
7
|
-
export interface UniquelyDenseTotalOrder<P> {
|
|
8
|
-
getReplicaId(): string;
|
|
9
|
-
/**
|
|
10
|
-
* Usual compare function for sorts: returns negative if a < b in
|
|
11
|
-
* their sort order, positive if a > b.
|
|
12
|
-
*/
|
|
13
|
-
compare(a: P, b: P): number;
|
|
14
|
-
/**
|
|
15
|
-
* Returns a globally unique new position c such that a < c < b.
|
|
16
|
-
*
|
|
17
|
-
* "Globally unique" means that the created position must be distinct
|
|
18
|
-
* from all other created positions, including ones created concurrently
|
|
19
|
-
* by other users.
|
|
20
|
-
*
|
|
21
|
-
* When a is undefined, it is treated as the start of the list, i.e.,
|
|
22
|
-
* this returns c such that c < b. Likewise, undefined b is treated
|
|
23
|
-
* as the end of the list.
|
|
24
|
-
*/
|
|
25
|
-
createBetween(a?: P, b?: P): P;
|
|
26
|
-
}
|
|
27
|
-
//# sourceMappingURL=UniquelyDenseTotalOrder.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"UniquelyDenseTotalOrder.d.ts","sourceRoot":"","sources":["../../../src/dts/TotalOrder/UniquelyDenseTotalOrder.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB,CAAC,CAAC;IACtC,YAAY,IAAI,MAAM,CAAC;IAEvB;;;OAGG;IACH,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC;IAE5B;;;;;;;;;;OAUG;IACH,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CAClC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dts/TotalOrder/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Fugue.d.ts","sourceRoot":"","sources":["../../../src/types/Fugue/Fugue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { FugueState } from "./Fugue.js";
|
|
2
|
-
export declare enum Operation {
|
|
3
|
-
INSERT = 0,
|
|
4
|
-
DELETE = 1,
|
|
5
|
-
JOIN = 2,
|
|
6
|
-
REJECT = 3,
|
|
7
|
-
LEAVE = 4
|
|
8
|
-
}
|
|
9
|
-
export type Data = string;
|
|
10
|
-
export interface FugueMessage<P> {
|
|
11
|
-
operation: Operation.INSERT | Operation.DELETE;
|
|
12
|
-
documentID: string;
|
|
13
|
-
replicaId: string;
|
|
14
|
-
position: P;
|
|
15
|
-
data: Data | null;
|
|
16
|
-
userIdentity?: string;
|
|
17
|
-
}
|
|
18
|
-
export interface FugueJoinMessage<P> {
|
|
19
|
-
operation: Operation.JOIN;
|
|
20
|
-
documentID: string;
|
|
21
|
-
state: FugueState<P> | null;
|
|
22
|
-
userIdentity?: string;
|
|
23
|
-
collaborators?: string[];
|
|
24
|
-
offlineChanges?: FugueState<P> | null;
|
|
25
|
-
replicaId?: string;
|
|
26
|
-
}
|
|
27
|
-
export interface FugueRejectMessage {
|
|
28
|
-
operation: Operation.REJECT;
|
|
29
|
-
}
|
|
30
|
-
export interface FugueLeaveMessage {
|
|
31
|
-
operation: Operation.LEAVE;
|
|
32
|
-
userIdentity: string;
|
|
33
|
-
}
|
|
34
|
-
export type FugueMessageType<P> = FugueMessage<P> | FugueJoinMessage<P> | FugueRejectMessage | FugueLeaveMessage;
|
|
35
|
-
export type FugueMutationMessageTypes<P> = Extract<FugueMessageType<P>, FugueMessage<P> | FugueJoinMessage<P>>;
|
|
36
|
-
//# sourceMappingURL=Message.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../../src/types/Fugue/Message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,oBAAY,SAAS;IACjB,MAAM,IAAA;IACN,MAAM,IAAA;IACN,IAAI,IAAA;IACJ,MAAM,IAAA;IACN,KAAK,IAAA;CACR;AAED,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC;AAE1B,MAAM,WAAW,YAAY,CAAC,CAAC;IAC3B,SAAS,EAAE,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,CAAC,CAAC;IACZ,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC;IAC/B,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IAC/B,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAE,SAAS,CAAC,KAAK,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,kBAAkB,GAAG,iBAAiB,CAAC;AAEjH,MAAM,MAAM,yBAAyB,CAAC,CAAC,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export var Operation;
|
|
2
|
-
(function (Operation) {
|
|
3
|
-
Operation[Operation["INSERT"] = 0] = "INSERT";
|
|
4
|
-
Operation[Operation["DELETE"] = 1] = "DELETE";
|
|
5
|
-
Operation[Operation["JOIN"] = 2] = "JOIN";
|
|
6
|
-
Operation[Operation["REJECT"] = 3] = "REJECT";
|
|
7
|
-
Operation[Operation["LEAVE"] = 4] = "LEAVE";
|
|
8
|
-
})(Operation || (Operation = {}));
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/Fugue/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
|