@nlozgachev/pipelined 0.6.4 → 0.7.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/esm/src/Core/Logged.js +111 -0
- package/esm/src/Core/Option.js +4 -1
- package/esm/src/Core/Predicate.js +133 -0
- package/esm/src/Core/Refinement.js +115 -0
- package/esm/src/Core/RemoteData.js +3 -0
- package/esm/src/Core/Result.js +4 -0
- package/esm/src/Core/State.js +181 -0
- package/esm/src/Core/Task.js +36 -0
- package/esm/src/Core/TaskOption.js +1 -0
- package/esm/src/Core/TaskResult.js +2 -0
- package/esm/src/Core/TaskValidation.js +5 -1
- package/esm/src/Core/These.js +4 -0
- package/esm/src/Core/Validation.js +4 -0
- package/esm/src/Core/index.js +4 -0
- package/package.json +1 -1
- package/script/src/Core/Logged.js +114 -0
- package/script/src/Core/Option.js +4 -1
- package/script/src/Core/Predicate.js +136 -0
- package/script/src/Core/Refinement.js +118 -0
- package/script/src/Core/RemoteData.js +3 -0
- package/script/src/Core/Result.js +4 -0
- package/script/src/Core/State.js +184 -0
- package/script/src/Core/Task.js +36 -0
- package/script/src/Core/TaskOption.js +1 -0
- package/script/src/Core/TaskResult.js +2 -0
- package/script/src/Core/TaskValidation.js +5 -1
- package/script/src/Core/These.js +4 -0
- package/script/src/Core/Validation.js +4 -0
- package/script/src/Core/index.js +4 -0
- package/types/src/Composition/on.d.ts.map +1 -1
- package/types/src/Core/InternalTypes.d.ts +3 -0
- package/types/src/Core/InternalTypes.d.ts.map +1 -1
- package/types/src/Core/Logged.d.ts +126 -0
- package/types/src/Core/Logged.d.ts.map +1 -0
- package/types/src/Core/Option.d.ts +6 -3
- package/types/src/Core/Option.d.ts.map +1 -1
- package/types/src/Core/Predicate.d.ts +161 -0
- package/types/src/Core/Predicate.d.ts.map +1 -0
- package/types/src/Core/Refinement.d.ts +138 -0
- package/types/src/Core/Refinement.d.ts.map +1 -0
- package/types/src/Core/RemoteData.d.ts +5 -2
- package/types/src/Core/RemoteData.d.ts.map +1 -1
- package/types/src/Core/Result.d.ts +7 -3
- package/types/src/Core/Result.d.ts.map +1 -1
- package/types/src/Core/State.d.ts +192 -0
- package/types/src/Core/State.d.ts.map +1 -0
- package/types/src/Core/Task.d.ts +30 -0
- package/types/src/Core/Task.d.ts.map +1 -1
- package/types/src/Core/TaskOption.d.ts +2 -1
- package/types/src/Core/TaskOption.d.ts.map +1 -1
- package/types/src/Core/TaskResult.d.ts +4 -2
- package/types/src/Core/TaskResult.d.ts.map +1 -1
- package/types/src/Core/TaskValidation.d.ts +4 -2
- package/types/src/Core/TaskValidation.d.ts.map +1 -1
- package/types/src/Core/These.d.ts +6 -2
- package/types/src/Core/These.d.ts.map +1 -1
- package/types/src/Core/Validation.d.ts +7 -3
- package/types/src/Core/Validation.d.ts.map +1 -1
- package/types/src/Core/index.d.ts +4 -0
- package/types/src/Core/index.d.ts.map +1 -1
|
@@ -87,6 +87,7 @@ export var TaskValidation;
|
|
|
87
87
|
TaskValidation.match = (cases) => (data) => Task.map(Validation.match(cases))(data);
|
|
88
88
|
/**
|
|
89
89
|
* Returns the success value or a default value if the TaskValidation is invalid.
|
|
90
|
+
* The default can be a different type, widening the result to `Task<A | B>`.
|
|
90
91
|
*/
|
|
91
92
|
TaskValidation.getOrElse = (defaultValue) => (data) => Task.map(Validation.getOrElse(defaultValue))(data);
|
|
92
93
|
/**
|
|
@@ -96,6 +97,9 @@ export var TaskValidation;
|
|
|
96
97
|
TaskValidation.tap = (f) => (data) => Task.map(Validation.tap(f))(data);
|
|
97
98
|
/**
|
|
98
99
|
* Recovers from an Invalid state by providing a fallback TaskValidation.
|
|
100
|
+
* The fallback can produce a different success type, widening the result to `TaskValidation<E, A | B>`.
|
|
99
101
|
*/
|
|
100
|
-
TaskValidation.recover = (fallback) => (data) => Task.chain((validation) => Validation.isValid(validation)
|
|
102
|
+
TaskValidation.recover = (fallback) => (data) => Task.chain((validation) => Validation.isValid(validation)
|
|
103
|
+
? Task.resolve(validation)
|
|
104
|
+
: fallback())(data);
|
|
101
105
|
})(TaskValidation || (TaskValidation = {}));
|
package/esm/src/Core/These.js
CHANGED
|
@@ -184,23 +184,27 @@ export var These;
|
|
|
184
184
|
};
|
|
185
185
|
/**
|
|
186
186
|
* Returns the first value, or a default if the These has no first value.
|
|
187
|
+
* The default can be a different type, widening the result to `A | C`.
|
|
187
188
|
*
|
|
188
189
|
* @example
|
|
189
190
|
* ```ts
|
|
190
191
|
* pipe(These.first(5), These.getFirstOrElse(0)); // 5
|
|
191
192
|
* pipe(These.both(5, "warn"), These.getFirstOrElse(0)); // 5
|
|
192
193
|
* pipe(These.second("warn"), These.getFirstOrElse(0)); // 0
|
|
194
|
+
* pipe(These.second("warn"), These.getFirstOrElse(null)); // null — typed as number | null
|
|
193
195
|
* ```
|
|
194
196
|
*/
|
|
195
197
|
These.getFirstOrElse = (defaultValue) => (data) => These.hasFirst(data) ? data.first : defaultValue;
|
|
196
198
|
/**
|
|
197
199
|
* Returns the second value, or a default if the These has no second value.
|
|
200
|
+
* The default can be a different type, widening the result to `B | D`.
|
|
198
201
|
*
|
|
199
202
|
* @example
|
|
200
203
|
* ```ts
|
|
201
204
|
* pipe(These.second("warn"), These.getSecondOrElse("none")); // "warn"
|
|
202
205
|
* pipe(These.both(5, "warn"), These.getSecondOrElse("none")); // "warn"
|
|
203
206
|
* pipe(These.first(5), These.getSecondOrElse("none")); // "none"
|
|
207
|
+
* pipe(These.first(5), These.getSecondOrElse(null)); // null — typed as string | null
|
|
204
208
|
* ```
|
|
205
209
|
*/
|
|
206
210
|
These.getSecondOrElse = (defaultValue) => (data) => These.hasSecond(data) ? data.second : defaultValue;
|
|
@@ -132,11 +132,13 @@ export var Validation;
|
|
|
132
132
|
Validation.match = (cases) => (data) => Validation.isValid(data) ? cases.valid(data.value) : cases.invalid(data.errors);
|
|
133
133
|
/**
|
|
134
134
|
* Returns the success value or a default value if the Validation is invalid.
|
|
135
|
+
* The default can be a different type, widening the result to `A | B`.
|
|
135
136
|
*
|
|
136
137
|
* @example
|
|
137
138
|
* ```ts
|
|
138
139
|
* pipe(Validation.valid(5), Validation.getOrElse(0)); // 5
|
|
139
140
|
* pipe(Validation.invalid("oops"), Validation.getOrElse(0)); // 0
|
|
141
|
+
* pipe(Validation.invalid("oops"), Validation.getOrElse(null)); // null — typed as number | null
|
|
140
142
|
* ```
|
|
141
143
|
*/
|
|
142
144
|
Validation.getOrElse = (defaultValue) => (data) => Validation.isValid(data) ? data.value : defaultValue;
|
|
@@ -159,10 +161,12 @@ export var Validation;
|
|
|
159
161
|
};
|
|
160
162
|
/**
|
|
161
163
|
* Recovers from an Invalid state by providing a fallback Validation.
|
|
164
|
+
* The fallback can produce a different success type, widening the result to `Validation<E, A | B>`.
|
|
162
165
|
*/
|
|
163
166
|
Validation.recover = (fallback) => (data) => Validation.isValid(data) ? data : fallback();
|
|
164
167
|
/**
|
|
165
168
|
* Recovers from an Invalid state unless the errors contain any of the blocked errors.
|
|
169
|
+
* The fallback can produce a different success type, widening the result to `Validation<E, A | B>`.
|
|
166
170
|
*/
|
|
167
171
|
Validation.recoverUnless = (blockedErrors, fallback) => (data) => Validation.isInvalid(data) &&
|
|
168
172
|
!data.errors.some((err) => blockedErrors.includes(err))
|
package/esm/src/Core/index.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
export * from "./Arr.js";
|
|
2
|
+
export * from "./Logged.js";
|
|
2
3
|
export * from "./Deferred.js";
|
|
3
4
|
export * from "./Lens.js";
|
|
4
5
|
export * from "./Option.js";
|
|
5
6
|
export * from "./Reader.js";
|
|
6
7
|
export * from "./Optional.js";
|
|
7
8
|
export * from "./Rec.js";
|
|
9
|
+
export * from "./Predicate.js";
|
|
10
|
+
export * from "./Refinement.js";
|
|
8
11
|
export * from "./RemoteData.js";
|
|
12
|
+
export * from "./State.js";
|
|
9
13
|
export * from "./Result.js";
|
|
10
14
|
export * from "./Task.js";
|
|
11
15
|
export * from "./TaskOption.js";
|
package/package.json
CHANGED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Logged = void 0;
|
|
4
|
+
var Logged;
|
|
5
|
+
(function (Logged) {
|
|
6
|
+
/**
|
|
7
|
+
* Wraps a pure value into a `Logged` with an empty log.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* Logged.make<string, number>(42); // { value: 42, log: [] }
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
Logged.make = (value) => ({ value, log: [] });
|
|
15
|
+
/**
|
|
16
|
+
* Creates a `Logged` that records a single log entry and produces no
|
|
17
|
+
* meaningful value. Use this to append to the log inside a `chain`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* Logged.tell("operation completed"); // { value: undefined, log: ["operation completed"] }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
Logged.tell = (entry) => ({ value: undefined, log: [entry] });
|
|
25
|
+
/**
|
|
26
|
+
* Transforms the value inside a `Logged` without affecting the log.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* pipe(
|
|
31
|
+
* Logged.of<string, number>(5),
|
|
32
|
+
* Logged.map(n => n * 2),
|
|
33
|
+
* ); // { value: 10, log: [] }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
Logged.map = (f) => (data) => ({
|
|
37
|
+
value: f(data.value),
|
|
38
|
+
log: data.log,
|
|
39
|
+
});
|
|
40
|
+
/**
|
|
41
|
+
* Sequences two `Logged` computations, concatenating their logs.
|
|
42
|
+
* The value from the first is passed to `f`; the resulting log entries are
|
|
43
|
+
* appended after the entries from the first.
|
|
44
|
+
*
|
|
45
|
+
* Data-last — the first computation is the data being piped.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const result = pipe(
|
|
50
|
+
* Logged.of<string, number>(1),
|
|
51
|
+
* Logged.chain(n => pipe(Logged.tell("step"), Logged.map(() => n + 1))),
|
|
52
|
+
* Logged.chain(n => pipe(Logged.tell("done"), Logged.map(() => n * 10))),
|
|
53
|
+
* );
|
|
54
|
+
*
|
|
55
|
+
* Logged.run(result); // [20, ["step", "done"]]
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
Logged.chain = (f) => (data) => {
|
|
59
|
+
const next = f(data.value);
|
|
60
|
+
return { value: next.value, log: [...data.log, ...next.log] };
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Applies a function wrapped in a `Logged` to a value wrapped in a `Logged`,
|
|
64
|
+
* concatenating both logs.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* const fn: Logged<string, (n: number) => number> = {
|
|
69
|
+
* value: n => n * 2,
|
|
70
|
+
* log: ["fn-loaded"],
|
|
71
|
+
* };
|
|
72
|
+
* const arg: Logged<string, number> = { value: 5, log: ["arg-loaded"] };
|
|
73
|
+
*
|
|
74
|
+
* const result = pipe(fn, Logged.ap(arg));
|
|
75
|
+
* Logged.run(result); // [10, ["fn-loaded", "arg-loaded"]]
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
Logged.ap = (arg) => (data) => ({
|
|
79
|
+
value: data.value(arg.value),
|
|
80
|
+
log: [...data.log, ...arg.log],
|
|
81
|
+
});
|
|
82
|
+
/**
|
|
83
|
+
* Runs a side effect on the value without changing the `Logged`.
|
|
84
|
+
* Useful for debugging or inspecting intermediate values.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* pipe(
|
|
89
|
+
* Logged.of<string, number>(42),
|
|
90
|
+
* Logged.tap(n => console.log("value:", n)),
|
|
91
|
+
* );
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
Logged.tap = (f) => (data) => {
|
|
95
|
+
f(data.value);
|
|
96
|
+
return data;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Extracts the value and log as a `readonly [A, ReadonlyArray<W>]` tuple.
|
|
100
|
+
* Use this at the boundary where you need to consume both.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* const result = pipe(
|
|
105
|
+
* Logged.of<string, number>(1),
|
|
106
|
+
* Logged.chain(n => pipe(Logged.tell("incremented"), Logged.map(() => n + 1))),
|
|
107
|
+
* );
|
|
108
|
+
*
|
|
109
|
+
* const [value, log] = Logged.run(result);
|
|
110
|
+
* // value = 2, log = ["incremented"]
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
Logged.run = (data) => [data.value, data.log];
|
|
114
|
+
})(Logged || (exports.Logged = Logged = {}));
|
|
@@ -130,12 +130,14 @@ var Option;
|
|
|
130
130
|
*/
|
|
131
131
|
Option.match = (cases) => (data) => Option.isSome(data) ? cases.some(data.value) : cases.none();
|
|
132
132
|
/**
|
|
133
|
-
* Returns the value inside
|
|
133
|
+
* Returns the value inside an Option, or a default value if None.
|
|
134
|
+
* The default can be a different type, widening the result to `A | B`.
|
|
134
135
|
*
|
|
135
136
|
* @example
|
|
136
137
|
* ```ts
|
|
137
138
|
* pipe(Option.some(5), Option.getOrElse(0)); // 5
|
|
138
139
|
* pipe(Option.none(), Option.getOrElse(0)); // 0
|
|
140
|
+
* pipe(Option.none<string>(), Option.getOrElse(null)); // null — typed as string | null
|
|
139
141
|
* ```
|
|
140
142
|
*/
|
|
141
143
|
Option.getOrElse = (defaultValue) => (data) => Option.isSome(data) ? data.value : defaultValue;
|
|
@@ -170,6 +172,7 @@ var Option;
|
|
|
170
172
|
Option.filter = (predicate) => (data) => Option.isSome(data) && predicate(data.value) ? data : Option.none();
|
|
171
173
|
/**
|
|
172
174
|
* Recovers from a None by providing a fallback Option.
|
|
175
|
+
* The fallback can produce a different type, widening the result to `Option<A | B>`.
|
|
173
176
|
*/
|
|
174
177
|
Option.recover = (fallback) => (data) => Option.isSome(data) ? data : fallback();
|
|
175
178
|
/**
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Predicate = void 0;
|
|
4
|
+
var Predicate;
|
|
5
|
+
(function (Predicate) {
|
|
6
|
+
/**
|
|
7
|
+
* Negates a predicate: the result passes exactly when the original fails.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const isBlank: Predicate<string> = s => s.trim().length === 0;
|
|
12
|
+
* const isNotBlank = Predicate.not(isBlank);
|
|
13
|
+
*
|
|
14
|
+
* isNotBlank("hello"); // true
|
|
15
|
+
* isNotBlank(" "); // false
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
Predicate.not = (p) => (a) => !p(a);
|
|
19
|
+
/**
|
|
20
|
+
* Combines two predicates with logical AND: passes only when both hold.
|
|
21
|
+
*
|
|
22
|
+
* Data-last — the first predicate is the data being piped.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const isPositive: Predicate<number> = n => n > 0;
|
|
27
|
+
* const isEven: Predicate<number> = n => n % 2 === 0;
|
|
28
|
+
*
|
|
29
|
+
* const isPositiveEven: Predicate<number> = pipe(isPositive, Predicate.and(isEven));
|
|
30
|
+
*
|
|
31
|
+
* isPositiveEven(4); // true
|
|
32
|
+
* isPositiveEven(3); // false — positive but odd
|
|
33
|
+
* isPositiveEven(-2); // false — even but not positive
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
Predicate.and = (second) => (first) => (a) => first(a) && second(a);
|
|
37
|
+
/**
|
|
38
|
+
* Combines two predicates with logical OR: passes when either holds.
|
|
39
|
+
*
|
|
40
|
+
* Data-last — the first predicate is the data being piped.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const isChild: Predicate<number> = n => n < 13;
|
|
45
|
+
* const isSenior: Predicate<number> = n => n >= 65;
|
|
46
|
+
*
|
|
47
|
+
* const getsDiscount: Predicate<number> = pipe(isChild, Predicate.or(isSenior));
|
|
48
|
+
*
|
|
49
|
+
* getsDiscount(8); // true
|
|
50
|
+
* getsDiscount(70); // true
|
|
51
|
+
* getsDiscount(30); // false
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
Predicate.or = (second) => (first) => (a) => first(a) || second(a);
|
|
55
|
+
/**
|
|
56
|
+
* Adapts a `Predicate<A>` to work on a different input type `B` by applying `f`
|
|
57
|
+
* to extract the relevant `A` from a `B` before running the check.
|
|
58
|
+
*
|
|
59
|
+
* Data-last — the predicate is the data being piped; `f` is the extractor.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* type User = { name: string; age: number };
|
|
64
|
+
*
|
|
65
|
+
* const isAdult: Predicate<number> = n => n >= 18;
|
|
66
|
+
*
|
|
67
|
+
* // Lift isAdult to work on Users by extracting the age field
|
|
68
|
+
* const isAdultUser: Predicate<User> = pipe(
|
|
69
|
+
* isAdult,
|
|
70
|
+
* Predicate.using((u: User) => u.age)
|
|
71
|
+
* );
|
|
72
|
+
*
|
|
73
|
+
* isAdultUser({ name: "Alice", age: 30 }); // true
|
|
74
|
+
* isAdultUser({ name: "Bob", age: 15 }); // false
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
Predicate.using = (f) => (p) => (b) => p(f(b));
|
|
78
|
+
/**
|
|
79
|
+
* Combines an array of predicates with AND: passes only when every predicate holds.
|
|
80
|
+
* Returns `true` for an empty array (vacuous truth).
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* const checks: Predicate<string>[] = [
|
|
85
|
+
* s => s.length > 0,
|
|
86
|
+
* s => s.length <= 100,
|
|
87
|
+
* s => !s.includes("<"),
|
|
88
|
+
* ];
|
|
89
|
+
*
|
|
90
|
+
* Predicate.all(checks)("hello"); // true
|
|
91
|
+
* Predicate.all(checks)(""); // false — too short
|
|
92
|
+
* Predicate.all(checks)("<b>"); // false — contains "<"
|
|
93
|
+
* Predicate.all([])("anything"); // true
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
Predicate.all = (predicates) => (a) => predicates.every((p) => p(a));
|
|
97
|
+
/**
|
|
98
|
+
* Combines an array of predicates with OR: passes when at least one holds.
|
|
99
|
+
* Returns `false` for an empty array.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* const acceptedFormats: Predicate<string>[] = [
|
|
104
|
+
* s => s.endsWith(".jpg"),
|
|
105
|
+
* s => s.endsWith(".png"),
|
|
106
|
+
* s => s.endsWith(".webp"),
|
|
107
|
+
* ];
|
|
108
|
+
*
|
|
109
|
+
* Predicate.any(acceptedFormats)("photo.jpg"); // true
|
|
110
|
+
* Predicate.any(acceptedFormats)("photo.gif"); // false
|
|
111
|
+
* Predicate.any([])("anything"); // false
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
Predicate.any = (predicates) => (a) => predicates.some((p) => p(a));
|
|
115
|
+
/**
|
|
116
|
+
* Converts a `Refinement<A, B>` into a `Predicate<A>`, discarding the compile-time
|
|
117
|
+
* narrowing. Use this when you want to combine a type guard with plain predicates
|
|
118
|
+
* using `and`, `or`, or `all`.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```ts
|
|
122
|
+
* const isString: Refinement<unknown, string> =
|
|
123
|
+
* Refinement.make(x => typeof x === "string");
|
|
124
|
+
*
|
|
125
|
+
* const isShortString: Predicate<unknown> = pipe(
|
|
126
|
+
* Predicate.fromRefinement(isString),
|
|
127
|
+
* Predicate.and(x => (x as string).length < 10)
|
|
128
|
+
* );
|
|
129
|
+
*
|
|
130
|
+
* isShortString("hi"); // true
|
|
131
|
+
* isShortString("a very long string that exceeds ten characters"); // false
|
|
132
|
+
* isShortString(42); // false
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
Predicate.fromRefinement = (r) => r;
|
|
136
|
+
})(Predicate || (exports.Predicate = Predicate = {}));
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Refinement = void 0;
|
|
4
|
+
const Option_js_1 = require("./Option.js");
|
|
5
|
+
const Result_js_1 = require("./Result.js");
|
|
6
|
+
var Refinement;
|
|
7
|
+
(function (Refinement) {
|
|
8
|
+
/**
|
|
9
|
+
* Creates a `Refinement<A, B>` from a plain boolean predicate.
|
|
10
|
+
*
|
|
11
|
+
* This is an unsafe cast — the caller is responsible for ensuring that the
|
|
12
|
+
* predicate truly characterises values of type `B`. Use this only when
|
|
13
|
+
* bootstrapping a new refinement; prefer `compose`, `and`, or `or` to build
|
|
14
|
+
* derived refinements from existing ones.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* type PositiveNumber = number & { readonly _tag: "PositiveNumber" };
|
|
19
|
+
*
|
|
20
|
+
* const isPositive: Refinement<number, PositiveNumber> =
|
|
21
|
+
* Refinement.make(n => n > 0);
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
Refinement.make = (f) => f;
|
|
25
|
+
/**
|
|
26
|
+
* Chains two refinements: if `ab` narrows `A` to `B` and `bc` narrows `B` to `C`,
|
|
27
|
+
* the result narrows `A` directly to `C`.
|
|
28
|
+
*
|
|
29
|
+
* Data-last — the first refinement `ab` is the data being piped.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* type NonEmptyString = string & { readonly _tag: "NonEmpty" };
|
|
34
|
+
* type TrimmedString = NonEmptyString & { readonly _tag: "Trimmed" };
|
|
35
|
+
*
|
|
36
|
+
* const isNonEmpty: Refinement<string, NonEmptyString> =
|
|
37
|
+
* Refinement.make(s => s.length > 0);
|
|
38
|
+
* const isTrimmed: Refinement<NonEmptyString, TrimmedString> =
|
|
39
|
+
* Refinement.make(s => s === s.trim());
|
|
40
|
+
*
|
|
41
|
+
* const isNonEmptyTrimmed: Refinement<string, TrimmedString> = pipe(
|
|
42
|
+
* isNonEmpty,
|
|
43
|
+
* Refinement.compose(isTrimmed)
|
|
44
|
+
* );
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
Refinement.compose = (bc) => (ab) => (a) => ab(a) && bc(a);
|
|
48
|
+
/**
|
|
49
|
+
* Intersects two refinements: the result narrows `A` to `B & C`, passing only
|
|
50
|
+
* when both refinements hold simultaneously.
|
|
51
|
+
*
|
|
52
|
+
* Data-last — the first refinement is the data being piped.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* const isString: Refinement<unknown, string> = Refinement.make(x => typeof x === "string");
|
|
57
|
+
* const isNonEmpty: Refinement<unknown, { length: number }> =
|
|
58
|
+
* Refinement.make(x => (x as any).length > 0);
|
|
59
|
+
*
|
|
60
|
+
* const isNonEmptyString = pipe(isString, Refinement.and(isNonEmpty));
|
|
61
|
+
* isNonEmptyString("hi"); // true
|
|
62
|
+
* isNonEmptyString(""); // false
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
Refinement.and = (second) => (first) => (a) => first(a) && second(a);
|
|
66
|
+
/**
|
|
67
|
+
* Unions two refinements: the result narrows `A` to `B | C`, passing when either
|
|
68
|
+
* refinement holds.
|
|
69
|
+
*
|
|
70
|
+
* Data-last — the first refinement is the data being piped.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* const isString: Refinement<unknown, string> = Refinement.make(x => typeof x === "string");
|
|
75
|
+
* const isNumber: Refinement<unknown, number> = Refinement.make(x => typeof x === "number");
|
|
76
|
+
*
|
|
77
|
+
* const isStringOrNumber = pipe(isString, Refinement.or(isNumber));
|
|
78
|
+
* isStringOrNumber("hi"); // true
|
|
79
|
+
* isStringOrNumber(42); // true
|
|
80
|
+
* isStringOrNumber(true); // false
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
Refinement.or = (second) => (first) => (a) => first(a) || second(a);
|
|
84
|
+
/**
|
|
85
|
+
* Converts a `Refinement<A, B>` into a function `(a: A) => Option<B>`.
|
|
86
|
+
*
|
|
87
|
+
* Returns `Some(a)` when the refinement holds, `None` otherwise. Useful for
|
|
88
|
+
* integrating runtime validation into an `Option`-based pipeline.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* type PositiveNumber = number & { readonly _tag: "Positive" };
|
|
93
|
+
* const isPositive: Refinement<number, PositiveNumber> =
|
|
94
|
+
* Refinement.make(n => n > 0);
|
|
95
|
+
*
|
|
96
|
+
* pipe(-1, Refinement.toFilter(isPositive)); // None
|
|
97
|
+
* pipe(42, Refinement.toFilter(isPositive)); // Some(42)
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
Refinement.toFilter = (r) => (a) => r(a) ? Option_js_1.Option.some(a) : Option_js_1.Option.none();
|
|
101
|
+
/**
|
|
102
|
+
* Converts a `Refinement<A, B>` into a function `(a: A) => Result<E, B>`.
|
|
103
|
+
*
|
|
104
|
+
* Returns `Ok(a)` when the refinement holds, `Err(onFail(a))` otherwise. Use
|
|
105
|
+
* this to surface validation failures as typed errors inside a `Result` pipeline.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* type NonEmptyString = string & { readonly _tag: "NonEmpty" };
|
|
110
|
+
* const isNonEmpty: Refinement<string, NonEmptyString> =
|
|
111
|
+
* Refinement.make(s => s.length > 0);
|
|
112
|
+
*
|
|
113
|
+
* pipe("", Refinement.toResult(isNonEmpty, () => "must not be empty")); // Err(...)
|
|
114
|
+
* pipe("hi", Refinement.toResult(isNonEmpty, () => "must not be empty")); // Ok("hi")
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
Refinement.toResult = (r, onFail) => (a) => r(a) ? Result_js_1.Result.ok(a) : Result_js_1.Result.err(onFail(a));
|
|
118
|
+
})(Refinement || (exports.Refinement = Refinement = {}));
|
|
@@ -156,11 +156,13 @@ var RemoteData;
|
|
|
156
156
|
};
|
|
157
157
|
/**
|
|
158
158
|
* Returns the success value or a default value if the RemoteData is not Success.
|
|
159
|
+
* The default can be a different type, widening the result to `A | B`.
|
|
159
160
|
*
|
|
160
161
|
* @example
|
|
161
162
|
* ```ts
|
|
162
163
|
* pipe(RemoteData.success(5), RemoteData.getOrElse(0)); // 5
|
|
163
164
|
* pipe(RemoteData.loading(), RemoteData.getOrElse(0)); // 0
|
|
165
|
+
* pipe(RemoteData.loading<string, number>(), RemoteData.getOrElse(null)); // null — typed as number | null
|
|
164
166
|
* ```
|
|
165
167
|
*/
|
|
166
168
|
RemoteData.getOrElse = (defaultValue) => (data) => RemoteData.isSuccess(data) ? data.value : defaultValue;
|
|
@@ -183,6 +185,7 @@ var RemoteData;
|
|
|
183
185
|
};
|
|
184
186
|
/**
|
|
185
187
|
* Recovers from a Failure state by providing a fallback RemoteData.
|
|
188
|
+
* The fallback can produce a different success type, widening the result to `RemoteData<E, A | B>`.
|
|
186
189
|
*/
|
|
187
190
|
RemoteData.recover = (fallback) => (data) => RemoteData.isFailure(data) ? fallback(data.error) : data;
|
|
188
191
|
/**
|
|
@@ -105,11 +105,13 @@ var Result;
|
|
|
105
105
|
Result.match = (cases) => (data) => Result.isOk(data) ? cases.ok(data.value) : cases.err(data.error);
|
|
106
106
|
/**
|
|
107
107
|
* Returns the success value or a default value if the Result is an error.
|
|
108
|
+
* The default can be a different type, widening the result to `A | B`.
|
|
108
109
|
*
|
|
109
110
|
* @example
|
|
110
111
|
* ```ts
|
|
111
112
|
* pipe(Result.ok(5), Result.getOrElse(0)); // 5
|
|
112
113
|
* pipe(Result.err("error"), Result.getOrElse(0)); // 0
|
|
114
|
+
* pipe(Result.err("error"), Result.getOrElse(null)); // null — typed as number | null
|
|
113
115
|
* ```
|
|
114
116
|
*/
|
|
115
117
|
Result.getOrElse = (defaultValue) => (data) => Result.isOk(data) ? data.value : defaultValue;
|
|
@@ -133,10 +135,12 @@ var Result;
|
|
|
133
135
|
};
|
|
134
136
|
/**
|
|
135
137
|
* Recovers from an error by providing a fallback Result.
|
|
138
|
+
* The fallback can produce a different success type, widening the result to `Result<E, A | B>`.
|
|
136
139
|
*/
|
|
137
140
|
Result.recover = (fallback) => (data) => Result.isOk(data) ? data : fallback();
|
|
138
141
|
/**
|
|
139
142
|
* Recovers from an error unless it matches the blocked error.
|
|
143
|
+
* The fallback can produce a different success type, widening the result to `Result<E, A | B>`.
|
|
140
144
|
*/
|
|
141
145
|
Result.recoverUnless = (blockedErr, fallback) => (data) => Result.isErr(data) && data.error !== blockedErr ? fallback() : data;
|
|
142
146
|
/**
|