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