@nickyzj2023/utils 1.0.47 → 1.0.49

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 (111) hide show
  1. package/AGENTS.md +58 -22
  2. package/dist/dom/index.d.ts +1 -0
  3. package/dist/function/index.d.ts +1 -0
  4. package/dist/hoc/index.d.ts +1 -0
  5. package/dist/index.js +1 -1
  6. package/dist/is/index.d.ts +5 -0
  7. package/dist/is/isFalsy.d.ts +9 -0
  8. package/dist/is/isNil.d.ts +9 -0
  9. package/dist/is/isObject.d.ts +8 -0
  10. package/dist/is/isPrimitive.d.ts +9 -0
  11. package/dist/is/isTruthy.d.ts +8 -0
  12. package/dist/is/types.d.ts +2 -0
  13. package/dist/network/fetcher.d.ts +57 -0
  14. package/dist/network/getRealURL.d.ts +2 -0
  15. package/dist/network/image.d.ts +59 -0
  16. package/dist/network/index.d.ts +4 -0
  17. package/dist/network/to.d.ts +9 -0
  18. package/dist/number/index.d.ts +1 -0
  19. package/dist/object/index.d.ts +3 -0
  20. package/dist/object/mapKeys.d.ts +17 -0
  21. package/dist/object/mapValues.d.ts +21 -0
  22. package/dist/object/mergeObjects.d.ts +12 -0
  23. package/dist/object/types.d.ts +6 -0
  24. package/dist/string/case.d.ts +32 -0
  25. package/dist/string/compact.d.ts +22 -0
  26. package/dist/string/image.d.ts +59 -0
  27. package/dist/string/index.d.ts +2 -0
  28. package/dist/string.d.ts +13 -97
  29. package/dist/time/debounce.d.ts +20 -0
  30. package/dist/time/index.d.ts +3 -0
  31. package/dist/time/sleep.d.ts +7 -0
  32. package/dist/time/throttle.d.ts +20 -0
  33. package/docs/functions/camelToSnake.html +1 -1
  34. package/docs/functions/capitalize.html +1 -1
  35. package/docs/functions/compactStr.html +1 -1
  36. package/docs/functions/debounce.html +1 -1
  37. package/docs/functions/decapitalize.html +1 -1
  38. package/docs/functions/fetcher.html +1 -1
  39. package/docs/functions/getRealURL.html +1 -1
  40. package/docs/functions/imageUrlToBase64.html +1 -1
  41. package/docs/functions/isFalsy.html +1 -1
  42. package/docs/functions/isNil.html +1 -1
  43. package/docs/functions/isObject.html +1 -1
  44. package/docs/functions/isPrimitive.html +1 -1
  45. package/docs/functions/isTruthy.html +1 -1
  46. package/docs/functions/loopUntil.html +1 -1
  47. package/docs/functions/mapKeys.html +1 -1
  48. package/docs/functions/mapValues.html +1 -1
  49. package/docs/functions/mergeObjects.html +1 -1
  50. package/docs/functions/randomInt.html +1 -1
  51. package/docs/functions/sleep.html +1 -1
  52. package/docs/functions/snakeToCamel.html +1 -1
  53. package/docs/functions/throttle.html +1 -1
  54. package/docs/functions/timeLog.html +1 -1
  55. package/docs/functions/to.html +1 -1
  56. package/docs/functions/withCache.html +3 -3
  57. package/docs/types/CamelToSnake.html +1 -1
  58. package/docs/types/Capitalize.html +1 -1
  59. package/docs/types/Decapitalize.html +1 -1
  60. package/docs/types/DeepMapKeys.html +1 -1
  61. package/docs/types/DeepMapValues.html +1 -1
  62. package/docs/types/Falsy.html +1 -1
  63. package/docs/types/ImageCompressionOptions.html +3 -3
  64. package/docs/types/Primitive.html +1 -1
  65. package/docs/types/RequestInit.html +1 -1
  66. package/docs/types/SetTtl.html +1 -1
  67. package/docs/types/SnakeToCamel.html +1 -1
  68. package/package.json +4 -4
  69. package/src/dom/index.ts +1 -0
  70. package/src/function/index.ts +1 -0
  71. package/src/{function.ts → function/loopUntil.ts} +36 -36
  72. package/src/hoc/index.ts +1 -0
  73. package/src/{hoc.ts → hoc/withCache.ts} +117 -117
  74. package/src/is/index.ts +5 -0
  75. package/src/is/isFalsy.ts +12 -0
  76. package/src/is/isNil.ts +11 -0
  77. package/src/is/isObject.ts +10 -0
  78. package/src/is/isPrimitive.ts +23 -0
  79. package/src/is/isTruthy.ts +10 -0
  80. package/src/lru-cache.ts +50 -50
  81. package/src/{network.ts → network/fetcher.ts} +2 -37
  82. package/src/network/getRealURL.ts +18 -0
  83. package/src/network/image.ts +202 -0
  84. package/src/network/index.ts +4 -0
  85. package/src/network/to.ts +17 -0
  86. package/src/number/index.ts +1 -0
  87. package/src/object/index.ts +3 -0
  88. package/src/object/mapKeys.ts +50 -0
  89. package/src/object/mapValues.ts +77 -0
  90. package/src/object/mergeObjects.ts +50 -0
  91. package/src/string/case.ts +71 -0
  92. package/src/string/compact.ts +56 -0
  93. package/src/string/index.ts +12 -0
  94. package/src/time/debounce.ts +34 -0
  95. package/src/time/index.ts +3 -0
  96. package/src/time/sleep.ts +11 -0
  97. package/src/time/throttle.ts +34 -0
  98. package/.github/workflows/docs.yml +0 -39
  99. package/dist/is.d.ts +0 -43
  100. package/dist/object.d.ts +0 -50
  101. package/dist/time.d.ts +0 -47
  102. package/src/is.ts +0 -70
  103. package/src/object.ts +0 -179
  104. package/src/string.ts +0 -259
  105. package/src/time.ts +0 -81
  106. /package/dist/{dom.d.ts → dom/timeLog.d.ts} +0 -0
  107. /package/dist/{function.d.ts → function/loopUntil.d.ts} +0 -0
  108. /package/dist/{hoc.d.ts → hoc/withCache.d.ts} +0 -0
  109. /package/dist/{number.d.ts → number/randomInt.d.ts} +0 -0
  110. /package/src/{dom.ts → dom/timeLog.ts} +0 -0
  111. /package/src/{number.ts → number/randomInt.ts} +0 -0
@@ -0,0 +1,34 @@
1
+ /**
2
+ * 节流函数 - 在指定时间间隔内最多执行一次调用
3
+ * @param fn 要节流的函数
4
+ * @param delay 间隔时间,默认 300ms
5
+ *
6
+ * @remarks
7
+ * 节流:连续触发时,按照固定间隔执行。适合用于滚动、拖拽等高频触发场景。
8
+ * 例如:滚动页面时,每300ms最多执行一次回调,而不是每次滚动都执行。
9
+ *
10
+ * 防抖 vs 节流:
11
+ * - 防抖:等待触发停止后才执行(最后一次)
12
+ * - 节流:按固定节奏执行(每隔多久执行一次)
13
+ *
14
+ * @example
15
+ * const handleScroll = throttle(() => {
16
+ * console.log('滚动位置:', window.scrollY);
17
+ * }, 200);
18
+ * window.addEventListener('scroll', handleScroll);
19
+ */
20
+ export const throttle = <T extends (...args: any[]) => any>(
21
+ fn: T,
22
+ delay = 300,
23
+ ) => {
24
+ let timer: ReturnType<typeof setTimeout> | null = null;
25
+
26
+ return function (this: any, ...args: Parameters<T>) {
27
+ if (!timer) {
28
+ timer = setTimeout(() => {
29
+ timer = null;
30
+ fn.apply(this, args);
31
+ }, delay);
32
+ }
33
+ };
34
+ };
@@ -1,39 +0,0 @@
1
- name: Generate Docs
2
-
3
- on:
4
- push:
5
- branches: [main, master]
6
- pull_request:
7
- branches: [main, master]
8
-
9
- jobs:
10
- docs:
11
- runs-on: ubuntu-latest
12
-
13
- steps:
14
- - name: Checkout code
15
- uses: actions/checkout@v4
16
-
17
- - name: Setup Bun
18
- uses: oven-sh/setup-bun@v2
19
- with:
20
- bun-version: latest
21
-
22
- - name: Install dependencies
23
- run: bun install
24
-
25
- - name: Generate docs
26
- run: bun run docs
27
-
28
- - name: Commit and push docs
29
- if: github.event_name == 'push'
30
- run: |
31
- git config --local user.email "github-actions[bot]@users.noreply.github.com"
32
- git config --local user.name "github-actions[bot]"
33
- git add docs/
34
- if git diff --staged --quiet; then
35
- echo "No changes to commit"
36
- else
37
- git commit -m "docs: auto-generate documentation"
38
- git push
39
- fi
package/dist/is.d.ts DELETED
@@ -1,43 +0,0 @@
1
- export type Primitive = number | string | boolean | symbol | bigint | undefined | null;
2
- export type Falsy = false | 0 | -0 | 0n | "" | null | undefined;
3
- /**
4
- * 检测传入的值是否为**普通对象**
5
- *
6
- * @example
7
- * const obj = { a: 1 };
8
- * isObject(obj); // true
9
- */
10
- export declare const isObject: (value: any) => value is Record<string, any>;
11
- /**
12
- * 检测传入的值是否为**原始值**(number、string、boolean、symbol、bigint、undefined、null)
13
- *
14
- * @example
15
- * isPrimitive(1); // true
16
- * isPrimitive([]); // false
17
- */
18
- export declare const isPrimitive: (value: any) => value is Primitive;
19
- /**
20
- * 检测传入的值是否为**假值**(false、0、''、null、undefined、NaN等)
21
- *
22
- * @example
23
- * isFalsy(""); // true
24
- * isFalsy(1); // false
25
- */
26
- export declare const isFalsy: (value: any) => value is Falsy;
27
- /**
28
- * 检测传入的值是否为**真值**
29
- *
30
- * @example
31
- * isTruthy(1); // true
32
- * isTruthy(""); // false
33
- */
34
- export declare const isTruthy: (value: any) => value is any;
35
- /**
36
- * 检测传入的值是否为**空值**(null、undefined)
37
- *
38
- * @example
39
- * isNil(null); // true
40
- * isNil(undefined); // true
41
- * isNil(1); // false
42
- */
43
- export declare const isNil: (value: any) => value is null | undefined;
package/dist/object.d.ts DELETED
@@ -1,50 +0,0 @@
1
- /**
2
- * 深度合并两个对象,规则如下:
3
- * 1. 原始值覆盖:如果两个值都是原始类型,则用后者覆盖;
4
- * 2. 数组拼接:如果两个值都是数组,则拼接为大数组;
5
- * 3. 对象递归合并:如果两个值都是对象,则进行递归深度合并;
6
- *
7
- * @template T 第一个对象
8
- * @template U 第二个对象
9
- * @param {T} obj1 要合并的第一个对象,相同字段会被 obj2 覆盖
10
- * @param {U} obj2 要合并的第二个对象
11
- */
12
- export declare const mergeObjects: <T extends Record<string, any>, U extends Record<string, any>>(obj1: T, obj2: U) => T & U;
13
- export type DeepMapKeys<T> = T extends Array<infer U> ? Array<DeepMapKeys<U>> : T extends object ? {
14
- [key: string]: DeepMapKeys<T[keyof T]>;
15
- } : T;
16
- /**
17
- * 递归处理对象里的 key
18
- *
19
- * @remarks
20
- * 无法完整推导出类型,只能做到有递归,key 全为 string,value 为同层级的所有类型的联合
21
- *
22
- * @template T 要转换的对象
23
- *
24
- * @example
25
- * const obj = { a: { b: 1 } };
26
- * const result = mapKeys(obj, (key) => key.toUpperCase());
27
- * console.log(result); // { A: { B: 1 } }
28
- */
29
- export declare const mapKeys: <T>(obj: T, getNewKey: (key: string) => string) => DeepMapKeys<T>;
30
- export type DeepMapValues<T, R> = T extends Array<infer U> ? Array<DeepMapValues<U, R>> : T extends object ? {
31
- [K in keyof T]: T[K] extends object ? DeepMapValues<T[K], R> : R;
32
- } : R;
33
- /**
34
- * 递归处理对象里的 value
35
- *
36
- * @remarks
37
- * 无法完整推导出类型,所有 value 最终都会变为 any
38
- *
39
- * @template T 要转换的对象
40
- * @template R 转换后的值类型,为 any,无法进一步推导
41
- *
42
- * @example
43
- * const obj = { a: 1, b: { c: 2 } };
44
- * const result = mapValues(obj, (value, key) => isPrimitive(value) ? value + 1 : value);
45
- * console.log(result); // { a: 2, b: { c: 3 } }
46
- */
47
- export declare const mapValues: <T, R = any>(obj: T, getNewValue: (value: any, key: string | number) => R, options?: {
48
- /** 过滤函数,返回 true 表示保留该字段 */
49
- filter?: (value: any, key: string | number) => boolean;
50
- }) => DeepMapValues<T, R>;
package/dist/time.d.ts DELETED
@@ -1,47 +0,0 @@
1
- /**
2
- * 延迟一段时间再执行后续代码
3
- * @param time 延迟时间,默认 150ms
4
- * @example
5
- * await sleep(1000); // 等待 1 秒执行后续代码
6
- */
7
- export declare const sleep: (time?: number) => Promise<unknown>;
8
- /**
9
- * 防抖:在指定时间内只执行最后一次调用
10
- * @param fn 要防抖的函数
11
- * @param delay 延迟时间,默认 300ms
12
- *
13
- * @remarks
14
- * 连续触发时,只有最后一次会执行。适合用于搜索框输入、窗口大小调整等场景。
15
- * 例如:用户输入"hello"过程中,不会触发搜索,只有停下来时才执行。
16
- *
17
- * 防抖 vs 节流:
18
- * - 防抖:等待触发停止后才执行(最后一次)
19
- * - 节流:按固定节奏执行(每隔多久执行一次)
20
- *
21
- * @example
22
- * const search = debounce((keyword: string) => {
23
- * console.log('搜索:', keyword);
24
- * });
25
- * search('hello'); // 300ms 后执行
26
- */
27
- export declare const debounce: <T extends (...args: any[]) => any>(fn: T, delay?: number) => (...args: Parameters<T>) => void;
28
- /**
29
- * 节流函数 - 在指定时间间隔内最多执行一次调用
30
- * @param fn 要节流的函数
31
- * @param delay 间隔时间,默认 300ms
32
- *
33
- * @remarks
34
- * 节流:连续触发时,按照固定间隔执行。适合用于滚动、拖拽等高频触发场景。
35
- * 例如:滚动页面时,每300ms最多执行一次回调,而不是每次滚动都执行。
36
- *
37
- * 防抖 vs 节流:
38
- * - 防抖:等待触发停止后才执行(最后一次)
39
- * - 节流:按固定节奏执行(每隔多久执行一次)
40
- *
41
- * @example
42
- * const handleScroll = throttle(() => {
43
- * console.log('滚动位置:', window.scrollY);
44
- * }, 200);
45
- * window.addEventListener('scroll', handleScroll);
46
- */
47
- export declare const throttle: <T extends (...args: any[]) => any>(fn: T, delay?: number) => (this: any, ...args: Parameters<T>) => void;
package/src/is.ts DELETED
@@ -1,70 +0,0 @@
1
- export type Primitive =
2
- | number
3
- | string
4
- | boolean
5
- | symbol
6
- | bigint
7
- | undefined
8
- | null;
9
-
10
- export type Falsy = false | 0 | -0 | 0n | "" | null | undefined;
11
-
12
- /**
13
- * 检测传入的值是否为**普通对象**
14
- *
15
- * @example
16
- * const obj = { a: 1 };
17
- * isObject(obj); // true
18
- */
19
- export const isObject = (value: any): value is Record<string, any> => {
20
- return value?.constructor === Object;
21
- };
22
-
23
- /**
24
- * 检测传入的值是否为**原始值**(number、string、boolean、symbol、bigint、undefined、null)
25
- *
26
- * @example
27
- * isPrimitive(1); // true
28
- * isPrimitive([]); // false
29
- */
30
- export const isPrimitive = (value: any): value is Primitive => {
31
- return (
32
- value === null ||
33
- value === undefined ||
34
- (typeof value !== "object" && typeof value !== "function")
35
- );
36
- };
37
-
38
- /**
39
- * 检测传入的值是否为**假值**(false、0、''、null、undefined、NaN等)
40
- *
41
- * @example
42
- * isFalsy(""); // true
43
- * isFalsy(1); // false
44
- */
45
- export const isFalsy = (value: any): value is Falsy => {
46
- return !value;
47
- };
48
-
49
- /**
50
- * 检测传入的值是否为**真值**
51
- *
52
- * @example
53
- * isTruthy(1); // true
54
- * isTruthy(""); // false
55
- */
56
- export const isTruthy = (value: any): value is any => {
57
- return !!value;
58
- };
59
-
60
- /**
61
- * 检测传入的值是否为**空值**(null、undefined)
62
- *
63
- * @example
64
- * isNil(null); // true
65
- * isNil(undefined); // true
66
- * isNil(1); // false
67
- */
68
- export const isNil = (value: any): value is null | undefined => {
69
- return value === null || value === undefined;
70
- };
package/src/object.ts DELETED
@@ -1,179 +0,0 @@
1
- import { isObject, isPrimitive } from "./is";
2
-
3
- /**
4
- * 深度合并两个对象,规则如下:
5
- * 1. 原始值覆盖:如果两个值都是原始类型,则用后者覆盖;
6
- * 2. 数组拼接:如果两个值都是数组,则拼接为大数组;
7
- * 3. 对象递归合并:如果两个值都是对象,则进行递归深度合并;
8
- *
9
- * @template T 第一个对象
10
- * @template U 第二个对象
11
- * @param {T} obj1 要合并的第一个对象,相同字段会被 obj2 覆盖
12
- * @param {U} obj2 要合并的第二个对象
13
- */
14
- export const mergeObjects = <
15
- T extends Record<string, any>,
16
- U extends Record<string, any>,
17
- >(
18
- obj1: T,
19
- obj2: U,
20
- ) => {
21
- const result: Record<string, any> = { ...obj1 };
22
-
23
- for (const key of Object.keys(obj2)) {
24
- const val1 = result[key];
25
- const val2 = obj2[key];
26
-
27
- // 如果都是原始值,则用后者覆盖
28
- if (isPrimitive(val1) && isPrimitive(val2)) {
29
- result[key] = val2;
30
- continue;
31
- }
32
-
33
- // 如果都是数组,则拼接为大数组
34
- if (Array.isArray(val1) && Array.isArray(val2)) {
35
- result[key] = val1.concat(val2);
36
- continue;
37
- }
38
-
39
- // 如果都是对象,则深度递归合并
40
- if (isObject(val1) && isObject(val2)) {
41
- result[key] = mergeObjects(val1, val2);
42
- continue;
43
- }
44
-
45
- // 其他情况用后者覆盖
46
- result[key] = val2;
47
- }
48
-
49
- return result as T & U;
50
- };
51
-
52
- // --- mapKeys ---
53
-
54
- // 这里的 DeepMapKeys 只能承诺 key 是 string,无法推断出 key 的具体字面量变化
55
- // 因为 TS 不支持根据任意函数反推 Key 的字面量类型
56
- export type DeepMapKeys<T> =
57
- T extends Array<infer U>
58
- ? Array<DeepMapKeys<U>>
59
- : T extends object
60
- ? { [key: string]: DeepMapKeys<T[keyof T]> }
61
- : T;
62
-
63
- /**
64
- * 递归处理对象里的 key
65
- *
66
- * @remarks
67
- * 无法完整推导出类型,只能做到有递归,key 全为 string,value 为同层级的所有类型的联合
68
- *
69
- * @template T 要转换的对象
70
- *
71
- * @example
72
- * const obj = { a: { b: 1 } };
73
- * const result = mapKeys(obj, (key) => key.toUpperCase());
74
- * console.log(result); // { A: { B: 1 } }
75
- */
76
- export const mapKeys = <T>(
77
- obj: T,
78
- getNewKey: (key: string) => string,
79
- ): DeepMapKeys<T> => {
80
- // 递归处理数组
81
- if (Array.isArray(obj)) {
82
- return obj.map((item) => mapKeys(item, getNewKey)) as any;
83
- }
84
-
85
- // 处理普通对象
86
- if (isObject(obj)) {
87
- const keys = Object.keys(obj);
88
- return keys.reduce(
89
- (result, key) => {
90
- const newKey = getNewKey(key);
91
- const value = (obj as any)[key];
92
- result[newKey] = mapKeys(value, getNewKey);
93
- return result;
94
- },
95
- {} as Record<string, any>,
96
- ) as DeepMapKeys<T>;
97
- }
98
-
99
- // 处理非数组/对象
100
- return obj as any;
101
- };
102
-
103
- // --- mapValues ---
104
-
105
- // 这里的 DeepMapValues 尝试保留 key,但将 value 类型替换为 R
106
- // 注意:如果原 value 是对象,我们递归处理结构,而不是把整个对象变成 R
107
- export type DeepMapValues<T, R> =
108
- T extends Array<infer U>
109
- ? Array<DeepMapValues<U, R>>
110
- : T extends object
111
- ? { [K in keyof T]: T[K] extends object ? DeepMapValues<T[K], R> : R }
112
- : R;
113
-
114
- /**
115
- * 递归处理对象里的 value
116
- *
117
- * @remarks
118
- * 无法完整推导出类型,所有 value 最终都会变为 any
119
- *
120
- * @template T 要转换的对象
121
- * @template R 转换后的值类型,为 any,无法进一步推导
122
- *
123
- * @example
124
- * const obj = { a: 1, b: { c: 2 } };
125
- * const result = mapValues(obj, (value, key) => isPrimitive(value) ? value + 1 : value);
126
- * console.log(result); // { a: 2, b: { c: 3 } }
127
- */
128
- export const mapValues = <T, R = any>(
129
- obj: T,
130
- getNewValue: (value: any, key: string | number) => R,
131
- options?: {
132
- /** 过滤函数,返回 true 表示保留该字段 */
133
- filter?: (value: any, key: string | number) => boolean;
134
- },
135
- ): DeepMapValues<T, R> => {
136
- const { filter } = options ?? {};
137
-
138
- // 处理数组
139
- if (Array.isArray(obj)) {
140
- const mappedArray = obj.map((item, index) => {
141
- // 如果元素是对象,则递归处理
142
- if (isObject(item)) {
143
- return mapValues(item, getNewValue, options);
144
- }
145
- // 如果元素是原始值,则直接应用 getNewValue(此时 key 为数组下标)
146
- return getNewValue(item, index);
147
- });
148
- // 如果有过滤器,则过滤一遍元素
149
- if (filter) {
150
- return mappedArray.filter((item, index) => filter(item, index)) as any;
151
- }
152
- return mappedArray as any;
153
- }
154
-
155
- // 处理普通对象
156
- if (isObject(obj)) {
157
- const keys = Object.keys(obj);
158
- return keys.reduce((result, key) => {
159
- const value = (obj as any)[key];
160
- let newValue: any;
161
- // 如果值为对象或数组,则递归处理
162
- if (isObject(value) || Array.isArray(value)) {
163
- newValue = mapValues(value, getNewValue, options);
164
- }
165
- // 否则直接应用 getNewValue
166
- else {
167
- newValue = getNewValue(value, key);
168
- }
169
- // 如果存在过滤器,则看情况保留该字段
170
- if (!filter || filter(newValue, key)) {
171
- result[key] = newValue;
172
- }
173
- return result;
174
- }, {} as any) as DeepMapValues<T, R>;
175
- }
176
-
177
- // 处理非数组/对象
178
- return obj as any;
179
- };