@zwa73/utils 1.0.106 → 1.0.107
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/UtilFunctions.d.ts +6 -2
- package/dist/UtilFunctions.js +20 -1
- package/dist/UtilInterfaces.d.ts +20 -0
- 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/UtilFunctions.ts +25 -2
- package/src/UtilInterfaces.ts +32 -0
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/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, ComposedCtorMixinable, 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 请使用 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): ComposedCtorMixinable<Base, Mixins>;
|
|
87
91
|
/**对对象的每个属性应用映射函数,并返回一个新的对象。
|
|
88
92
|
* @template T - 对象的类型
|
|
89
93
|
* @param obj - 要处理的对象
|
package/dist/UtilFunctions.js
CHANGED
|
@@ -279,7 +279,9 @@ class UtilFunc {
|
|
|
279
279
|
}
|
|
280
280
|
return compObj;
|
|
281
281
|
}
|
|
282
|
-
/**根据 MIXIN_FIELDS 自动混入
|
|
282
|
+
/**根据 MIXIN_FIELDS 自动混入
|
|
283
|
+
* @deprecated 请使用 composeRefMixinable
|
|
284
|
+
*/
|
|
283
285
|
static composeMixinable(base, ...mixins) {
|
|
284
286
|
let out = base;
|
|
285
287
|
const fieldsSet = new Set();
|
|
@@ -296,6 +298,23 @@ class UtilFunc {
|
|
|
296
298
|
}
|
|
297
299
|
return out;
|
|
298
300
|
}
|
|
301
|
+
/**根据 MIXIN_FIELDS 自动混入 */
|
|
302
|
+
static composeRefMixinable(base, ...mixins) {
|
|
303
|
+
let out = base;
|
|
304
|
+
const fieldsSet = new Set();
|
|
305
|
+
for (const mixin of mixins) {
|
|
306
|
+
const ctor = mixin.CTOR;
|
|
307
|
+
for (const field of ctor.MIXIN_FIELDS) {
|
|
308
|
+
const fixField = field;
|
|
309
|
+
if (fieldsSet.has(fixField))
|
|
310
|
+
UtilLogger_1.SLogger.warn(`composeMixinable 出现了重复的 field: ${fixField} 可能会导致问题`);
|
|
311
|
+
else
|
|
312
|
+
fieldsSet.add(fixField);
|
|
313
|
+
}
|
|
314
|
+
out = UtilFunc.composeClassPart(base, mixin, ctor.MIXIN_KEY, ...ctor.MIXIN_FIELDS);
|
|
315
|
+
}
|
|
316
|
+
return out;
|
|
317
|
+
}
|
|
299
318
|
/**对对象的每个属性应用映射函数,并返回一个新的对象。
|
|
300
319
|
* @template T - 对象的类型
|
|
301
320
|
* @param obj - 要处理的对象
|
package/dist/UtilInterfaces.d.ts
CHANGED
|
@@ -105,8 +105,28 @@ export type Mixinable<Mixin> = {
|
|
|
105
105
|
*/
|
|
106
106
|
readonly MIXIN_FIELDS: readonly (keyof Mixin)[];
|
|
107
107
|
};
|
|
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>;
|
|
108
126
|
/**自动组合可混入的类 */
|
|
109
127
|
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;
|
|
128
|
+
/**自动组合构造类型是可混入的类 */
|
|
129
|
+
export type ComposedCtorMixinable<B, Ms extends unknown[]> = Ms extends [infer M, ...infer Rest] ? M extends RefMixinable<unknown, M> ? ComposedCtorMixinable<ComposedClass<B, M, M['CTOR']['MIXIN_KEY'], M['CTOR']['MIXIN_FIELDS'][number]>, Rest> : "一个混入类没有实现 RefMixinable<typeof self, self>" & Error : B;
|
|
110
130
|
/** extends封装
|
|
111
131
|
* @template B - 基础类型
|
|
112
132
|
* @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/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, ComposedCtorMixinable, 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";
|
|
@@ -304,7 +304,9 @@ static composeClassPart
|
|
|
304
304
|
return compObj;
|
|
305
305
|
}
|
|
306
306
|
|
|
307
|
-
/**根据 MIXIN_FIELDS 自动混入
|
|
307
|
+
/**根据 MIXIN_FIELDS 自动混入
|
|
308
|
+
* @deprecated 请使用 composeRefMixinable
|
|
309
|
+
*/
|
|
308
310
|
static composeMixinable
|
|
309
311
|
<Base extends object, Mixins extends Mixinable<any>[]>
|
|
310
312
|
(base:Base,...mixins:Mixins):
|
|
@@ -325,6 +327,27 @@ static composeMixinable
|
|
|
325
327
|
return out as any;
|
|
326
328
|
}
|
|
327
329
|
|
|
330
|
+
/**根据 MIXIN_FIELDS 自动混入 */
|
|
331
|
+
static composeRefMixinable
|
|
332
|
+
<Base extends object, Mixins extends RefMixinable<any,unknown>[]>
|
|
333
|
+
(base:Base,...mixins:Mixins):
|
|
334
|
+
ComposedCtorMixinable<Base,Mixins>{
|
|
335
|
+
let out = base;
|
|
336
|
+
const fieldsSet = new Set<string>();
|
|
337
|
+
for(const mixin of mixins){
|
|
338
|
+
const ctor = mixin.CTOR;
|
|
339
|
+
for(const field of ctor.MIXIN_FIELDS) {
|
|
340
|
+
const fixField = field as string;
|
|
341
|
+
if(fieldsSet.has(fixField))
|
|
342
|
+
SLogger.warn(`composeMixinable 出现了重复的 field: ${fixField} 可能会导致问题`);
|
|
343
|
+
else
|
|
344
|
+
fieldsSet.add(fixField);
|
|
345
|
+
}
|
|
346
|
+
out = UtilFunc.composeClassPart(base,mixin,ctor.MIXIN_KEY,...ctor.MIXIN_FIELDS);
|
|
347
|
+
}
|
|
348
|
+
return out as any;
|
|
349
|
+
}
|
|
350
|
+
|
|
328
351
|
|
|
329
352
|
/**对对象的每个属性应用映射函数,并返回一个新的对象。
|
|
330
353
|
* @template T - 对象的类型
|
package/src/UtilInterfaces.ts
CHANGED
|
@@ -141,6 +141,25 @@ 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>;
|
|
162
|
+
|
|
144
163
|
|
|
145
164
|
/**自动组合可混入的类 */
|
|
146
165
|
export type ComposedMixinable<B, Ms extends unknown[]> =
|
|
@@ -150,6 +169,17 @@ export type ComposedMixinable<B, Ms extends unknown[]> =
|
|
|
150
169
|
: "一个混入类没有实现 Mixinable<self>" & Error
|
|
151
170
|
: B
|
|
152
171
|
|
|
172
|
+
/**自动组合构造类型是可混入的类 */
|
|
173
|
+
export type ComposedCtorMixinable<B, Ms extends unknown[]> =
|
|
174
|
+
Ms extends [infer M, ...infer Rest]
|
|
175
|
+
? M extends RefMixinable<unknown,M>
|
|
176
|
+
? ComposedCtorMixinable<ComposedClass<B,M,
|
|
177
|
+
M['CTOR']['MIXIN_KEY'],
|
|
178
|
+
M['CTOR']['MIXIN_FIELDS'][number]>,
|
|
179
|
+
Rest>
|
|
180
|
+
: "一个混入类没有实现 RefMixinable<typeof self, self>" & Error
|
|
181
|
+
: B
|
|
182
|
+
|
|
153
183
|
/** extends封装
|
|
154
184
|
* @template B - 基础类型
|
|
155
185
|
* @template T - 判断的目标类型
|
|
@@ -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
|
+
|