serializable-bptree 5.0.5 → 5.1.1

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.
@@ -27,16 +27,167 @@ var StringComparator = class extends ValueComparator {
27
27
  }
28
28
  };
29
29
 
30
- // src/utils/InvertedWeakMap.ts
30
+ // node_modules/cache-entanglement/dist/esm/index.mjs
31
+ var __create = Object.create;
32
+ var __defProp = Object.defineProperty;
33
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
34
+ var __getOwnPropNames = Object.getOwnPropertyNames;
35
+ var __getProtoOf = Object.getPrototypeOf;
36
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
37
+ var __commonJS = (cb, mod) => function __require() {
38
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
39
+ };
40
+ var __copyProps = (to, from, except, desc) => {
41
+ if (from && typeof from === "object" || typeof from === "function") {
42
+ for (let key of __getOwnPropNames(from))
43
+ if (!__hasOwnProp.call(to, key) && key !== except)
44
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
45
+ }
46
+ return to;
47
+ };
48
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
49
+ // If the importer is in node compatibility mode or this is not an ESM
50
+ // file that has been converted to a CommonJS file using a Babel-
51
+ // compatible transform (i.e. "__esModule" has not been set), then set
52
+ // "default" to the CommonJS "module.exports" for node compatibility.
53
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
54
+ mod
55
+ ));
56
+ var require_ms = __commonJS({
57
+ "node_modules/ms/index.js"(exports, module) {
58
+ var s = 1e3;
59
+ var m = s * 60;
60
+ var h = m * 60;
61
+ var d = h * 24;
62
+ var w = d * 7;
63
+ var y = d * 365.25;
64
+ module.exports = function(val, options) {
65
+ options = options || {};
66
+ var type = typeof val;
67
+ if (type === "string" && val.length > 0) {
68
+ return parse(val);
69
+ } else if (type === "number" && isFinite(val)) {
70
+ return options.long ? fmtLong(val) : fmtShort(val);
71
+ }
72
+ throw new Error(
73
+ "val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
74
+ );
75
+ };
76
+ function parse(str) {
77
+ str = String(str);
78
+ if (str.length > 100) {
79
+ return;
80
+ }
81
+ var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
82
+ str
83
+ );
84
+ if (!match) {
85
+ return;
86
+ }
87
+ var n = parseFloat(match[1]);
88
+ var type = (match[2] || "ms").toLowerCase();
89
+ switch (type) {
90
+ case "years":
91
+ case "year":
92
+ case "yrs":
93
+ case "yr":
94
+ case "y":
95
+ return n * y;
96
+ case "weeks":
97
+ case "week":
98
+ case "w":
99
+ return n * w;
100
+ case "days":
101
+ case "day":
102
+ case "d":
103
+ return n * d;
104
+ case "hours":
105
+ case "hour":
106
+ case "hrs":
107
+ case "hr":
108
+ case "h":
109
+ return n * h;
110
+ case "minutes":
111
+ case "minute":
112
+ case "mins":
113
+ case "min":
114
+ case "m":
115
+ return n * m;
116
+ case "seconds":
117
+ case "second":
118
+ case "secs":
119
+ case "sec":
120
+ case "s":
121
+ return n * s;
122
+ case "milliseconds":
123
+ case "millisecond":
124
+ case "msecs":
125
+ case "msec":
126
+ case "ms":
127
+ return n;
128
+ default:
129
+ return void 0;
130
+ }
131
+ }
132
+ function fmtShort(ms2) {
133
+ var msAbs = Math.abs(ms2);
134
+ if (msAbs >= d) {
135
+ return Math.round(ms2 / d) + "d";
136
+ }
137
+ if (msAbs >= h) {
138
+ return Math.round(ms2 / h) + "h";
139
+ }
140
+ if (msAbs >= m) {
141
+ return Math.round(ms2 / m) + "m";
142
+ }
143
+ if (msAbs >= s) {
144
+ return Math.round(ms2 / s) + "s";
145
+ }
146
+ return ms2 + "ms";
147
+ }
148
+ function fmtLong(ms2) {
149
+ var msAbs = Math.abs(ms2);
150
+ if (msAbs >= d) {
151
+ return plural(ms2, msAbs, d, "day");
152
+ }
153
+ if (msAbs >= h) {
154
+ return plural(ms2, msAbs, h, "hour");
155
+ }
156
+ if (msAbs >= m) {
157
+ return plural(ms2, msAbs, m, "minute");
158
+ }
159
+ if (msAbs >= s) {
160
+ return plural(ms2, msAbs, s, "second");
161
+ }
162
+ return ms2 + " ms";
163
+ }
164
+ function plural(ms2, msAbs, n, name) {
165
+ var isPlural = msAbs >= n * 1.5;
166
+ return Math.round(ms2 / n) + " " + name + (isPlural ? "s" : "");
167
+ }
168
+ }
169
+ });
170
+ var import_ms = __toESM(require_ms());
31
171
  var InvertedWeakMap = class {
32
172
  _map;
173
+ _keepAlive;
174
+ _timeouts;
33
175
  _registry;
34
- constructor() {
176
+ _lifespan;
177
+ constructor(option) {
178
+ const { lifespan } = option;
179
+ this._lifespan = lifespan;
35
180
  this._map = /* @__PURE__ */ new Map();
36
- this._registry = new FinalizationRegistry((key) => this._map.delete(key));
181
+ this._keepAlive = /* @__PURE__ */ new Map();
182
+ this._timeouts = /* @__PURE__ */ new Map();
183
+ this._registry = new FinalizationRegistry((key) => {
184
+ this._stopExpire(key, true);
185
+ this._map.delete(key);
186
+ });
37
187
  }
38
188
  clear() {
39
- return this._map.clear();
189
+ this._keepAlive.clear();
190
+ this._map.clear();
40
191
  }
41
192
  delete(key) {
42
193
  const ref = this._map.get(key);
@@ -46,6 +197,8 @@ var InvertedWeakMap = class {
46
197
  this._registry.unregister(raw);
47
198
  }
48
199
  }
200
+ this._stopExpire(key, true);
201
+ this._keepAlive.delete(key);
49
202
  return this._map.delete(key);
50
203
  }
51
204
  get(key) {
@@ -57,8 +210,39 @@ var InvertedWeakMap = class {
57
210
  set(key, value) {
58
211
  this._map.set(key, new WeakRef(value));
59
212
  this._registry.register(value, key);
213
+ if (this._lifespan > 0) {
214
+ this._stopExpire(key, true);
215
+ this._startExpire(key, value);
216
+ }
60
217
  return this;
61
218
  }
219
+ extendExpire(key) {
220
+ if (!(this._lifespan > 0)) {
221
+ return;
222
+ }
223
+ if (!this._keepAlive.has(key)) {
224
+ return;
225
+ }
226
+ this._stopExpire(key, false);
227
+ this._startExpire(key, this._keepAlive.get(key));
228
+ }
229
+ _startExpire(key, value) {
230
+ this._keepAlive.set(key, value);
231
+ this._timeouts.set(key, setTimeout(() => {
232
+ this._keepAlive.delete(key);
233
+ }, this._lifespan));
234
+ }
235
+ _stopExpire(key, removeKeepAlive) {
236
+ if (!this._timeouts.has(key)) {
237
+ return;
238
+ }
239
+ const timeout = this._timeouts.get(key);
240
+ this._timeouts.delete(key);
241
+ clearTimeout(timeout);
242
+ if (removeKeepAlive) {
243
+ this._keepAlive.delete(key);
244
+ }
245
+ }
62
246
  get size() {
63
247
  return this._map.size;
64
248
  }
@@ -66,13 +250,226 @@ var InvertedWeakMap = class {
66
250
  return this._map.keys();
67
251
  }
68
252
  };
253
+ var CacheEntanglement = class {
254
+ creation;
255
+ beforeUpdateHook;
256
+ lifespan;
257
+ dependencies;
258
+ caches;
259
+ assignments;
260
+ parameters;
261
+ constructor(creation, option) {
262
+ option = option ?? {};
263
+ const {
264
+ dependencies,
265
+ lifespan,
266
+ beforeUpdateHook
267
+ } = option;
268
+ this.creation = creation;
269
+ this.beforeUpdateHook = beforeUpdateHook ?? (() => {
270
+ });
271
+ this.lifespan = this._normalizeMs(lifespan ?? 0);
272
+ this.assignments = [];
273
+ this.caches = new InvertedWeakMap({ lifespan: this.lifespan });
274
+ this.dependencies = dependencies ?? {};
275
+ this.parameters = {};
276
+ for (const name in this.dependencies) {
277
+ const dependency = this.dependencies[name];
278
+ if (!dependency.assignments.includes(this)) {
279
+ dependency.assignments.push(this);
280
+ }
281
+ }
282
+ }
283
+ _normalizeMs(time) {
284
+ if (typeof time === "string") {
285
+ return (0, import_ms.default)(time);
286
+ }
287
+ return time;
288
+ }
289
+ dependencyKey(key) {
290
+ const tokens = key.split("/");
291
+ tokens.pop();
292
+ return tokens.join("/");
293
+ }
294
+ /**
295
+ * Returns all keys stored in the instance.
296
+ */
297
+ keys() {
298
+ return this.caches.keys();
299
+ }
300
+ /**
301
+ * Deletes all cache values stored in the instance.
302
+ */
303
+ clear() {
304
+ for (const key of this.keys()) {
305
+ this.delete(key);
306
+ }
307
+ }
308
+ /**
309
+ * Checks if there is a cache value stored in the key within the instance.
310
+ * @param key The key to search.
311
+ */
312
+ exists(key) {
313
+ return this.caches.has(key);
314
+ }
315
+ /**
316
+ * Returns the cache value stored in the key within the instance. If the cached value is not present, an error is thrown.
317
+ * @param key The key to search.
318
+ */
319
+ get(key) {
320
+ if (!this.caches.has(key)) {
321
+ throw new Error(`Cache value not found: ${key}`);
322
+ }
323
+ return this.caches.get(key);
324
+ }
325
+ /**
326
+ * Deletes the cache value stored in the key within the instance.
327
+ * @param key The key to delete.
328
+ */
329
+ delete(key) {
330
+ this.caches.delete(key);
331
+ }
332
+ };
333
+ var CacheData = class _CacheData {
334
+ static StructuredClone = globalThis.structuredClone.bind(globalThis);
335
+ _value;
336
+ constructor(value) {
337
+ this._value = value;
338
+ }
339
+ /**
340
+ * This is cached data.
341
+ * It was generated at the time of caching, so there is a risk of modification if it's an object due to shallow copying.
342
+ * Therefore, if it's not a primitive type, please avoid using this value directly and use the `clone` method to use a copied version of the data.
343
+ */
344
+ get raw() {
345
+ return this._value;
346
+ }
347
+ /**
348
+ * The method returns a copied value of the cached data.
349
+ * You can pass a function as a parameter to copy the value. This parameter function should return the copied value.
350
+ *
351
+ * If no parameter is passed, it defaults to using Javascript's or \@ungap/structured-clone's `structuredClone` function to copy the value.
352
+ * If you prefer shallow copying instead of deep copying,
353
+ * you can use the default options `array-shallow-copy`, `object-shallow-copy` and `deep-copy`,
354
+ * which are replaced with functions to shallow copy arrays and objects, respectively. This is a syntactic sugar.
355
+ * @param strategy The function that returns the copied value.
356
+ * If you want to perform a shallow copy, simply pass the strings `array-shallow-copy` or `object-shallow-copy` for easy use.
357
+ * The default is `structuredClone`.
358
+ */
359
+ clone(strategy = "deep-copy") {
360
+ if (strategy && typeof strategy !== "string") {
361
+ return strategy(this.raw);
362
+ }
363
+ switch (strategy) {
364
+ case "array-shallow-copy":
365
+ return [].concat(this.raw);
366
+ case "object-shallow-copy":
367
+ return Object.assign({}, this.raw);
368
+ case "deep-copy":
369
+ default:
370
+ return _CacheData.StructuredClone(this.raw);
371
+ }
372
+ }
373
+ };
374
+ var CacheEntanglementSync = class extends CacheEntanglement {
375
+ constructor(creation, option) {
376
+ super(creation, option);
377
+ }
378
+ resolve(key, ...parameter) {
379
+ const resolved = {};
380
+ const dependencyKey = this.dependencyKey(key);
381
+ this.beforeUpdateHook(key, dependencyKey, ...parameter);
382
+ for (const name in this.dependencies) {
383
+ const dependency = this.dependencies[name];
384
+ if (!dependency.caches.has(key) && !dependency.caches.has(dependencyKey)) {
385
+ throw new Error(`The key '${key}' or '${dependencyKey}' has not been assigned yet in dependency '${name}'.`, {
386
+ cause: {
387
+ from: this
388
+ }
389
+ });
390
+ }
391
+ const dependencyValue = dependency.caches.get(key) ?? dependency.caches.get(dependencyKey);
392
+ resolved[name] = dependencyValue;
393
+ }
394
+ this.parameters[key] = parameter;
395
+ const value = new CacheData(this.creation(key, resolved, ...parameter));
396
+ this.caches.set(key, value);
397
+ return value;
398
+ }
399
+ cache(key, ...parameter) {
400
+ if (!this.caches.has(key)) {
401
+ this.resolve(key, ...parameter);
402
+ } else {
403
+ this.caches.extendExpire(key);
404
+ }
405
+ return this.caches.get(key);
406
+ }
407
+ update(key, ...parameter) {
408
+ this.resolve(key, ...parameter);
409
+ for (const t of this.assignments) {
410
+ const instance = t;
411
+ for (const cacheKey of instance.caches.keys()) {
412
+ if (cacheKey === key || cacheKey.startsWith(`${key}/`)) {
413
+ instance.update(cacheKey, ...instance.parameters[cacheKey]);
414
+ }
415
+ }
416
+ }
417
+ return this.caches.get(key);
418
+ }
419
+ };
420
+ var CacheEntanglementAsync = class extends CacheEntanglement {
421
+ constructor(creation, option) {
422
+ super(creation, option);
423
+ }
424
+ async resolve(key, ...parameter) {
425
+ const resolved = {};
426
+ const dependencyKey = this.dependencyKey(key);
427
+ await this.beforeUpdateHook(key, dependencyKey, ...parameter);
428
+ for (const name in this.dependencies) {
429
+ const dependency = this.dependencies[name];
430
+ if (!dependency.caches.has(key) && !dependency.caches.has(dependencyKey)) {
431
+ throw new Error(`The key '${key}' or '${dependencyKey}' has not been assigned yet in dependency '${name}'.`, {
432
+ cause: {
433
+ from: this
434
+ }
435
+ });
436
+ }
437
+ const dependencyValue = dependency.caches.get(key) ?? dependency.caches.get(dependencyKey);
438
+ resolved[name] = dependencyValue;
439
+ }
440
+ this.parameters[key] = parameter;
441
+ const value = new CacheData(await this.creation(key, resolved, ...parameter));
442
+ this.caches.set(key, value);
443
+ return value;
444
+ }
445
+ async cache(key, ...parameter) {
446
+ if (!this.caches.has(key)) {
447
+ await this.resolve(key, ...parameter);
448
+ } else {
449
+ this.caches.extendExpire(key);
450
+ }
451
+ return this.caches.get(key);
452
+ }
453
+ async update(key, ...parameter) {
454
+ await this.resolve(key, ...parameter);
455
+ for (const t of this.assignments) {
456
+ const instance = t;
457
+ for (const cacheKey of instance.caches.keys()) {
458
+ if (cacheKey === key || cacheKey.startsWith(`${key}/`)) {
459
+ await instance.update(cacheKey, ...instance.parameters[cacheKey]);
460
+ }
461
+ }
462
+ }
463
+ return this.caches.get(key);
464
+ }
465
+ };
69
466
 
70
467
  // src/base/BPTree.ts
71
468
  var BPTree = class {
72
469
  _cachedRegexp;
73
470
  strategy;
74
471
  comparator;
75
- nodes;
472
+ option;
76
473
  order;
77
474
  root;
78
475
  _strategyDirty;
@@ -86,15 +483,12 @@ var BPTree = class {
86
483
  lte: (nv, v) => this.comparator.isLower(nv, v) || this.comparator.isSame(nv, v),
87
484
  equal: (nv, v) => this.comparator.isSame(nv, v),
88
485
  notEqual: (nv, v) => this.comparator.isSame(nv, v) === false,
486
+ or: (nv, v) => this.ensureValues(v).some((v2) => this.comparator.isSame(nv, v2)),
89
487
  like: (nv, v) => {
90
488
  const nodeValue = this.comparator.match(nv);
91
489
  const value = this.comparator.match(v);
92
- if (!this._cachedRegexp.has(value)) {
93
- const pattern = value.replace(/%/g, ".*").replace(/_/g, ".");
94
- const regexp2 = new RegExp(`^${pattern}$`, "i");
95
- this._cachedRegexp.set(value, regexp2);
96
- }
97
- const regexp = this._cachedRegexp.get(value);
490
+ const cache = this._cachedRegexp.cache(value);
491
+ const regexp = cache.raw;
98
492
  return regexp.test(nodeValue);
99
493
  }
100
494
  };
@@ -105,8 +499,22 @@ var BPTree = class {
105
499
  lte: (v) => this.insertableNode(v),
106
500
  equal: (v) => this.insertableNode(v),
107
501
  notEqual: (v) => this.leftestNode(),
502
+ or: (v) => this.insertableNode(this.lowestValue(this.ensureValues(v))),
108
503
  like: (v) => this.leftestNode()
109
504
  };
505
+ verifierEndNode = {
506
+ gt: (v) => null,
507
+ gte: (v) => null,
508
+ lt: (v) => null,
509
+ lte: (v) => null,
510
+ equal: (v) => this.insertableEndNode(v, this.verifierDirection.equal),
511
+ notEqual: (v) => null,
512
+ or: (v) => this.insertableEndNode(
513
+ this.highestValue(this.ensureValues(v)),
514
+ this.verifierDirection.or
515
+ ),
516
+ like: (v) => null
517
+ };
110
518
  verifierDirection = {
111
519
  gt: 1,
112
520
  gte: 1,
@@ -114,26 +522,41 @@ var BPTree = class {
114
522
  lte: -1,
115
523
  equal: 1,
116
524
  notEqual: 1,
525
+ or: 1,
117
526
  like: 1
118
527
  };
119
- verifierFullScan = {
120
- gt: false,
121
- gte: false,
122
- lt: false,
123
- lte: false,
124
- equal: false,
125
- notEqual: true,
126
- like: true
127
- };
128
- constructor(strategy, comparator) {
528
+ constructor(strategy, comparator, option) {
529
+ this.strategy = strategy;
530
+ this.comparator = comparator;
531
+ this.option = option ?? {};
129
532
  this._strategyDirty = false;
130
- this._cachedRegexp = new InvertedWeakMap();
131
533
  this._nodeCreateBuffer = /* @__PURE__ */ new Map();
132
534
  this._nodeUpdateBuffer = /* @__PURE__ */ new Map();
133
535
  this._nodeDeleteBuffer = /* @__PURE__ */ new Map();
134
- this.nodes = new InvertedWeakMap();
135
- this.strategy = strategy;
136
- this.comparator = comparator;
536
+ this._cachedRegexp = this._createCachedRegexp();
537
+ }
538
+ _createCachedRegexp() {
539
+ return new CacheEntanglementSync((key) => {
540
+ const pattern = key.replace(/%/g, ".*").replace(/_/g, ".");
541
+ const regexp = new RegExp(`^${pattern}$`, "i");
542
+ return regexp;
543
+ }, {
544
+ lifespan: this.option.lifespan ?? "3m"
545
+ });
546
+ }
547
+ ensureValues(v) {
548
+ if (!Array.isArray(v)) {
549
+ v = [v];
550
+ }
551
+ return v;
552
+ }
553
+ lowestValue(v) {
554
+ const i = 0;
555
+ return [...v].sort((a, b) => this.comparator.asc(a, b))[i];
556
+ }
557
+ highestValue(v) {
558
+ const i = v.length - 1;
559
+ return [...v].sort((a, b) => this.comparator.asc(a, b))[i];
137
560
  }
138
561
  _insertAtLeaf(node, key, value) {
139
562
  if (node.values.length) {
@@ -141,6 +564,11 @@ var BPTree = class {
141
564
  const nValue = node.values[i];
142
565
  if (this.comparator.isSame(value, nValue)) {
143
566
  const keys = node.keys[i];
567
+ if (keys.includes(key)) {
568
+ throw new Error("The key already exists.", {
569
+ cause: { key, value }
570
+ });
571
+ }
144
572
  keys.push(key);
145
573
  this.bufferForNodeUpdate(node);
146
574
  break;
@@ -188,32 +616,47 @@ var BPTree = class {
188
616
  getHeadData() {
189
617
  return this.strategy.head.data;
190
618
  }
619
+ /**
620
+ * Clears all cached nodes.
621
+ * This method is useful for freeing up memory when the tree is no longer needed.
622
+ */
623
+ clear() {
624
+ this._cachedRegexp.clear();
625
+ this.nodes.clear();
626
+ }
191
627
  };
192
628
 
193
629
  // src/BPTreeSync.ts
194
630
  var BPTreeSync = class extends BPTree {
195
- constructor(strategy, comparator) {
196
- super(strategy, comparator);
197
- }
198
- getPairsRightToLeft(value, startNode, fullScan, comparator) {
631
+ constructor(strategy, comparator, option) {
632
+ super(strategy, comparator, option);
633
+ this.nodes = this._createCachedNode();
634
+ }
635
+ _createCachedNode() {
636
+ return new CacheEntanglementSync((key) => {
637
+ return this.strategy.read(key);
638
+ }, {
639
+ lifespan: this.option.lifespan ?? "3m"
640
+ });
641
+ }
642
+ getPairsRightToLeft(value, startNode, endNode, comparator) {
199
643
  const pairs = [];
200
644
  let node = startNode;
201
645
  let done = false;
202
- let found = false;
203
646
  while (!done) {
647
+ if (endNode && node.id === endNode.id) {
648
+ done = true;
649
+ break;
650
+ }
204
651
  let i = node.values.length;
205
652
  while (i--) {
206
653
  const nValue = node.values[i];
207
654
  const keys = node.keys[i];
208
655
  if (comparator(nValue, value)) {
209
- found = true;
210
656
  let j = keys.length;
211
657
  while (j--) {
212
658
  pairs.push([keys[j], nValue]);
213
659
  }
214
- } else if (found && !fullScan) {
215
- done = true;
216
- break;
217
660
  }
218
661
  }
219
662
  if (!node.prev) {
@@ -224,24 +667,23 @@ var BPTreeSync = class extends BPTree {
224
667
  }
225
668
  return new Map(pairs.reverse());
226
669
  }
227
- getPairsLeftToRight(value, startNode, fullScan, comparator) {
670
+ getPairsLeftToRight(value, startNode, endNode, comparator) {
228
671
  const pairs = [];
229
672
  let node = startNode;
230
673
  let done = false;
231
- let found = false;
232
674
  while (!done) {
675
+ if (endNode && node.id === endNode.id) {
676
+ done = true;
677
+ break;
678
+ }
233
679
  for (let i = 0, len = node.values.length; i < len; i++) {
234
680
  const nValue = node.values[i];
235
681
  const keys = node.keys[i];
236
682
  if (comparator(nValue, value)) {
237
- found = true;
238
683
  for (let j = 0, len2 = keys.length; j < len2; j++) {
239
684
  const key = keys[j];
240
685
  pairs.push([key, nValue]);
241
686
  }
242
- } else if (found && !fullScan) {
243
- done = true;
244
- break;
245
687
  }
246
688
  }
247
689
  if (!node.next) {
@@ -252,12 +694,12 @@ var BPTreeSync = class extends BPTree {
252
694
  }
253
695
  return new Map(pairs);
254
696
  }
255
- getPairs(value, startNode, fullScan, comparator, direction) {
697
+ getPairs(value, startNode, endNode, comparator, direction) {
256
698
  switch (direction) {
257
699
  case -1:
258
- return this.getPairsRightToLeft(value, startNode, fullScan, comparator);
700
+ return this.getPairsRightToLeft(value, startNode, endNode, comparator);
259
701
  case 1:
260
- return this.getPairsLeftToRight(value, startNode, fullScan, comparator);
702
+ return this.getPairsLeftToRight(value, startNode, endNode, comparator);
261
703
  default:
262
704
  throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
263
705
  }
@@ -280,7 +722,7 @@ var BPTreeSync = class extends BPTree {
280
722
  next,
281
723
  prev
282
724
  };
283
- this.nodes.set(id, node);
725
+ this._nodeCreateBuffer.set(id, node);
284
726
  return node;
285
727
  }
286
728
  _deleteEntry(node, key, value) {
@@ -494,7 +936,6 @@ var BPTreeSync = class extends BPTree {
494
936
  this.strategy.head.root = root.id;
495
937
  node.parent = root.id;
496
938
  pointer.parent = root.id;
497
- this.bufferForNodeCreate(root);
498
939
  this.bufferForNodeUpdate(node);
499
940
  this.bufferForNodeUpdate(pointer);
500
941
  return;
@@ -530,7 +971,6 @@ var BPTreeSync = class extends BPTree {
530
971
  this.bufferForNodeUpdate(node2);
531
972
  }
532
973
  this._insertInParent(parentNode, midValue, parentPointer);
533
- this.bufferForNodeCreate(parentPointer);
534
974
  this.bufferForNodeUpdate(parentNode);
535
975
  }
536
976
  }
@@ -542,7 +982,6 @@ var BPTreeSync = class extends BPTree {
542
982
  this.order = this.strategy.order;
543
983
  this.root = this._createNode(true, [], [], true);
544
984
  this.strategy.head.root = this.root.id;
545
- this.bufferForNodeCreate(this.root);
546
985
  this.commitHeadBuffer();
547
986
  this.commitNodeCreateBuffer();
548
987
  } else {
@@ -556,10 +995,11 @@ var BPTreeSync = class extends BPTree {
556
995
  }
557
996
  }
558
997
  getNode(id) {
559
- if (!this.nodes.has(id)) {
560
- this.nodes.set(id, this.strategy.read(id));
998
+ if (this._nodeCreateBuffer.has(id)) {
999
+ return this._nodeCreateBuffer.get(id);
561
1000
  }
562
- return this.nodes.get(id);
1001
+ const cache = this.nodes.cache(id);
1002
+ return cache.raw;
563
1003
  }
564
1004
  insertableNode(value) {
565
1005
  let node = this.root;
@@ -581,6 +1021,25 @@ var BPTreeSync = class extends BPTree {
581
1021
  }
582
1022
  return node;
583
1023
  }
1024
+ insertableEndNode(value, direction) {
1025
+ const insertableNode = this.insertableNode(value);
1026
+ let key;
1027
+ switch (direction) {
1028
+ case -1:
1029
+ key = "prev";
1030
+ break;
1031
+ case 1:
1032
+ key = "next";
1033
+ break;
1034
+ default:
1035
+ throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
1036
+ }
1037
+ const guessNode = insertableNode[key];
1038
+ if (!guessNode) {
1039
+ return null;
1040
+ }
1041
+ return this.getNode(guessNode);
1042
+ }
584
1043
  leftestNode() {
585
1044
  let node = this.root;
586
1045
  while (!node.leaf) {
@@ -589,6 +1048,14 @@ var BPTreeSync = class extends BPTree {
589
1048
  }
590
1049
  return node;
591
1050
  }
1051
+ rightestNode() {
1052
+ let node = this.root;
1053
+ while (!node.leaf) {
1054
+ const keys = node.keys;
1055
+ node = this.getNode(keys[keys.length - 1]);
1056
+ }
1057
+ return node;
1058
+ }
592
1059
  commitHeadBuffer() {
593
1060
  if (!this._strategyDirty) {
594
1061
  return;
@@ -619,10 +1086,10 @@ var BPTreeSync = class extends BPTree {
619
1086
  const key = k;
620
1087
  const value = condition[key];
621
1088
  const startNode = this.verifierStartNode[key](value);
1089
+ const endNode = this.verifierEndNode[key](value);
622
1090
  const direction = this.verifierDirection[key];
623
- const fullScan = this.verifierFullScan[key];
624
1091
  const comparator = this.verifierMap[key];
625
- const pairs = this.getPairs(value, startNode, fullScan, comparator, direction);
1092
+ const pairs = this.getPairs(value, startNode, endNode, comparator, direction);
626
1093
  if (!filterValues) {
627
1094
  filterValues = new Set(pairs.keys());
628
1095
  } else {
@@ -644,10 +1111,10 @@ var BPTreeSync = class extends BPTree {
644
1111
  const key = k;
645
1112
  const value = condition[key];
646
1113
  const startNode = this.verifierStartNode[key](value);
1114
+ const endNode = this.verifierEndNode[key](value);
647
1115
  const direction = this.verifierDirection[key];
648
- const fullScan = this.verifierFullScan[key];
649
1116
  const comparator = this.verifierMap[key];
650
- const pairs = this.getPairs(value, startNode, fullScan, comparator, direction);
1117
+ const pairs = this.getPairs(value, startNode, endNode, comparator, direction);
651
1118
  if (result === null) {
652
1119
  result = pairs;
653
1120
  } else {
@@ -688,7 +1155,6 @@ var BPTreeSync = class extends BPTree {
688
1155
  this.bufferForNodeUpdate(node);
689
1156
  }
690
1157
  this._insertInParent(before, after.values[0], after);
691
- this.bufferForNodeCreate(after);
692
1158
  this.bufferForNodeUpdate(before);
693
1159
  }
694
1160
  this.commitHeadBuffer();
@@ -754,28 +1220,35 @@ var BPTreeSync = class extends BPTree {
754
1220
 
755
1221
  // src/BPTreeAsync.ts
756
1222
  var BPTreeAsync = class extends BPTree {
757
- constructor(strategy, comparator) {
758
- super(strategy, comparator);
759
- }
760
- async getPairsRightToLeft(value, startNode, fullScan, comparator) {
1223
+ constructor(strategy, comparator, option) {
1224
+ super(strategy, comparator, option);
1225
+ this.nodes = this._createCachedNode();
1226
+ }
1227
+ _createCachedNode() {
1228
+ return new CacheEntanglementAsync(async (key) => {
1229
+ return await this.strategy.read(key);
1230
+ }, {
1231
+ lifespan: this.option.lifespan ?? "3m"
1232
+ });
1233
+ }
1234
+ async getPairsRightToLeft(value, startNode, endNode, comparator) {
761
1235
  const pairs = [];
762
1236
  let node = startNode;
763
1237
  let done = false;
764
- let found = false;
765
1238
  while (!done) {
1239
+ if (endNode && node.id === endNode.id) {
1240
+ done = true;
1241
+ break;
1242
+ }
766
1243
  let i = node.values.length;
767
1244
  while (i--) {
768
1245
  const nValue = node.values[i];
769
1246
  const keys = node.keys[i];
770
1247
  if (comparator(nValue, value)) {
771
- found = true;
772
1248
  let j = keys.length;
773
1249
  while (j--) {
774
1250
  pairs.push([keys[j], nValue]);
775
1251
  }
776
- } else if (found && !fullScan) {
777
- done = true;
778
- break;
779
1252
  }
780
1253
  }
781
1254
  if (!node.prev) {
@@ -786,24 +1259,23 @@ var BPTreeAsync = class extends BPTree {
786
1259
  }
787
1260
  return new Map(pairs.reverse());
788
1261
  }
789
- async getPairsLeftToRight(value, startNode, fullScan, comparator) {
1262
+ async getPairsLeftToRight(value, startNode, endNode, comparator) {
790
1263
  const pairs = [];
791
1264
  let node = startNode;
792
1265
  let done = false;
793
- let found = false;
794
1266
  while (!done) {
1267
+ if (endNode && node.id === endNode.id) {
1268
+ done = true;
1269
+ break;
1270
+ }
795
1271
  for (let i = 0, len = node.values.length; i < len; i++) {
796
1272
  const nValue = node.values[i];
797
1273
  const keys = node.keys[i];
798
1274
  if (comparator(nValue, value)) {
799
- found = true;
800
1275
  for (let j = 0, len2 = keys.length; j < len2; j++) {
801
1276
  const key = keys[j];
802
1277
  pairs.push([key, nValue]);
803
1278
  }
804
- } else if (found && !fullScan) {
805
- done = true;
806
- break;
807
1279
  }
808
1280
  }
809
1281
  if (!node.next) {
@@ -814,12 +1286,12 @@ var BPTreeAsync = class extends BPTree {
814
1286
  }
815
1287
  return new Map(pairs);
816
1288
  }
817
- async getPairs(value, startNode, fullScan, comparator, direction) {
1289
+ async getPairs(value, startNode, endNode, comparator, direction) {
818
1290
  switch (direction) {
819
1291
  case -1:
820
- return await this.getPairsRightToLeft(value, startNode, fullScan, comparator);
1292
+ return await this.getPairsRightToLeft(value, startNode, endNode, comparator);
821
1293
  case 1:
822
- return await this.getPairsLeftToRight(value, startNode, fullScan, comparator);
1294
+ return await this.getPairsLeftToRight(value, startNode, endNode, comparator);
823
1295
  default:
824
1296
  throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
825
1297
  }
@@ -842,7 +1314,7 @@ var BPTreeAsync = class extends BPTree {
842
1314
  next,
843
1315
  prev
844
1316
  };
845
- this.nodes.set(id, node);
1317
+ this._nodeCreateBuffer.set(id, node);
846
1318
  return node;
847
1319
  }
848
1320
  async _deleteEntry(node, key, value) {
@@ -1056,7 +1528,6 @@ var BPTreeAsync = class extends BPTree {
1056
1528
  this.strategy.head.root = root.id;
1057
1529
  node.parent = root.id;
1058
1530
  pointer.parent = root.id;
1059
- this.bufferForNodeCreate(root);
1060
1531
  this.bufferForNodeUpdate(node);
1061
1532
  this.bufferForNodeUpdate(pointer);
1062
1533
  return;
@@ -1092,7 +1563,6 @@ var BPTreeAsync = class extends BPTree {
1092
1563
  this.bufferForNodeUpdate(node2);
1093
1564
  }
1094
1565
  await this._insertInParent(parentNode, midValue, parentPointer);
1095
- this.bufferForNodeCreate(parentPointer);
1096
1566
  this.bufferForNodeUpdate(parentNode);
1097
1567
  }
1098
1568
  }
@@ -1104,7 +1574,6 @@ var BPTreeAsync = class extends BPTree {
1104
1574
  this.order = this.strategy.order;
1105
1575
  this.root = await this._createNode(true, [], [], true);
1106
1576
  this.strategy.head.root = this.root.id;
1107
- this.bufferForNodeCreate(this.root);
1108
1577
  await this.commitHeadBuffer();
1109
1578
  await this.commitNodeCreateBuffer();
1110
1579
  } else {
@@ -1118,10 +1587,11 @@ var BPTreeAsync = class extends BPTree {
1118
1587
  }
1119
1588
  }
1120
1589
  async getNode(id) {
1121
- if (!this.nodes.has(id)) {
1122
- this.nodes.set(id, await this.strategy.read(id));
1590
+ if (this._nodeCreateBuffer.has(id)) {
1591
+ return this._nodeCreateBuffer.get(id);
1123
1592
  }
1124
- return this.nodes.get(id);
1593
+ const cache = await this.nodes.cache(id);
1594
+ return cache.raw;
1125
1595
  }
1126
1596
  async insertableNode(value) {
1127
1597
  let node = this.root;
@@ -1143,6 +1613,25 @@ var BPTreeAsync = class extends BPTree {
1143
1613
  }
1144
1614
  return node;
1145
1615
  }
1616
+ async insertableEndNode(value, direction) {
1617
+ const insertableNode = await this.insertableNode(value);
1618
+ let key;
1619
+ switch (direction) {
1620
+ case -1:
1621
+ key = "prev";
1622
+ break;
1623
+ case 1:
1624
+ key = "next";
1625
+ break;
1626
+ default:
1627
+ throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
1628
+ }
1629
+ const guessNode = insertableNode[key];
1630
+ if (!guessNode) {
1631
+ return null;
1632
+ }
1633
+ return await this.getNode(guessNode);
1634
+ }
1146
1635
  async leftestNode() {
1147
1636
  let node = this.root;
1148
1637
  while (!node.leaf) {
@@ -1151,6 +1640,14 @@ var BPTreeAsync = class extends BPTree {
1151
1640
  }
1152
1641
  return node;
1153
1642
  }
1643
+ async rightestNode() {
1644
+ let node = this.root;
1645
+ while (!node.leaf) {
1646
+ const keys = node.keys;
1647
+ node = await this.getNode(keys[keys.length - 1]);
1648
+ }
1649
+ return node;
1650
+ }
1154
1651
  async commitHeadBuffer() {
1155
1652
  if (!this._strategyDirty) {
1156
1653
  return;
@@ -1181,10 +1678,10 @@ var BPTreeAsync = class extends BPTree {
1181
1678
  const key = k;
1182
1679
  const value = condition[key];
1183
1680
  const startNode = await this.verifierStartNode[key](value);
1681
+ const endNode = await this.verifierEndNode[key](value);
1184
1682
  const direction = this.verifierDirection[key];
1185
- const fullScan = this.verifierFullScan[key];
1186
1683
  const comparator = this.verifierMap[key];
1187
- const pairs = await this.getPairs(value, startNode, fullScan, comparator, direction);
1684
+ const pairs = await this.getPairs(value, startNode, endNode, comparator, direction);
1188
1685
  if (!filterValues) {
1189
1686
  filterValues = new Set(pairs.keys());
1190
1687
  } else {
@@ -1206,10 +1703,10 @@ var BPTreeAsync = class extends BPTree {
1206
1703
  const key = k;
1207
1704
  const value = condition[key];
1208
1705
  const startNode = await this.verifierStartNode[key](value);
1706
+ const endNode = await this.verifierEndNode[key](value);
1209
1707
  const direction = this.verifierDirection[key];
1210
- const fullScan = this.verifierFullScan[key];
1211
1708
  const comparator = this.verifierMap[key];
1212
- const pairs = await this.getPairs(value, startNode, fullScan, comparator, direction);
1709
+ const pairs = await this.getPairs(value, startNode, endNode, comparator, direction);
1213
1710
  if (result === null) {
1214
1711
  result = pairs;
1215
1712
  } else {
@@ -1250,7 +1747,6 @@ var BPTreeAsync = class extends BPTree {
1250
1747
  this.bufferForNodeUpdate(node);
1251
1748
  }
1252
1749
  await this._insertInParent(before, after.values[0], after);
1253
- this.bufferForNodeCreate(after);
1254
1750
  this.bufferForNodeUpdate(before);
1255
1751
  }
1256
1752
  await this.commitHeadBuffer();