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