@andrew_l/toolkit 0.2.4 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +245 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +109 -24
- package/dist/index.d.mts +109 -24
- package/dist/index.d.ts +109 -24
- package/dist/index.mjs +242 -44
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const _get = require('lodash/get');
|
|
4
|
-
const _cloneDeep = require('lodash/cloneDeep');
|
|
5
|
-
const _cloneDeepWith = require('lodash/cloneDeepWith');
|
|
6
|
-
const _defaultsDeep = require('lodash/defaultsDeep');
|
|
7
|
-
const _set = require('lodash/set');
|
|
8
|
-
const _unset = require('lodash/unset');
|
|
3
|
+
const _get = require('lodash/get.js');
|
|
4
|
+
const _cloneDeep = require('lodash/cloneDeep.js');
|
|
5
|
+
const _cloneDeepWith = require('lodash/cloneDeepWith.js');
|
|
6
|
+
const _defaultsDeep = require('lodash/defaultsDeep.js');
|
|
7
|
+
const _set = require('lodash/set.js');
|
|
8
|
+
const _unset = require('lodash/unset.js');
|
|
9
9
|
|
|
10
10
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
11
11
|
|
|
@@ -248,6 +248,30 @@ function difference(...arrays) {
|
|
|
248
248
|
return Array.from(set);
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
+
function groupBy(array, keyBy, objectMode) {
|
|
252
|
+
const getItemKey = isFunction(keyBy) ? keyBy : (item) => item?.[keyBy];
|
|
253
|
+
let key;
|
|
254
|
+
if (objectMode === true) {
|
|
255
|
+
const result2 = {};
|
|
256
|
+
for (const item of array) {
|
|
257
|
+
key = getItemKey(item);
|
|
258
|
+
result2[key] = result2[key] || [];
|
|
259
|
+
result2[key].push(item);
|
|
260
|
+
}
|
|
261
|
+
return result2;
|
|
262
|
+
}
|
|
263
|
+
const result = /* @__PURE__ */ new Map();
|
|
264
|
+
for (const item of array) {
|
|
265
|
+
key = getItemKey(item);
|
|
266
|
+
if (!result.has(key)) {
|
|
267
|
+
result.set(key, [item]);
|
|
268
|
+
} else {
|
|
269
|
+
result.get(key).push(item);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return result;
|
|
273
|
+
}
|
|
274
|
+
|
|
251
275
|
function intersection(...arrays) {
|
|
252
276
|
if (arrays.length === 0) return [];
|
|
253
277
|
if (arrays.length === 1) return arrays[0];
|
|
@@ -358,6 +382,7 @@ let AssertionError;
|
|
|
358
382
|
(r) => r.BrowserAssertionError
|
|
359
383
|
) : await import('node:assert').then((r) => r.AssertionError);
|
|
360
384
|
})();
|
|
385
|
+
|
|
361
386
|
function ok(value, message) {
|
|
362
387
|
if (!value) {
|
|
363
388
|
throw toError$1(
|
|
@@ -379,6 +404,11 @@ function equal(actual, expected, message) {
|
|
|
379
404
|
});
|
|
380
405
|
}
|
|
381
406
|
}
|
|
407
|
+
function empty$1(value, message) {
|
|
408
|
+
if (isEmpty(value)) {
|
|
409
|
+
throw toError$1(empty$1, value, message, "Expected not empty value.");
|
|
410
|
+
}
|
|
411
|
+
}
|
|
382
412
|
function object(value, message) {
|
|
383
413
|
if (!isObject(value)) {
|
|
384
414
|
throw toError$1(object, value, message, "Expected object value.");
|
|
@@ -409,6 +439,36 @@ function number$1(value, message) {
|
|
|
409
439
|
throw toError$1(number$1, value, message, "Expected number value.");
|
|
410
440
|
}
|
|
411
441
|
}
|
|
442
|
+
function date(value, message) {
|
|
443
|
+
if (!isDate(value)) {
|
|
444
|
+
throw toError$1(date, value, message, "Expected date value.");
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
function fn(value, message) {
|
|
448
|
+
if (!isNumber(value)) {
|
|
449
|
+
throw toError$1(fn, value, message, "Expected function value.");
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
function greaterThan(value, target, message) {
|
|
453
|
+
if (!isNumber(value) || value < target) {
|
|
454
|
+
throw toError$1(
|
|
455
|
+
greaterThan,
|
|
456
|
+
value,
|
|
457
|
+
message,
|
|
458
|
+
"Expected number value greater then " + target + "."
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
function lessThan(value, target, message) {
|
|
463
|
+
if (!isNumber(value) || value > target) {
|
|
464
|
+
throw toError$1(
|
|
465
|
+
lessThan,
|
|
466
|
+
value,
|
|
467
|
+
message,
|
|
468
|
+
"Expected number value less then " + target + "."
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
412
472
|
function array(value, message) {
|
|
413
473
|
if (!Array.isArray(value)) {
|
|
414
474
|
throw toError$1(array, value, message, "Expected array value.");
|
|
@@ -442,7 +502,12 @@ const assert = {
|
|
|
442
502
|
arrayNumbers: arrayNumbers,
|
|
443
503
|
arrayStrings: arrayStrings,
|
|
444
504
|
boolean: boolean,
|
|
505
|
+
date: date,
|
|
506
|
+
empty: empty$1,
|
|
445
507
|
equal: equal,
|
|
508
|
+
fn: fn,
|
|
509
|
+
greaterThan: greaterThan,
|
|
510
|
+
lessThan: lessThan,
|
|
446
511
|
notEmptyString: notEmptyString,
|
|
447
512
|
number: number$1,
|
|
448
513
|
object: object,
|
|
@@ -450,6 +515,53 @@ const assert = {
|
|
|
450
515
|
string: string
|
|
451
516
|
};
|
|
452
517
|
|
|
518
|
+
function weightedRoundRobin(arr) {
|
|
519
|
+
ok(arr.length > 0, "Array must contain at least one item.");
|
|
520
|
+
const instance = new WeightedRoundRobin(
|
|
521
|
+
arr.map((v) => ({
|
|
522
|
+
item: v.item,
|
|
523
|
+
weight: Math.min(v.weight ?? 1, 1)
|
|
524
|
+
}))
|
|
525
|
+
);
|
|
526
|
+
return () => instance.nextItem();
|
|
527
|
+
}
|
|
528
|
+
const gcd = (a, b) => !b ? a : gcd(b, a % b);
|
|
529
|
+
class WeightedRoundRobin {
|
|
530
|
+
constructor(items) {
|
|
531
|
+
this.items = items;
|
|
532
|
+
this.maxWeight = this._calculateMaxWeight();
|
|
533
|
+
this.gcdWeight = this._calculateGCD();
|
|
534
|
+
}
|
|
535
|
+
currentIndex = -1;
|
|
536
|
+
currentWeight = 0;
|
|
537
|
+
maxWeight;
|
|
538
|
+
gcdWeight;
|
|
539
|
+
_calculateGCD() {
|
|
540
|
+
return this.items.reduce(
|
|
541
|
+
(acc, curr) => gcd(acc, curr.weight),
|
|
542
|
+
this.items[0].weight
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
_calculateMaxWeight() {
|
|
546
|
+
return Math.max(...this.items.map((s) => s.weight));
|
|
547
|
+
}
|
|
548
|
+
nextItem() {
|
|
549
|
+
const n = this.items.length;
|
|
550
|
+
while (true) {
|
|
551
|
+
this.currentIndex = (this.currentIndex + 1) % n;
|
|
552
|
+
if (this.currentIndex === 0) {
|
|
553
|
+
this.currentWeight -= this.gcdWeight;
|
|
554
|
+
if (this.currentWeight <= 0) {
|
|
555
|
+
this.currentWeight = this.maxWeight;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
if (this.items[this.currentIndex].weight >= this.currentWeight) {
|
|
559
|
+
return this.items[this.currentIndex].item;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
453
565
|
class Base64Encoding {
|
|
454
566
|
alphabet;
|
|
455
567
|
padding;
|
|
@@ -658,13 +770,12 @@ const def = (obj, key, value, writable = false) => {
|
|
|
658
770
|
const rndCharacters = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
659
771
|
const charactersLength = rndCharacters.length;
|
|
660
772
|
function randomString(length) {
|
|
661
|
-
let
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
);
|
|
773
|
+
let str = "";
|
|
774
|
+
let num = isNumber(length) ? Math.max(0, length) : 0;
|
|
775
|
+
while (num--) {
|
|
776
|
+
str += rndCharacters[charactersLength * Math.random() | 0];
|
|
666
777
|
}
|
|
667
|
-
return
|
|
778
|
+
return str;
|
|
668
779
|
}
|
|
669
780
|
|
|
670
781
|
const objectKeys = /* @__PURE__ */ new WeakMap();
|
|
@@ -1457,27 +1568,57 @@ function flatten(obj, {
|
|
|
1457
1568
|
isObjectCompare = isObject
|
|
1458
1569
|
} = {}) {
|
|
1459
1570
|
const result = {};
|
|
1460
|
-
const
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1571
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
1572
|
+
if (isObjectCompare(obj)) {
|
|
1573
|
+
iter(
|
|
1574
|
+
result,
|
|
1575
|
+
seen,
|
|
1576
|
+
isObjectCompare,
|
|
1577
|
+
separator,
|
|
1578
|
+
withArrays,
|
|
1579
|
+
obj,
|
|
1580
|
+
initialPrefix,
|
|
1581
|
+
true
|
|
1582
|
+
);
|
|
1583
|
+
}
|
|
1584
|
+
return result;
|
|
1585
|
+
}
|
|
1586
|
+
function iter(output, seen, isObjectCompare, separator, withArrays, val, key, initial) {
|
|
1587
|
+
if (seen.has(val)) return;
|
|
1588
|
+
let k, pfx = key && !initial ? key + separator : key;
|
|
1589
|
+
if (Array.isArray(val)) {
|
|
1590
|
+
seen.add(val);
|
|
1591
|
+
if (!withArrays) {
|
|
1592
|
+
output[key] = val;
|
|
1469
1593
|
return;
|
|
1470
1594
|
}
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1595
|
+
for (k = 0; k < val.length; k++) {
|
|
1596
|
+
iter(
|
|
1597
|
+
output,
|
|
1598
|
+
seen,
|
|
1599
|
+
isObjectCompare,
|
|
1600
|
+
separator,
|
|
1601
|
+
withArrays,
|
|
1602
|
+
val[k],
|
|
1603
|
+
pfx + k
|
|
1604
|
+
);
|
|
1476
1605
|
}
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1606
|
+
} else if (isObjectCompare(val)) {
|
|
1607
|
+
seen.add(val);
|
|
1608
|
+
for (k in val) {
|
|
1609
|
+
iter(
|
|
1610
|
+
output,
|
|
1611
|
+
seen,
|
|
1612
|
+
isObjectCompare,
|
|
1613
|
+
separator,
|
|
1614
|
+
withArrays,
|
|
1615
|
+
val[k],
|
|
1616
|
+
pfx + k
|
|
1617
|
+
);
|
|
1618
|
+
}
|
|
1619
|
+
} else {
|
|
1620
|
+
output[key] = val;
|
|
1621
|
+
}
|
|
1481
1622
|
}
|
|
1482
1623
|
|
|
1483
1624
|
function has(value, keys) {
|
|
@@ -1558,12 +1699,40 @@ const toMap = (obj) => {
|
|
|
1558
1699
|
return map;
|
|
1559
1700
|
};
|
|
1560
1701
|
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1702
|
+
const badKeys = Object.freeze(
|
|
1703
|
+
/* @__PURE__ */ new Set(["constructor", "__proto__", "prototype"])
|
|
1704
|
+
);
|
|
1705
|
+
function unflatten(input, separator = "_") {
|
|
1706
|
+
if (!isObject(input)) {
|
|
1707
|
+
return {};
|
|
1708
|
+
}
|
|
1709
|
+
let arr, tmp, output;
|
|
1710
|
+
let i = 0, k, key;
|
|
1711
|
+
for (k in input) {
|
|
1712
|
+
tmp = output;
|
|
1713
|
+
arr = k.split(separator);
|
|
1714
|
+
for (i = 0; i < arr.length; ) {
|
|
1715
|
+
key = arr[i++];
|
|
1716
|
+
if (tmp == null) {
|
|
1717
|
+
tmp = empty(+key);
|
|
1718
|
+
output = output || tmp;
|
|
1719
|
+
}
|
|
1720
|
+
if (badKeys.has(key)) break;
|
|
1721
|
+
if (i < arr.length) {
|
|
1722
|
+
if (key in tmp) {
|
|
1723
|
+
tmp = tmp[key];
|
|
1724
|
+
} else {
|
|
1725
|
+
tmp = tmp[key] = empty(+arr[i]);
|
|
1726
|
+
}
|
|
1727
|
+
} else {
|
|
1728
|
+
tmp[key] = input[k];
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
return output;
|
|
1733
|
+
}
|
|
1734
|
+
function empty(key) {
|
|
1735
|
+
return key === key ? [] : {};
|
|
1567
1736
|
}
|
|
1568
1737
|
|
|
1569
1738
|
const unset = _unset__default;
|
|
@@ -3188,7 +3357,7 @@ function getFileExtension(name, withDot = true) {
|
|
|
3188
3357
|
return null;
|
|
3189
3358
|
}
|
|
3190
3359
|
const ext = name.split(".").at(-1)?.split("?")?.at(0);
|
|
3191
|
-
return ext ? withDot ?
|
|
3360
|
+
return ext ? withDot ? `.${ext}` : ext : null;
|
|
3192
3361
|
}
|
|
3193
3362
|
|
|
3194
3363
|
const DEF_PROTOCOLS = ["http://", "https://"];
|
|
@@ -3206,7 +3375,21 @@ function getFileName(value) {
|
|
|
3206
3375
|
if (!ext) {
|
|
3207
3376
|
return value;
|
|
3208
3377
|
}
|
|
3209
|
-
return value.slice(0, -ext.length
|
|
3378
|
+
return value.slice(0, -ext.length);
|
|
3379
|
+
}
|
|
3380
|
+
|
|
3381
|
+
function getMostSpecificPaths(keys) {
|
|
3382
|
+
keys = [...keys].sort();
|
|
3383
|
+
const result = [];
|
|
3384
|
+
for (let i = 0; i < keys.length; i++) {
|
|
3385
|
+
const currentPath = keys[i];
|
|
3386
|
+
const nextPath = keys[i + 1];
|
|
3387
|
+
if (currentPath === nextPath) continue;
|
|
3388
|
+
if (!nextPath || !nextPath.startsWith(currentPath + ".")) {
|
|
3389
|
+
result.push(currentPath);
|
|
3390
|
+
}
|
|
3391
|
+
}
|
|
3392
|
+
return result;
|
|
3210
3393
|
}
|
|
3211
3394
|
|
|
3212
3395
|
function humanFileSize(bytes, digits = 1, withSpace = true) {
|
|
@@ -3308,19 +3491,37 @@ function tryStringify(o) {
|
|
|
3308
3491
|
}
|
|
3309
3492
|
}
|
|
3310
3493
|
|
|
3311
|
-
const
|
|
3494
|
+
const LEVEL_NUM = {
|
|
3495
|
+
debug: 0,
|
|
3496
|
+
log: 1,
|
|
3497
|
+
info: 2,
|
|
3498
|
+
warn: 3,
|
|
3499
|
+
error: 4
|
|
3500
|
+
};
|
|
3501
|
+
let currentLogLevel = LEVEL_NUM.log;
|
|
3502
|
+
const loggerSetLevel = (level) => {
|
|
3503
|
+
number$1(LEVEL_NUM[level], `Invalid log level: ${level}`);
|
|
3504
|
+
currentLogLevel = LEVEL_NUM[level];
|
|
3505
|
+
};
|
|
3312
3506
|
const logger = (...baseArgs) => {
|
|
3507
|
+
if (isString(baseArgs[0]?.url)) {
|
|
3508
|
+
baseArgs[0] = baseArgs[0]?.url;
|
|
3509
|
+
}
|
|
3313
3510
|
if (typeof baseArgs[0] === "string" && baseArgs[0][0] !== "[") {
|
|
3314
3511
|
baseArgs[0] = `[${baseArgs[0].split("/").at(-1).split("?", 1)[0]}]`;
|
|
3315
3512
|
}
|
|
3316
3513
|
const writeLog = (level, ...[pattern, ...args]) => {
|
|
3514
|
+
const levelNum = LEVEL_NUM[level];
|
|
3515
|
+
if (levelNum < currentLogLevel) {
|
|
3516
|
+
return;
|
|
3517
|
+
}
|
|
3317
3518
|
if (!isString(pattern)) {
|
|
3318
3519
|
console[level](...baseArgs, pattern, ...args);
|
|
3319
3520
|
return;
|
|
3320
3521
|
}
|
|
3321
3522
|
const unusedArgs = [];
|
|
3322
3523
|
const formatted = sprintf(pattern, args, unusedArgs);
|
|
3323
|
-
console[level](...baseArgs,
|
|
3524
|
+
console[level](...baseArgs, formatted, ...unusedArgs);
|
|
3324
3525
|
};
|
|
3325
3526
|
const log = writeLog.bind(null, "log");
|
|
3326
3527
|
const info = writeLog.bind(null, "info");
|
|
@@ -3338,9 +3539,6 @@ const logger = (...baseArgs) => {
|
|
|
3338
3539
|
debug,
|
|
3339
3540
|
extend
|
|
3340
3541
|
};
|
|
3341
|
-
Object.defineProperty(instance, "debug", {
|
|
3342
|
-
get: () => IS_DEV ? debug : noop
|
|
3343
|
-
});
|
|
3344
3542
|
return instance;
|
|
3345
3543
|
};
|
|
3346
3544
|
|
|
@@ -4325,9 +4523,11 @@ exports.get = get;
|
|
|
4325
4523
|
exports.getFileExtension = getFileExtension;
|
|
4326
4524
|
exports.getFileName = getFileName;
|
|
4327
4525
|
exports.getInitials = getInitials;
|
|
4526
|
+
exports.getMostSpecificPaths = getMostSpecificPaths;
|
|
4328
4527
|
exports.getRandomInt = getRandomInt;
|
|
4329
4528
|
exports.getRandomTime = getRandomTime;
|
|
4330
4529
|
exports.getWords = getWords;
|
|
4530
|
+
exports.groupBy = groupBy;
|
|
4331
4531
|
exports.has = has;
|
|
4332
4532
|
exports.hasOwn = hasOwn;
|
|
4333
4533
|
exports.hasProtocol = hasProtocol;
|
|
@@ -4377,6 +4577,7 @@ exports.isoToFlagEmoji = isoToFlagEmoji;
|
|
|
4377
4577
|
exports.kebabCase = kebabCase;
|
|
4378
4578
|
exports.keyBy = keyBy;
|
|
4379
4579
|
exports.logger = logger;
|
|
4580
|
+
exports.loggerSetLevel = loggerSetLevel;
|
|
4380
4581
|
exports.lowerCase = lowerCase;
|
|
4381
4582
|
exports.luminance = luminance;
|
|
4382
4583
|
exports.maskingEmail = maskingEmail;
|
|
@@ -4431,6 +4632,7 @@ exports.uniq = uniq;
|
|
|
4431
4632
|
exports.uniqBy = uniqBy;
|
|
4432
4633
|
exports.unset = unset;
|
|
4433
4634
|
exports.weeksInYear = weeksInYear;
|
|
4635
|
+
exports.weightedRoundRobin = weightedRoundRobin;
|
|
4434
4636
|
exports.withCache = withCache;
|
|
4435
4637
|
exports.withCacheBucket = withCacheBucket;
|
|
4436
4638
|
exports.withCacheBucketBatch = withCacheBucketBatch;
|