serializable-bptree 1.1.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,83 +20,206 @@ 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 {
35
+ // src/base/BPTree.ts
36
+ var BPTree = class {
37
+ strategy;
34
38
  comparator;
35
- constructor(comparator) {
39
+ nodes;
40
+ order;
41
+ data;
42
+ root;
43
+ _nodeCreateBuffer;
44
+ _nodeUpdateBuffer;
45
+ _headBuffer;
46
+ verifierMap = {
47
+ gt: (nv, v) => this.comparator.isHigher(nv, v),
48
+ gte: (nv, v) => this.comparator.isHigher(nv, v) || this.comparator.isSame(nv, v),
49
+ lt: (nv, v) => this.comparator.isLower(nv, v),
50
+ lte: (nv, v) => this.comparator.isLower(nv, v) || this.comparator.isSame(nv, v),
51
+ equal: (nv, v) => this.comparator.isSame(nv, v),
52
+ notEqual: (nv, v) => this.comparator.isSame(nv, v) === false,
53
+ like: (nv, v) => {
54
+ const nodeValue = nv.toString();
55
+ const value = v.toString();
56
+ const pattern = value.replace(/%/g, ".*").replace(/_/g, ".");
57
+ const regex = new RegExp(`^${pattern}$`, "i");
58
+ return regex.test(nodeValue);
59
+ }
60
+ };
61
+ verifierStartNode = {
62
+ gt: (v) => this.insertableNode(v),
63
+ gte: (v) => this.insertableNode(v),
64
+ lt: (v) => this.insertableNode(v),
65
+ lte: (v) => this.insertableNode(v),
66
+ equal: (v) => this.insertableNode(v),
67
+ notEqual: (v) => this.leftestNode(),
68
+ like: (v) => this.leftestNode()
69
+ };
70
+ verifierDirection = {
71
+ gt: 1,
72
+ gte: 1,
73
+ lt: -1,
74
+ lte: -1,
75
+ equal: 1,
76
+ notEqual: 1,
77
+ like: 1
78
+ };
79
+ verifierFullSearch = {
80
+ gt: false,
81
+ gte: false,
82
+ lt: false,
83
+ lte: false,
84
+ equal: false,
85
+ notEqual: true,
86
+ like: true
87
+ };
88
+ get headState() {
89
+ const root = this.root.id;
90
+ const order = this.order;
91
+ const data = this.data;
92
+ return {
93
+ root,
94
+ order,
95
+ data
96
+ };
97
+ }
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;
36
104
  this.comparator = comparator;
37
105
  }
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;
106
+ _insertAtLeaf(node, key, value) {
107
+ if (node.values.length) {
108
+ for (let i = 0, len = node.values.length; i < len; i++) {
109
+ const nValue = node.values[i];
110
+ if (this.comparator.isSame(value, nValue)) {
111
+ const keys = node.keys[i];
112
+ keys.push(key);
113
+ this.bufferForNodeUpdate(node);
114
+ break;
115
+ } else if (this.comparator.isLower(value, nValue)) {
116
+ node.values.splice(i, 0, value);
117
+ node.keys.splice(i, 0, [key]);
118
+ this.bufferForNodeUpdate(node);
119
+ break;
120
+ } else if (i + 1 === node.values.length) {
121
+ node.values.push(value);
122
+ node.keys.push([key]);
123
+ this.bufferForNodeUpdate(node);
124
+ break;
125
+ }
50
126
  }
127
+ } else {
128
+ node.values = [value];
129
+ node.keys = [[key]];
130
+ this.bufferForNodeUpdate(node);
51
131
  }
52
- return -1;
53
132
  }
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)) {
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);
156
+ }
157
+ _getPairsRightToLeft(value, startNode, fullSearch, comparator) {
158
+ const pairs = [];
159
+ let node = startNode;
160
+ let done = false;
161
+ let found = false;
162
+ while (!done) {
163
+ let i = node.values.length;
164
+ while (i--) {
165
+ const nValue = node.values[i];
166
+ const keys = node.keys[i];
167
+ if (comparator(nValue, value)) {
168
+ found = true;
169
+ let j = keys.length;
170
+ while (j--) {
171
+ pairs.push({ key: keys[j], value: nValue });
172
+ }
173
+ } else if (found && !fullSearch) {
174
+ done = true;
175
+ break;
176
+ }
177
+ }
178
+ if (!node.prev) {
179
+ done = true;
61
180
  break;
62
181
  }
63
- i--;
182
+ node = this.getNode(node.prev);
64
183
  }
65
- return i;
184
+ return pairs.reverse();
66
185
  }
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)) {
186
+ _getPairsLeftToRight(value, startNode, fullSearch, comparator) {
187
+ const pairs = [];
188
+ let node = startNode;
189
+ let done = false;
190
+ let found = false;
191
+ while (!done) {
192
+ for (let i = 0, len = node.values.length; i < len; i++) {
193
+ const nValue = node.values[i];
194
+ const keys = node.keys[i];
195
+ if (comparator(nValue, value)) {
196
+ found = true;
197
+ for (const key of keys) {
198
+ pairs.push({ key, value: nValue });
199
+ }
200
+ } else if (found && !fullSearch) {
201
+ done = true;
202
+ break;
203
+ }
204
+ }
205
+ if (!node.next) {
206
+ done = true;
75
207
  break;
76
208
  }
77
- i++;
209
+ node = this.getNode(node.next);
78
210
  }
79
- return i;
211
+ return pairs;
80
212
  }
81
- range(array, value) {
82
- const left = this.leftest(array, value);
83
- const right = this.rightest(array, value) + 1;
84
- return [left, right];
213
+ getPairs(value, startNode, fullSearch, comparator, direction) {
214
+ switch (direction) {
215
+ case -1:
216
+ return this._getPairsRightToLeft(value, startNode, fullSearch, comparator);
217
+ case 1:
218
+ return this._getPairsLeftToRight(value, startNode, fullSearch, comparator);
219
+ default:
220
+ throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
221
+ }
85
222
  }
86
- };
87
-
88
- // src/BPTree.ts
89
- var BPTree = class {
90
- strategy;
91
- comparator;
92
- search;
93
- order;
94
- nodes;
95
- data;
96
- root;
97
- _creates;
98
- _updates;
99
- _updatedHead;
100
223
  _createNodeId() {
101
224
  const id = this.strategy.id();
102
225
  if (id === 0) {
@@ -104,7 +227,7 @@ var BPTree = class {
104
227
  }
105
228
  return id;
106
229
  }
107
- _createNode(keys, values, leaf = false, parent = 0, next = 0) {
230
+ _createNode(keys, values, leaf = false, parent = 0, next = 0, prev = 0) {
108
231
  const id = this._createNodeId();
109
232
  const node = {
110
233
  id,
@@ -112,128 +235,209 @@ var BPTree = class {
112
235
  values,
113
236
  leaf,
114
237
  parent,
115
- next
238
+ next,
239
+ prev
116
240
  };
117
241
  this.nodes.set(id, node);
118
242
  return node;
119
243
  }
120
- /**
121
- * @param strategy An instance of a strategy that manages the read/write state of a node.
122
- * @param comparator An instance of a comparator that compares the size of values.
123
- */
124
- constructor(strategy, comparator) {
125
- const head = strategy.readHead();
126
- this._creates = /* @__PURE__ */ new Map();
127
- this._updates = /* @__PURE__ */ new Map();
128
- this._updatedHead = null;
129
- this.nodes = /* @__PURE__ */ new Map();
130
- this.search = new BinarySearch(comparator);
131
- this.strategy = strategy;
132
- this.comparator = comparator;
133
- if (head === null) {
134
- this.order = strategy.order;
135
- this.data = {};
136
- this.root = this._createNode([], [], true);
137
- this._setHeadUpdate(this._headState);
138
- this._setCreates(this.root);
139
- this._emitHeadUpdates();
140
- this._emitCreates();
141
- } else {
142
- const { root, order, data } = head;
143
- this.order = order;
144
- this.data = data ?? {};
145
- this.root = this.getNode(root);
146
- }
147
- if (this.order < 3) {
148
- throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
149
- }
150
- }
151
- get _headState() {
152
- const root = this.root.id;
153
- const order = this.order;
154
- const data = this.data;
155
- return {
156
- root,
157
- order,
158
- data
159
- };
160
- }
161
- _setHeadUpdate(head) {
162
- this._updatedHead = head;
163
- }
164
- _setCreates(node) {
165
- this._creates.set(node.id, node);
166
- }
167
- _setUpdates(node) {
168
- this._updates.set(node.id, node);
169
- }
170
- _emitHeadUpdates() {
171
- if (this._updatedHead !== null) {
172
- this.strategy.writeHead(this._updatedHead);
173
- }
174
- this._updatedHead = null;
175
- }
176
- _emitCreates() {
177
- for (const node of this._creates.values()) {
178
- this.strategy.write(node.id, node);
179
- }
180
- this._creates.clear();
181
- }
182
- _emitUpdates() {
183
- for (const node of this._updates.values()) {
184
- this.strategy.write(node.id, node);
185
- }
186
- this._updates.clear();
187
- }
188
- getNode(id) {
189
- if (!this.nodes.has(id)) {
190
- this.nodes.set(id, this.strategy.read(id));
191
- }
192
- return this.nodes.get(id);
193
- }
194
- leftestNode() {
195
- let node = this.root;
196
- while (!node.leaf) {
197
- const keys = node.keys;
198
- node = this.getNode(keys[0]);
199
- }
200
- return node;
201
- }
202
- _insertableNode(value) {
203
- let node = this.root;
204
- while (!node.leaf) {
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
+ }
205
254
  for (let i = 0, len = node.values.length; i < len; i++) {
206
255
  const nValue = node.values[i];
207
- const k = node.keys;
208
256
  if (this.comparator.isSame(value, nValue)) {
209
- node = this.getNode(k[i + 1]);
210
- break;
211
- } else if (this.comparator.isLower(value, nValue)) {
212
- node = this.getNode(k[i]);
213
- break;
214
- } else if (i + 1 === node.values.length) {
215
- node = this.getNode(k[i + 1]);
257
+ node.values.splice(i, 1);
258
+ this.bufferForNodeUpdate(node);
216
259
  break;
217
260
  }
218
261
  }
219
262
  }
220
- return node;
221
- }
222
- /**
223
- * It returns whether there is a value in the tree.
224
- * @param key The key value to search for.
225
- * @param value The value to search for.
226
- */
227
- exists(key, value) {
228
- const node = this._insertableNode(value);
229
- for (let i = 0, len = node.values.length; i < len; i++) {
230
- const nValue = node.values[i];
231
- if (this.comparator.isSame(value, nValue)) {
232
- const keys = node.keys[i];
233
- return keys.includes(key);
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
+ }
234
439
  }
235
440
  }
236
- return false;
237
441
  }
238
442
  _insertAtLeaf(node, key, value) {
239
443
  if (node.values.length) {
@@ -242,24 +446,24 @@ var BPTree = class {
242
446
  if (this.comparator.isSame(value, nValue)) {
243
447
  const keys = node.keys[i];
244
448
  keys.push(key);
245
- this._setUpdates(node);
449
+ this.bufferForNodeUpdate(node);
246
450
  break;
247
451
  } else if (this.comparator.isLower(value, nValue)) {
248
452
  node.values.splice(i, 0, value);
249
453
  node.keys.splice(i, 0, [key]);
250
- this._setUpdates(node);
454
+ this.bufferForNodeUpdate(node);
251
455
  break;
252
456
  } else if (i + 1 === node.values.length) {
253
457
  node.values.push(value);
254
458
  node.keys.push([key]);
255
- this._setUpdates(node);
459
+ this.bufferForNodeUpdate(node);
256
460
  break;
257
461
  }
258
462
  }
259
463
  } else {
260
464
  node.values = [value];
261
465
  node.keys = [[key]];
262
- this._setUpdates(node);
466
+ this.bufferForNodeUpdate(node);
263
467
  }
264
468
  }
265
469
  _insertInParent(node, value, pointer) {
@@ -268,10 +472,10 @@ var BPTree = class {
268
472
  this.root = root;
269
473
  node.parent = root.id;
270
474
  pointer.parent = root.id;
271
- this._setHeadUpdate(this._headState);
272
- this._setCreates(root);
273
- this._setUpdates(node);
274
- this._setUpdates(pointer);
475
+ this.bufferForHeadUpdate(this.headState);
476
+ this.bufferForNodeCreate(root);
477
+ this.bufferForNodeUpdate(node);
478
+ this.bufferForNodeUpdate(pointer);
275
479
  return;
276
480
  }
277
481
  const parentNode = this.getNode(node.parent);
@@ -280,7 +484,7 @@ var BPTree = class {
280
484
  if (nKeys === node.id) {
281
485
  parentNode.values.splice(i, 0, value);
282
486
  parentNode.keys.splice(i + 1, 0, pointer.id);
283
- this._setUpdates(parentNode);
487
+ this.bufferForNodeUpdate(parentNode);
284
488
  if (parentNode.keys.length > this.order) {
285
489
  const parentPointer = this._createNode([], []);
286
490
  parentPointer.parent = parentNode.parent;
@@ -297,259 +501,264 @@ var BPTree = class {
297
501
  for (const k of parentNode.keys) {
298
502
  const node2 = this.getNode(k);
299
503
  node2.parent = parentNode.id;
300
- this._setUpdates(node2);
504
+ this.bufferForNodeUpdate(node2);
301
505
  }
302
506
  for (const k of parentPointer.keys) {
303
507
  const node2 = this.getNode(k);
304
508
  node2.parent = parentPointer.id;
305
- this._setUpdates(node2);
509
+ this.bufferForNodeUpdate(node2);
306
510
  }
307
511
  this._insertInParent(parentNode, midValue, parentPointer);
308
- this._setCreates(parentPointer);
309
- this._setUpdates(parentNode);
512
+ this.bufferForNodeCreate(parentPointer);
513
+ this.bufferForNodeUpdate(parentNode);
310
514
  }
311
515
  }
312
516
  }
313
517
  }
314
- _equalCondition(condition) {
315
- return Object.prototype.hasOwnProperty.call(condition, "equal");
316
- }
317
- _notEqualCondition(condition) {
318
- return Object.prototype.hasOwnProperty.call(condition, "notEqual");
319
- }
320
- _onlyGtCondition(condition) {
321
- return Object.prototype.hasOwnProperty.call(condition, "gt") && !Object.prototype.hasOwnProperty.call(condition, "lt");
322
- }
323
- _onlyLtCondition(condition) {
324
- return Object.prototype.hasOwnProperty.call(condition, "lt") && !Object.prototype.hasOwnProperty.call(condition, "gt");
325
- }
326
- _rangeCondition(condition) {
327
- return Object.prototype.hasOwnProperty.call(condition, "gt") && Object.prototype.hasOwnProperty.call(condition, "lt");
328
- }
329
- _getKeysFromValue(value) {
330
- const keys = /* @__PURE__ */ new Set();
331
- const node = this._insertableNode(value);
332
- const [start, end] = this.search.range(node.values, value);
333
- if (start === -1) {
334
- return keys;
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);
335
533
  }
336
- for (let i = start; i < end; i++) {
337
- const pairKeys = node.keys[i];
338
- for (const key of pairKeys) {
339
- keys.add(key);
340
- }
534
+ if (this.order < 3) {
535
+ throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
341
536
  }
342
- return keys;
343
537
  }
344
- _getKeysFromNEValue(value) {
345
- const keys = /* @__PURE__ */ new Set();
346
- let node = this.leftestNode();
347
- let done = false;
348
- while (!done) {
349
- for (let i = 0, len = node.values.length; i < len; i++) {
350
- const nValue = node.values[i];
351
- const pairKeys = node.keys[i];
352
- if (this.comparator.isSame(nValue, value) === false) {
353
- for (const key of pairKeys) {
354
- keys.add(key);
355
- }
356
- }
357
- }
358
- if (!node.next) {
359
- done = true;
360
- break;
361
- }
362
- node = this.getNode(node.next);
538
+ getNode(id) {
539
+ if (!this.nodes.has(id)) {
540
+ this.nodes.set(id, this.strategy.read(id));
363
541
  }
364
- return keys;
542
+ return this.nodes.get(id);
365
543
  }
366
- _getKeysFromRange(gt, lt) {
367
- const keys = /* @__PURE__ */ new Set();
368
- let node = this._insertableNode(gt);
369
- let done = false;
370
- let found = false;
371
- while (!done) {
544
+ insertableNode(value) {
545
+ let node = this.root;
546
+ while (!node.leaf) {
372
547
  for (let i = 0, len = node.values.length; i < len; i++) {
373
548
  const nValue = node.values[i];
374
- const localKeys = node.keys[i];
375
- if (this.comparator.isHigher(nValue, gt) && this.comparator.isLower(nValue, lt)) {
376
- found = true;
377
- for (const key of localKeys) {
378
- keys.add(key);
379
- }
380
- } else if (found) {
381
- done = true;
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]);
382
558
  break;
383
559
  }
384
560
  }
385
- if (!node.next) {
386
- done = true;
387
- break;
388
- }
389
- node = this.getNode(node.next);
390
561
  }
391
- return keys;
562
+ return node;
392
563
  }
393
- _getKeysFromGt(gt) {
394
- const keys = /* @__PURE__ */ new Set();
395
- let node = this._insertableNode(gt);
396
- let done = false;
397
- let found = false;
398
- while (!done) {
399
- for (let i = 0, len = node.values.length; i < len; i++) {
400
- const nValue = node.values[i];
401
- const localKeys = node.keys[i];
402
- if (this.comparator.isHigher(nValue, gt)) {
403
- found = true;
404
- for (const key of localKeys) {
405
- keys.add(key);
406
- }
407
- } else if (found) {
408
- done = true;
409
- break;
410
- }
411
- }
412
- if (!node.next) {
413
- done = true;
414
- break;
415
- }
416
- node = this.getNode(node.next);
564
+ leftestNode() {
565
+ let node = this.root;
566
+ while (!node.leaf) {
567
+ const keys = node.keys;
568
+ node = this.getNode(keys[0]);
417
569
  }
418
- return keys;
570
+ return node;
419
571
  }
420
- _getKeysFromLt(lt) {
421
- const keys = /* @__PURE__ */ new Set();
422
- let node = this.leftestNode();
423
- let done = false;
424
- let found = false;
425
- while (!done) {
426
- for (let i = 0, len = node.values.length; i < len; i++) {
427
- const nValue = node.values[i];
428
- const localKeys = node.keys[i];
429
- if (this.comparator.isLower(nValue, lt)) {
430
- found = true;
431
- for (const key of localKeys) {
432
- keys.add(key);
433
- }
434
- } else if (found) {
435
- done = true;
436
- break;
437
- }
438
- }
439
- if (!node.next) {
440
- done = true;
441
- break;
442
- }
443
- node = this.getNode(node.next);
572
+ commitHeadBuffer() {
573
+ if (this._headBuffer !== null) {
574
+ this.strategy.writeHead(this._headBuffer);
444
575
  }
445
- return keys;
576
+ this.bufferForHeadUpdate(null);
446
577
  }
447
- _getPairsFromValue(value) {
448
- const node = this._insertableNode(value);
449
- const [start, end] = this.search.range(node.values, value);
450
- if (start === -1) {
451
- return [];
578
+ commitNodeCreateBuffer() {
579
+ for (const node of this._nodeCreateBuffer.values()) {
580
+ this.strategy.write(node.id, node);
452
581
  }
453
- const pairs = [];
454
- for (let i = start; i < end; i++) {
455
- const keys = node.keys[i];
456
- for (const key of keys) {
457
- pairs.push({ key, value });
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));
458
604
  }
459
605
  }
460
- return pairs;
606
+ return new Set(result ?? []);
461
607
  }
462
- _getPairsFromNEValue(value) {
463
- const pairs = [];
464
- let node = this.leftestNode();
465
- let done = false;
466
- while (!done) {
467
- for (let i = 0, len = node.values.length; i < len; i++) {
468
- const nValue = node.values[i];
469
- const keys = node.keys[i];
470
- if (this.comparator.isSame(nValue, value) === false) {
471
- for (const key of keys) {
472
- pairs.push({ key, value: nValue });
473
- }
474
- }
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));
475
622
  }
476
- if (!node.next) {
477
- done = true;
478
- break;
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);
479
649
  }
480
- node = this.getNode(node.next);
650
+ this._insertInParent(before, after.values[0], after);
651
+ this.bufferForNodeCreate(after);
652
+ this.bufferForNodeUpdate(before);
481
653
  }
482
- return pairs;
654
+ this.commitHeadBuffer();
655
+ this.commitNodeCreateBuffer();
656
+ this.commitNodeUpdateBuffer();
483
657
  }
484
- _getPairsFromRange(gt, lt) {
485
- const pairs = [];
486
- let node = this._insertableNode(gt);
487
- let done = false;
488
- let found = false;
489
- while (!done) {
490
- for (let i = 0, len = node.values.length; i < len; i++) {
491
- const nValue = node.values[i];
658
+ delete(key, value) {
659
+ const node = this.insertableNode(value);
660
+ let i = node.values.length;
661
+ while (i--) {
662
+ const nValue = node.values[i];
663
+ if (this.comparator.isSame(value, nValue)) {
492
664
  const keys = node.keys[i];
493
- if (this.comparator.isHigher(nValue, gt) && this.comparator.isLower(nValue, lt)) {
494
- found = true;
495
- for (const key of keys) {
496
- pairs.push({ key, value: nValue });
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);
497
679
  }
498
- } else if (found) {
499
- done = true;
500
- break;
501
680
  }
502
681
  }
503
- if (!node.next) {
504
- done = true;
505
- break;
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);
506
694
  }
507
- node = this.getNode(node.next);
508
695
  }
509
- return pairs;
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);
510
717
  }
511
- _getPairsFromGt(gt) {
718
+ async _getPairsRightToLeft(value, startNode, fullSearch, comparator) {
512
719
  const pairs = [];
513
- let node = this._insertableNode(gt);
720
+ let node = startNode;
514
721
  let done = false;
515
722
  let found = false;
516
723
  while (!done) {
517
- for (let i = 0, len = node.values.length; i < len; i++) {
724
+ let i = node.values.length;
725
+ while (i--) {
518
726
  const nValue = node.values[i];
519
727
  const keys = node.keys[i];
520
- if (this.comparator.isHigher(nValue, gt)) {
728
+ if (comparator(nValue, value)) {
521
729
  found = true;
522
- for (const key of keys) {
523
- pairs.push({ key, value: nValue });
730
+ let j = keys.length;
731
+ while (j--) {
732
+ pairs.push({ key: keys[j], value: nValue });
524
733
  }
525
- } else if (found) {
734
+ } else if (found && !fullSearch) {
526
735
  done = true;
527
736
  break;
528
737
  }
529
738
  }
530
- if (!node.next) {
739
+ if (!node.prev) {
531
740
  done = true;
532
741
  break;
533
742
  }
534
- node = this.getNode(node.next);
743
+ node = await this.getNode(node.prev);
535
744
  }
536
- return pairs;
745
+ return pairs.reverse();
537
746
  }
538
- _getPairsFromLt(lt) {
747
+ async _getPairsLeftToRight(value, startNode, fullSearch, comparator) {
539
748
  const pairs = [];
540
- let node = this.leftestNode();
749
+ let node = startNode;
541
750
  let done = false;
542
751
  let found = false;
543
752
  while (!done) {
544
753
  for (let i = 0, len = node.values.length; i < len; i++) {
545
754
  const nValue = node.values[i];
546
755
  const keys = node.keys[i];
547
- if (this.comparator.isLower(nValue, lt)) {
756
+ if (comparator(nValue, value)) {
548
757
  found = true;
549
758
  for (const key of keys) {
550
759
  pairs.push({ key, value: nValue });
551
760
  }
552
- } else if (found) {
761
+ } else if (found && !fullSearch) {
553
762
  done = true;
554
763
  break;
555
764
  }
@@ -558,125 +767,48 @@ var BPTree = class {
558
767
  done = true;
559
768
  break;
560
769
  }
561
- node = this.getNode(node.next);
770
+ node = await this.getNode(node.next);
562
771
  }
563
772
  return pairs;
564
773
  }
565
- /**
566
- * It searches for a key within the tree. The result is returned as an array sorted in ascending order based on the value.
567
- * The result is key set instance, and you can use the `gt`, `lt`, `equal`, `notEqual` condition statements.
568
- * This method operates much faster than first searching with `where` and then retrieving only the key list.
569
- * @param condition You can use the `gt`, `lt`, `equal`, `notEqual` condition statements.
570
- */
571
- keys(condition) {
572
- if (this._equalCondition(condition)) {
573
- return this._getKeysFromValue(condition.equal);
574
- } else if (this._notEqualCondition(condition)) {
575
- return this._getKeysFromNEValue(condition.notEqual);
576
- } else if (this._rangeCondition(condition)) {
577
- const { gt, lt } = condition;
578
- return this._getKeysFromRange(gt, lt);
579
- } else if (this._onlyGtCondition(condition)) {
580
- return this._getKeysFromGt(condition.gt);
581
- } else if (this._onlyLtCondition(condition)) {
582
- return this._getKeysFromLt(condition.lt);
583
- } else {
584
- throw new Error(`The 'condition' parameter is invalid.`);
585
- }
586
- }
587
- /**
588
- * It searches for a value within the tree. The result is returned as an array sorted in ascending order based on the value.
589
- * The result includes the key and value attributes, and you can use the `gt`, `lt`, `equal`, `notEqual` condition statements.
590
- * @param condition You can use the `gt`, `lt`, `equal`, `notEqual` condition statements.
591
- */
592
- where(condition) {
593
- if (this._equalCondition(condition)) {
594
- return this._getPairsFromValue(condition.equal);
595
- } else if (this._notEqualCondition(condition)) {
596
- return this._getPairsFromNEValue(condition.notEqual);
597
- } else if (this._rangeCondition(condition)) {
598
- const { gt, lt } = condition;
599
- return this._getPairsFromRange(gt, lt);
600
- } else if (this._onlyGtCondition(condition)) {
601
- return this._getPairsFromGt(condition.gt);
602
- } else if (this._onlyLtCondition(condition)) {
603
- return this._getPairsFromLt(condition.lt);
604
- } else {
605
- throw new Error(`The 'condition' parameter is invalid.`);
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}`);
606
782
  }
607
783
  }
608
- /**
609
- * You enter the key and value as a pair. You can later search for the pair by value.
610
- * This data is stored in the tree, sorted in ascending order of value.
611
- * @param key The key of the pair.
612
- * @param value The value of the pair.
613
- */
614
- insert(key, value) {
615
- const before = this._insertableNode(value);
616
- this._insertAtLeaf(before, key, value);
617
- if (before.values.length === this.order) {
618
- const after = this._createNode(
619
- [],
620
- [],
621
- true,
622
- before.parent,
623
- before.next
624
- );
625
- const mid = Math.ceil(this.order / 2) - 1;
626
- after.values = before.values.slice(mid + 1);
627
- after.keys = before.keys.slice(mid + 1);
628
- before.values = before.values.slice(0, mid + 1);
629
- before.keys = before.keys.slice(0, mid + 1);
630
- before.next = after.id;
631
- this._insertInParent(before, after.values[0], after);
632
- this._setCreates(after);
633
- this._setUpdates(before);
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.`);
634
788
  }
635
- this._emitHeadUpdates();
636
- this._emitCreates();
637
- this._emitUpdates();
789
+ return id;
638
790
  }
639
- /**
640
- * Deletes the pair that matches the key and value.
641
- * @param key The key of the pair.
642
- * @param value The value of the pair.
643
- */
644
- delete(key, value) {
645
- const node = this._insertableNode(value);
646
- let i = node.values.length;
647
- while (i--) {
648
- const nValue = node.values[i];
649
- if (this.comparator.isSame(value, nValue)) {
650
- const keys = node.keys[i];
651
- if (keys.includes(key)) {
652
- if (keys.length > 1) {
653
- keys.splice(keys.indexOf(key), 1);
654
- this._setUpdates(node);
655
- } else if (node === this.root) {
656
- node.values.splice(i, 1);
657
- node.keys.splice(i, 1);
658
- this._setUpdates(node);
659
- } else {
660
- keys.splice(keys.indexOf(key), 1);
661
- node.keys.splice(i, 1);
662
- node.values.splice(node.values.indexOf(value), 1);
663
- this._deleteEntry(node, key, value);
664
- this._setUpdates(node);
665
- }
666
- }
667
- }
668
- }
669
- this._emitHeadUpdates();
670
- this._emitCreates();
671
- this._emitUpdates();
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;
672
804
  }
673
- _deleteEntry(node, key, value) {
805
+ async _deleteEntry(node, key, value) {
674
806
  if (!node.leaf) {
675
807
  for (let i = 0, len = node.keys.length; i < len; i++) {
676
808
  const nKey = node.keys[i];
677
809
  if (nKey === key) {
678
810
  node.keys.splice(i, 1);
679
- this._setUpdates(node);
811
+ this.bufferForNodeUpdate(node);
680
812
  break;
681
813
  }
682
814
  }
@@ -684,37 +816,37 @@ var BPTree = class {
684
816
  const nValue = node.values[i];
685
817
  if (this.comparator.isSame(value, nValue)) {
686
818
  node.values.splice(i, 1);
687
- this._setUpdates(node);
819
+ this.bufferForNodeUpdate(node);
688
820
  break;
689
821
  }
690
822
  }
691
823
  }
692
824
  if (this.root === node && node.keys.length === 1) {
693
825
  const keys = node.keys;
694
- this.root = this.getNode(keys[0]);
826
+ this.root = await this.getNode(keys[0]);
695
827
  this.root.parent = 0;
696
- this._setHeadUpdate(this._headState);
697
- this._setUpdates(this.root);
828
+ this.bufferForHeadUpdate(this.headState);
829
+ this.bufferForNodeUpdate(this.root);
698
830
  return;
699
831
  } else if (this.root === node) {
700
832
  return;
701
833
  } else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
702
834
  let isPredecessor = false;
703
- let parentNode = this.getNode(node.parent);
835
+ let parentNode = await this.getNode(node.parent);
704
836
  let prevNode = null;
705
837
  let nextNode = null;
706
- let prevK = null;
707
- let postK = null;
838
+ let prevValue = null;
839
+ let postValue = null;
708
840
  for (let i = 0, len = parentNode.keys.length; i < len; i++) {
709
841
  const nKey = parentNode.keys[i];
710
842
  if (nKey === node.id) {
711
843
  if (i > 0) {
712
- prevNode = this.getNode(parentNode.keys[i - 1]);
713
- prevK = parentNode.values[i - 1];
844
+ prevNode = await this.getNode(parentNode.keys[i - 1]);
845
+ prevValue = parentNode.values[i - 1];
714
846
  }
715
847
  if (i < parentNode.keys.length - 1) {
716
- nextNode = this.getNode(parentNode.keys[i + 1]);
717
- postK = parentNode.values[i];
848
+ nextNode = await this.getNode(parentNode.keys[i + 1]);
849
+ postValue = parentNode.values[i];
718
850
  }
719
851
  }
720
852
  }
@@ -722,19 +854,19 @@ var BPTree = class {
722
854
  let guess;
723
855
  if (prevNode === null) {
724
856
  pointer = nextNode;
725
- guess = postK;
857
+ guess = postValue;
726
858
  } else if (nextNode === null) {
727
859
  isPredecessor = true;
728
860
  pointer = prevNode;
729
- guess = prevK;
861
+ guess = prevValue;
730
862
  } else {
731
863
  if (node.values.length + nextNode.values.length < this.order) {
732
864
  pointer = nextNode;
733
- guess = postK;
865
+ guess = postValue;
734
866
  } else {
735
867
  isPredecessor = true;
736
868
  pointer = prevNode;
737
- guess = prevK;
869
+ guess = prevValue;
738
870
  }
739
871
  }
740
872
  if (node.values.length + pointer.values.length < this.order) {
@@ -748,18 +880,32 @@ var BPTree = class {
748
880
  pointer.values.push(guess);
749
881
  } else {
750
882
  pointer.next = node.next;
883
+ pointer.prev = node.id;
884
+ if (pointer.next) {
885
+ const n = await this.getNode(node.next);
886
+ n.prev = pointer.id;
887
+ this.bufferForNodeUpdate(n);
888
+ }
889
+ if (pointer.prev) {
890
+ const n = await this.getNode(node.id);
891
+ n.next = pointer.id;
892
+ this.bufferForNodeUpdate(n);
893
+ }
894
+ if (isPredecessor) {
895
+ pointer.prev = 0;
896
+ }
751
897
  }
752
898
  pointer.values.push(...node.values);
753
899
  if (!pointer.leaf) {
754
900
  const keys = pointer.keys;
755
901
  for (const key2 of keys) {
756
- const node2 = this.getNode(key2);
902
+ const node2 = await this.getNode(key2);
757
903
  node2.parent = pointer.id;
758
- this._setUpdates(node2);
904
+ this.bufferForNodeUpdate(node2);
759
905
  }
760
906
  }
761
- this._deleteEntry(this.getNode(node.parent), node.id, guess);
762
- this._setUpdates(pointer);
907
+ await this._deleteEntry(await this.getNode(node.parent), node.id, guess);
908
+ this.bufferForNodeUpdate(pointer);
763
909
  } else {
764
910
  if (isPredecessor) {
765
911
  let pointerPm;
@@ -769,12 +915,12 @@ var BPTree = class {
769
915
  pointerKm = pointer.values.splice(-1)[0];
770
916
  node.keys = [pointerPm, ...node.keys];
771
917
  node.values = [guess, ...node.values];
772
- parentNode = this.getNode(node.parent);
918
+ parentNode = await this.getNode(node.parent);
773
919
  for (let i = 0, len = parentNode.values.length; i < len; i++) {
774
920
  const nValue = parentNode.values[i];
775
921
  if (this.comparator.isSame(guess, nValue)) {
776
922
  parentNode.values[i] = pointerKm;
777
- this._setUpdates(parentNode);
923
+ this.bufferForNodeUpdate(parentNode);
778
924
  break;
779
925
  }
780
926
  }
@@ -783,18 +929,18 @@ var BPTree = class {
783
929
  pointerKm = pointer.values.splice(-1)[0];
784
930
  node.keys = [pointerPm, ...node.keys];
785
931
  node.values = [pointerKm, ...node.values];
786
- parentNode = this.getNode(node.parent);
932
+ parentNode = await this.getNode(node.parent);
787
933
  for (let i = 0, len = parentNode.values.length; i < len; i++) {
788
934
  const nValue = parentNode.values[i];
789
935
  if (this.comparator.isSame(guess, nValue)) {
790
936
  parentNode.values[i] = pointerKm;
791
- this._setUpdates(parentNode);
937
+ this.bufferForNodeUpdate(parentNode);
792
938
  break;
793
939
  }
794
940
  }
795
941
  }
796
- this._setUpdates(node);
797
- this._setUpdates(pointer);
942
+ this.bufferForNodeUpdate(node);
943
+ this.bufferForNodeUpdate(pointer);
798
944
  } else {
799
945
  let pointerP0;
800
946
  let pointerK0;
@@ -803,12 +949,12 @@ var BPTree = class {
803
949
  pointerK0 = pointer.values.splice(0, 1)[0];
804
950
  node.keys = [...node.keys, pointerP0];
805
951
  node.values = [...node.values, guess];
806
- parentNode = this.getNode(node.parent);
952
+ parentNode = await this.getNode(node.parent);
807
953
  for (let i = 0, len = parentNode.values.length; i < len; i++) {
808
954
  const nValue = parentNode.values[i];
809
955
  if (this.comparator.isSame(guess, nValue)) {
810
956
  parentNode.values[i] = pointerK0;
811
- this._setUpdates(parentNode);
957
+ this.bufferForNodeUpdate(parentNode);
812
958
  break;
813
959
  }
814
960
  }
@@ -817,72 +963,299 @@ var BPTree = class {
817
963
  pointerK0 = pointer.values.splice(0, 1)[0];
818
964
  node.keys = [...node.keys, pointerP0];
819
965
  node.values = [...node.values, pointerK0];
820
- parentNode = this.getNode(node.parent);
966
+ parentNode = await this.getNode(node.parent);
821
967
  for (let i = 0, len = parentNode.values.length; i < len; i++) {
822
968
  const nValue = parentNode.values[i];
823
969
  if (this.comparator.isSame(guess, nValue)) {
824
970
  parentNode.values[i] = pointer.values[0];
825
- this._setUpdates(parentNode);
971
+ this.bufferForNodeUpdate(parentNode);
826
972
  break;
827
973
  }
828
974
  }
829
975
  }
830
- this._setUpdates(node);
831
- this._setUpdates(pointer);
976
+ this.bufferForNodeUpdate(node);
977
+ this.bufferForNodeUpdate(pointer);
832
978
  }
833
979
  if (!pointer.leaf) {
834
980
  for (const key2 of pointer.keys) {
835
- const n = this.getNode(key2);
981
+ const n = await this.getNode(key2);
836
982
  n.parent = pointer.id;
837
- this._setUpdates(n);
983
+ this.bufferForNodeUpdate(n);
838
984
  }
839
985
  }
840
986
  if (!node.leaf) {
841
987
  for (const key2 of node.keys) {
842
- const n = this.getNode(key2);
988
+ const n = await this.getNode(key2);
843
989
  n.parent = node.id;
844
- this._setUpdates(n);
990
+ this.bufferForNodeUpdate(n);
845
991
  }
846
992
  }
847
993
  if (!parentNode.leaf) {
848
994
  for (const key2 of parentNode.keys) {
849
- const n = this.getNode(key2);
995
+ const n = await this.getNode(key2);
850
996
  n.parent = parentNode.id;
851
- this._setUpdates(n);
997
+ this.bufferForNodeUpdate(n);
852
998
  }
853
999
  }
854
1000
  }
855
1001
  }
856
1002
  }
857
- /**
858
- * Returns the user-defined data stored in the head of the tree.
859
- * 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 `{}`.
860
- * @returns User-defined data stored in the head of the tree.
861
- */
862
- getHeadData() {
863
- 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
+ }
864
1051
  }
865
- /**
866
- * Inserts user-defined data into the head of the tree.
867
- * This feature is useful when you need to store separate, non-volatile information in the tree.
868
- * For example, you can store information such as the last update time and the number of insertions.
869
- * @param data User-defined data to be stored in the head of the tree.
870
- */
871
- 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) {
872
1233
  this.data = data;
873
- this._updatedHead = this._headState;
874
- 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;
875
1244
  }
876
1245
  };
877
1246
 
878
- // src/SerializeStrategy.ts
1247
+ // src/base/SerializeStrategy.ts
879
1248
  var SerializeStrategy = class {
880
1249
  order;
881
1250
  constructor(order) {
882
1251
  this.order = order;
883
1252
  }
884
1253
  };
885
- var InMemoryStoreStrategy = class extends SerializeStrategy {
1254
+
1255
+ // src/SerializeStrategySync.ts
1256
+ var SerializeStrategySync = class extends SerializeStrategy {
1257
+ };
1258
+ var InMemoryStoreStrategySync = class extends SerializeStrategySync {
886
1259
  data;
887
1260
  constructor(order) {
888
1261
  super(order);
@@ -911,6 +1284,38 @@ var InMemoryStoreStrategy = class extends SerializeStrategy {
911
1284
  }
912
1285
  };
913
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
+
914
1319
  // src/ValueComparator.ts
915
1320
  var ValueComparator = class {
916
1321
  isLower(value, than) {