retuple 1.0.0-next.3 → 1.0.0-next.30

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,17 +10,14 @@ 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.RetupleInvalidResultError = exports.RetupleThrownValueError = exports.RetupleExpectFailed = exports.RetupleUnwrapErrFailed = exports.RetupleUnwrapFailed = void 0;
15
+ exports.RetupleInvalidUnionError = exports.RetupleCaughtValueError = exports.RetupleIndexFailed = exports.RetupleFilterFailed = exports.RetupleAssertFailed = exports.RetupleExpectFailed = exports.RetupleUnwrapErrFailed = exports.RetupleUnwrapFailed = void 0;
16
16
  exports.Result = Result;
17
17
  exports.Ok = Ok;
18
18
  exports.Err = Err;
19
- exports.nonNullable = nonNullable;
20
- exports.truthy = truthy;
21
- exports.safe = safe;
22
- exports.safeAsync = safeAsync;
23
- exports.safePromise = safePromise;
19
+ const retuple_symbols_1 = require("retuple-symbols");
20
+ const RetupleStackSymbol = Symbol("RetupleStackSymbol");
24
21
  /**
25
22
  * ## Retuple Unwrap Failed
26
23
  *
@@ -48,7 +45,7 @@ exports.RetupleUnwrapErrFailed = RetupleUnwrapErrFailed;
48
45
  /**
49
46
  * ## Retuple Expect Failed
50
47
  *
51
- * An error which occurs when calling `$expect` on `Err`, and when the value
48
+ * An error which occurs when calling `$expect` on `Err`, when the value
52
49
  * contained in the `Err` is not an instance of `Error`.
53
50
  */
54
51
  class RetupleExpectFailed extends Error {
@@ -58,6 +55,46 @@ class RetupleExpectFailed extends Error {
58
55
  }
59
56
  }
60
57
  exports.RetupleExpectFailed = RetupleExpectFailed;
58
+ /**
59
+ * ## Retuple Assert Failed
60
+ *
61
+ * This error is used as the error type of a `Result` when using $assert,
62
+ * when no map error function is provided.
63
+ */
64
+ class RetupleAssertFailed extends Error {
65
+ constructor(value) {
66
+ super("Assert failed");
67
+ this.value = value;
68
+ }
69
+ }
70
+ exports.RetupleAssertFailed = RetupleAssertFailed;
71
+ /**
72
+ * ## Retuple Filter Failed
73
+ *
74
+ * This error is used as the error type of a `Result` when using $filter,
75
+ * when no map error function is provided.
76
+ */
77
+ class RetupleFilterFailed extends Error {
78
+ constructor(value) {
79
+ super("Filter failed");
80
+ this.value = value;
81
+ }
82
+ }
83
+ exports.RetupleFilterFailed = RetupleFilterFailed;
84
+ /**
85
+ * ## Retuple Index Failed
86
+ *
87
+ * This error is used as the error type of a `Result` when using $atIndex or
88
+ * $firstIndex, when no map error function is provided.
89
+ */
90
+ class RetupleIndexFailed extends Error {
91
+ constructor(index, value) {
92
+ super("Index failed");
93
+ this.index = index;
94
+ this.value = value;
95
+ }
96
+ }
97
+ exports.RetupleIndexFailed = RetupleIndexFailed;
61
98
  /**
62
99
  * ## Retuple Thrown Value Error
63
100
  *
@@ -65,49 +102,57 @@ exports.RetupleExpectFailed = RetupleExpectFailed;
65
102
  * thrown error or rejected value is not an instance of `Error`, and when no
66
103
  * map error function is provided.
67
104
  */
68
- class RetupleThrownValueError extends Error {
105
+ class RetupleCaughtValueError extends Error {
69
106
  constructor(value) {
70
107
  super("Caught value was not an instance of Error");
71
108
  this.value = value;
72
109
  }
73
110
  }
74
- exports.RetupleThrownValueError = RetupleThrownValueError;
111
+ exports.RetupleCaughtValueError = RetupleCaughtValueError;
75
112
  /**
76
- * ## Retuple Invalid Result Error
113
+ * ## Retuple Invalid Union Error
77
114
  *
78
- * An error constructed when a safe function call throws or rejects, when the
79
- * thrown error or rejected value is not an instance of `Error`, and when no
80
- * map error function is provided.
115
+ * This error is thrown when attempting to construct a `Result` from a
116
+ * discriminated union, when the 'success' property is not boolean. In this
117
+ * case, it is impossible to determine whether the result should be `Ok` or
118
+ * `Err`.
81
119
  */
82
- class RetupleInvalidResultError extends Error {
120
+ class RetupleInvalidUnionError extends Error {
83
121
  constructor(value) {
84
- super("Constructing a Result from tuple failed, at least one of the values at index 0 or 1 should be undefined");
122
+ super("Constructing a Result from discriminated union failed, the success " +
123
+ "property must be boolean");
85
124
  this.value = value;
86
125
  }
87
126
  }
88
- exports.RetupleInvalidResultError = RetupleInvalidResultError;
127
+ exports.RetupleInvalidUnionError = RetupleInvalidUnionError;
89
128
  /**
90
129
  * ## Result
91
130
  *
92
131
  * @TODO
93
132
  */
94
133
  function Result(resultLike) {
95
- const [err, ok] = resultLike;
96
- if (err === null || err === undefined) {
97
- return new ResultOk(ok);
98
- }
99
- if (ok === null || ok === undefined) {
100
- return new ResultErr(err);
101
- }
102
- throw new RetupleInvalidResultError(resultLike);
134
+ return asResult(resultLike);
103
135
  }
104
136
  Result.Ok = Ok;
105
137
  Result.Err = Err;
106
- Result.nonNullable = nonNullable;
107
- Result.truthy = truthy;
108
- Result.safe = safe;
109
- Result.safeAsync = safeAsync;
110
- Result.safePromise = safePromise;
138
+ Result.$from = $from;
139
+ Result.$resolve = $resolve;
140
+ Result.$nonNullable = $nonNullable;
141
+ Result.$truthy = $truthy;
142
+ Result.$fromUnion = $fromUnion;
143
+ Result.$safe = $safe;
144
+ Result.$safeAsync = $safeAsync;
145
+ Result.$safePromise = $safePromise;
146
+ Result.$retry = $retry;
147
+ Result.$safeRetry = $safeRetry;
148
+ Result.$all = $all;
149
+ Result.$allPromised = $allPromised;
150
+ Result.$any = $any;
151
+ Result.$anyPromised = $anyPromised;
152
+ Result.$collect = $collect;
153
+ Result.$collectPromised = $collectPromised;
154
+ Result.$pipe = $pipe;
155
+ Result.$pipeAsync = $pipeAsync;
111
156
  Object.freeze(Result);
112
157
  function Ok(val) {
113
158
  return new ResultOk(val);
@@ -115,43 +160,401 @@ function Ok(val) {
115
160
  function Err(err) {
116
161
  return new ResultErr(err);
117
162
  }
118
- function nonNullable(value, error = mapTrue) {
163
+ /**
164
+ * Construct a {@link Result} from a {@link ResultLike}.
165
+ *
166
+ * @example
167
+ *
168
+ * ```ts
169
+ * const value: Result<T, E> | ResultLike<T, E> = someResultFn();
170
+ * const result: Result<T, E> = Result.$from(result);
171
+ * ```
172
+ */
173
+ function $from(result) {
174
+ if (result instanceof ResultOk || result instanceof ResultErr) {
175
+ return result;
176
+ }
177
+ return asResult(result);
178
+ }
179
+ /**
180
+ * Construct a {@link ResultAsync} from a {@link ResultLikeAwaitable}.
181
+ *
182
+ * @example
183
+ *
184
+ * ```ts
185
+ * const value:
186
+ * | Result<T, E>
187
+ * | ResultLike<T, E>
188
+ * | ResultAsync<T, E>
189
+ * | Promise<Result<T, E>>
190
+ * | Promise<ResultLike<T, E>>
191
+ * | PromiseLike<Result<T, E>>
192
+ * | PromiseLike<ResultLike<T, E>> = someResultFn();
193
+ *
194
+ * const result: ResultAsync<T, E> = Result.$resolve(result);
195
+ * ```
196
+ */
197
+ function $resolve(result) {
198
+ switch (true) {
199
+ case result instanceof ResultAsync:
200
+ return result;
201
+ case result instanceof ResultOk:
202
+ case result instanceof ResultErr:
203
+ return new ResultAsync(Promise.resolve(result));
204
+ default:
205
+ return new ResultAsync(Promise.resolve(result).then((asResult)));
206
+ }
207
+ }
208
+ function $nonNullable(value, error = mapTrue) {
119
209
  if (value !== null && value !== undefined) {
120
- return new ResultOk(value);
210
+ return Ok(value);
121
211
  }
122
- return new ResultErr(error());
212
+ return Err(error());
123
213
  }
124
- function truthy(value, error = mapTrue) {
214
+ function $truthy(value, error = mapTrue) {
125
215
  if (value) {
126
- return new ResultOk(value);
216
+ return Ok(value);
127
217
  }
128
- return new ResultErr(error());
218
+ return Err(error());
129
219
  }
130
- function safe(f, mapError = ensureError) {
220
+ /**
221
+ * Construct a {@link Result} from a common discriminated union shape. If the
222
+ * union is 'success' then the result is `Ok`
223
+ *
224
+ * Otherwise, the result is `Err` containing:
225
+ *
226
+ * - the returned value from the error function when provided;
227
+ * - or `true` otherwise.
228
+ *
229
+ * @example
230
+ *
231
+ * ```ts
232
+ * const result: Result<string, Error> = Result.$truthy(
233
+ * username.trim(),
234
+ * () => new Error("Username is empty"),
235
+ * );
236
+ * ```
237
+ *
238
+ * @example
239
+ *
240
+ * ```ts
241
+ * const [err, value] = Result.$truthy("test");
242
+ *
243
+ * assert.equal(err, undefined);
244
+ * assert.equal(value, "test");
245
+ * ```
246
+ *
247
+ * @example
248
+ *
249
+ * ```ts
250
+ * const [err, value] = Result.$truthy("");
251
+ *
252
+ * assert.equal(err, true);
253
+ * assert.equal(value, undefined);
254
+ * ```
255
+ *
256
+ * @example
257
+ *
258
+ * ```ts
259
+ * const [err, value] = Result.$truthy(0, () => "error");
260
+ *
261
+ * assert.equal(err, "error");
262
+ * assert.equal(value, undefined);
263
+ * ```
264
+ */
265
+ function $fromUnion(union) {
266
+ if (union.success === true) {
267
+ return Ok(union.data);
268
+ }
269
+ if (union.success === false) {
270
+ return Err(union.error);
271
+ }
272
+ throw new RetupleInvalidUnionError(union);
273
+ }
274
+ function $safe(f, mapError = ensureError) {
131
275
  try {
132
- return new ResultOk(f());
276
+ return Ok(f());
133
277
  }
134
278
  catch (err) {
135
- return new ResultErr(mapError(err));
279
+ return Err(mapError(err));
136
280
  }
137
281
  }
138
- function safeAsync(f, mapError = ensureError) {
282
+ function $safeAsync(f, mapError = ensureError) {
139
283
  return new ResultAsync((async () => {
140
284
  try {
141
- return new ResultOk(await f());
285
+ return Ok(await f());
142
286
  }
143
287
  catch (err) {
144
- return new ResultErr(await mapError(err));
288
+ return Err(await mapError(err));
145
289
  }
146
290
  })());
147
291
  }
148
- function safePromise(promise, mapError = ensureError) {
292
+ function $safePromise(promise, mapError = ensureError) {
149
293
  return new ResultAsync(promise.then((Ok), async (err) => Err(await mapError(err))));
150
294
  }
151
295
  /**
152
- * ## Ok
296
+ * Construct a {@link ResultRetry} from a function which returns a
297
+ * {@link Result}. The function will be retried based on provided retry
298
+ * settings and eventually return a `Result`. No attempt is made to catch
299
+ * thrown errors or promise rejections.
153
300
  *
154
- * @TODO
301
+ * To retry a potentially unsafe function, use {@link Result.$safeRetry}.
302
+ *
303
+ * @example
304
+ *
305
+ * ```ts
306
+ * // Retry someResultFn up to 3 times until Ok is returned,
307
+ * // with a 1 second delay between each invocation:
308
+ * const result = await Result.$retry(someResultFn).$times(3).$delay(1000);
309
+ * ```
310
+ */
311
+ function $retry(f) {
312
+ return new ResultRetry(f);
313
+ }
314
+ function $safeRetry(f, mapError = ensureError) {
315
+ return new ResultRetry(async () => {
316
+ try {
317
+ return Ok(await f());
318
+ }
319
+ catch (err) {
320
+ return Err(mapError(err));
321
+ }
322
+ });
323
+ }
324
+ /**
325
+ * Construct a {@link Result} from an array of results. If all are Ok,
326
+ * then the result is `Ok` containing a tuple of values. Otherwise,
327
+ * the result is `Err` containing the first error encountered.
328
+ *
329
+ * @example
330
+ *
331
+ * ```ts
332
+ * const result: Result<[string, number], Error | string> = Result.$all([
333
+ * Result.$truthy(stringValue, () => new Error("Invalid string")),
334
+ * Result.$truthy(numberValue, () => "Invalid number"),
335
+ * ]);
336
+ * ```
337
+ *
338
+ * @example
339
+ *
340
+ * ```ts
341
+ * const tuple: [1, 2, 3] = Result.$all([
342
+ * Ok(1),
343
+ * Ok(2),
344
+ * Ok(3),
345
+ * ]).$unwrap();
346
+ * ```
347
+ *
348
+ * @example
349
+ *
350
+ * ```ts
351
+ * const error: "error" = Result.$all([
352
+ * Ok(1),
353
+ * Err("error"),
354
+ * Ok(3),
355
+ * ]).$unwrapErr();
356
+ * ```
357
+ */
358
+ function $all(results) {
359
+ const oks = [];
360
+ for (const result of results) {
361
+ const { ok, value } = result[retuple_symbols_1.ResultLikeSymbol]();
362
+ if (ok) {
363
+ oks.push(value);
364
+ }
365
+ else {
366
+ return Err(value);
367
+ }
368
+ }
369
+ return Ok(oks);
370
+ }
371
+ /**
372
+ * The same as {@link Result.$all|$all} except it accepts result-like
373
+ * promises and returns {@link ResultAsync}.
374
+ */
375
+ function $allPromised(results) {
376
+ return new ResultAsync(new Promise((resolve, reject) => {
377
+ void Promise.all(results.map((result) => Promise.resolve(result).then((result) => {
378
+ const { ok, value } = result[retuple_symbols_1.ResultLikeSymbol]();
379
+ return ok ? value : Promise.reject(value);
380
+ }, (err) => {
381
+ reject(err);
382
+ // Because reject has been called, we can safely return an
383
+ // empty rejection to ensure we don't end up with undefined
384
+ // in the Ok path. The subsequent call to resolve will not
385
+ // change the state of the Promise.
386
+ return Promise.reject();
387
+ }))).then((values) => resolve(Ok(values)), (err) => resolve(Err(err)));
388
+ }));
389
+ }
390
+ /**
391
+ * Construct a {@link Result} from an array of results. If any are Ok,
392
+ * then the result is `Ok` containing the first value encountered.
393
+ * Otherwise, the result is `Err` containing a tuple of errors.
394
+ *
395
+ * @example
396
+ *
397
+ * ```ts
398
+ * const result: Result<string | number, [Error, string]> = Result.$any([
399
+ * Result.$truthy(stringValue, () => new Error("Invalid string")),
400
+ * Result.$truthy(numberValue, () => "Invalid number"),
401
+ * ]);
402
+ * ```
403
+ *
404
+ * @example
405
+ *
406
+ * ```ts
407
+ * const tuple: 2 = Result.$any([
408
+ * Err("error1"),
409
+ * Ok(2),
410
+ * Err("error3"),
411
+ * ]).$unwrap();
412
+ * ```
413
+ *
414
+ * @example
415
+ *
416
+ * ```ts
417
+ * const error: ["error1", "error2", "error3"] = Result.$any([
418
+ * Err("error1"),
419
+ * Err("error2"),
420
+ * Err("error3"),
421
+ * ]).$unwrapErr();
422
+ * ```
423
+ */
424
+ function $any(results) {
425
+ const errs = [];
426
+ for (const result of results) {
427
+ const { ok, value } = result[retuple_symbols_1.ResultLikeSymbol]();
428
+ if (ok) {
429
+ return Ok(value);
430
+ }
431
+ else {
432
+ errs.push(value);
433
+ }
434
+ }
435
+ return Err(errs);
436
+ }
437
+ /**
438
+ * The same as {@link Result.$any|$any} except it accepts result-like
439
+ * promises and returns {@link ResultAsync}.
440
+ */
441
+ function $anyPromised(results) {
442
+ return new ResultAsync(new Promise((resolve, reject) => {
443
+ let rejected = false;
444
+ void Promise.any(results.map((result) => Promise.resolve(result).then((result) => {
445
+ const { ok, value } = result[retuple_symbols_1.ResultLikeSymbol]();
446
+ return ok ? value : Promise.reject(value);
447
+ }, (err) => {
448
+ rejected = true;
449
+ return Promise.reject(err);
450
+ }))).then((value) => resolve(Ok(value)), (err) => err instanceof AggregateError && rejected === false
451
+ ? resolve(Err(err.errors))
452
+ : reject(err));
453
+ }));
454
+ }
455
+ /**
456
+ * Construct a {@link Result} from an object of results. If all are Ok,
457
+ * then the result is `Ok` containing an object of the values. Otherwise,
458
+ * the result is `Err` containing the first error encountered.
459
+ *
460
+ * @example
461
+ *
462
+ * ```ts
463
+ * const result: Result<
464
+ * { test1: string, test2: number},
465
+ * string | Error,
466
+ * > = Result.$collect({
467
+ * test1: Result.$truthy(stringValue, () => new Error("Invalid string")),
468
+ * test2: Result.$truthy(numberValue, () => "Invalid number"),
469
+ * ]);
470
+ * ```
471
+ *
472
+ * @example
473
+ *
474
+ * ```ts
475
+ * const object: { a: 1, b: 2 } = Result.$collect({
476
+ * a: Ok(1),
477
+ * b: Ok(2),
478
+ * }).$unwrap();
479
+ * ```
480
+ *
481
+ * @example
482
+ *
483
+ * ```ts
484
+ * const error: "error" = Result.$collect({
485
+ * a: Ok(1),
486
+ * b: Err("error"),
487
+ * }).$unwrapErr();
488
+ * ```
489
+ */
490
+ function $collect(results) {
491
+ const oks = {};
492
+ for (const [key, result] of Object.entries(results)) {
493
+ const { ok, value } = result[retuple_symbols_1.ResultLikeSymbol]();
494
+ if (ok) {
495
+ oks[key] = value;
496
+ }
497
+ else {
498
+ return Err(value);
499
+ }
500
+ }
501
+ return Ok(oks);
502
+ }
503
+ /**
504
+ * The same as {@link Result.$collect|$collect} except it accepts result-like
505
+ * promises and returns {@link ResultAsync}.
506
+ */
507
+ function $collectPromised(results) {
508
+ return new ResultAsync(new Promise((resolve, reject) => {
509
+ void Promise.all(Object.entries(results).map(([key, result]) => Promise.resolve(result).then((result) => {
510
+ const { ok, value } = result[retuple_symbols_1.ResultLikeSymbol]();
511
+ return ok ? [key, value] : Promise.reject(value);
512
+ }, (err) => {
513
+ reject(err);
514
+ // Because reject has been called, we can safely return an
515
+ // empty rejection to ensure we don't end up with undefined
516
+ // in the Ok path. The subsequent call to resolve will not
517
+ // change the state of the Promise.
518
+ return Promise.reject();
519
+ }))).then((values) => resolve(Ok(Object.fromEntries(values))), (err) => resolve(Err(err)));
520
+ }));
521
+ }
522
+ function $pipe(f0, ...fnx) {
523
+ const first = asResult(f0());
524
+ if (first instanceof ResultErr) {
525
+ return first;
526
+ }
527
+ let current = first[1];
528
+ for (const fn of fnx) {
529
+ const result = asResult(fn(current));
530
+ if (result instanceof ResultErr) {
531
+ return result;
532
+ }
533
+ current = result[1];
534
+ }
535
+ return Ok(current);
536
+ }
537
+ function $pipeAsync(f0, ...fnx) {
538
+ return new ResultAsync((async () => {
539
+ const first = asResult(await f0());
540
+ if (first instanceof ResultErr) {
541
+ return first;
542
+ }
543
+ let current = first[1];
544
+ for (const fn of fnx) {
545
+ const result = asResult(await fn(current));
546
+ if (result instanceof ResultErr) {
547
+ return result;
548
+ }
549
+ current = result[1];
550
+ }
551
+ return Ok(current);
552
+ })());
553
+ }
554
+ /**
555
+ * ## ResultOk
556
+ *
557
+ * This is the `Ok` variant of a `Result`, used internally and not exported.
155
558
  */
156
559
  class ResultOk extends Array {
157
560
  constructor(value) {
@@ -159,13 +562,10 @@ class ResultOk extends Array {
159
562
  this[0] = undefined;
160
563
  this[1] = value;
161
564
  }
162
- toJSON() {
163
- return this[1];
164
- }
165
- $toNativeTuple() {
166
- return [undefined, this[1]];
565
+ [retuple_symbols_1.ResultLikeSymbol]() {
566
+ return { ok: true, value: this[1] };
167
567
  }
168
- $value() {
568
+ toJSON() {
169
569
  return this[1];
170
570
  }
171
571
  $isOk() {
@@ -196,50 +596,120 @@ class ResultOk extends Array {
196
596
  return this[1];
197
597
  }
198
598
  $map(f) {
199
- return new ResultOk(f(this[1]));
599
+ return Ok(f(this[1]));
200
600
  }
201
601
  $mapErr() {
202
602
  return this;
203
603
  }
204
604
  $mapOr(_def, f) {
205
- return new ResultOk(f(this[1]));
605
+ return Ok(f(this[1]));
206
606
  }
207
607
  $mapOrElse(_def, f) {
208
- return new ResultOk(f(this[1]));
209
- }
210
- $assertOr(def, condition = isTruthy) {
211
- return condition(this[1]) ? this : def;
212
- }
213
- $assertOrElse(def, condition = isTruthy) {
214
- return condition(this[1]) ? this : def();
608
+ return Ok(f(this[1]));
609
+ }
610
+ $assert(mapError) {
611
+ return this[1]
612
+ ? this
613
+ : Err(mapError
614
+ ? mapError(this[1])
615
+ : new RetupleAssertFailed(this[1]));
616
+ }
617
+ $filter(filter, mapError) {
618
+ return filter(this[1])
619
+ ? this
620
+ : Err(mapError ? mapError(this[1]) : new RetupleFilterFailed(this[1]));
621
+ }
622
+ $atIndex(index, mapError) {
623
+ const element = this[1][index];
624
+ return element
625
+ ? Ok(element)
626
+ : Err(mapError
627
+ ? mapError(this[1])
628
+ : new RetupleIndexFailed(index, this[1]));
629
+ }
630
+ $firstIndex(mapError) {
631
+ const first = this[1][0];
632
+ return first
633
+ ? Ok(first)
634
+ : Err(mapError
635
+ ? mapError(this[1])
636
+ : new RetupleIndexFailed(0, this[1]));
215
637
  }
216
638
  $or() {
217
639
  return this;
218
640
  }
641
+ $orAsync() {
642
+ return this.$async();
643
+ }
219
644
  $orElse() {
220
645
  return this;
221
646
  }
647
+ $orElseAsync() {
648
+ return this.$async();
649
+ }
222
650
  $orSafe() {
223
651
  return this;
224
652
  }
653
+ $orSafeAsync() {
654
+ return this.$async();
655
+ }
656
+ $orSafePromise() {
657
+ return this.$async();
658
+ }
225
659
  $and(and) {
226
- return and;
660
+ return asResult(and);
661
+ }
662
+ $andAsync(and) {
663
+ return this.$async().$and(and);
227
664
  }
228
665
  $andThen(f) {
229
- return f(this[1]);
666
+ return asResult(f(this[1]));
667
+ }
668
+ $andStack(f) {
669
+ const res = asResult(f(this[1]));
670
+ if (res instanceof ResultErr) {
671
+ return res;
672
+ }
673
+ if (this[1] instanceof RetupleStack) {
674
+ return Ok(new RetupleStack(...this[1], res[1]));
675
+ }
676
+ else {
677
+ return Ok(new RetupleStack(this[1], res[1]));
678
+ }
679
+ }
680
+ $andThenAsync(f) {
681
+ return this.$async().$andThen(f);
682
+ }
683
+ $andStackAsync(f) {
684
+ return this.$async().$andStack(f);
230
685
  }
231
686
  $andThrough(f) {
232
- const res = f(this[1]);
687
+ const res = asResult(f(this[1]));
233
688
  return res instanceof ResultErr ? res : this;
234
689
  }
690
+ $andThroughAsync(f) {
691
+ return this.$async().$andThrough(f);
692
+ }
235
693
  $andSafe(f, mapError = ensureError) {
236
694
  try {
237
- return new ResultOk(f(this[1]));
695
+ return Ok(f(this[1]));
238
696
  }
239
697
  catch (err) {
240
- return new ResultErr(mapError(err));
698
+ return Err(mapError(err));
241
699
  }
242
700
  }
701
+ $andSafeAsync(f, mapError = ensureError) {
702
+ return this.$async().$andSafe(f, mapError);
703
+ }
704
+ $andSafePromise(promise, mapError = ensureError) {
705
+ return this.$async().$andSafePromise(promise, mapError);
706
+ }
707
+ $andPipe(f0, ...fx) {
708
+ return Result.$pipe(() => f0(this[1]), ...fx);
709
+ }
710
+ $andPipeAsync(f0, ...fx) {
711
+ return Result.$pipeAsync(() => f0(this[1]), ...fx);
712
+ }
243
713
  $peek(f) {
244
714
  f(this);
245
715
  return this;
@@ -260,11 +730,14 @@ class ResultOk extends Array {
260
730
  $promise() {
261
731
  return Promise.resolve(this);
262
732
  }
733
+ *$iter() {
734
+ yield* this[1];
735
+ }
263
736
  }
264
737
  /**
265
- * ## Err
738
+ * ## ResultErr
266
739
  *
267
- * @TODO
740
+ * This is the `Err` variant of a `Result`, used internally and not exported.
268
741
  */
269
742
  class ResultErr extends Array {
270
743
  constructor(err) {
@@ -272,15 +745,12 @@ class ResultErr extends Array {
272
745
  this[0] = err;
273
746
  this[1] = undefined;
274
747
  }
748
+ [retuple_symbols_1.ResultLikeSymbol]() {
749
+ return { ok: false, value: this[0] };
750
+ }
275
751
  toJSON() {
276
752
  return null;
277
753
  }
278
- $toNativeTuple() {
279
- return [this[0], undefined];
280
- }
281
- $value() {
282
- return this[0];
283
- }
284
754
  $isOk() {
285
755
  return false;
286
756
  }
@@ -315,46 +785,91 @@ class ResultErr extends Array {
315
785
  return this;
316
786
  }
317
787
  $mapErr(f) {
318
- return new ResultErr(f(this[0]));
788
+ return Err(f(this[0]));
319
789
  }
320
790
  $mapOr(def) {
321
- return new ResultOk(def);
791
+ return Ok(def);
322
792
  }
323
793
  $mapOrElse(def) {
324
- return new ResultOk(def(this[0]));
794
+ return Ok(def(this[0]));
325
795
  }
326
- $assertOr() {
796
+ $assert() {
327
797
  return this;
328
798
  }
329
- $assertOrElse() {
799
+ $filter() {
800
+ return this;
801
+ }
802
+ $atIndex() {
803
+ return this;
804
+ }
805
+ $firstIndex() {
330
806
  return this;
331
807
  }
332
808
  $or(or) {
333
- return or;
809
+ return asResult(or);
810
+ }
811
+ $orAsync(or) {
812
+ return this.$async().$or(or);
334
813
  }
335
814
  $orElse(f) {
336
- return f(this[0]);
815
+ return asResult(f(this[0]));
816
+ }
817
+ $orElseAsync(f) {
818
+ return this.$async().$orElse(f);
337
819
  }
338
820
  $orSafe(f, mapError = ensureError) {
339
821
  try {
340
- return new ResultOk(f(this[0]));
822
+ return Ok(f(this[0]));
341
823
  }
342
824
  catch (err) {
343
- return new ResultErr(mapError(err));
825
+ return Err(mapError(err));
344
826
  }
345
827
  }
828
+ $orSafeAsync(f, mapError = ensureError) {
829
+ return this.$async().$orSafe(f, mapError);
830
+ }
831
+ $orSafePromise(promise, mapError = ensureError) {
832
+ return this.$async().$orSafePromise(promise, mapError);
833
+ }
346
834
  $and() {
347
835
  return this;
348
836
  }
837
+ $andAsync() {
838
+ return this.$async();
839
+ }
349
840
  $andThen() {
350
841
  return this;
351
842
  }
843
+ $andStack() {
844
+ return this;
845
+ }
846
+ $andThenAsync() {
847
+ return this.$async();
848
+ }
849
+ $andStackAsync() {
850
+ return this.$async();
851
+ }
352
852
  $andThrough() {
353
853
  return this;
354
854
  }
855
+ $andThroughAsync() {
856
+ return this.$async();
857
+ }
355
858
  $andSafe() {
356
859
  return this;
357
860
  }
861
+ $andSafeAsync() {
862
+ return this.$async();
863
+ }
864
+ $andSafePromise() {
865
+ return this.$async();
866
+ }
867
+ $andPipe() {
868
+ return this;
869
+ }
870
+ $andPipeAsync() {
871
+ return this.$async();
872
+ }
358
873
  $peek(f) {
359
874
  f(this);
360
875
  return this;
@@ -375,6 +890,9 @@ class ResultErr extends Array {
375
890
  $promise() {
376
891
  return Promise.resolve(this);
377
892
  }
893
+ *$iter() {
894
+ return;
895
+ }
378
896
  }
379
897
  /**
380
898
  * ## ResultAsync
@@ -390,44 +908,79 @@ class ResultAsync {
390
908
  return __classPrivateFieldGet(this, _ResultAsync_inner, "f").then(onfulfilled, onrejected);
391
909
  }
392
910
  /**
393
- * @TODO
394
- */
395
- async $value() {
396
- return (await __classPrivateFieldGet(this, _ResultAsync_inner, "f")).$value();
397
- }
398
- /**
399
- * @TODO
911
+ * The same as {@link Retuple.$expect|$expect}, except it returns a `Promise`.
400
912
  */
401
913
  async $expect() {
402
914
  return (await __classPrivateFieldGet(this, _ResultAsync_inner, "f")).$expect();
403
915
  }
404
916
  /**
405
- * @TODO
917
+ * The same as {@link Retuple.$unwrap|$unwrap}, except it returns a `Promise`.
406
918
  */
407
919
  async $unwrap(msg) {
408
920
  return (await __classPrivateFieldGet(this, _ResultAsync_inner, "f")).$unwrap(msg);
409
921
  }
410
922
  /**
411
- * @TODO
923
+ * Resolves this `ResultAsync` using the provided resolver. The resolver
924
+ * receives a promise which resolves when the result is `Ok` and rejects if
925
+ * the result is `Err`.
926
+ *
927
+ * This method should only be called when the `E` type extends `Error`. This
928
+ * is enforced with a type constraint. If the error value is not an instance
929
+ * of Error, the promise rejects with `RetupleExpectFailed`.
930
+ *
931
+ * @example
932
+ *
933
+ * ```ts
934
+ * async function resolver(promise: Promise<URL>): string {
935
+ * try {
936
+ * const url = await promise;
937
+ *
938
+ * return url.toString();
939
+ * } catch (cause) {
940
+ * throw new Error("Not a valid URL", { cause });
941
+ * }
942
+ * }
943
+ *
944
+ * const urlString = await Result.$safeAsync(() => getDataAsync())
945
+ * .$andSafe((data) => new URL(data.url))
946
+ * .$resolve(resolver);
947
+ * ```
948
+ */
949
+ async $resolve(resolver) {
950
+ return __classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (result) => {
951
+ if (result instanceof ResultOk) {
952
+ return await resolver(Promise.resolve(result[1]));
953
+ }
954
+ return await resolver(Promise.reject(result[0] instanceof Error
955
+ ? result[0]
956
+ : new RetupleExpectFailed(result[0])));
957
+ });
958
+ }
959
+ /**
960
+ * The same as {@link Retuple.$unwrapErr|$unwrapErr}, except it returns
961
+ * a `Promise`.
412
962
  */
413
963
  async $unwrapErr(msg) {
414
964
  return (await __classPrivateFieldGet(this, _ResultAsync_inner, "f")).$unwrapErr(msg);
415
965
  }
416
966
  /**
417
- * @TODO
967
+ * The same as {@link Retuple.$unwrapOr|$unwrapOr}, except it returns
968
+ * a `Promise`.
418
969
  */
419
970
  async $unwrapOr(def) {
420
971
  return (await __classPrivateFieldGet(this, _ResultAsync_inner, "f")).$unwrapOr(def);
421
972
  }
422
973
  /**
423
- * @TODO
974
+ * The same as {@link Retuple.$unwrapOrElse|$unwrapOrElse}, except it returns
975
+ * a `Promise`.
424
976
  */
425
977
  async $unwrapOrElse(f) {
426
978
  const res = await __classPrivateFieldGet(this, _ResultAsync_inner, "f");
427
979
  return res instanceof ResultOk ? res[1] : f();
428
980
  }
429
981
  /**
430
- * @TODO
982
+ * The same as {@link Retuple.$map|$map}, except it returns
983
+ * {@link ResultAsync}.
431
984
  */
432
985
  $map(f) {
433
986
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
@@ -437,7 +990,8 @@ class ResultAsync {
437
990
  }));
438
991
  }
439
992
  /**
440
- * @TODO
993
+ * The same as {@link Retuple.$mapErr|$mapErr}, except it returns
994
+ * {@link ResultAsync}.
441
995
  */
442
996
  $mapErr(f) {
443
997
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
@@ -447,7 +1001,8 @@ class ResultAsync {
447
1001
  }));
448
1002
  }
449
1003
  /**
450
- * @TODO
1004
+ * The same as {@link Retuple.$mapOr|$mapOr}, except it returns
1005
+ * {@link ResultAsync}.
451
1006
  */
452
1007
  $mapOr(def, f) {
453
1008
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
@@ -457,7 +1012,8 @@ class ResultAsync {
457
1012
  }));
458
1013
  }
459
1014
  /**
460
- * @TODO
1015
+ * The same as {@link Retuple.$mapOrElse|$mapOrElse}, except it returns
1016
+ * {@link ResultAsync}.
461
1017
  */
462
1018
  $mapOrElse(def, f) {
463
1019
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
@@ -466,36 +1022,68 @@ class ResultAsync {
466
1022
  : new ResultOk(def(res[0]));
467
1023
  }));
468
1024
  }
469
- $assertOr(def, condition = isTruthy) {
1025
+ $assert(mapError) {
470
1026
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
471
- if (res instanceof ResultErr || condition(res[1])) {
1027
+ if (res instanceof ResultErr) {
472
1028
  return res;
473
1029
  }
474
- return await def;
1030
+ return res[1]
1031
+ ? res
1032
+ : Err(mapError
1033
+ ? mapError(res[1])
1034
+ : new RetupleAssertFailed(res[1]));
475
1035
  }));
476
1036
  }
477
- $assertOrElse(def, condition = isTruthy) {
1037
+ $filter(check, mapError) {
478
1038
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
479
- if (res instanceof ResultErr || condition(res[1])) {
1039
+ if (res instanceof ResultErr) {
480
1040
  return res;
481
1041
  }
482
- return await def();
1042
+ return check(res[1])
1043
+ ? res
1044
+ : Err(mapError
1045
+ ? mapError(res[1])
1046
+ : new RetupleFilterFailed(res[1]));
1047
+ }));
1048
+ }
1049
+ $atIndex(index, mapError) {
1050
+ return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then((res) => {
1051
+ if (res instanceof ResultErr) {
1052
+ return res;
1053
+ }
1054
+ const element = res[1][index];
1055
+ return element
1056
+ ? Ok(element)
1057
+ : Err(mapError
1058
+ ? mapError(res[1])
1059
+ : new RetupleIndexFailed(index, res[1]));
1060
+ }));
1061
+ }
1062
+ $firstIndex(mapError) {
1063
+ return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then((res) => {
1064
+ if (res instanceof ResultErr) {
1065
+ return res;
1066
+ }
1067
+ const first = res[1][0];
1068
+ return first
1069
+ ? Ok(first)
1070
+ : Err(mapError
1071
+ ? mapError(res[1])
1072
+ : new RetupleIndexFailed(0, res[1]));
483
1073
  }));
484
1074
  }
485
- /**
486
- * @TODO
487
- */
488
1075
  $or(or) {
489
1076
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
490
- return res instanceof ResultErr ? await or : res;
1077
+ return res instanceof ResultErr
1078
+ ? asResult(await or)
1079
+ : res;
491
1080
  }));
492
1081
  }
493
- /**
494
- * @TODO
495
- */
496
1082
  $orElse(f) {
497
1083
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
498
- return res instanceof ResultErr ? await f(res[0]) : res;
1084
+ return res instanceof ResultErr
1085
+ ? asResult(await f(res[0]))
1086
+ : res;
499
1087
  }));
500
1088
  }
501
1089
  $orSafe(f, mapError = ensureError) {
@@ -511,29 +1099,52 @@ class ResultAsync {
511
1099
  }
512
1100
  }));
513
1101
  }
514
- /**
515
- * @TODO
516
- */
1102
+ $orSafePromise(promise, mapError = ensureError) {
1103
+ return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
1104
+ if (res instanceof ResultOk) {
1105
+ return res;
1106
+ }
1107
+ try {
1108
+ return new ResultOk(await promise);
1109
+ }
1110
+ catch (err) {
1111
+ return new ResultErr(mapError(err));
1112
+ }
1113
+ }));
1114
+ }
517
1115
  $and(and) {
518
1116
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
519
- return res instanceof ResultOk ? await and : res;
1117
+ return res instanceof ResultOk
1118
+ ? asResult(await and)
1119
+ : res;
520
1120
  }));
521
1121
  }
522
- /**
523
- * @TODO
524
- */
525
1122
  $andThen(f) {
526
1123
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
527
- return res instanceof ResultOk ? await f(res[1]) : res;
1124
+ return res instanceof ResultOk
1125
+ ? asResult(await f(res[1]))
1126
+ : res;
1127
+ }));
1128
+ }
1129
+ $andStack(f) {
1130
+ return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
1131
+ if (res instanceof ResultErr) {
1132
+ return res;
1133
+ }
1134
+ const resThen = asResult(await f(res[1]));
1135
+ if (resThen instanceof ResultErr) {
1136
+ return resThen;
1137
+ }
1138
+ if (res[1] instanceof RetupleStack) {
1139
+ return Ok(new RetupleStack(...res[1], resThen[1]));
1140
+ }
1141
+ return Ok(new RetupleStack(res[1], resThen[1]));
528
1142
  }));
529
1143
  }
530
- /**
531
- * @TODO
532
- */
533
1144
  $andThrough(f) {
534
1145
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
535
1146
  if (res instanceof ResultOk) {
536
- const through = await f(res[1]);
1147
+ const through = asResult(await f(res[1]));
537
1148
  if (through instanceof ResultErr) {
538
1149
  return through;
539
1150
  }
@@ -547,15 +1158,47 @@ class ResultAsync {
547
1158
  return res;
548
1159
  }
549
1160
  try {
550
- return new ResultOk(await f(res[1]));
1161
+ return Ok(await f(res[1]));
551
1162
  }
552
1163
  catch (err) {
553
- return new ResultErr(mapError(err));
1164
+ return Err(mapError(err));
1165
+ }
1166
+ }));
1167
+ }
1168
+ $andSafePromise(promise, mapError = ensureError) {
1169
+ return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
1170
+ if (res instanceof ResultErr) {
1171
+ return res;
1172
+ }
1173
+ try {
1174
+ return Ok(await promise);
1175
+ }
1176
+ catch (err) {
1177
+ return Err(mapError(err));
1178
+ }
1179
+ }));
1180
+ }
1181
+ $andPipe(...fx) {
1182
+ return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
1183
+ if (res instanceof ResultErr) {
1184
+ return res;
554
1185
  }
1186
+ let current = res[1];
1187
+ for (const f of fx) {
1188
+ const result = asResult(await f(current));
1189
+ if (result instanceof ResultErr) {
1190
+ return result;
1191
+ }
1192
+ current = result[1];
1193
+ }
1194
+ return Ok(current);
555
1195
  }));
556
1196
  }
557
1197
  /**
558
- * @TODO
1198
+ * The same as {@link Retuple.$peek|$peek}, except it:
1199
+ *
1200
+ * - awaits the peek function;
1201
+ * - returns {@link ResultAsync}.
559
1202
  */
560
1203
  $peek(f) {
561
1204
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
@@ -564,7 +1207,10 @@ class ResultAsync {
564
1207
  }));
565
1208
  }
566
1209
  /**
567
- * @TODO
1210
+ * The same as {@link Retuple.$tap|$tap}, except it:
1211
+ *
1212
+ * - awaits the tap function;
1213
+ * - returns {@link ResultAsync}.
568
1214
  */
569
1215
  $tap(f) {
570
1216
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
@@ -575,7 +1221,10 @@ class ResultAsync {
575
1221
  }));
576
1222
  }
577
1223
  /**
578
- * @TODO
1224
+ * The same as {@link Retuple.$tapErr|$tapErr}, except it:
1225
+ *
1226
+ * - awaits the tap error function;
1227
+ * - returns {@link ResultAsync}.
579
1228
  */
580
1229
  $tapErr(f) {
581
1230
  return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then(async (res) => {
@@ -586,22 +1235,171 @@ class ResultAsync {
586
1235
  }));
587
1236
  }
588
1237
  /**
589
- * @TODO
1238
+ * The same as {@link Retuple.$flatten|$flatten} except it returns
1239
+ * {@link ResultAsync}.
1240
+ */
1241
+ $flatten() {
1242
+ return new ResultAsync(__classPrivateFieldGet(this, _ResultAsync_inner, "f").then((res) => res.$flatten()));
1243
+ }
1244
+ /**
1245
+ * The same as {@link Retuple.$promise|$promise}.
590
1246
  */
591
1247
  $promise() {
592
1248
  return Promise.resolve(this);
593
1249
  }
1250
+ /**
1251
+ * The same as {@link Retuple.$iter|$iter}, except it returns a `Promise`.
1252
+ */
1253
+ async $iter() {
1254
+ return (await __classPrivateFieldGet(this, _ResultAsync_inner, "f")).$iter();
1255
+ }
594
1256
  }
595
1257
  _ResultAsync_inner = new WeakMap();
1258
+ /**
1259
+ * ## ResultRetry
1260
+ */
1261
+ class ResultRetry extends ResultAsync {
1262
+ static zero() {
1263
+ return 0;
1264
+ }
1265
+ static delay(ms) {
1266
+ return new Promise((resolve) => setTimeout(resolve, Math.min(ms, _a.MAX_TIMEOUT)));
1267
+ }
1268
+ static integer(value) {
1269
+ if (typeof value === "number" && Number.isInteger(value)) {
1270
+ return Math.max(0, value);
1271
+ }
1272
+ return 0;
1273
+ }
1274
+ constructor(f) {
1275
+ super(Promise.resolve().then(() => __classPrivateFieldGet(this, _ResultRetry_promise, "f")));
1276
+ _ResultRetry_f.set(this, void 0);
1277
+ _ResultRetry_promise.set(this, void 0);
1278
+ _ResultRetry_times.set(this, 1);
1279
+ _ResultRetry_attempt.set(this, 0);
1280
+ _ResultRetry_aborted.set(this, false);
1281
+ _ResultRetry_abort.set(this, () => (__classPrivateFieldSet(this, _ResultRetry_aborted, true, "f")));
1282
+ _ResultRetry_getDelay.set(this, _a.zero);
1283
+ _ResultRetry_handler.set(this, void 0);
1284
+ __classPrivateFieldSet(this, _ResultRetry_f, f, "f");
1285
+ __classPrivateFieldSet(this, _ResultRetry_promise, this.drain(), "f");
1286
+ }
1287
+ then(onfulfilled, onrejected) {
1288
+ return super.then(onfulfilled, onrejected);
1289
+ }
1290
+ /**
1291
+ * Sets the maximum number of times the retry function can be executed,
1292
+ * mutating this `ResultRetry` instance.
1293
+ *
1294
+ * **The default value is 1 - meaning that unless set, no retries will be
1295
+ * attempted.**
1296
+ *
1297
+ * The retry function can be called up to the maximum number of times until
1298
+ * it returns `Ok`. If it never returns `Ok`, the most recent `Err` is
1299
+ * returned.
1300
+ *
1301
+ * This function accepts a positive integer between 1 and 100:
1302
+ *
1303
+ * - Integers outside of this range are clamped to the nearest valid value;
1304
+ * - Any other value (NaN, Infinity, fractions, strings) are treated as 1.
1305
+ *
1306
+ * @example
1307
+ *
1308
+ * ```ts
1309
+ * // Retry someResultFn up to 3 times until Ok is returned:
1310
+ * const result = await Result.$retry(someResultFn).$times(3);
1311
+ * ```
1312
+ */
1313
+ $times(times) {
1314
+ __classPrivateFieldSet(this, _ResultRetry_times, Math.min(Math.max(1, _a.integer(times)), _a.MAX_RETRY), "f");
1315
+ return this;
1316
+ }
1317
+ $delay(fnOrMs) {
1318
+ if (typeof fnOrMs === "function") {
1319
+ __classPrivateFieldSet(this, _ResultRetry_getDelay, fnOrMs, "f");
1320
+ return this;
1321
+ }
1322
+ const delay = _a.integer(fnOrMs);
1323
+ if (delay > 0) {
1324
+ __classPrivateFieldSet(this, _ResultRetry_getDelay, () => delay, "f");
1325
+ }
1326
+ return this;
1327
+ }
1328
+ /**
1329
+ * Sets a handler to be called when an attempt returns `Err`, mutating this
1330
+ * `ResultRetry` instance. The handler can be used to capture information
1331
+ * about each failure, and to abort early and prevent further retries.
1332
+ *
1333
+ * The handler function is called with `ResultRetryHandleState`, containing:
1334
+ *
1335
+ * - **error** - The error value from the last failed attempt;
1336
+ * - **attempt** - The attempt number;
1337
+ * - **abort** - A function which when called, prevents further retries.
1338
+ *
1339
+ * @example
1340
+ *
1341
+ * ```ts
1342
+ * // Retry someResultFn up to 3 times until Ok is returned, logging each
1343
+ * // attempt and aborting early if the error code is "UNAUTHORIZED".
1344
+ * const result = await Result.$retry(someResultFn)
1345
+ * .$times(3)
1346
+ * .$handle(({ error, attempt, abort }) => {
1347
+ * console.info(`Attempt ${attempt} failed: ${error}`);
1348
+ * if (error === "UNAUTHORIZED") {
1349
+ * abort();
1350
+ * }
1351
+ * });
1352
+ * ```
1353
+ */
1354
+ $handle(f) {
1355
+ __classPrivateFieldSet(this, _ResultRetry_handler, f, "f");
1356
+ return this;
1357
+ }
1358
+ async drain() {
1359
+ var _b;
1360
+ while (__classPrivateFieldGet(this, _ResultRetry_attempt, "f") < __classPrivateFieldGet(this, _ResultRetry_times, "f")) {
1361
+ const result = asResult(await __classPrivateFieldGet(this, _ResultRetry_f, "f").call(this));
1362
+ __classPrivateFieldSet(this, _ResultRetry_attempt, (_b = __classPrivateFieldGet(this, _ResultRetry_attempt, "f"), _b++, _b), "f");
1363
+ if (result.$isOk()) {
1364
+ return result;
1365
+ }
1366
+ if (__classPrivateFieldGet(this, _ResultRetry_handler, "f")) {
1367
+ await __classPrivateFieldGet(this, _ResultRetry_handler, "f").call(this, {
1368
+ error: result[0],
1369
+ attempt: __classPrivateFieldGet(this, _ResultRetry_attempt, "f"),
1370
+ abort: __classPrivateFieldGet(this, _ResultRetry_abort, "f"),
1371
+ });
1372
+ }
1373
+ if (__classPrivateFieldGet(this, _ResultRetry_aborted, "f") || __classPrivateFieldGet(this, _ResultRetry_attempt, "f") >= __classPrivateFieldGet(this, _ResultRetry_times, "f")) {
1374
+ return result;
1375
+ }
1376
+ const delay = _a.integer(__classPrivateFieldGet(this, _ResultRetry_getDelay, "f").call(this, __classPrivateFieldGet(this, _ResultRetry_attempt, "f")));
1377
+ if (delay > 0) {
1378
+ await _a.delay(delay);
1379
+ }
1380
+ }
1381
+ /* v8 ignore next */
1382
+ throw new Error("Retuple: Unreachable code executed");
1383
+ }
1384
+ }
1385
+ _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();
1386
+ ResultRetry.MAX_TIMEOUT = 3600000;
1387
+ ResultRetry.MAX_RETRY = 100;
1388
+ class RetupleStack extends Array {
1389
+ }
1390
+ function asResult(resultLike) {
1391
+ if (resultLike instanceof ResultOk || resultLike instanceof ResultErr) {
1392
+ return resultLike;
1393
+ }
1394
+ const result = resultLike[retuple_symbols_1.ResultLikeSymbol]();
1395
+ return result.ok ? new ResultOk(result.value) : new ResultErr(result.value);
1396
+ }
596
1397
  function ensureError(err) {
597
1398
  if (err instanceof Error) {
598
1399
  return err;
599
1400
  }
600
- return new RetupleThrownValueError(err);
1401
+ return new RetupleCaughtValueError(err);
601
1402
  }
602
1403
  function mapTrue() {
603
1404
  return true;
604
1405
  }
605
- function isTruthy(val) {
606
- return !!val;
607
- }