@creejs/commons-lang 2.1.19 → 2.1.21

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.
@@ -4,6 +4,104 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.CommonsLang = {}));
5
5
  })(this, (function (exports) { 'use strict';
6
6
 
7
+ class _Error extends Error {
8
+ /**
9
+ * Creates and returns a 404 Not Found error instance with the given message.
10
+ * @param {string} message - The error message to include.
11
+ * @returns {_Error} A new Error instance with status code 404.
12
+ */
13
+ static notFound (message) {
14
+ return new _Error(`Not Found: ${message}`, 404)
15
+ }
16
+
17
+ static notImpled () {
18
+ return new _Error('Not Impled Yet', 501)
19
+ }
20
+
21
+ /**
22
+ * Creates and returns a new Error instance for not supported operations.
23
+ * @param {string} message - The error message to include.
24
+ * @returns {_Error} A new Error instance with "Not Supported:" prefix and 505 status code.
25
+ */
26
+ static notSupported (message) {
27
+ return new _Error('Not Supported:' + message, 505)
28
+ }
29
+
30
+ /**
31
+ * Checks if the given error is a "Not Supported" error.
32
+ * @param {Error|_Error|{[key:string]:any}|unknown} err - The error to check
33
+ * @returns {boolean} True if the error is a Not Supported error (code 505), false otherwise
34
+ */
35
+ static isNotSupported (err) {
36
+ // @ts-ignore
37
+ return err?.code === 505
38
+ }
39
+
40
+ /**
41
+ * Error constructor with custom message and code.
42
+ * @param {string} message - Error message
43
+ * @param {number|string} code - Error code
44
+ */
45
+ constructor (message, code) {
46
+ super(message);
47
+ this.code = code;
48
+ }
49
+ }
50
+
51
+ class AggregatedError extends Error {
52
+ /**
53
+ * Checks if the given error is an AggregatedErrorLike
54
+ * 1. have "message:string" property
55
+ * 2. have "errors:Error[]" property
56
+ * @param {any} err - The error to check
57
+ * @returns {boolean} True if the error is an AggregatedError, false otherwise
58
+ */
59
+ static isAggregatedErrorLike (err) {
60
+ return err && Array.isArray(err.errors)
61
+ }
62
+
63
+ /**
64
+ * Checks if the given error is an instance of AggregatedError.
65
+ * @param {Error} err - The error to check.
66
+ * @returns {boolean} True if the error is an AggregatedError, false otherwise.
67
+ */
68
+ static isAggregatedError (err) {
69
+ return err instanceof AggregatedError
70
+ }
71
+
72
+ /**
73
+ * Error constructor with custom message and code.
74
+ * @param {string} message - Error message
75
+ * @param {any[]} [errors] - Errors
76
+ */
77
+ constructor (message, errors) {
78
+ super(message);
79
+ this.errors = errors ?? [];
80
+ }
81
+
82
+ /**
83
+ * Adds an error to the errors collection.
84
+ * @param {any} err - The error object to be added.
85
+ */
86
+ addError (err) {
87
+ this.errors.push(err);
88
+ }
89
+
90
+ /**
91
+ * Removes a specific error from the errors array.
92
+ * @param {Error} err - The error instance to remove.
93
+ * @returns {boolean} True if the error was found and removed, false otherwise.
94
+ */
95
+ removeError (err) {
96
+ const index = this.errors.indexOf(err);
97
+ if (index === -1) {
98
+ return false
99
+ }
100
+ this.errors.splice(index, 1);
101
+ return true
102
+ }
103
+ }
104
+
7
105
  /**
8
106
  * @module LangUtils
9
107
  * @description Language utility functions
@@ -618,7 +716,7 @@
618
716
  */
619
717
  function assertArray (value, paramName) {
620
718
  if (!Array.isArray(value)) {
621
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Array: type=${typeof value} value=${JSON.stringify(value)}`)
719
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Array: type=${typeof value} value=${safeToString(value)}`)
622
720
  }
623
721
  }
624
722
  /**
@@ -630,7 +728,7 @@
630
728
  */
631
729
  function assertString (value, paramName) {
632
730
  if (!isString(value)) {
633
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not String: type=${typeof value} value=${JSON.stringify(value)}`)
731
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not String: type=${typeof value} value=${safeToString(value)}`)
634
732
  }
635
733
  }
636
734
  /**
@@ -642,7 +740,7 @@
642
740
  */
643
741
  function assertNumber (value, paramName) {
644
742
  if (!isNumber(value)) {
645
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Number: type=${typeof value} value=${JSON.stringify(value)}`)
743
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Number: type=${typeof value} value=${safeToString(value)}`)
646
744
  }
647
745
  }
648
746
 
@@ -654,7 +752,7 @@
654
752
  */
655
753
  function assertPositive (value, paramName) {
656
754
  if (!isPositive(value)) {
657
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Positive: ${value}`)
755
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Positive: ${value}`)
658
756
  }
659
757
  }
660
758
 
@@ -666,7 +764,7 @@
666
764
  */
667
765
  function assertNegative (value, paramName) {
668
766
  if (!isNegative(value)) {
669
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Negative: ${value}`)
767
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Negative: ${value}`)
670
768
  }
671
769
  }
672
770
 
@@ -678,7 +776,7 @@
678
776
  */
679
777
  function assertNotNegative (value, paramName) {
680
778
  if (!isNotNegative(value)) {
681
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not "0 or Positive": ${value}`)
779
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not "0 or Positive": ${value}`)
682
780
  }
683
781
  }
684
782
 
@@ -691,7 +789,7 @@
691
789
  */
692
790
  function assertBoolean (value, paramName) {
693
791
  if (!isBoolean(value)) {
694
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Boolean: type=${typeof value} value=${JSON.stringify(value)}`)
792
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Boolean: type=${typeof value} value=${safeToString(value)}`)
695
793
  }
696
794
  }
697
795
  /**
@@ -703,7 +801,7 @@
703
801
  */
704
802
  function assertObject (value, paramName) {
705
803
  if (!isObject(value)) {
706
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Object: type=${typeof value} value=${JSON.stringify(value)}`)
804
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Object: type=${typeof value} value=${safeToString(value)}`)
707
805
  }
708
806
  }
709
807
  /**
@@ -715,7 +813,7 @@
715
813
  */
716
814
  function assertPlainObject (value, paramName) {
717
815
  if (!isPlainObject$1(value)) {
718
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not PlainObject: type=${typeof value} value=${JSON.stringify(value)}`)
816
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not PlainObject: type=${typeof value} value=${safeToString(value)}`)
719
817
  }
720
818
  }
721
819
  /**
@@ -727,7 +825,7 @@
727
825
  */
728
826
  function assertSymbol (value, paramName) {
729
827
  if (!isSymbol(value)) {
730
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Symbol: type=${typeof value} value=${JSON.stringify(value)}`)
828
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Symbol: type=${typeof value} value=${safeToString(value)}`)
731
829
  }
732
830
  }
733
831
  /**
@@ -739,7 +837,7 @@
739
837
  */
740
838
  function assertFunction (value, paramName) {
741
839
  if (!isFunction(value)) {
742
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Function: type=${typeof value} value=${JSON.stringify(value)}`)
840
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Function: type=${typeof value} value=${safeToString(value)}`)
743
841
  }
744
842
  }
745
843
  /**
@@ -751,7 +849,7 @@
751
849
  */
752
850
  function assertInstance (value, paramName) {
753
851
  if (!isInstance(value)) {
754
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Class Instance: type=${typeof value} value=${JSON.stringify(value)}`)
852
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Class Instance: type=${typeof value} value=${safeToString(value)}`)
755
853
  }
756
854
  }
757
855
  /**
@@ -763,7 +861,7 @@
763
861
  */
764
862
  function assertPromise (value, paramName) {
765
863
  if (!isPromise(value)) {
766
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Promise: type=${typeof value} value=${JSON.stringify(value)}`)
864
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Promise: type=${typeof value} value=${safeToString(value)}`)
767
865
  }
768
866
  }
769
867
  /**
@@ -775,7 +873,7 @@
775
873
  */
776
874
  function assertNil (value, paramName) {
777
875
  if (!isNil(value)) {
778
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Neither Null nor Undefined: type=${typeof value} value=${JSON.stringify(value)}`)
876
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Neither Null nor Undefined: type=${typeof value} value=${safeToString(value)}`)
779
877
  }
780
878
  }
781
879
 
@@ -787,7 +885,7 @@
787
885
  */
788
886
  function assertNotNil (value, paramName) {
789
887
  if (isNil(value)) {
790
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Should Not Nil`)
888
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Should Not Nil`)
791
889
  }
792
890
  }
793
891
 
@@ -800,7 +898,7 @@
800
898
  */
801
899
  function assertNull (value, paramName) {
802
900
  if (!isNull(value)) {
803
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Null: type=${typeof value} value=${JSON.stringify(value)}`)
901
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Null: type=${typeof value} value=${safeToString(value)}`)
804
902
  }
805
903
  }
806
904
 
@@ -812,7 +910,7 @@
812
910
  */
813
911
  function assertNotNull (value, paramName) {
814
912
  if (isNull(value)) {
815
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Should Not Null`)
913
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Should Not Null`)
816
914
  }
817
915
  }
818
916
  /**
@@ -824,7 +922,7 @@
824
922
  */
825
923
  function assertUndefined (value, paramName) {
826
924
  if (!isUndefined(value)) {
827
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Undefined: type=${typeof value} value=${JSON.stringify(value)}`)
925
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Undefined: type=${typeof value} value=${safeToString(value)}`)
828
926
  }
829
927
  }
830
928
 
@@ -836,7 +934,7 @@
836
934
  */
837
935
  function assertStringOrSymbol (value, paramName) {
838
936
  if (!isString(value) && !isSymbol(value)) {
839
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not String or Symbol: type=${typeof value} value=${JSON.stringify(value)}`)
937
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not String or Symbol: type=${typeof value} value=${safeToString(value)}`)
840
938
  }
841
939
  }
842
940
 
@@ -847,7 +945,7 @@
847
945
  */
848
946
  function assertTypedArray (value, paramName) {
849
947
  if (isTypedArray(value)) {
850
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not TypedArray`)
948
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not TypedArray`)
851
949
  }
852
950
  }
853
951
  /**
@@ -857,7 +955,7 @@
857
955
  */
858
956
  function assertInt8Array (value, paramName) {
859
957
  if (isInt8Array(value)) {
860
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Int8Array`)
958
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Int8Array`)
861
959
  }
862
960
  }
863
961
  /**
@@ -867,7 +965,7 @@
867
965
  */
868
966
  function assertUint8Array (value, paramName) {
869
967
  if (isUint8Array(value)) {
870
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Uint8Array`)
968
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Uint8Array`)
871
969
  }
872
970
  }
873
971
  /**
@@ -877,7 +975,7 @@
877
975
  */
878
976
  function assertUint8ClampedArray (value, paramName) {
879
977
  if (isUint8ClampedArray(value)) {
880
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Uint8ClampedArray`)
978
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Uint8ClampedArray`)
881
979
  }
882
980
  }
883
981
  /**
@@ -887,7 +985,7 @@
887
985
  */
888
986
  function assertInt16Array (value, paramName) {
889
987
  if (isInt16Array(value)) {
890
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Int16Array`)
988
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Int16Array`)
891
989
  }
892
990
  }
893
991
  /**
@@ -897,7 +995,7 @@
897
995
  */
898
996
  function assertUint16Array (value, paramName) {
899
997
  if (isUint16Array(value)) {
900
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Uint16Array`)
998
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Uint16Array`)
901
999
  }
902
1000
  }
903
1001
  /**
@@ -907,7 +1005,7 @@
907
1005
  */
908
1006
  function assertInt32Array (value, paramName) {
909
1007
  if (isInt32Array(value)) {
910
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Int32Array`)
1008
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Int32Array`)
911
1009
  }
912
1010
  }
913
1011
  /**
@@ -917,7 +1015,7 @@
917
1015
  */
918
1016
  function assertUint32Array (value, paramName) {
919
1017
  if (isUint32Array(value)) {
920
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Uint32Array`)
1018
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Uint32Array`)
921
1019
  }
922
1020
  }
923
1021
  /**
@@ -927,7 +1025,7 @@
927
1025
  */
928
1026
  function assertFloat32Array (value, paramName) {
929
1027
  if (isFloat32Array(value)) {
930
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Float32Array`)
1028
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Float32Array`)
931
1029
  }
932
1030
  }
933
1031
  /**
@@ -937,7 +1035,7 @@
937
1035
  */
938
1036
  function assertFloat64Array (value, paramName) {
939
1037
  if (isFloat64Array(value)) {
940
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not Float64Array`)
1038
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not Float64Array`)
941
1039
  }
942
1040
  }
943
1041
  /**
@@ -947,7 +1045,7 @@
947
1045
  */
948
1046
  function assertBigInt64Array (value, paramName) {
949
1047
  if (isBigInt64Array(value)) {
950
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not BigInt64Array`)
1048
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not BigInt64Array`)
951
1049
  }
952
1050
  }
953
1051
  /**
@@ -957,7 +1055,7 @@
957
1055
  */
958
1056
  function assertBigUint64Array (value, paramName) {
959
1057
  if (isBigUint64Array(value)) {
960
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not BigUint64Array`)
1058
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not BigUint64Array`)
961
1059
  }
962
1060
  }
963
1061
 
@@ -969,7 +1067,7 @@
969
1067
  */
970
1068
  function assertArrayBuffer (value, paramName) {
971
1069
  if (!isArrayBuffer(value)) {
972
- throw new Error(`${paramName ? '"' + paramName + '" ' : ' '}Not ArrayBuffer`)
1070
+ throw new Error(`${paramName ? '"' + paramName + '" ' : ''}Not ArrayBuffer`)
973
1071
  }
974
1072
  }
975
1073
 
@@ -998,7 +1096,8 @@
998
1096
  substringAfterLast,
999
1097
  substringBetween,
1000
1098
  substringBetweenGreedy,
1001
- substringsBetween
1099
+ substringsBetween,
1100
+ safeToString
1002
1101
  };
1003
1102
 
1004
1103
  /**
@@ -1395,6 +1494,22 @@
1395
1494
  return substrings
1396
1495
  }
1397
1496
 
1497
+ /**
1498
+ * Safely converts a value to its string representation.
1499
+ * Attempts to use JSON.stringify first, falls back to toString() if stringify fails.
1500
+ * @param {*} value - The value to convert to string
1501
+ * @returns {string} The string representation of the value
1502
+ */
1503
+ function safeToString (value) {
1504
+ let valueStr;
1505
+ try {
1506
+ valueStr = JSON.stringify(value);
1507
+ } catch (e) {
1508
+ valueStr = value.toString();
1509
+ }
1510
+ return valueStr
1511
+ }
1512
+
1398
1513
  /**
1399
1514
  * @module ExecUtils
1400
1515
  * @description Utils about how to execute task functions.
@@ -1472,6 +1587,7 @@
1472
1587
  * promise: Promise<*>,
1473
1588
  * timerHandler: NodeJS.Timeout,
1474
1589
  * timerCleared: boolean,
1590
+ * pending: boolean,
1475
1591
  * resolved: boolean,
1476
1592
  * rejected: boolean,
1477
1593
  * canceled: boolean,
@@ -1484,7 +1600,8 @@
1484
1600
  * @typedef {{
1485
1601
  * promise: Promise<*>,
1486
1602
  * timerHandler: NodeJS.Timeout,
1487
- * resolve: (...args:any[])=> void
1603
+ * _resolve: (...args:any[])=> void,
1604
+ * wakeup: ()=> void
1488
1605
  * }} Waiter
1489
1606
  */
1490
1607
 
@@ -1493,6 +1610,7 @@
1493
1610
  * @description Promise utility functions for enhanced promise handling, including timeout, delay, parallel execution, and series execution.
1494
1611
  */
1495
1612
  var PromiseUtils = {
1613
+ any,
1496
1614
  defer,
1497
1615
  delay,
1498
1616
  timeout,
@@ -1501,6 +1619,7 @@
1501
1619
  series,
1502
1620
  seriesAllSettled,
1503
1621
  parallel,
1622
+ parallelAny,
1504
1623
  parallelAllSettled,
1505
1624
  wait
1506
1625
  };
@@ -1516,48 +1635,66 @@
1516
1635
  assertNumber(timeout);
1517
1636
  /** @type {Deferred} */
1518
1637
  const rtnVal = {};
1519
-
1638
+ rtnVal.pending = true;
1639
+ rtnVal.canceled = false;
1640
+ rtnVal.rejected = false;
1641
+ rtnVal.resolved = false;
1520
1642
  /**
1521
1643
  * @type {NodeJS.Timeout}
1522
1644
  */
1523
1645
  let timerHandler;
1524
1646
  if (timeout >= 0) {
1647
+ rtnVal.timerCleared = false;
1525
1648
  rtnVal.timerHandler = timerHandler = setTimeout(() => {
1526
1649
  clearTimeout(timerHandler); // must clear it
1527
- rtnVal.timerCleared = true; // easy to check in test case
1650
+ rtnVal.timerCleared = true;
1528
1651
  rtnVal.reject(new Error(timeoutMessage ?? `Promise Timeout: ${timeout}ms`));
1529
1652
  }, timeout);
1530
1653
  }
1531
1654
 
1532
1655
  rtnVal.promise = new Promise((resolve, reject) => {
1533
1656
  rtnVal.resolve = (arg) => {
1657
+ if (rtnVal.resolved || rtnVal.rejected || rtnVal.canceled) {
1658
+ return // already done, Can Not operate again
1659
+ }
1534
1660
  if (timerHandler != null) {
1535
1661
  clearTimeout(timerHandler); // must clear it
1536
- rtnVal.timerCleared = true; // easy to check in test case
1662
+ rtnVal.timerCleared = true;
1537
1663
  }
1664
+ rtnVal.pending = false;
1665
+ rtnVal.canceled = false;
1666
+ rtnVal.rejected = false;
1538
1667
  rtnVal.resolved = true;
1539
1668
  resolve(arg);
1540
1669
  };
1541
1670
 
1542
1671
  rtnVal.reject = (err) => {
1672
+ if (rtnVal.resolved || rtnVal.rejected || rtnVal.canceled) {
1673
+ return // already done, Can Not operate again
1674
+ }
1543
1675
  if (timerHandler != null) {
1544
1676
  clearTimeout(timerHandler); // must clear it
1545
- rtnVal.timerCleared = true; // easy to check in test case
1677
+ rtnVal.timerCleared = true;
1546
1678
  }
1679
+ rtnVal.pending = false;
1680
+ rtnVal.canceled = false;
1681
+ rtnVal.resolved = false;
1547
1682
  rtnVal.rejected = true;
1548
1683
  reject(err);
1549
1684
  };
1550
1685
  });
1551
1686
  // @ts-ignore
1552
- rtnVal.promise.cancel = () => {
1687
+ rtnVal.cancel = rtnVal.promise.cancel = (reason) => {
1688
+ if (rtnVal.resolved || rtnVal.rejected || rtnVal.canceled) {
1689
+ return // already done, Can Not operate again
1690
+ }
1553
1691
  if (timerHandler != null) {
1554
1692
  clearTimeout(timerHandler); // must clear it
1555
- rtnVal.timerCleared = true; // easy to check in test case
1693
+ rtnVal.timerCleared = true;
1556
1694
  }
1557
- rtnVal.rejected = true; // easy to check in test case
1695
+ rtnVal.reject(reason ?? new Error('Cancelled'));
1558
1696
  // @ts-ignore
1559
- rtnVal.canceled = rtnVal.promise.canceled = true; // easy to check in test case
1560
- rtnVal.reject(new Error('Cancelled'));
1697
+ rtnVal.canceled = rtnVal.promise.canceled = true;
1561
1698
  };
1562
1699
  return rtnVal
1563
1700
  }
@@ -1628,7 +1765,7 @@
1628
1765
  function returnValuePromised (task) {
1629
1766
  try {
1630
1767
  const taskRtnVal = task();
1631
- if (isPromise(taskRtnVal)) {
1768
+ if (TypeUtils.isPromise(taskRtnVal)) {
1632
1769
  return taskRtnVal
1633
1770
  }
1634
1771
  return Promise.resolve(taskRtnVal)
@@ -1649,7 +1786,7 @@
1649
1786
  * @returns {Promise<*>} A new promise that settles after the delay period
1650
1787
  */
1651
1788
  function delay (promise, ms) {
1652
- if (isNumber(promise)) { // defer(ms)
1789
+ if (TypeUtils.isNumber(promise)) { // defer(ms)
1653
1790
  // @ts-ignore
1654
1791
  ms = promise;
1655
1792
  promise = Promise.resolve();
@@ -1681,21 +1818,78 @@
1681
1818
  });
1682
1819
  return deferred.promise
1683
1820
  }
1821
+ /**
1822
+ * 1. run all tasks
1823
+ * 2. any Task succeed, return its result
1824
+ * * resolve with the result.
1825
+ * * the others tasks will run to its end, and results will be dropped.
1826
+ * 3. If all tasks fail, rejects with an array of errors. the array length is same as the input tasks
1827
+ * @param {Array<Promise<any>|Function>} tasks - Array of promises or async functions to execute
1828
+ * @returns {Promise<any>} A promise that resolves with the result of the first successful task
1829
+ */
1830
+ function any (tasks) {
1831
+ assertArray(tasks);
1832
+ if (tasks.length === 0) {
1833
+ throw new Error('Empty Tasks')
1834
+ }
1835
+ const deferred = defer();
1836
+ /** @type {any[]} */
1837
+ const errors = [];
1838
+ for (let i = 0; i < tasks.length; i++) {
1839
+ const task = tasks[i];
1840
+ /** @type {Promise<any>} */
1841
+ let taskPromise;
1842
+ if (TypeUtils.isPromise(task)) {
1843
+ // @ts-ignore
1844
+ taskPromise = task;
1845
+ } else if (TypeUtils.isFunction(task)) {
1846
+ // @ts-ignore
1847
+ taskPromise = returnValuePromised(task);
1848
+ } else {
1849
+ errors.push(new Error(`Invalid Task at index ${i}/${tasks.length - 1}: ${task}`));
1850
+ continue
1851
+ }
1852
+ taskPromise.then(/** @type {any} */ rtnVal => {
1853
+ deferred.resolve(rtnVal);
1854
+ }).catch(e => {
1855
+ errors.push(e);
1856
+ // all tasks failed
1857
+ if (errors.length >= tasks.length) {
1858
+ deferred.reject(errors);
1859
+ }
1860
+ });
1861
+ }
1862
+ if (errors.length === tasks.length) {
1863
+ deferred.reject(errors);
1864
+ }
1865
+ return deferred.promise
1866
+ }
1684
1867
 
1685
1868
  /**
1686
- * Fast-Fail mode to execute Tasks(functions) in series (one after another) and returns their results in order.
1687
- * 1. export function are executed one by one
1688
- * 2. Fast Fail: if any tasks fail, the whole chain is rejected with the first error
1689
- * 3. if an element is not function, rejects the whole chain with Error(Not Function)
1690
- * @param {Function[]} tasks
1691
- * @returns {Promise<any[]>} Promise that resolves with an array of results in the same order as input tasks
1692
- */
1869
+ * Execute Tasks(functions) in series (one after another) and returns their results in order.
1870
+ * 1. Tasks are executed one by one
1871
+ * * if task is a function, execute it.
1872
+ * * if task is a promise, wait for it to settle.
1873
+ * 2. Fast Fail: if any tasks fail, the whole chain is rejected with the first error
1874
+ * 3. if an element is not function, rejects the whole chain with Error(Not Function)
1875
+ * 4. All Tasks run successfully, Return Results Array, it's length is same as the input tasks
1876
+ * @param {Array<Promise<any>|Function>} tasks
1877
+ * @returns {Promise<any[]>} Promise that resolves with an array of results in the same order as input tasks
1878
+ */
1693
1879
  async function series (tasks) {
1694
1880
  assertArray(tasks);
1695
1881
  const results = [];
1696
1882
  for (const task of tasks) {
1697
1883
  assertFunction(task);
1698
- results.push(await task());
1884
+ if (TypeUtils.isFunction(task)) {
1885
+ // @ts-ignore
1886
+ results.push(await returnValuePromised(task));
1887
+ } else if (TypeUtils.isPromise(task)) {
1888
+ // @ts-ignore
1889
+ results.push(await task);
1890
+ } else {
1891
+ throw new Error(`Invalid Task: ${task}`)
1892
+ }
1699
1893
  }
1700
1894
  return results
1701
1895
  }
@@ -1770,7 +1964,7 @@
1770
1964
  * 2. all tasks will be executed, even some of them failed.
1771
1965
  * @param {Function[]} tasks
1772
1966
  * @param {number} [maxParallel=5] - Maximum number of tasks to run in parallel
1773
- * @returns {Promise<any[]>} Array of resolved values from all promises
1967
+ * @returns {Promise<{ok: boolean, result: any}[]>}
1774
1968
  * @throws {TypeError} If input is not an array of export function or maxParallel is not a number
1775
1969
  */
1776
1970
  async function parallelAllSettled (tasks, maxParallel = 5) {
@@ -1790,7 +1984,6 @@
1790
1984
  // run group by MaxParallel
1791
1985
  const tasksToRun = [];
1792
1986
  for (const task of tasks) {
1793
- assertFunction(task);
1794
1987
  tasksToRun.push(task);
1795
1988
  if (tasksToRun.length >= maxParallel) {
1796
1989
  const resultsForBatch = await allSettled(tasksToRun.map(task => returnValuePromised(task)));
@@ -1806,6 +1999,76 @@
1806
1999
  return rtnVal
1807
2000
  }
1808
2001
 
2002
+ /**
2003
+ * Executes multiple async tasks in parallel with limited concurrency,
2004
+ * 1. resolving when any task completes successfully.
2005
+ * 2. Maybe multiple tasks are executed as a bulk block, and all of them resolved.
2006
+ * * only the first fulfilled value is returned
2007
+ * * other results are dropped
2008
+ * @param {Array<Function|Promise<any>>} tasks - Array of async functions to execute
2009
+ * @param {number} [maxParallel=5] - Maximum number of tasks to run in parallel
2010
+ * @returns {Promise<any>} Resolves with the result of the first successfully completed task
2011
+ */
2012
+ async function parallelAny (tasks, maxParallel = 5) {
2013
+ assertArray(tasks, 'tasks');
2014
+ assertNumber(maxParallel);
2015
+ if (tasks.length === 0) {
2016
+ throw new Error('Empty Tasks')
2017
+ }
2018
+ if (maxParallel <= 0) {
2019
+ throw new Error(`Invalid maxParallel: ${maxParallel}, should > 0`)
2020
+ }
2021
+ /** @type {any[]} */
2022
+ const errors = [];
2023
+ let taskIndex = 0;
2024
+ let runningTasksCount = 0;
2025
+ const deferred = defer();
2026
+ function takeTaskAndRun () {
2027
+ if (taskIndex >= tasks.length) {
2028
+ return // no more task
2029
+ }
2030
+ // reach max parallel, wait for one task to finish
2031
+ if (runningTasksCount > maxParallel) {
2032
+ return
2033
+ }
2034
+ const task = tasks[taskIndex++];
2035
+ runningTasksCount++;
2036
+ /** @type {Promise<any>} */
2037
+ let taskPromise;
2038
+ if (TypeUtils.isPromise(task)) {
2039
+ // @ts-ignore
2040
+ taskPromise = task;
2041
+ } else if (TypeUtils.isFunction(task)) {
2042
+ // @ts-ignore
2043
+ taskPromise = returnValuePromised(task);
2044
+ } else {
2045
+ errors.push(new TypeError(`Invalid task: ${task}`));
2046
+ takeTaskAndRun();
2047
+ return
2048
+ }
2049
+ taskPromise.then(/** @type {any} */ rtnVal => {
2050
+ deferred.resolve(rtnVal);
2051
+ }).catch(e => {
2052
+ errors.push(e);
2053
+ // No task left, and No successful execution, reject with errors
2054
+ if (errors.length >= tasks.length) {
2055
+ if (deferred.pending) {
2056
+ deferred.reject(errors);
2057
+ return
2058
+ }
2059
+ }
2060
+ takeTaskAndRun();
2061
+ }).finally(() => {
2062
+ runningTasksCount--;
2063
+ });
2064
+ }
2065
+ // start tasks until maxParallel
2066
+ while (runningTasksCount < maxParallel) {
2067
+ takeTaskAndRun();
2068
+ }
2069
+ return deferred.promise
2070
+ }
2071
+
1809
2072
  /**
1810
2073
  * Creates a "Waiter" Object
1811
2074
  * 1. wait the specified time
@@ -1824,17 +2087,20 @@
1824
2087
  let timerHandler;
1825
2088
  rtnVal.timerHandler = timerHandler = setTimeout(() => {
1826
2089
  clearTimeout(timerHandler); // must clear it
1827
- rtnVal.resolve();
2090
+ rtnVal._resolve();
1828
2091
  }, waitTime);
1829
2092
 
1830
2093
  rtnVal.promise = new Promise((resolve, reject) => {
1831
- rtnVal.resolve = (arg) => {
2094
+ rtnVal._resolve = (arg) => {
1832
2095
  if (timerHandler != null) {
1833
2096
  clearTimeout(timerHandler); // must clear it
1834
2097
  }
1835
2098
  resolve(arg);
1836
2099
  };
1837
2100
  });
2101
+ rtnVal.wakeup = () => {
2102
+ rtnVal._resolve();
2103
+ };
1838
2104
  return rtnVal
1839
2105
  }
1840
2106
 
@@ -2295,6 +2561,7 @@
2295
2561
 
2296
2562
  var ArrayUtils = {
2297
2563
  first,
2564
+ chunk,
2298
2565
  last,
2299
2566
  equals,
2300
2567
  equalsIgnoreOrder
@@ -2378,13 +2645,35 @@
2378
2645
  return true
2379
2646
  }
2380
2647
 
2648
+ /**
2649
+ * Splits an array into chunks of the specified size.
2650
+ * @param {any[]} array - The array to be chunked.
2651
+ * @param {number} size - The size of each chunk.
2652
+ * @returns {any[]} An array of arrays containing the chunks.
2653
+ */
2654
+ function chunk (array, size) {
2655
+ assertArray(array, 'array');
2656
+ assertPositive(size, 'size');
2657
+ if (array.length <= size) {
2658
+ return array
2659
+ }
2660
+ const chunked = [];
2661
+ let index = 0;
2662
+ while (index < array.length) {
2663
+ chunked.push(array.slice(index, size + index));
2664
+ index += size;
2665
+ }
2666
+ return chunked
2667
+ }
2668
+
2381
2669
  /**
2382
2670
  * @module Lang
2383
2671
  * @description Core language utilities for type checking, string manipulation, and common operations.
2384
2672
  */
2385
2673
 
2386
-
2387
2674
  var index = {
2675
+ _Error,
2676
+ AggregatedError,
2388
2677
  LangUtils,
2389
2678
  StringUtils,
2390
2679
  TypeUtils,
@@ -2403,6 +2692,7 @@
2403
2692
  ArrayUtils
2404
2693
  };
2405
2694
 
2695
+ exports.AggregatedError = AggregatedError;
2406
2696
  exports.ArrayBufferUtils = ArrayBufferUtils;
2407
2697
  exports.ArrayUtils = ArrayUtils;
2408
2698
  exports.ClassProxyUtils = ClassProxyUtils;
@@ -2419,6 +2709,7 @@
2419
2709
  exports.TypeAssert = TypeAssert;
2420
2710
  exports.TypeUtils = TypeUtils;
2421
2711
  exports.TypedArrayUtils = TypedArrayUtils;
2712
+ exports._Error = _Error;
2422
2713
  exports.default = index;
2423
2714
 
2424
2715
  Object.defineProperty(exports, '__esModule', { value: true });