foreslash 0.3.0 → 0.3.2

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/lib/index.d.ts CHANGED
@@ -1,5 +1,61 @@
1
1
  import { A, F } from 'ts-toolbelt';
2
2
 
3
+ /**
4
+ * 将多个数组或类数组对象以笛卡尔积的形式拼接为一个新的二维数组
5
+ * @returns 笛卡尔积
6
+ * @example
7
+ * ```js
8
+ * cartesianProduct([1, 2, 3, 4, 5]) // [[1], [2], [3], [4], [5]]
9
+ * cartesianProduct([1, 2], '12') // [[1, '1'], [1, '2'], [2, '1'], [2, '2']]
10
+ * cartesianProduct([1, 2], '12', [3, 4])
11
+ * // [[1, '1', 3], [1, '1', 4], [1, '2', 3], [1, '2', 4]
12
+ * // [2, '1', 3], [2, '1', 4], [2, '2', 3], [2, '2', 4]]
13
+ * cartesianProduct([1, 2, 3, 4, 5], '12345', []) // [] 空集与其他集合的笛卡尔积是空集
14
+ * ```
15
+ * @version 0.3.2
16
+ */
17
+ declare function cartesianProduct<T>(arr1: ArrayLike<T>): [T][];
18
+ declare function cartesianProduct<T1, T2>(arr1: ArrayLike<T1>, arr2: ArrayLike<T2>): [T1, T2][];
19
+ declare function cartesianProduct<T1, T2, T3>(arr1: ArrayLike<T1>, arr2: ArrayLike<T2>, arr3: ArrayLike<T3>): [T1, T2, T3][];
20
+ declare function cartesianProduct<T1, T2, T3, T4>(arr1: ArrayLike<T1>, arr2: ArrayLike<T2>, arr3: ArrayLike<T3>, arr4: ArrayLike<T4>): [T1, T2, T3, T4][];
21
+ declare function cartesianProduct<T1, T2, T3, T4, T5>(arr1: ArrayLike<T1>, arr2: ArrayLike<T2>, arr3: ArrayLike<T3>, arr4: ArrayLike<T4>, arr5: ArrayLike<T5>): [T1, T2, T3, T4, T5][];
22
+ declare function cartesianProduct<T1, T2, T3, T4, T5, T6>(arr1: ArrayLike<T1>, arr2: ArrayLike<T2>, arr3: ArrayLike<T3>, arr4: ArrayLike<T4>, arr5: ArrayLike<T5>, arr6: ArrayLike<T6>): [T1, T2, T3, T4, T5, T6][];
23
+ declare function cartesianProduct<T1, T2, T3, T4, T5, T6, T7>(arr1: ArrayLike<T1>, arr2: ArrayLike<T2>, arr3: ArrayLike<T3>, arr4: ArrayLike<T4>, arr5: ArrayLike<T5>, arr6: ArrayLike<T6>, arr7: ArrayLike<T7>): [T1, T2, T3, T4, T5, T6, T7][];
24
+ declare function cartesianProduct<T1, T2, T3, T4, T5, T6, T7, T8>(arr1: ArrayLike<T1>, arr2: ArrayLike<T2>, arr3: ArrayLike<T3>, arr4: ArrayLike<T4>, arr5: ArrayLike<T5>, arr6: ArrayLike<T6>, arr7: ArrayLike<T7>, arr8: ArrayLike<T8>): [T1, T2, T3, T4, T5, T6, T7, T8][];
25
+ declare function cartesianProduct(...arrList: ArrayLike<any>[]): any[][];
26
+
27
+ type Not<T> = T extends false | 0 | '' | null | undefined ? true : false;
28
+
29
+ type Stringify<T extends string | number | boolean | bigint | null | undefined> = `${T}`;
30
+
31
+ /** 检查输入的数字是否为 `0` 或 `0n` */
32
+ type IsZero<T> = T extends 0 | 0n ? true : false;
33
+ /** 检查输入的数字是否为负数 */
34
+ type IsNegative<T> = T extends number | bigint ? (Stringify<T> extends `-${infer R}` ? true : false) : false;
35
+ /** 检查输入的数字是否为正数 */
36
+ type IsPositive<T> = T extends number | bigint ? (IsZero<T> extends true ? false : Not<IsNegative<T>>) : false;
37
+
38
+ /**
39
+ * 将一个数组或类数组对象分割成多个指定大小的小块\
40
+ * 类似 Lodash 的 `chunk` 或是 Radash 的 `cluster`\
41
+ * 可以填入 `size` 以自定义每个小块的大小
42
+ * @param array 需要分块的数组
43
+ * @param size 每块大小, 不能小于 1, 默认为 `2`
44
+ * @returns 分块后的数组
45
+ * @example
46
+ * ```js
47
+ * chunk([1, 2, 3, 4, 5], 2) // [[1, 2], [3, 4], [5]]
48
+ * chunk('12345', 3) // [['1', '2', '3'], ['4', '5']]
49
+ * chunk({0: 1, 1: 2, 2: 3, length: 3}, 2) // [[1, 2], [3]]
50
+ * // 如果传入了不正常的 size 则返回空数组(类型为 `never[]`)
51
+ * chunk([1, 2, 3, 4, 5], 0) // []
52
+ * chunk([1, 2, 3, 4, 5], NaN) // []
53
+ * ```
54
+ * @version 0.3.2
55
+ */
56
+ declare function chunk<T, Size extends number = 2>(array: ArrayLike<T>, size?: Size): Chunked<T, Size>;
57
+ type Chunked<T, Size extends number> = Size extends 1 ? [T][] : Size extends 2 ? [T, T][] : Size extends 3 ? [T, T, T][] : Size extends 4 ? [T, T, T, T][] : Size extends 5 ? [T, T, T, T, T][] : Size extends 6 ? [T, T, T, T, T, T][] : Size extends 7 ? [T, T, T, T, T, T, T][] : Size extends 8 ? [T, T, T, T, T, T, T, T][] : Size extends 9 ? [T, T, T, T, T, T, T, T, T][] : IsNegative<Size> extends true ? never[] : Size extends 0 ? never[] : T[][];
58
+
3
59
  type RangeOptions<T> = {
4
60
  step?: number;
5
61
  value?: T;
@@ -196,8 +252,7 @@ declare function retry<T>(asyncFunction: RetryFunction<T>, option?: RetryOption)
196
252
  */
197
253
  declare function sleep(time?: number): Promise<unknown>;
198
254
 
199
- type TryitResultType<Res, Err> = [undefined, Res] | [Err, undefined];
200
- type TryitResult<Res, Err extends Error> = Res extends Promise<infer R> ? Promise<TryitResultType<R, Err>> : TryitResultType<Res, Err>;
255
+ type TryitResult<Res, Err> = [undefined, Res] | [Err, undefined];
201
256
  /**
202
257
  * 将一个函数处理为 `error-first` 的函数
203
258
  * @param fn 需要处理的函数, 可以是异步函数
@@ -207,11 +262,6 @@ type TryitResult<Res, Err extends Error> = Res extends Promise<infer R> ? Promis
207
262
  * 如果出现异常则 `result` 为 `undefined`, `error` 是原函数抛出的错误
208
263
  * @example
209
264
  * ```js
210
- * // Sync Function
211
- * const normalFn = () => { return 1 }
212
- * const errorFn = () => { throw new Error('1') }
213
- * tryit(normalFn)() // [undefined, 1]
214
- * tryit(errorFn)() // [Error('1'), undefined]
215
265
  * // Async Function
216
266
  * const normalAsyncFn = () => { return Promise.resolve(1) }
217
267
  * const errorAsyncFn = () => { return Promise.reject('1') }
@@ -220,6 +270,24 @@ type TryitResult<Res, Err extends Error> = Res extends Promise<infer R> ? Promis
220
270
  * ```
221
271
  * @version 0.2.0
222
272
  */
273
+ declare function tryit<Args extends any[], Res, Err extends Error>(fn: (...args: Args) => Promise<Res>): (...args: Args) => Promise<TryitResult<Res, Err>>;
274
+ /**
275
+ * 将一个函数处理为 `error-first` 的函数
276
+ * @param fn 需要处理的函数, 可以是异步函数
277
+ * @returns 处理过的函数, 调用后返回一个 `error-first` 的元组 `[error, result]`;\
278
+ * 如果原函数是异步函数, 则返回值会是 `Promise<[error, result]>`;\
279
+ * 如果运行正常则 `result` 是原函数的返回值, `error` 为 `undefined`;\
280
+ * 如果出现异常则 `result` 为 `undefined`, `error` 是原函数抛出的错误
281
+ * @example
282
+ * ```js
283
+ * // Sync Function
284
+ * const normalFn = () => { return 1 }
285
+ * const errorFn = () => { throw new Error('1') }
286
+ * tryit(normalFn)() // [undefined, 1]
287
+ * tryit(errorFn)() // [Error('1'), undefined]
288
+ * ```
289
+ * @version 0.2.0
290
+ */
223
291
  declare function tryit<Args extends any[], Res, Err extends Error>(fn: (...args: Args) => Res): (...args: Args) => TryitResult<Res, Err>;
224
292
 
225
293
  interface PromiseLikeConstructor {
@@ -527,6 +595,21 @@ declare function isNumber(value: unknown): value is number;
527
595
  */
528
596
  declare function isObject(value: unknown): value is object;
529
597
 
598
+ /**
599
+ * 类型守卫,判断给定的值是否为普通对象(不是 `Date`、数组等特殊对象)
600
+ * - 注意,与 lodash 的同名方法不同,不会将函数视为对象
601
+ * @param value 要判断的值
602
+ * @example
603
+ * ```js
604
+ * isObject({}) // true
605
+ * isObject(Object.create(null)) // true
606
+ * isObject([]) // false
607
+ * isObject(Object(123)) // false
608
+ * isObject(null) // false
609
+ * ```
610
+ */
611
+ declare function isPlainObject(value: unknown): value is object;
612
+
530
613
  /**
531
614
  * 类型守卫,判断给定的值是否为原始类型(如字符串数字等 JS 内置的类型)
532
615
  * - 包括 `undefined` 和 `null`
@@ -864,6 +947,165 @@ declare function clamp(num: number, min: number, max: number, options?: {
864
947
  defaultMax?: number;
865
948
  }): number;
866
949
 
950
+ /**
951
+ * 将一个数字转换为正常的十进制计数法
952
+ * @param num 需要转换的数字
953
+ * @returns 返回一个十进制计数法表示的数字
954
+ * @example
955
+ * ```js
956
+ * decimalNotation(1e12) // 1000000000000
957
+ * decimalNotation(-2.33e8) // -233000000
958
+ * decimalNotation(1.234e-6) // 0.000001234
959
+ * decimalNotation(-4.321e-8) // -0.00000004321
960
+ * ```
961
+ * @version 0.3.2
962
+ */
963
+ declare function decimalNotation(num: string | number): string;
964
+
965
+ /**
966
+ * 将一个数字转换为指定的格式(如千分位逗号分隔)
967
+ * @param num 需要格式化的数字
968
+ * @param options 格式化配置\
969
+ * - `separator` 分割符, 默认为 `','`
970
+ * - `separate` 按位分割, 默认为 `3`
971
+ * - `decimal` 小数点, 默认为 `'.'`
972
+ * - `precision` 小数精度, 默认为 `2`
973
+ * - `round` 数值修约规则
974
+ * - `'round'` 四舍五入
975
+ * - `'banker'` 四舍六入五成双
976
+ * - `'floor'` 向下取整
977
+ * - `'ceil'` 向上取整
978
+ * @returns 返回一个指定格式的十进制数字
979
+ * @version 0.3.2
980
+ */
981
+ declare function format(num: number | string, options?: {
982
+ separator?: string;
983
+ separate?: number;
984
+ decimal?: string;
985
+ precision?: number;
986
+ round?: 'round' | 'banker' | 'floor' | 'ceil';
987
+ }): string;
988
+
989
+ /**
990
+ * 检查一个数字是否为奇数
991
+ * @param num 需要检查的数字
992
+ * @returns 如果是奇数则返回 true 否则返回 false
993
+ * @version 0.3.2
994
+ */
995
+ declare function isOdd(num: number): boolean;
996
+ /**
997
+ * 检查一个数字是否为偶数
998
+ * @param num 需要检查的数字
999
+ * @returns 如果是偶数则返回 true 否则返回 false
1000
+ * @version 0.3.2
1001
+ */
1002
+ declare function isEven(num: number): boolean;
1003
+
1004
+ /**
1005
+ * 数值修约, 可以使用 4 种修约方法, 默认使用四舍五入
1006
+ * - 四舍五入: 修约位置的后一位如果是 5 则进位, 否则不进位
1007
+ * - 四舍六入五成双: 修约位置的后一位如果是 5 且前一位是偶数则进位, 否则不进位
1008
+ * - 向下取整
1009
+ * - 向上取整
1010
+ * @param num 需要修约的数字
1011
+ * @param precision 精度, 小数点后几位
1012
+ * @param type 修约方法, 默认使用四舍五入
1013
+ * @example
1014
+ * ```js
1015
+ * // 四舍五入
1016
+ * round(1.95, 1) // '2.0'
1017
+ * round('1.95', 1) // '2.0'
1018
+ * // 四舍六入五成双
1019
+ * round('1.85', 1, 'banker') // '1.8'
1020
+ * round('1.95', 1, 'banker') // '2.0'
1021
+ * // 向下取整
1022
+ * round('1.95', 1, 'floor') // '1.9'
1023
+ * round(-1.95, 1, 'floor') // '-2.0'
1024
+ * // 向上取整
1025
+ * round('1.95', 1, 'ceil') // '2.0'
1026
+ * round(-1.95, 1, 'ceil') // '-1.9'
1027
+ * ```
1028
+ * @version 0.3.2
1029
+ */
1030
+ declare function round(num: string | number, precision: number, type?: 'round' | 'banker' | 'floor' | 'ceil'): string;
1031
+ /**
1032
+ * 四舍五入, 由于 JS 的 toFixed 有浮点误差所以不能使用
1033
+ * @example
1034
+ * ```js
1035
+ * // 四舍五入
1036
+ * roundBase('1', '34', 1, false) // ['1', '3']
1037
+ * roundBase('1', '35', 1, false) // ['1', '4']
1038
+ * roundBase('1', '36', 1, false) // ['1', '4']
1039
+ * // 与符号无关
1040
+ * roundBase('1', '34', 1, true) // ['1', '3']
1041
+ * roundBase('1', '35', 1, true) // ['1', '4']
1042
+ * roundBase('1', '36', 1, true) // ['1', '4']
1043
+ * ```
1044
+ * @version 0.3.2
1045
+ */
1046
+ declare function roundBase(integer: string, fractional: string, precision: number): [integer: string, fractional: string];
1047
+ /**
1048
+ * 四舍六入五成双
1049
+ * @example
1050
+ * ```js
1051
+ * // 四舍六入, 如果后一位是 5(000...) 则看前一位, 凑偶数
1052
+ * roundBank('1', '34', 1, false) // ['1', '3']
1053
+ * roundBank('1', '35', 1, false) // ['1', '4'] 五成双
1054
+ * roundBank('1', '36', 1, false) // ['1', '4']
1055
+ * roundBank('1', '44', 1, false) // ['1', '4']
1056
+ * roundBank('1', '45', 1, false) // ['1', '4'] 五成双
1057
+ * roundBank('1', '450001', 1, false) // ['1', '5'] 后一位比 5(000...) 多所以仍然进位
1058
+ * roundBank('1', '46', 1, false) // ['1', '5']
1059
+ * // 向整数进位也是如此
1060
+ * roundBank('1', '4', 0, false) // ['1', '']
1061
+ * roundBank('1', '5', 0, false) // ['2', ''] 五成双
1062
+ * roundBank('1', '6', 0, false) // ['2', '']
1063
+ * roundBank('2', '4', 0, false) // ['2', '']
1064
+ * roundBank('2', '5', 0, false) // ['2', ''] 五成双
1065
+ * roundBank('2', '6', 0, false) // ['3', '']
1066
+ * // 与符号无关
1067
+ * roundBank('1', '34', 1, true) // ['1', '3']
1068
+ * roundBank('1', '35', 1, true) // ['1', '4'] 五成双
1069
+ * roundBank('1', '36', 1, true) // ['1', '4']
1070
+ * roundBank('1', '44', 1, true) // ['1', '4']
1071
+ * roundBank('1', '45', 1, true) // ['1', '4'] 五成双
1072
+ * roundBank('1', '450001', 1, true) // ['1', '5']
1073
+ * roundBank('1', '46', 1, true) // ['1', '5']
1074
+ * ```
1075
+ * @version 0.3.2
1076
+ */
1077
+ declare function roundBank(integer: string, fractional: string, precision: number): [integer: string, fractional: string];
1078
+ /** 向下取整
1079
+ * @example
1080
+ * ```js
1081
+ * // 忽略后面的数字向下取整
1082
+ * roundFloor('1', '34', 1, false) // ['1', '3']
1083
+ * roundFloor('1', '36', 1, false) // ['1', '3']
1084
+ * roundFloor('1', '39', 1, false) // ['1', '3']
1085
+ * // 与符号有关 向更小的数字进位
1086
+ * roundFloor('1', '34', 1, true) // ['1', '4']
1087
+ * roundFloor('1', '35', 1, true) // ['1', '4']
1088
+ * roundFloor('1', '36', 1, true) // ['1', '4']
1089
+ * ```
1090
+ * @version 0.3.2
1091
+ */
1092
+ declare function roundFloor(integer: string, fractional: string, precision: number, isNegative: boolean): [integer: string, fractional: string];
1093
+ /** 向上取整
1094
+ * @example
1095
+ * ```js
1096
+ * // 忽略后面的数字向上取整
1097
+ * roundCeil('1', '34', 1, false) // ['1', '4']
1098
+ * roundCeil('1', '35', 1, false) // ['1', '4']
1099
+ * roundCeil('1', '36', 1, false) // ['1', '4']
1100
+ * // 与符号有关 向更大的数字进位
1101
+ * roundCeil('1', '34', 1, true) // ['1', '3']
1102
+ * roundCeil('1', '35', 1, true) // ['1', '3']
1103
+ * roundCeil('1', '36', 1, true) // ['1', '3']
1104
+ * ```
1105
+ * @version 0.3.2
1106
+ */
1107
+ declare function roundCeil(integer: string, fractional: string, precision: number, isNegative: boolean): [integer: string, fractional: string];
1108
+
867
1109
  /**
868
1110
  * 根据文件名称判断是否匹配支持的文件类型,需要注意 `.C` 与 `.c` 的区别
869
1111
  * - `text/x-c++src` 对应 `.C`
@@ -1264,6 +1506,74 @@ declare function caseKebab(str: string, keepLetterCase?: boolean, keepNumber?: b
1264
1506
  */
1265
1507
  declare function caseSnake(str: string, keepLetterCase?: boolean, keepNumber?: boolean): string;
1266
1508
 
1509
+ /**
1510
+ * 给一个多行的字符串清除缩进效果
1511
+ * @param str 需要处理的字符串
1512
+ * @param count 缩进数量, 默认为 `2`
1513
+ * @param indentStr 缩进字符串, 默认为 ` `(一个空格)
1514
+ * @returns 处理过的字符串
1515
+ * @example
1516
+ * ```js
1517
+ * dedent(` a\n b\n c`) // `a\nb\n c`
1518
+ * dedent(`*a\n**b\n****c`, 3, '*') // `a\nb\n*c`
1519
+ * ```
1520
+ * @version 0.3.1
1521
+ */
1522
+ declare function dedent(str: string, count?: number | null, indentStr?: string): string;
1523
+ /**
1524
+ * 给一个多行的字符串清除缩进效果
1525
+ * @param str 需要处理的字符串
1526
+ * @param option 缩进效果配置
1527
+ * - `count` 缩进数量, 默认为 `2`
1528
+ * - `indentStr` 缩进字符串, 默认为 ` `(一个空格)
1529
+ * @returns 处理过的字符串
1530
+ * @example
1531
+ * ```js
1532
+ * dedent(` a\n b\n c`) // `a\nb\n c`
1533
+ * dedent(`*a\n**b\n****c`, { count: 3, indentStr: '*' }) // `a\nb\n*c`
1534
+ * ```
1535
+ * @version 0.3.1
1536
+ */
1537
+ declare function dedent(str: string, option?: {
1538
+ count?: number;
1539
+ indentStr?: string;
1540
+ }): string;
1541
+
1542
+ /**
1543
+ * 给一个多行的字符串添加缩进效果
1544
+ * @param str 需要处理的字符串
1545
+ * @param count 缩进数量, 默认为 `2`
1546
+ * @param indentStr 缩进字符串, 默认为 ` `(一个空格)
1547
+ * @returns 处理过的字符串
1548
+ * @example
1549
+ * ```js
1550
+ * indent(`a\nb\n c`) // ` a\n b\n c`
1551
+ * indent(`a\nb\n c`, 1, '*') // `*a\n*b\n* c`
1552
+ * ```
1553
+ * @version 0.3.1
1554
+ */
1555
+ declare function indent(str: string, count?: number | null, indentStr?: string): string;
1556
+ /**
1557
+ * 给一个多行的字符串添加缩进效果
1558
+ * @param str 需要处理的字符串
1559
+ * @param option 缩进效果配置
1560
+ * - `count` 缩进数量, 默认为 `2`
1561
+ * - `indentStr` 缩进字符串, 默认为 ` `(一个空格)
1562
+ * - `ignoreEmptyLine` 是否忽略空行, 默认为是
1563
+ * @returns 处理过的字符串
1564
+ * @example
1565
+ * ```js
1566
+ * indent(`a\nb\n c`) // ` a\n b\n c`
1567
+ * indent(`a\nb\n c`, { count: 1, indentStr: '*' }) // `*a\n*b\n* c`
1568
+ * ```
1569
+ * @version 0.3.1
1570
+ */
1571
+ declare function indent(str: string, option?: {
1572
+ count?: number;
1573
+ indentStr?: string;
1574
+ ignoreEmptyLine?: boolean;
1575
+ }): string;
1576
+
1267
1577
  /**
1268
1578
  * 分割单词, 适用于分割、转换变量名的场景
1269
1579
  * - 任何非英文字母、数字的字符均会视为分割符
@@ -1906,5 +2216,5 @@ declare function throttle<T extends any[]>(fn: (...args: T) => any, delay: numbe
1906
2216
  reset: () => void;
1907
2217
  };
1908
2218
 
1909
- export { $$Empty, _, acceptableFileName, acceptableFileType, camelCase, capitalize, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, clamp, compose, _curryMore as curry, debounce, deepClone, deepMerge, defer, fastClone, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBlob, isBoolean, isBuffer, isDataView, isDate, isEmpty, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isMergeEmptyPlaceholder, isNil, isNull, isNumber, isObject, isPlaceholder, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, memo, noop, not, parallel, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, remove, retry, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, tryit, ulid, uncapitalize, uuidNil, uuidV4, withResolvers };
1910
- export type { BaseMargeType, CloneOptions, CustomCloner, MergeOption, MergeStrategy, MergeStrategyFunction, MergeType, MergeTypeStrategy, RangeOptions, SourceMergeType, TargetMergeType, TypedArray };
2219
+ export { $$Empty, _, acceptableFileName, acceptableFileType, camelCase, capitalize, cartesianProduct, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, chunk, clamp, compose, _curryMore as curry, debounce, decimalNotation, dedent, deepClone, deepMerge, defer, fastClone, format, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, indent, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBlob, isBoolean, isBuffer, isDataView, isDate, isEmpty, isEven, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isMergeEmptyPlaceholder, isNil, isNull, isNumber, isObject, isOdd, isPlaceholder, isPlainObject, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, memo, noop, not, parallel, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, remove, retry, round, roundBank, roundBase, roundCeil, roundFloor, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, tryit, ulid, uncapitalize, uuidNil, uuidV4, withResolvers };
2220
+ export type { BaseMargeType, Chunked, CloneOptions, CustomCloner, IsNegative, IsPositive, IsZero, MergeOption, MergeStrategy, MergeStrategyFunction, MergeType, MergeTypeStrategy, Not, RangeOptions, SourceMergeType, Stringify, TargetMergeType, TypedArray };
package/lib/index.mjs CHANGED
@@ -9,6 +9,53 @@ EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9
9
  MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10
10
  See the Mulan PSL v2 for more details.
11
11
  */
12
+ function cartesianProduct(...arrList) {
13
+ const arrLen = arrList.length;
14
+ const pList = Array(arrLen).fill(0);
15
+ const lastIndex = arrLen - 1;
16
+ const res = [];
17
+ for (let i = 0; i < arrLen; i++) {
18
+ if (!arrList[i].length)
19
+ return [];
20
+ }
21
+ while (1) {
22
+ const temp = [];
23
+ for (let i = 0; i < arrLen; i++) {
24
+ temp.push(arrList[i][pList[i]]);
25
+ }
26
+ res.push(temp);
27
+ pList[lastIndex] += 1;
28
+ for (let i = lastIndex; i >= 0; i--) {
29
+ if (pList[i] >= arrList[i].length) {
30
+ if (i > 0) {
31
+ pList[i] = 0;
32
+ pList[i - 1] += 1;
33
+ }
34
+ else
35
+ break;
36
+ }
37
+ else
38
+ break;
39
+ }
40
+ if (pList[0] >= arrList[0].length)
41
+ break;
42
+ }
43
+ return res;
44
+ }
45
+
46
+ function chunk(array, size = 2) {
47
+ const res = [];
48
+ if (size < 1 || isNaN(size))
49
+ return res;
50
+ let start = 0, end = size;
51
+ while (start < array.length) {
52
+ res.push(Array.prototype.slice.call(array, start, end));
53
+ start = end;
54
+ end += size;
55
+ }
56
+ return res;
57
+ }
58
+
12
59
  function range(start, end, stepOrOptions) {
13
60
  if (!isFinite(start))
14
61
  throw new Error('start must be finite');
@@ -200,6 +247,22 @@ function isNumber(value) {
200
247
  return typeof value === 'number';
201
248
  }
202
249
 
250
+ const fnToString = Function.prototype.toString;
251
+ const objProtoContString = fnToString.call(Object.prototype.constructor);
252
+ function isPlainObject(value) {
253
+ if (typeof value !== 'object' || value === null)
254
+ return false;
255
+ const prototype = Object.getPrototypeOf(value);
256
+ if (prototype === null)
257
+ return true;
258
+ if (!Object.prototype.hasOwnProperty.call(prototype, "constructor"))
259
+ return false;
260
+ const constructorFn = prototype.constructor;
261
+ if (!isFunction(constructorFn) || fnToString.call(constructorFn) !== objProtoContString)
262
+ return false;
263
+ return (Object.getPrototypeOf(prototype) === null);
264
+ }
265
+
203
266
  function isPrimitive(value) {
204
267
  return value === undefined || value === null || (typeof value !== 'object' && typeof value !== 'function');
205
268
  }
@@ -372,6 +435,178 @@ function clamp(num, min, max, options) {
372
435
  return num < min ? defaultMin : num > max ? defaultMax : num;
373
436
  }
374
437
 
438
+ function decimalNotation(num) {
439
+ const n = isNumber(num) ? num : Number(num);
440
+ if (!isFinite(n))
441
+ return String(n);
442
+ let str = String(n);
443
+ if (!/e/i.test(str))
444
+ return str;
445
+ const match = str.match(/^(-?)(\d+)\.?(\d*)e([+-]?)(\d+)$/);
446
+ const [_, sign, mantissaI, mantissaF, expSign, _exponent] = match;
447
+ const exponent = Number(_exponent);
448
+ let mantissa = mantissaI + mantissaF;
449
+ let dotPos = mantissaI.length;
450
+ if (expSign === '-') {
451
+ const zeroCount = exponent - dotPos + 1;
452
+ if (zeroCount > 0)
453
+ mantissa = '0'.repeat(zeroCount) + mantissa;
454
+ return sign + mantissa[0] + '.' + mantissa.substring(1);
455
+ }
456
+ else {
457
+ const zeroCount = exponent + dotPos - mantissa.length;
458
+ if (zeroCount > 0)
459
+ mantissa = mantissa + '0'.repeat(zeroCount);
460
+ return sign + mantissa.substring(0, exponent + dotPos);
461
+ }
462
+ }
463
+
464
+ function isOdd(num) {
465
+ return !!(num & 1);
466
+ }
467
+ function isEven(num) {
468
+ return !(num & 1);
469
+ }
470
+
471
+ function round(num, precision, type) {
472
+ const str = decimalNotation(num);
473
+ if (/NaN|Inf/.test(str))
474
+ return str;
475
+ let [_integer, _fractional] = str.split('.');
476
+ let sign = '';
477
+ if (/^-/.test(_integer)) {
478
+ _integer = _integer.substring(1);
479
+ sign = '-';
480
+ }
481
+ _fractional = _fractional !== null && _fractional !== void 0 ? _fractional : '';
482
+ const roundMap = { round: roundBase, banker: roundBank, floor: roundFloor, ceil: roundCeil };
483
+ const [integer, fractional] = (roundMap[type || 'round'] || roundBase)(_integer, _fractional, precision, !!sign);
484
+ if (precision > 0)
485
+ return sign + integer + '.' + fractional;
486
+ else
487
+ return sign + integer;
488
+ }
489
+ function roundBase(integer, fractional, precision) {
490
+ if (fractional.length > precision) {
491
+ const splitF = fractional.substring(0, precision);
492
+ if (Number(fractional[precision]) > 4)
493
+ return increase(integer, splitF);
494
+ return [integer, splitF];
495
+ }
496
+ if (fractional.length < precision) {
497
+ fractional += '0'.repeat(precision - fractional.length);
498
+ }
499
+ return [integer, fractional];
500
+ }
501
+ function roundBank(integer, fractional, precision) {
502
+ if (fractional.length > precision) {
503
+ const splitF = fractional.substring(0, precision);
504
+ const rightNumber = Number(fractional[precision]);
505
+ if (rightNumber < 5)
506
+ return [integer, splitF];
507
+ if (rightNumber > 5)
508
+ return increase(integer, splitF);
509
+ const rightNumbers = fractional.substring(precision);
510
+ if (!/^50*$/.test(rightNumbers))
511
+ return increase(integer, splitF);
512
+ const leftNumber = Number(precision ? fractional[precision - 1] : integer[integer.length - 1]);
513
+ if (isEven(leftNumber))
514
+ return [integer, splitF];
515
+ else
516
+ return increase(integer, splitF);
517
+ }
518
+ if (fractional.length < precision) {
519
+ fractional += '0'.repeat(precision - fractional.length);
520
+ }
521
+ return [integer, fractional];
522
+ }
523
+ function roundFloor(integer, fractional, precision, isNegative) {
524
+ if (fractional.length > precision) {
525
+ const splitF = fractional.substring(0, precision);
526
+ if (isNegative)
527
+ return increase(integer, splitF);
528
+ return [integer, splitF];
529
+ }
530
+ if (fractional.length < precision) {
531
+ fractional += '0'.repeat(precision - fractional.length);
532
+ }
533
+ return [integer, fractional];
534
+ }
535
+ function roundCeil(integer, fractional, precision, isNegative) {
536
+ if (fractional.length > precision) {
537
+ const splitF = fractional.substring(0, precision);
538
+ if (!isNegative)
539
+ return increase(integer, splitF);
540
+ return [integer, splitF];
541
+ }
542
+ if (fractional.length < precision) {
543
+ fractional += '0'.repeat(precision - fractional.length);
544
+ }
545
+ return [integer, fractional];
546
+ }
547
+ function increase(integer, fractional) {
548
+ if (fractional) {
549
+ const _fractional = _increase(fractional);
550
+ if (_fractional.length > fractional.length) {
551
+ return [_increase(integer), _fractional.substring(1)];
552
+ }
553
+ return [integer, _fractional];
554
+ }
555
+ return [_increase(integer), ''];
556
+ }
557
+ function _increase(num) {
558
+ const numList = num.split('').map(Number).reverse();
559
+ numList[0] += 1;
560
+ numList.push(0);
561
+ for (let i = 0; i < numList.length; i++) {
562
+ if (numList[i] > 9) {
563
+ numList[i] -= 10;
564
+ numList[i + 1] += 1;
565
+ }
566
+ else
567
+ break;
568
+ }
569
+ if (numList[numList.length - 1] === 0)
570
+ numList.pop();
571
+ return numList.reverse().map(String).join('');
572
+ }
573
+
574
+ function format(num, options) {
575
+ var _a;
576
+ const str = decimalNotation(num);
577
+ if (/NaN|Inf/.test(str))
578
+ return str;
579
+ const separator = (options || {}).separator || ',';
580
+ const separate = clamp((options || {}).separate || 3, 1, Infinity);
581
+ const decimal = (options || {}).decimal || '.';
582
+ const precision = clamp((_a = (options || {}).precision) !== null && _a !== void 0 ? _a : 2, 0, Infinity);
583
+ const round = (options || {}).round || 'round';
584
+ let [integer, fractional] = str.split('.');
585
+ let sign = '';
586
+ if (/^-/.test(integer)) {
587
+ integer = integer.substring(1);
588
+ sign = '-';
589
+ }
590
+ fractional = fractional !== null && fractional !== void 0 ? fractional : '';
591
+ if (fractional.length > precision) {
592
+ const roundMap = { round: roundBase, banker: roundBank, floor: roundFloor, ceil: roundCeil };
593
+ [integer, fractional] = (roundMap[round] || roundBase)(integer, fractional, precision, !!sign);
594
+ }
595
+ else if (fractional.length < precision) {
596
+ fractional += '0'.repeat(precision - fractional.length);
597
+ }
598
+ if (integer.length > separate) {
599
+ integer = chunk(Array.from(integer).reverse(), separate)
600
+ .map((part) => part.join(''))
601
+ .join(separator);
602
+ integer = Array.from(integer).reverse().join('');
603
+ }
604
+ if (precision > 0)
605
+ return sign + integer + decimal + fractional;
606
+ else
607
+ return sign + integer;
608
+ }
609
+
375
610
  function parallel(args, fn, options) {
376
611
  return __awaiter(this, void 0, void 0, function* () {
377
612
  if (!args.length)
@@ -1304,6 +1539,45 @@ function caseSnake(str, keepLetterCase = false, keepNumber = true) {
1304
1539
  return _caseConvert(tokens, '_', keepLetterCase ? ({ code }) => code : ({ code }) => code.toLowerCase());
1305
1540
  }
1306
1541
 
1542
+ function dedent(str, option, indentStr) {
1543
+ if (typeof option === 'number' || indentStr) {
1544
+ return _dedent(str, option || 2, indentStr || ' ');
1545
+ }
1546
+ else {
1547
+ const { count = 2, indentStr = ' ' } = option || {};
1548
+ return _dedent(str, count, indentStr);
1549
+ }
1550
+ }
1551
+ function _dedent(str, count, indentStr) {
1552
+ return str
1553
+ .split('\n')
1554
+ .map((s) => {
1555
+ let i = count;
1556
+ while (s && s.startsWith(indentStr) && i > 0) {
1557
+ s = s.slice(indentStr.length);
1558
+ i--;
1559
+ }
1560
+ return s;
1561
+ })
1562
+ .join('\n');
1563
+ }
1564
+
1565
+ function indent(str, option, indentStr) {
1566
+ if (typeof option === 'number' || indentStr) {
1567
+ return _indent(str, option || 2, indentStr || ' ', true);
1568
+ }
1569
+ else {
1570
+ const { count = 2, indentStr = ' ', ignoreEmptyLine = true } = option || {};
1571
+ return _indent(str, count, indentStr, ignoreEmptyLine);
1572
+ }
1573
+ }
1574
+ function _indent(str, count, indentStr, ignoreEmptyLine) {
1575
+ return str
1576
+ .split('\n')
1577
+ .map((s) => `${s || !ignoreEmptyLine ? indentStr.repeat(count) : ''}${s}`)
1578
+ .join('\n');
1579
+ }
1580
+
1307
1581
  function splitWords(str) {
1308
1582
  return _splitVar(str).map(({ code }) => code);
1309
1583
  }
@@ -2001,4 +2275,4 @@ function throttle(fn, delay, options) {
2001
2275
  return _throttle(fn, delay, Object.assign({ trailing: false, leading: true }, options));
2002
2276
  }
2003
2277
 
2004
- export { $$Empty, _, acceptableFileName, acceptableFileType, camelCase, capitalize, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, clamp, compose, _curryMore as curry, debounce, deepClone, deepMerge, defer, fastClone, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBlob, isBoolean, isBuffer, isDataView, isDate, isEmpty, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isMergeEmptyPlaceholder, isNil, isNull, isNumber, isObject, isPlaceholder, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, memo, noop, not, parallel, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, remove, retry, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, tryit, ulid, uncapitalize, uuidNil, uuidV4, withResolvers };
2278
+ export { $$Empty, _, acceptableFileName, acceptableFileType, camelCase, capitalize, cartesianProduct, caseCamel, caseConvert, caseKebab, casePascal, caseSnake, chunk, clamp, compose, _curryMore as curry, debounce, decimalNotation, dedent, deepClone, deepMerge, defer, fastClone, format, getAcceptableExtByMIME, getAcceptableMIMEByExt, getGlobalThis, getTag, indent, isArray, isArrayBuffer, isArrayLike, isBigInt, isBigInt64Array, isBigUint64Array, isBlob, isBoolean, isBuffer, isDataView, isDate, isEmpty, isEven, isFile, isFloat32Array, isFloat64Array, isFormData, isFunction, isInt16Array, isInt32Array, isInt8Array, isInteger, isIterable, isMap, isMergeEmptyPlaceholder, isNil, isNull, isNumber, isObject, isOdd, isPlaceholder, isPlainObject, isPrimitive, isPromise, isPromiseLike, isRegExp, isSet, isString, isSymbol, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray, isUndefined, isWeakMap, isWeakSet, isWrapperBigInt, isWrapperBoolean, isWrapperNumber, isWrapperObject, isWrapperString, isWrapperSymbol, kebabCase, memo, noop, not, parallel, pascalCase, pass, passWith, pipe, randomBase32String, randomChoice, randomHexString, randomInt, randomIntFloor, randomString, range, remove, retry, round, roundBank, roundBase, roundCeil, roundFloor, shuffle, sleep, snakeCase, splitWords, throttle, titleCase, tryit, ulid, uncapitalize, uuidNil, uuidV4, withResolvers };