@andrew_l/toolkit 0.2.15 → 0.2.17

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/index.cjs CHANGED
@@ -1,18 +1,18 @@
1
1
  'use strict';
2
2
 
3
- const _get = require('lodash/get.js');
4
3
  const _cloneDeep = require('lodash/cloneDeep.js');
5
4
  const _cloneDeepWith = require('lodash/cloneDeepWith.js');
6
5
  const _defaultsDeep = require('lodash/defaultsDeep.js');
6
+ const _get = require('lodash/get.js');
7
7
  const _set = require('lodash/set.js');
8
8
  const _unset = require('lodash/unset.js');
9
9
 
10
10
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
11
11
 
12
- const _get__default = /*#__PURE__*/_interopDefaultCompat(_get);
13
12
  const _cloneDeep__default = /*#__PURE__*/_interopDefaultCompat(_cloneDeep);
14
13
  const _cloneDeepWith__default = /*#__PURE__*/_interopDefaultCompat(_cloneDeepWith);
15
14
  const _defaultsDeep__default = /*#__PURE__*/_interopDefaultCompat(_defaultsDeep);
15
+ const _get__default = /*#__PURE__*/_interopDefaultCompat(_get);
16
16
  const _set__default = /*#__PURE__*/_interopDefaultCompat(_set);
17
17
  const _unset__default = /*#__PURE__*/_interopDefaultCompat(_unset);
18
18
 
@@ -357,685 +357,1200 @@ function shuffle(arr) {
357
357
  return result;
358
358
  }
359
359
 
360
- class SortedArray extends Array {
361
- #compareFn;
362
- /**
363
- * Creates a new SortedArray instance.
364
- *
365
- * @param compareFn The comparison function to determine the sort order
366
- * @param items Optional initial items to add to the array (will be sorted immediately)
367
- */
368
- constructor(compareFn, items = []) {
369
- super();
370
- this.#compareFn = compareFn;
371
- if (items.length > 0) {
372
- super.push.apply(this, items.toSorted(this.#compareFn));
373
- }
374
- }
375
- /**
376
- * Inserts multiple items while maintaining sort order
377
- * @param items The items to insert
378
- * @returns The new length of the array
379
- */
380
- push(...items) {
381
- var newItems = items.toSorted(this.#compareFn);
382
- var newItemsLen = newItems.length;
383
- var originalLen = this.length;
384
- var result = new Array(originalLen + newItemsLen);
385
- var i = 0, j = 0, k = 0;
386
- while (i < originalLen && j < newItemsLen) {
387
- if (this.#compareFn(this[i], newItems[j]) <= 0) {
388
- result[k++] = this[i++];
389
- } else {
390
- result[k++] = newItems[j++];
391
- }
392
- }
393
- while (i < originalLen) {
394
- result[k++] = this[i++];
395
- }
396
- while (j < newItemsLen) {
397
- result[k++] = newItems[j++];
398
- }
399
- this.length = 0;
400
- super.push.apply(this, result);
401
- return this.length;
402
- }
403
- /**
404
- * Override Array methods that would break the sorted order
405
- */
406
- unshift(...items) {
407
- return this.push(...items);
408
- }
409
- /**
410
- * Creates a new SortedArray with the same comparison function
411
- * @returns A new SortedArray instance
412
- */
413
- slice(start, end) {
414
- var result = new SortedArray(this.#compareFn);
415
- var sliced = super.slice(start, end);
416
- super.push.apply(result, sliced);
417
- return result;
418
- }
419
- /**
420
- * Concatenates arrays or values while maintaining sort order
421
- * @param items Arrays or values to concatenate
422
- * @returns A new SortedArray with the concatenated elements
423
- */
424
- concat(...items) {
425
- var result = new SortedArray(this.#compareFn, this);
426
- for (const item of items) {
427
- if (Array.isArray(item)) {
428
- result.push.apply(result, item);
429
- } else {
430
- result.push(item);
431
- }
360
+ function cleanEmpty(obj) {
361
+ let value;
362
+ for (const key of Object.keys(obj)) {
363
+ value = obj[key];
364
+ if (isEmpty(value)) {
365
+ delete obj[key];
432
366
  }
433
- return result;
434
367
  }
368
+ return obj;
435
369
  }
436
- ["map", "filter", "flatMap", "flat", "reverse", "sort"].forEach((key) => {
437
- SortedArray.prototype[key] = function() {
438
- const arr = Array.prototype[key].apply(this, arguments);
439
- Object.setPrototypeOf(arr, Array.prototype);
440
- return arr;
441
- };
442
- });
443
370
 
444
- const sum = (values) => {
445
- return values.reduce((a, b) => a + (isNumber(b) ? b : 0), 0);
371
+ const cleanObject = (input) => {
372
+ [...Object.keys(input), ...Object.getOwnPropertySymbols(input)].forEach(
373
+ (key) => {
374
+ delete input[key];
375
+ }
376
+ );
446
377
  };
447
378
 
448
- function uniq(value) {
449
- if (!Array.isArray(value)) {
450
- return [];
379
+ const deepAssign = (dest, source) => {
380
+ for (const key of Object.keys(source)) {
381
+ const destValue = dest[key];
382
+ const sourceValue = source[key];
383
+ if (isObject(destValue) && isObject(sourceValue)) {
384
+ deepAssign(destValue, sourceValue);
385
+ } else {
386
+ dest[key] = sourceValue;
387
+ }
451
388
  }
452
- return [...new Set(value)];
453
- }
389
+ };
454
390
 
455
- function union(...arrays) {
456
- if (arrays.length === 0) return [];
457
- if (arrays.length === 1) return [...arrays[0]];
458
- const [first, ...rest] = arrays;
459
- return uniq(first.concat(...rest));
460
- }
391
+ const deepClone = (value) => {
392
+ return _cloneDeep__default(value);
393
+ };
461
394
 
462
- const get = _get__default;
395
+ const def = (obj, key, value, writable = false) => {
396
+ Object.defineProperty(obj, key, {
397
+ configurable: true,
398
+ enumerable: false,
399
+ writable,
400
+ value
401
+ });
402
+ };
463
403
 
464
- function uniqBy(array, comparator) {
465
- const seen = /* @__PURE__ */ new Set();
466
- if (!isFunction(comparator)) {
467
- const key = comparator;
468
- comparator = (value) => get(value, key);
469
- }
470
- return array.filter((value) => {
471
- const computed = comparator(value);
472
- const hasSeen = seen.has(computed);
473
- if (!hasSeen) {
474
- seen.add(computed);
404
+ const WITH_CUSTOMIZER_FACTORY_SYM = Symbol();
405
+ function deepCloneWith(value, customizer) {
406
+ const fns = prepareCustomizes(customizer);
407
+ return _cloneDeepWith__default(value, (value2, key) => {
408
+ let newValue;
409
+ let replaced = false;
410
+ for (const fn of fns) {
411
+ newValue = fn(value2, key);
412
+ if (newValue !== void 0) {
413
+ value2 = newValue;
414
+ replaced = true;
415
+ }
475
416
  }
476
- return !hasSeen;
417
+ if (replaced) return value2;
477
418
  });
478
419
  }
479
-
480
- let AssertionError;
481
- (async () => {
482
- AssertionError = globalThis.window ? await Promise.resolve().then(function () { return BrowserAssertionError$1; }).then(
483
- (r) => r.BrowserAssertionError
484
- ) : await import('node:assert').then((r) => r.AssertionError);
485
- })();
486
-
487
- function ok(value, message) {
488
- if (!value) {
489
- throw toError$1(
490
- ok,
491
- value,
492
- message,
493
- "The expression evaluated to a falsy value."
494
- );
495
- }
420
+ function createDeepCloneWith(customizer) {
421
+ return (value) => {
422
+ return deepCloneWith(value, customizer);
423
+ };
496
424
  }
497
- function equal(actual, expected, message) {
498
- if (actual !== expected) {
499
- new AssertionError({
500
- actual,
501
- expected,
502
- message: isString(message) ? message : "The actual value not as expected.",
503
- operator: "equal",
504
- stackStartFn: equal
505
- });
506
- }
425
+ function prepareCustomizes(value) {
426
+ return arrayable(value).map((v) => isCustomizerFactory(v) ? v() : v);
507
427
  }
508
- function notEmpty(value, message) {
509
- if (isEmpty(value)) {
510
- throw toError$1(notEmpty, value, message, "Expected not empty value.");
511
- }
428
+ function isCustomizerFactory(value) {
429
+ return value?.[WITH_CUSTOMIZER_FACTORY_SYM] === true;
512
430
  }
513
- function object(value, message) {
514
- if (!isObject(value)) {
515
- throw toError$1(object, value, message, "Expected object value.");
516
- }
431
+ function createCustomizer(fn) {
432
+ return fn;
517
433
  }
518
- function string(value, message) {
519
- if (!isString(value)) {
520
- throw toError$1(string, value, message, "Expected string value.");
521
- }
434
+ function createCustomizerFactory(fn) {
435
+ def(fn, WITH_CUSTOMIZER_FACTORY_SYM, true);
436
+ return fn;
522
437
  }
523
- function boolean(value, message) {
524
- if (!isBoolean(value)) {
525
- throw toError$1(boolean, value, message, "Expected boolean value.");
526
- }
438
+ function createSecureCustomizer(properties, opts) {
439
+ const secureLabel = `<** secure **>`;
440
+ const circularLabel = `<** circular **>`;
441
+ const propertiesSet = Object.freeze(
442
+ new Set(properties.map((v) => v.toLocaleLowerCase()))
443
+ );
444
+ const withCustomizer = (seenSet, value, key) => {
445
+ if (isPrimitive(value)) {
446
+ if (!isString(key)) return;
447
+ if (!propertiesSet.has(key.toLocaleLowerCase())) return;
448
+ return secureLabel;
449
+ }
450
+ if (seenSet.has(value)) {
451
+ return circularLabel;
452
+ }
453
+ seenSet.add(value);
454
+ if (isError(value) && opts?.normalizeError !== false) {
455
+ return {
456
+ message: value.message,
457
+ stack: value.stack,
458
+ name: value.name,
459
+ cause: value.cause !== void 0 ? withCustomizer(seenSet, value.cause) : void 0
460
+ };
461
+ }
462
+ };
463
+ return createCustomizerFactory(() => {
464
+ const seenSet = /* @__PURE__ */ new WeakSet();
465
+ return withCustomizer.bind(null, seenSet);
466
+ });
527
467
  }
528
- function notEmptyString(value, message) {
529
- if (!isString(value) || !value.trim()) {
530
- throw toError$1(
531
- notEmptyString,
532
- value,
533
- message,
534
- "Expected not empty string value."
535
- );
468
+
469
+ const deepDefaults = _defaultsDeep__default;
470
+
471
+ function deepFreeze(value) {
472
+ let currentValue = value;
473
+ if (!currentValue || typeof currentValue !== "object") return currentValue;
474
+ Object.freeze(currentValue);
475
+ if (Array.isArray(currentValue)) {
476
+ for (const item of currentValue) {
477
+ deepFreeze(item);
478
+ }
479
+ return currentValue;
480
+ } else {
481
+ for (const value2 of Object.values(currentValue)) {
482
+ deepFreeze(value2);
483
+ }
536
484
  }
485
+ return currentValue;
537
486
  }
538
- function number$1(value, message) {
539
- if (!isNumber(value)) {
540
- throw toError$1(number$1, value, message, "Expected number value.");
487
+
488
+ function flagsToMap(value, bitmaskMap) {
489
+ const result = {};
490
+ const compare = typeof value === "bigint" ? 0n : 0;
491
+ for (const [key, mask] of Object.entries(bitmaskMap)) {
492
+ result[key] = (value & mask) !== compare;
541
493
  }
494
+ return result;
542
495
  }
543
- function date(value, message) {
544
- if (!isDate(value)) {
545
- throw toError$1(date, value, message, "Expected date value.");
496
+
497
+ function flatten(obj, {
498
+ separator = "_",
499
+ initialPrefix = "",
500
+ withArrays = true,
501
+ isObjectCompare = isObject
502
+ } = {}) {
503
+ const result = {};
504
+ const seen = /* @__PURE__ */ new WeakSet();
505
+ if (isObjectCompare(obj)) {
506
+ iter(
507
+ result,
508
+ seen,
509
+ isObjectCompare,
510
+ separator,
511
+ withArrays,
512
+ obj,
513
+ initialPrefix,
514
+ true
515
+ );
546
516
  }
517
+ return result;
547
518
  }
548
- function fn(value, message) {
549
- if (!isFunction(value)) {
550
- throw toError$1(fn, value, message, "Expected function value.");
519
+ function iter(output, seen, isObjectCompare, separator, withArrays, val, key, initial) {
520
+ if (seen.has(val)) return;
521
+ let k, pfx = key && !initial ? key + separator : key;
522
+ if (Array.isArray(val)) {
523
+ seen.add(val);
524
+ if (!withArrays) {
525
+ output[key] = val;
526
+ return;
527
+ }
528
+ for (k = 0; k < val.length; k++) {
529
+ iter(
530
+ output,
531
+ seen,
532
+ isObjectCompare,
533
+ separator,
534
+ withArrays,
535
+ val[k],
536
+ pfx + k
537
+ );
538
+ }
539
+ } else if (isObjectCompare(val)) {
540
+ seen.add(val);
541
+ for (k in val) {
542
+ iter(
543
+ output,
544
+ seen,
545
+ isObjectCompare,
546
+ separator,
547
+ withArrays,
548
+ val[k],
549
+ pfx + k
550
+ );
551
+ }
552
+ } else {
553
+ output[key] = val;
551
554
  }
552
555
  }
553
- function greaterThan(value, target, message) {
554
- if (!isNumber(value) || value < target) {
555
- throw toError$1(
556
- greaterThan,
557
- value,
558
- message,
559
- "Expected number value greater then " + target + "."
560
- );
556
+
557
+ const get = _get__default;
558
+
559
+ function has(value, keys) {
560
+ if (!isObject(value)) return false;
561
+ for (let idx = 0; idx < keys.length; idx++) {
562
+ const element = keys[idx];
563
+ if (!(element in value)) return false;
561
564
  }
565
+ return true;
562
566
  }
563
- function lessThan(value, target, message) {
564
- if (!isNumber(value) || value > target) {
565
- throw toError$1(
566
- lessThan,
567
- value,
568
- message,
569
- "Expected number value less then " + target + "."
570
- );
567
+
568
+ const hasOwn = (val, key) => Object.prototype.hasOwnProperty.call(val, key);
569
+
570
+ function omit(obj, excludes) {
571
+ const excludesSet = Array.isArray(excludes) ? new Set(excludes) : excludes instanceof Set ? excludes : void 0;
572
+ if (!excludesSet) {
573
+ return obj;
571
574
  }
572
- }
573
- function array(value, message) {
574
- if (!Array.isArray(value)) {
575
- throw toError$1(array, value, message, "Expected array value.");
575
+ const result = {};
576
+ if (!isObject(obj)) {
577
+ return result;
578
+ }
579
+ for (const [key, value] of Object.entries(obj)) {
580
+ if (excludesSet.has(key)) continue;
581
+ result[key] = value;
576
582
  }
583
+ return result;
577
584
  }
578
- function arrayStrings(value, message) {
579
- if (!Array.isArray(value) || !value.every(isString)) {
580
- throw toError$1(arrayStrings, value, message, "Expected strings list value.");
585
+
586
+ function omitPrefixed(obj, prefix) {
587
+ const result = {};
588
+ for (const [key, value] of Object.entries(obj)) {
589
+ if (key.startsWith(prefix)) continue;
590
+ result[key] = value;
581
591
  }
592
+ return result;
582
593
  }
583
- function arrayNumbers(value, message) {
584
- if (!Array.isArray(value) || !value.every(isNumber)) {
585
- throw toError$1(arrayNumbers, value, message, "Expected numbers list value.");
594
+
595
+ function pick(obj, keys) {
596
+ const keysSet = Array.isArray(keys) ? new Set(keys) : keys instanceof Set ? keys : void 0;
597
+ const result = {};
598
+ if (!keysSet || !isObject(obj)) {
599
+ return result;
600
+ }
601
+ for (const key of keysSet.values()) {
602
+ if (hasOwn(obj, key)) {
603
+ result[key] = obj[key];
604
+ }
586
605
  }
606
+ return result;
587
607
  }
588
- function toError$1(operator, actual, message, unknownMessage = "Unknown error") {
589
- if (isError(message)) {
590
- return message;
608
+
609
+ function pickPrefixed(obj, options) {
610
+ let prefix;
611
+ let prefixTrim = false;
612
+ if (typeof options === "string") {
613
+ prefix = options;
614
+ } else {
615
+ prefix = options.prefix;
616
+ prefixTrim = options.prefixTrim === true;
591
617
  }
592
- return new AssertionError({
593
- actual,
594
- message: isString(message) ? message : unknownMessage,
595
- operator: operator.name,
596
- stackStartFn: operator
597
- });
618
+ const result = {};
619
+ for (let [key, value] of Object.entries(obj)) {
620
+ if (!key.startsWith(prefix)) continue;
621
+ if (prefixTrim) key = key.substring(prefix.length);
622
+ result[key] = value;
623
+ }
624
+ return result;
598
625
  }
599
626
 
600
- const assert = {
601
- __proto__: null,
602
- array: array,
603
- arrayNumbers: arrayNumbers,
604
- arrayStrings: arrayStrings,
605
- boolean: boolean,
606
- date: date,
607
- equal: equal,
608
- fn: fn,
609
- greaterThan: greaterThan,
610
- lessThan: lessThan,
611
- notEmpty: notEmpty,
612
- notEmptyString: notEmptyString,
613
- number: number$1,
614
- object: object,
615
- ok: ok,
616
- string: string
617
- };
627
+ const set = _set__default;
618
628
 
619
- function weightedRoundRobin(arr) {
620
- ok(arr.length > 0, "Array must contain at least one item.");
621
- const instance = new WeightedRoundRobin(
622
- arr.map((v) => ({
623
- item: v.item,
624
- weight: Math.min(v.weight ?? 1, 1)
625
- }))
626
- );
627
- return () => instance.nextItem();
628
- }
629
- const gcd = (a, b) => !b ? a : gcd(b, a % b);
630
- class WeightedRoundRobin {
631
- constructor(items) {
632
- this.items = items;
633
- this.maxWeight = this._calculateMaxWeight();
634
- this.gcdWeight = this._calculateGCD();
635
- }
636
- currentIndex = -1;
637
- currentWeight = 0;
638
- maxWeight;
639
- gcdWeight;
640
- _calculateGCD() {
641
- return this.items.reduce(
642
- (acc, curr) => gcd(acc, curr.weight),
643
- this.items[0].weight
644
- );
629
+ const toMap = (obj) => {
630
+ const map = new Map(Object.entries(obj));
631
+ for (const symbol of Object.getOwnPropertySymbols(obj)) {
632
+ map.set(symbol, obj[symbol]);
645
633
  }
646
- _calculateMaxWeight() {
647
- return Math.max(...this.items.map((s) => s.weight));
634
+ return map;
635
+ };
636
+
637
+ const badKeys = Object.freeze(
638
+ /* @__PURE__ */ new Set(["constructor", "__proto__", "prototype"])
639
+ );
640
+ function unflatten(input, separator = "_") {
641
+ if (!isObject(input)) {
642
+ return {};
648
643
  }
649
- nextItem() {
650
- const n = this.items.length;
651
- while (true) {
652
- this.currentIndex = (this.currentIndex + 1) % n;
653
- if (this.currentIndex === 0) {
654
- this.currentWeight -= this.gcdWeight;
655
- if (this.currentWeight <= 0) {
656
- this.currentWeight = this.maxWeight;
657
- }
644
+ let arr, tmp, output;
645
+ let i = 0, k, key;
646
+ for (k in input) {
647
+ tmp = output;
648
+ arr = k.split(separator);
649
+ for (i = 0; i < arr.length; ) {
650
+ key = arr[i++];
651
+ if (tmp == null) {
652
+ tmp = empty(+key);
653
+ output = output || tmp;
658
654
  }
659
- if (this.items[this.currentIndex].weight >= this.currentWeight) {
660
- return this.items[this.currentIndex].item;
655
+ if (badKeys.has(key)) break;
656
+ if (i < arr.length) {
657
+ if (key in tmp) {
658
+ tmp = tmp[key];
659
+ } else {
660
+ tmp = tmp[key] = empty(+arr[i]);
661
+ }
662
+ } else {
663
+ tmp[key] = input[k];
661
664
  }
662
665
  }
663
666
  }
667
+ return output;
668
+ }
669
+ function empty(key) {
670
+ return key === key ? [] : {};
664
671
  }
665
672
 
666
- class Base64Encoding {
667
- alphabet;
668
- padding;
669
- decodeMap = /* @__PURE__ */ new Map();
670
- constructor(alphabet, options) {
671
- if (alphabet.length !== 64) {
672
- throw new Error("Invalid alphabet");
673
- }
674
- this.alphabet = alphabet;
675
- this.padding = options?.padding ?? "=";
676
- if (this.alphabet.includes(this.padding) || this.padding.length !== 1) {
677
- throw new Error("Invalid padding");
678
- }
679
- for (let i = 0; i < alphabet.length; i++) {
680
- this.decodeMap.set(alphabet[i], i);
673
+ const unset = _unset__default;
674
+
675
+ const SYM_COMPARE_FN = Symbol("SYM_COMPARE_FN");
676
+ class SortedArray extends Array {
677
+ // @ts-expect-error
678
+ [SYM_COMPARE_FN];
679
+ /**
680
+ * Creates a new SortedArray instance.
681
+ *
682
+ * @param compareFn The comparison function to determine the sort order
683
+ * @param items Optional initial items to add to the array (will be sorted immediately)
684
+ */
685
+ constructor(compareFn, items = []) {
686
+ super();
687
+ def(this, SYM_COMPARE_FN, compareFn);
688
+ if (items.length > 0) {
689
+ super.push.apply(this, items.toSorted(compareFn));
681
690
  }
682
691
  }
683
- encode(data, options) {
684
- let result = "";
685
- let buffer = 0;
686
- let shift = 0;
687
- for (let i = 0; i < data.length; i++) {
688
- buffer = buffer << 8 | data[i];
689
- shift += 8;
690
- while (shift >= 6) {
691
- shift += -6;
692
- result += this.alphabet[buffer >> shift & 63];
692
+ /**
693
+ * Inserts multiple items while maintaining sort order
694
+ * @param items The items to insert
695
+ * @returns The new length of the array
696
+ */
697
+ push(...items) {
698
+ var newItems = items.toSorted(this[SYM_COMPARE_FN]);
699
+ var newItemsLen = newItems.length;
700
+ var originalLen = this.length;
701
+ var result = new Array(originalLen + newItemsLen);
702
+ var i = 0, j = 0, k = 0;
703
+ while (i < originalLen && j < newItemsLen) {
704
+ if (this[SYM_COMPARE_FN](this[i], newItems[j]) <= 0) {
705
+ result[k++] = this[i++];
706
+ } else {
707
+ result[k++] = newItems[j++];
693
708
  }
694
709
  }
695
- if (shift > 0) {
696
- result += this.alphabet[buffer << 6 - shift & 63];
710
+ while (i < originalLen) {
711
+ result[k++] = this[i++];
697
712
  }
698
- const includePadding = options?.includePadding ?? true;
699
- if (includePadding) {
700
- const padCount = (4 - result.length % 4) % 4;
701
- for (let i = 0; i < padCount; i++) {
702
- result += "=";
703
- }
713
+ while (j < newItemsLen) {
714
+ result[k++] = newItems[j++];
704
715
  }
716
+ this.length = 0;
717
+ super.push.apply(this, result);
718
+ return this.length;
719
+ }
720
+ /**
721
+ * Override Array methods that would break the sorted order
722
+ */
723
+ unshift(...items) {
724
+ return this.push(...items);
725
+ }
726
+ /**
727
+ * Creates a new SortedArray with the same comparison function
728
+ * @returns A new SortedArray instance
729
+ */
730
+ slice(start, end) {
731
+ var result = new SortedArray(this[SYM_COMPARE_FN]);
732
+ var sliced = super.slice(start, end);
733
+ super.push.apply(result, sliced);
705
734
  return result;
706
735
  }
707
- decode(data, options) {
708
- const strict = options?.strict ?? true;
709
- const chunkCount = Math.ceil(data.length / 4);
710
- const result = [];
711
- for (let i = 0; i < chunkCount; i++) {
712
- let padCount = 0;
713
- let buffer = 0;
714
- for (let j = 0; j < 4; j++) {
715
- const encoded = data[i * 4 + j];
716
- if (encoded === "=") {
717
- if (i + 1 !== chunkCount) {
718
- throw new Error(`Invalid character: ${encoded}`);
719
- }
720
- padCount += 1;
721
- continue;
722
- }
723
- if (encoded === void 0) {
724
- if (strict) {
725
- throw new Error("Invalid data");
726
- }
727
- padCount += 1;
728
- continue;
729
- }
730
- const value = this.decodeMap.get(encoded) ?? null;
731
- if (value === null) {
732
- throw new Error(`Invalid character: ${encoded}`);
733
- }
734
- buffer += value << 6 * (3 - j);
735
- }
736
- result.push(buffer >> 16 & 255);
737
- if (padCount < 2) {
738
- result.push(buffer >> 8 & 255);
739
- }
740
- if (padCount < 1) {
741
- result.push(buffer & 255);
736
+ /**
737
+ * Concatenates arrays or values while maintaining sort order
738
+ * @param items Arrays or values to concatenate
739
+ * @returns A new SortedArray with the concatenated elements
740
+ */
741
+ concat(...items) {
742
+ var result = new SortedArray(this[SYM_COMPARE_FN], this);
743
+ for (const item of items) {
744
+ if (Array.isArray(item)) {
745
+ result.push.apply(result, item);
746
+ } else {
747
+ result.push(item);
742
748
  }
743
749
  }
744
- return Uint8Array.from(result);
750
+ return result;
745
751
  }
746
752
  }
753
+ ["map", "filter", "flatMap", "flat", "reverse", "sort"].forEach((key) => {
754
+ SortedArray.prototype[key] = function() {
755
+ const arr = Array.prototype[key].apply(this, arguments);
756
+ Object.setPrototypeOf(arr, Array.prototype);
757
+ return arr;
758
+ };
759
+ });
747
760
 
748
- const base64 = new Base64Encoding(
749
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
750
- );
751
- const base64url = new Base64Encoding(
752
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
753
- );
761
+ const sum = (values) => {
762
+ return values.reduce((a, b) => a + (isNumber(b) ? b : 0), 0);
763
+ };
754
764
 
755
- function base64ToBytes(data, { encoding = "base64", strict } = {}) {
756
- if (encoding === "base64") {
757
- return base64.decode(data, { strict: strict ?? true });
758
- } else if (encoding === "base64url") {
759
- return base64url.decode(data, { strict: strict ?? false });
765
+ function uniq(value) {
766
+ if (!Array.isArray(value)) {
767
+ return [];
760
768
  }
761
- ok(false, "Invalid encoding options: " + encoding);
769
+ return [...new Set(value)];
762
770
  }
763
771
 
764
- function bigIntBytes(value) {
765
- if (value < 0n) {
766
- value = value * -1n;
767
- }
768
- let byteLength = 1;
769
- while (value > 2n ** BigInt(byteLength * 8) - 1n) {
770
- byteLength++;
771
- }
772
- const encoded = new Uint8Array(byteLength);
773
- for (let i = 0; i < encoded.byteLength; i++) {
774
- encoded[i] = Number(
775
- value >> BigInt((encoded.byteLength - i - 1) * 8) & 0xffn
776
- );
777
- }
778
- return encoded;
772
+ function union(...arrays) {
773
+ if (arrays.length === 0) return [];
774
+ if (arrays.length === 1) return [...arrays[0]];
775
+ const [first, ...rest] = arrays;
776
+ return uniq(first.concat(...rest));
779
777
  }
780
778
 
781
- function bigIntFromBytes(bytes) {
782
- ok(bytes.byteLength > 0, "Empty Uint8Array");
783
- let decoded = 0n;
784
- for (let i = 0; i < bytes.byteLength; i++) {
785
- decoded += BigInt(bytes[i]) << BigInt((bytes.byteLength - 1 - i) * 8);
779
+ function uniqBy(array, comparator) {
780
+ const seen = /* @__PURE__ */ new Set();
781
+ if (!isFunction(comparator)) {
782
+ const key = comparator;
783
+ comparator = (value) => get(value, key);
786
784
  }
787
- return decoded;
785
+ return array.filter((value) => {
786
+ const computed = comparator(value);
787
+ const hasSeen = seen.has(computed);
788
+ if (!hasSeen) {
789
+ seen.add(computed);
790
+ }
791
+ return !hasSeen;
792
+ });
788
793
  }
789
794
 
790
- function bytesToBase64(data, { encoding = "base64", padding } = {}) {
791
- if (encoding === "base64") {
792
- return base64.encode(data, { includePadding: padding ?? true });
793
- } else if (encoding === "base64url") {
794
- return base64url.encode(data, { includePadding: padding ?? false });
795
- }
796
- ok(false, "Invalid encoding options: " + encoding);
797
- }
795
+ let AssertionError;
796
+ (async () => {
797
+ AssertionError = globalThis.window ? await Promise.resolve().then(function () { return BrowserAssertionError$1; }).then(
798
+ (r) => r.BrowserAssertionError
799
+ ) : await import('node:assert').then((r) => r.AssertionError);
800
+ })();
798
801
 
799
- function compareBytes(a, b) {
800
- if (a.byteLength !== b.byteLength) {
801
- return false;
802
- }
803
- for (let i = 0; i < b.byteLength; i++) {
804
- if (a[i] !== b[i]) {
805
- return false;
806
- }
802
+ function ok(value, message) {
803
+ if (!value) {
804
+ throw toError$1(
805
+ ok,
806
+ value,
807
+ message,
808
+ "The expression evaluated to a falsy value."
809
+ );
807
810
  }
808
- return true;
809
811
  }
810
-
811
- function concatenateBytes(a, b) {
812
- const result = new Uint8Array(a.byteLength + b.byteLength);
813
- result.set(a);
814
- result.set(b, a.byteLength);
815
- return result;
812
+ function equal(actual, expected, message) {
813
+ if (actual !== expected) {
814
+ new AssertionError({
815
+ actual,
816
+ expected,
817
+ message: isString(message) ? message : "The actual value not as expected.",
818
+ operator: "equal",
819
+ stackStartFn: equal
820
+ });
821
+ }
816
822
  }
817
-
818
- function uint16ToUint8(value) {
819
- const uint8Array = new Uint8Array(value.length * 2);
820
- for (let i = 0; i < value.length; i++) {
821
- uint8Array[i * 2] = value[i] & 255;
822
- uint8Array[i * 2 + 1] = value[i] >> 8;
823
+ function notEmpty(value, message) {
824
+ if (isEmpty(value)) {
825
+ throw toError$1(notEmpty, value, message, "Expected not empty value.");
823
826
  }
824
- return uint8Array;
825
827
  }
826
-
827
- function uint32ToUint8(value) {
828
- const uint8Array = new Uint8Array(value.length * 4);
829
- for (let i = 0; i < value.length; i++) {
830
- uint8Array[i * 4] = value[i] & 255;
831
- uint8Array[i * 4 + 1] = value[i] >> 8 & 255;
832
- uint8Array[i * 4 + 2] = value[i] >> 16 & 255;
833
- uint8Array[i * 4 + 3] = value[i] >> 24 & 255;
828
+ function object(value, message) {
829
+ if (!isObject(value)) {
830
+ throw toError$1(object, value, message, "Expected object value.");
834
831
  }
835
- return uint8Array;
836
832
  }
837
-
838
- function uint8ToUint16(value) {
839
- ok(
840
- value.length % 2 === 0,
841
- "Uint8Array length must be even for conversion to Uint16Array"
842
- );
843
- const uint16Array = new Uint16Array(value.length / 2);
844
- for (let i = 0; i < uint16Array.length; i++) {
845
- uint16Array[i] = value[i * 2] << 8 | value[i * 2 + 1];
833
+ function string(value, message) {
834
+ if (!isString(value)) {
835
+ throw toError$1(string, value, message, "Expected string value.");
846
836
  }
847
- return uint16Array;
848
837
  }
849
-
850
- function uint8ToUint32(value) {
851
- ok(
852
- value.length % 4 === 0,
853
- "Uint8Array length must be a multiple of 4 for conversion to Uint32Array"
854
- );
855
- const uint32Array = new Uint32Array(value.length / 4);
856
- for (let i = 0; i < uint32Array.length; i++) {
857
- uint32Array[i] = value[i * 4] << 24 | value[i * 4 + 1] << 16 | value[i * 4 + 2] << 8 | value[i * 4 + 3];
838
+ function boolean(value, message) {
839
+ if (!isBoolean(value)) {
840
+ throw toError$1(boolean, value, message, "Expected boolean value.");
858
841
  }
859
- return uint32Array;
860
842
  }
861
-
862
- const def = (obj, key, value, writable = false) => {
863
- Object.defineProperty(obj, key, {
864
- configurable: true,
865
- enumerable: false,
866
- writable,
867
- value
868
- });
869
- };
870
-
871
- const rndCharacters = "abcdefghijklmnopqrstuvwxyz0123456789";
872
- const charactersLength = rndCharacters.length;
873
- function randomString(length) {
874
- let str = "";
875
- let num = isNumber(length) ? Math.max(0, length) : 0;
876
- while (num--) {
877
- str += rndCharacters[charactersLength * Math.random() | 0];
843
+ function notEmptyString(value, message) {
844
+ if (!isString(value) || !value.trim()) {
845
+ throw toError$1(
846
+ notEmptyString,
847
+ value,
848
+ message,
849
+ "Expected not empty string value."
850
+ );
878
851
  }
879
- return str;
880
852
  }
881
-
882
- const objectKeys = /* @__PURE__ */ new WeakMap();
883
- const BSON_TYPES = Object.freeze(/* @__PURE__ */ new Set(["ObjectID", "ObjectId"]));
884
- const SYM_WITH_CACHE = Symbol();
885
- const argToKey = (value, options = { objectStrategy: "ref" }) => {
886
- let result = "";
887
- if (isObject(value)) {
888
- if (BSON_TYPES.has(value?._bsontype)) {
889
- return String(value);
890
- }
891
- let key;
892
- if (options.objectStrategy === "json") {
893
- key = JSON.stringify(value);
894
- } else {
895
- key = objectKeys.get(value);
896
- if (!key) {
897
- key = createRadomKey();
898
- objectKeys.set(value, key);
899
- }
900
- }
901
- return key;
902
- } else if (Array.isArray(value)) {
903
- result += value.map((v) => argToKey(v, options)).join("/");
904
- } else {
905
- result = String(value);
853
+ function number$1(value, message) {
854
+ if (!isNumber(value)) {
855
+ throw toError$1(number$1, value, message, "Expected number value.");
906
856
  }
907
- return result;
908
- };
909
- function createRadomKey() {
910
- return Date.now() + "_" + randomString(16);
911
- }
912
-
913
- function createWithCache({
914
- fn,
915
- getPointer,
916
- getBucket,
917
- objectStrategy = "ref"
918
- }) {
919
- const isAsync = fn.constructor.name === "AsyncFunction";
920
- const argToKeyOptions = { objectStrategy };
921
- const $cache = {
922
- getBucket: () => getBucket(getPointer()),
923
- getPointer,
924
- argToKeyOptions
925
- };
926
- const wrapFn = function(...args) {
927
- const storage = getBucket(getPointer());
928
- const cacheKey = args.map((v) => argToKey(v, argToKeyOptions)).join("_");
929
- if (storage.has(cacheKey)) {
930
- const value = storage.get(cacheKey);
931
- return isAsync ? Promise.resolve(value) : value;
932
- }
933
- const newValue = fn.apply(this, args);
934
- if (isPromise(newValue)) {
935
- return newValue.then((value) => {
936
- storage.set(cacheKey, value);
937
- return value;
938
- });
939
- }
940
- storage.set(cacheKey, newValue);
941
- return newValue;
942
- };
943
- wrapFn.$cache = $cache;
944
- def(wrapFn, SYM_WITH_CACHE, true);
945
- return wrapFn;
946
- }
947
- function isWithCache(value) {
948
- return !!value && value[SYM_WITH_CACHE] === true;
949
857
  }
950
-
951
- const cache = /* @__PURE__ */ new WeakMap();
952
- function withCache(...args) {
953
- let options = {};
954
- let fn = noop;
955
- if (isFunction(args[0])) {
956
- fn = args[0];
957
- } else if (isFunction(args[1])) {
958
- options = args[0] || {};
959
- fn = args[1];
858
+ function date(value, message) {
859
+ if (!isDate(value)) {
860
+ throw toError$1(date, value, message, "Expected date value.");
960
861
  }
961
- const pointer = options.cachePointer || fn;
962
- const getPointer = () => pointer;
963
- const getBucket = (pointer2) => {
964
- let fnCache = cache.get(pointer2);
965
- if (!fnCache) {
966
- fnCache = /* @__PURE__ */ new Map();
967
- cache.set(pointer2, fnCache);
968
- }
969
- return fnCache;
970
- };
971
- return createWithCache({
972
- fn,
973
- getBucket,
974
- getPointer,
975
- ...options
976
- });
977
- }
978
-
979
- function assertCapacity(value) {
980
- number$1(value, "capacity must be a number");
981
- ok(value > 0, "capacity must be more then 0.");
982
862
  }
983
-
984
- class FixedMap extends Map {
985
- constructor(_capacity) {
986
- assertCapacity(_capacity);
987
- super();
988
- this._capacity = _capacity;
989
- this._tail = [];
863
+ function fn(value, message) {
864
+ if (!isFunction(value)) {
865
+ throw toError$1(fn, value, message, "Expected function value.");
990
866
  }
991
- _tail;
992
- set(key, value) {
993
- if (!super.has.call(this, key)) {
994
- this._tail.push(key);
995
- }
996
- super.set.call(this, key, value);
997
- this._drain();
998
- return this;
867
+ }
868
+ function greaterThan(value, target, message) {
869
+ if (!isNumber(value) || value < target) {
870
+ throw toError$1(
871
+ greaterThan,
872
+ value,
873
+ message,
874
+ "Expected number value greater then " + target + "."
875
+ );
999
876
  }
1000
- delete(key) {
1001
- const removed = super.delete.call(this, key);
1002
- if (removed) {
1003
- const idx = this._tail.findIndex((v) => v === key);
1004
- if (idx > -1) {
1005
- this._tail.splice(idx, 1);
1006
- }
1007
- }
1008
- return removed;
877
+ }
878
+ function lessThan(value, target, message) {
879
+ if (!isNumber(value) || value > target) {
880
+ throw toError$1(
881
+ lessThan,
882
+ value,
883
+ message,
884
+ "Expected number value less then " + target + "."
885
+ );
1009
886
  }
1010
- clear() {
1011
- delete this._tail;
1012
- this._tail = [];
1013
- super.clear.call(this);
887
+ }
888
+ function array(value, message) {
889
+ if (!Array.isArray(value)) {
890
+ throw toError$1(array, value, message, "Expected array value.");
1014
891
  }
1015
- get capacity() {
1016
- return this._capacity;
892
+ }
893
+ function arrayStrings(value, message) {
894
+ if (!Array.isArray(value) || !value.every(isString)) {
895
+ throw toError$1(arrayStrings, value, message, "Expected strings list value.");
1017
896
  }
1018
- set capacity(value) {
1019
- assertCapacity(value);
1020
- this._capacity = value;
1021
- this._drain();
897
+ }
898
+ function arrayNumbers(value, message) {
899
+ if (!Array.isArray(value) || !value.every(isNumber)) {
900
+ throw toError$1(arrayNumbers, value, message, "Expected numbers list value.");
1022
901
  }
1023
- _drain() {
1024
- while (this._tail.length > this._capacity) {
1025
- const key = this._tail.shift();
1026
- key !== void 0 && this.delete(key);
1027
- }
902
+ }
903
+ function toError$1(operator, actual, message, unknownMessage = "Unknown error") {
904
+ if (isError(message)) {
905
+ return message;
1028
906
  }
907
+ return new AssertionError({
908
+ actual,
909
+ message: isString(message) ? message : unknownMessage,
910
+ operator: operator.name,
911
+ stackStartFn: operator
912
+ });
1029
913
  }
1030
914
 
1031
- class TimeBucket {
1032
- _pointer;
1033
- _sizeMs;
1034
- _bucket;
1035
- constructor({ capacity = Infinity, sizeMs }) {
1036
- assetSizeMs(sizeMs);
1037
- this._sizeMs = sizeMs;
1038
- this._pointer = 0;
915
+ const assert = {
916
+ __proto__: null,
917
+ array: array,
918
+ arrayNumbers: arrayNumbers,
919
+ arrayStrings: arrayStrings,
920
+ boolean: boolean,
921
+ date: date,
922
+ equal: equal,
923
+ fn: fn,
924
+ greaterThan: greaterThan,
925
+ lessThan: lessThan,
926
+ notEmpty: notEmpty,
927
+ notEmptyString: notEmptyString,
928
+ number: number$1,
929
+ object: object,
930
+ ok: ok,
931
+ string: string
932
+ };
933
+
934
+ function weightedRoundRobin(arr) {
935
+ ok(arr.length > 0, "Array must contain at least one item.");
936
+ const instance = new WeightedRoundRobin(
937
+ arr.map((v) => ({
938
+ item: v.item,
939
+ weight: Math.min(v.weight ?? 1, 1)
940
+ }))
941
+ );
942
+ return () => instance.nextItem();
943
+ }
944
+ const gcd = (a, b) => !b ? a : gcd(b, a % b);
945
+ class WeightedRoundRobin {
946
+ constructor(items) {
947
+ this.items = items;
948
+ this.maxWeight = this._calculateMaxWeight();
949
+ this.gcdWeight = this._calculateGCD();
950
+ }
951
+ currentIndex = -1;
952
+ currentWeight = 0;
953
+ maxWeight;
954
+ gcdWeight;
955
+ _calculateGCD() {
956
+ return this.items.reduce(
957
+ (acc, curr) => gcd(acc, curr.weight),
958
+ this.items[0].weight
959
+ );
960
+ }
961
+ _calculateMaxWeight() {
962
+ return Math.max(...this.items.map((s) => s.weight));
963
+ }
964
+ nextItem() {
965
+ const n = this.items.length;
966
+ while (true) {
967
+ this.currentIndex = (this.currentIndex + 1) % n;
968
+ if (this.currentIndex === 0) {
969
+ this.currentWeight -= this.gcdWeight;
970
+ if (this.currentWeight <= 0) {
971
+ this.currentWeight = this.maxWeight;
972
+ }
973
+ }
974
+ if (this.items[this.currentIndex].weight >= this.currentWeight) {
975
+ return this.items[this.currentIndex].item;
976
+ }
977
+ }
978
+ }
979
+ }
980
+
981
+ function basex(alphabet) {
982
+ var BASE = BigInt(alphabet.length);
983
+ var ZERO_CHAR = alphabet[0];
984
+ var CHAR_INDEX = {};
985
+ for (let idx = 0; idx < alphabet.length; idx++) {
986
+ CHAR_INDEX[alphabet[idx]] = idx;
987
+ }
988
+ return {
989
+ alphabet,
990
+ padding: "",
991
+ encode,
992
+ decode
993
+ };
994
+ function encode(input) {
995
+ var value = 0n;
996
+ var i = 0;
997
+ var result = new Array((input.length * 8 / 5 | 0) + 1);
998
+ var pos = result.length;
999
+ var leadingZeros = 0;
1000
+ var rem = 0n;
1001
+ for (i = 0; i < input.length; i++) {
1002
+ value = (value << 8n) + BigInt(input[i]);
1003
+ }
1004
+ while (value > 0) {
1005
+ rem = value % BASE;
1006
+ result[--pos] = alphabet[Number(rem)];
1007
+ value = value / BASE;
1008
+ }
1009
+ while (leadingZeros < input.length && input[leadingZeros] === 0) {
1010
+ result[--pos] = ZERO_CHAR;
1011
+ leadingZeros++;
1012
+ }
1013
+ return result.slice(pos).join("");
1014
+ }
1015
+ function decode(input) {
1016
+ var value = 0n;
1017
+ var leadingZeros = 0;
1018
+ var i = 0;
1019
+ var char = "";
1020
+ var index = 0;
1021
+ var bytes = new Uint8Array(input.length * 1.25 | 0);
1022
+ var pos = bytes.length;
1023
+ while (leadingZeros < input.length && input[leadingZeros] === ZERO_CHAR) {
1024
+ leadingZeros++;
1025
+ }
1026
+ for (i = leadingZeros; i < input.length; i++) {
1027
+ char = input[i];
1028
+ index = CHAR_INDEX[char];
1029
+ if (index === void 0) throw new Error("Invalid base62 character");
1030
+ value = value * BASE + BigInt(index);
1031
+ }
1032
+ while (value > 0) {
1033
+ bytes[--pos] = Number(value & 0xffn);
1034
+ value >>= 8n;
1035
+ }
1036
+ return bytes.subarray(pos - leadingZeros);
1037
+ }
1038
+ }
1039
+
1040
+ const base62 = basex(
1041
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
1042
+ );
1043
+
1044
+ var ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1045
+ var ENCODE_TABLE = new TextEncoder().encode(ALPHABET);
1046
+ var DECODE_TABLE = new Uint8Array(256);
1047
+ for (let i = 0; i < ENCODE_TABLE.length; ++i) {
1048
+ DECODE_TABLE[ENCODE_TABLE[i]] = i;
1049
+ }
1050
+ var LOG2_TABLE = new Uint8Array(62);
1051
+ LOG2_TABLE[0] = 1;
1052
+ for (let i = 1; i < 62; ++i) {
1053
+ LOG2_TABLE[i] = Math.ceil(Math.log2(i + 1));
1054
+ }
1055
+ const allocEncode = createAllocator();
1056
+ const base62Fast = {
1057
+ alphabet: ALPHABET,
1058
+ padding: "",
1059
+ /**
1060
+ * Encodes a Uint8Array into a Base62 string using a custom 5/6-bit variable length scheme.
1061
+ * Processes bits from right to left (most significant bit first conceptually).
1062
+ * @param input The Uint8Array to encode.
1063
+ * @returns The encoded Base62 string.
1064
+ */
1065
+ encode(input) {
1066
+ var position = input.length * 8;
1067
+ var output = allocEncode((position / 5 | 0) + 1);
1068
+ var outputIndex = 0;
1069
+ var chunkSize;
1070
+ var remainderBits;
1071
+ var byteIndex;
1072
+ var extractedBits;
1073
+ var value;
1074
+ while (position > 0) {
1075
+ chunkSize = 6;
1076
+ remainderBits = position & 7;
1077
+ byteIndex = position >>> 3;
1078
+ if (remainderBits === 0) {
1079
+ byteIndex -= 1;
1080
+ remainderBits = 8;
1081
+ }
1082
+ extractedBits = input[byteIndex] >> 8 - remainderBits;
1083
+ if (remainderBits < 6 && byteIndex > 0) {
1084
+ extractedBits |= input[byteIndex - 1] << remainderBits;
1085
+ }
1086
+ value = extractedBits & 63;
1087
+ if ((value & 30) === 30) {
1088
+ if (position > 6 || value > 31) {
1089
+ chunkSize = 5;
1090
+ value &= 31;
1091
+ }
1092
+ }
1093
+ output[outputIndex] = ENCODE_TABLE[additiveCipher(value, outputIndex % 63)];
1094
+ outputIndex++;
1095
+ position -= chunkSize;
1096
+ }
1097
+ return new TextDecoder().decode(output.subarray(0, outputIndex));
1098
+ },
1099
+ /**
1100
+ * Decodes a Base62 string generated by the custom encoder back into a Uint8Array.
1101
+ * @param input The Base62 string to decode.
1102
+ * @returns The decoded Uint8Array.
1103
+ */
1104
+ decode(input) {
1105
+ var inputLength = input.length;
1106
+ var maxOutputLength = inputLength * 6 / 8 | 0;
1107
+ var output = new Uint8Array(maxOutputLength);
1108
+ var writeIndex = maxOutputLength;
1109
+ var bitPosition = 0;
1110
+ var buffer = 0;
1111
+ var charCode = 0;
1112
+ var value = 0;
1113
+ for (var readIndex = 0; readIndex < inputLength; readIndex++) {
1114
+ charCode = input.charCodeAt(readIndex);
1115
+ value = DECODE_TABLE[charCode];
1116
+ value = DECODE_TABLE[ENCODE_TABLE[additiveCipherReverse(value, readIndex % 63)]];
1117
+ if (isNaN(charCode) || value === void 0) {
1118
+ throw new Error(
1119
+ "Invalid Base62 input: contains non-alphabet characters. Index: " + readIndex
1120
+ );
1121
+ }
1122
+ buffer |= value << bitPosition;
1123
+ if (readIndex === inputLength - 1) {
1124
+ if (LOG2_TABLE[value] === void 0) {
1125
+ throw new Error(
1126
+ "Invalid Base62 input: unexpected value for last character."
1127
+ );
1128
+ }
1129
+ bitPosition += LOG2_TABLE[value];
1130
+ } else if ((value & 30) === 30) {
1131
+ bitPosition += 5;
1132
+ } else {
1133
+ bitPosition += 6;
1134
+ }
1135
+ if (bitPosition >= 8) {
1136
+ output[--writeIndex] = buffer;
1137
+ bitPosition &= 7;
1138
+ buffer >>= 8;
1139
+ }
1140
+ }
1141
+ if (bitPosition > 0) {
1142
+ output[--writeIndex] = buffer;
1143
+ }
1144
+ return output.subarray(writeIndex);
1145
+ }
1146
+ };
1147
+ function createAllocator() {
1148
+ var currentBuffer = new Uint8Array(512);
1149
+ var currentSize = 512;
1150
+ return (size) => {
1151
+ if (currentSize < size) {
1152
+ currentBuffer = new Uint8Array(size);
1153
+ currentSize = size;
1154
+ }
1155
+ return currentBuffer;
1156
+ };
1157
+ }
1158
+ function additiveCipher(value, shift) {
1159
+ return (value + shift) % 62;
1160
+ }
1161
+ function additiveCipherReverse(obscured, shift) {
1162
+ return (obscured - shift + 62) % 62;
1163
+ }
1164
+
1165
+ class Base64Encoding {
1166
+ alphabet;
1167
+ padding;
1168
+ decodeMap = /* @__PURE__ */ new Map();
1169
+ constructor(alphabet, options) {
1170
+ if (alphabet.length !== 64) {
1171
+ throw new Error("Invalid alphabet");
1172
+ }
1173
+ this.alphabet = alphabet;
1174
+ this.padding = options?.padding ?? "=";
1175
+ if (this.alphabet.includes(this.padding) || this.padding.length !== 1) {
1176
+ throw new Error("Invalid padding");
1177
+ }
1178
+ for (let i = 0; i < alphabet.length; i++) {
1179
+ this.decodeMap.set(alphabet[i], i);
1180
+ }
1181
+ }
1182
+ /**
1183
+ * Encodes binary data into a base64 string representation
1184
+ *
1185
+ * @param input - The binary data to encode
1186
+ * @returns The encoded string
1187
+ *
1188
+ * @example
1189
+ * ```typescript
1190
+ * const data = new Uint8Array([255, 255]);
1191
+ * console.log(base64.encode(data));
1192
+ * ```
1193
+ */
1194
+ encode(data, options) {
1195
+ let result = "";
1196
+ let buffer = 0;
1197
+ let shift = 0;
1198
+ for (let i = 0; i < data.length; i++) {
1199
+ buffer = buffer << 8 | data[i];
1200
+ shift += 8;
1201
+ while (shift >= 6) {
1202
+ shift += -6;
1203
+ result += this.alphabet[buffer >> shift & 63];
1204
+ }
1205
+ }
1206
+ if (shift > 0) {
1207
+ result += this.alphabet[buffer << 6 - shift & 63];
1208
+ }
1209
+ const includePadding = options?.includePadding ?? true;
1210
+ if (includePadding) {
1211
+ const padCount = (4 - result.length % 4) % 4;
1212
+ for (let i = 0; i < padCount; i++) {
1213
+ result += "=";
1214
+ }
1215
+ }
1216
+ return result;
1217
+ }
1218
+ /**
1219
+ * Decodes a base64 string back into binary data
1220
+ *
1221
+ * @param input - The encoded string to decode
1222
+ * @returns The decoded binary data
1223
+ * @throws {Error} When the input contains invalid characters or format
1224
+ *
1225
+ * @example
1226
+ * ```typescript
1227
+ * const encoded = "AA==";
1228
+ * console.log(base64.decode(encoded)); // Uint8Array [255, 255]
1229
+ * ```
1230
+ */
1231
+ decode(data, options) {
1232
+ const strict = options?.strict ?? true;
1233
+ const chunkCount = Math.ceil(data.length / 4);
1234
+ const result = [];
1235
+ for (let i = 0; i < chunkCount; i++) {
1236
+ let padCount = 0;
1237
+ let buffer = 0;
1238
+ for (let j = 0; j < 4; j++) {
1239
+ const encoded = data[i * 4 + j];
1240
+ if (encoded === "=") {
1241
+ if (i + 1 !== chunkCount) {
1242
+ throw new Error(`Invalid character: ${encoded}`);
1243
+ }
1244
+ padCount += 1;
1245
+ continue;
1246
+ }
1247
+ if (encoded === void 0) {
1248
+ if (strict) {
1249
+ throw new Error("Invalid data");
1250
+ }
1251
+ padCount += 1;
1252
+ continue;
1253
+ }
1254
+ const value = this.decodeMap.get(encoded) ?? null;
1255
+ if (value === null) {
1256
+ throw new Error(`Invalid character: ${encoded}`);
1257
+ }
1258
+ buffer += value << 6 * (3 - j);
1259
+ }
1260
+ result.push(buffer >> 16 & 255);
1261
+ if (padCount < 2) {
1262
+ result.push(buffer >> 8 & 255);
1263
+ }
1264
+ if (padCount < 1) {
1265
+ result.push(buffer & 255);
1266
+ }
1267
+ }
1268
+ return Uint8Array.from(result);
1269
+ }
1270
+ }
1271
+
1272
+ const base64 = new Base64Encoding(
1273
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
1274
+ );
1275
+ const base64url = new Base64Encoding(
1276
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
1277
+ );
1278
+
1279
+ function base64ToBytes(data, { encoding = "base64", strict } = {}) {
1280
+ if (encoding === "base64") {
1281
+ return base64.decode(data, { strict: strict ?? true });
1282
+ } else if (encoding === "base64url") {
1283
+ return base64url.decode(data, { strict: strict ?? false });
1284
+ }
1285
+ ok(false, "Invalid encoding options: " + encoding);
1286
+ }
1287
+
1288
+ function bigIntBytes(value) {
1289
+ if (value < 0n) {
1290
+ value = value * -1n;
1291
+ }
1292
+ let byteLength = 1;
1293
+ while (value > 2n ** BigInt(byteLength * 8) - 1n) {
1294
+ byteLength++;
1295
+ }
1296
+ const encoded = new Uint8Array(byteLength);
1297
+ for (let i = 0; i < encoded.byteLength; i++) {
1298
+ encoded[i] = Number(
1299
+ value >> BigInt((encoded.byteLength - i - 1) * 8) & 0xffn
1300
+ );
1301
+ }
1302
+ return encoded;
1303
+ }
1304
+
1305
+ function bigIntFromBytes(bytes) {
1306
+ ok(bytes.byteLength > 0, "Empty Uint8Array");
1307
+ let decoded = 0n;
1308
+ for (let i = 0; i < bytes.byteLength; i++) {
1309
+ decoded += BigInt(bytes[i]) << BigInt((bytes.byteLength - 1 - i) * 8);
1310
+ }
1311
+ return decoded;
1312
+ }
1313
+
1314
+ function bytesToBase64(data, { encoding = "base64", padding } = {}) {
1315
+ if (encoding === "base64") {
1316
+ return base64.encode(data, { includePadding: padding ?? true });
1317
+ } else if (encoding === "base64url") {
1318
+ return base64url.encode(data, { includePadding: padding ?? false });
1319
+ }
1320
+ ok(false, "Invalid encoding options: " + encoding);
1321
+ }
1322
+
1323
+ function compareBytes(a, b) {
1324
+ if (a.byteLength !== b.byteLength) {
1325
+ return false;
1326
+ }
1327
+ for (let i = 0; i < b.byteLength; i++) {
1328
+ if (a[i] !== b[i]) {
1329
+ return false;
1330
+ }
1331
+ }
1332
+ return true;
1333
+ }
1334
+
1335
+ function concatenateBytes(a, b) {
1336
+ const result = new Uint8Array(a.byteLength + b.byteLength);
1337
+ result.set(a);
1338
+ result.set(b, a.byteLength);
1339
+ return result;
1340
+ }
1341
+
1342
+ function uint16ToUint8(value) {
1343
+ const uint8Array = new Uint8Array(value.length * 2);
1344
+ for (let i = 0; i < value.length; i++) {
1345
+ uint8Array[i * 2] = value[i] & 255;
1346
+ uint8Array[i * 2 + 1] = value[i] >> 8;
1347
+ }
1348
+ return uint8Array;
1349
+ }
1350
+
1351
+ function uint32ToUint8(value) {
1352
+ const uint8Array = new Uint8Array(value.length * 4);
1353
+ for (let i = 0; i < value.length; i++) {
1354
+ uint8Array[i * 4] = value[i] & 255;
1355
+ uint8Array[i * 4 + 1] = value[i] >> 8 & 255;
1356
+ uint8Array[i * 4 + 2] = value[i] >> 16 & 255;
1357
+ uint8Array[i * 4 + 3] = value[i] >> 24 & 255;
1358
+ }
1359
+ return uint8Array;
1360
+ }
1361
+
1362
+ function uint8ToUint16(value) {
1363
+ ok(
1364
+ value.length % 2 === 0,
1365
+ "Uint8Array length must be even for conversion to Uint16Array"
1366
+ );
1367
+ const uint16Array = new Uint16Array(value.length / 2);
1368
+ for (let i = 0; i < uint16Array.length; i++) {
1369
+ uint16Array[i] = value[i * 2] << 8 | value[i * 2 + 1];
1370
+ }
1371
+ return uint16Array;
1372
+ }
1373
+
1374
+ function uint8ToUint32(value) {
1375
+ ok(
1376
+ value.length % 4 === 0,
1377
+ "Uint8Array length must be a multiple of 4 for conversion to Uint32Array"
1378
+ );
1379
+ const uint32Array = new Uint32Array(value.length / 4);
1380
+ for (let i = 0; i < uint32Array.length; i++) {
1381
+ uint32Array[i] = value[i * 4] << 24 | value[i * 4 + 1] << 16 | value[i * 4 + 2] << 8 | value[i * 4 + 3];
1382
+ }
1383
+ return uint32Array;
1384
+ }
1385
+
1386
+ const rndCharacters = "abcdefghijklmnopqrstuvwxyz0123456789";
1387
+ const charactersLength = rndCharacters.length;
1388
+ function randomString(length) {
1389
+ let str = "";
1390
+ let num = isNumber(length) ? Math.max(0, length) : 0;
1391
+ while (num--) {
1392
+ str += rndCharacters[charactersLength * Math.random() | 0];
1393
+ }
1394
+ return str;
1395
+ }
1396
+
1397
+ const objectKeys = /* @__PURE__ */ new WeakMap();
1398
+ const BSON_TYPES = Object.freeze(/* @__PURE__ */ new Set(["ObjectID", "ObjectId"]));
1399
+ const SYM_WITH_CACHE = Symbol();
1400
+ const argToKey = (value, options = { objectStrategy: "ref" }) => {
1401
+ let result = "";
1402
+ if (isObject(value)) {
1403
+ if (BSON_TYPES.has(value?._bsontype)) {
1404
+ return String(value);
1405
+ }
1406
+ let key;
1407
+ if (options.objectStrategy === "json") {
1408
+ key = JSON.stringify(value);
1409
+ } else {
1410
+ key = objectKeys.get(value);
1411
+ if (!key) {
1412
+ key = createRadomKey();
1413
+ objectKeys.set(value, key);
1414
+ }
1415
+ }
1416
+ return key;
1417
+ } else if (Array.isArray(value)) {
1418
+ result += value.map((v) => argToKey(v, options)).join("/");
1419
+ } else {
1420
+ result = String(value);
1421
+ }
1422
+ return result;
1423
+ };
1424
+ function createRadomKey() {
1425
+ return Date.now() + "_" + randomString(16);
1426
+ }
1427
+
1428
+ function createWithCache({
1429
+ fn,
1430
+ getPointer,
1431
+ getBucket,
1432
+ objectStrategy = "ref"
1433
+ }) {
1434
+ const isAsync = fn.constructor.name === "AsyncFunction";
1435
+ const argToKeyOptions = { objectStrategy };
1436
+ const $cache = {
1437
+ getBucket: () => getBucket(getPointer()),
1438
+ getPointer,
1439
+ argToKeyOptions
1440
+ };
1441
+ const wrapFn = function(...args) {
1442
+ const storage = getBucket(getPointer());
1443
+ const cacheKey = args.map((v) => argToKey(v, argToKeyOptions)).join("_");
1444
+ if (storage.has(cacheKey)) {
1445
+ const value = storage.get(cacheKey);
1446
+ return isAsync ? Promise.resolve(value) : value;
1447
+ }
1448
+ const newValue = fn.apply(this, args);
1449
+ if (isPromise(newValue)) {
1450
+ return newValue.then((value) => {
1451
+ storage.set(cacheKey, value);
1452
+ return value;
1453
+ });
1454
+ }
1455
+ storage.set(cacheKey, newValue);
1456
+ return newValue;
1457
+ };
1458
+ wrapFn.$cache = $cache;
1459
+ def(wrapFn, SYM_WITH_CACHE, true);
1460
+ return wrapFn;
1461
+ }
1462
+ function isWithCache(value) {
1463
+ return !!value && value[SYM_WITH_CACHE] === true;
1464
+ }
1465
+
1466
+ const cache = /* @__PURE__ */ new WeakMap();
1467
+ function withCache(...args) {
1468
+ let options = {};
1469
+ let fn = noop;
1470
+ if (isFunction(args[0])) {
1471
+ fn = args[0];
1472
+ } else if (isFunction(args[1])) {
1473
+ options = args[0] || {};
1474
+ fn = args[1];
1475
+ }
1476
+ const pointer = options.cachePointer || fn;
1477
+ const getPointer = () => pointer;
1478
+ const getBucket = (pointer2) => {
1479
+ let fnCache = cache.get(pointer2);
1480
+ if (!fnCache) {
1481
+ fnCache = /* @__PURE__ */ new Map();
1482
+ cache.set(pointer2, fnCache);
1483
+ }
1484
+ return fnCache;
1485
+ };
1486
+ return createWithCache({
1487
+ fn,
1488
+ getBucket,
1489
+ getPointer,
1490
+ ...options
1491
+ });
1492
+ }
1493
+
1494
+ function assertCapacity(value) {
1495
+ number$1(value, "capacity must be a number");
1496
+ ok(value > 0, "capacity must be more then 0.");
1497
+ }
1498
+
1499
+ class FixedMap extends Map {
1500
+ constructor(_capacity) {
1501
+ assertCapacity(_capacity);
1502
+ super();
1503
+ this._capacity = _capacity;
1504
+ this._tail = [];
1505
+ }
1506
+ _tail;
1507
+ set(key, value) {
1508
+ if (!super.has.call(this, key)) {
1509
+ this._tail.push(key);
1510
+ }
1511
+ super.set.call(this, key, value);
1512
+ this._drain();
1513
+ return this;
1514
+ }
1515
+ delete(key) {
1516
+ const removed = super.delete.call(this, key);
1517
+ if (removed) {
1518
+ const idx = this._tail.findIndex((v) => v === key);
1519
+ if (idx > -1) {
1520
+ this._tail.splice(idx, 1);
1521
+ }
1522
+ }
1523
+ return removed;
1524
+ }
1525
+ clear() {
1526
+ delete this._tail;
1527
+ this._tail = [];
1528
+ super.clear.call(this);
1529
+ }
1530
+ get capacity() {
1531
+ return this._capacity;
1532
+ }
1533
+ set capacity(value) {
1534
+ assertCapacity(value);
1535
+ this._capacity = value;
1536
+ this._drain();
1537
+ }
1538
+ _drain() {
1539
+ while (this._tail.length > this._capacity) {
1540
+ const key = this._tail.shift();
1541
+ key !== void 0 && this.delete(key);
1542
+ }
1543
+ }
1544
+ }
1545
+
1546
+ class TimeBucket {
1547
+ _pointer;
1548
+ _sizeMs;
1549
+ _bucket;
1550
+ constructor({ capacity = Infinity, sizeMs }) {
1551
+ assetSizeMs(sizeMs);
1552
+ this._sizeMs = sizeMs;
1553
+ this._pointer = 0;
1039
1554
  this._bucket = capacity === Infinity ? /* @__PURE__ */ new Map() : new FixedMap(capacity);
1040
1555
  }
1041
1556
  get capacity() {
@@ -1307,537 +1822,234 @@ class LruCache {
1307
1822
  return {
1308
1823
  done: false,
1309
1824
  value: [key, value]
1310
- };
1311
- }
1312
- };
1313
- return {
1314
- ...iterator,
1315
- [Symbol.iterator]() {
1316
- return this;
1317
- }
1318
- };
1319
- }
1320
- /**
1321
- * Method used to splay a value on top.
1322
- *
1323
- * @param {number} pointer - Pointer of the value to splay on top.
1324
- */
1325
- splayOnTop(pointer) {
1326
- const oldHead = this.head;
1327
- if (this.head === pointer) return this;
1328
- const previous = this.backward[pointer], next = this.forward[pointer];
1329
- if (this.tail === pointer) {
1330
- this.tail = previous;
1331
- } else {
1332
- this.backward[next] = previous;
1333
- }
1334
- this.forward[previous] = next;
1335
- this.backward[oldHead] = pointer;
1336
- this.head = pointer;
1337
- this.forward[pointer] = oldHead;
1338
- return this;
1339
- }
1340
- [Symbol.iterator]() {
1341
- return this.entries();
1342
- }
1343
- }
1344
- const MAX_8BIT_INTEGER = Math.pow(2, 8) - 1, MAX_16BIT_INTEGER = Math.pow(2, 16) - 1, MAX_32BIT_INTEGER = Math.pow(2, 32) - 1;
1345
- function pointerArray(size) {
1346
- const maxIndex = size - 1;
1347
- if (maxIndex <= MAX_8BIT_INTEGER) return new Uint8Array(size);
1348
- if (maxIndex <= MAX_16BIT_INTEGER) return new Uint16Array(size);
1349
- if (maxIndex <= MAX_32BIT_INTEGER) return new Uint32Array(size);
1350
- throw new Error("Pointer Array of size > 4294967295 is not supported.");
1351
- }
1352
-
1353
- const cacheLRU = /* @__PURE__ */ new WeakMap();
1354
- function withCacheLRU({ capacity, cachePointer, ...options }, fn) {
1355
- const pointer = cachePointer || fn;
1356
- const getPointer = () => {
1357
- return pointer;
1358
- };
1359
- const getBucket = () => {
1360
- let fnCache = cacheLRU.get(pointer);
1361
- if (!fnCache) {
1362
- fnCache = new LruCache(capacity);
1363
- cacheLRU.set(pointer, fnCache);
1364
- }
1365
- return fnCache;
1366
- };
1367
- return createWithCache({
1368
- fn,
1369
- getBucket,
1370
- getPointer,
1371
- ...options
1372
- });
1373
- }
1374
-
1375
- function dropCache(cachePointer, ...args) {
1376
- let argToKeyOptions = { objectStrategy: "ref" };
1377
- let removed = false;
1378
- if (isWithCache(cachePointer)) {
1379
- argToKeyOptions = cachePointer.$cache.argToKeyOptions;
1380
- }
1381
- const cacheKey = args.map((v) => argToKey(v, argToKeyOptions)).join("_");
1382
- if (isWithCache(cachePointer)) {
1383
- if (cachePointer.$cache.getBucket().has(cacheKey)) {
1384
- removed = true;
1385
- cachePointer.$cache.getBucket().delete(cacheKey);
1386
- }
1387
- cachePointer = cachePointer.$cache.getPointer();
1388
- }
1389
- [cache, cacheFixed, cacheBucket, cacheLRU].forEach((map) => {
1390
- if (map.get(cachePointer)?.has(cacheKey)) {
1391
- removed = true;
1392
- map.get(cachePointer)?.delete(cacheKey);
1393
- }
1394
- });
1395
- return removed;
1396
- }
1397
-
1398
- class FixedWeakMap extends WeakMap {
1399
- constructor(_capacity) {
1400
- assertCapacity(_capacity);
1401
- super();
1402
- this._capacity = _capacity;
1403
- this._tail = [];
1404
- }
1405
- _tail;
1406
- set(key, value) {
1407
- if (!super.has(key)) {
1408
- this._tail.push(key);
1409
- }
1410
- super.set(key, value);
1411
- this._drain();
1412
- return this;
1413
- }
1414
- delete(key) {
1415
- const removed = super.delete(key);
1416
- if (removed) {
1417
- const idx = this._tail.findIndex((v) => v === key);
1418
- if (idx > -1) {
1419
- this._tail.splice(idx, 1);
1420
- }
1421
- }
1422
- return removed;
1423
- }
1424
- clear() {
1425
- for (const item of this._tail) {
1426
- super.delete(item);
1427
- }
1428
- delete this._tail;
1429
- this._tail = [];
1430
- }
1431
- get size() {
1432
- return this._tail.length;
1433
- }
1434
- get capacity() {
1435
- return this._capacity;
1436
- }
1437
- set capacity(value) {
1438
- assertCapacity(value);
1439
- this._capacity = value;
1440
- this._drain();
1441
- }
1442
- _drain() {
1443
- while (this._tail.length > this._capacity) {
1444
- const key = this._tail.shift();
1445
- key !== void 0 && this.delete(key);
1446
- }
1447
- }
1448
- }
1449
-
1450
- function isCached(fn, ...args) {
1451
- let argToKeyOptions = { objectStrategy: "ref" };
1452
- let cachePointer = fn;
1453
- let cached = false;
1454
- if (isWithCache(fn)) {
1455
- argToKeyOptions = fn.$cache.argToKeyOptions;
1456
- }
1457
- const cacheKey = args.map((v) => argToKey(v, argToKeyOptions)).join("_");
1458
- if (isWithCache(fn)) {
1459
- cached = fn.$cache.getBucket().has(cacheKey);
1460
- cachePointer = fn.$cache.getPointer();
1461
- if (cached) return true;
1462
- }
1463
- return !![cache, cacheFixed, cacheBucket, cacheLRU].some(
1464
- (storage) => storage.get(cachePointer)?.has(cacheKey)
1465
- );
1466
- }
1467
-
1468
- const EMPTY_SYM = Symbol("empty");
1469
- function withCacheBucketBatch({
1470
- capacity,
1471
- sizeMs,
1472
- key,
1473
- batchSize = 10,
1474
- cachePointer,
1475
- retryEmpty = true
1476
- }, resolver) {
1477
- const pointer = cachePointer || resolver;
1478
- const argToKeyOptions = {
1479
- objectStrategy: "json"
1480
- };
1481
- const getPointer = () => {
1482
- return pointer;
1483
- };
1484
- const getBucket = () => {
1485
- let fnCache = cacheBucket.get(pointer);
1486
- if (!fnCache) {
1487
- fnCache = new TimeBucket({ sizeMs, capacity });
1488
- cacheBucket.set(pointer, fnCache);
1489
- }
1490
- return fnCache;
1491
- };
1492
- const wrapFn = async function(values) {
1493
- const result = /* @__PURE__ */ new Map();
1494
- let fnCache = getBucket();
1495
- const batchSet = /* @__PURE__ */ new Set();
1496
- const drainMaybe = async () => {
1497
- if (!batchSet.size) return;
1498
- const items = await resolver.call(this, Array.from(batchSet));
1499
- for (let idx = 0; idx < items.length; idx++) {
1500
- const item = items[idx];
1501
- if (!isObject(item)) continue;
1502
- const id = argToKey(item[key], argToKeyOptions);
1503
- batchSet.delete(id);
1504
- result.set(id, item);
1505
- fnCache?.set(id, item);
1506
- }
1507
- for (const batchItem of batchSet.values()) {
1508
- fnCache?.set(batchItem, EMPTY_SYM);
1509
- }
1510
- batchSet.clear();
1511
- };
1512
- let pos = 0;
1513
- while (pos < values.length) {
1514
- const id = argToKey(values[pos], argToKeyOptions);
1515
- const item = fnCache.get(id);
1516
- if (item) {
1517
- if (item === EMPTY_SYM) {
1518
- if (retryEmpty) batchSet.add(id);
1519
- } else {
1520
- result.set(id, item);
1521
- }
1522
- } else {
1523
- batchSet.add(id);
1524
- }
1525
- if (batchSet.size >= batchSize) {
1526
- await drainMaybe();
1527
- }
1528
- pos++;
1529
- }
1530
- await drainMaybe();
1531
- return result;
1532
- };
1533
- wrapFn.$cache = { getBucket, getPointer, argToKeyOptions };
1534
- def(wrapFn, SYM_WITH_CACHE, true);
1535
- return wrapFn;
1536
- }
1537
-
1538
- function cleanEmpty(obj) {
1539
- let value;
1540
- for (const key of Object.keys(obj)) {
1541
- value = obj[key];
1542
- if (isEmpty(value)) {
1543
- delete obj[key];
1544
- }
1545
- }
1546
- return obj;
1547
- }
1548
-
1549
- const cleanObject = (input) => {
1550
- [...Object.keys(input), ...Object.getOwnPropertySymbols(input)].forEach(
1551
- (key) => {
1552
- delete input[key];
1553
- }
1554
- );
1555
- };
1556
-
1557
- const deepAssign = (dest, source) => {
1558
- for (const key of Object.keys(source)) {
1559
- const destValue = dest[key];
1560
- const sourceValue = source[key];
1561
- if (isObject(destValue) && isObject(sourceValue)) {
1562
- deepAssign(destValue, sourceValue);
1825
+ };
1826
+ }
1827
+ };
1828
+ return {
1829
+ ...iterator,
1830
+ [Symbol.iterator]() {
1831
+ return this;
1832
+ }
1833
+ };
1834
+ }
1835
+ /**
1836
+ * Method used to splay a value on top.
1837
+ *
1838
+ * @param {number} pointer - Pointer of the value to splay on top.
1839
+ */
1840
+ splayOnTop(pointer) {
1841
+ const oldHead = this.head;
1842
+ if (this.head === pointer) return this;
1843
+ const previous = this.backward[pointer], next = this.forward[pointer];
1844
+ if (this.tail === pointer) {
1845
+ this.tail = previous;
1563
1846
  } else {
1564
- dest[key] = sourceValue;
1847
+ this.backward[next] = previous;
1565
1848
  }
1849
+ this.forward[previous] = next;
1850
+ this.backward[oldHead] = pointer;
1851
+ this.head = pointer;
1852
+ this.forward[pointer] = oldHead;
1853
+ return this;
1854
+ }
1855
+ [Symbol.iterator]() {
1856
+ return this.entries();
1566
1857
  }
1567
- };
1568
-
1569
- const deepClone = (value) => {
1570
- return _cloneDeep__default(value);
1571
- };
1572
-
1573
- const WITH_CUSTOMIZER_FACTORY_SYM = Symbol();
1574
- function deepCloneWith(value, customizer) {
1575
- const fns = prepareCustomizes(customizer);
1576
- return _cloneDeepWith__default(value, (value2, key) => {
1577
- let newValue;
1578
- let replaced = false;
1579
- for (const fn of fns) {
1580
- newValue = fn(value2, key);
1581
- if (newValue !== void 0) {
1582
- value2 = newValue;
1583
- replaced = true;
1584
- }
1585
- }
1586
- if (replaced) return value2;
1587
- });
1588
- }
1589
- function createDeepCloneWith(customizer) {
1590
- return (value) => {
1591
- return deepCloneWith(value, customizer);
1592
- };
1593
- }
1594
- function prepareCustomizes(value) {
1595
- return arrayable(value).map((v) => isCustomizerFactory(v) ? v() : v);
1596
- }
1597
- function isCustomizerFactory(value) {
1598
- return value?.[WITH_CUSTOMIZER_FACTORY_SYM] === true;
1599
- }
1600
- function createCustomizer(fn) {
1601
- return fn;
1602
1858
  }
1603
- function createCustomizerFactory(fn) {
1604
- def(fn, WITH_CUSTOMIZER_FACTORY_SYM, true);
1605
- return fn;
1859
+ const MAX_8BIT_INTEGER = Math.pow(2, 8) - 1, MAX_16BIT_INTEGER = Math.pow(2, 16) - 1, MAX_32BIT_INTEGER = Math.pow(2, 32) - 1;
1860
+ function pointerArray(size) {
1861
+ const maxIndex = size - 1;
1862
+ if (maxIndex <= MAX_8BIT_INTEGER) return new Uint8Array(size);
1863
+ if (maxIndex <= MAX_16BIT_INTEGER) return new Uint16Array(size);
1864
+ if (maxIndex <= MAX_32BIT_INTEGER) return new Uint32Array(size);
1865
+ throw new Error("Pointer Array of size > 4294967295 is not supported.");
1606
1866
  }
1607
- function createSecureCustomizer(properties) {
1608
- const secureLabel = `<** secure **>`;
1609
- const circularLabel = `<** circular **>`;
1610
- const propertiesSet = Object.freeze(
1611
- new Set(properties.map((v) => v.toLocaleLowerCase()))
1612
- );
1613
- const withCustomizer = (seenSet, value, key) => {
1614
- if (isPrimitive(value)) {
1615
- if (!isString(key)) return;
1616
- if (!propertiesSet.has(key.toLocaleLowerCase())) return;
1617
- return secureLabel;
1618
- }
1619
- if (seenSet.has(value)) {
1620
- return circularLabel;
1621
- }
1622
- seenSet.add(value);
1623
- if (isError(value)) {
1624
- return {
1625
- message: value.message,
1626
- stack: value.stack,
1627
- name: value.name
1628
- };
1867
+
1868
+ const cacheLRU = /* @__PURE__ */ new WeakMap();
1869
+ function withCacheLRU({ capacity, cachePointer, ...options }, fn) {
1870
+ const pointer = cachePointer || fn;
1871
+ const getPointer = () => {
1872
+ return pointer;
1873
+ };
1874
+ const getBucket = () => {
1875
+ let fnCache = cacheLRU.get(pointer);
1876
+ if (!fnCache) {
1877
+ fnCache = new LruCache(capacity);
1878
+ cacheLRU.set(pointer, fnCache);
1629
1879
  }
1880
+ return fnCache;
1630
1881
  };
1631
- return createCustomizerFactory(() => {
1632
- const seenSet = /* @__PURE__ */ new WeakSet();
1633
- return withCustomizer.bind(null, seenSet);
1882
+ return createWithCache({
1883
+ fn,
1884
+ getBucket,
1885
+ getPointer,
1886
+ ...options
1634
1887
  });
1635
1888
  }
1636
1889
 
1637
- const deepDefaults = _defaultsDeep__default;
1638
-
1639
- function deepFreeze(value) {
1640
- let currentValue = value;
1641
- if (!currentValue || typeof currentValue !== "object") return currentValue;
1642
- Object.freeze(currentValue);
1643
- if (Array.isArray(currentValue)) {
1644
- for (const item of currentValue) {
1645
- deepFreeze(item);
1646
- }
1647
- return currentValue;
1648
- } else {
1649
- for (const value2 of Object.values(currentValue)) {
1650
- deepFreeze(value2);
1651
- }
1652
- }
1653
- return currentValue;
1654
- }
1655
-
1656
- function flagsToMap(value, bitmaskMap) {
1657
- const result = {};
1658
- const compare = typeof value === "bigint" ? 0n : 0;
1659
- for (const [key, mask] of Object.entries(bitmaskMap)) {
1660
- result[key] = (value & mask) !== compare;
1661
- }
1662
- return result;
1663
- }
1664
-
1665
- function flatten(obj, {
1666
- separator = "_",
1667
- initialPrefix = "",
1668
- withArrays = true,
1669
- isObjectCompare = isObject
1670
- } = {}) {
1671
- const result = {};
1672
- const seen = /* @__PURE__ */ new WeakSet();
1673
- if (isObjectCompare(obj)) {
1674
- iter(
1675
- result,
1676
- seen,
1677
- isObjectCompare,
1678
- separator,
1679
- withArrays,
1680
- obj,
1681
- initialPrefix,
1682
- true
1683
- );
1890
+ function dropCache(cachePointer, ...args) {
1891
+ let argToKeyOptions = { objectStrategy: "ref" };
1892
+ let removed = false;
1893
+ if (isWithCache(cachePointer)) {
1894
+ argToKeyOptions = cachePointer.$cache.argToKeyOptions;
1684
1895
  }
1685
- return result;
1686
- }
1687
- function iter(output, seen, isObjectCompare, separator, withArrays, val, key, initial) {
1688
- if (seen.has(val)) return;
1689
- let k, pfx = key && !initial ? key + separator : key;
1690
- if (Array.isArray(val)) {
1691
- seen.add(val);
1692
- if (!withArrays) {
1693
- output[key] = val;
1694
- return;
1695
- }
1696
- for (k = 0; k < val.length; k++) {
1697
- iter(
1698
- output,
1699
- seen,
1700
- isObjectCompare,
1701
- separator,
1702
- withArrays,
1703
- val[k],
1704
- pfx + k
1705
- );
1706
- }
1707
- } else if (isObjectCompare(val)) {
1708
- seen.add(val);
1709
- for (k in val) {
1710
- iter(
1711
- output,
1712
- seen,
1713
- isObjectCompare,
1714
- separator,
1715
- withArrays,
1716
- val[k],
1717
- pfx + k
1718
- );
1896
+ const cacheKey = args.map((v) => argToKey(v, argToKeyOptions)).join("_");
1897
+ if (isWithCache(cachePointer)) {
1898
+ if (cachePointer.$cache.getBucket().has(cacheKey)) {
1899
+ removed = true;
1900
+ cachePointer.$cache.getBucket().delete(cacheKey);
1719
1901
  }
1720
- } else {
1721
- output[key] = val;
1902
+ cachePointer = cachePointer.$cache.getPointer();
1722
1903
  }
1904
+ [cache, cacheFixed, cacheBucket, cacheLRU].forEach((map) => {
1905
+ if (map.get(cachePointer)?.has(cacheKey)) {
1906
+ removed = true;
1907
+ map.get(cachePointer)?.delete(cacheKey);
1908
+ }
1909
+ });
1910
+ return removed;
1723
1911
  }
1724
1912
 
1725
- function has(value, keys) {
1726
- if (!isObject(value)) return false;
1727
- for (let idx = 0; idx < keys.length; idx++) {
1728
- const element = keys[idx];
1729
- if (!(element in value)) return false;
1913
+ class FixedWeakMap extends WeakMap {
1914
+ constructor(_capacity) {
1915
+ assertCapacity(_capacity);
1916
+ super();
1917
+ this._capacity = _capacity;
1918
+ this._tail = [];
1730
1919
  }
1731
- return true;
1732
- }
1733
-
1734
- const hasOwn = (val, key) => Object.prototype.hasOwnProperty.call(val, key);
1735
-
1736
- function omit(obj, excludes) {
1737
- const excludesSet = Array.isArray(excludes) ? new Set(excludes) : excludes instanceof Set ? excludes : void 0;
1738
- if (!excludesSet) {
1739
- return obj;
1920
+ _tail;
1921
+ set(key, value) {
1922
+ if (!super.has(key)) {
1923
+ this._tail.push(key);
1924
+ }
1925
+ super.set(key, value);
1926
+ this._drain();
1927
+ return this;
1740
1928
  }
1741
- const result = {};
1742
- if (!isObject(obj)) {
1743
- return result;
1929
+ delete(key) {
1930
+ const removed = super.delete(key);
1931
+ if (removed) {
1932
+ const idx = this._tail.findIndex((v) => v === key);
1933
+ if (idx > -1) {
1934
+ this._tail.splice(idx, 1);
1935
+ }
1936
+ }
1937
+ return removed;
1744
1938
  }
1745
- for (const [key, value] of Object.entries(obj)) {
1746
- if (excludesSet.has(key)) continue;
1747
- result[key] = value;
1939
+ clear() {
1940
+ for (const item of this._tail) {
1941
+ super.delete(item);
1942
+ }
1943
+ delete this._tail;
1944
+ this._tail = [];
1748
1945
  }
1749
- return result;
1750
- }
1751
-
1752
- function omitPrefixed(obj, prefix) {
1753
- const result = {};
1754
- for (const [key, value] of Object.entries(obj)) {
1755
- if (key.startsWith(prefix)) continue;
1756
- result[key] = value;
1946
+ get size() {
1947
+ return this._tail.length;
1757
1948
  }
1758
- return result;
1759
- }
1760
-
1761
- function pick(obj, keys) {
1762
- const keysSet = Array.isArray(keys) ? new Set(keys) : keys instanceof Set ? keys : void 0;
1763
- const result = {};
1764
- if (!keysSet || !isObject(obj)) {
1765
- return result;
1949
+ get capacity() {
1950
+ return this._capacity;
1766
1951
  }
1767
- for (const key of keysSet.values()) {
1768
- if (hasOwn(obj, key)) {
1769
- result[key] = obj[key];
1952
+ set capacity(value) {
1953
+ assertCapacity(value);
1954
+ this._capacity = value;
1955
+ this._drain();
1956
+ }
1957
+ _drain() {
1958
+ while (this._tail.length > this._capacity) {
1959
+ const key = this._tail.shift();
1960
+ key !== void 0 && this.delete(key);
1770
1961
  }
1771
1962
  }
1772
- return result;
1773
1963
  }
1774
1964
 
1775
- function pickPrefixed(obj, options) {
1776
- let prefix;
1777
- let prefixTrim = false;
1778
- if (typeof options === "string") {
1779
- prefix = options;
1780
- } else {
1781
- prefix = options.prefix;
1782
- prefixTrim = options.prefixTrim === true;
1965
+ function isCached(fn, ...args) {
1966
+ let argToKeyOptions = { objectStrategy: "ref" };
1967
+ let cachePointer = fn;
1968
+ let cached = false;
1969
+ if (isWithCache(fn)) {
1970
+ argToKeyOptions = fn.$cache.argToKeyOptions;
1783
1971
  }
1784
- const result = {};
1785
- for (let [key, value] of Object.entries(obj)) {
1786
- if (!key.startsWith(prefix)) continue;
1787
- if (prefixTrim) key = key.substring(prefix.length);
1788
- result[key] = value;
1972
+ const cacheKey = args.map((v) => argToKey(v, argToKeyOptions)).join("_");
1973
+ if (isWithCache(fn)) {
1974
+ cached = fn.$cache.getBucket().has(cacheKey);
1975
+ cachePointer = fn.$cache.getPointer();
1976
+ if (cached) return true;
1789
1977
  }
1790
- return result;
1978
+ return !![cache, cacheFixed, cacheBucket, cacheLRU].some(
1979
+ (storage) => storage.get(cachePointer)?.has(cacheKey)
1980
+ );
1791
1981
  }
1792
1982
 
1793
- const set = _set__default;
1794
-
1795
- const toMap = (obj) => {
1796
- const map = new Map(Object.entries(obj));
1797
- for (const symbol of Object.getOwnPropertySymbols(obj)) {
1798
- map.set(symbol, obj[symbol]);
1799
- }
1800
- return map;
1801
- };
1802
-
1803
- const badKeys = Object.freeze(
1804
- /* @__PURE__ */ new Set(["constructor", "__proto__", "prototype"])
1805
- );
1806
- function unflatten(input, separator = "_") {
1807
- if (!isObject(input)) {
1808
- return {};
1809
- }
1810
- let arr, tmp, output;
1811
- let i = 0, k, key;
1812
- for (k in input) {
1813
- tmp = output;
1814
- arr = k.split(separator);
1815
- for (i = 0; i < arr.length; ) {
1816
- key = arr[i++];
1817
- if (tmp == null) {
1818
- tmp = empty(+key);
1819
- output = output || tmp;
1983
+ const EMPTY_SYM = Symbol("empty");
1984
+ function withCacheBucketBatch({
1985
+ capacity,
1986
+ sizeMs,
1987
+ key,
1988
+ batchSize = 10,
1989
+ cachePointer,
1990
+ retryEmpty = true
1991
+ }, resolver) {
1992
+ const pointer = cachePointer || resolver;
1993
+ const argToKeyOptions = {
1994
+ objectStrategy: "json"
1995
+ };
1996
+ const getPointer = () => {
1997
+ return pointer;
1998
+ };
1999
+ const getBucket = () => {
2000
+ let fnCache = cacheBucket.get(pointer);
2001
+ if (!fnCache) {
2002
+ fnCache = new TimeBucket({ sizeMs, capacity });
2003
+ cacheBucket.set(pointer, fnCache);
2004
+ }
2005
+ return fnCache;
2006
+ };
2007
+ const wrapFn = async function(values) {
2008
+ const result = /* @__PURE__ */ new Map();
2009
+ let fnCache = getBucket();
2010
+ const batchSet = /* @__PURE__ */ new Set();
2011
+ const drainMaybe = async () => {
2012
+ if (!batchSet.size) return;
2013
+ const items = await resolver.call(this, Array.from(batchSet));
2014
+ for (let idx = 0; idx < items.length; idx++) {
2015
+ const item = items[idx];
2016
+ if (!isObject(item)) continue;
2017
+ const id = argToKey(item[key], argToKeyOptions);
2018
+ batchSet.delete(id);
2019
+ result.set(id, item);
2020
+ fnCache?.set(id, item);
1820
2021
  }
1821
- if (badKeys.has(key)) break;
1822
- if (i < arr.length) {
1823
- if (key in tmp) {
1824
- tmp = tmp[key];
2022
+ for (const batchItem of batchSet.values()) {
2023
+ fnCache?.set(batchItem, EMPTY_SYM);
2024
+ }
2025
+ batchSet.clear();
2026
+ };
2027
+ let pos = 0;
2028
+ while (pos < values.length) {
2029
+ const id = argToKey(values[pos], argToKeyOptions);
2030
+ const item = fnCache.get(id);
2031
+ if (item) {
2032
+ if (item === EMPTY_SYM) {
2033
+ if (retryEmpty) batchSet.add(id);
1825
2034
  } else {
1826
- tmp = tmp[key] = empty(+arr[i]);
2035
+ result.set(id, item);
1827
2036
  }
1828
2037
  } else {
1829
- tmp[key] = input[k];
2038
+ batchSet.add(id);
1830
2039
  }
2040
+ if (batchSet.size >= batchSize) {
2041
+ await drainMaybe();
2042
+ }
2043
+ pos++;
1831
2044
  }
1832
- }
1833
- return output;
1834
- }
1835
- function empty(key) {
1836
- return key === key ? [] : {};
2045
+ await drainMaybe();
2046
+ return result;
2047
+ };
2048
+ wrapFn.$cache = { getBucket, getPointer, argToKeyOptions };
2049
+ def(wrapFn, SYM_WITH_CACHE, true);
2050
+ return wrapFn;
1837
2051
  }
1838
2052
 
1839
- const unset = _unset__default;
1840
-
1841
2053
  function withDeepClone(fn) {
1842
2054
  const wrapFn = function(...args) {
1843
2055
  const result = fn.apply(this, args);
@@ -4625,6 +4837,308 @@ function rafPromise() {
4625
4837
  });
4626
4838
  }
4627
4839
 
4840
+ class ResourcePool extends SimpleEventEmitter {
4841
+ poolSize;
4842
+ auto;
4843
+ createResource;
4844
+ destroyResource;
4845
+ state;
4846
+ /**
4847
+ * Creates a new ResourcePool instance.
4848
+ *
4849
+ * @param options Configuration options for the pool
4850
+ *
4851
+ * @example
4852
+ * ```typescript
4853
+ * const pool = new ResourcePool({
4854
+ * poolSize: 5,
4855
+ * auto: true,
4856
+ * createResource: async () => new DatabaseConnection(),
4857
+ * destroyResource: async (conn) => conn.close()
4858
+ * });
4859
+ * ```
4860
+ */
4861
+ constructor({
4862
+ poolSize,
4863
+ auto = false,
4864
+ createResource,
4865
+ destroyResource
4866
+ }) {
4867
+ super();
4868
+ this.poolSize = poolSize;
4869
+ this.auto = auto;
4870
+ this.createResource = createResource;
4871
+ this.destroyResource = destroyResource;
4872
+ this.removeAllListeners("error");
4873
+ this.state = {
4874
+ availableResources: [],
4875
+ inUseResources: /* @__PURE__ */ new Set(),
4876
+ queueAcquire: [],
4877
+ queueDrain: [],
4878
+ queueDestroy: [],
4879
+ destroying: false
4880
+ };
4881
+ }
4882
+ /**
4883
+ * Whether the pool is idle (no resources currently in use).
4884
+ * Useful for determining if it's safe to destroy the pool.
4885
+ */
4886
+ get isIdle() {
4887
+ return this.state.inUseResources.size === 0;
4888
+ }
4889
+ /** Number of resources currently available for acquisition */
4890
+ get availableCount() {
4891
+ return this.state.availableResources.length;
4892
+ }
4893
+ /** Number of resources currently in use */
4894
+ get usedCount() {
4895
+ return this.state.inUseResources.size;
4896
+ }
4897
+ /** Maximum number of resources this pool can manage */
4898
+ get size() {
4899
+ return this.poolSize;
4900
+ }
4901
+ /**
4902
+ * Acquires a resource from the pool.
4903
+ *
4904
+ * This method will:
4905
+ * 1. Return an available resource immediately if one exists
4906
+ * 2. Create a new resource if auto mode is enabled and under the pool limit
4907
+ * 3. Queue the request and wait if no resources are available
4908
+ *
4909
+ * @returns Promise that resolves to an acquired resource
4910
+ * @throws Error if the pool is destroyed while waiting (when rejectAcquires is true)
4911
+ *
4912
+ * @example
4913
+ * ```typescript
4914
+ * const resource = await pool.acquire();
4915
+ * try {
4916
+ * // Use the resource
4917
+ * await resource.doSomething();
4918
+ * } finally {
4919
+ * pool.release(resource); // Always release in finally block
4920
+ * }
4921
+ * ```
4922
+ */
4923
+ async acquire() {
4924
+ if (this.state.destroying) {
4925
+ return this.enqueueAcquireRequest();
4926
+ }
4927
+ let availableResource = this.tryGetAvailableResource();
4928
+ if (availableResource !== null) {
4929
+ return availableResource;
4930
+ }
4931
+ const autoCreatedResource = await this.tryCreateAutoResource();
4932
+ if (autoCreatedResource !== null) {
4933
+ return autoCreatedResource;
4934
+ }
4935
+ availableResource = this.tryGetAvailableResource();
4936
+ if (availableResource !== null) {
4937
+ return availableResource;
4938
+ }
4939
+ return this.enqueueAcquireRequest();
4940
+ }
4941
+ /**
4942
+ * Returns a resource to the pool, making it available for reuse.
4943
+ *
4944
+ * The resource will be made available to the next queued acquisition request,
4945
+ * or returned to the available pool if no requests are pending.
4946
+ *
4947
+ * @param resource The resource to return to the pool
4948
+ *
4949
+ * @example
4950
+ * ```typescript
4951
+ * const resource = await pool.acquire();
4952
+ * try {
4953
+ * // Use resource...
4954
+ * } finally {
4955
+ * pool.release(resource); // Always release when done
4956
+ * }
4957
+ * ```
4958
+ *
4959
+ * @remarks
4960
+ * - Safe to call multiple times with the same resource (idempotent)
4961
+ * - Only resources that were acquired from this pool should be released
4962
+ * - Triggers drain completion if this was the last resource in use
4963
+ */
4964
+ release(resource) {
4965
+ if (!this.state.inUseResources.has(resource)) {
4966
+ return;
4967
+ }
4968
+ this.processNextAcquireRequest(resource);
4969
+ this.checkForDrainCompletion();
4970
+ }
4971
+ /**
4972
+ * Manually add a resource to the pool.
4973
+ *
4974
+ * @param resource The resource to return to the pool
4975
+ *
4976
+ * @throws Error if resource already exists in the pool.
4977
+ * @throws Error if size reached.
4978
+ */
4979
+ add(resource) {
4980
+ ok(
4981
+ this.poolSize > this.state.availableResources.length + this.state.inUseResources.size,
4982
+ "Pool size reached"
4983
+ );
4984
+ ok(
4985
+ !this.state.inUseResources.has(resource) && !this.state.availableResources.includes(resource),
4986
+ "This resource already added to the pool"
4987
+ );
4988
+ this.state.inUseResources.add(resource);
4989
+ this.processNextAcquireRequest(resource);
4990
+ }
4991
+ /**
4992
+ * Waits for all currently acquired resources to be released.
4993
+ *
4994
+ * This is useful for graceful shutdown scenarios where you want to ensure
4995
+ * all work is completed before destroying the pool.
4996
+ *
4997
+ * @returns Promise that resolves when all resources are returned to the pool
4998
+ *
4999
+ * @example
5000
+ * ```typescript
5001
+ * // Graceful shutdown
5002
+ * console.log('Waiting for all connections to be released...');
5003
+ * await pool.drain();
5004
+ * console.log('All connections released, safe to destroy pool');
5005
+ * await pool.destroy();
5006
+ * ```
5007
+ *
5008
+ * @remarks
5009
+ * - Resolves immediately if no resources are currently in use
5010
+ * - Multiple drain calls can be made concurrently; they will all resolve together
5011
+ * - Does not prevent new acquisitions; use destroy() to prevent new usage
5012
+ */
5013
+ async drain() {
5014
+ if (this.isIdle) {
5015
+ return;
5016
+ }
5017
+ const drainDefer = defer();
5018
+ this.state.queueDrain.push(drainDefer);
5019
+ return drainDefer.promise;
5020
+ }
5021
+ /**
5022
+ * Destroys the pool and all its resources.
5023
+ *
5024
+ * This method will:
5025
+ * 1. Wait for all resources to be released (drain)
5026
+ * 2. Optionally reject any pending acquisition requests
5027
+ * 3. Call destroyResource() on all available resources
5028
+ * 4. Clean up internal state
5029
+ *
5030
+ * @param rejectAcquires Whether to reject pending acquire() requests with an error
5031
+ * If false, pending requests will remain queued indefinitely
5032
+ * @returns Promise that resolves when destruction is complete
5033
+ *
5034
+ * @example
5035
+ * ```typescript
5036
+ * // Graceful shutdown - let pending requests complete
5037
+ * await pool.destroy(false);
5038
+ *
5039
+ * // Immediate shutdown - reject pending requests
5040
+ * await pool.destroy(true);
5041
+ * ```
5042
+ *
5043
+ * @remarks
5044
+ * - Safe to call multiple times; subsequent calls will wait for the first to complete
5045
+ * - The pool cannot be used after destruction
5046
+ * - Resources currently in use will not be force-destroyed; drain() is called first
5047
+ * - If destroyResource was not provided, resources are simply discarded
5048
+ */
5049
+ async destroy(rejectAcquires = false) {
5050
+ if (this.state.destroying) {
5051
+ return this.enqueueDestroyRequest();
5052
+ }
5053
+ this.state.destroying = true;
5054
+ try {
5055
+ await this.drain();
5056
+ if (rejectAcquires) {
5057
+ this.rejectPendingAcquires();
5058
+ }
5059
+ await this.destroyAllResources();
5060
+ this.resetState();
5061
+ } catch (err) {
5062
+ this.emit("error", toError(err));
5063
+ } finally {
5064
+ this.state.destroying = false;
5065
+ this.resolveDestroyQueue();
5066
+ }
5067
+ }
5068
+ tryGetAvailableResource() {
5069
+ if (this.state.availableResources.length === 0) {
5070
+ return null;
5071
+ }
5072
+ const resource = this.state.availableResources.pop();
5073
+ this.state.inUseResources.add(resource);
5074
+ return resource;
5075
+ }
5076
+ async tryCreateAutoResource() {
5077
+ if (!this.auto || this.state.inUseResources.size >= this.poolSize) {
5078
+ return null;
5079
+ }
5080
+ const resource = await this.createResource();
5081
+ this.state.inUseResources.add(resource);
5082
+ return resource;
5083
+ }
5084
+ enqueueAcquireRequest() {
5085
+ const acquireDefer = defer();
5086
+ this.state.queueAcquire.push(acquireDefer);
5087
+ return acquireDefer.promise;
5088
+ }
5089
+ moveResourceToAvailable(resource) {
5090
+ this.state.inUseResources.delete(resource);
5091
+ this.state.availableResources.push(resource);
5092
+ }
5093
+ processNextAcquireRequest(resource) {
5094
+ if (this.state.destroying || this.state.queueAcquire.length === 0) {
5095
+ this.moveResourceToAvailable(resource);
5096
+ return;
5097
+ }
5098
+ const nextRequest = this.state.queueAcquire.shift();
5099
+ nextRequest.resolve(resource);
5100
+ }
5101
+ checkForDrainCompletion() {
5102
+ if (this.isIdle && this.state.queueDrain.length > 0) {
5103
+ this.state.queueDrain.forEach((deferred) => deferred.resolve());
5104
+ this.state.queueDrain = [];
5105
+ }
5106
+ }
5107
+ enqueueDestroyRequest() {
5108
+ const destroyDefer = defer();
5109
+ this.state.queueDestroy.push(destroyDefer);
5110
+ return destroyDefer.promise;
5111
+ }
5112
+ rejectPendingAcquires() {
5113
+ const destroyError = new Error("ResourcePool destroyed");
5114
+ this.state.queueAcquire.forEach((deferred) => deferred.reject(destroyError));
5115
+ this.state.queueAcquire = [];
5116
+ }
5117
+ async destroyAllResources() {
5118
+ if (!this.destroyResource || this.state.availableResources.length === 0) {
5119
+ return;
5120
+ }
5121
+ await asyncForEach(
5122
+ this.state.availableResources,
5123
+ async (resource) => {
5124
+ try {
5125
+ await this.destroyResource(resource);
5126
+ } catch (err) {
5127
+ this.emit("error", toError(err));
5128
+ }
5129
+ },
5130
+ { concurrency: 4 }
5131
+ );
5132
+ }
5133
+ resetState() {
5134
+ this.state.availableResources = [];
5135
+ }
5136
+ resolveDestroyQueue() {
5137
+ this.state.queueDestroy.forEach((deferred) => deferred.resolve());
5138
+ this.state.queueDestroy = [];
5139
+ }
5140
+ }
5141
+
4628
5142
  function timeout(ms, promiseOrCallback, timeoutError = new AppError(408)) {
4629
5143
  const abortController = new AbortController();
4630
5144
  let taskResult;
@@ -4904,6 +5418,7 @@ exports.FixedMap = FixedMap;
4904
5418
  exports.FixedWeakMap = FixedWeakMap;
4905
5419
  exports.LruCache = LruCache;
4906
5420
  exports.Queue = Queue;
5421
+ exports.ResourcePool = ResourcePool;
4907
5422
  exports.SimpleEventEmitter = SimpleEventEmitter;
4908
5423
  exports.SortedArray = SortedArray;
4909
5424
  exports.TWEMOJI_REGEX = TWEMOJI_REGEX;
@@ -4918,7 +5433,12 @@ exports.asyncForEach = asyncForEach;
4918
5433
  exports.asyncMap = asyncMap;
4919
5434
  exports.avg = avg;
4920
5435
  exports.avgCircular = avgCircular;
5436
+ exports.base62 = base62;
5437
+ exports.base62Fast = base62Fast;
5438
+ exports.base64 = base64;
4921
5439
  exports.base64ToBytes = base64ToBytes;
5440
+ exports.base64url = base64url;
5441
+ exports.basex = basex;
4922
5442
  exports.bigIntBytes = bigIntBytes;
4923
5443
  exports.bigIntFromBytes = bigIntFromBytes;
4924
5444
  exports.blendColors = blendColors;