serializable-bptree 1.1.0 → 3.0.0

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