@zwa73/utils 1.0.46 → 1.0.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/UtilClass.d.ts +36 -0
- package/dist/UtilClass.js +53 -1
- package/dist/UtilCom.js +6 -6
- package/dist/UtilDecorators.d.ts +8 -12
- package/dist/UtilDecorators.js +75 -13
- package/dist/UtilFileTools.d.ts +12 -2
- package/dist/UtilFileTools.js +23 -9
- package/dist/UtilFunctions.d.ts +74 -14
- package/dist/UtilFunctions.js +156 -37
- package/dist/UtilInterfaces.d.ts +22 -9
- package/dist/test/test.d.ts +1 -0
- package/dist/test/test.js +187 -0
- package/dist/test/test2.d.ts +1 -0
- package/dist/test/test2.js +35 -0
- package/package.json +4 -2
- package/postinstall.js +39 -0
- package/publish.bat +1 -1
- package/src/UtilClass.ts +68 -0
- package/src/UtilCom.ts +7 -7
- package/src/UtilDecorators.ts +66 -12
- package/src/UtilFileTools.ts +21 -9
- package/src/UtilFunctions.ts +212 -39
- package/src/UtilInterfaces.ts +56 -11
- package/src/test/test.ts +223 -0
- package/src/test/test2.ts +40 -0
- package/tsconfig.json +2 -0
package/src/UtilCom.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { JObject,
|
|
1
|
+
import { JObject, PromiseVerifyFn, stringifyJToken } from "./UtilInterfaces";
|
|
2
2
|
import * as https from 'https';
|
|
3
3
|
import * as http from 'http';
|
|
4
4
|
import { SLogger } from "./UtilLogger";
|
|
@@ -22,7 +22,7 @@ function sPost(posttype:"http"|"https",json:JObject,options:Object,timeLimit:num
|
|
|
22
22
|
timeLimit*=1000
|
|
23
23
|
|
|
24
24
|
const jsonStr = stringifyJToken(json);
|
|
25
|
-
const funcName =
|
|
25
|
+
const funcName = `s${posttype}Psot`;
|
|
26
26
|
|
|
27
27
|
return new Promise((resolve, rejecte)=>{
|
|
28
28
|
const resFunc = (res:http.IncomingMessage)=>{
|
|
@@ -31,7 +31,7 @@ function sPost(posttype:"http"|"https",json:JObject,options:Object,timeLimit:num
|
|
|
31
31
|
if(hasTimeLimit){
|
|
32
32
|
res.setTimeout(timeLimit, ()=>{
|
|
33
33
|
//res.abort();
|
|
34
|
-
SLogger.warn(funcName
|
|
34
|
+
SLogger.warn(`${funcName} 接收反馈超时: ${timeLimit} ms`);
|
|
35
35
|
resolve(null);
|
|
36
36
|
return;
|
|
37
37
|
});
|
|
@@ -42,7 +42,7 @@ function sPost(posttype:"http"|"https",json:JObject,options:Object,timeLimit:num
|
|
|
42
42
|
res.on('data',(chunk)=>resdata+=chunk);
|
|
43
43
|
|
|
44
44
|
res.on('error',(e)=>{
|
|
45
|
-
SLogger.warn(funcName
|
|
45
|
+
SLogger.warn(`${funcName} 接收反馈错误:${e}`);
|
|
46
46
|
resolve(null);
|
|
47
47
|
return;
|
|
48
48
|
});
|
|
@@ -60,7 +60,7 @@ function sPost(posttype:"http"|"https",json:JObject,options:Object,timeLimit:num
|
|
|
60
60
|
return;
|
|
61
61
|
}
|
|
62
62
|
catch(e){
|
|
63
|
-
SLogger.warn(funcName
|
|
63
|
+
SLogger.warn(`${funcName} 接收反馈错误:${e}\n原始字符串:${resdata}`);
|
|
64
64
|
resolve(null);
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
@@ -81,13 +81,13 @@ function sPost(posttype:"http"|"https",json:JObject,options:Object,timeLimit:num
|
|
|
81
81
|
//请求超时
|
|
82
82
|
if(hasTimeLimit){
|
|
83
83
|
req.setTimeout(timeLimit, ()=>{
|
|
84
|
-
SLogger.warn(funcName
|
|
84
|
+
SLogger.warn(`${funcName} 发送请求超时: ${timeLimit} ms`);
|
|
85
85
|
req.destroy();
|
|
86
86
|
});
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
req.on('error', (e)=>{
|
|
90
|
-
SLogger.warn(funcName
|
|
90
|
+
SLogger.warn(`${funcName} 发送请求错误:${e}`);
|
|
91
91
|
resolve(null);
|
|
92
92
|
});
|
|
93
93
|
|
package/src/UtilDecorators.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { SLogger } from "./UtilLogger";
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
/**用于打印方法的调用
|
|
5
|
-
* @returns {void}
|
|
6
|
-
*/
|
|
4
|
+
/**用于打印方法的调用 */
|
|
7
5
|
export function DLogger(){
|
|
8
6
|
return function (target:any, propertyKey:string, descriptor:PropertyDescriptor){
|
|
9
7
|
const originalMethod = descriptor.value;
|
|
@@ -15,9 +13,7 @@ export function DLogger(){
|
|
|
15
13
|
}
|
|
16
14
|
}
|
|
17
15
|
|
|
18
|
-
/**用于打印异步方法的调用
|
|
19
|
-
* @returns {void}
|
|
20
|
-
*/
|
|
16
|
+
/**用于打印异步方法的调用 */
|
|
21
17
|
export function DLoggerAsync(){
|
|
22
18
|
return function (target:any, propertyKey:string, descriptor:PropertyDescriptor){
|
|
23
19
|
const originalMethod = descriptor.value;
|
|
@@ -28,10 +24,42 @@ export function DLoggerAsync(){
|
|
|
28
24
|
}
|
|
29
25
|
}
|
|
30
26
|
}
|
|
27
|
+
/**try-finally包装 */
|
|
28
|
+
export function Defer(deferLogic: () => void) {
|
|
29
|
+
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
|
30
|
+
const originalMethod = descriptor.value;
|
|
31
|
+
descriptor.value = function (...args: any[]) {
|
|
32
|
+
try {
|
|
33
|
+
const result = originalMethod.apply(this, args);
|
|
34
|
+
deferLogic();
|
|
35
|
+
return result;
|
|
36
|
+
} catch(e) {
|
|
37
|
+
deferLogic();
|
|
38
|
+
throw e;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
return descriptor;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**异步的try-finally包装 */
|
|
45
|
+
export function DeferAsync(deferLogic: () => void) {
|
|
46
|
+
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
|
47
|
+
const originalMethod = descriptor.value;
|
|
48
|
+
descriptor.value = async function (...args: any[]) {
|
|
49
|
+
try {
|
|
50
|
+
const result = await originalMethod.apply(this, args);
|
|
51
|
+
deferLogic();
|
|
52
|
+
return result;
|
|
53
|
+
} catch(e) {
|
|
54
|
+
deferLogic();
|
|
55
|
+
throw e;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
return descriptor;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
31
61
|
|
|
32
|
-
/**用于捕获方法中的错误
|
|
33
|
-
* @returns {void}
|
|
34
|
-
*/
|
|
62
|
+
/**用于捕获方法中的错误 */
|
|
35
63
|
export function DCatchErrors() {
|
|
36
64
|
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
|
37
65
|
const originalMethod = descriptor.value;
|
|
@@ -45,9 +73,7 @@ export function DCatchErrors() {
|
|
|
45
73
|
};
|
|
46
74
|
}
|
|
47
75
|
|
|
48
|
-
/**用于捕获异步方法中的错误
|
|
49
|
-
* @returns {void}
|
|
50
|
-
*/
|
|
76
|
+
/**用于捕获异步方法中的错误 */
|
|
51
77
|
export function DCatchErrorsAsync() {
|
|
52
78
|
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
|
53
79
|
const originalMethod = descriptor.value;
|
|
@@ -60,3 +86,31 @@ export function DCatchErrorsAsync() {
|
|
|
60
86
|
};
|
|
61
87
|
};
|
|
62
88
|
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
function AddNumberDecorator(n: number) {
|
|
92
|
+
type NumberToNumberFunc = (num: number) => number;
|
|
93
|
+
return function(
|
|
94
|
+
this:any,
|
|
95
|
+
target: Object,
|
|
96
|
+
propertyKey: string,
|
|
97
|
+
descriptor: TypedPropertyDescriptor<NumberToNumberFunc>
|
|
98
|
+
) {
|
|
99
|
+
const originalMethod = descriptor.value!;
|
|
100
|
+
descriptor.value = function (num: number) {
|
|
101
|
+
const result = originalMethod.apply(this, [num]);
|
|
102
|
+
return result + n;
|
|
103
|
+
};
|
|
104
|
+
return descriptor;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
class Example {
|
|
109
|
+
@AddNumberDecorator(10)
|
|
110
|
+
myMethod(num: number): number {
|
|
111
|
+
return num;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
//let a = new Example();
|
|
116
|
+
//a.myMethod(10);//?
|
package/src/UtilFileTools.ts
CHANGED
|
@@ -3,6 +3,7 @@ import * as path from "path";
|
|
|
3
3
|
import { JObject, JToken, stringifyJToken } from "./UtilInterfaces";
|
|
4
4
|
import { SLogger } from "./UtilLogger";
|
|
5
5
|
import * as JSON5 from 'json5';
|
|
6
|
+
import { globSync } from "glob";
|
|
6
7
|
|
|
7
8
|
/**文件工具 */
|
|
8
9
|
export namespace UtilFT{
|
|
@@ -201,25 +202,36 @@ export async function writeJSONFile(
|
|
|
201
202
|
/**搜索路径符合正则表达式的文件
|
|
202
203
|
* @param folder - 文件夹路径
|
|
203
204
|
* @param traitRegex - 正则表达式
|
|
204
|
-
* @returns
|
|
205
|
+
* @returns 文件名路径数组
|
|
205
206
|
*/
|
|
206
|
-
export function
|
|
207
|
-
let
|
|
207
|
+
export function fileSearchRegex(folder: string, traitRegex: string) {
|
|
208
|
+
let outArray: string[] = [];
|
|
208
209
|
let subFiles = fs.readdirSync(folder);
|
|
209
210
|
let regex = new RegExp(traitRegex);
|
|
210
211
|
for (let subFile of subFiles) {
|
|
211
212
|
let subFilePath = path.join(folder, subFile);
|
|
212
|
-
subFilePath = subFilePath.replace(/\\/g, "/");
|
|
213
213
|
let stat = fs.lstatSync(subFilePath);
|
|
214
|
-
|
|
215
214
|
//判断是否是文件夹,递归调用
|
|
216
215
|
if (stat.isDirectory()) {
|
|
217
|
-
|
|
218
|
-
for (let key in subMap) outMap[key] = subMap[key];
|
|
216
|
+
outArray.push(...fileSearchRegex(path.join(subFilePath, path.sep), traitRegex));
|
|
219
217
|
continue;
|
|
220
218
|
}
|
|
221
|
-
if (regex.test(subFilePath))
|
|
219
|
+
if (regex.test(subFilePath)) outArray.push(subFilePath);
|
|
222
220
|
}
|
|
223
|
-
return
|
|
221
|
+
return outArray;
|
|
222
|
+
}
|
|
223
|
+
/**搜索符合Glob匹配的文件
|
|
224
|
+
* @param globPattern - glob匹配
|
|
225
|
+
* @param ignore - 忽略的文件
|
|
226
|
+
* @returns 文件绝对路径数组
|
|
227
|
+
*/
|
|
228
|
+
export function fileSearchGlob(globPattern:string|string[],ignore?:string|string[]){
|
|
229
|
+
return globSync(globPattern,{ignore,absolute:true});
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* @deprecated 请使用 fileSearchRegex 或 fileSearchGlob
|
|
233
|
+
*/
|
|
234
|
+
export function fileSearch(...patams:any[]){
|
|
235
|
+
throw "请使用 fileSearchRegex 或 fileSearchGlob"
|
|
224
236
|
}
|
|
225
237
|
}
|
package/src/UtilFunctions.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as crypto from "crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { ComposedClass, ComposedClassMult, ComposedPartClass as ComposedPartClass, FuncPropNames, JToken, PromiseProcFn, PromiseStat, PromiseVerifyFn } from "./UtilInterfaces";
|
|
3
3
|
import * as cp from "child_process";
|
|
4
4
|
import { SLogger } from "./UtilLogger";
|
|
5
5
|
|
|
@@ -92,22 +92,38 @@ export function exec(command: string) {
|
|
|
92
92
|
});
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
/**永不完成的Promise单例 */
|
|
95
96
|
const NeverResolvedPromise = new Promise(()=>{});
|
|
96
97
|
/**获得一个永不完成的Promise单例 */
|
|
97
98
|
export function getNeverResolvedPromise<T>():Promise<T>{
|
|
98
99
|
return NeverResolvedPromise as Promise<T>;
|
|
99
100
|
}
|
|
100
101
|
|
|
102
|
+
/**进行中的请求 */
|
|
103
|
+
type ProcessingPromise<T> = {
|
|
104
|
+
/**主体请求 */
|
|
105
|
+
result:T;
|
|
106
|
+
/**请求状态 */
|
|
107
|
+
stat:PromiseStat|Promise<PromiseStat>;
|
|
108
|
+
/**请求下标/序号 */
|
|
109
|
+
index:number;
|
|
110
|
+
};
|
|
111
|
+
|
|
101
112
|
/**重复尝试promise
|
|
102
113
|
* @async
|
|
103
114
|
* @param {PromiseProcFn<T>} [procFn] - 发起函数
|
|
104
115
|
* @param {PromiseVerifyFn<T>} [verifyFn] - 验证函数
|
|
105
|
-
* @param {number} [repeatCount]
|
|
106
|
-
* @param {number} [repeatTime]
|
|
107
|
-
* @returns {Promise<T|null>}
|
|
116
|
+
* @param {number} [repeatCount] - 重试次数
|
|
117
|
+
* @param {number} [repeatTime] - 超时时间/秒 最小为10秒
|
|
118
|
+
* @returns {Promise<T|null>} - 结果 null 为全部失败/超时
|
|
108
119
|
*/
|
|
109
120
|
export async function repeatPromise<T>(procFn:PromiseProcFn<T>,verifyFn?:PromiseVerifyFn<T>,
|
|
110
121
|
repeatCount:number=3,repeatTime:number=180):Promise<T|null>{
|
|
122
|
+
|
|
123
|
+
//计时
|
|
124
|
+
const timeflag = "repeatPromise "+UtilFunc.genUUID();
|
|
125
|
+
SLogger.time(timeflag);
|
|
126
|
+
|
|
111
127
|
//转换为毫秒
|
|
112
128
|
const hasRepeatTime = (repeatTime>=10);
|
|
113
129
|
if(hasRepeatTime) repeatTime*=1000;
|
|
@@ -132,61 +148,218 @@ export async function repeatPromise<T>(procFn:PromiseProcFn<T>,verifyFn?:Promise
|
|
|
132
148
|
}
|
|
133
149
|
|
|
134
150
|
//进行中的请求
|
|
135
|
-
const plist:Promise<ProcessingPromise<T>>[] =
|
|
136
|
-
.fill(UtilFunc.getNeverResolvedPromise());
|
|
137
|
-
for(let i=0;i<repeatCount;){
|
|
138
|
-
SLogger.info("开始第 "+(i+1)+" 次 repeatPromise");
|
|
139
|
-
//创建当前任务
|
|
140
|
-
plist[i] = procFn().then(result =>
|
|
141
|
-
({result, stat:verifyFn!(result), index:i}));
|
|
142
|
-
|
|
143
|
-
//创建定时器
|
|
144
|
-
if(timerP==null){
|
|
145
|
-
timerP = new Promise<"Timeout">(function(resolve, rejecte){
|
|
146
|
-
resolveFn = resolve;
|
|
147
|
-
timer = setTimeout(()=>resolve("Timeout"),
|
|
148
|
-
hasRepeatTime? repeatTime:Infinity);//无限制则无限时间
|
|
149
|
-
})
|
|
150
|
-
}
|
|
151
|
+
const plist:Promise<ProcessingPromise<T>>[] = [];
|
|
151
152
|
|
|
152
|
-
|
|
153
|
-
|
|
153
|
+
//开始处理
|
|
154
|
+
try{
|
|
155
|
+
for(let i=0;i<repeatCount;){
|
|
156
|
+
SLogger.info(`开始第 ${i+1} 次 repeatPromise`);
|
|
157
|
+
//创建当前任务
|
|
158
|
+
if(plist.length<i+1){
|
|
159
|
+
plist.push(procFn().then(result =>
|
|
160
|
+
({result, stat:verifyFn!(result), index:i})));
|
|
161
|
+
}
|
|
154
162
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
163
|
+
//创建定时器
|
|
164
|
+
if(timerP==null){
|
|
165
|
+
timerP = new Promise<"Timeout">(function(resolve, rejecte){
|
|
166
|
+
resolveFn = resolve;
|
|
167
|
+
timer = setTimeout(()=>resolve("Timeout"),
|
|
168
|
+
hasRepeatTime? repeatTime:Infinity);//无限制则无限时间
|
|
169
|
+
})
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
//等待完成
|
|
173
|
+
const currObj = await Promise.race([...plist, timerP]);
|
|
174
|
+
|
|
175
|
+
//超时处理
|
|
176
|
+
if(currObj=="Timeout"){
|
|
177
|
+
SLogger.warn(`第 ${i+1} 次 repeatPromise 超时 ${repeatTime} ms 开始重试`);
|
|
178
|
+
clearTimer(); i++;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
161
181
|
const poststat = await currObj.stat;
|
|
162
182
|
switch(poststat){
|
|
163
183
|
case "Completed"://完成
|
|
164
|
-
SLogger.info(
|
|
165
|
-
|
|
184
|
+
SLogger.info(`第 ${currObj.index+1} 次 repeatPromise 成功`);
|
|
185
|
+
//非当前
|
|
186
|
+
if(currObj.index!=i)
|
|
187
|
+
SLogger.info(`成功的 promise 非当前 promise 考虑增大重试间隔\n当前index: ${i}\n当前间隔: ${repeatTime}`);
|
|
166
188
|
return currObj.result;
|
|
167
189
|
case "Terminated"://终止
|
|
168
|
-
SLogger.warn(
|
|
169
|
-
clearTimer();
|
|
190
|
+
SLogger.warn(`第 ${currObj.index+1} 次 repeatPromise 终止 停止重试`);
|
|
170
191
|
return currObj.result;
|
|
171
192
|
case "Failed"://验证失败
|
|
193
|
+
//抛弃失败
|
|
194
|
+
plist[currObj.index] = UtilFunc.getNeverResolvedPromise();
|
|
172
195
|
//是当前
|
|
173
196
|
if(currObj.index==i){
|
|
174
|
-
SLogger.warn(
|
|
197
|
+
SLogger.warn(`第 ${currObj.index+1} 次 repeatPromise 失败 开始重试`);
|
|
175
198
|
clearTimer(); i++;
|
|
176
199
|
continue;
|
|
177
200
|
}
|
|
178
201
|
//非当前
|
|
179
|
-
SLogger.warn(
|
|
180
|
-
//抛弃失败
|
|
181
|
-
plist[currObj.index] = UtilFunc.getNeverResolvedPromise();
|
|
202
|
+
SLogger.warn(`第 ${currObj.index+1} 次 repeatPromise 失败`);
|
|
182
203
|
continue;
|
|
183
204
|
}
|
|
184
205
|
}
|
|
206
|
+
//全部失败或超时则返回null
|
|
207
|
+
SLogger.warn(`${repeatCount} 次 repeatPromise 尝试均失败`);
|
|
208
|
+
return null;
|
|
209
|
+
}catch(err){
|
|
210
|
+
SLogger.warn(`repeatPromise 发生错误`,err);
|
|
211
|
+
return null;
|
|
212
|
+
}finally{
|
|
213
|
+
//清理
|
|
214
|
+
clearTimer();
|
|
215
|
+
SLogger.timeEnd(timeflag);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
/**柯里化函数类型 */
|
|
221
|
+
type CurryFunc<T, PrevArgs extends any[] = []> = T extends (...args: infer Args) => infer Result
|
|
222
|
+
? Args extends [infer Arg, ...infer RestArgs]
|
|
223
|
+
? RestArgs extends []
|
|
224
|
+
? ((...args: [...PrevArgs, Arg]) => Result )
|
|
225
|
+
: ((...args: [...PrevArgs, Arg]) => CurryFunc<(...rest:RestArgs) => Result> )
|
|
226
|
+
& (CurryFunc<(...args: RestArgs) => Result, [...PrevArgs, Arg]>)
|
|
227
|
+
: Args extends []
|
|
228
|
+
? () => Result
|
|
229
|
+
: never
|
|
230
|
+
: never;
|
|
231
|
+
|
|
232
|
+
/**柯里化转换
|
|
233
|
+
* @param {T} fn - 将要转换的函数
|
|
234
|
+
* @returns {CurryFunc<T>} 柯里化的函数
|
|
235
|
+
*/
|
|
236
|
+
export function curry<T extends (...args: any[]) => any>(fn: T): CurryFunc<T> {
|
|
237
|
+
return (function curried(...args: any[]) {
|
|
238
|
+
if (args.length >= fn.length)
|
|
239
|
+
return fn(...args);
|
|
240
|
+
return (...restArgs: any[]) => curried(...args, ...restArgs);
|
|
241
|
+
}) as CurryFunc<T>;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
let sumvoid = ()=>10;
|
|
245
|
+
let a = curry(sumvoid);//?
|
|
246
|
+
console.log(a());
|
|
247
|
+
let sum = (a:number,b:string,c:number,d:boolean)=>a+b+c+d;
|
|
248
|
+
let sumCu = curry(sum);//?
|
|
249
|
+
let suma = sumCu(1)("ss");//?
|
|
250
|
+
let sumb = sumCu(1,"1")(2);//?
|
|
251
|
+
let sumc = sumCu(4);//?
|
|
252
|
+
let sumz = sumCu(1,"b",3)(false);//?
|
|
253
|
+
console.log(suma(2,true));
|
|
254
|
+
console.log(sumb(true));
|
|
255
|
+
console.log(sumc("s",3,false));
|
|
256
|
+
*/
|
|
257
|
+
/**可组合的函数 */
|
|
258
|
+
type CompFunc<T = any, R = any> = (arg: T) => R;
|
|
259
|
+
/**函数组合 从右到左执行 */
|
|
260
|
+
export function compose<T>(...fs: CompFunc<T, T>[]): CompFunc<T, T>;
|
|
261
|
+
export function compose<T, R>(f1: CompFunc<T, R>): CompFunc<T, R>;
|
|
262
|
+
export function compose<T, R, R1>(f2: CompFunc<R, R1>, f1: CompFunc<T, R>): CompFunc<T, R1>;
|
|
263
|
+
export function compose<T, R, R1, R2>(f3: CompFunc<R1, R2>, f2: CompFunc<R, R1>, f1: CompFunc<T, R>): CompFunc<T, R2>;
|
|
264
|
+
export function compose<T, R, R1, R2, R3>(f4: CompFunc<R2, R3>, f3: CompFunc<R1, R2>, f2: CompFunc<R, R1>, f1: CompFunc<T, R>): CompFunc<T, R3>;
|
|
265
|
+
export function compose<T, R, R1, R2, R3, R4>(f5: CompFunc<R3, R4>,f4: CompFunc<R2, R3>, f3: CompFunc<R1, R2>, f2: CompFunc<R, R1>, f1: CompFunc<T, R>): CompFunc<T, R4>;
|
|
266
|
+
/**函数组合
|
|
267
|
+
* 从右到左执行
|
|
268
|
+
* @param {Function[]} funcs - 待组合的函数
|
|
269
|
+
* @returns {(arg: any)=>any} 组合完成的函数
|
|
270
|
+
*/
|
|
271
|
+
export function compose(...funcs: Function[]) {
|
|
272
|
+
return (arg: any) => funcs.reduceRight((value, func) => func(value), arg);
|
|
273
|
+
}
|
|
274
|
+
/**函数管道 从左到右执行 */
|
|
275
|
+
export function pipeline<T>(...fs: CompFunc<T, T>[]): CompFunc<T, T>;
|
|
276
|
+
export function pipeline<T, R>(f1: CompFunc<T, R>): CompFunc<T, R>;
|
|
277
|
+
export function pipeline<T, R, R1>(f1: CompFunc<T, R>, f2: CompFunc<R, R1>): CompFunc<T, R1>;
|
|
278
|
+
export function pipeline<T, R, R1, R2>(f1: CompFunc<T, R>, f2: CompFunc<R, R1>, f3: CompFunc<R1, R2>): CompFunc<T, R2>;
|
|
279
|
+
export function pipeline<T, R, R1, R2, R3>(f1: CompFunc<T, R>, f2: CompFunc<R, R1>, f3: CompFunc<R1, R2>, f4: CompFunc<R2, R3>): CompFunc<T, R3>;
|
|
280
|
+
export function pipeline<T, R, R1, R2, R3, R4>(f1: CompFunc<T, R>, f2: CompFunc<R, R1>, f3: CompFunc<R1, R2>, f4: CompFunc<R2, R3>, f5: CompFunc<R3, R4>): CompFunc<T, R4>;
|
|
281
|
+
/**函数管道
|
|
282
|
+
* 从左到右执行
|
|
283
|
+
* @param {((arg: T) => T)} funcs - 待组合的函数
|
|
284
|
+
* @returns {((arg: T) => T)} 组合完成的函数
|
|
285
|
+
*/
|
|
286
|
+
export function pipeline<T>(...funcs: ((arg: T) => T)[]): (arg: T) => T {
|
|
287
|
+
return (arg: T): T => {
|
|
288
|
+
return funcs.reduce((value, func) => func(value), arg);
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**部分类组合
|
|
293
|
+
* 将mixin的部分字段混入base
|
|
294
|
+
* @param base - 基础类
|
|
295
|
+
* @param mixin - 目标类
|
|
296
|
+
* @param fields - 需要混入的字段
|
|
297
|
+
* @returns - 混合完成的类
|
|
298
|
+
*/
|
|
299
|
+
export function composePartClass<Base extends object,Mixin extends object>
|
|
300
|
+
(base:Base,mixin:Mixin,...fields:(keyof Mixin)[]):ComposedPartClass<Base,Mixin,keyof Mixin>{
|
|
301
|
+
const compObj = base as any;
|
|
302
|
+
for(const fd of fields){
|
|
303
|
+
Object.defineProperty(compObj, fd, {
|
|
304
|
+
get: ()=>mixin[fd],
|
|
305
|
+
set: (value)=>{mixin[fd] = value},
|
|
306
|
+
enumerable:true ,
|
|
307
|
+
//writable: true ,
|
|
308
|
+
configurable: true
|
|
309
|
+
});
|
|
310
|
+
//(compObj as any)[fd] = (mixin[fd] as any).bind(mixin);
|
|
311
|
+
}
|
|
312
|
+
return compObj;
|
|
313
|
+
}
|
|
314
|
+
/**类组合
|
|
315
|
+
* 将mixinList每个成员的字段混入base
|
|
316
|
+
* @param base - 基础类
|
|
317
|
+
* @param mixinList - 目标类
|
|
318
|
+
* @returns - 混合完成的类
|
|
319
|
+
*/
|
|
320
|
+
export function composeClass<Base extends object,MixinList extends object[]>
|
|
321
|
+
(base:Base,...mixinList:MixinList):ComposedClassMult<Base,MixinList>{
|
|
322
|
+
let obj = base as any;
|
|
323
|
+
for(let mixin of mixinList as any){
|
|
324
|
+
let propks = Object.getOwnPropertyNames(mixin.constructor.prototype)
|
|
325
|
+
for(const key of propks){
|
|
326
|
+
if(key != "constructor"){
|
|
327
|
+
Object.defineProperty(obj, key, {
|
|
328
|
+
get: ()=>mixin[key],
|
|
329
|
+
set: (value)=>{mixin[key] = value},
|
|
330
|
+
enumerable:true,
|
|
331
|
+
//writable: true,
|
|
332
|
+
configurable: true
|
|
333
|
+
});
|
|
334
|
+
//obj[key] = (mixin as any)[key];
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
for(const key in mixin){
|
|
338
|
+
Object.defineProperty(obj, key, {
|
|
339
|
+
get: ()=>mixin[key],
|
|
340
|
+
set: (value)=>{mixin[key] = value},
|
|
341
|
+
enumerable:true ,
|
|
342
|
+
//writable: true ,
|
|
343
|
+
configurable: true
|
|
344
|
+
});
|
|
345
|
+
//obj[key] = (mixin as any)[key];
|
|
346
|
+
}
|
|
185
347
|
}
|
|
186
|
-
|
|
187
|
-
//全部失败或超时则返回null
|
|
188
|
-
return null;
|
|
348
|
+
return obj;
|
|
189
349
|
}
|
|
190
350
|
|
|
351
|
+
/**对对象的每个属性应用映射函数,并返回一个新的对象。
|
|
352
|
+
* @template T - 对象的类型
|
|
353
|
+
* @param obj - 要处理的对象
|
|
354
|
+
* @param mapper - 映射函数,接受一个值和一个键,返回一个新的值
|
|
355
|
+
* @returns - 一个新的对象,它的属性是原对象的属性经过映射函数处理后的结果
|
|
356
|
+
*/
|
|
357
|
+
export function mapObject<T extends Object>
|
|
358
|
+
(obj: T, mapper: (key: keyof T, value: T[keyof T]) => T[keyof T]): T {
|
|
359
|
+
return Object.entries(obj).reduce((result, [key, value]) => {
|
|
360
|
+
result[key as keyof T] = mapper(key as keyof T, value);
|
|
361
|
+
return result;
|
|
362
|
+
}, {} as T);
|
|
191
363
|
}
|
|
192
364
|
|
|
365
|
+
}
|
package/src/UtilInterfaces.ts
CHANGED
|
@@ -72,16 +72,6 @@ export type ExclusiveJObject<B extends JObject,T extends JToken,K extends string
|
|
|
72
72
|
TMP extends JArray = ExclusiveRecursive<B,T,K>> = TMP[number];
|
|
73
73
|
|
|
74
74
|
|
|
75
|
-
/**进行中的请求 */
|
|
76
|
-
export type ProcessingPromise<T> = {
|
|
77
|
-
/**主体请求 */
|
|
78
|
-
result:T;
|
|
79
|
-
/**请求状态 */
|
|
80
|
-
stat:PromiseStat|Promise<PromiseStat>;
|
|
81
|
-
/**请求下标/序号 */
|
|
82
|
-
index:number;
|
|
83
|
-
};
|
|
84
|
-
|
|
85
75
|
/**请求完成状态 成功/失败/终止
|
|
86
76
|
* 成功/终止 将直接返回
|
|
87
77
|
* 失败 将重试
|
|
@@ -90,4 +80,59 @@ export type PromiseStat = "Completed"|"Failed"|"Terminated";
|
|
|
90
80
|
/**promise验证函数 */
|
|
91
81
|
export type PromiseVerifyFn<T> = (obj:T)=>Promise<PromiseStat>|PromiseStat;
|
|
92
82
|
/**发起promise的函数 */
|
|
93
|
-
export type PromiseProcFn<T> = ()=>Promise<T>;
|
|
83
|
+
export type PromiseProcFn<T> = ()=>Promise<T>;
|
|
84
|
+
|
|
85
|
+
/**类型中任意函数的字符串名称 */
|
|
86
|
+
export type FuncPropNames<T> = {
|
|
87
|
+
[K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;
|
|
88
|
+
}[keyof T];
|
|
89
|
+
|
|
90
|
+
/**部分组合的类
|
|
91
|
+
* @template {Base} - 基类
|
|
92
|
+
* @template {Mixin} - 待混入的类
|
|
93
|
+
* @template {PropKeys} - 需要混入的成员key
|
|
94
|
+
*/
|
|
95
|
+
export type ComposedPartClass<Base extends object, Mixin extends object, PropKeys extends keyof Mixin> =
|
|
96
|
+
Base & Pick<Mixin, PropKeys>;
|
|
97
|
+
|
|
98
|
+
/**组合的类 嵌套变体 */
|
|
99
|
+
export type ComposedPartClassMult<Base extends object,
|
|
100
|
+
Mixin1 extends object = {}, PropKeys1 extends keyof Mixin1 = keyof Mixin1,
|
|
101
|
+
Mixin2 extends object = {}, PropKeys2 extends keyof Mixin2 = keyof Mixin2,
|
|
102
|
+
Mixin3 extends object = {}, PropKeys3 extends keyof Mixin3 = keyof Mixin3,
|
|
103
|
+
Mixin4 extends object = {}, PropKeys4 extends keyof Mixin4 = keyof Mixin4,
|
|
104
|
+
Mixin5 extends object = {}, PropKeys5 extends keyof Mixin5 = keyof Mixin5,
|
|
105
|
+
Mixin6 extends object = {}, PropKeys6 extends keyof Mixin6 = keyof Mixin6> =
|
|
106
|
+
ComposedPartClass<ComposedPartClass<ComposedPartClass<
|
|
107
|
+
ComposedPartClass<ComposedPartClass<ComposedPartClass<
|
|
108
|
+
Base,
|
|
109
|
+
Mixin1,PropKeys1>,Mixin2,PropKeys2>,Mixin3,PropKeys3>,
|
|
110
|
+
Mixin4,PropKeys4>,Mixin5,PropKeys5>,Mixin6,PropKeys6>
|
|
111
|
+
|
|
112
|
+
/**递归多组合 仅单key有效 */
|
|
113
|
+
type ComposedClassOnceKey<Base extends object,Data extends [object,string][]> =
|
|
114
|
+
Data extends [[infer Mixin extends object, infer FuncKeys], ...infer Rest]
|
|
115
|
+
? FuncKeys extends FuncPropNames<Mixin>
|
|
116
|
+
? Rest extends [any, any][]
|
|
117
|
+
? ComposedClassOnceKey<ComposedPartClass<Base, Mixin, FuncKeys>,Rest>
|
|
118
|
+
: Base
|
|
119
|
+
: Base
|
|
120
|
+
: Base;
|
|
121
|
+
|
|
122
|
+
/**组合的类
|
|
123
|
+
* @template {Base} - 基类
|
|
124
|
+
* @template {Mixin} - 待混入的类
|
|
125
|
+
*/
|
|
126
|
+
export type ComposedClass<Base extends object,Mixin extends object> = Base&Mixin;
|
|
127
|
+
/**组合的类 多组合变体
|
|
128
|
+
* @template {Base} - 基类
|
|
129
|
+
* @template {MixinList}- 待混入的类型数组
|
|
130
|
+
*/
|
|
131
|
+
export type ComposedClassMult<Base extends object,MixinList extends object[]> =
|
|
132
|
+
MixinList extends [infer Mixin, ...infer Rest]
|
|
133
|
+
? Mixin extends object
|
|
134
|
+
? Rest extends object[]
|
|
135
|
+
? ComposedClassMult<ComposedClass<Base,Mixin>,Rest>
|
|
136
|
+
: Base
|
|
137
|
+
: Base
|
|
138
|
+
: Base;
|