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