@terrygonguet/utils 0.0.2 → 0.0.3
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/package.json +1 -1
- package/src/functional/maybe.ts +41 -35
- package/src/functional/result.ts +41 -35
- package/src/main.ts +12 -5
- package/types/functional/maybe.d.ts +6 -4
- package/types/functional/result.d.ts +3 -1
- package/types/main.d.ts +4 -1
- package/src/async.test.js +0 -9
- package/src/functional/index.test.js +0 -11
- package/src/functional/maybe.test.js +0 -85
- package/src/functional/result.test.js +0 -150
- package/src/main.test.js +0 -43
package/package.json
CHANGED
package/src/functional/maybe.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { identity } from "./index.ts"
|
|
|
2
2
|
|
|
3
3
|
interface API<T> {
|
|
4
4
|
isSome(this: Maybe<T>): this is Some<T>
|
|
5
|
-
isNone(this: Maybe<T>): this is None
|
|
5
|
+
isNone(this: Maybe<T>): this is None<T>
|
|
6
6
|
orDefault(this: Maybe<T>, defaultValue: T): T
|
|
7
7
|
map<U>(this: Maybe<T>, f: (value: T) => U): Maybe<U>
|
|
8
8
|
flatMap<U>(this: Maybe<T>, f: (value: T) => Maybe<U>): Maybe<U>
|
|
@@ -10,51 +10,57 @@ interface API<T> {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export type Some<T> = { value: T } & API<T>
|
|
13
|
-
export type None =
|
|
14
|
-
export type Maybe<T> = Some<T> | None
|
|
13
|
+
export type None<T> = API<T>
|
|
14
|
+
export type Maybe<T> = Some<T> | None<T>
|
|
15
15
|
|
|
16
16
|
const $_kind = "@terrygonguet/utils/functional/maybe"
|
|
17
17
|
const $_variant_Some = "@terrygonguet/utils/functional/maybe/Some"
|
|
18
18
|
const $_variant_None = "@terrygonguet/utils/functional/maybe/None"
|
|
19
19
|
|
|
20
20
|
export function Some<T>(value: NonNullable<T>): Some<T> {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
return Object.create(
|
|
22
|
+
{
|
|
23
|
+
isSome: () => true,
|
|
24
|
+
isNone: () => false,
|
|
25
|
+
orDefault(this: Some<T>) {
|
|
26
|
+
return this.value
|
|
27
|
+
},
|
|
28
|
+
map(this: Some<T>, f) {
|
|
29
|
+
return Some(f(this.value)!)
|
|
30
|
+
},
|
|
31
|
+
flatMap(this: Some<T>, f) {
|
|
32
|
+
return f(this.value)
|
|
33
|
+
},
|
|
34
|
+
toJSON(this: Some<T>) {
|
|
35
|
+
return { $_kind, $_variant: $_variant_Some, value: this.value }
|
|
36
|
+
},
|
|
37
|
+
} as API<T>,
|
|
38
|
+
{
|
|
39
|
+
$_kind: { value: $_kind, enumerable: false, writable: false },
|
|
40
|
+
$_variant: { value: $_variant_Some, enumerable: false, writable: false },
|
|
41
|
+
value: { value, writable: false },
|
|
26
42
|
},
|
|
27
|
-
|
|
28
|
-
return Some(f(this.value)!)
|
|
29
|
-
},
|
|
30
|
-
flatMap(this: Some<T>, f) {
|
|
31
|
-
return f(this.value)
|
|
32
|
-
},
|
|
33
|
-
toJSON(this: Some<T>) {
|
|
34
|
-
return { $_kind, $_variant: $_variant_Some, value: this.value }
|
|
35
|
-
},
|
|
36
|
-
}
|
|
37
|
-
return Object.create(SomePrototype, {
|
|
38
|
-
$_kind: { value: $_kind, enumerable: false, writable: false },
|
|
39
|
-
$_variant: { value: $_variant_Some, enumerable: false, writable: false },
|
|
40
|
-
value: { value, writable: false },
|
|
41
|
-
})
|
|
43
|
+
)
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
46
|
+
export const None: None<any> = Object.create(
|
|
47
|
+
{
|
|
48
|
+
isSome: () => false,
|
|
49
|
+
isNone: () => true,
|
|
50
|
+
orDefault: identity,
|
|
51
|
+
map: () => None,
|
|
52
|
+
flatMap: () => None,
|
|
53
|
+
toJSON: () => ({ $_kind, $_variant: $_variant_None }),
|
|
54
|
+
} as API<any>,
|
|
55
|
+
{
|
|
56
|
+
$_kind: { value: $_kind, enumerable: false, writable: false },
|
|
57
|
+
$_variant: { value: $_variant_None, enumerable: false, writable: false },
|
|
58
|
+
},
|
|
59
|
+
)
|
|
56
60
|
|
|
57
61
|
export const Maybe = {
|
|
62
|
+
Some,
|
|
63
|
+
None,
|
|
58
64
|
from<T>(value: T | undefined | null): Maybe<T> {
|
|
59
65
|
switch (value) {
|
|
60
66
|
case null:
|
package/src/functional/result.ts
CHANGED
|
@@ -17,48 +17,54 @@ const $_variant_Success = "@terrygonguet/utils/functional/result/Success"
|
|
|
17
17
|
const $_variant_Failure = "@terrygonguet/utils/functional/result/Failure"
|
|
18
18
|
|
|
19
19
|
export function Success<S, F>(value: S): Success<S, F> {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
return Object.create(
|
|
21
|
+
{
|
|
22
|
+
isSuccess: () => true,
|
|
23
|
+
isFailure: () => false,
|
|
24
|
+
map<S2>(this: Success<S, F>, f: (value: S) => S2) {
|
|
25
|
+
return Success(f(this.value))
|
|
26
|
+
},
|
|
27
|
+
flatMap<S2, F2>(this: Success<S, F>, f: (value: S) => Result<S2, F2>) {
|
|
28
|
+
return f(this.value)
|
|
29
|
+
},
|
|
30
|
+
toJSON(this: Success<S, F>) {
|
|
31
|
+
return { $_kind, $_variant: $_variant_Success, value: this.value }
|
|
32
|
+
},
|
|
33
|
+
} as API<S, F>,
|
|
34
|
+
{
|
|
35
|
+
$_kind: { value: $_kind, enumerable: false, writable: false },
|
|
36
|
+
$_variant: { value: $_variant_Success, enumerable: false, writable: false },
|
|
37
|
+
value: { value, writable: false },
|
|
25
38
|
},
|
|
26
|
-
|
|
27
|
-
return f(this.value)
|
|
28
|
-
},
|
|
29
|
-
toJSON(this: Success<S, F>) {
|
|
30
|
-
return { $_kind, $_variant: $_variant_Success, value: this.value }
|
|
31
|
-
},
|
|
32
|
-
}
|
|
33
|
-
return Object.create(SuccessPrototype, {
|
|
34
|
-
$_kind: { value: $_kind, enumerable: false, writable: false },
|
|
35
|
-
$_variant: { value: $_variant_Success, enumerable: false, writable: false },
|
|
36
|
-
value: { value, writable: false },
|
|
37
|
-
})
|
|
39
|
+
)
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
export function Failure<S, F>(reason: F): Failure<S, F> {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
return Object.create(
|
|
44
|
+
{
|
|
45
|
+
isSuccess: () => false,
|
|
46
|
+
isFailure: () => true,
|
|
47
|
+
map<S2>(this: Failure<S, F>) {
|
|
48
|
+
return this as unknown as Result<S2, F>
|
|
49
|
+
},
|
|
50
|
+
flatMap<S2, F2>(this: Failure<S, F>) {
|
|
51
|
+
return this as unknown as Result<S2, F | F2>
|
|
52
|
+
},
|
|
53
|
+
toJSON(this: Failure<S, F>) {
|
|
54
|
+
return { $_kind, $_variant: $_variant_Failure, reason: this.reason }
|
|
55
|
+
},
|
|
56
|
+
} as API<S, F>,
|
|
57
|
+
{
|
|
58
|
+
$_kind: { value: $_kind, enumerable: false, writable: false },
|
|
59
|
+
$_variant: { value: $_variant_Success, enumerable: false, writable: false },
|
|
60
|
+
reason: { value: reason, writable: false },
|
|
46
61
|
},
|
|
47
|
-
|
|
48
|
-
return this as unknown as Result<S2, F | F2>
|
|
49
|
-
},
|
|
50
|
-
toJSON(this: Failure<S, F>) {
|
|
51
|
-
return { $_kind, $_variant: $_variant_Failure, reason: this.reason }
|
|
52
|
-
},
|
|
53
|
-
}
|
|
54
|
-
return Object.create(FailurePrototype, {
|
|
55
|
-
$_kind: { value: $_kind, enumerable: false, writable: false },
|
|
56
|
-
$_variant: { value: $_variant_Success, enumerable: false, writable: false },
|
|
57
|
-
reason: { value: reason, writable: false },
|
|
58
|
-
})
|
|
62
|
+
)
|
|
59
63
|
}
|
|
60
64
|
|
|
61
65
|
export const Result = {
|
|
66
|
+
Success,
|
|
67
|
+
Failure,
|
|
62
68
|
try<S, F>(tryFn: () => S) {
|
|
63
69
|
return new TryCatch<S, F>(tryFn)
|
|
64
70
|
},
|
|
@@ -72,7 +78,7 @@ export const Result = {
|
|
|
72
78
|
},
|
|
73
79
|
}
|
|
74
80
|
|
|
75
|
-
class TryCatch<S, F> {
|
|
81
|
+
export class TryCatch<S, F> {
|
|
76
82
|
tryFn: () => S
|
|
77
83
|
catchFn: (err: unknown) => F
|
|
78
84
|
|
package/src/main.ts
CHANGED
|
@@ -5,14 +5,21 @@ export function clamp(value: number, min: number, max: number) {
|
|
|
5
5
|
return Math.min(Math.max(value, min), max)
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
reviver?: (key: string, value: any) => any,
|
|
12
|
-
) {
|
|
8
|
+
type JSONReviver = (key: string, value: any) => any
|
|
9
|
+
|
|
10
|
+
export function safeParse<T>(str: string, defaultValue: T, reviver?: JSONReviver) {
|
|
13
11
|
try {
|
|
14
12
|
return JSON.parse(str, reviver)
|
|
15
13
|
} catch (_) {
|
|
16
14
|
return defaultValue
|
|
17
15
|
}
|
|
18
16
|
}
|
|
17
|
+
|
|
18
|
+
export function composeJSONRevivers(...revivers: JSONReviver[]): JSONReviver {
|
|
19
|
+
return function (key, value) {
|
|
20
|
+
for (const reviver of revivers) {
|
|
21
|
+
value = reviver(key, value)
|
|
22
|
+
}
|
|
23
|
+
return value
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
interface API<T> {
|
|
2
2
|
isSome(this: Maybe<T>): this is Some<T>;
|
|
3
|
-
isNone(this: Maybe<T>): this is None
|
|
3
|
+
isNone(this: Maybe<T>): this is None<T>;
|
|
4
4
|
orDefault(this: Maybe<T>, defaultValue: T): T;
|
|
5
5
|
map<U>(this: Maybe<T>, f: (value: T) => U): Maybe<U>;
|
|
6
6
|
flatMap<U>(this: Maybe<T>, f: (value: T) => Maybe<U>): Maybe<U>;
|
|
@@ -9,11 +9,13 @@ interface API<T> {
|
|
|
9
9
|
export type Some<T> = {
|
|
10
10
|
value: T;
|
|
11
11
|
} & API<T>;
|
|
12
|
-
export type None =
|
|
13
|
-
export type Maybe<T> = Some<T> | None
|
|
12
|
+
export type None<T> = API<T>;
|
|
13
|
+
export type Maybe<T> = Some<T> | None<T>;
|
|
14
14
|
export declare function Some<T>(value: NonNullable<T>): Some<T>;
|
|
15
|
-
export declare const None: None
|
|
15
|
+
export declare const None: None<any>;
|
|
16
16
|
export declare const Maybe: {
|
|
17
|
+
Some: typeof Some;
|
|
18
|
+
None: None<any>;
|
|
17
19
|
from<T>(value: T | null | undefined): Maybe<T>;
|
|
18
20
|
JSONReviver(_key: string, value: any): any;
|
|
19
21
|
};
|
|
@@ -15,10 +15,12 @@ export type Result<S, F> = Success<S, F> | Failure<S, F>;
|
|
|
15
15
|
export declare function Success<S, F>(value: S): Success<S, F>;
|
|
16
16
|
export declare function Failure<S, F>(reason: F): Failure<S, F>;
|
|
17
17
|
export declare const Result: {
|
|
18
|
+
Success: typeof Success;
|
|
19
|
+
Failure: typeof Failure;
|
|
18
20
|
try<S, F>(tryFn: () => S): TryCatch<S, F>;
|
|
19
21
|
JSONReviver(_key: string, value: any): any;
|
|
20
22
|
};
|
|
21
|
-
declare class TryCatch<S, F> {
|
|
23
|
+
export declare class TryCatch<S, F> {
|
|
22
24
|
tryFn: () => S;
|
|
23
25
|
catchFn: (err: unknown) => F;
|
|
24
26
|
constructor(tryFn: () => S);
|
package/types/main.d.ts
CHANGED
|
@@ -2,4 +2,7 @@
|
|
|
2
2
|
* Behaviour is undefined when max < min
|
|
3
3
|
*/
|
|
4
4
|
export declare function clamp(value: number, min: number, max: number): number;
|
|
5
|
-
|
|
5
|
+
type JSONReviver = (key: string, value: any) => any;
|
|
6
|
+
export declare function safeParse<T>(str: string, defaultValue: T, reviver?: JSONReviver): any;
|
|
7
|
+
export declare function composeJSONRevivers(...revivers: JSONReviver[]): JSONReviver;
|
|
8
|
+
export {};
|
package/src/async.test.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { describe } from "vitest"
|
|
2
|
-
import { identity } from "./index.ts"
|
|
3
|
-
|
|
4
|
-
describe.concurrent("identity()", it => {
|
|
5
|
-
it("does nothing", ({ expect }) => {
|
|
6
|
-
expect(identity(5)).to.equal(5)
|
|
7
|
-
expect(identity("test")).to.equal("test")
|
|
8
|
-
const object = { prop: "value" }
|
|
9
|
-
expect(identity(object)).to.equal(object)
|
|
10
|
-
})
|
|
11
|
-
})
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { describe } from "vitest"
|
|
2
|
-
import { Some, None, Maybe } from "./maybe.ts"
|
|
3
|
-
|
|
4
|
-
describe.concurrent("Maybe", it => {
|
|
5
|
-
/** @type {Maybe<number>} */
|
|
6
|
-
const some = Some(5)
|
|
7
|
-
/** @type {Maybe<number>} */
|
|
8
|
-
const none = None
|
|
9
|
-
|
|
10
|
-
it("isSome()", ({ expect }) => {
|
|
11
|
-
expect(some.isSome()).to.be.true
|
|
12
|
-
expect(none.isSome()).to.be.false
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
it("isNone()", ({ expect }) => {
|
|
16
|
-
expect(some.isNone()).to.be.false
|
|
17
|
-
expect(none.isNone()).to.be.true
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it("orDefault()", ({ expect }) => {
|
|
21
|
-
expect(some.orDefault(15)).to.equal(5)
|
|
22
|
-
expect(none.orDefault(15)).to.equal(15)
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it("map()", ({ expect }) => {
|
|
26
|
-
const mappedSome = some.map(n => n * 2)
|
|
27
|
-
expect(mappedSome.isSome()).to.be.true
|
|
28
|
-
expect(mappedSome.value).to.equal(10)
|
|
29
|
-
const mappedNone = none.map(n => n * 2)
|
|
30
|
-
expect(mappedNone.isNone()).to.be.true
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it("flatMap()", ({ expect }) => {
|
|
34
|
-
const some1 = some.flatMap(n => Some(n * 2))
|
|
35
|
-
expect(some1.isSome()).to.be.true
|
|
36
|
-
expect(some1.value).to.equal(10)
|
|
37
|
-
const none1 = some.flatMap(n => None)
|
|
38
|
-
expect(none1.isNone()).to.be.true
|
|
39
|
-
const some2 = none.flatMap(n => Some(n * 2))
|
|
40
|
-
expect(some2.isSome()).to.be.false
|
|
41
|
-
const none2 = some.flatMap(n => None)
|
|
42
|
-
expect(none2.isNone()).to.be.true
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
it("toJSON()", ({ expect }) => {
|
|
46
|
-
expect(some.toJSON()).toMatchInlineSnapshot()
|
|
47
|
-
expect(none.toJSON()).toMatchInlineSnapshot()
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
describe.concurrent("Maybe.JSONReviver()", it => {
|
|
51
|
-
const $_kind = "@terrygonguet/utils/functional/maybe"
|
|
52
|
-
const $_variant_Some = "@terrygonguet/utils/functional/maybe/Some"
|
|
53
|
-
const $_variant_None = "@terrygonguet/utils/functional/maybe/None"
|
|
54
|
-
|
|
55
|
-
it("does nothing to normal objects", ({ expect }) => {
|
|
56
|
-
const json1 = `{"prop":"value"}`
|
|
57
|
-
const obj1 = JSON.parse(json1, Maybe.JSONReviver)
|
|
58
|
-
expect(obj1).to.deep.equal({ prop: "value" })
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
it("revives a Some", ({ expect }) => {
|
|
62
|
-
const json2 = `{"prop":"value","some":{"$_kind":"${$_kind}","$_variant":"${$_variant_Some}","value":5}}`
|
|
63
|
-
const obj2 = JSON.parse(json2, Maybe.JSONReviver)
|
|
64
|
-
expect(obj2.prop).to.equal("value")
|
|
65
|
-
expect(obj2.some.isSome()).to.be.true
|
|
66
|
-
expect(obj2.some.value).to.equal(5)
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
it("revives a None", ({ expect }) => {
|
|
70
|
-
const json3 = `{"prop":"value","none":{"$_kind":"${$_kind}","$_variant":"${$_variant_None}"}}`
|
|
71
|
-
const obj3 = JSON.parse(json3, Maybe.JSONReviver)
|
|
72
|
-
expect(obj3.prop).to.equal("value")
|
|
73
|
-
expect(obj3.none).to.equal(None)
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
it("does a round trip", ({ expect }) => {
|
|
77
|
-
const json4 = JSON.stringify({ prop: "value", some: Some(5), none: None })
|
|
78
|
-
const obj4 = JSON.parse(json4, Maybe.JSONReviver)
|
|
79
|
-
expect(obj4.prop).to.equal("value")
|
|
80
|
-
expect(obj4.some.isSome()).to.be.true
|
|
81
|
-
expect(obj4.some.value).to.equal(5)
|
|
82
|
-
expect(obj4.none).to.equal(None)
|
|
83
|
-
})
|
|
84
|
-
})
|
|
85
|
-
})
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import { describe } from "vitest"
|
|
2
|
-
import { Success, Failure, Result } from "./result.ts"
|
|
3
|
-
|
|
4
|
-
describe.concurrent("Result", it => {
|
|
5
|
-
/** @type {Result<number, string>} */
|
|
6
|
-
const success = Success(5)
|
|
7
|
-
/** @type {Result<number, string>} */
|
|
8
|
-
const failure = Failure("reason")
|
|
9
|
-
|
|
10
|
-
it("isSuccess()", ({ expect }) => {
|
|
11
|
-
expect(success.isSuccess()).to.be.true
|
|
12
|
-
expect(failure.isSuccess()).to.be.false
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
it("isFailure()", ({ expect }) => {
|
|
16
|
-
expect(success.isFailure()).to.be.false
|
|
17
|
-
expect(failure.isFailure()).to.be.true
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it("map()", ({ expect }) => {
|
|
21
|
-
const mappedSuccess = success.map(n => n * 2)
|
|
22
|
-
expect(mappedSuccess.isSuccess()).to.be.true
|
|
23
|
-
expect(mappedSuccess.value).to.equal(10)
|
|
24
|
-
const mappedFailure = failure.map(n => n * 2)
|
|
25
|
-
expect(mappedFailure.isSuccess()).to.be.false
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
it("flatMap()", ({ expect }) => {
|
|
29
|
-
const succ1 = success.flatMap(n => Success(n * 2))
|
|
30
|
-
expect(succ1.isSuccess()).to.be.true
|
|
31
|
-
expect(succ1.value).to.equal(10)
|
|
32
|
-
|
|
33
|
-
const fail1 = success.flatMap(n => Failure("fail"))
|
|
34
|
-
expect(fail1.isSuccess()).to.be.false
|
|
35
|
-
expect(fail1.reason).to.equal("fail")
|
|
36
|
-
|
|
37
|
-
const fail2 = failure.flatMap(n => Success(n * 2))
|
|
38
|
-
expect(fail2.isSuccess()).to.be.false
|
|
39
|
-
expect(fail2.reason).to.equal("reason")
|
|
40
|
-
|
|
41
|
-
const fail3 = failure.flatMap(n => Failure("fail"))
|
|
42
|
-
expect(fail3.isSuccess()).to.be.false
|
|
43
|
-
expect(fail3.reason).to.equal("reason")
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it("toJSON()", ({ expect }) => {
|
|
47
|
-
expect(success.toJSON()).toMatchInlineSnapshot(`
|
|
48
|
-
{
|
|
49
|
-
"$_kind": "@terrygonguet/utils/functional/result",
|
|
50
|
-
"$_variant": "@terrygonguet/utils/functional/result/Success",
|
|
51
|
-
"value": 5,
|
|
52
|
-
}
|
|
53
|
-
`)
|
|
54
|
-
expect(failure.toJSON()).toMatchInlineSnapshot(`
|
|
55
|
-
{
|
|
56
|
-
"$_kind": "@terrygonguet/utils/functional/result",
|
|
57
|
-
"$_variant": "@terrygonguet/utils/functional/result/Failure",
|
|
58
|
-
"reason": "reason",
|
|
59
|
-
}
|
|
60
|
-
`)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
describe.concurrent("Result.JSONReviver()", it => {
|
|
64
|
-
const $_kind = "@terrygonguet/utils/functional/result"
|
|
65
|
-
const $_variant_Success = "@terrygonguet/utils/functional/result/Success"
|
|
66
|
-
const $_variant_Failure = "@terrygonguet/utils/functional/result/Failure"
|
|
67
|
-
|
|
68
|
-
it("does nothing to normal objects", ({ expect }) => {
|
|
69
|
-
const json = `{"prop":"value"}`
|
|
70
|
-
const obj = JSON.parse(json, Result.JSONReviver)
|
|
71
|
-
expect(obj.prop).to.equal("value")
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
it("revives a Success", ({ expect }) => {
|
|
75
|
-
const json = `{
|
|
76
|
-
"prop":"value",
|
|
77
|
-
"success": {
|
|
78
|
-
"$_kind": "@terrygonguet/utils/functional/result",
|
|
79
|
-
"$_variant": "@terrygonguet/utils/functional/result/Success",
|
|
80
|
-
"value": 5
|
|
81
|
-
}
|
|
82
|
-
}`
|
|
83
|
-
const obj = JSON.parse(json, Result.JSONReviver)
|
|
84
|
-
expect(obj.prop).to.equal("value")
|
|
85
|
-
expect(obj.success.isSuccess()).to.be.true
|
|
86
|
-
expect(obj.success.value).to.equal(5)
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
it("revives a Failure", ({ expect }) => {
|
|
90
|
-
const json = `{
|
|
91
|
-
"prop":"value",
|
|
92
|
-
"failure": {
|
|
93
|
-
"$_kind": "@terrygonguet/utils/functional/result",
|
|
94
|
-
"$_variant": "@terrygonguet/utils/functional/result/Failure",
|
|
95
|
-
"reason": "reason"
|
|
96
|
-
}
|
|
97
|
-
}`
|
|
98
|
-
const obj = JSON.parse(json, Result.JSONReviver)
|
|
99
|
-
expect(obj.prop).to.equal("value")
|
|
100
|
-
expect(obj.failure.isSuccess()).to.be.false
|
|
101
|
-
expect(obj.failure.reason).to.equal("reason")
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
it("does a round trip", ({ expect }) => {
|
|
105
|
-
const json = JSON.stringify({ prop: "value", success, failure })
|
|
106
|
-
const obj = JSON.parse(json, Result.JSONReviver)
|
|
107
|
-
expect(obj.prop).to.equal("value")
|
|
108
|
-
expect(obj.success.isSuccess()).to.be.true
|
|
109
|
-
expect(obj.success.value).to.equal(5)
|
|
110
|
-
expect(obj.failure.isSuccess()).to.be.false
|
|
111
|
-
expect(obj.failure.reason).to.equal("reason")
|
|
112
|
-
})
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
describe("Result.try()", it => {
|
|
116
|
-
it("gets the value from the try function", ({ expect }) => {
|
|
117
|
-
const result = Result.try(() => {
|
|
118
|
-
const n = 5
|
|
119
|
-
return n * 2
|
|
120
|
-
}).exec()
|
|
121
|
-
expect(result.isSuccess()).to.be.true
|
|
122
|
-
expect(result.value).to.equal(10)
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
it("gets the value from catch on error", ({ expect }) => {
|
|
126
|
-
const result = Result.try(() => {
|
|
127
|
-
throw new Error("fail")
|
|
128
|
-
})
|
|
129
|
-
.catch(err => {
|
|
130
|
-
return err.message
|
|
131
|
-
})
|
|
132
|
-
.exec()
|
|
133
|
-
expect(result.isSuccess()).to.be.false
|
|
134
|
-
expect(result.reason).to.equal("fail")
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
it("ignores catch if try does not throw", ({ expect }) => {
|
|
138
|
-
const result = Result.try(() => {
|
|
139
|
-
const n = 5
|
|
140
|
-
return n * 2
|
|
141
|
-
})
|
|
142
|
-
.catch(err => {
|
|
143
|
-
throw new Error("Should not run")
|
|
144
|
-
})
|
|
145
|
-
.exec()
|
|
146
|
-
expect(result.isSuccess()).to.be.true
|
|
147
|
-
expect(result.value).to.equal(10)
|
|
148
|
-
})
|
|
149
|
-
})
|
|
150
|
-
})
|
package/src/main.test.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { describe } from "vitest"
|
|
2
|
-
import { clamp, safeParse } from "./main.ts"
|
|
3
|
-
|
|
4
|
-
describe.concurrent("clamp()", it => {
|
|
5
|
-
it("does nothing to values within range", ({ expect }) => {
|
|
6
|
-
expect(clamp(5, 0, 10)).to.equal(5)
|
|
7
|
-
expect(clamp(10, 10, 10)).to.equal(10)
|
|
8
|
-
expect(clamp(0, 0, 10)).to.equal(0)
|
|
9
|
-
expect(clamp(10, 0, 10)).to.equal(10)
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
it("clamps values outside of range", ({ expect }) => {
|
|
13
|
-
expect(clamp(-5, 0, 10)).to.equal(0)
|
|
14
|
-
expect(clamp(15, 0, 10)).to.equal(10)
|
|
15
|
-
expect(clamp(-5, 10, 10)).to.equal(10)
|
|
16
|
-
expect(clamp(15, 10, 10)).to.equal(10)
|
|
17
|
-
})
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
describe.concurrent("safeParse()", it => {
|
|
21
|
-
it("works the same as JSON.parse for valid objects", ({ expect }) => {
|
|
22
|
-
const json = `{"prop":"value"}`
|
|
23
|
-
expect(safeParse(json, {})).to.deep.equal(JSON.parse(json))
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it("uses default value for malformed JSON", ({ expect }) => {
|
|
27
|
-
const json = `{"prop":}`
|
|
28
|
-
expect(safeParse(json, { prop: "default" })).to.deep.equal({ prop: "default" })
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
it("uses revivers", ({ expect }) => {
|
|
32
|
-
const json = `{"prop":"value","other":"ignored"}`
|
|
33
|
-
function reviver(key, value) {
|
|
34
|
-
if (key == "prop") return "replaced"
|
|
35
|
-
else return value
|
|
36
|
-
}
|
|
37
|
-
const defaultValue = { prop: "value", other: "ignored" }
|
|
38
|
-
expect(safeParse(json, defaultValue, reviver)).to.deep.equal({
|
|
39
|
-
prop: "replaced",
|
|
40
|
-
other: "ignored",
|
|
41
|
-
})
|
|
42
|
-
})
|
|
43
|
-
})
|