@cloudcome/utils-core 1.1.1 → 1.2.1

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.
Files changed (293) hide show
  1. package/README.md +18 -0
  2. package/dist/array.cjs +129 -0
  3. package/dist/array.cjs.map +1 -0
  4. package/dist/array.d.ts +171 -0
  5. package/dist/array.mjs +129 -0
  6. package/dist/array.mjs.map +1 -0
  7. package/dist/async.cjs +219 -0
  8. package/dist/async.cjs.map +1 -0
  9. package/dist/async.d.ts +137 -0
  10. package/dist/async.mjs +219 -0
  11. package/dist/async.mjs.map +1 -0
  12. package/dist/base64.cjs +16 -0
  13. package/dist/base64.cjs.map +1 -0
  14. package/dist/base64.d.ts +7 -0
  15. package/dist/base64.mjs +16 -0
  16. package/dist/base64.mjs.map +1 -0
  17. package/dist/cache.cjs +79 -0
  18. package/dist/cache.cjs.map +1 -0
  19. package/dist/cache.d.ts +90 -0
  20. package/dist/cache.mjs +79 -0
  21. package/dist/cache.mjs.map +1 -0
  22. package/{src/color/contrast.ts → dist/color/contrast.d.ts} +2 -12
  23. package/dist/color/distance.d.ts +8 -0
  24. package/dist/color/helpers.d.ts +2 -0
  25. package/dist/color/hex-hsl.d.ts +3 -0
  26. package/{src/color/hex-hsv.ts → dist/color/hex-hsv.d.ts} +3 -11
  27. package/{src/color/hex-hwb.ts → dist/color/hex-hwb.d.ts} +3 -11
  28. package/dist/color/hex-rgb.d.ts +18 -0
  29. package/{src/color/hsl-lighten.ts → dist/color/hsl-lighten.d.ts} +2 -7
  30. package/{src/color/hsv-brighten.ts → dist/color/hsv-brighten.d.ts} +2 -7
  31. package/{src/color/luminance.ts → dist/color/luminance.d.ts} +2 -9
  32. package/{src/color/mix.ts → dist/color/mix.d.ts} +2 -10
  33. package/dist/color/rgb-hsl.d.ts +23 -0
  34. package/{src/color/rgb-hsv.ts → dist/color/rgb-hsv.d.ts} +3 -30
  35. package/dist/color/rgb-hwb.d.ts +29 -0
  36. package/{src/color/rgb-lab.ts → dist/color/rgb-lab.d.ts} +3 -11
  37. package/dist/color/rgb-whiter.d.ts +12 -0
  38. package/dist/color/rgb-xyz.d.ts +22 -0
  39. package/{src/color/types.ts → dist/color/types.d.ts} +30 -12
  40. package/{src/color/xyz-lab.ts → dist/color/xyz-lab.d.ts} +3 -32
  41. package/dist/color.cjs +250 -0
  42. package/dist/color.cjs.map +1 -0
  43. package/dist/color.mjs +250 -0
  44. package/dist/color.mjs.map +1 -0
  45. package/dist/const.cjs +14 -0
  46. package/dist/const.cjs.map +1 -0
  47. package/dist/const.mjs +15 -0
  48. package/dist/const.mjs.map +1 -0
  49. package/dist/core.cjs +250 -0
  50. package/dist/core.cjs.map +1 -0
  51. package/dist/core.mjs +251 -0
  52. package/dist/core.mjs.map +1 -0
  53. package/dist/crypto/md5.d.mts +1 -0
  54. package/dist/crypto/sha1.d.mts +1 -0
  55. package/dist/crypto/sha256.d.mts +1 -0
  56. package/dist/crypto/sha512.d.mts +1 -0
  57. package/dist/crypto.cjs +812 -0
  58. package/dist/crypto.cjs.map +1 -0
  59. package/{src/crypto.ts → dist/crypto.d.ts} +4 -20
  60. package/dist/crypto.mjs +812 -0
  61. package/dist/crypto.mjs.map +1 -0
  62. package/dist/date/const.d.ts +6 -0
  63. package/dist/date/core.d.ts +52 -0
  64. package/dist/date/days.d.ts +23 -0
  65. package/{src/date/is.ts → dist/date/is.d.ts} +8 -102
  66. package/dist/date/relative.d.ts +44 -0
  67. package/dist/date/start-end.d.ts +73 -0
  68. package/dist/date/timezone.d.ts +67 -0
  69. package/dist/date/weeks.d.ts +72 -0
  70. package/dist/date.cjs +239 -0
  71. package/dist/date.cjs.map +1 -0
  72. package/dist/date.mjs +241 -0
  73. package/dist/date.mjs.map +1 -0
  74. package/dist/dict.cjs +2 -0
  75. package/dist/dict.cjs.map +1 -0
  76. package/dist/dict.mjs +2 -0
  77. package/dist/dict.mjs.map +1 -0
  78. package/dist/each.cjs +18 -0
  79. package/dist/each.cjs.map +1 -0
  80. package/dist/each.mjs +19 -0
  81. package/dist/each.mjs.map +1 -0
  82. package/dist/easing.cjs +151 -0
  83. package/dist/easing.cjs.map +1 -0
  84. package/dist/easing.d.ts +46 -0
  85. package/dist/easing.mjs +151 -0
  86. package/dist/easing.mjs.map +1 -0
  87. package/dist/emitter.cjs +94 -0
  88. package/dist/emitter.cjs.map +1 -0
  89. package/dist/emitter.d.ts +68 -0
  90. package/dist/emitter.mjs +94 -0
  91. package/dist/emitter.mjs.map +1 -0
  92. package/dist/enum.cjs +58 -0
  93. package/dist/enum.cjs.map +1 -0
  94. package/dist/enum.d.ts +68 -0
  95. package/dist/enum.mjs +58 -0
  96. package/dist/enum.mjs.map +1 -0
  97. package/dist/env.cjs +28 -0
  98. package/dist/env.cjs.map +1 -0
  99. package/{src/env.ts → dist/env.d.ts} +6 -30
  100. package/dist/env.mjs +28 -0
  101. package/dist/env.mjs.map +1 -0
  102. package/dist/error.cjs +12 -0
  103. package/dist/error.cjs.map +1 -0
  104. package/{src/error.ts → dist/error.d.ts} +3 -12
  105. package/dist/error.mjs +12 -0
  106. package/dist/error.mjs.map +1 -0
  107. package/dist/exception.cjs +22 -0
  108. package/dist/exception.cjs.map +1 -0
  109. package/dist/exception.d.ts +31 -0
  110. package/dist/exception.mjs +22 -0
  111. package/dist/exception.mjs.map +1 -0
  112. package/dist/fn.cjs +76 -0
  113. package/dist/fn.cjs.map +1 -0
  114. package/dist/fn.d.ts +102 -0
  115. package/dist/fn.mjs +76 -0
  116. package/dist/fn.mjs.map +1 -0
  117. package/dist/index.cjs +5 -0
  118. package/dist/index.cjs.map +1 -0
  119. package/dist/index.d.ts +1 -0
  120. package/dist/index.mjs +5 -0
  121. package/dist/index.mjs.map +1 -0
  122. package/dist/merge.cjs +87 -0
  123. package/dist/merge.cjs.map +1 -0
  124. package/dist/merge.mjs +88 -0
  125. package/dist/merge.mjs.map +1 -0
  126. package/dist/number.cjs +14 -0
  127. package/dist/number.cjs.map +1 -0
  128. package/dist/number.d.ts +153 -0
  129. package/dist/number.mjs +14 -0
  130. package/dist/number.mjs.map +1 -0
  131. package/{src/object/each.ts → dist/object/each.d.ts} +3 -23
  132. package/dist/object/get-set.d.ts +111 -0
  133. package/dist/object/is.d.ts +32 -0
  134. package/dist/object/merge.d.ts +72 -0
  135. package/{src/object/process.ts → dist/object/process.d.ts} +4 -38
  136. package/dist/object.cjs +130 -0
  137. package/dist/object.cjs.map +1 -0
  138. package/dist/object.mjs +130 -0
  139. package/dist/object.mjs.map +1 -0
  140. package/dist/path.cjs +77 -0
  141. package/dist/path.cjs.map +1 -0
  142. package/dist/path.d.ts +82 -0
  143. package/dist/path.mjs +77 -0
  144. package/dist/path.mjs.map +1 -0
  145. package/dist/promise.cjs +62 -0
  146. package/dist/promise.cjs.map +1 -0
  147. package/{src/promise.ts → dist/promise.d.ts} +6 -67
  148. package/dist/promise.mjs +62 -0
  149. package/dist/promise.mjs.map +1 -0
  150. package/dist/qs.cjs +47 -0
  151. package/dist/qs.cjs.map +1 -0
  152. package/{src/qs.ts → dist/qs.d.ts} +3 -60
  153. package/dist/qs.mjs +47 -0
  154. package/dist/qs.mjs.map +1 -0
  155. package/dist/regexp.cjs +66 -0
  156. package/dist/regexp.cjs.map +1 -0
  157. package/dist/regexp.d.ts +65 -0
  158. package/dist/regexp.mjs +66 -0
  159. package/dist/regexp.mjs.map +1 -0
  160. package/dist/string.cjs +16 -0
  161. package/dist/string.cjs.map +1 -0
  162. package/dist/string.d.ts +80 -0
  163. package/dist/string.mjs +16 -0
  164. package/dist/string.mjs.map +1 -0
  165. package/dist/string2.cjs +157 -0
  166. package/dist/string2.cjs.map +1 -0
  167. package/dist/string2.mjs +158 -0
  168. package/dist/string2.mjs.map +1 -0
  169. package/dist/time/from.d.ts +14 -0
  170. package/dist/time/to.d.ts +38 -0
  171. package/dist/time.cjs +82 -0
  172. package/dist/time.cjs.map +1 -0
  173. package/dist/time.mjs +82 -0
  174. package/dist/time.mjs.map +1 -0
  175. package/dist/timer.cjs +119 -0
  176. package/dist/timer.cjs.map +1 -0
  177. package/dist/timer.d.ts +96 -0
  178. package/{src/timer.ts → dist/timer.mjs} +17 -124
  179. package/dist/timer.mjs.map +1 -0
  180. package/dist/tree.cjs +125 -0
  181. package/dist/tree.cjs.map +1 -0
  182. package/dist/tree.d.ts +210 -0
  183. package/dist/tree.mjs +125 -0
  184. package/dist/tree.mjs.map +1 -0
  185. package/dist/type.cjs +78 -0
  186. package/dist/type.cjs.map +1 -0
  187. package/{src/type.ts → dist/type.d.ts} +20 -96
  188. package/dist/type.mjs +78 -0
  189. package/dist/type.mjs.map +1 -0
  190. package/dist/types.cjs +2 -0
  191. package/dist/types.cjs.map +1 -0
  192. package/{src/types.ts → dist/types.d.ts} +12 -33
  193. package/dist/types.mjs +2 -0
  194. package/dist/types.mjs.map +1 -0
  195. package/dist/unique.cjs +46 -0
  196. package/dist/unique.cjs.map +1 -0
  197. package/dist/unique.d.ts +22 -0
  198. package/dist/unique.mjs +46 -0
  199. package/dist/unique.mjs.map +1 -0
  200. package/dist/url.cjs +37 -0
  201. package/dist/url.cjs.map +1 -0
  202. package/dist/url.d.ts +53 -0
  203. package/dist/url.mjs +37 -0
  204. package/dist/url.mjs.map +1 -0
  205. package/dist/version.cjs +33 -0
  206. package/dist/version.cjs.map +1 -0
  207. package/dist/version.d.ts +32 -0
  208. package/dist/version.mjs +33 -0
  209. package/dist/version.mjs.map +1 -0
  210. package/package.json +8 -2
  211. package/CHANGELOG.md +0 -52
  212. package/src/array.ts +0 -312
  213. package/src/async.ts +0 -379
  214. package/src/base64.ts +0 -20
  215. package/src/cache.ts +0 -146
  216. package/src/color/distance.ts +0 -28
  217. package/src/color/helpers.ts +0 -23
  218. package/src/color/hex-hsl.ts +0 -11
  219. package/src/color/hex-rgb.ts +0 -39
  220. package/src/color/rgb-hsl.ts +0 -53
  221. package/src/color/rgb-hwb.ts +0 -56
  222. package/src/color/rgb-whiter.ts +0 -22
  223. package/src/color/rgb-xyz.ts +0 -62
  224. package/src/crypto/md5.mjs +0 -357
  225. package/src/crypto/sha1.mjs +0 -300
  226. package/src/crypto/sha256.mjs +0 -310
  227. package/src/crypto/sha512.mjs +0 -459
  228. package/src/date/const.ts +0 -6
  229. package/src/date/core.ts +0 -162
  230. package/src/date/days.ts +0 -51
  231. package/src/date/relative.ts +0 -92
  232. package/src/date/start-end.ts +0 -246
  233. package/src/date/timezone.ts +0 -220
  234. package/src/date/weeks.ts +0 -100
  235. package/src/dts/global.d.ts +0 -27
  236. package/src/easing.ts +0 -166
  237. package/src/emitter.ts +0 -117
  238. package/src/enum.ts +0 -171
  239. package/src/exception.ts +0 -68
  240. package/src/fn.ts +0 -197
  241. package/src/index.ts +0 -1
  242. package/src/number.ts +0 -236
  243. package/src/object/get-set.ts +0 -273
  244. package/src/object/is.ts +0 -128
  245. package/src/object/merge.ts +0 -180
  246. package/src/path.ts +0 -188
  247. package/src/regexp.ts +0 -156
  248. package/src/string.ts +0 -146
  249. package/src/time/from.ts +0 -57
  250. package/src/time/to.ts +0 -106
  251. package/src/tree.ts +0 -394
  252. package/src/unique.ts +0 -77
  253. package/src/url.ts +0 -93
  254. package/src/version.ts +0 -71
  255. package/test/array.test.ts +0 -332
  256. package/test/async-real.test.ts +0 -39
  257. package/test/async.test.ts +0 -375
  258. package/test/base64.test.ts +0 -32
  259. package/test/cache.test.ts +0 -83
  260. package/test/color.test.ts +0 -163
  261. package/test/crypto.test.ts +0 -34
  262. package/test/date-tz.test.ts +0 -206
  263. package/test/date.test.ts +0 -353
  264. package/test/easing.test.ts +0 -33
  265. package/test/emitter.test.ts +0 -71
  266. package/test/enum.test.ts +0 -113
  267. package/test/env.test.ts +0 -69
  268. package/test/error.test.ts +0 -58
  269. package/test/exception.test.ts +0 -43
  270. package/test/fn.test.ts +0 -263
  271. package/test/helpers.ts +0 -23
  272. package/test/index.test.ts +0 -6
  273. package/test/number.test.ts +0 -213
  274. package/test/object.test.ts +0 -309
  275. package/test/path.test.ts +0 -156
  276. package/test/promise.test.ts +0 -199
  277. package/test/qs.test.ts +0 -79
  278. package/test/regexp.test.ts +0 -97
  279. package/test/string.test.ts +0 -150
  280. package/test/time.test.ts +0 -214
  281. package/test/timer.test.ts +0 -114
  282. package/test/tree.test.ts +0 -348
  283. package/test/type.test.ts +0 -226
  284. package/test/unique.test.ts +0 -71
  285. package/test/url.test.ts +0 -136
  286. package/test/version.test.ts +0 -52
  287. package/tsconfig.json +0 -31
  288. package/vite.config.mts +0 -114
  289. /package/{src/color.ts → dist/color.d.ts} +0 -0
  290. /package/{src/date.ts → dist/date.d.ts} +0 -0
  291. /package/{src/dict.ts → dist/dict.d.ts} +0 -0
  292. /package/{src/object.ts → dist/object.d.ts} +0 -0
  293. /package/{src/time.ts → dist/time.d.ts} +0 -0
package/src/string.ts DELETED
@@ -1,146 +0,0 @@
1
- import { numberConvert, randomNumber } from './number';
2
- import { isFunction, isNullish, isNumber, isObject, isString, isUndefined } from './type';
3
-
4
- export const STRING_ARABIC_NUMERALS = '0123456789';
5
- export const STRING_HEXADECIMALS = '0123456789abcdef';
6
- export const STRING_LOWERCASE_ALPHA = 'abcdefghijklmnopqrstuvwxyz';
7
- export const STRING_UPPERCASE_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
8
- export const STRING_DICT = `${STRING_ARABIC_NUMERALS + STRING_UPPERCASE_ALPHA + STRING_LOWERCASE_ALPHA}`;
9
-
10
- /**
11
- * 将字符串转换为驼峰格式
12
- * @param {string} string - 要转换的字符串
13
- * @param {boolean} [bigger] - 是否大写第一个字母,默认为 false
14
- * @returns {string} - 转换后的驼峰格式字符串
15
- */
16
- export function stringCamelCase(string: string, bigger?: boolean): string {
17
- const string2 = string.replace(/[\s_-](.)/g, (_, char) => (char as string).toUpperCase());
18
- return bigger ? string2.slice(0, 1).toUpperCase() + string2.slice(1) : string2;
19
- }
20
-
21
- /**
22
- * 将字符串转换为连字格式
23
- * @param {string} string - 要转换的字符串
24
- * @param {string} [separator] - 分隔符,默认是 "-"(短横线)
25
- * @returns {string} - 转换后的连字格式字符串
26
- */
27
- export function stringKebabCase(string: string, separator = '-'): string {
28
- return string.replace(/[A-Z]/g, (origin) => `${separator}${origin.toLowerCase()}`);
29
- }
30
-
31
- /**
32
- * 生成随机字符串
33
- * @param {number} length - 生成的随机字符串长度
34
- * @param {string} [dict] - 用于生成随机字符串的字符字典,默认为数字、小写字母和大写字母的组合
35
- * @returns {string} - 生成的随机字符串
36
- * @example
37
- * randomString(10); // 生成一个长度为 10 的随机字符串
38
- * randomString(8, 'ABCDEF'); // 生成一个长度为 8 的随机字符串,仅包含字符 'ABCDEF'
39
- */
40
- export function randomString(length: number, dict?: string): string {
41
- const dictFinal = dict || STRING_DICT;
42
- const dictLength = dictFinal.length;
43
-
44
- let result = '';
45
-
46
- for (let i = 0; i < length; i++) {
47
- result += dictFinal.charAt(randomNumber(0, dictLength - 1));
48
- }
49
-
50
- return result;
51
- }
52
-
53
- /**
54
- * 简单的模板引擎,类似于 Python 的 `.format()` 方法
55
- * 支持通过索引或对象/名称的方式传递变量
56
- * 当使用对象/名称方式时,可以传递一个回退值作为第三个参数
57
- *
58
- * @category 字符串
59
- * @example
60
- * ```
61
- * // 索引方式
62
- * const result = stringFormat(
63
- * '你好 {0}!我的名字是 {1}。',
64
- * '张三',
65
- * '李四'
66
- * ); // 你好 张三!我的名字是 李四。
67
- * ```
68
- *
69
- * @example
70
- * ```
71
- * // 对象方式
72
- * const result = stringFormat(
73
- * '{greet}!我的名字是 {name}。',
74
- * { greet: '你好', name: '王五' }
75
- * ); // 你好!我的名字是 王五。
76
- * ```
77
- *
78
- * @example
79
- * ```
80
- * // 带回退值的对象方式
81
- * const result = stringFormat(
82
- * '{greet}!我的名字是 {name}。',
83
- * { greet: '你好' }, // name 未传递,因此会使用回退值
84
- * '未知'
85
- * ); // 你好!我的名字是 未知。
86
- * ```
87
- */
88
- export function stringFormat(
89
- str: string,
90
- object: Record<string | number, unknown>,
91
- fallback?: string | ((key: string) => string),
92
- ): string;
93
- export function stringFormat(str: string, ...args: (string | number | bigint | undefined | null)[]): string;
94
- export function stringFormat(str: string, ...args: unknown[]): string {
95
- const [firstArg, fallback] = args;
96
-
97
- if (isObject(firstArg) || isUndefined(firstArg)) {
98
- const vars = firstArg || {};
99
- return str.replace(/\{(\w+)\}/g, (_, key) => vars[key] ?? (isFunction(fallback) ? fallback(key) : fallback) ?? key);
100
- }
101
-
102
- return str.replace(/\{(\d+)\}/g, (_, key) => {
103
- const index = Number(key);
104
- if (Number.isNaN(index)) return key;
105
- return args[index];
106
- });
107
- }
108
-
109
- /**
110
- * 生成符合 [RFC 4122](https://www.ietf.org/rfc/rfc4122.txt) 版本 4 的 UUID 字符串
111
- * @returns {string} - 生成的 UUID 字符串
112
- * @example
113
- * const uuid = randomUUID4();
114
- * console.log(uuid); // 输出类似 '123e4567-e89b-12d3-a456-426614174000' 的 UUID 字符串
115
- */
116
- export function randomUUID4(): string {
117
- const template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
118
- let result = '';
119
-
120
- for (let i = 0; i < template.length; i++) {
121
- const t = template[i];
122
-
123
- if (t === '-' || t === '4') {
124
- result += t;
125
- continue;
126
- }
127
-
128
- if (t === 'y') {
129
- result += randomString(1, '89ab');
130
- continue;
131
- }
132
-
133
- result += randomString(1, STRING_HEXADECIMALS);
134
- }
135
-
136
- return result;
137
- }
138
-
139
- /**
140
- * 将值转换为字符串,若值为 null 或 undefined 则返回空字符串
141
- * @param {unknown} value - 需要转换的值
142
- * @returns {string} 转换后的字符串结果
143
- */
144
- export function stringify(value: unknown) {
145
- return isNullish(value) ? '' : String(value);
146
- }
package/src/time/from.ts DELETED
@@ -1,57 +0,0 @@
1
- // @rer https://day.js.org/docs/en/durations/creating
2
-
3
- import { DATE_DAY_MS, DATE_HOUR_MS, DATE_MINUTE_MS, DATE_MONTH_MS, DATE_SECOND_MS, DATE_YEAR_MS } from '@/date';
4
- import { isString } from '@/type';
5
- import type { TTimeDuration } from './to';
6
-
7
- /**
8
- * 时间转换规则数组
9
- * @type {Array<[RegExp, (match: RegExpMatchArray) => number]>}
10
- * @property {RegExp} 0 - 匹配时间单位正则表达式
11
- * @property {function} 1 - 将匹配结果转换为毫秒数的函数
12
- */
13
- const rules: [key: keyof TTimeDuration, time: number][] = [
14
- ['years', DATE_YEAR_MS],
15
- ['months', DATE_MONTH_MS],
16
- ['days', DATE_DAY_MS],
17
- ['hours', DATE_HOUR_MS],
18
- ['minutes', DATE_MINUTE_MS],
19
- ['seconds', DATE_SECOND_MS],
20
- ];
21
-
22
- /**
23
- * 将时间持续时间字符串或对象转换为毫秒数
24
- *
25
- * @param duration - 可以是时间持续时间字符串(如 '1d2h')或 TTimeDuration 对象
26
- * @returns 计算得到的总毫秒数
27
- */
28
- export function timeFrom(duration: string | TTimeDuration) {
29
- const td = isString(duration) ? timeParse(duration) : duration;
30
- return rules.reduce((acc, [key, time]) => acc + (td[key] || 0) * time, 0);
31
- }
32
-
33
- const durationMatchRules: [RegExp, key: keyof TTimeDuration][] = [
34
- [/(\d+)y/i, 'years'],
35
- [/(\d+)M/, 'months'],
36
- [/(\d+)d/i, 'days'],
37
- [/(\d+)h/i, 'hours'],
38
- [/(\d+)m/, 'minutes'],
39
- [/(\d+)s/, 'seconds'],
40
- ];
41
-
42
- /**
43
- * 将时长字符串解析为时间对象
44
- * @param duration - 时长字符串(例如 "1h30m")
45
- * @returns 包含解析后时间单位的对象(小时、分钟等)
46
- */
47
- export function timeParse(duration: string) {
48
- const result = {} as TTimeDuration;
49
-
50
- for (const [regex, key] of durationMatchRules) {
51
- const match = duration.match(regex);
52
- if (match) result[key] = Number(match[1]);
53
- else result[key] = 0;
54
- }
55
-
56
- return result;
57
- }
package/src/time/to.ts DELETED
@@ -1,106 +0,0 @@
1
- import { DATE_DAY_MS, DATE_HOUR_MS, DATE_MINUTE_MS, DATE_SECOND_MS } from '../date';
2
-
3
- export type TTimeDuration = {
4
- years: number;
5
- months: number;
6
- /** 天数 */
7
- days: number;
8
- /** 小时数 */
9
- hours: number;
10
- /** 分钟数 */
11
- minutes: number;
12
- /** 秒数 */
13
- seconds: number;
14
- /** 毫秒数 */
15
- milliseconds: number;
16
- };
17
-
18
- type _TTimeParsePoint = 'D' | 'h' | 'm' | 's' | 'S';
19
-
20
- /**
21
- * 解析时间毫秒数为绝对时间对象
22
- * @param timeMs 时间毫秒数
23
- * @param maxPoint 最大时间单位(决定分解的起始单位)
24
- * @returns 包含时间单位分解结果的对象
25
- * @example
26
- * ```typescript
27
- * // 默认以天为最大单位分解
28
- * timeInDay(123456789);
29
- * // { days: 1, hours: 10, minutes: 17, seconds: 36, milliseconds: 789 }
30
- *
31
- * // 指定最大单位为分钟,分解到分钟及以下单位
32
- * timeInMinute(123456789);
33
- * // { days: 0, hours: 0, minutes: 2057, seconds: 36, milliseconds: 789 }
34
- * ```
35
- */
36
- function _timeAbsolute(timeMs: number, maxPoint: _TTimeParsePoint): TTimeDuration {
37
- const minPoint: _TTimeParsePoint = 'S';
38
-
39
- const defines: [point: _TTimeParsePoint, key: keyof TTimeDuration, base: number][] = [
40
- ['D', 'days', DATE_DAY_MS],
41
- ['h', 'hours', DATE_HOUR_MS],
42
- ['m', 'minutes', DATE_MINUTE_MS],
43
- ['s', 'seconds', DATE_SECOND_MS],
44
- ['S', 'milliseconds', 1],
45
- ] as const;
46
-
47
- const minIndex = defines.findIndex((item) => item[0] === maxPoint);
48
- const maxIndex = defines.findIndex((item) => item[0] === minPoint);
49
-
50
- let timeMsFinal = timeMs;
51
- const dao: TTimeDuration = {
52
- years: 0,
53
- months: 0,
54
- days: 0,
55
- hours: 0,
56
- minutes: 0,
57
- seconds: 0,
58
- milliseconds: 0,
59
- };
60
-
61
- for (let i = minIndex; i <= maxIndex; i++) {
62
- const mode = defines[i];
63
- const base = mode[2];
64
- const value = Math.floor(timeMsFinal / base);
65
- timeMsFinal = timeMsFinal - value * base;
66
- dao[mode[1]] = value;
67
- }
68
-
69
- return dao;
70
- }
71
-
72
- /**
73
- * 将时间毫秒数解析为以天为最大单位的绝对时间对象
74
- * @param timeMs 时间毫秒数
75
- * @returns 包含天/小时/分钟/秒/毫秒分解结果的对象
76
- */
77
- export function timeToDays(timeMs: number) {
78
- return _timeAbsolute(timeMs, 'D');
79
- }
80
-
81
- /**
82
- * 将时间毫秒数解析为以小时为最大单位的绝对时间对象
83
- * @param timeMs 时间毫秒数
84
- * @returns 包含小时/分钟/秒/毫秒分解结果的对象
85
- */
86
- export function timeToHours(timeMs: number) {
87
- return _timeAbsolute(timeMs, 'h');
88
- }
89
-
90
- /**
91
- * 将时间毫秒数解析为以分钟为最大单位的绝对时间对象
92
- * @param timeMs 时间毫秒数
93
- * @returns 包含分钟/秒/毫秒分解结果的对象
94
- */
95
- export function timeToMinutes(timeMs: number) {
96
- return _timeAbsolute(timeMs, 'm');
97
- }
98
-
99
- /**
100
- * 将时间毫秒数解析为以秒为最大单位的绝对时间对象
101
- * @param timeMs 时间毫秒数
102
- * @returns 包含秒/毫秒分解结果的对象
103
- */
104
- export function timeToSeconds(timeMs: number) {
105
- return _timeAbsolute(timeMs, 's');
106
- }
package/src/tree.ts DELETED
@@ -1,394 +0,0 @@
1
- import { arrayEach } from './array';
2
- import { isArray, isNullish, isUndefined } from './type';
3
- import type { AnyObject } from './types';
4
-
5
- /**
6
- * 表示深度遍历中的节点对象,包含子节点列表。
7
- */
8
- export type TTreeItem = AnyObject & {
9
- /**
10
- * 子节点列表。
11
- */
12
- children?: TTreeItem[];
13
- };
14
-
15
- /**
16
- * 表示深度遍历中的节点列表。
17
- *
18
- * @template I - 节点对象的类型,必须继承自 `TreeItem`。
19
- */
20
- export type TTreeList<I extends TTreeItem> = I[];
21
-
22
- /**
23
- * 表示深度遍历中的遍历器状态。
24
- *
25
- * @template I - 节点对象的类型,必须继承自 `TreeItem`。
26
- */
27
- export type TTreeWalker<I extends TTreeItem> = {
28
- /**
29
- * 当前层级的节点列表。
30
- */
31
- list: TTreeList<I>;
32
-
33
- /**
34
- * 当前节点的父节点,如果为根节点则为 `null`。
35
- */
36
- parent: I | null;
37
-
38
- /**
39
- * 当前节点的层级,从 1 开始计数。
40
- */
41
- level: number;
42
-
43
- /**
44
- * 从根节点到当前节点的路径。
45
- */
46
- path: TTreeList<I>;
47
- };
48
-
49
- /**
50
- * 表示深度遍历中的节点信息。
51
- *
52
- * @template I - 节点对象的类型,必须继承自 `TreeItem`。
53
- */
54
- export type TTreeInfo<I extends TTreeItem> = TTreeWalker<I> & {
55
- /**
56
- * 当前节点。
57
- */
58
- item: I;
59
-
60
- /**
61
- * 当前节点在 `list` 中的索引。
62
- */
63
- index: number;
64
- };
65
-
66
- /**
67
- * 深度遍历的同步迭代器函数类型。
68
- *
69
- * @template I - 节点对象的类型,必须继承自 `TreeItem`。
70
- * @param info - 当前节点的信息。
71
- * @returns 如果返回 `false`,则提前终止遍历。
72
- */
73
- export type TreeEachIterator<I extends TTreeItem> = (info: TTreeInfo<I>) => false | unknown;
74
-
75
- /**
76
- * 深度遍历的异步迭代器函数类型。
77
- *
78
- * @template I - 节点对象的类型,必须继承自 `TreeItem`。
79
- * @param info - 当前节点的信息。
80
- * @returns 如果返回 `false`,则提前终止遍历。
81
- */
82
- export type TreeEachIteratorAsync<I extends TTreeItem> = (info: TTreeInfo<I>) => Promise<boolean | unknown>;
83
-
84
- /**
85
- * 深度遍历的同步遍历器函数类型。
86
- *
87
- * @template I - 节点对象的类型,必须继承自 `TreeItem`。
88
- * @param walker - 遍历器状态。
89
- * @returns 遍历结果。
90
- */
91
- export type TreeWalk<I extends TTreeItem> = (walker: TTreeWalker<I>) => unknown;
92
-
93
- /**
94
- * 深度遍历的异步遍历器函数类型。
95
- *
96
- * @template I - 节点对象的类型,必须继承自 `TreeItem`。
97
- * @param walker - 遍历器状态。
98
- * @returns 异步遍历结果。
99
- */
100
- export type TreeWalkAsync<I extends TTreeItem> = (walker: TTreeWalker<I>) => Promise<unknown>;
101
-
102
- /**
103
- * 深度遍历数组中的每个元素,并对每个元素执行提供的回调函数。
104
- *
105
- * @param treeList - 要遍历的深度数组。
106
- * @param iterator - 对每个元素执行的回调函数。如果回调函数返回 `false`,则提前终止遍历。
107
- * @param breadthFist - 是否使用广度优先遍历,默认为 `false`(深度优先)。
108
- * @returns 无返回值。
109
- *
110
- * @example
111
- * ```typescript
112
- * const treeList = [
113
- * { value: 1, children: [{ value: 2 }, { value: 3 }] },
114
- * { value: 4 }
115
- * ];
116
- *
117
- * treeEach(treeList, (item) => {
118
- * console.log(item.value);
119
- * if (item.value === 2) return false; // 提前终止遍历
120
- * });
121
- * ```
122
- */
123
- export function treeEach<I extends TTreeItem = TTreeItem>(
124
- treeList: TTreeList<I>,
125
- iterator: TreeEachIterator<I>,
126
- breadthFist = false,
127
- ): void {
128
- const treeInfoList: TTreeInfo<I>[] = [];
129
- let returnFalse = false;
130
-
131
- const iterate = (info: TTreeInfo<I>) => {
132
- if (iterator(info) === false) {
133
- returnFalse = true;
134
- return false;
135
- }
136
- };
137
-
138
- const next = (info: TTreeInfo<I>, walk: TreeWalk<I>) => {
139
- const { item, level, parent, path } = info;
140
- const { children } = item;
141
-
142
- if (isArray(children)) {
143
- returnFalse =
144
- walk({
145
- ...info,
146
- parent: item,
147
- list: children as TTreeList<I>,
148
- level: level + 1,
149
- }) === false;
150
- }
151
- };
152
-
153
- const walk: TreeWalk<I> = (walker) => {
154
- const { list, level, parent, path } = walker;
155
-
156
- const path2 = [...path];
157
- while (parent !== null && path2.length > 0 && path2[path2.length - 1] !== parent) {
158
- path2.pop();
159
- }
160
-
161
- arrayEach(list, (item, index) => {
162
- if (returnFalse) return false;
163
-
164
- const info: TTreeInfo<I> = {
165
- ...walker,
166
- item,
167
- index,
168
- path: [...path2, item],
169
- };
170
-
171
- // 广度优先
172
- if (breadthFist) {
173
- treeInfoList.push(info);
174
- }
175
- // 深度优先
176
- else {
177
- iterate(info);
178
- if (returnFalse) return false;
179
- next(info, walk);
180
- }
181
- });
182
-
183
- if (breadthFist) {
184
- while (!returnFalse) {
185
- const info = treeInfoList.shift();
186
- if (!info) break;
187
-
188
- iterate(info);
189
- if (returnFalse) break;
190
-
191
- // 内部也会进入 walk
192
- next(info, walk);
193
- }
194
- }
195
-
196
- return !returnFalse;
197
- };
198
-
199
- walk({
200
- list: treeList,
201
- level: 1,
202
- parent: null,
203
- path: [],
204
- });
205
- }
206
-
207
- /**
208
- * 在深度数组中查找满足条件的第一个节点信息。
209
- *
210
- * @param treeList - 要查找的深度数组。
211
- * @param predicate - 判断节点是否满足条件的回调函数。
212
- * @param breadthFist - 是否使用广度优先查找,默认为 `false`(深度优先)。
213
- * @returns 如果找到满足条件的节点,则返回该节点的信息;否则返回 `undefined`。
214
- *
215
- * @example
216
- * ```typescript
217
- * const treeList = [
218
- * { value: 1, children: [{ value: 2 }, { value: 3 }] },
219
- * { value: 4 }
220
- * ];
221
- *
222
- * const found = treeFind(treeList, (info) => info.item.value === 3);
223
- * console.log(found);
224
- * // {
225
- * // item: { value: 3 },
226
- * // index: 1,
227
- * // list: [{ value: 2 }, { value: 3 }],
228
- * // parent: { value: 1, children: [{ value: 2 }, { value: 3 }] },
229
- * // level: 2,
230
- * // path: [{ value: 1, children: [{ value: 2 }, { value: 3 }] }, { value: 3 }]
231
- * // }
232
- * ```
233
- */
234
- export function treeFind<I extends TTreeItem>(
235
- treeList: TTreeList<I>,
236
- predicate: (info: TTreeInfo<I>) => boolean,
237
- breadthFist = false,
238
- ): TTreeInfo<I> | undefined {
239
- let found: TTreeInfo<I> | undefined;
240
-
241
- treeEach(
242
- treeList,
243
- (info) => {
244
- if (predicate(info)) {
245
- found = info;
246
- return false;
247
- }
248
- },
249
- breadthFist,
250
- );
251
-
252
- return found;
253
- }
254
-
255
- /**
256
- * 将深度嵌套的树形结构扁平化为一维数组,并对每个节点执行指定的转换函数。
257
- *
258
- * @template I - 树节点的类型,必须继承自 `TreeItem`。
259
- * @template T - 转换后的数据类型。
260
- * @param {TTreeList<I>} deepList - 要扁平化的深度嵌套树形结构。
261
- * @param {(info: TTreeInfo<I>) => T} flatten - 对每个节点执行的转换函数,返回转换后的数据。
262
- * @param {boolean} [breadthFist=false] - 是否使用广度优先遍历,默认为 `false`(深度优先)。
263
- * @returns {T[]} - 转换后的一维数组。
264
- * @example
265
- * ```typescript
266
- * const treeList = [
267
- * { value: 1, children: [{ value: 2 }, { value: 3 }] },
268
- * { value: 4 }
269
- * ];
270
- *
271
- * const flattened = deepFlat(treeList, (info) => info.item.value);
272
- * console.log(flattened); // [1, 2, 3, 4]
273
- * ```
274
- */
275
- export function deepFlat<I extends TTreeItem, T>(
276
- deepList: TTreeList<I>,
277
- flatten: (info: TTreeInfo<I>) => T,
278
- breadthFist = false,
279
- ): T[] {
280
- const list2: T[] = [];
281
-
282
- treeEach(
283
- deepList,
284
- (info) => {
285
- list2.push(flatten(info));
286
- },
287
- breadthFist,
288
- );
289
-
290
- return list2;
291
- }
292
-
293
- type FromItemInfo<I> = {
294
- selfKey: unknown;
295
- parentKey: unknown;
296
- item: I;
297
- index: number;
298
- };
299
-
300
- export type TTreeFromOptions<I extends TTreeItem> = {
301
- getSelfKey: (item: I, index: number) => unknown;
302
- getParentKey: (item: I, index: number) => unknown;
303
- appendChild: (parentInfo: FromItemInfo<I>, info: FromItemInfo<I>) => unknown;
304
- };
305
-
306
- /**
307
- * 从扁平列表构建树形结构。
308
- *
309
- * @template I - 节点对象的类型,必须继承自 `AnyObject`。
310
- * @param {I[]} list - 扁平化的节点列表。
311
- * @param {TTreeFromOptions<I>} options - 构建树形结构的配置选项。
312
- * @param {function} options.getSelfKey - 获取节点自身唯一标识的函数。
313
- * @param {function} options.getParentKey - 获取节点父节点唯一标识的函数。
314
- * @param {function} options.appendChild - 将子节点添加到父节点的函数。
315
- * @returns {I | undefined} - 构建的树形结构的根节点,如果未找到根节点则返回 `undefined`。
316
- *
317
- * @example
318
- * ```typescript
319
- * const list = [
320
- * { id: 1, parentId: null, name: 'Root' },
321
- * { id: 2, parentId: 1, name: 'Child 1' },
322
- * { id: 3, parentId: 1, name: 'Child 2' }
323
- * ];
324
- *
325
- * const tree = treeFrom(list, {
326
- * getSelfKey: (item) => item.id,
327
- * getParentKey: (item) => item.parentId,
328
- * appendChild: (parent, info) => {
329
- * if (!parent.children) parent.children = [];
330
- * parent.children.push(info.item);
331
- * }
332
- * });
333
- *
334
- * console.log(tree);
335
- * // {
336
- * // id: 1,
337
- * // parentId: null,
338
- * // name: 'Root',
339
- * // children: [
340
- * // { id: 2, parentId: 1, name: 'Child 1' },
341
- * // { id: 3, parentId: 1, name: 'Child 2' }
342
- * // ]
343
- * // }
344
- * ```
345
- */
346
- export function treeFrom<I extends TTreeItem>(list: I[], options: TTreeFromOptions<I>): TTreeList<I> | undefined {
347
- const keyMap = new Map<unknown, FromItemInfo<I>>();
348
- const freeSet = new Set<FromItemInfo<I>>();
349
- const roots: TTreeList<I> = [];
350
-
351
- // 分配节点
352
- const assign = (info: FromItemInfo<I>, isFirst = false) => {
353
- const { selfKey, parentKey, item, index } = info;
354
-
355
- // 父级指向为空
356
- if (isNullish(parentKey)) {
357
- roots.push(item);
358
- }
359
- // 父级指向不为空
360
- else {
361
- const parent = keyMap.get(parentKey);
362
-
363
- // 未找到父级节点
364
- if (isUndefined(parent)) {
365
- // 游离节点
366
- if (isFirst) freeSet.add(info);
367
- }
368
- // 已找到父级节点
369
- else {
370
- options.appendChild(parent, info);
371
- }
372
- }
373
- };
374
-
375
- // 构建 map
376
- arrayEach(list, (item, index) => {
377
- const selfKey = options.getSelfKey(item, index);
378
- const parentKey = options.getParentKey(item, index);
379
-
380
- if (isNullish(selfKey)) return;
381
-
382
- const info = { selfKey, parentKey, item, index };
383
- keyMap.set(selfKey, info);
384
-
385
- assign(info, true);
386
- });
387
-
388
- // 处理游离节点
389
- for (const info of freeSet.values()) {
390
- assign(info);
391
- }
392
-
393
- return roots;
394
- }