@pawover/kit 0.0.0-beta.4 → 0.0.0-beta.40

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 (40) hide show
  1. package/dist/enums-BL6w5-mS.js +148 -0
  2. package/dist/enums-BL6w5-mS.js.map +1 -0
  3. package/dist/enums.d.ts +2 -25
  4. package/dist/enums.js +2 -24
  5. package/dist/except-MacUK44u.d.ts +971 -0
  6. package/dist/except-MacUK44u.d.ts.map +1 -0
  7. package/dist/hooks-alova.d.ts +23 -14
  8. package/dist/hooks-alova.d.ts.map +1 -1
  9. package/dist/hooks-alova.js +54 -24
  10. package/dist/hooks-alova.js.map +1 -1
  11. package/dist/hooks-react.d.ts +82 -42
  12. package/dist/hooks-react.d.ts.map +1 -1
  13. package/dist/hooks-react.js +83 -260
  14. package/dist/hooks-react.js.map +1 -1
  15. package/dist/index-Bn_PNnsM.d.ts +212 -0
  16. package/dist/index-Bn_PNnsM.d.ts.map +1 -0
  17. package/dist/index-DBPmnr4a.d.ts +21 -0
  18. package/dist/index-DBPmnr4a.d.ts.map +1 -0
  19. package/dist/index.d.ts +1936 -1029
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +2 -1430
  22. package/dist/patches-fetchEventSource.d.ts +2 -721
  23. package/dist/patches-fetchEventSource.d.ts.map +1 -1
  24. package/dist/patches-fetchEventSource.js +1 -114
  25. package/dist/patches-fetchEventSource.js.map +1 -1
  26. package/dist/utils-DbMbll5L.js +2004 -0
  27. package/dist/utils-DbMbll5L.js.map +1 -0
  28. package/dist/value-of-DUmTbnuw.d.ts +26 -0
  29. package/dist/value-of-DUmTbnuw.d.ts.map +1 -0
  30. package/dist/vite.d.ts.map +1 -1
  31. package/dist/vite.js.map +1 -1
  32. package/dist/zod.d.ts +8 -1
  33. package/dist/zod.d.ts.map +1 -1
  34. package/dist/zod.js +13 -1
  35. package/dist/zod.js.map +1 -1
  36. package/metadata.json +34 -7
  37. package/package.json +31 -23
  38. package/dist/enums.d.ts.map +0 -1
  39. package/dist/enums.js.map +0 -1
  40. package/dist/index.js.map +0 -1
@@ -0,0 +1,2004 @@
1
+ import { clone, cloneDeep, cloneDeepWith } from "lodash-es";
2
+
3
+ //#region src/utils/typeof/types.ts
4
+ const PROTOTYPE_TAGS = Object.freeze({
5
+ abortSignal: "[object AbortSignal]",
6
+ array: "[object Array]",
7
+ asyncFunction: "[object AsyncFunction]",
8
+ asyncGeneratorFunction: "[object AsyncGeneratorFunction]",
9
+ bigInt: "[object BigInt]",
10
+ blob: "[object Blob]",
11
+ boolean: "[object Boolean]",
12
+ date: "[object Date]",
13
+ error: "[object Error]",
14
+ file: "[object File]",
15
+ function: "[object Function]",
16
+ generatorFunction: "[object GeneratorFunction]",
17
+ global: "[object global]",
18
+ iframe: "[object HTMLIFrameElement]",
19
+ map: "[object Map]",
20
+ null: "[object Null]",
21
+ number: "[object Number]",
22
+ object: "[object Object]",
23
+ promise: "[object Promise]",
24
+ readableStream: "[object ReadableStream]",
25
+ regExp: "[object RegExp]",
26
+ set: "[object Set]",
27
+ string: "[object String]",
28
+ symbol: "[object Symbol]",
29
+ undefined: "[object Undefined]",
30
+ URLSearchParams: "[object URLSearchParams]",
31
+ weakMap: "[object WeakMap]",
32
+ weakSet: "[object WeakSet]",
33
+ webSocket: "[object WebSocket]",
34
+ window: "[object Window]"
35
+ });
36
+ const TYPED_ARRAY_TAGS = new Set([
37
+ "[object Int8Array]",
38
+ "[object Uint8Array]",
39
+ "[object Uint8ClampedArray]",
40
+ "[object Int16Array]",
41
+ "[object Uint16Array]",
42
+ "[object Int32Array]",
43
+ "[object Uint32Array]",
44
+ "[object Float32Array]",
45
+ "[object Float64Array]",
46
+ "[object BigInt64Array]",
47
+ "[object BigUint64Array]"
48
+ ]);
49
+ function resolvePrototypeString(value) {
50
+ return Object.prototype.toString.call(value);
51
+ }
52
+
53
+ //#endregion
54
+ //#region src/utils/typeof/isAbortSignal.ts
55
+ /**
56
+ * 检查 value 是否为 AbortSignal
57
+ * @param value 待检查值
58
+ * @returns 是否为 AbortSignal
59
+ */
60
+ function isAbortSignal(value) {
61
+ return resolvePrototypeString(value) === PROTOTYPE_TAGS.abortSignal;
62
+ }
63
+
64
+ //#endregion
65
+ //#region src/utils/typeof/isArray.ts
66
+ /**
67
+ * 检查 value 是否为数组
68
+ *
69
+ * @param value 待检查值
70
+ * @returns 是否为数组
71
+ * @example
72
+ * ```ts
73
+ * isArray([]); // true
74
+ * ```
75
+ */
76
+ function isArray(value) {
77
+ return Array.isArray(value);
78
+ }
79
+ /**
80
+ * 检查 value 是否为 TypedArray
81
+ *
82
+ * @param value 待检查值
83
+ * @returns 是否为 TypedArray
84
+ * @example
85
+ * ```ts
86
+ * isTypedArray(new Int8Array()); // true
87
+ * ```
88
+ */
89
+ function isTypedArray(value) {
90
+ return typeof value === "object" && value !== null && TYPED_ARRAY_TAGS.has(resolvePrototypeString(value));
91
+ }
92
+
93
+ //#endregion
94
+ //#region src/utils/typeof/isBigInt.ts
95
+ /**
96
+ * 检查 value 是否为 BigInt
97
+ * @param value 待检查值
98
+ * @returns 是否为 BigInt
99
+ */
100
+ function isBigInt(value) {
101
+ return typeof value === "bigint";
102
+ }
103
+
104
+ //#endregion
105
+ //#region src/utils/typeof/isBlob.ts
106
+ /**
107
+ * 检查 value 是否为 Blob
108
+ * @param value 待检查值
109
+ * @returns 是否为 Blob
110
+ */
111
+ function isBlob(value) {
112
+ return resolvePrototypeString(value) === PROTOTYPE_TAGS.blob;
113
+ }
114
+ function isFile(value) {
115
+ return resolvePrototypeString(value) === PROTOTYPE_TAGS.file;
116
+ }
117
+
118
+ //#endregion
119
+ //#region src/utils/typeof/isBoolean.ts
120
+ /**
121
+ * 检查 value 是否为 Boolean
122
+ * @param value 待检查值
123
+ * @returns 是否为 Boolean
124
+ */
125
+ function isBoolean(value) {
126
+ return typeof value === "boolean";
127
+ }
128
+
129
+ //#endregion
130
+ //#region src/utils/typeof/isFunction.ts
131
+ /**
132
+ * 检查 value 是否为 Function
133
+ * @param value 待检查值
134
+ * @returns 是否为 Function
135
+ */
136
+ function isFunction(value) {
137
+ return typeof value === "function";
138
+ }
139
+ /**
140
+ * 检查 value 是否为 AsyncFunction
141
+ * @param value 待检查值
142
+ * @returns 是否为 AsyncFunction
143
+ */
144
+ function isAsyncFunction(value) {
145
+ return isFunction(value) && resolvePrototypeString(value) === PROTOTYPE_TAGS.asyncFunction;
146
+ }
147
+ /**
148
+ * 检查 value 是否为 GeneratorFunction
149
+ * @param value 待检查值
150
+ * @returns 是否为 GeneratorFunction
151
+ */
152
+ function isGeneratorFunction(value) {
153
+ return isFunction(value) && resolvePrototypeString(value) === PROTOTYPE_TAGS.generatorFunction;
154
+ }
155
+ /**
156
+ * 检查 value 是否为 AsyncGeneratorFunction
157
+ * @param value 待检查值
158
+ * @returns 是否为 AsyncGeneratorFunction
159
+ */
160
+ function isAsyncGeneratorFunction(value) {
161
+ return isFunction(value) && resolvePrototypeString(value) === PROTOTYPE_TAGS.asyncGeneratorFunction;
162
+ }
163
+
164
+ //#endregion
165
+ //#region src/utils/typeof/isClass.ts
166
+ function isConstructable(fn) {
167
+ try {
168
+ Reflect.construct(fn, []);
169
+ return true;
170
+ } catch {
171
+ return false;
172
+ }
173
+ }
174
+ /**
175
+ * 检查 value 是否为 Class
176
+ *
177
+ * @param value 待检查值
178
+ * @returns 是否为 Class
179
+ * @example
180
+ * ```ts
181
+ * class A {}
182
+ * isClass(A); // true
183
+ * isClass(() => {}); // false
184
+ * ```
185
+ */
186
+ function isClass(value) {
187
+ return isFunction(value) && !isAsyncFunction(value) && Function.prototype.toString.call(value).startsWith("class ") && isConstructable(value) && value.prototype !== void 0;
188
+ }
189
+
190
+ //#endregion
191
+ //#region src/utils/typeof/isDate.ts
192
+ /**
193
+ * 检查 value 是否为 Date 对象
194
+ *
195
+ * @param value 待检查值
196
+ * @param invalidCheck 是否要求日期有效(非 Invalid Date)。默认 true
197
+ * - true: 仅当是有效 Date 对象时返回 true(排除 new Date('invalid'))
198
+ * - false: 只要 [[Prototype]] 是 Date 即返回 true(包含 Invalid Date)
199
+ * @returns 是否为 Date 对象,根据 invalidCheck 返回不同语义的 Date 判定
200
+ *
201
+ * @example
202
+ * ```ts
203
+ * isDate(new Date()); // true
204
+ * isDate(new Date('invalid')); // false
205
+ * isDate(new Date('invalid'), false); // true
206
+ * isDate(null); // false
207
+ * isDate({}); // false
208
+ * ```
209
+ */
210
+ function isDate(value, invalidCheck = true) {
211
+ if (!value || typeof value !== "object") return false;
212
+ if (resolvePrototypeString(value) !== PROTOTYPE_TAGS.date) return false;
213
+ if (!invalidCheck) return true;
214
+ try {
215
+ const time = value.getTime();
216
+ return typeof time === "number" && !Number.isNaN(time);
217
+ } catch {
218
+ return false;
219
+ }
220
+ }
221
+
222
+ //#endregion
223
+ //#region src/utils/typeof/isEnumeration.ts
224
+ /**
225
+ * 判断一个对象是否为有效的枚举
226
+ * - 枚举成员不能为空
227
+ * - 枚举成员的键不能具有数值名
228
+ * - 枚举成员的值必须类型一致且为 `string` 或 `number` 类型
229
+ * - 枚举成员的值不能重复
230
+ * - 枚举成员的值必须全部为双向映射或非双向映射
231
+ *
232
+ * @param enumeration 待检查值
233
+ * @returns [是否为有效的枚举, 是否为双向枚举]
234
+ */
235
+ function isEnumeration(enumeration) {
236
+ if (typeof enumeration !== "object" || enumeration === null) return [false, false];
237
+ const keys = Object.keys(enumeration);
238
+ if (keys.length === 0) return [false, false];
239
+ const originalKeys = [];
240
+ const numericKeys = [];
241
+ for (const key of keys) if (/^\d+$/.test(key)) numericKeys.push(key);
242
+ else originalKeys.push(key);
243
+ if (originalKeys.length === 0) return [false, false];
244
+ let valueType = null;
245
+ const values = [];
246
+ for (const key of originalKeys) {
247
+ const value = enumeration[key];
248
+ const type = typeof value;
249
+ if (type !== "string" && type !== "number") return [false, false];
250
+ if (valueType === null) valueType = type;
251
+ else if (type !== valueType) return [false, false];
252
+ values.push(value);
253
+ }
254
+ if (new Set(values).size !== values.length) return [false, false];
255
+ let isBidirectional = false;
256
+ if (numericKeys.length > 0) {
257
+ if (numericKeys.length !== originalKeys.length) return [false, false];
258
+ const reverseMappedNames = /* @__PURE__ */ new Set();
259
+ for (const numKey of numericKeys) {
260
+ const reverseValue = enumeration[numKey];
261
+ if (typeof reverseValue !== "string") return [false, false];
262
+ if (!originalKeys.includes(reverseValue)) return [false, false];
263
+ reverseMappedNames.add(reverseValue);
264
+ }
265
+ if (reverseMappedNames.size !== originalKeys.length) return [false, false];
266
+ isBidirectional = true;
267
+ }
268
+ return [true, isBidirectional];
269
+ }
270
+
271
+ //#endregion
272
+ //#region src/utils/typeof/isEqual.ts
273
+ /**
274
+ * 深度比较两个值是否相等
275
+ *
276
+ * @param value 待比较值 A
277
+ * @param other 待比较值 B
278
+ * @returns 是否相等
279
+ * @example
280
+ * ```ts
281
+ * isEqual({ a: 1 }, { a: 1 }); // true
282
+ * ```
283
+ */
284
+ function isEqual(x, y) {
285
+ const seen = /* @__PURE__ */ new WeakMap();
286
+ function _isEqual(a, b) {
287
+ if (Object.is(a, b)) return true;
288
+ if (isDate(a) && isDate(b)) return a.getTime() === b.getTime();
289
+ if (isRegExp(a) && isRegExp(b)) return a.toString() === b.toString();
290
+ if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
291
+ if (seen.has(a)) {
292
+ if (seen.get(a).has(b)) return true;
293
+ } else seen.set(a, /* @__PURE__ */ new Set());
294
+ seen.get(a).add(b);
295
+ const keysA = Reflect.ownKeys(a);
296
+ const keysB = Reflect.ownKeys(b);
297
+ if (keysA.length !== keysB.length) return false;
298
+ for (const key of keysA) {
299
+ if (!Reflect.has(b, key)) return false;
300
+ if (!_isEqual(a[key], b[key])) return false;
301
+ }
302
+ return true;
303
+ }
304
+ return _isEqual(x, y);
305
+ }
306
+
307
+ //#endregion
308
+ //#region src/utils/typeof/isError.ts
309
+ /**
310
+ * 检查 value 是否为 Error 对象
311
+ * @param value 待检查值
312
+ * @returns 是否为 Error
313
+ */
314
+ function isError(value) {
315
+ return value instanceof Error || resolvePrototypeString(value) === PROTOTYPE_TAGS.error;
316
+ }
317
+
318
+ //#endregion
319
+ //#region src/utils/typeof/isFalsy.ts
320
+ /**
321
+ * 检查 value 是否为 Falsy 值 (false, 0, "", null, undefined, NaN)
322
+ * @param value 待检查值
323
+ * @returns 是否为 Falsy
324
+ */
325
+ function isFalsy(value) {
326
+ if (isNaN(value) || isNull(value) || isUndefined(value)) return true;
327
+ return value === false || value === 0 || value === 0n || value === "";
328
+ }
329
+ function isFalsyLike(value) {
330
+ if (isFalsy(value)) return true;
331
+ return typeof value === "string" && (value === "null" || value === "undefined" || value === "NaN" || value === "false" || value === "0" || value === "-0" || value === "0n");
332
+ }
333
+
334
+ //#endregion
335
+ //#region src/utils/typeof/isIframe.ts
336
+ /**
337
+ * 检查 value 是否为 HTMLIFrameElement
338
+ * @param value 待检查值
339
+ * @returns 是否为 HTMLIFrameElement
340
+ */
341
+ function isIframe(value) {
342
+ if (typeof window === "undefined") return false;
343
+ return resolvePrototypeString(value) === PROTOTYPE_TAGS.iframe;
344
+ }
345
+ function isInIframe() {
346
+ if (typeof window === "undefined") return false;
347
+ try {
348
+ return window.top !== window.self;
349
+ } catch (error) {
350
+ if (error.name === "SecurityError") return true;
351
+ return false;
352
+ }
353
+ }
354
+
355
+ //#endregion
356
+ //#region src/utils/typeof/isIterable.ts
357
+ /**
358
+ * 检查 value 是否为可迭代对象 (Iterable)
359
+ * @param value 待检查值
360
+ * @returns 是否为 Iterable
361
+ */
362
+ function isIterable(value) {
363
+ return !!value && typeof value[Symbol.iterator] === "function";
364
+ }
365
+
366
+ //#endregion
367
+ //#region src/utils/typeof/isMap.ts
368
+ /**
369
+ * 检查 value 是否为 Map
370
+ * @param value 待检查值
371
+ * @returns 是否为 Map
372
+ */
373
+ function isMap(value) {
374
+ return resolvePrototypeString(value) === PROTOTYPE_TAGS.map;
375
+ }
376
+ /**
377
+ * 检查 value 是否为 WeakMap
378
+ * @param value 待检查值
379
+ * @returns 是否为 WeakMap
380
+ */
381
+ function isWeakMap(value) {
382
+ return resolvePrototypeString(value) === PROTOTYPE_TAGS.weakMap;
383
+ }
384
+
385
+ //#endregion
386
+ //#region src/utils/typeof/isNull.ts
387
+ /**
388
+ * 检查 value 是否为 null
389
+ * @param value 待检查值
390
+ * @returns 是否为 null
391
+ */
392
+ function isNull(value) {
393
+ return value === null;
394
+ }
395
+
396
+ //#endregion
397
+ //#region src/utils/typeof/isNumber.ts
398
+ /**
399
+ * 检查 value 是否为 number 类型
400
+ *
401
+ * @param value 待检查值
402
+ * @param NaNCheck 是否排除 `NaN`,默认为 `true`
403
+ * @returns 是否为 number
404
+ * @example
405
+ * ```ts
406
+ * isNumber(1); // true
407
+ * isNumber(NaN); // false (default)
408
+ * isNumber(NaN, false); // true
409
+ * ```
410
+ */
411
+ function isNumber(value, NaNCheck = true) {
412
+ return typeof value === "number" && (!NaNCheck || !isNaN(value));
413
+ }
414
+ /**
415
+ * 检查 value 是否为 NaN
416
+ *
417
+ * @param value 待检查值
418
+ * @returns 是否为 NaN
419
+ */
420
+ function isNaN(value) {
421
+ return Number.isNaN(value);
422
+ }
423
+ /**
424
+ * 检查 value 是否为整数
425
+ *
426
+ * @param value 待检查值
427
+ * @param safeCheck 是否附加安全整数检查
428
+ * @returns 是否为整数
429
+ */
430
+ function isInteger(value, safeCheck = true) {
431
+ const check = Number.isInteger(value);
432
+ return safeCheck ? check && Number.isSafeInteger(value) : check;
433
+ }
434
+ /**
435
+ * 检查 value 是否为正整数
436
+ * - 此函数中 `0` 不被视为正整数
437
+ *
438
+ * @param value 待检查值
439
+ * @param safeCheck 是否附加安全整数检查
440
+ */
441
+ function isPositiveInteger(value, safeCheck = true) {
442
+ return isInteger(value, safeCheck) && value > 0;
443
+ }
444
+ /**
445
+ * 检查 value 是否为负整数
446
+ * - 此函数中 `0` 不被视为负整数
447
+ *
448
+ * @param value 待检查值
449
+ * @param safeCheck 是否附加安全整数检查
450
+ */
451
+ function isNegativeInteger(value, safeCheck = true) {
452
+ return isInteger(value, safeCheck) && value < 0;
453
+ }
454
+ /**
455
+ * 检查 value 是否为 Infinity
456
+ * - 排除 `NaN`
457
+ *
458
+ * @param value 待检查值
459
+ */
460
+ function isInfinity(value) {
461
+ return isNumber(value) && (Number.POSITIVE_INFINITY === value || Number.NEGATIVE_INFINITY === value);
462
+ }
463
+ /**
464
+ * 检查 value 是否类似 Infinity
465
+ * - 排除 `NaN`
466
+ *
467
+ * @param value 待检查值
468
+ */
469
+ function isInfinityLike(value) {
470
+ const check = isInfinity(value);
471
+ if (check) return check;
472
+ if (typeof value === "string") {
473
+ const v = value.trim().toLowerCase();
474
+ return v === "infinity" || v === "-infinity" || v === "+infinity";
475
+ }
476
+ return false;
477
+ }
478
+
479
+ //#endregion
480
+ //#region src/utils/typeof/isObject.ts
481
+ /**
482
+ * 判断是否为普通对象类型
483
+ * - 可选是否检查原型为 `Object.prototype`,防止原型链污染
484
+ *
485
+ * @param value 待检查值
486
+ * @param prototypeCheck 是否进行原型检查,默认 `true`
487
+ * @returns 是否为 Plain Object (当 checkPrototype=true) 或 object
488
+ * @example
489
+ * ```ts
490
+ * isObject({}); // true
491
+ * isObject([]); // false
492
+ * isObject(new Date()); // false (because prototype is not Object.prototype)
493
+ * isObject(new Date(), false); // true (is object type)
494
+ * isObject(Object.create(null)) // false
495
+ * isObject(Object.create(null), false) // true
496
+ * ```
497
+ */
498
+ function isObject(value, prototypeCheck = true) {
499
+ const check = resolvePrototypeString(value) === PROTOTYPE_TAGS.object;
500
+ return prototypeCheck ? check && Object.getPrototypeOf(value) === Object.prototype : check;
501
+ }
502
+
503
+ //#endregion
504
+ //#region src/utils/typeof/isPromise.ts
505
+ /**
506
+ * 检查 value 是否为 Promise
507
+ * @param value 待检查值
508
+ * @returns 是否为 Promise
509
+ */
510
+ function isPromise(value) {
511
+ return resolvePrototypeString(value) === PROTOTYPE_TAGS.promise;
512
+ }
513
+ /**
514
+ * 检查 value 是否为 PromiseLike (thenable)
515
+ * @param value 待检查值
516
+ * @returns 是否为 PromiseLike
517
+ */
518
+ function isPromiseLike(value) {
519
+ return isPromise(value) || isObject(value) && isFunction(value["then"]);
520
+ }
521
+
522
+ //#endregion
523
+ //#region src/utils/typeof/isReadableStream.ts
524
+ /**
525
+ * 检查 value 是否为 ReadableStream
526
+ * - Uses `Object.prototype.toString` where supported (modern browsers, Node.js ≥18).
527
+ * - Falls back to duck-typing in older environments.
528
+ * - Resistant to basic forgery, but not 100% secure in all polyfill scenarios.
529
+ * - ⚠️ Note: In older Node.js (<18) or with non-compliant polyfills, this may return false positives or negatives.
530
+ *
531
+ * @param value 待检查值
532
+ * @returns 是否为 ReadableStream
533
+ */
534
+ function isReadableStream(value) {
535
+ if (resolvePrototypeString(value) === PROTOTYPE_TAGS.readableStream) return true;
536
+ return isObject(value) && isFunction(value["getReader"]) && isFunction(value["pipeThrough"]);
537
+ }
538
+
539
+ //#endregion
540
+ //#region src/utils/typeof/isString.ts
541
+ /**
542
+ * 检查 value 是否为 string 类型
543
+ *
544
+ * @param value 待检查值
545
+ * @param checkEmpty 是否排除空字符串
546
+ * @returns 是否为字符串
547
+ * @example
548
+ * ```ts
549
+ * isString("abc"); // true
550
+ * isString(""); // true
551
+ * isString("", true); // false
552
+ * ```
553
+ */
554
+ function isString(value, checkEmpty = false) {
555
+ return typeof value === "string" && (!checkEmpty || !!value.length);
556
+ }
557
+
558
+ //#endregion
559
+ //#region src/utils/typeof/isRegExp.ts
560
+ /**
561
+ * 检查 value 是否为 RegExp
562
+ * @param value 待检查值
563
+ * @returns 是否为 RegExp
564
+ */
565
+ function isRegExp(value) {
566
+ if (typeof value !== "object" || value === null) return false;
567
+ try {
568
+ const regex = value;
569
+ return resolvePrototypeString(value) === PROTOTYPE_TAGS.regExp && isString(regex.source) && isString(regex.flags) && isBoolean(regex.global) && isFunction(regex.test);
570
+ } catch (error) {
571
+ return false;
572
+ }
573
+ }
574
+
575
+ //#endregion
576
+ //#region src/utils/typeof/isSet.ts
577
+ /**
578
+ * 检查 value 是否为 Set
579
+ * @param value 待检查值
580
+ * @returns 是否为 Set
581
+ */
582
+ function isSet(value) {
583
+ return resolvePrototypeString(value) === PROTOTYPE_TAGS.set;
584
+ }
585
+ /**
586
+ * 检查 value 是否为 WeakSet
587
+ * @param value 待检查值
588
+ * @returns 是否为 WeakSet
589
+ */
590
+ function isWeakSet(value) {
591
+ return resolvePrototypeString(value) === PROTOTYPE_TAGS.weakSet;
592
+ }
593
+
594
+ //#endregion
595
+ //#region src/utils/typeof/isSymbol.ts
596
+ /**
597
+ * 检查 value 是否为 Symbol
598
+ * @param value 待检查值
599
+ * @returns 是否为 Symbol
600
+ */
601
+ function isSymbol(value) {
602
+ return typeof value === "symbol";
603
+ }
604
+
605
+ //#endregion
606
+ //#region src/utils/typeof/isUndefined.ts
607
+ /**
608
+ * 检查 value 是否为 undefined
609
+ * @param value 待检查值
610
+ * @returns 是否为 undefined
611
+ */
612
+ function isUndefined(value) {
613
+ return typeof value === "undefined";
614
+ }
615
+
616
+ //#endregion
617
+ //#region src/utils/typeof/isURLSearchParams.ts
618
+ /**
619
+ * 检查 value 是否为 URLSearchParams
620
+ * @param value 待检查值
621
+ * @returns 是否为 URLSearchParams
622
+ */
623
+ function isURLSearchParams(value) {
624
+ return resolvePrototypeString(value) === PROTOTYPE_TAGS.URLSearchParams;
625
+ }
626
+
627
+ //#endregion
628
+ //#region src/utils/typeof/isWebSocket.ts
629
+ /**
630
+ * 检查 value 是否为 WebSocket
631
+ * @param value 待检查值
632
+ * @returns 是否为 WebSocket
633
+ */
634
+ function isWebSocket(value) {
635
+ return resolvePrototypeString(value) === PROTOTYPE_TAGS.webSocket;
636
+ }
637
+
638
+ //#endregion
639
+ //#region src/utils/typeof/isWindow.ts
640
+ /**
641
+ * 检查 value 是否为 Window
642
+ * @param value 待检查值
643
+ * @returns 是否为 Window
644
+ */
645
+ function isWindow(value) {
646
+ return resolvePrototypeString(value) === PROTOTYPE_TAGS.window;
647
+ }
648
+
649
+ //#endregion
650
+ //#region src/utils/array/arrayCast.ts
651
+ function arrayCast(candidate, checkEmpty = true) {
652
+ if (checkEmpty && (isUndefined(candidate) || isNull(candidate))) return [];
653
+ return isArray(candidate) ? [...candidate] : [candidate];
654
+ }
655
+
656
+ //#endregion
657
+ //#region src/utils/array/arrayCompete.ts
658
+ /**
659
+ * 数组竞争
660
+ * - 返回在匹配函数的比较条件中获胜的最终项目,适用于更复杂的最小值/最大值计算
661
+ *
662
+ * @param initialList 数组
663
+ * @param match 匹配函数
664
+ * @returns 获胜的元素,如果数组为空或参数无效则返回 `null`
665
+ * @example
666
+ * ```ts
667
+ * const list = [1, 10, 5];
668
+ * arrayCompete(list, (a, b) => (a > b ? a : b)); // 10
669
+ * arrayCompete(list, (a, b) => (a < b ? a : b)); // 1
670
+ * ```
671
+ */
672
+ function arrayCompete(initialList, match) {
673
+ if (!isArray(initialList) || initialList.length === 0 || !isFunction(match)) return null;
674
+ return initialList.reduce(match);
675
+ }
676
+
677
+ //#endregion
678
+ //#region src/utils/array/arrayCounting.ts
679
+ /**
680
+ * 统计数组的项目出现次数
681
+ * - 通过给定的标识符匹配函数,返回一个对象,其中键是回调函数返回的 key 值,每个值是一个整数,表示该 key 出现的次数
682
+ *
683
+ * @param initialList 初始数组
684
+ * @param match 匹配函数
685
+ * @returns 统计对象
686
+ * @example
687
+ * ```ts
688
+ * const list = ["a", "b", "a", "c"];
689
+ * arrayCounting(list, (x) => x); // { a: 2, b: 1, c: 1 }
690
+ *
691
+ * const users = [{ id: 1, group: "A" }, { id: 2, group: "B" }, { id: 3, group: "A" }];
692
+ * arrayCounting(users, (u) => u.group); // { A: 2, B: 1 }
693
+ * ```
694
+ */
695
+ function arrayCounting(initialList, match) {
696
+ if (!isArray(initialList) || !isFunction(match)) return {};
697
+ return initialList.reduce((prev, curr, index) => {
698
+ const id = match(curr, index).toString();
699
+ prev[id] = (prev[id] ?? 0) + 1;
700
+ return prev;
701
+ }, {});
702
+ }
703
+
704
+ //#endregion
705
+ //#region src/utils/array/arrayDifference.ts
706
+ /**
707
+ * 求数组差集
708
+ * - 返回在 `initialList` 中存在,但在 `diffList` 中不存在的元素
709
+ *
710
+ * @param initialList 初始数组
711
+ * @param diffList 对比数组
712
+ * @param match 匹配函数
713
+ * @returns 差集数组
714
+ * @example
715
+ * ```ts
716
+ * arrayDifference([1, 2, 3], [2, 3, 4]); // [1]
717
+ * arrayDifference([{ id: 1 }, { id: 2 }], [{ id: 2 }], (x) => x.id); // [{ id: 1 }]
718
+ * ```
719
+ */
720
+ function arrayDifference(initialList, diffList, match) {
721
+ if (!isArray(initialList) && !isArray(diffList)) return [];
722
+ if (!isArray(initialList) || !initialList.length) return [];
723
+ if (!isArray(diffList) || !diffList.length) return [...initialList];
724
+ if (!isFunction(match)) {
725
+ const arraySet = new Set(diffList);
726
+ return Array.from(new Set(initialList.filter((item) => !arraySet.has(item))));
727
+ }
728
+ const map = /* @__PURE__ */ new Map();
729
+ diffList.forEach((item, index) => {
730
+ map.set(match(item, index), true);
731
+ });
732
+ return initialList.filter((item, index) => !map.get(match(item, index)));
733
+ }
734
+
735
+ //#endregion
736
+ //#region src/utils/array/arrayFirst.ts
737
+ function arrayFirst(initialList, saveValue) {
738
+ if (!isArray(initialList) || initialList.length === 0) return saveValue;
739
+ return initialList[0];
740
+ }
741
+
742
+ //#endregion
743
+ //#region src/utils/array/arrayFork.ts
744
+ /**
745
+ * 数组分组过滤
746
+ * - 给定一个数组和一个条件,返回一个由两个数组组成的元组,其中第一个数组包含所有满足条件的项,第二个数组包含所有不满足条件的项
747
+ *
748
+ * @param initialList 初始数组
749
+ * @param match 条件匹配函数
750
+ * @returns [满足条件的项[], 不满足条件的项[]]
751
+ * @example
752
+ * ```ts
753
+ * arrayFork([1, 2, 3, 4], (n) => n % 2 === 0); // [[2, 4], [1, 3]]
754
+ * ```
755
+ */
756
+ function arrayFork(initialList, match) {
757
+ const forked = [[], []];
758
+ if (isArray(initialList)) initialList.forEach((item, index) => {
759
+ forked[match(item, index) ? 0 : 1].push(item);
760
+ });
761
+ return forked;
762
+ }
763
+
764
+ //#endregion
765
+ //#region src/utils/array/arrayIntersection.ts
766
+ function arrayIntersection(initialList, diffList, match) {
767
+ if (!isArray(initialList) || !isArray(diffList)) return [];
768
+ if (!initialList.length || !diffList.length) return [];
769
+ if (!isFunction(match)) {
770
+ const diffSet = new Set(diffList);
771
+ return initialList.filter((item) => diffSet.has(item));
772
+ }
773
+ const diffKeys = new Set(diffList.map((item, index) => match(item, index)));
774
+ return initialList.filter((item, index) => diffKeys.has(match(item, index)));
775
+ }
776
+
777
+ //#endregion
778
+ //#region src/utils/array/arrayLast.ts
779
+ function arrayLast(initialList, saveValue) {
780
+ if (!isArray(initialList) || initialList.length === 0) return saveValue;
781
+ return initialList[initialList.length - 1];
782
+ }
783
+
784
+ //#endregion
785
+ //#region src/utils/array/arrayMerge.ts
786
+ function arrayMerge(initialList, mergeList, match) {
787
+ if (!isArray(initialList)) return [];
788
+ if (!isArray(mergeList)) return [...initialList];
789
+ if (!isFunction(match)) return Array.from(new Set([...initialList, ...mergeList]));
790
+ const keys = /* @__PURE__ */ new Map();
791
+ mergeList.forEach((item, index) => {
792
+ keys.set(match(item, index), item);
793
+ });
794
+ return initialList.map((prevItem, index) => {
795
+ const key = match(prevItem, index);
796
+ return keys.has(key) ? keys.get(key) : prevItem;
797
+ });
798
+ }
799
+
800
+ //#endregion
801
+ //#region src/utils/array/arrayPick.ts
802
+ function arrayPick(initialList, filter, mapper) {
803
+ if (!isArray(initialList)) return [];
804
+ if (!isFunction(filter)) return [...initialList];
805
+ const hasMapper = isFunction(mapper);
806
+ return initialList.reduce((prev, curr, index) => {
807
+ if (!filter(curr, index)) return prev;
808
+ if (hasMapper) prev.push(mapper(curr, index));
809
+ else prev.push(curr);
810
+ return prev;
811
+ }, []);
812
+ }
813
+
814
+ //#endregion
815
+ //#region src/utils/array/arrayReplace.ts
816
+ function arrayReplace(initialList, newItem, match) {
817
+ if (!isArray(initialList) || !initialList.length) return [];
818
+ if (!isFunction(match)) return [...initialList];
819
+ for (let i = 0; i < initialList.length; i++) {
820
+ const item = initialList[i];
821
+ if (match(item, i)) return [
822
+ ...initialList.slice(0, i),
823
+ newItem,
824
+ ...initialList.slice(i + 1, initialList.length)
825
+ ];
826
+ }
827
+ return [...initialList];
828
+ }
829
+
830
+ //#endregion
831
+ //#region src/utils/array/arrayReplaceMove.ts
832
+ /**
833
+ * 数组项替换并移动
834
+ * - 在给定的数组中,替换并移动符合匹配函数结果的项目
835
+ * - 只替换和移动第一个匹配项
836
+ * - 未匹配时,根据 `position` 在指定位置插入 `newItem`
837
+ *
838
+ * @param initialList 初始数组
839
+ * @param newItem 替换项
840
+ * @param match 匹配函数
841
+ * @param position 移动位置,可选 `start` | `end` | 索引位置, 默认为 `end`
842
+ * @returns
843
+ * @example
844
+ * ```ts
845
+ * arrayReplaceMove([1, 2, 3, 4], 5, (n) => n === 2, 0); // [5, 1, 3, 4]
846
+ * arrayReplaceMove([1, 2, 3, 4], 5, (n) => n === 2, 2); // [1, 3, 5, 4]
847
+ * arrayReplaceMove([1, 2, 3, 4], 5, (n) => n === 2, "start"); // [5, 1, 3, 4]
848
+ * arrayReplaceMove([1, 2, 3, 4], 5, (n) => n === 2); // [1, 3, 4, 5]
849
+ * ```
850
+ */
851
+ function arrayReplaceMove(initialList, newItem, match, position) {
852
+ if (!isArray(initialList)) return [];
853
+ if (!initialList.length) return [newItem];
854
+ if (!isFunction(match)) return [...initialList];
855
+ const result = [...initialList];
856
+ const matchIndex = initialList.findIndex(match);
857
+ if (matchIndex !== -1) result.splice(matchIndex, 1);
858
+ if (position === "start") result.unshift(newItem);
859
+ else if (position === 0 || isPositiveInteger(position, false)) result.splice(Math.min(position, result.length), 0, newItem);
860
+ else result.push(newItem);
861
+ return result;
862
+ }
863
+
864
+ //#endregion
865
+ //#region src/utils/array/arraySplit.ts
866
+ /**
867
+ * 数组切分
868
+ * - 将数组以指定的长度切分后,组合在高维数组中
869
+ *
870
+ * @param initialList 初始数组
871
+ * @param size 分割尺寸,默认 `10`
872
+ * @returns 切分后的二维数组
873
+ * @example
874
+ * ```ts
875
+ * arraySplit([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
876
+ * ```
877
+ */
878
+ function arraySplit(initialList, size = 10) {
879
+ if (!isArray(initialList)) return [];
880
+ if (!isPositiveInteger(size, false)) return [];
881
+ const count = Math.ceil(initialList.length / size);
882
+ return Array.from({ length: count }).fill(null).map((_c, i) => {
883
+ return initialList.slice(i * size, i * size + size);
884
+ });
885
+ }
886
+
887
+ //#endregion
888
+ //#region src/utils/array/arrayZip.ts
889
+ /**
890
+ * 数组解压
891
+ * - `arrayZip` 的反向操作
892
+ *
893
+ * @param arrays 压缩后的数组
894
+ * @returns 解压后的二维数组
895
+ * @example
896
+ * ```ts
897
+ * arrayUnzip([[1, "a"], [2, "b"]]); // [[1, 2], ["a", "b"]]
898
+ * ```
899
+ */
900
+ function arrayUnzip(arrays) {
901
+ if (!isArray(arrays) || !arrays.length) return [];
902
+ const out = new Array(arrays.reduce((max, arr) => Math.max(max, arr.length), 0));
903
+ let index = 0;
904
+ const get = (array) => array[index];
905
+ for (; index < out.length; index++) out[index] = Array.from(arrays, get);
906
+ return out;
907
+ }
908
+ function arrayZip(...arrays) {
909
+ return arrayUnzip(arrays);
910
+ }
911
+
912
+ //#endregion
913
+ //#region src/utils/array/arrayZipToObject.ts
914
+ function arrayZipToObject(keys, values) {
915
+ const result = {};
916
+ if (!isArray(keys) || !keys.length) return result;
917
+ const getValue = isFunction(values) ? values : isArray(values) ? (_k, i) => values[i] : (_k, _i) => values;
918
+ return keys.reduce((acc, key, idx) => {
919
+ acc[key] = getValue(key, idx);
920
+ return acc;
921
+ }, result);
922
+ }
923
+
924
+ //#endregion
925
+ //#region src/utils/device/isBrowser.ts
926
+ function isBrowser() {
927
+ return typeof window !== "undefined" && isFunction(window?.document?.createElement);
928
+ }
929
+ function isWebWorker() {
930
+ return typeof window === "undefined" && typeof self !== "undefined" && "importScripts" in self;
931
+ }
932
+
933
+ //#endregion
934
+ //#region src/utils/device/isMobile.ts
935
+ /**
936
+ * 检测当前设备是否为移动设备
937
+ *
938
+ * @param maxWidth - 移动设备最大宽度(默认 768px)
939
+ * @param dpi - 标准 DPI 基准(默认 160)
940
+ * @returns 是否为移动设备
941
+ * @example
942
+ * ```ts
943
+ * // 假设 window.innerWidth = 500
944
+ * isMobile(); // true
945
+ * ```
946
+ */
947
+ function isMobile(maxWidth = 768, dpi = 160) {
948
+ if (typeof window === "undefined" || !isPositiveInteger(maxWidth)) return false;
949
+ return !isTablet(maxWidth, 1200, dpi);
950
+ }
951
+ /**
952
+ * 检测当前设备是否为IOS移动设备
953
+ *
954
+ * @param maxWidth - 移动设备最大宽度(默认 768px)
955
+ * @param dpi - 标准 DPI 基准(默认 160)
956
+ * @returns 是否为 iOS 移动设备 (iPhone/iPad/iPod 且非平板)
957
+ * @example
958
+ * ```ts
959
+ * // UA contains iPhone
960
+ * isIOSMobile(); // true
961
+ * ```
962
+ */
963
+ function isIOSMobile(maxWidth = 768, dpi = 160) {
964
+ if (typeof navigator === "undefined" || !navigator.userAgent || !isPositiveInteger(maxWidth)) return false;
965
+ return /iPhone|iPad|iPod/i.test(navigator.userAgent) && !isTablet(maxWidth, 1200, dpi);
966
+ }
967
+
968
+ //#endregion
969
+ //#region src/utils/device/isTablet.ts
970
+ /**
971
+ * 检测当前设备是否为平板
972
+ *
973
+ * @param minWidth - 平板最小宽度(默认 768px)
974
+ * @param maxWidth - 平板最大宽度(默认 1200px)
975
+ * @param dpi - 标准 DPI 基准(默认 160)
976
+ * @returns 是否为平板设备
977
+ * @example
978
+ * ```ts
979
+ * // 假设 window.innerWidth = 1000
980
+ * isTablet(); // true
981
+ * ```
982
+ */
983
+ function isTablet(minWidth = 768, maxWidth = 1200, dpi = 160) {
984
+ if (typeof window === "undefined" || !isPositiveInteger(minWidth) || !isPositiveInteger(maxWidth)) return false;
985
+ const width = window.innerWidth;
986
+ const isWithinWidthRange = width >= minWidth && width <= maxWidth;
987
+ try {
988
+ const widthPx = window.screen.width;
989
+ const heightPx = window.screen.height;
990
+ const DPI = dpi * (window.devicePixelRatio || 1);
991
+ const widthInch = widthPx / DPI;
992
+ const heightInch = heightPx / DPI;
993
+ const screenInches = Math.sqrt(widthInch ** 2 + heightInch ** 2);
994
+ return isWithinWidthRange || screenInches >= 7;
995
+ } catch {
996
+ return isWithinWidthRange;
997
+ }
998
+ }
999
+
1000
+ //#endregion
1001
+ //#region src/utils/function/to.ts
1002
+ /**
1003
+ *将 Promise 转换为 `[err, result]` 格式,方便 async/await 错误处理
1004
+ *
1005
+ * @param promise 待处理的 Promise
1006
+ * @param errorExt 附加到 error 对象的扩展信息(注意:如果原 error 是 Error 实例,扩展属性可能会覆盖或无法正确合并非枚举属性)
1007
+ * @returns `[err, null]` 或 `[null, data]`
1008
+ * @example
1009
+ * ```ts
1010
+ * const [err, data] = await to(someAsyncFunc());
1011
+ * if (err) return;
1012
+ * console.log(data);
1013
+ * ```
1014
+ */
1015
+ function to(promise, errorExt) {
1016
+ return promise.then((data) => [null, data]).catch((err) => {
1017
+ if (errorExt) {
1018
+ const parsedError = {
1019
+ name: "",
1020
+ message: "",
1021
+ stack: ""
1022
+ };
1023
+ if (err instanceof Error) {
1024
+ parsedError.message = err.message;
1025
+ parsedError.name = err.name;
1026
+ parsedError.stack = err.stack;
1027
+ Object.getOwnPropertyNames(err).forEach((key) => {
1028
+ if (!(key in parsedError)) parsedError[key] = err[key];
1029
+ });
1030
+ } else Object.assign(parsedError, err);
1031
+ Object.assign(parsedError, errorExt);
1032
+ return [parsedError, void 0];
1033
+ }
1034
+ return [err ? err : /* @__PURE__ */ new Error("defaultError"), void 0];
1035
+ });
1036
+ }
1037
+
1038
+ //#endregion
1039
+ //#region src/utils/string/stringToNumber.ts
1040
+ const R1$2 = /[^0-9.-]/g;
1041
+ /**
1042
+ * 从字符串中提取数字字符串
1043
+ * - 移除非数字字符,保留符号和小数点
1044
+ *
1045
+ * @param input 待处理字符串
1046
+ * @returns 提取出的数字字符串
1047
+ * @example
1048
+ * ```ts
1049
+ * stringToNumber("$1,234.56"); // "1234.56"
1050
+ * stringToNumber("abc-123"); // "-123"
1051
+ * ```
1052
+ */
1053
+ function stringToNumber(input) {
1054
+ if (!isString(input, true)) return "0";
1055
+ const cleaned = input.replace(R1$2, "");
1056
+ if (!cleaned) return "0";
1057
+ let isDecimal = false;
1058
+ let signCount = 0;
1059
+ let firstIndex = -1;
1060
+ const stringList = cleaned.split("").map((s, i) => {
1061
+ if (s === ".") {
1062
+ if (isDecimal) return "";
1063
+ isDecimal = true;
1064
+ return ".";
1065
+ }
1066
+ if (s === "-") {
1067
+ firstIndex === -1 && signCount++;
1068
+ return "";
1069
+ }
1070
+ firstIndex === -1 && (firstIndex = i);
1071
+ return s;
1072
+ });
1073
+ const sign = signCount % 2 === 1 ? "-" : "";
1074
+ if (firstIndex === -1) return sign + "0";
1075
+ let result = stringList.join("");
1076
+ if (result.startsWith(".")) result = "0" + result;
1077
+ if (result.endsWith(".")) result = result.slice(0, -1);
1078
+ return sign + result;
1079
+ }
1080
+
1081
+ //#endregion
1082
+ //#region src/utils/math/mathToBignumber.ts
1083
+ /**
1084
+ * 将任意类型的值转换为 `math.bignumber`
1085
+ *
1086
+ * @param mathJsInstance mathJs 实例
1087
+ * @param value 任意类型的值
1088
+ * @param saveValue 安全值
1089
+ * @returns 转换后的 BigNumber
1090
+ * @example
1091
+ * ```ts
1092
+ * import { create, all } from "mathjs";
1093
+ * const math = create(all);
1094
+ * mathToBignumber(math, "0.1");
1095
+ * ```
1096
+ */
1097
+ function mathToBignumber(mathJsInstance, value, saveValue) {
1098
+ const errorValue = saveValue ?? mathJsInstance.bignumber(0);
1099
+ if (isFalsyLike(value) || isInfinityLike(value)) return errorValue;
1100
+ try {
1101
+ return mathJsInstance.bignumber(stringToNumber(`${value}`));
1102
+ } catch (error) {
1103
+ return errorValue;
1104
+ }
1105
+ }
1106
+
1107
+ //#endregion
1108
+ //#region src/utils/math/mathToDecimal.ts
1109
+ function mathToDecimal(mathJsInstance, value, precision, isFormat = true) {
1110
+ const bigNumber = mathToBignumber(mathJsInstance, value);
1111
+ return isFormat ? mathJsInstance.format(bigNumber, {
1112
+ notation: "fixed",
1113
+ precision
1114
+ }) : bigNumber;
1115
+ }
1116
+
1117
+ //#endregion
1118
+ //#region src/utils/math/mathToEvaluate.ts
1119
+ /**
1120
+ * 数学表达式求值
1121
+ *
1122
+ * @param mathJsInstance mathJs 实例
1123
+ * @param expr 表达式
1124
+ * @param scope 键值映射
1125
+ * @returns 计算结果的字符串表示
1126
+ * @example
1127
+ * ```ts
1128
+ * mathToEvaluate(math, "a + b", { a: 1, b: 2 }); // "3"
1129
+ * ```
1130
+ */
1131
+ function mathToEvaluate(mathJsInstance, expr, scope) {
1132
+ const evaluateValue = `${mathJsInstance.evaluate(expr, scope || {})}`;
1133
+ return mathJsInstance.format(mathToBignumber(mathJsInstance, evaluateValue), { notation: "fixed" });
1134
+ }
1135
+
1136
+ //#endregion
1137
+ //#region src/utils/number/numberWithin.ts
1138
+ /**
1139
+ * 数字区间检查函数
1140
+ *
1141
+ * @param input 待检查数字
1142
+ * @param interval 由两个数字组成的元组 [left, right]
1143
+ * @param includeLeft 是否包含左边界(默认 true)
1144
+ * @param includeRight 是否包含右边界(默认 false)
1145
+ * @returns 是否在区间内
1146
+ * @example
1147
+ * ```ts
1148
+ * numberWithin(5, [1, 10]); // true
1149
+ * numberWithin(1, [1, 10], false); // false
1150
+ * ```
1151
+ */
1152
+ function numberWithin(input, interval, includeLeft = true, includeRight = false) {
1153
+ if (!isNumber(input)) throw new Error("params [input] mast be a number.");
1154
+ if (isInfinity(input)) throw new Error("params [input] mast be a finite number.");
1155
+ const [left, right] = interval;
1156
+ if (left > right) throw new Error(`Invalid interval: left (${left}) must be <= right (${right}).`);
1157
+ if (includeLeft && includeRight) return input >= left && input <= right;
1158
+ else if (includeLeft) return input >= left && input < right;
1159
+ else if (includeRight) return input > left && input <= right;
1160
+ else return input > left && input < right;
1161
+ }
1162
+
1163
+ //#endregion
1164
+ //#region src/utils/object/enumEntries.ts
1165
+ function enumEntries(enumeration) {
1166
+ const [isEnum, isBidirectionalEnum] = isEnumeration(enumeration);
1167
+ if (!isEnum) throw Error("function enumEntries expected parameter is a enum, and requires at least one member");
1168
+ const entries = objectEntries(enumeration);
1169
+ if (isBidirectionalEnum) return entries.splice(entries.length / 2, entries.length / 2);
1170
+ return entries;
1171
+ }
1172
+
1173
+ //#endregion
1174
+ //#region src/utils/object/enumKeys.ts
1175
+ function enumKeys(enumeration) {
1176
+ const [isEnum, isBidirectionalEnum] = isEnumeration(enumeration);
1177
+ if (!isEnum) throw Error("function enumKeys expected parameter is a enum, and requires at least one member");
1178
+ const keys = objectKeys(enumeration);
1179
+ if (isBidirectionalEnum) return keys.splice(keys.length / 2, keys.length / 2);
1180
+ return keys;
1181
+ }
1182
+
1183
+ //#endregion
1184
+ //#region src/utils/object/enumValues.ts
1185
+ function enumValues(enumeration) {
1186
+ const [isEnum, isBidirectionalEnum] = isEnumeration(enumeration);
1187
+ if (!isEnum) throw Error("function enumValues expected parameter is a enum, and requires at least one member");
1188
+ const values = objectValues(enumeration);
1189
+ if (isBidirectionalEnum) return values.splice(values.length / 2, values.length / 2);
1190
+ return values;
1191
+ }
1192
+
1193
+ //#endregion
1194
+ //#region src/utils/object/objectEntries.ts
1195
+ function objectEntries(value) {
1196
+ return Object.entries(value);
1197
+ }
1198
+
1199
+ //#endregion
1200
+ //#region src/utils/object/objectMapEntries.ts
1201
+ /**
1202
+ * 映射对象条目
1203
+ * - 将对象的键值对映射为新的键值对
1204
+ *
1205
+ * @param plainObject 对象
1206
+ * @param toEntry 映射函数
1207
+ * @returns 映射后的新对象
1208
+ * @example
1209
+ * ```ts
1210
+ * const obj = { a: 1, b: 2 };
1211
+ * objectMapEntries(obj, (k, v) => [k, v * 2]); // { a: 2, b: 4 }
1212
+ * ```
1213
+ */
1214
+ function objectMapEntries(plainObject, toEntry) {
1215
+ const defaultResult = {};
1216
+ if (!isObject(plainObject)) return defaultResult;
1217
+ return objectEntries(plainObject).reduce((acc, [key, value]) => {
1218
+ const [newKey, newValue] = toEntry(key, value);
1219
+ acc[newKey] = newValue;
1220
+ return acc;
1221
+ }, defaultResult);
1222
+ }
1223
+
1224
+ //#endregion
1225
+ //#region src/utils/object/objectAssign.ts
1226
+ const OBJECT_PROTO = Object.prototype;
1227
+ /**
1228
+ * 为对象创建一个具有相同原型的新副本
1229
+ * 这个辅助函数是保留原型的关键。
1230
+ */
1231
+ function cloneWithProto(obj) {
1232
+ const proto = Object.getPrototypeOf(obj);
1233
+ return proto === OBJECT_PROTO ? { ...obj } : Object.assign(Object.create(proto), obj);
1234
+ }
1235
+ function _objectAssign(initial, override, _seen) {
1236
+ if (!isObject(initial, false) && !isObject(override, false)) return {};
1237
+ if (!isObject(initial, false)) return cloneWithProto(override);
1238
+ if (!isObject(override, false)) return cloneWithProto(initial);
1239
+ if (_seen.has(initial)) return cloneWithProto(override);
1240
+ _seen.add(initial);
1241
+ const assigned = cloneWithProto(initial);
1242
+ for (const key of Object.keys(override)) if (isObject(initial[key]) && isObject(override[key])) assigned[key] = _objectAssign(initial[key], override[key], _seen);
1243
+ else assigned[key] = override[key];
1244
+ _seen.delete(initial);
1245
+ return assigned;
1246
+ }
1247
+ function objectAssign(initial, override) {
1248
+ return _objectAssign(initial, override, /* @__PURE__ */ new WeakSet());
1249
+ }
1250
+
1251
+ //#endregion
1252
+ //#region src/utils/object/objectCrush.ts
1253
+ function objectCrush(obj) {
1254
+ if (!obj) return {};
1255
+ function crushReducer(crushed, value, path) {
1256
+ if (isObject(value) || isArray(value)) for (const [prop, propValue] of Object.entries(value)) crushReducer(crushed, propValue, path ? `${path}.${prop}` : prop);
1257
+ else crushed[path] = value;
1258
+ return crushed;
1259
+ }
1260
+ return crushReducer({}, obj, "");
1261
+ }
1262
+
1263
+ //#endregion
1264
+ //#region src/utils/object/objectInvert.ts
1265
+ function objectInvert(obj) {
1266
+ const result = {};
1267
+ if (!isObject(obj)) return result;
1268
+ for (const [k, v] of objectEntries(obj)) if (isString(v) || isNumber(v) || isSymbol(v)) result[v] = k;
1269
+ return result;
1270
+ }
1271
+
1272
+ //#endregion
1273
+ //#region src/utils/object/objectKeys.ts
1274
+ function objectKeys(value) {
1275
+ return Object.keys(value);
1276
+ }
1277
+
1278
+ //#endregion
1279
+ //#region src/utils/object/objectOmit.ts
1280
+ function objectOmit(obj, keys) {
1281
+ const result = {};
1282
+ if (!isObject(obj)) return result;
1283
+ if (!isArray(keys)) return obj;
1284
+ const keysToOmit = new Set(keys);
1285
+ return Object.keys(obj).reduce((acc, key) => {
1286
+ if (!keysToOmit.has(key)) acc[key] = obj[key];
1287
+ return acc;
1288
+ }, result);
1289
+ }
1290
+
1291
+ //#endregion
1292
+ //#region src/utils/object/objectPick.ts
1293
+ function objectPick(obj, keys) {
1294
+ const result = {};
1295
+ if (!isObject(obj)) return result;
1296
+ if (!isArray(keys)) return obj;
1297
+ return keys.reduce((acc, key) => {
1298
+ if (key in obj) acc[key] = obj[key];
1299
+ return acc;
1300
+ }, result);
1301
+ }
1302
+
1303
+ //#endregion
1304
+ //#region src/utils/object/objectValues.ts
1305
+ function objectValues(value) {
1306
+ return Object.values(value);
1307
+ }
1308
+
1309
+ //#endregion
1310
+ //#region src/utils/string/stringInitialCase.ts
1311
+ const R1$1 = /\S+/g;
1312
+ const R2 = /[^a-zA-Z\u00C0-\u017F]/;
1313
+ /**
1314
+ * 字符串首字母大小写
1315
+ * - 包含非西欧字母字符时,不处理
1316
+ * - 纯字母且全大写时,不处理
1317
+ * - 纯字母且非全大写时,首字母小写,其余保留
1318
+ * - 纯字母且非全大写时,首字母大写,其余保留
1319
+ *
1320
+ /**
1321
+ * 字符串首字母大小写
1322
+ * - 包含非西欧字母字符时,不处理
1323
+ * - 纯字母且全大写时,不处理
1324
+ * - 纯字母且非全大写时,首字母小写,其余保留
1325
+ * - 纯字母且非全大写时,首字母大写,其余保留
1326
+ *
1327
+ * @param input 待处理字符串
1328
+ * @param caseType 大小写类型
1329
+ * @returns 处理后的字符串
1330
+ * @example
1331
+ * ```ts
1332
+ * stringInitialCase("Hello", "lower"); // "hello"
1333
+ * stringInitialCase("hello", "upper"); // "Hello"
1334
+ * ```
1335
+ */
1336
+ function stringInitialCase(input, caseType) {
1337
+ if (!isString(input, true)) return "";
1338
+ return input.replace(R1$1, (word) => {
1339
+ if (R2.test(word)) return word;
1340
+ if (word === word.toLocaleUpperCase()) return word;
1341
+ if (caseType === "lower" && word[0]) return word[0].toLocaleLowerCase() + word.slice(1);
1342
+ if (caseType === "upper" && word[0]) return word[0].toLocaleUpperCase() + word.slice(1);
1343
+ return word;
1344
+ });
1345
+ }
1346
+
1347
+ //#endregion
1348
+ //#region src/utils/string/stringReplace.ts
1349
+ /**
1350
+ * 字符串替换
1351
+ * - 替换第一个匹配项
1352
+ *
1353
+ /**
1354
+ * 字符串替换
1355
+ * - 替换第一个匹配项
1356
+ *
1357
+ * @param input 待处理字符串
1358
+ * @param search 匹配项
1359
+ * @param replacement 替换项
1360
+ * @returns 替换后的字符串
1361
+ * @example
1362
+ * ```ts
1363
+ * stringReplace("hello world", "world", "context"); // "hello context"
1364
+ * ```
1365
+ */
1366
+ function stringReplace(input, search, replacement) {
1367
+ if (!isString(input, true)) return "";
1368
+ return input.replace(search, replacement);
1369
+ }
1370
+
1371
+ //#endregion
1372
+ //#region src/utils/string/stringTemplate.ts
1373
+ const R1 = /\{\{(.+?)\}\}/g;
1374
+ /**
1375
+ * 字符串模板替换
1376
+ * - 使用对象的属性值替换字符串中的 {{key}} 模板
1377
+ *
1378
+ * @param input 待处理字符串
1379
+ * @param template 模板对象
1380
+ * @param regex 模板匹配正则 (默认: `\{\{(.+?)\}\}`)
1381
+ * @returns 替换后的字符串
1382
+ * @example
1383
+ * ```ts
1384
+ * stringTemplate("Hello {{name}}", { name: "World" }); // "Hello World"
1385
+ * ```
1386
+ */
1387
+ function stringTemplate(input, template, regex = R1) {
1388
+ if (!isString(input, true)) return "";
1389
+ regex.lastIndex = 0;
1390
+ let result = "";
1391
+ let from = 0;
1392
+ let match;
1393
+ while (match = regex.exec(input)) {
1394
+ const replacement = template[match[1]];
1395
+ const valueToInsert = replacement === null || replacement === void 0 ? match[0] : replacement;
1396
+ result += input.slice(from, match.index) + valueToInsert;
1397
+ from = regex.lastIndex;
1398
+ }
1399
+ return result + input.slice(from);
1400
+ }
1401
+
1402
+ //#endregion
1403
+ //#region src/utils/string/stringToJson.ts
1404
+ /**
1405
+ * 处理 JSON 字符串
1406
+ *
1407
+ /**
1408
+ * 处理 JSON 字符串
1409
+ *
1410
+ * @param input 待处理字符串
1411
+ * @param safeValue 安全值 (当解析失败或输入无效时返回)
1412
+ * @returns 解析后的对象 或 安全值
1413
+ * @example
1414
+ * ```ts
1415
+ * stringToJson('{"a": 1}', {}); // { a: 1 }
1416
+ * stringToJson('invalid', {}); // {}
1417
+ * ```
1418
+ */
1419
+ function stringToJson(input, safeValue) {
1420
+ if (!isString(input, true)) return safeValue;
1421
+ try {
1422
+ return JSON.parse(input);
1423
+ } catch (error) {
1424
+ return safeValue;
1425
+ }
1426
+ }
1427
+
1428
+ //#endregion
1429
+ //#region src/utils/string/stringToPosix.ts
1430
+ /**
1431
+ * 将路径转换为 POSIX 风格
1432
+ * - 统一使用正斜杠 (/)
1433
+ * - 可选移除 Windows 盘符 (如 C:)
1434
+ * - 可选移除开头的斜杠
1435
+ * - 规范化连续斜杠为单个斜杠
1436
+ *
1437
+ * @param input 待处理字符串
1438
+ * @param removeLeadingSlash 是否移除开头斜杠,默认为 `false`。如果移除了盘符,路径通常会以 / 开头,此参数可控制是否保留该 /
1439
+ * @returns 转换后的路径,如果输入无效则返回空字符串
1440
+ *
1441
+ * @example
1442
+ * ```ts
1443
+ * stringToPosix("C:\\Windows\\System32");
1444
+ * // 默认: "/Windows/System32" (移除了 C: 并标准化)
1445
+ *
1446
+ * stringToPosix("C:\\Windows\\System32", true);
1447
+ * // 移除开头斜杠: "Windows/System32"
1448
+ *
1449
+ * stringToPosix("\\\\server\\share\\file.txt");
1450
+ * // UNC 路径: "/server/share/file.txt"
1451
+ *
1452
+ * stringToPosix("folder\\subfolder\\file.txt");
1453
+ * // 相对路径: "folder/subfolder/file.txt"
1454
+ * ```
1455
+ */
1456
+ function stringToPosix(input, removeLeadingSlash = false) {
1457
+ if (!isString(input, true)) return "";
1458
+ let normalized = input.replace(/^[A-Za-z]:([\\/])?/, (_, separator) => {
1459
+ return separator ? "/" : "";
1460
+ });
1461
+ normalized = normalized.replace(/\\/g, "/");
1462
+ normalized = normalized.replace(/\/+/g, "/");
1463
+ if (removeLeadingSlash && normalized.startsWith("/")) normalized = normalized.substring(1);
1464
+ return normalized;
1465
+ }
1466
+
1467
+ //#endregion
1468
+ //#region src/utils/string/stringToValues.ts
1469
+ function stringToValues(input, valueType = "number", splitSymbol = ",") {
1470
+ if (!isString(input, true)) return [];
1471
+ try {
1472
+ const values = input.split(splitSymbol);
1473
+ if (valueType === "number") return values.map((d) => Number(d));
1474
+ return values;
1475
+ } catch (error) {
1476
+ return [];
1477
+ }
1478
+ }
1479
+
1480
+ //#endregion
1481
+ //#region src/utils/string/stringTrim.ts
1482
+ /**
1483
+ * 从字符串中裁切掉所有的前缀和后缀字符
1484
+ *
1485
+ * @param input 待处理字符串
1486
+ * @param charsToTrim 裁切字符,默认为 `" "`
1487
+ * @returns 裁切后的字符串
1488
+ * @example
1489
+ * ```ts
1490
+ * stringTrim(" hello "); // "hello"
1491
+ * stringTrim("__hello__", "_"); // "hello"
1492
+ * ```
1493
+ */
1494
+ function stringTrim(input, charsToTrim = " ") {
1495
+ if (!isString(input, true)) return "";
1496
+ const toTrim = charsToTrim.replace(/[\W]{1}/g, "\\$&");
1497
+ const regex = new RegExp(`^[${toTrim}]+|[${toTrim}]+$`, "g");
1498
+ return input.replace(regex, "");
1499
+ }
1500
+
1501
+ //#endregion
1502
+ //#region src/utils/string/stringTruncate.ts
1503
+ /**
1504
+ * 截取字符串
1505
+ * - 支持自定义省略符,不会截断在汉字中间(因为JS字符串本身按字符处理)
1506
+ *
1507
+ * @param input 待处理字符串
1508
+ * @param maxLength 最大长度 (包含省略符)
1509
+ * @param ellipsis 省略符,默认为 `...`
1510
+ * @returns 截取后的字符串
1511
+ * @example
1512
+ * ```ts
1513
+ * stringTruncate("hello world", 8); // "hello..."
1514
+ * ```
1515
+ */
1516
+ function stringTruncate(input, maxLength, ellipsis = "...") {
1517
+ if (!isString(input, true)) return "";
1518
+ const codePoints = Array.from(input);
1519
+ if (!isInteger(maxLength) || maxLength < 0) return input;
1520
+ if (codePoints.length <= maxLength) return input;
1521
+ const availableLength = maxLength - ellipsis.length;
1522
+ if (availableLength <= 0) return "";
1523
+ return codePoints.slice(0, availableLength).join("") + ellipsis;
1524
+ }
1525
+
1526
+ //#endregion
1527
+ //#region src/utils/time/timeZone.ts
1528
+ /**
1529
+ * 获取当前时区信息
1530
+ *
1531
+ * @returns 时区信息对象 (UTC偏移和时区名称)
1532
+ * @example
1533
+ * ```ts
1534
+ * getTimeZone(); // { UTC: "UTC+8", timeZone: "Asia/Shanghai" }
1535
+ * ```
1536
+ */
1537
+ function getTimeZone() {
1538
+ const hour = 0 - (/* @__PURE__ */ new Date()).getTimezoneOffset() / 60;
1539
+ return {
1540
+ UTC: "UTC" + (hour >= 0 ? "+" + hour : hour),
1541
+ timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
1542
+ };
1543
+ }
1544
+
1545
+ //#endregion
1546
+ //#region src/utils/tree/types.ts
1547
+ function getFinalChildrenKey(tree, meta, options) {
1548
+ if (isFunction(options.getChildrenKey)) {
1549
+ const dynamicChildrenKey = options.getChildrenKey(tree, meta);
1550
+ if (dynamicChildrenKey && dynamicChildrenKey !== null) return dynamicChildrenKey;
1551
+ }
1552
+ return options.childrenKey;
1553
+ }
1554
+
1555
+ //#endregion
1556
+ //#region src/utils/tree/treeFilter.ts
1557
+ function preImpl$3(row, callback, options) {
1558
+ if (!callback(row, options)) return;
1559
+ const finalChildrenKey = getFinalChildrenKey(row, options, options);
1560
+ const children = row[finalChildrenKey];
1561
+ let newChildren;
1562
+ if (isArray(children)) {
1563
+ const nextLevelOptions = {
1564
+ ...options,
1565
+ parents: [...options.parents, row],
1566
+ depth: options.depth + 1
1567
+ };
1568
+ newChildren = children.map((c) => preImpl$3(c, callback, nextLevelOptions)).filter((c) => !!c);
1569
+ }
1570
+ return {
1571
+ ...row,
1572
+ [finalChildrenKey]: newChildren
1573
+ };
1574
+ }
1575
+ function postImpl$3(row, callback, options) {
1576
+ const finalChildrenKey = getFinalChildrenKey(row, options, options);
1577
+ const children = row[finalChildrenKey];
1578
+ let newChildren;
1579
+ if (isArray(children)) {
1580
+ const nextLevelOptions = {
1581
+ ...options,
1582
+ parents: [...options.parents, row],
1583
+ depth: options.depth + 1
1584
+ };
1585
+ newChildren = children.map((c) => preImpl$3(c, callback, nextLevelOptions)).filter((c) => !!c);
1586
+ }
1587
+ if (!callback(row, options)) return;
1588
+ return {
1589
+ ...row,
1590
+ [finalChildrenKey]: newChildren
1591
+ };
1592
+ }
1593
+ function breadthImpl$3(row, callback, options) {
1594
+ const queue = [{
1595
+ queueRow: row,
1596
+ queueOptions: options
1597
+ }];
1598
+ const resultCache = /* @__PURE__ */ new WeakMap();
1599
+ const newNodeCache = /* @__PURE__ */ new WeakMap();
1600
+ const childrenKeyCache = /* @__PURE__ */ new WeakMap();
1601
+ let result;
1602
+ const runQueue = () => {
1603
+ if (queue.length === 0) return result;
1604
+ const { queueRow, queueOptions } = queue.shift();
1605
+ const finalChildrenKey = getFinalChildrenKey(queueRow, queueOptions, queueOptions);
1606
+ const children = queueRow[finalChildrenKey];
1607
+ if (isArray(children)) {
1608
+ const nextLevelOptions = {
1609
+ ...queueOptions,
1610
+ parents: [...queueOptions.parents, queueRow],
1611
+ depth: queueOptions.depth + 1
1612
+ };
1613
+ const subQueueItems = children.map((queueRow$1) => ({
1614
+ queueRow: queueRow$1,
1615
+ queueOptions: nextLevelOptions
1616
+ }));
1617
+ queue.push(...subQueueItems);
1618
+ }
1619
+ const parent = arrayLast(queueOptions.parents);
1620
+ const isTopNode = queueOptions.depth === 0;
1621
+ const parentResult = parent && resultCache.get(parent);
1622
+ if (!isTopNode && !parentResult) return runQueue();
1623
+ const callbackResult = callback(queueRow, queueOptions);
1624
+ if (isTopNode && !callbackResult) return;
1625
+ const newNode = {
1626
+ ...queueRow,
1627
+ [finalChildrenKey]: void 0
1628
+ };
1629
+ if (isTopNode) result = newNode;
1630
+ resultCache.set(queueRow, callbackResult);
1631
+ newNodeCache.set(queueRow, newNode);
1632
+ childrenKeyCache.set(queueRow, finalChildrenKey);
1633
+ if (callbackResult && parent) {
1634
+ const parentNewNode = newNodeCache.get(parent);
1635
+ const parentChildrenKey = childrenKeyCache.get(parent);
1636
+ if (parentNewNode && parentChildrenKey) {
1637
+ if (!parentNewNode[parentChildrenKey]) parentNewNode[parentChildrenKey] = [];
1638
+ parentNewNode[parentChildrenKey].push(newNode);
1639
+ }
1640
+ }
1641
+ return runQueue();
1642
+ };
1643
+ return runQueue();
1644
+ }
1645
+ const strategies$3 = {
1646
+ pre: preImpl$3,
1647
+ post: postImpl$3,
1648
+ breadth: breadthImpl$3
1649
+ };
1650
+ function treeFilter(tree, callback, options = {}) {
1651
+ const { childrenKey = "children", strategy = "pre", getChildrenKey } = options;
1652
+ const traversalMethod = strategies$3[strategy];
1653
+ const innerOptions = {
1654
+ childrenKey,
1655
+ depth: 0,
1656
+ parents: [],
1657
+ getChildrenKey
1658
+ };
1659
+ return isArray(tree) ? tree.map((row) => traversalMethod(row, callback, innerOptions)).filter((t) => !!t) : traversalMethod(tree, callback, innerOptions) || [];
1660
+ }
1661
+
1662
+ //#endregion
1663
+ //#region src/utils/tree/treeFind.ts
1664
+ const strategies$2 = {
1665
+ pre: preImpl$2,
1666
+ post: postImpl$2,
1667
+ breadth: breadthImpl$2
1668
+ };
1669
+ function preImpl$2(row, callback, options) {
1670
+ if (callback(row, options)) return row;
1671
+ const children = row[getFinalChildrenKey(row, options, options)];
1672
+ if (isArray(children)) for (const child of children) {
1673
+ const result = preImpl$2(child, callback, {
1674
+ ...options,
1675
+ parents: [...options.parents, row],
1676
+ depth: options.depth + 1
1677
+ });
1678
+ if (result) return result;
1679
+ }
1680
+ }
1681
+ function postImpl$2(row, callback, options) {
1682
+ const children = row[getFinalChildrenKey(row, options, options)];
1683
+ if (isArray(children)) for (const child of children) {
1684
+ const result = postImpl$2(child, callback, {
1685
+ ...options,
1686
+ parents: [...options.parents, row],
1687
+ depth: options.depth + 1
1688
+ });
1689
+ if (result) return result;
1690
+ }
1691
+ if (callback(row, options)) return row;
1692
+ }
1693
+ function breadthImpl$2(row, callback, options) {
1694
+ const queue = [{
1695
+ queueRow: row,
1696
+ queueOptions: options
1697
+ }];
1698
+ const runQueue = () => {
1699
+ if (queue.length === 0) return;
1700
+ const { queueRow, queueOptions } = queue.shift();
1701
+ const children = queueRow[getFinalChildrenKey(queueRow, queueOptions, queueOptions)];
1702
+ if (isArray(children)) {
1703
+ const nextLevelOptions = {
1704
+ ...queueOptions,
1705
+ parents: [...queueOptions.parents, queueRow],
1706
+ depth: queueOptions.depth + 1
1707
+ };
1708
+ const subQueueItems = children.map((queueRow$1) => ({
1709
+ queueRow: queueRow$1,
1710
+ queueOptions: nextLevelOptions
1711
+ }));
1712
+ queue.push(...subQueueItems);
1713
+ }
1714
+ if (callback(queueRow, queueOptions)) return queueRow;
1715
+ return runQueue();
1716
+ };
1717
+ return runQueue();
1718
+ }
1719
+ /**
1720
+ * 查找树节点
1721
+ * - 返回第一个回调返回 true 的节点
1722
+ *
1723
+ * @param tree 树结构数据
1724
+ * @param callback 回调函数
1725
+ * @param options 配置项
1726
+ * @returns 找到的节点,未找到则返回 undefined
1727
+ * @example
1728
+ * ```ts
1729
+ * const tree = [{ id: 1, children: [{ id: 2 }] }];
1730
+ * treeFind(tree, (node) => node.id === 2); // { id: 2, ... }
1731
+ * ```
1732
+ */
1733
+ function treeFind(tree, callback, options = {}) {
1734
+ const { childrenKey = "children", strategy = "pre", getChildrenKey } = options;
1735
+ const traversalMethod = strategies$2[strategy];
1736
+ const innerOptions = {
1737
+ childrenKey,
1738
+ depth: 0,
1739
+ parents: [],
1740
+ getChildrenKey
1741
+ };
1742
+ if (isArray(tree)) {
1743
+ for (const row of tree) {
1744
+ const result = traversalMethod(row, callback, innerOptions);
1745
+ if (result) return result;
1746
+ }
1747
+ return;
1748
+ }
1749
+ return traversalMethod(tree, callback, innerOptions);
1750
+ }
1751
+
1752
+ //#endregion
1753
+ //#region src/utils/tree/treeForEach.ts
1754
+ const strategies$1 = {
1755
+ pre: preImpl$1,
1756
+ post: postImpl$1,
1757
+ breadth: breadthImpl$1
1758
+ };
1759
+ function preImpl$1(row, callback, options) {
1760
+ callback(row, options);
1761
+ const children = row[getFinalChildrenKey(row, options, options)];
1762
+ if (isArray(children)) {
1763
+ const nextLevelOptions = {
1764
+ ...options,
1765
+ parents: [...options.parents, row],
1766
+ depth: options.depth + 1
1767
+ };
1768
+ for (const child of children) preImpl$1(child, callback, nextLevelOptions);
1769
+ }
1770
+ }
1771
+ function postImpl$1(row, callback, options) {
1772
+ const children = row[getFinalChildrenKey(row, options, options)];
1773
+ if (isArray(children)) {
1774
+ const nextLevelOptions = {
1775
+ ...options,
1776
+ parents: [...options.parents, row],
1777
+ depth: options.depth + 1
1778
+ };
1779
+ for (const child of children) postImpl$1(child, callback, nextLevelOptions);
1780
+ }
1781
+ callback(row, options);
1782
+ }
1783
+ function breadthImpl$1(row, callback, options) {
1784
+ const queue = [{
1785
+ queueRow: row,
1786
+ queueOptions: options
1787
+ }];
1788
+ const runQueue = () => {
1789
+ if (queue.length === 0) return;
1790
+ const { queueRow, queueOptions } = queue.shift();
1791
+ const children = queueRow[getFinalChildrenKey(queueRow, queueOptions, queueOptions)];
1792
+ if (isArray(children)) {
1793
+ const nextLevelOptions = {
1794
+ ...queueOptions,
1795
+ parents: [...queueOptions.parents, queueRow],
1796
+ depth: queueOptions.depth + 1
1797
+ };
1798
+ const subQueueItems = children.map((queueRow$1) => ({
1799
+ queueRow: queueRow$1,
1800
+ queueOptions: nextLevelOptions
1801
+ }));
1802
+ queue.push(...subQueueItems);
1803
+ }
1804
+ callback(queueRow, queueOptions);
1805
+ runQueue();
1806
+ };
1807
+ runQueue();
1808
+ }
1809
+ /**
1810
+ * 遍历树节点
1811
+ *
1812
+ * @param tree 树结构数据
1813
+ * @param callback 回调函数
1814
+ * @param options 配置项
1815
+ * @example
1816
+ * ```ts
1817
+ * const tree = [{ id: 1, children: [{ id: 2 }] }];
1818
+ * const ids: number[] = [];
1819
+ * treeForEach(tree, (node) => ids.push(node.id));
1820
+ * // ids: [1, 2] (pre-order default)
1821
+ * ```
1822
+ */
1823
+ function treeForEach(tree, callback, options = {}) {
1824
+ const { childrenKey = "children", strategy = "pre", getChildrenKey } = options;
1825
+ const traversalMethod = strategies$1[strategy];
1826
+ const innerOptions = {
1827
+ childrenKey,
1828
+ depth: 0,
1829
+ parents: [],
1830
+ getChildrenKey
1831
+ };
1832
+ if (isArray(tree)) for (const row of tree) traversalMethod(row, callback, innerOptions);
1833
+ else traversalMethod(tree, callback, innerOptions);
1834
+ }
1835
+
1836
+ //#endregion
1837
+ //#region src/utils/tree/treeMap.ts
1838
+ const strategies = {
1839
+ pre: preImpl,
1840
+ post: postImpl,
1841
+ breadth: breadthImpl
1842
+ };
1843
+ function preImpl(row, callback, options) {
1844
+ const finalChildrenKey = getFinalChildrenKey(row, options, options);
1845
+ const result = callback(row, options);
1846
+ const children = row[finalChildrenKey];
1847
+ let newChildren;
1848
+ if (isArray(children)) {
1849
+ const nextLevelOptions = {
1850
+ ...options,
1851
+ parents: [...options.parents, row],
1852
+ depth: options.depth + 1
1853
+ };
1854
+ newChildren = children.map((c) => preImpl(c, callback, nextLevelOptions));
1855
+ }
1856
+ return {
1857
+ ...result,
1858
+ [finalChildrenKey]: newChildren
1859
+ };
1860
+ }
1861
+ function postImpl(row, callback, options) {
1862
+ const finalChildrenKey = getFinalChildrenKey(row, options, options);
1863
+ const children = row[finalChildrenKey];
1864
+ let newChildren;
1865
+ if (isArray(children)) {
1866
+ const nextLevelOptions = {
1867
+ ...options,
1868
+ parents: [...options.parents, row],
1869
+ depth: options.depth + 1
1870
+ };
1871
+ newChildren = children.map((c) => postImpl(c, callback, nextLevelOptions));
1872
+ }
1873
+ return {
1874
+ ...callback(row, options),
1875
+ [finalChildrenKey]: newChildren
1876
+ };
1877
+ }
1878
+ function breadthImpl(row, callback, options) {
1879
+ const queue = [{
1880
+ queueRow: row,
1881
+ queueOptions: options
1882
+ }];
1883
+ const cache = /* @__PURE__ */ new WeakMap();
1884
+ const childrenKeyCache = /* @__PURE__ */ new WeakMap();
1885
+ let result;
1886
+ const runQueue = () => {
1887
+ if (queue.length === 0) return result;
1888
+ const { queueRow, queueOptions } = queue.shift();
1889
+ const finalChildrenKey = getFinalChildrenKey(queueRow, queueOptions, queueOptions);
1890
+ const children = queueRow[finalChildrenKey];
1891
+ if (isArray(children)) {
1892
+ const nextLevelOptions = {
1893
+ ...queueOptions,
1894
+ parents: [...queueOptions.parents, queueRow],
1895
+ depth: queueOptions.depth + 1
1896
+ };
1897
+ const subQueueItems = children.map((queueRow$1) => ({
1898
+ queueRow: queueRow$1,
1899
+ queueOptions: nextLevelOptions
1900
+ }));
1901
+ queue.push(...subQueueItems);
1902
+ }
1903
+ const res = callback(queueRow, queueOptions);
1904
+ cache.set(queueRow, res);
1905
+ childrenKeyCache.set(queueRow, finalChildrenKey);
1906
+ const parent = arrayLast(queueOptions.parents);
1907
+ if (parent) {
1908
+ const newParent = cache.get(parent);
1909
+ const parentChildrenKey = childrenKeyCache.get(parent);
1910
+ if (newParent && parentChildrenKey) if (newParent[parentChildrenKey]) newParent[parentChildrenKey].push(res);
1911
+ else newParent[parentChildrenKey] = [res];
1912
+ }
1913
+ if (queueOptions.depth === 0) result = res;
1914
+ return runQueue();
1915
+ };
1916
+ return runQueue();
1917
+ }
1918
+ function treeMap(tree, callback, options = {}) {
1919
+ const { childrenKey = "children", strategy = "pre", getChildrenKey } = options;
1920
+ const traversalMethod = strategies[strategy];
1921
+ const innerOptions = {
1922
+ childrenKey,
1923
+ depth: 0,
1924
+ parents: [],
1925
+ getChildrenKey
1926
+ };
1927
+ return isArray(tree) ? tree.map((row) => traversalMethod(row, callback, innerOptions)) : traversalMethod(tree, callback, innerOptions);
1928
+ }
1929
+
1930
+ //#endregion
1931
+ //#region src/utils/tree/rowsToTree.ts
1932
+ /**
1933
+ * 行结构 转 树结构
1934
+ * - 将平铺的数组转换为树形结构
1935
+ *
1936
+ * @param rows 行数据数组
1937
+ * @param options 配置项
1938
+ * @returns 树结构数组
1939
+ * @example
1940
+ * ```ts
1941
+ * const rows = [
1942
+ * { id: 1, parentId: null },
1943
+ * { id: 2, parentId: 1 },
1944
+ * ];
1945
+ * rowsToTree(rows);
1946
+ * // [{ id: 1, parentId: null, children: [{ id: 2, parentId: 1 }] }]
1947
+ * ```
1948
+ */
1949
+ function rowsToTree(rows, options) {
1950
+ const { parentIdKey = "parentId", rowKey = "id", childrenKey = "children" } = options || {};
1951
+ const result = [];
1952
+ const map = /* @__PURE__ */ new Map();
1953
+ for (const row of rows) {
1954
+ const id = row[rowKey];
1955
+ if (!map.get(id)) map.set(id, row);
1956
+ }
1957
+ for (const row of rows) {
1958
+ const parentId = row[parentIdKey];
1959
+ const parent = map.get(parentId);
1960
+ if (!parent || !parentId) {
1961
+ result.push(row);
1962
+ continue;
1963
+ }
1964
+ const siblings = parent[childrenKey];
1965
+ if (isNull(siblings) || isUndefined(siblings)) parent[childrenKey] = [row];
1966
+ else if (Array.isArray(siblings)) siblings.push(row);
1967
+ else {
1968
+ const message = `The key "${childrenKey.toString()}" in parent item is not an array.`;
1969
+ throw new Error(message);
1970
+ }
1971
+ }
1972
+ return result;
1973
+ }
1974
+
1975
+ //#endregion
1976
+ //#region src/utils/tree/treeToRows.ts
1977
+ /**
1978
+ * 树结构 转 行结构
1979
+ * - 将树形结构扁平化为数组
1980
+ *
1981
+ * @param tree 树结构数据 (单个节点或节点数组)
1982
+ * @param options 配置项
1983
+ * @returns 扁平化后的数组
1984
+ * @example
1985
+ * ```ts
1986
+ * const tree = [{ id: 1, children: [{ id: 2 }] }];
1987
+ * treeToRows(tree);
1988
+ * // [{ id: 1, children: undefined }, { id: 2, children: undefined }]
1989
+ * ```
1990
+ */
1991
+ function treeToRows(tree, options = {}) {
1992
+ const { childrenKey = "children" } = options;
1993
+ const result = [];
1994
+ if (!tree) return result;
1995
+ treeForEach(tree, (t) => result.push({
1996
+ ...t,
1997
+ [childrenKey]: void 0
1998
+ }), options);
1999
+ return result;
2000
+ }
2001
+
2002
+ //#endregion
2003
+ export { arrayFirst as $, mathToDecimal as A, isFalsy as At, isBrowser as B, isGeneratorFunction as Bt, objectMapEntries as C, isPositiveInteger as Ct, enumEntries as D, isIterable as Dt, enumKeys as E, isWeakMap as Et, cloneDeepWith as F, isDate as Ft, arraySplit as G, isArray as Gt, arrayZipToObject as H, isBlob as Ht, to as I, isClass as It, arrayPick as J, arrayReplaceMove as K, isTypedArray as Kt, isTablet as L, isAsyncFunction as Lt, stringToNumber as M, isError as Mt, clone as N, isEqual as Nt, numberWithin as O, isIframe as Ot, cloneDeep as P, isEnumeration as Pt, arrayFork as Q, isIOSMobile as R, isAsyncGeneratorFunction as Rt, objectAssign as S, isNumber as St, enumValues as T, isMap as Tt, arrayUnzip as U, isFile as Ut, isWebWorker as V, isBoolean as Vt, arrayZip as W, isBigInt as Wt, arrayLast as X, arrayMerge as Y, arrayIntersection as Z, objectPick as _, isInfinity as _t, treeFind as a, isWebSocket as at, objectInvert as b, isNaN as bt, stringTruncate as c, isSymbol as ct, stringToPosix as d, isRegExp as dt, arrayDifference as et, stringToJson as f, isString as ft, objectValues as g, isObject as gt, stringInitialCase as h, isPromiseLike as ht, treeForEach as i, isWindow as it, mathToBignumber as j, isFalsyLike as jt, mathToEvaluate as k, isInIframe as kt, stringTrim as l, isSet as lt, stringReplace as m, isPromise as mt, rowsToTree as n, arrayCompete as nt, treeFilter as o, isURLSearchParams as ot, stringTemplate as p, isReadableStream as pt, arrayReplace as q, isAbortSignal as qt, treeMap as r, arrayCast as rt, getTimeZone as s, isUndefined as st, treeToRows as t, arrayCounting as tt, stringToValues as u, isWeakSet as ut, objectOmit as v, isInfinityLike as vt, objectEntries as w, isNull as wt, objectCrush as x, isNegativeInteger as xt, objectKeys as y, isInteger as yt, isMobile as z, isFunction as zt };
2004
+ //# sourceMappingURL=utils-DbMbll5L.js.map