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