@planet-matrix/mobius-model 0.3.0 → 0.5.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 +15 -0
- package/README.md +30 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +22 -4
- package/package.json +3 -3
- package/scripts/build.ts +4 -4
- package/src/basic/README.md +144 -0
- package/src/basic/array.ts +872 -0
- package/src/basic/bigint.ts +114 -0
- package/src/basic/boolean.ts +180 -0
- package/src/basic/enhance.ts +10 -0
- package/src/basic/error.ts +51 -0
- package/src/basic/function.ts +453 -0
- package/src/basic/helper.ts +276 -0
- package/src/basic/index.ts +17 -0
- package/src/basic/is.ts +320 -0
- package/src/basic/number.ts +178 -0
- package/src/basic/object.ts +140 -0
- package/src/basic/promise.ts +464 -0
- package/src/basic/regexp.ts +7 -0
- package/src/basic/stream.ts +140 -0
- package/src/basic/string.ts +308 -0
- package/src/basic/symbol.ts +164 -0
- package/src/basic/temporal.ts +224 -0
- package/src/encoding/README.md +105 -0
- package/src/encoding/base64.ts +98 -0
- package/src/encoding/index.ts +1 -0
- package/src/index.ts +4 -0
- package/src/random/README.md +109 -0
- package/src/random/index.ts +1 -0
- package/src/random/uuid.ts +103 -0
- package/src/type/README.md +330 -0
- package/src/type/array.ts +5 -0
- package/src/type/boolean.ts +471 -0
- package/src/type/class.ts +419 -0
- package/src/type/function.ts +1519 -0
- package/src/type/helper.ts +135 -0
- package/src/type/index.ts +14 -0
- package/src/type/intersection.ts +93 -0
- package/src/type/is.ts +247 -0
- package/src/type/iteration.ts +233 -0
- package/src/type/number.ts +732 -0
- package/src/type/object.ts +788 -0
- package/src/type/path.ts +73 -0
- package/src/type/string.ts +1004 -0
- package/src/type/tuple.ts +2424 -0
- package/src/type/union.ts +108 -0
- package/tests/unit/basic/array.spec.ts +290 -0
- package/tests/unit/basic/bigint.spec.ts +50 -0
- package/tests/unit/basic/boolean.spec.ts +74 -0
- package/tests/unit/basic/error.spec.ts +32 -0
- package/tests/unit/basic/function.spec.ts +175 -0
- package/tests/unit/basic/helper.spec.ts +118 -0
- package/tests/unit/basic/number.spec.ts +74 -0
- package/tests/unit/basic/object.spec.ts +46 -0
- package/tests/unit/basic/promise.spec.ts +232 -0
- package/tests/unit/basic/regexp.spec.ts +11 -0
- package/tests/unit/basic/stream.spec.ts +120 -0
- package/tests/unit/basic/string.spec.ts +74 -0
- package/tests/unit/basic/symbol.spec.ts +72 -0
- package/tests/unit/basic/temporal.spec.ts +78 -0
- package/tests/unit/encoding/base64.spec.ts +40 -0
- package/tests/unit/random/uuid.spec.ts +37 -0
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/reactor/index.d.ts +0 -3
- package/dist/reactor/index.d.ts.map +0 -1
- package/dist/reactor/reactor-core/flags.d.ts +0 -99
- package/dist/reactor/reactor-core/flags.d.ts.map +0 -1
- package/dist/reactor/reactor-core/index.d.ts +0 -4
- package/dist/reactor/reactor-core/index.d.ts.map +0 -1
- package/dist/reactor/reactor-core/primitive.d.ts +0 -276
- package/dist/reactor/reactor-core/primitive.d.ts.map +0 -1
- package/dist/reactor/reactor-core/reactive-system.d.ts +0 -241
- package/dist/reactor/reactor-core/reactive-system.d.ts.map +0 -1
- package/dist/reactor/reactor-operators/branch.d.ts +0 -19
- package/dist/reactor/reactor-operators/branch.d.ts.map +0 -1
- package/dist/reactor/reactor-operators/convert.d.ts +0 -30
- package/dist/reactor/reactor-operators/convert.d.ts.map +0 -1
- package/dist/reactor/reactor-operators/create.d.ts +0 -26
- package/dist/reactor/reactor-operators/create.d.ts.map +0 -1
- package/dist/reactor/reactor-operators/filter.d.ts +0 -269
- package/dist/reactor/reactor-operators/filter.d.ts.map +0 -1
- package/dist/reactor/reactor-operators/index.d.ts +0 -8
- package/dist/reactor/reactor-operators/index.d.ts.map +0 -1
- package/dist/reactor/reactor-operators/join.d.ts +0 -48
- package/dist/reactor/reactor-operators/join.d.ts.map +0 -1
- package/dist/reactor/reactor-operators/map.d.ts +0 -165
- package/dist/reactor/reactor-operators/map.d.ts.map +0 -1
- package/dist/reactor/reactor-operators/utility.d.ts +0 -48
- package/dist/reactor/reactor-operators/utility.d.ts.map +0 -1
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize a value to a 0-1 range based on min and max.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```
|
|
6
|
+
* // Expect: 0.5
|
|
7
|
+
* const example1 = normalize(5, 0, 10)
|
|
8
|
+
* // Expect: 0
|
|
9
|
+
* const example2 = normalize(2, 2, 6)
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export const normalize = (value: number, min: number, max: number): number => {
|
|
13
|
+
if (min === max) {
|
|
14
|
+
throw new Error("Min and max value are the same.")
|
|
15
|
+
}
|
|
16
|
+
if (value < min || value > max) {
|
|
17
|
+
throw new Error(`Value ${value} is not in the range of ${min} to ${max}.`)
|
|
18
|
+
}
|
|
19
|
+
return (value - min) / (max - min)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Check if a number is even.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```
|
|
27
|
+
* // Expect: true
|
|
28
|
+
* const example1 = isEven(10)
|
|
29
|
+
* // Expect: false
|
|
30
|
+
* const example2 = isEven(7)
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export const isEven = (x: number): boolean => x % 2 === 0
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Check if a number is odd.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```
|
|
40
|
+
* // Expect: true
|
|
41
|
+
* const example1 = isOdd(7)
|
|
42
|
+
* // Expect: false
|
|
43
|
+
* const example2 = isOdd(10)
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export const isOdd = (x: number): boolean => x % 2 !== 0
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Clamp a number to a maximum value.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```
|
|
53
|
+
* // Expect: 5
|
|
54
|
+
* const example1 = maxTo(5, 10)
|
|
55
|
+
* // Expect: 3
|
|
56
|
+
* const example2 = maxTo(5, 3)
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export const maxTo = (max: number, x: number): number => x > max ? max : x
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Clamp a number to a minimum value.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```
|
|
66
|
+
* // Expect: 5
|
|
67
|
+
* const example1 = minTo(5, 3)
|
|
68
|
+
* // Expect: 8
|
|
69
|
+
* const example2 = minTo(5, 8)
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export const minTo = (min: number, x: number): number => x < min ? min : x
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get the smaller of two numbers.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```
|
|
79
|
+
* // Expect: 2
|
|
80
|
+
* const example1 = minOf(2, 9)
|
|
81
|
+
* // Expect: -1
|
|
82
|
+
* const example2 = minOf(5, -1)
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export const minOf = (x: number, y: number): number => x < y ? x : y
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get the larger of two numbers.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```
|
|
92
|
+
* // Expect: 9
|
|
93
|
+
* const example1 = maxOf(2, 9)
|
|
94
|
+
* // Expect: 5
|
|
95
|
+
* const example2 = maxOf(5, -1)
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export const maxOf = (x: number, y: number): number => x > y ? x : y
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Clamp a number between two bounds.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```
|
|
105
|
+
* // Expect: 5
|
|
106
|
+
* const example1 = between(0, 10, 5)
|
|
107
|
+
* // Expect: 0
|
|
108
|
+
* const example2 = between(0, 10, -3)
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export const between = (a: number, b: number, x: number): number => {
|
|
112
|
+
const min = minOf(a, b)
|
|
113
|
+
const max = maxOf(a, b)
|
|
114
|
+
return x < min ? min : (x > max ? max : x)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Get a random integer between min and max, inclusive.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```
|
|
122
|
+
* // Expect: 4
|
|
123
|
+
* const example1 = randomBetween(4, 4)
|
|
124
|
+
* // Expect: 10
|
|
125
|
+
* const example2 = randomBetween(10, 10)
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export const randomBetween = (min: number, max: number): number => {
|
|
129
|
+
return Math.floor(Math.random() * (max - min + 1) + min)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Get a random integer between two values, regardless of order, inclusive.
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```
|
|
137
|
+
* // Expect: 4
|
|
138
|
+
* const example1 = randomIntBetween(4, 4)
|
|
139
|
+
* // Expect: 10
|
|
140
|
+
* const example2 = randomIntBetween(10, 10)
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
export const randomIntBetween = (a: number, b: number): number => {
|
|
144
|
+
const min = minOf(a, b)
|
|
145
|
+
const max = maxOf(a, b)
|
|
146
|
+
return Math.floor(Math.random() * (max - min + 1)) + min
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export interface NumberConstraints {
|
|
150
|
+
min?: number | undefined
|
|
151
|
+
max?: number | undefined
|
|
152
|
+
step?: number | undefined
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Constrain a number by step size and min/max bounds.
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```
|
|
160
|
+
* // Expect: 10
|
|
161
|
+
* const example1 = constrainNumber(12, { step: 5, max: 10 })
|
|
162
|
+
* // Expect: 3
|
|
163
|
+
* const example2 = constrainNumber(2.6, { step: 0.5, min: 3 })
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
export const constrainNumber = (value: number, constraints: NumberConstraints): number => {
|
|
167
|
+
let constrainedValue = value
|
|
168
|
+
if (constraints.step !== undefined) {
|
|
169
|
+
constrainedValue = Math.round(constrainedValue / constraints.step) * constraints.step
|
|
170
|
+
}
|
|
171
|
+
if (constraints.min !== undefined) {
|
|
172
|
+
constrainedValue = Math.max(constraints.min, constrainedValue)
|
|
173
|
+
}
|
|
174
|
+
if (constraints.max !== undefined) {
|
|
175
|
+
constrainedValue = Math.min(constraints.max, constrainedValue)
|
|
176
|
+
}
|
|
177
|
+
return constrainedValue
|
|
178
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { AnyRecord } from "../type/index.ts"
|
|
2
|
+
import { isDate } from "./is.ts"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Return a new object that includes only the specified keys from the source object.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```
|
|
9
|
+
* // Expect: { a: 1, c: 3 }
|
|
10
|
+
* const example1 = includeFields({ a: 1, b: 2, c: 3 }, ["a", "c"])
|
|
11
|
+
* // Expect: {}
|
|
12
|
+
* const example2 = includeFields(null, ["a"])
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export const includeFields = <T extends AnyRecord, K extends keyof T>(
|
|
16
|
+
object: T | null | undefined,
|
|
17
|
+
keys: K[],
|
|
18
|
+
): Pick<T, K> => {
|
|
19
|
+
if (object === null || object === undefined) {
|
|
20
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
21
|
+
return {} as Pick<T, K>
|
|
22
|
+
}
|
|
23
|
+
const newObject: Partial<Pick<T, K>> = {} // 初始化一个部分类型的对象
|
|
24
|
+
keys.forEach((key) => {
|
|
25
|
+
if (key in object) {
|
|
26
|
+
newObject[key] = object[key]
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
30
|
+
return newObject as Pick<T, K> // 使用正确的变量名并断言返回类型
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Return a new object that excludes the specified keys from the source object.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```
|
|
38
|
+
* // Expect: { a: 1 }
|
|
39
|
+
* const example1 = excludeFields({ a: 1, b: 2 }, ["b"])
|
|
40
|
+
* // Expect: {}
|
|
41
|
+
* const example2 = excludeFields(undefined, ["a"])
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export const excludeFields = <T extends AnyRecord, K extends keyof T>(
|
|
45
|
+
object: T | null | undefined,
|
|
46
|
+
keys: K[],
|
|
47
|
+
): Omit<T, K> => {
|
|
48
|
+
if (object === null || object === undefined) {
|
|
49
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
50
|
+
return {} as Omit<T, K>
|
|
51
|
+
}
|
|
52
|
+
const newObject: Partial<T> = { ...object } // 创建原对象的浅拷贝
|
|
53
|
+
keys.forEach((key) => {
|
|
54
|
+
// oxlint-disable-next-line no-dynamic-delete
|
|
55
|
+
delete newObject[key] // 删除指定的键
|
|
56
|
+
})
|
|
57
|
+
// oxlint-disable-next-line no-unsafe-type-assertion
|
|
58
|
+
return newObject as Omit<T, K> // 使用Omit类型确保返回的类型反映了被排除的键
|
|
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
|
+
}
|