@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/dist/node.js
CHANGED
|
@@ -1,201 +1,2 @@
|
|
|
1
|
-
import * as e from "
|
|
2
|
-
import t from "node:fs/promises";
|
|
3
|
-
import n from "node:path";
|
|
4
|
-
import { exec as r } from "node:child_process";
|
|
5
|
-
import * as i from "iconv-lite";
|
|
6
|
-
//#region ../src/node/utils/env.ts
|
|
7
|
-
function a() {
|
|
8
|
-
let e = {};
|
|
9
|
-
for (let t in process.env) e[t] = process.env[t];
|
|
10
|
-
return e;
|
|
11
|
-
}
|
|
12
|
-
//#endregion
|
|
13
|
-
//#region ../src/node/utils/file/base.ts
|
|
14
|
-
async function o(e) {
|
|
15
|
-
try {
|
|
16
|
-
return (await t.stat(e)).isFile();
|
|
17
|
-
} catch {
|
|
18
|
-
return !1;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
async function s(e, n) {
|
|
22
|
-
try {
|
|
23
|
-
return t.access(e, n), !0;
|
|
24
|
-
} catch {
|
|
25
|
-
return !1;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
async function c(e) {
|
|
29
|
-
t.mkdir(e, { recursive: !0 });
|
|
30
|
-
}
|
|
31
|
-
async function l(e) {
|
|
32
|
-
await t.mkdir(e, { recursive: !0 });
|
|
33
|
-
}
|
|
34
|
-
function u(e) {
|
|
35
|
-
return typeof e == "object" && !!e && "code" in e && e.code === "ENOENT";
|
|
36
|
-
}
|
|
37
|
-
//#endregion
|
|
38
|
-
//#region ../src/node/utils/file/delete.ts
|
|
39
|
-
async function d(e) {
|
|
40
|
-
let r = [], i = await t.readdir(e, { withFileTypes: !0 });
|
|
41
|
-
for (let a of i) {
|
|
42
|
-
let i = n.join(e, a.name);
|
|
43
|
-
a.isDirectory() ? (r.push(...await d(i)), await t.rmdir(i)) : await t.unlink(i), r.push(i);
|
|
44
|
-
}
|
|
45
|
-
return r;
|
|
46
|
-
}
|
|
47
|
-
async function f(e) {
|
|
48
|
-
return (await Promise.allSettled(e.map(async (e) => (await t.unlink(e), e)))).filter((e) => e.status === "fulfilled").map((e) => e.value);
|
|
49
|
-
}
|
|
50
|
-
//#endregion
|
|
51
|
-
//#region ../src/node/utils/file/json.ts
|
|
52
|
-
async function p(e) {
|
|
53
|
-
if (!await o(e)) throw Error("文件不存在");
|
|
54
|
-
let r = await t.readFile(n.resolve(e), "utf-8");
|
|
55
|
-
return JSON.parse(r);
|
|
56
|
-
}
|
|
57
|
-
async function m(e, n) {
|
|
58
|
-
let r = `${e}.tmp.${Date.now()}`, i = JSON.stringify(n, null, 2);
|
|
59
|
-
await t.writeFile(r, i, "utf-8"), await t.rename(r, e);
|
|
60
|
-
}
|
|
61
|
-
async function h(e, t) {
|
|
62
|
-
let n = t(await p(e));
|
|
63
|
-
return await m(e, n), n;
|
|
64
|
-
}
|
|
65
|
-
async function g(e, r) {
|
|
66
|
-
try {
|
|
67
|
-
let n = await t.readFile(e, "utf-8");
|
|
68
|
-
return JSON.parse(n);
|
|
69
|
-
} catch (i) {
|
|
70
|
-
if (!u(i)) throw i;
|
|
71
|
-
let a = await r();
|
|
72
|
-
return await l(n.dirname(e)), await t.writeFile(e, JSON.stringify(a, null, 2), "utf-8"), a;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
//#endregion
|
|
76
|
-
//#region ../src/core/utils/number/format.ts
|
|
77
|
-
function _(e, t, n, r = "") {
|
|
78
|
-
if (!Number.isFinite(e)) return {
|
|
79
|
-
size: 0,
|
|
80
|
-
unit: "",
|
|
81
|
-
text: r
|
|
82
|
-
};
|
|
83
|
-
let i = e, a = 0;
|
|
84
|
-
for (; i >= t && a < n.length - 1;) i /= t, a++;
|
|
85
|
-
return {
|
|
86
|
-
size: i,
|
|
87
|
-
unit: n[a],
|
|
88
|
-
text: `${i.toFixed(2).replace(/\.?0+$/, "")} ${n[a]}`
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
//#endregion
|
|
92
|
-
//#region ../src/node/utils/file/size.ts
|
|
93
|
-
function v(e, t = "") {
|
|
94
|
-
let { size: n, unit: r, text: i } = _(e, 1024, [
|
|
95
|
-
"KB",
|
|
96
|
-
"MB",
|
|
97
|
-
"GB"
|
|
98
|
-
], t);
|
|
99
|
-
if (i === t) return t;
|
|
100
|
-
let a = Math.floor(n), o;
|
|
101
|
-
return o = a > 99 ? 0 : a > 9 ? 1 : 2, `${Math.round(n * 10 ** o) / 10 ** o} ${r}`;
|
|
102
|
-
}
|
|
103
|
-
async function y(e) {
|
|
104
|
-
try {
|
|
105
|
-
return (await t.stat(e)).size;
|
|
106
|
-
} catch {
|
|
107
|
-
return 0;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
async function b(e) {
|
|
111
|
-
try {
|
|
112
|
-
return (await t.lstat(e)).size;
|
|
113
|
-
} catch {
|
|
114
|
-
return 0;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
async function x(e) {
|
|
118
|
-
let r;
|
|
119
|
-
try {
|
|
120
|
-
r = await t.readdir(e, { withFileTypes: !0 });
|
|
121
|
-
} catch {
|
|
122
|
-
return 0;
|
|
123
|
-
}
|
|
124
|
-
let i = [];
|
|
125
|
-
for (let t of r) {
|
|
126
|
-
let r = n.join(e, t.name);
|
|
127
|
-
if (t.isDirectory()) {
|
|
128
|
-
i.push(x(r));
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
if (t.isSymbolicLink()) {
|
|
132
|
-
i.push(b(r));
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
i.push(y(r));
|
|
136
|
-
}
|
|
137
|
-
return (await Promise.allSettled(i)).reduce((e, t) => e + (t.status === "fulfilled" ? t.value : 0), 0);
|
|
138
|
-
}
|
|
139
|
-
async function S(e) {
|
|
140
|
-
try {
|
|
141
|
-
let n = await t.stat(e);
|
|
142
|
-
return n.isDirectory() ? await x(e) / 1024 : n.size / 1024;
|
|
143
|
-
} catch {
|
|
144
|
-
return 0;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
//#endregion
|
|
148
|
-
//#region ../src/core/utils/error.ts
|
|
149
|
-
function C(e) {
|
|
150
|
-
let t = Error(e ?? "操作已取消");
|
|
151
|
-
return t.name = "AbortError", t;
|
|
152
|
-
}
|
|
153
|
-
//#endregion
|
|
154
|
-
//#region ../src/node/utils/win/cmd.ts
|
|
155
|
-
async function w(e, t) {
|
|
156
|
-
return new Promise((n, a) => {
|
|
157
|
-
if (t?.signal?.aborted) throw C();
|
|
158
|
-
let o = null, s = r(`${e}`, { encoding: "buffer" }, (e, r, s) => {
|
|
159
|
-
let c = i.decode(r, "cp936"), l = i.decode(s, "cp936");
|
|
160
|
-
o && t?.signal?.removeEventListener("abort", o);
|
|
161
|
-
let u = e ? Number(e.code ?? 0) : 0;
|
|
162
|
-
(t?.codeIsSuccess ? !t.codeIsSuccess(u) : u !== 0) ? a(/* @__PURE__ */ Error(`命令行执行出错 (${u}): ${l || c}`)) : n(c);
|
|
163
|
-
}), c;
|
|
164
|
-
o = () => {
|
|
165
|
-
s.kill("SIGTERM"), c = setTimeout(() => {
|
|
166
|
-
s.kill("SIGKILL");
|
|
167
|
-
}, 3e3), a(C());
|
|
168
|
-
}, t?.signal && t.signal.addEventListener("abort", o), s.on("close", () => {
|
|
169
|
-
c !== void 0 && clearTimeout(c), t?.signal?.removeEventListener("abort", o);
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
//#endregion
|
|
174
|
-
//#region ../src/node/utils/win/copy.ts
|
|
175
|
-
async function T(e, t, r) {
|
|
176
|
-
let i = n.resolve(e), a = n.resolve(t), s;
|
|
177
|
-
await o(e) ? (s = `copy "${i}" "${a}"`, await w(s, { signal: r })) : (s = `robocopy "${i}" "${a}" /E /NFL /NDL /NJH /NJS /NC /NS /NP`, await w(s, {
|
|
178
|
-
codeIsSuccess: (e) => e < 8,
|
|
179
|
-
signal: r
|
|
180
|
-
}));
|
|
181
|
-
}
|
|
182
|
-
//#endregion
|
|
183
|
-
//#region ../src/node/utils/win/explorer.ts
|
|
184
|
-
async function E(t) {
|
|
185
|
-
t = n.resolve(t), (await e.stat(t)).isDirectory() ? await w(`start "" "${t}"`) : await w(`start "" explorer /select,"${t}"`);
|
|
186
|
-
}
|
|
187
|
-
//#endregion
|
|
188
|
-
//#region ../src/node/utils/win/regedit.ts
|
|
189
|
-
async function D(e) {
|
|
190
|
-
return w(`taskkill /f /im regedit.exe & REG ADD "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit" /v "LastKey" /d "${e}" /f & regedit`);
|
|
191
|
-
}
|
|
192
|
-
async function O(e, t) {
|
|
193
|
-
t = n.resolve(t), await l(e), await w(`reg export "${e}" "${t}" /y`, void 0);
|
|
194
|
-
}
|
|
195
|
-
async function k(e, t) {
|
|
196
|
-
await w(`reg import "${n.resolve(t)}"`, void 0);
|
|
197
|
-
}
|
|
198
|
-
//#endregion
|
|
199
|
-
export { T as copyFile, f as deleteFiles, d as emptyDirectory, l as ensureDir, c as ensureDirSync, s as existsFile, O as exportRegedit, v as formatFileSizeFromKB, x as getDirSize, a as getEnv, S as getFileSizeKB, k as importRegedit, o as isFile, u as isFileNotFoundError, D as openRegedit, p as readJSONFile, g as readOrInitJSON, E as showInExplorer, h as updateJSON, m as writeJSONFile };
|
|
200
|
-
|
|
1
|
+
function K(){let t={};for(let r in process.env)t[r]=process.env[r];return t}import d from"fs/promises";import{mkdirSync as N}from"fs";async function u(t){try{return(await d.stat(t)).isFile()}catch{return!1}}async function Y(t,r){try{return d.access(t,r),!0}catch{return!1}}function X(t){N(t,{recursive:!0})}async function f(t){await d.mkdir(t,{recursive:!0})}function y(t){return typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT"}import m from"fs/promises";import O from"path";async function A(t){let r=[],e=await m.readdir(t,{withFileTypes:!0});for(let n of e){let o=O.join(t,n.name);n.isDirectory()?(r.push(...await A(o)),await m.rmdir(o)):await m.unlink(o),r.push(o)}return r}async function rt(t){return(await Promise.allSettled(t.map(async e=>(await m.unlink(e),e)))).filter(e=>e.status==="fulfilled").map(e=>e.value)}import{pipeline as M}from"stream/promises";import{createWriteStream as B}from"fs";import C from"path";async function st(t,r){let e=C.resolve(r),n=await fetch(t);if(!n.ok||!n.body)throw new Error(`\u4E0B\u8F7D\u5931\u8D25: ${n.status}`);await M(n.body,B(e))}import b from"fs/promises";import T from"path";async function ft(t,r,e){return(await b.readdir(t,{withFileTypes:!0})).filter(n=>n.isFile()&&n.name.startsWith(r||"")&&n.name.endsWith(e||"")).map(n=>T.join(t,n.name))}async function L(t,r){let e=[],n=await b.readdir(t,{withFileTypes:!0});for(let o of n){let i=T.join(t,o.name);o.isDirectory()?e.push(...await L(i,r)):(typeof r=="string"&&o.name===r||typeof r=="function"&&r(o.name,i))&&e.push(i)}return e}import c from"fs/promises";import E from"path";async function U(t){if(!await u(t))throw new Error("\u6587\u4EF6\u4E0D\u5B58\u5728");let r=await c.readFile(E.resolve(t),"utf-8");return JSON.parse(r)}async function z(t,r){let e=`${t}.tmp.${Date.now()}`,n=JSON.stringify(r,null,2);await c.writeFile(e,n,"utf-8"),await c.rename(e,t)}async function dt(t,r){let e=await U(t),n=r(e);return await z(t,n),n}async function xt(t,r){try{let e=await c.readFile(t,"utf-8");return JSON.parse(e)}catch(e){if(!y(e))throw e;let n=await r();return await f(E.dirname(t)),await c.writeFile(t,JSON.stringify(n,null,2),"utf-8"),n}}function S(t,r,e,n=""){if(!Number.isFinite(t))return{size:0,unit:"",text:n};let o=t,i=0;for(;o>=r&&i<e.length-1;)o/=r,i++;return{size:o,unit:e[i],text:`${o.toFixed(2).replace(/\.?0+$/,"")} ${e[i]}`}}import p from"fs/promises";import I from"path";function Et(t,r=""){let{size:e,unit:n,text:o}=S(t,1024,["KB","MB","GB"],r);if(o===r)return r;let i=Math.floor(e),s;return i>99?s=0:i>9?s=1:s=2,`${Math.round(e*10**s)/10**s} ${n}`}async function v(t){try{return(await p.stat(t)).size}catch{return 0}}async function G(t){try{return(await p.lstat(t)).size}catch{return 0}}async function P(t){let r;try{r=await p.readdir(t,{withFileTypes:!0})}catch{return 0}let e=[];for(let o of r){let i=I.join(t,o.name);if(o.isDirectory()){e.push(P(i));continue}if(o.isSymbolicLink()){e.push(G(i));continue}e.push(v(i))}return(await Promise.allSettled(e)).reduce((o,i)=>o+(i.status==="fulfilled"?i.value:0),0)}async function St(t){try{let r=await p.stat(t);return r.isDirectory()?await P(t)/1024:r.size/1024}catch{return 0}}function x(t){let r=new Error(t??"\u64CD\u4F5C\u5DF2\u53D6\u6D88");return r.name="AbortError",r}import{exec as J}from"child_process";import*as h from"iconv-lite";async function a(t,r){return new Promise((e,n)=>{if(r?.signal?.aborted)throw x();let o=null,i=J(`${t}`,{encoding:"buffer"},(l,j,D)=>{let w=h.decode(j,"cp936"),k=h.decode(D,"cp936");o&&r?.signal?.removeEventListener("abort",o);let g=l?Number(l.code??0):0;(r?.codeIsSuccess?!r.codeIsSuccess(g):g!==0)?n(new Error(`\u547D\u4EE4\u884C\u6267\u884C\u51FA\u9519 (${g}): ${k||w}`)):e(w)}),s;o=()=>{i.kill("SIGTERM"),s=setTimeout(()=>{i.kill("SIGKILL")},3e3),n(x())},r?.signal&&r.signal.addEventListener("abort",o),i.on("close",()=>{s!==void 0&&clearTimeout(s),r?.signal?.removeEventListener("abort",o)})})}import $ from"path";async function yr(t,r,e){let n=$.resolve(t),o=$.resolve(r),i;await u(t)?(i=`copy "${n}" "${o}"`,await a(i,{signal:e})):(i=`robocopy "${n}" "${o}" /E /NFL /NDL /NJH /NJS /NC /NS /NP`,await a(i,{codeIsSuccess:s=>s<8,signal:e}))}import W from"path";import*as F from"fs/promises";async function Sr(t){t=W.resolve(t),(await F.stat(t)).isDirectory()?await a(`start "" "${t}"`):await a(`start "" explorer /select,"${t}"`)}import R from"path";async function jr(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 Dr(t,r){r=R.resolve(r),await f(t),await a(`reg export "${t}" "${r}" /y`,void 0)}async function kr(t,r){await a(`reg import "${R.resolve(r)}"`,void 0)}export{yr as copyFile,rt as deleteFiles,st as downloadFile,A as emptyDirectory,f as ensureDir,X as ensureDirSync,a as execWinCmd,Y as existsFile,Dr as exportRegedit,L as findFiles,ft as findFilesByPrefixAndSuffix,Et as formatFileSizeFromKB,P as getDirSize,K as getEnv,St as getFileSizeKB,kr as importRegedit,u as isFile,y as isFileNotFoundError,jr as openRegedit,U as readJSONFile,xt as readOrInitJSON,Sr as showInExplorer,dt as updateJSON,z as writeJSONFile};
|
|
201
2
|
//# sourceMappingURL=node.js.map
|
package/dist/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","names":[],"sources":["../src/node/utils/env.ts","../src/node/utils/file/base.ts","../src/node/utils/file/delete.ts","../src/node/utils/file/json.ts","../src/core/utils/number/format.ts","../src/node/utils/file/size.ts","../src/core/utils/error.ts","../src/node/utils/win/cmd.ts","../src/node/utils/win/copy.ts","../src/node/utils/win/explorer.ts","../src/node/utils/win/regedit.ts"],"sourcesContent":["/**\n * 获取环境变量\n */\nexport function getEnv(): { [p: string]: string } {\n const env: { [p: string]: string } = {}\n for (const envKey in process.env) {\n env[envKey] = process.env[envKey] as string\n }\n return env\n}\n","import fs from 'node:fs/promises'\n\n/**\n * 判断路径是否是文件\n */\nexport async function isFile(filePath: string) {\n try {\n return (await fs.stat(filePath)).isFile()\n } catch {\n return false\n }\n}\n\n/**\n * 判断文件是否存在\n */\nexport async function existsFile(file: string, mode?: number) {\n try {\n fs.access(file, mode)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * 确保目录存在\n */\nexport async function ensureDirSync(dirPath: string) {\n fs.mkdir(dirPath, { recursive: true })\n}\n\n/**\n * 确保目录存在\n */\nexport async function ensureDir(dirPath: string) {\n await fs.mkdir(dirPath, { recursive: true })\n}\n\n/**\n * 判断错误是否为文件不存在\n */\nexport function isFileNotFoundError(error: unknown): boolean {\n return (\n typeof error === 'object' && error !== null && 'code' in error && (error as NodeJS.ErrnoException).code === 'ENOENT'\n )\n}\n","import fs from 'node:fs/promises'\nimport path from 'node:path'\n\n/**\n * 删除指定目录下的所有文件和子目录(保留指定目录)\n * @param dir 目标目录路径\n * @return 成功删除的文件或目录路径数组\n */\nexport async function emptyDirectory(dir: string) {\n const deletedPaths: string[] = []\n // 读取目录中的所有文件和子目录\n const entries = await fs.readdir(dir, { withFileTypes: true })\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n if (entry.isDirectory()) {\n // 如果是目录,递归删除其内容\n deletedPaths.push(...(await emptyDirectory(fullPath)))\n // 删除空目录\n await fs.rmdir(fullPath)\n } else {\n // 如果是文件,删除文件\n await fs.unlink(fullPath)\n }\n deletedPaths.push(fullPath)\n }\n return deletedPaths\n}\n\n/**\n * 删除文件(不删除目录)\n * @param paths 文件路径列表\n * @returns 成功删除的文件路径数组\n */\nexport async function deleteFiles(paths: string[]): Promise<string[]> {\n const results = await Promise.allSettled(\n paths.map(async (file) => {\n await fs.unlink(file)\n return file\n }),\n )\n\n return results.filter((r): r is PromiseFulfilledResult<string> => r.status === 'fulfilled').map((r) => r.value)\n}\n","import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { isFileNotFoundError, ensureDir, isFile } from './base.js'\n\n/**\n * 读取 JSON 文件\n */\nexport async function readJSONFile<T>(filePath: string): Promise<T> {\n if (!(await isFile(filePath))) {\n throw new Error('文件不存在')\n }\n const jsonRaw = await fs.readFile(path.resolve(filePath), 'utf-8')\n return JSON.parse(jsonRaw) as T\n}\n\n/**\n * 将数据原子写入 JSON 文件(先写临时文件再替换)\n */\nexport async function writeJSONFile<T>(file: string, data: T): Promise<void> {\n const tempFile = `${file}.tmp.${Date.now()}`\n const jsonContent = JSON.stringify(data, null, 2)\n await fs.writeFile(tempFile, jsonContent, 'utf-8')\n // 直接替换(会覆原文件)\n await fs.rename(tempFile, file)\n}\n\n/**\n * 读取 JSON 文件,修改后写回(原子操作)\n */\nexport async function updateJSON<T>(file: string, updater: (oldData: T) => T): Promise<T> {\n const oldData = await readJSONFile<T>(file)\n const newData = updater(oldData)\n await writeJSONFile(file, newData)\n return newData\n}\n\n/**\n * 从文件读取 JSON,若文件不存在则调用 initData 初始化并写入\n *\n * @param file 文件绝对路径或相对路径\n * @param initData 返回要写入的数据的异步函数\n * @returns 解析后的数据\n */\nexport async function readOrInitJSON<T>(file: string, initData: () => Promise<T>): Promise<T> {\n try {\n const content = await fs.readFile(file, 'utf-8')\n // 解析 JSON,若失败则抛出错误(不会误判为“不存在”)\n return JSON.parse(content) as T\n } catch (error) {\n // 文件不存在等其他错误要透传\n if (!isFileNotFoundError(error)) {\n throw error\n }\n // 文件不存在,生成初始数据\n const data = await initData()\n // 确保目录存在\n await ensureDir(path.dirname(file))\n // 写入文件,格式化 JSON\n await fs.writeFile(file, JSON.stringify(data, null, 2), 'utf-8')\n return data\n }\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","import { formatUnitSize } from '../../../core/utils/number/format.js'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\n\n/**\n * 将 KB 文件大小格式化为字符串\n * @param sizeKB 文件大小(单位:KB)\n * @param invalidText 输入无效时返回文本\n */\nexport function formatFileSizeFromKB(sizeKB: number, invalidText: string = '') {\n const { size, unit, text } = formatUnitSize(sizeKB, 1024, ['KB', 'MB', 'GB'], invalidText)\n\n if (text === invalidText) {\n return invalidText\n }\n\n // 整数部分\n const integerPart = Math.floor(size)\n\n // 根据整数位数动态控制小数位\n let fractionDigits: number\n // 整数位 >= 3:不保留小数\n if (integerPart > 99) fractionDigits = 0\n // 整数位 = 2:保留 1 位小数\n else if (integerPart > 9) fractionDigits = 1\n // 整数位 = 1:保留 2 位小数\n else fractionDigits = 2\n\n const rounded = Math.round(size * 10 ** fractionDigits) / 10 ** fractionDigits\n return `${rounded} ${unit}`\n}\n\n/**\n * 获取单个文件的大小(字节)\n * @param filePath 文件路径\n * @returns 文件大小,读取失败返回 0\n */\nasync function getFileSize(filePath: string): Promise<number> {\n try {\n const stat = await fs.stat(filePath)\n return stat.size\n } catch {\n // 权限不足或文件不存在时忽略,当作 0\n return 0\n }\n}\n\n/**\n * 获取符号链接自身的大小(指向路径的字符串长度,不是目标文件大小)\n */\nasync function getSymbolicLinkSize(linkPath: string): Promise<number> {\n try {\n const stat = await fs.lstat(linkPath)\n return stat.size\n } catch {\n return 0\n }\n}\n\n/**\n * 获取目录总大小(字节),递归统计所有子文件\n * 符号链接:只计算链接文件本身的大小,不跟随指向目录\n * 权限错误:跳过该文件/目录,大小计为 0\n * @param dir 目录路径\n * @returns 总字节数\n */\nexport async function getDirSize(dir: string): Promise<number> {\n let entries\n try {\n entries = await fs.readdir(dir, { withFileTypes: true })\n } catch {\n // 无法读取目录时忽略,计为 0\n return 0\n }\n\n const tasks: Promise<number>[] = []\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n\n // 目录:递归\n if (entry.isDirectory()) {\n tasks.push(getDirSize(fullPath))\n continue\n }\n\n // 符号链接:只计算链接自身大小(不跟随)\n if (entry.isSymbolicLink()) {\n tasks.push(getSymbolicLinkSize(fullPath))\n continue\n }\n\n // 普通文件\n tasks.push(getFileSize(fullPath))\n }\n\n const results = await Promise.allSettled(tasks)\n return results.reduce((total, result) => {\n return total + (result.status === 'fulfilled' ? result.value : 0)\n }, 0)\n}\n\n/**\n * 获取文件/文件夹大小\n * @param filePath 文件/文件夹路径\n */\nexport async function getFileSizeKB(filePath: string) {\n try {\n const stat = await fs.stat(filePath)\n if (stat.isDirectory()) {\n return (await getDirSize(filePath)) / 1024\n } else {\n return stat.size / 1024\n }\n } catch {\n return 0\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 { createAbortError } from '../../../core/index.js'\nimport { exec } from 'node:child_process'\nimport * as iconv from 'iconv-lite'\n\n/**\n * 命令执行的选项\n */\ninterface ExecOptions {\n /**\n * 判断结果码是否成功\n * @param number 结果码\n */\n codeIsSuccess?: (number: number) => boolean\n /**\n * 终止信号\n */\n signal?: AbortSignal\n}\n\n/**\n * 执行 windows 的命令\n * @param cmd 命令\n * @param options 执行选项\n */\nexport async function execWinCmd(cmd: string, options?: ExecOptions) {\n return new Promise<string>((resolve, reject) => {\n // 前置检查:如果 signal 已终止,直接拒绝\n if (options?.signal?.aborted) {\n throw createAbortError()\n }\n let abortHandler: (() => void) | null = null\n\n const child = exec(`${cmd}`, { encoding: 'buffer' }, (error, stdout, stderr) => {\n const stdoutStr = iconv.decode(stdout, 'cp936')\n const stderrStr = iconv.decode(stderr, 'cp936')\n\n // 清理 abort 监听\n if (abortHandler) {\n options?.signal?.removeEventListener('abort', abortHandler)\n }\n\n const exitCode = error ? Number((error as NodeJS.ErrnoException).code ?? 0) : 0\n if (options?.codeIsSuccess ? !options.codeIsSuccess(exitCode) : exitCode !== 0) {\n reject(new Error(`命令行执行出错 (${exitCode}): ${stderrStr || stdoutStr}`))\n } else {\n resolve(stdoutStr)\n }\n })\n // 进程取消后超时响应的处理定时器\n let timeout: ReturnType<typeof setTimeout>\n // 定义 abort 处理函数\n abortHandler = () => {\n // 请求终止,进程可拒绝或延迟\n child.kill('SIGTERM')\n timeout = setTimeout(() => {\n child.kill('SIGKILL')\n }, 3000)\n reject(createAbortError())\n }\n // 注册 abort 监听\n if (options?.signal) {\n options.signal.addEventListener('abort', abortHandler)\n }\n\n // 进程意外终止处理\n child.on('close', () => {\n if (timeout !== undefined) clearTimeout(timeout)\n options?.signal?.removeEventListener('abort', abortHandler)\n })\n })\n}\n","import path from 'node:path'\nimport { execWinCmd } from './cmd.js'\nimport { isFile } from '../file/base.js'\n\n/**\n * 文件拷贝工具,支持文件或文件夹\n */\nexport async function copyFile(source: string, destination: string, signal?: AbortSignal) {\n const src = path.resolve(source)\n const dest = path.resolve(destination)\n\n let command: string\n\n if (await isFile(source)) {\n // 文件用 copy 命令\n command = `copy \"${src}\" \"${dest}\"`\n await execWinCmd(command, { signal: signal })\n } else {\n // 文件夹用 robocopy\n command = `robocopy \"${src}\" \"${dest}\" /E /NFL /NDL /NJH /NJS /NC /NS /NP`\n await execWinCmd(command, {\n codeIsSuccess: (number) => number < 8,\n signal: signal,\n })\n }\n}\n","import path from 'node:path'\nimport * as fs from 'node:fs/promises'\nimport { execWinCmd } from './cmd.js'\n\n/**\n * 打开资源管理器并定位到目录或者文件\n * @param fileOrDir 定位的目录或文件\n */\nexport async function showInExplorer(fileOrDir: string) {\n fileOrDir = path.resolve(fileOrDir)\n if ((await fs.stat(fileOrDir)).isDirectory()) {\n await execWinCmd(`start \"\" \"${fileOrDir}\"`)\n } else {\n await execWinCmd(`start \"\" explorer /select,\"${fileOrDir}\"`)\n }\n}\n","import { execWinCmd } from './cmd.js'\nimport path from 'node:path'\nimport { ensureDir } from '../file/base.js'\n\n/**\n * 打开注册表\n * @param path 显示的路径\n */\nexport async function openRegedit(path: string) {\n return execWinCmd(\n `taskkill /f /im regedit.exe & REG ADD \"HKCU\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Applets\\\\Regedit\" /v \"LastKey\" /d \"${path}\" /f & regedit`,\n )\n}\n\n/**\n * 导出注册表\n * @param regPath 注册表路径\n * @param filePath 导出的文件路径\n */\nexport async function exportRegedit(regPath: string, filePath: string) {\n filePath = path.resolve(filePath)\n await ensureDir(regPath)\n await execWinCmd(`reg export \"${regPath}\" \"${filePath}\" /y`, undefined)\n}\n\n/**\n * 导入注册表\n * @param regPath 注册表路径\n * @param filePath 导入的文件路径\n */\nexport async function importRegedit(regPath: string, filePath: string) {\n await execWinCmd(`reg import \"${path.resolve(filePath)}\"`, undefined)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/node/utils/env.ts","../src/node/utils/file/base.ts","../src/node/utils/file/delete.ts","../src/node/utils/file/download.ts","../src/node/utils/file/find.ts","../src/node/utils/file/json.ts","../src/core/utils/number/format.ts","../src/node/utils/file/size.ts","../src/core/utils/error.ts","../src/node/utils/win/cmd.ts","../src/node/utils/win/copy.ts","../src/node/utils/win/explorer.ts","../src/node/utils/win/regedit.ts"],"sourcesContent":["/**\n * 获取环境变量\n */\nexport function getEnv(): { [p: string]: string } {\n const env: { [p: string]: string } = {}\n for (const envKey in process.env) {\n env[envKey] = process.env[envKey] as string\n }\n return env\n}\n","import fs from 'node:fs/promises'\nimport { mkdirSync } from 'node:fs'\n\n/**\n * 判断路径是否是文件\n */\nexport async function isFile(filePath: string) {\n try {\n return (await fs.stat(filePath)).isFile()\n } catch {\n return false\n }\n}\n\n/**\n * 判断文件是否存在\n */\nexport async function existsFile(file: string, mode?: number) {\n try {\n fs.access(file, mode)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * 确保目录存在\n */\nexport function ensureDirSync(dirPath: string) {\n mkdirSync(dirPath, { recursive: true })\n}\n\n/**\n * 确保目录存在\n */\nexport async function ensureDir(dirPath: string) {\n await fs.mkdir(dirPath, { recursive: true })\n}\n\n/**\n * 判断错误是否为文件不存在\n */\nexport function isFileNotFoundError(error: unknown): boolean {\n return (\n typeof error === 'object' && error !== null && 'code' in error && (error as NodeJS.ErrnoException).code === 'ENOENT'\n )\n}\n","import fs from 'node:fs/promises'\nimport path from 'node:path'\n\n/**\n * 删除指定目录下的所有文件和子目录(保留指定目录)\n * @param dir 目标目录路径\n * @return 成功删除的文件或目录路径数组\n */\nexport async function emptyDirectory(dir: string) {\n const deletedPaths: string[] = []\n // 读取目录中的所有文件和子目录\n const entries = await fs.readdir(dir, { withFileTypes: true })\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n if (entry.isDirectory()) {\n // 如果是目录,递归删除其内容\n deletedPaths.push(...(await emptyDirectory(fullPath)))\n // 删除空目录\n await fs.rmdir(fullPath)\n } else {\n // 如果是文件,删除文件\n await fs.unlink(fullPath)\n }\n deletedPaths.push(fullPath)\n }\n return deletedPaths\n}\n\n/**\n * 删除文件(不删除目录)\n * @param paths 文件路径列表\n * @returns 成功删除的文件路径数组\n */\nexport async function deleteFiles(paths: string[]): Promise<string[]> {\n const results = await Promise.allSettled(\n paths.map(async (file) => {\n await fs.unlink(file)\n return file\n }),\n )\n\n return results.filter((r): r is PromiseFulfilledResult<string> => r.status === 'fulfilled').map((r) => r.value)\n}\n","import { pipeline } from 'node:stream/promises'\nimport { createWriteStream } from 'node:fs'\nimport path from 'node:path'\n\n/**\n * 下载文件\n */\nexport async function downloadFile(url: string, filePath: string) {\n const file = path.resolve(filePath)\n const res = await fetch(url)\n\n if (!res.ok || !res.body) {\n throw new Error(`下载失败: ${res.status}`)\n }\n\n await pipeline(res.body, createWriteStream(file))\n}\n","import fs from 'node:fs/promises'\nimport path from 'node:path'\n\n/**\n * 查找目录下符合条件的文件路径(不遍历子目录)\n * @param dir 目标目录路径\n * @param prefix 文件名前缀(需全字匹配)\n * @param suffix 文件名后缀(需全字匹配,如 \".txt\")\n * @return 符合条件的文件完整路径的数组\n */\nexport async function findFilesByPrefixAndSuffix(dir: string, prefix?: string, suffix?: string): Promise<string[]> {\n return (await fs.readdir(dir, { withFileTypes: true }))\n .filter(\n (dirent) =>\n // 仅保留文件(排除子目录)\n dirent.isFile() &&\n // 文件名匹配前缀\n dirent.name.startsWith(prefix || '') &&\n // 文件名匹配后缀\n dirent.name.endsWith(suffix || ''),\n )\n .map((dirent) => path.join(dir, dirent.name))\n}\n\n/**\n * 查找文件(包含子目录)\n * @param dir 目录\n * @param target 查找目标名称或者过滤函数\n */\nexport async function findFiles(\n dir: string,\n target: string | ((fileName: string, fullPath?: string) => boolean),\n): Promise<string[]> {\n const results: string[] = []\n const entries = await fs.readdir(dir, { withFileTypes: true })\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n if (entry.isDirectory()) {\n results.push(...(await findFiles(fullPath, target)))\n } else if (typeof target === 'string' && entry.name === target) {\n results.push(fullPath)\n } else if (typeof target === 'function' && target(entry.name, fullPath)) {\n results.push(fullPath)\n }\n }\n return results\n}\n","import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { isFileNotFoundError, ensureDir, isFile } from './base.js'\n\n/**\n * 读取 JSON 文件\n */\nexport async function readJSONFile<T>(filePath: string): Promise<T> {\n if (!(await isFile(filePath))) {\n throw new Error('文件不存在')\n }\n const jsonRaw = await fs.readFile(path.resolve(filePath), 'utf-8')\n return JSON.parse(jsonRaw) as T\n}\n\n/**\n * 将数据原子写入 JSON 文件(先写临时文件再替换)\n */\nexport async function writeJSONFile<T>(file: string, data: T): Promise<void> {\n const tempFile = `${file}.tmp.${Date.now()}`\n const jsonContent = JSON.stringify(data, null, 2)\n await fs.writeFile(tempFile, jsonContent, 'utf-8')\n // 直接替换(会覆原文件)\n await fs.rename(tempFile, file)\n}\n\n/**\n * 读取 JSON 文件,修改后写回(原子操作)\n */\nexport async function updateJSON<T>(file: string, updater: (oldData: T) => T): Promise<T> {\n const oldData = await readJSONFile<T>(file)\n const newData = updater(oldData)\n await writeJSONFile(file, newData)\n return newData\n}\n\n/**\n * 从文件读取 JSON,若文件不存在则调用 initData 初始化并写入\n *\n * @param file 文件绝对路径或相对路径\n * @param initData 返回要写入的数据的异步函数\n * @returns 解析后的数据\n */\nexport async function readOrInitJSON<T>(file: string, initData: () => Promise<T>): Promise<T> {\n try {\n const content = await fs.readFile(file, 'utf-8')\n // 解析 JSON,若失败则抛出错误(不会误判为“不存在”)\n return JSON.parse(content) as T\n } catch (error) {\n // 文件不存在等其他错误要透传\n if (!isFileNotFoundError(error)) {\n throw error\n }\n // 文件不存在,生成初始数据\n const data = await initData()\n // 确保目录存在\n await ensureDir(path.dirname(file))\n // 写入文件,格式化 JSON\n await fs.writeFile(file, JSON.stringify(data, null, 2), 'utf-8')\n return data\n }\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","import { formatUnitSize } from '../../../core/utils/number/format.js'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\n\n/**\n * 将 KB 文件大小格式化为字符串\n * @param sizeKB 文件大小(单位:KB)\n * @param invalidText 输入无效时返回文本\n */\nexport function formatFileSizeFromKB(sizeKB: number, invalidText: string = '') {\n const { size, unit, text } = formatUnitSize(sizeKB, 1024, ['KB', 'MB', 'GB'], invalidText)\n\n if (text === invalidText) {\n return invalidText\n }\n\n // 整数部分\n const integerPart = Math.floor(size)\n\n // 根据整数位数动态控制小数位\n let fractionDigits: number\n // 整数位 >= 3:不保留小数\n if (integerPart > 99) fractionDigits = 0\n // 整数位 = 2:保留 1 位小数\n else if (integerPart > 9) fractionDigits = 1\n // 整数位 = 1:保留 2 位小数\n else fractionDigits = 2\n\n const rounded = Math.round(size * 10 ** fractionDigits) / 10 ** fractionDigits\n return `${rounded} ${unit}`\n}\n\n/**\n * 获取单个文件的大小(字节)\n * @param filePath 文件路径\n * @returns 文件大小,读取失败返回 0\n */\nasync function getFileSize(filePath: string): Promise<number> {\n try {\n const stat = await fs.stat(filePath)\n return stat.size\n } catch {\n // 权限不足或文件不存在时忽略,当作 0\n return 0\n }\n}\n\n/**\n * 获取符号链接自身的大小(指向路径的字符串长度,不是目标文件大小)\n */\nasync function getSymbolicLinkSize(linkPath: string): Promise<number> {\n try {\n const stat = await fs.lstat(linkPath)\n return stat.size\n } catch {\n return 0\n }\n}\n\n/**\n * 获取目录总大小(字节),递归统计所有子文件\n * 符号链接:只计算链接文件本身的大小,不跟随指向目录\n * 权限错误:跳过该文件/目录,大小计为 0\n * @param dir 目录路径\n * @returns 总字节数\n */\nexport async function getDirSize(dir: string): Promise<number> {\n let entries\n try {\n entries = await fs.readdir(dir, { withFileTypes: true })\n } catch {\n // 无法读取目录时忽略,计为 0\n return 0\n }\n\n const tasks: Promise<number>[] = []\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n\n // 目录:递归\n if (entry.isDirectory()) {\n tasks.push(getDirSize(fullPath))\n continue\n }\n\n // 符号链接:只计算链接自身大小(不跟随)\n if (entry.isSymbolicLink()) {\n tasks.push(getSymbolicLinkSize(fullPath))\n continue\n }\n\n // 普通文件\n tasks.push(getFileSize(fullPath))\n }\n\n const results = await Promise.allSettled(tasks)\n return results.reduce((total, result) => {\n return total + (result.status === 'fulfilled' ? result.value : 0)\n }, 0)\n}\n\n/**\n * 获取文件/文件夹大小\n * @param filePath 文件/文件夹路径\n */\nexport async function getFileSizeKB(filePath: string) {\n try {\n const stat = await fs.stat(filePath)\n if (stat.isDirectory()) {\n return (await getDirSize(filePath)) / 1024\n } else {\n return stat.size / 1024\n }\n } catch {\n return 0\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 { createAbortError } from '../../../core/index.js'\nimport { exec } from 'node:child_process'\nimport * as iconv from 'iconv-lite'\n\n/**\n * 命令执行的选项\n */\ninterface ExecOptions {\n /**\n * 判断结果码是否成功\n * @param number 结果码\n */\n codeIsSuccess?: (number: number) => boolean\n /**\n * 终止信号\n */\n signal?: AbortSignal\n}\n\n/**\n * 执行 windows 的命令\n * @param cmd 命令\n * @param options 执行选项\n */\nexport async function execWinCmd(cmd: string, options?: ExecOptions) {\n return new Promise<string>((resolve, reject) => {\n // 前置检查:如果 signal 已终止,直接拒绝\n if (options?.signal?.aborted) {\n throw createAbortError()\n }\n let abortHandler: (() => void) | null = null\n\n const child = exec(`${cmd}`, { encoding: 'buffer' }, (error, stdout, stderr) => {\n const stdoutStr = iconv.decode(stdout, 'cp936')\n const stderrStr = iconv.decode(stderr, 'cp936')\n\n // 清理 abort 监听\n if (abortHandler) {\n options?.signal?.removeEventListener('abort', abortHandler)\n }\n\n const exitCode = error ? Number((error as NodeJS.ErrnoException).code ?? 0) : 0\n if (options?.codeIsSuccess ? !options.codeIsSuccess(exitCode) : exitCode !== 0) {\n reject(new Error(`命令行执行出错 (${exitCode}): ${stderrStr || stdoutStr}`))\n } else {\n resolve(stdoutStr)\n }\n })\n // 进程取消后超时响应的处理定时器\n let timeout: ReturnType<typeof setTimeout>\n // 定义 abort 处理函数\n abortHandler = () => {\n // 请求终止,进程可拒绝或延迟\n child.kill('SIGTERM')\n timeout = setTimeout(() => {\n child.kill('SIGKILL')\n }, 3000)\n reject(createAbortError())\n }\n // 注册 abort 监听\n if (options?.signal) {\n options.signal.addEventListener('abort', abortHandler)\n }\n\n // 进程意外终止处理\n child.on('close', () => {\n if (timeout !== undefined) clearTimeout(timeout)\n options?.signal?.removeEventListener('abort', abortHandler)\n })\n })\n}\n","import path from 'node:path'\nimport { execWinCmd } from './cmd.js'\nimport { isFile } from '../file/base.js'\n\n/**\n * 文件拷贝工具,支持文件或文件夹\n */\nexport async function copyFile(source: string, destination: string, signal?: AbortSignal) {\n const src = path.resolve(source)\n const dest = path.resolve(destination)\n\n let command: string\n\n if (await isFile(source)) {\n // 文件用 copy 命令\n command = `copy \"${src}\" \"${dest}\"`\n await execWinCmd(command, { signal: signal })\n } else {\n // 文件夹用 robocopy\n command = `robocopy \"${src}\" \"${dest}\" /E /NFL /NDL /NJH /NJS /NC /NS /NP`\n await execWinCmd(command, {\n codeIsSuccess: (number) => number < 8,\n signal: signal,\n })\n }\n}\n","import path from 'node:path'\nimport * as fs from 'node:fs/promises'\nimport { execWinCmd } from './cmd.js'\n\n/**\n * 打开资源管理器并定位到目录或者文件\n * @param fileOrDir 定位的目录或文件\n */\nexport async function showInExplorer(fileOrDir: string) {\n fileOrDir = path.resolve(fileOrDir)\n if ((await fs.stat(fileOrDir)).isDirectory()) {\n await execWinCmd(`start \"\" \"${fileOrDir}\"`)\n } else {\n await execWinCmd(`start \"\" explorer /select,\"${fileOrDir}\"`)\n }\n}\n","import { execWinCmd } from './cmd.js'\nimport path from 'node:path'\nimport { ensureDir } from '../file/base.js'\n\n/**\n * 打开注册表\n * @param path 显示的路径\n */\nexport async function openRegedit(path: string) {\n return execWinCmd(\n `taskkill /f /im regedit.exe & REG ADD \"HKCU\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Applets\\\\Regedit\" /v \"LastKey\" /d \"${path}\" /f & regedit`,\n )\n}\n\n/**\n * 导出注册表\n * @param regPath 注册表路径\n * @param filePath 导出的文件路径\n */\nexport async function exportRegedit(regPath: string, filePath: string) {\n filePath = path.resolve(filePath)\n await ensureDir(regPath)\n await execWinCmd(`reg export \"${regPath}\" \"${filePath}\" /y`, undefined)\n}\n\n/**\n * 导入注册表\n * @param regPath 注册表路径\n * @param filePath 导入的文件路径\n */\nexport async function importRegedit(regPath: string, filePath: string) {\n await execWinCmd(`reg import \"${path.resolve(filePath)}\"`, undefined)\n}\n"],"mappings":"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","names":["getEnv","env","envKey","fs","mkdirSync","isFile","filePath","existsFile","file","mode","ensureDirSync","dirPath","ensureDir","isFileNotFoundError","error","fs","path","emptyDirectory","dir","deletedPaths","entries","entry","fullPath","deleteFiles","paths","file","r","pipeline","createWriteStream","path","downloadFile","url","filePath","file","res","fs","path","findFilesByPrefixAndSuffix","dir","prefix","suffix","dirent","findFiles","target","results","entries","entry","fullPath","fs","path","readJSONFile","filePath","isFile","jsonRaw","fs","path","writeJSONFile","file","data","tempFile","jsonContent","updateJSON","updater","oldData","newData","readOrInitJSON","initData","content","error","isFileNotFoundError","ensureDir","formatUnitSize","value","base","units","invalidText","size","unitIndex","fs","path","formatFileSizeFromKB","sizeKB","invalidText","size","unit","text","formatUnitSize","integerPart","fractionDigits","getFileSize","filePath","getSymbolicLinkSize","linkPath","getDirSize","dir","entries","tasks","entry","fullPath","total","result","getFileSizeKB","stat","createAbortError","msg","error","exec","iconv","execWinCmd","cmd","options","resolve","reject","createAbortError","abortHandler","child","error","stdout","stderr","stdoutStr","stderrStr","exitCode","timeout","path","copyFile","source","destination","signal","src","path","dest","command","isFile","execWinCmd","number","path","fs","showInExplorer","fileOrDir","path","execWinCmd","path","openRegedit","path","execWinCmd","exportRegedit","regPath","filePath","ensureDir","importRegedit"]}
|
package/package.json
CHANGED
|
@@ -1,39 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ybgnb/utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"author": "hzhilong",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "自用工具库",
|
|
7
7
|
"type": "module",
|
|
8
|
-
"main": "./dist/core.
|
|
8
|
+
"main": "./dist/core.cjs",
|
|
9
9
|
"module": "./dist/core.js",
|
|
10
10
|
"types": "./dist/core.d.ts",
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
13
|
"types": "./dist/core.d.ts",
|
|
14
14
|
"import": "./dist/core.js",
|
|
15
|
-
"require": "./dist/core.
|
|
15
|
+
"require": "./dist/core.cjs"
|
|
16
16
|
},
|
|
17
17
|
"./dom": {
|
|
18
18
|
"types": "./dist/dom.d.ts",
|
|
19
19
|
"import": "./dist/dom.js",
|
|
20
|
-
"require": "./dist/dom.
|
|
20
|
+
"require": "./dist/dom.cjs"
|
|
21
21
|
},
|
|
22
22
|
"./node": {
|
|
23
23
|
"types": "./dist/node.d.ts",
|
|
24
24
|
"import": "./dist/node.js",
|
|
25
|
-
"require": "./dist/node.
|
|
25
|
+
"require": "./dist/node.cjs"
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"dist"
|
|
30
30
|
],
|
|
31
31
|
"scripts": {
|
|
32
|
-
"check": "tsc --build --noEmit",
|
|
32
|
+
"check": "tsc --build --noEmit && eslint .",
|
|
33
33
|
"lint": "eslint . --fix",
|
|
34
34
|
"format": "prettier --write .",
|
|
35
|
-
"barrelsby": "barrelsby -c barrelsby.json &
|
|
36
|
-
"build": "
|
|
35
|
+
"barrelsby": "barrelsby -c barrelsby.json & import-suffixer \"src/**/*.ts\"",
|
|
36
|
+
"build": "tsx ./scripts/build.ts",
|
|
37
37
|
"npm login": "npm login",
|
|
38
38
|
"npm publish": "npm publish --access public"
|
|
39
39
|
},
|
|
@@ -55,12 +55,12 @@
|
|
|
55
55
|
"barrelsby": "^2.8.1",
|
|
56
56
|
"eslint": "^9.39.4",
|
|
57
57
|
"eslint-config-prettier": "^10.1.8",
|
|
58
|
+
"import-suffixer": "^0.0.1",
|
|
58
59
|
"prettier": "^3.8.1",
|
|
59
60
|
"rimraf": "^6.1.3",
|
|
61
|
+
"tsup": "^8.5.1",
|
|
60
62
|
"typescript": "^6.0.2",
|
|
61
|
-
"typescript-eslint": "^8.58.0"
|
|
62
|
-
"vite": "^8.0.8",
|
|
63
|
-
"vite-plugin-dts": "^4.5.4"
|
|
63
|
+
"typescript-eslint": "^8.58.0"
|
|
64
64
|
},
|
|
65
65
|
"optionalDependencies": {
|
|
66
66
|
"iconv-lite": "^0.7.2"
|
package/dist/core/index.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export * from './error/common-error.js';
|
|
2
|
-
export * from './result/biz-result.js';
|
|
3
|
-
export * from './result/exec-biz.js';
|
|
4
|
-
export * from './types/helpers.js';
|
|
5
|
-
export * from './types/physical.js';
|
|
6
|
-
export * from './utils/array.js';
|
|
7
|
-
export * from './utils/error.js';
|
|
8
|
-
export * from './utils/fetch.js';
|
|
9
|
-
export * from './utils/function.js';
|
|
10
|
-
export * from './utils/github.js';
|
|
11
|
-
export * from './utils/random.js';
|
|
12
|
-
export * from './utils/serialize.js';
|
|
13
|
-
export * from './utils/sleep.js';
|
|
14
|
-
export * from './utils/time.js';
|
|
15
|
-
export * from './utils/type.js';
|
|
16
|
-
export * from './utils/url.js';
|
|
17
|
-
export * from './utils/number/format.js';
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 业务执行结果
|
|
3
|
-
*/
|
|
4
|
-
export declare class BizResult<T> {
|
|
5
|
-
success: boolean;
|
|
6
|
-
msg: string;
|
|
7
|
-
data?: T;
|
|
8
|
-
constructor(success: boolean, msg: string, data?: T);
|
|
9
|
-
static createSuccess<T>(data: T): BizResult<T>;
|
|
10
|
-
static createFail<T>(msg?: string, data?: T): BizResult<T>;
|
|
11
|
-
static createError<T>(e: unknown): BizResult<T>;
|
|
12
|
-
/**
|
|
13
|
-
* 展开成Promise
|
|
14
|
-
*/
|
|
15
|
-
toPromise(): Promise<void>;
|
|
16
|
-
toPromise<T>(): Promise<T>;
|
|
17
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 提取getter属性
|
|
3
|
-
*/
|
|
4
|
-
export type ExtractGetterProperties<T> = {
|
|
5
|
-
[K in keyof T as K extends `get${infer Rest}` ? Uncapitalize<Rest> : never]: T[K] extends (...args: any[]) => Promise<infer R> ? R : never;
|
|
6
|
-
};
|
|
7
|
-
/**
|
|
8
|
-
* 至少包含一个字段
|
|
9
|
-
*/
|
|
10
|
-
export type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> & {
|
|
11
|
-
[K in Keys]: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>;
|
|
12
|
-
}[Keys];
|
|
13
|
-
/**
|
|
14
|
-
* 用元组限制长度
|
|
15
|
-
*/
|
|
16
|
-
export type MaxLengthArray<T, N extends number> = T[] & {
|
|
17
|
-
length: N;
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* 提取 T 中所有值类型为 V 的键
|
|
21
|
-
*/
|
|
22
|
-
export type KeysMatching<T, V> = {
|
|
23
|
-
[K in keyof T]: T[K] extends V ? K : never;
|
|
24
|
-
}[keyof T];
|
|
25
|
-
/**
|
|
26
|
-
* 任意方法
|
|
27
|
-
*/
|
|
28
|
-
export type AnyFn = (...args: any[]) => any;
|
|
29
|
-
/**
|
|
30
|
-
* 提取所有方法
|
|
31
|
-
*/
|
|
32
|
-
export type MethodKeys<T> = {
|
|
33
|
-
[K in keyof T]-?: T[K] extends AnyFn ? K : never;
|
|
34
|
-
}[keyof T];
|
|
35
|
-
/**
|
|
36
|
-
* 方法参数类型
|
|
37
|
-
*/
|
|
38
|
-
export type MethodParams<T> = T extends (...args: infer P) => any ? P : never;
|
|
39
|
-
/**
|
|
40
|
-
* 方法返回类型
|
|
41
|
-
*/
|
|
42
|
-
export type MethodReturn<T> = T extends (...args: any[]) => infer R ? R : never;
|
|
43
|
-
/**
|
|
44
|
-
* 提取所有函数 key
|
|
45
|
-
*/
|
|
46
|
-
export type FunctionKeys<T> = {
|
|
47
|
-
[K in keyof T]: T[K] extends AnyFn ? K : never;
|
|
48
|
-
}[keyof T];
|
|
49
|
-
/**
|
|
50
|
-
* 拥有指定键集合的对象类型
|
|
51
|
-
*/
|
|
52
|
-
export type ObjectWithKeys<K extends string | symbol> = {
|
|
53
|
-
[key in K]: any;
|
|
54
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 是否为空数组
|
|
3
|
-
* @param data
|
|
4
|
-
*/
|
|
5
|
-
export declare function isEmptyArr(data: unknown): boolean;
|
|
6
|
-
/**
|
|
7
|
-
* 将数组分块为指定大小的多个子数组
|
|
8
|
-
* @param arr 原数组
|
|
9
|
-
* @param size 每个块的长度
|
|
10
|
-
* @example chunk([1,2,3,4,5], 2) => [[1,2],[3,4],[5]]
|
|
11
|
-
*/
|
|
12
|
-
export declare function chunk<T>(arr: T[], size: number): T[][];
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { CommonError } from '../error/common-error.js';
|
|
2
|
-
/**
|
|
3
|
-
* 是否为取消操作的错误
|
|
4
|
-
*/
|
|
5
|
-
export declare function isCanceledError(err: unknown): boolean;
|
|
6
|
-
/**
|
|
7
|
-
* 创建取消错误
|
|
8
|
-
* @param msg
|
|
9
|
-
*/
|
|
10
|
-
export declare function createAbortError(msg?: string): Error;
|
|
11
|
-
/**
|
|
12
|
-
* 是否为通用错误对象
|
|
13
|
-
*/
|
|
14
|
-
export declare function isCommonError(error: unknown): error is CommonError;
|
|
15
|
-
/**
|
|
16
|
-
* 转换到通用异常
|
|
17
|
-
*/
|
|
18
|
-
export declare function convertToCommonError(error: unknown, prefix?: string): Error;
|
|
19
|
-
/**
|
|
20
|
-
* 获取异常信息
|
|
21
|
-
*/
|
|
22
|
-
export declare function getErrorMessage(error: unknown): string;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 用于指定 `fetch` 响应体的解析方式。
|
|
3
|
-
* 对应 `Response` 对象的不同解析方法(`.json()`、`.text()` 等)。
|
|
4
|
-
*/
|
|
5
|
-
export type ResponseBodyFormat = 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData';
|
|
6
|
-
/**
|
|
7
|
-
* 创建响应错误
|
|
8
|
-
*/
|
|
9
|
-
export declare function createResponseError(response: Response): Error;
|
|
10
|
-
/**
|
|
11
|
-
* 使用指定的响应解析格式发起 fetch 请求
|
|
12
|
-
*/
|
|
13
|
-
export declare function fetchWithFormat<T = any>(url: string, format: ResponseBodyFormat, init?: RequestInit): Promise<T>;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 随机运行参数
|
|
3
|
-
* @param fns
|
|
4
|
-
* @param maxCount 最多执行次数(1 ~ fns.length)
|
|
5
|
-
*/
|
|
6
|
-
export declare function runRandomFunctions(fns: Array<() => void>, maxCount?: number): void;
|
|
7
|
-
/**
|
|
8
|
-
* 将数字范围按批次处理,每个批次调用一次异步函数
|
|
9
|
-
*
|
|
10
|
-
* @param start - 起始值(包含)
|
|
11
|
-
* @param end - 结束值(包含)
|
|
12
|
-
* @param batchSize - 每批最大元素个数
|
|
13
|
-
* @param processor - 处理单批数字数组的异步函数
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* // 分批处理 1..10,每批最多 3 个数字
|
|
17
|
-
* await processRangeInBatches(1, 10, 3, async (batch) => {
|
|
18
|
-
* console.log(batch) // 输出: [1,2,3], [4,5,6], [7,8,9], [10]
|
|
19
|
-
* })
|
|
20
|
-
*/
|
|
21
|
-
export declare function processRangeInBatches(start: number, end: number, batchSize: number, processor: (batch: number[]) => Promise<void>): Promise<void>;
|
|
22
|
-
/**
|
|
23
|
-
* 动态调用
|
|
24
|
-
* @param root 对象
|
|
25
|
-
* @param path 调用路径
|
|
26
|
-
* @param args 参数
|
|
27
|
-
*/
|
|
28
|
-
export declare function dynamicCall<T = any>(root: any, path: string, ...args: any[]): T;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/** github 仓库信息 */
|
|
2
|
-
export interface GitHubRepo {
|
|
3
|
-
/** 仓库所有者(用户或组织名) */
|
|
4
|
-
owner: string;
|
|
5
|
-
/** 仓库名称 */
|
|
6
|
-
repo: string;
|
|
7
|
-
}
|
|
8
|
-
/** github 仓库分支信息 */
|
|
9
|
-
export type GitHubRepoBranch = GitHubRepo & {
|
|
10
|
-
/** 分支名称 */
|
|
11
|
-
branch: string;
|
|
12
|
-
};
|
|
13
|
-
/** github 仓库文件信息 */
|
|
14
|
-
export type GitHubRepoFile = GitHubRepoBranch & {
|
|
15
|
-
/** 文件路径 */
|
|
16
|
-
filePath: string;
|
|
17
|
-
};
|
|
18
|
-
/**
|
|
19
|
-
* 从 url 解析 github 仓库信息
|
|
20
|
-
* @param repositoryUrl 仓库 URL(支持带有git+前缀、具体文件路径)
|
|
21
|
-
*/
|
|
22
|
-
export declare function parseGithubRepoUrl(repositoryUrl: string): GitHubRepoBranch;
|
|
23
|
-
/**
|
|
24
|
-
* 解析 github 仓库文件的原始内容的 url
|
|
25
|
-
*/
|
|
26
|
-
export declare function parseGithubRawUrl(gitHubRepoFile: GitHubRepoFile): string;
|
|
27
|
-
/**
|
|
28
|
-
* 获取 github 仓库文件的 json 内容并解析为对象 T
|
|
29
|
-
* @param gitHubRepoFile
|
|
30
|
-
*/
|
|
31
|
-
export declare function getGithubRawJson<O>(gitHubRepoFile: GitHubRepoFile): Promise<O>;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 格式化后的单位数据(如文件大小)
|
|
3
|
-
*/
|
|
4
|
-
export interface FormattedUnitSize {
|
|
5
|
-
/** 换算后该单位的数值(未四舍五入) */
|
|
6
|
-
size: number;
|
|
7
|
-
/** 单位名称,如 'MB' */
|
|
8
|
-
unit: string;
|
|
9
|
-
/** 显示文本:数值四舍五入保留两位小数 + 单位,如 '1.50 MB' */
|
|
10
|
-
text: string;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* 按进制自动格式化单位
|
|
14
|
-
* @param value 数值
|
|
15
|
-
* @param base 进制(1024 / 1000)
|
|
16
|
-
* @param units 单位列表
|
|
17
|
-
* @param invalidText 无效值返回文本
|
|
18
|
-
*/
|
|
19
|
-
export declare function formatUnitSize(value: number, base: number, units: string[], invalidText?: string): FormattedUnitSize;
|