serializable-bptree 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js CHANGED
@@ -1,72 +1,15 @@
1
- // src/utils/BinarySearch.ts
2
- var BinarySearch = class {
3
- comparator;
4
- constructor(comparator) {
5
- this.comparator = comparator;
6
- }
7
- _withRange(array, value, left = 0, right = array.length - 1) {
8
- while (left <= right) {
9
- const mid = Math.floor((left + right) / 2);
10
- const guess = array[mid];
11
- if (this.comparator.isSame(guess, value)) {
12
- return mid;
13
- } else if (this.comparator.isLower(guess, value)) {
14
- left = mid + 1;
15
- continue;
16
- } else {
17
- right = mid - 1;
18
- continue;
19
- }
20
- }
21
- return -1;
22
- }
23
- leftest(array, value) {
24
- let i = this._withRange(array, value);
25
- if (i === -1) {
26
- return -1;
27
- }
28
- while (i > 0) {
29
- if (!this.comparator.isSame(array[i - 1], value)) {
30
- break;
31
- }
32
- i--;
33
- }
34
- return i;
35
- }
36
- rightest(array, value) {
37
- let i = this._withRange(array, value);
38
- if (i === -1) {
39
- return -1;
40
- }
41
- const max = array.length - 1;
42
- while (i < max) {
43
- if (!this.comparator.isSame(array[i + 1], value)) {
44
- break;
45
- }
46
- i++;
47
- }
48
- return i;
49
- }
50
- range(array, value) {
51
- const left = this.leftest(array, value);
52
- const right = this.rightest(array, value) + 1;
53
- return [left, right];
54
- }
55
- };
56
-
57
- // src/BPTree.ts
1
+ // src/base/BPTree.ts
58
2
  var BPTree = class {
59
3
  strategy;
60
4
  comparator;
61
- search;
62
- order;
63
5
  nodes;
6
+ order;
64
7
  data;
65
8
  root;
66
- _creates;
67
- _updates;
68
- _updatedHead;
69
- _verifierMap = {
9
+ _nodeCreateBuffer;
10
+ _nodeUpdateBuffer;
11
+ _headBuffer;
12
+ verifierMap = {
70
13
  gt: (nv, v) => this.comparator.isHigher(nv, v),
71
14
  gte: (nv, v) => this.comparator.isHigher(nv, v) || this.comparator.isSame(nv, v),
72
15
  lt: (nv, v) => this.comparator.isLower(nv, v),
@@ -81,19 +24,16 @@ var BPTree = class {
81
24
  return regex.test(nodeValue);
82
25
  }
83
26
  };
84
- _verifierStartNode = {
27
+ verifierStartNode = {
85
28
  gt: (v) => this.insertableNode(v),
86
29
  gte: (v) => this.insertableNode(v),
87
- // todo
88
30
  lt: (v) => this.insertableNode(v),
89
31
  lte: (v) => this.insertableNode(v),
90
- // todo
91
32
  equal: (v) => this.insertableNode(v),
92
33
  notEqual: (v) => this.leftestNode(),
93
34
  like: (v) => this.leftestNode()
94
- // todo
95
35
  };
96
- _verifierDirection = {
36
+ verifierDirection = {
97
37
  gt: 1,
98
38
  gte: 1,
99
39
  lt: -1,
@@ -102,7 +42,7 @@ var BPTree = class {
102
42
  notEqual: 1,
103
43
  like: 1
104
44
  };
105
- _verifierFullSearch = {
45
+ verifierFullSearch = {
106
46
  gt: false,
107
47
  gte: false,
108
48
  lt: false,
@@ -111,59 +51,7 @@ var BPTree = class {
111
51
  notEqual: true,
112
52
  like: true
113
53
  };
114
- _createNodeId() {
115
- const id = this.strategy.id();
116
- if (id === 0) {
117
- throw new Error(`The node's id should never be 0.`);
118
- }
119
- return id;
120
- }
121
- _createNode(keys, values, leaf = false, parent = 0, next = 0, prev = 0) {
122
- const id = this._createNodeId();
123
- const node = {
124
- id,
125
- keys,
126
- values,
127
- leaf,
128
- parent,
129
- next,
130
- prev
131
- };
132
- this.nodes.set(id, node);
133
- return node;
134
- }
135
- /**
136
- * @param strategy An instance of a strategy that manages the read/write state of a node.
137
- * @param comparator An instance of a comparator that compares the size of values.
138
- */
139
- constructor(strategy, comparator) {
140
- const head = strategy.readHead();
141
- this._creates = /* @__PURE__ */ new Map();
142
- this._updates = /* @__PURE__ */ new Map();
143
- this._updatedHead = null;
144
- this.nodes = /* @__PURE__ */ new Map();
145
- this.search = new BinarySearch(comparator);
146
- this.strategy = strategy;
147
- this.comparator = comparator;
148
- if (head === null) {
149
- this.order = strategy.order;
150
- this.data = {};
151
- this.root = this._createNode([], [], true);
152
- this._setHeadUpdate(this._headState);
153
- this._setCreates(this.root);
154
- this._emitHeadUpdates();
155
- this._emitCreates();
156
- } else {
157
- const { root, order, data } = head;
158
- this.order = order;
159
- this.data = data ?? {};
160
- this.root = this.getNode(root);
161
- }
162
- if (this.order < 3) {
163
- throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
164
- }
165
- }
166
- get _headState() {
54
+ get headState() {
167
55
  const root = this.root.id;
168
56
  const order = this.order;
169
57
  const data = this.data;
@@ -173,82 +61,13 @@ var BPTree = class {
173
61
  data
174
62
  };
175
63
  }
176
- _setHeadUpdate(head) {
177
- this._updatedHead = head;
178
- }
179
- _setCreates(node) {
180
- this._creates.set(node.id, node);
181
- }
182
- _setUpdates(node) {
183
- this._updates.set(node.id, node);
184
- }
185
- _emitHeadUpdates() {
186
- if (this._updatedHead !== null) {
187
- this.strategy.writeHead(this._updatedHead);
188
- }
189
- this._updatedHead = null;
190
- }
191
- _emitCreates() {
192
- for (const node of this._creates.values()) {
193
- this.strategy.write(node.id, node);
194
- }
195
- this._creates.clear();
196
- }
197
- _emitUpdates() {
198
- for (const node of this._updates.values()) {
199
- this.strategy.write(node.id, node);
200
- }
201
- this._updates.clear();
202
- }
203
- getNode(id) {
204
- if (!this.nodes.has(id)) {
205
- this.nodes.set(id, this.strategy.read(id));
206
- }
207
- return this.nodes.get(id);
208
- }
209
- leftestNode() {
210
- let node = this.root;
211
- while (!node.leaf) {
212
- const keys = node.keys;
213
- node = this.getNode(keys[0]);
214
- }
215
- return node;
216
- }
217
- insertableNode(value) {
218
- let node = this.root;
219
- while (!node.leaf) {
220
- for (let i = 0, len = node.values.length; i < len; i++) {
221
- const nValue = node.values[i];
222
- const k = node.keys;
223
- if (this.comparator.isSame(value, nValue)) {
224
- node = this.getNode(k[i + 1]);
225
- break;
226
- } else if (this.comparator.isLower(value, nValue)) {
227
- node = this.getNode(k[i]);
228
- break;
229
- } else if (i + 1 === node.values.length) {
230
- node = this.getNode(k[i + 1]);
231
- break;
232
- }
233
- }
234
- }
235
- return node;
236
- }
237
- /**
238
- * It returns whether there is a value in the tree.
239
- * @param key The key value to search for.
240
- * @param value The value to search for.
241
- */
242
- exists(key, value) {
243
- const node = this.insertableNode(value);
244
- for (let i = 0, len = node.values.length; i < len; i++) {
245
- const nValue = node.values[i];
246
- if (this.comparator.isSame(value, nValue)) {
247
- const keys = node.keys[i];
248
- return keys.includes(key);
249
- }
250
- }
251
- return false;
64
+ constructor(strategy, comparator) {
65
+ this._headBuffer = null;
66
+ this._nodeCreateBuffer = /* @__PURE__ */ new Map();
67
+ this._nodeUpdateBuffer = /* @__PURE__ */ new Map();
68
+ this.nodes = /* @__PURE__ */ new Map();
69
+ this.strategy = strategy;
70
+ this.comparator = comparator;
252
71
  }
253
72
  _insertAtLeaf(node, key, value) {
254
73
  if (node.values.length) {
@@ -257,74 +76,49 @@ var BPTree = class {
257
76
  if (this.comparator.isSame(value, nValue)) {
258
77
  const keys = node.keys[i];
259
78
  keys.push(key);
260
- this._setUpdates(node);
79
+ this.bufferForNodeUpdate(node);
261
80
  break;
262
81
  } else if (this.comparator.isLower(value, nValue)) {
263
82
  node.values.splice(i, 0, value);
264
83
  node.keys.splice(i, 0, [key]);
265
- this._setUpdates(node);
84
+ this.bufferForNodeUpdate(node);
266
85
  break;
267
86
  } else if (i + 1 === node.values.length) {
268
87
  node.values.push(value);
269
88
  node.keys.push([key]);
270
- this._setUpdates(node);
89
+ this.bufferForNodeUpdate(node);
271
90
  break;
272
91
  }
273
92
  }
274
93
  } else {
275
94
  node.values = [value];
276
95
  node.keys = [[key]];
277
- this._setUpdates(node);
96
+ this.bufferForNodeUpdate(node);
278
97
  }
279
98
  }
280
- _insertInParent(node, value, pointer) {
281
- if (this.root === node) {
282
- const root = this._createNode([node.id, pointer.id], [value]);
283
- this.root = root;
284
- node.parent = root.id;
285
- pointer.parent = root.id;
286
- this._setHeadUpdate(this._headState);
287
- this._setCreates(root);
288
- this._setUpdates(node);
289
- this._setUpdates(pointer);
290
- return;
291
- }
292
- const parentNode = this.getNode(node.parent);
293
- for (let i = 0, len = parentNode.keys.length; i < len; i++) {
294
- const nKeys = parentNode.keys[i];
295
- if (nKeys === node.id) {
296
- parentNode.values.splice(i, 0, value);
297
- parentNode.keys.splice(i + 1, 0, pointer.id);
298
- this._setUpdates(parentNode);
299
- if (parentNode.keys.length > this.order) {
300
- const parentPointer = this._createNode([], []);
301
- parentPointer.parent = parentNode.parent;
302
- const mid = Math.ceil(this.order / 2) - 1;
303
- parentPointer.values = parentNode.values.slice(mid + 1);
304
- parentPointer.keys = parentNode.keys.slice(mid + 1);
305
- const midValue = parentNode.values[mid];
306
- if (mid === 0) {
307
- parentNode.values = parentNode.values.slice(0, mid + 1);
308
- } else {
309
- parentNode.values = parentNode.values.slice(0, mid);
310
- }
311
- parentNode.keys = parentNode.keys.slice(0, mid + 1);
312
- for (const k of parentNode.keys) {
313
- const node2 = this.getNode(k);
314
- node2.parent = parentNode.id;
315
- this._setUpdates(node2);
316
- }
317
- for (const k of parentPointer.keys) {
318
- const node2 = this.getNode(k);
319
- node2.parent = parentPointer.id;
320
- this._setUpdates(node2);
321
- }
322
- this._insertInParent(parentNode, midValue, parentPointer);
323
- this._setCreates(parentPointer);
324
- this._setUpdates(parentNode);
325
- }
326
- }
327
- }
99
+ bufferForHeadUpdate(head) {
100
+ this._headBuffer = head;
101
+ }
102
+ bufferForNodeCreate(node) {
103
+ this._nodeCreateBuffer.set(node.id, node);
104
+ }
105
+ bufferForNodeUpdate(node) {
106
+ this._nodeUpdateBuffer.set(node.id, node);
107
+ }
108
+ /**
109
+ * Returns the user-defined data stored in the head of the tree.
110
+ * This value can be set using the `setHeadData` method. If no data has been previously inserted, the default value is returned, and the default value is `{}`.
111
+ * @returns User-defined data stored in the head of the tree.
112
+ */
113
+ getHeadData() {
114
+ return this.data;
115
+ }
116
+ };
117
+
118
+ // src/BPTreeSync.ts
119
+ var BPTreeSync = class extends BPTree {
120
+ constructor(strategy, comparator) {
121
+ super(strategy, comparator);
328
122
  }
329
123
  _getPairsRightToLeft(value, startNode, fullSearch, comparator) {
330
124
  const pairs = [];
@@ -392,96 +186,441 @@ var BPTree = class {
392
186
  throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
393
187
  }
394
188
  }
395
- /**
396
- * It searches for a key within the tree. The result is returned as an array sorted in ascending order based on the value.
397
- * The result is key set instance, and you can use the `gt`, `lt`, `gte`, `lte`, `equal`, `notEqual`, `like` condition statements.
398
- * This method operates much faster than first searching with `where` and then retrieving only the key list.
399
- * @param condition You can use the `gt`, `lt`, `gte`, `lte`, `equal`, `notEqual`, `like` condition statements.
400
- */
401
- keys(condition) {
402
- let result = null;
403
- for (const k in condition) {
404
- const key = k;
405
- const value = condition[key];
406
- const startNode = this._verifierStartNode[key](value);
407
- const direction = this._verifierDirection[key];
408
- const fullSearch = this._verifierFullSearch[key];
409
- const comparator = this._verifierMap[key];
410
- const pairs = this.getPairs(value, startNode, fullSearch, comparator, direction);
411
- if (result === null) {
412
- result = pairs.map((pair) => pair.key);
413
- } else {
414
- result = result.filter((key2) => pairs.find((p) => p.key === key2));
415
- }
189
+ _createNodeId() {
190
+ const id = this.strategy.id();
191
+ if (id === 0) {
192
+ throw new Error(`The node's id should never be 0.`);
416
193
  }
417
- return new Set(result ?? []);
194
+ return id;
418
195
  }
419
- /**
420
- * It searches for a value within the tree. The result is returned as an array sorted in ascending order based on the value.
421
- * The result includes the key and value attributes, and you can use the `gt`, `lt`, `gte`, `lte`, `equal`, `notEqual`, `like` condition statements.
422
- * @param condition You can use the `gt`, `lt`, `gte`, `lte`, `equal`, `notEqual`, `like` condition statements.
423
- */
424
- where(condition) {
425
- let result = null;
426
- for (const k in condition) {
427
- const key = k;
428
- const value = condition[key];
429
- const startNode = this._verifierStartNode[key](value);
430
- const direction = this._verifierDirection[key];
431
- const fullSearch = this._verifierFullSearch[key];
432
- const comparator = this._verifierMap[key];
433
- const pairs = this.getPairs(value, startNode, fullSearch, comparator, direction);
434
- if (result === null) {
435
- result = pairs;
436
- } else {
437
- result = result.filter((pair) => pairs.find((p) => p.key === pair.key));
438
- }
439
- }
440
- return result ?? [];
196
+ _createNode(keys, values, leaf = false, parent = 0, next = 0, prev = 0) {
197
+ const id = this._createNodeId();
198
+ const node = {
199
+ id,
200
+ keys,
201
+ values,
202
+ leaf,
203
+ parent,
204
+ next,
205
+ prev
206
+ };
207
+ this.nodes.set(id, node);
208
+ return node;
441
209
  }
442
- /**
443
- * You enter the key and value as a pair. You can later search for the pair by value.
444
- * This data is stored in the tree, sorted in ascending order of value.
445
- * @param key The key of the pair.
446
- * @param value The value of the pair.
447
- */
448
- insert(key, value) {
449
- const before = this.insertableNode(value);
450
- this._insertAtLeaf(before, key, value);
451
- if (before.values.length === this.order) {
452
- const after = this._createNode(
453
- [],
454
- [],
455
- true,
456
- before.parent,
457
- before.next,
458
- before.id
459
- );
460
- const mid = Math.ceil(this.order / 2) - 1;
461
- const beforeNext = before.next;
462
- after.values = before.values.slice(mid + 1);
463
- after.keys = before.keys.slice(mid + 1);
464
- before.values = before.values.slice(0, mid + 1);
465
- before.keys = before.keys.slice(0, mid + 1);
466
- before.next = after.id;
467
- if (beforeNext) {
468
- const node = this.getNode(beforeNext);
469
- node.prev = after.id;
470
- this._setUpdates(node);
210
+ _deleteEntry(node, key, value) {
211
+ if (!node.leaf) {
212
+ for (let i = 0, len = node.keys.length; i < len; i++) {
213
+ const nKey = node.keys[i];
214
+ if (nKey === key) {
215
+ node.keys.splice(i, 1);
216
+ this.bufferForNodeUpdate(node);
217
+ break;
218
+ }
219
+ }
220
+ for (let i = 0, len = node.values.length; i < len; i++) {
221
+ const nValue = node.values[i];
222
+ if (this.comparator.isSame(value, nValue)) {
223
+ node.values.splice(i, 1);
224
+ this.bufferForNodeUpdate(node);
225
+ break;
226
+ }
227
+ }
228
+ }
229
+ if (this.root === node && node.keys.length === 1) {
230
+ const keys = node.keys;
231
+ this.root = this.getNode(keys[0]);
232
+ this.root.parent = 0;
233
+ this.bufferForHeadUpdate(this.headState);
234
+ this.bufferForNodeUpdate(this.root);
235
+ return;
236
+ } else if (this.root === node) {
237
+ return;
238
+ } else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
239
+ let isPredecessor = false;
240
+ let parentNode = this.getNode(node.parent);
241
+ let prevNode = null;
242
+ let nextNode = null;
243
+ let prevValue = null;
244
+ let postValue = null;
245
+ for (let i = 0, len = parentNode.keys.length; i < len; i++) {
246
+ const nKey = parentNode.keys[i];
247
+ if (nKey === node.id) {
248
+ if (i > 0) {
249
+ prevNode = this.getNode(parentNode.keys[i - 1]);
250
+ prevValue = parentNode.values[i - 1];
251
+ }
252
+ if (i < parentNode.keys.length - 1) {
253
+ nextNode = this.getNode(parentNode.keys[i + 1]);
254
+ postValue = parentNode.values[i];
255
+ }
256
+ }
257
+ }
258
+ let pointer;
259
+ let guess;
260
+ if (prevNode === null) {
261
+ pointer = nextNode;
262
+ guess = postValue;
263
+ } else if (nextNode === null) {
264
+ isPredecessor = true;
265
+ pointer = prevNode;
266
+ guess = prevValue;
267
+ } else {
268
+ if (node.values.length + nextNode.values.length < this.order) {
269
+ pointer = nextNode;
270
+ guess = postValue;
271
+ } else {
272
+ isPredecessor = true;
273
+ pointer = prevNode;
274
+ guess = prevValue;
275
+ }
276
+ }
277
+ if (node.values.length + pointer.values.length < this.order) {
278
+ if (!isPredecessor) {
279
+ const pTemp = pointer;
280
+ pointer = node;
281
+ node = pTemp;
282
+ }
283
+ pointer.keys.push(...node.keys);
284
+ if (!node.leaf) {
285
+ pointer.values.push(guess);
286
+ } else {
287
+ pointer.next = node.next;
288
+ pointer.prev = node.id;
289
+ if (pointer.next) {
290
+ const n = this.getNode(node.next);
291
+ n.prev = pointer.id;
292
+ this.bufferForNodeUpdate(n);
293
+ }
294
+ if (pointer.prev) {
295
+ const n = this.getNode(node.id);
296
+ n.next = pointer.id;
297
+ this.bufferForNodeUpdate(n);
298
+ }
299
+ if (isPredecessor) {
300
+ pointer.prev = 0;
301
+ }
302
+ }
303
+ pointer.values.push(...node.values);
304
+ if (!pointer.leaf) {
305
+ const keys = pointer.keys;
306
+ for (const key2 of keys) {
307
+ const node2 = this.getNode(key2);
308
+ node2.parent = pointer.id;
309
+ this.bufferForNodeUpdate(node2);
310
+ }
311
+ }
312
+ this._deleteEntry(this.getNode(node.parent), node.id, guess);
313
+ this.bufferForNodeUpdate(pointer);
314
+ } else {
315
+ if (isPredecessor) {
316
+ let pointerPm;
317
+ let pointerKm;
318
+ if (!node.leaf) {
319
+ pointerPm = pointer.keys.splice(-1)[0];
320
+ pointerKm = pointer.values.splice(-1)[0];
321
+ node.keys = [pointerPm, ...node.keys];
322
+ node.values = [guess, ...node.values];
323
+ parentNode = this.getNode(node.parent);
324
+ for (let i = 0, len = parentNode.values.length; i < len; i++) {
325
+ const nValue = parentNode.values[i];
326
+ if (this.comparator.isSame(guess, nValue)) {
327
+ parentNode.values[i] = pointerKm;
328
+ this.bufferForNodeUpdate(parentNode);
329
+ break;
330
+ }
331
+ }
332
+ } else {
333
+ pointerPm = pointer.keys.splice(-1)[0];
334
+ pointerKm = pointer.values.splice(-1)[0];
335
+ node.keys = [pointerPm, ...node.keys];
336
+ node.values = [pointerKm, ...node.values];
337
+ parentNode = this.getNode(node.parent);
338
+ for (let i = 0, len = parentNode.values.length; i < len; i++) {
339
+ const nValue = parentNode.values[i];
340
+ if (this.comparator.isSame(guess, nValue)) {
341
+ parentNode.values[i] = pointerKm;
342
+ this.bufferForNodeUpdate(parentNode);
343
+ break;
344
+ }
345
+ }
346
+ }
347
+ this.bufferForNodeUpdate(node);
348
+ this.bufferForNodeUpdate(pointer);
349
+ } else {
350
+ let pointerP0;
351
+ let pointerK0;
352
+ if (!node.leaf) {
353
+ pointerP0 = pointer.keys.splice(0, 1)[0];
354
+ pointerK0 = pointer.values.splice(0, 1)[0];
355
+ node.keys = [...node.keys, pointerP0];
356
+ node.values = [...node.values, guess];
357
+ parentNode = this.getNode(node.parent);
358
+ for (let i = 0, len = parentNode.values.length; i < len; i++) {
359
+ const nValue = parentNode.values[i];
360
+ if (this.comparator.isSame(guess, nValue)) {
361
+ parentNode.values[i] = pointerK0;
362
+ this.bufferForNodeUpdate(parentNode);
363
+ break;
364
+ }
365
+ }
366
+ } else {
367
+ pointerP0 = pointer.keys.splice(0, 1)[0];
368
+ pointerK0 = pointer.values.splice(0, 1)[0];
369
+ node.keys = [...node.keys, pointerP0];
370
+ node.values = [...node.values, pointerK0];
371
+ parentNode = this.getNode(node.parent);
372
+ for (let i = 0, len = parentNode.values.length; i < len; i++) {
373
+ const nValue = parentNode.values[i];
374
+ if (this.comparator.isSame(guess, nValue)) {
375
+ parentNode.values[i] = pointer.values[0];
376
+ this.bufferForNodeUpdate(parentNode);
377
+ break;
378
+ }
379
+ }
380
+ }
381
+ this.bufferForNodeUpdate(node);
382
+ this.bufferForNodeUpdate(pointer);
383
+ }
384
+ if (!pointer.leaf) {
385
+ for (const key2 of pointer.keys) {
386
+ const n = this.getNode(key2);
387
+ n.parent = pointer.id;
388
+ this.bufferForNodeUpdate(n);
389
+ }
390
+ }
391
+ if (!node.leaf) {
392
+ for (const key2 of node.keys) {
393
+ const n = this.getNode(key2);
394
+ n.parent = node.id;
395
+ this.bufferForNodeUpdate(n);
396
+ }
397
+ }
398
+ if (!parentNode.leaf) {
399
+ for (const key2 of parentNode.keys) {
400
+ const n = this.getNode(key2);
401
+ n.parent = parentNode.id;
402
+ this.bufferForNodeUpdate(n);
403
+ }
404
+ }
471
405
  }
472
- this._insertInParent(before, after.values[0], after);
473
- this._setCreates(after);
474
- this._setUpdates(before);
475
406
  }
476
- this._emitHeadUpdates();
477
- this._emitCreates();
478
- this._emitUpdates();
479
407
  }
480
- /**
481
- * Deletes the pair that matches the key and value.
482
- * @param key The key of the pair.
483
- * @param value The value of the pair.
484
- */
408
+ _insertAtLeaf(node, key, value) {
409
+ if (node.values.length) {
410
+ for (let i = 0, len = node.values.length; i < len; i++) {
411
+ const nValue = node.values[i];
412
+ if (this.comparator.isSame(value, nValue)) {
413
+ const keys = node.keys[i];
414
+ keys.push(key);
415
+ this.bufferForNodeUpdate(node);
416
+ break;
417
+ } else if (this.comparator.isLower(value, nValue)) {
418
+ node.values.splice(i, 0, value);
419
+ node.keys.splice(i, 0, [key]);
420
+ this.bufferForNodeUpdate(node);
421
+ break;
422
+ } else if (i + 1 === node.values.length) {
423
+ node.values.push(value);
424
+ node.keys.push([key]);
425
+ this.bufferForNodeUpdate(node);
426
+ break;
427
+ }
428
+ }
429
+ } else {
430
+ node.values = [value];
431
+ node.keys = [[key]];
432
+ this.bufferForNodeUpdate(node);
433
+ }
434
+ }
435
+ _insertInParent(node, value, pointer) {
436
+ if (this.root === node) {
437
+ const root = this._createNode([node.id, pointer.id], [value]);
438
+ this.root = root;
439
+ node.parent = root.id;
440
+ pointer.parent = root.id;
441
+ this.bufferForHeadUpdate(this.headState);
442
+ this.bufferForNodeCreate(root);
443
+ this.bufferForNodeUpdate(node);
444
+ this.bufferForNodeUpdate(pointer);
445
+ return;
446
+ }
447
+ const parentNode = this.getNode(node.parent);
448
+ for (let i = 0, len = parentNode.keys.length; i < len; i++) {
449
+ const nKeys = parentNode.keys[i];
450
+ if (nKeys === node.id) {
451
+ parentNode.values.splice(i, 0, value);
452
+ parentNode.keys.splice(i + 1, 0, pointer.id);
453
+ this.bufferForNodeUpdate(parentNode);
454
+ if (parentNode.keys.length > this.order) {
455
+ const parentPointer = this._createNode([], []);
456
+ parentPointer.parent = parentNode.parent;
457
+ const mid = Math.ceil(this.order / 2) - 1;
458
+ parentPointer.values = parentNode.values.slice(mid + 1);
459
+ parentPointer.keys = parentNode.keys.slice(mid + 1);
460
+ const midValue = parentNode.values[mid];
461
+ if (mid === 0) {
462
+ parentNode.values = parentNode.values.slice(0, mid + 1);
463
+ } else {
464
+ parentNode.values = parentNode.values.slice(0, mid);
465
+ }
466
+ parentNode.keys = parentNode.keys.slice(0, mid + 1);
467
+ for (const k of parentNode.keys) {
468
+ const node2 = this.getNode(k);
469
+ node2.parent = parentNode.id;
470
+ this.bufferForNodeUpdate(node2);
471
+ }
472
+ for (const k of parentPointer.keys) {
473
+ const node2 = this.getNode(k);
474
+ node2.parent = parentPointer.id;
475
+ this.bufferForNodeUpdate(node2);
476
+ }
477
+ this._insertInParent(parentNode, midValue, parentPointer);
478
+ this.bufferForNodeCreate(parentPointer);
479
+ this.bufferForNodeUpdate(parentNode);
480
+ }
481
+ }
482
+ }
483
+ }
484
+ init() {
485
+ const head = this.strategy.readHead();
486
+ if (head === null) {
487
+ this.order = this.strategy.order;
488
+ this.data = {};
489
+ this.root = this._createNode([], [], true);
490
+ this.bufferForHeadUpdate(this.headState);
491
+ this.bufferForNodeCreate(this.root);
492
+ this.commitHeadBuffer();
493
+ this.commitNodeCreateBuffer();
494
+ } else {
495
+ const { root, order, data } = head;
496
+ this.order = order;
497
+ this.data = data ?? {};
498
+ this.root = this.getNode(root);
499
+ }
500
+ if (this.order < 3) {
501
+ throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
502
+ }
503
+ }
504
+ getNode(id) {
505
+ if (!this.nodes.has(id)) {
506
+ this.nodes.set(id, this.strategy.read(id));
507
+ }
508
+ return this.nodes.get(id);
509
+ }
510
+ insertableNode(value) {
511
+ let node = this.root;
512
+ while (!node.leaf) {
513
+ for (let i = 0, len = node.values.length; i < len; i++) {
514
+ const nValue = node.values[i];
515
+ const k = node.keys;
516
+ if (this.comparator.isSame(value, nValue)) {
517
+ node = this.getNode(k[i + 1]);
518
+ break;
519
+ } else if (this.comparator.isLower(value, nValue)) {
520
+ node = this.getNode(k[i]);
521
+ break;
522
+ } else if (i + 1 === node.values.length) {
523
+ node = this.getNode(k[i + 1]);
524
+ break;
525
+ }
526
+ }
527
+ }
528
+ return node;
529
+ }
530
+ leftestNode() {
531
+ let node = this.root;
532
+ while (!node.leaf) {
533
+ const keys = node.keys;
534
+ node = this.getNode(keys[0]);
535
+ }
536
+ return node;
537
+ }
538
+ commitHeadBuffer() {
539
+ if (this._headBuffer !== null) {
540
+ this.strategy.writeHead(this._headBuffer);
541
+ }
542
+ this.bufferForHeadUpdate(null);
543
+ }
544
+ commitNodeCreateBuffer() {
545
+ for (const node of this._nodeCreateBuffer.values()) {
546
+ this.strategy.write(node.id, node);
547
+ }
548
+ this._nodeCreateBuffer.clear();
549
+ }
550
+ commitNodeUpdateBuffer() {
551
+ for (const node of this._nodeUpdateBuffer.values()) {
552
+ this.strategy.write(node.id, node);
553
+ }
554
+ this._nodeUpdateBuffer.clear();
555
+ }
556
+ keys(condition) {
557
+ let result = null;
558
+ for (const k in condition) {
559
+ const key = k;
560
+ const value = condition[key];
561
+ const startNode = this.verifierStartNode[key](value);
562
+ const direction = this.verifierDirection[key];
563
+ const fullSearch = this.verifierFullSearch[key];
564
+ const comparator = this.verifierMap[key];
565
+ const pairs = this.getPairs(value, startNode, fullSearch, comparator, direction);
566
+ if (result === null) {
567
+ result = pairs.map((pair) => pair.key);
568
+ } else {
569
+ result = result.filter((key2) => pairs.find((p) => p.key === key2));
570
+ }
571
+ }
572
+ return new Set(result ?? []);
573
+ }
574
+ where(condition) {
575
+ let result = null;
576
+ for (const k in condition) {
577
+ const key = k;
578
+ const value = condition[key];
579
+ const startNode = this.verifierStartNode[key](value);
580
+ const direction = this.verifierDirection[key];
581
+ const fullSearch = this.verifierFullSearch[key];
582
+ const comparator = this.verifierMap[key];
583
+ const pairs = this.getPairs(value, startNode, fullSearch, comparator, direction);
584
+ if (result === null) {
585
+ result = pairs;
586
+ } else {
587
+ result = result.filter((pair) => pairs.find((p) => p.key === pair.key));
588
+ }
589
+ }
590
+ return result ?? [];
591
+ }
592
+ insert(key, value) {
593
+ const before = this.insertableNode(value);
594
+ this._insertAtLeaf(before, key, value);
595
+ if (before.values.length === this.order) {
596
+ const after = this._createNode(
597
+ [],
598
+ [],
599
+ true,
600
+ before.parent,
601
+ before.next,
602
+ before.id
603
+ );
604
+ const mid = Math.ceil(this.order / 2) - 1;
605
+ const beforeNext = before.next;
606
+ after.values = before.values.slice(mid + 1);
607
+ after.keys = before.keys.slice(mid + 1);
608
+ before.values = before.values.slice(0, mid + 1);
609
+ before.keys = before.keys.slice(0, mid + 1);
610
+ before.next = after.id;
611
+ if (beforeNext) {
612
+ const node = this.getNode(beforeNext);
613
+ node.prev = after.id;
614
+ this.bufferForNodeUpdate(node);
615
+ }
616
+ this._insertInParent(before, after.values[0], after);
617
+ this.bufferForNodeCreate(after);
618
+ this.bufferForNodeUpdate(before);
619
+ }
620
+ this.commitHeadBuffer();
621
+ this.commitNodeCreateBuffer();
622
+ this.commitNodeUpdateBuffer();
623
+ }
485
624
  delete(key, value) {
486
625
  const node = this.insertableNode(value);
487
626
  let i = node.values.length;
@@ -489,35 +628,153 @@ var BPTree = class {
489
628
  const nValue = node.values[i];
490
629
  if (this.comparator.isSame(value, nValue)) {
491
630
  const keys = node.keys[i];
492
- if (keys.includes(key)) {
493
- if (keys.length > 1) {
494
- keys.splice(keys.indexOf(key), 1);
495
- this._setUpdates(node);
496
- } else if (node === this.root) {
497
- node.values.splice(i, 1);
498
- node.keys.splice(i, 1);
499
- this._setUpdates(node);
500
- } else {
501
- keys.splice(keys.indexOf(key), 1);
502
- node.keys.splice(i, 1);
503
- node.values.splice(node.values.indexOf(value), 1);
504
- this._deleteEntry(node, key, value);
505
- this._setUpdates(node);
631
+ if (keys.includes(key)) {
632
+ if (keys.length > 1) {
633
+ keys.splice(keys.indexOf(key), 1);
634
+ this.bufferForNodeUpdate(node);
635
+ } else if (node === this.root) {
636
+ node.values.splice(i, 1);
637
+ node.keys.splice(i, 1);
638
+ this.bufferForNodeUpdate(node);
639
+ } else {
640
+ keys.splice(keys.indexOf(key), 1);
641
+ node.keys.splice(i, 1);
642
+ node.values.splice(node.values.indexOf(value), 1);
643
+ this._deleteEntry(node, key, value);
644
+ this.bufferForNodeUpdate(node);
645
+ }
646
+ }
647
+ }
648
+ }
649
+ this.commitHeadBuffer();
650
+ this.commitNodeCreateBuffer();
651
+ this.commitNodeUpdateBuffer();
652
+ }
653
+ exists(key, value) {
654
+ const node = this.insertableNode(value);
655
+ for (let i = 0, len = node.values.length; i < len; i++) {
656
+ const nValue = node.values[i];
657
+ if (this.comparator.isSame(value, nValue)) {
658
+ const keys = node.keys[i];
659
+ return keys.includes(key);
660
+ }
661
+ }
662
+ return false;
663
+ }
664
+ setHeadData(data) {
665
+ this.data = data;
666
+ this.bufferForHeadUpdate(this.headState);
667
+ this.commitHeadBuffer();
668
+ }
669
+ forceUpdate(nodeId = null) {
670
+ const ids = nodeId === null ? [...this.nodes.keys()] : [nodeId];
671
+ for (const id of ids) {
672
+ this.nodes.delete(id);
673
+ this.getNode(id);
674
+ }
675
+ return ids.length;
676
+ }
677
+ };
678
+
679
+ // src/BPTreeAsync.ts
680
+ var BPTreeAsync = class extends BPTree {
681
+ constructor(strategy, comparator) {
682
+ super(strategy, comparator);
683
+ }
684
+ async _getPairsRightToLeft(value, startNode, fullSearch, comparator) {
685
+ const pairs = [];
686
+ let node = startNode;
687
+ let done = false;
688
+ let found = false;
689
+ while (!done) {
690
+ let i = node.values.length;
691
+ while (i--) {
692
+ const nValue = node.values[i];
693
+ const keys = node.keys[i];
694
+ if (comparator(nValue, value)) {
695
+ found = true;
696
+ let j = keys.length;
697
+ while (j--) {
698
+ pairs.push({ key: keys[j], value: nValue });
699
+ }
700
+ } else if (found && !fullSearch) {
701
+ done = true;
702
+ break;
703
+ }
704
+ }
705
+ if (!node.prev) {
706
+ done = true;
707
+ break;
708
+ }
709
+ node = await this.getNode(node.prev);
710
+ }
711
+ return pairs.reverse();
712
+ }
713
+ async _getPairsLeftToRight(value, startNode, fullSearch, comparator) {
714
+ const pairs = [];
715
+ let node = startNode;
716
+ let done = false;
717
+ let found = false;
718
+ while (!done) {
719
+ for (let i = 0, len = node.values.length; i < len; i++) {
720
+ const nValue = node.values[i];
721
+ const keys = node.keys[i];
722
+ if (comparator(nValue, value)) {
723
+ found = true;
724
+ for (const key of keys) {
725
+ pairs.push({ key, value: nValue });
506
726
  }
727
+ } else if (found && !fullSearch) {
728
+ done = true;
729
+ break;
507
730
  }
508
731
  }
732
+ if (!node.next) {
733
+ done = true;
734
+ break;
735
+ }
736
+ node = await this.getNode(node.next);
509
737
  }
510
- this._emitHeadUpdates();
511
- this._emitCreates();
512
- this._emitUpdates();
738
+ return pairs;
513
739
  }
514
- _deleteEntry(node, key, value) {
740
+ async getPairs(value, startNode, fullSearch, comparator, direction) {
741
+ switch (direction) {
742
+ case -1:
743
+ return await this._getPairsRightToLeft(value, startNode, fullSearch, comparator);
744
+ case 1:
745
+ return await this._getPairsLeftToRight(value, startNode, fullSearch, comparator);
746
+ default:
747
+ throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
748
+ }
749
+ }
750
+ async _createNodeId() {
751
+ const id = await this.strategy.id();
752
+ if (id === 0) {
753
+ throw new Error(`The node's id should never be 0.`);
754
+ }
755
+ return id;
756
+ }
757
+ async _createNode(keys, values, leaf = false, parent = 0, next = 0, prev = 0) {
758
+ const id = await this._createNodeId();
759
+ const node = {
760
+ id,
761
+ keys,
762
+ values,
763
+ leaf,
764
+ parent,
765
+ next,
766
+ prev
767
+ };
768
+ this.nodes.set(id, node);
769
+ return node;
770
+ }
771
+ async _deleteEntry(node, key, value) {
515
772
  if (!node.leaf) {
516
773
  for (let i = 0, len = node.keys.length; i < len; i++) {
517
774
  const nKey = node.keys[i];
518
775
  if (nKey === key) {
519
776
  node.keys.splice(i, 1);
520
- this._setUpdates(node);
777
+ this.bufferForNodeUpdate(node);
521
778
  break;
522
779
  }
523
780
  }
@@ -525,23 +782,23 @@ var BPTree = class {
525
782
  const nValue = node.values[i];
526
783
  if (this.comparator.isSame(value, nValue)) {
527
784
  node.values.splice(i, 1);
528
- this._setUpdates(node);
785
+ this.bufferForNodeUpdate(node);
529
786
  break;
530
787
  }
531
788
  }
532
789
  }
533
790
  if (this.root === node && node.keys.length === 1) {
534
791
  const keys = node.keys;
535
- this.root = this.getNode(keys[0]);
792
+ this.root = await this.getNode(keys[0]);
536
793
  this.root.parent = 0;
537
- this._setHeadUpdate(this._headState);
538
- this._setUpdates(this.root);
794
+ this.bufferForHeadUpdate(this.headState);
795
+ this.bufferForNodeUpdate(this.root);
539
796
  return;
540
797
  } else if (this.root === node) {
541
798
  return;
542
799
  } else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
543
800
  let isPredecessor = false;
544
- let parentNode = this.getNode(node.parent);
801
+ let parentNode = await this.getNode(node.parent);
545
802
  let prevNode = null;
546
803
  let nextNode = null;
547
804
  let prevValue = null;
@@ -550,11 +807,11 @@ var BPTree = class {
550
807
  const nKey = parentNode.keys[i];
551
808
  if (nKey === node.id) {
552
809
  if (i > 0) {
553
- prevNode = this.getNode(parentNode.keys[i - 1]);
810
+ prevNode = await this.getNode(parentNode.keys[i - 1]);
554
811
  prevValue = parentNode.values[i - 1];
555
812
  }
556
813
  if (i < parentNode.keys.length - 1) {
557
- nextNode = this.getNode(parentNode.keys[i + 1]);
814
+ nextNode = await this.getNode(parentNode.keys[i + 1]);
558
815
  postValue = parentNode.values[i];
559
816
  }
560
817
  }
@@ -591,14 +848,14 @@ var BPTree = class {
591
848
  pointer.next = node.next;
592
849
  pointer.prev = node.id;
593
850
  if (pointer.next) {
594
- const n = this.getNode(node.next);
851
+ const n = await this.getNode(node.next);
595
852
  n.prev = pointer.id;
596
- this._setUpdates(n);
853
+ this.bufferForNodeUpdate(n);
597
854
  }
598
855
  if (pointer.prev) {
599
- const n = this.getNode(node.id);
856
+ const n = await this.getNode(node.id);
600
857
  n.next = pointer.id;
601
- this._setUpdates(n);
858
+ this.bufferForNodeUpdate(n);
602
859
  }
603
860
  if (isPredecessor) {
604
861
  pointer.prev = 0;
@@ -608,13 +865,13 @@ var BPTree = class {
608
865
  if (!pointer.leaf) {
609
866
  const keys = pointer.keys;
610
867
  for (const key2 of keys) {
611
- const node2 = this.getNode(key2);
868
+ const node2 = await this.getNode(key2);
612
869
  node2.parent = pointer.id;
613
- this._setUpdates(node2);
870
+ this.bufferForNodeUpdate(node2);
614
871
  }
615
872
  }
616
- this._deleteEntry(this.getNode(node.parent), node.id, guess);
617
- this._setUpdates(pointer);
873
+ await this._deleteEntry(await this.getNode(node.parent), node.id, guess);
874
+ this.bufferForNodeUpdate(pointer);
618
875
  } else {
619
876
  if (isPredecessor) {
620
877
  let pointerPm;
@@ -624,12 +881,12 @@ var BPTree = class {
624
881
  pointerKm = pointer.values.splice(-1)[0];
625
882
  node.keys = [pointerPm, ...node.keys];
626
883
  node.values = [guess, ...node.values];
627
- parentNode = this.getNode(node.parent);
884
+ parentNode = await this.getNode(node.parent);
628
885
  for (let i = 0, len = parentNode.values.length; i < len; i++) {
629
886
  const nValue = parentNode.values[i];
630
887
  if (this.comparator.isSame(guess, nValue)) {
631
888
  parentNode.values[i] = pointerKm;
632
- this._setUpdates(parentNode);
889
+ this.bufferForNodeUpdate(parentNode);
633
890
  break;
634
891
  }
635
892
  }
@@ -638,18 +895,18 @@ var BPTree = class {
638
895
  pointerKm = pointer.values.splice(-1)[0];
639
896
  node.keys = [pointerPm, ...node.keys];
640
897
  node.values = [pointerKm, ...node.values];
641
- parentNode = this.getNode(node.parent);
898
+ parentNode = await this.getNode(node.parent);
642
899
  for (let i = 0, len = parentNode.values.length; i < len; i++) {
643
900
  const nValue = parentNode.values[i];
644
901
  if (this.comparator.isSame(guess, nValue)) {
645
902
  parentNode.values[i] = pointerKm;
646
- this._setUpdates(parentNode);
903
+ this.bufferForNodeUpdate(parentNode);
647
904
  break;
648
905
  }
649
906
  }
650
907
  }
651
- this._setUpdates(node);
652
- this._setUpdates(pointer);
908
+ this.bufferForNodeUpdate(node);
909
+ this.bufferForNodeUpdate(pointer);
653
910
  } else {
654
911
  let pointerP0;
655
912
  let pointerK0;
@@ -658,12 +915,12 @@ var BPTree = class {
658
915
  pointerK0 = pointer.values.splice(0, 1)[0];
659
916
  node.keys = [...node.keys, pointerP0];
660
917
  node.values = [...node.values, guess];
661
- parentNode = this.getNode(node.parent);
918
+ parentNode = await this.getNode(node.parent);
662
919
  for (let i = 0, len = parentNode.values.length; i < len; i++) {
663
920
  const nValue = parentNode.values[i];
664
921
  if (this.comparator.isSame(guess, nValue)) {
665
922
  parentNode.values[i] = pointerK0;
666
- this._setUpdates(parentNode);
923
+ this.bufferForNodeUpdate(parentNode);
667
924
  break;
668
925
  }
669
926
  }
@@ -672,72 +929,299 @@ var BPTree = class {
672
929
  pointerK0 = pointer.values.splice(0, 1)[0];
673
930
  node.keys = [...node.keys, pointerP0];
674
931
  node.values = [...node.values, pointerK0];
675
- parentNode = this.getNode(node.parent);
932
+ parentNode = await this.getNode(node.parent);
676
933
  for (let i = 0, len = parentNode.values.length; i < len; i++) {
677
934
  const nValue = parentNode.values[i];
678
935
  if (this.comparator.isSame(guess, nValue)) {
679
936
  parentNode.values[i] = pointer.values[0];
680
- this._setUpdates(parentNode);
937
+ this.bufferForNodeUpdate(parentNode);
681
938
  break;
682
939
  }
683
940
  }
684
941
  }
685
- this._setUpdates(node);
686
- this._setUpdates(pointer);
942
+ this.bufferForNodeUpdate(node);
943
+ this.bufferForNodeUpdate(pointer);
687
944
  }
688
945
  if (!pointer.leaf) {
689
946
  for (const key2 of pointer.keys) {
690
- const n = this.getNode(key2);
947
+ const n = await this.getNode(key2);
691
948
  n.parent = pointer.id;
692
- this._setUpdates(n);
949
+ this.bufferForNodeUpdate(n);
693
950
  }
694
951
  }
695
952
  if (!node.leaf) {
696
953
  for (const key2 of node.keys) {
697
- const n = this.getNode(key2);
954
+ const n = await this.getNode(key2);
698
955
  n.parent = node.id;
699
- this._setUpdates(n);
956
+ this.bufferForNodeUpdate(n);
700
957
  }
701
958
  }
702
959
  if (!parentNode.leaf) {
703
960
  for (const key2 of parentNode.keys) {
704
- const n = this.getNode(key2);
961
+ const n = await this.getNode(key2);
705
962
  n.parent = parentNode.id;
706
- this._setUpdates(n);
963
+ this.bufferForNodeUpdate(n);
707
964
  }
708
965
  }
709
966
  }
710
967
  }
711
968
  }
712
- /**
713
- * Returns the user-defined data stored in the head of the tree.
714
- * This value can be set using the `setHeadData` method. If no data has been previously inserted, the default value is returned, and the default value is `{}`.
715
- * @returns User-defined data stored in the head of the tree.
716
- */
717
- getHeadData() {
718
- return this.data;
969
+ async _insertInParent(node, value, pointer) {
970
+ if (this.root === node) {
971
+ const root = await this._createNode([node.id, pointer.id], [value]);
972
+ this.root = root;
973
+ node.parent = root.id;
974
+ pointer.parent = root.id;
975
+ this.bufferForHeadUpdate(this.headState);
976
+ this.bufferForNodeCreate(root);
977
+ this.bufferForNodeUpdate(node);
978
+ this.bufferForNodeUpdate(pointer);
979
+ return;
980
+ }
981
+ const parentNode = await this.getNode(node.parent);
982
+ for (let i = 0, len = parentNode.keys.length; i < len; i++) {
983
+ const nKeys = parentNode.keys[i];
984
+ if (nKeys === node.id) {
985
+ parentNode.values.splice(i, 0, value);
986
+ parentNode.keys.splice(i + 1, 0, pointer.id);
987
+ this.bufferForNodeUpdate(parentNode);
988
+ if (parentNode.keys.length > this.order) {
989
+ const parentPointer = await this._createNode([], []);
990
+ parentPointer.parent = parentNode.parent;
991
+ const mid = Math.ceil(this.order / 2) - 1;
992
+ parentPointer.values = parentNode.values.slice(mid + 1);
993
+ parentPointer.keys = parentNode.keys.slice(mid + 1);
994
+ const midValue = parentNode.values[mid];
995
+ if (mid === 0) {
996
+ parentNode.values = parentNode.values.slice(0, mid + 1);
997
+ } else {
998
+ parentNode.values = parentNode.values.slice(0, mid);
999
+ }
1000
+ parentNode.keys = parentNode.keys.slice(0, mid + 1);
1001
+ for (const k of parentNode.keys) {
1002
+ const node2 = await this.getNode(k);
1003
+ node2.parent = parentNode.id;
1004
+ this.bufferForNodeUpdate(node2);
1005
+ }
1006
+ for (const k of parentPointer.keys) {
1007
+ const node2 = await this.getNode(k);
1008
+ node2.parent = parentPointer.id;
1009
+ this.bufferForNodeUpdate(node2);
1010
+ }
1011
+ await this._insertInParent(parentNode, midValue, parentPointer);
1012
+ this.bufferForNodeCreate(parentPointer);
1013
+ this.bufferForNodeUpdate(parentNode);
1014
+ }
1015
+ }
1016
+ }
719
1017
  }
720
- /**
721
- * Inserts user-defined data into the head of the tree.
722
- * This feature is useful when you need to store separate, non-volatile information in the tree.
723
- * For example, you can store information such as the last update time and the number of insertions.
724
- * @param data User-defined data to be stored in the head of the tree.
725
- */
726
- setHeadData(data) {
1018
+ async init() {
1019
+ const head = await this.strategy.readHead();
1020
+ if (head === null) {
1021
+ this.order = this.strategy.order;
1022
+ this.data = {};
1023
+ this.root = await this._createNode([], [], true);
1024
+ this.bufferForHeadUpdate(this.headState);
1025
+ this.bufferForNodeCreate(this.root);
1026
+ this.commitHeadBuffer();
1027
+ this.commitNodeCreateBuffer();
1028
+ } else {
1029
+ const { root, order, data } = head;
1030
+ this.order = order;
1031
+ this.data = data ?? {};
1032
+ this.root = await this.getNode(root);
1033
+ }
1034
+ if (this.order < 3) {
1035
+ throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
1036
+ }
1037
+ }
1038
+ async getNode(id) {
1039
+ if (!this.nodes.has(id)) {
1040
+ this.nodes.set(id, await this.strategy.read(id));
1041
+ }
1042
+ return this.nodes.get(id);
1043
+ }
1044
+ async insertableNode(value) {
1045
+ let node = this.root;
1046
+ while (!node.leaf) {
1047
+ for (let i = 0, len = node.values.length; i < len; i++) {
1048
+ const nValue = node.values[i];
1049
+ const k = node.keys;
1050
+ if (this.comparator.isSame(value, nValue)) {
1051
+ node = await this.getNode(k[i + 1]);
1052
+ break;
1053
+ } else if (this.comparator.isLower(value, nValue)) {
1054
+ node = await this.getNode(k[i]);
1055
+ break;
1056
+ } else if (i + 1 === node.values.length) {
1057
+ node = await this.getNode(k[i + 1]);
1058
+ break;
1059
+ }
1060
+ }
1061
+ }
1062
+ return node;
1063
+ }
1064
+ async leftestNode() {
1065
+ let node = this.root;
1066
+ while (!node.leaf) {
1067
+ const keys = node.keys;
1068
+ node = await this.getNode(keys[0]);
1069
+ }
1070
+ return node;
1071
+ }
1072
+ async commitHeadBuffer() {
1073
+ if (this._headBuffer !== null) {
1074
+ await this.strategy.writeHead(this._headBuffer);
1075
+ }
1076
+ this.bufferForHeadUpdate(null);
1077
+ }
1078
+ async commitNodeCreateBuffer() {
1079
+ for (const node of this._nodeCreateBuffer.values()) {
1080
+ await this.strategy.write(node.id, node);
1081
+ }
1082
+ this._nodeCreateBuffer.clear();
1083
+ }
1084
+ async commitNodeUpdateBuffer() {
1085
+ for (const node of this._nodeUpdateBuffer.values()) {
1086
+ await this.strategy.write(node.id, node);
1087
+ }
1088
+ this._nodeUpdateBuffer.clear();
1089
+ }
1090
+ async keys(condition) {
1091
+ let result = null;
1092
+ for (const k in condition) {
1093
+ const key = k;
1094
+ const value = condition[key];
1095
+ const startNode = await this.verifierStartNode[key](value);
1096
+ const direction = this.verifierDirection[key];
1097
+ const fullSearch = this.verifierFullSearch[key];
1098
+ const comparator = this.verifierMap[key];
1099
+ const pairs = await this.getPairs(value, startNode, fullSearch, comparator, direction);
1100
+ if (result === null) {
1101
+ result = pairs.map((pair) => pair.key);
1102
+ } else {
1103
+ result = result.filter((key2) => pairs.find((p) => p.key === key2));
1104
+ }
1105
+ }
1106
+ return new Set(result ?? []);
1107
+ }
1108
+ async where(condition) {
1109
+ let result = null;
1110
+ for (const k in condition) {
1111
+ const key = k;
1112
+ const value = condition[key];
1113
+ const startNode = await this.verifierStartNode[key](value);
1114
+ const direction = this.verifierDirection[key];
1115
+ const fullSearch = this.verifierFullSearch[key];
1116
+ const comparator = this.verifierMap[key];
1117
+ const pairs = await this.getPairs(value, startNode, fullSearch, comparator, direction);
1118
+ if (result === null) {
1119
+ result = pairs;
1120
+ } else {
1121
+ result = result.filter((pair) => pairs.find((p) => p.key === pair.key));
1122
+ }
1123
+ }
1124
+ return result ?? [];
1125
+ }
1126
+ async insert(key, value) {
1127
+ const before = await this.insertableNode(value);
1128
+ this._insertAtLeaf(before, key, value);
1129
+ if (before.values.length === this.order) {
1130
+ const after = await this._createNode(
1131
+ [],
1132
+ [],
1133
+ true,
1134
+ before.parent,
1135
+ before.next,
1136
+ before.id
1137
+ );
1138
+ const mid = Math.ceil(this.order / 2) - 1;
1139
+ const beforeNext = before.next;
1140
+ after.values = before.values.slice(mid + 1);
1141
+ after.keys = before.keys.slice(mid + 1);
1142
+ before.values = before.values.slice(0, mid + 1);
1143
+ before.keys = before.keys.slice(0, mid + 1);
1144
+ before.next = after.id;
1145
+ if (beforeNext) {
1146
+ const node = await this.getNode(beforeNext);
1147
+ node.prev = after.id;
1148
+ this.bufferForNodeUpdate(node);
1149
+ }
1150
+ await this._insertInParent(before, after.values[0], after);
1151
+ this.bufferForNodeCreate(after);
1152
+ this.bufferForNodeUpdate(before);
1153
+ }
1154
+ await this.commitHeadBuffer();
1155
+ await this.commitNodeCreateBuffer();
1156
+ await this.commitNodeUpdateBuffer();
1157
+ }
1158
+ async delete(key, value) {
1159
+ const node = await this.insertableNode(value);
1160
+ let i = node.values.length;
1161
+ while (i--) {
1162
+ const nValue = node.values[i];
1163
+ if (this.comparator.isSame(value, nValue)) {
1164
+ const keys = node.keys[i];
1165
+ if (keys.includes(key)) {
1166
+ if (keys.length > 1) {
1167
+ keys.splice(keys.indexOf(key), 1);
1168
+ this.bufferForNodeUpdate(node);
1169
+ } else if (node === this.root) {
1170
+ node.values.splice(i, 1);
1171
+ node.keys.splice(i, 1);
1172
+ this.bufferForNodeUpdate(node);
1173
+ } else {
1174
+ keys.splice(keys.indexOf(key), 1);
1175
+ node.keys.splice(i, 1);
1176
+ node.values.splice(node.values.indexOf(value), 1);
1177
+ await this._deleteEntry(node, key, value);
1178
+ this.bufferForNodeUpdate(node);
1179
+ }
1180
+ }
1181
+ }
1182
+ }
1183
+ await this.commitHeadBuffer();
1184
+ await this.commitNodeCreateBuffer();
1185
+ await this.commitNodeUpdateBuffer();
1186
+ }
1187
+ async exists(key, value) {
1188
+ const node = await this.insertableNode(value);
1189
+ for (let i = 0, len = node.values.length; i < len; i++) {
1190
+ const nValue = node.values[i];
1191
+ if (this.comparator.isSame(value, nValue)) {
1192
+ const keys = node.keys[i];
1193
+ return keys.includes(key);
1194
+ }
1195
+ }
1196
+ return false;
1197
+ }
1198
+ async setHeadData(data) {
727
1199
  this.data = data;
728
- this._updatedHead = this._headState;
729
- this._emitHeadUpdates();
1200
+ this.bufferForHeadUpdate(this.headState);
1201
+ await this.commitHeadBuffer();
1202
+ }
1203
+ async forceUpdate(nodeId = null) {
1204
+ const ids = nodeId === null ? [...this.nodes.keys()] : [nodeId];
1205
+ for (const id of ids) {
1206
+ this.nodes.delete(id);
1207
+ await this.getNode(id);
1208
+ }
1209
+ return ids.length;
730
1210
  }
731
1211
  };
732
1212
 
733
- // src/SerializeStrategy.ts
1213
+ // src/base/SerializeStrategy.ts
734
1214
  var SerializeStrategy = class {
735
1215
  order;
736
1216
  constructor(order) {
737
1217
  this.order = order;
738
1218
  }
739
1219
  };
740
- var InMemoryStoreStrategy = class extends SerializeStrategy {
1220
+
1221
+ // src/SerializeStrategySync.ts
1222
+ var SerializeStrategySync = class extends SerializeStrategy {
1223
+ };
1224
+ var InMemoryStoreStrategySync = class extends SerializeStrategySync {
741
1225
  data;
742
1226
  constructor(order) {
743
1227
  super(order);
@@ -766,6 +1250,38 @@ var InMemoryStoreStrategy = class extends SerializeStrategy {
766
1250
  }
767
1251
  };
768
1252
 
1253
+ // src/SerializeStrategyAsync.ts
1254
+ var SerializeStrategyAsync = class extends SerializeStrategy {
1255
+ };
1256
+ var InMemoryStoreStrategyAsync = class extends SerializeStrategyAsync {
1257
+ data;
1258
+ constructor(order) {
1259
+ super(order);
1260
+ this.data = {
1261
+ head: null,
1262
+ node: {}
1263
+ };
1264
+ }
1265
+ async id() {
1266
+ return Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER - 1);
1267
+ }
1268
+ async read(id) {
1269
+ if (!Object.prototype.hasOwnProperty.call(this.data.node, id)) {
1270
+ throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
1271
+ }
1272
+ return this.data.node[id];
1273
+ }
1274
+ async write(id, node) {
1275
+ this.data.node[id] = node;
1276
+ }
1277
+ async readHead() {
1278
+ return this.data.head;
1279
+ }
1280
+ async writeHead(head) {
1281
+ this.data.head = head;
1282
+ }
1283
+ };
1284
+
769
1285
  // src/ValueComparator.ts
770
1286
  var ValueComparator = class {
771
1287
  isLower(value, than) {
@@ -789,10 +1305,13 @@ var StringComparator = class extends ValueComparator {
789
1305
  }
790
1306
  };
791
1307
  export {
792
- BPTree,
793
- InMemoryStoreStrategy,
1308
+ BPTreeAsync,
1309
+ BPTreeSync,
1310
+ InMemoryStoreStrategyAsync,
1311
+ InMemoryStoreStrategySync,
794
1312
  NumericComparator,
795
- SerializeStrategy,
1313
+ SerializeStrategyAsync,
1314
+ SerializeStrategySync,
796
1315
  StringComparator,
797
1316
  ValueComparator
798
1317
  };