@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,108 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Helpers
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Strict version of builtin `Extract`, `U` must be subset of `T`.
|
|
7
|
+
*/
|
|
8
|
+
export type StrictExtract<T, U extends T> = Extract<T, U>
|
|
9
|
+
/**
|
|
10
|
+
* Strict version of builtin `Exclude`, `U` must be subset of `T`.
|
|
11
|
+
*/
|
|
12
|
+
export type StrictExclude<T, U extends T> = Exclude<T, U>
|
|
13
|
+
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Manipulation
|
|
16
|
+
// ============================================================================
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @example
|
|
20
|
+
* ```
|
|
21
|
+
* // Expect: "2" | "3"
|
|
22
|
+
* UnionIntersection<'1' | '2' | '3', '2' | '3' | '4'>;
|
|
23
|
+
*
|
|
24
|
+
* // Expect: () => void
|
|
25
|
+
* UnionIntersection<string | number | (() => void), Function>;
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export type UnionIntersection<UnionA, UnionB> = UnionA extends UnionB ? UnionA : never
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @example
|
|
32
|
+
* ```
|
|
33
|
+
* // Expect: "1"
|
|
34
|
+
* UnionDifference<'1' | '2' | '3', '2' | '3' | '4'>;
|
|
35
|
+
*
|
|
36
|
+
* // Expect: string | number
|
|
37
|
+
* UnionDifference<string | number | (() => void), Function>;
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export type UnionDifference<UnionA, UnionB> = UnionA extends UnionB ? never : UnionA
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @example
|
|
44
|
+
* ```
|
|
45
|
+
* // Expect: "1"
|
|
46
|
+
* UnionComplement<'1' | '2' | '3', '2' | '3'>;
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export type UnionComplement<Union, SubUnion extends Union> = UnionDifference<Union, SubUnion>
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @example
|
|
53
|
+
* ```
|
|
54
|
+
* // Expect: "1" | "4"
|
|
55
|
+
* UnionSymmetricDifference<'1' | '2' | '3', '2' | '3' | '4'>;
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export type UnionSymmetricDifference<UnionA, UnionB> = UnionDifference<UnionA | UnionB, UnionA & UnionB>
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @example
|
|
62
|
+
* ```
|
|
63
|
+
* // Expect: "c"
|
|
64
|
+
* type Result = LastOfUnion<'a' | 'b' | 'c'>
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export type LastOfUnion<Union> = UnionToIntersection<
|
|
68
|
+
Union extends unknown ? (x: Union) => void : never
|
|
69
|
+
> extends (x: infer L) => void ? L : never
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @example
|
|
73
|
+
* ```
|
|
74
|
+
* // Expect: "a" | "b"
|
|
75
|
+
* type Result = UnionPop<'a' | 'b' | 'c'>
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export type UnionPop<U> = Exclude<U, LastOfUnion<U>>
|
|
79
|
+
|
|
80
|
+
// ============================================================================
|
|
81
|
+
// Conversion
|
|
82
|
+
// ============================================================================
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @example
|
|
86
|
+
* ```
|
|
87
|
+
* // Expect: { name: string } & { age: number } & { visible: boolean }
|
|
88
|
+
* UnionToIntersection<{ name: string } | { age: number } | { visible: boolean }>
|
|
89
|
+
* ```
|
|
90
|
+
* @see {@link https://stackoverflow.com/a/50375286/7381355}
|
|
91
|
+
*/
|
|
92
|
+
export type UnionToIntersection<Union> = (Union extends unknown
|
|
93
|
+
? (_: Union) => void
|
|
94
|
+
: never
|
|
95
|
+
) extends (_: infer Result) => void ? Result : never
|
|
96
|
+
|
|
97
|
+
type InternalUnionToTuple<U, T extends unknown[]> =
|
|
98
|
+
[U] extends [never]
|
|
99
|
+
? T
|
|
100
|
+
: InternalUnionToTuple<Exclude<U, LastOfUnion<U>>, [LastOfUnion<U>, ...T]>
|
|
101
|
+
/**
|
|
102
|
+
* @example
|
|
103
|
+
* ```
|
|
104
|
+
* // Expect: ["1", "2", "3"]
|
|
105
|
+
* type Example = UnionToTuple<'1' | '2' | '3'>
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export type UnionToTuple<U> = InternalUnionToTuple<U, []>
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { expect, test } from "vitest"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
arrayAdjust,
|
|
5
|
+
arrayAll,
|
|
6
|
+
arrayAny,
|
|
7
|
+
arrayAppend,
|
|
8
|
+
arrayConcat,
|
|
9
|
+
arrayDrop,
|
|
10
|
+
arrayDropLast,
|
|
11
|
+
arrayEvery,
|
|
12
|
+
arrayFilter,
|
|
13
|
+
arrayFlat,
|
|
14
|
+
arrayFlatMap,
|
|
15
|
+
arrayForEach,
|
|
16
|
+
arrayFromSpread,
|
|
17
|
+
arrayHead,
|
|
18
|
+
arrayIncludes,
|
|
19
|
+
arrayIndexOf,
|
|
20
|
+
arrayInit,
|
|
21
|
+
arrayIntersection,
|
|
22
|
+
arrayJoin,
|
|
23
|
+
arrayLast,
|
|
24
|
+
arrayLastIndexOf,
|
|
25
|
+
arrayLength,
|
|
26
|
+
arrayMap,
|
|
27
|
+
arrayPartition,
|
|
28
|
+
arrayPop,
|
|
29
|
+
arrayPrepend,
|
|
30
|
+
arrayPush,
|
|
31
|
+
arrayReduce,
|
|
32
|
+
arrayReduceLeft,
|
|
33
|
+
arrayReduceRight,
|
|
34
|
+
arrayReject,
|
|
35
|
+
arrayRemove,
|
|
36
|
+
arrayRemoveIndex,
|
|
37
|
+
arrayReverse,
|
|
38
|
+
arrayShift,
|
|
39
|
+
arraySlice,
|
|
40
|
+
arraySliceInit,
|
|
41
|
+
arraySliceTail,
|
|
42
|
+
arraySome,
|
|
43
|
+
arraySort,
|
|
44
|
+
arrayTail,
|
|
45
|
+
arrayUnion,
|
|
46
|
+
arrayUnique,
|
|
47
|
+
arrayUniqueBy,
|
|
48
|
+
arrayUnshift,
|
|
49
|
+
arrayUpdate,
|
|
50
|
+
shuffle,
|
|
51
|
+
} from "#Source/basic/index.ts"
|
|
52
|
+
|
|
53
|
+
test("arrayFromSpread converts iterables", () => {
|
|
54
|
+
expect(arrayFromSpread(new Set([1, 2, 3]))).toEqual([1, 2, 3])
|
|
55
|
+
expect(arrayFromSpread([])).toEqual([])
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test("arrayLength returns array length", () => {
|
|
59
|
+
expect(arrayLength(["a", "b", "c"])).toBe(3)
|
|
60
|
+
expect(arrayLength([])).toBe(0)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test("arrayPop removes the last item", () => {
|
|
64
|
+
expect(arrayPop([1, 2, 3])).toEqual([1, 2])
|
|
65
|
+
expect(arrayPop(["only"])).toEqual([])
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test("arrayPush appends an item", () => {
|
|
69
|
+
expect(arrayPush(3, [1, 2])).toEqual([1, 2, 3])
|
|
70
|
+
expect(arrayPush("a", [])).toEqual(["a"])
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test("arrayAppend aliases arrayPush", () => {
|
|
74
|
+
expect(arrayAppend(2, [1])).toEqual([1, 2])
|
|
75
|
+
expect(arrayAppend("x", [])).toEqual(["x"])
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test("arrayUnshift prepends an item", () => {
|
|
79
|
+
expect(arrayUnshift(0, [1, 2])).toEqual([0, 1, 2])
|
|
80
|
+
expect(arrayUnshift("a", [])).toEqual(["a"])
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test("arrayPrepend aliases arrayUnshift", () => {
|
|
84
|
+
expect(arrayPrepend("first", ["second"])).toEqual(["first", "second"])
|
|
85
|
+
expect(arrayPrepend(true, [])).toEqual([true])
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
test("arrayShift removes the first item", () => {
|
|
89
|
+
expect(arrayShift([1, 2, 3])).toEqual([2, 3])
|
|
90
|
+
expect(arrayShift(["only"])).toEqual([])
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
test("arrayHead returns the first element", () => {
|
|
94
|
+
expect(arrayHead([1, 2, 3])).toBe(1)
|
|
95
|
+
expect(arrayHead([])).toBeUndefined()
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
test("arrayTail returns all but the first element", () => {
|
|
99
|
+
expect(arrayTail([1, 2, 3])).toEqual([2, 3])
|
|
100
|
+
expect(arrayTail(["only"])).toEqual([])
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
test("arrayInit returns all but the last element", () => {
|
|
104
|
+
expect(arrayInit([1, 2, 3])).toEqual([1, 2])
|
|
105
|
+
expect(arrayInit(["only"])).toEqual([])
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
test("arrayLast returns the last element", () => {
|
|
109
|
+
expect(arrayLast([1, 2, 3])).toBe(3)
|
|
110
|
+
expect(arrayLast([])).toBeUndefined()
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
test("arraySlice returns a portion of the array", () => {
|
|
114
|
+
expect(arraySlice(1, 3, ["a", "b", "c", "d"])).toEqual(["b", "c"])
|
|
115
|
+
expect(arraySlice(2, 2, [1, 2, 3])).toEqual([])
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
test("arraySliceTail returns a tail slice", () => {
|
|
119
|
+
expect(arraySliceTail(2, [1, 2, 3, 4])).toEqual([3, 4])
|
|
120
|
+
expect(arraySliceTail(1, ["only"])).toEqual([])
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test("arrayDrop drops a rounded count", () => {
|
|
124
|
+
expect(arrayDrop(2, [1, 2, 3, 4])).toEqual([3, 4])
|
|
125
|
+
expect(arrayDrop(-2, [1, 2])).toEqual([])
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
test("arraySliceInit returns a head slice", () => {
|
|
129
|
+
expect(arraySliceInit(2, [1, 2, 3, 4])).toEqual([1, 2])
|
|
130
|
+
expect(arraySliceInit(0, [1, 2])).toEqual([])
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
test("arrayDropLast drops elements from the end", () => {
|
|
134
|
+
expect(arrayDropLast(2, [1, 2, 3, 4])).toEqual([1, 2])
|
|
135
|
+
expect(arrayDropLast(3, [1, 2])).toEqual([])
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
test("arrayRemove removes a range", () => {
|
|
139
|
+
expect(arrayRemove(1, 3, ["a", "b", "c", "d"])).toEqual(["a", "d"])
|
|
140
|
+
expect(arrayRemove(3, 1, [1, 2, 3, 4])).toEqual([1, 4])
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
test("arrayRemoveIndex removes a single index", () => {
|
|
144
|
+
expect(arrayRemoveIndex(1, ["a", "b", "c"])).toEqual(["a", "c"])
|
|
145
|
+
expect(arrayRemoveIndex(0, ["only"])).toEqual([])
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
test("arrayConcat appends arrays", () => {
|
|
149
|
+
expect(arrayConcat([3, 4], [1, 2])).toEqual([1, 2, 3, 4])
|
|
150
|
+
expect(arrayConcat([], ["a"])).toEqual(["a"])
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
test("arrayJoin joins elements", () => {
|
|
154
|
+
expect(arrayJoin(",", ["a", "b", "c"])).toBe("a,b,c")
|
|
155
|
+
expect(arrayJoin("-", [])).toBe("")
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
test("arrayIndexOf finds the first index", () => {
|
|
159
|
+
expect(arrayIndexOf("b", ["a", "b", "c"])).toBe(1)
|
|
160
|
+
expect(arrayIndexOf(9, [1, 2, 3])).toBe(-1)
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
test("arrayLastIndexOf finds the last index", () => {
|
|
164
|
+
expect(arrayLastIndexOf("a", ["a", "b", "a"])).toBe(2)
|
|
165
|
+
expect(arrayLastIndexOf(9, [1, 2, 3])).toBe(-1)
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
test("arrayIncludes checks membership", () => {
|
|
169
|
+
expect(arrayIncludes(2, [1, 2, 3])).toBe(true)
|
|
170
|
+
expect(arrayIncludes("x", ["a", "b"])).toBe(false)
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
test("arrayEvery verifies all items", () => {
|
|
174
|
+
expect(arrayEvery((item) => item > 0, [1, 2, 3])).toBe(true)
|
|
175
|
+
expect(arrayEvery((item) => item > 1, [1, 2, 3])).toBe(false)
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
test("arrayAll aliases arrayEvery", () => {
|
|
179
|
+
expect(arrayAll((item) => item !== null, [1, 2])).toBe(true)
|
|
180
|
+
expect(arrayAll((item) => item === 0, [0, 1])).toBe(false)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
test("arraySome verifies at least one item", () => {
|
|
184
|
+
expect(arraySome((item) => item > 2, [1, 2, 3])).toBe(true)
|
|
185
|
+
expect(arraySome((item) => item < 0, [1, 2, 3])).toBe(false)
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
test("arrayAny aliases arraySome", () => {
|
|
189
|
+
expect(arrayAny((item) => item === "b", ["a", "b"])).toBe(true)
|
|
190
|
+
expect(arrayAny((item) => item === "x", ["a", "b"])).toBe(false)
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
test("arrayForEach applies the callback", () => {
|
|
194
|
+
const target: number[] = []
|
|
195
|
+
arrayForEach((item) => target.push(item * 2), [1, 2, 3])
|
|
196
|
+
expect(target).toEqual([2, 4, 6])
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
test("arrayFilter keeps matching elements", () => {
|
|
200
|
+
expect(arrayFilter((item) => item % 2 === 0, [1, 2, 3, 4])).toEqual([2, 4])
|
|
201
|
+
expect(arrayFilter((item) => item > 0, [])).toEqual([])
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
test("arrayReject removes matching elements", () => {
|
|
205
|
+
expect(arrayReject((item) => item % 2 === 0, [1, 2, 3, 4])).toEqual([1, 3])
|
|
206
|
+
expect(arrayReject((item) => item === "b", ["a", "b"])).toEqual(["a"])
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
test("arrayPartition splits by predicate", () => {
|
|
210
|
+
expect(arrayPartition((item) => item % 2 === 0, [1, 2, 3, 4])).toEqual([[2, 4], [1, 3]])
|
|
211
|
+
expect(arrayPartition((item) => item === "b", ["a"])).toEqual([[], ["a"]])
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
test("arrayMap transforms values", () => {
|
|
215
|
+
expect(arrayMap((item) => item * 2, [1, 2, 3])).toEqual([2, 4, 6])
|
|
216
|
+
expect(arrayMap((item) => item, [])).toEqual([])
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
test("arrayFlat flattens to specified depth", () => {
|
|
220
|
+
expect(arrayFlat(1, [1, [2, 3], [4]])).toEqual([1, 2, 3, 4])
|
|
221
|
+
expect(arrayFlat(2, [1, [[2]]])).toEqual([1, 2])
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
test("arrayFlatMap maps and flattens", () => {
|
|
225
|
+
expect(arrayFlatMap((item) => [item, item], [1, 2])).toEqual([1, 1, 2, 2])
|
|
226
|
+
expect(arrayFlatMap((item) => [item], [])).toEqual([])
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
test("arrayReduce aggregates left to right", () => {
|
|
230
|
+
expect(arrayReduce((acc, item) => acc + item, 0, [1, 2, 3])).toBe(6)
|
|
231
|
+
expect(arrayReduce((acc, item) => acc + item, "", ["a", "b", "c"])).toBe("abc")
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
test("arrayReduceLeft aliases arrayReduce", () => {
|
|
235
|
+
expect(arrayReduceLeft((acc, item) => acc + item, 0, [1, 2, 3])).toBe(6)
|
|
236
|
+
expect(arrayReduceLeft((acc, item) => acc + item, "", ["a", "b"])).toBe("ab")
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
test("arrayReduceRight aggregates right to left", () => {
|
|
240
|
+
expect(arrayReduceRight((acc, item) => acc + item, "", ["a", "b", "c"])).toBe("cba")
|
|
241
|
+
expect(arrayReduceRight((acc, item) => acc + item, 0, [1, 2, 3])).toBe(6)
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
test("arrayUnique removes duplicates", () => {
|
|
245
|
+
expect(arrayUnique([1, 2, 1, 3])).toEqual([1, 2, 3])
|
|
246
|
+
expect(arrayUnique(["a", "a"])).toEqual(["a"])
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
test("arrayUniqueBy removes duplicates by key", () => {
|
|
250
|
+
const input = [{ id: 1 }, { id: 1 }, { id: 2 }]
|
|
251
|
+
expect(arrayUniqueBy((item) => item.id, input)).toEqual([{ id: 1 }, { id: 2 }])
|
|
252
|
+
expect(arrayUniqueBy((item) => item, [])).toEqual([])
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
test("arrayUnion combines unique values", () => {
|
|
256
|
+
expect(arrayUnion([1, 2], [2, 3])).toEqual([1, 2, 3])
|
|
257
|
+
expect(arrayUnion(["a"], [])).toEqual(["a"])
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
test("arrayIntersection finds common values", () => {
|
|
261
|
+
expect(arrayIntersection([1, 2], [2, 3])).toEqual([2])
|
|
262
|
+
expect(arrayIntersection(["a"], ["b"])).toEqual([])
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
test("arrayReverse returns reversed copy", () => {
|
|
266
|
+
expect(arrayReverse([1, 2, 3])).toEqual([3, 2, 1])
|
|
267
|
+
expect(arrayReverse([])).toEqual([])
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
test("arraySort sorts with compare function", () => {
|
|
271
|
+
expect(arraySort((a, b) => a - b, [3, 1, 2])).toEqual([1, 2, 3])
|
|
272
|
+
expect(arraySort((a, b) => a.localeCompare(b), ["b", "a"])).toEqual(["a", "b"])
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
test("shuffle preserves elements", () => {
|
|
276
|
+
const input = [1, 2, 3, 4]
|
|
277
|
+
const result = shuffle(input)
|
|
278
|
+
expect(result).toHaveLength(4)
|
|
279
|
+
expect(result.toSorted((a, b) => a - b)).toEqual(input.toSorted((a, b) => a - b))
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
test("arrayAdjust replaces a value via callback", () => {
|
|
283
|
+
expect(arrayAdjust(1, (item) => item * 10, [1, 2, 3])).toEqual([1, 20, 3])
|
|
284
|
+
expect(arrayAdjust(0, (item) => item, ["a"])).toEqual(["a"])
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
test("arrayUpdate replaces a value", () => {
|
|
288
|
+
expect(arrayUpdate(1, 9, [1, 2, 3])).toEqual([1, 9, 3])
|
|
289
|
+
expect(arrayUpdate(0, "x", ["a"])).toEqual(["x"])
|
|
290
|
+
})
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { expect, test } from "vitest"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
bigintAbs,
|
|
5
|
+
bigintClamp,
|
|
6
|
+
bigintIsNegative,
|
|
7
|
+
bigintIsPositive,
|
|
8
|
+
bigintIsZero,
|
|
9
|
+
bigintMaxOf,
|
|
10
|
+
bigintMinOf,
|
|
11
|
+
} from "#Source/basic/index.ts"
|
|
12
|
+
|
|
13
|
+
test("bigintIsZero returns expected values", () => {
|
|
14
|
+
expect(bigintIsZero(0n)).toBe(true)
|
|
15
|
+
expect(bigintIsZero(2n)).toBe(false)
|
|
16
|
+
expect(bigintIsZero(0)).toBe(false)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test("bigintIsPositive returns expected values", () => {
|
|
20
|
+
expect(bigintIsPositive(3n)).toBe(true)
|
|
21
|
+
expect(bigintIsPositive(0n)).toBe(false)
|
|
22
|
+
expect(bigintIsPositive(-1n)).toBe(false)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test("bigintIsNegative returns expected values", () => {
|
|
26
|
+
expect(bigintIsNegative(-3n)).toBe(true)
|
|
27
|
+
expect(bigintIsNegative(0n)).toBe(false)
|
|
28
|
+
expect(bigintIsNegative(1n)).toBe(false)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test("bigintAbs returns absolute values", () => {
|
|
32
|
+
expect(bigintAbs(-5n)).toBe(5n)
|
|
33
|
+
expect(bigintAbs(2n)).toBe(2n)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test("bigintMinOf returns expected values", () => {
|
|
37
|
+
expect(bigintMinOf(2n, 9n)).toBe(2n)
|
|
38
|
+
expect(bigintMinOf(5n, -1n)).toBe(-1n)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test("bigintMaxOf returns expected values", () => {
|
|
42
|
+
expect(bigintMaxOf(2n, 9n)).toBe(9n)
|
|
43
|
+
expect(bigintMaxOf(5n, -1n)).toBe(5n)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test("bigintClamp clamps to provided bounds", () => {
|
|
47
|
+
expect(bigintClamp(0n, 10n, 5n)).toBe(5n)
|
|
48
|
+
expect(bigintClamp(0n, 10n, -3n)).toBe(0n)
|
|
49
|
+
expect(bigintClamp(10n, 0n, 12n)).toBe(10n)
|
|
50
|
+
})
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { expect, test } from "vitest"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
booleanAnd,
|
|
5
|
+
booleanComplement,
|
|
6
|
+
booleanFrom,
|
|
7
|
+
booleanIsFalsy,
|
|
8
|
+
booleanIsTruthy,
|
|
9
|
+
booleanNand,
|
|
10
|
+
booleanNor,
|
|
11
|
+
booleanNot,
|
|
12
|
+
booleanOr,
|
|
13
|
+
booleanXnor,
|
|
14
|
+
booleanXor,
|
|
15
|
+
} from "#Source/basic/index.ts"
|
|
16
|
+
|
|
17
|
+
test("boolean converts values", () => {
|
|
18
|
+
expect(booleanFrom(1)).toBe(true)
|
|
19
|
+
expect(booleanFrom(0)).toBe(false)
|
|
20
|
+
expect(booleanFrom("")).toBe(false)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test("booleanNot inverts values", () => {
|
|
24
|
+
expect(booleanNot(true)).toBe(false)
|
|
25
|
+
expect(booleanNot(0)).toBe(true)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test("booleanAnd performs logical AND", () => {
|
|
29
|
+
expect(booleanAnd(true, 1)).toBe(true)
|
|
30
|
+
expect(booleanAnd(true, 0)).toBe(false)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test("booleanOr performs logical OR", () => {
|
|
34
|
+
expect(booleanOr(false, "a")).toBe(true)
|
|
35
|
+
expect(booleanOr(false, 0)).toBe(false)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test("booleanNand performs logical NAND", () => {
|
|
39
|
+
expect(booleanNand(true, true)).toBe(false)
|
|
40
|
+
expect(booleanNand(true, 0)).toBe(true)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test("booleanNor performs logical NOR", () => {
|
|
44
|
+
expect(booleanNor(false, 0)).toBe(true)
|
|
45
|
+
expect(booleanNor(true, false)).toBe(false)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test("booleanXor performs logical XOR", () => {
|
|
49
|
+
expect(booleanXor(true, false)).toBe(true)
|
|
50
|
+
expect(booleanXor(true, 1)).toBe(false)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test("booleanXnor performs logical XNOR", () => {
|
|
54
|
+
expect(booleanXnor(true, true)).toBe(true)
|
|
55
|
+
expect(booleanXnor(true, 0)).toBe(false)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test("booleanComplement inverts predicate result", () => {
|
|
59
|
+
const isEven = (value: number): boolean => value % 2 === 0
|
|
60
|
+
const isOdd = booleanComplement(isEven)
|
|
61
|
+
|
|
62
|
+
expect(isOdd(3)).toBe(true)
|
|
63
|
+
expect(isOdd(4)).toBe(false)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
test("booleanIsTruthy checks truthy values", () => {
|
|
67
|
+
expect(booleanIsTruthy("ok")).toBe(true)
|
|
68
|
+
expect(booleanIsTruthy("")).toBe(false)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test("booleanIsFalsy checks falsy values", () => {
|
|
72
|
+
expect(booleanIsFalsy(0)).toBe(true)
|
|
73
|
+
expect(booleanIsFalsy("0")).toBe(false)
|
|
74
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { expect, test } from "vitest"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
errorIsNetworkError,
|
|
5
|
+
errorStringifyException,
|
|
6
|
+
} from "#Source/basic/index.ts"
|
|
7
|
+
|
|
8
|
+
test("errorIsNetworkError returns expected values", () => {
|
|
9
|
+
expect(errorIsNetworkError(null)).toBe(false)
|
|
10
|
+
expect(errorIsNetworkError(undefined)).toBe(false)
|
|
11
|
+
expect(errorIsNetworkError("Network request failed")).toBe(false)
|
|
12
|
+
|
|
13
|
+
const nonTypeError = new Error("Failed to fetch")
|
|
14
|
+
expect(errorIsNetworkError(nonTypeError)).toBe(false)
|
|
15
|
+
|
|
16
|
+
const networkError = new TypeError("Failed to fetch")
|
|
17
|
+
expect(errorIsNetworkError(networkError)).toBe(true)
|
|
18
|
+
|
|
19
|
+
const safariError = new TypeError("Load failed")
|
|
20
|
+
// @ts-expect-error --- IGNORE ---
|
|
21
|
+
safariError.stack = undefined
|
|
22
|
+
expect(errorIsNetworkError(safariError)).toBe(true)
|
|
23
|
+
|
|
24
|
+
const safariWithStack = new TypeError("Load failed")
|
|
25
|
+
safariWithStack.stack = "TypeError: Load failed"
|
|
26
|
+
expect(errorIsNetworkError(safariWithStack)).toBe(false)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test("errorStringifyException returns readable output", () => {
|
|
30
|
+
expect(errorStringifyException(new Error("boom"))).toBe("Error: boom")
|
|
31
|
+
expect(errorStringifyException(123)).toBe("123")
|
|
32
|
+
})
|