retuple 1.0.0-next.2 → 1.0.0-next.21
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 +14 -1
- package/dist/index.cjs +538 -112
- package/dist/index.d.cts +1343 -297
- package/dist/index.d.ts +1343 -297
- package/dist/index.js +534 -106
- package/package.json +13 -10
package/dist/index.js
CHANGED
|
@@ -9,61 +9,209 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _ResultAsync_inner;
|
|
12
|
+
var _ResultAsync_inner, _a, _ResultRetry_f, _ResultRetry_promise, _ResultRetry_times, _ResultRetry_attempt, _ResultRetry_aborted, _ResultRetry_abort, _ResultRetry_getDelay, _ResultRetry_handler;
|
|
13
|
+
import { ResultLikeSymbol, } from "retuple-symbols";
|
|
14
|
+
/**
|
|
15
|
+
* ## Retuple Unwrap Failed
|
|
16
|
+
*
|
|
17
|
+
* An error which occurs when calling `$unwrap` on `Err`.
|
|
18
|
+
*/
|
|
13
19
|
export class RetupleUnwrapFailed extends Error {
|
|
14
20
|
constructor(value, msg = "Unwrap failed") {
|
|
15
21
|
super(msg, value instanceof Error ? { cause: value } : undefined);
|
|
16
22
|
this.value = value;
|
|
17
23
|
}
|
|
18
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* ## Retuple Unwrap Err Failed
|
|
27
|
+
*
|
|
28
|
+
* An error which occurs when calling `$unwrapErr` on `Ok`.
|
|
29
|
+
*/
|
|
19
30
|
export class RetupleUnwrapErrFailed extends Error {
|
|
20
31
|
constructor(value, msg = "Unwrap error failed") {
|
|
21
32
|
super(msg);
|
|
22
33
|
this.value = value;
|
|
23
34
|
}
|
|
24
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* ## Retuple Expect Failed
|
|
38
|
+
*
|
|
39
|
+
* An error which occurs when calling `$expect` on `Err`, when the value
|
|
40
|
+
* contained in the `Err` is not an instance of `Error`.
|
|
41
|
+
*/
|
|
25
42
|
export class RetupleExpectFailed extends Error {
|
|
26
43
|
constructor(value) {
|
|
27
44
|
super("Expect failed");
|
|
28
45
|
this.value = value;
|
|
29
46
|
}
|
|
30
47
|
}
|
|
31
|
-
|
|
48
|
+
/**
|
|
49
|
+
* ## Retuple Thrown Value Error
|
|
50
|
+
*
|
|
51
|
+
* An error constructed when a safe function call throws or rejects, when the
|
|
52
|
+
* thrown error or rejected value is not an instance of `Error`, and when no
|
|
53
|
+
* map error function is provided.
|
|
54
|
+
*/
|
|
55
|
+
export class RetupleCaughtValueError extends Error {
|
|
32
56
|
constructor(value) {
|
|
33
57
|
super("Caught value was not an instance of Error");
|
|
34
58
|
this.value = value;
|
|
35
59
|
}
|
|
36
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* ## Retuple Invalid Union Error
|
|
63
|
+
*
|
|
64
|
+
* This error is thrown when attempting to construct a `Result` from a
|
|
65
|
+
* discriminated union, when the 'success' property is not boolean. In this
|
|
66
|
+
* case, it is impossible to determine whether the result should be `Ok` or
|
|
67
|
+
* `Err`.
|
|
68
|
+
*/
|
|
69
|
+
export class RetupleInvalidUnionError extends Error {
|
|
70
|
+
constructor(value) {
|
|
71
|
+
super("Constructing a Result from discriminated union failed, the success " +
|
|
72
|
+
"property must be boolean");
|
|
73
|
+
this.value = value;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
37
76
|
/**
|
|
38
77
|
* ## Result
|
|
39
78
|
*
|
|
40
79
|
* @TODO
|
|
41
80
|
*/
|
|
42
|
-
export
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
81
|
+
export function Result(resultLike) {
|
|
82
|
+
return asResult(resultLike);
|
|
83
|
+
}
|
|
84
|
+
Result.Ok = Ok;
|
|
85
|
+
Result.Err = Err;
|
|
86
|
+
Result.$from = $from;
|
|
87
|
+
Result.$resolve = $resolve;
|
|
88
|
+
Result.$nonNullable = $nonNullable;
|
|
89
|
+
Result.$truthy = $truthy;
|
|
90
|
+
Result.$fromUnion = $fromUnion;
|
|
91
|
+
Result.$safe = $safe;
|
|
92
|
+
Result.$safeAsync = $safeAsync;
|
|
93
|
+
Result.$safePromise = $safePromise;
|
|
94
|
+
Result.$retry = $retry;
|
|
95
|
+
Result.$safeRetry = $safeRetry;
|
|
96
|
+
Object.freeze(Result);
|
|
51
97
|
export function Ok(val) {
|
|
52
98
|
return new ResultOk(val);
|
|
53
99
|
}
|
|
54
100
|
export function Err(err) {
|
|
55
101
|
return new ResultErr(err);
|
|
56
102
|
}
|
|
57
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Construct a {@link Result} from a {@link ResultLike}.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
*
|
|
108
|
+
* ```ts
|
|
109
|
+
* const value: Result<T, E> | ResultLike<T, E> = someResultFn();
|
|
110
|
+
* const result: Result<T, E> = Result.$from(result);
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
function $from(result) {
|
|
114
|
+
if (result instanceof ResultOk || result instanceof ResultErr) {
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
return asResult(result);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Construct a {@link ResultAsync} from a {@link ResultLikeAwaitable}.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
*
|
|
124
|
+
* ```ts
|
|
125
|
+
* const value:
|
|
126
|
+
* | Result<T, E>
|
|
127
|
+
* | ResultLike<T, E>
|
|
128
|
+
* | ResultAsync<T, E>
|
|
129
|
+
* | Promise<Result<T, E>>
|
|
130
|
+
* | Promise<ResultLike<T, E>>
|
|
131
|
+
* | PromiseLike<Result<T, E>>
|
|
132
|
+
* | PromiseLike<ResultLike<T, E>> = someResultFn();
|
|
133
|
+
*
|
|
134
|
+
* const result: ResultAsync<T, E> = Result.$resolve(result);
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
function $resolve(result) {
|
|
138
|
+
switch (true) {
|
|
139
|
+
case result instanceof ResultAsync:
|
|
140
|
+
return result;
|
|
141
|
+
case result instanceof ResultOk:
|
|
142
|
+
case result instanceof ResultErr:
|
|
143
|
+
return new ResultAsync(Promise.resolve(result));
|
|
144
|
+
default:
|
|
145
|
+
return new ResultAsync(Promise.resolve(result).then((asResult)));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function $nonNullable(value, error = mapTrue) {
|
|
149
|
+
if (value !== null && value !== undefined) {
|
|
150
|
+
return Ok(value);
|
|
151
|
+
}
|
|
152
|
+
return Err(error());
|
|
153
|
+
}
|
|
154
|
+
function $truthy(value, error = mapTrue) {
|
|
58
155
|
if (value) {
|
|
59
|
-
return
|
|
156
|
+
return Ok(value);
|
|
157
|
+
}
|
|
158
|
+
return Err(error());
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Construct a {@link Result} from a common discriminated union shape. If the
|
|
162
|
+
* union is 'success' then the result is `Ok`
|
|
163
|
+
*
|
|
164
|
+
* Otherwise, the result is `Err` containing:
|
|
165
|
+
*
|
|
166
|
+
* - the returned value from the error function when provided;
|
|
167
|
+
* - or `true` otherwise.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
*
|
|
171
|
+
* ```ts
|
|
172
|
+
* const result: Result<string, Error> = Result.$truthy(
|
|
173
|
+
* username.trim(),
|
|
174
|
+
* () => new Error("Username is empty"),
|
|
175
|
+
* );
|
|
176
|
+
* ```
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
*
|
|
180
|
+
* ```ts
|
|
181
|
+
* const [err, value] = Result.$truthy("test");
|
|
182
|
+
*
|
|
183
|
+
* assert.equal(err, undefined);
|
|
184
|
+
* assert.equal(value, "test");
|
|
185
|
+
* ```
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
*
|
|
189
|
+
* ```ts
|
|
190
|
+
* const [err, value] = Result.$truthy("");
|
|
191
|
+
*
|
|
192
|
+
* assert.equal(err, true);
|
|
193
|
+
* assert.equal(value, undefined);
|
|
194
|
+
* ```
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
*
|
|
198
|
+
* ```ts
|
|
199
|
+
* const [err, value] = Result.$truthy(0, () => "error");
|
|
200
|
+
*
|
|
201
|
+
* assert.equal(err, "error");
|
|
202
|
+
* assert.equal(value, undefined);
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
function $fromUnion(union) {
|
|
206
|
+
if (union.success === true) {
|
|
207
|
+
return Ok(union.data);
|
|
60
208
|
}
|
|
61
|
-
if (
|
|
62
|
-
return
|
|
209
|
+
if (union.success === false) {
|
|
210
|
+
return Err(union.error);
|
|
63
211
|
}
|
|
64
|
-
|
|
212
|
+
throw new RetupleInvalidUnionError(union);
|
|
65
213
|
}
|
|
66
|
-
|
|
214
|
+
function $safe(f, mapError = ensureError) {
|
|
67
215
|
try {
|
|
68
216
|
return Ok(f());
|
|
69
217
|
}
|
|
@@ -71,7 +219,7 @@ export function safe(f, mapError = ensureError) {
|
|
|
71
219
|
return Err(mapError(err));
|
|
72
220
|
}
|
|
73
221
|
}
|
|
74
|
-
|
|
222
|
+
function $safeAsync(f, mapError = ensureError) {
|
|
75
223
|
return new ResultAsync((async () => {
|
|
76
224
|
try {
|
|
77
225
|
return Ok(await f());
|
|
@@ -81,13 +229,42 @@ export function safeAsync(f, mapError = ensureError) {
|
|
|
81
229
|
}
|
|
82
230
|
})());
|
|
83
231
|
}
|
|
84
|
-
|
|
232
|
+
function $safePromise(promise, mapError = ensureError) {
|
|
85
233
|
return new ResultAsync(promise.then((Ok), async (err) => Err(await mapError(err))));
|
|
86
234
|
}
|
|
87
235
|
/**
|
|
88
|
-
*
|
|
236
|
+
* Construct a {@link ResultRetry} from a function which returns a
|
|
237
|
+
* {@link Result}. The function will be retried based on provided retry
|
|
238
|
+
* settings and eventually return a `Result`. No attempt is made to catch
|
|
239
|
+
* thrown errors or promise rejections.
|
|
89
240
|
*
|
|
90
|
-
* @
|
|
241
|
+
* To retry a potentially unsafe function, use {@link Result.$safeRetry}.
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
*
|
|
245
|
+
* ```ts
|
|
246
|
+
* // Retry someResultFn up to 3 times until Ok is returned,
|
|
247
|
+
* // with a 1 second delay between each invocation:
|
|
248
|
+
* const result = await Result.$retry(someResultFn).$times(3).$delay(1000);
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
function $retry(f) {
|
|
252
|
+
return new ResultRetry(f);
|
|
253
|
+
}
|
|
254
|
+
function $safeRetry(f, mapError = ensureError) {
|
|
255
|
+
return new ResultRetry(async () => {
|
|
256
|
+
try {
|
|
257
|
+
return Ok(await f());
|
|
258
|
+
}
|
|
259
|
+
catch (err) {
|
|
260
|
+
return Err(mapError(err));
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* ## ResultOk
|
|
266
|
+
*
|
|
267
|
+
* This is the `Ok` variant of a `Result`, used internally and not exported.
|
|
91
268
|
*/
|
|
92
269
|
class ResultOk extends Array {
|
|
93
270
|
constructor(value) {
|
|
@@ -95,14 +272,17 @@ class ResultOk extends Array {
|
|
|
95
272
|
this[0] = undefined;
|
|
96
273
|
this[1] = value;
|
|
97
274
|
}
|
|
98
|
-
|
|
275
|
+
[ResultLikeSymbol]() {
|
|
276
|
+
return { ok: true, value: this[1] };
|
|
277
|
+
}
|
|
278
|
+
toJSON() {
|
|
99
279
|
return this[1];
|
|
100
280
|
}
|
|
101
281
|
$isOk() {
|
|
102
282
|
return true;
|
|
103
283
|
}
|
|
104
284
|
$isOkAnd(f) {
|
|
105
|
-
return f(this[1]);
|
|
285
|
+
return !!f(this[1]);
|
|
106
286
|
}
|
|
107
287
|
$isErr() {
|
|
108
288
|
return false;
|
|
@@ -126,44 +306,77 @@ class ResultOk extends Array {
|
|
|
126
306
|
return this[1];
|
|
127
307
|
}
|
|
128
308
|
$map(f) {
|
|
129
|
-
return
|
|
309
|
+
return Ok(f(this[1]));
|
|
130
310
|
}
|
|
131
311
|
$mapErr() {
|
|
132
312
|
return this;
|
|
133
313
|
}
|
|
134
314
|
$mapOr(_def, f) {
|
|
135
|
-
return
|
|
315
|
+
return Ok(f(this[1]));
|
|
136
316
|
}
|
|
137
317
|
$mapOrElse(_def, f) {
|
|
138
|
-
return
|
|
318
|
+
return Ok(f(this[1]));
|
|
319
|
+
}
|
|
320
|
+
$andAssertOr(def, condition = isTruthy) {
|
|
321
|
+
return condition(this[1]) ? this : asResult(def);
|
|
322
|
+
}
|
|
323
|
+
$andAssertOrElse(def, condition = isTruthy) {
|
|
324
|
+
return condition(this[1]) ? this : asResult(def(this[1]));
|
|
139
325
|
}
|
|
140
326
|
$or() {
|
|
141
327
|
return this;
|
|
142
328
|
}
|
|
329
|
+
$orAsync() {
|
|
330
|
+
return this.$async();
|
|
331
|
+
}
|
|
143
332
|
$orElse() {
|
|
144
333
|
return this;
|
|
145
334
|
}
|
|
335
|
+
$orElseAsync() {
|
|
336
|
+
return this.$async();
|
|
337
|
+
}
|
|
146
338
|
$orSafe() {
|
|
147
339
|
return this;
|
|
148
340
|
}
|
|
341
|
+
$orSafeAsync() {
|
|
342
|
+
return this.$async();
|
|
343
|
+
}
|
|
344
|
+
$orSafePromise() {
|
|
345
|
+
return this.$async();
|
|
346
|
+
}
|
|
149
347
|
$and(and) {
|
|
150
|
-
return and;
|
|
348
|
+
return asResult(and);
|
|
349
|
+
}
|
|
350
|
+
$andAsync(and) {
|
|
351
|
+
return this.$async().$and(and);
|
|
151
352
|
}
|
|
152
353
|
$andThen(f) {
|
|
153
|
-
return f(this[1]);
|
|
354
|
+
return asResult(f(this[1]));
|
|
355
|
+
}
|
|
356
|
+
$andThenAsync(f) {
|
|
357
|
+
return this.$async().$andThen(f);
|
|
154
358
|
}
|
|
155
359
|
$andThrough(f) {
|
|
156
|
-
const res = f(this[1]);
|
|
360
|
+
const res = asResult(f(this[1]));
|
|
157
361
|
return res instanceof ResultErr ? res : this;
|
|
158
362
|
}
|
|
363
|
+
$andThroughAsync(f) {
|
|
364
|
+
return this.$async().$andThrough(f);
|
|
365
|
+
}
|
|
159
366
|
$andSafe(f, mapError = ensureError) {
|
|
160
367
|
try {
|
|
161
|
-
return
|
|
368
|
+
return Ok(f(this[1]));
|
|
162
369
|
}
|
|
163
370
|
catch (err) {
|
|
164
|
-
return
|
|
371
|
+
return Err(mapError(err));
|
|
165
372
|
}
|
|
166
373
|
}
|
|
374
|
+
$andSafeAsync(f, mapError = ensureError) {
|
|
375
|
+
return this.$async().$andSafe(f, mapError);
|
|
376
|
+
}
|
|
377
|
+
$andSafePromise(promise, mapError = ensureError) {
|
|
378
|
+
return this.$async().$andSafePromise(promise, mapError);
|
|
379
|
+
}
|
|
167
380
|
$peek(f) {
|
|
168
381
|
f(this);
|
|
169
382
|
return this;
|
|
@@ -184,11 +397,14 @@ class ResultOk extends Array {
|
|
|
184
397
|
$promise() {
|
|
185
398
|
return Promise.resolve(this);
|
|
186
399
|
}
|
|
400
|
+
*$iter() {
|
|
401
|
+
yield* this[1];
|
|
402
|
+
}
|
|
187
403
|
}
|
|
188
404
|
/**
|
|
189
|
-
* ##
|
|
405
|
+
* ## ResultErr
|
|
190
406
|
*
|
|
191
|
-
*
|
|
407
|
+
* This is the `Err` variant of a `Result`, used internally and not exported.
|
|
192
408
|
*/
|
|
193
409
|
class ResultErr extends Array {
|
|
194
410
|
constructor(err) {
|
|
@@ -196,8 +412,11 @@ class ResultErr extends Array {
|
|
|
196
412
|
this[0] = err;
|
|
197
413
|
this[1] = undefined;
|
|
198
414
|
}
|
|
199
|
-
|
|
200
|
-
return this[0];
|
|
415
|
+
[ResultLikeSymbol]() {
|
|
416
|
+
return { ok: false, value: this[0] };
|
|
417
|
+
}
|
|
418
|
+
toJSON() {
|
|
419
|
+
return null;
|
|
201
420
|
}
|
|
202
421
|
$isOk() {
|
|
203
422
|
return false;
|
|
@@ -209,7 +428,7 @@ class ResultErr extends Array {
|
|
|
209
428
|
return true;
|
|
210
429
|
}
|
|
211
430
|
$isErrAnd(f) {
|
|
212
|
-
return f(this[0]);
|
|
431
|
+
return !!f(this[0]);
|
|
213
432
|
}
|
|
214
433
|
$expect() {
|
|
215
434
|
if (this[0] instanceof Error) {
|
|
@@ -233,40 +452,73 @@ class ResultErr extends Array {
|
|
|
233
452
|
return this;
|
|
234
453
|
}
|
|
235
454
|
$mapErr(f) {
|
|
236
|
-
return
|
|
455
|
+
return Err(f(this[0]));
|
|
237
456
|
}
|
|
238
457
|
$mapOr(def) {
|
|
239
|
-
return
|
|
458
|
+
return Ok(def);
|
|
240
459
|
}
|
|
241
460
|
$mapOrElse(def) {
|
|
242
|
-
return
|
|
461
|
+
return Ok(def(this[0]));
|
|
462
|
+
}
|
|
463
|
+
$andAssertOr() {
|
|
464
|
+
return this;
|
|
465
|
+
}
|
|
466
|
+
$andAssertOrElse() {
|
|
467
|
+
return this;
|
|
243
468
|
}
|
|
244
469
|
$or(or) {
|
|
245
|
-
return or;
|
|
470
|
+
return asResult(or);
|
|
471
|
+
}
|
|
472
|
+
$orAsync(or) {
|
|
473
|
+
return this.$async().$or(or);
|
|
246
474
|
}
|
|
247
475
|
$orElse(f) {
|
|
248
|
-
return f(this[0]);
|
|
476
|
+
return asResult(f(this[0]));
|
|
477
|
+
}
|
|
478
|
+
$orElseAsync(f) {
|
|
479
|
+
return this.$async().$orElse(f);
|
|
249
480
|
}
|
|
250
481
|
$orSafe(f, mapError = ensureError) {
|
|
251
482
|
try {
|
|
252
|
-
return
|
|
483
|
+
return Ok(f(this[0]));
|
|
253
484
|
}
|
|
254
485
|
catch (err) {
|
|
255
|
-
return
|
|
486
|
+
return Err(mapError(err));
|
|
256
487
|
}
|
|
257
488
|
}
|
|
489
|
+
$orSafeAsync(f, mapError = ensureError) {
|
|
490
|
+
return this.$async().$orSafe(f, mapError);
|
|
491
|
+
}
|
|
492
|
+
$orSafePromise(promise, mapError = ensureError) {
|
|
493
|
+
return this.$async().$orSafePromise(promise, mapError);
|
|
494
|
+
}
|
|
258
495
|
$and() {
|
|
259
496
|
return this;
|
|
260
497
|
}
|
|
498
|
+
$andAsync() {
|
|
499
|
+
return this.$async();
|
|
500
|
+
}
|
|
261
501
|
$andThen() {
|
|
262
502
|
return this;
|
|
263
503
|
}
|
|
504
|
+
$andThenAsync() {
|
|
505
|
+
return this.$async();
|
|
506
|
+
}
|
|
264
507
|
$andThrough() {
|
|
265
508
|
return this;
|
|
266
509
|
}
|
|
510
|
+
$andThroughAsync() {
|
|
511
|
+
return this.$async();
|
|
512
|
+
}
|
|
267
513
|
$andSafe() {
|
|
268
514
|
return this;
|
|
269
515
|
}
|
|
516
|
+
$andSafeAsync() {
|
|
517
|
+
return this.$async();
|
|
518
|
+
}
|
|
519
|
+
$andSafePromise() {
|
|
520
|
+
return this.$async();
|
|
521
|
+
}
|
|
270
522
|
$peek(f) {
|
|
271
523
|
f(this);
|
|
272
524
|
return this;
|
|
@@ -287,6 +539,9 @@ class ResultErr extends Array {
|
|
|
287
539
|
$promise() {
|
|
288
540
|
return Promise.resolve(this);
|
|
289
541
|
}
|
|
542
|
+
*$iter() {
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
290
545
|
}
|
|
291
546
|
/**
|
|
292
547
|
* ## ResultAsync
|
|
@@ -302,44 +557,42 @@ class ResultAsync {
|
|
|
302
557
|
return __classPrivateFieldGet(this, _ResultAsync_inner, "f").then(onfulfilled, onrejected);
|
|
303
558
|
}
|
|
304
559
|
/**
|
|
305
|
-
* @
|
|
306
|
-
*/
|
|
307
|
-
async $value() {
|
|
308
|
-
return (await __classPrivateFieldGet(this, _ResultAsync_inner, "f")).$value();
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* @TODO
|
|
560
|
+
* The same as {@link Retuple.$expect|$expect}, except it returns a `Promise`.
|
|
312
561
|
*/
|
|
313
562
|
async $expect() {
|
|
314
563
|
return (await __classPrivateFieldGet(this, _ResultAsync_inner, "f")).$expect();
|
|
315
564
|
}
|
|
316
565
|
/**
|
|
317
|
-
* @
|
|
566
|
+
* The same as {@link Retuple.$unwrap|$unwrap}, except it returns a `Promise`.
|
|
318
567
|
*/
|
|
319
568
|
async $unwrap(msg) {
|
|
320
569
|
return (await __classPrivateFieldGet(this, _ResultAsync_inner, "f")).$unwrap(msg);
|
|
321
570
|
}
|
|
322
571
|
/**
|
|
323
|
-
* @
|
|
572
|
+
* The same as {@link Retuple.$unwrapErr|$unwrapErr}, except it returns
|
|
573
|
+
* a `Promise`.
|
|
324
574
|
*/
|
|
325
575
|
async $unwrapErr(msg) {
|
|
326
576
|
return (await __classPrivateFieldGet(this, _ResultAsync_inner, "f")).$unwrapErr(msg);
|
|
327
577
|
}
|
|
328
578
|
/**
|
|
329
|
-
* @
|
|
579
|
+
* The same as {@link Retuple.$unwrapOr|$unwrapOr}, except it returns
|
|
580
|
+
* a `Promise`.
|
|
330
581
|
*/
|
|
331
582
|
async $unwrapOr(def) {
|
|
332
583
|
return (await __classPrivateFieldGet(this, _ResultAsync_inner, "f")).$unwrapOr(def);
|
|
333
584
|
}
|
|
334
585
|
/**
|
|
335
|
-
* @
|
|
586
|
+
* The same as {@link Retuple.$unwrapOrElse|$unwrapOrElse}, except it returns
|
|
587
|
+
* a `Promise`.
|
|
336
588
|
*/
|
|
337
589
|
async $unwrapOrElse(f) {
|
|
338
590
|
const res = await __classPrivateFieldGet(this, _ResultAsync_inner, "f");
|
|
339
591
|
return res instanceof ResultOk ? res[1] : f();
|
|
340
592
|
}
|
|
341
593
|
/**
|
|
342
|
-
* @
|
|
594
|
+
* The same as {@link Retuple.$map|$map}, except it returns
|
|
595
|
+
* {@link ResultAsync}.
|
|
343
596
|
*/
|
|
344
597
|
$map(f) {
|
|
345
598
|
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
@@ -349,7 +602,8 @@ class ResultAsync {
|
|
|
349
602
|
}));
|
|
350
603
|
}
|
|
351
604
|
/**
|
|
352
|
-
* @
|
|
605
|
+
* The same as {@link Retuple.$mapErr|$mapErr}, except it returns
|
|
606
|
+
* {@link ResultAsync}.
|
|
353
607
|
*/
|
|
354
608
|
$mapErr(f) {
|
|
355
609
|
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
@@ -359,7 +613,8 @@ class ResultAsync {
|
|
|
359
613
|
}));
|
|
360
614
|
}
|
|
361
615
|
/**
|
|
362
|
-
* @
|
|
616
|
+
* The same as {@link Retuple.$mapOr|$mapOr}, except it returns
|
|
617
|
+
* {@link ResultAsync}.
|
|
363
618
|
*/
|
|
364
619
|
$mapOr(def, f) {
|
|
365
620
|
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
@@ -369,7 +624,8 @@ class ResultAsync {
|
|
|
369
624
|
}));
|
|
370
625
|
}
|
|
371
626
|
/**
|
|
372
|
-
* @
|
|
627
|
+
* The same as {@link Retuple.$mapOrElse|$mapOrElse}, except it returns
|
|
628
|
+
* {@link ResultAsync}.
|
|
373
629
|
*/
|
|
374
630
|
$mapOrElse(def, f) {
|
|
375
631
|
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
@@ -378,25 +634,36 @@ class ResultAsync {
|
|
|
378
634
|
: new ResultOk(def(res[0]));
|
|
379
635
|
}));
|
|
380
636
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
637
|
+
$andAssertOr(def, condition = isTruthy) {
|
|
638
|
+
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
639
|
+
if (res instanceof ResultErr || condition(res[1])) {
|
|
640
|
+
return res;
|
|
641
|
+
}
|
|
642
|
+
return asResult(await def);
|
|
643
|
+
}));
|
|
644
|
+
}
|
|
645
|
+
$andAssertOrElse(def, condition = isTruthy) {
|
|
646
|
+
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
647
|
+
if (res instanceof ResultErr || condition(res[1])) {
|
|
648
|
+
return res;
|
|
649
|
+
}
|
|
650
|
+
return asResult(await def(res[1]));
|
|
651
|
+
}));
|
|
652
|
+
}
|
|
384
653
|
$or(or) {
|
|
385
654
|
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
386
|
-
return res instanceof ResultErr
|
|
655
|
+
return res instanceof ResultErr
|
|
656
|
+
? asResult(await or)
|
|
657
|
+
: res;
|
|
387
658
|
}));
|
|
388
659
|
}
|
|
389
|
-
/**
|
|
390
|
-
* @TODO
|
|
391
|
-
*/
|
|
392
660
|
$orElse(f) {
|
|
393
661
|
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
394
|
-
return res instanceof ResultErr
|
|
662
|
+
return res instanceof ResultErr
|
|
663
|
+
? asResult(await f(res[0]))
|
|
664
|
+
: res;
|
|
395
665
|
}));
|
|
396
666
|
}
|
|
397
|
-
/**
|
|
398
|
-
* @TODO
|
|
399
|
-
*/
|
|
400
667
|
$orSafe(f, mapError = ensureError) {
|
|
401
668
|
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
402
669
|
if (res instanceof ResultOk) {
|
|
@@ -410,29 +677,37 @@ class ResultAsync {
|
|
|
410
677
|
}
|
|
411
678
|
}));
|
|
412
679
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
680
|
+
$orSafePromise(promise, mapError = ensureError) {
|
|
681
|
+
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
682
|
+
if (res instanceof ResultOk) {
|
|
683
|
+
return res;
|
|
684
|
+
}
|
|
685
|
+
try {
|
|
686
|
+
return new ResultOk(await promise);
|
|
687
|
+
}
|
|
688
|
+
catch (err) {
|
|
689
|
+
return new ResultErr(mapError(err));
|
|
690
|
+
}
|
|
691
|
+
}));
|
|
692
|
+
}
|
|
416
693
|
$and(and) {
|
|
417
694
|
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
418
|
-
return res instanceof ResultOk
|
|
695
|
+
return res instanceof ResultOk
|
|
696
|
+
? asResult(await and)
|
|
697
|
+
: res;
|
|
419
698
|
}));
|
|
420
699
|
}
|
|
421
|
-
/**
|
|
422
|
-
* @TODO
|
|
423
|
-
*/
|
|
424
700
|
$andThen(f) {
|
|
425
701
|
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
426
|
-
return res instanceof ResultOk
|
|
702
|
+
return res instanceof ResultOk
|
|
703
|
+
? asResult(await f(res[1]))
|
|
704
|
+
: res;
|
|
427
705
|
}));
|
|
428
706
|
}
|
|
429
|
-
/**
|
|
430
|
-
* @TODO
|
|
431
|
-
*/
|
|
432
707
|
$andThrough(f) {
|
|
433
708
|
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
434
709
|
if (res instanceof ResultOk) {
|
|
435
|
-
const through = await f(res[1]);
|
|
710
|
+
const through = asResult(await f(res[1]));
|
|
436
711
|
if (through instanceof ResultErr) {
|
|
437
712
|
return through;
|
|
438
713
|
}
|
|
@@ -440,24 +715,37 @@ class ResultAsync {
|
|
|
440
715
|
return res;
|
|
441
716
|
}));
|
|
442
717
|
}
|
|
443
|
-
/**
|
|
444
|
-
* @TODO
|
|
445
|
-
*/
|
|
446
718
|
$andSafe(f, mapError = ensureError) {
|
|
447
719
|
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
448
720
|
if (res instanceof ResultErr) {
|
|
449
721
|
return res;
|
|
450
722
|
}
|
|
451
723
|
try {
|
|
452
|
-
return
|
|
724
|
+
return Ok(await f(res[1]));
|
|
453
725
|
}
|
|
454
726
|
catch (err) {
|
|
455
|
-
return
|
|
727
|
+
return Err(mapError(err));
|
|
728
|
+
}
|
|
729
|
+
}));
|
|
730
|
+
}
|
|
731
|
+
$andSafePromise(promise, mapError = ensureError) {
|
|
732
|
+
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
733
|
+
if (res instanceof ResultErr) {
|
|
734
|
+
return res;
|
|
735
|
+
}
|
|
736
|
+
try {
|
|
737
|
+
return Ok(await promise);
|
|
738
|
+
}
|
|
739
|
+
catch (err) {
|
|
740
|
+
return Err(mapError(err));
|
|
456
741
|
}
|
|
457
742
|
}));
|
|
458
743
|
}
|
|
459
744
|
/**
|
|
460
|
-
* @
|
|
745
|
+
* The same as {@link Retuple.$peek|$peek}, except it:
|
|
746
|
+
*
|
|
747
|
+
* - awaits the peek function;
|
|
748
|
+
* - returns {@link ResultAsync}.
|
|
461
749
|
*/
|
|
462
750
|
$peek(f) {
|
|
463
751
|
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
@@ -466,7 +754,10 @@ class ResultAsync {
|
|
|
466
754
|
}));
|
|
467
755
|
}
|
|
468
756
|
/**
|
|
469
|
-
* @
|
|
757
|
+
* The same as {@link Retuple.$tap|$tap}, except it:
|
|
758
|
+
*
|
|
759
|
+
* - awaits the tap function;
|
|
760
|
+
* - returns {@link ResultAsync}.
|
|
470
761
|
*/
|
|
471
762
|
$tap(f) {
|
|
472
763
|
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
@@ -477,7 +768,10 @@ class ResultAsync {
|
|
|
477
768
|
}));
|
|
478
769
|
}
|
|
479
770
|
/**
|
|
480
|
-
* @
|
|
771
|
+
* The same as {@link Retuple.$tapErr|$tapErr}, except it:
|
|
772
|
+
*
|
|
773
|
+
* - awaits the tap error function;
|
|
774
|
+
* - returns {@link ResultAsync}.
|
|
481
775
|
*/
|
|
482
776
|
$tapErr(f) {
|
|
483
777
|
return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
|
|
@@ -488,31 +782,165 @@ class ResultAsync {
|
|
|
488
782
|
}));
|
|
489
783
|
}
|
|
490
784
|
/**
|
|
491
|
-
* @
|
|
785
|
+
* The same as {@link Retuple.$promise|$promise}.
|
|
492
786
|
*/
|
|
493
787
|
$promise() {
|
|
494
788
|
return Promise.resolve(this);
|
|
495
789
|
}
|
|
790
|
+
/**
|
|
791
|
+
* The same as {@link Retuple.$iter|$iter}, except it returns a `Promise`.
|
|
792
|
+
*/
|
|
793
|
+
async $iter() {
|
|
794
|
+
return (await __classPrivateFieldGet(this, _ResultAsync_inner, "f")).$iter();
|
|
795
|
+
}
|
|
496
796
|
}
|
|
497
797
|
_ResultAsync_inner = new WeakMap();
|
|
798
|
+
/**
|
|
799
|
+
* ## ResultRetry
|
|
800
|
+
*/
|
|
801
|
+
class ResultRetry extends ResultAsync {
|
|
802
|
+
static zero() {
|
|
803
|
+
return 0;
|
|
804
|
+
}
|
|
805
|
+
static delay(ms) {
|
|
806
|
+
return new Promise((resolve) => setTimeout(resolve, Math.min(ms, _a.MAX_TIMEOUT)));
|
|
807
|
+
}
|
|
808
|
+
static integer(value) {
|
|
809
|
+
if (typeof value === "number" && Number.isInteger(value)) {
|
|
810
|
+
return Math.max(0, value);
|
|
811
|
+
}
|
|
812
|
+
return 0;
|
|
813
|
+
}
|
|
814
|
+
constructor(f) {
|
|
815
|
+
super(Promise.resolve().then(() => __classPrivateFieldGet(this, _ResultRetry_promise, "f")));
|
|
816
|
+
_ResultRetry_f.set(this, void 0);
|
|
817
|
+
_ResultRetry_promise.set(this, void 0);
|
|
818
|
+
_ResultRetry_times.set(this, 1);
|
|
819
|
+
_ResultRetry_attempt.set(this, 0);
|
|
820
|
+
_ResultRetry_aborted.set(this, false);
|
|
821
|
+
_ResultRetry_abort.set(this, () => (__classPrivateFieldSet(this, _ResultRetry_aborted, true, "f")));
|
|
822
|
+
_ResultRetry_getDelay.set(this, _a.zero);
|
|
823
|
+
_ResultRetry_handler.set(this, void 0);
|
|
824
|
+
__classPrivateFieldSet(this, _ResultRetry_f, f, "f");
|
|
825
|
+
__classPrivateFieldSet(this, _ResultRetry_promise, this.drain(), "f");
|
|
826
|
+
}
|
|
827
|
+
then(onfulfilled, onrejected) {
|
|
828
|
+
return super.then(onfulfilled, onrejected);
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Sets the maximum number of times the retry function can be executed,
|
|
832
|
+
* mutating this `ResultRetry` instance.
|
|
833
|
+
*
|
|
834
|
+
* **The default value is 1 - meaning that unless set, no retries will be
|
|
835
|
+
* attempted.**
|
|
836
|
+
*
|
|
837
|
+
* The retry function can be called up to the maximum number of times until
|
|
838
|
+
* it returns `Ok`. If it never returns `Ok`, the most recent `Err` is
|
|
839
|
+
* returned.
|
|
840
|
+
*
|
|
841
|
+
* This function accepts a positive integer between 1 and 100:
|
|
842
|
+
*
|
|
843
|
+
* - Integers outside of this range are clamped to the nearest valid value;
|
|
844
|
+
* - Any other value (NaN, Infinity, fractions, strings) are treated as 1.
|
|
845
|
+
*
|
|
846
|
+
* @example
|
|
847
|
+
*
|
|
848
|
+
* ```ts
|
|
849
|
+
* // Retry someResultFn up to 3 times until Ok is returned:
|
|
850
|
+
* const result = await Result.$retry(someResultFn).$times(3);
|
|
851
|
+
* ```
|
|
852
|
+
*/
|
|
853
|
+
$times(times) {
|
|
854
|
+
__classPrivateFieldSet(this, _ResultRetry_times, Math.min(Math.max(1, _a.integer(times)), _a.MAX_RETRY), "f");
|
|
855
|
+
return this;
|
|
856
|
+
}
|
|
857
|
+
$delay(fnOrMs) {
|
|
858
|
+
if (typeof fnOrMs === "function") {
|
|
859
|
+
__classPrivateFieldSet(this, _ResultRetry_getDelay, fnOrMs, "f");
|
|
860
|
+
return this;
|
|
861
|
+
}
|
|
862
|
+
const delay = _a.integer(fnOrMs);
|
|
863
|
+
if (delay > 0) {
|
|
864
|
+
__classPrivateFieldSet(this, _ResultRetry_getDelay, () => delay, "f");
|
|
865
|
+
}
|
|
866
|
+
return this;
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* Sets a handler to be called when an attempt returns `Err`, mutating this
|
|
870
|
+
* `ResultRetry` instance. The handler can be used to capture information
|
|
871
|
+
* about each failure, and to abort early and prevent further retries.
|
|
872
|
+
*
|
|
873
|
+
* The handler function is called with `ResultRetryHandleState`, containing:
|
|
874
|
+
*
|
|
875
|
+
* - **error** - The error value from the last failed attempt;
|
|
876
|
+
* - **attempt** - The attempt number;
|
|
877
|
+
* - **abort** - A function which when called, prevents further retries.
|
|
878
|
+
*
|
|
879
|
+
* @example
|
|
880
|
+
*
|
|
881
|
+
* ```ts
|
|
882
|
+
* // Retry someResultFn up to 3 times until Ok is returned, logging each
|
|
883
|
+
* // attempt and aborting early if the error code is "UNAUTHORIZED".
|
|
884
|
+
* const result = await Result.$retry(someResultFn)
|
|
885
|
+
* .$times(3)
|
|
886
|
+
* .$handle(({ error, attempt, abort }) => {
|
|
887
|
+
* console.info(`Attempt ${attempt} failed: ${error}`);
|
|
888
|
+
* if (error === "UNAUTHORIZED") {
|
|
889
|
+
* abort();
|
|
890
|
+
* }
|
|
891
|
+
* });
|
|
892
|
+
* ```
|
|
893
|
+
*/
|
|
894
|
+
$handle(f) {
|
|
895
|
+
__classPrivateFieldSet(this, _ResultRetry_handler, f, "f");
|
|
896
|
+
return this;
|
|
897
|
+
}
|
|
898
|
+
async drain() {
|
|
899
|
+
var _b;
|
|
900
|
+
while (__classPrivateFieldGet(this, _ResultRetry_attempt, "f") < __classPrivateFieldGet(this, _ResultRetry_times, "f")) {
|
|
901
|
+
const result = asResult(await __classPrivateFieldGet(this, _ResultRetry_f, "f").call(this));
|
|
902
|
+
__classPrivateFieldSet(this, _ResultRetry_attempt, (_b = __classPrivateFieldGet(this, _ResultRetry_attempt, "f"), _b++, _b), "f");
|
|
903
|
+
if (result.$isOk()) {
|
|
904
|
+
return result;
|
|
905
|
+
}
|
|
906
|
+
if (__classPrivateFieldGet(this, _ResultRetry_handler, "f")) {
|
|
907
|
+
await __classPrivateFieldGet(this, _ResultRetry_handler, "f").call(this, {
|
|
908
|
+
error: result[0],
|
|
909
|
+
attempt: __classPrivateFieldGet(this, _ResultRetry_attempt, "f"),
|
|
910
|
+
abort: __classPrivateFieldGet(this, _ResultRetry_abort, "f"),
|
|
911
|
+
});
|
|
912
|
+
}
|
|
913
|
+
if (__classPrivateFieldGet(this, _ResultRetry_aborted, "f") || __classPrivateFieldGet(this, _ResultRetry_attempt, "f") >= __classPrivateFieldGet(this, _ResultRetry_times, "f")) {
|
|
914
|
+
return result;
|
|
915
|
+
}
|
|
916
|
+
const delay = _a.integer(__classPrivateFieldGet(this, _ResultRetry_getDelay, "f").call(this, __classPrivateFieldGet(this, _ResultRetry_attempt, "f")));
|
|
917
|
+
if (delay > 0) {
|
|
918
|
+
await _a.delay(delay);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
/* v8 ignore next */
|
|
922
|
+
throw new Error("Retuple: Unreachable code executed");
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
_a = ResultRetry, _ResultRetry_f = new WeakMap(), _ResultRetry_promise = new WeakMap(), _ResultRetry_times = new WeakMap(), _ResultRetry_attempt = new WeakMap(), _ResultRetry_aborted = new WeakMap(), _ResultRetry_abort = new WeakMap(), _ResultRetry_getDelay = new WeakMap(), _ResultRetry_handler = new WeakMap();
|
|
926
|
+
ResultRetry.MAX_TIMEOUT = 3600000;
|
|
927
|
+
ResultRetry.MAX_RETRY = 100;
|
|
928
|
+
function asResult(resultLike) {
|
|
929
|
+
if (resultLike instanceof ResultOk || resultLike instanceof ResultErr) {
|
|
930
|
+
return resultLike;
|
|
931
|
+
}
|
|
932
|
+
const result = resultLike[ResultLikeSymbol]();
|
|
933
|
+
return result.ok ? new ResultOk(result.value) : new ResultErr(result.value);
|
|
934
|
+
}
|
|
498
935
|
function ensureError(err) {
|
|
499
936
|
if (err instanceof Error) {
|
|
500
937
|
return err;
|
|
501
938
|
}
|
|
502
|
-
return new
|
|
939
|
+
return new RetupleCaughtValueError(err);
|
|
940
|
+
}
|
|
941
|
+
function mapTrue() {
|
|
942
|
+
return true;
|
|
943
|
+
}
|
|
944
|
+
function isTruthy(val) {
|
|
945
|
+
return !!val;
|
|
503
946
|
}
|
|
504
|
-
Object.freeze(Result);
|
|
505
|
-
Object.freeze(ResultOk);
|
|
506
|
-
Object.freeze(ResultErr);
|
|
507
|
-
Object.freeze(ResultAsync);
|
|
508
|
-
Object.freeze(RetupleUnwrapFailed);
|
|
509
|
-
Object.freeze(RetupleUnwrapErrFailed);
|
|
510
|
-
Object.freeze(RetupleExpectFailed);
|
|
511
|
-
Object.freeze(RetupleThrownValueError);
|
|
512
|
-
Object.freeze(ResultOk.prototype);
|
|
513
|
-
Object.freeze(ResultErr.prototype);
|
|
514
|
-
Object.freeze(ResultAsync.prototype);
|
|
515
|
-
Object.freeze(RetupleUnwrapFailed.prototype);
|
|
516
|
-
Object.freeze(RetupleUnwrapErrFailed.prototype);
|
|
517
|
-
Object.freeze(RetupleExpectFailed.prototype);
|
|
518
|
-
Object.freeze(RetupleThrownValueError.prototype);
|