@d1g1tal/transportr
Version:
JavaScript wrapper for the Fetch API
1,194 lines (1,178 loc) • 105 kB
JavaScript
// node_modules/.pnpm/@d1g1tal+collections@0.2.5/node_modules/@d1g1tal/collections/src/set-multi-map.js
var SetMultiMap = class extends Map {
/**
* Adds a new element with a specified key and value to the SetMultiMap.
* If an element with the same key already exists, the value will be added to the underlying {@link Set}.
* If the value already exists in the {@link Set}, it will not be added again.
*
* @param {K} key The key to set.
* @param {V} value The value to add to the SetMultiMap
* @returns {SetMultiMap<K, V>} The SetMultiMap with the updated key and value.
*/
set(key, value) {
super.set(key, (super.get(key) ?? /* @__PURE__ */ new Set()).add(value));
return this;
}
/**
* Checks if a specific key has a specific value.
*
* @param {K} key The key to check.
* @param {V} value The value to check.
* @returns {boolean} True if the key has the value, false otherwise.
*/
hasValue(key, value) {
const values = super.get(key);
return values ? values.has(value) : false;
}
/**
* Removes a specific value from a specific key.
*
* @param {K} key The key to remove the value from.
* @param {V} value The value to remove.
* @returns {boolean} True if the value was removed, false otherwise.
*/
deleteValue(key, value) {
const values = super.get(key);
if (values) {
return values.delete(value);
}
return false;
}
get [Symbol.toStringTag]() {
return "SetMultiMap";
}
};
// node_modules/.pnpm/@d1g1tal+subscribr@3.0.3/node_modules/@d1g1tal/subscribr/src/context-event-handler.js
var ContextEventHandler = class {
#context;
#eventHandler;
/**
* @param {*} context The context to bind to the event handler.
* @param {function(*): void} eventHandler The event handler to call when the event is published.
*/
constructor(context, eventHandler) {
this.#context = context;
this.#eventHandler = eventHandler;
}
/**
* Call the event handler for the provided event.
*
* @param {Event} event The event to handle
* @param {*} [data] The value to be passed to the event handler as a parameter.
*/
handle(event, data) {
this.#eventHandler.call(this.#context, event, data);
}
get [Symbol.toStringTag]() {
return "ContextEventHandler";
}
};
// node_modules/.pnpm/@d1g1tal+subscribr@3.0.3/node_modules/@d1g1tal/subscribr/src/subscription.js
var Subscription = class {
#eventName;
#contextEventHandler;
/**
* @param {string} eventName The event name.
* @param {ContextEventHandler} contextEventHandler Then context event handler.
*/
constructor(eventName, contextEventHandler) {
this.#eventName = eventName;
this.#contextEventHandler = contextEventHandler;
}
/**
* Gets the event name for the subscription.
*
* @returns {string} The event name.
*/
get eventName() {
return this.#eventName;
}
/**
* Gets the context event handler.
*
* @returns {ContextEventHandler} The context event handler
*/
get contextEventHandler() {
return this.#contextEventHandler;
}
get [Symbol.toStringTag]() {
return "Subscription";
}
};
// node_modules/.pnpm/@d1g1tal+subscribr@3.0.3/node_modules/@d1g1tal/subscribr/src/subscribr.js
var Subscribr = class {
/** @type {SetMultiMap<string, ContextEventHandler>} */
#subscribers;
constructor() {
this.#subscribers = new SetMultiMap();
}
/**
* Subscribe to an event
*
* @param {string} eventName The event name to subscribe to.
* @param {function(Event, *): void} eventHandler The event handler to call when the event is published.
* @param {*} [context] The context to bind to the event handler.
* @returns {Subscription} An object used to check if the subscription still exists and to unsubscribe from the event.
*/
subscribe(eventName, eventHandler, context = eventHandler) {
const contextEventHandler = new ContextEventHandler(context, eventHandler);
this.#subscribers.set(eventName, contextEventHandler);
return new Subscription(eventName, contextEventHandler);
}
/**
* Unsubscribe from the event
*
* @param {Subscription} subscription The subscription to unsubscribe.
* @param {string} subscription.eventName The event name to subscribe to.
* @param {ContextEventHandler} subscription.contextEventHandler The event handler to call when the event is published.
* @returns {boolean} true if eventListener has been removed successfully. false if the value is not found or if the value is not an object.
*/
unsubscribe({ eventName, contextEventHandler }) {
const contextEventHandlers = this.#subscribers.get(eventName);
const removed = contextEventHandlers?.delete(contextEventHandler);
if (removed && contextEventHandlers.size == 0) {
this.#subscribers.delete(eventName);
}
return removed;
}
/**
* Publish an event
*
* @param {string} eventName The name of the event.
* @param {Event} [event=new CustomEvent(eventName)] The event to be handled.
* @param {*} [data] The value to be passed to the event handler as a parameter.
*/
publish(eventName, event = new CustomEvent(eventName), data) {
if (data == null && !(event instanceof Event)) {
[data, event] = [event, new CustomEvent(eventName)];
}
this.#subscribers.get(eventName)?.forEach((contextEventHandler) => contextEventHandler.handle(event, data));
}
/**
* Check if the event and handler are subscribed.
*
* @param {Subscription} subscription The subscription object.
* @param {string} subscription.eventName The name of the event to check.
* @param {ContextEventHandler} subscription.contextEventHandler The event handler to check.
* @returns {boolean} true if the event name and handler are subscribed, false otherwise.
*/
isSubscribed({ eventName, contextEventHandler }) {
return this.#subscribers.get(eventName)?.has(contextEventHandler);
}
get [Symbol.toStringTag]() {
return "Subscribr";
}
};
// src/http-request-methods.js
var HttpRequestMethod = {
/**
* The OPTIONS method represents a request for information about the communication options available on the
* request/response chain identified by the Request-URI. This method allows the client to determine the options and/or
* requirements associated with a resource, or the capabilities of a server, without implying a resource action or
* initiating a resource retrieval.
*
* Responses to this method are not cacheable.
*
* If the OPTIONS request includes an entity-body (as indicated by the presence of Content-Length or
* Transfer-Encoding), then the media type MUST be indicated by a Content-Type field. Although this specification does
* not define any use for such a body, future extensions to HTTP might use the OPTIONS body to make more detailed
* queries on the server. A server that does not support such an extension MAY discard the request body.
*
* If the Request-URI is an asterisk ("*"), the OPTIONS request is intended to apply to the server in general rather
* than to a specific resource. Since a server's communication options typically depend on the resource, the "*"
* request is only useful as a "ping" or "no-op" type of method, it does nothing beyond allowing the client to test the
* capabilities of the server. For example, this can be used to test a proxy for HTTP/1.1 compliance (or lack thereof).
*
* If the Request-URI is not an asterisk, the OPTIONS request applies only to the options that are available when
* communicating with that resource.
*
* A 200 response SHOULD include any header fields that indicate optional features implemented by the server and
* applicable to that resource (e.g., Allow), possibly including extensions not defined by this specification. The
* response body, if any, SHOULD also include information about the communication options. The format for such a body
* is not defined by this specification, but might be defined by future extensions to HTTP. Content negotiation MAY be
* used to select the appropriate response format. If no response body is included, the response MUST include a
* Content-Length field with a field-value of "0".
*
* The Max-Forwards request-header field MAY be used to target a specific proxy in the request chain. When a proxy
* receives an OPTIONS request on an absoluteURI for which request forwarding is permitted, the proxy MUST check for a
* Max-Forwards field. If the Max-Forwards field-value is zero ("0"), the proxy MUST NOT forward the message, instead,
* the proxy SHOULD respond with its own communication options. If the Max-Forwards field-value is an integer greater
* than zero, the proxy MUST decrement the field-value when it forwards the request. If no Max-Forwards field is
* present in the request, then the forwarded request MUST NOT include a Max-Forwards field.
*/
OPTIONS: "OPTIONS",
/**
* The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI. If
* the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity in
* the response and not the source text of the process, unless that text happens to be the output of the process.
*
* The semantics of the GET method change to a "conditional GET" if the request message includes an If-Modified-Since;
* If-Unmodified-Since, If-Match, If-None-Match, or If-Range header field. A conditional GET method requests that the
* entity be transferred only under the circumstances described by the conditional header field(s). The conditional GET
* method is intended to reduce unnecessary network usage by allowing cached entities to be refreshed without requiring
* multiple requests or transferring data already held by the client.
*
* The semantics of the GET method change to a "partial GET" if the request message includes a Range header field. A
* partial GET requests that only part of the entity be transferred, as described in section 14.35. The partial GET
* method is intended to reduce unnecessary network usage by allowing partially-retrieved entities to be completed
* without transferring data already held by the client.
*
* The response to a GET request is cacheable if and only if it meets the requirements for HTTP caching described in
* section 13.
*
* See section 15.1.3 for security considerations when used for forms.
*/
GET: "GET",
/**
* The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response. The
* meta information contained in the HTTP headers in response to a HEAD request SHOULD be identical to the information
* sent in response to a GET request. This method can be used for obtaining meta information about the entity implied by
* the request without transferring the entity-body itself. This method is often used for testing hypertext links for
* validity, accessibility, and recent modification.
*
* The response to a HEAD request MAY be cacheable in the sense that the information contained in the response MAY be
* used to update a previously cached entity from that resource. If the new field values indicate that the cached
* entity differs from the current entity (as would be indicated by a change in Content-Length, Content-MD5, ETag or
* Last-Modified), then the cache MUST treat the cache entry as stale.
*/
HEAD: "HEAD",
/**
* The POST method is used to request that the origin server accept the entity enclosed in the request as a new
* subordinate of the resource identified by the Request-URI in the Request-Line. POST is designed to allow a uniform
* method to cover the following functions:
* <ul>
* <li>Annotation of existing resources,</li>
* <li>Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles,</li>
* <li>Providing a block of data, such as the result of submitting a form, to a data-handling process,</li>
* <li>Extending a database through an append operation.</li>
* </ul>
*
* The actual function performed by the POST method is determined by the server and is usually dependent on the
* Request-URI. The posted entity is subordinate to that URI in the same way that a file is subordinate to a directory
* containing it, a news article is subordinate to a newsgroup to which it is posted, or a record is subordinate to a
* database.
*
* The action performed by the POST method might not result in a resource that can be identified by a URI. In this
* case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the
* response includes an entity that describes the result.
*
* If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity
* which describes the status of the request and refers to the new resource, and a Location header (see section 14.30).
*
* Responses to this method are not cacheable, unless the response includes appropriate Cache-Control or Expires header
* fields. However, the 303 (See Other) response can be used to direct the user agent to retrieve a cacheable resource.
*
* POST requests MUST obey the message transmission requirements set out in section 8.2.
*
* See section 15.1.3 for security considerations.
*/
POST: "POST",
/**
* The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers
* to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing
* on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being
* defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. If
* a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an
* existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate
* successful completion of the request. If the resource could not be created or modified with the Request-URI, an
* appropriate error response SHOULD be given that reflects the nature of the problem. The recipient of the entity MUST
* \NOT ignore any Content-* (e.g. Content-Range) headers that it does not understand or implement and MUST return a
* 501 (Not Implemented) response in such cases.
*
* If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those
* entries SHOULD be treated as stale. Responses to this method are not cacheable.
*
* The fundamental difference between the POST and PUT requests is reflected in the different meaning of the
* Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource
* might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations.
* In contrast, the URI in a PUT request identifies the entity enclosed with the request -- the user agent knows what
* URI is intended and the server MUST NOT attempt to apply the request to some other resource. If the server desires
* that the request be applied to a different URI, it MUST send a 301 (Moved Permanently) response, the user agent MAY
* then make its own decision regarding whether or not to redirect the request.
*
* A single resource MAY be identified by many different URIs. For example, an article might have a URI for identifying
* "the current version" which is separate from the URI identifying each particular version. In this case, a PUT
* request on a general URI might result in several other URIs being defined by the origin server.
*
* HTTP/1.1 does not define how a PUT method affects the state of an origin server.
*
* PUT requests MUST obey the message transmission requirements set out in section 8.2.
*
* Unless otherwise specified for a particular entity-header, the entity-headers in the PUT request SHOULD be applied
* to the resource created or modified by the PUT.
*/
PUT: "PUT",
/**
* The DELETE method requests that the origin server delete the resource identified by the Request-URI. This method MAY
* be overridden by human intervention (or other means) on the origin server. The client cannot be guaranteed that the
* operation has been carried out, even if the status code returned from the origin server indicates that the action
* has been completed successfully. However, the server SHOULD NOT indicate success unless, at the time the response
* is given, it intends to delete the resource or move it to an inaccessible location.
*
* A successful response SHOULD be 200 (OK) if the response includes an entity describing the status, 202 (Accepted) if
* the action has not yet been enacted, or 204 (No Content) if the action has been enacted but the response does not
* include an entity.
*
* If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those
* entries SHOULD be treated as stale. Responses to this method are not cacheable.
*/
DELETE: "DELETE",
/**
* The TRACE method is used to invoke a remote, application-layer loop- back of the request message. The final
* recipient of the request SHOULD reflect the message received back to the client as the entity-body of a 200 (OK)
* response. The final recipient is either the origin server or the first proxy or gateway to receive a Max-Forwards
* value of zero (0) in the request (see section 14.31). A TRACE request MUST NOT include an entity.
*
* TRACE allows the client to see what is being received at the other end of the request chain and use that data for
* testing or diagnostic information. The value of the Via header field (section 14.45) is of particular interest,
* since it acts as a trace of the request chain. Use of the Max-Forwards header field allows the client to limit the
* length of the request chain, which is useful for testing a chain of proxies forwarding messages in an infinite loop.
*
* If the request is valid, the response SHOULD contain the entire request message in the entity-body, with a
* Content-Type of "message/http". Responses to this method MUST NOT be cached.
*/
TRACE: "TRACE",
/**
* This specification reserves the method name CONNECT for use with a proxy that can dynamically switch to being a
* tunnel (e.g. SSL tunneling [44]).
*/
CONNECT: "CONNECT",
/**
* The PATCH method requests that a set of changes described in the
* request entity be applied to the resource identified by the Request-
* URI. The set of changes is represented in a format called a "patch
* document" identified by a media type. If the Request-URI does not
* point to an existing resource, the server MAY create a new resource,
* depending on the patch document type (whether it can logically modify
* a null resource) and permissions, etc.
*
* The difference between the PUT and PATCH requests is reflected in the
* way the server processes the enclosed entity to modify the resource
* identified by the Request-URI. In a PUT request, the enclosed entity
* is considered to be a modified version of the resource stored on the
* origin server, and the client is requesting that the stored version
* be replaced. With PATCH, however, the enclosed entity contains a set
* of instructions describing how a resource currently residing on the
* origin server should be modified to produce a new version. The PATCH
* method affects the resource identified by the Request-URI, and it
* also MAY have side effects on other resources; i.e., new resources
* may be created, or existing ones modified, by the application of a
* PATCH.
*
* PATCH is neither safe nor idempotent as defined by [RFC2616], Section
* 9.1.
*
* A PATCH request can be issued in such a way as to be idempotent,
* which also helps prevent bad outcomes from collisions between two
* PATCH requests on the same resource in a similar time frame.
* Collisions from multiple PATCH requests may be more dangerous than
* PUT collisions because some patch formats need to operate from a
* known base-point or else they will corrupt the resource. Clients
* using this kind of patch application SHOULD use a conditional request
* such that the request will fail if the resource has been updated
* since the client last accessed the resource. For example, the client
* can use a strong ETag [RFC2616] in an If-Match header on the PATCH
* request.
*
* There are also cases where patch formats do not need to operate from
* a known base-point (e.g., appending text lines to log files, or non-
* colliding rows to database tables), in which case the same care in
* client requests is not needed.
*
* The server MUST apply the entire set of changes atomically and never
* provide (e.g., in response to a GET during this operation) a
* partially modified representation. If the entire patch document
* cannot be successfully applied, then the server MUST NOT apply any of
* the changes. The determination of what constitutes a successful
* PATCH can vary depending on the patch document and the type of
* resource(s) being modified. For example, the common 'diff' utility
* can generate a patch document that applies to multiple files in a
* directory hierarchy. The atomicity requirement holds for all
* directly affected files. See "Error Handling", Section 2.2, for
* details on status codes and possible error conditions.
*
* If the request passes through a cache and the Request-URI identifies
* one or more currently cached entities, those entries SHOULD be
* treated as stale. A response to this method is only cacheable if it
* contains explicit freshness information (such as an Expires header or
* "Cache-Control: max-age" directive) as well as the Content-Location
* header matching the Request-URI, indicating that the PATCH response
* body is a resource representation. A cached PATCH response can only
* be used to respond to subsequent GET and HEAD requests; it MUST NOT
* be used to respond to other methods (in particular, PATCH).
*
* Note that entity-headers contained in the request apply only to the
* contained patch document and MUST NOT be applied to the resource
* being modified. Thus, a Content-Language header could be present on
* the request, but it would only mean (for whatever that's worth) that
* the patch document had a language. Servers SHOULD NOT store such
* headers except as trace information, and SHOULD NOT use such header
* values the same way they might be used on PUT requests. Therefore,
* this document does not specify a way to modify a document's Content-
* Type or Content-Language value through headers, though a mechanism
* could well be designed to achieve this goal through a patch document.
*
* There is no guarantee that a resource can be modified with PATCH.
* Further, it is expected that different patch document formats will be
* appropriate for different types of resources and that no single
* format will be appropriate for all types of resources. Therefore,
* there is no single default patch document format that implementations
* are required to support. Servers MUST ensure that a received patch
* document is appropriate for the type of resource identified by the
* Request-URI.
*
* Clients need to choose when to use PATCH rather than PUT. For
* example, if the patch document size is larger than the size of the
* new resource data that would be used in a PUT, then it might make
* sense to use PUT instead of PATCH. A comparison to POST is even more
* difficult, because POST is used in widely varying ways and can
* encompass PUT and PATCH-like operations if the server chooses. If
* the operation does not modify the resource identified by the Request-
* URI in a predictable way, POST should be considered instead of PATCH
* or PUT.
*/
PATCH: "PATCH"
};
var http_request_methods_default = HttpRequestMethod;
// src/response-status.js
var ResponseStatus = class {
/** @type {number} */
#code;
/** @type {string} */
#text;
/**
*
* @param {number} code The status code from the {@link Response}
* @param {string} text The status text from the {@link Response}
*/
constructor(code, text) {
this.#code = code;
this.#text = text;
}
/**
* Returns the status code from the {@link Response}
*
* @returns {number} The status code.
*/
get code() {
return this.#code;
}
/**
* Returns the status text from the {@link Response}.
*
* @returns {string} The status text.
*/
get text() {
return this.#text;
}
/**
* A String value that is used in the creation of the default string
* description of an object. Called by the built-in method {@link Object.prototype.toString}.
*
* @override
* @returns {string} The default string description of this object.
*/
get [Symbol.toStringTag]() {
return "ResponseStatus";
}
/**
* tostring method for the class.
*
* @override
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString|Object.prototype.toString}
* @returns {string} The status code and status text.
*/
toString() {
return `${this.#code} ${this.#text}`;
}
};
// node_modules/.pnpm/@d1g1tal+chrysalis@2.2.1/node_modules/@d1g1tal/chrysalis/src/esm/object-type.js
var _type = (object) => object?.constructor ?? object?.prototype?.constructor ?? globalThis[Object.prototype.toString.call(object).slice(8, -1)] ?? object;
var object_type_default = _type;
// node_modules/.pnpm/@d1g1tal+chrysalis@2.2.1/node_modules/@d1g1tal/chrysalis/src/esm/object-merge.js
var _objectMerge = (...objects) => {
const target = {};
for (const source of objects) {
if (object_type_default(source) != Object)
return void 0;
let descriptor, sourceType;
for (const property of Object.getOwnPropertyNames(source)) {
descriptor = Object.getOwnPropertyDescriptor(source, property);
if (descriptor.enumerable) {
sourceType = object_type_default(source[property]);
if (sourceType == Object) {
descriptor.value = object_type_default(target[property]) == Object ? _objectMerge(target[property], source[property]) : { ...source[property] };
} else if (sourceType == Array) {
descriptor.value = Array.isArray(target[property]) ? [.../* @__PURE__ */ new Set([...source[property], ...target[property]])] : [...source[property]];
}
target[property] = descriptor.value;
}
}
}
return target;
};
var object_merge_default = _objectMerge;
// node_modules/.pnpm/@d1g1tal+media-type@5.0.0/node_modules/@d1g1tal/media-type/src/utils.js
var httpTokenCodePoints = /^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/u;
var utils_default = httpTokenCodePoints;
// node_modules/.pnpm/@d1g1tal+media-type@5.0.0/node_modules/@d1g1tal/media-type/src/media-type-parameters.js
var matcher = /(["\\])/ug;
var httpQuotedStringTokenCodePoints = /^[\t\u0020-\u007E\u0080-\u00FF]*$/u;
var MediaTypeParameters = class _MediaTypeParameters extends Map {
/**
* Create a new MediaTypeParameters instance.
*
* @param {Array<[string, string]>} entries An array of [name, value] tuples.
*/
constructor(entries = []) {
super(entries);
}
/**
* Indicates whether the supplied name and value are valid media type parameters.
*
* @static
* @param {string} name The name of the media type parameter to validate.
* @param {string} value The media type parameter value to validate.
* @returns {boolean} true if the media type parameter is valid, false otherwise.
*/
static isValid(name, value) {
return utils_default.test(name) && httpQuotedStringTokenCodePoints.test(value);
}
/**
* Gets the media type parameter value for the supplied name.
*
* @param {string} name The name of the media type parameter to retrieve.
* @returns {string} The media type parameter value.
*/
get(name) {
return super.get(name.toLowerCase());
}
/**
* Indicates whether the media type parameter with the specified name exists or not.
*
* @param {string} name The name of the media type parameter to check.
* @returns {boolean} true if the media type parameter exists, false otherwise.
*/
has(name) {
return super.has(name.toLowerCase());
}
/**
* Adds a new media type parameter using the specified name and value to the MediaTypeParameters.
* If an parameter with the same name already exists, the parameter will be updated.
*
* @param {string} name The name of the media type parameter to set.
* @param {string} value The media type parameter value.
* @returns {MediaTypeParameters} This instance.
*/
set(name, value) {
if (!_MediaTypeParameters.isValid(name, value)) {
throw new Error(`Invalid media type parameter name/value: ${name}/${value}`);
}
super.set(name.toLowerCase(), value);
return this;
}
/**
* Removes the media type parameter using the specified name.
*
* @param {string} name The name of the media type parameter to delete.
* @returns {boolean} true if the parameter existed and has been removed, or false if the parameter does not exist.
*/
delete(name) {
return super.delete(name.toLowerCase());
}
/**
* Returns a string representation of the media type parameters.
*
* @override
* @returns {string} The string representation of the media type parameters.
*/
toString() {
return Array.from(this).map(([name, value]) => `;${name}=${!value || !utils_default.test(value) ? `"${value.replace(matcher, "\\$1")}"` : value}`).join("");
}
/**
* Returns the name of this class.
*
* @override
* @returns {string} The name of this class.
*/
[Symbol.toStringTag]() {
return "MediaTypeParameters";
}
};
// node_modules/.pnpm/@d1g1tal+media-type@5.0.0/node_modules/@d1g1tal/media-type/src/media-type-parser.js
var whitespaceCharacters = [" ", " ", "\n", "\r"];
var trailingWhitespace = /[ \t\n\r]+$/u;
var leadingAndTrailingWhitespace = /^[ \t\n\r]+|[ \t\n\r]+$/ug;
var MediaTypeParser = class _MediaTypeParser {
/**
* Function to parse a media type.
*
* @static
* @param {string} input The media type to parse
* @returns {{ type: string, subtype: string, parameters: MediaTypeParameters }} An object populated with the parsed media type properties and any parameters.
*/
static parse(input) {
input = input.replace(leadingAndTrailingWhitespace, "");
const length = input.length, trim = true, lowerCase = false;
let { position, result: type, subtype = "" } = _MediaTypeParser.#filterComponent({ input }, "/");
if (!type.length || position >= length || !utils_default.test(type)) {
throw new TypeError(_MediaTypeParser.#generateErrorMessage("type", type));
}
({ position, result: subtype } = _MediaTypeParser.#filterComponent({ position: ++position, input, trim }, ";"));
if (!subtype.length || !utils_default.test(subtype)) {
throw new TypeError(_MediaTypeParser.#generateErrorMessage("subtype", subtype));
}
let parameterName = "", parameterValue = null;
const parameters = new MediaTypeParameters();
while (position++ < length) {
while (whitespaceCharacters.includes(input[position])) {
++position;
}
({ position, result: parameterName } = _MediaTypeParser.#filterComponent({ position, input, lowerCase }, ";", "="));
if (position < length) {
if (input[position] == ";") {
continue;
}
++position;
}
if (input[position] == '"') {
[parameterValue, position] = _MediaTypeParser.#collectHttpQuotedString(input, position);
while (position < length && input[position] != ";") {
++position;
}
} else {
({ position, result: parameterValue } = _MediaTypeParser.#filterComponent({ position, input, lowerCase, trim }, ";"));
if (!parameterValue) {
continue;
}
}
if (parameterName && MediaTypeParameters.isValid(parameterName, parameterValue) && !parameters.has(parameterName)) {
parameters.set(parameterName, parameterValue);
}
}
return { type, subtype, parameters };
}
/**
* Filters a component from the input string.
*
* @private
* @static
* @param {Object} options The options.
* @param {number} [options.position] The starting position.
* @param {string} options.input The input string.
* @param {boolean} [options.lowerCase] Indicates whether the result should be lowercased.
* @param {boolean} [options.trim] Indicates whether the result should be trimmed.
* @param {string[]} charactersToFilter The characters to filter.
* @returns {{ position: number, result: string }} An object that includes the resulting string and updated position.
*/
static #filterComponent({ position = 0, input, lowerCase = true, trim = false }, ...charactersToFilter) {
let result = "";
for (const length = input.length; position < length && !charactersToFilter.includes(input[position]); position++) {
result += input[position];
}
if (lowerCase) {
result = result.toLowerCase();
}
if (trim) {
result = result.replace(trailingWhitespace, "");
}
return { position, result };
}
/**
* Collects all the HTTP quoted strings.
* This variant only implements it with the extract-value flag set.
*
* @private
* @static
* @param {string} input The string to process.
* @param {number} position The starting position.
* @returns {Array<string|number>} An array that includes the resulting string and updated position.
*/
static #collectHttpQuotedString(input, position) {
let value = "";
for (let length = input.length, char; ++position < length; ) {
if ((char = input[position]) == '"') {
break;
}
value += char == "\\" && ++position < length ? input[position] : char;
}
return [value, position];
}
/**
* Generates an error message.
*
* @private
* @static
* @param {string} component The component name.
* @param {string} value The component value.
* @returns {string} The error message.
*/
static #generateErrorMessage(component, value) {
return `Invalid ${component} "${value}": only HTTP token code points are valid.`;
}
};
// node_modules/.pnpm/@d1g1tal+media-type@5.0.0/node_modules/@d1g1tal/media-type/src/media-type.js
var MediaType = class _MediaType {
/** @type {string} */
#type;
/** @type {string} */
#subtype;
/** @type {MediaTypeParameters} */
#parameters;
/**
* Create a new MediaType instance from a string representation.
*
* @param {string} mediaType The media type to parse.
* @param {Object} [parameters] Optional parameters.
*/
constructor(mediaType, parameters = {}) {
if (object_type_default(parameters) != Object) {
throw new TypeError("The parameters argument must be an object");
}
({ type: this.#type, subtype: this.#subtype, parameters: this.#parameters } = MediaTypeParser.parse(mediaType));
for (const [name, value] of Object.entries(parameters)) {
this.#parameters.set(name, value);
}
}
static parse(mediaType) {
try {
return new _MediaType(mediaType);
} catch (e) {
}
return null;
}
/**
* Gets the type.
*
* @returns {string} The type.
*/
get type() {
return this.#type;
}
/**
* Gets the subtype.
*
* @returns {string} The subtype.
*/
get subtype() {
return this.#subtype;
}
/**
* Gets the media type essence (type/subtype).
*
* @returns {string} The media type without any parameters
*/
get essence() {
return `${this.#type}/${this.#subtype}`;
}
/**
* Gets the parameters.
*
* @returns {MediaTypeParameters} The media type parameters.
*/
get parameters() {
return this.#parameters;
}
/**
* Checks if the media type matches the specified type.
*
* @todo Fix string handling to parse the type and subtype from the string.
* @param {MediaType|string} type The media type to check.
* @returns {boolean} true if the media type matches the specified type, false otherwise.
*/
matches(type) {
return this.#type == type?.type && this.#subtype == type?.subtype || this.essence.includes(type);
}
/**
* Gets the serialized version of the media type.
*
* @returns {string} The serialized media type.
*/
toString() {
return `${this.essence}${this.#parameters.toString()}`;
}
/**
* Gets the name of the class.
*
* @returns {string} The class name
*/
get [Symbol.toStringTag]() {
return "MediaType";
}
};
// src/http-media-type.js
var HttpMediaType = {
/** Advanced Audio Coding (AAC) */
AAC: "audio/aac",
/** AbiWord */
ABW: "application/x-abiword",
/** Archive document (multiple files embedded) */
ARC: "application/x-freearc",
/** AVIF image */
AVIF: "image/avif",
/** Audio Video Interleave (AVI) */
AVI: "video/x-msvideo",
/** Amazon Kindle eBook format */
AZW: "application/vnd.amazon.ebook",
/** Binary Data */
BIN: "application/octet-stream",
/** Windows OS/2 Bitmap Graphics */
BMP: "image/bmp",
/** Bzip Archive */
BZIP: "application/x-bzip",
/** Bzip2 Archive */
BZIP2: "application/x-bzip2",
/** CD audio */
CDA: "application/x-cdf",
/** C Shell Script */
CSH: "application/x-csh",
/** Cascading Style Sheets (CSS) */
CSS: "text/css",
/** Comma-Separated Values */
CSV: "text/csv",
/** Microsoft Office Word Document */
DOC: "application/msword",
/** Microsoft Office Word Document (OpenXML) */
DOCX: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
/** Microsoft Embedded OpenType */
EOT: "application/vnd.ms-fontobject",
/** Electronic Publication (EPUB) */
EPUB: "application/epub+zip",
/** GZip Compressed Archive */
GZIP: "application/gzip",
/** Graphics Interchange Format */
GIF: "image/gif",
/** HyperText Markup Language (HTML) */
HTML: "text/html",
/** Icon Format */
ICO: "image/vnd.microsoft.icon",
/** iCalendar Format */
ICS: "text/calendar",
/** Java Archive (JAR) */
JAR: "application/java-archive",
/** JPEG Image */
JPEG: "image/jpeg",
/** JavaScript */
JAVA_SCRIPT: "text/javascript",
/** JavaScript Object Notation Format (JSON) */
JSON: "application/json",
/** JavaScript Object Notation LD Format */
JSON_LD: "application/ld+json",
/** JavaScript Object Notation (JSON) Merge Patch */
JSON_MERGE_PATCH: "application/merge-patch+json",
/** Musical Instrument Digital Interface (MIDI) */
MID: "audio/midi",
/** Musical Instrument Digital Interface (MIDI) */
X_MID: "audio/x-midi",
/** MP3 Audio */
MP3: "audio/mpeg",
/** MPEG-4 Audio */
MP4A: "audio/mp4",
/** MPEG-4 Video */
MP4: "video/mp4",
/** MPEG Video */
MPEG: "video/mpeg",
/** Apple Installer Package */
MPKG: "application/vnd.apple.installer+xml",
/** OpenDocument Presentation Document */
ODP: "application/vnd.oasis.opendocument.presentation",
/** OpenDocument Spreadsheet Document */
ODS: "application/vnd.oasis.opendocument.spreadsheet",
/** OpenDocument Text Document */
ODT: "application/vnd.oasis.opendocument.text",
/** Ogg Audio */
OGA: "audio/ogg",
/** Ogg Video */
OGV: "video/ogg",
/** Ogg */
OGX: "application/ogg",
/** Opus audio */
OPUS: "audio/opus",
/** OpenType Font File */
OTF: "font/otf",
/** Portable Network Graphics (PNG) */
PNG: "image/png",
/** Adobe Portable Document Format */
PDF: "application/pdf",
/** Hypertext Preprocessor (Personal Home Page) */
PHP: "application/x-httpd-php",
/** Microsoft PowerPoint */
PPT: "application/vnd.ms-powerpoint",
/** Microsoft Office Presentation (OpenXML) */
PPTX: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
/** RAR Archive */
RAR: "application/vnd.rar",
/** Rich Text Format */
RTF: "application/rtf",
/** Bourne Shell Script */
SH: "application/x-sh",
/** Scalable Vector Graphics (SVG) */
SVG: "image/svg+xml",
/** Tape Archive (TAR) */
TAR: "application/x-tar",
/** Tagged Image File Format (TIFF) */
TIFF: "image/tiff",
/** MPEG transport stream */
TRANSPORT_STREAM: "video/mp2t",
/** TrueType Font */
TTF: "font/ttf",
/** Text, (generally ASCII or ISO 8859-n) */
TEXT: "text/plain",
/** Microsoft Visio */
VSD: "application/vnd.visio",
/** Waveform Audio Format (WAV) */
WAV: "audio/wav",
/** Open Web Media Project - Audio */
WEBA: "audio/webm",
/** Open Web Media Project - Video */
WEBM: "video/webm",
/** WebP Image */
WEBP: "image/webp",
/** Web Open Font Format */
WOFF: "font/woff",
/** Web Open Font Format */
WOFF2: "font/woff2",
/** Form - Encoded */
FORM: "application/x-www-form-urlencoded",
/** Multipart FormData */
MULTIPART_FORM_DATA: "multipart/form-data",
/** XHTML - The Extensible HyperText Markup Language */
XHTML: "application/xhtml+xml",
/** Microsoft Excel Document */
XLS: "application/vnd.ms-excel",
/** Microsoft Office Spreadsheet Document (OpenXML) */
XLSX: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
/** Extensible Markup Language (XML) */
XML: "application/xml",
/** XML User Interface Language (XUL) */
XUL: "application/vnd.mozilla.xul+xml",
/** Zip Archive */
ZIP: "application/zip",
/** 3GPP audio/video container */
"3GP": "video/3gpp",
/** 3GPP2 audio/video container */
"3G2": "video/3gpp2",
/** 7-Zip Archive */
"7Z": "application/x-7z-compressed"
};
var http_media_type_default = HttpMediaType;
// src/constants.js
var defaultCharset = "utf-8";
var endsWithSlashRegEx = /\/$/;
var mediaTypes = /* @__PURE__ */ new Map([
[http_media_type_default.PNG, new MediaType(http_media_type_default.PNG)],
[http_media_type_default.TEXT, new MediaType(http_media_type_default.TEXT, { defaultCharset })],
[http_media_type_default.JSON, new MediaType(http_media_type_default.JSON, { defaultCharset })],
[http_media_type_default.HTML, new MediaType(http_media_type_default.HTML, { defaultCharset })],
[http_media_type_default.JAVA_SCRIPT, new MediaType(http_media_type_default.JAVA_SCRIPT, { defaultCharset })],
[http_media_type_default.CSS, new MediaType(http_media_type_default.CSS, { defaultCharset })],
[http_media_type_default.XML, new MediaType(http_media_type_default.XML, { defaultCharset })],
[http_media_type_default.BIN, new MediaType(http_media_type_default.BIN)]
]);
var RequestEvents = Object.freeze({
CONFIGURED: "configured",
SUCCESS: "success",
ERROR: "error",
ABORTED: "aborted",
TIMEOUT: "timeout",
COMPLETE: "complete",
ALL_COMPLETE: "all-complete"
});
var SignalEvents = Object.freeze({
ABORT: "abort",
TIMEOUT: "timeout"
});
var _abortEvent = new CustomEvent(SignalEvents.ABORT, { detail: { cause: new DOMException("The request was aborted", "AbortError") } });
var requestBodyMethods = [http_request_methods_default.POST, http_request_methods_default.PUT, http_request_methods_default.PATCH];
var internalServerError = new ResponseStatus(500, "Internal Server Error");
var eventResponseStatuses = Object.freeze({
[RequestEvents.ABORTED]: new ResponseStatus(499, "Aborted"),
[RequestEvents.TIMEOUT]: new ResponseStatus(504, "Request Timeout")
});
var abortSignalProxyHandler = { get: (target, property) => property == "signal" ? target.signal.timeout(target.timeout) : Reflect.get(target, property) };
// src/abort-signal.js
var AbortSignal = class {
/** @type {AbortController} */
#abortController;
/** @type {number} */
#timeoutId;
/**
* @param {NativeAbortSignal} signal The signal to chain.
* This signal will be able to abort the request, but will not be notified if the request is aborted by the timeout.
*/
constructor(signal) {
this.#abortController = new AbortController();
signal?.addEventListener(SignalEvents.ABORT, (event) => this.#abort(event));
}
/**
* The aborted property is a Boolean that indicates whether the request has been aborted (true) or not (false).
*
* @returns {boolean} Whether the signal was aborted or not
*/
get aborted() {
return this.#abortController.signal.aborted;
}
/**
* The reason property returns a DOMException object indicating the reason the operation was aborted, or null if the operation is not aborted.
*
* @returns {DOMException} The reason the signal was aborted
*/
get reason() {
return this.#abortController.signal.reason;
}
/**
* Returns an AbortSignal instance that will be aborted when the provided amount of milliseconds have passed.
* A value of {@link Infinity} means there is no timeout.
* Note: You can't set this property to a value less than 0.
*
* @param {number} timeout The timeout in milliseconds
* @returns {AbortSignal} The abort signal
*/
timeout(timeout) {
if (timeout < 0) {
throw new RangeError("The timeout cannot be negative");
}
if (timeout != Infinity) {
this.#timeoutId ??= setTimeout(() => this.#abort(new CustomEvent(SignalEvents.TIMEOUT, { detail: { timeout, cause: new DOMException(`The request timed-out after ${timeout / 1e3} seconds`, "TimeoutError") } }), true), timeout);
}
return this.#abortController.signal;
}
/**
* Clears the timeout.
* Note: This does not abort the signal, dispatch the timeout event, or reset the timeout.
*
* @returns {void}
*/
clearTimeout() {
clearTimeout(this.#timeoutId);
}
/**
* Adds an event listener for the 'abort' event.
*
* @param {EventListener} listener The listener to add
* @returns {AbortSignal} The AbortSignal
*/
onAbort(listener) {
this.#abortController.signal.addEventListener(SignalEvents.ABORT, listener);
return this;
}
/**
* Adds an event listener for the 'timeout' event.
*
* @param {EventListener} listener The listener to add
* @returns {AbortSignal} The AbortSignal
*/
onTimeout(listener) {
this.#abortController.signal.addEventListener(SignalEvents.TIMEOUT, listener);
return this;
}
/**
* Aborts the signal. This is so naughty. ¯\_(ツ)_/¯
*
* @param {Event} event The event to abort with
* @returns {void}
*/
abort(event) {
this.#abort(event);
}
/**
* Aborts the signal.
*
* @private
* @param {Event} event The event to abort with
* @param {boolean} [dispatchEvent = false] Whether to dispatch the event or not
* @returns {void}
* @fires SignalEvents.ABORT When the signal is aborted
* @fires SignalEvents.TIMEOUT When the signal times out
*/
#abort(event = _abortEvent, dispatchEvent = false) {
clearTimeout(this.#timeoutId);
this.#abortController.abort(event.detail?.cause);
if (dispatchEvent) {
this.#abortController.signal.dispatchEvent(event);
}
}
};
// src/http-error.js
var HttpError = class extends Error {
/** @type {ResponseBody} */
#entity;
/** @type {ResponseStatus} */
#responseStatus;
/**
* @param {string} [message] The error message.
* @param {HttpErrorOptions} [httpErrorOptions] The http error options.
* @param {any} [httpErrorOptions.cause] The cause of the error.
* @param {ResponseStatus} [httpErrorOptions.status] The response status.
* @param {ResponseBody} [httpErrorOptions.entity] The error entity from the server, if any.
*/
constructor(message, { cause, status, entity }) {
super(message, { cause });
this.#entity = entity;
this.#responseStatus = status;
}
/**
* It returns the value of the private variable #entity.
*
* @returns {ResponseBody} The entity property of the class.
*/
get entity() {
return this.#entity;
}
/**
* It returns the status code of the {@link Response}.
*
* @returns {number} The status code of the {@link Response}.
*/
get statusCode() {
return this.#responseStatus?.code;
}
/**
* It returns the status text of the {@link Response}.
*
* @returns {string} The status code and status text of the {@link Response}.
*/
get statusText() {
return this.#responseStatus?.text;
}
get name() {
return "HttpError";
}
/**
* A String value that is used in the creation of the default string
* description of an object. Called by the built-in method {@link Object.prototype.toString}.
*
* @returns {string} The default string description of this object.
*/
get [Symbol.toStringTag]() {
return "HttpError";
}
};
// src/http-request-headers.js
var HttpRequestHeader = {
/**
* Content-Types that are acceptable for the response. See Content negotiation. Permanent.
*
* @example
* <code>Accept: text/plain</code>
*/
ACCEPT: "accept",
/**
* Character sets that are acceptable. Permanent.
*
* @example
* <code>Accept-Charset: utf-8</code>
*/
ACCEPT_CHARSET: "accept-charset",
/**
* List of acceptable encodings. See HTTP compression. Permanent.
*
* @example
* <code>Accept-Encoding: gzip, deflate</code>
*/
ACCEPT_ENCODING: "accept-encoding",
/**
* List of acceptable human languages for response. See Content negotiation. Permanent.
*
* @example
* <code>Accept-Lang