runtry 0.8.2 → 0.9.0

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 CHANGED
@@ -4,7 +4,7 @@ Run async functions and return a typed `Result` **instead of throwing**.
4
4
 
5
5
  - ✅ No repetitive `try/catch` in UI code
6
6
  - ✅ Typed success/error handling
7
- - ✅ Pluggable error normalization (matchers / adapters)
7
+ - ✅ Pluggable error normalization (rules)
8
8
  - ✅ **Automatic Retries** with backoff & jitter
9
9
  - ✅ **Concurrency control** with `runAll`
10
10
 
@@ -35,176 +35,118 @@ const result = await run(async () => {
35
35
  if (result.ok) {
36
36
  console.log("data:", result.data);
37
37
  } else {
38
- console.error("error:", result.error.code, result.error.message);
38
+ console.log("error:", result.error.code); // "UNKNOWN" | "ABORTED" | ...
39
39
  }
40
40
  ```
41
41
 
42
42
  ---
43
43
 
44
- ## API
44
+ ## `createRunner()` (Recommended)
45
45
 
46
- ### `run(fn, options?)`
46
+ Define your error rules once and reuse them. Types are inferred automatically!
47
47
 
48
48
  ```ts
49
- import type { AppError, RunOptions, RunResult } from "runtry";
49
+ import { createRunner, rules, errorRule } from "runtry";
50
+ import { ZodError } from "zod";
51
+ import { AxiosError } from "axios";
50
52
 
51
- declare function run<T, E extends AppError = AppError>(
52
- fn: () => Promise<T>,
53
- options?: RunOptions<T, E>
54
- ): Promise<RunResult<T, E>>;
53
+ const runner = createRunner({
54
+ rules: [
55
+ // Core rules (optional)
56
+ rules.abort(), // code: "ABORTED"
57
+ rules.timeout(), // code: "TIMEOUT"
58
+
59
+ // Custom rules (type inferred!)
60
+ errorRule.instance(ZodError).toError((e) => ({
61
+ code: "VALIDATION_ERROR", // Literal type "VALIDATION_ERROR"
62
+ message: "Validation failed",
63
+ meta: { issues: e.issues },
64
+ })),
65
+
66
+ errorRule.instance(AxiosError).toError((e) => ({
67
+ code: "HTTP_ERROR",
68
+ message: e.message,
69
+ status: e.response?.status,
70
+ })),
71
+ ],
72
+ });
73
+
74
+ // Now use it everywhere
75
+ const result = await runner.run(fetchUser);
76
+
77
+ if (!result.ok) {
78
+ // ⭐️ Strict typing based on your rules!
79
+ // error.code is "ABORTED" | "TIMEOUT" | "VALIDATION_ERROR" | "HTTP_ERROR" | "UNKNOWN"
80
+
81
+ if (result.error.code === "VALIDATION_ERROR") {
82
+ console.log(result.error.meta.issues); // Typed!
83
+ }
84
+ }
55
85
  ```
56
86
 
57
- #### Options
87
+ ---
58
88
 
59
- - `toError`: Custom error normalizer.
60
- - `onError`: Callback for final failure.
61
- - `onSuccess`: Callback for success.
62
- - `onFinally`: Callback after completion (success or fail).
63
- - `ignoreAbort`: Don't trigger onError for Abort/Cancellation (default: true).
89
+ ## API
64
90
 
65
- #### Retries
91
+ ### `run(fn, options?)`
66
92
 
67
- You can configure automatic retries for failed operations:
93
+ Executes a single async function.
68
94
 
69
95
  ```ts
70
- await run(fetchData, {
96
+ await runner.run(fn, {
71
97
  retries: 3,
72
- retryDelay: (attempt, err) => attempt * 1000,
73
- jitter: { ratio: 0.5, mode: "full" }, // adds randomization to delay
74
- shouldRetry: (attempt, err) => err.status === 503, // optional filter
98
+ retryDelay: (attempt) => attempt * 1000,
99
+ onError: (err) => toast.error(err.message),
100
+ onSuccess: (data) => console.log(data),
75
101
  });
76
102
  ```
77
103
 
78
- ---
79
-
80
104
  ### `runAll(tasks, options?)`
81
105
 
82
- Executes multiple tasks with **concurrency control**.
106
+ Executes multiple tasks with concurrency control.
83
107
 
84
108
  ```ts
85
- import { runAll } from "runtry";
86
-
87
109
  const tasks = [
88
110
  () => fetch("/api/1"),
89
111
  () => fetch("/api/2"),
90
112
  () => fetch("/api/3"),
91
113
  ];
92
114
 
93
- // Run max 2 at a time
94
- const results = await runAll(tasks, {
115
+ // Run max 2 at a time, stop if any fails
116
+ const results = await runner.all(tasks, {
95
117
  concurrency: 2,
96
- onSettled: (res, index) => console.log(`Task ${index} done`),
97
- retries: 2, // Inherits all run() options including retries!
98
- });
99
- ```
100
-
101
- ---
102
-
103
- ## Normalizing errors (matchers)
104
-
105
- `runtry` can normalize unknown thrown values (`unknown`) into a consistent `AppError` shape.
106
-
107
- ### 1) Create matchers (adapters)
108
-
109
- ```ts
110
- import {
111
- createNormalizer,
112
- abortMatcher,
113
- matchInstance,
114
- defaultFallback,
115
- } from "runtry";
116
- import type { AppError } from "runtry";
117
- import { HttpError } from "./http-error"; // your app error class
118
-
119
- type MyMeta = { url?: string; body?: unknown };
120
-
121
- const httpMatcher = matchInstance(HttpError, (e) => ({
122
- code: "HTTP",
123
- message: e.message,
124
- status: e.status,
125
- meta: { url: e.url, body: e.body } as MyMeta,
126
- cause: e,
127
- }));
128
-
129
- const toError = createNormalizer<AppError<MyMeta>>(
130
- [abortMatcher, httpMatcher],
131
- (e) => defaultFallback(e) as AppError<MyMeta>
132
- );
133
- ```
134
-
135
- ### 2) Use the normalizer in `run`
136
-
137
- ```ts
138
- import { run } from "runtry";
139
-
140
- const res = await run(getDocuments, {
141
- toError,
142
- onError: (e) => console.log(e.status, e.message),
118
+ mode: "fail-fast", // or "settle" (default)
143
119
  });
144
120
  ```
145
121
 
146
- ---
147
-
148
- ## `createRunner()` (configure once, reuse everywhere)
122
+ ### `runAllOrThrow(tasks, options?)`
149
123
 
150
- If you don't want to pass `toError` every time, create a runner:
124
+ Like `Promise.all` but with concurrency control and retries. Throws the first error (normalized).
151
125
 
152
126
  ```ts
153
- import {
154
- createRunner,
155
- abortMatcher,
156
- matchInstance,
157
- defaultFallback,
158
- } from "runtry";
159
- import { HttpError } from "./http-error";
160
-
161
- const runner = createRunner({
162
- matchers: [
163
- abortMatcher,
164
- matchInstance(HttpError, (e) => ({
165
- code: "HTTP",
166
- message: e.message,
167
- status: e.status,
168
- meta: { url: e.url, body: e.body },
169
- cause: e,
170
- })),
171
- ],
172
- fallback: defaultFallback,
173
- ignoreAbort: true, // default
174
- });
175
-
176
- const result = await client.run(getDocuments, {
177
- onError: (e) => console.log(e.code, e.message),
178
- });
127
+ try {
128
+ const data = await runner.allOrThrow(tasks, { concurrency: 5 });
129
+ } catch (err) {
130
+ // err is your typed AppError
131
+ console.error(err.code);
132
+ }
179
133
  ```
180
134
 
181
135
  ---
182
136
 
183
- ## React example (loading + toast, no try/catch)
137
+ ## React Example
184
138
 
185
139
  ```ts
186
- import { createRunner, abortMatcher, defaultFallback } from "runtry";
187
-
188
- const runner = createRunner({
189
- matchers: [abortMatcher],
190
- fallback: defaultFallback,
191
- });
192
-
193
140
  useEffect(() => {
194
141
  let cancelled = false;
195
- setIsLoading(true);
196
142
 
197
- client.run(getDocuments, {
198
- onSuccess: (docs) => {
199
- if (cancelled) return;
200
- setUploadedFiles(docs.map(mapper));
201
- },
202
- onError: (e) => {
203
- if (e.code === "ABORTED") return;
204
- toast.error(e.message);
143
+ runner.run(fetchData, {
144
+ onSuccess: (data) => {
145
+ if (!cancelled) setData(data);
205
146
  },
206
- onFinally: () => {
207
- if (!cancelled) setIsLoading(false);
147
+ onError: (err) => {
148
+ if (err.code === "ABORTED") return;
149
+ toast.error(err.message);
208
150
  },
209
151
  });
210
152
 
@@ -1 +1 @@
1
- {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/error/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE9C,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,QAAQ,EACjD,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAChB,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,IAErB,KAAK,OAAO,KAAG,CAAC,CAOzB;AAGD,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAQtD;AAGD,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAMjD"}
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/error/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE9C,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,QAAQ,EACjD,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAChB,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,IAErB,KAAK,OAAO,KAAG,CAAC,CAOzB;AAGD,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAQtD;AAGD,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CASjD"}
@@ -24,6 +24,9 @@ export function toAppError(err) {
24
24
  if (err instanceof DOMException && err.name === "AbortError") {
25
25
  return { code: "ABORTED", message: "Request cancelled", cause: err };
26
26
  }
27
+ if (err instanceof DOMException && err.name === "TimeoutError") {
28
+ return { code: "TIMEOUT", message: "Request timed out", cause: err };
29
+ }
27
30
  return defaultFallback(err);
28
31
  }
29
32
  //# sourceMappingURL=normalize.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/error/normalize.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAC9B,KAAgB,EAChB,QAA6B;IAE7B,OAAO,CAAC,GAAY,EAAK,EAAE;QACzB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YACnB,IAAI,GAAG;gBAAE,OAAO,GAAG,CAAC;QACtB,CAAC;QACD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC;AACJ,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,eAAe,CAAC,GAAY;IAC1C,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACzB,mEAAmE;QACnE,gEAAgE;QAChE,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,sBAAsB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IAC9E,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,sBAAsB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AAC1E,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,UAAU,CAAC,GAAY;IACrC,iDAAiD;IACjD,IAAI,GAAG,YAAY,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAC7D,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IACvE,CAAC;IACD,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/error/normalize.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAC9B,KAAgB,EAChB,QAA6B;IAE7B,OAAO,CAAC,GAAY,EAAK,EAAE;QACzB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YACnB,IAAI,GAAG;gBAAE,OAAO,GAAG,CAAC;QACtB,CAAC;QACD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC;AACJ,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,eAAe,CAAC,GAAY;IAC1C,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACzB,mEAAmE;QACnE,gEAAgE;QAChE,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,sBAAsB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IAC9E,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,sBAAsB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AAC1E,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,UAAU,CAAC,GAAY;IACrC,iDAAiD;IACjD,IAAI,GAAG,YAAY,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAC7D,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IACvE,CAAC;IACD,IAAI,GAAG,YAAY,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;QAC/D,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IACvE,CAAC;IACD,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  export { run } from "./runner/run";
2
2
  export { runAll } from "./runner/runAll";
3
- export type { RunAllOptions } from "./runner/runAll";
3
+ export type { RunAllOptions, SuccessResult, ErrorResult } from "./runner/runAll";
4
+ export { isSuccess } from "./runner/runAll";
4
5
  export type { RunOptions, RunResult, RetryOptions } from "./types";
6
+ export type { BackoffStrategy, CircuitBreakerOptions, Metrics, RetryContext, } from "./types";
5
7
  export type { AppError, AppErrorCode } from "./error/types";
6
8
  export { toAppError, defaultFallback, createNormalizer, } from "./error/normalize";
7
9
  export { rules } from "./error/core";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EACL,UAAU,EACV,eAAe,EACf,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnE,YAAY,EACV,eAAe,EACf,qBAAqB,EACrB,OAAO,EACP,YAAY,GACb,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EACL,UAAU,EACV,eAAe,EACf,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { run } from "./runner/run";
2
2
  export { runAll } from "./runner/runAll";
3
+ export { isSuccess } from "./runner/runAll";
3
4
  export { toAppError, defaultFallback, createNormalizer, } from "./error/normalize";
4
5
  export { rules } from "./error/core";
5
6
  export { errorRule } from "./error/builder";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAKzC,OAAO,EACL,UAAU,EACV,eAAe,EACf,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAU5C,OAAO,EACL,UAAU,EACV,eAAe,EACf,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/runner/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGtD;;;;;;;;GAQG;AACH,wBAAsB,GAAG,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,EACxD,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,GAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAM,GAC7B,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAmE1B"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/runner/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAItD;;;;;;;;GAQG;AACH,wBAAsB,GAAG,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,EACxD,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,GAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAM,GAC7B,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CA8I1B"}
@@ -1,4 +1,5 @@
1
1
  import { toAppError as defaultToAppError } from "../error/normalize";
2
+ import { validateOptions } from "../types";
2
3
  import { applyJitter, resolveRetryDelay, sleep } from "../utils";
3
4
  /**
4
5
  * Executes an async operation and returns a Result instead of throwing.
@@ -10,37 +11,88 @@ import { applyJitter, resolveRetryDelay, sleep } from "../utils";
10
11
  * React effects, and any async context.
11
12
  */
12
13
  export async function run(fn, options = {}) {
13
- const { toError = defaultToAppError, mapError, onError, onSuccess, onFinally, ignoreAbort = true, retries = 0, retryDelay, shouldRetry = () => true, jitter = { ratio: 0.5, mode: "full" }, } = options;
14
+ const { toError = defaultToAppError, mapError, onError, onSuccess, onFinally, ignoreAbort = true, retries = 0, retryDelay, shouldRetry = () => true, jitter = { ratio: 0.5, mode: "full" }, backoffStrategy, maxDelay, timeout, signal, onRetry, logger, cleanup, onAbort, } = options;
14
15
  const defaultBaseDelay = retries > 0 ? 300 : 0;
16
+ validateOptions(options);
17
+ if (signal?.aborted) {
18
+ try {
19
+ onAbort?.(signal);
20
+ }
21
+ finally {
22
+ const err = toError(new DOMException("Aborted", "AbortError"));
23
+ const mapped = mapError ? mapError(err) : err;
24
+ if (!ignoreAbort) {
25
+ onError?.(mapped);
26
+ }
27
+ onFinally?.();
28
+ return { ok: false, data: null, error: mapped, metrics: { totalAttempts: 0, totalRetries: 0, totalDuration: 0, lastError: mapped } };
29
+ }
30
+ }
31
+ const startedAt = Date.now();
15
32
  let attempt = 0;
33
+ let lastError;
16
34
  while (true) {
17
35
  try {
18
- const data = await fn();
36
+ const timeoutPromise = timeout && timeout > 0
37
+ ? new Promise((_, reject) => setTimeout(() => reject(new DOMException("Timeout", "TimeoutError")), timeout))
38
+ : null;
39
+ const data = await (timeoutPromise ? Promise.race([fn(), timeoutPromise]) : fn());
19
40
  onSuccess?.(data);
20
41
  onFinally?.();
21
- return { ok: true, data, error: null };
42
+ const totalDuration = Date.now() - startedAt;
43
+ const metrics = {
44
+ totalAttempts: attempt + 1,
45
+ totalRetries: attempt,
46
+ totalDuration,
47
+ lastError,
48
+ };
49
+ logger?.debug?.("run:success", { attempts: metrics.totalAttempts, duration: metrics.totalDuration });
50
+ return { ok: true, data, error: null, metrics };
22
51
  }
23
52
  catch (e) {
24
53
  let err = toError(e);
25
54
  if (mapError)
26
55
  err = mapError(err);
27
- const isAborted = err.code === "ABORTED";
56
+ const isAborted = err?.code === "ABORTED" ||
57
+ (e instanceof DOMException && e.name === "AbortError") ||
58
+ signal?.aborted;
28
59
  if (isAborted) {
29
- if (!ignoreAbort) {
30
- onError?.(err);
60
+ try {
61
+ if (signal)
62
+ onAbort?.(signal);
63
+ }
64
+ finally {
65
+ if (!ignoreAbort) {
66
+ onError?.(err);
67
+ }
68
+ onFinally?.();
69
+ const totalDuration = Date.now() - startedAt;
70
+ const metrics = {
71
+ totalAttempts: attempt,
72
+ totalRetries: attempt,
73
+ totalDuration,
74
+ lastError: err,
75
+ };
76
+ logger?.debug?.("run:aborted", { attempt, duration: metrics.totalDuration });
77
+ return { ok: false, data: null, error: err, metrics };
31
78
  }
32
- onFinally?.();
33
- return { ok: false, data: null, error: err };
34
- // If not ignoring abort, we fall through to onError and return
35
79
  }
80
+ lastError = err;
36
81
  const nextAttempt = attempt + 1;
37
- const canRetry = attempt < retries && shouldRetry(nextAttempt, err);
82
+ const context = {
83
+ totalAttempts: nextAttempt,
84
+ elapsedTime: Date.now() - startedAt,
85
+ };
86
+ const decision = await Promise.resolve(shouldRetry(nextAttempt, err, context));
87
+ const canRetry = attempt < retries && decision;
38
88
  if (canRetry) {
39
89
  attempt = nextAttempt;
40
- let delay = resolveRetryDelay(retryDelay, attempt, err, defaultBaseDelay);
90
+ let delay = resolveRetryDelay(retryDelay, attempt, err, defaultBaseDelay, backoffStrategy, maxDelay);
41
91
  if (!Number.isFinite(delay) || delay < 0)
42
92
  delay = 0;
43
93
  delay = applyJitter(delay, jitter);
94
+ onRetry?.(attempt, err, delay);
95
+ logger?.debug?.("run:retry", { attempt, delay });
44
96
  if (delay > 0)
45
97
  await sleep(delay);
46
98
  continue;
@@ -48,7 +100,15 @@ export async function run(fn, options = {}) {
48
100
  // Final failure or aborted
49
101
  onError?.(err);
50
102
  onFinally?.();
51
- return { ok: false, data: null, error: err };
103
+ const totalDuration = Date.now() - startedAt;
104
+ const metrics = {
105
+ totalAttempts: attempt + 1,
106
+ totalRetries: attempt,
107
+ totalDuration,
108
+ lastError: err,
109
+ };
110
+ logger?.error?.("run:error", err);
111
+ return { ok: false, data: null, error: err, metrics };
52
112
  }
53
113
  }
54
114
  }
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/runner/run.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,IAAI,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAErE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjE;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,GAAG,CACvB,EAAoB,EACpB,UAA4B,EAAE;IAE9B,MAAM,EACJ,OAAO,GAAG,iBAAmD,EAC7D,QAAQ,EACR,OAAO,EACP,SAAS,EACT,SAAS,EACT,WAAW,GAAG,IAAI,EAClB,OAAO,GAAG,CAAC,EACX,UAAU,EACV,WAAW,GAAG,GAAG,EAAE,CAAC,IAAI,EACxB,MAAM,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,GACtC,GAAG,OAAO,CAAC;IAEZ,MAAM,gBAAgB,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAE/C,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,EAAE,EAAE,CAAC;YACxB,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC;YAClB,SAAS,EAAE,EAAE,CAAC;YACd,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACzC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,QAAQ;gBAAE,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YAElC,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC;YAEzC,IAAI,SAAS,EAAE,CAAC;gBACd,IAAI,CAAC,WAAW,EAAE,CAAC;oBACjB,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;gBACjB,CAAC;gBAED,SAAS,EAAE,EAAE,CAAC;gBACd,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;gBAC7C,+DAA+D;YACjE,CAAC;YAED,MAAM,WAAW,GAAG,OAAO,GAAG,CAAC,CAAC;YAChC,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,IAAI,WAAW,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;YAEpE,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,GAAG,WAAW,CAAC;gBAEtB,IAAI,KAAK,GAAG,iBAAiB,CAC3B,UAAU,EACV,OAAO,EACP,GAAG,EACH,gBAAgB,CACjB,CAAC;gBAEF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;oBAAE,KAAK,GAAG,CAAC,CAAC;gBAEpD,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBAEnC,IAAI,KAAK,GAAG,CAAC;oBAAE,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;gBAClC,SAAS;YACX,CAAC;YAED,2BAA2B;YAC3B,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;YACf,SAAS,EAAE,EAAE,CAAC;YACd,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QAC/C,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/runner/run.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,11 @@
1
1
  import type { AppError } from "../error/types";
2
2
  import type { RunOptions } from "../types";
3
+ /**
4
+ * Resultado discriminado por ítem en `runAll`:
5
+ * - "ok": tarea exitosa con `data`
6
+ * - "error": tarea fallida con `error`
7
+ * - "skipped": tarea no ejecutada por cancelación/fail-fast/concurrencia
8
+ */
3
9
  export type RunAllItemResult<T, E extends AppError = AppError> = {
4
10
  status: "ok";
5
11
  ok: true;
@@ -16,6 +22,16 @@ export type RunAllItemResult<T, E extends AppError = AppError> = {
16
22
  data: null;
17
23
  error: null;
18
24
  };
25
+ /** Helper para discriminar resultados exitosos. */
26
+ export type SuccessResult<T> = Extract<RunAllItemResult<T, any>, {
27
+ status: "ok";
28
+ }>;
29
+ /** Helper para discriminar resultados con error. */
30
+ export type ErrorResult<E> = Extract<RunAllItemResult<any, E extends AppError ? E : AppError>, {
31
+ status: "error";
32
+ }>;
33
+ /** Type guard que detecta `status: "ok"` con tipado de `data`. */
34
+ export declare const isSuccess: <T, E extends AppError = AppError>(r: RunAllItemResult<T, E>) => r is SuccessResult<T>;
19
35
  export type RunAllOptions<T, E extends AppError = AppError> = RunOptions<T, E> & {
20
36
  /**
21
37
  * Maximum number of concurrent tasks to run.
@@ -1 +1 @@
1
- {"version":3,"file":"runAll.d.ts","sourceRoot":"","sources":["../../src/runner/runAll.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,UAAU,CAAC;AAEtD,MAAM,MAAM,gBAAgB,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,IACzD;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GAChD;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GACpD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,CAAC;AAE9D,MAAM,MAAM,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI,UAAU,CACtE,CAAC,EACD,CAAC,CACF,GAAG;IACF;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;CAC/B,CAAC;AAEF,wBAAsB,MAAM,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,EAC3D,KAAK,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,EAC9B,OAAO,GAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAM,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAqEnC"}
1
+ {"version":3,"file":"runAll.d.ts","sourceRoot":"","sources":["../../src/runner/runAll.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,UAAU,CAAC;AAGtD;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,IACzD;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GAChD;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GACpD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,CAAC;AAE9D,mDAAmD;AACnD,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,OAAO,CACpC,gBAAgB,CAAC,CAAC,EAAE,GAAG,CAAC,EACxB;IAAE,MAAM,EAAE,IAAI,CAAA;CAAE,CACjB,CAAC;AACF,oDAAoD;AACpD,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,OAAO,CAClC,gBAAgB,CAAC,GAAG,EAAE,CAAC,SAAS,QAAQ,GAAG,CAAC,GAAG,QAAQ,CAAC,EACxD;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CACpB,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,EACxD,GAAG,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,KACxB,CAAC,IAAI,aAAa,CAAC,CAAC,CAAsB,CAAC;AAE9C,MAAM,MAAM,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI,UAAU,CACtE,CAAC,EACD,CAAC,CACF,GAAG;IACF;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;CAC/B,CAAC;AAEF,wBAAsB,MAAM,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,EAC3D,KAAK,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,EAC9B,OAAO,GAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAM,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAsEnC"}
@@ -1,6 +1,10 @@
1
1
  import { run } from "./run";
2
+ import { validateOptions } from "../types";
3
+ /** Type guard que detecta `status: "ok"` con tipado de `data`. */
4
+ export const isSuccess = (r) => r.status === "ok";
2
5
  export async function runAll(tasks, options = {}) {
3
6
  const { concurrency = Infinity, mode = "settle", ...runOptions } = options;
7
+ validateOptions(runOptions);
4
8
  if (tasks.length === 0)
5
9
  return [];
6
10
  const limit = Number.isFinite(concurrency)
@@ -1 +1 @@
1
- {"version":3,"file":"runAll.js","sourceRoot":"","sources":["../../src/runner/runAll.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runAll.js","sourceRoot":"","sources":["../../src/runner/runAll.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,10 @@
1
1
  import type { AppError } from "../error/types";
2
2
  import type { RunOptions } from "../types";
3
+ /**
4
+ * Opciones para `runAllOrThrow`:
5
+ * - Hereda todas las opciones de `RunOptions`
6
+ * - `concurrency`: límite de tareas simultáneas; si falla una, se lanza
7
+ */
3
8
  export type RunAllOrThrowOptions<T, E extends AppError = AppError> = RunOptions<T, E> & {
4
9
  /**
5
10
  * Maximum number of concurrent tasks to run.
@@ -1 +1 @@
1
- {"version":3,"file":"runAllOrThrow.d.ts","sourceRoot":"","sources":["../../src/runner/runAllOrThrow.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,UAAU,CAAC;AAEtD,MAAM,MAAM,oBAAoB,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI,UAAU,CAC7E,CAAC,EACD,CAAC,CACF,GAAG;IACF;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,wBAAsB,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,EAClE,KAAK,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,EAC9B,OAAO,GAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAM,GACvC,OAAO,CAAC,CAAC,EAAE,CAAC,CAyDd"}
1
+ {"version":3,"file":"runAllOrThrow.d.ts","sourceRoot":"","sources":["../../src/runner/runAllOrThrow.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,UAAU,CAAC;AAGtD;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI,UAAU,CAC7E,CAAC,EACD,CAAC,CACF,GAAG;IACF;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,wBAAsB,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,EAClE,KAAK,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,EAC9B,OAAO,GAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAM,GACvC,OAAO,CAAC,CAAC,EAAE,CAAC,CA0Dd"}
@@ -1,6 +1,8 @@
1
1
  import { run } from "./run";
2
+ import { validateOptions } from "../types";
2
3
  export async function runAllOrThrow(tasks, options = {}) {
3
4
  const { concurrency = Infinity, ...runOptions } = options;
5
+ validateOptions(runOptions);
4
6
  if (tasks.length === 0)
5
7
  return [];
6
8
  const limit = Number.isFinite(concurrency)
@@ -1 +1 @@
1
- {"version":3,"file":"runAllOrThrow.js","sourceRoot":"","sources":["../../src/runner/runAllOrThrow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAe5B,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAA8B,EAC9B,UAAsC,EAAE;IAExC,MAAM,EAAE,WAAW,GAAG,QAAQ,EAAE,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC;IAE1D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC;QACxC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACtC,CAAC,CAAC,QAAQ,CAAC;IAEb,MAAM,IAAI,GAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAE1C,qDAAqD;IACrD,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;YACvB,MAAM,CAAC,GAAG,MAAM,GAAG,CAAO,CAAC,EAAE,UAAU,CAAC,CAAC;YACzC,IAAI,CAAC,CAAC,CAAC,EAAE;gBAAE,MAAM,CAAC,CAAC,KAAK,CAAC;YACzB,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,CAAC,CAAC,CACH,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,UAAU,GAAa,IAAI,CAAC;IAEhC,MAAM,MAAM,GAAG,KAAK,IAAI,EAAE;QACxB,OAAO,IAAI,EAAE,CAAC;YACZ,IAAI,OAAO;gBAAE,OAAO;YAEpB,MAAM,CAAC,GAAG,SAAS,EAAE,CAAC;YACtB,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM;gBAAE,OAAO;YAE9B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,IAAI,CAAC,IAAI;gBAAE,SAAS,CAAC,4BAA4B;YAEjD,MAAM,CAAC,GAAG,MAAM,GAAG,CAAO,IAAI,EAAE,UAAU,CAAC,CAAC;YAE5C,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBACV,UAAU,KAAV,UAAU,GAAK,CAAC,CAAC,KAAK,EAAC;gBACvB,OAAO,GAAG,IAAI,CAAC;gBACf,OAAO;YACT,CAAC;YAED,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,CACtE,CAAC;IAEF,IAAI,UAAU;QAAE,MAAM,UAAU,CAAC;IAEjC,cAAc;IACd,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"runAllOrThrow.js","sourceRoot":"","sources":["../../src/runner/runAllOrThrow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAG5B,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAkB3C,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAA8B,EAC9B,UAAsC,EAAE;IAExC,MAAM,EAAE,WAAW,GAAG,QAAQ,EAAE,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC;IAC1D,eAAe,CAAC,UAAU,CAAC,CAAC;IAE5B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC;QACxC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACtC,CAAC,CAAC,QAAQ,CAAC;IAEb,MAAM,IAAI,GAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAE1C,qDAAqD;IACrD,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;YACvB,MAAM,CAAC,GAAG,MAAM,GAAG,CAAO,CAAC,EAAE,UAAU,CAAC,CAAC;YACzC,IAAI,CAAC,CAAC,CAAC,EAAE;gBAAE,MAAM,CAAC,CAAC,KAAK,CAAC;YACzB,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,CAAC,CAAC,CACH,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,UAAU,GAAa,IAAI,CAAC;IAEhC,MAAM,MAAM,GAAG,KAAK,IAAI,EAAE;QACxB,OAAO,IAAI,EAAE,CAAC;YACZ,IAAI,OAAO;gBAAE,OAAO;YAEpB,MAAM,CAAC,GAAG,SAAS,EAAE,CAAC;YACtB,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM;gBAAE,OAAO;YAE9B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,IAAI,CAAC,IAAI;gBAAE,SAAS,CAAC,4BAA4B;YAEjD,MAAM,CAAC,GAAG,MAAM,GAAG,CAAO,IAAI,EAAE,UAAU,CAAC,CAAC;YAE5C,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBACV,UAAU,KAAV,UAAU,GAAK,CAAC,CAAC,KAAK,EAAC;gBACvB,OAAO,GAAG,IAAI,CAAC;gBACf,OAAO;YACT,CAAC;YAED,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,CACtE,CAAC;IAEF,IAAI,UAAU;QAAE,MAAM,UAAU,CAAC;IAEjC,cAAc;IACd,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import type { AppError, Rule, InferErrorFromRules } from "../error/types";
2
2
  import type { RunOptions, RunResult } from "../types";
3
+ import type { CircuitBreakerOptions } from "../types";
3
4
  import { type RunAllItemResult, type RunAllOptions } from "./runAll";
4
5
  export type CreateRunnerOptions<E extends AppError = AppError> = {
5
6
  /**
@@ -21,6 +22,11 @@ export type CreateRunnerOptions<E extends AppError = AppError> = {
21
22
  ignoreAbort?: boolean;
22
23
  /** Optional default mapper for all runs */
23
24
  mapError?: (error: E) => E;
25
+ /**
26
+ * Circuit breaker por defecto para todas las ejecuciones de la instancia.
27
+ * Puede ser sobreescrito por `options.circuitBreaker` en cada `run`.
28
+ */
29
+ circuitBreaker?: CircuitBreakerOptions;
24
30
  };
25
31
  export interface Runner<E extends AppError> {
26
32
  run<T>(fn: () => Promise<T>, options?: RunOptions<T, E>): Promise<RunResult<T, E>>;
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/runner/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAO1E,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEtD,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,UAAU,CAAC;AAElB,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI;IAC/D;;;OAGG;IACH,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAElB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,CAAC;IAE/B;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,CAAC;IAE9B,8BAA8B;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;CAC5B,CAAC;AAOF,MAAM,WAAW,MAAM,CAAC,CAAC,SAAS,QAAQ;IACxC,GAAG,CAAC,CAAC,EACH,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GACzB,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5B,GAAG,CAAC,CAAC,EACH,GAAG,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,EAC5B,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACrC,UAAU,CAAC,CAAC,EACV,GAAG,EAAE,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,EACzB,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GACzB,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;CACjB;AAED,wBAAgB,YAAY,CAC1B,IAAI,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,GAClD,MAAM,CAAC,QAAQ,CAAC,CAAC;AAEpB,wBAAgB,YAAY,CAAC,KAAK,CAAC,MAAM,SAAS,SAAS,IAAI,CAAC,GAAG,CAAC,EAAE,EACpE,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAC5B,mBAAmB,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,EAChD,OAAO,CACR,GACA,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/runner/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAO1E,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEtD,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,UAAU,CAAC;AAElB,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI;IAC/D;;;OAGG;IACH,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAElB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,CAAC;IAE/B;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,CAAC;IAE9B,8BAA8B;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;IAC3B;;;OAGG;IACH,cAAc,CAAC,EAAE,qBAAqB,CAAC;CACxC,CAAC;AAOF,MAAM,WAAW,MAAM,CAAC,CAAC,SAAS,QAAQ;IACxC,GAAG,CAAC,CAAC,EACH,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GACzB,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5B,GAAG,CAAC,CAAC,EACH,GAAG,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,EAC5B,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACrC,UAAU,CAAC,CAAC,EACV,GAAG,EAAE,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,EACzB,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GACzB,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;CACjB;AAED,wBAAgB,YAAY,CAC1B,IAAI,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,GAClD,MAAM,CAAC,QAAQ,CAAC,CAAC;AAEpB,wBAAgB,YAAY,CAAC,KAAK,CAAC,MAAM,SAAS,SAAS,IAAI,CAAC,GAAG,CAAC,EAAE,EACpE,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAC5B,mBAAmB,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,EAChD,OAAO,CACR,GACA,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC"}
@@ -4,18 +4,85 @@ import { runAllOrThrow as baseRunAllOrThrow } from "./runAllOrThrow";
4
4
  import { runAll as baseRunAll, } from "./runAll";
5
5
  const composeMapError = (base, local) => (e) => local ? local(base ? base(e) : e) : base ? base(e) : e;
6
6
  export function createRunner(opts = {}) {
7
- const { rules = [], fallback = (e) => defaultFallback(e), toError: customToError, ignoreAbort = true, mapError: defaultMapError, } = opts;
7
+ const { rules = [], fallback = (e) => defaultFallback(e), toError: customToError, ignoreAbort = true, mapError: defaultMapError, circuitBreaker: defaultCircuitBreaker, } = opts;
8
8
  const toError = customToError ??
9
9
  (rules.length > 0
10
10
  ? createNormalizer(rules, fallback)
11
11
  : toAppError);
12
+ let failureCount = 0;
13
+ let openUntil = null;
14
+ let halfOpenRemaining = null;
12
15
  return {
13
16
  run(fn, options = {}) {
17
+ const cb = options.circuitBreaker ?? defaultCircuitBreaker;
18
+ const now = Date.now();
19
+ if (cb) {
20
+ if (openUntil && now < openUntil) {
21
+ const err = toError(new Error("Circuit open"));
22
+ const mapped = composeMapError(defaultMapError, options.mapError)(err);
23
+ options.onError?.(mapped);
24
+ options.onFinally?.();
25
+ return Promise.resolve({
26
+ ok: false,
27
+ data: null,
28
+ error: mapped,
29
+ metrics: {
30
+ totalAttempts: 0,
31
+ totalRetries: 0,
32
+ totalDuration: 0,
33
+ lastError: mapped,
34
+ },
35
+ });
36
+ }
37
+ if (openUntil && now >= openUntil) {
38
+ openUntil = null;
39
+ failureCount = 0;
40
+ halfOpenRemaining = cb.halfOpenRequests ?? 1;
41
+ }
42
+ if (halfOpenRemaining != null) {
43
+ if (halfOpenRemaining <= 0) {
44
+ const err = toError(new Error("Circuit half-open limit"));
45
+ const mapped = composeMapError(defaultMapError, options.mapError)(err);
46
+ options.onError?.(mapped);
47
+ options.onFinally?.();
48
+ return Promise.resolve({
49
+ ok: false,
50
+ data: null,
51
+ error: mapped,
52
+ metrics: {
53
+ totalAttempts: 0,
54
+ totalRetries: 0,
55
+ totalDuration: 0,
56
+ lastError: mapped,
57
+ },
58
+ });
59
+ }
60
+ else {
61
+ halfOpenRemaining--;
62
+ }
63
+ }
64
+ }
14
65
  return baseRun(fn, {
15
66
  toError,
16
67
  ignoreAbort,
17
68
  ...options,
18
69
  mapError: composeMapError(defaultMapError, options.mapError),
70
+ }).then((r) => {
71
+ if (!cb)
72
+ return r;
73
+ if (!r.ok) {
74
+ failureCount++;
75
+ if (failureCount >= cb.failureThreshold) {
76
+ openUntil = Date.now() + cb.resetTimeout;
77
+ halfOpenRemaining = null;
78
+ }
79
+ }
80
+ else {
81
+ failureCount = 0;
82
+ openUntil = null;
83
+ halfOpenRemaining = null;
84
+ }
85
+ return r;
19
86
  });
20
87
  },
21
88
  all(fns, options = {}) {
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/runner/runner.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,UAAU,GACX,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAE,aAAa,IAAI,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EACL,MAAM,IAAI,UAAU,GAGrB,MAAM,UAAU,CAAC;AA4BlB,MAAM,eAAe,GACnB,CAAI,IAAkB,EAAE,KAAmB,EAAE,EAAE,CAC/C,CAAC,CAAI,EAAE,EAAE,CACP,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AA4B3D,MAAM,UAAU,YAAY,CAC1B,OAAY,EAAE;IAId,MAAM,EACJ,KAAK,GAAG,EAAE,EACV,QAAQ,GAAG,CAAC,CAAU,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAiB,EAC7D,OAAO,EAAE,aAAa,EACtB,WAAW,GAAG,IAAI,EAClB,QAAQ,EAAE,eAAe,GAC1B,GAAG,IAA8B,CAAC;IAEnC,MAAM,OAAO,GACX,aAAa;QACb,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;YACf,CAAC,CAAC,gBAAgB,CAAI,KAA6B,EAAE,QAAQ,CAAC;YAC9D,CAAC,CAAE,UAA2C,CAAC,CAAC;IAEpD,OAAO;QACL,GAAG,CACD,EAAoB,EACpB,UAA4B,EAAE;YAE9B,OAAO,OAAO,CAAC,EAAE,EAAE;gBACjB,OAAO;gBACP,WAAW;gBACX,GAAG,OAAO;gBACV,QAAQ,EAAE,eAAe,CAAC,eAAe,EAAE,OAAO,CAAC,QAAQ,CAAC;aAC7D,CAAC,CAAC;QACL,CAAC;QACD,GAAG,CACD,GAA4B,EAC5B,UAA+B,EAAE;YAEjC,OAAO,UAAU,CAAC,GAAG,EAAE;gBACrB,OAAO;gBACP,WAAW;gBACX,GAAG,OAAO;gBACV,QAAQ,EAAE,eAAe,CAAC,eAAe,EAAE,OAAO,CAAC,QAAQ,CAAC;aAC7D,CAAC,CAAC;QACL,CAAC;QACD,UAAU,CACR,GAAyB,EACzB,UAA4B,EAAE;YAE9B,OAAO,iBAAiB,CAAC,GAAG,EAAE;gBAC5B,OAAO;gBACP,WAAW;gBACX,GAAG,OAAO;gBACV,QAAQ,EAAE,eAAe,CAAC,eAAe,EAAE,OAAO,CAAC,QAAQ,CAAC;aAC7D,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/runner/runner.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -5,90 +5,166 @@ export type Jitter = boolean | number | {
5
5
  mode?: "full" | "equal";
6
6
  rng?: () => number;
7
7
  };
8
+ /**
9
+ * Estrategia de backoff para calcular el delay entre reintentos.
10
+ * - "linear": usa el delay base tal cual en cada intento.
11
+ * - "exponential": multiplica por 2^(attempt-1) el delay.
12
+ * - "fibonacci": multiplica por F(attempt) (serie fibonacci clásica).
13
+ * - function: función personalizada basada en el número de intento.
14
+ */
15
+ export type BackoffStrategy = "linear" | "exponential" | "fibonacci" | ((attempt: number) => number);
16
+ /**
17
+ * Opciones de reintentos para `run`, `runAll` y `runAllOrThrow`.
18
+ */
8
19
  export type RetryOptions<E extends AppError = AppError> = {
9
20
  /**
10
- * Number of retries to attempt.
21
+ * Cantidad de reintentos a realizar (no incluye el intento inicial).
11
22
  * @default 0
12
23
  */
13
24
  retries?: number;
14
25
  /**
15
- * Delay in milliseconds between retries.
16
- *
17
- * - `number` for a fixed delay
18
- * - `function` for custom delay based on attempt and error
19
- *
20
- * @default 0
26
+ * Delay entre intentos:
27
+ * - number: delay fijo (ms)
28
+ * - () => number: delay lazy (evaluado por intento)
29
+ * - (attempt, err) => number: delay basado en intento y último error
30
+ * @default 0 o un baseDelay por defecto si hay retries
21
31
  */
22
- retryDelay?: number | RetryDelayFn<E>;
32
+ retryDelay?: number | (() => number) | RetryDelayFn<E>;
23
33
  /**
24
- * Function to determine if a retry should be attempted.
25
- * Returns true to retry, false to stop.
34
+ * Decide si se debe reintentar ante un error dado.
35
+ * Puede ser síncrono o asíncrono.
36
+ * Recibe el intento siguiente y un contexto con métricas acumuladas.
26
37
  * @default () => true
27
38
  */
28
- shouldRetry?: (attempt: number, error: E) => boolean;
39
+ shouldRetry?: (attempt: number, error: E, context: RetryContext) => boolean | Promise<boolean>;
29
40
  /**
30
- * Adds random jitter to the delay to prevent thundering herd.
31
- *
32
- * - `true` for default 0.5 ratio
33
- * - `false` to disable jitter
34
- * - `number` for custom ratio 0..1
35
- * - `{ ratio, mode, rng }` for full control
36
- *
41
+ * Jitter aleatorio para evitar thundering herd:
42
+ * - true: ratio 0.5 por defecto
43
+ * - false: sin jitter
44
+ * - number: ratio 0..1
45
+ * - object: control completo (ratio, mode, rng)
37
46
  * @default 0.5
38
47
  */
39
48
  jitter?: Jitter;
49
+ /**
50
+ * Estrategia de backoff a aplicar sobre el delay calculado.
51
+ * @default "linear"
52
+ */
53
+ backoffStrategy?: BackoffStrategy;
54
+ /**
55
+ * Límite superior del delay tras backoff y antes de jitter.
56
+ * @default undefined (sin límite)
57
+ */
58
+ maxDelay?: number;
59
+ };
60
+ /**
61
+ * Contexto para `shouldRetry` con acumulados del intento actual.
62
+ */
63
+ export type RetryContext = {
64
+ /** Total de intentos (incluyendo el próximo reintento). */
65
+ totalAttempts: number;
66
+ /** Tiempo transcurrido en ms desde el inicio del `run`. */
67
+ elapsedTime: number;
40
68
  };
69
+ /**
70
+ * Opciones principales para `run` y extendidas a `runAll`/`runAllOrThrow`.
71
+ */
41
72
  export type RunOptions<T, E extends AppError = AppError> = RetryOptions<E> & {
42
73
  /**
43
- * Converts an unknown thrown value into your normalized error type `E`.
44
- *
45
- * Use this to integrate custom errors (e.g. HttpError, AxiosError, ZodError),
46
- * map status codes, or attach metadata for UI/debugging.
47
- *
48
- * If omitted, a default normalizer is used (best-effort).
74
+ * Normaliza un valor de error desconocido a tu tipo `E`.
75
+ * Si no se provee, se usa un normalizador por defecto.
49
76
  */
50
77
  toError?: (err: unknown) => E;
51
78
  /**
52
- * Optional error transformer applied AFTER `toError`.
53
- *
54
- * Useful for translating messages, mapping status to user-friendly text,
55
- * or enforcing a consistent error format across the app.
79
+ * Transformación opcional aplicada luego de `toError`.
80
+ * Útil para ajustar mensajes, códigos o agregar metadata.
56
81
  */
57
82
  mapError?: (error: E) => E;
58
83
  /**
59
- * Called when the operation fails (except when `ignoreAbort` is true and the error code is "ABORTED").
60
- *
61
- * Great place for toasts, logging, analytics, etc.
84
+ * Callback al fallar (no se llama si `ignoreAbort` y el error es ABORTED).
62
85
  */
63
86
  onError?: (error: E) => void;
64
87
  /**
65
- * Called when the operation succeeds.
88
+ * Callback al tener éxito.
66
89
  */
67
90
  onSuccess?: (data: T) => void;
68
91
  /**
69
- * Called after success or failure, similar to `finally`, but with no return value.
70
- *
71
- * Common use: stop loading spinners, cleanup state, etc.
92
+ * Callback que se ejecuta siempre al finalizar (éxito o error).
72
93
  */
73
94
  onFinally?: () => void;
74
95
  /**
75
- * When true, errors with `code === "ABORTED"` are treated as non-fatal:
76
- * - `onError` is NOT called
77
- * - the result is returned as `{ ok: false, error }`
78
- *
79
- * This is useful for cancellable side-effects (React effects, debounced searches, etc.).
80
- *
96
+ * Si true, los abortos (ABORTED) no se consideran error fatal:
97
+ * no se llama `onError` y se devuelve `{ ok: false, error }`.
81
98
  * @default true
82
99
  */
83
100
  ignoreAbort?: boolean;
101
+ /**
102
+ * Señal para cancelación nativa del trabajo.
103
+ * Si está abortada, se corta con `AbortError`.
104
+ */
105
+ signal?: AbortSignal;
106
+ /**
107
+ * Timeout máximo en ms para el trabajo; expira con `TimeoutError`.
108
+ */
109
+ timeout?: number;
110
+ /**
111
+ * Observabilidad de reintentos: recibe intento, error y delay siguiente.
112
+ */
113
+ onRetry?: (attempt: number, error: E, nextDelay: number) => void;
114
+ /**
115
+ * Logger estructurado opcional para debug y errores.
116
+ */
117
+ logger?: {
118
+ debug?: (msg: string, meta?: any) => void;
119
+ error?: (msg: string, error: E) => void;
120
+ };
121
+ /**
122
+ * Limpieza de recursos que se ejecuta siempre al terminar.
123
+ */
124
+ cleanup?: () => void | Promise<void>;
125
+ /**
126
+ * Callback al abortar, útil para reaccionar a `AbortSignal`.
127
+ */
128
+ onAbort?: (signal: AbortSignal) => void;
129
+ /**
130
+ * Configuración de circuit breaker por llamada.
131
+ * Si no se define, puede usar el valor por defecto del `Runner`.
132
+ */
133
+ circuitBreaker?: CircuitBreakerOptions;
134
+ };
135
+ /**
136
+ * Opciones de configuración del circuit breaker:
137
+ * - failureThreshold: número de fallos consecutivos para abrir el circuito
138
+ * - resetTimeout: tiempo en ms que permanece abierto antes de intentar half-open
139
+ * - halfOpenRequests: cantidad permitida en estado half-open
140
+ */
141
+ export type CircuitBreakerOptions = {
142
+ failureThreshold: number;
143
+ resetTimeout: number;
144
+ halfOpenRequests?: number;
145
+ };
146
+ /**
147
+ * Métricas de ejecución devueltas opcionalmente en `RunResult`.
148
+ */
149
+ export type Metrics = {
150
+ totalAttempts: number;
151
+ totalRetries: number;
152
+ totalDuration: number;
153
+ lastError?: AppError;
84
154
  };
85
155
  export type RunResult<T, E extends AppError = AppError> = {
86
156
  ok: true;
87
157
  data: T;
88
158
  error: null;
159
+ metrics?: Metrics;
89
160
  } | {
90
161
  ok: false;
91
162
  data: null;
92
163
  error: E;
164
+ metrics?: Metrics;
93
165
  };
166
+ /**
167
+ * Valida opciones comunes de ejecución/reintentos.
168
+ */
169
+ export declare function validateOptions<T, E extends AppError = AppError>(options: RunOptions<T, E>): void;
94
170
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,MAAM,CAAC;AAElE,MAAM,MAAM,MAAM,GACd,OAAO,GACP,MAAM,GACN;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAAE,CAAC;AAEpE,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI;IACxD;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAEtC;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC;IAErD;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,UAAU,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI,YAAY,CAAC,CAAC,CAAC,GAAG;IAC3E;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,CAAC;IAE9B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;IAE3B;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAE7B;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IAE9B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAEvB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAClD;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GAClC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js CHANGED
@@ -1,2 +1,27 @@
1
- export {};
1
+ /**
2
+ * Valida opciones comunes de ejecución/reintentos.
3
+ */
4
+ export function validateOptions(options) {
5
+ if (options.retries != null && options.retries < 0) {
6
+ throw new Error("retries must be >= 0");
7
+ }
8
+ if (options.timeout != null && options.timeout <= 0) {
9
+ throw new Error("timeout must be > 0");
10
+ }
11
+ if (options.maxDelay != null && options.maxDelay < 0) {
12
+ throw new Error("maxDelay must be >= 0");
13
+ }
14
+ const cb = options.circuitBreaker;
15
+ if (cb) {
16
+ if (cb.failureThreshold < 1) {
17
+ throw new Error("failureThreshold must be >= 1");
18
+ }
19
+ if (cb.resetTimeout <= 0) {
20
+ throw new Error("resetTimeout must be > 0");
21
+ }
22
+ if (cb.halfOpenRequests != null && cb.halfOpenRequests < 1) {
23
+ throw new Error("halfOpenRequests must be >= 1");
24
+ }
25
+ }
26
+ }
2
27
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA8KA;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAyB;IAEzB,IAAI,OAAO,CAAC,OAAO,IAAI,IAAI,IAAI,OAAO,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,IAAI,IAAI,IAAI,OAAO,CAAC,OAAO,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IACD,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IAClC,IAAI,EAAE,EAAE,CAAC;QACP,IAAI,EAAE,CAAC,gBAAgB,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,EAAE,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,EAAE,CAAC,gBAAgB,IAAI,IAAI,IAAI,EAAE,CAAC,gBAAgB,GAAG,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;AACH,CAAC"}
package/dist/utils.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- import type { Jitter, RetryDelayFn } from "./types";
1
+ import type { Jitter, RetryDelayFn, BackoffStrategy } from "./types";
2
2
  export declare const sleep: (ms: number) => Promise<unknown>;
3
3
  export declare function clamp(n: number, min: number, max: number): number;
4
- export declare function resolveRetryDelay<E>(retryDelay: number | RetryDelayFn<E> | undefined, attempt: number, err: E, defaultBaseDelay: number): number;
4
+ export declare function resolveRetryDelay<E>(retryDelay: number | RetryDelayFn<E> | undefined, attempt: number, err: E, defaultBaseDelay: number, backoffStrategy?: BackoffStrategy, maxDelay?: number): number;
5
5
  export declare function applyJitter(delay: number, jitter: Jitter | undefined): number;
6
+ export declare function computeBackoffDelay(strategy: BackoffStrategy, base: number, attempt: number): number;
6
7
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEpD,eAAO,MAAM,KAAK,GAAI,IAAI,MAAM,qBACmB,CAAC;AAEpD,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,UAExD;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,UAAU,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,EAChD,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,CAAC,EACN,gBAAgB,EAAE,MAAM,GACvB,MAAM,CAIR;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CA4B7E"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAErE,eAAO,MAAM,KAAK,GAAI,IAAI,MAAM,qBACmB,CAAC;AAEpD,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,UAExD;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,UAAU,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,EAChD,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,CAAC,EACN,gBAAgB,EAAE,MAAM,EACxB,eAAe,CAAC,EAAE,eAAe,EACjC,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAkBR;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CA4B7E;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,MAAM,CAqBR"}
package/dist/utils.js CHANGED
@@ -2,12 +2,17 @@ export const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2
2
  export function clamp(n, min, max) {
3
3
  return Math.max(min, Math.min(max, n));
4
4
  }
5
- export function resolveRetryDelay(retryDelay, attempt, err, defaultBaseDelay) {
6
- if (typeof retryDelay === "function")
7
- return retryDelay(attempt, err);
8
- if (typeof retryDelay === "number")
9
- return retryDelay;
10
- return defaultBaseDelay;
5
+ export function resolveRetryDelay(retryDelay, attempt, err, defaultBaseDelay, backoffStrategy, maxDelay) {
6
+ let base = typeof retryDelay === "function"
7
+ ? retryDelay(attempt, err)
8
+ : typeof retryDelay === "number"
9
+ ? retryDelay
10
+ : typeof retryDelay === "undefined"
11
+ ? defaultBaseDelay
12
+ : defaultBaseDelay;
13
+ const backoff = computeBackoffDelay(backoffStrategy ?? "linear", base, attempt);
14
+ const out = maxDelay != null ? clamp(backoff, 0, maxDelay) : backoff;
15
+ return Number.isFinite(out) ? out : 0;
11
16
  }
12
17
  export function applyJitter(delay, jitter) {
13
18
  if (delay <= 0 || !jitter)
@@ -31,4 +36,29 @@ export function applyJitter(delay, jitter) {
31
36
  // full jitter
32
37
  return rng() * delay * (1 + r);
33
38
  }
39
+ export function computeBackoffDelay(strategy, base, attempt) {
40
+ if (typeof strategy === "function") {
41
+ const v = strategy(attempt);
42
+ return v >= 0 ? v : 0;
43
+ }
44
+ const b = base >= 0 ? base : 0;
45
+ const a = attempt >= 1 ? attempt : 1;
46
+ if (strategy === "linear")
47
+ return b;
48
+ if (strategy === "exponential")
49
+ return b * Math.pow(2, a - 1);
50
+ if (strategy === "fibonacci") {
51
+ if (a <= 2)
52
+ return b;
53
+ let prev = 1;
54
+ let curr = 1;
55
+ for (let i = 3; i <= a; i++) {
56
+ const next = prev + curr;
57
+ prev = curr;
58
+ curr = next;
59
+ }
60
+ return b * curr;
61
+ }
62
+ return b;
63
+ }
34
64
  //# sourceMappingURL=utils.js.map
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAClC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAEpD,MAAM,UAAU,KAAK,CAAC,CAAS,EAAE,GAAW,EAAE,GAAW;IACvD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,UAAgD,EAChD,OAAe,EACf,GAAM,EACN,gBAAwB;IAExB,IAAI,OAAO,UAAU,KAAK,UAAU;QAAE,OAAO,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACtE,IAAI,OAAO,UAAU,KAAK,QAAQ;QAAE,OAAO,UAAU,CAAC;IACtD,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,MAA0B;IACnE,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAExC,MAAM,GAAG,GACP,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IAEtE,sBAAsB;IACtB,MAAM,KAAK,GACT,OAAO,MAAM,KAAK,QAAQ;QACxB,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,MAAM,KAAK,IAAI;YACjB,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI;gBACpD,CAAC,CAAC,MAAM,CAAC,KAAK;gBACd,CAAC,CAAC,GAAG,CAAC;IAEV,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAE7B,MAAM,IAAI,GAAG,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAE9E,qEAAqE;IACrE,4CAA4C;IAC5C,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,KAAK,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED,cAAc;IACd,OAAO,GAAG,EAAE,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runtry",
3
- "version": "0.8.2",
3
+ "version": "0.9.0",
4
4
  "description": "Run async functions and return a typed Result instead of throwing.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -19,14 +19,19 @@
19
19
  "scripts": {
20
20
  "build": "tsc -p tsconfig.build.json",
21
21
  "test": "bun test",
22
+ "docs:dev": "cd docs && mintlify dev",
23
+ "docs:dev:es": "cd docs && mintlify dev --config mint.es.json",
24
+ "docs:build": "cd docs && mintlify build",
25
+ "docs:preview": "cd docs && mintlify preview",
22
26
  "prepublishOnly": "npm run build"
23
27
  },
24
28
  "devDependencies": {
25
29
  "@types/bun": "latest",
26
- "typescript": "^5.0.0"
30
+ "typescript": "^5.0.0",
31
+ "mint": "latest"
27
32
  },
28
33
  "license": "MIT",
29
- "homepage": "https://github.com/sebasxsala/runtry#readme",
34
+ "homepage": "https://runtry.sebastian-sala-tech.workers.dev/",
30
35
  "bugs": "https://github.com/sebasxsala/runtry/issues",
31
36
  "author": {
32
37
  "name": "sebasxsala",