@d1g1tal/transportr 1.0.0 → 1.2.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.
@@ -54,6 +54,10 @@ var Transportr = (() => {
54
54
  var _type = (object) => object?.constructor ?? object?.prototype?.constructor ?? globalThis[Object.prototype.toString.call(object).slice(8, -1)] ?? object;
55
55
  var object_type_default = _type;
56
56
 
57
+ // node_modules/@d1g1tal/chrysalis/src/esm/object-is-empty.js
58
+ var _objectIsEmpty = (object) => !!object && Object.keys(object).length === 0 && object.constructor === Object;
59
+ var object_is_empty_default = _objectIsEmpty;
60
+
57
61
  // node_modules/@d1g1tal/chrysalis/src/esm/object-merge.js
58
62
  var _objectMerge = (...objects) => {
59
63
  const target = {};
@@ -78,10 +82,6 @@ var Transportr = (() => {
78
82
  };
79
83
  var object_merge_default = _objectMerge;
80
84
 
81
- // node_modules/@d1g1tal/chrysalis/src/esm/object-is-empty.js
82
- var _objectIsEmpty = (object) => !!object && Object.keys(object).length === 0 && object.constructor === Object;
83
- var object_is_empty_default = _objectIsEmpty;
84
-
85
85
  // node_modules/@d1g1tal/collections/src/set-multi-map.js
86
86
  var SetMultiMap = class extends Map {
87
87
  /**
@@ -101,34 +101,33 @@ var Transportr = (() => {
101
101
  };
102
102
 
103
103
  // node_modules/@d1g1tal/media-type/src/utils.js
104
- var removeLeadingAndTrailingHTTPWhitespace = (string) => string.replace(/^[ \t\n\r]+/u, "").replace(/[ \t\n\r]+$/u, "");
105
- var removeTrailingHTTPWhitespace = (string) => string.replace(/[ \t\n\r]+$/u, "");
106
- var isHTTPWhitespaceChar = (char) => char === " " || char === " " || char === "\n" || char === "\r";
107
- var solelyContainsHTTPTokenCodePoints = (string) => /^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/u.test(string);
108
- var solelyContainsHTTPQuotedStringTokenCodePoints = (string) => /^[\t\u0020-\u007E\u0080-\u00FF]*$/u.test(string);
109
- var asciiLowercase = (string) => string.replace(/[A-Z]/ug, (l) => l.toLowerCase());
104
+ var whitespaceCharacters = [" ", " ", "\n", "\r"];
105
+ var leadingWhitespace = /^[ \t\n\r]+/u;
106
+ var trailingWhitespace = /[ \t\n\r]+$/u;
107
+ var httpTokenCodePoints = /^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/u;
108
+ var httpQuotedTokenCodePoints = /^[\t\u0020-\u007E\u0080-\u00FF]*$/u;
109
+ var removeLeadingAndTrailingHTTPWhitespace = (string) => string.replace(leadingWhitespace, "").replace(trailingWhitespace, "");
110
+ var removeTrailingHTTPWhitespace = (string) => string.replace(trailingWhitespace, "");
111
+ var isHTTPWhitespaceChar = (char) => whitespaceCharacters.includes(char);
112
+ var solelyContainsHTTPTokenCodePoints = (string) => httpTokenCodePoints.test(string);
113
+ var solelyContainsHTTPQuotedStringTokenCodePoints = (string) => httpQuotedTokenCodePoints.test(string);
114
+ var asciiLowercase = (string) => {
115
+ let result = "";
116
+ for (const [char, charCode = char.charCodeAt(0)] of string) {
117
+ result += charCode >= 65 && charCode <= 90 ? String.fromCharCode(charCode + 32) : char;
118
+ }
119
+ return result;
120
+ };
110
121
  var collectAnHTTPQuotedString = (input, position) => {
111
122
  let value = "";
112
- position++;
113
- while (true) {
114
- while (position < input.length && input[position] !== '"' && input[position] !== "\\") {
115
- value += input[position];
116
- ++position;
117
- }
118
- if (position >= input.length) {
123
+ for (let length = input.length, char; ++position < length; ) {
124
+ char = input[position];
125
+ if (char == "\\") {
126
+ value += ++position < length ? input[position] : char;
127
+ } else if (char == '"') {
119
128
  break;
120
- }
121
- const quoteOrBackslash = input[position];
122
- ++position;
123
- if (quoteOrBackslash === "\\") {
124
- if (position >= input.length) {
125
- value += "\\";
126
- break;
127
- }
128
- value += input[position];
129
- ++position;
130
129
  } else {
131
- break;
130
+ value += char;
132
131
  }
133
132
  }
134
133
  return [value, position];
@@ -136,13 +135,15 @@ var Transportr = (() => {
136
135
 
137
136
  // node_modules/@d1g1tal/media-type/src/media-type-parameters.js
138
137
  var MediaTypeParameters = class {
138
+ /** @type {Map<string, string>} */
139
+ #map;
139
140
  /**
140
141
  * Create a new MediaTypeParameters instance.
141
142
  *
142
- * @param {Map.<string, string>} map The map of parameters for a media type.
143
+ * @param {Array<Array<string>>} entries An array of [name, value] tuples.
143
144
  */
144
- constructor(map) {
145
- this._map = map;
145
+ constructor(entries) {
146
+ this.#map = new Map(entries);
146
147
  }
147
148
  /**
148
149
  * Gets the number of media type parameters.
@@ -150,7 +151,7 @@ var Transportr = (() => {
150
151
  * @returns {number} The number of media type parameters
151
152
  */
152
153
  get size() {
153
- return this._map.size;
154
+ return this.#map.size;
154
155
  }
155
156
  /**
156
157
  * Gets the media type parameter value for the supplied name.
@@ -159,7 +160,7 @@ var Transportr = (() => {
159
160
  * @returns {string} The media type parameter value.
160
161
  */
161
162
  get(name) {
162
- return this._map.get(asciiLowercase(String(name)));
163
+ return this.#map.get(asciiLowercase(String(name)));
163
164
  }
164
165
  /**
165
166
  * Indicates whether the media type parameter with the specified name exists or not.
@@ -168,7 +169,7 @@ var Transportr = (() => {
168
169
  * @returns {boolean} true if the media type parameter exists, false otherwise.
169
170
  */
170
171
  has(name) {
171
- return this._map.has(asciiLowercase(String(name)));
172
+ return this.#map.has(asciiLowercase(String(name)));
172
173
  }
173
174
  /**
174
175
  * Adds a new media type parameter using the specified name and value to the MediaTypeParameters.
@@ -187,14 +188,14 @@ var Transportr = (() => {
187
188
  if (!solelyContainsHTTPQuotedStringTokenCodePoints(value)) {
188
189
  throw new Error(`Invalid media type parameter value "${value}": only HTTP quoted-string token code points are valid.`);
189
190
  }
190
- this._map.set(name, value);
191
+ this.#map.set(name, value);
191
192
  return this;
192
193
  }
193
194
  /**
194
195
  * Clears all the media type parameters.
195
196
  */
196
197
  clear() {
197
- this._map.clear();
198
+ this.#map.clear();
198
199
  }
199
200
  /**
200
201
  * Removes the media type parameter using the specified name.
@@ -204,7 +205,7 @@ var Transportr = (() => {
204
205
  */
205
206
  delete(name) {
206
207
  name = asciiLowercase(String(name));
207
- return this._map.delete(name);
208
+ return this.#map.delete(name);
208
209
  }
209
210
  /**
210
211
  * Executes a provided function once per each name/value pair in the MediaTypeParameters, in insertion order.
@@ -213,7 +214,7 @@ var Transportr = (() => {
213
214
  * @param {*} [thisArg] Optional object when binding 'this' to the callback.
214
215
  */
215
216
  forEach(callback, thisArg) {
216
- this._map.forEach(callback, thisArg);
217
+ this.#map.forEach(callback, thisArg);
217
218
  }
218
219
  /**
219
220
  * Returns an iterable of parameter names.
@@ -221,7 +222,7 @@ var Transportr = (() => {
221
222
  * @returns {IterableIterator<string>} The {@link IterableIterator} of media type parameter names.
222
223
  */
223
224
  keys() {
224
- return this._map.keys();
225
+ return this.#map.keys();
225
226
  }
226
227
  /**
227
228
  * Returns an iterable of parameter values.
@@ -229,7 +230,7 @@ var Transportr = (() => {
229
230
  * @returns {IterableIterator<string>} The {@link IterableIterator} of media type parameter values.
230
231
  */
231
232
  values() {
232
- return this._map.values();
233
+ return this.#map.values();
233
234
  }
234
235
  /**
235
236
  * Returns an iterable of name, value pairs for every parameter entry in the media type parameters.
@@ -237,7 +238,7 @@ var Transportr = (() => {
237
238
  * @returns {IterableIterator<Array<Array<string>>>} The media type parameter entries.
238
239
  */
239
240
  entries() {
240
- return this._map.entries();
241
+ return this.#map.entries();
241
242
  }
242
243
  /**
243
244
  * A method that returns the default iterator for the {@link MediaTypeParameters}. Called by the semantics of the for-of statement.
@@ -245,7 +246,26 @@ var Transportr = (() => {
245
246
  * @returns {Iterator<string, string, undefined>} The {@link Symbol.iterator} for the media type parameters.
246
247
  */
247
248
  [Symbol.iterator]() {
248
- return this._map[Symbol.iterator]();
249
+ return this.#map[Symbol.iterator]();
250
+ }
251
+ /**
252
+ * Returns a string representation of the media type parameters.
253
+ * This method is called by the `String()` function.
254
+ *
255
+ * @example
256
+ * const parameters = new MediaTypeParameters(new Map([['charset', 'utf-8']]));
257
+ * String(parameters); // 'charset=utf-8'
258
+ * parameters.toString(); // 'charset=utf-8'
259
+ * parameters + ''; // 'charset=utf-8'
260
+ * `${parameters}`; // 'charset=utf-8'
261
+ * parameters[Symbol.toStringTag]; // 'MediaTypeParameters'
262
+ * parameters[Symbol.toStringTag](); // 'MediaTypeParameters'
263
+ * Object.prototype.toString.call(parameters); // '[object MediaTypeParameters]'
264
+ * parameters + ''; // 'charset=utf-8'
265
+ * @returns {string} The string representation of the media type parameters.
266
+ */
267
+ [Symbol.toStringTag]() {
268
+ return "MediaTypeParameters";
249
269
  }
250
270
  };
251
271
 
@@ -254,7 +274,7 @@ var Transportr = (() => {
254
274
  input = removeLeadingAndTrailingHTTPWhitespace(input);
255
275
  let position = 0;
256
276
  let type = "";
257
- while (position < input.length && input[position] !== "/") {
277
+ while (position < input.length && input[position] != "/") {
258
278
  type += input[position];
259
279
  ++position;
260
280
  }
@@ -266,7 +286,7 @@ var Transportr = (() => {
266
286
  }
267
287
  ++position;
268
288
  let subtype = "";
269
- while (position < input.length && input[position] !== ";") {
289
+ while (position < input.length && input[position] != ";") {
270
290
  subtype += input[position];
271
291
  ++position;
272
292
  }
@@ -285,26 +305,26 @@ var Transportr = (() => {
285
305
  ++position;
286
306
  }
287
307
  let parameterName = "";
288
- while (position < input.length && input[position] !== ";" && input[position] !== "=") {
308
+ while (position < input.length && input[position] != ";" && input[position] != "=") {
289
309
  parameterName += input[position];
290
310
  ++position;
291
311
  }
292
312
  parameterName = asciiLowercase(parameterName);
293
313
  if (position < input.length) {
294
- if (input[position] === ";") {
314
+ if (input[position] == ";") {
295
315
  continue;
296
316
  }
297
317
  ++position;
298
318
  }
299
319
  let parameterValue = null;
300
- if (input[position] === '"') {
320
+ if (input[position] == '"') {
301
321
  [parameterValue, position] = collectAnHTTPQuotedString(input, position);
302
- while (position < input.length && input[position] !== ";") {
322
+ while (position < input.length && input[position] != ";") {
303
323
  ++position;
304
324
  }
305
325
  } else {
306
326
  parameterValue = "";
307
- while (position < input.length && input[position] !== ";") {
327
+ while (position < input.length && input[position] != ";") {
308
328
  parameterValue += input[position];
309
329
  ++position;
310
330
  }
@@ -328,12 +348,9 @@ var Transportr = (() => {
328
348
  return serialization;
329
349
  }
330
350
  for (let [name, value] of mediaType.parameters) {
331
- serialization += ";";
332
- serialization += name;
333
- serialization += "=";
351
+ serialization += `;${name}=`;
334
352
  if (!solelyContainsHTTPTokenCodePoints(value) || value.length === 0) {
335
- value = value.replace(/(["\\])/ug, "\\$1");
336
- value = `"${value}"`;
353
+ value = `"${value.replace(/(["\\])/ug, "\\$1")}"`;
337
354
  }
338
355
  serialization += value;
339
356
  }
@@ -343,32 +360,35 @@ var Transportr = (() => {
343
360
 
344
361
  // node_modules/@d1g1tal/media-type/src/media-type.js
345
362
  var MediaType = class {
363
+ /** @type {string} */
364
+ #type;
365
+ /** @type {string} */
366
+ #subtype;
367
+ /** @type {MediaTypeParameters} */
368
+ #parameters;
346
369
  /**
347
370
  * Create a new MediaType instance from a string representation.
348
371
  *
349
- * @param {string} string The media type to parse
372
+ * @param {string} mediaType The media type to parse.
373
+ * @param {Object} [parameters] Optional parameters.
350
374
  */
351
- constructor(string) {
352
- string = String(string);
353
- const result = parser_default(string);
354
- if (result === null) {
355
- throw new Error(`Could not parse media type string '${string}'`);
356
- }
357
- this._type = result.type;
358
- this._subtype = result.subtype;
359
- this._parameters = new MediaTypeParameters(result.parameters);
375
+ constructor(mediaType, parameters = {}) {
376
+ const { type, subtype, parameters: parsedParameters } = parser_default(mediaType);
377
+ this.#type = type;
378
+ this.#subtype = subtype;
379
+ this.#parameters = new MediaTypeParameters([...parsedParameters, ...Object.entries(parameters).map(([name, value]) => [asciiLowercase(name), asciiLowercase(value)])]);
360
380
  }
361
381
  /**
362
- * Static factor method for parsing a media type.
382
+ * Static factory method for parsing a media type.
363
383
  *
364
- * @param {string} string The media type to parse
365
- * @returns {MediaType} The parsed {@link MediaType} object
384
+ * @param {string} string The media type to parse.
385
+ * @returns {MediaType} The parsed {@link MediaType} object or null if the string could not be parsed.
366
386
  */
367
387
  static parse(string) {
368
388
  try {
369
- return new this(string);
389
+ return new MediaType(string);
370
390
  } catch (e) {
371
- return null;
391
+ throw new Error(`Could not parse media type string '${string}'`);
372
392
  }
373
393
  }
374
394
  /**
@@ -377,7 +397,7 @@ var Transportr = (() => {
377
397
  * @returns {string} The media type without any parameters
378
398
  */
379
399
  get essence() {
380
- return `${this.type}/${this.subtype}`;
400
+ return `${this.#type}/${this.#subtype}`;
381
401
  }
382
402
  /**
383
403
  * Gets the type.
@@ -385,7 +405,7 @@ var Transportr = (() => {
385
405
  * @returns {string} The type.
386
406
  */
387
407
  get type() {
388
- return this._type;
408
+ return this.#type;
389
409
  }
390
410
  /**
391
411
  * Sets the type.
@@ -398,7 +418,7 @@ var Transportr = (() => {
398
418
  if (!solelyContainsHTTPTokenCodePoints(value)) {
399
419
  throw new Error(`Invalid type ${value}: must contain only HTTP token code points`);
400
420
  }
401
- this._type = value;
421
+ this.#type = value;
402
422
  }
403
423
  /**
404
424
  * Gets the subtype.
@@ -406,7 +426,7 @@ var Transportr = (() => {
406
426
  * @returns {string} The subtype.
407
427
  */
408
428
  get subtype() {
409
- return this._subtype;
429
+ return this.#subtype;
410
430
  }
411
431
  /**
412
432
  * Sets the subtype.
@@ -419,7 +439,7 @@ var Transportr = (() => {
419
439
  if (!solelyContainsHTTPTokenCodePoints(value)) {
420
440
  throw new Error(`Invalid subtype ${value}: must contain only HTTP token code points`);
421
441
  }
422
- this._subtype = value;
442
+ this.#subtype = value;
423
443
  }
424
444
  /**
425
445
  * Gets the parameters.
@@ -427,7 +447,7 @@ var Transportr = (() => {
427
447
  * @returns {MediaTypeParameters} The media type parameters.
428
448
  */
429
449
  get parameters() {
430
- return this._parameters;
450
+ return this.#parameters;
431
451
  }
432
452
  /**
433
453
  * Gets the serialized version of the media type.
@@ -445,9 +465,9 @@ var Transportr = (() => {
445
465
  * @returns {boolean} true if this instance represents a JavaScript media type, false otherwise.
446
466
  */
447
467
  isJavaScript({ prohibitParameters = false } = {}) {
448
- switch (this._type) {
468
+ switch (this.#type) {
449
469
  case "text": {
450
- switch (this._subtype) {
470
+ switch (this.#subtype) {
451
471
  case "ecmascript":
452
472
  case "javascript":
453
473
  case "javascript1.0":
@@ -460,18 +480,18 @@ var Transportr = (() => {
460
480
  case "livescript":
461
481
  case "x-ecmascript":
462
482
  case "x-javascript":
463
- return !prohibitParameters || this._parameters.size === 0;
483
+ return !prohibitParameters || this.#parameters.size === 0;
464
484
  default:
465
485
  return false;
466
486
  }
467
487
  }
468
488
  case "application": {
469
- switch (this._subtype) {
489
+ switch (this.#subtype) {
470
490
  case "ecmascript":
471
491
  case "javascript":
472
492
  case "x-ecmascript":
473
493
  case "x-javascript":
474
- return !prohibitParameters || this._parameters.size === 0;
494
+ return !prohibitParameters || this.#parameters.size === 0;
475
495
  default:
476
496
  return false;
477
497
  }
@@ -486,7 +506,7 @@ var Transportr = (() => {
486
506
  * @returns {boolean} true if this instance represents an XML media type, false otherwise.
487
507
  */
488
508
  isXML() {
489
- return this._subtype === "xml" && (this._type === "text" || this._type === "application") || this._subtype.endsWith("+xml");
509
+ return this.#subtype === "xml" && (this.#type === "text" || this.#type === "application") || this.#subtype.endsWith("+xml");
490
510
  }
491
511
  /**
492
512
  * Determines if this instance is an HTML media type.
@@ -494,7 +514,7 @@ var Transportr = (() => {
494
514
  * @returns {boolean} true if this instance represents an HTML media type, false otherwise.
495
515
  */
496
516
  isHTML() {
497
- return this._subtype === "html" && this._type === "text";
517
+ return this.#subtype === "html" && this.#type === "text";
498
518
  }
499
519
  /**
500
520
  * Gets the name of the class.
@@ -506,6 +526,130 @@ var Transportr = (() => {
506
526
  }
507
527
  };
508
528
 
529
+ // node_modules/@d1g1tal/subscribr/src/context-event-handler.js
530
+ var ContextEventHandler = class {
531
+ #context;
532
+ #eventHandler;
533
+ /**
534
+ * @param {*} context The context to bind to the event handler.
535
+ * @param {function(*): void} eventHandler The event handler to call when the event is published.
536
+ */
537
+ constructor(context, eventHandler) {
538
+ this.#context = context;
539
+ this.#eventHandler = eventHandler;
540
+ }
541
+ /**
542
+ * Call the event handler for the provided event.
543
+ *
544
+ * @param {Event} event The event to handle
545
+ * @param {*} [data] The value to be passed to the event handler as a parameter.
546
+ */
547
+ handle(event, data) {
548
+ this.#eventHandler.call(this.#context, event, data);
549
+ }
550
+ get [Symbol.toStringTag]() {
551
+ return "ContextEventHandler";
552
+ }
553
+ };
554
+
555
+ // node_modules/@d1g1tal/subscribr/src/subscription.js
556
+ var Subscription = class {
557
+ #eventName;
558
+ #contextEventHandler;
559
+ /**
560
+ * @param {string} eventName The event name.
561
+ * @param {ContextEventHandler} contextEventHandler Then context event handler.
562
+ */
563
+ constructor(eventName, contextEventHandler) {
564
+ this.#eventName = eventName;
565
+ this.#contextEventHandler = contextEventHandler;
566
+ }
567
+ /**
568
+ * Gets the event name for the subscription.
569
+ *
570
+ * @returns {string} The event name.
571
+ */
572
+ get eventName() {
573
+ return this.#eventName;
574
+ }
575
+ /**
576
+ * Gets the context event handler.
577
+ *
578
+ * @returns {ContextEventHandler} The context event handler
579
+ */
580
+ get contextEventHandler() {
581
+ return this.#contextEventHandler;
582
+ }
583
+ get [Symbol.toStringTag]() {
584
+ return "Subscription";
585
+ }
586
+ };
587
+
588
+ // node_modules/@d1g1tal/subscribr/src/subscribr.js
589
+ var Subscribr = class {
590
+ /** @type {SetMultiMap<string, ContextEventHandler>} */
591
+ #subscribers;
592
+ constructor() {
593
+ this.#subscribers = new SetMultiMap();
594
+ }
595
+ /**
596
+ * Subscribe to an event
597
+ *
598
+ * @param {string} eventName The event name to subscribe to.
599
+ * @param {function(Event, *): void} eventHandler The event handler to call when the event is published.
600
+ * @param {*} [context] The context to bind to the event handler.
601
+ * @returns {Subscription} An object used to check if the subscription still exists and to unsubscribe from the event.
602
+ */
603
+ subscribe(eventName, eventHandler, context = eventHandler) {
604
+ const contextEventHandler = new ContextEventHandler(context, eventHandler);
605
+ this.#subscribers.set(eventName, contextEventHandler);
606
+ return new Subscription(eventName, contextEventHandler);
607
+ }
608
+ /**
609
+ * Unsubscribe from the event
610
+ *
611
+ * @param {Subscription} subscription The subscription to unsubscribe.
612
+ * @param {string} subscription.eventName The event name to subscribe to.
613
+ * @param {ContextEventHandler} subscription.contextEventHandler The event handler to call when the event is published.
614
+ * @returns {boolean} true if eventListener has been removed successfully. false if the value is not found or if the value is not an object.
615
+ */
616
+ unsubscribe({ eventName, contextEventHandler }) {
617
+ const contextEventHandlers = this.#subscribers.get(eventName);
618
+ const removed = contextEventHandlers?.delete(contextEventHandler);
619
+ if (removed && contextEventHandlers.size == 0) {
620
+ this.#subscribers.delete(eventName);
621
+ }
622
+ return removed;
623
+ }
624
+ /**
625
+ * Publish an event
626
+ *
627
+ * @param {string} eventName The name of the event.
628
+ * @param {Event} event The event to be handled.
629
+ * @param {*} [data] The value to be passed to the event handler as a parameter.
630
+ */
631
+ publish(eventName, event = new CustomEvent(eventName), data) {
632
+ if (data == null && !(event instanceof Event)) {
633
+ [data, event] = [event, new CustomEvent(eventName)];
634
+ }
635
+ this.#subscribers.get(eventName)?.forEach((contextEventHandler) => contextEventHandler.handle(event, data));
636
+ }
637
+ /**
638
+ * Check if the event and handler are subscribed.
639
+ *
640
+ * @param {Subscription} subscription The subscription object.
641
+ * @param {string} subscription.eventName The name of the event to check.
642
+ * @param {ContextEventHandler} subscription.contextEventHandler The event handler to check.
643
+ * @returns {boolean} true if the event name and handler are subscribed, false otherwise.
644
+ */
645
+ isSubscribed({ eventName, contextEventHandler }) {
646
+ return this.#subscribers.get(eventName)?.has(contextEventHandler);
647
+ }
648
+ get [Symbol.toStringTag]() {
649
+ return "Subscribr";
650
+ }
651
+ };
652
+
509
653
  // src/http-error.js
510
654
  var HttpError = class extends Error {
511
655
  /** @type {ResponseBody} */
@@ -1694,8 +1838,60 @@ var Transportr = (() => {
1694
1838
  }
1695
1839
  };
1696
1840
 
1841
+ // src/signal-controller.js
1842
+ var SignalController = class {
1843
+ /** @type {AbortController} */
1844
+ #abortController;
1845
+ /**
1846
+ * @param {AbortSignal} [signal] The signal to be used to abort the request.
1847
+ */
1848
+ constructor(signal) {
1849
+ this.#abortController = new AbortController();
1850
+ signal?.addEventListener("abort", () => this.#abortController.abort());
1851
+ }
1852
+ /**
1853
+ * Returns the {@link AbortSignal} object associated with this object.
1854
+ *
1855
+ * @returns {AbortSignal} The {@link AbortSignal} object associated with this object.
1856
+ */
1857
+ get signal() {
1858
+ return this.#abortController.signal;
1859
+ }
1860
+ /**
1861
+ * Aborts a DOM request before it has completed.
1862
+ * This is able to abort fetch requests, data sent using the XMLHttpRequest API, and Web Sockets.
1863
+ *
1864
+ * @param {DOMException} [reason] The reason for aborting the request.
1865
+ * @returns {void}
1866
+ */
1867
+ abort(reason) {
1868
+ this.#abortController.abort(reason);
1869
+ }
1870
+ /**
1871
+ * A String value that is used in the creation of the default string
1872
+ * description of an object. Called by the built-in method {@link Object.prototype.toString}.
1873
+ *
1874
+ * @override
1875
+ * @returns {string} The default string description of this object.
1876
+ */
1877
+ get [Symbol.toStringTag]() {
1878
+ return "SignalController";
1879
+ }
1880
+ };
1881
+
1697
1882
  // src/transportr.js
1698
1883
  var endsWithSlashRegEx = /\/$/;
1884
+ var charset = "utf-8";
1885
+ var _mediaTypes = /* @__PURE__ */ new Map([
1886
+ [http_media_type_default.PNG, new MediaType(http_media_type_default.PNG)],
1887
+ [http_media_type_default.TEXT, new MediaType(http_media_type_default.TEXT, { charset })],
1888
+ [http_media_type_default.JSON, new MediaType(http_media_type_default.JSON, { charset })],
1889
+ [http_media_type_default.HTML, new MediaType(http_media_type_default.HTML, { charset })],
1890
+ [http_media_type_default.JAVA_SCRIPT, new MediaType(http_media_type_default.JAVA_SCRIPT, { charset })],
1891
+ [http_media_type_default.CSS, new MediaType(http_media_type_default.CSS, { charset })],
1892
+ [http_media_type_default.XML, new MediaType(http_media_type_default.XML, { charset })],
1893
+ [http_media_type_default.BIN, new MediaType(http_media_type_default.BIN)]
1894
+ ]);
1699
1895
  var _handleText = async (response) => await response.text();
1700
1896
  var _handleScript = async (response) => {
1701
1897
  const objectURL = URL.createObjectURL(await response.blob());
@@ -1714,16 +1910,16 @@ var Transportr = (() => {
1714
1910
  var _handleImage = async (response) => URL.createObjectURL(await response.blob());
1715
1911
  var _handleBuffer = async (response) => await response.arrayBuffer();
1716
1912
  var _handleReadableStream = async (response) => response.body;
1717
- var _handleXml = async (response) => new DOMParser().parseFromString(await response.text(), http_media_type_default.XML.essence);
1718
- var _handleHtml = async (response) => new DOMParser().parseFromString(await response.text(), http_media_type_default.HTML.essence);
1913
+ var _handleXml = async (response) => new DOMParser().parseFromString(await response.text(), http_media_type_default.XML);
1914
+ var _handleHtml = async (response) => new DOMParser().parseFromString(await response.text(), http_media_type_default.HTML);
1719
1915
  var _handleHtmlFragment = async (response) => document.createRange().createContextualFragment(await response.text());
1720
1916
  var _typeConverter = (data) => Object.fromEntries(Array.from(data.keys()).map((key, index, keys, value = data.getAll(key)) => [key, value.length > 1 ? value : value[0]]));
1721
- var _baseUrl, _options, _contentTypeHandlers, _propertyTypeConverters, _defaultRequestOptions, _get, get_fn, _request, request_fn, _processResponse, processResponse_fn, _createUrl, createUrl_fn, _needsSerialization, needsSerialization_fn, _convertRequestOptions, convertRequestOptions_fn;
1917
+ var _baseUrl, _options, _subscribr, _globalSubscribr, _activeRequests, _contentTypeHandlers, _propertyTypeConverters, _defaultRequestOptions, _eventResponseStatuses, _get, get_fn, _request, request_fn, _handleError, handleError_fn, _publish, publish_fn, _generateResponseStatusFromError, generateResponseStatusFromError_fn, _processResponse, processResponse_fn, _createUrl, createUrl_fn, _needsSerialization, needsSerialization_fn, _convertRequestOptions, convertRequestOptions_fn;
1722
1918
  var _Transportr = class {
1723
1919
  /**
1724
1920
  * Create a new Transportr instance with the provided location or origin and context path.
1725
1921
  *
1726
- * @param {URL | string | RequestOptions} [url=location.origin] The URL for {@link fetch} requests.
1922
+ * @param {URL|string|RequestOptions} [url=location.origin] The URL for {@link fetch} requests.
1727
1923
  * @param {RequestOptions} [options={}] The default {@link RequestOptions} for this instance.
1728
1924
  */
1729
1925
  constructor(url = location.origin, options = {}) {
@@ -1754,10 +1950,45 @@ var Transportr = (() => {
1754
1950
  * @returns {Promise<ResponseBody>} The response from the API call.
1755
1951
  */
1756
1952
  __privateAdd(this, _request);
1953
+ /**
1954
+ * Handles an error by logging it and throwing it.
1955
+ *
1956
+ * @private
1957
+ * @param {URL} url The path to the resource you want to access.
1958
+ * @param {import('./http-error.js').HttpErrorOptions} options The options for the HttpError.
1959
+ * @returns {HttpError} The HttpError.
1960
+ */
1961
+ __privateAdd(this, _handleError);
1962
+ /**
1963
+ * Publishes an event to the global and instance subscribers.
1964
+ *
1965
+ * @private
1966
+ * @param {string} eventName The name of the event.
1967
+ * @param {boolean} global Whether or not to publish the event to the global subscribers.
1968
+ * @param {Event} [event] The event object.
1969
+ * @param {*} [data] The data to pass to the subscribers.
1970
+ * @returns {void}
1971
+ */
1972
+ __privateAdd(this, _publish);
1973
+ /**
1974
+ * It takes a response and a handler, and if the handler is not defined, it tries to find a handler
1975
+ * based on the response's content type
1976
+ *
1977
+ * @private
1978
+ * @static
1979
+ * @async
1980
+ * @param {Response} response - The response object returned by the fetch API.
1981
+ * @param {URL} url - The path to the resource you want to access. Used for error handling.
1982
+ * @param {ResponseHandler<ResponseBody>} [handler] - The handler to use for processing the response.
1983
+ * @returns {Promise<ResponseBody>} The response is being returned.
1984
+ */
1985
+ __privateAdd(this, _processResponse);
1757
1986
  /** @type {URL} */
1758
1987
  __privateAdd(this, _baseUrl, void 0);
1759
1988
  /** @type {RequestOptions} */
1760
1989
  __privateAdd(this, _options, void 0);
1990
+ /** @type {Subscribr} */
1991
+ __privateAdd(this, _subscribr, void 0);
1761
1992
  var _a;
1762
1993
  const type = object_type_default(url);
1763
1994
  if (type == Object) {
@@ -1768,6 +1999,54 @@ var Transportr = (() => {
1768
1999
  }
1769
2000
  __privateSet(this, _baseUrl, url);
1770
2001
  __privateSet(this, _options, object_merge_default(__privateGet(_Transportr, _defaultRequestOptions), __privateMethod(_a = _Transportr, _convertRequestOptions, convertRequestOptions_fn).call(_a, options)));
2002
+ __privateSet(this, _subscribr, new Subscribr());
2003
+ }
2004
+ /**
2005
+ * Returns a {@link SignalController} used for aborting requests.
2006
+ *
2007
+ * @static
2008
+ * @param {AbortSignal} [signal] The optional {@link AbortSignal} to used for chaining.
2009
+ * @returns {SignalController} A new {@link SignalController} instance.
2010
+ */
2011
+ static signalController(signal) {
2012
+ return new SignalController(signal);
2013
+ }
2014
+ /**
2015
+ * Returns a {@link EventRegistration} used for subscribing to global events.
2016
+ *
2017
+ * @static
2018
+ * @param {TransportrEvent} event The event to subscribe to.
2019
+ * @param {function(Event, *): void} handler The event handler.
2020
+ * @param {*} context The context to bind the handler to.
2021
+ * @returns {EventRegistration} A new {@link EventRegistration} instance.
2022
+ */
2023
+ static register(event, handler, context) {
2024
+ return __privateGet(_Transportr, _globalSubscribr).subscribe(event, handler, context);
2025
+ }
2026
+ /**
2027
+ * Removes a {@link EventRegistration} from the global event handler.
2028
+ *
2029
+ * @static
2030
+ * @param {EventRegistration} eventRegistration The {@link EventRegistration} to remove.
2031
+ * @returns {boolean} True if the {@link EventRegistration} was removed, false otherwise.
2032
+ */
2033
+ static unregister(eventRegistration) {
2034
+ return __privateGet(_Transportr, _globalSubscribr).unsubscribe(eventRegistration);
2035
+ }
2036
+ /**
2037
+ * Aborts all active requests.
2038
+ * This is useful for when the user navigates away from the current page.
2039
+ * This will also clear the {@link Transportr#activeRequests} array.
2040
+ * This is called automatically when the {@link Transportr#abort} method is called.
2041
+ *
2042
+ * @static
2043
+ * @returns {void}
2044
+ */
2045
+ static abortAll() {
2046
+ for (const signalController of __privateGet(this, _activeRequests)) {
2047
+ signalController.abort();
2048
+ }
2049
+ __privateSet(this, _activeRequests, []);
1771
2050
  }
1772
2051
  /**
1773
2052
  * It returns the base {@link URL} for the API.
@@ -1777,6 +2056,26 @@ var Transportr = (() => {
1777
2056
  get baseUrl() {
1778
2057
  return __privateGet(this, _baseUrl);
1779
2058
  }
2059
+ /**
2060
+ * Registers an event handler with a {@link Transportr} instance.
2061
+ *
2062
+ * @param {TransportrEvent} event The name of the event to listen for.
2063
+ * @param {function(Event, *): void} handler The function to call when the event is triggered.
2064
+ * @param {*} [context] The context to bind to the handler.
2065
+ * @returns {EventRegistration} An object that can be used to remove the event handler.
2066
+ */
2067
+ register(event, handler, context) {
2068
+ return __privateGet(this, _subscribr).subscribe(event, handler, context);
2069
+ }
2070
+ /**
2071
+ * Unregisters an event handler from a {@link Transportr} instance.
2072
+ *
2073
+ * @param {EventRegistration} eventRegistration The event registration to remove.
2074
+ * @returns {void}
2075
+ */
2076
+ unregister(eventRegistration) {
2077
+ __privateGet(this, _subscribr).unsubscribe(eventRegistration);
2078
+ }
1780
2079
  /**
1781
2080
  * This function returns a promise that resolves to the result of a request to the specified path with
1782
2081
  * the specified options, where the method is GET.
@@ -1877,7 +2176,7 @@ var Transportr = (() => {
1877
2176
  * @returns {Promise<JsonObject>} A promise that resolves to the response body as a JSON object.
1878
2177
  */
1879
2178
  async getJson(path, options) {
1880
- return __privateMethod(this, _get, get_fn).call(this, path, options, { headers: { [http_request_headers_default.ACCEPT]: http_media_type_default.JSON } }, _handleJson);
2179
+ return __privateMethod(this, _get, get_fn).call(this, path, options, { headers: { [http_request_headers_default.ACCEPT]: _mediaTypes.get(http_media_type_default.JSON).toString() } }, _handleJson);
1881
2180
  }
1882
2181
  /**
1883
2182
  * It gets the XML representation of the resource at the given path.
@@ -1888,7 +2187,7 @@ var Transportr = (() => {
1888
2187
  * @returns {Promise<Document>} The result of the function call to #get.
1889
2188
  */
1890
2189
  async getXml(path, options) {
1891
- return __privateMethod(this, _get, get_fn).call(this, path, options, { headers: { [http_request_headers_default.ACCEPT]: http_media_type_default.XML } }, _handleXml);
2190
+ return __privateMethod(this, _get, get_fn).call(this, path, options, { headers: { [http_request_headers_default.ACCEPT]: _mediaTypes.get(http_media_type_default.XML).toString() } }, _handleXml);
1892
2191
  }
1893
2192
  /**
1894
2193
  * Get the HTML content of the specified path.
@@ -1901,7 +2200,7 @@ var Transportr = (() => {
1901
2200
  * method of the promise returned by the `#get` method.
1902
2201
  */
1903
2202
  async getHtml(path, options) {
1904
- return __privateMethod(this, _get, get_fn).call(this, path, options, { headers: { [http_request_headers_default.ACCEPT]: http_media_type_default.HTML } }, _handleHtml);
2203
+ return __privateMethod(this, _get, get_fn).call(this, path, options, { headers: { [http_request_headers_default.ACCEPT]: _mediaTypes.get(http_media_type_default.HTML).toString() } }, _handleHtml);
1905
2204
  }
1906
2205
  /**
1907
2206
  * It returns a promise that resolves to the HTML fragment at the given path.
@@ -1913,7 +2212,7 @@ var Transportr = (() => {
1913
2212
  * @returns {Promise<DocumentFragment>} A promise that resolves to an HTML fragment.
1914
2213
  */
1915
2214
  async getHtmlFragment(path, options) {
1916
- return __privateMethod(this, _get, get_fn).call(this, path, options, { headers: { [http_request_headers_default.ACCEPT]: http_media_type_default.HTML } }, _handleHtmlFragment);
2215
+ return __privateMethod(this, _get, get_fn).call(this, path, options, { headers: { [http_request_headers_default.ACCEPT]: _mediaTypes.get(http_media_type_default.HTML).toString() } }, _handleHtmlFragment);
1917
2216
  }
1918
2217
  /**
1919
2218
  * It gets a script from the server, and appends the script to the {@link Document} {@link HTMLHeadElement}
@@ -1925,7 +2224,7 @@ var Transportr = (() => {
1925
2224
  * @returns {Promise<void>} A promise that has been resolved.
1926
2225
  */
1927
2226
  async getScript(path, options) {
1928
- return __privateMethod(this, _get, get_fn).call(this, path, options, { headers: { [http_request_headers_default.ACCEPT]: http_media_type_default.JAVA_SCRIPT } }, _handleScript);
2227
+ return __privateMethod(this, _get, get_fn).call(this, path, options, { headers: { [http_request_headers_default.ACCEPT]: _mediaTypes.get(http_media_type_default.JAVA_SCRIPT).toString() } }, _handleScript);
1929
2228
  }
1930
2229
  /**
1931
2230
  * Gets a stylesheet from the server, and adds it as a {@link Blob} {@link URL}.
@@ -1936,7 +2235,7 @@ var Transportr = (() => {
1936
2235
  * @returns {Promise<void>} A promise that has been resolved.
1937
2236
  */
1938
2237
  async getStylesheet(path, options) {
1939
- return __privateMethod(this, _get, get_fn).call(this, path, options, { headers: { [http_request_headers_default.ACCEPT]: http_media_type_default.CSS } }, _handleCss);
2238
+ return __privateMethod(this, _get, get_fn).call(this, path, options, { headers: { [http_request_headers_default.ACCEPT]: _mediaTypes.get(http_media_type_default.CSS).toString() } }, _handleCss);
1940
2239
  }
1941
2240
  /**
1942
2241
  * It returns a blob from the specified path.
@@ -1995,9 +2294,13 @@ var Transportr = (() => {
1995
2294
  var Transportr = _Transportr;
1996
2295
  _baseUrl = new WeakMap();
1997
2296
  _options = new WeakMap();
2297
+ _subscribr = new WeakMap();
2298
+ _globalSubscribr = new WeakMap();
2299
+ _activeRequests = new WeakMap();
1998
2300
  _contentTypeHandlers = new WeakMap();
1999
2301
  _propertyTypeConverters = new WeakMap();
2000
2302
  _defaultRequestOptions = new WeakMap();
2303
+ _eventResponseStatuses = new WeakMap();
2001
2304
  _get = new WeakSet();
2002
2305
  get_fn = async function(path, userOptions, options, responseHandler) {
2003
2306
  return __privateMethod(this, _request, request_fn).call(this, path, userOptions, options, responseHandler);
@@ -2006,30 +2309,83 @@ var Transportr = (() => {
2006
2309
  request_fn = async function(path, userOptions = {}, options = {}, responseHandler) {
2007
2310
  var _a, _b, _c, _d, _e;
2008
2311
  const requestOptions = object_merge_default(__privateGet(this, _options), __privateMethod(_a = _Transportr, _convertRequestOptions, convertRequestOptions_fn).call(_a, userOptions), options);
2009
- const errorMessage = `An error has occurred with your Request: ${path}`;
2010
- if (__privateMethod(_b = _Transportr, _needsSerialization, needsSerialization_fn).call(_b, requestOptions.method, requestOptions.headers[http_request_headers_default.CONTENT_TYPE])) {
2011
- requestOptions.body = JSON.stringify(requestOptions.body);
2312
+ const url = __privateMethod(_b = _Transportr, _createUrl, createUrl_fn).call(_b, __privateGet(this, _baseUrl), path, requestOptions.searchParams);
2313
+ const signalController = new SignalController(requestOptions.signal);
2314
+ __privateGet(_Transportr, _activeRequests).push(signalController);
2315
+ requestOptions.signal = signalController.signal;
2316
+ if (__privateMethod(_c = _Transportr, _needsSerialization, needsSerialization_fn).call(_c, requestOptions.method, requestOptions.headers[http_request_headers_default.CONTENT_TYPE])) {
2317
+ try {
2318
+ requestOptions.body = JSON.stringify(requestOptions.body);
2319
+ } catch (error) {
2320
+ return Promise.reject(new HttpError(url, { cause: error }));
2321
+ }
2012
2322
  } else if (requestOptions.method == http_request_methods_default.GET && requestOptions.headers[http_request_headers_default.CONTENT_TYPE] != "") {
2013
2323
  delete requestOptions.headers[http_request_headers_default.CONTENT_TYPE];
2014
2324
  delete requestOptions.body;
2015
2325
  }
2016
- let response;
2326
+ requestOptions.signal.addEventListener("abort", (event) => __privateMethod(this, _publish, publish_fn).call(this, _Transportr.Events.ABORTED, requestOptions.global, event));
2327
+ requestOptions.signal.addEventListener("timeout", (event) => __privateMethod(this, _publish, publish_fn).call(this, _Transportr.Events.TIMEOUT, requestOptions.global, event));
2328
+ __privateMethod(this, _publish, publish_fn).call(this, _Transportr.Events.CONFIGURED, requestOptions.global, requestOptions);
2329
+ let result, timeoutId, response;
2017
2330
  try {
2018
- response = await fetch(__privateMethod(_c = _Transportr, _createUrl, createUrl_fn).call(_c, __privateGet(this, _baseUrl), path, requestOptions.searchParams), requestOptions);
2331
+ timeoutId = setTimeout(() => {
2332
+ const cause = new DOMException(`The call to '${url}' timed-out after ${requestOptions.timeout / 1e3} seconds`, "TimeoutError");
2333
+ signalController.abort(cause);
2334
+ requestOptions.signal.dispatchEvent(new CustomEvent(_Transportr.Events.TIMEOUT, { detail: { url, options: requestOptions, cause } }));
2335
+ }, requestOptions.timeout);
2336
+ response = await fetch(url, requestOptions);
2337
+ if (!response.ok) {
2338
+ return Promise.reject(__privateMethod(this, _handleError, handleError_fn).call(this, url, { status: __privateMethod(_d = _Transportr, _generateResponseStatusFromError, generateResponseStatusFromError_fn).call(_d, "ResponseError", response), entity: await __privateMethod(this, _processResponse, processResponse_fn).call(this, response, url) }));
2339
+ }
2340
+ result = await __privateMethod(this, _processResponse, processResponse_fn).call(this, response, url, responseHandler);
2341
+ __privateMethod(this, _publish, publish_fn).call(this, _Transportr.Events.SUCCESS, requestOptions.global, result);
2019
2342
  } catch (error) {
2020
- console.error(errorMessage, error);
2021
- throw new HttpError(errorMessage, { cause: error, status: response ? new ResponseStatus(response.status, response.statusText) : new ResponseStatus(0, "Unknown") });
2343
+ return Promise.reject(__privateMethod(this, _handleError, handleError_fn).call(this, url, { cause: error, status: __privateMethod(_e = _Transportr, _generateResponseStatusFromError, generateResponseStatusFromError_fn).call(_e, error.name, response) }));
2344
+ } finally {
2345
+ clearTimeout(timeoutId);
2346
+ if (!requestOptions.signal.aborted) {
2347
+ __privateMethod(this, _publish, publish_fn).call(this, _Transportr.Events.COMPLETE, requestOptions.global, response);
2348
+ const index = __privateGet(_Transportr, _activeRequests).indexOf(signalController);
2349
+ if (index > -1) {
2350
+ __privateGet(_Transportr, _activeRequests).splice(index, 1);
2351
+ }
2352
+ if (__privateGet(_Transportr, _activeRequests).length === 0) {
2353
+ __privateMethod(this, _publish, publish_fn).call(this, _Transportr.Events.ALL_COMPLETE, requestOptions.global, response);
2354
+ }
2355
+ }
2356
+ }
2357
+ return result;
2358
+ };
2359
+ _handleError = new WeakSet();
2360
+ handleError_fn = function(url, options) {
2361
+ const error = new HttpError(`An error has occurred with your request to: '${url}'`, options);
2362
+ __privateMethod(this, _publish, publish_fn).call(this, _Transportr.Events.ERROR, true, error);
2363
+ return error;
2364
+ };
2365
+ _publish = new WeakSet();
2366
+ publish_fn = function(eventName, global, event, data) {
2367
+ if (global) {
2368
+ __privateGet(_Transportr, _globalSubscribr).publish(eventName, event, data);
2022
2369
  }
2023
- if (!response.ok) {
2024
- throw new HttpError(errorMessage, { status: new ResponseStatus(response.status, response.statusText), entity: await __privateMethod(_d = _Transportr, _processResponse, processResponse_fn).call(_d, response) });
2370
+ __privateGet(this, _subscribr).publish(eventName, event, data);
2371
+ };
2372
+ _generateResponseStatusFromError = new WeakSet();
2373
+ generateResponseStatusFromError_fn = function(errorName, response) {
2374
+ switch (errorName) {
2375
+ case "AbortError":
2376
+ return __privateGet(_Transportr, _eventResponseStatuses).get(_Transportr.Events.ABORTED);
2377
+ case "TimeoutError":
2378
+ return __privateGet(_Transportr, _eventResponseStatuses).get(_Transportr.Events.TIMEOUT);
2379
+ default:
2380
+ return response ? new ResponseStatus(response.status, response.statusText) : new ResponseStatus(500, "Internal Server Error");
2025
2381
  }
2026
- return await __privateMethod(_e = _Transportr, _processResponse, processResponse_fn).call(_e, response, responseHandler);
2027
2382
  };
2028
2383
  _processResponse = new WeakSet();
2029
- processResponse_fn = async function(response, handler) {
2384
+ processResponse_fn = async function(response, url, handler) {
2030
2385
  try {
2386
+ let mediaType;
2031
2387
  if (!handler) {
2032
- const mediaType = new MediaType(response.headers.get(http_response_headers_default.CONTENT_TYPE));
2388
+ mediaType = MediaType.parse(response.headers.get(http_response_headers_default.CONTENT_TYPE));
2033
2389
  if (mediaType) {
2034
2390
  for (const [responseHandler, contentTypes] of __privateGet(_Transportr, _contentTypeHandlers)) {
2035
2391
  if (contentTypes.has(mediaType.type) || contentTypes.has(mediaType.subtype)) {
@@ -2041,20 +2397,21 @@ var Transportr = (() => {
2041
2397
  }
2042
2398
  return (handler ?? _handleText)(response);
2043
2399
  } catch (error) {
2044
- const errorMessage = "Unable to process response.";
2045
- console.error(errorMessage, error, response);
2046
- throw new HttpError(errorMessage, { cause: error });
2400
+ console.error("Unable to process response.", error, response);
2401
+ return Promise.reject(__privateMethod(this, _handleError, handleError_fn).call(this, url, { cause: error }));
2047
2402
  }
2048
2403
  };
2049
2404
  _createUrl = new WeakSet();
2050
2405
  createUrl_fn = function(url, path, searchParams = {}) {
2051
- url = path.startsWith("/") ? new URL(`${url.pathname.replace(endsWithSlashRegEx, "")}${path}`, url.origin) : new URL(path);
2406
+ if (path) {
2407
+ url = path.startsWith("/") ? new URL(`${url.pathname.replace(endsWithSlashRegEx, "")}${path}`, url.origin) : new URL(path);
2408
+ }
2052
2409
  Object.entries(searchParams).forEach(([key, value]) => url.searchParams.append(key, value));
2053
2410
  return url;
2054
2411
  };
2055
2412
  _needsSerialization = new WeakSet();
2056
2413
  needsSerialization_fn = function(method, contentType) {
2057
- return contentType == http_media_type_default.JSON && [http_request_methods_default.POST, http_request_methods_default.PUT, http_request_methods_default.PATCH].includes(method);
2414
+ return (_mediaTypes.get(contentType) ?? new MediaType(contentType)).essence == http_media_type_default.JSON && [http_request_methods_default.POST, http_request_methods_default.PUT, http_request_methods_default.PATCH].includes(method);
2058
2415
  };
2059
2416
  _convertRequestOptions = new WeakSet();
2060
2417
  convertRequestOptions_fn = function(options) {
@@ -2068,17 +2425,15 @@ var Transportr = (() => {
2068
2425
  return options;
2069
2426
  };
2070
2427
  /**
2071
- * It takes a response and a handler, and if the handler is not defined, it tries to find a handler
2072
- * based on the response's content type
2428
+ * Generates a ResponseStatus object based on the error name and the response.
2073
2429
  *
2074
2430
  * @private
2075
2431
  * @static
2076
- * @async
2077
- * @param {Response} response - The response object returned by the fetch API.
2078
- * @param {ResponseHandler<ResponseBody>} [handler] - The handler to use for processing the response.
2079
- * @returns {Promise<ResponseBody>} The response is being returned.
2432
+ * @param {string} errorName The name of the error.
2433
+ * @param {Response} response The response object returned by the fetch API.
2434
+ * @returns {ResponseStatus} The response status object.
2080
2435
  */
2081
- __privateAdd(Transportr, _processResponse);
2436
+ __privateAdd(Transportr, _generateResponseStatusFromError);
2082
2437
  /**
2083
2438
  * It takes a URL, a path, and a set of search parameters, and returns a new URL with the path and
2084
2439
  * search parameters applied.
@@ -2109,20 +2464,24 @@ var Transportr = (() => {
2109
2464
  * @returns {RequestOptions} The options to use for the request.
2110
2465
  */
2111
2466
  __privateAdd(Transportr, _convertRequestOptions);
2467
+ /** @type {Subscribr} */
2468
+ __privateAdd(Transportr, _globalSubscribr, new Subscribr());
2469
+ /** @type {Array<SignalController>} */
2470
+ __privateAdd(Transportr, _activeRequests, []);
2112
2471
  /**
2113
2472
  * @private
2114
2473
  * @static
2115
2474
  * @type {SetMultiMap<ResponseHandler<ResponseBody>, string>}
2116
2475
  */
2117
2476
  __privateAdd(Transportr, _contentTypeHandlers, new SetMultiMap([
2118
- [_handleImage, new MediaType(http_media_type_default.PNG).type],
2119
- [_handleText, new MediaType(http_media_type_default.TEXT).type],
2120
- [_handleJson, new MediaType(http_media_type_default.JSON).subtype],
2121
- [_handleHtml, new MediaType(http_media_type_default.HTML).subtype],
2122
- [_handleScript, new MediaType(http_media_type_default.JAVA_SCRIPT).subtype],
2123
- [_handleCss, new MediaType(http_media_type_default.CSS).subtype],
2124
- [_handleXml, new MediaType(http_media_type_default.XML).subtype],
2125
- [_handleReadableStream, new MediaType(http_media_type_default.BIN).subtype]
2477
+ [_handleImage, _mediaTypes.get(http_media_type_default.PNG).type],
2478
+ [_handleText, _mediaTypes.get(http_media_type_default.TEXT).type],
2479
+ [_handleJson, _mediaTypes.get(http_media_type_default.JSON).subtype],
2480
+ [_handleHtml, _mediaTypes.get(http_media_type_default.HTML).subtype],
2481
+ [_handleScript, _mediaTypes.get(http_media_type_default.JAVA_SCRIPT).subtype],
2482
+ [_handleCss, _mediaTypes.get(http_media_type_default.CSS).subtype],
2483
+ [_handleXml, _mediaTypes.get(http_media_type_default.XML).subtype],
2484
+ [_handleReadableStream, _mediaTypes.get(http_media_type_default.BIN).subtype]
2126
2485
  ]));
2127
2486
  /**
2128
2487
  * @private
@@ -2209,6 +2568,19 @@ var Transportr = (() => {
2209
2568
  STRICT_ORIGIN_WHEN_CROSS_ORIGIN: "strict-origin-when-cross-origin",
2210
2569
  UNSAFE_URL: "unsafe-url"
2211
2570
  }));
2571
+ /**
2572
+ * @static
2573
+ * @constant {Object<string, TransportrEvent>}
2574
+ */
2575
+ __publicField(Transportr, "Events", Object.freeze({
2576
+ CONFIGURED: "configured",
2577
+ SUCCESS: "success",
2578
+ ERROR: "error",
2579
+ ABORTED: "aborted",
2580
+ TIMEOUT: "timeout",
2581
+ COMPLETE: "complete",
2582
+ ALL_COMPLETE: "all-complete"
2583
+ }));
2212
2584
  /**
2213
2585
  * @private
2214
2586
  * @static
@@ -2218,7 +2590,7 @@ var Transportr = (() => {
2218
2590
  body: null,
2219
2591
  cache: _Transportr.CachingPolicy.NO_STORE,
2220
2592
  credentials: _Transportr.CredentialsPolicy.SAME_ORIGIN,
2221
- headers: { [http_request_headers_default.CONTENT_TYPE]: _Transportr.MediaType.JSON, [http_request_headers_default.ACCEPT]: _Transportr.MediaType.JSON },
2593
+ headers: { [http_request_headers_default.CONTENT_TYPE]: _mediaTypes.get(http_media_type_default.JSON).toString(), [http_request_headers_default.ACCEPT]: _mediaTypes.get(http_media_type_default.JSON).toString() },
2222
2594
  searchParams: {},
2223
2595
  integrity: void 0,
2224
2596
  keepalive: void 0,
@@ -2227,9 +2599,20 @@ var Transportr = (() => {
2227
2599
  redirect: _Transportr.RedirectPolicy.FOLLOW,
2228
2600
  referrer: "about:client",
2229
2601
  referrerPolicy: _Transportr.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
2230
- signal: null,
2602
+ signal: void 0,
2603
+ timeout: 1e4,
2604
+ global: true,
2231
2605
  window: null
2232
2606
  }));
2607
+ /**
2608
+ * @private
2609
+ * @static
2610
+ * @type {Map<TransportrEvent, ResponseStatus>}
2611
+ */
2612
+ __privateAdd(Transportr, _eventResponseStatuses, /* @__PURE__ */ new Map([
2613
+ [_Transportr.Events.ABORTED, new ResponseStatus(499, "Aborted")],
2614
+ [_Transportr.Events.TIMEOUT, new ResponseStatus(504, "Gateway Timeout")]
2615
+ ]));
2233
2616
  return __toCommonJS(transportr_exports);
2234
2617
  })();
2235
2618
  window.Transportr = Transportr.default;