@zwa73/utils 1.0.134 → 1.0.135
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/UtilCom.d.ts +22 -5
- package/dist/UtilCom.js +1 -1
- package/dist/UtilFP.d.ts +4 -4
- package/dist/UtilFileTools.d.ts +19 -5
- package/dist/UtilFileTools.js +14 -13
- package/dist/UtilFunctions.d.ts +18 -9
- package/dist/UtilFunctions.js +22 -5
- package/dist/UtilInterfaces.d.ts +19 -2
- package/package.json +1 -1
- package/src/UtilCom.ts +25 -9
- package/src/UtilFP.ts +5 -5
- package/src/UtilFileTools.ts +35 -19
- package/src/UtilFunctions.ts +39 -12
- package/src/UtilInterfaces.ts +22 -3
package/dist/UtilCom.d.ts
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
|
-
import { JObject, ReqVerifyFn } from "./UtilInterfaces";
|
|
1
|
+
import { AnyString, JObject, ReqVerifyFn } from "./UtilInterfaces";
|
|
2
2
|
import { RepeatPromiseOpt } from "./UtilFunctions";
|
|
3
|
+
export type ComPostOption = {
|
|
4
|
+
/**请求域名 */
|
|
5
|
+
hostname: string;
|
|
6
|
+
/**请求路径 */
|
|
7
|
+
path: string;
|
|
8
|
+
/**方式 post为 POST */
|
|
9
|
+
method: 'POST';
|
|
10
|
+
/**端口 */
|
|
11
|
+
port?: number;
|
|
12
|
+
/**请求头 */
|
|
13
|
+
headers?: {
|
|
14
|
+
/**内容类型 */
|
|
15
|
+
'Content-Type'?: 'application/json' | AnyString;
|
|
16
|
+
/**内容长度 一般无需填写 应为buffer长度而非字符串长度 */
|
|
17
|
+
'Content-Length'?: number;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
3
20
|
type RepeatPostOpt = Partial<{
|
|
4
21
|
/**httppost 超时中断时间限制 */
|
|
5
22
|
postTimeLimit?: number;
|
|
@@ -13,7 +30,7 @@ export declare namespace UtilCom {
|
|
|
13
30
|
* @param timeLimit - 超时时间/秒 最小为10秒
|
|
14
31
|
* @returns 结果 null 为未能成功接收
|
|
15
32
|
*/
|
|
16
|
-
function shttpsPost(json: JObject, options:
|
|
33
|
+
function shttpsPost(json: JObject, options: ComPostOption, timeLimit?: number): Promise<JObject | null>;
|
|
17
34
|
/**发送一个 http POST请求并接受数据
|
|
18
35
|
* @async
|
|
19
36
|
* @param json - 数据对象
|
|
@@ -21,7 +38,7 @@ export declare namespace UtilCom {
|
|
|
21
38
|
* @param timeLimit - 超时时间/秒 最小为10秒
|
|
22
39
|
* @returns 结果 null 为未能成功接收
|
|
23
40
|
*/
|
|
24
|
-
function shttpPost(json: JObject, options:
|
|
41
|
+
function shttpPost(json: JObject, options: ComPostOption, timeLimit?: number): Promise<JObject | null>;
|
|
25
42
|
/**重复一个 https POST请求并接受数据
|
|
26
43
|
* @async
|
|
27
44
|
* @param json - 数据对象
|
|
@@ -34,7 +51,7 @@ export declare namespace UtilCom {
|
|
|
34
51
|
* @param opt.try_delay - 重试间隔 秒 默认0
|
|
35
52
|
* @returns 结果 null 为未能成功接收
|
|
36
53
|
*/
|
|
37
|
-
function shttpsRepeatPost(json: JObject, options:
|
|
54
|
+
function shttpsRepeatPost(json: JObject, options: ComPostOption, verifyFn?: ReqVerifyFn<JObject | null>, opt?: RepeatPostOpt): Promise<JObject | null>;
|
|
38
55
|
/**重复一个 http POST请求并接受数据
|
|
39
56
|
* Object ()
|
|
40
57
|
* @async
|
|
@@ -48,6 +65,6 @@ export declare namespace UtilCom {
|
|
|
48
65
|
* @param opt.try_delay - 重试间隔 秒 默认0
|
|
49
66
|
* @returns 结果 null 为未能成功接收
|
|
50
67
|
*/
|
|
51
|
-
function shttpRepeatPost(json: JObject, options:
|
|
68
|
+
function shttpRepeatPost(json: JObject, options: ComPostOption, verifyFn?: ReqVerifyFn<JObject | null>, opt?: RepeatPostOpt): Promise<JObject | null>;
|
|
52
69
|
}
|
|
53
70
|
export {};
|
package/dist/UtilCom.js
CHANGED
package/dist/UtilFP.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Keyable, Literal, Matchable, MatchableFlag, ProperSubsetCheck } from "./UtilInterfaces";
|
|
1
|
+
import { AnyRecord, Keyable, Literal, Matchable, MatchableFlag, ProperSubsetCheck } from "./UtilInterfaces";
|
|
2
2
|
import { FailedLike } from "./UtilSymbol";
|
|
3
3
|
/**常用函数式编程库 */
|
|
4
4
|
export declare namespace UtilFP {
|
|
@@ -76,7 +76,7 @@ export declare namespace UtilFP {
|
|
|
76
76
|
* 然后返回一个新的对象新的对象包含了基础对象的所有属性,
|
|
77
77
|
* 以及一个新的属性, 这个新的属性的键是`key`, 值是`value`
|
|
78
78
|
*/
|
|
79
|
-
export function bind<K extends Keyable, V>(key: Literal<K>, value: V): <B extends
|
|
79
|
+
export function bind<K extends Keyable, V>(key: Literal<K>, value: V): <B extends AnyRecord>(base?: B) => keyof B extends K ? "Base中已有对应键" & Error : {
|
|
80
80
|
[P in K | keyof B]: P extends K ? V : P extends keyof B ? B[P] : never;
|
|
81
81
|
};
|
|
82
82
|
/**绑定一个键到一个基础对象上,
|
|
@@ -88,7 +88,7 @@ export declare namespace UtilFP {
|
|
|
88
88
|
* 然后返回一个新的对象新的对象包含了基础对象的所有属性,
|
|
89
89
|
* 以及一个新的属性, 这个新的属性的键是`key`, 值是基础对象
|
|
90
90
|
*/
|
|
91
|
-
export function bind<K extends Keyable>(key: Literal<K>): <B extends
|
|
91
|
+
export function bind<K extends Keyable>(key: Literal<K>): <B extends AnyRecord>(base?: B) => {
|
|
92
92
|
[P in K]: B;
|
|
93
93
|
};
|
|
94
94
|
/**绑定一个键和一个值到一个基础对象上, 并返回一个新的对象
|
|
@@ -102,7 +102,7 @@ export declare namespace UtilFP {
|
|
|
102
102
|
* @param base - 基础对象
|
|
103
103
|
* @returns 完成绑定的基础对象
|
|
104
104
|
*/
|
|
105
|
-
export function bind<K extends Keyable, V, B extends
|
|
105
|
+
export function bind<K extends Keyable, V, B extends AnyRecord>(key: Literal<K>, value: V, base: B): keyof B extends K ? "Base中已有对应键" & Error : {
|
|
106
106
|
[P in K | keyof B]: P extends K ? V : P extends keyof B ? B[P] : never;
|
|
107
107
|
};
|
|
108
108
|
/**创建一个对对象的每个属性进行映射的函数
|
package/dist/UtilFileTools.d.ts
CHANGED
|
@@ -29,6 +29,15 @@ type LoadJsonFileOpt<T> = Partial<{
|
|
|
29
29
|
default: T;
|
|
30
30
|
/**以json5模式加载 略慢 默认false */
|
|
31
31
|
json5: boolean;
|
|
32
|
+
/**不自动修改扩展名为json */
|
|
33
|
+
forceExt: boolean;
|
|
34
|
+
}>;
|
|
35
|
+
/**json文件写入选项 */
|
|
36
|
+
type WriteJsonFileOpt = Partial<{
|
|
37
|
+
/**使用紧凑风格 */
|
|
38
|
+
compress: boolean;
|
|
39
|
+
/**不自动修改扩展名为json */
|
|
40
|
+
forceExt: boolean;
|
|
32
41
|
}>;
|
|
33
42
|
/**文件工具 */
|
|
34
43
|
export declare namespace UtilFT {
|
|
@@ -81,8 +90,9 @@ export declare namespace UtilFT {
|
|
|
81
90
|
/**加载json文件 同步
|
|
82
91
|
* @param filePath - 文件路径
|
|
83
92
|
* @param opt - 可选参数
|
|
84
|
-
* @param opt.default
|
|
85
|
-
* @param opt.json5
|
|
93
|
+
* @param opt.default - 默认值
|
|
94
|
+
* @param opt.json5 - json5模式
|
|
95
|
+
* @param opt.forceExt - 不自动修改扩展名为json
|
|
86
96
|
* @returns 加载完成的对象或默认值
|
|
87
97
|
*/
|
|
88
98
|
function loadJSONFileSync<T extends JToken>(filePath: string, opt: LoadJsonFileOpt<T>): T;
|
|
@@ -96,8 +106,9 @@ export declare namespace UtilFT {
|
|
|
96
106
|
* @async
|
|
97
107
|
* @param filePath - 文件路径
|
|
98
108
|
* @param opt - 可选参数
|
|
99
|
-
* @param opt.default
|
|
100
|
-
* @param opt.json5
|
|
109
|
+
* @param opt.default - 默认值
|
|
110
|
+
* @param opt.json5 - json5模式
|
|
111
|
+
* @param opt.forceExt - 不自动修改扩展名为json
|
|
101
112
|
* @returns 加载完成的对象或默认值
|
|
102
113
|
*/
|
|
103
114
|
function loadJSONFile<T extends JToken>(filePath: string, opt: LoadJsonFileOpt<T>): Promise<T>;
|
|
@@ -106,8 +117,11 @@ export declare namespace UtilFT {
|
|
|
106
117
|
* @async
|
|
107
118
|
* @param filePath - 文件路径
|
|
108
119
|
* @param token - 所要写入的JToken
|
|
120
|
+
* @param opt - 可选参数
|
|
121
|
+
* @param opt.compress - 使用紧凑风格
|
|
122
|
+
* @param opt.forceExt - 不自动修改扩展名为json
|
|
109
123
|
*/
|
|
110
|
-
function writeJSONFile(filePath: string, token: JToken): Promise<void>;
|
|
124
|
+
function writeJSONFile(filePath: string, token: JToken, opt?: WriteJsonFileOpt): Promise<void>;
|
|
111
125
|
/**保证路径为某个风格
|
|
112
126
|
* @param filePath - 输入路径
|
|
113
127
|
* @param style - 目标风格 undefined 时不改变
|
package/dist/UtilFileTools.js
CHANGED
|
@@ -142,12 +142,11 @@ var UtilFT;
|
|
|
142
142
|
}
|
|
143
143
|
UtilFT.ensurePathExistsSync = ensurePathExistsSync;
|
|
144
144
|
function loadJSONFileSync(filePath, opt) {
|
|
145
|
-
if (pathe_1.default.extname(filePath) !== '.json')
|
|
145
|
+
if (opt?.forceExt !== true && pathe_1.default.extname(filePath) !== '.json')
|
|
146
146
|
filePath += '.json';
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
str = fs.readFileSync(filePath, "utf-8");
|
|
147
|
+
const str = pathExistsSync(filePath)
|
|
148
|
+
? fs.readFileSync(filePath, "utf-8")
|
|
149
|
+
: "";
|
|
151
150
|
// 如果不存在则返回默认值
|
|
152
151
|
if (str == "" || str == null) {
|
|
153
152
|
if (opt?.default !== undefined)
|
|
@@ -160,12 +159,11 @@ var UtilFT;
|
|
|
160
159
|
}
|
|
161
160
|
UtilFT.loadJSONFileSync = loadJSONFileSync;
|
|
162
161
|
async function loadJSONFile(filePath, opt) {
|
|
163
|
-
if (pathe_1.default.extname(filePath) !== '.json')
|
|
162
|
+
if (opt?.forceExt !== true && pathe_1.default.extname(filePath) !== '.json')
|
|
164
163
|
filePath += '.json';
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
str = await fs.promises.readFile(filePath, "utf-8");
|
|
164
|
+
const str = (await pathExists(filePath))
|
|
165
|
+
? await fs.promises.readFile(filePath, "utf-8")
|
|
166
|
+
: "";
|
|
169
167
|
// 如果不存在则返回默认值
|
|
170
168
|
if (str == "" || str == null) {
|
|
171
169
|
if (opt?.default !== undefined)
|
|
@@ -182,10 +180,13 @@ var UtilFT;
|
|
|
182
180
|
* @async
|
|
183
181
|
* @param filePath - 文件路径
|
|
184
182
|
* @param token - 所要写入的JToken
|
|
183
|
+
* @param opt - 可选参数
|
|
184
|
+
* @param opt.compress - 使用紧凑风格
|
|
185
|
+
* @param opt.forceExt - 不自动修改扩展名为json
|
|
185
186
|
*/
|
|
186
|
-
async function writeJSONFile(filePath, token) {
|
|
187
|
-
const str = UtilFunctions_1.UtilFunc.stringifyJToken(token);
|
|
188
|
-
if (pathe_1.default.extname(filePath) !== '.json')
|
|
187
|
+
async function writeJSONFile(filePath, token, opt) {
|
|
188
|
+
const str = UtilFunctions_1.UtilFunc.stringifyJToken(token, opt);
|
|
189
|
+
if (opt?.forceExt !== true && pathe_1.default.extname(filePath) !== '.json')
|
|
189
190
|
filePath += '.json';
|
|
190
191
|
// 判断文件路径是否存在 不存在则创建
|
|
191
192
|
if (!(await pathExists(filePath)))
|
package/dist/UtilFunctions.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AnyFunc, ComposedClass, ComposedMixinable, ComposedRefMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, Literal, Matchable, MatchableFlag, Mixinable, Outcome, ReqVerifyFn, ProperSubsetCheck, RefMixinable, UnionToIntersection, Await } from "./UtilInterfaces";
|
|
1
|
+
import { AnyFunc, ComposedClass, ComposedMixinable, ComposedRefMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, Literal, Matchable, MatchableFlag, Mixinable, Outcome, ReqVerifyFn, ProperSubsetCheck, RefMixinable, UnionToIntersection, Await, AnyRecord } from "./UtilInterfaces";
|
|
2
2
|
import { LogLevel } from "./UtilLogger";
|
|
3
3
|
import { Failed, FailedLike, None, StatusSymbol, Success, SuccessLike, Timeout } from "./UtilSymbol";
|
|
4
4
|
declare const HashMethodList: readonly ["md5", "sha1", "sha256", "sha512", "sha3", "blake2", "blake3"];
|
|
@@ -8,6 +8,13 @@ type ExecOpt = Partial<{
|
|
|
8
8
|
outlvl: LogLevel;
|
|
9
9
|
errlvl: LogLevel;
|
|
10
10
|
}>;
|
|
11
|
+
/**序列化选项 */
|
|
12
|
+
type StringifyOpt = Partial<{
|
|
13
|
+
/**使用紧凑风格 */
|
|
14
|
+
compress: boolean;
|
|
15
|
+
/**插入的空格 数字为空格数量 默认为制表符\t */
|
|
16
|
+
space: string | number | null | undefined;
|
|
17
|
+
}>;
|
|
11
18
|
/**Promise重试选项 */
|
|
12
19
|
export type RepeatPromiseOpt = Partial<{
|
|
13
20
|
/**重试次数 默认3*/
|
|
@@ -34,7 +41,7 @@ export declare class UtilFunc {
|
|
|
34
41
|
* @param defaultVal - 默认值
|
|
35
42
|
* @returns 最终值
|
|
36
43
|
*/
|
|
37
|
-
static initField<T extends
|
|
44
|
+
static initField<T extends AnyRecord, K extends keyof T>(obj: T, field: K, defaultVal: T[K]): T[K];
|
|
38
45
|
/**初始化一个数据对象
|
|
39
46
|
* @param obj - 目标对象
|
|
40
47
|
* @param checkObj - 用于检测的对象 在对应key缺失时赋予对应值 如果值为函数, 则赋予执行结果 如果结果为 undefined 则不赋值
|
|
@@ -107,26 +114,28 @@ export declare class UtilFunc {
|
|
|
107
114
|
* @param fields - 需要混入的字段
|
|
108
115
|
* @returns 混合完成的类
|
|
109
116
|
*/
|
|
110
|
-
static composeClassPart<Base extends
|
|
117
|
+
static composeClassPart<Base extends AnyRecord, Mixin extends AnyRecord, Field extends keyof Mixin>(base: Base, mixin: Mixin, key: string, ...fields: Field[]): ComposedClass<Base, Mixin, typeof key, Field>;
|
|
111
118
|
/**根据 MIXIN_FIELDS 自动混入
|
|
112
119
|
* @deprecated 非必要情况下, 对class定义请使用 composeRefMixinable
|
|
113
120
|
*/
|
|
114
|
-
static composeMixinable<Base extends
|
|
121
|
+
static composeMixinable<Base extends AnyRecord, Mixins extends Mixinable<any>[]>(base: Base, ...mixins: Mixins): ComposedMixinable<Base, Mixins>;
|
|
115
122
|
/**根据 MIXIN_FIELDS 自动混入 */
|
|
116
|
-
static composeRefMixinable<Base extends
|
|
123
|
+
static composeRefMixinable<Base extends AnyRecord, Mixins extends RefMixinable<any, unknown>[]>(base: Base, ...mixins: Mixins): ComposedRefMixinable<Base, Mixins>;
|
|
117
124
|
/**对对象的每个属性应用映射函数,并返回一个新的对象。
|
|
118
125
|
* @template T - 对象的类型
|
|
119
126
|
* @param obj - 要处理的对象
|
|
120
127
|
* @param mapper - 映射函数,接受一个值和一个键,返回一个新的值
|
|
121
128
|
* @returns - 一个新的对象,它的属性是原对象的属性经过映射函数处理后的结果
|
|
122
129
|
*/
|
|
123
|
-
static mapEntries<T extends
|
|
130
|
+
static mapEntries<T extends AnyRecord>(obj: T, mapper: (key: keyof T, value: T[keyof T]) => T[keyof T]): T;
|
|
124
131
|
/**将JToken转换为字符串
|
|
125
132
|
* @param token - 待转换的Token
|
|
126
|
-
* @param
|
|
133
|
+
* @param opt - 可选参数
|
|
134
|
+
* @param opt.space - 插入的空格 数字为空格数量 默认为制表符\t
|
|
135
|
+
* @param opt.compress - 使用紧凑风格
|
|
127
136
|
* @returns 转换完成的字符串
|
|
128
137
|
*/
|
|
129
|
-
static stringifyJToken(token: JToken | IJData,
|
|
138
|
+
static stringifyJToken(token: JToken | IJData, opt?: StringifyOpt): string;
|
|
130
139
|
/**代办表 用于队列处理等待 */
|
|
131
140
|
static pendingMap: Record<Keyable, AnyFunc[]>;
|
|
132
141
|
/**队列处理
|
|
@@ -202,7 +211,7 @@ export declare class UtilFunc {
|
|
|
202
211
|
*/
|
|
203
212
|
static isSafeNumber(num: unknown): boolean;
|
|
204
213
|
/**将一个字段加入一个对象中,将改变对象,返回新类型 */
|
|
205
|
-
static bindTo<K extends Keyable, V, B extends
|
|
214
|
+
static bindTo<K extends Keyable, V, B extends AnyRecord = {}>(key: Literal<K>, value: V, base?: B): keyof B extends K ? "Base中已有对应键" & Error : {
|
|
206
215
|
[P in K | keyof B]: P extends K ? V : P extends keyof B ? B[P] : never;
|
|
207
216
|
};
|
|
208
217
|
/**移除多行字符串中每行开始的最小空格数。
|
package/dist/UtilFunctions.js
CHANGED
|
@@ -377,13 +377,30 @@ class UtilFunc {
|
|
|
377
377
|
}
|
|
378
378
|
/**将JToken转换为字符串
|
|
379
379
|
* @param token - 待转换的Token
|
|
380
|
-
* @param
|
|
380
|
+
* @param opt - 可选参数
|
|
381
|
+
* @param opt.space - 插入的空格 数字为空格数量 默认为制表符\t
|
|
382
|
+
* @param opt.compress - 使用紧凑风格
|
|
381
383
|
* @returns 转换完成的字符串
|
|
382
384
|
*/
|
|
383
|
-
static stringifyJToken(token,
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
385
|
+
static stringifyJToken(token, opt) {
|
|
386
|
+
opt ??= {};
|
|
387
|
+
let { compress, space } = opt;
|
|
388
|
+
space ??= "\t";
|
|
389
|
+
space = space === null ? undefined : space;
|
|
390
|
+
if (!compress)
|
|
391
|
+
return JSON.stringify(token, null, space);
|
|
392
|
+
const compressReplacer = (key, value) => {
|
|
393
|
+
if (Array.isArray(value) && value.every(item => typeof item === 'number' || typeof item === 'string' ||
|
|
394
|
+
typeof item === 'boolean' || item == null))
|
|
395
|
+
return `@@@${JSON.stringify(value)}@@@`;
|
|
396
|
+
const str = JSON.stringify(value);
|
|
397
|
+
if (str.length <= 100)
|
|
398
|
+
return `@@@${str}@@@`;
|
|
399
|
+
return value;
|
|
400
|
+
};
|
|
401
|
+
return JSON.stringify(token, compressReplacer, space)
|
|
402
|
+
.replace(/"@@@(.*?)@@@"/g, `$1`)
|
|
403
|
+
.replace(/\\([\\"])/g, '$1');
|
|
387
404
|
}
|
|
388
405
|
/**代办表 用于队列处理等待 */
|
|
389
406
|
static pendingMap = {};
|
package/dist/UtilInterfaces.d.ts
CHANGED
|
@@ -49,7 +49,7 @@ export type Literal<L> = ProperSubset<string, L> | ProperSubset<number, L> | Pro
|
|
|
49
49
|
*/
|
|
50
50
|
export type LiteralCheck<L> = ProperSubsetCheck<string, L> extends "P" ? true : ProperSubsetCheck<number, L> extends "P" ? true : ProperSubsetCheck<boolean, L> extends "P" ? true : ProperSubsetCheck<symbol, L> extends "P" ? true : ProperSubsetCheck<any[], L> extends "P" ? true : ProperSubsetCheck<Record<any, any>, L> extends "P" ? true : L extends null | undefined ? true : false;
|
|
51
51
|
/**返回将Mixin分配给Base的结果,相同字段时Mixin覆盖Base */
|
|
52
|
-
export type AssignObject<Base extends
|
|
52
|
+
export type AssignObject<Base extends AnyRecord, Mixin extends AnyRecord> = {
|
|
53
53
|
[P in keyof Mixin | keyof Base]: P extends keyof Mixin ? Mixin[P] : P extends keyof Base ? Base[P] : never;
|
|
54
54
|
};
|
|
55
55
|
/**转为可写的 */
|
|
@@ -138,8 +138,17 @@ export type ReflectionAble<Ctor, Constraint = {}> = {
|
|
|
138
138
|
};
|
|
139
139
|
/**可反射的 且 构造函数是可混入的类
|
|
140
140
|
* @template Ctor - 构造器类型
|
|
141
|
-
* @template Instance - 实例类型
|
|
141
|
+
* @template Instance - 实例类型 如果采用了内部混入, 那么填入对外实际暴露的类型, 以支持混入多层字段
|
|
142
142
|
* @template Constraint - 构造器约束
|
|
143
|
+
* @example
|
|
144
|
+
* export class MixinModule implements RefMixinable<typeof MixinModule,MixinModule>{
|
|
145
|
+
* static readonly MIXIN_FIELDS = [
|
|
146
|
+
* 'func_a',
|
|
147
|
+
* 'field_b'
|
|
148
|
+
* ] as const;
|
|
149
|
+
* static readonly MIXIN_KEY = '__mixinModule';
|
|
150
|
+
* CTOR = MixinModule;
|
|
151
|
+
* }
|
|
143
152
|
*/
|
|
144
153
|
export type RefMixinable<Ctor, Instance, Constraint = {}> = ReflectionAble<Ctor, Mixinable<Instance> & Constraint>;
|
|
145
154
|
/**自动组合可混入的类
|
|
@@ -194,4 +203,12 @@ export type NeedInit = {
|
|
|
194
203
|
};
|
|
195
204
|
/**可选的record */
|
|
196
205
|
export type PRecord<K extends Keyable, V> = Partial<Record<K, V>>;
|
|
206
|
+
/**任何Record */
|
|
207
|
+
export type AnyRecord = Record<Keyable, any>;
|
|
208
|
+
/**注释元组
|
|
209
|
+
* @template T - 提供注释的类型, 索引需从0开始
|
|
210
|
+
*/
|
|
211
|
+
export type AnnotableTuple<T extends {
|
|
212
|
+
[K: number]: unknown;
|
|
213
|
+
}, Tuple extends unknown[] = []> = unknown extends T[Tuple['length']] ? T & Tuple : AnnotableTuple<T, [...Tuple, T[Tuple['length']]]>;
|
|
197
214
|
export {};
|
package/package.json
CHANGED
package/src/UtilCom.ts
CHANGED
|
@@ -1,10 +1,26 @@
|
|
|
1
|
-
import { JObject, ReqVerifyFn } from "@src/UtilInterfaces";
|
|
1
|
+
import { AnyString, JObject, ReqVerifyFn } from "@src/UtilInterfaces";
|
|
2
2
|
import * as https from 'https';
|
|
3
3
|
import * as http from 'http';
|
|
4
4
|
import { SLogger } from "@src/UtilLogger";
|
|
5
5
|
import { RepeatPromiseOpt, UtilFunc } from "@src/UtilFunctions";
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
export type ComPostOption = {
|
|
8
|
+
/**请求域名 */
|
|
9
|
+
hostname: string;
|
|
10
|
+
/**请求路径 */
|
|
11
|
+
path: string;
|
|
12
|
+
/**方式 post为 POST */
|
|
13
|
+
method: 'POST';
|
|
14
|
+
/**端口 */
|
|
15
|
+
port?:number;
|
|
16
|
+
/**请求头 */
|
|
17
|
+
headers?: {
|
|
18
|
+
/**内容类型 */
|
|
19
|
+
'Content-Type'?: 'application/json'|AnyString;
|
|
20
|
+
/**内容长度 一般无需填写 应为buffer长度而非字符串长度 */
|
|
21
|
+
'Content-Length'?: number;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
8
24
|
|
|
9
25
|
type RepeatPostOpt = Partial<{
|
|
10
26
|
/**httppost 超时中断时间限制 */
|
|
@@ -21,7 +37,7 @@ export namespace UtilCom{
|
|
|
21
37
|
* @param timeLimit - 超时时间/秒 最小为10秒
|
|
22
38
|
* @returns 结果 null 为未能成功接收
|
|
23
39
|
*/
|
|
24
|
-
function sPost(posttype:"http"|"https",json:JObject,options:
|
|
40
|
+
function sPost(posttype:"http"|"https",json:JObject,options:ComPostOption,timeLimit?:number):Promise<JObject|null>{
|
|
25
41
|
//转换为毫秒
|
|
26
42
|
const hasTimeLimit = (timeLimit ? timeLimit>=10 : false );
|
|
27
43
|
if(hasTimeLimit && timeLimit!=undefined) timeLimit*=1000;
|
|
@@ -60,7 +76,7 @@ function sPost(posttype:"http"|"https",json:JObject,options:Object,timeLimit?:nu
|
|
|
60
76
|
return;
|
|
61
77
|
}
|
|
62
78
|
try{
|
|
63
|
-
|
|
79
|
+
const obj = JSON.parse(resdata);
|
|
64
80
|
SLogger.http(funcName+" 接受信息:",UtilFunc.stringifyJToken(obj));
|
|
65
81
|
resolve(obj);
|
|
66
82
|
return;
|
|
@@ -109,7 +125,7 @@ function sPost(posttype:"http"|"https",json:JObject,options:Object,timeLimit?:nu
|
|
|
109
125
|
* @param timeLimit - 超时时间/秒 最小为10秒
|
|
110
126
|
* @returns 结果 null 为未能成功接收
|
|
111
127
|
*/
|
|
112
|
-
export function shttpsPost(json:JObject,options:
|
|
128
|
+
export function shttpsPost(json:JObject,options:ComPostOption,timeLimit?:number):Promise<JObject|null>{
|
|
113
129
|
return sPost("https",json,options,timeLimit);
|
|
114
130
|
}
|
|
115
131
|
|
|
@@ -120,7 +136,7 @@ export function shttpsPost(json:JObject,options:Object,timeLimit?:number):Promis
|
|
|
120
136
|
* @param timeLimit - 超时时间/秒 最小为10秒
|
|
121
137
|
* @returns 结果 null 为未能成功接收
|
|
122
138
|
*/
|
|
123
|
-
export function shttpPost(json:JObject,options:
|
|
139
|
+
export function shttpPost(json:JObject,options:ComPostOption,timeLimit?:number):Promise<JObject|null>{
|
|
124
140
|
return sPost("http",json,options,timeLimit);
|
|
125
141
|
}
|
|
126
142
|
|
|
@@ -139,7 +155,7 @@ export function shttpPost(json:JObject,options:Object,timeLimit?:number):Promise
|
|
|
139
155
|
* @param opt.try_delay - 重试间隔 秒 默认0
|
|
140
156
|
* @returns 结果 null 为未能成功接收
|
|
141
157
|
*/
|
|
142
|
-
async function sRepeatPost(posttype:"http"|"https",json:JObject,options:
|
|
158
|
+
async function sRepeatPost(posttype:"http"|"https",json:JObject,options:ComPostOption,verifyFn?:ReqVerifyFn<JObject|null>,opt:RepeatPostOpt={}):Promise<JObject|null>{
|
|
143
159
|
opt.count = opt.count??3;
|
|
144
160
|
opt.tryInterval = opt.tryInterval??180;
|
|
145
161
|
opt.tryDelay = opt.tryDelay??1;
|
|
@@ -161,7 +177,7 @@ async function sRepeatPost(posttype:"http"|"https",json:JObject,options:Object,v
|
|
|
161
177
|
* @param opt.try_delay - 重试间隔 秒 默认0
|
|
162
178
|
* @returns 结果 null 为未能成功接收
|
|
163
179
|
*/
|
|
164
|
-
export function shttpsRepeatPost(json:JObject,options:
|
|
180
|
+
export function shttpsRepeatPost(json:JObject,options:ComPostOption,verifyFn?:ReqVerifyFn<JObject|null>,opt?:RepeatPostOpt):Promise<JObject|null>{
|
|
165
181
|
return sRepeatPost("https",json,options,verifyFn,opt);
|
|
166
182
|
}
|
|
167
183
|
|
|
@@ -178,7 +194,7 @@ export function shttpsRepeatPost(json:JObject,options:Object,verifyFn?:ReqVerify
|
|
|
178
194
|
* @param opt.try_delay - 重试间隔 秒 默认0
|
|
179
195
|
* @returns 结果 null 为未能成功接收
|
|
180
196
|
*/
|
|
181
|
-
export function shttpRepeatPost(json:JObject,options:
|
|
197
|
+
export function shttpRepeatPost(json:JObject,options:ComPostOption,verifyFn?:ReqVerifyFn<JObject|null>,opt?:RepeatPostOpt):Promise<JObject|null>{
|
|
182
198
|
return sRepeatPost("http",json,options,verifyFn,opt);
|
|
183
199
|
}
|
|
184
200
|
|
package/src/UtilFP.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isFailed, likeNone } from "./QuickFunction";
|
|
2
|
-
import { Keyable, Literal, Matchable, MatchableFlag, ProperSubset, ProperSubsetCheck } from "./UtilInterfaces";
|
|
2
|
+
import { AnyRecord, Keyable, Literal, Matchable, MatchableFlag, ProperSubset, ProperSubsetCheck } from "./UtilInterfaces";
|
|
3
3
|
import { Failed, FailedLike, None } from "./UtilSymbol";
|
|
4
4
|
|
|
5
5
|
/**常用函数式编程库 */
|
|
@@ -116,7 +116,7 @@ export function pipe<T>(input: T, ...fs: ((arg: T) => T)[]): T {
|
|
|
116
116
|
* 以及一个新的属性, 这个新的属性的键是`key`, 值是`value`
|
|
117
117
|
*/
|
|
118
118
|
export function bind<K extends Keyable, V>
|
|
119
|
-
(key: Literal<K>,value: V): <B extends
|
|
119
|
+
(key: Literal<K>,value: V): <B extends AnyRecord>
|
|
120
120
|
(base?: B) => keyof B extends K
|
|
121
121
|
? "Base中已有对应键"&Error
|
|
122
122
|
: {[P in K | keyof B]: P extends K ? V : P extends keyof B ? B[P] : never;};
|
|
@@ -130,7 +130,7 @@ export function bind<K extends Keyable, V>
|
|
|
130
130
|
* 以及一个新的属性, 这个新的属性的键是`key`, 值是基础对象
|
|
131
131
|
*/
|
|
132
132
|
export function bind<K extends Keyable>
|
|
133
|
-
(key: Literal<K>): <B extends
|
|
133
|
+
(key: Literal<K>): <B extends AnyRecord>
|
|
134
134
|
(base?: B) => { [P in K]: B };
|
|
135
135
|
/**绑定一个键和一个值到一个基础对象上, 并返回一个新的对象
|
|
136
136
|
* 新的对象包含了基础对象的所有属性, 以及一个新的属性,
|
|
@@ -143,7 +143,7 @@ export function bind<K extends Keyable>
|
|
|
143
143
|
* @param base - 基础对象
|
|
144
144
|
* @returns 完成绑定的基础对象
|
|
145
145
|
*/
|
|
146
|
-
export function bind<K extends Keyable, V, B extends
|
|
146
|
+
export function bind<K extends Keyable, V, B extends AnyRecord>
|
|
147
147
|
(key: Literal<K>,value: V, base:B):keyof B extends K
|
|
148
148
|
? "Base中已有对应键"&Error
|
|
149
149
|
: {[P in K | keyof B]: P extends K ? V : P extends keyof B ? B[P] : never;};
|
|
@@ -156,7 +156,7 @@ export function bind
|
|
|
156
156
|
return <B>(base?: B) =>
|
|
157
157
|
({[key as Keyable]:base});
|
|
158
158
|
|
|
159
|
-
return <B extends
|
|
159
|
+
return <B extends AnyRecord>
|
|
160
160
|
(base?: B):{
|
|
161
161
|
[P in K | keyof B]: P extends K ? V : P extends keyof B ? B[P] : never;
|
|
162
162
|
} => base !== undefined
|
package/src/UtilFileTools.ts
CHANGED
|
@@ -40,8 +40,19 @@ type LoadJsonFileOpt<T> = Partial<{
|
|
|
40
40
|
default:T;
|
|
41
41
|
/**以json5模式加载 略慢 默认false */
|
|
42
42
|
json5:boolean;
|
|
43
|
+
/**不自动修改扩展名为json */
|
|
44
|
+
forceExt:boolean;
|
|
43
45
|
}>
|
|
44
46
|
|
|
47
|
+
/**json文件写入选项 */
|
|
48
|
+
type WriteJsonFileOpt = Partial<{
|
|
49
|
+
/**使用紧凑风格 */
|
|
50
|
+
compress:boolean;
|
|
51
|
+
/**不自动修改扩展名为json */
|
|
52
|
+
forceExt:boolean;
|
|
53
|
+
}>
|
|
54
|
+
|
|
55
|
+
|
|
45
56
|
/**文件工具 */
|
|
46
57
|
export namespace UtilFT{
|
|
47
58
|
|
|
@@ -157,19 +168,19 @@ export function loadJSONFileSync(filePath: string): JToken
|
|
|
157
168
|
/**加载json文件 同步
|
|
158
169
|
* @param filePath - 文件路径
|
|
159
170
|
* @param opt - 可选参数
|
|
160
|
-
* @param opt.default
|
|
161
|
-
* @param opt.json5
|
|
171
|
+
* @param opt.default - 默认值
|
|
172
|
+
* @param opt.json5 - json5模式
|
|
173
|
+
* @param opt.forceExt - 不自动修改扩展名为json
|
|
162
174
|
* @returns 加载完成的对象或默认值
|
|
163
175
|
*/
|
|
164
176
|
export function loadJSONFileSync<T extends JToken>(filePath: string,opt:LoadJsonFileOpt<T>): T
|
|
165
177
|
export function loadJSONFileSync<T extends JToken>(filePath: string,opt?:LoadJsonFileOpt<T>): T {
|
|
166
|
-
if
|
|
167
|
-
|
|
168
|
-
let str = "";
|
|
178
|
+
if(opt?.forceExt!==true && path.extname(filePath) !== '.json')
|
|
179
|
+
filePath += '.json';
|
|
169
180
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
181
|
+
const str = pathExistsSync(filePath)
|
|
182
|
+
? fs.readFileSync(filePath, "utf-8")
|
|
183
|
+
: "";
|
|
173
184
|
|
|
174
185
|
// 如果不存在则返回默认值
|
|
175
186
|
if (str == "" || str == null){
|
|
@@ -192,19 +203,19 @@ export async function loadJSONFile(filePath: string): Promise<JToken>
|
|
|
192
203
|
* @async
|
|
193
204
|
* @param filePath - 文件路径
|
|
194
205
|
* @param opt - 可选参数
|
|
195
|
-
* @param opt.default
|
|
196
|
-
* @param opt.json5
|
|
206
|
+
* @param opt.default - 默认值
|
|
207
|
+
* @param opt.json5 - json5模式
|
|
208
|
+
* @param opt.forceExt - 不自动修改扩展名为json
|
|
197
209
|
* @returns 加载完成的对象或默认值
|
|
198
210
|
*/
|
|
199
211
|
export async function loadJSONFile<T extends JToken>(filePath: string,opt:LoadJsonFileOpt<T>): Promise<T>
|
|
200
212
|
export async function loadJSONFile<T extends JToken>(filePath: string,opt?:LoadJsonFileOpt<T>): Promise<T> {
|
|
201
|
-
if
|
|
202
|
-
|
|
203
|
-
let str = "";
|
|
213
|
+
if(opt?.forceExt!==true && path.extname(filePath) !== '.json')
|
|
214
|
+
filePath += '.json';
|
|
204
215
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
216
|
+
const str = (await pathExists(filePath))
|
|
217
|
+
? await fs.promises.readFile(filePath, "utf-8")
|
|
218
|
+
: "";
|
|
208
219
|
|
|
209
220
|
// 如果不存在则返回默认值
|
|
210
221
|
if (str == "" || str == null){
|
|
@@ -222,13 +233,18 @@ export async function loadJSONFile<T extends JToken>(filePath: string,opt?:LoadJ
|
|
|
222
233
|
* @async
|
|
223
234
|
* @param filePath - 文件路径
|
|
224
235
|
* @param token - 所要写入的JToken
|
|
236
|
+
* @param opt - 可选参数
|
|
237
|
+
* @param opt.compress - 使用紧凑风格
|
|
238
|
+
* @param opt.forceExt - 不自动修改扩展名为json
|
|
225
239
|
*/
|
|
226
240
|
export async function writeJSONFile(
|
|
227
241
|
filePath: string,
|
|
228
|
-
token: JToken
|
|
242
|
+
token: JToken,
|
|
243
|
+
opt?: WriteJsonFileOpt
|
|
229
244
|
): Promise<void> {
|
|
230
|
-
const str = UtilFunc.stringifyJToken(token);
|
|
231
|
-
if
|
|
245
|
+
const str = UtilFunc.stringifyJToken(token,opt);
|
|
246
|
+
if(opt?.forceExt!==true && path.extname(filePath) !== '.json')
|
|
247
|
+
filePath += '.json';
|
|
232
248
|
|
|
233
249
|
// 判断文件路径是否存在 不存在则创建
|
|
234
250
|
if(!(await pathExists(filePath)))
|
package/src/UtilFunctions.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as crypto from "crypto";
|
|
2
|
-
import { AnyFunc, ComposedClass, ComposedMixinable, ComposedRefMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, Literal, Matchable, MatchableFlag, Mixinable, Outcome, ReqStat, ReqVerifyFn, ProperSubsetCheck, RefMixinable, UnionToIntersection, Await } from "@src/UtilInterfaces";
|
|
2
|
+
import { AnyFunc, ComposedClass, ComposedMixinable, ComposedRefMixinable, ExtractOutcome, IJData, JObject, JToken, Keyable, Literal, Matchable, MatchableFlag, Mixinable, Outcome, ReqStat, ReqVerifyFn, ProperSubsetCheck, RefMixinable, UnionToIntersection, Await, AnyRecord } 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";
|
|
@@ -18,6 +18,14 @@ type ExecOpt = Partial<{
|
|
|
18
18
|
errlvl:LogLevel,
|
|
19
19
|
}>
|
|
20
20
|
|
|
21
|
+
/**序列化选项 */
|
|
22
|
+
type StringifyOpt = Partial<{
|
|
23
|
+
/**使用紧凑风格 */
|
|
24
|
+
compress:boolean;
|
|
25
|
+
/**插入的空格 数字为空格数量 默认为制表符\t */
|
|
26
|
+
space:string|number|null|undefined;
|
|
27
|
+
}>
|
|
28
|
+
|
|
21
29
|
/**Promise重试选项 */
|
|
22
30
|
export type RepeatPromiseOpt = Partial<{
|
|
23
31
|
/**重试次数 默认3*/
|
|
@@ -59,7 +67,7 @@ static getTime(): number {
|
|
|
59
67
|
* @param defaultVal - 默认值
|
|
60
68
|
* @returns 最终值
|
|
61
69
|
*/
|
|
62
|
-
static initField<T extends
|
|
70
|
+
static initField<T extends AnyRecord,K extends keyof T>(
|
|
63
71
|
obj: T,
|
|
64
72
|
field: K,
|
|
65
73
|
defaultVal: T[K]
|
|
@@ -333,7 +341,7 @@ static timelimitPromise<T>
|
|
|
333
341
|
* @returns 混合完成的类
|
|
334
342
|
*/
|
|
335
343
|
static composeClassPart
|
|
336
|
-
<Base extends
|
|
344
|
+
<Base extends AnyRecord,Mixin extends AnyRecord,Field extends keyof Mixin>
|
|
337
345
|
(base:Base,mixin:Mixin,key:string,...fields:Field[]):ComposedClass<Base,Mixin,typeof key,Field>{
|
|
338
346
|
const compObj = base as any;
|
|
339
347
|
if(compObj[key]!==undefined)
|
|
@@ -374,7 +382,7 @@ static composeClassPart
|
|
|
374
382
|
* @deprecated 非必要情况下, 对class定义请使用 composeRefMixinable
|
|
375
383
|
*/
|
|
376
384
|
static composeMixinable
|
|
377
|
-
<Base extends
|
|
385
|
+
<Base extends AnyRecord, Mixins extends Mixinable<any>[]>
|
|
378
386
|
(base:Base,...mixins:Mixins):
|
|
379
387
|
ComposedMixinable<Base,Mixins>{
|
|
380
388
|
let out = base;
|
|
@@ -395,7 +403,7 @@ static composeMixinable
|
|
|
395
403
|
|
|
396
404
|
/**根据 MIXIN_FIELDS 自动混入 */
|
|
397
405
|
static composeRefMixinable
|
|
398
|
-
<Base extends
|
|
406
|
+
<Base extends AnyRecord, Mixins extends RefMixinable<any,unknown>[]>
|
|
399
407
|
(base:Base,...mixins:Mixins):
|
|
400
408
|
ComposedRefMixinable<Base,Mixins>{
|
|
401
409
|
let out = base;
|
|
@@ -421,7 +429,7 @@ static composeRefMixinable
|
|
|
421
429
|
* @param mapper - 映射函数,接受一个值和一个键,返回一个新的值
|
|
422
430
|
* @returns - 一个新的对象,它的属性是原对象的属性经过映射函数处理后的结果
|
|
423
431
|
*/
|
|
424
|
-
static mapEntries<T extends
|
|
432
|
+
static mapEntries<T extends AnyRecord>
|
|
425
433
|
(obj: T, mapper: (key: keyof T, value: T[keyof T]) => T[keyof T]): T {
|
|
426
434
|
return Object.entries(obj).reduce((result, [key, value]) => {
|
|
427
435
|
result[key as keyof T] = mapper(key as keyof T, value);
|
|
@@ -431,13 +439,32 @@ static mapEntries<T extends object>
|
|
|
431
439
|
|
|
432
440
|
/**将JToken转换为字符串
|
|
433
441
|
* @param token - 待转换的Token
|
|
434
|
-
* @param
|
|
442
|
+
* @param opt - 可选参数
|
|
443
|
+
* @param opt.space - 插入的空格 数字为空格数量 默认为制表符\t
|
|
444
|
+
* @param opt.compress - 使用紧凑风格
|
|
435
445
|
* @returns 转换完成的字符串
|
|
436
446
|
*/
|
|
437
|
-
static stringifyJToken(token:JToken|IJData,
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
447
|
+
static stringifyJToken(token:JToken|IJData,opt?:StringifyOpt){
|
|
448
|
+
opt ??= {};
|
|
449
|
+
let {compress,space} = opt;
|
|
450
|
+
space ??="\t";
|
|
451
|
+
space = space===null ? undefined : space;
|
|
452
|
+
|
|
453
|
+
if(!compress) return JSON.stringify(token,null,space);
|
|
454
|
+
|
|
455
|
+
const compressReplacer = (key: string, value: any)=> {
|
|
456
|
+
if (Array.isArray(value) && value.every(item =>
|
|
457
|
+
typeof item === 'number' || typeof item === 'string' ||
|
|
458
|
+
typeof item === 'boolean' || item == null))
|
|
459
|
+
return `@@@${JSON.stringify(value)}@@@`;
|
|
460
|
+
const str = JSON.stringify(value);
|
|
461
|
+
if(str.length<=100) return `@@@${str}@@@`;
|
|
462
|
+
return value;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return JSON.stringify(token,compressReplacer,space)
|
|
466
|
+
.replace(/"@@@(.*?)@@@"/g,`$1`)
|
|
467
|
+
.replace(/\\([\\"])/g, '$1');
|
|
441
468
|
}
|
|
442
469
|
|
|
443
470
|
/**代办表 用于队列处理等待 */
|
|
@@ -643,7 +670,7 @@ static isSafeNumber(num: unknown): boolean {
|
|
|
643
670
|
}
|
|
644
671
|
|
|
645
672
|
/**将一个字段加入一个对象中,将改变对象,返回新类型 */
|
|
646
|
-
static bindTo<K extends Keyable, V, B extends
|
|
673
|
+
static bindTo<K extends Keyable, V, B extends AnyRecord = {}>
|
|
647
674
|
(key: Literal<K>,value: V, base?:B):keyof B extends K
|
|
648
675
|
? "Base中已有对应键"&Error
|
|
649
676
|
: {[P in K | keyof B]: P extends K ? V : P extends keyof B ? B[P] : never;}{
|
package/src/UtilInterfaces.ts
CHANGED
|
@@ -73,7 +73,7 @@ export type LiteralCheck<L> =
|
|
|
73
73
|
L extends null | undefined ? true : false;
|
|
74
74
|
|
|
75
75
|
/**返回将Mixin分配给Base的结果,相同字段时Mixin覆盖Base */
|
|
76
|
-
export type AssignObject<Base extends
|
|
76
|
+
export type AssignObject<Base extends AnyRecord, Mixin extends AnyRecord> = {
|
|
77
77
|
[P in keyof Mixin | keyof Base]: P extends keyof Mixin ? Mixin[P] : P extends keyof Base ? Base[P] : never;
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -180,8 +180,17 @@ export type ReflectionAble<Ctor,Constraint={}> = {
|
|
|
180
180
|
};
|
|
181
181
|
/**可反射的 且 构造函数是可混入的类
|
|
182
182
|
* @template Ctor - 构造器类型
|
|
183
|
-
* @template Instance - 实例类型
|
|
183
|
+
* @template Instance - 实例类型 如果采用了内部混入, 那么填入对外实际暴露的类型, 以支持混入多层字段
|
|
184
184
|
* @template Constraint - 构造器约束
|
|
185
|
+
* @example
|
|
186
|
+
* export class MixinModule implements RefMixinable<typeof MixinModule,MixinModule>{
|
|
187
|
+
* static readonly MIXIN_FIELDS = [
|
|
188
|
+
* 'func_a',
|
|
189
|
+
* 'field_b'
|
|
190
|
+
* ] as const;
|
|
191
|
+
* static readonly MIXIN_KEY = '__mixinModule';
|
|
192
|
+
* CTOR = MixinModule;
|
|
193
|
+
* }
|
|
185
194
|
*/
|
|
186
195
|
export type RefMixinable<Ctor,Instance,Constraint={}> =
|
|
187
196
|
ReflectionAble<Ctor,Mixinable<Instance>&Constraint>;
|
|
@@ -284,4 +293,14 @@ export type NeedInit = {
|
|
|
284
293
|
};
|
|
285
294
|
|
|
286
295
|
/**可选的record */
|
|
287
|
-
export type PRecord<K extends Keyable,V> = Partial<Record<K,V>>;
|
|
296
|
+
export type PRecord<K extends Keyable,V> = Partial<Record<K,V>>;
|
|
297
|
+
/**任何Record */
|
|
298
|
+
export type AnyRecord = Record<Keyable,any>;
|
|
299
|
+
|
|
300
|
+
/**注释元组
|
|
301
|
+
* @template T - 提供注释的类型, 索引需从0开始
|
|
302
|
+
*/
|
|
303
|
+
export type AnnotableTuple<T extends {[K:number]:unknown},Tuple extends unknown[]=[]> =
|
|
304
|
+
unknown extends T[Tuple['length']]
|
|
305
|
+
? T & Tuple
|
|
306
|
+
: AnnotableTuple<T,[...Tuple,T[Tuple['length']]]>;
|