trybox 0.1.1 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -20
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -34
- package/dist/index.d.ts +42 -34
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MaybePromise as MaybePromise$1 } from 'bun';
|
|
2
2
|
|
|
3
|
-
type
|
|
3
|
+
type ResultErrorCode = "ABORTED" | "NETWORK" | "TIMEOUT" | "VALIDATION" | "HTTP" | "UNKNOWN";
|
|
4
4
|
/**
|
|
5
5
|
* A normalized error shape returned by `run()`.
|
|
6
6
|
*
|
|
@@ -10,7 +10,7 @@ type AppErrorCode = "ABORTED" | "NETWORK" | "TIMEOUT" | "VALIDATION" | "HTTP" |
|
|
|
10
10
|
* - `meta`: Optional payload with extra context (response body, validation fields, etc.).
|
|
11
11
|
* - `cause`: The original thrown value for debugging.
|
|
12
12
|
*/
|
|
13
|
-
type
|
|
13
|
+
type ResultError<Code extends string = ResultErrorCode | (string & {}), Meta = unknown> = {
|
|
14
14
|
code: Code;
|
|
15
15
|
message: string;
|
|
16
16
|
status?: number;
|
|
@@ -19,8 +19,8 @@ type AppError<Code extends string = AppErrorCode | (string & {}), Meta = unknown
|
|
|
19
19
|
};
|
|
20
20
|
type NonNull<T> = T extends null ? never : T;
|
|
21
21
|
type RuleReturn<R> = R extends (err: unknown) => infer Out ? NonNull<Out> : never;
|
|
22
|
-
type InferErrorFromRules<TRules extends readonly Rule<any>[]> = TRules extends readonly [] ?
|
|
23
|
-
type Rule<E extends
|
|
22
|
+
type InferErrorFromRules<TRules extends readonly Rule<any>[]> = TRules extends readonly [] ? ResultError : RuleReturn<TRules[number]> | ResultError<"UNKNOWN">;
|
|
23
|
+
type Rule<E extends ResultError = ResultError> = (err: unknown) => E | null;
|
|
24
24
|
|
|
25
25
|
type RetryDelayFn<E> = (attempt: number, err: E) => number;
|
|
26
26
|
type MaybePromise<T> = T | Promise<T>;
|
|
@@ -40,7 +40,7 @@ type BackoffStrategy = "linear" | "exponential" | "fibonacci" | ((attempt: numbe
|
|
|
40
40
|
/**
|
|
41
41
|
* Retry options for `run`, `runAll` and `runAllOrThrow`.
|
|
42
42
|
*/
|
|
43
|
-
type RetryOptions<E extends
|
|
43
|
+
type RetryOptions<E extends ResultError = ResultError> = {
|
|
44
44
|
/**
|
|
45
45
|
* Number of retries to perform (does not include the initial attempt).
|
|
46
46
|
* @default 0
|
|
@@ -93,7 +93,7 @@ type RetryContext = {
|
|
|
93
93
|
/**
|
|
94
94
|
* Main options for `run` and extended to `runAll`/`runAllOrThrow`.
|
|
95
95
|
*/
|
|
96
|
-
type RunOptions<T, E extends
|
|
96
|
+
type RunOptions<T, E extends ResultError = ResultError> = RetryOptions<E> & {
|
|
97
97
|
/**
|
|
98
98
|
* Normalizes an unknown error value to your type `E`.
|
|
99
99
|
* If not provided, a default normalizer is used.
|
|
@@ -170,9 +170,9 @@ type Metrics = {
|
|
|
170
170
|
totalAttempts: number;
|
|
171
171
|
totalRetries: number;
|
|
172
172
|
totalDuration: number;
|
|
173
|
-
lastError?:
|
|
173
|
+
lastError?: ResultError;
|
|
174
174
|
};
|
|
175
|
-
type RunResult<T, E extends
|
|
175
|
+
type RunResult<T, E extends ResultError = ResultError> = {
|
|
176
176
|
ok: true;
|
|
177
177
|
data: T;
|
|
178
178
|
error: null;
|
|
@@ -187,13 +187,13 @@ type RunResult<T, E extends AppError = AppError> = {
|
|
|
187
187
|
/**
|
|
188
188
|
* Executes an async operation and returns a Result instead of throwing.
|
|
189
189
|
*
|
|
190
|
-
* Errors are normalized into an `
|
|
190
|
+
* Errors are normalized into an `ResultError` (or a custom error type `E`)
|
|
191
191
|
* using the provided `toError` function.
|
|
192
192
|
*
|
|
193
193
|
* This utility is framework-agnostic and works in browsers, Node.js,
|
|
194
194
|
* React effects, and any async context.
|
|
195
195
|
*/
|
|
196
|
-
declare function run<T, E extends
|
|
196
|
+
declare function run<T, E extends ResultError = ResultError>(fn: () => MaybePromise<T>, options?: RunOptions<T, E>): Promise<RunResult<T, E>>;
|
|
197
197
|
|
|
198
198
|
/**
|
|
199
199
|
* Discriminated result per item in `runAllSettled`:
|
|
@@ -201,7 +201,7 @@ declare function run<T, E extends AppError = AppError>(fn: () => MaybePromise<T>
|
|
|
201
201
|
* - "error": failed task with `error`
|
|
202
202
|
* - "skipped": task not executed due to cancellation/fail-fast/concurrency
|
|
203
203
|
*/
|
|
204
|
-
type RunAllItemResult<T, E extends
|
|
204
|
+
type RunAllItemResult<T, E extends ResultError = ResultError> = {
|
|
205
205
|
status: "ok";
|
|
206
206
|
ok: true;
|
|
207
207
|
data: T;
|
|
@@ -222,12 +222,12 @@ type SuccessResult<T> = Extract<RunAllItemResult<T, any>, {
|
|
|
222
222
|
status: "ok";
|
|
223
223
|
}>;
|
|
224
224
|
/** Helper to discriminate error results. */
|
|
225
|
-
type ErrorResult<E> = Extract<RunAllItemResult<any, E extends
|
|
225
|
+
type ErrorResult<E> = Extract<RunAllItemResult<any, E extends ResultError ? E : ResultError>, {
|
|
226
226
|
status: "error";
|
|
227
227
|
}>;
|
|
228
228
|
/** Type guard that detects `status: "ok"` with `data` typing. */
|
|
229
|
-
declare const isSuccess: <T, E extends
|
|
230
|
-
type RunAllOptions<T, E extends
|
|
229
|
+
declare const isSuccess: <T, E extends ResultError = ResultError>(r: RunAllItemResult<T, E>) => r is SuccessResult<T>;
|
|
230
|
+
type RunAllOptions<T, E extends ResultError = ResultError> = RunOptions<T, E> & {
|
|
231
231
|
/**
|
|
232
232
|
* Maximum number of concurrent tasks to run.
|
|
233
233
|
* @default Infinity
|
|
@@ -241,53 +241,60 @@ type RunAllOptions<T, E extends AppError = AppError> = RunOptions<T, E> & {
|
|
|
241
241
|
*/
|
|
242
242
|
mode?: "settle" | "fail-fast";
|
|
243
243
|
};
|
|
244
|
-
declare function runAllSettled<T, E extends
|
|
244
|
+
declare function runAllSettled<T, E extends ResultError = ResultError>(tasks: Array<() => MaybePromise<T>>, options?: RunAllOptions<T, E>): Promise<RunAllItemResult<T, E>[]>;
|
|
245
245
|
|
|
246
246
|
/**
|
|
247
247
|
* Options for `runAll`:
|
|
248
248
|
* - Inherits all options from `RunOptions`
|
|
249
249
|
* - `concurrency`: limit of simultaneous tasks; if one fails, it throws
|
|
250
250
|
*/
|
|
251
|
-
type RunAllOrThrowOptions<T, E extends
|
|
251
|
+
type RunAllOrThrowOptions<T, E extends ResultError = ResultError> = RunOptions<T, E> & {
|
|
252
252
|
/**
|
|
253
253
|
* Maximum number of concurrent tasks to run.
|
|
254
254
|
* @default Infinity
|
|
255
255
|
*/
|
|
256
256
|
concurrency?: number;
|
|
257
257
|
};
|
|
258
|
-
declare function runAll<T, E extends
|
|
258
|
+
declare function runAll<T, E extends ResultError = ResultError>(tasks: Array<() => MaybePromise$1<T>>, options?: RunAllOrThrowOptions<T, E>): Promise<T[]>;
|
|
259
259
|
|
|
260
|
-
declare function createNormalizer<E extends
|
|
261
|
-
declare function defaultFallback(err: unknown):
|
|
262
|
-
declare function
|
|
260
|
+
declare function createNormalizer<E extends ResultError>(rules: Rule<E>[], fallback: (err: unknown) => E): (err: unknown) => E;
|
|
261
|
+
declare function defaultFallback(err: unknown): ResultError;
|
|
262
|
+
declare function toResultError(err: unknown): ResultError;
|
|
263
263
|
|
|
264
264
|
declare const rules: {
|
|
265
|
-
abort: Rule<
|
|
266
|
-
timeout: Rule<
|
|
267
|
-
httpStatus: Rule<
|
|
268
|
-
aggregate: Rule<
|
|
265
|
+
abort: Rule<ResultError<"ABORTED">>;
|
|
266
|
+
timeout: Rule<ResultError<"TIMEOUT">>;
|
|
267
|
+
httpStatus: Rule<ResultError<"HTTP">>;
|
|
268
|
+
aggregate: Rule<ResultError<"UNKNOWN", {
|
|
269
269
|
errors: unknown[];
|
|
270
270
|
}>>;
|
|
271
|
-
string: Rule<
|
|
272
|
-
message: Rule<
|
|
271
|
+
string: Rule<ResultError<"UNKNOWN">>;
|
|
272
|
+
message: Rule<ResultError<"UNKNOWN">>;
|
|
273
273
|
};
|
|
274
274
|
|
|
275
275
|
declare class ErrorRuleBuilder<E> {
|
|
276
276
|
private readonly matcher;
|
|
277
277
|
constructor(matcher: (err: unknown) => err is E);
|
|
278
|
-
toError<const Out extends
|
|
278
|
+
toError<const Out extends ResultError>(mapper: (err: E) => Out): Rule<Out>;
|
|
279
279
|
}
|
|
280
280
|
declare const errorRule: {
|
|
281
281
|
instance<E extends new (...args: any[]) => unknown>(ctor: E): ErrorRuleBuilder<InstanceType<E>>;
|
|
282
282
|
when<E = unknown>(predicate: (err: unknown) => err is E): ErrorRuleBuilder<E>;
|
|
283
283
|
};
|
|
284
284
|
|
|
285
|
-
type
|
|
285
|
+
type RulesMode = "extend" | "replace";
|
|
286
|
+
type CreateRunnerOptions<E extends ResultError = ResultError> = {
|
|
286
287
|
/**
|
|
287
288
|
* Custom matchers to use for normalizing errors.
|
|
288
289
|
* If not provided, the default matchers are used.
|
|
289
290
|
*/
|
|
290
291
|
rules?: Rule<E>[];
|
|
292
|
+
/**
|
|
293
|
+
* How to treat provided rules in relation to default rules.
|
|
294
|
+
* - "extend": Use default rules after custom rules (default).
|
|
295
|
+
* - "replace": Use only custom rules (and fallback).
|
|
296
|
+
*/
|
|
297
|
+
rulesMode?: RulesMode;
|
|
291
298
|
/**
|
|
292
299
|
* Custom fallback function to use for normalizing errors.
|
|
293
300
|
* If not provided, the default fallback is used.
|
|
@@ -308,14 +315,15 @@ type CreateRunnerOptions<E extends AppError = AppError> = {
|
|
|
308
315
|
*/
|
|
309
316
|
circuitBreaker?: CircuitBreakerOptions;
|
|
310
317
|
};
|
|
311
|
-
interface Runner<E extends
|
|
318
|
+
interface Runner<E extends ResultError> {
|
|
312
319
|
run<T>(fn: () => Promise<T>, options?: RunOptions<T, E>): Promise<RunResult<T, E>>;
|
|
313
|
-
|
|
314
|
-
|
|
320
|
+
allSettled<T>(fns: Array<() => MaybePromise<T>>, options?: RunAllOptions<T, E>): Promise<RunAllItemResult<T, E>[]>;
|
|
321
|
+
all<T>(fns: Array<() => MaybePromise<T>>, options?: RunOptions<T, E>): Promise<T[]>;
|
|
315
322
|
}
|
|
316
|
-
|
|
317
|
-
declare function
|
|
323
|
+
|
|
324
|
+
declare function trybox(options?: Omit<CreateRunnerOptions<ResultError>, "rules">): Runner<ResultError>;
|
|
325
|
+
declare function trybox<const TRules extends readonly Rule<any>[]>(options: {
|
|
318
326
|
rules: TRules;
|
|
319
327
|
} & Omit<CreateRunnerOptions<InferErrorFromRules<TRules>>, "rules">): Runner<InferErrorFromRules<TRules>>;
|
|
320
328
|
|
|
321
|
-
export { type
|
|
329
|
+
export { type BackoffStrategy, type CircuitBreakerOptions, type ErrorResult, type Metrics, type ResultError, type ResultErrorCode, type RetryContext, type RetryOptions, type RunAllItemResult, type RunAllOptions, type RunOptions, type RunResult, type SuccessResult, createNormalizer, trybox as default, defaultFallback, errorRule, isSuccess, rules, run, runAll, runAllSettled, toResultError };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MaybePromise as MaybePromise$1 } from 'bun';
|
|
2
2
|
|
|
3
|
-
type
|
|
3
|
+
type ResultErrorCode = "ABORTED" | "NETWORK" | "TIMEOUT" | "VALIDATION" | "HTTP" | "UNKNOWN";
|
|
4
4
|
/**
|
|
5
5
|
* A normalized error shape returned by `run()`.
|
|
6
6
|
*
|
|
@@ -10,7 +10,7 @@ type AppErrorCode = "ABORTED" | "NETWORK" | "TIMEOUT" | "VALIDATION" | "HTTP" |
|
|
|
10
10
|
* - `meta`: Optional payload with extra context (response body, validation fields, etc.).
|
|
11
11
|
* - `cause`: The original thrown value for debugging.
|
|
12
12
|
*/
|
|
13
|
-
type
|
|
13
|
+
type ResultError<Code extends string = ResultErrorCode | (string & {}), Meta = unknown> = {
|
|
14
14
|
code: Code;
|
|
15
15
|
message: string;
|
|
16
16
|
status?: number;
|
|
@@ -19,8 +19,8 @@ type AppError<Code extends string = AppErrorCode | (string & {}), Meta = unknown
|
|
|
19
19
|
};
|
|
20
20
|
type NonNull<T> = T extends null ? never : T;
|
|
21
21
|
type RuleReturn<R> = R extends (err: unknown) => infer Out ? NonNull<Out> : never;
|
|
22
|
-
type InferErrorFromRules<TRules extends readonly Rule<any>[]> = TRules extends readonly [] ?
|
|
23
|
-
type Rule<E extends
|
|
22
|
+
type InferErrorFromRules<TRules extends readonly Rule<any>[]> = TRules extends readonly [] ? ResultError : RuleReturn<TRules[number]> | ResultError<"UNKNOWN">;
|
|
23
|
+
type Rule<E extends ResultError = ResultError> = (err: unknown) => E | null;
|
|
24
24
|
|
|
25
25
|
type RetryDelayFn<E> = (attempt: number, err: E) => number;
|
|
26
26
|
type MaybePromise<T> = T | Promise<T>;
|
|
@@ -40,7 +40,7 @@ type BackoffStrategy = "linear" | "exponential" | "fibonacci" | ((attempt: numbe
|
|
|
40
40
|
/**
|
|
41
41
|
* Retry options for `run`, `runAll` and `runAllOrThrow`.
|
|
42
42
|
*/
|
|
43
|
-
type RetryOptions<E extends
|
|
43
|
+
type RetryOptions<E extends ResultError = ResultError> = {
|
|
44
44
|
/**
|
|
45
45
|
* Number of retries to perform (does not include the initial attempt).
|
|
46
46
|
* @default 0
|
|
@@ -93,7 +93,7 @@ type RetryContext = {
|
|
|
93
93
|
/**
|
|
94
94
|
* Main options for `run` and extended to `runAll`/`runAllOrThrow`.
|
|
95
95
|
*/
|
|
96
|
-
type RunOptions<T, E extends
|
|
96
|
+
type RunOptions<T, E extends ResultError = ResultError> = RetryOptions<E> & {
|
|
97
97
|
/**
|
|
98
98
|
* Normalizes an unknown error value to your type `E`.
|
|
99
99
|
* If not provided, a default normalizer is used.
|
|
@@ -170,9 +170,9 @@ type Metrics = {
|
|
|
170
170
|
totalAttempts: number;
|
|
171
171
|
totalRetries: number;
|
|
172
172
|
totalDuration: number;
|
|
173
|
-
lastError?:
|
|
173
|
+
lastError?: ResultError;
|
|
174
174
|
};
|
|
175
|
-
type RunResult<T, E extends
|
|
175
|
+
type RunResult<T, E extends ResultError = ResultError> = {
|
|
176
176
|
ok: true;
|
|
177
177
|
data: T;
|
|
178
178
|
error: null;
|
|
@@ -187,13 +187,13 @@ type RunResult<T, E extends AppError = AppError> = {
|
|
|
187
187
|
/**
|
|
188
188
|
* Executes an async operation and returns a Result instead of throwing.
|
|
189
189
|
*
|
|
190
|
-
* Errors are normalized into an `
|
|
190
|
+
* Errors are normalized into an `ResultError` (or a custom error type `E`)
|
|
191
191
|
* using the provided `toError` function.
|
|
192
192
|
*
|
|
193
193
|
* This utility is framework-agnostic and works in browsers, Node.js,
|
|
194
194
|
* React effects, and any async context.
|
|
195
195
|
*/
|
|
196
|
-
declare function run<T, E extends
|
|
196
|
+
declare function run<T, E extends ResultError = ResultError>(fn: () => MaybePromise<T>, options?: RunOptions<T, E>): Promise<RunResult<T, E>>;
|
|
197
197
|
|
|
198
198
|
/**
|
|
199
199
|
* Discriminated result per item in `runAllSettled`:
|
|
@@ -201,7 +201,7 @@ declare function run<T, E extends AppError = AppError>(fn: () => MaybePromise<T>
|
|
|
201
201
|
* - "error": failed task with `error`
|
|
202
202
|
* - "skipped": task not executed due to cancellation/fail-fast/concurrency
|
|
203
203
|
*/
|
|
204
|
-
type RunAllItemResult<T, E extends
|
|
204
|
+
type RunAllItemResult<T, E extends ResultError = ResultError> = {
|
|
205
205
|
status: "ok";
|
|
206
206
|
ok: true;
|
|
207
207
|
data: T;
|
|
@@ -222,12 +222,12 @@ type SuccessResult<T> = Extract<RunAllItemResult<T, any>, {
|
|
|
222
222
|
status: "ok";
|
|
223
223
|
}>;
|
|
224
224
|
/** Helper to discriminate error results. */
|
|
225
|
-
type ErrorResult<E> = Extract<RunAllItemResult<any, E extends
|
|
225
|
+
type ErrorResult<E> = Extract<RunAllItemResult<any, E extends ResultError ? E : ResultError>, {
|
|
226
226
|
status: "error";
|
|
227
227
|
}>;
|
|
228
228
|
/** Type guard that detects `status: "ok"` with `data` typing. */
|
|
229
|
-
declare const isSuccess: <T, E extends
|
|
230
|
-
type RunAllOptions<T, E extends
|
|
229
|
+
declare const isSuccess: <T, E extends ResultError = ResultError>(r: RunAllItemResult<T, E>) => r is SuccessResult<T>;
|
|
230
|
+
type RunAllOptions<T, E extends ResultError = ResultError> = RunOptions<T, E> & {
|
|
231
231
|
/**
|
|
232
232
|
* Maximum number of concurrent tasks to run.
|
|
233
233
|
* @default Infinity
|
|
@@ -241,53 +241,60 @@ type RunAllOptions<T, E extends AppError = AppError> = RunOptions<T, E> & {
|
|
|
241
241
|
*/
|
|
242
242
|
mode?: "settle" | "fail-fast";
|
|
243
243
|
};
|
|
244
|
-
declare function runAllSettled<T, E extends
|
|
244
|
+
declare function runAllSettled<T, E extends ResultError = ResultError>(tasks: Array<() => MaybePromise<T>>, options?: RunAllOptions<T, E>): Promise<RunAllItemResult<T, E>[]>;
|
|
245
245
|
|
|
246
246
|
/**
|
|
247
247
|
* Options for `runAll`:
|
|
248
248
|
* - Inherits all options from `RunOptions`
|
|
249
249
|
* - `concurrency`: limit of simultaneous tasks; if one fails, it throws
|
|
250
250
|
*/
|
|
251
|
-
type RunAllOrThrowOptions<T, E extends
|
|
251
|
+
type RunAllOrThrowOptions<T, E extends ResultError = ResultError> = RunOptions<T, E> & {
|
|
252
252
|
/**
|
|
253
253
|
* Maximum number of concurrent tasks to run.
|
|
254
254
|
* @default Infinity
|
|
255
255
|
*/
|
|
256
256
|
concurrency?: number;
|
|
257
257
|
};
|
|
258
|
-
declare function runAll<T, E extends
|
|
258
|
+
declare function runAll<T, E extends ResultError = ResultError>(tasks: Array<() => MaybePromise$1<T>>, options?: RunAllOrThrowOptions<T, E>): Promise<T[]>;
|
|
259
259
|
|
|
260
|
-
declare function createNormalizer<E extends
|
|
261
|
-
declare function defaultFallback(err: unknown):
|
|
262
|
-
declare function
|
|
260
|
+
declare function createNormalizer<E extends ResultError>(rules: Rule<E>[], fallback: (err: unknown) => E): (err: unknown) => E;
|
|
261
|
+
declare function defaultFallback(err: unknown): ResultError;
|
|
262
|
+
declare function toResultError(err: unknown): ResultError;
|
|
263
263
|
|
|
264
264
|
declare const rules: {
|
|
265
|
-
abort: Rule<
|
|
266
|
-
timeout: Rule<
|
|
267
|
-
httpStatus: Rule<
|
|
268
|
-
aggregate: Rule<
|
|
265
|
+
abort: Rule<ResultError<"ABORTED">>;
|
|
266
|
+
timeout: Rule<ResultError<"TIMEOUT">>;
|
|
267
|
+
httpStatus: Rule<ResultError<"HTTP">>;
|
|
268
|
+
aggregate: Rule<ResultError<"UNKNOWN", {
|
|
269
269
|
errors: unknown[];
|
|
270
270
|
}>>;
|
|
271
|
-
string: Rule<
|
|
272
|
-
message: Rule<
|
|
271
|
+
string: Rule<ResultError<"UNKNOWN">>;
|
|
272
|
+
message: Rule<ResultError<"UNKNOWN">>;
|
|
273
273
|
};
|
|
274
274
|
|
|
275
275
|
declare class ErrorRuleBuilder<E> {
|
|
276
276
|
private readonly matcher;
|
|
277
277
|
constructor(matcher: (err: unknown) => err is E);
|
|
278
|
-
toError<const Out extends
|
|
278
|
+
toError<const Out extends ResultError>(mapper: (err: E) => Out): Rule<Out>;
|
|
279
279
|
}
|
|
280
280
|
declare const errorRule: {
|
|
281
281
|
instance<E extends new (...args: any[]) => unknown>(ctor: E): ErrorRuleBuilder<InstanceType<E>>;
|
|
282
282
|
when<E = unknown>(predicate: (err: unknown) => err is E): ErrorRuleBuilder<E>;
|
|
283
283
|
};
|
|
284
284
|
|
|
285
|
-
type
|
|
285
|
+
type RulesMode = "extend" | "replace";
|
|
286
|
+
type CreateRunnerOptions<E extends ResultError = ResultError> = {
|
|
286
287
|
/**
|
|
287
288
|
* Custom matchers to use for normalizing errors.
|
|
288
289
|
* If not provided, the default matchers are used.
|
|
289
290
|
*/
|
|
290
291
|
rules?: Rule<E>[];
|
|
292
|
+
/**
|
|
293
|
+
* How to treat provided rules in relation to default rules.
|
|
294
|
+
* - "extend": Use default rules after custom rules (default).
|
|
295
|
+
* - "replace": Use only custom rules (and fallback).
|
|
296
|
+
*/
|
|
297
|
+
rulesMode?: RulesMode;
|
|
291
298
|
/**
|
|
292
299
|
* Custom fallback function to use for normalizing errors.
|
|
293
300
|
* If not provided, the default fallback is used.
|
|
@@ -308,14 +315,15 @@ type CreateRunnerOptions<E extends AppError = AppError> = {
|
|
|
308
315
|
*/
|
|
309
316
|
circuitBreaker?: CircuitBreakerOptions;
|
|
310
317
|
};
|
|
311
|
-
interface Runner<E extends
|
|
318
|
+
interface Runner<E extends ResultError> {
|
|
312
319
|
run<T>(fn: () => Promise<T>, options?: RunOptions<T, E>): Promise<RunResult<T, E>>;
|
|
313
|
-
|
|
314
|
-
|
|
320
|
+
allSettled<T>(fns: Array<() => MaybePromise<T>>, options?: RunAllOptions<T, E>): Promise<RunAllItemResult<T, E>[]>;
|
|
321
|
+
all<T>(fns: Array<() => MaybePromise<T>>, options?: RunOptions<T, E>): Promise<T[]>;
|
|
315
322
|
}
|
|
316
|
-
|
|
317
|
-
declare function
|
|
323
|
+
|
|
324
|
+
declare function trybox(options?: Omit<CreateRunnerOptions<ResultError>, "rules">): Runner<ResultError>;
|
|
325
|
+
declare function trybox<const TRules extends readonly Rule<any>[]>(options: {
|
|
318
326
|
rules: TRules;
|
|
319
327
|
} & Omit<CreateRunnerOptions<InferErrorFromRules<TRules>>, "rules">): Runner<InferErrorFromRules<TRules>>;
|
|
320
328
|
|
|
321
|
-
export { type
|
|
329
|
+
export { type BackoffStrategy, type CircuitBreakerOptions, type ErrorResult, type Metrics, type ResultError, type ResultErrorCode, type RetryContext, type RetryOptions, type RunAllItemResult, type RunAllOptions, type RunOptions, type RunResult, type SuccessResult, createNormalizer, trybox as default, defaultFallback, errorRule, isSuccess, rules, run, runAll, runAllSettled, toResultError };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function
|
|
1
|
+
function C(r,e){return t=>{for(let n of r){let u=n(t);if(u)return u}return e(t)}}function S(r){return r instanceof Error?{code:r.name==="TypeError"?"NETWORK":"UNKNOWN",message:r.message||"Something went wrong",cause:r}:{code:"UNKNOWN",message:"Something went wrong",cause:r}}function P(r){return r instanceof DOMException&&r.name==="AbortError"?{code:"ABORTED",message:"Request cancelled",cause:r}:r instanceof DOMException&&r.name==="TimeoutError"?{code:"TIMEOUT",message:"Request timed out",cause:r}:S(r)}function k(r){if(r.retries!=null&&r.retries<0)throw new Error("retries must be >= 0");if(r.timeout!=null&&r.timeout<=0)throw new Error("timeout must be > 0");if(r.maxDelay!=null&&r.maxDelay<0)throw new Error("maxDelay must be >= 0");let e=r.circuitBreaker;if(e){if(e.failureThreshold<1)throw new Error("failureThreshold must be >= 1");if(e.resetTimeout<=0)throw new Error("resetTimeout must be > 0");if(e.halfOpenRequests!=null&&e.halfOpenRequests<1)throw new Error("halfOpenRequests must be >= 1")}}var H=r=>new Promise(e=>setTimeout(e,r));function L(r,e,t){return Math.max(e,Math.min(t,r))}function _(r,e,t,n,u,l){let s=typeof r=="function"?r(e,t):typeof r=="number"?r:n,E=X(u??"linear",s,e),a=l!=null?L(E,0,l):E;return Number.isFinite(a)?a:0}function $(r,e){if(r<=0||!e)return r;let t=typeof e=="object"&&e.rng?e.rng:Math.random,n=typeof e=="number"?e:e===true?.5:typeof e=="object"&&e.ratio!=null?e.ratio:.5,u=L(n,0,1);return (typeof e=="object"&&e.mode?e.mode:"full")==="equal"?r*(1-u)+t()*r*u:r+t()*r*u}function X(r,e,t){if(typeof r=="function"){let l=r(t);return l>=0?l:0}let n=e>=0?e:0,u=t>=1?t:1;if(r==="linear")return n;if(r==="exponential")return n*Math.pow(2,u-1);if(r==="fibonacci"){if(u<=2)return n;let l=1,s=1;for(let E=3;E<=u;E++){let a=l+s;l=s,s=a;}return n*s}return n}async function w(r,e={}){let{toError:t=P,mapError:n,onError:u,onSuccess:l,onFinally:s,ignoreAbort:E=true,retries:a=0,retryDelay:g,shouldRetry:R=()=>true,jitter:d={ratio:.5,mode:"full"},backoffStrategy:o,maxDelay:c,timeout:f,signal:i,onRetry:h,logger:y,onAbort:T}=e,O=a>0?300:0;if(k(e),i?.aborted)try{T?.(i);}finally{let x=t(new DOMException("Aborted","AbortError")),m=n?n(x):x;return E||u?.(m),s?.(),{ok:false,data:null,error:m,metrics:{totalAttempts:0,totalRetries:0,totalDuration:0,lastError:m}}}let I=Date.now(),b=0,W;for(;;)try{let x=null,m=f&&f>0?new Promise((A,J)=>{x=setTimeout(()=>J(new DOMException("Timeout","TimeoutError")),f);}):null,v=await(m?Promise.race([r(),m]):r());x&&clearTimeout(x);try{l?.(v);}catch(A){y?.error?.("run:onSuccess failed",t(A));}try{s?.();}catch(A){y?.error?.("run:onFinally failed",t(A));}let M=Date.now()-I,D={totalAttempts:b+1,totalRetries:b,totalDuration:M,lastError:W};return y?.debug?.("run:success",{attempts:D.totalAttempts,duration:D.totalDuration}),{ok:!0,data:v,error:null,metrics:D}}catch(x){let m=t(x);if(n&&(m=n(m)),m?.code==="ABORTED"||x instanceof DOMException&&x.name==="AbortError"||i?.aborted)try{if(i)try{T?.(i);}catch(p){y?.error?.("run:onAbort failed",t(p));}}finally{if(!E)try{u?.(m);}catch(B){y?.error?.("run:onError failed",t(B));}try{s?.();}catch(B){y?.error?.("run:onFinally failed",t(B));}let p=Date.now()-I,z={totalAttempts:b,totalRetries:b,totalDuration:p,lastError:m};return y?.debug?.("run:aborted",{attempt:b,duration:z.totalDuration}),{ok:false,data:null,error:m,metrics:z}}W=m;let M=b+1,D={totalAttempts:M,elapsedTime:Date.now()-I},A=await Promise.resolve(R(M,m,D));if(b<a&&A){b=M;let p=_(g,b,m,O,o,c);(!Number.isFinite(p)||p<0)&&(p=0),p=$(p,d),h?.(b,m,p),y?.debug?.("run:retry",{attempt:b,delay:p}),p>0&&await H(p);continue}try{u?.(m);}catch(p){y?.error?.("run:onError failed",t(p));}try{s?.();}catch(p){y?.error?.("run:onFinally failed",t(p));}let Q=Date.now()-I,V={totalAttempts:b+1,totalRetries:b,totalDuration:Q,lastError:m};return y?.error?.("run:error",m),{ok:false,data:null,error:m,metrics:V}}}var Y=r=>r.status==="ok";async function q(r,e={}){let{concurrency:t=1/0,mode:n="settle",...u}=e;if(k(u),r.length===0)return [];let l=Number.isFinite(t)?Math.max(1,Math.floor(t)):1/0,s=new Array(r.length),E=0,a=false,g=(o,c)=>{s[o]=c.ok?{status:"ok",ok:true,data:c.data,error:null}:{status:"error",ok:false,data:null,error:c.error};},R=()=>{for(let o=0;o<r.length;o++)s[o]||(s[o]={status:"skipped",ok:false,data:null,error:null});};if(l>=r.length)return (await Promise.all(r.map(c=>w(c,u)))).forEach((c,f)=>{g(f,c);}),s;let d=async()=>{for(;;){if(a)return;let o=E++;if(o>=r.length)return;let c=r[o];if(!c)continue;let f=await w(c,u);if(g(o,f),!f.ok&&n==="fail-fast"){a=true;return}}};return await Promise.all(Array.from({length:Math.min(l,r.length)},()=>d())),R(),s}async function U(r,e={}){let{concurrency:t=1/0,...n}=e;if(k(n),r.length===0)return [];let u=Number.isFinite(t)?Math.max(1,Math.floor(t)):1/0,l=new Array(r.length);if(u>=r.length)return await Promise.all(r.map(async(R,d)=>{let o=await w(R,n);if(!o.ok)throw o.error;l[d]=o.data;})),l;let s=0,E=false,a=null,g=async()=>{for(;;){if(E)return;let R=s++;if(R>=r.length)return;let d=r[R];if(!d)continue;let o=await w(d,n);if(!o.ok){a??(a=o.error),E=true;return}l[R]=o.data;}};if(await Promise.all(Array.from({length:Math.min(u,r.length)},()=>g())),a)throw a;return l}var Z=r=>r instanceof DOMException&&r.name==="AbortError"?{code:"ABORTED",message:"Request cancelled",cause:r}:r instanceof Error&&r.name==="AbortError"?{code:"ABORTED",message:r.message||"Request cancelled",cause:r}:null,j=r=>r instanceof DOMException&&r.name==="TimeoutError"?{code:"TIMEOUT",message:"Request timed out",cause:r}:r instanceof Error&&r.name==="TimeoutError"?{code:"TIMEOUT",message:r.message||"Request timed out",cause:r}:null,rr=r=>{if(typeof r=="object"&&r!==null){let e=r,t=e.status??e.statusCode;if(typeof t=="number")return {code:"HTTP",message:typeof e.message=="string"?e.message:`HTTP Error ${t}`,status:t,cause:r}}return null},er=r=>typeof AggregateError<"u"&&r instanceof AggregateError?{code:"UNKNOWN",message:r.message||"Multiple errors occurred",cause:r,meta:{errors:r.errors}}:null,tr=r=>typeof r=="string"?{code:"UNKNOWN",message:r,cause:r}:null,or=r=>typeof r=="object"&&r!==null&&"message"in r&&typeof r.message=="string"?{code:"UNKNOWN",message:r.message,cause:r}:null,K={abort:Z,timeout:j,httpStatus:rr,aggregate:er,string:tr,message:or};var F=class{constructor(e){this.matcher=e;}toError(e){return t=>this.matcher(t)?e(t):null}},nr={instance(r){return new F(e=>e instanceof r)},when(r){return new F(r)}};var N=(r,e)=>t=>e?e(r?r(t):t):r?r(t):t;function G(r={}){let{rules:e=[],rulesMode:t="extend",fallback:n=f=>S(f),toError:u,ignoreAbort:l=true,mapError:s,circuitBreaker:E}=r,a=[],g=Object.values(K);e.length>0?t==="extend"?a=[...e,...g]:a=[...e]:t==="extend"?a=g:a=[];let R=u??(a.length>0?C(a,n):P),d=0,o=null,c=null;return {run(f,i={}){let h=i.circuitBreaker??E,y=Date.now();if(h){if(o&&y<o){let T=R(new Error("Circuit open")),O=N(s,i.mapError)(T);return i.onError?.(O),i.onFinally?.(),Promise.resolve({ok:false,data:null,error:O,metrics:{totalAttempts:0,totalRetries:0,totalDuration:0,lastError:O}})}if(o&&y>=o&&(o=null,d=0,c=h.halfOpenRequests??1),c!=null)if(c<=0){let T=R(new Error("Circuit half-open limit")),O=N(s,i.mapError)(T);return i.onError?.(O),i.onFinally?.(),Promise.resolve({ok:false,data:null,error:O,metrics:{totalAttempts:0,totalRetries:0,totalDuration:0,lastError:O}})}else c--;}return w(f,{toError:R,ignoreAbort:l,...i,mapError:N(s,i.mapError)}).then(T=>(h&&(T.ok?(d=0,o=null,c=null):(d++,d>=h.failureThreshold&&(o=Date.now()+h.resetTimeout,c=null))),T))},allSettled(f,i={}){return q(f,{toError:R,ignoreAbort:l,...i,mapError:N(s,i.mapError)})},all(f,i={}){return U(f,{toError:R,ignoreAbort:l,...i,mapError:N(s,i.mapError)})}}}function ur(r={}){return G(r)}export{C as createNormalizer,ur as default,S as defaultFallback,nr as errorRule,Y as isSuccess,K as rules,w as run,U as runAll,q as runAllSettled,P as toResultError};//# sourceMappingURL=index.js.map
|
|
2
2
|
//# sourceMappingURL=index.js.map
|