tool-db 2.5.3 → 2.5.5

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.
Files changed (183) hide show
  1. package/README.md +82 -82
  2. package/bundle.js +1 -1
  3. package/dist/adapters-base/networkAdapter.d.ts +58 -58
  4. package/dist/adapters-base/networkAdapter.js +215 -215
  5. package/dist/adapters-base/storageAdapter.d.ts +11 -11
  6. package/dist/adapters-base/storageAdapter.js +35 -35
  7. package/dist/adapters-base/userAdapter.d.ts +15 -15
  8. package/dist/adapters-base/userAdapter.js +41 -41
  9. package/dist/crdt/baseCrdt.d.ts +9 -9
  10. package/dist/crdt/baseCrdt.js +26 -26
  11. package/dist/crdt/counterCrdt.d.ts +30 -30
  12. package/dist/crdt/counterCrdt.js +105 -105
  13. package/dist/crdt/listCrdt.d.ts +42 -42
  14. package/dist/crdt/listCrdt.js +158 -158
  15. package/dist/crdt/mapCrdt.d.ts +32 -32
  16. package/dist/crdt/mapCrdt.js +117 -117
  17. package/dist/index.d.ts +35 -34
  18. package/dist/index.js +84 -82
  19. package/dist/index.js.map +1 -1
  20. package/dist/logger.d.ts +2 -2
  21. package/dist/logger.js +28 -28
  22. package/dist/messageHandlers/handleCrdtGet.d.ts +2 -2
  23. package/dist/messageHandlers/handleCrdtGet.js +49 -28
  24. package/dist/messageHandlers/handleCrdtGet.js.map +1 -1
  25. package/dist/messageHandlers/handleCrdtPut.d.ts +2 -2
  26. package/dist/messageHandlers/handleCrdtPut.js +102 -92
  27. package/dist/messageHandlers/handleCrdtPut.js.map +1 -1
  28. package/dist/messageHandlers/handleFunction.d.ts +2 -0
  29. package/dist/messageHandlers/handleFunction.js +56 -0
  30. package/dist/messageHandlers/handleFunction.js.map +1 -0
  31. package/dist/messageHandlers/handleGet.d.ts +2 -2
  32. package/dist/messageHandlers/handleGet.js +49 -28
  33. package/dist/messageHandlers/handleGet.js.map +1 -1
  34. package/dist/messageHandlers/handlePing.d.ts +2 -2
  35. package/dist/messageHandlers/handlePing.js +35 -35
  36. package/dist/messageHandlers/handlePing.js.map +1 -1
  37. package/dist/messageHandlers/handlePong.d.ts +2 -2
  38. package/dist/messageHandlers/handlePong.js +25 -25
  39. package/dist/messageHandlers/handlePut.d.ts +2 -2
  40. package/dist/messageHandlers/handlePut.js +77 -56
  41. package/dist/messageHandlers/handlePut.js.map +1 -1
  42. package/dist/messageHandlers/handleQuery.d.ts +2 -2
  43. package/dist/messageHandlers/handleQuery.js +43 -22
  44. package/dist/messageHandlers/handleQuery.js.map +1 -1
  45. package/dist/messageHandlers/handleSubscribe.d.ts +2 -2
  46. package/dist/messageHandlers/handleSubscribe.js +43 -43
  47. package/dist/server.d.ts +1 -1
  48. package/dist/server.js +8 -8
  49. package/dist/shared.d.ts +2 -2
  50. package/dist/shared.js +6 -6
  51. package/dist/toolDbAnonSignIn.d.ts +2 -2
  52. package/dist/toolDbAnonSignIn.js +6 -6
  53. package/dist/toolDbClientOnMessage.d.ts +2 -2
  54. package/dist/toolDbClientOnMessage.js +61 -58
  55. package/dist/toolDbClientOnMessage.js.map +1 -1
  56. package/dist/toolDbCrdtGet.d.ts +9 -9
  57. package/dist/toolDbCrdtGet.js +76 -76
  58. package/dist/toolDbCrdtGet.js.map +1 -1
  59. package/dist/toolDbCrdtPut.d.ts +9 -9
  60. package/dist/toolDbCrdtPut.js +62 -62
  61. package/dist/toolDbCrdtPut.js.map +1 -1
  62. package/dist/toolDbFunction.d.ts +9 -0
  63. package/dist/toolDbFunction.js +38 -0
  64. package/dist/toolDbFunction.js.map +1 -0
  65. package/dist/toolDbGet.d.ts +9 -9
  66. package/dist/toolDbGet.js +76 -76
  67. package/dist/toolDbGet.js.map +1 -1
  68. package/dist/toolDbKeysSignIn.d.ts +2 -2
  69. package/dist/toolDbKeysSignIn.js +15 -15
  70. package/dist/toolDbPut.d.ts +9 -9
  71. package/dist/toolDbPut.js +68 -68
  72. package/dist/toolDbPut.js.map +1 -1
  73. package/dist/toolDbQueryKeys.d.ts +8 -8
  74. package/dist/toolDbQueryKeys.js +65 -65
  75. package/dist/toolDbQueryKeys.js.map +1 -1
  76. package/dist/toolDbSignIn.d.ts +2 -2
  77. package/dist/toolDbSignIn.js +26 -26
  78. package/dist/toolDbSignIn.js.map +1 -1
  79. package/dist/toolDbSignUp.d.ts +2 -2
  80. package/dist/toolDbSignUp.js +100 -100
  81. package/dist/toolDbSignUp.js.map +1 -1
  82. package/dist/toolDbSubscribe.d.ts +9 -9
  83. package/dist/toolDbSubscribe.js +49 -49
  84. package/dist/toolDbSubscribe.js.map +1 -1
  85. package/dist/toolDbVerificationWrapper.d.ts +2 -2
  86. package/dist/toolDbVerificationWrapper.js +97 -97
  87. package/dist/tooldb.d.ts +123 -108
  88. package/dist/tooldb.js +309 -285
  89. package/dist/tooldb.js.map +1 -1
  90. package/dist/types/message.d.ts +110 -100
  91. package/dist/types/message.js +16 -16
  92. package/dist/types/message.js.map +1 -1
  93. package/dist/types/tooldb.d.ts +110 -84
  94. package/dist/types/tooldb.js +2 -2
  95. package/dist/utils/catchReturn.d.ts +1 -1
  96. package/dist/utils/catchReturn.js +7 -7
  97. package/dist/utils/encoding/arrayBufferToHex.d.ts +1 -1
  98. package/dist/utils/encoding/arrayBufferToHex.js +18 -18
  99. package/dist/utils/encoding/arrayBufferToString.d.ts +1 -1
  100. package/dist/utils/encoding/arrayBufferToString.js +11 -11
  101. package/dist/utils/encoding/hexToArrayBuffer.d.ts +1 -1
  102. package/dist/utils/encoding/hexToArrayBuffer.js +14 -14
  103. package/dist/utils/encoding/hexToString.d.ts +1 -1
  104. package/dist/utils/encoding/hexToString.js +11 -11
  105. package/dist/utils/encoding/hexToUint8.d.ts +1 -1
  106. package/dist/utils/encoding/hexToUint8.js +7 -7
  107. package/dist/utils/encoding/stringToArrayBuffer.d.ts +1 -1
  108. package/dist/utils/encoding/stringToArrayBuffer.js +11 -11
  109. package/dist/utils/getPeerSignature.d.ts +2 -2
  110. package/dist/utils/getPeerSignature.js +8 -8
  111. package/dist/utils/getTimestamp.d.ts +1 -1
  112. package/dist/utils/getTimestamp.js +6 -6
  113. package/dist/utils/proofOfWork.d.ts +4 -4
  114. package/dist/utils/proofOfWork.js +15 -15
  115. package/dist/utils/randomAnimal.d.ts +1 -1
  116. package/dist/utils/randomAnimal.js +76 -76
  117. package/dist/utils/sha1.d.ts +1 -1
  118. package/dist/utils/sha1.js +12 -12
  119. package/dist/utils/sha256.d.ts +3 -3
  120. package/dist/utils/sha256.js +12 -12
  121. package/dist/utils/textRandom.d.ts +1 -1
  122. package/dist/utils/textRandom.js +14 -14
  123. package/dist/utils/uniq.d.ts +1 -1
  124. package/dist/utils/uniq.js +6 -6
  125. package/dist/utils/verifyMessage.d.ts +8 -8
  126. package/dist/utils/verifyMessage.js +128 -128
  127. package/dist/utils/verifyPeer.d.ts +2 -2
  128. package/dist/utils/verifyPeer.js +14 -14
  129. package/lib/adapters-base/networkAdapter.ts +217 -217
  130. package/lib/adapters-base/storageAdapter.ts +35 -35
  131. package/lib/adapters-base/userAdapter.ts +49 -49
  132. package/lib/crdt/baseCrdt.ts +21 -21
  133. package/lib/crdt/counterCrdt.ts +111 -111
  134. package/lib/crdt/listCrdt.ts +190 -190
  135. package/lib/crdt/mapCrdt.ts +119 -119
  136. package/lib/index.ts +43 -42
  137. package/lib/logger.ts +30 -30
  138. package/lib/messageHandlers/handleCrdtGet.ts +34 -29
  139. package/lib/messageHandlers/handleCrdtPut.ts +123 -118
  140. package/lib/messageHandlers/handleFunction.ts +59 -0
  141. package/lib/messageHandlers/handleGet.ts +34 -29
  142. package/lib/messageHandlers/handlePing.ts +40 -40
  143. package/lib/messageHandlers/handlePong.ts +30 -30
  144. package/lib/messageHandlers/handlePut.ts +59 -54
  145. package/lib/messageHandlers/handleQuery.ts +30 -25
  146. package/lib/messageHandlers/handleSubscribe.ts +46 -46
  147. package/lib/server.ts +7 -7
  148. package/lib/shared.ts +5 -5
  149. package/lib/toolDbAnonSignIn.ts +5 -5
  150. package/lib/toolDbClientOnMessage.ts +79 -75
  151. package/lib/toolDbCrdtGet.ts +83 -82
  152. package/lib/toolDbCrdtPut.ts +78 -77
  153. package/lib/toolDbFunction.ts +49 -0
  154. package/lib/toolDbGet.ts +81 -80
  155. package/lib/toolDbKeysSignIn.ts +16 -16
  156. package/lib/toolDbPut.ts +84 -83
  157. package/lib/toolDbQueryKeys.ts +65 -64
  158. package/lib/toolDbSignIn.ts +32 -31
  159. package/lib/toolDbSignUp.ts +72 -71
  160. package/lib/toolDbSubscribe.ts +54 -53
  161. package/lib/toolDbVerificationWrapper.ts +55 -55
  162. package/lib/tooldb.ts +343 -316
  163. package/lib/types/message.ts +154 -133
  164. package/lib/types/tooldb.ts +139 -97
  165. package/lib/utils/catchReturn.ts +4 -4
  166. package/lib/utils/encoding/arrayBufferToHex.ts +18 -18
  167. package/lib/utils/encoding/arrayBufferToString.ts +8 -8
  168. package/lib/utils/encoding/hexToArrayBuffer.ts +13 -13
  169. package/lib/utils/encoding/hexToString.ts +8 -8
  170. package/lib/utils/encoding/hexToUint8.ts +5 -5
  171. package/lib/utils/encoding/stringToArrayBuffer.ts +8 -8
  172. package/lib/utils/getPeerSignature.ts +12 -12
  173. package/lib/utils/getTimestamp.ts +3 -3
  174. package/lib/utils/proofOfWork.ts +16 -16
  175. package/lib/utils/randomAnimal.ts +77 -77
  176. package/lib/utils/sha1.ts +7 -7
  177. package/lib/utils/sha256.ts +7 -7
  178. package/lib/utils/textRandom.ts +11 -11
  179. package/lib/utils/uniq.ts +3 -3
  180. package/lib/utils/verifyMessage.ts +88 -88
  181. package/lib/utils/verifyPeer.ts +15 -15
  182. package/package.json +2 -2
  183. package/tsconfig.json +14 -14
@@ -1,21 +1,21 @@
1
- export const CRDT_MAP = "MAP";
2
-
3
- export const CRDT_LIST = "LIST";
4
-
5
- export const CRDT_COUNTER = "COUNTER";
6
-
7
- export class BaseCrdt<T = any, Changes = any, Value = any> {
8
- public type: string = "";
9
-
10
- public mergeChanges(changes: Changes[]) {
11
- //
12
- }
13
-
14
- public getChanges(): Changes[] {
15
- return [];
16
- }
17
-
18
- get value(): Value {
19
- return "" as any;
20
- }
21
- }
1
+ export const CRDT_MAP = "MAP";
2
+
3
+ export const CRDT_LIST = "LIST";
4
+
5
+ export const CRDT_COUNTER = "COUNTER";
6
+
7
+ export class BaseCrdt<T = any, Changes = any, Value = any> {
8
+ public type: string = "";
9
+
10
+ public mergeChanges(changes: Changes[]) {
11
+ //
12
+ }
13
+
14
+ public getChanges(): Changes[] {
15
+ return [];
16
+ }
17
+
18
+ get value(): Value {
19
+ return "" as any;
20
+ }
21
+ }
@@ -1,111 +1,111 @@
1
- import { BaseCrdt, CRDT_LIST } from "..";
2
-
3
- export type CounterOperations = "ADD" | "SUB";
4
-
5
- export interface ChangeCounterBase {
6
- t: CounterOperations; // Operation type
7
- v: number; // Value
8
- a: string;
9
- i: number;
10
- }
11
-
12
- export interface AddCounterChange extends ChangeCounterBase {
13
- t: "ADD";
14
- }
15
-
16
- export interface SubCounterChange extends ChangeCounterBase {
17
- t: "SUB";
18
- }
19
-
20
- export type CounterChanges = AddCounterChange | SubCounterChange;
21
-
22
- export class CounterCrdt<T> extends BaseCrdt<number, CounterChanges, number> {
23
- public type = CRDT_LIST;
24
-
25
- public _changes: CounterChanges[] = [];
26
-
27
- private _author = "";
28
-
29
- private _value: number = 0;
30
-
31
- private _lastUpdateSize: number = 0;
32
-
33
- constructor(author: string, changes?: CounterChanges[]) {
34
- super();
35
- this._author = author;
36
- if (changes) {
37
- this.mergeChanges(changes);
38
- }
39
-
40
- this.calculate();
41
- }
42
-
43
- changesSort(a: CounterChanges, b: CounterChanges) {
44
- if (a.i > b.i) return 1;
45
- if (a.i < b.i) return -1;
46
- return 0; // Should never be equal!
47
- }
48
-
49
- calculate() {
50
- let temp: number = 0;
51
- // Only update if we have new changes
52
- if (Object.values(this._changes).length !== this._lastUpdateSize) {
53
- this._changes.sort(this.changesSort).forEach((change) => {
54
- if (change.t === "ADD") {
55
- temp += change.v;
56
- } else if (change.t === "SUB") {
57
- temp -= change.v;
58
- }
59
- });
60
-
61
- this._value = temp;
62
- }
63
- }
64
-
65
- get value(): number {
66
- this.calculate();
67
- return this._value;
68
- }
69
-
70
- public mergeChanges(newChanges: CounterChanges[]) {
71
- newChanges.forEach((change) => {
72
- // Filter by author and index
73
- const filtered = this._changes.filter(
74
- (c) => c.i === change.i && c.a === change.a && c.t === change.t
75
- );
76
- // Only add if there are not matches
77
- if (filtered.length === 0) {
78
- this._changes.push(change);
79
- }
80
- });
81
- this.calculate();
82
- }
83
-
84
- public getChanges(): CounterChanges[] {
85
- return this._changes;
86
- }
87
-
88
- public ADD(value: number) {
89
- const ourChanges = this._changes.filter((c) => c.a === this._author);
90
-
91
- this._changes.push({
92
- t: "ADD",
93
- v: value,
94
- a: this._author,
95
- i: ourChanges.length,
96
- });
97
- this.calculate();
98
- }
99
-
100
- public SUB(value: number) {
101
- const ourChanges = this._changes.filter((c) => c.a === this._author);
102
-
103
- this._changes.push({
104
- t: "SUB",
105
- v: value,
106
- a: this._author,
107
- i: ourChanges.length,
108
- });
109
- this.calculate();
110
- }
111
- }
1
+ import { BaseCrdt, CRDT_LIST } from "..";
2
+
3
+ export type CounterOperations = "ADD" | "SUB";
4
+
5
+ export interface ChangeCounterBase {
6
+ t: CounterOperations; // Operation type
7
+ v: number; // Value
8
+ a: string;
9
+ i: number;
10
+ }
11
+
12
+ export interface AddCounterChange extends ChangeCounterBase {
13
+ t: "ADD";
14
+ }
15
+
16
+ export interface SubCounterChange extends ChangeCounterBase {
17
+ t: "SUB";
18
+ }
19
+
20
+ export type CounterChanges = AddCounterChange | SubCounterChange;
21
+
22
+ export class CounterCrdt<T> extends BaseCrdt<number, CounterChanges, number> {
23
+ public type = CRDT_LIST;
24
+
25
+ public _changes: CounterChanges[] = [];
26
+
27
+ private _author = "";
28
+
29
+ private _value: number = 0;
30
+
31
+ private _lastUpdateSize: number = 0;
32
+
33
+ constructor(author: string, changes?: CounterChanges[]) {
34
+ super();
35
+ this._author = author;
36
+ if (changes) {
37
+ this.mergeChanges(changes);
38
+ }
39
+
40
+ this.calculate();
41
+ }
42
+
43
+ changesSort(a: CounterChanges, b: CounterChanges) {
44
+ if (a.i > b.i) return 1;
45
+ if (a.i < b.i) return -1;
46
+ return 0; // Should never be equal!
47
+ }
48
+
49
+ calculate() {
50
+ let temp: number = 0;
51
+ // Only update if we have new changes
52
+ if (Object.values(this._changes).length !== this._lastUpdateSize) {
53
+ this._changes.sort(this.changesSort).forEach((change) => {
54
+ if (change.t === "ADD") {
55
+ temp += change.v;
56
+ } else if (change.t === "SUB") {
57
+ temp -= change.v;
58
+ }
59
+ });
60
+
61
+ this._value = temp;
62
+ }
63
+ }
64
+
65
+ get value(): number {
66
+ this.calculate();
67
+ return this._value;
68
+ }
69
+
70
+ public mergeChanges(newChanges: CounterChanges[]) {
71
+ newChanges.forEach((change) => {
72
+ // Filter by author and index
73
+ const filtered = this._changes.filter(
74
+ (c) => c.i === change.i && c.a === change.a && c.t === change.t
75
+ );
76
+ // Only add if there are not matches
77
+ if (filtered.length === 0) {
78
+ this._changes.push(change);
79
+ }
80
+ });
81
+ this.calculate();
82
+ }
83
+
84
+ public getChanges(): CounterChanges[] {
85
+ return this._changes;
86
+ }
87
+
88
+ public ADD(value: number) {
89
+ const ourChanges = this._changes.filter((c) => c.a === this._author);
90
+
91
+ this._changes.push({
92
+ t: "ADD",
93
+ v: value,
94
+ a: this._author,
95
+ i: ourChanges.length,
96
+ });
97
+ this.calculate();
98
+ }
99
+
100
+ public SUB(value: number) {
101
+ const ourChanges = this._changes.filter((c) => c.a === this._author);
102
+
103
+ this._changes.push({
104
+ t: "SUB",
105
+ v: value,
106
+ a: this._author,
107
+ i: ourChanges.length,
108
+ });
109
+ this.calculate();
110
+ }
111
+ }
@@ -1,190 +1,190 @@
1
- import { BaseCrdt, CRDT_LIST } from "..";
2
-
3
- export type ListOperations = "INS" | "DEL";
4
-
5
- export interface ChangeListBase<T> {
6
- t: ListOperations; // Operation type
7
- i: string; // "index", author + n
8
- }
9
-
10
- export interface InsListChange<T> extends ChangeListBase<T> {
11
- t: "INS";
12
- v: T; // Value
13
- p: string | undefined; // Previous index, if any
14
- n: string | undefined; // Next index, if any
15
- }
16
-
17
- export interface DelListChange<T> extends ChangeListBase<T> {
18
- t: "DEL";
19
- v: string; // target index to tombstone
20
- }
21
-
22
- export type ListChanges<T> = InsListChange<T> | DelListChange<T>;
23
-
24
- interface ListTempCursor<T> {
25
- value: T;
26
- index: string;
27
- tomb: boolean;
28
- prev: string | undefined;
29
- next: string | undefined;
30
- }
31
-
32
- export class ListCrdt<T> extends BaseCrdt<T, ListChanges<T>, T[]> {
33
- public type = CRDT_LIST;
34
-
35
- public _changes: ListChanges<T>[] = [];
36
-
37
- private _author = "";
38
-
39
- private _value: T[] = [];
40
-
41
- public _tempValues: ListTempCursor<T>[] = [];
42
-
43
- private _lastUpdateSize: number = 0;
44
-
45
- constructor(author: string, changes?: ListChanges<T>[]) {
46
- super();
47
- this._author = author;
48
- if (changes) {
49
- this.mergeChanges(changes);
50
- }
51
-
52
- this.calculate();
53
- }
54
-
55
- changesSort(a: ListChanges<T>, b: ListChanges<T>) {
56
- if (a.i > b.i) return 1;
57
- if (a.i < b.i) return -1;
58
- return 0; // Should never be equal!
59
- }
60
-
61
- calculate() {
62
- const temp: ListTempCursor<T>[] = [];
63
- // Only update if we have new changes
64
- if (Object.values(this._changes).length !== this._lastUpdateSize) {
65
- this._changes.sort(this.changesSort).forEach((change) => {
66
- if (change.t === "INS") {
67
- let poisitionToInsert = 0;
68
- if (change.p) {
69
- poisitionToInsert = temp.findIndex((v) => v.index === change.p) + 1;
70
- } else if (change.n) {
71
- poisitionToInsert = temp.findIndex((v) => v.index === change.n);
72
- }
73
-
74
- const cursorValue: ListTempCursor<T> = {
75
- value: change.v,
76
- index: change.i,
77
- tomb: false,
78
- prev: change.p,
79
- next: change.n,
80
- };
81
-
82
- temp.splice(poisitionToInsert, 0, cursorValue);
83
- } else if (change.t === "DEL") {
84
- const poisitionToInsert = temp.findIndex((v) => v.index === change.v);
85
- temp[poisitionToInsert].tomb = true;
86
- }
87
- });
88
- this._lastUpdateSize = Object.values(temp).length;
89
-
90
- this._tempValues = temp;
91
-
92
- this._value = temp.filter((v) => !v.tomb).map((v) => v.value);
93
- }
94
- }
95
-
96
- get value(): T[] {
97
- this.calculate();
98
- return this._value;
99
- }
100
-
101
- public mergeChanges(newChanges: ListChanges<T>[]) {
102
- newChanges.forEach((change) => {
103
- // Filter by author and index
104
- const filtered = this._changes.filter(
105
- (c) => c.i === change.i && c.t === change.t && c.v === change.v
106
- );
107
- // Only add if there are not matches
108
- if (filtered.length === 0) {
109
- this._changes.push(change);
110
- }
111
- });
112
- this.calculate();
113
- }
114
-
115
- public getChanges(): ListChanges<T>[] {
116
- return this._changes;
117
- }
118
-
119
- public INS(value: T, index: number) {
120
- const filterTombs = this._tempValues.filter((v) => !v.tomb);
121
-
122
- let currentPrev = undefined;
123
- let currentNext = undefined;
124
-
125
- if (filterTombs.length !== 0) {
126
- const currentIndex = filterTombs[index].index;
127
- const currentIndexPosition = this._tempValues.findIndex(
128
- (v) => v.index === currentIndex
129
- );
130
- currentPrev = this._tempValues[currentIndexPosition - 1];
131
- currentNext = this._tempValues[currentIndexPosition];
132
- }
133
-
134
- const ourChanges = this._changes.filter((c) =>
135
- c.i.startsWith(this._author)
136
- );
137
-
138
- this._changes.push({
139
- t: "INS",
140
- p: currentPrev?.index,
141
- n: currentNext?.index,
142
- v: value,
143
- i: this._author + "-" + `${ourChanges.length}`.padStart(8, "0"),
144
- });
145
- this.calculate();
146
- }
147
-
148
- public PUSH(value: T) {
149
- const filterTombs = this._tempValues.filter((v) => !v.tomb);
150
- const currentIndex = filterTombs[filterTombs.length - 1]?.index;
151
- const currentIndexPosition = this._tempValues.findIndex(
152
- (v) => v.index === currentIndex
153
- );
154
-
155
- const currentPrev = this._tempValues[currentIndexPosition];
156
-
157
- const ourChanges = this._changes.filter((c) =>
158
- c.i.startsWith(this._author)
159
- );
160
-
161
- this._changes.push({
162
- t: "INS",
163
- p: currentPrev?.index,
164
- n: undefined,
165
- v: value,
166
- i: this._author + "-" + `${ourChanges.length}`.padStart(8, "0"),
167
- });
168
- this.calculate();
169
- }
170
-
171
- public DEL(index: number) {
172
- const currentIndex = this._tempValues.filter((v) => !v.tomb)[index].index;
173
- const currentIndexPosition = this._tempValues.findIndex(
174
- (v) => v.index === currentIndex
175
- );
176
-
177
- const current = this._tempValues[currentIndexPosition];
178
-
179
- const ourChanges = this._changes.filter((c) =>
180
- c.i.startsWith(this._author)
181
- );
182
-
183
- this._changes.push({
184
- t: "DEL",
185
- v: current.index,
186
- i: this._author + "-" + `${ourChanges.length}`.padStart(8, "0"),
187
- });
188
- this.calculate();
189
- }
190
- }
1
+ import { BaseCrdt, CRDT_LIST } from "..";
2
+
3
+ export type ListOperations = "INS" | "DEL";
4
+
5
+ export interface ChangeListBase<T> {
6
+ t: ListOperations; // Operation type
7
+ i: string; // "index", author + n
8
+ }
9
+
10
+ export interface InsListChange<T> extends ChangeListBase<T> {
11
+ t: "INS";
12
+ v: T; // Value
13
+ p: string | undefined; // Previous index, if any
14
+ n: string | undefined; // Next index, if any
15
+ }
16
+
17
+ export interface DelListChange<T> extends ChangeListBase<T> {
18
+ t: "DEL";
19
+ v: string; // target index to tombstone
20
+ }
21
+
22
+ export type ListChanges<T> = InsListChange<T> | DelListChange<T>;
23
+
24
+ interface ListTempCursor<T> {
25
+ value: T;
26
+ index: string;
27
+ tomb: boolean;
28
+ prev: string | undefined;
29
+ next: string | undefined;
30
+ }
31
+
32
+ export class ListCrdt<T> extends BaseCrdt<T, ListChanges<T>, T[]> {
33
+ public type = CRDT_LIST;
34
+
35
+ public _changes: ListChanges<T>[] = [];
36
+
37
+ private _author = "";
38
+
39
+ private _value: T[] = [];
40
+
41
+ public _tempValues: ListTempCursor<T>[] = [];
42
+
43
+ private _lastUpdateSize: number = 0;
44
+
45
+ constructor(author: string, changes?: ListChanges<T>[]) {
46
+ super();
47
+ this._author = author;
48
+ if (changes) {
49
+ this.mergeChanges(changes);
50
+ }
51
+
52
+ this.calculate();
53
+ }
54
+
55
+ changesSort(a: ListChanges<T>, b: ListChanges<T>) {
56
+ if (a.i > b.i) return 1;
57
+ if (a.i < b.i) return -1;
58
+ return 0; // Should never be equal!
59
+ }
60
+
61
+ calculate() {
62
+ const temp: ListTempCursor<T>[] = [];
63
+ // Only update if we have new changes
64
+ if (Object.values(this._changes).length !== this._lastUpdateSize) {
65
+ this._changes.sort(this.changesSort).forEach((change) => {
66
+ if (change.t === "INS") {
67
+ let poisitionToInsert = 0;
68
+ if (change.p) {
69
+ poisitionToInsert = temp.findIndex((v) => v.index === change.p) + 1;
70
+ } else if (change.n) {
71
+ poisitionToInsert = temp.findIndex((v) => v.index === change.n);
72
+ }
73
+
74
+ const cursorValue: ListTempCursor<T> = {
75
+ value: change.v,
76
+ index: change.i,
77
+ tomb: false,
78
+ prev: change.p,
79
+ next: change.n,
80
+ };
81
+
82
+ temp.splice(poisitionToInsert, 0, cursorValue);
83
+ } else if (change.t === "DEL") {
84
+ const poisitionToInsert = temp.findIndex((v) => v.index === change.v);
85
+ temp[poisitionToInsert].tomb = true;
86
+ }
87
+ });
88
+ this._lastUpdateSize = Object.values(temp).length;
89
+
90
+ this._tempValues = temp;
91
+
92
+ this._value = temp.filter((v) => !v.tomb).map((v) => v.value);
93
+ }
94
+ }
95
+
96
+ get value(): T[] {
97
+ this.calculate();
98
+ return this._value;
99
+ }
100
+
101
+ public mergeChanges(newChanges: ListChanges<T>[]) {
102
+ newChanges.forEach((change) => {
103
+ // Filter by author and index
104
+ const filtered = this._changes.filter(
105
+ (c) => c.i === change.i && c.t === change.t && c.v === change.v
106
+ );
107
+ // Only add if there are not matches
108
+ if (filtered.length === 0) {
109
+ this._changes.push(change);
110
+ }
111
+ });
112
+ this.calculate();
113
+ }
114
+
115
+ public getChanges(): ListChanges<T>[] {
116
+ return this._changes;
117
+ }
118
+
119
+ public INS(value: T, index: number) {
120
+ const filterTombs = this._tempValues.filter((v) => !v.tomb);
121
+
122
+ let currentPrev = undefined;
123
+ let currentNext = undefined;
124
+
125
+ if (filterTombs.length !== 0) {
126
+ const currentIndex = filterTombs[index].index;
127
+ const currentIndexPosition = this._tempValues.findIndex(
128
+ (v) => v.index === currentIndex
129
+ );
130
+ currentPrev = this._tempValues[currentIndexPosition - 1];
131
+ currentNext = this._tempValues[currentIndexPosition];
132
+ }
133
+
134
+ const ourChanges = this._changes.filter((c) =>
135
+ c.i.startsWith(this._author)
136
+ );
137
+
138
+ this._changes.push({
139
+ t: "INS",
140
+ p: currentPrev?.index,
141
+ n: currentNext?.index,
142
+ v: value,
143
+ i: this._author + "-" + `${ourChanges.length}`.padStart(8, "0"),
144
+ });
145
+ this.calculate();
146
+ }
147
+
148
+ public PUSH(value: T) {
149
+ const filterTombs = this._tempValues.filter((v) => !v.tomb);
150
+ const currentIndex = filterTombs[filterTombs.length - 1]?.index;
151
+ const currentIndexPosition = this._tempValues.findIndex(
152
+ (v) => v.index === currentIndex
153
+ );
154
+
155
+ const currentPrev = this._tempValues[currentIndexPosition];
156
+
157
+ const ourChanges = this._changes.filter((c) =>
158
+ c.i.startsWith(this._author)
159
+ );
160
+
161
+ this._changes.push({
162
+ t: "INS",
163
+ p: currentPrev?.index,
164
+ n: undefined,
165
+ v: value,
166
+ i: this._author + "-" + `${ourChanges.length}`.padStart(8, "0"),
167
+ });
168
+ this.calculate();
169
+ }
170
+
171
+ public DEL(index: number) {
172
+ const currentIndex = this._tempValues.filter((v) => !v.tomb)[index].index;
173
+ const currentIndexPosition = this._tempValues.findIndex(
174
+ (v) => v.index === currentIndex
175
+ );
176
+
177
+ const current = this._tempValues[currentIndexPosition];
178
+
179
+ const ourChanges = this._changes.filter((c) =>
180
+ c.i.startsWith(this._author)
181
+ );
182
+
183
+ this._changes.push({
184
+ t: "DEL",
185
+ v: current.index,
186
+ i: this._author + "-" + `${ourChanges.length}`.padStart(8, "0"),
187
+ });
188
+ this.calculate();
189
+ }
190
+ }