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