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 +142 -2
- package/dist/index.d.cts +85 -6
- package/dist/index.d.ts +85 -6
- package/dist/index.js +140 -1
- package/package.json +1 -1
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
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
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
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
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;
|