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/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,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 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;
@@ -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 [] ? AppError : RuleReturn<TRules[number]> | AppError<"UNKNOWN">;
23
- type Rule<E extends AppError = AppError> = (err: unknown) => E | null;
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 AppError = AppError> = {
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 AppError = AppError> = RetryOptions<E> & {
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?: AppError;
173
+ lastError?: ResultError;
174
174
  };
175
- type RunResult<T, E extends AppError = AppError> = {
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 `AppError` (or a custom error type `E`)
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 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>>;
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 AppError = AppError> = {
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 AppError ? E : AppError>, {
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 AppError = AppError>(r: RunAllItemResult<T, E>) => r is SuccessResult<T>;
230
- 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> & {
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 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>[]>;
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 AppError = AppError> = RunOptions<T, E> & {
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 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[]>;
259
259
 
260
- declare function createNormalizer<E extends AppError>(rules: Rule<E>[], fallback: (err: unknown) => E): (err: unknown) => E;
261
- declare function defaultFallback(err: unknown): AppError;
262
- 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;
263
263
 
264
264
  declare const rules: {
265
- abort: Rule<AppError<"ABORTED">>;
266
- timeout: Rule<AppError<"TIMEOUT">>;
267
- httpStatus: Rule<AppError<"HTTP">>;
268
- aggregate: Rule<AppError<"UNKNOWN", {
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<AppError<"UNKNOWN">>;
272
- message: Rule<AppError<"UNKNOWN">>;
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 AppError>(mapper: (err: E) => Out): Rule<Out>;
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 CreateRunnerOptions<E extends AppError = AppError> = {
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 AppError> {
318
+ interface Runner<E extends ResultError> {
312
319
  run<T>(fn: () => Promise<T>, options?: RunOptions<T, E>): Promise<RunResult<T, E>>;
313
- all<T>(fns: Array<() => MaybePromise<T>>, options?: RunAllOptions<T, E>): Promise<RunAllItemResult<T, E>[]>;
314
- 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[]>;
315
322
  }
316
- declare function createRunner(opts?: Omit<CreateRunnerOptions<AppError>, "rules">): Runner<AppError>;
317
- declare function createRunner<const TRules extends readonly Rule<any>[]>(opts: {
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 AppError, type AppErrorCode, type BackoffStrategy, type CircuitBreakerOptions, type CreateRunnerOptions, type ErrorResult, type Metrics, type RetryContext, type RetryOptions, type RunAllItemResult, type RunAllOptions, type RunOptions, type RunResult, type SuccessResult, createNormalizer, createRunner, 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,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 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;
@@ -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 [] ? AppError : RuleReturn<TRules[number]> | AppError<"UNKNOWN">;
23
- type Rule<E extends AppError = AppError> = (err: unknown) => E | null;
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 AppError = AppError> = {
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 AppError = AppError> = RetryOptions<E> & {
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?: AppError;
173
+ lastError?: ResultError;
174
174
  };
175
- type RunResult<T, E extends AppError = AppError> = {
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 `AppError` (or a custom error type `E`)
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 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>>;
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 AppError = AppError> = {
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 AppError ? E : AppError>, {
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 AppError = AppError>(r: RunAllItemResult<T, E>) => r is SuccessResult<T>;
230
- 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> & {
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 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>[]>;
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 AppError = AppError> = RunOptions<T, E> & {
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 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[]>;
259
259
 
260
- declare function createNormalizer<E extends AppError>(rules: Rule<E>[], fallback: (err: unknown) => E): (err: unknown) => E;
261
- declare function defaultFallback(err: unknown): AppError;
262
- 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;
263
263
 
264
264
  declare const rules: {
265
- abort: Rule<AppError<"ABORTED">>;
266
- timeout: Rule<AppError<"TIMEOUT">>;
267
- httpStatus: Rule<AppError<"HTTP">>;
268
- aggregate: Rule<AppError<"UNKNOWN", {
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<AppError<"UNKNOWN">>;
272
- message: Rule<AppError<"UNKNOWN">>;
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 AppError>(mapper: (err: E) => Out): Rule<Out>;
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 CreateRunnerOptions<E extends AppError = AppError> = {
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 AppError> {
318
+ interface Runner<E extends ResultError> {
312
319
  run<T>(fn: () => Promise<T>, options?: RunOptions<T, E>): Promise<RunResult<T, E>>;
313
- all<T>(fns: Array<() => MaybePromise<T>>, options?: RunAllOptions<T, E>): Promise<RunAllItemResult<T, E>[]>;
314
- 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[]>;
315
322
  }
316
- declare function createRunner(opts?: Omit<CreateRunnerOptions<AppError>, "rules">): Runner<AppError>;
317
- declare function createRunner<const TRules extends readonly Rule<any>[]>(opts: {
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 AppError, type AppErrorCode, type BackoffStrategy, type CircuitBreakerOptions, type CreateRunnerOptions, type ErrorResult, type Metrics, type RetryContext, type RetryOptions, type RunAllItemResult, type RunAllOptions, type RunOptions, type RunResult, type SuccessResult, createNormalizer, createRunner, 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 O(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=Q(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 Q(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,$=p>0?300:0;if(O(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((w,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(w){b?.error?.("run:onSuccess failed",t(w));}try{a?.();}catch(w){b?.error?.("run:onFinally failed",t(w));}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},w=await Promise.resolve(f(h,l,k));if(d<p&&w){d=h;let c=H(y,d,l,$,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 G=Date.now()-M,L={totalAttempts:d+1,totalRetries:d,totalDuration:G,lastError:l};return b?.error?.("run:error",l),{ok:false,data:null,error:l,metrics:L}}}var V=r=>r.status==="ok";async function v(r,e={}){let{concurrency:t=1/0,mode:u="settle",...n}=e;if(O(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(O(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 X=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,Y=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,Z=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},j=r=>typeof AggregateError<"u"&&r instanceof AggregateError?{code:"UNKNOWN",message:r.message||"Multiple errors occurred",cause:r,meta:{errors:r.errors}}:null,rr=r=>typeof r=="string"?{code:"UNKNOWN",message:r,cause:r}:null,er=r=>typeof r=="object"&&r!==null&&"message"in r&&typeof r.message=="string"?{code:"UNKNOWN",message:r.message,cause:r}:null,tr={abort:X,timeout:Y,httpStatus:Z,aggregate:j,string:rr,message:er};var S=class{constructor(e){this.matcher=e;}toError(e){return t=>this.matcher(t)?e(t):null}},or={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 nr(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)})}}}export{B as createNormalizer,nr as createRunner,N as defaultFallback,or as errorRule,V as isSuccess,tr 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