breaker-box 8.0.0 → 9.0.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
@@ -182,7 +182,7 @@ Creates a circuit breaker around the provided async function.
182
182
 
183
183
  - `fn`: The async function to protect
184
184
  - `options`: Configuration object (optional)
185
- - `errorIsFailure`: Function to determine if an error is a non-retryable failure; when true, the error is thrown immediately without counting toward metrics (default: `() => false`)
185
+ - `errorIsTransient`: Function to determine if an error is transient; when true, the error is thrown to the caller but does NOT count toward the circuit breaker's failure rate (default: `() => false`)
186
186
  - `errorThreshold`: Percentage (0-1) of errors that triggers circuit opening (default: `0`)
187
187
  - `errorWindow`: Time window in ms for tracking errors (default: `10_000`)
188
188
  - `fallback`: Function to call when an error occurs or circuit is open (default: undefined)
@@ -208,41 +208,15 @@ A function with the same signature as `fn` and additional methods:
208
208
 
209
209
  ### Helper Functions
210
210
 
211
- #### `withRetry(fn, options?)` *(Deprecated)*
211
+ #### `CircuitError`
212
212
 
213
- > **Deprecated:** Use the `retryLimit`, `retryDelay`, and `retryTest` options on `createCircuitBreaker` instead.
213
+ Error class thrown by the circuit breaker. All errors from `createCircuitBreaker` are instances of `CircuitError` with a prefixed message (e.g., `ERR_CIRCUIT_BREAKER_CALL_FAILURE`, `ERR_CIRCUIT_BREAKER_MAX_RETRIES`).
214
214
 
215
- Wraps a function with retry logic. Failures will be retried according to the provided options.
215
+ **Properties:**
216
216
 
217
- **Parameters:**
218
-
219
- - `fn`: The async function to wrap with retry logic
220
- - `options`: Configuration object (optional)
221
- - `maxAttempts`: Maximum number of attempts (default: `3`)
222
- - `retryDelay`: Function `(attempt: number, signal: AbortSignal) => Promise<void>` for delay before retry (default: immediate)
223
- - `shouldRetry`: Function `(error: unknown, attempt: number) => boolean` to determine if error should be retried (default: `() => true`)
224
-
225
- **Example:**
226
-
227
- ```typescript
228
- const retryCall = withRetry(apiCall, {
229
- maxAttempts: 5,
230
- retryDelay: useExponentialBackoff(30),
231
- shouldRetry: (error) => error.statusCode !== 404,
232
- })
233
- ```
234
-
235
- #### `withTimeout(fn, timeoutMs, message?)` *(Deprecated)*
236
-
237
- > **Deprecated:** Use the `timeout` option on `createCircuitBreaker` instead.
238
-
239
- Wraps a function with a timeout. Rejects with `Error(message)` if execution exceeds `timeoutMs`.
240
-
241
- **Parameters:**
242
-
243
- - `fn`: The async function to wrap with timeout
244
- - `timeoutMs`: Timeout in milliseconds
245
- - `message`: Error message to use when timeout occurs (default: `"ERR_CIRCUIT_BREAKER_TIMEOUT"`)
217
+ - `message`: Prefixed error code (e.g., `"ERR_CIRCUIT_BREAKER_OPEN"`)
218
+ - `cause`: The underlying error that triggered the circuit breaker error
219
+ - `isTransient`: `true` if the error was classified as transient via `errorIsTransient`
246
220
 
247
221
  #### `useExponentialBackoff(maxSeconds)`
248
222
 
package/dist/index.cjs CHANGED
@@ -28,16 +28,6 @@ const delayMs = (ms, signal) => {
28
28
  signal.addEventListener("abort", onAbort, { once: true });
29
29
  }) : new Promise((next) => setTimeout(next, ms));
30
30
  };
31
- const deprecated = (fn, method, message) => {
32
- let warned = false;
33
- return ((...args) => {
34
- if (!warned) {
35
- console.warn(`[breaker-box] ${method} Deprecation: ${message}`);
36
- warned = true;
37
- }
38
- return fn(...args);
39
- });
40
- };
41
31
  const noop = () => {
42
32
  };
43
33
  function promiseTry(fn) {
@@ -47,64 +37,6 @@ function promiseTry(fn) {
47
37
  return Promise.reject(error);
48
38
  }
49
39
  }
50
- async function shouldRetry(options) {
51
- const { retries, lastError, retryDelay, retryLimit, retryTest, signal } = options;
52
- if (retries >= retryLimit) throw lastError;
53
- if (!retryTest(lastError)) throw lastError;
54
- try {
55
- if (!retryDelay) return true;
56
- else if (typeof retryDelay === "number") await delayMs(retryDelay, signal);
57
- else if (typeof retryDelay === "function") await retryDelay(retries, signal);
58
- } catch {
59
- }
60
- return true;
61
- }
62
-
63
- function withRetry$1(main, options = {}) {
64
- const {
65
- shouldRetry = () => true,
66
- maxAttempts = 3,
67
- retryDelay = () => Promise.resolve()
68
- } = options;
69
- assert(maxAttempts >= 1, "maxAttempts must be a number greater than 0");
70
- const controller = new AbortController();
71
- const { signal } = controller;
72
- async function withRetryFunction(...args) {
73
- let attempt = 1;
74
- while (true) {
75
- try {
76
- return await main(...args);
77
- } catch (cause) {
78
- if (attempt >= maxAttempts) {
79
- throw new Error(`ERR_CIRCUIT_BREAKER_MAX_ATTEMPTS (${maxAttempts})`, {
80
- cause
81
- });
82
- }
83
- if (!shouldRetry(cause, attempt)) throw cause;
84
- }
85
- attempt++;
86
- await abortable(signal, retryDelay(attempt, signal));
87
- }
88
- }
89
- return Object.assign(withRetryFunction, {
90
- [Symbol.dispose]: () => controller.abort()
91
- });
92
- }
93
-
94
- function withTimeout$1(main, timeoutMs, timeoutMessage = "ERR_CIRCUIT_BREAKER_TIMEOUT") {
95
- const error = new Error(timeoutMessage);
96
- const controller = new AbortController();
97
- const { signal } = controller;
98
- function withTimeoutFunction(...args) {
99
- return new Promise((resolve, reject) => {
100
- const timer = setTimeout(reject, timeoutMs, error);
101
- abortable(signal, main(...args)).then(resolve, reject).finally(() => clearTimeout(timer));
102
- });
103
- }
104
- return Object.assign(withTimeoutFunction, {
105
- [Symbol.dispose]: () => controller.abort()
106
- });
107
- }
108
40
 
109
41
  function useExponentialBackoff(maxSeconds) {
110
42
  return function exponentialBackoff(attempt, signal) {
@@ -122,9 +54,18 @@ function useFibonacciBackoff(maxSeconds) {
122
54
  };
123
55
  }
124
56
 
57
+ class CircuitError extends Error {
58
+ isTransient;
59
+ constructor(message, options) {
60
+ super(`ERR_CIRCUIT_BREAKER_${message}`, options);
61
+ this.isTransient = options?.isTransient ?? false;
62
+ }
63
+ }
64
+
65
+ let warnedErrorIsFailure = false;
125
66
  function parseOptions(options) {
126
67
  const {
127
- errorIsFailure = () => false,
68
+ errorIsTransient = options.errorIsFailure ?? (() => false),
128
69
  errorThreshold = 0,
129
70
  errorWindow = 1e4,
130
71
  fallback,
@@ -138,9 +79,15 @@ function parseOptions(options) {
138
79
  retryTest = () => true,
139
80
  timeout = 0
140
81
  } = options;
82
+ if ("errorIsFailure" in options && !("errorIsTransient" in options) && !warnedErrorIsFailure) {
83
+ warnedErrorIsFailure = true;
84
+ console.warn(
85
+ 'breaker-box: "errorIsFailure" is deprecated. Use "errorIsTransient" instead.'
86
+ );
87
+ }
141
88
  assert(
142
- typeof errorIsFailure === "function",
143
- `"errorIsFailure" must be a function (received ${typeof errorIsFailure})`
89
+ typeof errorIsTransient === "function",
90
+ `"errorIsTransient" must be a function (received ${typeof errorIsTransient})`
144
91
  );
145
92
  assert(
146
93
  errorThreshold >= 0 && errorThreshold <= 1,
@@ -195,7 +142,7 @@ function parseOptions(options) {
195
142
  `"timeout" must be a finite, non-negative number (received ${timeout})`
196
143
  );
197
144
  return {
198
- errorIsFailure,
145
+ errorIsTransient,
199
146
  errorThreshold,
200
147
  errorWindow,
201
148
  fallback,
@@ -211,6 +158,20 @@ function parseOptions(options) {
211
158
  };
212
159
  }
213
160
 
161
+ async function shouldContinue(options) {
162
+ const { retries, lastError, retryDelay, retryLimit, retryTest, signal } = options;
163
+ if (retries >= retryLimit)
164
+ throw new CircuitError("MAX_RETRIES", { cause: lastError });
165
+ if (!retryTest(lastError))
166
+ throw new CircuitError("NON_RETRYABLE", { cause: lastError });
167
+ try {
168
+ if (!retryDelay) return true;
169
+ else if (typeof retryDelay === "number") await delayMs(retryDelay, signal);
170
+ else if (typeof retryDelay === "function") await retryDelay(retries, signal);
171
+ } catch {
172
+ }
173
+ return true;
174
+ }
214
175
  const validTransitions = {
215
176
  closed: ["open", "disposed"],
216
177
  open: ["halfOpen", "disposed"],
@@ -223,13 +184,6 @@ function assertTransition(from, to) {
223
184
  `Invalid transition from ${from} to ${to}`
224
185
  );
225
186
  }
226
- class CircuitError extends Error {
227
- isTransient;
228
- constructor(message, options) {
229
- super(`ERR_CIRCUIT_BREAKER_${message}`, options);
230
- this.isTransient = options?.isTransient ?? false;
231
- }
232
- }
233
187
  function createState(status, failureCause) {
234
188
  const controller = new AbortController();
235
189
  return {
@@ -242,7 +196,7 @@ function createState(status, failureCause) {
242
196
  }
243
197
  function createCircuitBreaker(main, options = {}) {
244
198
  const {
245
- errorIsFailure,
199
+ errorIsTransient,
246
200
  errorThreshold,
247
201
  errorWindow,
248
202
  fallback,
@@ -268,7 +222,7 @@ function createCircuitBreaker(main, options = {}) {
268
222
  return result;
269
223
  } catch (cause) {
270
224
  historyItem.status = "rejected";
271
- const isTransient = errorIsFailure(cause);
225
+ const isTransient = errorIsTransient(cause);
272
226
  if (isTransient) historyItem = void 0;
273
227
  throw new CircuitError("CALL_FAILURE", { cause, isTransient });
274
228
  } finally {
@@ -305,7 +259,7 @@ function createCircuitBreaker(main, options = {}) {
305
259
  if (state === nextState) transitionToHalfOpen();
306
260
  }
307
261
  function transitionToHalfOpen() {
308
- transitionTo("halfOpen");
262
+ transitionTo("halfOpen", state.failureCause);
309
263
  if (onHalfOpen) setImmediate(onHalfOpen);
310
264
  }
311
265
  function transitionToClosed() {
@@ -324,6 +278,7 @@ function createCircuitBreaker(main, options = {}) {
324
278
  let retries = 0;
325
279
  do {
326
280
  const current = state;
281
+ lastError = void 0;
327
282
  if (current.status === "closed") {
328
283
  try {
329
284
  return await tryCall(current, args);
@@ -339,6 +294,7 @@ function createCircuitBreaker(main, options = {}) {
339
294
  return await tryCall(current, args);
340
295
  } catch (error) {
341
296
  if (guardIsCurrent(current, error)) lastError = error;
297
+ break;
342
298
  } finally {
343
299
  if (state === current && current.history.size >= minimumCandidates) {
344
300
  const rate = current.failureRate = calculateFailureRate();
@@ -348,23 +304,21 @@ function createCircuitBreaker(main, options = {}) {
348
304
  }
349
305
  }
350
306
  } else if (current.status === "open" || current.status === "halfOpen") {
351
- if (!fallback) {
352
- throw (
353
- // eslint-disable-next-line @typescript-eslint/only-throw-error
354
- current.failureCause ?? new CircuitError("OPEN", { cause: current.failureCause })
355
- );
356
- }
357
- return await fallback(...args);
307
+ break;
358
308
  } else throw current.failureCause;
359
- } while (await shouldRetry({
309
+ } while (await shouldContinue({
360
310
  retries: ++retries,
361
- lastError,
311
+ lastError: lastError?.cause ?? lastError,
362
312
  retryDelay,
363
313
  retryLimit,
364
314
  retryTest,
365
315
  signal: state.controller.signal
316
+ }).catch((error) => {
317
+ lastError = error;
318
+ return false;
366
319
  }));
367
- throw new Error("unknown error in circuit breaker retry logic");
320
+ if (!fallback) throw lastError ?? state.failureCause;
321
+ return fallback(...args);
368
322
  }
369
323
  function dispose(disposeMessage = "ERR_CIRCUIT_BREAKER_DISPOSED") {
370
324
  if (state.status === "disposed") return;
@@ -380,21 +334,9 @@ function createCircuitBreaker(main, options = {}) {
380
334
  return wrapped;
381
335
  }
382
336
 
383
- const withRetry = deprecated(
384
- withRetry$1,
385
- "withRetry",
386
- "Use `retryLimit`, `retryDelay`, and `retryTest` options on `createCircuitBreaker` instead."
387
- );
388
- const withTimeout = deprecated(
389
- withTimeout$1,
390
- "withTimeout",
391
- "Use `options.timeout` on`createCircuitBreaker` instead."
392
- );
393
-
337
+ exports.CircuitError = CircuitError;
394
338
  exports.createCircuitBreaker = createCircuitBreaker;
395
339
  exports.delayMs = delayMs;
396
340
  exports.useExponentialBackoff = useExponentialBackoff;
397
341
  exports.useFibonacciBackoff = useFibonacciBackoff;
398
- exports.withRetry = withRetry;
399
- exports.withTimeout = withTimeout;
400
342
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../lib/util.ts","../lib/retry.ts","../lib/timeout.ts","../lib/backoff.ts","../lib/options.ts","../lib/circuit-breaker.ts","../lib/index.ts"],"sourcesContent":["import type { AnyFn, RetryDelayFn } from \"./types.js\"\n\n/**\n * Returns a promise which rejects when the abort signal is triggered or\n * resolves when the promise is fulfilled.\n */\nexport const abortable = <T>(\n\tsignal: AbortSignal,\n\tpending: PromiseLike<T>,\n): Promise<T> =>\n\tnew Promise((resolve, reject) => {\n\t\tsignal.throwIfAborted()\n\n\t\tconst onAbort = () => reject(signal.reason)\n\t\tsignal.addEventListener(\"abort\", onAbort, { once: true })\n\n\t\tPromise.resolve(pending)\n\t\t\t.finally(() => signal.removeEventListener(\"abort\", onAbort))\n\t\t\t.then(resolve, reject)\n\t})\n\n/**\n * Asserts that the given value is truthy. If not, throws a `TypeError`.\n */\nexport function assert(value: unknown, message?: string): asserts value {\n\tif (!value) throw new TypeError(message)\n}\n\n/**\n * Returns a promise that resolves after the specified number of milliseconds.\n */\nexport const delayMs = (ms: number, signal?: AbortSignal): Promise<void> => {\n\tif (!Number.isFinite(ms) || ms < 0) {\n\t\tthrow new RangeError(\n\t\t\t`\"ms\" must be a finite, non-negative number (received ${ms})`,\n\t\t)\n\t}\n\n\treturn signal\n\t\t? new Promise((resolve, reject) => {\n\t\t\t\tsignal.throwIfAborted()\n\n\t\t\t\tconst timer = setTimeout(() => {\n\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort)\n\t\t\t\t\tresolve()\n\t\t\t\t}, ms)\n\n\t\t\t\tconst onAbort = () => {\n\t\t\t\t\tclearTimeout(timer)\n\t\t\t\t\treject(signal.reason)\n\t\t\t\t}\n\n\t\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true })\n\t\t\t})\n\t\t: new Promise((next) => setTimeout(next, ms))\n}\n\nexport const deprecated = <T extends AnyFn>(\n\tfn: T,\n\tmethod: string,\n\tmessage: string,\n): T => {\n\tlet warned = false\n\treturn ((...args) => {\n\t\tif (!warned) {\n\t\t\tconsole.warn(`[breaker-box] ${method} Deprecation: ${message}`)\n\t\t\twarned = true\n\t\t}\n\t\treturn fn(...args)\n\t}) as T\n}\n\nexport const identity = <T>(value: T): T => value\n\nexport const noop: (...args: unknown[]) => void = () => {}\n\n/**\n * Polyfill for `Promise.try()`\n */\nexport function promiseTry<T>(fn: () => T): Promise<T> {\n\ttry {\n\t\treturn Promise.resolve(fn())\n\t} catch (error) {\n\t\treturn Promise.reject(error)\n\t}\n}\n\nexport async function shouldRetry(options: {\n\tretries: number\n\tlastError: unknown\n\tretryDelay: number | RetryDelayFn\n\tretryLimit: number\n\tretryTest: (error: unknown) => boolean\n\tsignal: AbortSignal\n}): Promise<true> {\n\tconst { retries, lastError, retryDelay, retryLimit, retryTest, signal } =\n\t\toptions\n\n\tif (retries >= retryLimit) throw lastError\n\tif (!retryTest(lastError)) throw lastError\n\n\ttry {\n\t\tif (!retryDelay) return true\n\t\telse if (typeof retryDelay === \"number\") await delayMs(retryDelay, signal)\n\t\telse if (typeof retryDelay === \"function\") await retryDelay(retries, signal)\n\t} catch {\n\t\t/* empty */\n\t}\n\n\treturn true\n}\n","import { type MainFn, type RetryOptions } from \"./types.js\"\nimport { assert, abortable } from \"./util.js\"\n\n/**\n * Wrap a function with retry logic. Errors will be retried according to the\n * provided options.\n *\n * @example\n * ```ts\n * // Compose with circuit breaker. Retry up to 3 times with no delay\n * const protectedA = createCircuitBreaker(\n * withRetry(unreliableApiCall, { maxAttempts: 3 })\n * )\n *\n * // Retry up to 5 times with exponential backoff\n * const protectedB = createCircuitBreaker(\n * withRetry(unreliableApiCall, {\n * maxAttempts: 5,\n * retryDelay: useExponentialBackoff(30),\n * })\n * )\n * ```\n */\nexport function withRetry<Ret, Args extends readonly unknown[]>(\n\tmain: MainFn<Ret, Args>,\n\toptions: Readonly<RetryOptions> = {},\n): MainFn<Ret, Args> & Disposable {\n\tconst {\n\t\tshouldRetry = () => true,\n\t\tmaxAttempts = 3,\n\t\tretryDelay = () => Promise.resolve(),\n\t} = options\n\n\tassert(maxAttempts >= 1, \"maxAttempts must be a number greater than 0\")\n\n\tconst controller = new AbortController()\n\tconst { signal } = controller\n\n\tasync function withRetryFunction(...args: Args): Promise<Ret> {\n\t\tlet attempt = 1\n\t\twhile (true) {\n\t\t\ttry {\n\t\t\t\treturn await main(...args)\n\t\t\t} catch (cause) {\n\t\t\t\tif (attempt >= maxAttempts) {\n\t\t\t\t\tthrow new Error(`ERR_CIRCUIT_BREAKER_MAX_ATTEMPTS (${maxAttempts})`, {\n\t\t\t\t\t\tcause,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tif (!shouldRetry(cause, attempt)) throw cause\n\t\t\t}\n\n\t\t\tattempt++\n\t\t\tawait abortable(signal, retryDelay(attempt, signal))\n\t\t}\n\t}\n\n\treturn Object.assign(withRetryFunction, {\n\t\t[Symbol.dispose]: () => controller.abort(),\n\t})\n}\n","import { type MainFn } from \"./types.js\"\nimport { abortable } from \"./util.js\"\n\n/**\n * Wraps an async function with a timeout constraint. Rejects with an Error if\n * execution exceeds the specified timeout.\n *\n * @example\n * ```ts\n * const fetchWithTimeout = withTimeout(fetchData, 5000, \"Fetch timed out\")\n * try {\n * const data = await fetchWithTimeout(url)\n * } catch (error) {\n * console.error(error.message) // \"Fetch timed out\" after 5 seconds\n * }\n * ```\n */\nexport function withTimeout<Ret, Args extends readonly unknown[]>(\n\tmain: MainFn<Ret, Args>,\n\ttimeoutMs: number,\n\ttimeoutMessage = \"ERR_CIRCUIT_BREAKER_TIMEOUT\",\n): MainFn<Ret, Args> & Disposable {\n\tconst error = new Error(timeoutMessage)\n\tconst controller = new AbortController()\n\tconst { signal } = controller\n\n\tfunction withTimeoutFunction(...args: Args): Promise<Ret> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timer = setTimeout(reject, timeoutMs, error)\n\n\t\t\tabortable(signal, main(...args))\n\t\t\t\t.then(resolve, reject)\n\t\t\t\t.finally(() => clearTimeout(timer))\n\t\t})\n\t}\n\n\treturn Object.assign(withTimeoutFunction, {\n\t\t[Symbol.dispose]: () => controller.abort(),\n\t})\n}\n","import type { RetryDelayFn } from \"./types.js\"\nimport { delayMs } from \"./util.js\"\n\n/**\n * Creates an exponential backoff strategy for retry delays.\n * Delay grows as 2^(attempt-2) seconds, capped at maxSeconds.\n *\n * The sequence is: 1s, 2s, 4s, 8s, 16s, 32s, etc.\n *\n * @example\n * ```ts\n * const backoff = useExponentialBackoff(30)\n * await backoff(2) // waits 1 second\n * await backoff(3) // waits 2 seconds\n * await backoff(10) // waits 30 seconds (capped)\n * ```\n */\nexport function useExponentialBackoff(maxSeconds: number): RetryDelayFn {\n\treturn function exponentialBackoff(attempt, signal) {\n\t\tconst num = Math.max(attempt - 2, 0)\n\t\tconst delay = Math.min(2 ** num, maxSeconds)\n\t\treturn delayMs(delay * 1_000, signal)\n\t}\n}\n\nconst sqrt5 = /* @__PURE__ */ Math.sqrt(5)\n/**\n * Binet's formula for calculating Fibonacci numbers in constant time.\n * @see https://en.wikipedia.org/wiki/Fibonacci_sequence#Closed-form_expression\n */\nconst binet = (n: number) =>\n\tMath.round(((1 + sqrt5) ** n - (1 - sqrt5) ** n) / (2 ** n * sqrt5))\n\n/**\n * Creates a Fibonacci backoff strategy for retry delays. It is more gradual\n * than exponential backoff, useful for more aggressive retry patterns.\n *\n * The sequence is: 1s, 2s, 3s, 5s, 8s, 13s, etc.\n *\n * @example\n * ```ts\n * const backoff = useFibonacciBackoff(60)\n * await backoff(2) // waits 1 second\n * await backoff(5) // waits 5 seconds\n * await backoff(10) // waits 55 seconds\n * ```\n */\nexport function useFibonacciBackoff(maxSeconds: number): RetryDelayFn {\n\treturn function fibonacciBackoff(attempt, signal) {\n\t\tconst delay = Math.min(binet(attempt), maxSeconds)\n\t\treturn delayMs(delay * 1_000, signal)\n\t}\n}\n","import type { AnyFn, CircuitBreakerOptions } from \"./types.js\"\nimport { assert } from \"./util.js\"\n\nexport function parseOptions<Fallback extends AnyFn>(\n\toptions: CircuitBreakerOptions<Fallback>,\n) {\n\tconst {\n\t\terrorIsFailure = () => false,\n\t\terrorThreshold = 0,\n\t\terrorWindow = 10_000,\n\t\tfallback,\n\t\tminimumCandidates = 1,\n\t\tonClose,\n\t\tonHalfOpen,\n\t\tonOpen,\n\t\tresetAfter = 30_000,\n\t\tretryDelay = 0,\n\t\tretryLimit = Infinity,\n\t\tretryTest = () => true,\n\t\ttimeout = 0,\n\t} = options\n\n\t// errorIsFailure\n\tassert(\n\t\ttypeof errorIsFailure === \"function\",\n\t\t`\"errorIsFailure\" must be a function (received ${typeof errorIsFailure})`,\n\t)\n\n\t// errorThreshold\n\tassert(\n\t\terrorThreshold >= 0 && errorThreshold <= 1,\n\t\t`\"errorThreshold\" must be between 0 and 1 (received ${errorThreshold})`,\n\t)\n\n\t// errorWindow\n\tassert(\n\t\terrorWindow >= 1_000,\n\t\t`\"errorWindow\" must be milliseconds of at least 1 second (received ${errorWindow})`,\n\t)\n\n\t// (optional) fallback\n\tassert(\n\t\t!fallback || typeof fallback === \"function\",\n\t\t`\"fallback\" must be a function (received ${typeof fallback})`,\n\t)\n\n\t// minimumCandidates\n\tassert(\n\t\tminimumCandidates >= 1,\n\t\t`\"minimumCandidates\" must be greater than 0 (received ${minimumCandidates})`,\n\t)\n\n\t// (optional) onClose\n\tassert(\n\t\t!onClose || typeof onClose === \"function\",\n\t\t`\"onClose\" must be a function (received ${typeof onClose})`,\n\t)\n\n\t// (optional) onHalfOpen\n\tassert(\n\t\t!onHalfOpen || typeof onHalfOpen === \"function\",\n\t\t`\"onHalfOpen\" must be a function (received ${typeof onHalfOpen})`,\n\t)\n\n\t// (optional) onOpen\n\tassert(\n\t\t!onOpen || typeof onOpen === \"function\",\n\t\t`\"onOpen\" must be a function (received ${typeof onOpen})`,\n\t)\n\n\t// resetAfter\n\tassert(\n\t\tresetAfter >= 1_000,\n\t\t`\"resetAfter\" must be milliseconds of at least 1 second (received ${resetAfter})`,\n\t)\n\tassert(\n\t\tresetAfter >= errorWindow,\n\t\t`\"resetAfter\" must be greater than or equal to \"errorWindow\" (received ${resetAfter}, expected >= ${errorWindow})`,\n\t)\n\n\t// retryDelay\n\tassert(\n\t\ttypeof retryDelay === \"function\" ||\n\t\t\t(typeof retryDelay === \"number\" &&\n\t\t\t\tretryDelay >= 0 &&\n\t\t\t\tNumber.isFinite(retryDelay)),\n\t\t`\"retryDelay\" must be a function or a finite, non-negative number (received ${typeof retryDelay})`,\n\t)\n\n\t// retryLimit\n\tassert(\n\t\ttypeof retryLimit === \"number\" && retryLimit >= 1,\n\t\t`\"retryLimit\" must be greater than 0 (received ${retryLimit})`,\n\t)\n\n\t// retryTest\n\tassert(\n\t\ttypeof retryTest === \"function\",\n\t\t`\"retryTest\" must be a function (received ${typeof retryTest})`,\n\t)\n\n\t// timeout\n\tassert(\n\t\tNumber.isFinite(timeout) && timeout >= 0,\n\t\t`\"timeout\" must be a finite, non-negative number (received ${timeout})`,\n\t)\n\n\treturn {\n\t\terrorIsFailure,\n\t\terrorThreshold,\n\t\terrorWindow,\n\t\tfallback,\n\t\tminimumCandidates,\n\t\tonClose,\n\t\tonHalfOpen,\n\t\tonOpen,\n\t\tresetAfter,\n\t\tretryDelay,\n\t\tretryLimit,\n\t\tretryTest,\n\t\ttimeout,\n\t}\n}\n","import { parseOptions } from \"./options.js\"\nimport type {\n\tCircuitBreakerOptions,\n\tCircuitBreakerProtectedFn,\n\tHistoryEntry,\n\tHistoryMap,\n\tMainFn,\n\tStateName,\n} from \"./types.js\"\nimport {\n\tabortable,\n\tassert,\n\tdelayMs,\n\tnoop,\n\tpromiseTry,\n\tshouldRetry,\n} from \"./util.js\"\n\nconst validTransitions: Record<StateName, StateName[]> = {\n\tclosed: [\"open\", \"disposed\"],\n\topen: [\"halfOpen\", \"disposed\"],\n\thalfOpen: [\"closed\", \"open\", \"disposed\"],\n\tdisposed: [],\n}\n\nfunction assertTransition(from: StateName, to: StateName): void {\n\tassert(\n\t\tvalidTransitions[from].includes(to),\n\t\t`Invalid transition from ${from} to ${to}`,\n\t)\n}\n\ninterface CircuitInternalState<T extends StateName = StateName> {\n\tcontroller: AbortController\n\tfailureCause: unknown\n\tfailureRate: number\n\thistory: HistoryMap\n\tstatus: T\n}\n\nclass CircuitError extends Error {\n\tisTransient: boolean\n\tconstructor(\n\t\tmessage: string,\n\t\toptions?: { cause?: unknown; isTransient?: boolean },\n\t) {\n\t\tsuper(`ERR_CIRCUIT_BREAKER_${message}`, options)\n\t\tthis.isTransient = options?.isTransient ?? false\n\t}\n}\n\nfunction createState(\n\tstatus: StateName,\n\tfailureCause?: unknown,\n): CircuitInternalState {\n\tconst controller = new AbortController()\n\treturn {\n\t\tcontroller,\n\t\tfailureCause,\n\t\tfailureRate: 0,\n\t\thistory: new Map(),\n\t\tstatus,\n\t}\n}\n\n/**\n * Creates a circuit breaker that wraps an async function with failure tracking\n * and automatic fallback behavior.\n *\n * The circuit breaker operates in four states:\n *\n * - `closed`: Normal operation, tracks failures in a sliding window\n * - `open`: Failed state, fallback is used until `resetAfter` milliseconds\n * - `halfOpen`: Testing recovery, allows trial calls\n * - `disposed`: Terminal state, all calls rejected\n *\n * When the failure rate exceeds `errorThreshold` within the `errorWindow`, the\n * circuit opens and rejects calls (using fallback if provided) for `resetAfter`\n * milliseconds. After this period, it transitions to half-open and allows up\n * to `minimumCandidates` concurrent trial calls. If their failure rate stays\n * at or below the threshold, the circuit closes; otherwise it reopens.\n *\n * @example\n * ```ts\n * const protectedFn = createCircuitBreaker(unreliableApiCall, {\n * errorThreshold: 0.5,\n * errorWindow: 10_000,\n * resetAfter: 30_000,\n * fallback: () => cachedResponse,\n * })\n *\n * try {\n * const result = await protectedFn(arg1, arg2)\n * } catch (error) {\n * console.error('Circuit breaker rejected call:', error)\n * }\n *\n * console.log(protectedFn.getState()) // 'closed' | 'open' | 'halfOpen' | 'disposed'\n * protectedFn[Symbol.dispose]() // Clean up timers and resources\n * ```\n */\nexport function createCircuitBreaker<Ret, Args extends unknown[]>(\n\tmain: MainFn<Ret, Args>,\n\toptions: CircuitBreakerOptions<MainFn<Ret, Args>> = {},\n): CircuitBreakerProtectedFn<Ret, Args> {\n\tconst {\n\t\terrorIsFailure,\n\t\terrorThreshold,\n\t\terrorWindow,\n\t\tfallback,\n\t\tminimumCandidates,\n\t\tonClose,\n\t\tonHalfOpen,\n\t\tonOpen,\n\t\tresetAfter,\n\t\tretryDelay,\n\t\tretryLimit,\n\t\tretryTest,\n\t\ttimeout,\n\t} = parseOptions(options)\n\n\tlet state = createState(\"closed\")\n\n\tasync function tryCall(\n\t\tcurrent: CircuitInternalState,\n\t\targs: Args,\n\t): Promise<Ret> {\n\t\tconst { history } = current\n\t\tconst request = promiseTry(() => main(...args))\n\n\t\tlet historyItem: HistoryEntry | undefined = { status: \"pending\" }\n\t\thistory.set(request, historyItem)\n\n\t\ttry {\n\t\t\tconst result =\n\t\t\t\ttimeout > 0\n\t\t\t\t\t? await abortable(AbortSignal.timeout(timeout), request)\n\t\t\t\t\t: await request\n\t\t\thistoryItem.status = \"resolved\"\n\t\t\treturn result\n\t\t} catch (cause) {\n\t\t\thistoryItem.status = \"rejected\"\n\t\t\t// Drop this request if it's a transient error that shouldn't count\n\t\t\t// towards the failure rate\n\t\t\tconst isTransient = errorIsFailure(cause)\n\t\t\tif (isTransient) historyItem = undefined\n\n\t\t\t// Wrap the error in a CircuitError to provide additional context and\n\t\t\t// control flow handling.\n\t\t\tthrow new CircuitError(\"CALL_FAILURE\", { cause, isTransient })\n\t\t} finally {\n\t\t\t// Remove the request if it was a transient failure, or if it's stale.\n\t\t\tif (!historyItem || state !== current) history.delete(request)\n\t\t\t// Keep the request in history until the end of the error window, or until\n\t\t\t// the circuit transitions.\n\t\t\telse {\n\t\t\t\tconst { signal } = current.controller\n\t\t\t\tdelayMs(errorWindow, signal)\n\t\t\t\t\t.catch(() => {})\n\t\t\t\t\t.finally(() => history.delete(request))\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction calculateFailureRate(): number {\n\t\tlet failures = 0\n\t\tlet total = 0\n\t\tfor (const { status } of state.history.values()) {\n\t\t\tif (status === \"rejected\") failures++\n\t\t\tif (status !== \"pending\") total++\n\t\t}\n\t\tif (!total || total < minimumCandidates) return 0\n\t\treturn failures / total\n\t}\n\n\tfunction transitionTo(\n\t\ttoStatus: StateName,\n\t\tfailureCause?: unknown,\n\t): CircuitInternalState {\n\t\tassertTransition(state.status, toStatus)\n\t\tstate.controller.abort()\n\t\treturn (state = createState(toStatus, failureCause))\n\t}\n\n\tasync function transitionToOpen(error: CircuitError): Promise<void> {\n\t\t// Race guard: a concurrent failure may have already changed state.\n\t\tif (state.status !== \"closed\" && state.status !== \"halfOpen\") return\n\n\t\tconst cause = error.cause ?? error\n\t\tconst nextState = transitionTo(\"open\", cause)\n\t\tif (onOpen) setImmediate(onOpen, cause)\n\n\t\tconst { signal } = nextState.controller\n\t\tawait delayMs(resetAfter, signal)\n\t\tif (state === nextState) transitionToHalfOpen()\n\t}\n\n\tfunction transitionToHalfOpen(): void {\n\t\ttransitionTo(\"halfOpen\")\n\t\tif (onHalfOpen) setImmediate(onHalfOpen)\n\t}\n\n\tfunction transitionToClosed(): void {\n\t\ttransitionTo(\"closed\")\n\t\tif (onClose) setImmediate(onClose)\n\t}\n\n\tfunction guardIsCurrent(\n\t\tcurrent: CircuitInternalState,\n\t\terror: unknown,\n\t): error is CircuitError {\n\t\tif (!(error instanceof CircuitError)) throw error\n\t\t// Transient errors shouldn't affect the circuit breaker's state. Re-throw\n\t\t// the original cause of the error.\n\t\tif (error.isTransient) throw error.cause\n\n\t\t// If the circuit breaker was disposed mid-flight, surface the underlying\n\t\t// cause of the in-flight call rather than the dispose error.\n\t\tif (state.status === \"disposed\")\n\t\t\t// eslint-disable-next-line @typescript-eslint/only-throw-error\n\t\t\tthrow error.cause ?? new CircuitError(\"DISPOSED\")\n\n\t\t// If the circuit breaker transitioned states, try again.\n\t\treturn state === current\n\t}\n\n\tasync function protectedFn(...args: Args): Promise<Ret> {\n\t\tlet lastError: CircuitError | undefined\n\t\tlet retries = 0\n\t\tdo {\n\t\t\tconst current = state\n\n\t\t\t// Closed: Normal Operation\n\t\t\tif (current.status === \"closed\") {\n\t\t\t\ttry {\n\t\t\t\t\treturn await tryCall(current, args)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (guardIsCurrent(current, error)) {\n\t\t\t\t\t\tlastError = error\n\t\t\t\t\t\t// Determine if the failure rate should open the circuit.\n\t\t\t\t\t\tconst rate = (current.failureRate = calculateFailureRate())\n\t\t\t\t\t\tif (rate > errorThreshold) transitionToOpen(error).catch(noop)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Half-Open: Execute trial calls until we have enough candidates.\n\t\t\telse if (\n\t\t\t\tcurrent.status === \"halfOpen\" &&\n\t\t\t\tcurrent.history.size < minimumCandidates\n\t\t\t) {\n\t\t\t\ttry {\n\t\t\t\t\treturn await tryCall(current, args)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (guardIsCurrent(current, error)) lastError = error\n\t\t\t\t} finally {\n\t\t\t\t\t// Do nothing until we have enough candidates to make a decision.\n\t\t\t\t\tif (state === current && current.history.size >= minimumCandidates) {\n\t\t\t\t\t\tconst rate = (current.failureRate = calculateFailureRate())\n\t\t\t\t\t\t// Determine if the failure rate should re-open the circuit or\n\t\t\t\t\t\t// if it is healthy enough to close it again.\n\t\t\t\t\t\tif (rate > errorThreshold && lastError)\n\t\t\t\t\t\t\ttransitionToOpen(lastError).catch(noop)\n\t\t\t\t\t\telse if (rate <= errorThreshold) transitionToClosed()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Open: Skip calls and immediately return fallback if available.\n\t\t\telse if (current.status === \"open\" || current.status === \"halfOpen\") {\n\t\t\t\tif (!fallback) {\n\t\t\t\t\tthrow (\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/only-throw-error\n\t\t\t\t\t\tcurrent.failureCause ??\n\t\t\t\t\t\tnew CircuitError(\"OPEN\", { cause: current.failureCause })\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\treturn await fallback(...args)\n\t\t\t}\n\n\t\t\t// Disposed: Reject all calls with dispose error.\n\t\t\telse throw current.failureCause\n\t\t} while (\n\t\t\tawait shouldRetry({\n\t\t\t\tretries: ++retries,\n\t\t\t\tlastError,\n\t\t\t\tretryDelay,\n\t\t\t\tretryLimit,\n\t\t\t\tretryTest,\n\t\t\t\tsignal: state.controller.signal,\n\t\t\t})\n\t\t)\n\t\tthrow new Error(\"unknown error in circuit breaker retry logic\")\n\t}\n\n\tfunction dispose(disposeMessage = \"ERR_CIRCUIT_BREAKER_DISPOSED\"): void {\n\t\tif (state.status === \"disposed\") return\n\t\ttransitionTo(\"disposed\", new ReferenceError(disposeMessage))\n\t\tmain[Symbol.dispose]?.()\n\t}\n\n\tconst wrapped = protectedFn as CircuitBreakerProtectedFn<Ret, Args>\n\twrapped[Symbol.dispose] = () => dispose()\n\twrapped.dispose = dispose\n\twrapped.getFailureRate = () => state.failureRate\n\twrapped.getLatestError = () => state.failureCause\n\twrapped.getState = () => state.status\n\n\treturn wrapped\n}\n","import { withRetry as internalWithRetry } from \"./retry.js\"\nimport { withTimeout as internalWithTimeout } from \"./timeout.js\"\nimport type { StateName } from \"./types.js\"\n\nexport { useExponentialBackoff, useFibonacciBackoff } from \"./backoff.js\"\nexport { createCircuitBreaker } from \"./circuit-breaker.js\"\n\nexport type {\n\tCircuitBreakerOptions,\n\tCircuitBreakerProtectedFn,\n\tMainFn,\n\tRetryOptions,\n\tStateName,\n} from \"./types.js\"\nexport { delayMs } from \"./util.js\"\n\n// =============================================================================\n// Deprecated API properties\nimport { deprecated } from \"./util.js\"\n\n/** @deprecated Use `StateName` instead. */\nexport type CircuitState = StateName\n\n/** @deprecated Use `retryLimit`, `retryDelay`, and `retryTest` options on `createCircuitBreaker` instead. */\nexport const withRetry = deprecated(\n\tinternalWithRetry,\n\t\"withRetry\",\n\t\"Use `retryLimit`, `retryDelay`, and `retryTest` options on `createCircuitBreaker` instead.\",\n)\n\n/** @deprecated Use `options.timeout` on `createCircuitBreaker` instead. */\nexport const withTimeout = deprecated(\n\tinternalWithTimeout,\n\t\"withTimeout\",\n\t\"Use `options.timeout` on`createCircuitBreaker` instead.\",\n)\n"],"names":["withRetry","withTimeout","internalWithRetry","internalWithTimeout"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../lib/util.ts","../lib/backoff.ts","../lib/circuit-error.ts","../lib/options.ts","../lib/circuit-breaker.ts"],"sourcesContent":["\n/**\n * Returns a promise which rejects when the abort signal is triggered or\n * resolves when the promise is fulfilled.\n */\nexport const abortable = <T>(\n\tsignal: AbortSignal,\n\tpending: PromiseLike<T>,\n): Promise<T> =>\n\tnew Promise((resolve, reject) => {\n\t\tsignal.throwIfAborted()\n\n\t\tconst onAbort = () => reject(signal.reason)\n\t\tsignal.addEventListener(\"abort\", onAbort, { once: true })\n\n\t\tPromise.resolve(pending)\n\t\t\t.finally(() => signal.removeEventListener(\"abort\", onAbort))\n\t\t\t.then(resolve, reject)\n\t})\n\n/**\n * Asserts that the given value is truthy. If not, throws a `TypeError`.\n */\nexport function assert(value: unknown, message?: string): asserts value {\n\tif (!value) throw new TypeError(message)\n}\n\n/**\n * Returns a promise that resolves after the specified number of milliseconds.\n */\nexport const delayMs = (ms: number, signal?: AbortSignal): Promise<void> => {\n\tif (!Number.isFinite(ms) || ms < 0) {\n\t\tthrow new RangeError(\n\t\t\t`\"ms\" must be a finite, non-negative number (received ${ms})`,\n\t\t)\n\t}\n\n\treturn signal\n\t\t? new Promise((resolve, reject) => {\n\t\t\t\tsignal.throwIfAborted()\n\n\t\t\t\tconst timer = setTimeout(() => {\n\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort)\n\t\t\t\t\tresolve()\n\t\t\t\t}, ms)\n\n\t\t\t\tconst onAbort = () => {\n\t\t\t\t\tclearTimeout(timer)\n\t\t\t\t\treject(signal.reason)\n\t\t\t\t}\n\n\t\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true })\n\t\t\t})\n\t\t: new Promise((next) => setTimeout(next, ms))\n}\n\nexport const noop: (...args: unknown[]) => void = () => {}\n\n/**\n * Polyfill for `Promise.try()`\n */\nexport function promiseTry<T>(fn: () => T): Promise<T> {\n\ttry {\n\t\treturn Promise.resolve(fn())\n\t} catch (error) {\n\t\treturn Promise.reject(error)\n\t}\n}\n\n\n","import type { RetryDelayFn } from \"./types.js\"\nimport { delayMs } from \"./util.js\"\n\n/**\n * Creates an exponential backoff strategy for retry delays.\n * Delay grows as 2^(attempt-2) seconds, capped at maxSeconds.\n *\n * The sequence is: 1s, 2s, 4s, 8s, 16s, 32s, etc.\n *\n * @example\n * ```ts\n * const backoff = useExponentialBackoff(30)\n * await backoff(2) // waits 1 second\n * await backoff(3) // waits 2 seconds\n * await backoff(10) // waits 30 seconds (capped)\n * ```\n */\nexport function useExponentialBackoff(maxSeconds: number): RetryDelayFn {\n\treturn function exponentialBackoff(attempt, signal) {\n\t\tconst num = Math.max(attempt - 2, 0)\n\t\tconst delay = Math.min(2 ** num, maxSeconds)\n\t\treturn delayMs(delay * 1_000, signal)\n\t}\n}\n\nconst sqrt5 = /* @__PURE__ */ Math.sqrt(5)\n/**\n * Binet's formula for calculating Fibonacci numbers in constant time.\n * @see https://en.wikipedia.org/wiki/Fibonacci_sequence#Closed-form_expression\n */\nconst binet = (n: number) =>\n\tMath.round(((1 + sqrt5) ** n - (1 - sqrt5) ** n) / (2 ** n * sqrt5))\n\n/**\n * Creates a Fibonacci backoff strategy for retry delays. It is more gradual\n * than exponential backoff, useful for more aggressive retry patterns.\n *\n * The sequence is: 1s, 2s, 3s, 5s, 8s, 13s, etc.\n *\n * @example\n * ```ts\n * const backoff = useFibonacciBackoff(60)\n * await backoff(2) // waits 1 second\n * await backoff(5) // waits 5 seconds\n * await backoff(10) // waits 55 seconds\n * ```\n */\nexport function useFibonacciBackoff(maxSeconds: number): RetryDelayFn {\n\treturn function fibonacciBackoff(attempt, signal) {\n\t\tconst delay = Math.min(binet(attempt), maxSeconds)\n\t\treturn delayMs(delay * 1_000, signal)\n\t}\n}\n","export class CircuitError extends Error {\n\tisTransient: boolean\n\tconstructor(\n\t\tmessage: string,\n\t\toptions?: { cause?: unknown; isTransient?: boolean },\n\t) {\n\t\tsuper(`ERR_CIRCUIT_BREAKER_${message}`, options)\n\t\tthis.isTransient = options?.isTransient ?? false\n\t}\n}\n","import type { AnyFn, CircuitBreakerOptions } from \"./types.js\"\nimport { assert } from \"./util.js\"\n\nlet warnedErrorIsFailure = false\n\nexport function parseOptions<Fallback extends AnyFn>(\n\toptions: CircuitBreakerOptions<Fallback>,\n) {\n\tconst {\n\t\terrorIsTransient = options.errorIsFailure ?? (() => false),\n\t\terrorThreshold = 0,\n\t\terrorWindow = 10_000,\n\t\tfallback,\n\t\tminimumCandidates = 1,\n\t\tonClose,\n\t\tonHalfOpen,\n\t\tonOpen,\n\t\tresetAfter = 30_000,\n\t\tretryDelay = 0,\n\t\tretryLimit = Infinity,\n\t\tretryTest = () => true,\n\t\ttimeout = 0,\n\t} = options\n\n\tif (\n\t\t\"errorIsFailure\" in options &&\n\t\t!(\"errorIsTransient\" in options) &&\n\t\t!warnedErrorIsFailure\n\t) {\n\t\twarnedErrorIsFailure = true\n\t\tconsole.warn(\n\t\t\t'breaker-box: \"errorIsFailure\" is deprecated. Use \"errorIsTransient\" instead.',\n\t\t)\n\t}\n\n\t// errorIsTransient\n\tassert(\n\t\ttypeof errorIsTransient === \"function\",\n\t\t`\"errorIsTransient\" must be a function (received ${typeof errorIsTransient})`,\n\t)\n\n\t// errorThreshold\n\tassert(\n\t\terrorThreshold >= 0 && errorThreshold <= 1,\n\t\t`\"errorThreshold\" must be between 0 and 1 (received ${errorThreshold})`,\n\t)\n\n\t// errorWindow\n\tassert(\n\t\terrorWindow >= 1_000,\n\t\t`\"errorWindow\" must be milliseconds of at least 1 second (received ${errorWindow})`,\n\t)\n\n\t// (optional) fallback\n\tassert(\n\t\t!fallback || typeof fallback === \"function\",\n\t\t`\"fallback\" must be a function (received ${typeof fallback})`,\n\t)\n\n\t// minimumCandidates\n\tassert(\n\t\tminimumCandidates >= 1,\n\t\t`\"minimumCandidates\" must be greater than 0 (received ${minimumCandidates})`,\n\t)\n\n\t// (optional) onClose\n\tassert(\n\t\t!onClose || typeof onClose === \"function\",\n\t\t`\"onClose\" must be a function (received ${typeof onClose})`,\n\t)\n\n\t// (optional) onHalfOpen\n\tassert(\n\t\t!onHalfOpen || typeof onHalfOpen === \"function\",\n\t\t`\"onHalfOpen\" must be a function (received ${typeof onHalfOpen})`,\n\t)\n\n\t// (optional) onOpen\n\tassert(\n\t\t!onOpen || typeof onOpen === \"function\",\n\t\t`\"onOpen\" must be a function (received ${typeof onOpen})`,\n\t)\n\n\t// resetAfter\n\tassert(\n\t\tresetAfter >= 1_000,\n\t\t`\"resetAfter\" must be milliseconds of at least 1 second (received ${resetAfter})`,\n\t)\n\tassert(\n\t\tresetAfter >= errorWindow,\n\t\t`\"resetAfter\" must be greater than or equal to \"errorWindow\" (received ${resetAfter}, expected >= ${errorWindow})`,\n\t)\n\n\t// retryDelay\n\tassert(\n\t\ttypeof retryDelay === \"function\" ||\n\t\t\t(typeof retryDelay === \"number\" &&\n\t\t\t\tretryDelay >= 0 &&\n\t\t\t\tNumber.isFinite(retryDelay)),\n\t\t`\"retryDelay\" must be a function or a finite, non-negative number (received ${typeof retryDelay})`,\n\t)\n\n\t// retryLimit\n\tassert(\n\t\ttypeof retryLimit === \"number\" && retryLimit >= 1,\n\t\t`\"retryLimit\" must be greater than 0 (received ${retryLimit})`,\n\t)\n\n\t// retryTest\n\tassert(\n\t\ttypeof retryTest === \"function\",\n\t\t`\"retryTest\" must be a function (received ${typeof retryTest})`,\n\t)\n\n\t// timeout\n\tassert(\n\t\tNumber.isFinite(timeout) && timeout >= 0,\n\t\t`\"timeout\" must be a finite, non-negative number (received ${timeout})`,\n\t)\n\n\treturn {\n\t\terrorIsTransient,\n\t\terrorThreshold,\n\t\terrorWindow,\n\t\tfallback,\n\t\tminimumCandidates,\n\t\tonClose,\n\t\tonHalfOpen,\n\t\tonOpen,\n\t\tresetAfter,\n\t\tretryDelay,\n\t\tretryLimit,\n\t\tretryTest,\n\t\ttimeout,\n\t}\n}\n","import { parseOptions } from \"./options.js\"\nimport type {\n\tCircuitBreakerOptions,\n\tCircuitBreakerProtectedFn,\n\tHistoryEntry,\n\tHistoryMap,\n\tMainFn,\n\tRetryDelayFn,\n\tStateName,\n} from \"./types.js\"\nimport { CircuitError } from \"./circuit-error.js\"\nimport {\n\tabortable,\n\tassert,\n\tdelayMs,\n\tnoop,\n\tpromiseTry,\n} from \"./util.js\"\n\nasync function shouldContinue(options: {\n\tretries: number\n\tlastError: unknown\n\tretryDelay: number | RetryDelayFn\n\tretryLimit: number\n\tretryTest: (error: unknown) => boolean\n\tsignal: AbortSignal\n}): Promise<true> {\n\tconst { retries, lastError, retryDelay, retryLimit, retryTest, signal } =\n\t\toptions\n\n\tif (retries >= retryLimit)\n\t\tthrow new CircuitError(\"MAX_RETRIES\", { cause: lastError })\n\tif (!retryTest(lastError))\n\t\tthrow new CircuitError(\"NON_RETRYABLE\", { cause: lastError })\n\n\ttry {\n\t\tif (!retryDelay) return true\n\t\telse if (typeof retryDelay === \"number\") await delayMs(retryDelay, signal)\n\t\telse if (typeof retryDelay === \"function\") await retryDelay(retries, signal)\n\t} catch {\n\t\t/* empty */\n\t}\n\n\treturn true\n}\n\nconst validTransitions: Record<StateName, StateName[]> = {\n\tclosed: [\"open\", \"disposed\"],\n\topen: [\"halfOpen\", \"disposed\"],\n\thalfOpen: [\"closed\", \"open\", \"disposed\"],\n\tdisposed: [],\n}\n\nfunction assertTransition(from: StateName, to: StateName): void {\n\tassert(\n\t\tvalidTransitions[from].includes(to),\n\t\t`Invalid transition from ${from} to ${to}`,\n\t)\n}\n\ninterface CircuitInternalState<T extends StateName = StateName> {\n\tcontroller: AbortController\n\tfailureCause: unknown\n\tfailureRate: number\n\thistory: HistoryMap\n\tstatus: T\n}\n\nfunction createState(\n\tstatus: StateName,\n\tfailureCause?: unknown,\n): CircuitInternalState {\n\tconst controller = new AbortController()\n\treturn {\n\t\tcontroller,\n\t\tfailureCause,\n\t\tfailureRate: 0,\n\t\thistory: new Map(),\n\t\tstatus,\n\t}\n}\n\n/**\n * Creates a circuit breaker that wraps an async function with failure tracking\n * and automatic fallback behavior.\n *\n * The circuit breaker operates in four states:\n *\n * - `closed`: Normal operation, tracks failures in a sliding window\n * - `open`: Failed state, fallback is used until `resetAfter` milliseconds\n * - `halfOpen`: Testing recovery, allows trial calls\n * - `disposed`: Terminal state, all calls rejected\n *\n * When the failure rate exceeds `errorThreshold` within the `errorWindow`, the\n * circuit opens and rejects calls (using fallback if provided) for `resetAfter`\n * milliseconds. After this period, it transitions to half-open and allows up\n * to `minimumCandidates` concurrent trial calls. If their failure rate stays\n * at or below the threshold, the circuit closes; otherwise it reopens.\n *\n * @example\n * ```ts\n * const protectedFn = createCircuitBreaker(unreliableApiCall, {\n * errorThreshold: 0.5,\n * errorWindow: 10_000,\n * resetAfter: 30_000,\n * fallback: () => cachedResponse,\n * })\n *\n * try {\n * const result = await protectedFn(arg1, arg2)\n * } catch (error) {\n * console.error('Circuit breaker rejected call:', error)\n * }\n *\n * console.log(protectedFn.getState()) // 'closed' | 'open' | 'halfOpen' | 'disposed'\n * protectedFn[Symbol.dispose]() // Clean up timers and resources\n * ```\n */\nexport function createCircuitBreaker<Ret, Args extends unknown[]>(\n\tmain: MainFn<Ret, Args>,\n\toptions: CircuitBreakerOptions<MainFn<Ret, Args>> = {},\n): CircuitBreakerProtectedFn<Ret, Args> {\n\tconst {\n\t\terrorIsTransient,\n\t\terrorThreshold,\n\t\terrorWindow,\n\t\tfallback,\n\t\tminimumCandidates,\n\t\tonClose,\n\t\tonHalfOpen,\n\t\tonOpen,\n\t\tresetAfter,\n\t\tretryDelay,\n\t\tretryLimit,\n\t\tretryTest,\n\t\ttimeout,\n\t} = parseOptions(options)\n\n\tlet state = createState(\"closed\")\n\n\tasync function tryCall(\n\t\tcurrent: CircuitInternalState,\n\t\targs: Args,\n\t): Promise<Ret> {\n\t\tconst { history } = current\n\t\tconst request = promiseTry(() => main(...args))\n\n\t\tlet historyItem: HistoryEntry | undefined = { status: \"pending\" }\n\t\thistory.set(request, historyItem)\n\n\t\ttry {\n\t\t\tconst result =\n\t\t\t\ttimeout > 0\n\t\t\t\t\t? await abortable(AbortSignal.timeout(timeout), request)\n\t\t\t\t\t: await request\n\t\t\thistoryItem.status = \"resolved\"\n\t\t\treturn result\n\t\t} catch (cause) {\n\t\t\thistoryItem.status = \"rejected\"\n\t\t\t// Drop this request if it's a transient error that shouldn't count\n\t\t\t// towards the failure rate\n\t\t\tconst isTransient = errorIsTransient(cause)\n\t\t\tif (isTransient) historyItem = undefined\n\n\t\t\t// Wrap the error in a CircuitError to provide additional context and\n\t\t\t// control flow handling.\n\t\t\tthrow new CircuitError(\"CALL_FAILURE\", { cause, isTransient })\n\t\t} finally {\n\t\t\t// Remove the request if it was a transient failure, or if it's stale.\n\t\t\tif (!historyItem || state !== current) history.delete(request)\n\t\t\t// Keep the request in history until the end of the error window, or until\n\t\t\t// the circuit transitions.\n\t\t\telse {\n\t\t\t\tconst { signal } = current.controller\n\t\t\t\tdelayMs(errorWindow, signal)\n\t\t\t\t\t.catch(() => {})\n\t\t\t\t\t.finally(() => history.delete(request))\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction calculateFailureRate(): number {\n\t\tlet failures = 0\n\t\tlet total = 0\n\t\tfor (const { status } of state.history.values()) {\n\t\t\tif (status === \"rejected\") failures++\n\t\t\tif (status !== \"pending\") total++\n\t\t}\n\t\tif (!total || total < minimumCandidates) return 0\n\t\treturn failures / total\n\t}\n\n\tfunction transitionTo(\n\t\ttoStatus: StateName,\n\t\tfailureCause?: unknown,\n\t): CircuitInternalState {\n\t\tassertTransition(state.status, toStatus)\n\t\tstate.controller.abort()\n\t\treturn (state = createState(toStatus, failureCause))\n\t}\n\n\tasync function transitionToOpen(error: CircuitError): Promise<void> {\n\t\t// Race guard: a concurrent failure may have already changed state.\n\t\tif (state.status !== \"closed\" && state.status !== \"halfOpen\") return\n\n\t\tconst cause = error.cause ?? error\n\t\tconst nextState = transitionTo(\"open\", cause)\n\t\tif (onOpen) setImmediate(onOpen, cause)\n\n\t\tconst { signal } = nextState.controller\n\t\tawait delayMs(resetAfter, signal)\n\t\tif (state === nextState) transitionToHalfOpen()\n\t}\n\n\tfunction transitionToHalfOpen(): void {\n\t\ttransitionTo(\"halfOpen\", state.failureCause)\n\t\tif (onHalfOpen) setImmediate(onHalfOpen)\n\t}\n\n\tfunction transitionToClosed(): void {\n\t\ttransitionTo(\"closed\")\n\t\tif (onClose) setImmediate(onClose)\n\t}\n\n\tfunction guardIsCurrent(\n\t\tcurrent: CircuitInternalState,\n\t\terror: unknown,\n\t): error is CircuitError {\n\t\tif (!(error instanceof CircuitError)) throw error\n\t\t// Transient errors shouldn't affect the circuit breaker's state. Re-throw\n\t\t// the original cause of the error.\n\t\tif (error.isTransient) throw error.cause\n\n\t\t// If the circuit breaker was disposed mid-flight, surface the underlying\n\t\t// cause of the in-flight call rather than the dispose error.\n\t\tif (state.status === \"disposed\")\n\t\t\t// eslint-disable-next-line @typescript-eslint/only-throw-error\n\t\t\tthrow error.cause ?? new CircuitError(\"DISPOSED\")\n\n\t\t// If the circuit breaker transitioned states, try again.\n\t\treturn state === current\n\t}\n\n\tasync function protectedFn(...args: Args): Promise<Ret> {\n\t\tlet lastError: CircuitError | undefined\n\t\tlet retries = 0\n\t\tdo {\n\t\t\tconst current = state\n\t\t\tlastError = undefined\n\n\t\t\t// Closed: Normal Operation\n\t\t\tif (current.status === \"closed\") {\n\t\t\t\ttry {\n\t\t\t\t\treturn await tryCall(current, args)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (guardIsCurrent(current, error)) {\n\t\t\t\t\t\tlastError = error\n\t\t\t\t\t\t// Determine if the failure rate should open the circuit.\n\t\t\t\t\t\tconst rate = (current.failureRate = calculateFailureRate())\n\t\t\t\t\t\tif (rate > errorThreshold) transitionToOpen(error).catch(noop)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Half-Open: Execute trial calls until we have enough candidates.\n\t\t\telse if (\n\t\t\t\tcurrent.status === \"halfOpen\" &&\n\t\t\t\tcurrent.history.size < minimumCandidates\n\t\t\t) {\n\t\t\t\ttry {\n\t\t\t\t\treturn await tryCall(current, args)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (guardIsCurrent(current, error)) lastError = error\n\t\t\t\t\tbreak\n\t\t\t\t} finally {\n\t\t\t\t\t// Do nothing until we have enough candidates to make a decision.\n\t\t\t\t\tif (state === current && current.history.size >= minimumCandidates) {\n\t\t\t\t\t\tconst rate = (current.failureRate = calculateFailureRate())\n\t\t\t\t\t\t// Determine if the failure rate should re-open the circuit or\n\t\t\t\t\t\t// if it is healthy enough to close it again.\n\t\t\t\t\t\tif (rate > errorThreshold && lastError)\n\t\t\t\t\t\t\ttransitionToOpen(lastError).catch(noop)\n\t\t\t\t\t\telse if (rate <= errorThreshold) transitionToClosed()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Open: Skip calls and immediately return fallback if available.\n\t\t\telse if (current.status === \"open\" || current.status === \"halfOpen\") {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// Disposed: Reject all calls with dispose error.\n\t\t\telse throw current.failureCause\n\t\t} while (\n\t\t\tawait shouldContinue({\n\t\t\t\tretries: ++retries,\n\t\t\t\tlastError: lastError?.cause ?? lastError,\n\t\t\t\tretryDelay,\n\t\t\t\tretryLimit,\n\t\t\t\tretryTest,\n\t\t\t\tsignal: state.controller.signal,\n\t\t\t}).catch((error: CircuitError) => {\n\t\t\t\tlastError = error\n\t\t\t\treturn false\n\t\t\t})\n\t\t)\n\n\t\tif (!fallback) throw lastError ?? state.failureCause\n\t\treturn fallback(...args)\n\t}\n\n\tfunction dispose(disposeMessage = \"ERR_CIRCUIT_BREAKER_DISPOSED\"): void {\n\t\tif (state.status === \"disposed\") return\n\t\ttransitionTo(\"disposed\", new ReferenceError(disposeMessage))\n\t\tmain[Symbol.dispose]?.()\n\t}\n\n\tconst wrapped = protectedFn as CircuitBreakerProtectedFn<Ret, Args>\n\twrapped[Symbol.dispose] = () => dispose()\n\twrapped.dispose = dispose\n\twrapped.getFailureRate = () => state.failureRate\n\twrapped.getLatestError = () => state.failureCause\n\twrapped.getState = () => state.status\n\n\treturn wrapped\n}\n"],"names":[],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -14,13 +14,16 @@ type StateName = "closed" | "halfOpen" | "open" | "disposed";
14
14
  */
15
15
  interface CircuitBreakerOptions<Fallback extends AnyFn = AnyFn> {
16
16
  /**
17
- * Whether an error should be treated as non-retryable failure. When used and
18
- * when an error is considered a failure, the error will be thrown to the
19
- * caller and the request will *not* count tawards the error rate for circuit
20
- * breaker decisions.
17
+ * When this returns true, the error is treated as transient it will be
18
+ * thrown to the caller but will NOT count towards the circuit breaker's
19
+ * failure rate.
21
20
  *
22
21
  * @default () => false // No errors are excluded
23
22
  */
23
+ errorIsTransient?: ErrorTest;
24
+ /**
25
+ * @deprecated Use `errorIsTransient` instead.
26
+ */
24
27
  errorIsFailure?: ErrorTest;
25
28
  /**
26
29
  * The percentage of errors (as a number between 0 and 1) which must occur
@@ -104,7 +107,7 @@ interface CircuitBreakerOptions<Fallback extends AnyFn = AnyFn> {
104
107
  * If greater than zero, each call to `main` is raced against an
105
108
  * `AbortSignal.timeout` of this many milliseconds. When the timeout fires
106
109
  * first, the call rejects with the signal's reason and is counted as a
107
- * failure (subject to `errorIsFailure`).
110
+ * failure (subject to `errorIsTransient`).
108
111
  *
109
112
  * @default 0 // No per-call timeout
110
113
  */
@@ -139,69 +142,6 @@ interface MainFn<Ret = unknown, Args extends readonly unknown[] = never[]> {
139
142
  interface RetryDelayFn {
140
143
  (attempt: number, signal?: AbortSignal): Promise<void>;
141
144
  }
142
- /**
143
- * Configuration options for retry behavior.
144
- */
145
- interface RetryOptions {
146
- /**
147
- * Whether an error should be treated as non-retryable. When this returns
148
- * true, the error will be thrown immediately without retrying.
149
- *
150
- * @default () => true // All errors are retried
151
- */
152
- shouldRetry?: (error: unknown, attempt: number) => boolean;
153
- /**
154
- * Maximum number of retries
155
- *
156
- * @default 3
157
- */
158
- maxAttempts?: number;
159
- /**
160
- * Function that returns a promise resolving when the next retry should occur.
161
- * Receives the attempt number (starting at 2) and an abort signal.
162
- *
163
- * @default () => Promise.resolve() // Immediate retry
164
- */
165
- retryDelay?: RetryDelayFn;
166
- }
167
-
168
- /**
169
- * Wrap a function with retry logic. Errors will be retried according to the
170
- * provided options.
171
- *
172
- * @example
173
- * ```ts
174
- * // Compose with circuit breaker. Retry up to 3 times with no delay
175
- * const protectedA = createCircuitBreaker(
176
- * withRetry(unreliableApiCall, { maxAttempts: 3 })
177
- * )
178
- *
179
- * // Retry up to 5 times with exponential backoff
180
- * const protectedB = createCircuitBreaker(
181
- * withRetry(unreliableApiCall, {
182
- * maxAttempts: 5,
183
- * retryDelay: useExponentialBackoff(30),
184
- * })
185
- * )
186
- * ```
187
- */
188
- declare function withRetry$1<Ret, Args extends readonly unknown[]>(main: MainFn<Ret, Args>, options?: Readonly<RetryOptions>): MainFn<Ret, Args> & Disposable;
189
-
190
- /**
191
- * Wraps an async function with a timeout constraint. Rejects with an Error if
192
- * execution exceeds the specified timeout.
193
- *
194
- * @example
195
- * ```ts
196
- * const fetchWithTimeout = withTimeout(fetchData, 5000, "Fetch timed out")
197
- * try {
198
- * const data = await fetchWithTimeout(url)
199
- * } catch (error) {
200
- * console.error(error.message) // "Fetch timed out" after 5 seconds
201
- * }
202
- * ```
203
- */
204
- declare function withTimeout$1<Ret, Args extends readonly unknown[]>(main: MainFn<Ret, Args>, timeoutMs: number, timeoutMessage?: string): MainFn<Ret, Args> & Disposable;
205
145
 
206
146
  /**
207
147
  * Creates an exponential backoff strategy for retry delays.
@@ -234,6 +174,14 @@ declare function useExponentialBackoff(maxSeconds: number): RetryDelayFn;
234
174
  */
235
175
  declare function useFibonacciBackoff(maxSeconds: number): RetryDelayFn;
236
176
 
177
+ declare class CircuitError extends Error {
178
+ isTransient: boolean;
179
+ constructor(message: string, options?: {
180
+ cause?: unknown;
181
+ isTransient?: boolean;
182
+ });
183
+ }
184
+
237
185
  /**
238
186
  * Creates a circuit breaker that wraps an async function with failure tracking
239
187
  * and automatic fallback behavior.
@@ -277,12 +225,5 @@ declare function createCircuitBreaker<Ret, Args extends unknown[]>(main: MainFn<
277
225
  */
278
226
  declare const delayMs: (ms: number, signal?: AbortSignal) => Promise<void>;
279
227
 
280
- /** @deprecated Use `StateName` instead. */
281
- type CircuitState = StateName;
282
- /** @deprecated Use `retryLimit`, `retryDelay`, and `retryTest` options on `createCircuitBreaker` instead. */
283
- declare const withRetry: typeof withRetry$1;
284
- /** @deprecated Use `options.timeout` on `createCircuitBreaker` instead. */
285
- declare const withTimeout: typeof withTimeout$1;
286
-
287
- export { createCircuitBreaker, delayMs, useExponentialBackoff, useFibonacciBackoff, withRetry, withTimeout };
288
- export type { CircuitBreakerOptions, CircuitBreakerProtectedFn, CircuitState, MainFn, RetryOptions, StateName };
228
+ export { CircuitError, createCircuitBreaker, delayMs, useExponentialBackoff, useFibonacciBackoff };
229
+ export type { CircuitBreakerOptions, CircuitBreakerProtectedFn, MainFn, StateName };
package/dist/index.d.mts CHANGED
@@ -14,13 +14,16 @@ type StateName = "closed" | "halfOpen" | "open" | "disposed";
14
14
  */
15
15
  interface CircuitBreakerOptions<Fallback extends AnyFn = AnyFn> {
16
16
  /**
17
- * Whether an error should be treated as non-retryable failure. When used and
18
- * when an error is considered a failure, the error will be thrown to the
19
- * caller and the request will *not* count tawards the error rate for circuit
20
- * breaker decisions.
17
+ * When this returns true, the error is treated as transient it will be
18
+ * thrown to the caller but will NOT count towards the circuit breaker's
19
+ * failure rate.
21
20
  *
22
21
  * @default () => false // No errors are excluded
23
22
  */
23
+ errorIsTransient?: ErrorTest;
24
+ /**
25
+ * @deprecated Use `errorIsTransient` instead.
26
+ */
24
27
  errorIsFailure?: ErrorTest;
25
28
  /**
26
29
  * The percentage of errors (as a number between 0 and 1) which must occur
@@ -104,7 +107,7 @@ interface CircuitBreakerOptions<Fallback extends AnyFn = AnyFn> {
104
107
  * If greater than zero, each call to `main` is raced against an
105
108
  * `AbortSignal.timeout` of this many milliseconds. When the timeout fires
106
109
  * first, the call rejects with the signal's reason and is counted as a
107
- * failure (subject to `errorIsFailure`).
110
+ * failure (subject to `errorIsTransient`).
108
111
  *
109
112
  * @default 0 // No per-call timeout
110
113
  */
@@ -139,69 +142,6 @@ interface MainFn<Ret = unknown, Args extends readonly unknown[] = never[]> {
139
142
  interface RetryDelayFn {
140
143
  (attempt: number, signal?: AbortSignal): Promise<void>;
141
144
  }
142
- /**
143
- * Configuration options for retry behavior.
144
- */
145
- interface RetryOptions {
146
- /**
147
- * Whether an error should be treated as non-retryable. When this returns
148
- * true, the error will be thrown immediately without retrying.
149
- *
150
- * @default () => true // All errors are retried
151
- */
152
- shouldRetry?: (error: unknown, attempt: number) => boolean;
153
- /**
154
- * Maximum number of retries
155
- *
156
- * @default 3
157
- */
158
- maxAttempts?: number;
159
- /**
160
- * Function that returns a promise resolving when the next retry should occur.
161
- * Receives the attempt number (starting at 2) and an abort signal.
162
- *
163
- * @default () => Promise.resolve() // Immediate retry
164
- */
165
- retryDelay?: RetryDelayFn;
166
- }
167
-
168
- /**
169
- * Wrap a function with retry logic. Errors will be retried according to the
170
- * provided options.
171
- *
172
- * @example
173
- * ```ts
174
- * // Compose with circuit breaker. Retry up to 3 times with no delay
175
- * const protectedA = createCircuitBreaker(
176
- * withRetry(unreliableApiCall, { maxAttempts: 3 })
177
- * )
178
- *
179
- * // Retry up to 5 times with exponential backoff
180
- * const protectedB = createCircuitBreaker(
181
- * withRetry(unreliableApiCall, {
182
- * maxAttempts: 5,
183
- * retryDelay: useExponentialBackoff(30),
184
- * })
185
- * )
186
- * ```
187
- */
188
- declare function withRetry$1<Ret, Args extends readonly unknown[]>(main: MainFn<Ret, Args>, options?: Readonly<RetryOptions>): MainFn<Ret, Args> & Disposable;
189
-
190
- /**
191
- * Wraps an async function with a timeout constraint. Rejects with an Error if
192
- * execution exceeds the specified timeout.
193
- *
194
- * @example
195
- * ```ts
196
- * const fetchWithTimeout = withTimeout(fetchData, 5000, "Fetch timed out")
197
- * try {
198
- * const data = await fetchWithTimeout(url)
199
- * } catch (error) {
200
- * console.error(error.message) // "Fetch timed out" after 5 seconds
201
- * }
202
- * ```
203
- */
204
- declare function withTimeout$1<Ret, Args extends readonly unknown[]>(main: MainFn<Ret, Args>, timeoutMs: number, timeoutMessage?: string): MainFn<Ret, Args> & Disposable;
205
145
 
206
146
  /**
207
147
  * Creates an exponential backoff strategy for retry delays.
@@ -234,6 +174,14 @@ declare function useExponentialBackoff(maxSeconds: number): RetryDelayFn;
234
174
  */
235
175
  declare function useFibonacciBackoff(maxSeconds: number): RetryDelayFn;
236
176
 
177
+ declare class CircuitError extends Error {
178
+ isTransient: boolean;
179
+ constructor(message: string, options?: {
180
+ cause?: unknown;
181
+ isTransient?: boolean;
182
+ });
183
+ }
184
+
237
185
  /**
238
186
  * Creates a circuit breaker that wraps an async function with failure tracking
239
187
  * and automatic fallback behavior.
@@ -277,12 +225,5 @@ declare function createCircuitBreaker<Ret, Args extends unknown[]>(main: MainFn<
277
225
  */
278
226
  declare const delayMs: (ms: number, signal?: AbortSignal) => Promise<void>;
279
227
 
280
- /** @deprecated Use `StateName` instead. */
281
- type CircuitState = StateName;
282
- /** @deprecated Use `retryLimit`, `retryDelay`, and `retryTest` options on `createCircuitBreaker` instead. */
283
- declare const withRetry: typeof withRetry$1;
284
- /** @deprecated Use `options.timeout` on `createCircuitBreaker` instead. */
285
- declare const withTimeout: typeof withTimeout$1;
286
-
287
- export { createCircuitBreaker, delayMs, useExponentialBackoff, useFibonacciBackoff, withRetry, withTimeout };
288
- export type { CircuitBreakerOptions, CircuitBreakerProtectedFn, CircuitState, MainFn, RetryOptions, StateName };
228
+ export { CircuitError, createCircuitBreaker, delayMs, useExponentialBackoff, useFibonacciBackoff };
229
+ export type { CircuitBreakerOptions, CircuitBreakerProtectedFn, MainFn, StateName };
package/dist/index.mjs CHANGED
@@ -26,16 +26,6 @@ const delayMs = (ms, signal) => {
26
26
  signal.addEventListener("abort", onAbort, { once: true });
27
27
  }) : new Promise((next) => setTimeout(next, ms));
28
28
  };
29
- const deprecated = (fn, method, message) => {
30
- let warned = false;
31
- return ((...args) => {
32
- if (!warned) {
33
- console.warn(`[breaker-box] ${method} Deprecation: ${message}`);
34
- warned = true;
35
- }
36
- return fn(...args);
37
- });
38
- };
39
29
  const noop = () => {
40
30
  };
41
31
  function promiseTry(fn) {
@@ -45,64 +35,6 @@ function promiseTry(fn) {
45
35
  return Promise.reject(error);
46
36
  }
47
37
  }
48
- async function shouldRetry(options) {
49
- const { retries, lastError, retryDelay, retryLimit, retryTest, signal } = options;
50
- if (retries >= retryLimit) throw lastError;
51
- if (!retryTest(lastError)) throw lastError;
52
- try {
53
- if (!retryDelay) return true;
54
- else if (typeof retryDelay === "number") await delayMs(retryDelay, signal);
55
- else if (typeof retryDelay === "function") await retryDelay(retries, signal);
56
- } catch {
57
- }
58
- return true;
59
- }
60
-
61
- function withRetry$1(main, options = {}) {
62
- const {
63
- shouldRetry = () => true,
64
- maxAttempts = 3,
65
- retryDelay = () => Promise.resolve()
66
- } = options;
67
- assert(maxAttempts >= 1, "maxAttempts must be a number greater than 0");
68
- const controller = new AbortController();
69
- const { signal } = controller;
70
- async function withRetryFunction(...args) {
71
- let attempt = 1;
72
- while (true) {
73
- try {
74
- return await main(...args);
75
- } catch (cause) {
76
- if (attempt >= maxAttempts) {
77
- throw new Error(`ERR_CIRCUIT_BREAKER_MAX_ATTEMPTS (${maxAttempts})`, {
78
- cause
79
- });
80
- }
81
- if (!shouldRetry(cause, attempt)) throw cause;
82
- }
83
- attempt++;
84
- await abortable(signal, retryDelay(attempt, signal));
85
- }
86
- }
87
- return Object.assign(withRetryFunction, {
88
- [Symbol.dispose]: () => controller.abort()
89
- });
90
- }
91
-
92
- function withTimeout$1(main, timeoutMs, timeoutMessage = "ERR_CIRCUIT_BREAKER_TIMEOUT") {
93
- const error = new Error(timeoutMessage);
94
- const controller = new AbortController();
95
- const { signal } = controller;
96
- function withTimeoutFunction(...args) {
97
- return new Promise((resolve, reject) => {
98
- const timer = setTimeout(reject, timeoutMs, error);
99
- abortable(signal, main(...args)).then(resolve, reject).finally(() => clearTimeout(timer));
100
- });
101
- }
102
- return Object.assign(withTimeoutFunction, {
103
- [Symbol.dispose]: () => controller.abort()
104
- });
105
- }
106
38
 
107
39
  function useExponentialBackoff(maxSeconds) {
108
40
  return function exponentialBackoff(attempt, signal) {
@@ -120,9 +52,18 @@ function useFibonacciBackoff(maxSeconds) {
120
52
  };
121
53
  }
122
54
 
55
+ class CircuitError extends Error {
56
+ isTransient;
57
+ constructor(message, options) {
58
+ super(`ERR_CIRCUIT_BREAKER_${message}`, options);
59
+ this.isTransient = options?.isTransient ?? false;
60
+ }
61
+ }
62
+
63
+ let warnedErrorIsFailure = false;
123
64
  function parseOptions(options) {
124
65
  const {
125
- errorIsFailure = () => false,
66
+ errorIsTransient = options.errorIsFailure ?? (() => false),
126
67
  errorThreshold = 0,
127
68
  errorWindow = 1e4,
128
69
  fallback,
@@ -136,9 +77,15 @@ function parseOptions(options) {
136
77
  retryTest = () => true,
137
78
  timeout = 0
138
79
  } = options;
80
+ if ("errorIsFailure" in options && !("errorIsTransient" in options) && !warnedErrorIsFailure) {
81
+ warnedErrorIsFailure = true;
82
+ console.warn(
83
+ 'breaker-box: "errorIsFailure" is deprecated. Use "errorIsTransient" instead.'
84
+ );
85
+ }
139
86
  assert(
140
- typeof errorIsFailure === "function",
141
- `"errorIsFailure" must be a function (received ${typeof errorIsFailure})`
87
+ typeof errorIsTransient === "function",
88
+ `"errorIsTransient" must be a function (received ${typeof errorIsTransient})`
142
89
  );
143
90
  assert(
144
91
  errorThreshold >= 0 && errorThreshold <= 1,
@@ -193,7 +140,7 @@ function parseOptions(options) {
193
140
  `"timeout" must be a finite, non-negative number (received ${timeout})`
194
141
  );
195
142
  return {
196
- errorIsFailure,
143
+ errorIsTransient,
197
144
  errorThreshold,
198
145
  errorWindow,
199
146
  fallback,
@@ -209,6 +156,20 @@ function parseOptions(options) {
209
156
  };
210
157
  }
211
158
 
159
+ async function shouldContinue(options) {
160
+ const { retries, lastError, retryDelay, retryLimit, retryTest, signal } = options;
161
+ if (retries >= retryLimit)
162
+ throw new CircuitError("MAX_RETRIES", { cause: lastError });
163
+ if (!retryTest(lastError))
164
+ throw new CircuitError("NON_RETRYABLE", { cause: lastError });
165
+ try {
166
+ if (!retryDelay) return true;
167
+ else if (typeof retryDelay === "number") await delayMs(retryDelay, signal);
168
+ else if (typeof retryDelay === "function") await retryDelay(retries, signal);
169
+ } catch {
170
+ }
171
+ return true;
172
+ }
212
173
  const validTransitions = {
213
174
  closed: ["open", "disposed"],
214
175
  open: ["halfOpen", "disposed"],
@@ -221,13 +182,6 @@ function assertTransition(from, to) {
221
182
  `Invalid transition from ${from} to ${to}`
222
183
  );
223
184
  }
224
- class CircuitError extends Error {
225
- isTransient;
226
- constructor(message, options) {
227
- super(`ERR_CIRCUIT_BREAKER_${message}`, options);
228
- this.isTransient = options?.isTransient ?? false;
229
- }
230
- }
231
185
  function createState(status, failureCause) {
232
186
  const controller = new AbortController();
233
187
  return {
@@ -240,7 +194,7 @@ function createState(status, failureCause) {
240
194
  }
241
195
  function createCircuitBreaker(main, options = {}) {
242
196
  const {
243
- errorIsFailure,
197
+ errorIsTransient,
244
198
  errorThreshold,
245
199
  errorWindow,
246
200
  fallback,
@@ -266,7 +220,7 @@ function createCircuitBreaker(main, options = {}) {
266
220
  return result;
267
221
  } catch (cause) {
268
222
  historyItem.status = "rejected";
269
- const isTransient = errorIsFailure(cause);
223
+ const isTransient = errorIsTransient(cause);
270
224
  if (isTransient) historyItem = void 0;
271
225
  throw new CircuitError("CALL_FAILURE", { cause, isTransient });
272
226
  } finally {
@@ -303,7 +257,7 @@ function createCircuitBreaker(main, options = {}) {
303
257
  if (state === nextState) transitionToHalfOpen();
304
258
  }
305
259
  function transitionToHalfOpen() {
306
- transitionTo("halfOpen");
260
+ transitionTo("halfOpen", state.failureCause);
307
261
  if (onHalfOpen) setImmediate(onHalfOpen);
308
262
  }
309
263
  function transitionToClosed() {
@@ -322,6 +276,7 @@ function createCircuitBreaker(main, options = {}) {
322
276
  let retries = 0;
323
277
  do {
324
278
  const current = state;
279
+ lastError = void 0;
325
280
  if (current.status === "closed") {
326
281
  try {
327
282
  return await tryCall(current, args);
@@ -337,6 +292,7 @@ function createCircuitBreaker(main, options = {}) {
337
292
  return await tryCall(current, args);
338
293
  } catch (error) {
339
294
  if (guardIsCurrent(current, error)) lastError = error;
295
+ break;
340
296
  } finally {
341
297
  if (state === current && current.history.size >= minimumCandidates) {
342
298
  const rate = current.failureRate = calculateFailureRate();
@@ -346,23 +302,21 @@ function createCircuitBreaker(main, options = {}) {
346
302
  }
347
303
  }
348
304
  } else if (current.status === "open" || current.status === "halfOpen") {
349
- if (!fallback) {
350
- throw (
351
- // eslint-disable-next-line @typescript-eslint/only-throw-error
352
- current.failureCause ?? new CircuitError("OPEN", { cause: current.failureCause })
353
- );
354
- }
355
- return await fallback(...args);
305
+ break;
356
306
  } else throw current.failureCause;
357
- } while (await shouldRetry({
307
+ } while (await shouldContinue({
358
308
  retries: ++retries,
359
- lastError,
309
+ lastError: lastError?.cause ?? lastError,
360
310
  retryDelay,
361
311
  retryLimit,
362
312
  retryTest,
363
313
  signal: state.controller.signal
314
+ }).catch((error) => {
315
+ lastError = error;
316
+ return false;
364
317
  }));
365
- throw new Error("unknown error in circuit breaker retry logic");
318
+ if (!fallback) throw lastError ?? state.failureCause;
319
+ return fallback(...args);
366
320
  }
367
321
  function dispose(disposeMessage = "ERR_CIRCUIT_BREAKER_DISPOSED") {
368
322
  if (state.status === "disposed") return;
@@ -378,16 +332,5 @@ function createCircuitBreaker(main, options = {}) {
378
332
  return wrapped;
379
333
  }
380
334
 
381
- const withRetry = deprecated(
382
- withRetry$1,
383
- "withRetry",
384
- "Use `retryLimit`, `retryDelay`, and `retryTest` options on `createCircuitBreaker` instead."
385
- );
386
- const withTimeout = deprecated(
387
- withTimeout$1,
388
- "withTimeout",
389
- "Use `options.timeout` on`createCircuitBreaker` instead."
390
- );
391
-
392
- export { createCircuitBreaker, delayMs, useExponentialBackoff, useFibonacciBackoff, withRetry, withTimeout };
335
+ export { CircuitError, createCircuitBreaker, delayMs, useExponentialBackoff, useFibonacciBackoff };
393
336
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../lib/util.ts","../lib/retry.ts","../lib/timeout.ts","../lib/backoff.ts","../lib/options.ts","../lib/circuit-breaker.ts","../lib/index.ts"],"sourcesContent":["import type { AnyFn, RetryDelayFn } from \"./types.js\"\n\n/**\n * Returns a promise which rejects when the abort signal is triggered or\n * resolves when the promise is fulfilled.\n */\nexport const abortable = <T>(\n\tsignal: AbortSignal,\n\tpending: PromiseLike<T>,\n): Promise<T> =>\n\tnew Promise((resolve, reject) => {\n\t\tsignal.throwIfAborted()\n\n\t\tconst onAbort = () => reject(signal.reason)\n\t\tsignal.addEventListener(\"abort\", onAbort, { once: true })\n\n\t\tPromise.resolve(pending)\n\t\t\t.finally(() => signal.removeEventListener(\"abort\", onAbort))\n\t\t\t.then(resolve, reject)\n\t})\n\n/**\n * Asserts that the given value is truthy. If not, throws a `TypeError`.\n */\nexport function assert(value: unknown, message?: string): asserts value {\n\tif (!value) throw new TypeError(message)\n}\n\n/**\n * Returns a promise that resolves after the specified number of milliseconds.\n */\nexport const delayMs = (ms: number, signal?: AbortSignal): Promise<void> => {\n\tif (!Number.isFinite(ms) || ms < 0) {\n\t\tthrow new RangeError(\n\t\t\t`\"ms\" must be a finite, non-negative number (received ${ms})`,\n\t\t)\n\t}\n\n\treturn signal\n\t\t? new Promise((resolve, reject) => {\n\t\t\t\tsignal.throwIfAborted()\n\n\t\t\t\tconst timer = setTimeout(() => {\n\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort)\n\t\t\t\t\tresolve()\n\t\t\t\t}, ms)\n\n\t\t\t\tconst onAbort = () => {\n\t\t\t\t\tclearTimeout(timer)\n\t\t\t\t\treject(signal.reason)\n\t\t\t\t}\n\n\t\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true })\n\t\t\t})\n\t\t: new Promise((next) => setTimeout(next, ms))\n}\n\nexport const deprecated = <T extends AnyFn>(\n\tfn: T,\n\tmethod: string,\n\tmessage: string,\n): T => {\n\tlet warned = false\n\treturn ((...args) => {\n\t\tif (!warned) {\n\t\t\tconsole.warn(`[breaker-box] ${method} Deprecation: ${message}`)\n\t\t\twarned = true\n\t\t}\n\t\treturn fn(...args)\n\t}) as T\n}\n\nexport const identity = <T>(value: T): T => value\n\nexport const noop: (...args: unknown[]) => void = () => {}\n\n/**\n * Polyfill for `Promise.try()`\n */\nexport function promiseTry<T>(fn: () => T): Promise<T> {\n\ttry {\n\t\treturn Promise.resolve(fn())\n\t} catch (error) {\n\t\treturn Promise.reject(error)\n\t}\n}\n\nexport async function shouldRetry(options: {\n\tretries: number\n\tlastError: unknown\n\tretryDelay: number | RetryDelayFn\n\tretryLimit: number\n\tretryTest: (error: unknown) => boolean\n\tsignal: AbortSignal\n}): Promise<true> {\n\tconst { retries, lastError, retryDelay, retryLimit, retryTest, signal } =\n\t\toptions\n\n\tif (retries >= retryLimit) throw lastError\n\tif (!retryTest(lastError)) throw lastError\n\n\ttry {\n\t\tif (!retryDelay) return true\n\t\telse if (typeof retryDelay === \"number\") await delayMs(retryDelay, signal)\n\t\telse if (typeof retryDelay === \"function\") await retryDelay(retries, signal)\n\t} catch {\n\t\t/* empty */\n\t}\n\n\treturn true\n}\n","import { type MainFn, type RetryOptions } from \"./types.js\"\nimport { assert, abortable } from \"./util.js\"\n\n/**\n * Wrap a function with retry logic. Errors will be retried according to the\n * provided options.\n *\n * @example\n * ```ts\n * // Compose with circuit breaker. Retry up to 3 times with no delay\n * const protectedA = createCircuitBreaker(\n * withRetry(unreliableApiCall, { maxAttempts: 3 })\n * )\n *\n * // Retry up to 5 times with exponential backoff\n * const protectedB = createCircuitBreaker(\n * withRetry(unreliableApiCall, {\n * maxAttempts: 5,\n * retryDelay: useExponentialBackoff(30),\n * })\n * )\n * ```\n */\nexport function withRetry<Ret, Args extends readonly unknown[]>(\n\tmain: MainFn<Ret, Args>,\n\toptions: Readonly<RetryOptions> = {},\n): MainFn<Ret, Args> & Disposable {\n\tconst {\n\t\tshouldRetry = () => true,\n\t\tmaxAttempts = 3,\n\t\tretryDelay = () => Promise.resolve(),\n\t} = options\n\n\tassert(maxAttempts >= 1, \"maxAttempts must be a number greater than 0\")\n\n\tconst controller = new AbortController()\n\tconst { signal } = controller\n\n\tasync function withRetryFunction(...args: Args): Promise<Ret> {\n\t\tlet attempt = 1\n\t\twhile (true) {\n\t\t\ttry {\n\t\t\t\treturn await main(...args)\n\t\t\t} catch (cause) {\n\t\t\t\tif (attempt >= maxAttempts) {\n\t\t\t\t\tthrow new Error(`ERR_CIRCUIT_BREAKER_MAX_ATTEMPTS (${maxAttempts})`, {\n\t\t\t\t\t\tcause,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tif (!shouldRetry(cause, attempt)) throw cause\n\t\t\t}\n\n\t\t\tattempt++\n\t\t\tawait abortable(signal, retryDelay(attempt, signal))\n\t\t}\n\t}\n\n\treturn Object.assign(withRetryFunction, {\n\t\t[Symbol.dispose]: () => controller.abort(),\n\t})\n}\n","import { type MainFn } from \"./types.js\"\nimport { abortable } from \"./util.js\"\n\n/**\n * Wraps an async function with a timeout constraint. Rejects with an Error if\n * execution exceeds the specified timeout.\n *\n * @example\n * ```ts\n * const fetchWithTimeout = withTimeout(fetchData, 5000, \"Fetch timed out\")\n * try {\n * const data = await fetchWithTimeout(url)\n * } catch (error) {\n * console.error(error.message) // \"Fetch timed out\" after 5 seconds\n * }\n * ```\n */\nexport function withTimeout<Ret, Args extends readonly unknown[]>(\n\tmain: MainFn<Ret, Args>,\n\ttimeoutMs: number,\n\ttimeoutMessage = \"ERR_CIRCUIT_BREAKER_TIMEOUT\",\n): MainFn<Ret, Args> & Disposable {\n\tconst error = new Error(timeoutMessage)\n\tconst controller = new AbortController()\n\tconst { signal } = controller\n\n\tfunction withTimeoutFunction(...args: Args): Promise<Ret> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timer = setTimeout(reject, timeoutMs, error)\n\n\t\t\tabortable(signal, main(...args))\n\t\t\t\t.then(resolve, reject)\n\t\t\t\t.finally(() => clearTimeout(timer))\n\t\t})\n\t}\n\n\treturn Object.assign(withTimeoutFunction, {\n\t\t[Symbol.dispose]: () => controller.abort(),\n\t})\n}\n","import type { RetryDelayFn } from \"./types.js\"\nimport { delayMs } from \"./util.js\"\n\n/**\n * Creates an exponential backoff strategy for retry delays.\n * Delay grows as 2^(attempt-2) seconds, capped at maxSeconds.\n *\n * The sequence is: 1s, 2s, 4s, 8s, 16s, 32s, etc.\n *\n * @example\n * ```ts\n * const backoff = useExponentialBackoff(30)\n * await backoff(2) // waits 1 second\n * await backoff(3) // waits 2 seconds\n * await backoff(10) // waits 30 seconds (capped)\n * ```\n */\nexport function useExponentialBackoff(maxSeconds: number): RetryDelayFn {\n\treturn function exponentialBackoff(attempt, signal) {\n\t\tconst num = Math.max(attempt - 2, 0)\n\t\tconst delay = Math.min(2 ** num, maxSeconds)\n\t\treturn delayMs(delay * 1_000, signal)\n\t}\n}\n\nconst sqrt5 = /* @__PURE__ */ Math.sqrt(5)\n/**\n * Binet's formula for calculating Fibonacci numbers in constant time.\n * @see https://en.wikipedia.org/wiki/Fibonacci_sequence#Closed-form_expression\n */\nconst binet = (n: number) =>\n\tMath.round(((1 + sqrt5) ** n - (1 - sqrt5) ** n) / (2 ** n * sqrt5))\n\n/**\n * Creates a Fibonacci backoff strategy for retry delays. It is more gradual\n * than exponential backoff, useful for more aggressive retry patterns.\n *\n * The sequence is: 1s, 2s, 3s, 5s, 8s, 13s, etc.\n *\n * @example\n * ```ts\n * const backoff = useFibonacciBackoff(60)\n * await backoff(2) // waits 1 second\n * await backoff(5) // waits 5 seconds\n * await backoff(10) // waits 55 seconds\n * ```\n */\nexport function useFibonacciBackoff(maxSeconds: number): RetryDelayFn {\n\treturn function fibonacciBackoff(attempt, signal) {\n\t\tconst delay = Math.min(binet(attempt), maxSeconds)\n\t\treturn delayMs(delay * 1_000, signal)\n\t}\n}\n","import type { AnyFn, CircuitBreakerOptions } from \"./types.js\"\nimport { assert } from \"./util.js\"\n\nexport function parseOptions<Fallback extends AnyFn>(\n\toptions: CircuitBreakerOptions<Fallback>,\n) {\n\tconst {\n\t\terrorIsFailure = () => false,\n\t\terrorThreshold = 0,\n\t\terrorWindow = 10_000,\n\t\tfallback,\n\t\tminimumCandidates = 1,\n\t\tonClose,\n\t\tonHalfOpen,\n\t\tonOpen,\n\t\tresetAfter = 30_000,\n\t\tretryDelay = 0,\n\t\tretryLimit = Infinity,\n\t\tretryTest = () => true,\n\t\ttimeout = 0,\n\t} = options\n\n\t// errorIsFailure\n\tassert(\n\t\ttypeof errorIsFailure === \"function\",\n\t\t`\"errorIsFailure\" must be a function (received ${typeof errorIsFailure})`,\n\t)\n\n\t// errorThreshold\n\tassert(\n\t\terrorThreshold >= 0 && errorThreshold <= 1,\n\t\t`\"errorThreshold\" must be between 0 and 1 (received ${errorThreshold})`,\n\t)\n\n\t// errorWindow\n\tassert(\n\t\terrorWindow >= 1_000,\n\t\t`\"errorWindow\" must be milliseconds of at least 1 second (received ${errorWindow})`,\n\t)\n\n\t// (optional) fallback\n\tassert(\n\t\t!fallback || typeof fallback === \"function\",\n\t\t`\"fallback\" must be a function (received ${typeof fallback})`,\n\t)\n\n\t// minimumCandidates\n\tassert(\n\t\tminimumCandidates >= 1,\n\t\t`\"minimumCandidates\" must be greater than 0 (received ${minimumCandidates})`,\n\t)\n\n\t// (optional) onClose\n\tassert(\n\t\t!onClose || typeof onClose === \"function\",\n\t\t`\"onClose\" must be a function (received ${typeof onClose})`,\n\t)\n\n\t// (optional) onHalfOpen\n\tassert(\n\t\t!onHalfOpen || typeof onHalfOpen === \"function\",\n\t\t`\"onHalfOpen\" must be a function (received ${typeof onHalfOpen})`,\n\t)\n\n\t// (optional) onOpen\n\tassert(\n\t\t!onOpen || typeof onOpen === \"function\",\n\t\t`\"onOpen\" must be a function (received ${typeof onOpen})`,\n\t)\n\n\t// resetAfter\n\tassert(\n\t\tresetAfter >= 1_000,\n\t\t`\"resetAfter\" must be milliseconds of at least 1 second (received ${resetAfter})`,\n\t)\n\tassert(\n\t\tresetAfter >= errorWindow,\n\t\t`\"resetAfter\" must be greater than or equal to \"errorWindow\" (received ${resetAfter}, expected >= ${errorWindow})`,\n\t)\n\n\t// retryDelay\n\tassert(\n\t\ttypeof retryDelay === \"function\" ||\n\t\t\t(typeof retryDelay === \"number\" &&\n\t\t\t\tretryDelay >= 0 &&\n\t\t\t\tNumber.isFinite(retryDelay)),\n\t\t`\"retryDelay\" must be a function or a finite, non-negative number (received ${typeof retryDelay})`,\n\t)\n\n\t// retryLimit\n\tassert(\n\t\ttypeof retryLimit === \"number\" && retryLimit >= 1,\n\t\t`\"retryLimit\" must be greater than 0 (received ${retryLimit})`,\n\t)\n\n\t// retryTest\n\tassert(\n\t\ttypeof retryTest === \"function\",\n\t\t`\"retryTest\" must be a function (received ${typeof retryTest})`,\n\t)\n\n\t// timeout\n\tassert(\n\t\tNumber.isFinite(timeout) && timeout >= 0,\n\t\t`\"timeout\" must be a finite, non-negative number (received ${timeout})`,\n\t)\n\n\treturn {\n\t\terrorIsFailure,\n\t\terrorThreshold,\n\t\terrorWindow,\n\t\tfallback,\n\t\tminimumCandidates,\n\t\tonClose,\n\t\tonHalfOpen,\n\t\tonOpen,\n\t\tresetAfter,\n\t\tretryDelay,\n\t\tretryLimit,\n\t\tretryTest,\n\t\ttimeout,\n\t}\n}\n","import { parseOptions } from \"./options.js\"\nimport type {\n\tCircuitBreakerOptions,\n\tCircuitBreakerProtectedFn,\n\tHistoryEntry,\n\tHistoryMap,\n\tMainFn,\n\tStateName,\n} from \"./types.js\"\nimport {\n\tabortable,\n\tassert,\n\tdelayMs,\n\tnoop,\n\tpromiseTry,\n\tshouldRetry,\n} from \"./util.js\"\n\nconst validTransitions: Record<StateName, StateName[]> = {\n\tclosed: [\"open\", \"disposed\"],\n\topen: [\"halfOpen\", \"disposed\"],\n\thalfOpen: [\"closed\", \"open\", \"disposed\"],\n\tdisposed: [],\n}\n\nfunction assertTransition(from: StateName, to: StateName): void {\n\tassert(\n\t\tvalidTransitions[from].includes(to),\n\t\t`Invalid transition from ${from} to ${to}`,\n\t)\n}\n\ninterface CircuitInternalState<T extends StateName = StateName> {\n\tcontroller: AbortController\n\tfailureCause: unknown\n\tfailureRate: number\n\thistory: HistoryMap\n\tstatus: T\n}\n\nclass CircuitError extends Error {\n\tisTransient: boolean\n\tconstructor(\n\t\tmessage: string,\n\t\toptions?: { cause?: unknown; isTransient?: boolean },\n\t) {\n\t\tsuper(`ERR_CIRCUIT_BREAKER_${message}`, options)\n\t\tthis.isTransient = options?.isTransient ?? false\n\t}\n}\n\nfunction createState(\n\tstatus: StateName,\n\tfailureCause?: unknown,\n): CircuitInternalState {\n\tconst controller = new AbortController()\n\treturn {\n\t\tcontroller,\n\t\tfailureCause,\n\t\tfailureRate: 0,\n\t\thistory: new Map(),\n\t\tstatus,\n\t}\n}\n\n/**\n * Creates a circuit breaker that wraps an async function with failure tracking\n * and automatic fallback behavior.\n *\n * The circuit breaker operates in four states:\n *\n * - `closed`: Normal operation, tracks failures in a sliding window\n * - `open`: Failed state, fallback is used until `resetAfter` milliseconds\n * - `halfOpen`: Testing recovery, allows trial calls\n * - `disposed`: Terminal state, all calls rejected\n *\n * When the failure rate exceeds `errorThreshold` within the `errorWindow`, the\n * circuit opens and rejects calls (using fallback if provided) for `resetAfter`\n * milliseconds. After this period, it transitions to half-open and allows up\n * to `minimumCandidates` concurrent trial calls. If their failure rate stays\n * at or below the threshold, the circuit closes; otherwise it reopens.\n *\n * @example\n * ```ts\n * const protectedFn = createCircuitBreaker(unreliableApiCall, {\n * errorThreshold: 0.5,\n * errorWindow: 10_000,\n * resetAfter: 30_000,\n * fallback: () => cachedResponse,\n * })\n *\n * try {\n * const result = await protectedFn(arg1, arg2)\n * } catch (error) {\n * console.error('Circuit breaker rejected call:', error)\n * }\n *\n * console.log(protectedFn.getState()) // 'closed' | 'open' | 'halfOpen' | 'disposed'\n * protectedFn[Symbol.dispose]() // Clean up timers and resources\n * ```\n */\nexport function createCircuitBreaker<Ret, Args extends unknown[]>(\n\tmain: MainFn<Ret, Args>,\n\toptions: CircuitBreakerOptions<MainFn<Ret, Args>> = {},\n): CircuitBreakerProtectedFn<Ret, Args> {\n\tconst {\n\t\terrorIsFailure,\n\t\terrorThreshold,\n\t\terrorWindow,\n\t\tfallback,\n\t\tminimumCandidates,\n\t\tonClose,\n\t\tonHalfOpen,\n\t\tonOpen,\n\t\tresetAfter,\n\t\tretryDelay,\n\t\tretryLimit,\n\t\tretryTest,\n\t\ttimeout,\n\t} = parseOptions(options)\n\n\tlet state = createState(\"closed\")\n\n\tasync function tryCall(\n\t\tcurrent: CircuitInternalState,\n\t\targs: Args,\n\t): Promise<Ret> {\n\t\tconst { history } = current\n\t\tconst request = promiseTry(() => main(...args))\n\n\t\tlet historyItem: HistoryEntry | undefined = { status: \"pending\" }\n\t\thistory.set(request, historyItem)\n\n\t\ttry {\n\t\t\tconst result =\n\t\t\t\ttimeout > 0\n\t\t\t\t\t? await abortable(AbortSignal.timeout(timeout), request)\n\t\t\t\t\t: await request\n\t\t\thistoryItem.status = \"resolved\"\n\t\t\treturn result\n\t\t} catch (cause) {\n\t\t\thistoryItem.status = \"rejected\"\n\t\t\t// Drop this request if it's a transient error that shouldn't count\n\t\t\t// towards the failure rate\n\t\t\tconst isTransient = errorIsFailure(cause)\n\t\t\tif (isTransient) historyItem = undefined\n\n\t\t\t// Wrap the error in a CircuitError to provide additional context and\n\t\t\t// control flow handling.\n\t\t\tthrow new CircuitError(\"CALL_FAILURE\", { cause, isTransient })\n\t\t} finally {\n\t\t\t// Remove the request if it was a transient failure, or if it's stale.\n\t\t\tif (!historyItem || state !== current) history.delete(request)\n\t\t\t// Keep the request in history until the end of the error window, or until\n\t\t\t// the circuit transitions.\n\t\t\telse {\n\t\t\t\tconst { signal } = current.controller\n\t\t\t\tdelayMs(errorWindow, signal)\n\t\t\t\t\t.catch(() => {})\n\t\t\t\t\t.finally(() => history.delete(request))\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction calculateFailureRate(): number {\n\t\tlet failures = 0\n\t\tlet total = 0\n\t\tfor (const { status } of state.history.values()) {\n\t\t\tif (status === \"rejected\") failures++\n\t\t\tif (status !== \"pending\") total++\n\t\t}\n\t\tif (!total || total < minimumCandidates) return 0\n\t\treturn failures / total\n\t}\n\n\tfunction transitionTo(\n\t\ttoStatus: StateName,\n\t\tfailureCause?: unknown,\n\t): CircuitInternalState {\n\t\tassertTransition(state.status, toStatus)\n\t\tstate.controller.abort()\n\t\treturn (state = createState(toStatus, failureCause))\n\t}\n\n\tasync function transitionToOpen(error: CircuitError): Promise<void> {\n\t\t// Race guard: a concurrent failure may have already changed state.\n\t\tif (state.status !== \"closed\" && state.status !== \"halfOpen\") return\n\n\t\tconst cause = error.cause ?? error\n\t\tconst nextState = transitionTo(\"open\", cause)\n\t\tif (onOpen) setImmediate(onOpen, cause)\n\n\t\tconst { signal } = nextState.controller\n\t\tawait delayMs(resetAfter, signal)\n\t\tif (state === nextState) transitionToHalfOpen()\n\t}\n\n\tfunction transitionToHalfOpen(): void {\n\t\ttransitionTo(\"halfOpen\")\n\t\tif (onHalfOpen) setImmediate(onHalfOpen)\n\t}\n\n\tfunction transitionToClosed(): void {\n\t\ttransitionTo(\"closed\")\n\t\tif (onClose) setImmediate(onClose)\n\t}\n\n\tfunction guardIsCurrent(\n\t\tcurrent: CircuitInternalState,\n\t\terror: unknown,\n\t): error is CircuitError {\n\t\tif (!(error instanceof CircuitError)) throw error\n\t\t// Transient errors shouldn't affect the circuit breaker's state. Re-throw\n\t\t// the original cause of the error.\n\t\tif (error.isTransient) throw error.cause\n\n\t\t// If the circuit breaker was disposed mid-flight, surface the underlying\n\t\t// cause of the in-flight call rather than the dispose error.\n\t\tif (state.status === \"disposed\")\n\t\t\t// eslint-disable-next-line @typescript-eslint/only-throw-error\n\t\t\tthrow error.cause ?? new CircuitError(\"DISPOSED\")\n\n\t\t// If the circuit breaker transitioned states, try again.\n\t\treturn state === current\n\t}\n\n\tasync function protectedFn(...args: Args): Promise<Ret> {\n\t\tlet lastError: CircuitError | undefined\n\t\tlet retries = 0\n\t\tdo {\n\t\t\tconst current = state\n\n\t\t\t// Closed: Normal Operation\n\t\t\tif (current.status === \"closed\") {\n\t\t\t\ttry {\n\t\t\t\t\treturn await tryCall(current, args)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (guardIsCurrent(current, error)) {\n\t\t\t\t\t\tlastError = error\n\t\t\t\t\t\t// Determine if the failure rate should open the circuit.\n\t\t\t\t\t\tconst rate = (current.failureRate = calculateFailureRate())\n\t\t\t\t\t\tif (rate > errorThreshold) transitionToOpen(error).catch(noop)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Half-Open: Execute trial calls until we have enough candidates.\n\t\t\telse if (\n\t\t\t\tcurrent.status === \"halfOpen\" &&\n\t\t\t\tcurrent.history.size < minimumCandidates\n\t\t\t) {\n\t\t\t\ttry {\n\t\t\t\t\treturn await tryCall(current, args)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (guardIsCurrent(current, error)) lastError = error\n\t\t\t\t} finally {\n\t\t\t\t\t// Do nothing until we have enough candidates to make a decision.\n\t\t\t\t\tif (state === current && current.history.size >= minimumCandidates) {\n\t\t\t\t\t\tconst rate = (current.failureRate = calculateFailureRate())\n\t\t\t\t\t\t// Determine if the failure rate should re-open the circuit or\n\t\t\t\t\t\t// if it is healthy enough to close it again.\n\t\t\t\t\t\tif (rate > errorThreshold && lastError)\n\t\t\t\t\t\t\ttransitionToOpen(lastError).catch(noop)\n\t\t\t\t\t\telse if (rate <= errorThreshold) transitionToClosed()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Open: Skip calls and immediately return fallback if available.\n\t\t\telse if (current.status === \"open\" || current.status === \"halfOpen\") {\n\t\t\t\tif (!fallback) {\n\t\t\t\t\tthrow (\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/only-throw-error\n\t\t\t\t\t\tcurrent.failureCause ??\n\t\t\t\t\t\tnew CircuitError(\"OPEN\", { cause: current.failureCause })\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\treturn await fallback(...args)\n\t\t\t}\n\n\t\t\t// Disposed: Reject all calls with dispose error.\n\t\t\telse throw current.failureCause\n\t\t} while (\n\t\t\tawait shouldRetry({\n\t\t\t\tretries: ++retries,\n\t\t\t\tlastError,\n\t\t\t\tretryDelay,\n\t\t\t\tretryLimit,\n\t\t\t\tretryTest,\n\t\t\t\tsignal: state.controller.signal,\n\t\t\t})\n\t\t)\n\t\tthrow new Error(\"unknown error in circuit breaker retry logic\")\n\t}\n\n\tfunction dispose(disposeMessage = \"ERR_CIRCUIT_BREAKER_DISPOSED\"): void {\n\t\tif (state.status === \"disposed\") return\n\t\ttransitionTo(\"disposed\", new ReferenceError(disposeMessage))\n\t\tmain[Symbol.dispose]?.()\n\t}\n\n\tconst wrapped = protectedFn as CircuitBreakerProtectedFn<Ret, Args>\n\twrapped[Symbol.dispose] = () => dispose()\n\twrapped.dispose = dispose\n\twrapped.getFailureRate = () => state.failureRate\n\twrapped.getLatestError = () => state.failureCause\n\twrapped.getState = () => state.status\n\n\treturn wrapped\n}\n","import { withRetry as internalWithRetry } from \"./retry.js\"\nimport { withTimeout as internalWithTimeout } from \"./timeout.js\"\nimport type { StateName } from \"./types.js\"\n\nexport { useExponentialBackoff, useFibonacciBackoff } from \"./backoff.js\"\nexport { createCircuitBreaker } from \"./circuit-breaker.js\"\n\nexport type {\n\tCircuitBreakerOptions,\n\tCircuitBreakerProtectedFn,\n\tMainFn,\n\tRetryOptions,\n\tStateName,\n} from \"./types.js\"\nexport { delayMs } from \"./util.js\"\n\n// =============================================================================\n// Deprecated API properties\nimport { deprecated } from \"./util.js\"\n\n/** @deprecated Use `StateName` instead. */\nexport type CircuitState = StateName\n\n/** @deprecated Use `retryLimit`, `retryDelay`, and `retryTest` options on `createCircuitBreaker` instead. */\nexport const withRetry = deprecated(\n\tinternalWithRetry,\n\t\"withRetry\",\n\t\"Use `retryLimit`, `retryDelay`, and `retryTest` options on `createCircuitBreaker` instead.\",\n)\n\n/** @deprecated Use `options.timeout` on `createCircuitBreaker` instead. */\nexport const withTimeout = deprecated(\n\tinternalWithTimeout,\n\t\"withTimeout\",\n\t\"Use `options.timeout` on`createCircuitBreaker` instead.\",\n)\n"],"names":["withRetry","withTimeout","internalWithRetry","internalWithTimeout"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../lib/util.ts","../lib/backoff.ts","../lib/circuit-error.ts","../lib/options.ts","../lib/circuit-breaker.ts"],"sourcesContent":["\n/**\n * Returns a promise which rejects when the abort signal is triggered or\n * resolves when the promise is fulfilled.\n */\nexport const abortable = <T>(\n\tsignal: AbortSignal,\n\tpending: PromiseLike<T>,\n): Promise<T> =>\n\tnew Promise((resolve, reject) => {\n\t\tsignal.throwIfAborted()\n\n\t\tconst onAbort = () => reject(signal.reason)\n\t\tsignal.addEventListener(\"abort\", onAbort, { once: true })\n\n\t\tPromise.resolve(pending)\n\t\t\t.finally(() => signal.removeEventListener(\"abort\", onAbort))\n\t\t\t.then(resolve, reject)\n\t})\n\n/**\n * Asserts that the given value is truthy. If not, throws a `TypeError`.\n */\nexport function assert(value: unknown, message?: string): asserts value {\n\tif (!value) throw new TypeError(message)\n}\n\n/**\n * Returns a promise that resolves after the specified number of milliseconds.\n */\nexport const delayMs = (ms: number, signal?: AbortSignal): Promise<void> => {\n\tif (!Number.isFinite(ms) || ms < 0) {\n\t\tthrow new RangeError(\n\t\t\t`\"ms\" must be a finite, non-negative number (received ${ms})`,\n\t\t)\n\t}\n\n\treturn signal\n\t\t? new Promise((resolve, reject) => {\n\t\t\t\tsignal.throwIfAborted()\n\n\t\t\t\tconst timer = setTimeout(() => {\n\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort)\n\t\t\t\t\tresolve()\n\t\t\t\t}, ms)\n\n\t\t\t\tconst onAbort = () => {\n\t\t\t\t\tclearTimeout(timer)\n\t\t\t\t\treject(signal.reason)\n\t\t\t\t}\n\n\t\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true })\n\t\t\t})\n\t\t: new Promise((next) => setTimeout(next, ms))\n}\n\nexport const noop: (...args: unknown[]) => void = () => {}\n\n/**\n * Polyfill for `Promise.try()`\n */\nexport function promiseTry<T>(fn: () => T): Promise<T> {\n\ttry {\n\t\treturn Promise.resolve(fn())\n\t} catch (error) {\n\t\treturn Promise.reject(error)\n\t}\n}\n\n\n","import type { RetryDelayFn } from \"./types.js\"\nimport { delayMs } from \"./util.js\"\n\n/**\n * Creates an exponential backoff strategy for retry delays.\n * Delay grows as 2^(attempt-2) seconds, capped at maxSeconds.\n *\n * The sequence is: 1s, 2s, 4s, 8s, 16s, 32s, etc.\n *\n * @example\n * ```ts\n * const backoff = useExponentialBackoff(30)\n * await backoff(2) // waits 1 second\n * await backoff(3) // waits 2 seconds\n * await backoff(10) // waits 30 seconds (capped)\n * ```\n */\nexport function useExponentialBackoff(maxSeconds: number): RetryDelayFn {\n\treturn function exponentialBackoff(attempt, signal) {\n\t\tconst num = Math.max(attempt - 2, 0)\n\t\tconst delay = Math.min(2 ** num, maxSeconds)\n\t\treturn delayMs(delay * 1_000, signal)\n\t}\n}\n\nconst sqrt5 = /* @__PURE__ */ Math.sqrt(5)\n/**\n * Binet's formula for calculating Fibonacci numbers in constant time.\n * @see https://en.wikipedia.org/wiki/Fibonacci_sequence#Closed-form_expression\n */\nconst binet = (n: number) =>\n\tMath.round(((1 + sqrt5) ** n - (1 - sqrt5) ** n) / (2 ** n * sqrt5))\n\n/**\n * Creates a Fibonacci backoff strategy for retry delays. It is more gradual\n * than exponential backoff, useful for more aggressive retry patterns.\n *\n * The sequence is: 1s, 2s, 3s, 5s, 8s, 13s, etc.\n *\n * @example\n * ```ts\n * const backoff = useFibonacciBackoff(60)\n * await backoff(2) // waits 1 second\n * await backoff(5) // waits 5 seconds\n * await backoff(10) // waits 55 seconds\n * ```\n */\nexport function useFibonacciBackoff(maxSeconds: number): RetryDelayFn {\n\treturn function fibonacciBackoff(attempt, signal) {\n\t\tconst delay = Math.min(binet(attempt), maxSeconds)\n\t\treturn delayMs(delay * 1_000, signal)\n\t}\n}\n","export class CircuitError extends Error {\n\tisTransient: boolean\n\tconstructor(\n\t\tmessage: string,\n\t\toptions?: { cause?: unknown; isTransient?: boolean },\n\t) {\n\t\tsuper(`ERR_CIRCUIT_BREAKER_${message}`, options)\n\t\tthis.isTransient = options?.isTransient ?? false\n\t}\n}\n","import type { AnyFn, CircuitBreakerOptions } from \"./types.js\"\nimport { assert } from \"./util.js\"\n\nlet warnedErrorIsFailure = false\n\nexport function parseOptions<Fallback extends AnyFn>(\n\toptions: CircuitBreakerOptions<Fallback>,\n) {\n\tconst {\n\t\terrorIsTransient = options.errorIsFailure ?? (() => false),\n\t\terrorThreshold = 0,\n\t\terrorWindow = 10_000,\n\t\tfallback,\n\t\tminimumCandidates = 1,\n\t\tonClose,\n\t\tonHalfOpen,\n\t\tonOpen,\n\t\tresetAfter = 30_000,\n\t\tretryDelay = 0,\n\t\tretryLimit = Infinity,\n\t\tretryTest = () => true,\n\t\ttimeout = 0,\n\t} = options\n\n\tif (\n\t\t\"errorIsFailure\" in options &&\n\t\t!(\"errorIsTransient\" in options) &&\n\t\t!warnedErrorIsFailure\n\t) {\n\t\twarnedErrorIsFailure = true\n\t\tconsole.warn(\n\t\t\t'breaker-box: \"errorIsFailure\" is deprecated. Use \"errorIsTransient\" instead.',\n\t\t)\n\t}\n\n\t// errorIsTransient\n\tassert(\n\t\ttypeof errorIsTransient === \"function\",\n\t\t`\"errorIsTransient\" must be a function (received ${typeof errorIsTransient})`,\n\t)\n\n\t// errorThreshold\n\tassert(\n\t\terrorThreshold >= 0 && errorThreshold <= 1,\n\t\t`\"errorThreshold\" must be between 0 and 1 (received ${errorThreshold})`,\n\t)\n\n\t// errorWindow\n\tassert(\n\t\terrorWindow >= 1_000,\n\t\t`\"errorWindow\" must be milliseconds of at least 1 second (received ${errorWindow})`,\n\t)\n\n\t// (optional) fallback\n\tassert(\n\t\t!fallback || typeof fallback === \"function\",\n\t\t`\"fallback\" must be a function (received ${typeof fallback})`,\n\t)\n\n\t// minimumCandidates\n\tassert(\n\t\tminimumCandidates >= 1,\n\t\t`\"minimumCandidates\" must be greater than 0 (received ${minimumCandidates})`,\n\t)\n\n\t// (optional) onClose\n\tassert(\n\t\t!onClose || typeof onClose === \"function\",\n\t\t`\"onClose\" must be a function (received ${typeof onClose})`,\n\t)\n\n\t// (optional) onHalfOpen\n\tassert(\n\t\t!onHalfOpen || typeof onHalfOpen === \"function\",\n\t\t`\"onHalfOpen\" must be a function (received ${typeof onHalfOpen})`,\n\t)\n\n\t// (optional) onOpen\n\tassert(\n\t\t!onOpen || typeof onOpen === \"function\",\n\t\t`\"onOpen\" must be a function (received ${typeof onOpen})`,\n\t)\n\n\t// resetAfter\n\tassert(\n\t\tresetAfter >= 1_000,\n\t\t`\"resetAfter\" must be milliseconds of at least 1 second (received ${resetAfter})`,\n\t)\n\tassert(\n\t\tresetAfter >= errorWindow,\n\t\t`\"resetAfter\" must be greater than or equal to \"errorWindow\" (received ${resetAfter}, expected >= ${errorWindow})`,\n\t)\n\n\t// retryDelay\n\tassert(\n\t\ttypeof retryDelay === \"function\" ||\n\t\t\t(typeof retryDelay === \"number\" &&\n\t\t\t\tretryDelay >= 0 &&\n\t\t\t\tNumber.isFinite(retryDelay)),\n\t\t`\"retryDelay\" must be a function or a finite, non-negative number (received ${typeof retryDelay})`,\n\t)\n\n\t// retryLimit\n\tassert(\n\t\ttypeof retryLimit === \"number\" && retryLimit >= 1,\n\t\t`\"retryLimit\" must be greater than 0 (received ${retryLimit})`,\n\t)\n\n\t// retryTest\n\tassert(\n\t\ttypeof retryTest === \"function\",\n\t\t`\"retryTest\" must be a function (received ${typeof retryTest})`,\n\t)\n\n\t// timeout\n\tassert(\n\t\tNumber.isFinite(timeout) && timeout >= 0,\n\t\t`\"timeout\" must be a finite, non-negative number (received ${timeout})`,\n\t)\n\n\treturn {\n\t\terrorIsTransient,\n\t\terrorThreshold,\n\t\terrorWindow,\n\t\tfallback,\n\t\tminimumCandidates,\n\t\tonClose,\n\t\tonHalfOpen,\n\t\tonOpen,\n\t\tresetAfter,\n\t\tretryDelay,\n\t\tretryLimit,\n\t\tretryTest,\n\t\ttimeout,\n\t}\n}\n","import { parseOptions } from \"./options.js\"\nimport type {\n\tCircuitBreakerOptions,\n\tCircuitBreakerProtectedFn,\n\tHistoryEntry,\n\tHistoryMap,\n\tMainFn,\n\tRetryDelayFn,\n\tStateName,\n} from \"./types.js\"\nimport { CircuitError } from \"./circuit-error.js\"\nimport {\n\tabortable,\n\tassert,\n\tdelayMs,\n\tnoop,\n\tpromiseTry,\n} from \"./util.js\"\n\nasync function shouldContinue(options: {\n\tretries: number\n\tlastError: unknown\n\tretryDelay: number | RetryDelayFn\n\tretryLimit: number\n\tretryTest: (error: unknown) => boolean\n\tsignal: AbortSignal\n}): Promise<true> {\n\tconst { retries, lastError, retryDelay, retryLimit, retryTest, signal } =\n\t\toptions\n\n\tif (retries >= retryLimit)\n\t\tthrow new CircuitError(\"MAX_RETRIES\", { cause: lastError })\n\tif (!retryTest(lastError))\n\t\tthrow new CircuitError(\"NON_RETRYABLE\", { cause: lastError })\n\n\ttry {\n\t\tif (!retryDelay) return true\n\t\telse if (typeof retryDelay === \"number\") await delayMs(retryDelay, signal)\n\t\telse if (typeof retryDelay === \"function\") await retryDelay(retries, signal)\n\t} catch {\n\t\t/* empty */\n\t}\n\n\treturn true\n}\n\nconst validTransitions: Record<StateName, StateName[]> = {\n\tclosed: [\"open\", \"disposed\"],\n\topen: [\"halfOpen\", \"disposed\"],\n\thalfOpen: [\"closed\", \"open\", \"disposed\"],\n\tdisposed: [],\n}\n\nfunction assertTransition(from: StateName, to: StateName): void {\n\tassert(\n\t\tvalidTransitions[from].includes(to),\n\t\t`Invalid transition from ${from} to ${to}`,\n\t)\n}\n\ninterface CircuitInternalState<T extends StateName = StateName> {\n\tcontroller: AbortController\n\tfailureCause: unknown\n\tfailureRate: number\n\thistory: HistoryMap\n\tstatus: T\n}\n\nfunction createState(\n\tstatus: StateName,\n\tfailureCause?: unknown,\n): CircuitInternalState {\n\tconst controller = new AbortController()\n\treturn {\n\t\tcontroller,\n\t\tfailureCause,\n\t\tfailureRate: 0,\n\t\thistory: new Map(),\n\t\tstatus,\n\t}\n}\n\n/**\n * Creates a circuit breaker that wraps an async function with failure tracking\n * and automatic fallback behavior.\n *\n * The circuit breaker operates in four states:\n *\n * - `closed`: Normal operation, tracks failures in a sliding window\n * - `open`: Failed state, fallback is used until `resetAfter` milliseconds\n * - `halfOpen`: Testing recovery, allows trial calls\n * - `disposed`: Terminal state, all calls rejected\n *\n * When the failure rate exceeds `errorThreshold` within the `errorWindow`, the\n * circuit opens and rejects calls (using fallback if provided) for `resetAfter`\n * milliseconds. After this period, it transitions to half-open and allows up\n * to `minimumCandidates` concurrent trial calls. If their failure rate stays\n * at or below the threshold, the circuit closes; otherwise it reopens.\n *\n * @example\n * ```ts\n * const protectedFn = createCircuitBreaker(unreliableApiCall, {\n * errorThreshold: 0.5,\n * errorWindow: 10_000,\n * resetAfter: 30_000,\n * fallback: () => cachedResponse,\n * })\n *\n * try {\n * const result = await protectedFn(arg1, arg2)\n * } catch (error) {\n * console.error('Circuit breaker rejected call:', error)\n * }\n *\n * console.log(protectedFn.getState()) // 'closed' | 'open' | 'halfOpen' | 'disposed'\n * protectedFn[Symbol.dispose]() // Clean up timers and resources\n * ```\n */\nexport function createCircuitBreaker<Ret, Args extends unknown[]>(\n\tmain: MainFn<Ret, Args>,\n\toptions: CircuitBreakerOptions<MainFn<Ret, Args>> = {},\n): CircuitBreakerProtectedFn<Ret, Args> {\n\tconst {\n\t\terrorIsTransient,\n\t\terrorThreshold,\n\t\terrorWindow,\n\t\tfallback,\n\t\tminimumCandidates,\n\t\tonClose,\n\t\tonHalfOpen,\n\t\tonOpen,\n\t\tresetAfter,\n\t\tretryDelay,\n\t\tretryLimit,\n\t\tretryTest,\n\t\ttimeout,\n\t} = parseOptions(options)\n\n\tlet state = createState(\"closed\")\n\n\tasync function tryCall(\n\t\tcurrent: CircuitInternalState,\n\t\targs: Args,\n\t): Promise<Ret> {\n\t\tconst { history } = current\n\t\tconst request = promiseTry(() => main(...args))\n\n\t\tlet historyItem: HistoryEntry | undefined = { status: \"pending\" }\n\t\thistory.set(request, historyItem)\n\n\t\ttry {\n\t\t\tconst result =\n\t\t\t\ttimeout > 0\n\t\t\t\t\t? await abortable(AbortSignal.timeout(timeout), request)\n\t\t\t\t\t: await request\n\t\t\thistoryItem.status = \"resolved\"\n\t\t\treturn result\n\t\t} catch (cause) {\n\t\t\thistoryItem.status = \"rejected\"\n\t\t\t// Drop this request if it's a transient error that shouldn't count\n\t\t\t// towards the failure rate\n\t\t\tconst isTransient = errorIsTransient(cause)\n\t\t\tif (isTransient) historyItem = undefined\n\n\t\t\t// Wrap the error in a CircuitError to provide additional context and\n\t\t\t// control flow handling.\n\t\t\tthrow new CircuitError(\"CALL_FAILURE\", { cause, isTransient })\n\t\t} finally {\n\t\t\t// Remove the request if it was a transient failure, or if it's stale.\n\t\t\tif (!historyItem || state !== current) history.delete(request)\n\t\t\t// Keep the request in history until the end of the error window, or until\n\t\t\t// the circuit transitions.\n\t\t\telse {\n\t\t\t\tconst { signal } = current.controller\n\t\t\t\tdelayMs(errorWindow, signal)\n\t\t\t\t\t.catch(() => {})\n\t\t\t\t\t.finally(() => history.delete(request))\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction calculateFailureRate(): number {\n\t\tlet failures = 0\n\t\tlet total = 0\n\t\tfor (const { status } of state.history.values()) {\n\t\t\tif (status === \"rejected\") failures++\n\t\t\tif (status !== \"pending\") total++\n\t\t}\n\t\tif (!total || total < minimumCandidates) return 0\n\t\treturn failures / total\n\t}\n\n\tfunction transitionTo(\n\t\ttoStatus: StateName,\n\t\tfailureCause?: unknown,\n\t): CircuitInternalState {\n\t\tassertTransition(state.status, toStatus)\n\t\tstate.controller.abort()\n\t\treturn (state = createState(toStatus, failureCause))\n\t}\n\n\tasync function transitionToOpen(error: CircuitError): Promise<void> {\n\t\t// Race guard: a concurrent failure may have already changed state.\n\t\tif (state.status !== \"closed\" && state.status !== \"halfOpen\") return\n\n\t\tconst cause = error.cause ?? error\n\t\tconst nextState = transitionTo(\"open\", cause)\n\t\tif (onOpen) setImmediate(onOpen, cause)\n\n\t\tconst { signal } = nextState.controller\n\t\tawait delayMs(resetAfter, signal)\n\t\tif (state === nextState) transitionToHalfOpen()\n\t}\n\n\tfunction transitionToHalfOpen(): void {\n\t\ttransitionTo(\"halfOpen\", state.failureCause)\n\t\tif (onHalfOpen) setImmediate(onHalfOpen)\n\t}\n\n\tfunction transitionToClosed(): void {\n\t\ttransitionTo(\"closed\")\n\t\tif (onClose) setImmediate(onClose)\n\t}\n\n\tfunction guardIsCurrent(\n\t\tcurrent: CircuitInternalState,\n\t\terror: unknown,\n\t): error is CircuitError {\n\t\tif (!(error instanceof CircuitError)) throw error\n\t\t// Transient errors shouldn't affect the circuit breaker's state. Re-throw\n\t\t// the original cause of the error.\n\t\tif (error.isTransient) throw error.cause\n\n\t\t// If the circuit breaker was disposed mid-flight, surface the underlying\n\t\t// cause of the in-flight call rather than the dispose error.\n\t\tif (state.status === \"disposed\")\n\t\t\t// eslint-disable-next-line @typescript-eslint/only-throw-error\n\t\t\tthrow error.cause ?? new CircuitError(\"DISPOSED\")\n\n\t\t// If the circuit breaker transitioned states, try again.\n\t\treturn state === current\n\t}\n\n\tasync function protectedFn(...args: Args): Promise<Ret> {\n\t\tlet lastError: CircuitError | undefined\n\t\tlet retries = 0\n\t\tdo {\n\t\t\tconst current = state\n\t\t\tlastError = undefined\n\n\t\t\t// Closed: Normal Operation\n\t\t\tif (current.status === \"closed\") {\n\t\t\t\ttry {\n\t\t\t\t\treturn await tryCall(current, args)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (guardIsCurrent(current, error)) {\n\t\t\t\t\t\tlastError = error\n\t\t\t\t\t\t// Determine if the failure rate should open the circuit.\n\t\t\t\t\t\tconst rate = (current.failureRate = calculateFailureRate())\n\t\t\t\t\t\tif (rate > errorThreshold) transitionToOpen(error).catch(noop)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Half-Open: Execute trial calls until we have enough candidates.\n\t\t\telse if (\n\t\t\t\tcurrent.status === \"halfOpen\" &&\n\t\t\t\tcurrent.history.size < minimumCandidates\n\t\t\t) {\n\t\t\t\ttry {\n\t\t\t\t\treturn await tryCall(current, args)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (guardIsCurrent(current, error)) lastError = error\n\t\t\t\t\tbreak\n\t\t\t\t} finally {\n\t\t\t\t\t// Do nothing until we have enough candidates to make a decision.\n\t\t\t\t\tif (state === current && current.history.size >= minimumCandidates) {\n\t\t\t\t\t\tconst rate = (current.failureRate = calculateFailureRate())\n\t\t\t\t\t\t// Determine if the failure rate should re-open the circuit or\n\t\t\t\t\t\t// if it is healthy enough to close it again.\n\t\t\t\t\t\tif (rate > errorThreshold && lastError)\n\t\t\t\t\t\t\ttransitionToOpen(lastError).catch(noop)\n\t\t\t\t\t\telse if (rate <= errorThreshold) transitionToClosed()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Open: Skip calls and immediately return fallback if available.\n\t\t\telse if (current.status === \"open\" || current.status === \"halfOpen\") {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// Disposed: Reject all calls with dispose error.\n\t\t\telse throw current.failureCause\n\t\t} while (\n\t\t\tawait shouldContinue({\n\t\t\t\tretries: ++retries,\n\t\t\t\tlastError: lastError?.cause ?? lastError,\n\t\t\t\tretryDelay,\n\t\t\t\tretryLimit,\n\t\t\t\tretryTest,\n\t\t\t\tsignal: state.controller.signal,\n\t\t\t}).catch((error: CircuitError) => {\n\t\t\t\tlastError = error\n\t\t\t\treturn false\n\t\t\t})\n\t\t)\n\n\t\tif (!fallback) throw lastError ?? state.failureCause\n\t\treturn fallback(...args)\n\t}\n\n\tfunction dispose(disposeMessage = \"ERR_CIRCUIT_BREAKER_DISPOSED\"): void {\n\t\tif (state.status === \"disposed\") return\n\t\ttransitionTo(\"disposed\", new ReferenceError(disposeMessage))\n\t\tmain[Symbol.dispose]?.()\n\t}\n\n\tconst wrapped = protectedFn as CircuitBreakerProtectedFn<Ret, Args>\n\twrapped[Symbol.dispose] = () => dispose()\n\twrapped.dispose = dispose\n\twrapped.getFailureRate = () => state.failureRate\n\twrapped.getLatestError = () => state.failureCause\n\twrapped.getState = () => state.status\n\n\treturn wrapped\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "breaker-box",
3
- "version": "8.0.0",
3
+ "version": "9.0.0",
4
4
  "description": "A zero-dependency circuit breaker implementation for Node.js",
5
5
  "repository": {
6
6
  "type": "git",
@@ -11,12 +11,12 @@
11
11
  "types": "./dist/index.d.cts",
12
12
  "exports": {
13
13
  "require": {
14
- "default": "./dist/index.cjs",
15
- "types": "./dist/index.d.cts"
14
+ "types": "./dist/index.d.cts",
15
+ "default": "./dist/index.cjs"
16
16
  },
17
17
  "import": {
18
- "default": "./dist/index.mjs",
19
- "types": "./dist/index.d.mts"
18
+ "types": "./dist/index.d.mts",
19
+ "default": "./dist/index.mjs"
20
20
  }
21
21
  },
22
22
  "files": [