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