@zwa73/utils 1.0.124 → 1.0.125

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.
@@ -1,4 +1,4 @@
1
1
  import { UtilFT } from "./UtilFileTools";
2
2
  import { UtilFunc } from "./UtilFunctions";
3
- export declare const outcome: typeof UtilFunc.outcome, matchProc: typeof UtilFunc.matchProc, sucesProc: typeof UtilFunc.sucesProc, isFailed: typeof UtilFunc.isFailed, isSafeNumber: typeof UtilFunc.isSafeNumber, isSuccess: typeof UtilFunc.isSuccess, likeNone: typeof UtilFunc.likeNone, expect: typeof UtilFunc.expect, assertType: typeof UtilFunc.assertType, assertLiteral: typeof UtilFunc.assertLiteral, deepClone: typeof UtilFunc.deepClone, sleep: typeof UtilFunc.sleep, stringifyJToken: typeof UtilFunc.stringifyJToken, getTime: typeof UtilFunc.getTime, mapEntries: typeof UtilFunc.mapEntries, dedent: typeof UtilFunc.dedent, throwError: typeof UtilFunc.throwError;
3
+ export declare const outcome: typeof UtilFunc.outcome, matchProc: typeof UtilFunc.matchProc, sucesProc: typeof UtilFunc.sucesProc, isFailed: typeof UtilFunc.isFailed, isSafeNumber: typeof UtilFunc.isSafeNumber, isSuccess: typeof UtilFunc.isSuccess, likeNone: typeof UtilFunc.likeNone, expect: typeof UtilFunc.expect, assertType: typeof UtilFunc.assertType, assertLiteral: typeof UtilFunc.assertLiteral, deepClone: typeof UtilFunc.deepClone, sleep: typeof UtilFunc.sleep, stringifyJToken: typeof UtilFunc.stringifyJToken, getTime: typeof UtilFunc.getTime, mapEntries: typeof UtilFunc.mapEntries, dedent: typeof UtilFunc.dedent, throwError: typeof UtilFunc.throwError, eitherify: typeof UtilFunc.eitherify, taskEitherify: typeof UtilFunc.taskEitherify;
4
4
  export declare const stylizePath: typeof UtilFT.stylizePath, posixizePath: typeof UtilFT.posixizePath, win32izePath: typeof UtilFT.win32izePath, currosizePath: typeof UtilFT.currosizePath;
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.currosizePath = exports.win32izePath = exports.posixizePath = exports.stylizePath = exports.throwError = exports.dedent = exports.mapEntries = exports.getTime = exports.stringifyJToken = exports.sleep = exports.deepClone = exports.assertLiteral = exports.assertType = exports.expect = exports.likeNone = exports.isSuccess = exports.isSafeNumber = exports.isFailed = exports.sucesProc = exports.matchProc = exports.outcome = void 0;
3
+ exports.currosizePath = exports.win32izePath = exports.posixizePath = exports.stylizePath = exports.taskEitherify = exports.eitherify = exports.throwError = exports.dedent = exports.mapEntries = exports.getTime = exports.stringifyJToken = exports.sleep = exports.deepClone = exports.assertLiteral = exports.assertType = exports.expect = exports.likeNone = exports.isSuccess = exports.isSafeNumber = exports.isFailed = exports.sucesProc = exports.matchProc = exports.outcome = void 0;
4
4
  const UtilFileTools_1 = require("./UtilFileTools");
5
5
  const UtilFunctions_1 = require("./UtilFunctions");
6
6
  const UtilSymbol_1 = require("./UtilSymbol");
7
- exports.outcome = UtilFunctions_1.UtilFunc.outcome, exports.matchProc = UtilFunctions_1.UtilFunc.matchProc, exports.sucesProc = UtilFunctions_1.UtilFunc.sucesProc, exports.isFailed = UtilFunctions_1.UtilFunc.isFailed, exports.isSafeNumber = UtilFunctions_1.UtilFunc.isSafeNumber, exports.isSuccess = UtilFunctions_1.UtilFunc.isSuccess, exports.likeNone = UtilFunctions_1.UtilFunc.likeNone, exports.expect = UtilFunctions_1.UtilFunc.expect, exports.assertType = UtilFunctions_1.UtilFunc.assertType, exports.assertLiteral = UtilFunctions_1.UtilFunc.assertLiteral, exports.deepClone = UtilFunctions_1.UtilFunc.deepClone, exports.sleep = UtilFunctions_1.UtilFunc.sleep, exports.stringifyJToken = UtilFunctions_1.UtilFunc.stringifyJToken, exports.getTime = UtilFunctions_1.UtilFunc.getTime, exports.mapEntries = UtilFunctions_1.UtilFunc.mapEntries, exports.dedent = UtilFunctions_1.UtilFunc.dedent, exports.throwError = UtilFunctions_1.UtilFunc.throwError;
7
+ exports.outcome = UtilFunctions_1.UtilFunc.outcome, exports.matchProc = UtilFunctions_1.UtilFunc.matchProc, exports.sucesProc = UtilFunctions_1.UtilFunc.sucesProc, exports.isFailed = UtilFunctions_1.UtilFunc.isFailed, exports.isSafeNumber = UtilFunctions_1.UtilFunc.isSafeNumber, exports.isSuccess = UtilFunctions_1.UtilFunc.isSuccess, exports.likeNone = UtilFunctions_1.UtilFunc.likeNone, exports.expect = UtilFunctions_1.UtilFunc.expect, exports.assertType = UtilFunctions_1.UtilFunc.assertType, exports.assertLiteral = UtilFunctions_1.UtilFunc.assertLiteral, exports.deepClone = UtilFunctions_1.UtilFunc.deepClone, exports.sleep = UtilFunctions_1.UtilFunc.sleep, exports.stringifyJToken = UtilFunctions_1.UtilFunc.stringifyJToken, exports.getTime = UtilFunctions_1.UtilFunc.getTime, exports.mapEntries = UtilFunctions_1.UtilFunc.mapEntries, exports.dedent = UtilFunctions_1.UtilFunc.dedent, exports.throwError = UtilFunctions_1.UtilFunc.throwError, exports.eitherify = UtilFunctions_1.UtilFunc.eitherify, exports.taskEitherify = UtilFunctions_1.UtilFunc.taskEitherify;
8
8
  exports.stylizePath = UtilFileTools_1.UtilFT.stylizePath, exports.posixizePath = UtilFileTools_1.UtilFT.posixizePath, exports.win32izePath = UtilFileTools_1.UtilFT.win32izePath, exports.currosizePath = UtilFileTools_1.UtilFT.currosizePath;
9
9
  if (false) {
10
10
  let aaser = (0, exports.assertLiteral)({ a: 1 });
package/dist/UtilCom.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { JObject, PromiseVerifyFn } from "./UtilInterfaces";
1
+ import { JObject, ReqVerifyFn } from "./UtilInterfaces";
2
2
  /**网络工具 */
3
3
  export declare namespace UtilCom {
4
4
  /**发送一个 https POST请求并接受数据
@@ -27,7 +27,7 @@ export declare namespace UtilCom {
27
27
  * @param verifyFn - 判断有效性函数
28
28
  * @returns 结果 null 为未能成功接收
29
29
  */
30
- function shttpsRepeatPost(json: JObject, options: Object, timeLimit?: number, repeatCount?: number, repeatTime?: number, verifyFn?: PromiseVerifyFn<JObject | null>): Promise<JObject | null>;
30
+ function shttpsRepeatPost(json: JObject, options: Object, timeLimit?: number, repeatCount?: number, repeatTime?: number, verifyFn?: ReqVerifyFn<JObject | null>): Promise<JObject | null>;
31
31
  /**重复一个 http POST请求并接受数据
32
32
  * Object ()
33
33
  * @async
@@ -39,5 +39,5 @@ export declare namespace UtilCom {
39
39
  * @param verifyFn - 判断有效性函数
40
40
  * @returns 结果 null 为未能成功接收
41
41
  */
42
- function shttpRepeatPost(json: JObject, options: Object, timeLimit?: number, repeatCount?: number, repeatTime?: number, verifyFn?: PromiseVerifyFn<JObject | null>): Promise<JObject | null>;
42
+ function shttpRepeatPost(json: JObject, options: Object, timeLimit?: number, repeatCount?: number, repeatTime?: number, verifyFn?: ReqVerifyFn<JObject | null>): Promise<JObject | null>;
43
43
  }
@@ -23,6 +23,13 @@ type FileSearchRegexOpt = Partial<{
23
23
  /**搜索子目录 默认 true */
24
24
  relative: boolean;
25
25
  }>;
26
+ /**json文件加载选项 */
27
+ type LoadJsonFileOpt<T> = Partial<{
28
+ /**默认值 默认{} */
29
+ default: T;
30
+ /**以json5模式加载 略慢 默认false */
31
+ json5: boolean;
32
+ }>;
26
33
  /**文件工具 */
27
34
  export declare namespace UtilFT {
28
35
  /**验证路径 文件或文件夹 是否存在 异步
@@ -73,10 +80,12 @@ export declare namespace UtilFT {
73
80
  function loadJSONFileSync(filePath: string): JToken;
74
81
  /**加载json文件 同步
75
82
  * @param filePath - 文件路径
76
- * @param def - 默认值
83
+ * @param opt - 可选参数
84
+ * @param opt.default - 默认值
85
+ * @param opt.json5 - json5模式
77
86
  * @returns 加载完成的对象或默认值
78
87
  */
79
- function loadJSONFileSync<T extends JToken>(filePath: string, def: T): T;
88
+ function loadJSONFileSync<T extends JToken>(filePath: string, opt: LoadJsonFileOpt<T>): T;
80
89
  /**加载json文件 异步
81
90
  * @async
82
91
  * @param filePath - 文件路径
@@ -86,10 +95,12 @@ export declare namespace UtilFT {
86
95
  /**加载json文件 异步
87
96
  * @async
88
97
  * @param filePath - 文件路径
89
- * @param def - 默认值
98
+ * @param opt - 可选参数
99
+ * @param opt.default - 默认值
100
+ * @param opt.json5 - json5模式
90
101
  * @returns 加载完成的对象或默认值
91
102
  */
92
- function loadJSONFile<T extends JToken>(filePath: string, def: T): Promise<T>;
103
+ function loadJSONFile<T extends JToken>(filePath: string, opt: LoadJsonFileOpt<T>): Promise<T>;
93
104
  /**写入JSON文件
94
105
  * void (string,Object)
95
106
  * @async
@@ -141,7 +141,7 @@ var UtilFT;
141
141
  return createPathSync(filePath, opt);
142
142
  }
143
143
  UtilFT.ensurePathExistsSync = ensurePathExistsSync;
144
- function loadJSONFileSync(filePath, def) {
144
+ function loadJSONFileSync(filePath, opt) {
145
145
  if (pathe_1.default.extname(filePath) !== '.json')
146
146
  filePath += '.json';
147
147
  let str = "";
@@ -150,14 +150,16 @@ var UtilFT;
150
150
  str = fs.readFileSync(filePath, "utf-8");
151
151
  // 如果不存在则返回默认值
152
152
  if (str == "" || str == null) {
153
- if (def !== undefined)
154
- return def;
153
+ if (opt?.default !== undefined)
154
+ return opt.default;
155
155
  return {};
156
156
  }
157
- return JSON5.parse(str);
157
+ if (opt?.json5)
158
+ return JSON5.parse(str);
159
+ return JSON.parse(str);
158
160
  }
159
161
  UtilFT.loadJSONFileSync = loadJSONFileSync;
160
- async function loadJSONFile(filePath, def) {
162
+ async function loadJSONFile(filePath, opt) {
161
163
  if (pathe_1.default.extname(filePath) !== '.json')
162
164
  filePath += '.json';
163
165
  let str = "";
@@ -166,11 +168,13 @@ var UtilFT;
166
168
  str = await fs.promises.readFile(filePath, "utf-8");
167
169
  // 如果不存在则返回默认值
168
170
  if (str == "" || str == null) {
169
- if (def !== undefined)
170
- return def;
171
+ if (opt?.default !== undefined)
172
+ return opt.default;
171
173
  return {};
172
174
  }
173
- return JSON5.parse(str);
175
+ if (opt?.json5)
176
+ return JSON5.parse(str);
177
+ return JSON.parse(str);
174
178
  }
175
179
  UtilFT.loadJSONFile = loadJSONFile;
176
180
  /**写入JSON文件
@@ -1,6 +1,6 @@
1
- import { AnyFunc, ComposedClass, ComposedMixinable, ComposedRefMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, Literal, Matchable, MatchableFlag, Mixinable, Outcome, PromiseVerifyFn, ProperSubsetCheck, RefMixinable, UnionToIntersection } from "./UtilInterfaces";
1
+ import { AnyFunc, ComposedClass, ComposedMixinable, ComposedRefMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, Literal, Matchable, MatchableFlag, Mixinable, Outcome, ReqVerifyFn, ProperSubsetCheck, RefMixinable, UnionToIntersection, Await } from "./UtilInterfaces";
2
2
  import { LogLevel } from "./UtilLogger";
3
- import { FailedLike, None, StatusSymbol, Success, SuccessLike, Timeout } from "./UtilSymbol";
3
+ import { Failed, FailedLike, None, StatusSymbol, Success, SuccessLike, Timeout } from "./UtilSymbol";
4
4
  declare const HashMethodList: readonly ["md5", "sha1", "sha256", "sha512", "sha3", "blake2", "blake3"];
5
5
  type HashMethod = typeof HashMethodList[number];
6
6
  /**执行选项 */
@@ -79,7 +79,7 @@ export declare class UtilFunc {
79
79
  * @param repeatTime - 超时时间/秒 最小为5秒
80
80
  * @returns 结果 null 为全部失败/超时
81
81
  */
82
- static repeatPromise<T>(procFn: () => Promise<T>, verifyFn?: PromiseVerifyFn<T>, repeatCount?: number, repeatTime?: number): Promise<T | null>;
82
+ static repeatPromise<T>(procFn: () => Promise<T>, verifyFn?: ReqVerifyFn<T>, repeatCount?: number, repeatTime?: number): Promise<T | null>;
83
83
  /**创建一个限时的Promise
84
84
  * @param func - 处理函数
85
85
  * @param timeLimit - 毫秒限时
@@ -223,9 +223,36 @@ export declare class UtilFunc {
223
223
  filePath: string;
224
224
  lineNumber: `${number}:${number}`;
225
225
  } | undefined;
226
+ private static publicIp?;
226
227
  /**获取当前公网ipv4
227
- * @returns undefined 时为错误
228
228
  */
229
- static getPublicIpv4(): Promise<string | undefined>;
229
+ static getPublicIpv4(): Promise<string>;
230
+ /**将传入函数包装为显示处理错误的函数
231
+ * @param func - 待转换函数
232
+ * @returns 转换完成的函数
233
+ */
234
+ static eitherify<T extends AnyFunc>(func: T): (...args: Parameters<T>) => Outcome<typeof Success, ReturnType<T>> | Outcome<typeof Failed, Error>;
235
+ /**将传入的异步函数包装为显示处理错误的函数
236
+ * @param func - 待转换函数
237
+ * @returns 转换完成的函数
238
+ */
239
+ static taskEitherify<T extends (...args: any) => Promise<any>>(func: T): (...args: Parameters<T>) => Promise<Outcome<typeof Failed, Error> | Outcome<typeof Success, Await<ReturnType<T>>>>;
240
+ /**动态导入模块的函数。这个函数是为了在TypeScript的模块系统配置为CommonJS时,防止动态import被转译为require而设计的。
241
+ * 使用这个函数,你可以在TypeScript中动态地导入模块,而不需要担心import()被转译为require()。
242
+ * 请注意,这个函数使用了eval(),可能会带来安全风险。
243
+ *
244
+ * @param {string} moduleName - 需要导入的模块的名称。
245
+ * @returns {Promise<any>} 返回一个Promise。当模块被成功导入时,这个Promise会解析为导入的模块。如果导入失败,这个Promise会被拒绝。
246
+ *
247
+ * @example
248
+ * async function main() {
249
+ * const pip = (await dynamicImport('public-ip')).default;
250
+ * console.log(await pip.v4());
251
+ * }
252
+ * main();
253
+ *
254
+ * @since Node.js 13.2,Node.js开始支持动态import。
255
+ */
256
+ static dynamicImport(moduleName: string): Promise<any>;
230
257
  }
231
258
  export {};
@@ -43,6 +43,7 @@ const UtilSymbol_1 = require("./UtilSymbol");
43
43
  const UtilDecorators_1 = require("./UtilDecorators");
44
44
  const path_1 = __importDefault(require("path"));
45
45
  const UtilFileTools_1 = require("./UtilFileTools");
46
+ const util_1 = require("util");
46
47
  const HashMethodList = ["md5", "sha1", "sha256", "sha512", "sha3", "blake2", "blake3"];
47
48
  /**永不完成的Promise单例 */
48
49
  const NeverResolvedPromise = new Promise(() => { });
@@ -614,17 +615,66 @@ class UtilFunc {
614
615
  }
615
616
  return undefined;
616
617
  }
618
+ static publicIp;
617
619
  /**获取当前公网ipv4
618
- * @returns undefined 时为错误
619
620
  */
620
621
  static async getPublicIpv4() {
621
- const { stdout } = await UtilFunc.exec('public-ip -4');
622
- const ip = stdout.trim();
623
- // 单独的 0-255 的正则表达式
624
- const i255regex = /(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/.source;
625
- // 使用 .source 属性来拼接正则表达式
626
- const ipv4Pattern = new RegExp(`^(${i255regex}\\.){3}${i255regex}$`);
627
- return ipv4Pattern.test(ip) ? ip : undefined;
622
+ if (UtilFunc.publicIp === undefined)
623
+ UtilFunc.publicIp = await UtilFunc.dynamicImport('public-ip');
624
+ return UtilFunc.publicIp.publicIpv4();
625
+ }
626
+ /**将传入函数包装为显示处理错误的函数
627
+ * @param func - 待转换函数
628
+ * @returns 转换完成的函数
629
+ */
630
+ static eitherify(func) {
631
+ return (...args) => {
632
+ try {
633
+ const result = func(...args);
634
+ return UtilFunc.outcome(UtilSymbol_1.Success, result);
635
+ }
636
+ catch (error) {
637
+ if (error instanceof Error)
638
+ return UtilFunc.outcome(UtilSymbol_1.Failed, error);
639
+ return UtilFunc.outcome(UtilSymbol_1.Failed, new Error((0, util_1.inspect)(error)));
640
+ }
641
+ };
642
+ }
643
+ /**将传入的异步函数包装为显示处理错误的函数
644
+ * @param func - 待转换函数
645
+ * @returns 转换完成的函数
646
+ */
647
+ static taskEitherify(func) {
648
+ return async (...args) => {
649
+ try {
650
+ const result = await func(...args);
651
+ return UtilFunc.outcome(UtilSymbol_1.Success, result);
652
+ }
653
+ catch (error) {
654
+ if (error instanceof Error)
655
+ return UtilFunc.outcome(UtilSymbol_1.Failed, error);
656
+ return UtilFunc.outcome(UtilSymbol_1.Failed, new Error((0, util_1.inspect)(error)));
657
+ }
658
+ };
659
+ }
660
+ /**动态导入模块的函数。这个函数是为了在TypeScript的模块系统配置为CommonJS时,防止动态import被转译为require而设计的。
661
+ * 使用这个函数,你可以在TypeScript中动态地导入模块,而不需要担心import()被转译为require()。
662
+ * 请注意,这个函数使用了eval(),可能会带来安全风险。
663
+ *
664
+ * @param {string} moduleName - 需要导入的模块的名称。
665
+ * @returns {Promise<any>} 返回一个Promise。当模块被成功导入时,这个Promise会解析为导入的模块。如果导入失败,这个Promise会被拒绝。
666
+ *
667
+ * @example
668
+ * async function main() {
669
+ * const pip = (await dynamicImport('public-ip')).default;
670
+ * console.log(await pip.v4());
671
+ * }
672
+ * main();
673
+ *
674
+ * @since Node.js 13.2,Node.js开始支持动态import。
675
+ */
676
+ static async dynamicImport(moduleName) {
677
+ return await eval(`import('${moduleName}')`);
628
678
  }
629
679
  }
630
680
  exports.UtilFunc = UtilFunc;
@@ -96,11 +96,11 @@ export type ExclusiveJObject<B extends JObject, T extends JToken, K extends stri
96
96
  * 终止 将直接返回 null
97
97
  * 失败 将重试
98
98
  */
99
- export type PromiseStat = Success | Failed | Terminated;
100
- /**promise验证函数 */
101
- export type PromiseVerifyFn<T> = (obj: T) => Promise<PromiseStat> | PromiseStat;
102
- /**获取Promise的结果类型 */
103
- export type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
99
+ export type ReqStat = Success | Failed | Terminated;
100
+ /**请求状态验证函数 */
101
+ export type ReqVerifyFn<T> = (obj: T) => Promise<ReqStat> | ReqStat;
102
+ /**获取Promise的结果类型 如同await那样 */
103
+ export type Await<T> = T extends Promise<infer U> ? U : T;
104
104
  /**类型中任意函数的字符串名称 */
105
105
  export type FuncPropNames<T> = {
106
106
  [K in keyof T]: T[K] extends AnyFunc ? K : never;
@@ -172,6 +172,11 @@ export type Outcome<K extends Keyable, V> = {
172
172
  /**值 */
173
173
  readonly result: V;
174
174
  };
175
+ /**可成功或失败的结果
176
+ * @template S - 成功时的结果
177
+ * @template F - 失败时的结果
178
+ */
179
+ export type Eithercome<S, F> = Outcome<Success, S> | Outcome<Failed, F>;
175
180
  /**可进行匹配的 outcome或symbol */
176
181
  export type Matchable<T extends Keyable> = T | Outcome<T, unknown>;
177
182
  /**可进行匹配的 outcome或symbol 中的状态类型 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zwa73/utils",
3
- "version": "1.0.124",
3
+ "version": "1.0.125",
4
4
  "description": "my utils",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -17,8 +17,6 @@
17
17
  "author": "zwa73",
18
18
  "license": "ISC",
19
19
  "dependencies": {
20
- "esm": "^3.2.25",
21
- "esm-resolve": "^1.0.8",
22
20
  "fluent-ffmpeg": "2.1.2",
23
21
  "glob": "^10.3.10",
24
22
  "html-entities": "^2.3.3",
@@ -26,7 +24,7 @@
26
24
  "https-proxy-agent": "^5.0.1",
27
25
  "json5": "^2.2.3",
28
26
  "pathe": "^1.1.2",
29
- "public-ip-cli": "^3.0.0",
27
+ "public-ip": "^6.0.2",
30
28
  "tiktoken": "^1.0.7",
31
29
  "winston": "^3.10.0",
32
30
  "winston-daily-rotate-file": "^4.7.1"
@@ -21,6 +21,8 @@ export const {
21
21
  mapEntries,
22
22
  dedent,
23
23
  throwError,
24
+ eitherify,
25
+ taskEitherify,
24
26
  } = UtilFunc;
25
27
 
26
28
  export const {
package/src/UtilCom.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { JObject, PromiseVerifyFn } from "@src/UtilInterfaces";
1
+ import { JObject, ReqVerifyFn } from "@src/UtilInterfaces";
2
2
  import * as https from 'https';
3
3
  import * as http from 'http';
4
4
  import { SLogger } from "@src/UtilLogger";
@@ -132,7 +132,7 @@ export function shttpPost(json:JObject,options:Object,timeLimit:number=-1):Promi
132
132
  * @returns 结果 null 为未能成功接收
133
133
  */
134
134
  async function sRepeatPost(posttype:"http"|"https",json:JObject,options:Object,timeLimit:number=-1,
135
- repeatCount:number=3,repeatTime:number=180,verifyFn?:PromiseVerifyFn<JObject|null>):Promise<JObject|null>{
135
+ repeatCount:number=3,repeatTime:number=180,verifyFn?:ReqVerifyFn<JObject|null>):Promise<JObject|null>{
136
136
  const procFn = ()=>sPost(posttype,json,options,timeLimit);
137
137
  return UtilFunc.repeatPromise(procFn,verifyFn,repeatCount,repeatTime);
138
138
  }
@@ -149,7 +149,7 @@ async function sRepeatPost(posttype:"http"|"https",json:JObject,options:Object,t
149
149
  * @returns 结果 null 为未能成功接收
150
150
  */
151
151
  export function shttpsRepeatPost(json:JObject,options:Object,timeLimit:number=-1,
152
- repeatCount:number=3,repeatTime:number=180,verifyFn?:PromiseVerifyFn<JObject|null>):Promise<JObject|null>{
152
+ repeatCount:number=3,repeatTime:number=180,verifyFn?:ReqVerifyFn<JObject|null>):Promise<JObject|null>{
153
153
  return sRepeatPost("https",json,options,timeLimit,repeatCount,repeatTime,verifyFn);
154
154
  }
155
155
 
@@ -165,7 +165,7 @@ export function shttpsRepeatPost(json:JObject,options:Object,timeLimit:number=-1
165
165
  * @returns 结果 null 为未能成功接收
166
166
  */
167
167
  export function shttpRepeatPost(json:JObject,options:Object,timeLimit:number=-1,
168
- repeatCount:number=3,repeatTime:number=180,verifyFn?:PromiseVerifyFn<JObject|null>):Promise<JObject|null>{
168
+ repeatCount:number=3,repeatTime:number=180,verifyFn?:ReqVerifyFn<JObject|null>):Promise<JObject|null>{
169
169
  return sRepeatPost("http",json,options,timeLimit,repeatCount,repeatTime,verifyFn);
170
170
  }
171
171
 
@@ -1,5 +1,5 @@
1
1
  import { UtilFunc } from "./UtilFunctions";
2
- import { UnwrapPromise } from "./UtilInterfaces";
2
+ import { Await } from "./UtilInterfaces";
3
3
  import { SLogger } from "./UtilLogger";
4
4
 
5
5
  type TDTg<T> =
@@ -34,6 +34,14 @@ type FileSearchRegexOpt = Partial<{
34
34
  relative:boolean;
35
35
  }>
36
36
 
37
+ /**json文件加载选项 */
38
+ type LoadJsonFileOpt<T> = Partial<{
39
+ /**默认值 默认{} */
40
+ default:T;
41
+ /**以json5模式加载 略慢 默认false */
42
+ json5:boolean;
43
+ }>
44
+
37
45
  /**文件工具 */
38
46
  export namespace UtilFT{
39
47
 
@@ -148,11 +156,13 @@ export function ensurePathExistsSync(filePath: string, opt?:EnsurePathExistsOpt)
148
156
  export function loadJSONFileSync(filePath: string): JToken
149
157
  /**加载json文件 同步
150
158
  * @param filePath - 文件路径
151
- * @param def - 默认值
159
+ * @param opt - 可选参数
160
+ * @param opt.default - 默认值
161
+ * @param opt.json5 - json5模式
152
162
  * @returns 加载完成的对象或默认值
153
163
  */
154
- export function loadJSONFileSync<T extends JToken>(filePath: string,def: T): T
155
- export function loadJSONFileSync<T extends JToken>(filePath: string,def?: T): T {
164
+ export function loadJSONFileSync<T extends JToken>(filePath: string,opt:LoadJsonFileOpt<T>): T
165
+ export function loadJSONFileSync<T extends JToken>(filePath: string,opt?:LoadJsonFileOpt<T>): T {
156
166
  if (path.extname(filePath) !== '.json') filePath += '.json';
157
167
 
158
168
  let str = "";
@@ -163,11 +173,13 @@ export function loadJSONFileSync<T extends JToken>(filePath: string,def?: T): T
163
173
 
164
174
  // 如果不存在则返回默认值
165
175
  if (str == "" || str == null){
166
- if(def!==undefined)
167
- return def;
176
+ if(opt?.default!==undefined)
177
+ return opt.default;
168
178
  return {} as T;
169
179
  }
170
- return JSON5.parse(str);
180
+ if(opt?.json5)
181
+ return JSON5.parse(str);
182
+ return JSON.parse(str);
171
183
  }
172
184
 
173
185
  /**加载json文件 异步
@@ -179,11 +191,13 @@ export async function loadJSONFile(filePath: string): Promise<JToken>
179
191
  /**加载json文件 异步
180
192
  * @async
181
193
  * @param filePath - 文件路径
182
- * @param def - 默认值
194
+ * @param opt - 可选参数
195
+ * @param opt.default - 默认值
196
+ * @param opt.json5 - json5模式
183
197
  * @returns 加载完成的对象或默认值
184
198
  */
185
- export async function loadJSONFile<T extends JToken>(filePath: string,def: T): Promise<T>
186
- export async function loadJSONFile<T extends JToken>(filePath: string,def?: T): Promise<T> {
199
+ export async function loadJSONFile<T extends JToken>(filePath: string,opt:LoadJsonFileOpt<T>): Promise<T>
200
+ export async function loadJSONFile<T extends JToken>(filePath: string,opt?:LoadJsonFileOpt<T>): Promise<T> {
187
201
  if (path.extname(filePath) !== '.json') filePath += '.json';
188
202
 
189
203
  let str = "";
@@ -194,11 +208,13 @@ export async function loadJSONFile<T extends JToken>(filePath: string,def?: T):
194
208
 
195
209
  // 如果不存在则返回默认值
196
210
  if (str == "" || str == null){
197
- if(def!==undefined)
198
- return def;
211
+ if(opt?.default!==undefined)
212
+ return opt.default;
199
213
  return {} as T;
200
214
  }
201
- return JSON5.parse(str);
215
+ if(opt?.json5)
216
+ return JSON5.parse(str);
217
+ return JSON.parse(str);
202
218
  }
203
219
 
204
220
  /**写入JSON文件
@@ -1,11 +1,13 @@
1
1
  import * as crypto from "crypto";
2
- import { AnyFunc, ComposedClass, ComposedMixinable, ComposedRefMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, Literal, Matchable, MatchableFlag, Mixinable, Outcome, PromiseStat, PromiseVerifyFn, ProperSubset, ProperSubsetCheck, RefMixinable, UnionToIntersection } from "@src/UtilInterfaces";
2
+ import { AnyFunc, ComposedClass, ComposedMixinable, ComposedRefMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, Literal, Matchable, MatchableFlag, Mixinable, Outcome, ReqStat, ReqVerifyFn, ProperSubset, ProperSubsetCheck, RefMixinable, UnionToIntersection, Await } from "@src/UtilInterfaces";
3
3
  import * as cp from "child_process";
4
4
  import { LogLevel, SLogger } from "@src/UtilLogger";
5
5
  import { Completed, Failed, FailedLike, None, StatusSymbol, Success, SuccessLike, Terminated, Timeout } from "./UtilSymbol";
6
6
  import { Catch, DeferAsync, LogTimeAsync } from "./UtilDecorators";
7
7
  import opath from 'path';
8
8
  import { UtilFT } from "./UtilFileTools";
9
+ import {inspect} from 'util';
10
+ import type * as publicIp from 'public-ip';
9
11
 
10
12
  const HashMethodList = ["md5","sha1","sha256","sha512","sha3","blake2","blake3"] as const;
11
13
  type HashMethod = typeof HashMethodList[number];
@@ -25,7 +27,7 @@ type PromiseResult<T> = {
25
27
  /**请求结果 */
26
28
  result:T;
27
29
  /**请求状态 */
28
- stat:PromiseStat;
30
+ stat:ReqStat;
29
31
  /**请求下标/序号 */
30
32
  index:number;
31
33
  };
@@ -181,7 +183,7 @@ static getNeverResolvedPromise<T>():Promise<T>{
181
183
  * @returns 结果 null 为全部失败/超时
182
184
  */
183
185
  @LogTimeAsync("repeatPromise ",true)
184
- static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>,
186
+ static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:ReqVerifyFn<T>,
185
187
  repeatCount:number=3,repeatTime:number=180):Promise<T|null>{
186
188
 
187
189
  /**是否含有超时时间 */
@@ -695,17 +697,68 @@ static getFuncLoc(stack=1) {
695
697
  return undefined;
696
698
  }
697
699
 
700
+
701
+ private static publicIp?:typeof publicIp;
702
+
698
703
  /**获取当前公网ipv4
699
- * @returns undefined 时为错误
700
704
  */
701
705
  static async getPublicIpv4(){
702
- const {stdout} = await UtilFunc.exec('public-ip -4');
703
- const ip = stdout.trim();
704
- // 单独的 0-255 的正则表达式
705
- const i255regex = /(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/.source;
706
- // 使用 .source 属性来拼接正则表达式
707
- const ipv4Pattern = new RegExp(`^(${i255regex}\\.){3}${i255regex}$`);
708
- return ipv4Pattern.test(ip) ? ip : undefined;
706
+ if(UtilFunc.publicIp===undefined)
707
+ UtilFunc.publicIp = await UtilFunc.dynamicImport('public-ip') as typeof publicIp;
708
+ return UtilFunc.publicIp.publicIpv4();
709
+ }
710
+
711
+ /**将传入函数包装为显示处理错误的函数
712
+ * @param func - 待转换函数
713
+ * @returns 转换完成的函数
714
+ */
715
+ static eitherify<T extends AnyFunc>(func:T) {
716
+ return (...args: Parameters<T>) => {
717
+ try {
718
+ const result:ReturnType<T> = func(...args as any);
719
+ return UtilFunc.outcome(Success,result);
720
+ } catch (error) {
721
+ if(error instanceof Error)
722
+ return UtilFunc.outcome(Failed,error);
723
+ return UtilFunc.outcome(Failed,new Error(inspect(error)));
724
+ }
725
+ };
726
+ }
727
+ /**将传入的异步函数包装为显示处理错误的函数
728
+ * @param func - 待转换函数
729
+ * @returns 转换完成的函数
730
+ */
731
+ static taskEitherify<T extends (...args:any)=>Promise<any>>(func:T) {
732
+ return async (...args: Parameters<T>) => {
733
+ try {
734
+ const result:Await<ReturnType<T>> = await func(...args as any);
735
+ return UtilFunc.outcome(Success,result);
736
+ } catch (error) {
737
+ if(error instanceof Error)
738
+ return UtilFunc.outcome(Failed,error);
739
+ return UtilFunc.outcome(Failed,new Error(inspect(error)));
740
+ }
741
+ };
742
+ }
743
+
744
+ /**动态导入模块的函数。这个函数是为了在TypeScript的模块系统配置为CommonJS时,防止动态import被转译为require而设计的。
745
+ * 使用这个函数,你可以在TypeScript中动态地导入模块,而不需要担心import()被转译为require()。
746
+ * 请注意,这个函数使用了eval(),可能会带来安全风险。
747
+ *
748
+ * @param {string} moduleName - 需要导入的模块的名称。
749
+ * @returns {Promise<any>} 返回一个Promise。当模块被成功导入时,这个Promise会解析为导入的模块。如果导入失败,这个Promise会被拒绝。
750
+ *
751
+ * @example
752
+ * async function main() {
753
+ * const pip = (await dynamicImport('public-ip')).default;
754
+ * console.log(await pip.v4());
755
+ * }
756
+ * main();
757
+ *
758
+ * @since Node.js 13.2,Node.js开始支持动态import。
759
+ */
760
+ static async dynamicImport(moduleName:string):Promise<any> {
761
+ return await eval(`import('${moduleName}')`);
709
762
  }
710
763
 
711
764
  }
@@ -136,13 +136,12 @@ export type ExclusiveJObject<B extends JObject,T extends JToken,K extends string
136
136
  * 终止 将直接返回 null
137
137
  * 失败 将重试
138
138
  */
139
- export type PromiseStat = Success|Failed|Terminated;
140
- /**promise验证函数 */
141
- export type PromiseVerifyFn<T> = (obj:T)=>Promise<PromiseStat>|PromiseStat;
142
-
143
- /**获取Promise的结果类型 */
144
- export type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
139
+ export type ReqStat = Success|Failed|Terminated;
140
+ /**请求状态验证函数 */
141
+ export type ReqVerifyFn<T> = (obj:T)=>Promise<ReqStat>|ReqStat;
145
142
 
143
+ /**获取Promise的结果类型 如同await那样 */
144
+ export type Await<T> = T extends Promise<infer U> ? U : T;
146
145
 
147
146
  /**类型中任意函数的字符串名称 */
148
147
  export type FuncPropNames<T> = {
@@ -241,7 +240,7 @@ export type WithPrefix<T,P extends string> = {
241
240
  : K
242
241
  ]: T[K]
243
242
  };
244
- /**返回结果
243
+ /**返回结果
245
244
  * @template K - 类型键值
246
245
  * @template V - 值
247
246
  */
@@ -251,6 +250,12 @@ export type Outcome<K extends Keyable,V> = {
251
250
  /**值 */
252
251
  readonly result:V;
253
252
  }
253
+ /**可成功或失败的结果
254
+ * @template S - 成功时的结果
255
+ * @template F - 失败时的结果
256
+ */
257
+ export type Eithercome<S,F> =
258
+ Outcome<Success,S>|Outcome<Failed,F>;
254
259
 
255
260
  /**可进行匹配的 outcome或symbol */
256
261
  export type Matchable<T extends Keyable> = T|Outcome<T,unknown>;
@@ -0,0 +1,2 @@
1
+ node dist/test/ip
2
+ pause