@fetchkit/ffetch 5.0.1 → 5.1.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/dist/index.d.cts CHANGED
@@ -1,51 +1,9 @@
1
- import { C as ClientPlugin, P as PluginExtensionBase, a as PluginExtensions } from './plugins-9qcU31nU.cjs';
2
- export { c as PluginDispatch, b as PluginRequestContext, d as PluginSetupContext } from './plugins-9qcU31nU.cjs';
1
+ import { F as FFetchOptions, a as FFetch } from './types-DbmivXba.cjs';
2
+ export { H as Hooks } from './types-DbmivXba.cjs';
3
+ import { C as ClientPlugin, P as PluginExtensionBase, a as PluginRequestPromiseExtensionBase, b as PluginExtensions, c as PluginRequestPromiseExtensions } from './plugins-DqBQVM4I.cjs';
4
+ export { e as PluginDispatch, d as PluginRequestContext, f as PluginSetupContext } from './plugins-DqBQVM4I.cjs';
3
5
 
4
- type Hooks = {
5
- before?: (req: Request) => void | Promise<void>;
6
- after?: (req: Request, res: Response) => void | Promise<void>;
7
- onError?: (req: Request, err: unknown) => void | Promise<void>;
8
- onRetry?: (req: Request, attempt: number, err?: unknown, res?: Response) => void | Promise<void>;
9
- onTimeout?: (req: Request) => void | Promise<void>;
10
- onAbort?: (req: Request) => void | Promise<void>;
11
- onComplete?: (req: Request, res?: Response, err?: unknown) => void | Promise<void>;
12
- transformRequest?: (req: Request) => Request | Promise<Request>;
13
- transformResponse?: (res: Response, req: Request) => Response | Promise<Response>;
14
- };
15
-
16
- interface RetryContext {
17
- attempt: number;
18
- request: Request;
19
- response?: Response;
20
- error?: unknown;
21
- }
22
- interface CoreClientOptions {
23
- timeout?: number;
24
- retries?: number;
25
- retryDelay?: number | ((ctx: RetryContext) => number);
26
- shouldRetry?: (ctx: RetryContext) => boolean;
27
- throwOnHttpError?: boolean;
28
- hooks?: Hooks;
29
- fetchHandler?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
30
- }
31
- interface FFetchOptions<TPlugins extends readonly ClientPlugin<PluginExtensionBase>[] = readonly ClientPlugin<PluginExtensionBase>[]> extends CoreClientOptions {
32
- plugins?: TPlugins;
33
- }
34
- type FFetchRequestOptions = CoreClientOptions;
35
- type FFetch<TExtensions extends object = Record<never, never>> = {
36
- (input: RequestInfo | URL, init?: FFetchRequestInit): Promise<Response>;
37
- pendingRequests: PendingRequest[];
38
- abortAll: () => void;
39
- } & TExtensions;
40
- interface FFetchRequestInit extends RequestInit, FFetchRequestOptions {
41
- }
42
- type PendingRequest = {
43
- promise: Promise<Response>;
44
- request: Request;
45
- controller?: AbortController;
46
- };
47
-
48
- declare function createClient<TPlugins extends readonly ClientPlugin<PluginExtensionBase>[] = readonly ClientPlugin<PluginExtensionBase>[]>(opts?: FFetchOptions<TPlugins>): FFetch<PluginExtensions<TPlugins>>;
6
+ declare function createClient<TPlugins extends readonly ClientPlugin<PluginExtensionBase, PluginRequestPromiseExtensionBase>[] = readonly ClientPlugin<PluginExtensionBase, PluginRequestPromiseExtensionBase>[]>(opts?: FFetchOptions<TPlugins>): FFetch<PluginExtensions<TPlugins>, PluginRequestPromiseExtensions<TPlugins>>;
49
7
 
50
8
  declare class BaseError extends Error {
51
9
  cause?: unknown;
@@ -66,5 +24,8 @@ declare class RetryLimitError extends BaseError {
66
24
  declare class NetworkError extends BaseError {
67
25
  constructor(message?: string, cause?: unknown);
68
26
  }
27
+ declare class HttpError extends BaseError {
28
+ constructor(message?: string, cause?: unknown);
29
+ }
69
30
 
70
- export { AbortError, CircuitOpenError, ClientPlugin, type FFetch, type FFetchOptions, type Hooks, NetworkError, RetryLimitError, TimeoutError, createClient };
31
+ export { AbortError, CircuitOpenError, ClientPlugin, FFetch, FFetchOptions, HttpError, NetworkError, RetryLimitError, TimeoutError, createClient };
package/dist/index.d.ts CHANGED
@@ -1,51 +1,9 @@
1
- import { C as ClientPlugin, P as PluginExtensionBase, a as PluginExtensions } from './plugins-9qcU31nU.js';
2
- export { c as PluginDispatch, b as PluginRequestContext, d as PluginSetupContext } from './plugins-9qcU31nU.js';
1
+ import { F as FFetchOptions, a as FFetch } from './types-DpHoyvhy.js';
2
+ export { H as Hooks } from './types-DpHoyvhy.js';
3
+ import { C as ClientPlugin, P as PluginExtensionBase, a as PluginRequestPromiseExtensionBase, b as PluginExtensions, c as PluginRequestPromiseExtensions } from './plugins-DqBQVM4I.js';
4
+ export { e as PluginDispatch, d as PluginRequestContext, f as PluginSetupContext } from './plugins-DqBQVM4I.js';
3
5
 
4
- type Hooks = {
5
- before?: (req: Request) => void | Promise<void>;
6
- after?: (req: Request, res: Response) => void | Promise<void>;
7
- onError?: (req: Request, err: unknown) => void | Promise<void>;
8
- onRetry?: (req: Request, attempt: number, err?: unknown, res?: Response) => void | Promise<void>;
9
- onTimeout?: (req: Request) => void | Promise<void>;
10
- onAbort?: (req: Request) => void | Promise<void>;
11
- onComplete?: (req: Request, res?: Response, err?: unknown) => void | Promise<void>;
12
- transformRequest?: (req: Request) => Request | Promise<Request>;
13
- transformResponse?: (res: Response, req: Request) => Response | Promise<Response>;
14
- };
15
-
16
- interface RetryContext {
17
- attempt: number;
18
- request: Request;
19
- response?: Response;
20
- error?: unknown;
21
- }
22
- interface CoreClientOptions {
23
- timeout?: number;
24
- retries?: number;
25
- retryDelay?: number | ((ctx: RetryContext) => number);
26
- shouldRetry?: (ctx: RetryContext) => boolean;
27
- throwOnHttpError?: boolean;
28
- hooks?: Hooks;
29
- fetchHandler?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
30
- }
31
- interface FFetchOptions<TPlugins extends readonly ClientPlugin<PluginExtensionBase>[] = readonly ClientPlugin<PluginExtensionBase>[]> extends CoreClientOptions {
32
- plugins?: TPlugins;
33
- }
34
- type FFetchRequestOptions = CoreClientOptions;
35
- type FFetch<TExtensions extends object = Record<never, never>> = {
36
- (input: RequestInfo | URL, init?: FFetchRequestInit): Promise<Response>;
37
- pendingRequests: PendingRequest[];
38
- abortAll: () => void;
39
- } & TExtensions;
40
- interface FFetchRequestInit extends RequestInit, FFetchRequestOptions {
41
- }
42
- type PendingRequest = {
43
- promise: Promise<Response>;
44
- request: Request;
45
- controller?: AbortController;
46
- };
47
-
48
- declare function createClient<TPlugins extends readonly ClientPlugin<PluginExtensionBase>[] = readonly ClientPlugin<PluginExtensionBase>[]>(opts?: FFetchOptions<TPlugins>): FFetch<PluginExtensions<TPlugins>>;
6
+ declare function createClient<TPlugins extends readonly ClientPlugin<PluginExtensionBase, PluginRequestPromiseExtensionBase>[] = readonly ClientPlugin<PluginExtensionBase, PluginRequestPromiseExtensionBase>[]>(opts?: FFetchOptions<TPlugins>): FFetch<PluginExtensions<TPlugins>, PluginRequestPromiseExtensions<TPlugins>>;
49
7
 
50
8
  declare class BaseError extends Error {
51
9
  cause?: unknown;
@@ -66,5 +24,8 @@ declare class RetryLimitError extends BaseError {
66
24
  declare class NetworkError extends BaseError {
67
25
  constructor(message?: string, cause?: unknown);
68
26
  }
27
+ declare class HttpError extends BaseError {
28
+ constructor(message?: string, cause?: unknown);
29
+ }
69
30
 
70
- export { AbortError, CircuitOpenError, ClientPlugin, type FFetch, type FFetchOptions, type Hooks, NetworkError, RetryLimitError, TimeoutError, createClient };
31
+ export { AbortError, CircuitOpenError, ClientPlugin, FFetch, FFetchOptions, HttpError, NetworkError, RetryLimitError, TimeoutError, createClient };
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  AbortError,
3
3
  CircuitOpenError,
4
+ HttpError,
4
5
  NetworkError,
5
6
  RetryLimitError,
6
7
  TimeoutError
@@ -129,251 +130,260 @@ function createClient(opts = {}) {
129
130
  entry.controller?.abort();
130
131
  }
131
132
  }
132
- const client = async (input, init = {}) => {
133
- let request = new Request(input, init);
134
- const effectiveHooks = { ...clientDefaultHooks, ...init.hooks || {} };
135
- if (effectiveHooks.transformRequest) {
136
- request = await effectiveHooks.transformRequest(request);
137
- }
138
- await effectiveHooks.before?.(request);
139
- const effectiveRetries = init.retries ?? clientDefaultRetries;
140
- const effectiveRetryDelay = typeof init.retryDelay !== "undefined" ? init.retryDelay : clientDefaultRetryDelay;
141
- const effectiveShouldRetry = init.shouldRetry ?? clientDefaultShouldRetry;
142
- const effectiveTimeout = init.timeout ?? clientDefaultTimeout;
143
- const userSignal = init.signal;
144
- const transformedSignal = request.signal;
145
- const pluginContext = {
146
- request,
147
- init,
148
- state: /* @__PURE__ */ Object.create(null),
149
- metadata: {
150
- startedAt: Date.now(),
151
- timeoutMs: effectiveTimeout,
152
- signals: {
153
- user: userSignal === void 0 || userSignal === null ? void 0 : userSignal,
154
- transformed: transformedSignal
155
- },
156
- retry: {
157
- configuredRetries: effectiveRetries,
158
- configuredDelay: effectiveRetryDelay,
159
- attempt: 0
160
- }
133
+ const client = (input, init = {}) => {
134
+ const execute = async () => {
135
+ let request = new Request(input, init);
136
+ const effectiveHooks = { ...clientDefaultHooks, ...init.hooks || {} };
137
+ if (effectiveHooks.transformRequest) {
138
+ request = await effectiveHooks.transformRequest(request);
161
139
  }
162
- };
163
- for (const plugin of plugins) {
164
- await plugin.preRequest?.(pluginContext);
165
- }
166
- const effectiveThrowOnHttpError = typeof init.throwOnHttpError !== "undefined" ? init.throwOnHttpError : opts.throwOnHttpError ?? false;
167
- function createTimeoutSignal(timeout) {
168
- if (typeof AbortSignal?.timeout === "function") {
169
- return AbortSignal.timeout(timeout);
140
+ await effectiveHooks.before?.(request);
141
+ const effectiveRetries = init.retries ?? clientDefaultRetries;
142
+ const effectiveRetryDelay = typeof init.retryDelay !== "undefined" ? init.retryDelay : clientDefaultRetryDelay;
143
+ const effectiveShouldRetry = init.shouldRetry ?? clientDefaultShouldRetry;
144
+ const effectiveTimeout = init.timeout ?? clientDefaultTimeout;
145
+ const userSignal = init.signal;
146
+ const transformedSignal = request.signal;
147
+ const pluginContext = {
148
+ request,
149
+ init,
150
+ state: /* @__PURE__ */ Object.create(null),
151
+ metadata: {
152
+ startedAt: Date.now(),
153
+ timeoutMs: effectiveTimeout,
154
+ signals: {
155
+ user: userSignal === void 0 || userSignal === null ? void 0 : userSignal,
156
+ transformed: transformedSignal
157
+ },
158
+ retry: {
159
+ configuredRetries: effectiveRetries,
160
+ configuredDelay: effectiveRetryDelay,
161
+ attempt: 0
162
+ }
163
+ }
164
+ };
165
+ for (const plugin of plugins) {
166
+ await plugin.preRequest?.(pluginContext);
170
167
  }
171
- const controller2 = new AbortController();
172
- const timeoutId = setTimeout(() => controller2.abort(), timeout);
173
- controller2.signal.addEventListener(
174
- "abort",
175
- () => clearTimeout(timeoutId),
176
- { once: true }
177
- );
178
- return controller2.signal;
179
- }
180
- let timeoutSignal = void 0;
181
- let combinedSignal = void 0;
182
- let controller = void 0;
183
- if (effectiveTimeout > 0) {
184
- timeoutSignal = createTimeoutSignal(effectiveTimeout);
185
- pluginContext.metadata.signals.timeout = timeoutSignal;
186
- }
187
- const signals = [];
188
- if (userSignal) signals.push(userSignal);
189
- if (transformedSignal && transformedSignal !== userSignal) {
190
- signals.push(transformedSignal);
191
- }
192
- if (timeoutSignal) signals.push(timeoutSignal);
193
- if (signals.length === 1) {
194
- combinedSignal = signals[0];
195
- controller = new AbortController();
196
- } else {
197
- if (typeof AbortSignal.any !== "function") {
198
- throw new Error(
199
- "AbortSignal.any is required for combining multiple signals. Please install a polyfill for environments that do not support it."
168
+ const effectiveThrowOnHttpError = typeof init.throwOnHttpError !== "undefined" ? init.throwOnHttpError : opts.throwOnHttpError ?? false;
169
+ function createTimeoutSignal(timeout) {
170
+ if (typeof AbortSignal?.timeout === "function") {
171
+ return AbortSignal.timeout(timeout);
172
+ }
173
+ const controller2 = new AbortController();
174
+ const timeoutId = setTimeout(() => controller2.abort(), timeout);
175
+ controller2.signal.addEventListener(
176
+ "abort",
177
+ () => clearTimeout(timeoutId),
178
+ { once: true }
200
179
  );
180
+ return controller2.signal;
201
181
  }
202
- combinedSignal = AbortSignal.any(signals);
203
- controller = new AbortController();
204
- }
205
- pluginContext.metadata.signals.combined = combinedSignal;
206
- const retryWithHooks = async () => {
207
- let attempt = 0;
208
- const shouldRetryWithHook = (ctx) => {
209
- attempt = ctx.attempt;
210
- pluginContext.metadata.retry.attempt = attempt;
211
- pluginContext.metadata.retry.lastError = ctx.error;
212
- pluginContext.metadata.retry.lastResponse = ctx.response;
213
- const retrying = effectiveShouldRetry(ctx);
214
- pluginContext.metadata.retry.shouldRetryResult = retrying;
215
- if (retrying && attempt <= effectiveRetries) {
216
- effectiveHooks.onRetry?.(
217
- request,
218
- attempt - 1,
219
- ctx.error,
220
- ctx.response
182
+ let timeoutSignal = void 0;
183
+ let combinedSignal = void 0;
184
+ let controller = void 0;
185
+ if (effectiveTimeout > 0) {
186
+ timeoutSignal = createTimeoutSignal(effectiveTimeout);
187
+ pluginContext.metadata.signals.timeout = timeoutSignal;
188
+ }
189
+ const signals = [];
190
+ if (userSignal) signals.push(userSignal);
191
+ if (transformedSignal && transformedSignal !== userSignal) {
192
+ signals.push(transformedSignal);
193
+ }
194
+ if (timeoutSignal) signals.push(timeoutSignal);
195
+ if (signals.length === 1) {
196
+ combinedSignal = signals[0];
197
+ controller = new AbortController();
198
+ } else {
199
+ if (typeof AbortSignal.any !== "function") {
200
+ throw new Error(
201
+ "AbortSignal.any is required for combining multiple signals. Please install a polyfill for environments that do not support it."
221
202
  );
222
203
  }
223
- return retrying;
224
- };
225
- let lastResponse = void 0;
226
- try {
227
- let res = await retry(
228
- async () => {
229
- if (userSignal?.aborted) {
230
- effectiveHooks.onAbort?.(request);
231
- throw new AbortError("Request was aborted by user");
232
- }
233
- if (timeoutSignal?.aborted) {
234
- effectiveHooks.onTimeout?.(request);
235
- throw new TimeoutError("signal timed out");
236
- }
237
- if (typeof combinedSignal?.throwIfAborted === "function") {
238
- combinedSignal.throwIfAborted();
239
- } else if (combinedSignal?.aborted) {
204
+ combinedSignal = AbortSignal.any(signals);
205
+ controller = new AbortController();
206
+ }
207
+ pluginContext.metadata.signals.combined = combinedSignal;
208
+ const retryWithHooks = async () => {
209
+ let attempt = 0;
210
+ const shouldRetryWithHook = (ctx) => {
211
+ attempt = ctx.attempt;
212
+ pluginContext.metadata.retry.attempt = attempt;
213
+ pluginContext.metadata.retry.lastError = ctx.error;
214
+ pluginContext.metadata.retry.lastResponse = ctx.response;
215
+ const retrying = effectiveShouldRetry(ctx);
216
+ pluginContext.metadata.retry.shouldRetryResult = retrying;
217
+ if (retrying && attempt <= effectiveRetries) {
218
+ effectiveHooks.onRetry?.(
219
+ request,
220
+ attempt - 1,
221
+ ctx.error,
222
+ ctx.response
223
+ );
224
+ }
225
+ return retrying;
226
+ };
227
+ let lastResponse = void 0;
228
+ try {
229
+ let res = await retry(
230
+ async () => {
240
231
  if (userSignal?.aborted) {
241
232
  effectiveHooks.onAbort?.(request);
242
233
  throw new AbortError("Request was aborted by user");
243
- } else if (timeoutSignal?.aborted) {
234
+ }
235
+ if (timeoutSignal?.aborted) {
244
236
  effectiveHooks.onTimeout?.(request);
245
237
  throw new TimeoutError("signal timed out");
246
- } else {
247
- throw new AbortError(
248
- "Request was aborted",
249
- new DOMException("Aborted", "AbortError")
250
- );
251
238
  }
252
- }
253
- const reqWithSignal = new Request(request, {
254
- signal: combinedSignal
255
- });
256
- try {
257
- const handler = init.fetchHandler ?? fetchHandler ?? fetch;
258
- const response = await handler(reqWithSignal);
259
- lastResponse = response;
260
- pluginContext.metadata.retry.lastResponse = response;
261
- return response;
262
- } catch (err) {
263
- pluginContext.metadata.retry.lastError = err;
264
- if (err instanceof DOMException && err.name === "AbortError") {
265
- if (timeoutSignal?.aborted && (!userSignal || !userSignal.aborted)) {
266
- effectiveHooks.onTimeout?.(request);
267
- throw new TimeoutError("signal timed out", err);
268
- } else if (userSignal?.aborted) {
239
+ if (typeof combinedSignal?.throwIfAborted === "function") {
240
+ combinedSignal.throwIfAborted();
241
+ } else if (combinedSignal?.aborted) {
242
+ if (userSignal?.aborted) {
269
243
  effectiveHooks.onAbort?.(request);
270
244
  throw new AbortError("Request was aborted by user");
245
+ } else if (timeoutSignal?.aborted) {
246
+ effectiveHooks.onTimeout?.(request);
247
+ throw new TimeoutError("signal timed out");
271
248
  } else {
272
249
  throw new AbortError(
273
250
  "Request was aborted",
274
251
  new DOMException("Aborted", "AbortError")
275
252
  );
276
253
  }
277
- } else if (err instanceof TypeError && /NetworkError|network error|failed to fetch|lost connection|NetworkError when attempting to fetch resource/i.test(
278
- err.message
279
- )) {
280
- throw new NetworkError(err.message, err);
281
254
  }
282
- throw err;
283
- }
284
- },
285
- effectiveRetries,
286
- effectiveRetryDelay,
287
- shouldRetryWithHook,
288
- request,
289
- combinedSignal
290
- );
291
- if (effectiveHooks.transformResponse) {
292
- res = await effectiveHooks.transformResponse(res, request);
293
- }
294
- await effectiveHooks.after?.(request, res);
295
- await effectiveHooks.onComplete?.(request, res, void 0);
296
- if (effectiveThrowOnHttpError && (res.status >= 400 && res.status < 500 && res.status !== 429 || res.status >= 500 || res.status === 429)) {
297
- const { HttpError } = await import("./error-XBHPSMAQ.js");
298
- throw new HttpError(
299
- `HTTP error: ${res.status} ${res.statusText}`,
300
- res
255
+ const reqWithSignal = new Request(request, {
256
+ signal: combinedSignal
257
+ });
258
+ try {
259
+ const handler = init.fetchHandler ?? fetchHandler ?? fetch;
260
+ const response = await handler(reqWithSignal);
261
+ lastResponse = response;
262
+ pluginContext.metadata.retry.lastResponse = response;
263
+ return response;
264
+ } catch (err) {
265
+ pluginContext.metadata.retry.lastError = err;
266
+ if (err instanceof DOMException && err.name === "AbortError") {
267
+ if (timeoutSignal?.aborted && (!userSignal || !userSignal.aborted)) {
268
+ effectiveHooks.onTimeout?.(request);
269
+ throw new TimeoutError("signal timed out", err);
270
+ } else if (userSignal?.aborted) {
271
+ effectiveHooks.onAbort?.(request);
272
+ throw new AbortError("Request was aborted by user");
273
+ } else {
274
+ throw new AbortError(
275
+ "Request was aborted",
276
+ new DOMException("Aborted", "AbortError")
277
+ );
278
+ }
279
+ } else if (err instanceof TypeError && /NetworkError|network error|failed to fetch|lost connection|NetworkError when attempting to fetch resource/i.test(
280
+ err.message
281
+ )) {
282
+ throw new NetworkError(err.message, err);
283
+ }
284
+ throw err;
285
+ }
286
+ },
287
+ effectiveRetries,
288
+ effectiveRetryDelay,
289
+ shouldRetryWithHook,
290
+ request,
291
+ combinedSignal
301
292
  );
302
- }
303
- return res;
304
- } catch (err) {
305
- pluginContext.metadata.retry.lastError = err;
306
- if (lastResponse) {
307
- const resp = lastResponse;
308
- if (effectiveThrowOnHttpError && (resp.status >= 400 && resp.status < 500 && resp.status !== 429 || resp.status >= 500 || resp.status === 429)) {
309
- const { HttpError } = await import("./error-XBHPSMAQ.js");
310
- throw new HttpError(
311
- `HTTP error: ${resp.status} ${resp.statusText}`,
312
- resp
293
+ if (effectiveHooks.transformResponse) {
294
+ res = await effectiveHooks.transformResponse(res, request);
295
+ }
296
+ await effectiveHooks.after?.(request, res);
297
+ await effectiveHooks.onComplete?.(request, res, void 0);
298
+ if (effectiveThrowOnHttpError && (res.status >= 400 && res.status < 500 && res.status !== 429 || res.status >= 500 || res.status === 429)) {
299
+ const { HttpError: HttpError2 } = await import("./error-XBHPSMAQ.js");
300
+ throw new HttpError2(
301
+ `HTTP error: ${res.status} ${res.statusText}`,
302
+ res
313
303
  );
314
304
  }
315
- return resp;
305
+ return res;
306
+ } catch (err) {
307
+ pluginContext.metadata.retry.lastError = err;
308
+ if (lastResponse) {
309
+ const resp = lastResponse;
310
+ if (effectiveThrowOnHttpError && (resp.status >= 400 && resp.status < 500 && resp.status !== 429 || resp.status >= 500 || resp.status === 429)) {
311
+ const { HttpError: HttpError2 } = await import("./error-XBHPSMAQ.js");
312
+ throw new HttpError2(
313
+ `HTTP error: ${resp.status} ${resp.statusText}`,
314
+ resp
315
+ );
316
+ }
317
+ return resp;
318
+ }
319
+ if (err instanceof TimeoutError) {
320
+ await effectiveHooks.onTimeout?.(request);
321
+ await effectiveHooks.onError?.(request, err);
322
+ await effectiveHooks.onComplete?.(request, void 0, err);
323
+ throw err;
324
+ }
325
+ if (err instanceof AbortError) {
326
+ await effectiveHooks.onAbort?.(request);
327
+ await effectiveHooks.onError?.(request, err);
328
+ await effectiveHooks.onComplete?.(request, void 0, err);
329
+ throw err;
330
+ }
331
+ if (err instanceof NetworkError) {
332
+ await effectiveHooks.onError?.(request, err);
333
+ await effectiveHooks.onComplete?.(request, void 0, err);
334
+ throw err;
335
+ }
336
+ const retryErr = new RetryLimitError(
337
+ typeof err === "object" && err && "message" in err && typeof err.message === "string" ? err.message : "Retry limit reached",
338
+ err
339
+ );
340
+ await effectiveHooks.onError?.(request, retryErr);
341
+ await effectiveHooks.onComplete?.(request, void 0, retryErr);
342
+ throw retryErr;
316
343
  }
317
- if (err instanceof TimeoutError) {
318
- await effectiveHooks.onTimeout?.(request);
319
- await effectiveHooks.onError?.(request, err);
320
- await effectiveHooks.onComplete?.(request, void 0, err);
321
- throw err;
344
+ };
345
+ const baseDispatch = async () => retryWithHooks();
346
+ let dispatch = baseDispatch;
347
+ for (let i = plugins.length - 1; i >= 0; i--) {
348
+ const plugin = plugins[i];
349
+ if (plugin.wrapDispatch) {
350
+ dispatch = plugin.wrapDispatch(dispatch);
322
351
  }
323
- if (err instanceof AbortError) {
324
- await effectiveHooks.onAbort?.(request);
325
- await effectiveHooks.onError?.(request, err);
326
- await effectiveHooks.onComplete?.(request, void 0, err);
327
- throw err;
352
+ }
353
+ const actualPromise = dispatch(pluginContext).then(async (response) => {
354
+ for (const plugin of plugins) {
355
+ await plugin.onSuccess?.(pluginContext, response);
328
356
  }
329
- if (err instanceof NetworkError) {
330
- await effectiveHooks.onError?.(request, err);
331
- await effectiveHooks.onComplete?.(request, void 0, err);
332
- throw err;
357
+ return response;
358
+ }).catch(async (err) => {
359
+ for (const plugin of plugins) {
360
+ await plugin.onError?.(pluginContext, err);
333
361
  }
334
- const retryErr = new RetryLimitError(
335
- typeof err === "object" && err && "message" in err && typeof err.message === "string" ? err.message : "Retry limit reached",
336
- err
337
- );
338
- await effectiveHooks.onError?.(request, retryErr);
339
- await effectiveHooks.onComplete?.(request, void 0, retryErr);
340
- throw retryErr;
341
- }
362
+ throw err;
363
+ });
364
+ const pendingEntry = {
365
+ promise: actualPromise,
366
+ request,
367
+ controller
368
+ };
369
+ pendingRequests.push(pendingEntry);
370
+ return actualPromise.finally(async () => {
371
+ for (const plugin of plugins) {
372
+ await plugin.onFinally?.(pluginContext);
373
+ }
374
+ const index = pendingRequests.indexOf(pendingEntry);
375
+ if (index > -1) {
376
+ pendingRequests.splice(index, 1);
377
+ }
378
+ });
342
379
  };
343
- const baseDispatch = async () => retryWithHooks();
344
- let dispatch = baseDispatch;
345
- for (let i = plugins.length - 1; i >= 0; i--) {
346
- const plugin = plugins[i];
347
- if (plugin.wrapDispatch) {
348
- dispatch = plugin.wrapDispatch(dispatch);
380
+ let promise = execute();
381
+ for (const plugin of plugins) {
382
+ if (plugin.decoratePromise) {
383
+ promise = plugin.decoratePromise(promise);
349
384
  }
350
385
  }
351
- const actualPromise = dispatch(pluginContext).then(async (response) => {
352
- for (const plugin of plugins) {
353
- await plugin.onSuccess?.(pluginContext, response);
354
- }
355
- return response;
356
- }).catch(async (err) => {
357
- for (const plugin of plugins) {
358
- await plugin.onError?.(pluginContext, err);
359
- }
360
- throw err;
361
- });
362
- const pendingEntry = {
363
- promise: actualPromise,
364
- request,
365
- controller
366
- };
367
- pendingRequests.push(pendingEntry);
368
- return actualPromise.finally(async () => {
369
- for (const plugin of plugins) {
370
- await plugin.onFinally?.(pluginContext);
371
- }
372
- const index = pendingRequests.indexOf(pendingEntry);
373
- if (index > -1) {
374
- pendingRequests.splice(index, 1);
375
- }
376
- });
386
+ return promise;
377
387
  };
378
388
  Object.defineProperty(client, "pendingRequests", {
379
389
  get() {
@@ -394,6 +404,7 @@ function createClient(opts = {}) {
394
404
  export {
395
405
  AbortError,
396
406
  CircuitOpenError,
407
+ HttpError,
397
408
  NetworkError,
398
409
  RetryLimitError,
399
410
  TimeoutError,