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