@ybgnb/utils 0.1.8 → 0.2.0
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/LICENSE +1 -1
- package/dist/core.cjs +2 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +369 -0
- package/dist/core.d.ts +369 -2
- package/dist/core.js +1 -298
- package/dist/core.js.map +1 -1
- package/dist/dom.cjs +2 -0
- package/dist/dom.cjs.map +1 -0
- package/dist/dom.d.cts +105 -0
- package/dist/dom.d.ts +105 -2
- package/dist/dom.js +1 -133
- package/dist/dom.js.map +1 -1
- package/dist/node.cjs +2 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.cts +153 -0
- package/dist/node.d.ts +153 -2
- package/dist/node.js +1 -200
- package/dist/node.js.map +1 -1
- package/package.json +11 -11
- package/dist/core/error/common-error.d.ts +0 -8
- package/dist/core/index.d.ts +0 -17
- package/dist/core/result/biz-result.d.ts +0 -17
- package/dist/core/result/exec-biz.d.ts +0 -6
- package/dist/core/types/helpers.d.ts +0 -54
- package/dist/core/types/physical.d.ts +0 -16
- package/dist/core/utils/array.d.ts +0 -12
- package/dist/core/utils/error.d.ts +0 -22
- package/dist/core/utils/fetch.d.ts +0 -13
- package/dist/core/utils/function.d.ts +0 -28
- package/dist/core/utils/github.d.ts +0 -31
- package/dist/core/utils/number/format.d.ts +0 -19
- package/dist/core/utils/random.d.ts +0 -28
- package/dist/core/utils/serialize.d.ts +0 -23
- package/dist/core/utils/sleep.d.ts +0 -13
- package/dist/core/utils/time.d.ts +0 -19
- package/dist/core/utils/type.d.ts +0 -9
- package/dist/core/utils/url.d.ts +0 -36
- package/dist/core.umd.cjs +0 -2
- package/dist/core.umd.cjs.map +0 -1
- package/dist/dom/index.d.ts +0 -6
- package/dist/dom/utils/color.d.ts +0 -32
- package/dist/dom/utils/css.d.ts +0 -4
- package/dist/dom/utils/img.d.ts +0 -14
- package/dist/dom/utils/network.d.ts +0 -25
- package/dist/dom/utils/page.d.ts +0 -10
- package/dist/dom/utils/scroll.d.ts +0 -13
- package/dist/dom.umd.cjs +0 -2
- package/dist/dom.umd.cjs.map +0 -1
- package/dist/node/index.d.ts +0 -8
- package/dist/node/utils/env.d.ts +0 -6
- package/dist/node/utils/file/base.d.ts +0 -20
- package/dist/node/utils/file/delete.d.ts +0 -12
- package/dist/node/utils/file/download.d.ts +0 -4
- package/dist/node/utils/file/find.d.ts +0 -14
- package/dist/node/utils/file/json.d.ts +0 -20
- package/dist/node/utils/file/size.d.ts +0 -19
- package/dist/node/utils/win/cmd.d.ts +0 -21
- package/dist/node/utils/win/copy.d.ts +0 -4
- package/dist/node/utils/win/explorer.d.ts +0 -5
- package/dist/node/utils/win/regedit.d.ts +0 -17
- package/dist/node.umd.cjs +0 -2
- package/dist/node.umd.cjs.map +0 -1
package/LICENSE
CHANGED
package/dist/core.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var h=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var j=Object.prototype.hasOwnProperty;var S=(t,r)=>{for(var e in r)h(t,e,{get:r[e],enumerable:!0})},F=(t,r,e,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of P(r))!j.call(t,o)&&o!==e&&h(t,o,{get:()=>r[o],enumerable:!(n=$(r,o))||n.enumerable});return t};var k=t=>F(h({},"__esModule",{value:!0}),t);var st={};S(st,{BizResult:()=>c,CommonError:()=>a,chunk:()=>C,convertToCommonError:()=>U,createAbortError:()=>D,createResponseError:()=>w,dynamicCall:()=>L,encodeURLParams:()=>et,execBiz:()=>M,fetchWithFormat:()=>l,formatDate:()=>p,formatUnitSize:()=>ot,getErrorMessage:()=>f,getFormattedDate:()=>Z,getFormattedDateTime:()=>X,getFormattedTime:()=>_,getGithubRawJson:()=>I,invalidCharRegex:()=>v,isCanceledError:()=>A,isCommonError:()=>d,isEmptyArr:()=>B,isHttpUrl:()=>tt,isObject:()=>q,isPlainObject:()=>b,mergeQueryParams:()=>nt,parseGithubRawUrl:()=>y,parseGithubRepoUrl:()=>z,parseUrl:()=>rt,processRangeInBatches:()=>H,random1ToN:()=>J,randomFloat:()=>N,randomInt:()=>m,runRandomFunctions:()=>G,sample:()=>Q,sampleOne:()=>K,sampleWithReplacement:()=>W,serializeError:()=>V,shuffle:()=>T,sleep:()=>E,sleepRandom:()=>Y,stripFunctions:()=>x});module.exports=k(st);var a=class extends Error{constructor(r,e){super(r),e!==void 0&&(this.rawError=e instanceof Error?e:new Error(String(e))),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}toString(){return`${this.name}: ${this.message}${this.rawError?` (caused by ${this.rawError})`:""}`}};function A(t){return t instanceof Error?t.name==="AbortError"||t.name==="CanceledError"||"code"in t&&t.code==="ERR_CANCELED":!1}function D(t){let r=new Error(t??"\u64CD\u4F5C\u5DF2\u53D6\u6D88");return r.name="AbortError",r}function d(t){return t instanceof a||t instanceof Error&&t.name==="CommonError"}function O(t,r){return r&&(t.message=`${r} ${t.message}`),t}function U(t,r){return d(t)?O(t,r):new a(`${r} ${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 c=class t{constructor(r,e,n){this.success=r,this.msg=e,this.data=n}static createSuccess(r){return new t(!0,"\u64CD\u4F5C\u6210\u529F",r)}static createFail(r="\u64CD\u4F5C\u5931\u8D25",e){return new t(!1,r,e)}static createError(r){return new t(!1,f(r))}async toPromise(){if(this.success)return this.data;throw new a(this.msg)}};var M=async t=>{try{return c.createSuccess(await t())}catch(r){return c.createError(r)}};function B(t){return Array.isArray(t)&&t.length===0}function C(t,r){if(!Number.isInteger(r)||r<1)throw new Error("size \u5FC5\u987B\u662F\u6B63\u6574\u6570");let e=[];for(let n=0;n<t.length;n+=r)e.push(t.slice(n,n+r));return e}function w(t){return new Error(`HTTP ${t.status}: ${t.statusText}`)}async function l(t,r,e){let n=await fetch(t,e);if(!n.ok)throw w(n);switch(r){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 G(t,r){r=r??t.length;let e=Math.floor(Math.random()*r)+1,n=[...t];for(let s=n.length-1;s>0;s--){let i=Math.floor(Math.random()*(s+1));[n[s],n[i]]=[n[i],n[s]]}let o=n.slice(0,e);for(let s of o)s()}async function H(t,r,e,n){for(let o=t;o<=r;o+=e){let s=r-o+1,i=Math.min(e,s),u=Array.from({length:i},(g,R)=>o+R);await n(u)}}function L(t,r,...e){let n=r.split("."),o=t,s=0;for(;s<n.length-1;s++)if(o=o[n[s]],o==null)throw new Error(`Path '${n.slice(0,s+1).join(".")}' is null/undefined`);let i=o[n[s]];if(typeof i!="function")throw new Error(`'${r}' is not a function`);return i.apply(o,e)}function z(t){t=t.replace(/^git\+/,"");let r=/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git|\/)?$/,e=/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)$/,n=t.match(r);if(n)return{owner:n[1],repo:n[2],branch:"main"};let o=t.match(e);if(o)return{owner:o[1],repo:o[2],branch:o[3]};throw new Error("\u89E3\u6790\u63D2\u4EF6\u4ED3\u5E93URL\u5931\u8D25")}function y(t){let{owner:r,repo:e,branch:n,filePath:o}=t;return`https://raw.githubusercontent.com/${r}/${e}/${n}/${o}`}async function I(t){return JSON.parse(await l(y(t),"json"))}function T(t){let r=t.slice();for(let e=r.length-1;e>0;e--){let n=Math.floor(Math.random()*(e+1));[r[e],r[n]]=[r[n],r[e]]}return r}function m(t,r){return Math.floor(Math.random()*(r-t+1))+t}function N(t,r){return Math.random()*(r-t)+t}function Q(t,r){return T(t).slice(0,r)}function W(t,r){let e=[];for(let n=0;n<r;n++){let o=m(0,t.length-1);e.push(t[o])}return e}function K(t){return t[m(0,t.length-1)]}function J(t){return m(1,t)}function b(t){if(t===null||typeof t!="object")return!1;let r=Object.getPrototypeOf(t);return r===Object.prototype||r===null}function q(t,r){return t===null||typeof t!="object"||Array.isArray(t)?!1:r!==void 0?r in t:!0}function x(t,r=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(r.has(t))return r.get(t);if(Array.isArray(t)){let n=[];r.set(t,n);for(let o of t)n.push(x(o,r));return n}if(!b(t))return t;let e={};r.set(t,e);for(let[n,o]of Object.entries(t)){if(typeof o=="function")continue;let s=x(o,r);s!==void 0&&(e[n]=s)}return e}function V(t){return t instanceof Error?{name:t.name,message:t.message,stack:t.stack}:{name:"Error",message:String(t)}}function E(t,r){return new Promise((e,n)=>{if(r?.aborted)return n(new Error("\u53D6\u6D88\u64CD\u4F5C"));let o=setTimeout(()=>{i(),e()},t),s=()=>{clearTimeout(o),i(),n(new Error("\u53D6\u6D88\u64CD\u4F5C"))},i=()=>{r?.removeEventListener("abort",s)};r?.addEventListener("abort",s)})}function Y(t,r,e){let n=Math.random()*(r-t)+t;return E(n,e)}function p(t,r){let e=isNaN(t.getTime())?new Date:t,n=e.getFullYear(),o=String(e.getMonth()+1).padStart(2,"0"),s=String(e.getDate()).padStart(2,"0"),i=String(e.getHours()).padStart(2,"0"),u=String(e.getMinutes()).padStart(2,"0"),g=String(e.getSeconds()).padStart(2,"0");return r==="date"?`${n}-${o}-${s}`:r==="time"?`${i}:${u}:${g}`:`${n}-${o}-${s} ${i}:${u}:${g}`}function X(t){return p(t??new Date,"datetime")}function Z(t){return p(t??new Date,"date")}function _(t){return p(t??new Date,"time")}var v=/[!'()*]/g;function tt(t){try{let r=new URL(t);return r.protocol==="http:"||r.protocol==="https:"}catch{return!1}}function rt(t){try{let{origin:r,pathname:e,searchParams:n}=new URL(t);return{baseUrl:r+e,searchParams:n}}catch{throw new Error("Invalid URL")}}function et(t,r=!1){return Object.keys(t).sort().filter(e=>r||t[e]!=null).map(e=>{let n=t[e]??"";return`${encodeURIComponent(e)}=${encodeURIComponent(String(n))}`}).join("&")}function nt(t,r){let e={};return t.size>0&&t.forEach((n,o)=>{e[o]=n}),r&&(e={...e,...r}),e}function ot(t,r,e,n=""){if(!Number.isFinite(t))return{size:0,unit:"",text:n};let o=t,s=0;for(;o>=r&&s<e.length-1;)o/=r,s++;return{size:o,unit:e[s],text:`${o.toFixed(2).replace(/\.?0+$/,"")} ${e[s]}`}}
|
|
2
|
+
//# sourceMappingURL=core.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/index.ts","../src/core/error/common-error.ts","../src/core/utils/error.ts","../src/core/result/biz-result.ts","../src/core/result/exec-biz.ts","../src/core/utils/array.ts","../src/core/utils/fetch.ts","../src/core/utils/function.ts","../src/core/utils/github.ts","../src/core/utils/random.ts","../src/core/utils/type.ts","../src/core/utils/serialize.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 './result/biz-result.js'\nexport * from './result/exec-biz.js'\nexport * from './types/helpers.js'\nexport * from './types/physical.js'\nexport * from './utils/array.js'\nexport * from './utils/error.js'\nexport * from './utils/fetch.js'\nexport * from './utils/function.js'\nexport * from './utils/github.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\nexport {}\n","/**\n * 通用错误\n */\nexport class CommonError extends Error {\n // 原始错误\n rawError?: Error\n\n constructor(message: string, rawError?: unknown) {\n super(message)\n\n if (rawError !== undefined) {\n this.rawError = rawError instanceof Error ? rawError : new Error(String(rawError))\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.rawError ? ` (caused by ${this.rawError})` : ''}`\n }\n}\n","import { CommonError } from '../error/common-error.js'\n\n/**\n * 是否为取消操作的错误\n */\nexport function isCanceledError(err: unknown): boolean {\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'\nimport { CommonError } from '../error/common-error.js'\n\n/**\n * 业务执行结果\n */\nexport class BizResult<T> {\n success: boolean\n msg: string\n data?: T\n\n constructor(success: boolean, msg: string, data?: T) {\n this.success = success\n this.msg = msg\n this.data = data\n }\n\n static createSuccess<T>(data: T) {\n return new BizResult(true, '操作成功', data)\n }\n\n static createFail<T>(msg: string = '操作失败', data?: T) {\n return new BizResult(false, msg, data)\n }\n\n static createError<T>(e: unknown) {\n return new BizResult<T>(false, getErrorMessage(e))\n }\n\n /**\n * 展开成Promise\n */\n async toPromise(): Promise<void>\n async toPromise<T>(): Promise<T>\n async toPromise<T = void>(): Promise<T> {\n if (this.success) {\n return this.data as T\n } else {\n throw new CommonError(this.msg)\n }\n }\n}\n","import { BizResult } from './biz-result.js'\n\n/**\n * 执行业务(自动包裹BuResult)\n * @param run 执行方法\n */\nexport const execBiz = async <T>(run: () => Promise<T>): Promise<BizResult<T>> => {\n try {\n return BizResult.createSuccess<T>(await run())\n } catch (e) {\n return BizResult.createError(e)\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 * 用于指定 `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","/**\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 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'\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 * 将错误转换为可 JSON 序列化的普通对象。\n */\nexport function serializeError(err: unknown) {\n if (err instanceof Error) {\n return {\n name: err.name,\n message: err.message,\n stack: err.stack,\n }\n }\n\n return {\n name: 'Error',\n message: String(err),\n }\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(new Error('取消操作'))\n\n const timer = setTimeout(() => {\n cleanup()\n resolve()\n }, ms)\n\n const onAbort = () => {\n clearTimeout(timer)\n cleanup()\n reject(new Error('取消操作'))\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","/** 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","BizResult","CommonError","chunk","convertToCommonError","createAbortError","createResponseError","dynamicCall","encodeURLParams","execBiz","fetchWithFormat","formatDate","formatUnitSize","getErrorMessage","getFormattedDate","getFormattedDateTime","getFormattedTime","getGithubRawJson","invalidCharRegex","isCanceledError","isCommonError","isEmptyArr","isHttpUrl","isObject","isPlainObject","mergeQueryParams","parseGithubRawUrl","parseGithubRepoUrl","parseUrl","processRangeInBatches","random1ToN","randomFloat","randomInt","runRandomFunctions","sample","sampleOne","sampleWithReplacement","serializeError","shuffle","sleep","sleepRandom","stripFunctions","__toCommonJS","CommonError","message","rawError","isCanceledError","err","createAbortError","msg","error","isCommonError","CommonError","prefixError","prefix","convertToCommonError","getErrorMessage","BizResult","_BizResult","success","msg","data","e","getErrorMessage","CommonError","execBiz","run","BizResult","e","isEmptyArr","data","chunk","arr","size","result","i","createResponseError","response","fetchWithFormat","url","format","init","runRandomFunctions","fns","maxCount","count","shuffled","i","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","shuffle","arr","clone","i","j","randomInt","min","max","randomFloat","sample","count","sampleWithReplacement","result","index","sampleOne","random1ToN","n","isPlainObject","value","proto","isObject","key","stripFunctions","value","seen","out","item","isPlainObject","key","next","serializeError","err","sleep","ms","signal","resolve","reject","timer","cleanup","onAbort","sleepRandom","minMS","maxMS","formatDate","date","pattern","d","year","month","day","hours","minutes","seconds","getFormattedDateTime","getFormattedDate","getFormattedTime","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
ADDED
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 通用错误
|
|
3
|
+
*/
|
|
4
|
+
declare class CommonError extends Error {
|
|
5
|
+
rawError?: Error;
|
|
6
|
+
constructor(message: string, rawError?: unknown);
|
|
7
|
+
toString(): string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 业务执行结果
|
|
12
|
+
*/
|
|
13
|
+
declare class BizResult<T> {
|
|
14
|
+
success: boolean;
|
|
15
|
+
msg: string;
|
|
16
|
+
data?: T;
|
|
17
|
+
constructor(success: boolean, msg: string, data?: T);
|
|
18
|
+
static createSuccess<T>(data: T): BizResult<T>;
|
|
19
|
+
static createFail<T>(msg?: string, data?: T): BizResult<T>;
|
|
20
|
+
static createError<T>(e: unknown): BizResult<T>;
|
|
21
|
+
/**
|
|
22
|
+
* 展开成Promise
|
|
23
|
+
*/
|
|
24
|
+
toPromise(): Promise<void>;
|
|
25
|
+
toPromise<T>(): Promise<T>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 执行业务(自动包裹BuResult)
|
|
30
|
+
* @param run 执行方法
|
|
31
|
+
*/
|
|
32
|
+
declare const execBiz: <T>(run: () => Promise<T>) => Promise<BizResult<T>>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 提取getter属性
|
|
36
|
+
*/
|
|
37
|
+
type ExtractGetterProperties<T> = {
|
|
38
|
+
[K in keyof T as K extends `get${infer Rest}` ? Uncapitalize<Rest> : never]: T[K] extends (...args: any[]) => Promise<infer R> ? R : never;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* 至少包含一个字段
|
|
42
|
+
*/
|
|
43
|
+
type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> & {
|
|
44
|
+
[K in Keys]: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>;
|
|
45
|
+
}[Keys];
|
|
46
|
+
/**
|
|
47
|
+
* 用元组限制长度
|
|
48
|
+
*/
|
|
49
|
+
type MaxLengthArray<T, N extends number> = T[] & {
|
|
50
|
+
length: N;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* 提取 T 中所有值类型为 V 的键
|
|
54
|
+
*/
|
|
55
|
+
type KeysMatching<T, V> = {
|
|
56
|
+
[K in keyof T]: T[K] extends V ? K : never;
|
|
57
|
+
}[keyof T];
|
|
58
|
+
/**
|
|
59
|
+
* 任意方法
|
|
60
|
+
*/
|
|
61
|
+
type AnyFn = (...args: any[]) => any;
|
|
62
|
+
/**
|
|
63
|
+
* 提取所有方法
|
|
64
|
+
*/
|
|
65
|
+
type MethodKeys<T> = {
|
|
66
|
+
[K in keyof T]-?: T[K] extends AnyFn ? K : never;
|
|
67
|
+
}[keyof T];
|
|
68
|
+
/**
|
|
69
|
+
* 方法参数类型
|
|
70
|
+
*/
|
|
71
|
+
type MethodParams<T> = T extends (...args: infer P) => any ? P : never;
|
|
72
|
+
/**
|
|
73
|
+
* 方法返回类型
|
|
74
|
+
*/
|
|
75
|
+
type MethodReturn<T> = T extends (...args: any[]) => infer R ? R : never;
|
|
76
|
+
/**
|
|
77
|
+
* 提取所有函数 key
|
|
78
|
+
*/
|
|
79
|
+
type FunctionKeys<T> = {
|
|
80
|
+
[K in keyof T]: T[K] extends AnyFn ? K : never;
|
|
81
|
+
}[keyof T];
|
|
82
|
+
/**
|
|
83
|
+
* 拥有指定键集合的对象类型
|
|
84
|
+
*/
|
|
85
|
+
type ObjectWithKeys<K extends string | symbol> = {
|
|
86
|
+
[key in K]: any;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 物理像素的区域数据
|
|
91
|
+
*/
|
|
92
|
+
interface PhysicalRect {
|
|
93
|
+
x: number;
|
|
94
|
+
y: number;
|
|
95
|
+
width: number;
|
|
96
|
+
height: number;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 物理像素的点位
|
|
100
|
+
*/
|
|
101
|
+
interface PhysicalPoint {
|
|
102
|
+
x: number;
|
|
103
|
+
y: number;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* 是否为空数组
|
|
108
|
+
* @param data
|
|
109
|
+
*/
|
|
110
|
+
declare function isEmptyArr(data: unknown): boolean;
|
|
111
|
+
/**
|
|
112
|
+
* 将数组分块为指定大小的多个子数组
|
|
113
|
+
* @param arr 原数组
|
|
114
|
+
* @param size 每个块的长度
|
|
115
|
+
* @example chunk([1,2,3,4,5], 2) => [[1,2],[3,4],[5]]
|
|
116
|
+
*/
|
|
117
|
+
declare function chunk<T>(arr: T[], size: number): T[][];
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 是否为取消操作的错误
|
|
121
|
+
*/
|
|
122
|
+
declare function isCanceledError(err: unknown): boolean;
|
|
123
|
+
/**
|
|
124
|
+
* 创建取消错误
|
|
125
|
+
* @param msg
|
|
126
|
+
*/
|
|
127
|
+
declare function createAbortError(msg?: string): Error;
|
|
128
|
+
/**
|
|
129
|
+
* 是否为通用错误对象
|
|
130
|
+
*/
|
|
131
|
+
declare function isCommonError(error: unknown): error is CommonError;
|
|
132
|
+
/**
|
|
133
|
+
* 转换到通用异常
|
|
134
|
+
*/
|
|
135
|
+
declare function convertToCommonError(error: unknown, prefix?: string): Error;
|
|
136
|
+
/**
|
|
137
|
+
* 获取异常信息
|
|
138
|
+
*/
|
|
139
|
+
declare function getErrorMessage(error: unknown): string;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* 用于指定 `fetch` 响应体的解析方式。
|
|
143
|
+
* 对应 `Response` 对象的不同解析方法(`.json()`、`.text()` 等)。
|
|
144
|
+
*/
|
|
145
|
+
type ResponseBodyFormat = 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData';
|
|
146
|
+
/**
|
|
147
|
+
* 创建响应错误
|
|
148
|
+
*/
|
|
149
|
+
declare function createResponseError(response: Response): Error;
|
|
150
|
+
/**
|
|
151
|
+
* 使用指定的响应解析格式发起 fetch 请求
|
|
152
|
+
*/
|
|
153
|
+
declare function fetchWithFormat<T = any>(url: string, format: ResponseBodyFormat, init?: RequestInit): Promise<T>;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* 随机运行参数
|
|
157
|
+
* @param fns
|
|
158
|
+
* @param maxCount 最多执行次数(1 ~ fns.length)
|
|
159
|
+
*/
|
|
160
|
+
declare function runRandomFunctions(fns: Array<() => void>, maxCount?: number): void;
|
|
161
|
+
/**
|
|
162
|
+
* 将数字范围按批次处理,每个批次调用一次异步函数
|
|
163
|
+
*
|
|
164
|
+
* @param start - 起始值(包含)
|
|
165
|
+
* @param end - 结束值(包含)
|
|
166
|
+
* @param batchSize - 每批最大元素个数
|
|
167
|
+
* @param processor - 处理单批数字数组的异步函数
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* // 分批处理 1..10,每批最多 3 个数字
|
|
171
|
+
* await processRangeInBatches(1, 10, 3, async (batch) => {
|
|
172
|
+
* console.log(batch) // 输出: [1,2,3], [4,5,6], [7,8,9], [10]
|
|
173
|
+
* })
|
|
174
|
+
*/
|
|
175
|
+
declare function processRangeInBatches(start: number, end: number, batchSize: number, processor: (batch: number[]) => Promise<void>): Promise<void>;
|
|
176
|
+
/**
|
|
177
|
+
* 动态调用
|
|
178
|
+
* @param root 对象
|
|
179
|
+
* @param path 调用路径
|
|
180
|
+
* @param args 参数
|
|
181
|
+
*/
|
|
182
|
+
declare function dynamicCall<T = any>(root: any, path: string, ...args: any[]): T;
|
|
183
|
+
|
|
184
|
+
/** github 仓库信息 */
|
|
185
|
+
interface GitHubRepo {
|
|
186
|
+
/** 仓库所有者(用户或组织名) */
|
|
187
|
+
owner: string;
|
|
188
|
+
/** 仓库名称 */
|
|
189
|
+
repo: string;
|
|
190
|
+
}
|
|
191
|
+
/** github 仓库分支信息 */
|
|
192
|
+
type GitHubRepoBranch = GitHubRepo & {
|
|
193
|
+
/** 分支名称 */
|
|
194
|
+
branch: string;
|
|
195
|
+
};
|
|
196
|
+
/** github 仓库文件信息 */
|
|
197
|
+
type GitHubRepoFile = GitHubRepoBranch & {
|
|
198
|
+
/** 文件路径 */
|
|
199
|
+
filePath: string;
|
|
200
|
+
};
|
|
201
|
+
/**
|
|
202
|
+
* 从 url 解析 github 仓库信息
|
|
203
|
+
* @param repositoryUrl 仓库 URL(支持带有git+前缀、具体文件路径)
|
|
204
|
+
*/
|
|
205
|
+
declare function parseGithubRepoUrl(repositoryUrl: string): GitHubRepoBranch;
|
|
206
|
+
/**
|
|
207
|
+
* 解析 github 仓库文件的原始内容的 url
|
|
208
|
+
*/
|
|
209
|
+
declare function parseGithubRawUrl(gitHubRepoFile: GitHubRepoFile): string;
|
|
210
|
+
/**
|
|
211
|
+
* 获取 github 仓库文件的 json 内容并解析为对象 T
|
|
212
|
+
* @param gitHubRepoFile
|
|
213
|
+
*/
|
|
214
|
+
declare function getGithubRawJson<O>(gitHubRepoFile: GitHubRepoFile): Promise<O>;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* 数组洗牌
|
|
218
|
+
*/
|
|
219
|
+
declare function shuffle<T>(arr: T[]): T[];
|
|
220
|
+
/**
|
|
221
|
+
* 获取 [min, max] 的随机整数
|
|
222
|
+
*/
|
|
223
|
+
declare function randomInt(min: number, max: number): number;
|
|
224
|
+
/**
|
|
225
|
+
* 获取 [min, max) 的随机浮点数
|
|
226
|
+
*/
|
|
227
|
+
declare function randomFloat(min: number, max: number): number;
|
|
228
|
+
/**
|
|
229
|
+
* 从数组中随机取若干项,不可重复
|
|
230
|
+
*/
|
|
231
|
+
declare function sample<T>(arr: T[], count: number): T[];
|
|
232
|
+
/**
|
|
233
|
+
* 从数组中随机取若干项,可重复
|
|
234
|
+
*/
|
|
235
|
+
declare function sampleWithReplacement<T>(arr: T[], count: number): T[];
|
|
236
|
+
/**
|
|
237
|
+
* 从数组中获取随机项
|
|
238
|
+
*/
|
|
239
|
+
declare function sampleOne<T>(arr: T[]): T;
|
|
240
|
+
/**
|
|
241
|
+
* 获取 1~n 的随机数
|
|
242
|
+
*/
|
|
243
|
+
declare function random1ToN(n: number): number;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* 递归移除对象(或数组)中的所有函数属性,返回一个可安全序列化的副本。
|
|
247
|
+
*
|
|
248
|
+
* @typeParam T - 输入值的类型。
|
|
249
|
+
* @param value - 待处理的值(基本类型、对象、数组等)。
|
|
250
|
+
* @param seen - 内部使用的 WeakMap,用于记录已访问过的对象,防止循环引用。
|
|
251
|
+
* 调用方通常无需传递此参数。
|
|
252
|
+
* @returns 处理后的新副本,其中所有函数属性都被移除。
|
|
253
|
+
* 基本类型(string, number, boolean, null, undefined)将原样返回。
|
|
254
|
+
*/
|
|
255
|
+
declare function stripFunctions<T>(value: T, seen?: WeakMap<object, any>): T;
|
|
256
|
+
/**
|
|
257
|
+
* 将错误转换为可 JSON 序列化的普通对象。
|
|
258
|
+
*/
|
|
259
|
+
declare function serializeError(err: unknown): {
|
|
260
|
+
name: string;
|
|
261
|
+
message: string;
|
|
262
|
+
stack: string | undefined;
|
|
263
|
+
} | {
|
|
264
|
+
name: string;
|
|
265
|
+
message: string;
|
|
266
|
+
stack?: undefined;
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* 支持取消的 sleep
|
|
271
|
+
* @param ms 延迟毫秒数
|
|
272
|
+
* @param signal 取消信号
|
|
273
|
+
*/
|
|
274
|
+
declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
|
|
275
|
+
/**
|
|
276
|
+
* 支持取消的随机 sleep
|
|
277
|
+
* @param minMS 最小延迟毫秒数
|
|
278
|
+
* @param maxMS 最大延迟毫秒数
|
|
279
|
+
* @param signal 取消信号
|
|
280
|
+
*/
|
|
281
|
+
declare function sleepRandom(minMS: number, maxMS: number, signal?: AbortSignal): Promise<void>;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* 格式化日期
|
|
285
|
+
*/
|
|
286
|
+
declare function formatDate(date: Date, pattern: 'date' | 'time' | 'datetime'): string;
|
|
287
|
+
/**
|
|
288
|
+
* 格式化时间为 2020-02-02 20:20:20 的字符串
|
|
289
|
+
* @param date 需要格式化的时间,为空则获取当前时间
|
|
290
|
+
*/
|
|
291
|
+
declare function getFormattedDateTime(date?: Date): string;
|
|
292
|
+
/**
|
|
293
|
+
* 格式化时间为 2020-02-02 20:20:20 的字符串
|
|
294
|
+
* @param date 需要格式化的时间,为空则获取当前时间
|
|
295
|
+
*/
|
|
296
|
+
declare function getFormattedDate(date?: Date): string;
|
|
297
|
+
/**
|
|
298
|
+
* 格式化时间为 20:20:20 的字符串
|
|
299
|
+
* @param date 需要格式化的时间,为空则获取当前时间
|
|
300
|
+
*/
|
|
301
|
+
declare function getFormattedTime(date?: Date): string;
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* 判断一个值是否为纯对象
|
|
305
|
+
*/
|
|
306
|
+
declare function isPlainObject(value: unknown): value is Record<string, unknown>;
|
|
307
|
+
/**
|
|
308
|
+
* 包括类实例、普通对象,不包括 数组、null 和原始类型
|
|
309
|
+
*/
|
|
310
|
+
declare function isObject<K extends string | symbol>(value: unknown, key?: K): value is ObjectWithKeys<K>;
|
|
311
|
+
|
|
312
|
+
/** URL query 中必须编码的保留字符 (RFC 3986) */
|
|
313
|
+
declare const invalidCharRegex: RegExp;
|
|
314
|
+
/** 查询参数 */
|
|
315
|
+
type QueryParams = Record<string, string | number | boolean | null | undefined>;
|
|
316
|
+
/**
|
|
317
|
+
* 已解析的 url
|
|
318
|
+
*/
|
|
319
|
+
interface ParsedUrl {
|
|
320
|
+
baseUrl: string;
|
|
321
|
+
searchParams: URLSearchParams;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* 判断字符串是否为有效的 HTTP/HTTPS URL
|
|
325
|
+
* @param path - 待检测的字符串
|
|
326
|
+
*/
|
|
327
|
+
declare function isHttpUrl(path: string): boolean;
|
|
328
|
+
/**
|
|
329
|
+
* 解析 url
|
|
330
|
+
* @param url
|
|
331
|
+
*/
|
|
332
|
+
declare function parseUrl(url: string): ParsedUrl;
|
|
333
|
+
/**
|
|
334
|
+
* 编码 URL 参数
|
|
335
|
+
* @param params 查询参数
|
|
336
|
+
* @param keepEmptyValues 保留 null/undefined的值(空字符串)
|
|
337
|
+
*/
|
|
338
|
+
declare function encodeURLParams(params: QueryParams, keepEmptyValues?: boolean): string;
|
|
339
|
+
/**
|
|
340
|
+
*
|
|
341
|
+
*/
|
|
342
|
+
/**
|
|
343
|
+
* 合并查询参数
|
|
344
|
+
* @param urlSearchParams url解析后查询参数
|
|
345
|
+
* @param params 单独传的查询参数
|
|
346
|
+
*/
|
|
347
|
+
declare function mergeQueryParams(urlSearchParams: URLSearchParams, params?: QueryParams): QueryParams;
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* 格式化后的单位数据(如文件大小)
|
|
351
|
+
*/
|
|
352
|
+
interface FormattedUnitSize {
|
|
353
|
+
/** 换算后该单位的数值(未四舍五入) */
|
|
354
|
+
size: number;
|
|
355
|
+
/** 单位名称,如 'MB' */
|
|
356
|
+
unit: string;
|
|
357
|
+
/** 显示文本:数值四舍五入保留两位小数 + 单位,如 '1.50 MB' */
|
|
358
|
+
text: string;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* 按进制自动格式化单位
|
|
362
|
+
* @param value 数值
|
|
363
|
+
* @param base 进制(1024 / 1000)
|
|
364
|
+
* @param units 单位列表
|
|
365
|
+
* @param invalidText 无效值返回文本
|
|
366
|
+
*/
|
|
367
|
+
declare function formatUnitSize(value: number, base: number, units: string[], invalidText?: string): FormattedUnitSize;
|
|
368
|
+
|
|
369
|
+
export { type AnyFn, BizResult, CommonError, type ExtractGetterProperties, type FormattedUnitSize, type FunctionKeys, type GitHubRepo, type GitHubRepoBranch, type GitHubRepoFile, type KeysMatching, type MaxLengthArray, type MethodKeys, type MethodParams, type MethodReturn, type ObjectWithKeys, type ParsedUrl, type PhysicalPoint, type PhysicalRect, type QueryParams, type RequireAtLeastOne, type ResponseBodyFormat, chunk, convertToCommonError, createAbortError, createResponseError, dynamicCall, encodeURLParams, execBiz, fetchWithFormat, formatDate, formatUnitSize, getErrorMessage, getFormattedDate, getFormattedDateTime, getFormattedTime, getGithubRawJson, invalidCharRegex, isCanceledError, isCommonError, isEmptyArr, isHttpUrl, isObject, isPlainObject, mergeQueryParams, parseGithubRawUrl, parseGithubRepoUrl, parseUrl, processRangeInBatches, random1ToN, randomFloat, randomInt, runRandomFunctions, sample, sampleOne, sampleWithReplacement, serializeError, shuffle, sleep, sleepRandom, stripFunctions };
|