runtry 0.8.1 → 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,41 +1,20 @@
1
1
  import type { AppError, Rule } from "./types";
2
- /**
3
- * AbortError (AbortController, fetch abort, etc)
4
- */
5
- export declare const abort: () => Rule<AppError<"ABORTED">>;
6
- /**
7
- * Timeout errors (AbortSignal.timeout, libs, etc)
8
- */
9
- export declare const timeout: () => Rule<AppError<"TIMEOUT">>;
10
- /**
11
- * HTTP-like errors (status / statusCode)
12
- */
13
- export declare const httpStatus: () => Rule<AppError<"HTTP">>;
14
- /**
15
- * AggregateError (Promise.any, etc)
16
- */
17
- export declare const aggregate: () => Rule<AppError<"UNKNOWN", {
2
+ export declare const abort: Rule<AppError<"ABORTED">>;
3
+ export declare const timeout: Rule<AppError<"TIMEOUT">>;
4
+ export declare const httpStatus: Rule<AppError<"HTTP">>;
5
+ export declare const aggregate: Rule<AppError<"UNKNOWN", {
18
6
  errors: unknown[];
19
7
  }>>;
20
- /**
21
- * String thrown errors
22
- */
23
- export declare const string: () => Rule<AppError<"UNKNOWN">>;
24
- /**
25
- * Message-like objects (final fallback)
26
- */
27
- export declare const message: () => Rule<AppError<"UNKNOWN">>;
28
- /**
29
- * Namespace export
30
- */
8
+ export declare const string: Rule<AppError<"UNKNOWN">>;
9
+ export declare const message: Rule<AppError<"UNKNOWN">>;
31
10
  export declare const rules: {
32
- abort: () => Rule<AppError<"ABORTED">>;
33
- timeout: () => Rule<AppError<"TIMEOUT">>;
34
- httpStatus: () => Rule<AppError<"HTTP">>;
35
- aggregate: () => Rule<AppError<"UNKNOWN", {
11
+ abort: Rule<AppError<"ABORTED">>;
12
+ timeout: Rule<AppError<"TIMEOUT">>;
13
+ httpStatus: Rule<AppError<"HTTP">>;
14
+ aggregate: Rule<AppError<"UNKNOWN", {
36
15
  errors: unknown[];
37
16
  }>>;
38
- string: () => Rule<AppError<"UNKNOWN">>;
39
- message: () => Rule<AppError<"UNKNOWN">>;
17
+ string: Rule<AppError<"UNKNOWN">>;
18
+ message: Rule<AppError<"UNKNOWN">>;
40
19
  };
41
20
  //# sourceMappingURL=core.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/error/core.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,KAAK,QAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAchD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,OAAO,QAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAclD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,QAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAclD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,QAChB,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE;IAAE,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,CAalD,CAAC;AAEJ;;GAEG;AACH,eAAO,MAAM,MAAM,QAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAKjD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,OAAO,QAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAclD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,KAAK;iBAzGO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;mBAmBvB,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;sBAmBtB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;qBAoB9C,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE;QAAE,MAAM,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC,CAAC;kBAkB5B,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;mBAUxB,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;CA0BnD,CAAC"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/error/core.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE9C,eAAO,MAAM,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAY3C,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAY7C,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAa7C,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE;IAAE,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,CAYtE,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAK5C,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAU7C,CAAC;AAEF,eAAO,MAAM,KAAK;;;;;gBAjCyC,OAAO,EAAE;;;;CAwC1B,CAAC"}
@@ -1,7 +1,6 @@
1
- /**
2
- * AbortError (AbortController, fetch abort, etc)
3
- */
4
- export const abort = () => (err) => {
1
+ import { createRunner } from "../runner/runner";
2
+ import { errorRule } from "./builder";
3
+ export const abort = (err) => {
5
4
  if (err instanceof DOMException && err.name === "AbortError") {
6
5
  return { code: "ABORTED", message: "Request cancelled", cause: err };
7
6
  }
@@ -14,10 +13,7 @@ export const abort = () => (err) => {
14
13
  }
15
14
  return null;
16
15
  };
17
- /**
18
- * Timeout errors (AbortSignal.timeout, libs, etc)
19
- */
20
- export const timeout = () => (err) => {
16
+ export const timeout = (err) => {
21
17
  if (err instanceof DOMException && err.name === "TimeoutError") {
22
18
  return { code: "TIMEOUT", message: "Request timed out", cause: err };
23
19
  }
@@ -30,10 +26,7 @@ export const timeout = () => (err) => {
30
26
  }
31
27
  return null;
32
28
  };
33
- /**
34
- * HTTP-like errors (status / statusCode)
35
- */
36
- export const httpStatus = () => (err) => {
29
+ export const httpStatus = (err) => {
37
30
  if (typeof err === "object" && err !== null) {
38
31
  const status = err.status ?? err.statusCode;
39
32
  if (typeof status === "number") {
@@ -47,12 +40,8 @@ export const httpStatus = () => (err) => {
47
40
  }
48
41
  return null;
49
42
  };
50
- /**
51
- * AggregateError (Promise.any, etc)
52
- */
53
- export const aggregate = () => (err) => {
54
- if (typeof AggregateError !== "undefined" &&
55
- err instanceof AggregateError) {
43
+ export const aggregate = (err) => {
44
+ if (typeof AggregateError !== "undefined" && err instanceof AggregateError) {
56
45
  return {
57
46
  code: "UNKNOWN",
58
47
  message: err.message || "Multiple errors occurred",
@@ -62,34 +51,21 @@ export const aggregate = () => (err) => {
62
51
  }
63
52
  return null;
64
53
  };
65
- /**
66
- * String thrown errors
67
- */
68
- export const string = () => (err) => {
54
+ export const string = (err) => {
69
55
  if (typeof err === "string") {
70
56
  return { code: "UNKNOWN", message: err, cause: err };
71
57
  }
72
58
  return null;
73
59
  };
74
- /**
75
- * Message-like objects (final fallback)
76
- */
77
- export const message = () => (err) => {
60
+ export const message = (err) => {
78
61
  if (typeof err === "object" &&
79
62
  err !== null &&
80
63
  "message" in err &&
81
64
  typeof err.message === "string") {
82
- return {
83
- code: "UNKNOWN",
84
- message: err.message,
85
- cause: err,
86
- };
65
+ return { code: "UNKNOWN", message: err.message, cause: err };
87
66
  }
88
67
  return null;
89
68
  };
90
- /**
91
- * Namespace export
92
- */
93
69
  export const rules = {
94
70
  abort,
95
71
  timeout,
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/error/core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/error/core.ts"],"names":[],"mappings":"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"}
@@ -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"}
@@ -17,7 +17,7 @@ export type AppError<Code extends string = AppErrorCode | (string & {}), Meta =
17
17
  };
18
18
  type NonNull<T> = T extends null ? never : T;
19
19
  type RuleReturn<R> = R extends (err: unknown) => infer Out ? NonNull<Out> : never;
20
- export type InferErrorFromRules<TRules extends readonly Rule<any>[]> = TRules extends readonly [] ? AppError : RuleReturn<TRules[number]>;
20
+ export type InferErrorFromRules<TRules extends readonly Rule<any>[]> = TRules extends readonly [] ? AppError : RuleReturn<TRules[number]> | AppError<"UNKNOWN">;
21
21
  export type Rule<E extends AppError = AppError> = (err: unknown) => E | null;
22
22
  export {};
23
23
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/error/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,SAAS,GACT,SAAS,GACT,YAAY,GACZ,MAAM,GACN,SAAS,CAAC;AAEd;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,CAClB,IAAI,SAAS,MAAM,GAAG,YAAY,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,EAClD,IAAI,GAAG,OAAO,IACZ;IACF,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC;AAC7C,KAAK,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,GAAG,GACtD,OAAO,CAAC,GAAG,CAAC,GACZ,KAAK,CAAC;AACV,MAAM,MAAM,mBAAmB,CAAC,MAAM,SAAS,SAAS,IAAI,CAAC,GAAG,CAAC,EAAE,IACjE,MAAM,SAAS,SAAS,EAAE,GAAG,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AACrE,MAAM,MAAM,IAAI,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,GAAG,IAAI,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/error/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,SAAS,GACT,SAAS,GACT,YAAY,GACZ,MAAM,GACN,SAAS,CAAC;AAEd;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,CAClB,IAAI,SAAS,MAAM,GAAG,YAAY,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,EAClD,IAAI,GAAG,OAAO,IACZ;IACF,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC;AAC7C,KAAK,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,GAAG,GACtD,OAAO,CAAC,GAAG,CAAC,GACZ,KAAK,CAAC;AACV,MAAM,MAAM,mBAAmB,CAAC,MAAM,SAAS,SAAS,IAAI,CAAC,GAAG,CAAC,EAAE,IACjE,MAAM,SAAS,SAAS,EAAE,GACtB,QAAQ,GACR,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;AACvD,MAAM,MAAM,IAAI,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,GAAG,IAAI,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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"}