retuple 1.0.0-next.11 → 1.0.0-next.13

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,9 +10,9 @@ 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_errorHandler;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.RetupleArrayMethodUnavailableError = exports.RetupleInvalidResultError = exports.RetupleThrownValueError = exports.RetupleFlattenFailed = exports.RetupleExpectFailed = exports.RetupleUnwrapErrFailed = exports.RetupleUnwrapFailed = void 0;
15
+ exports.RetupleArrayMethodUnavailableError = exports.RetupleInvalidUnionError = exports.RetupleInvalidResultError = exports.RetupleThrownValueError = exports.RetupleFlattenFailed = exports.RetupleExpectFailed = exports.RetupleUnwrapErrFailed = exports.RetupleUnwrapFailed = void 0;
16
16
  exports.Result = Result;
17
17
  exports.Ok = Ok;
18
18
  exports.Err = Err;
@@ -95,6 +95,22 @@ class RetupleInvalidResultError extends Error {
95
95
  }
96
96
  }
97
97
  exports.RetupleInvalidResultError = RetupleInvalidResultError;
98
+ /**
99
+ * ## Retuple Invalid Union Error
100
+ *
101
+ * This error is thrown when attempting to construct a `Result` from a
102
+ * discriminated union, when the 'success' property is not boolean. In this
103
+ * case, it is impossible to determine whether the result should be `Ok` or
104
+ * `Err`.
105
+ */
106
+ class RetupleInvalidUnionError extends Error {
107
+ constructor(value) {
108
+ super("Constructing a Result from discriminated union failed, the success " +
109
+ "property must be boolean");
110
+ this.value = value;
111
+ }
112
+ }
113
+ exports.RetupleInvalidUnionError = RetupleInvalidUnionError;
98
114
  /**
99
115
  * ## Retuple Array Method Unavailable Error
100
116
  *
@@ -128,9 +144,12 @@ Result.Err = Err;
128
144
  Result.$resolve = resolve;
129
145
  Result.$nonNullable = nonNullable;
130
146
  Result.$truthy = truthy;
147
+ Result.$union = union;
131
148
  Result.$safe = safe;
132
149
  Result.$safeAsync = safeAsync;
133
150
  Result.$safePromise = safePromise;
151
+ Result.$retry = retry;
152
+ Result.$safeRetry = safeRetry;
134
153
  Object.freeze(Result);
135
154
  function Ok(val) {
136
155
  return new ResultOk(val);
@@ -138,6 +157,9 @@ function Ok(val) {
138
157
  function Err(err) {
139
158
  return new ResultErr(err);
140
159
  }
160
+ /**
161
+ * @TODO
162
+ */
141
163
  function resolve(result) {
142
164
  if (result instanceof ResultAsync) {
143
165
  return result;
@@ -161,6 +183,18 @@ function truthy(value, error = mapTrue) {
161
183
  }
162
184
  return Err(error());
163
185
  }
186
+ /**
187
+ * @TODO
188
+ */
189
+ function union(union) {
190
+ if (union.success === true) {
191
+ return Ok(union.data);
192
+ }
193
+ if (union.success === false) {
194
+ return Err(union.error);
195
+ }
196
+ throw new RetupleInvalidUnionError(union);
197
+ }
164
198
  function safe(f, mapError = ensureError) {
165
199
  try {
166
200
  return Ok(f());
@@ -182,6 +216,22 @@ function safeAsync(f, mapError = ensureError) {
182
216
  function safePromise(promise, mapError = ensureError) {
183
217
  return new ResultAsync(promise.then((Ok), async (err) => Err(await mapError(err))));
184
218
  }
219
+ /**
220
+ * @TODO
221
+ */
222
+ function retry(f) {
223
+ return new ResultRetry(f);
224
+ }
225
+ function safeRetry(f, mapError = ensureError) {
226
+ return new ResultRetry(async () => {
227
+ try {
228
+ return Ok(await f());
229
+ }
230
+ catch (err) {
231
+ return Err(mapError(err));
232
+ }
233
+ });
234
+ }
185
235
  /**
186
236
  * ## RetupleArray
187
237
  *
@@ -1082,6 +1132,96 @@ class ResultAsync {
1082
1132
  }
1083
1133
  }
1084
1134
  _ResultAsync_inner = new WeakMap();
1135
+ /**
1136
+ * @TODO
1137
+ */
1138
+ class ResultRetry {
1139
+ static zero() {
1140
+ return 0;
1141
+ }
1142
+ static delay(ms) {
1143
+ return new Promise((resolve) => setTimeout(resolve, Math.min(ms, _a.MAX_TIMEOUT)));
1144
+ }
1145
+ static integer(value) {
1146
+ if (typeof value === "number" && Number.isInteger(value)) {
1147
+ return Math.max(0, value);
1148
+ }
1149
+ return 0;
1150
+ }
1151
+ constructor(f) {
1152
+ _ResultRetry_f.set(this, void 0);
1153
+ _ResultRetry_promise.set(this, void 0);
1154
+ _ResultRetry_times.set(this, 1);
1155
+ _ResultRetry_attempt.set(this, 0);
1156
+ _ResultRetry_aborted.set(this, false);
1157
+ _ResultRetry_abort.set(this, () => (__classPrivateFieldSet(this, _ResultRetry_aborted, true, "f")));
1158
+ _ResultRetry_getDelay.set(this, _a.zero);
1159
+ _ResultRetry_errorHandler.set(this, void 0);
1160
+ __classPrivateFieldSet(this, _ResultRetry_f, f, "f");
1161
+ __classPrivateFieldSet(this, _ResultRetry_promise, this.drain(), "f");
1162
+ }
1163
+ then(onfulfilled, onrejected) {
1164
+ return __classPrivateFieldGet(this, _ResultRetry_promise, "f").then(onfulfilled, onrejected);
1165
+ }
1166
+ /**
1167
+ * @TODO - Capped 100
1168
+ */
1169
+ $times(times) {
1170
+ __classPrivateFieldSet(this, _ResultRetry_times, Math.min(Math.max(1, _a.integer(times)), _a.MAX_RETRY), "f");
1171
+ return this;
1172
+ }
1173
+ $delay(fnOrMs) {
1174
+ if (typeof fnOrMs === "function") {
1175
+ __classPrivateFieldSet(this, _ResultRetry_getDelay, fnOrMs, "f");
1176
+ return this;
1177
+ }
1178
+ const delay = _a.integer(fnOrMs);
1179
+ if (delay > 0) {
1180
+ __classPrivateFieldSet(this, _ResultRetry_getDelay, () => delay, "f");
1181
+ }
1182
+ return this;
1183
+ }
1184
+ /**
1185
+ * @TODO
1186
+ */
1187
+ $monitor(f) {
1188
+ __classPrivateFieldSet(this, _ResultRetry_errorHandler, f, "f");
1189
+ return this;
1190
+ }
1191
+ /**
1192
+ * @TODO
1193
+ */
1194
+ $async() {
1195
+ return new ResultAsync(this);
1196
+ }
1197
+ async drain() {
1198
+ var _b;
1199
+ while (__classPrivateFieldGet(this, _ResultRetry_attempt, "f") < __classPrivateFieldGet(this, _ResultRetry_times, "f")) {
1200
+ const result = await __classPrivateFieldGet(this, _ResultRetry_f, "f").call(this);
1201
+ __classPrivateFieldSet(this, _ResultRetry_attempt, (_b = __classPrivateFieldGet(this, _ResultRetry_attempt, "f"), _b++, _b), "f");
1202
+ if (result.$isOk()) {
1203
+ return result;
1204
+ }
1205
+ if (__classPrivateFieldGet(this, _ResultRetry_errorHandler, "f")) {
1206
+ await __classPrivateFieldGet(this, _ResultRetry_errorHandler, "f").call(this, {
1207
+ error: result[0],
1208
+ attempt: __classPrivateFieldGet(this, _ResultRetry_attempt, "f"),
1209
+ abort: __classPrivateFieldGet(this, _ResultRetry_abort, "f"),
1210
+ });
1211
+ }
1212
+ if (__classPrivateFieldGet(this, _ResultRetry_aborted, "f") || __classPrivateFieldGet(this, _ResultRetry_attempt, "f") === __classPrivateFieldGet(this, _ResultRetry_times, "f")) {
1213
+ return result;
1214
+ }
1215
+ const delay = _a.integer(__classPrivateFieldGet(this, _ResultRetry_getDelay, "f").call(this, __classPrivateFieldGet(this, _ResultRetry_attempt, "f")));
1216
+ if (delay > 0) {
1217
+ await _a.delay(delay);
1218
+ }
1219
+ }
1220
+ }
1221
+ }
1222
+ _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_errorHandler = new WeakMap();
1223
+ ResultRetry.MAX_TIMEOUT = 3600000;
1224
+ ResultRetry.MAX_RETRY = 100;
1085
1225
  function ensureError(err) {
1086
1226
  if (err instanceof Error) {
1087
1227
  return err;
package/dist/index.d.cts CHANGED
@@ -62,6 +62,18 @@ export declare class RetupleInvalidResultError extends Error {
62
62
  value: unknown[];
63
63
  constructor(value: unknown[]);
64
64
  }
65
+ /**
66
+ * ## Retuple Invalid Union Error
67
+ *
68
+ * This error is thrown when attempting to construct a `Result` from a
69
+ * discriminated union, when the 'success' property is not boolean. In this
70
+ * case, it is impossible to determine whether the result should be `Ok` or
71
+ * `Err`.
72
+ */
73
+ export declare class RetupleInvalidUnionError extends Error {
74
+ value: unknown;
75
+ constructor(value: unknown);
76
+ }
65
77
  /**
66
78
  * ## Retuple Array Method Unavailable Error
67
79
  *
@@ -83,9 +95,12 @@ export declare namespace Result {
83
95
  var $resolve: typeof resolve;
84
96
  var $nonNullable: typeof nonNullable;
85
97
  var $truthy: typeof truthy;
98
+ var $union: typeof union;
86
99
  var $safe: typeof safe;
87
100
  var $safeAsync: typeof safeAsync;
88
101
  var $safePromise: typeof safePromise;
102
+ var $retry: typeof retry;
103
+ var $safeRetry: typeof safeRetry;
89
104
  }
90
105
  /**
91
106
  * Create a new {@link Result} with the `Ok` variant. When called without
@@ -129,6 +144,9 @@ export declare function Ok<const T>(val: T): Result<T, never>;
129
144
  */
130
145
  export declare function Err(): Result<never, void>;
131
146
  export declare function Err<const E>(err: E): Result<never, E>;
147
+ /**
148
+ * @TODO
149
+ */
132
150
  declare function resolve<T, E>(result: Retuple<T, E> | PromiseLike<Retuple<T, E>>): ResultAsync<T, E>;
133
151
  /**
134
152
  * Construct a {@link Result} from a value. If the value is neither null or
@@ -224,6 +242,10 @@ declare function nonNullable<const T, E>(value: T, error: () => E): Result<NonNu
224
242
  */
225
243
  declare function truthy<const T>(value: T): Result<Truthy<T>, true>;
226
244
  declare function truthy<const T, E>(value: T, error: () => E): Result<Truthy<T>, E>;
245
+ /**
246
+ * @TODO
247
+ */
248
+ declare function union<U extends ObjectUnionOk<any> | ObjectUnionErr<any>>(union: U): Result<U extends ObjectUnionOk<infer T> ? T : never, U extends ObjectUnionErr<infer E> ? E : never>;
227
249
  /**
228
250
  * Construct a {@link Result} from a synchronous function call. If the function
229
251
  * returns without throwing, the result is `Ok`.
@@ -421,6 +443,15 @@ declare function safeAsync<T, E>(f: () => T | PromiseLike<T>, mapError: (err: un
421
443
  */
422
444
  declare function safePromise<T>(promise: PromiseLike<T>): ResultAsync<T, Error>;
423
445
  declare function safePromise<T, E>(promise: PromiseLike<T>, mapError: (err: unknown) => E): ResultAsync<T, E>;
446
+ /**
447
+ * @TODO
448
+ */
449
+ declare function retry<T, E>(f: () => Retuple<T, E> | PromiseLike<Retuple<T, E>>): ResultRetry<T, E>;
450
+ /**
451
+ * @TODO
452
+ */
453
+ declare function safeRetry<T>(f: () => T | PromiseLike<T>): ResultRetry<T, Error>;
454
+ declare function safeRetry<T, E>(f: () => T | PromiseLike<T>, mapError: (err: unknown) => E): ResultRetry<T, E>;
424
455
  /**
425
456
  * ## RetupleArray
426
457
  *
@@ -934,12 +965,42 @@ declare class ResultAsync<T, E> {
934
965
  */
935
966
  $iter<U>(this: ResultAsync<Iterable<U>, E>): Promise<IterableIterator<U, undefined, unknown>>;
936
967
  }
937
- type Truthy<T> = Exclude<T, false | null | undefined | 0 | 0n | "">;
938
- type OkTuple<T> = [err: undefined, value: T];
939
- type ErrTuple<E> = [err: E, value: undefined];
940
- type ThisOk<T> = OkTuple<T> & Retuple<T, never>;
941
- type ThisErr<E> = ErrTuple<E> & Retuple<never, E>;
942
- type RetupleAwaitable<T, E> = Retuple<T, E> | PromiseLike<Retuple<T, E>>;
968
+ interface ResultRetryMonitor<E> {
969
+ error: E;
970
+ attempt: number;
971
+ abort: () => void;
972
+ }
973
+ /**
974
+ * @TODO
975
+ */
976
+ declare class ResultRetry<T, E> implements PromiseLike<Result<T, E>> {
977
+ #private;
978
+ private static MAX_TIMEOUT;
979
+ private static MAX_RETRY;
980
+ private static zero;
981
+ private static delay;
982
+ private static integer;
983
+ constructor(f: () => RetupleAwaitable<T, E>);
984
+ then<U = Result<T, E>, F = never>(onfulfilled?: ((value: Result<T, E>) => U | PromiseLike<U>) | null | undefined, onrejected?: ((reason: any) => F | PromiseLike<F>) | null | undefined): PromiseLike<U | F>;
985
+ /**
986
+ * @TODO - Capped 100
987
+ */
988
+ $times<N extends number>(this: ResultRetry<T, E>, times: NonZero<N> & NonNegativeOrDecimal<N>): ResultRetry<T, E>;
989
+ /**
990
+ * @TODO - Capped 1 hour
991
+ */
992
+ $delay<N extends number>(this: ResultRetry<T, E>, f: (attempt: number) => NonNegativeOrDecimal<N>): ResultRetry<T, E>;
993
+ $delay<N extends number>(this: ResultRetry<T, E>, ms: NonNegativeOrDecimal<N>): ResultRetry<T, E>;
994
+ /**
995
+ * @TODO
996
+ */
997
+ $monitor(f: (state: ResultRetryMonitor<E>) => void): ResultRetry<T, E>;
998
+ /**
999
+ * @TODO
1000
+ */
1001
+ $async(this: ResultRetry<T, E>): ResultAsync<T, E>;
1002
+ private drain;
1003
+ }
943
1004
  interface Retuple<T, E> extends RetupleArray<T | E | undefined> {
944
1005
  /**
945
1006
  * Returns true when this result is `Ok`. Acts as a type guard.
@@ -1950,3 +2011,21 @@ interface Retuple<T, E> extends RetupleArray<T | E | undefined> {
1950
2011
  */
1951
2012
  $iter<U>(this: Result<Iterable<U>, E>): IterableIterator<U, undefined, unknown>;
1952
2013
  }
2014
+ type OkTuple<T> = [err: undefined, value: T];
2015
+ type ErrTuple<E> = [err: E, value: undefined];
2016
+ type ThisOk<T> = OkTuple<T> & Retuple<T, never>;
2017
+ type ThisErr<E> = ErrTuple<E> & Retuple<never, E>;
2018
+ type RetupleAwaitable<T, E> = Retuple<T, E> | PromiseLike<Retuple<T, E>>;
2019
+ type ObjectUnionOk<T> = {
2020
+ success: true;
2021
+ data: T;
2022
+ error?: never | undefined;
2023
+ };
2024
+ type ObjectUnionErr<E> = {
2025
+ success: false;
2026
+ data?: never | undefined;
2027
+ error: E;
2028
+ };
2029
+ type Truthy<T> = Exclude<T, false | null | undefined | 0 | 0n | "">;
2030
+ type NonZero<N extends number> = N & (`${N}` extends "0" ? never : N);
2031
+ type NonNegativeOrDecimal<N extends number> = N & (`${N}` extends `-${string}` | `${string}.${string}` ? never : N);
package/dist/index.d.ts CHANGED
@@ -62,6 +62,18 @@ export declare class RetupleInvalidResultError extends Error {
62
62
  value: unknown[];
63
63
  constructor(value: unknown[]);
64
64
  }
65
+ /**
66
+ * ## Retuple Invalid Union Error
67
+ *
68
+ * This error is thrown when attempting to construct a `Result` from a
69
+ * discriminated union, when the 'success' property is not boolean. In this
70
+ * case, it is impossible to determine whether the result should be `Ok` or
71
+ * `Err`.
72
+ */
73
+ export declare class RetupleInvalidUnionError extends Error {
74
+ value: unknown;
75
+ constructor(value: unknown);
76
+ }
65
77
  /**
66
78
  * ## Retuple Array Method Unavailable Error
67
79
  *
@@ -83,9 +95,12 @@ export declare namespace Result {
83
95
  var $resolve: typeof resolve;
84
96
  var $nonNullable: typeof nonNullable;
85
97
  var $truthy: typeof truthy;
98
+ var $union: typeof union;
86
99
  var $safe: typeof safe;
87
100
  var $safeAsync: typeof safeAsync;
88
101
  var $safePromise: typeof safePromise;
102
+ var $retry: typeof retry;
103
+ var $safeRetry: typeof safeRetry;
89
104
  }
90
105
  /**
91
106
  * Create a new {@link Result} with the `Ok` variant. When called without
@@ -129,6 +144,9 @@ export declare function Ok<const T>(val: T): Result<T, never>;
129
144
  */
130
145
  export declare function Err(): Result<never, void>;
131
146
  export declare function Err<const E>(err: E): Result<never, E>;
147
+ /**
148
+ * @TODO
149
+ */
132
150
  declare function resolve<T, E>(result: Retuple<T, E> | PromiseLike<Retuple<T, E>>): ResultAsync<T, E>;
133
151
  /**
134
152
  * Construct a {@link Result} from a value. If the value is neither null or
@@ -224,6 +242,10 @@ declare function nonNullable<const T, E>(value: T, error: () => E): Result<NonNu
224
242
  */
225
243
  declare function truthy<const T>(value: T): Result<Truthy<T>, true>;
226
244
  declare function truthy<const T, E>(value: T, error: () => E): Result<Truthy<T>, E>;
245
+ /**
246
+ * @TODO
247
+ */
248
+ declare function union<U extends ObjectUnionOk<any> | ObjectUnionErr<any>>(union: U): Result<U extends ObjectUnionOk<infer T> ? T : never, U extends ObjectUnionErr<infer E> ? E : never>;
227
249
  /**
228
250
  * Construct a {@link Result} from a synchronous function call. If the function
229
251
  * returns without throwing, the result is `Ok`.
@@ -421,6 +443,15 @@ declare function safeAsync<T, E>(f: () => T | PromiseLike<T>, mapError: (err: un
421
443
  */
422
444
  declare function safePromise<T>(promise: PromiseLike<T>): ResultAsync<T, Error>;
423
445
  declare function safePromise<T, E>(promise: PromiseLike<T>, mapError: (err: unknown) => E): ResultAsync<T, E>;
446
+ /**
447
+ * @TODO
448
+ */
449
+ declare function retry<T, E>(f: () => Retuple<T, E> | PromiseLike<Retuple<T, E>>): ResultRetry<T, E>;
450
+ /**
451
+ * @TODO
452
+ */
453
+ declare function safeRetry<T>(f: () => T | PromiseLike<T>): ResultRetry<T, Error>;
454
+ declare function safeRetry<T, E>(f: () => T | PromiseLike<T>, mapError: (err: unknown) => E): ResultRetry<T, E>;
424
455
  /**
425
456
  * ## RetupleArray
426
457
  *
@@ -934,12 +965,42 @@ declare class ResultAsync<T, E> {
934
965
  */
935
966
  $iter<U>(this: ResultAsync<Iterable<U>, E>): Promise<IterableIterator<U, undefined, unknown>>;
936
967
  }
937
- type Truthy<T> = Exclude<T, false | null | undefined | 0 | 0n | "">;
938
- type OkTuple<T> = [err: undefined, value: T];
939
- type ErrTuple<E> = [err: E, value: undefined];
940
- type ThisOk<T> = OkTuple<T> & Retuple<T, never>;
941
- type ThisErr<E> = ErrTuple<E> & Retuple<never, E>;
942
- type RetupleAwaitable<T, E> = Retuple<T, E> | PromiseLike<Retuple<T, E>>;
968
+ interface ResultRetryMonitor<E> {
969
+ error: E;
970
+ attempt: number;
971
+ abort: () => void;
972
+ }
973
+ /**
974
+ * @TODO
975
+ */
976
+ declare class ResultRetry<T, E> implements PromiseLike<Result<T, E>> {
977
+ #private;
978
+ private static MAX_TIMEOUT;
979
+ private static MAX_RETRY;
980
+ private static zero;
981
+ private static delay;
982
+ private static integer;
983
+ constructor(f: () => RetupleAwaitable<T, E>);
984
+ then<U = Result<T, E>, F = never>(onfulfilled?: ((value: Result<T, E>) => U | PromiseLike<U>) | null | undefined, onrejected?: ((reason: any) => F | PromiseLike<F>) | null | undefined): PromiseLike<U | F>;
985
+ /**
986
+ * @TODO - Capped 100
987
+ */
988
+ $times<N extends number>(this: ResultRetry<T, E>, times: NonZero<N> & NonNegativeOrDecimal<N>): ResultRetry<T, E>;
989
+ /**
990
+ * @TODO - Capped 1 hour
991
+ */
992
+ $delay<N extends number>(this: ResultRetry<T, E>, f: (attempt: number) => NonNegativeOrDecimal<N>): ResultRetry<T, E>;
993
+ $delay<N extends number>(this: ResultRetry<T, E>, ms: NonNegativeOrDecimal<N>): ResultRetry<T, E>;
994
+ /**
995
+ * @TODO
996
+ */
997
+ $monitor(f: (state: ResultRetryMonitor<E>) => void): ResultRetry<T, E>;
998
+ /**
999
+ * @TODO
1000
+ */
1001
+ $async(this: ResultRetry<T, E>): ResultAsync<T, E>;
1002
+ private drain;
1003
+ }
943
1004
  interface Retuple<T, E> extends RetupleArray<T | E | undefined> {
944
1005
  /**
945
1006
  * Returns true when this result is `Ok`. Acts as a type guard.
@@ -1950,3 +2011,21 @@ interface Retuple<T, E> extends RetupleArray<T | E | undefined> {
1950
2011
  */
1951
2012
  $iter<U>(this: Result<Iterable<U>, E>): IterableIterator<U, undefined, unknown>;
1952
2013
  }
2014
+ type OkTuple<T> = [err: undefined, value: T];
2015
+ type ErrTuple<E> = [err: E, value: undefined];
2016
+ type ThisOk<T> = OkTuple<T> & Retuple<T, never>;
2017
+ type ThisErr<E> = ErrTuple<E> & Retuple<never, E>;
2018
+ type RetupleAwaitable<T, E> = Retuple<T, E> | PromiseLike<Retuple<T, E>>;
2019
+ type ObjectUnionOk<T> = {
2020
+ success: true;
2021
+ data: T;
2022
+ error?: never | undefined;
2023
+ };
2024
+ type ObjectUnionErr<E> = {
2025
+ success: false;
2026
+ data?: never | undefined;
2027
+ error: E;
2028
+ };
2029
+ type Truthy<T> = Exclude<T, false | null | undefined | 0 | 0n | "">;
2030
+ type NonZero<N extends number> = N & (`${N}` extends "0" ? never : N);
2031
+ type NonNegativeOrDecimal<N extends number> = N & (`${N}` extends `-${string}` | `${string}.${string}` ? never : N);
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ 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_errorHandler;
13
13
  /**
14
14
  * ## Retuple Unwrap Failed
15
15
  *
@@ -83,6 +83,21 @@ export class RetupleInvalidResultError extends Error {
83
83
  this.value = value;
84
84
  }
85
85
  }
86
+ /**
87
+ * ## Retuple Invalid Union Error
88
+ *
89
+ * This error is thrown when attempting to construct a `Result` from a
90
+ * discriminated union, when the 'success' property is not boolean. In this
91
+ * case, it is impossible to determine whether the result should be `Ok` or
92
+ * `Err`.
93
+ */
94
+ export class RetupleInvalidUnionError extends Error {
95
+ constructor(value) {
96
+ super("Constructing a Result from discriminated union failed, the success " +
97
+ "property must be boolean");
98
+ this.value = value;
99
+ }
100
+ }
86
101
  /**
87
102
  * ## Retuple Array Method Unavailable Error
88
103
  *
@@ -115,9 +130,12 @@ Result.Err = Err;
115
130
  Result.$resolve = resolve;
116
131
  Result.$nonNullable = nonNullable;
117
132
  Result.$truthy = truthy;
133
+ Result.$union = union;
118
134
  Result.$safe = safe;
119
135
  Result.$safeAsync = safeAsync;
120
136
  Result.$safePromise = safePromise;
137
+ Result.$retry = retry;
138
+ Result.$safeRetry = safeRetry;
121
139
  Object.freeze(Result);
122
140
  export function Ok(val) {
123
141
  return new ResultOk(val);
@@ -125,6 +143,9 @@ export function Ok(val) {
125
143
  export function Err(err) {
126
144
  return new ResultErr(err);
127
145
  }
146
+ /**
147
+ * @TODO
148
+ */
128
149
  function resolve(result) {
129
150
  if (result instanceof ResultAsync) {
130
151
  return result;
@@ -148,6 +169,18 @@ function truthy(value, error = mapTrue) {
148
169
  }
149
170
  return Err(error());
150
171
  }
172
+ /**
173
+ * @TODO
174
+ */
175
+ function union(union) {
176
+ if (union.success === true) {
177
+ return Ok(union.data);
178
+ }
179
+ if (union.success === false) {
180
+ return Err(union.error);
181
+ }
182
+ throw new RetupleInvalidUnionError(union);
183
+ }
151
184
  function safe(f, mapError = ensureError) {
152
185
  try {
153
186
  return Ok(f());
@@ -169,6 +202,22 @@ function safeAsync(f, mapError = ensureError) {
169
202
  function safePromise(promise, mapError = ensureError) {
170
203
  return new ResultAsync(promise.then((Ok), async (err) => Err(await mapError(err))));
171
204
  }
205
+ /**
206
+ * @TODO
207
+ */
208
+ function retry(f) {
209
+ return new ResultRetry(f);
210
+ }
211
+ function safeRetry(f, mapError = ensureError) {
212
+ return new ResultRetry(async () => {
213
+ try {
214
+ return Ok(await f());
215
+ }
216
+ catch (err) {
217
+ return Err(mapError(err));
218
+ }
219
+ });
220
+ }
172
221
  /**
173
222
  * ## RetupleArray
174
223
  *
@@ -1069,6 +1118,96 @@ class ResultAsync {
1069
1118
  }
1070
1119
  }
1071
1120
  _ResultAsync_inner = new WeakMap();
1121
+ /**
1122
+ * @TODO
1123
+ */
1124
+ class ResultRetry {
1125
+ static zero() {
1126
+ return 0;
1127
+ }
1128
+ static delay(ms) {
1129
+ return new Promise((resolve) => setTimeout(resolve, Math.min(ms, _a.MAX_TIMEOUT)));
1130
+ }
1131
+ static integer(value) {
1132
+ if (typeof value === "number" && Number.isInteger(value)) {
1133
+ return Math.max(0, value);
1134
+ }
1135
+ return 0;
1136
+ }
1137
+ constructor(f) {
1138
+ _ResultRetry_f.set(this, void 0);
1139
+ _ResultRetry_promise.set(this, void 0);
1140
+ _ResultRetry_times.set(this, 1);
1141
+ _ResultRetry_attempt.set(this, 0);
1142
+ _ResultRetry_aborted.set(this, false);
1143
+ _ResultRetry_abort.set(this, () => (__classPrivateFieldSet(this, _ResultRetry_aborted, true, "f")));
1144
+ _ResultRetry_getDelay.set(this, _a.zero);
1145
+ _ResultRetry_errorHandler.set(this, void 0);
1146
+ __classPrivateFieldSet(this, _ResultRetry_f, f, "f");
1147
+ __classPrivateFieldSet(this, _ResultRetry_promise, this.drain(), "f");
1148
+ }
1149
+ then(onfulfilled, onrejected) {
1150
+ return __classPrivateFieldGet(this, _ResultRetry_promise, "f").then(onfulfilled, onrejected);
1151
+ }
1152
+ /**
1153
+ * @TODO - Capped 100
1154
+ */
1155
+ $times(times) {
1156
+ __classPrivateFieldSet(this, _ResultRetry_times, Math.min(Math.max(1, _a.integer(times)), _a.MAX_RETRY), "f");
1157
+ return this;
1158
+ }
1159
+ $delay(fnOrMs) {
1160
+ if (typeof fnOrMs === "function") {
1161
+ __classPrivateFieldSet(this, _ResultRetry_getDelay, fnOrMs, "f");
1162
+ return this;
1163
+ }
1164
+ const delay = _a.integer(fnOrMs);
1165
+ if (delay > 0) {
1166
+ __classPrivateFieldSet(this, _ResultRetry_getDelay, () => delay, "f");
1167
+ }
1168
+ return this;
1169
+ }
1170
+ /**
1171
+ * @TODO
1172
+ */
1173
+ $monitor(f) {
1174
+ __classPrivateFieldSet(this, _ResultRetry_errorHandler, f, "f");
1175
+ return this;
1176
+ }
1177
+ /**
1178
+ * @TODO
1179
+ */
1180
+ $async() {
1181
+ return new ResultAsync(this);
1182
+ }
1183
+ async drain() {
1184
+ var _b;
1185
+ while (__classPrivateFieldGet(this, _ResultRetry_attempt, "f") < __classPrivateFieldGet(this, _ResultRetry_times, "f")) {
1186
+ const result = await __classPrivateFieldGet(this, _ResultRetry_f, "f").call(this);
1187
+ __classPrivateFieldSet(this, _ResultRetry_attempt, (_b = __classPrivateFieldGet(this, _ResultRetry_attempt, "f"), _b++, _b), "f");
1188
+ if (result.$isOk()) {
1189
+ return result;
1190
+ }
1191
+ if (__classPrivateFieldGet(this, _ResultRetry_errorHandler, "f")) {
1192
+ await __classPrivateFieldGet(this, _ResultRetry_errorHandler, "f").call(this, {
1193
+ error: result[0],
1194
+ attempt: __classPrivateFieldGet(this, _ResultRetry_attempt, "f"),
1195
+ abort: __classPrivateFieldGet(this, _ResultRetry_abort, "f"),
1196
+ });
1197
+ }
1198
+ if (__classPrivateFieldGet(this, _ResultRetry_aborted, "f") || __classPrivateFieldGet(this, _ResultRetry_attempt, "f") === __classPrivateFieldGet(this, _ResultRetry_times, "f")) {
1199
+ return result;
1200
+ }
1201
+ const delay = _a.integer(__classPrivateFieldGet(this, _ResultRetry_getDelay, "f").call(this, __classPrivateFieldGet(this, _ResultRetry_attempt, "f")));
1202
+ if (delay > 0) {
1203
+ await _a.delay(delay);
1204
+ }
1205
+ }
1206
+ }
1207
+ }
1208
+ _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_errorHandler = new WeakMap();
1209
+ ResultRetry.MAX_TIMEOUT = 3600000;
1210
+ ResultRetry.MAX_RETRY = 100;
1072
1211
  function ensureError(err) {
1073
1212
  if (err instanceof Error) {
1074
1213
  return err;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "retuple",
3
- "version": "1.0.0-next.11",
3
+ "version": "1.0.0-next.13",
4
4
  "scripts": {
5
5
  "test": "vitest",
6
6
  "lint": "eslint . --ext .ts -c eslint.config.mjs --fix",