@nickyzj2023/utils 1.0.56 → 1.0.58

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.
@@ -1,17 +1,18 @@
1
+ //#region src/dom/log.d.ts
1
2
  /**
2
3
  * log 配置选项
3
4
  */
4
5
  interface LogOptions {
5
- /**
6
- * 是否显示时间
7
- * @default true
8
- */
9
- time?: boolean;
10
- /**
11
- * 是否显示调用者文件名
12
- * @default true
13
- */
14
- fileName?: boolean;
6
+ /**
7
+ * 是否显示时间
8
+ * @default true
9
+ */
10
+ time?: boolean;
11
+ /**
12
+ * 是否显示调用者文件名
13
+ * @default true
14
+ */
15
+ fileName?: boolean;
15
16
  }
16
17
  /**
17
18
  * 带额外信息的 console.log
@@ -26,7 +27,8 @@ interface LogOptions {
26
27
  * log(["消息1", "消息2"]); // "[14:30:00] [index.ts:15] 消息1 消息2"
27
28
  */
28
29
  declare const log: (message: any | any[], options?: LogOptions) => void;
29
-
30
+ //#endregion
31
+ //#region src/function/loop-until.d.ts
30
32
  /**
31
33
  * 循环执行函数,直到符合停止条件
32
34
  *
@@ -55,15 +57,15 @@ declare const log: (message: any | any[], options?: LogOptions) => void;
55
57
  * ),
56
58
  */
57
59
  declare const loopUntil: <T>(fn: (count: number) => T | Promise<T>, options?: {
58
- /**
59
- * 最大循环次数
60
- * @default 5
61
- */
62
- maxRetries?: number;
63
- /** 停止循环条件。如果未传递,则执行 maxRetries 次后退出并返回最后结果 */
64
- shouldStop?: (result: T) => boolean;
60
+ /**
61
+ * 最大循环次数
62
+ * @default 5
63
+ */
64
+ maxRetries?: number; /** 停止循环条件。如果未传递,则执行 maxRetries 次后退出并返回最后结果 */
65
+ shouldStop?: (result: T) => boolean;
65
66
  }) => Promise<T>;
66
-
67
+ //#endregion
68
+ //#region src/hoc/with-cache.d.ts
67
69
  type SetTtl = (seconds: number) => void;
68
70
  /**
69
71
  * 创建一个带缓存的高阶函数
@@ -100,13 +102,14 @@ type SetTtl = (seconds: number) => void;
100
102
  * await fetchData(urlB); // 使用缓存结果
101
103
  */
102
104
  declare const withCache: <Args extends any[], Result>(fn: (this: {
103
- setTtl: SetTtl;
105
+ setTtl: SetTtl;
104
106
  }, ...args: Args) => Result, ttlSeconds?: number) => {
105
- (...args: Args): Result;
106
- clear(): void;
107
- updateTtl(seconds: number): void;
107
+ (...args: Args): Result;
108
+ clear(): void;
109
+ updateTtl(seconds: number): void;
108
110
  };
109
-
111
+ //#endregion
112
+ //#region src/is/is-falsy.d.ts
110
113
  type Falsy = false | 0 | -0 | 0n | "" | null | undefined;
111
114
  /**
112
115
  * 检测传入的值是否为**假值**(false、0、''、null、undefined、NaN等)
@@ -116,7 +119,8 @@ type Falsy = false | 0 | -0 | 0n | "" | null | undefined;
116
119
  * isFalsy(1); // false
117
120
  */
118
121
  declare const isFalsy: (value: any) => value is Falsy;
119
-
122
+ //#endregion
123
+ //#region src/is/is-nil.d.ts
120
124
  /**
121
125
  * 检测传入的值是否为**空值**(null、undefined)
122
126
  *
@@ -126,7 +130,8 @@ declare const isFalsy: (value: any) => value is Falsy;
126
130
  * isNil(1); // false
127
131
  */
128
132
  declare const isNil: (value: any) => value is null | undefined;
129
-
133
+ //#endregion
134
+ //#region src/is/is-object.d.ts
130
135
  /**
131
136
  * 检测传入的值是否为**普通对象**
132
137
  *
@@ -135,7 +140,8 @@ declare const isNil: (value: any) => value is null | undefined;
135
140
  * isObject(obj); // true
136
141
  */
137
142
  declare const isObject: (value: any) => value is Record<string, any>;
138
-
143
+ //#endregion
144
+ //#region src/is/is-primitive.d.ts
139
145
  type Primitive = number | string | boolean | symbol | bigint | undefined | null;
140
146
  /**
141
147
  * 检测传入的值是否为**原始值**(number、string、boolean、symbol、bigint、undefined、null)
@@ -145,14 +151,14 @@ type Primitive = number | string | boolean | symbol | bigint | undefined | null;
145
151
  * isPrimitive([]); // false
146
152
  */
147
153
  declare const isPrimitive: (value: any) => value is Primitive;
148
-
154
+ //#endregion
155
+ //#region src/network/fetcher.d.ts
149
156
  type FetchOptions = {
150
- /** 代理服务器配置 */
151
- proxy?: string;
157
+ /** 代理服务器配置 */proxy?: string;
152
158
  };
153
159
  type RequestInit = globalThis.RequestInit & FetchOptions & {
154
- params?: Record<string, any>;
155
- parser?: (response: Response) => Promise<any>;
160
+ params?: Record<string, any>;
161
+ parser?: (response: Response) => Promise<any>;
156
162
  };
157
163
  /**
158
164
  * 基于 Fetch API 的请求客户端
@@ -197,36 +203,37 @@ type RequestInit = globalThis.RequestInit & FetchOptions & {
197
203
  * await getBlogs("/blogs"); // 不发请求,使用缓存
198
204
  */
199
205
  declare const fetcher: (baseURL?: string, baseOptions?: RequestInit) => {
200
- get: <T>(url: string, options?: Omit<RequestInit, "method">) => Promise<T>;
201
- post: <T>(url: string, body: any, options?: Omit<RequestInit, "method" | "body">) => Promise<T>;
202
- put: <T>(url: string, body: any, options?: Omit<RequestInit, "method" | "body">) => Promise<T>;
203
- delete: <T>(url: string, options?: Omit<RequestInit, "method" | "body">) => Promise<T>;
206
+ get: <T>(url: string, options?: Omit<RequestInit, "method">) => Promise<T>;
207
+ post: <T>(url: string, body: any, options?: Omit<RequestInit, "method" | "body">) => Promise<T>;
208
+ put: <T>(url: string, body: any, options?: Omit<RequestInit, "method" | "body">) => Promise<T>;
209
+ delete: <T>(url: string, options?: Omit<RequestInit, "method" | "body">) => Promise<T>;
204
210
  };
205
-
211
+ //#endregion
212
+ //#region src/network/get-real-url.d.ts
206
213
  /** 从 url 响应头获取真实链接 */
207
214
  declare const getRealURL: (originURL: string) => Promise<string>;
208
-
215
+ //#endregion
216
+ //#region src/network/image.d.ts
209
217
  /**
210
218
  * 图片压缩选项
211
219
  */
212
220
  type ImageCompressionOptions = {
213
- /** 压缩比率,默认 0.92 */
214
- quality?: number;
215
- /**
216
- * 自定义压缩函数,用于覆盖默认压缩行为
217
- * @param arrayBuffer 图片的 ArrayBuffer 数据
218
- * @param mime 图片的 MIME 类型
219
- * @param quality 压缩质量
220
- * @returns 压缩后的 base64 字符串
221
- */
222
- compressor?: (arrayBuffer: ArrayBuffer, mime: string, quality: number) => Promise<string> | string;
223
- /**
224
- * 自定义 fetch 函数,用于使用自己封装的请求库读取图片
225
- * 必须返回符合 Web 标准的 Response 对象
226
- * @param url 图片地址
227
- * @returns Promise<Response>
228
- */
229
- fetcher?: (url: string) => Promise<Response>;
221
+ /** 压缩比率,默认 0.92 */quality?: number;
222
+ /**
223
+ * 自定义压缩函数,用于覆盖默认压缩行为
224
+ * @param arrayBuffer 图片的 ArrayBuffer 数据
225
+ * @param mime 图片的 MIME 类型
226
+ * @param quality 压缩质量
227
+ * @returns 压缩后的 base64 字符串
228
+ */
229
+ compressor?: (arrayBuffer: ArrayBuffer, mime: string, quality: number) => Promise<string> | string;
230
+ /**
231
+ * 自定义 fetch 函数,用于使用自己封装的请求库读取图片
232
+ * 必须返回符合 Web 标准的 Response 对象
233
+ * @param url 图片地址
234
+ * @returns Promise<Response>
235
+ */
236
+ fetcher?: (url: string) => Promise<Response>;
230
237
  };
231
238
  /**
232
239
  * 图片地址转 base64 数据
@@ -265,7 +272,8 @@ type ImageCompressionOptions = {
265
272
  * });
266
273
  */
267
274
  declare const imageUrlToBase64: (imageUrl: string, options?: ImageCompressionOptions) => Promise<string>;
268
-
275
+ //#endregion
276
+ //#region src/network/to.d.ts
269
277
  /**
270
278
  * Go 语言风格的异步处理方式
271
279
  * @param promise 一个能被 await 的异步函数
@@ -275,7 +283,8 @@ declare const imageUrlToBase64: (imageUrl: string, options?: ImageCompressionOpt
275
283
  * const [error, response] = await to(fetcher().get<Blog>("/blogs/hello-world"));
276
284
  */
277
285
  declare const to: <T, E = Error>(promise: Promise<T>) => Promise<[null, T] | [E, undefined]>;
278
-
286
+ //#endregion
287
+ //#region src/number/random-int.d.ts
279
288
  /**
280
289
  * 在指定闭区间内生成随机整数
281
290
  *
@@ -283,9 +292,10 @@ declare const to: <T, E = Error>(promise: Promise<T>) => Promise<[null, T] | [E,
283
292
  * randomInt(1, 10); // 1 <= x <= 10
284
293
  */
285
294
  declare const randomInt: (min: number, max: number) => number;
286
-
295
+ //#endregion
296
+ //#region src/object/map-keys.d.ts
287
297
  type DeepMapKeys<T> = T extends Array<infer U> ? Array<DeepMapKeys<U>> : T extends object ? {
288
- [key: string]: DeepMapKeys<T[keyof T]>;
298
+ [key: string]: DeepMapKeys<T[keyof T]>;
289
299
  } : T;
290
300
  /**
291
301
  * 递归处理对象里的 key
@@ -301,10 +311,9 @@ type DeepMapKeys<T> = T extends Array<infer U> ? Array<DeepMapKeys<U>> : T exten
301
311
  * console.log(result); // { A: { B: 1 } }
302
312
  */
303
313
  declare const mapKeys: <T>(obj: T, getNewKey: (key: string) => string) => DeepMapKeys<T>;
304
-
305
- type DeepMapValues<T, R> = T extends Array<infer U> ? Array<DeepMapValues<U, R>> : T extends object ? {
306
- [K in keyof T]: T[K] extends object ? DeepMapValues<T[K], R> : R;
307
- } : R;
314
+ //#endregion
315
+ //#region src/object/map-values.d.ts
316
+ type DeepMapValues<T, R> = T extends Array<infer U> ? Array<DeepMapValues<U, R>> : T extends object ? { [K in keyof T]: T[K] extends object ? DeepMapValues<T[K], R> : R } : R;
308
317
  /**
309
318
  * 递归处理对象里的 value
310
319
  *
@@ -320,10 +329,10 @@ type DeepMapValues<T, R> = T extends Array<infer U> ? Array<DeepMapValues<U, R>>
320
329
  * console.log(result); // { a: 2, b: { c: 3 } }
321
330
  */
322
331
  declare const mapValues: <T, R = any>(obj: T, getNewValue: (value: any, key: string | number) => R, options?: {
323
- /** 过滤函数,返回 true 表示保留该字段 */
324
- filter?: (value: any, key: string | number) => boolean;
332
+ /** 过滤函数,返回 true 表示保留该字段 */filter?: (value: any, key: string | number) => boolean;
325
333
  }) => DeepMapValues<T, R>;
326
-
334
+ //#endregion
335
+ //#region src/object/merge-objects.d.ts
327
336
  /**
328
337
  * 深度合并两个对象,规则如下:
329
338
  * 1. 原始值覆盖:如果两个值都是原始类型,则用后者覆盖;
@@ -336,7 +345,8 @@ declare const mapValues: <T, R = any>(obj: T, getNewValue: (value: any, key: str
336
345
  * @param {U} obj2 要合并的第二个对象
337
346
  */
338
347
  declare const mergeObjects: <T extends Record<string, any>, U extends Record<string, any>>(obj1: T, obj2: U) => T & U;
339
-
348
+ //#endregion
349
+ //#region src/string/case.d.ts
340
350
  type SnakeToCamel<S extends string> = S extends `${infer Before}_${infer After}` ? After extends `${infer First}${infer Rest}` ? `${Before}${Uppercase<First>}${SnakeToCamel<Rest>}` : Before : S;
341
351
  /**
342
352
  * 下划线命名法转为驼峰命名法
@@ -369,7 +379,8 @@ type Decapitalize<S extends string> = S extends `${infer P1}${infer Rest}` ? P1
369
379
  * decapitalize("Hello") // "hello"
370
380
  */
371
381
  declare const decapitalize: <S extends string>(s: S) => Decapitalize<S>;
372
-
382
+ //#endregion
383
+ //#region src/string/compact.d.ts
373
384
  /**
374
385
  * 将字符串压缩为单行精简格式
375
386
  *
@@ -383,16 +394,31 @@ declare const decapitalize: <S extends string>(s: S) => Decapitalize<S>;
383
394
  * });
384
395
  */
385
396
  declare const compactStr: (text?: string, options?: {
386
- /** 最大保留长度,设为 0 或 Infinity 则不截断,默认 Infinity */
387
- maxLength?: number;
388
- /** 是否将换行符替换为字面量 \n,默认开启 */
389
- disableNewLineReplace?: boolean;
390
- /** 是否合并连续的空格/制表符为一个空格,默认开启 */
391
- disableWhitespaceCollapse?: boolean;
392
- /** 截断后的后缀,默认为 "..." */
393
- omission?: string;
397
+ /** 最大保留长度,设为 0 或 Infinity 则不截断,默认 Infinity */maxLength?: number; /** 是否将换行符替换为字面量 \n,默认开启 */
398
+ disableNewLineReplace?: boolean; /** 是否合并连续的空格/制表符为一个空格,默认开启 */
399
+ disableWhitespaceCollapse?: boolean; /** 截断后的后缀,默认为 "..." */
400
+ omission?: string;
394
401
  }) => string;
395
-
402
+ //#endregion
403
+ //#region src/string/qs.d.ts
404
+ /**
405
+ * 针对 URL 查询字符串的解析和序列化
406
+ * @example
407
+ * qs.parse("?a=1&b=2") // { a: 1, b: 2 }
408
+ * qs.stringify({ a: 1, b: 2 }, { addQueryPrefix: true }) // "?a=1&b=2"
409
+ */
410
+ declare const qs: {
411
+ /** queryString -> queryParams */parse: (queryString: string) => Record<string, any>;
412
+ stringify: (params: Record<string, any>, options?: {
413
+ /**
414
+ * 是否在结果前添加“?”
415
+ * @default false
416
+ */
417
+ addQueryPrefix: boolean;
418
+ }) => string;
419
+ };
420
+ //#endregion
421
+ //#region src/time/debounce.d.ts
396
422
  /**
397
423
  * 防抖:在指定时间内只执行最后一次调用
398
424
  * @param fn 要防抖的函数
@@ -413,7 +439,8 @@ declare const compactStr: (text?: string, options?: {
413
439
  * search('hello'); // 300ms 后执行
414
440
  */
415
441
  declare const debounce: <T extends (...args: any[]) => any>(fn: T, delay?: number) => (...args: Parameters<T>) => void;
416
-
442
+ //#endregion
443
+ //#region src/time/sleep.d.ts
417
444
  /**
418
445
  * 延迟一段时间再执行后续代码
419
446
  * @param time 延迟时间,默认 150ms
@@ -421,7 +448,8 @@ declare const debounce: <T extends (...args: any[]) => any>(fn: T, delay?: numbe
421
448
  * await sleep(1000); // 等待 1 秒执行后续代码
422
449
  */
423
450
  declare const sleep: (time?: number) => Promise<unknown>;
424
-
451
+ //#endregion
452
+ //#region src/time/throttle.d.ts
425
453
  /**
426
454
  * 节流函数 - 在指定时间间隔内最多执行一次调用
427
455
  * @param fn 要节流的函数
@@ -442,5 +470,5 @@ declare const sleep: (time?: number) => Promise<unknown>;
442
470
  * window.addEventListener('scroll', handleScroll);
443
471
  */
444
472
  declare const throttle: <T extends (...args: any[]) => any>(fn: T, delay?: number) => (this: any, ...args: Parameters<T>) => void;
445
-
446
- export { type CamelToSnake, type Capitalize, type Decapitalize, type DeepMapKeys, type DeepMapValues, type Falsy, type FetchOptions, type ImageCompressionOptions, type LogOptions, type Primitive, type RequestInit, type SetTtl, type SnakeToCamel, camelToSnake, capitalize, compactStr, debounce, decapitalize, fetcher, getRealURL, imageUrlToBase64, isFalsy, isNil, isObject, isPrimitive, log, loopUntil, mapKeys, mapValues, mergeObjects, randomInt, sleep, snakeToCamel, throttle, to, withCache };
473
+ //#endregion
474
+ export { CamelToSnake, Capitalize, Decapitalize, DeepMapKeys, DeepMapValues, Falsy, FetchOptions, ImageCompressionOptions, LogOptions, Primitive, RequestInit, SetTtl, SnakeToCamel, camelToSnake, capitalize, compactStr, debounce, decapitalize, fetcher, getRealURL, imageUrlToBase64, isFalsy, isNil, isObject, isPrimitive, log, loopUntil, mapKeys, mapValues, mergeObjects, qs, randomInt, sleep, snakeToCamel, throttle, to, withCache };
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ const e=(e,t)=>{let{time:n=!0,fileName:r=!0}=t??{},i=[];if(n&&i.push(`[${new Date().toLocaleTimeString()}]`),r){let{stack:e}=Error(),t=(e?.split(`
2
+ `)[2]?.trim())?.match(/at\s+(.*):(\d+)/);if(t?.[1]){let e=t[1].split(/[/\\]/).pop();i.push(`[${e}:${t[2]}]`)}}Array.isArray(e)?i.push(...e):i.push(e),console.log(...i)},t=async(e,t)=>{let{maxRetries:n=5,shouldStop:r}=t??{},i;for(let t=0;t<n;t++)if(i=await e(t),r?.(i)===!0)return i;if(!r)return i;throw Error(`超过了最大循环次数(${n})且未满足停止执行条件`)},n=(e,t=-1)=>{let n=new Map,r=(...r)=>{let i=JSON.stringify(r),a=Date.now(),o=n.get(i);if(o&&a<o.expiresAt)return o.value;let s=t===-1?1/0:a+t*1e3,c=e.apply({setTtl:e=>{s=a+e*1e3}},r);if(c instanceof Promise){let e=c.then(e=>(n.set(i,{value:e,expiresAt:s}),e));return n.set(i,{value:e,expiresAt:s}),e}return n.set(i,{value:c,expiresAt:s}),c};return r.clear=()=>n.clear(),r.updateTtl=e=>{t=e;let r=Date.now(),i=r+e*1e3;for(let[e,t]of n.entries())t.expiresAt>r&&(t.expiresAt=i,n.set(e,t))},r},r=e=>!e,i=e=>e==null,a=e=>e?.constructor===Object,o=e=>e==null||typeof e!=`object`&&typeof e!=`function`,s=(e,t)=>Array.isArray(e)?e.map(e=>s(e,t)):a(e)?Object.keys(e).reduce((n,r)=>{let i=t(r),a=e[r];return n[i]=s(a,t),n},{}):e,c=(e,t,n)=>{let{filter:r}=n??{};if(Array.isArray(e)){let i=e.map((e,r)=>a(e)?c(e,t,n):t(e,r));return r?i.filter((e,t)=>r(e,t)):i}return a(e)?Object.keys(e).reduce((i,o)=>{let s=e[o],l;return l=a(s)||Array.isArray(s)?c(s,t,n):t(s,o),(!r||r(l,o))&&(i[o]=l),i},{}):e},l=(e,t)=>{let n={...e};for(let e of Object.keys(t)){let r=n[e],i=t[e];if(o(r)&&o(i)){n[e]=i;continue}if(Array.isArray(r)&&Array.isArray(i)){n[e]=r.concat(i);continue}if(a(r)&&a(i)){n[e]=l(r,i);continue}n[e]=i}return n},u=(e=``,t={})=>{let n=async(n,r={})=>{let o=new URL(e?`${e}${n}`:n),{params:s,parser:c,...u}=l(t,r);a(s)&&Object.entries(s).forEach(([e,t])=>{i(t)||o.searchParams.append(e,t.toString())}),(a(u.body)||Array.isArray(u.body))&&(u.body=JSON.stringify(u.body),u.headers={...u.headers,"Content-Type":`application/json`});let d=await fetch(o,u);if(!d.ok)throw d.headers.get(`Content-Type`)?.startsWith(`application/json`)?await d.json():Error(d.statusText);return await(c?.(d)??d.json())};return{get:(e,t)=>n(e,{...t,method:`GET`}),post:(e,t,r)=>n(e,{...r,method:`POST`,body:t}),put:(e,t,r)=>n(e,{...r,method:`PUT`,body:t}),delete:(e,t)=>n(e,{...t,method:`DELETE`})}},d=async e=>{try{return[null,await e]}catch(e){return[e,void 0]}},f=async e=>{let[t,n]=await d(fetch(e,{method:`HEAD`,redirect:`manual`}));return t?e:n.headers.get(`location`)||e},p=e=>{let t=new Uint8Array(e),n=``;for(let e=0;e<t.byteLength;e++)n+=String.fromCharCode(t[e]);return btoa(n)},m=async()=>{try{let e=await Function(`modulePath`,`return import(modulePath)`)(`sharp`);return e.default||e}catch{return null}},h=async(e,t,n,r)=>{let i=e(Buffer.from(t));if(n===`image/jpeg`)i=i.jpeg({quality:Math.round(r*100)});else if(n===`image/png`){let e=Math.round((1-r)*9);i=i.png({compressionLevel:e})}return`data:${n};base64,${(await i.toBuffer()).toString(`base64`)}`},g=async(e,t={})=>{let{quality:n=.92,compressor:r,fetcher:i=fetch}=t;if(!e.startsWith(`http`))throw Error(`图片地址必须以http或https开头`);let a=await i(e);if(!a.ok)throw Error(`获取图片失败: ${a.statusText}`);let o=a.headers.get(`Content-Type`)||`image/jpeg`,s=await a.arrayBuffer();if(o!==`image/jpeg`&&o!==`image/png`)return`data:${o};base64,${p(s)}`;if(r)return await r(s,o,n);if(typeof OffscreenCanvas<`u`){let e=null;try{let t=new Blob([s],{type:o});e=await createImageBitmap(t);let r=new OffscreenCanvas(e.width,e.height),i=r.getContext(`2d`);if(!i)throw Error(`无法获取 OffscreenCanvas context`);return i.drawImage(e,0,0),e.close(),e=null,`data:${o};base64,${p(await(await r.convertToBlob({type:o,quality:n})).arrayBuffer())}`}catch{return e?.close(),`data:${o};base64,${p(s)}`}}let c=await m();if(c)try{return await h(c,s,o,n)}catch{return`data:${o};base64,${p(s)}`}return`data:${o};base64,${p(s)}`},_=(e,t)=>Math.floor(Math.random()*(t-e+1))+e,v=e=>e.replace(/_([a-zA-Z])/g,(e,t)=>t.toUpperCase()),y=e=>e.replace(/([A-Z])/g,(e,t)=>`_${t.toLowerCase()}`),b=e=>e.charAt(0).toUpperCase()+e.slice(1),x=e=>e.charAt(0).toLowerCase()+e.slice(1),S=(e=``,t)=>{if(!e)return``;let{maxLength:n=1/0,disableNewLineReplace:r=!1,disableWhitespaceCollapse:i=!1,omission:a=`...`}=t??{},o=e;return o=r?o.replace(/\r?\n/g,` `):o.replace(/\r?\n/g,`\\n`),i||(o=o.replace(/\s+/g,` `)),o=o.trim(),n>0&&o.length>n?o.slice(0,n)+a:o},C={parse:e=>{let t=new URLSearchParams(e),n={};for(let[e,r]of t)Number.isNaN(Number(r))?n[e]=r:n[e]=Number(r);return n},stringify:(e,t)=>{let{addQueryPrefix:n=!1}=t??{},r=new URLSearchParams(e).toString();return r?n?`?${r}`:r:``}},w=(e,t=300)=>{let n=null;return(...r)=>{n&&clearTimeout(n),n=setTimeout(()=>{e(...r)},t)}},T=async(e=150)=>new Promise(t=>{setTimeout(t,e)}),E=(e,t=300)=>{let n=null;return function(...r){n||=setTimeout(()=>{n=null,e.apply(this,r)},t)}};export{y as camelToSnake,b as capitalize,S as compactStr,w as debounce,x as decapitalize,u as fetcher,f as getRealURL,g as imageUrlToBase64,r as isFalsy,i as isNil,a as isObject,o as isPrimitive,e as log,t as loopUntil,s as mapKeys,c as mapValues,l as mergeObjects,C as qs,_ as randomInt,T as sleep,v as snakeToCamel,E as throttle,d as to,n as withCache};
package/package.json CHANGED
@@ -1,20 +1,27 @@
1
1
  {
2
2
  "name": "@nickyzj2023/utils",
3
- "version": "1.0.56",
4
- "repository": {
5
- "type": "git",
6
- "url": "https://github.com/Nickyzj628/utils.git"
7
- },
3
+ "version": "1.0.58",
8
4
  "type": "module",
9
- "module": "dist/index.js",
10
- "types": "dist/index.d.ts",
5
+ "main": "dist/index.mjs",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.mts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.mts",
11
+ "import": "./dist/index.mjs"
12
+ }
13
+ },
11
14
  "files": [
12
15
  "dist"
13
16
  ],
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/Nickyzj628/utils.git"
20
+ },
14
21
  "devDependencies": {
15
22
  "@biomejs/biome": "^2.4.4",
16
- "@types/node": "^25.3.2",
17
- "tsup": "^8.5.1",
23
+ "@types/node": "^25.5.0",
24
+ "tsdown": "^0.21.2",
18
25
  "typedoc": "^0.28.17",
19
26
  "typedoc-material-theme": "^1.4.1"
20
27
  },
@@ -22,7 +29,7 @@
22
29
  "typescript": "^5.9.3"
23
30
  },
24
31
  "scripts": {
25
- "docs": "typedoc src/index.ts --plugin typedoc-material-theme",
26
- "build": "tsup src/index.ts --format esm --dts --minify --out-dir dist && pnpm docs"
32
+ "build": "tsdown",
33
+ "docs": "typedoc src/index.ts --plugin typedoc-material-theme"
27
34
  }
28
- }
35
+ }
package/dist/index.js DELETED
@@ -1,2 +0,0 @@
1
- var P=(e,s)=>{let{time:t=!0,fileName:n=!0}=s??{},a=[];if(t&&a.push(`[${new Date().toLocaleTimeString()}]`),n){let{stack:r}=new Error,i=r?.split(`
2
- `)[2]?.trim()?.match(/at\s+(.*):(\d+)/);if(i?.[1]){let p=i[1].split(/[/\\]/).pop();a.push(`[${p}:${i[2]}]`)}}Array.isArray(e)?a.push(...e):a.push(e),console.log(...a)};var v=async(e,s)=>{let{maxRetries:t=5,shouldStop:n}=s??{},a;for(let r=0;r<t;r++)if(a=await e(r),n?.(a)===!0)return a;if(!n)return a;throw new Error(`\u8D85\u8FC7\u4E86\u6700\u5927\u5FAA\u73AF\u6B21\u6570\uFF08${t}\uFF09\u4E14\u672A\u6EE1\u8DB3\u505C\u6B62\u6267\u884C\u6761\u4EF6`)};var L=(e,s=-1)=>{let t=new Map,n=(...a)=>{let r=JSON.stringify(a),o=Date.now(),i=t.get(r);if(i&&o<i.expiresAt)return i.value;let p=s===-1?1/0:o+s*1e3,f={setTtl:u=>{p=o+u*1e3}},c=e.apply(f,a);if(c instanceof Promise){let u=c.then(m=>(t.set(r,{value:m,expiresAt:p}),m));return t.set(r,{value:u,expiresAt:p}),u}return t.set(r,{value:c,expiresAt:p}),c};return n.clear=()=>t.clear(),n.updateTtl=a=>{s=a;let r=Date.now(),o=r+a*1e3;for(let[i,p]of t.entries())p.expiresAt>r&&(p.expiresAt=o,t.set(i,p))},n};var q=e=>!e;var g=e=>e==null;var l=e=>e?.constructor===Object;var d=e=>e==null||typeof e!="object"&&typeof e!="function";var h=(e,s)=>Array.isArray(e)?e.map(t=>h(t,s)):l(e)?Object.keys(e).reduce((n,a)=>{let r=s(a),o=e[a];return n[r]=h(o,s),n},{}):e;var b=(e,s,t)=>{let{filter:n}=t??{};if(Array.isArray(e)){let a=e.map((r,o)=>l(r)?b(r,s,t):s(r,o));return n?a.filter((r,o)=>n(r,o)):a}return l(e)?Object.keys(e).reduce((r,o)=>{let i=e[o],p;return l(i)||Array.isArray(i)?p=b(i,s,t):p=s(i,o),(!n||n(p,o))&&(r[o]=p),r},{}):e};var x=(e,s)=>{let t={...e};for(let n of Object.keys(s)){let a=t[n],r=s[n];if(d(a)&&d(r)){t[n]=r;continue}if(Array.isArray(a)&&Array.isArray(r)){t[n]=a.concat(r);continue}if(l(a)&&l(r)){t[n]=x(a,r);continue}t[n]=r}return t};var ce=(e="",s={})=>{let t=async(n,a={})=>{let r=new URL(e?`${e}${n}`:n),{params:o,parser:i,...p}=x(s,a);l(o)&&Object.entries(o).forEach(([u,m])=>{g(m)||r.searchParams.append(u,m.toString())}),(l(p.body)||Array.isArray(p.body))&&(p.body=JSON.stringify(p.body),p.headers={...p.headers,"Content-Type":"application/json"});let f=await fetch(r,p);if(!f.ok)throw f.headers.get("Content-Type")?.startsWith("application/json")?await f.json():new Error(f.statusText);return await(i?.(f)??f.json())};return{get:(n,a)=>t(n,{...a,method:"GET"}),post:(n,a,r)=>t(n,{...r,method:"POST",body:a}),put:(n,a,r)=>t(n,{...r,method:"PUT",body:a}),delete:(n,a)=>t(n,{...a,method:"DELETE"})}};var w=async e=>{try{return[null,await e]}catch(s){return[s,void 0]}};var me=async e=>{let[s,t]=await w(fetch(e,{method:"HEAD",redirect:"manual"}));return s?e:t.headers.get("location")||e};var y=e=>{let s=new Uint8Array(e),t="";for(let n=0;n<s.byteLength;n++)t+=String.fromCharCode(s[n]);return btoa(t)},A=async()=>{try{let s=await new Function("modulePath","return import(modulePath)")("sharp");return s.default||s}catch{return null}},$=async(e,s,t,n)=>{let a=Buffer.from(s),r=e(a);if(t==="image/jpeg")r=r.jpeg({quality:Math.round(n*100)});else if(t==="image/png"){let i=Math.round((1-n)*9);r=r.png({compressionLevel:i})}let o=await r.toBuffer();return`data:${t};base64,${o.toString("base64")}`},de=async(e,s={})=>{let{quality:t=.92,compressor:n,fetcher:a=fetch}=s;if(!e.startsWith("http"))throw new Error("\u56FE\u7247\u5730\u5740\u5FC5\u987B\u4EE5http\u6216https\u5F00\u5934");let r=await a(e);if(!r.ok)throw new Error(`\u83B7\u53D6\u56FE\u7247\u5931\u8D25: ${r.statusText}`);let o=r.headers.get("Content-Type")||"image/jpeg",i=await r.arrayBuffer();if(o!=="image/jpeg"&&o!=="image/png"){let c=y(i);return`data:${o};base64,${c}`}if(n)return await n(i,o,t);if(typeof OffscreenCanvas<"u"){let c=null;try{let u=new Blob([i],{type:o});c=await createImageBitmap(u);let m=new OffscreenCanvas(c.width,c.height),T=m.getContext("2d");if(!T)throw new Error("\u65E0\u6CD5\u83B7\u53D6 OffscreenCanvas context");T.drawImage(c,0,0),c.close(),c=null;let S=await(await m.convertToBlob({type:o,quality:t})).arrayBuffer(),R=y(S);return`data:${o};base64,${R}`}catch{c?.close();let u=y(i);return`data:${o};base64,${u}`}}let p=await A();if(p)try{return await $(p,i,o,t)}catch{let c=y(i);return`data:${o};base64,${c}`}let f=y(i);return`data:${o};base64,${f}`};var Se=(e,s)=>Math.floor(Math.random()*(s-e+1))+e;var Ce=e=>e.replace(/_([a-zA-Z])/g,(s,t)=>t.toUpperCase()),Pe=e=>e.replace(/([A-Z])/g,(s,t)=>`_${t.toLowerCase()}`),Oe=e=>e.charAt(0).toUpperCase()+e.slice(1),ke=e=>e.charAt(0).toLowerCase()+e.slice(1);var ve=(e="",s)=>{if(!e)return"";let{maxLength:t=1/0,disableNewLineReplace:n=!1,disableWhitespaceCollapse:a=!1,omission:r="..."}=s??{},o=e;return n?o=o.replace(/\r?\n/g," "):o=o.replace(/\r?\n/g,"\\n"),a||(o=o.replace(/\s+/g," ")),o=o.trim(),t>0&&o.length>t?o.slice(0,t)+r:o};var Me=(e,s=300)=>{let t=null;return(...n)=>{t&&clearTimeout(t),t=setTimeout(()=>{e(...n)},s)}};var je=async(e=150)=>new Promise(s=>{setTimeout(s,e)});var Fe=(e,s=300)=>{let t=null;return function(...n){t||(t=setTimeout(()=>{t=null,e.apply(this,n)},s))}};export{Pe as camelToSnake,Oe as capitalize,ve as compactStr,Me as debounce,ke as decapitalize,ce as fetcher,me as getRealURL,de as imageUrlToBase64,q as isFalsy,g as isNil,l as isObject,d as isPrimitive,P as log,v as loopUntil,h as mapKeys,b as mapValues,x as mergeObjects,Se as randomInt,je as sleep,Ce as snakeToCamel,Fe as throttle,w as to,L as withCache};