@nunofyobiz/effect-extras 1.0.0 → 2.1.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/README.md +50 -6
- package/dist/ArrayX.d.ts +415 -0
- package/dist/ArrayX.d.ts.map +1 -0
- package/dist/ArrayX.js +547 -0
- package/dist/ArrayX.js.map +1 -0
- package/dist/BigIntX.d.ts +24 -0
- package/dist/BigIntX.d.ts.map +1 -0
- package/dist/BigIntX.js +30 -0
- package/dist/BigIntX.js.map +1 -0
- package/dist/BooleanX.d.ts +25 -0
- package/dist/BooleanX.d.ts.map +1 -0
- package/dist/BooleanX.js +25 -0
- package/dist/BooleanX.js.map +1 -0
- package/dist/DurationX.d.ts +73 -0
- package/dist/DurationX.d.ts.map +1 -0
- package/dist/DurationX.js +91 -0
- package/dist/DurationX.js.map +1 -0
- package/dist/EffectX.d.ts +120 -0
- package/dist/EffectX.d.ts.map +1 -0
- package/dist/EffectX.js +140 -0
- package/dist/EffectX.js.map +1 -0
- package/dist/FormDataX.d.ts +49 -0
- package/dist/FormDataX.d.ts.map +1 -0
- package/dist/FormDataX.js +42 -0
- package/dist/FormDataX.js.map +1 -0
- package/dist/MapX.d.ts +32 -0
- package/dist/MapX.d.ts.map +1 -0
- package/dist/MapX.js +49 -0
- package/dist/MapX.js.map +1 -0
- package/dist/NonNullableX.d.ts +174 -0
- package/dist/NonNullableX.d.ts.map +1 -0
- package/dist/NonNullableX.js +212 -0
- package/dist/NonNullableX.js.map +1 -0
- package/dist/NumberX.d.ts +178 -0
- package/dist/NumberX.d.ts.map +1 -0
- package/dist/NumberX.js +214 -0
- package/dist/NumberX.js.map +1 -0
- package/dist/OptionX.d.ts +181 -0
- package/dist/OptionX.d.ts.map +1 -0
- package/dist/OptionX.js +195 -0
- package/dist/OptionX.js.map +1 -0
- package/dist/OrderX.d.ts +32 -0
- package/dist/OrderX.d.ts.map +1 -0
- package/dist/OrderX.js +32 -0
- package/dist/OrderX.js.map +1 -0
- package/dist/PredicateX.d.ts +76 -0
- package/dist/PredicateX.d.ts.map +1 -0
- package/dist/PredicateX.js +73 -0
- package/dist/PredicateX.js.map +1 -0
- package/dist/PromiseX.d.ts +32 -0
- package/dist/PromiseX.d.ts.map +1 -0
- package/dist/PromiseX.js +32 -0
- package/dist/PromiseX.js.map +1 -0
- package/dist/RecordX.d.ts +323 -0
- package/dist/RecordX.d.ts.map +1 -0
- package/dist/RecordX.js +326 -0
- package/dist/RecordX.js.map +1 -0
- package/dist/ResultX.d.ts +50 -0
- package/dist/ResultX.d.ts.map +1 -0
- package/dist/ResultX.js +50 -0
- package/dist/ResultX.js.map +1 -0
- package/dist/SchemaX.d.ts +249 -0
- package/dist/SchemaX.d.ts.map +1 -0
- package/dist/SchemaX.js +243 -0
- package/dist/SchemaX.js.map +1 -0
- package/dist/SetX.d.ts +121 -0
- package/dist/SetX.d.ts.map +1 -0
- package/dist/SetX.js +137 -0
- package/dist/SetX.js.map +1 -0
- package/dist/StringX.d.ts +70 -0
- package/dist/StringX.d.ts.map +1 -0
- package/dist/StringX.js +81 -0
- package/dist/StringX.js.map +1 -0
- package/dist/StructX.d.ts +219 -0
- package/dist/StructX.d.ts.map +1 -0
- package/dist/StructX.js +173 -0
- package/dist/StructX.js.map +1 -0
- package/dist/WarnResult.d.ts +1146 -0
- package/dist/WarnResult.d.ts.map +1 -0
- package/dist/WarnResult.js +1060 -0
- package/dist/WarnResult.js.map +1 -0
- package/dist/index.d.ts +22 -3703
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -1005
- package/dist/index.js.map +1 -1
- package/package.json +18 -5
- package/src/{ArrayX/ArrayX.ts → ArrayX.ts} +29 -27
- package/src/{DurationX/DurationX.ts → DurationX.ts} +1 -1
- package/src/{RecordX/RecordX.ts → RecordX.ts} +1 -1
- package/src/WarnResult.ts +1265 -0
- package/src/index.ts +21 -20
- package/src/ArrayX/index.ts +0 -1
- package/src/BigIntX/index.ts +0 -1
- package/src/BooleanX/index.ts +0 -1
- package/src/DurationX/index.ts +0 -1
- package/src/EffectX/index.ts +0 -1
- package/src/FormDataX/index.ts +0 -1
- package/src/MapX/index.ts +0 -1
- package/src/NonNullableX/index.ts +0 -2
- package/src/NumberX/index.ts +0 -1
- package/src/OptionX/index.ts +0 -1
- package/src/OrderX/index.ts +0 -1
- package/src/PredicateX/index.ts +0 -1
- package/src/PromiseX/index.ts +0 -1
- package/src/RecordX/index.ts +0 -1
- package/src/ResultX/index.ts +0 -1
- package/src/SchemaX/index.ts +0 -1
- package/src/SetX/index.ts +0 -1
- package/src/StringX/index.ts +0 -1
- package/src/StructX/index.ts +0 -1
- package/src/These/These.ts +0 -1173
- package/src/These/index.ts +0 -1
- /package/src/{BigIntX/BigIntX.ts → BigIntX.ts} +0 -0
- /package/src/{BooleanX/BooleanX.ts → BooleanX.ts} +0 -0
- /package/src/{EffectX/EffectX.ts → EffectX.ts} +0 -0
- /package/src/{FormDataX/FormDataX.ts → FormDataX.ts} +0 -0
- /package/src/{MapX/MapX.ts → MapX.ts} +0 -0
- /package/src/{NonNullableX/NonNullableX.ts → NonNullableX.ts} +0 -0
- /package/src/{NumberX/NumberX.ts → NumberX.ts} +0 -0
- /package/src/{OptionX/OptionX.ts → OptionX.ts} +0 -0
- /package/src/{OrderX/OrderX.ts → OrderX.ts} +0 -0
- /package/src/{PredicateX/PredicateX.ts → PredicateX.ts} +0 -0
- /package/src/{PromiseX/PromiseX.ts → PromiseX.ts} +0 -0
- /package/src/{ResultX/ResultX.ts → ResultX.ts} +0 -0
- /package/src/{SchemaX/SchemaX.ts → SchemaX.ts} +0 -0
- /package/src/{SetX/SetX.ts → SetX.ts} +0 -0
- /package/src/{StringX/StringX.ts → StringX.ts} +0 -0
- /package/src/{StructX/StructX.ts → StructX.ts} +0 -0
|
@@ -0,0 +1,1265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `WarnResult` data type — a result that may carry a success value and/or
|
|
3
|
+
* warnings, where both sides are optional but never both absent.
|
|
4
|
+
*
|
|
5
|
+
* @since 0.0.0
|
|
6
|
+
*/
|
|
7
|
+
import { Data, Effect, Option, Predicate, Struct, pipe } from "effect";
|
|
8
|
+
import { constUndefined, identity } from "effect/Function";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A result that may come with a success value and may come with warnings — both
|
|
12
|
+
* are optional, but never both absent.
|
|
13
|
+
*
|
|
14
|
+
* Where `Result<A, E>` models an exclusive choice (success _or_ failure),
|
|
15
|
+
* `WarnResult` is an "inclusive or": the success value and the warnings can each
|
|
16
|
+
* be present independently. It is a tagged enum with three constructors:
|
|
17
|
+
* `SuccessOnly` (only a `success` value), `WarningsOnly` (only `warnings`), and
|
|
18
|
+
* `SuccessWithWarnings` (both). Reach for it when an operation can succeed, warn,
|
|
19
|
+
* or do both at once — e.g. a parse that yields a value _and_ a list of warnings,
|
|
20
|
+
* or that only produces warnings.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
25
|
+
*
|
|
26
|
+
* const both: WarnResult.WarnResult<string, number> =
|
|
27
|
+
* WarnResult.SuccessWithWarnings({
|
|
28
|
+
* warnings: "rounded down",
|
|
29
|
+
* success: 1
|
|
30
|
+
* })
|
|
31
|
+
*
|
|
32
|
+
* assert.deepStrictEqual(both._tag, "SuccessWithWarnings")
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @category models
|
|
36
|
+
* @since 0.0.0
|
|
37
|
+
*/
|
|
38
|
+
export type WarnResult<W, A> = Data.TaggedEnum<{
|
|
39
|
+
WarningsOnly: {
|
|
40
|
+
readonly warnings: W;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
SuccessOnly: {
|
|
44
|
+
readonly success: A;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
SuccessWithWarnings: {
|
|
48
|
+
readonly warnings: W;
|
|
49
|
+
readonly success: A;
|
|
50
|
+
};
|
|
51
|
+
}>;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The `WarningsOnly` member of `WarnResult` — a result that carries only
|
|
55
|
+
* `warnings` and no `success` value.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
60
|
+
*
|
|
61
|
+
* const value: WarnResult.WarningsOnly<string> = WarnResult.WarningsOnly({
|
|
62
|
+
* warnings: "skipped 2 rows"
|
|
63
|
+
* })
|
|
64
|
+
*
|
|
65
|
+
* assert.deepStrictEqual(value.warnings, "skipped 2 rows")
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* @category models
|
|
69
|
+
* @since 0.0.0
|
|
70
|
+
*/
|
|
71
|
+
export type WarningsOnly<W> = WarnResult<W, never> & {
|
|
72
|
+
_tag: "WarningsOnly";
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* The `SuccessOnly` member of `WarnResult` — a result that carries only a
|
|
77
|
+
* `success` value and no `warnings`.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
82
|
+
*
|
|
83
|
+
* const value: WarnResult.SuccessOnly<number> = WarnResult.SuccessOnly({
|
|
84
|
+
* success: 1
|
|
85
|
+
* })
|
|
86
|
+
*
|
|
87
|
+
* assert.deepStrictEqual(value.success, 1)
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* @category models
|
|
91
|
+
* @since 0.0.0
|
|
92
|
+
*/
|
|
93
|
+
export type SuccessOnly<A> = WarnResult<never, A> & {
|
|
94
|
+
_tag: "SuccessOnly";
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* The `SuccessWithWarnings` member of `WarnResult` — a result that carries both a
|
|
99
|
+
* `success` value and `warnings`.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
104
|
+
*
|
|
105
|
+
* const value: WarnResult.SuccessWithWarnings<string, number> =
|
|
106
|
+
* WarnResult.SuccessWithWarnings({
|
|
107
|
+
* warnings: "rounded down",
|
|
108
|
+
* success: 1
|
|
109
|
+
* })
|
|
110
|
+
*
|
|
111
|
+
* assert.deepStrictEqual(value, {
|
|
112
|
+
* _tag: "SuccessWithWarnings",
|
|
113
|
+
* warnings: "rounded down",
|
|
114
|
+
* success: 1
|
|
115
|
+
* })
|
|
116
|
+
* ```
|
|
117
|
+
*
|
|
118
|
+
* @category models
|
|
119
|
+
* @since 0.0.0
|
|
120
|
+
*/
|
|
121
|
+
export type SuccessWithWarnings<W, A> = WarnResult<W, A> & {
|
|
122
|
+
_tag: "SuccessWithWarnings";
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Any `WarnResult` that is guaranteed to carry `warnings` — either `WarningsOnly`
|
|
127
|
+
* or `SuccessWithWarnings`.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```ts
|
|
131
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
132
|
+
*
|
|
133
|
+
* const value: WarnResult.WithWarnings<string, number> = WarnResult.WarningsOnly({
|
|
134
|
+
* warnings: "skipped 2 rows"
|
|
135
|
+
* })
|
|
136
|
+
*
|
|
137
|
+
* assert.deepStrictEqual(value.warnings, "skipped 2 rows")
|
|
138
|
+
* ```
|
|
139
|
+
*
|
|
140
|
+
* @category models
|
|
141
|
+
* @since 0.0.0
|
|
142
|
+
*/
|
|
143
|
+
export type WithWarnings<W, A> = WarningsOnly<W> | SuccessWithWarnings<W, A>;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Any `WarnResult` that is guaranteed to carry a `success` value — either
|
|
147
|
+
* `SuccessOnly` or `SuccessWithWarnings`.
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```ts
|
|
151
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
152
|
+
*
|
|
153
|
+
* const value: WarnResult.WithSuccess<string, number> = WarnResult.SuccessOnly({
|
|
154
|
+
* success: 1
|
|
155
|
+
* })
|
|
156
|
+
*
|
|
157
|
+
* assert.deepStrictEqual(value.success, 1)
|
|
158
|
+
* ```
|
|
159
|
+
*
|
|
160
|
+
* @category models
|
|
161
|
+
* @since 0.0.0
|
|
162
|
+
*/
|
|
163
|
+
export type WithSuccess<W, A> = SuccessOnly<A> | SuccessWithWarnings<W, A>;
|
|
164
|
+
|
|
165
|
+
interface WarnResultDefinition extends Data.TaggedEnum.WithGenerics<2> {
|
|
166
|
+
readonly taggedEnum: WarnResult<this["A"], this["B"]>;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const taggedEnum = Data.taggedEnum<WarnResultDefinition>();
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Constructs a `WarningsOnly` — a `WarnResult` that carries only `warnings`.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```ts
|
|
176
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
177
|
+
*
|
|
178
|
+
* const value = WarnResult.WarningsOnly({ warnings: "skipped 2 rows" })
|
|
179
|
+
*
|
|
180
|
+
* assert.deepStrictEqual(value._tag, "WarningsOnly")
|
|
181
|
+
* assert.deepStrictEqual(value.warnings, "skipped 2 rows")
|
|
182
|
+
* ```
|
|
183
|
+
*
|
|
184
|
+
* @category constructors
|
|
185
|
+
* @since 0.0.0
|
|
186
|
+
*/
|
|
187
|
+
export const WarningsOnly = taggedEnum.WarningsOnly;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Constructs a `SuccessOnly` — a `WarnResult` that carries only a `success` value.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```ts
|
|
194
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
195
|
+
*
|
|
196
|
+
* const value = WarnResult.SuccessOnly({ success: 1 })
|
|
197
|
+
*
|
|
198
|
+
* assert.deepStrictEqual(value._tag, "SuccessOnly")
|
|
199
|
+
* assert.deepStrictEqual(value.success, 1)
|
|
200
|
+
* ```
|
|
201
|
+
*
|
|
202
|
+
* @category constructors
|
|
203
|
+
* @since 0.0.0
|
|
204
|
+
*/
|
|
205
|
+
export const SuccessOnly = taggedEnum.SuccessOnly;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Constructs a `SuccessWithWarnings` — a `WarnResult` that carries both a
|
|
209
|
+
* `success` value and `warnings`.
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```ts
|
|
213
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
214
|
+
*
|
|
215
|
+
* const value = WarnResult.SuccessWithWarnings({
|
|
216
|
+
* warnings: "rounded down",
|
|
217
|
+
* success: 1
|
|
218
|
+
* })
|
|
219
|
+
*
|
|
220
|
+
* assert.deepStrictEqual(value._tag, "SuccessWithWarnings")
|
|
221
|
+
* assert.deepStrictEqual(value.warnings, "rounded down")
|
|
222
|
+
* assert.deepStrictEqual(value.success, 1)
|
|
223
|
+
* ```
|
|
224
|
+
*
|
|
225
|
+
* @category constructors
|
|
226
|
+
* @since 0.0.0
|
|
227
|
+
*/
|
|
228
|
+
export const SuccessWithWarnings = taggedEnum.SuccessWithWarnings;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Builds per-tag refinements for `WarnResult`. `is("WarningsOnly")` is a type
|
|
232
|
+
* guard that narrows a `WarnResult` to its `WarningsOnly` member, and likewise for
|
|
233
|
+
* `"SuccessOnly"` and `"SuccessWithWarnings"`.
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```ts
|
|
237
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
238
|
+
*
|
|
239
|
+
* assert.deepStrictEqual(
|
|
240
|
+
* WarnResult.is("WarningsOnly")(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
241
|
+
* true
|
|
242
|
+
* )
|
|
243
|
+
* assert.deepStrictEqual(
|
|
244
|
+
* WarnResult.is("WarningsOnly")(WarnResult.SuccessOnly({ success: 1 })),
|
|
245
|
+
* false
|
|
246
|
+
* )
|
|
247
|
+
* ```
|
|
248
|
+
*
|
|
249
|
+
* @category guards
|
|
250
|
+
* @since 0.0.0
|
|
251
|
+
*/
|
|
252
|
+
export const is = taggedEnum.$is;
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Folds a `WarnResult` over its three tags. Provide a handler for `WarningsOnly`,
|
|
256
|
+
* `SuccessOnly`, and `SuccessWithWarnings` and `match` returns a function from a
|
|
257
|
+
* `WarnResult` to the handlers' common result type.
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```ts
|
|
261
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
262
|
+
*
|
|
263
|
+
* const describe = WarnResult.match({
|
|
264
|
+
* WarningsOnly: ({ warnings }) => `warnings ${warnings}`,
|
|
265
|
+
* SuccessOnly: ({ success }) => `success ${success}`,
|
|
266
|
+
* SuccessWithWarnings: ({ warnings, success }) => `both ${warnings}/${success}`
|
|
267
|
+
* })
|
|
268
|
+
*
|
|
269
|
+
* assert.deepStrictEqual(
|
|
270
|
+
* describe(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })),
|
|
271
|
+
* "both w/1"
|
|
272
|
+
* )
|
|
273
|
+
* ```
|
|
274
|
+
*
|
|
275
|
+
* @category pattern matching
|
|
276
|
+
* @since 0.0.0
|
|
277
|
+
*/
|
|
278
|
+
export const match = taggedEnum.$match;
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Builds a `WarnResult` known to carry `warnings`, choosing `SuccessWithWarnings`
|
|
282
|
+
* when a `success` value is present and `WarningsOnly` otherwise.
|
|
283
|
+
*
|
|
284
|
+
* Use it when the `warnings` are mandatory and the `success` value is an optional
|
|
285
|
+
* companion: pass an absent (`null`/`undefined`) `success` to get a
|
|
286
|
+
* `WarningsOnly`, or a present one to get a `SuccessWithWarnings`. The return type
|
|
287
|
+
* `WithWarnings<W, A>` reflects that `warnings` are always present.
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* ```ts
|
|
291
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
292
|
+
*
|
|
293
|
+
* assert.deepStrictEqual(
|
|
294
|
+
* WarnResult.WithWarnings({ warnings: "w", success: 1 }),
|
|
295
|
+
* WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })
|
|
296
|
+
* )
|
|
297
|
+
*
|
|
298
|
+
* assert.deepStrictEqual(
|
|
299
|
+
* WarnResult.WithWarnings({ warnings: "w" }),
|
|
300
|
+
* WarnResult.WarningsOnly({ warnings: "w" })
|
|
301
|
+
* )
|
|
302
|
+
* ```
|
|
303
|
+
*
|
|
304
|
+
* @category constructors
|
|
305
|
+
* @since 0.0.0
|
|
306
|
+
*/
|
|
307
|
+
export const WithWarnings = <W, A>({
|
|
308
|
+
warnings,
|
|
309
|
+
success,
|
|
310
|
+
}: {
|
|
311
|
+
warnings: W;
|
|
312
|
+
success?: A | undefined;
|
|
313
|
+
}): WithWarnings<W, A> =>
|
|
314
|
+
Predicate.isNotNullish(success)
|
|
315
|
+
? SuccessWithWarnings({ warnings, success })
|
|
316
|
+
: WarningsOnly({ warnings });
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Builds a `WarnResult` known to carry a `success` value, choosing
|
|
320
|
+
* `SuccessWithWarnings` when `warnings` are present and `SuccessOnly` otherwise.
|
|
321
|
+
*
|
|
322
|
+
* The mirror of `WithWarnings`: the `success` value is mandatory and the
|
|
323
|
+
* `warnings` are an optional companion. Pass absent (`null`/`undefined`)
|
|
324
|
+
* `warnings` to get a `SuccessOnly`, or present ones to get a
|
|
325
|
+
* `SuccessWithWarnings`. The return type `WithSuccess<W, A>` reflects that a
|
|
326
|
+
* `success` value is always present.
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* ```ts
|
|
330
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
331
|
+
*
|
|
332
|
+
* assert.deepStrictEqual(
|
|
333
|
+
* WarnResult.WithSuccess({ warnings: "w", success: 1 }),
|
|
334
|
+
* WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })
|
|
335
|
+
* )
|
|
336
|
+
*
|
|
337
|
+
* assert.deepStrictEqual(
|
|
338
|
+
* WarnResult.WithSuccess({ success: 1 }),
|
|
339
|
+
* WarnResult.SuccessOnly({ success: 1 })
|
|
340
|
+
* )
|
|
341
|
+
* ```
|
|
342
|
+
*
|
|
343
|
+
* @category constructors
|
|
344
|
+
* @since 0.0.0
|
|
345
|
+
*/
|
|
346
|
+
export const WithSuccess = <W, A>({
|
|
347
|
+
warnings,
|
|
348
|
+
success,
|
|
349
|
+
}: {
|
|
350
|
+
warnings?: W | undefined;
|
|
351
|
+
success: A;
|
|
352
|
+
}): WithSuccess<W, A> =>
|
|
353
|
+
Predicate.isNotNullish(warnings)
|
|
354
|
+
? SuccessWithWarnings({ warnings, success })
|
|
355
|
+
: SuccessOnly({ success });
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Builds a `WarnResult` from a pair of possibly-nullish inputs, wrapping the
|
|
359
|
+
* result in an `Option` so the all-absent case is expressible.
|
|
360
|
+
*
|
|
361
|
+
* Returns `Option.some(SuccessWithWarnings)` when both are present,
|
|
362
|
+
* `Option.some(WarningsOnly)` or `Option.some(SuccessOnly)` when exactly one is
|
|
363
|
+
* present, and `Option.none()` when both are nullish. Use it as the total entry
|
|
364
|
+
* point for turning an optional success value and optional warnings into a
|
|
365
|
+
* `WarnResult`.
|
|
366
|
+
*
|
|
367
|
+
* @example
|
|
368
|
+
* ```ts
|
|
369
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
370
|
+
* import { Option } from "effect"
|
|
371
|
+
*
|
|
372
|
+
* assert.deepStrictEqual(
|
|
373
|
+
* WarnResult.optionFromNullables({ warnings: "w", success: 1 }),
|
|
374
|
+
* Option.some(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 }))
|
|
375
|
+
* )
|
|
376
|
+
*
|
|
377
|
+
* assert.deepStrictEqual(
|
|
378
|
+
* WarnResult.optionFromNullables({ warnings: "w", success: null }),
|
|
379
|
+
* Option.some(WarnResult.WarningsOnly({ warnings: "w" }))
|
|
380
|
+
* )
|
|
381
|
+
*
|
|
382
|
+
* assert.deepStrictEqual(
|
|
383
|
+
* WarnResult.optionFromNullables({ warnings: null, success: undefined }),
|
|
384
|
+
* Option.none()
|
|
385
|
+
* )
|
|
386
|
+
* ```
|
|
387
|
+
*
|
|
388
|
+
* @category constructors
|
|
389
|
+
* @since 0.0.0
|
|
390
|
+
*/
|
|
391
|
+
export const optionFromNullables = <W, A>({
|
|
392
|
+
warnings,
|
|
393
|
+
success,
|
|
394
|
+
}: {
|
|
395
|
+
warnings?: W | null | undefined;
|
|
396
|
+
success?: A | null | undefined;
|
|
397
|
+
}): Option.Option<WarnResult<W, A>> => {
|
|
398
|
+
if (Predicate.isNotNullish(warnings) && Predicate.isNotNullish(success)) {
|
|
399
|
+
return Option.some(SuccessWithWarnings({ warnings, success }));
|
|
400
|
+
}
|
|
401
|
+
if (Predicate.isNotNullish(warnings)) {
|
|
402
|
+
return Option.some(WarningsOnly({ warnings }));
|
|
403
|
+
}
|
|
404
|
+
if (Predicate.isNotNullish(success)) {
|
|
405
|
+
return Option.some(SuccessOnly({ success }));
|
|
406
|
+
}
|
|
407
|
+
return Option.none();
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Builds a `WarnResult` from a pair of possibly-nullish inputs, falling back to
|
|
412
|
+
* the `orElse` thunk when both are absent.
|
|
413
|
+
*
|
|
414
|
+
* The non-optional companion to `optionFromNullables`: it unwraps the same logic
|
|
415
|
+
* but resolves the all-absent case with `orElse` instead of an `Option`. The
|
|
416
|
+
* default `orElse` throws, so omit it only when at least one side is guaranteed
|
|
417
|
+
* present.
|
|
418
|
+
*
|
|
419
|
+
* @example
|
|
420
|
+
* ```ts
|
|
421
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
422
|
+
*
|
|
423
|
+
* assert.deepStrictEqual(
|
|
424
|
+
* WarnResult.fromNullables({ warnings: "w", success: 1 }),
|
|
425
|
+
* WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })
|
|
426
|
+
* )
|
|
427
|
+
*
|
|
428
|
+
* // Both absent — fall back via orElse instead of throwing
|
|
429
|
+
* assert.deepStrictEqual(
|
|
430
|
+
* WarnResult.fromNullables({
|
|
431
|
+
* warnings: null,
|
|
432
|
+
* success: null,
|
|
433
|
+
* orElse: () => WarnResult.WarningsOnly({ warnings: "none" })
|
|
434
|
+
* }),
|
|
435
|
+
* WarnResult.WarningsOnly({ warnings: "none" })
|
|
436
|
+
* )
|
|
437
|
+
* ```
|
|
438
|
+
*
|
|
439
|
+
* @category constructors
|
|
440
|
+
* @since 0.0.0
|
|
441
|
+
*/
|
|
442
|
+
export const fromNullables = <W, A>({
|
|
443
|
+
warnings,
|
|
444
|
+
success,
|
|
445
|
+
orElse = () => {
|
|
446
|
+
throw new Error("Both warnings and success are nullish");
|
|
447
|
+
},
|
|
448
|
+
}: {
|
|
449
|
+
warnings?: W | null | undefined;
|
|
450
|
+
success?: A | null | undefined;
|
|
451
|
+
orElse?: () => WarnResult<W, A>;
|
|
452
|
+
}): WarnResult<W, A> =>
|
|
453
|
+
pipe(optionFromNullables({ warnings, success }), Option.getOrElse(orElse));
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Folds a `WarnResult` from the warnings' perspective, collapsing the three tags
|
|
457
|
+
* into two handlers.
|
|
458
|
+
*
|
|
459
|
+
* Both `WarningsOnly` and `SuccessWithWarnings` carry `warnings`, so they route to
|
|
460
|
+
* the `Warnings` handler; only `SuccessOnly` lacks `warnings` and routes to
|
|
461
|
+
* `SuccessOnly`. Use it when you care about the `warnings` and treat the
|
|
462
|
+
* success-only case as the exception.
|
|
463
|
+
*
|
|
464
|
+
* @example
|
|
465
|
+
* ```ts
|
|
466
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
467
|
+
*
|
|
468
|
+
* const onWarnings = WarnResult.matchWarnings({
|
|
469
|
+
* Warnings: (warnings: string) => `warnings ${warnings}`,
|
|
470
|
+
* SuccessOnly: (success: number) => `success ${success}`
|
|
471
|
+
* })
|
|
472
|
+
*
|
|
473
|
+
* assert.deepStrictEqual(
|
|
474
|
+
* onWarnings(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
475
|
+
* "warnings w"
|
|
476
|
+
* )
|
|
477
|
+
* assert.deepStrictEqual(
|
|
478
|
+
* onWarnings(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })),
|
|
479
|
+
* "warnings w"
|
|
480
|
+
* )
|
|
481
|
+
* assert.deepStrictEqual(
|
|
482
|
+
* onWarnings(WarnResult.SuccessOnly({ success: 1 })),
|
|
483
|
+
* "success 1"
|
|
484
|
+
* )
|
|
485
|
+
* ```
|
|
486
|
+
*
|
|
487
|
+
* @category pattern matching
|
|
488
|
+
* @since 0.0.0
|
|
489
|
+
*/
|
|
490
|
+
export const matchWarnings =
|
|
491
|
+
<W, A, Z>({
|
|
492
|
+
Warnings,
|
|
493
|
+
SuccessOnly,
|
|
494
|
+
}: {
|
|
495
|
+
Warnings: (warnings: W) => Z;
|
|
496
|
+
SuccessOnly: (success: A) => Z;
|
|
497
|
+
}) =>
|
|
498
|
+
(warnResult: WarnResult<W, A>): Z =>
|
|
499
|
+
pipe(
|
|
500
|
+
warnResult,
|
|
501
|
+
|
|
502
|
+
match({
|
|
503
|
+
WarningsOnly: ({ warnings }) => Warnings(warnings),
|
|
504
|
+
SuccessOnly: ({ success }) => SuccessOnly(success),
|
|
505
|
+
SuccessWithWarnings: ({ warnings }) => Warnings(warnings),
|
|
506
|
+
}),
|
|
507
|
+
|
|
508
|
+
// Make Typescript happy
|
|
509
|
+
(a) => a as Z,
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Folds a `WarnResult` from the success value's perspective, collapsing the three
|
|
514
|
+
* tags into two handlers.
|
|
515
|
+
*
|
|
516
|
+
* The mirror of `matchWarnings`: both `SuccessOnly` and `SuccessWithWarnings`
|
|
517
|
+
* carry a `success` value, so they route to the `Success` handler; only
|
|
518
|
+
* `WarningsOnly` lacks a `success` value and routes to `WarningsOnly`. Use it when
|
|
519
|
+
* you care about the `success` value and treat the warnings-only case as the
|
|
520
|
+
* exception.
|
|
521
|
+
*
|
|
522
|
+
* @example
|
|
523
|
+
* ```ts
|
|
524
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
525
|
+
*
|
|
526
|
+
* const onSuccess = WarnResult.matchSuccess({
|
|
527
|
+
* WarningsOnly: (warnings: string) => `warnings ${warnings}`,
|
|
528
|
+
* Success: (success: number) => `success ${success}`
|
|
529
|
+
* })
|
|
530
|
+
*
|
|
531
|
+
* assert.deepStrictEqual(
|
|
532
|
+
* onSuccess(WarnResult.SuccessOnly({ success: 1 })),
|
|
533
|
+
* "success 1"
|
|
534
|
+
* )
|
|
535
|
+
* assert.deepStrictEqual(
|
|
536
|
+
* onSuccess(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })),
|
|
537
|
+
* "success 1"
|
|
538
|
+
* )
|
|
539
|
+
* assert.deepStrictEqual(
|
|
540
|
+
* onSuccess(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
541
|
+
* "warnings w"
|
|
542
|
+
* )
|
|
543
|
+
* ```
|
|
544
|
+
*
|
|
545
|
+
* @category pattern matching
|
|
546
|
+
* @since 0.0.0
|
|
547
|
+
*/
|
|
548
|
+
export const matchSuccess =
|
|
549
|
+
<W, A, Z>({
|
|
550
|
+
WarningsOnly,
|
|
551
|
+
Success,
|
|
552
|
+
}: {
|
|
553
|
+
WarningsOnly: (warnings: W) => Z;
|
|
554
|
+
Success: (success: A) => Z;
|
|
555
|
+
}) =>
|
|
556
|
+
(warnResult: WarnResult<W, A>): Z =>
|
|
557
|
+
pipe(
|
|
558
|
+
warnResult,
|
|
559
|
+
|
|
560
|
+
match({
|
|
561
|
+
WarningsOnly: ({ warnings }) => WarningsOnly(warnings),
|
|
562
|
+
SuccessOnly: ({ success }) => Success(success),
|
|
563
|
+
SuccessWithWarnings: ({ success }) => Success(success),
|
|
564
|
+
}),
|
|
565
|
+
|
|
566
|
+
// Make Typescript happy
|
|
567
|
+
(a) => a as Z,
|
|
568
|
+
);
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Completes a `WarnResult` into a guaranteed `SuccessWithWarnings` by filling
|
|
572
|
+
* whichever side is missing from the matching `orElse` thunk.
|
|
573
|
+
*
|
|
574
|
+
* A `SuccessWithWarnings` passes through unchanged; a `WarningsOnly` gains a
|
|
575
|
+
* `success` value from `orElseSuccess`; a `SuccessOnly` gains `warnings` from
|
|
576
|
+
* `orElseWarnings`. Use it to normalise a partial `WarnResult` into the
|
|
577
|
+
* both-present shape before reading both sides.
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* ```ts
|
|
581
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
582
|
+
*
|
|
583
|
+
* const fill = WarnResult.orElse({
|
|
584
|
+
* orElseWarnings: () => "no warnings",
|
|
585
|
+
* orElseSuccess: () => 0
|
|
586
|
+
* })
|
|
587
|
+
*
|
|
588
|
+
* assert.deepStrictEqual(
|
|
589
|
+
* fill(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
590
|
+
* WarnResult.SuccessWithWarnings({ warnings: "w", success: 0 })
|
|
591
|
+
* )
|
|
592
|
+
* assert.deepStrictEqual(
|
|
593
|
+
* fill(WarnResult.SuccessOnly({ success: 1 })),
|
|
594
|
+
* WarnResult.SuccessWithWarnings({ warnings: "no warnings", success: 1 })
|
|
595
|
+
* )
|
|
596
|
+
* ```
|
|
597
|
+
*
|
|
598
|
+
* @category getters
|
|
599
|
+
* @since 0.0.0
|
|
600
|
+
*/
|
|
601
|
+
export const orElse = <W2, A2>({
|
|
602
|
+
orElseWarnings,
|
|
603
|
+
orElseSuccess,
|
|
604
|
+
}: {
|
|
605
|
+
orElseWarnings: () => W2;
|
|
606
|
+
orElseSuccess: () => A2;
|
|
607
|
+
}): (<W, A>(
|
|
608
|
+
warnResult: WarnResult<W, A>,
|
|
609
|
+
) => SuccessWithWarnings<W | W2, A | A2>) =>
|
|
610
|
+
match({
|
|
611
|
+
WarningsOnly: ({ warnings }) =>
|
|
612
|
+
SuccessWithWarnings({ warnings, success: orElseSuccess() }),
|
|
613
|
+
SuccessOnly: ({ success }) =>
|
|
614
|
+
SuccessWithWarnings({ warnings: orElseWarnings(), success }),
|
|
615
|
+
SuccessWithWarnings: ({ warnings, success }) =>
|
|
616
|
+
SuccessWithWarnings({ warnings, success }),
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Completes a `WarnResult` into a `SuccessWithWarnings` whose missing side is
|
|
621
|
+
* filled with `undefined`.
|
|
622
|
+
*
|
|
623
|
+
* A specialisation of `orElse` that supplies `undefined` for whichever side is
|
|
624
|
+
* absent, so the result always exposes both `warnings` and `success` keys (each
|
|
625
|
+
* possibly `undefined`). Use it when you want to destructure both sides without
|
|
626
|
+
* branching on the tag.
|
|
627
|
+
*
|
|
628
|
+
* @example
|
|
629
|
+
* ```ts
|
|
630
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
631
|
+
*
|
|
632
|
+
* assert.deepStrictEqual(
|
|
633
|
+
* WarnResult.orUndefined(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
634
|
+
* WarnResult.SuccessWithWarnings({ warnings: "w", success: undefined })
|
|
635
|
+
* )
|
|
636
|
+
* assert.deepStrictEqual(
|
|
637
|
+
* WarnResult.orUndefined(WarnResult.SuccessOnly({ success: 1 })),
|
|
638
|
+
* WarnResult.SuccessWithWarnings({ warnings: undefined, success: 1 })
|
|
639
|
+
* )
|
|
640
|
+
* ```
|
|
641
|
+
*
|
|
642
|
+
* @category getters
|
|
643
|
+
* @since 0.0.0
|
|
644
|
+
*/
|
|
645
|
+
export const orUndefined = orElse({
|
|
646
|
+
orElseWarnings: () => undefined,
|
|
647
|
+
orElseSuccess: () => undefined,
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
/**
|
|
651
|
+
* Extracts the `warnings` of a `WarnResult`, falling back to `orElseReturn` when
|
|
652
|
+
* no `warnings` are present.
|
|
653
|
+
*
|
|
654
|
+
* `WarningsOnly` and `SuccessWithWarnings` return their `warnings`; `SuccessOnly`
|
|
655
|
+
* returns the result of `orElseReturn`. Use it to read the warnings with a default
|
|
656
|
+
* in one step.
|
|
657
|
+
*
|
|
658
|
+
* @example
|
|
659
|
+
* ```ts
|
|
660
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
661
|
+
*
|
|
662
|
+
* const warningsOrNone = WarnResult.warningsOrElse(() => "no warnings")
|
|
663
|
+
*
|
|
664
|
+
* assert.deepStrictEqual(
|
|
665
|
+
* warningsOrNone(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
666
|
+
* "w"
|
|
667
|
+
* )
|
|
668
|
+
* assert.deepStrictEqual(
|
|
669
|
+
* warningsOrNone(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })),
|
|
670
|
+
* "w"
|
|
671
|
+
* )
|
|
672
|
+
* assert.deepStrictEqual(
|
|
673
|
+
* warningsOrNone(WarnResult.SuccessOnly({ success: 1 })),
|
|
674
|
+
* "no warnings"
|
|
675
|
+
* )
|
|
676
|
+
* ```
|
|
677
|
+
*
|
|
678
|
+
* @category getters
|
|
679
|
+
* @since 0.0.0
|
|
680
|
+
*/
|
|
681
|
+
export const warningsOrElse =
|
|
682
|
+
<Z>(orElseReturn: () => Z) =>
|
|
683
|
+
<W, A>(warnResult: WarnResult<W, A>): W | Z =>
|
|
684
|
+
pipe(
|
|
685
|
+
warnResult,
|
|
686
|
+
orElse({
|
|
687
|
+
orElseWarnings: orElseReturn,
|
|
688
|
+
orElseSuccess: constUndefined,
|
|
689
|
+
}),
|
|
690
|
+
Struct.get("warnings"),
|
|
691
|
+
);
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Extracts the `warnings` of a `WarnResult`, returning `undefined` when no
|
|
695
|
+
* `warnings` are present.
|
|
696
|
+
*
|
|
697
|
+
* A specialisation of `warningsOrElse` whose fallback is `undefined`:
|
|
698
|
+
* `WarningsOnly` and `SuccessWithWarnings` yield their `warnings`, while
|
|
699
|
+
* `SuccessOnly` yields `undefined`.
|
|
700
|
+
*
|
|
701
|
+
* @example
|
|
702
|
+
* ```ts
|
|
703
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
704
|
+
*
|
|
705
|
+
* assert.deepStrictEqual(
|
|
706
|
+
* WarnResult.warningsOrUndefined(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
707
|
+
* "w"
|
|
708
|
+
* )
|
|
709
|
+
* assert.deepStrictEqual(
|
|
710
|
+
* WarnResult.warningsOrUndefined(WarnResult.SuccessOnly({ success: 1 })),
|
|
711
|
+
* undefined
|
|
712
|
+
* )
|
|
713
|
+
* ```
|
|
714
|
+
*
|
|
715
|
+
* @category getters
|
|
716
|
+
* @since 0.0.0
|
|
717
|
+
*/
|
|
718
|
+
export const warningsOrUndefined = warningsOrElse(() => undefined);
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* Extracts the `success` value of a `WarnResult`, falling back to `orElseReturn`
|
|
722
|
+
* when no `success` value is present.
|
|
723
|
+
*
|
|
724
|
+
* The mirror of `warningsOrElse`: `SuccessOnly` and `SuccessWithWarnings` return
|
|
725
|
+
* their `success` value; `WarningsOnly` returns the result of `orElseReturn`.
|
|
726
|
+
*
|
|
727
|
+
* @example
|
|
728
|
+
* ```ts
|
|
729
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
730
|
+
*
|
|
731
|
+
* const successOrZero = WarnResult.successOrElse(() => 0)
|
|
732
|
+
*
|
|
733
|
+
* assert.deepStrictEqual(
|
|
734
|
+
* successOrZero(WarnResult.SuccessOnly({ success: 1 })),
|
|
735
|
+
* 1
|
|
736
|
+
* )
|
|
737
|
+
* assert.deepStrictEqual(
|
|
738
|
+
* successOrZero(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
739
|
+
* 0
|
|
740
|
+
* )
|
|
741
|
+
* ```
|
|
742
|
+
*
|
|
743
|
+
* @category getters
|
|
744
|
+
* @since 0.0.0
|
|
745
|
+
*/
|
|
746
|
+
export const successOrElse =
|
|
747
|
+
<Z>(orElseReturn: () => Z) =>
|
|
748
|
+
<W, A>(warnResult: WarnResult<W, A>): A | Z =>
|
|
749
|
+
pipe(
|
|
750
|
+
warnResult,
|
|
751
|
+
orElse({
|
|
752
|
+
orElseWarnings: constUndefined,
|
|
753
|
+
orElseSuccess: orElseReturn,
|
|
754
|
+
}),
|
|
755
|
+
Struct.get("success"),
|
|
756
|
+
);
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Extracts the `success` value of a `WarnResult`, returning `undefined` when no
|
|
760
|
+
* `success` value is present.
|
|
761
|
+
*
|
|
762
|
+
* A specialisation of `successOrElse` whose fallback is `undefined`: `SuccessOnly`
|
|
763
|
+
* and `SuccessWithWarnings` yield their `success` value, while `WarningsOnly`
|
|
764
|
+
* yields `undefined`.
|
|
765
|
+
*
|
|
766
|
+
* @example
|
|
767
|
+
* ```ts
|
|
768
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
769
|
+
*
|
|
770
|
+
* assert.deepStrictEqual(
|
|
771
|
+
* WarnResult.successOrUndefined(WarnResult.SuccessOnly({ success: 1 })),
|
|
772
|
+
* 1
|
|
773
|
+
* )
|
|
774
|
+
* assert.deepStrictEqual(
|
|
775
|
+
* WarnResult.successOrUndefined(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
776
|
+
* undefined
|
|
777
|
+
* )
|
|
778
|
+
* ```
|
|
779
|
+
*
|
|
780
|
+
* @category getters
|
|
781
|
+
* @since 0.0.0
|
|
782
|
+
*/
|
|
783
|
+
export const successOrUndefined = successOrElse(() => undefined);
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* Extracts the `success` value of a `WarnResult` as an `Option`.
|
|
787
|
+
*
|
|
788
|
+
* `SuccessOnly` and `SuccessWithWarnings` yield `Option.some(success)`;
|
|
789
|
+
* `WarningsOnly` yields `Option.none()`. Use it when you want to chain the success
|
|
790
|
+
* value through `Option` combinators rather than fall back to a default eagerly.
|
|
791
|
+
*
|
|
792
|
+
* @example
|
|
793
|
+
* ```ts
|
|
794
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
795
|
+
* import { Option } from "effect"
|
|
796
|
+
*
|
|
797
|
+
* assert.deepStrictEqual(
|
|
798
|
+
* WarnResult.successOption(WarnResult.SuccessOnly({ success: 1 })),
|
|
799
|
+
* Option.some(1)
|
|
800
|
+
* )
|
|
801
|
+
* assert.deepStrictEqual(
|
|
802
|
+
* WarnResult.successOption(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
803
|
+
* Option.none()
|
|
804
|
+
* )
|
|
805
|
+
* ```
|
|
806
|
+
*
|
|
807
|
+
* @category getters
|
|
808
|
+
* @since 0.0.0
|
|
809
|
+
*/
|
|
810
|
+
export const successOption = <W, A>(
|
|
811
|
+
warnResult: WarnResult<W, A>,
|
|
812
|
+
): Option.Option<A> =>
|
|
813
|
+
pipe(
|
|
814
|
+
warnResult,
|
|
815
|
+
matchSuccess({
|
|
816
|
+
WarningsOnly: () => Option.none(),
|
|
817
|
+
Success: Option.some,
|
|
818
|
+
}),
|
|
819
|
+
);
|
|
820
|
+
|
|
821
|
+
/**
|
|
822
|
+
* Extracts the `warnings` of a `WarnResult` as an `Option`.
|
|
823
|
+
*
|
|
824
|
+
* The mirror of `successOption`: `WarningsOnly` and `SuccessWithWarnings` yield
|
|
825
|
+
* `Option.some(warnings)`, while `SuccessOnly` yields `Option.none()`.
|
|
826
|
+
*
|
|
827
|
+
* @example
|
|
828
|
+
* ```ts
|
|
829
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
830
|
+
* import { Option } from "effect"
|
|
831
|
+
*
|
|
832
|
+
* assert.deepStrictEqual(
|
|
833
|
+
* WarnResult.warningsOption(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
834
|
+
* Option.some("w")
|
|
835
|
+
* )
|
|
836
|
+
* assert.deepStrictEqual(
|
|
837
|
+
* WarnResult.warningsOption(WarnResult.SuccessOnly({ success: 1 })),
|
|
838
|
+
* Option.none()
|
|
839
|
+
* )
|
|
840
|
+
* ```
|
|
841
|
+
*
|
|
842
|
+
* @category getters
|
|
843
|
+
* @since 0.0.0
|
|
844
|
+
*/
|
|
845
|
+
export const warningsOption = <W, A>(
|
|
846
|
+
warnResult: WarnResult<W, A>,
|
|
847
|
+
): Option.Option<W> =>
|
|
848
|
+
pipe(
|
|
849
|
+
warnResult,
|
|
850
|
+
matchWarnings({
|
|
851
|
+
Warnings: Option.some,
|
|
852
|
+
SuccessOnly: () => Option.none(),
|
|
853
|
+
}),
|
|
854
|
+
);
|
|
855
|
+
|
|
856
|
+
/**
|
|
857
|
+
* Transforms both sides of a `WarnResult`, applying `mapWarnings` to any
|
|
858
|
+
* `warnings` and `mapSuccess` to any `success` value.
|
|
859
|
+
*
|
|
860
|
+
* Each constructor is rebuilt with its mapped contents, so `WarningsOnly` maps
|
|
861
|
+
* only the warnings, `SuccessOnly` only the success value, and
|
|
862
|
+
* `SuccessWithWarnings` both. The tag is preserved. Use it as the bifunctor map
|
|
863
|
+
* over `WarnResult`.
|
|
864
|
+
*
|
|
865
|
+
* @example
|
|
866
|
+
* ```ts
|
|
867
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
868
|
+
*
|
|
869
|
+
* const both = WarnResult.mapBoth({
|
|
870
|
+
* mapWarnings: (warnings: string) => warnings.toUpperCase(),
|
|
871
|
+
* mapSuccess: (success: number) => success + 1
|
|
872
|
+
* })
|
|
873
|
+
*
|
|
874
|
+
* assert.deepStrictEqual(
|
|
875
|
+
* both(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })),
|
|
876
|
+
* WarnResult.SuccessWithWarnings({ warnings: "W", success: 2 })
|
|
877
|
+
* )
|
|
878
|
+
* assert.deepStrictEqual(
|
|
879
|
+
* both(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
880
|
+
* WarnResult.WarningsOnly({ warnings: "W" })
|
|
881
|
+
* )
|
|
882
|
+
* ```
|
|
883
|
+
*
|
|
884
|
+
* @category mapping
|
|
885
|
+
* @since 0.0.0
|
|
886
|
+
*/
|
|
887
|
+
export const mapBoth = <W1, A1, W2, A2>({
|
|
888
|
+
mapWarnings,
|
|
889
|
+
mapSuccess,
|
|
890
|
+
}: {
|
|
891
|
+
mapWarnings: (warnings: W1) => W2;
|
|
892
|
+
mapSuccess: (success: A1) => A2;
|
|
893
|
+
}): ((warnResult: WarnResult<W1, A1>) => WarnResult<W2, A2>) =>
|
|
894
|
+
match({
|
|
895
|
+
WarningsOnly: ({ warnings }) =>
|
|
896
|
+
WarningsOnly({ warnings: mapWarnings(warnings) }),
|
|
897
|
+
SuccessOnly: ({ success }) => SuccessOnly({ success: mapSuccess(success) }),
|
|
898
|
+
SuccessWithWarnings: ({ warnings, success }) =>
|
|
899
|
+
SuccessWithWarnings({
|
|
900
|
+
warnings: mapWarnings(warnings),
|
|
901
|
+
success: mapSuccess(success),
|
|
902
|
+
}),
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
/**
|
|
906
|
+
* Effectful `mapBoth`: transforms each present side through an `Effect`,
|
|
907
|
+
* reassembling the results into a `WarnResult` inside an `Effect`.
|
|
908
|
+
*
|
|
909
|
+
* For `SuccessWithWarnings` both effects run via `Effect.all` and their results
|
|
910
|
+
* are combined; `WarningsOnly`/`SuccessOnly` run only the relevant effect. Errors
|
|
911
|
+
* and requirements from both mappers are unioned into the result type. Use it when
|
|
912
|
+
* mapping a `WarnResult`'s sides requires effects (validation, IO).
|
|
913
|
+
*
|
|
914
|
+
* @example
|
|
915
|
+
* ```ts
|
|
916
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
917
|
+
* import { Effect } from "effect"
|
|
918
|
+
*
|
|
919
|
+
* const both = WarnResult.mapBothEffect({
|
|
920
|
+
* mapWarnings: (warnings: string) => Effect.succeed(warnings.toUpperCase()),
|
|
921
|
+
* mapSuccess: (success: number) => Effect.succeed(success + 1)
|
|
922
|
+
* })
|
|
923
|
+
*
|
|
924
|
+
* assert.deepStrictEqual(
|
|
925
|
+
* Effect.runSync(
|
|
926
|
+
* both(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 }))
|
|
927
|
+
* ),
|
|
928
|
+
* WarnResult.SuccessWithWarnings({ warnings: "W", success: 2 })
|
|
929
|
+
* )
|
|
930
|
+
* ```
|
|
931
|
+
*
|
|
932
|
+
* @category sequencing
|
|
933
|
+
* @since 0.0.0
|
|
934
|
+
*/
|
|
935
|
+
export const mapBothEffect = <W1, A1, W2, A2, EW, EA, RW, RA>({
|
|
936
|
+
mapWarnings,
|
|
937
|
+
mapSuccess,
|
|
938
|
+
}: {
|
|
939
|
+
mapWarnings: (warnings: W1) => Effect.Effect<W2, EW, RW>;
|
|
940
|
+
mapSuccess: (success: A1) => Effect.Effect<A2, EA, RA>;
|
|
941
|
+
}): ((
|
|
942
|
+
warnResult: WarnResult<W1, A1>,
|
|
943
|
+
) => Effect.Effect<WarnResult<W2, A2>, EW | EA, RW | RA>) =>
|
|
944
|
+
match({
|
|
945
|
+
WarningsOnly: ({ warnings }) =>
|
|
946
|
+
pipe(
|
|
947
|
+
mapWarnings(warnings),
|
|
948
|
+
Effect.map((warnings2) => WarningsOnly({ warnings: warnings2 })),
|
|
949
|
+
),
|
|
950
|
+
|
|
951
|
+
SuccessOnly: ({ success }) =>
|
|
952
|
+
pipe(
|
|
953
|
+
mapSuccess(success),
|
|
954
|
+
Effect.map((success2) => SuccessOnly({ success: success2 })),
|
|
955
|
+
),
|
|
956
|
+
|
|
957
|
+
SuccessWithWarnings: ({ warnings, success }) =>
|
|
958
|
+
pipe(
|
|
959
|
+
Effect.all({
|
|
960
|
+
warnings: mapWarnings(warnings),
|
|
961
|
+
success: mapSuccess(success),
|
|
962
|
+
}),
|
|
963
|
+
Effect.map(({ warnings: warnings2, success: success2 }) =>
|
|
964
|
+
SuccessWithWarnings({ warnings: warnings2, success: success2 }),
|
|
965
|
+
),
|
|
966
|
+
),
|
|
967
|
+
});
|
|
968
|
+
|
|
969
|
+
/**
|
|
970
|
+
* Transforms the `warnings` of a `WarnResult`, leaving any `success` value
|
|
971
|
+
* untouched.
|
|
972
|
+
*
|
|
973
|
+
* A specialisation of `mapBoth` with the success mapper set to `identity`:
|
|
974
|
+
* `WarningsOnly` and `SuccessWithWarnings` have their `warnings` mapped, while
|
|
975
|
+
* `SuccessOnly` passes through unchanged.
|
|
976
|
+
*
|
|
977
|
+
* @example
|
|
978
|
+
* ```ts
|
|
979
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
980
|
+
*
|
|
981
|
+
* const shout = WarnResult.mapWarnings((warnings: string) =>
|
|
982
|
+
* warnings.toUpperCase()
|
|
983
|
+
* )
|
|
984
|
+
*
|
|
985
|
+
* assert.deepStrictEqual(
|
|
986
|
+
* shout(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })),
|
|
987
|
+
* WarnResult.SuccessWithWarnings({ warnings: "W", success: 1 })
|
|
988
|
+
* )
|
|
989
|
+
* assert.deepStrictEqual(
|
|
990
|
+
* shout(WarnResult.SuccessOnly({ success: 1 })),
|
|
991
|
+
* WarnResult.SuccessOnly({ success: 1 })
|
|
992
|
+
* )
|
|
993
|
+
* ```
|
|
994
|
+
*
|
|
995
|
+
* @category mapping
|
|
996
|
+
* @since 0.0.0
|
|
997
|
+
*/
|
|
998
|
+
export const mapWarnings = <W1, W2>(
|
|
999
|
+
mapWarnings: (warnings: W1) => W2,
|
|
1000
|
+
): (<A>(warnResult: WarnResult<W1, A>) => WarnResult<W2, A>) =>
|
|
1001
|
+
mapBoth({ mapWarnings, mapSuccess: identity });
|
|
1002
|
+
|
|
1003
|
+
/**
|
|
1004
|
+
* Chains the `warnings` of a `WarnResult` into a new `WarnResult`, flattening the
|
|
1005
|
+
* result.
|
|
1006
|
+
*
|
|
1007
|
+
* Whenever `warnings` are present (`WarningsOnly` or `SuccessWithWarnings`) they
|
|
1008
|
+
* are passed to `mapWarnings`, whose returned `WarnResult` replaces the original;
|
|
1009
|
+
* `SuccessOnly` passes through unchanged. Use it to sequence warnings-driven
|
|
1010
|
+
* computations that themselves produce a `WarnResult`.
|
|
1011
|
+
*
|
|
1012
|
+
* @example
|
|
1013
|
+
* ```ts
|
|
1014
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
1015
|
+
*
|
|
1016
|
+
* const chain = WarnResult.flatMapWarnings((warnings: string) =>
|
|
1017
|
+
* warnings.length > 0
|
|
1018
|
+
* ? WarnResult.WarningsOnly({ warnings: warnings.toUpperCase() })
|
|
1019
|
+
* : WarnResult.SuccessOnly({ success: 0 })
|
|
1020
|
+
* )
|
|
1021
|
+
*
|
|
1022
|
+
* assert.deepStrictEqual(
|
|
1023
|
+
* chain(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
1024
|
+
* WarnResult.WarningsOnly({ warnings: "W" })
|
|
1025
|
+
* )
|
|
1026
|
+
* assert.deepStrictEqual(
|
|
1027
|
+
* chain(WarnResult.SuccessOnly({ success: 1 })),
|
|
1028
|
+
* WarnResult.SuccessOnly({ success: 1 })
|
|
1029
|
+
* )
|
|
1030
|
+
* ```
|
|
1031
|
+
*
|
|
1032
|
+
* @category sequencing
|
|
1033
|
+
* @since 0.0.0
|
|
1034
|
+
*/
|
|
1035
|
+
export const flatMapWarnings = <W1, W2, A2>(
|
|
1036
|
+
mapWarnings: (warnings: W1) => WarnResult<W2, A2>,
|
|
1037
|
+
): (<A1>(warnResult: WarnResult<W1, A1>) => WarnResult<W2, A1 | A2>) =>
|
|
1038
|
+
match({
|
|
1039
|
+
WarningsOnly: ({ warnings }) => mapWarnings(warnings),
|
|
1040
|
+
SuccessOnly: ({ success }) => SuccessOnly({ success }),
|
|
1041
|
+
SuccessWithWarnings: ({ warnings }) => mapWarnings(warnings),
|
|
1042
|
+
});
|
|
1043
|
+
|
|
1044
|
+
/**
|
|
1045
|
+
* Effectful `mapWarnings`: transforms the `warnings` of a `WarnResult` through an
|
|
1046
|
+
* `Effect`, leaving any `success` value untouched.
|
|
1047
|
+
*
|
|
1048
|
+
* A specialisation of `mapBothEffect` with the success mapper set to
|
|
1049
|
+
* `Effect.succeed`: the `warnings` (when present) are mapped effectfully and the
|
|
1050
|
+
* `success` value is carried through unchanged.
|
|
1051
|
+
*
|
|
1052
|
+
* @example
|
|
1053
|
+
* ```ts
|
|
1054
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
1055
|
+
* import { Effect } from "effect"
|
|
1056
|
+
*
|
|
1057
|
+
* const shout = WarnResult.mapWarningsEffect((warnings: string) =>
|
|
1058
|
+
* Effect.succeed(warnings.toUpperCase())
|
|
1059
|
+
* )
|
|
1060
|
+
*
|
|
1061
|
+
* assert.deepStrictEqual(
|
|
1062
|
+
* Effect.runSync(
|
|
1063
|
+
* shout(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 }))
|
|
1064
|
+
* ),
|
|
1065
|
+
* WarnResult.SuccessWithWarnings({ warnings: "W", success: 1 })
|
|
1066
|
+
* )
|
|
1067
|
+
* ```
|
|
1068
|
+
*
|
|
1069
|
+
* @category sequencing
|
|
1070
|
+
* @since 0.0.0
|
|
1071
|
+
*/
|
|
1072
|
+
export const mapWarningsEffect = <W1, W2, EW, RW>(
|
|
1073
|
+
mapWarnings: (warnings: W1) => Effect.Effect<W2, EW, RW>,
|
|
1074
|
+
): (<A>(
|
|
1075
|
+
warnResult: WarnResult<W1, A>,
|
|
1076
|
+
) => Effect.Effect<WarnResult<W2, A>, EW, RW>) =>
|
|
1077
|
+
mapBothEffect({ mapWarnings, mapSuccess: Effect.succeed });
|
|
1078
|
+
|
|
1079
|
+
/**
|
|
1080
|
+
* Effectful `flatMapWarnings`: chains the `warnings` of a `WarnResult` into an
|
|
1081
|
+
* `Effect` that yields a new `WarnResult`, flattening the result.
|
|
1082
|
+
*
|
|
1083
|
+
* When `warnings` are present they are passed to `mapWarnings`, whose effectful
|
|
1084
|
+
* `WarnResult` replaces the original; `SuccessOnly` is lifted unchanged via
|
|
1085
|
+
* `Effect.succeed`. Use it to sequence warnings-driven effectful computations that
|
|
1086
|
+
* produce a `WarnResult`.
|
|
1087
|
+
*
|
|
1088
|
+
* @example
|
|
1089
|
+
* ```ts
|
|
1090
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
1091
|
+
* import { Effect } from "effect"
|
|
1092
|
+
*
|
|
1093
|
+
* const chain = WarnResult.flatMapWarningsEffect((warnings: string) =>
|
|
1094
|
+
* Effect.succeed(WarnResult.WarningsOnly({ warnings: warnings.toUpperCase() }))
|
|
1095
|
+
* )
|
|
1096
|
+
*
|
|
1097
|
+
* assert.deepStrictEqual(
|
|
1098
|
+
* Effect.runSync(chain(WarnResult.WarningsOnly({ warnings: "w" }))),
|
|
1099
|
+
* WarnResult.WarningsOnly({ warnings: "W" })
|
|
1100
|
+
* )
|
|
1101
|
+
* assert.deepStrictEqual(
|
|
1102
|
+
* Effect.runSync(chain(WarnResult.SuccessOnly({ success: 1 }))),
|
|
1103
|
+
* WarnResult.SuccessOnly({ success: 1 })
|
|
1104
|
+
* )
|
|
1105
|
+
* ```
|
|
1106
|
+
*
|
|
1107
|
+
* @category sequencing
|
|
1108
|
+
* @since 0.0.0
|
|
1109
|
+
*/
|
|
1110
|
+
export const flatMapWarningsEffect = <W1, W2, A2, EW, RW>(
|
|
1111
|
+
mapWarnings: (warnings: W1) => Effect.Effect<WarnResult<W2, A2>, EW, RW>,
|
|
1112
|
+
): (<A1>(
|
|
1113
|
+
warnResult: WarnResult<W1, A1>,
|
|
1114
|
+
) => Effect.Effect<WarnResult<W2, A1 | A2>, EW, RW>) =>
|
|
1115
|
+
match({
|
|
1116
|
+
WarningsOnly: ({ warnings }) => mapWarnings(warnings),
|
|
1117
|
+
SuccessOnly: ({ success }) => Effect.succeed(SuccessOnly({ success })),
|
|
1118
|
+
SuccessWithWarnings: ({ warnings }) => mapWarnings(warnings),
|
|
1119
|
+
});
|
|
1120
|
+
|
|
1121
|
+
/**
|
|
1122
|
+
* Transforms the `success` value of a `WarnResult`, leaving any `warnings`
|
|
1123
|
+
* untouched.
|
|
1124
|
+
*
|
|
1125
|
+
* The mirror of `mapWarnings`: `SuccessOnly` and `SuccessWithWarnings` have their
|
|
1126
|
+
* `success` value mapped, while `WarningsOnly` passes through unchanged.
|
|
1127
|
+
*
|
|
1128
|
+
* @example
|
|
1129
|
+
* ```ts
|
|
1130
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
1131
|
+
*
|
|
1132
|
+
* const inc = WarnResult.mapSuccess((success: number) => success + 1)
|
|
1133
|
+
*
|
|
1134
|
+
* assert.deepStrictEqual(
|
|
1135
|
+
* inc(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 })),
|
|
1136
|
+
* WarnResult.SuccessWithWarnings({ warnings: "w", success: 2 })
|
|
1137
|
+
* )
|
|
1138
|
+
* assert.deepStrictEqual(
|
|
1139
|
+
* inc(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
1140
|
+
* WarnResult.WarningsOnly({ warnings: "w" })
|
|
1141
|
+
* )
|
|
1142
|
+
* ```
|
|
1143
|
+
*
|
|
1144
|
+
* @category mapping
|
|
1145
|
+
* @since 0.0.0
|
|
1146
|
+
*/
|
|
1147
|
+
export const mapSuccess = <A1, A2>(
|
|
1148
|
+
mapSuccess: (success: A1) => A2,
|
|
1149
|
+
): (<W>(warnResult: WarnResult<W, A1>) => WarnResult<W, A2>) =>
|
|
1150
|
+
mapBoth({ mapWarnings: identity, mapSuccess });
|
|
1151
|
+
|
|
1152
|
+
/**
|
|
1153
|
+
* Chains the `success` value of a `WarnResult` into a new `WarnResult`, flattening
|
|
1154
|
+
* the result.
|
|
1155
|
+
*
|
|
1156
|
+
* The mirror of `flatMapWarnings`: whenever a `success` value is present
|
|
1157
|
+
* (`SuccessOnly` or `SuccessWithWarnings`) it is passed to `mapSuccess`, whose
|
|
1158
|
+
* returned `WarnResult` replaces the original; `WarningsOnly` passes through
|
|
1159
|
+
* unchanged.
|
|
1160
|
+
*
|
|
1161
|
+
* @example
|
|
1162
|
+
* ```ts
|
|
1163
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
1164
|
+
*
|
|
1165
|
+
* const chain = WarnResult.flatMapSuccess((success: number) =>
|
|
1166
|
+
* WarnResult.SuccessOnly({ success: success + 1 })
|
|
1167
|
+
* )
|
|
1168
|
+
*
|
|
1169
|
+
* assert.deepStrictEqual(
|
|
1170
|
+
* chain(WarnResult.SuccessOnly({ success: 1 })),
|
|
1171
|
+
* WarnResult.SuccessOnly({ success: 2 })
|
|
1172
|
+
* )
|
|
1173
|
+
* assert.deepStrictEqual(
|
|
1174
|
+
* chain(WarnResult.WarningsOnly({ warnings: "w" })),
|
|
1175
|
+
* WarnResult.WarningsOnly({ warnings: "w" })
|
|
1176
|
+
* )
|
|
1177
|
+
* ```
|
|
1178
|
+
*
|
|
1179
|
+
* @category sequencing
|
|
1180
|
+
* @since 0.0.0
|
|
1181
|
+
*/
|
|
1182
|
+
export const flatMapSuccess = <W2, A1, A2>(
|
|
1183
|
+
mapSuccess: (success: A1) => WarnResult<W2, A2>,
|
|
1184
|
+
): (<W1>(warnResult: WarnResult<W1, A1>) => WarnResult<W1 | W2, A2>) =>
|
|
1185
|
+
match({
|
|
1186
|
+
WarningsOnly: ({ warnings }) => WarningsOnly({ warnings }),
|
|
1187
|
+
SuccessOnly: ({ success }) => mapSuccess(success),
|
|
1188
|
+
SuccessWithWarnings: ({ success }) => mapSuccess(success),
|
|
1189
|
+
});
|
|
1190
|
+
|
|
1191
|
+
/**
|
|
1192
|
+
* Effectful `mapSuccess`: transforms the `success` value of a `WarnResult` through
|
|
1193
|
+
* an `Effect`, leaving any `warnings` untouched.
|
|
1194
|
+
*
|
|
1195
|
+
* The mirror of `mapWarningsEffect`: the `success` value (when present) is mapped
|
|
1196
|
+
* effectfully and the `warnings` are carried through unchanged via
|
|
1197
|
+
* `Effect.succeed`.
|
|
1198
|
+
*
|
|
1199
|
+
* @example
|
|
1200
|
+
* ```ts
|
|
1201
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
1202
|
+
* import { Effect } from "effect"
|
|
1203
|
+
*
|
|
1204
|
+
* const inc = WarnResult.mapSuccessEffect((success: number) =>
|
|
1205
|
+
* Effect.succeed(success + 1)
|
|
1206
|
+
* )
|
|
1207
|
+
*
|
|
1208
|
+
* assert.deepStrictEqual(
|
|
1209
|
+
* Effect.runSync(
|
|
1210
|
+
* inc(WarnResult.SuccessWithWarnings({ warnings: "w", success: 1 }))
|
|
1211
|
+
* ),
|
|
1212
|
+
* WarnResult.SuccessWithWarnings({ warnings: "w", success: 2 })
|
|
1213
|
+
* )
|
|
1214
|
+
* ```
|
|
1215
|
+
*
|
|
1216
|
+
* @category sequencing
|
|
1217
|
+
* @since 0.0.0
|
|
1218
|
+
*/
|
|
1219
|
+
export const mapSuccessEffect = <A1, A2, EA, RA>(
|
|
1220
|
+
mapSuccess: (success: A1) => Effect.Effect<A2, EA, RA>,
|
|
1221
|
+
): (<W>(
|
|
1222
|
+
warnResult: WarnResult<W, A1>,
|
|
1223
|
+
) => Effect.Effect<WarnResult<W, A2>, EA, RA>) =>
|
|
1224
|
+
mapBothEffect({ mapWarnings: Effect.succeed, mapSuccess });
|
|
1225
|
+
|
|
1226
|
+
/**
|
|
1227
|
+
* Effectful `flatMapSuccess`: chains the `success` value of a `WarnResult` into an
|
|
1228
|
+
* `Effect` that yields a new `WarnResult`, flattening the result.
|
|
1229
|
+
*
|
|
1230
|
+
* The mirror of `flatMapWarningsEffect`: when a `success` value is present it is
|
|
1231
|
+
* passed to `mapSuccess`, whose effectful `WarnResult` replaces the original;
|
|
1232
|
+
* `WarningsOnly` is lifted unchanged via `Effect.succeed`.
|
|
1233
|
+
*
|
|
1234
|
+
* @example
|
|
1235
|
+
* ```ts
|
|
1236
|
+
* import { WarnResult } from "@nunofyobiz/effect-extras"
|
|
1237
|
+
* import { Effect } from "effect"
|
|
1238
|
+
*
|
|
1239
|
+
* const chain = WarnResult.flatMapSuccessEffect((success: number) =>
|
|
1240
|
+
* Effect.succeed(WarnResult.SuccessOnly({ success: success + 1 }))
|
|
1241
|
+
* )
|
|
1242
|
+
*
|
|
1243
|
+
* assert.deepStrictEqual(
|
|
1244
|
+
* Effect.runSync(chain(WarnResult.SuccessOnly({ success: 1 }))),
|
|
1245
|
+
* WarnResult.SuccessOnly({ success: 2 })
|
|
1246
|
+
* )
|
|
1247
|
+
* assert.deepStrictEqual(
|
|
1248
|
+
* Effect.runSync(chain(WarnResult.WarningsOnly({ warnings: "w" }))),
|
|
1249
|
+
* WarnResult.WarningsOnly({ warnings: "w" })
|
|
1250
|
+
* )
|
|
1251
|
+
* ```
|
|
1252
|
+
*
|
|
1253
|
+
* @category sequencing
|
|
1254
|
+
* @since 0.0.0
|
|
1255
|
+
*/
|
|
1256
|
+
export const flatMapSuccessEffect = <W2, A1, A2, EA, RA>(
|
|
1257
|
+
mapSuccess: (success: A1) => Effect.Effect<WarnResult<W2, A2>, EA, RA>,
|
|
1258
|
+
): (<W1>(
|
|
1259
|
+
warnResult: WarnResult<W1, A1>,
|
|
1260
|
+
) => Effect.Effect<WarnResult<W1 | W2, A2>, EA, RA>) =>
|
|
1261
|
+
match({
|
|
1262
|
+
WarningsOnly: ({ warnings }) => Effect.succeed(WarningsOnly({ warnings })),
|
|
1263
|
+
SuccessOnly: ({ success }) => mapSuccess(success),
|
|
1264
|
+
SuccessWithWarnings: ({ success }) => mapSuccess(success),
|
|
1265
|
+
});
|