@nickyzj2023/utils 1.0.59 → 1.0.61

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.
package/dist/index.d.mts CHANGED
@@ -153,53 +153,56 @@ type Primitive = number | string | boolean | symbol | bigint | undefined | null;
153
153
  declare const isPrimitive: (value: any) => value is Primitive;
154
154
  //#endregion
155
155
  //#region src/network/fetcher.d.ts
156
- type FetchOptions = {
157
- /** 代理服务器配置 */proxy?: string;
158
- };
159
- type RequestInit = globalThis.RequestInit & FetchOptions & {
156
+ type RequestInit = globalThis.RequestInit & {
157
+ /**
158
+ * searchParams 查询参数对象
159
+ */
160
160
  params?: Record<string, any>;
161
+ /**
162
+ * 响应解析器,默认的解析方法为 response.json()
163
+ */
161
164
  parser?: (response: Response) => Promise<any>;
162
165
  };
163
166
  /**
164
- * 基于 Fetch API 的请求客户端
167
+ * 基于 Fetch API 的请求实例
165
168
  * @param baseURL 接口前缀
166
- * @param baseOptions 客户端级别的请求体,后续调用时传递相同参数会覆盖上去
169
+ * @param baseOptions 应用于整个实例的请求体,后续请求都会带上
167
170
  *
168
171
  * @remarks
169
172
  * 特性:
170
- * - 合并实例、调用时的相同请求体
171
- * - params 里传递对象,自动转换为 queryString
172
- * - body 里传递对象,自动 JSON.stringify
173
- * - 可选择使用 to() 转换请求结果为 [Error, Response]
174
- * - 可选择使用 withCache() 缓存请求结果
175
- * - 支持 proxy 选项
173
+ * - 支持在创建实例、发出请求时合并相同的请求体(后者覆盖前者)
174
+ * - 支持在 GET 的 params 请求体中传递对象
175
+ * - 支持在 POST、PUT 的 body 请求体中传递对象
176
+ * - 可选 to() 函数转换请求结果为 [Error, Response]
177
+ * - 可选 withCache() 函数缓存请求结果
176
178
  *
177
179
  * @example
180
+ * // 直接发请求
181
+ * const res = await fetcher().get<Blog>("https://nickyzj.run:3030/blogs/hello-world", {
182
+ * params: {
183
+ * page: 2,
184
+ * pageSize: 10,
185
+ * }
186
+ * });
178
187
  *
179
- * // 用法1:直接发送请求
180
- * const res = await fetcher().get<Blog>("https://nickyzj.run:3030/blogs/hello-world");
181
- *
182
- * // 用法2:创建实例
183
- * const api = fetcher("https://nickyzj.run:3030", { headers: { Authorization: "Bearer token" } });
184
- * const res = await api.get<Blog>("/blogs/hello-world", { headers: {...}, params: { page: 1 } }); // 与实例相同的 headers 会覆盖上去,params 会转成 ?page=1 跟到 url 后面
185
- *
186
- * // 用法3:使用代理
187
- * const api = fetcher("https://api.example.com", {
188
- * proxy: "http://127.0.0.1:7890"
188
+ * // 创建实例,发请求
189
+ * const api = fetcher("https://nickyzj.run:3030", {
190
+ * headers: {
191
+ * Authorization: "Bearer token"
192
+ * }
189
193
  * });
194
+ * const res = await api.get<Blog>("/blogs/hello-world");
190
195
  *
191
- * // 安全处理请求结果
196
+ * // 安全返回请求结果,不抛异常
192
197
  * const [error, data] = await to(api.get<Blog>("/blogs/hello-world"));
193
198
  * if (error) {
194
- * console.error(error);
195
- * return;
199
+ * // ...
196
200
  * }
197
- * console.log(data);
201
+ * // ...
198
202
  *
199
203
  * // 缓存请求结果
200
204
  * const getBlogs = withCache(api.get);
201
205
  * await getBlogs("/blogs");
202
- * await sleep();
203
206
  * await getBlogs("/blogs"); // 不发请求,使用缓存
204
207
  */
205
208
  declare const fetcher: (baseURL?: string, baseOptions?: RequestInit) => {
@@ -293,7 +296,7 @@ declare const to: <T, E = Error>(promise: Promise<T>) => Promise<[null, T] | [E,
293
296
  */
294
297
  declare const randomInt: (min: number, max: number) => number;
295
298
  //#endregion
296
- //#region src/object/map-keys.d.ts
299
+ //#region src/object/map.d.ts
297
300
  type DeepMapKeys<T> = T extends Array<infer U> ? Array<DeepMapKeys<U>> : T extends object ? {
298
301
  [key: string]: DeepMapKeys<T[keyof T]>;
299
302
  } : T;
@@ -311,8 +314,6 @@ type DeepMapKeys<T> = T extends Array<infer U> ? Array<DeepMapKeys<U>> : T exten
311
314
  * console.log(result); // { A: { B: 1 } }
312
315
  */
313
316
  declare const mapKeys: <T>(obj: T, getNewKey: (key: string) => string) => DeepMapKeys<T>;
314
- //#endregion
315
- //#region src/object/map-values.d.ts
316
317
  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;
317
318
  /**
318
319
  * 递归处理对象里的 value
@@ -332,7 +333,7 @@ declare const mapValues: <T, R = any>(obj: T, getNewValue: (value: any, key: str
332
333
  /** 过滤函数,返回 true 表示保留该字段 */filter?: (value: any, key: string | number) => boolean;
333
334
  }) => DeepMapValues<T, R>;
334
335
  //#endregion
335
- //#region src/object/merge-objects.d.ts
336
+ //#region src/object/merge.d.ts
336
337
  /**
337
338
  * 深度合并两个对象,规则如下:
338
339
  * 1. 原始值覆盖:如果两个值都是原始类型,则用后者覆盖;
@@ -346,6 +347,92 @@ declare const mapValues: <T, R = any>(obj: T, getNewValue: (value: any, key: str
346
347
  */
347
348
  declare const mergeObjects: <T extends Record<string, any>, U extends Record<string, any>>(obj1: T, obj2: U) => T & U;
348
349
  //#endregion
350
+ //#region src/object/omit.d.ts
351
+ /**
352
+ * 从对象中排除指定的键,返回不包含这些键的新对象
353
+ *
354
+ * @typeParam T - 源对象的类型
355
+ * @typeParam K - 要排除的键,必须是源对象的键之一
356
+ *
357
+ * @param obj - 源对象
358
+ * @param keys - 要排除的键名数组
359
+ * @returns 不包含指定键的新对象
360
+ *
361
+ * @example
362
+ * const user = {
363
+ * id: 1,
364
+ * name: "Alice",
365
+ * age: 25,
366
+ * password: "secret"
367
+ * };
368
+ * // { id: 1, name: "Alice", age: 25 }
369
+ * const safeUser = omit(user, ["password"]);
370
+ */
371
+ declare const omit: <T extends Record<string, any>, K extends keyof T>(obj: T, keys: readonly K[]) => Omit<T, K>;
372
+ /**
373
+ * 从对象中排除满足条件的键值对,返回不包含这些键的新对象
374
+ *
375
+ * @typeParam T - 源对象的类型
376
+ *
377
+ * @param obj - 源对象
378
+ * @param shouldOmit - 判断函数,接收键和值,返回 `true` 则排除该键值对
379
+ * @returns 不包含满足条件的键值对的新对象
380
+ *
381
+ * @example
382
+ * const user = {
383
+ * id: 1,
384
+ * name: "Alice",
385
+ * age: 25,
386
+ * password: "secret"
387
+ * };
388
+ * // { name: "Alice", password: "secret" }
389
+ * const stringFields = omitBy(user, (key, value) => typeof value === "number");
390
+ */
391
+ declare const omitBy: <T extends Record<string, any>>(obj: T, shouldOmit: (key: keyof T, value: T[keyof T]) => boolean) => Partial<T>;
392
+ //#endregion
393
+ //#region src/object/pick.d.ts
394
+ /**
395
+ * 从对象中选取指定的键,返回仅包含这些键的新对象
396
+ *
397
+ * @typeParam T - 源对象的类型
398
+ * @typeParam K - 要选取的键,必须是源对象的键之一
399
+ *
400
+ * @param obj - 源对象
401
+ * @param keys - 要选取的键名数组
402
+ * @returns 仅包含指定键的新对象
403
+ *
404
+ * @example
405
+ * const user = {
406
+ * id: 1,
407
+ * name: "Alice",
408
+ * age: 25,
409
+ * password: "secret"
410
+ * };
411
+ * // { id: 1, name: "Alice", age: 25 }
412
+ * const safeUser = pick(user, ["id", "name", "age"]);
413
+ */
414
+ declare const pick: <T extends Record<string, any>, K extends keyof T>(obj: T, keys: readonly K[]) => Pick<T, K>;
415
+ /**
416
+ * 从对象中选取满足条件的键值对,返回仅包含这些键的新对象
417
+ *
418
+ * @typeParam T - 源对象的类型
419
+ *
420
+ * @param obj - 源对象
421
+ * @param shouldPick - 判断函数,返回 `true` 时保留该字段
422
+ * @returns 仅包含满足条件的键值对的新对象
423
+ *
424
+ * @example
425
+ * const user = {
426
+ * id: 1,
427
+ * name: "Alice",
428
+ * age: 25,
429
+ * password: "secret"
430
+ * };
431
+ * // { id: 1, age: 25 }
432
+ * const numericFields = pickBy(user, (key, value) => typeof value === "number");
433
+ */
434
+ declare const pickBy: <T extends Record<string, any>>(obj: T, shouldPick: (key: keyof T, value: T[keyof T]) => boolean) => Partial<T>;
435
+ //#endregion
349
436
  //#region src/string/case.d.ts
350
437
  type SnakeToCamel<S extends string> = S extends `${infer Before}_${infer After}` ? After extends `${infer First}${infer Rest}` ? `${Before}${Uppercase<First>}${SnakeToCamel<Rest>}` : Before : S;
351
438
  /**
@@ -485,4 +572,4 @@ declare const sleep: (time?: number) => Promise<unknown>;
485
572
  */
486
573
  declare const throttle: <T extends (...args: any[]) => any>(fn: T, delay?: number) => (this: any, ...args: Parameters<T>) => void;
487
574
  //#endregion
488
- 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 };
575
+ export { CamelToSnake, Capitalize, Decapitalize, DeepMapKeys, DeepMapValues, Falsy, ImageCompressionOptions, LogOptions, Primitive, RequestInit, SetTtl, SnakeToCamel, camelToSnake, capitalize, compactStr, debounce, decapitalize, fetcher, getRealURL, imageUrlToBase64, isFalsy, isNil, isObject, isPrimitive, log, loopUntil, mapKeys, mapValues, mergeObjects, omit, omitBy, pick, pickBy, qs, randomInt, sleep, snakeToCamel, throttle, to, withCache };
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
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,disableCollapse:i=!1}=t??{},a=e;return i||(a=a.replace(/[\n\t]+/g,`
3
- `)),a=r?a.replace(/\r?\n/g,` `):a.replace(/\r?\n/g,`\\n`),a=a.replace(/\s+/g,` `).trim(),n>0&&a.length>n?a.slice(0,n)+`...`:a},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};
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={...e};for(let e of t)delete n[e];return n},d=(e,t)=>{let n={};for(let[r,i]of Object.entries(e))t(r,i)||(n[r]=i);return n},f=(e,t)=>t.reduce((t,n)=>(Object.hasOwn(e,n)&&(t[n]=e[n]),t),{}),p=(e,t)=>{let n={};for(let[r,i]of Object.entries(e))t(r,i)&&(n[r]=i);return n},m=(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`})}},h=async e=>{try{return[null,await e]}catch(e){return[e,void 0]}},g=async e=>{let[t,n]=await h(fetch(e,{method:`HEAD`,redirect:`manual`}));return t?e:n.headers.get(`location`)||e},_=e=>{let t=new Uint8Array(e),n=``;for(let e=0;e<t.byteLength;e++)n+=String.fromCharCode(t[e]);return btoa(n)},v=async()=>{try{let e=await Function(`modulePath`,`return import(modulePath)`)(`sharp`);return e.default||e}catch{return null}},y=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`)}`},b=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,${_(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,${_(await(await r.convertToBlob({type:o,quality:n})).arrayBuffer())}`}catch{return e?.close(),`data:${o};base64,${_(s)}`}}let c=await v();if(c)try{return await y(c,s,o,n)}catch{return`data:${o};base64,${_(s)}`}return`data:${o};base64,${_(s)}`},x=(e,t)=>Math.floor(Math.random()*(t-e+1))+e,S=e=>e.replace(/_([a-zA-Z])/g,(e,t)=>t.toUpperCase()),C=e=>e.replace(/([A-Z])/g,(e,t)=>`_${t.toLowerCase()}`),w=e=>e.charAt(0).toUpperCase()+e.slice(1),T=e=>e.charAt(0).toLowerCase()+e.slice(1),E=(e=``,t)=>{if(!e)return``;let{maxLength:n=1/0,disableNewLineReplace:r=!1,disableCollapse:i=!1}=t??{},a=e;return i||(a=a.replace(/[\n\t]+/g,`
3
+ `)),a=r?a.replace(/\r?\n/g,` `):a.replace(/\r?\n/g,`\\n`),a=a.replace(/\s+/g,` `).trim(),n>0&&a.length>n?a.slice(0,n)+`...`:a},D={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:``}},O=(e,t=300)=>{let n=null;return(...r)=>{n&&clearTimeout(n),n=setTimeout(()=>{e(...r)},t)}},k=async(e=150)=>new Promise(t=>{setTimeout(t,e)}),A=(e,t=300)=>{let n=null;return function(...r){n||=setTimeout(()=>{n=null,e.apply(this,r)},t)}};export{C as camelToSnake,w as capitalize,E as compactStr,O as debounce,T as decapitalize,m as fetcher,g as getRealURL,b 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,u as omit,d as omitBy,f as pick,p as pickBy,D as qs,x as randomInt,k as sleep,S as snakeToCamel,A as throttle,h as to,n as withCache};
package/package.json CHANGED
@@ -1,35 +1,35 @@
1
1
  {
2
- "name": "@nickyzj2023/utils",
3
- "version": "1.0.59",
4
- "type": "module",
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
- },
14
- "files": [
15
- "dist"
16
- ],
17
- "repository": {
18
- "type": "git",
19
- "url": "https://github.com/Nickyzj628/utils.git"
20
- },
21
- "devDependencies": {
22
- "@biomejs/biome": "^2.4.4",
23
- "@types/node": "^25.5.0",
24
- "tsdown": "^0.21.2",
25
- "typedoc": "^0.28.17",
26
- "typedoc-material-theme": "^1.4.1"
27
- },
28
- "peerDependencies": {
29
- "typescript": "^5.9.3"
30
- },
31
- "scripts": {
32
- "build": "tsdown",
33
- "docs": "typedoc src/index.ts --plugin typedoc-material-theme"
34
- }
35
- }
2
+ "name": "@nickyzj2023/utils",
3
+ "version": "1.0.61",
4
+ "type": "module",
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
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsdown",
19
+ "docs": "typedoc src/index.ts --plugin typedoc-material-theme"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/Nickyzj628/utils.git"
24
+ },
25
+ "devDependencies": {
26
+ "@biomejs/biome": "^2.4.11",
27
+ "@types/node": "^25.6.0",
28
+ "tsdown": "^0.21.7",
29
+ "typedoc": "^0.28.19",
30
+ "typedoc-material-theme": "^1.4.1"
31
+ },
32
+ "peerDependencies": {
33
+ "typescript": "^5.9.3"
34
+ }
35
+ }