@zwa73/utils 1.0.106 → 1.0.108
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 +17 -6
- package/dist/UtilClass.js +66 -33
- package/dist/UtilCodecs.d.ts +2 -2
- package/dist/UtilCodecs.js +29 -5
- package/dist/UtilFfmpegTools.js +4 -4
- package/dist/UtilFileTools.d.ts +4 -4
- package/dist/UtilFileTools.js +8 -8
- package/dist/UtilFunctions.d.ts +6 -2
- package/dist/UtilFunctions.js +31 -8
- package/dist/UtilInterfaces.d.ts +22 -1
- package/package.json +1 -1
- package/src/UtilClass.ts +69 -36
- package/src/UtilCodecs.ts +5 -3
- package/src/UtilFfmpegTools.ts +4 -4
- package/src/UtilFileTools.ts +8 -8
- package/src/UtilFunctions.ts +36 -9
- package/src/UtilInterfaces.ts +35 -3
package/dist/UtilClass.d.ts
CHANGED
|
@@ -18,26 +18,30 @@ export declare class Piper<Arg, Result = Arg> {
|
|
|
18
18
|
}
|
|
19
19
|
type StreamOperation<T, U> = (item: T) => Promise<U> | U;
|
|
20
20
|
/**并行流 */
|
|
21
|
-
export declare class Stream<T> {
|
|
21
|
+
export declare class Stream<T> implements Iterable<T> {
|
|
22
22
|
/**并发数*/
|
|
23
23
|
private _concurrent;
|
|
24
|
-
/**原始列表*/
|
|
25
24
|
private _list;
|
|
26
25
|
/**加工函数列表*/
|
|
27
26
|
private _operation;
|
|
28
|
-
constructor(
|
|
27
|
+
constructor(base?: Array<T> | number, concurrent?: number);
|
|
29
28
|
/**平分数组
|
|
30
29
|
* @param count - 份数
|
|
31
30
|
* @param mode - 模式 average:轮询平均分 chunk:切块均分
|
|
32
31
|
* @returns 新数组
|
|
33
32
|
*/
|
|
34
33
|
private divide;
|
|
35
|
-
|
|
34
|
+
/**转换流
|
|
35
|
+
* @param operation - 加工函数
|
|
36
|
+
* @returns 新流
|
|
37
|
+
*/
|
|
38
|
+
private trans;
|
|
39
|
+
/**流式的 映射加工
|
|
36
40
|
* @param operation - 加工函数
|
|
37
41
|
* @returns 新流
|
|
38
42
|
*/
|
|
39
43
|
map<U>(operation: StreamOperation<T, U>): Stream<U>;
|
|
40
|
-
|
|
44
|
+
/**流式的 遍历
|
|
41
45
|
* 返回自身
|
|
42
46
|
* @param operation - 遍历函数
|
|
43
47
|
* @returns 自身
|
|
@@ -47,9 +51,16 @@ export declare class Stream<T> {
|
|
|
47
51
|
* @returns 自身
|
|
48
52
|
*/
|
|
49
53
|
append(): Promise<Stream<T>>;
|
|
50
|
-
|
|
54
|
+
/**应用加工 并转换为数组
|
|
51
55
|
* @returns 数组
|
|
52
56
|
*/
|
|
53
57
|
toArray(): Promise<Array<T>>;
|
|
58
|
+
/**应用加工 并过滤
|
|
59
|
+
* @param func - 过滤函数
|
|
60
|
+
* @returns 自身
|
|
61
|
+
*/
|
|
62
|
+
filter(func: (value: T, index: number, array: T[]) => boolean): Promise<Stream<T>>;
|
|
63
|
+
[Symbol.iterator](): Iterator<T>;
|
|
64
|
+
get length(): number;
|
|
54
65
|
}
|
|
55
66
|
export {};
|
package/dist/UtilClass.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Stream = exports.Piper = void 0;
|
|
4
|
+
const QuickFunction_1 = require("./QuickFunction");
|
|
4
5
|
/**函数管道器 */
|
|
5
6
|
class Piper {
|
|
6
7
|
/**管道函数列表 */
|
|
@@ -31,12 +32,16 @@ exports.Piper = Piper;
|
|
|
31
32
|
class Stream {
|
|
32
33
|
/**并发数*/
|
|
33
34
|
_concurrent;
|
|
34
|
-
/**原始列表*/
|
|
35
35
|
_list;
|
|
36
36
|
/**加工函数列表*/
|
|
37
37
|
_operation = [];
|
|
38
|
-
constructor(
|
|
39
|
-
|
|
38
|
+
constructor(base, concurrent = 1) {
|
|
39
|
+
if (base == undefined)
|
|
40
|
+
this._list = new Array();
|
|
41
|
+
else if (typeof base === 'number')
|
|
42
|
+
this._list = new Array(base);
|
|
43
|
+
else
|
|
44
|
+
this._list = new Array(...base);
|
|
40
45
|
this._concurrent = concurrent;
|
|
41
46
|
}
|
|
42
47
|
/**平分数组
|
|
@@ -48,22 +53,21 @@ class Stream {
|
|
|
48
53
|
if (count <= 0)
|
|
49
54
|
return [];
|
|
50
55
|
if (count == 1)
|
|
51
|
-
return [[...this
|
|
56
|
+
return [[...this]];
|
|
57
|
+
const size = this.length;
|
|
52
58
|
const result = [];
|
|
53
|
-
|
|
59
|
+
(0, QuickFunction_1.matchProc)(mode, {
|
|
54
60
|
//轮询平均分
|
|
55
|
-
|
|
61
|
+
'average': () => {
|
|
56
62
|
for (let i = 0; i < count; i++) {
|
|
57
63
|
const clist = [];
|
|
58
|
-
const size = this._list.length;
|
|
59
64
|
for (let j = i; j < size; j += count)
|
|
60
65
|
clist.push(this._list[j]);
|
|
61
66
|
result.push(clist);
|
|
62
67
|
}
|
|
63
|
-
|
|
68
|
+
},
|
|
64
69
|
//切块均分
|
|
65
|
-
|
|
66
|
-
const size = this._list.length;
|
|
70
|
+
'chunk': () => {
|
|
67
71
|
const chunkSize = Math.ceil(size / count);
|
|
68
72
|
for (let i = 0; i < count; i++) {
|
|
69
73
|
const start = i * chunkSize;
|
|
@@ -72,19 +76,28 @@ class Stream {
|
|
|
72
76
|
end = size;
|
|
73
77
|
result.push(this._list.slice(start, end));
|
|
74
78
|
}
|
|
75
|
-
|
|
76
|
-
}
|
|
79
|
+
},
|
|
80
|
+
});
|
|
77
81
|
return result;
|
|
78
82
|
}
|
|
79
|
-
|
|
83
|
+
/**转换流
|
|
84
|
+
* @param operation - 加工函数
|
|
85
|
+
* @returns 新流
|
|
86
|
+
*/
|
|
87
|
+
trans(operation) {
|
|
88
|
+
const ns = new Stream(this._list, this._concurrent);
|
|
89
|
+
ns._operation.push(...this._operation);
|
|
90
|
+
ns._operation.push(operation);
|
|
91
|
+
return ns;
|
|
92
|
+
}
|
|
93
|
+
/**流式的 映射加工
|
|
80
94
|
* @param operation - 加工函数
|
|
81
95
|
* @returns 新流
|
|
82
96
|
*/
|
|
83
97
|
map(operation) {
|
|
84
|
-
this.
|
|
85
|
-
return this;
|
|
98
|
+
return this.trans(operation);
|
|
86
99
|
}
|
|
87
|
-
|
|
100
|
+
/**流式的 遍历
|
|
88
101
|
* 返回自身
|
|
89
102
|
* @param operation - 遍历函数
|
|
90
103
|
* @returns 自身
|
|
@@ -94,8 +107,8 @@ class Stream {
|
|
|
94
107
|
operation(item);
|
|
95
108
|
return item;
|
|
96
109
|
};
|
|
97
|
-
this.
|
|
98
|
-
|
|
110
|
+
return this.trans(opera);
|
|
111
|
+
;
|
|
99
112
|
}
|
|
100
113
|
//终结操作
|
|
101
114
|
/**应用加工
|
|
@@ -104,14 +117,12 @@ class Stream {
|
|
|
104
117
|
async append() {
|
|
105
118
|
if (this._operation.length == 0)
|
|
106
119
|
return this;
|
|
107
|
-
const
|
|
120
|
+
const pList = [];
|
|
108
121
|
//均分处理
|
|
109
|
-
|
|
110
|
-
for (let i = 0; i < this._concurrent; i++) {
|
|
111
|
-
const subList = sliceList[i];
|
|
122
|
+
this.divide(this._concurrent).forEach((subList) => {
|
|
112
123
|
if (!subList)
|
|
113
|
-
|
|
114
|
-
|
|
124
|
+
return;
|
|
125
|
+
pList.push(new Promise(async (reslove) => {
|
|
115
126
|
const result = [];
|
|
116
127
|
for (let item of subList) {
|
|
117
128
|
if (!item)
|
|
@@ -122,28 +133,50 @@ class Stream {
|
|
|
122
133
|
}
|
|
123
134
|
reslove(result);
|
|
124
135
|
}));
|
|
125
|
-
}
|
|
126
|
-
const
|
|
136
|
+
});
|
|
137
|
+
const rlist = await Promise.all(pList);
|
|
127
138
|
//拼接结果 轮询均分
|
|
128
|
-
const result = new Array(this.
|
|
129
|
-
|
|
130
|
-
const subList = nlist[i];
|
|
139
|
+
const result = new Array(this.length).fill(undefined);
|
|
140
|
+
rlist.forEach((subList, i) => {
|
|
131
141
|
if (!subList)
|
|
132
|
-
|
|
142
|
+
return;
|
|
133
143
|
const subSize = subList.length;
|
|
134
144
|
for (let j = 0; j < subSize; j++)
|
|
135
145
|
result[i + j * this._concurrent] = subList[j];
|
|
136
|
-
}
|
|
146
|
+
});
|
|
137
147
|
this._list = result;
|
|
138
148
|
this._operation = [];
|
|
139
149
|
return this;
|
|
140
150
|
}
|
|
141
|
-
|
|
151
|
+
/**应用加工 并转换为数组
|
|
142
152
|
* @returns 数组
|
|
143
153
|
*/
|
|
144
154
|
async toArray() {
|
|
145
155
|
await this.append();
|
|
146
|
-
return this
|
|
156
|
+
return [...this];
|
|
157
|
+
}
|
|
158
|
+
/**应用加工 并过滤
|
|
159
|
+
* @param func - 过滤函数
|
|
160
|
+
* @returns 自身
|
|
161
|
+
*/
|
|
162
|
+
async filter(func) {
|
|
163
|
+
await this.append();
|
|
164
|
+
return new Stream(this._list.filter(func));
|
|
165
|
+
}
|
|
166
|
+
//迭代器
|
|
167
|
+
[Symbol.iterator]() {
|
|
168
|
+
let index = 0;
|
|
169
|
+
const data = this._list;
|
|
170
|
+
return {
|
|
171
|
+
next: () => ({
|
|
172
|
+
value: data[index++],
|
|
173
|
+
done: index > data.length
|
|
174
|
+
})
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
// 创建 length 属性的 getter 和 setter
|
|
178
|
+
get length() {
|
|
179
|
+
return this._list.length;
|
|
147
180
|
}
|
|
148
181
|
}
|
|
149
182
|
exports.Stream = Stream;
|
package/dist/UtilCodecs.d.ts
CHANGED
|
@@ -34,10 +34,10 @@ export declare namespace UtilCodec {
|
|
|
34
34
|
* @param arr = Token数组
|
|
35
35
|
* @returns 消息字符串
|
|
36
36
|
*/
|
|
37
|
-
function decodeTokenTurbo(arr: Uint32Array): string;
|
|
37
|
+
function decodeTokenTurbo(arr: Uint32Array | number[]): string;
|
|
38
38
|
/**token解码 Davinci模型
|
|
39
39
|
* @param arr = Token数组
|
|
40
40
|
* @returns 消息字符串
|
|
41
41
|
*/
|
|
42
|
-
function decodeTokenDavinci(arr: Uint32Array): string;
|
|
42
|
+
function decodeTokenDavinci(arr: Uint32Array | number[]): string;
|
|
43
43
|
}
|
package/dist/UtilCodecs.js
CHANGED
|
@@ -1,10 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
4
24
|
};
|
|
5
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
26
|
exports.UtilCodec = void 0;
|
|
7
|
-
const
|
|
27
|
+
const he = __importStar(require("html-entities"));
|
|
8
28
|
const tiktoken_1 = require("tiktoken");
|
|
9
29
|
/**编码/解码器 */
|
|
10
30
|
var UtilCodec;
|
|
@@ -17,7 +37,7 @@ var UtilCodec;
|
|
|
17
37
|
* @returns 转换后的字符串
|
|
18
38
|
*/
|
|
19
39
|
function decodeHtmlEntities(str) {
|
|
20
|
-
return
|
|
40
|
+
return he.decode(str);
|
|
21
41
|
}
|
|
22
42
|
UtilCodec.decodeHtmlEntities = decodeHtmlEntities;
|
|
23
43
|
/**HTML实体编码 将一个字符串中的 需编码字符转换为 HTML实体
|
|
@@ -25,7 +45,7 @@ var UtilCodec;
|
|
|
25
45
|
* @returns 转换后的字符串
|
|
26
46
|
*/
|
|
27
47
|
function encodeHtmlEntities(str) {
|
|
28
|
-
return
|
|
48
|
+
return he.encode(str);
|
|
29
49
|
}
|
|
30
50
|
UtilCodec.encodeHtmlEntities = encodeHtmlEntities;
|
|
31
51
|
//#region LAM
|
|
@@ -83,6 +103,8 @@ var UtilCodec;
|
|
|
83
103
|
*/
|
|
84
104
|
function decodeTokenTurbo(arr) {
|
|
85
105
|
initTikTokenEncoder();
|
|
106
|
+
if (Array.isArray(arr))
|
|
107
|
+
arr = new Uint32Array(arr);
|
|
86
108
|
return textDecoder.decode(encoderTurbo?.decode(arr));
|
|
87
109
|
}
|
|
88
110
|
UtilCodec.decodeTokenTurbo = decodeTokenTurbo;
|
|
@@ -92,6 +114,8 @@ var UtilCodec;
|
|
|
92
114
|
*/
|
|
93
115
|
function decodeTokenDavinci(arr) {
|
|
94
116
|
initTikTokenEncoder();
|
|
117
|
+
if (Array.isArray(arr))
|
|
118
|
+
arr = new Uint32Array(arr);
|
|
95
119
|
return textDecoder.decode(encoderDavinci?.decode(arr));
|
|
96
120
|
}
|
|
97
121
|
UtilCodec.decodeTokenDavinci = decodeTokenDavinci;
|
package/dist/UtilFfmpegTools.js
CHANGED
|
@@ -164,7 +164,7 @@ class SFfmpegTool {
|
|
|
164
164
|
static async wav2oggMP(ioMap, quality = 10, cpCount = 16) {
|
|
165
165
|
await new UtilClass_1.Stream(Object.entries(ioMap))
|
|
166
166
|
.map(async ([inPath, outPath]) => {
|
|
167
|
-
UtilLogger_1.SLogger.info(
|
|
167
|
+
UtilLogger_1.SLogger.info(`SFfmpegTool.wav2oggMP 正在处理:${outPath}`);
|
|
168
168
|
await SFfmpegTool.wav2ogg(inPath, outPath, quality);
|
|
169
169
|
})
|
|
170
170
|
.append();
|
|
@@ -177,7 +177,7 @@ class SFfmpegTool {
|
|
|
177
177
|
static async flac2oggMP(ioMap, quality = 10, cpCount = 16) {
|
|
178
178
|
await new UtilClass_1.Stream(Object.entries(ioMap))
|
|
179
179
|
.map(async ([inPath, outPath]) => {
|
|
180
|
-
UtilLogger_1.SLogger.info(
|
|
180
|
+
UtilLogger_1.SLogger.info(`SFfmpegTool.flac2oggMP 正在处理:${outPath}`);
|
|
181
181
|
await SFfmpegTool.flac2ogg(inPath, outPath, quality);
|
|
182
182
|
})
|
|
183
183
|
.append();
|
|
@@ -190,7 +190,7 @@ class SFfmpegTool {
|
|
|
190
190
|
static async trimSilenceMP(ioMap, threshold = -50, silence = 0.2, cpCount = 16) {
|
|
191
191
|
await new UtilClass_1.Stream(Object.entries(ioMap))
|
|
192
192
|
.map(async ([inPath, outPath]) => {
|
|
193
|
-
UtilLogger_1.SLogger.info(
|
|
193
|
+
UtilLogger_1.SLogger.info(`SFfmpegTool.trimSilenceMP 正在处理:${outPath}`);
|
|
194
194
|
await SFfmpegTool.trimSilence(inPath, outPath, threshold, silence);
|
|
195
195
|
})
|
|
196
196
|
.append();
|
|
@@ -203,7 +203,7 @@ class SFfmpegTool {
|
|
|
203
203
|
static async resampleMP(ioMap, rate = 22050, cpCount = 16) {
|
|
204
204
|
await new UtilClass_1.Stream(Object.entries(ioMap))
|
|
205
205
|
.map(async ([inPath, outPath]) => {
|
|
206
|
-
UtilLogger_1.SLogger.info(
|
|
206
|
+
UtilLogger_1.SLogger.info(`SFfmpegTool.resampleMP 正在处理:${outPath}`);
|
|
207
207
|
await SFfmpegTool.resample(inPath, outPath, rate);
|
|
208
208
|
})
|
|
209
209
|
.append();
|
package/dist/UtilFileTools.d.ts
CHANGED
|
@@ -98,21 +98,21 @@ export declare namespace UtilFT {
|
|
|
98
98
|
*/
|
|
99
99
|
function writeJSONFile(filePath: string, token: JToken): Promise<void>;
|
|
100
100
|
/**搜索路径符合正则表达式的文件
|
|
101
|
-
* @param
|
|
101
|
+
* @param dir - 起始目录
|
|
102
102
|
* @param traitRegex - 正则表达式
|
|
103
103
|
* @param opt - 可选参数
|
|
104
104
|
* @param opt.relative - 搜索子目录
|
|
105
105
|
* @returns 文件名路径数组
|
|
106
106
|
*/
|
|
107
|
-
function fileSearchRegex(
|
|
107
|
+
function fileSearchRegex(dir: string, traitRegex: string, opt?: FileSearchRegexOpt): string[];
|
|
108
108
|
/**搜索符合Glob匹配的文件
|
|
109
|
-
* @param
|
|
109
|
+
* @param dir - 起始目录
|
|
110
110
|
* @param globPattern - glob匹配
|
|
111
111
|
* @param opt - 可选参数
|
|
112
112
|
* @param opt.ignore - 忽略的文件
|
|
113
113
|
* @returns 文件绝对路径数组
|
|
114
114
|
*/
|
|
115
|
-
function fileSearchGlob(
|
|
115
|
+
function fileSearchGlob(dir: string, globPattern: string | string[], opt?: FileSearchGlobOpt): string[];
|
|
116
116
|
/**
|
|
117
117
|
* @deprecated 请使用 fileSearchRegex 或 fileSearchGlob
|
|
118
118
|
*/
|
package/dist/UtilFileTools.js
CHANGED
|
@@ -194,19 +194,19 @@ var UtilFT;
|
|
|
194
194
|
}
|
|
195
195
|
UtilFT.writeJSONFile = writeJSONFile;
|
|
196
196
|
/**搜索路径符合正则表达式的文件
|
|
197
|
-
* @param
|
|
197
|
+
* @param dir - 起始目录
|
|
198
198
|
* @param traitRegex - 正则表达式
|
|
199
199
|
* @param opt - 可选参数
|
|
200
200
|
* @param opt.relative - 搜索子目录
|
|
201
201
|
* @returns 文件名路径数组
|
|
202
202
|
*/
|
|
203
|
-
function fileSearchRegex(
|
|
203
|
+
function fileSearchRegex(dir, traitRegex, opt) {
|
|
204
204
|
const relative = opt?.relative ?? true;
|
|
205
205
|
const outArray = [];
|
|
206
|
-
const subFiles = fs.readdirSync(
|
|
206
|
+
const subFiles = fs.readdirSync(dir, { withFileTypes: true });
|
|
207
207
|
const regex = new RegExp(traitRegex);
|
|
208
208
|
for (const subFile of subFiles) {
|
|
209
|
-
const subFilePath = path.join(
|
|
209
|
+
const subFilePath = path.join(dir, subFile.name);
|
|
210
210
|
//判断是否是文件夹,递归调用
|
|
211
211
|
if (subFile.isDirectory()) {
|
|
212
212
|
if (relative)
|
|
@@ -220,16 +220,16 @@ var UtilFT;
|
|
|
220
220
|
}
|
|
221
221
|
UtilFT.fileSearchRegex = fileSearchRegex;
|
|
222
222
|
/**搜索符合Glob匹配的文件
|
|
223
|
-
* @param
|
|
223
|
+
* @param dir - 起始目录
|
|
224
224
|
* @param globPattern - glob匹配
|
|
225
225
|
* @param opt - 可选参数
|
|
226
226
|
* @param opt.ignore - 忽略的文件
|
|
227
227
|
* @returns 文件绝对路径数组
|
|
228
228
|
*/
|
|
229
|
-
function fileSearchGlob(
|
|
229
|
+
function fileSearchGlob(dir, globPattern, opt) {
|
|
230
230
|
const fixedPath = typeof globPattern === "string"
|
|
231
|
-
? path.join(
|
|
232
|
-
: globPattern.map((p) => path.join(
|
|
231
|
+
? path.join(dir, path.posix.normalize(globPattern))
|
|
232
|
+
: globPattern.map((p) => path.join(dir, path.posix.normalize(p)));
|
|
233
233
|
return (0, glob_1.globSync)(fixedPath, { ignore: opt?.ingore, absolute: true });
|
|
234
234
|
}
|
|
235
235
|
UtilFT.fileSearchGlob = fileSearchGlob;
|
package/dist/UtilFunctions.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AnyFunc, ComposedClass, ComposedMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, LiteralCheck, Matchable, MatchableFlag, Mixinable, Outcome, PromiseVerifyFn, UnionToIntersection } from "./UtilInterfaces";
|
|
1
|
+
import { AnyFunc, ComposedClass, ComposedMixinable, ComposedRefMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, LiteralCheck, Matchable, MatchableFlag, Mixinable, Outcome, PromiseVerifyFn, RefMixinable, UnionToIntersection } from "./UtilInterfaces";
|
|
2
2
|
import { LogLevel } from "./UtilLogger";
|
|
3
3
|
import { FailedLike, None, StatusSymbol, Success, SuccessLike, Timeout } from "./UtilSymbol";
|
|
4
4
|
type SuccessOut<T> = Outcome<Success, T>;
|
|
@@ -82,8 +82,12 @@ export declare class UtilFunc {
|
|
|
82
82
|
* @returns 混合完成的类
|
|
83
83
|
*/
|
|
84
84
|
static composeClassPart<Base extends object, Mixin extends object, Field extends keyof Mixin>(base: Base, mixin: Mixin, key: string, ...fields: Field[]): ComposedClass<Base, Mixin, typeof key, Field>;
|
|
85
|
-
/**根据 MIXIN_FIELDS 自动混入
|
|
85
|
+
/**根据 MIXIN_FIELDS 自动混入
|
|
86
|
+
* @deprecated 非必要情况下, 对class定义请使用 composeRefMixinable
|
|
87
|
+
*/
|
|
86
88
|
static composeMixinable<Base extends object, Mixins extends Mixinable<any>[]>(base: Base, ...mixins: Mixins): ComposedMixinable<Base, Mixins>;
|
|
89
|
+
/**根据 MIXIN_FIELDS 自动混入 */
|
|
90
|
+
static composeRefMixinable<Base extends object, Mixins extends RefMixinable<any, unknown>[]>(base: Base, ...mixins: Mixins): ComposedRefMixinable<Base, Mixins>;
|
|
87
91
|
/**对对象的每个属性应用映射函数,并返回一个新的对象。
|
|
88
92
|
* @template T - 对象的类型
|
|
89
93
|
* @param obj - 要处理的对象
|
package/dist/UtilFunctions.js
CHANGED
|
@@ -255,17 +255,21 @@ class UtilFunc {
|
|
|
255
255
|
for (const fd of fields) {
|
|
256
256
|
if (compObj[fd] !== undefined)
|
|
257
257
|
UtilLogger_1.SLogger.warn(`field: ${fd} 已存在于基础类中, 混入可能导致类型问题, 如需覆盖, 请使用 ${key}=val`);
|
|
258
|
-
//
|
|
259
|
-
// get: ()=>compObj[key][fd],
|
|
260
|
-
// set: (value)=>{compObj[key][fd] = value},
|
|
261
|
-
// enumerable:true ,
|
|
262
|
-
// //writable: true ,
|
|
263
|
-
// configurable: true
|
|
264
|
-
//});
|
|
258
|
+
//func需绑定this无法直接设置属性
|
|
265
259
|
if (typeof mixin[fd] === 'function') {
|
|
266
260
|
compObj[fd] = (...args) => compObj[key][fd](...args);
|
|
261
|
+
//#region other
|
|
262
|
+
//const memo = (...args: any[]) => compObj[key][fd](...args);
|
|
263
|
+
//Object.defineProperty(compObj, fd, {
|
|
264
|
+
// get:()=>memo,
|
|
265
|
+
// set:()=>SLogger.warn(new Error(`试图修改一个由 composeClassPart 组合的函数字段:${String(fd)}, 修改已被忽略`)),
|
|
266
|
+
// enumerable:true ,
|
|
267
|
+
// //writable: true ,
|
|
268
|
+
// configurable: true
|
|
269
|
+
//});
|
|
267
270
|
//(compObj as any)[fd] = (...args: any[]) => (mixin[fd] as any).apply(mixin, args);
|
|
268
271
|
//(compObj as any)[fd] = (mixin[fd] as any).bind(mixin);
|
|
272
|
+
//#endregion
|
|
269
273
|
}
|
|
270
274
|
else {
|
|
271
275
|
Object.defineProperty(compObj, fd, {
|
|
@@ -279,7 +283,9 @@ class UtilFunc {
|
|
|
279
283
|
}
|
|
280
284
|
return compObj;
|
|
281
285
|
}
|
|
282
|
-
/**根据 MIXIN_FIELDS 自动混入
|
|
286
|
+
/**根据 MIXIN_FIELDS 自动混入
|
|
287
|
+
* @deprecated 非必要情况下, 对class定义请使用 composeRefMixinable
|
|
288
|
+
*/
|
|
283
289
|
static composeMixinable(base, ...mixins) {
|
|
284
290
|
let out = base;
|
|
285
291
|
const fieldsSet = new Set();
|
|
@@ -296,6 +302,23 @@ class UtilFunc {
|
|
|
296
302
|
}
|
|
297
303
|
return out;
|
|
298
304
|
}
|
|
305
|
+
/**根据 MIXIN_FIELDS 自动混入 */
|
|
306
|
+
static composeRefMixinable(base, ...mixins) {
|
|
307
|
+
let out = base;
|
|
308
|
+
const fieldsSet = new Set();
|
|
309
|
+
for (const mixin of mixins) {
|
|
310
|
+
const ctor = mixin.CTOR;
|
|
311
|
+
for (const field of ctor.MIXIN_FIELDS) {
|
|
312
|
+
const fixField = field;
|
|
313
|
+
if (fieldsSet.has(fixField))
|
|
314
|
+
UtilLogger_1.SLogger.warn(`composeMixinable 出现了重复的 field: ${fixField} 可能会导致问题`);
|
|
315
|
+
else
|
|
316
|
+
fieldsSet.add(fixField);
|
|
317
|
+
}
|
|
318
|
+
out = UtilFunc.composeClassPart(base, mixin, ctor.MIXIN_KEY, ...ctor.MIXIN_FIELDS);
|
|
319
|
+
}
|
|
320
|
+
return out;
|
|
321
|
+
}
|
|
299
322
|
/**对对象的每个属性应用映射函数,并返回一个新的对象。
|
|
300
323
|
* @template T - 对象的类型
|
|
301
324
|
* @param obj - 要处理的对象
|
package/dist/UtilInterfaces.d.ts
CHANGED
|
@@ -105,8 +105,29 @@ export type Mixinable<Mixin> = {
|
|
|
105
105
|
*/
|
|
106
106
|
readonly MIXIN_FIELDS: readonly (keyof Mixin)[];
|
|
107
107
|
};
|
|
108
|
-
|
|
108
|
+
/**是原型构造器类型 */
|
|
109
|
+
export type IsCtor<T> = T extends {
|
|
110
|
+
new (): infer Ins;
|
|
111
|
+
} ? T : never;
|
|
112
|
+
/**可反射的
|
|
113
|
+
* @template Ctor - 构造器类型
|
|
114
|
+
* @template Constraint - 构造器约束
|
|
115
|
+
*/
|
|
116
|
+
export type ReflectionAble<Ctor, Constraint = {}> = {
|
|
117
|
+
/**原型构造器 */
|
|
118
|
+
readonly CTOR: Ctor & Constraint;
|
|
119
|
+
};
|
|
120
|
+
/**可反射的 且 构造函数是可混入的类
|
|
121
|
+
* @template Ctor - 构造器类型
|
|
122
|
+
* @template Instance - 实例类型
|
|
123
|
+
* @template Constraint - 构造器约束
|
|
124
|
+
*/
|
|
125
|
+
export type RefMixinable<Ctor, Instance, Constraint = {}> = ReflectionAble<Ctor, Mixinable<Instance> & Constraint>;
|
|
126
|
+
/**自动组合可混入的类
|
|
127
|
+
*/
|
|
109
128
|
export type ComposedMixinable<B, Ms extends unknown[]> = Ms extends [infer M, ...infer Rest] ? M extends Mixinable<M> ? ComposedMixinable<ComposedClass<B, M, M['MIXIN_KEY'], M['MIXIN_FIELDS'][number]>, Rest> : "一个混入类没有实现 Mixinable<self>" & Error : B;
|
|
129
|
+
/**自动组合 可反射的 且 构造函数是可混入的 类 */
|
|
130
|
+
export type ComposedRefMixinable<B, Ms extends unknown[]> = Ms extends [infer M, ...infer Rest] ? M extends RefMixinable<unknown, M> ? ComposedRefMixinable<ComposedClass<B, M, M['CTOR']['MIXIN_KEY'], M['CTOR']['MIXIN_FIELDS'][number]>, Rest> : "一个混入类没有实现 RefMixinable<typeof self, self>" & Error : B;
|
|
110
131
|
/** extends封装
|
|
111
132
|
* @template B - 基础类型
|
|
112
133
|
* @template T - 判断的目标类型
|
package/package.json
CHANGED
package/src/UtilClass.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { matchProc } from "./QuickFunction";
|
|
2
|
+
|
|
1
3
|
/**函数管道器 */
|
|
2
4
|
export class Piper<Arg, Result = Arg> {
|
|
3
5
|
/**管道函数列表 */
|
|
@@ -35,15 +37,16 @@ export class Piper<Arg, Result = Arg> {
|
|
|
35
37
|
|
|
36
38
|
type StreamOperation<T, U> = (item: T)=>Promise<U>|U;
|
|
37
39
|
/**并行流 */
|
|
38
|
-
export class Stream<T> {
|
|
40
|
+
export class Stream<T> implements Iterable<T>{
|
|
39
41
|
/**并发数*/
|
|
40
42
|
private _concurrent: number;
|
|
41
|
-
/**原始列表*/
|
|
42
43
|
private _list: T[];
|
|
43
44
|
/**加工函数列表*/
|
|
44
45
|
private _operation: Array<StreamOperation<T, T>> = [];
|
|
45
|
-
constructor(
|
|
46
|
-
this._list =
|
|
46
|
+
constructor(base?: Array<T>|number, concurrent: number = 1) {
|
|
47
|
+
if(base==undefined) this._list = new Array();
|
|
48
|
+
else if(typeof base === 'number') this._list = new Array(base);
|
|
49
|
+
else this._list = new Array(...base);
|
|
47
50
|
this._concurrent = concurrent;
|
|
48
51
|
}
|
|
49
52
|
/**平分数组
|
|
@@ -53,23 +56,22 @@ export class Stream<T> {
|
|
|
53
56
|
*/
|
|
54
57
|
private divide(count: number, mode: "average" | "chunk" = "average"): T[][] {
|
|
55
58
|
if (count <= 0) return [];
|
|
56
|
-
if (count == 1) return [[...this
|
|
59
|
+
if (count == 1) return [[...this]];
|
|
60
|
+
const size = this.length;
|
|
61
|
+
const result:T[][] = [];
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
switch (mode) {
|
|
63
|
+
matchProc(mode,{
|
|
60
64
|
//轮询平均分
|
|
61
|
-
|
|
65
|
+
'average':()=>{
|
|
62
66
|
for (let i = 0; i < count; i++) {
|
|
63
67
|
const clist = [];
|
|
64
|
-
const size = this._list.length;
|
|
65
68
|
for (let j = i; j < size; j += count)
|
|
66
69
|
clist.push(this._list[j]);
|
|
67
70
|
result.push(clist);
|
|
68
71
|
}
|
|
69
|
-
|
|
72
|
+
},
|
|
70
73
|
//切块均分
|
|
71
|
-
|
|
72
|
-
const size = this._list.length;
|
|
74
|
+
'chunk':()=>{
|
|
73
75
|
const chunkSize = Math.ceil(size / count);
|
|
74
76
|
for (let i = 0; i < count; i++) {
|
|
75
77
|
const start = i * chunkSize;
|
|
@@ -77,20 +79,29 @@ export class Stream<T> {
|
|
|
77
79
|
if (end > size) end = size;
|
|
78
80
|
result.push(this._list.slice(start, end));
|
|
79
81
|
}
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
+
},
|
|
83
|
+
})
|
|
82
84
|
return result;
|
|
83
85
|
}
|
|
86
|
+
/**转换流
|
|
87
|
+
* @param operation - 加工函数
|
|
88
|
+
* @returns 新流
|
|
89
|
+
*/
|
|
90
|
+
private trans<U>(operation:StreamOperation<T, U>): Stream<U>{
|
|
91
|
+
const ns = new Stream(this._list,this._concurrent);
|
|
92
|
+
ns._operation.push(...this._operation);
|
|
93
|
+
ns._operation.push(operation as any);
|
|
94
|
+
return ns as any;
|
|
95
|
+
}
|
|
84
96
|
|
|
85
|
-
|
|
97
|
+
/**流式的 映射加工
|
|
86
98
|
* @param operation - 加工函数
|
|
87
99
|
* @returns 新流
|
|
88
100
|
*/
|
|
89
101
|
map<U>(operation: StreamOperation<T, U>): Stream<U> {
|
|
90
|
-
this.
|
|
91
|
-
return this as any as Stream<U>;
|
|
102
|
+
return this.trans(operation);
|
|
92
103
|
}
|
|
93
|
-
|
|
104
|
+
/**流式的 遍历
|
|
94
105
|
* 返回自身
|
|
95
106
|
* @param operation - 遍历函数
|
|
96
107
|
* @returns 自身
|
|
@@ -100,8 +111,7 @@ export class Stream<T> {
|
|
|
100
111
|
operation(item);
|
|
101
112
|
return item;
|
|
102
113
|
};
|
|
103
|
-
this.
|
|
104
|
-
return this;
|
|
114
|
+
return this.trans(opera);;
|
|
105
115
|
}
|
|
106
116
|
|
|
107
117
|
//终结操作
|
|
@@ -111,13 +121,11 @@ export class Stream<T> {
|
|
|
111
121
|
async append(): Promise<Stream<T>> {
|
|
112
122
|
if (this._operation.length == 0) return this;
|
|
113
123
|
|
|
114
|
-
const
|
|
124
|
+
const pList: Promise<T[]>[] = [];
|
|
115
125
|
//均分处理
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (!subList) continue;
|
|
120
|
-
promiseList.push(
|
|
126
|
+
this.divide(this._concurrent).forEach((subList)=>{
|
|
127
|
+
if (!subList) return;
|
|
128
|
+
pList.push(
|
|
121
129
|
new Promise(async (reslove) => {
|
|
122
130
|
const result:T[] = [];
|
|
123
131
|
for (let item of subList) {
|
|
@@ -129,27 +137,52 @@ export class Stream<T> {
|
|
|
129
137
|
reslove(result);
|
|
130
138
|
})
|
|
131
139
|
);
|
|
132
|
-
}
|
|
133
|
-
const
|
|
140
|
+
})
|
|
141
|
+
const rlist = await Promise.all(pList);
|
|
142
|
+
|
|
134
143
|
//拼接结果 轮询均分
|
|
135
|
-
const result = new Array(this.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (!subList) continue;
|
|
144
|
+
const result = new Array(this.length).fill(undefined);
|
|
145
|
+
rlist.forEach((subList,i)=>{
|
|
146
|
+
if (!subList) return;
|
|
139
147
|
const subSize = subList.length;
|
|
140
148
|
for (let j = 0; j < subSize; j++)
|
|
141
149
|
result[i + j * this._concurrent] = subList[j];
|
|
142
|
-
}
|
|
150
|
+
});
|
|
151
|
+
|
|
143
152
|
this._list = result;
|
|
144
153
|
this._operation = [];
|
|
145
154
|
return this;
|
|
146
155
|
}
|
|
147
|
-
|
|
156
|
+
/**应用加工 并转换为数组
|
|
148
157
|
* @returns 数组
|
|
149
158
|
*/
|
|
150
159
|
async toArray(): Promise<Array<T>> {
|
|
151
160
|
await this.append();
|
|
152
|
-
return this
|
|
161
|
+
return [...this];
|
|
153
162
|
}
|
|
154
|
-
|
|
163
|
+
/**应用加工 并过滤
|
|
164
|
+
* @param func - 过滤函数
|
|
165
|
+
* @returns 自身
|
|
166
|
+
*/
|
|
167
|
+
async filter(func:(value: T, index: number, array: T[])=>boolean): Promise<Stream<T>>{
|
|
168
|
+
await this.append();
|
|
169
|
+
return new Stream(this._list.filter(func));
|
|
170
|
+
}
|
|
171
|
+
//迭代器
|
|
172
|
+
[Symbol.iterator](): Iterator<T> {
|
|
173
|
+
let index = 0;
|
|
174
|
+
const data = this._list;
|
|
155
175
|
|
|
176
|
+
return {
|
|
177
|
+
next: () => ({
|
|
178
|
+
value: data[index++],
|
|
179
|
+
done: index > data.length
|
|
180
|
+
})
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// 创建 length 属性的 getter 和 setter
|
|
185
|
+
get length(): number {
|
|
186
|
+
return this._list.length;
|
|
187
|
+
}
|
|
188
|
+
}
|
package/src/UtilCodecs.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import he from 'html-entities';
|
|
1
|
+
import * as he from 'html-entities';
|
|
2
2
|
import {get_encoding,Tiktoken} from 'tiktoken';
|
|
3
3
|
|
|
4
4
|
|
|
@@ -81,16 +81,18 @@ export function encodeTokenDavinci(str:string):Uint32Array{
|
|
|
81
81
|
* @param arr = Token数组
|
|
82
82
|
* @returns 消息字符串
|
|
83
83
|
*/
|
|
84
|
-
export function decodeTokenTurbo(arr:Uint32Array):string{
|
|
84
|
+
export function decodeTokenTurbo(arr:Uint32Array|number[]):string{
|
|
85
85
|
initTikTokenEncoder();
|
|
86
|
+
if(Array.isArray(arr)) arr = new Uint32Array(arr);
|
|
86
87
|
return textDecoder.decode(encoderTurbo?.decode(arr));
|
|
87
88
|
}
|
|
88
89
|
/**token解码 Davinci模型
|
|
89
90
|
* @param arr = Token数组
|
|
90
91
|
* @returns 消息字符串
|
|
91
92
|
*/
|
|
92
|
-
export function decodeTokenDavinci(arr:Uint32Array):string{
|
|
93
|
+
export function decodeTokenDavinci(arr:Uint32Array|number[]):string{
|
|
93
94
|
initTikTokenEncoder();
|
|
95
|
+
if(Array.isArray(arr)) arr = new Uint32Array(arr);
|
|
94
96
|
return textDecoder.decode(encoderDavinci?.decode(arr));
|
|
95
97
|
}
|
|
96
98
|
//#endregion
|
package/src/UtilFfmpegTools.ts
CHANGED
|
@@ -168,7 +168,7 @@ class SFfmpegTool {
|
|
|
168
168
|
static async wav2oggMP(ioMap: IOMap, quality = 10, cpCount = 16) {
|
|
169
169
|
await new Stream(Object.entries(ioMap))
|
|
170
170
|
.map(async ([inPath, outPath]) => {
|
|
171
|
-
SLogger.info(
|
|
171
|
+
SLogger.info(`SFfmpegTool.wav2oggMP 正在处理:${outPath}`);
|
|
172
172
|
await SFfmpegTool.wav2ogg(inPath, outPath, quality);
|
|
173
173
|
})
|
|
174
174
|
.append();
|
|
@@ -185,7 +185,7 @@ class SFfmpegTool {
|
|
|
185
185
|
) {
|
|
186
186
|
await new Stream(Object.entries(ioMap))
|
|
187
187
|
.map(async ([inPath, outPath]) => {
|
|
188
|
-
SLogger.info(
|
|
188
|
+
SLogger.info(`SFfmpegTool.flac2oggMP 正在处理:${outPath}`);
|
|
189
189
|
await SFfmpegTool.flac2ogg(inPath, outPath, quality);
|
|
190
190
|
})
|
|
191
191
|
.append();
|
|
@@ -203,7 +203,7 @@ class SFfmpegTool {
|
|
|
203
203
|
) {
|
|
204
204
|
await new Stream(Object.entries(ioMap))
|
|
205
205
|
.map(async ([inPath, outPath]) => {
|
|
206
|
-
SLogger.info(
|
|
206
|
+
SLogger.info(`SFfmpegTool.trimSilenceMP 正在处理:${outPath}`);
|
|
207
207
|
await SFfmpegTool.trimSilence(inPath, outPath, threshold, silence);
|
|
208
208
|
})
|
|
209
209
|
.append();
|
|
@@ -217,7 +217,7 @@ class SFfmpegTool {
|
|
|
217
217
|
static async resampleMP(ioMap: IOMap, rate: number = 22050, cpCount: number = 16) {
|
|
218
218
|
await new Stream(Object.entries(ioMap))
|
|
219
219
|
.map(async ([inPath, outPath]) => {
|
|
220
|
-
SLogger.info(
|
|
220
|
+
SLogger.info(`SFfmpegTool.resampleMP 正在处理:${outPath}`);
|
|
221
221
|
await SFfmpegTool.resample(inPath, outPath, rate);
|
|
222
222
|
})
|
|
223
223
|
.append();
|
package/src/UtilFileTools.ts
CHANGED
|
@@ -228,19 +228,19 @@ export async function writeJSONFile(
|
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
/**搜索路径符合正则表达式的文件
|
|
231
|
-
* @param
|
|
231
|
+
* @param dir - 起始目录
|
|
232
232
|
* @param traitRegex - 正则表达式
|
|
233
233
|
* @param opt - 可选参数
|
|
234
234
|
* @param opt.relative - 搜索子目录
|
|
235
235
|
* @returns 文件名路径数组
|
|
236
236
|
*/
|
|
237
|
-
export function fileSearchRegex(
|
|
237
|
+
export function fileSearchRegex(dir: string, traitRegex: string, opt?:FileSearchRegexOpt) {
|
|
238
238
|
const relative = opt?.relative ?? true;
|
|
239
239
|
const outArray: string[] = [];
|
|
240
|
-
const subFiles = fs.readdirSync(
|
|
240
|
+
const subFiles = fs.readdirSync(dir,{withFileTypes:true});
|
|
241
241
|
const regex = new RegExp(traitRegex);
|
|
242
242
|
for (const subFile of subFiles) {
|
|
243
|
-
const subFilePath = path.join(
|
|
243
|
+
const subFilePath = path.join(dir, subFile.name);
|
|
244
244
|
//判断是否是文件夹,递归调用
|
|
245
245
|
if (subFile.isDirectory()) {
|
|
246
246
|
if(relative) outArray.push(...fileSearchRegex(path.join(subFilePath, path.sep), traitRegex));
|
|
@@ -251,16 +251,16 @@ export function fileSearchRegex(folder: string, traitRegex: string, opt?:FileSea
|
|
|
251
251
|
return outArray;
|
|
252
252
|
}
|
|
253
253
|
/**搜索符合Glob匹配的文件
|
|
254
|
-
* @param
|
|
254
|
+
* @param dir - 起始目录
|
|
255
255
|
* @param globPattern - glob匹配
|
|
256
256
|
* @param opt - 可选参数
|
|
257
257
|
* @param opt.ignore - 忽略的文件
|
|
258
258
|
* @returns 文件绝对路径数组
|
|
259
259
|
*/
|
|
260
|
-
export function fileSearchGlob(
|
|
260
|
+
export function fileSearchGlob(dir: string, globPattern:string|string[],opt?:FileSearchGlobOpt){
|
|
261
261
|
const fixedPath = typeof globPattern === "string"
|
|
262
|
-
? path.join(
|
|
263
|
-
: globPattern.map((p)=>path.join(
|
|
262
|
+
? path.join(dir,path.posix.normalize(globPattern))
|
|
263
|
+
: globPattern.map((p)=>path.join(dir,path.posix.normalize(p)));
|
|
264
264
|
return globSync(fixedPath,{ignore:opt?.ingore,absolute:true});
|
|
265
265
|
}
|
|
266
266
|
/**
|
package/src/UtilFunctions.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as crypto from "crypto";
|
|
2
|
-
import { AnyFunc, ComposedClass, ComposedMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, LiteralCheck, Matchable, MatchableFlag, Mixinable, Outcome, PromiseStat, PromiseVerifyFn, UnionToIntersection } from "@src/UtilInterfaces";
|
|
2
|
+
import { AnyFunc, ComposedClass, ComposedMixinable, ComposedRefMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, LiteralCheck, Matchable, MatchableFlag, Mixinable, Outcome, PromiseStat, PromiseVerifyFn, RefMixinable, UnionToIntersection } 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";
|
|
@@ -280,17 +280,21 @@ static composeClassPart
|
|
|
280
280
|
for(const fd of fields){
|
|
281
281
|
if(compObj[fd]!==undefined)
|
|
282
282
|
SLogger.warn(`field: ${fd as string} 已存在于基础类中, 混入可能导致类型问题, 如需覆盖, 请使用 ${key}=val`);
|
|
283
|
-
//
|
|
284
|
-
// get: ()=>compObj[key][fd],
|
|
285
|
-
// set: (value)=>{compObj[key][fd] = value},
|
|
286
|
-
// enumerable:true ,
|
|
287
|
-
// //writable: true ,
|
|
288
|
-
// configurable: true
|
|
289
|
-
//});
|
|
283
|
+
//func需绑定this无法直接设置属性
|
|
290
284
|
if(typeof mixin[fd] === 'function') {
|
|
291
285
|
compObj[fd] = (...args: any[]) => compObj[key][fd](...args);
|
|
286
|
+
//#region other
|
|
287
|
+
//const memo = (...args: any[]) => compObj[key][fd](...args);
|
|
288
|
+
//Object.defineProperty(compObj, fd, {
|
|
289
|
+
// get:()=>memo,
|
|
290
|
+
// set:()=>SLogger.warn(new Error(`试图修改一个由 composeClassPart 组合的函数字段:${String(fd)}, 修改已被忽略`)),
|
|
291
|
+
// enumerable:true ,
|
|
292
|
+
// //writable: true ,
|
|
293
|
+
// configurable: true
|
|
294
|
+
//});
|
|
292
295
|
//(compObj as any)[fd] = (...args: any[]) => (mixin[fd] as any).apply(mixin, args);
|
|
293
296
|
//(compObj as any)[fd] = (mixin[fd] as any).bind(mixin);
|
|
297
|
+
//#endregion
|
|
294
298
|
} else {
|
|
295
299
|
Object.defineProperty(compObj, fd, {
|
|
296
300
|
get: ()=>compObj[key][fd],
|
|
@@ -304,7 +308,9 @@ static composeClassPart
|
|
|
304
308
|
return compObj;
|
|
305
309
|
}
|
|
306
310
|
|
|
307
|
-
/**根据 MIXIN_FIELDS 自动混入
|
|
311
|
+
/**根据 MIXIN_FIELDS 自动混入
|
|
312
|
+
* @deprecated 非必要情况下, 对class定义请使用 composeRefMixinable
|
|
313
|
+
*/
|
|
308
314
|
static composeMixinable
|
|
309
315
|
<Base extends object, Mixins extends Mixinable<any>[]>
|
|
310
316
|
(base:Base,...mixins:Mixins):
|
|
@@ -325,6 +331,27 @@ static composeMixinable
|
|
|
325
331
|
return out as any;
|
|
326
332
|
}
|
|
327
333
|
|
|
334
|
+
/**根据 MIXIN_FIELDS 自动混入 */
|
|
335
|
+
static composeRefMixinable
|
|
336
|
+
<Base extends object, Mixins extends RefMixinable<any,unknown>[]>
|
|
337
|
+
(base:Base,...mixins:Mixins):
|
|
338
|
+
ComposedRefMixinable<Base,Mixins>{
|
|
339
|
+
let out = base;
|
|
340
|
+
const fieldsSet = new Set<string>();
|
|
341
|
+
for(const mixin of mixins){
|
|
342
|
+
const ctor = mixin.CTOR;
|
|
343
|
+
for(const field of ctor.MIXIN_FIELDS) {
|
|
344
|
+
const fixField = field as string;
|
|
345
|
+
if(fieldsSet.has(fixField))
|
|
346
|
+
SLogger.warn(`composeMixinable 出现了重复的 field: ${fixField} 可能会导致问题`);
|
|
347
|
+
else
|
|
348
|
+
fieldsSet.add(fixField);
|
|
349
|
+
}
|
|
350
|
+
out = UtilFunc.composeClassPart(base,mixin,ctor.MIXIN_KEY,...ctor.MIXIN_FIELDS);
|
|
351
|
+
}
|
|
352
|
+
return out as any;
|
|
353
|
+
}
|
|
354
|
+
|
|
328
355
|
|
|
329
356
|
/**对对象的每个属性应用映射函数,并返回一个新的对象。
|
|
330
357
|
* @template T - 对象的类型
|
package/src/UtilInterfaces.ts
CHANGED
|
@@ -141,8 +141,28 @@ export type Mixinable<Mixin> = {
|
|
|
141
141
|
*/
|
|
142
142
|
readonly MIXIN_FIELDS: readonly (keyof Mixin)[];
|
|
143
143
|
};
|
|
144
|
+
/**是原型构造器类型 */
|
|
145
|
+
export type IsCtor<T> = T extends {new():infer Ins}
|
|
146
|
+
? T : never;
|
|
147
|
+
/**可反射的
|
|
148
|
+
* @template Ctor - 构造器类型
|
|
149
|
+
* @template Constraint - 构造器约束
|
|
150
|
+
*/
|
|
151
|
+
export type ReflectionAble<Ctor,Constraint={}> = {
|
|
152
|
+
/**原型构造器 */
|
|
153
|
+
readonly CTOR:Ctor&Constraint
|
|
154
|
+
};
|
|
155
|
+
/**可反射的 且 构造函数是可混入的类
|
|
156
|
+
* @template Ctor - 构造器类型
|
|
157
|
+
* @template Instance - 实例类型
|
|
158
|
+
* @template Constraint - 构造器约束
|
|
159
|
+
*/
|
|
160
|
+
export type RefMixinable<Ctor,Instance,Constraint={}> =
|
|
161
|
+
ReflectionAble<Ctor,Mixinable<Instance>&Constraint>;
|
|
144
162
|
|
|
145
|
-
|
|
163
|
+
|
|
164
|
+
/**自动组合可混入的类
|
|
165
|
+
*/
|
|
146
166
|
export type ComposedMixinable<B, Ms extends unknown[]> =
|
|
147
167
|
Ms extends [infer M, ...infer Rest]
|
|
148
168
|
? M extends Mixinable<M>
|
|
@@ -150,6 +170,17 @@ export type ComposedMixinable<B, Ms extends unknown[]> =
|
|
|
150
170
|
: "一个混入类没有实现 Mixinable<self>" & Error
|
|
151
171
|
: B
|
|
152
172
|
|
|
173
|
+
/**自动组合 可反射的 且 构造函数是可混入的 类 */
|
|
174
|
+
export type ComposedRefMixinable<B, Ms extends unknown[]> =
|
|
175
|
+
Ms extends [infer M, ...infer Rest]
|
|
176
|
+
? M extends RefMixinable<unknown,M>
|
|
177
|
+
? ComposedRefMixinable<ComposedClass<B,M,
|
|
178
|
+
M['CTOR']['MIXIN_KEY'],
|
|
179
|
+
M['CTOR']['MIXIN_FIELDS'][number]>,
|
|
180
|
+
Rest>
|
|
181
|
+
: "一个混入类没有实现 RefMixinable<typeof self, self>" & Error
|
|
182
|
+
: B
|
|
183
|
+
|
|
153
184
|
/** extends封装
|
|
154
185
|
* @template B - 基础类型
|
|
155
186
|
* @template T - 判断的目标类型
|
|
@@ -166,8 +197,7 @@ export type ExtendThen<B,T,Y,N = never> = B extends T ? Y : N;
|
|
|
166
197
|
*/
|
|
167
198
|
type UnionInclude<B,T,Y,N = never> =
|
|
168
199
|
B extends Exclude<B,T>
|
|
169
|
-
? N
|
|
170
|
-
: Y
|
|
200
|
+
? N : Y
|
|
171
201
|
/**排除可选字段 */
|
|
172
202
|
export type RequiredOnly<T> = {
|
|
173
203
|
[K in keyof T as
|
|
@@ -214,3 +244,5 @@ export type ExtractOutcome<T,K extends Keyable> =
|
|
|
214
244
|
* 输出schema后替换为 ^.*$ 的 string 匹配
|
|
215
245
|
*/
|
|
216
246
|
export type SchemaString = `${string}SchemaString`;
|
|
247
|
+
|
|
248
|
+
|