@jiakun-zhao/utils 1.4.4 → 1.4.5

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 (3) hide show
  1. package/dist/index.mjs +5 -2
  2. package/package.json +6 -8
  3. package/llms.txt +0 -596
package/dist/index.mjs CHANGED
@@ -359,7 +359,7 @@ const isString = (val) => typeof val === "string";
359
359
  * slash('path/to/file') // 'path/to/file'
360
360
  * ```
361
361
  */
362
- const slash = (str) => str.replace(/\\\\/g, "/");
362
+ const slash = (str) => str.replace(/\\/g, "/");
363
363
  /**
364
364
  * 确保字符串以指定前缀开头
365
365
  * @param str - 输入字符串
@@ -399,7 +399,10 @@ const ensureSuffix = (str, suffix) => str.endsWith(suffix) ? str : str + suffix;
399
399
  * // ⚠️ 空字符串会返回 'undefined'
400
400
  * ```
401
401
  */
402
- const capitalize = (str) => str[0].toUpperCase() + str.slice(1).toLowerCase();
402
+ const capitalize = (str) => {
403
+ if (str.length === 0) return str;
404
+ return str[0].toUpperCase() + str.slice(1).toLowerCase();
405
+ };
403
406
 
404
407
  //#endregion
405
408
  //#region src/base/date.ts
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jiakun-zhao/utils",
3
3
  "type": "module",
4
- "version": "1.4.4",
4
+ "version": "1.4.5",
5
5
  "description": "Utils.",
6
6
  "author": "Jiakun Zhao <hi@zhaojiakun.com>",
7
7
  "license": "MIT",
@@ -17,24 +17,22 @@
17
17
  ".": {
18
18
  "import": "./dist/index.mjs",
19
19
  "types": "./dist/index.d.mts"
20
- },
21
- "./llms.txt": "./llms.txt"
20
+ }
22
21
  },
23
22
  "main": "./dist/index.mjs",
24
23
  "module": "./dist/index.mjs",
25
24
  "types": "./dist/index.d.mts",
26
25
  "files": [
27
- "dist",
28
- "llms.txt"
26
+ "dist"
29
27
  ],
30
28
  "devDependencies": {
31
29
  "@jiakun-zhao/eslint-config": "^4.2.0",
32
- "@types/node": "^25.0.9",
30
+ "@types/node": "^25.0.10",
33
31
  "bumpp": "^10.4.0",
34
32
  "eslint": "^9.39.2",
35
- "tsdown": "^0.20.0-beta.3",
33
+ "tsdown": "^0.20.1",
36
34
  "typescript": "^5.9.3",
37
- "vitest": "^4.0.17"
35
+ "vitest": "^4.0.18"
38
36
  },
39
37
  "scripts": {
40
38
  "build": "tsdown",
package/llms.txt DELETED
@@ -1,596 +0,0 @@
1
- # @jiakun-zhao/utils
2
-
3
- ## 目录
4
-
5
- - [类型定义](#类型定义)
6
- - [数组工具](#数组工具)
7
- - [字符串工具](#字符串工具)
8
- - [对象工具](#对象工具)
9
- - [数字工具](#数字工具)
10
- - [日期工具](#日期工具)
11
- - [函数工具](#函数工具)
12
- - [布尔工具](#布尔工具)
13
- - [正则工具](#正则工具)
14
- - [null/undefined 工具](#nullundefined-工具)
15
- - [扩展工具](#扩展工具)
16
-
17
- ---
18
-
19
- ## 类型定义
20
-
21
- ### ElementOf<T>
22
- 获取数组元素的类型
23
-
24
- ```typescript
25
- type ElementType = ElementOf<string[]> // string
26
- type ElementType2 = ElementOf<number[]> // number
27
- ```
28
-
29
- ### Arrayable<T>
30
- 可数组的类型,可以是单个值或数组
31
-
32
- ```typescript
33
- type StringOrArray = Arrayable<string> // string | string[]
34
- function process(val: Arrayable<string>) {
35
- const arr = toArray(val) // 总是得到 string[]
36
- }
37
- ```
38
-
39
- ### Nullable<T>
40
- 可为空值的类型,包含 T、null 或 undefined
41
-
42
- ```typescript
43
- type StringOrNull = Nullable<string> // string | null | undefined
44
- const val1: StringOrNull = 'hello'
45
- const val2: StringOrNull = null
46
- const val3: StringOrNull = undefined
47
- ```
48
-
49
- ### Awaitable<T>
50
- 可等待的类型,可以是普通值或 Promise
51
-
52
- ```typescript
53
- async function process<T>(value: Awaitable<T>): Promise<T> {
54
- return await value
55
- }
56
-
57
- process('hello') // 返回 Promise<'hello'>
58
- process(Promise.resolve('hello')) // 返回 Promise<'hello'>
59
- ```
60
-
61
- ### Fn<T>
62
- 函数类型定义
63
-
64
- ```typescript
65
- type MyFunc = Fn<string> // () => string
66
- const fn: MyFunc = () => 'hello'
67
- ```
68
-
69
- ---
70
-
71
- ## 数组工具
72
-
73
- ### isArray
74
- 判断值是否为数组
75
-
76
- ```typescript
77
- isArray([]) // true
78
- isArray([1, 2, 3]) // true
79
- isArray('') // false
80
- isArray(null) // false
81
- ```
82
-
83
- ### toArray
84
- 将值转换为数组,如果已经是数组则返回原数组
85
-
86
- ```typescript
87
- toArray(1) // [1]
88
- toArray([1, 2, 3]) // [1, 2, 3]
89
- toArray('hello') // ['hello']
90
- toArray(null) // [null]
91
- ```
92
-
93
- ### uniq
94
- 数组去重
95
-
96
- ```typescript
97
- uniq([1, 2, 2, 3, 3, 3]) // [1, 2, 3]
98
- uniq(['a', 'b', 'a', 'c']) // ['a', 'b', 'c']
99
- uniq([]) // []
100
- ```
101
-
102
- ### singleOrNull
103
- 获取数组的单个元素,如果数组只有一个元素则返回该元素,否则返回 null
104
-
105
- ```typescript
106
- singleOrNull([1]) // 1
107
- singleOrNull(['only']) // 'only'
108
- singleOrNull([]) // null
109
- singleOrNull([1, 2, 3]) // null
110
- ```
111
-
112
- ### createArray
113
- 创建指定长度的数组
114
-
115
- ```typescript
116
- createArray(3) // [0, 1, 2]
117
- createArray(3, (i) => i * 2) // [0, 2, 4]
118
- createArray(5, (i) => `item-${i}`) // ['item-0', 'item-1', 'item-2', 'item-3', 'item-4']
119
- createArray(0) // []
120
- ```
121
-
122
- ### shuffle
123
- 随机打乱数组(会修改原数组)
124
-
125
- ```typescript
126
- const arr = [1, 2, 3, 4, 5]
127
- shuffle(arr) // [3, 1, 5, 2, 4] (随机顺序)
128
- // ⚠️ 原数组也会被修改
129
- ```
130
-
131
- ### range
132
- 生成数字范围序列
133
-
134
- ```typescript
135
- range(5) // [0, 1, 2, 3, 4]
136
- range(1, 5) // [1, 2, 3, 4]
137
- range(0, 10, 2) // [0, 2, 4, 6, 8]
138
- range(1, 1) // []
139
- range(0, 0) // []
140
- ```
141
-
142
- ---
143
-
144
- ## 字符串工具
145
-
146
- ### toString
147
- 获取值的字符串表示形式
148
-
149
- ```typescript
150
- toString({}) // '[object Object]'
151
- toString([]) // '[object Array]'
152
- toString(null) // '[object Null]'
153
- toString(undefined) // '[object Undefined]'
154
- toString(123) // '[object Number]'
155
- ```
156
-
157
- ### isString
158
- 判断值是否为字符串
159
-
160
- ```typescript
161
- isString('hello') // true
162
- isString('') // true
163
- isString(123) // false
164
- isString(null) // false
165
- ```
166
-
167
- ### slash
168
- 将反斜杠转换为正斜杠
169
-
170
- ```typescript
171
- slash('C:\\Users\\test') // 'C:/Users/test'
172
- slash('path\\to\\file') // 'path/to/file'
173
- slash('path/to/file') // 'path/to/file'
174
- ```
175
-
176
- ### ensurePrefix
177
- 确保字符串以指定前缀开头
178
-
179
- ```typescript
180
- ensurePrefix('example.com', 'https://') // 'https://example.com'
181
- ensurePrefix('https://example.com', 'https://') // 'https://example.com'
182
- ensurePrefix('path', '/') // '/path'
183
- ```
184
-
185
- ### ensureSuffix
186
- 确保字符串以指定后缀结尾
187
-
188
- ```typescript
189
- ensureSuffix('file', '.json') // 'file.json'
190
- ensureSuffix('file.json', '.json') // 'file.json'
191
- ensureSuffix('path', '/') // 'path/'
192
- ```
193
-
194
- ### capitalize
195
- 将字符串首字母大写,其余字母小写
196
-
197
- ```typescript
198
- capitalize('hello') // 'Hello'
199
- capitalize('HELLO') // 'Hello'
200
- capitalize('hELLO') // 'Hello'
201
- capitalize('hello world') // 'Hello world'
202
- // ⚠️ 空字符串会返回 'undefined'
203
- ```
204
-
205
- ---
206
-
207
- ## 对象工具
208
-
209
- ### isObject
210
- 判断值是否为普通对象
211
-
212
- ```typescript
213
- isObject({}) // true
214
- isObject({ a: 1 }) // true
215
- isObject([]) // false
216
- isObject(null) // false
217
- isObject(new Date()) // false
218
- ```
219
-
220
- ### isKeyOf
221
- 判断键是否为对象的键
222
-
223
- ```typescript
224
- const obj = { a: 1, b: 2, c: 3 }
225
- isKeyOf(obj, 'a') // true
226
- isKeyOf(obj, 'b') // true
227
- isKeyOf(obj, 'd') // false
228
- // 注意:isKeyOf 使用 'key in val',所以继承属性也会返回 true
229
- isKeyOf(obj, 'toString') // true
230
- ```
231
-
232
- ### objectFilter
233
- 根据条件过滤对象的属性
234
-
235
- ```typescript
236
- const obj = { a: 1, b: 2, c: 3, d: 4 }
237
- objectFilter(obj, (key, value) => value > 2) // { c: 3, d: 4 }
238
- objectFilter(obj, (key, value) => key === 'a') // { a: 1 }
239
- ```
240
-
241
- ### objectPick
242
- 从对象中选取指定的属性
243
-
244
- ```typescript
245
- const obj = { a: 1, b: 2, c: 3, d: 4 }
246
- objectPick(obj, 'a', 'c') // { a: 1, c: 3 }
247
- objectPick(obj, 'a', 'x') // { a: 1 }
248
- objectPick(obj) // {}
249
- ```
250
-
251
- ### objectOmit
252
- 从对象中排除指定的属性
253
-
254
- ```typescript
255
- const obj = { a: 1, b: 2, c: 3, d: 4 }
256
- objectOmit(obj, 'a', 'c') // { b: 2, d: 4 }
257
- objectOmit(obj, 'a', 'x') // { b: 2, c: 3, d: 4 }
258
- objectOmit(obj) // { a: 1, b: 2, c: 3, d: 4 }
259
- ```
260
-
261
- ### clearUndefined
262
- 清除对象中值为 undefined 的属性
263
-
264
- ```typescript
265
- clearUndefined({ a: 1, b: undefined, c: 3 }) // { a: 1, c: 3 }
266
- clearUndefined({ a: undefined }) // {}
267
- clearUndefined({ a: null, b: undefined }) // { a: null } // null 不会被清除
268
- ```
269
-
270
- ---
271
-
272
- ## 数字工具
273
-
274
- ### isNumber
275
- 判断值是否为数字类型
276
-
277
- ```typescript
278
- isNumber(0) // true
279
- isNumber(1) // true
280
- isNumber(1.5) // true
281
- isNumber(Number.NaN) // true
282
- isNumber(Number.POSITIVE_INFINITY) // true
283
- isNumber('123') // false
284
- isNumber(null) // false
285
- ```
286
-
287
- ### clamp
288
- 将值限制在指定范围内
289
-
290
- ```typescript
291
- clamp(5, 0, 10) // 5 (在范围内)
292
- clamp(-5, 0, 10) // 0 (小于最小值,返回最小值)
293
- clamp(15, 0, 10) // 10 (大于最大值,返回最大值)
294
- clamp(1.5, 0, 1) // 1
295
- clamp(0.5, 0, 1) // 0.5
296
- ```
297
-
298
- ### lerp
299
- 线性插值,返回两个值之间的插值
300
-
301
- ```typescript
302
- lerp(0, 100, 0.5) // 50 (中点)
303
- lerp(0, 100, 0) // 0 (起始点)
304
- lerp(0, 100, 1) // 100 (结束点)
305
- lerp(0, 100, -0.5) // 0 (t 被限制到 0)
306
- lerp(0, 100, 1.5) // 100 (t 被限制到 1)
307
- lerp(-100, 0, 0.5) // -50
308
- lerp(0, 10, 0.25) // 2.5
309
- ```
310
-
311
- ---
312
-
313
- ## 日期工具
314
-
315
- ### isDate
316
- 判断值是否为 Date 对象
317
-
318
- ```typescript
319
- isDate(new Date()) // true
320
- isDate(new Date('2024-01-01')) // true
321
- isDate('2024-01-01') // false
322
- isDate(null) // false
323
- ```
324
-
325
- ### timestamp
326
- 获取当前时间戳(毫秒)
327
-
328
- ```typescript
329
- timestamp() // 1705401600000
330
- ```
331
-
332
- ### isToDay
333
- 判断日期是否为今天
334
-
335
- ```typescript
336
- isToDay(new Date()) // true
337
- isToDay(new Date('2000-01-01')) // false
338
- ```
339
-
340
- ### isSameDay
341
- 判断两个日期是否为同一天
342
-
343
- ```typescript
344
- const date1 = new Date('2024-01-15T10:30:00')
345
- const date2 = new Date('2024-01-15T23:59:59')
346
- isSameDay(date1, date2) // true
347
- ```
348
-
349
- ```typescript
350
- const date1 = new Date('2024-01-15')
351
- const date2 = new Date('2024-01-16')
352
- isSameDay(date1, date2) // false
353
- ```
354
-
355
- ---
356
-
357
- ## 函数工具
358
-
359
- ### isFunction
360
- 判断值是否为函数
361
-
362
- ```typescript
363
- isFunction(() => {}) // true
364
- isFunction(function() {}) // true
365
- isFunction('function') // false
366
- isFunction(null) // false
367
- ```
368
-
369
- ### noop
370
- 空函数,什么都不做
371
-
372
- ```typescript
373
- const callback: Fn = noop // 作为默认回调
374
- callback() // 什么都不执行
375
- ```
376
-
377
- ### transform
378
- 对值应用转换函数
379
-
380
- ```typescript
381
- transform(5, (x) => x * 2) // 10
382
- transform('hello', (s) => s.toUpperCase()) // 'HELLO'
383
- transform([1, 2, 3], (arr) => arr.length) // 3
384
- ```
385
-
386
- ---
387
-
388
- ## 布尔工具
389
-
390
- ### isBoolean
391
- 判断值是否为布尔类型
392
-
393
- ```typescript
394
- isBoolean(true) // true
395
- isBoolean(false) // true
396
- isBoolean('true') // false
397
- isBoolean(1) // false
398
- isBoolean(null) // false
399
- ```
400
-
401
- ---
402
-
403
- ## 正则工具
404
-
405
- ### isRegExp
406
- 判断值是否为正则表达式
407
-
408
- ```typescript
409
- isRegExp(/test/) // true
410
- isRegExp(new RegExp('test')) // true
411
- isRegExp('test') // false
412
- isRegExp(null) // false
413
- ```
414
-
415
- ---
416
-
417
- ## null/undefined 工具
418
-
419
- ### isTruthy
420
- 判断值是否为真值
421
-
422
- ```typescript
423
- isTruthy(true) // true
424
- isTruthy(1) // true
425
- isTruthy('hello') // true
426
- isTruthy({}) // true
427
- isTruthy([]) // true
428
- isTruthy(false) // false
429
- isTruthy(0) // false
430
- isTruthy('') // false
431
- isTruthy(null) // false
432
- isTruthy(undefined) // false
433
- ```
434
-
435
- ### isUndefined
436
- 判断值是否为 undefined
437
-
438
- ```typescript
439
- isUndefined(undefined) // true
440
- isUndefined(void 0) // true
441
- isUndefined(null) // false
442
- isUndefined('') // false
443
- ```
444
-
445
- ### notUndefined
446
- 判断值是否不为 undefined
447
-
448
- ```typescript
449
- notUndefined('hello') // true
450
- notUndefined(0) // true
451
- notUndefined(null) // true
452
- notUndefined(undefined) // false
453
- ```
454
-
455
- ### isNull
456
- 判断值是否为 null
457
-
458
- ```typescript
459
- isNull(null) // true
460
- isNull(undefined) // false
461
- isNull('') // false
462
- isNull(0) // false
463
- ```
464
-
465
- ### notNull
466
- 判断值是否不为 null
467
-
468
- ```typescript
469
- notNull('hello') // true
470
- notNull(0) // true
471
- notNull(undefined) // true
472
- notNull(null) // false
473
- ```
474
-
475
- ### notNullish
476
- 判断值是否不为 null 且不为 undefined
477
-
478
- ```typescript
479
- notNullish('hello') // true
480
- notNullish(0) // true
481
- notNullish(false) // true
482
- notNullish(null) // false
483
- notNullish(undefined) // false
484
- ```
485
-
486
- ### isDefined
487
- 判断值是否已定义(不是 undefined)
488
-
489
- ```typescript
490
- isDefined('hello') // true
491
- isDefined(0) // true
492
- isDefined(null) // true
493
- isDefined(false) // true
494
- isDefined(undefined) // false
495
- ```
496
-
497
- ---
498
-
499
- ## 扩展工具
500
-
501
- ### assert
502
- 断言函数,当条件为 false 时抛出错误
503
-
504
- ```typescript
505
- assert(true, '不会抛出错误') // 正常执行
506
- assert(false, '会抛出错误') // 抛出 Error: 会抛出错误
507
- ```
508
-
509
- ### isDeepEqual
510
- 深度比较两个值是否相等
511
- 支持 Array、Object、RegExp、Date 等类型的比较
512
-
513
- ```typescript
514
- isDeepEqual(1, 1) // true
515
- isDeepEqual({}, {}) // true
516
- isDeepEqual('foo', 'foo') // true
517
- isDeepEqual([1, 2, 3], [1, 2, 3]) // true
518
- isDeepEqual(isDeepEqual, isDeepEqual) // true
519
- isDeepEqual(/foo/, /foo/) // true
520
- isDeepEqual(null, null) // true
521
- isDeepEqual(Number.NaN, Number.NaN) // true
522
- isDeepEqual([], []) // true
523
- isDeepEqual([{ a: 1 }, [{ b: { c: [1] } }]], [{ a: 1 }, [{ b: { c: [1] } }]]) // true
524
- isDeepEqual(1, '1') // false
525
- isDeepEqual(null, undefined) // false
526
- isDeepEqual({ a: 1, b: [2, 3] }, { a: 1, b: [2, 5] }) // false
527
- isDeepEqual(/foo/i, /bar/g) // false
528
- ```
529
-
530
- ### naturalCompare
531
- 自然排序比较函数,按自然语言顺序比较字符串或数字
532
- 类似文件名排序,"file2" < "file10"
533
-
534
- ```typescript
535
- naturalCompare(1, 2) // -1
536
- naturalCompare(2, 1) // 1
537
- naturalCompare(1, 1) // 0
538
-
539
- naturalCompare('a', 'b') // -1
540
- naturalCompare('b', 'a') // 1
541
- naturalCompare('a', 'a') // 0
542
-
543
- // 数字字符串按数值大小排序,而不是字典序
544
- naturalCompare('file1', 'file2') // -1
545
- naturalCompare('file2', 'file10') // -1 (2 < 10 自然顺序)
546
- naturalCompare('file10', 'file2') // 1
547
-
548
- // 用于数组排序
549
- ['file10.txt', 'file2.txt', 'file1.txt'].sort(naturalCompare) // ['file1.txt', 'file2.txt', 'file10.txt']
550
-
551
- // 版本号比较
552
- naturalCompare('v1.0.1', 'v1.0.10') // -1
553
- naturalCompare('v1.0.10', 'v1.0.2') // 1
554
- ```
555
-
556
- ### status
557
- HTTP 状态码及其对应的描述信息
558
- 包含了所有标准的 HTTP 状态码
559
-
560
- ```typescript
561
- status[200] // 'OK'
562
- status[404] // 'Not Found'
563
- status[500] // 'Internal Server Error'
564
- status[418] // "I'm a Teapot"
565
- ```
566
-
567
- ### getHttpStatusMessage
568
- 根据 HTTP 状态码获取对应的描述信息
569
-
570
- ```typescript
571
- getHttpStatusMessage(200) // 'OK'
572
- getHttpStatusMessage(404) // 'Not Found'
573
- getHttpStatusMessage(500) // 'Internal Server Error'
574
- getHttpStatusMessage(418) // "I'm a Teapot"
575
- ```
576
-
577
- ---
578
-
579
- ## 已知问题
580
-
581
- ### shuffle
582
- 会修改原数组,而不是返回新数组。建议使用前先复制数组。
583
-
584
- ### capitalize
585
- 空字符串会返回 `'undefined'`,建议在使用前检查空字符串。
586
-
587
- ### isSameDay
588
- 使用本地日期方法,对时区敏感。不同时区的相同日期可能返回 false。
589
-
590
- ### clearUndefined
591
- 只会清除 `undefined`,不会清除 `null`。
592
-
593
- ### isDeepEqual
594
- 没有处理循环引用,循环引用会导致栈溢出。
595
-
596
- ---