@planet-matrix/mobius-model 0.4.0 → 0.6.0
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/CHANGELOG.md +32 -0
- package/README.md +134 -21
- package/dist/index.js +45 -4
- package/dist/index.js.map +186 -11
- package/oxlint.config.ts +6 -0
- package/package.json +16 -10
- package/src/abort/README.md +92 -0
- package/src/abort/abort-manager.ts +278 -0
- package/src/abort/abort-signal-listener-manager.ts +81 -0
- package/src/abort/index.ts +2 -0
- package/src/basic/README.md +69 -117
- package/src/basic/enhance.ts +10 -0
- package/src/basic/function.ts +81 -62
- package/src/basic/index.ts +2 -0
- package/src/basic/is.ts +152 -71
- package/src/basic/object.ts +82 -0
- package/src/basic/promise.ts +29 -8
- package/src/basic/string.ts +2 -33
- package/src/color/README.md +105 -0
- package/src/color/index.ts +3 -0
- package/src/color/internal.ts +42 -0
- package/src/color/rgb/analyze.ts +236 -0
- package/src/color/rgb/construct.ts +130 -0
- package/src/color/rgb/convert.ts +227 -0
- package/src/color/rgb/derive.ts +303 -0
- package/src/color/rgb/index.ts +6 -0
- package/src/color/rgb/internal.ts +208 -0
- package/src/color/rgb/parse.ts +302 -0
- package/src/color/rgb/serialize.ts +144 -0
- package/src/color/types.ts +57 -0
- package/src/color/xyz/analyze.ts +80 -0
- package/src/color/xyz/construct.ts +19 -0
- package/src/color/xyz/convert.ts +71 -0
- package/src/color/xyz/index.ts +3 -0
- package/src/color/xyz/internal.ts +23 -0
- package/src/css/README.md +93 -0
- package/src/css/class.ts +559 -0
- package/src/css/index.ts +1 -0
- package/src/encoding/README.md +92 -0
- package/src/encoding/base64.ts +107 -0
- package/src/encoding/index.ts +1 -0
- package/src/environment/README.md +97 -0
- package/src/environment/basic.ts +26 -0
- package/src/environment/device.ts +311 -0
- package/src/environment/feature.ts +285 -0
- package/src/environment/geo.ts +337 -0
- package/src/environment/index.ts +7 -0
- package/src/environment/runtime.ts +400 -0
- package/src/environment/snapshot.ts +60 -0
- package/src/environment/variable.ts +239 -0
- package/src/event/README.md +90 -0
- package/src/event/class-event-proxy.ts +228 -0
- package/src/event/common.ts +19 -0
- package/src/event/event-manager.ts +203 -0
- package/src/event/index.ts +4 -0
- package/src/event/instance-event-proxy.ts +186 -0
- package/src/event/internal.ts +24 -0
- package/src/exception/README.md +96 -0
- package/src/exception/browser.ts +219 -0
- package/src/exception/index.ts +4 -0
- package/src/exception/nodejs.ts +169 -0
- package/src/exception/normalize.ts +106 -0
- package/src/exception/types.ts +99 -0
- package/src/identifier/README.md +92 -0
- package/src/identifier/id.ts +119 -0
- package/src/identifier/index.ts +2 -0
- package/src/identifier/uuid.ts +187 -0
- package/src/index.ts +18 -1
- package/src/log/README.md +79 -0
- package/src/log/index.ts +5 -0
- package/src/log/log-emitter.ts +72 -0
- package/src/log/log-record.ts +10 -0
- package/src/log/log-scheduler.ts +74 -0
- package/src/log/log-type.ts +8 -0
- package/src/log/logger.ts +543 -0
- package/src/orchestration/README.md +89 -0
- package/src/orchestration/coordination/barrier.ts +214 -0
- package/src/orchestration/coordination/count-down-latch.ts +215 -0
- package/src/orchestration/coordination/errors.ts +98 -0
- package/src/orchestration/coordination/index.ts +16 -0
- package/src/orchestration/coordination/internal/wait-constraints.ts +95 -0
- package/src/orchestration/coordination/internal/wait-queue.ts +109 -0
- package/src/orchestration/coordination/keyed-lock.ts +168 -0
- package/src/orchestration/coordination/mutex.ts +257 -0
- package/src/orchestration/coordination/permit.ts +127 -0
- package/src/orchestration/coordination/read-write-lock.ts +444 -0
- package/src/orchestration/coordination/semaphore.ts +280 -0
- package/src/orchestration/index.ts +1 -0
- package/src/random/README.md +78 -0
- package/src/random/index.ts +1 -0
- package/src/random/string.ts +35 -0
- package/src/reactor/README.md +4 -0
- package/src/reactor/reactor-core/primitive.ts +9 -9
- package/src/reactor/reactor-core/reactive-system.ts +5 -5
- package/src/singleton/README.md +79 -0
- package/src/singleton/factory.ts +55 -0
- package/src/singleton/index.ts +2 -0
- package/src/singleton/manager.ts +204 -0
- package/src/storage/README.md +107 -0
- package/src/storage/index.ts +1 -0
- package/src/storage/table.ts +449 -0
- package/src/timer/README.md +86 -0
- package/src/timer/expiration/expiration-manager.ts +594 -0
- package/src/timer/expiration/index.ts +3 -0
- package/src/timer/expiration/min-heap.ts +208 -0
- package/src/timer/expiration/remaining-manager.ts +241 -0
- package/src/timer/index.ts +1 -0
- package/src/type/README.md +54 -307
- package/src/type/class.ts +2 -2
- package/src/type/index.ts +14 -14
- package/src/type/is.ts +265 -2
- package/src/type/object.ts +37 -0
- package/src/type/string.ts +7 -2
- package/src/type/tuple.ts +6 -6
- package/src/type/union.ts +16 -0
- package/src/web/README.md +77 -0
- package/src/web/capture.ts +35 -0
- package/src/web/clipboard.ts +97 -0
- package/src/web/dom.ts +117 -0
- package/src/web/download.ts +16 -0
- package/src/web/event.ts +46 -0
- package/src/web/index.ts +10 -0
- package/src/web/local-storage.ts +113 -0
- package/src/web/location.ts +28 -0
- package/src/web/permission.ts +172 -0
- package/src/web/script-loader.ts +432 -0
- package/tests/unit/abort/abort-manager.spec.ts +225 -0
- package/tests/unit/abort/abort-signal-listener-manager.spec.ts +62 -0
- package/tests/unit/basic/array.spec.ts +1 -1
- package/tests/unit/basic/object.spec.ts +32 -1
- package/tests/unit/basic/stream.spec.ts +1 -1
- package/tests/unit/basic/string.spec.ts +0 -9
- package/tests/unit/color/rgb/analyze.spec.ts +110 -0
- package/tests/unit/color/rgb/construct.spec.ts +56 -0
- package/tests/unit/color/rgb/convert.spec.ts +60 -0
- package/tests/unit/color/rgb/derive.spec.ts +103 -0
- package/tests/unit/color/rgb/parse.spec.ts +66 -0
- package/tests/unit/color/rgb/serialize.spec.ts +46 -0
- package/tests/unit/color/xyz/analyze.spec.ts +33 -0
- package/tests/unit/color/xyz/construct.spec.ts +10 -0
- package/tests/unit/color/xyz/convert.spec.ts +18 -0
- package/tests/unit/css/class.spec.ts +157 -0
- package/tests/unit/encoding/base64.spec.ts +40 -0
- package/tests/unit/environment/basic.spec.ts +20 -0
- package/tests/unit/environment/device.spec.ts +146 -0
- package/tests/unit/environment/feature.spec.ts +388 -0
- package/tests/unit/environment/geo.spec.ts +111 -0
- package/tests/unit/environment/runtime.spec.ts +364 -0
- package/tests/unit/environment/snapshot.spec.ts +4 -0
- package/tests/unit/environment/variable.spec.ts +190 -0
- package/tests/unit/event/class-event-proxy.spec.ts +225 -0
- package/tests/unit/event/event-manager.spec.ts +246 -0
- package/tests/unit/event/instance-event-proxy.spec.ts +187 -0
- package/tests/unit/exception/browser.spec.ts +213 -0
- package/tests/unit/exception/nodejs.spec.ts +144 -0
- package/tests/unit/exception/normalize.spec.ts +57 -0
- package/tests/unit/identifier/id.spec.ts +71 -0
- package/tests/unit/identifier/uuid.spec.ts +85 -0
- package/tests/unit/log/log-emitter.spec.ts +33 -0
- package/tests/unit/log/log-scheduler.spec.ts +40 -0
- package/tests/unit/log/log-type.spec.ts +7 -0
- package/tests/unit/log/logger.spec.ts +222 -0
- package/tests/unit/orchestration/coordination/barrier.spec.ts +96 -0
- package/tests/unit/orchestration/coordination/count-down-latch.spec.ts +63 -0
- package/tests/unit/orchestration/coordination/errors.spec.ts +29 -0
- package/tests/unit/orchestration/coordination/keyed-lock.spec.ts +109 -0
- package/tests/unit/orchestration/coordination/mutex.spec.ts +132 -0
- package/tests/unit/orchestration/coordination/permit.spec.ts +43 -0
- package/tests/unit/orchestration/coordination/read-write-lock.spec.ts +154 -0
- package/tests/unit/orchestration/coordination/semaphore.spec.ts +135 -0
- package/tests/unit/random/string.spec.ts +11 -0
- package/tests/unit/reactor/alien-signals-effect.spec.ts +11 -10
- package/tests/unit/reactor/preact-signal.spec.ts +1 -2
- package/tests/unit/singleton/singleton.spec.ts +49 -0
- package/tests/unit/storage/table.spec.ts +620 -0
- package/tests/unit/timer/expiration/expiration-manager.spec.ts +464 -0
- package/tests/unit/timer/expiration/min-heap.spec.ts +71 -0
- package/tests/unit/timer/expiration/remaining-manager.spec.ts +234 -0
- package/.oxlintrc.json +0 -5
package/src/basic/is.ts
CHANGED
|
@@ -13,81 +13,140 @@ import type {
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* 进行类型检测的常用手段包括:
|
|
16
|
-
*
|
|
16
|
+
* - typeof: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
|
|
17
17
|
* https://tc39.es/ecma262/#sec-typeof-operator
|
|
18
|
-
*
|
|
19
|
-
*
|
|
18
|
+
* - instanceof: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof
|
|
19
|
+
* - toString: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
|
|
20
20
|
*
|
|
21
|
-
*
|
|
21
|
+
* 检测可能不存在的变量:
|
|
22
|
+
* - typeof value === "undefined"
|
|
23
|
+
* - globalThis.value === undefined
|
|
22
24
|
*/
|
|
23
25
|
|
|
24
26
|
/**
|
|
25
|
-
*
|
|
27
|
+
* 判断目标值是否为原始值(primitive)。
|
|
26
28
|
*/
|
|
27
29
|
export const isPrimitive = (target: unknown): target is Primitive => {
|
|
28
30
|
return isString(target) || isNumber(target) || isBoolean(target) || isBigInt(target) || isSymbol(target) || isNull(target) || isUndefined(target)
|
|
29
31
|
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 判断目标值是否为非原始值(non-primitive)。
|
|
35
|
+
*/
|
|
30
36
|
export const isNonPrimitive = (target: unknown): target is NonPrimitive => {
|
|
31
37
|
return isPrimitive(target) === false
|
|
32
38
|
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 判断目标值是否为字符串。
|
|
42
|
+
*/
|
|
33
43
|
export const isString = (target: unknown): target is string => {
|
|
34
44
|
return Object.prototype.toString.call(target) === "[object String]"
|
|
35
45
|
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 判断目标值是否为数字。
|
|
49
|
+
*/
|
|
36
50
|
export const isNumber = (target: unknown): target is number => {
|
|
37
51
|
return Object.prototype.toString.call(target) === "[object Number]" && isNaN(Number.parseFloat(String(target)))
|
|
38
52
|
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 判断目标值是否为 `NaN`。
|
|
56
|
+
*/
|
|
39
57
|
export const isNaN = (target: unknown): boolean => {
|
|
40
58
|
return Number.isNaN(target)
|
|
41
59
|
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 判断目标值是否为有限数字。
|
|
63
|
+
*/
|
|
42
64
|
export const isFiniteNumber = (target: unknown): target is number => {
|
|
43
65
|
return isNumber(target) && Number.isFinite(target)
|
|
44
66
|
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 判断目标值是否为无限数字。
|
|
70
|
+
*/
|
|
45
71
|
export const isInfiniteNumber = (target: unknown): target is number => {
|
|
46
72
|
return isNumber(target) && !Number.isFinite(target)
|
|
47
73
|
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 判断目标值是否为布尔值。
|
|
77
|
+
*/
|
|
48
78
|
export const isBoolean = (target: unknown): target is boolean => {
|
|
49
79
|
return Object.prototype.toString.call(target) === "[object Boolean]"
|
|
50
80
|
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 判断目标值是否为 `true`。
|
|
84
|
+
*/
|
|
51
85
|
export const isTrue = (target: unknown): target is true => {
|
|
52
86
|
return isBoolean(target) && target === true
|
|
53
87
|
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 判断目标值是否为 `false`。
|
|
91
|
+
*/
|
|
54
92
|
export const isFalse = (target: unknown): target is false => {
|
|
55
93
|
return isBoolean(target) && target === false
|
|
56
94
|
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 判断目标值是否为大整数(BigInt)。
|
|
98
|
+
*/
|
|
57
99
|
export const isBigInt = (target: unknown): target is bigint => {
|
|
58
100
|
return Object.prototype.toString.call(target) === "[object BigInt]"
|
|
59
101
|
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* 判断目标值是否为符号(Symbol)。
|
|
105
|
+
*/
|
|
60
106
|
export const isSymbol = (target: unknown): target is symbol => {
|
|
61
107
|
return Object.prototype.toString.call(target) === "[object Symbol]"
|
|
62
108
|
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 判断目标值是否为 `null`。
|
|
112
|
+
*/
|
|
63
113
|
export const isNull = (target: unknown): target is null => {
|
|
64
114
|
return Object.prototype.toString.call((target)) === "[object Null]"
|
|
65
115
|
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* 判断目标值是否为 `undefined`。
|
|
119
|
+
*/
|
|
66
120
|
export const isUndefined = (target: unknown): target is undefined => {
|
|
67
121
|
return Object.prototype.toString.call(target) === "[object Undefined]"
|
|
68
122
|
}
|
|
69
123
|
/**
|
|
124
|
+
* 判断目标值是否不是 `undefined`。
|
|
125
|
+
*
|
|
70
126
|
* @see {@link https://stackoverflow.com/a/52097700}
|
|
71
127
|
*/
|
|
72
128
|
export const isDefined = <T>(target: T | undefined): target is T => {
|
|
73
129
|
return isUndefined(target) === false
|
|
74
130
|
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 判断目标值是否为 `null` 或 `undefined`。
|
|
134
|
+
*/
|
|
75
135
|
export const isNil = (target: unknown): target is (null | undefined) => {
|
|
76
136
|
return target === null || target === undefined
|
|
77
137
|
}
|
|
78
138
|
|
|
79
139
|
/**
|
|
80
|
-
*
|
|
140
|
+
* 使用 `instanceof` 判断目标值是否为对象。
|
|
81
141
|
*
|
|
82
142
|
* @see {@link isGeneralObject}, {@link isPlainObject}
|
|
83
143
|
*/
|
|
84
144
|
// oxlint-disable-next-line no-wrapper-object-types
|
|
85
145
|
export const isObject = (target: unknown): target is Object => {
|
|
86
|
-
// oxlint-disable-next-line no-instanceof-builtins
|
|
87
146
|
return target instanceof Object
|
|
88
147
|
}
|
|
89
148
|
/**
|
|
90
|
-
*
|
|
149
|
+
* 使用 `typeof` 判断目标值是否为广义对象。
|
|
91
150
|
*
|
|
92
151
|
* A general object is an object that is:
|
|
93
152
|
* - not `null`, not a `function`, not a `primitive`.
|
|
@@ -97,17 +156,12 @@ export const isObject = (target: unknown): target is Object => {
|
|
|
97
156
|
*
|
|
98
157
|
* @example
|
|
99
158
|
* ```
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* typeof (new Set()) // => 'object'
|
|
107
|
-
* typeof (new WeakSet()) // => 'object'
|
|
108
|
-
* typeof (new Date()) // => 'object'
|
|
109
|
-
* typeof window // => 'object'
|
|
110
|
-
* typeof document // => 'object'
|
|
159
|
+
* // Expect: true
|
|
160
|
+
* const example1 = isGeneralObject([])
|
|
161
|
+
* // Expect: true
|
|
162
|
+
* const example2 = isGeneralObject(new Map())
|
|
163
|
+
* // Expect: false
|
|
164
|
+
* const example3 = isGeneralObject(null)
|
|
111
165
|
* ```
|
|
112
166
|
*
|
|
113
167
|
* @see {@link isObject}, {@link isPlainObject}
|
|
@@ -141,88 +195,151 @@ export const isPlainObject = (target: unknown): target is PlainObject => {
|
|
|
141
195
|
const proto = Object.getPrototypeOf(target)
|
|
142
196
|
return proto === Object.prototype || proto === null
|
|
143
197
|
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 判断目标值是否为空普通对象。
|
|
201
|
+
*/
|
|
144
202
|
export const isEmptyPlainObject = (target: unknown): target is PlainObject => {
|
|
145
203
|
return isPlainObject(target) && Reflect.ownKeys(target).length === 0
|
|
146
204
|
}
|
|
147
205
|
|
|
206
|
+
/**
|
|
207
|
+
* 判断目标值是否为数组。
|
|
208
|
+
*/
|
|
148
209
|
export function isArray<T>(target: T[]): target is T[]
|
|
149
210
|
export function isArray<T>(target: unknown): target is T[]
|
|
150
211
|
export function isArray<T>(target: unknown): target is T[] {
|
|
151
212
|
return Array.isArray(target)
|
|
152
213
|
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* 判断目标值是否为空数组。
|
|
217
|
+
*/
|
|
153
218
|
export const isEmptyArray = (target: unknown): target is [] => {
|
|
154
219
|
return isArray(target) && target.length === 0
|
|
155
220
|
}
|
|
156
221
|
|
|
222
|
+
/**
|
|
223
|
+
* 判断目标值是否为类数组对象(array-like)。
|
|
224
|
+
*/
|
|
157
225
|
export function isArrayLike<T>(target: ArrayLike<T>): target is ArrayLike<T>
|
|
158
226
|
export function isArrayLike<T>(target: unknown): target is ArrayLike<T>
|
|
159
227
|
export function isArrayLike<T>(target: unknown): target is ArrayLike<T> {
|
|
160
228
|
return isGeneralObject(target) && ("length" in target) && isNumber(target.length)
|
|
161
229
|
}
|
|
162
230
|
|
|
231
|
+
/**
|
|
232
|
+
* 判断目标值是否为 `Map`。
|
|
233
|
+
*/
|
|
163
234
|
export function isMap<K, V>(target: Map<K, V>): target is Map<K, V>
|
|
164
235
|
export function isMap<K, V>(target: unknown): target is Map<K, V>
|
|
165
236
|
export function isMap<K, V>(target: unknown): target is Map<K, V> {
|
|
166
237
|
return Object.prototype.toString.call(target) === "[object Map]"
|
|
167
238
|
}
|
|
168
239
|
|
|
240
|
+
/**
|
|
241
|
+
* 判断目标值是否为 `WeakMap`。
|
|
242
|
+
*/
|
|
169
243
|
export function isWeakMap<K extends object, V>(target: WeakMap<K, V>): target is WeakMap<K, V>
|
|
170
244
|
export function isWeakMap<K extends object, V>(target: unknown): target is WeakMap<K, V>
|
|
171
245
|
export function isWeakMap<K extends object, V>(target: unknown): target is WeakMap<K, V> {
|
|
172
246
|
return Object.prototype.toString.call(target) === "[object WeakMap]"
|
|
173
247
|
}
|
|
174
248
|
|
|
249
|
+
/**
|
|
250
|
+
* 判断目标值是否为 `Set`。
|
|
251
|
+
*/
|
|
175
252
|
export function isSet<T>(target: Set<T>): target is Set<T>
|
|
176
253
|
export function isSet<T>(target: unknown): target is Set<T>
|
|
177
254
|
export function isSet<T>(target: unknown): target is Set<T> {
|
|
178
255
|
return Object.prototype.toString.call(target) === "[object Set]"
|
|
179
256
|
}
|
|
180
257
|
|
|
258
|
+
/**
|
|
259
|
+
* 判断目标值是否为 `WeakSet`。
|
|
260
|
+
*/
|
|
181
261
|
export function isWeakSet<T extends object>(target: WeakSet<T>): target is WeakSet<T>
|
|
182
262
|
export function isWeakSet<T extends object>(target: unknown): target is WeakSet<T>
|
|
183
263
|
export function isWeakSet<T extends object>(target: unknown): target is WeakSet<T> {
|
|
184
264
|
return Object.prototype.toString.call(target) === "[object WeakSet]"
|
|
185
265
|
}
|
|
186
266
|
|
|
267
|
+
/**
|
|
268
|
+
* 判断目标值是否为 `Date`。
|
|
269
|
+
*/
|
|
187
270
|
export const isDate = (target: unknown): target is Date => {
|
|
188
271
|
return Object.prototype.toString.call(target) === "[object Date]"
|
|
189
272
|
}
|
|
190
273
|
|
|
274
|
+
/**
|
|
275
|
+
* 判断目标值是否为 `RegExp`。
|
|
276
|
+
*/
|
|
191
277
|
export const isRegExp = (target: unknown): target is RegExp => {
|
|
192
278
|
return Object.prototype.toString.call(target) === "[object RegExp]"
|
|
193
279
|
}
|
|
194
280
|
|
|
281
|
+
/**
|
|
282
|
+
* 判断目标值是否为 `Error`。
|
|
283
|
+
*/
|
|
195
284
|
export const isError = (target: unknown): target is Error => {
|
|
196
285
|
return Object.prototype.toString.call(target) === "[object Error]"
|
|
197
286
|
}
|
|
198
287
|
|
|
288
|
+
/**
|
|
289
|
+
* 判断目标值是否为 `Promise`。
|
|
290
|
+
*/
|
|
199
291
|
export function isPromise<T>(target: Promise<T>): target is Promise<T>
|
|
200
292
|
export function isPromise<T>(target: unknown): target is Promise<T>
|
|
201
293
|
export function isPromise<T>(target: unknown): target is Promise<T> {
|
|
202
294
|
return Object.prototype.toString.call(target) === "[object Promise]"
|
|
203
295
|
}
|
|
204
296
|
|
|
297
|
+
/**
|
|
298
|
+
* 判断目标值是否为任意函数。
|
|
299
|
+
*/
|
|
205
300
|
// oxlint-disable-next-line no-unsafe-function-type
|
|
206
301
|
export const isFunction = (target: unknown): target is Function => {
|
|
207
302
|
return typeof target === "function"
|
|
208
303
|
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* 判断目标值是否为任意同步或异步函数类型。
|
|
307
|
+
*/
|
|
209
308
|
export const isAnyFunction = (target: unknown): target is AnyFunction => {
|
|
210
309
|
return isFunction(target)
|
|
211
310
|
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* 判断目标值是否为同步函数。
|
|
314
|
+
*/
|
|
212
315
|
export const isSyncFunction = (target: unknown): target is AnySyncFunction => {
|
|
213
316
|
return Object.prototype.toString.call(target) === "[object Function]"
|
|
214
317
|
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* 判断目标值是否为异步函数。
|
|
321
|
+
*/
|
|
215
322
|
export const isAsyncFunction = (target: unknown): target is AnyAsyncFunction => {
|
|
216
323
|
return Object.prototype.toString.call(target) === "[object AsyncFunction]"
|
|
217
324
|
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* 判断目标值是否为生成器函数。
|
|
328
|
+
*/
|
|
218
329
|
export const isGeneratorFunction = (target: unknown): target is AnyGeneratorFunction => {
|
|
219
330
|
return Object.prototype.toString.call((target)) === "[object GeneratorFunction]"
|
|
220
331
|
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* 判断目标值是否为异步生成器函数。
|
|
335
|
+
*/
|
|
221
336
|
export const isAsyncGeneratorFunction = (target: unknown): target is AnyAsyncGeneratorFunction => {
|
|
222
337
|
return Object.prototype.toString.call(target) === "[object AsyncGeneratorFunction]"
|
|
223
338
|
}
|
|
224
339
|
|
|
225
340
|
/**
|
|
341
|
+
* 判断目标值是否实现可迭代协议(iterable protocol)。
|
|
342
|
+
*
|
|
226
343
|
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol}
|
|
227
344
|
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator}
|
|
228
345
|
*/
|
|
@@ -233,6 +350,8 @@ export function isIterable<T>(target: unknown): target is Iterable<T> {
|
|
|
233
350
|
return isGeneralObject(target) && typeof (target as any)[Symbol.iterator] === "function"
|
|
234
351
|
}
|
|
235
352
|
/**
|
|
353
|
+
* 判断目标值是否实现异步可迭代协议。
|
|
354
|
+
*
|
|
236
355
|
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator}
|
|
237
356
|
*/
|
|
238
357
|
export function isAsyncIterable<T>(target: AsyncIterable<T>): target is AsyncIterable<T>
|
|
@@ -242,6 +361,8 @@ export function isAsyncIterable<T>(target: unknown): target is AsyncIterable<T>
|
|
|
242
361
|
return isGeneralObject(target) && typeof (target as any)[Symbol.asyncIterator] === "function"
|
|
243
362
|
}
|
|
244
363
|
/**
|
|
364
|
+
* 判断目标值是否实现迭代器协议(iterator protocol)。
|
|
365
|
+
*
|
|
245
366
|
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterator_protocol}
|
|
246
367
|
*/
|
|
247
368
|
export function isIterator<T, TReturn = unknown, TNext = undefined>(target: Iterator<T, TReturn, TNext>): target is Iterator<T, TReturn, TNext>
|
|
@@ -250,71 +371,31 @@ export function isIterator<T, TReturn = unknown, TNext = undefined>(target: unkn
|
|
|
250
371
|
// oxlint-disable-next-line no-unsafe-type-assertion no-unsafe-member-access
|
|
251
372
|
return isGeneralObject(target) && typeof (target as any).next === "function"
|
|
252
373
|
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* 判断目标值是否实现异步迭代器协议。
|
|
377
|
+
*/
|
|
253
378
|
export function isAsyncIterator<T, TReturn = unknown, TNext = undefined>(target: AsyncIterator<T, TReturn, TNext>): target is AsyncIterator<T, TReturn, TNext>
|
|
254
379
|
export function isAsyncIterator<T, TReturn = unknown, TNext = undefined>(target: unknown): target is AsyncIterator<T, TReturn, TNext>
|
|
255
380
|
export function isAsyncIterator<T, TReturn = unknown, TNext = undefined>(target: unknown): target is AsyncIterator<T, TReturn, TNext> {
|
|
256
381
|
// oxlint-disable-next-line no-unsafe-type-assertion no-unsafe-member-access
|
|
257
382
|
return isGeneralObject(target) && typeof (target as any).next === "function"
|
|
258
383
|
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* 判断目标值是否同时满足可迭代对象与迭代器的条件。
|
|
387
|
+
*/
|
|
259
388
|
export function isIterableIterator<T, TReturn = unknown, TNext = undefined>(target: IterableIterator<T>): target is IterableIterator<T, TReturn, TNext>
|
|
260
389
|
export function isIterableIterator<T, TReturn = unknown, TNext = undefined>(target: unknown): target is IterableIterator<T, TReturn, TNext>
|
|
261
390
|
export function isIterableIterator<T, TReturn = unknown, TNext = undefined>(target: unknown): target is IterableIterator<T> {
|
|
262
391
|
return isIterator<T, TReturn, TNext>(target) && isIterable<T>(target)
|
|
263
392
|
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* 判断目标值是否同时满足异步可迭代对象与异步迭代器的条件。
|
|
396
|
+
*/
|
|
264
397
|
export function isAsyncIterableIterator<T, TReturn = unknown, TNext = undefined>(target: AsyncIterableIterator<T>): target is AsyncIterableIterator<T, TReturn, TNext>
|
|
265
398
|
export function isAsyncIterableIterator<T, TReturn = unknown, TNext = undefined>(target: unknown): target is AsyncIterableIterator<T, TReturn, TNext>
|
|
266
399
|
export function isAsyncIterableIterator<T, TReturn = unknown, TNext = undefined>(target: unknown): target is AsyncIterableIterator<T> {
|
|
267
400
|
return isAsyncIterator<T, TReturn, TNext>(target) && isAsyncIterable<T>(target)
|
|
268
401
|
}
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Check `target` and `Window` is both defined
|
|
272
|
-
* before use the `instanceof` operator to check `target` is instanceof `Window`.
|
|
273
|
-
*/
|
|
274
|
-
export const isWindow = (target: unknown): target is Window => {
|
|
275
|
-
return isGeneralObject(target) && isDefined(Window) && target instanceof Window
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* Check `target` and `Element` is both defined
|
|
279
|
-
* before use the `instanceof` operator to check `target` is instanceof `Element`.
|
|
280
|
-
*/
|
|
281
|
-
export const isElement = (target: unknown): target is Element => {
|
|
282
|
-
return isGeneralObject(target) && isDefined(Element) && target instanceof Element
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Check `target` and `Node` is both defined
|
|
286
|
-
* before use the `instanceof` operator to check `target` is instanceof `Node`.
|
|
287
|
-
*/
|
|
288
|
-
export const isNode = (target: unknown): target is Node => {
|
|
289
|
-
return isGeneralObject(target) && isDefined(Node) && target instanceof Node
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* Check `target` and `HTMLElement` is both defined
|
|
293
|
-
* before use the `instanceof` operator to check `target` is instanceof `HTMLElement`.
|
|
294
|
-
*/
|
|
295
|
-
export const isHTMLElement = (target: unknown): target is HTMLElement => {
|
|
296
|
-
return isGeneralObject(target) && isDefined(HTMLElement) && target instanceof HTMLElement
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* Check `target` and `HTMLCollection` is both defined
|
|
300
|
-
* before use the `instanceof` operator to check `target` is instanceof `HTMLCollection`.
|
|
301
|
-
*/
|
|
302
|
-
export const isHTMLCollection = (target: unknown): target is HTMLCollection => {
|
|
303
|
-
return isGeneralObject(target) && isDefined(HTMLCollection) && target instanceof HTMLCollection
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* Check `target` and `Document` is both defined
|
|
307
|
-
* before use the `instanceof` operator to check `target` is instanceof `Document`.
|
|
308
|
-
*/
|
|
309
|
-
export const isDocument = (target: unknown): target is Document => {
|
|
310
|
-
return isGeneralObject(target) && isDefined(Document) && target instanceof Document
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* Check `target` and `EventTarget` is both defined
|
|
314
|
-
* before use the `instanceof` operator to check `target` is instanceof `EventTarget`.
|
|
315
|
-
*
|
|
316
|
-
* @see {@link https://developer.mozilla.org/zh-CN/docs/Web/API/Event}
|
|
317
|
-
*/
|
|
318
|
-
export const isEventTarget = (target: unknown): target is EventTarget => {
|
|
319
|
-
return isGeneralObject(target) && isDefined(EventTarget) && target instanceof EventTarget
|
|
320
|
-
}
|
package/src/basic/object.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AnyRecord } from "../type/index.ts"
|
|
2
|
+
import { isDate } from "./is.ts"
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Return a new object that includes only the specified keys from the source object.
|
|
@@ -56,3 +57,84 @@ export const excludeFields = <T extends AnyRecord, K extends keyof T>(
|
|
|
56
57
|
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
57
58
|
return newObject as Omit<T, K> // 使用Omit类型确保返回的类型反映了被排除的键
|
|
58
59
|
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Convert all Date fields in an object to number.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```before
|
|
66
|
+
* type Obj = {
|
|
67
|
+
* createdAt: Date,
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
* ```after
|
|
71
|
+
* type Obj = {
|
|
72
|
+
* createdAt: number,
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```before
|
|
78
|
+
* type Obj = {
|
|
79
|
+
* createdAt: Date | undefined,
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
* ```after
|
|
83
|
+
* type Obj = {
|
|
84
|
+
* createdAt: number | undefined,
|
|
85
|
+
* }
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```before
|
|
90
|
+
* type Obj = {
|
|
91
|
+
* createdAt: Date | null,
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
* ```after
|
|
95
|
+
* type Obj = {
|
|
96
|
+
* createdAt: number | null,
|
|
97
|
+
* }
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export type ObjectDateFieldsToNumber<O extends object> = {
|
|
101
|
+
[K in keyof O]: O[K] extends Date
|
|
102
|
+
? number
|
|
103
|
+
: (
|
|
104
|
+
O[K] extends Date | undefined
|
|
105
|
+
? number | undefined
|
|
106
|
+
:
|
|
107
|
+
(O[K] extends Date | null
|
|
108
|
+
? number | null
|
|
109
|
+
: (
|
|
110
|
+
O[K] extends object
|
|
111
|
+
? ObjectDateFieldsToNumber<O[K]>
|
|
112
|
+
: O[K]
|
|
113
|
+
)
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Convert all Date fields in an object to number.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```
|
|
122
|
+
* const obj = { createdAt: new Date() };
|
|
123
|
+
* const result = objectDateFieldsToNumber(obj);
|
|
124
|
+
* // Expect: { createdAt: 1712345678901 }
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export const objectDateFieldsToNumber = <O extends Record<string | number | symbol, unknown>>(
|
|
128
|
+
obj: O
|
|
129
|
+
): ObjectDateFieldsToNumber<O> => {
|
|
130
|
+
// oxlint-disable-next-line guard-for-in
|
|
131
|
+
for (const key in obj) {
|
|
132
|
+
const value = obj[key];
|
|
133
|
+
if (isDate(value)) {
|
|
134
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
135
|
+
obj[key] = value.getTime() as O[Extract<keyof O, string>]
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
139
|
+
return obj as ObjectDateFieldsToNumber<O>
|
|
140
|
+
}
|
package/src/basic/promise.ts
CHANGED
|
@@ -56,32 +56,43 @@ export const promiseFinally = async <V>(
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
const INTERNAL_PROMISE_FAIL_RESULT_TYPE: symbol = Symbol("fail")
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 表示标准化的 Promise 失败结果。
|
|
62
|
+
*/
|
|
59
63
|
export interface PromiseFailResult {
|
|
60
64
|
__type__: typeof INTERNAL_PROMISE_FAIL_RESULT_TYPE
|
|
61
65
|
reason: unknown
|
|
62
66
|
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 表示带原始下标信息的 Promise 失败结果。
|
|
70
|
+
*/
|
|
63
71
|
export interface PromiseIndexedFailResult extends PromiseFailResult {
|
|
64
72
|
index: number
|
|
65
73
|
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 根据拒因构造标准化的 Promise 失败结果。
|
|
77
|
+
*/
|
|
66
78
|
export const promiseConstructFailResult = (reason: unknown): PromiseFailResult => {
|
|
67
79
|
return { __type__: INTERNAL_PROMISE_FAIL_RESULT_TYPE, reason }
|
|
68
80
|
}
|
|
69
81
|
/**
|
|
70
|
-
*
|
|
82
|
+
* 判断目标值是否为标准化的 Promise 失败结果。
|
|
71
83
|
*/
|
|
72
84
|
export const isPromiseFailResult = (target: unknown): target is PromiseFailResult => {
|
|
73
85
|
return isPlainObject(target) && target["__type__"] === INTERNAL_PROMISE_FAIL_RESULT_TYPE
|
|
74
86
|
}
|
|
75
87
|
/**
|
|
76
|
-
*
|
|
77
|
-
* to return a standard `PromiseFailResult`.
|
|
88
|
+
* 用作 `Promise.catch` 的 `onrejected` 回调,并返回标准化失败结果。
|
|
78
89
|
*/
|
|
79
90
|
export const promiseCatchToFailResult = (reason: unknown): PromiseFailResult => {
|
|
80
91
|
return { __type__: INTERNAL_PROMISE_FAIL_RESULT_TYPE, reason }
|
|
81
92
|
}
|
|
82
93
|
|
|
83
94
|
/**
|
|
84
|
-
*
|
|
95
|
+
* 从结果数组中过滤出非 `PromiseFailResult` 项。
|
|
85
96
|
*/
|
|
86
97
|
export const promiseFilterSuccessResults = <V>(
|
|
87
98
|
results: Array<V | PromiseFailResult>,
|
|
@@ -93,8 +104,7 @@ export const promiseFilterSuccessResults = <V>(
|
|
|
93
104
|
return filtered as V[]
|
|
94
105
|
}
|
|
95
106
|
/**
|
|
96
|
-
*
|
|
97
|
-
* which indicate the index of the item in the original array.
|
|
107
|
+
* 从结果数组中过滤出失败项,并补充其原始下标。
|
|
98
108
|
*/
|
|
99
109
|
export const promiseFilterFailResults = <V>(
|
|
100
110
|
results: Array<V | PromiseFailResult>,
|
|
@@ -125,8 +135,12 @@ type PromiseQueueFirstPromiseMaker<T, S = unknown> = (context: PromiseQueueFirst
|
|
|
125
135
|
type PromiseQueueRestPromiseMaker<T, S = unknown> = (context: PromiseQueueRestPromiseMakerContext<T, S>) => Promise<T>
|
|
126
136
|
type PromiseQueuePromiseMakers<T, S = unknown> = [
|
|
127
137
|
PromiseQueueFirstPromiseMaker<T, S>,
|
|
128
|
-
...PromiseQueueRestPromiseMaker<T, S
|
|
138
|
+
...Array<PromiseQueueRestPromiseMaker<T, S>>
|
|
129
139
|
]
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* `promiseQueue` 的配置项。
|
|
143
|
+
*/
|
|
130
144
|
export interface PromiseQueueOptions {
|
|
131
145
|
/**
|
|
132
146
|
* @default 0
|
|
@@ -204,6 +218,10 @@ interface PromiseRetryRestPromiseMakerContext<T, S = unknown> {
|
|
|
204
218
|
type PromiseRetryPromiseMaker<T, S = unknown> = (
|
|
205
219
|
context: PromiseRetryFirstPromiseMakerContext<S> | PromiseRetryRestPromiseMakerContext<T, S>
|
|
206
220
|
) => Promise<T>
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* `promiseRetryWhile` 与 `promiseRetryUntil` 的配置项。
|
|
224
|
+
*/
|
|
207
225
|
export interface PromiseRetryOptions {
|
|
208
226
|
/**
|
|
209
227
|
* @default 0
|
|
@@ -387,6 +405,10 @@ interface PromiseForeverRestPromiseMakerContext<T, S = unknown> {
|
|
|
387
405
|
type PromiseForeverPromiseMaker<T, S = unknown> = (
|
|
388
406
|
context: PromiseForeverFirstPromiseMakerContext<S> | PromiseForeverRestPromiseMakerContext<T, S>
|
|
389
407
|
) => Promise<T>
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* `promiseForever` 的配置项。
|
|
411
|
+
*/
|
|
390
412
|
export interface PromiseForeverOptions {
|
|
391
413
|
/**
|
|
392
414
|
* @default 0
|
|
@@ -441,7 +463,6 @@ export const promiseForever = <T, S = unknown>(
|
|
|
441
463
|
context: PromiseForeverFirstPromiseMakerContext<S> | PromiseForeverRestPromiseMakerContext<T, S>
|
|
442
464
|
): void => {
|
|
443
465
|
void promiseMaker(context)
|
|
444
|
-
// oxlint-disable-next-line prefer-await-to-callbacks
|
|
445
466
|
.catch((error: unknown) => {
|
|
446
467
|
const failedResult = promiseCatchToFailResult(error)
|
|
447
468
|
if (onRejected !== undefined) {
|
package/src/basic/string.ts
CHANGED
|
@@ -1,34 +1,3 @@
|
|
|
1
|
-
const internalRandomPacket: Record<number, string[]> = {}
|
|
2
|
-
/**
|
|
3
|
-
* Generate a random string with a fixed length and optional character set.
|
|
4
|
-
*
|
|
5
|
-
* @example
|
|
6
|
-
* ```
|
|
7
|
-
* // Expect: 8
|
|
8
|
-
* const example1 = stringRandom(8).length
|
|
9
|
-
* // Expect: true
|
|
10
|
-
* const example2 = stringRandom(4, "ab").split("").every(char => char === "a" || char === "b")
|
|
11
|
-
* ```
|
|
12
|
-
*/
|
|
13
|
-
export const stringRandom = (length: number, chars?: string | undefined): string => {
|
|
14
|
-
let result = ""
|
|
15
|
-
const preparedChars = chars ?? "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
16
|
-
|
|
17
|
-
Array.from({ length }).forEach(() => {
|
|
18
|
-
result = result + preparedChars[Math.floor(Math.random() * preparedChars.length)]!
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
internalRandomPacket[length] = internalRandomPacket[length] ?? []
|
|
22
|
-
const packet = internalRandomPacket[length]
|
|
23
|
-
if (packet.includes(result)) {
|
|
24
|
-
return stringRandom(length, preparedChars)
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
packet.push(result)
|
|
28
|
-
return result
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
1
|
/**
|
|
33
2
|
* Convert a camelCase string into kebab-case.
|
|
34
3
|
*
|
|
@@ -177,8 +146,8 @@ export const stringSliceByUnits = (text: string, start: number, end: number): st
|
|
|
177
146
|
|
|
178
147
|
export interface StringSplitOptions {
|
|
179
148
|
input: string
|
|
180
|
-
chunkSize
|
|
181
|
-
chunkOverlap
|
|
149
|
+
chunkSize?: number | undefined
|
|
150
|
+
chunkOverlap?: number | undefined
|
|
182
151
|
}
|
|
183
152
|
|
|
184
153
|
/**
|