@andrew_l/toolkit 0.2.14 → 0.2.16

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