@nickyzj2023/utils 1.0.58 → 1.0.60
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 +56 -39
- package/dist/index.mjs +2 -1
- package/package.json +34 -34
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
|
|
157
|
-
/**
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
* -
|
|
172
|
-
* -
|
|
173
|
-
* -
|
|
174
|
-
* -
|
|
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
|
-
* //
|
|
180
|
-
* const
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
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
|
-
*
|
|
195
|
-
* return;
|
|
199
|
+
* // ...
|
|
196
200
|
* }
|
|
197
|
-
*
|
|
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) => {
|
|
@@ -385,19 +388,33 @@ declare const decapitalize: <S extends string>(s: S) => Decapitalize<S>;
|
|
|
385
388
|
* 将字符串压缩为单行精简格式
|
|
386
389
|
*
|
|
387
390
|
* @example
|
|
388
|
-
* // "Hello
|
|
389
|
-
* compactStr(`
|
|
390
|
-
*
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
391
|
+
* // "Hello\nworld"
|
|
392
|
+
* compactStr(`Hello,
|
|
393
|
+
*
|
|
394
|
+
* world
|
|
395
|
+
*
|
|
396
|
+
* !`);
|
|
397
|
+
*
|
|
398
|
+
* @example
|
|
399
|
+
* // "Hello...world" (maxLength: 15)
|
|
400
|
+
* compactStr("Hello, beautiful world!", { maxLength: 15 });
|
|
395
401
|
*/
|
|
396
402
|
declare const compactStr: (text?: string, options?: {
|
|
397
|
-
/**
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
403
|
+
/**
|
|
404
|
+
* 最大保留长度,超过该长度使用 "..." 替代
|
|
405
|
+
@default Infinity
|
|
406
|
+
*/
|
|
407
|
+
maxLength?: number;
|
|
408
|
+
/**
|
|
409
|
+
* 是否将换行符替换为字面量"\n"
|
|
410
|
+
* @default false
|
|
411
|
+
*/
|
|
412
|
+
disableNewLineReplace?: boolean;
|
|
413
|
+
/**
|
|
414
|
+
* 是否合并连续的换行符/制表符为单个
|
|
415
|
+
* @default false
|
|
416
|
+
*/
|
|
417
|
+
disableCollapse?: boolean;
|
|
401
418
|
}) => string;
|
|
402
419
|
//#endregion
|
|
403
420
|
//#region src/string/qs.d.ts
|
|
@@ -471,4 +488,4 @@ declare const sleep: (time?: number) => Promise<unknown>;
|
|
|
471
488
|
*/
|
|
472
489
|
declare const throttle: <T extends (...args: any[]) => any>(fn: T, delay?: number) => (this: any, ...args: Parameters<T>) => void;
|
|
473
490
|
//#endregion
|
|
474
|
-
export { CamelToSnake, Capitalize, Decapitalize, DeepMapKeys, DeepMapValues, Falsy,
|
|
491
|
+
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, qs, randomInt, sleep, snakeToCamel, throttle, to, withCache };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +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,
|
|
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};
|
package/package.json
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
2
|
+
"name": "@nickyzj2023/utils",
|
|
3
|
+
"version": "1.0.60",
|
|
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
|
+
}
|