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