@zwa73/utils 1.0.80 → 1.0.82
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/compile.bat +2 -0
- package/dist/QuickFunction.d.ts +2 -15
- package/dist/QuickFunction.js +21 -19
- package/dist/UtilCodecs.js +1 -1
- package/dist/UtilCom.js +1 -1
- package/dist/UtilDecorators.d.ts +1 -1
- package/dist/UtilDecorators.js +4 -3
- package/dist/UtilFP.js +1 -1
- package/dist/UtilFileTools.js +1 -1
- package/dist/UtilFunctions.d.ts +65 -18
- package/dist/UtilFunctions.js +141 -29
- package/dist/UtilInterfaces.d.ts +18 -13
- package/dist/UtilSymbol.d.ts +29 -10
- package/dist/UtilSymbol.js +22 -9
- package/jest.config.js +16 -0
- package/package.json +12 -5
- package/release.bat +3 -4
- package/{postinstall.js → scripts/postinstall.js} +2 -2
- package/src/QuickFunction.ts +47 -28
- package/src/UtilDecorators.ts +3 -1
- package/src/UtilFunctions.ts +183 -44
- package/src/UtilInterfaces.ts +44 -11
- package/src/UtilSymbol.ts +35 -11
- package/test.bat +1 -1
- package/tsconfig.compile.json +4 -0
- package/tsconfig.json +3 -2
- package/watch.bat +1 -0
- package/backup/package - 1.json +0 -26
- package/dist/test/composeTest.d.ts +0 -78
- package/dist/test/composeTest.js +0 -95
- package/dist/test/importtest.d.ts +0 -1
- package/dist/test/importtest.js +0 -4
- package/dist/test/repeatTest.d.ts +0 -1
- package/dist/test/repeatTest.js +0 -29
- package/dist/test/test.d.ts +0 -1
- package/dist/test/test.js +0 -139
- package/dist/test/test2.d.ts +0 -1
- package/dist/test/test2.js +0 -35
- package/req_test/cjsRmjs.bat +0 -2
- package/req_test/cjsRmjs.cjs +0 -3
- package/req_test/mjsRcjs.bat +0 -2
- package/req_test/mjsRcjs.mjs +0 -3
- package/req_test/req.cjs +0 -7
- package/req_test/req.mjs +0 -3
- package/src/test/composeTest.ts +0 -134
- package/src/test/importtest.ts +0 -5
- package/src/test/repeatTest.ts +0 -29
- package/src/test/test.ts +0 -167
- package/src/test/test2.ts +0 -39
- package/test/test.bat +0 -2
- package/test/test.js +0 -37
- package/test.js +0 -53
- package/testAndCompile.bat +0 -4
- package/tsCompile.bat +0 -3
- package/tsCompileWatch.bat +0 -2
package/jest.config.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
roots: ['./jest'],
|
|
7
|
+
transform: {
|
|
8
|
+
'^.+\\.tsx?$': 'ts-jest',
|
|
9
|
+
},
|
|
10
|
+
moduleNameMapper: {
|
|
11
|
+
'^@src/(.*)$': '<rootDir>/dist/$1',
|
|
12
|
+
'^@/(.*)$': '<rootDir>/$1',
|
|
13
|
+
'^@$': '<rootDir>/index'
|
|
14
|
+
},
|
|
15
|
+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
|
16
|
+
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zwa73/utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.82",
|
|
4
4
|
"description": "my utils",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "
|
|
8
|
-
"postinstall": "start node postinstall.js",
|
|
9
|
-
"release": "call release.bat"
|
|
7
|
+
"test": "call npm run compile && jest",
|
|
8
|
+
"postinstall": "start node ./scripts/postinstall.js",
|
|
9
|
+
"release": "call release.bat",
|
|
10
|
+
"compile": "call tsc -p tsconfig.compile.json && call tsc-alias -p tsconfig.compile.json",
|
|
11
|
+
"watch": "start tsc-alias -w -p tsconfig.compile.json && start tsc -w -p tsconfig.compile.json"
|
|
10
12
|
},
|
|
11
13
|
"keywords": [
|
|
12
14
|
"zwa73"
|
|
@@ -28,6 +30,11 @@
|
|
|
28
30
|
"winston-daily-rotate-file": "^4.7.1"
|
|
29
31
|
},
|
|
30
32
|
"devDependencies": {
|
|
31
|
-
"@types/
|
|
33
|
+
"@types/jest": "^29.5.12",
|
|
34
|
+
"@types/node": "^18.16.3",
|
|
35
|
+
"jest": "^29.7.0",
|
|
36
|
+
"ts-jest": "^29.1.2",
|
|
37
|
+
"tsc-alias": "^1.8.8",
|
|
38
|
+
"typescript": "^5.3.3"
|
|
32
39
|
}
|
|
33
40
|
}
|
package/release.bat
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const currentVersion = require('
|
|
1
|
+
const currentVersion = require('../package.json').version;
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const { UtilFT } = require("
|
|
3
|
+
const { UtilFT } = require("../index");
|
|
4
4
|
const readline = require('readline');
|
|
5
5
|
|
|
6
6
|
// 将版本号转换为可以比较的数字
|
package/src/QuickFunction.ts
CHANGED
|
@@ -1,37 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export function outcome<K extends Keyable,V> (key:K,value:V):Outcome<K,V>{
|
|
5
|
-
return {status:key,result:value}
|
|
6
|
-
}
|
|
1
|
+
import { UtilFunc } from "./UtilFunctions";
|
|
2
|
+
import { Outcome } from "./UtilInterfaces";
|
|
3
|
+
import { Completed, Failed, FailedLike, None, NoneOut, StatusSymbol, Success, SuccessLike, Terminated, Timeout } from "./UtilSymbol";
|
|
7
4
|
|
|
5
|
+
export const {
|
|
6
|
+
outcome,
|
|
7
|
+
matchProc,
|
|
8
|
+
sucesProc,
|
|
9
|
+
isFailed,
|
|
10
|
+
isSafeNumber,
|
|
11
|
+
isSuccess,
|
|
12
|
+
assertType,
|
|
13
|
+
assertLiteral,
|
|
14
|
+
deepClone,
|
|
15
|
+
sleep,
|
|
16
|
+
stringifyJToken,
|
|
17
|
+
getTime,
|
|
18
|
+
mapEntries,
|
|
19
|
+
composeMixinable
|
|
20
|
+
} = UtilFunc;
|
|
8
21
|
|
|
9
|
-
/**处理联合值
|
|
10
|
-
* @param t - 目标值
|
|
11
|
-
* @param procObj - 所有可能的id组成的处理函数映射
|
|
12
|
-
* @returns 任意处理函数的返回值
|
|
13
|
-
*/
|
|
14
|
-
export function match<
|
|
15
|
-
T extends Keyable | Outcome<Keyable, unknown>,
|
|
16
|
-
P extends UnionToIntersection<(T extends Keyable
|
|
17
|
-
? {[K in T]:(k:K)=>unknown}
|
|
18
|
-
: T extends Outcome<Keyable,unknown>
|
|
19
|
-
? { [K in T['status']] : (k:K,v:ExtractOutcome<T,K>['result'])=>unknown }
|
|
20
|
-
: never)>>
|
|
21
|
-
(t:T, procObj:P):
|
|
22
|
-
P extends Record<any,(...args:any)=>any>
|
|
23
|
-
? {[K in keyof P]: ReturnType<P[K]>}[keyof P]
|
|
24
|
-
: never {
|
|
25
|
-
if (typeof t === 'string' || typeof t === 'number' || typeof t === 'symbol')
|
|
26
|
-
return (procObj as any)[t](t);
|
|
27
|
-
else
|
|
28
|
-
return (procObj as any)[t.status](t.status,t.result);
|
|
29
|
-
}
|
|
30
22
|
if(false){
|
|
23
|
+
let aaser = assertLiteral({a:1})
|
|
24
|
+
|
|
31
25
|
let a:"asd"|"dsa" = null as any;
|
|
32
|
-
const r =
|
|
26
|
+
const r = matchProc(a,{
|
|
33
27
|
"asd":(a)=>"ssa" as const,
|
|
34
28
|
"dsa":(b)=>"ssb" as const,
|
|
35
29
|
})
|
|
30
|
+
let b:Outcome<"a","123">|NoneOut = null as any;
|
|
31
|
+
const r1 = matchProc(b,{
|
|
32
|
+
"a":(a,s)=>"ssa" as const,
|
|
33
|
+
[None]:(b,s)=>"ssb" as const,
|
|
34
|
+
})
|
|
35
|
+
let udt = outcome("ssa","None");
|
|
36
|
+
|
|
37
|
+
type test = Outcome<"a"|"b",any> extends Outcome<"a",12>|Outcome<"b",34>
|
|
38
|
+
? "suc" : "fal"
|
|
39
|
+
let assa = isFailed(null as any as Failed)
|
|
40
|
+
let assb = isFailed(null as any as Failed|Success)
|
|
41
|
+
let assc = isFailed(null as any as Success)
|
|
42
|
+
let asssc = isFailed(null)
|
|
43
|
+
let assa1 = isFailed(null as any as Outcome<Failed,unknown>)
|
|
44
|
+
let assb1 = isFailed(null as any as Outcome<Failed|Success,unknown>)
|
|
45
|
+
let assc1 = isFailed(null as any as Outcome<Success,unknown>)
|
|
46
|
+
|
|
47
|
+
let proct = sucesProc(null as any as Outcome<Failed|Success,"123">|Outcome<Failed,"1234">|Outcome<Success,"1s23">,
|
|
48
|
+
(s)=>"ssa" as const,
|
|
49
|
+
(f)=>"ssad" as const,
|
|
50
|
+
()=>123 as const)
|
|
51
|
+
|
|
52
|
+
let matt = matchProc(null as any as Outcome<symbol,123>,{
|
|
53
|
+
|
|
54
|
+
})
|
|
36
55
|
}
|
|
37
56
|
|
package/src/UtilDecorators.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { UtilFunc } from "./UtilFunctions";
|
|
2
|
+
import { UnwrapPromise } from "./UtilInterfaces";
|
|
2
3
|
import { SLogger } from "./UtilLogger";
|
|
3
4
|
|
|
4
5
|
type TDTg<T> =
|
|
@@ -136,7 +137,7 @@ export function DeferAsync<T extends (...args:any)=>Promise<any>>
|
|
|
136
137
|
};
|
|
137
138
|
}
|
|
138
139
|
/**try-catch包装 */
|
|
139
|
-
export function
|
|
140
|
+
export function Catch<T extends (...args:any)=>any>
|
|
140
141
|
(catchLogic:(error: any, ...args:Parameters<T>)=>ReturnType<T>):TDTg<T> {
|
|
141
142
|
return function(target, propertyKey, descriptor) {
|
|
142
143
|
const originalMethod = descriptor.value!;
|
|
@@ -198,6 +199,7 @@ class Example {
|
|
|
198
199
|
}
|
|
199
200
|
@LogCall()
|
|
200
201
|
@Defer((a,b)=>null)
|
|
202
|
+
@CatchAsync(async (a,b)=>123)
|
|
201
203
|
static async myMethod1(num: number,ss:string) {
|
|
202
204
|
return 312;
|
|
203
205
|
}
|
package/src/UtilFunctions.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import * as crypto from "crypto";
|
|
2
|
-
import { ComposedClass, ComposedMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, Mixinable, Outcome, PromiseStat, PromiseVerifyFn } from "@src/UtilInterfaces";
|
|
2
|
+
import { AnyFunc, ComposedClass, ComposedMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, LiteralCheck, Matchable, MatchableFlag, Mixinable, Outcome, PromiseStat, PromiseVerifyFn, UnionToIntersection } from "@src/UtilInterfaces";
|
|
3
3
|
import * as cp from "child_process";
|
|
4
4
|
import { SLogger } from "@src/UtilLogger";
|
|
5
|
-
import { Completed, Failed, None, Success, Terminated, Timeout } from "./UtilSymbol";
|
|
6
|
-
import {
|
|
7
|
-
import { LogTimeAsync } from "./UtilDecorators";
|
|
5
|
+
import { Completed, Failed, FailedLike, None, StatusSymbol, Success, SuccessLike, Terminated, Timeout } from "./UtilSymbol";
|
|
6
|
+
import { DeferAsync, LogTimeAsync } from "./UtilDecorators";
|
|
8
7
|
|
|
9
8
|
|
|
10
|
-
type
|
|
11
|
-
type
|
|
9
|
+
type SuccessOut<T> = Outcome<Success,T>;
|
|
10
|
+
type TimeoutOut<T> = Outcome<Timeout,Promise<T>>;
|
|
12
11
|
/**永不完成的Promise单例 */
|
|
13
12
|
const NeverResolvedPromise = new Promise(()=>{});
|
|
14
|
-
|
|
15
|
-
type
|
|
16
|
-
|
|
13
|
+
/**完成的请求 */
|
|
14
|
+
type PromiseResult<T> = {
|
|
15
|
+
/**请求结果 */
|
|
17
16
|
result:T;
|
|
18
17
|
/**请求状态 */
|
|
19
18
|
stat:PromiseStat;
|
|
@@ -80,24 +79,6 @@ static calcHash(str:string) {
|
|
|
80
79
|
return crypto.createHash('md5').update(str).digest('hex');
|
|
81
80
|
}
|
|
82
81
|
|
|
83
|
-
/**深克隆 序列化并反序列化
|
|
84
|
-
* @template T - JToken类型的泛型
|
|
85
|
-
* @param obj - 克隆目标
|
|
86
|
-
* @returns 克隆结果
|
|
87
|
-
*/
|
|
88
|
-
static deepClone<T extends JToken>(obj: T): T {
|
|
89
|
-
return JSON.parse(JSON.stringify(obj));
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**是否为安全的数字
|
|
93
|
-
* @param num - 所要检测的数字
|
|
94
|
-
* @returns 是否安全
|
|
95
|
-
*/
|
|
96
|
-
static isSafeNumber(num: number): boolean {
|
|
97
|
-
if (num === undefined || num == null || isNaN(num)) return false;
|
|
98
|
-
if(typeof num === 'number') return true;
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
82
|
|
|
102
83
|
/**等待 timeMs 毫秒
|
|
103
84
|
* @async
|
|
@@ -146,7 +127,7 @@ static getNeverResolvedPromise<T>():Promise<T>{
|
|
|
146
127
|
* @param procFn - 发起函数
|
|
147
128
|
* @param verifyFn - 验证函数
|
|
148
129
|
* @param repeatCount - 重试次数
|
|
149
|
-
* @param repeatTime - 超时时间/秒 最小为
|
|
130
|
+
* @param repeatTime - 超时时间/秒 最小为5秒
|
|
150
131
|
* @returns 结果 null 为全部失败/超时
|
|
151
132
|
*/
|
|
152
133
|
@LogTimeAsync("repeatPromise ",true)
|
|
@@ -154,7 +135,7 @@ static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>
|
|
|
154
135
|
repeatCount:number=3,repeatTime:number=180):Promise<T|null>{
|
|
155
136
|
|
|
156
137
|
/**是否含有超时时间 */
|
|
157
|
-
const hasRepeatTime = (repeatTime>=
|
|
138
|
+
const hasRepeatTime = (repeatTime>=5);
|
|
158
139
|
//转换为毫秒
|
|
159
140
|
if(hasRepeatTime) repeatTime*=1000;
|
|
160
141
|
|
|
@@ -164,8 +145,8 @@ static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>
|
|
|
164
145
|
|
|
165
146
|
//进行中的请求
|
|
166
147
|
const plist:Promise<
|
|
167
|
-
|
|
168
|
-
|
|
148
|
+
SuccessOut<PromiseResult<T>>|
|
|
149
|
+
TimeoutOut<PromiseResult<T>>
|
|
169
150
|
>[] = [];
|
|
170
151
|
|
|
171
152
|
//开始处理
|
|
@@ -176,7 +157,7 @@ static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>
|
|
|
176
157
|
|
|
177
158
|
//如果 plist 中当前下标的任务还未创建 则 创建当前任务
|
|
178
159
|
if(plist.length<i+1){
|
|
179
|
-
plist.push(UtilFunc.timelimitPromise<
|
|
160
|
+
plist.push(UtilFunc.timelimitPromise<PromiseResult<T>>(async ()=>{
|
|
180
161
|
const index = i;
|
|
181
162
|
const result = await procFn();
|
|
182
163
|
const stat = await verifyFn!(result);
|
|
@@ -192,7 +173,7 @@ static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>
|
|
|
192
173
|
//解除timeout替换原参数
|
|
193
174
|
plist[i]=new Promise(async (rslove)=>{
|
|
194
175
|
const res = await currObj.result;
|
|
195
|
-
rslove(outcome(
|
|
176
|
+
rslove(UtilFunc.outcome(Success,res));
|
|
196
177
|
})
|
|
197
178
|
SLogger.warn(`第 ${i+1} 次 repeatPromise 超时 ${repeatTime} ms 开始重试`);
|
|
198
179
|
i++;
|
|
@@ -201,7 +182,7 @@ static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>
|
|
|
201
182
|
|
|
202
183
|
//路由请求状态
|
|
203
184
|
const postresult = currObj.result;
|
|
204
|
-
const result =
|
|
185
|
+
const result = UtilFunc.matchProc(postresult.stat,{
|
|
205
186
|
[Success](){
|
|
206
187
|
SLogger.info(`第 ${postresult.index+1} 次 repeatPromise 成功`);
|
|
207
188
|
//非当前
|
|
@@ -245,29 +226,29 @@ static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>
|
|
|
245
226
|
* @returns 超时则返回 处理函数委托 完成则返回结果
|
|
246
227
|
*/
|
|
247
228
|
static timelimitPromise<T>
|
|
248
|
-
(func:()=>Promise<T>|T,timeLimit?:number):Promise<
|
|
249
|
-
return new Promise<
|
|
229
|
+
(func:()=>Promise<T>|T,timeLimit?:number):Promise<SuccessOut<T>|TimeoutOut<T>>{
|
|
230
|
+
return new Promise<SuccessOut<T>|TimeoutOut<T>>((reslove)=>{
|
|
250
231
|
let clearTimer:(()=>void)| null = null;
|
|
251
232
|
const procer = (async ()=>await func())();
|
|
252
233
|
|
|
253
|
-
const procerP = new Promise<
|
|
234
|
+
const procerP = new Promise<SuccessOut<T>>(async (resolve)=>{
|
|
254
235
|
const res = await procer;
|
|
255
|
-
resolve(outcome(
|
|
236
|
+
resolve(UtilFunc.outcome(Success,res));
|
|
256
237
|
if(clearTimer) clearTimer();
|
|
257
238
|
});
|
|
258
239
|
|
|
259
240
|
const timerP = timeLimit
|
|
260
|
-
? new Promise<
|
|
241
|
+
? new Promise<TimeoutOut<T>>((resolve)=>{
|
|
261
242
|
const timer = setTimeout(()=>
|
|
262
|
-
resolve(outcome(Timeout,procer))
|
|
243
|
+
resolve(UtilFunc.outcome(Timeout,procer))
|
|
263
244
|
,timeLimit);//无限制则无限时间
|
|
264
245
|
|
|
265
246
|
clearTimer = ()=>{
|
|
266
|
-
resolve(outcome(Timeout,procer))
|
|
247
|
+
resolve(UtilFunc.outcome(Timeout,procer))
|
|
267
248
|
clearInterval(timer)
|
|
268
249
|
}
|
|
269
|
-
})
|
|
270
|
-
: UtilFunc.getNeverResolvedPromise<
|
|
250
|
+
})//未定义时间限制则无限
|
|
251
|
+
: UtilFunc.getNeverResolvedPromise<TimeoutOut<T>>();
|
|
271
252
|
|
|
272
253
|
const result = Promise.race([procerP,timerP]);
|
|
273
254
|
reslove(result);
|
|
@@ -346,7 +327,7 @@ static composeMixinable
|
|
|
346
327
|
* @param mapper - 映射函数,接受一个值和一个键,返回一个新的值
|
|
347
328
|
* @returns - 一个新的对象,它的属性是原对象的属性经过映射函数处理后的结果
|
|
348
329
|
*/
|
|
349
|
-
static mapEntries<T extends
|
|
330
|
+
static mapEntries<T extends object>
|
|
350
331
|
(obj: T, mapper: (key: keyof T, value: T[keyof T]) => T[keyof T]): T {
|
|
351
332
|
return Object.entries(obj).reduce((result, [key, value]) => {
|
|
352
333
|
result[key as keyof T] = mapper(key as keyof T, value);
|
|
@@ -365,4 +346,162 @@ static stringifyJToken(token:JToken|IJData,space:string|number|null|undefined="\
|
|
|
365
346
|
return JSON.stringify(token,null,space);
|
|
366
347
|
}
|
|
367
348
|
|
|
349
|
+
/**代办表 用于队列处理等待 */
|
|
350
|
+
static pendingMap:Record<Keyable,AnyFunc[]> = {};
|
|
351
|
+
|
|
352
|
+
/**队列处理
|
|
353
|
+
* 等待标签为 flag 的队列
|
|
354
|
+
* 直到排在之前的任务全部完成再处理当前Promise
|
|
355
|
+
* @param flag - 队列标签
|
|
356
|
+
* @param task - 任务逻辑
|
|
357
|
+
* @returns 处理结果
|
|
358
|
+
*/
|
|
359
|
+
static async queueProc<T>(flag:Keyable,task:(()=>Promise<T>)|Promise<T>):Promise<T> {
|
|
360
|
+
this.pendingMap[flag] = this.pendingMap[flag]??[];
|
|
361
|
+
const pending = this.pendingMap[flag];
|
|
362
|
+
|
|
363
|
+
//尝试解除下个任务的等待
|
|
364
|
+
const tryRes = function(){
|
|
365
|
+
const thispd = pending;
|
|
366
|
+
const resolve = thispd.shift();
|
|
367
|
+
if(resolve) resolve();
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
//空时直接运行 非空时等待
|
|
371
|
+
if (pending.length <= 0)
|
|
372
|
+
pending.push(()=>tryRes());
|
|
373
|
+
else await new Promise((resolve) => pending.push(resolve));
|
|
374
|
+
|
|
375
|
+
try {
|
|
376
|
+
const result = typeof task === 'function'
|
|
377
|
+
? await task()
|
|
378
|
+
: await task;
|
|
379
|
+
return result;
|
|
380
|
+
} catch(e){
|
|
381
|
+
SLogger.fatal(`queuePromise 出现错误`,e);
|
|
382
|
+
throw e;
|
|
383
|
+
}finally {
|
|
384
|
+
tryRes();
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
/**创建一个Outcome */
|
|
391
|
+
static outcome<K extends Keyable,V> (key:K,value:V):Outcome<K,V>{
|
|
392
|
+
return {
|
|
393
|
+
status:key,
|
|
394
|
+
result:value
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
/**处理联合值
|
|
400
|
+
* @param t - 目标值
|
|
401
|
+
* @param procObj - 所有可能的id组成的处理函数映射 (status, result)=>any
|
|
402
|
+
* @returns 任意处理函数的返回值
|
|
403
|
+
*/
|
|
404
|
+
static matchProc<
|
|
405
|
+
T extends Matchable<Keyable>,
|
|
406
|
+
P extends UnionToIntersection<
|
|
407
|
+
{ [K in MatchableFlag<T>] :
|
|
408
|
+
(k:K,v:ExtractOutcome<T,MatchableFlag<K>>['result'])=>unknown }>>
|
|
409
|
+
(t:T, procObj:P):
|
|
410
|
+
P extends Record<any,AnyFunc>
|
|
411
|
+
? {[K in keyof P]: ReturnType<P[K]>}[keyof P]
|
|
412
|
+
: never {
|
|
413
|
+
if (typeof t === 'string' || typeof t === 'number' || typeof t === 'symbol'){
|
|
414
|
+
if ((procObj as any)[t])
|
|
415
|
+
return (procObj as any)[t](t);
|
|
416
|
+
SLogger.fatal(`matchProc 传入了一个预料之外的值: `,t);
|
|
417
|
+
throw None;
|
|
418
|
+
}
|
|
419
|
+
else{
|
|
420
|
+
if ((procObj as any)[t.status])
|
|
421
|
+
return (procObj as any)[t.status](t.status,(t as any).result);
|
|
422
|
+
SLogger.fatal(`matchProc 传入了一个预料之外的值: `,t);
|
|
423
|
+
throw None;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**根据典型的成功或失败状态运行函数
|
|
428
|
+
* @param t - 目标值
|
|
429
|
+
* @param sucessFunc - 成功则运行的函数 (result)=>any
|
|
430
|
+
* @param failedFunc - 失败则运行的函数 (result)=>any
|
|
431
|
+
* @param noneFunc - 无结果或不匹配时运行的函数 ()=>any
|
|
432
|
+
* @returns 非成功或失败时返回 None
|
|
433
|
+
*/
|
|
434
|
+
static sucesProc<T extends Matchable<StatusSymbol>,
|
|
435
|
+
S extends (arg:ExtractOutcome<T,SuccessLike>['result'])=>unknown,
|
|
436
|
+
F extends (arg:ExtractOutcome<T,FailedLike>['result'])=>unknown =
|
|
437
|
+
(arg:ExtractOutcome<T,FailedLike>['result'])=>None,
|
|
438
|
+
N extends ()=>unknown = ()=>None>
|
|
439
|
+
(t:T,sucessFunc:S,failedFunc?:F,noneFunc?:N):
|
|
440
|
+
ReturnType<S>|ReturnType<F>|ReturnType<N>{
|
|
441
|
+
failedFunc = failedFunc ?? (()=>None) as any as F;
|
|
442
|
+
noneFunc = noneFunc ?? (()=>None) as N;
|
|
443
|
+
const val = typeof t === 'symbol' ? undefined : t.result;
|
|
444
|
+
if(UtilFunc.isSuccess(t)) return sucessFunc(val) as any;
|
|
445
|
+
if(UtilFunc.isFailed(t)) return failedFunc(val) as any;
|
|
446
|
+
if(t!==None) SLogger.warn(`sucesProc 传入了一个不匹配的值, 将作为None运行: `,t);
|
|
447
|
+
return noneFunc() as any;
|
|
448
|
+
}
|
|
449
|
+
/**是失败的 */
|
|
450
|
+
static isFailed<T>
|
|
451
|
+
(tg:T):T extends Matchable<FailedLike>
|
|
452
|
+
? true : MatchableFlag<T> extends Exclude<MatchableFlag<T>,FailedLike>
|
|
453
|
+
? false : boolean{
|
|
454
|
+
const test = (t:any)=>t === Failed || t === Terminated || t === Timeout;
|
|
455
|
+
if(tg!=null && typeof tg === 'object' && 'status' in tg)
|
|
456
|
+
return test(tg.status) as any
|
|
457
|
+
return test(tg) as any
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**是成功的 */
|
|
461
|
+
static isSuccess<T>
|
|
462
|
+
(tg:T):T extends Matchable<SuccessLike>
|
|
463
|
+
? true: MatchableFlag<T> extends Exclude<MatchableFlag<T>,SuccessLike>
|
|
464
|
+
? false : boolean{
|
|
465
|
+
const test = (t:any)=>t === Success || t === Completed;
|
|
466
|
+
if(tg!=null && typeof tg === 'object' && 'status' in tg)
|
|
467
|
+
return test(tg.status) as any
|
|
468
|
+
return test(tg) as any
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**验证一个变量的类型是否为 T
|
|
472
|
+
* @template T - 验证类型
|
|
473
|
+
* @param t - 验证目标
|
|
474
|
+
*/
|
|
475
|
+
static assertType<T>(t:T):T{return t;}
|
|
476
|
+
/**验证一个变量的类型是否为字面量
|
|
477
|
+
* 仅限浅层
|
|
478
|
+
* @template T - 验证类型
|
|
479
|
+
* @param t - 验证目标
|
|
480
|
+
*/
|
|
481
|
+
static assertLiteral<T>(t:LiteralCheck<T>):T{return t as T;}
|
|
482
|
+
|
|
483
|
+
/**深克隆 序列化并反序列化
|
|
484
|
+
* @template T - JToken类型的泛型
|
|
485
|
+
* @param obj - 克隆目标
|
|
486
|
+
* @returns 克隆结果
|
|
487
|
+
*/
|
|
488
|
+
static deepClone<T extends JToken>(obj: T): T {
|
|
489
|
+
return JSON.parse(JSON.stringify(obj));
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**是否为安全的数字
|
|
493
|
+
* 非NaN 非null/undefined
|
|
494
|
+
* 且是数字
|
|
495
|
+
* @param num - 所要检测的数字
|
|
496
|
+
* @returns 是否安全
|
|
497
|
+
*/
|
|
498
|
+
static isSafeNumber(num: unknown): boolean {
|
|
499
|
+
if (num == null) return false;
|
|
500
|
+
if(typeof num === 'number') {
|
|
501
|
+
if(isNaN(num)) return false;
|
|
502
|
+
return true;
|
|
503
|
+
}
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
|
|
368
507
|
}
|
package/src/UtilInterfaces.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Failed, Success, Terminated } from "./UtilSymbol";
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
/**可以序列化为JSON文件的对象 */
|
|
@@ -17,10 +17,25 @@ export interface IJData{
|
|
|
17
17
|
*/
|
|
18
18
|
toJSON():JToken;
|
|
19
19
|
}
|
|
20
|
+
/**任何可能有ReturnType的函数 */
|
|
21
|
+
export type AnyFunc = (...args:any)=>any;
|
|
20
22
|
|
|
21
23
|
/**任意可作为键值的类型 */
|
|
22
24
|
export type Keyable = string | number | symbol;
|
|
23
25
|
|
|
26
|
+
/**真子集 */
|
|
27
|
+
export type ProperSubset<B, T = B> = T extends B ? B extends T ? never : T : never;
|
|
28
|
+
|
|
29
|
+
/**字面量检测 */
|
|
30
|
+
export type LiteralCheck<L> =
|
|
31
|
+
ProperSubset<string, L> |
|
|
32
|
+
ProperSubset<number, L> |
|
|
33
|
+
ProperSubset<boolean, L>|
|
|
34
|
+
ProperSubset<symbol, L> |
|
|
35
|
+
ProperSubset<any[], L> |
|
|
36
|
+
ProperSubset<Record<any,any>, L> |
|
|
37
|
+
null | undefined;
|
|
38
|
+
|
|
24
39
|
/**转为可写的 */
|
|
25
40
|
export type Writeable<T> = {
|
|
26
41
|
-readonly [P in keyof T]: T[P]
|
|
@@ -84,9 +99,13 @@ export type PromiseStat = Success|Failed|Terminated;
|
|
|
84
99
|
/**promise验证函数 */
|
|
85
100
|
export type PromiseVerifyFn<T> = (obj:T)=>Promise<PromiseStat>|PromiseStat;
|
|
86
101
|
|
|
102
|
+
/**获取Promise的结果类型 */
|
|
103
|
+
export type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
|
|
104
|
+
|
|
105
|
+
|
|
87
106
|
/**类型中任意函数的字符串名称 */
|
|
88
107
|
export type FuncPropNames<T> = {
|
|
89
|
-
[K in keyof T]: T[K] extends
|
|
108
|
+
[K in keyof T]: T[K] extends AnyFunc ? K : never;
|
|
90
109
|
}[keyof T];
|
|
91
110
|
|
|
92
111
|
/**部分组合的类
|
|
@@ -124,20 +143,23 @@ export type ComposedMixinable<B, Ms extends unknown[]> =
|
|
|
124
143
|
* @template N - 如果为假的返回值
|
|
125
144
|
*/
|
|
126
145
|
export type ExtendThen<B,T,Y,N = never> = B extends T ? Y : N;
|
|
127
|
-
/** 一个联合类型 B 中如果包含 T
|
|
146
|
+
/** 一个联合类型 B 中如果包含 联合类型 T 中的任意项
|
|
147
|
+
* 无效
|
|
128
148
|
* @template B - 基础类型
|
|
129
149
|
* @template T - 判断的目标类型
|
|
130
150
|
* @template Y - 如果为真的返回值
|
|
131
151
|
* @template N - 如果为假的返回值
|
|
132
152
|
*/
|
|
133
|
-
|
|
153
|
+
type UnionInclude<B,T,Y,N = never> =
|
|
134
154
|
B extends Exclude<B,T>
|
|
135
|
-
?
|
|
136
|
-
:
|
|
155
|
+
? N
|
|
156
|
+
: Y
|
|
137
157
|
/**排除可选字段 */
|
|
138
158
|
export type RequiredOnly<T> = {
|
|
139
159
|
[K in keyof T as
|
|
140
|
-
|
|
160
|
+
T[K] extends Exclude<T[K],undefined>
|
|
161
|
+
? K
|
|
162
|
+
: never
|
|
141
163
|
]: T[K]
|
|
142
164
|
};
|
|
143
165
|
/**添加前缀 */
|
|
@@ -154,12 +176,23 @@ export type WithPrefix<T,P extends string> = {
|
|
|
154
176
|
*/
|
|
155
177
|
export type Outcome<K extends Keyable,V> = {
|
|
156
178
|
/**状态类型 */
|
|
157
|
-
status:K;
|
|
179
|
+
readonly status:K;
|
|
158
180
|
/**值 */
|
|
159
|
-
result:V;
|
|
181
|
+
readonly result:V;
|
|
160
182
|
}
|
|
161
183
|
|
|
162
|
-
|
|
184
|
+
/**可进行匹配的 outcome或symbol */
|
|
185
|
+
export type Matchable<T extends Keyable> = T|Outcome<T,unknown>;
|
|
186
|
+
/**可进行匹配的 outcome或symbol 中的状态类型 */
|
|
187
|
+
export type MatchableFlag<T> =
|
|
188
|
+
T extends infer O|Outcome<infer O,unknown>
|
|
189
|
+
? O : never;
|
|
190
|
+
|
|
191
|
+
/**从联合 Outcome 中 根据 id 提取对应 Outcome */
|
|
163
192
|
export type ExtractOutcome<T,K extends Keyable> =
|
|
164
|
-
T extends Outcome<
|
|
193
|
+
T extends Outcome<infer O,unknown>
|
|
194
|
+
? O extends Exclude<O,K>
|
|
195
|
+
? never
|
|
196
|
+
: T
|
|
197
|
+
: never;
|
|
165
198
|
|
package/src/UtilSymbol.ts
CHANGED
|
@@ -1,18 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/**成功 */
|
|
1
|
+
import { Outcome } from "./UtilInterfaces";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
/**成功 经过验证的结果 */
|
|
5
5
|
export const Success = Symbol("Success");
|
|
6
6
|
export type Success = typeof Success;
|
|
7
|
-
/**失败 */
|
|
7
|
+
/**失败 可重试的 */
|
|
8
8
|
export const Failed = Symbol("Failed");
|
|
9
9
|
export type Failed = typeof Failed;
|
|
10
|
-
|
|
11
|
-
export const Terminated = Symbol("Terminated");
|
|
12
|
-
export type Terminated = typeof Terminated;
|
|
13
|
-
/**不存在 */
|
|
10
|
+
/**不存在 无 */
|
|
14
11
|
export const None = Symbol("None");
|
|
15
12
|
export type None = typeof None;
|
|
16
|
-
|
|
13
|
+
/**完成 未经验证/未超时的结果
|
|
14
|
+
* Success扩展
|
|
15
|
+
* 仅在Success同时出现时使用
|
|
16
|
+
*/
|
|
17
|
+
export const Completed = Symbol("Completed");
|
|
18
|
+
export type Completed = typeof Completed;
|
|
19
|
+
/**终止 熔断运行
|
|
20
|
+
* Failed扩展
|
|
21
|
+
* 仅在Failed同时出现时使用
|
|
22
|
+
*/
|
|
23
|
+
export const Terminated = Symbol("Terminated");
|
|
24
|
+
export type Terminated = typeof Terminated;
|
|
25
|
+
/**超时 超时类型的失败
|
|
26
|
+
* Failed扩展
|
|
27
|
+
* 仅在超时时使用
|
|
28
|
+
*/
|
|
17
29
|
export const Timeout = Symbol("Timeout");
|
|
18
|
-
export type Timeout = typeof Timeout;
|
|
30
|
+
export type Timeout = typeof Timeout;
|
|
31
|
+
/**失败及其拓展 */
|
|
32
|
+
export type FailedLike = Failed|Timeout|Terminated;
|
|
33
|
+
/**成功及其拓展 */
|
|
34
|
+
export type SuccessLike = Success|Completed;
|
|
35
|
+
/**任意状态标识符 */
|
|
36
|
+
export type StatusSymbol = FailedLike|SuccessLike|None;
|
|
37
|
+
/**结果为 None 的 Outcome */
|
|
38
|
+
export type NoneOut = Outcome<None,None>;
|
|
39
|
+
export const NoneOut = {
|
|
40
|
+
status:None,
|
|
41
|
+
result:None,
|
|
42
|
+
} as const as NoneOut;
|
package/test.bat
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
call npm run test
|
|
2
2
|
pause
|
package/tsconfig.json
CHANGED
|
@@ -11,9 +11,10 @@
|
|
|
11
11
|
"experimentalDecorators": true,
|
|
12
12
|
"paths": {
|
|
13
13
|
"@src/*": ["./src/*"],
|
|
14
|
-
"
|
|
14
|
+
"@/*" : ["./*"],
|
|
15
|
+
"@" : ["./src/index"]
|
|
15
16
|
}
|
|
16
17
|
},
|
|
17
|
-
"include": ["./src/**/*.ts", "./src/**/*.js"],
|
|
18
|
+
"include": ["./src/**/*.ts", "./src/**/*.js","./jest/**/*.ts"],
|
|
18
19
|
"exclude": ["./node_modules/**/*"]
|
|
19
20
|
}
|
package/watch.bat
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
npm run watch
|