@ybgnb/utils 0.2.7 → 0.2.9

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/core.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var d=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var F=Object.prototype.hasOwnProperty;var O=(t,e)=>{for(var r in e)d(t,r,{get:e[r],enumerable:!0})},K=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of z(e))!F.call(t,o)&&o!==r&&d(t,o,{get:()=>e[o],enumerable:!(n=A(e,o))||n.enumerable});return t};var D=t=>K(d({},"__esModule",{value:!0}),t);var yt={};O(yt,{CommonError:()=>f,LogLevelMap:()=>p,bizErrorToError:()=>R,checkAbortSignal:()=>G,chunk:()=>N,convertToCommonError:()=>C,createAbortError:()=>c,createLogger:()=>Z,createResponseError:()=>P,dynamicCall:()=>q,encodeURLParams:()=>dt,execBiz:()=>Q,fetchWithFormat:()=>w,formatDate:()=>x,formatTime:()=>pt,formatUnitSize:()=>ht,getErrorMessage:()=>u,getFormattedDate:()=>ft,getFormattedDateTime:()=>ut,getFormattedTime:()=>mt,getGithubRawJson:()=>Y,inArray:()=>v,invalidCharRegex:()=>gt,isBizResult:()=>L,isCanceledError:()=>M,isCommonError:()=>E,isEmptyArr:()=>H,isHttpUrl:()=>lt,isLogLevel:()=>T,isObject:()=>I,isPlainObject:()=>h,logLevels:()=>b,mergeQueryParams:()=>bt,omitUndefined:()=>tt,parseGithubRawUrl:()=>$,parseGithubRepoUrl:()=>V,parseUrl:()=>xt,processRangeInBatches:()=>J,random1ToN:()=>at,randomFloat:()=>nt,randomInt:()=>l,runRandomFunctions:()=>_,sample:()=>ot,sampleOne:()=>st,sampleWithReplacement:()=>it,serializeError:()=>g,shuffle:()=>k,sleep:()=>S,sleepRandom:()=>ct,stripFunctions:()=>y,unwrapBizResult:()=>W,withRetry:()=>rt,withTimeout:()=>et});module.exports=D(yt);function M(t){return t instanceof Error?t.name==="AbortError"||t.name==="CanceledError"||"code"in t&&t.code==="ERR_CANCELED":!1}function c(t){let e=new Error(t??"\u64CD\u4F5C\u5DF2\u53D6\u6D88");return e.name="AbortError",e}function E(t){return t instanceof f||t instanceof Error&&t.name==="CommonError"}function U(t,e){return e&&(t.message=`${e} ${t.message}`),t}function C(t,e){return E(t)?U(t,e):new f(`${e} ${u(t)}`,t)}function u(t){return typeof t=="string"?t:t instanceof Error||t&&typeof t=="object"&&"message"in t&&typeof t.message=="string"?t.message:String(t)??"\u672A\u77E5\u9519\u8BEF"}var f=class extends Error{constructor(e,r){super(e),r!==void 0&&(this.cause=r instanceof Error?r:new Error(u(r))),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}toString(){return`${this.name}: ${this.message}${this.cause?` (caused by ${this.cause})`:""}`}};var p={trace:0,debug:1,info:2,warn:3,error:4},b=["trace","debug","info","warn","error"];function G(t){if(t?.aborted)throw c()}function H(t){return Array.isArray(t)&&t.length===0}function N(t,e){if(!Number.isInteger(e)||e<1)throw new Error("size \u5FC5\u987B\u662F\u6B63\u6574\u6570");let r=[];for(let n=0;n<t.length;n+=e)r.push(t.slice(n,n+e));return r}function v(t,e){return e.includes(t)}function h(t){if(t===null||typeof t!="object")return!1;let e=Object.getPrototypeOf(t);return e===Object.prototype||e===null}function I(t,e){return t===null||typeof t!="object"||Array.isArray(t)?!1:e!==void 0?e in t:!0}function y(t,e=new WeakMap){if(typeof t=="function")return;if(t===null||typeof t!="object"||t instanceof Date||t instanceof RegExp||t instanceof Map||t instanceof Set||ArrayBuffer.isView(t)||t instanceof ArrayBuffer)return t;if(e.has(t))return e.get(t);if(Array.isArray(t)){let n=[];e.set(t,n);for(let o of t)n.push(y(o,e));return n}if(!h(t))return t;let r={};e.set(t,r);for(let[n,o]of Object.entries(t)){if(typeof o=="function")continue;let i=y(o,e);i!==void 0&&(r[n]=i)}return r}function g(t){return t instanceof Error?{name:t.name,message:t.message,stack:t.stack,cause:"cause"in t&&t.cause?g(t.cause):void 0}:{name:"UnknownError",message:u(t)}}function L(t){return t!=null&&typeof t=="object"&&"success"in t&&typeof t.success=="boolean"&&"msg"in t&&typeof t.msg=="string"}var Q=async t=>{try{return{success:!0,msg:"\u64CD\u4F5C\u6210\u529F",data:await t()}}catch(e){return{success:!1,msg:"\u64CD\u4F5C\u5931\u8D25",error:g(e)}}};async function W(t){if(L(t)){if(t.success)return t.data;throw t.error?R(t.error):new Error(t.msg)}else return t}function R(t){return Object.assign(new Error,t)}function P(t){return new Error(`HTTP ${t.status}: ${t.statusText}`)}async function w(t,e,r){let n=await fetch(t,r);if(!n.ok)throw P(n);switch(e){case"json":return await n.json();case"text":return await n.text();case"blob":return await n.blob();case"arrayBuffer":return await n.arrayBuffer();case"formData":return await n.formData();default:return await n.text()}}function _(t,e){e=e??t.length;let r=Math.floor(Math.random()*e)+1,n=[...t];for(let i=n.length-1;i>0;i--){let s=Math.floor(Math.random()*(i+1));[n[i],n[s]]=[n[s],n[i]]}let o=n.slice(0,r);for(let i of o)i()}async function J(t,e,r,n){for(let o=t;o<=e;o+=r){let i=e-o+1,s=Math.min(r,i),m=Array.from({length:s},(a,B)=>o+B);await n(m)}}function q(t,e,...r){let n=e.split("."),o=t,i=0;for(;i<n.length-1;i++)if(o=o[n[i]],o==null)throw new Error(`Path '${n.slice(0,i+1).join(".")}' is null/undefined`);let s=o[n[i]];if(typeof s!="function")throw new Error(`'${e}' is not a function`);return s.apply(o,r)}function V(t){t=t.replace(/^git\+/,"");let e=/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git|\/)?$/,r=/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)$/,n=t.match(e);if(n)return{owner:n[1],repo:n[2],branch:"main"};let o=t.match(r);if(o)return{owner:o[1],repo:o[2],branch:o[3]};throw new Error("\u89E3\u6790\u63D2\u4EF6\u4ED3\u5E93URL\u5931\u8D25")}function $(t){let{owner:e,repo:r,branch:n,filePath:o}=t;return`https://raw.githubusercontent.com/${e}/${r}/${n}/${o}`}async function Y(t){return JSON.parse(await w($(t),"json"))}var j=()=>{},X=new Set(["then","catch","finally","toJSON","toString","valueOf"]);function T(t){return b.indexOf(t)>-1}function Z(t,e){let r="info";return(async()=>{try{let o=(await t()).toLowerCase();T(o)?r=o:r="info"}catch{r="info"}})().then(),new Proxy(j,{get(o,i){if(!(typeof i!="string"||X.has(i))&&T(i))return new Proxy(j,{apply(s,m,a){a&&(p[i]<p[r]||e(i,...a))}})}})}var tt=t=>Object.fromEntries(Object.entries(t).filter(([e,r])=>r!==void 0));async function et(t,e){return await Promise.race([t,new Promise((r,n)=>{setTimeout(()=>{n(new Error("Timeout"))},e)})])}async function rt(t,e=3,r=1e3){for(let n=0;n<e;n++)try{return await t()}catch(o){if(n===e-1)throw o;await new Promise(i=>setTimeout(i,r))}throw new Error("Unreachable")}function k(t){let e=t.slice();for(let r=e.length-1;r>0;r--){let n=Math.floor(Math.random()*(r+1));[e[r],e[n]]=[e[n],e[r]]}return e}function l(t,e){return Math.floor(Math.random()*(e-t+1))+t}function nt(t,e){return Math.random()*(e-t)+t}function ot(t,e){return k(t).slice(0,e)}function it(t,e){let r=[];for(let n=0;n<e;n++){let o=l(0,t.length-1);r.push(t[o])}return r}function st(t){return t[l(0,t.length-1)]}function at(t){return l(1,t)}function S(t,e){return new Promise((r,n)=>{if(e?.aborted)return n(c());let o=setTimeout(()=>{s(),r()},t),i=()=>{clearTimeout(o),s(),n(c())},s=()=>{e?.removeEventListener("abort",i)};e?.addEventListener("abort",i)})}function ct(t,e,r){let n=Math.random()*(e-t)+t;return S(n,r)}function x(t,e){let r=isNaN(t.getTime())?new Date:t,n=r.getFullYear(),o=String(r.getMonth()+1).padStart(2,"0"),i=String(r.getDate()).padStart(2,"0"),s=String(r.getHours()).padStart(2,"0"),m=String(r.getMinutes()).padStart(2,"0"),a=String(r.getSeconds()).padStart(2,"0");return e==="date"?`${n}-${o}-${i}`:e==="time"?`${s}:${m}:${a}`:`${n}-${o}-${i} ${s}:${m}:${a}`}function ut(t){return x(t??new Date,"datetime")}function ft(t){return x(t??new Date,"date")}function mt(t){return x(t??new Date,"time")}function pt(t){if(typeof t>"u")return"";if(t instanceof Date)return t.toLocaleString();{let e=typeof t=="string"?Number(t):t;return isNaN(e)?"":new Date(e<1e12?e*1e3:e).toLocaleString()}}var gt=/[!'()*]/g;function lt(t){try{let e=new URL(t);return e.protocol==="http:"||e.protocol==="https:"}catch{return!1}}function xt(t){try{let{origin:e,pathname:r,searchParams:n}=new URL(t);return{baseUrl:e+r,searchParams:n}}catch{throw new Error("Invalid URL")}}function dt(t,e=!1){return Object.keys(t).sort().filter(r=>e||t[r]!=null).map(r=>{let n=t[r]??"";return`${encodeURIComponent(r)}=${encodeURIComponent(String(n))}`}).join("&")}function bt(t,e){let r={};return t.size>0&&t.forEach((n,o)=>{r[o]=n}),e&&(r={...r,...e}),r}function ht(t,e,r,n=""){if(!Number.isFinite(t))return{size:0,unit:"",text:n};let o=t,i=0;for(;o>=e&&i<r.length-1;)o/=e,i++;return{size:o,unit:r[i],text:`${o.toFixed(2).replace(/\.?0+$/,"")} ${r[i]}`}}
1
+ "use strict";var d=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var F=(t,e)=>{for(var r in e)d(t,r,{get:e[r],enumerable:!0})},K=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of z(e))!U.call(t,o)&&o!==r&&d(t,o,{get:()=>e[o],enumerable:!(n=B(e,o))||n.enumerable});return t};var O=t=>K(d({},"__esModule",{value:!0}),t);var wt={};F(wt,{CommonError:()=>f,LogLevelMap:()=>p,bizErrorToError:()=>R,checkAbortSignal:()=>G,chunk:()=>N,concatUint8Arrays:()=>_,convertToCommonError:()=>C,createAbortError:()=>c,createLogger:()=>tt,createResponseError:()=>P,dynamicCall:()=>V,encodeURLParams:()=>bt,execBiz:()=>Q,fetchWithFormat:()=>w,formatDate:()=>x,formatTime:()=>gt,formatUnitSize:()=>yt,getErrorMessage:()=>u,getFormattedDate:()=>mt,getFormattedDateTime:()=>ft,getFormattedTime:()=>pt,getGithubRawJson:()=>X,inArray:()=>v,invalidCharRegex:()=>lt,isBizResult:()=>L,isCanceledError:()=>D,isCommonError:()=>E,isEmptyArr:()=>H,isHttpUrl:()=>xt,isLogLevel:()=>T,isObject:()=>I,isPlainObject:()=>h,logLevels:()=>b,mergeQueryParams:()=>ht,omitUndefined:()=>et,parseGithubRawUrl:()=>$,parseGithubRepoUrl:()=>Y,parseUrl:()=>dt,processRangeInBatches:()=>q,random1ToN:()=>ct,randomFloat:()=>ot,randomInt:()=>l,runRandomFunctions:()=>J,sample:()=>it,sampleOne:()=>at,sampleWithReplacement:()=>st,serializeError:()=>g,shuffle:()=>A,sleep:()=>k,sleepRandom:()=>ut,stripFunctions:()=>y,unwrapBizResult:()=>W,withRetry:()=>nt,withTimeout:()=>rt});module.exports=O(wt);function D(t){return t instanceof Error?t.name==="AbortError"||t.name==="CanceledError"||"code"in t&&t.code==="ERR_CANCELED":!1}function c(t){let e=new Error(t??"\u64CD\u4F5C\u5DF2\u53D6\u6D88");return e.name="AbortError",e}function E(t){return t instanceof f||t instanceof Error&&t.name==="CommonError"}function M(t,e){return e&&(t.message=`${e} ${t.message}`),t}function C(t,e){return E(t)?M(t,e):new f(`${e} ${u(t)}`,t)}function u(t){return typeof t=="string"?t:t instanceof Error||t&&typeof t=="object"&&"message"in t&&typeof t.message=="string"?t.message:String(t)??"\u672A\u77E5\u9519\u8BEF"}var f=class extends Error{constructor(e,r){super(e),r!==void 0&&(this.cause=r instanceof Error?r:new Error(u(r))),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}toString(){return`${this.name}: ${this.message}${this.cause?` (caused by ${this.cause})`:""}`}};var p={trace:0,debug:1,info:2,warn:3,error:4},b=["trace","debug","info","warn","error"];function G(t){if(t?.aborted)throw c()}function H(t){return Array.isArray(t)&&t.length===0}function N(t,e){if(!Number.isInteger(e)||e<1)throw new Error("size \u5FC5\u987B\u662F\u6B63\u6574\u6570");let r=[];for(let n=0;n<t.length;n+=e)r.push(t.slice(n,n+e));return r}function v(t,e){return e.includes(t)}function h(t){if(t===null||typeof t!="object")return!1;let e=Object.getPrototypeOf(t);return e===Object.prototype||e===null}function I(t,e){return t===null||typeof t!="object"||Array.isArray(t)?!1:e!==void 0?e in t:!0}function y(t,e=new WeakMap){if(typeof t=="function")return;if(t===null||typeof t!="object"||t instanceof Date||t instanceof RegExp||t instanceof Map||t instanceof Set||ArrayBuffer.isView(t)||t instanceof ArrayBuffer)return t;if(e.has(t))return e.get(t);if(Array.isArray(t)){let n=[];e.set(t,n);for(let o of t)n.push(y(o,e));return n}if(!h(t))return t;let r={};e.set(t,r);for(let[n,o]of Object.entries(t)){if(typeof o=="function")continue;let i=y(o,e);i!==void 0&&(r[n]=i)}return r}function g(t){return t instanceof Error?{name:t.name,message:t.message,stack:t.stack,cause:"cause"in t&&t.cause?g(t.cause):void 0}:{name:"UnknownError",message:u(t)}}function L(t){return t!=null&&typeof t=="object"&&"success"in t&&typeof t.success=="boolean"&&"msg"in t&&typeof t.msg=="string"}var Q=async t=>{try{return{success:!0,msg:"\u64CD\u4F5C\u6210\u529F",data:await t()}}catch(e){return{success:!1,msg:"\u64CD\u4F5C\u5931\u8D25",error:g(e)}}};async function W(t){if(L(t)){if(t.success)return t.data;throw t.error?R(t.error):new Error(t.msg)}else return t}function R(t){return Object.assign(new Error,t)}function _(t){let e=t.reduce((o,i)=>o+i.length,0),r=new Uint8Array(e),n=0;for(let o of t)r.set(o,n),n+=o.length;return r}function P(t){return new Error(`HTTP ${t.status}: ${t.statusText}`)}async function w(t,e,r){let n=await fetch(t,r);if(!n.ok)throw P(n);switch(e){case"json":return await n.json();case"text":return await n.text();case"blob":return await n.blob();case"arrayBuffer":return await n.arrayBuffer();case"formData":return await n.formData();default:return await n.text()}}function J(t,e){e=e??t.length;let r=Math.floor(Math.random()*e)+1,n=[...t];for(let i=n.length-1;i>0;i--){let s=Math.floor(Math.random()*(i+1));[n[i],n[s]]=[n[s],n[i]]}let o=n.slice(0,r);for(let i of o)i()}async function q(t,e,r,n){for(let o=t;o<=e;o+=r){let i=e-o+1,s=Math.min(r,i),m=Array.from({length:s},(a,S)=>o+S);await n(m)}}function V(t,e,...r){let n=e.split("."),o=t,i=0;for(;i<n.length-1;i++)if(o=o[n[i]],o==null)throw new Error(`Path '${n.slice(0,i+1).join(".")}' is null/undefined`);let s=o[n[i]];if(typeof s!="function")throw new Error(`'${e}' is not a function`);return s.apply(o,r)}function Y(t){t=t.replace(/^git\+/,"");let e=/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git|\/)?$/,r=/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)$/,n=t.match(e);if(n)return{owner:n[1],repo:n[2],branch:"main"};let o=t.match(r);if(o)return{owner:o[1],repo:o[2],branch:o[3]};throw new Error("\u89E3\u6790\u63D2\u4EF6\u4ED3\u5E93URL\u5931\u8D25")}function $(t){let{owner:e,repo:r,branch:n,filePath:o}=t;return`https://raw.githubusercontent.com/${e}/${r}/${n}/${o}`}async function X(t){return await w($(t),"json")}var j=()=>{},Z=new Set(["then","catch","finally","toJSON","toString","valueOf"]);function T(t){return b.indexOf(t)>-1}function tt(t,e){let r="info";return(async()=>{try{let o=(typeof t=="function"?await t():t).toLowerCase();T(o)?r=o:r="info"}catch{r="info"}})().then(),new Proxy(j,{get(o,i){if(!(typeof i!="string"||Z.has(i))&&T(i))return new Proxy(j,{apply(s,m,a){a&&(p[i]<p[r]||e(i,...a))}})}})}var et=t=>Object.fromEntries(Object.entries(t).filter(([e,r])=>r!==void 0));async function rt(t,e){return await Promise.race([t,new Promise((r,n)=>{setTimeout(()=>{n(new Error("Timeout"))},e)})])}async function nt(t,e=3,r=1e3){for(let n=0;n<e;n++)try{return await t()}catch(o){if(n===e-1)throw o;await new Promise(i=>setTimeout(i,r))}throw new Error("Unreachable")}function A(t){let e=t.slice();for(let r=e.length-1;r>0;r--){let n=Math.floor(Math.random()*(r+1));[e[r],e[n]]=[e[n],e[r]]}return e}function l(t,e){return Math.floor(Math.random()*(e-t+1))+t}function ot(t,e){return Math.random()*(e-t)+t}function it(t,e){return A(t).slice(0,e)}function st(t,e){let r=[];for(let n=0;n<e;n++){let o=l(0,t.length-1);r.push(t[o])}return r}function at(t){return t[l(0,t.length-1)]}function ct(t){return l(1,t)}function k(t,e){return new Promise((r,n)=>{if(e?.aborted)return n(c());let o=setTimeout(()=>{s(),r()},t),i=()=>{clearTimeout(o),s(),n(c())},s=()=>{e?.removeEventListener("abort",i)};e?.addEventListener("abort",i)})}function ut(t,e,r){let n=Math.random()*(e-t)+t;return k(n,r)}function x(t,e){let r=isNaN(t.getTime())?new Date:t,n=r.getFullYear(),o=String(r.getMonth()+1).padStart(2,"0"),i=String(r.getDate()).padStart(2,"0"),s=String(r.getHours()).padStart(2,"0"),m=String(r.getMinutes()).padStart(2,"0"),a=String(r.getSeconds()).padStart(2,"0");return e==="date"?`${n}-${o}-${i}`:e==="time"?`${s}:${m}:${a}`:`${n}-${o}-${i} ${s}:${m}:${a}`}function ft(t){return x(t??new Date,"datetime")}function mt(t){return x(t??new Date,"date")}function pt(t){return x(t??new Date,"time")}function gt(t){if(typeof t>"u")return"";if(t instanceof Date)return t.toLocaleString();{let e=typeof t=="string"?Number(t):t;return isNaN(e)?"":new Date(e<1e12?e*1e3:e).toLocaleString()}}var lt=/[!'()*]/g;function xt(t){try{let e=new URL(t);return e.protocol==="http:"||e.protocol==="https:"}catch{return!1}}function dt(t){try{let{origin:e,pathname:r,searchParams:n}=new URL(t);return{baseUrl:e+r,searchParams:n}}catch{throw new Error("Invalid URL")}}function bt(t,e=!1){return Object.keys(t).sort().filter(r=>e||t[r]!=null).map(r=>{let n=t[r]??"";return`${encodeURIComponent(r)}=${encodeURIComponent(String(n))}`}).join("&")}function ht(t,e){let r={};return t.size>0&&t.forEach((n,o)=>{r[o]=n}),e&&(r={...r,...e}),r}function yt(t,e,r,n=""){if(!Number.isFinite(t))return{size:0,unit:"",text:n};let o=t,i=0;for(;o>=e&&i<r.length-1;)o/=e,i++;return{size:o,unit:r[i],text:`${o.toFixed(2).replace(/\.?0+$/,"")} ${r[i]}`}}
2
2
  //# sourceMappingURL=core.cjs.map
package/dist/core.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/index.ts","../src/core/utils/error.ts","../src/core/error/common-error.ts","../src/core/types/logger.ts","../src/core/utils/abort.ts","../src/core/utils/array.ts","../src/core/utils/type.ts","../src/core/utils/serialize.ts","../src/core/utils/biz-result.ts","../src/core/utils/fetch.ts","../src/core/utils/function.ts","../src/core/utils/github.ts","../src/core/utils/logger.ts","../src/core/utils/object.ts","../src/core/utils/promise.ts","../src/core/utils/random.ts","../src/core/utils/sleep.ts","../src/core/utils/time.ts","../src/core/utils/url.ts","../src/core/utils/number/format.ts"],"sourcesContent":["export * from \"./error/common-error.js\";\nexport * from \"./types/biz-result.js\";\nexport * from \"./types/helpers.js\";\nexport * from \"./types/logger.js\";\nexport * from \"./types/physical.js\";\nexport * from \"./utils/abort.js\";\nexport * from \"./utils/array.js\";\nexport * from \"./utils/biz-result.js\";\nexport * from \"./utils/error.js\";\nexport * from \"./utils/fetch.js\";\nexport * from \"./utils/function.js\";\nexport * from \"./utils/github.js\";\nexport * from \"./utils/logger.js\";\nexport * from \"./utils/object.js\";\nexport * from \"./utils/promise.js\";\nexport * from \"./utils/random.js\";\nexport * from \"./utils/serialize.js\";\nexport * from \"./utils/sleep.js\";\nexport * from \"./utils/time.js\";\nexport * from \"./utils/type.js\";\nexport * from \"./utils/url.js\";\nexport * from \"./utils/number/format.js\";\n","import { CommonError } from '../error/common-error.js'\n\n/**\n * 是否为取消操作的错误\n */\nexport function isCanceledError(err: unknown): err is Error {\n if (!(err instanceof Error)) return false\n\n return err.name === 'AbortError' || err.name === 'CanceledError' || ('code' in err && err.code === 'ERR_CANCELED')\n}\n\n/**\n * 创建取消错误\n * @param msg\n */\nexport function createAbortError(msg?: string): Error {\n const error = new Error(msg ?? '操作已取消')\n error.name = 'AbortError'\n return error\n}\n\n/**\n * 是否为通用错误对象\n */\nexport function isCommonError(error: unknown): error is CommonError {\n return error instanceof CommonError || (error instanceof Error && error.name === 'CommonError')\n}\n\n/**\n * 给错误消息添加前缀(空格隔开)\n */\nfunction prefixError(error: Error, prefix?: string): Error {\n if (!prefix) return error\n\n error.message = `${prefix} ${error.message}`\n return error\n}\n\n/**\n * 转换到通用异常\n */\nexport function convertToCommonError(error: unknown, prefix?: string) {\n if (isCommonError(error)) {\n return prefixError(error, prefix)\n }\n return new CommonError(`${prefix} ${getErrorMessage(error)}`, error)\n}\n\n/**\n * 获取异常信息\n */\nexport function getErrorMessage(error: unknown): string {\n if (typeof error === 'string') {\n return error\n }\n if (error instanceof Error) {\n return error.message\n }\n if (error && typeof error === 'object' && 'message' in error && typeof error.message === 'string') {\n return error.message\n }\n return String(error) ?? '未知错误'\n}\n","import { getErrorMessage } from '../utils/error.js'\n\n/**\n * 通用错误\n */\nexport class CommonError extends Error {\n // 原始错误\n cause?: Error\n\n constructor(message: string, cause?: unknown) {\n super(message)\n\n if (cause !== undefined) {\n this.cause = cause instanceof Error ? cause : new Error(getErrorMessage(cause))\n }\n\n this.name = new.target.name\n Object.setPrototypeOf(this, new.target.prototype)\n }\n\n toString() {\n return `${this.name}: ${this.message}${this.cause ? ` (caused by ${this.cause})` : ''}`\n }\n}\n","export const LogLevelMap = {\n trace: 0,\n debug: 1,\n info: 2,\n warn: 3,\n error: 4,\n} as const\n\nexport type LogLevel = keyof typeof LogLevelMap\n\nexport const logLevels = ['trace', 'debug', 'info', 'warn', 'error'] as LogLevel[]\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type LogFn = (...data: any[]) => void\n\nexport type Logger<K extends LogLevel = LogLevel> = {\n [key in K]: LogFn\n}\n","import { createAbortError } from './error.js'\n\n/**\n * 检查取消信号\n */\nexport function checkAbortSignal(abortSignal?: AbortSignal) {\n if (abortSignal?.aborted) {\n throw createAbortError()\n }\n}\n","/**\n * 是否为空数组\n * @param data\n */\nexport function isEmptyArr(data: unknown) {\n return Array.isArray(data) && data.length === 0\n}\n\n/**\n * 将数组分块为指定大小的多个子数组\n * @param arr 原数组\n * @param size 每个块的长度\n * @example chunk([1,2,3,4,5], 2) => [[1,2],[3,4],[5]]\n */\nexport function chunk<T>(arr: T[], size: number): T[][] {\n if (!Number.isInteger(size) || size < 1) throw new Error('size 必须是正整数')\n const result: T[][] = []\n for (let i = 0; i < arr.length; i += size) {\n result.push(arr.slice(i, i + size))\n }\n return result\n}\n\n/**\n * 判断数组是否存在某些项\n */\nexport function inArray<T>(value: T, array: readonly T[]): boolean {\n return array.includes(value)\n}\n","import type { ObjectWithKeys } from '../types/helpers.js'\n\n/**\n * 判断一个值是否为纯对象\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object') return false\n const proto = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\n/**\n * 包括类实例、普通对象,不包括 数组、null 和原始类型\n */\nexport function isObject<K extends string | symbol>(value: unknown, key?: K): value is ObjectWithKeys<K> {\n if (value === null || typeof value !== 'object') return false\n if (Array.isArray(value)) return false\n if (key !== undefined) {\n return key in value\n }\n return true\n}\n","import { isPlainObject } from './type.js'\nimport { getErrorMessage } from './error.js'\nimport type { BizError } from '../types/biz-result.js'\n\n/**\n * 递归移除对象(或数组)中的所有函数属性,返回一个可安全序列化的副本。\n *\n * @typeParam T - 输入值的类型。\n * @param value - 待处理的值(基本类型、对象、数组等)。\n * @param seen - 内部使用的 WeakMap,用于记录已访问过的对象,防止循环引用。\n * 调用方通常无需传递此参数。\n * @returns 处理后的新副本,其中所有函数属性都被移除。\n * 基本类型(string, number, boolean, null, undefined)将原样返回。\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function stripFunctions<T>(value: T, seen = new WeakMap<object, any>()): T {\n if (typeof value === 'function') return undefined as T\n if (value === null || typeof value !== 'object') return value\n\n if (\n value instanceof Date ||\n value instanceof RegExp ||\n value instanceof Map ||\n value instanceof Set ||\n ArrayBuffer.isView(value) ||\n value instanceof ArrayBuffer\n ) {\n return value\n }\n\n if (seen.has(value as object)) {\n return seen.get(value as object)\n }\n\n if (Array.isArray(value)) {\n const out: unknown[] = []\n seen.set(value as object, out)\n for (const item of value) {\n out.push(stripFunctions(item, seen))\n }\n return out as T\n }\n\n if (!isPlainObject(value)) {\n return value\n }\n\n const out: Record<string, unknown> = {}\n seen.set(value as object, out)\n\n for (const [key, item] of Object.entries(value)) {\n if (typeof item === 'function') continue\n const next = stripFunctions(item, seen)\n if (next !== undefined) out[key] = next\n }\n\n return out as T\n}\n\n/**\n * 序列号错误对象 为 BizError\n */\nexport function serializeError(err: unknown): BizError {\n if (!(err instanceof Error)) {\n return {\n name: 'UnknownError',\n message: getErrorMessage(err),\n }\n }\n\n return {\n name: err.name,\n message: err.message,\n stack: err.stack,\n cause: 'cause' in err && err.cause ? serializeError(err.cause) : undefined,\n }\n}\n","import type { BizResult, BizError } from '../types/biz-result.js'\nimport { serializeError } from './serialize.js'\n\n/**\n * 是否为业务结果(序列化后)\n */\nexport function isBizResult<T = unknown>(result: unknown): result is BizResult<T> {\n return (\n result != null &&\n typeof result === 'object' &&\n 'success' in result &&\n typeof result.success === 'boolean' &&\n 'msg' in result &&\n typeof result.msg === 'string'\n )\n}\n\n/**\n * 执行异步函数,自动捕获异常并转换为 BizResult 对象\n * @param runFn 执行方法\n */\nexport const execBiz = async <T>(runFn: () => T | Promise<T>): Promise<BizResult<Awaited<T>>> => {\n try {\n return {\n success: true,\n msg: '操作成功',\n data: await runFn(),\n }\n } catch (e) {\n return {\n success: false,\n msg: '操作失败',\n error: serializeError(e),\n }\n }\n}\n\n/**\n * 解包 BizResult<T> 对象为 Promise<T>,非 BizResult 对象原样返回。\n */\nexport async function unwrapBizResult<T>(result: BizResult<T>): Promise<T>\nexport async function unwrapBizResult(result: unknown): Promise<unknown>\nexport async function unwrapBizResult<T>(result: BizResult<T> | unknown): Promise<T | unknown> {\n if (isBizResult<T>(result)) {\n if (result.success) {\n return result.data as T\n }\n\n if (result.error) {\n throw bizErrorToError(result.error)\n }\n\n throw new Error(result.msg)\n } else {\n return result\n }\n}\n\nexport function bizErrorToError(bizError: BizError) {\n return Object.assign(new Error(), bizError)\n}\n","/**\n * 用于指定 `fetch` 响应体的解析方式。\n * 对应 `Response` 对象的不同解析方法(`.json()`、`.text()` 等)。\n */\nexport type ResponseBodyFormat =\n | 'json' // 解析为 JSON 对象\n | 'text' // 解析为原始字符串\n | 'blob' // 解析为 Blob 对象(适用于二进制文件,如图片、压缩包)\n | 'arrayBuffer' // 解析为 ArrayBuffer(适用于底层二进制操作)\n | 'formData' // 解析为 FormData 对象(适用于处理 multipart/form-data 响应)\n\n/**\n * 创建响应错误\n */\nexport function createResponseError(response: Response) {\n return new Error(`HTTP ${response.status}: ${response.statusText}`)\n}\n\n/**\n * 使用指定的响应解析格式发起 fetch 请求\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function fetchWithFormat<T = any>(\n url: string,\n format: ResponseBodyFormat,\n init?: RequestInit,\n): Promise<T> {\n const response = await fetch(url, init)\n if (!response.ok) {\n throw createResponseError(response)\n }\n switch (format) {\n case 'json':\n return (await response.json()) as T\n case 'text':\n return (await response.text()) as T\n case 'blob':\n return (await response.blob()) as T\n case 'arrayBuffer':\n return (await response.arrayBuffer()) as T\n case 'formData':\n return (await response.formData()) as T\n default:\n return (await response.text()) as T\n }\n}\n","/**\n * 随机运行参数\n * @param fns\n * @param maxCount 最多执行次数(1 ~ fns.length)\n */\nexport function runRandomFunctions(fns: Array<() => void>, maxCount?: number): void {\n maxCount = maxCount ?? fns.length\n const count = Math.floor(Math.random() * maxCount) + 1\n\n const shuffled = [...fns]\n for (let i = shuffled.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1))\n ;[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]\n }\n\n const selected = shuffled.slice(0, count)\n\n for (const fn of selected) {\n fn()\n }\n}\n\n/**\n * 将数字范围按批次处理,每个批次调用一次异步函数\n *\n * @param start - 起始值(包含)\n * @param end - 结束值(包含)\n * @param batchSize - 每批最大元素个数\n * @param processor - 处理单批数字数组的异步函数\n *\n * @example\n * // 分批处理 1..10,每批最多 3 个数字\n * await processRangeInBatches(1, 10, 3, async (batch) => {\n * console.log(batch) // 输出: [1,2,3], [4,5,6], [7,8,9], [10]\n * })\n */\nexport async function processRangeInBatches(\n start: number,\n end: number,\n batchSize: number,\n processor: (batch: number[]) => Promise<void>,\n): Promise<void> {\n for (let current = start; current <= end; current += batchSize) {\n const remaining = end - current + 1\n const actualSize = Math.min(batchSize, remaining)\n const batch = Array.from({ length: actualSize }, (_, idx) => current + idx)\n\n await processor(batch)\n }\n}\n\n/**\n * 动态调用\n * @param root 对象\n * @param path 调用路径\n * @param args 参数\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function dynamicCall<T = any>(root: any, path: string, ...args: any[]): T {\n const segments = path.split('.')\n let context = root\n let i = 0\n for (; i < segments.length - 1; i++) {\n context = context[segments[i]]\n if (context == null) {\n throw new Error(`Path '${segments.slice(0, i + 1).join('.')}' is null/undefined`)\n }\n }\n const fn = context[segments[i]]\n if (typeof fn !== 'function') {\n throw new Error(`'${path}' is not a function`)\n }\n return fn.apply(context, args)\n}\n","import { fetchWithFormat } from './fetch.js'\n\n/** github 仓库信息 */\nexport interface GitHubRepo {\n /** 仓库所有者(用户或组织名) */\n owner: string\n /** 仓库名称 */\n repo: string\n}\n\n/** github 仓库分支信息 */\nexport type GitHubRepoBranch = GitHubRepo & {\n /** 分支名称 */\n branch: string\n}\n\n/** github 仓库文件信息 */\nexport type GitHubRepoFile = GitHubRepoBranch & {\n /** 文件路径 */\n filePath: string\n}\n\n/**\n * 从 url 解析 github 仓库信息\n * @param repositoryUrl 仓库 URL(支持带有git+前缀、具体文件路径)\n */\nexport function parseGithubRepoUrl(repositoryUrl: string): GitHubRepoBranch {\n // 去掉 git+ 前缀\n repositoryUrl = repositoryUrl.replace(/^git\\+/, '')\n\n const regexBase = /^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git|\\/)?$/\n const regexFile = /^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+)\\/blob\\/([^/]+)$/\n\n // 情况 1:git clone 地址 或 repo 根路径\n const m1 = repositoryUrl.match(regexBase)\n if (m1) {\n return {\n owner: m1[1],\n repo: m1[2],\n branch: 'main', // 默认分支 main\n }\n }\n\n // 情况 2:具体文件路径\n const m2 = repositoryUrl.match(regexFile)\n if (m2) {\n return {\n owner: m2[1],\n repo: m2[2],\n branch: m2[3],\n }\n }\n\n throw new Error('解析插件仓库URL失败')\n}\n\n/**\n * 解析 github 仓库文件的原始内容的 url\n */\nexport function parseGithubRawUrl(gitHubRepoFile: GitHubRepoFile) {\n const { owner, repo, branch, filePath } = gitHubRepoFile\n return `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${filePath}`\n}\n\n/**\n * 获取 github 仓库文件的 json 内容并解析为对象 T\n * @param gitHubRepoFile\n */\nexport async function getGithubRawJson<O>(gitHubRepoFile: GitHubRepoFile): Promise<O> {\n return JSON.parse(await fetchWithFormat(parseGithubRawUrl(gitHubRepoFile), 'json')) as O\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { type LogLevel, logLevels, type Logger, type LogFn, LogLevelMap } from '../types/logger.js'\n\nconst noop = () => {}\nconst ignoredProps = new Set(['then', 'catch', 'finally', 'toJSON', 'toString', 'valueOf'])\n\nexport function isLogLevel<K extends LogLevel = LogLevel>(level: string): level is K {\n return logLevels.indexOf(level as LogLevel) > -1\n}\n\n/**\n * 创建一个带级别过滤的 logger 代理。\n *\n * @template K - 支持的日志级别类型\n * @param getLogLevel - 获取当前配置级别的函数,仅在创建代理时执行\n * @param logWriter - 执行实际日志输出的函数(如 console.log)\n * @returns 返回一个可直接调用的 logger 实例\n */\nexport function createLogger<K extends LogLevel = LogLevel>(\n getLogLevel: () => K | Promise<K>,\n logWriter: (logLevel: K, ...data: any[]) => void,\n): Logger<K> {\n let cachedLevel: K = 'info' as K\n\n const syncConfig = async () => {\n try {\n const configLevel = (await getLogLevel()).toLowerCase()\n if (isLogLevel<K>(configLevel)) {\n cachedLevel = configLevel\n } else {\n cachedLevel = 'info' as K\n }\n } catch {\n cachedLevel = 'info' as K\n }\n }\n\n syncConfig().then()\n\n return new Proxy(noop, {\n get(target, logLevel) {\n if (typeof logLevel !== 'string' || ignoredProps.has(logLevel)) return undefined\n if (!isLogLevel<K>(logLevel)) return undefined\n\n return new Proxy(noop, {\n apply(_target: () => void, _thisArg: any, args: any[]): void {\n if (!args) return\n\n if (LogLevelMap[logLevel] < LogLevelMap[cachedLevel]) {\n return\n }\n\n logWriter(logLevel, ...args)\n },\n }) as LogFn\n },\n }) as unknown as Logger<K>\n}\n","/**\n * 忽略 undefined 值的字段\n * @param obj\n */\nexport const omitUndefined = <T extends object>(obj: T): Partial<T> =>\n Object.fromEntries(Object.entries(obj).filter(([_, v]) => v !== undefined)) as Partial<T>\n","/**\n * 为 Promise 添加超时控制\n * @param promise - 原始异步任务\n * @param timeout - 超时时间(毫秒)\n * @returns 若原 Promise 在超时前完成,则返回其结果;否则抛出超时错误\n * @throws {Error} 超时后抛出 'Timeout' 错误\n */\nexport async function withTimeout<T>(promise: Promise<T>, timeout: number): Promise<T> {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error('Timeout'))\n }, timeout)\n }),\n ])\n}\n\n/**\n * 带重试机制的异步函数执行器\n * @param fn - 返回 Promise 的异步函数\n * @param retries - 最大重试次数(默认 3)\n * @param delay - 重试间隔毫秒(默认 1000)\n * @returns Promise<T>\n */\nexport async function withRetry<T>(fn: () => Promise<T>, retries: number = 3, delay: number = 1000): Promise<T> {\n for (let i = 0; i < retries; i++) {\n try {\n return await fn()\n } catch (error) {\n if (i === retries - 1) throw error\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n }\n throw new Error('Unreachable')\n}\n","/**\n * 数组洗牌\n */\nexport function shuffle<T>(arr: T[]): T[] {\n const clone = arr.slice()\n for (let i = clone.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1))\n ;[clone[i], clone[j]] = [clone[j], clone[i]]\n }\n return clone\n}\n\n/**\n * 获取 [min, max] 的随机整数\n */\nexport function randomInt(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min\n}\n\n/**\n * 获取 [min, max) 的随机浮点数\n */\nexport function randomFloat(min: number, max: number): number {\n return Math.random() * (max - min) + min\n}\n\n/**\n * 从数组中随机取若干项,不可重复\n */\nexport function sample<T>(arr: T[], count: number): T[] {\n return shuffle(arr).slice(0, count)\n}\n\n/**\n * 从数组中随机取若干项,可重复\n */\nexport function sampleWithReplacement<T>(arr: T[], count: number): T[] {\n const result: T[] = []\n for (let i = 0; i < count; i++) {\n const index = randomInt(0, arr.length - 1)\n result.push(arr[index])\n }\n return result\n}\n\n/**\n * 从数组中获取随机项\n */\nexport function sampleOne<T>(arr: T[]): T {\n return arr[randomInt(0, arr.length - 1)]\n}\n\n/**\n * 获取 1~n 的随机数\n */\nexport function random1ToN(n: number): number {\n return randomInt(1, n)\n}\n","import { createAbortError } from './error.js'\n\n/**\n * 支持取消的 sleep\n * @param ms 延迟毫秒数\n * @param signal 取消信号\n */\nexport function sleep(ms: number, signal?: AbortSignal) {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) return reject(createAbortError())\n\n const timer = setTimeout(() => {\n cleanup()\n resolve()\n }, ms)\n\n const onAbort = () => {\n clearTimeout(timer)\n cleanup()\n reject(createAbortError())\n }\n\n const cleanup = () => {\n signal?.removeEventListener('abort', onAbort)\n }\n\n signal?.addEventListener('abort', onAbort)\n })\n}\n\n/**\n * 支持取消的随机 sleep\n * @param minMS 最小延迟毫秒数\n * @param maxMS 最大延迟毫秒数\n * @param signal 取消信号\n */\nexport function sleepRandom(minMS: number, maxMS: number, signal?: AbortSignal) {\n const ms = Math.random() * (maxMS - minMS) + minMS\n return sleep(ms, signal)\n}\n","/**\n * 格式化日期\n */\nexport function formatDate(date: Date, pattern: 'date' | 'time' | 'datetime'): string {\n const d = !isNaN(date.getTime()) ? date : new Date()\n const year = d.getFullYear()\n const month = String(d.getMonth() + 1).padStart(2, '0')\n const day = String(d.getDate()).padStart(2, '0')\n const hours = String(d.getHours()).padStart(2, '0')\n const minutes = String(d.getMinutes()).padStart(2, '0')\n const seconds = String(d.getSeconds()).padStart(2, '0')\n\n if (pattern === 'date') return `${year}-${month}-${day}`\n if (pattern === 'time') return `${hours}:${minutes}:${seconds}`\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`\n}\n\n/**\n * 格式化时间为 2020-02-02 20:20:20 的字符串\n * @param date 需要格式化的时间,为空则获取当前时间\n */\nexport function getFormattedDateTime(date?: Date): string {\n return formatDate(date ?? new Date(), 'datetime')\n}\n\n/**\n * 格式化时间为 2020-02-02 20:20:20 的字符串\n * @param date 需要格式化的时间,为空则获取当前时间\n */\nexport function getFormattedDate(date?: Date): string {\n return formatDate(date ?? new Date(), 'date')\n}\n\n/**\n * 格式化时间为 20:20:20 的字符串\n * @param date 需要格式化的时间,为空则获取当前时间\n */\nexport function getFormattedTime(date?: Date): string {\n return formatDate(date ?? new Date(), 'time')\n}\n\n/**\n * 格式化时间戳。可自动判断 10/13 位时间戳\n * @param timestamp\n */\nexport function formatTime(timestamp: number | string | Date | undefined): string {\n if (typeof timestamp === 'undefined') return ''\n if (timestamp instanceof Date) {\n return timestamp.toLocaleString()\n } else {\n const num = typeof timestamp === 'string' ? Number(timestamp) : timestamp\n if (isNaN(num)) return ''\n\n return new Date(num < 1e12 ? num * 1000 : num).toLocaleString()\n }\n}\n","/** URL query 中必须编码的保留字符 (RFC 3986) */\nexport const invalidCharRegex = /[!'()*]/g\n\n/** 查询参数 */\nexport type QueryParams = Record<string, string | number | boolean | null | undefined>\n\n/**\n * 已解析的 url\n */\nexport interface ParsedUrl {\n baseUrl: string\n searchParams: URLSearchParams\n}\n\n/**\n * 判断字符串是否为有效的 HTTP/HTTPS URL\n * @param path - 待检测的字符串\n */\nexport function isHttpUrl(path: string) {\n try {\n const url = new URL(path)\n return url.protocol === 'http:' || url.protocol === 'https:'\n } catch {\n return false\n }\n}\n\n/**\n * 解析 url\n * @param url\n */\nexport function parseUrl(url: string): ParsedUrl {\n try {\n const { origin, pathname, searchParams } = new URL(url)\n return {\n baseUrl: origin + pathname,\n searchParams,\n }\n } catch {\n throw new Error('Invalid URL')\n }\n}\n\n/**\n * 编码 URL 参数\n * @param params 查询参数\n * @param keepEmptyValues 保留 null/undefined的值(空字符串)\n */\nexport function encodeURLParams(params: QueryParams, keepEmptyValues: boolean = false) {\n return (\n Object.keys(params)\n // 排序\n .sort()\n // 过滤\n .filter((key) => {\n return keepEmptyValues || params[key] != null\n })\n // 编码 key 和 value\n .map((key) => {\n const raw = params[key] ?? ''\n return `${encodeURIComponent(key)}=${encodeURIComponent(String(raw))}`\n })\n // 拼接\n .join('&')\n )\n}\n\n/**\n *\n */\n/**\n * 合并查询参数\n * @param urlSearchParams url解析后查询参数\n * @param params 单独传的查询参数\n */\nexport function mergeQueryParams(urlSearchParams: URLSearchParams, params?: QueryParams): QueryParams {\n let mergedParams: QueryParams = {}\n if (urlSearchParams.size > 0) {\n // 合并url里的查询参数\n urlSearchParams.forEach((value, key) => {\n mergedParams[key] = value\n })\n }\n // 处理单独传的查询参数对象\n if (params) {\n mergedParams = { ...mergedParams, ...params }\n }\n return mergedParams\n}\n","/**\n * 格式化后的单位数据(如文件大小)\n */\nexport interface FormattedUnitSize {\n /** 换算后该单位的数值(未四舍五入) */\n size: number\n /** 单位名称,如 'MB' */\n unit: string\n /** 显示文本:数值四舍五入保留两位小数 + 单位,如 '1.50 MB' */\n text: string\n}\n\n/**\n * 按进制自动格式化单位\n * @param value 数值\n * @param base 进制(1024 / 1000)\n * @param units 单位列表\n * @param invalidText 无效值返回文本\n */\nexport function formatUnitSize(value: number, base: number, units: string[], invalidText = ''): FormattedUnitSize {\n if (!Number.isFinite(value)) {\n return { size: 0, unit: '', text: invalidText }\n }\n\n let size = value\n let unitIndex = 0\n\n while (size >= base && unitIndex < units.length - 1) {\n size /= base\n unitIndex++\n }\n\n return {\n size,\n unit: units[unitIndex],\n text: `${size.toFixed(2).replace(/\\.?0+$/, '')} ${units[unitIndex]}`,\n }\n}\n"],"mappings":"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","names":["core_exports","__export","CommonError","LogLevelMap","bizErrorToError","checkAbortSignal","chunk","convertToCommonError","createAbortError","createLogger","createResponseError","dynamicCall","encodeURLParams","execBiz","fetchWithFormat","formatDate","formatTime","formatUnitSize","getErrorMessage","getFormattedDate","getFormattedDateTime","getFormattedTime","getGithubRawJson","inArray","invalidCharRegex","isBizResult","isCanceledError","isCommonError","isEmptyArr","isHttpUrl","isLogLevel","isObject","isPlainObject","logLevels","mergeQueryParams","omitUndefined","parseGithubRawUrl","parseGithubRepoUrl","parseUrl","processRangeInBatches","random1ToN","randomFloat","randomInt","runRandomFunctions","sample","sampleOne","sampleWithReplacement","serializeError","shuffle","sleep","sleepRandom","stripFunctions","unwrapBizResult","withRetry","withTimeout","__toCommonJS","isCanceledError","err","createAbortError","msg","error","isCommonError","CommonError","prefixError","prefix","convertToCommonError","getErrorMessage","CommonError","message","cause","getErrorMessage","LogLevelMap","logLevels","checkAbortSignal","abortSignal","createAbortError","isEmptyArr","data","chunk","arr","size","result","i","inArray","value","array","isPlainObject","value","proto","isObject","key","stripFunctions","value","seen","out","item","isPlainObject","key","next","serializeError","err","getErrorMessage","isBizResult","result","execBiz","runFn","serializeError","unwrapBizResult","bizErrorToError","bizError","createResponseError","response","fetchWithFormat","url","format","init","runRandomFunctions","fns","maxCount","count","shuffled","j","selected","fn","processRangeInBatches","start","end","batchSize","processor","current","remaining","actualSize","batch","_","idx","dynamicCall","root","path","args","segments","context","parseGithubRepoUrl","repositoryUrl","regexBase","regexFile","m1","m2","parseGithubRawUrl","gitHubRepoFile","owner","repo","branch","filePath","getGithubRawJson","fetchWithFormat","noop","ignoredProps","isLogLevel","level","logLevels","createLogger","getLogLevel","logWriter","cachedLevel","configLevel","target","logLevel","_target","_thisArg","args","LogLevelMap","omitUndefined","obj","_","v","withTimeout","promise","timeout","_","reject","withRetry","fn","retries","delay","i","error","resolve","shuffle","arr","clone","i","j","randomInt","min","max","randomFloat","sample","count","sampleWithReplacement","result","index","sampleOne","random1ToN","n","sleep","ms","signal","resolve","reject","createAbortError","timer","cleanup","onAbort","sleepRandom","minMS","maxMS","formatDate","date","pattern","d","year","month","day","hours","minutes","seconds","getFormattedDateTime","getFormattedDate","getFormattedTime","formatTime","timestamp","num","invalidCharRegex","isHttpUrl","path","url","parseUrl","origin","pathname","searchParams","encodeURLParams","params","keepEmptyValues","key","raw","mergeQueryParams","urlSearchParams","mergedParams","value","formatUnitSize","value","base","units","invalidText","size","unitIndex"]}
1
+ {"version":3,"sources":["../src/core/index.ts","../src/core/utils/error.ts","../src/core/error/common-error.ts","../src/core/types/logger.ts","../src/core/utils/abort.ts","../src/core/utils/array.ts","../src/core/utils/type.ts","../src/core/utils/serialize.ts","../src/core/utils/biz-result.ts","../src/core/utils/bytes.ts","../src/core/utils/fetch.ts","../src/core/utils/function.ts","../src/core/utils/github.ts","../src/core/utils/logger.ts","../src/core/utils/object.ts","../src/core/utils/promise.ts","../src/core/utils/random.ts","../src/core/utils/sleep.ts","../src/core/utils/time.ts","../src/core/utils/url.ts","../src/core/utils/number/format.ts"],"sourcesContent":["export * from \"./error/common-error.js\";\nexport * from \"./types/biz-result.js\";\nexport * from \"./types/helpers.js\";\nexport * from \"./types/logger.js\";\nexport * from \"./types/physical.js\";\nexport * from \"./utils/abort.js\";\nexport * from \"./utils/array.js\";\nexport * from \"./utils/biz-result.js\";\nexport * from \"./utils/bytes.js\";\nexport * from \"./utils/error.js\";\nexport * from \"./utils/fetch.js\";\nexport * from \"./utils/function.js\";\nexport * from \"./utils/github.js\";\nexport * from \"./utils/logger.js\";\nexport * from \"./utils/object.js\";\nexport * from \"./utils/promise.js\";\nexport * from \"./utils/random.js\";\nexport * from \"./utils/serialize.js\";\nexport * from \"./utils/sleep.js\";\nexport * from \"./utils/time.js\";\nexport * from \"./utils/type.js\";\nexport * from \"./utils/url.js\";\nexport * from \"./utils/number/format.js\";\n","import { CommonError } from '../error/common-error.js'\n\n/**\n * 是否为取消操作的错误\n */\nexport function isCanceledError(err: unknown): err is Error {\n if (!(err instanceof Error)) return false\n\n return err.name === 'AbortError' || err.name === 'CanceledError' || ('code' in err && err.code === 'ERR_CANCELED')\n}\n\n/**\n * 创建取消错误\n * @param msg\n */\nexport function createAbortError(msg?: string): Error {\n const error = new Error(msg ?? '操作已取消')\n error.name = 'AbortError'\n return error\n}\n\n/**\n * 是否为通用错误对象\n */\nexport function isCommonError(error: unknown): error is CommonError {\n return error instanceof CommonError || (error instanceof Error && error.name === 'CommonError')\n}\n\n/**\n * 给错误消息添加前缀(空格隔开)\n */\nfunction prefixError(error: Error, prefix?: string): Error {\n if (!prefix) return error\n\n error.message = `${prefix} ${error.message}`\n return error\n}\n\n/**\n * 转换到通用异常\n */\nexport function convertToCommonError(error: unknown, prefix?: string) {\n if (isCommonError(error)) {\n return prefixError(error, prefix)\n }\n return new CommonError(`${prefix} ${getErrorMessage(error)}`, error)\n}\n\n/**\n * 获取异常信息\n */\nexport function getErrorMessage(error: unknown): string {\n if (typeof error === 'string') {\n return error\n }\n if (error instanceof Error) {\n return error.message\n }\n if (error && typeof error === 'object' && 'message' in error && typeof error.message === 'string') {\n return error.message\n }\n return String(error) ?? '未知错误'\n}\n","import { getErrorMessage } from '../utils/error.js'\n\n/**\n * 通用错误\n */\nexport class CommonError extends Error {\n // 原始错误\n cause?: Error\n\n constructor(message: string, cause?: unknown) {\n super(message)\n\n if (cause !== undefined) {\n this.cause = cause instanceof Error ? cause : new Error(getErrorMessage(cause))\n }\n\n this.name = new.target.name\n Object.setPrototypeOf(this, new.target.prototype)\n }\n\n toString() {\n return `${this.name}: ${this.message}${this.cause ? ` (caused by ${this.cause})` : ''}`\n }\n}\n","export const LogLevelMap = {\n trace: 0,\n debug: 1,\n info: 2,\n warn: 3,\n error: 4,\n} as const\n\nexport type LogLevel = keyof typeof LogLevelMap\n\nexport const logLevels = ['trace', 'debug', 'info', 'warn', 'error'] as LogLevel[]\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type LogFn = (...data: any[]) => void\n\nexport type Logger<K extends LogLevel = LogLevel> = {\n [key in K]: LogFn\n}\n","import { createAbortError } from './error.js'\n\n/**\n * 检查取消信号\n */\nexport function checkAbortSignal(abortSignal?: AbortSignal) {\n if (abortSignal?.aborted) {\n throw createAbortError()\n }\n}\n","/**\n * 是否为空数组\n * @param data\n */\nexport function isEmptyArr(data: unknown) {\n return Array.isArray(data) && data.length === 0\n}\n\n/**\n * 将数组分块为指定大小的多个子数组\n * @param arr 原数组\n * @param size 每个块的长度\n * @example chunk([1,2,3,4,5], 2) => [[1,2],[3,4],[5]]\n */\nexport function chunk<T>(arr: T[], size: number): T[][] {\n if (!Number.isInteger(size) || size < 1) throw new Error('size 必须是正整数')\n const result: T[][] = []\n for (let i = 0; i < arr.length; i += size) {\n result.push(arr.slice(i, i + size))\n }\n return result\n}\n\n/**\n * 判断数组是否存在某些项\n */\nexport function inArray<T>(value: T, array: readonly T[]): boolean {\n return array.includes(value)\n}\n","import type { ObjectWithKeys } from '../types/helpers.js'\n\n/**\n * 判断一个值是否为纯对象\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object') return false\n const proto = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\n/**\n * 包括类实例、普通对象,不包括 数组、null 和原始类型\n */\nexport function isObject<K extends string | symbol>(value: unknown, key?: K): value is ObjectWithKeys<K> {\n if (value === null || typeof value !== 'object') return false\n if (Array.isArray(value)) return false\n if (key !== undefined) {\n return key in value\n }\n return true\n}\n","import { isPlainObject } from './type.js'\nimport { getErrorMessage } from './error.js'\nimport type { BizError } from '../types/biz-result.js'\n\n/**\n * 递归移除对象(或数组)中的所有函数属性,返回一个可安全序列化的副本。\n *\n * @typeParam T - 输入值的类型。\n * @param value - 待处理的值(基本类型、对象、数组等)。\n * @param seen - 内部使用的 WeakMap,用于记录已访问过的对象,防止循环引用。\n * 调用方通常无需传递此参数。\n * @returns 处理后的新副本,其中所有函数属性都被移除。\n * 基本类型(string, number, boolean, null, undefined)将原样返回。\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function stripFunctions<T>(value: T, seen = new WeakMap<object, any>()): T {\n if (typeof value === 'function') return undefined as T\n if (value === null || typeof value !== 'object') return value\n\n if (\n value instanceof Date ||\n value instanceof RegExp ||\n value instanceof Map ||\n value instanceof Set ||\n ArrayBuffer.isView(value) ||\n value instanceof ArrayBuffer\n ) {\n return value\n }\n\n if (seen.has(value as object)) {\n return seen.get(value as object)\n }\n\n if (Array.isArray(value)) {\n const out: unknown[] = []\n seen.set(value as object, out)\n for (const item of value) {\n out.push(stripFunctions(item, seen))\n }\n return out as T\n }\n\n if (!isPlainObject(value)) {\n return value\n }\n\n const out: Record<string, unknown> = {}\n seen.set(value as object, out)\n\n for (const [key, item] of Object.entries(value)) {\n if (typeof item === 'function') continue\n const next = stripFunctions(item, seen)\n if (next !== undefined) out[key] = next\n }\n\n return out as T\n}\n\n/**\n * 序列号错误对象 为 BizError\n */\nexport function serializeError(err: unknown): BizError {\n if (!(err instanceof Error)) {\n return {\n name: 'UnknownError',\n message: getErrorMessage(err),\n }\n }\n\n return {\n name: err.name,\n message: err.message,\n stack: err.stack,\n cause: 'cause' in err && err.cause ? serializeError(err.cause) : undefined,\n }\n}\n","import type { BizResult, BizError } from '../types/biz-result.js'\nimport { serializeError } from './serialize.js'\n\n/**\n * 是否为业务结果(序列化后)\n */\nexport function isBizResult<T = unknown>(result: unknown): result is BizResult<T> {\n return (\n result != null &&\n typeof result === 'object' &&\n 'success' in result &&\n typeof result.success === 'boolean' &&\n 'msg' in result &&\n typeof result.msg === 'string'\n )\n}\n\n/**\n * 执行异步函数,自动捕获异常并转换为 BizResult 对象\n * @param runFn 执行方法\n */\nexport const execBiz = async <T>(runFn: () => T | Promise<T>): Promise<BizResult<Awaited<T>>> => {\n try {\n return {\n success: true,\n msg: '操作成功',\n data: await runFn(),\n }\n } catch (e) {\n return {\n success: false,\n msg: '操作失败',\n error: serializeError(e),\n }\n }\n}\n\n/**\n * 解包 BizResult<T> 对象为 Promise<T>,非 BizResult 对象原样返回。\n */\nexport async function unwrapBizResult<T>(result: BizResult<T>): Promise<T>\nexport async function unwrapBizResult(result: unknown): Promise<unknown>\nexport async function unwrapBizResult<T>(result: BizResult<T> | unknown): Promise<T | unknown> {\n if (isBizResult<T>(result)) {\n if (result.success) {\n return result.data as T\n }\n\n if (result.error) {\n throw bizErrorToError(result.error)\n }\n\n throw new Error(result.msg)\n } else {\n return result\n }\n}\n\nexport function bizErrorToError(bizError: BizError) {\n return Object.assign(new Error(), bizError)\n}\n","/**\n * 合并多个 Uint8Array 为一个新的 Uint8Array。\n *\n * 会分配一个新的连续内存块,并按顺序复制所有数据。\n *\n * @param chunks 待合并的数据块\n * @returns 合并后的 Uint8Array\n */\nexport function concatUint8Arrays(chunks: readonly Uint8Array[]): Uint8Array {\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0)\n\n const result = new Uint8Array(totalLength)\n\n let offset = 0\n for (const chunk of chunks) {\n result.set(chunk, offset)\n offset += chunk.length\n }\n\n return result\n}\n","/**\n * 用于指定 `fetch` 响应体的解析方式。\n * 对应 `Response` 对象的不同解析方法(`.json()`、`.text()` 等)。\n */\nexport type ResponseBodyFormat =\n | 'json' // 解析为 JSON 对象\n | 'text' // 解析为原始字符串\n | 'blob' // 解析为 Blob 对象(适用于二进制文件,如图片、压缩包)\n | 'arrayBuffer' // 解析为 ArrayBuffer(适用于底层二进制操作)\n | 'formData' // 解析为 FormData 对象(适用于处理 multipart/form-data 响应)\n\n/**\n * 创建响应错误\n */\nexport function createResponseError(response: Response) {\n return new Error(`HTTP ${response.status}: ${response.statusText}`)\n}\n\n/**\n * 使用指定的响应解析格式发起 fetch 请求\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function fetchWithFormat<T = any>(\n url: string,\n format: ResponseBodyFormat,\n init?: RequestInit,\n): Promise<T> {\n const response = await fetch(url, init)\n if (!response.ok) {\n throw createResponseError(response)\n }\n switch (format) {\n case 'json':\n return (await response.json()) as T\n case 'text':\n return (await response.text()) as T\n case 'blob':\n return (await response.blob()) as T\n case 'arrayBuffer':\n return (await response.arrayBuffer()) as T\n case 'formData':\n return (await response.formData()) as T\n default:\n return (await response.text()) as T\n }\n}\n","/**\n * 随机运行参数\n * @param fns\n * @param maxCount 最多执行次数(1 ~ fns.length)\n */\nexport function runRandomFunctions(fns: Array<() => void>, maxCount?: number): void {\n maxCount = maxCount ?? fns.length\n const count = Math.floor(Math.random() * maxCount) + 1\n\n const shuffled = [...fns]\n for (let i = shuffled.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1))\n ;[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]\n }\n\n const selected = shuffled.slice(0, count)\n\n for (const fn of selected) {\n fn()\n }\n}\n\n/**\n * 将数字范围按批次处理,每个批次调用一次异步函数\n *\n * @param start - 起始值(包含)\n * @param end - 结束值(包含)\n * @param batchSize - 每批最大元素个数\n * @param processor - 处理单批数字数组的异步函数\n *\n * @example\n * // 分批处理 1..10,每批最多 3 个数字\n * await processRangeInBatches(1, 10, 3, async (batch) => {\n * console.log(batch) // 输出: [1,2,3], [4,5,6], [7,8,9], [10]\n * })\n */\nexport async function processRangeInBatches(\n start: number,\n end: number,\n batchSize: number,\n processor: (batch: number[]) => Promise<void>,\n): Promise<void> {\n for (let current = start; current <= end; current += batchSize) {\n const remaining = end - current + 1\n const actualSize = Math.min(batchSize, remaining)\n const batch = Array.from({ length: actualSize }, (_, idx) => current + idx)\n\n await processor(batch)\n }\n}\n\n/**\n * 动态调用\n * @param root 对象\n * @param path 调用路径\n * @param args 参数\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function dynamicCall<T = any>(root: any, path: string, ...args: any[]): T {\n const segments = path.split('.')\n let context = root\n let i = 0\n for (; i < segments.length - 1; i++) {\n context = context[segments[i]]\n if (context == null) {\n throw new Error(`Path '${segments.slice(0, i + 1).join('.')}' is null/undefined`)\n }\n }\n const fn = context[segments[i]]\n if (typeof fn !== 'function') {\n throw new Error(`'${path}' is not a function`)\n }\n return fn.apply(context, args)\n}\n","import { fetchWithFormat } from './fetch.js'\n\n/** github 仓库信息 */\nexport interface GitHubRepo {\n /** 仓库所有者(用户或组织名) */\n owner: string\n /** 仓库名称 */\n repo: string\n}\n\n/** github 仓库分支信息 */\nexport type GitHubRepoBranch = GitHubRepo & {\n /** 分支名称 */\n branch: string\n}\n\n/** github 仓库文件信息 */\nexport type GitHubRepoFile = GitHubRepoBranch & {\n /** 文件路径 */\n filePath: string\n}\n\n/**\n * 从 url 解析 github 仓库信息\n * @param repositoryUrl 仓库 URL(支持带有git+前缀、具体文件路径)\n */\nexport function parseGithubRepoUrl(repositoryUrl: string): GitHubRepoBranch {\n // 去掉 git+ 前缀\n repositoryUrl = repositoryUrl.replace(/^git\\+/, '')\n\n const regexBase = /^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git|\\/)?$/\n const regexFile = /^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+)\\/blob\\/([^/]+)$/\n\n // 情况 1:git clone 地址 或 repo 根路径\n const m1 = repositoryUrl.match(regexBase)\n if (m1) {\n return {\n owner: m1[1],\n repo: m1[2],\n branch: 'main', // 默认分支 main\n }\n }\n\n // 情况 2:具体文件路径\n const m2 = repositoryUrl.match(regexFile)\n if (m2) {\n return {\n owner: m2[1],\n repo: m2[2],\n branch: m2[3],\n }\n }\n\n throw new Error('解析插件仓库URL失败')\n}\n\n/**\n * 解析 github 仓库文件的原始内容的 url\n */\nexport function parseGithubRawUrl(gitHubRepoFile: GitHubRepoFile) {\n const { owner, repo, branch, filePath } = gitHubRepoFile\n return `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${filePath}`\n}\n\n/**\n * 获取 github 仓库文件的 json 内容并解析为对象 T\n * @param gitHubRepoFile\n */\nexport async function getGithubRawJson<O>(gitHubRepoFile: GitHubRepoFile): Promise<O> {\n return await fetchWithFormat(parseGithubRawUrl(gitHubRepoFile), 'json')\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { type LogLevel, logLevels, type Logger, type LogFn, LogLevelMap } from '../types/logger.js'\n\nconst noop = () => {}\nconst ignoredProps = new Set(['then', 'catch', 'finally', 'toJSON', 'toString', 'valueOf'])\n\nexport function isLogLevel<K extends LogLevel = LogLevel>(level: string): level is K {\n return logLevels.indexOf(level as LogLevel) > -1\n}\n\n/**\n * 创建一个带级别过滤的 logger 代理。\n *\n * @template K - 支持的日志级别类型\n * @param getLogLevel - 获取当前配置级别的函数,仅在创建代理时执行\n * @param logWriter - 执行实际日志输出的函数(如 console.log)\n * @returns 返回一个可直接调用的 logger 实例\n */\nexport function createLogger<K extends LogLevel = LogLevel>(\n getLogLevel: K | (() => K | Promise<K>),\n logWriter: (logLevel: K, ...data: any[]) => void,\n): Logger<K> {\n let cachedLevel: K = 'info' as K\n\n const syncConfig = async () => {\n try {\n const configLevel = (typeof getLogLevel === 'function' ? await getLogLevel() : getLogLevel).toLowerCase()\n if (isLogLevel<K>(configLevel)) {\n cachedLevel = configLevel\n } else {\n cachedLevel = 'info' as K\n }\n } catch {\n cachedLevel = 'info' as K\n }\n }\n\n syncConfig().then()\n\n return new Proxy(noop, {\n get(target, logLevel) {\n if (typeof logLevel !== 'string' || ignoredProps.has(logLevel)) return undefined\n if (!isLogLevel<K>(logLevel)) return undefined\n\n return new Proxy(noop, {\n apply(_target: () => void, _thisArg: any, args: any[]): void {\n if (!args) return\n\n if (LogLevelMap[logLevel] < LogLevelMap[cachedLevel]) {\n return\n }\n\n logWriter(logLevel, ...args)\n },\n }) as LogFn\n },\n }) as unknown as Logger<K>\n}\n","/**\n * 忽略 undefined 值的字段\n * @param obj\n */\nexport const omitUndefined = <T extends object>(obj: T): Partial<T> =>\n Object.fromEntries(Object.entries(obj).filter(([_, v]) => v !== undefined)) as Partial<T>\n","/**\n * 为 Promise 添加超时控制\n * @param promise - 原始异步任务\n * @param timeout - 超时时间(毫秒)\n * @returns 若原 Promise 在超时前完成,则返回其结果;否则抛出超时错误\n * @throws {Error} 超时后抛出 'Timeout' 错误\n */\nexport async function withTimeout<T>(promise: Promise<T>, timeout: number): Promise<T> {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error('Timeout'))\n }, timeout)\n }),\n ])\n}\n\n/**\n * 带重试机制的异步函数执行器\n * @param fn - 返回 Promise 的异步函数\n * @param retries - 最大重试次数(默认 3)\n * @param delay - 重试间隔毫秒(默认 1000)\n * @returns Promise<T>\n */\nexport async function withRetry<T>(fn: () => Promise<T>, retries: number = 3, delay: number = 1000): Promise<T> {\n for (let i = 0; i < retries; i++) {\n try {\n return await fn()\n } catch (error) {\n if (i === retries - 1) throw error\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n }\n throw new Error('Unreachable')\n}\n","/**\n * 数组洗牌\n */\nexport function shuffle<T>(arr: T[]): T[] {\n const clone = arr.slice()\n for (let i = clone.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1))\n ;[clone[i], clone[j]] = [clone[j], clone[i]]\n }\n return clone\n}\n\n/**\n * 获取 [min, max] 的随机整数\n */\nexport function randomInt(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min\n}\n\n/**\n * 获取 [min, max) 的随机浮点数\n */\nexport function randomFloat(min: number, max: number): number {\n return Math.random() * (max - min) + min\n}\n\n/**\n * 从数组中随机取若干项,不可重复\n */\nexport function sample<T>(arr: T[], count: number): T[] {\n return shuffle(arr).slice(0, count)\n}\n\n/**\n * 从数组中随机取若干项,可重复\n */\nexport function sampleWithReplacement<T>(arr: T[], count: number): T[] {\n const result: T[] = []\n for (let i = 0; i < count; i++) {\n const index = randomInt(0, arr.length - 1)\n result.push(arr[index])\n }\n return result\n}\n\n/**\n * 从数组中获取随机项\n */\nexport function sampleOne<T>(arr: T[]): T {\n return arr[randomInt(0, arr.length - 1)]\n}\n\n/**\n * 获取 1~n 的随机数\n */\nexport function random1ToN(n: number): number {\n return randomInt(1, n)\n}\n","import { createAbortError } from './error.js'\n\n/**\n * 支持取消的 sleep\n * @param ms 延迟毫秒数\n * @param signal 取消信号\n */\nexport function sleep(ms: number, signal?: AbortSignal) {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) return reject(createAbortError())\n\n const timer = setTimeout(() => {\n cleanup()\n resolve()\n }, ms)\n\n const onAbort = () => {\n clearTimeout(timer)\n cleanup()\n reject(createAbortError())\n }\n\n const cleanup = () => {\n signal?.removeEventListener('abort', onAbort)\n }\n\n signal?.addEventListener('abort', onAbort)\n })\n}\n\n/**\n * 支持取消的随机 sleep\n * @param minMS 最小延迟毫秒数\n * @param maxMS 最大延迟毫秒数\n * @param signal 取消信号\n */\nexport function sleepRandom(minMS: number, maxMS: number, signal?: AbortSignal) {\n const ms = Math.random() * (maxMS - minMS) + minMS\n return sleep(ms, signal)\n}\n","/**\n * 格式化日期\n */\nexport function formatDate(date: Date, pattern: 'date' | 'time' | 'datetime'): string {\n const d = !isNaN(date.getTime()) ? date : new Date()\n const year = d.getFullYear()\n const month = String(d.getMonth() + 1).padStart(2, '0')\n const day = String(d.getDate()).padStart(2, '0')\n const hours = String(d.getHours()).padStart(2, '0')\n const minutes = String(d.getMinutes()).padStart(2, '0')\n const seconds = String(d.getSeconds()).padStart(2, '0')\n\n if (pattern === 'date') return `${year}-${month}-${day}`\n if (pattern === 'time') return `${hours}:${minutes}:${seconds}`\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`\n}\n\n/**\n * 格式化时间为 2020-02-02 20:20:20 的字符串\n * @param date 需要格式化的时间,为空则获取当前时间\n */\nexport function getFormattedDateTime(date?: Date): string {\n return formatDate(date ?? new Date(), 'datetime')\n}\n\n/**\n * 格式化时间为 2020-02-02 的字符串\n * @param date 需要格式化的时间,为空则获取当前时间\n */\nexport function getFormattedDate(date?: Date): string {\n return formatDate(date ?? new Date(), 'date')\n}\n\n/**\n * 格式化时间为 20:20:20 的字符串\n * @param date 需要格式化的时间,为空则获取当前时间\n */\nexport function getFormattedTime(date?: Date): string {\n return formatDate(date ?? new Date(), 'time')\n}\n\n/**\n * 格式化时间戳。可自动判断 10/13 位时间戳\n * @param timestamp\n */\nexport function formatTime(timestamp: number | string | Date | undefined): string {\n if (typeof timestamp === 'undefined') return ''\n if (timestamp instanceof Date) {\n return timestamp.toLocaleString()\n } else {\n const num = typeof timestamp === 'string' ? Number(timestamp) : timestamp\n if (isNaN(num)) return ''\n\n return new Date(num < 1e12 ? num * 1000 : num).toLocaleString()\n }\n}\n","/** URL query 中必须编码的保留字符 (RFC 3986) */\nexport const invalidCharRegex = /[!'()*]/g\n\n/** 查询参数 */\nexport type QueryParams = Record<string, string | number | boolean | null | undefined>\n\n/**\n * 已解析的 url\n */\nexport interface ParsedUrl {\n baseUrl: string\n searchParams: URLSearchParams\n}\n\n/**\n * 判断字符串是否为有效的 HTTP/HTTPS URL\n * @param path - 待检测的字符串\n */\nexport function isHttpUrl(path: string) {\n try {\n const url = new URL(path)\n return url.protocol === 'http:' || url.protocol === 'https:'\n } catch {\n return false\n }\n}\n\n/**\n * 解析 url\n * @param url\n */\nexport function parseUrl(url: string): ParsedUrl {\n try {\n const { origin, pathname, searchParams } = new URL(url)\n return {\n baseUrl: origin + pathname,\n searchParams,\n }\n } catch {\n throw new Error('Invalid URL')\n }\n}\n\n/**\n * 编码 URL 参数\n * @param params 查询参数\n * @param keepEmptyValues 保留 null/undefined的值(空字符串)\n */\nexport function encodeURLParams(params: QueryParams, keepEmptyValues: boolean = false) {\n return (\n Object.keys(params)\n // 排序\n .sort()\n // 过滤\n .filter((key) => {\n return keepEmptyValues || params[key] != null\n })\n // 编码 key 和 value\n .map((key) => {\n const raw = params[key] ?? ''\n return `${encodeURIComponent(key)}=${encodeURIComponent(String(raw))}`\n })\n // 拼接\n .join('&')\n )\n}\n\n/**\n *\n */\n/**\n * 合并查询参数\n * @param urlSearchParams url解析后查询参数\n * @param params 单独传的查询参数\n */\nexport function mergeQueryParams(urlSearchParams: URLSearchParams, params?: QueryParams): QueryParams {\n let mergedParams: QueryParams = {}\n if (urlSearchParams.size > 0) {\n // 合并url里的查询参数\n urlSearchParams.forEach((value, key) => {\n mergedParams[key] = value\n })\n }\n // 处理单独传的查询参数对象\n if (params) {\n mergedParams = { ...mergedParams, ...params }\n }\n return mergedParams\n}\n","/**\n * 格式化后的单位数据(如文件大小)\n */\nexport interface FormattedUnitSize {\n /** 换算后该单位的数值(未四舍五入) */\n size: number\n /** 单位名称,如 'MB' */\n unit: string\n /** 显示文本:数值四舍五入保留两位小数 + 单位,如 '1.50 MB' */\n text: string\n}\n\n/**\n * 按进制自动格式化单位\n * @param value 数值\n * @param base 进制(1024 / 1000)\n * @param units 单位列表\n * @param invalidText 无效值返回文本\n */\nexport function formatUnitSize(value: number, base: number, units: string[], invalidText = ''): FormattedUnitSize {\n if (!Number.isFinite(value)) {\n return { size: 0, unit: '', text: invalidText }\n }\n\n let size = value\n let unitIndex = 0\n\n while (size >= base && unitIndex < units.length - 1) {\n size /= base\n unitIndex++\n }\n\n return {\n size,\n unit: units[unitIndex],\n text: `${size.toFixed(2).replace(/\\.?0+$/, '')} ${units[unitIndex]}`,\n }\n}\n"],"mappings":"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","names":["core_exports","__export","CommonError","LogLevelMap","bizErrorToError","checkAbortSignal","chunk","concatUint8Arrays","convertToCommonError","createAbortError","createLogger","createResponseError","dynamicCall","encodeURLParams","execBiz","fetchWithFormat","formatDate","formatTime","formatUnitSize","getErrorMessage","getFormattedDate","getFormattedDateTime","getFormattedTime","getGithubRawJson","inArray","invalidCharRegex","isBizResult","isCanceledError","isCommonError","isEmptyArr","isHttpUrl","isLogLevel","isObject","isPlainObject","logLevels","mergeQueryParams","omitUndefined","parseGithubRawUrl","parseGithubRepoUrl","parseUrl","processRangeInBatches","random1ToN","randomFloat","randomInt","runRandomFunctions","sample","sampleOne","sampleWithReplacement","serializeError","shuffle","sleep","sleepRandom","stripFunctions","unwrapBizResult","withRetry","withTimeout","__toCommonJS","isCanceledError","err","createAbortError","msg","error","isCommonError","CommonError","prefixError","prefix","convertToCommonError","getErrorMessage","CommonError","message","cause","getErrorMessage","LogLevelMap","logLevels","checkAbortSignal","abortSignal","createAbortError","isEmptyArr","data","chunk","arr","size","result","i","inArray","value","array","isPlainObject","value","proto","isObject","key","stripFunctions","value","seen","out","item","isPlainObject","key","next","serializeError","err","getErrorMessage","isBizResult","result","execBiz","runFn","serializeError","unwrapBizResult","bizErrorToError","bizError","concatUint8Arrays","chunks","totalLength","sum","chunk","result","offset","createResponseError","response","fetchWithFormat","url","format","init","runRandomFunctions","fns","maxCount","count","shuffled","j","selected","fn","processRangeInBatches","start","end","batchSize","processor","current","remaining","actualSize","batch","_","idx","dynamicCall","root","path","args","segments","context","parseGithubRepoUrl","repositoryUrl","regexBase","regexFile","m1","m2","parseGithubRawUrl","gitHubRepoFile","owner","repo","branch","filePath","getGithubRawJson","fetchWithFormat","noop","ignoredProps","isLogLevel","level","logLevels","createLogger","getLogLevel","logWriter","cachedLevel","configLevel","target","logLevel","_target","_thisArg","args","LogLevelMap","omitUndefined","obj","_","v","withTimeout","promise","timeout","_","reject","withRetry","fn","retries","delay","i","error","resolve","shuffle","arr","clone","i","j","randomInt","min","max","randomFloat","sample","count","sampleWithReplacement","result","index","sampleOne","random1ToN","n","sleep","ms","signal","resolve","reject","createAbortError","timer","cleanup","onAbort","sleepRandom","minMS","maxMS","formatDate","date","pattern","d","year","month","day","hours","minutes","seconds","getFormattedDateTime","getFormattedDate","getFormattedTime","formatTime","timestamp","num","invalidCharRegex","isHttpUrl","path","url","parseUrl","origin","pathname","searchParams","encodeURLParams","params","keepEmptyValues","key","raw","mergeQueryParams","urlSearchParams","mergedParams","value","formatUnitSize","value","base","units","invalidText","size","unitIndex"]}
package/dist/core.d.cts CHANGED
@@ -158,6 +158,16 @@ declare function unwrapBizResult<T>(result: BizResult<T>): Promise<T>;
158
158
  declare function unwrapBizResult(result: unknown): Promise<unknown>;
159
159
  declare function bizErrorToError(bizError: BizError): Error & BizError;
160
160
 
161
+ /**
162
+ * 合并多个 Uint8Array 为一个新的 Uint8Array。
163
+ *
164
+ * 会分配一个新的连续内存块,并按顺序复制所有数据。
165
+ *
166
+ * @param chunks 待合并的数据块
167
+ * @returns 合并后的 Uint8Array
168
+ */
169
+ declare function concatUint8Arrays(chunks: readonly Uint8Array[]): Uint8Array;
170
+
161
171
  /**
162
172
  * 是否为取消操作的错误
163
173
  */
@@ -264,7 +274,7 @@ declare function isLogLevel<K extends LogLevel = LogLevel>(level: string): level
264
274
  * @param logWriter - 执行实际日志输出的函数(如 console.log)
265
275
  * @returns 返回一个可直接调用的 logger 实例
266
276
  */
267
- declare function createLogger<K extends LogLevel = LogLevel>(getLogLevel: () => K | Promise<K>, logWriter: (logLevel: K, ...data: any[]) => void): Logger<K>;
277
+ declare function createLogger<K extends LogLevel = LogLevel>(getLogLevel: K | (() => K | Promise<K>), logWriter: (logLevel: K, ...data: any[]) => void): Logger<K>;
268
278
 
269
279
  /**
270
280
  * 忽略 undefined 值的字段
@@ -358,7 +368,7 @@ declare function formatDate(date: Date, pattern: 'date' | 'time' | 'datetime'):
358
368
  */
359
369
  declare function getFormattedDateTime(date?: Date): string;
360
370
  /**
361
- * 格式化时间为 2020-02-02 20:20:20 的字符串
371
+ * 格式化时间为 2020-02-02 的字符串
362
372
  * @param date 需要格式化的时间,为空则获取当前时间
363
373
  */
364
374
  declare function getFormattedDate(date?: Date): string;
@@ -439,4 +449,4 @@ interface FormattedUnitSize {
439
449
  */
440
450
  declare function formatUnitSize(value: number, base: number, units: string[], invalidText?: string): FormattedUnitSize;
441
451
 
442
- export { type AnyFn, type BizError, type BizResult, CommonError, type ExactlyOne, type ExtractGetterProperties, type FormattedUnitSize, type FunctionKeys, type GitHubRepo, type GitHubRepoBranch, type GitHubRepoFile, type KeysMatching, type LogFn, type LogLevel, LogLevelMap, type Logger, type MaxLengthArray, type MethodKeys, type MethodParams, type MethodReturn, type ObjectWithKeys, type ParsedUrl, type PhysicalPoint, type PhysicalRect, type QueryParams, type RequireAtLeastOne, type ResponseBodyFormat, bizErrorToError, checkAbortSignal, chunk, convertToCommonError, createAbortError, createLogger, createResponseError, dynamicCall, encodeURLParams, execBiz, fetchWithFormat, formatDate, formatTime, formatUnitSize, getErrorMessage, getFormattedDate, getFormattedDateTime, getFormattedTime, getGithubRawJson, inArray, invalidCharRegex, isBizResult, isCanceledError, isCommonError, isEmptyArr, isHttpUrl, isLogLevel, isObject, isPlainObject, logLevels, mergeQueryParams, omitUndefined, parseGithubRawUrl, parseGithubRepoUrl, parseUrl, processRangeInBatches, random1ToN, randomFloat, randomInt, runRandomFunctions, sample, sampleOne, sampleWithReplacement, serializeError, shuffle, sleep, sleepRandom, stripFunctions, unwrapBizResult, withRetry, withTimeout };
452
+ export { type AnyFn, type BizError, type BizResult, CommonError, type ExactlyOne, type ExtractGetterProperties, type FormattedUnitSize, type FunctionKeys, type GitHubRepo, type GitHubRepoBranch, type GitHubRepoFile, type KeysMatching, type LogFn, type LogLevel, LogLevelMap, type Logger, type MaxLengthArray, type MethodKeys, type MethodParams, type MethodReturn, type ObjectWithKeys, type ParsedUrl, type PhysicalPoint, type PhysicalRect, type QueryParams, type RequireAtLeastOne, type ResponseBodyFormat, bizErrorToError, checkAbortSignal, chunk, concatUint8Arrays, convertToCommonError, createAbortError, createLogger, createResponseError, dynamicCall, encodeURLParams, execBiz, fetchWithFormat, formatDate, formatTime, formatUnitSize, getErrorMessage, getFormattedDate, getFormattedDateTime, getFormattedTime, getGithubRawJson, inArray, invalidCharRegex, isBizResult, isCanceledError, isCommonError, isEmptyArr, isHttpUrl, isLogLevel, isObject, isPlainObject, logLevels, mergeQueryParams, omitUndefined, parseGithubRawUrl, parseGithubRepoUrl, parseUrl, processRangeInBatches, random1ToN, randomFloat, randomInt, runRandomFunctions, sample, sampleOne, sampleWithReplacement, serializeError, shuffle, sleep, sleepRandom, stripFunctions, unwrapBizResult, withRetry, withTimeout };
package/dist/core.d.ts CHANGED
@@ -158,6 +158,16 @@ declare function unwrapBizResult<T>(result: BizResult<T>): Promise<T>;
158
158
  declare function unwrapBizResult(result: unknown): Promise<unknown>;
159
159
  declare function bizErrorToError(bizError: BizError): Error & BizError;
160
160
 
161
+ /**
162
+ * 合并多个 Uint8Array 为一个新的 Uint8Array。
163
+ *
164
+ * 会分配一个新的连续内存块,并按顺序复制所有数据。
165
+ *
166
+ * @param chunks 待合并的数据块
167
+ * @returns 合并后的 Uint8Array
168
+ */
169
+ declare function concatUint8Arrays(chunks: readonly Uint8Array[]): Uint8Array;
170
+
161
171
  /**
162
172
  * 是否为取消操作的错误
163
173
  */
@@ -264,7 +274,7 @@ declare function isLogLevel<K extends LogLevel = LogLevel>(level: string): level
264
274
  * @param logWriter - 执行实际日志输出的函数(如 console.log)
265
275
  * @returns 返回一个可直接调用的 logger 实例
266
276
  */
267
- declare function createLogger<K extends LogLevel = LogLevel>(getLogLevel: () => K | Promise<K>, logWriter: (logLevel: K, ...data: any[]) => void): Logger<K>;
277
+ declare function createLogger<K extends LogLevel = LogLevel>(getLogLevel: K | (() => K | Promise<K>), logWriter: (logLevel: K, ...data: any[]) => void): Logger<K>;
268
278
 
269
279
  /**
270
280
  * 忽略 undefined 值的字段
@@ -358,7 +368,7 @@ declare function formatDate(date: Date, pattern: 'date' | 'time' | 'datetime'):
358
368
  */
359
369
  declare function getFormattedDateTime(date?: Date): string;
360
370
  /**
361
- * 格式化时间为 2020-02-02 20:20:20 的字符串
371
+ * 格式化时间为 2020-02-02 的字符串
362
372
  * @param date 需要格式化的时间,为空则获取当前时间
363
373
  */
364
374
  declare function getFormattedDate(date?: Date): string;
@@ -439,4 +449,4 @@ interface FormattedUnitSize {
439
449
  */
440
450
  declare function formatUnitSize(value: number, base: number, units: string[], invalidText?: string): FormattedUnitSize;
441
451
 
442
- export { type AnyFn, type BizError, type BizResult, CommonError, type ExactlyOne, type ExtractGetterProperties, type FormattedUnitSize, type FunctionKeys, type GitHubRepo, type GitHubRepoBranch, type GitHubRepoFile, type KeysMatching, type LogFn, type LogLevel, LogLevelMap, type Logger, type MaxLengthArray, type MethodKeys, type MethodParams, type MethodReturn, type ObjectWithKeys, type ParsedUrl, type PhysicalPoint, type PhysicalRect, type QueryParams, type RequireAtLeastOne, type ResponseBodyFormat, bizErrorToError, checkAbortSignal, chunk, convertToCommonError, createAbortError, createLogger, createResponseError, dynamicCall, encodeURLParams, execBiz, fetchWithFormat, formatDate, formatTime, formatUnitSize, getErrorMessage, getFormattedDate, getFormattedDateTime, getFormattedTime, getGithubRawJson, inArray, invalidCharRegex, isBizResult, isCanceledError, isCommonError, isEmptyArr, isHttpUrl, isLogLevel, isObject, isPlainObject, logLevels, mergeQueryParams, omitUndefined, parseGithubRawUrl, parseGithubRepoUrl, parseUrl, processRangeInBatches, random1ToN, randomFloat, randomInt, runRandomFunctions, sample, sampleOne, sampleWithReplacement, serializeError, shuffle, sleep, sleepRandom, stripFunctions, unwrapBizResult, withRetry, withTimeout };
452
+ export { type AnyFn, type BizError, type BizResult, CommonError, type ExactlyOne, type ExtractGetterProperties, type FormattedUnitSize, type FunctionKeys, type GitHubRepo, type GitHubRepoBranch, type GitHubRepoFile, type KeysMatching, type LogFn, type LogLevel, LogLevelMap, type Logger, type MaxLengthArray, type MethodKeys, type MethodParams, type MethodReturn, type ObjectWithKeys, type ParsedUrl, type PhysicalPoint, type PhysicalRect, type QueryParams, type RequireAtLeastOne, type ResponseBodyFormat, bizErrorToError, checkAbortSignal, chunk, concatUint8Arrays, convertToCommonError, createAbortError, createLogger, createResponseError, dynamicCall, encodeURLParams, execBiz, fetchWithFormat, formatDate, formatTime, formatUnitSize, getErrorMessage, getFormattedDate, getFormattedDateTime, getFormattedTime, getGithubRawJson, inArray, invalidCharRegex, isBizResult, isCanceledError, isCommonError, isEmptyArr, isHttpUrl, isLogLevel, isObject, isPlainObject, logLevels, mergeQueryParams, omitUndefined, parseGithubRawUrl, parseGithubRepoUrl, parseUrl, processRangeInBatches, random1ToN, randomFloat, randomInt, runRandomFunctions, sample, sampleOne, sampleWithReplacement, serializeError, shuffle, sleep, sleepRandom, stripFunctions, unwrapBizResult, withRetry, withTimeout };
package/dist/core.js CHANGED
@@ -1,2 +1,2 @@
1
- function F(t){return t instanceof Error?t.name==="AbortError"||t.name==="CanceledError"||"code"in t&&t.code==="ERR_CANCELED":!1}function u(t){let e=new Error(t??"\u64CD\u4F5C\u5DF2\u53D6\u6D88");return e.name="AbortError",e}function L(t){return t instanceof m||t instanceof Error&&t.name==="CommonError"}function R(t,e){return e&&(t.message=`${e} ${t.message}`),t}function O(t,e){return L(t)?R(t,e):new m(`${e} ${f(t)}`,t)}function f(t){return typeof t=="string"?t:t instanceof Error||t&&typeof t=="object"&&"message"in t&&typeof t.message=="string"?t.message:String(t)??"\u672A\u77E5\u9519\u8BEF"}var m=class extends Error{constructor(e,r){super(e),r!==void 0&&(this.cause=r instanceof Error?r:new Error(f(r))),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}toString(){return`${this.name}: ${this.message}${this.cause?` (caused by ${this.cause})`:""}`}};var p={trace:0,debug:1,info:2,warn:3,error:4},d=["trace","debug","info","warn","error"];function G(t){if(t?.aborted)throw u()}function N(t){return Array.isArray(t)&&t.length===0}function v(t,e){if(!Number.isInteger(e)||e<1)throw new Error("size \u5FC5\u987B\u662F\u6B63\u6574\u6570");let r=[];for(let n=0;n<t.length;n+=e)r.push(t.slice(n,n+e));return r}function I(t,e){return e.includes(t)}function b(t){if(t===null||typeof t!="object")return!1;let e=Object.getPrototypeOf(t);return e===Object.prototype||e===null}function W(t,e){return t===null||typeof t!="object"||Array.isArray(t)?!1:e!==void 0?e in t:!0}function h(t,e=new WeakMap){if(typeof t=="function")return;if(t===null||typeof t!="object"||t instanceof Date||t instanceof RegExp||t instanceof Map||t instanceof Set||ArrayBuffer.isView(t)||t instanceof ArrayBuffer)return t;if(e.has(t))return e.get(t);if(Array.isArray(t)){let n=[];e.set(t,n);for(let o of t)n.push(h(o,e));return n}if(!b(t))return t;let r={};e.set(t,r);for(let[n,o]of Object.entries(t)){if(typeof o=="function")continue;let i=h(o,e);i!==void 0&&(r[n]=i)}return r}function g(t){return t instanceof Error?{name:t.name,message:t.message,stack:t.stack,cause:"cause"in t&&t.cause?g(t.cause):void 0}:{name:"UnknownError",message:f(t)}}function P(t){return t!=null&&typeof t=="object"&&"success"in t&&typeof t.success=="boolean"&&"msg"in t&&typeof t.msg=="string"}var X=async t=>{try{return{success:!0,msg:"\u64CD\u4F5C\u6210\u529F",data:await t()}}catch(e){return{success:!1,msg:"\u64CD\u4F5C\u5931\u8D25",error:g(e)}}};async function Z(t){if(P(t)){if(t.success)return t.data;throw t.error?$(t.error):new Error(t.msg)}else return t}function $(t){return Object.assign(new Error,t)}function j(t){return new Error(`HTTP ${t.status}: ${t.statusText}`)}async function y(t,e,r){let n=await fetch(t,r);if(!n.ok)throw j(n);switch(e){case"json":return await n.json();case"text":return await n.text();case"blob":return await n.blob();case"arrayBuffer":return await n.arrayBuffer();case"formData":return await n.formData();default:return await n.text()}}function rt(t,e){e=e??t.length;let r=Math.floor(Math.random()*e)+1,n=[...t];for(let i=n.length-1;i>0;i--){let s=Math.floor(Math.random()*(i+1));[n[i],n[s]]=[n[s],n[i]]}let o=n.slice(0,r);for(let i of o)i()}async function nt(t,e,r,n){for(let o=t;o<=e;o+=r){let i=e-o+1,s=Math.min(r,i),c=Array.from({length:s},(a,E)=>o+E);await n(c)}}function ot(t,e,...r){let n=e.split("."),o=t,i=0;for(;i<n.length-1;i++)if(o=o[n[i]],o==null)throw new Error(`Path '${n.slice(0,i+1).join(".")}' is null/undefined`);let s=o[n[i]];if(typeof s!="function")throw new Error(`'${e}' is not a function`);return s.apply(o,r)}function at(t){t=t.replace(/^git\+/,"");let e=/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git|\/)?$/,r=/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)$/,n=t.match(e);if(n)return{owner:n[1],repo:n[2],branch:"main"};let o=t.match(r);if(o)return{owner:o[1],repo:o[2],branch:o[3]};throw new Error("\u89E3\u6790\u63D2\u4EF6\u4ED3\u5E93URL\u5931\u8D25")}function k(t){let{owner:e,repo:r,branch:n,filePath:o}=t;return`https://raw.githubusercontent.com/${e}/${r}/${n}/${o}`}async function ct(t){return JSON.parse(await y(k(t),"json"))}var w=()=>{},S=new Set(["then","catch","finally","toJSON","toString","valueOf"]);function T(t){return d.indexOf(t)>-1}function mt(t,e){let r="info";return(async()=>{try{let o=(await t()).toLowerCase();T(o)?r=o:r="info"}catch{r="info"}})().then(),new Proxy(w,{get(o,i){if(!(typeof i!="string"||S.has(i))&&T(i))return new Proxy(w,{apply(s,c,a){a&&(p[i]<p[r]||e(i,...a))}})}})}var gt=t=>Object.fromEntries(Object.entries(t).filter(([e,r])=>r!==void 0));async function xt(t,e){return await Promise.race([t,new Promise((r,n)=>{setTimeout(()=>{n(new Error("Timeout"))},e)})])}async function dt(t,e=3,r=1e3){for(let n=0;n<e;n++)try{return await t()}catch(o){if(n===e-1)throw o;await new Promise(i=>setTimeout(i,r))}throw new Error("Unreachable")}function B(t){let e=t.slice();for(let r=e.length-1;r>0;r--){let n=Math.floor(Math.random()*(r+1));[e[r],e[n]]=[e[n],e[r]]}return e}function l(t,e){return Math.floor(Math.random()*(e-t+1))+t}function ht(t,e){return Math.random()*(e-t)+t}function yt(t,e){return B(t).slice(0,e)}function wt(t,e){let r=[];for(let n=0;n<e;n++){let o=l(0,t.length-1);r.push(t[o])}return r}function Tt(t){return t[l(0,t.length-1)]}function Et(t){return l(1,t)}function A(t,e){return new Promise((r,n)=>{if(e?.aborted)return n(u());let o=setTimeout(()=>{s(),r()},t),i=()=>{clearTimeout(o),s(),n(u())},s=()=>{e?.removeEventListener("abort",i)};e?.addEventListener("abort",i)})}function Pt(t,e,r){let n=Math.random()*(e-t)+t;return A(n,r)}function x(t,e){let r=isNaN(t.getTime())?new Date:t,n=r.getFullYear(),o=String(r.getMonth()+1).padStart(2,"0"),i=String(r.getDate()).padStart(2,"0"),s=String(r.getHours()).padStart(2,"0"),c=String(r.getMinutes()).padStart(2,"0"),a=String(r.getSeconds()).padStart(2,"0");return e==="date"?`${n}-${o}-${i}`:e==="time"?`${s}:${c}:${a}`:`${n}-${o}-${i} ${s}:${c}:${a}`}function jt(t){return x(t??new Date,"datetime")}function kt(t){return x(t??new Date,"date")}function St(t){return x(t??new Date,"time")}function Bt(t){if(typeof t>"u")return"";if(t instanceof Date)return t.toLocaleString();{let e=typeof t=="string"?Number(t):t;return isNaN(e)?"":new Date(e<1e12?e*1e3:e).toLocaleString()}}var zt=/[!'()*]/g;function Ft(t){try{let e=new URL(t);return e.protocol==="http:"||e.protocol==="https:"}catch{return!1}}function Ot(t){try{let{origin:e,pathname:r,searchParams:n}=new URL(t);return{baseUrl:e+r,searchParams:n}}catch{throw new Error("Invalid URL")}}function Kt(t,e=!1){return Object.keys(t).sort().filter(r=>e||t[r]!=null).map(r=>{let n=t[r]??"";return`${encodeURIComponent(r)}=${encodeURIComponent(String(n))}`}).join("&")}function Dt(t,e){let r={};return t.size>0&&t.forEach((n,o)=>{r[o]=n}),e&&(r={...r,...e}),r}function Ut(t,e,r,n=""){if(!Number.isFinite(t))return{size:0,unit:"",text:n};let o=t,i=0;for(;o>=e&&i<r.length-1;)o/=e,i++;return{size:o,unit:r[i],text:`${o.toFixed(2).replace(/\.?0+$/,"")} ${r[i]}`}}export{m as CommonError,p as LogLevelMap,$ as bizErrorToError,G as checkAbortSignal,v as chunk,O as convertToCommonError,u as createAbortError,mt as createLogger,j as createResponseError,ot as dynamicCall,Kt as encodeURLParams,X as execBiz,y as fetchWithFormat,x as formatDate,Bt as formatTime,Ut as formatUnitSize,f as getErrorMessage,kt as getFormattedDate,jt as getFormattedDateTime,St as getFormattedTime,ct as getGithubRawJson,I as inArray,zt as invalidCharRegex,P as isBizResult,F as isCanceledError,L as isCommonError,N as isEmptyArr,Ft as isHttpUrl,T as isLogLevel,W as isObject,b as isPlainObject,d as logLevels,Dt as mergeQueryParams,gt as omitUndefined,k as parseGithubRawUrl,at as parseGithubRepoUrl,Ot as parseUrl,nt as processRangeInBatches,Et as random1ToN,ht as randomFloat,l as randomInt,rt as runRandomFunctions,yt as sample,Tt as sampleOne,wt as sampleWithReplacement,g as serializeError,B as shuffle,A as sleep,Pt as sleepRandom,h as stripFunctions,Z as unwrapBizResult,dt as withRetry,xt as withTimeout};
1
+ function U(t){return t instanceof Error?t.name==="AbortError"||t.name==="CanceledError"||"code"in t&&t.code==="ERR_CANCELED":!1}function u(t){let e=new Error(t??"\u64CD\u4F5C\u5DF2\u53D6\u6D88");return e.name="AbortError",e}function L(t){return t instanceof m||t instanceof Error&&t.name==="CommonError"}function R(t,e){return e&&(t.message=`${e} ${t.message}`),t}function F(t,e){return L(t)?R(t,e):new m(`${e} ${f(t)}`,t)}function f(t){return typeof t=="string"?t:t instanceof Error||t&&typeof t=="object"&&"message"in t&&typeof t.message=="string"?t.message:String(t)??"\u672A\u77E5\u9519\u8BEF"}var m=class extends Error{constructor(e,r){super(e),r!==void 0&&(this.cause=r instanceof Error?r:new Error(f(r))),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}toString(){return`${this.name}: ${this.message}${this.cause?` (caused by ${this.cause})`:""}`}};var p={trace:0,debug:1,info:2,warn:3,error:4},d=["trace","debug","info","warn","error"];function G(t){if(t?.aborted)throw u()}function N(t){return Array.isArray(t)&&t.length===0}function v(t,e){if(!Number.isInteger(e)||e<1)throw new Error("size \u5FC5\u987B\u662F\u6B63\u6574\u6570");let r=[];for(let n=0;n<t.length;n+=e)r.push(t.slice(n,n+e));return r}function I(t,e){return e.includes(t)}function b(t){if(t===null||typeof t!="object")return!1;let e=Object.getPrototypeOf(t);return e===Object.prototype||e===null}function W(t,e){return t===null||typeof t!="object"||Array.isArray(t)?!1:e!==void 0?e in t:!0}function h(t,e=new WeakMap){if(typeof t=="function")return;if(t===null||typeof t!="object"||t instanceof Date||t instanceof RegExp||t instanceof Map||t instanceof Set||ArrayBuffer.isView(t)||t instanceof ArrayBuffer)return t;if(e.has(t))return e.get(t);if(Array.isArray(t)){let n=[];e.set(t,n);for(let o of t)n.push(h(o,e));return n}if(!b(t))return t;let r={};e.set(t,r);for(let[n,o]of Object.entries(t)){if(typeof o=="function")continue;let i=h(o,e);i!==void 0&&(r[n]=i)}return r}function g(t){return t instanceof Error?{name:t.name,message:t.message,stack:t.stack,cause:"cause"in t&&t.cause?g(t.cause):void 0}:{name:"UnknownError",message:f(t)}}function P(t){return t!=null&&typeof t=="object"&&"success"in t&&typeof t.success=="boolean"&&"msg"in t&&typeof t.msg=="string"}var X=async t=>{try{return{success:!0,msg:"\u64CD\u4F5C\u6210\u529F",data:await t()}}catch(e){return{success:!1,msg:"\u64CD\u4F5C\u5931\u8D25",error:g(e)}}};async function Z(t){if(P(t)){if(t.success)return t.data;throw t.error?$(t.error):new Error(t.msg)}else return t}function $(t){return Object.assign(new Error,t)}function et(t){let e=t.reduce((o,i)=>o+i.length,0),r=new Uint8Array(e),n=0;for(let o of t)r.set(o,n),n+=o.length;return r}function j(t){return new Error(`HTTP ${t.status}: ${t.statusText}`)}async function y(t,e,r){let n=await fetch(t,r);if(!n.ok)throw j(n);switch(e){case"json":return await n.json();case"text":return await n.text();case"blob":return await n.blob();case"arrayBuffer":return await n.arrayBuffer();case"formData":return await n.formData();default:return await n.text()}}function ot(t,e){e=e??t.length;let r=Math.floor(Math.random()*e)+1,n=[...t];for(let i=n.length-1;i>0;i--){let s=Math.floor(Math.random()*(i+1));[n[i],n[s]]=[n[s],n[i]]}let o=n.slice(0,r);for(let i of o)i()}async function it(t,e,r,n){for(let o=t;o<=e;o+=r){let i=e-o+1,s=Math.min(r,i),c=Array.from({length:s},(a,E)=>o+E);await n(c)}}function st(t,e,...r){let n=e.split("."),o=t,i=0;for(;i<n.length-1;i++)if(o=o[n[i]],o==null)throw new Error(`Path '${n.slice(0,i+1).join(".")}' is null/undefined`);let s=o[n[i]];if(typeof s!="function")throw new Error(`'${e}' is not a function`);return s.apply(o,r)}function ut(t){t=t.replace(/^git\+/,"");let e=/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git|\/)?$/,r=/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)$/,n=t.match(e);if(n)return{owner:n[1],repo:n[2],branch:"main"};let o=t.match(r);if(o)return{owner:o[1],repo:o[2],branch:o[3]};throw new Error("\u89E3\u6790\u63D2\u4EF6\u4ED3\u5E93URL\u5931\u8D25")}function A(t){let{owner:e,repo:r,branch:n,filePath:o}=t;return`https://raw.githubusercontent.com/${e}/${r}/${n}/${o}`}async function ft(t){return await y(A(t),"json")}var w=()=>{},k=new Set(["then","catch","finally","toJSON","toString","valueOf"]);function T(t){return d.indexOf(t)>-1}function gt(t,e){let r="info";return(async()=>{try{let o=(typeof t=="function"?await t():t).toLowerCase();T(o)?r=o:r="info"}catch{r="info"}})().then(),new Proxy(w,{get(o,i){if(!(typeof i!="string"||k.has(i))&&T(i))return new Proxy(w,{apply(s,c,a){a&&(p[i]<p[r]||e(i,...a))}})}})}var xt=t=>Object.fromEntries(Object.entries(t).filter(([e,r])=>r!==void 0));async function bt(t,e){return await Promise.race([t,new Promise((r,n)=>{setTimeout(()=>{n(new Error("Timeout"))},e)})])}async function ht(t,e=3,r=1e3){for(let n=0;n<e;n++)try{return await t()}catch(o){if(n===e-1)throw o;await new Promise(i=>setTimeout(i,r))}throw new Error("Unreachable")}function S(t){let e=t.slice();for(let r=e.length-1;r>0;r--){let n=Math.floor(Math.random()*(r+1));[e[r],e[n]]=[e[n],e[r]]}return e}function l(t,e){return Math.floor(Math.random()*(e-t+1))+t}function wt(t,e){return Math.random()*(e-t)+t}function Tt(t,e){return S(t).slice(0,e)}function Et(t,e){let r=[];for(let n=0;n<e;n++){let o=l(0,t.length-1);r.push(t[o])}return r}function Lt(t){return t[l(0,t.length-1)]}function Rt(t){return l(1,t)}function B(t,e){return new Promise((r,n)=>{if(e?.aborted)return n(u());let o=setTimeout(()=>{s(),r()},t),i=()=>{clearTimeout(o),s(),n(u())},s=()=>{e?.removeEventListener("abort",i)};e?.addEventListener("abort",i)})}function jt(t,e,r){let n=Math.random()*(e-t)+t;return B(n,r)}function x(t,e){let r=isNaN(t.getTime())?new Date:t,n=r.getFullYear(),o=String(r.getMonth()+1).padStart(2,"0"),i=String(r.getDate()).padStart(2,"0"),s=String(r.getHours()).padStart(2,"0"),c=String(r.getMinutes()).padStart(2,"0"),a=String(r.getSeconds()).padStart(2,"0");return e==="date"?`${n}-${o}-${i}`:e==="time"?`${s}:${c}:${a}`:`${n}-${o}-${i} ${s}:${c}:${a}`}function kt(t){return x(t??new Date,"datetime")}function St(t){return x(t??new Date,"date")}function Bt(t){return x(t??new Date,"time")}function zt(t){if(typeof t>"u")return"";if(t instanceof Date)return t.toLocaleString();{let e=typeof t=="string"?Number(t):t;return isNaN(e)?"":new Date(e<1e12?e*1e3:e).toLocaleString()}}var Ft=/[!'()*]/g;function Kt(t){try{let e=new URL(t);return e.protocol==="http:"||e.protocol==="https:"}catch{return!1}}function Ot(t){try{let{origin:e,pathname:r,searchParams:n}=new URL(t);return{baseUrl:e+r,searchParams:n}}catch{throw new Error("Invalid URL")}}function Dt(t,e=!1){return Object.keys(t).sort().filter(r=>e||t[r]!=null).map(r=>{let n=t[r]??"";return`${encodeURIComponent(r)}=${encodeURIComponent(String(n))}`}).join("&")}function Mt(t,e){let r={};return t.size>0&&t.forEach((n,o)=>{r[o]=n}),e&&(r={...r,...e}),r}function Gt(t,e,r,n=""){if(!Number.isFinite(t))return{size:0,unit:"",text:n};let o=t,i=0;for(;o>=e&&i<r.length-1;)o/=e,i++;return{size:o,unit:r[i],text:`${o.toFixed(2).replace(/\.?0+$/,"")} ${r[i]}`}}export{m as CommonError,p as LogLevelMap,$ as bizErrorToError,G as checkAbortSignal,v as chunk,et as concatUint8Arrays,F as convertToCommonError,u as createAbortError,gt as createLogger,j as createResponseError,st as dynamicCall,Dt as encodeURLParams,X as execBiz,y as fetchWithFormat,x as formatDate,zt as formatTime,Gt as formatUnitSize,f as getErrorMessage,St as getFormattedDate,kt as getFormattedDateTime,Bt as getFormattedTime,ft as getGithubRawJson,I as inArray,Ft as invalidCharRegex,P as isBizResult,U as isCanceledError,L as isCommonError,N as isEmptyArr,Kt as isHttpUrl,T as isLogLevel,W as isObject,b as isPlainObject,d as logLevels,Mt as mergeQueryParams,xt as omitUndefined,A as parseGithubRawUrl,ut as parseGithubRepoUrl,Ot as parseUrl,it as processRangeInBatches,Rt as random1ToN,wt as randomFloat,l as randomInt,ot as runRandomFunctions,Tt as sample,Lt as sampleOne,Et as sampleWithReplacement,g as serializeError,S as shuffle,B as sleep,jt as sleepRandom,h as stripFunctions,Z as unwrapBizResult,ht as withRetry,bt as withTimeout};
2
2
  //# sourceMappingURL=core.js.map
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/utils/error.ts","../src/core/error/common-error.ts","../src/core/types/logger.ts","../src/core/utils/abort.ts","../src/core/utils/array.ts","../src/core/utils/type.ts","../src/core/utils/serialize.ts","../src/core/utils/biz-result.ts","../src/core/utils/fetch.ts","../src/core/utils/function.ts","../src/core/utils/github.ts","../src/core/utils/logger.ts","../src/core/utils/object.ts","../src/core/utils/promise.ts","../src/core/utils/random.ts","../src/core/utils/sleep.ts","../src/core/utils/time.ts","../src/core/utils/url.ts","../src/core/utils/number/format.ts"],"sourcesContent":["import { CommonError } from '../error/common-error.js'\n\n/**\n * 是否为取消操作的错误\n */\nexport function isCanceledError(err: unknown): err is Error {\n if (!(err instanceof Error)) return false\n\n return err.name === 'AbortError' || err.name === 'CanceledError' || ('code' in err && err.code === 'ERR_CANCELED')\n}\n\n/**\n * 创建取消错误\n * @param msg\n */\nexport function createAbortError(msg?: string): Error {\n const error = new Error(msg ?? '操作已取消')\n error.name = 'AbortError'\n return error\n}\n\n/**\n * 是否为通用错误对象\n */\nexport function isCommonError(error: unknown): error is CommonError {\n return error instanceof CommonError || (error instanceof Error && error.name === 'CommonError')\n}\n\n/**\n * 给错误消息添加前缀(空格隔开)\n */\nfunction prefixError(error: Error, prefix?: string): Error {\n if (!prefix) return error\n\n error.message = `${prefix} ${error.message}`\n return error\n}\n\n/**\n * 转换到通用异常\n */\nexport function convertToCommonError(error: unknown, prefix?: string) {\n if (isCommonError(error)) {\n return prefixError(error, prefix)\n }\n return new CommonError(`${prefix} ${getErrorMessage(error)}`, error)\n}\n\n/**\n * 获取异常信息\n */\nexport function getErrorMessage(error: unknown): string {\n if (typeof error === 'string') {\n return error\n }\n if (error instanceof Error) {\n return error.message\n }\n if (error && typeof error === 'object' && 'message' in error && typeof error.message === 'string') {\n return error.message\n }\n return String(error) ?? '未知错误'\n}\n","import { getErrorMessage } from '../utils/error.js'\n\n/**\n * 通用错误\n */\nexport class CommonError extends Error {\n // 原始错误\n cause?: Error\n\n constructor(message: string, cause?: unknown) {\n super(message)\n\n if (cause !== undefined) {\n this.cause = cause instanceof Error ? cause : new Error(getErrorMessage(cause))\n }\n\n this.name = new.target.name\n Object.setPrototypeOf(this, new.target.prototype)\n }\n\n toString() {\n return `${this.name}: ${this.message}${this.cause ? ` (caused by ${this.cause})` : ''}`\n }\n}\n","export const LogLevelMap = {\n trace: 0,\n debug: 1,\n info: 2,\n warn: 3,\n error: 4,\n} as const\n\nexport type LogLevel = keyof typeof LogLevelMap\n\nexport const logLevels = ['trace', 'debug', 'info', 'warn', 'error'] as LogLevel[]\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type LogFn = (...data: any[]) => void\n\nexport type Logger<K extends LogLevel = LogLevel> = {\n [key in K]: LogFn\n}\n","import { createAbortError } from './error.js'\n\n/**\n * 检查取消信号\n */\nexport function checkAbortSignal(abortSignal?: AbortSignal) {\n if (abortSignal?.aborted) {\n throw createAbortError()\n }\n}\n","/**\n * 是否为空数组\n * @param data\n */\nexport function isEmptyArr(data: unknown) {\n return Array.isArray(data) && data.length === 0\n}\n\n/**\n * 将数组分块为指定大小的多个子数组\n * @param arr 原数组\n * @param size 每个块的长度\n * @example chunk([1,2,3,4,5], 2) => [[1,2],[3,4],[5]]\n */\nexport function chunk<T>(arr: T[], size: number): T[][] {\n if (!Number.isInteger(size) || size < 1) throw new Error('size 必须是正整数')\n const result: T[][] = []\n for (let i = 0; i < arr.length; i += size) {\n result.push(arr.slice(i, i + size))\n }\n return result\n}\n\n/**\n * 判断数组是否存在某些项\n */\nexport function inArray<T>(value: T, array: readonly T[]): boolean {\n return array.includes(value)\n}\n","import type { ObjectWithKeys } from '../types/helpers.js'\n\n/**\n * 判断一个值是否为纯对象\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object') return false\n const proto = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\n/**\n * 包括类实例、普通对象,不包括 数组、null 和原始类型\n */\nexport function isObject<K extends string | symbol>(value: unknown, key?: K): value is ObjectWithKeys<K> {\n if (value === null || typeof value !== 'object') return false\n if (Array.isArray(value)) return false\n if (key !== undefined) {\n return key in value\n }\n return true\n}\n","import { isPlainObject } from './type.js'\nimport { getErrorMessage } from './error.js'\nimport type { BizError } from '../types/biz-result.js'\n\n/**\n * 递归移除对象(或数组)中的所有函数属性,返回一个可安全序列化的副本。\n *\n * @typeParam T - 输入值的类型。\n * @param value - 待处理的值(基本类型、对象、数组等)。\n * @param seen - 内部使用的 WeakMap,用于记录已访问过的对象,防止循环引用。\n * 调用方通常无需传递此参数。\n * @returns 处理后的新副本,其中所有函数属性都被移除。\n * 基本类型(string, number, boolean, null, undefined)将原样返回。\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function stripFunctions<T>(value: T, seen = new WeakMap<object, any>()): T {\n if (typeof value === 'function') return undefined as T\n if (value === null || typeof value !== 'object') return value\n\n if (\n value instanceof Date ||\n value instanceof RegExp ||\n value instanceof Map ||\n value instanceof Set ||\n ArrayBuffer.isView(value) ||\n value instanceof ArrayBuffer\n ) {\n return value\n }\n\n if (seen.has(value as object)) {\n return seen.get(value as object)\n }\n\n if (Array.isArray(value)) {\n const out: unknown[] = []\n seen.set(value as object, out)\n for (const item of value) {\n out.push(stripFunctions(item, seen))\n }\n return out as T\n }\n\n if (!isPlainObject(value)) {\n return value\n }\n\n const out: Record<string, unknown> = {}\n seen.set(value as object, out)\n\n for (const [key, item] of Object.entries(value)) {\n if (typeof item === 'function') continue\n const next = stripFunctions(item, seen)\n if (next !== undefined) out[key] = next\n }\n\n return out as T\n}\n\n/**\n * 序列号错误对象 为 BizError\n */\nexport function serializeError(err: unknown): BizError {\n if (!(err instanceof Error)) {\n return {\n name: 'UnknownError',\n message: getErrorMessage(err),\n }\n }\n\n return {\n name: err.name,\n message: err.message,\n stack: err.stack,\n cause: 'cause' in err && err.cause ? serializeError(err.cause) : undefined,\n }\n}\n","import type { BizResult, BizError } from '../types/biz-result.js'\nimport { serializeError } from './serialize.js'\n\n/**\n * 是否为业务结果(序列化后)\n */\nexport function isBizResult<T = unknown>(result: unknown): result is BizResult<T> {\n return (\n result != null &&\n typeof result === 'object' &&\n 'success' in result &&\n typeof result.success === 'boolean' &&\n 'msg' in result &&\n typeof result.msg === 'string'\n )\n}\n\n/**\n * 执行异步函数,自动捕获异常并转换为 BizResult 对象\n * @param runFn 执行方法\n */\nexport const execBiz = async <T>(runFn: () => T | Promise<T>): Promise<BizResult<Awaited<T>>> => {\n try {\n return {\n success: true,\n msg: '操作成功',\n data: await runFn(),\n }\n } catch (e) {\n return {\n success: false,\n msg: '操作失败',\n error: serializeError(e),\n }\n }\n}\n\n/**\n * 解包 BizResult<T> 对象为 Promise<T>,非 BizResult 对象原样返回。\n */\nexport async function unwrapBizResult<T>(result: BizResult<T>): Promise<T>\nexport async function unwrapBizResult(result: unknown): Promise<unknown>\nexport async function unwrapBizResult<T>(result: BizResult<T> | unknown): Promise<T | unknown> {\n if (isBizResult<T>(result)) {\n if (result.success) {\n return result.data as T\n }\n\n if (result.error) {\n throw bizErrorToError(result.error)\n }\n\n throw new Error(result.msg)\n } else {\n return result\n }\n}\n\nexport function bizErrorToError(bizError: BizError) {\n return Object.assign(new Error(), bizError)\n}\n","/**\n * 用于指定 `fetch` 响应体的解析方式。\n * 对应 `Response` 对象的不同解析方法(`.json()`、`.text()` 等)。\n */\nexport type ResponseBodyFormat =\n | 'json' // 解析为 JSON 对象\n | 'text' // 解析为原始字符串\n | 'blob' // 解析为 Blob 对象(适用于二进制文件,如图片、压缩包)\n | 'arrayBuffer' // 解析为 ArrayBuffer(适用于底层二进制操作)\n | 'formData' // 解析为 FormData 对象(适用于处理 multipart/form-data 响应)\n\n/**\n * 创建响应错误\n */\nexport function createResponseError(response: Response) {\n return new Error(`HTTP ${response.status}: ${response.statusText}`)\n}\n\n/**\n * 使用指定的响应解析格式发起 fetch 请求\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function fetchWithFormat<T = any>(\n url: string,\n format: ResponseBodyFormat,\n init?: RequestInit,\n): Promise<T> {\n const response = await fetch(url, init)\n if (!response.ok) {\n throw createResponseError(response)\n }\n switch (format) {\n case 'json':\n return (await response.json()) as T\n case 'text':\n return (await response.text()) as T\n case 'blob':\n return (await response.blob()) as T\n case 'arrayBuffer':\n return (await response.arrayBuffer()) as T\n case 'formData':\n return (await response.formData()) as T\n default:\n return (await response.text()) as T\n }\n}\n","/**\n * 随机运行参数\n * @param fns\n * @param maxCount 最多执行次数(1 ~ fns.length)\n */\nexport function runRandomFunctions(fns: Array<() => void>, maxCount?: number): void {\n maxCount = maxCount ?? fns.length\n const count = Math.floor(Math.random() * maxCount) + 1\n\n const shuffled = [...fns]\n for (let i = shuffled.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1))\n ;[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]\n }\n\n const selected = shuffled.slice(0, count)\n\n for (const fn of selected) {\n fn()\n }\n}\n\n/**\n * 将数字范围按批次处理,每个批次调用一次异步函数\n *\n * @param start - 起始值(包含)\n * @param end - 结束值(包含)\n * @param batchSize - 每批最大元素个数\n * @param processor - 处理单批数字数组的异步函数\n *\n * @example\n * // 分批处理 1..10,每批最多 3 个数字\n * await processRangeInBatches(1, 10, 3, async (batch) => {\n * console.log(batch) // 输出: [1,2,3], [4,5,6], [7,8,9], [10]\n * })\n */\nexport async function processRangeInBatches(\n start: number,\n end: number,\n batchSize: number,\n processor: (batch: number[]) => Promise<void>,\n): Promise<void> {\n for (let current = start; current <= end; current += batchSize) {\n const remaining = end - current + 1\n const actualSize = Math.min(batchSize, remaining)\n const batch = Array.from({ length: actualSize }, (_, idx) => current + idx)\n\n await processor(batch)\n }\n}\n\n/**\n * 动态调用\n * @param root 对象\n * @param path 调用路径\n * @param args 参数\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function dynamicCall<T = any>(root: any, path: string, ...args: any[]): T {\n const segments = path.split('.')\n let context = root\n let i = 0\n for (; i < segments.length - 1; i++) {\n context = context[segments[i]]\n if (context == null) {\n throw new Error(`Path '${segments.slice(0, i + 1).join('.')}' is null/undefined`)\n }\n }\n const fn = context[segments[i]]\n if (typeof fn !== 'function') {\n throw new Error(`'${path}' is not a function`)\n }\n return fn.apply(context, args)\n}\n","import { fetchWithFormat } from './fetch.js'\n\n/** github 仓库信息 */\nexport interface GitHubRepo {\n /** 仓库所有者(用户或组织名) */\n owner: string\n /** 仓库名称 */\n repo: string\n}\n\n/** github 仓库分支信息 */\nexport type GitHubRepoBranch = GitHubRepo & {\n /** 分支名称 */\n branch: string\n}\n\n/** github 仓库文件信息 */\nexport type GitHubRepoFile = GitHubRepoBranch & {\n /** 文件路径 */\n filePath: string\n}\n\n/**\n * 从 url 解析 github 仓库信息\n * @param repositoryUrl 仓库 URL(支持带有git+前缀、具体文件路径)\n */\nexport function parseGithubRepoUrl(repositoryUrl: string): GitHubRepoBranch {\n // 去掉 git+ 前缀\n repositoryUrl = repositoryUrl.replace(/^git\\+/, '')\n\n const regexBase = /^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git|\\/)?$/\n const regexFile = /^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+)\\/blob\\/([^/]+)$/\n\n // 情况 1:git clone 地址 或 repo 根路径\n const m1 = repositoryUrl.match(regexBase)\n if (m1) {\n return {\n owner: m1[1],\n repo: m1[2],\n branch: 'main', // 默认分支 main\n }\n }\n\n // 情况 2:具体文件路径\n const m2 = repositoryUrl.match(regexFile)\n if (m2) {\n return {\n owner: m2[1],\n repo: m2[2],\n branch: m2[3],\n }\n }\n\n throw new Error('解析插件仓库URL失败')\n}\n\n/**\n * 解析 github 仓库文件的原始内容的 url\n */\nexport function parseGithubRawUrl(gitHubRepoFile: GitHubRepoFile) {\n const { owner, repo, branch, filePath } = gitHubRepoFile\n return `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${filePath}`\n}\n\n/**\n * 获取 github 仓库文件的 json 内容并解析为对象 T\n * @param gitHubRepoFile\n */\nexport async function getGithubRawJson<O>(gitHubRepoFile: GitHubRepoFile): Promise<O> {\n return JSON.parse(await fetchWithFormat(parseGithubRawUrl(gitHubRepoFile), 'json')) as O\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { type LogLevel, logLevels, type Logger, type LogFn, LogLevelMap } from '../types/logger.js'\n\nconst noop = () => {}\nconst ignoredProps = new Set(['then', 'catch', 'finally', 'toJSON', 'toString', 'valueOf'])\n\nexport function isLogLevel<K extends LogLevel = LogLevel>(level: string): level is K {\n return logLevels.indexOf(level as LogLevel) > -1\n}\n\n/**\n * 创建一个带级别过滤的 logger 代理。\n *\n * @template K - 支持的日志级别类型\n * @param getLogLevel - 获取当前配置级别的函数,仅在创建代理时执行\n * @param logWriter - 执行实际日志输出的函数(如 console.log)\n * @returns 返回一个可直接调用的 logger 实例\n */\nexport function createLogger<K extends LogLevel = LogLevel>(\n getLogLevel: () => K | Promise<K>,\n logWriter: (logLevel: K, ...data: any[]) => void,\n): Logger<K> {\n let cachedLevel: K = 'info' as K\n\n const syncConfig = async () => {\n try {\n const configLevel = (await getLogLevel()).toLowerCase()\n if (isLogLevel<K>(configLevel)) {\n cachedLevel = configLevel\n } else {\n cachedLevel = 'info' as K\n }\n } catch {\n cachedLevel = 'info' as K\n }\n }\n\n syncConfig().then()\n\n return new Proxy(noop, {\n get(target, logLevel) {\n if (typeof logLevel !== 'string' || ignoredProps.has(logLevel)) return undefined\n if (!isLogLevel<K>(logLevel)) return undefined\n\n return new Proxy(noop, {\n apply(_target: () => void, _thisArg: any, args: any[]): void {\n if (!args) return\n\n if (LogLevelMap[logLevel] < LogLevelMap[cachedLevel]) {\n return\n }\n\n logWriter(logLevel, ...args)\n },\n }) as LogFn\n },\n }) as unknown as Logger<K>\n}\n","/**\n * 忽略 undefined 值的字段\n * @param obj\n */\nexport const omitUndefined = <T extends object>(obj: T): Partial<T> =>\n Object.fromEntries(Object.entries(obj).filter(([_, v]) => v !== undefined)) as Partial<T>\n","/**\n * 为 Promise 添加超时控制\n * @param promise - 原始异步任务\n * @param timeout - 超时时间(毫秒)\n * @returns 若原 Promise 在超时前完成,则返回其结果;否则抛出超时错误\n * @throws {Error} 超时后抛出 'Timeout' 错误\n */\nexport async function withTimeout<T>(promise: Promise<T>, timeout: number): Promise<T> {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error('Timeout'))\n }, timeout)\n }),\n ])\n}\n\n/**\n * 带重试机制的异步函数执行器\n * @param fn - 返回 Promise 的异步函数\n * @param retries - 最大重试次数(默认 3)\n * @param delay - 重试间隔毫秒(默认 1000)\n * @returns Promise<T>\n */\nexport async function withRetry<T>(fn: () => Promise<T>, retries: number = 3, delay: number = 1000): Promise<T> {\n for (let i = 0; i < retries; i++) {\n try {\n return await fn()\n } catch (error) {\n if (i === retries - 1) throw error\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n }\n throw new Error('Unreachable')\n}\n","/**\n * 数组洗牌\n */\nexport function shuffle<T>(arr: T[]): T[] {\n const clone = arr.slice()\n for (let i = clone.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1))\n ;[clone[i], clone[j]] = [clone[j], clone[i]]\n }\n return clone\n}\n\n/**\n * 获取 [min, max] 的随机整数\n */\nexport function randomInt(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min\n}\n\n/**\n * 获取 [min, max) 的随机浮点数\n */\nexport function randomFloat(min: number, max: number): number {\n return Math.random() * (max - min) + min\n}\n\n/**\n * 从数组中随机取若干项,不可重复\n */\nexport function sample<T>(arr: T[], count: number): T[] {\n return shuffle(arr).slice(0, count)\n}\n\n/**\n * 从数组中随机取若干项,可重复\n */\nexport function sampleWithReplacement<T>(arr: T[], count: number): T[] {\n const result: T[] = []\n for (let i = 0; i < count; i++) {\n const index = randomInt(0, arr.length - 1)\n result.push(arr[index])\n }\n return result\n}\n\n/**\n * 从数组中获取随机项\n */\nexport function sampleOne<T>(arr: T[]): T {\n return arr[randomInt(0, arr.length - 1)]\n}\n\n/**\n * 获取 1~n 的随机数\n */\nexport function random1ToN(n: number): number {\n return randomInt(1, n)\n}\n","import { createAbortError } from './error.js'\n\n/**\n * 支持取消的 sleep\n * @param ms 延迟毫秒数\n * @param signal 取消信号\n */\nexport function sleep(ms: number, signal?: AbortSignal) {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) return reject(createAbortError())\n\n const timer = setTimeout(() => {\n cleanup()\n resolve()\n }, ms)\n\n const onAbort = () => {\n clearTimeout(timer)\n cleanup()\n reject(createAbortError())\n }\n\n const cleanup = () => {\n signal?.removeEventListener('abort', onAbort)\n }\n\n signal?.addEventListener('abort', onAbort)\n })\n}\n\n/**\n * 支持取消的随机 sleep\n * @param minMS 最小延迟毫秒数\n * @param maxMS 最大延迟毫秒数\n * @param signal 取消信号\n */\nexport function sleepRandom(minMS: number, maxMS: number, signal?: AbortSignal) {\n const ms = Math.random() * (maxMS - minMS) + minMS\n return sleep(ms, signal)\n}\n","/**\n * 格式化日期\n */\nexport function formatDate(date: Date, pattern: 'date' | 'time' | 'datetime'): string {\n const d = !isNaN(date.getTime()) ? date : new Date()\n const year = d.getFullYear()\n const month = String(d.getMonth() + 1).padStart(2, '0')\n const day = String(d.getDate()).padStart(2, '0')\n const hours = String(d.getHours()).padStart(2, '0')\n const minutes = String(d.getMinutes()).padStart(2, '0')\n const seconds = String(d.getSeconds()).padStart(2, '0')\n\n if (pattern === 'date') return `${year}-${month}-${day}`\n if (pattern === 'time') return `${hours}:${minutes}:${seconds}`\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`\n}\n\n/**\n * 格式化时间为 2020-02-02 20:20:20 的字符串\n * @param date 需要格式化的时间,为空则获取当前时间\n */\nexport function getFormattedDateTime(date?: Date): string {\n return formatDate(date ?? new Date(), 'datetime')\n}\n\n/**\n * 格式化时间为 2020-02-02 20:20:20 的字符串\n * @param date 需要格式化的时间,为空则获取当前时间\n */\nexport function getFormattedDate(date?: Date): string {\n return formatDate(date ?? new Date(), 'date')\n}\n\n/**\n * 格式化时间为 20:20:20 的字符串\n * @param date 需要格式化的时间,为空则获取当前时间\n */\nexport function getFormattedTime(date?: Date): string {\n return formatDate(date ?? new Date(), 'time')\n}\n\n/**\n * 格式化时间戳。可自动判断 10/13 位时间戳\n * @param timestamp\n */\nexport function formatTime(timestamp: number | string | Date | undefined): string {\n if (typeof timestamp === 'undefined') return ''\n if (timestamp instanceof Date) {\n return timestamp.toLocaleString()\n } else {\n const num = typeof timestamp === 'string' ? Number(timestamp) : timestamp\n if (isNaN(num)) return ''\n\n return new Date(num < 1e12 ? num * 1000 : num).toLocaleString()\n }\n}\n","/** URL query 中必须编码的保留字符 (RFC 3986) */\nexport const invalidCharRegex = /[!'()*]/g\n\n/** 查询参数 */\nexport type QueryParams = Record<string, string | number | boolean | null | undefined>\n\n/**\n * 已解析的 url\n */\nexport interface ParsedUrl {\n baseUrl: string\n searchParams: URLSearchParams\n}\n\n/**\n * 判断字符串是否为有效的 HTTP/HTTPS URL\n * @param path - 待检测的字符串\n */\nexport function isHttpUrl(path: string) {\n try {\n const url = new URL(path)\n return url.protocol === 'http:' || url.protocol === 'https:'\n } catch {\n return false\n }\n}\n\n/**\n * 解析 url\n * @param url\n */\nexport function parseUrl(url: string): ParsedUrl {\n try {\n const { origin, pathname, searchParams } = new URL(url)\n return {\n baseUrl: origin + pathname,\n searchParams,\n }\n } catch {\n throw new Error('Invalid URL')\n }\n}\n\n/**\n * 编码 URL 参数\n * @param params 查询参数\n * @param keepEmptyValues 保留 null/undefined的值(空字符串)\n */\nexport function encodeURLParams(params: QueryParams, keepEmptyValues: boolean = false) {\n return (\n Object.keys(params)\n // 排序\n .sort()\n // 过滤\n .filter((key) => {\n return keepEmptyValues || params[key] != null\n })\n // 编码 key 和 value\n .map((key) => {\n const raw = params[key] ?? ''\n return `${encodeURIComponent(key)}=${encodeURIComponent(String(raw))}`\n })\n // 拼接\n .join('&')\n )\n}\n\n/**\n *\n */\n/**\n * 合并查询参数\n * @param urlSearchParams url解析后查询参数\n * @param params 单独传的查询参数\n */\nexport function mergeQueryParams(urlSearchParams: URLSearchParams, params?: QueryParams): QueryParams {\n let mergedParams: QueryParams = {}\n if (urlSearchParams.size > 0) {\n // 合并url里的查询参数\n urlSearchParams.forEach((value, key) => {\n mergedParams[key] = value\n })\n }\n // 处理单独传的查询参数对象\n if (params) {\n mergedParams = { ...mergedParams, ...params }\n }\n return mergedParams\n}\n","/**\n * 格式化后的单位数据(如文件大小)\n */\nexport interface FormattedUnitSize {\n /** 换算后该单位的数值(未四舍五入) */\n size: number\n /** 单位名称,如 'MB' */\n unit: string\n /** 显示文本:数值四舍五入保留两位小数 + 单位,如 '1.50 MB' */\n text: string\n}\n\n/**\n * 按进制自动格式化单位\n * @param value 数值\n * @param base 进制(1024 / 1000)\n * @param units 单位列表\n * @param invalidText 无效值返回文本\n */\nexport function formatUnitSize(value: number, base: number, units: string[], invalidText = ''): FormattedUnitSize {\n if (!Number.isFinite(value)) {\n return { size: 0, unit: '', text: invalidText }\n }\n\n let size = value\n let unitIndex = 0\n\n while (size >= base && unitIndex < units.length - 1) {\n size /= base\n unitIndex++\n }\n\n return {\n size,\n unit: units[unitIndex],\n text: `${size.toFixed(2).replace(/\\.?0+$/, '')} ${units[unitIndex]}`,\n }\n}\n"],"mappings":"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","names":["isCanceledError","err","createAbortError","msg","error","isCommonError","CommonError","prefixError","prefix","convertToCommonError","getErrorMessage","CommonError","message","cause","getErrorMessage","LogLevelMap","logLevels","checkAbortSignal","abortSignal","createAbortError","isEmptyArr","data","chunk","arr","size","result","i","inArray","value","array","isPlainObject","value","proto","isObject","key","stripFunctions","value","seen","out","item","isPlainObject","key","next","serializeError","err","getErrorMessage","isBizResult","result","execBiz","runFn","serializeError","unwrapBizResult","bizErrorToError","bizError","createResponseError","response","fetchWithFormat","url","format","init","runRandomFunctions","fns","maxCount","count","shuffled","j","selected","fn","processRangeInBatches","start","end","batchSize","processor","current","remaining","actualSize","batch","_","idx","dynamicCall","root","path","args","segments","context","parseGithubRepoUrl","repositoryUrl","regexBase","regexFile","m1","m2","parseGithubRawUrl","gitHubRepoFile","owner","repo","branch","filePath","getGithubRawJson","fetchWithFormat","noop","ignoredProps","isLogLevel","level","logLevels","createLogger","getLogLevel","logWriter","cachedLevel","configLevel","target","logLevel","_target","_thisArg","args","LogLevelMap","omitUndefined","obj","_","v","withTimeout","promise","timeout","_","reject","withRetry","fn","retries","delay","i","error","resolve","shuffle","arr","clone","i","j","randomInt","min","max","randomFloat","sample","count","sampleWithReplacement","result","index","sampleOne","random1ToN","n","sleep","ms","signal","resolve","reject","createAbortError","timer","cleanup","onAbort","sleepRandom","minMS","maxMS","formatDate","date","pattern","d","year","month","day","hours","minutes","seconds","getFormattedDateTime","getFormattedDate","getFormattedTime","formatTime","timestamp","num","invalidCharRegex","isHttpUrl","path","url","parseUrl","origin","pathname","searchParams","encodeURLParams","params","keepEmptyValues","key","raw","mergeQueryParams","urlSearchParams","mergedParams","value","formatUnitSize","value","base","units","invalidText","size","unitIndex"]}
1
+ {"version":3,"sources":["../src/core/utils/error.ts","../src/core/error/common-error.ts","../src/core/types/logger.ts","../src/core/utils/abort.ts","../src/core/utils/array.ts","../src/core/utils/type.ts","../src/core/utils/serialize.ts","../src/core/utils/biz-result.ts","../src/core/utils/bytes.ts","../src/core/utils/fetch.ts","../src/core/utils/function.ts","../src/core/utils/github.ts","../src/core/utils/logger.ts","../src/core/utils/object.ts","../src/core/utils/promise.ts","../src/core/utils/random.ts","../src/core/utils/sleep.ts","../src/core/utils/time.ts","../src/core/utils/url.ts","../src/core/utils/number/format.ts"],"sourcesContent":["import { CommonError } from '../error/common-error.js'\n\n/**\n * 是否为取消操作的错误\n */\nexport function isCanceledError(err: unknown): err is Error {\n if (!(err instanceof Error)) return false\n\n return err.name === 'AbortError' || err.name === 'CanceledError' || ('code' in err && err.code === 'ERR_CANCELED')\n}\n\n/**\n * 创建取消错误\n * @param msg\n */\nexport function createAbortError(msg?: string): Error {\n const error = new Error(msg ?? '操作已取消')\n error.name = 'AbortError'\n return error\n}\n\n/**\n * 是否为通用错误对象\n */\nexport function isCommonError(error: unknown): error is CommonError {\n return error instanceof CommonError || (error instanceof Error && error.name === 'CommonError')\n}\n\n/**\n * 给错误消息添加前缀(空格隔开)\n */\nfunction prefixError(error: Error, prefix?: string): Error {\n if (!prefix) return error\n\n error.message = `${prefix} ${error.message}`\n return error\n}\n\n/**\n * 转换到通用异常\n */\nexport function convertToCommonError(error: unknown, prefix?: string) {\n if (isCommonError(error)) {\n return prefixError(error, prefix)\n }\n return new CommonError(`${prefix} ${getErrorMessage(error)}`, error)\n}\n\n/**\n * 获取异常信息\n */\nexport function getErrorMessage(error: unknown): string {\n if (typeof error === 'string') {\n return error\n }\n if (error instanceof Error) {\n return error.message\n }\n if (error && typeof error === 'object' && 'message' in error && typeof error.message === 'string') {\n return error.message\n }\n return String(error) ?? '未知错误'\n}\n","import { getErrorMessage } from '../utils/error.js'\n\n/**\n * 通用错误\n */\nexport class CommonError extends Error {\n // 原始错误\n cause?: Error\n\n constructor(message: string, cause?: unknown) {\n super(message)\n\n if (cause !== undefined) {\n this.cause = cause instanceof Error ? cause : new Error(getErrorMessage(cause))\n }\n\n this.name = new.target.name\n Object.setPrototypeOf(this, new.target.prototype)\n }\n\n toString() {\n return `${this.name}: ${this.message}${this.cause ? ` (caused by ${this.cause})` : ''}`\n }\n}\n","export const LogLevelMap = {\n trace: 0,\n debug: 1,\n info: 2,\n warn: 3,\n error: 4,\n} as const\n\nexport type LogLevel = keyof typeof LogLevelMap\n\nexport const logLevels = ['trace', 'debug', 'info', 'warn', 'error'] as LogLevel[]\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type LogFn = (...data: any[]) => void\n\nexport type Logger<K extends LogLevel = LogLevel> = {\n [key in K]: LogFn\n}\n","import { createAbortError } from './error.js'\n\n/**\n * 检查取消信号\n */\nexport function checkAbortSignal(abortSignal?: AbortSignal) {\n if (abortSignal?.aborted) {\n throw createAbortError()\n }\n}\n","/**\n * 是否为空数组\n * @param data\n */\nexport function isEmptyArr(data: unknown) {\n return Array.isArray(data) && data.length === 0\n}\n\n/**\n * 将数组分块为指定大小的多个子数组\n * @param arr 原数组\n * @param size 每个块的长度\n * @example chunk([1,2,3,4,5], 2) => [[1,2],[3,4],[5]]\n */\nexport function chunk<T>(arr: T[], size: number): T[][] {\n if (!Number.isInteger(size) || size < 1) throw new Error('size 必须是正整数')\n const result: T[][] = []\n for (let i = 0; i < arr.length; i += size) {\n result.push(arr.slice(i, i + size))\n }\n return result\n}\n\n/**\n * 判断数组是否存在某些项\n */\nexport function inArray<T>(value: T, array: readonly T[]): boolean {\n return array.includes(value)\n}\n","import type { ObjectWithKeys } from '../types/helpers.js'\n\n/**\n * 判断一个值是否为纯对象\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object') return false\n const proto = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\n/**\n * 包括类实例、普通对象,不包括 数组、null 和原始类型\n */\nexport function isObject<K extends string | symbol>(value: unknown, key?: K): value is ObjectWithKeys<K> {\n if (value === null || typeof value !== 'object') return false\n if (Array.isArray(value)) return false\n if (key !== undefined) {\n return key in value\n }\n return true\n}\n","import { isPlainObject } from './type.js'\nimport { getErrorMessage } from './error.js'\nimport type { BizError } from '../types/biz-result.js'\n\n/**\n * 递归移除对象(或数组)中的所有函数属性,返回一个可安全序列化的副本。\n *\n * @typeParam T - 输入值的类型。\n * @param value - 待处理的值(基本类型、对象、数组等)。\n * @param seen - 内部使用的 WeakMap,用于记录已访问过的对象,防止循环引用。\n * 调用方通常无需传递此参数。\n * @returns 处理后的新副本,其中所有函数属性都被移除。\n * 基本类型(string, number, boolean, null, undefined)将原样返回。\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function stripFunctions<T>(value: T, seen = new WeakMap<object, any>()): T {\n if (typeof value === 'function') return undefined as T\n if (value === null || typeof value !== 'object') return value\n\n if (\n value instanceof Date ||\n value instanceof RegExp ||\n value instanceof Map ||\n value instanceof Set ||\n ArrayBuffer.isView(value) ||\n value instanceof ArrayBuffer\n ) {\n return value\n }\n\n if (seen.has(value as object)) {\n return seen.get(value as object)\n }\n\n if (Array.isArray(value)) {\n const out: unknown[] = []\n seen.set(value as object, out)\n for (const item of value) {\n out.push(stripFunctions(item, seen))\n }\n return out as T\n }\n\n if (!isPlainObject(value)) {\n return value\n }\n\n const out: Record<string, unknown> = {}\n seen.set(value as object, out)\n\n for (const [key, item] of Object.entries(value)) {\n if (typeof item === 'function') continue\n const next = stripFunctions(item, seen)\n if (next !== undefined) out[key] = next\n }\n\n return out as T\n}\n\n/**\n * 序列号错误对象 为 BizError\n */\nexport function serializeError(err: unknown): BizError {\n if (!(err instanceof Error)) {\n return {\n name: 'UnknownError',\n message: getErrorMessage(err),\n }\n }\n\n return {\n name: err.name,\n message: err.message,\n stack: err.stack,\n cause: 'cause' in err && err.cause ? serializeError(err.cause) : undefined,\n }\n}\n","import type { BizResult, BizError } from '../types/biz-result.js'\nimport { serializeError } from './serialize.js'\n\n/**\n * 是否为业务结果(序列化后)\n */\nexport function isBizResult<T = unknown>(result: unknown): result is BizResult<T> {\n return (\n result != null &&\n typeof result === 'object' &&\n 'success' in result &&\n typeof result.success === 'boolean' &&\n 'msg' in result &&\n typeof result.msg === 'string'\n )\n}\n\n/**\n * 执行异步函数,自动捕获异常并转换为 BizResult 对象\n * @param runFn 执行方法\n */\nexport const execBiz = async <T>(runFn: () => T | Promise<T>): Promise<BizResult<Awaited<T>>> => {\n try {\n return {\n success: true,\n msg: '操作成功',\n data: await runFn(),\n }\n } catch (e) {\n return {\n success: false,\n msg: '操作失败',\n error: serializeError(e),\n }\n }\n}\n\n/**\n * 解包 BizResult<T> 对象为 Promise<T>,非 BizResult 对象原样返回。\n */\nexport async function unwrapBizResult<T>(result: BizResult<T>): Promise<T>\nexport async function unwrapBizResult(result: unknown): Promise<unknown>\nexport async function unwrapBizResult<T>(result: BizResult<T> | unknown): Promise<T | unknown> {\n if (isBizResult<T>(result)) {\n if (result.success) {\n return result.data as T\n }\n\n if (result.error) {\n throw bizErrorToError(result.error)\n }\n\n throw new Error(result.msg)\n } else {\n return result\n }\n}\n\nexport function bizErrorToError(bizError: BizError) {\n return Object.assign(new Error(), bizError)\n}\n","/**\n * 合并多个 Uint8Array 为一个新的 Uint8Array。\n *\n * 会分配一个新的连续内存块,并按顺序复制所有数据。\n *\n * @param chunks 待合并的数据块\n * @returns 合并后的 Uint8Array\n */\nexport function concatUint8Arrays(chunks: readonly Uint8Array[]): Uint8Array {\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0)\n\n const result = new Uint8Array(totalLength)\n\n let offset = 0\n for (const chunk of chunks) {\n result.set(chunk, offset)\n offset += chunk.length\n }\n\n return result\n}\n","/**\n * 用于指定 `fetch` 响应体的解析方式。\n * 对应 `Response` 对象的不同解析方法(`.json()`、`.text()` 等)。\n */\nexport type ResponseBodyFormat =\n | 'json' // 解析为 JSON 对象\n | 'text' // 解析为原始字符串\n | 'blob' // 解析为 Blob 对象(适用于二进制文件,如图片、压缩包)\n | 'arrayBuffer' // 解析为 ArrayBuffer(适用于底层二进制操作)\n | 'formData' // 解析为 FormData 对象(适用于处理 multipart/form-data 响应)\n\n/**\n * 创建响应错误\n */\nexport function createResponseError(response: Response) {\n return new Error(`HTTP ${response.status}: ${response.statusText}`)\n}\n\n/**\n * 使用指定的响应解析格式发起 fetch 请求\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function fetchWithFormat<T = any>(\n url: string,\n format: ResponseBodyFormat,\n init?: RequestInit,\n): Promise<T> {\n const response = await fetch(url, init)\n if (!response.ok) {\n throw createResponseError(response)\n }\n switch (format) {\n case 'json':\n return (await response.json()) as T\n case 'text':\n return (await response.text()) as T\n case 'blob':\n return (await response.blob()) as T\n case 'arrayBuffer':\n return (await response.arrayBuffer()) as T\n case 'formData':\n return (await response.formData()) as T\n default:\n return (await response.text()) as T\n }\n}\n","/**\n * 随机运行参数\n * @param fns\n * @param maxCount 最多执行次数(1 ~ fns.length)\n */\nexport function runRandomFunctions(fns: Array<() => void>, maxCount?: number): void {\n maxCount = maxCount ?? fns.length\n const count = Math.floor(Math.random() * maxCount) + 1\n\n const shuffled = [...fns]\n for (let i = shuffled.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1))\n ;[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]\n }\n\n const selected = shuffled.slice(0, count)\n\n for (const fn of selected) {\n fn()\n }\n}\n\n/**\n * 将数字范围按批次处理,每个批次调用一次异步函数\n *\n * @param start - 起始值(包含)\n * @param end - 结束值(包含)\n * @param batchSize - 每批最大元素个数\n * @param processor - 处理单批数字数组的异步函数\n *\n * @example\n * // 分批处理 1..10,每批最多 3 个数字\n * await processRangeInBatches(1, 10, 3, async (batch) => {\n * console.log(batch) // 输出: [1,2,3], [4,5,6], [7,8,9], [10]\n * })\n */\nexport async function processRangeInBatches(\n start: number,\n end: number,\n batchSize: number,\n processor: (batch: number[]) => Promise<void>,\n): Promise<void> {\n for (let current = start; current <= end; current += batchSize) {\n const remaining = end - current + 1\n const actualSize = Math.min(batchSize, remaining)\n const batch = Array.from({ length: actualSize }, (_, idx) => current + idx)\n\n await processor(batch)\n }\n}\n\n/**\n * 动态调用\n * @param root 对象\n * @param path 调用路径\n * @param args 参数\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function dynamicCall<T = any>(root: any, path: string, ...args: any[]): T {\n const segments = path.split('.')\n let context = root\n let i = 0\n for (; i < segments.length - 1; i++) {\n context = context[segments[i]]\n if (context == null) {\n throw new Error(`Path '${segments.slice(0, i + 1).join('.')}' is null/undefined`)\n }\n }\n const fn = context[segments[i]]\n if (typeof fn !== 'function') {\n throw new Error(`'${path}' is not a function`)\n }\n return fn.apply(context, args)\n}\n","import { fetchWithFormat } from './fetch.js'\n\n/** github 仓库信息 */\nexport interface GitHubRepo {\n /** 仓库所有者(用户或组织名) */\n owner: string\n /** 仓库名称 */\n repo: string\n}\n\n/** github 仓库分支信息 */\nexport type GitHubRepoBranch = GitHubRepo & {\n /** 分支名称 */\n branch: string\n}\n\n/** github 仓库文件信息 */\nexport type GitHubRepoFile = GitHubRepoBranch & {\n /** 文件路径 */\n filePath: string\n}\n\n/**\n * 从 url 解析 github 仓库信息\n * @param repositoryUrl 仓库 URL(支持带有git+前缀、具体文件路径)\n */\nexport function parseGithubRepoUrl(repositoryUrl: string): GitHubRepoBranch {\n // 去掉 git+ 前缀\n repositoryUrl = repositoryUrl.replace(/^git\\+/, '')\n\n const regexBase = /^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git|\\/)?$/\n const regexFile = /^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+)\\/blob\\/([^/]+)$/\n\n // 情况 1:git clone 地址 或 repo 根路径\n const m1 = repositoryUrl.match(regexBase)\n if (m1) {\n return {\n owner: m1[1],\n repo: m1[2],\n branch: 'main', // 默认分支 main\n }\n }\n\n // 情况 2:具体文件路径\n const m2 = repositoryUrl.match(regexFile)\n if (m2) {\n return {\n owner: m2[1],\n repo: m2[2],\n branch: m2[3],\n }\n }\n\n throw new Error('解析插件仓库URL失败')\n}\n\n/**\n * 解析 github 仓库文件的原始内容的 url\n */\nexport function parseGithubRawUrl(gitHubRepoFile: GitHubRepoFile) {\n const { owner, repo, branch, filePath } = gitHubRepoFile\n return `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${filePath}`\n}\n\n/**\n * 获取 github 仓库文件的 json 内容并解析为对象 T\n * @param gitHubRepoFile\n */\nexport async function getGithubRawJson<O>(gitHubRepoFile: GitHubRepoFile): Promise<O> {\n return await fetchWithFormat(parseGithubRawUrl(gitHubRepoFile), 'json')\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { type LogLevel, logLevels, type Logger, type LogFn, LogLevelMap } from '../types/logger.js'\n\nconst noop = () => {}\nconst ignoredProps = new Set(['then', 'catch', 'finally', 'toJSON', 'toString', 'valueOf'])\n\nexport function isLogLevel<K extends LogLevel = LogLevel>(level: string): level is K {\n return logLevels.indexOf(level as LogLevel) > -1\n}\n\n/**\n * 创建一个带级别过滤的 logger 代理。\n *\n * @template K - 支持的日志级别类型\n * @param getLogLevel - 获取当前配置级别的函数,仅在创建代理时执行\n * @param logWriter - 执行实际日志输出的函数(如 console.log)\n * @returns 返回一个可直接调用的 logger 实例\n */\nexport function createLogger<K extends LogLevel = LogLevel>(\n getLogLevel: K | (() => K | Promise<K>),\n logWriter: (logLevel: K, ...data: any[]) => void,\n): Logger<K> {\n let cachedLevel: K = 'info' as K\n\n const syncConfig = async () => {\n try {\n const configLevel = (typeof getLogLevel === 'function' ? await getLogLevel() : getLogLevel).toLowerCase()\n if (isLogLevel<K>(configLevel)) {\n cachedLevel = configLevel\n } else {\n cachedLevel = 'info' as K\n }\n } catch {\n cachedLevel = 'info' as K\n }\n }\n\n syncConfig().then()\n\n return new Proxy(noop, {\n get(target, logLevel) {\n if (typeof logLevel !== 'string' || ignoredProps.has(logLevel)) return undefined\n if (!isLogLevel<K>(logLevel)) return undefined\n\n return new Proxy(noop, {\n apply(_target: () => void, _thisArg: any, args: any[]): void {\n if (!args) return\n\n if (LogLevelMap[logLevel] < LogLevelMap[cachedLevel]) {\n return\n }\n\n logWriter(logLevel, ...args)\n },\n }) as LogFn\n },\n }) as unknown as Logger<K>\n}\n","/**\n * 忽略 undefined 值的字段\n * @param obj\n */\nexport const omitUndefined = <T extends object>(obj: T): Partial<T> =>\n Object.fromEntries(Object.entries(obj).filter(([_, v]) => v !== undefined)) as Partial<T>\n","/**\n * 为 Promise 添加超时控制\n * @param promise - 原始异步任务\n * @param timeout - 超时时间(毫秒)\n * @returns 若原 Promise 在超时前完成,则返回其结果;否则抛出超时错误\n * @throws {Error} 超时后抛出 'Timeout' 错误\n */\nexport async function withTimeout<T>(promise: Promise<T>, timeout: number): Promise<T> {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error('Timeout'))\n }, timeout)\n }),\n ])\n}\n\n/**\n * 带重试机制的异步函数执行器\n * @param fn - 返回 Promise 的异步函数\n * @param retries - 最大重试次数(默认 3)\n * @param delay - 重试间隔毫秒(默认 1000)\n * @returns Promise<T>\n */\nexport async function withRetry<T>(fn: () => Promise<T>, retries: number = 3, delay: number = 1000): Promise<T> {\n for (let i = 0; i < retries; i++) {\n try {\n return await fn()\n } catch (error) {\n if (i === retries - 1) throw error\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n }\n throw new Error('Unreachable')\n}\n","/**\n * 数组洗牌\n */\nexport function shuffle<T>(arr: T[]): T[] {\n const clone = arr.slice()\n for (let i = clone.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1))\n ;[clone[i], clone[j]] = [clone[j], clone[i]]\n }\n return clone\n}\n\n/**\n * 获取 [min, max] 的随机整数\n */\nexport function randomInt(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min\n}\n\n/**\n * 获取 [min, max) 的随机浮点数\n */\nexport function randomFloat(min: number, max: number): number {\n return Math.random() * (max - min) + min\n}\n\n/**\n * 从数组中随机取若干项,不可重复\n */\nexport function sample<T>(arr: T[], count: number): T[] {\n return shuffle(arr).slice(0, count)\n}\n\n/**\n * 从数组中随机取若干项,可重复\n */\nexport function sampleWithReplacement<T>(arr: T[], count: number): T[] {\n const result: T[] = []\n for (let i = 0; i < count; i++) {\n const index = randomInt(0, arr.length - 1)\n result.push(arr[index])\n }\n return result\n}\n\n/**\n * 从数组中获取随机项\n */\nexport function sampleOne<T>(arr: T[]): T {\n return arr[randomInt(0, arr.length - 1)]\n}\n\n/**\n * 获取 1~n 的随机数\n */\nexport function random1ToN(n: number): number {\n return randomInt(1, n)\n}\n","import { createAbortError } from './error.js'\n\n/**\n * 支持取消的 sleep\n * @param ms 延迟毫秒数\n * @param signal 取消信号\n */\nexport function sleep(ms: number, signal?: AbortSignal) {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) return reject(createAbortError())\n\n const timer = setTimeout(() => {\n cleanup()\n resolve()\n }, ms)\n\n const onAbort = () => {\n clearTimeout(timer)\n cleanup()\n reject(createAbortError())\n }\n\n const cleanup = () => {\n signal?.removeEventListener('abort', onAbort)\n }\n\n signal?.addEventListener('abort', onAbort)\n })\n}\n\n/**\n * 支持取消的随机 sleep\n * @param minMS 最小延迟毫秒数\n * @param maxMS 最大延迟毫秒数\n * @param signal 取消信号\n */\nexport function sleepRandom(minMS: number, maxMS: number, signal?: AbortSignal) {\n const ms = Math.random() * (maxMS - minMS) + minMS\n return sleep(ms, signal)\n}\n","/**\n * 格式化日期\n */\nexport function formatDate(date: Date, pattern: 'date' | 'time' | 'datetime'): string {\n const d = !isNaN(date.getTime()) ? date : new Date()\n const year = d.getFullYear()\n const month = String(d.getMonth() + 1).padStart(2, '0')\n const day = String(d.getDate()).padStart(2, '0')\n const hours = String(d.getHours()).padStart(2, '0')\n const minutes = String(d.getMinutes()).padStart(2, '0')\n const seconds = String(d.getSeconds()).padStart(2, '0')\n\n if (pattern === 'date') return `${year}-${month}-${day}`\n if (pattern === 'time') return `${hours}:${minutes}:${seconds}`\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`\n}\n\n/**\n * 格式化时间为 2020-02-02 20:20:20 的字符串\n * @param date 需要格式化的时间,为空则获取当前时间\n */\nexport function getFormattedDateTime(date?: Date): string {\n return formatDate(date ?? new Date(), 'datetime')\n}\n\n/**\n * 格式化时间为 2020-02-02 的字符串\n * @param date 需要格式化的时间,为空则获取当前时间\n */\nexport function getFormattedDate(date?: Date): string {\n return formatDate(date ?? new Date(), 'date')\n}\n\n/**\n * 格式化时间为 20:20:20 的字符串\n * @param date 需要格式化的时间,为空则获取当前时间\n */\nexport function getFormattedTime(date?: Date): string {\n return formatDate(date ?? new Date(), 'time')\n}\n\n/**\n * 格式化时间戳。可自动判断 10/13 位时间戳\n * @param timestamp\n */\nexport function formatTime(timestamp: number | string | Date | undefined): string {\n if (typeof timestamp === 'undefined') return ''\n if (timestamp instanceof Date) {\n return timestamp.toLocaleString()\n } else {\n const num = typeof timestamp === 'string' ? Number(timestamp) : timestamp\n if (isNaN(num)) return ''\n\n return new Date(num < 1e12 ? num * 1000 : num).toLocaleString()\n }\n}\n","/** URL query 中必须编码的保留字符 (RFC 3986) */\nexport const invalidCharRegex = /[!'()*]/g\n\n/** 查询参数 */\nexport type QueryParams = Record<string, string | number | boolean | null | undefined>\n\n/**\n * 已解析的 url\n */\nexport interface ParsedUrl {\n baseUrl: string\n searchParams: URLSearchParams\n}\n\n/**\n * 判断字符串是否为有效的 HTTP/HTTPS URL\n * @param path - 待检测的字符串\n */\nexport function isHttpUrl(path: string) {\n try {\n const url = new URL(path)\n return url.protocol === 'http:' || url.protocol === 'https:'\n } catch {\n return false\n }\n}\n\n/**\n * 解析 url\n * @param url\n */\nexport function parseUrl(url: string): ParsedUrl {\n try {\n const { origin, pathname, searchParams } = new URL(url)\n return {\n baseUrl: origin + pathname,\n searchParams,\n }\n } catch {\n throw new Error('Invalid URL')\n }\n}\n\n/**\n * 编码 URL 参数\n * @param params 查询参数\n * @param keepEmptyValues 保留 null/undefined的值(空字符串)\n */\nexport function encodeURLParams(params: QueryParams, keepEmptyValues: boolean = false) {\n return (\n Object.keys(params)\n // 排序\n .sort()\n // 过滤\n .filter((key) => {\n return keepEmptyValues || params[key] != null\n })\n // 编码 key 和 value\n .map((key) => {\n const raw = params[key] ?? ''\n return `${encodeURIComponent(key)}=${encodeURIComponent(String(raw))}`\n })\n // 拼接\n .join('&')\n )\n}\n\n/**\n *\n */\n/**\n * 合并查询参数\n * @param urlSearchParams url解析后查询参数\n * @param params 单独传的查询参数\n */\nexport function mergeQueryParams(urlSearchParams: URLSearchParams, params?: QueryParams): QueryParams {\n let mergedParams: QueryParams = {}\n if (urlSearchParams.size > 0) {\n // 合并url里的查询参数\n urlSearchParams.forEach((value, key) => {\n mergedParams[key] = value\n })\n }\n // 处理单独传的查询参数对象\n if (params) {\n mergedParams = { ...mergedParams, ...params }\n }\n return mergedParams\n}\n","/**\n * 格式化后的单位数据(如文件大小)\n */\nexport interface FormattedUnitSize {\n /** 换算后该单位的数值(未四舍五入) */\n size: number\n /** 单位名称,如 'MB' */\n unit: string\n /** 显示文本:数值四舍五入保留两位小数 + 单位,如 '1.50 MB' */\n text: string\n}\n\n/**\n * 按进制自动格式化单位\n * @param value 数值\n * @param base 进制(1024 / 1000)\n * @param units 单位列表\n * @param invalidText 无效值返回文本\n */\nexport function formatUnitSize(value: number, base: number, units: string[], invalidText = ''): FormattedUnitSize {\n if (!Number.isFinite(value)) {\n return { size: 0, unit: '', text: invalidText }\n }\n\n let size = value\n let unitIndex = 0\n\n while (size >= base && unitIndex < units.length - 1) {\n size /= base\n unitIndex++\n }\n\n return {\n size,\n unit: units[unitIndex],\n text: `${size.toFixed(2).replace(/\\.?0+$/, '')} ${units[unitIndex]}`,\n }\n}\n"],"mappings":"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","names":["isCanceledError","err","createAbortError","msg","error","isCommonError","CommonError","prefixError","prefix","convertToCommonError","getErrorMessage","CommonError","message","cause","getErrorMessage","LogLevelMap","logLevels","checkAbortSignal","abortSignal","createAbortError","isEmptyArr","data","chunk","arr","size","result","i","inArray","value","array","isPlainObject","value","proto","isObject","key","stripFunctions","value","seen","out","item","isPlainObject","key","next","serializeError","err","getErrorMessage","isBizResult","result","execBiz","runFn","serializeError","unwrapBizResult","bizErrorToError","bizError","concatUint8Arrays","chunks","totalLength","sum","chunk","result","offset","createResponseError","response","fetchWithFormat","url","format","init","runRandomFunctions","fns","maxCount","count","shuffled","j","selected","fn","processRangeInBatches","start","end","batchSize","processor","current","remaining","actualSize","batch","_","idx","dynamicCall","root","path","args","segments","context","parseGithubRepoUrl","repositoryUrl","regexBase","regexFile","m1","m2","parseGithubRawUrl","gitHubRepoFile","owner","repo","branch","filePath","getGithubRawJson","fetchWithFormat","noop","ignoredProps","isLogLevel","level","logLevels","createLogger","getLogLevel","logWriter","cachedLevel","configLevel","target","logLevel","_target","_thisArg","args","LogLevelMap","omitUndefined","obj","_","v","withTimeout","promise","timeout","_","reject","withRetry","fn","retries","delay","i","error","resolve","shuffle","arr","clone","i","j","randomInt","min","max","randomFloat","sample","count","sampleWithReplacement","result","index","sampleOne","random1ToN","n","sleep","ms","signal","resolve","reject","createAbortError","timer","cleanup","onAbort","sleepRandom","minMS","maxMS","formatDate","date","pattern","d","year","month","day","hours","minutes","seconds","getFormattedDateTime","getFormattedDate","getFormattedTime","formatTime","timestamp","num","invalidCharRegex","isHttpUrl","path","url","parseUrl","origin","pathname","searchParams","encodeURLParams","params","keepEmptyValues","key","raw","mergeQueryParams","urlSearchParams","mergedParams","value","formatUnitSize","value","base","units","invalidText","size","unitIndex"]}
package/dist/dom.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var w=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var k=(e,n)=>{for(var t in n)w(e,t,{get:n[t],enumerable:!0})},H=(e,n,t,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of T(n))!L.call(e,r)&&r!==t&&w(e,r,{get:()=>n[r],enumerable:!(o=E(n,r))||o.enumerable});return e};var I=e=>H(w({},"__esModule",{value:!0}),e);var A={};k(A,{getImageArrayBuffer:()=>b,getImgArrayBufferAfterLoad:()=>Y,getNetworkInfo:()=>p,hexToRgb:()=>P,humanScrollElIntoCenter:()=>B,humanScrollTo:()=>x,mixColor:()=>C,onNetworkChange:()=>N,onVisibilityChange:()=>S,setCssVar:()=>X,waitScrollTo:()=>g,whenImageLoaded:()=>h});module.exports=I(A);var C=(e,n,t,o="srgb",r)=>`color-mix(in ${o}, ${e} ${t}%, ${n} ${r||100-t}%)`,P=e=>{let n=parseInt(e.slice(1,3),16),t=parseInt(e.slice(3,5),16),o=parseInt(e.slice(5,7),16);return{r:n,g:t,b:o}};var X=(e,n)=>{document.documentElement.style.setProperty(e,n)};function h(e){return new Promise((n,t)=>{if(e.dataset.state==="loading"&&(e.src=e.dataset.src),e.complete&&e.naturalWidth>0){n(e);return}let o=()=>{i(),n(e)},r=()=>{i(),t(new Error(`\u56FE\u7247\u52A0\u8F7D\u5931\u8D25: ${e.src}`))},i=()=>{e.removeEventListener("load",o),e.removeEventListener("error",r)};e.addEventListener("load",o),e.addEventListener("error",r)})}async function b(e,n="image/png"){let t=document.createElement("canvas");t.width=e.naturalWidth,t.height=e.naturalHeight;let o=t.getContext("2d");if(!o)throw new Error("\u65E0\u6CD5\u521B\u5EFA Canvas 2D \u4E0A\u4E0B\u6587");return o.drawImage(e,0,0),await(await new Promise((i,a)=>{t.toBlob(s=>s?i(s):a(new Error("toBlob \u5931\u8D25")),n)})).arrayBuffer()}async function Y(e,n){let t=await h(e);return await b(t,n)}function v(e){return e!==null&&typeof e=="object"&&"downlink"in e&&"rtt"in e&&"effectiveType"in e}function p(){if(!navigator.onLine)return"offline";if("connection"in navigator&&v(navigator.connection)){let e=navigator.connection;return{downlink:e.downlink,rtt:e.rtt,effectiveType:e.effectiveType}}else return"online"}function N(e){let n=()=>{e(p())};if("connection"in navigator&&v(navigator.connection)){let t=navigator.connection;return t.addEventListener("change",n),()=>t.removeEventListener("change",n)}else return window.addEventListener("online",n),window.addEventListener("offline",n),()=>{window.removeEventListener("online",n),window.removeEventListener("offline",n)}}function S(e){let n,t;if(typeof document.hidden<"u"?(n="hidden",t="visibilitychange"):"msHidden"in document&&typeof document.msHidden<"u"?(n="msHidden",t="msvisibilitychange"):"webkitHidden"in document&&typeof document.webkitHidden<"u"&&(n="webkitHidden",t="webkitvisibilitychange"),!n||!t)return null;let o=()=>{e(document[n])};return document.addEventListener(t,o),()=>{document.removeEventListener(t,o)}}async function B(e){if(!e)return;let n=e.getBoundingClientRect(),t=document.documentElement,o=document.body,r=window.scrollX||t.scrollLeft||o.scrollLeft,i=window.scrollY||t.scrollTop||o.scrollTop,a=window.innerWidth,s=window.innerHeight,d=n.left+r+n.width/2-a/2,l=n.top+i+n.height/2-s/2,c=Math.max(0,o.scrollWidth-a),u=Math.max(0,o.scrollHeight-s);if(c===0&&u===0)return;let f=c>0?Math.min(Math.max(d,0),c):r,m=u>0?Math.min(Math.max(l,0),u):i,y=Math.abs(window.scrollX-f)>1,M=Math.abs(window.scrollY-m)>1;!y&&!M||await x(f,m)}function g(e,n){return new Promise(t=>{let o=window.scrollX,r=window.scrollY;if(Math.abs(o-e)<1&&Math.abs(r-n)<1){t();return}let i,a=!1,s=()=>{a||(a=!0,window.removeEventListener("scroll",d),i&&clearTimeout(i),t())},d=()=>{i&&clearTimeout(i),i=window.setTimeout(s,50)},l=window.setTimeout(()=>{console.debug("[waitScrollTo] fallback timeout reached"),s()},1e3),c=()=>{s(),clearTimeout(l)},u=()=>{i&&clearTimeout(i),i=window.setTimeout(c,50)};window.addEventListener("scroll",u,{passive:!0}),window.scrollTo({left:e,top:n}),requestAnimationFrame(()=>{let f=window.scrollX,m=window.scrollY;Math.abs(f-e)<1&&Math.abs(m-n)<1&&c()})})}async function x(e,n){return new Promise(t=>{let o=window.scrollX,r=window.scrollY;async function i(){let a=e-o,s=n-r;if(Math.abs(a)<1&&Math.abs(s)<1){window.scrollTo(e,n),t();return}let d=Math.sign(a)*Math.min(Math.max(2,Math.random()*Math.abs(a)*.2),Math.abs(a)),l=Math.sign(s)*Math.min(Math.max(2,Math.random()*Math.abs(s)*.2),Math.abs(s));o+=d,r+=l,await g(o,r);let c=10+Math.random()*20;setTimeout(i,c)}i()})}
1
+ "use strict";var w=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var H=(e,n)=>{for(var t in n)w(e,t,{get:n[t],enumerable:!0})},k=(e,n,t,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let i of L(n))!T.call(e,i)&&i!==t&&w(e,i,{get:()=>n[i],enumerable:!(r=x(n,i))||r.enumerable});return e};var I=e=>k(w({},"__esModule",{value:!0}),e);var N={};H(N,{getImageArrayBuffer:()=>p,getImgArrayBufferAfterLoad:()=>Y,getNetworkInfo:()=>b,hexToRgb:()=>X,humanScrollElIntoCenter:()=>R,humanScrollTo:()=>y,mixColor:()=>P,onNetworkChange:()=>_,onVisibilityChange:()=>O,setCssVar:()=>C,setupDevProxyHook:()=>S,waitScrollTo:()=>v,whenImageLoaded:()=>h});module.exports=I(N);var P=(e,n,t,r="srgb",i)=>`color-mix(in ${r}, ${e} ${t}%, ${n} ${i||100-t}%)`,X=e=>{let n=parseInt(e.slice(1,3),16),t=parseInt(e.slice(3,5),16),r=parseInt(e.slice(5,7),16);return{r:n,g:t,b:r}};var C=(e,n)=>{document.documentElement.style.setProperty(e,n)};function S(e="/proxy?url="){if(window.__DEV_PROXY_HOOKED__)return;let n=o=>/^http?:\/\//.test(o)||/^https?:\/\//.test(o)?`${e}${encodeURIComponent(o)}`:o,t=window.fetch;window.fetch=function(o,s){if(o instanceof Request)return o=new Request(n(o.url),o),t.call(this,o,s);let c=n(o.toString());return t.call(this,c,s)};let r=XMLHttpRequest.prototype.open;XMLHttpRequest.prototype.open=function(o,s,c,a,d){return typeof s=="string"?s=n(s):s=new URL(n(s.href)),r.call(this,o,s,c??!0,a,d)};let i=(o,s)=>{let c=Object.getOwnPropertyDescriptor(o,s);c?.set&&Object.defineProperty(o,s,{configurable:!0,enumerable:c.enumerable,get:c.get,set(a){return c.set.call(this,n(a))}})};i(HTMLImageElement.prototype,"src"),i(HTMLScriptElement.prototype,"src"),i(HTMLLinkElement.prototype,"href"),i(HTMLSourceElement.prototype,"src"),i(HTMLIFrameElement.prototype,"src"),window.__DEV_PROXY_HOOKED__=!0}function h(e){return new Promise((n,t)=>{if(e.dataset.state==="loading"&&(e.src=e.dataset.src),e.complete&&e.naturalWidth>0){n(e);return}let r=()=>{o(),n(e)},i=()=>{o(),t(new Error(`\u56FE\u7247\u52A0\u8F7D\u5931\u8D25: ${e.src}`))},o=()=>{e.removeEventListener("load",r),e.removeEventListener("error",i)};e.addEventListener("load",r),e.addEventListener("error",i)})}async function p(e,n="image/png"){let t=document.createElement("canvas");t.width=e.naturalWidth,t.height=e.naturalHeight;let r=t.getContext("2d");if(!r)throw new Error("\u65E0\u6CD5\u521B\u5EFA Canvas 2D \u4E0A\u4E0B\u6587");return r.drawImage(e,0,0),await(await new Promise((o,s)=>{t.toBlob(c=>c?o(c):s(new Error("toBlob \u5931\u8D25")),n)})).arrayBuffer()}async function Y(e,n){let t=await h(e);return await p(t,n)}function g(e){return e!==null&&typeof e=="object"&&"downlink"in e&&"rtt"in e&&"effectiveType"in e}function b(){if(!navigator.onLine)return"offline";if("connection"in navigator&&g(navigator.connection)){let e=navigator.connection;return{downlink:e.downlink,rtt:e.rtt,effectiveType:e.effectiveType}}else return"online"}function _(e){let n=()=>{e(b())};if("connection"in navigator&&g(navigator.connection)){let t=navigator.connection;return t.addEventListener("change",n),()=>t.removeEventListener("change",n)}else return window.addEventListener("online",n),window.addEventListener("offline",n),()=>{window.removeEventListener("online",n),window.removeEventListener("offline",n)}}function O(e){let n,t;if(typeof document.hidden<"u"?(n="hidden",t="visibilitychange"):"msHidden"in document&&typeof document.msHidden<"u"?(n="msHidden",t="msvisibilitychange"):"webkitHidden"in document&&typeof document.webkitHidden<"u"&&(n="webkitHidden",t="webkitvisibilitychange"),!n||!t)return null;let r=()=>{e(document[n])};return document.addEventListener(t,r),()=>{document.removeEventListener(t,r)}}async function R(e){if(!e)return;let n=e.getBoundingClientRect(),t=document.documentElement,r=document.body,i=window.scrollX||t.scrollLeft||r.scrollLeft,o=window.scrollY||t.scrollTop||r.scrollTop,s=window.innerWidth,c=window.innerHeight,a=n.left+i+n.width/2-s/2,d=n.top+o+n.height/2-c/2,l=Math.max(0,r.scrollWidth-s),u=Math.max(0,r.scrollHeight-c);if(l===0&&u===0)return;let f=l>0?Math.min(Math.max(a,0),l):i,m=u>0?Math.min(Math.max(d,0),u):o,E=Math.abs(window.scrollX-f)>1,M=Math.abs(window.scrollY-m)>1;!E&&!M||await y(f,m)}function v(e,n){return new Promise(t=>{let r=window.scrollX,i=window.scrollY;if(Math.abs(r-e)<1&&Math.abs(i-n)<1){t();return}let o,s=!1,c=()=>{s||(s=!0,window.removeEventListener("scroll",a),o&&clearTimeout(o),t())},a=()=>{o&&clearTimeout(o),o=window.setTimeout(c,50)},d=window.setTimeout(()=>{console.debug("[waitScrollTo] fallback timeout reached"),c()},1e3),l=()=>{c(),clearTimeout(d)},u=()=>{o&&clearTimeout(o),o=window.setTimeout(l,50)};window.addEventListener("scroll",u,{passive:!0}),window.scrollTo({left:e,top:n}),requestAnimationFrame(()=>{let f=window.scrollX,m=window.scrollY;Math.abs(f-e)<1&&Math.abs(m-n)<1&&l()})})}async function y(e,n){return new Promise(t=>{let r=window.scrollX,i=window.scrollY;async function o(){let s=e-r,c=n-i;if(Math.abs(s)<1&&Math.abs(c)<1){window.scrollTo(e,n),t();return}let a=Math.sign(s)*Math.min(Math.max(2,Math.random()*Math.abs(s)*.2),Math.abs(s)),d=Math.sign(c)*Math.min(Math.max(2,Math.random()*Math.abs(c)*.2),Math.abs(c));r+=a,i+=d,await v(r,i);let l=10+Math.random()*20;setTimeout(o,l)}o()})}
2
2
  //# sourceMappingURL=dom.cjs.map
package/dist/dom.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dom/index.ts","../src/dom/utils/color.ts","../src/dom/utils/css.ts","../src/dom/utils/img.ts","../src/dom/utils/network.ts","../src/dom/utils/page.ts","../src/dom/utils/scroll.ts"],"sourcesContent":["export * from \"./utils/color.js\";\nexport * from \"./utils/css.js\";\nexport * from \"./utils/img.js\";\nexport * from \"./utils/network.js\";\nexport * from \"./utils/page.js\";\nexport * from \"./utils/scroll.js\";\n","/**\n * 生成 CSS `color-mix()` 函数的字符串表示,用于动态计算两种颜色的混合结果\n *\n * @param {string} color1 - 参与混合的第一种颜色(支持 CSS 合法颜色值,如 HEX、RGB、HSL 等)\n * @param {string} color2 - 参与混合的第二种颜色\n * @param {number} percentage - 主颜色(color1)在混合中的占比(百分比数值,范围 0-100)\n * @param {'srgb' | 'hsl'} [colorSpace='srgb'] - 色彩空间选项:\n * - `'srgb'`: 标准 RGB 色彩空间(默认)\n * - `'hsl'`: 色相-饱和度-明度色彩空间\n * @param {number} [percentage2] - 可选参数:副颜色(color2)的独立占比。\n * 若未提供,则自动计算为 `100 - percentage`\n * @returns {string} 可直接用于 CSS 的 `color-mix()` 函数字符串(如 `color-mix(in srgb, red 30%, blue 70%)`)\n *\n * @example\n * // 基础用法(自动计算互补占比)\n * mixColor('red', 'blue', 30)\n * // 返回: \"color-mix(in srgb, red 30%, blue 70%)\"\n *\n * @example\n * // 显式指定双占比 + HSL 色彩空间\n * mixColor('#ff0000', '#0000ff', 40, 'hsl', 60)\n * // 返回: \"color-mix(in hsl, #ff0000 40%, #0000ff 60%)\"\n */\nexport const mixColor = (\n color1: string,\n color2: string,\n percentage: number,\n colorSpace: 'srgb' | 'hsl' = 'srgb',\n percentage2?: number,\n): string => {\n return `color-mix(in ${colorSpace}, ${color1} ${percentage}%, ${color2} ${percentage2 ? percentage2 : 100 - percentage}%)`\n}\n\n/**\n * 将十六进制颜色转换为 RGB\n */\nexport const hexToRgb = (hex: string): { r: number; g: number; b: number } => {\n const r = parseInt(hex.slice(1, 3), 16)\n const g = parseInt(hex.slice(3, 5), 16)\n const b = parseInt(hex.slice(5, 7), 16)\n return { r, g, b }\n}\n","/**\n * 设置 html 根元素的 css 变量\n */\nexport const setCssVar = (k: string, v: string) => {\n document.documentElement.style.setProperty(k, v)\n}\n","/**\n * 等待 <img> 加载完成\n */\nexport function whenImageLoaded(img: HTMLImageElement): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n if (img.dataset['state'] === 'loading') {\n img.src = img.dataset['src']!\n }\n\n if (img.complete && img.naturalWidth > 0) {\n resolve(img)\n return\n }\n\n const onLoad = () => {\n cleanup()\n resolve(img)\n }\n\n const onError = () => {\n cleanup()\n reject(new Error(`图片加载失败: ${img.src}`))\n }\n\n const cleanup = () => {\n img.removeEventListener('load', onLoad)\n img.removeEventListener('error', onError)\n }\n\n img.addEventListener('load', onLoad)\n img.addEventListener('error', onError)\n })\n}\n\n/**\n * 从 <img> 元素获取图片字节数据(ArrayBuffer)\n * @param img 已加载的 <img> 元素\n * @param type 图片类型,可选(默认 png)\n */\nexport async function getImageArrayBuffer(img: HTMLImageElement, type: string = 'image/png'): Promise<ArrayBuffer> {\n const canvas = document.createElement('canvas')\n canvas.width = img.naturalWidth\n canvas.height = img.naturalHeight\n const ctx = canvas.getContext('2d')\n if (!ctx) throw new Error('无法创建 Canvas 2D 上下文')\n ctx.drawImage(img, 0, 0)\n\n const blob: Blob = await new Promise((resolve, reject) => {\n canvas.toBlob((b) => (b ? resolve(b) : reject(new Error('toBlob 失败'))), type)\n })\n\n return await blob.arrayBuffer()\n}\n\n/**\n * 等待加载完成并获取字节数据\n */\nexport async function getImgArrayBufferAfterLoad(img: HTMLImageElement, type?: string): Promise<ArrayBuffer> {\n const loaded = await whenImageLoaded(img)\n return await getImageArrayBuffer(loaded, type)\n}\n","/**\n * 网络信息\n */\nexport interface NetworkInfo extends EventTarget {\n // 带宽(估算)\n downlink: number\n // 延迟(估算)\n rtt: number\n // 类型(估算)\n effectiveType: 'slow-2g' | '2g' | '3g' | '4g'\n}\n\n/**\n * 网络状态\n * - 'offline': 无网络\n * - 'online': 在线但不支持 NetworkInformation API\n * - NetworkInformation: 含详细网络信息\n */\nexport type NetworkState = 'offline' | Omit<NetworkInfo, keyof EventTarget> | 'online'\n\nfunction isConnection(obj: unknown): obj is NetworkInfo {\n return obj !== null && typeof obj === 'object' && 'downlink' in obj && 'rtt' in obj && 'effectiveType' in obj\n}\n\n/**\n * 获取网络信息\n */\nexport function getNetworkInfo(): NetworkState {\n if (!navigator.onLine) {\n return 'offline'\n }\n\n if ('connection' in navigator && isConnection(navigator.connection)) {\n // 现代 Web API 直接获取网络连接的信息\n const connection = navigator.connection\n return {\n downlink: connection.downlink,\n rtt: connection.rtt,\n effectiveType: connection.effectiveType,\n }\n } else {\n return 'online'\n }\n}\n\n/**\n * 监听网络状态变化\n * @param listener 监听器\n * @returns 成功监听时返回解绑函数\n */\nexport function onNetworkChange(listener: (info: NetworkState) => void) {\n const handleChange = () => {\n listener(getNetworkInfo())\n }\n\n if ('connection' in navigator && isConnection(navigator.connection)) {\n // 现代 Web API\n const connection = navigator.connection\n connection.addEventListener('change', handleChange)\n return () => connection.removeEventListener('change', handleChange)\n } else {\n window.addEventListener('online', handleChange)\n window.addEventListener('offline', handleChange)\n return () => {\n window.removeEventListener('online', handleChange)\n window.removeEventListener('offline', handleChange)\n }\n }\n}\n","/** 可见性改变的监听器 */\nexport interface VisibilityChangeListener {\n (hidden: boolean): void\n}\n\n/**\n * 监听页面可见性变化(兼容旧的IE/Chrome)\n * @param listener 监听器\n * @returns 成功监听时返回解绑函数\n */\nexport function onVisibilityChange(listener: VisibilityChangeListener) {\n let hiddenPropName: string | undefined = undefined,\n hiddenEventName: string | undefined = undefined\n\n if (typeof document.hidden !== 'undefined') {\n // 现代 Web API\n hiddenPropName = 'hidden'\n hiddenEventName = 'visibilitychange'\n } else if ('msHidden' in document && typeof document.msHidden !== 'undefined') {\n // 旧 IE\n hiddenPropName = 'msHidden'\n hiddenEventName = 'msvisibilitychange'\n } else if ('webkitHidden' in document && typeof document.webkitHidden !== 'undefined') {\n // 旧 Chrome\n hiddenPropName = 'webkitHidden'\n hiddenEventName = 'webkitvisibilitychange'\n }\n\n if (!hiddenPropName || !hiddenEventName) {\n return null\n }\n\n const handler = () => {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n listener(document[hiddenPropName])\n }\n\n document.addEventListener(hiddenEventName, handler)\n\n return () => {\n document.removeEventListener(hiddenEventName, handler)\n }\n}\n","/**\n * 滚动元素到屏幕中心\n * @param el\n */\nexport async function humanScrollElIntoCenter(el: HTMLElement) {\n if (!el) return\n\n const rect = el.getBoundingClientRect()\n const doc = document.documentElement\n const body = document.body\n\n const scrollX = window.scrollX || doc.scrollLeft || body.scrollLeft\n const scrollY = window.scrollY || doc.scrollTop || body.scrollTop\n\n const viewW = window.innerWidth\n const viewH = window.innerHeight\n\n // 目标中心点相对页面的位置\n const targetX = rect.left + scrollX + rect.width / 2 - viewW / 2\n const targetY = rect.top + scrollY + rect.height / 2 - viewH / 2\n\n const maxX = Math.max(0, body.scrollWidth - viewW)\n const maxY = Math.max(0, body.scrollHeight - viewH)\n\n // 页面不需要滚动\n if (maxX === 0 && maxY === 0) return\n\n // 水平滚动:仅在可滚动时\n const newX = maxX > 0 ? Math.min(Math.max(targetX, 0), maxX) : scrollX\n // 垂直滚动\n const newY = maxY > 0 ? Math.min(Math.max(targetY, 0), maxY) : scrollY\n\n // 判断是否真正需要滚动\n const needScrollX = Math.abs(window.scrollX - newX) > 1\n const needScrollY = Math.abs(window.scrollY - newY) > 1\n if (!needScrollX && !needScrollY) return\n\n await humanScrollTo(newX, newY)\n}\n\n/**\n * 等待滚动\n */\nexport function waitScrollTo(targetX: number, targetY: number): Promise<void> {\n return new Promise((resolve) => {\n const currentX = window.scrollX\n const currentY = window.scrollY\n\n // 若无需滚动\n if (Math.abs(currentX - targetX) < 1 && Math.abs(currentY - targetY) < 1) {\n resolve()\n return\n }\n\n let timer: number | undefined\n let finished = false\n\n const cleanup = () => {\n if (finished) return\n finished = true\n window.removeEventListener('scroll', handler)\n if (timer) clearTimeout(timer)\n resolve()\n }\n\n const handler = () => {\n if (timer) clearTimeout(timer)\n // 若 50ms 内无新滚动事件,则视为滚动结束\n timer = window.setTimeout(cleanup, 50)\n }\n\n // 启动兜底超时(比如滚动事件根本不触发)\n const failSafe = window.setTimeout(() => {\n console.debug('[waitScrollTo] fallback timeout reached')\n cleanup()\n }, 1000)\n\n const cleanupWithTimeout = () => {\n cleanup()\n clearTimeout(failSafe)\n }\n\n // 替换 cleanup,确保清理超时器\n const finalHandler = () => {\n if (timer) clearTimeout(timer)\n timer = window.setTimeout(cleanupWithTimeout, 50)\n }\n\n // 注册事件\n window.addEventListener('scroll', finalHandler, { passive: true })\n\n // 立即触发滚动\n window.scrollTo({ left: targetX, top: targetY })\n\n // 有时浏览器同步滚动,不触发 scroll 事件\n requestAnimationFrame(() => {\n const nowX = window.scrollX\n const nowY = window.scrollY\n if (Math.abs(nowX - targetX) < 1 && Math.abs(nowY - targetY) < 1) {\n cleanupWithTimeout()\n }\n })\n })\n}\n\n/**\n * 模拟人类手感滚动到指定位置\n */\nexport async function humanScrollTo(targetX: number, targetY: number): Promise<void> {\n return new Promise<void>((resolve) => {\n let currentX = window.scrollX\n let currentY = window.scrollY\n\n async function step() {\n const dx = targetX - currentX\n const dy = targetY - currentY\n\n // 如果距离足够小,直接跳到目标结束\n if (Math.abs(dx) < 1 && Math.abs(dy) < 1) {\n window.scrollTo(targetX, targetY)\n resolve()\n return\n }\n\n // 随机步长 (最小 2px,最大剩余距离的 20%)\n const stepX = Math.sign(dx) * Math.min(Math.max(2, Math.random() * Math.abs(dx) * 0.2), Math.abs(dx))\n const stepY = Math.sign(dy) * Math.min(Math.max(2, Math.random() * Math.abs(dy) * 0.2), Math.abs(dy))\n\n currentX += stepX\n currentY += stepY\n await waitScrollTo(currentX, currentY)\n\n // 随机短暂停顿 10~30ms\n const delay = 10 + Math.random() * 20\n setTimeout(step, delay)\n }\n\n step()\n })\n}\n"],"mappings":"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","names":["dom_exports","__export","getImageArrayBuffer","getImgArrayBufferAfterLoad","getNetworkInfo","hexToRgb","humanScrollElIntoCenter","humanScrollTo","mixColor","onNetworkChange","onVisibilityChange","setCssVar","waitScrollTo","whenImageLoaded","__toCommonJS","mixColor","color1","color2","percentage","colorSpace","percentage2","hexToRgb","hex","r","g","b","setCssVar","k","v","whenImageLoaded","img","resolve","reject","onLoad","cleanup","onError","getImageArrayBuffer","type","canvas","ctx","b","getImgArrayBufferAfterLoad","loaded","isConnection","obj","getNetworkInfo","connection","onNetworkChange","listener","handleChange","onVisibilityChange","listener","hiddenPropName","hiddenEventName","handler","humanScrollElIntoCenter","el","rect","doc","body","scrollX","scrollY","viewW","viewH","targetX","targetY","maxX","maxY","newX","newY","needScrollX","needScrollY","humanScrollTo","waitScrollTo","resolve","currentX","currentY","timer","finished","cleanup","handler","failSafe","cleanupWithTimeout","finalHandler","nowX","nowY","step","dx","dy","stepX","stepY","delay"]}
1
+ {"version":3,"sources":["../src/dom/index.ts","../src/dom/utils/color.ts","../src/dom/utils/css.ts","../src/dom/utils/dev-proxy-hook.ts","../src/dom/utils/img.ts","../src/dom/utils/network.ts","../src/dom/utils/page.ts","../src/dom/utils/scroll.ts"],"sourcesContent":["export * from \"./utils/color.js\";\nexport * from \"./utils/css.js\";\nexport * from \"./utils/dev-proxy-hook.js\";\nexport * from \"./utils/img.js\";\nexport * from \"./utils/network.js\";\nexport * from \"./utils/page.js\";\nexport * from \"./utils/scroll.js\";\n","/**\n * 生成 CSS `color-mix()` 函数的字符串表示,用于动态计算两种颜色的混合结果\n *\n * @param {string} color1 - 参与混合的第一种颜色(支持 CSS 合法颜色值,如 HEX、RGB、HSL 等)\n * @param {string} color2 - 参与混合的第二种颜色\n * @param {number} percentage - 主颜色(color1)在混合中的占比(百分比数值,范围 0-100)\n * @param {'srgb' | 'hsl'} [colorSpace='srgb'] - 色彩空间选项:\n * - `'srgb'`: 标准 RGB 色彩空间(默认)\n * - `'hsl'`: 色相-饱和度-明度色彩空间\n * @param {number} [percentage2] - 可选参数:副颜色(color2)的独立占比。\n * 若未提供,则自动计算为 `100 - percentage`\n * @returns {string} 可直接用于 CSS 的 `color-mix()` 函数字符串(如 `color-mix(in srgb, red 30%, blue 70%)`)\n *\n * @example\n * // 基础用法(自动计算互补占比)\n * mixColor('red', 'blue', 30)\n * // 返回: \"color-mix(in srgb, red 30%, blue 70%)\"\n *\n * @example\n * // 显式指定双占比 + HSL 色彩空间\n * mixColor('#ff0000', '#0000ff', 40, 'hsl', 60)\n * // 返回: \"color-mix(in hsl, #ff0000 40%, #0000ff 60%)\"\n */\nexport const mixColor = (\n color1: string,\n color2: string,\n percentage: number,\n colorSpace: 'srgb' | 'hsl' = 'srgb',\n percentage2?: number,\n): string => {\n return `color-mix(in ${colorSpace}, ${color1} ${percentage}%, ${color2} ${percentage2 ? percentage2 : 100 - percentage}%)`\n}\n\n/**\n * 将十六进制颜色转换为 RGB\n */\nexport const hexToRgb = (hex: string): { r: number; g: number; b: number } => {\n const r = parseInt(hex.slice(1, 3), 16)\n const g = parseInt(hex.slice(3, 5), 16)\n const b = parseInt(hex.slice(5, 7), 16)\n return { r, g, b }\n}\n","/**\n * 设置 html 根元素的 css 变量\n */\nexport const setCssVar = (k: string, v: string) => {\n document.documentElement.style.setProperty(k, v)\n}\n","/**\n * 安装开发环境代理劫持。\n *\n * 作用:\n * - 将所有绝对 URL(http/https)重写为 `/proxy?url=...`(默认前缀)\n * - 统一走本地开发代理,绕过 CORS,并方便调试与拦截请求\n *\n * 当前覆盖:\n * - fetch\n * - XMLHttpRequest\n * - img.src\n * - script.src\n * - link.href(如 stylesheet / preload)\n * - source.src(如 video / audio / picture)\n * - iframe.src\n *\n * 说明:\n * - 仅重写绝对 URL(http:// / https://)\n * - 相对路径不会处理\n * - 仅建议在开发环境使用\n * - 内部带防重复安装保护,避免 HMR 导致重复 hook\n */\nexport function setupDevProxyHook(prefix: string = '/proxy?url=') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((window as any).__DEV_PROXY_HOOKED__) return\n\n const rewrite = (url: string) => {\n if (/^http?:\\/\\//.test(url) || /^https?:\\/\\//.test(url)) {\n return `${prefix}${encodeURIComponent(url)}`\n }\n return url\n }\n\n const originFetch = window.fetch\n window.fetch = function (input, init) {\n if (input instanceof Request) {\n input = new Request(rewrite(input.url), input)\n return originFetch.call(this, input, init)\n }\n\n const url = rewrite(input.toString())\n return originFetch.call(this, url, init)\n }\n\n const originOpen = XMLHttpRequest.prototype.open\n XMLHttpRequest.prototype.open = function (\n method: string,\n url: string | URL,\n async?: boolean,\n username?: string | null | undefined,\n password?: string | null | undefined,\n ) {\n if (typeof url === 'string') {\n url = rewrite(url)\n } else {\n url = new URL(rewrite(url.href))\n }\n return originOpen.call(this, method, url, async ?? true, username, password)\n }\n\n /**\n * 通用属性 Hook\n *\n * 用于重写资源加载类元素的 src / href 属性\n */\n const hookUrlProperty = (proto: object, key: 'src' | 'href') => {\n const desc = Object.getOwnPropertyDescriptor(proto, key)\n if (!desc?.set) return\n\n Object.defineProperty(proto, key, {\n configurable: true,\n enumerable: desc.enumerable,\n get: desc.get,\n set(value: string) {\n return desc.set!.call(this, rewrite(value))\n },\n })\n }\n\n // 图片资源\n hookUrlProperty(HTMLImageElement.prototype, 'src')\n\n // 动态脚本资源\n hookUrlProperty(HTMLScriptElement.prototype, 'src')\n\n // 样式 / preload / prefetch\n hookUrlProperty(HTMLLinkElement.prototype, 'href')\n\n // video / audio / picture\n hookUrlProperty(HTMLSourceElement.prototype, 'src')\n\n // iframe 页面资源\n hookUrlProperty(HTMLIFrameElement.prototype, 'src')\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(window as any).__DEV_PROXY_HOOKED__ = true\n}\n","/**\n * 等待 <img> 加载完成\n */\nexport function whenImageLoaded(img: HTMLImageElement): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n if (img.dataset['state'] === 'loading') {\n img.src = img.dataset['src']!\n }\n\n if (img.complete && img.naturalWidth > 0) {\n resolve(img)\n return\n }\n\n const onLoad = () => {\n cleanup()\n resolve(img)\n }\n\n const onError = () => {\n cleanup()\n reject(new Error(`图片加载失败: ${img.src}`))\n }\n\n const cleanup = () => {\n img.removeEventListener('load', onLoad)\n img.removeEventListener('error', onError)\n }\n\n img.addEventListener('load', onLoad)\n img.addEventListener('error', onError)\n })\n}\n\n/**\n * 从 <img> 元素获取图片字节数据(ArrayBuffer)\n * @param img 已加载的 <img> 元素\n * @param type 图片类型,可选(默认 png)\n */\nexport async function getImageArrayBuffer(img: HTMLImageElement, type: string = 'image/png'): Promise<ArrayBuffer> {\n const canvas = document.createElement('canvas')\n canvas.width = img.naturalWidth\n canvas.height = img.naturalHeight\n const ctx = canvas.getContext('2d')\n if (!ctx) throw new Error('无法创建 Canvas 2D 上下文')\n ctx.drawImage(img, 0, 0)\n\n const blob: Blob = await new Promise((resolve, reject) => {\n canvas.toBlob((b) => (b ? resolve(b) : reject(new Error('toBlob 失败'))), type)\n })\n\n return await blob.arrayBuffer()\n}\n\n/**\n * 等待加载完成并获取字节数据\n */\nexport async function getImgArrayBufferAfterLoad(img: HTMLImageElement, type?: string): Promise<ArrayBuffer> {\n const loaded = await whenImageLoaded(img)\n return await getImageArrayBuffer(loaded, type)\n}\n","/**\n * 网络信息\n */\nexport interface NetworkInfo extends EventTarget {\n // 带宽(估算)\n downlink: number\n // 延迟(估算)\n rtt: number\n // 类型(估算)\n effectiveType: 'slow-2g' | '2g' | '3g' | '4g'\n}\n\n/**\n * 网络状态\n * - 'offline': 无网络\n * - 'online': 在线但不支持 NetworkInformation API\n * - NetworkInformation: 含详细网络信息\n */\nexport type NetworkState = 'offline' | Omit<NetworkInfo, keyof EventTarget> | 'online'\n\nfunction isConnection(obj: unknown): obj is NetworkInfo {\n return obj !== null && typeof obj === 'object' && 'downlink' in obj && 'rtt' in obj && 'effectiveType' in obj\n}\n\n/**\n * 获取网络信息\n */\nexport function getNetworkInfo(): NetworkState {\n if (!navigator.onLine) {\n return 'offline'\n }\n\n if ('connection' in navigator && isConnection(navigator.connection)) {\n // 现代 Web API 直接获取网络连接的信息\n const connection = navigator.connection\n return {\n downlink: connection.downlink,\n rtt: connection.rtt,\n effectiveType: connection.effectiveType,\n }\n } else {\n return 'online'\n }\n}\n\n/**\n * 监听网络状态变化\n * @param listener 监听器\n * @returns 成功监听时返回解绑函数\n */\nexport function onNetworkChange(listener: (info: NetworkState) => void) {\n const handleChange = () => {\n listener(getNetworkInfo())\n }\n\n if ('connection' in navigator && isConnection(navigator.connection)) {\n // 现代 Web API\n const connection = navigator.connection\n connection.addEventListener('change', handleChange)\n return () => connection.removeEventListener('change', handleChange)\n } else {\n window.addEventListener('online', handleChange)\n window.addEventListener('offline', handleChange)\n return () => {\n window.removeEventListener('online', handleChange)\n window.removeEventListener('offline', handleChange)\n }\n }\n}\n","/** 可见性改变的监听器 */\nexport interface VisibilityChangeListener {\n (hidden: boolean): void\n}\n\n/**\n * 监听页面可见性变化(兼容旧的IE/Chrome)\n * @param listener 监听器\n * @returns 成功监听时返回解绑函数\n */\nexport function onVisibilityChange(listener: VisibilityChangeListener) {\n let hiddenPropName: string | undefined = undefined,\n hiddenEventName: string | undefined = undefined\n\n if (typeof document.hidden !== 'undefined') {\n // 现代 Web API\n hiddenPropName = 'hidden'\n hiddenEventName = 'visibilitychange'\n } else if ('msHidden' in document && typeof document.msHidden !== 'undefined') {\n // 旧 IE\n hiddenPropName = 'msHidden'\n hiddenEventName = 'msvisibilitychange'\n } else if ('webkitHidden' in document && typeof document.webkitHidden !== 'undefined') {\n // 旧 Chrome\n hiddenPropName = 'webkitHidden'\n hiddenEventName = 'webkitvisibilitychange'\n }\n\n if (!hiddenPropName || !hiddenEventName) {\n return null\n }\n\n const handler = () => {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n listener(document[hiddenPropName])\n }\n\n document.addEventListener(hiddenEventName, handler)\n\n return () => {\n document.removeEventListener(hiddenEventName, handler)\n }\n}\n","/**\n * 滚动元素到屏幕中心\n * @param el\n */\nexport async function humanScrollElIntoCenter(el: HTMLElement) {\n if (!el) return\n\n const rect = el.getBoundingClientRect()\n const doc = document.documentElement\n const body = document.body\n\n const scrollX = window.scrollX || doc.scrollLeft || body.scrollLeft\n const scrollY = window.scrollY || doc.scrollTop || body.scrollTop\n\n const viewW = window.innerWidth\n const viewH = window.innerHeight\n\n // 目标中心点相对页面的位置\n const targetX = rect.left + scrollX + rect.width / 2 - viewW / 2\n const targetY = rect.top + scrollY + rect.height / 2 - viewH / 2\n\n const maxX = Math.max(0, body.scrollWidth - viewW)\n const maxY = Math.max(0, body.scrollHeight - viewH)\n\n // 页面不需要滚动\n if (maxX === 0 && maxY === 0) return\n\n // 水平滚动:仅在可滚动时\n const newX = maxX > 0 ? Math.min(Math.max(targetX, 0), maxX) : scrollX\n // 垂直滚动\n const newY = maxY > 0 ? Math.min(Math.max(targetY, 0), maxY) : scrollY\n\n // 判断是否真正需要滚动\n const needScrollX = Math.abs(window.scrollX - newX) > 1\n const needScrollY = Math.abs(window.scrollY - newY) > 1\n if (!needScrollX && !needScrollY) return\n\n await humanScrollTo(newX, newY)\n}\n\n/**\n * 等待滚动\n */\nexport function waitScrollTo(targetX: number, targetY: number): Promise<void> {\n return new Promise((resolve) => {\n const currentX = window.scrollX\n const currentY = window.scrollY\n\n // 若无需滚动\n if (Math.abs(currentX - targetX) < 1 && Math.abs(currentY - targetY) < 1) {\n resolve()\n return\n }\n\n let timer: number | undefined\n let finished = false\n\n const cleanup = () => {\n if (finished) return\n finished = true\n window.removeEventListener('scroll', handler)\n if (timer) clearTimeout(timer)\n resolve()\n }\n\n const handler = () => {\n if (timer) clearTimeout(timer)\n // 若 50ms 内无新滚动事件,则视为滚动结束\n timer = window.setTimeout(cleanup, 50)\n }\n\n // 启动兜底超时(比如滚动事件根本不触发)\n const failSafe = window.setTimeout(() => {\n console.debug('[waitScrollTo] fallback timeout reached')\n cleanup()\n }, 1000)\n\n const cleanupWithTimeout = () => {\n cleanup()\n clearTimeout(failSafe)\n }\n\n // 替换 cleanup,确保清理超时器\n const finalHandler = () => {\n if (timer) clearTimeout(timer)\n timer = window.setTimeout(cleanupWithTimeout, 50)\n }\n\n // 注册事件\n window.addEventListener('scroll', finalHandler, { passive: true })\n\n // 立即触发滚动\n window.scrollTo({ left: targetX, top: targetY })\n\n // 有时浏览器同步滚动,不触发 scroll 事件\n requestAnimationFrame(() => {\n const nowX = window.scrollX\n const nowY = window.scrollY\n if (Math.abs(nowX - targetX) < 1 && Math.abs(nowY - targetY) < 1) {\n cleanupWithTimeout()\n }\n })\n })\n}\n\n/**\n * 模拟人类手感滚动到指定位置\n */\nexport async function humanScrollTo(targetX: number, targetY: number): Promise<void> {\n return new Promise<void>((resolve) => {\n let currentX = window.scrollX\n let currentY = window.scrollY\n\n async function step() {\n const dx = targetX - currentX\n const dy = targetY - currentY\n\n // 如果距离足够小,直接跳到目标结束\n if (Math.abs(dx) < 1 && Math.abs(dy) < 1) {\n window.scrollTo(targetX, targetY)\n resolve()\n return\n }\n\n // 随机步长 (最小 2px,最大剩余距离的 20%)\n const stepX = Math.sign(dx) * Math.min(Math.max(2, Math.random() * Math.abs(dx) * 0.2), Math.abs(dx))\n const stepY = Math.sign(dy) * Math.min(Math.max(2, Math.random() * Math.abs(dy) * 0.2), Math.abs(dy))\n\n currentX += stepX\n currentY += stepY\n await waitScrollTo(currentX, currentY)\n\n // 随机短暂停顿 10~30ms\n const delay = 10 + Math.random() * 20\n setTimeout(step, delay)\n }\n\n step()\n })\n}\n"],"mappings":"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","names":["dom_exports","__export","getImageArrayBuffer","getImgArrayBufferAfterLoad","getNetworkInfo","hexToRgb","humanScrollElIntoCenter","humanScrollTo","mixColor","onNetworkChange","onVisibilityChange","setCssVar","setupDevProxyHook","waitScrollTo","whenImageLoaded","__toCommonJS","mixColor","color1","color2","percentage","colorSpace","percentage2","hexToRgb","hex","r","g","b","setCssVar","k","v","setupDevProxyHook","prefix","rewrite","url","originFetch","input","init","originOpen","method","async","username","password","hookUrlProperty","proto","key","desc","value","whenImageLoaded","img","resolve","reject","onLoad","cleanup","onError","getImageArrayBuffer","type","canvas","ctx","b","getImgArrayBufferAfterLoad","loaded","isConnection","obj","getNetworkInfo","connection","onNetworkChange","listener","handleChange","onVisibilityChange","listener","hiddenPropName","hiddenEventName","handler","humanScrollElIntoCenter","el","rect","doc","body","scrollX","scrollY","viewW","viewH","targetX","targetY","maxX","maxY","newX","newY","needScrollX","needScrollY","humanScrollTo","waitScrollTo","resolve","currentX","currentY","timer","finished","cleanup","handler","failSafe","cleanupWithTimeout","finalHandler","nowX","nowY","step","dx","dy","stepX","stepY","delay"]}
package/dist/dom.d.cts CHANGED
@@ -36,6 +36,30 @@ declare const hexToRgb: (hex: string) => {
36
36
  */
37
37
  declare const setCssVar: (k: string, v: string) => void;
38
38
 
39
+ /**
40
+ * 安装开发环境代理劫持。
41
+ *
42
+ * 作用:
43
+ * - 将所有绝对 URL(http/https)重写为 `/proxy?url=...`(默认前缀)
44
+ * - 统一走本地开发代理,绕过 CORS,并方便调试与拦截请求
45
+ *
46
+ * 当前覆盖:
47
+ * - fetch
48
+ * - XMLHttpRequest
49
+ * - img.src
50
+ * - script.src
51
+ * - link.href(如 stylesheet / preload)
52
+ * - source.src(如 video / audio / picture)
53
+ * - iframe.src
54
+ *
55
+ * 说明:
56
+ * - 仅重写绝对 URL(http:// / https://)
57
+ * - 相对路径不会处理
58
+ * - 仅建议在开发环境使用
59
+ * - 内部带防重复安装保护,避免 HMR 导致重复 hook
60
+ */
61
+ declare function setupDevProxyHook(prefix?: string): void;
62
+
39
63
  /**
40
64
  * 等待 <img> 加载完成
41
65
  */
@@ -102,4 +126,4 @@ declare function waitScrollTo(targetX: number, targetY: number): Promise<void>;
102
126
  */
103
127
  declare function humanScrollTo(targetX: number, targetY: number): Promise<void>;
104
128
 
105
- export { type NetworkInfo, type NetworkState, type VisibilityChangeListener, getImageArrayBuffer, getImgArrayBufferAfterLoad, getNetworkInfo, hexToRgb, humanScrollElIntoCenter, humanScrollTo, mixColor, onNetworkChange, onVisibilityChange, setCssVar, waitScrollTo, whenImageLoaded };
129
+ export { type NetworkInfo, type NetworkState, type VisibilityChangeListener, getImageArrayBuffer, getImgArrayBufferAfterLoad, getNetworkInfo, hexToRgb, humanScrollElIntoCenter, humanScrollTo, mixColor, onNetworkChange, onVisibilityChange, setCssVar, setupDevProxyHook, waitScrollTo, whenImageLoaded };
package/dist/dom.d.ts CHANGED
@@ -36,6 +36,30 @@ declare const hexToRgb: (hex: string) => {
36
36
  */
37
37
  declare const setCssVar: (k: string, v: string) => void;
38
38
 
39
+ /**
40
+ * 安装开发环境代理劫持。
41
+ *
42
+ * 作用:
43
+ * - 将所有绝对 URL(http/https)重写为 `/proxy?url=...`(默认前缀)
44
+ * - 统一走本地开发代理,绕过 CORS,并方便调试与拦截请求
45
+ *
46
+ * 当前覆盖:
47
+ * - fetch
48
+ * - XMLHttpRequest
49
+ * - img.src
50
+ * - script.src
51
+ * - link.href(如 stylesheet / preload)
52
+ * - source.src(如 video / audio / picture)
53
+ * - iframe.src
54
+ *
55
+ * 说明:
56
+ * - 仅重写绝对 URL(http:// / https://)
57
+ * - 相对路径不会处理
58
+ * - 仅建议在开发环境使用
59
+ * - 内部带防重复安装保护,避免 HMR 导致重复 hook
60
+ */
61
+ declare function setupDevProxyHook(prefix?: string): void;
62
+
39
63
  /**
40
64
  * 等待 <img> 加载完成
41
65
  */
@@ -102,4 +126,4 @@ declare function waitScrollTo(targetX: number, targetY: number): Promise<void>;
102
126
  */
103
127
  declare function humanScrollTo(targetX: number, targetY: number): Promise<void>;
104
128
 
105
- export { type NetworkInfo, type NetworkState, type VisibilityChangeListener, getImageArrayBuffer, getImgArrayBufferAfterLoad, getNetworkInfo, hexToRgb, humanScrollElIntoCenter, humanScrollTo, mixColor, onNetworkChange, onVisibilityChange, setCssVar, waitScrollTo, whenImageLoaded };
129
+ export { type NetworkInfo, type NetworkState, type VisibilityChangeListener, getImageArrayBuffer, getImgArrayBufferAfterLoad, getNetworkInfo, hexToRgb, humanScrollElIntoCenter, humanScrollTo, mixColor, onNetworkChange, onVisibilityChange, setCssVar, setupDevProxyHook, waitScrollTo, whenImageLoaded };
package/dist/dom.js CHANGED
@@ -1,2 +1,2 @@
1
- var M=(e,n,t,o="srgb",i)=>`color-mix(in ${o}, ${e} ${t}%, ${n} ${i||100-t}%)`,E=e=>{let n=parseInt(e.slice(1,3),16),t=parseInt(e.slice(3,5),16),o=parseInt(e.slice(5,7),16);return{r:n,g:t,b:o}};var L=(e,n)=>{document.documentElement.style.setProperty(e,n)};function v(e){return new Promise((n,t)=>{if(e.dataset.state==="loading"&&(e.src=e.dataset.src),e.complete&&e.naturalWidth>0){n(e);return}let o=()=>{r(),n(e)},i=()=>{r(),t(new Error(`\u56FE\u7247\u52A0\u8F7D\u5931\u8D25: ${e.src}`))},r=()=>{e.removeEventListener("load",o),e.removeEventListener("error",i)};e.addEventListener("load",o),e.addEventListener("error",i)})}async function p(e,n="image/png"){let t=document.createElement("canvas");t.width=e.naturalWidth,t.height=e.naturalHeight;let o=t.getContext("2d");if(!o)throw new Error("\u65E0\u6CD5\u521B\u5EFA Canvas 2D \u4E0A\u4E0B\u6587");return o.drawImage(e,0,0),await(await new Promise((r,a)=>{t.toBlob(s=>s?r(s):a(new Error("toBlob \u5931\u8D25")),n)})).arrayBuffer()}async function H(e,n){let t=await v(e);return await p(t,n)}function w(e){return e!==null&&typeof e=="object"&&"downlink"in e&&"rtt"in e&&"effectiveType"in e}function g(){if(!navigator.onLine)return"offline";if("connection"in navigator&&w(navigator.connection)){let e=navigator.connection;return{downlink:e.downlink,rtt:e.rtt,effectiveType:e.effectiveType}}else return"online"}function C(e){let n=()=>{e(g())};if("connection"in navigator&&w(navigator.connection)){let t=navigator.connection;return t.addEventListener("change",n),()=>t.removeEventListener("change",n)}else return window.addEventListener("online",n),window.addEventListener("offline",n),()=>{window.removeEventListener("online",n),window.removeEventListener("offline",n)}}function X(e){let n,t;if(typeof document.hidden<"u"?(n="hidden",t="visibilitychange"):"msHidden"in document&&typeof document.msHidden<"u"?(n="msHidden",t="msvisibilitychange"):"webkitHidden"in document&&typeof document.webkitHidden<"u"&&(n="webkitHidden",t="webkitvisibilitychange"),!n||!t)return null;let o=()=>{e(document[n])};return document.addEventListener(t,o),()=>{document.removeEventListener(t,o)}}async function N(e){if(!e)return;let n=e.getBoundingClientRect(),t=document.documentElement,o=document.body,i=window.scrollX||t.scrollLeft||o.scrollLeft,r=window.scrollY||t.scrollTop||o.scrollTop,a=window.innerWidth,s=window.innerHeight,d=n.left+i+n.width/2-a/2,l=n.top+r+n.height/2-s/2,c=Math.max(0,o.scrollWidth-a),u=Math.max(0,o.scrollHeight-s);if(c===0&&u===0)return;let f=c>0?Math.min(Math.max(d,0),c):i,m=u>0?Math.min(Math.max(l,0),u):r,h=Math.abs(window.scrollX-f)>1,b=Math.abs(window.scrollY-m)>1;!h&&!b||await y(f,m)}function x(e,n){return new Promise(t=>{let o=window.scrollX,i=window.scrollY;if(Math.abs(o-e)<1&&Math.abs(i-n)<1){t();return}let r,a=!1,s=()=>{a||(a=!0,window.removeEventListener("scroll",d),r&&clearTimeout(r),t())},d=()=>{r&&clearTimeout(r),r=window.setTimeout(s,50)},l=window.setTimeout(()=>{console.debug("[waitScrollTo] fallback timeout reached"),s()},1e3),c=()=>{s(),clearTimeout(l)},u=()=>{r&&clearTimeout(r),r=window.setTimeout(c,50)};window.addEventListener("scroll",u,{passive:!0}),window.scrollTo({left:e,top:n}),requestAnimationFrame(()=>{let f=window.scrollX,m=window.scrollY;Math.abs(f-e)<1&&Math.abs(m-n)<1&&c()})})}async function y(e,n){return new Promise(t=>{let o=window.scrollX,i=window.scrollY;async function r(){let a=e-o,s=n-i;if(Math.abs(a)<1&&Math.abs(s)<1){window.scrollTo(e,n),t();return}let d=Math.sign(a)*Math.min(Math.max(2,Math.random()*Math.abs(a)*.2),Math.abs(a)),l=Math.sign(s)*Math.min(Math.max(2,Math.random()*Math.abs(s)*.2),Math.abs(s));o+=d,i+=l,await x(o,i);let c=10+Math.random()*20;setTimeout(r,c)}r()})}export{p as getImageArrayBuffer,H as getImgArrayBufferAfterLoad,g as getNetworkInfo,E as hexToRgb,N as humanScrollElIntoCenter,y as humanScrollTo,M as mixColor,C as onNetworkChange,X as onVisibilityChange,L as setCssVar,x as waitScrollTo,v as whenImageLoaded};
1
+ var M=(e,n,o,r="srgb",c)=>`color-mix(in ${r}, ${e} ${o}%, ${n} ${c||100-o}%)`,x=e=>{let n=parseInt(e.slice(1,3),16),o=parseInt(e.slice(3,5),16),r=parseInt(e.slice(5,7),16);return{r:n,g:o,b:r}};var T=(e,n)=>{document.documentElement.style.setProperty(e,n)};function k(e="/proxy?url="){if(window.__DEV_PROXY_HOOKED__)return;let n=t=>/^http?:\/\//.test(t)||/^https?:\/\//.test(t)?`${e}${encodeURIComponent(t)}`:t,o=window.fetch;window.fetch=function(t,i){if(t instanceof Request)return t=new Request(n(t.url),t),o.call(this,t,i);let s=n(t.toString());return o.call(this,s,i)};let r=XMLHttpRequest.prototype.open;XMLHttpRequest.prototype.open=function(t,i,s,a,d){return typeof i=="string"?i=n(i):i=new URL(n(i.href)),r.call(this,t,i,s??!0,a,d)};let c=(t,i)=>{let s=Object.getOwnPropertyDescriptor(t,i);s?.set&&Object.defineProperty(t,i,{configurable:!0,enumerable:s.enumerable,get:s.get,set(a){return s.set.call(this,n(a))}})};c(HTMLImageElement.prototype,"src"),c(HTMLScriptElement.prototype,"src"),c(HTMLLinkElement.prototype,"href"),c(HTMLSourceElement.prototype,"src"),c(HTMLIFrameElement.prototype,"src"),window.__DEV_PROXY_HOOKED__=!0}function g(e){return new Promise((n,o)=>{if(e.dataset.state==="loading"&&(e.src=e.dataset.src),e.complete&&e.naturalWidth>0){n(e);return}let r=()=>{t(),n(e)},c=()=>{t(),o(new Error(`\u56FE\u7247\u52A0\u8F7D\u5931\u8D25: ${e.src}`))},t=()=>{e.removeEventListener("load",r),e.removeEventListener("error",c)};e.addEventListener("load",r),e.addEventListener("error",c)})}async function b(e,n="image/png"){let o=document.createElement("canvas");o.width=e.naturalWidth,o.height=e.naturalHeight;let r=o.getContext("2d");if(!r)throw new Error("\u65E0\u6CD5\u521B\u5EFA Canvas 2D \u4E0A\u4E0B\u6587");return r.drawImage(e,0,0),await(await new Promise((t,i)=>{o.toBlob(s=>s?t(s):i(new Error("toBlob \u5931\u8D25")),n)})).arrayBuffer()}async function P(e,n){let o=await g(e);return await b(o,n)}function w(e){return e!==null&&typeof e=="object"&&"downlink"in e&&"rtt"in e&&"effectiveType"in e}function v(){if(!navigator.onLine)return"offline";if("connection"in navigator&&w(navigator.connection)){let e=navigator.connection;return{downlink:e.downlink,rtt:e.rtt,effectiveType:e.effectiveType}}else return"online"}function C(e){let n=()=>{e(v())};if("connection"in navigator&&w(navigator.connection)){let o=navigator.connection;return o.addEventListener("change",n),()=>o.removeEventListener("change",n)}else return window.addEventListener("online",n),window.addEventListener("offline",n),()=>{window.removeEventListener("online",n),window.removeEventListener("offline",n)}}function Y(e){let n,o;if(typeof document.hidden<"u"?(n="hidden",o="visibilitychange"):"msHidden"in document&&typeof document.msHidden<"u"?(n="msHidden",o="msvisibilitychange"):"webkitHidden"in document&&typeof document.webkitHidden<"u"&&(n="webkitHidden",o="webkitvisibilitychange"),!n||!o)return null;let r=()=>{e(document[n])};return document.addEventListener(o,r),()=>{document.removeEventListener(o,r)}}async function O(e){if(!e)return;let n=e.getBoundingClientRect(),o=document.documentElement,r=document.body,c=window.scrollX||o.scrollLeft||r.scrollLeft,t=window.scrollY||o.scrollTop||r.scrollTop,i=window.innerWidth,s=window.innerHeight,a=n.left+c+n.width/2-i/2,d=n.top+t+n.height/2-s/2,l=Math.max(0,r.scrollWidth-i),u=Math.max(0,r.scrollHeight-s);if(l===0&&u===0)return;let f=l>0?Math.min(Math.max(a,0),l):c,m=u>0?Math.min(Math.max(d,0),u):t,h=Math.abs(window.scrollX-f)>1,p=Math.abs(window.scrollY-m)>1;!h&&!p||await E(f,m)}function y(e,n){return new Promise(o=>{let r=window.scrollX,c=window.scrollY;if(Math.abs(r-e)<1&&Math.abs(c-n)<1){o();return}let t,i=!1,s=()=>{i||(i=!0,window.removeEventListener("scroll",a),t&&clearTimeout(t),o())},a=()=>{t&&clearTimeout(t),t=window.setTimeout(s,50)},d=window.setTimeout(()=>{console.debug("[waitScrollTo] fallback timeout reached"),s()},1e3),l=()=>{s(),clearTimeout(d)},u=()=>{t&&clearTimeout(t),t=window.setTimeout(l,50)};window.addEventListener("scroll",u,{passive:!0}),window.scrollTo({left:e,top:n}),requestAnimationFrame(()=>{let f=window.scrollX,m=window.scrollY;Math.abs(f-e)<1&&Math.abs(m-n)<1&&l()})})}async function E(e,n){return new Promise(o=>{let r=window.scrollX,c=window.scrollY;async function t(){let i=e-r,s=n-c;if(Math.abs(i)<1&&Math.abs(s)<1){window.scrollTo(e,n),o();return}let a=Math.sign(i)*Math.min(Math.max(2,Math.random()*Math.abs(i)*.2),Math.abs(i)),d=Math.sign(s)*Math.min(Math.max(2,Math.random()*Math.abs(s)*.2),Math.abs(s));r+=a,c+=d,await y(r,c);let l=10+Math.random()*20;setTimeout(t,l)}t()})}export{b as getImageArrayBuffer,P as getImgArrayBufferAfterLoad,v as getNetworkInfo,x as hexToRgb,O as humanScrollElIntoCenter,E as humanScrollTo,M as mixColor,C as onNetworkChange,Y as onVisibilityChange,T as setCssVar,k as setupDevProxyHook,y as waitScrollTo,g as whenImageLoaded};
2
2
  //# sourceMappingURL=dom.js.map
package/dist/dom.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dom/utils/color.ts","../src/dom/utils/css.ts","../src/dom/utils/img.ts","../src/dom/utils/network.ts","../src/dom/utils/page.ts","../src/dom/utils/scroll.ts"],"sourcesContent":["/**\n * 生成 CSS `color-mix()` 函数的字符串表示,用于动态计算两种颜色的混合结果\n *\n * @param {string} color1 - 参与混合的第一种颜色(支持 CSS 合法颜色值,如 HEX、RGB、HSL 等)\n * @param {string} color2 - 参与混合的第二种颜色\n * @param {number} percentage - 主颜色(color1)在混合中的占比(百分比数值,范围 0-100)\n * @param {'srgb' | 'hsl'} [colorSpace='srgb'] - 色彩空间选项:\n * - `'srgb'`: 标准 RGB 色彩空间(默认)\n * - `'hsl'`: 色相-饱和度-明度色彩空间\n * @param {number} [percentage2] - 可选参数:副颜色(color2)的独立占比。\n * 若未提供,则自动计算为 `100 - percentage`\n * @returns {string} 可直接用于 CSS 的 `color-mix()` 函数字符串(如 `color-mix(in srgb, red 30%, blue 70%)`)\n *\n * @example\n * // 基础用法(自动计算互补占比)\n * mixColor('red', 'blue', 30)\n * // 返回: \"color-mix(in srgb, red 30%, blue 70%)\"\n *\n * @example\n * // 显式指定双占比 + HSL 色彩空间\n * mixColor('#ff0000', '#0000ff', 40, 'hsl', 60)\n * // 返回: \"color-mix(in hsl, #ff0000 40%, #0000ff 60%)\"\n */\nexport const mixColor = (\n color1: string,\n color2: string,\n percentage: number,\n colorSpace: 'srgb' | 'hsl' = 'srgb',\n percentage2?: number,\n): string => {\n return `color-mix(in ${colorSpace}, ${color1} ${percentage}%, ${color2} ${percentage2 ? percentage2 : 100 - percentage}%)`\n}\n\n/**\n * 将十六进制颜色转换为 RGB\n */\nexport const hexToRgb = (hex: string): { r: number; g: number; b: number } => {\n const r = parseInt(hex.slice(1, 3), 16)\n const g = parseInt(hex.slice(3, 5), 16)\n const b = parseInt(hex.slice(5, 7), 16)\n return { r, g, b }\n}\n","/**\n * 设置 html 根元素的 css 变量\n */\nexport const setCssVar = (k: string, v: string) => {\n document.documentElement.style.setProperty(k, v)\n}\n","/**\n * 等待 <img> 加载完成\n */\nexport function whenImageLoaded(img: HTMLImageElement): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n if (img.dataset['state'] === 'loading') {\n img.src = img.dataset['src']!\n }\n\n if (img.complete && img.naturalWidth > 0) {\n resolve(img)\n return\n }\n\n const onLoad = () => {\n cleanup()\n resolve(img)\n }\n\n const onError = () => {\n cleanup()\n reject(new Error(`图片加载失败: ${img.src}`))\n }\n\n const cleanup = () => {\n img.removeEventListener('load', onLoad)\n img.removeEventListener('error', onError)\n }\n\n img.addEventListener('load', onLoad)\n img.addEventListener('error', onError)\n })\n}\n\n/**\n * 从 <img> 元素获取图片字节数据(ArrayBuffer)\n * @param img 已加载的 <img> 元素\n * @param type 图片类型,可选(默认 png)\n */\nexport async function getImageArrayBuffer(img: HTMLImageElement, type: string = 'image/png'): Promise<ArrayBuffer> {\n const canvas = document.createElement('canvas')\n canvas.width = img.naturalWidth\n canvas.height = img.naturalHeight\n const ctx = canvas.getContext('2d')\n if (!ctx) throw new Error('无法创建 Canvas 2D 上下文')\n ctx.drawImage(img, 0, 0)\n\n const blob: Blob = await new Promise((resolve, reject) => {\n canvas.toBlob((b) => (b ? resolve(b) : reject(new Error('toBlob 失败'))), type)\n })\n\n return await blob.arrayBuffer()\n}\n\n/**\n * 等待加载完成并获取字节数据\n */\nexport async function getImgArrayBufferAfterLoad(img: HTMLImageElement, type?: string): Promise<ArrayBuffer> {\n const loaded = await whenImageLoaded(img)\n return await getImageArrayBuffer(loaded, type)\n}\n","/**\n * 网络信息\n */\nexport interface NetworkInfo extends EventTarget {\n // 带宽(估算)\n downlink: number\n // 延迟(估算)\n rtt: number\n // 类型(估算)\n effectiveType: 'slow-2g' | '2g' | '3g' | '4g'\n}\n\n/**\n * 网络状态\n * - 'offline': 无网络\n * - 'online': 在线但不支持 NetworkInformation API\n * - NetworkInformation: 含详细网络信息\n */\nexport type NetworkState = 'offline' | Omit<NetworkInfo, keyof EventTarget> | 'online'\n\nfunction isConnection(obj: unknown): obj is NetworkInfo {\n return obj !== null && typeof obj === 'object' && 'downlink' in obj && 'rtt' in obj && 'effectiveType' in obj\n}\n\n/**\n * 获取网络信息\n */\nexport function getNetworkInfo(): NetworkState {\n if (!navigator.onLine) {\n return 'offline'\n }\n\n if ('connection' in navigator && isConnection(navigator.connection)) {\n // 现代 Web API 直接获取网络连接的信息\n const connection = navigator.connection\n return {\n downlink: connection.downlink,\n rtt: connection.rtt,\n effectiveType: connection.effectiveType,\n }\n } else {\n return 'online'\n }\n}\n\n/**\n * 监听网络状态变化\n * @param listener 监听器\n * @returns 成功监听时返回解绑函数\n */\nexport function onNetworkChange(listener: (info: NetworkState) => void) {\n const handleChange = () => {\n listener(getNetworkInfo())\n }\n\n if ('connection' in navigator && isConnection(navigator.connection)) {\n // 现代 Web API\n const connection = navigator.connection\n connection.addEventListener('change', handleChange)\n return () => connection.removeEventListener('change', handleChange)\n } else {\n window.addEventListener('online', handleChange)\n window.addEventListener('offline', handleChange)\n return () => {\n window.removeEventListener('online', handleChange)\n window.removeEventListener('offline', handleChange)\n }\n }\n}\n","/** 可见性改变的监听器 */\nexport interface VisibilityChangeListener {\n (hidden: boolean): void\n}\n\n/**\n * 监听页面可见性变化(兼容旧的IE/Chrome)\n * @param listener 监听器\n * @returns 成功监听时返回解绑函数\n */\nexport function onVisibilityChange(listener: VisibilityChangeListener) {\n let hiddenPropName: string | undefined = undefined,\n hiddenEventName: string | undefined = undefined\n\n if (typeof document.hidden !== 'undefined') {\n // 现代 Web API\n hiddenPropName = 'hidden'\n hiddenEventName = 'visibilitychange'\n } else if ('msHidden' in document && typeof document.msHidden !== 'undefined') {\n // 旧 IE\n hiddenPropName = 'msHidden'\n hiddenEventName = 'msvisibilitychange'\n } else if ('webkitHidden' in document && typeof document.webkitHidden !== 'undefined') {\n // 旧 Chrome\n hiddenPropName = 'webkitHidden'\n hiddenEventName = 'webkitvisibilitychange'\n }\n\n if (!hiddenPropName || !hiddenEventName) {\n return null\n }\n\n const handler = () => {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n listener(document[hiddenPropName])\n }\n\n document.addEventListener(hiddenEventName, handler)\n\n return () => {\n document.removeEventListener(hiddenEventName, handler)\n }\n}\n","/**\n * 滚动元素到屏幕中心\n * @param el\n */\nexport async function humanScrollElIntoCenter(el: HTMLElement) {\n if (!el) return\n\n const rect = el.getBoundingClientRect()\n const doc = document.documentElement\n const body = document.body\n\n const scrollX = window.scrollX || doc.scrollLeft || body.scrollLeft\n const scrollY = window.scrollY || doc.scrollTop || body.scrollTop\n\n const viewW = window.innerWidth\n const viewH = window.innerHeight\n\n // 目标中心点相对页面的位置\n const targetX = rect.left + scrollX + rect.width / 2 - viewW / 2\n const targetY = rect.top + scrollY + rect.height / 2 - viewH / 2\n\n const maxX = Math.max(0, body.scrollWidth - viewW)\n const maxY = Math.max(0, body.scrollHeight - viewH)\n\n // 页面不需要滚动\n if (maxX === 0 && maxY === 0) return\n\n // 水平滚动:仅在可滚动时\n const newX = maxX > 0 ? Math.min(Math.max(targetX, 0), maxX) : scrollX\n // 垂直滚动\n const newY = maxY > 0 ? Math.min(Math.max(targetY, 0), maxY) : scrollY\n\n // 判断是否真正需要滚动\n const needScrollX = Math.abs(window.scrollX - newX) > 1\n const needScrollY = Math.abs(window.scrollY - newY) > 1\n if (!needScrollX && !needScrollY) return\n\n await humanScrollTo(newX, newY)\n}\n\n/**\n * 等待滚动\n */\nexport function waitScrollTo(targetX: number, targetY: number): Promise<void> {\n return new Promise((resolve) => {\n const currentX = window.scrollX\n const currentY = window.scrollY\n\n // 若无需滚动\n if (Math.abs(currentX - targetX) < 1 && Math.abs(currentY - targetY) < 1) {\n resolve()\n return\n }\n\n let timer: number | undefined\n let finished = false\n\n const cleanup = () => {\n if (finished) return\n finished = true\n window.removeEventListener('scroll', handler)\n if (timer) clearTimeout(timer)\n resolve()\n }\n\n const handler = () => {\n if (timer) clearTimeout(timer)\n // 若 50ms 内无新滚动事件,则视为滚动结束\n timer = window.setTimeout(cleanup, 50)\n }\n\n // 启动兜底超时(比如滚动事件根本不触发)\n const failSafe = window.setTimeout(() => {\n console.debug('[waitScrollTo] fallback timeout reached')\n cleanup()\n }, 1000)\n\n const cleanupWithTimeout = () => {\n cleanup()\n clearTimeout(failSafe)\n }\n\n // 替换 cleanup,确保清理超时器\n const finalHandler = () => {\n if (timer) clearTimeout(timer)\n timer = window.setTimeout(cleanupWithTimeout, 50)\n }\n\n // 注册事件\n window.addEventListener('scroll', finalHandler, { passive: true })\n\n // 立即触发滚动\n window.scrollTo({ left: targetX, top: targetY })\n\n // 有时浏览器同步滚动,不触发 scroll 事件\n requestAnimationFrame(() => {\n const nowX = window.scrollX\n const nowY = window.scrollY\n if (Math.abs(nowX - targetX) < 1 && Math.abs(nowY - targetY) < 1) {\n cleanupWithTimeout()\n }\n })\n })\n}\n\n/**\n * 模拟人类手感滚动到指定位置\n */\nexport async function humanScrollTo(targetX: number, targetY: number): Promise<void> {\n return new Promise<void>((resolve) => {\n let currentX = window.scrollX\n let currentY = window.scrollY\n\n async function step() {\n const dx = targetX - currentX\n const dy = targetY - currentY\n\n // 如果距离足够小,直接跳到目标结束\n if (Math.abs(dx) < 1 && Math.abs(dy) < 1) {\n window.scrollTo(targetX, targetY)\n resolve()\n return\n }\n\n // 随机步长 (最小 2px,最大剩余距离的 20%)\n const stepX = Math.sign(dx) * Math.min(Math.max(2, Math.random() * Math.abs(dx) * 0.2), Math.abs(dx))\n const stepY = Math.sign(dy) * Math.min(Math.max(2, Math.random() * Math.abs(dy) * 0.2), Math.abs(dy))\n\n currentX += stepX\n currentY += stepY\n await waitScrollTo(currentX, currentY)\n\n // 随机短暂停顿 10~30ms\n const delay = 10 + Math.random() * 20\n setTimeout(step, delay)\n }\n\n step()\n })\n}\n"],"mappings":"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","names":["mixColor","color1","color2","percentage","colorSpace","percentage2","hexToRgb","hex","r","g","b","setCssVar","k","v","whenImageLoaded","img","resolve","reject","onLoad","cleanup","onError","getImageArrayBuffer","type","canvas","ctx","b","getImgArrayBufferAfterLoad","loaded","isConnection","obj","getNetworkInfo","connection","onNetworkChange","listener","handleChange","onVisibilityChange","listener","hiddenPropName","hiddenEventName","handler","humanScrollElIntoCenter","el","rect","doc","body","scrollX","scrollY","viewW","viewH","targetX","targetY","maxX","maxY","newX","newY","needScrollX","needScrollY","humanScrollTo","waitScrollTo","resolve","currentX","currentY","timer","finished","cleanup","handler","failSafe","cleanupWithTimeout","finalHandler","nowX","nowY","step","dx","dy","stepX","stepY","delay"]}
1
+ {"version":3,"sources":["../src/dom/utils/color.ts","../src/dom/utils/css.ts","../src/dom/utils/dev-proxy-hook.ts","../src/dom/utils/img.ts","../src/dom/utils/network.ts","../src/dom/utils/page.ts","../src/dom/utils/scroll.ts"],"sourcesContent":["/**\n * 生成 CSS `color-mix()` 函数的字符串表示,用于动态计算两种颜色的混合结果\n *\n * @param {string} color1 - 参与混合的第一种颜色(支持 CSS 合法颜色值,如 HEX、RGB、HSL 等)\n * @param {string} color2 - 参与混合的第二种颜色\n * @param {number} percentage - 主颜色(color1)在混合中的占比(百分比数值,范围 0-100)\n * @param {'srgb' | 'hsl'} [colorSpace='srgb'] - 色彩空间选项:\n * - `'srgb'`: 标准 RGB 色彩空间(默认)\n * - `'hsl'`: 色相-饱和度-明度色彩空间\n * @param {number} [percentage2] - 可选参数:副颜色(color2)的独立占比。\n * 若未提供,则自动计算为 `100 - percentage`\n * @returns {string} 可直接用于 CSS 的 `color-mix()` 函数字符串(如 `color-mix(in srgb, red 30%, blue 70%)`)\n *\n * @example\n * // 基础用法(自动计算互补占比)\n * mixColor('red', 'blue', 30)\n * // 返回: \"color-mix(in srgb, red 30%, blue 70%)\"\n *\n * @example\n * // 显式指定双占比 + HSL 色彩空间\n * mixColor('#ff0000', '#0000ff', 40, 'hsl', 60)\n * // 返回: \"color-mix(in hsl, #ff0000 40%, #0000ff 60%)\"\n */\nexport const mixColor = (\n color1: string,\n color2: string,\n percentage: number,\n colorSpace: 'srgb' | 'hsl' = 'srgb',\n percentage2?: number,\n): string => {\n return `color-mix(in ${colorSpace}, ${color1} ${percentage}%, ${color2} ${percentage2 ? percentage2 : 100 - percentage}%)`\n}\n\n/**\n * 将十六进制颜色转换为 RGB\n */\nexport const hexToRgb = (hex: string): { r: number; g: number; b: number } => {\n const r = parseInt(hex.slice(1, 3), 16)\n const g = parseInt(hex.slice(3, 5), 16)\n const b = parseInt(hex.slice(5, 7), 16)\n return { r, g, b }\n}\n","/**\n * 设置 html 根元素的 css 变量\n */\nexport const setCssVar = (k: string, v: string) => {\n document.documentElement.style.setProperty(k, v)\n}\n","/**\n * 安装开发环境代理劫持。\n *\n * 作用:\n * - 将所有绝对 URL(http/https)重写为 `/proxy?url=...`(默认前缀)\n * - 统一走本地开发代理,绕过 CORS,并方便调试与拦截请求\n *\n * 当前覆盖:\n * - fetch\n * - XMLHttpRequest\n * - img.src\n * - script.src\n * - link.href(如 stylesheet / preload)\n * - source.src(如 video / audio / picture)\n * - iframe.src\n *\n * 说明:\n * - 仅重写绝对 URL(http:// / https://)\n * - 相对路径不会处理\n * - 仅建议在开发环境使用\n * - 内部带防重复安装保护,避免 HMR 导致重复 hook\n */\nexport function setupDevProxyHook(prefix: string = '/proxy?url=') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((window as any).__DEV_PROXY_HOOKED__) return\n\n const rewrite = (url: string) => {\n if (/^http?:\\/\\//.test(url) || /^https?:\\/\\//.test(url)) {\n return `${prefix}${encodeURIComponent(url)}`\n }\n return url\n }\n\n const originFetch = window.fetch\n window.fetch = function (input, init) {\n if (input instanceof Request) {\n input = new Request(rewrite(input.url), input)\n return originFetch.call(this, input, init)\n }\n\n const url = rewrite(input.toString())\n return originFetch.call(this, url, init)\n }\n\n const originOpen = XMLHttpRequest.prototype.open\n XMLHttpRequest.prototype.open = function (\n method: string,\n url: string | URL,\n async?: boolean,\n username?: string | null | undefined,\n password?: string | null | undefined,\n ) {\n if (typeof url === 'string') {\n url = rewrite(url)\n } else {\n url = new URL(rewrite(url.href))\n }\n return originOpen.call(this, method, url, async ?? true, username, password)\n }\n\n /**\n * 通用属性 Hook\n *\n * 用于重写资源加载类元素的 src / href 属性\n */\n const hookUrlProperty = (proto: object, key: 'src' | 'href') => {\n const desc = Object.getOwnPropertyDescriptor(proto, key)\n if (!desc?.set) return\n\n Object.defineProperty(proto, key, {\n configurable: true,\n enumerable: desc.enumerable,\n get: desc.get,\n set(value: string) {\n return desc.set!.call(this, rewrite(value))\n },\n })\n }\n\n // 图片资源\n hookUrlProperty(HTMLImageElement.prototype, 'src')\n\n // 动态脚本资源\n hookUrlProperty(HTMLScriptElement.prototype, 'src')\n\n // 样式 / preload / prefetch\n hookUrlProperty(HTMLLinkElement.prototype, 'href')\n\n // video / audio / picture\n hookUrlProperty(HTMLSourceElement.prototype, 'src')\n\n // iframe 页面资源\n hookUrlProperty(HTMLIFrameElement.prototype, 'src')\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(window as any).__DEV_PROXY_HOOKED__ = true\n}\n","/**\n * 等待 <img> 加载完成\n */\nexport function whenImageLoaded(img: HTMLImageElement): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n if (img.dataset['state'] === 'loading') {\n img.src = img.dataset['src']!\n }\n\n if (img.complete && img.naturalWidth > 0) {\n resolve(img)\n return\n }\n\n const onLoad = () => {\n cleanup()\n resolve(img)\n }\n\n const onError = () => {\n cleanup()\n reject(new Error(`图片加载失败: ${img.src}`))\n }\n\n const cleanup = () => {\n img.removeEventListener('load', onLoad)\n img.removeEventListener('error', onError)\n }\n\n img.addEventListener('load', onLoad)\n img.addEventListener('error', onError)\n })\n}\n\n/**\n * 从 <img> 元素获取图片字节数据(ArrayBuffer)\n * @param img 已加载的 <img> 元素\n * @param type 图片类型,可选(默认 png)\n */\nexport async function getImageArrayBuffer(img: HTMLImageElement, type: string = 'image/png'): Promise<ArrayBuffer> {\n const canvas = document.createElement('canvas')\n canvas.width = img.naturalWidth\n canvas.height = img.naturalHeight\n const ctx = canvas.getContext('2d')\n if (!ctx) throw new Error('无法创建 Canvas 2D 上下文')\n ctx.drawImage(img, 0, 0)\n\n const blob: Blob = await new Promise((resolve, reject) => {\n canvas.toBlob((b) => (b ? resolve(b) : reject(new Error('toBlob 失败'))), type)\n })\n\n return await blob.arrayBuffer()\n}\n\n/**\n * 等待加载完成并获取字节数据\n */\nexport async function getImgArrayBufferAfterLoad(img: HTMLImageElement, type?: string): Promise<ArrayBuffer> {\n const loaded = await whenImageLoaded(img)\n return await getImageArrayBuffer(loaded, type)\n}\n","/**\n * 网络信息\n */\nexport interface NetworkInfo extends EventTarget {\n // 带宽(估算)\n downlink: number\n // 延迟(估算)\n rtt: number\n // 类型(估算)\n effectiveType: 'slow-2g' | '2g' | '3g' | '4g'\n}\n\n/**\n * 网络状态\n * - 'offline': 无网络\n * - 'online': 在线但不支持 NetworkInformation API\n * - NetworkInformation: 含详细网络信息\n */\nexport type NetworkState = 'offline' | Omit<NetworkInfo, keyof EventTarget> | 'online'\n\nfunction isConnection(obj: unknown): obj is NetworkInfo {\n return obj !== null && typeof obj === 'object' && 'downlink' in obj && 'rtt' in obj && 'effectiveType' in obj\n}\n\n/**\n * 获取网络信息\n */\nexport function getNetworkInfo(): NetworkState {\n if (!navigator.onLine) {\n return 'offline'\n }\n\n if ('connection' in navigator && isConnection(navigator.connection)) {\n // 现代 Web API 直接获取网络连接的信息\n const connection = navigator.connection\n return {\n downlink: connection.downlink,\n rtt: connection.rtt,\n effectiveType: connection.effectiveType,\n }\n } else {\n return 'online'\n }\n}\n\n/**\n * 监听网络状态变化\n * @param listener 监听器\n * @returns 成功监听时返回解绑函数\n */\nexport function onNetworkChange(listener: (info: NetworkState) => void) {\n const handleChange = () => {\n listener(getNetworkInfo())\n }\n\n if ('connection' in navigator && isConnection(navigator.connection)) {\n // 现代 Web API\n const connection = navigator.connection\n connection.addEventListener('change', handleChange)\n return () => connection.removeEventListener('change', handleChange)\n } else {\n window.addEventListener('online', handleChange)\n window.addEventListener('offline', handleChange)\n return () => {\n window.removeEventListener('online', handleChange)\n window.removeEventListener('offline', handleChange)\n }\n }\n}\n","/** 可见性改变的监听器 */\nexport interface VisibilityChangeListener {\n (hidden: boolean): void\n}\n\n/**\n * 监听页面可见性变化(兼容旧的IE/Chrome)\n * @param listener 监听器\n * @returns 成功监听时返回解绑函数\n */\nexport function onVisibilityChange(listener: VisibilityChangeListener) {\n let hiddenPropName: string | undefined = undefined,\n hiddenEventName: string | undefined = undefined\n\n if (typeof document.hidden !== 'undefined') {\n // 现代 Web API\n hiddenPropName = 'hidden'\n hiddenEventName = 'visibilitychange'\n } else if ('msHidden' in document && typeof document.msHidden !== 'undefined') {\n // 旧 IE\n hiddenPropName = 'msHidden'\n hiddenEventName = 'msvisibilitychange'\n } else if ('webkitHidden' in document && typeof document.webkitHidden !== 'undefined') {\n // 旧 Chrome\n hiddenPropName = 'webkitHidden'\n hiddenEventName = 'webkitvisibilitychange'\n }\n\n if (!hiddenPropName || !hiddenEventName) {\n return null\n }\n\n const handler = () => {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n listener(document[hiddenPropName])\n }\n\n document.addEventListener(hiddenEventName, handler)\n\n return () => {\n document.removeEventListener(hiddenEventName, handler)\n }\n}\n","/**\n * 滚动元素到屏幕中心\n * @param el\n */\nexport async function humanScrollElIntoCenter(el: HTMLElement) {\n if (!el) return\n\n const rect = el.getBoundingClientRect()\n const doc = document.documentElement\n const body = document.body\n\n const scrollX = window.scrollX || doc.scrollLeft || body.scrollLeft\n const scrollY = window.scrollY || doc.scrollTop || body.scrollTop\n\n const viewW = window.innerWidth\n const viewH = window.innerHeight\n\n // 目标中心点相对页面的位置\n const targetX = rect.left + scrollX + rect.width / 2 - viewW / 2\n const targetY = rect.top + scrollY + rect.height / 2 - viewH / 2\n\n const maxX = Math.max(0, body.scrollWidth - viewW)\n const maxY = Math.max(0, body.scrollHeight - viewH)\n\n // 页面不需要滚动\n if (maxX === 0 && maxY === 0) return\n\n // 水平滚动:仅在可滚动时\n const newX = maxX > 0 ? Math.min(Math.max(targetX, 0), maxX) : scrollX\n // 垂直滚动\n const newY = maxY > 0 ? Math.min(Math.max(targetY, 0), maxY) : scrollY\n\n // 判断是否真正需要滚动\n const needScrollX = Math.abs(window.scrollX - newX) > 1\n const needScrollY = Math.abs(window.scrollY - newY) > 1\n if (!needScrollX && !needScrollY) return\n\n await humanScrollTo(newX, newY)\n}\n\n/**\n * 等待滚动\n */\nexport function waitScrollTo(targetX: number, targetY: number): Promise<void> {\n return new Promise((resolve) => {\n const currentX = window.scrollX\n const currentY = window.scrollY\n\n // 若无需滚动\n if (Math.abs(currentX - targetX) < 1 && Math.abs(currentY - targetY) < 1) {\n resolve()\n return\n }\n\n let timer: number | undefined\n let finished = false\n\n const cleanup = () => {\n if (finished) return\n finished = true\n window.removeEventListener('scroll', handler)\n if (timer) clearTimeout(timer)\n resolve()\n }\n\n const handler = () => {\n if (timer) clearTimeout(timer)\n // 若 50ms 内无新滚动事件,则视为滚动结束\n timer = window.setTimeout(cleanup, 50)\n }\n\n // 启动兜底超时(比如滚动事件根本不触发)\n const failSafe = window.setTimeout(() => {\n console.debug('[waitScrollTo] fallback timeout reached')\n cleanup()\n }, 1000)\n\n const cleanupWithTimeout = () => {\n cleanup()\n clearTimeout(failSafe)\n }\n\n // 替换 cleanup,确保清理超时器\n const finalHandler = () => {\n if (timer) clearTimeout(timer)\n timer = window.setTimeout(cleanupWithTimeout, 50)\n }\n\n // 注册事件\n window.addEventListener('scroll', finalHandler, { passive: true })\n\n // 立即触发滚动\n window.scrollTo({ left: targetX, top: targetY })\n\n // 有时浏览器同步滚动,不触发 scroll 事件\n requestAnimationFrame(() => {\n const nowX = window.scrollX\n const nowY = window.scrollY\n if (Math.abs(nowX - targetX) < 1 && Math.abs(nowY - targetY) < 1) {\n cleanupWithTimeout()\n }\n })\n })\n}\n\n/**\n * 模拟人类手感滚动到指定位置\n */\nexport async function humanScrollTo(targetX: number, targetY: number): Promise<void> {\n return new Promise<void>((resolve) => {\n let currentX = window.scrollX\n let currentY = window.scrollY\n\n async function step() {\n const dx = targetX - currentX\n const dy = targetY - currentY\n\n // 如果距离足够小,直接跳到目标结束\n if (Math.abs(dx) < 1 && Math.abs(dy) < 1) {\n window.scrollTo(targetX, targetY)\n resolve()\n return\n }\n\n // 随机步长 (最小 2px,最大剩余距离的 20%)\n const stepX = Math.sign(dx) * Math.min(Math.max(2, Math.random() * Math.abs(dx) * 0.2), Math.abs(dx))\n const stepY = Math.sign(dy) * Math.min(Math.max(2, Math.random() * Math.abs(dy) * 0.2), Math.abs(dy))\n\n currentX += stepX\n currentY += stepY\n await waitScrollTo(currentX, currentY)\n\n // 随机短暂停顿 10~30ms\n const delay = 10 + Math.random() * 20\n setTimeout(step, delay)\n }\n\n step()\n })\n}\n"],"mappings":"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","names":["mixColor","color1","color2","percentage","colorSpace","percentage2","hexToRgb","hex","r","g","b","setCssVar","k","v","setupDevProxyHook","prefix","rewrite","url","originFetch","input","init","originOpen","method","async","username","password","hookUrlProperty","proto","key","desc","value","whenImageLoaded","img","resolve","reject","onLoad","cleanup","onError","getImageArrayBuffer","type","canvas","ctx","b","getImgArrayBufferAfterLoad","loaded","isConnection","obj","getNetworkInfo","connection","onNetworkChange","listener","handleChange","onVisibilityChange","listener","hiddenPropName","hiddenEventName","handler","humanScrollElIntoCenter","el","rect","doc","body","scrollX","scrollY","viewW","viewH","targetX","targetY","maxX","maxY","newX","newY","needScrollX","needScrollY","humanScrollTo","waitScrollTo","resolve","currentX","currentY","timer","finished","cleanup","handler","failSafe","cleanupWithTimeout","finalHandler","nowX","nowY","step","dx","dy","stepX","stepY","delay"]}
package/dist/node.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var W=Object.create;var d=Object.defineProperty;var Q=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var V=Object.getPrototypeOf,q=Object.prototype.hasOwnProperty;var Y=(t,e)=>{for(var r in e)d(t,r,{get:e[r],enumerable:!0})},$=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of _(e))!q.call(t,o)&&o!==r&&d(t,o,{get:()=>e[o],enumerable:!(n=Q(e,o))||n.enumerable});return t};var s=(t,e,r)=>(r=t!=null?W(V(t)):{},$(e||!t||!t.__esModule?d(r,"default",{value:t,enumerable:!0}):r,t)),X=t=>$(d({},"__esModule",{value:!0}),t);var yt={};Y(yt,{copyFile:()=>pt,deleteFiles:()=>rt,downloadFile:()=>nt,emptyDirectory:()=>v,ensureDir:()=>m,ensureDirSync:()=>et,execWinCmd:()=>c,existsFile:()=>tt,exportRegedit:()=>dt,findFiles:()=>B,findFilesByPrefixAndSuffix:()=>ot,formatFileSizeFromKB:()=>at,getDirSize:()=>S,getEnv:()=>Z,getFileSizeKB:()=>ft,importRegedit:()=>xt,isFile:()=>f,isFileNotFoundError:()=>h,openRegedit:()=>gt,readJSONFile:()=>A,readOrInitJSON:()=>st,showInExplorer:()=>lt,updateJSON:()=>it,writeJSONFile:()=>O});module.exports=X(yt);function Z(){let t={};for(let e in process.env)t[e]=process.env[e];return t}var x=s(require("fs/promises"),1),k=require("fs");async function f(t){try{return(await x.default.stat(t)).isFile()}catch{return!1}}async function tt(t,e){try{return x.default.access(t,e),!0}catch{return!1}}function et(t){(0,k.mkdirSync)(t,{recursive:!0})}async function m(t){await x.default.mkdir(t,{recursive:!0})}function h(t){return typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT"}var p=s(require("fs/promises"),1),j=s(require("path"),1);async function v(t){let e=[],r=await p.default.readdir(t,{withFileTypes:!0});for(let n of r){let o=j.default.join(t,n.name);n.isDirectory()?(e.push(...await v(o)),await p.default.rmdir(o)):await p.default.unlink(o),e.push(o)}return e}async function rt(t){return(await Promise.allSettled(t.map(async r=>(await p.default.unlink(r),r)))).filter(r=>r.status==="fulfilled").map(r=>r.value)}var D=require("stream/promises"),z=require("fs"),N=s(require("path"),1);async function nt(t,e){let r=N.default.resolve(e),n=await fetch(t);if(!n.ok||!n.body)throw new Error(`\u4E0B\u8F7D\u5931\u8D25: ${n.status}`);await(0,D.pipeline)(n.body,(0,z.createWriteStream)(r))}var b=s(require("fs/promises"),1),T=s(require("path"),1);async function ot(t,e,r){return(await b.default.readdir(t,{withFileTypes:!0})).filter(n=>n.isFile()&&n.name.startsWith(e||"")&&n.name.endsWith(r||"")).map(n=>T.default.join(t,n.name))}async function B(t,e){let r=[],n=await b.default.readdir(t,{withFileTypes:!0});for(let o of n){let i=T.default.join(t,o.name);o.isDirectory()?r.push(...await B(i,e)):(typeof e=="string"&&o.name===e||typeof e=="function"&&e(o.name,i))&&r.push(i)}return r}var u=s(require("fs/promises"),1),E=s(require("path"),1);async function A(t){if(!await f(t))throw new Error("\u6587\u4EF6\u4E0D\u5B58\u5728");let e=await u.default.readFile(E.default.resolve(t),"utf-8");return JSON.parse(e)}async function O(t,e){let r=`${t}.tmp.${Date.now()}`,n=JSON.stringify(e,null,2);await u.default.writeFile(r,n,"utf-8"),await u.default.rename(r,t)}async function it(t,e){let r=await A(t),n=e(r);return await O(t,n),n}async function st(t,e){try{let r=await u.default.readFile(t,"utf-8");return JSON.parse(r)}catch(r){if(!h(r))throw r;let n=await e();return await m(E.default.dirname(t)),await u.default.writeFile(t,JSON.stringify(n,null,2),"utf-8"),n}}function K(t,e,r,n=""){if(!Number.isFinite(t))return{size:0,unit:"",text:n};let o=t,i=0;for(;o>=e&&i<r.length-1;)o/=e,i++;return{size:o,unit:r[i],text:`${o.toFixed(2).replace(/\.?0+$/,"")} ${r[i]}`}}var l=s(require("fs/promises"),1),M=s(require("path"),1);function at(t,e=""){let{size:r,unit:n,text:o}=K(t,1024,["KB","MB","GB"],e);if(o===e)return e;let i=Math.floor(r),a;return i>99?a=0:i>9?a=1:a=2,`${Math.round(r*10**a)/10**a} ${n}`}async function ct(t){try{return(await l.default.stat(t)).size}catch{return 0}}async function ut(t){try{return(await l.default.lstat(t)).size}catch{return 0}}async function S(t){let e;try{e=await l.default.readdir(t,{withFileTypes:!0})}catch{return 0}let r=[];for(let o of e){let i=M.default.join(t,o.name);if(o.isDirectory()){r.push(S(i));continue}if(o.isSymbolicLink()){r.push(ut(i));continue}r.push(ct(i))}return(await Promise.allSettled(r)).reduce((o,i)=>o+(i.status==="fulfilled"?i.value:0),0)}async function ft(t){try{let e=await l.default.stat(t);return e.isDirectory()?await S(t)/1024:e.size/1024}catch{return 0}}function g(t){let e=new Error(t??"\u64CD\u4F5C\u5DF2\u53D6\u6D88");return e.name="AbortError",e}var C=require("child_process"),P=s(require("iconv-lite"),1);async function c(t,e){return new Promise((r,n)=>{if(e?.signal?.aborted)throw g();let o=null,i=(0,C.exec)(`${t}`,{encoding:"buffer"},(y,G,J)=>{let R=P.decode(G,"cp936"),H=P.decode(J,"cp936");o&&e?.signal?.removeEventListener("abort",o);let w=y?Number(y.code??0):0;(e?.codeIsSuccess?!e.codeIsSuccess(w):w!==0)?n(new Error(`\u547D\u4EE4\u884C\u6267\u884C\u51FA\u9519 (${w}): ${H||R}`)):r(R)}),a;o=()=>{i.kill("SIGTERM"),a=setTimeout(()=>{i.kill("SIGKILL")},3e3),n(g())},e?.signal&&e.signal.addEventListener("abort",o),i.on("close",()=>{a!==void 0&&clearTimeout(a),e?.signal?.removeEventListener("abort",o)})})}var L=s(require("path"),1);async function pt(t,e,r){let n=L.default.resolve(t),o=L.default.resolve(e),i;await f(t)?(i=`copy "${n}" "${o}"`,await c(i,{signal:r})):(i=`robocopy "${n}" "${o}" /E /NFL /NDL /NJH /NJS /NC /NS /NP`,await c(i,{codeIsSuccess:a=>a<8,signal:r}))}var U=s(require("path"),1),I=s(require("fs/promises"),1);async function lt(t){t=U.default.resolve(t),(await I.stat(t)).isDirectory()?await c(`start "" "${t}"`):await c(`start "" explorer /select,"${t}"`)}var F=s(require("path"),1);async function gt(t){return c(`taskkill /f /im regedit.exe & REG ADD "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit" /v "LastKey" /d "${t}" /f & regedit`)}async function dt(t,e){e=F.default.resolve(e),await m(t),await c(`reg export "${t}" "${e}" /y`,void 0)}async function xt(t,e){await c(`reg import "${F.default.resolve(e)}"`,void 0)}0&&(module.exports={copyFile,deleteFiles,downloadFile,emptyDirectory,ensureDir,ensureDirSync,execWinCmd,existsFile,exportRegedit,findFiles,findFilesByPrefixAndSuffix,formatFileSizeFromKB,getDirSize,getEnv,getFileSizeKB,importRegedit,isFile,isFileNotFoundError,openRegedit,readJSONFile,readOrInitJSON,showInExplorer,updateJSON,writeJSONFile});
1
+ "use strict";var W=Object.create;var d=Object.defineProperty;var Q=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var V=Object.getPrototypeOf,q=Object.prototype.hasOwnProperty;var Y=(t,e)=>{for(var r in e)d(t,r,{get:e[r],enumerable:!0})},$=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of _(e))!q.call(t,o)&&o!==r&&d(t,o,{get:()=>e[o],enumerable:!(n=Q(e,o))||n.enumerable});return t};var s=(t,e,r)=>(r=t!=null?W(V(t)):{},$(e||!t||!t.__esModule?d(r,"default",{value:t,enumerable:!0}):r,t)),X=t=>$(d({},"__esModule",{value:!0}),t);var xt={};Y(xt,{copyFile:()=>pt,deleteFiles:()=>rt,downloadFile:()=>nt,emptyDirectory:()=>A,ensureDir:()=>m,ensureDirSync:()=>et,execWinCmd:()=>c,existsFile:()=>tt,exportRegedit:()=>dt,findFiles:()=>N,findFilesByPrefixAndSuffix:()=>ot,formatFileSizeFromKB:()=>at,getDirSize:()=>P,getEnv:()=>Z,getFileSizeKB:()=>ft,importRegedit:()=>yt,isFile:()=>f,isFileNotFoundError:()=>h,openRegedit:()=>gt,readJSONFile:()=>B,readOrInitJSON:()=>st,showInExplorer:()=>lt,updateJSON:()=>it,writeJSONFile:()=>K});module.exports=X(xt);function Z(){let t={};for(let e in process.env)t[e]=process.env[e];return t}var y=s(require("fs/promises"),1),k=require("fs");async function f(t){try{return(await y.default.stat(t)).isFile()}catch{return!1}}async function tt(t,e){try{return y.default.access(t,e),!0}catch{return!1}}function et(t){(0,k.mkdirSync)(t,{recursive:!0})}async function m(t){await y.default.mkdir(t,{recursive:!0})}function h(t){return typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT"}var p=s(require("fs/promises"),1),j=s(require("path"),1);async function A(t){let e=[],r=await p.default.readdir(t,{withFileTypes:!0});for(let n of r){let o=j.default.join(t,n.name);n.isDirectory()?(e.push(...await A(o)),await p.default.rmdir(o)):await p.default.unlink(o),e.push(o)}return e}async function rt(t){return(await Promise.allSettled(t.map(async r=>(await p.default.unlink(r),r)))).filter(r=>r.status==="fulfilled").map(r=>r.value)}var D=require("stream/promises"),z=require("fs"),v=s(require("path"),1);async function nt(t,e){let r=v.default.resolve(e),n=await fetch(t);if(!n.ok||!n.body)throw new Error(`\u4E0B\u8F7D\u5931\u8D25: ${n.status}`);await(0,D.pipeline)(n.body,(0,z.createWriteStream)(r))}var b=s(require("fs/promises"),1),T=s(require("path"),1);async function ot(t,e,r){return(await b.default.readdir(t,{withFileTypes:!0})).filter(n=>n.isFile()&&n.name.startsWith(e||"")&&n.name.endsWith(r||"")).map(n=>T.default.join(t,n.name))}async function N(t,e){let r=[],n=await b.default.readdir(t,{withFileTypes:!0});for(let o of n){let i=T.default.join(t,o.name);o.isDirectory()?r.push(...await N(i,e)):(typeof e=="string"&&o.name===e||typeof e=="function"&&e(o.name,i))&&r.push(i)}return r}var u=s(require("fs/promises"),1),E=s(require("path"),1);async function B(t){if(!await f(t))throw new Error("\u6587\u4EF6\u4E0D\u5B58\u5728");let e=await u.default.readFile(E.default.resolve(t),"utf-8");return JSON.parse(e)}async function K(t,e){let r=`${t}.tmp.${Date.now()}`,n=JSON.stringify(e,null,2);await u.default.writeFile(r,n,"utf-8"),await u.default.rename(r,t)}async function it(t,e){let r=await B(t),n=e(r);return await K(t,n),n}async function st(t,e){try{let r=await u.default.readFile(t,"utf-8");return JSON.parse(r)}catch(r){if(!h(r))throw r;let n=await e();return await m(E.default.dirname(t)),await u.default.writeFile(t,JSON.stringify(n,null,2),"utf-8"),n}}function O(t,e,r,n=""){if(!Number.isFinite(t))return{size:0,unit:"",text:n};let o=t,i=0;for(;o>=e&&i<r.length-1;)o/=e,i++;return{size:o,unit:r[i],text:`${o.toFixed(2).replace(/\.?0+$/,"")} ${r[i]}`}}var l=s(require("fs/promises"),1),U=s(require("path"),1);function at(t,e=""){let{size:r,unit:n,text:o}=O(t,1024,["KB","MB","GB"],e);if(o===e)return e;let i=Math.floor(r),a;return i>99?a=0:i>9?a=1:a=2,`${Math.round(r*10**a)/10**a} ${n}`}async function ct(t){try{return(await l.default.stat(t)).size}catch{return 0}}async function ut(t){try{return(await l.default.lstat(t)).size}catch{return 0}}async function P(t){let e;try{e=await l.default.readdir(t,{withFileTypes:!0})}catch{return 0}let r=[];for(let o of e){let i=U.default.join(t,o.name);if(o.isDirectory()){r.push(P(i));continue}if(o.isSymbolicLink()){r.push(ut(i));continue}r.push(ct(i))}return(await Promise.allSettled(r)).reduce((o,i)=>o+(i.status==="fulfilled"?i.value:0),0)}async function ft(t){try{let e=await l.default.stat(t);return e.isDirectory()?await P(t)/1024:e.size/1024}catch{return 0}}function g(t){let e=new Error(t??"\u64CD\u4F5C\u5DF2\u53D6\u6D88");return e.name="AbortError",e}var M=require("child_process"),S=s(require("iconv-lite"),1);async function c(t,e){return new Promise((r,n)=>{if(e?.signal?.aborted)throw g();let o=null,i=(0,M.exec)(`${t}`,{encoding:"buffer"},(x,G,H)=>{let R=S.decode(G,"cp936"),J=S.decode(H,"cp936");o&&e?.signal?.removeEventListener("abort",o);let w=x?Number(x.code??0):0;(e?.codeIsSuccess?!e.codeIsSuccess(w):w!==0)?n(new Error(`\u547D\u4EE4\u884C\u6267\u884C\u51FA\u9519 (${w}): ${J||R}`)):r(R)}),a;o=()=>{i.kill("SIGTERM"),a=setTimeout(()=>{i.kill("SIGKILL")},3e3),n(g())},e?.signal&&e.signal.addEventListener("abort",o),i.on("close",()=>{a!==void 0&&clearTimeout(a),e?.signal?.removeEventListener("abort",o)})})}var L=s(require("path"),1);async function pt(t,e,r){let n=L.default.resolve(t),o=L.default.resolve(e),i;await f(t)?(i=`copy "${n}" "${o}"`,await c(i,{signal:r})):(i=`robocopy "${n}" "${o}" /E /NFL /NDL /NJH /NJS /NC /NS /NP`,await c(i,{codeIsSuccess:a=>a<8,signal:r}))}var C=s(require("path"),1),I=s(require("fs/promises"),1);async function lt(t){t=C.default.resolve(t),(await I.stat(t)).isDirectory()?await c(`start "" "${t}"`):await c(`start "" explorer /select,"${t}"`)}var F=s(require("path"),1);async function gt(t){return c(`taskkill /f /im regedit.exe & REG ADD "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit" /v "LastKey" /d "${t}" /f & regedit`)}async function dt(t,e){e=F.default.resolve(e),await m(t),await c(`reg export "${t}" "${e}" /y`,void 0)}async function yt(t,e){await c(`reg import "${F.default.resolve(e)}"`,void 0)}0&&(module.exports={copyFile,deleteFiles,downloadFile,emptyDirectory,ensureDir,ensureDirSync,execWinCmd,existsFile,exportRegedit,findFiles,findFilesByPrefixAndSuffix,formatFileSizeFromKB,getDirSize,getEnv,getFileSizeKB,importRegedit,isFile,isFileNotFoundError,openRegedit,readJSONFile,readOrInitJSON,showInExplorer,updateJSON,writeJSONFile});
2
2
  //# sourceMappingURL=node.cjs.map
package/dist/node.js CHANGED
@@ -1,2 +1,2 @@
1
- function W(){let t={};for(let e in process.env)t[e]=process.env[e];return t}import x from"fs/promises";import{mkdirSync as v}from"fs";async function f(t){try{return(await x.stat(t)).isFile()}catch{return!1}}async function q(t,e){try{return x.access(t,e),!0}catch{return!1}}function Y(t){v(t,{recursive:!0})}async function m(t){await x.mkdir(t,{recursive:!0})}function h(t){return typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT"}import p from"fs/promises";import D from"path";async function z(t){let e=[],r=await p.readdir(t,{withFileTypes:!0});for(let n of r){let o=D.join(t,n.name);n.isDirectory()?(e.push(...await z(o)),await p.rmdir(o)):await p.unlink(o),e.push(o)}return e}async function et(t){return(await Promise.allSettled(t.map(async r=>(await p.unlink(r),r)))).filter(r=>r.status==="fulfilled").map(r=>r.value)}import{pipeline as N}from"stream/promises";import{createWriteStream as B}from"fs";import A from"path";async function st(t,e){let r=A.resolve(e),n=await fetch(t);if(!n.ok||!n.body)throw new Error(`\u4E0B\u8F7D\u5931\u8D25: ${n.status}`);await N(n.body,B(r))}import b from"fs/promises";import T from"path";async function ft(t,e,r){return(await b.readdir(t,{withFileTypes:!0})).filter(n=>n.isFile()&&n.name.startsWith(e||"")&&n.name.endsWith(r||"")).map(n=>T.join(t,n.name))}async function O(t,e){let r=[],n=await b.readdir(t,{withFileTypes:!0});for(let o of n){let i=T.join(t,o.name);o.isDirectory()?r.push(...await O(i,e)):(typeof e=="string"&&o.name===e||typeof e=="function"&&e(o.name,i))&&r.push(i)}return r}import c from"fs/promises";import E from"path";async function K(t){if(!await f(t))throw new Error("\u6587\u4EF6\u4E0D\u5B58\u5728");let e=await c.readFile(E.resolve(t),"utf-8");return JSON.parse(e)}async function M(t,e){let r=`${t}.tmp.${Date.now()}`,n=JSON.stringify(e,null,2);await c.writeFile(r,n,"utf-8"),await c.rename(r,t)}async function dt(t,e){let r=await K(t),n=e(r);return await M(t,n),n}async function xt(t,e){try{let r=await c.readFile(t,"utf-8");return JSON.parse(r)}catch(r){if(!h(r))throw r;let n=await e();return await m(E.dirname(t)),await c.writeFile(t,JSON.stringify(n,null,2),"utf-8"),n}}function S(t,e,r,n=""){if(!Number.isFinite(t))return{size:0,unit:"",text:n};let o=t,i=0;for(;o>=e&&i<r.length-1;)o/=e,i++;return{size:o,unit:r[i],text:`${o.toFixed(2).replace(/\.?0+$/,"")} ${r[i]}`}}import l from"fs/promises";import C from"path";function Et(t,e=""){let{size:r,unit:n,text:o}=S(t,1024,["KB","MB","GB"],e);if(o===e)return e;let i=Math.floor(r),s;return i>99?s=0:i>9?s=1:s=2,`${Math.round(r*10**s)/10**s} ${n}`}async function U(t){try{return(await l.stat(t)).size}catch{return 0}}async function I(t){try{return(await l.lstat(t)).size}catch{return 0}}async function P(t){let e;try{e=await l.readdir(t,{withFileTypes:!0})}catch{return 0}let r=[];for(let o of e){let i=C.join(t,o.name);if(o.isDirectory()){r.push(P(i));continue}if(o.isSymbolicLink()){r.push(I(i));continue}r.push(U(i))}return(await Promise.allSettled(r)).reduce((o,i)=>o+(i.status==="fulfilled"?i.value:0),0)}async function St(t){try{let e=await l.stat(t);return e.isDirectory()?await P(t)/1024:e.size/1024}catch{return 0}}function u(t){let e=new Error(t??"\u64CD\u4F5C\u5DF2\u53D6\u6D88");return e.name="AbortError",e}import{exec as J}from"child_process";import*as y from"iconv-lite";async function a(t,e){return new Promise((r,n)=>{if(e?.signal?.aborted)throw u();let o=null,i=J(`${t}`,{encoding:"buffer"},(g,$,k)=>{let w=y.decode($,"cp936"),j=y.decode(k,"cp936");o&&e?.signal?.removeEventListener("abort",o);let d=g?Number(g.code??0):0;(e?.codeIsSuccess?!e.codeIsSuccess(d):d!==0)?n(new Error(`\u547D\u4EE4\u884C\u6267\u884C\u51FA\u9519 (${d}): ${j||w}`)):r(w)}),s;o=()=>{i.kill("SIGTERM"),s=setTimeout(()=>{i.kill("SIGKILL")},3e3),n(u())},e?.signal&&e.signal.addEventListener("abort",o),i.on("close",()=>{s!==void 0&&clearTimeout(s),e?.signal?.removeEventListener("abort",o)})})}import L from"path";async function ze(t,e,r){let n=L.resolve(t),o=L.resolve(e),i;await f(t)?(i=`copy "${n}" "${o}"`,await a(i,{signal:r})):(i=`robocopy "${n}" "${o}" /E /NFL /NDL /NJH /NJS /NC /NS /NP`,await a(i,{codeIsSuccess:s=>s<8,signal:r}))}import H from"path";import*as F from"fs/promises";async function Oe(t){t=H.resolve(t),(await F.stat(t)).isDirectory()?await a(`start "" "${t}"`):await a(`start "" explorer /select,"${t}"`)}import R from"path";async function Ie(t){return a(`taskkill /f /im regedit.exe & REG ADD "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit" /v "LastKey" /d "${t}" /f & regedit`)}async function Ge(t,e){e=R.resolve(e),await m(t),await a(`reg export "${t}" "${e}" /y`,void 0)}async function Je(t,e){await a(`reg import "${R.resolve(e)}"`,void 0)}export{ze as copyFile,et as deleteFiles,st as downloadFile,z as emptyDirectory,m as ensureDir,Y as ensureDirSync,a as execWinCmd,q as existsFile,Ge as exportRegedit,O as findFiles,ft as findFilesByPrefixAndSuffix,Et as formatFileSizeFromKB,P as getDirSize,W as getEnv,St as getFileSizeKB,Je as importRegedit,f as isFile,h as isFileNotFoundError,Ie as openRegedit,K as readJSONFile,xt as readOrInitJSON,Oe as showInExplorer,dt as updateJSON,M as writeJSONFile};
1
+ function W(){let t={};for(let e in process.env)t[e]=process.env[e];return t}import y from"fs/promises";import{mkdirSync as A}from"fs";async function f(t){try{return(await y.stat(t)).isFile()}catch{return!1}}async function q(t,e){try{return y.access(t,e),!0}catch{return!1}}function Y(t){A(t,{recursive:!0})}async function m(t){await y.mkdir(t,{recursive:!0})}function h(t){return typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT"}import p from"fs/promises";import D from"path";async function z(t){let e=[],r=await p.readdir(t,{withFileTypes:!0});for(let n of r){let o=D.join(t,n.name);n.isDirectory()?(e.push(...await z(o)),await p.rmdir(o)):await p.unlink(o),e.push(o)}return e}async function et(t){return(await Promise.allSettled(t.map(async r=>(await p.unlink(r),r)))).filter(r=>r.status==="fulfilled").map(r=>r.value)}import{pipeline as v}from"stream/promises";import{createWriteStream as N}from"fs";import B from"path";async function st(t,e){let r=B.resolve(e),n=await fetch(t);if(!n.ok||!n.body)throw new Error(`\u4E0B\u8F7D\u5931\u8D25: ${n.status}`);await v(n.body,N(r))}import b from"fs/promises";import T from"path";async function ft(t,e,r){return(await b.readdir(t,{withFileTypes:!0})).filter(n=>n.isFile()&&n.name.startsWith(e||"")&&n.name.endsWith(r||"")).map(n=>T.join(t,n.name))}async function K(t,e){let r=[],n=await b.readdir(t,{withFileTypes:!0});for(let o of n){let i=T.join(t,o.name);o.isDirectory()?r.push(...await K(i,e)):(typeof e=="string"&&o.name===e||typeof e=="function"&&e(o.name,i))&&r.push(i)}return r}import c from"fs/promises";import E from"path";async function O(t){if(!await f(t))throw new Error("\u6587\u4EF6\u4E0D\u5B58\u5728");let e=await c.readFile(E.resolve(t),"utf-8");return JSON.parse(e)}async function U(t,e){let r=`${t}.tmp.${Date.now()}`,n=JSON.stringify(e,null,2);await c.writeFile(r,n,"utf-8"),await c.rename(r,t)}async function dt(t,e){let r=await O(t),n=e(r);return await U(t,n),n}async function yt(t,e){try{let r=await c.readFile(t,"utf-8");return JSON.parse(r)}catch(r){if(!h(r))throw r;let n=await e();return await m(E.dirname(t)),await c.writeFile(t,JSON.stringify(n,null,2),"utf-8"),n}}function P(t,e,r,n=""){if(!Number.isFinite(t))return{size:0,unit:"",text:n};let o=t,i=0;for(;o>=e&&i<r.length-1;)o/=e,i++;return{size:o,unit:r[i],text:`${o.toFixed(2).replace(/\.?0+$/,"")} ${r[i]}`}}import l from"fs/promises";import M from"path";function Et(t,e=""){let{size:r,unit:n,text:o}=P(t,1024,["KB","MB","GB"],e);if(o===e)return e;let i=Math.floor(r),s;return i>99?s=0:i>9?s=1:s=2,`${Math.round(r*10**s)/10**s} ${n}`}async function C(t){try{return(await l.stat(t)).size}catch{return 0}}async function I(t){try{return(await l.lstat(t)).size}catch{return 0}}async function S(t){let e;try{e=await l.readdir(t,{withFileTypes:!0})}catch{return 0}let r=[];for(let o of e){let i=M.join(t,o.name);if(o.isDirectory()){r.push(S(i));continue}if(o.isSymbolicLink()){r.push(I(i));continue}r.push(C(i))}return(await Promise.allSettled(r)).reduce((o,i)=>o+(i.status==="fulfilled"?i.value:0),0)}async function Pt(t){try{let e=await l.stat(t);return e.isDirectory()?await S(t)/1024:e.size/1024}catch{return 0}}function u(t){let e=new Error(t??"\u64CD\u4F5C\u5DF2\u53D6\u6D88");return e.name="AbortError",e}import{exec as H}from"child_process";import*as x from"iconv-lite";async function a(t,e){return new Promise((r,n)=>{if(e?.signal?.aborted)throw u();let o=null,i=H(`${t}`,{encoding:"buffer"},(g,$,k)=>{let w=x.decode($,"cp936"),j=x.decode(k,"cp936");o&&e?.signal?.removeEventListener("abort",o);let d=g?Number(g.code??0):0;(e?.codeIsSuccess?!e.codeIsSuccess(d):d!==0)?n(new Error(`\u547D\u4EE4\u884C\u6267\u884C\u51FA\u9519 (${d}): ${j||w}`)):r(w)}),s;o=()=>{i.kill("SIGTERM"),s=setTimeout(()=>{i.kill("SIGKILL")},3e3),n(u())},e?.signal&&e.signal.addEventListener("abort",o),i.on("close",()=>{s!==void 0&&clearTimeout(s),e?.signal?.removeEventListener("abort",o)})})}import L from"path";async function Ne(t,e,r){let n=L.resolve(t),o=L.resolve(e),i;await f(t)?(i=`copy "${n}" "${o}"`,await a(i,{signal:r})):(i=`robocopy "${n}" "${o}" /E /NFL /NDL /NJH /NJS /NC /NS /NP`,await a(i,{codeIsSuccess:s=>s<8,signal:r}))}import J from"path";import*as F from"fs/promises";async function Ue(t){t=J.resolve(t),(await F.stat(t)).isDirectory()?await a(`start "" "${t}"`):await a(`start "" explorer /select,"${t}"`)}import R from"path";async function He(t){return a(`taskkill /f /im regedit.exe & REG ADD "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit" /v "LastKey" /d "${t}" /f & regedit`)}async function Je(t,e){e=R.resolve(e),await m(t),await a(`reg export "${t}" "${e}" /y`,void 0)}async function We(t,e){await a(`reg import "${R.resolve(e)}"`,void 0)}export{Ne as copyFile,et as deleteFiles,st as downloadFile,z as emptyDirectory,m as ensureDir,Y as ensureDirSync,a as execWinCmd,q as existsFile,Je as exportRegedit,K as findFiles,ft as findFilesByPrefixAndSuffix,Et as formatFileSizeFromKB,S as getDirSize,W as getEnv,Pt as getFileSizeKB,We as importRegedit,f as isFile,h as isFileNotFoundError,He as openRegedit,O as readJSONFile,yt as readOrInitJSON,Ue as showInExplorer,dt as updateJSON,U as writeJSONFile};
2
2
  //# sourceMappingURL=node.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ybgnb/utils",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "author": "hzhilong",
5
5
  "private": false,
6
6
  "description": "自用工具库",