serializable-bptree 2.0.0 → 3.1.0

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