@d1g1tal/transportr 1.4.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +329 -76
- package/dist/transportr.d.ts +1799 -0
- package/dist/transportr.js +2753 -1503
- package/dist/transportr.js.map +7 -0
- package/package.json +72 -49
- package/dist/iife/transportr.js +0 -2656
- package/dist/iife/transportr.min.js +0 -3
- package/dist/iife/transportr.min.js.map +0 -7
- package/dist/transportr.min.js +0 -3
- package/dist/transportr.min.js.map +0 -7
- package/src/abort-signal.js +0 -124
- package/src/constants.js +0 -61
- package/src/http-error.js +0 -75
- package/src/http-media-type.js +0 -162
- package/src/http-request-headers.js +0 -312
- package/src/http-request-methods.js +0 -277
- package/src/http-response-headers.js +0 -350
- package/src/parameter-map.js +0 -221
- package/src/response-status.js +0 -62
- package/src/transportr.js +0 -838
package/dist/transportr.js
CHANGED
|
@@ -1,818 +1,604 @@
|
|
|
1
|
-
// node_modules/.pnpm/@d1g1tal+
|
|
2
|
-
var
|
|
1
|
+
// node_modules/.pnpm/@d1g1tal+media-type@6.0.4/node_modules/@d1g1tal/media-type/dist/media-type.js
|
|
2
|
+
var httpTokenCodePoints = /^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/u;
|
|
3
|
+
var matcher = /(["\\])/ug;
|
|
4
|
+
var httpQuotedStringTokenCodePoints = /^[\t\u0020-\u007E\u0080-\u00FF]*$/u;
|
|
5
|
+
var MediaTypeParameters = class _MediaTypeParameters extends Map {
|
|
3
6
|
/**
|
|
4
|
-
*
|
|
5
|
-
* If an element with the same key already exists, the value will be added to the underlying {@link Set}.
|
|
6
|
-
* If the value already exists in the {@link Set}, it will not be added again.
|
|
7
|
+
* Create a new MediaTypeParameters instance.
|
|
7
8
|
*
|
|
8
|
-
* @param
|
|
9
|
-
* @param {V} value The value to add to the SetMultiMap
|
|
10
|
-
* @returns {SetMultiMap<K, V>} The SetMultiMap with the updated key and value.
|
|
9
|
+
* @param entries An array of [ name, value ] tuples.
|
|
11
10
|
*/
|
|
12
|
-
|
|
13
|
-
super
|
|
14
|
-
return this;
|
|
11
|
+
constructor(entries2 = []) {
|
|
12
|
+
super(entries2);
|
|
15
13
|
}
|
|
16
14
|
/**
|
|
17
|
-
*
|
|
15
|
+
* Indicates whether the supplied name and value are valid media type parameters.
|
|
18
16
|
*
|
|
19
|
-
* @param
|
|
20
|
-
* @param
|
|
21
|
-
* @returns
|
|
17
|
+
* @param name The name of the media type parameter to validate.
|
|
18
|
+
* @param value The media type parameter value to validate.
|
|
19
|
+
* @returns true if the media type parameter is valid, false otherwise.
|
|
22
20
|
*/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return values ? values.has(value) : false;
|
|
21
|
+
static isValid(name, value) {
|
|
22
|
+
return httpTokenCodePoints.test(name) && httpQuotedStringTokenCodePoints.test(value);
|
|
26
23
|
}
|
|
27
24
|
/**
|
|
28
|
-
*
|
|
25
|
+
* Gets the media type parameter value for the supplied name.
|
|
29
26
|
*
|
|
30
|
-
* @param
|
|
31
|
-
* @
|
|
32
|
-
* @returns {boolean} True if the value was removed, false otherwise.
|
|
27
|
+
* @param name The name of the media type parameter to retrieve.
|
|
28
|
+
* @returns The media type parameter value.
|
|
33
29
|
*/
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (values) {
|
|
37
|
-
return values.delete(value);
|
|
38
|
-
}
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
get [Symbol.toStringTag]() {
|
|
42
|
-
return "SetMultiMap";
|
|
30
|
+
get(name) {
|
|
31
|
+
return super.get(name.toLowerCase());
|
|
43
32
|
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// node_modules/.pnpm/@d1g1tal+subscribr@3.0.2/node_modules/@d1g1tal/subscribr/src/context-event-handler.js
|
|
47
|
-
var ContextEventHandler = class {
|
|
48
|
-
#context;
|
|
49
|
-
#eventHandler;
|
|
50
33
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
34
|
+
* Indicates whether the media type parameter with the specified name exists or not.
|
|
35
|
+
*
|
|
36
|
+
* @param name The name of the media type parameter to check.
|
|
37
|
+
* @returns true if the media type parameter exists, false otherwise.
|
|
53
38
|
*/
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
this.#eventHandler = eventHandler;
|
|
39
|
+
has(name) {
|
|
40
|
+
return super.has(name.toLowerCase());
|
|
57
41
|
}
|
|
58
42
|
/**
|
|
59
|
-
*
|
|
43
|
+
* Adds a new media type parameter using the specified name and value to the MediaTypeParameters.
|
|
44
|
+
* If an parameter with the same name already exists, the parameter will be updated.
|
|
60
45
|
*
|
|
61
|
-
* @param
|
|
62
|
-
* @param
|
|
46
|
+
* @param name The name of the media type parameter to set.
|
|
47
|
+
* @param value The media type parameter value.
|
|
48
|
+
* @returns This instance.
|
|
63
49
|
*/
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
50
|
+
set(name, value) {
|
|
51
|
+
if (!_MediaTypeParameters.isValid(name, value)) {
|
|
52
|
+
throw new Error(`Invalid media type parameter name/value: ${name}/${value}`);
|
|
53
|
+
}
|
|
54
|
+
super.set(name.toLowerCase(), value);
|
|
55
|
+
return this;
|
|
69
56
|
}
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
// node_modules/.pnpm/@d1g1tal+subscribr@3.0.2/node_modules/@d1g1tal/subscribr/src/subscription.js
|
|
73
|
-
var Subscription = class {
|
|
74
|
-
#eventName;
|
|
75
|
-
#contextEventHandler;
|
|
76
57
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
58
|
+
* Removes the media type parameter using the specified name.
|
|
59
|
+
*
|
|
60
|
+
* @param name The name of the media type parameter to delete.
|
|
61
|
+
* @returns true if the parameter existed and has been removed, or false if the parameter does not exist.
|
|
79
62
|
*/
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
this.#contextEventHandler = contextEventHandler;
|
|
63
|
+
delete(name) {
|
|
64
|
+
return super.delete(name.toLowerCase());
|
|
83
65
|
}
|
|
84
66
|
/**
|
|
85
|
-
*
|
|
67
|
+
* Returns a string representation of the media type parameters.
|
|
86
68
|
*
|
|
87
|
-
* @returns
|
|
69
|
+
* @returns The string representation of the media type parameters.
|
|
88
70
|
*/
|
|
89
|
-
|
|
90
|
-
return this
|
|
71
|
+
toString() {
|
|
72
|
+
return Array.from(this).map(([name, value]) => `;${name}=${!value || !httpTokenCodePoints.test(value) ? `"${value.replace(matcher, "\\$1")}"` : value}`).join("");
|
|
91
73
|
}
|
|
92
74
|
/**
|
|
93
|
-
*
|
|
75
|
+
* Returns the name of this class.
|
|
94
76
|
*
|
|
95
|
-
* @returns
|
|
77
|
+
* @returns The name of this class.
|
|
96
78
|
*/
|
|
97
|
-
get contextEventHandler() {
|
|
98
|
-
return this.#contextEventHandler;
|
|
99
|
-
}
|
|
100
79
|
get [Symbol.toStringTag]() {
|
|
101
|
-
return "
|
|
80
|
+
return "MediaTypeParameters";
|
|
102
81
|
}
|
|
103
82
|
};
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
var
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
83
|
+
var whitespaceChars = /* @__PURE__ */ new Set([" ", " ", "\n", "\r"]);
|
|
84
|
+
var trailingWhitespace = /[ \t\n\r]+$/u;
|
|
85
|
+
var leadingAndTrailingWhitespace = /^[ \t\n\r]+|[ \t\n\r]+$/ug;
|
|
86
|
+
var MediaTypeParser = class _MediaTypeParser {
|
|
87
|
+
/**
|
|
88
|
+
* Function to parse a media type.
|
|
89
|
+
* @param input The media type to parse
|
|
90
|
+
* @returns An object populated with the parsed media type properties and any parameters.
|
|
91
|
+
*/
|
|
92
|
+
static parse(input) {
|
|
93
|
+
input = input.replace(leadingAndTrailingWhitespace, "");
|
|
94
|
+
let position = 0;
|
|
95
|
+
const [type, typeEnd] = _MediaTypeParser.collect(input, position, ["/"]);
|
|
96
|
+
position = typeEnd;
|
|
97
|
+
if (!type.length || position >= input.length || !httpTokenCodePoints.test(type)) {
|
|
98
|
+
throw new TypeError(_MediaTypeParser.generateErrorMessage("type", type));
|
|
99
|
+
}
|
|
100
|
+
++position;
|
|
101
|
+
const [subtype, subtypeEnd] = _MediaTypeParser.collect(input, position, [";"], true, true);
|
|
102
|
+
position = subtypeEnd;
|
|
103
|
+
if (!subtype.length || !httpTokenCodePoints.test(subtype)) {
|
|
104
|
+
throw new TypeError(_MediaTypeParser.generateErrorMessage("subtype", subtype));
|
|
105
|
+
}
|
|
106
|
+
const parameters = new MediaTypeParameters();
|
|
107
|
+
while (position < input.length) {
|
|
108
|
+
++position;
|
|
109
|
+
while (whitespaceChars.has(input[position])) {
|
|
110
|
+
++position;
|
|
111
|
+
}
|
|
112
|
+
let name;
|
|
113
|
+
[name, position] = _MediaTypeParser.collect(input, position, [";", "="], false);
|
|
114
|
+
if (position >= input.length || input[position] === ";") {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
++position;
|
|
118
|
+
let value;
|
|
119
|
+
if (input[position] === '"') {
|
|
120
|
+
[value, position] = _MediaTypeParser.collectHttpQuotedString(input, position);
|
|
121
|
+
while (position < input.length && input[position] !== ";") {
|
|
122
|
+
++position;
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
[value, position] = _MediaTypeParser.collect(input, position, [";"], false, true);
|
|
126
|
+
if (!value) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (name && MediaTypeParameters.isValid(name, value) && !parameters.has(name)) {
|
|
131
|
+
parameters.set(name, value);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return { type, subtype, parameters };
|
|
111
135
|
}
|
|
112
136
|
/**
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* @param {string} eventName The event name to subscribe to.
|
|
116
|
-
* @param {function(Event, *): void} eventHandler The event handler to call when the event is published.
|
|
117
|
-
* @param {*} [context] The context to bind to the event handler.
|
|
118
|
-
* @returns {Subscription} An object used to check if the subscription still exists and to unsubscribe from the event.
|
|
137
|
+
* Gets the name of this class.
|
|
138
|
+
* @returns The string tag of this class.
|
|
119
139
|
*/
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
this.#subscribers.set(eventName, contextEventHandler);
|
|
123
|
-
return new Subscription(eventName, contextEventHandler);
|
|
140
|
+
get [Symbol.toStringTag]() {
|
|
141
|
+
return "MediaTypeParser";
|
|
124
142
|
}
|
|
125
143
|
/**
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* @param
|
|
129
|
-
* @param
|
|
130
|
-
* @param
|
|
131
|
-
* @
|
|
144
|
+
* Collects characters from `input` starting at `pos` until a stop character is found.
|
|
145
|
+
* @param input The input string.
|
|
146
|
+
* @param pos The starting position.
|
|
147
|
+
* @param stopChars Characters that end collection.
|
|
148
|
+
* @param lowerCase Whether to ASCII-lowercase the result.
|
|
149
|
+
* @param trim Whether to strip trailing HTTP whitespace.
|
|
150
|
+
* @returns A tuple of the collected string and the updated position.
|
|
132
151
|
*/
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
this.#subscribers.delete(eventName);
|
|
152
|
+
static collect(input, pos, stopChars, lowerCase = true, trim = false) {
|
|
153
|
+
let result = "";
|
|
154
|
+
for (const { length } = input; pos < length && !stopChars.includes(input[pos]); pos++) {
|
|
155
|
+
result += input[pos];
|
|
138
156
|
}
|
|
139
|
-
|
|
157
|
+
if (lowerCase) {
|
|
158
|
+
result = result.toLowerCase();
|
|
159
|
+
}
|
|
160
|
+
if (trim) {
|
|
161
|
+
result = result.replace(trailingWhitespace, "");
|
|
162
|
+
}
|
|
163
|
+
return [result, pos];
|
|
140
164
|
}
|
|
141
165
|
/**
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
* @param
|
|
145
|
-
* @param
|
|
146
|
-
* @
|
|
166
|
+
* Collects all the HTTP quoted strings.
|
|
167
|
+
* This variant only implements it with the extract-value flag set.
|
|
168
|
+
* @param input The string to process.
|
|
169
|
+
* @param position The starting position.
|
|
170
|
+
* @returns An array that includes the resulting string and updated position.
|
|
147
171
|
*/
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
172
|
+
static collectHttpQuotedString(input, position) {
|
|
173
|
+
let value = "";
|
|
174
|
+
for (let length = input.length, char; ++position < length; ) {
|
|
175
|
+
if ((char = input[position]) === '"') {
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
value += char == "\\" && ++position < length ? input[position] : char;
|
|
151
179
|
}
|
|
152
|
-
|
|
180
|
+
return [value, position];
|
|
153
181
|
}
|
|
154
182
|
/**
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
* @param
|
|
158
|
-
* @
|
|
159
|
-
* @param {ContextEventHandler} subscription.contextEventHandler The event handler to check.
|
|
160
|
-
* @returns {boolean} true if the event name and handler are subscribed, false otherwise.
|
|
183
|
+
* Generates an error message.
|
|
184
|
+
* @param component The component name.
|
|
185
|
+
* @param value The component value.
|
|
186
|
+
* @returns The error message.
|
|
161
187
|
*/
|
|
162
|
-
|
|
163
|
-
return
|
|
164
|
-
}
|
|
165
|
-
get [Symbol.toStringTag]() {
|
|
166
|
-
return "Subscribr";
|
|
188
|
+
static generateErrorMessage(component, value) {
|
|
189
|
+
return `Invalid ${component} "${value}": only HTTP token code points are valid.`;
|
|
167
190
|
}
|
|
168
191
|
};
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
192
|
+
var MediaType = class _MediaType {
|
|
193
|
+
_type;
|
|
194
|
+
_subtype;
|
|
195
|
+
_parameters;
|
|
172
196
|
/**
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
* initiating a resource retrieval.
|
|
177
|
-
*
|
|
178
|
-
* Responses to this method are not cacheable.
|
|
179
|
-
*
|
|
180
|
-
* If the OPTIONS request includes an entity-body (as indicated by the presence of Content-Length or
|
|
181
|
-
* Transfer-Encoding), then the media type MUST be indicated by a Content-Type field. Although this specification does
|
|
182
|
-
* not define any use for such a body, future extensions to HTTP might use the OPTIONS body to make more detailed
|
|
183
|
-
* queries on the server. A server that does not support such an extension MAY discard the request body.
|
|
184
|
-
*
|
|
185
|
-
* If the Request-URI is an asterisk ("*"), the OPTIONS request is intended to apply to the server in general rather
|
|
186
|
-
* than to a specific resource. Since a server's communication options typically depend on the resource, the "*"
|
|
187
|
-
* request is only useful as a "ping" or "no-op" type of method, it does nothing beyond allowing the client to test the
|
|
188
|
-
* capabilities of the server. For example, this can be used to test a proxy for HTTP/1.1 compliance (or lack thereof).
|
|
189
|
-
*
|
|
190
|
-
* If the Request-URI is not an asterisk, the OPTIONS request applies only to the options that are available when
|
|
191
|
-
* communicating with that resource.
|
|
192
|
-
*
|
|
193
|
-
* A 200 response SHOULD include any header fields that indicate optional features implemented by the server and
|
|
194
|
-
* applicable to that resource (e.g., Allow), possibly including extensions not defined by this specification. The
|
|
195
|
-
* response body, if any, SHOULD also include information about the communication options. The format for such a body
|
|
196
|
-
* is not defined by this specification, but might be defined by future extensions to HTTP. Content negotiation MAY be
|
|
197
|
-
* used to select the appropriate response format. If no response body is included, the response MUST include a
|
|
198
|
-
* Content-Length field with a field-value of "0".
|
|
199
|
-
*
|
|
200
|
-
* The Max-Forwards request-header field MAY be used to target a specific proxy in the request chain. When a proxy
|
|
201
|
-
* receives an OPTIONS request on an absoluteURI for which request forwarding is permitted, the proxy MUST check for a
|
|
202
|
-
* Max-Forwards field. If the Max-Forwards field-value is zero ("0"), the proxy MUST NOT forward the message, instead,
|
|
203
|
-
* the proxy SHOULD respond with its own communication options. If the Max-Forwards field-value is an integer greater
|
|
204
|
-
* than zero, the proxy MUST decrement the field-value when it forwards the request. If no Max-Forwards field is
|
|
205
|
-
* present in the request, then the forwarded request MUST NOT include a Max-Forwards field.
|
|
197
|
+
* Create a new MediaType instance from a string representation.
|
|
198
|
+
* @param mediaType The media type to parse.
|
|
199
|
+
* @param parameters Optional parameters.
|
|
206
200
|
*/
|
|
207
|
-
|
|
201
|
+
constructor(mediaType, parameters = {}) {
|
|
202
|
+
if (parameters === null || typeof parameters !== "object" || Array.isArray(parameters)) {
|
|
203
|
+
throw new TypeError("The parameters argument must be an object");
|
|
204
|
+
}
|
|
205
|
+
({ type: this._type, subtype: this._subtype, parameters: this._parameters } = MediaTypeParser.parse(mediaType));
|
|
206
|
+
for (const [name, value] of Object.entries(parameters)) {
|
|
207
|
+
this._parameters.set(name, value);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
208
210
|
/**
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
* The semantics of the GET method change to a "conditional GET" if the request message includes an If-Modified-Since;
|
|
214
|
-
* If-Unmodified-Since, If-Match, If-None-Match, or If-Range header field. A conditional GET method requests that the
|
|
215
|
-
* entity be transferred only under the circumstances described by the conditional header field(s). The conditional GET
|
|
216
|
-
* method is intended to reduce unnecessary network usage by allowing cached entities to be refreshed without requiring
|
|
217
|
-
* multiple requests or transferring data already held by the client.
|
|
218
|
-
*
|
|
219
|
-
* The semantics of the GET method change to a "partial GET" if the request message includes a Range header field. A
|
|
220
|
-
* partial GET requests that only part of the entity be transferred, as described in section 14.35. The partial GET
|
|
221
|
-
* method is intended to reduce unnecessary network usage by allowing partially-retrieved entities to be completed
|
|
222
|
-
* without transferring data already held by the client.
|
|
223
|
-
*
|
|
224
|
-
* The response to a GET request is cacheable if and only if it meets the requirements for HTTP caching described in
|
|
225
|
-
* section 13.
|
|
226
|
-
*
|
|
227
|
-
* See section 15.1.3 for security considerations when used for forms.
|
|
211
|
+
* Parses a media type string.
|
|
212
|
+
* @param mediaType The media type to parse.
|
|
213
|
+
* @returns The parsed media type or null if the mediaType cannot be parsed.
|
|
228
214
|
*/
|
|
229
|
-
|
|
215
|
+
static parse(mediaType) {
|
|
216
|
+
try {
|
|
217
|
+
return new _MediaType(mediaType);
|
|
218
|
+
} catch {
|
|
219
|
+
}
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
230
222
|
/**
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
* sent in response to a GET request. This method can be used for obtaining meta information about the entity implied by
|
|
234
|
-
* the request without transferring the entity-body itself. This method is often used for testing hypertext links for
|
|
235
|
-
* validity, accessibility, and recent modification.
|
|
236
|
-
*
|
|
237
|
-
* The response to a HEAD request MAY be cacheable in the sense that the information contained in the response MAY be
|
|
238
|
-
* used to update a previously cached entity from that resource. If the new field values indicate that the cached
|
|
239
|
-
* entity differs from the current entity (as would be indicated by a change in Content-Length, Content-MD5, ETag or
|
|
240
|
-
* Last-Modified), then the cache MUST treat the cache entry as stale.
|
|
223
|
+
* Gets the type.
|
|
224
|
+
* @returns The type.
|
|
241
225
|
*/
|
|
242
|
-
|
|
226
|
+
get type() {
|
|
227
|
+
return this._type;
|
|
228
|
+
}
|
|
243
229
|
/**
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
* method to cover the following functions:
|
|
247
|
-
* <ul>
|
|
248
|
-
* <li>Annotation of existing resources,</li>
|
|
249
|
-
* <li>Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles,</li>
|
|
250
|
-
* <li>Providing a block of data, such as the result of submitting a form, to a data-handling process,</li>
|
|
251
|
-
* <li>Extending a database through an append operation.</li>
|
|
252
|
-
* </ul>
|
|
253
|
-
*
|
|
254
|
-
* The actual function performed by the POST method is determined by the server and is usually dependent on the
|
|
255
|
-
* Request-URI. The posted entity is subordinate to that URI in the same way that a file is subordinate to a directory
|
|
256
|
-
* containing it, a news article is subordinate to a newsgroup to which it is posted, or a record is subordinate to a
|
|
257
|
-
* database.
|
|
258
|
-
*
|
|
259
|
-
* The action performed by the POST method might not result in a resource that can be identified by a URI. In this
|
|
260
|
-
* case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the
|
|
261
|
-
* response includes an entity that describes the result.
|
|
262
|
-
*
|
|
263
|
-
* If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity
|
|
264
|
-
* which describes the status of the request and refers to the new resource, and a Location header (see section 14.30).
|
|
265
|
-
*
|
|
266
|
-
* Responses to this method are not cacheable, unless the response includes appropriate Cache-Control or Expires header
|
|
267
|
-
* fields. However, the 303 (See Other) response can be used to direct the user agent to retrieve a cacheable resource.
|
|
268
|
-
*
|
|
269
|
-
* POST requests MUST obey the message transmission requirements set out in section 8.2.
|
|
270
|
-
*
|
|
271
|
-
* See section 15.1.3 for security considerations.
|
|
230
|
+
* Gets the subtype.
|
|
231
|
+
* @returns The subtype.
|
|
272
232
|
*/
|
|
273
|
-
|
|
233
|
+
get subtype() {
|
|
234
|
+
return this._subtype;
|
|
235
|
+
}
|
|
274
236
|
/**
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
* on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being
|
|
278
|
-
* defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. If
|
|
279
|
-
* a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an
|
|
280
|
-
* existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate
|
|
281
|
-
* successful completion of the request. If the resource could not be created or modified with the Request-URI, an
|
|
282
|
-
* appropriate error response SHOULD be given that reflects the nature of the problem. The recipient of the entity MUST
|
|
283
|
-
* \NOT ignore any Content-* (e.g. Content-Range) headers that it does not understand or implement and MUST return a
|
|
284
|
-
* 501 (Not Implemented) response in such cases.
|
|
285
|
-
*
|
|
286
|
-
* If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those
|
|
287
|
-
* entries SHOULD be treated as stale. Responses to this method are not cacheable.
|
|
288
|
-
*
|
|
289
|
-
* The fundamental difference between the POST and PUT requests is reflected in the different meaning of the
|
|
290
|
-
* Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource
|
|
291
|
-
* might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations.
|
|
292
|
-
* In contrast, the URI in a PUT request identifies the entity enclosed with the request -- the user agent knows what
|
|
293
|
-
* URI is intended and the server MUST NOT attempt to apply the request to some other resource. If the server desires
|
|
294
|
-
* that the request be applied to a different URI, it MUST send a 301 (Moved Permanently) response, the user agent MAY
|
|
295
|
-
* then make its own decision regarding whether or not to redirect the request.
|
|
296
|
-
*
|
|
297
|
-
* A single resource MAY be identified by many different URIs. For example, an article might have a URI for identifying
|
|
298
|
-
* "the current version" which is separate from the URI identifying each particular version. In this case, a PUT
|
|
299
|
-
* request on a general URI might result in several other URIs being defined by the origin server.
|
|
300
|
-
*
|
|
301
|
-
* HTTP/1.1 does not define how a PUT method affects the state of an origin server.
|
|
302
|
-
*
|
|
303
|
-
* PUT requests MUST obey the message transmission requirements set out in section 8.2.
|
|
304
|
-
*
|
|
305
|
-
* Unless otherwise specified for a particular entity-header, the entity-headers in the PUT request SHOULD be applied
|
|
306
|
-
* to the resource created or modified by the PUT.
|
|
237
|
+
* Gets the media type essence (type/subtype).
|
|
238
|
+
* @returns The media type without any parameters
|
|
307
239
|
*/
|
|
308
|
-
|
|
240
|
+
get essence() {
|
|
241
|
+
return `${this._type}/${this._subtype}`;
|
|
242
|
+
}
|
|
309
243
|
/**
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
* operation has been carried out, even if the status code returned from the origin server indicates that the action
|
|
313
|
-
* has been completed successfully. However, the server SHOULD NOT indicate success unless, at the time the response
|
|
314
|
-
* is given, it intends to delete the resource or move it to an inaccessible location.
|
|
315
|
-
*
|
|
316
|
-
* A successful response SHOULD be 200 (OK) if the response includes an entity describing the status, 202 (Accepted) if
|
|
317
|
-
* the action has not yet been enacted, or 204 (No Content) if the action has been enacted but the response does not
|
|
318
|
-
* include an entity.
|
|
319
|
-
*
|
|
320
|
-
* If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those
|
|
321
|
-
* entries SHOULD be treated as stale. Responses to this method are not cacheable.
|
|
244
|
+
* Gets the parameters.
|
|
245
|
+
* @returns The media type parameters.
|
|
322
246
|
*/
|
|
323
|
-
|
|
247
|
+
get parameters() {
|
|
248
|
+
return this._parameters;
|
|
249
|
+
}
|
|
324
250
|
/**
|
|
325
|
-
*
|
|
326
|
-
* recipient of the request SHOULD reflect the message received back to the client as the entity-body of a 200 (OK)
|
|
327
|
-
* response. The final recipient is either the origin server or the first proxy or gateway to receive a Max-Forwards
|
|
328
|
-
* value of zero (0) in the request (see section 14.31). A TRACE request MUST NOT include an entity.
|
|
329
|
-
*
|
|
330
|
-
* TRACE allows the client to see what is being received at the other end of the request chain and use that data for
|
|
331
|
-
* testing or diagnostic information. The value of the Via header field (section 14.45) is of particular interest,
|
|
332
|
-
* since it acts as a trace of the request chain. Use of the Max-Forwards header field allows the client to limit the
|
|
333
|
-
* length of the request chain, which is useful for testing a chain of proxies forwarding messages in an infinite loop.
|
|
251
|
+
* Checks if the media type matches the specified type.
|
|
334
252
|
*
|
|
335
|
-
*
|
|
336
|
-
*
|
|
253
|
+
* @param mediaType The media type to check.
|
|
254
|
+
* @returns true if the media type matches the specified type, false otherwise.
|
|
337
255
|
*/
|
|
338
|
-
|
|
256
|
+
matches(mediaType) {
|
|
257
|
+
return typeof mediaType === "string" ? this.essence.includes(mediaType) : this._type === mediaType._type && this._subtype === mediaType._subtype;
|
|
258
|
+
}
|
|
339
259
|
/**
|
|
340
|
-
*
|
|
341
|
-
*
|
|
260
|
+
* Gets the serialized version of the media type.
|
|
261
|
+
*
|
|
262
|
+
* @returns The serialized media type.
|
|
342
263
|
*/
|
|
343
|
-
|
|
264
|
+
toString() {
|
|
265
|
+
return `${this.essence}${this._parameters.toString()}`;
|
|
266
|
+
}
|
|
344
267
|
/**
|
|
345
|
-
*
|
|
346
|
-
*
|
|
347
|
-
* URI. The set of changes is represented in a format called a "patch
|
|
348
|
-
* document" identified by a media type. If the Request-URI does not
|
|
349
|
-
* point to an existing resource, the server MAY create a new resource,
|
|
350
|
-
* depending on the patch document type (whether it can logically modify
|
|
351
|
-
* a null resource) and permissions, etc.
|
|
352
|
-
*
|
|
353
|
-
* The difference between the PUT and PATCH requests is reflected in the
|
|
354
|
-
* way the server processes the enclosed entity to modify the resource
|
|
355
|
-
* identified by the Request-URI. In a PUT request, the enclosed entity
|
|
356
|
-
* is considered to be a modified version of the resource stored on the
|
|
357
|
-
* origin server, and the client is requesting that the stored version
|
|
358
|
-
* be replaced. With PATCH, however, the enclosed entity contains a set
|
|
359
|
-
* of instructions describing how a resource currently residing on the
|
|
360
|
-
* origin server should be modified to produce a new version. The PATCH
|
|
361
|
-
* method affects the resource identified by the Request-URI, and it
|
|
362
|
-
* also MAY have side effects on other resources; i.e., new resources
|
|
363
|
-
* may be created, or existing ones modified, by the application of a
|
|
364
|
-
* PATCH.
|
|
365
|
-
*
|
|
366
|
-
* PATCH is neither safe nor idempotent as defined by [RFC2616], Section
|
|
367
|
-
* 9.1.
|
|
368
|
-
*
|
|
369
|
-
* A PATCH request can be issued in such a way as to be idempotent,
|
|
370
|
-
* which also helps prevent bad outcomes from collisions between two
|
|
371
|
-
* PATCH requests on the same resource in a similar time frame.
|
|
372
|
-
* Collisions from multiple PATCH requests may be more dangerous than
|
|
373
|
-
* PUT collisions because some patch formats need to operate from a
|
|
374
|
-
* known base-point or else they will corrupt the resource. Clients
|
|
375
|
-
* using this kind of patch application SHOULD use a conditional request
|
|
376
|
-
* such that the request will fail if the resource has been updated
|
|
377
|
-
* since the client last accessed the resource. For example, the client
|
|
378
|
-
* can use a strong ETag [RFC2616] in an If-Match header on the PATCH
|
|
379
|
-
* request.
|
|
380
|
-
*
|
|
381
|
-
* There are also cases where patch formats do not need to operate from
|
|
382
|
-
* a known base-point (e.g., appending text lines to log files, or non-
|
|
383
|
-
* colliding rows to database tables), in which case the same care in
|
|
384
|
-
* client requests is not needed.
|
|
385
|
-
*
|
|
386
|
-
* The server MUST apply the entire set of changes atomically and never
|
|
387
|
-
* provide (e.g., in response to a GET during this operation) a
|
|
388
|
-
* partially modified representation. If the entire patch document
|
|
389
|
-
* cannot be successfully applied, then the server MUST NOT apply any of
|
|
390
|
-
* the changes. The determination of what constitutes a successful
|
|
391
|
-
* PATCH can vary depending on the patch document and the type of
|
|
392
|
-
* resource(s) being modified. For example, the common 'diff' utility
|
|
393
|
-
* can generate a patch document that applies to multiple files in a
|
|
394
|
-
* directory hierarchy. The atomicity requirement holds for all
|
|
395
|
-
* directly affected files. See "Error Handling", Section 2.2, for
|
|
396
|
-
* details on status codes and possible error conditions.
|
|
397
|
-
*
|
|
398
|
-
* If the request passes through a cache and the Request-URI identifies
|
|
399
|
-
* one or more currently cached entities, those entries SHOULD be
|
|
400
|
-
* treated as stale. A response to this method is only cacheable if it
|
|
401
|
-
* contains explicit freshness information (such as an Expires header or
|
|
402
|
-
* "Cache-Control: max-age" directive) as well as the Content-Location
|
|
403
|
-
* header matching the Request-URI, indicating that the PATCH response
|
|
404
|
-
* body is a resource representation. A cached PATCH response can only
|
|
405
|
-
* be used to respond to subsequent GET and HEAD requests; it MUST NOT
|
|
406
|
-
* be used to respond to other methods (in particular, PATCH).
|
|
407
|
-
*
|
|
408
|
-
* Note that entity-headers contained in the request apply only to the
|
|
409
|
-
* contained patch document and MUST NOT be applied to the resource
|
|
410
|
-
* being modified. Thus, a Content-Language header could be present on
|
|
411
|
-
* the request, but it would only mean (for whatever that's worth) that
|
|
412
|
-
* the patch document had a language. Servers SHOULD NOT store such
|
|
413
|
-
* headers except as trace information, and SHOULD NOT use such header
|
|
414
|
-
* values the same way they might be used on PUT requests. Therefore,
|
|
415
|
-
* this document does not specify a way to modify a document's Content-
|
|
416
|
-
* Type or Content-Language value through headers, though a mechanism
|
|
417
|
-
* could well be designed to achieve this goal through a patch document.
|
|
418
|
-
*
|
|
419
|
-
* There is no guarantee that a resource can be modified with PATCH.
|
|
420
|
-
* Further, it is expected that different patch document formats will be
|
|
421
|
-
* appropriate for different types of resources and that no single
|
|
422
|
-
* format will be appropriate for all types of resources. Therefore,
|
|
423
|
-
* there is no single default patch document format that implementations
|
|
424
|
-
* are required to support. Servers MUST ensure that a received patch
|
|
425
|
-
* document is appropriate for the type of resource identified by the
|
|
426
|
-
* Request-URI.
|
|
427
|
-
*
|
|
428
|
-
* Clients need to choose when to use PATCH rather than PUT. For
|
|
429
|
-
* example, if the patch document size is larger than the size of the
|
|
430
|
-
* new resource data that would be used in a PUT, then it might make
|
|
431
|
-
* sense to use PUT instead of PATCH. A comparison to POST is even more
|
|
432
|
-
* difficult, because POST is used in widely varying ways and can
|
|
433
|
-
* encompass PUT and PATCH-like operations if the server chooses. If
|
|
434
|
-
* the operation does not modify the resource identified by the Request-
|
|
435
|
-
* URI in a predictable way, POST should be considered instead of PATCH
|
|
436
|
-
* or PUT.
|
|
268
|
+
* Gets the name of the class.
|
|
269
|
+
* @returns The class name
|
|
437
270
|
*/
|
|
438
|
-
|
|
271
|
+
get [Symbol.toStringTag]() {
|
|
272
|
+
return "MediaType";
|
|
273
|
+
}
|
|
439
274
|
};
|
|
440
|
-
var http_request_methods_default = HttpRequestMethod;
|
|
441
275
|
|
|
442
|
-
//
|
|
443
|
-
var
|
|
444
|
-
/** @type {number} */
|
|
445
|
-
#code;
|
|
446
|
-
/** @type {string} */
|
|
447
|
-
#text;
|
|
276
|
+
// node_modules/.pnpm/@d1g1tal+subscribr@4.1.8_typescript@5.9.3/node_modules/@d1g1tal/subscribr/dist/subscribr.js
|
|
277
|
+
var SetMultiMap = class extends Map {
|
|
448
278
|
/**
|
|
279
|
+
* Adds a new element with a specified key and value to the SetMultiMap.
|
|
280
|
+
* If an element with the same key already exists, the value will be added to the underlying {@link Set}.
|
|
281
|
+
* If the value already exists in the {@link Set}, it will not be added again.
|
|
449
282
|
*
|
|
450
|
-
* @param
|
|
451
|
-
* @param
|
|
283
|
+
* @param key The key to set.
|
|
284
|
+
* @param value The value to add to the SetMultiMap
|
|
285
|
+
* @returns The SetMultiMap with the updated key and value.
|
|
452
286
|
*/
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
this
|
|
287
|
+
set(key, value) {
|
|
288
|
+
super.set(key, value instanceof Set ? value : (super.get(key) ?? /* @__PURE__ */ new Set()).add(value));
|
|
289
|
+
return this;
|
|
456
290
|
}
|
|
457
291
|
/**
|
|
458
|
-
*
|
|
459
|
-
*
|
|
460
|
-
* @
|
|
292
|
+
* Finds a specific value for a specific key using an iterator function.
|
|
293
|
+
* @param key The key to find the value for.
|
|
294
|
+
* @param iterator The iterator function to use to find the value.
|
|
295
|
+
* @returns The value for the specified key
|
|
461
296
|
*/
|
|
462
|
-
|
|
463
|
-
|
|
297
|
+
find(key, iterator) {
|
|
298
|
+
const values = this.get(key);
|
|
299
|
+
if (values !== void 0) {
|
|
300
|
+
return Array.from(values).find(iterator);
|
|
301
|
+
}
|
|
302
|
+
return void 0;
|
|
464
303
|
}
|
|
465
304
|
/**
|
|
466
|
-
*
|
|
305
|
+
* Checks if a specific key has a specific value.
|
|
467
306
|
*
|
|
468
|
-
* @
|
|
307
|
+
* @param key The key to check.
|
|
308
|
+
* @param value The value to check.
|
|
309
|
+
* @returns True if the key has the value, false otherwise.
|
|
469
310
|
*/
|
|
470
|
-
|
|
471
|
-
|
|
311
|
+
hasValue(key, value) {
|
|
312
|
+
const values = super.get(key);
|
|
313
|
+
return values ? values.has(value) : false;
|
|
472
314
|
}
|
|
473
315
|
/**
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
* @
|
|
478
|
-
|
|
316
|
+
* Removes a specific value from a specific key.
|
|
317
|
+
* @param key The key to remove the value from.
|
|
318
|
+
* @param value The value to remove.
|
|
319
|
+
* @returns True if the value was removed, false otherwise.
|
|
320
|
+
*/
|
|
321
|
+
deleteValue(key, value) {
|
|
322
|
+
if (value === void 0) {
|
|
323
|
+
return this.delete(key);
|
|
324
|
+
}
|
|
325
|
+
const values = super.get(key);
|
|
326
|
+
if (values) {
|
|
327
|
+
const deleted = values.delete(value);
|
|
328
|
+
if (values.size === 0) {
|
|
329
|
+
super.delete(key);
|
|
330
|
+
}
|
|
331
|
+
return deleted;
|
|
332
|
+
}
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* The string tag of the SetMultiMap.
|
|
337
|
+
* @returns The string tag of the SetMultiMap.
|
|
479
338
|
*/
|
|
480
339
|
get [Symbol.toStringTag]() {
|
|
481
|
-
return "
|
|
340
|
+
return "SetMultiMap";
|
|
482
341
|
}
|
|
342
|
+
};
|
|
343
|
+
var ContextEventHandler = class {
|
|
344
|
+
context;
|
|
345
|
+
eventHandler;
|
|
483
346
|
/**
|
|
484
|
-
*
|
|
347
|
+
* @param context The context to bind to the event handler.
|
|
348
|
+
* @param eventHandler The event handler to call when the event is published.
|
|
349
|
+
*/
|
|
350
|
+
constructor(context, eventHandler) {
|
|
351
|
+
this.context = context;
|
|
352
|
+
this.eventHandler = eventHandler;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Call the event handler for the provided event.
|
|
485
356
|
*
|
|
486
|
-
* @
|
|
487
|
-
* @
|
|
488
|
-
* @returns {string} The status code and status text.
|
|
357
|
+
* @param event The event to handle
|
|
358
|
+
* @param data The value to be passed to the event handler as a parameter.
|
|
489
359
|
*/
|
|
490
|
-
|
|
491
|
-
|
|
360
|
+
handle(event, data) {
|
|
361
|
+
this.eventHandler.call(this.context, event, data);
|
|
492
362
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
const target = {};
|
|
502
|
-
for (const source of objects) {
|
|
503
|
-
if (object_type_default(source) != Object)
|
|
504
|
-
return void 0;
|
|
505
|
-
let descriptor, sourceType;
|
|
506
|
-
for (const property of Object.getOwnPropertyNames(source)) {
|
|
507
|
-
descriptor = Object.getOwnPropertyDescriptor(source, property);
|
|
508
|
-
if (descriptor.enumerable) {
|
|
509
|
-
sourceType = object_type_default(source[property]);
|
|
510
|
-
if (sourceType == Object) {
|
|
511
|
-
descriptor.value = object_type_default(target[property]) == Object ? _objectMerge(target[property], source[property]) : { ...source[property] };
|
|
512
|
-
} else if (sourceType == Array) {
|
|
513
|
-
descriptor.value = Array.isArray(target[property]) ? [.../* @__PURE__ */ new Set([...source[property], ...target[property]])] : [...source[property]];
|
|
514
|
-
}
|
|
515
|
-
target[property] = descriptor.value;
|
|
516
|
-
}
|
|
517
|
-
}
|
|
363
|
+
/**
|
|
364
|
+
* A String value that is used in the creation of the default string
|
|
365
|
+
* description of an object. Called by the built-in method {@link Object.prototype.toString}.
|
|
366
|
+
*
|
|
367
|
+
* @returns The default string description of this object.
|
|
368
|
+
*/
|
|
369
|
+
get [Symbol.toStringTag]() {
|
|
370
|
+
return "ContextEventHandler";
|
|
518
371
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
// node_modules/.pnpm/@d1g1tal+media-type@5.0.0/node_modules/@d1g1tal/media-type/src/utils.js
|
|
524
|
-
var httpTokenCodePoints = /^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/u;
|
|
525
|
-
var utils_default = httpTokenCodePoints;
|
|
526
|
-
|
|
527
|
-
// node_modules/.pnpm/@d1g1tal+media-type@5.0.0/node_modules/@d1g1tal/media-type/src/media-type-parameters.js
|
|
528
|
-
var matcher = /(["\\])/ug;
|
|
529
|
-
var httpQuotedStringTokenCodePoints = /^[\t\u0020-\u007E\u0080-\u00FF]*$/u;
|
|
530
|
-
var MediaTypeParameters = class _MediaTypeParameters extends Map {
|
|
372
|
+
};
|
|
373
|
+
var Subscription = class {
|
|
374
|
+
_eventName;
|
|
375
|
+
_contextEventHandler;
|
|
531
376
|
/**
|
|
532
|
-
*
|
|
533
|
-
*
|
|
534
|
-
* @param {Array<[string, string]>} entries An array of [name, value] tuples.
|
|
377
|
+
* @param eventName The event name.
|
|
378
|
+
* @param contextEventHandler The context event handler.
|
|
535
379
|
*/
|
|
536
|
-
constructor(
|
|
537
|
-
|
|
380
|
+
constructor(eventName, contextEventHandler) {
|
|
381
|
+
this._eventName = eventName;
|
|
382
|
+
this._contextEventHandler = contextEventHandler;
|
|
538
383
|
}
|
|
539
384
|
/**
|
|
540
|
-
*
|
|
385
|
+
* Gets the event name for the subscription.
|
|
541
386
|
*
|
|
542
|
-
* @
|
|
543
|
-
* @param {string} name The name of the media type parameter to validate.
|
|
544
|
-
* @param {string} value The media type parameter value to validate.
|
|
545
|
-
* @returns {boolean} true if the media type parameter is valid, false otherwise.
|
|
387
|
+
* @returns The event name.
|
|
546
388
|
*/
|
|
547
|
-
|
|
548
|
-
return
|
|
389
|
+
get eventName() {
|
|
390
|
+
return this._eventName;
|
|
549
391
|
}
|
|
550
392
|
/**
|
|
551
|
-
* Gets the
|
|
393
|
+
* Gets the context event handler.
|
|
552
394
|
*
|
|
553
|
-
* @
|
|
554
|
-
* @returns {string} The media type parameter value.
|
|
395
|
+
* @returns The context event handler
|
|
555
396
|
*/
|
|
556
|
-
get(
|
|
557
|
-
return
|
|
397
|
+
get contextEventHandler() {
|
|
398
|
+
return this._contextEventHandler;
|
|
558
399
|
}
|
|
559
400
|
/**
|
|
560
|
-
*
|
|
401
|
+
* A String value that is used in the creation of the default string
|
|
402
|
+
* description of an object. Called by the built-in method {@link Object.prototype.toString}.
|
|
561
403
|
*
|
|
562
|
-
* @
|
|
563
|
-
* @returns {boolean} true if the media type parameter exists, false otherwise.
|
|
404
|
+
* @returns The default string description of this object.
|
|
564
405
|
*/
|
|
565
|
-
|
|
566
|
-
return
|
|
406
|
+
get [Symbol.toStringTag]() {
|
|
407
|
+
return "Subscription";
|
|
567
408
|
}
|
|
409
|
+
};
|
|
410
|
+
var Subscribr = class {
|
|
411
|
+
subscribers = new SetMultiMap();
|
|
412
|
+
errorHandler;
|
|
568
413
|
/**
|
|
569
|
-
*
|
|
570
|
-
* If
|
|
414
|
+
* Set a custom error handler for handling errors that occur in event listeners.
|
|
415
|
+
* If not set, errors will be logged to the console.
|
|
571
416
|
*
|
|
572
|
-
* @param
|
|
573
|
-
* @param {string} value The media type parameter value.
|
|
574
|
-
* @returns {MediaTypeParameters} This instance.
|
|
417
|
+
* @param errorHandler The error handler function to call when an error occurs in an event listener.
|
|
575
418
|
*/
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
throw new Error(`Invalid media type parameter name/value: ${name}/${value}`);
|
|
579
|
-
}
|
|
580
|
-
super.set(name.toLowerCase(), value);
|
|
581
|
-
return this;
|
|
419
|
+
setErrorHandler(errorHandler) {
|
|
420
|
+
this.errorHandler = errorHandler;
|
|
582
421
|
}
|
|
583
422
|
/**
|
|
584
|
-
*
|
|
423
|
+
* Subscribe to an event
|
|
585
424
|
*
|
|
586
|
-
* @param
|
|
587
|
-
* @
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
425
|
+
* @param eventName The event name to subscribe to.
|
|
426
|
+
* @param eventHandler The event handler to call when the event is published.
|
|
427
|
+
* @param context The context to bind to the event handler.
|
|
428
|
+
* @param options Subscription options.
|
|
429
|
+
* @returns An object used to check if the subscription still exists and to unsubscribe from the event.
|
|
430
|
+
*/
|
|
431
|
+
subscribe(eventName, eventHandler, context = eventHandler, options) {
|
|
432
|
+
this.validateEventName(eventName);
|
|
433
|
+
if (options?.once) {
|
|
434
|
+
const originalHandler = eventHandler;
|
|
435
|
+
eventHandler = (event, data) => {
|
|
436
|
+
originalHandler.call(context, event, data);
|
|
437
|
+
this.unsubscribe(subscription);
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
const contextEventHandler = new ContextEventHandler(context, eventHandler);
|
|
441
|
+
this.subscribers.set(eventName, contextEventHandler);
|
|
442
|
+
const subscription = new Subscription(eventName, contextEventHandler);
|
|
443
|
+
return subscription;
|
|
591
444
|
}
|
|
592
445
|
/**
|
|
593
|
-
*
|
|
446
|
+
* Unsubscribe from the event
|
|
594
447
|
*
|
|
595
|
-
* @
|
|
596
|
-
* @returns
|
|
448
|
+
* @param subscription The subscription to unsubscribe.
|
|
449
|
+
* @returns true if eventListener has been removed successfully. false if the value is not found or if the value is not an object.
|
|
597
450
|
*/
|
|
598
|
-
|
|
599
|
-
|
|
451
|
+
unsubscribe({ eventName, contextEventHandler }) {
|
|
452
|
+
const contextEventHandlers = this.subscribers.get(eventName) ?? /* @__PURE__ */ new Set();
|
|
453
|
+
const removed = contextEventHandlers.delete(contextEventHandler);
|
|
454
|
+
if (removed && contextEventHandlers.size === 0) {
|
|
455
|
+
this.subscribers.delete(eventName);
|
|
456
|
+
}
|
|
457
|
+
return removed;
|
|
600
458
|
}
|
|
601
459
|
/**
|
|
602
|
-
*
|
|
460
|
+
* Publish an event
|
|
603
461
|
*
|
|
604
|
-
* @
|
|
605
|
-
* @
|
|
462
|
+
* @template T
|
|
463
|
+
* @param eventName The name of the event.
|
|
464
|
+
* @param event The event to be handled.
|
|
465
|
+
* @param data The value to be passed to the event handler as a parameter.
|
|
606
466
|
*/
|
|
607
|
-
|
|
608
|
-
|
|
467
|
+
publish(eventName, event = new CustomEvent(eventName), data) {
|
|
468
|
+
this.validateEventName(eventName);
|
|
469
|
+
this.subscribers.get(eventName)?.forEach((contextEventHandler) => {
|
|
470
|
+
try {
|
|
471
|
+
contextEventHandler.handle(event, data);
|
|
472
|
+
} catch (error) {
|
|
473
|
+
if (this.errorHandler) {
|
|
474
|
+
this.errorHandler(error, eventName, event, data);
|
|
475
|
+
} else {
|
|
476
|
+
console.error(`Error in event handler for '${eventName}':`, error);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
});
|
|
609
480
|
}
|
|
610
|
-
};
|
|
611
|
-
|
|
612
|
-
// node_modules/.pnpm/@d1g1tal+media-type@5.0.0/node_modules/@d1g1tal/media-type/src/media-type-parser.js
|
|
613
|
-
var whitespaceCharacters = [" ", " ", "\n", "\r"];
|
|
614
|
-
var trailingWhitespace = /[ \t\n\r]+$/u;
|
|
615
|
-
var leadingAndTrailingWhitespace = /^[ \t\n\r]+|[ \t\n\r]+$/ug;
|
|
616
|
-
var MediaTypeParser = class _MediaTypeParser {
|
|
617
481
|
/**
|
|
618
|
-
*
|
|
482
|
+
* Check if the event and handler are subscribed.
|
|
619
483
|
*
|
|
620
|
-
* @
|
|
621
|
-
* @
|
|
622
|
-
* @returns {{ type: string, subtype: string, parameters: MediaTypeParameters }} An object populated with the parsed media type properties and any parameters.
|
|
484
|
+
* @param subscription The subscription object.
|
|
485
|
+
* @returns true if the event name and handler are subscribed, false otherwise.
|
|
623
486
|
*/
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
const length = input.length, trim = true, lowerCase = false;
|
|
627
|
-
let { position, result: type, subtype = "" } = _MediaTypeParser.#filterComponent({ input }, "/");
|
|
628
|
-
if (!type.length || position >= length || !utils_default.test(type)) {
|
|
629
|
-
throw new TypeError(_MediaTypeParser.#generateErrorMessage("type", type));
|
|
630
|
-
}
|
|
631
|
-
({ position, result: subtype } = _MediaTypeParser.#filterComponent({ position: ++position, input, trim }, ";"));
|
|
632
|
-
if (!subtype.length || !utils_default.test(subtype)) {
|
|
633
|
-
throw new TypeError(_MediaTypeParser.#generateErrorMessage("subtype", subtype));
|
|
634
|
-
}
|
|
635
|
-
let parameterName = "", parameterValue = null;
|
|
636
|
-
const parameters = new MediaTypeParameters();
|
|
637
|
-
while (position++ < length) {
|
|
638
|
-
while (whitespaceCharacters.includes(input[position])) {
|
|
639
|
-
++position;
|
|
640
|
-
}
|
|
641
|
-
({ position, result: parameterName } = _MediaTypeParser.#filterComponent({ position, input, lowerCase }, ";", "="));
|
|
642
|
-
if (position < length) {
|
|
643
|
-
if (input[position] == ";") {
|
|
644
|
-
continue;
|
|
645
|
-
}
|
|
646
|
-
++position;
|
|
647
|
-
}
|
|
648
|
-
if (input[position] == '"') {
|
|
649
|
-
[parameterValue, position] = _MediaTypeParser.#collectHttpQuotedString(input, position);
|
|
650
|
-
while (position < length && input[position] != ";") {
|
|
651
|
-
++position;
|
|
652
|
-
}
|
|
653
|
-
} else {
|
|
654
|
-
({ position, result: parameterValue } = _MediaTypeParser.#filterComponent({ position, input, lowerCase, trim }, ";"));
|
|
655
|
-
if (!parameterValue) {
|
|
656
|
-
continue;
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
if (parameterName && MediaTypeParameters.isValid(parameterName, parameterValue) && !parameters.has(parameterName)) {
|
|
660
|
-
parameters.set(parameterName, parameterValue);
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
return { type, subtype, parameters };
|
|
487
|
+
isSubscribed({ eventName, contextEventHandler }) {
|
|
488
|
+
return this.subscribers.get(eventName)?.has(contextEventHandler) ?? false;
|
|
664
489
|
}
|
|
665
490
|
/**
|
|
666
|
-
*
|
|
491
|
+
* Validate the event name
|
|
667
492
|
*
|
|
668
|
-
* @
|
|
669
|
-
* @
|
|
670
|
-
* @
|
|
671
|
-
* @param {number} [options.position] The starting position.
|
|
672
|
-
* @param {string} options.input The input string.
|
|
673
|
-
* @param {boolean} [options.lowerCase] Indicates whether the result should be lowercased.
|
|
674
|
-
* @param {boolean} [options.trim] Indicates whether the result should be trimmed.
|
|
675
|
-
* @param {string[]} charactersToFilter The characters to filter.
|
|
676
|
-
* @returns {{ position: number, result: string }} An object that includes the resulting string and updated position.
|
|
493
|
+
* @param eventName The event name to validate.
|
|
494
|
+
* @throws {TypeError} If the event name is not a non-empty string.
|
|
495
|
+
* @throws {Error} If the event name has leading or trailing whitespace.
|
|
677
496
|
*/
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
result += input[position];
|
|
682
|
-
}
|
|
683
|
-
if (lowerCase) {
|
|
684
|
-
result = result.toLowerCase();
|
|
497
|
+
validateEventName(eventName) {
|
|
498
|
+
if (!eventName || typeof eventName !== "string") {
|
|
499
|
+
throw new TypeError("Event name must be a non-empty string");
|
|
685
500
|
}
|
|
686
|
-
if (trim) {
|
|
687
|
-
|
|
501
|
+
if (eventName.trim() !== eventName) {
|
|
502
|
+
throw new Error("Event name cannot have leading or trailing whitespace");
|
|
688
503
|
}
|
|
689
|
-
return { position, result };
|
|
690
504
|
}
|
|
691
505
|
/**
|
|
692
|
-
*
|
|
693
|
-
* This variant only implements it with the extract-value flag set.
|
|
694
|
-
*
|
|
695
|
-
* @private
|
|
696
|
-
* @static
|
|
697
|
-
* @param {string} input The string to process.
|
|
698
|
-
* @param {number} position The starting position.
|
|
699
|
-
* @returns {Array<string|number>} An array that includes the resulting string and updated position.
|
|
506
|
+
* Clears all subscriptions. The instance should not be used after calling this method.
|
|
700
507
|
*/
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
for (let length = input.length, char; ++position < length; ) {
|
|
704
|
-
if ((char = input[position]) == '"') {
|
|
705
|
-
break;
|
|
706
|
-
}
|
|
707
|
-
value += char == "\\" && ++position < length ? input[position] : char;
|
|
708
|
-
}
|
|
709
|
-
return [value, position];
|
|
508
|
+
destroy() {
|
|
509
|
+
this.subscribers.clear();
|
|
710
510
|
}
|
|
711
511
|
/**
|
|
712
|
-
*
|
|
512
|
+
* A String value that is used in the creation of the default string
|
|
513
|
+
* description of an object. Called by the built-in method {@link Object.prototype.toString}.
|
|
713
514
|
*
|
|
714
|
-
* @
|
|
715
|
-
* @static
|
|
716
|
-
* @param {string} component The component name.
|
|
717
|
-
* @param {string} value The component value.
|
|
718
|
-
* @returns {string} The error message.
|
|
515
|
+
* @returns The default string description of this object.
|
|
719
516
|
*/
|
|
720
|
-
|
|
721
|
-
return
|
|
517
|
+
get [Symbol.toStringTag]() {
|
|
518
|
+
return "Subscribr";
|
|
722
519
|
}
|
|
723
520
|
};
|
|
724
521
|
|
|
725
|
-
//
|
|
726
|
-
var
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
#parameters;
|
|
522
|
+
// src/http-error.ts
|
|
523
|
+
var HttpError = class extends Error {
|
|
524
|
+
_entity;
|
|
525
|
+
responseStatus;
|
|
526
|
+
_url;
|
|
527
|
+
_method;
|
|
528
|
+
_timing;
|
|
733
529
|
/**
|
|
734
|
-
*
|
|
735
|
-
*
|
|
736
|
-
* @param
|
|
737
|
-
* @param {Object} [parameters] Optional parameters.
|
|
530
|
+
* Creates an instance of HttpError.
|
|
531
|
+
* @param status The status code and status text of the {@link Response}.
|
|
532
|
+
* @param httpErrorOptions The http error options.
|
|
738
533
|
*/
|
|
739
|
-
constructor(
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
}
|
|
534
|
+
constructor(status, { message, cause, entity, url, method, timing } = {}) {
|
|
535
|
+
super(message, { cause });
|
|
536
|
+
this._entity = entity;
|
|
537
|
+
this.responseStatus = status;
|
|
538
|
+
this._url = url;
|
|
539
|
+
this._method = method;
|
|
540
|
+
this._timing = timing;
|
|
747
541
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
return
|
|
542
|
+
/**
|
|
543
|
+
* It returns the value of the private variable #entity.
|
|
544
|
+
* @returns The entity property of the class.
|
|
545
|
+
*/
|
|
546
|
+
get entity() {
|
|
547
|
+
return this._entity;
|
|
754
548
|
}
|
|
755
549
|
/**
|
|
756
|
-
*
|
|
757
|
-
*
|
|
758
|
-
* @returns {string} The type.
|
|
550
|
+
* It returns the status code of the {@link Response}.
|
|
551
|
+
* @returns The status code of the {@link Response}.
|
|
759
552
|
*/
|
|
760
|
-
get
|
|
761
|
-
return this
|
|
553
|
+
get statusCode() {
|
|
554
|
+
return this.responseStatus.code;
|
|
762
555
|
}
|
|
763
556
|
/**
|
|
764
|
-
*
|
|
765
|
-
*
|
|
766
|
-
* @returns {string} The subtype.
|
|
557
|
+
* It returns the status text of the {@link Response}.
|
|
558
|
+
* @returns The status code and status text of the {@link Response}.
|
|
767
559
|
*/
|
|
768
|
-
get
|
|
769
|
-
return this
|
|
560
|
+
get statusText() {
|
|
561
|
+
return this.responseStatus?.text;
|
|
770
562
|
}
|
|
771
563
|
/**
|
|
772
|
-
*
|
|
773
|
-
*
|
|
774
|
-
* @returns {string} The media type without any parameters
|
|
564
|
+
* The request URL that caused the error.
|
|
565
|
+
* @returns The URL or undefined.
|
|
775
566
|
*/
|
|
776
|
-
get
|
|
777
|
-
return
|
|
567
|
+
get url() {
|
|
568
|
+
return this._url;
|
|
778
569
|
}
|
|
779
570
|
/**
|
|
780
|
-
*
|
|
781
|
-
*
|
|
782
|
-
* @returns {MediaTypeParameters} The media type parameters.
|
|
571
|
+
* The HTTP method that was used for the failed request.
|
|
572
|
+
* @returns The method string or undefined.
|
|
783
573
|
*/
|
|
784
|
-
get
|
|
785
|
-
return this
|
|
574
|
+
get method() {
|
|
575
|
+
return this._method;
|
|
786
576
|
}
|
|
787
577
|
/**
|
|
788
|
-
*
|
|
789
|
-
*
|
|
790
|
-
* @todo Fix string handling to parse the type and subtype from the string.
|
|
791
|
-
* @param {MediaType|string} type The media type to check.
|
|
792
|
-
* @returns {boolean} true if the media type matches the specified type, false otherwise.
|
|
578
|
+
* Timing information for the failed request.
|
|
579
|
+
* @returns The timing object or undefined.
|
|
793
580
|
*/
|
|
794
|
-
|
|
795
|
-
return this
|
|
581
|
+
get timing() {
|
|
582
|
+
return this._timing;
|
|
796
583
|
}
|
|
797
584
|
/**
|
|
798
|
-
*
|
|
799
|
-
*
|
|
800
|
-
* @returns {string} The serialized media type.
|
|
585
|
+
* A String value representing the name of the error.
|
|
586
|
+
* @returns The name of the error.
|
|
801
587
|
*/
|
|
802
|
-
|
|
803
|
-
return
|
|
588
|
+
get name() {
|
|
589
|
+
return "HttpError";
|
|
804
590
|
}
|
|
805
591
|
/**
|
|
806
|
-
*
|
|
807
|
-
*
|
|
808
|
-
* @returns
|
|
592
|
+
* A String value that is used in the creation of the default string
|
|
593
|
+
* description of an object. Called by the built-in method {@link Object.prototype.toString}.
|
|
594
|
+
* @returns The default string description of this object.
|
|
809
595
|
*/
|
|
810
596
|
get [Symbol.toStringTag]() {
|
|
811
|
-
return
|
|
597
|
+
return this.name;
|
|
812
598
|
}
|
|
813
599
|
};
|
|
814
600
|
|
|
815
|
-
// src/http-media-type.
|
|
601
|
+
// src/http-media-type.ts
|
|
816
602
|
var HttpMediaType = {
|
|
817
603
|
/** Advanced Audio Coding (AAC) */
|
|
818
604
|
AAC: "audio/aac",
|
|
@@ -967,204 +753,8 @@ var HttpMediaType = {
|
|
|
967
753
|
/** 7-Zip Archive */
|
|
968
754
|
"7Z": "application/x-7z-compressed"
|
|
969
755
|
};
|
|
970
|
-
var http_media_type_default = HttpMediaType;
|
|
971
|
-
|
|
972
|
-
// src/constants.js
|
|
973
|
-
var defaultCharset = "utf-8";
|
|
974
|
-
var endsWithSlashRegEx = /\/$/;
|
|
975
|
-
var mediaTypes = /* @__PURE__ */ new Map([
|
|
976
|
-
[http_media_type_default.PNG, new MediaType(http_media_type_default.PNG)],
|
|
977
|
-
[http_media_type_default.TEXT, new MediaType(http_media_type_default.TEXT, { defaultCharset })],
|
|
978
|
-
[http_media_type_default.JSON, new MediaType(http_media_type_default.JSON, { defaultCharset })],
|
|
979
|
-
[http_media_type_default.HTML, new MediaType(http_media_type_default.HTML, { defaultCharset })],
|
|
980
|
-
[http_media_type_default.JAVA_SCRIPT, new MediaType(http_media_type_default.JAVA_SCRIPT, { defaultCharset })],
|
|
981
|
-
[http_media_type_default.CSS, new MediaType(http_media_type_default.CSS, { defaultCharset })],
|
|
982
|
-
[http_media_type_default.XML, new MediaType(http_media_type_default.XML, { defaultCharset })],
|
|
983
|
-
[http_media_type_default.BIN, new MediaType(http_media_type_default.BIN)]
|
|
984
|
-
]);
|
|
985
|
-
var RequestEvents = Object.freeze({
|
|
986
|
-
CONFIGURED: "configured",
|
|
987
|
-
SUCCESS: "success",
|
|
988
|
-
ERROR: "error",
|
|
989
|
-
ABORTED: "aborted",
|
|
990
|
-
TIMEOUT: "timeout",
|
|
991
|
-
COMPLETE: "complete",
|
|
992
|
-
ALL_COMPLETE: "all-complete"
|
|
993
|
-
});
|
|
994
|
-
var SignalEvents = Object.freeze({
|
|
995
|
-
ABORT: "abort",
|
|
996
|
-
TIMEOUT: "timeout"
|
|
997
|
-
});
|
|
998
|
-
var _abortEvent = new CustomEvent(SignalEvents.ABORT, { detail: { cause: new DOMException("The request was aborted", "AbortError") } });
|
|
999
|
-
var requestBodyMethods = [http_request_methods_default.POST, http_request_methods_default.PUT, http_request_methods_default.PATCH];
|
|
1000
|
-
var internalServerError = new ResponseStatus(500, "Internal Server Error");
|
|
1001
|
-
var eventResponseStatuses = Object.freeze({
|
|
1002
|
-
[RequestEvents.ABORTED]: new ResponseStatus(499, "Aborted"),
|
|
1003
|
-
[RequestEvents.TIMEOUT]: new ResponseStatus(504, "Request Timeout")
|
|
1004
|
-
});
|
|
1005
|
-
var abortSignalProxyHandler = { get: (target, property) => property == "signal" ? target.signal.timeout(target.timeout) : Reflect.get(target, property) };
|
|
1006
|
-
|
|
1007
|
-
// src/abort-signal.js
|
|
1008
|
-
var AbortSignal = class {
|
|
1009
|
-
/** @type {AbortController} */
|
|
1010
|
-
#abortController;
|
|
1011
|
-
/** @type {number} */
|
|
1012
|
-
#timeoutId;
|
|
1013
|
-
/**
|
|
1014
|
-
* @param {NativeAbortSignal} signal The signal to chain.
|
|
1015
|
-
* This signal will be able to abort the request, but will not be notified if the request is aborted by the timeout.
|
|
1016
|
-
*/
|
|
1017
|
-
constructor(signal) {
|
|
1018
|
-
this.#abortController = new AbortController();
|
|
1019
|
-
signal?.addEventListener(SignalEvents.ABORT, (event) => this.#abort(event));
|
|
1020
|
-
}
|
|
1021
|
-
/**
|
|
1022
|
-
* The aborted property is a Boolean that indicates whether the request has been aborted (true) or not (false).
|
|
1023
|
-
*
|
|
1024
|
-
* @returns {boolean} Whether the signal was aborted or not
|
|
1025
|
-
*/
|
|
1026
|
-
get aborted() {
|
|
1027
|
-
return this.#abortController.signal.aborted;
|
|
1028
|
-
}
|
|
1029
|
-
/**
|
|
1030
|
-
* The reason property returns a DOMException object indicating the reason the operation was aborted, or null if the operation is not aborted.
|
|
1031
|
-
*
|
|
1032
|
-
* @returns {DOMException} The reason the signal was aborted
|
|
1033
|
-
*/
|
|
1034
|
-
get reason() {
|
|
1035
|
-
return this.#abortController.signal.reason;
|
|
1036
|
-
}
|
|
1037
|
-
/**
|
|
1038
|
-
* Returns an AbortSignal instance that will be aborted when the provided amount of milliseconds have passed.
|
|
1039
|
-
* A value of {@link Infinity} means there is no timeout.
|
|
1040
|
-
* Note: You can't set this property to a value less than 0.
|
|
1041
|
-
*
|
|
1042
|
-
* @param {number} timeout The timeout in milliseconds
|
|
1043
|
-
* @returns {AbortSignal} The abort signal
|
|
1044
|
-
*/
|
|
1045
|
-
timeout(timeout) {
|
|
1046
|
-
if (timeout < 0) {
|
|
1047
|
-
throw new RangeError("The timeout cannot be negative");
|
|
1048
|
-
}
|
|
1049
|
-
if (timeout != Infinity) {
|
|
1050
|
-
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);
|
|
1051
|
-
}
|
|
1052
|
-
return this.#abortController.signal;
|
|
1053
|
-
}
|
|
1054
|
-
/**
|
|
1055
|
-
* Clears the timeout.
|
|
1056
|
-
* Note: This does not abort the signal, dispatch the timeout event, or reset the timeout.
|
|
1057
|
-
*
|
|
1058
|
-
* @returns {void}
|
|
1059
|
-
*/
|
|
1060
|
-
clearTimeout() {
|
|
1061
|
-
clearTimeout(this.#timeoutId);
|
|
1062
|
-
}
|
|
1063
|
-
/**
|
|
1064
|
-
* Adds an event listener for the 'abort' event.
|
|
1065
|
-
*
|
|
1066
|
-
* @param {EventListener} listener The listener to add
|
|
1067
|
-
* @returns {AbortSignal} The AbortSignal
|
|
1068
|
-
*/
|
|
1069
|
-
onAbort(listener) {
|
|
1070
|
-
this.#abortController.signal.addEventListener(SignalEvents.ABORT, listener);
|
|
1071
|
-
return this;
|
|
1072
|
-
}
|
|
1073
|
-
/**
|
|
1074
|
-
* Adds an event listener for the 'timeout' event.
|
|
1075
|
-
*
|
|
1076
|
-
* @param {EventListener} listener The listener to add
|
|
1077
|
-
* @returns {AbortSignal} The AbortSignal
|
|
1078
|
-
*/
|
|
1079
|
-
onTimeout(listener) {
|
|
1080
|
-
this.#abortController.signal.addEventListener(SignalEvents.TIMEOUT, listener);
|
|
1081
|
-
return this;
|
|
1082
|
-
}
|
|
1083
|
-
/**
|
|
1084
|
-
* Aborts the signal. This is so naughty. ¯\_(ツ)_/¯
|
|
1085
|
-
*
|
|
1086
|
-
* @param {Event} event The event to abort with
|
|
1087
|
-
* @returns {void}
|
|
1088
|
-
*/
|
|
1089
|
-
abort(event) {
|
|
1090
|
-
this.#abort(event);
|
|
1091
|
-
}
|
|
1092
|
-
/**
|
|
1093
|
-
* Aborts the signal.
|
|
1094
|
-
*
|
|
1095
|
-
* @private
|
|
1096
|
-
* @param {Event} event The event to abort with
|
|
1097
|
-
* @param {boolean} [dispatchEvent = false] Whether to dispatch the event or not
|
|
1098
|
-
* @returns {void}
|
|
1099
|
-
* @fires SignalEvents.ABORT When the signal is aborted
|
|
1100
|
-
* @fires SignalEvents.TIMEOUT When the signal times out
|
|
1101
|
-
*/
|
|
1102
|
-
#abort(event = _abortEvent, dispatchEvent = false) {
|
|
1103
|
-
clearTimeout(this.#timeoutId);
|
|
1104
|
-
this.#abortController.abort(event.detail?.cause);
|
|
1105
|
-
if (dispatchEvent) {
|
|
1106
|
-
this.#abortController.signal.dispatchEvent(event);
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1109
|
-
};
|
|
1110
|
-
|
|
1111
|
-
// src/http-error.js
|
|
1112
|
-
var HttpError = class extends Error {
|
|
1113
|
-
/** @type {ResponseBody} */
|
|
1114
|
-
#entity;
|
|
1115
|
-
/** @type {ResponseStatus} */
|
|
1116
|
-
#responseStatus;
|
|
1117
|
-
/**
|
|
1118
|
-
* @param {string} [message] The error message.
|
|
1119
|
-
* @param {HttpErrorOptions} [httpErrorOptions] The http error options.
|
|
1120
|
-
* @param {any} [httpErrorOptions.cause] The cause of the error.
|
|
1121
|
-
* @param {ResponseStatus} [httpErrorOptions.status] The response status.
|
|
1122
|
-
* @param {ResponseBody} [httpErrorOptions.entity] The error entity from the server, if any.
|
|
1123
|
-
*/
|
|
1124
|
-
constructor(message, { cause, status, entity }) {
|
|
1125
|
-
super(message, { cause });
|
|
1126
|
-
this.#entity = entity;
|
|
1127
|
-
this.#responseStatus = status;
|
|
1128
|
-
}
|
|
1129
|
-
/**
|
|
1130
|
-
* It returns the value of the private variable #entity.
|
|
1131
|
-
*
|
|
1132
|
-
* @returns {ResponseBody} The entity property of the class.
|
|
1133
|
-
*/
|
|
1134
|
-
get entity() {
|
|
1135
|
-
return this.#entity;
|
|
1136
|
-
}
|
|
1137
|
-
/**
|
|
1138
|
-
* It returns the status code of the {@link Response}.
|
|
1139
|
-
*
|
|
1140
|
-
* @returns {number} The status code of the {@link Response}.
|
|
1141
|
-
*/
|
|
1142
|
-
get statusCode() {
|
|
1143
|
-
return this.#responseStatus?.code;
|
|
1144
|
-
}
|
|
1145
|
-
/**
|
|
1146
|
-
* It returns the status text of the {@link Response}.
|
|
1147
|
-
*
|
|
1148
|
-
* @returns {string} The status code and status text of the {@link Response}.
|
|
1149
|
-
*/
|
|
1150
|
-
get statusText() {
|
|
1151
|
-
return this.#responseStatus?.text;
|
|
1152
|
-
}
|
|
1153
|
-
get name() {
|
|
1154
|
-
return "HttpError";
|
|
1155
|
-
}
|
|
1156
|
-
/**
|
|
1157
|
-
* A String value that is used in the creation of the default string
|
|
1158
|
-
* description of an object. Called by the built-in method {@link Object.prototype.toString}.
|
|
1159
|
-
*
|
|
1160
|
-
* @returns {string} The default string description of this object.
|
|
1161
|
-
*/
|
|
1162
|
-
get [Symbol.toStringTag]() {
|
|
1163
|
-
return "HttpError";
|
|
1164
|
-
}
|
|
1165
|
-
};
|
|
1166
756
|
|
|
1167
|
-
// src/http-request-headers.
|
|
757
|
+
// src/http-request-headers.ts
|
|
1168
758
|
var HttpRequestHeader = {
|
|
1169
759
|
/**
|
|
1170
760
|
* Content-Types that are acceptable for the response. See Content negotiation. Permanent.
|
|
@@ -1245,26 +835,12 @@ var HttpRequestHeader = {
|
|
|
1245
835
|
CONTENT_TYPE: "content-type",
|
|
1246
836
|
/**
|
|
1247
837
|
* The date and time that the message was sent (in "HTTP-date" format as defined by RFC 7231 Date/Time Formats).
|
|
1248
|
-
* Permanent.
|
|
1249
|
-
*
|
|
1250
|
-
* @example
|
|
1251
|
-
* <code>Date: Tue, 15 Nov 1994 08:12:31 GMT</code>
|
|
1252
|
-
*/
|
|
1253
|
-
DATE: "date",
|
|
1254
|
-
/**
|
|
1255
|
-
* Indicates that particular server behaviors are required by the client. Permanent.
|
|
1256
|
-
*
|
|
1257
|
-
* @example
|
|
1258
|
-
* <code>Expect: 100-continue</code>
|
|
1259
|
-
*/
|
|
1260
|
-
EXPECT: "expect",
|
|
1261
|
-
/**
|
|
1262
|
-
* The email address of the user making the request. Permanent.
|
|
838
|
+
* Permanent.
|
|
1263
839
|
*
|
|
1264
840
|
* @example
|
|
1265
|
-
* <code>
|
|
841
|
+
* <code>Date: Tue, 15 Nov 1994 08:12:31 GMT</code>
|
|
1266
842
|
*/
|
|
1267
|
-
|
|
843
|
+
DATE: "date",
|
|
1268
844
|
/**
|
|
1269
845
|
* The domain name of the server (for virtual hosting), and the TCP port number on which the server is listening. The
|
|
1270
846
|
* port number may be omitted if the port is the standard port for the service requested. Permanent. Mandatory since
|
|
@@ -1380,13 +956,6 @@ var HttpRequestHeader = {
|
|
|
1380
956
|
* <code>Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11</code>
|
|
1381
957
|
*/
|
|
1382
958
|
UPGRADE: "upgrade",
|
|
1383
|
-
/**
|
|
1384
|
-
* Informs the server of proxies through which the request was sent. Permanent.
|
|
1385
|
-
*
|
|
1386
|
-
* @example
|
|
1387
|
-
* <code>Via: 1.0 fred, 1.1 example.com (Apache/1.1)</code>
|
|
1388
|
-
*/
|
|
1389
|
-
VIA: "via",
|
|
1390
959
|
/**
|
|
1391
960
|
* A general warning about possible problems with the entity body. Permanent.
|
|
1392
961
|
*
|
|
@@ -1401,16 +970,6 @@ var HttpRequestHeader = {
|
|
|
1401
970
|
* <code>X-Requested-With: XMLHttpRequest</code>
|
|
1402
971
|
*/
|
|
1403
972
|
X_REQUESTED_WITH: "x-requested-with",
|
|
1404
|
-
/**
|
|
1405
|
-
* Requests a web application to disable their tracking of a user. This is Mozilla's version of the X-Do-Not-Track
|
|
1406
|
-
* header field (since Firefox 4.0 Beta 11). Safari and IE9 also have support for this field. On March 7, 2011, a
|
|
1407
|
-
* draft proposal was submitted to IETF. The W3C Tracking Protection Working Group is producing a specification.
|
|
1408
|
-
*
|
|
1409
|
-
* @example
|
|
1410
|
-
* <code>DNT: 1 (Do Not Track Enabled)</code>
|
|
1411
|
-
* <code>DNT: 0 (Do Not Track Disabled)</code>
|
|
1412
|
-
*/
|
|
1413
|
-
DNT: "dnt",
|
|
1414
973
|
/**
|
|
1415
974
|
* A de facto standard for identifying the originating IP address of a client connecting to a web server through an
|
|
1416
975
|
* HTTP proxy or load balancer.
|
|
@@ -1438,40 +997,281 @@ var HttpRequestHeader = {
|
|
|
1438
997
|
* @example
|
|
1439
998
|
* <code>X-Forwarded-Proto: https</code>
|
|
1440
999
|
*/
|
|
1441
|
-
X_FORWARDED_PROTO: "x-forwarded-proto"
|
|
1000
|
+
X_FORWARDED_PROTO: "x-forwarded-proto"
|
|
1001
|
+
};
|
|
1002
|
+
|
|
1003
|
+
// src/http-request-methods.ts
|
|
1004
|
+
var HttpRequestMethod = {
|
|
1442
1005
|
/**
|
|
1443
|
-
*
|
|
1006
|
+
* The OPTIONS method represents a request for information about the communication options available on the
|
|
1007
|
+
* request/response chain identified by the Request-URI. This method allows the client to determine the options and/or
|
|
1008
|
+
* requirements associated with a resource, or the capabilities of a server, without implying a resource action or
|
|
1009
|
+
* initiating a resource retrieval.
|
|
1444
1010
|
*
|
|
1445
|
-
*
|
|
1446
|
-
*
|
|
1011
|
+
* Responses to this method are not cacheable.
|
|
1012
|
+
*
|
|
1013
|
+
* If the OPTIONS request includes an entity-body (as indicated by the presence of Content-Length or
|
|
1014
|
+
* Transfer-Encoding), then the media type MUST be indicated by a Content-Type field. Although this specification does
|
|
1015
|
+
* not define any use for such a body, future extensions to HTTP might use the OPTIONS body to make more detailed
|
|
1016
|
+
* queries on the server. A server that does not support such an extension MAY discard the request body.
|
|
1017
|
+
*
|
|
1018
|
+
* If the Request-URI is an asterisk ("*"), the OPTIONS request is intended to apply to the server in general rather
|
|
1019
|
+
* than to a specific resource. Since a server's communication options typically depend on the resource, the "*"
|
|
1020
|
+
* request is only useful as a "ping" or "no-op" type of method, it does nothing beyond allowing the client to test the
|
|
1021
|
+
* capabilities of the server. For example, this can be used to test a proxy for HTTP/1.1 compliance (or lack thereof).
|
|
1022
|
+
*
|
|
1023
|
+
* If the Request-URI is not an asterisk, the OPTIONS request applies only to the options that are available when
|
|
1024
|
+
* communicating with that resource.
|
|
1025
|
+
*
|
|
1026
|
+
* A 200 response SHOULD include any header fields that indicate optional features implemented by the server and
|
|
1027
|
+
* applicable to that resource (e.g., Allow), possibly including extensions not defined by this specification. The
|
|
1028
|
+
* response body, if any, SHOULD also include information about the communication options. The format for such a body
|
|
1029
|
+
* is not defined by this specification, but might be defined by future extensions to HTTP. Content negotiation MAY be
|
|
1030
|
+
* used to select the appropriate response format. If no response body is included, the response MUST include a
|
|
1031
|
+
* Content-Length field with a field-value of "0".
|
|
1032
|
+
*
|
|
1033
|
+
* The Max-Forwards request-header field MAY be used to target a specific proxy in the request chain. When a proxy
|
|
1034
|
+
* receives an OPTIONS request on an absoluteURI for which request forwarding is permitted, the proxy MUST check for a
|
|
1035
|
+
* Max-Forwards field. If the Max-Forwards field-value is zero ("0"), the proxy MUST NOT forward the message, instead,
|
|
1036
|
+
* the proxy SHOULD respond with its own communication options. If the Max-Forwards field-value is an integer greater
|
|
1037
|
+
* than zero, the proxy MUST decrement the field-value when it forwards the request. If no Max-Forwards field is
|
|
1038
|
+
* present in the request, then the forwarded request MUST NOT include a Max-Forwards field.
|
|
1039
|
+
*/
|
|
1040
|
+
OPTIONS: "OPTIONS",
|
|
1041
|
+
/**
|
|
1042
|
+
* The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI. If
|
|
1043
|
+
* the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity in
|
|
1044
|
+
* the response and not the source text of the process, unless that text happens to be the output of the process.
|
|
1045
|
+
*
|
|
1046
|
+
* The semantics of the GET method change to a "conditional GET" if the request message includes an If-Modified-Since;
|
|
1047
|
+
* If-Unmodified-Since, If-Match, If-None-Match, or If-Range header field. A conditional GET method requests that the
|
|
1048
|
+
* entity be transferred only under the circumstances described by the conditional header field(s). The conditional GET
|
|
1049
|
+
* method is intended to reduce unnecessary network usage by allowing cached entities to be refreshed without requiring
|
|
1050
|
+
* multiple requests or transferring data already held by the client.
|
|
1051
|
+
*
|
|
1052
|
+
* The semantics of the GET method change to a "partial GET" if the request message includes a Range header field. A
|
|
1053
|
+
* partial GET requests that only part of the entity be transferred, as described in section 14.35. The partial GET
|
|
1054
|
+
* method is intended to reduce unnecessary network usage by allowing partially-retrieved entities to be completed
|
|
1055
|
+
* without transferring data already held by the client.
|
|
1056
|
+
*
|
|
1057
|
+
* The response to a GET request is cacheable if and only if it meets the requirements for HTTP caching described in
|
|
1058
|
+
* section 13.
|
|
1059
|
+
*
|
|
1060
|
+
* See section 15.1.3 for security considerations when used for forms.
|
|
1061
|
+
*/
|
|
1062
|
+
GET: "GET",
|
|
1063
|
+
/**
|
|
1064
|
+
* The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response. The
|
|
1065
|
+
* meta information contained in the HTTP headers in response to a HEAD request SHOULD be identical to the information
|
|
1066
|
+
* sent in response to a GET request. This method can be used for obtaining meta information about the entity implied by
|
|
1067
|
+
* the request without transferring the entity-body itself. This method is often used for testing hypertext links for
|
|
1068
|
+
* validity, accessibility, and recent modification.
|
|
1069
|
+
*
|
|
1070
|
+
* The response to a HEAD request MAY be cacheable in the sense that the information contained in the response MAY be
|
|
1071
|
+
* used to update a previously cached entity from that resource. If the new field values indicate that the cached
|
|
1072
|
+
* entity differs from the current entity (as would be indicated by a change in Content-Length, Content-MD5, ETag or
|
|
1073
|
+
* Last-Modified), then the cache MUST treat the cache entry as stale.
|
|
1074
|
+
*/
|
|
1075
|
+
HEAD: "HEAD",
|
|
1076
|
+
/**
|
|
1077
|
+
* The POST method is used to request that the origin server accept the entity enclosed in the request as a new
|
|
1078
|
+
* subordinate of the resource identified by the Request-URI in the Request-Line. POST is designed to allow a uniform
|
|
1079
|
+
* method to cover the following functions:
|
|
1080
|
+
* <ul>
|
|
1081
|
+
* <li>Annotation of existing resources,</li>
|
|
1082
|
+
* <li>Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles,</li>
|
|
1083
|
+
* <li>Providing a block of data, such as the result of submitting a form, to a data-handling process,</li>
|
|
1084
|
+
* <li>Extending a database through an append operation.</li>
|
|
1085
|
+
* </ul>
|
|
1086
|
+
*
|
|
1087
|
+
* The actual function performed by the POST method is determined by the server and is usually dependent on the
|
|
1088
|
+
* Request-URI. The posted entity is subordinate to that URI in the same way that a file is subordinate to a directory
|
|
1089
|
+
* containing it, a news article is subordinate to a newsgroup to which it is posted, or a record is subordinate to a
|
|
1090
|
+
* database.
|
|
1091
|
+
*
|
|
1092
|
+
* The action performed by the POST method might not result in a resource that can be identified by a URI. In this
|
|
1093
|
+
* case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the
|
|
1094
|
+
* response includes an entity that describes the result.
|
|
1095
|
+
*
|
|
1096
|
+
* If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity
|
|
1097
|
+
* which describes the status of the request and refers to the new resource, and a Location header (see section 14.30).
|
|
1098
|
+
*
|
|
1099
|
+
* Responses to this method are not cacheable, unless the response includes appropriate Cache-Control or Expires header
|
|
1100
|
+
* fields. However, the 303 (See Other) response can be used to direct the user agent to retrieve a cacheable resource.
|
|
1101
|
+
*
|
|
1102
|
+
* POST requests MUST obey the message transmission requirements set out in section 8.2.
|
|
1103
|
+
*
|
|
1104
|
+
* See section 15.1.3 for security considerations.
|
|
1105
|
+
*/
|
|
1106
|
+
POST: "POST",
|
|
1107
|
+
/**
|
|
1108
|
+
* The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers
|
|
1109
|
+
* to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing
|
|
1110
|
+
* on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being
|
|
1111
|
+
* defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. If
|
|
1112
|
+
* a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an
|
|
1113
|
+
* existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate
|
|
1114
|
+
* successful completion of the request. If the resource could not be created or modified with the Request-URI, an
|
|
1115
|
+
* appropriate error response SHOULD be given that reflects the nature of the problem. The recipient of the entity MUST
|
|
1116
|
+
* \NOT ignore any Content-* (e.g. Content-Range) headers that it does not understand or implement and MUST return a
|
|
1117
|
+
* 501 (Not Implemented) response in such cases.
|
|
1118
|
+
*
|
|
1119
|
+
* If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those
|
|
1120
|
+
* entries SHOULD be treated as stale. Responses to this method are not cacheable.
|
|
1121
|
+
*
|
|
1122
|
+
* The fundamental difference between the POST and PUT requests is reflected in the different meaning of the
|
|
1123
|
+
* Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource
|
|
1124
|
+
* might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations.
|
|
1125
|
+
* In contrast, the URI in a PUT request identifies the entity enclosed with the request -- the user agent knows what
|
|
1126
|
+
* URI is intended and the server MUST NOT attempt to apply the request to some other resource. If the server desires
|
|
1127
|
+
* that the request be applied to a different URI, it MUST send a 301 (Moved Permanently) response, the user agent MAY
|
|
1128
|
+
* then make its own decision regarding whether or not to redirect the request.
|
|
1129
|
+
*
|
|
1130
|
+
* A single resource MAY be identified by many different URIs. For example, an article might have a URI for identifying
|
|
1131
|
+
* "the current version" which is separate from the URI identifying each particular version. In this case, a PUT
|
|
1132
|
+
* request on a general URI might result in several other URIs being defined by the origin server.
|
|
1133
|
+
*
|
|
1134
|
+
* HTTP/1.1 does not define how a PUT method affects the state of an origin server.
|
|
1135
|
+
*
|
|
1136
|
+
* PUT requests MUST obey the message transmission requirements set out in section 8.2.
|
|
1137
|
+
*
|
|
1138
|
+
* Unless otherwise specified for a particular entity-header, the entity-headers in the PUT request SHOULD be applied
|
|
1139
|
+
* to the resource created or modified by the PUT.
|
|
1140
|
+
*/
|
|
1141
|
+
PUT: "PUT",
|
|
1142
|
+
/**
|
|
1143
|
+
* The DELETE method requests that the origin server delete the resource identified by the Request-URI. This method MAY
|
|
1144
|
+
* be overridden by human intervention (or other means) on the origin server. The client cannot be guaranteed that the
|
|
1145
|
+
* operation has been carried out, even if the status code returned from the origin server indicates that the action
|
|
1146
|
+
* has been completed successfully. However, the server SHOULD NOT indicate success unless, at the time the response
|
|
1147
|
+
* is given, it intends to delete the resource or move it to an inaccessible location.
|
|
1148
|
+
*
|
|
1149
|
+
* A successful response SHOULD be 200 (OK) if the response includes an entity describing the status, 202 (Accepted) if
|
|
1150
|
+
* the action has not yet been enacted, or 204 (No Content) if the action has been enacted but the response does not
|
|
1151
|
+
* include an entity.
|
|
1152
|
+
*
|
|
1153
|
+
* If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those
|
|
1154
|
+
* entries SHOULD be treated as stale. Responses to this method are not cacheable.
|
|
1155
|
+
*/
|
|
1156
|
+
DELETE: "DELETE",
|
|
1157
|
+
/**
|
|
1158
|
+
* The TRACE method is used to invoke a remote, application-layer loop- back of the request message. The final
|
|
1159
|
+
* recipient of the request SHOULD reflect the message received back to the client as the entity-body of a 200 (OK)
|
|
1160
|
+
* response. The final recipient is either the origin server or the first proxy or gateway to receive a Max-Forwards
|
|
1161
|
+
* value of zero (0) in the request (see section 14.31). A TRACE request MUST NOT include an entity.
|
|
1162
|
+
*
|
|
1163
|
+
* TRACE allows the client to see what is being received at the other end of the request chain and use that data for
|
|
1164
|
+
* testing or diagnostic information. The value of the Via header field (section 14.45) is of particular interest,
|
|
1165
|
+
* since it acts as a trace of the request chain. Use of the Max-Forwards header field allows the client to limit the
|
|
1166
|
+
* length of the request chain, which is useful for testing a chain of proxies forwarding messages in an infinite loop.
|
|
1167
|
+
*
|
|
1168
|
+
* If the request is valid, the response SHOULD contain the entire request message in the entity-body, with a
|
|
1169
|
+
* Content-Type of "message/http". Responses to this method MUST NOT be cached.
|
|
1170
|
+
*/
|
|
1171
|
+
TRACE: "TRACE",
|
|
1172
|
+
/**
|
|
1173
|
+
* This specification reserves the method name CONNECT for use with a proxy that can dynamically switch to being a
|
|
1174
|
+
* tunnel (e.g. SSL tunneling [44]).
|
|
1447
1175
|
*/
|
|
1448
|
-
|
|
1176
|
+
CONNECT: "CONNECT",
|
|
1449
1177
|
/**
|
|
1450
|
-
*
|
|
1451
|
-
*
|
|
1452
|
-
*
|
|
1453
|
-
*
|
|
1178
|
+
* The PATCH method requests that a set of changes described in the
|
|
1179
|
+
* request entity be applied to the resource identified by the Request-
|
|
1180
|
+
* URI. The set of changes is represented in a format called a "patch
|
|
1181
|
+
* document" identified by a media type. If the Request-URI does not
|
|
1182
|
+
* point to an existing resource, the server MAY create a new resource,
|
|
1183
|
+
* depending on the patch document type (whether it can logically modify
|
|
1184
|
+
* a null resource) and permissions, etc.
|
|
1185
|
+
*
|
|
1186
|
+
* The difference between the PUT and PATCH requests is reflected in the
|
|
1187
|
+
* way the server processes the enclosed entity to modify the resource
|
|
1188
|
+
* identified by the Request-URI. In a PUT request, the enclosed entity
|
|
1189
|
+
* is considered to be a modified version of the resource stored on the
|
|
1190
|
+
* origin server, and the client is requesting that the stored version
|
|
1191
|
+
* be replaced. With PATCH, however, the enclosed entity contains a set
|
|
1192
|
+
* of instructions describing how a resource currently residing on the
|
|
1193
|
+
* origin server should be modified to produce a new version. The PATCH
|
|
1194
|
+
* method affects the resource identified by the Request-URI, and it
|
|
1195
|
+
* also MAY have side effects on other resources; i.e., new resources
|
|
1196
|
+
* may be created, or existing ones modified, by the application of a
|
|
1197
|
+
* PATCH.
|
|
1198
|
+
*
|
|
1199
|
+
* PATCH is neither safe nor idempotent as defined by [RFC2616], Section
|
|
1200
|
+
* 9.1.
|
|
1201
|
+
*
|
|
1202
|
+
* A PATCH request can be issued in such a way as to be idempotent,
|
|
1203
|
+
* which also helps prevent bad outcomes from collisions between two
|
|
1204
|
+
* PATCH requests on the same resource in a similar time frame.
|
|
1205
|
+
* Collisions from multiple PATCH requests may be more dangerous than
|
|
1206
|
+
* PUT collisions because some patch formats need to operate from a
|
|
1207
|
+
* known base-point or else they will corrupt the resource. Clients
|
|
1208
|
+
* using this kind of patch application SHOULD use a conditional request
|
|
1209
|
+
* such that the request will fail if the resource has been updated
|
|
1210
|
+
* since the client last accessed the resource. For example, the client
|
|
1211
|
+
* can use a strong ETag [RFC2616] in an If-Match header on the PATCH
|
|
1212
|
+
* request.
|
|
1213
|
+
*
|
|
1214
|
+
* There are also cases where patch formats do not need to operate from
|
|
1215
|
+
* a known base-point (e.g., appending text lines to log files, or non-
|
|
1216
|
+
* colliding rows to database tables), in which case the same care in
|
|
1217
|
+
* client requests is not needed.
|
|
1218
|
+
*
|
|
1219
|
+
* The server MUST apply the entire set of changes atomically and never
|
|
1220
|
+
* provide (e.g., in response to a GET during this operation) a
|
|
1221
|
+
* partially modified representation. If the entire patch document
|
|
1222
|
+
* cannot be successfully applied, then the server MUST NOT apply any of
|
|
1223
|
+
* the changes. The determination of what constitutes a successful
|
|
1224
|
+
* PATCH can vary depending on the patch document and the type of
|
|
1225
|
+
* resource(s) being modified. For example, the common 'diff' utility
|
|
1226
|
+
* can generate a patch document that applies to multiple files in a
|
|
1227
|
+
* directory hierarchy. The atomicity requirement holds for all
|
|
1228
|
+
* directly affected files. See "Error Handling", Section 2.2, for
|
|
1229
|
+
* details on status codes and possible error conditions.
|
|
1230
|
+
*
|
|
1231
|
+
* If the request passes through a cache and the Request-URI identifies
|
|
1232
|
+
* one or more currently cached entities, those entries SHOULD be
|
|
1233
|
+
* treated as stale. A response to this method is only cacheable if it
|
|
1234
|
+
* contains explicit freshness information (such as an Expires header or
|
|
1235
|
+
* "Cache-Control: max-age" directive) as well as the Content-Location
|
|
1236
|
+
* header matching the Request-URI, indicating that the PATCH response
|
|
1237
|
+
* body is a resource representation. A cached PATCH response can only
|
|
1238
|
+
* be used to respond to subsequent GET and HEAD requests; it MUST NOT
|
|
1239
|
+
* be used to respond to other methods (in particular, PATCH).
|
|
1240
|
+
*
|
|
1241
|
+
* Note that entity-headers contained in the request apply only to the
|
|
1242
|
+
* contained patch document and MUST NOT be applied to the resource
|
|
1243
|
+
* being modified. Thus, a Content-Language header could be present on
|
|
1244
|
+
* the request, but it would only mean (for whatever that's worth) that
|
|
1245
|
+
* the patch document had a language. Servers SHOULD NOT store such
|
|
1246
|
+
* headers except as trace information, and SHOULD NOT use such header
|
|
1247
|
+
* values the same way they might be used on PUT requests. Therefore,
|
|
1248
|
+
* this document does not specify a way to modify a document's Content-
|
|
1249
|
+
* Type or Content-Language value through headers, though a mechanism
|
|
1250
|
+
* could well be designed to achieve this goal through a patch document.
|
|
1454
1251
|
*
|
|
1455
|
-
*
|
|
1456
|
-
*
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
*
|
|
1252
|
+
* There is no guarantee that a resource can be modified with PATCH.
|
|
1253
|
+
* Further, it is expected that different patch document formats will be
|
|
1254
|
+
* appropriate for different types of resources and that no single
|
|
1255
|
+
* format will be appropriate for all types of resources. Therefore,
|
|
1256
|
+
* there is no single default patch document format that implementations
|
|
1257
|
+
* are required to support. Servers MUST ensure that a received patch
|
|
1258
|
+
* document is appropriate for the type of resource identified by the
|
|
1259
|
+
* Request-URI.
|
|
1461
1260
|
*
|
|
1462
|
-
*
|
|
1463
|
-
*
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
*
|
|
1468
|
-
*
|
|
1261
|
+
* Clients need to choose when to use PATCH rather than PUT. For
|
|
1262
|
+
* example, if the patch document size is larger than the size of the
|
|
1263
|
+
* new resource data that would be used in a PUT, then it might make
|
|
1264
|
+
* sense to use PUT instead of PATCH. A comparison to POST is even more
|
|
1265
|
+
* difficult, because POST is used in widely varying ways and can
|
|
1266
|
+
* encompass PUT and PATCH-like operations if the server chooses. If
|
|
1267
|
+
* the operation does not modify the resource identified by the Request-
|
|
1268
|
+
* URI in a predictable way, POST should be considered instead of PATCH
|
|
1269
|
+
* or PUT.
|
|
1469
1270
|
*/
|
|
1470
|
-
|
|
1271
|
+
PATCH: "PATCH"
|
|
1471
1272
|
};
|
|
1472
|
-
var http_request_headers_default = HttpRequestHeader;
|
|
1473
1273
|
|
|
1474
|
-
// src/http-response-headers.
|
|
1274
|
+
// src/http-response-headers.ts
|
|
1475
1275
|
var HttpResponseHeader = {
|
|
1476
1276
|
/**
|
|
1477
1277
|
* Implemented as a misunderstanding of the HTTP specifications. Common because of mistakes in implementations of early HTTP versions. Has exactly the same functionality as standard Connection field.
|
|
@@ -1814,325 +1614,1463 @@ var HttpResponseHeader = {
|
|
|
1814
1614
|
*/
|
|
1815
1615
|
X_POWERED_BY: "x-powered-by"
|
|
1816
1616
|
};
|
|
1817
|
-
var http_response_headers_default = HttpResponseHeader;
|
|
1818
1617
|
|
|
1819
|
-
// src/
|
|
1820
|
-
var
|
|
1618
|
+
// src/response-status.ts
|
|
1619
|
+
var ResponseStatus = class {
|
|
1620
|
+
_code;
|
|
1621
|
+
_text;
|
|
1821
1622
|
/**
|
|
1822
|
-
*
|
|
1823
|
-
* @
|
|
1623
|
+
*
|
|
1624
|
+
* @param code The status code from the {@link Response}
|
|
1625
|
+
* @param text The status text from the {@link Response}
|
|
1824
1626
|
*/
|
|
1825
|
-
constructor(
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
this.append(key, value);
|
|
1829
|
-
}
|
|
1627
|
+
constructor(code, text2) {
|
|
1628
|
+
this._code = code;
|
|
1629
|
+
this._text = text2;
|
|
1830
1630
|
}
|
|
1831
1631
|
/**
|
|
1832
|
-
*
|
|
1833
|
-
* If an element with the same key already exists, the value will be replaced in the underlying {@link Set}.
|
|
1632
|
+
* Returns the status code from the {@link Response}
|
|
1834
1633
|
*
|
|
1835
|
-
* @
|
|
1836
|
-
* @param {string} key The key to set.
|
|
1837
|
-
* @param {*} value The value to add to the ParameterMap
|
|
1838
|
-
* @returns {ParameterMap<string, *>} The ParameterMap with the updated key and value.
|
|
1634
|
+
* @returns The status code.
|
|
1839
1635
|
*/
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1636
|
+
get code() {
|
|
1637
|
+
return this._code;
|
|
1638
|
+
}
|
|
1639
|
+
/**
|
|
1640
|
+
* Returns the status text from the {@link Response}.
|
|
1641
|
+
*
|
|
1642
|
+
* @returns The status text.
|
|
1643
|
+
*/
|
|
1644
|
+
get text() {
|
|
1645
|
+
return this._text;
|
|
1646
|
+
}
|
|
1647
|
+
/**
|
|
1648
|
+
* A String value that is used in the creation of the default string
|
|
1649
|
+
* description of an object. Called by the built-in method {@link Object.prototype.toString}.
|
|
1650
|
+
*
|
|
1651
|
+
* @returns The default string description of this object.
|
|
1652
|
+
*/
|
|
1653
|
+
get [Symbol.toStringTag]() {
|
|
1654
|
+
return "ResponseStatus";
|
|
1849
1655
|
}
|
|
1850
1656
|
/**
|
|
1851
|
-
*
|
|
1852
|
-
* If a key already exists, the value will be replaced in the underlying {@link Array}.
|
|
1657
|
+
* tostring method for the class.
|
|
1853
1658
|
*
|
|
1854
|
-
* @
|
|
1855
|
-
* @returns
|
|
1659
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString|Object.prototype.toString}
|
|
1660
|
+
* @returns The status code and status text.
|
|
1661
|
+
*/
|
|
1662
|
+
toString() {
|
|
1663
|
+
return `${this._code} ${this._text}`;
|
|
1664
|
+
}
|
|
1665
|
+
};
|
|
1666
|
+
|
|
1667
|
+
// src/constants.ts
|
|
1668
|
+
var charset = { charset: "utf-8" };
|
|
1669
|
+
var endsWithSlashRegEx = /\/$/;
|
|
1670
|
+
var XSRF_COOKIE_NAME = "XSRF-TOKEN";
|
|
1671
|
+
var XSRF_HEADER_NAME = "X-XSRF-TOKEN";
|
|
1672
|
+
var mediaTypes = {
|
|
1673
|
+
PNG: new MediaType(HttpMediaType.PNG),
|
|
1674
|
+
TEXT: new MediaType(HttpMediaType.TEXT, charset),
|
|
1675
|
+
JSON: new MediaType(HttpMediaType.JSON, charset),
|
|
1676
|
+
HTML: new MediaType(HttpMediaType.HTML, charset),
|
|
1677
|
+
JAVA_SCRIPT: new MediaType(HttpMediaType.JAVA_SCRIPT, charset),
|
|
1678
|
+
CSS: new MediaType(HttpMediaType.CSS, charset),
|
|
1679
|
+
XML: new MediaType(HttpMediaType.XML, charset),
|
|
1680
|
+
BIN: new MediaType(HttpMediaType.BIN)
|
|
1681
|
+
};
|
|
1682
|
+
var defaultMediaType = mediaTypes.JSON.toString();
|
|
1683
|
+
var RequestCachingPolicy = {
|
|
1684
|
+
DEFAULT: "default",
|
|
1685
|
+
FORCE_CACHE: "force-cache",
|
|
1686
|
+
NO_CACHE: "no-cache",
|
|
1687
|
+
NO_STORE: "no-store",
|
|
1688
|
+
ONLY_IF_CACHED: "only-if-cached",
|
|
1689
|
+
RELOAD: "reload"
|
|
1690
|
+
};
|
|
1691
|
+
var RequestEvent = {
|
|
1692
|
+
CONFIGURED: "configured",
|
|
1693
|
+
SUCCESS: "success",
|
|
1694
|
+
ERROR: "error",
|
|
1695
|
+
ABORTED: "aborted",
|
|
1696
|
+
TIMEOUT: "timeout",
|
|
1697
|
+
RETRY: "retry",
|
|
1698
|
+
COMPLETE: "complete",
|
|
1699
|
+
ALL_COMPLETE: "all-complete"
|
|
1700
|
+
};
|
|
1701
|
+
var SignalEvents = {
|
|
1702
|
+
ABORT: "abort",
|
|
1703
|
+
TIMEOUT: "timeout"
|
|
1704
|
+
};
|
|
1705
|
+
var SignalErrors = {
|
|
1706
|
+
ABORT: "AbortError",
|
|
1707
|
+
TIMEOUT: "TimeoutError"
|
|
1708
|
+
};
|
|
1709
|
+
var eventListenerOptions = { once: true, passive: true };
|
|
1710
|
+
var abortEvent = () => new CustomEvent(SignalEvents.ABORT, { detail: { cause: SignalErrors.ABORT } });
|
|
1711
|
+
var timeoutEvent = () => new CustomEvent(SignalEvents.TIMEOUT, { detail: { cause: SignalErrors.TIMEOUT } });
|
|
1712
|
+
var requestBodyMethods = [HttpRequestMethod.POST, HttpRequestMethod.PUT, HttpRequestMethod.PATCH, HttpRequestMethod.DELETE];
|
|
1713
|
+
var internalServerError = new ResponseStatus(500, "Internal Server Error");
|
|
1714
|
+
var aborted = new ResponseStatus(499, "Aborted");
|
|
1715
|
+
var timedOut = new ResponseStatus(504, "Request Timeout");
|
|
1716
|
+
var retryStatusCodes = [408, 413, 429, 500, 502, 503, 504];
|
|
1717
|
+
var retryMethods = [HttpRequestMethod.GET, HttpRequestMethod.PUT, HttpRequestMethod.HEAD, HttpRequestMethod.DELETE, HttpRequestMethod.OPTIONS];
|
|
1718
|
+
var retryDelay = 300;
|
|
1719
|
+
var retryBackoffFactor = 2;
|
|
1720
|
+
|
|
1721
|
+
// src/signal-controller.ts
|
|
1722
|
+
var SignalController = class {
|
|
1723
|
+
abortSignal;
|
|
1724
|
+
abortController = new AbortController();
|
|
1725
|
+
events = /* @__PURE__ */ new Map();
|
|
1726
|
+
/**
|
|
1727
|
+
* Creates a new SignalController instance.
|
|
1728
|
+
* @param options - The options for the SignalController.
|
|
1729
|
+
* @param options.signal - The signal to listen for abort events. Defaults to the internal abort signal.
|
|
1730
|
+
* @param options.timeout - The timeout value in milliseconds. Defaults to Infinity.
|
|
1731
|
+
* @throws {RangeError} If the timeout value is negative.
|
|
1732
|
+
*/
|
|
1733
|
+
constructor({ signal, timeout = Infinity } = {}) {
|
|
1734
|
+
if (timeout < 0) {
|
|
1735
|
+
throw new RangeError("The timeout cannot be negative");
|
|
1736
|
+
}
|
|
1737
|
+
const signals = [this.abortController.signal];
|
|
1738
|
+
if (signal != null) {
|
|
1739
|
+
signals.push(signal);
|
|
1740
|
+
}
|
|
1741
|
+
if (timeout !== Infinity) {
|
|
1742
|
+
signals.push(AbortSignal.timeout(timeout));
|
|
1743
|
+
}
|
|
1744
|
+
(this.abortSignal = AbortSignal.any(signals)).addEventListener(SignalEvents.ABORT, this, eventListenerOptions);
|
|
1745
|
+
}
|
|
1746
|
+
/**
|
|
1747
|
+
* Handles the 'abort' event. If the event is caused by a timeout, the 'timeout' event is dispatched.
|
|
1748
|
+
* Guards against a timeout firing after a manual abort to prevent spurious timeout events.
|
|
1749
|
+
* @param event The event to abort with
|
|
1750
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#specifying_this_using_bind
|
|
1856
1751
|
*/
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1752
|
+
handleEvent({ target: { reason } }) {
|
|
1753
|
+
if (this.abortController.signal.aborted) {
|
|
1754
|
+
return;
|
|
1860
1755
|
}
|
|
1861
|
-
|
|
1756
|
+
if (reason instanceof DOMException && reason.name === SignalErrors.TIMEOUT) {
|
|
1757
|
+
this.abortSignal.dispatchEvent(timeoutEvent());
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
/**
|
|
1761
|
+
* Gets the signal. This signal will be able to abort the request, but will not be notified if the request is aborted by the timeout.
|
|
1762
|
+
* @returns The signal
|
|
1763
|
+
*/
|
|
1764
|
+
get signal() {
|
|
1765
|
+
return this.abortSignal;
|
|
1766
|
+
}
|
|
1767
|
+
/**
|
|
1768
|
+
* Adds an event listener for the 'abort' event.
|
|
1769
|
+
*
|
|
1770
|
+
* @param eventListener The listener to add
|
|
1771
|
+
* @returns The SignalController
|
|
1772
|
+
*/
|
|
1773
|
+
onAbort(eventListener) {
|
|
1774
|
+
return this.addEventListener(SignalEvents.ABORT, eventListener);
|
|
1775
|
+
}
|
|
1776
|
+
/**
|
|
1777
|
+
* Adds an event listener for the 'timeout' event.
|
|
1778
|
+
*
|
|
1779
|
+
* @param eventListener The listener to add
|
|
1780
|
+
* @returns The SignalController
|
|
1781
|
+
*/
|
|
1782
|
+
onTimeout(eventListener) {
|
|
1783
|
+
return this.addEventListener(SignalEvents.TIMEOUT, eventListener);
|
|
1784
|
+
}
|
|
1785
|
+
/**
|
|
1786
|
+
* Aborts the signal.
|
|
1787
|
+
*
|
|
1788
|
+
* @param event The event to abort with
|
|
1789
|
+
*/
|
|
1790
|
+
abort(event = abortEvent()) {
|
|
1791
|
+
this.abortController.abort(event.detail?.cause);
|
|
1862
1792
|
}
|
|
1863
1793
|
/**
|
|
1864
|
-
*
|
|
1865
|
-
* If the key has multiple values, the first value will be returned.
|
|
1866
|
-
* If the key has no values, undefined will be returned.
|
|
1794
|
+
* Removes all event listeners from the signal.
|
|
1867
1795
|
*
|
|
1868
|
-
* @
|
|
1869
|
-
* @param {string} key The key to get.
|
|
1870
|
-
* @returns {*} The value associated to the key, or undefined if there is none.
|
|
1796
|
+
* @returns The SignalController
|
|
1871
1797
|
*/
|
|
1872
|
-
|
|
1873
|
-
|
|
1798
|
+
destroy() {
|
|
1799
|
+
this.abortSignal.removeEventListener(SignalEvents.ABORT, this, eventListenerOptions);
|
|
1800
|
+
for (const [eventListener, type] of this.events) {
|
|
1801
|
+
this.abortSignal.removeEventListener(type, eventListener, eventListenerOptions);
|
|
1802
|
+
}
|
|
1803
|
+
this.events.clear();
|
|
1804
|
+
return this;
|
|
1874
1805
|
}
|
|
1875
1806
|
/**
|
|
1876
|
-
*
|
|
1807
|
+
* Adds an event listener for the specified event type.
|
|
1877
1808
|
*
|
|
1878
|
-
* @param
|
|
1879
|
-
* @
|
|
1809
|
+
* @param type The event type to listen for
|
|
1810
|
+
* @param eventListener The listener to add
|
|
1811
|
+
* @returns The SignalController
|
|
1880
1812
|
*/
|
|
1881
|
-
|
|
1882
|
-
|
|
1813
|
+
addEventListener(type, eventListener) {
|
|
1814
|
+
this.abortSignal.addEventListener(type, eventListener, eventListenerOptions);
|
|
1815
|
+
this.events.set(eventListener, type);
|
|
1816
|
+
return this;
|
|
1883
1817
|
}
|
|
1884
1818
|
/**
|
|
1885
|
-
*
|
|
1819
|
+
* A String value that is used in the creation of the default string
|
|
1820
|
+
* description of an object. Called by the built-in method {@link Object.prototype.toString}.
|
|
1886
1821
|
*
|
|
1887
|
-
* @
|
|
1888
|
-
* @param {*} value The value to append.
|
|
1889
|
-
* @returns {ParameterMap<string, *>} The ParameterMap with the updated key and value to allow chaining.
|
|
1822
|
+
* @returns The default string description of this object.
|
|
1890
1823
|
*/
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1824
|
+
get [Symbol.toStringTag]() {
|
|
1825
|
+
return "SignalController";
|
|
1826
|
+
}
|
|
1827
|
+
};
|
|
1828
|
+
|
|
1829
|
+
// node_modules/.pnpm/dompurify@3.3.3/node_modules/dompurify/dist/purify.es.mjs
|
|
1830
|
+
var {
|
|
1831
|
+
entries,
|
|
1832
|
+
setPrototypeOf,
|
|
1833
|
+
isFrozen,
|
|
1834
|
+
getPrototypeOf,
|
|
1835
|
+
getOwnPropertyDescriptor
|
|
1836
|
+
} = Object;
|
|
1837
|
+
var {
|
|
1838
|
+
freeze,
|
|
1839
|
+
seal,
|
|
1840
|
+
create
|
|
1841
|
+
} = Object;
|
|
1842
|
+
var {
|
|
1843
|
+
apply,
|
|
1844
|
+
construct
|
|
1845
|
+
} = typeof Reflect !== "undefined" && Reflect;
|
|
1846
|
+
if (!freeze) {
|
|
1847
|
+
freeze = function freeze2(x) {
|
|
1848
|
+
return x;
|
|
1849
|
+
};
|
|
1850
|
+
}
|
|
1851
|
+
if (!seal) {
|
|
1852
|
+
seal = function seal2(x) {
|
|
1853
|
+
return x;
|
|
1854
|
+
};
|
|
1855
|
+
}
|
|
1856
|
+
if (!apply) {
|
|
1857
|
+
apply = function apply2(func, thisArg) {
|
|
1858
|
+
for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
|
|
1859
|
+
args[_key - 2] = arguments[_key];
|
|
1860
|
+
}
|
|
1861
|
+
return func.apply(thisArg, args);
|
|
1862
|
+
};
|
|
1863
|
+
}
|
|
1864
|
+
if (!construct) {
|
|
1865
|
+
construct = function construct2(Func) {
|
|
1866
|
+
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
|
|
1867
|
+
args[_key2 - 1] = arguments[_key2];
|
|
1868
|
+
}
|
|
1869
|
+
return new Func(...args);
|
|
1870
|
+
};
|
|
1871
|
+
}
|
|
1872
|
+
var arrayForEach = unapply(Array.prototype.forEach);
|
|
1873
|
+
var arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);
|
|
1874
|
+
var arrayPop = unapply(Array.prototype.pop);
|
|
1875
|
+
var arrayPush = unapply(Array.prototype.push);
|
|
1876
|
+
var arraySplice = unapply(Array.prototype.splice);
|
|
1877
|
+
var stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
1878
|
+
var stringToString = unapply(String.prototype.toString);
|
|
1879
|
+
var stringMatch = unapply(String.prototype.match);
|
|
1880
|
+
var stringReplace = unapply(String.prototype.replace);
|
|
1881
|
+
var stringIndexOf = unapply(String.prototype.indexOf);
|
|
1882
|
+
var stringTrim = unapply(String.prototype.trim);
|
|
1883
|
+
var objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
|
|
1884
|
+
var regExpTest = unapply(RegExp.prototype.test);
|
|
1885
|
+
var typeErrorCreate = unconstruct(TypeError);
|
|
1886
|
+
function unapply(func) {
|
|
1887
|
+
return function(thisArg) {
|
|
1888
|
+
if (thisArg instanceof RegExp) {
|
|
1889
|
+
thisArg.lastIndex = 0;
|
|
1890
|
+
}
|
|
1891
|
+
for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
|
|
1892
|
+
args[_key3 - 1] = arguments[_key3];
|
|
1893
|
+
}
|
|
1894
|
+
return apply(func, thisArg, args);
|
|
1895
|
+
};
|
|
1896
|
+
}
|
|
1897
|
+
function unconstruct(Func) {
|
|
1898
|
+
return function() {
|
|
1899
|
+
for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
|
|
1900
|
+
args[_key4] = arguments[_key4];
|
|
1901
|
+
}
|
|
1902
|
+
return construct(Func, args);
|
|
1903
|
+
};
|
|
1904
|
+
}
|
|
1905
|
+
function addToSet(set, array) {
|
|
1906
|
+
let transformCaseFunc = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : stringToLowerCase;
|
|
1907
|
+
if (setPrototypeOf) {
|
|
1908
|
+
setPrototypeOf(set, null);
|
|
1909
|
+
}
|
|
1910
|
+
let l = array.length;
|
|
1911
|
+
while (l--) {
|
|
1912
|
+
let element = array[l];
|
|
1913
|
+
if (typeof element === "string") {
|
|
1914
|
+
const lcElement = transformCaseFunc(element);
|
|
1915
|
+
if (lcElement !== element) {
|
|
1916
|
+
if (!isFrozen(array)) {
|
|
1917
|
+
array[l] = lcElement;
|
|
1918
|
+
}
|
|
1919
|
+
element = lcElement;
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
set[element] = true;
|
|
1923
|
+
}
|
|
1924
|
+
return set;
|
|
1925
|
+
}
|
|
1926
|
+
function cleanArray(array) {
|
|
1927
|
+
for (let index = 0; index < array.length; index++) {
|
|
1928
|
+
const isPropertyExist = objectHasOwnProperty(array, index);
|
|
1929
|
+
if (!isPropertyExist) {
|
|
1930
|
+
array[index] = null;
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
return array;
|
|
1934
|
+
}
|
|
1935
|
+
function clone(object) {
|
|
1936
|
+
const newObject = create(null);
|
|
1937
|
+
for (const [property, value] of entries(object)) {
|
|
1938
|
+
const isPropertyExist = objectHasOwnProperty(object, property);
|
|
1939
|
+
if (isPropertyExist) {
|
|
1940
|
+
if (Array.isArray(value)) {
|
|
1941
|
+
newObject[property] = cleanArray(value);
|
|
1942
|
+
} else if (value && typeof value === "object" && value.constructor === Object) {
|
|
1943
|
+
newObject[property] = clone(value);
|
|
1944
|
+
} else {
|
|
1945
|
+
newObject[property] = value;
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
return newObject;
|
|
1950
|
+
}
|
|
1951
|
+
function lookupGetter(object, prop) {
|
|
1952
|
+
while (object !== null) {
|
|
1953
|
+
const desc = getOwnPropertyDescriptor(object, prop);
|
|
1954
|
+
if (desc) {
|
|
1955
|
+
if (desc.get) {
|
|
1956
|
+
return unapply(desc.get);
|
|
1957
|
+
}
|
|
1958
|
+
if (typeof desc.value === "function") {
|
|
1959
|
+
return unapply(desc.value);
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
object = getPrototypeOf(object);
|
|
1963
|
+
}
|
|
1964
|
+
function fallbackValue() {
|
|
1965
|
+
return null;
|
|
1966
|
+
}
|
|
1967
|
+
return fallbackValue;
|
|
1968
|
+
}
|
|
1969
|
+
var html$1 = freeze(["a", "abbr", "acronym", "address", "area", "article", "aside", "audio", "b", "bdi", "bdo", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "content", "data", "datalist", "dd", "decorator", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt", "element", "em", "fieldset", "figcaption", "figure", "font", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "img", "input", "ins", "kbd", "label", "legend", "li", "main", "map", "mark", "marquee", "menu", "menuitem", "meter", "nav", "nobr", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "search", "section", "select", "shadow", "slot", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "tr", "track", "tt", "u", "ul", "var", "video", "wbr"]);
|
|
1970
|
+
var svg$1 = freeze(["svg", "a", "altglyph", "altglyphdef", "altglyphitem", "animatecolor", "animatemotion", "animatetransform", "circle", "clippath", "defs", "desc", "ellipse", "enterkeyhint", "exportparts", "filter", "font", "g", "glyph", "glyphref", "hkern", "image", "inputmode", "line", "lineargradient", "marker", "mask", "metadata", "mpath", "part", "path", "pattern", "polygon", "polyline", "radialgradient", "rect", "stop", "style", "switch", "symbol", "text", "textpath", "title", "tref", "tspan", "view", "vkern"]);
|
|
1971
|
+
var svgFilters = freeze(["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence"]);
|
|
1972
|
+
var svgDisallowed = freeze(["animate", "color-profile", "cursor", "discard", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignobject", "hatch", "hatchpath", "mesh", "meshgradient", "meshpatch", "meshrow", "missing-glyph", "script", "set", "solidcolor", "unknown", "use"]);
|
|
1973
|
+
var mathMl$1 = freeze(["math", "menclose", "merror", "mfenced", "mfrac", "mglyph", "mi", "mlabeledtr", "mmultiscripts", "mn", "mo", "mover", "mpadded", "mphantom", "mroot", "mrow", "ms", "mspace", "msqrt", "mstyle", "msub", "msup", "msubsup", "mtable", "mtd", "mtext", "mtr", "munder", "munderover", "mprescripts"]);
|
|
1974
|
+
var mathMlDisallowed = freeze(["maction", "maligngroup", "malignmark", "mlongdiv", "mscarries", "mscarry", "msgroup", "mstack", "msline", "msrow", "semantics", "annotation", "annotation-xml", "mprescripts", "none"]);
|
|
1975
|
+
var text = freeze(["#text"]);
|
|
1976
|
+
var html = freeze(["accept", "action", "align", "alt", "autocapitalize", "autocomplete", "autopictureinpicture", "autoplay", "background", "bgcolor", "border", "capture", "cellpadding", "cellspacing", "checked", "cite", "class", "clear", "color", "cols", "colspan", "controls", "controlslist", "coords", "crossorigin", "datetime", "decoding", "default", "dir", "disabled", "disablepictureinpicture", "disableremoteplayback", "download", "draggable", "enctype", "enterkeyhint", "exportparts", "face", "for", "headers", "height", "hidden", "high", "href", "hreflang", "id", "inert", "inputmode", "integrity", "ismap", "kind", "label", "lang", "list", "loading", "loop", "low", "max", "maxlength", "media", "method", "min", "minlength", "multiple", "muted", "name", "nonce", "noshade", "novalidate", "nowrap", "open", "optimum", "part", "pattern", "placeholder", "playsinline", "popover", "popovertarget", "popovertargetaction", "poster", "preload", "pubdate", "radiogroup", "readonly", "rel", "required", "rev", "reversed", "role", "rows", "rowspan", "spellcheck", "scope", "selected", "shape", "size", "sizes", "slot", "span", "srclang", "start", "src", "srcset", "step", "style", "summary", "tabindex", "title", "translate", "type", "usemap", "valign", "value", "width", "wrap", "xmlns", "slot"]);
|
|
1977
|
+
var svg = freeze(["accent-height", "accumulate", "additive", "alignment-baseline", "amplitude", "ascent", "attributename", "attributetype", "azimuth", "basefrequency", "baseline-shift", "begin", "bias", "by", "class", "clip", "clippathunits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "cx", "cy", "d", "dx", "dy", "diffuseconstant", "direction", "display", "divisor", "dur", "edgemode", "elevation", "end", "exponent", "fill", "fill-opacity", "fill-rule", "filter", "filterunits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "fx", "fy", "g1", "g2", "glyph-name", "glyphref", "gradientunits", "gradienttransform", "height", "href", "id", "image-rendering", "in", "in2", "intercept", "k", "k1", "k2", "k3", "k4", "kerning", "keypoints", "keysplines", "keytimes", "lang", "lengthadjust", "letter-spacing", "kernelmatrix", "kernelunitlength", "lighting-color", "local", "marker-end", "marker-mid", "marker-start", "markerheight", "markerunits", "markerwidth", "maskcontentunits", "maskunits", "max", "mask", "mask-type", "media", "method", "mode", "min", "name", "numoctaves", "offset", "operator", "opacity", "order", "orient", "orientation", "origin", "overflow", "paint-order", "path", "pathlength", "patterncontentunits", "patterntransform", "patternunits", "points", "preservealpha", "preserveaspectratio", "primitiveunits", "r", "rx", "ry", "radius", "refx", "refy", "repeatcount", "repeatdur", "restart", "result", "rotate", "scale", "seed", "shape-rendering", "slope", "specularconstant", "specularexponent", "spreadmethod", "startoffset", "stddeviation", "stitchtiles", "stop-color", "stop-opacity", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke", "stroke-width", "style", "surfacescale", "systemlanguage", "tabindex", "tablevalues", "targetx", "targety", "transform", "transform-origin", "text-anchor", "text-decoration", "text-rendering", "textlength", "type", "u1", "u2", "unicode", "values", "viewbox", "visibility", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "width", "word-spacing", "wrap", "writing-mode", "xchannelselector", "ychannelselector", "x", "x1", "x2", "xmlns", "y", "y1", "y2", "z", "zoomandpan"]);
|
|
1978
|
+
var mathMl = freeze(["accent", "accentunder", "align", "bevelled", "close", "columnsalign", "columnlines", "columnspan", "denomalign", "depth", "dir", "display", "displaystyle", "encoding", "fence", "frame", "height", "href", "id", "largeop", "length", "linethickness", "lspace", "lquote", "mathbackground", "mathcolor", "mathsize", "mathvariant", "maxsize", "minsize", "movablelimits", "notation", "numalign", "open", "rowalign", "rowlines", "rowspacing", "rowspan", "rspace", "rquote", "scriptlevel", "scriptminsize", "scriptsizemultiplier", "selection", "separator", "separators", "stretchy", "subscriptshift", "supscriptshift", "symmetric", "voffset", "width", "xmlns"]);
|
|
1979
|
+
var xml = freeze(["xlink:href", "xml:id", "xlink:title", "xml:space", "xmlns:xlink"]);
|
|
1980
|
+
var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm);
|
|
1981
|
+
var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
|
|
1982
|
+
var TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm);
|
|
1983
|
+
var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/);
|
|
1984
|
+
var ARIA_ATTR = seal(/^aria-[\-\w]+$/);
|
|
1985
|
+
var IS_ALLOWED_URI = seal(
|
|
1986
|
+
/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i
|
|
1987
|
+
// eslint-disable-line no-useless-escape
|
|
1988
|
+
);
|
|
1989
|
+
var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
|
|
1990
|
+
var ATTR_WHITESPACE = seal(
|
|
1991
|
+
/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g
|
|
1992
|
+
// eslint-disable-line no-control-regex
|
|
1993
|
+
);
|
|
1994
|
+
var DOCTYPE_NAME = seal(/^html$/i);
|
|
1995
|
+
var CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
|
|
1996
|
+
var EXPRESSIONS = /* @__PURE__ */ Object.freeze({
|
|
1997
|
+
__proto__: null,
|
|
1998
|
+
ARIA_ATTR,
|
|
1999
|
+
ATTR_WHITESPACE,
|
|
2000
|
+
CUSTOM_ELEMENT,
|
|
2001
|
+
DATA_ATTR,
|
|
2002
|
+
DOCTYPE_NAME,
|
|
2003
|
+
ERB_EXPR,
|
|
2004
|
+
IS_ALLOWED_URI,
|
|
2005
|
+
IS_SCRIPT_OR_DATA,
|
|
2006
|
+
MUSTACHE_EXPR,
|
|
2007
|
+
TMPLIT_EXPR
|
|
2008
|
+
});
|
|
2009
|
+
var NODE_TYPE = {
|
|
2010
|
+
element: 1,
|
|
2011
|
+
attribute: 2,
|
|
2012
|
+
text: 3,
|
|
2013
|
+
cdataSection: 4,
|
|
2014
|
+
entityReference: 5,
|
|
2015
|
+
// Deprecated
|
|
2016
|
+
entityNode: 6,
|
|
2017
|
+
// Deprecated
|
|
2018
|
+
progressingInstruction: 7,
|
|
2019
|
+
comment: 8,
|
|
2020
|
+
document: 9,
|
|
2021
|
+
documentType: 10,
|
|
2022
|
+
documentFragment: 11,
|
|
2023
|
+
notation: 12
|
|
2024
|
+
// Deprecated
|
|
2025
|
+
};
|
|
2026
|
+
var getGlobal = function getGlobal2() {
|
|
2027
|
+
return typeof window === "undefined" ? null : window;
|
|
2028
|
+
};
|
|
2029
|
+
var _createTrustedTypesPolicy = function _createTrustedTypesPolicy2(trustedTypes, purifyHostElement) {
|
|
2030
|
+
if (typeof trustedTypes !== "object" || typeof trustedTypes.createPolicy !== "function") {
|
|
2031
|
+
return null;
|
|
2032
|
+
}
|
|
2033
|
+
let suffix = null;
|
|
2034
|
+
const ATTR_NAME = "data-tt-policy-suffix";
|
|
2035
|
+
if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {
|
|
2036
|
+
suffix = purifyHostElement.getAttribute(ATTR_NAME);
|
|
2037
|
+
}
|
|
2038
|
+
const policyName = "dompurify" + (suffix ? "#" + suffix : "");
|
|
2039
|
+
try {
|
|
2040
|
+
return trustedTypes.createPolicy(policyName, {
|
|
2041
|
+
createHTML(html2) {
|
|
2042
|
+
return html2;
|
|
2043
|
+
},
|
|
2044
|
+
createScriptURL(scriptUrl) {
|
|
2045
|
+
return scriptUrl;
|
|
2046
|
+
}
|
|
2047
|
+
});
|
|
2048
|
+
} catch (_) {
|
|
2049
|
+
console.warn("TrustedTypes policy " + policyName + " could not be created.");
|
|
2050
|
+
return null;
|
|
2051
|
+
}
|
|
2052
|
+
};
|
|
2053
|
+
var _createHooksMap = function _createHooksMap2() {
|
|
2054
|
+
return {
|
|
2055
|
+
afterSanitizeAttributes: [],
|
|
2056
|
+
afterSanitizeElements: [],
|
|
2057
|
+
afterSanitizeShadowDOM: [],
|
|
2058
|
+
beforeSanitizeAttributes: [],
|
|
2059
|
+
beforeSanitizeElements: [],
|
|
2060
|
+
beforeSanitizeShadowDOM: [],
|
|
2061
|
+
uponSanitizeAttribute: [],
|
|
2062
|
+
uponSanitizeElement: [],
|
|
2063
|
+
uponSanitizeShadowNode: []
|
|
2064
|
+
};
|
|
2065
|
+
};
|
|
2066
|
+
function createDOMPurify() {
|
|
2067
|
+
let window2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal();
|
|
2068
|
+
const DOMPurify = (root) => createDOMPurify(root);
|
|
2069
|
+
DOMPurify.version = "3.3.3";
|
|
2070
|
+
DOMPurify.removed = [];
|
|
2071
|
+
if (!window2 || !window2.document || window2.document.nodeType !== NODE_TYPE.document || !window2.Element) {
|
|
2072
|
+
DOMPurify.isSupported = false;
|
|
2073
|
+
return DOMPurify;
|
|
2074
|
+
}
|
|
2075
|
+
let {
|
|
2076
|
+
document: document2
|
|
2077
|
+
} = window2;
|
|
2078
|
+
const originalDocument = document2;
|
|
2079
|
+
const currentScript = originalDocument.currentScript;
|
|
2080
|
+
const {
|
|
2081
|
+
DocumentFragment: DocumentFragment2,
|
|
2082
|
+
HTMLTemplateElement,
|
|
2083
|
+
Node,
|
|
2084
|
+
Element,
|
|
2085
|
+
NodeFilter,
|
|
2086
|
+
NamedNodeMap = window2.NamedNodeMap || window2.MozNamedAttrMap,
|
|
2087
|
+
HTMLFormElement,
|
|
2088
|
+
DOMParser: DOMParser2,
|
|
2089
|
+
trustedTypes
|
|
2090
|
+
} = window2;
|
|
2091
|
+
const ElementPrototype = Element.prototype;
|
|
2092
|
+
const cloneNode = lookupGetter(ElementPrototype, "cloneNode");
|
|
2093
|
+
const remove = lookupGetter(ElementPrototype, "remove");
|
|
2094
|
+
const getNextSibling = lookupGetter(ElementPrototype, "nextSibling");
|
|
2095
|
+
const getChildNodes = lookupGetter(ElementPrototype, "childNodes");
|
|
2096
|
+
const getParentNode = lookupGetter(ElementPrototype, "parentNode");
|
|
2097
|
+
if (typeof HTMLTemplateElement === "function") {
|
|
2098
|
+
const template = document2.createElement("template");
|
|
2099
|
+
if (template.content && template.content.ownerDocument) {
|
|
2100
|
+
document2 = template.content.ownerDocument;
|
|
2101
|
+
}
|
|
2102
|
+
}
|
|
2103
|
+
let trustedTypesPolicy;
|
|
2104
|
+
let emptyHTML = "";
|
|
2105
|
+
const {
|
|
2106
|
+
implementation,
|
|
2107
|
+
createNodeIterator,
|
|
2108
|
+
createDocumentFragment,
|
|
2109
|
+
getElementsByTagName
|
|
2110
|
+
} = document2;
|
|
2111
|
+
const {
|
|
2112
|
+
importNode
|
|
2113
|
+
} = originalDocument;
|
|
2114
|
+
let hooks = _createHooksMap();
|
|
2115
|
+
DOMPurify.isSupported = typeof entries === "function" && typeof getParentNode === "function" && implementation && implementation.createHTMLDocument !== void 0;
|
|
2116
|
+
const {
|
|
2117
|
+
MUSTACHE_EXPR: MUSTACHE_EXPR2,
|
|
2118
|
+
ERB_EXPR: ERB_EXPR2,
|
|
2119
|
+
TMPLIT_EXPR: TMPLIT_EXPR2,
|
|
2120
|
+
DATA_ATTR: DATA_ATTR2,
|
|
2121
|
+
ARIA_ATTR: ARIA_ATTR2,
|
|
2122
|
+
IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA2,
|
|
2123
|
+
ATTR_WHITESPACE: ATTR_WHITESPACE2,
|
|
2124
|
+
CUSTOM_ELEMENT: CUSTOM_ELEMENT2
|
|
2125
|
+
} = EXPRESSIONS;
|
|
2126
|
+
let {
|
|
2127
|
+
IS_ALLOWED_URI: IS_ALLOWED_URI$1
|
|
2128
|
+
} = EXPRESSIONS;
|
|
2129
|
+
let ALLOWED_TAGS = null;
|
|
2130
|
+
const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);
|
|
2131
|
+
let ALLOWED_ATTR = null;
|
|
2132
|
+
const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);
|
|
2133
|
+
let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {
|
|
2134
|
+
tagNameCheck: {
|
|
2135
|
+
writable: true,
|
|
2136
|
+
configurable: false,
|
|
2137
|
+
enumerable: true,
|
|
2138
|
+
value: null
|
|
2139
|
+
},
|
|
2140
|
+
attributeNameCheck: {
|
|
2141
|
+
writable: true,
|
|
2142
|
+
configurable: false,
|
|
2143
|
+
enumerable: true,
|
|
2144
|
+
value: null
|
|
2145
|
+
},
|
|
2146
|
+
allowCustomizedBuiltInElements: {
|
|
2147
|
+
writable: true,
|
|
2148
|
+
configurable: false,
|
|
2149
|
+
enumerable: true,
|
|
2150
|
+
value: false
|
|
2151
|
+
}
|
|
2152
|
+
}));
|
|
2153
|
+
let FORBID_TAGS = null;
|
|
2154
|
+
let FORBID_ATTR = null;
|
|
2155
|
+
const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {
|
|
2156
|
+
tagCheck: {
|
|
2157
|
+
writable: true,
|
|
2158
|
+
configurable: false,
|
|
2159
|
+
enumerable: true,
|
|
2160
|
+
value: null
|
|
2161
|
+
},
|
|
2162
|
+
attributeCheck: {
|
|
2163
|
+
writable: true,
|
|
2164
|
+
configurable: false,
|
|
2165
|
+
enumerable: true,
|
|
2166
|
+
value: null
|
|
2167
|
+
}
|
|
2168
|
+
}));
|
|
2169
|
+
let ALLOW_ARIA_ATTR = true;
|
|
2170
|
+
let ALLOW_DATA_ATTR = true;
|
|
2171
|
+
let ALLOW_UNKNOWN_PROTOCOLS = false;
|
|
2172
|
+
let ALLOW_SELF_CLOSE_IN_ATTR = true;
|
|
2173
|
+
let SAFE_FOR_TEMPLATES = false;
|
|
2174
|
+
let SAFE_FOR_XML = true;
|
|
2175
|
+
let WHOLE_DOCUMENT = false;
|
|
2176
|
+
let SET_CONFIG = false;
|
|
2177
|
+
let FORCE_BODY = false;
|
|
2178
|
+
let RETURN_DOM = false;
|
|
2179
|
+
let RETURN_DOM_FRAGMENT = false;
|
|
2180
|
+
let RETURN_TRUSTED_TYPE = false;
|
|
2181
|
+
let SANITIZE_DOM = true;
|
|
2182
|
+
let SANITIZE_NAMED_PROPS = false;
|
|
2183
|
+
const SANITIZE_NAMED_PROPS_PREFIX = "user-content-";
|
|
2184
|
+
let KEEP_CONTENT = true;
|
|
2185
|
+
let IN_PLACE = false;
|
|
2186
|
+
let USE_PROFILES = {};
|
|
2187
|
+
let FORBID_CONTENTS = null;
|
|
2188
|
+
const DEFAULT_FORBID_CONTENTS = addToSet({}, ["annotation-xml", "audio", "colgroup", "desc", "foreignobject", "head", "iframe", "math", "mi", "mn", "mo", "ms", "mtext", "noembed", "noframes", "noscript", "plaintext", "script", "style", "svg", "template", "thead", "title", "video", "xmp"]);
|
|
2189
|
+
let DATA_URI_TAGS = null;
|
|
2190
|
+
const DEFAULT_DATA_URI_TAGS = addToSet({}, ["audio", "video", "img", "source", "image", "track"]);
|
|
2191
|
+
let URI_SAFE_ATTRIBUTES = null;
|
|
2192
|
+
const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ["alt", "class", "for", "id", "label", "name", "pattern", "placeholder", "role", "summary", "title", "value", "style", "xmlns"]);
|
|
2193
|
+
const MATHML_NAMESPACE = "http://www.w3.org/1998/Math/MathML";
|
|
2194
|
+
const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
2195
|
+
const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
|
|
2196
|
+
let NAMESPACE = HTML_NAMESPACE;
|
|
2197
|
+
let IS_EMPTY_INPUT = false;
|
|
2198
|
+
let ALLOWED_NAMESPACES = null;
|
|
2199
|
+
const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
|
|
2200
|
+
let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ["mi", "mo", "mn", "ms", "mtext"]);
|
|
2201
|
+
let HTML_INTEGRATION_POINTS = addToSet({}, ["annotation-xml"]);
|
|
2202
|
+
const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ["title", "style", "font", "a", "script"]);
|
|
2203
|
+
let PARSER_MEDIA_TYPE = null;
|
|
2204
|
+
const SUPPORTED_PARSER_MEDIA_TYPES = ["application/xhtml+xml", "text/html"];
|
|
2205
|
+
const DEFAULT_PARSER_MEDIA_TYPE = "text/html";
|
|
2206
|
+
let transformCaseFunc = null;
|
|
2207
|
+
let CONFIG = null;
|
|
2208
|
+
const formElement = document2.createElement("form");
|
|
2209
|
+
const isRegexOrFunction = function isRegexOrFunction2(testValue) {
|
|
2210
|
+
return testValue instanceof RegExp || testValue instanceof Function;
|
|
2211
|
+
};
|
|
2212
|
+
const _parseConfig = function _parseConfig2() {
|
|
2213
|
+
let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
|
2214
|
+
if (CONFIG && CONFIG === cfg) {
|
|
2215
|
+
return;
|
|
2216
|
+
}
|
|
2217
|
+
if (!cfg || typeof cfg !== "object") {
|
|
2218
|
+
cfg = {};
|
|
2219
|
+
}
|
|
2220
|
+
cfg = clone(cfg);
|
|
2221
|
+
PARSER_MEDIA_TYPE = // eslint-disable-next-line unicorn/prefer-includes
|
|
2222
|
+
SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;
|
|
2223
|
+
transformCaseFunc = PARSER_MEDIA_TYPE === "application/xhtml+xml" ? stringToString : stringToLowerCase;
|
|
2224
|
+
ALLOWED_TAGS = objectHasOwnProperty(cfg, "ALLOWED_TAGS") ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
|
|
2225
|
+
ALLOWED_ATTR = objectHasOwnProperty(cfg, "ALLOWED_ATTR") ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
|
|
2226
|
+
ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, "ALLOWED_NAMESPACES") ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
|
|
2227
|
+
URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, "ADD_URI_SAFE_ATTR") ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
|
|
2228
|
+
DATA_URI_TAGS = objectHasOwnProperty(cfg, "ADD_DATA_URI_TAGS") ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
|
|
2229
|
+
FORBID_CONTENTS = objectHasOwnProperty(cfg, "FORBID_CONTENTS") ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
|
|
2230
|
+
FORBID_TAGS = objectHasOwnProperty(cfg, "FORBID_TAGS") ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
|
|
2231
|
+
FORBID_ATTR = objectHasOwnProperty(cfg, "FORBID_ATTR") ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
|
|
2232
|
+
USE_PROFILES = objectHasOwnProperty(cfg, "USE_PROFILES") ? cfg.USE_PROFILES : false;
|
|
2233
|
+
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
|
|
2234
|
+
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
|
|
2235
|
+
ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false;
|
|
2236
|
+
ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false;
|
|
2237
|
+
SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false;
|
|
2238
|
+
SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false;
|
|
2239
|
+
WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false;
|
|
2240
|
+
RETURN_DOM = cfg.RETURN_DOM || false;
|
|
2241
|
+
RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false;
|
|
2242
|
+
RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false;
|
|
2243
|
+
FORCE_BODY = cfg.FORCE_BODY || false;
|
|
2244
|
+
SANITIZE_DOM = cfg.SANITIZE_DOM !== false;
|
|
2245
|
+
SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false;
|
|
2246
|
+
KEEP_CONTENT = cfg.KEEP_CONTENT !== false;
|
|
2247
|
+
IN_PLACE = cfg.IN_PLACE || false;
|
|
2248
|
+
IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;
|
|
2249
|
+
NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
|
|
2250
|
+
MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;
|
|
2251
|
+
HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;
|
|
2252
|
+
CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
|
|
2253
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
|
|
2254
|
+
CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
|
|
2255
|
+
}
|
|
2256
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
|
|
2257
|
+
CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
|
|
2258
|
+
}
|
|
2259
|
+
if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === "boolean") {
|
|
2260
|
+
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
|
|
2261
|
+
}
|
|
2262
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
2263
|
+
ALLOW_DATA_ATTR = false;
|
|
2264
|
+
}
|
|
2265
|
+
if (RETURN_DOM_FRAGMENT) {
|
|
2266
|
+
RETURN_DOM = true;
|
|
2267
|
+
}
|
|
2268
|
+
if (USE_PROFILES) {
|
|
2269
|
+
ALLOWED_TAGS = addToSet({}, text);
|
|
2270
|
+
ALLOWED_ATTR = create(null);
|
|
2271
|
+
if (USE_PROFILES.html === true) {
|
|
2272
|
+
addToSet(ALLOWED_TAGS, html$1);
|
|
2273
|
+
addToSet(ALLOWED_ATTR, html);
|
|
2274
|
+
}
|
|
2275
|
+
if (USE_PROFILES.svg === true) {
|
|
2276
|
+
addToSet(ALLOWED_TAGS, svg$1);
|
|
2277
|
+
addToSet(ALLOWED_ATTR, svg);
|
|
2278
|
+
addToSet(ALLOWED_ATTR, xml);
|
|
2279
|
+
}
|
|
2280
|
+
if (USE_PROFILES.svgFilters === true) {
|
|
2281
|
+
addToSet(ALLOWED_TAGS, svgFilters);
|
|
2282
|
+
addToSet(ALLOWED_ATTR, svg);
|
|
2283
|
+
addToSet(ALLOWED_ATTR, xml);
|
|
2284
|
+
}
|
|
2285
|
+
if (USE_PROFILES.mathMl === true) {
|
|
2286
|
+
addToSet(ALLOWED_TAGS, mathMl$1);
|
|
2287
|
+
addToSet(ALLOWED_ATTR, mathMl);
|
|
2288
|
+
addToSet(ALLOWED_ATTR, xml);
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
if (!objectHasOwnProperty(cfg, "ADD_TAGS")) {
|
|
2292
|
+
EXTRA_ELEMENT_HANDLING.tagCheck = null;
|
|
2293
|
+
}
|
|
2294
|
+
if (!objectHasOwnProperty(cfg, "ADD_ATTR")) {
|
|
2295
|
+
EXTRA_ELEMENT_HANDLING.attributeCheck = null;
|
|
2296
|
+
}
|
|
2297
|
+
if (cfg.ADD_TAGS) {
|
|
2298
|
+
if (typeof cfg.ADD_TAGS === "function") {
|
|
2299
|
+
EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
|
|
2300
|
+
} else {
|
|
2301
|
+
if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
|
|
2302
|
+
ALLOWED_TAGS = clone(ALLOWED_TAGS);
|
|
2303
|
+
}
|
|
2304
|
+
addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
if (cfg.ADD_ATTR) {
|
|
2308
|
+
if (typeof cfg.ADD_ATTR === "function") {
|
|
2309
|
+
EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
|
|
2310
|
+
} else {
|
|
2311
|
+
if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
|
|
2312
|
+
ALLOWED_ATTR = clone(ALLOWED_ATTR);
|
|
2313
|
+
}
|
|
2314
|
+
addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
if (cfg.ADD_URI_SAFE_ATTR) {
|
|
2318
|
+
addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
|
|
2319
|
+
}
|
|
2320
|
+
if (cfg.FORBID_CONTENTS) {
|
|
2321
|
+
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
|
|
2322
|
+
FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
2323
|
+
}
|
|
2324
|
+
addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
|
|
2325
|
+
}
|
|
2326
|
+
if (cfg.ADD_FORBID_CONTENTS) {
|
|
2327
|
+
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
|
|
2328
|
+
FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
2329
|
+
}
|
|
2330
|
+
addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
|
|
2331
|
+
}
|
|
2332
|
+
if (KEEP_CONTENT) {
|
|
2333
|
+
ALLOWED_TAGS["#text"] = true;
|
|
2334
|
+
}
|
|
2335
|
+
if (WHOLE_DOCUMENT) {
|
|
2336
|
+
addToSet(ALLOWED_TAGS, ["html", "head", "body"]);
|
|
2337
|
+
}
|
|
2338
|
+
if (ALLOWED_TAGS.table) {
|
|
2339
|
+
addToSet(ALLOWED_TAGS, ["tbody"]);
|
|
2340
|
+
delete FORBID_TAGS.tbody;
|
|
2341
|
+
}
|
|
2342
|
+
if (cfg.TRUSTED_TYPES_POLICY) {
|
|
2343
|
+
if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== "function") {
|
|
2344
|
+
throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');
|
|
2345
|
+
}
|
|
2346
|
+
if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== "function") {
|
|
2347
|
+
throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
|
|
2348
|
+
}
|
|
2349
|
+
trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
|
|
2350
|
+
emptyHTML = trustedTypesPolicy.createHTML("");
|
|
2351
|
+
} else {
|
|
2352
|
+
if (trustedTypesPolicy === void 0) {
|
|
2353
|
+
trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
|
|
2354
|
+
}
|
|
2355
|
+
if (trustedTypesPolicy !== null && typeof emptyHTML === "string") {
|
|
2356
|
+
emptyHTML = trustedTypesPolicy.createHTML("");
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
if (freeze) {
|
|
2360
|
+
freeze(cfg);
|
|
2361
|
+
}
|
|
2362
|
+
CONFIG = cfg;
|
|
2363
|
+
};
|
|
2364
|
+
const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);
|
|
2365
|
+
const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);
|
|
2366
|
+
const _checkValidNamespace = function _checkValidNamespace2(element) {
|
|
2367
|
+
let parent = getParentNode(element);
|
|
2368
|
+
if (!parent || !parent.tagName) {
|
|
2369
|
+
parent = {
|
|
2370
|
+
namespaceURI: NAMESPACE,
|
|
2371
|
+
tagName: "template"
|
|
2372
|
+
};
|
|
2373
|
+
}
|
|
2374
|
+
const tagName = stringToLowerCase(element.tagName);
|
|
2375
|
+
const parentTagName = stringToLowerCase(parent.tagName);
|
|
2376
|
+
if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
|
|
2377
|
+
return false;
|
|
2378
|
+
}
|
|
2379
|
+
if (element.namespaceURI === SVG_NAMESPACE) {
|
|
2380
|
+
if (parent.namespaceURI === HTML_NAMESPACE) {
|
|
2381
|
+
return tagName === "svg";
|
|
2382
|
+
}
|
|
2383
|
+
if (parent.namespaceURI === MATHML_NAMESPACE) {
|
|
2384
|
+
return tagName === "svg" && (parentTagName === "annotation-xml" || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
|
|
2385
|
+
}
|
|
2386
|
+
return Boolean(ALL_SVG_TAGS[tagName]);
|
|
2387
|
+
}
|
|
2388
|
+
if (element.namespaceURI === MATHML_NAMESPACE) {
|
|
2389
|
+
if (parent.namespaceURI === HTML_NAMESPACE) {
|
|
2390
|
+
return tagName === "math";
|
|
2391
|
+
}
|
|
2392
|
+
if (parent.namespaceURI === SVG_NAMESPACE) {
|
|
2393
|
+
return tagName === "math" && HTML_INTEGRATION_POINTS[parentTagName];
|
|
2394
|
+
}
|
|
2395
|
+
return Boolean(ALL_MATHML_TAGS[tagName]);
|
|
2396
|
+
}
|
|
2397
|
+
if (element.namespaceURI === HTML_NAMESPACE) {
|
|
2398
|
+
if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
|
|
2399
|
+
return false;
|
|
2400
|
+
}
|
|
2401
|
+
if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
|
|
2402
|
+
return false;
|
|
2403
|
+
}
|
|
2404
|
+
return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
|
|
2405
|
+
}
|
|
2406
|
+
if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && ALLOWED_NAMESPACES[element.namespaceURI]) {
|
|
2407
|
+
return true;
|
|
2408
|
+
}
|
|
2409
|
+
return false;
|
|
2410
|
+
};
|
|
2411
|
+
const _forceRemove = function _forceRemove2(node) {
|
|
2412
|
+
arrayPush(DOMPurify.removed, {
|
|
2413
|
+
element: node
|
|
2414
|
+
});
|
|
2415
|
+
try {
|
|
2416
|
+
getParentNode(node).removeChild(node);
|
|
2417
|
+
} catch (_) {
|
|
2418
|
+
remove(node);
|
|
2419
|
+
}
|
|
2420
|
+
};
|
|
2421
|
+
const _removeAttribute = function _removeAttribute2(name, element) {
|
|
2422
|
+
try {
|
|
2423
|
+
arrayPush(DOMPurify.removed, {
|
|
2424
|
+
attribute: element.getAttributeNode(name),
|
|
2425
|
+
from: element
|
|
2426
|
+
});
|
|
2427
|
+
} catch (_) {
|
|
2428
|
+
arrayPush(DOMPurify.removed, {
|
|
2429
|
+
attribute: null,
|
|
2430
|
+
from: element
|
|
2431
|
+
});
|
|
2432
|
+
}
|
|
2433
|
+
element.removeAttribute(name);
|
|
2434
|
+
if (name === "is") {
|
|
2435
|
+
if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
|
|
2436
|
+
try {
|
|
2437
|
+
_forceRemove(element);
|
|
2438
|
+
} catch (_) {
|
|
2439
|
+
}
|
|
2440
|
+
} else {
|
|
2441
|
+
try {
|
|
2442
|
+
element.setAttribute(name, "");
|
|
2443
|
+
} catch (_) {
|
|
2444
|
+
}
|
|
2445
|
+
}
|
|
2446
|
+
}
|
|
2447
|
+
};
|
|
2448
|
+
const _initDocument = function _initDocument2(dirty) {
|
|
2449
|
+
let doc = null;
|
|
2450
|
+
let leadingWhitespace = null;
|
|
2451
|
+
if (FORCE_BODY) {
|
|
2452
|
+
dirty = "<remove></remove>" + dirty;
|
|
2453
|
+
} else {
|
|
2454
|
+
const matches = stringMatch(dirty, /^[\r\n\t ]+/);
|
|
2455
|
+
leadingWhitespace = matches && matches[0];
|
|
2456
|
+
}
|
|
2457
|
+
if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && NAMESPACE === HTML_NAMESPACE) {
|
|
2458
|
+
dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + "</body></html>";
|
|
2459
|
+
}
|
|
2460
|
+
const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
2461
|
+
if (NAMESPACE === HTML_NAMESPACE) {
|
|
2462
|
+
try {
|
|
2463
|
+
doc = new DOMParser2().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
|
|
2464
|
+
} catch (_) {
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
if (!doc || !doc.documentElement) {
|
|
2468
|
+
doc = implementation.createDocument(NAMESPACE, "template", null);
|
|
2469
|
+
try {
|
|
2470
|
+
doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
|
|
2471
|
+
} catch (_) {
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
const body = doc.body || doc.documentElement;
|
|
2475
|
+
if (dirty && leadingWhitespace) {
|
|
2476
|
+
body.insertBefore(document2.createTextNode(leadingWhitespace), body.childNodes[0] || null);
|
|
2477
|
+
}
|
|
2478
|
+
if (NAMESPACE === HTML_NAMESPACE) {
|
|
2479
|
+
return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? "html" : "body")[0];
|
|
2480
|
+
}
|
|
2481
|
+
return WHOLE_DOCUMENT ? doc.documentElement : body;
|
|
2482
|
+
};
|
|
2483
|
+
const _createNodeIterator = function _createNodeIterator2(root) {
|
|
2484
|
+
return createNodeIterator.call(
|
|
2485
|
+
root.ownerDocument || root,
|
|
2486
|
+
root,
|
|
2487
|
+
// eslint-disable-next-line no-bitwise
|
|
2488
|
+
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION,
|
|
2489
|
+
null
|
|
2490
|
+
);
|
|
2491
|
+
};
|
|
2492
|
+
const _isClobbered = function _isClobbered2(element) {
|
|
2493
|
+
return element instanceof HTMLFormElement && (typeof element.nodeName !== "string" || typeof element.textContent !== "string" || typeof element.removeChild !== "function" || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== "function" || typeof element.setAttribute !== "function" || typeof element.namespaceURI !== "string" || typeof element.insertBefore !== "function" || typeof element.hasChildNodes !== "function");
|
|
2494
|
+
};
|
|
2495
|
+
const _isNode = function _isNode2(value) {
|
|
2496
|
+
return typeof Node === "function" && value instanceof Node;
|
|
2497
|
+
};
|
|
2498
|
+
function _executeHooks(hooks2, currentNode, data) {
|
|
2499
|
+
arrayForEach(hooks2, (hook) => {
|
|
2500
|
+
hook.call(DOMPurify, currentNode, data, CONFIG);
|
|
2501
|
+
});
|
|
2502
|
+
}
|
|
2503
|
+
const _sanitizeElements = function _sanitizeElements2(currentNode) {
|
|
2504
|
+
let content = null;
|
|
2505
|
+
_executeHooks(hooks.beforeSanitizeElements, currentNode, null);
|
|
2506
|
+
if (_isClobbered(currentNode)) {
|
|
2507
|
+
_forceRemove(currentNode);
|
|
2508
|
+
return true;
|
|
2509
|
+
}
|
|
2510
|
+
const tagName = transformCaseFunc(currentNode.nodeName);
|
|
2511
|
+
_executeHooks(hooks.uponSanitizeElement, currentNode, {
|
|
2512
|
+
tagName,
|
|
2513
|
+
allowedTags: ALLOWED_TAGS
|
|
2514
|
+
});
|
|
2515
|
+
if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\w!]/g, currentNode.textContent)) {
|
|
2516
|
+
_forceRemove(currentNode);
|
|
2517
|
+
return true;
|
|
2518
|
+
}
|
|
2519
|
+
if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
|
|
2520
|
+
_forceRemove(currentNode);
|
|
2521
|
+
return true;
|
|
2522
|
+
}
|
|
2523
|
+
if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\w]/g, currentNode.data)) {
|
|
2524
|
+
_forceRemove(currentNode);
|
|
2525
|
+
return true;
|
|
2526
|
+
}
|
|
2527
|
+
if (!(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName])) {
|
|
2528
|
+
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
|
|
2529
|
+
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
|
|
2530
|
+
return false;
|
|
2531
|
+
}
|
|
2532
|
+
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {
|
|
2533
|
+
return false;
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
2537
|
+
const parentNode = getParentNode(currentNode) || currentNode.parentNode;
|
|
2538
|
+
const childNodes = getChildNodes(currentNode) || currentNode.childNodes;
|
|
2539
|
+
if (childNodes && parentNode) {
|
|
2540
|
+
const childCount = childNodes.length;
|
|
2541
|
+
for (let i = childCount - 1; i >= 0; --i) {
|
|
2542
|
+
const childClone = cloneNode(childNodes[i], true);
|
|
2543
|
+
childClone.__removalCount = (currentNode.__removalCount || 0) + 1;
|
|
2544
|
+
parentNode.insertBefore(childClone, getNextSibling(currentNode));
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
_forceRemove(currentNode);
|
|
2549
|
+
return true;
|
|
2550
|
+
}
|
|
2551
|
+
if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
|
|
2552
|
+
_forceRemove(currentNode);
|
|
2553
|
+
return true;
|
|
2554
|
+
}
|
|
2555
|
+
if ((tagName === "noscript" || tagName === "noembed" || tagName === "noframes") && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) {
|
|
2556
|
+
_forceRemove(currentNode);
|
|
2557
|
+
return true;
|
|
2558
|
+
}
|
|
2559
|
+
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
|
|
2560
|
+
content = currentNode.textContent;
|
|
2561
|
+
arrayForEach([MUSTACHE_EXPR2, ERB_EXPR2, TMPLIT_EXPR2], (expr) => {
|
|
2562
|
+
content = stringReplace(content, expr, " ");
|
|
2563
|
+
});
|
|
2564
|
+
if (currentNode.textContent !== content) {
|
|
2565
|
+
arrayPush(DOMPurify.removed, {
|
|
2566
|
+
element: currentNode.cloneNode()
|
|
2567
|
+
});
|
|
2568
|
+
currentNode.textContent = content;
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2571
|
+
_executeHooks(hooks.afterSanitizeElements, currentNode, null);
|
|
2572
|
+
return false;
|
|
2573
|
+
};
|
|
2574
|
+
const _isValidAttribute = function _isValidAttribute2(lcTag, lcName, value) {
|
|
2575
|
+
if (FORBID_ATTR[lcName]) {
|
|
2576
|
+
return false;
|
|
2577
|
+
}
|
|
2578
|
+
if (SANITIZE_DOM && (lcName === "id" || lcName === "name") && (value in document2 || value in formElement)) {
|
|
2579
|
+
return false;
|
|
2580
|
+
}
|
|
2581
|
+
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR2, lcName)) ;
|
|
2582
|
+
else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR2, lcName)) ;
|
|
2583
|
+
else if (EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag)) ;
|
|
2584
|
+
else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
2585
|
+
if (
|
|
2586
|
+
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
2587
|
+
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
2588
|
+
// and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
|
|
2589
|
+
_isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName, lcTag)) || // Alternative, second condition checks if it's an `is`-attribute, AND
|
|
2590
|
+
// the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
2591
|
+
lcName === "is" && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))
|
|
2592
|
+
) ;
|
|
2593
|
+
else {
|
|
2594
|
+
return false;
|
|
2595
|
+
}
|
|
2596
|
+
} else if (URI_SAFE_ATTRIBUTES[lcName]) ;
|
|
2597
|
+
else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE2, ""))) ;
|
|
2598
|
+
else if ((lcName === "src" || lcName === "xlink:href" || lcName === "href") && lcTag !== "script" && stringIndexOf(value, "data:") === 0 && DATA_URI_TAGS[lcTag]) ;
|
|
2599
|
+
else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA2, stringReplace(value, ATTR_WHITESPACE2, ""))) ;
|
|
2600
|
+
else if (value) {
|
|
2601
|
+
return false;
|
|
2602
|
+
} else ;
|
|
2603
|
+
return true;
|
|
2604
|
+
};
|
|
2605
|
+
const _isBasicCustomElement = function _isBasicCustomElement2(tagName) {
|
|
2606
|
+
return tagName !== "annotation-xml" && stringMatch(tagName, CUSTOM_ELEMENT2);
|
|
2607
|
+
};
|
|
2608
|
+
const _sanitizeAttributes = function _sanitizeAttributes2(currentNode) {
|
|
2609
|
+
_executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
|
|
2610
|
+
const {
|
|
2611
|
+
attributes
|
|
2612
|
+
} = currentNode;
|
|
2613
|
+
if (!attributes || _isClobbered(currentNode)) {
|
|
2614
|
+
return;
|
|
2615
|
+
}
|
|
2616
|
+
const hookEvent = {
|
|
2617
|
+
attrName: "",
|
|
2618
|
+
attrValue: "",
|
|
2619
|
+
keepAttr: true,
|
|
2620
|
+
allowedAttributes: ALLOWED_ATTR,
|
|
2621
|
+
forceKeepAttr: void 0
|
|
2622
|
+
};
|
|
2623
|
+
let l = attributes.length;
|
|
2624
|
+
while (l--) {
|
|
2625
|
+
const attr = attributes[l];
|
|
2626
|
+
const {
|
|
2627
|
+
name,
|
|
2628
|
+
namespaceURI,
|
|
2629
|
+
value: attrValue
|
|
2630
|
+
} = attr;
|
|
2631
|
+
const lcName = transformCaseFunc(name);
|
|
2632
|
+
const initValue = attrValue;
|
|
2633
|
+
let value = name === "value" ? initValue : stringTrim(initValue);
|
|
2634
|
+
hookEvent.attrName = lcName;
|
|
2635
|
+
hookEvent.attrValue = value;
|
|
2636
|
+
hookEvent.keepAttr = true;
|
|
2637
|
+
hookEvent.forceKeepAttr = void 0;
|
|
2638
|
+
_executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
|
|
2639
|
+
value = hookEvent.attrValue;
|
|
2640
|
+
if (SANITIZE_NAMED_PROPS && (lcName === "id" || lcName === "name")) {
|
|
2641
|
+
_removeAttribute(name, currentNode);
|
|
2642
|
+
value = SANITIZE_NAMED_PROPS_PREFIX + value;
|
|
2643
|
+
}
|
|
2644
|
+
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
|
|
2645
|
+
_removeAttribute(name, currentNode);
|
|
2646
|
+
continue;
|
|
2647
|
+
}
|
|
2648
|
+
if (lcName === "attributename" && stringMatch(value, "href")) {
|
|
2649
|
+
_removeAttribute(name, currentNode);
|
|
2650
|
+
continue;
|
|
2651
|
+
}
|
|
2652
|
+
if (hookEvent.forceKeepAttr) {
|
|
2653
|
+
continue;
|
|
2654
|
+
}
|
|
2655
|
+
if (!hookEvent.keepAttr) {
|
|
2656
|
+
_removeAttribute(name, currentNode);
|
|
2657
|
+
continue;
|
|
2658
|
+
}
|
|
2659
|
+
if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
|
|
2660
|
+
_removeAttribute(name, currentNode);
|
|
2661
|
+
continue;
|
|
2662
|
+
}
|
|
2663
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
2664
|
+
arrayForEach([MUSTACHE_EXPR2, ERB_EXPR2, TMPLIT_EXPR2], (expr) => {
|
|
2665
|
+
value = stringReplace(value, expr, " ");
|
|
2666
|
+
});
|
|
2667
|
+
}
|
|
2668
|
+
const lcTag = transformCaseFunc(currentNode.nodeName);
|
|
2669
|
+
if (!_isValidAttribute(lcTag, lcName, value)) {
|
|
2670
|
+
_removeAttribute(name, currentNode);
|
|
2671
|
+
continue;
|
|
2672
|
+
}
|
|
2673
|
+
if (trustedTypesPolicy && typeof trustedTypes === "object" && typeof trustedTypes.getAttributeType === "function") {
|
|
2674
|
+
if (namespaceURI) ;
|
|
2675
|
+
else {
|
|
2676
|
+
switch (trustedTypes.getAttributeType(lcTag, lcName)) {
|
|
2677
|
+
case "TrustedHTML": {
|
|
2678
|
+
value = trustedTypesPolicy.createHTML(value);
|
|
2679
|
+
break;
|
|
2680
|
+
}
|
|
2681
|
+
case "TrustedScriptURL": {
|
|
2682
|
+
value = trustedTypesPolicy.createScriptURL(value);
|
|
2683
|
+
break;
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
if (value !== initValue) {
|
|
2689
|
+
try {
|
|
2690
|
+
if (namespaceURI) {
|
|
2691
|
+
currentNode.setAttributeNS(namespaceURI, name, value);
|
|
2692
|
+
} else {
|
|
2693
|
+
currentNode.setAttribute(name, value);
|
|
2694
|
+
}
|
|
2695
|
+
if (_isClobbered(currentNode)) {
|
|
2696
|
+
_forceRemove(currentNode);
|
|
2697
|
+
} else {
|
|
2698
|
+
arrayPop(DOMPurify.removed);
|
|
2699
|
+
}
|
|
2700
|
+
} catch (_) {
|
|
2701
|
+
_removeAttribute(name, currentNode);
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
_executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
|
|
2706
|
+
};
|
|
2707
|
+
const _sanitizeShadowDOM = function _sanitizeShadowDOM2(fragment) {
|
|
2708
|
+
let shadowNode = null;
|
|
2709
|
+
const shadowIterator = _createNodeIterator(fragment);
|
|
2710
|
+
_executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);
|
|
2711
|
+
while (shadowNode = shadowIterator.nextNode()) {
|
|
2712
|
+
_executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
|
|
2713
|
+
_sanitizeElements(shadowNode);
|
|
2714
|
+
_sanitizeAttributes(shadowNode);
|
|
2715
|
+
if (shadowNode.content instanceof DocumentFragment2) {
|
|
2716
|
+
_sanitizeShadowDOM2(shadowNode.content);
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
_executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
|
|
2720
|
+
};
|
|
2721
|
+
DOMPurify.sanitize = function(dirty) {
|
|
2722
|
+
let cfg = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
2723
|
+
let body = null;
|
|
2724
|
+
let importedNode = null;
|
|
2725
|
+
let currentNode = null;
|
|
2726
|
+
let returnNode = null;
|
|
2727
|
+
IS_EMPTY_INPUT = !dirty;
|
|
2728
|
+
if (IS_EMPTY_INPUT) {
|
|
2729
|
+
dirty = "<!-->";
|
|
2730
|
+
}
|
|
2731
|
+
if (typeof dirty !== "string" && !_isNode(dirty)) {
|
|
2732
|
+
if (typeof dirty.toString === "function") {
|
|
2733
|
+
dirty = dirty.toString();
|
|
2734
|
+
if (typeof dirty !== "string") {
|
|
2735
|
+
throw typeErrorCreate("dirty is not a string, aborting");
|
|
2736
|
+
}
|
|
2737
|
+
} else {
|
|
2738
|
+
throw typeErrorCreate("toString is not a function");
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2741
|
+
if (!DOMPurify.isSupported) {
|
|
2742
|
+
return dirty;
|
|
2743
|
+
}
|
|
2744
|
+
if (!SET_CONFIG) {
|
|
2745
|
+
_parseConfig(cfg);
|
|
2746
|
+
}
|
|
2747
|
+
DOMPurify.removed = [];
|
|
2748
|
+
if (typeof dirty === "string") {
|
|
2749
|
+
IN_PLACE = false;
|
|
2750
|
+
}
|
|
2751
|
+
if (IN_PLACE) {
|
|
2752
|
+
if (dirty.nodeName) {
|
|
2753
|
+
const tagName = transformCaseFunc(dirty.nodeName);
|
|
2754
|
+
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
2755
|
+
throw typeErrorCreate("root node is forbidden and cannot be sanitized in-place");
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2758
|
+
} else if (dirty instanceof Node) {
|
|
2759
|
+
body = _initDocument("<!---->");
|
|
2760
|
+
importedNode = body.ownerDocument.importNode(dirty, true);
|
|
2761
|
+
if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === "BODY") {
|
|
2762
|
+
body = importedNode;
|
|
2763
|
+
} else if (importedNode.nodeName === "HTML") {
|
|
2764
|
+
body = importedNode;
|
|
2765
|
+
} else {
|
|
2766
|
+
body.appendChild(importedNode);
|
|
2767
|
+
}
|
|
1895
2768
|
} else {
|
|
1896
|
-
|
|
2769
|
+
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && // eslint-disable-next-line unicorn/prefer-includes
|
|
2770
|
+
dirty.indexOf("<") === -1) {
|
|
2771
|
+
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
2772
|
+
}
|
|
2773
|
+
body = _initDocument(dirty);
|
|
2774
|
+
if (!body) {
|
|
2775
|
+
return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : "";
|
|
2776
|
+
}
|
|
1897
2777
|
}
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
/**
|
|
1901
|
-
* Appends all key-value pairs from an iterable or object to the ParameterMap.
|
|
1902
|
-
* If a key already exists, the value will be appended to the underlying {@link Array}.
|
|
1903
|
-
* If a key does not exist, the key and value will be added to the ParameterMap.
|
|
1904
|
-
*
|
|
1905
|
-
* @param {Iterable<[string, *]>|Object} parameters The parameters to append.
|
|
1906
|
-
* @returns {ParameterMap<string, *>} The ParameterMap with the updated key and value.
|
|
1907
|
-
*/
|
|
1908
|
-
appendAll(parameters) {
|
|
1909
|
-
for (const [key, value] of _ParameterMap.#entries(parameters)) {
|
|
1910
|
-
this.append(key, value);
|
|
2778
|
+
if (body && FORCE_BODY) {
|
|
2779
|
+
_forceRemove(body.firstChild);
|
|
1911
2780
|
}
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
* @returns {boolean} True if the key has the value, false otherwise.
|
|
1919
|
-
*/
|
|
1920
|
-
hasValue(value) {
|
|
1921
|
-
for (const array of super.values()) {
|
|
1922
|
-
if (array.includes(value)) {
|
|
1923
|
-
return true;
|
|
2781
|
+
const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);
|
|
2782
|
+
while (currentNode = nodeIterator.nextNode()) {
|
|
2783
|
+
_sanitizeElements(currentNode);
|
|
2784
|
+
_sanitizeAttributes(currentNode);
|
|
2785
|
+
if (currentNode.content instanceof DocumentFragment2) {
|
|
2786
|
+
_sanitizeShadowDOM(currentNode.content);
|
|
1924
2787
|
}
|
|
1925
2788
|
}
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
return array.splice(array.indexOf(value), 1).length > 0;
|
|
2789
|
+
if (IN_PLACE) {
|
|
2790
|
+
return dirty;
|
|
2791
|
+
}
|
|
2792
|
+
if (RETURN_DOM) {
|
|
2793
|
+
if (RETURN_DOM_FRAGMENT) {
|
|
2794
|
+
returnNode = createDocumentFragment.call(body.ownerDocument);
|
|
2795
|
+
while (body.firstChild) {
|
|
2796
|
+
returnNode.appendChild(body.firstChild);
|
|
2797
|
+
}
|
|
2798
|
+
} else {
|
|
2799
|
+
returnNode = body;
|
|
1938
2800
|
}
|
|
2801
|
+
if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {
|
|
2802
|
+
returnNode = importNode.call(originalDocument, returnNode, true);
|
|
2803
|
+
}
|
|
2804
|
+
return returnNode;
|
|
2805
|
+
}
|
|
2806
|
+
let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
|
|
2807
|
+
if (WHOLE_DOCUMENT && ALLOWED_TAGS["!doctype"] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
|
|
2808
|
+
serializedHTML = "<!DOCTYPE " + body.ownerDocument.doctype.name + ">\n" + serializedHTML;
|
|
2809
|
+
}
|
|
2810
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
2811
|
+
arrayForEach([MUSTACHE_EXPR2, ERB_EXPR2, TMPLIT_EXPR2], (expr) => {
|
|
2812
|
+
serializedHTML = stringReplace(serializedHTML, expr, " ");
|
|
2813
|
+
});
|
|
2814
|
+
}
|
|
2815
|
+
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
|
|
2816
|
+
};
|
|
2817
|
+
DOMPurify.setConfig = function() {
|
|
2818
|
+
let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
|
2819
|
+
_parseConfig(cfg);
|
|
2820
|
+
SET_CONFIG = true;
|
|
2821
|
+
};
|
|
2822
|
+
DOMPurify.clearConfig = function() {
|
|
2823
|
+
CONFIG = null;
|
|
2824
|
+
SET_CONFIG = false;
|
|
2825
|
+
};
|
|
2826
|
+
DOMPurify.isValidAttribute = function(tag, attr, value) {
|
|
2827
|
+
if (!CONFIG) {
|
|
2828
|
+
_parseConfig({});
|
|
2829
|
+
}
|
|
2830
|
+
const lcTag = transformCaseFunc(tag);
|
|
2831
|
+
const lcName = transformCaseFunc(attr);
|
|
2832
|
+
return _isValidAttribute(lcTag, lcName, value);
|
|
2833
|
+
};
|
|
2834
|
+
DOMPurify.addHook = function(entryPoint, hookFunction) {
|
|
2835
|
+
if (typeof hookFunction !== "function") {
|
|
2836
|
+
return;
|
|
2837
|
+
}
|
|
2838
|
+
arrayPush(hooks[entryPoint], hookFunction);
|
|
2839
|
+
};
|
|
2840
|
+
DOMPurify.removeHook = function(entryPoint, hookFunction) {
|
|
2841
|
+
if (hookFunction !== void 0) {
|
|
2842
|
+
const index = arrayLastIndexOf(hooks[entryPoint], hookFunction);
|
|
2843
|
+
return index === -1 ? void 0 : arraySplice(hooks[entryPoint], index, 1)[0];
|
|
2844
|
+
}
|
|
2845
|
+
return arrayPop(hooks[entryPoint]);
|
|
2846
|
+
};
|
|
2847
|
+
DOMPurify.removeHooks = function(entryPoint) {
|
|
2848
|
+
hooks[entryPoint] = [];
|
|
2849
|
+
};
|
|
2850
|
+
DOMPurify.removeAllHooks = function() {
|
|
2851
|
+
hooks = _createHooksMap();
|
|
2852
|
+
};
|
|
2853
|
+
return DOMPurify;
|
|
2854
|
+
}
|
|
2855
|
+
var purify = createDOMPurify();
|
|
2856
|
+
|
|
2857
|
+
// src/response-handlers.ts
|
|
2858
|
+
var domReady;
|
|
2859
|
+
var ensureDom = async () => {
|
|
2860
|
+
if (typeof document !== "undefined" && typeof DOMParser !== "undefined" && typeof DocumentFragment !== "undefined") {
|
|
2861
|
+
return Promise.resolve();
|
|
2862
|
+
}
|
|
2863
|
+
return domReady ??= import("jsdom").then(({ JSDOM }) => {
|
|
2864
|
+
const { window: window2 } = new JSDOM("<!DOCTYPE html><html><head></head><body></body></html>");
|
|
2865
|
+
globalThis.window = window2;
|
|
2866
|
+
Object.assign(globalThis, { document: window2.document, DOMParser: window2.DOMParser, DocumentFragment: window2.DocumentFragment });
|
|
2867
|
+
});
|
|
2868
|
+
};
|
|
2869
|
+
var handleText = async (response) => await response.text();
|
|
2870
|
+
var handleScript = async (response) => {
|
|
2871
|
+
await ensureDom();
|
|
2872
|
+
const objectURL = URL.createObjectURL(await response.blob());
|
|
2873
|
+
return new Promise((resolve, reject) => {
|
|
2874
|
+
const script = document.createElement("script");
|
|
2875
|
+
Object.assign(script, { src: objectURL, type: HttpMediaType.JAVA_SCRIPT, async: true });
|
|
2876
|
+
script.onload = () => {
|
|
2877
|
+
URL.revokeObjectURL(objectURL);
|
|
2878
|
+
document.head.removeChild(script);
|
|
2879
|
+
resolve();
|
|
2880
|
+
};
|
|
2881
|
+
script.onerror = () => {
|
|
2882
|
+
URL.revokeObjectURL(objectURL);
|
|
2883
|
+
document.head.removeChild(script);
|
|
2884
|
+
reject(new Error("Script failed to load"));
|
|
2885
|
+
};
|
|
2886
|
+
document.head.appendChild(script);
|
|
2887
|
+
});
|
|
2888
|
+
};
|
|
2889
|
+
var handleCss = async (response) => {
|
|
2890
|
+
await ensureDom();
|
|
2891
|
+
const objectURL = URL.createObjectURL(await response.blob());
|
|
2892
|
+
return new Promise((resolve, reject) => {
|
|
2893
|
+
const link = document.createElement("link");
|
|
2894
|
+
Object.assign(link, { href: objectURL, type: HttpMediaType.CSS, rel: "stylesheet" });
|
|
2895
|
+
link.onload = () => resolve(URL.revokeObjectURL(objectURL));
|
|
2896
|
+
link.onerror = () => {
|
|
2897
|
+
URL.revokeObjectURL(objectURL);
|
|
2898
|
+
document.head.removeChild(link);
|
|
2899
|
+
reject(new Error("Stylesheet load failed"));
|
|
2900
|
+
};
|
|
2901
|
+
document.head.appendChild(link);
|
|
2902
|
+
});
|
|
2903
|
+
};
|
|
2904
|
+
var handleJson = async (response) => await response.json();
|
|
2905
|
+
var handleBlob = async (response) => await response.blob();
|
|
2906
|
+
var handleImage = async (response) => {
|
|
2907
|
+
await ensureDom();
|
|
2908
|
+
const objectURL = URL.createObjectURL(await response.blob());
|
|
2909
|
+
return new Promise((resolve, reject) => {
|
|
2910
|
+
const img = new Image();
|
|
2911
|
+
img.onload = () => {
|
|
2912
|
+
URL.revokeObjectURL(objectURL);
|
|
2913
|
+
resolve(img);
|
|
2914
|
+
};
|
|
2915
|
+
img.onerror = () => {
|
|
2916
|
+
URL.revokeObjectURL(objectURL);
|
|
2917
|
+
reject(new Error("Image failed to load"));
|
|
2918
|
+
};
|
|
2919
|
+
img.src = objectURL;
|
|
2920
|
+
});
|
|
2921
|
+
};
|
|
2922
|
+
var handleBuffer = async (response) => await response.arrayBuffer();
|
|
2923
|
+
var handleReadableStream = async (response) => Promise.resolve(response.body);
|
|
2924
|
+
var handleXml = async (response) => {
|
|
2925
|
+
await ensureDom();
|
|
2926
|
+
return new DOMParser().parseFromString(purify.sanitize(await response.text()), HttpMediaType.XML);
|
|
2927
|
+
};
|
|
2928
|
+
var handleHtml = async (response) => {
|
|
2929
|
+
await ensureDom();
|
|
2930
|
+
return new DOMParser().parseFromString(purify.sanitize(await response.text()), HttpMediaType.HTML);
|
|
2931
|
+
};
|
|
2932
|
+
var handleHtmlFragment = async (response) => {
|
|
2933
|
+
await ensureDom();
|
|
2934
|
+
return document.createRange().createContextualFragment(purify.sanitize(await response.text()));
|
|
2935
|
+
};
|
|
2936
|
+
|
|
2937
|
+
// src/utils.ts
|
|
2938
|
+
var isRequestBodyMethod = (method) => method !== void 0 && requestBodyMethods.includes(method);
|
|
2939
|
+
var isRawBody = (body) => body instanceof FormData || body instanceof Blob || body instanceof ArrayBuffer || body instanceof ReadableStream || body instanceof URLSearchParams || ArrayBuffer.isView(body);
|
|
2940
|
+
var getCookieValue = (name) => {
|
|
2941
|
+
if (typeof document === "undefined" || !document.cookie) {
|
|
2942
|
+
return;
|
|
2943
|
+
}
|
|
2944
|
+
const prefix = `${name}=`;
|
|
2945
|
+
const cookies = document.cookie.split(";");
|
|
2946
|
+
for (let i = 0, length = cookies.length; i < length; i++) {
|
|
2947
|
+
const cookie = cookies[i].trim();
|
|
2948
|
+
if (cookie.startsWith(prefix)) {
|
|
2949
|
+
return decodeURIComponent(cookie.slice(prefix.length));
|
|
1939
2950
|
}
|
|
1940
|
-
return false;
|
|
1941
2951
|
}
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
2952
|
+
return void 0;
|
|
2953
|
+
};
|
|
2954
|
+
var serialize = (data) => JSON.stringify(data);
|
|
2955
|
+
var isString = (value) => value !== null && typeof value === "string";
|
|
2956
|
+
var isObject = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
2957
|
+
var objectMerge = (...objects) => {
|
|
2958
|
+
const length = objects.length;
|
|
2959
|
+
if (length === 0) {
|
|
2960
|
+
return void 0;
|
|
1949
2961
|
}
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
* If a key has no values, the value will be undefined.
|
|
1955
|
-
*
|
|
1956
|
-
* @override
|
|
1957
|
-
* @returns {Object} The Object to be serialized to JSON.
|
|
1958
|
-
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON_behavior}
|
|
1959
|
-
*/
|
|
1960
|
-
toJSON() {
|
|
1961
|
-
const obj = /* @__PURE__ */ Object.create(null);
|
|
1962
|
-
for (const [key, values] of super.entries()) {
|
|
1963
|
-
obj[key] = values.length === 1 ? values[0] : values;
|
|
2962
|
+
if (length === 1) {
|
|
2963
|
+
const [obj] = objects;
|
|
2964
|
+
if (!isObject(obj)) {
|
|
2965
|
+
return obj;
|
|
1964
2966
|
}
|
|
1965
|
-
return obj;
|
|
2967
|
+
return deepClone(obj);
|
|
1966
2968
|
}
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
2969
|
+
const target = {};
|
|
2970
|
+
for (const source of objects) {
|
|
2971
|
+
if (!isObject(source)) {
|
|
2972
|
+
return void 0;
|
|
2973
|
+
}
|
|
2974
|
+
for (const [property, sourceValue] of Object.entries(source)) {
|
|
2975
|
+
const targetValue = target[property];
|
|
2976
|
+
if (Array.isArray(sourceValue)) {
|
|
2977
|
+
target[property] = [...sourceValue, ...Array.isArray(targetValue) ? targetValue.filter((item) => !sourceValue.includes(item)) : []];
|
|
2978
|
+
} else if (isObject(sourceValue)) {
|
|
2979
|
+
target[property] = isObject(targetValue) ? objectMerge(targetValue, sourceValue) : deepClone(sourceValue);
|
|
2980
|
+
} else {
|
|
2981
|
+
target[property] = sourceValue;
|
|
1977
2982
|
}
|
|
1978
2983
|
}
|
|
1979
2984
|
}
|
|
1980
|
-
|
|
1981
|
-
* Returns an iterator that yields all key-value pairs in the map as arrays in their insertion order.
|
|
1982
|
-
*
|
|
1983
|
-
* @override
|
|
1984
|
-
* @yields {[string, *]} An iterator for the key-value pairs in the map.
|
|
1985
|
-
*/
|
|
1986
|
-
*[Symbol.iterator]() {
|
|
1987
|
-
yield* this.entries();
|
|
1988
|
-
}
|
|
1989
|
-
/**
|
|
1990
|
-
* Returns an iterable of key, value pairs for every entry in the parameters object.
|
|
1991
|
-
*
|
|
1992
|
-
* @private
|
|
1993
|
-
* @static
|
|
1994
|
-
* @param {Iterable<[string, *]>|Object} parameters The parameters to set.
|
|
1995
|
-
* @returns {Iterable<[string, *]>} An iterable of key, value pairs for every entry in the parameters object.
|
|
1996
|
-
*/
|
|
1997
|
-
static #entries(parameters) {
|
|
1998
|
-
return parameters[Symbol.iterator] ? parameters : Object.entries(parameters);
|
|
1999
|
-
}
|
|
2000
|
-
/**
|
|
2001
|
-
* A String value that is used in the creation of the default string description of an object.
|
|
2002
|
-
* Called by the built-in method {@link Object.prototype.toString}.
|
|
2003
|
-
*
|
|
2004
|
-
* @override
|
|
2005
|
-
* @returns {string} The default string description of this object.
|
|
2006
|
-
*/
|
|
2007
|
-
get [Symbol.toStringTag]() {
|
|
2008
|
-
return "ParameterMap";
|
|
2009
|
-
}
|
|
2985
|
+
return target;
|
|
2010
2986
|
};
|
|
2987
|
+
function deepClone(object) {
|
|
2988
|
+
if (isObject(object)) {
|
|
2989
|
+
const cloned = {};
|
|
2990
|
+
const keys = Object.keys(object);
|
|
2991
|
+
for (let i = 0, length = keys.length, key; i < length; i++) {
|
|
2992
|
+
key = keys[i];
|
|
2993
|
+
cloned[key] = deepClone(object[key]);
|
|
2994
|
+
}
|
|
2995
|
+
return cloned;
|
|
2996
|
+
}
|
|
2997
|
+
return object;
|
|
2998
|
+
}
|
|
2011
2999
|
|
|
2012
|
-
// src/transportr.
|
|
2013
|
-
var _handleText = async (response) => await response.text();
|
|
2014
|
-
var _handleScript = async (response) => {
|
|
2015
|
-
const objectURL = URL.createObjectURL(await response.blob());
|
|
2016
|
-
document.head.removeChild(document.head.appendChild(Object.assign(document.createElement("script"), { src: objectURL, type: http_media_type_default.JAVA_SCRIPT, async: true })));
|
|
2017
|
-
URL.revokeObjectURL(objectURL);
|
|
2018
|
-
return Promise.resolve();
|
|
2019
|
-
};
|
|
2020
|
-
var _handleCss = async (response) => {
|
|
2021
|
-
const objectURL = URL.createObjectURL(await response.blob());
|
|
2022
|
-
document.head.appendChild(Object.assign(document.createElement("link"), { href: objectURL, type: http_media_type_default.CSS, rel: "stylesheet" }));
|
|
2023
|
-
URL.revokeObjectURL(objectURL);
|
|
2024
|
-
return Promise.resolve();
|
|
2025
|
-
};
|
|
2026
|
-
var _handleJson = async (response) => await response.json();
|
|
2027
|
-
var _handleBlob = async (response) => await response.blob();
|
|
2028
|
-
var _handleImage = async (response) => URL.createObjectURL(await response.blob());
|
|
2029
|
-
var _handleBuffer = async (response) => await response.arrayBuffer();
|
|
2030
|
-
var _handleReadableStream = async (response) => response.body;
|
|
2031
|
-
var _handleXml = async (response) => new DOMParser().parseFromString(await response.text(), http_media_type_default.XML);
|
|
2032
|
-
var _handleHtml = async (response) => new DOMParser().parseFromString(await response.text(), http_media_type_default.HTML);
|
|
2033
|
-
var _handleHtmlFragment = async (response) => document.createRange().createContextualFragment(await response.text());
|
|
3000
|
+
// src/transportr.ts
|
|
2034
3001
|
var Transportr = class _Transportr {
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
static
|
|
2047
|
-
[
|
|
2048
|
-
[
|
|
2049
|
-
[
|
|
2050
|
-
[
|
|
2051
|
-
[
|
|
2052
|
-
[
|
|
2053
|
-
[
|
|
2054
|
-
[
|
|
2055
|
-
]
|
|
3002
|
+
_baseUrl;
|
|
3003
|
+
_options;
|
|
3004
|
+
subscribr;
|
|
3005
|
+
hooks = { beforeRequest: [], afterResponse: [], beforeError: [] };
|
|
3006
|
+
static globalSubscribr = new Subscribr();
|
|
3007
|
+
static globalHooks = { beforeRequest: [], afterResponse: [], beforeError: [] };
|
|
3008
|
+
static signalControllers = /* @__PURE__ */ new Set();
|
|
3009
|
+
/** Map of in-flight deduplicated requests keyed by URL + method */
|
|
3010
|
+
static inflightRequests = /* @__PURE__ */ new Map();
|
|
3011
|
+
/** Cache for parsed MediaType instances to avoid re-parsing the same content-type strings */
|
|
3012
|
+
static mediaTypeCache = new Map(Object.values(mediaTypes).map((mediaType) => [mediaType.toString(), mediaType]));
|
|
3013
|
+
static contentTypeHandlers = [
|
|
3014
|
+
[mediaTypes.TEXT.type, handleText],
|
|
3015
|
+
[mediaTypes.JSON.subtype, handleJson],
|
|
3016
|
+
[mediaTypes.BIN.subtype, handleReadableStream],
|
|
3017
|
+
[mediaTypes.HTML.subtype, handleHtml],
|
|
3018
|
+
[mediaTypes.XML.subtype, handleXml],
|
|
3019
|
+
[mediaTypes.PNG.type, handleImage],
|
|
3020
|
+
[mediaTypes.JAVA_SCRIPT.subtype, handleScript],
|
|
3021
|
+
[mediaTypes.CSS.subtype, handleCss]
|
|
3022
|
+
];
|
|
2056
3023
|
/**
|
|
2057
3024
|
* Create a new Transportr instance with the provided location or origin and context path.
|
|
2058
3025
|
*
|
|
2059
|
-
* @param
|
|
2060
|
-
* @param
|
|
3026
|
+
* @param url The URL for {@link fetch} requests.
|
|
3027
|
+
* @param options The default {@link RequestOptions} for this instance.
|
|
2061
3028
|
*/
|
|
2062
|
-
constructor(url = globalThis.location
|
|
2063
|
-
if (
|
|
2064
|
-
[url, options] = [globalThis.location
|
|
3029
|
+
constructor(url = globalThis.location?.origin ?? "http://localhost", options = {}) {
|
|
3030
|
+
if (isObject(url)) {
|
|
3031
|
+
[url, options] = [globalThis.location?.origin ?? "http://localhost", url];
|
|
2065
3032
|
}
|
|
2066
|
-
this
|
|
2067
|
-
this
|
|
2068
|
-
this
|
|
2069
|
-
}
|
|
2070
|
-
/**
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
static
|
|
2080
|
-
/**
|
|
2081
|
-
|
|
2082
|
-
* @see {@link HttpRequestHeader}
|
|
2083
|
-
* @constant {Object<string, HttpRequestHeader>}
|
|
2084
|
-
*/
|
|
2085
|
-
static RequestHeader = Object.freeze(http_request_headers_default);
|
|
2086
|
-
/**
|
|
2087
|
-
* @static
|
|
2088
|
-
* @constant {Object<string, HttpResponseHeader>}
|
|
2089
|
-
*/
|
|
2090
|
-
static ResponseHeader = Object.freeze(http_response_headers_default);
|
|
2091
|
-
/**
|
|
2092
|
-
* @static
|
|
2093
|
-
* @constant {Object<string, RequestCache>}
|
|
2094
|
-
*/
|
|
2095
|
-
static CachingPolicy = Object.freeze({
|
|
2096
|
-
DEFAULT: "default",
|
|
2097
|
-
FORCE_CACHE: "force-cache",
|
|
2098
|
-
NO_CACHE: "no-cache",
|
|
2099
|
-
NO_STORE: "no-store",
|
|
2100
|
-
ONLY_IF_CACHED: "only-if-cached",
|
|
2101
|
-
RELOAD: "reload"
|
|
2102
|
-
});
|
|
2103
|
-
/**
|
|
2104
|
-
* @static
|
|
2105
|
-
* @constant {Object<string, RequestCredentials>}
|
|
2106
|
-
*/
|
|
2107
|
-
static CredentialsPolicy = Object.freeze({
|
|
3033
|
+
this._baseUrl = _Transportr.getBaseUrl(url);
|
|
3034
|
+
this._options = _Transportr.createOptions(options, _Transportr.defaultRequestOptions);
|
|
3035
|
+
this.subscribr = new Subscribr();
|
|
3036
|
+
}
|
|
3037
|
+
/** HTTP Media Types */
|
|
3038
|
+
static MediaType = HttpMediaType;
|
|
3039
|
+
/** HTTP Request Methods */
|
|
3040
|
+
static RequestMethod = HttpRequestMethod;
|
|
3041
|
+
/** HTTP Request Headers */
|
|
3042
|
+
static RequestHeader = HttpRequestHeader;
|
|
3043
|
+
/** HTTP Response Headers */
|
|
3044
|
+
static ResponseHeader = HttpResponseHeader;
|
|
3045
|
+
/** Request Caching Policy */
|
|
3046
|
+
static CachingPolicy = RequestCachingPolicy;
|
|
3047
|
+
/** Credentials Policy */
|
|
3048
|
+
static CredentialsPolicy = {
|
|
2108
3049
|
INCLUDE: "include",
|
|
2109
3050
|
OMIT: "omit",
|
|
2110
3051
|
SAME_ORIGIN: "same-origin"
|
|
2111
|
-
}
|
|
2112
|
-
/**
|
|
2113
|
-
|
|
2114
|
-
* @constant {Object<string, RequestMode>}
|
|
2115
|
-
*/
|
|
2116
|
-
static RequestMode = Object.freeze({
|
|
3052
|
+
};
|
|
3053
|
+
/** Request Modes */
|
|
3054
|
+
static RequestModes = {
|
|
2117
3055
|
CORS: "cors",
|
|
2118
3056
|
NAVIGATE: "navigate",
|
|
2119
3057
|
NO_CORS: "no-cors",
|
|
2120
3058
|
SAME_ORIGIN: "same-origin"
|
|
2121
|
-
}
|
|
2122
|
-
/**
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
3059
|
+
};
|
|
3060
|
+
/** Request Priorities */
|
|
3061
|
+
static RequestPriorities = {
|
|
3062
|
+
HIGH: "high",
|
|
3063
|
+
LOW: "low",
|
|
3064
|
+
AUTO: "auto"
|
|
3065
|
+
};
|
|
3066
|
+
/** Redirect Policies */
|
|
3067
|
+
static RedirectPolicies = {
|
|
2127
3068
|
ERROR: "error",
|
|
2128
3069
|
FOLLOW: "follow",
|
|
2129
3070
|
MANUAL: "manual"
|
|
2130
|
-
}
|
|
2131
|
-
/**
|
|
2132
|
-
|
|
2133
|
-
* @constant {Object<string, ReferrerPolicy>}
|
|
2134
|
-
*/
|
|
2135
|
-
static ReferrerPolicy = Object.freeze({
|
|
3071
|
+
};
|
|
3072
|
+
/** Referrer Policies */
|
|
3073
|
+
static ReferrerPolicy = {
|
|
2136
3074
|
NO_REFERRER: "no-referrer",
|
|
2137
3075
|
NO_REFERRER_WHEN_DOWNGRADE: "no-referrer-when-downgrade",
|
|
2138
3076
|
ORIGIN: "origin",
|
|
@@ -2141,555 +3079,867 @@ var Transportr = class _Transportr {
|
|
|
2141
3079
|
STRICT_ORIGIN: "strict-origin",
|
|
2142
3080
|
STRICT_ORIGIN_WHEN_CROSS_ORIGIN: "strict-origin-when-cross-origin",
|
|
2143
3081
|
UNSAFE_URL: "unsafe-url"
|
|
2144
|
-
}
|
|
2145
|
-
/**
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
* @private
|
|
2152
|
-
* @static
|
|
2153
|
-
* @type {RequestOptions}
|
|
2154
|
-
*/
|
|
2155
|
-
static #defaultRequestOptions = Object.freeze({
|
|
2156
|
-
body: null,
|
|
2157
|
-
cache: _Transportr.CachingPolicy.NO_STORE,
|
|
3082
|
+
};
|
|
3083
|
+
/** Request Events */
|
|
3084
|
+
static RequestEvents = RequestEvent;
|
|
3085
|
+
/** Default Request Options */
|
|
3086
|
+
static defaultRequestOptions = {
|
|
3087
|
+
body: void 0,
|
|
3088
|
+
cache: RequestCachingPolicy.NO_STORE,
|
|
2158
3089
|
credentials: _Transportr.CredentialsPolicy.SAME_ORIGIN,
|
|
2159
|
-
headers: { [
|
|
2160
|
-
searchParams:
|
|
3090
|
+
headers: new Headers({ [HttpRequestHeader.CONTENT_TYPE]: defaultMediaType, [HttpRequestHeader.ACCEPT]: defaultMediaType }),
|
|
3091
|
+
searchParams: void 0,
|
|
2161
3092
|
integrity: void 0,
|
|
2162
3093
|
keepalive: void 0,
|
|
2163
|
-
method:
|
|
2164
|
-
mode: _Transportr.
|
|
2165
|
-
|
|
3094
|
+
method: HttpRequestMethod.GET,
|
|
3095
|
+
mode: _Transportr.RequestModes.CORS,
|
|
3096
|
+
priority: _Transportr.RequestPriorities.AUTO,
|
|
3097
|
+
redirect: _Transportr.RedirectPolicies.FOLLOW,
|
|
2166
3098
|
referrer: "about:client",
|
|
2167
3099
|
referrerPolicy: _Transportr.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
|
|
2168
3100
|
signal: void 0,
|
|
2169
3101
|
timeout: 3e4,
|
|
2170
|
-
global: true
|
|
2171
|
-
|
|
2172
|
-
});
|
|
3102
|
+
global: true
|
|
3103
|
+
};
|
|
2173
3104
|
/**
|
|
2174
3105
|
* Returns a {@link EventRegistration} used for subscribing to global events.
|
|
2175
3106
|
*
|
|
2176
|
-
* @
|
|
2177
|
-
* @param
|
|
2178
|
-
* @param
|
|
2179
|
-
* @
|
|
2180
|
-
* @returns {EventRegistration} A new {@link EventRegistration} instance.
|
|
3107
|
+
* @param event The event to subscribe to.
|
|
3108
|
+
* @param handler The event handler.
|
|
3109
|
+
* @param context The context to bind the handler to.
|
|
3110
|
+
* @returns A new {@link EventRegistration} instance.
|
|
2181
3111
|
*/
|
|
2182
3112
|
static register(event, handler, context) {
|
|
2183
|
-
return _Transportr
|
|
3113
|
+
return _Transportr.globalSubscribr.subscribe(event, handler, context);
|
|
2184
3114
|
}
|
|
2185
3115
|
/**
|
|
2186
3116
|
* Removes a {@link EventRegistration} from the global event handler.
|
|
2187
3117
|
*
|
|
2188
|
-
* @
|
|
2189
|
-
* @
|
|
2190
|
-
* @returns {boolean} True if the {@link EventRegistration} was removed, false otherwise.
|
|
3118
|
+
* @param eventRegistration The {@link EventRegistration} to remove.
|
|
3119
|
+
* @returns True if the {@link EventRegistration} was removed, false otherwise.
|
|
2191
3120
|
*/
|
|
2192
3121
|
static unregister(eventRegistration) {
|
|
2193
|
-
return _Transportr
|
|
3122
|
+
return _Transportr.globalSubscribr.unsubscribe(eventRegistration);
|
|
2194
3123
|
}
|
|
2195
3124
|
/**
|
|
2196
3125
|
* Aborts all active requests.
|
|
2197
3126
|
* This is useful for when the user navigates away from the current page.
|
|
2198
|
-
* This will also clear the {@link Transportr#
|
|
2199
|
-
*
|
|
2200
|
-
* @static
|
|
2201
|
-
* @returns {void}
|
|
3127
|
+
* This will also clear the {@link Transportr#signalControllers} set.
|
|
2202
3128
|
*/
|
|
2203
3129
|
static abortAll() {
|
|
2204
|
-
for (const
|
|
2205
|
-
|
|
3130
|
+
for (const signalController of this.signalControllers) {
|
|
3131
|
+
signalController.abort(abortEvent());
|
|
3132
|
+
}
|
|
3133
|
+
this.signalControllers.clear();
|
|
3134
|
+
}
|
|
3135
|
+
/**
|
|
3136
|
+
* Registers a custom content-type response handler.
|
|
3137
|
+
* The handler will be matched against response content-type headers using MediaType matching.
|
|
3138
|
+
* New handlers are prepended so they take priority over built-in handlers.
|
|
3139
|
+
*
|
|
3140
|
+
* @param contentType The content-type string to match (e.g. 'application/pdf', 'text', 'csv').
|
|
3141
|
+
* @param handler The response handler function.
|
|
3142
|
+
*/
|
|
3143
|
+
static registerContentTypeHandler(contentType, handler) {
|
|
3144
|
+
_Transportr.contentTypeHandlers.unshift([contentType, handler]);
|
|
3145
|
+
}
|
|
3146
|
+
/**
|
|
3147
|
+
* Removes a previously registered content-type response handler.
|
|
3148
|
+
*
|
|
3149
|
+
* @param contentType The content-type string to remove.
|
|
3150
|
+
* @returns True if the handler was found and removed, false otherwise.
|
|
3151
|
+
*/
|
|
3152
|
+
static unregisterContentTypeHandler(contentType) {
|
|
3153
|
+
const index = _Transportr.contentTypeHandlers.findIndex(([type]) => type === contentType);
|
|
3154
|
+
if (index === -1) {
|
|
3155
|
+
return false;
|
|
3156
|
+
}
|
|
3157
|
+
_Transportr.contentTypeHandlers.splice(index, 1);
|
|
3158
|
+
return true;
|
|
3159
|
+
}
|
|
3160
|
+
/**
|
|
3161
|
+
* Registers global lifecycle hooks that run on all requests from all instances.
|
|
3162
|
+
* Global hooks execute before instance and per-request hooks.
|
|
3163
|
+
*
|
|
3164
|
+
* @param hooks The hooks to register globally.
|
|
3165
|
+
*/
|
|
3166
|
+
static addHooks(hooks) {
|
|
3167
|
+
if (hooks.beforeRequest) {
|
|
3168
|
+
_Transportr.globalHooks.beforeRequest.push(...hooks.beforeRequest);
|
|
2206
3169
|
}
|
|
2207
|
-
|
|
3170
|
+
if (hooks.afterResponse) {
|
|
3171
|
+
_Transportr.globalHooks.afterResponse.push(...hooks.afterResponse);
|
|
3172
|
+
}
|
|
3173
|
+
if (hooks.beforeError) {
|
|
3174
|
+
_Transportr.globalHooks.beforeError.push(...hooks.beforeError);
|
|
3175
|
+
}
|
|
3176
|
+
}
|
|
3177
|
+
/**
|
|
3178
|
+
* Removes all global lifecycle hooks.
|
|
3179
|
+
*/
|
|
3180
|
+
static clearHooks() {
|
|
3181
|
+
_Transportr.globalHooks = { beforeRequest: [], afterResponse: [], beforeError: [] };
|
|
3182
|
+
}
|
|
3183
|
+
/**
|
|
3184
|
+
* Tears down all global state: aborts in-flight requests, clears global event subscriptions,
|
|
3185
|
+
* hooks, in-flight deduplication map, and media type cache (retaining built-in entries).
|
|
3186
|
+
*/
|
|
3187
|
+
static unregisterAll() {
|
|
3188
|
+
_Transportr.abortAll();
|
|
3189
|
+
_Transportr.globalSubscribr = new Subscribr();
|
|
3190
|
+
_Transportr.clearHooks();
|
|
3191
|
+
_Transportr.inflightRequests.clear();
|
|
2208
3192
|
}
|
|
2209
3193
|
/**
|
|
2210
3194
|
* It returns the base {@link URL} for the API.
|
|
2211
3195
|
*
|
|
2212
|
-
* @returns
|
|
3196
|
+
* @returns The baseUrl property.
|
|
2213
3197
|
*/
|
|
2214
3198
|
get baseUrl() {
|
|
2215
|
-
return this
|
|
3199
|
+
return this._baseUrl;
|
|
2216
3200
|
}
|
|
2217
3201
|
/**
|
|
2218
3202
|
* Registers an event handler with a {@link Transportr} instance.
|
|
2219
3203
|
*
|
|
2220
|
-
* @param
|
|
2221
|
-
* @param
|
|
2222
|
-
* @param
|
|
2223
|
-
* @returns
|
|
3204
|
+
* @param event The name of the event to listen for.
|
|
3205
|
+
* @param handler The function to call when the event is triggered.
|
|
3206
|
+
* @param context The context to bind to the handler.
|
|
3207
|
+
* @returns An object that can be used to remove the event handler.
|
|
2224
3208
|
*/
|
|
2225
3209
|
register(event, handler, context) {
|
|
2226
|
-
return this
|
|
3210
|
+
return this.subscribr.subscribe(event, handler, context);
|
|
2227
3211
|
}
|
|
2228
3212
|
/**
|
|
2229
3213
|
* Unregisters an event handler from a {@link Transportr} instance.
|
|
2230
3214
|
*
|
|
2231
|
-
* @param
|
|
2232
|
-
* @returns {
|
|
3215
|
+
* @param eventRegistration The event registration to remove.
|
|
3216
|
+
* @returns True if the {@link EventRegistration} was removed, false otherwise.
|
|
2233
3217
|
*/
|
|
2234
3218
|
unregister(eventRegistration) {
|
|
2235
|
-
this
|
|
3219
|
+
return this.subscribr.unsubscribe(eventRegistration);
|
|
3220
|
+
}
|
|
3221
|
+
/**
|
|
3222
|
+
* Registers instance-level lifecycle hooks that run on all requests from this instance.
|
|
3223
|
+
* Instance hooks execute after global hooks but before per-request hooks.
|
|
3224
|
+
*
|
|
3225
|
+
* @param hooks The hooks to register on this instance.
|
|
3226
|
+
* @returns This instance for method chaining.
|
|
3227
|
+
*/
|
|
3228
|
+
addHooks(hooks) {
|
|
3229
|
+
if (hooks.beforeRequest) {
|
|
3230
|
+
this.hooks.beforeRequest.push(...hooks.beforeRequest);
|
|
3231
|
+
}
|
|
3232
|
+
if (hooks.afterResponse) {
|
|
3233
|
+
this.hooks.afterResponse.push(...hooks.afterResponse);
|
|
3234
|
+
}
|
|
3235
|
+
if (hooks.beforeError) {
|
|
3236
|
+
this.hooks.beforeError.push(...hooks.beforeError);
|
|
3237
|
+
}
|
|
3238
|
+
return this;
|
|
3239
|
+
}
|
|
3240
|
+
/**
|
|
3241
|
+
* Removes all instance-level lifecycle hooks.
|
|
3242
|
+
* @returns This instance for method chaining.
|
|
3243
|
+
*/
|
|
3244
|
+
clearHooks() {
|
|
3245
|
+
this.hooks.beforeRequest.length = 0;
|
|
3246
|
+
this.hooks.afterResponse.length = 0;
|
|
3247
|
+
this.hooks.beforeError.length = 0;
|
|
3248
|
+
return this;
|
|
3249
|
+
}
|
|
3250
|
+
/**
|
|
3251
|
+
* Tears down this instance: clears all instance subscriptions and hooks.
|
|
3252
|
+
* The instance should not be used after calling this method.
|
|
3253
|
+
*/
|
|
3254
|
+
destroy() {
|
|
3255
|
+
this.clearHooks();
|
|
3256
|
+
this.subscribr.destroy();
|
|
2236
3257
|
}
|
|
2237
3258
|
/**
|
|
2238
3259
|
* This function returns a promise that resolves to the result of a request to the specified path with
|
|
2239
3260
|
* the specified options, where the method is GET.
|
|
2240
3261
|
*
|
|
2241
3262
|
* @async
|
|
2242
|
-
* @param
|
|
2243
|
-
* @param
|
|
2244
|
-
* @returns
|
|
3263
|
+
* @param path The path to the resource you want to get.
|
|
3264
|
+
* @param options The options for the request.
|
|
3265
|
+
* @returns A promise that resolves to the response of the request.
|
|
2245
3266
|
*/
|
|
2246
3267
|
async get(path, options) {
|
|
2247
|
-
return this
|
|
3268
|
+
return this._get(path, options);
|
|
2248
3269
|
}
|
|
2249
3270
|
/**
|
|
2250
3271
|
* This function makes a POST request to the given path with the given body and options.
|
|
2251
3272
|
*
|
|
2252
3273
|
* @async
|
|
2253
|
-
* @
|
|
2254
|
-
* @param
|
|
2255
|
-
* @param
|
|
2256
|
-
* @returns
|
|
2257
|
-
*/
|
|
2258
|
-
async post(path,
|
|
2259
|
-
if (
|
|
2260
|
-
[path,
|
|
3274
|
+
* @template T The expected response type (defaults to ResponseBody)
|
|
3275
|
+
* @param path The path to the endpoint you want to call.
|
|
3276
|
+
* @param options The options for the request.
|
|
3277
|
+
* @returns A promise that resolves to the response body.
|
|
3278
|
+
*/
|
|
3279
|
+
async post(path, options) {
|
|
3280
|
+
if (typeof path !== "string") {
|
|
3281
|
+
[path, options] = [void 0, path];
|
|
2261
3282
|
}
|
|
2262
|
-
return this
|
|
3283
|
+
return this.execute(path, options, { method: HttpRequestMethod.POST });
|
|
2263
3284
|
}
|
|
2264
3285
|
/**
|
|
2265
3286
|
* This function returns a promise that resolves to the result of a request to the specified path with
|
|
2266
3287
|
* the specified options, where the method is PUT.
|
|
2267
3288
|
*
|
|
2268
3289
|
* @async
|
|
2269
|
-
* @
|
|
2270
|
-
* @param
|
|
2271
|
-
* @
|
|
3290
|
+
* @template T The expected response type (defaults to ResponseBody)
|
|
3291
|
+
* @param path The path to the endpoint you want to call.
|
|
3292
|
+
* @param options The options for the request.
|
|
3293
|
+
* @returns The return value of the #request method.
|
|
2272
3294
|
*/
|
|
2273
3295
|
async put(path, options) {
|
|
2274
|
-
return this
|
|
3296
|
+
return this.execute(path, options, { method: HttpRequestMethod.PUT });
|
|
2275
3297
|
}
|
|
2276
3298
|
/**
|
|
2277
3299
|
* It takes a path and options, and returns a request with the method set to PATCH.
|
|
2278
3300
|
*
|
|
2279
3301
|
* @async
|
|
2280
|
-
* @
|
|
2281
|
-
* @param
|
|
2282
|
-
* @
|
|
3302
|
+
* @template T The expected response type (defaults to ResponseBody)
|
|
3303
|
+
* @param path The path to the endpoint you want to hit.
|
|
3304
|
+
* @param options The options for the request.
|
|
3305
|
+
* @returns A promise that resolves to the response of the request.
|
|
2283
3306
|
*/
|
|
2284
3307
|
async patch(path, options) {
|
|
2285
|
-
return this
|
|
3308
|
+
return this.execute(path, options, { method: HttpRequestMethod.PATCH });
|
|
2286
3309
|
}
|
|
2287
3310
|
/**
|
|
2288
3311
|
* It takes a path and options, and returns a request with the method set to DELETE.
|
|
2289
3312
|
*
|
|
2290
3313
|
* @async
|
|
2291
|
-
* @param
|
|
2292
|
-
* @param
|
|
2293
|
-
* @returns
|
|
3314
|
+
* @param path The path to the resource you want to access.
|
|
3315
|
+
* @param options The options for the request.
|
|
3316
|
+
* @returns The result of the request.
|
|
2294
3317
|
*/
|
|
2295
3318
|
async delete(path, options) {
|
|
2296
|
-
return this
|
|
3319
|
+
return this.execute(path, options, { method: HttpRequestMethod.DELETE });
|
|
2297
3320
|
}
|
|
2298
3321
|
/**
|
|
2299
3322
|
* Returns the response headers of a request to the given path.
|
|
2300
3323
|
*
|
|
2301
3324
|
* @async
|
|
2302
|
-
* @param
|
|
2303
|
-
* @param
|
|
2304
|
-
* @returns
|
|
3325
|
+
* @param path The path to the resource you want to access.
|
|
3326
|
+
* @param options The options for the request.
|
|
3327
|
+
* @returns A promise that resolves to the response object.
|
|
2305
3328
|
*/
|
|
2306
3329
|
async head(path, options) {
|
|
2307
|
-
return this
|
|
3330
|
+
return this.execute(path, options, { method: HttpRequestMethod.HEAD });
|
|
2308
3331
|
}
|
|
2309
3332
|
/**
|
|
2310
3333
|
* It returns a promise that resolves to the allowed request methods for the given resource path.
|
|
2311
3334
|
*
|
|
2312
3335
|
* @async
|
|
2313
|
-
* @param
|
|
2314
|
-
* @param
|
|
2315
|
-
* @returns
|
|
3336
|
+
* @param path The path to the resource.
|
|
3337
|
+
* @param options The options for the request.
|
|
3338
|
+
* @returns A promise that resolves to an array of allowed request methods for this resource.
|
|
2316
3339
|
*/
|
|
2317
|
-
async options(path, options) {
|
|
2318
|
-
|
|
2319
|
-
|
|
3340
|
+
async options(path, options = {}) {
|
|
3341
|
+
if (isObject(path)) {
|
|
3342
|
+
[path, options] = [void 0, path];
|
|
3343
|
+
}
|
|
3344
|
+
const requestConfig = this.processRequestOptions(options, { method: HttpRequestMethod.OPTIONS });
|
|
3345
|
+
const { requestOptions } = requestConfig;
|
|
3346
|
+
const requestHooks = requestOptions.hooks;
|
|
3347
|
+
let url = _Transportr.createUrl(this._baseUrl, path, requestOptions.searchParams);
|
|
3348
|
+
const beforeRequestHookSets = [_Transportr.globalHooks.beforeRequest, this.hooks.beforeRequest, requestHooks?.beforeRequest];
|
|
3349
|
+
for (const hooks of beforeRequestHookSets) {
|
|
3350
|
+
if (!hooks) {
|
|
3351
|
+
continue;
|
|
3352
|
+
}
|
|
3353
|
+
for (const hook of hooks) {
|
|
3354
|
+
const result = await hook(requestOptions, url);
|
|
3355
|
+
if (result) {
|
|
3356
|
+
Object.assign(requestOptions, result);
|
|
3357
|
+
if (result.searchParams !== void 0) {
|
|
3358
|
+
url = _Transportr.createUrl(this._baseUrl, path, requestOptions.searchParams);
|
|
3359
|
+
}
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
let response = await this._request(path, requestConfig);
|
|
3364
|
+
const afterResponseHookSets = [_Transportr.globalHooks.afterResponse, this.hooks.afterResponse, requestHooks?.afterResponse];
|
|
3365
|
+
for (const hooks of afterResponseHookSets) {
|
|
3366
|
+
if (!hooks) {
|
|
3367
|
+
continue;
|
|
3368
|
+
}
|
|
3369
|
+
for (const hook of hooks) {
|
|
3370
|
+
const result = await hook(response, requestOptions);
|
|
3371
|
+
if (result) {
|
|
3372
|
+
response = result;
|
|
3373
|
+
}
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
const allowedMethods = response.headers.get("allow")?.split(",").map((method) => method.trim());
|
|
3377
|
+
this.publish({ name: RequestEvent.SUCCESS, data: allowedMethods, global: options.global });
|
|
3378
|
+
return allowedMethods;
|
|
2320
3379
|
}
|
|
2321
3380
|
/**
|
|
2322
|
-
* It takes a path and options, and makes a request to the server
|
|
2323
|
-
*
|
|
3381
|
+
* It takes a path and options, and makes a request to the server
|
|
2324
3382
|
* @async
|
|
2325
|
-
* @param
|
|
2326
|
-
* @param
|
|
2327
|
-
* @returns
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
3383
|
+
* @param path The path to the endpoint you want to hit.
|
|
3384
|
+
* @param options The options for the request.
|
|
3385
|
+
* @returns The return value of the function is the return value of the function that is passed to the `then` method of the promise returned by the `fetch` method.
|
|
3386
|
+
* @throws {HttpError} If an error occurs during the request.
|
|
3387
|
+
*/
|
|
3388
|
+
async request(path, options = {}) {
|
|
3389
|
+
if (isObject(path)) {
|
|
3390
|
+
[path, options] = [void 0, path];
|
|
3391
|
+
}
|
|
3392
|
+
const response = await this._request(path, this.processRequestOptions(options, {}));
|
|
3393
|
+
this.publish({ name: RequestEvent.SUCCESS, data: response, global: options.global });
|
|
3394
|
+
return response;
|
|
2331
3395
|
}
|
|
2332
3396
|
/**
|
|
2333
|
-
* It gets
|
|
3397
|
+
* It gets the JSON representation of the resource at the given path.
|
|
2334
3398
|
*
|
|
2335
3399
|
* @async
|
|
2336
|
-
* @
|
|
2337
|
-
* @param
|
|
2338
|
-
* @
|
|
3400
|
+
* @template T The expected JSON response type (defaults to JsonObject)
|
|
3401
|
+
* @param path The path to the resource.
|
|
3402
|
+
* @param options The options object to pass to the request.
|
|
3403
|
+
* @returns A promise that resolves to the response body as a typed JSON value.
|
|
2339
3404
|
*/
|
|
2340
3405
|
async getJson(path, options) {
|
|
2341
|
-
return this
|
|
3406
|
+
return this._get(path, options, { headers: { [HttpRequestHeader.ACCEPT]: `${mediaTypes.JSON}` } }, handleJson);
|
|
2342
3407
|
}
|
|
2343
3408
|
/**
|
|
2344
3409
|
* It gets the XML representation of the resource at the given path.
|
|
2345
3410
|
*
|
|
2346
3411
|
* @async
|
|
2347
|
-
* @param
|
|
2348
|
-
* @param
|
|
2349
|
-
* @returns
|
|
3412
|
+
* @param path The path to the resource you want to get.
|
|
3413
|
+
* @param options The options for the request.
|
|
3414
|
+
* @returns The result of the function call to #get.
|
|
2350
3415
|
*/
|
|
2351
3416
|
async getXml(path, options) {
|
|
2352
|
-
return this
|
|
3417
|
+
return this._get(path, options, { headers: { [HttpRequestHeader.ACCEPT]: `${mediaTypes.XML}` } }, handleXml);
|
|
2353
3418
|
}
|
|
2354
3419
|
/**
|
|
2355
3420
|
* Get the HTML content of the specified path.
|
|
3421
|
+
* When a selector is provided, returns only the first matching element from the parsed document.
|
|
2356
3422
|
*
|
|
2357
|
-
* @todo Add way to return portion of the retrieved HTML using a selector. Like jQuery.
|
|
2358
3423
|
* @async
|
|
2359
|
-
* @param
|
|
2360
|
-
* @param
|
|
2361
|
-
* @
|
|
2362
|
-
*
|
|
3424
|
+
* @param path The path to the resource.
|
|
3425
|
+
* @param options The options for the request.
|
|
3426
|
+
* @param selector An optional CSS selector to extract a specific element from the parsed HTML.
|
|
3427
|
+
* @returns A promise that resolves to a Document, an Element (if selector matched), or void.
|
|
2363
3428
|
*/
|
|
2364
|
-
async getHtml(path, options) {
|
|
2365
|
-
|
|
3429
|
+
async getHtml(path, options, selector) {
|
|
3430
|
+
const doc = await this._get(path, options, { headers: { [HttpRequestHeader.ACCEPT]: `${mediaTypes.HTML}` } }, handleHtml);
|
|
3431
|
+
return selector && doc ? doc.querySelector(selector) : doc;
|
|
2366
3432
|
}
|
|
2367
3433
|
/**
|
|
2368
3434
|
* It returns a promise that resolves to the HTML fragment at the given path.
|
|
3435
|
+
* When a selector is provided, returns only the first matching element from the parsed fragment.
|
|
2369
3436
|
*
|
|
2370
|
-
* @todo Add way to return portion of the retrieved HTML using a selector. Like jQuery.
|
|
2371
3437
|
* @async
|
|
2372
|
-
* @param
|
|
2373
|
-
* @param
|
|
2374
|
-
* @
|
|
3438
|
+
* @param path The path to the resource.
|
|
3439
|
+
* @param options The options for the request.
|
|
3440
|
+
* @param selector An optional CSS selector to extract a specific element from the parsed fragment.
|
|
3441
|
+
* @returns A promise that resolves to a DocumentFragment, an Element (if selector matched), or void.
|
|
2375
3442
|
*/
|
|
2376
|
-
async getHtmlFragment(path, options) {
|
|
2377
|
-
|
|
3443
|
+
async getHtmlFragment(path, options, selector) {
|
|
3444
|
+
const fragment = await this._get(path, options, { headers: { [HttpRequestHeader.ACCEPT]: `${mediaTypes.HTML}` } }, handleHtmlFragment);
|
|
3445
|
+
return selector && fragment ? fragment.querySelector(selector) : fragment;
|
|
2378
3446
|
}
|
|
2379
3447
|
/**
|
|
2380
|
-
* It gets a script from the server, and appends the script to the
|
|
2381
|
-
*
|
|
2382
|
-
*
|
|
2383
|
-
* @
|
|
2384
|
-
* @param {string} [path] The path to the script.
|
|
2385
|
-
* @param {RequestOptions} [options] The options for the request.
|
|
2386
|
-
* @returns {Promise<void>} A promise that has been resolved.
|
|
3448
|
+
* It gets a script from the server, and appends the script to the Document HTMLHeadElement
|
|
3449
|
+
* @param path The path to the script.
|
|
3450
|
+
* @param options The options for the request.
|
|
3451
|
+
* @returns A promise that resolves to void.
|
|
2387
3452
|
*/
|
|
2388
3453
|
async getScript(path, options) {
|
|
2389
|
-
return this
|
|
3454
|
+
return this._get(path, options, { headers: { [HttpRequestHeader.ACCEPT]: `${mediaTypes.JAVA_SCRIPT}` } }, handleScript);
|
|
2390
3455
|
}
|
|
2391
3456
|
/**
|
|
2392
|
-
* Gets a stylesheet from the server, and adds it as a
|
|
2393
|
-
*
|
|
2394
|
-
* @
|
|
2395
|
-
* @
|
|
2396
|
-
* @param {RequestOptions} [options] The options for the request.
|
|
2397
|
-
* @returns {Promise<void>} A promise that has been resolved.
|
|
3457
|
+
* Gets a stylesheet from the server, and adds it as a Blob URL.
|
|
3458
|
+
* @param path The path to the stylesheet.
|
|
3459
|
+
* @param options The options for the request.
|
|
3460
|
+
* @returns A promise that resolves to void.
|
|
2398
3461
|
*/
|
|
2399
3462
|
async getStylesheet(path, options) {
|
|
2400
|
-
return this
|
|
3463
|
+
return this._get(path, options, { headers: { [HttpRequestHeader.ACCEPT]: `${mediaTypes.CSS}` } }, handleCss);
|
|
2401
3464
|
}
|
|
2402
3465
|
/**
|
|
2403
3466
|
* It returns a blob from the specified path.
|
|
2404
|
-
*
|
|
2405
|
-
* @
|
|
2406
|
-
* @
|
|
2407
|
-
* @param {RequestOptions} [options] The options for the request.
|
|
2408
|
-
* @returns {Promise<Blob>} A promise that resolves to a blob.
|
|
3467
|
+
* @param path The path to the resource.
|
|
3468
|
+
* @param options The options for the request.
|
|
3469
|
+
* @returns A promise that resolves to a Blob or void.
|
|
2409
3470
|
*/
|
|
2410
3471
|
async getBlob(path, options) {
|
|
2411
|
-
return this
|
|
3472
|
+
return this._get(path, options, { headers: { [HttpRequestHeader.ACCEPT]: HttpMediaType.BIN } }, handleBlob);
|
|
2412
3473
|
}
|
|
2413
3474
|
/**
|
|
2414
|
-
* It returns a promise that resolves to an
|
|
2415
|
-
*
|
|
2416
|
-
*
|
|
2417
|
-
* @param
|
|
2418
|
-
* @param
|
|
2419
|
-
* @returns
|
|
3475
|
+
* It returns a promise that resolves to an `HTMLImageElement`.
|
|
3476
|
+
* The object URL created to load the image is automatically revoked to prevent memory leaks.
|
|
3477
|
+
* Works in both browser and Node.js (via JSDOM) environments.
|
|
3478
|
+
* @param path The path to the image.
|
|
3479
|
+
* @param options The options for the request.
|
|
3480
|
+
* @returns A promise that resolves to an `HTMLImageElement` or `void`.
|
|
2420
3481
|
*/
|
|
2421
3482
|
async getImage(path, options) {
|
|
2422
|
-
return this
|
|
3483
|
+
return this._get(path, options, { headers: { [HttpRequestHeader.ACCEPT]: "image/*" } }, handleImage);
|
|
2423
3484
|
}
|
|
2424
3485
|
/**
|
|
2425
3486
|
* It gets a buffer from the specified path
|
|
2426
|
-
*
|
|
2427
|
-
* @
|
|
2428
|
-
* @
|
|
2429
|
-
* @param {RequestOptions} [options] The options for the request.
|
|
2430
|
-
* @returns {Promise<ArrayBuffer>} A promise that resolves to a buffer.
|
|
3487
|
+
* @param path The path to the resource.
|
|
3488
|
+
* @param options The options for the request.
|
|
3489
|
+
* @returns A promise that resolves to an ArrayBuffer or void.
|
|
2431
3490
|
*/
|
|
2432
3491
|
async getBuffer(path, options) {
|
|
2433
|
-
return this
|
|
3492
|
+
return this._get(path, options, { headers: { [HttpRequestHeader.ACCEPT]: HttpMediaType.BIN } }, handleBuffer);
|
|
2434
3493
|
}
|
|
2435
3494
|
/**
|
|
2436
3495
|
* It returns a readable stream of the response body from the specified path.
|
|
2437
|
-
*
|
|
2438
|
-
* @
|
|
2439
|
-
* @
|
|
2440
|
-
* @param {RequestOptions} [options] The options for the request.
|
|
2441
|
-
* @returns {Promise<ReadableStream<Uint8Array>>} A readable stream.
|
|
3496
|
+
* @param path The path to the resource.
|
|
3497
|
+
* @param options The options for the request.
|
|
3498
|
+
* @returns A promise that resolves to a ReadableStream, null, or void.
|
|
2442
3499
|
*/
|
|
2443
3500
|
async getStream(path, options) {
|
|
2444
|
-
return this
|
|
3501
|
+
return this._get(path, options, { headers: { [HttpRequestHeader.ACCEPT]: HttpMediaType.BIN } }, handleReadableStream);
|
|
2445
3502
|
}
|
|
2446
3503
|
/**
|
|
2447
|
-
*
|
|
2448
|
-
* given response handler with the response.
|
|
2449
|
-
*
|
|
2450
|
-
* @private
|
|
3504
|
+
* Handles a GET request.
|
|
2451
3505
|
* @async
|
|
2452
|
-
* @param
|
|
2453
|
-
* @param
|
|
2454
|
-
* @param
|
|
2455
|
-
* @param
|
|
2456
|
-
* @returns
|
|
2457
|
-
*/
|
|
2458
|
-
async
|
|
2459
|
-
return this
|
|
3506
|
+
* @param path The path to the resource.
|
|
3507
|
+
* @param userOptions The user options for the request.
|
|
3508
|
+
* @param options The options for the request.
|
|
3509
|
+
* @param responseHandler The response handler for the request.
|
|
3510
|
+
* @returns A promise that resolves to the response body or void.
|
|
3511
|
+
*/
|
|
3512
|
+
async _get(path, userOptions, options = {}, responseHandler) {
|
|
3513
|
+
return this.execute(path, userOptions, { ...options, method: HttpRequestMethod.GET, body: void 0 }, responseHandler);
|
|
3514
|
+
}
|
|
3515
|
+
/**
|
|
3516
|
+
* It processes the request options and returns a new object with the processed options.
|
|
3517
|
+
* @param path The path to the resource.
|
|
3518
|
+
* @param processedRequestOptions The user options for the request.
|
|
3519
|
+
* @returns A new object with the processed options.
|
|
3520
|
+
*/
|
|
3521
|
+
async _request(path, { signalController, requestOptions, global }) {
|
|
3522
|
+
_Transportr.signalControllers.add(signalController);
|
|
3523
|
+
const retryConfig = _Transportr.normalizeRetryOptions(requestOptions.retry);
|
|
3524
|
+
const method = requestOptions.method ?? "GET";
|
|
3525
|
+
const canRetry = retryConfig.limit > 0 && retryConfig.methods.includes(method);
|
|
3526
|
+
const canDedupe = requestOptions.dedupe === true && (method === "GET" || method === "HEAD");
|
|
3527
|
+
let attempt = 0;
|
|
3528
|
+
const startTime = performance.now();
|
|
3529
|
+
const getTiming = () => {
|
|
3530
|
+
const end = performance.now();
|
|
3531
|
+
return { start: startTime, end, duration: end - startTime };
|
|
3532
|
+
};
|
|
3533
|
+
try {
|
|
3534
|
+
const url = _Transportr.createUrl(this._baseUrl, path, requestOptions.searchParams);
|
|
3535
|
+
const dedupeKey = canDedupe ? `${method}:${url.href}` : "";
|
|
3536
|
+
if (canDedupe) {
|
|
3537
|
+
const inflight = _Transportr.inflightRequests.get(dedupeKey);
|
|
3538
|
+
if (inflight) {
|
|
3539
|
+
return (await inflight).clone();
|
|
3540
|
+
}
|
|
3541
|
+
}
|
|
3542
|
+
const doFetch = async () => {
|
|
3543
|
+
while (true) {
|
|
3544
|
+
try {
|
|
3545
|
+
const response = await fetch(url, requestOptions);
|
|
3546
|
+
if (!response.ok) {
|
|
3547
|
+
if (canRetry && attempt < retryConfig.limit && retryConfig.statusCodes.includes(response.status)) {
|
|
3548
|
+
attempt++;
|
|
3549
|
+
this.publish({ name: RequestEvent.RETRY, data: { attempt, status: response.status, method, path, timing: getTiming() }, global });
|
|
3550
|
+
await _Transportr.retryDelay(retryConfig, attempt);
|
|
3551
|
+
continue;
|
|
3552
|
+
}
|
|
3553
|
+
let entity;
|
|
3554
|
+
try {
|
|
3555
|
+
entity = await response.text();
|
|
3556
|
+
} catch {
|
|
3557
|
+
}
|
|
3558
|
+
throw await this.handleError(path, response, { entity, url, method, timing: getTiming() }, requestOptions);
|
|
3559
|
+
}
|
|
3560
|
+
return response;
|
|
3561
|
+
} catch (cause) {
|
|
3562
|
+
if (cause instanceof HttpError) {
|
|
3563
|
+
throw cause;
|
|
3564
|
+
}
|
|
3565
|
+
if (canRetry && attempt < retryConfig.limit) {
|
|
3566
|
+
attempt++;
|
|
3567
|
+
this.publish({ name: RequestEvent.RETRY, data: { attempt, error: cause.message, method, path, timing: getTiming() }, global });
|
|
3568
|
+
await _Transportr.retryDelay(retryConfig, attempt);
|
|
3569
|
+
continue;
|
|
3570
|
+
}
|
|
3571
|
+
throw await this.handleError(path, void 0, { cause, url, method, timing: getTiming() }, requestOptions);
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3574
|
+
};
|
|
3575
|
+
if (canDedupe) {
|
|
3576
|
+
const promise = doFetch();
|
|
3577
|
+
_Transportr.inflightRequests.set(dedupeKey, promise);
|
|
3578
|
+
try {
|
|
3579
|
+
const response = await promise;
|
|
3580
|
+
return response;
|
|
3581
|
+
} finally {
|
|
3582
|
+
_Transportr.inflightRequests.delete(dedupeKey);
|
|
3583
|
+
}
|
|
3584
|
+
}
|
|
3585
|
+
return await doFetch();
|
|
3586
|
+
} finally {
|
|
3587
|
+
_Transportr.signalControllers.delete(signalController.destroy());
|
|
3588
|
+
if (!requestOptions.signal?.aborted) {
|
|
3589
|
+
const timing = getTiming();
|
|
3590
|
+
this.publish({ name: RequestEvent.COMPLETE, data: { timing }, global });
|
|
3591
|
+
if (_Transportr.signalControllers.size === 0) {
|
|
3592
|
+
this.publish({ name: RequestEvent.ALL_COMPLETE, global });
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
}
|
|
2460
3596
|
}
|
|
2461
3597
|
/**
|
|
2462
|
-
*
|
|
2463
|
-
*
|
|
2464
|
-
*
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
3598
|
+
* Normalizes a retry option into a full RetryOptions object.
|
|
3599
|
+
* @param retry The retry option from request options.
|
|
3600
|
+
* @returns Normalized retry configuration.
|
|
3601
|
+
*/
|
|
3602
|
+
static normalizeRetryOptions(retry) {
|
|
3603
|
+
if (retry === void 0) {
|
|
3604
|
+
return { limit: 0, statusCodes: [], methods: [], delay: retryDelay, backoffFactor: retryBackoffFactor };
|
|
3605
|
+
}
|
|
3606
|
+
if (typeof retry === "number") {
|
|
3607
|
+
return { limit: retry, statusCodes: [...retryStatusCodes], methods: [...retryMethods], delay: retryDelay, backoffFactor: retryBackoffFactor };
|
|
3608
|
+
}
|
|
3609
|
+
return {
|
|
3610
|
+
limit: retry.limit ?? 0,
|
|
3611
|
+
statusCodes: retry.statusCodes ?? [...retryStatusCodes],
|
|
3612
|
+
methods: retry.methods ?? [...retryMethods],
|
|
3613
|
+
delay: retry.delay ?? retryDelay,
|
|
3614
|
+
backoffFactor: retry.backoffFactor ?? retryBackoffFactor
|
|
3615
|
+
};
|
|
3616
|
+
}
|
|
3617
|
+
/**
|
|
3618
|
+
* Waits for the appropriate delay before a retry attempt.
|
|
3619
|
+
* @param config The retry configuration.
|
|
3620
|
+
* @param attempt The current attempt number (1-based).
|
|
3621
|
+
* @returns A promise that resolves after the delay.
|
|
3622
|
+
*/
|
|
3623
|
+
static retryDelay(config, attempt) {
|
|
3624
|
+
const ms = typeof config.delay === "function" ? config.delay(attempt) : config.delay * config.backoffFactor ** (attempt - 1);
|
|
3625
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3626
|
+
}
|
|
3627
|
+
/**
|
|
3628
|
+
* It returns a response handler based on the content type of the response.
|
|
3629
|
+
* @param path The path to the resource.
|
|
3630
|
+
* @param userOptions The user options for the request.
|
|
3631
|
+
* @param options The options for the request.
|
|
3632
|
+
* @param responseHandler The response handler for the request.
|
|
3633
|
+
* @returns A response handler function.
|
|
3634
|
+
*/
|
|
3635
|
+
async execute(path, userOptions = {}, options = {}, responseHandler) {
|
|
3636
|
+
if (isObject(path)) {
|
|
2476
3637
|
[path, userOptions] = [void 0, path];
|
|
2477
3638
|
}
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
const
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
if (!
|
|
2485
|
-
|
|
3639
|
+
const requestConfig = this.processRequestOptions(userOptions, options);
|
|
3640
|
+
const { requestOptions } = requestConfig;
|
|
3641
|
+
const requestHooks = requestOptions.hooks;
|
|
3642
|
+
let url = _Transportr.createUrl(this._baseUrl, path, requestOptions.searchParams);
|
|
3643
|
+
const beforeRequestHookSets = [_Transportr.globalHooks.beforeRequest, this.hooks.beforeRequest, requestHooks?.beforeRequest];
|
|
3644
|
+
for (const hooks of beforeRequestHookSets) {
|
|
3645
|
+
if (!hooks) {
|
|
3646
|
+
continue;
|
|
2486
3647
|
}
|
|
2487
|
-
const
|
|
2488
|
-
|
|
2489
|
-
|
|
3648
|
+
for (const hook of hooks) {
|
|
3649
|
+
const result = await hook(requestOptions, url);
|
|
3650
|
+
if (result) {
|
|
3651
|
+
Object.assign(requestOptions, result);
|
|
3652
|
+
if (result.searchParams !== void 0) {
|
|
3653
|
+
url = _Transportr.createUrl(this._baseUrl, path, requestOptions.searchParams);
|
|
3654
|
+
}
|
|
3655
|
+
}
|
|
2490
3656
|
}
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
if (
|
|
2501
|
-
|
|
3657
|
+
}
|
|
3658
|
+
let response = await this._request(path, requestConfig);
|
|
3659
|
+
const afterResponseHookSets = [_Transportr.globalHooks.afterResponse, this.hooks.afterResponse, requestHooks?.afterResponse];
|
|
3660
|
+
for (const hooks of afterResponseHookSets) {
|
|
3661
|
+
if (!hooks) {
|
|
3662
|
+
continue;
|
|
3663
|
+
}
|
|
3664
|
+
for (const hook of hooks) {
|
|
3665
|
+
const result = await hook(response, requestOptions);
|
|
3666
|
+
if (result) {
|
|
3667
|
+
response = result;
|
|
2502
3668
|
}
|
|
2503
3669
|
}
|
|
2504
3670
|
}
|
|
3671
|
+
try {
|
|
3672
|
+
if (!responseHandler && response.status !== 204) {
|
|
3673
|
+
responseHandler = this.getResponseHandler(response.headers.get(HttpResponseHeader.CONTENT_TYPE));
|
|
3674
|
+
}
|
|
3675
|
+
const data = await responseHandler?.(response);
|
|
3676
|
+
this.publish({ name: RequestEvent.SUCCESS, data, global: requestConfig.global });
|
|
3677
|
+
return data;
|
|
3678
|
+
} catch (cause) {
|
|
3679
|
+
throw await this.handleError(path, response, { cause }, requestOptions);
|
|
3680
|
+
}
|
|
2505
3681
|
}
|
|
2506
3682
|
/**
|
|
2507
|
-
* Creates
|
|
2508
|
-
*
|
|
2509
|
-
* @
|
|
2510
|
-
* @
|
|
2511
|
-
* @param {RequestOptions} userOptions The {@link RequestOptions} to convert.
|
|
2512
|
-
* @param {RequestOptions} options The default {@link RequestOptions}.
|
|
2513
|
-
* @returns {RequestOptions} The converted {@link RequestOptions}.
|
|
3683
|
+
* Creates a new set of options for a request.
|
|
3684
|
+
* @param options The user options for the request.
|
|
3685
|
+
* @param userOptions The default options for the request.
|
|
3686
|
+
* @returns A new set of options for the request.
|
|
2514
3687
|
*/
|
|
2515
|
-
static
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
searchParams: _Transportr.#mergeOptions(new URLSearchParams(), userSearchParams, searchParams)
|
|
2520
|
-
});
|
|
3688
|
+
static createOptions({ headers: userHeaders, searchParams: userSearchParams, ...userOptions }, { headers, searchParams, ...options }) {
|
|
3689
|
+
headers = _Transportr.mergeHeaders(new Headers(), userHeaders, headers);
|
|
3690
|
+
searchParams = _Transportr.mergeSearchParams(new URLSearchParams(), userSearchParams, searchParams);
|
|
3691
|
+
return { ...objectMerge(options, userOptions) ?? {}, headers, searchParams };
|
|
2521
3692
|
}
|
|
2522
3693
|
/**
|
|
2523
|
-
*
|
|
2524
|
-
*
|
|
2525
|
-
* @
|
|
2526
|
-
* @
|
|
2527
|
-
* @param {Headers|URLSearchParams|FormData} target The target to merge the options into.
|
|
2528
|
-
* @param {Headers|URLSearchParams|FormData|Object} userOption The user options to merge into the target.
|
|
2529
|
-
* @param {Headers|URLSearchParams|FormData|Object} requestOption The request options to merge into the target.
|
|
2530
|
-
* @returns {Headers|URLSearchParams} The target.
|
|
3694
|
+
* Merges user and request headers into the target Headers object.
|
|
3695
|
+
* @param target The target Headers object.
|
|
3696
|
+
* @param headerSources Variable number of header sources to merge.
|
|
3697
|
+
* @returns The merged Headers object.
|
|
2531
3698
|
*/
|
|
2532
|
-
static
|
|
2533
|
-
for (const
|
|
2534
|
-
|
|
2535
|
-
|
|
3699
|
+
static mergeHeaders(target, ...headerSources) {
|
|
3700
|
+
for (const headers of headerSources) {
|
|
3701
|
+
if (headers === void 0) {
|
|
3702
|
+
continue;
|
|
3703
|
+
}
|
|
3704
|
+
if (headers instanceof Headers) {
|
|
3705
|
+
headers.forEach((value, name) => target.set(name, value));
|
|
3706
|
+
} else if (Array.isArray(headers)) {
|
|
3707
|
+
for (const [name, value] of headers) {
|
|
3708
|
+
target.set(name, value);
|
|
3709
|
+
}
|
|
3710
|
+
} else {
|
|
3711
|
+
const record = headers;
|
|
3712
|
+
const keys = Object.keys(record);
|
|
3713
|
+
for (let i = 0; i < keys.length; i++) {
|
|
3714
|
+
const name = keys[i];
|
|
3715
|
+
const value = record[name];
|
|
3716
|
+
if (value !== void 0) {
|
|
3717
|
+
target.set(name, String(value));
|
|
3718
|
+
}
|
|
3719
|
+
}
|
|
2536
3720
|
}
|
|
2537
3721
|
}
|
|
2538
3722
|
return target;
|
|
2539
3723
|
}
|
|
2540
3724
|
/**
|
|
2541
|
-
* Merges
|
|
2542
|
-
*
|
|
2543
|
-
* @
|
|
2544
|
-
* @
|
|
2545
|
-
* @param {RequestOptions} options The request options to merge into the user options.
|
|
2546
|
-
* @returns {RequestOptions} The merged options.
|
|
3725
|
+
* Merges user and request search parameters into the target URLSearchParams object.
|
|
3726
|
+
* @param target The target URLSearchParams object.
|
|
3727
|
+
* @param sources The search parameters to merge.
|
|
3728
|
+
* @returns The merged URLSearchParams object.
|
|
2547
3729
|
*/
|
|
2548
|
-
|
|
2549
|
-
const
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
const
|
|
2557
|
-
|
|
2558
|
-
requestOptions.body = _Transportr.#mergeOptions(new FormData(requestOptions.body), userBody);
|
|
2559
|
-
} else if (mediaType == http_media_type_default.FORM) {
|
|
2560
|
-
requestOptions.body = _Transportr.#mergeOptions(new URLSearchParams(requestOptions.body), userBody);
|
|
2561
|
-
} else if (mediaType.includes("json")) {
|
|
2562
|
-
requestOptions.body = JSON.stringify(_Transportr.#mergeOptions(new ParameterMap(requestOptions.body), userBody));
|
|
2563
|
-
} else {
|
|
2564
|
-
requestOptions.body = _Transportr.#mergeOptions(new ParameterMap(requestOptions.body), userBody);
|
|
3730
|
+
static mergeSearchParams(target, ...sources) {
|
|
3731
|
+
for (const searchParams of sources) {
|
|
3732
|
+
if (searchParams === void 0) {
|
|
3733
|
+
continue;
|
|
3734
|
+
}
|
|
3735
|
+
if (searchParams instanceof URLSearchParams) {
|
|
3736
|
+
searchParams.forEach((value, name) => target.set(name, value));
|
|
3737
|
+
} else if (isString(searchParams) || Array.isArray(searchParams)) {
|
|
3738
|
+
for (const [name, value] of new URLSearchParams(searchParams)) {
|
|
3739
|
+
target.set(name, value);
|
|
2565
3740
|
}
|
|
2566
3741
|
} else {
|
|
3742
|
+
const keys = Object.keys(searchParams);
|
|
3743
|
+
for (let i = 0; i < keys.length; i++) {
|
|
3744
|
+
const name = keys[i];
|
|
3745
|
+
const value = searchParams[name];
|
|
3746
|
+
if (value !== void 0) {
|
|
3747
|
+
target.set(name, String(value));
|
|
3748
|
+
}
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3751
|
+
}
|
|
3752
|
+
return target;
|
|
3753
|
+
}
|
|
3754
|
+
/**
|
|
3755
|
+
* Processes request options by merging user, instance, and method-specific options.
|
|
3756
|
+
* This method optimizes performance by using cached instance options and performing
|
|
3757
|
+
* shallow merges where possible instead of deep object cloning.
|
|
3758
|
+
* @param userOptions The user-provided options for the request.
|
|
3759
|
+
* @param options Additional method-specific options.
|
|
3760
|
+
* @returns Processed request options with signal controller and global flag.
|
|
3761
|
+
*/
|
|
3762
|
+
processRequestOptions({ body: userBody, headers: userHeaders, searchParams: userSearchParams, ...userOptions }, { headers, searchParams, ...options }) {
|
|
3763
|
+
const requestOptions = {
|
|
3764
|
+
// Spread instance options (already merged with defaults)
|
|
3765
|
+
...this._options,
|
|
3766
|
+
// Spread user options (shallow merge, sufficient for flat properties)
|
|
3767
|
+
...userOptions,
|
|
3768
|
+
// Spread method-specific options (e.g., method: 'POST')
|
|
3769
|
+
...options,
|
|
3770
|
+
// Deep merge required for headers and searchParams
|
|
3771
|
+
headers: _Transportr.mergeHeaders(new Headers(), this._options.headers, userHeaders, headers),
|
|
3772
|
+
searchParams: _Transportr.mergeSearchParams(new URLSearchParams(), this._options.searchParams, userSearchParams, searchParams)
|
|
3773
|
+
};
|
|
3774
|
+
if (isRequestBodyMethod(requestOptions.method)) {
|
|
3775
|
+
if (isRawBody(userBody)) {
|
|
2567
3776
|
requestOptions.body = userBody;
|
|
3777
|
+
requestOptions.headers.delete(HttpRequestHeader.CONTENT_TYPE);
|
|
3778
|
+
} else {
|
|
3779
|
+
const isJson = requestOptions.headers.get(HttpRequestHeader.CONTENT_TYPE)?.includes("json") ?? false;
|
|
3780
|
+
requestOptions.body = isJson && isObject(userBody) ? serialize(userBody) : userBody;
|
|
2568
3781
|
}
|
|
2569
3782
|
} else {
|
|
2570
|
-
requestOptions.headers.delete(
|
|
2571
|
-
if (requestOptions.body) {
|
|
2572
|
-
_Transportr
|
|
3783
|
+
requestOptions.headers.delete(HttpRequestHeader.CONTENT_TYPE);
|
|
3784
|
+
if (requestOptions.body instanceof URLSearchParams) {
|
|
3785
|
+
_Transportr.mergeSearchParams(requestOptions.searchParams, requestOptions.body);
|
|
2573
3786
|
}
|
|
2574
3787
|
requestOptions.body = void 0;
|
|
2575
3788
|
}
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
3789
|
+
const { signal, timeout, global = false, xsrf } = requestOptions;
|
|
3790
|
+
if (xsrf) {
|
|
3791
|
+
const xsrfConfig = typeof xsrf === "object" ? xsrf : {};
|
|
3792
|
+
const token = getCookieValue(xsrfConfig.cookieName ?? XSRF_COOKIE_NAME);
|
|
3793
|
+
if (token) {
|
|
3794
|
+
requestOptions.headers.set(xsrfConfig.headerName ?? XSRF_HEADER_NAME, token);
|
|
3795
|
+
}
|
|
3796
|
+
}
|
|
3797
|
+
const signalController = new SignalController({ signal, timeout }).onAbort((event) => this.publish({ name: RequestEvent.ABORTED, event, global })).onTimeout((event) => this.publish({ name: RequestEvent.TIMEOUT, event, global }));
|
|
3798
|
+
requestOptions.signal = signalController.signal;
|
|
3799
|
+
this.publish({ name: RequestEvent.CONFIGURED, data: requestOptions, global });
|
|
3800
|
+
return { signalController, requestOptions, global };
|
|
2579
3801
|
}
|
|
2580
3802
|
/**
|
|
2581
|
-
*
|
|
2582
|
-
*
|
|
2583
|
-
*
|
|
2584
|
-
* @private
|
|
2585
|
-
* @static
|
|
2586
|
-
* @param {URL|string} url The URL to convert to a {@link URL} instance.
|
|
2587
|
-
* @returns {URL} A {@link URL} instance.
|
|
2588
|
-
* @throws {TypeError} If the url is not a string or {@link URL} instance.
|
|
3803
|
+
* Gets the base URL from a URL or string.
|
|
3804
|
+
* @param url The URL or string to parse.
|
|
3805
|
+
* @returns The base URL.
|
|
2589
3806
|
*/
|
|
2590
|
-
static
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
default:
|
|
2597
|
-
throw new TypeError("Invalid URL");
|
|
3807
|
+
static getBaseUrl(url) {
|
|
3808
|
+
if (url instanceof URL) {
|
|
3809
|
+
return url;
|
|
3810
|
+
}
|
|
3811
|
+
if (!isString(url)) {
|
|
3812
|
+
throw new TypeError("Invalid URL");
|
|
2598
3813
|
}
|
|
3814
|
+
return new URL(url, url.startsWith("/") ? globalThis.location.origin : void 0);
|
|
2599
3815
|
}
|
|
2600
3816
|
/**
|
|
2601
|
-
*
|
|
2602
|
-
*
|
|
2603
|
-
*
|
|
2604
|
-
* @
|
|
2605
|
-
* @
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
3817
|
+
* Parses a content-type string into a MediaType instance with caching.
|
|
3818
|
+
* This method caches parsed MediaType instances to avoid re-parsing the same content-type strings,
|
|
3819
|
+
* which significantly improves performance for repeated requests with the same content types.
|
|
3820
|
+
* @param contentType The content-type string to parse.
|
|
3821
|
+
* @returns The parsed MediaType instance, or undefined if parsing fails.
|
|
3822
|
+
*/
|
|
3823
|
+
static getOrParseMediaType(contentType) {
|
|
3824
|
+
if (contentType === null) {
|
|
3825
|
+
return;
|
|
3826
|
+
}
|
|
3827
|
+
let mediaType = _Transportr.mediaTypeCache.get(contentType);
|
|
3828
|
+
if (mediaType !== void 0) {
|
|
3829
|
+
return mediaType;
|
|
3830
|
+
}
|
|
3831
|
+
mediaType = MediaType.parse(contentType) ?? void 0;
|
|
3832
|
+
if (mediaType !== void 0) {
|
|
3833
|
+
if (_Transportr.mediaTypeCache.size >= 100) {
|
|
3834
|
+
const firstKey = _Transportr.mediaTypeCache.keys().next().value;
|
|
3835
|
+
if (firstKey !== void 0) {
|
|
3836
|
+
_Transportr.mediaTypeCache.delete(firstKey);
|
|
3837
|
+
}
|
|
3838
|
+
}
|
|
3839
|
+
_Transportr.mediaTypeCache.set(contentType, mediaType);
|
|
3840
|
+
}
|
|
3841
|
+
return mediaType;
|
|
3842
|
+
}
|
|
3843
|
+
/**
|
|
3844
|
+
* Creates a new URL with the given path and search parameters.
|
|
3845
|
+
* @param url The base URL.
|
|
3846
|
+
* @param path The path to append to the base URL.
|
|
3847
|
+
* @param searchParams The search parameters to append to the URL.
|
|
3848
|
+
* @returns A new URL with the given path and search parameters.
|
|
2610
3849
|
*/
|
|
2611
|
-
static
|
|
3850
|
+
static createUrl(url, path, searchParams) {
|
|
2612
3851
|
const requestUrl = path ? new URL(`${url.pathname.replace(endsWithSlashRegEx, "")}${path}`, url.origin) : new URL(url);
|
|
2613
|
-
searchParams
|
|
3852
|
+
if (searchParams) {
|
|
3853
|
+
_Transportr.mergeSearchParams(requestUrl.searchParams, searchParams);
|
|
3854
|
+
}
|
|
2614
3855
|
return requestUrl;
|
|
2615
3856
|
}
|
|
2616
3857
|
/**
|
|
2617
|
-
*
|
|
2618
|
-
*
|
|
2619
|
-
* @
|
|
2620
|
-
* @
|
|
2621
|
-
* @param {string} errorName The name of the error.
|
|
2622
|
-
* @param {Response} response The response object returned by the fetch API.
|
|
2623
|
-
* @returns {ResponseStatus} The response status object.
|
|
3858
|
+
* It generates a ResponseStatus object from an error name and a Response object.
|
|
3859
|
+
* @param errorName The name of the error.
|
|
3860
|
+
* @param response The Response object.
|
|
3861
|
+
* @returns A ResponseStatus object.
|
|
2624
3862
|
*/
|
|
2625
|
-
static
|
|
3863
|
+
static generateResponseStatusFromError(errorName, { status, statusText } = new Response()) {
|
|
2626
3864
|
switch (errorName) {
|
|
2627
|
-
case
|
|
2628
|
-
return
|
|
2629
|
-
case
|
|
2630
|
-
return
|
|
3865
|
+
case SignalErrors.ABORT:
|
|
3866
|
+
return aborted;
|
|
3867
|
+
case SignalErrors.TIMEOUT:
|
|
3868
|
+
return timedOut;
|
|
2631
3869
|
default:
|
|
2632
|
-
return
|
|
3870
|
+
return status >= 400 ? new ResponseStatus(status, statusText) : internalServerError;
|
|
2633
3871
|
}
|
|
2634
3872
|
}
|
|
2635
3873
|
/**
|
|
2636
|
-
* Handles an error
|
|
2637
|
-
*
|
|
2638
|
-
* @
|
|
2639
|
-
* @param
|
|
2640
|
-
* @param
|
|
2641
|
-
* @returns
|
|
2642
|
-
*/
|
|
2643
|
-
|
|
2644
|
-
const
|
|
2645
|
-
|
|
3874
|
+
* Handles an error that occurs during a request.
|
|
3875
|
+
* @param path The path of the request.
|
|
3876
|
+
* @param response The Response object.
|
|
3877
|
+
* @param options Additional error context including cause, entity, url, method, and timing.
|
|
3878
|
+
* @param requestOptions The original request options that led to the error, used for hooks context.
|
|
3879
|
+
* @returns An HttpError object.
|
|
3880
|
+
*/
|
|
3881
|
+
async handleError(path, response, { cause, entity, url, method, timing } = {}, requestOptions) {
|
|
3882
|
+
const message = method && url ? `${method} ${url.href} failed${response ? ` with status ${response.status}` : ""}` : `An error has occurred with your request to: '${path}'`;
|
|
3883
|
+
let error = new HttpError(_Transportr.generateResponseStatusFromError(cause?.name, response), { message, cause, entity, url, method, timing });
|
|
3884
|
+
const beforeErrorHookSets = [_Transportr.globalHooks.beforeError, this.hooks.beforeError, requestOptions?.hooks?.beforeError];
|
|
3885
|
+
for (const hooks of beforeErrorHookSets) {
|
|
3886
|
+
if (!hooks) {
|
|
3887
|
+
continue;
|
|
3888
|
+
}
|
|
3889
|
+
for (const hook of hooks) {
|
|
3890
|
+
const result = await hook(error);
|
|
3891
|
+
if (result instanceof HttpError) {
|
|
3892
|
+
error = result;
|
|
3893
|
+
}
|
|
3894
|
+
}
|
|
3895
|
+
}
|
|
3896
|
+
this.publish({ name: RequestEvent.ERROR, data: error });
|
|
2646
3897
|
return error;
|
|
2647
3898
|
}
|
|
2648
3899
|
/**
|
|
2649
|
-
* Publishes an event to the global and instance
|
|
2650
|
-
*
|
|
2651
|
-
* @private
|
|
2652
|
-
* @param {Object} options The options for the event.
|
|
2653
|
-
* @param {string} options.name The name of the event.
|
|
2654
|
-
* @param {Event} [options.event] The event object.
|
|
2655
|
-
* @param {*} [options.data] The data to pass to the subscribers.
|
|
2656
|
-
* @param {boolean} [options.global=true] Whether or not to publish the event to the global subscribers.
|
|
2657
|
-
* @returns {void}
|
|
3900
|
+
* Publishes an event to the global and instance event handlers.
|
|
3901
|
+
* @param eventObject The event object to publish.
|
|
2658
3902
|
*/
|
|
2659
|
-
|
|
3903
|
+
publish({ name, event = new CustomEvent(name), data, global = true }) {
|
|
2660
3904
|
if (global) {
|
|
2661
|
-
_Transportr
|
|
3905
|
+
_Transportr.globalSubscribr.publish(name, event, data);
|
|
2662
3906
|
}
|
|
2663
|
-
this
|
|
3907
|
+
this.subscribr.publish(name, event, data);
|
|
2664
3908
|
}
|
|
2665
3909
|
/**
|
|
2666
|
-
*
|
|
2667
|
-
*
|
|
2668
|
-
* @
|
|
2669
|
-
* @param {string} contentType The content type of the response.
|
|
2670
|
-
* @returns {ResponseHandler<ResponseBody>} The response handler.
|
|
3910
|
+
* It returns a response handler based on the content type of the response.
|
|
3911
|
+
* @param contentType The content type of the response.
|
|
3912
|
+
* @returns A response handler function.
|
|
2671
3913
|
*/
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
3914
|
+
getResponseHandler(contentType) {
|
|
3915
|
+
if (!contentType) {
|
|
3916
|
+
return;
|
|
3917
|
+
}
|
|
3918
|
+
const mediaType = _Transportr.getOrParseMediaType(contentType);
|
|
3919
|
+
if (!mediaType) {
|
|
3920
|
+
return;
|
|
3921
|
+
}
|
|
3922
|
+
for (const [contentType2, responseHandler] of _Transportr.contentTypeHandlers) {
|
|
3923
|
+
if (mediaType.matches(contentType2)) {
|
|
3924
|
+
return responseHandler;
|
|
2679
3925
|
}
|
|
2680
3926
|
}
|
|
2681
3927
|
return void 0;
|
|
2682
3928
|
}
|
|
2683
3929
|
/**
|
|
2684
|
-
* A
|
|
2685
|
-
*
|
|
2686
|
-
*
|
|
2687
|
-
* @returns {string} The default string description of this object.
|
|
3930
|
+
* A string representation of the Transportr instance.
|
|
3931
|
+
* @returns The string 'Transportr'.
|
|
2688
3932
|
*/
|
|
2689
3933
|
get [Symbol.toStringTag]() {
|
|
2690
3934
|
return "Transportr";
|
|
2691
3935
|
}
|
|
2692
3936
|
};
|
|
2693
3937
|
export {
|
|
2694
|
-
Transportr
|
|
3938
|
+
Transportr
|
|
2695
3939
|
};
|
|
3940
|
+
/*! Bundled license information:
|
|
3941
|
+
|
|
3942
|
+
dompurify/dist/purify.es.mjs:
|
|
3943
|
+
(*! @license DOMPurify 3.3.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.3/LICENSE *)
|
|
3944
|
+
*/
|
|
3945
|
+
//# sourceMappingURL=transportr.js.map
|