superjs-core 0.6.0 → 0.7.0
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/collection/index.js +6 -0
- package/dist/collection/index.js.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/crypto/index.js +3 -6
- package/dist/crypto/index.js.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +1676 -15
- package/dist/index.js.map +1 -1
- package/dist/io/index.js +1 -0
- package/dist/io/index.js.map +1 -1
- package/dist/string/index.js +23 -6
- package/dist/string/index.js.map +1 -1
- package/dist/type/index.d.ts +2 -4
- package/dist/type/index.js +1 -3
- package/dist/type/index.js.map +1 -1
- package/dist/validation/index.d.ts +166 -2
- package/package.json +8 -2
- package/dist/isNoRekening-CHSpgD4P.d.ts +0 -167
package/dist/index.js
CHANGED
|
@@ -78,6 +78,7 @@ function deepMerge(...objects) {
|
|
|
78
78
|
const keys = Object.keys(obj);
|
|
79
79
|
for (let j = 0; j < keys.length; j++) {
|
|
80
80
|
const key = keys[j];
|
|
81
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
|
|
81
82
|
const val = obj[key];
|
|
82
83
|
const existing = result[key];
|
|
83
84
|
if (val !== void 0 && isPlainObject(val) && isPlainObject(existing)) {
|
|
@@ -265,6 +266,54 @@ function once(fn) {
|
|
|
265
266
|
return result;
|
|
266
267
|
};
|
|
267
268
|
}
|
|
269
|
+
function deepEqual(a, b) {
|
|
270
|
+
if (Object.is(a, b)) return true;
|
|
271
|
+
if (a === null || b === null || typeof a !== typeof b) return false;
|
|
272
|
+
if (typeof a !== "object") return false;
|
|
273
|
+
const aObj = a;
|
|
274
|
+
const bObj = b;
|
|
275
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
276
|
+
if (a.length !== b.length) return false;
|
|
277
|
+
for (let i = 0; i < a.length; i++) {
|
|
278
|
+
if (!deepEqual(a[i], b[i])) return false;
|
|
279
|
+
}
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
if (a instanceof Date && b instanceof Date) {
|
|
283
|
+
return a.getTime() === b.getTime();
|
|
284
|
+
}
|
|
285
|
+
if (a instanceof RegExp && b instanceof RegExp) {
|
|
286
|
+
return a.source === b.source && a.flags === b.flags;
|
|
287
|
+
}
|
|
288
|
+
if (a instanceof Map && b instanceof Map) {
|
|
289
|
+
if (a.size !== b.size) return false;
|
|
290
|
+
for (const [k, v] of a) {
|
|
291
|
+
if (!b.has(k) || !deepEqual(v, b.get(k))) return false;
|
|
292
|
+
}
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
if (a instanceof Set && b instanceof Set) {
|
|
296
|
+
if (a.size !== b.size) return false;
|
|
297
|
+
for (const v of a) {
|
|
298
|
+
if (!b.has(v)) return false;
|
|
299
|
+
}
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
const keysA = Object.keys(aObj);
|
|
303
|
+
const keysB = Object.keys(bObj);
|
|
304
|
+
if (keysA.length !== keysB.length) return false;
|
|
305
|
+
for (const key of keysA) {
|
|
306
|
+
if (!Object.prototype.hasOwnProperty.call(bObj, key)) return false;
|
|
307
|
+
if (!deepEqual(aObj[key], bObj[key])) return false;
|
|
308
|
+
}
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
function pipe(initial, ...fns) {
|
|
312
|
+
return fns.reduce((acc, fn) => fn(acc), initial);
|
|
313
|
+
}
|
|
314
|
+
function compose(...fns) {
|
|
315
|
+
return (initial) => fns.reduceRight((acc, fn) => fn(acc), initial);
|
|
316
|
+
}
|
|
268
317
|
|
|
269
318
|
// src/math/index.ts
|
|
270
319
|
var DivisionByZeroError = class extends Error {
|
|
@@ -354,6 +403,250 @@ function randomInt(min, max) {
|
|
|
354
403
|
function inRange(value, min, max) {
|
|
355
404
|
return value >= min && value <= max;
|
|
356
405
|
}
|
|
406
|
+
function median(values) {
|
|
407
|
+
if (values.length === 0) throw new RangeError("Cannot compute median of an empty array");
|
|
408
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
409
|
+
const mid = Math.floor(sorted.length / 2);
|
|
410
|
+
return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
|
|
411
|
+
}
|
|
412
|
+
function stddev(values) {
|
|
413
|
+
if (values.length < 2) throw new RangeError("Need at least 2 values for stddev");
|
|
414
|
+
const mean = sum(values) / values.length;
|
|
415
|
+
const sqDiffs = values.map((v) => (v - mean) ** 2);
|
|
416
|
+
return Math.sqrt(sqDiffs.reduce((a, b) => a + b, 0) / values.length);
|
|
417
|
+
}
|
|
418
|
+
function sampleStddev(values) {
|
|
419
|
+
if (values.length < 2) throw new RangeError("Need at least 2 values for sample stddev");
|
|
420
|
+
const mean = sum(values) / values.length;
|
|
421
|
+
const sqDiffs = values.map((v) => (v - mean) ** 2);
|
|
422
|
+
return Math.sqrt(sqDiffs.reduce((a, b) => a + b, 0) / (values.length - 1));
|
|
423
|
+
}
|
|
424
|
+
function percentile(values, p) {
|
|
425
|
+
if (values.length === 0) throw new RangeError("Cannot compute percentile of empty array");
|
|
426
|
+
if (p < 0 || p > 100) throw new RangeError("Percentile must be between 0 and 100");
|
|
427
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
428
|
+
const rank = p / 100 * (sorted.length - 1);
|
|
429
|
+
const lower = Math.floor(rank);
|
|
430
|
+
const upper = Math.ceil(rank);
|
|
431
|
+
if (lower === upper) return sorted[lower];
|
|
432
|
+
return sorted[lower] + (sorted[upper] - sorted[lower]) * (rank - lower);
|
|
433
|
+
}
|
|
434
|
+
function correlation(x, y) {
|
|
435
|
+
if (x.length !== y.length) throw new RangeError("Arrays must have the same length");
|
|
436
|
+
if (x.length < 2) throw new RangeError("Need at least 2 pairs for correlation");
|
|
437
|
+
const n = x.length;
|
|
438
|
+
const meanX = sum(x) / n;
|
|
439
|
+
const meanY = sum(y) / n;
|
|
440
|
+
let num = 0;
|
|
441
|
+
let denX = 0;
|
|
442
|
+
let denY = 0;
|
|
443
|
+
for (let i = 0; i < n; i++) {
|
|
444
|
+
const dx = x[i] - meanX;
|
|
445
|
+
const dy = y[i] - meanY;
|
|
446
|
+
num += dx * dy;
|
|
447
|
+
denX += dx * dx;
|
|
448
|
+
denY += dy * dy;
|
|
449
|
+
}
|
|
450
|
+
if (denX === 0 || denY === 0) return 0;
|
|
451
|
+
return num / Math.sqrt(denX * denY);
|
|
452
|
+
}
|
|
453
|
+
function formatCurrency(value, options) {
|
|
454
|
+
const locale = options?.locale ?? "id-ID";
|
|
455
|
+
const currency = options?.currency ?? "IDR";
|
|
456
|
+
const notation = options?.notation ?? "standard";
|
|
457
|
+
try {
|
|
458
|
+
return new Intl.NumberFormat(locale, {
|
|
459
|
+
style: "currency",
|
|
460
|
+
currency,
|
|
461
|
+
notation,
|
|
462
|
+
minimumFractionDigits: 0,
|
|
463
|
+
maximumFractionDigits: 2
|
|
464
|
+
}).format(value);
|
|
465
|
+
} catch {
|
|
466
|
+
return `${currency} ${value.toLocaleString(locale)}`;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
function isEven(n) {
|
|
470
|
+
return n % 2 === 0;
|
|
471
|
+
}
|
|
472
|
+
function isOdd(n) {
|
|
473
|
+
return n % 2 !== 0;
|
|
474
|
+
}
|
|
475
|
+
function gcd(a, b) {
|
|
476
|
+
if (!Number.isInteger(a) || !Number.isInteger(b)) {
|
|
477
|
+
throw new RangeError("Arguments must be integers");
|
|
478
|
+
}
|
|
479
|
+
a = Math.abs(a);
|
|
480
|
+
b = Math.abs(b);
|
|
481
|
+
while (b !== 0) {
|
|
482
|
+
const t = b;
|
|
483
|
+
b = a % b;
|
|
484
|
+
a = t;
|
|
485
|
+
}
|
|
486
|
+
return a;
|
|
487
|
+
}
|
|
488
|
+
function lcm(a, b) {
|
|
489
|
+
if (!Number.isInteger(a) || !Number.isInteger(b)) {
|
|
490
|
+
throw new RangeError("Arguments must be integers");
|
|
491
|
+
}
|
|
492
|
+
if (a === 0 || b === 0) {
|
|
493
|
+
throw new RangeError("Arguments must be non-zero");
|
|
494
|
+
}
|
|
495
|
+
return Math.abs(a * b) / gcd(a, b);
|
|
496
|
+
}
|
|
497
|
+
function factorial(n) {
|
|
498
|
+
if (!Number.isInteger(n)) {
|
|
499
|
+
throw new RangeError("Argument must be an integer");
|
|
500
|
+
}
|
|
501
|
+
if (n < 0) {
|
|
502
|
+
throw new RangeError("Factorial is not defined for negative numbers");
|
|
503
|
+
}
|
|
504
|
+
let result = 1;
|
|
505
|
+
for (let i = 2; i <= n; i++) {
|
|
506
|
+
result *= i;
|
|
507
|
+
}
|
|
508
|
+
return result;
|
|
509
|
+
}
|
|
510
|
+
function isPrime(n) {
|
|
511
|
+
if (!Number.isInteger(n)) {
|
|
512
|
+
throw new RangeError("Argument must be an integer");
|
|
513
|
+
}
|
|
514
|
+
if (n < 2) return false;
|
|
515
|
+
if (n === 2 || n === 3) return true;
|
|
516
|
+
if (n % 2 === 0 || n % 3 === 0) return false;
|
|
517
|
+
const limit = Math.sqrt(n);
|
|
518
|
+
for (let i = 5; i <= limit; i += 6) {
|
|
519
|
+
if (n % i === 0 || n % (i + 2) === 0) return false;
|
|
520
|
+
}
|
|
521
|
+
return true;
|
|
522
|
+
}
|
|
523
|
+
function toRadians(degrees) {
|
|
524
|
+
return degrees * Math.PI / 180;
|
|
525
|
+
}
|
|
526
|
+
function toDegrees(radians) {
|
|
527
|
+
return radians * 180 / Math.PI;
|
|
528
|
+
}
|
|
529
|
+
function lerp(a, b, t) {
|
|
530
|
+
return a + (b - a) * t;
|
|
531
|
+
}
|
|
532
|
+
function percentageOf(value, total) {
|
|
533
|
+
if (total === 0) {
|
|
534
|
+
throw new RangeError("Total must be non-zero");
|
|
535
|
+
}
|
|
536
|
+
return value / total * 100;
|
|
537
|
+
}
|
|
538
|
+
function mapRange(value, inMin, inMax, outMin, outMax) {
|
|
539
|
+
if (inMin === inMax) {
|
|
540
|
+
throw new RangeError("Input range must not be zero");
|
|
541
|
+
}
|
|
542
|
+
return (value - inMin) / (inMax - inMin) * (outMax - outMin) + outMin;
|
|
543
|
+
}
|
|
544
|
+
function mode(values) {
|
|
545
|
+
if (values.length === 0) {
|
|
546
|
+
throw new RangeError("Cannot compute mode of an empty array");
|
|
547
|
+
}
|
|
548
|
+
const freq = /* @__PURE__ */ new Map();
|
|
549
|
+
let maxFreq = 0;
|
|
550
|
+
for (const v of values) {
|
|
551
|
+
const count = (freq.get(v) ?? 0) + 1;
|
|
552
|
+
freq.set(v, count);
|
|
553
|
+
if (count > maxFreq) maxFreq = count;
|
|
554
|
+
}
|
|
555
|
+
const result = [];
|
|
556
|
+
for (const [v, count] of freq) {
|
|
557
|
+
if (count === maxFreq) result.push(v);
|
|
558
|
+
}
|
|
559
|
+
return result;
|
|
560
|
+
}
|
|
561
|
+
function range(start, end, step) {
|
|
562
|
+
const dir = end >= start ? 1 : -1;
|
|
563
|
+
const s = step ?? dir;
|
|
564
|
+
if (s === 0) {
|
|
565
|
+
throw new RangeError("Step must not be zero");
|
|
566
|
+
}
|
|
567
|
+
if ((end - start) * s < 0) {
|
|
568
|
+
return [];
|
|
569
|
+
}
|
|
570
|
+
const result = [];
|
|
571
|
+
let i = start;
|
|
572
|
+
if (s > 0) {
|
|
573
|
+
while (i <= end) {
|
|
574
|
+
result.push(i);
|
|
575
|
+
i += s;
|
|
576
|
+
}
|
|
577
|
+
} else {
|
|
578
|
+
while (i >= end) {
|
|
579
|
+
result.push(i);
|
|
580
|
+
i += s;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
return result;
|
|
584
|
+
}
|
|
585
|
+
function weightedAverage(values, weights) {
|
|
586
|
+
if (values.length === 0 || weights.length === 0) {
|
|
587
|
+
throw new RangeError("Arrays must not be empty");
|
|
588
|
+
}
|
|
589
|
+
if (values.length !== weights.length) {
|
|
590
|
+
throw new RangeError("Values and weights must have the same length");
|
|
591
|
+
}
|
|
592
|
+
let weightedSum = 0;
|
|
593
|
+
let weightSum = 0;
|
|
594
|
+
for (let i = 0; i < values.length; i++) {
|
|
595
|
+
weightedSum += values[i] * weights[i];
|
|
596
|
+
weightSum += weights[i];
|
|
597
|
+
}
|
|
598
|
+
if (weightSum === 0) {
|
|
599
|
+
throw new RangeError("Sum of weights must be non-zero");
|
|
600
|
+
}
|
|
601
|
+
return weightedSum / weightSum;
|
|
602
|
+
}
|
|
603
|
+
function geometricMean(values) {
|
|
604
|
+
if (values.length === 0) {
|
|
605
|
+
throw new RangeError("Cannot compute geometric mean of an empty array");
|
|
606
|
+
}
|
|
607
|
+
for (const v of values) {
|
|
608
|
+
if (v < 0) {
|
|
609
|
+
throw new RangeError("Values must be non-negative for geometric mean");
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
const logSum = values.reduce((acc, v) => v === 0 ? acc : acc + Math.log(v), 0);
|
|
613
|
+
if (logSum === -Infinity) return 0;
|
|
614
|
+
return Math.exp(logSum / values.length);
|
|
615
|
+
}
|
|
616
|
+
function combinations(n, k) {
|
|
617
|
+
if (!Number.isInteger(n) || !Number.isInteger(k)) {
|
|
618
|
+
throw new RangeError("Arguments must be integers");
|
|
619
|
+
}
|
|
620
|
+
if (n < 0 || k < 0) {
|
|
621
|
+
throw new RangeError("Arguments must be non-negative");
|
|
622
|
+
}
|
|
623
|
+
if (k > n) {
|
|
624
|
+
throw new RangeError("k must not exceed n");
|
|
625
|
+
}
|
|
626
|
+
if (k === 0 || k === n) return 1;
|
|
627
|
+
const r = Math.min(k, n - k);
|
|
628
|
+
let result = 1;
|
|
629
|
+
for (let i = 1; i <= r; i++) {
|
|
630
|
+
result = result * (n - r + i) / i;
|
|
631
|
+
}
|
|
632
|
+
return result;
|
|
633
|
+
}
|
|
634
|
+
function permutations(n, k) {
|
|
635
|
+
if (!Number.isInteger(n) || !Number.isInteger(k)) {
|
|
636
|
+
throw new RangeError("Arguments must be integers");
|
|
637
|
+
}
|
|
638
|
+
if (n < 0 || k < 0) {
|
|
639
|
+
throw new RangeError("Arguments must be non-negative");
|
|
640
|
+
}
|
|
641
|
+
if (k > n) {
|
|
642
|
+
throw new RangeError("k must not exceed n");
|
|
643
|
+
}
|
|
644
|
+
let result = 1;
|
|
645
|
+
for (let i = n; i > n - k; i--) {
|
|
646
|
+
result *= i;
|
|
647
|
+
}
|
|
648
|
+
return result;
|
|
649
|
+
}
|
|
357
650
|
|
|
358
651
|
// src/date/index.ts
|
|
359
652
|
var InvalidDateError = class extends Error {
|
|
@@ -610,6 +903,427 @@ function calculateAge(birthDate) {
|
|
|
610
903
|
}
|
|
611
904
|
return age;
|
|
612
905
|
}
|
|
906
|
+
var LOCALE_LABELS = {
|
|
907
|
+
id: {
|
|
908
|
+
years: { single: "tahun", plural: "tahun" },
|
|
909
|
+
months: { single: "bulan", plural: "bulan" },
|
|
910
|
+
weeks: { single: "minggu", plural: "minggu" },
|
|
911
|
+
days: { single: "hari", plural: "hari" },
|
|
912
|
+
hours: { single: "jam", plural: "jam" },
|
|
913
|
+
minutes: { single: "menit", plural: "menit" },
|
|
914
|
+
seconds: { single: "detik", plural: "detik" }
|
|
915
|
+
},
|
|
916
|
+
en: {
|
|
917
|
+
years: { single: "year", plural: "years" },
|
|
918
|
+
months: { single: "month", plural: "months" },
|
|
919
|
+
weeks: { single: "week", plural: "weeks" },
|
|
920
|
+
days: { single: "day", plural: "days" },
|
|
921
|
+
hours: { single: "hour", plural: "hours" },
|
|
922
|
+
minutes: { single: "minute", plural: "minutes" },
|
|
923
|
+
seconds: { single: "second", plural: "seconds" }
|
|
924
|
+
}
|
|
925
|
+
};
|
|
926
|
+
function getSuffix(diffMs, kind, locale) {
|
|
927
|
+
if (diffMs < 0) {
|
|
928
|
+
return locale === "en" ? "ago" : "yang lalu";
|
|
929
|
+
}
|
|
930
|
+
if (kind === "remaining") {
|
|
931
|
+
return locale === "en" ? "remaining" : "lagi";
|
|
932
|
+
}
|
|
933
|
+
return locale === "en" ? "ago" : "yang lalu";
|
|
934
|
+
}
|
|
935
|
+
function formatRelativeTime(absDiffMs, suffix, locale) {
|
|
936
|
+
const labels = LOCALE_LABELS[locale] ?? LOCALE_LABELS.id;
|
|
937
|
+
const seconds = Math.floor(absDiffMs / 1e3);
|
|
938
|
+
const minutes = Math.floor(seconds / 60);
|
|
939
|
+
const hours = Math.floor(minutes / 60);
|
|
940
|
+
const days = Math.floor(hours / 24);
|
|
941
|
+
const weeks = Math.floor(days / 7);
|
|
942
|
+
const months = Math.floor(days / 30.4375);
|
|
943
|
+
const years = Math.floor(days / 365.25);
|
|
944
|
+
let count;
|
|
945
|
+
let unit;
|
|
946
|
+
if (years >= 1) {
|
|
947
|
+
count = years;
|
|
948
|
+
unit = "years";
|
|
949
|
+
} else if (months >= 1) {
|
|
950
|
+
count = months;
|
|
951
|
+
unit = "months";
|
|
952
|
+
} else if (weeks >= 1) {
|
|
953
|
+
count = weeks;
|
|
954
|
+
unit = "weeks";
|
|
955
|
+
} else if (days >= 1) {
|
|
956
|
+
count = days;
|
|
957
|
+
unit = "days";
|
|
958
|
+
} else if (hours >= 1) {
|
|
959
|
+
count = hours;
|
|
960
|
+
unit = "hours";
|
|
961
|
+
} else if (minutes >= 1) {
|
|
962
|
+
count = minutes;
|
|
963
|
+
unit = "minutes";
|
|
964
|
+
} else {
|
|
965
|
+
count = Math.max(1, seconds);
|
|
966
|
+
unit = "seconds";
|
|
967
|
+
}
|
|
968
|
+
const label = count === 1 ? labels[unit].single : labels[unit].plural;
|
|
969
|
+
return `${count} ${label} ${suffix}`;
|
|
970
|
+
}
|
|
971
|
+
function timeAgo(date, options) {
|
|
972
|
+
const diff = Date.now() - date.getTime();
|
|
973
|
+
const locale = options?.locale ?? "id";
|
|
974
|
+
const suffix = getSuffix(diff, "ago", locale);
|
|
975
|
+
return formatRelativeTime(Math.abs(diff), suffix, locale);
|
|
976
|
+
}
|
|
977
|
+
function timeRemaining(target, options) {
|
|
978
|
+
const diff = target.getTime() - Date.now();
|
|
979
|
+
const locale = options?.locale ?? "id";
|
|
980
|
+
const suffix = getSuffix(diff, "remaining", locale);
|
|
981
|
+
return formatRelativeTime(Math.abs(diff), suffix, locale);
|
|
982
|
+
}
|
|
983
|
+
function formatDuration(duration, options) {
|
|
984
|
+
const locale = options?.locale ?? "id";
|
|
985
|
+
const labels = LOCALE_LABELS[locale] ?? LOCALE_LABELS.id;
|
|
986
|
+
const parts = [];
|
|
987
|
+
const entries = [
|
|
988
|
+
["years", duration.years],
|
|
989
|
+
["months", duration.months],
|
|
990
|
+
["days", duration.days],
|
|
991
|
+
["hours", duration.hours],
|
|
992
|
+
["minutes", duration.minutes],
|
|
993
|
+
["seconds", duration.seconds]
|
|
994
|
+
];
|
|
995
|
+
for (const [key, value] of entries) {
|
|
996
|
+
if (value > 0) {
|
|
997
|
+
const label = value === 1 ? labels[key].single : labels[key].plural;
|
|
998
|
+
parts.push(`${value} ${label}`);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
if (parts.length === 0) {
|
|
1002
|
+
const label = labels.seconds.plural;
|
|
1003
|
+
return `0 ${label}`;
|
|
1004
|
+
}
|
|
1005
|
+
return parts.join(" ");
|
|
1006
|
+
}
|
|
1007
|
+
var TIMEZONE_WIB = 7;
|
|
1008
|
+
var TIMEZONE_WITA = 8;
|
|
1009
|
+
var TIMEZONE_WIT = 9;
|
|
1010
|
+
function toTimezone(date, offsetHours) {
|
|
1011
|
+
if (!isValidDate(date)) throw new InvalidDateError(date);
|
|
1012
|
+
const utcMs = date.getTime() + date.getTimezoneOffset() * 6e4;
|
|
1013
|
+
return new Date(utcMs + offsetHours * 36e5);
|
|
1014
|
+
}
|
|
1015
|
+
function formatInTimezone(date, format2, offsetHours) {
|
|
1016
|
+
return formatDate(toTimezone(date, offsetHours), format2);
|
|
1017
|
+
}
|
|
1018
|
+
function isToday(date) {
|
|
1019
|
+
if (!isValidDate(date)) throw new InvalidDateError(date);
|
|
1020
|
+
const now = /* @__PURE__ */ new Date();
|
|
1021
|
+
return date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate();
|
|
1022
|
+
}
|
|
1023
|
+
function isYesterday(date) {
|
|
1024
|
+
if (!isValidDate(date)) throw new InvalidDateError(date);
|
|
1025
|
+
const yesterday = /* @__PURE__ */ new Date();
|
|
1026
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
1027
|
+
return date.getFullYear() === yesterday.getFullYear() && date.getMonth() === yesterday.getMonth() && date.getDate() === yesterday.getDate();
|
|
1028
|
+
}
|
|
1029
|
+
function isTomorrow(date) {
|
|
1030
|
+
if (!isValidDate(date)) throw new InvalidDateError(date);
|
|
1031
|
+
const tomorrow = /* @__PURE__ */ new Date();
|
|
1032
|
+
tomorrow.setDate(tomorrow.getDate() + 1);
|
|
1033
|
+
return date.getFullYear() === tomorrow.getFullYear() && date.getMonth() === tomorrow.getMonth() && date.getDate() === tomorrow.getDate();
|
|
1034
|
+
}
|
|
1035
|
+
function isPast(date) {
|
|
1036
|
+
if (!isValidDate(date)) throw new InvalidDateError(date);
|
|
1037
|
+
return date.getTime() < Date.now();
|
|
1038
|
+
}
|
|
1039
|
+
function isFuture(date) {
|
|
1040
|
+
if (!isValidDate(date)) throw new InvalidDateError(date);
|
|
1041
|
+
return date.getTime() > Date.now();
|
|
1042
|
+
}
|
|
1043
|
+
function isSameDay(date1, date2) {
|
|
1044
|
+
if (!isValidDate(date1) || !isValidDate(date2)) {
|
|
1045
|
+
throw new InvalidDateError("Invalid date provided to isSameDay");
|
|
1046
|
+
}
|
|
1047
|
+
return date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && date1.getDate() === date2.getDate();
|
|
1048
|
+
}
|
|
1049
|
+
function daysInMonth(date) {
|
|
1050
|
+
if (!isValidDate(date)) throw new InvalidDateError(date);
|
|
1051
|
+
return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
1052
|
+
}
|
|
1053
|
+
function dayOfYear(date) {
|
|
1054
|
+
if (!isValidDate(date)) throw new InvalidDateError(date);
|
|
1055
|
+
const start = new Date(date.getFullYear(), 0, 0);
|
|
1056
|
+
return Math.floor((date.getTime() - start.getTime()) / MS_IN_DAY);
|
|
1057
|
+
}
|
|
1058
|
+
function weekOfYear(date) {
|
|
1059
|
+
if (!isValidDate(date)) throw new InvalidDateError(date);
|
|
1060
|
+
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
|
|
1061
|
+
const dayNum = d.getUTCDay() || 7;
|
|
1062
|
+
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
|
|
1063
|
+
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
|
1064
|
+
const weekNum = Math.ceil(((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7);
|
|
1065
|
+
return weekNum;
|
|
1066
|
+
}
|
|
1067
|
+
function quarter(date) {
|
|
1068
|
+
if (!isValidDate(date)) throw new InvalidDateError(date);
|
|
1069
|
+
return Math.floor(date.getMonth() / 3) + 1;
|
|
1070
|
+
}
|
|
1071
|
+
function maxDate(dates) {
|
|
1072
|
+
if (dates.length === 0) throw new Error("maxDate requires at least one date");
|
|
1073
|
+
const ms = Math.max(...dates.map((d) => {
|
|
1074
|
+
if (!isValidDate(d)) throw new InvalidDateError(d);
|
|
1075
|
+
return d.getTime();
|
|
1076
|
+
}));
|
|
1077
|
+
return new Date(ms);
|
|
1078
|
+
}
|
|
1079
|
+
function minDate(dates) {
|
|
1080
|
+
if (dates.length === 0) throw new Error("minDate requires at least one date");
|
|
1081
|
+
const ms = Math.min(...dates.map((d) => {
|
|
1082
|
+
if (!isValidDate(d)) throw new InvalidDateError(d);
|
|
1083
|
+
return d.getTime();
|
|
1084
|
+
}));
|
|
1085
|
+
return new Date(ms);
|
|
1086
|
+
}
|
|
1087
|
+
function getNextWeekday(date, targetDay) {
|
|
1088
|
+
if (!isValidDate(date)) throw new InvalidDateError(date);
|
|
1089
|
+
const result = new Date(date);
|
|
1090
|
+
const currentDay = result.getDay();
|
|
1091
|
+
let diff = targetDay - currentDay;
|
|
1092
|
+
if (diff <= 0) diff += 7;
|
|
1093
|
+
result.setDate(result.getDate() + diff);
|
|
1094
|
+
return result;
|
|
1095
|
+
}
|
|
1096
|
+
function getLastWeekday(date, targetDay) {
|
|
1097
|
+
if (!isValidDate(date)) throw new InvalidDateError(date);
|
|
1098
|
+
const result = new Date(date);
|
|
1099
|
+
const currentDay = result.getDay();
|
|
1100
|
+
let diff = currentDay - targetDay;
|
|
1101
|
+
if (diff <= 0) diff += 7;
|
|
1102
|
+
result.setDate(result.getDate() - diff);
|
|
1103
|
+
return result;
|
|
1104
|
+
}
|
|
1105
|
+
function nextMonday(date) {
|
|
1106
|
+
return getNextWeekday(date, 1);
|
|
1107
|
+
}
|
|
1108
|
+
function nextTuesday(date) {
|
|
1109
|
+
return getNextWeekday(date, 2);
|
|
1110
|
+
}
|
|
1111
|
+
function nextWednesday(date) {
|
|
1112
|
+
return getNextWeekday(date, 3);
|
|
1113
|
+
}
|
|
1114
|
+
function nextThursday(date) {
|
|
1115
|
+
return getNextWeekday(date, 4);
|
|
1116
|
+
}
|
|
1117
|
+
function nextFriday(date) {
|
|
1118
|
+
return getNextWeekday(date, 5);
|
|
1119
|
+
}
|
|
1120
|
+
function nextSaturday(date) {
|
|
1121
|
+
return getNextWeekday(date, 6);
|
|
1122
|
+
}
|
|
1123
|
+
function nextSunday(date) {
|
|
1124
|
+
return getNextWeekday(date, 0);
|
|
1125
|
+
}
|
|
1126
|
+
function lastMonday(date) {
|
|
1127
|
+
return getLastWeekday(date, 1);
|
|
1128
|
+
}
|
|
1129
|
+
function lastTuesday(date) {
|
|
1130
|
+
return getLastWeekday(date, 2);
|
|
1131
|
+
}
|
|
1132
|
+
function lastWednesday(date) {
|
|
1133
|
+
return getLastWeekday(date, 3);
|
|
1134
|
+
}
|
|
1135
|
+
function lastThursday(date) {
|
|
1136
|
+
return getLastWeekday(date, 4);
|
|
1137
|
+
}
|
|
1138
|
+
function lastFriday(date) {
|
|
1139
|
+
return getLastWeekday(date, 5);
|
|
1140
|
+
}
|
|
1141
|
+
function lastSaturday(date) {
|
|
1142
|
+
return getLastWeekday(date, 6);
|
|
1143
|
+
}
|
|
1144
|
+
function lastSunday(date) {
|
|
1145
|
+
return getLastWeekday(date, 0);
|
|
1146
|
+
}
|
|
1147
|
+
function parseDuration(input) {
|
|
1148
|
+
const regex = /(\d+)\s*([wdhms])/g;
|
|
1149
|
+
let ms = 0;
|
|
1150
|
+
let match;
|
|
1151
|
+
while ((match = regex.exec(input)) !== null) {
|
|
1152
|
+
const val = parseInt(match[1], 10);
|
|
1153
|
+
switch (match[2]) {
|
|
1154
|
+
case "w":
|
|
1155
|
+
ms += val * 7 * MS_IN_DAY;
|
|
1156
|
+
break;
|
|
1157
|
+
case "d":
|
|
1158
|
+
ms += val * MS_IN_DAY;
|
|
1159
|
+
break;
|
|
1160
|
+
case "h":
|
|
1161
|
+
ms += val * MS_IN_HOUR;
|
|
1162
|
+
break;
|
|
1163
|
+
case "m":
|
|
1164
|
+
ms += val * MS_IN_MINUTE;
|
|
1165
|
+
break;
|
|
1166
|
+
case "s":
|
|
1167
|
+
ms += val * MS_IN_SECOND;
|
|
1168
|
+
break;
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
return ms;
|
|
1172
|
+
}
|
|
1173
|
+
var INDONESIAN_FIXED_HOLIDAYS = [
|
|
1174
|
+
{ name: "New Year", month: 0, day: 1 },
|
|
1175
|
+
{ name: "Labor Day", month: 4, day: 1 },
|
|
1176
|
+
{ name: "Pancasila Day", month: 5, day: 1 },
|
|
1177
|
+
{ name: "Independence Day", month: 7, day: 17 },
|
|
1178
|
+
{ name: "National Awakening Day", month: 4, day: 20 },
|
|
1179
|
+
{ name: "National Heroes Day", month: 10, day: 10 },
|
|
1180
|
+
{ name: "Christmas", month: 11, day: 25 }
|
|
1181
|
+
];
|
|
1182
|
+
function computeEaster(year) {
|
|
1183
|
+
const a = year % 19;
|
|
1184
|
+
const b = Math.floor(year / 100);
|
|
1185
|
+
const c = year % 100;
|
|
1186
|
+
const d = Math.floor(b / 4);
|
|
1187
|
+
const e = b % 4;
|
|
1188
|
+
const f = Math.floor((b + 8) / 25);
|
|
1189
|
+
const g = Math.floor((b - f + 1) / 3);
|
|
1190
|
+
const h = (19 * a + b - d - g + 15) % 30;
|
|
1191
|
+
const i = Math.floor(c / 4);
|
|
1192
|
+
const k = c % 4;
|
|
1193
|
+
const l = (32 + 2 * e + 2 * i - h - k) % 7;
|
|
1194
|
+
const m = Math.floor((a + 11 * h + 22 * l) / 451);
|
|
1195
|
+
const month = Math.floor((h + l - 7 * m + 114) / 31);
|
|
1196
|
+
const day = (h + l - 7 * m + 114) % 31 + 1;
|
|
1197
|
+
return new Date(year, month - 1, day);
|
|
1198
|
+
}
|
|
1199
|
+
var CHINESE_NEW_YEAR = {
|
|
1200
|
+
2024: { month: 1, day: 10 },
|
|
1201
|
+
2025: { month: 0, day: 29 },
|
|
1202
|
+
2026: { month: 1, day: 17 },
|
|
1203
|
+
2027: { month: 1, day: 6 },
|
|
1204
|
+
2028: { month: 0, day: 26 },
|
|
1205
|
+
2029: { month: 1, day: 13 },
|
|
1206
|
+
2030: { month: 2, day: 3 }
|
|
1207
|
+
};
|
|
1208
|
+
var NYEPI = {
|
|
1209
|
+
2024: { month: 2, day: 11 },
|
|
1210
|
+
2025: { month: 2, day: 29 },
|
|
1211
|
+
2026: { month: 2, day: 19 },
|
|
1212
|
+
2027: { month: 2, day: 7 },
|
|
1213
|
+
2028: { month: 2, day: 26 },
|
|
1214
|
+
2029: { month: 2, day: 15 },
|
|
1215
|
+
2030: { month: 2, day: 5 }
|
|
1216
|
+
};
|
|
1217
|
+
var VESAK = {
|
|
1218
|
+
2024: { month: 4, day: 23 },
|
|
1219
|
+
2025: { month: 4, day: 12 },
|
|
1220
|
+
2026: { month: 4, day: 31 },
|
|
1221
|
+
2027: { month: 4, day: 20 },
|
|
1222
|
+
2028: { month: 4, day: 9 },
|
|
1223
|
+
2029: { month: 4, day: 28 },
|
|
1224
|
+
2030: { month: 4, day: 18 }
|
|
1225
|
+
};
|
|
1226
|
+
var EID_AL_FITR = {
|
|
1227
|
+
2024: [{ month: 3, day: 10 }, { month: 3, day: 11 }],
|
|
1228
|
+
2025: [{ month: 2, day: 31 }, { month: 3, day: 1 }],
|
|
1229
|
+
2026: [{ month: 2, day: 21 }, { month: 2, day: 22 }],
|
|
1230
|
+
2027: [{ month: 2, day: 10 }, { month: 2, day: 11 }],
|
|
1231
|
+
2028: [{ month: 2, day: 28 }, { month: 2, day: 29 }],
|
|
1232
|
+
2029: [{ month: 2, day: 17 }, { month: 2, day: 18 }],
|
|
1233
|
+
2030: [{ month: 2, day: 7 }, { month: 2, day: 8 }]
|
|
1234
|
+
};
|
|
1235
|
+
var EID_AL_ADHA = {
|
|
1236
|
+
2024: { month: 5, day: 17 },
|
|
1237
|
+
2025: { month: 5, day: 7 },
|
|
1238
|
+
2026: { month: 4, day: 27 },
|
|
1239
|
+
2027: { month: 4, day: 17 },
|
|
1240
|
+
2028: { month: 5, day: 5 },
|
|
1241
|
+
2029: { month: 4, day: 25 },
|
|
1242
|
+
2030: { month: 4, day: 15 }
|
|
1243
|
+
};
|
|
1244
|
+
var ISLAMIC_NEW_YEAR = {
|
|
1245
|
+
2024: { month: 6, day: 7 },
|
|
1246
|
+
2025: { month: 5, day: 27 },
|
|
1247
|
+
2026: { month: 5, day: 16 },
|
|
1248
|
+
2027: { month: 5, day: 6 },
|
|
1249
|
+
2028: { month: 6, day: 24 },
|
|
1250
|
+
2029: { month: 6, day: 13 },
|
|
1251
|
+
2030: { month: 6, day: 3 }
|
|
1252
|
+
};
|
|
1253
|
+
var PROPHETS_BIRTHDAY = {
|
|
1254
|
+
2024: { month: 8, day: 16 },
|
|
1255
|
+
2025: { month: 8, day: 5 },
|
|
1256
|
+
2026: { month: 7, day: 26 },
|
|
1257
|
+
2027: { month: 7, day: 16 },
|
|
1258
|
+
2028: { month: 8, day: 3 },
|
|
1259
|
+
2029: { month: 7, day: 23 },
|
|
1260
|
+
2030: { month: 7, day: 13 }
|
|
1261
|
+
};
|
|
1262
|
+
var ISRA_MIRAJ = {
|
|
1263
|
+
2024: { month: 1, day: 8 },
|
|
1264
|
+
2025: { month: 0, day: 28 },
|
|
1265
|
+
2026: { month: 0, day: 17 },
|
|
1266
|
+
2027: { month: 0, day: 6 },
|
|
1267
|
+
2028: { month: 0, day: 26 },
|
|
1268
|
+
2029: { month: 1, day: 14 },
|
|
1269
|
+
2030: { month: 1, day: 3 }
|
|
1270
|
+
};
|
|
1271
|
+
function addHolidayEntry(entries, name, month, day) {
|
|
1272
|
+
entries.push({ name, month, day });
|
|
1273
|
+
}
|
|
1274
|
+
function getIndonesianHolidaysForYear(year) {
|
|
1275
|
+
const holidays = [...INDONESIAN_FIXED_HOLIDAYS];
|
|
1276
|
+
const easter = computeEaster(year);
|
|
1277
|
+
addHolidayEntry(holidays, "Good Friday", easter.getMonth(), easter.getDate() - 2);
|
|
1278
|
+
addHolidayEntry(holidays, "Easter", easter.getMonth(), easter.getDate());
|
|
1279
|
+
const ascension = new Date(easter);
|
|
1280
|
+
ascension.setDate(ascension.getDate() + 39);
|
|
1281
|
+
addHolidayEntry(holidays, "Ascension of Jesus Christ", ascension.getMonth(), ascension.getDate());
|
|
1282
|
+
const cny = CHINESE_NEW_YEAR[year];
|
|
1283
|
+
if (cny) addHolidayEntry(holidays, "Chinese New Year", cny.month, cny.day);
|
|
1284
|
+
const nyepi = NYEPI[year];
|
|
1285
|
+
if (nyepi) addHolidayEntry(holidays, "Nyepi (Day of Silence)", nyepi.month, nyepi.day);
|
|
1286
|
+
const vesak = VESAK[year];
|
|
1287
|
+
if (vesak) addHolidayEntry(holidays, "Vesak (Buddha's Birthday)", vesak.month, vesak.day);
|
|
1288
|
+
const eidDays = EID_AL_FITR[year];
|
|
1289
|
+
if (eidDays) {
|
|
1290
|
+
eidDays.forEach((entry, idx) => {
|
|
1291
|
+
addHolidayEntry(holidays, idx === 0 ? "Eid al-Fitr" : "Eid al-Fitr (Day 2)", entry.month, entry.day);
|
|
1292
|
+
});
|
|
1293
|
+
}
|
|
1294
|
+
const eidAdha = EID_AL_ADHA[year];
|
|
1295
|
+
if (eidAdha) addHolidayEntry(holidays, "Eid al-Adha", eidAdha.month, eidAdha.day);
|
|
1296
|
+
const islNewYear = ISLAMIC_NEW_YEAR[year];
|
|
1297
|
+
if (islNewYear) addHolidayEntry(holidays, "Islamic New Year", islNewYear.month, islNewYear.day);
|
|
1298
|
+
const prophetBday = PROPHETS_BIRTHDAY[year];
|
|
1299
|
+
if (prophetBday) addHolidayEntry(holidays, "Prophet Muhammad's Birthday", prophetBday.month, prophetBday.day);
|
|
1300
|
+
const isra = ISRA_MIRAJ[year];
|
|
1301
|
+
if (isra) addHolidayEntry(holidays, "Isra' Mi'raj (Ascension of Prophet Muhammad)", isra.month, isra.day);
|
|
1302
|
+
return holidays;
|
|
1303
|
+
}
|
|
1304
|
+
function isHolidayIndonesia(date) {
|
|
1305
|
+
if (!isValidDate(date)) throw new InvalidDateError(date);
|
|
1306
|
+
const year = date.getFullYear();
|
|
1307
|
+
const holidays = getIndonesianHolidaysForYear(year);
|
|
1308
|
+
for (const h of holidays) {
|
|
1309
|
+
if (h.month === date.getMonth() && h.day === date.getDate()) {
|
|
1310
|
+
return true;
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
return false;
|
|
1314
|
+
}
|
|
1315
|
+
function getIndonesianHolidayNames(date) {
|
|
1316
|
+
if (!isValidDate(date)) throw new InvalidDateError(date);
|
|
1317
|
+
const year = date.getFullYear();
|
|
1318
|
+
const holidays = getIndonesianHolidaysForYear(year);
|
|
1319
|
+
const names = [];
|
|
1320
|
+
for (const h of holidays) {
|
|
1321
|
+
if (h.month === date.getMonth() && h.day === date.getDate()) {
|
|
1322
|
+
names.push(h.name);
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
return names;
|
|
1326
|
+
}
|
|
613
1327
|
|
|
614
1328
|
// src/crypto/index.ts
|
|
615
1329
|
function hash(str) {
|
|
@@ -635,15 +1349,12 @@ function simpleHash(str) {
|
|
|
635
1349
|
return toHex(h1) + toHex(h2) + toHex(h3) + toHex(h4);
|
|
636
1350
|
}
|
|
637
1351
|
function getRandomBytes(size) {
|
|
638
|
-
const bytes = new Uint8Array(size);
|
|
639
1352
|
if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
|
|
1353
|
+
const bytes = new Uint8Array(size);
|
|
640
1354
|
crypto.getRandomValues(bytes);
|
|
641
|
-
|
|
642
|
-
for (let i = 0; i < size; i++) {
|
|
643
|
-
bytes[i] = Math.floor(Math.random() * 256);
|
|
644
|
-
}
|
|
1355
|
+
return bytes;
|
|
645
1356
|
}
|
|
646
|
-
|
|
1357
|
+
throw new Error("Crypto API unavailable. Cannot generate secure random bytes.");
|
|
647
1358
|
}
|
|
648
1359
|
function randomHex(size = 16) {
|
|
649
1360
|
const bytes = getRandomBytes(size);
|
|
@@ -988,6 +1699,217 @@ function isEmpty(value) {
|
|
|
988
1699
|
if (value !== null && typeof value === "object") return Object.keys(value).length === 0;
|
|
989
1700
|
return false;
|
|
990
1701
|
}
|
|
1702
|
+
function topoSort(items) {
|
|
1703
|
+
const adj = /* @__PURE__ */ new Map();
|
|
1704
|
+
const inDegree = /* @__PURE__ */ new Map();
|
|
1705
|
+
const itemMap = /* @__PURE__ */ new Map();
|
|
1706
|
+
for (const item of items) {
|
|
1707
|
+
itemMap.set(item.id, item);
|
|
1708
|
+
if (!adj.has(item.id)) adj.set(item.id, []);
|
|
1709
|
+
if (!inDegree.has(item.id)) inDegree.set(item.id, 0);
|
|
1710
|
+
}
|
|
1711
|
+
for (const item of items) {
|
|
1712
|
+
if (item.dependencies) {
|
|
1713
|
+
for (const depId of item.dependencies) {
|
|
1714
|
+
adj.get(depId)?.push(item.id);
|
|
1715
|
+
inDegree.set(item.id, (inDegree.get(item.id) ?? 0) + 1);
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
const queue = [];
|
|
1720
|
+
for (const [id, degree] of inDegree) {
|
|
1721
|
+
if (degree === 0) queue.push(id);
|
|
1722
|
+
}
|
|
1723
|
+
const sorted = [];
|
|
1724
|
+
while (queue.length > 0) {
|
|
1725
|
+
const id = queue.shift();
|
|
1726
|
+
sorted.push(id);
|
|
1727
|
+
for (const neighbor of adj.get(id) ?? []) {
|
|
1728
|
+
const newDegree = (inDegree.get(neighbor) ?? 1) - 1;
|
|
1729
|
+
inDegree.set(neighbor, newDegree);
|
|
1730
|
+
if (newDegree === 0) queue.push(neighbor);
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
if (sorted.length !== items.length) {
|
|
1734
|
+
throw new Error("Circular dependency detected");
|
|
1735
|
+
}
|
|
1736
|
+
return sorted.map((id) => itemMap.get(id));
|
|
1737
|
+
}
|
|
1738
|
+
function slidingWindows(items, size, step = 1) {
|
|
1739
|
+
if (size <= 0 || items.length === 0 || step <= 0) return [];
|
|
1740
|
+
const result = [];
|
|
1741
|
+
for (let i = 0; i + size <= items.length; i += step) {
|
|
1742
|
+
result.push(items.slice(i, i + size));
|
|
1743
|
+
}
|
|
1744
|
+
return result;
|
|
1745
|
+
}
|
|
1746
|
+
function tumblingWindows(items, size) {
|
|
1747
|
+
if (size <= 0 || items.length === 0) return [];
|
|
1748
|
+
const result = [];
|
|
1749
|
+
for (let i = 0; i < items.length; i += size) {
|
|
1750
|
+
result.push(items.slice(i, i + size));
|
|
1751
|
+
}
|
|
1752
|
+
return result;
|
|
1753
|
+
}
|
|
1754
|
+
function deepGet(obj, path, default_) {
|
|
1755
|
+
const keys = path.split(".");
|
|
1756
|
+
let current = obj;
|
|
1757
|
+
for (const key of keys) {
|
|
1758
|
+
if (current === null || current === void 0) return default_;
|
|
1759
|
+
if (typeof current !== "object") return default_;
|
|
1760
|
+
const curObj = current;
|
|
1761
|
+
if (!(key in curObj)) return default_;
|
|
1762
|
+
current = curObj[key];
|
|
1763
|
+
}
|
|
1764
|
+
return current ?? default_;
|
|
1765
|
+
}
|
|
1766
|
+
function deepSet(obj, path, value) {
|
|
1767
|
+
const keys = path.split(".");
|
|
1768
|
+
const PROTO_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1769
|
+
for (const key of keys) {
|
|
1770
|
+
if (PROTO_KEYS.has(key)) {
|
|
1771
|
+
return { ...obj };
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
const result = { ...obj };
|
|
1775
|
+
let current = result;
|
|
1776
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
1777
|
+
const key = keys[i];
|
|
1778
|
+
const next = current[key];
|
|
1779
|
+
if (next === null || next === void 0 || typeof next !== "object") {
|
|
1780
|
+
const isArray2 = /^\d+$/.test(keys[i + 1]);
|
|
1781
|
+
current[key] = isArray2 ? [] : {};
|
|
1782
|
+
}
|
|
1783
|
+
current = current[key];
|
|
1784
|
+
}
|
|
1785
|
+
current[keys[keys.length - 1]] = value;
|
|
1786
|
+
return result;
|
|
1787
|
+
}
|
|
1788
|
+
function partition(items, predicate) {
|
|
1789
|
+
const pass = [];
|
|
1790
|
+
const fail = [];
|
|
1791
|
+
for (const item of items) {
|
|
1792
|
+
if (predicate(item)) pass.push(item);
|
|
1793
|
+
else fail.push(item);
|
|
1794
|
+
}
|
|
1795
|
+
return [pass, fail];
|
|
1796
|
+
}
|
|
1797
|
+
function compact(items) {
|
|
1798
|
+
return items.filter(Boolean);
|
|
1799
|
+
}
|
|
1800
|
+
function difference(a, b) {
|
|
1801
|
+
const setB = new Set(b);
|
|
1802
|
+
return a.filter((item) => !setB.has(item));
|
|
1803
|
+
}
|
|
1804
|
+
function intersection(a, b) {
|
|
1805
|
+
const setB = new Set(b);
|
|
1806
|
+
return a.filter((item) => setB.has(item));
|
|
1807
|
+
}
|
|
1808
|
+
function union(...arrays) {
|
|
1809
|
+
const set = /* @__PURE__ */ new Set();
|
|
1810
|
+
for (const arr of arrays) {
|
|
1811
|
+
for (const item of arr) {
|
|
1812
|
+
set.add(item);
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
return [...set];
|
|
1816
|
+
}
|
|
1817
|
+
function zip(...arrays) {
|
|
1818
|
+
if (arrays.length === 0) return [];
|
|
1819
|
+
const minLen = Math.min(...arrays.map((a) => a.length));
|
|
1820
|
+
const result = [];
|
|
1821
|
+
for (let i = 0; i < minLen; i++) {
|
|
1822
|
+
const tuple = [];
|
|
1823
|
+
for (const arr of arrays) {
|
|
1824
|
+
tuple.push(arr[i]);
|
|
1825
|
+
}
|
|
1826
|
+
result.push(tuple);
|
|
1827
|
+
}
|
|
1828
|
+
return result;
|
|
1829
|
+
}
|
|
1830
|
+
function unzip(paired) {
|
|
1831
|
+
if (paired.length === 0) return [];
|
|
1832
|
+
const tupleLen = paired.reduce((max, t) => Math.max(max, t.length), 0);
|
|
1833
|
+
const result = Array.from({ length: tupleLen }, () => []);
|
|
1834
|
+
for (const tuple of paired) {
|
|
1835
|
+
for (let i = 0; i < tupleLen; i++) {
|
|
1836
|
+
result[i].push(tuple[i]);
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
return result;
|
|
1840
|
+
}
|
|
1841
|
+
function countBy(items, keyFn) {
|
|
1842
|
+
const result = {};
|
|
1843
|
+
for (const item of items) {
|
|
1844
|
+
const key = keyFn(item);
|
|
1845
|
+
result[key] = (result[key] ?? 0) + 1;
|
|
1846
|
+
}
|
|
1847
|
+
return result;
|
|
1848
|
+
}
|
|
1849
|
+
function maxBy(items, keyFn) {
|
|
1850
|
+
if (items.length === 0) return void 0;
|
|
1851
|
+
let maxItem = items[0];
|
|
1852
|
+
let maxVal = keyFn(maxItem);
|
|
1853
|
+
for (let i = 1; i < items.length; i++) {
|
|
1854
|
+
const val = keyFn(items[i]);
|
|
1855
|
+
if (val > maxVal) {
|
|
1856
|
+
maxVal = val;
|
|
1857
|
+
maxItem = items[i];
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
return maxItem;
|
|
1861
|
+
}
|
|
1862
|
+
function minBy(items, keyFn) {
|
|
1863
|
+
if (items.length === 0) return void 0;
|
|
1864
|
+
let minItem = items[0];
|
|
1865
|
+
let minVal = keyFn(minItem);
|
|
1866
|
+
for (let i = 1; i < items.length; i++) {
|
|
1867
|
+
const val = keyFn(items[i]);
|
|
1868
|
+
if (val < minVal) {
|
|
1869
|
+
minVal = val;
|
|
1870
|
+
minItem = items[i];
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
return minItem;
|
|
1874
|
+
}
|
|
1875
|
+
function sumBy(items, keyFn) {
|
|
1876
|
+
let total = 0;
|
|
1877
|
+
for (const item of items) {
|
|
1878
|
+
total += keyFn(item);
|
|
1879
|
+
}
|
|
1880
|
+
return total;
|
|
1881
|
+
}
|
|
1882
|
+
function findIndex(items, predicate, fromIndex = 0) {
|
|
1883
|
+
for (let i = fromIndex; i < items.length; i++) {
|
|
1884
|
+
if (predicate(items[i])) return i;
|
|
1885
|
+
}
|
|
1886
|
+
return -1;
|
|
1887
|
+
}
|
|
1888
|
+
function findLast(items, predicate) {
|
|
1889
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
1890
|
+
if (predicate(items[i])) return items[i];
|
|
1891
|
+
}
|
|
1892
|
+
return void 0;
|
|
1893
|
+
}
|
|
1894
|
+
function drop(items, n = 1) {
|
|
1895
|
+
return items.slice(Math.max(0, n));
|
|
1896
|
+
}
|
|
1897
|
+
function dropRight(items, n = 1) {
|
|
1898
|
+
return items.slice(0, Math.max(0, items.length - n));
|
|
1899
|
+
}
|
|
1900
|
+
function take(items, n = 1) {
|
|
1901
|
+
return items.slice(0, Math.max(0, n));
|
|
1902
|
+
}
|
|
1903
|
+
function takeRight(items, n = 1) {
|
|
1904
|
+
return items.slice(Math.max(0, items.length - n));
|
|
1905
|
+
}
|
|
1906
|
+
function without(items, ...values) {
|
|
1907
|
+
const exclude = new Set(values);
|
|
1908
|
+
return items.filter((item) => !exclude.has(item));
|
|
1909
|
+
}
|
|
1910
|
+
function nth(items, index) {
|
|
1911
|
+
return index < 0 ? items[items.length + index] : items[index];
|
|
1912
|
+
}
|
|
991
1913
|
|
|
992
1914
|
// src/string/index.ts
|
|
993
1915
|
var WORD_SPLIT_RE = /[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|\d|\b)|\d+/g;
|
|
@@ -1019,6 +1941,7 @@ function truncate(str, maxLength, suffix = "...") {
|
|
|
1019
1941
|
}
|
|
1020
1942
|
function template(str, data) {
|
|
1021
1943
|
return str.replace(/\{\{(\w+)\}\}/g, (_2, key) => {
|
|
1944
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") return `{{${key}}}`;
|
|
1022
1945
|
const value = data[key];
|
|
1023
1946
|
return value !== void 0 ? String(value) : `{{${key}}}`;
|
|
1024
1947
|
});
|
|
@@ -1044,9 +1967,15 @@ function uuid() {
|
|
|
1044
1967
|
}
|
|
1045
1968
|
function nanoid(size = 21, alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-") {
|
|
1046
1969
|
const len = alphabet.length;
|
|
1970
|
+
const bytes = new Uint8Array(size);
|
|
1971
|
+
if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
|
|
1972
|
+
crypto.getRandomValues(bytes);
|
|
1973
|
+
} else {
|
|
1974
|
+
throw new Error("Crypto API unavailable. Cannot generate secure random ID.");
|
|
1975
|
+
}
|
|
1047
1976
|
let result = "";
|
|
1048
1977
|
for (let i = 0; i < size; i++) {
|
|
1049
|
-
result += alphabet[
|
|
1978
|
+
result += alphabet[bytes[i] % len];
|
|
1050
1979
|
}
|
|
1051
1980
|
return result;
|
|
1052
1981
|
}
|
|
@@ -1055,7 +1984,9 @@ var HTML_ESCAPE_MAP = {
|
|
|
1055
1984
|
"<": "<",
|
|
1056
1985
|
">": ">",
|
|
1057
1986
|
'"': """,
|
|
1058
|
-
"'": "'"
|
|
1987
|
+
"'": "'",
|
|
1988
|
+
"`": "`",
|
|
1989
|
+
"/": "/"
|
|
1059
1990
|
};
|
|
1060
1991
|
var HTML_UNESCAPE_MAP = {
|
|
1061
1992
|
"&": "&",
|
|
@@ -1063,13 +1994,15 @@ var HTML_UNESCAPE_MAP = {
|
|
|
1063
1994
|
">": ">",
|
|
1064
1995
|
""": '"',
|
|
1065
1996
|
"'": "'",
|
|
1066
|
-
"'": "'"
|
|
1997
|
+
"'": "'",
|
|
1998
|
+
"`": "`",
|
|
1999
|
+
"/": "/"
|
|
1067
2000
|
};
|
|
1068
2001
|
function escapeHtml(str) {
|
|
1069
|
-
return str.replace(/[&<>"']/g, (ch) => HTML_ESCAPE_MAP[ch] ?? ch);
|
|
2002
|
+
return str.replace(/[&<>"'`\/]/g, (ch) => HTML_ESCAPE_MAP[ch] ?? ch);
|
|
1070
2003
|
}
|
|
1071
2004
|
function unescapeHtml(str) {
|
|
1072
|
-
return str.replace(/&(?:amp|lt|gt|quot|#39|#x27);/g, (entity) => HTML_UNESCAPE_MAP[entity] ?? entity);
|
|
2005
|
+
return str.replace(/&(?:amp|lt|gt|quot|#39|#x27|#96|#x2F);/g, (entity) => HTML_UNESCAPE_MAP[entity] ?? entity);
|
|
1073
2006
|
}
|
|
1074
2007
|
function trim(str) {
|
|
1075
2008
|
return str.trim();
|
|
@@ -1111,6 +2044,494 @@ function countOccurrences(str, substring) {
|
|
|
1111
2044
|
}
|
|
1112
2045
|
return count;
|
|
1113
2046
|
}
|
|
2047
|
+
function levenshtein(a, b) {
|
|
2048
|
+
const an = a.length;
|
|
2049
|
+
const bn = b.length;
|
|
2050
|
+
if (an === 0) return bn;
|
|
2051
|
+
if (bn === 0) return an;
|
|
2052
|
+
if (an < bn) return levenshtein(b, a);
|
|
2053
|
+
let prev = new Uint32Array(bn + 1);
|
|
2054
|
+
let curr = new Uint32Array(bn + 1);
|
|
2055
|
+
for (let j = 0; j <= bn; j++) prev[j] = j;
|
|
2056
|
+
for (let i = 1; i <= an; i++) {
|
|
2057
|
+
curr[0] = i;
|
|
2058
|
+
for (let j = 1; j <= bn; j++) {
|
|
2059
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
2060
|
+
curr[j] = Math.min(
|
|
2061
|
+
prev[j] + 1,
|
|
2062
|
+
curr[j - 1] + 1,
|
|
2063
|
+
prev[j - 1] + cost
|
|
2064
|
+
);
|
|
2065
|
+
}
|
|
2066
|
+
;
|
|
2067
|
+
[prev, curr] = [curr, prev];
|
|
2068
|
+
}
|
|
2069
|
+
return prev[bn];
|
|
2070
|
+
}
|
|
2071
|
+
function fuzzyMatch(str, query) {
|
|
2072
|
+
if (query.length === 0) return true;
|
|
2073
|
+
if (str.length === 0) return false;
|
|
2074
|
+
const sl = str.toLowerCase();
|
|
2075
|
+
const ql = query.toLowerCase();
|
|
2076
|
+
let si = 0;
|
|
2077
|
+
for (let qi = 0; qi < ql.length; qi++) {
|
|
2078
|
+
si = sl.indexOf(ql[qi], si);
|
|
2079
|
+
if (si === -1) return false;
|
|
2080
|
+
si++;
|
|
2081
|
+
}
|
|
2082
|
+
return true;
|
|
2083
|
+
}
|
|
2084
|
+
function maskString(str, options) {
|
|
2085
|
+
if (str.length === 0) return str;
|
|
2086
|
+
const maskChar = options?.char ?? "*";
|
|
2087
|
+
const start = options?.start ?? Math.ceil(str.length * 0.25);
|
|
2088
|
+
const end = options?.end ?? Math.floor(str.length * 0.75);
|
|
2089
|
+
if (start >= end || start < 0) return str;
|
|
2090
|
+
const clampedStart = Math.max(0, start);
|
|
2091
|
+
const clampedEnd = Math.min(str.length, end);
|
|
2092
|
+
return str.slice(0, clampedStart) + maskChar.repeat(clampedEnd - clampedStart) + str.slice(clampedEnd);
|
|
2093
|
+
}
|
|
2094
|
+
var SATUAN = ["", "satu", "dua", "tiga", "empat", "lima", "enam", "tujuh", "delapan", "sembilan"];
|
|
2095
|
+
var BELASAN = ["sepuluh", "sebelas", "dua belas", "tiga belas", "empat belas", "lima belas", "enam belas", "tujuh belas", "delapan belas", "sembilan belas"];
|
|
2096
|
+
var PULUHAN = ["", "", "dua puluh", "tiga puluh", "empat puluh", "lima puluh", "enam puluh", "tujuh puluh", "delapan puluh", "sembilan puluh"];
|
|
2097
|
+
function _terbilang(n) {
|
|
2098
|
+
if (n < 0) return "minus " + _terbilang(-n);
|
|
2099
|
+
if (n === 0) return "nol";
|
|
2100
|
+
if (n < 10) return SATUAN[n];
|
|
2101
|
+
if (n < 20) return n === 10 ? "sepuluh" : n === 11 ? "sebelas" : BELASAN[n - 10];
|
|
2102
|
+
if (n < 100) {
|
|
2103
|
+
const pul = Math.floor(n / 10);
|
|
2104
|
+
const sat = n % 10;
|
|
2105
|
+
return PULUHAN[pul] + (sat > 0 ? " " + SATUAN[sat] : "");
|
|
2106
|
+
}
|
|
2107
|
+
if (n < 1e3) {
|
|
2108
|
+
const ratus = Math.floor(n / 100);
|
|
2109
|
+
const sis2 = n % 100;
|
|
2110
|
+
const ratusStr = ratus === 1 ? "seratus" : SATUAN[ratus] + " ratus";
|
|
2111
|
+
return ratusStr + (sis2 > 0 ? " " + _terbilang(sis2) : "");
|
|
2112
|
+
}
|
|
2113
|
+
if (n < 1e6) {
|
|
2114
|
+
const rib = Math.floor(n / 1e3);
|
|
2115
|
+
const sis2 = n % 1e3;
|
|
2116
|
+
const ribStr = rib === 1 ? "seribu" : _terbilang(rib) + " ribu";
|
|
2117
|
+
return ribStr + (sis2 > 0 ? " " + _terbilang(sis2) : "");
|
|
2118
|
+
}
|
|
2119
|
+
if (n < 1e9) {
|
|
2120
|
+
const jut = Math.floor(n / 1e6);
|
|
2121
|
+
const sis2 = n % 1e6;
|
|
2122
|
+
return _terbilang(jut) + " juta" + (sis2 > 0 ? " " + _terbilang(sis2) : "");
|
|
2123
|
+
}
|
|
2124
|
+
if (n < 1e12) {
|
|
2125
|
+
const mil = Math.floor(n / 1e9);
|
|
2126
|
+
const sis2 = n % 1e9;
|
|
2127
|
+
return _terbilang(mil) + " miliar" + (sis2 > 0 ? " " + _terbilang(sis2) : "");
|
|
2128
|
+
}
|
|
2129
|
+
const tril = Math.floor(n / 1e12);
|
|
2130
|
+
const sis = n % 1e12;
|
|
2131
|
+
return _terbilang(tril) + " triliun" + (sis > 0 ? " " + _terbilang(sis) : "");
|
|
2132
|
+
}
|
|
2133
|
+
function terbilang(value) {
|
|
2134
|
+
if (!Number.isFinite(value)) throw new RangeError("Input must be a finite number");
|
|
2135
|
+
if (value > Number.MAX_SAFE_INTEGER) throw new RangeError("Input terlalu besar");
|
|
2136
|
+
return _terbilang(Math.floor(Math.abs(value)));
|
|
2137
|
+
}
|
|
2138
|
+
function formatRupiah(value, options) {
|
|
2139
|
+
return formatCurrency(value, { locale: "id-ID", currency: "IDR", notation: options?.notation });
|
|
2140
|
+
}
|
|
2141
|
+
function formatBytes(bytes, options) {
|
|
2142
|
+
if (bytes === 0) return "0 B";
|
|
2143
|
+
if (!Number.isFinite(bytes) || bytes < 0) return "0 B";
|
|
2144
|
+
const k = 1024;
|
|
2145
|
+
const sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB"];
|
|
2146
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
2147
|
+
const dm = options?.decimals ?? (i === 0 ? 0 : 1);
|
|
2148
|
+
const index = Math.min(i, sizes.length - 1);
|
|
2149
|
+
return parseFloat((bytes / Math.pow(k, index)).toFixed(dm)) + " " + sizes[index];
|
|
2150
|
+
}
|
|
2151
|
+
function randomString(length = 16) {
|
|
2152
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
2153
|
+
const bytes = new Uint8Array(length);
|
|
2154
|
+
if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
|
|
2155
|
+
crypto.getRandomValues(bytes);
|
|
2156
|
+
} else {
|
|
2157
|
+
throw new Error("Crypto API unavailable. Cannot generate secure random string.");
|
|
2158
|
+
}
|
|
2159
|
+
let result = "";
|
|
2160
|
+
for (let i = 0; i < length; i++) {
|
|
2161
|
+
result += chars[bytes[i] % chars.length];
|
|
2162
|
+
}
|
|
2163
|
+
return result;
|
|
2164
|
+
}
|
|
2165
|
+
function randomBoolean() {
|
|
2166
|
+
return Math.random() >= 0.5;
|
|
2167
|
+
}
|
|
2168
|
+
function pluralize(count, singular) {
|
|
2169
|
+
if (count === 1) return singular;
|
|
2170
|
+
const last2 = singular[singular.length - 1];
|
|
2171
|
+
const lastTwo = singular.slice(-2);
|
|
2172
|
+
if (last2 === "s" || last2 === "x" || last2 === "z" || lastTwo === "ch" || lastTwo === "sh") {
|
|
2173
|
+
return singular + "es";
|
|
2174
|
+
}
|
|
2175
|
+
if (last2 === "y" && singular.length > 2 && !"aeiou".includes(singular[singular.length - 2])) {
|
|
2176
|
+
return singular.slice(0, -1) + "ies";
|
|
2177
|
+
}
|
|
2178
|
+
return singular + "s";
|
|
2179
|
+
}
|
|
2180
|
+
function stripHtml(str) {
|
|
2181
|
+
return str.replace(/<[^>]*>/g, "");
|
|
2182
|
+
}
|
|
2183
|
+
function truncateWords(str, count, suffix = "...") {
|
|
2184
|
+
const words2 = str.split(/\s+/).filter(Boolean);
|
|
2185
|
+
if (words2.length <= count) return str;
|
|
2186
|
+
return words2.slice(0, count).join(" ") + suffix;
|
|
2187
|
+
}
|
|
2188
|
+
function isPalindrome(str) {
|
|
2189
|
+
const cleaned = str.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
|
2190
|
+
if (cleaned.length <= 1) return true;
|
|
2191
|
+
let left = 0;
|
|
2192
|
+
let right = cleaned.length - 1;
|
|
2193
|
+
while (left < right) {
|
|
2194
|
+
if (cleaned[left] !== cleaned[right]) return false;
|
|
2195
|
+
left++;
|
|
2196
|
+
right--;
|
|
2197
|
+
}
|
|
2198
|
+
return true;
|
|
2199
|
+
}
|
|
2200
|
+
function isAnagram(str1, str2) {
|
|
2201
|
+
const clean = (s) => s.replace(/\s/g, "").toLowerCase().split("").sort().join("");
|
|
2202
|
+
return clean(str1) === clean(str2);
|
|
2203
|
+
}
|
|
2204
|
+
function similarity(a, b) {
|
|
2205
|
+
if (a === b) return 1;
|
|
2206
|
+
if (a.length < 2 || b.length < 2) return 0;
|
|
2207
|
+
const bigrams = /* @__PURE__ */ new Map();
|
|
2208
|
+
for (let i = 0; i < a.length - 1; i++) {
|
|
2209
|
+
const bg = a.slice(i, i + 2);
|
|
2210
|
+
bigrams.set(bg, (bigrams.get(bg) ?? 0) + 1);
|
|
2211
|
+
}
|
|
2212
|
+
let intersection2 = 0;
|
|
2213
|
+
for (let i = 0; i < b.length - 1; i++) {
|
|
2214
|
+
const bg = b.slice(i, i + 2);
|
|
2215
|
+
const count = bigrams.get(bg) ?? 0;
|
|
2216
|
+
if (count > 0) {
|
|
2217
|
+
bigrams.set(bg, count - 1);
|
|
2218
|
+
intersection2++;
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
return 2 * intersection2 / (a.length + b.length - 2);
|
|
2222
|
+
}
|
|
2223
|
+
function dedent(str) {
|
|
2224
|
+
const lines = str.split("\n");
|
|
2225
|
+
if (lines.length === 0) return str;
|
|
2226
|
+
const indent = lines.reduce((min, line) => {
|
|
2227
|
+
if (line.trim().length === 0) return min;
|
|
2228
|
+
const leading = line.match(/^[ \t]*/)?.[0]?.length ?? 0;
|
|
2229
|
+
return min === null ? leading : Math.min(min, leading);
|
|
2230
|
+
}, null);
|
|
2231
|
+
if (indent === null || indent === 0) return str;
|
|
2232
|
+
return lines.map((line) => line.slice(indent)).join("\n");
|
|
2233
|
+
}
|
|
2234
|
+
function wordCount(str) {
|
|
2235
|
+
const match = str.match(/[a-zA-Z0-9]+(?:['\u2019][a-zA-Z]+)?/g);
|
|
2236
|
+
return match ? match.length : 0;
|
|
2237
|
+
}
|
|
2238
|
+
function swapCase(str) {
|
|
2239
|
+
let result = "";
|
|
2240
|
+
for (let i = 0; i < str.length; i++) {
|
|
2241
|
+
const ch = str[i];
|
|
2242
|
+
if (ch >= "a" && ch <= "z") {
|
|
2243
|
+
result += ch.toUpperCase();
|
|
2244
|
+
} else if (ch >= "A" && ch <= "Z") {
|
|
2245
|
+
result += ch.toLowerCase();
|
|
2246
|
+
} else {
|
|
2247
|
+
result += ch;
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
return result;
|
|
2251
|
+
}
|
|
2252
|
+
function toCobolCase(str) {
|
|
2253
|
+
const words2 = splitWords(str);
|
|
2254
|
+
return words2.map((w) => w.toUpperCase()).join("_");
|
|
2255
|
+
}
|
|
2256
|
+
function charCount(str) {
|
|
2257
|
+
const result = {};
|
|
2258
|
+
for (let i = 0; i < str.length; i++) {
|
|
2259
|
+
const ch = str[i];
|
|
2260
|
+
result[ch] = (result[ch] ?? 0) + 1;
|
|
2261
|
+
}
|
|
2262
|
+
return result;
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
// src/async/queue.ts
|
|
2266
|
+
var Queue = class {
|
|
2267
|
+
_tasks = [];
|
|
2268
|
+
_running = 0;
|
|
2269
|
+
_paused = false;
|
|
2270
|
+
_idleResolve = null;
|
|
2271
|
+
_maxConcurrency;
|
|
2272
|
+
constructor(options) {
|
|
2273
|
+
this._maxConcurrency = options?.concurrency ?? 1;
|
|
2274
|
+
if (this._maxConcurrency < 1) this._maxConcurrency = 1;
|
|
2275
|
+
}
|
|
2276
|
+
get pending() {
|
|
2277
|
+
return this._tasks.length;
|
|
2278
|
+
}
|
|
2279
|
+
get running() {
|
|
2280
|
+
return this._running;
|
|
2281
|
+
}
|
|
2282
|
+
add(task, options) {
|
|
2283
|
+
return new Promise((resolve2, reject) => {
|
|
2284
|
+
this._tasks.push({
|
|
2285
|
+
priority: options?.priority ?? 0,
|
|
2286
|
+
task,
|
|
2287
|
+
resolve: resolve2,
|
|
2288
|
+
reject
|
|
2289
|
+
});
|
|
2290
|
+
this._tasks.sort((a, b) => b.priority - a.priority);
|
|
2291
|
+
this._process();
|
|
2292
|
+
});
|
|
2293
|
+
}
|
|
2294
|
+
pause() {
|
|
2295
|
+
this._paused = true;
|
|
2296
|
+
}
|
|
2297
|
+
resume() {
|
|
2298
|
+
this._paused = false;
|
|
2299
|
+
this._process();
|
|
2300
|
+
}
|
|
2301
|
+
clear() {
|
|
2302
|
+
const err = new Error("Queue cleared");
|
|
2303
|
+
for (const t of this._tasks) t.reject(err);
|
|
2304
|
+
this._tasks = [];
|
|
2305
|
+
}
|
|
2306
|
+
onIdle() {
|
|
2307
|
+
if (this._running === 0 && this._tasks.length === 0) return Promise.resolve();
|
|
2308
|
+
return new Promise((resolve2) => {
|
|
2309
|
+
this._idleResolve = resolve2;
|
|
2310
|
+
});
|
|
2311
|
+
}
|
|
2312
|
+
_process() {
|
|
2313
|
+
if (this._paused) return;
|
|
2314
|
+
while (this._running < this._maxConcurrency && this._tasks.length > 0) {
|
|
2315
|
+
const item = this._tasks.shift();
|
|
2316
|
+
this._running++;
|
|
2317
|
+
item.task().then((result) => item.resolve(result)).catch((err) => item.reject(err)).finally(() => {
|
|
2318
|
+
this._running--;
|
|
2319
|
+
this._process();
|
|
2320
|
+
if (this._running === 0 && this._tasks.length === 0 && this._idleResolve) {
|
|
2321
|
+
this._idleResolve();
|
|
2322
|
+
this._idleResolve = null;
|
|
2323
|
+
}
|
|
2324
|
+
});
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
};
|
|
2328
|
+
|
|
2329
|
+
// src/async/semaphore.ts
|
|
2330
|
+
var Semaphore = class {
|
|
2331
|
+
_available;
|
|
2332
|
+
_waiting = [];
|
|
2333
|
+
constructor(concurrency) {
|
|
2334
|
+
if (concurrency < 1) throw new RangeError("Semaphore concurrency must be >= 1");
|
|
2335
|
+
this._available = concurrency;
|
|
2336
|
+
}
|
|
2337
|
+
get available() {
|
|
2338
|
+
return this._available;
|
|
2339
|
+
}
|
|
2340
|
+
acquire() {
|
|
2341
|
+
if (this._available > 0) {
|
|
2342
|
+
this._available--;
|
|
2343
|
+
return Promise.resolve(this._release.bind(this));
|
|
2344
|
+
}
|
|
2345
|
+
return new Promise((resolve2) => {
|
|
2346
|
+
this._waiting.push(() => {
|
|
2347
|
+
this._available--;
|
|
2348
|
+
resolve2(this._release.bind(this));
|
|
2349
|
+
});
|
|
2350
|
+
});
|
|
2351
|
+
}
|
|
2352
|
+
async use(fn) {
|
|
2353
|
+
const release = await this.acquire();
|
|
2354
|
+
try {
|
|
2355
|
+
return await fn();
|
|
2356
|
+
} finally {
|
|
2357
|
+
release();
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
_release() {
|
|
2361
|
+
this._available++;
|
|
2362
|
+
if (this._waiting.length > 0) {
|
|
2363
|
+
const next = this._waiting.shift();
|
|
2364
|
+
if (next) next();
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
};
|
|
2368
|
+
|
|
2369
|
+
// src/async/memoize.ts
|
|
2370
|
+
function memoizeAsync(fn, options) {
|
|
2371
|
+
const {
|
|
2372
|
+
ttl = 6e4,
|
|
2373
|
+
staleWhileRevalidate = false,
|
|
2374
|
+
maxSize = 100,
|
|
2375
|
+
resolver = (...args) => JSON.stringify(args)
|
|
2376
|
+
} = options ?? {};
|
|
2377
|
+
const cache = /* @__PURE__ */ new Map();
|
|
2378
|
+
const memoized = (async (...args) => {
|
|
2379
|
+
const key = resolver(...args);
|
|
2380
|
+
const now = Date.now();
|
|
2381
|
+
const entry = cache.get(key);
|
|
2382
|
+
if (entry && now - entry.timestamp < ttl) {
|
|
2383
|
+
return entry.value;
|
|
2384
|
+
}
|
|
2385
|
+
if (entry && staleWhileRevalidate && now - entry.timestamp >= ttl) {
|
|
2386
|
+
if (entry.promise) {
|
|
2387
|
+
return entry.value;
|
|
2388
|
+
}
|
|
2389
|
+
entry.promise = fn(...args).then((result2) => {
|
|
2390
|
+
entry.value = result2;
|
|
2391
|
+
entry.timestamp = now;
|
|
2392
|
+
entry.promise = void 0;
|
|
2393
|
+
return result2;
|
|
2394
|
+
}).catch((err) => {
|
|
2395
|
+
entry.promise = void 0;
|
|
2396
|
+
throw err;
|
|
2397
|
+
});
|
|
2398
|
+
return entry.value;
|
|
2399
|
+
}
|
|
2400
|
+
const result = await fn(...args);
|
|
2401
|
+
cache.set(key, { value: result, timestamp: now });
|
|
2402
|
+
if (cache.size > maxSize) {
|
|
2403
|
+
const firstKey = cache.keys().next().value;
|
|
2404
|
+
if (firstKey !== void 0) cache.delete(firstKey);
|
|
2405
|
+
}
|
|
2406
|
+
return result;
|
|
2407
|
+
});
|
|
2408
|
+
memoized.cache = cache;
|
|
2409
|
+
memoized.clear = () => cache.clear();
|
|
2410
|
+
return memoized;
|
|
2411
|
+
}
|
|
2412
|
+
|
|
2413
|
+
// src/async/ratelimit.ts
|
|
2414
|
+
var RateLimiter = class {
|
|
2415
|
+
_maxRequests;
|
|
2416
|
+
_perWindow;
|
|
2417
|
+
_timestamps = [];
|
|
2418
|
+
constructor(options) {
|
|
2419
|
+
if (options.maxRequests < 1) throw new RangeError("maxRequests must be >= 1");
|
|
2420
|
+
if (options.perWindow < 1) throw new RangeError("perWindow must be >= 1");
|
|
2421
|
+
this._maxRequests = options.maxRequests;
|
|
2422
|
+
this._perWindow = options.perWindow;
|
|
2423
|
+
}
|
|
2424
|
+
_prune() {
|
|
2425
|
+
const now = Date.now();
|
|
2426
|
+
const cutoff = now - this._perWindow;
|
|
2427
|
+
while (this._timestamps.length > 0) {
|
|
2428
|
+
const ts = this._timestamps[0];
|
|
2429
|
+
if (ts === void 0 || ts > cutoff) break;
|
|
2430
|
+
this._timestamps.shift();
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
/**
|
|
2434
|
+
* Check if a request is allowed without waiting.
|
|
2435
|
+
*/
|
|
2436
|
+
tryAcquire() {
|
|
2437
|
+
this._prune();
|
|
2438
|
+
if (this._timestamps.length < this._maxRequests) {
|
|
2439
|
+
this._timestamps.push(Date.now());
|
|
2440
|
+
return true;
|
|
2441
|
+
}
|
|
2442
|
+
return false;
|
|
2443
|
+
}
|
|
2444
|
+
/**
|
|
2445
|
+
* Wait until a request is allowed.
|
|
2446
|
+
*/
|
|
2447
|
+
async acquire() {
|
|
2448
|
+
while (true) {
|
|
2449
|
+
this._prune();
|
|
2450
|
+
if (this._timestamps.length < this._maxRequests) {
|
|
2451
|
+
this._timestamps.push(Date.now());
|
|
2452
|
+
return;
|
|
2453
|
+
}
|
|
2454
|
+
const oldest = this._timestamps[0] ?? Date.now();
|
|
2455
|
+
const waitMs = oldest + this._perWindow - Date.now();
|
|
2456
|
+
if (waitMs > 0) {
|
|
2457
|
+
await new Promise((resolve2) => setTimeout(resolve2, waitMs));
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
/**
|
|
2462
|
+
* Current number of pending requests in the window.
|
|
2463
|
+
*/
|
|
2464
|
+
get pending() {
|
|
2465
|
+
this._prune();
|
|
2466
|
+
return this._timestamps.length;
|
|
2467
|
+
}
|
|
2468
|
+
};
|
|
2469
|
+
|
|
2470
|
+
// src/async/mutex.ts
|
|
2471
|
+
var Mutex = class {
|
|
2472
|
+
_locked = false;
|
|
2473
|
+
_waiting = [];
|
|
2474
|
+
/**
|
|
2475
|
+
* Acquire the lock. Returns a release function to be called when done.
|
|
2476
|
+
*/
|
|
2477
|
+
acquire() {
|
|
2478
|
+
if (!this._locked) {
|
|
2479
|
+
this._locked = true;
|
|
2480
|
+
return Promise.resolve(this._release.bind(this));
|
|
2481
|
+
}
|
|
2482
|
+
return new Promise((resolve2) => {
|
|
2483
|
+
this._waiting.push(() => {
|
|
2484
|
+
resolve2(this._release.bind(this));
|
|
2485
|
+
});
|
|
2486
|
+
});
|
|
2487
|
+
}
|
|
2488
|
+
/**
|
|
2489
|
+
* Run a function with the lock held and automatically release it.
|
|
2490
|
+
*/
|
|
2491
|
+
async use(fn) {
|
|
2492
|
+
const release = await this.acquire();
|
|
2493
|
+
try {
|
|
2494
|
+
return await fn();
|
|
2495
|
+
} finally {
|
|
2496
|
+
release();
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
/**
|
|
2500
|
+
* Whether the mutex is currently locked.
|
|
2501
|
+
*/
|
|
2502
|
+
get locked() {
|
|
2503
|
+
return this._locked;
|
|
2504
|
+
}
|
|
2505
|
+
_release() {
|
|
2506
|
+
if (this._waiting.length > 0) {
|
|
2507
|
+
const next = this._waiting.shift();
|
|
2508
|
+
if (next) next();
|
|
2509
|
+
} else {
|
|
2510
|
+
this._locked = false;
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
};
|
|
2514
|
+
|
|
2515
|
+
// src/async/batch.ts
|
|
2516
|
+
async function batch(items, batchSize, fn) {
|
|
2517
|
+
if (batchSize < 1) throw new RangeError("batchSize must be >= 1");
|
|
2518
|
+
const results = [];
|
|
2519
|
+
for (let i = 0; i < items.length; i += batchSize) {
|
|
2520
|
+
const chunk2 = items.slice(i, i + batchSize);
|
|
2521
|
+
const batchResults = await fn(chunk2);
|
|
2522
|
+
results.push(...batchResults);
|
|
2523
|
+
}
|
|
2524
|
+
return results;
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
// src/async/waterfall.ts
|
|
2528
|
+
async function waterfall(tasks, initial) {
|
|
2529
|
+
let result = initial;
|
|
2530
|
+
for (const task of tasks) {
|
|
2531
|
+
result = await task(result);
|
|
2532
|
+
}
|
|
2533
|
+
return result;
|
|
2534
|
+
}
|
|
1114
2535
|
|
|
1115
2536
|
// src/async/index.ts
|
|
1116
2537
|
function sleep(ms) {
|
|
@@ -1208,6 +2629,7 @@ function parseCsv(input, options) {
|
|
|
1208
2629
|
return body.map((row) => {
|
|
1209
2630
|
const record = {};
|
|
1210
2631
|
for (let i = 0; i < head.length; i++) {
|
|
2632
|
+
if (head[i] === "__proto__" || head[i] === "constructor" || head[i] === "prototype") continue;
|
|
1211
2633
|
record[head[i]] = row[i] ?? "";
|
|
1212
2634
|
}
|
|
1213
2635
|
return record;
|
|
@@ -1348,9 +2770,7 @@ function assertType(value, guard, message) {
|
|
|
1348
2770
|
function ensureArray(value) {
|
|
1349
2771
|
return Array.isArray(value) ? value : [value];
|
|
1350
2772
|
}
|
|
1351
|
-
|
|
1352
|
-
return ensureArray(value);
|
|
1353
|
-
}
|
|
2773
|
+
var castArray = ensureArray;
|
|
1354
2774
|
function getType2(value) {
|
|
1355
2775
|
if (value === null) return "null";
|
|
1356
2776
|
if (value === void 0) return "undefined";
|
|
@@ -2182,6 +3602,29 @@ function isNoRekening(value) {
|
|
|
2182
3602
|
return true;
|
|
2183
3603
|
}
|
|
2184
3604
|
|
|
3605
|
+
// src/validation/isNoSIM.ts
|
|
3606
|
+
function isNoSIM(value) {
|
|
3607
|
+
const digits = value.replace(/\D/g, "");
|
|
3608
|
+
return digits.length === 12;
|
|
3609
|
+
}
|
|
3610
|
+
|
|
3611
|
+
// src/validation/isPassport.ts
|
|
3612
|
+
function isPassport(value) {
|
|
3613
|
+
return /^[A-Za-z]{2}\d{7}$/.test(value.trim());
|
|
3614
|
+
}
|
|
3615
|
+
|
|
3616
|
+
// src/validation/isNoBPJS.ts
|
|
3617
|
+
function isNoBPJS(value) {
|
|
3618
|
+
const digits = value.replace(/\D/g, "");
|
|
3619
|
+
return digits.length === 13;
|
|
3620
|
+
}
|
|
3621
|
+
|
|
3622
|
+
// src/validation/isNoKK.ts
|
|
3623
|
+
function isNoKK(value) {
|
|
3624
|
+
const digits = value.replace(/\D/g, "");
|
|
3625
|
+
return digits.length === 16;
|
|
3626
|
+
}
|
|
3627
|
+
|
|
2185
3628
|
// src/error/createError.ts
|
|
2186
3629
|
var defaultStatus = {
|
|
2187
3630
|
"BAD_REQUEST": 400,
|
|
@@ -2545,6 +3988,98 @@ function meetsWCAG(hex1, hex2, level) {
|
|
|
2545
3988
|
const threshold = level === "AAA" ? 7 : 4.5;
|
|
2546
3989
|
return ratio >= threshold;
|
|
2547
3990
|
}
|
|
3991
|
+
function isValidHex(value) {
|
|
3992
|
+
return /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value);
|
|
3993
|
+
}
|
|
3994
|
+
function hexToHsl(hex) {
|
|
3995
|
+
const rgb = hexToRgb(hex);
|
|
3996
|
+
if (!rgb) return null;
|
|
3997
|
+
const r = rgb.r / 255;
|
|
3998
|
+
const g = rgb.g / 255;
|
|
3999
|
+
const b = rgb.b / 255;
|
|
4000
|
+
const max = Math.max(r, g, b);
|
|
4001
|
+
const min = Math.min(r, g, b);
|
|
4002
|
+
const l = (max + min) / 2;
|
|
4003
|
+
if (max === min) return { h: 0, s: 0, l: Math.round(l * 100) };
|
|
4004
|
+
const d = max - min;
|
|
4005
|
+
const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
4006
|
+
let h = 0;
|
|
4007
|
+
switch (max) {
|
|
4008
|
+
case r:
|
|
4009
|
+
h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
|
4010
|
+
break;
|
|
4011
|
+
case g:
|
|
4012
|
+
h = ((b - r) / d + 2) / 6;
|
|
4013
|
+
break;
|
|
4014
|
+
case b:
|
|
4015
|
+
h = ((r - g) / d + 4) / 6;
|
|
4016
|
+
break;
|
|
4017
|
+
}
|
|
4018
|
+
return {
|
|
4019
|
+
h: Math.round(h * 360),
|
|
4020
|
+
s: Math.round(s * 100),
|
|
4021
|
+
l: Math.round(l * 100)
|
|
4022
|
+
};
|
|
4023
|
+
}
|
|
4024
|
+
function hslToHex(h, s, l) {
|
|
4025
|
+
const hue = h / 360;
|
|
4026
|
+
const sat = s / 100;
|
|
4027
|
+
const lig = l / 100;
|
|
4028
|
+
if (sat === 0) {
|
|
4029
|
+
const val = Math.round(lig * 255);
|
|
4030
|
+
return rgbToHex(val, val, val);
|
|
4031
|
+
}
|
|
4032
|
+
const hue2rgb = (p2, q2, t) => {
|
|
4033
|
+
let tt = t;
|
|
4034
|
+
if (tt < 0) tt += 1;
|
|
4035
|
+
if (tt > 1) tt -= 1;
|
|
4036
|
+
if (tt < 1 / 6) return p2 + (q2 - p2) * 6 * tt;
|
|
4037
|
+
if (tt < 1 / 2) return q2;
|
|
4038
|
+
if (tt < 2 / 3) return p2 + (q2 - p2) * (2 / 3 - tt) * 6;
|
|
4039
|
+
return p2;
|
|
4040
|
+
};
|
|
4041
|
+
const q = lig < 0.5 ? lig * (1 + sat) : lig + sat - lig * sat;
|
|
4042
|
+
const p = 2 * lig - q;
|
|
4043
|
+
return rgbToHex(
|
|
4044
|
+
Math.round(hue2rgb(p, q, hue + 1 / 3) * 255),
|
|
4045
|
+
Math.round(hue2rgb(p, q, hue) * 255),
|
|
4046
|
+
Math.round(hue2rgb(p, q, hue - 1 / 3) * 255)
|
|
4047
|
+
);
|
|
4048
|
+
}
|
|
4049
|
+
function mix(color1, color2, weight = 0.5) {
|
|
4050
|
+
const rgb1 = hexToRgb(color1);
|
|
4051
|
+
const rgb2 = hexToRgb(color2);
|
|
4052
|
+
if (!rgb1 || !rgb2) return color1;
|
|
4053
|
+
const w = Math.max(0, Math.min(1, weight));
|
|
4054
|
+
const lerp2 = (a, b) => Math.floor(a + (b - a) * w);
|
|
4055
|
+
return rgbToHex(lerp2(rgb1.r, rgb2.r), lerp2(rgb1.g, rgb2.g), lerp2(rgb1.b, rgb2.b));
|
|
4056
|
+
}
|
|
4057
|
+
function randomColor() {
|
|
4058
|
+
const r = Math.floor(Math.random() * 256);
|
|
4059
|
+
const g = Math.floor(Math.random() * 256);
|
|
4060
|
+
const b = Math.floor(Math.random() * 256);
|
|
4061
|
+
return rgbToHex(r, g, b);
|
|
4062
|
+
}
|
|
4063
|
+
function isLight(hex) {
|
|
4064
|
+
const rgb = hexToRgb(hex);
|
|
4065
|
+
if (!rgb) return false;
|
|
4066
|
+
return (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255 > 0.5;
|
|
4067
|
+
}
|
|
4068
|
+
function isDark(hex) {
|
|
4069
|
+
return !isLight(hex);
|
|
4070
|
+
}
|
|
4071
|
+
function complementary(hex) {
|
|
4072
|
+
const hsl = hexToHsl(hex);
|
|
4073
|
+
if (!hsl) return hex;
|
|
4074
|
+
return hslToHex((hsl.h + 180) % 360, hsl.s, hsl.l);
|
|
4075
|
+
}
|
|
4076
|
+
function alpha(hex, opacity) {
|
|
4077
|
+
const rgb = hexToRgb(hex);
|
|
4078
|
+
if (!rgb) return hex;
|
|
4079
|
+
const a = Math.max(0, Math.min(1, opacity));
|
|
4080
|
+
const alphaHex = Math.round(a * 255).toString(16).padStart(2, "0");
|
|
4081
|
+
return rgbToHex(rgb.r, rgb.g, rgb.b) + alphaHex;
|
|
4082
|
+
}
|
|
2548
4083
|
export {
|
|
2549
4084
|
DivisionByZeroError,
|
|
2550
4085
|
InvalidDateError,
|
|
@@ -2552,6 +4087,13 @@ export {
|
|
|
2552
4087
|
KNOWN_MAPPINGS,
|
|
2553
4088
|
Logger,
|
|
2554
4089
|
MultiError,
|
|
4090
|
+
Mutex,
|
|
4091
|
+
Queue,
|
|
4092
|
+
RateLimiter,
|
|
4093
|
+
Semaphore,
|
|
4094
|
+
TIMEZONE_WIB,
|
|
4095
|
+
TIMEZONE_WIT,
|
|
4096
|
+
TIMEZONE_WITA,
|
|
2555
4097
|
TypedError,
|
|
2556
4098
|
add,
|
|
2557
4099
|
addBusinessDays,
|
|
@@ -2559,6 +4101,7 @@ export {
|
|
|
2559
4101
|
addMonths,
|
|
2560
4102
|
addYears,
|
|
2561
4103
|
allSettledMap,
|
|
4104
|
+
alpha,
|
|
2562
4105
|
analyzeUsage,
|
|
2563
4106
|
approxEqual,
|
|
2564
4107
|
assertDefined,
|
|
@@ -2567,18 +4110,26 @@ export {
|
|
|
2567
4110
|
base64Decode,
|
|
2568
4111
|
base64Encode,
|
|
2569
4112
|
basename,
|
|
4113
|
+
batch,
|
|
2570
4114
|
calculateAge,
|
|
2571
4115
|
camelCase,
|
|
2572
4116
|
capitalize,
|
|
2573
4117
|
castArray,
|
|
2574
4118
|
ceil,
|
|
4119
|
+
charCount,
|
|
2575
4120
|
checksum,
|
|
2576
4121
|
chunk,
|
|
2577
4122
|
clamp,
|
|
2578
4123
|
collectErrors,
|
|
4124
|
+
combinations,
|
|
4125
|
+
compact,
|
|
4126
|
+
complementary,
|
|
4127
|
+
compose,
|
|
2579
4128
|
consoleTransport,
|
|
2580
4129
|
constantTimeEqual,
|
|
2581
4130
|
contrastRatio,
|
|
4131
|
+
correlation,
|
|
4132
|
+
countBy,
|
|
2582
4133
|
countOccurrences,
|
|
2583
4134
|
createBufferedTransport,
|
|
2584
4135
|
createConsoleTransport,
|
|
@@ -2587,12 +4138,21 @@ export {
|
|
|
2587
4138
|
createJsonTransport,
|
|
2588
4139
|
darken,
|
|
2589
4140
|
dateDiff,
|
|
4141
|
+
dayOfYear,
|
|
4142
|
+
daysInMonth,
|
|
2590
4143
|
debounce,
|
|
4144
|
+
dedent,
|
|
2591
4145
|
deepClone,
|
|
4146
|
+
deepEqual,
|
|
4147
|
+
deepGet,
|
|
2592
4148
|
deepMerge,
|
|
4149
|
+
deepSet,
|
|
2593
4150
|
deferred,
|
|
4151
|
+
difference,
|
|
2594
4152
|
dirname,
|
|
2595
4153
|
div,
|
|
4154
|
+
drop,
|
|
4155
|
+
dropRight,
|
|
2596
4156
|
endOfDay,
|
|
2597
4157
|
endOfMonth,
|
|
2598
4158
|
endOfYear,
|
|
@@ -2602,63 +4162,125 @@ export {
|
|
|
2602
4162
|
envInt,
|
|
2603
4163
|
escapeHtml,
|
|
2604
4164
|
extname,
|
|
4165
|
+
factorial,
|
|
4166
|
+
findIndex,
|
|
4167
|
+
findLast,
|
|
2605
4168
|
first,
|
|
2606
4169
|
flatten,
|
|
2607
4170
|
floor,
|
|
2608
4171
|
format,
|
|
4172
|
+
formatBytes,
|
|
4173
|
+
formatCurrency,
|
|
2609
4174
|
formatDate,
|
|
4175
|
+
formatDuration,
|
|
4176
|
+
formatInTimezone,
|
|
4177
|
+
formatRupiah,
|
|
4178
|
+
fuzzyMatch,
|
|
4179
|
+
gcd,
|
|
2610
4180
|
generateOTP,
|
|
2611
4181
|
generateReport,
|
|
2612
4182
|
generateToken,
|
|
4183
|
+
geometricMean,
|
|
4184
|
+
getIndonesianHolidayNames,
|
|
2613
4185
|
getType2 as getType,
|
|
2614
4186
|
groupBy,
|
|
2615
4187
|
hash,
|
|
4188
|
+
hexToHsl,
|
|
2616
4189
|
hexToRgb,
|
|
4190
|
+
hslToHex,
|
|
2617
4191
|
identity,
|
|
2618
4192
|
inRange,
|
|
4193
|
+
intersection,
|
|
2619
4194
|
isAbsolute,
|
|
2620
4195
|
isAfter,
|
|
4196
|
+
isAnagram,
|
|
2621
4197
|
isArray,
|
|
2622
4198
|
isBefore,
|
|
2623
4199
|
isBetween,
|
|
2624
4200
|
isBoolean,
|
|
2625
4201
|
isBusinessDay,
|
|
4202
|
+
isDark,
|
|
2626
4203
|
isDate,
|
|
2627
4204
|
isEmail,
|
|
2628
4205
|
isEmpty,
|
|
4206
|
+
isEven,
|
|
2629
4207
|
isFunction,
|
|
4208
|
+
isFuture,
|
|
4209
|
+
isHolidayIndonesia,
|
|
2630
4210
|
isKodepos,
|
|
2631
4211
|
isLeapYear,
|
|
4212
|
+
isLight,
|
|
2632
4213
|
isMap,
|
|
2633
4214
|
isNIK,
|
|
2634
4215
|
isNPWP,
|
|
2635
4216
|
isNil,
|
|
4217
|
+
isNoBPJS,
|
|
4218
|
+
isNoKK,
|
|
2636
4219
|
isNoRekening,
|
|
4220
|
+
isNoSIM,
|
|
2637
4221
|
isNull,
|
|
2638
4222
|
isNumber,
|
|
2639
4223
|
isObject,
|
|
4224
|
+
isOdd,
|
|
4225
|
+
isPalindrome,
|
|
4226
|
+
isPassport,
|
|
4227
|
+
isPast,
|
|
2640
4228
|
isPhone,
|
|
2641
4229
|
isPlatNomor,
|
|
4230
|
+
isPrime,
|
|
2642
4231
|
isPromise,
|
|
2643
4232
|
isRegExp,
|
|
4233
|
+
isSameDay,
|
|
2644
4234
|
isSet,
|
|
2645
4235
|
isString,
|
|
4236
|
+
isToday,
|
|
4237
|
+
isTomorrow,
|
|
2646
4238
|
isTypedError,
|
|
2647
4239
|
isURL,
|
|
2648
4240
|
isUndefined,
|
|
4241
|
+
isValidHex,
|
|
2649
4242
|
isWeekend,
|
|
4243
|
+
isYesterday,
|
|
2650
4244
|
join,
|
|
2651
4245
|
kebabCase,
|
|
2652
4246
|
keyBy,
|
|
2653
4247
|
last,
|
|
4248
|
+
lastFriday,
|
|
4249
|
+
lastMonday,
|
|
4250
|
+
lastSaturday,
|
|
4251
|
+
lastSunday,
|
|
4252
|
+
lastThursday,
|
|
4253
|
+
lastTuesday,
|
|
4254
|
+
lastWednesday,
|
|
4255
|
+
lcm,
|
|
4256
|
+
lerp,
|
|
4257
|
+
levenshtein,
|
|
2654
4258
|
lighten,
|
|
2655
4259
|
logger,
|
|
4260
|
+
mapRange,
|
|
4261
|
+
maskString,
|
|
4262
|
+
maxBy,
|
|
4263
|
+
maxDate,
|
|
4264
|
+
median,
|
|
2656
4265
|
meetsWCAG,
|
|
2657
4266
|
memoize,
|
|
4267
|
+
memoizeAsync,
|
|
4268
|
+
minBy,
|
|
4269
|
+
minDate,
|
|
4270
|
+
mix,
|
|
4271
|
+
mode,
|
|
2658
4272
|
mul,
|
|
2659
4273
|
nanoid,
|
|
4274
|
+
nextFriday,
|
|
4275
|
+
nextMonday,
|
|
4276
|
+
nextSaturday,
|
|
4277
|
+
nextSunday,
|
|
4278
|
+
nextThursday,
|
|
4279
|
+
nextTuesday,
|
|
4280
|
+
nextWednesday,
|
|
2660
4281
|
noop,
|
|
2661
4282
|
normalize,
|
|
4283
|
+
nth,
|
|
2662
4284
|
omit,
|
|
2663
4285
|
once,
|
|
2664
4286
|
orderBy,
|
|
@@ -2669,14 +4291,26 @@ export {
|
|
|
2669
4291
|
parse,
|
|
2670
4292
|
parseCsv,
|
|
2671
4293
|
parseDate,
|
|
4294
|
+
parseDuration,
|
|
2672
4295
|
parseNIK,
|
|
4296
|
+
partition,
|
|
2673
4297
|
pascalCase,
|
|
4298
|
+
percentageOf,
|
|
4299
|
+
percentile,
|
|
4300
|
+
permutations,
|
|
2674
4301
|
pick,
|
|
4302
|
+
pipe,
|
|
2675
4303
|
pipeline,
|
|
2676
4304
|
pluck,
|
|
4305
|
+
pluralize,
|
|
4306
|
+
quarter,
|
|
2677
4307
|
raceWithTimeout,
|
|
4308
|
+
randomBoolean,
|
|
4309
|
+
randomColor,
|
|
2678
4310
|
randomHex,
|
|
2679
4311
|
randomInt,
|
|
4312
|
+
randomString,
|
|
4313
|
+
range,
|
|
2680
4314
|
relative,
|
|
2681
4315
|
resolve,
|
|
2682
4316
|
retry,
|
|
@@ -2687,31 +4321,58 @@ export {
|
|
|
2687
4321
|
safeJsonParse,
|
|
2688
4322
|
sample,
|
|
2689
4323
|
sampleSize,
|
|
4324
|
+
sampleStddev,
|
|
2690
4325
|
scanProject,
|
|
2691
4326
|
shuffle,
|
|
4327
|
+
similarity,
|
|
2692
4328
|
simpleHash,
|
|
2693
4329
|
sleep,
|
|
4330
|
+
slidingWindows,
|
|
2694
4331
|
slugify,
|
|
2695
4332
|
snakeCase,
|
|
2696
4333
|
sortBy,
|
|
2697
4334
|
startOfDay,
|
|
2698
4335
|
startOfMonth,
|
|
2699
4336
|
startOfYear,
|
|
4337
|
+
stddev,
|
|
2700
4338
|
stringifyCsv,
|
|
4339
|
+
stripHtml,
|
|
2701
4340
|
sub,
|
|
2702
4341
|
sum,
|
|
4342
|
+
sumBy,
|
|
4343
|
+
swapCase,
|
|
4344
|
+
take,
|
|
4345
|
+
takeRight,
|
|
2703
4346
|
template,
|
|
4347
|
+
terbilang,
|
|
2704
4348
|
throttle,
|
|
4349
|
+
timeAgo,
|
|
4350
|
+
timeRemaining,
|
|
2705
4351
|
timeout,
|
|
4352
|
+
toCobolCase,
|
|
4353
|
+
toDegrees,
|
|
4354
|
+
toRadians,
|
|
4355
|
+
toTimezone,
|
|
4356
|
+
topoSort,
|
|
2706
4357
|
trim,
|
|
2707
4358
|
trimEnd,
|
|
2708
4359
|
trimStart,
|
|
2709
4360
|
truncate,
|
|
4361
|
+
truncateWords,
|
|
4362
|
+
tumblingWindows,
|
|
2710
4363
|
unescapeHtml,
|
|
4364
|
+
union,
|
|
2711
4365
|
uniq,
|
|
2712
4366
|
uniqueBy,
|
|
4367
|
+
unzip,
|
|
2713
4368
|
uuid,
|
|
4369
|
+
waterfall,
|
|
4370
|
+
weekOfYear,
|
|
4371
|
+
weightedAverage,
|
|
4372
|
+
without,
|
|
4373
|
+
wordCount,
|
|
2714
4374
|
words,
|
|
2715
|
-
xorCipher
|
|
4375
|
+
xorCipher,
|
|
4376
|
+
zip
|
|
2716
4377
|
};
|
|
2717
4378
|
//# sourceMappingURL=index.js.map
|