@andrew_l/toolkit 0.2.15 → 0.2.17

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