@ahoo-wang/fetcher-eventbus 2.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1460 @@
1
+ class pe {
2
+ /**
3
+ * Creates a generic event bus
4
+ *
5
+ * @param typeEventBusSupplier - Function to create TypedEventBus for specific event types
6
+ */
7
+ constructor(e) {
8
+ this.typeEventBusSupplier = e, this.buses = /* @__PURE__ */ new Map();
9
+ }
10
+ /**
11
+ * Adds an event handler for a specific event type
12
+ *
13
+ * @template Key - The event type
14
+ * @param type - The event type to listen for
15
+ * @param handler - The event handler to add
16
+ * @returns true if the handler was added, false if a handler with the same name already exists
17
+ */
18
+ on(e, t) {
19
+ let r = this.buses.get(e);
20
+ return r || (r = this.typeEventBusSupplier(e), this.buses.set(e, r)), r?.on(t) ?? !1;
21
+ }
22
+ /**
23
+ * Removes an event handler for a specific event type
24
+ *
25
+ * @template Key - The event type
26
+ * @param type - The event type
27
+ * @param name - The name of the event handler to remove
28
+ * @returns true if a handler was removed, false otherwise
29
+ */
30
+ off(e, t) {
31
+ return this.buses.get(e)?.off(t) ?? !1;
32
+ }
33
+ /**
34
+ * Emits an event for a specific event type
35
+ *
36
+ * @template Key - The event type
37
+ * @param type - The event type to emit
38
+ * @param event - The event data
39
+ * @returns Promise if the underlying bus is async, void otherwise
40
+ */
41
+ emit(e, t) {
42
+ return this.buses.get(e)?.emit(t);
43
+ }
44
+ /**
45
+ * Cleans up all managed event buses
46
+ */
47
+ destroy() {
48
+ for (const e of this.buses.values())
49
+ e.destroy();
50
+ this.buses.clear();
51
+ }
52
+ }
53
+ class fe {
54
+ /**
55
+ * Creates a parallel typed event bus
56
+ *
57
+ * @param type - The event type identifier for this bus
58
+ */
59
+ constructor(e) {
60
+ this.type = e, this.eventHandlers = [];
61
+ }
62
+ /**
63
+ * Gets a copy of all registered event handlers, sorted by order
64
+ */
65
+ get handlers() {
66
+ return [...this.eventHandlers];
67
+ }
68
+ /**
69
+ * Emits an event to all registered handlers in parallel
70
+ *
71
+ * Handlers are executed concurrently. Once-only handlers are removed after all executions complete.
72
+ * Errors in individual handlers are logged but do not affect other handlers.
73
+ *
74
+ * @param event - The event to emit
75
+ */
76
+ async emit(e) {
77
+ const t = [], r = this.eventHandlers.map(async (n) => {
78
+ try {
79
+ await n.handle(e);
80
+ } catch (a) {
81
+ console.warn(`Event handler error for ${n.name}:`, a);
82
+ } finally {
83
+ n.once && t.push(n);
84
+ }
85
+ });
86
+ await Promise.all(r), t.length > 0 && (this.eventHandlers = this.eventHandlers.filter(
87
+ (n) => !t.includes(n)
88
+ ));
89
+ }
90
+ /**
91
+ * Removes an event handler by name
92
+ *
93
+ * @param name - The name of the handler to remove
94
+ * @returns true if a handler was removed, false otherwise
95
+ */
96
+ off(e) {
97
+ const t = this.eventHandlers;
98
+ return t.some((r) => r.name === e) ? (this.eventHandlers = t.filter((r) => r.name !== e), !0) : !1;
99
+ }
100
+ /**
101
+ * Adds an event handler if not already present
102
+ *
103
+ * Handlers are sorted by their order property after addition.
104
+ *
105
+ * @param handler - The event handler to add
106
+ * @returns true if the handler was added, false if a handler with the same name already exists
107
+ */
108
+ on(e) {
109
+ const t = this.eventHandlers;
110
+ return t.some((r) => r.name === e.name) ? !1 : (this.eventHandlers = [...t, e], !0);
111
+ }
112
+ destroy() {
113
+ this.eventHandlers = [];
114
+ }
115
+ }
116
+ function M(s) {
117
+ return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(s);
118
+ }
119
+ function B(s, e) {
120
+ return M(e) ? e : e ? s.replace(/\/?\/$/, "") + "/" + e.replace(/^\/+/, "") : s;
121
+ }
122
+ function G(s) {
123
+ return s === 1 ? X : $;
124
+ }
125
+ function H(s, e, t) {
126
+ return t ? s.replace(e, (r, n) => {
127
+ const a = t[n];
128
+ if (a === void 0)
129
+ throw new Error(`Missing required path parameter: ${n}`);
130
+ return encodeURIComponent(a);
131
+ }) : s;
132
+ }
133
+ function v(s, e) {
134
+ const t = [];
135
+ let r;
136
+ for (; (r = e.exec(s)) !== null; )
137
+ t.push(r[1]);
138
+ return t;
139
+ }
140
+ const I = class m {
141
+ /**
142
+ * Extracts path parameters from a URL string.
143
+ *
144
+ * @param urlTemplate - The URL string to extract path parameters from
145
+ * @returns An array of path parameter names without the curly braces, or an empty array if no matches found
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * const resolver = uriTemplateResolver;
150
+ *
151
+ * // Extract multiple parameters
152
+ * const params = resolver.extractPathParams('/users/{id}/posts/{postId}');
153
+ * // params = ['id', 'postId']
154
+ *
155
+ * // Extract parameters from full URLs
156
+ * const urlParams = resolver.extractPathParams('https://api.example.com/{resource}/{id}');
157
+ * // urlParams = ['resource', 'id']
158
+ *
159
+ * // No parameters
160
+ * const noParams = resolver.extractPathParams('/users/profile');
161
+ * // noParams = []
162
+ * ```
163
+ */
164
+ extractPathParams(e) {
165
+ return v(
166
+ e,
167
+ m.PATH_PARAM_REGEX
168
+ );
169
+ }
170
+ /**
171
+ * Replaces placeholders in the URL with path parameters.
172
+ *
173
+ * @param urlTemplate - Path string containing placeholders, e.g., "http://localhost/users/{id}/posts/{postId}"
174
+ * @param pathParams - Path parameter object used to replace placeholders in the URL
175
+ * @returns Path string with placeholders replaced
176
+ * @throws Error when required path parameters are missing
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * const resolver = uriTemplateResolver;
181
+ *
182
+ * // Replace parameters
183
+ * const url = resolver.resolve('/users/{id}/posts/{postId}', { id: 123, postId: 456 });
184
+ * // url = '/users/123/posts/456'
185
+ *
186
+ * // Handle string parameter values
187
+ * const stringUrl = resolver.resolve('/users/{username}', { username: 'john_doe' });
188
+ * // stringUrl = '/users/john_doe'
189
+ *
190
+ * // URL encode parameter values
191
+ * const encodedUrl = resolver.resolve('/search/{query}', { query: 'hello world' });
192
+ * // encodedUrl = '/search/hello%20world'
193
+ * ```
194
+ *
195
+ * @example
196
+ * ```typescript
197
+ * // Missing required parameter throws an error
198
+ * const resolver = uriTemplateResolver;
199
+ * try {
200
+ * resolver.resolve('/users/{id}', { name: 'John' });
201
+ * } catch (error) {
202
+ * console.error(error.message); // "Missing required path parameter: id"
203
+ * }
204
+ * ```
205
+ */
206
+ resolve(e, t) {
207
+ return H(
208
+ e,
209
+ m.PATH_PARAM_REGEX,
210
+ t
211
+ );
212
+ }
213
+ };
214
+ I.PATH_PARAM_REGEX = /{([^}]+)}/g;
215
+ let U = I;
216
+ const $ = new U(), S = class E {
217
+ /**
218
+ * Extracts path parameters from an Express-style URL string.
219
+ *
220
+ * @param urlTemplate - The URL string with Express-style parameter placeholders
221
+ * @returns An array of parameter names extracted from the URL template
222
+ *
223
+ * @example
224
+ * ```typescript
225
+ * const resolver = new expressUrlTemplateResolver;
226
+ *
227
+ * // Extract multiple parameters
228
+ * const params = resolver.extractPathParams('/users/:id/posts/:postId');
229
+ * // params = ['id', 'postId']
230
+ *
231
+ * // No parameters
232
+ * const noParams = resolver.extractPathParams('/users/profile');
233
+ * // noParams = []
234
+ * ```
235
+ */
236
+ extractPathParams(e) {
237
+ return v(
238
+ e,
239
+ E.PATH_PARAM_REGEX
240
+ );
241
+ }
242
+ /**
243
+ * Replaces Express-style placeholders in the URL with path parameters.
244
+ *
245
+ * @param urlTemplate - Path string containing Express-style placeholders
246
+ * @param pathParams - Object containing parameter values to replace placeholders
247
+ * @returns Path string with placeholders replaced
248
+ * @throws Error when required path parameters are missing
249
+ *
250
+ * @example
251
+ * ```typescript
252
+ * const resolver = expressUrlTemplateResolver;
253
+ *
254
+ * // Replace parameters
255
+ * const url = resolver.resolve('/users/:id/posts/:postId', { id: 123, postId: 456 });
256
+ * // url = '/users/123/posts/456'
257
+ *
258
+ * // Handle string parameter values
259
+ * const stringUrl = resolver.resolve('/users/:username', { username: 'john_doe' });
260
+ * // stringUrl = '/users/john_doe'
261
+ * ```
262
+ *
263
+ * @example
264
+ * ```typescript
265
+ * // Missing required parameter throws an error
266
+ * const resolver = expressUrlTemplateResolver;
267
+ * try {
268
+ * resolver.resolve('/users/:id', { name: 'John' });
269
+ * } catch (error) {
270
+ * console.error(error.message); // "Missing required path parameter: id"
271
+ * }
272
+ * ```
273
+ */
274
+ resolve(e, t) {
275
+ return H(
276
+ e,
277
+ E.PATH_PARAM_REGEX,
278
+ t
279
+ );
280
+ }
281
+ };
282
+ S.PATH_PARAM_REGEX = /:([^/]+)/g;
283
+ let L = S;
284
+ const X = new L();
285
+ class j {
286
+ /**
287
+ * Initializes a new UrlBuilder instance.
288
+ *
289
+ * @param baseURL - Base URL that all constructed URLs will be based on
290
+ * @param urlTemplateStyle - Optional style configuration for URL template resolution.
291
+ * Determines how path parameters are parsed and resolved.
292
+ * Defaults to UriTemplate style if not specified.
293
+ *
294
+ * @example
295
+ * ```typescript
296
+ * // Create a URL builder with default URI template style
297
+ * const urlBuilder = new UrlBuilder('https://api.example.com');
298
+ *
299
+ * // Create a URL builder with Express-style template resolution
300
+ * const expressUrlBuilder = new UrlBuilder('https://api.example.com', UrlTemplateStyle.Express);
301
+ * ```
302
+ */
303
+ constructor(e, t) {
304
+ this.baseURL = e, this.urlTemplateResolver = G(t);
305
+ }
306
+ /**
307
+ * Builds a complete URL, including path parameter replacement and query parameter addition.
308
+ *
309
+ * @param url - URL path to build (e.g., '/users/{id}/posts')
310
+ * @param params - URL parameters including path and query parameters
311
+ * @returns Complete URL string with base URL, path parameters interpolated, and query string appended
312
+ * @throws Error when required path parameters are missing
313
+ *
314
+ * @example
315
+ * ```typescript
316
+ * const urlBuilder = new UrlBuilder('https://api.example.com');
317
+ * const url = urlBuilder.build('/users/{id}/posts/{postId}', {
318
+ * path: { id: 123, postId: 456 },
319
+ * query: { filter: 'active', limit: 10 }
320
+ * });
321
+ * // Result: https://api.example.com/users/123/posts/456?filter=active&limit=10
322
+ * ```
323
+ */
324
+ build(e, t) {
325
+ const r = t?.path, n = t?.query, a = B(this.baseURL, e);
326
+ let i = this.urlTemplateResolver.resolve(a, r);
327
+ if (n) {
328
+ const u = new URLSearchParams(n).toString();
329
+ u && (i += "?" + u);
330
+ }
331
+ return i;
332
+ }
333
+ /**
334
+ * Resolves a complete URL from a FetchRequest.
335
+ *
336
+ * Used internally by the Fetcher to build the final URL for a request
337
+ * by combining the request URL with its URL parameters using this UrlBuilder.
338
+ *
339
+ * @param request - The FetchRequest containing URL and URL parameters
340
+ * @returns Complete resolved URL string
341
+ */
342
+ resolveRequestUrl(e) {
343
+ return this.build(e.url, e.urlParams);
344
+ }
345
+ }
346
+ class d extends Error {
347
+ /**
348
+ * Creates a new FetcherError instance.
349
+ *
350
+ * @param errorMsg - Optional error message. If not provided, will use the cause's message or a default message.
351
+ * @param cause - Optional underlying error that caused this error.
352
+ */
353
+ constructor(e, t) {
354
+ const r = e || t?.message || "An error occurred in the fetcher";
355
+ super(r), this.cause = t, this.name = "FetcherError", t?.stack && (this.stack = t.stack), Object.setPrototypeOf(this, d.prototype);
356
+ }
357
+ }
358
+ class l extends d {
359
+ /**
360
+ * Creates a new ExchangeError instance.
361
+ *
362
+ * @param exchange - The FetchExchange object containing request/response/error information.
363
+ * @param errorMsg - An optional error message.
364
+ */
365
+ constructor(e, t) {
366
+ const r = t || e.error?.message || e.response?.statusText || `Request to ${e.request.url} failed during exchange`;
367
+ super(r, e.error), this.exchange = e, this.name = "ExchangeError", Object.setPrototypeOf(this, l.prototype);
368
+ }
369
+ }
370
+ class T extends d {
371
+ /**
372
+ * Creates a new FetchTimeoutError instance.
373
+ *
374
+ * @param request - The request options that timed out
375
+ */
376
+ constructor(e) {
377
+ const t = e.method || "GET", r = `Request timeout of ${e.timeout}ms exceeded for ${t} ${e.url}`;
378
+ super(r), this.name = "FetchTimeoutError", this.request = e, Object.setPrototypeOf(this, T.prototype);
379
+ }
380
+ }
381
+ function D(s, e) {
382
+ return typeof s < "u" ? s : e;
383
+ }
384
+ async function J(s) {
385
+ const e = s.url, t = s.timeout, r = s;
386
+ if (s.signal)
387
+ return await fetch(e, r);
388
+ if (!t)
389
+ return s.abortController && (r.signal = s.abortController.signal), await fetch(e, r);
390
+ const n = s.abortController ?? new AbortController();
391
+ s.abortController = n, r.signal = n.signal;
392
+ let a = null;
393
+ const i = new Promise((u, F) => {
394
+ a = setTimeout(() => {
395
+ a && clearTimeout(a);
396
+ const b = new T(s);
397
+ n.abort(b), F(b);
398
+ }, t);
399
+ });
400
+ try {
401
+ return await Promise.race([fetch(e, r), i]);
402
+ } finally {
403
+ a && clearTimeout(a);
404
+ }
405
+ }
406
+ const V = (s) => s, k = (s) => s.requiredResponse, R = {
407
+ /**
408
+ * Returns the original FetchExchange object
409
+ */
410
+ Exchange: V,
411
+ /**
412
+ * Extracts the raw Response object
413
+ */
414
+ Response: k
415
+ };
416
+ function z(s, e) {
417
+ if (e ??= /* @__PURE__ */ new Map(), !s)
418
+ return e;
419
+ if (s instanceof Map) {
420
+ for (const [t, r] of s)
421
+ e.set(t, r);
422
+ return e;
423
+ }
424
+ for (const [t, r] of Object.entries(s))
425
+ e.set(t, r);
426
+ return e;
427
+ }
428
+ class Q {
429
+ constructor(e) {
430
+ this.fetcher = e.fetcher, this.request = e.request, this.resultExtractor = e.resultExtractor ?? R.Exchange, this.attributes = z(e.attributes), this._response = e.response, this.error = e.error;
431
+ }
432
+ /**
433
+ * Ensures that request headers object exists, creating it if necessary.
434
+ *
435
+ * This method checks if the request headers object is present and initializes
436
+ * it as an empty object if it's missing. This guarantees that headers can
437
+ * be safely accessed and modified after calling this method.
438
+ *
439
+ * @returns The request headers object, guaranteed to be non-null
440
+ */
441
+ ensureRequestHeaders() {
442
+ return this.request.headers || (this.request.headers = {}), this.request.headers;
443
+ }
444
+ /**
445
+ * Ensures that request URL parameters object exists with all required properties,
446
+ * creating them if necessary.
447
+ *
448
+ * This method checks if the request URL parameters object is present and initializes
449
+ * it with empty path and query objects if it's missing. It also ensures that both
450
+ * path and query sub-objects exist. This guarantees that URL parameters can be
451
+ * safely accessed and modified after calling this method.
452
+ *
453
+ * @returns The request URL parameters object with guaranteed non-null path and query properties
454
+ */
455
+ ensureRequestUrlParams() {
456
+ return this.request.urlParams || (this.request.urlParams = {
457
+ path: {},
458
+ query: {}
459
+ }), this.request.urlParams.path || (this.request.urlParams.path = {}), this.request.urlParams.query || (this.request.urlParams.query = {}), this.request.urlParams;
460
+ }
461
+ /**
462
+ * Checks if the exchange has an error.
463
+ *
464
+ * @returns true if an error is present, false otherwise
465
+ */
466
+ hasError() {
467
+ return !!this.error;
468
+ }
469
+ /**
470
+ * Sets the response object for this exchange.
471
+ * Also invalidates the cached extracted result to ensure data consistency
472
+ * when the response changes.
473
+ *
474
+ * @param response - The Response object to set, or undefined to clear the response
475
+ */
476
+ set response(e) {
477
+ this._response = e, this.cachedExtractedResult = void 0;
478
+ }
479
+ /**
480
+ * Gets the response object for this exchange.
481
+ *
482
+ * @returns The response object if available, undefined otherwise
483
+ */
484
+ get response() {
485
+ return this._response;
486
+ }
487
+ /**
488
+ * Checks if the exchange has a response.
489
+ *
490
+ * @returns true if a response is present, false otherwise
491
+ */
492
+ hasResponse() {
493
+ return !!this.response;
494
+ }
495
+ /**
496
+ * Gets the required response object, throwing an error if no response is available.
497
+ *
498
+ * This getter ensures that a response object is available, and throws an ExchangeError
499
+ * with details about the request if no response was received. This is useful for
500
+ * guaranteeing that downstream code always has a valid Response object to work with.
501
+ *
502
+ * @throws {ExchangeError} If no response is available for the current exchange
503
+ * @returns The Response object for this exchange
504
+ */
505
+ get requiredResponse() {
506
+ if (!this.response)
507
+ throw new l(
508
+ this,
509
+ `Request to ${this.request.url} failed with no response`
510
+ );
511
+ return this.response;
512
+ }
513
+ /**
514
+ * Extracts the result by applying the result extractor to the exchange.
515
+ * The result is cached after the first computation to avoid repeated computations.
516
+ *
517
+ * @returns The extracted result
518
+ */
519
+ async extractResult() {
520
+ return this.cachedExtractedResult !== void 0 ? await this.cachedExtractedResult : (this.cachedExtractedResult = this.resultExtractor(this), await this.cachedExtractedResult);
521
+ }
522
+ }
523
+ var o = /* @__PURE__ */ ((s) => (s.GET = "GET", s.POST = "POST", s.PUT = "PUT", s.DELETE = "DELETE", s.PATCH = "PATCH", s.HEAD = "HEAD", s.OPTIONS = "OPTIONS", s.TRACE = "TRACE", s))(o || {});
524
+ const h = "Content-Type", y = class {
525
+ };
526
+ y.APPLICATION_JSON = "application/json", y.TEXT_EVENT_STREAM = "text/event-stream";
527
+ let C = y;
528
+ const Y = "UrlResolveInterceptor", O = Number.MIN_SAFE_INTEGER + 1e3;
529
+ class K {
530
+ constructor() {
531
+ this.name = Y, this.order = O;
532
+ }
533
+ /**
534
+ * Resolves the final URL by combining the base URL, path parameters, and query parameters.
535
+ *
536
+ * @param exchange - The fetch exchange containing the request information
537
+ */
538
+ intercept(e) {
539
+ const t = e.request;
540
+ t.url = e.fetcher.urlBuilder.resolveRequestUrl(t);
541
+ }
542
+ }
543
+ const W = "RequestBodyInterceptor", Z = O + 1e3;
544
+ class ee {
545
+ constructor() {
546
+ this.name = W, this.order = Z;
547
+ }
548
+ /**
549
+ * Checks if the provided body is of a supported complex type that doesn't require JSON serialization.
550
+ *
551
+ * @param body - The request body to check
552
+ * @returns True if the body is an ArrayBuffer, TypedArray, DataView or ReadableStream, false otherwise
553
+ */
554
+ isSupportedComplexBodyType(e) {
555
+ return e instanceof ArrayBuffer || ArrayBuffer.isView(e) || e instanceof ReadableStream;
556
+ }
557
+ /**
558
+ * Checks if the provided body is of a type that automatically appends Content-Type header.
559
+ *
560
+ * @param body - The request body to check
561
+ * @returns True if the body is a Blob, File, FormData or URLSearchParams, false otherwise
562
+ */
563
+ isAutoAppendContentType(e) {
564
+ return e instanceof Blob || e instanceof File || e instanceof FormData || e instanceof URLSearchParams;
565
+ }
566
+ /**
567
+ * Attempts to convert request body to a valid fetch API body type.
568
+ *
569
+ * This method follows a specific processing order to handle different types of request bodies:
570
+ * 1. Check if the body is null or undefined and return early if so
571
+ * 2. Check if the body is a non-object type and return early if so
572
+ * 3. Check if the body is a type that automatically appends Content-Type header
573
+ * 4. Check if the body is a supported complex type that doesn't require JSON serialization
574
+ * 5. For plain objects, convert to JSON string and set Content-Type header to application/json
575
+ *
576
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#setting_a_body}
577
+ *
578
+ * Supported types:
579
+ * - a string
580
+ * - ArrayBuffer
581
+ * - TypedArray
582
+ * - DataView
583
+ * - Blob
584
+ * - File
585
+ * - URLSearchParams
586
+ * - FormData
587
+ * - ReadableStream
588
+ *
589
+ * For unsupported object types (like plain objects), they will be automatically
590
+ * converted to JSON strings.
591
+ *
592
+ * @param exchange - The exchange object containing the request to process
593
+ *
594
+ * @example
595
+ * // Plain object body will be converted to JSON
596
+ * const fetcher = new Fetcher();
597
+ * const exchange = new FetchExchange(
598
+ * fetcher,
599
+ * {
600
+ * body: { name: 'John', age: 30 }
601
+ * }
602
+ * );
603
+ * interceptor.intercept(exchange);
604
+ * // exchange.request.body will be '{"name":"John","age":30}'
605
+ * // exchange.request.headers will include 'Content-Type: application/json'
606
+ */
607
+ intercept(e) {
608
+ const t = e.request;
609
+ if (t.body === void 0 || t.body === null || typeof t.body != "object")
610
+ return;
611
+ const r = e.ensureRequestHeaders();
612
+ if (this.isAutoAppendContentType(t.body)) {
613
+ r[h] && delete r[h];
614
+ return;
615
+ }
616
+ this.isSupportedComplexBodyType(t.body) || (e.request.body = JSON.stringify(t.body), r[h] || (r[h] = C.APPLICATION_JSON));
617
+ }
618
+ }
619
+ const te = "FetchInterceptor", re = Number.MAX_SAFE_INTEGER - 1e3;
620
+ class se {
621
+ constructor() {
622
+ this.name = te, this.order = re;
623
+ }
624
+ /**
625
+ * Intercept and process HTTP requests.
626
+ *
627
+ * Executes the actual HTTP request and applies timeout control. This is the final
628
+ * step in the request processing chain, responsible for calling the timeoutFetch
629
+ * function to send the network request.
630
+ *
631
+ * @param exchange - Exchange object containing request information
632
+ *
633
+ * @throws {FetchTimeoutError} Throws timeout exception when request times out
634
+ *
635
+ * @example
636
+ * // Usually called internally by Fetcher
637
+ * const fetcher = new Fetcher();
638
+ * const exchange = new FetchExchange(
639
+ * fetcher,
640
+ * {
641
+ * url: 'https://api.example.com/users',
642
+ * method: 'GET',
643
+ * timeout: 5000
644
+ * }
645
+ * );
646
+ * await fetchInterceptor.intercept(exchange);
647
+ * console.log(exchange.response); // HTTP response object
648
+ */
649
+ async intercept(e) {
650
+ e.response = await J(e.request);
651
+ }
652
+ }
653
+ const A = 0;
654
+ function q(s, e) {
655
+ return (s.order ?? A) - (e.order ?? A);
656
+ }
657
+ function c(s, e) {
658
+ return e ? s.filter(e).sort(q) : [...s].sort(q);
659
+ }
660
+ class p {
661
+ /**
662
+ * Initializes a new InterceptorRegistry instance.
663
+ *
664
+ * @param interceptors - Initial array of interceptors to manage
665
+ *
666
+ * @remarks
667
+ * The provided interceptors will be sorted by their order property immediately
668
+ * upon construction.
669
+ */
670
+ constructor(e = []) {
671
+ this.sortedInterceptors = [], this.sortedInterceptors = c(e);
672
+ }
673
+ /**
674
+ * Gets the name of this interceptor registry.
675
+ *
676
+ * @returns The constructor name of this class
677
+ */
678
+ get name() {
679
+ return this.constructor.name;
680
+ }
681
+ /**
682
+ * Gets the order of this interceptor registry.
683
+ *
684
+ * @returns Number.MIN_SAFE_INTEGER, indicating this registry should execute early
685
+ */
686
+ get order() {
687
+ return Number.MIN_SAFE_INTEGER;
688
+ }
689
+ /**
690
+ * Returns an array of all interceptors in the registry.
691
+ */
692
+ get interceptors() {
693
+ return [...this.sortedInterceptors];
694
+ }
695
+ /**
696
+ * Adds an interceptor to this registry.
697
+ *
698
+ * @param interceptor - The interceptor to add
699
+ * @returns True if the interceptor was added, false if an interceptor with the
700
+ * same name already exists
701
+ *
702
+ * @remarks
703
+ * Interceptors are uniquely identified by their name property. Attempting to add
704
+ * an interceptor with a name that already exists in the registry will fail.
705
+ *
706
+ * After adding, interceptors are automatically sorted by their order property.
707
+ */
708
+ use(e) {
709
+ return this.sortedInterceptors.some((t) => t.name === e.name) ? !1 : (this.sortedInterceptors = c([
710
+ ...this.sortedInterceptors,
711
+ e
712
+ ]), !0);
713
+ }
714
+ /**
715
+ * Removes an interceptor by name.
716
+ *
717
+ * @param name - The name of the interceptor to remove
718
+ * @returns True if an interceptor was removed, false if no interceptor with the
719
+ * given name was found
720
+ */
721
+ eject(e) {
722
+ const t = this.sortedInterceptors;
723
+ return this.sortedInterceptors = c(
724
+ t,
725
+ (r) => r.name !== e
726
+ ), t.length !== this.sortedInterceptors.length;
727
+ }
728
+ /**
729
+ * Removes all interceptors from this registry.
730
+ */
731
+ clear() {
732
+ this.sortedInterceptors = [];
733
+ }
734
+ /**
735
+ * Executes all managed interceptors on the given exchange object.
736
+ *
737
+ * @param exchange - The exchange object to process
738
+ * @returns A promise that resolves when all interceptors have been executed
739
+ *
740
+ * @remarks
741
+ * Interceptors are executed in order, with each interceptor receiving the result
742
+ * of the previous interceptor. The first interceptor receives the original
743
+ * exchange object.
744
+ *
745
+ * If any interceptor throws an error, the execution chain is broken and the error
746
+ * is propagated to the caller.
747
+ */
748
+ async intercept(e) {
749
+ for (const t of this.sortedInterceptors)
750
+ await t.intercept(e);
751
+ }
752
+ }
753
+ class P extends l {
754
+ constructor(e) {
755
+ super(
756
+ e,
757
+ `Request failed with status code ${e.response?.status} for ${e.request.url}`
758
+ ), this.name = "HttpStatusValidationError", Object.setPrototypeOf(this, P.prototype);
759
+ }
760
+ }
761
+ const ne = (s) => s >= 200 && s < 300, ae = "ValidateStatusInterceptor", oe = Number.MAX_SAFE_INTEGER - 1e3;
762
+ class ie {
763
+ /**
764
+ * Creates a new ValidateStatusInterceptor instance.
765
+ *
766
+ * @param validateStatus - Function that determines if a status code is valid
767
+ */
768
+ constructor(e = ne) {
769
+ this.validateStatus = e;
770
+ }
771
+ /**
772
+ * Gets the name of this interceptor.
773
+ *
774
+ * @returns The name of this interceptor
775
+ */
776
+ get name() {
777
+ return ae;
778
+ }
779
+ /**
780
+ * Gets the order of this interceptor.
781
+ *
782
+ * @returns VALIDATE_STATUS_INTERCEPTOR_ORDER, indicating this interceptor should execute early
783
+ */
784
+ get order() {
785
+ return oe;
786
+ }
787
+ /**
788
+ * Validates the response status code.
789
+ *
790
+ * @param exchange - The exchange containing the response to validate
791
+ * @throws HttpStatusValidationError if the status code is not valid
792
+ *
793
+ * @remarks
794
+ * This method runs at the beginning of the response interceptor chain to ensure
795
+ * status validation happens before any other response processing. Invalid responses
796
+ * are caught and converted to HttpStatusValidationError early in the pipeline,
797
+ * preventing other response handlers from attempting to process them. Valid responses
798
+ * proceed through the rest of the response interceptor chain normally.
799
+ */
800
+ intercept(e) {
801
+ if (!e.response)
802
+ return;
803
+ const t = e.response.status;
804
+ if (!this.validateStatus(t))
805
+ throw new P(e);
806
+ }
807
+ }
808
+ class ce {
809
+ constructor() {
810
+ this.request = new p([
811
+ new K(),
812
+ new ee(),
813
+ new se()
814
+ ]), this.response = new p([
815
+ new ie()
816
+ ]), this.error = new p();
817
+ }
818
+ /**
819
+ * Processes a FetchExchange through the interceptor pipeline.
820
+ *
821
+ * This method is the core of the Fetcher's interceptor system. It executes the three
822
+ * phases of interceptors in sequence:
823
+ * 1. Request interceptors - Process the request before sending
824
+ * 2. Response interceptors - Process the response after receiving
825
+ * 3. Error interceptors - Handle any errors that occurred during the process
826
+ *
827
+ * The interceptor pipeline follows the Chain of Responsibility pattern, where each
828
+ * interceptor can modify the exchange object and decide whether to continue or
829
+ * terminate the chain.
830
+ *
831
+ * @param fetchExchange - The exchange object containing request, response, and error information
832
+ * @returns Promise that resolves to the processed FetchExchange
833
+ * @throws ExchangeError if an unhandled error occurs during processing
834
+ *
835
+ * @remarks
836
+ * The method handles three distinct phases:
837
+ *
838
+ * 1. Request Phase: Executes request interceptors which can modify headers, URL, body, etc.
839
+ * Built-in interceptors handle URL resolution, body serialization, and actual HTTP execution.
840
+ *
841
+ * 2. Response Phase: Executes response interceptors which can transform or validate responses.
842
+ * These interceptors only run if the request phase completed without throwing.
843
+ *
844
+ * 3. Error Phase: Executes error interceptors when any phase throws an error. Error interceptors
845
+ * can handle errors by clearing the error property. If error interceptors clear the error,
846
+ * the exchange is returned successfully.
847
+ *
848
+ * Error Handling:
849
+ * - If any interceptor throws an error, the error phase is triggered
850
+ * - Error interceptors can "fix" errors by clearing the error property on the exchange
851
+ * - If errors remain after error interceptors run, they are wrapped in ExchangeError
852
+ *
853
+ * Order of Execution:
854
+ * 1. Request interceptors (sorted by order property, ascending)
855
+ * 2. Response interceptors (sorted by order property, ascending) - only if no error in request phase
856
+ * 3. Error interceptors (sorted by order property, ascending) - only if an error occurred
857
+ *
858
+ * @example
859
+ * ```typescript
860
+ * // Create a fetcher with custom interceptors
861
+ * const fetcher = new Fetcher();
862
+ *
863
+ * // Add a request interceptor
864
+ * fetcher.interceptors.request.use({
865
+ * name: 'AuthInterceptor',
866
+ * order: 100,
867
+ * async intercept(exchange: FetchExchange) {
868
+ * exchange.request.headers = {
869
+ * ...exchange.request.headers,
870
+ * 'Authorization': 'Bearer ' + getToken()
871
+ * };
872
+ * }
873
+ * });
874
+ *
875
+ * // Add a response interceptor
876
+ * fetcher.interceptors.response.use({
877
+ * name: 'ResponseLogger',
878
+ * order: 100,
879
+ * async intercept(exchange: FetchExchange) {
880
+ * console.log(`Response status: ${exchange.response?.status}`);
881
+ * }
882
+ * });
883
+ *
884
+ * // Add an error interceptor
885
+ * fetcher.interceptors.error.use({
886
+ * name: 'ErrorLogger',
887
+ * order: 100,
888
+ * async intercept(exchange: FetchExchange) {
889
+ * console.error(`Request to ${exchange.request.url} failed:`, exchange.error);
890
+ * // Clear the error to indicate it's been handled
891
+ * exchange.error = undefined;
892
+ * }
893
+ * });
894
+ *
895
+ * // Create and process an exchange
896
+ * const request: FetchRequest = {
897
+ * url: '/api/users',
898
+ * method: HttpMethod.GET
899
+ * };
900
+ * const exchange = new FetchExchange(fetcher, request);
901
+ * const result = await fetcher.exchange(exchange);
902
+ * ```
903
+ */
904
+ async exchange(e) {
905
+ try {
906
+ return await this.request.intercept(e), await this.response.intercept(e), e;
907
+ } catch (t) {
908
+ if (e.error = t, await this.error.intercept(e), !e.hasError())
909
+ return e;
910
+ throw new l(e);
911
+ }
912
+ }
913
+ }
914
+ function f(s, e) {
915
+ return e && e.resultExtractor && e.attributes ? e : {
916
+ resultExtractor: e?.resultExtractor ?? s?.resultExtractor ?? _.resultExtractor,
917
+ attributes: e?.attributes ?? s?.attributes
918
+ };
919
+ }
920
+ const w = {
921
+ [h]: C.APPLICATION_JSON
922
+ }, N = {
923
+ baseURL: "",
924
+ headers: w
925
+ }, _ = {
926
+ resultExtractor: R.Exchange
927
+ }, x = {
928
+ resultExtractor: R.Response
929
+ };
930
+ class ue {
931
+ /**
932
+ * Initializes a new Fetcher instance with optional configuration.
933
+ *
934
+ * Creates a Fetcher with default settings that can be overridden through the options parameter.
935
+ * If no interceptors are provided, a default set of interceptors will be used.
936
+ *
937
+ * @param options - Configuration options for the Fetcher instance
938
+ * @param options.baseURL - The base URL to prepend to all requests. Defaults to empty string.
939
+ * @param options.headers - Default headers to include in all requests. Defaults to JSON content type.
940
+ * @param options.timeout - Default timeout for requests in milliseconds. No timeout by default.
941
+ * @param options.urlTemplateStyle - Style for URL template parameter interpolation.
942
+ * @param options.interceptors - Interceptor manager for processing requests and responses.
943
+ */
944
+ constructor(e = N) {
945
+ this.headers = w, this.urlBuilder = new j(e.baseURL, e.urlTemplateStyle), this.headers = e.headers ?? w, this.timeout = e.timeout, this.interceptors = e.interceptors ?? new ce();
946
+ }
947
+ /**
948
+ * Processes an HTTP request through the Fetcher's internal workflow.
949
+ *
950
+ * This method creates a FetchExchange object and passes it through the interceptor chain.
951
+ * It handles header merging, timeout resolution, and result extractor configuration.
952
+ *
953
+ * @param request - The HTTP request configuration to process
954
+ * @param options - Optional request options including result extractor and attributes
955
+ * @returns Promise that resolves to the processed FetchExchange object
956
+ */
957
+ async exchange(e, t) {
958
+ const r = {
959
+ ...this.headers,
960
+ ...e.headers
961
+ }, n = {
962
+ ...e,
963
+ headers: r,
964
+ timeout: D(e.timeout, this.timeout)
965
+ }, { resultExtractor: a, attributes: i } = f(
966
+ _,
967
+ t
968
+ ), u = new Q({
969
+ fetcher: this,
970
+ request: n,
971
+ resultExtractor: a,
972
+ attributes: i
973
+ });
974
+ return await this.interceptors.exchange(u);
975
+ }
976
+ /**
977
+ * Processes an HTTP request through the Fetcher's internal workflow.
978
+ *
979
+ * This method prepares the request by merging headers and timeout settings,
980
+ * creates a FetchExchange object, and passes it through the exchange method
981
+ * for interceptor processing.
982
+ *
983
+ * @template R - The type of the result to be returned
984
+ * @param request - Complete request configuration object
985
+ * @param options - Request options including result extractor and attributes
986
+ * @param options.resultExtractor - Function to extract the desired result from the exchange.
987
+ * Defaults to ExchangeResultExtractor which returns the entire exchange object.
988
+ * @param options.attributes - Optional shared attributes that can be accessed by interceptors
989
+ * throughout the request lifecycle. These attributes allow passing
990
+ * custom data between different interceptors.
991
+ * @returns Promise that resolves to the extracted result based on resultExtractor
992
+ * @throws Error if an unhandled error occurs during request processing
993
+ */
994
+ async request(e, t) {
995
+ return await (await this.exchange(e, t)).extractResult();
996
+ }
997
+ /**
998
+ * Executes an HTTP request with the specified URL and options.
999
+ *
1000
+ * This is the primary method for making HTTP requests. It processes the request
1001
+ * through the interceptor chain and returns the resulting Response.
1002
+ *
1003
+ * @template R - The type of the result to be returned
1004
+ * @param url - The URL path for the request (relative to baseURL if set)
1005
+ * @param request - Request configuration including headers, body, parameters, etc.
1006
+ * @param options - Request options including result extractor and attributes
1007
+ * @param options.resultExtractor - Function to extract the desired result from the exchange.
1008
+ * Defaults to ResponseResultExtractor which returns the entire exchange object.
1009
+ * @param options.attributes - Optional shared attributes that can be accessed by interceptors
1010
+ * throughout the request lifecycle. These attributes allow passing
1011
+ * custom data between different interceptors.
1012
+ * @returns Promise that resolves to the HTTP response
1013
+ * @throws FetchError if the request fails and no response is generated
1014
+ */
1015
+ async fetch(e, t = {}, r) {
1016
+ const n = {
1017
+ ...t,
1018
+ url: e
1019
+ };
1020
+ return await this.request(
1021
+ n,
1022
+ f(x, r)
1023
+ );
1024
+ }
1025
+ /**
1026
+ * Internal helper method for making HTTP requests with a specific method.
1027
+ *
1028
+ * This private method is used by the public HTTP method methods (get, post, etc.)
1029
+ * to execute requests with the appropriate HTTP verb.
1030
+ *
1031
+ * @template R - The type of the result to be returned
1032
+ * @param method - The HTTP method to use for the request
1033
+ * @param url - The URL path for the request
1034
+ * @param request - Additional request options
1035
+ * @param options - Request options including result extractor and attributes
1036
+ * @param options.resultExtractor - Function to extract the desired result from the exchange.
1037
+ * Defaults to ResponseResultExtractor which returns the entire exchange object.
1038
+ * @param options.attributes - Optional shared attributes that can be accessed by interceptors
1039
+ * throughout the request lifecycle. These attributes allow passing
1040
+ * custom data between different interceptors.
1041
+ * @returns Promise that resolves to the HTTP response
1042
+ */
1043
+ async methodFetch(e, t, r = {}, n) {
1044
+ const a = {
1045
+ ...r,
1046
+ url: t,
1047
+ method: e
1048
+ };
1049
+ return await this.request(
1050
+ a,
1051
+ f(x, n)
1052
+ );
1053
+ }
1054
+ /**
1055
+ * Makes a GET HTTP request.
1056
+ *
1057
+ * Convenience method for making GET requests. The request body is omitted
1058
+ * as GET requests should not contain a body according to HTTP specification.
1059
+ *
1060
+ * @template R - The type of the result to be returned
1061
+ * @param url - The URL path for the request
1062
+ * @param request - Request options excluding method and body
1063
+ * @param options - Request options including result extractor and attributes
1064
+ * @param options.resultExtractor - Function to extract the desired result from the exchange.
1065
+ * Defaults to ResponseResultExtractor which returns the entire exchange object.
1066
+ * @param options.attributes - Optional shared attributes that can be accessed by interceptors
1067
+ * throughout the request lifecycle. These attributes allow passing
1068
+ * custom data between different interceptors.
1069
+ * @returns Promise that resolves to the HTTP response
1070
+ */
1071
+ async get(e, t = {}, r) {
1072
+ return await this.methodFetch(o.GET, e, t, r);
1073
+ }
1074
+ /**
1075
+ * Makes a PUT HTTP request.
1076
+ *
1077
+ * Convenience method for making PUT requests, commonly used for updating resources.
1078
+ *
1079
+ * @template R - The type of the result to be returned
1080
+ * @param url - The URL path for the request
1081
+ * @param request - Request options including body and other parameters
1082
+ * @param options - Request options including result extractor and attributes
1083
+ * @param options.resultExtractor - Function to extract the desired result from the exchange.
1084
+ * Defaults to ResponseResultExtractor which returns the entire exchange object.
1085
+ * @param options.attributes - Optional shared attributes that can be accessed by interceptors
1086
+ * throughout the request lifecycle. These attributes allow passing
1087
+ * custom data between different interceptors.
1088
+ * @returns Promise that resolves to the HTTP response
1089
+ */
1090
+ async put(e, t = {}, r) {
1091
+ return await this.methodFetch(o.PUT, e, t, r);
1092
+ }
1093
+ /**
1094
+ * Makes a POST HTTP request.
1095
+ *
1096
+ * Convenience method for making POST requests, commonly used for creating resources.
1097
+ *
1098
+ * @template R - The type of the result to be returned
1099
+ * @param url - The URL path for the request
1100
+ * @param request - Request options including body and other parameters
1101
+ * @param options - Request options including result extractor and attributes
1102
+ * @param options.resultExtractor - Function to extract the desired result from the exchange.
1103
+ * Defaults to ResponseResultExtractor which returns the entire exchange object.
1104
+ * @param options.attributes - Optional shared attributes that can be accessed by interceptors
1105
+ * throughout the request lifecycle. These attributes allow passing
1106
+ * custom data between different interceptors.
1107
+ * @returns Promise that resolves to the HTTP response
1108
+ */
1109
+ async post(e, t = {}, r) {
1110
+ return await this.methodFetch(o.POST, e, t, r);
1111
+ }
1112
+ /**
1113
+ * Makes a PATCH HTTP request.
1114
+ *
1115
+ * Convenience method for making PATCH requests, commonly used for partial updates.
1116
+ *
1117
+ * @template R - The type of the result to be returned
1118
+ * @param url - The URL path for the request
1119
+ * @param request - Request options including body and other parameters
1120
+ * @param options - Request options including result extractor and attributes
1121
+ * @param options.resultExtractor - Function to extract the desired result from the exchange.
1122
+ * Defaults to ResponseResultExtractor which returns the entire exchange object.
1123
+ * @param options.attributes - Optional shared attributes that can be accessed by interceptors
1124
+ * throughout the request lifecycle. These attributes allow passing
1125
+ * custom data between different interceptors.
1126
+ * @returns Promise that resolves to the HTTP response
1127
+ */
1128
+ async patch(e, t = {}, r) {
1129
+ return await this.methodFetch(o.PATCH, e, t, r);
1130
+ }
1131
+ /**
1132
+ * Makes a DELETE HTTP request.
1133
+ *
1134
+ * Convenience method for making DELETE requests, commonly used for deleting resources.
1135
+ *
1136
+ * @template R - The type of the result to be returned
1137
+ * @param url - The URL path for the request
1138
+ * @param request - Request options excluding method and body
1139
+ * @param options - Request options including result extractor and attributes
1140
+ * @param options.resultExtractor - Function to extract the desired result from the exchange.
1141
+ * Defaults to ResponseResultExtractor which returns the entire exchange object.
1142
+ * @param options.attributes - Optional shared attributes that can be accessed by interceptors
1143
+ * throughout the request lifecycle. These attributes allow passing
1144
+ * custom data between different interceptors.
1145
+ * @returns Promise that resolves to the HTTP response
1146
+ */
1147
+ async delete(e, t = {}, r) {
1148
+ return await this.methodFetch(o.DELETE, e, t, r);
1149
+ }
1150
+ /**
1151
+ * Makes a HEAD HTTP request.
1152
+ *
1153
+ * Convenience method for making HEAD requests, which retrieve headers only.
1154
+ * The request body is omitted as HEAD requests should not contain a body.
1155
+ *
1156
+ * @template R - The type of the result to be returned
1157
+ * @param url - The URL path for the request
1158
+ * @param request - Request options excluding method and body
1159
+ * @param options - Request options including result extractor and attributes
1160
+ * @param options.resultExtractor - Function to extract the desired result from the exchange.
1161
+ * Defaults to ResponseResultExtractor which returns the entire exchange object.
1162
+ * @param options.attributes - Optional shared attributes that can be accessed by interceptors
1163
+ * throughout the request lifecycle. These attributes allow passing
1164
+ * custom data between different interceptors.
1165
+ * @returns Promise that resolves to the HTTP response
1166
+ */
1167
+ async head(e, t = {}, r) {
1168
+ return await this.methodFetch(o.HEAD, e, t, r);
1169
+ }
1170
+ /**
1171
+ * Makes an OPTIONS HTTP request.
1172
+ *
1173
+ * Convenience method for making OPTIONS requests, commonly used for CORS preflight.
1174
+ * The request body is omitted as OPTIONS requests typically don't contain a body.
1175
+ *
1176
+ * @template R - The type of the result to be returned
1177
+ * @param url - The URL path for the request
1178
+ * @param request - Request options excluding method and body
1179
+ * @param options - Request options including result extractor and attributes
1180
+ * @param options.resultExtractor - Function to extract the desired result from the exchange.
1181
+ * Defaults to ResponseResultExtractor which returns the entire exchange object.
1182
+ * @param options.attributes - Optional shared attributes that can be accessed by interceptors
1183
+ * throughout the request lifecycle. These attributes allow passing
1184
+ * custom data between different interceptors.
1185
+ * @returns Promise that resolves to the HTTP response
1186
+ */
1187
+ async options(e, t = {}, r) {
1188
+ return await this.methodFetch(o.OPTIONS, e, t, r);
1189
+ }
1190
+ /**
1191
+ * Sends an HTTP TRACE request to the specified URL and returns the response.
1192
+ *
1193
+ * The TRACE method is used to echo the received request for debugging purposes.
1194
+ * This method automatically sets the HTTP method to TRACE and omits the request body
1195
+ * since TRACE requests must not have a body according to the HTTP specification.
1196
+ *
1197
+ * @param url - The target URL for the TRACE request. Must be a valid absolute or relative URL.
1198
+ * @param request - Request configuration options excluding 'method' and 'body' properties.
1199
+ * Defaults to an empty object. Common properties include headers, cache settings, etc.
1200
+ * @param options - Optional additional request parameters for extended functionality.
1201
+ * May include custom handling logic or metadata for the request pipeline.
1202
+ * @returns A Promise resolving to the response object of type R (defaults to Response).
1203
+ * The response contains status, headers, and body data from the TRACE request.
1204
+ */
1205
+ async trace(e, t = {}, r) {
1206
+ return await this.methodFetch(o.TRACE, e, t, r);
1207
+ }
1208
+ }
1209
+ const g = "default";
1210
+ class he {
1211
+ constructor() {
1212
+ this.registrar = /* @__PURE__ */ new Map();
1213
+ }
1214
+ /**
1215
+ * Register a Fetcher instance with a given name
1216
+ *
1217
+ * @param name - The name to register the fetcher under
1218
+ * @param fetcher - The Fetcher instance to register
1219
+ * @example
1220
+ * const fetcher = new Fetcher({ baseURL: 'https://api.example.com' });
1221
+ * fetcherRegistrar.register('api', fetcher);
1222
+ */
1223
+ register(e, t) {
1224
+ this.registrar.set(e, t);
1225
+ }
1226
+ /**
1227
+ * Unregister a Fetcher instance by name
1228
+ *
1229
+ * @param name - The name of the fetcher to unregister
1230
+ * @returns boolean - True if the fetcher was successfully unregistered, false otherwise
1231
+ * @example
1232
+ * const success = fetcherRegistrar.unregister('api');
1233
+ * if (success) {
1234
+ * console.log('Fetcher unregistered successfully');
1235
+ * }
1236
+ */
1237
+ unregister(e) {
1238
+ return this.registrar.delete(e);
1239
+ }
1240
+ /**
1241
+ * Get a Fetcher instance by name
1242
+ *
1243
+ * @param name - The name of the fetcher to retrieve
1244
+ * @returns Fetcher | undefined - The Fetcher instance if found, undefined otherwise
1245
+ * @example
1246
+ * const fetcher = fetcherRegistrar.get('api');
1247
+ * if (fetcher) {
1248
+ * // Use the fetcher
1249
+ * }
1250
+ */
1251
+ get(e) {
1252
+ return this.registrar.get(e);
1253
+ }
1254
+ /**
1255
+ * Get a Fetcher instance by name, throwing an error if not found
1256
+ *
1257
+ * @param name - The name of the fetcher to retrieve
1258
+ * @returns Fetcher - The Fetcher instance
1259
+ * @throws Error - If no fetcher is registered with the given name
1260
+ * @example
1261
+ * try {
1262
+ * const fetcher = fetcherRegistrar.requiredGet('api');
1263
+ * // Use the fetcher
1264
+ * } catch (error) {
1265
+ * console.error('Fetcher not found:', error.message);
1266
+ * }
1267
+ */
1268
+ requiredGet(e) {
1269
+ const t = this.get(e);
1270
+ if (!t)
1271
+ throw new Error(`Fetcher ${e} not found`);
1272
+ return t;
1273
+ }
1274
+ /**
1275
+ * Get the default Fetcher instance
1276
+ *
1277
+ * @returns Fetcher - The default Fetcher instance
1278
+ * @throws Error - If no default fetcher is registered
1279
+ * @example
1280
+ * const defaultFetcher = fetcherRegistrar.default;
1281
+ */
1282
+ get default() {
1283
+ return this.requiredGet(g);
1284
+ }
1285
+ /**
1286
+ * Set the default Fetcher instance
1287
+ *
1288
+ * @param fetcher - The Fetcher instance to set as default
1289
+ * @example
1290
+ * const fetcher = new Fetcher({ baseURL: 'https://api.example.com' });
1291
+ * fetcherRegistrar.default = fetcher;
1292
+ */
1293
+ set default(e) {
1294
+ this.register(g, e);
1295
+ }
1296
+ /**
1297
+ * Get a copy of all registered fetchers
1298
+ *
1299
+ * @returns Map<string, Fetcher> - A copy of the internal registrar map
1300
+ * @example
1301
+ * const allFetchers = fetcherRegistrar.fetchers;
1302
+ * for (const [name, fetcher] of allFetchers) {
1303
+ * console.log(`Fetcher ${name}:`, fetcher);
1304
+ * }
1305
+ */
1306
+ get fetchers() {
1307
+ return new Map(this.registrar);
1308
+ }
1309
+ }
1310
+ const le = new he();
1311
+ class de extends ue {
1312
+ /**
1313
+ * Create a NamedFetcher instance and automatically register it with the global fetcherRegistrar
1314
+ *
1315
+ * @param name - The name to register this fetcher under
1316
+ * @param options - Fetcher configuration options (same as Fetcher constructor)
1317
+ *
1318
+ * @example
1319
+ * // Create with default options
1320
+ * const fetcher1 = new NamedFetcher('default');
1321
+ *
1322
+ * // Create with custom options
1323
+ * const fetcher2 = new NamedFetcher('api', {
1324
+ * baseURL: 'https://api.example.com',
1325
+ * timeout: 5000,
1326
+ * headers: { 'Authorization': 'Bearer token' }
1327
+ * });
1328
+ */
1329
+ constructor(e, t = N) {
1330
+ super(t), this.name = e, le.register(e, this);
1331
+ }
1332
+ }
1333
+ new de(g);
1334
+ class Ee {
1335
+ /**
1336
+ * Creates an in-memory typed event bus
1337
+ *
1338
+ * @param type - The event type identifier for this bus
1339
+ */
1340
+ constructor(e) {
1341
+ this.type = e, this.sortedHandlers = [];
1342
+ }
1343
+ /**
1344
+ * Gets a copy of all registered event handlers, sorted by order
1345
+ */
1346
+ get handlers() {
1347
+ return [...this.sortedHandlers];
1348
+ }
1349
+ /**
1350
+ * Emits an event to all registered handlers serially
1351
+ *
1352
+ * Handlers are executed in order of their priority. Once-only handlers are removed after execution.
1353
+ * Errors in individual handlers are logged but do not stop other handlers.
1354
+ *
1355
+ * @param event - The event to emit
1356
+ */
1357
+ async emit(e) {
1358
+ const t = [];
1359
+ for (const r of this.sortedHandlers)
1360
+ try {
1361
+ await r.handle(e);
1362
+ } catch (n) {
1363
+ console.warn(`Event handler error for ${r.name}:`, n);
1364
+ } finally {
1365
+ r.once && t.push(r);
1366
+ }
1367
+ t.length > 0 && (this.sortedHandlers = c(
1368
+ this.sortedHandlers.filter((r) => !t.includes(r))
1369
+ ));
1370
+ }
1371
+ /**
1372
+ * Removes an event handler by name
1373
+ *
1374
+ * @param name - The name of the handler to remove
1375
+ * @returns true if a handler was removed, false otherwise
1376
+ */
1377
+ off(e) {
1378
+ const t = this.sortedHandlers;
1379
+ return t.some((r) => r.name === e) ? (this.sortedHandlers = c(t, (r) => r.name !== e), !0) : !1;
1380
+ }
1381
+ /**
1382
+ * Adds an event handler if not already present
1383
+ *
1384
+ * Handlers are sorted by their order property after addition.
1385
+ *
1386
+ * @param handler - The event handler to add
1387
+ * @returns true if the handler was added, false if a handler with the same name already exists
1388
+ */
1389
+ on(e) {
1390
+ const t = this.sortedHandlers;
1391
+ return t.some((r) => r.name === e.name) ? !1 : (this.sortedHandlers = c([...t, e]), !0);
1392
+ }
1393
+ destroy() {
1394
+ this.sortedHandlers = [];
1395
+ }
1396
+ }
1397
+ class ye {
1398
+ /**
1399
+ * Creates a broadcast typed event bus
1400
+ *
1401
+ * @param delegate - The underlying TypedEventBus for local event handling
1402
+ * @param channel - Optional custom BroadcastChannel name; defaults to `_broadcast_:{type}`
1403
+ */
1404
+ constructor(e, t) {
1405
+ this.delegate = e, this.type = e.type;
1406
+ const r = t ?? `_broadcast_:${this.type}`;
1407
+ this.broadcastChannel = new BroadcastChannel(r), this.broadcastChannel.onmessage = async (n) => {
1408
+ try {
1409
+ await this.delegate.emit(n.data);
1410
+ } catch (a) {
1411
+ console.warn(`Broadcast event handler error for ${this.type}:`, a);
1412
+ }
1413
+ };
1414
+ }
1415
+ /**
1416
+ * Gets a copy of all registered event handlers from the delegate
1417
+ */
1418
+ get handlers() {
1419
+ return this.delegate.handlers;
1420
+ }
1421
+ /**
1422
+ * Emits an event locally and broadcasts it to other tabs/windows
1423
+ *
1424
+ * @param event - The event to emit
1425
+ */
1426
+ async emit(e) {
1427
+ await this.delegate.emit(e), this.broadcastChannel.postMessage(e);
1428
+ }
1429
+ /**
1430
+ * Removes an event handler by name from the delegate
1431
+ *
1432
+ * @param name - The name of the handler to remove
1433
+ * @returns true if a handler was removed, false otherwise
1434
+ */
1435
+ off(e) {
1436
+ return this.delegate.off(e);
1437
+ }
1438
+ /**
1439
+ * Adds an event handler to the delegate
1440
+ *
1441
+ * @param handler - The event handler to add
1442
+ * @returns true if the handler was added, false if a handler with the same name already exists
1443
+ */
1444
+ on(e) {
1445
+ return this.delegate.on(e);
1446
+ }
1447
+ /**
1448
+ * Cleans up resources by closing the BroadcastChannel
1449
+ */
1450
+ destroy() {
1451
+ this.broadcastChannel.close();
1452
+ }
1453
+ }
1454
+ export {
1455
+ ye as BroadcastTypedEventBus,
1456
+ pe as EventBus,
1457
+ fe as ParallelTypedEventBus,
1458
+ Ee as SerialTypedEventBus
1459
+ };
1460
+ //# sourceMappingURL=index.es.js.map