@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.
Files changed (91) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +30 -1
  3. package/dist/index.js +4 -2
  4. package/dist/index.js.map +22 -4
  5. package/package.json +3 -3
  6. package/scripts/build.ts +4 -4
  7. package/src/basic/README.md +144 -0
  8. package/src/basic/array.ts +872 -0
  9. package/src/basic/bigint.ts +114 -0
  10. package/src/basic/boolean.ts +180 -0
  11. package/src/basic/enhance.ts +10 -0
  12. package/src/basic/error.ts +51 -0
  13. package/src/basic/function.ts +453 -0
  14. package/src/basic/helper.ts +276 -0
  15. package/src/basic/index.ts +17 -0
  16. package/src/basic/is.ts +320 -0
  17. package/src/basic/number.ts +178 -0
  18. package/src/basic/object.ts +140 -0
  19. package/src/basic/promise.ts +464 -0
  20. package/src/basic/regexp.ts +7 -0
  21. package/src/basic/stream.ts +140 -0
  22. package/src/basic/string.ts +308 -0
  23. package/src/basic/symbol.ts +164 -0
  24. package/src/basic/temporal.ts +224 -0
  25. package/src/encoding/README.md +105 -0
  26. package/src/encoding/base64.ts +98 -0
  27. package/src/encoding/index.ts +1 -0
  28. package/src/index.ts +4 -0
  29. package/src/random/README.md +109 -0
  30. package/src/random/index.ts +1 -0
  31. package/src/random/uuid.ts +103 -0
  32. package/src/type/README.md +330 -0
  33. package/src/type/array.ts +5 -0
  34. package/src/type/boolean.ts +471 -0
  35. package/src/type/class.ts +419 -0
  36. package/src/type/function.ts +1519 -0
  37. package/src/type/helper.ts +135 -0
  38. package/src/type/index.ts +14 -0
  39. package/src/type/intersection.ts +93 -0
  40. package/src/type/is.ts +247 -0
  41. package/src/type/iteration.ts +233 -0
  42. package/src/type/number.ts +732 -0
  43. package/src/type/object.ts +788 -0
  44. package/src/type/path.ts +73 -0
  45. package/src/type/string.ts +1004 -0
  46. package/src/type/tuple.ts +2424 -0
  47. package/src/type/union.ts +108 -0
  48. package/tests/unit/basic/array.spec.ts +290 -0
  49. package/tests/unit/basic/bigint.spec.ts +50 -0
  50. package/tests/unit/basic/boolean.spec.ts +74 -0
  51. package/tests/unit/basic/error.spec.ts +32 -0
  52. package/tests/unit/basic/function.spec.ts +175 -0
  53. package/tests/unit/basic/helper.spec.ts +118 -0
  54. package/tests/unit/basic/number.spec.ts +74 -0
  55. package/tests/unit/basic/object.spec.ts +46 -0
  56. package/tests/unit/basic/promise.spec.ts +232 -0
  57. package/tests/unit/basic/regexp.spec.ts +11 -0
  58. package/tests/unit/basic/stream.spec.ts +120 -0
  59. package/tests/unit/basic/string.spec.ts +74 -0
  60. package/tests/unit/basic/symbol.spec.ts +72 -0
  61. package/tests/unit/basic/temporal.spec.ts +78 -0
  62. package/tests/unit/encoding/base64.spec.ts +40 -0
  63. package/tests/unit/random/uuid.spec.ts +37 -0
  64. package/dist/index.d.ts +0 -2
  65. package/dist/index.d.ts.map +0 -1
  66. package/dist/reactor/index.d.ts +0 -3
  67. package/dist/reactor/index.d.ts.map +0 -1
  68. package/dist/reactor/reactor-core/flags.d.ts +0 -99
  69. package/dist/reactor/reactor-core/flags.d.ts.map +0 -1
  70. package/dist/reactor/reactor-core/index.d.ts +0 -4
  71. package/dist/reactor/reactor-core/index.d.ts.map +0 -1
  72. package/dist/reactor/reactor-core/primitive.d.ts +0 -276
  73. package/dist/reactor/reactor-core/primitive.d.ts.map +0 -1
  74. package/dist/reactor/reactor-core/reactive-system.d.ts +0 -241
  75. package/dist/reactor/reactor-core/reactive-system.d.ts.map +0 -1
  76. package/dist/reactor/reactor-operators/branch.d.ts +0 -19
  77. package/dist/reactor/reactor-operators/branch.d.ts.map +0 -1
  78. package/dist/reactor/reactor-operators/convert.d.ts +0 -30
  79. package/dist/reactor/reactor-operators/convert.d.ts.map +0 -1
  80. package/dist/reactor/reactor-operators/create.d.ts +0 -26
  81. package/dist/reactor/reactor-operators/create.d.ts.map +0 -1
  82. package/dist/reactor/reactor-operators/filter.d.ts +0 -269
  83. package/dist/reactor/reactor-operators/filter.d.ts.map +0 -1
  84. package/dist/reactor/reactor-operators/index.d.ts +0 -8
  85. package/dist/reactor/reactor-operators/index.d.ts.map +0 -1
  86. package/dist/reactor/reactor-operators/join.d.ts +0 -48
  87. package/dist/reactor/reactor-operators/join.d.ts.map +0 -1
  88. package/dist/reactor/reactor-operators/map.d.ts +0 -165
  89. package/dist/reactor/reactor-operators/map.d.ts.map +0 -1
  90. package/dist/reactor/reactor-operators/utility.d.ts +0 -48
  91. 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
+ })