@nickyzj2023/utils 1.0.64 → 1.0.66

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- 男生自用全新前端工具库
1
+ 男生自用全新前端工具库,0依赖
2
2
 
3
3
  安装到你的前端项目里:
4
4
 
@@ -29,5 +29,3 @@ if (error) {
29
29
 
30
30
  console.log(data);
31
31
  ```
32
-
33
-
package/dist/index.d.mts CHANGED
@@ -1,3 +1,117 @@
1
+ //#region src/ai/chatCompletions/types.d.ts
2
+ declare namespace ChatCompletions {
3
+ type Model = {
4
+ /** 模型名称(如果不传,会尝试从 /models 读取模型) */model?: string; /** API 基础地址 */
5
+ baseURL: string; /** API 密钥(本地模型可不传) */
6
+ apiKey?: string;
7
+ };
8
+ type TextContent = {
9
+ type: "text";
10
+ text: string;
11
+ };
12
+ type ImageContent = {
13
+ type: "image_url";
14
+ image_url: {
15
+ url: string;
16
+ };
17
+ };
18
+ type ContentPart = TextContent | ImageContent;
19
+ type Message = {
20
+ role: "system" | "user" | "assistant" | "tool" | "function";
21
+ content: string | ContentPart[];
22
+ name?: string;
23
+ tool_calls?: ToolCall[];
24
+ tool_call_id?: string;
25
+ };
26
+ type ToolCall = {
27
+ id: string;
28
+ type: "function";
29
+ function: {
30
+ name: string;
31
+ arguments: string;
32
+ };
33
+ };
34
+ type ToolDefinition = {
35
+ type: "function";
36
+ function: {
37
+ name: string;
38
+ description?: string;
39
+ parameters?: Record<string, any>;
40
+ };
41
+ };
42
+ type Usage = {
43
+ prompt_tokens: number;
44
+ completion_tokens: number;
45
+ total_tokens: number;
46
+ };
47
+ type Response = {
48
+ id: string;
49
+ object: "chat.completion";
50
+ created: number;
51
+ model: string;
52
+ choices: Array<{
53
+ index: number;
54
+ message: Message;
55
+ finish_reason: "stop" | "length" | "tool_calls" | "content_filter" | null;
56
+ }>;
57
+ usage: Usage;
58
+ system_fingerprint?: string;
59
+ };
60
+ type ExtraBody = {
61
+ /** 工具列表 */tools?: ToolDefinition[]; /** 工具调用函数表,key 为工具名,value 为函数 */
62
+ toolHandlers?: Record<string, (args: any) => any | Promise<any>>; /** 其他额外参数 */
63
+ [key: string]: any;
64
+ };
65
+ type Result = {
66
+ /** 模型的最终回复内容(多模态时取所有 text 拼接) */content: string; /** Token 消耗情况 */
67
+ usage: Usage; /** 原始响应中的其他字段 */
68
+ [key: string]: any;
69
+ };
70
+ }
71
+ //#endregion
72
+ //#region src/ai/chatCompletions/index.d.ts
73
+ /**
74
+ * 兼容 OpenAI API 的聊天补全函数
75
+ * - 自动处理工具调用
76
+ * - 返回最终回复内容和 token 消耗情况
77
+ *
78
+ * @param model 模型配置,包含 model、baseURL、apiKey
79
+ * @param messages OpenAI API 兼容的消息数组
80
+ * @param extraBody 可选的额外参数,如 tools、toolHandlers、temperature 等
81
+ * @returns 包含 content、usage 和其他原始字段的对象
82
+ *
83
+ * @example
84
+ * // 最简调用
85
+ * // 未填写模型名,会自动使用/v1/models的第一个模型
86
+ * const { content, usage } = await chatCompletions(
87
+ * { baseURL: "http://127.0.0.1:11434/v1" },
88
+ * [{ role: "user", content: "你好" }],
89
+ * );
90
+ * console.log(content); // "你好!有什么我可以帮你的吗?"
91
+ * console.log(usage); // { prompt_tokens: 13, completion_tokens: 9, total_tokens: 22 }
92
+ *
93
+ * @example
94
+ * // 工具调用
95
+ * const { content, usage } = await chatCompletions(
96
+ * { baseURL: "http://127.0.0.1:11434/v1", model: "model.gguf", apiKey: "sk-local-no-need-key" },
97
+ * [{ role: "user", content: "查询上海天气" }],
98
+ * {
99
+ * tools: [{
100
+ * type: "function",
101
+ * function: {
102
+ * name: "getWeather",
103
+ * description: "查询城市天气情况",
104
+ * parameters: { type: "object", properties: { city: { type: "string" } } },
105
+ * },
106
+ * }],
107
+ * toolHandlers: {
108
+ * getWeather: (args) => `${args.city}今日晴转多云,25°C`,
109
+ * },
110
+ * },
111
+ * );
112
+ */
113
+ declare const chatCompletions: (model: ChatCompletions.Model, messages: ChatCompletions.Message[], extraBody?: ChatCompletions.ExtraBody) => Promise<ChatCompletions.Result>;
114
+ //#endregion
1
115
  //#region src/dom/log.d.ts
2
116
  /**
3
117
  * log 配置选项
@@ -109,17 +223,6 @@ declare const withCache: <Args extends any[], Result>(fn: (this: {
109
223
  updateTtl(seconds: number): void;
110
224
  };
111
225
  //#endregion
112
- //#region src/is/is-falsy.d.ts
113
- type Falsy = false | 0 | -0 | 0n | "" | null | undefined;
114
- /**
115
- * 检测传入的值是否为**假值**(false、0、''、null、undefined、NaN等)
116
- *
117
- * @example
118
- * isFalsy(""); // true
119
- * isFalsy(1); // false
120
- */
121
- declare const isFalsy: (value: any) => value is Falsy;
122
- //#endregion
123
226
  //#region src/is/is-nil.d.ts
124
227
  /**
125
228
  * 检测传入的值是否为**空值**(null、undefined)
@@ -480,7 +583,7 @@ declare const decapitalize: <S extends string>(s: S) => Decapitalize<S>;
480
583
  * !`);
481
584
  *
482
585
  * @example
483
- * // "Hello...world" (maxLength: 15)
586
+ * // "Hello...world"
484
587
  * compactStr("Hello, beautiful world!", { maxLength: 15 });
485
588
  */
486
589
  declare const compactStr: (text?: string, options?: {
@@ -501,6 +604,10 @@ declare const compactStr: (text?: string, options?: {
501
604
  disableCollapse?: boolean;
502
605
  }) => string;
503
606
  //#endregion
607
+ //#region src/string/extract-error-message.d.ts
608
+ /** 从任意异常中提取类似 error.message 的可读文字 */
609
+ declare const extractErrorMessage: (error: unknown) => string;
610
+ //#endregion
504
611
  //#region src/string/qs.d.ts
505
612
  /**
506
613
  * 针对 URL 查询字符串的解析和序列化
@@ -605,4 +712,4 @@ declare const sleep: (time?: number) => Promise<unknown>;
605
712
  */
606
713
  declare const throttle: <T extends (...args: any[]) => any>(fn: T, delay?: number) => (this: any, ...args: Parameters<T>) => void;
607
714
  //#endregion
608
- export { CamelToSnake, Capitalize, Decapitalize, DeepMapKeys, DeepMapValues, Falsy, ImageCompressionOptions, LockQueue, 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 };
715
+ export { CamelToSnake, Capitalize, Decapitalize, DeepMapKeys, DeepMapValues, ImageCompressionOptions, LockQueue, LogOptions, Primitive, RequestInit, SetTtl, SnakeToCamel, camelToSnake, capitalize, chatCompletions, compactStr, debounce, decapitalize, extractErrorMessage, fetcher, getRealURL, imageUrlToBase64, 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,4 @@
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={...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(new Uint8Array(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})}let a=await i.toBuffer();return`data:${n};base64,${_(a.buffer.slice(a.byteOffset,a.byteOffset+a.byteLength))}`},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)}};var k=class{queue;constructor(){this.queue=Promise.resolve()}waitInQueue(){let e,t=new Promise(t=>{e=t}),n=this.queue.then(()=>e);return this.queue=t,n}};const A=async(e=150)=>new Promise(t=>{setTimeout(t,e)}),j=(e,t=300)=>{let n=null;return function(...r){n||=setTimeout(()=>{n=null,e.apply(this,r)},t)}};export{k as LockQueue,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,A as sleep,S as snakeToCamel,j as throttle,h as to,n as withCache};
1
+ const e=e=>e==null,t=e=>e?.constructor===Object,n=e=>e==null||typeof e!=`object`&&typeof e!=`function`,r=(e,n)=>Array.isArray(e)?e.map(e=>r(e,n)):t(e)?Object.keys(e).reduce((t,i)=>{let a=n(i),o=e[i];return t[a]=r(o,n),t},{}):e,i=(e,n,r)=>{let{filter:a}=r??{};if(Array.isArray(e)){let o=e.map((e,a)=>t(e)?i(e,n,r):n(e,a));return a?o.filter((e,t)=>a(e,t)):o}return t(e)?Object.keys(e).reduce((o,s)=>{let c=e[s],l;return l=t(c)||Array.isArray(c)?i(c,n,r):n(c,s),(!a||a(l,s))&&(o[s]=l),o},{}):e},a=(e,r)=>{let i={...e};for(let e of Object.keys(r)){let o=i[e],s=r[e];if(n(o)&&n(s)){i[e]=s;continue}if(Array.isArray(o)&&Array.isArray(s)){i[e]=o.concat(s);continue}if(t(o)&&t(s)){i[e]=a(o,s);continue}i[e]=s}return i},o=(e,t)=>{let n={...e};for(let e of t)delete n[e];return n},s=(e,t)=>{let n={};for(let[r,i]of Object.entries(e))t(r,i)||(n[r]=i);return n},c=(e,t)=>t.reduce((t,n)=>(Object.hasOwn(e,n)&&(t[n]=e[n]),t),{}),l=(e,t)=>{let n={};for(let[r,i]of Object.entries(e))t(r,i)&&(n[r]=i);return n},u=(n=``,r={})=>{let i=async(i,o={})=>{let s=new URL(n?`${n}${i}`:i),{params:c,parser:l,...u}=a(r,o);t(c)&&Object.entries(c).forEach(([t,n])=>{e(n)||s.searchParams.append(t,n.toString())}),(t(u.body)||Array.isArray(u.body))&&(u.body=JSON.stringify(u.body),u.headers={...u.headers,"Content-Type":`application/json`});let d=await fetch(s,u);if(!d.ok){if(d.headers.get(`Content-Type`)?.startsWith(`application/json`)){let e=await d.json(),t=Error(e.error?.message||d.statusText);throw t.data=e,t}throw Error(d.statusText)}return await(l?.(d)??d.json())};return{get:(e,t)=>i(e,{...t,method:`GET`}),post:(e,t,n)=>i(e,{...n,method:`POST`,body:t}),put:(e,t,n)=>i(e,{...n,method:`PUT`,body:t}),delete:(e,t)=>i(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(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)}`}}return`data:${o};base64,${p(s)}`},h=e=>e.replace(/_([a-zA-Z])/g,(e,t)=>t.toUpperCase()),g=e=>e.replace(/([A-Z])/g,(e,t)=>`_${t.toLowerCase()}`),_=e=>e.charAt(0).toUpperCase()+e.slice(1),v=e=>e.charAt(0).toLowerCase()+e.slice(1),y=(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,`
2
+ `)),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},b=e=>{if(e instanceof Error)return e.message;if(typeof e==`string`)return e;if(t(e)){let t=e.message||e.msg;if(t)return t;for(let t of Object.values(e)){let e=b(t);if(e)return e}}return JSON.stringify(e,null,2)},x={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:``}},S=async e=>{let t=(await e.get(`/models`)).data[0]?.id;if(!t)throw Error(`无法从 /models 获取模型名称`);return t},C=async(e,t,n={})=>{let{model:r,baseURL:i,apiKey:a=``}=e,o=u(i,{headers:{Authorization:`Bearer ${a}`}}),s={model:r??await S(o),messages:t,...n};return o.post(`/chat/completions`,s)},w=async(e,t)=>{let n=t[e.function.name];if(!n)return`没有找到工具“${e.function.name}”的处理函数`;try{let t=await n(JSON.parse(e.function.arguments));return typeof t==`string`?t:JSON.stringify(t)}catch(t){return`工具“${e.function.name}”处理失败:${b(t)}`}},T=e=>typeof e==`string`?e:e.filter(e=>e.type===`text`).map(e=>e.text).join(`
3
+ `),E=async(e,t,n={})=>{let{toolHandlers:r={},...i}=n;for(;;){let{choices:n,usage:a,...o}=await C(e,t,i),{message:s}=n[0]??{};if(!s)throw Error(`模型没有回复任何内容`);let{content:c=``,tool_calls:l=[],...u}=s;if(t.push(s),l.length>0&&Object.keys(r).length>0){for(let e of l){let n=await w(e,r);t.push({role:`tool`,content:n,tool_call_id:e.id})}continue}return{content:T(c),usage:a,...o,...u}}},D=(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(`
4
+ `)[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)},O=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})且未满足停止执行条件`)},k=(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},A=(e,t)=>Math.floor(Math.random()*(t-e+1))+e,j=(e,t=300)=>{let n=null;return(...r)=>{n&&clearTimeout(n),n=setTimeout(()=>{e(...r)},t)}};var M=class{queue;constructor(){this.queue=Promise.resolve()}waitInQueue(){let e,t=new Promise(t=>{e=t}),n=this.queue.then(()=>e);return this.queue=t,n}};const N=async(e=150)=>new Promise(t=>{setTimeout(t,e)}),P=(e,t=300)=>{let n=null;return function(...r){n||=setTimeout(()=>{n=null,e.apply(this,r)},t)}};export{M as LockQueue,g as camelToSnake,_ as capitalize,E as chatCompletions,y as compactStr,j as debounce,v as decapitalize,b as extractErrorMessage,u as fetcher,f as getRealURL,m as imageUrlToBase64,e as isNil,t as isObject,n as isPrimitive,D as log,O as loopUntil,r as mapKeys,i as mapValues,a as mergeObjects,o as omit,s as omitBy,c as pick,l as pickBy,x as qs,A as randomInt,N as sleep,h as snakeToCamel,P as throttle,d as to,k as withCache};
package/package.json CHANGED
@@ -1,34 +1,33 @@
1
1
  {
2
- "name": "@nickyzj2023/utils",
3
- "version": "1.0.64",
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
- "check": "biome check --write src/"
21
- },
22
- "repository": {
23
- "type": "git",
24
- "url": "https://github.com/Nickyzj628/utils.git"
25
- },
26
- "devDependencies": {
27
- "@biomejs/biome": "^2.4.11",
28
- "@types/node": "^25.6.0",
29
- "tsdown": "^0.21.7",
30
- "typedoc": "^0.28.19",
31
- "typedoc-material-theme": "^1.4.1",
32
- "typescript": "^6.0.2"
33
- }
34
- }
2
+ "name": "@nickyzj2023/utils",
3
+ "version": "1.0.66",
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
+ "@types/node": "^25.6.0",
23
+ "tsdown": "^0.21.10",
24
+ "typedoc": "^0.28.19",
25
+ "typedoc-material-theme": "^1.4.1",
26
+ "typescript": "^6.0.3"
27
+ },
28
+ "scripts": {
29
+ "build": "tsdown",
30
+ "docs": "typedoc src/index.ts --plugin typedoc-material-theme",
31
+ "check": "biome check --diagnostic-level=error --write src/"
32
+ }
33
+ }