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