From 6ee3237d5ebf3f12319fdb10a40919741a8eeeff Mon Sep 17 00:00:00 2001 From: Mike McCready <66998419+MikeMcC399@users.noreply.github.com> Date: Mon, 31 Aug 2026 09:15:19 +0200 Subject: [PATCH] fix: migrate from got@11 to got@16 Provide better messages for ping-cli. --- dist/849.index.js | 13075 ++++++++++++++++++++++++++++++++++++++++++++ dist/index.js | 8665 ++--------------------------- package-lock.json | 394 +- package.json | 2 +- src/ping-cli.js | 7 + src/ping.js | 18 +- 6 files changed, 13680 insertions(+), 8481 deletions(-) create mode 100644 dist/849.index.js diff --git a/dist/849.index.js b/dist/849.index.js new file mode 100644 index 000000000..d27fa5cf6 --- /dev/null +++ b/dist/849.index.js @@ -0,0 +1,13075 @@ +"use strict"; +exports.id = 849; +exports.ids = [849]; +exports.modules = { + +/***/ 12203: +/***/ ((module) => { + + + +/** + * @typedef {Object} HttpRequest + * @property {Record} headers - Request headers + * @property {string} [method] - HTTP method + * @property {string} [url] - Request URL + */ + +/** + * @typedef {Object} HttpResponse + * @property {Record} headers - Response headers + * @property {number} [status] - HTTP status code + */ + +/** + * Set of default cacheable status codes per RFC 7231 section 6.1. + * @type {Set} + */ +const statusCodeCacheableByDefault = new Set([ + 200, + 203, + 204, + 206, + 300, + 301, + 308, + 404, + 405, + 410, + 414, + 501, +]); + +/** + * Set of HTTP status codes that the cache implementation understands. + * Note: This implementation does not understand partial responses (206). + * @type {Set} + */ +const understoodStatuses = new Set([ + 200, + 203, + 204, + 300, + 301, + 302, + 303, + 307, + 308, + 404, + 405, + 410, + 414, + 501, +]); + +/** + * Set of HTTP error status codes. + * @type {Set} + */ +const errorStatusCodes = new Set([ + 500, + 502, + 503, + 504, +]); + +/** + * Object representing hop-by-hop headers that should be removed. + * @type {Record} + */ +const hopByHopHeaders = { + date: true, // included, because we add Age update Date + connection: true, + 'keep-alive': true, + 'proxy-authenticate': true, + 'proxy-authorization': true, + te: true, + trailer: true, + 'transfer-encoding': true, + upgrade: true, +}; + +/** + * Headers that are excluded from revalidation update. + * @type {Record} + */ +const excludedFromRevalidationUpdate = { + // Since the old body is reused, it doesn't make sense to change properties of the body + 'content-length': true, + 'content-encoding': true, + 'transfer-encoding': true, + 'content-range': true, +}; + +/** + * Converts a string to a number or returns zero if the conversion fails. + * @param {string} s - The string to convert. + * @returns {number} The parsed number or 0. + */ +function toNumberOrZero(s) { + const n = parseInt(s, 10); + return isFinite(n) ? n : 0; +} + +/** + * Determines if the given response is an error response. + * Implements RFC 5861 behavior. + * @param {HttpResponse|undefined} response - The HTTP response object. + * @returns {boolean} true if the response is an error or undefined, false otherwise. + */ +function isErrorResponse(response) { + // consider undefined response as faulty + if (!response) { + return true; + } + return errorStatusCodes.has(response.status); +} + +/** + * Parses a Cache-Control header string into an object. + * @param {string} [header] - The Cache-Control header value. + * @returns {Record} An object representing Cache-Control directives. + */ +function parseCacheControl(header) { + /** @type {Record} */ + const cc = {}; + if (!header) return cc; + + // TODO: When there is more than one value present for a given directive (e.g., two Expires header fields, multiple Cache-Control: max-age directives), + // the directive's value is considered invalid. Caches are encouraged to consider responses that have invalid freshness information to be stale + const parts = header.trim().split(/,/); + for (const part of parts) { + const [k, v] = part.split(/=/, 2); + cc[k.trim()] = v === undefined ? true : v.trim().replace(/^"|"$/g, ''); + } + + return cc; +} + +/** + * Formats a Cache-Control directives object into a header string. + * @param {Record} cc - The Cache-Control directives. + * @returns {string|undefined} A formatted Cache-Control header string or undefined if empty. + */ +function formatCacheControl(cc) { + let parts = []; + for (const k in cc) { + const v = cc[k]; + parts.push(v === true ? k : k + '=' + v); + } + if (!parts.length) { + return undefined; + } + return parts.join(', '); +} + +module.exports = class CachePolicy { + /** + * Creates a new CachePolicy instance. + * @param {HttpRequest} req - Incoming client request. + * @param {HttpResponse} res - Received server response. + * @param {Object} [options={}] - Configuration options. + * @param {boolean} [options.shared=true] - Is the cache shared (a public proxy)? `false` for personal browser caches. + * @param {number} [options.cacheHeuristic=0.1] - Fallback heuristic (age fraction) for cache duration. + * @param {number} [options.immutableMinTimeToLive=86400000] - Minimum TTL for immutable responses in milliseconds. + * @param {boolean} [options.ignoreCargoCult=false] - Detect nonsense cache headers, and override them. + * @param {any} [options._fromObject] - Internal parameter for deserialization. Do not use. + */ + constructor( + req, + res, + { + shared, + cacheHeuristic, + immutableMinTimeToLive, + ignoreCargoCult, + _fromObject, + } = {} + ) { + if (_fromObject) { + this._fromObject(_fromObject); + return; + } + + if (!res || !res.headers) { + throw Error('Response headers missing'); + } + this._assertRequestHasHeaders(req); + + /** @type {number} Timestamp when the response was received */ + this._responseTime = this.now(); + /** @type {boolean} Indicates if the cache is shared */ + this._isShared = shared !== false; + /** @type {boolean} Indicates if legacy cargo cult directives should be ignored */ + this._ignoreCargoCult = !!ignoreCargoCult; + /** @type {number} Heuristic cache fraction */ + this._cacheHeuristic = + undefined !== cacheHeuristic ? cacheHeuristic : 0.1; // 10% matches IE + /** @type {number} Minimum TTL for immutable responses in ms */ + this._immutableMinTtl = + undefined !== immutableMinTimeToLive + ? immutableMinTimeToLive + : 24 * 3600 * 1000; + + /** @type {number} HTTP status code */ + this._status = 'status' in res ? res.status : 200; + /** @type {Record} Response headers */ + this._resHeaders = res.headers; + /** @type {Record} Parsed Cache-Control directives from response */ + this._rescc = parseCacheControl(res.headers['cache-control']); + /** @type {string} HTTP method (e.g., GET, POST) */ + this._method = 'method' in req ? req.method : 'GET'; + /** @type {string} Request URL */ + this._url = req.url; + /** @type {string} Host header from the request */ + this._host = req.headers.host; + /** @type {boolean} Whether the request does not include an Authorization header */ + this._noAuthorization = !req.headers.authorization; + /** @type {Record|null} Request headers used for Vary matching */ + this._reqHeaders = res.headers.vary ? req.headers : null; // Don't keep all request headers if they won't be used + /** @type {Record} Parsed Cache-Control directives from request */ + this._reqcc = parseCacheControl(req.headers['cache-control']); + + // Assume that if someone uses legacy, non-standard uncecessary options they don't understand caching, + // so there's no point stricly adhering to the blindly copy&pasted directives. + if ( + this._ignoreCargoCult && + 'pre-check' in this._rescc && + 'post-check' in this._rescc + ) { + delete this._rescc['pre-check']; + delete this._rescc['post-check']; + delete this._rescc['no-cache']; + delete this._rescc['no-store']; + delete this._rescc['must-revalidate']; + this._resHeaders = Object.assign({}, this._resHeaders, { + 'cache-control': formatCacheControl(this._rescc), + }); + delete this._resHeaders.expires; + delete this._resHeaders.pragma; + } + + // When the Cache-Control header field is not present in a request, caches MUST consider the no-cache request pragma-directive + // as having the same effect as if "Cache-Control: no-cache" were present (see Section 5.2.1). + if ( + res.headers['cache-control'] == null && + /no-cache/.test(res.headers.pragma) + ) { + this._rescc['no-cache'] = true; + } + } + + /** + * You can monkey-patch it for testing. + * @returns {number} Current time in milliseconds. + */ + now() { + return Date.now(); + } + + /** + * Determines if the response is storable in a cache. + * @returns {boolean} `false` if can never be cached. + */ + storable() { + // The "no-store" request directive indicates that a cache MUST NOT store any part of either this request or any response to it. + return !!( + !this._reqcc['no-store'] && + // A cache MUST NOT store a response to any request, unless: + // The request method is understood by the cache and defined as being cacheable, and + ('GET' === this._method || + 'HEAD' === this._method || + ('POST' === this._method && this._hasExplicitExpiration())) && + // the response status code is understood by the cache, and + understoodStatuses.has(this._status) && + // the "no-store" cache directive does not appear in request or response header fields, and + !this._rescc['no-store'] && + // the "private" response directive does not appear in the response, if the cache is shared, and + (!this._isShared || !this._rescc.private) && + // the Authorization header field does not appear in the request, if the cache is shared, + (!this._isShared || + this._noAuthorization || + this._allowsStoringAuthenticated()) && + // the response either: + // contains an Expires header field, or + (this._resHeaders.expires || + // contains a max-age response directive, or + // contains a s-maxage response directive and the cache is shared, or + // contains a public response directive. + this._rescc['max-age'] || + (this._isShared && this._rescc['s-maxage']) || + this._rescc.public || + // has a status code that is defined as cacheable by default + statusCodeCacheableByDefault.has(this._status)) + ); + } + + /** + * @returns {boolean} true if expiration is explicitly defined. + */ + _hasExplicitExpiration() { + // 4.2.1 Calculating Freshness Lifetime + return !!( + (this._isShared && this._rescc['s-maxage']) || + this._rescc['max-age'] || + this._resHeaders.expires + ); + } + + /** + * @param {HttpRequest} req - a request + * @throws {Error} if the headers are missing. + */ + _assertRequestHasHeaders(req) { + if (!req || !req.headers) { + throw Error('Request headers missing'); + } + } + + /** + * Checks if the request matches the cache and can be satisfied from the cache immediately, + * without having to make a request to the server. + * + * This doesn't support `stale-while-revalidate`. See `evaluateRequest()` for a more complete solution. + * + * @param {HttpRequest} req - The new incoming HTTP request. + * @returns {boolean} `true`` if the cached response used to construct this cache policy satisfies the request without revalidation. + */ + satisfiesWithoutRevalidation(req) { + const result = this.evaluateRequest(req); + return !result.revalidation; + } + + /** + * @param {{headers: Record, synchronous: boolean}|undefined} revalidation - Revalidation information, if any. + * @returns {{response: {headers: Record}, revalidation: {headers: Record, synchronous: boolean}|undefined}} An object with a cached response headers and revalidation info. + */ + _evaluateRequestHitResult(revalidation) { + return { + response: { + headers: this.responseHeaders(), + }, + revalidation, + }; + } + + /** + * @param {HttpRequest} request - new incoming + * @param {boolean} synchronous - whether revalidation must be synchronous (not s-w-r). + * @returns {{headers: Record, synchronous: boolean}} An object with revalidation headers and a synchronous flag. + */ + _evaluateRequestRevalidation(request, synchronous) { + return { + synchronous, + headers: this.revalidationHeaders(request), + }; + } + + /** + * @param {HttpRequest} request - new incoming + * @returns {{response: undefined, revalidation: {headers: Record, synchronous: boolean}}} An object indicating no cached response and revalidation details. + */ + _evaluateRequestMissResult(request) { + return { + response: undefined, + revalidation: this._evaluateRequestRevalidation(request, true), + }; + } + + /** + * Checks if the given request matches this cache entry, and how the cache can be used to satisfy it. Returns an object with: + * + * ``` + * { + * // If defined, you must send a request to the server. + * revalidation: { + * headers: {}, // HTTP headers to use when sending the revalidation response + * // If true, you MUST wait for a response from the server before using the cache + * // If false, this is stale-while-revalidate. The cache is stale, but you can use it while you update it asynchronously. + * synchronous: bool, + * }, + * // If defined, you can use this cached response. + * response: { + * headers: {}, // Updated cached HTTP headers you must use when responding to the client + * }, + * } + * ``` + * @param {HttpRequest} req - new incoming HTTP request + * @returns {{response: {headers: Record}|undefined, revalidation: {headers: Record, synchronous: boolean}|undefined}} An object containing keys: + * - revalidation: { headers: Record, synchronous: boolean } Set if you should send this to the origin server + * - response: { headers: Record } Set if you can respond to the client with these cached headers + */ + evaluateRequest(req) { + this._assertRequestHasHeaders(req); + + // In all circumstances, a cache MUST NOT ignore the must-revalidate directive + if (this._rescc['must-revalidate']) { + return this._evaluateRequestMissResult(req); + } + + if (!this._requestMatches(req, false)) { + return this._evaluateRequestMissResult(req); + } + + // When presented with a request, a cache MUST NOT reuse a stored response, unless: + // the presented request does not contain the no-cache pragma (Section 5.4), nor the no-cache cache directive, + // unless the stored response is successfully validated (Section 4.3), and + const requestCC = parseCacheControl(req.headers['cache-control']); + + if (requestCC['no-cache'] || /no-cache/.test(req.headers.pragma)) { + return this._evaluateRequestMissResult(req); + } + + if (requestCC['max-age'] && this.age() > toNumberOrZero(requestCC['max-age'])) { + return this._evaluateRequestMissResult(req); + } + + if (requestCC['min-fresh'] && this.maxAge() - this.age() < toNumberOrZero(requestCC['min-fresh'])) { + return this._evaluateRequestMissResult(req); + } + + // the stored response is either: + // fresh, or allowed to be served stale + if (this.stale()) { + // If a value is present, then the client is willing to accept a response that has + // exceeded its freshness lifetime by no more than the specified number of seconds + const allowsStaleWithoutRevalidation = 'max-stale' in requestCC && + (true === requestCC['max-stale'] || requestCC['max-stale'] > this.age() - this.maxAge()); + + if (allowsStaleWithoutRevalidation) { + return this._evaluateRequestHitResult(undefined); + } + + if (this.useStaleWhileRevalidate()) { + return this._evaluateRequestHitResult(this._evaluateRequestRevalidation(req, false)); + } + + return this._evaluateRequestMissResult(req); + } + + return this._evaluateRequestHitResult(undefined); + } + + /** + * @param {HttpRequest} req - check if this is for the same cache entry + * @param {boolean} allowHeadMethod - allow a HEAD method to match. + * @returns {boolean} `true` if the request matches. + */ + _requestMatches(req, allowHeadMethod) { + // The presented effective request URI and that of the stored response match, and + return !!( + (!this._url || this._url === req.url) && + this._host === req.headers.host && + // the request method associated with the stored response allows it to be used for the presented request, and + (!req.method || + this._method === req.method || + (allowHeadMethod && 'HEAD' === req.method)) && + // selecting header fields nominated by the stored response (if any) match those presented, and + this._varyMatches(req) + ); + } + + /** + * Determines whether storing authenticated responses is allowed. + * @returns {boolean} `true` if allowed. + */ + _allowsStoringAuthenticated() { + // following Cache-Control response directives (Section 5.2.2) have such an effect: must-revalidate, public, and s-maxage. + return !!( + this._rescc['must-revalidate'] || + this._rescc.public || + this._rescc['s-maxage'] + ); + } + + /** + * Checks whether the Vary header in the response matches the new request. + * @param {HttpRequest} req - incoming HTTP request + * @returns {boolean} `true` if the vary headers match. + */ + _varyMatches(req) { + if (!this._resHeaders.vary) { + return true; + } + + // A Vary header field-value of "*" always fails to match + if (this._resHeaders.vary === '*') { + return false; + } + + const fields = this._resHeaders.vary + .trim() + .toLowerCase() + .split(/\s*,\s*/); + for (const name of fields) { + if (req.headers[name] !== this._reqHeaders[name]) return false; + } + return true; + } + + /** + * Creates a copy of the given headers without any hop-by-hop headers. + * @param {Record} inHeaders - old headers from the cached response + * @returns {Record} A new headers object without hop-by-hop headers. + */ + _copyWithoutHopByHopHeaders(inHeaders) { + /** @type {Record} */ + const headers = {}; + for (const name in inHeaders) { + if (hopByHopHeaders[name]) continue; + headers[name] = inHeaders[name]; + } + // 9.1. Connection + if (inHeaders.connection) { + const tokens = inHeaders.connection.trim().split(/\s*,\s*/); + for (const name of tokens) { + delete headers[name]; + } + } + if (headers.warning) { + const warnings = headers.warning.split(/,/).filter(warning => { + return !/^\s*1[0-9][0-9]/.test(warning); + }); + if (!warnings.length) { + delete headers.warning; + } else { + headers.warning = warnings.join(',').trim(); + } + } + return headers; + } + + /** + * Returns the response headers adjusted for serving the cached response. + * Removes hop-by-hop headers and updates the Age and Date headers. + * @returns {Record} The adjusted response headers. + */ + responseHeaders() { + const headers = this._copyWithoutHopByHopHeaders(this._resHeaders); + const age = this.age(); + + // A cache SHOULD generate 113 warning if it heuristically chose a freshness + // lifetime greater than 24 hours and the response's age is greater than 24 hours. + if ( + age > 3600 * 24 && + !this._hasExplicitExpiration() && + this.maxAge() > 3600 * 24 + ) { + headers.warning = + (headers.warning ? `${headers.warning}, ` : '') + + '113 - "rfc7234 5.5.4"'; + } + headers.age = `${Math.round(age)}`; + headers.date = new Date(this.now()).toUTCString(); + return headers; + } + + /** + * Returns the Date header value from the response or the current time if invalid. + * @returns {number} Timestamp (in milliseconds) representing the Date header or response time. + */ + date() { + const serverDate = Date.parse(this._resHeaders.date); + if (isFinite(serverDate)) { + return serverDate; + } + return this._responseTime; + } + + /** + * Value of the Age header, in seconds, updated for the current time. + * May be fractional. + * @returns {number} The age in seconds. + */ + age() { + let age = this._ageValue(); + + const residentTime = (this.now() - this._responseTime) / 1000; + return age + residentTime; + } + + /** + * @returns {number} The Age header value as a number. + */ + _ageValue() { + return toNumberOrZero(this._resHeaders.age); + } + + /** + * Possibly outdated value of applicable max-age (or heuristic equivalent) in seconds. + * This counts since response's `Date`. + * + * For an up-to-date value, see `timeToLive()`. + * + * Returns the maximum age (freshness lifetime) of the response in seconds. + * @returns {number} The max-age value in seconds. + */ + maxAge() { + if (!this.storable() || this._rescc['no-cache']) { + return 0; + } + + // Shared responses with cookies are cacheable according to the RFC, but IMHO it'd be unwise to do so by default + // so this implementation requires explicit opt-in via public header + if ( + this._isShared && + (this._resHeaders['set-cookie'] && + !this._rescc.public && + !this._rescc.immutable) + ) { + return 0; + } + + if (this._resHeaders.vary === '*') { + return 0; + } + + if (this._isShared) { + if (this._rescc['proxy-revalidate']) { + return 0; + } + // if a response includes the s-maxage directive, a shared cache recipient MUST ignore the Expires field. + if (this._rescc['s-maxage']) { + return toNumberOrZero(this._rescc['s-maxage']); + } + } + + // If a response includes a Cache-Control field with the max-age directive, a recipient MUST ignore the Expires field. + if (this._rescc['max-age']) { + return toNumberOrZero(this._rescc['max-age']); + } + + const defaultMinTtl = this._rescc.immutable ? this._immutableMinTtl : 0; + + const serverDate = this.date(); + if (this._resHeaders.expires) { + const expires = Date.parse(this._resHeaders.expires); + // A cache recipient MUST interpret invalid date formats, especially the value "0", as representing a time in the past (i.e., "already expired"). + if (Number.isNaN(expires) || expires < serverDate) { + return 0; + } + return Math.max(defaultMinTtl, (expires - serverDate) / 1000); + } + + if (this._resHeaders['last-modified']) { + const lastModified = Date.parse(this._resHeaders['last-modified']); + if (isFinite(lastModified) && serverDate > lastModified) { + return Math.max( + defaultMinTtl, + ((serverDate - lastModified) / 1000) * this._cacheHeuristic + ); + } + } + + return defaultMinTtl; + } + + /** + * Remaining time this cache entry may be useful for, in *milliseconds*. + * You can use this as an expiration time for your cache storage. + * + * Prefer this method over `maxAge()`, because it includes other factors like `age` and `stale-while-revalidate`. + * @returns {number} Time-to-live in milliseconds. + */ + timeToLive() { + const age = this.maxAge() - this.age(); + const staleIfErrorAge = age + toNumberOrZero(this._rescc['stale-if-error']); + const staleWhileRevalidateAge = age + toNumberOrZero(this._rescc['stale-while-revalidate']); + return Math.round(Math.max(0, age, staleIfErrorAge, staleWhileRevalidateAge) * 1000); + } + + /** + * If true, this cache entry is past its expiration date. + * Note that stale cache may be useful sometimes, see `evaluateRequest()`. + * @returns {boolean} `false` doesn't mean it's fresh nor usable + */ + stale() { + return this.maxAge() <= this.age(); + } + + /** + * @returns {boolean} `true` if `stale-if-error` condition allows use of a stale response. + */ + _useStaleIfError() { + return this.maxAge() + toNumberOrZero(this._rescc['stale-if-error']) > this.age(); + } + + /** See `evaluateRequest()` for a more complete solution + * @returns {boolean} `true` if `stale-while-revalidate` is currently allowed. + */ + useStaleWhileRevalidate() { + const swr = toNumberOrZero(this._rescc['stale-while-revalidate']); + return swr > 0 && this.maxAge() + swr > this.age(); + } + + /** + * Creates a `CachePolicy` instance from a serialized object. + * @param {Object} obj - The serialized object. + * @returns {CachePolicy} A new CachePolicy instance. + */ + static fromObject(obj) { + return new this(undefined, undefined, { _fromObject: obj }); + } + + /** + * @param {any} obj - The serialized object. + * @throws {Error} If already initialized or if the object is invalid. + */ + _fromObject(obj) { + if (this._responseTime) throw Error('Reinitialized'); + if (!obj || obj.v !== 1) throw Error('Invalid serialization'); + + this._responseTime = obj.t; + this._isShared = obj.sh; + this._cacheHeuristic = obj.ch; + this._immutableMinTtl = + obj.imm !== undefined ? obj.imm : 24 * 3600 * 1000; + this._ignoreCargoCult = !!obj.icc; + this._status = obj.st; + this._resHeaders = obj.resh; + this._rescc = obj.rescc; + this._method = obj.m; + this._url = obj.u; + this._host = obj.h; + this._noAuthorization = obj.a; + this._reqHeaders = obj.reqh; + this._reqcc = obj.reqcc; + } + + /** + * Serializes the `CachePolicy` instance into a JSON-serializable object. + * @returns {Object} The serialized object. + */ + toObject() { + return { + v: 1, + t: this._responseTime, + sh: this._isShared, + ch: this._cacheHeuristic, + imm: this._immutableMinTtl, + icc: this._ignoreCargoCult, + st: this._status, + resh: this._resHeaders, + rescc: this._rescc, + m: this._method, + u: this._url, + h: this._host, + a: this._noAuthorization, + reqh: this._reqHeaders, + reqcc: this._reqcc, + }; + } + + /** + * Headers for sending to the origin server to revalidate stale response. + * Allows server to return 304 to allow reuse of the previous response. + * + * Hop by hop headers are always stripped. + * Revalidation headers may be added or removed, depending on request. + * @param {HttpRequest} incomingReq - The incoming HTTP request. + * @returns {Record} The headers for the revalidation request. + */ + revalidationHeaders(incomingReq) { + this._assertRequestHasHeaders(incomingReq); + const headers = this._copyWithoutHopByHopHeaders(incomingReq.headers); + + // This implementation does not understand range requests + delete headers['if-range']; + + if (!this._requestMatches(incomingReq, true) || !this.storable()) { + // revalidation allowed via HEAD + // not for the same resource, or wasn't allowed to be cached anyway + delete headers['if-none-match']; + delete headers['if-modified-since']; + return headers; + } + + /* MUST send that entity-tag in any cache validation request (using If-Match or If-None-Match) if an entity-tag has been provided by the origin server. */ + if (this._resHeaders.etag) { + headers['if-none-match'] = headers['if-none-match'] + ? `${headers['if-none-match']}, ${this._resHeaders.etag}` + : this._resHeaders.etag; + } + + // Clients MAY issue simple (non-subrange) GET requests with either weak validators or strong validators. Clients MUST NOT use weak validators in other forms of request. + const forbidsWeakValidators = + headers['accept-ranges'] || + headers['if-match'] || + headers['if-unmodified-since'] || + (this._method && this._method != 'GET'); + + /* SHOULD send the Last-Modified value in non-subrange cache validation requests (using If-Modified-Since) if only a Last-Modified value has been provided by the origin server. + Note: This implementation does not understand partial responses (206) */ + if (forbidsWeakValidators) { + delete headers['if-modified-since']; + + if (headers['if-none-match']) { + const etags = headers['if-none-match'] + .split(/,/) + .filter(etag => { + return !/^\s*W\//.test(etag); + }); + if (!etags.length) { + delete headers['if-none-match']; + } else { + headers['if-none-match'] = etags.join(',').trim(); + } + } + } else if ( + this._resHeaders['last-modified'] && + !headers['if-modified-since'] + ) { + headers['if-modified-since'] = this._resHeaders['last-modified']; + } + + return headers; + } + + /** + * Creates new CachePolicy with information combined from the previews response, + * and the new revalidation response. + * + * Returns {policy, modified} where modified is a boolean indicating + * whether the response body has been modified, and old cached body can't be used. + * + * @param {HttpRequest} request - The latest HTTP request asking for the cached entry. + * @param {HttpResponse} response - The latest revalidation HTTP response from the origin server. + * @returns {{policy: CachePolicy, modified: boolean, matches: boolean}} The updated policy and modification status. + * @throws {Error} If the response headers are missing. + */ + revalidatedPolicy(request, response) { + this._assertRequestHasHeaders(request); + + if (this._useStaleIfError() && isErrorResponse(response)) { + return { + policy: this, + modified: false, + matches: true, + }; + } + + if (!response || !response.headers) { + throw Error('Response headers missing'); + } + + // These aren't going to be supported exactly, since one CachePolicy object + // doesn't know about all the other cached objects. + let matches = false; + if (response.status !== undefined && response.status != 304) { + matches = false; + } else if ( + response.headers.etag && + !/^\s*W\//.test(response.headers.etag) + ) { + // "All of the stored responses with the same strong validator are selected. + // If none of the stored responses contain the same strong validator, + // then the cache MUST NOT use the new response to update any stored responses." + matches = + this._resHeaders.etag && + this._resHeaders.etag.replace(/^\s*W\//, '') === + response.headers.etag; + } else if (this._resHeaders.etag && response.headers.etag) { + // "If the new response contains a weak validator and that validator corresponds + // to one of the cache's stored responses, + // then the most recent of those matching stored responses is selected for update." + matches = + this._resHeaders.etag.replace(/^\s*W\//, '') === + response.headers.etag.replace(/^\s*W\//, ''); + } else if (this._resHeaders['last-modified']) { + matches = + this._resHeaders['last-modified'] === + response.headers['last-modified']; + } else { + // If the new response does not include any form of validator (such as in the case where + // a client generates an If-Modified-Since request from a source other than the Last-Modified + // response header field), and there is only one stored response, and that stored response also + // lacks a validator, then that stored response is selected for update. + if ( + !this._resHeaders.etag && + !this._resHeaders['last-modified'] && + !response.headers.etag && + !response.headers['last-modified'] + ) { + matches = true; + } + } + + const optionsCopy = { + shared: this._isShared, + cacheHeuristic: this._cacheHeuristic, + immutableMinTimeToLive: this._immutableMinTtl, + ignoreCargoCult: this._ignoreCargoCult, + }; + + if (!matches) { + return { + policy: new this.constructor(request, response, optionsCopy), + // Client receiving 304 without body, even if it's invalid/mismatched has no option + // but to reuse a cached body. We don't have a good way to tell clients to do + // error recovery in such case. + modified: response.status != 304, + matches: false, + }; + } + + // use other header fields provided in the 304 (Not Modified) response to replace all instances + // of the corresponding header fields in the stored response. + const headers = {}; + for (const k in this._resHeaders) { + headers[k] = + k in response.headers && !excludedFromRevalidationUpdate[k] + ? response.headers[k] + : this._resHeaders[k]; + } + + const newResponse = Object.assign({}, response, { + status: this._status, + method: this._method, + headers, + }); + return { + policy: new this.constructor(request, newResponse, optionsCopy), + modified: false, + matches: true, + }; + } +}; + + +/***/ }), + +/***/ 20849: +/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { + + +// EXPORTS +__webpack_require__.d(__webpack_exports__, { + "default": () => (/* binding */ source) +}); + +// UNUSED EXPORTS: AbortError, CacheError, HTTPError, MaxRedirectsError, Options, ParseError, ReadError, RequestError, RetryError, TimeoutError, UploadError, applyUrlOverride, assertUrlHasSameOriginAsPrefixUrlIfNeeded, cacheDecodedBody, calculateRetryDelay, create, crossOriginStripHeaders, decodeUint8Array, generateRequestId, getUrlPrefixBoundary, hasExplicitCredentialInUrlChange, hasUrlOrPrefixUrlBoundaryChanged, isBodyUnchanged, isCrossOriginCredentialChanged, isResponseOk, isSameOrigin, isUtf8Encoding, normalizeError, parseBody, parseLinkHeader, publishError, publishRedirect, publishRequestCreate, publishRequestStart, publishResponseEnd, publishResponseStart, publishRetry, snapshotCrossOriginState + +// EXTERNAL MODULE: external "node:timers/promises" +var promises_ = __webpack_require__(58500); +;// CONCATENATED MODULE: ./node_modules/@sindresorhus/is/distribution/utilities.js +function keysOf(value) { + return Object.keys(value); +} + +;// CONCATENATED MODULE: ./node_modules/@sindresorhus/is/distribution/index.js + +const typedArrayTypeNames = [ + 'Int8Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'Int16Array', + 'Uint16Array', + 'Int32Array', + 'Uint32Array', + 'Float32Array', + 'Float64Array', + 'BigInt64Array', + 'BigUint64Array', +]; +function isTypedArrayName(name) { + return typedArrayTypeNames.includes(name); +} +const objectTypeNames = [ + 'Function', + 'Generator', + 'AsyncGenerator', + 'GeneratorFunction', + 'AsyncGeneratorFunction', + 'AsyncFunction', + 'Observable', + 'Array', + 'Buffer', + 'Blob', + 'Object', + 'RegExp', + 'Date', + 'Error', + 'Map', + 'Set', + 'WeakMap', + 'WeakSet', + 'WeakRef', + 'ArrayBuffer', + 'SharedArrayBuffer', + 'DataView', + 'Promise', + 'URL', + 'FormData', + 'URLSearchParams', + 'HTMLElement', + 'NaN', + ...typedArrayTypeNames, +]; +function isObjectTypeName(name) { + return objectTypeNames.includes(name); +} +const primitiveTypeNames = [ + 'null', + 'undefined', + 'string', + 'number', + 'bigint', + 'boolean', + 'symbol', +]; +function isPrimitiveTypeName(name) { + return primitiveTypeNames.includes(name); +} +const assertionTypeDescriptions = [ + 'bound Function', + 'positive number', + 'negative number', + 'Class', + 'string with a number', + 'null or undefined', + 'Iterable', + 'AsyncIterable', + 'native Promise', + 'EnumCase', + 'string with a URL', + 'truthy', + 'falsy', + 'primitive', + 'integer', + 'plain object', + 'TypedArray', + 'array-like', + 'tuple-like', + 'Node.js Stream', + 'infinite number', + 'empty array', + 'non-empty array', + 'empty string', + 'empty string or whitespace', + 'non-empty string', + 'non-empty string and not whitespace', + 'empty object', + 'non-empty object', + 'empty set', + 'non-empty set', + 'empty map', + 'non-empty map', + 'PropertyKey', + 'even integer', + 'finite number', + 'negative integer', + 'non-negative integer', + 'non-negative number', + 'odd integer', + 'positive integer', + 'safe integer', + 'T', + 'in range', + 'predicate returns truthy for any value', + 'predicate returns truthy for all values', + 'valid Date', + 'valid length', + 'whitespace string', + ...objectTypeNames, + ...primitiveTypeNames, +]; +const getObjectType = (value) => { + const objectTypeName = Object.prototype.toString.call(value).slice(8, -1); + if (/HTML\w+Element/v.test(objectTypeName) && isHtmlElement(value)) { + return 'HTMLElement'; + } + if (isObjectTypeName(objectTypeName)) { + return objectTypeName; + } + return undefined; +}; +function detect(value) { + if (value === null) { + return 'null'; + } + // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check + switch (typeof value) { + case 'undefined': { + return 'undefined'; + } + case 'string': { + return 'string'; + } + case 'number': { + return Number.isNaN(value) ? 'NaN' : 'number'; + } + case 'boolean': { + return 'boolean'; + } + case 'function': { + return 'Function'; + } + case 'bigint': { + return 'bigint'; + } + case 'symbol': { + return 'symbol'; + } + default: + } + if (isObservable(value)) { + return 'Observable'; + } + if (isArray(value)) { + return 'Array'; + } + if (isBuffer(value)) { + return 'Buffer'; + } + const tagType = getObjectType(value); + if (tagType !== undefined && tagType !== 'Object') { + return tagType; + } + if (hasPromiseApi(value)) { + return 'Promise'; + } + if (isBoxedPrimitiveObject(value)) { + throw new TypeError('Please don\'t use object wrappers for primitive types'); + } + return 'Object'; +} +function hasPromiseApi(value) { + return isFunction(value?.then) && isFunction(value?.catch); +} +function hasBoxedPrimitiveBrand(value, valueOf) { + try { + // `Object.prototype.toString` can be spoofed via `Symbol.toStringTag`, but the + // boxed primitive `valueOf` methods still enforce the real internal brand. + Reflect.apply(valueOf, value, []); + return true; + } + catch { + return false; + } +} +function isBoxedPrimitiveObject(value) { + return hasBoxedPrimitiveBrand(value, String.prototype.valueOf) + || hasBoxedPrimitiveBrand(value, Boolean.prototype.valueOf) + || hasBoxedPrimitiveBrand(value, Number.prototype.valueOf); +} +const is = Object.assign(detect, { + all: isAll, + any: isAny, + array: isArray, + arrayBuffer: isArrayBuffer, + arrayLike: isArrayLike, + arrayOf: isArrayOf, + asyncFunction: isAsyncFunction, + asyncGenerator: isAsyncGenerator, + asyncGeneratorFunction: isAsyncGeneratorFunction, + asyncIterable: isAsyncIterable, + bigint: isBigint, + bigInt64Array: isBigInt64Array, + bigUint64Array: isBigUint64Array, + blob: isBlob, + boolean: isBoolean, + boundFunction: isBoundFunction, + buffer: isBuffer, + class: isClass, + dataView: isDataView, + date: isDate, + detect, + directInstanceOf: isDirectInstanceOf, + emptyArray: isEmptyArray, + emptyMap: isEmptyMap, + emptyObject: isEmptyObject, + emptySet: isEmptySet, + emptyString: isEmptyString, + emptyStringOrWhitespace: isEmptyStringOrWhitespace, + enumCase: isEnumCase, + error: isError, + evenInteger: isEvenInteger, + falsy: isFalsy, + finiteNumber: isFiniteNumber, + float32Array: isFloat32Array, + float64Array: isFloat64Array, + formData: isFormData, + function: isFunction, + generator: isGenerator, + generatorFunction: isGeneratorFunction, + htmlElement: isHtmlElement, + infinite: isInfinite, + inRange: isInRange, + int16Array: isInt16Array, + int32Array: isInt32Array, + int8Array: isInt8Array, + integer: isInteger, + iterable: isIterable, + map: isMap, + nan: isNan, + nativePromise: isNativePromise, + negativeInteger: isNegativeInteger, + negativeNumber: isNegativeNumber, + nodeStream: isNodeStream, + nonEmptyArray: isNonEmptyArray, + nonEmptyMap: isNonEmptyMap, + nonEmptyObject: isNonEmptyObject, + nonEmptySet: isNonEmptySet, + nonEmptyString: isNonEmptyString, + nonEmptyStringAndNotWhitespace: isNonEmptyStringAndNotWhitespace, + nonNegativeInteger: isNonNegativeInteger, + nonNegativeNumber: isNonNegativeNumber, + null: isNull, + nullOrUndefined: isNullOrUndefined, + number: isNumber, + numericString: isNumericString, + object: isObject, + observable: isObservable, + oddInteger: isOddInteger, + oneOf: isOneOf, + plainObject: isPlainObject, + positiveInteger: isPositiveInteger, + positiveNumber: isPositiveNumber, + primitive: isPrimitive, + promise: isPromise, + propertyKey: isPropertyKey, + regExp: isRegExp, + safeInteger: isSafeInteger, + set: isSet, + sharedArrayBuffer: isSharedArrayBuffer, + string: isString, + symbol: isSymbol, + truthy: isTruthy, + tupleLike: isTupleLike, + typedArray: isTypedArray, + uint16Array: isUint16Array, + uint32Array: isUint32Array, + uint8Array: isUint8Array, + uint8ClampedArray: isUint8ClampedArray, + undefined: isUndefined, + urlInstance: isUrlInstance, + urlSearchParams: isUrlSearchParams, + urlString: isUrlString, + optional: isOptional, + validDate: isValidDate, + validLength: isValidLength, + weakMap: isWeakMap, + weakRef: isWeakRef, + weakSet: isWeakSet, + whitespaceString: isWhitespaceString, +}); +function isAbsoluteModule2(remainder) { + return (value) => isInteger(value) && Math.abs(value % 2) === remainder; +} +function validatePredicateArray(predicateArray, allowEmpty) { + if (predicateArray.length === 0) { + if (allowEmpty) { + // Next major release: throw for empty predicate arrays to avoid vacuous results. + // throw new TypeError('Invalid predicate array'); + } + else { + throw new TypeError('Invalid predicate array'); + } + return; + } + for (const predicate of predicateArray) { + validatePredicate(predicate); + } +} +function validatePredicate(predicate) { + if (!isFunction(predicate)) { + throw new TypeError(`Invalid predicate: ${JSON.stringify(predicate)}`); + } +} +function isAll(predicate, ...values) { + if (Array.isArray(predicate)) { + const predicateArray = predicate; + validatePredicateArray(predicateArray, values.length === 0); + const combinedPredicate = (value) => predicateArray.every(singlePredicate => singlePredicate(value)); + if (values.length === 0) { + return combinedPredicate; + } + return predicateOnArray(Array.prototype.every, combinedPredicate, values); + } + return predicateOnArray(Array.prototype.every, predicate, values); +} +function isAny(predicate, ...values) { + if (Array.isArray(predicate)) { + const predicateArray = predicate; + validatePredicateArray(predicateArray, values.length === 0); + const combinedPredicate = (value) => predicateArray.some(singlePredicate => singlePredicate(value)); + if (values.length === 0) { + return combinedPredicate; + } + return predicateOnArray(Array.prototype.some, combinedPredicate, values); + } + return predicateOnArray(Array.prototype.some, predicate, values); +} +function isOptional(value, predicate) { + return isUndefined(value) || predicate(value); +} +function isArray(value, assertion) { + if (!Array.isArray(value)) { + return false; + } + if (!isFunction(assertion)) { + return true; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + return value.every(element => assertion(element)); +} +function isArrayBuffer(value) { + return getObjectType(value) === 'ArrayBuffer'; +} +function isArrayLike(value) { + return !isNullOrUndefined(value) && !isFunction(value) && isValidLength(value.length); +} +function isArrayOf(predicate) { + return (value) => isArray(value) && value.every(element => predicate(element)); +} +function isAsyncFunction(value) { + return getObjectType(value) === 'AsyncFunction'; +} +function isAsyncGenerator(value) { + return isAsyncIterable(value) && isFunction(value.next) && isFunction(value.throw); +} +function isAsyncGeneratorFunction(value) { + return getObjectType(value) === 'AsyncGeneratorFunction'; +} +function isAsyncIterable(value) { + return isFunction(value?.[Symbol.asyncIterator]); +} +function isBigint(value) { + return typeof value === 'bigint'; +} +function isBigInt64Array(value) { + return getObjectType(value) === 'BigInt64Array'; +} +function isBigUint64Array(value) { + return getObjectType(value) === 'BigUint64Array'; +} +function isBlob(value) { + return getObjectType(value) === 'Blob'; +} +function isBoolean(value) { + return value === true || value === false; +} +// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type +function isBoundFunction(value) { + return isFunction(value) && !Object.hasOwn(value, 'prototype'); +} +/** +Note: [Prefer using `Uint8Array` instead of `Buffer`.](https://sindresorhus.com/blog/goodbye-nodejs-buffer) +*/ +function isBuffer(value) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + return value?.constructor?.isBuffer?.(value) ?? false; +} +function isClass(value) { + return isFunction(value) && /^class(?:\s+|\{)/v.test(value.toString()); +} +function isDataView(value) { + return getObjectType(value) === 'DataView'; +} +function isDate(value) { + return getObjectType(value) === 'Date'; +} +function isDirectInstanceOf(instance, class_) { + if (instance === undefined || instance === null) { + return false; + } + return Object.getPrototypeOf(instance) === class_.prototype; +} +function isEmptyArray(value) { + return isArray(value) && value.length === 0; +} +function isEmptyMap(value) { + return isMap(value) && value.size === 0; +} +function isEmptyObject(value) { + return isObject(value) && !isFunction(value) && !isArray(value) && !isMap(value) && !isSet(value) && Object.keys(value).length === 0; +} +function isEmptySet(value) { + return isSet(value) && value.size === 0; +} +function isEmptyString(value) { + return isString(value) && value.length === 0; +} +function isEmptyStringOrWhitespace(value) { + return isEmptyString(value) || isWhitespaceString(value); +} +function isEnumCase(value, targetEnum) { + // Numeric enums have reverse mappings (e.g. `Direction[0] = "Up"`), so their runtime object contains both `{ Up: 0 }` and `{ "0": "Up" }`. Filtering out entries that round-trip like a canonical number and point back to an own property leaves only actual enum member values. + const enumObject = targetEnum; + return Object.entries(enumObject).some(([key, enumValue]) => { + if (!isString(enumValue)) { + return enumValue === value; + } + const numericKey = Number(key); + if (Number.isNaN(numericKey) || String(numericKey) !== key) { + return enumValue === value; + } + return enumValue === value && !(Object.hasOwn(enumObject, enumValue) && enumObject[enumValue] === numericKey); + }); +} +function isError(value) { + // TODO: Use `Error.isError` when targeting Node.js 24. + return getObjectType(value) === 'Error'; +} +function isEvenInteger(value) { + return isAbsoluteModule2(0)(value); +} +// Example: `is.falsy = (value: unknown): value is (not true | 0 | '' | undefined | null) => Boolean(value);` +function isFalsy(value) { + return !value; +} +function isFiniteNumber(value) { + return Number.isFinite(value); +} +// TODO: Support detecting Float16Array when targeting Node.js 24. +function isFloat32Array(value) { + return getObjectType(value) === 'Float32Array'; +} +function isFloat64Array(value) { + return getObjectType(value) === 'Float64Array'; +} +function isFormData(value) { + return getObjectType(value) === 'FormData'; +} +// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type +function isFunction(value) { + return typeof value === 'function'; +} +function isGenerator(value) { + return isIterable(value) && isFunction(value?.next) && isFunction(value?.throw); +} +function isGeneratorFunction(value) { + return getObjectType(value) === 'GeneratorFunction'; +} +const NODE_TYPE_ELEMENT = 1; // eslint-disable-line @typescript-eslint/naming-convention +const DOM_PROPERTIES_TO_CHECK = [ + 'innerHTML', + 'ownerDocument', + 'style', + 'attributes', + 'nodeValue', +]; +function isHtmlElement(value) { + return isObject(value) + && value.nodeType === NODE_TYPE_ELEMENT + && isString(value.nodeName) + && !isPlainObject(value) + && DOM_PROPERTIES_TO_CHECK.every(property => property in value); +} +function isInfinite(value) { + return value === Number.POSITIVE_INFINITY || value === Number.NEGATIVE_INFINITY; +} +function isInRange(value, range) { + if (isNumber(range)) { + return value >= Math.min(0, range) && value <= Math.max(range, 0); + } + if (isArray(range) && range.length === 2) { + if (Number.isNaN(range[0]) || Number.isNaN(range[1])) { + throw new TypeError(`Invalid range: ${JSON.stringify(range)}`); + } + return value >= Math.min(...range) && value <= Math.max(...range); + } + throw new TypeError(`Invalid range: ${JSON.stringify(range)}`); +} +function isInt16Array(value) { + return getObjectType(value) === 'Int16Array'; +} +function isInt32Array(value) { + return getObjectType(value) === 'Int32Array'; +} +function isInt8Array(value) { + return getObjectType(value) === 'Int8Array'; +} +function isInteger(value) { + return Number.isInteger(value); +} +function isIterable(value) { + return isFunction(value?.[Symbol.iterator]); +} +function isMap(value) { + return getObjectType(value) === 'Map'; +} +function isNan(value) { + return Number.isNaN(value); +} +function isNativePromise(value) { + return getObjectType(value) === 'Promise'; +} +function isNegativeInteger(value) { + return isInteger(value) && value < 0; +} +function isNegativeNumber(value) { + return isNumber(value) && value < 0; +} +function isNodeStream(value) { + return isObject(value) && isFunction(value.pipe) && !isObservable(value); +} +function isNonEmptyArray(value) { + return isArray(value) && value.length > 0; +} +function isNonEmptyMap(value) { + return isMap(value) && value.size > 0; +} +// TODO: Use `not` operator here to remove `Map` and `Set` from type guard: +// - https://github.com/Microsoft/TypeScript/pull/29317 +function isNonEmptyObject(value) { + return isObject(value) && !isFunction(value) && !isArray(value) && !isMap(value) && !isSet(value) && Object.keys(value).length > 0; +} +function isNonEmptySet(value) { + return isSet(value) && value.size > 0; +} +// TODO: Use `not ''` when the `not` operator is available. +function isNonEmptyString(value) { + return isString(value) && value.length > 0; +} +// TODO: Use `not ''` when the `not` operator is available. +function isNonEmptyStringAndNotWhitespace(value) { + return isString(value) && !isEmptyStringOrWhitespace(value); +} +function isNonNegativeInteger(value) { + return isInteger(value) && value >= 0; +} +function isNonNegativeNumber(value) { + return isNumber(value) && value >= 0; +} +// eslint-disable-next-line @typescript-eslint/no-restricted-types +function isNull(value) { + return value === null; +} +// eslint-disable-next-line @typescript-eslint/no-restricted-types +function isNullOrUndefined(value) { + return isNull(value) || isUndefined(value); +} +function isNumber(value) { + return typeof value === 'number' && !Number.isNaN(value); +} +function isNumericString(value) { + return isString(value) && !isEmptyStringOrWhitespace(value) && value === value.trim() && !Number.isNaN(Number(value)); +} +// eslint-disable-next-line @typescript-eslint/no-restricted-types +function isObject(value) { + return !isNull(value) && (typeof value === 'object' || isFunction(value)); +} +function isObservable(value) { + if (!value) { + return false; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + if (Symbol.observable !== undefined && value === value[Symbol.observable]?.()) { + return true; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + if (value === value['@@observable']?.()) { + return true; + } + return false; +} +function isOddInteger(value) { + return isAbsoluteModule2(1)(value); +} +function isOneOf(values) { + return (value) => values.includes(value); +} +function isPlainObject(value) { + // From: https://github.com/sindresorhus/is-plain-obj/blob/main/index.js + if (typeof value !== 'object' || value === null) { + return false; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const prototype = Object.getPrototypeOf(value); + return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value); +} +function isPositiveInteger(value) { + return isInteger(value) && value > 0; +} +function isPositiveNumber(value) { + return isNumber(value) && value > 0; +} +function isPrimitive(value) { + return isNull(value) || isPrimitiveTypeName(typeof value); +} +function isPromise(value) { + return isNativePromise(value) || hasPromiseApi(value); +} +// `PropertyKey` is any value that can be used as an object key (string, number, or symbol). Note: NaN is technically `typeof 'number'` and thus fits TypeScript's `PropertyKey`, but we intentionally exclude it here because using NaN as a property key is almost always a mistake. +function isPropertyKey(value) { + return isAny([isString, isNumber, isSymbol], value); +} +function isRegExp(value) { + return getObjectType(value) === 'RegExp'; +} +function isSafeInteger(value) { + return Number.isSafeInteger(value); +} +function isSet(value) { + return getObjectType(value) === 'Set'; +} +function isSharedArrayBuffer(value) { + return getObjectType(value) === 'SharedArrayBuffer'; +} +function isString(value) { + return typeof value === 'string'; +} +function isSymbol(value) { + return typeof value === 'symbol'; +} +// Example: `is.truthy = (value: unknown): value is (not false | not 0 | not '' | not undefined | not null) => Boolean(value);` +// eslint-disable-next-line unicorn/prefer-native-coercion-functions +function isTruthy(value) { + return Boolean(value); +} +function isTupleLike(value, guards) { + if (isArray(guards) && isArray(value) && guards.length === value.length) { + return guards.every((guard, index) => guard(value[index])); + } + return false; +} +function isTypedArray(value) { + return isTypedArrayName(getObjectType(value)); +} +function isUint16Array(value) { + return getObjectType(value) === 'Uint16Array'; +} +function isUint32Array(value) { + return getObjectType(value) === 'Uint32Array'; +} +function isUint8Array(value) { + return getObjectType(value) === 'Uint8Array'; +} +function isUint8ClampedArray(value) { + return getObjectType(value) === 'Uint8ClampedArray'; +} +function isUndefined(value) { + return value === undefined; +} +function isUrlInstance(value) { + return getObjectType(value) === 'URL'; +} +// eslint-disable-next-line unicorn/prevent-abbreviations +function isUrlSearchParams(value) { + return getObjectType(value) === 'URLSearchParams'; +} +function isUrlString(value) { + if (!isString(value)) { + return false; + } + try { + new URL(value); // eslint-disable-line no-new + return true; + } + catch { + return false; + } +} +function isValidDate(value) { + return isDate(value) && !isNan(Number(value)); +} +function isValidLength(value) { + return isSafeInteger(value) && value >= 0; +} +// eslint-disable-next-line @typescript-eslint/no-restricted-types +function isWeakMap(value) { + return getObjectType(value) === 'WeakMap'; +} +// eslint-disable-next-line @typescript-eslint/no-restricted-types +function isWeakRef(value) { + return getObjectType(value) === 'WeakRef'; +} +// eslint-disable-next-line @typescript-eslint/no-restricted-types +function isWeakSet(value) { + return getObjectType(value) === 'WeakSet'; +} +function isWhitespaceString(value) { + return isString(value) && /^\s+$/v.test(value); +} +function predicateOnArray(method, predicate, values) { + validatePredicate(predicate); + if (values.length === 0) { + throw new TypeError('Invalid number of values'); + } + return method.call(values, predicate); +} +function typeErrorMessage(description, value) { + return `Expected value which is \`${description}\`, received value of type \`${is(value)}\`.`; +} +function typeErrorMessageNot(description, value) { + return `Expected value which is not \`${description}\`, received value of type \`${is(value)}\`.`; +} +function unique(values) { + // eslint-disable-next-line unicorn/prefer-spread + return Array.from(new Set(values)); +} +const andFormatter = new Intl.ListFormat('en', { style: 'long', type: 'conjunction' }); +const orFormatter = new Intl.ListFormat('en', { style: 'long', type: 'disjunction' }); +function typeErrorMessageMultipleValues(expectedType, values) { + const uniqueExpectedTypes = unique((isArray(expectedType) ? expectedType : [expectedType]).map(value => `\`${value}\``)); + const uniqueValueTypes = unique(values.map(value => `\`${is(value)}\``)); + return `Expected values which are ${orFormatter.format(uniqueExpectedTypes)}. Received values of type${uniqueValueTypes.length > 1 ? 's' : ''} ${andFormatter.format(uniqueValueTypes)}.`; +} +// Negative assertions are limited to types where the assertion rejects every TypeScript value assignable to the forbidden type. Structural object types such as `Map`, `Set`, `Date`, and `Array` are excluded because TypeScript accepts shape-compatible mocks while the runtime checks use object brands, so `Exclude` would narrow values that can pass the negative assertion. +function createAssertNot(predicate, description) { + return (value, message) => { + if (predicate(value)) { + throw new TypeError(message ?? typeErrorMessageNot(description, value)); + } + }; +} +const assertNotUndefined = createAssertNot(isUndefined, 'undefined'); +// eslint-disable-next-line @typescript-eslint/no-restricted-types +const assertNotNull = createAssertNot(isNull, 'null'); +// eslint-disable-next-line @typescript-eslint/no-restricted-types +const assertNotNullOrUndefined +// eslint-disable-next-line @typescript-eslint/no-restricted-types += createAssertNot(isNullOrUndefined, 'null or undefined'); +const assertNotString = createAssertNot(isString, 'string'); +const assertNotBoolean = createAssertNot(isBoolean, 'boolean'); +const assertNotSymbol = createAssertNot(isSymbol, 'symbol'); +const assertNotBigint = createAssertNot(isBigint, 'bigint'); +const assertNotPrimitive = createAssertNot(isPrimitive, 'primitive'); // eslint-disable-line @typescript-eslint/no-restricted-types +// We intentionally do not support `assert.not(is.undefined, value)`. TypeScript cannot derive safe complement types from arbitrary predicates, and many predicates here are refinements (for example, `is.number` rejects `NaN`). Explicit methods keep runtime checks and type narrowing aligned. +const notAssertions = { + bigint: assertNotBigint, + boolean: assertNotBoolean, + null: assertNotNull, + nullOrUndefined: assertNotNullOrUndefined, + primitive: assertNotPrimitive, + string: assertNotString, + symbol: assertNotSymbol, + undefined: assertNotUndefined, +}; +const assert = { + all: assertAll, + any: assertAny, + not: notAssertions, + optional: assertOptional, + array: assertArray, + arrayBuffer: assertArrayBuffer, + arrayLike: assertArrayLike, + asyncFunction: assertAsyncFunction, + asyncGenerator: assertAsyncGenerator, + asyncGeneratorFunction: assertAsyncGeneratorFunction, + asyncIterable: assertAsyncIterable, + bigint: assertBigint, + bigInt64Array: assertBigInt64Array, + bigUint64Array: assertBigUint64Array, + blob: assertBlob, + boolean: assertBoolean, + boundFunction: assertBoundFunction, + buffer: assertBuffer, + class: assertClass, + dataView: assertDataView, + date: assertDate, + directInstanceOf: assertDirectInstanceOf, + emptyArray: assertEmptyArray, + emptyMap: assertEmptyMap, + emptyObject: assertEmptyObject, + emptySet: assertEmptySet, + emptyString: assertEmptyString, + emptyStringOrWhitespace: assertEmptyStringOrWhitespace, + enumCase: assertEnumCase, + error: assertError, + evenInteger: assertEvenInteger, + falsy: assertFalsy, + finiteNumber: assertFiniteNumber, + float32Array: assertFloat32Array, + float64Array: assertFloat64Array, + formData: assertFormData, + function: assertFunction, + generator: assertGenerator, + generatorFunction: assertGeneratorFunction, + htmlElement: assertHtmlElement, + infinite: assertInfinite, + inRange: assertInRange, + int16Array: assertInt16Array, + int32Array: assertInt32Array, + int8Array: assertInt8Array, + integer: assertInteger, + iterable: assertIterable, + map: assertMap, + nan: assertNan, + nativePromise: assertNativePromise, + negativeInteger: assertNegativeInteger, + negativeNumber: assertNegativeNumber, + nodeStream: assertNodeStream, + nonEmptyArray: assertNonEmptyArray, + nonEmptyMap: assertNonEmptyMap, + nonEmptyObject: assertNonEmptyObject, + nonEmptySet: assertNonEmptySet, + nonEmptyString: assertNonEmptyString, + nonEmptyStringAndNotWhitespace: assertNonEmptyStringAndNotWhitespace, + nonNegativeInteger: assertNonNegativeInteger, + nonNegativeNumber: assertNonNegativeNumber, + null: assertNull, + nullOrUndefined: assertNullOrUndefined, + number: assertNumber, + numericString: assertNumericString, + object: assertObject, + observable: assertObservable, + oddInteger: assertOddInteger, + plainObject: assertPlainObject, + positiveInteger: assertPositiveInteger, + positiveNumber: assertPositiveNumber, + primitive: assertPrimitive, + promise: assertPromise, + propertyKey: assertPropertyKey, + regExp: assertRegExp, + safeInteger: assertSafeInteger, + set: assertSet, + sharedArrayBuffer: assertSharedArrayBuffer, + string: assertString, + symbol: assertSymbol, + truthy: assertTruthy, + tupleLike: assertTupleLike, + typedArray: assertTypedArray, + uint16Array: assertUint16Array, + uint32Array: assertUint32Array, + uint8Array: assertUint8Array, + uint8ClampedArray: assertUint8ClampedArray, + undefined: assertUndefined, + urlInstance: assertUrlInstance, + urlSearchParams: assertUrlSearchParams, + urlString: assertUrlString, + validDate: assertValidDate, + validLength: assertValidLength, + weakMap: assertWeakMap, + weakRef: assertWeakRef, + weakSet: assertWeakSet, + whitespaceString: assertWhitespaceString, +}; +const methodTypeMap = { + isArray: 'Array', + isArrayBuffer: 'ArrayBuffer', + isArrayLike: 'array-like', + isAsyncFunction: 'AsyncFunction', + isAsyncGenerator: 'AsyncGenerator', + isAsyncGeneratorFunction: 'AsyncGeneratorFunction', + isAsyncIterable: 'AsyncIterable', + isBigint: 'bigint', + isBigInt64Array: 'BigInt64Array', + isBigUint64Array: 'BigUint64Array', + isBlob: 'Blob', + isBoolean: 'boolean', + isBoundFunction: 'bound Function', + isBuffer: 'Buffer', + isClass: 'Class', + isDataView: 'DataView', + isDate: 'Date', + isDirectInstanceOf: 'T', + isEmptyArray: 'empty array', + isEmptyMap: 'empty map', + isEmptyObject: 'empty object', + isEmptySet: 'empty set', + isEmptyString: 'empty string', + isEmptyStringOrWhitespace: 'empty string or whitespace', + isEnumCase: 'EnumCase', + isError: 'Error', + isEvenInteger: 'even integer', + isFalsy: 'falsy', + isFiniteNumber: 'finite number', + isFloat32Array: 'Float32Array', + isFloat64Array: 'Float64Array', + isFormData: 'FormData', + isFunction: 'Function', + isGenerator: 'Generator', + isGeneratorFunction: 'GeneratorFunction', + isHtmlElement: 'HTMLElement', + isInfinite: 'infinite number', + isInRange: 'in range', + isInt16Array: 'Int16Array', + isInt32Array: 'Int32Array', + isInt8Array: 'Int8Array', + isInteger: 'integer', + isIterable: 'Iterable', + isMap: 'Map', + isNan: 'NaN', + isNativePromise: 'native Promise', + isNegativeInteger: 'negative integer', + isNegativeNumber: 'negative number', + isNodeStream: 'Node.js Stream', + isNonEmptyArray: 'non-empty array', + isNonEmptyMap: 'non-empty map', + isNonEmptyObject: 'non-empty object', + isNonEmptySet: 'non-empty set', + isNonEmptyString: 'non-empty string', + isNonEmptyStringAndNotWhitespace: 'non-empty string and not whitespace', + isNonNegativeInteger: 'non-negative integer', + isNonNegativeNumber: 'non-negative number', + isNull: 'null', + isNullOrUndefined: 'null or undefined', + isNumber: 'number', + isNumericString: 'string with a number', + isObject: 'Object', + isObservable: 'Observable', + isOddInteger: 'odd integer', + isPlainObject: 'plain object', + isPositiveInteger: 'positive integer', + isPositiveNumber: 'positive number', + isPrimitive: 'primitive', + isPromise: 'Promise', + isPropertyKey: 'PropertyKey', + isRegExp: 'RegExp', + isSafeInteger: 'safe integer', + isSet: 'Set', + isSharedArrayBuffer: 'SharedArrayBuffer', + isString: 'string', + isSymbol: 'symbol', + isTruthy: 'truthy', + isTupleLike: 'tuple-like', + isTypedArray: 'TypedArray', + isUint16Array: 'Uint16Array', + isUint32Array: 'Uint32Array', + isUint8Array: 'Uint8Array', + isUint8ClampedArray: 'Uint8ClampedArray', + isUndefined: 'undefined', + isUrlInstance: 'URL', + isUrlSearchParams: 'URLSearchParams', + isUrlString: 'string with a URL', + isValidDate: 'valid Date', + isValidLength: 'valid length', + isWeakMap: 'WeakMap', + isWeakRef: 'WeakRef', + isWeakSet: 'WeakSet', + isWhitespaceString: 'whitespace string', +}; +const isMethodNames = keysOf(methodTypeMap); +function isIsMethodName(value) { + return isMethodNames.includes(value); +} +function assertAll(predicate, ...values) { + if (values.length === 0) { + throw new TypeError('Invalid number of values'); + } + if (!isAll(predicate, ...values)) { + const predicateFunction = predicate; + const expectedType = !Array.isArray(predicate) && isIsMethodName(predicateFunction.name) ? methodTypeMap[predicateFunction.name] : 'predicate returns truthy for all values'; + throw new TypeError(typeErrorMessageMultipleValues(expectedType, values)); + } +} +function assertAny(predicate, ...values) { + if (values.length === 0) { + throw new TypeError('Invalid number of values'); + } + if (!isAny(predicate, ...values)) { + const predicates = Array.isArray(predicate) ? predicate : [predicate]; + const expectedTypes = predicates.map(singlePredicate => isIsMethodName(singlePredicate.name) ? methodTypeMap[singlePredicate.name] : 'predicate returns truthy for any value'); + throw new TypeError(typeErrorMessageMultipleValues(expectedTypes, values)); + } +} +function assertOptional(value, assertion, message) { + if (!isUndefined(value)) { + assertion(value, message); + } +} +function assertArray(value, assertion, message) { + if (!isArray(value)) { + throw new TypeError(message ?? typeErrorMessage('Array', value)); + } + if (assertion) { + for (const element of value) { + // @ts-expect-error: "Assertions require every name in the call target to be declared with an explicit type annotation." + assertion(element, message); + } + } +} +function assertArrayBuffer(value, message) { + if (!isArrayBuffer(value)) { + throw new TypeError(message ?? typeErrorMessage('ArrayBuffer', value)); + } +} +function assertArrayLike(value, message) { + if (!isArrayLike(value)) { + throw new TypeError(message ?? typeErrorMessage('array-like', value)); + } +} +// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type +function assertAsyncFunction(value, message) { + if (!isAsyncFunction(value)) { + throw new TypeError(message ?? typeErrorMessage('AsyncFunction', value)); + } +} +function assertAsyncGenerator(value, message) { + if (!isAsyncGenerator(value)) { + throw new TypeError(message ?? typeErrorMessage('AsyncGenerator', value)); + } +} +function assertAsyncGeneratorFunction(value, message) { + if (!isAsyncGeneratorFunction(value)) { + throw new TypeError(message ?? typeErrorMessage('AsyncGeneratorFunction', value)); + } +} +function assertAsyncIterable(value, message) { + if (!isAsyncIterable(value)) { + throw new TypeError(message ?? typeErrorMessage('AsyncIterable', value)); + } +} +function assertBigint(value, message) { + if (!isBigint(value)) { + throw new TypeError(message ?? typeErrorMessage('bigint', value)); + } +} +function assertBigInt64Array(value, message) { + if (!isBigInt64Array(value)) { + throw new TypeError(message ?? typeErrorMessage('BigInt64Array', value)); + } +} +function assertBigUint64Array(value, message) { + if (!isBigUint64Array(value)) { + throw new TypeError(message ?? typeErrorMessage('BigUint64Array', value)); + } +} +function assertBlob(value, message) { + if (!isBlob(value)) { + throw new TypeError(message ?? typeErrorMessage('Blob', value)); + } +} +function assertBoolean(value, message) { + if (!isBoolean(value)) { + throw new TypeError(message ?? typeErrorMessage('boolean', value)); + } +} +// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type +function assertBoundFunction(value, message) { + if (!isBoundFunction(value)) { + throw new TypeError(message ?? typeErrorMessage('bound Function', value)); + } +} +/** +Note: [Prefer using `Uint8Array` instead of `Buffer`.](https://sindresorhus.com/blog/goodbye-nodejs-buffer) +*/ +function assertBuffer(value, message) { + if (!isBuffer(value)) { + throw new TypeError(message ?? typeErrorMessage('Buffer', value)); + } +} +function assertClass(value, message) { + if (!isClass(value)) { + throw new TypeError(message ?? typeErrorMessage('Class', value)); + } +} +function assertDataView(value, message) { + if (!isDataView(value)) { + throw new TypeError(message ?? typeErrorMessage('DataView', value)); + } +} +function assertDate(value, message) { + if (!isDate(value)) { + throw new TypeError(message ?? typeErrorMessage('Date', value)); + } +} +function assertDirectInstanceOf(instance, class_, message) { + if (!isDirectInstanceOf(instance, class_)) { + throw new TypeError(message ?? typeErrorMessage('T', instance)); + } +} +function assertEmptyArray(value, message) { + if (!isEmptyArray(value)) { + throw new TypeError(message ?? typeErrorMessage('empty array', value)); + } +} +function assertEmptyMap(value, message) { + if (!isEmptyMap(value)) { + throw new TypeError(message ?? typeErrorMessage('empty map', value)); + } +} +function assertEmptyObject(value, message) { + if (!isEmptyObject(value)) { + throw new TypeError(message ?? typeErrorMessage('empty object', value)); + } +} +function assertEmptySet(value, message) { + if (!isEmptySet(value)) { + throw new TypeError(message ?? typeErrorMessage('empty set', value)); + } +} +function assertEmptyString(value, message) { + if (!isEmptyString(value)) { + throw new TypeError(message ?? typeErrorMessage('empty string', value)); + } +} +function assertEmptyStringOrWhitespace(value, message) { + if (!isEmptyStringOrWhitespace(value)) { + throw new TypeError(message ?? typeErrorMessage('empty string or whitespace', value)); + } +} +function assertEnumCase(value, targetEnum, message) { + if (!isEnumCase(value, targetEnum)) { + throw new TypeError(message ?? typeErrorMessage('EnumCase', value)); + } +} +function assertError(value, message) { + if (!isError(value)) { + throw new TypeError(message ?? typeErrorMessage('Error', value)); + } +} +function assertEvenInteger(value, message) { + if (!isEvenInteger(value)) { + throw new TypeError(message ?? typeErrorMessage('even integer', value)); + } +} +function assertFalsy(value, message) { + if (!isFalsy(value)) { + throw new TypeError(message ?? typeErrorMessage('falsy', value)); + } +} +function assertFiniteNumber(value, message) { + if (!isFiniteNumber(value)) { + throw new TypeError(message ?? typeErrorMessage('finite number', value)); + } +} +function assertFloat32Array(value, message) { + if (!isFloat32Array(value)) { + throw new TypeError(message ?? typeErrorMessage('Float32Array', value)); + } +} +function assertFloat64Array(value, message) { + if (!isFloat64Array(value)) { + throw new TypeError(message ?? typeErrorMessage('Float64Array', value)); + } +} +function assertFormData(value, message) { + if (!isFormData(value)) { + throw new TypeError(message ?? typeErrorMessage('FormData', value)); + } +} +// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type +function assertFunction(value, message) { + if (!isFunction(value)) { + throw new TypeError(message ?? typeErrorMessage('Function', value)); + } +} +function assertGenerator(value, message) { + if (!isGenerator(value)) { + throw new TypeError(message ?? typeErrorMessage('Generator', value)); + } +} +function assertGeneratorFunction(value, message) { + if (!isGeneratorFunction(value)) { + throw new TypeError(message ?? typeErrorMessage('GeneratorFunction', value)); + } +} +function assertHtmlElement(value, message) { + if (!isHtmlElement(value)) { + throw new TypeError(message ?? typeErrorMessage('HTMLElement', value)); + } +} +function assertInfinite(value, message) { + if (!isInfinite(value)) { + throw new TypeError(message ?? typeErrorMessage('infinite number', value)); + } +} +function assertInRange(value, range, message) { + if (!isInRange(value, range)) { + throw new TypeError(message ?? typeErrorMessage('in range', value)); + } +} +function assertInt16Array(value, message) { + if (!isInt16Array(value)) { + throw new TypeError(message ?? typeErrorMessage('Int16Array', value)); + } +} +function assertInt32Array(value, message) { + if (!isInt32Array(value)) { + throw new TypeError(message ?? typeErrorMessage('Int32Array', value)); + } +} +function assertInt8Array(value, message) { + if (!isInt8Array(value)) { + throw new TypeError(message ?? typeErrorMessage('Int8Array', value)); + } +} +function assertInteger(value, message) { + if (!isInteger(value)) { + throw new TypeError(message ?? typeErrorMessage('integer', value)); + } +} +function assertIterable(value, message) { + if (!isIterable(value)) { + throw new TypeError(message ?? typeErrorMessage('Iterable', value)); + } +} +function assertMap(value, message) { + if (!isMap(value)) { + throw new TypeError(message ?? typeErrorMessage('Map', value)); + } +} +function assertNan(value, message) { + if (!isNan(value)) { + throw new TypeError(message ?? typeErrorMessage('NaN', value)); + } +} +function assertNativePromise(value, message) { + if (!isNativePromise(value)) { + throw new TypeError(message ?? typeErrorMessage('native Promise', value)); + } +} +function assertNegativeInteger(value, message) { + if (!isNegativeInteger(value)) { + throw new TypeError(message ?? typeErrorMessage('negative integer', value)); + } +} +function assertNegativeNumber(value, message) { + if (!isNegativeNumber(value)) { + throw new TypeError(message ?? typeErrorMessage('negative number', value)); + } +} +function assertNodeStream(value, message) { + if (!isNodeStream(value)) { + throw new TypeError(message ?? typeErrorMessage('Node.js Stream', value)); + } +} +function assertNonEmptyArray(value, message) { + if (!isNonEmptyArray(value)) { + throw new TypeError(message ?? typeErrorMessage('non-empty array', value)); + } +} +function assertNonEmptyMap(value, message) { + if (!isNonEmptyMap(value)) { + throw new TypeError(message ?? typeErrorMessage('non-empty map', value)); + } +} +function assertNonEmptyObject(value, message) { + if (!isNonEmptyObject(value)) { + throw new TypeError(message ?? typeErrorMessage('non-empty object', value)); + } +} +function assertNonEmptySet(value, message) { + if (!isNonEmptySet(value)) { + throw new TypeError(message ?? typeErrorMessage('non-empty set', value)); + } +} +function assertNonEmptyString(value, message) { + if (!isNonEmptyString(value)) { + throw new TypeError(message ?? typeErrorMessage('non-empty string', value)); + } +} +function assertNonEmptyStringAndNotWhitespace(value, message) { + if (!isNonEmptyStringAndNotWhitespace(value)) { + throw new TypeError(message ?? typeErrorMessage('non-empty string and not whitespace', value)); + } +} +function assertNonNegativeInteger(value, message) { + if (!isNonNegativeInteger(value)) { + throw new TypeError(message ?? typeErrorMessage('non-negative integer', value)); + } +} +function assertNonNegativeNumber(value, message) { + if (!isNonNegativeNumber(value)) { + throw new TypeError(message ?? typeErrorMessage('non-negative number', value)); + } +} +// eslint-disable-next-line @typescript-eslint/no-restricted-types +function assertNull(value, message) { + if (!isNull(value)) { + throw new TypeError(message ?? typeErrorMessage('null', value)); + } +} +// eslint-disable-next-line @typescript-eslint/no-restricted-types +function assertNullOrUndefined(value, message) { + if (!isNullOrUndefined(value)) { + throw new TypeError(message ?? typeErrorMessage('null or undefined', value)); + } +} +function assertNumber(value, message) { + if (!isNumber(value)) { + throw new TypeError(message ?? typeErrorMessage('number', value)); + } +} +function assertNumericString(value, message) { + if (!isNumericString(value)) { + throw new TypeError(message ?? typeErrorMessage('string with a number', value)); + } +} +// eslint-disable-next-line @typescript-eslint/no-restricted-types +function assertObject(value, message) { + if (!isObject(value)) { + throw new TypeError(message ?? typeErrorMessage('Object', value)); + } +} +function assertObservable(value, message) { + if (!isObservable(value)) { + throw new TypeError(message ?? typeErrorMessage('Observable', value)); + } +} +function assertOddInteger(value, message) { + if (!isOddInteger(value)) { + throw new TypeError(message ?? typeErrorMessage('odd integer', value)); + } +} +function assertPlainObject(value, message) { + if (!isPlainObject(value)) { + throw new TypeError(message ?? typeErrorMessage('plain object', value)); + } +} +function assertPositiveInteger(value, message) { + if (!isPositiveInteger(value)) { + throw new TypeError(message ?? typeErrorMessage('positive integer', value)); + } +} +function assertPositiveNumber(value, message) { + if (!isPositiveNumber(value)) { + throw new TypeError(message ?? typeErrorMessage('positive number', value)); + } +} +function assertPrimitive(value, message) { + if (!isPrimitive(value)) { + throw new TypeError(message ?? typeErrorMessage('primitive', value)); + } +} +function assertPromise(value, message) { + if (!isPromise(value)) { + throw new TypeError(message ?? typeErrorMessage('Promise', value)); + } +} +function assertPropertyKey(value, message) { + if (!isPropertyKey(value)) { + throw new TypeError(message ?? typeErrorMessage('PropertyKey', value)); + } +} +function assertRegExp(value, message) { + if (!isRegExp(value)) { + throw new TypeError(message ?? typeErrorMessage('RegExp', value)); + } +} +function assertSafeInteger(value, message) { + if (!isSafeInteger(value)) { + throw new TypeError(message ?? typeErrorMessage('safe integer', value)); + } +} +function assertSet(value, message) { + if (!isSet(value)) { + throw new TypeError(message ?? typeErrorMessage('Set', value)); + } +} +function assertSharedArrayBuffer(value, message) { + if (!isSharedArrayBuffer(value)) { + throw new TypeError(message ?? typeErrorMessage('SharedArrayBuffer', value)); + } +} +function assertString(value, message) { + if (!isString(value)) { + throw new TypeError(message ?? typeErrorMessage('string', value)); + } +} +function assertSymbol(value, message) { + if (!isSymbol(value)) { + throw new TypeError(message ?? typeErrorMessage('symbol', value)); + } +} +function assertTruthy(value, message) { + if (!isTruthy(value)) { + throw new TypeError(message ?? typeErrorMessage('truthy', value)); + } +} +function assertTupleLike(value, guards, message) { + if (!isTupleLike(value, guards)) { + throw new TypeError(message ?? typeErrorMessage('tuple-like', value)); + } +} +function assertTypedArray(value, message) { + if (!isTypedArray(value)) { + throw new TypeError(message ?? typeErrorMessage('TypedArray', value)); + } +} +function assertUint16Array(value, message) { + if (!isUint16Array(value)) { + throw new TypeError(message ?? typeErrorMessage('Uint16Array', value)); + } +} +function assertUint32Array(value, message) { + if (!isUint32Array(value)) { + throw new TypeError(message ?? typeErrorMessage('Uint32Array', value)); + } +} +function assertUint8Array(value, message) { + if (!isUint8Array(value)) { + throw new TypeError(message ?? typeErrorMessage('Uint8Array', value)); + } +} +function assertUint8ClampedArray(value, message) { + if (!isUint8ClampedArray(value)) { + throw new TypeError(message ?? typeErrorMessage('Uint8ClampedArray', value)); + } +} +function assertUndefined(value, message) { + if (!isUndefined(value)) { + throw new TypeError(message ?? typeErrorMessage('undefined', value)); + } +} +function assertUrlInstance(value, message) { + if (!isUrlInstance(value)) { + throw new TypeError(message ?? typeErrorMessage('URL', value)); + } +} +// eslint-disable-next-line unicorn/prevent-abbreviations +function assertUrlSearchParams(value, message) { + if (!isUrlSearchParams(value)) { + throw new TypeError(message ?? typeErrorMessage('URLSearchParams', value)); + } +} +function assertUrlString(value, message) { + if (!isUrlString(value)) { + throw new TypeError(message ?? typeErrorMessage('string with a URL', value)); + } +} +function assertValidDate(value, message) { + if (!isValidDate(value)) { + throw new TypeError(message ?? typeErrorMessage('valid Date', value)); + } +} +function assertValidLength(value, message) { + if (!isValidLength(value)) { + throw new TypeError(message ?? typeErrorMessage('valid length', value)); + } +} +// eslint-disable-next-line @typescript-eslint/no-restricted-types +function assertWeakMap(value, message) { + if (!isWeakMap(value)) { + throw new TypeError(message ?? typeErrorMessage('WeakMap', value)); + } +} +// eslint-disable-next-line @typescript-eslint/no-restricted-types +function assertWeakRef(value, message) { + if (!isWeakRef(value)) { + throw new TypeError(message ?? typeErrorMessage('WeakRef', value)); + } +} +// eslint-disable-next-line @typescript-eslint/no-restricted-types +function assertWeakSet(value, message) { + if (!isWeakSet(value)) { + throw new TypeError(message ?? typeErrorMessage('WeakSet', value)); + } +} +function assertWhitespaceString(value, message) { + if (!isWhitespaceString(value)) { + throw new TypeError(message ?? typeErrorMessage('whitespace string', value)); + } +} +/* harmony default export */ const distribution = (is); + +// EXTERNAL MODULE: external "node:events" +var external_node_events_ = __webpack_require__(78474); +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/utils/strip-url-auth.js +/* +Returns the URL as a string with `username` and `password` stripped. +*/ +function stripUrlAuth(url) { + const sanitized = new URL(url); + sanitized.username = ''; + sanitized.password = ''; + return sanitized.toString(); +} + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/errors.js + + +// A hacky check to prevent circular references. +function isRequest(x) { + return distribution.object(x) && '_onResponse' in x; +} +/** +An error to be thrown when a request fails. +Contains a `code` property with error class code, like `ECONNREFUSED`. +*/ +class RequestError extends Error { + name = 'RequestError'; + code = 'ERR_GOT_REQUEST_ERROR'; + input; + stack; + response; + request; + timings; + constructor(message, error, self) { + super(message, { cause: error }); + Error.captureStackTrace(this, this.constructor); + if (error.code) { + this.code = error.code; + } + this.input = error.input; + if (isRequest(self)) { + Object.defineProperty(this, 'request', { + enumerable: false, + value: self, + }); + Object.defineProperty(this, 'response', { + enumerable: false, + value: self.response, + }); + this.options = self.options; + } + else { + this.options = self; + } + this.timings = this.request?.timings; + // Recover the original stacktrace + if (distribution.string(error.stack) && distribution.string(this.stack)) { + const indexOfMessage = this.stack.indexOf(this.message) + this.message.length; + const thisStackTrace = this.stack.slice(indexOfMessage).split('\n').toReversed(); + const errorStackTrace = error.stack.slice(error.stack.indexOf(error.message) + error.message.length).split('\n').toReversed(); + // Remove duplicated traces + while (errorStackTrace.length > 0 && errorStackTrace[0] === thisStackTrace[0]) { + thisStackTrace.shift(); + } + this.stack = `${this.stack.slice(0, indexOfMessage)}${thisStackTrace.toReversed().join('\n')}${errorStackTrace.toReversed().join('\n')}`; + } + } +} +/** +An error to be thrown when the server redirects you more than ten times. +Includes a `response` property. +*/ +class MaxRedirectsError extends RequestError { + name = 'MaxRedirectsError'; + code = 'ERR_TOO_MANY_REDIRECTS'; + constructor(request) { + super(`Redirected ${request.options.maxRedirects} times. Aborting.`, {}, request); + } +} +/** +An error to be thrown when the server response code is not 2xx nor 3xx if `options.followRedirect` is `true`, but always except for 304. +Includes a `response` property. +*/ +// eslint-disable-next-line @typescript-eslint/naming-convention +class HTTPError extends RequestError { + name = 'HTTPError'; + code = 'ERR_NON_2XX_3XX_RESPONSE'; + constructor(response) { + super(`Request failed with status code ${response.statusCode} (${response.statusMessage}): ${response.request.options.method} ${stripUrlAuth(response.request.options.url)}`, {}, response.request); + } +} +/** +An error to be thrown when a cache method fails. +For example, if the database goes down or there's a filesystem error. +*/ +class CacheError extends RequestError { + name = 'CacheError'; + constructor(error, request) { + super(error.message, error, request); + this.code = 'ERR_CACHE_ACCESS'; + } +} +/** +An error to be thrown when the request body is a stream and an error occurs while reading from that stream. +*/ +class UploadError extends RequestError { + name = 'UploadError'; + constructor(error, request) { + super(error.message, error, request); + this.code = 'ERR_UPLOAD'; + } +} +/** +An error to be thrown when the request is aborted due to a timeout. +Includes an `event` and `timings` property. +*/ +class TimeoutError extends RequestError { + name = 'TimeoutError'; + timings; + event; + constructor(error, timings, request) { + super(error.message, error, request); + this.event = error.event; + this.timings = timings; + } +} +/** +An error to be thrown when reading from response stream fails. +*/ +class ReadError extends RequestError { + name = 'ReadError'; + code = 'ERR_READING_RESPONSE_STREAM'; + constructor(error, request) { + super(error.message, error, request); + if (error.code === 'ECONNRESET' || error.code === 'ERR_HTTP_CONTENT_LENGTH_MISMATCH') { + this.code = error.code; + } + } +} +/** +An error which always triggers a new retry when thrown. +*/ +class RetryError extends RequestError { + name = 'RetryError'; + code = 'ERR_RETRYING'; + constructor(request) { + super('Retrying', {}, request); + } +} +/** +An error to be thrown when the request is aborted by AbortController. +*/ +class AbortError extends RequestError { + name = 'AbortError'; + code = 'ERR_ABORTED'; + constructor(request) { + super('This operation was aborted.', {}, request); + } +} + +// EXTERNAL MODULE: external "node:process" +var external_node_process_ = __webpack_require__(1708); +// EXTERNAL MODULE: external "node:buffer" +var external_node_buffer_ = __webpack_require__(4573); +// EXTERNAL MODULE: external "node:stream" +var external_node_stream_ = __webpack_require__(57075); +// EXTERNAL MODULE: external "node:http" +var external_node_http_ = __webpack_require__(37067); +;// CONCATENATED MODULE: ./node_modules/byte-counter/utilities.js +const textEncoder = new TextEncoder(); + +function byteLength(data) { + if (typeof data === 'string') { + return textEncoder.encode(data).byteLength; + } + + if (ArrayBuffer.isView(data) || data instanceof ArrayBuffer || data instanceof SharedArrayBuffer) { + return data.byteLength; + } + + return 0; +} + +;// CONCATENATED MODULE: ./node_modules/chunk-data/index.js +const toUint8Array = data => (data instanceof Uint8Array + ? data + : new Uint8Array(data.buffer, data.byteOffset, data.byteLength)); + +function * chunk(data, chunkSize) { + if (!ArrayBuffer.isView(data)) { + throw new TypeError('Expected data to be ArrayBufferView'); + } + + if (!Number.isSafeInteger(chunkSize) || chunkSize <= 0) { + throw new TypeError('Expected chunkSize to be a positive integer'); + } + + const uint8Array = toUint8Array(data); + + for (let offset = 0; offset < uint8Array.length; offset += chunkSize) { + yield uint8Array.subarray(offset, offset + chunkSize); + } +} + +function * chunkFrom(iterable, chunkSize) { + if (typeof iterable?.[Symbol.iterator] !== 'function' || typeof iterable === 'string') { + throw new TypeError('Expected iterable to be an Iterable'); + } + + if (!Number.isSafeInteger(chunkSize) || chunkSize <= 0) { + throw new TypeError('Expected chunkSize to be a positive integer'); + } + + let carryBuffer; + let carryLength = 0; + + for (const part of iterable) { + if (!ArrayBuffer.isView(part)) { + throw new TypeError('Expected iterable chunks to be Uint8Array or ArrayBufferView'); + } + + const buffer = toUint8Array(part); + + // Skip empty buffers + if (buffer.length === 0) { + continue; + } + + let offset = 0; + + // Fill carry buffer to a full chunk if present + if (carryLength > 0) { + const needed = chunkSize - carryLength; + if (buffer.length >= needed) { + // Complete the chunk: merge carry + needed bytes from buffer + const out = new Uint8Array(chunkSize); + out.set(carryBuffer.subarray(0, carryLength), 0); + out.set(buffer.subarray(0, needed), carryLength); + yield out; + carryLength = 0; + offset = needed; + } else { + // Accumulate into fixed carry buffer (avoids O(n²) from repeated reallocations) + // Safe: buffer.length < needed implies carryLength + buffer.length < chunkSize + carryBuffer.set(buffer, carryLength); + carryLength += buffer.length; + continue; + } + } + + // Emit direct slices from current buffer + for (; offset + chunkSize <= buffer.length; offset += chunkSize) { + yield buffer.subarray(offset, offset + chunkSize); + } + + // Save remainder in carry buffer + if (offset < buffer.length) { + carryBuffer ||= new Uint8Array(chunkSize); + + const remainder = buffer.length - offset; + carryBuffer.set(buffer.subarray(offset), 0); + carryLength = remainder; + } + } + + if (carryLength > 0) { + yield carryBuffer.subarray(0, carryLength); + } +} + +async function * chunkFromAsync(iterable, chunkSize) { + if (typeof iterable?.[Symbol.asyncIterator] !== 'function' && typeof iterable?.[Symbol.iterator] !== 'function') { + throw new TypeError('Expected iterable to be an async iterable or iterable'); + } + + if (!Number.isSafeInteger(chunkSize) || chunkSize <= 0) { + throw new TypeError('Expected chunkSize to be a positive integer'); + } + + let carryBuffer; + let carryLength = 0; + + for await (const part of iterable) { + if (!ArrayBuffer.isView(part)) { + throw new TypeError('Expected iterable chunks to be Uint8Array or ArrayBufferView'); + } + + const buffer = toUint8Array(part); + + // Skip empty buffers + if (buffer.length === 0) { + continue; + } + + let offset = 0; + + // Fill carry buffer to a full chunk if present + if (carryLength > 0) { + const needed = chunkSize - carryLength; + if (buffer.length >= needed) { + // Complete the chunk: merge carry + needed bytes from buffer + const out = new Uint8Array(chunkSize); + out.set(carryBuffer.subarray(0, carryLength), 0); + out.set(buffer.subarray(0, needed), carryLength); + yield out; + carryLength = 0; + offset = needed; + } else { + // Accumulate into fixed carry buffer (avoids O(n²) from repeated reallocations) + // Safe: buffer.length < needed implies carryLength + buffer.length < chunkSize + carryBuffer.set(buffer, carryLength); + carryLength += buffer.length; + continue; + } + } + + // Emit direct slices from current buffer + for (; offset + chunkSize <= buffer.length; offset += chunkSize) { + yield buffer.subarray(offset, offset + chunkSize); + } + + // Save remainder in carry buffer + if (offset < buffer.length) { + carryBuffer ||= new Uint8Array(chunkSize); + + const remainder = buffer.length - offset; + carryBuffer.set(buffer.subarray(offset), 0); + carryLength = remainder; + } + } + + if (carryLength > 0) { + yield carryBuffer.subarray(0, carryLength); + } +} + +;// CONCATENATED MODULE: ./node_modules/uint8array-extras/index.js +const objectToString = Object.prototype.toString; +const uint8ArrayStringified = '[object Uint8Array]'; +const arrayBufferStringified = '[object ArrayBuffer]'; + +function isType(value, typeConstructor, typeStringified) { + if (!value) { + return false; + } + + if (value.constructor === typeConstructor) { + return true; + } + + return objectToString.call(value) === typeStringified; +} + +function uint8array_extras_isUint8Array(value) { + return isType(value, Uint8Array, uint8ArrayStringified); +} + +function uint8array_extras_isArrayBuffer(value) { + return isType(value, ArrayBuffer, arrayBufferStringified); +} + +function isUint8ArrayOrArrayBuffer(value) { + return uint8array_extras_isUint8Array(value) || uint8array_extras_isArrayBuffer(value); +} + +function uint8array_extras_assertUint8Array(value) { + if (!uint8array_extras_isUint8Array(value)) { + throw new TypeError(`Expected \`Uint8Array\`, got \`${typeof value}\``); + } +} + +function assertUint8ArrayOrArrayBuffer(value) { + if (!isUint8ArrayOrArrayBuffer(value)) { + throw new TypeError(`Expected \`Uint8Array\` or \`ArrayBuffer\`, got \`${typeof value}\``); + } +} + +function uint8array_extras_toUint8Array(value) { + if (value instanceof ArrayBuffer) { + return new Uint8Array(value); + } + + if (ArrayBuffer.isView(value)) { + return new Uint8Array(value.buffer, value.byteOffset, value.byteLength); + } + + throw new TypeError(`Unsupported value, got \`${typeof value}\`.`); +} + +function concatUint8Arrays(arrays, totalLength) { + if (arrays.length === 0) { + return new Uint8Array(0); + } + + totalLength ??= arrays.reduce((accumulator, currentValue) => accumulator + currentValue.length, 0); + + const returnValue = new Uint8Array(totalLength); + + let offset = 0; + for (const array of arrays) { + uint8array_extras_assertUint8Array(array); + returnValue.set(array, offset); + offset += array.length; + } + + return returnValue; +} + +function areUint8ArraysEqual(a, b) { + uint8array_extras_assertUint8Array(a); + uint8array_extras_assertUint8Array(b); + + if (a === b) { + return true; + } + + if (a.length !== b.length) { + return false; + } + + // eslint-disable-next-line unicorn/no-for-loop + for (let index = 0; index < a.length; index++) { + if (a[index] !== b[index]) { + return false; + } + } + + return true; +} + +function compareUint8Arrays(a, b) { + uint8array_extras_assertUint8Array(a); + uint8array_extras_assertUint8Array(b); + + const length = Math.min(a.length, b.length); + + for (let index = 0; index < length; index++) { + const diff = a[index] - b[index]; + if (diff !== 0) { + return Math.sign(diff); + } + } + + // At this point, all the compared elements are equal. + // The shorter array should come first if the arrays are of different lengths. + return Math.sign(a.length - b.length); +} + +const cachedDecoders = { + utf8: new globalThis.TextDecoder('utf8'), +}; + +function uint8ArrayToString(array, encoding = 'utf8') { + assertUint8ArrayOrArrayBuffer(array); + cachedDecoders[encoding] ??= new globalThis.TextDecoder(encoding); + return cachedDecoders[encoding].decode(array); +} + +function uint8array_extras_assertString(value) { + if (typeof value !== 'string') { + throw new TypeError(`Expected \`string\`, got \`${typeof value}\``); + } +} + +const cachedEncoder = new globalThis.TextEncoder(); + +function stringToUint8Array(string) { + uint8array_extras_assertString(string); + return cachedEncoder.encode(string); +} + +function base64ToBase64Url(base64) { + return base64.replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/, ''); +} + +function base64UrlToBase64(base64url) { + const base64 = base64url.replaceAll('-', '+').replaceAll('_', '/'); + const padding = (4 - (base64.length % 4)) % 4; + return base64 + '='.repeat(padding); +} + +// Reference: https://phuoc.ng/collection/this-vs-that/concat-vs-push/ +// Important: Keep this value divisible by 3 so intermediate chunks produce no Base64 padding. +const MAX_BLOCK_SIZE = 65_535; + +function uint8ArrayToBase64(array, {urlSafe = false} = {}) { + uint8array_extras_assertUint8Array(array); + + let base64 = ''; + + for (let index = 0; index < array.length; index += MAX_BLOCK_SIZE) { + const chunk = array.subarray(index, index + MAX_BLOCK_SIZE); + // Required as `btoa` and `atob` don't properly support Unicode: https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem + base64 += globalThis.btoa(String.fromCodePoint.apply(undefined, chunk)); + } + + return urlSafe ? base64ToBase64Url(base64) : base64; +} + +function base64ToUint8Array(base64String) { + uint8array_extras_assertString(base64String); + return Uint8Array.from(globalThis.atob(base64UrlToBase64(base64String)), x => x.codePointAt(0)); +} + +function stringToBase64(string, {urlSafe = false} = {}) { + uint8array_extras_assertString(string); + return uint8ArrayToBase64(stringToUint8Array(string), {urlSafe}); +} + +function base64ToString(base64String) { + uint8array_extras_assertString(base64String); + return uint8ArrayToString(base64ToUint8Array(base64String)); +} + +const byteToHexLookupTable = Array.from({length: 256}, (_, index) => index.toString(16).padStart(2, '0')); + +function uint8ArrayToHex(array) { + uint8array_extras_assertUint8Array(array); + + // Concatenating a string is faster than using an array. + let hexString = ''; + + // eslint-disable-next-line unicorn/no-for-loop -- Max performance is critical. + for (let index = 0; index < array.length; index++) { + hexString += byteToHexLookupTable[array[index]]; + } + + return hexString; +} + +const hexToDecimalLookupTable = { + 0: 0, + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + 6: 6, + 7: 7, + 8: 8, + 9: 9, + a: 10, + b: 11, + c: 12, + d: 13, + e: 14, + f: 15, + A: 10, + B: 11, + C: 12, + D: 13, + E: 14, + F: 15, +}; + +function hexToUint8Array(hexString) { + uint8array_extras_assertString(hexString); + + if (hexString.length % 2 !== 0) { + throw new Error('Invalid Hex string length.'); + } + + const resultLength = hexString.length / 2; + const bytes = new Uint8Array(resultLength); + + for (let index = 0; index < resultLength; index++) { + const highNibble = hexToDecimalLookupTable[hexString[index * 2]]; + const lowNibble = hexToDecimalLookupTable[hexString[(index * 2) + 1]]; + + if (highNibble === undefined || lowNibble === undefined) { + throw new Error(`Invalid Hex character encountered at position ${index * 2}`); + } + + bytes[index] = (highNibble << 4) | lowNibble; // eslint-disable-line no-bitwise + } + + return bytes; +} + +/** +@param {DataView} view +@returns {number} +*/ +function getUintBE(view) { + const {byteLength} = view; + + if (byteLength === 6) { + return (view.getUint16(0) * (2 ** 32)) + view.getUint32(2); + } + + if (byteLength === 5) { + return (view.getUint8(0) * (2 ** 32)) + view.getUint32(1); + } + + if (byteLength === 4) { + return view.getUint32(0); + } + + if (byteLength === 3) { + return (view.getUint8(0) * (2 ** 16)) + view.getUint16(1); + } + + if (byteLength === 2) { + return view.getUint16(0); + } + + if (byteLength === 1) { + return view.getUint8(0); + } +} + +/** +@param {Uint8Array} array +@param {Uint8Array} value +@returns {number} +*/ +function indexOf(array, value) { + const arrayLength = array.length; + const valueLength = value.length; + + if (valueLength === 0) { + return -1; + } + + if (valueLength > arrayLength) { + return -1; + } + + const validOffsetLength = arrayLength - valueLength; + + for (let index = 0; index <= validOffsetLength; index++) { + let isMatch = true; + for (let index2 = 0; index2 < valueLength; index2++) { + if (array[index + index2] !== value[index2]) { + isMatch = false; + break; + } + } + + if (isMatch) { + return index; + } + } + + return -1; +} + +/** +@param {Uint8Array} array +@param {Uint8Array} value +@returns {boolean} +*/ +function includes(array, value) { + return indexOf(array, value) !== -1; +} + +// EXTERNAL MODULE: external "node:crypto" +var external_node_crypto_ = __webpack_require__(77598); +// EXTERNAL MODULE: external "node:url" +var external_node_url_ = __webpack_require__(73136); +;// CONCATENATED MODULE: ./node_modules/get-stream/node_modules/is-stream/index.js +function isStream(stream, {checkOpen = true} = {}) { + return stream !== null + && typeof stream === 'object' + && (stream.writable || stream.readable || !checkOpen || (stream.writable === undefined && stream.readable === undefined)) + && typeof stream.pipe === 'function'; +} + +function isWritableStream(stream, {checkOpen = true} = {}) { + return isStream(stream, {checkOpen}) + && (stream.writable || !checkOpen) + && typeof stream.write === 'function' + && typeof stream.end === 'function' + && typeof stream.writable === 'boolean' + && typeof stream.writableObjectMode === 'boolean' + && typeof stream.destroy === 'function' + && typeof stream.destroyed === 'boolean'; +} + +function isReadableStream(stream, {checkOpen = true} = {}) { + return isStream(stream, {checkOpen}) + && (stream.readable || !checkOpen) + && typeof stream.read === 'function' + && typeof stream.readable === 'boolean' + && typeof stream.readableObjectMode === 'boolean' + && typeof stream.destroy === 'function' + && typeof stream.destroyed === 'boolean'; +} + +function isDuplexStream(stream, options) { + return isWritableStream(stream, options) + && isReadableStream(stream, options); +} + +function isTransformStream(stream, options) { + return isDuplexStream(stream, options) + && typeof stream._transform === 'function'; +} + +;// CONCATENATED MODULE: ./node_modules/@sec-ant/readable-stream/dist/ponyfill/asyncIterator.js +const a = Object.getPrototypeOf( + Object.getPrototypeOf( + /* istanbul ignore next */ + async function* () { + } + ).prototype +); +class c { + #t; + #n; + #r = !1; + #e = void 0; + constructor(e, t) { + this.#t = e, this.#n = t; + } + next() { + const e = () => this.#s(); + return this.#e = this.#e ? this.#e.then(e, e) : e(), this.#e; + } + return(e) { + const t = () => this.#i(e); + return this.#e ? this.#e.then(t, t) : t(); + } + async #s() { + if (this.#r) + return { + done: !0, + value: void 0 + }; + let e; + try { + e = await this.#t.read(); + } catch (t) { + throw this.#e = void 0, this.#r = !0, this.#t.releaseLock(), t; + } + return e.done && (this.#e = void 0, this.#r = !0, this.#t.releaseLock()), e; + } + async #i(e) { + if (this.#r) + return { + done: !0, + value: e + }; + if (this.#r = !0, !this.#n) { + const t = this.#t.cancel(e); + return this.#t.releaseLock(), await t, { + done: !0, + value: e + }; + } + return this.#t.releaseLock(), { + done: !0, + value: e + }; + } +} +const n = Symbol(); +function i() { + return this[n].next(); +} +Object.defineProperty(i, "name", { value: "next" }); +function o(r) { + return this[n].return(r); +} +Object.defineProperty(o, "name", { value: "return" }); +const u = Object.create(a, { + next: { + enumerable: !0, + configurable: !0, + writable: !0, + value: i + }, + return: { + enumerable: !0, + configurable: !0, + writable: !0, + value: o + } +}); +function h({ preventCancel: r = !1 } = {}) { + const e = this.getReader(), t = new c( + e, + r + ), s = Object.create(u); + return s[n] = t, s; +} + + +;// CONCATENATED MODULE: ./node_modules/@sec-ant/readable-stream/dist/ponyfill/index.js + + + + +;// CONCATENATED MODULE: ./node_modules/get-stream/source/stream.js + + + +const getAsyncIterable = stream => { + if (isReadableStream(stream, {checkOpen: false}) && nodeImports.on !== undefined) { + return getStreamIterable(stream); + } + + if (typeof stream?.[Symbol.asyncIterator] === 'function') { + return stream; + } + + // `ReadableStream[Symbol.asyncIterator]` support is missing in multiple browsers, so we ponyfill it + if (stream_toString.call(stream) === '[object ReadableStream]') { + return h.call(stream); + } + + throw new TypeError('The first argument must be a Readable, a ReadableStream, or an async iterable.'); +}; + +const {toString: stream_toString} = Object.prototype; + +// The default iterable for Node.js streams does not allow for multiple readers at once, so we re-implement it +const getStreamIterable = async function * (stream) { + const controller = new AbortController(); + const state = {}; + handleStreamEnd(stream, controller, state); + + try { + for await (const [chunk] of nodeImports.on(stream, 'data', {signal: controller.signal})) { + yield chunk; + } + } catch (error) { + // Stream failure, for example due to `stream.destroy(error)` + if (state.error !== undefined) { + throw state.error; + // `error` event directly emitted on stream + } else if (!controller.signal.aborted) { + throw error; + // Otherwise, stream completed successfully + } + // The `finally` block also runs when the caller throws, for example due to the `maxBuffer` option + } finally { + stream.destroy(); + } +}; + +const handleStreamEnd = async (stream, controller, state) => { + try { + await nodeImports.finished(stream, { + cleanup: true, + readable: true, + writable: false, + error: false, + }); + } catch (error) { + state.error = error; + } finally { + controller.abort(); + } +}; + +// Loaded by the Node entrypoint, but not by the browser one. +// This prevents using dynamic imports. +const nodeImports = {}; + +;// CONCATENATED MODULE: ./node_modules/get-stream/source/contents.js + + +const getStreamContents = async (stream, {init, convertChunk, getSize, truncateChunk, addChunk, getFinalChunk, finalize}, {maxBuffer = Number.POSITIVE_INFINITY} = {}) => { + const asyncIterable = getAsyncIterable(stream); + + const state = init(); + state.length = 0; + + try { + for await (const chunk of asyncIterable) { + const chunkType = getChunkType(chunk); + const convertedChunk = convertChunk[chunkType](chunk, state); + appendChunk({ + convertedChunk, + state, + getSize, + truncateChunk, + addChunk, + maxBuffer, + }); + } + + appendFinalChunk({ + state, + convertChunk, + getSize, + truncateChunk, + addChunk, + getFinalChunk, + maxBuffer, + }); + return finalize(state); + } catch (error) { + const normalizedError = typeof error === 'object' && error !== null ? error : new Error(error); + normalizedError.bufferedData = finalize(state); + throw normalizedError; + } +}; + +const appendFinalChunk = ({state, getSize, truncateChunk, addChunk, getFinalChunk, maxBuffer}) => { + const convertedChunk = getFinalChunk(state); + if (convertedChunk !== undefined) { + appendChunk({ + convertedChunk, + state, + getSize, + truncateChunk, + addChunk, + maxBuffer, + }); + } +}; + +const appendChunk = ({convertedChunk, state, getSize, truncateChunk, addChunk, maxBuffer}) => { + const chunkSize = getSize(convertedChunk); + const newLength = state.length + chunkSize; + + if (newLength <= maxBuffer) { + addNewChunk(convertedChunk, state, addChunk, newLength); + return; + } + + const truncatedChunk = truncateChunk(convertedChunk, maxBuffer - state.length); + + if (truncatedChunk !== undefined) { + addNewChunk(truncatedChunk, state, addChunk, maxBuffer); + } + + throw new MaxBufferError(); +}; + +const addNewChunk = (convertedChunk, state, addChunk, newLength) => { + state.contents = addChunk(convertedChunk, state, newLength); + state.length = newLength; +}; + +const getChunkType = chunk => { + const typeOfChunk = typeof chunk; + + if (typeOfChunk === 'string') { + return 'string'; + } + + if (typeOfChunk !== 'object' || chunk === null) { + return 'others'; + } + + if (globalThis.Buffer?.isBuffer(chunk)) { + return 'buffer'; + } + + const prototypeName = contents_objectToString.call(chunk); + + if (prototypeName === '[object ArrayBuffer]') { + return 'arrayBuffer'; + } + + if (prototypeName === '[object DataView]') { + return 'dataView'; + } + + if ( + Number.isInteger(chunk.byteLength) + && Number.isInteger(chunk.byteOffset) + && contents_objectToString.call(chunk.buffer) === '[object ArrayBuffer]' + ) { + return 'typedArray'; + } + + return 'others'; +}; + +const {toString: contents_objectToString} = Object.prototype; + +class MaxBufferError extends Error { + name = 'MaxBufferError'; + + constructor() { + super('maxBuffer exceeded'); + } +} + +;// CONCATENATED MODULE: ./node_modules/get-stream/source/utils.js +const identity = value => value; + +const noop = () => undefined; + +const getContentsProperty = ({contents}) => contents; + +const throwObjectStream = chunk => { + throw new Error(`Streams in object mode are not supported: ${String(chunk)}`); +}; + +const getLengthProperty = convertedChunk => convertedChunk.length; + +;// CONCATENATED MODULE: ./node_modules/get-stream/source/array-buffer.js + + + +async function getStreamAsArrayBuffer(stream, options) { + return getStreamContents(stream, arrayBufferMethods, options); +} + +const initArrayBuffer = () => ({contents: new ArrayBuffer(0)}); + +const useTextEncoder = chunk => array_buffer_textEncoder.encode(chunk); +const array_buffer_textEncoder = new TextEncoder(); + +const useUint8Array = chunk => new Uint8Array(chunk); + +const useUint8ArrayWithOffset = chunk => new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); + +const truncateArrayBufferChunk = (convertedChunk, chunkSize) => convertedChunk.slice(0, chunkSize); + +// `contents` is an increasingly growing `Uint8Array`. +const addArrayBufferChunk = (convertedChunk, {contents, length: previousLength}, length) => { + const newContents = hasArrayBufferResize() ? resizeArrayBuffer(contents, length) : resizeArrayBufferSlow(contents, length); + new Uint8Array(newContents).set(convertedChunk, previousLength); + return newContents; +}; + +// Without `ArrayBuffer.resize()`, `contents` size is always a power of 2. +// This means its last bytes are zeroes (not stream data), which need to be +// trimmed at the end with `ArrayBuffer.slice()`. +const resizeArrayBufferSlow = (contents, length) => { + if (length <= contents.byteLength) { + return contents; + } + + const arrayBuffer = new ArrayBuffer(getNewContentsLength(length)); + new Uint8Array(arrayBuffer).set(new Uint8Array(contents), 0); + return arrayBuffer; +}; + +// With `ArrayBuffer.resize()`, `contents` size matches exactly the size of +// the stream data. It does not include extraneous zeroes to trim at the end. +// The underlying `ArrayBuffer` does allocate a number of bytes that is a power +// of 2, but those bytes are only visible after calling `ArrayBuffer.resize()`. +const resizeArrayBuffer = (contents, length) => { + if (length <= contents.maxByteLength) { + contents.resize(length); + return contents; + } + + const arrayBuffer = new ArrayBuffer(length, {maxByteLength: getNewContentsLength(length)}); + new Uint8Array(arrayBuffer).set(new Uint8Array(contents), 0); + return arrayBuffer; +}; + +// Retrieve the closest `length` that is both >= and a power of 2 +const getNewContentsLength = length => SCALE_FACTOR ** Math.ceil(Math.log(length) / Math.log(SCALE_FACTOR)); + +const SCALE_FACTOR = 2; + +const finalizeArrayBuffer = ({contents, length}) => hasArrayBufferResize() ? contents : contents.slice(0, length); + +// `ArrayBuffer.slice()` is slow. When `ArrayBuffer.resize()` is available +// (Node >=20.0.0, Safari >=16.4 and Chrome), we can use it instead. +// eslint-disable-next-line no-warning-comments +// TODO: remove after dropping support for Node 20. +// eslint-disable-next-line no-warning-comments +// TODO: use `ArrayBuffer.transferToFixedLength()` instead once it is available +const hasArrayBufferResize = () => 'resize' in ArrayBuffer.prototype; + +const arrayBufferMethods = { + init: initArrayBuffer, + convertChunk: { + string: useTextEncoder, + buffer: useUint8Array, + arrayBuffer: useUint8Array, + dataView: useUint8ArrayWithOffset, + typedArray: useUint8ArrayWithOffset, + others: throwObjectStream, + }, + getSize: getLengthProperty, + truncateChunk: truncateArrayBufferChunk, + addChunk: addArrayBufferChunk, + getFinalChunk: noop, + finalize: finalizeArrayBuffer, +}; + +;// CONCATENATED MODULE: ./node_modules/get-stream/source/buffer.js + + +async function getStreamAsBuffer(stream, options) { + if (!('Buffer' in globalThis)) { + throw new Error('getStreamAsBuffer() is only supported in Node.js'); + } + + try { + return arrayBufferToNodeBuffer(await getStreamAsArrayBuffer(stream, options)); + } catch (error) { + if (error.bufferedData !== undefined) { + error.bufferedData = arrayBufferToNodeBuffer(error.bufferedData); + } + + throw error; + } +} + +const arrayBufferToNodeBuffer = arrayBuffer => globalThis.Buffer.from(arrayBuffer); + +// EXTERNAL MODULE: ./node_modules/http-cache-semantics/index.js +var http_cache_semantics = __webpack_require__(12203); +// EXTERNAL MODULE: external "buffer" +var external_buffer_ = __webpack_require__(20181); +;// CONCATENATED MODULE: ./node_modules/@keyv/serialize/dist/index.js +// src/index.ts + +var _serialize = (data, escapeColonStrings = true) => { + if (data === void 0 || data === null) { + return "null"; + } + if (typeof data === "string") { + return JSON.stringify( + escapeColonStrings && data.startsWith(":") ? `:${data}` : data + ); + } + if (external_buffer_.Buffer.isBuffer(data)) { + return JSON.stringify(`:base64:${data.toString("base64")}`); + } + if (data?.toJSON) { + data = data.toJSON(); + } + if (typeof data === "object") { + let s = ""; + const array = Array.isArray(data); + s = array ? "[" : "{"; + let first = true; + for (const k in data) { + const ignore = typeof data[k] === "function" || !array && data[k] === void 0; + if (!Object.hasOwn(data, k) || ignore) { + continue; + } + if (!first) { + s += ","; + } + first = false; + if (array) { + s += _serialize(data[k], escapeColonStrings); + } else if (data[k] !== void 0) { + s += `${_serialize(k, false)}:${_serialize(data[k], escapeColonStrings)}`; + } + } + s += array ? "]" : "}"; + return s; + } + return JSON.stringify(data); +}; +var defaultSerialize = (data) => { + return _serialize(data, true); +}; +var defaultDeserialize = (data) => JSON.parse(data, (_, value) => { + if (typeof value === "string") { + if (value.startsWith(":base64:")) { + return external_buffer_.Buffer.from(value.slice(8), "base64"); + } + return value.startsWith(":") ? value.slice(1) : value; + } + return value; +}); + + +;// CONCATENATED MODULE: ./node_modules/cacheable-request/node_modules/keyv/dist/index.js +// src/index.ts + + +// src/event-manager.ts +var EventManager = class { + _eventListeners; + _maxListeners; + constructor() { + this._eventListeners = /* @__PURE__ */ new Map(); + this._maxListeners = 100; + } + maxListeners() { + return this._maxListeners; + } + // Add an event listener + addListener(event, listener) { + this.on(event, listener); + } + on(event, listener) { + if (!this._eventListeners.has(event)) { + this._eventListeners.set(event, []); + } + const listeners = this._eventListeners.get(event); + if (listeners) { + if (listeners.length >= this._maxListeners) { + console.warn( + `MaxListenersExceededWarning: Possible event memory leak detected. ${listeners.length + 1} ${event} listeners added. Use setMaxListeners() to increase limit.` + ); + } + listeners.push(listener); + } + return this; + } + // Remove an event listener + removeListener(event, listener) { + this.off(event, listener); + } + off(event, listener) { + const listeners = this._eventListeners.get(event) ?? []; + const index = listeners.indexOf(listener); + if (index !== -1) { + listeners.splice(index, 1); + } + if (listeners.length === 0) { + this._eventListeners.delete(event); + } + } + once(event, listener) { + const onceListener = (...arguments_) => { + listener(...arguments_); + this.off(event, onceListener); + }; + this.on(event, onceListener); + } + // Emit an event + // biome-ignore lint/suspicious/noExplicitAny: type format + emit(event, ...arguments_) { + const listeners = this._eventListeners.get(event); + if (listeners && listeners.length > 0) { + for (const listener of listeners) { + listener(...arguments_); + } + } + } + // Get all listeners for a specific event + listeners(event) { + return this._eventListeners.get(event) ?? []; + } + // Remove all listeners for a specific event + removeAllListeners(event) { + if (event) { + this._eventListeners.delete(event); + } else { + this._eventListeners.clear(); + } + } + // Set the maximum number of listeners for a single event + setMaxListeners(n) { + this._maxListeners = n; + } +}; +var event_manager_default = EventManager; + +// src/hooks-manager.ts +var HooksManager = class extends event_manager_default { + _hookHandlers; + constructor() { + super(); + this._hookHandlers = /* @__PURE__ */ new Map(); + } + // Adds a handler function for a specific event + addHandler(event, handler) { + const eventHandlers = this._hookHandlers.get(event); + if (eventHandlers) { + eventHandlers.push(handler); + } else { + this._hookHandlers.set(event, [handler]); + } + } + // Removes a specific handler function for a specific event + removeHandler(event, handler) { + const eventHandlers = this._hookHandlers.get(event); + if (eventHandlers) { + const index = eventHandlers.indexOf(handler); + if (index !== -1) { + eventHandlers.splice(index, 1); + } + } + } + // Triggers all handlers for a specific event with provided data + // biome-ignore lint/suspicious/noExplicitAny: type format + trigger(event, data) { + const eventHandlers = this._hookHandlers.get(event); + if (eventHandlers) { + for (const handler of eventHandlers) { + try { + handler(data); + } catch (error) { + this.emit( + "error", + new Error( + `Error in hook handler for event "${event}": ${error.message}` + ) + ); + } + } + } + } + // Provides read-only access to the current handlers + get handlers() { + return new Map(this._hookHandlers); + } +}; +var hooks_manager_default = HooksManager; + +// src/stats-manager.ts +var StatsManager = class extends event_manager_default { + enabled = true; + hits = 0; + misses = 0; + sets = 0; + deletes = 0; + errors = 0; + constructor(enabled) { + super(); + if (enabled !== void 0) { + this.enabled = enabled; + } + this.reset(); + } + hit() { + if (this.enabled) { + this.hits++; + } + } + miss() { + if (this.enabled) { + this.misses++; + } + } + set() { + if (this.enabled) { + this.sets++; + } + } + delete() { + if (this.enabled) { + this.deletes++; + } + } + hitsOrMisses(array) { + for (const item of array) { + if (item === void 0) { + this.miss(); + } else { + this.hit(); + } + } + } + reset() { + this.hits = 0; + this.misses = 0; + this.sets = 0; + this.deletes = 0; + this.errors = 0; + } +}; +var stats_manager_default = StatsManager; + +// src/index.ts +var KeyvHooks = /* @__PURE__ */ ((KeyvHooks2) => { + KeyvHooks2["PRE_SET"] = "preSet"; + KeyvHooks2["POST_SET"] = "postSet"; + KeyvHooks2["PRE_GET"] = "preGet"; + KeyvHooks2["POST_GET"] = "postGet"; + KeyvHooks2["PRE_GET_MANY"] = "preGetMany"; + KeyvHooks2["POST_GET_MANY"] = "postGetMany"; + KeyvHooks2["PRE_GET_RAW"] = "preGetRaw"; + KeyvHooks2["POST_GET_RAW"] = "postGetRaw"; + KeyvHooks2["PRE_GET_MANY_RAW"] = "preGetManyRaw"; + KeyvHooks2["POST_GET_MANY_RAW"] = "postGetManyRaw"; + KeyvHooks2["PRE_DELETE"] = "preDelete"; + KeyvHooks2["POST_DELETE"] = "postDelete"; + return KeyvHooks2; +})(KeyvHooks || {}); +var iterableAdapters = [ + "sqlite", + "postgres", + "mysql", + "mongo", + "redis", + "valkey", + "etcd" +]; +var Keyv = class extends event_manager_default { + opts; + iterator; + hooks = new hooks_manager_default(); + stats = new stats_manager_default(false); + /** + * Time to live in milliseconds + */ + _ttl; + /** + * Namespace + */ + _namespace; + /** + * Store + */ + // biome-ignore lint/suspicious/noExplicitAny: type format + _store = /* @__PURE__ */ new Map(); + _serialize = defaultSerialize; + _deserialize = defaultDeserialize; + _compression; + _useKeyPrefix = true; + _throwOnErrors = false; + /** + * Keyv Constructor + * @param {KeyvStoreAdapter | KeyvOptions} store + * @param {Omit} [options] if you provide the store you can then provide the Keyv Options + */ + constructor(store, options) { + super(); + options ??= {}; + store ??= {}; + this.opts = { + namespace: "keyv", + serialize: defaultSerialize, + deserialize: defaultDeserialize, + emitErrors: true, + // @ts-expect-error - Map is not a KeyvStoreAdapter + store: /* @__PURE__ */ new Map(), + ...options + }; + if (store && store.get) { + this.opts.store = store; + } else { + this.opts = { + ...this.opts, + ...store + }; + } + this._store = this.opts.store ?? /* @__PURE__ */ new Map(); + this._compression = this.opts.compression; + this._serialize = this.opts.serialize; + this._deserialize = this.opts.deserialize; + if (this.opts.namespace) { + this._namespace = this.opts.namespace; + } + if (this._store) { + if (!this._isValidStorageAdapter(this._store)) { + throw new Error("Invalid storage adapter"); + } + if (typeof this._store.on === "function") { + this._store.on("error", (error) => this.emit("error", error)); + } + this._store.namespace = this._namespace; + if (typeof this._store[Symbol.iterator] === "function" && this._store instanceof Map) { + this.iterator = this.generateIterator( + this._store + ); + } else if ("iterator" in this._store && this._store.opts && this._checkIterableAdapter()) { + this.iterator = this.generateIterator( + // biome-ignore lint/style/noNonNullAssertion: need to fix + this._store.iterator.bind(this._store) + ); + } + } + if (this.opts.stats) { + this.stats.enabled = this.opts.stats; + } + if (this.opts.ttl) { + this._ttl = this.opts.ttl; + } + if (this.opts.useKeyPrefix !== void 0) { + this._useKeyPrefix = this.opts.useKeyPrefix; + } + if (this.opts.throwOnErrors !== void 0) { + this._throwOnErrors = this.opts.throwOnErrors; + } + } + /** + * Get the current store + */ + // biome-ignore lint/suspicious/noExplicitAny: type format + get store() { + return this._store; + } + /** + * Set the current store. This will also set the namespace, event error handler, and generate the iterator. If the store is not valid it will throw an error. + * @param {KeyvStoreAdapter | Map | any} store the store to set + */ + // biome-ignore lint/suspicious/noExplicitAny: type format + set store(store) { + if (this._isValidStorageAdapter(store)) { + this._store = store; + this.opts.store = store; + if (typeof store.on === "function") { + store.on("error", (error) => this.emit("error", error)); + } + if (this._namespace) { + this._store.namespace = this._namespace; + } + if (typeof store[Symbol.iterator] === "function" && store instanceof Map) { + this.iterator = this.generateIterator( + store + ); + } else if ("iterator" in store && store.opts && this._checkIterableAdapter()) { + this.iterator = this.generateIterator(store.iterator?.bind(store)); + } + } else { + throw new Error("Invalid storage adapter"); + } + } + /** + * Get the current compression function + * @returns {CompressionAdapter} The current compression function + */ + get compression() { + return this._compression; + } + /** + * Set the current compression function + * @param {CompressionAdapter} compress The compression function to set + */ + set compression(compress) { + this._compression = compress; + } + /** + * Get the current namespace. + * @returns {string | undefined} The current namespace. + */ + get namespace() { + return this._namespace; + } + /** + * Set the current namespace. + * @param {string | undefined} namespace The namespace to set. + */ + set namespace(namespace) { + this._namespace = namespace; + this.opts.namespace = namespace; + this._store.namespace = namespace; + if (this.opts.store) { + this.opts.store.namespace = namespace; + } + } + /** + * Get the current TTL. + * @returns {number} The current TTL in milliseconds. + */ + get ttl() { + return this._ttl; + } + /** + * Set the current TTL. + * @param {number} ttl The TTL to set in milliseconds. + */ + set ttl(ttl) { + this.opts.ttl = ttl; + this._ttl = ttl; + } + /** + * Get the current serialize function. + * @returns {Serialize} The current serialize function. + */ + get serialize() { + return this._serialize; + } + /** + * Set the current serialize function. + * @param {Serialize} serialize The serialize function to set. + */ + set serialize(serialize) { + this.opts.serialize = serialize; + this._serialize = serialize; + } + /** + * Get the current deserialize function. + * @returns {Deserialize} The current deserialize function. + */ + get deserialize() { + return this._deserialize; + } + /** + * Set the current deserialize function. + * @param {Deserialize} deserialize The deserialize function to set. + */ + set deserialize(deserialize) { + this.opts.deserialize = deserialize; + this._deserialize = deserialize; + } + /** + * Get the current useKeyPrefix value. This will enable or disable key prefixing. + * @returns {boolean} The current useKeyPrefix value. + * @default true + */ + get useKeyPrefix() { + return this._useKeyPrefix; + } + /** + * Set the current useKeyPrefix value. This will enable or disable key prefixing. + * @param {boolean} value The useKeyPrefix value to set. + */ + set useKeyPrefix(value) { + this._useKeyPrefix = value; + this.opts.useKeyPrefix = value; + } + /** + * Get the current throwErrors value. This will enable or disable throwing errors on methods in addition to emitting them. + * @return {boolean} The current throwOnErrors value. + */ + get throwOnErrors() { + return this._throwOnErrors; + } + /** + * Set the current throwOnErrors value. This will enable or disable throwing errors on methods in addition to emitting them. + * @param {boolean} value The throwOnErrors value to set. + */ + set throwOnErrors(value) { + this._throwOnErrors = value; + this.opts.throwOnErrors = value; + } + generateIterator(iterator) { + const function_ = async function* () { + for await (const [key, raw] of typeof iterator === "function" ? iterator(this._store.namespace) : iterator) { + const data = await this.deserializeData(raw); + if (this._useKeyPrefix && this._store.namespace && !key.includes(this._store.namespace)) { + continue; + } + if (typeof data.expires === "number" && Date.now() > data.expires) { + await this.delete(key); + continue; + } + yield [this._getKeyUnprefix(key), data.value]; + } + }; + return function_.bind(this); + } + _checkIterableAdapter() { + return iterableAdapters.includes(this._store.opts.dialect) || iterableAdapters.some( + (element) => this._store.opts.url.includes(element) + ); + } + _getKeyPrefix(key) { + if (!this._useKeyPrefix) { + return key; + } + if (!this._namespace) { + return key; + } + if (key.startsWith(`${this._namespace}:`)) { + return key; + } + return `${this._namespace}:${key}`; + } + _getKeyPrefixArray(keys) { + if (!this._useKeyPrefix) { + return keys; + } + if (!this._namespace) { + return keys; + } + return keys.map((key) => `${this._namespace}:${key}`); + } + _getKeyUnprefix(key) { + if (!this._useKeyPrefix) { + return key; + } + return key.split(":").splice(1).join(":"); + } + // biome-ignore lint/suspicious/noExplicitAny: type format + _isValidStorageAdapter(store) { + return store instanceof Map || typeof store.get === "function" && typeof store.set === "function" && typeof store.delete === "function" && typeof store.clear === "function"; + } + // eslint-disable-next-line @stylistic/max-len + async get(key, options) { + const { store } = this.opts; + const isArray = Array.isArray(key); + const keyPrefixed = isArray ? this._getKeyPrefixArray(key) : this._getKeyPrefix(key); + const isDataExpired = (data) => typeof data.expires === "number" && Date.now() > data.expires; + if (isArray) { + if (options?.raw === true) { + return this.getMany(key, { raw: true }); + } + return this.getMany(key, { raw: false }); + } + this.hooks.trigger("preGet" /* PRE_GET */, { key: keyPrefixed }); + let rawData; + try { + rawData = await store.get(keyPrefixed); + } catch (error) { + if (this.throwOnErrors) { + throw error; + } + } + const deserializedData = typeof rawData === "string" || this.opts.compression ? await this.deserializeData(rawData) : rawData; + if (deserializedData === void 0 || deserializedData === null) { + this.hooks.trigger("postGet" /* POST_GET */, { + key: keyPrefixed, + value: void 0 + }); + this.stats.miss(); + return void 0; + } + if (isDataExpired(deserializedData)) { + await this.delete(key); + this.hooks.trigger("postGet" /* POST_GET */, { + key: keyPrefixed, + value: void 0 + }); + this.stats.miss(); + return void 0; + } + this.hooks.trigger("postGet" /* POST_GET */, { + key: keyPrefixed, + value: deserializedData + }); + this.stats.hit(); + return options?.raw ? deserializedData : deserializedData.value; + } + async getMany(keys, options) { + const { store } = this.opts; + const keyPrefixed = this._getKeyPrefixArray(keys); + const isDataExpired = (data) => typeof data.expires === "number" && Date.now() > data.expires; + this.hooks.trigger("preGetMany" /* PRE_GET_MANY */, { keys: keyPrefixed }); + if (store.getMany === void 0) { + const promises = keyPrefixed.map(async (key) => { + const rawData2 = await store.get(key); + const deserializedRow = typeof rawData2 === "string" || this.opts.compression ? await this.deserializeData(rawData2) : rawData2; + if (deserializedRow === void 0 || deserializedRow === null) { + return void 0; + } + if (isDataExpired(deserializedRow)) { + await this.delete(key); + return void 0; + } + return options?.raw ? deserializedRow : deserializedRow.value; + }); + const deserializedRows = await Promise.allSettled(promises); + const result2 = deserializedRows.map( + // biome-ignore lint/suspicious/noExplicitAny: type format + (row) => row.value + ); + this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result2); + if (result2.length > 0) { + this.stats.hit(); + } + return result2; + } + const rawData = await store.getMany(keyPrefixed); + const result = []; + const expiredKeys = []; + for (const index in rawData) { + let row = rawData[index]; + if (typeof row === "string") { + row = await this.deserializeData(row); + } + if (row === void 0 || row === null) { + result.push(void 0); + continue; + } + if (isDataExpired(row)) { + expiredKeys.push(keys[index]); + result.push(void 0); + continue; + } + const value = options?.raw ? row : row.value; + result.push(value); + } + if (expiredKeys.length > 0) { + await this.deleteMany(expiredKeys); + } + this.hooks.trigger("postGetMany" /* POST_GET_MANY */, result); + if (result.length > 0) { + this.stats.hit(); + } + return result; + } + /** + * Get the raw value of a key. This is the replacement for setting raw to true in the get() method. + * @param {string} key the key to get + * @returns {Promise | undefined>} will return a StoredDataRaw or undefined if the key does not exist or is expired. + */ + async getRaw(key) { + const { store } = this.opts; + const keyPrefixed = this._getKeyPrefix(key); + this.hooks.trigger("preGetRaw" /* PRE_GET_RAW */, { key: keyPrefixed }); + const rawData = await store.get(keyPrefixed); + if (rawData === void 0 || rawData === null) { + this.hooks.trigger("postGetRaw" /* POST_GET_RAW */, { + key: keyPrefixed, + value: void 0 + }); + this.stats.miss(); + return void 0; + } + const deserializedData = typeof rawData === "string" || this.opts.compression ? await this.deserializeData(rawData) : rawData; + if (deserializedData !== void 0 && deserializedData.expires !== void 0 && deserializedData.expires !== null && // biome-ignore lint/style/noNonNullAssertion: need to fix + deserializedData.expires < Date.now()) { + this.hooks.trigger("postGetRaw" /* POST_GET_RAW */, { + key: keyPrefixed, + value: void 0 + }); + this.stats.miss(); + await this.delete(key); + return void 0; + } + this.stats.hit(); + this.hooks.trigger("postGetRaw" /* POST_GET_RAW */, { + key: keyPrefixed, + value: deserializedData + }); + return deserializedData; + } + /** + * Get the raw values of many keys. This is the replacement for setting raw to true in the getMany() method. + * @param {string[]} keys the keys to get + * @returns {Promise>>} will return an array of StoredDataRaw or undefined if the key does not exist or is expired. + */ + async getManyRaw(keys) { + const { store } = this.opts; + const keyPrefixed = this._getKeyPrefixArray(keys); + if (keys.length === 0) { + const result2 = Array.from({ length: keys.length }).fill( + void 0 + ); + this.stats.misses += keys.length; + this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, { + keys: keyPrefixed, + values: result2 + }); + return result2; + } + let result = []; + if (store.getMany === void 0) { + const promises = keyPrefixed.map(async (key) => { + const rawData = await store.get(key); + if (rawData !== void 0 && rawData !== null) { + return this.deserializeData(rawData); + } + return void 0; + }); + const deserializedRows = await Promise.allSettled(promises); + result = deserializedRows.map( + // biome-ignore lint/suspicious/noExplicitAny: type format + (row) => row.value + ); + } else { + const rawData = await store.getMany(keyPrefixed); + for (const row of rawData) { + if (row !== void 0 && row !== null) { + result.push(await this.deserializeData(row)); + } else { + result.push(void 0); + } + } + } + const expiredKeys = []; + const isDataExpired = (data) => typeof data.expires === "number" && Date.now() > data.expires; + for (const [index, row] of result.entries()) { + if (row !== void 0 && isDataExpired(row)) { + expiredKeys.push(keyPrefixed[index]); + result[index] = void 0; + } + } + if (expiredKeys.length > 0) { + await this.deleteMany(expiredKeys); + } + this.stats.hitsOrMisses(result); + this.hooks.trigger("postGetManyRaw" /* POST_GET_MANY_RAW */, { + keys: keyPrefixed, + values: result + }); + return result; + } + /** + * Set an item to the store + * @param {string | Array} key the key to use. If you pass in an array of KeyvEntry it will set many items + * @param {Value} value the value of the key + * @param {number} [ttl] time to live in milliseconds + * @returns {boolean} if it sets then it will return a true. On failure will return false. + */ + async set(key, value, ttl) { + const data = { key, value, ttl }; + this.hooks.trigger("preSet" /* PRE_SET */, data); + const keyPrefixed = this._getKeyPrefix(data.key); + data.ttl ??= this._ttl; + if (data.ttl === 0) { + data.ttl = void 0; + } + const { store } = this.opts; + const expires = typeof data.ttl === "number" ? Date.now() + data.ttl : void 0; + if (typeof data.value === "symbol") { + this.emit("error", "symbol cannot be serialized"); + throw new Error("symbol cannot be serialized"); + } + const formattedValue = { value: data.value, expires }; + const serializedValue = await this.serializeData(formattedValue); + let result = true; + try { + const value2 = await store.set(keyPrefixed, serializedValue, data.ttl); + if (typeof value2 === "boolean") { + result = value2; + } + } catch (error) { + result = false; + this.emit("error", error); + if (this._throwOnErrors) { + throw error; + } + } + this.hooks.trigger("postSet" /* POST_SET */, { + key: keyPrefixed, + value: serializedValue, + ttl + }); + this.stats.set(); + return result; + } + /** + * Set many items to the store + * @param {Array} entries the entries to set + * @returns {boolean[]} will return an array of booleans if it sets then it will return a true. On failure will return false. + */ + // biome-ignore lint/correctness/noUnusedVariables: type format + async setMany(entries) { + let results = []; + try { + if (this._store.setMany === void 0) { + const promises = []; + for (const entry of entries) { + promises.push(this.set(entry.key, entry.value, entry.ttl)); + } + const promiseResults = await Promise.all(promises); + results = promiseResults; + } else { + const serializedEntries = await Promise.all( + entries.map(async ({ key, value, ttl }) => { + ttl ??= this._ttl; + if (ttl === 0) { + ttl = void 0; + } + const expires = typeof ttl === "number" ? Date.now() + ttl : void 0; + if (typeof value === "symbol") { + this.emit("error", "symbol cannot be serialized"); + throw new Error("symbol cannot be serialized"); + } + const formattedValue = { value, expires }; + const serializedValue = await this.serializeData(formattedValue); + const keyPrefixed = this._getKeyPrefix(key); + return { key: keyPrefixed, value: serializedValue, ttl }; + }) + ); + results = await this._store.setMany(serializedEntries); + } + } catch (error) { + this.emit("error", error); + if (this._throwOnErrors) { + throw error; + } + results = entries.map(() => false); + } + return results; + } + /** + * Delete an Entry + * @param {string | string[]} key the key to be deleted. if an array it will delete many items + * @returns {boolean} will return true if item or items are deleted. false if there is an error + */ + async delete(key) { + const { store } = this.opts; + if (Array.isArray(key)) { + return this.deleteMany(key); + } + const keyPrefixed = this._getKeyPrefix(key); + this.hooks.trigger("preDelete" /* PRE_DELETE */, { key: keyPrefixed }); + let result = true; + try { + const value = await store.delete(keyPrefixed); + if (typeof value === "boolean") { + result = value; + } + } catch (error) { + result = false; + this.emit("error", error); + if (this._throwOnErrors) { + throw error; + } + } + this.hooks.trigger("postDelete" /* POST_DELETE */, { + key: keyPrefixed, + value: result + }); + this.stats.delete(); + return result; + } + /** + * Delete many items from the store + * @param {string[]} keys the keys to be deleted + * @returns {boolean} will return true if item or items are deleted. false if there is an error + */ + async deleteMany(keys) { + try { + const { store } = this.opts; + const keyPrefixed = this._getKeyPrefixArray(keys); + this.hooks.trigger("preDelete" /* PRE_DELETE */, { key: keyPrefixed }); + if (store.deleteMany !== void 0) { + return await store.deleteMany(keyPrefixed); + } + const promises = keyPrefixed.map(async (key) => store.delete(key)); + const results = await Promise.all(promises); + const returnResult = results.every(Boolean); + this.hooks.trigger("postDelete" /* POST_DELETE */, { + key: keyPrefixed, + value: returnResult + }); + return returnResult; + } catch (error) { + this.emit("error", error); + if (this._throwOnErrors) { + throw error; + } + return false; + } + } + /** + * Clear the store + * @returns {void} + */ + async clear() { + this.emit("clear"); + const { store } = this.opts; + try { + await store.clear(); + } catch (error) { + this.emit("error", error); + if (this._throwOnErrors) { + throw error; + } + } + } + async has(key) { + if (Array.isArray(key)) { + return this.hasMany(key); + } + const keyPrefixed = this._getKeyPrefix(key); + const { store } = this.opts; + if (store.has !== void 0 && !(store instanceof Map)) { + return store.has(keyPrefixed); + } + let rawData; + try { + rawData = await store.get(keyPrefixed); + } catch (error) { + this.emit("error", error); + if (this._throwOnErrors) { + throw error; + } + return false; + } + if (rawData) { + const data = await this.deserializeData(rawData); + if (data) { + if (data.expires === void 0 || data.expires === null) { + return true; + } + return data.expires > Date.now(); + } + } + return false; + } + /** + * Check if many keys exist + * @param {string[]} keys the keys to check + * @returns {boolean[]} will return an array of booleans if the keys exist + */ + async hasMany(keys) { + const keyPrefixed = this._getKeyPrefixArray(keys); + const { store } = this.opts; + if (store.hasMany !== void 0) { + return store.hasMany(keyPrefixed); + } + const results = []; + for (const key of keys) { + results.push(await this.has(key)); + } + return results; + } + /** + * Will disconnect the store. This is only available if the store has a disconnect method + * @returns {Promise} + */ + async disconnect() { + const { store } = this.opts; + this.emit("disconnect"); + if (typeof store.disconnect === "function") { + return store.disconnect(); + } + } + // biome-ignore lint/suspicious/noExplicitAny: type format + emit(event, ...arguments_) { + if (event === "error" && !this.opts.emitErrors) { + return; + } + super.emit(event, ...arguments_); + } + async serializeData(data) { + if (!this._serialize) { + return data; + } + if (this._compression?.compress) { + return this._serialize({ + value: await this._compression.compress(data.value), + expires: data.expires + }); + } + return this._serialize(data); + } + async deserializeData(data) { + if (!this._deserialize) { + return data; + } + if (this._compression?.decompress && typeof data === "string") { + const result = await this._deserialize(data); + return { + value: await this._compression.decompress(result?.value), + expires: result?.expires + }; + } + if (typeof data === "string") { + return this._deserialize(data); + } + return void 0; + } +}; +var index_default = (/* unused pure expression or super */ null && (Keyv)); + +/* v8 ignore next -- @preserve */ + +;// CONCATENATED MODULE: ./node_modules/mimic-response/index.js +// We define these manually to ensure they're always copied +// even if they would move up the prototype chain +// https://nodejs.org/api/http.html#http_class_http_incomingmessage +const knownProperties = [ + 'aborted', + 'complete', + 'headers', + 'httpVersion', + 'httpVersionMinor', + 'httpVersionMajor', + 'method', + 'rawHeaders', + 'rawTrailers', + 'setTimeout', + 'socket', + 'statusCode', + 'statusMessage', + 'trailers', + 'url', +]; + +function mimicResponse(fromStream, toStream) { + if (toStream._readableState.autoDestroy) { + throw new Error('The second stream must have the `autoDestroy` option set to `false`'); + } + + const fromProperties = new Set([...Object.keys(fromStream), ...knownProperties]); + + const properties = {}; + + for (const property of fromProperties) { + // Don't overwrite existing properties. + if (property in toStream) { + continue; + } + + properties[property] = { + get() { + const value = fromStream[property]; + const isFunction = typeof value === 'function'; + + return isFunction ? value.bind(fromStream) : value; + }, + set(value) { + fromStream[property] = value; + }, + enumerable: true, + configurable: false, + }; + } + + Object.defineProperties(toStream, properties); + + fromStream.once('aborted', () => { + toStream.destroy(); + + toStream.emit('aborted'); + }); + + fromStream.once('close', () => { + if (fromStream.complete) { + if (toStream.readable) { + toStream.once('end', () => { + toStream.emit('close'); + }); + } else { + toStream.emit('close'); + } + } else { + toStream.emit('close'); + } + }); + + return toStream; +} + +;// CONCATENATED MODULE: ./node_modules/normalize-url/index.js +// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs +const DATA_URL_DEFAULT_MIME_TYPE = 'text/plain'; +const DATA_URL_DEFAULT_CHARSET = 'us-ascii'; + +const testParameter = (name, filters) => filters.some(filter => filter instanceof RegExp ? filter.test(name) : filter === name); + +const supportedProtocols = new Set([ + 'https:', + 'http:', + 'file:', +]); + +const hasCustomProtocol = urlString => { + try { + const {protocol} = new URL(urlString); + + return protocol.endsWith(':') + && !protocol.includes('.') + && !supportedProtocols.has(protocol); + } catch { + return false; + } +}; + +const normalizeDataURL = (urlString, {stripHash}) => { + const match = /^data:(?[^,]*?),(?[^#]*?)(?:#(?.*))?$/.exec(urlString); + + if (!match) { + throw new Error(`Invalid URL: ${urlString}`); + } + + const {type, data, hash} = match.groups; + const mediaType = type.split(';'); + + const isBase64 = mediaType.at(-1) === 'base64'; + if (isBase64) { + mediaType.pop(); + } + + // Lowercase MIME type + const mimeType = mediaType.shift()?.toLowerCase() ?? ''; + const attributes = mediaType + .map(attribute => { + let [key, value = ''] = attribute.split('=').map(string => string.trim()); + + // Lowercase `charset` + if (key === 'charset') { + value = value.toLowerCase(); + + if (value === DATA_URL_DEFAULT_CHARSET) { + return ''; + } + } + + return `${key}${value ? `=${value}` : ''}`; + }) + .filter(Boolean); + + const normalizedMediaType = [...attributes]; + + if (isBase64) { + normalizedMediaType.push('base64'); + } + + if (normalizedMediaType.length > 0 || (mimeType && mimeType !== DATA_URL_DEFAULT_MIME_TYPE)) { + normalizedMediaType.unshift(mimeType); + } + + const hashPart = stripHash || !hash ? '' : `#${hash}`; + return `data:${normalizedMediaType.join(';')},${isBase64 ? data.trim() : data}${hashPart}`; +}; + +function normalizeUrl(urlString, options) { + options = { + defaultProtocol: 'http', + normalizeProtocol: true, + forceHttp: false, + forceHttps: false, + stripAuthentication: true, + stripHash: false, + stripTextFragment: true, + stripWWW: true, + removeQueryParameters: [/^utm_\w+/i], + removeTrailingSlash: true, + removeSingleSlash: true, + removeDirectoryIndex: false, + removeExplicitPort: false, + sortQueryParameters: true, + removePath: false, + transformPath: false, + ...options, + }; + + // Legacy: Append `:` to the protocol if missing. + if (typeof options.defaultProtocol === 'string' && !options.defaultProtocol.endsWith(':')) { + options.defaultProtocol = `${options.defaultProtocol}:`; + } + + urlString = urlString.trim(); + + // Data URL + if (/^data:/i.test(urlString)) { + return normalizeDataURL(urlString, options); + } + + if (hasCustomProtocol(urlString)) { + return urlString; + } + + const hasRelativeProtocol = urlString.startsWith('//'); + const isRelativeUrl = !hasRelativeProtocol && /^\.*\//.test(urlString); + + // Prepend protocol + if (!isRelativeUrl) { + urlString = urlString.replace(/^(?!(?:\w+:)?\/\/)|^\/\//, options.defaultProtocol); + } + + const urlObject = new URL(urlString); + + if (options.forceHttp && options.forceHttps) { + throw new Error('The `forceHttp` and `forceHttps` options cannot be used together'); + } + + if (options.forceHttp && urlObject.protocol === 'https:') { + urlObject.protocol = 'http:'; + } + + if (options.forceHttps && urlObject.protocol === 'http:') { + urlObject.protocol = 'https:'; + } + + // Remove auth + if (options.stripAuthentication) { + urlObject.username = ''; + urlObject.password = ''; + } + + // Remove hash + if (options.stripHash) { + urlObject.hash = ''; + } else if (options.stripTextFragment) { + urlObject.hash = urlObject.hash.replace(/#?:~:text.*?$/i, ''); + } + + // Remove duplicate slashes if not preceded by a protocol + // NOTE: This could be implemented using a single negative lookbehind + // regex, but we avoid that to maintain compatibility with older js engines + // which do not have support for that feature. + if (urlObject.pathname) { + // TODO: Replace everything below with `urlObject.pathname = urlObject.pathname.replace(/(? 0) { + const pathComponents = urlObject.pathname.split('/').filter(Boolean); + const lastComponent = pathComponents.at(-1); + + if (lastComponent && testParameter(lastComponent, options.removeDirectoryIndex)) { + pathComponents.pop(); + urlObject.pathname = pathComponents.length > 0 ? `/${pathComponents.join('/')}/` : '/'; + } + } + + // Remove path + if (options.removePath) { + urlObject.pathname = '/'; + } + + // Transform path components + if (options.transformPath && typeof options.transformPath === 'function') { + const pathComponents = urlObject.pathname.split('/').filter(Boolean); + const newComponents = options.transformPath(pathComponents); + urlObject.pathname = newComponents?.length > 0 ? `/${newComponents.join('/')}` : '/'; + } + + if (urlObject.hostname) { + // Remove trailing dot + urlObject.hostname = urlObject.hostname.replace(/\.$/, ''); + + // Remove `www.` + if (options.stripWWW && /^www\.(?!www\.)[a-z\-\d]{1,63}\.[a-z.\-\d]{2,63}$/.test(urlObject.hostname)) { + // Each label should be max 63 at length (min: 1). + // Source: https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names + // Each TLD should be up to 63 characters long (min: 2). + // It is technically possible to have a single character TLD, but none currently exist. + urlObject.hostname = urlObject.hostname.replace(/^www\./, ''); + } + } + + // Remove query unwanted parameters + if (Array.isArray(options.removeQueryParameters)) { + // eslint-disable-next-line unicorn/no-useless-spread -- We are intentionally spreading to get a copy. + for (const key of [...urlObject.searchParams.keys()]) { + if (testParameter(key, options.removeQueryParameters)) { + urlObject.searchParams.delete(key); + } + } + } + + if (!Array.isArray(options.keepQueryParameters) && options.removeQueryParameters === true) { + urlObject.search = ''; + } + + // Keep wanted query parameters + if (Array.isArray(options.keepQueryParameters) && options.keepQueryParameters.length > 0) { + // eslint-disable-next-line unicorn/no-useless-spread -- We are intentionally spreading to get a copy. + for (const key of [...urlObject.searchParams.keys()]) { + if (!testParameter(key, options.keepQueryParameters)) { + urlObject.searchParams.delete(key); + } + } + } + + // Sort query parameters + if (options.sortQueryParameters) { + const originalSearch = urlObject.search; + urlObject.searchParams.sort(); + + // Calling `.sort()` encodes the search parameters, so we need to decode them again. + try { + urlObject.search = decodeURIComponent(urlObject.search); + } catch {} + + // Fix parameters that originally had no equals sign but got one added by URLSearchParams + const partsWithoutEquals = originalSearch.slice(1).split('&').filter(p => p && !p.includes('=')); + for (const part of partsWithoutEquals) { + const decoded = decodeURIComponent(part); + // Only replace at word boundaries to avoid partial matches + urlObject.search = urlObject.search.replace(`?${decoded}=`, `?${decoded}`).replace(`&${decoded}=`, `&${decoded}`); + } + } + + if (options.removeTrailingSlash) { + urlObject.pathname = urlObject.pathname.replace(/\/$/, ''); + } + + // Remove an explicit port number, excluding a default port number, if applicable + if (options.removeExplicitPort && urlObject.port) { + urlObject.port = ''; + } + + const oldUrlString = urlString; + + // Take advantage of many of the Node `url` normalizations + urlString = urlObject.toString(); + + if (!options.removeSingleSlash && urlObject.pathname === '/' && !oldUrlString.endsWith('/') && urlObject.hash === '') { + urlString = urlString.replace(/\/$/, ''); + } + + // Remove ending `/` unless removeSingleSlash is false + if ((options.removeTrailingSlash || urlObject.pathname === '/') && urlObject.hash === '' && options.removeSingleSlash) { + urlString = urlString.replace(/\/$/, ''); + } + + // Restore relative protocol, if applicable + if (hasRelativeProtocol && !options.normalizeProtocol) { + urlString = urlString.replace(/^http:\/\//, '//'); + } + + // Remove http/https + if (options.stripProtocol) { + urlString = urlString.replace(/^(?:https?:)?\/\//, ''); + } + + return urlString; +} + +;// CONCATENATED MODULE: ./node_modules/responselike/node_modules/lowercase-keys/index.js +function lowercaseKeys(object) { + return Object.fromEntries(Object.entries(object).map(([key, value]) => [key.toLowerCase(), value])); +} + +;// CONCATENATED MODULE: ./node_modules/responselike/index.js + + + +class Response extends external_node_stream_.Readable { + statusCode; + headers; + body; + url; + complete; + + constructor({statusCode, headers, body, url}) { + if (typeof statusCode !== 'number') { + throw new TypeError('Argument `statusCode` should be a number'); + } + + if (typeof headers !== 'object') { + throw new TypeError('Argument `headers` should be an object'); + } + + if (!(body instanceof Uint8Array)) { + throw new TypeError('Argument `body` should be a buffer'); + } + + if (typeof url !== 'string') { + throw new TypeError('Argument `url` should be a string'); + } + + let bodyPushed = false; + super({ + read() { + // Push body on first read, end stream on second read. + // This allows listeners to attach before data flows through pipes. + if (!bodyPushed) { + bodyPushed = true; + this.push(body); + return; + } + + this.push(null); + }, + }); + + this.statusCode = statusCode; + this.headers = lowercaseKeys(headers); + this.body = body; + this.url = url; + this.complete = true; + } +} + +;// CONCATENATED MODULE: ./node_modules/cacheable-request/dist/types.js +// Type definitions for cacheable-request 6.0 +// Project: https://github.com/lukechilds/cacheable-request#readme +// Definitions by: BendingBender +// Paul Melnikow +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.3 +class types_RequestError extends Error { + constructor(error) { + super(error.message); + Object.defineProperties(this, Object.getOwnPropertyDescriptors(error)); + } +} +class types_CacheError extends Error { + constructor(error) { + super(error.message); + Object.defineProperties(this, Object.getOwnPropertyDescriptors(error)); + } +} +//# sourceMappingURL=types.js.map +;// CONCATENATED MODULE: ./node_modules/cacheable-request/dist/index.js +// biome-ignore-all lint/suspicious/noImplicitAnyLet: legacy format +// biome-ignore-all lint/suspicious/noExplicitAny: legacy format + + + + + + + + + + + +class CacheableRequest { + constructor(cacheRequest, cacheAdapter) { + this.cache = new Keyv({ namespace: "cacheable-request" }); + this.hooks = new Map(); + this.request = () => (options, callback) => { + let url; + if (typeof options === "string") { + url = normalizeUrlObject(parseWithWhatwg(options)); + options = {}; + } + else if (options instanceof external_node_url_.URL) { + url = normalizeUrlObject(parseWithWhatwg(options.toString())); + options = {}; + } + else { + const [pathname, ...searchParts] = (options.path ?? "").split("?"); + const search = searchParts.length > 0 ? `?${searchParts.join("?")}` : ""; + url = normalizeUrlObject({ ...options, pathname, search }); + } + options = { + headers: {}, + method: "GET", + cache: true, + strictTtl: false, + automaticFailover: false, + ...options, + ...urlObjectToRequestOptions(url), + }; + options.headers = Object.fromEntries(entries(options.headers).map(([key, value]) => [ + key.toLowerCase(), + value, + ])); + const ee = new external_node_events_(); + const normalizedUrlString = normalizeUrl(external_node_url_.format(url), { + stripWWW: false, + removeTrailingSlash: false, + stripAuthentication: false, + }); + let key = `${options.method}:${normalizedUrlString}`; + // POST, PATCH, and PUT requests may be cached, depending on the response + // cache-control headers. As a result, the body of the request should be + // added to the cache key in order to avoid collisions. + if (options.body && + options.method !== undefined && + ["POST", "PATCH", "PUT"].includes(options.method)) { + if (options.body instanceof external_node_stream_.Readable) { + // Streamed bodies should completely skip the cache because they may + // or may not be hashable and in either case the stream would need to + // close before the cache key could be generated. + options.cache = false; + } + else { + key += `:${external_node_crypto_.createHash("md5").update(options.body).digest("hex")}`; + } + } + let revalidate = false; + let madeRequest = false; + const makeRequest = (options_) => { + madeRequest = true; + let requestErrored = false; + /* c8 ignore next 4 */ + let requestErrorCallback = () => { + /* do nothing */ + }; + const requestErrorPromise = new Promise((resolve) => { + requestErrorCallback = () => { + if (!requestErrored) { + requestErrored = true; + resolve(); + } + }; + }); + const handler = async (response) => { + if (revalidate) { + response.status = response.statusCode; + const originalPolicy = http_cache_semantics.fromObject(revalidate.cachePolicy); + const revalidatedPolicy = originalPolicy.revalidatedPolicy(options_, response); + if (!revalidatedPolicy.modified) { + response.resume(); + await new Promise((resolve) => { + // Skipping 'error' handler cause 'error' event should't be emitted for 304 response + response.once("end", resolve); + }); + // Get headers from revalidated policy + const headers = convertHeaders(revalidatedPolicy.policy.responseHeaders()); + // Preserve headers from the original cached response that may have been + // lost during revalidation (e.g., content-encoding, content-type, etc.) + // This works around a limitation in http-cache-semantics where some headers + // are not preserved when a 304 response has minimal headers + const originalHeaders = convertHeaders(originalPolicy.responseHeaders()); + // Headers that should be preserved from the cached response + // according to RFC 7232 section 4.1 + const preserveHeaders = [ + "content-encoding", + "content-type", + "content-length", + "content-language", + "content-location", + "etag", + ]; + for (const headerName of preserveHeaders) { + if (originalHeaders[headerName] !== undefined && + headers[headerName] === undefined) { + headers[headerName] = originalHeaders[headerName]; + } + } + response = new Response({ + statusCode: revalidate.statusCode, + headers, + body: revalidate.body, + url: revalidate.url, + }); + response.cachePolicy = revalidatedPolicy.policy; + response.fromCache = true; + } + } + if (!response.fromCache) { + response.cachePolicy = new http_cache_semantics(options_, response, options_); + response.fromCache = false; + } + let clonedResponse; + if (options_.cache && response.cachePolicy.storable()) { + clonedResponse = cloneResponse(response); + (async () => { + try { + const bodyPromise = getStreamAsBuffer(response); + await Promise.race([ + requestErrorPromise, + new Promise((resolve) => response.once("end", resolve)), + new Promise((resolve) => response.once("close", resolve)), + ]); + const body = await bodyPromise; + let value = { + url: response.url, + statusCode: response.fromCache + ? revalidate.statusCode + : response.statusCode, + body, + cachePolicy: response.cachePolicy.toObject(), + }; + let ttl = options_.strictTtl + ? response.cachePolicy.timeToLive() + : undefined; + if (options_.maxTtl) { + ttl = ttl ? Math.min(ttl, options_.maxTtl) : options_.maxTtl; + } + if (this.hooks.size > 0) { + for (const key_ of this.hooks.keys()) { + value = await this.runHook(key_, value, response); + } + } + await this.cache.set(key, value, ttl); + /* c8 ignore next -- @preserve */ + } + catch (error) { + /* c8 ignore next -- @preserve */ + ee.emit("error", new types_CacheError(error)); + /* c8 ignore next -- @preserve */ + } + })(); + } + else if (options_.cache && revalidate) { + (async () => { + try { + await this.cache.delete(key); + /* c8 ignore next -- @preserve */ + } + catch (error) { + /* c8 ignore next -- @preserve */ + ee.emit("error", new types_CacheError(error)); + /* c8 ignore next -- @preserve */ + } + })(); + } + ee.emit("response", clonedResponse ?? response); + if (typeof callback === "function") { + callback(clonedResponse ?? response); + } + }; + try { + const request_ = this.cacheRequest(options_, handler); + request_.once("error", requestErrorCallback); + request_.once("abort", requestErrorCallback); + request_.once("destroy", requestErrorCallback); + ee.emit("request", request_); + } + catch (error) { + ee.emit("error", new types_RequestError(error)); + } + }; + (async () => { + const get = async (options_) => { + await Promise.resolve(); + const cacheEntry = options_.cache + ? await this.cache.get(key) + : undefined; + if (cacheEntry === undefined && !options_.forceRefresh) { + makeRequest(options_); + return; + } + const policy = http_cache_semantics.fromObject(cacheEntry.cachePolicy); + if (policy.satisfiesWithoutRevalidation(options_) && + !options_.forceRefresh) { + const headers = convertHeaders(policy.responseHeaders()); + const bodyBuffer = cacheEntry.body; + const body = Buffer.from(bodyBuffer); + const response = new Response({ + statusCode: cacheEntry.statusCode, + headers, + body, + url: cacheEntry.url, + }); + response.cachePolicy = policy; + response.fromCache = true; + ee.emit("response", response); + if (typeof callback === "function") { + callback(response); + } + } + else if (policy.satisfiesWithoutRevalidation(options_) && + Date.now() >= policy.timeToLive() && + options_.forceRefresh) { + await this.cache.delete(key); + options_.headers = policy.revalidationHeaders(options_); + makeRequest(options_); + } + else { + revalidate = cacheEntry; + options_.headers = policy.revalidationHeaders(options_); + makeRequest(options_); + } + }; + const errorHandler = (error) => ee.emit("error", new types_CacheError(error)); + if (this.cache instanceof Keyv) { + const cachek = this.cache; + cachek.once("error", errorHandler); + ee.on("error", () => { + cachek.removeListener("error", errorHandler); + }); + ee.on("response", () => { + cachek.removeListener("error", errorHandler); + }); + } + try { + await get(options); + } + catch (error) { + /* v8 ignore next -- @preserve */ + if (options.automaticFailover && !madeRequest) { + makeRequest(options); + } + ee.emit("error", new types_CacheError(error)); + } + })(); + return ee; + }; + this.addHook = (name, function_) => { + if (!this.hooks.has(name)) { + this.hooks.set(name, function_); + } + }; + this.removeHook = (name) => this.hooks.delete(name); + this.getHook = (name) => this.hooks.get(name); + this.runHook = async (name, ...arguments_) => this.hooks.get(name)?.(...arguments_); + if (cacheAdapter) { + if (cacheAdapter instanceof Keyv) { + this.cache = cacheAdapter; + } + else { + this.cache = new Keyv({ + store: cacheAdapter, + namespace: "cacheable-request", + }); + } + } + this.request = this.request.bind(this); + this.cacheRequest = cacheRequest; + } +} +const entries = Object.entries; +const cloneResponse = (response) => { + const clone = new external_node_stream_.PassThrough({ autoDestroy: false }); + mimicResponse(response, clone); + return response.pipe(clone); +}; +const urlObjectToRequestOptions = (url) => { + const options = { ...url }; + options.path = `${url.pathname || "/"}${url.search || ""}`; + delete options.pathname; + delete options.search; + return options; +}; +const normalizeUrlObject = (url) => +// If url was parsed by url.parse or new URL: +// - hostname will be set +// - host will be hostname[:port] +// - port will be set if it was explicit in the parsed string +// Otherwise, url was from request options: +// - hostname or host may be set +// - host shall not have port encoded +({ + protocol: url.protocol, + auth: url.auth, + hostname: url.hostname || url.host || "localhost", + port: url.port, + pathname: url.pathname, + search: url.search, +}); +const convertHeaders = (headers) => { + const result = []; + for (const name of Object.keys(headers)) { + result[name.toLowerCase()] = headers[name]; + } + return result; +}; +const parseWithWhatwg = (raw) => { + const u = new external_node_url_.URL(raw); + // If normalizeUrlObject expects the same fields as url.parse() + return { + protocol: u.protocol, // E.g. 'https:' + slashes: true, // Always true for WHATWG URLs + /* c8 ignore next 3 */ + auth: u.username || u.password ? `${u.username}:${u.password}` : undefined, + host: u.host, // E.g. 'example.com:8080' + port: u.port, // E.g. '8080' + hostname: u.hostname, // E.g. 'example.com' + hash: u.hash, // E.g. '#quux' + search: u.search, // E.g. '?bar=baz' + query: Object.fromEntries(u.searchParams), // { bar: 'baz' } + pathname: u.pathname, // E.g. '/foo' + path: u.pathname + u.search, // '/foo?bar=baz' + href: u.href, // Full serialized URL + }; +}; +/* harmony default export */ const dist = (CacheableRequest); + +const onResponse = "onResponse"; +//# sourceMappingURL=index.js.map +// EXTERNAL MODULE: external "node:zlib" +var external_node_zlib_ = __webpack_require__(38522); +;// CONCATENATED MODULE: ./node_modules/decompress-response/index.js + + + + +// Detect zstd support (available in Node.js >= 22.15.0) +const supportsZstd = typeof external_node_zlib_.createZstdDecompress === 'function'; + +function decompressResponse(response) { + const contentEncoding = (response.headers['content-encoding'] || '').toLowerCase(); + const supportedEncodings = ['gzip', 'deflate', 'br']; + if (supportsZstd) { + supportedEncodings.push('zstd'); + } + + if (!supportedEncodings.includes(contentEncoding)) { + return response; + } + + let isEmpty = true; + + // Clone headers to avoid modifying the original response headers + const headers = {...response.headers}; + + const finalStream = new external_node_stream_.PassThrough({ + autoDestroy: false, + }); + + // Only destroy response on error, not on normal completion + finalStream.once('error', () => { + response.destroy(); + }); + + function handleContentEncoding(data) { + let decompressStream; + + if (contentEncoding === 'zstd') { + decompressStream = external_node_zlib_.createZstdDecompress(); + } else if (contentEncoding === 'br') { + decompressStream = external_node_zlib_.createBrotliDecompress(); + } else if (contentEncoding === 'deflate' && data.length > 0 && (data[0] & 0x08) === 0) { // eslint-disable-line no-bitwise + decompressStream = external_node_zlib_.createInflateRaw(); + } else { + decompressStream = external_node_zlib_.createUnzip(); + } + + decompressStream.once('error', error => { + if (isEmpty && !response.readable) { + finalStream.end(); + return; + } + + finalStream.destroy(error); + }); + + checker.pipe(decompressStream).pipe(finalStream); + } + + const checker = new external_node_stream_.Transform({ + transform(data, _encoding, callback) { + if (isEmpty === false) { + callback(null, data); + return; + } + + isEmpty = false; + + handleContentEncoding(data); + + callback(null, data); + }, + + flush(callback) { + if (isEmpty) { + finalStream.end(); + } + + callback(); + }, + }); + + delete headers['content-encoding']; + delete headers['content-length']; + finalStream.headers = headers; + + mimicResponse(response, finalStream); + + response.pipe(checker); + + return finalStream; +} + +// EXTERNAL MODULE: external "node:util" +var external_node_util_ = __webpack_require__(57975); +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/utils/defer-to-connect.js +function isTlsSocket(socket) { + return 'encrypted' in socket; +} +const deferToConnect = (socket, fn) => { + const listeners = typeof fn === 'function' ? { connect: fn } : fn; + const onConnect = () => { + listeners.connect?.(); + if (isTlsSocket(socket) && listeners.secureConnect) { + if (socket.authorized) { + listeners.secureConnect(); + } + else { + // Wait for secureConnect event (even if authorization fails, we need the timing) + socket.once('secureConnect', listeners.secureConnect); + } + } + if (listeners.close) { + socket.once('close', listeners.close); + } + }; + if (socket.writable && !socket.connecting) { + onConnect(); + } + else if (socket.connecting) { + socket.once('connect', onConnect); + } + else if (socket.destroyed && listeners.close) { + const hadError = '_hadError' in socket ? Boolean(socket._hadError) : false; + listeners.close(hadError); + } +}; +/* harmony default export */ const defer_to_connect = (deferToConnect); + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/utils/timer.js + + + +const getInitialConnectionTimings = (socket) => Reflect.get(socket, '__initial_connection_timings__'); +const setInitialConnectionTimings = (socket, timings) => { + Reflect.set(socket, '__initial_connection_timings__', timings); +}; +const timer = (request) => { + if (request.timings) { + return request.timings; + } + const timings = { + start: Date.now(), + socket: undefined, + lookup: undefined, + connect: undefined, + secureConnect: undefined, + upload: undefined, + response: undefined, + end: undefined, + error: undefined, + abort: undefined, + phases: { + wait: undefined, + dns: undefined, + tcp: undefined, + tls: undefined, + request: undefined, + firstByte: undefined, + download: undefined, + total: undefined, + }, + }; + request.timings = timings; + const handleError = (origin) => { + origin.once(external_node_events_.errorMonitor, () => { + timings.error = Date.now(); + timings.phases.total = timings.error - timings.start; + }); + }; + handleError(request); + const onAbort = () => { + timings.abort = Date.now(); + timings.phases.total = timings.abort - timings.start; + }; + request.prependOnceListener('abort', onAbort); + const onSocket = (socket) => { + timings.socket = Date.now(); + timings.phases.wait = timings.socket - timings.start; + if (external_node_util_.types.isProxy(socket)) { + // HTTP/2: The socket is a proxy, so connection events won't fire. + // We can't measure connection timings, so leave them undefined. + // This prevents NaN in phases.request calculation. + return; + } + // Check if socket is already connected (reused from connection pool) + const socketAlreadyConnected = socket.writable && !socket.connecting; + if (socketAlreadyConnected) { + // Socket reuse detected: the socket was already connected from a previous request. + // For reused sockets, set all connection timestamps to socket time since no new + // connection was made for THIS request. But preserve phase durations from the + // original connection so they're not lost. + timings.lookup = timings.socket; + timings.connect = timings.socket; + const initialConnectionTimings = getInitialConnectionTimings(socket); + if (initialConnectionTimings) { + // Restore the phase timings from the initial connection + timings.phases.dns = initialConnectionTimings.dnsPhase; + timings.phases.tcp = initialConnectionTimings.tcpPhase; + timings.phases.tls = initialConnectionTimings.tlsPhase; + // Set secureConnect timestamp if there was TLS + if (timings.phases.tls !== undefined) { + timings.secureConnect = timings.socket; + } + } + else { + // Socket reused but no initial timings stored (e.g., from external code) + // Set phases to 0 + timings.phases.dns = 0; + timings.phases.tcp = 0; + } + return; + } + const lookupListener = () => { + timings.lookup = Date.now(); + timings.phases.dns = timings.lookup - timings.socket; + }; + socket.prependOnceListener('lookup', lookupListener); + defer_to_connect(socket, { + connect() { + timings.connect = Date.now(); + if (timings.lookup === undefined) { + // No DNS lookup occurred (e.g., connecting to an IP address directly) + // Set lookup to socket time (no time elapsed for DNS) + socket.removeListener('lookup', lookupListener); + timings.lookup = timings.socket; + timings.phases.dns = 0; + } + timings.phases.tcp = timings.connect - timings.lookup; + // If lookup and connect happen at the EXACT same time (tcp = 0), + // DNS was served from cache and the dns value is just event loop overhead. + // Set dns to 0 to indicate no actual DNS resolution occurred. + // Fixes https://github.com/szmarczak/http-timer/issues/35 + if (timings.phases.tcp === 0 && timings.phases.dns && timings.phases.dns > 0) { + timings.phases.dns = 0; + } + // Store connection phase timings on socket for potential reuse + if (!getInitialConnectionTimings(socket)) { + setInitialConnectionTimings(socket, { + dnsPhase: timings.phases.dns, + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion -- TypeScript can't prove this is defined due to callback structure + tcpPhase: timings.phases.tcp, + }); + } + }, + secureConnect() { + timings.secureConnect = Date.now(); + timings.phases.tls = timings.secureConnect - timings.connect; + // Update stored timings with TLS phase timing + const initialConnectionTimings = getInitialConnectionTimings(socket); + if (initialConnectionTimings) { + initialConnectionTimings.tlsPhase = timings.phases.tls; + } + }, + }); + }; + if (request.socket) { + onSocket(request.socket); + } + else { + request.prependOnceListener('socket', onSocket); + } + const onUpload = () => { + timings.upload = Date.now(); + // Calculate request phase if we have connection timings + const secureOrConnect = timings.secureConnect ?? timings.connect; + if (secureOrConnect !== undefined) { + timings.phases.request = timings.upload - secureOrConnect; + } + // If both are undefined (HTTP/2), phases.request stays undefined (not NaN) + }; + if (request.writableFinished) { + onUpload(); + } + else { + request.prependOnceListener('finish', onUpload); + } + request.prependOnceListener('response', (response) => { + timings.response = Date.now(); + timings.phases.firstByte = timings.response - timings.upload; + response.timings = timings; + handleError(response); + response.prependOnceListener('end', () => { + request.off('abort', onAbort); + response.off('aborted', onAbort); + if (timings.phases.total !== undefined) { + // Aborted or errored + return; + } + timings.end = Date.now(); + timings.phases.download = timings.end - timings.response; + timings.phases.total = timings.end - timings.start; + }); + response.prependOnceListener('aborted', onAbort); + }); + return timings; +}; +/* harmony default export */ const utils_timer = (timer); + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/utils/get-body-size.js + + +function getBodySize(body, headers) { + if (headers && 'content-length' in headers) { + return Number(headers['content-length']); + } + if (!body) { + return 0; + } + if (distribution.string(body)) { + return stringToUint8Array(body).byteLength; + } + if (distribution.buffer(body)) { + return body.length; + } + if (distribution.typedArray(body)) { + return body.byteLength; + } + return undefined; +} + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/utils/proxy-events.js +function proxyEvents(from, to, events) { + const eventFunctions = new Map(); + for (const event of events) { + const eventFunction = (...arguments_) => { + to.emit(event, ...arguments_); + }; + eventFunctions.set(event, eventFunction); + from.on(event, eventFunction); + } + return () => { + for (const [event, eventFunction] of eventFunctions) { + from.off(event, eventFunction); + } + }; +} + +// EXTERNAL MODULE: external "node:net" +var external_node_net_ = __webpack_require__(77030); +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/utils/unhandle.js +// When attaching listeners, it's very easy to forget about them. +// Especially if you do error handling and set timeouts. +// So instead of checking if it's proper to throw an error on every timeout ever, +// use this simple tool which will remove all listeners you have attached. +function unhandle() { + const handlers = []; + return { + once(origin, event, function_) { + origin.once(event, function_); + handlers.push({ origin, event, fn: function_ }); + }, + unhandleAll() { + for (const { origin, event, fn } of handlers) { + origin.removeListener(event, fn); + } + handlers.length = 0; + }, + }; +} + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/timed-out.js + + +const reentry = Symbol('reentry'); +const timed_out_noop = () => { }; +class timed_out_TimeoutError extends Error { + name = 'TimeoutError'; + code = 'ETIMEDOUT'; + event; + constructor(threshold, event) { + super(`Timeout awaiting '${event}' for ${threshold}ms`); + this.event = event; + } +} +function timedOut(request, delays, options) { + if (reentry in request) { + return timed_out_noop; + } + request[reentry] = true; + const cancelers = []; + const { once, unhandleAll } = unhandle(); + const handled = new Set(); + const addTimeout = (delay, callback, event) => { + const timeout = setTimeout(callback, delay, delay, event); + timeout.unref(); + const cancel = () => { + handled.add(event); + clearTimeout(timeout); + }; + cancelers.push(cancel); + return cancel; + }; + const { host, hostname } = options; + const timeoutHandler = (delay, event) => { + // Use setTimeout to allow for any cancelled events to be handled first, + // to prevent firing any TimeoutError unneeded when the event loop is busy or blocked + setTimeout(() => { + if (!handled.has(event)) { + request.destroy(new timed_out_TimeoutError(delay, event)); + } + }, 0); + }; + const cancelTimeouts = () => { + for (const cancel of cancelers) { + cancel(); + } + unhandleAll(); + }; + request.once('error', error => { + cancelTimeouts(); + // Save original behavior + /* istanbul ignore next */ + if (request.listenerCount('error') === 0) { + throw error; + } + }); + if (delays.request !== undefined) { + const cancelTimeout = addTimeout(delays.request, timeoutHandler, 'request'); + once(request, 'response', (response) => { + once(response, 'end', cancelTimeout); + }); + } + if (delays.socket !== undefined) { + const { socket } = delays; + const socketTimeoutHandler = () => { + timeoutHandler(socket, 'socket'); + }; + request.setTimeout(socket, socketTimeoutHandler); + // `request.setTimeout(0)` causes a memory leak. + // We can just remove the listener and forget about the timer - it's unreffed. + // See https://github.com/sindresorhus/got/issues/690 + cancelers.push(() => { + request.removeListener('timeout', socketTimeoutHandler); + }); + } + const hasLookup = delays.lookup !== undefined; + const hasConnect = delays.connect !== undefined; + const hasSecureConnect = delays.secureConnect !== undefined; + const hasSend = delays.send !== undefined; + if (hasLookup || hasConnect || hasSecureConnect || hasSend) { + once(request, 'socket', (socket) => { + const { socketPath } = request; + /* istanbul ignore next: hard to test */ + if (socket.connecting) { + const hasPath = Boolean(socketPath ?? (external_node_net_.isIP(hostname ?? host ?? '') !== 0)); + if (hasLookup && !hasPath && socket.address().address === undefined) { + const cancelTimeout = addTimeout(delays.lookup, timeoutHandler, 'lookup'); + once(socket, 'lookup', cancelTimeout); + } + if (hasConnect) { + const timeConnect = () => addTimeout(delays.connect, timeoutHandler, 'connect'); + if (hasPath) { + once(socket, 'connect', timeConnect()); + } + else { + once(socket, 'lookup', (error) => { + if (error === null) { + once(socket, 'connect', timeConnect()); + } + }); + } + } + if (hasSecureConnect && options.protocol === 'https:') { + once(socket, 'connect', () => { + const cancelTimeout = addTimeout(delays.secureConnect, timeoutHandler, 'secureConnect'); + once(socket, 'secureConnect', cancelTimeout); + }); + } + } + if (hasSend) { + const timeRequest = () => addTimeout(delays.send, timeoutHandler, 'send'); + /* istanbul ignore next: hard to test */ + if (socket.connecting) { + once(socket, 'connect', () => { + once(request, 'upload-complete', timeRequest()); + }); + } + else { + once(request, 'upload-complete', timeRequest()); + } + } + }); + } + if (delays.response !== undefined) { + once(request, 'upload-complete', () => { + const cancelTimeout = addTimeout(delays.response, timeoutHandler, 'response'); + once(request, 'response', cancelTimeout); + }); + } + if (delays.read !== undefined) { + once(request, 'response', (response) => { + const cancelTimeout = addTimeout(delays.read, timeoutHandler, 'read'); + once(response, 'end', cancelTimeout); + }); + } + return cancelTimeouts; +} + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/utils/weakable-map.js +class WeakableMap { + weakMap = new WeakMap(); + map = new Map(); + set(key, value) { + if (typeof key === 'object') { + this.weakMap.set(key, value); + } + else { + this.map.set(key, value); + } + } + get(key) { + if (typeof key === 'object') { + return this.weakMap.get(key); + } + return this.map.get(key); + } + has(key) { + if (typeof key === 'object') { + return this.weakMap.has(key); + } + return this.map.has(key); + } +} + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/calculate-retry-delay.js +const calculateRetryDelay = ({ attemptCount, retryOptions, error, retryAfter, computedValue, }) => { + if (error.name === 'RetryError') { + return 1; + } + if (attemptCount > retryOptions.limit) { + return 0; + } + const hasMethod = retryOptions.methods.includes(error.options.method); + const hasErrorCode = retryOptions.errorCodes.includes(error.code); + const hasStatusCode = error.response && retryOptions.statusCodes.includes(error.response.statusCode); + if (!hasMethod || (!hasErrorCode && !hasStatusCode)) { + return 0; + } + if (error.response) { + if (retryAfter) { + // In this case `computedValue` is `retryOptions.maxRetryAfter ?? options.timeout.request ?? Infinity` + return retryAfter > computedValue ? 0 : retryAfter; + } + if (error.response.statusCode === 413) { + return 0; + } + } + const noise = Math.random() * retryOptions.noise; + return Math.min(((2 ** (attemptCount - 1)) * 1000), retryOptions.backoffLimit) + noise; +}; +/* harmony default export */ const calculate_retry_delay = (calculateRetryDelay); + +// EXTERNAL MODULE: external "node:tls" +var external_node_tls_ = __webpack_require__(41692); +// EXTERNAL MODULE: external "node:https" +var external_node_https_ = __webpack_require__(44708); +;// CONCATENATED MODULE: ./node_modules/lowercase-keys/index.js +function lowercase_keys_lowercaseKeys(object, {onConflict} = {}) { + if (typeof object !== 'object' || object === null) { + throw new TypeError(`Expected an object, got ${object === null ? 'null' : typeof object}`); + } + + const result = {}; + + for (const [key, value] of Object.entries(object)) { + const lowercasedKey = key.toLowerCase(); + const hasExistingKey = Object.hasOwn(result, lowercasedKey); + const existingValue = hasExistingKey ? result[lowercasedKey] : undefined; + + const resolvedValue = onConflict && hasExistingKey + ? onConflict({key: lowercasedKey, newValue: value, existingValue}) + : value; + + Object.defineProperty(result, lowercasedKey, { + value: resolvedValue, + writable: true, + enumerable: true, + configurable: true, + }); + } + + return result; +} + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/parse-link-header.js +const splitHeaderValue = (value, separator) => { + const values = []; + let current = ''; + let inQuotes = false; + let inReference = false; + let isEscaped = false; + for (const character of value) { + if (inQuotes && isEscaped) { + current += character; + isEscaped = false; + continue; + } + if (inQuotes && character === '\\') { + current += character; + isEscaped = true; + continue; + } + if (character === '"') { + inQuotes = !inQuotes; + current += character; + continue; + } + if (!inQuotes && character === '<') { + inReference = true; + current += character; + continue; + } + if (!inQuotes && character === '>') { + inReference = false; + current += character; + continue; + } + // Link headers use both quoted strings and values, so raw + // splitting on `,` / `;` would break valid values containing those characters. + if (!inQuotes && !inReference && character === separator) { + values.push(current); + current = ''; + continue; + } + current += character; + } + if (inQuotes) { + throw new Error(`Failed to parse Link header: ${value}`); + } + values.push(current); + return values; +}; +function parseLinkHeader(link) { + const parsed = []; + const items = splitHeaderValue(link, ','); + for (const item of items) { + // https://tools.ietf.org/html/rfc5988#section-5 + const [rawUriReference, ...rawLinkParameters] = splitHeaderValue(item, ';'); + const trimmedUriReference = rawUriReference.trim(); + // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with + if (trimmedUriReference[0] !== '<' || trimmedUriReference.at(-1) !== '>') { + throw new Error(`Invalid format of the Link header reference: ${trimmedUriReference}`); + } + const reference = trimmedUriReference.slice(1, -1); + const parameters = {}; + if (reference.includes('<') || reference.includes('>')) { + throw new Error(`Invalid format of the Link header reference: ${trimmedUriReference}`); + } + if (rawLinkParameters.length === 0) { + throw new Error(`Unexpected end of Link header parameters: ${rawLinkParameters.join(';')}`); + } + for (const rawParameter of rawLinkParameters) { + const trimmedRawParameter = rawParameter.trim(); + const center = trimmedRawParameter.indexOf('='); + if (center === -1) { + throw new Error(`Failed to parse Link header: ${link}`); + } + const name = trimmedRawParameter.slice(0, center).trim(); + const value = trimmedRawParameter.slice(center + 1).trim(); + parameters[name] = value; + } + parsed.push({ + reference, + parameters, + }); + } + return parsed; +} + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/utils/is-unix-socket-url.js +function isUnixSocketUrl(url) { + return url.protocol === 'unix:' || url.hostname === 'unix'; +} +/** +Extract the socket path from a UNIX socket URL. + +@example +``` +getUnixSocketPath(new URL('http://unix/foo:/path')); +//=> '/foo' + +getUnixSocketPath(new URL('unix:/foo:/path')); +//=> '/foo' + +getUnixSocketPath(new URL('http://example.com')); +//=> undefined +``` +*/ +function getUnixSocketPath(url) { + if (!isUnixSocketUrl(url)) { + return undefined; + } + return /^(?[^:]+):/v.exec(`${url.pathname}${url.search}`)?.groups?.socketPath; +} + +// EXTERNAL MODULE: external "node:dns" +var external_node_dns_ = __webpack_require__(40610); +// EXTERNAL MODULE: external "node:os" +var external_node_os_ = __webpack_require__(48161); +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/utils/dns-cache.js + + + + +const ttl = { ttl: true }; +const noResultErrorCodes = new Set(['ENODATA', 'ENOTFOUND', 'ENOENT']); +const maximumCacheTtl = Math.floor(2_147_483_647 / 1000); +const isPromiseLike = (value) => typeof value?.then === 'function'; +const now = () => Date.now(); +const hasUnexpired = (cache, key) => { + const expires = cache.get(key); + if (expires === undefined) { + return false; + } + if (expires <= now()) { + cache.delete(key); + return false; + } + return true; +}; +const deleteExpiredMapEntries = (cache, time = now()) => { + for (const [key, expires] of cache) { + if (expires <= time) { + cache.delete(key); + } + } +}; +// eslint-disable-next-line no-bitwise +const hasFlag = (value, flag) => value !== undefined && (value & flag) === flag; +const getInterfaceInfo = () => { + let has4 = false; + let has6 = false; + for (const networkInterface of Object.values(external_node_os_.networkInterfaces())) { + if (networkInterface === undefined) { + continue; + } + for (const address of networkInterface) { + if (address.internal) { + continue; + } + if (address.family === 'IPv6') { + has6 = true; + } + else { + has4 = true; + } + if (has4 && has6) { + return { has4, has6 }; + } + } + } + return { has4, has6 }; +}; +const createNoResultError = (hostname) => { + const error = new Error(`DNS cache lookup ENOTFOUND ${hostname}`); + error.code = 'ENOTFOUND'; + error.hostname = hostname; + return error; +}; +const normalizeLookupOptions = (options) => { + if (typeof options === 'number') { + return { family: options }; + } + return options ?? {}; +}; +const normalizeResolverRecord = (record, family, maxTtl) => { + const entryTtl = Math.min(record.ttl, maxTtl); + return { + address: record.address, + family, + expires: now() + (entryTtl * 1000), + }; +}; +const map4To6 = (entries) => entries.map(entry => { + if (entry.family === 6) { + return entry; + } + return { + ...entry, + address: `::ffff:${entry.address}`, + family: 6, + }; +}); +const familyFromOptions = (options) => { + if (options.family === 4 || options.family === 6) { + return options.family; + } + if (options.family === 'IPv4') { + return 4; + } + if (options.family === 'IPv6') { + return 6; + } + return undefined; +}; +const orderFromOptions = (options) => { + if (options.order !== undefined) { + return options.order; + } + if (options.verbatim !== undefined) { + return options.verbatim ? 'verbatim' : 'ipv4first'; + } + return (0,external_node_dns_.getDefaultResultOrder)(); +}; +const familiesFromOptions = (options) => { + const family = familyFromOptions(options); + if (family === 6 && hasFlag(options.hints, external_node_dns_.V4MAPPED) && hasFlag(options.hints, external_node_dns_.ALL)) { + return [6, 4]; + } + if (family !== undefined) { + return [family]; + } + if (orderFromOptions(options) === 'ipv6first') { + return [6, 4]; + } + return [4, 6]; +}; +const filterFamiliesByAddrConfig = (families, options) => { + if (!hasFlag(options.hints, external_node_dns_.ADDRCONFIG)) { + return families; + } + const interfaceInfo = getInterfaceInfo(); + return families.filter(family => family === 6 ? interfaceInfo.has6 : interfaceInfo.has4); +}; +const shouldQueryMappedIpv4 = (entries, options) => familyFromOptions(options) === 6 + && hasFlag(options.hints, external_node_dns_.V4MAPPED) + && !hasFlag(options.hints, external_node_dns_.ALL) + && entries.every(entry => entry.family !== 6); +const cacheKey = (hostname, family) => `${hostname}:${family}`; +const lookupOptionsKey = (hostname, options) => `${hostname}:${familyFromOptions(options) ?? 0}:${options.hints ?? 0}:${orderFromOptions(options)}`; +const shouldIgnoreResolveError = (error) => error.code !== undefined && noResultErrorCodes.has(error.code); +const toLookupResult = ({ address, family }) => ({ + address, + family, +}); +class DnsCache { + lookup; + #cache; + #resolver; + #dnsLookupAsync; + #cacheKeys = new Set(); + #pending = new Map(); + #pendingFallback = new Map(); + #lookupOptionsToFallback = new Map(); + #lookupOptionsWithoutFallback = new Map(); + #maxTtl; + #fallbackDuration; + #errorTtl; + #minimumVersionByHostname = new Map(); + #activeQueriesByHostname = new Map(); + #minimumVersion = 0; + #clearVersion = 0; + constructor({ cache = new Map(), maxTtl = maximumCacheTtl, fallbackDuration = 3600, errorTtl = 0.15, resolver = new external_node_dns_.promises.Resolver(), lookup = external_node_dns_.lookup, } = {}) { + this.#cache = cache; + this.#resolver = resolver; + this.#maxTtl = Math.min(maxTtl, maximumCacheTtl); + this.#fallbackDuration = fallbackDuration; + this.#errorTtl = errorTtl; + this.#dnsLookupAsync = lookup === false ? undefined : (0,external_node_util_.promisify)(lookup); + this.lookup = this.#lookup.bind(this); + } + async lookupAsync(hostname, options) { + const normalizedOptions = normalizeLookupOptions(options); + const literalFamily = (0,external_node_net_.isIP)(hostname); + if (literalFamily !== 0) { + const entries = [{ + address: hostname, + family: literalFamily, + }]; + return normalizedOptions.all ? entries : entries[0]; + } + let entries = await this.#query(hostname, normalizedOptions); + entries = this.#filterEntries(entries, normalizedOptions); + if (entries.length === 0) { + throw createNoResultError(hostname); + } + const lookupResults = entries.map(entry => toLookupResult(entry)); + return normalizedOptions.all ? lookupResults : lookupResults[0]; + } + clear(hostname) { + this.#clearVersion++; + if (hostname === undefined) { + this.#minimumVersion = this.#clearVersion; + this.#minimumVersionByHostname.clear(); + for (const key of this.#cacheKeys) { + this.#cache.delete(key); + } + this.#cacheKeys.clear(); + this.#pending.clear(); + this.#pendingFallback.clear(); + this.#lookupOptionsToFallback.clear(); + this.#lookupOptionsWithoutFallback.clear(); + return; + } + for (const family of [4, 6]) { + const key = cacheKey(hostname, family); + this.#cache.delete(key); + this.#cacheKeys.delete(key); + this.#pending.delete(key); + } + if (this.#activeQueriesByHostname.has(hostname)) { + this.#minimumVersionByHostname.set(hostname, this.#clearVersion); + } + for (const key of this.#pendingFallback.keys()) { + if (key.startsWith(`${hostname}:`)) { + this.#pendingFallback.delete(key); + } + } + for (const key of this.#lookupOptionsToFallback.keys()) { + if (key.startsWith(`${hostname}:`)) { + this.#lookupOptionsToFallback.delete(key); + } + } + for (const key of this.#lookupOptionsWithoutFallback.keys()) { + if (key.startsWith(`${hostname}:`)) { + this.#lookupOptionsWithoutFallback.delete(key); + } + } + } + #lookup(hostname, options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } + if (callback === undefined) { + throw new Error('Callback must be a function.'); + } + const normalizedOptions = normalizeLookupOptions(options); + void this.#lookupAndCallback(hostname, normalizedOptions, callback); + } + async #lookupAndCallback(hostname, options, callback) { + let result; + try { + result = await this.lookupAsync(hostname, options); + } + catch (error) { + queueMicrotask(() => { + const callbackWithError = callback; + callbackWithError(error); + }); + return; + } + queueMicrotask(() => { + if (options.all) { + callback(null, result); + return; + } + const entry = result; + callback(null, entry.address, entry.family); + }); + } + async #query(hostname, options) { + this.#activeQueriesByHostname.set(hostname, (this.#activeQueriesByHostname.get(hostname) ?? 0) + 1); + try { + const lookupOptionKey = lookupOptionsKey(hostname, options); + if (hasUnexpired(this.#lookupOptionsToFallback, lookupOptionKey)) { + return await this.#fallbackLookupOnce(hostname, options, lookupOptionKey); + } + let families = filterFamiliesByAddrConfig(familiesFromOptions(options), options); + const clearVersion = this.#clearVersion; + let flattenedEntries = await this.#queryFamilies(hostname, families, clearVersion); + if (shouldQueryMappedIpv4(flattenedEntries, options) && !families.includes(4)) { + families = filterFamiliesByAddrConfig([4], options); + flattenedEntries = await this.#queryFamilies(hostname, families, clearVersion); + } + if (flattenedEntries.length > 0 || this.#dnsLookupAsync === undefined) { + return flattenedEntries; + } + if (hasUnexpired(this.#lookupOptionsWithoutFallback, lookupOptionKey)) { + return []; + } + const fallbackEntries = await this.#fallbackLookupOnce(hostname, options, lookupOptionKey); + if (!this.#isVersionCurrent(hostname, clearVersion)) { + return fallbackEntries; + } + this.#deleteExpiredFallbackState(); + if (fallbackEntries.length > 0 && this.#fallbackDuration > 0) { + this.#lookupOptionsToFallback.set(lookupOptionKey, now() + (this.#fallbackDuration * 1000)); + } + else if (fallbackEntries.length === 0 && this.#errorTtl > 0) { + this.#lookupOptionsWithoutFallback.set(lookupOptionKey, now() + (this.#errorTtl * 1000)); + } + return fallbackEntries; + } + finally { + this.#finishQuery(hostname); + } + } + #finishQuery(hostname) { + const activeQueryCount = this.#activeQueriesByHostname.get(hostname); + if (activeQueryCount === undefined) { + return; + } + if (activeQueryCount > 1) { + this.#activeQueriesByHostname.set(hostname, activeQueryCount - 1); + return; + } + this.#activeQueriesByHostname.delete(hostname); + this.#minimumVersionByHostname.delete(hostname); + } + #deleteExpiredFallbackState() { + const time = now(); + deleteExpiredMapEntries(this.#lookupOptionsToFallback, time); + deleteExpiredMapEntries(this.#lookupOptionsWithoutFallback, time); + } + async #queryFamilies(hostname, families, clearVersion) { + if (families.length === 1) { + return this.#queryFamily(hostname, families[0], clearVersion); + } + const results = await Promise.allSettled(families.map(family => this.#queryFamily(hostname, family, clearVersion))); + const entries = results.flatMap(result => result.status === 'fulfilled' ? result.value : []); + if (entries.length > 0) { + return entries; + } + const rejected = results.find(result => result.status === 'rejected'); + if (rejected !== undefined) { + if (rejected.reason instanceof Error) { + throw rejected.reason; + } + throw new Error(String(rejected.reason)); + } + return []; + } + async #queryFamily(hostname, family, clearVersion) { + const key = cacheKey(hostname, family); + const cached = await this.#getCachedFamily(key, hostname); + if (cached !== undefined) { + return cached.entries; + } + if (!this.#isVersionCurrent(hostname, clearVersion)) { + return this.#resolveAndCache(hostname, family, clearVersion); + } + const pending = this.#pending.get(key); + if (pending !== undefined) { + return pending; + } + const promise = this.#resolveAndCache(hostname, family, clearVersion); + this.#pending.set(key, promise); + try { + return await promise; + } + finally { + if (this.#pending.get(key) === promise) { + this.#pending.delete(key); + } + } + } + async #getCachedFamily(key, hostname) { + let cached = this.#cache.get(key); + if (isPromiseLike(cached)) { + cached = await cached; + } + if (cached === undefined) { + return undefined; + } + if (!this.#isVersionCurrent(hostname, cached.clearVersion)) { + return undefined; + } + if (cached.expires <= now()) { + this.#cache.delete(key); + this.#cacheKeys.delete(key); + return undefined; + } + return cached; + } + async #resolveAndCache(hostname, family, clearVersion) { + const entries = await this.#resolveFamily(hostname, family); + const expires = this.#expiresFor(entries); + const key = cacheKey(hostname, family); + if (!this.#isVersionCurrent(hostname, clearVersion)) { + return entries; + } + if (expires !== undefined) { + await this.#setCachedFamily(key, hostname, { + entries, + expires, + }, clearVersion); + } + else if (entries.length === 0 && this.#errorTtl > 0) { + await this.#setCachedFamily(key, hostname, { + entries, + expires: now() + (this.#errorTtl * 1000), + }, clearVersion); + } + return entries; + } + async #setCachedFamily(key, hostname, cached, clearVersion) { + if (!this.#isVersionCurrent(hostname, clearVersion)) { + return; + } + await this.#deleteExpiredCacheEntries(); + await this.#cache.set(key, { + ...cached, + clearVersion, + }); + this.#cacheKeys.add(key); + if (this.#isVersionCurrent(hostname, clearVersion)) { + return; + } + let current = this.#cache.get(key); + if (isPromiseLike(current)) { + current = await current; + } + if (current?.clearVersion === clearVersion && !this.#isVersionCurrent(hostname, current.clearVersion)) { + this.#cache.delete(key); + this.#cacheKeys.delete(key); + } + } + async #deleteExpiredCacheEntries() { + const time = now(); + await Promise.all([...this.#cacheKeys].map(async (key) => this.#deleteExpiredCacheEntry(key, time))); + } + async #deleteExpiredCacheEntry(key, time) { + let cached = this.#cache.get(key); + if (isPromiseLike(cached)) { + cached = await cached; + } + if (cached === undefined) { + this.#cacheKeys.delete(key); + return; + } + if (cached.expires > time) { + return; + } + let current = this.#cache.get(key); + if (isPromiseLike(current)) { + current = await current; + } + if (current?.clearVersion === cached.clearVersion && current.expires === cached.expires) { + this.#cache.delete(key); + this.#cacheKeys.delete(key); + } + } + #isVersionCurrent(hostname, clearVersion) { + const minimumVersion = this.#minimumVersionByHostname.get(hostname) ?? this.#minimumVersion; + return clearVersion >= minimumVersion; + } + async #resolveFamily(hostname, family) { + try { + const records = family === 4 + ? await this.#resolver.resolve4(hostname, ttl) + : await this.#resolver.resolve6(hostname, ttl); + return records.map(record => normalizeResolverRecord(record, family, this.#maxTtl)); + } + catch (error) { + if (shouldIgnoreResolveError(error)) { + return []; + } + throw error; + } + } + #expiresFor(entries) { + let expires = Number.POSITIVE_INFINITY; + for (const entry of entries) { + if (entry.expires === undefined) { + continue; + } + expires = Math.min(expires, entry.expires); + } + return expires === Number.POSITIVE_INFINITY ? undefined : expires; + } + #filterEntries(entries, options) { + if (hasFlag(options.hints, external_node_dns_.ADDRCONFIG)) { + const interfaceInfo = getInterfaceInfo(); + entries = entries.filter(entry => entry.family === 6 ? interfaceInfo.has6 : interfaceInfo.has4); + } + const family = familyFromOptions(options); + if (family === 6) { + const ipv6Entries = entries.filter(entry => entry.family === 6); + if (hasFlag(options.hints, external_node_dns_.V4MAPPED)) { + entries = hasFlag(options.hints, external_node_dns_.ALL) || ipv6Entries.length === 0 + ? map4To6(entries) + : ipv6Entries; + } + else { + entries = ipv6Entries; + } + } + else if (family === 4) { + entries = entries.filter(entry => entry.family === 4); + } + return entries; + } + async #fallbackLookupOnce(hostname, options, key) { + const pending = this.#pendingFallback.get(key); + if (pending !== undefined) { + return pending; + } + const promise = this.#fallbackLookup(hostname, options); + this.#pendingFallback.set(key, promise); + try { + return await promise; + } + finally { + if (this.#pendingFallback.get(key) === promise) { + this.#pendingFallback.delete(key); + } + } + } + async #fallbackLookup(hostname, options) { + if (this.#dnsLookupAsync === undefined) { + return []; + } + let entries; + try { + entries = await this.#dnsLookupAsync(hostname, { + ...options, + all: true, + }); + } + catch (error) { + if (shouldIgnoreResolveError(error)) { + return []; + } + throw error; + } + return entries.map(entry => ({ + address: entry.address, + family: entry.family, + })); + } +} + +// EXTERNAL MODULE: external "node:http2" +var external_node_http2_ = __webpack_require__(32467); +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/utils/http2-client.js +/* eslint-disable @typescript-eslint/member-ordering, @typescript-eslint/naming-convention, @typescript-eslint/no-restricted-types, @typescript-eslint/no-deprecated, promise/prefer-await-to-then */ + + + + + + + + + + +const { HTTP2_HEADER_AUTHORITY, HTTP2_HEADER_METHOD, HTTP2_HEADER_PATH, HTTP2_HEADER_SCHEME, HTTP2_HEADER_STATUS, HTTP2_METHOD_CONNECT, NGHTTP2_CANCEL, } = external_node_http2_.constants; +const maxProtocolCacheSize = 100; +const protocolCache = new Map(); +const referenceIds = new WeakMap(); +let nextReferenceId = 0; +const connectionSpecificHeaders = new Set([ + 'connection', + 'http2-settings', + 'keep-alive', + 'proxy-connection', + 'transfer-encoding', + 'upgrade', +]); +const normalizeRequestHeaderName = (name) => name.toLowerCase() === 'host' ? HTTP2_HEADER_AUTHORITY : name.toLowerCase(); +const getConnectionHeaderTokens = (value) => { + if (value === undefined) { + return []; + } + const values = Array.isArray(value) ? value : [value]; + const tokens = []; + for (const item of values) { + for (const token of String(item).split(',')) { + const normalizedToken = token.trim().toLowerCase(); + if (normalizedToken.length > 0) { + tokens.push(normalizedToken); + } + } + } + return tokens; +}; +const isTrailersTeHeader = (value) => { + if (value === undefined) { + return true; + } + if (Array.isArray(value)) { + return value.length === 1 && value[0].toLowerCase() === 'trailers'; + } + return String(value).trim().toLowerCase() === 'trailers'; +}; +const setProtocolCache = (key, value) => { + if (!protocolCache.has(key) && protocolCache.size >= maxProtocolCacheSize) { + protocolCache.delete(protocolCache.keys().next().value); + } + protocolCache.set(key, value); +}; +const getReferenceId = (value) => { + let referenceId = referenceIds.get(value); + if (referenceId === undefined) { + referenceId = nextReferenceId++; + referenceIds.set(value, referenceId); + } + return referenceId; +}; +const http2_client_isPlainObject = (value) => { + const prototype = Object.getPrototypeOf(value); + return prototype === Object.prototype || prototype === null; +}; +const serializeSessionOption = (value) => { + if (value === undefined) { + return ['undefined']; + } + if (value === null) { + return ['null']; + } + if (typeof value === 'function') { + return ['function', getReferenceId(value)]; + } + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return [typeof value, value]; + } + if (typeof value === 'bigint') { + return ['bigint', value.toString()]; + } + if (typeof value === 'symbol') { + return ['symbol', value.description]; + } + if (Array.isArray(value)) { + return ['array', value.map(item => serializeSessionOption(item))]; + } + if (typeof value === 'object') { + if (ArrayBuffer.isView(value)) { + return ['bytes', external_node_buffer_.Buffer.from(value.buffer, value.byteOffset, value.byteLength).toString('base64')]; + } + if (http2_client_isPlainObject(value)) { + return ['object', Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => [key, serializeSessionOption(item)])]; + } + return ['object-reference', getReferenceId(value)]; + } + return [typeof value]; +}; +const serializeSessionOptions = (values) => JSON.stringify(values.map(value => serializeSessionOption(value))); +const getTlsSessionOptions = (options) => [ + options.ca, + options.cert, + options.key, + options.pfx, + options.rejectUnauthorized, + options.servername, + options.localAddress, + options.lookup, + options.family, + options.minVersion, + options.maxVersion, + options.ciphers, + options.honorCipherOrder, + options.checkServerIdentity, + options.passphrase, + options.sigalgs, + options.sessionTimeout, + options.dhparam, + options.ecdhCurve, + options.crl, + options.secureOptions, + options.secureContext, + options.secureProtocol, +]; +const destroyReuseSocket = (options) => { + options._reuseSocket?.destroy(); + delete options._reuseSocket; + delete options._reuseSocketShouldPool; +}; +const normalizeInput = (input, options, callback) => { + let normalizedOptions; + if (typeof input === 'string') { + normalizedOptions = (0,external_node_url_.urlToHttpOptions)(new URL(input)); + } + else if (input instanceof URL) { + normalizedOptions = (0,external_node_url_.urlToHttpOptions)(input); + } + else { + normalizedOptions = { ...input }; + } + if (typeof options === 'function' || options === undefined) { + callback = options; + } + else { + normalizedOptions = { + ...normalizedOptions, + ...options, + }; + } + return { options: normalizedOptions, callback }; +}; +const getAuthority = (options) => { + const protocol = options.protocol ?? 'https:'; + const defaultPort = protocol === 'https:' ? 443 : 80; + if (options.hostname === undefined && options.host !== undefined) { + try { + const authority = new URL(`${protocol}//${options.host}`); + const port = options.port ?? authority.port; + authority.port = String(port === '' ? defaultPort : port); + return authority; + } + catch { + // Fall back to hostname normalization for values like bare IPv6 addresses. + } + } + const hostname = options.hostname ?? options.host ?? 'localhost'; + const port = options.port ?? defaultPort; + const hostnameString = String(hostname); + const normalizedHostname = hostnameString.startsWith('[') && hostnameString.endsWith(']') + ? hostnameString.slice(1, -1) + : hostnameString; + const formattedHostname = external_node_net_.isIP(normalizedHostname) === 6 ? `[${normalizedHostname}]` : normalizedHostname; + const authority = new URL(`${protocol}//${formattedHostname}`); + authority.port = String(port); + return authority; +}; +const getAuthorityPort = (authority) => { + if (authority.port !== '') { + return Number(authority.port); + } + return authority.protocol === 'https:' ? 443 : 80; +}; +const getConnectionHostname = (authority) => { + const { hostname } = authority; + return hostname.startsWith('[') && hostname.endsWith(']') + ? hostname.slice(1, -1) + : hostname; +}; +const hasCustomHttpsAgent = (agent) => typeof agent === 'object' + && 'https' in agent + && agent.https !== undefined + && agent.https !== false; +const getProtocolCacheKey = (options) => { + const authority = getAuthority(options); + const protocols = (options.ALPNProtocols ?? ['h2', 'http/1.1']).join(','); + return serializeSessionOptions([ + authority.host, + protocols, + ...getTlsSessionOptions(options), + ]); +}; +const resolveProtocol = async (options, sourceOptions) => { + const cacheKey = getProtocolCacheKey(options); + const cachedProtocol = options.createConnection ? undefined : protocolCache.get(cacheKey); + if (cachedProtocol !== undefined) { + return { alpnProtocol: cachedProtocol }; + } + const authority = getAuthority(options); + const { path: _path, agent: _agent, h2session: _h2session, _reuseSocket, _reuseSocketShouldPool, _alpnSocket, _socketTimeout, timeout, createConnection, checkServerIdentity, ...connectionOptions } = options; + const port = getAuthorityPort(authority); + const hostname = getConnectionHostname(authority); + const servername = options.servername ?? (external_node_net_.isIP(hostname) === 0 ? hostname : undefined); + const tlsOptions = { + ...connectionOptions, + ALPNProtocols: options.ALPNProtocols ?? ['h2', 'http/1.1'], + host: hostname, + port, + servername, + }; + if (checkServerIdentity) { + tlsOptions.checkServerIdentity = checkServerIdentity; + } + const socket = createConnection + ? createConnection(tlsOptions, () => { }) + : external_node_tls_.connect(port, hostname, tlsOptions); + options._alpnSocket = socket; + sourceOptions._alpnSocket = socket; + return new Promise((resolve, reject) => { + let settled = false; + let timeoutId; + let removeAbortListener; + let socketTimeoutApplied = false; + const cleanup = () => { + if (timeoutId) { + clearTimeout(timeoutId); + } + removeAbortListener?.(); + socket.off('secureConnect', onSecureConnect); + socket.off('error', onError); + socket.off('close', onClose); + socket.off('connect', applySocketTimeout); + socket.off('timeout', onSocketTimeout); + if (socketTimeoutApplied) { + socket.setTimeout(0); + } + delete options._alpnSocket; + delete sourceOptions._alpnSocket; + }; + const rejectOnce = (error) => { + if (settled) { + return; + } + settled = true; + cleanup(); + socket.destroy(); + reject(error); + }; + const onSecureConnect = () => { + if (settled) { + return; + } + settled = true; + cleanup(); + const alpnProtocol = socket.alpnProtocol ?? false; + if (!options.createConnection) { + setProtocolCache(cacheKey, alpnProtocol); + } + resolve({ alpnProtocol, socket }); + }; + const onError = (error) => { + rejectOnce(error); + }; + const onTimeout = () => { + rejectOnce(new timed_out_TimeoutError(Number(timeout), 'request')); + }; + const onSocketTimeout = () => { + rejectOnce(new timed_out_TimeoutError(_socketTimeout, 'socket')); + }; + const applySocketTimeout = () => { + socketTimeoutApplied = true; + socket.setTimeout(_socketTimeout); + socket.once('timeout', onSocketTimeout); + }; + const onClose = () => { + const error = new Error('The HTTP/2 ALPN socket closed before negotiation completed'); + error.code = 'ECONNRESET'; + rejectOnce(error); + }; + const onAbort = () => { + const error = new Error('This operation was aborted.'); + error.name = 'AbortError'; + error.code = 'ERR_ABORTED'; + rejectOnce(error); + }; + if (options.signal?.aborted) { + onAbort(); + return; + } + socket.once('secureConnect', onSecureConnect); + socket.once('error', onError); + socket.once('close', onClose); + if (_socketTimeout !== undefined) { + if (socket.connecting) { + socket.once('connect', applySocketTimeout); + } + else { + applySocketTimeout(); + } + } + if (options.signal) { + options.signal.addEventListener('abort', onAbort, { once: true }); + removeAbortListener = () => { + options.signal?.removeEventListener('abort', onAbort); + }; + } + if (timeout !== undefined) { + timeoutId = setTimeout(onTimeout, Number(timeout)); + timeoutId.unref(); + } + }); +}; +const toRawHeaders = (headers) => { + const rawHeaders = []; + for (const [key, value] of Object.entries(headers)) { + if (key.startsWith(':') || value === undefined) { + continue; + } + if (Array.isArray(value)) { + for (const item of value) { + rawHeaders.push(key, item); + } + } + else { + rawHeaders.push(key, String(value)); + } + } + return rawHeaders; +}; +const filterRawHeaders = (rawHeaders) => { + const filteredHeaders = []; + for (let index = 0; index < rawHeaders.length; index += 2) { + const key = rawHeaders[index]; + if (key.startsWith(':')) { + continue; + } + filteredHeaders.push(key, rawHeaders[index + 1]); + } + return filteredHeaders; +}; +const filterHeaders = (headers) => { + const filteredHeaders = {}; + for (const [key, value] of Object.entries(headers)) { + if (key.startsWith(':') || value === undefined) { + continue; + } + filteredHeaders[key] = value; + } + return filteredHeaders; +}; +const createSocketProxy = (stream) => new Proxy(stream.session.socket, { + get(target, property, receiver) { + if (property === 'destroy') { + return stream.destroy.bind(stream); + } + if (property === 'destroyed') { + return stream.destroyed; + } + if (property === 'setTimeout') { + return stream.setTimeout.bind(stream); + } + return Reflect.get(target, property, receiver); + }, +}); +class Http2IncomingMessage extends external_node_stream_.Readable { + stream; + req; + constructor(stream, request_, highWaterMark) { + super({ + autoDestroy: true, + emitClose: false, + highWaterMark, + }); + this.stream = stream; + this.req = request_; + this.socket = request_.socket; + } + aborted = false; + httpVersion = '2.0'; + httpVersionMajor = 2; + httpVersionMinor = 0; + complete = false; + rawHeaders = []; + rawTrailers = []; + headers = {}; + trailers = {}; + statusCode; + statusMessage; + socket; + url = ''; + method; + upgrade = false; + get connection() { + return this.socket; + } + set connection(value) { + this.socket = value; + } + setTimeout(ms, callback) { + this.req.setTimeout(ms, callback); + return this; + } + _destroy(error, callback) { + if (!this.readableEnded) { + this.aborted = true; + } + this.stream.destroy(error ?? undefined); + callback(); + } + _read() { + this.stream.resume(); + } + _dump() { + this.removeAllListeners('data'); + this.resume(); + } +} +class Http2Agent extends external_node_events_.EventEmitter { + timeout; + maxSessions; + maxEmptySessions; + sessions = new Map(); + pendingSessions = new Set(); + pendingSessionKeys = new Set(); + queue = []; + emptySessionCount = 0; + sessionCount = 0; + settings = { + enablePush: false, + initialWindowSize: 1024 * 1024 * 32, + }; + constructor({ timeout = 0, maxSessions = Number.POSITIVE_INFINITY, maxEmptySessions = 10 } = {}) { + super(); + this.timeout = timeout; + this.maxSessions = maxSessions; + this.maxEmptySessions = maxEmptySessions; + } + get protocol() { + return 'https:'; + } + async request(origin, options, headers, streamOptions) { + const { session, reusedSocket } = await this.getSessionWithMetadata(origin, options, true); + return { + stream: session.request(headers, streamOptions), + reusedSocket, + }; + } + async getSession(origin, options = {}) { + const { session } = await this.getSessionWithMetadata(origin, options); + return session; + } + async getSessionWithMetadata(origin, options = {}, reserveStream = false) { + const normalizedOrigin = typeof origin === 'string' ? new URL(origin) : origin; + const key = this.normalizeOptions(normalizedOrigin, options); + const canUsePooledSession = options._reuseSocket === undefined || options._reuseSocketShouldPool === true; + const session = canUsePooledSession ? this.getAvailableSession(key) : undefined; + if (session) { + if (reserveStream) { + this.reserveStream(session); + } + destroyReuseSocket(options); + return { + session, + reusedSocket: true, + }; + } + return new Promise((resolve, reject) => { + const entry = { + origin: normalizedOrigin, + options, + reserveStream, + resolve, + reject, + }; + options._cancelSessionSetup = () => { + const index = this.queue.indexOf(entry); + if (index !== -1) { + this.queue.splice(index, 1); + delete options._cancelSessionSetup; + destroyReuseSocket(options); + reject(new Error('HTTP/2 session setup canceled')); + } + }; + this.queue.push(entry); + this.processQueue(); + }); + } + normalizeOptions(origin, options = {}) { + return serializeSessionOptions([ + origin.origin, + ...getTlsSessionOptions(options), + ]); + } + closeEmptySessions(maxCount = Number.POSITIVE_INFINITY) { + let closedCount = 0; + for (const sessions of this.sessions.values()) { + for (const session of sessions) { + if ((session.currentStreamCount ?? 0) === 0) { + closedCount++; + session.close(); + if (closedCount >= maxCount) { + return closedCount; + } + } + } + } + return closedCount; + } + destroy(reason) { + for (const sessions of this.sessions.values()) { + for (const session of sessions) { + session.destroy(reason); + } + } + for (const session of this.pendingSessions) { + session.destroy(reason); + } + this.sessions.clear(); + this.pendingSessionKeys.clear(); + while (this.queue.length > 0) { + const entry = this.queue.shift(); + delete entry.options._cancelSessionSetup; + destroyReuseSocket(entry.options); + entry.reject(reason ?? new Error('Agent has been destroyed')); + } + } + getAvailableSession(key) { + const sessions = this.sessions.get(key); + if (!sessions) { + return; + } + return sessions.find(session => !session.destroyed + && !session.closed + && !session.gracefullyClosing + && (session.currentStreamCount ?? 0) < (session.remoteSettings.maxConcurrentStreams ?? 100)); + } + processQueue() { + let index = 0; + while (index < this.queue.length) { + const entry = this.queue[index]; + const key = this.normalizeOptions(entry.origin, entry.options); + const canUsePooledSession = entry.options._reuseSocket === undefined || entry.options._reuseSocketShouldPool === true; + const session = canUsePooledSession ? this.getAvailableSession(key) : undefined; + if (session) { + this.queue.splice(index, 1); + delete entry.options._cancelSessionSetup; + if (entry.reserveStream) { + this.reserveStream(session); + } + destroyReuseSocket(entry.options); + entry.resolve({ + session, + reusedSocket: true, + }); + continue; + } + if (canUsePooledSession && this.pendingSessionKeys.has(key)) { + index++; + continue; + } + if (this.sessionCount >= this.maxSessions) { + this.closeEmptySessions(this.sessionCount - this.maxSessions + 1); + if (this.sessionCount >= this.maxSessions) { + index++; + continue; + } + } + this.queue.splice(index, 1); + if (canUsePooledSession) { + this.pendingSessionKeys.add(key); + } + this.createSession(entry, key); + } + } + reserveStream(session) { + session.ref(); + if (session.currentStreamCount === 0 && session.emptySessionCounted) { + this.emptySessionCount--; + session.emptySessionCounted = false; + } + session.currentStreamCount = (session.currentStreamCount ?? 0) + 1; + session.reservedStreamCount = (session.reservedStreamCount ?? 0) + 1; + } + releaseStream(session, shouldPoolSession) { + session.currentStreamCount = session.currentStreamCount - 1; + if (session.currentStreamCount === 0) { + if (!shouldPoolSession) { + session.close(); + this.processQueue(); + return; + } + this.emptySessionCount++; + session.emptySessionCounted = true; + session.unref(); + if (this.emptySessionCount > this.maxEmptySessions || session.gracefullyClosing) { + session.close(); + return; + } + } + this.processQueue(); + } + createSession(entry, key) { + this.sessionCount++; + const { path: _path, agent: _agent, h2session: _h2session, _reuseSocketShouldPool, _socketTimeout, timeout: setupTimeout, ...sessionOptions } = entry.options; + const options = { + ...sessionOptions, + settings: entry.options.settings ?? this.settings, + ALPNProtocols: ['h2'], + }; + const reuseSocket = options._reuseSocket; + const shouldPoolSession = reuseSocket === undefined || _reuseSocketShouldPool === true; + if (options._reuseSocket) { + options.createConnection = () => reuseSocket; + delete options._reuseSocket; + } + let session; + try { + session = external_node_http2_.connect(entry.origin, options); + } + catch (error) { + this.sessionCount--; + this.pendingSessionKeys.delete(key); + delete entry.options._cancelSessionSetup; + reuseSocket?.destroy(); + entry.reject(error); + this.processQueue(); + return; + } + this.pendingSessions.add(session); + session.currentStreamCount = 0; + session.reservedStreamCount = 0; + session.emptySessionCounted = false; + session.gracefullyClosing = false; + let settled = false; + let sessionSetupTimeout; + let socketTimeoutApplied = false; + const sessionSocket = session.socket; + const removeSessionSocketListener = sessionSocket.removeListener.bind(sessionSocket); + const clearSessionSetupTimeout = () => { + if (sessionSetupTimeout) { + clearTimeout(sessionSetupTimeout); + sessionSetupTimeout = undefined; + } + }; + const clearSocketTimeout = () => { + removeSessionSocketListener('connect', applySocketTimeout); + if (!socketTimeoutApplied) { + return; + } + socketTimeoutApplied = false; + session.off('timeout', onSocketTimeout); + if (!session.closed && !session.destroyed) { + session.setTimeout(this.timeout); + } + }; + const clearSessionSetup = () => { + clearSessionSetupTimeout(); + clearSocketTimeout(); + this.pendingSessions.delete(session); + this.pendingSessionKeys.delete(key); + delete entry.options._cancelSessionSetup; + }; + const rejectSessionSetup = (error) => { + if (settled) { + return; + } + settled = true; + clearSessionSetup(); + entry.reject(error); + queueMicrotask(() => { + session.destroy(error); + }); + }; + const onSocketTimeout = () => { + rejectSessionSetup(new timed_out_TimeoutError(_socketTimeout, 'socket')); + }; + const applySocketTimeout = () => { + socketTimeoutApplied = true; + session.setTimeout(_socketTimeout, onSocketTimeout); + }; + if (this.timeout > 0) { + session.setTimeout(this.timeout, () => { + session.destroy(); + }); + } + if (_socketTimeout !== undefined) { + if (sessionSocket.connecting) { + sessionSocket.once('connect', applySocketTimeout); + } + else { + applySocketTimeout(); + } + } + if (setupTimeout !== undefined) { + sessionSetupTimeout = setTimeout(() => { + rejectSessionSetup(new timed_out_TimeoutError(Number(setupTimeout), 'request')); + }, Number(setupTimeout)); + sessionSetupTimeout.unref(); + } + const removeSession = () => { + if (session.emptySessionCounted) { + this.emptySessionCount--; + session.emptySessionCounted = false; + } + const sessions = this.sessions.get(key); + if (sessions) { + const index = sessions.indexOf(session); + if (index !== -1) { + sessions.splice(index, 1); + } + if (sessions.length === 0) { + this.sessions.delete(key); + } + } + }; + session.once('remoteSettings', () => { + if (settled) { + return; + } + settled = true; + clearSessionSetup(); + if (shouldPoolSession) { + const sessions = this.sessions.get(key) ?? []; + sessions.push(session); + this.sessions.set(key, sessions); + } + this.emit('session', session); + if (entry.reserveStream) { + this.reserveStream(session); + } + entry.resolve({ + session, + reusedSocket: false, + }); + this.processQueue(); + }); + session.once('error', error => { + clearSessionSetup(); + if (!settled) { + settled = true; + entry.reject(error); + } + removeSession(); + }); + session.once('goaway', () => { + session.gracefullyClosing = true; + if (session.currentStreamCount === 0) { + session.close(); + } + }); + session.once('close', () => { + clearSessionSetup(); + this.sessionCount--; + if (!settled) { + settled = true; + entry.reject(new Error('The HTTP/2 session closed before settings were received')); + } + removeSession(); + this.processQueue(); + }); + entry.options._cancelSessionSetup = () => { + if (settled) { + return; + } + settled = true; + clearSessionSetup(); + entry.reject(new Error('HTTP/2 session setup canceled')); + session.destroy(); + }; + const request = session.request.bind(session); + session.request = (headers, streamOptions) => { + const hasReservedStream = (session.reservedStreamCount ?? 0) > 0; + if (hasReservedStream) { + session.reservedStreamCount = session.reservedStreamCount - 1; + } + if (session.gracefullyClosing) { + if (hasReservedStream) { + this.releaseStream(session, shouldPoolSession); + } + throw new Error('The session is gracefully closing. No new streams are allowed.'); + } + if (!hasReservedStream) { + this.reserveStream(session); + } + let stream; + try { + stream = request(headers, streamOptions); + } + catch (error) { + this.releaseStream(session, shouldPoolSession); + throw error; + } + stream.once('close', () => { + this.releaseStream(session, shouldPoolSession); + }); + return stream; + }; + } +} +class Http2ClientRequest extends external_node_stream_.Writable { + constructor(input, options, callback) { + super({ + autoDestroy: false, + emitClose: false, + }); + const normalized = normalizeInput(input, options, callback); + this.options = normalized.options; + this.callback = normalized.callback; + this.method = (this.options.method ?? 'GET').toUpperCase(); + this.path = this.method === HTTP2_METHOD_CONNECT ? String(this.options.path ?? '') : String(this.options.path ?? '/'); + this.protocol = String(this.options.protocol ?? 'https:'); + this.headers = Object.create(null); + if (this.protocol !== 'https:' && !this.options.h2session) { + throw new Error(`Protocol "${this.protocol}" not supported. Expected "https:"`); + } + const headers = this.options.headers; + if (headers) { + for (const [key, value] of Object.entries(headers)) { + this.setHeader(key, value); + } + } + if (this.options.auth && !this.hasHeader('authorization')) { + this.setHeader('authorization', `Basic ${external_node_buffer_.Buffer.from(this.options.auth).toString('base64')}`); + } + if (this.callback) { + this.once('response', this.callback); + } + const authority = getAuthority(this.options); + this.origin = authority; + if (!this.hasHeader(HTTP2_HEADER_AUTHORITY)) { + this.headers[HTTP2_HEADER_AUTHORITY] = this.method === HTTP2_METHOD_CONNECT ? this.path : authority.host; + } + this.headers[HTTP2_HEADER_METHOD] = this.method; + if (this.method !== HTTP2_METHOD_CONNECT) { + this.headers[HTTP2_HEADER_SCHEME] = this.protocol.slice(0, -1); + this.headers[HTTP2_HEADER_PATH] = this.path; + } + } + agent; + aborted = false; + reusedSocket = false; + res; + socket; + connection; + method; + path; + protocol; + host; + headersSent = false; + maxHeadersCount; + options; + callback; + headers; + origin; + stream; + pendingJobs = []; + pendingAgentPromise; + connectionHeaderNames = new Set(); + trailers; + get isGotHttp2Request() { + return true; + } + _write(chunk, encoding, callback) { + const write = () => { + this.stream.write(chunk, encoding, callback); + }; + if (this.stream) { + write(); + } + else { + this.pendingJobs.push({ + run: write, + cancel: callback, + }); + } + void this.flushHeaders(); + } + _final(callback) { + const end = () => { + if (this.trailers) { + this.stream.once('wantTrailers', () => { + this.stream.sendTrailers(this.trailers); + }); + } + this.stream.end(callback); + }; + if (this.stream) { + end(); + } + else { + this.pendingJobs.push({ + run: end, + cancel: callback, + }); + } + void this.flushHeaders(); + } + _destroy(error, callback) { + if (this.res && typeof this.res._dump === 'function') { + this.res._dump(); + } + if (this.stream) { + this.stream.close(NGHTTP2_CANCEL); + } + else { + this.options._cancelSessionSetup?.(); + if (error === null) { + queueMicrotask(() => { + this.emit('close'); + }); + } + } + if (this.pendingAgentPromise) { + void this.pendingAgentPromise.catch(() => { }); + } + if (!this.stream) { + this.cancelPendingJobs(error ?? new Error('The HTTP/2 request was destroyed before a stream was created')); + } + callback(error); + } + abort() { + if (this.res?.complete) { + return; + } + if (!this.aborted) { + queueMicrotask(() => { + this.emit('abort'); + }); + } + this.aborted = true; + this.destroy(); + } + async flushHeaders() { + if (this.headersSent || this.destroyed) { + return; + } + this.headersSent = true; + try { + if (this.options.h2session) { + this.reusedSocket = true; + this.onStream(this.options.h2session.request(this.headers, { + endStream: false, + waitForTrailers: this.trailers !== undefined, + })); + return; + } + this.agent = this.options.agent === false ? new Http2Agent({ maxEmptySessions: 0 }) : this.options.agent ?? globalAgent; + const streamPromise = this.agent.request(this.origin, this.options, this.headers, { + endStream: false, + waitForTrailers: this.trailers !== undefined, + }); + this.pendingAgentPromise = streamPromise; + const { stream, reusedSocket } = await streamPromise; + this.reusedSocket = reusedSocket; + this.onStream(stream); + this.pendingAgentPromise = undefined; + } + catch (error) { + this.pendingAgentPromise = undefined; + this.destroy(error); + } + } + addTrailers(headers) { + if (this.headersSent) { + throw new Error('Cannot add trailers after the HTTP/2 stream has been created'); + } + const trailers = Object.create(null); + const connectionHeaderNames = new Set(); + for (const [name, value] of Object.entries(headers)) { + (0,external_node_http_.validateHeaderName)(name); + (0,external_node_http_.validateHeaderValue)(name, value); + const lowercasedName = name.toLowerCase(); + if (lowercasedName === 'connection' || lowercasedName === 'proxy-connection') { + for (const token of getConnectionHeaderTokens(value)) { + connectionHeaderNames.add(token); + Reflect.deleteProperty(trailers, token); + } + continue; + } + if (connectionSpecificHeaders.has(lowercasedName)) { + continue; + } + if (connectionHeaderNames.has(lowercasedName)) { + continue; + } + if (lowercasedName === 'te' && !isTrailersTeHeader(value)) { + continue; + } + trailers[lowercasedName] = value; + } + this.trailers = trailers; + } + setHeader(name, value) { + if (this.headersSent) { + throw new Error('Cannot set headers after they are sent to the client'); + } + (0,external_node_http_.validateHeaderName)(name); + (0,external_node_http_.validateHeaderValue)(name, value); + const lowercasedName = name.toLowerCase(); + if (lowercasedName === 'connection' || lowercasedName === 'proxy-connection') { + for (const token of getConnectionHeaderTokens(value)) { + this.connectionHeaderNames.add(token); + Reflect.deleteProperty(this.headers, normalizeRequestHeaderName(token)); + } + return this; + } + if (connectionSpecificHeaders.has(lowercasedName)) { + return this; + } + if (this.connectionHeaderNames.has(lowercasedName)) { + return this; + } + if (lowercasedName === 'te' && !isTrailersTeHeader(value)) { + return this; + } + this.headers[normalizeRequestHeaderName(name)] = value; + return this; + } + getHeader(name) { + return this.headers[normalizeRequestHeaderName(name)]; + } + getHeaders() { + return { ...this.headers }; + } + getHeaderNames() { + return Object.keys(this.headers); + } + hasHeader(name) { + return this.getHeader(name) !== undefined; + } + removeHeader(name) { + if (this.headersSent) { + throw new Error('Cannot remove headers after they are sent to the client'); + } + Reflect.deleteProperty(this.headers, normalizeRequestHeaderName(name)); + } + setNoDelay() { } + setSocketKeepAlive() { } + setTimeout(ms, callback) { + const applyTimeout = () => { + this.stream.setTimeout(ms, callback); + }; + if (this.stream) { + applyTimeout(); + } + else { + this.pendingJobs.push({ run: applyTimeout }); + } + return this; + } + cancelPendingJobs(error) { + const jobs = this.pendingJobs; + this.pendingJobs = []; + for (const job of jobs) { + job.cancel?.(error); + } + } + onStream(stream) { + this.stream = stream; + this.socket = createSocketProxy(stream); + this.connection = this.socket; + if (this.destroyed) { + stream.destroy(); + return; + } + stream.once('error', error => { + if (this.destroyed) { + return; + } + this.destroy(error); + }); + stream.once('aborted', () => { + if (this.res) { + this.res.aborted = true; + this.res.emit('aborted'); + this.res.destroy(); + } + else { + this.destroy(new Error('The server aborted the HTTP/2 stream')); + } + }); + stream.once('response', (headers, _flags, rawHeaders) => { + const response = new Http2IncomingMessage(stream, this, stream.readableHighWaterMark); + const incomingResponse = response; + response.statusCode = Number(headers[HTTP2_HEADER_STATUS]); + response.headers = filterHeaders(headers); + response.rawHeaders = rawHeaders ? filterRawHeaders(rawHeaders) : toRawHeaders(headers); + response.url = `${this.origin.origin}${this.path}`; + incomingResponse.req = this; + this.res = incomingResponse; + stream.on('data', chunk => { + if (!response.push(chunk)) { + stream.pause(); + } + }); + stream.once('end', () => { + if (!this.aborted) { + response.complete = true; + response.push(null); + } + }); + if (!this.emit('response', incomingResponse)) { + response._dump(); + } + }); + stream.on('headers', (headers, _flags, rawHeaders) => { + this.emit('information', { + statusCode: Number(headers[HTTP2_HEADER_STATUS]), + statusMessage: '', + httpVersion: '2.0', + httpVersionMajor: 2, + httpVersionMinor: 0, + headers: filterHeaders(headers), + rawHeaders: rawHeaders ? filterRawHeaders(rawHeaders) : toRawHeaders(headers), + }); + }); + stream.once('trailers', (trailers, _flags, rawTrailers) => { + if (!this.res) { + return; + } + this.res.trailers = trailers; + this.res.rawTrailers = Array.isArray(rawTrailers) ? rawTrailers : toRawHeaders(trailers); + }); + stream.once('close', () => { + if (this.res) { + if (this.aborted) { + this.res.aborted = true; + this.res.emit('aborted'); + this.res.destroy(); + } + const finish = () => { + this.res.emit('close'); + this.destroy(); + this.emit('close'); + }; + if (this.res.readable) { + this.res.once('end', finish); + } + else { + finish(); + } + return; + } + if (!this.destroyed) { + this.destroy(new Error('The HTTP/2 stream has been early terminated')); + queueMicrotask(() => { + this.emit('close'); + }); + return; + } + this.destroy(); + this.emit('close'); + }); + for (const job of this.pendingJobs) { + job.run(); + } + this.pendingJobs = []; + this.emit('socket', this.socket); + } +} +const globalAgent = new Http2Agent(); +const request = (input, options, callback) => new Http2ClientRequest(input, options, callback); +const getSourceOptions = (input, options) => { + if (typeof input === 'object' && !(input instanceof URL)) { + return input; + } + return typeof options === 'object' ? options : {}; +}; +const requestHttp1 = (options, agent, callback) => { + if (typeof agent === 'object' && 'https' in agent) { + options.agent = agent.https; + } + options.ALPNProtocols = ['http/1.1']; + delete options.timeout; + delete options._socketTimeout; + if (options.headers) { + const headers = { ...options.headers }; + Reflect.deleteProperty(headers, HTTP2_HEADER_METHOD); + Reflect.deleteProperty(headers, HTTP2_HEADER_SCHEME); + Reflect.deleteProperty(headers, HTTP2_HEADER_PATH); + if (headers[HTTP2_HEADER_AUTHORITY] && !headers.host) { + headers.host = headers[HTTP2_HEADER_AUTHORITY]; + } + Reflect.deleteProperty(headers, HTTP2_HEADER_AUTHORITY); + options.headers = headers; + } + return external_node_https_.request(options, callback); +}; +const requestWithCustomHttpsAgent = (options, agent, callback) => { + options.agent = agent.https; + options.ALPNProtocols = ['http/1.1']; + delete options.timeout; + delete options._socketTimeout; + return external_node_https_.request(options, callback); +}; +const requestHttp2 = (options, agent, socket, callback) => { + options.agent = typeof agent === 'object' && 'http2' in agent ? agent.http2 : agent; + if (socket) { + options._reuseSocket = socket; + options._reuseSocketShouldPool = options.createConnection === undefined; + } + return request(options, callback); +}; +const auto = async (input, options, callback) => { + const sourceOptions = getSourceOptions(input, options); + const normalized = normalizeInput(input, options, callback); + options = normalized.options; + callback = normalized.callback; + options.ALPNProtocols ??= ['h2', 'http/1.1']; + options.protocol ??= 'https:'; + if (options.h2session) { + return request(options, callback); + } + const isHttps = options.protocol === 'https:'; + if (!isHttps) { + options.agent = options.agent?.http; + return external_node_http_.request(options, callback); + } + const agent = options.agent; + if (hasCustomHttpsAgent(agent) && options.createConnection === undefined) { + return requestWithCustomHttpsAgent(options, agent, callback); + } + const { alpnProtocol, socket } = await resolveProtocol(options, sourceOptions); + if (alpnProtocol === 'h2') { + return requestHttp2(options, agent, socket, callback); + } + socket?.destroy(); + return requestHttp1(options, agent, callback); +}; +const http2Client = { + Agent: Http2Agent, + auto, + globalAgent, + request, +}; +/* harmony default export */ const http2_client = (http2Client); + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/options.js + + +// DO NOT use destructuring for `https.request` and `http.request` as it's not compatible with `nock`. + + + + + + + + + +const isAgentObject = (agent) => distribution.object(agent) && ('http' in agent || 'https' in agent || 'http2' in agent); +const getNativeAgent = (url, agent) => { + if (!isAgentObject(agent)) { + return agent; + } + return url.protocol === 'https:' ? agent.https : agent.http; +}; +const resolveWithRequestTimeout = async (promise, timeout, onLateResolution) => { + let timeoutId; + let didTimeOut = false; + const timeoutPromise = new Promise((_resolve, reject) => { + timeoutId = setTimeout(() => { + didTimeOut = true; + reject(new timed_out_TimeoutError(timeout, 'request')); + }, timeout); + timeoutId.unref(); + }); + void (async () => { + try { + const value = await promise; + if (didTimeOut) { + onLateResolution?.(value); + } + } + catch { } + })(); + try { + return await Promise.race([promise, timeoutPromise]); + } + finally { + if (timeoutId) { + clearTimeout(timeoutId); + } + } +}; +/** +Generic helper that wraps any assertion function to add context to error messages. +*/ +function wrapAssertionWithContext(optionName, assertionFn) { + try { + assertionFn(); + } + catch (error) { + if (error instanceof Error) { + error.message = `Option '${optionName}': ${error.message}`; + } + throw error; + } +} +/** +Helper function that wraps assert.any() to provide better error messages. +When assertion fails, it includes the option name in the error message. +*/ +function options_assertAny(optionName, validators, value) { + wrapAssertionWithContext(optionName, () => { + assert.any(validators, value); + }); +} +/** +Helper function that wraps assert.plainObject() to provide better error messages. +When assertion fails, it includes the option name in the error message. +*/ +function options_assertPlainObject(optionName, value) { + wrapAssertionWithContext(optionName, () => { + assert.plainObject(value); + }); +} +function isSameOrigin(previousUrl, nextUrl) { + return previousUrl.origin === nextUrl.origin + && getUnixSocketPath(previousUrl) === getUnixSocketPath(nextUrl); +} +const crossOriginStripHeaders = ['host', 'cookie', 'cookie2', 'authorization', 'proxy-authorization']; +const bodyHeaderNames = ['content-length', 'content-encoding', 'content-language', 'content-location', 'content-type', 'transfer-encoding']; +function usesUnixSocket(url) { + return url.protocol === 'unix:' || getUnixSocketPath(url) !== undefined; +} +function hasCredentialInUrl(url, credential) { + if (url instanceof URL) { + return url[credential] !== ''; + } + if (!distribution.string(url)) { + return false; + } + try { + return new URL(url)[credential] !== ''; + } + catch { + return false; + } +} +const hasExplicitCredentialInUrlChange = (changedState, url, credential) => (changedState.has(credential) + || ((changedState.has('url') || changedState.has('prefixUrl')) && url?.[credential] !== '')); +const hasProtocolSlashes = (value) => /^[a-z][\d+\-.a-z]*:\/\//iv.test(value); +const hasHttpProtocolWithoutSlashes = (value) => /^https?:(?!\/\/)/iv.test(value); +const hasUnixProtocolWithoutSlashes = (value) => /^unix:/iv.test(value); +const isAbsoluteUrl = (url) => distribution.urlInstance(url) || (distribution.string(url) && (hasProtocolSlashes(url) || url.startsWith('//'))); +const isSlashOrBackslash = (character) => character === '/' || character === '\\'; +const startsWithSchemeRelativeSeparators = (value) => value.length > 1 && isSlashOrBackslash(value[0]) && isSlashOrBackslash(value[1]); +const stripLeadingC0ControlOrSpace = (value) => { + let index = 0; + while (index < value.length && value.codePointAt(index) <= 0x20) { + index++; + } + return value.slice(index); +}; +const removeAsciiTabOrNewline = (value) => { + let result = ''; + for (const character of value) { + const codePoint = character.codePointAt(0); + if (codePoint !== 0x09 && codePoint !== 0x0A && codePoint !== 0x0D) { + result += character; + } + } + return result; +}; +const assertRelativeUrlIfNeeded = (options, url) => { + if (!options.prefixUrl || options.allowAbsoluteUrls) { + return; + } + const normalizedUrl = distribution.string(url) ? stripLeadingC0ControlOrSpace(removeAsciiTabOrNewline(url)) : url; + const isDisallowed = isAbsoluteUrl(normalizedUrl) + || (distribution.string(normalizedUrl) && (hasHttpProtocolWithoutSlashes(normalizedUrl) + || startsWithSchemeRelativeSeparators(normalizedUrl) + || (options.enableUnixSockets && hasUnixProtocolWithoutSlashes(normalizedUrl)))); + if (isDisallowed) { + throw new Error('The `url` option must be relative when `allowAbsoluteUrls` is false and `prefixUrl` is set'); + } +}; +const assertUrlHasSameOriginAsPrefixUrlIfNeeded = (options, url) => { + if (!options.prefixUrl || options.allowAbsoluteUrls) { + return; + } + let prefixUrl; + try { + prefixUrl = new URL(options.prefixUrl); + } + catch { + return; + } + if (isSameOrigin(prefixUrl, url)) { + return; + } + throw new Error('The `url` option must stay on the same origin as `prefixUrl` when `allowAbsoluteUrls` is false'); +}; +const getUrlPrefixBoundary = (options) => ({ + url: options.url instanceof URL ? new URL(options.url) : undefined, + prefixUrl: options.prefixUrl.toString(), + allowAbsoluteUrls: options.allowAbsoluteUrls, +}); +const hasUrlOrPrefixUrlBoundaryChanged = (options, currentUrl, previous) => (currentUrl.href !== previous.url?.href + || options.prefixUrl.toString() !== previous.prefixUrl + || options.allowAbsoluteUrls !== previous.allowAbsoluteUrls); +function applyUrlOverride(options, url, { username, password, baseUrl } = {}) { + assertRelativeUrlIfNeeded(options, url); + if (distribution.string(url) && options.url) { + const resolvedUrl = new URL(url, baseUrl ?? options.url); + url = resolvedUrl.toString(); + } + if (options.allowAbsoluteUrls) { + options.prefixUrl = ''; + options.url = url; + } + else { + const { allowAbsoluteUrls } = options; + try { + options.allowAbsoluteUrls = true; + options.url = url; + } + finally { + options.allowAbsoluteUrls = allowAbsoluteUrls; + } + } + if (username !== undefined) { + options.username = username; + } + if (password !== undefined) { + options.password = password; + } + return options.url; +} +function assertValidHeaderName(name) { + if (name.startsWith(':')) { + throw new TypeError(`HTTP/2 pseudo-headers are not supported in \`options.headers\`: ${name}`); + } +} +/** +Safely assign own properties from source to target, skipping `__proto__` to prevent prototype pollution from JSON.parse'd input. +*/ +function safeObjectAssign(target, source) { + for (const [key, value] of Object.entries(source)) { + if (key === '__proto__') { + continue; + } + Reflect.set(target, key, value); + } +} +const isToughCookieJar = (cookieJar) => cookieJar.setCookie.length === 4 && cookieJar.getCookieString.length === 0; +const destroyLateRequestResult = (result) => { + if (result && 'destroy' in result && distribution.function(result.destroy)) { + if ('once' in result && distribution.function(result.once)) { + result.once('error', () => { }); + } + result.destroy(); + } +}; +function validateSearchParameters(searchParameters) { + for (const key of Object.keys(searchParameters)) { + if (key === '__proto__') { + continue; + } + const value = searchParameters[key]; + options_assertAny(`searchParams.${key}`, [distribution.string, distribution.number, distribution.boolean, distribution.null, distribution.undefined], value); + } +} +const globalCache = new Map(); +let globalDnsCache; +const getGlobalDnsCache = () => { + if (globalDnsCache) { + return globalDnsCache; + } + globalDnsCache = new DnsCache(); + return globalDnsCache; +}; +// Detects and wraps QuickLRU v7+ instances to make them compatible with the StorageAdapter interface +const wrapQuickLruIfNeeded = (value) => { + // Check if this is QuickLRU v7+ using Symbol.toStringTag and the evict method (added in v7) + if (value?.[Symbol.toStringTag] === 'QuickLRU' && typeof value.evict === 'function') { + // QuickLRU v7+ uses set(key, value, {maxAge: number}) but StorageAdapter expects set(key, value, ttl) + // Wrap it to translate the interface + return { + get(key) { + return value.get(key); + }, + set(key, cacheValue, ttl) { + if (ttl === undefined) { + value.set(key, cacheValue); + } + else { + value.set(key, cacheValue, { maxAge: ttl }); + } + return true; + }, + delete(key) { + return value.delete(key); + }, + clear() { + return value.clear(); + }, + has(key) { + return value.has(key); + }, + }; + } + // QuickLRU v5 and other caches work as-is + return value; +}; +const defaultInternals = { + request: undefined, + agent: { + http: undefined, + https: undefined, + http2: undefined, + }, + h2session: undefined, + decompress: true, + timeout: { + connect: undefined, + lookup: undefined, + read: undefined, + request: undefined, + response: undefined, + secureConnect: undefined, + send: undefined, + socket: undefined, + }, + prefixUrl: '', + body: undefined, + form: undefined, + json: undefined, + cookieJar: undefined, + ignoreInvalidCookies: false, + searchParams: undefined, + dnsLookup: undefined, + dnsCache: undefined, + context: {}, + hooks: { + init: [], + beforeRequest: [], + beforeError: [], + beforeRedirect: [], + beforeRetry: [], + beforeCache: [], + afterResponse: [], + }, + followRedirect: true, + maxRedirects: 10, + cache: undefined, + throwHttpErrors: true, + username: '', + password: '', + http2: false, + allowGetBody: false, + allowAbsoluteUrls: true, + copyPipedHeaders: false, + headers: { + 'user-agent': 'got (https://github.com/sindresorhus/got)', + }, + methodRewriting: false, + dnsLookupIpVersion: undefined, + parseJson: JSON.parse, + stringifyJson: JSON.stringify, + retry: { + limit: 2, + methods: [ + 'GET', + 'PUT', + 'HEAD', + 'DELETE', + 'OPTIONS', + 'TRACE', + 'QUERY', + ], + statusCodes: [ + 408, + 413, + 429, + 500, + 502, + 503, + 504, + 521, + 522, + 524, + ], + errorCodes: [ + 'ETIMEDOUT', + 'ECONNRESET', + 'EADDRINUSE', + 'ECONNREFUSED', + 'EPIPE', + 'ENOTFOUND', + 'ENETUNREACH', + 'EAI_AGAIN', + ], + maxRetryAfter: undefined, + calculateDelay: ({ computedValue }) => computedValue, + backoffLimit: Number.POSITIVE_INFINITY, + noise: 100, + enforceRetryRules: true, + }, + localAddress: undefined, + method: 'GET', + createConnection: undefined, + cacheOptions: { + shared: undefined, + cacheHeuristic: undefined, + immutableMinTimeToLive: undefined, + ignoreCargoCult: undefined, + }, + https: { + alpnProtocols: undefined, + rejectUnauthorized: undefined, + checkServerIdentity: undefined, + serverName: undefined, + certificateAuthority: undefined, + key: undefined, + certificate: undefined, + passphrase: undefined, + pfx: undefined, + ciphers: undefined, + honorCipherOrder: undefined, + minVersion: undefined, + maxVersion: undefined, + signatureAlgorithms: undefined, + tlsSessionLifetime: undefined, + dhparam: undefined, + ecdhCurve: undefined, + certificateRevocationLists: undefined, + secureOptions: undefined, + }, + encoding: undefined, + resolveBodyOnly: false, + isStream: false, + responseType: 'text', + url: undefined, + pagination: { + transform(response) { + if (response.request.options.responseType === 'json') { + return response.body; + } + return JSON.parse(response.body); + }, + paginate({ response }) { + const rawLinkHeader = response.headers.link; + if (typeof rawLinkHeader !== 'string' || rawLinkHeader.trim() === '') { + return false; + } + const parsed = parseLinkHeader(rawLinkHeader); + const next = parsed.find(entry => entry.parameters.rel === 'next' || entry.parameters.rel === '"next"'); + if (next) { + return { + url: next.reference, + }; + } + return false; + }, + filter: () => true, + shouldContinue: () => true, + countLimit: Number.POSITIVE_INFINITY, + backoff: 0, + requestLimit: 10_000, + stackAllItems: false, + }, + setHost: true, + maxHeaderSize: undefined, + signal: undefined, + enableUnixSockets: false, + strictContentLength: true, +}; +const cloneInternals = (internals) => { + const { hooks, retry } = internals; + const result = { + ...internals, + context: { ...internals.context }, + cacheOptions: { ...internals.cacheOptions }, + https: { ...internals.https }, + agent: { ...internals.agent }, + headers: { ...internals.headers }, + retry: { + ...retry, + errorCodes: [...retry.errorCodes], + methods: [...retry.methods], + statusCodes: [...retry.statusCodes], + }, + timeout: { ...internals.timeout }, + hooks: { + init: [...hooks.init], + beforeRequest: [...hooks.beforeRequest], + beforeError: [...hooks.beforeError], + beforeRedirect: [...hooks.beforeRedirect], + beforeRetry: [...hooks.beforeRetry], + beforeCache: [...hooks.beforeCache], + afterResponse: [...hooks.afterResponse], + }, + searchParams: internals.searchParams ? new URLSearchParams(internals.searchParams) : undefined, + pagination: { ...internals.pagination }, + }; + return result; +}; +const cloneRaw = (raw) => { + const result = { ...raw }; + if (Object.hasOwn(raw, 'context') && distribution.object(raw.context)) { + result.context = { ...raw.context }; + } + if (Object.hasOwn(raw, 'cacheOptions') && distribution.object(raw.cacheOptions)) { + result.cacheOptions = { ...raw.cacheOptions }; + } + if (Object.hasOwn(raw, 'https') && distribution.object(raw.https)) { + result.https = { ...raw.https }; + } + if (Object.hasOwn(raw, 'agent') && distribution.object(raw.agent)) { + result.agent = { ...raw.agent }; + } + if (Object.hasOwn(raw, 'headers') && distribution.object(raw.headers)) { + result.headers = { ...raw.headers }; + } + if (Object.hasOwn(raw, 'retry') && distribution.object(raw.retry)) { + const { retry } = raw; + result.retry = { ...retry }; + if (distribution.array(retry.errorCodes)) { + result.retry.errorCodes = [...retry.errorCodes]; + } + if (distribution.array(retry.methods)) { + result.retry.methods = [...retry.methods]; + } + if (distribution.array(retry.statusCodes)) { + result.retry.statusCodes = [...retry.statusCodes]; + } + } + if (Object.hasOwn(raw, 'timeout') && distribution.object(raw.timeout)) { + result.timeout = { ...raw.timeout }; + } + if (Object.hasOwn(raw, 'hooks') && distribution.object(raw.hooks)) { + const { hooks } = raw; + result.hooks = { + ...hooks, + }; + if (distribution.array(hooks.init)) { + result.hooks.init = [...hooks.init]; + } + if (distribution.array(hooks.beforeRequest)) { + result.hooks.beforeRequest = [...hooks.beforeRequest]; + } + if (distribution.array(hooks.beforeError)) { + result.hooks.beforeError = [...hooks.beforeError]; + } + if (distribution.array(hooks.beforeRedirect)) { + result.hooks.beforeRedirect = [...hooks.beforeRedirect]; + } + if (distribution.array(hooks.beforeRetry)) { + result.hooks.beforeRetry = [...hooks.beforeRetry]; + } + if (distribution.array(hooks.beforeCache)) { + result.hooks.beforeCache = [...hooks.beforeCache]; + } + if (distribution.array(hooks.afterResponse)) { + result.hooks.afterResponse = [...hooks.afterResponse]; + } + } + if (Object.hasOwn(raw, 'searchParams') && raw.searchParams) { + if (distribution.string(raw.searchParams)) { + result.searchParams = raw.searchParams; + } + else if (raw.searchParams instanceof URLSearchParams) { + result.searchParams = new URLSearchParams(raw.searchParams); + } + else if (distribution.object(raw.searchParams)) { + result.searchParams = { ...raw.searchParams }; + } + } + if (Object.hasOwn(raw, 'pagination') && distribution.object(raw.pagination)) { + result.pagination = { ...raw.pagination }; + } + return result; +}; +const getHttp2TimeoutOption = (internals) => { + const delays = [ + internals.timeout.connect, + internals.timeout.lookup, + internals.timeout.request, + internals.timeout.secureConnect, + ].filter(delay => typeof delay === 'number'); + return delays.length > 0 ? Math.min(...delays) : undefined; +}; +const usesHttp2Alpn = (internals, url) => { + const usesCustomHttpsAgent = internals.agent.https !== undefined + && internals.agent.https !== false + && internals.createConnection === undefined; + return internals.http2 + && url.protocol === 'https:' + && !internals.h2session + && !usesCustomHttpsAgent; +}; +const trackStateMutation = (trackedStateMutations, name) => { + trackedStateMutations?.add(name); +}; +const addExplicitHeader = (explicitHeaders, name) => { + explicitHeaders.add(name); +}; +const markHeaderAsExplicit = (explicitHeaders, trackedStateMutations, name) => { + addExplicitHeader(explicitHeaders, name); + trackStateMutation(trackedStateMutations, name); +}; +const trackReplacedHeaderMutations = (trackedStateMutations, previousHeaders, nextHeaders) => { + if (!trackedStateMutations) { + return; + } + for (const header of new Set([...Object.keys(previousHeaders), ...Object.keys(nextHeaders)])) { + if (previousHeaders[header] !== nextHeaders[header]) { + trackStateMutation(trackedStateMutations, header); + } + } +}; +const init = (options, withOptions, self) => { + const initHooks = options.hooks?.init; + if (initHooks) { + for (const hook of initHooks) { + hook(withOptions, self); + } + } +}; +// Keys never merged: got.extend() internals, url (passed as first arg), control flags, security +const nonMergeableKeys = new Set(['mutableDefaults', 'handlers', 'url', 'preserveHooks', 'isStream', '__proto__']); +class Options { + #internals; + #headersProxy; + #merging = false; + #init; + #explicitHeaders; + #trackedStateMutations; + constructor(input, options, defaults) { + options_assertAny('input', [distribution.string, distribution.urlInstance, distribution.object, distribution.undefined], input); + options_assertAny('options', [distribution.object, distribution.undefined], options); + options_assertAny('defaults', [distribution.object, distribution.undefined], defaults); + if (input instanceof Options || options instanceof Options) { + throw new TypeError('The defaults must be passed as the third argument'); + } + if (defaults) { + this.#internals = cloneInternals(defaults.#internals); + this.#init = [...defaults.#init]; + this.#explicitHeaders = new Set(defaults.#explicitHeaders); + } + else { + this.#internals = cloneInternals(defaultInternals); + this.#init = []; + this.#explicitHeaders = new Set(); + } + this.#headersProxy = this.#createHeadersProxy(); + // This rule allows `finally` to be considered more important. + // Meaning no matter the error thrown in the `try` block, + // if `finally` throws then the `finally` error will be thrown. + // + // Yes, we want this. If we set `url` first, then the `url.searchParams` + // would get merged. Instead we set the `searchParams` first, then + // `url.searchParams` is overwritten as expected. + // + /* eslint-disable no-unsafe-finally -- `finally` is used intentionally here to ensure `url` is always set last, overwriting any merged searchParams */ + try { + if (distribution.plainObject(input)) { + try { + this.merge(input); + this.merge(options); + } + finally { + this.url = input.url; + } + } + else { + try { + this.merge(options); + } + finally { + if (options?.url !== undefined) { + if (input === undefined) { + this.url = options.url; + } + else { + throw new TypeError('The `url` option is mutually exclusive with the `input` argument'); + } + } + else if (input !== undefined) { + this.url = input; + } + } + } + } + catch (error) { + error.options = this; + throw error; + } + /* eslint-enable no-unsafe-finally */ + } + merge(options) { + if (!options) { + return; + } + if (options instanceof Options) { + // Create a copy of the #init array to avoid infinite loop + // when merging an Options instance with itself + const initArray = [...options.#init]; + for (const init of initArray) { + this.merge(init); + } + return; + } + options = cloneRaw(options); + init(this, options, this); + init(options, options, this); + this.#merging = true; + try { + let push = false; + for (const key of Object.keys(options)) { + if (nonMergeableKeys.has(key)) { + continue; + } + if (!(key in this)) { + throw new Error(`Unexpected option: ${key}`); + } + // @ts-expect-error Type 'unknown' is not assignable to type 'never'. + const value = options[key]; + if (value === undefined) { + continue; + } + // @ts-expect-error Type 'unknown' is not assignable to type 'never'. + this[key] = value; + push = true; + } + if (push) { + this.#init.push(options); + } + } + finally { + this.#merging = false; + } + } + /** + Custom request function. + + @default Got's built-in HTTP/1.1 or HTTP/2 request implementation + */ + get request() { + return this.#internals.request; + } + set request(value) { + options_assertAny('request', [distribution.function, distribution.undefined], value); + this.#internals.request = value; + } + /** + An object representing `http`, `https` and `http2` keys for [`http.Agent`](https://nodejs.org/api/http.html#http_class_http_agent), [`https.Agent`](https://nodejs.org/api/https.html#https_class_https_agent), and Got's internal HTTP/2 session pool. + This is necessary because a request to one protocol might redirect to another. + In such a scenario, Got will switch over to the right protocol agent for you. + When `http2` is enabled, a custom `agent.https` instance makes Got use the native HTTP/1.1 request path because Got's built-in HTTP/2 session pool does not support custom HTTPS agents. + + If a key is not present, it will default to a global agent. + + @example + ``` + import got from 'got'; + import HttpAgent from 'agentkeepalive'; + + const {HttpsAgent} = HttpAgent; + + await got('https://sindresorhus.com', { + agent: { + http: new HttpAgent(), + https: new HttpsAgent() + } + }); + ``` + */ + get agent() { + return this.#internals.agent; + } + set agent(value) { + options_assertPlainObject('agent', value); + for (const key of Object.keys(value)) { + if (key === '__proto__') { + continue; + } + if (!(key in this.#internals.agent)) { + throw new TypeError(`Unexpected agent option: ${key}`); + } + const validators = key === 'http2' + ? [distribution.undefined, (v) => v === false] + : [distribution.object, distribution.undefined, (v) => v === false]; + options_assertAny(`agent.${key}`, validators, value[key]); + } + if (this.#merging) { + safeObjectAssign(this.#internals.agent, value); + } + else { + this.#internals.agent = { ...value }; + } + } + get h2session() { + return this.#internals.h2session; + } + set h2session(value) { + this.#internals.h2session = value; + } + /** + Decompress the response automatically. + + This will set the `accept-encoding` header to `gzip, deflate, br` unless you set it yourself. + + If this is disabled, a compressed response is returned as a `Uint8Array`. + This may be useful if you want to handle decompression yourself or stream the raw compressed data. + + @default true + */ + get decompress() { + return this.#internals.decompress; + } + set decompress(value) { + assert.boolean(value); + this.#internals.decompress = value; + } + /** + Milliseconds to wait for the server to end the response before aborting the request with `got.TimeoutError` error (a.k.a. `request` property). + By default, there's no timeout. + + This also accepts an `object` with the following fields to constrain the duration of each phase of the request lifecycle: + + - `lookup` starts when a socket is assigned and ends when the hostname has been resolved. + Does not apply when using a Unix domain socket. + - `connect` starts when `lookup` completes (or when the socket is assigned if lookup does not apply to the request) and ends when the socket is connected. + - `secureConnect` starts when `connect` completes and ends when the handshaking process completes (HTTPS only). + - `socket` starts when the socket is connected. See [request.setTimeout](https://nodejs.org/api/http.html#http_request_settimeout_timeout_callback). + - `response` starts when the request has been written to the socket and ends when the response headers are received. + - `send` starts when the socket is connected and ends with the request has been written to the socket. + - `request` starts when the request is initiated and ends when the response's end event fires. + */ + get timeout() { + // We always return `Delays` here. + // It has to be `Delays | number`, otherwise TypeScript will error because the getter and the setter have incompatible types. + return this.#internals.timeout; + } + set timeout(value) { + options_assertPlainObject('timeout', value); + for (const key of Object.keys(value)) { + if (key === '__proto__') { + continue; + } + if (!(key in this.#internals.timeout)) { + throw new Error(`Unexpected timeout option: ${key}`); + } + options_assertAny(`timeout.${key}`, [distribution.number, distribution.undefined], value[key]); + } + if (this.#merging) { + safeObjectAssign(this.#internals.timeout, value); + } + else { + this.#internals.timeout = { ...value }; + } + } + /** + When specified, `prefixUrl` will be prepended to relative string `url` input. + The prefix can be any valid URL, either relative or absolute. + A trailing slash `/` is optional - one will be added automatically. + + __Note__: Absolute string URLs and URL instances bypass `prefixUrl` by default. Other instance defaults, including headers, still apply. For untrusted URLs, set `allowAbsoluteUrls` to `false`. + + __Note__: Got cannot know which custom headers are sensitive. If you use headers like `x-api-key`, only pass trusted URLs or use `allowAbsoluteUrls: false`. + + __Note__: Leading slashes in `input` are disallowed when using this option to enforce consistency and avoid confusion. + For example, when the prefix URL is `https://example.com/foo` and the input is `/bar`, there's ambiguity whether the resulting URL would become `https://example.com/foo/bar` or `https://example.com/bar`. + The latter is used by browsers. + + __Tip__: Useful when used with `got.extend()` to create niche-specific Got instances. + + __Tip__: You can change `prefixUrl` using hooks as long as the URL still includes the `prefixUrl`. + If the URL doesn't include it anymore, it will throw. + + @example + ``` + import got from 'got'; + + await got('unicorn', {prefixUrl: 'https://cats.com'}); + //=> 'https://cats.com/unicorn' + + const instance = got.extend({ + prefixUrl: 'https://google.com' + }); + + await instance('unicorn', { + hooks: { + beforeRequest: [ + options => { + options.prefixUrl = 'https://cats.com'; + } + ] + } + }); + //=> 'https://cats.com/unicorn' + ``` + */ + get prefixUrl() { + // We always return `string` here. + // It has to be `string | URL`, otherwise TypeScript will error because the getter and the setter have incompatible types. + return this.#internals.prefixUrl; + } + set prefixUrl(value) { + options_assertAny('prefixUrl', [distribution.string, distribution.urlInstance], value); + if (value === '') { + this.#internals.prefixUrl = ''; + return; + } + value = value.toString(); + if (!value.endsWith('/')) { + value += '/'; + } + if (this.#internals.prefixUrl && this.#internals.url) { + const url = this.#internals.url; + const previousUrl = new URL(url); + const { username, password } = url; + const urlWithoutCredentials = new URL(url); + urlWithoutCredentials.username = ''; + urlWithoutCredentials.password = ''; + let prefixUrlWithoutCredentials = this.#internals.prefixUrl.toString(); + let hasNewPrefixCredentials = false; + if (isAbsoluteUrl(value)) { + const nextPrefixUrl = new URL(value); + hasNewPrefixCredentials = nextPrefixUrl.username !== '' || nextPrefixUrl.password !== ''; + } + if (isAbsoluteUrl(this.#internals.prefixUrl)) { + const prefixUrl = new URL(this.#internals.prefixUrl); + prefixUrl.username = ''; + prefixUrl.password = ''; + prefixUrlWithoutCredentials = prefixUrl.href; + } + url.href = value + urlWithoutCredentials.href.slice(prefixUrlWithoutCredentials.length); + const isSameOriginUrl = isSameOrigin(previousUrl, url); + if (username && !url.username && isSameOriginUrl && !hasNewPrefixCredentials) { + url.username = username; + } + if (password && !url.password && isSameOriginUrl && !hasNewPrefixCredentials) { + url.password = password; + } + } + this.#internals.prefixUrl = value; + trackStateMutation(this.#trackedStateMutations, 'prefixUrl'); + } + /** + __Note #1__: The `body` option cannot be used with the `json` or `form` option. + + __Note #2__: If you provide this option, `got.stream()` will be read-only. + + __Note #3__: If you provide a payload with the `GET` or `HEAD` method, it will throw a `TypeError` unless the method is `GET` and the `allowGetBody` option is set to `true`. + + __Note #4__: This option is not enumerable and will not be merged with the instance defaults. + + The `content-length` header will be automatically set if `body` is a `string` / `Uint8Array` / typed array, and `content-length` and `transfer-encoding` are not manually set in `options.headers`. + + Since Got 12, the `content-length` is not automatically set when `body` is a `fs.createReadStream`. + + You can use `Iterable` and `AsyncIterable` objects as request body, including Web [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream): + + @example + ``` + import got from 'got'; + + // Using an async generator + async function* generateData() { + yield 'Hello, '; + yield 'world!'; + } + + await got.post('https://httpbin.org/anything', { + body: generateData() + }); + ``` + */ + get body() { + return this.#internals.body; + } + set body(value) { + options_assertAny('body', [distribution.string, distribution.buffer, distribution.nodeStream, distribution.generator, distribution.asyncGenerator, distribution.iterable, distribution.asyncIterable, distribution.typedArray, distribution.undefined], value); + if (distribution.nodeStream(value)) { + assert.truthy(value.readable); + } + if (value !== undefined) { + assert.undefined(this.#internals.form); + assert.undefined(this.#internals.json); + } + this.#internals.body = value; + trackStateMutation(this.#trackedStateMutations, 'body'); + } + /** + The form body is converted to a query string using [`(new URLSearchParams(object)).toString()`](https://nodejs.org/api/url.html#url_constructor_new_urlsearchparams_obj). + + If the `Content-Type` header is not present, it will be set to `application/x-www-form-urlencoded`. + + __Note #1__: If you provide this option, `got.stream()` will be read-only. + + __Note #2__: This option is not enumerable and will not be merged with the instance defaults. + */ + get form() { + return this.#internals.form; + } + set form(value) { + options_assertAny('form', [distribution.plainObject, distribution.undefined], value); + if (value !== undefined) { + assert.undefined(this.#internals.body); + assert.undefined(this.#internals.json); + } + this.#internals.form = value; + trackStateMutation(this.#trackedStateMutations, 'form'); + } + /** + JSON request body. If the `content-type` header is not set, it will be set to `application/json`. + + __Important__: This option only affects the request body you send to the server. To parse the response as JSON, you must either call `.json()` on the promise or set `responseType: 'json'` in the options. + + __Note #1__: If you provide this option, `got.stream()` will be read-only. + + __Note #2__: This option is not enumerable and will not be merged with the instance defaults. + */ + get json() { + return this.#internals.json; + } + set json(value) { + if (value !== undefined) { + assert.undefined(this.#internals.body); + assert.undefined(this.#internals.form); + } + this.#internals.json = value; + trackStateMutation(this.#trackedStateMutations, 'json'); + } + /** + The URL to request, as a string, a [`https.request` options object](https://nodejs.org/api/https.html#https_https_request_options_callback), or a [WHATWG `URL`](https://nodejs.org/api/url.html#url_class_url). + + Properties from `options` will override properties in the parsed `url`. + + If no protocol is specified, it will throw a `TypeError`. + + __Note__: The query string is **not** parsed as search params. + + @example + ``` + await got('https://example.com/?query=a b'); //=> https://example.com/?query=a%20b + await got('https://example.com/', {searchParams: {query: 'a b'}}); //=> https://example.com/?query=a+b + + // The query string is overridden by `searchParams` + await got('https://example.com/?query=a b', {searchParams: {query: 'a b'}}); //=> https://example.com/?query=a+b + ``` + */ + get url() { + return this.#internals.url; + } + set url(value) { + options_assertAny('url', [distribution.string, distribution.urlInstance, distribution.undefined], value); + if (value === undefined) { + this.#internals.url = undefined; + trackStateMutation(this.#trackedStateMutations, 'url'); + return; + } + if (distribution.string(value) && value.startsWith('/')) { + throw new Error('`url` must not start with a slash'); + } + const valueString = value.toString(); + if (distribution.string(value) + && !this.prefixUrl + && hasHttpProtocolWithoutSlashes(valueString)) { + throw new Error('`url` protocol must be followed by `//`'); + } + // Detect if URL is already absolute. + const isAbsolute = isAbsoluteUrl(value); + assertRelativeUrlIfNeeded(this, value); + // Only concatenate prefixUrl if the URL is relative + const urlString = isAbsolute ? valueString : `${this.prefixUrl}${valueString}`; + const url = new URL(urlString); + this.#internals.url = url; + trackStateMutation(this.#trackedStateMutations, 'url'); + if (usesUnixSocket(url) && !this.#internals.enableUnixSockets) { + throw new Error('Using UNIX domain sockets but option `enableUnixSockets` is not enabled'); + } + if (url.protocol === 'unix:') { + url.href = `http://unix${url.pathname}${url.search}`; + } + if (url.protocol !== 'http:' && url.protocol !== 'https:') { + const error = new Error(`Unsupported protocol: ${url.protocol}`); + error.code = 'ERR_UNSUPPORTED_PROTOCOL'; + throw error; + } + if (this.#internals.username) { + url.username = this.#internals.username; + this.#internals.username = ''; + } + if (this.#internals.password) { + url.password = this.#internals.password; + this.#internals.password = ''; + } + if (this.#internals.searchParams) { + url.search = this.#internals.searchParams.toString(); + this.#internals.searchParams = undefined; + } + } + /** + Cookie support. You don't have to care about parsing or how to store them. + + __Note__: If you provide this option, `options.headers.cookie` will be overridden. + */ + get cookieJar() { + return this.#internals.cookieJar; + } + set cookieJar(value) { + options_assertAny('cookieJar', [distribution.object, distribution.undefined], value); + if (value === undefined) { + this.#internals.cookieJar = undefined; + return; + } + const { setCookie, getCookieString } = value; + assert.function(setCookie); + assert.function(getCookieString); + /* istanbul ignore next: Horrible `tough-cookie` v3 check */ + if (isToughCookieJar(value)) { + this.#internals.cookieJar = { + setCookie: (0,external_node_util_.promisify)(value.setCookie.bind(value)), + getCookieString: (0,external_node_util_.promisify)(value.getCookieString.bind(value)), + }; + } + else { + this.#internals.cookieJar = value; + } + } + /** + You can abort the `request` using [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController). + + @example + ``` + import got from 'got'; + + const abortController = new AbortController(); + + const request = got('https://httpbin.org/anything', { + signal: abortController.signal + }); + + setTimeout(() => { + abortController.abort(); + }, 100); + ``` + */ + get signal() { + return this.#internals.signal; + } + set signal(value) { + options_assertAny('signal', [distribution.object, distribution.undefined], value); + this.#internals.signal = value; + } + /** + Ignore invalid cookies instead of throwing an error. + Only useful when the `cookieJar` option has been set. Not recommended. + + @default false + */ + get ignoreInvalidCookies() { + return this.#internals.ignoreInvalidCookies; + } + set ignoreInvalidCookies(value) { + assert.boolean(value); + this.#internals.ignoreInvalidCookies = value; + } + /** + Query string that will be added to the request URL. + This will override the query string in `url`. + + If you need to pass in an array, you can do it using a `URLSearchParams` instance. + + @example + ``` + import got from 'got'; + + const searchParams = new URLSearchParams([['key', 'a'], ['key', 'b']]); + + await got('https://example.com', {searchParams}); + + console.log(searchParams.toString()); + //=> 'key=a&key=b' + ``` + */ + get searchParams() { + if (this.#internals.url) { + return this.#internals.url.searchParams; + } + this.#internals.searchParams ??= new URLSearchParams(); + return this.#internals.searchParams; + } + set searchParams(value) { + options_assertAny('searchParams', [distribution.string, distribution.object, distribution.undefined], value); + const url = this.#internals.url; + if (value === undefined) { + this.#internals.searchParams = undefined; + if (url) { + url.search = ''; + } + return; + } + const searchParameters = this.searchParams; + let updated; + if (distribution.string(value)) { + updated = new URLSearchParams(value); + } + else if (value instanceof URLSearchParams) { + // Clone so the caller-owned object is not stored by reference. + updated = new URLSearchParams(value); + } + else { + validateSearchParameters(value); + updated = new URLSearchParams(); + for (const key of Object.keys(value)) { + if (key === '__proto__') { + continue; + } + const entry = value[key]; + if (entry === null) { + updated.append(key, ''); + } + else if (entry === undefined) { + searchParameters.delete(key); + } + else { + updated.append(key, entry); + } + } + } + if (this.#merging) { + // These keys will be replaced + for (const key of updated.keys()) { + searchParameters.delete(key); + } + for (const [key, value] of updated) { + searchParameters.append(key, value); + } + } + else if (url) { + // Overrides the query string in the URL. + url.search = updated.toString(); + } + else { + this.#internals.searchParams = updated; + } + } + get dnsLookup() { + return this.#internals.dnsLookup; + } + set dnsLookup(value) { + options_assertAny('dnsLookup', [distribution.function, distribution.undefined], value); + this.#internals.dnsLookup = value; + } + /** + A DNS cache instance used for making DNS lookups. + Useful when making lots of requests to different *public* hostnames. + Set to `true` to use Got's shared DNS cache. + When using `got.extend()`, set to `false` to opt out of a DNS cache configured by the parent instance. + + Got's built-in DNS cache uses `dns.resolve4(…)` and `dns.resolve6(…)` under the hood and falls back to `dns.lookup(…)` when no DNS records are found, which may lead to additional delay. + Because it resolves A and AAAA records separately, it cannot preserve OS-specific `verbatim` address ordering from `dns.lookup(…)`. + If present, `clear(hostname?)` can be called by user code to clear cached entries. + + __Note__: This should stay disabled when making requests to internal hostnames such as `localhost`, `database.local` etc. + + @default false + */ + get dnsCache() { + return this.#internals.dnsCache; + } + set dnsCache(value) { + options_assertAny('dnsCache', [distribution.object, distribution.boolean, distribution.undefined], value); + if (value === true) { + this.#internals.dnsCache = getGlobalDnsCache(); + } + else if (value === false) { + this.#internals.dnsCache = undefined; + } + else { + if (value !== undefined) { + options_assertAny('dnsCache.lookup', [distribution.function], value.lookup); + options_assertAny('dnsCache.clear', [distribution.function, distribution.undefined], value.clear); + } + this.#internals.dnsCache = value; + } + } + /** + User data. `context` is shallow merged and enumerable. If it contains non-enumerable properties they will NOT be merged. + + @example + ``` + import got from 'got'; + + const instance = got.extend({ + hooks: { + beforeRequest: [ + options => { + if (!options.context || !options.context.token) { + throw new Error('Token required'); + } + + options.headers.token = options.context.token; + } + ] + } + }); + + const context = { + token: 'secret' + }; + + const response = await instance('https://httpbin.org/headers', {context}); + + // Let's see the headers + console.log(response.body); + ``` + */ + get context() { + return this.#internals.context; + } + set context(value) { + assert.object(value); + if (this.#merging) { + safeObjectAssign(this.#internals.context, value); + } + else { + this.#internals.context = { ...value }; + } + } + /** + Hooks allow modifications during the request lifecycle. + Hook functions may be async and are run serially. + */ + get hooks() { + return this.#internals.hooks; + } + set hooks(value) { + assert.object(value); + for (const knownHookEvent of Object.keys(value)) { + if (knownHookEvent === '__proto__') { + continue; + } + if (!(knownHookEvent in this.#internals.hooks)) { + throw new Error(`Unexpected hook event: ${knownHookEvent}`); + } + const typedKnownHookEvent = knownHookEvent; + const hooks = value[typedKnownHookEvent]; + options_assertAny(`hooks.${knownHookEvent}`, [distribution.array, distribution.undefined], hooks); + if (hooks) { + for (const hook of hooks) { + assert.function(hook); + } + } + if (this.#merging) { + if (hooks) { + // @ts-expect-error Indexing by a widened `keyof Hooks` loses the correlation to `hooks`'s specific array type. + this.#internals.hooks[typedKnownHookEvent].push(...hooks); + } + } + else { + if (!hooks) { + throw new Error(`Missing hook event: ${knownHookEvent}`); + } + // @ts-expect-error Indexing by a widened `keyof Hooks` loses the correlation to `hooks`'s specific array type. + this.#internals.hooks[knownHookEvent] = [...hooks]; + } + } + } + /** + Whether redirect responses should be followed automatically. + + Optionally, pass a function to dynamically decide based on the response object. + + Note that if a `303` is sent by the server in response to any request type (`POST`, `DELETE`, etc.), Got will automatically request the resource pointed to in the location header via `GET`. + This is in accordance with [the spec](https://tools.ietf.org/html/rfc7231#section-6.4.4). You can optionally turn on this behavior also for other redirect codes - see `methodRewriting`. + On cross-origin redirects, Got strips `host`, `cookie`, `cookie2`, `authorization`, and `proxy-authorization`. When a redirect rewrites the request to `GET`, Got also strips request body headers. Use `hooks.beforeRedirect` for app-specific sensitive headers. + + @default true + */ + get followRedirect() { + return this.#internals.followRedirect; + } + set followRedirect(value) { + options_assertAny('followRedirect', [distribution.boolean, distribution.function], value); + this.#internals.followRedirect = value; + } + /** + If exceeded, the request will be aborted and a `MaxRedirectsError` will be thrown. + + @default 10 + */ + get maxRedirects() { + return this.#internals.maxRedirects; + } + set maxRedirects(value) { + assert.number(value); + this.#internals.maxRedirects = value; + } + /** + A cache adapter instance for storing cached response data. + + @default false + */ + get cache() { + return this.#internals.cache; + } + set cache(value) { + options_assertAny('cache', [distribution.object, distribution.string, distribution.boolean, distribution.undefined], value); + if (value === true) { + this.#internals.cache = globalCache; + } + else if (value === false) { + this.#internals.cache = undefined; + } + else { + this.#internals.cache = wrapQuickLruIfNeeded(value); + } + } + /** + Determines if a `got.HTTPError` is thrown for unsuccessful responses. + + If this is disabled, requests that encounter an error status code will be resolved with the `response` instead of throwing. + This may be useful if you are checking for resource availability and are expecting error responses. + + @default true + */ + get throwHttpErrors() { + return this.#internals.throwHttpErrors; + } + set throwHttpErrors(value) { + assert.boolean(value); + this.#internals.throwHttpErrors = value; + } + get username() { + const url = this.#internals.url; + const value = url ? url.username : this.#internals.username; + return decodeURIComponent(value); + } + set username(value) { + assert.string(value); + const url = this.#internals.url; + const fixedValue = encodeURIComponent(value); + if (url) { + url.username = fixedValue; + } + else { + this.#internals.username = fixedValue; + } + trackStateMutation(this.#trackedStateMutations, 'username'); + } + get password() { + const url = this.#internals.url; + const value = url ? url.password : this.#internals.password; + return decodeURIComponent(value); + } + set password(value) { + assert.string(value); + const url = this.#internals.url; + const fixedValue = encodeURIComponent(value); + if (url) { + url.password = fixedValue; + } + else { + this.#internals.password = fixedValue; + } + trackStateMutation(this.#trackedStateMutations, 'password'); + } + /** + If set to `true`, Got will additionally accept HTTP/2 requests. + + It will choose either HTTP/1.1 or HTTP/2 depending on the ALPN protocol. When a custom `agent.https` instance is set, Got uses that native HTTPS agent directly and skips HTTP/2 negotiation. + + __Note__: If `options.request` returns a request or response, it controls the transport and Got's HTTP/2 client is bypassed. Return `undefined` to fall back to Got's built-in transport. + + @default false + + @example + ``` + import got from 'got'; + + const {headers} = await got('https://nghttp2.org/httpbin/anything', {http2: true}); + + console.log(headers.via); + //=> '2 nghttpx' + ``` + */ + get http2() { + return this.#internals.http2; + } + set http2(value) { + assert.boolean(value); + this.#internals.http2 = value; + } + /** + Set this to `true` to allow sending body for the `GET` method. + This option is only meant to interact with non-compliant servers when you have no other choice. + + __Note__: The [RFC 7231](https://tools.ietf.org/html/rfc7231#section-4.3.1) doesn't specify any particular behavior for the GET method having a payload, therefore __it's considered an [anti-pattern](https://en.wikipedia.org/wiki/Anti-pattern)__. + + @default false + */ + get allowGetBody() { + return this.#internals.allowGetBody; + } + set allowGetBody(value) { + assert.boolean(value); + this.#internals.allowGetBody = value; + } + /** + Allow absolute URLs to bypass `prefixUrl`. + + When set to `false` with `prefixUrl`, passing an absolute `url` will throw. This also rejects scheme-relative URL strings like `//example.com/path` in retry and pagination URL overrides. Use this when untrusted URL input must stay on the same origin as the configured `prefixUrl`. This is not a path sandbox: relative paths like `../other` still follow standard URL resolution on the same origin. Set `prefixUrl` to an empty string for a request that intentionally needs an absolute URL. + + __Note__: This guards the `url` you pass. It does not block cross-origin redirects issued by the server, though inherited sensitive headers are still stripped when a redirect changes origin. + + __Note__: The check is defeated if the same hook or `pagination.paginate(…)` return also sets `prefixUrl` or `allowAbsoluteUrls`. Do not populate those options from untrusted data. + + @default true + */ + get allowAbsoluteUrls() { + return this.#internals.allowAbsoluteUrls; + } + set allowAbsoluteUrls(value) { + assert.boolean(value); + this.#internals.allowAbsoluteUrls = value; + } + /** + Automatically copy headers from piped streams. + + When piping a request into a Got stream (e.g., `request.pipe(got.stream(url))`), this controls whether headers from the source stream are automatically merged into the Got request headers. + + Note: Explicitly set headers take precedence over piped headers. Piped headers are only copied when a header is not already explicitly set. + + Useful for proxy scenarios when explicitly enabled. Got automatically omits `host`, `authorization`, `cookie`, `cookie2`, `set-cookie`, `set-cookie2`, hop-by-hop headers, and headers nominated by `Connection`/`Proxy-Connection`. Got cannot know which app-specific headers are sensitive. Leave `copyPipedHeaders` disabled and copy only safe headers manually, or explicitly omit those headers before piping. If you trust the upstream and want to forward credentials, pass them explicitly in `headers`. + + @default false + + @example + ``` + import got from 'got'; + import {pipeline} from 'node:stream/promises'; + + // Opt in to automatic header copying for proxy scenarios + server.get('/proxy', async (request, response) => { + const gotStream = got.stream('https://example.com', { + copyPipedHeaders: true, + // Explicit headers win over piped headers. + // Add credentials here only when the upstream is trusted. + headers: { + host: 'example.com', + } + }); + + await pipeline(request, gotStream, response); + }); + ``` + + @example + ``` + import got from 'got'; + import {pipeline} from 'node:stream/promises'; + + // Keep it disabled and manually copy only safe headers + server.get('/proxy', async (request, response) => { + const gotStream = got.stream('https://example.com', { + headers: { + 'user-agent': request.headers['user-agent'], + 'accept': request.headers['accept'], + // Explicitly NOT copying host, connection, authorization, etc. + } + }); + + await pipeline(request, gotStream, response); + }); + ``` + */ + get copyPipedHeaders() { + return this.#internals.copyPipedHeaders; + } + set copyPipedHeaders(value) { + assert.boolean(value); + this.#internals.copyPipedHeaders = value; + } + isHeaderExplicitlySet(name) { + return this.#explicitHeaders.has(name.toLowerCase()); + } + shouldCopyPipedHeader(name) { + return !this.isHeaderExplicitlySet(name); + } + setPipedHeader(name, value) { + assertValidHeaderName(name); + this.#internals.headers[name.toLowerCase()] = value; + } + getInternalHeaders() { + return this.#internals.headers; + } + setInternalHeader(name, value) { + assertValidHeaderName(name); + this.#internals.headers[name.toLowerCase()] = value; + } + deleteInternalHeader(name) { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete this.#internals.headers[name.toLowerCase()]; + } + async trackStateMutations(operation) { + const changedState = new Set(); + this.#trackedStateMutations = changedState; + try { + return await operation(changedState); + } + finally { + this.#trackedStateMutations = undefined; + } + } + clearBody() { + this.body = undefined; + this.json = undefined; + this.form = undefined; + for (const header of bodyHeaderNames) { + this.deleteInternalHeader(header); + } + } + clearUnchangedCookieHeader(previousState, changedState) { + if (previousState?.hadCookieJar + && this.cookieJar === undefined + && !this.isHeaderExplicitlySet('cookie') + && !changedState?.has('cookie') + && this.headers.cookie === previousState.headers.cookie) { + this.deleteInternalHeader('cookie'); + } + } + restoreCookieHeader(previousState, headers) { + if (!previousState) { + return; + } + if (Object.hasOwn(headers ?? {}, 'cookie')) { + return; + } + if (previousState.cookieWasExplicitlySet) { + this.headers.cookie = previousState.headers.cookie; + return; + } + delete this.headers.cookie; + if (previousState.headers.cookie !== undefined) { + this.setInternalHeader('cookie', previousState.headers.cookie); + } + } + syncCookieHeaderAfterMerge(previousState, headers) { + this.restoreCookieHeader(previousState, headers); + this.clearUnchangedCookieHeader(previousState); + } + stripUnchangedCrossOriginState(previousState, changedState, { clearBody = true } = {}) { + const headers = this.getInternalHeaders(); + const url = this.#internals.url; + for (const header of crossOriginStripHeaders) { + if (!changedState.has(header) && headers[header] === previousState.headers[header]) { + this.deleteInternalHeader(header); + } + } + if (!hasExplicitCredentialInUrlChange(changedState, url, 'username')) { + this.username = ''; + } + if (!hasExplicitCredentialInUrlChange(changedState, url, 'password')) { + this.password = ''; + } + if (clearBody && !changedState.has('body') && !changedState.has('json') && !changedState.has('form') && isBodyUnchanged(this, previousState)) { + this.clearBody(); + } + } + /** + Strip sensitive headers and credentials when navigating to a different origin. + Headers and credentials explicitly provided in `userOptions` are preserved. + */ + stripSensitiveHeaders(previousUrl, nextUrl, userOptions) { + if (isSameOrigin(previousUrl, nextUrl)) { + return; + } + const headers = lowercase_keys_lowercaseKeys(userOptions.headers ?? {}); + for (const header of crossOriginStripHeaders) { + if (headers[header] === undefined) { + this.deleteInternalHeader(header); + } + } + const explicitUsername = Object.hasOwn(userOptions, 'username') ? userOptions.username : undefined; + const explicitPassword = Object.hasOwn(userOptions, 'password') ? userOptions.password : undefined; + const hasExplicitUsername = explicitUsername !== undefined + || hasCredentialInUrl(userOptions.url, 'username') + || hasCredentialInUrl(userOptions.prefixUrl, 'username') + || isCrossOriginCredentialChanged(previousUrl, nextUrl, 'username'); + const hasExplicitPassword = explicitPassword !== undefined + || hasCredentialInUrl(userOptions.url, 'password') + || hasCredentialInUrl(userOptions.prefixUrl, 'password') + || isCrossOriginCredentialChanged(previousUrl, nextUrl, 'password'); + if (!hasExplicitUsername && this.username) { + this.username = ''; + } + if (!hasExplicitPassword && this.password) { + this.password = ''; + } + } + /** + Request headers. + + Existing headers will be overwritten. Headers set to `undefined` will be omitted. + + @default {} + */ + get headers() { + return this.#headersProxy; + } + set headers(value) { + options_assertPlainObject('headers', value); + const normalizedHeaders = lowercase_keys_lowercaseKeys(value); + for (const header of Object.keys(normalizedHeaders)) { + assertValidHeaderName(header); + } + if (this.#merging) { + safeObjectAssign(this.#internals.headers, normalizedHeaders); + } + else { + const previousHeaders = this.#internals.headers; + this.#internals.headers = normalizedHeaders; + this.#headersProxy = this.#createHeadersProxy(); + this.#explicitHeaders.clear(); + trackReplacedHeaderMutations(this.#trackedStateMutations, previousHeaders, normalizedHeaders); + } + for (const header of Object.keys(normalizedHeaders)) { + if (this.#merging) { + markHeaderAsExplicit(this.#explicitHeaders, this.#trackedStateMutations, header); + } + else { + addExplicitHeader(this.#explicitHeaders, header); + } + } + } + /** + Specifies if the HTTP request method should be [rewritten as `GET`](https://tools.ietf.org/html/rfc7231#section-6.4) on redirects. + + As the [specification](https://tools.ietf.org/html/rfc7231#section-6.4) prefers to rewrite the HTTP method only on `303` responses, this is Got's default behavior. Cross-origin `301` and `302` redirects also rewrite `POST` requests to `GET` by default to avoid forwarding request bodies to another origin. + Setting `methodRewriting` to `true` will also rewrite same-origin `301` and `302` responses, as allowed by the spec. This is the behavior followed by `curl` and browsers. + + __Note__: Got never performs method rewriting on `307` and `308` responses, as this is [explicitly prohibited by the specification](https://www.rfc-editor.org/rfc/rfc7231#section-6.4.7). + + @default false + */ + get methodRewriting() { + return this.#internals.methodRewriting; + } + set methodRewriting(value) { + assert.boolean(value); + this.#internals.methodRewriting = value; + } + /** + Indicates which DNS record family to use. + + Values: + - `undefined`: IPv4 (if present) or IPv6 + - `4`: Only IPv4 + - `6`: Only IPv6 + + @default undefined + */ + get dnsLookupIpVersion() { + return this.#internals.dnsLookupIpVersion; + } + set dnsLookupIpVersion(value) { + if (value !== undefined && value !== 4 && value !== 6) { + throw new TypeError(`Invalid DNS lookup IP version: ${value}`); + } + this.#internals.dnsLookupIpVersion = value; + } + /** + A function used to parse JSON responses. + + @example + ``` + import got from 'got'; + import Bourne from '@hapi/bourne'; + + const parsed = await got('https://example.com', { + parseJson: text => Bourne.parse(text) + }).json(); + + console.log(parsed); + ``` + */ + get parseJson() { + return this.#internals.parseJson; + } + set parseJson(value) { + assert.function(value); + this.#internals.parseJson = value; + } + /** + A function used to stringify the body of JSON requests. + + @example + ``` + import got from 'got'; + + await got.post('https://example.com', { + stringifyJson: object => JSON.stringify(object, (key, value) => { + if (key.startsWith('_')) { + return; + } + + return value; + }), + json: { + some: 'payload', + _ignoreMe: 1234 + } + }); + ``` + + @example + ``` + import got from 'got'; + + await got.post('https://example.com', { + stringifyJson: object => JSON.stringify(object, (key, value) => { + if (typeof value === 'number') { + return value.toString(); + } + + return value; + }), + json: { + some: 'payload', + number: 1 + } + }); + ``` + */ + get stringifyJson() { + return this.#internals.stringifyJson; + } + set stringifyJson(value) { + assert.function(value); + this.#internals.stringifyJson = value; + } + /** + An object representing `limit`, `calculateDelay`, `methods`, `statusCodes`, `maxRetryAfter` and `errorCodes` fields for maximum retry count, retry handler, allowed methods, allowed status codes, maximum [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) time and allowed error codes. + + Delays between retries counts with function `1000 * Math.pow(2, retry) + Math.random() * 100`, where `retry` is attempt number (starts from 1). + + The `calculateDelay` property is a `function` that receives an object with `attemptCount`, `retryOptions`, `error` and `computedValue` properties for current retry count, the retry options, error and default computed value. + The function must return a delay in milliseconds (or a Promise resolving with it) (`0` return value cancels retry). + + The `enforceRetryRules` property is a `boolean` that, when set to `true` (default), enforces the `limit`, `methods`, `statusCodes`, and `errorCodes` options before calling `calculateDelay`. Your `calculateDelay` function is only invoked when a retry is allowed based on these criteria. When `false`, `calculateDelay` receives the computed value but can override all retry logic. + + __Note:__ When `enforceRetryRules` is `false`, you must check `computedValue` in your `calculateDelay` function to respect retry rules. When `true` (default), the retry rules are enforced automatically. + + By default, it retries *only* on the specified methods, status codes, and on these network errors: + + - `ETIMEDOUT`: One of the [timeout](#timeout) limits were reached. + - `ECONNRESET`: Connection was forcibly closed by a peer. + - `EADDRINUSE`: Could not bind to any free port. + - `ECONNREFUSED`: Connection was refused by the server. + - `EPIPE`: The remote side of the stream being written has been closed. + - `ENOTFOUND`: Couldn't resolve the hostname to an IP address. + - `ENETUNREACH`: No internet connection. + - `EAI_AGAIN`: DNS lookup timed out. + + __Note__: If `maxRetryAfter` is set to `undefined`, it will use `options.timeout`. + __Note__: If [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header is greater than `maxRetryAfter`, it will cancel the request. + */ + get retry() { + return this.#internals.retry; + } + set retry(value) { + options_assertPlainObject('retry', value); + options_assertAny('retry.calculateDelay', [distribution.function, distribution.undefined], value.calculateDelay); + options_assertAny('retry.maxRetryAfter', [distribution.number, distribution.undefined], value.maxRetryAfter); + options_assertAny('retry.limit', [distribution.number, distribution.undefined], value.limit); + options_assertAny('retry.methods', [distribution.array, distribution.undefined], value.methods); + options_assertAny('retry.statusCodes', [distribution.array, distribution.undefined], value.statusCodes); + options_assertAny('retry.errorCodes', [distribution.array, distribution.undefined], value.errorCodes); + options_assertAny('retry.noise', [distribution.number, distribution.undefined], value.noise); + options_assertAny('retry.enforceRetryRules', [distribution.boolean, distribution.undefined], value.enforceRetryRules); + if (value.noise && Math.abs(value.noise) > 100) { + throw new Error(`The maximum acceptable retry noise is +/- 100ms, got ${value.noise}`); + } + for (const key of Object.keys(value)) { + if (key === '__proto__') { + continue; + } + if (!(key in this.#internals.retry)) { + throw new Error(`Unexpected retry option: ${key}`); + } + } + if (this.#merging) { + safeObjectAssign(this.#internals.retry, value); + } + else { + this.#internals.retry = { ...value }; + } + const { retry } = this.#internals; + retry.methods = [...new Set(retry.methods.map(method => method.toUpperCase()))]; + retry.statusCodes = [...new Set(retry.statusCodes)]; + retry.errorCodes = [...new Set(retry.errorCodes)]; + } + /** + From `http.RequestOptions`. + + The IP address used to send the request from. + */ + get localAddress() { + return this.#internals.localAddress; + } + set localAddress(value) { + options_assertAny('localAddress', [distribution.string, distribution.undefined], value); + this.#internals.localAddress = value; + } + /** + The HTTP method used to make the request. + + @default 'GET' + */ + get method() { + return this.#internals.method; + } + set method(value) { + assert.string(value); + this.#internals.method = value.toUpperCase(); + } + get createConnection() { + return this.#internals.createConnection; + } + set createConnection(value) { + options_assertAny('createConnection', [distribution.function, distribution.undefined], value); + this.#internals.createConnection = value; + } + /** + From `http-cache-semantics` + + @default {} + */ + get cacheOptions() { + return this.#internals.cacheOptions; + } + set cacheOptions(value) { + options_assertPlainObject('cacheOptions', value); + options_assertAny('cacheOptions.shared', [distribution.boolean, distribution.undefined], value.shared); + options_assertAny('cacheOptions.cacheHeuristic', [distribution.number, distribution.undefined], value.cacheHeuristic); + options_assertAny('cacheOptions.immutableMinTimeToLive', [distribution.number, distribution.undefined], value.immutableMinTimeToLive); + options_assertAny('cacheOptions.ignoreCargoCult', [distribution.boolean, distribution.undefined], value.ignoreCargoCult); + for (const key of Object.keys(value)) { + if (key === '__proto__') { + continue; + } + if (!(key in this.#internals.cacheOptions)) { + throw new Error(`Cache option \`${key}\` does not exist`); + } + } + if (this.#merging) { + safeObjectAssign(this.#internals.cacheOptions, value); + } + else { + this.#internals.cacheOptions = { ...value }; + } + } + /** + Options for the advanced HTTPS API. + */ + get https() { + return this.#internals.https; + } + set https(value) { + options_assertPlainObject('https', value); + options_assertAny('https.rejectUnauthorized', [distribution.boolean, distribution.undefined], value.rejectUnauthorized); + options_assertAny('https.checkServerIdentity', [distribution.function, distribution.undefined], value.checkServerIdentity); + options_assertAny('https.serverName', [distribution.string, distribution.undefined], value.serverName); + options_assertAny('https.certificateAuthority', [distribution.string, distribution.object, distribution.array, distribution.undefined], value.certificateAuthority); + options_assertAny('https.key', [distribution.string, distribution.object, distribution.array, distribution.undefined], value.key); + options_assertAny('https.certificate', [distribution.string, distribution.object, distribution.array, distribution.undefined], value.certificate); + options_assertAny('https.passphrase', [distribution.string, distribution.undefined], value.passphrase); + options_assertAny('https.pfx', [distribution.string, distribution.buffer, distribution.array, distribution.undefined], value.pfx); + options_assertAny('https.alpnProtocols', [distribution.array, distribution.undefined], value.alpnProtocols); + options_assertAny('https.ciphers', [distribution.string, distribution.undefined], value.ciphers); + options_assertAny('https.dhparam', [distribution.string, distribution.buffer, distribution.undefined], value.dhparam); + options_assertAny('https.signatureAlgorithms', [distribution.string, distribution.undefined], value.signatureAlgorithms); + options_assertAny('https.minVersion', [distribution.string, distribution.undefined], value.minVersion); + options_assertAny('https.maxVersion', [distribution.string, distribution.undefined], value.maxVersion); + options_assertAny('https.honorCipherOrder', [distribution.boolean, distribution.undefined], value.honorCipherOrder); + options_assertAny('https.tlsSessionLifetime', [distribution.number, distribution.undefined], value.tlsSessionLifetime); + options_assertAny('https.ecdhCurve', [distribution.string, distribution.undefined], value.ecdhCurve); + options_assertAny('https.certificateRevocationLists', [distribution.string, distribution.buffer, distribution.array, distribution.undefined], value.certificateRevocationLists); + options_assertAny('https.secureOptions', [distribution.number, distribution.undefined], value.secureOptions); + for (const key of Object.keys(value)) { + if (key === '__proto__') { + continue; + } + if (!(key in this.#internals.https)) { + throw new Error(`HTTPS option \`${key}\` does not exist`); + } + } + if (this.#merging) { + safeObjectAssign(this.#internals.https, value); + } + else { + this.#internals.https = { ...value }; + } + } + /** + [Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data. + + To get a [`Uint8Array`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array), you need to set `responseType` to `buffer` instead. + Don't set this option to `null`. + + __Note__: This doesn't affect streams! Instead, you need to do `got.stream(...).setEncoding(encoding)`. + + @default 'utf-8' + */ + get encoding() { + return this.#internals.encoding; + } + set encoding(value) { + if (value === null) { + throw new TypeError('To get a Uint8Array, set `options.responseType` to `buffer` instead'); + } + options_assertAny('encoding', [distribution.string, distribution.undefined], value); + this.#internals.encoding = value; + } + /** + When set to `true` the promise will return the Response body instead of the Response object. + + @default false + */ + get resolveBodyOnly() { + return this.#internals.resolveBodyOnly; + } + set resolveBodyOnly(value) { + assert.boolean(value); + this.#internals.resolveBodyOnly = value; + } + /** + Returns a `Stream` instead of a `Promise`. + Set internally by `got.stream()`. + + @default false + @internal + */ + get isStream() { + return this.#internals.isStream; + } + set isStream(value) { + assert.boolean(value); + this.#internals.isStream = value; + } + /** + The parsing method. + + The promise also has `.text()`, `.json()` and `.buffer()` methods which return another Got promise for the parsed body. + + It's like setting the options to `{responseType: 'json', resolveBodyOnly: true}` but without affecting the main Got promise. + + __Note__: When using streams, this option is ignored. + + @example + ``` + const responsePromise = got(url); + const bufferPromise = responsePromise.buffer(); + const jsonPromise = responsePromise.json(); + + const [response, buffer, json] = Promise.all([responsePromise, bufferPromise, jsonPromise]); + // `response` is an instance of Got Response + // `buffer` is an instance of Uint8Array + // `json` is an object + ``` + + @example + ``` + // This + const body = await got(url).json(); + + // is semantically the same as this + const body = await got(url, {responseType: 'json', resolveBodyOnly: true}); + ``` + */ + get responseType() { + return this.#internals.responseType; + } + set responseType(value) { + if (value !== 'text' && value !== 'buffer' && value !== 'json') { + throw new Error(`Invalid \`responseType\` option: ${value}`); + } + this.#internals.responseType = value; + } + get pagination() { + return this.#internals.pagination; + } + set pagination(value) { + assert.object(value); + if (this.#merging) { + safeObjectAssign(this.#internals.pagination, value); + } + else { + this.#internals.pagination = value; + } + } + get setHost() { + return this.#internals.setHost; + } + set setHost(value) { + assert.boolean(value); + this.#internals.setHost = value; + } + get maxHeaderSize() { + return this.#internals.maxHeaderSize; + } + set maxHeaderSize(value) { + options_assertAny('maxHeaderSize', [distribution.number, distribution.undefined], value); + this.#internals.maxHeaderSize = value; + } + get enableUnixSockets() { + return this.#internals.enableUnixSockets; + } + set enableUnixSockets(value) { + assert.boolean(value); + this.#internals.enableUnixSockets = value; + } + /** + Throw an error if the server response's `content-length` header value doesn't match the number of bytes received. + + This is useful for detecting truncated responses and follows RFC 9112 requirements for message completeness. + + __Note__: Responses without a `content-length` header are not validated. + __Note__: When enabled and validation fails, a `ReadError` with code `ERR_HTTP_CONTENT_LENGTH_MISMATCH` will be thrown. + + @default true + */ + get strictContentLength() { + return this.#internals.strictContentLength; + } + set strictContentLength(value) { + assert.boolean(value); + this.#internals.strictContentLength = value; + } + // eslint-disable-next-line @typescript-eslint/naming-convention + toJSON() { + return { ...this.#internals }; + } + [Symbol.for('nodejs.util.inspect.custom')](_depth, options) { + return (0,external_node_util_.inspect)(this.#internals, options); + } + createNativeRequestOptions() { + const internals = this.#internals; + const url = internals.url; + const usesAlpn = usesHttp2Alpn(internals, url); + const socketTimeout = usesAlpn ? internals.timeout.socket : undefined; + let agent; + if (url.protocol === 'https:') { + if (internals.http2) { + // Ensure HTTP/2 pooling is configured for connection reuse. + // If agent.http2 is unset, use the global agent for connection pooling. + agent = { + ...internals.agent, + http2: internals.agent.http2 ?? http2_client.globalAgent, + }; + } + else { + agent = internals.agent.https; + } + } + else { + agent = internals.agent.http; + } + const { https } = internals; + let { pfx } = https; + if (distribution.array(pfx) && distribution.plainObject(pfx[0])) { + pfx = pfx.map(object => ({ + buf: object.buffer, + passphrase: object.passphrase, + })); + } + const unixSocketPath = getUnixSocketPath(url); + if (usesUnixSocket(url) && !internals.enableUnixSockets) { + throw new Error('Using UNIX domain sockets but option `enableUnixSockets` is not enabled'); + } + let unixSocketGroups; + if (unixSocketPath !== undefined) { + unixSocketGroups = /^(?[^:]+):(?.+)$/v.exec(`${url.pathname}${url.search}`)?.groups; + } + const unixOptions = unixSocketGroups + ? { socketPath: unixSocketGroups.socketPath, path: unixSocketGroups.path, host: '' } + : undefined; + const nativeRequestOptions = { + ...internals.cacheOptions, + ...unixOptions, + // HTTPS options + // eslint-disable-next-line @typescript-eslint/naming-convention + ALPNProtocols: https.alpnProtocols, + ca: https.certificateAuthority, + cert: https.certificate, + key: https.key, + passphrase: https.passphrase, + pfx, + rejectUnauthorized: https.rejectUnauthorized, + checkServerIdentity: https.checkServerIdentity ?? external_node_tls_.checkServerIdentity, + servername: https.serverName, + ciphers: https.ciphers, + honorCipherOrder: https.honorCipherOrder, + minVersion: https.minVersion, + maxVersion: https.maxVersion, + sigalgs: https.signatureAlgorithms, + sessionTimeout: https.tlsSessionLifetime, + dhparam: https.dhparam, + ecdhCurve: https.ecdhCurve, + crl: https.certificateRevocationLists, + secureOptions: https.secureOptions, + // HTTP options + lookup: internals.dnsLookup ?? internals.dnsCache?.lookup, + family: internals.dnsLookupIpVersion, + agent, + setHost: internals.setHost, + method: internals.method, + maxHeaderSize: internals.maxHeaderSize, + localAddress: internals.localAddress, + headers: internals.headers, + createConnection: internals.createConnection, + signal: internals.http2 ? internals.signal : undefined, + timeout: usesAlpn ? getHttp2TimeoutOption(internals) : undefined, + ...(socketTimeout === undefined ? {} : { _socketTimeout: socketTimeout }), + // HTTP/2 options + h2session: internals.h2session, + }; + return nativeRequestOptions; + } + getRequestFunction() { + const { request: customRequest } = this.#internals; + if (!customRequest) { + return this.#getFallbackRequestFunction(); + } + const requestWithFallback = (url, options, callback) => { + const requestStartedAt = Date.now(); + const nativeAgent = getNativeAgent(url, options.agent); + const hasInternalSocketTimeout = Object.hasOwn(options, '_socketTimeout'); + const customRequestOptions = options.timeout !== undefined || hasInternalSocketTimeout || nativeAgent !== options.agent + ? { + ...options, + agent: nativeAgent, + timeout: undefined, + } + : options; + if (hasInternalSocketTimeout) { + Reflect.deleteProperty(customRequestOptions, '_socketTimeout'); + } + const result = customRequest(url, customRequestOptions, callback); + if (distribution.promise(result)) { + return this.#resolveRequestWithFallback(result, { + url, + options, + callback, + requestStartedAt, + }); + } + if (result !== undefined) { + return result; + } + return this.#callFallbackRequest(url, options, callback); + }; + return requestWithFallback; + } + freeze() { + const options = this.#internals; + Object.freeze(options); + Object.freeze(options.hooks); + Object.freeze(options.hooks.afterResponse); + Object.freeze(options.hooks.beforeCache); + Object.freeze(options.hooks.beforeError); + Object.freeze(options.hooks.beforeRedirect); + Object.freeze(options.hooks.beforeRequest); + Object.freeze(options.hooks.beforeRetry); + Object.freeze(options.hooks.init); + Object.freeze(options.https); + Object.freeze(options.cacheOptions); + Object.freeze(options.agent); + Object.freeze(options.headers); + Object.freeze(options.timeout); + Object.freeze(options.retry); + Object.freeze(options.retry.errorCodes); + Object.freeze(options.retry.methods); + Object.freeze(options.retry.statusCodes); + } + #createHeadersProxy() { + return new Proxy(this.#internals.headers, { + get(target, property, receiver) { + if (typeof property === 'string') { + if (Reflect.has(target, property)) { + return Reflect.get(target, property, receiver); + } + const normalizedProperty = property.toLowerCase(); + return Reflect.get(target, normalizedProperty, receiver); + } + return Reflect.get(target, property, receiver); + }, + set: (target, property, value) => { + if (typeof property === 'string') { + const normalizedProperty = property.toLowerCase(); + assertValidHeaderName(normalizedProperty); + const isSuccess = Reflect.set(target, normalizedProperty, value); + if (isSuccess) { + markHeaderAsExplicit(this.#explicitHeaders, this.#trackedStateMutations, normalizedProperty); + } + return isSuccess; + } + return Reflect.set(target, property, value); + }, + deleteProperty: (target, property) => { + if (typeof property === 'string') { + const normalizedProperty = property.toLowerCase(); + const isSuccess = Reflect.deleteProperty(target, normalizedProperty); + if (isSuccess) { + this.#explicitHeaders.delete(normalizedProperty); + trackStateMutation(this.#trackedStateMutations, normalizedProperty); + } + return isSuccess; + } + return Reflect.deleteProperty(target, property); + }, + }); + } + #getFallbackRequestFunction() { + const url = this.#internals.url; + if (!url) { + return; + } + if (this.#internals.h2session) { + return http2_client.auto; + } + if (url.protocol === 'https:') { + if (this.#internals.http2) { + return http2_client.auto; + } + return external_node_https_.request; + } + return external_node_http_.request; + } + #callFallbackRequest(url, options, callback) { + const fallbackRequest = this.#getFallbackRequestFunction(); + if (!fallbackRequest) { + throw new TypeError('The request function must return a value'); + } + const fallbackResult = fallbackRequest(url, options, callback); + if (fallbackResult === undefined) { + throw new TypeError('The request function must return a value'); + } + if (distribution.promise(fallbackResult)) { + return this.#resolveFallbackRequestResult(fallbackResult); + } + return fallbackResult; + } + async #resolveRequestWithFallback(requestResult, { url, options, callback, requestStartedAt }) { + let resolvedRequestResult = requestResult; + if (this.#internals.timeout.request !== undefined) { + const remainingRequestTimeout = this.#internals.timeout.request - (Date.now() - requestStartedAt); + resolvedRequestResult = resolveWithRequestTimeout(requestResult, Math.max(0, remainingRequestTimeout), destroyLateRequestResult); + } + const result = await resolvedRequestResult; + if (result !== undefined) { + return result; + } + if (this.#internals.timeout.request !== undefined && options.timeout !== undefined) { + const remainingRequestTimeout = this.#internals.timeout.request - (Date.now() - requestStartedAt); + options.timeout = Math.min(options.timeout, Math.max(0, remainingRequestTimeout)); + } + return this.#callFallbackRequest(url, options, callback); + } + async #resolveFallbackRequestResult(fallbackResult) { + const resolvedFallbackResult = await fallbackResult; + if (resolvedFallbackResult === undefined) { + throw new TypeError('The request function must return a value'); + } + return resolvedFallbackResult; + } +} +const snapshotCrossOriginState = (options) => ({ + headers: { ...options.getInternalHeaders() }, + hadCookieJar: options.cookieJar !== undefined, + cookieWasExplicitlySet: options.isHeaderExplicitlySet('cookie'), + username: options.username, + password: options.password, + body: options.body, + json: options.json, + form: options.form, + bodySnapshot: cloneCrossOriginBodyValue(options.body), + jsonSnapshot: cloneCrossOriginBodyValue(options.json), + formSnapshot: cloneCrossOriginBodyValue(options.form), +}); +const cloneCrossOriginBodyValue = (value) => { + if (value === undefined || value === null || typeof value !== 'object') { + return value; + } + try { + return structuredClone(value); + } + catch { + return undefined; + } +}; +const isUnchangedCrossOriginBodyValue = (currentValue, previousValue, previousSnapshot) => { + if (currentValue !== previousValue) { + return false; + } + if (currentValue === undefined || currentValue === null || typeof currentValue !== 'object') { + return true; + } + if (previousSnapshot === undefined) { + return true; + } + return (0,external_node_util_.isDeepStrictEqual)(currentValue, previousSnapshot); +}; +const isCrossOriginCredentialChanged = (previousUrl, nextUrl, credential) => (nextUrl[credential] !== '' && nextUrl[credential] !== previousUrl[credential]); +const isBodyUnchanged = (options, previousState) => isUnchangedCrossOriginBodyValue(options.body, previousState.body, previousState.bodySnapshot) + && isUnchangedCrossOriginBodyValue(options.json, previousState.json, previousState.jsonSnapshot) + && isUnchangedCrossOriginBodyValue(options.form, previousState.form, previousState.formSnapshot); + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/response.js + + + +const decodedBodyCache = new WeakMap(); +// Intentionally uses TextDecoder so the UTF-8 path strips a leading BOM. +const textDecoder = new TextDecoder(); +const isUtf8Encoding = (encoding) => encoding === undefined || encoding.toLowerCase().replace('-', '') === 'utf8'; +const decodeUint8Array = (data, encoding) => { + if (isUtf8Encoding(encoding)) { + return textDecoder.decode(data); + } + return external_node_buffer_.Buffer.from(data).toString(encoding); +}; +const isResponseOk = (response) => { + const { statusCode } = response; + const { followRedirect } = response.request.options; + const shouldFollow = typeof followRedirect === 'function' ? followRedirect(response) : followRedirect; + const limitStatusCode = shouldFollow ? 299 : 399; + return (statusCode >= 200 && statusCode <= limitStatusCode) || statusCode === 304; +}; +/** +An error to be thrown when server response code is 2xx, and parsing body fails. +Includes a `response` property. +*/ +class ParseError extends RequestError { + name = 'ParseError'; + code = 'ERR_BODY_PARSE_FAILURE'; + constructor(error, response) { + const { options } = response.request; + super(`${error.message} in "${stripUrlAuth(options.url)}"`, error, response.request); + } +} +const cacheDecodedBody = (response, decodedBody) => { + decodedBodyCache.set(response, decodedBody); +}; +const parseBody = (response, responseType, parseJson, encoding) => { + const { rawBody } = response; + const cachedDecodedBody = decodedBodyCache.get(response); + try { + if (responseType === 'text') { + if (cachedDecodedBody !== undefined) { + return cachedDecodedBody; + } + return decodeUint8Array(rawBody, encoding); + } + if (responseType === 'json') { + if (rawBody.length === 0) { + return ''; + } + const text = cachedDecodedBody ?? decodeUint8Array(rawBody, encoding); + return parseJson(text); + } + if (responseType === 'buffer') { + return rawBody; + } + } + catch (error) { + throw new ParseError(error, response); + } + throw new ParseError({ + message: `Unknown body type '${responseType}'`, + name: 'Error', + }, response); +}; + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/utils/is-client-request.js +function isClientRequest(clientRequest) { + return clientRequest.writable && !clientRequest.writableEnded; +} +/* harmony default export */ const is_client_request = (isClientRequest); + +// EXTERNAL MODULE: external "node:diagnostics_channel" +var external_node_diagnostics_channel_ = __webpack_require__(53053); +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/diagnostics-channel.js + + +const channels = { + requestCreate: external_node_diagnostics_channel_.channel('got:request:create'), + requestStart: external_node_diagnostics_channel_.channel('got:request:start'), + responseStart: external_node_diagnostics_channel_.channel('got:response:start'), + responseEnd: external_node_diagnostics_channel_.channel('got:response:end'), + retry: external_node_diagnostics_channel_.channel('got:request:retry'), + error: external_node_diagnostics_channel_.channel('got:request:error'), + redirect: external_node_diagnostics_channel_.channel('got:response:redirect'), +}; +function generateRequestId() { + return (0,external_node_crypto_.randomUUID)(); +} +const publishToChannel = (channel, message) => { + if (channel.hasSubscribers) { + channel.publish(message); + } +}; +function publishRequestCreate(message) { + publishToChannel(channels.requestCreate, message); +} +function publishRequestStart(message) { + publishToChannel(channels.requestStart, message); +} +function publishResponseStart(message) { + publishToChannel(channels.responseStart, message); +} +function publishResponseEnd(message) { + publishToChannel(channels.responseEnd, message); +} +function publishRetry(message) { + publishToChannel(channels.retry, message); +} +function publishError(message) { + publishToChannel(channels.error, message); +} +function publishRedirect(message) { + publishToChannel(channels.redirect, message); +} + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/core/index.js + + + + + + + + + + + + + + + + + + + + + + + + +const supportsBrotli = distribution.string(external_node_process_.versions.brotli); +const core_supportsZstd = distribution.string(external_node_process_.versions.zstd); +const methodsWithoutBody = new Set(['GET', 'HEAD']); +const singleValueRequestHeaders = new Set([ + 'authorization', + 'content-length', + 'proxy-authorization', +]); +const cacheableStore = new WeakableMap(); +const redirectCodes = new Set([301, 302, 303, 307, 308]); + +const transientWriteErrorCodes = new Set(['EPIPE', 'ECONNRESET']); +const omittedPipedHeaders = new Set([ + 'host', + 'connection', + 'authorization', + 'cookie', + 'cookie2', + 'keep-alive', + 'proxy-authenticate', + 'proxy-authorization', + 'proxy-connection', + 'set-cookie', + 'set-cookie2', + 'te', + 'trailer', + 'transfer-encoding', + 'upgrade', +]); +// Track errors that have been processed by beforeError hooks to preserve custom error types +const errorsProcessedByHooks = new WeakSet(); +const proxiedRequestEvents = [ + 'socket', + 'connect', + 'continue', + 'information', + 'upgrade', +]; +const core_noop = () => { }; +const createPreRequestErrorTimings = () => { + const now = Date.now(); + return { + start: now, + error: now, + phases: { + total: 0, + }, + }; +}; +const serializeNativeFormDataBody = (form) => { + const response = new globalThis.Response(form); + return { + body: response.body, + contentType: response.headers.get('content-type') ?? 'multipart/form-data', + }; +}; +// A body is replayable only if iterating it again restarts from the beginning. +// Node streams, Web `ReadableStream`s, generators, and self-iterating (one-shot) iterators all yield their data only once, so they cannot be replayed on a redirect. +const isNonReplayableBody = (body) => distribution.nodeStream(body) + || body instanceof ReadableStream + || distribution.generator(body) + || (distribution.asyncIterable(body) && body[Symbol.asyncIterator]() === body) + || (distribution.iterable(body) && body[Symbol.iterator]() === body); +const isTransientWriteError = (error) => { + const { code } = error; + return typeof code === 'string' && transientWriteErrorCodes.has(code); +}; +const getConnectionListedHeaders = (headers) => { + const connectionListedHeaders = new Set(); + for (const [header, connectionHeader] of Object.entries(headers)) { + const normalizedHeader = header.toLowerCase(); + if (normalizedHeader !== 'connection' && normalizedHeader !== 'proxy-connection') { + continue; + } + const connectionHeaderValues = Array.isArray(connectionHeader) ? connectionHeader : [connectionHeader]; + for (const value of connectionHeaderValues) { + if (typeof value !== 'string') { + continue; + } + for (const token of value.split(',')) { + const normalizedToken = token.trim().toLowerCase(); + if (normalizedToken.length > 0) { + connectionListedHeaders.add(normalizedToken); + } + } + } + } + return connectionListedHeaders; +}; +const normalizeError = (error) => { + if (error instanceof globalThis.Error) { + return error; + } + if (distribution.object(error)) { + const errorLike = error; + const message = typeof errorLike.message === 'string' ? errorLike.message : 'Non-error object thrown'; + const normalizedError = new globalThis.Error(message, { cause: error }); + if (typeof errorLike.stack === 'string') { + normalizedError.stack = errorLike.stack; + } + if (typeof errorLike.code === 'string') { + normalizedError.code = errorLike.code; + } + if (typeof errorLike.input === 'string') { + normalizedError.input = errorLike.input; + } + return normalizedError; + } + return new globalThis.Error(String(error)); +}; +const getSanitizedUrl = (options) => options?.url ? stripUrlAuth(options.url) : ''; +const makeProgress = (transferred, total) => { + let percent = 0; + if (total === transferred) { + // Known-size complete transfers (including 0/0) should report 100% rather than 0%. + percent = 1; + } + else if (total) { + percent = transferred / total; + } + return { percent, transferred, total }; +}; +class Request extends external_node_stream_.Duplex { + // @ts-expect-error - Ignoring for now. + ['constructor']; + _noPipe; + // @ts-expect-error https://github.com/microsoft/TypeScript/issues/9568 + options; + response; + requestUrl; + redirectUrls = []; + retryCount = 0; + _stopReading = false; + _stopRetry; + _downloadedSize = 0; + _uploadedSize = 0; + _pipedServerResponses = new Set(); + _request; + _responseSize; + _bodySize; + _nativeFormDataBody; + _unproxyEvents; + _triggerRead = false; + _jobs = []; + _cancelTimeouts; + _abortListenerDisposer; + _flushed = false; + _aborted = false; + _expectedContentLength; + _compressedBytesCount; + _skipRequestEndInFinal = false; + _hasWrittenBody = false; + _hasWritableBody = false; + _discardBodyWrites = false; + _incrementalDecode; + _requestId = generateRequestId(); + // We need this because `this._request` if `undefined` when using cache + _requestInitialized = false; + constructor(url, options, defaults) { + super({ + // Don't destroy immediately, as the error may be emitted on unsuccessful retry + autoDestroy: false, + // It needs to be zero because we're just proxying the data to another stream + highWaterMark: 0, + }); + this.on('pipe', (source) => { + if (this.options.copyPipedHeaders && source?.headers) { + const connectionListedHeaders = getConnectionListedHeaders(source.headers); + for (const [header, value] of Object.entries(source.headers)) { + const normalizedHeader = header.toLowerCase(); + if (omittedPipedHeaders.has(normalizedHeader) || connectionListedHeaders.has(normalizedHeader)) { + continue; + } + if (!this.options.shouldCopyPipedHeader(normalizedHeader)) { + continue; + } + this.options.setPipedHeader(normalizedHeader, value); + } + } + }); + this.on('newListener', event => { + if (event === 'retry' && this.listenerCount('retry') > 0) { + throw new Error('A retry listener has been attached already.'); + } + }); + try { + this.options = new Options(url, options, defaults); + if (!this.options.url) { + if (this.options.prefixUrl === '') { + throw new TypeError('Missing `url` property'); + } + this.options.url = ''; + } + this.requestUrl = this.options.url; + // Publish request creation event + publishRequestCreate({ + requestId: this._requestId, + url: getSanitizedUrl(this.options), + method: this.options.method, + }); + } + catch (error) { + const { options } = error; + if (options) { + this.options = options; + } + this.flush = async () => { + this.flush = async () => { }; + // Defer error emission to next tick to allow user to attach error handlers + external_node_process_.nextTick(() => { + // _beforeError requires options to access retry logic and hooks + if (this.options) { + this._beforeError(normalizeError(error)); + } + else { + // Options is undefined, skip _beforeError and destroy directly + const normalizedError = normalizeError(error); + const requestError = normalizedError instanceof RequestError ? normalizedError : new RequestError(normalizedError.message, normalizedError, this); + this.destroy(requestError); + } + }); + }; + return; + } + // Important! If you replace `body` in a handler with another stream, make sure it's readable first. + // The below is run only once. + const { body } = this.options; + if (distribution.nodeStream(body)) { + body.once('error', this._onBodyError); + } + } + async flush() { + if (this._flushed) { + return; + } + this._flushed = true; + try { + this._attachAbortListener(); + if (this.destroyed) { + return; + } + await this._finalizeBody(); + if (this.destroyed) { + return; + } + this._hasWritableBody = this._canWriteBody(); + await this._makeRequest(); + if (this.destroyed) { + this._request?.destroy(); + return; + } + // Queued writes etc. + for (const job of this._jobs) { + job(); + } + // Prevent memory leak + this._jobs.length = 0; + this._requestInitialized = true; + } + catch (error) { + this._beforeError(normalizeError(error)); + } + } + _beforeError(error) { + if (this._stopReading) { + return; + } + const { response, options } = this; + const attemptCount = this.retryCount + (error.name === 'RetryError' ? 0 : 1); + this._stopReading = true; + if (error instanceof timed_out_TimeoutError) { + error = new TimeoutError(error, this.timings ?? createPreRequestErrorTimings(), this); + } + else if (!(error instanceof RequestError)) { + error = new RequestError(error.message, error, this); + } + const typedError = error; + void (async () => { + // Node.js parser is really weird. + // It emits post-request Parse Errors on the same instance as previous request. WTF. + // Therefore, we need to check if it has been destroyed as well. + if (response?.readable && !response.rawBody && !this._request?.socket?.destroyed) { + // @types/node has incorrect typings. `setEncoding` accepts `null` as well. + response.setEncoding(this.readableEncoding); + await this._setRawBody(response); + } + if (response?.rawBody && response.body === undefined) { + try { + response.body = decodeUint8Array(response.rawBody, options.encoding); + } + catch { + // Preserve the original request error when decoding its response body also fails. + } + } + if (this.listenerCount('retry') !== 0) { + let backoff; + try { + let retryAfter; + if (response && 'retry-after' in response.headers) { + retryAfter = Number(response.headers['retry-after']); + if (Number.isNaN(retryAfter)) { + retryAfter = Date.parse(response.headers['retry-after']) - Date.now(); + } + else { + retryAfter *= 1000; + } + if (retryAfter <= 0) { + retryAfter = 1; + } + } + const retryOptions = options.retry; + const computedValue = calculate_retry_delay({ + attemptCount, + retryOptions, + error: typedError, + retryAfter, + computedValue: retryOptions.maxRetryAfter ?? options.timeout.request ?? Number.POSITIVE_INFINITY, + }); + // When enforceRetryRules is true, respect the retry rules (limit, methods, statusCodes, errorCodes) + // before calling the user's calculateDelay function. If computedValue is 0 (meaning retry is not allowed + // based on these rules), skip calling calculateDelay entirely. + // When false, always call calculateDelay, allowing it to override retry decisions. + if (retryOptions.enforceRetryRules && computedValue === 0) { + backoff = 0; + } + else { + backoff = await retryOptions.calculateDelay({ + attemptCount, + retryOptions, + error: typedError, + retryAfter, + computedValue, + }); + } + } + catch (error_) { + const normalizedError = normalizeError(error_); + void this._error(new RequestError(normalizedError.message, normalizedError, this)); + return; + } + if (backoff) { + await new Promise(resolve => { + const timeout = setTimeout(resolve, backoff); + this._stopRetry = () => { + clearTimeout(timeout); + resolve(); + }; + }); + // Something forced us to abort the retry + if (this.destroyed) { + return; + } + // Capture body BEFORE hooks run to detect reassignment + const bodyBeforeHooks = this.options.body; + try { + for (const hook of this.options.hooks.beforeRetry) { + // eslint-disable-next-line no-await-in-loop + await hook(typedError, this.retryCount + 1); + } + } + catch (error_) { + const normalizedError = normalizeError(error_); + void this._error(new RequestError(normalizedError.message, normalizedError, this)); + return; + } + // Something forced us to abort the retry + if (this.destroyed) { + return; + } + // Preserve stream body reassigned in beforeRetry hooks. + const bodyAfterHooks = this.options.body; + const bodyWasReassigned = bodyBeforeHooks !== bodyAfterHooks; + // Resource cleanup and preservation logic for retry with body reassignment. + // The Promise wrapper (as-promise/index.ts) compares body identity to detect consumed streams, + // so we must preserve the body reference across destroy(). However, destroy() calls _destroy() + // which destroys this.options.body, creating a complex dance of clear/restore operations. + // + // Key constraints: + // 1. If body was reassigned, we must NOT destroy the NEW stream (it will be used for retry) + // 2. If body was reassigned, we MUST destroy the OLD stream to prevent memory leaks + // 3. We must restore the body reference after destroy() for identity checks in promise wrapper + // 4. We cannot use the normal setter after destroy() because it validates stream readability + try { + if (bodyWasReassigned) { + const oldBody = bodyBeforeHooks; + // Temporarily clear body to prevent destroy() from destroying the new stream + this.options.body = undefined; + this.destroy(); + // Clean up the old stream resource if it's a stream and different from new body + // (edge case: if old and new are same stream object, don't destroy it) + if (distribution.nodeStream(oldBody) && oldBody !== bodyAfterHooks) { + oldBody.destroy(); + } + // Restore new body for promise wrapper's identity check + if (distribution.nodeStream(bodyAfterHooks) && (bodyAfterHooks.readableEnded || bodyAfterHooks.destroyed)) { + throw new TypeError('The reassigned stream body must be readable. Ensure you provide a fresh, readable stream in the beforeRetry hook.'); + } + this.options.body = bodyAfterHooks; + } + else { + // Body wasn't reassigned - use normal destroy flow which handles body cleanup + this.destroy(); + // Note: We do NOT restore the body reference here. The stream was destroyed by _destroy() + // and should not be accessed. The promise wrapper will see that body identity hasn't changed + // and will detect it's a consumed stream, which is the correct behavior. + } + } + catch (error_) { + const normalizedError = normalizeError(error_); + void this._error(new RequestError(normalizedError.message, normalizedError, this)); + return; + } + // Publish retry event + publishRetry({ + requestId: this._requestId, + retryCount: this.retryCount + 1, + error: typedError, + delay: backoff, + }); + this.emit('retry', this.retryCount + 1, error, (updatedOptions) => { + const request = new Request(undefined, updatedOptions, options); + request.retryCount = this.retryCount + 1; + external_node_process_.nextTick(() => { + void request.flush(); + }); + return request; + }); + return; + } + } + void this._error(typedError); + })(); + } + _read() { + this._triggerRead = true; + const { response } = this; + if (response && !this._stopReading) { + // We cannot put this in the `if` above + // because `.read()` also triggers the `end` event + if (response.readableLength) { + this._triggerRead = false; + } + let data; + while ((data = response.read()) !== null) { + this._downloadedSize += data.length; // eslint-disable-line @typescript-eslint/restrict-plus-operands + if (this._incrementalDecode) { + try { + const decodedChunk = typeof data === 'string' ? data : this._incrementalDecode.decoder.decode(data, { stream: true }); + if (decodedChunk.length > 0) { + this._incrementalDecode.chunks.push(decodedChunk); + } + } + catch { + this._incrementalDecode = undefined; + } + } + const progress = this.downloadProgress; + if (progress.percent < 1) { + this.emit('downloadProgress', progress); + } + if (this._stopReading) { + return; + } + this.push(data); + if (this._stopReading) { + return; + } + } + } + } + _write(chunk, encoding, callback) { + const write = () => { + if (this._discardBodyWrites) { + callback(); + return; + } + this._hasWrittenBody = true; + this._writeRequest(chunk, encoding, callback); + }; + if (this._requestInitialized) { + write(); + } + else { + this._jobs.push(write); + } + } + _final(callback) { + const endRequest = () => { + if (this._discardBodyWrites) { + this._hasWritableBody = false; + callback(); + return; + } + if (this._skipRequestEndInFinal) { + this._skipRequestEndInFinal = false; + callback(); + return; + } + const request = this._request; + // We need to check if `this._request` is present, + // because it isn't when we use cache. + if (!request || request.destroyed) { + this._hasWritableBody = false; + callback(); + return; + } + request.end((error) => { + // The request has been destroyed before `_final` finished. + // See https://github.com/nodejs/node/issues/39356 + if (request?._writableState?.errored) { + return; + } + this._hasWritableBody = false; + if (error) { + // `ClientRequest.end()` can report the same failure as the request's `error` event. Route it through Got's retry handling without completing `_final`, so this Duplex does not finish a failed upload. + this._beforeError(error); + return; + } + this._emitUploadComplete(request); + callback(); + }); + }; + if (this._requestInitialized) { + endRequest(); + } + else { + this._jobs.push(endRequest); + } + } + _destroy(error, callback) { + this._stopReading = true; + this.flush = async () => { }; + // Prevent further retries + this._stopRetry?.(); + this._cancelTimeouts?.(); + this._abortListenerDisposer?.[Symbol.dispose](); + this._destroyInFlightAlpnSocket(); + if (this.options) { + const { body } = this.options; + if (distribution.nodeStream(body)) { + body.destroy(); + } + } + if (this._request) { + this._request.destroy(); + } + // Workaround: http-timer only sets timings.end when the response emits 'end'. + // When a stream is destroyed before completion, the 'end' event may not fire, + // leaving timings.end undefined. This should ideally be fixed in http-timer + // by listening to the 'close' event, but we handle it here for now. + // Only set timings.end if there was no error or abort (to maintain semantic correctness). + const timings = this._request?.timings; + if (timings && distribution.undefined(timings.end) && !distribution.undefined(timings.response) && distribution.undefined(timings.error) && distribution.undefined(timings.abort)) { + timings.end = Date.now(); + if (distribution.undefined(timings.phases.total)) { + timings.phases.download = timings.end - timings.response; + timings.phases.total = timings.end - timings.start; + } + } + // Preserve custom errors returned by beforeError hooks. + // For other errors, wrap non-RequestError instances for consistency. + if (error !== null) { + const processedByHooks = error instanceof Error && errorsProcessedByHooks.has(error); + if (!processedByHooks && !(error instanceof RequestError)) { + error = error instanceof Error + ? new RequestError(error.message, error, this) + : new RequestError(String(error), {}, this); + } + } + callback(error); + } + pipe(destination, options) { + if (destination instanceof external_node_http_.ServerResponse) { + this._pipedServerResponses.add(destination); + } + return super.pipe(destination, options); + } + unpipe(destination) { + if (destination instanceof external_node_http_.ServerResponse) { + this._pipedServerResponses.delete(destination); + } + super.unpipe(destination); + return this; + } + _attachAbortListener() { + if (this._abortListenerDisposer) { + return; + } + const { signal } = this.options; + if (!signal) { + return; + } + const abort = () => { + this._destroyInFlightAlpnSocket(); + // See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static#return_value + if (signal.reason?.name === 'TimeoutError') { + this.destroy(new TimeoutError(signal.reason, this.timings ?? createPreRequestErrorTimings(), this)); + } + else { + this.destroy(new AbortError(this)); + } + }; + if (signal.aborted) { + abort(); + } + else { + this._abortListenerDisposer = (0,external_node_events_.addAbortListener)(signal, abort); + } + } + _destroyInFlightAlpnSocket() { + this._requestOptions?._alpnSocket?.destroy(); + } + _shouldIncrementallyDecodeBody() { + const { responseType, encoding } = this.options; + return Boolean(this._noPipe) + && (responseType === 'text' || responseType === 'json') + && isUtf8Encoding(encoding); + } + _checkContentLengthMismatch() { + if (this.options.strictContentLength && this._expectedContentLength !== undefined) { + // Use compressed bytes count when available (for compressed responses), + // otherwise use _downloadedSize (for uncompressed responses) + const actualSize = this._compressedBytesCount ?? this._downloadedSize; + if (actualSize !== this._expectedContentLength) { + this._beforeError(new ReadError({ + message: `Content-Length mismatch: expected ${this._expectedContentLength} bytes, received ${actualSize} bytes`, + name: 'Error', + code: 'ERR_HTTP_CONTENT_LENGTH_MISMATCH', + }, this)); + return true; + } + } + return false; + } + async _finalizeBody() { + const { options } = this; + const headers = options.getInternalHeaders(); + const isForm = !distribution.undefined(options.form); + // eslint-disable-next-line @typescript-eslint/naming-convention + const isJSON = !distribution.undefined(options.json); + const isBody = !distribution.undefined(options.body); + const cannotHaveBody = !this._methodCanHaveBody; + if (isForm || isJSON || isBody) { + if (cannotHaveBody) { + throw new TypeError(`The \`${options.method}\` method cannot be used with a body`); + } + // Serialize body + const noContentType = !distribution.string(headers['content-type']); + if (isBody) { + // Native FormData + if (options.body instanceof FormData) { + const { body, contentType } = serializeNativeFormDataBody(options.body); + this._nativeFormDataBody = { + form: options.body, + body, + contentTypeWasGenerated: noContentType, + }; + if (noContentType) { + headers['content-type'] = contentType; + } + options.body = body; + } + else if (Object.prototype.toString.call(options.body) === '[object FormData]') { + throw new TypeError('Non-native FormData is not supported. Use globalThis.FormData instead.'); + } + } + else if (isForm) { + if (noContentType) { + headers['content-type'] = 'application/x-www-form-urlencoded'; + } + const { form } = options; + options.form = undefined; + options.body = (new URLSearchParams(form)).toString(); + } + else { + if (noContentType) { + headers['content-type'] = 'application/json'; + } + const { json } = options; + options.json = undefined; + options.body = options.stringifyJson(json); + } + const uploadBodySize = getBodySize(options.body, headers); + // See https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD send a Content-Length in a request message when + // no Transfer-Encoding is sent and the request method defines a meaning + // for an enclosed payload body. For example, a Content-Length header + // field is normally sent in a POST request even when the value is 0 + // (indicating an empty payload body). A user agent SHOULD NOT send a + // Content-Length header field when the request message does not contain + // a payload body and the method semantics do not anticipate such a + // body. + if (distribution.undefined(headers['content-length']) && distribution.undefined(headers['transfer-encoding']) && !cannotHaveBody && !distribution.undefined(uploadBodySize)) { + headers['content-length'] = String(uploadBodySize); + } + } + if (options.responseType === 'json' && !('accept' in headers)) { + headers.accept = 'application/json'; + } + this._bodySize = Number(headers['content-length']) || undefined; + } + async _onResponseBase(response) { + // This will be called e.g. when using cache so we need to check if this request has been aborted. + if (this.isAborted) { + return; + } + const { options } = this; + const { url } = options; + const nativeResponse = response; + const statusCode = response.statusCode; + const { method } = options; + const redirectLocationHeader = response.headers.location; + const redirectLocation = Array.isArray(redirectLocationHeader) ? redirectLocationHeader[0] : redirectLocationHeader; + const isRedirect = Boolean(redirectLocation && redirectCodes.has(statusCode)); + // Skip decompression for responses that must not have bodies per RFC 9110: + // - HEAD responses (any status code) + // - 1xx (Informational): 100, 101, 102, 103, etc. + // - 204 (No Content) + // - 205 (Reset Content) + // - 304 (Not Modified) + const hasNoBody = method === 'HEAD' + || (statusCode >= 100 && statusCode < 200) + || statusCode === 204 + || statusCode === 205 + || statusCode === 304; + const prepareResponse = (response) => { + if (!Object.hasOwn(response, 'headers')) { + Object.defineProperty(response, 'headers', { + value: response.headers, + enumerable: true, + writable: true, + configurable: true, + }); + } + response.statusMessage ||= external_node_http_.STATUS_CODES[statusCode]; // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing -- The status message can be empty. + response.url = stripUrlAuth(options.url); + response.requestUrl = this.requestUrl; + response.redirectUrls = this.redirectUrls; + response.request = this; + response.isFromCache = nativeResponse.fromCache ?? false; + response.ip = this.ip; + response.retryCount = this.retryCount; + response.ok = isResponseOk(response); + return response; + }; + let typedResponse = prepareResponse(response); + // Redirect responses that will be followed are drained raw. Decompressing them can + // turn an irrelevant redirect body into a client-side failure or decompression DoS. + const shouldFollowRedirect = isRedirect && (typeof options.followRedirect === 'function' ? options.followRedirect(typedResponse) : options.followRedirect); + if (options.decompress && !hasNoBody && !shouldFollowRedirect) { + response = decompressResponse(response); + typedResponse = prepareResponse(response); + // When strictContentLength is enabled, track the compressed bytes emitted by the native response. + if (options.strictContentLength && response !== nativeResponse) { + this._compressedBytesCount = 0; + nativeResponse.on('data', (chunk) => { + this._compressedBytesCount += byteLength(chunk); + }); + } + } + // `decompressResponse` wraps the response stream when it decompresses, + // so `response !== nativeResponse` indicates decompression happened. + const wasDecompressed = response !== nativeResponse; + this._responseSize = Number(response.headers['content-length']) || undefined; + this.response = typedResponse; + // eslint-disable-next-line @typescript-eslint/naming-convention + this._incrementalDecode = this._shouldIncrementallyDecodeBody() ? { decoder: new globalThis.TextDecoder('utf8', { ignoreBOM: true }), chunks: [] } : undefined; + // Publish response start event + publishResponseStart({ + requestId: this._requestId, + url: typedResponse.url, + statusCode, + headers: response.headers, + isFromCache: typedResponse.isFromCache, + }); + response.once('error', (error) => { + // Node synthesizes ECONNRESET for close-delimited responses after all body + // bytes have been delivered. Only ignore that late synthetic error on the + // native response. Wrapped decompression streams surface real checksum and + // truncation failures after the underlying response has completed. + if (!wasDecompressed + && response.complete + && this._responseSize === undefined + && error.code === 'ECONNRESET') { + return; + } + this._aborted = true; + this._beforeError(new ReadError(error, this)); + }); + response.once('aborted', () => { + // Without Content-Length, connection close is the intended EOF signal (RFC 9110 §8.6), + // not a premature abort. For wrapped decompression streams, rely on the native + // response completion state because the wrapper strips `content-length`. + if (this._responseSize === undefined && nativeResponse.complete) { + return; + } + this._aborted = true; + // Check if there's a content-length mismatch to provide a more specific error + if (!this._checkContentLengthMismatch()) { + this._beforeError(new ReadError({ + name: 'Error', + message: 'The server aborted pending request', + code: 'ECONNRESET', + }, this)); + } + }); + let canFinalizeResponse = false; + const handleResponseEnd = () => { + if (!canFinalizeResponse + || !response.readableEnded) { + return; + } + canFinalizeResponse = false; + if (this._stopReading) { + return; + } + // Validate content-length if it was provided + // Per RFC 9112: "If the sender closes the connection before the indicated number + // of octets are received, the recipient MUST consider the message to be incomplete" + if (this._checkContentLengthMismatch()) { + return; + } + this._responseSize = this._downloadedSize; + this.emit('downloadProgress', this.downloadProgress); + // Publish response end event + publishResponseEnd({ + requestId: this._requestId, + url: typedResponse.url, + statusCode, + bodySize: this._downloadedSize, + timings: this.timings, + }); + this.push(null); + }; + if (!shouldFollowRedirect) { + // `set-cookie` handling below awaits the cookie jar. A fast response can fully + // end during that await, so we need to observe `end` early without completing + // the outward stream until cookie handling has finished. + response.once('end', handleResponseEnd); + } + const rawCookies = response.headers['set-cookie']; + const responseRawBodyPromise = this._noPipe + && distribution.object(options.cookieJar) + && rawCookies !== undefined + && !shouldFollowRedirect + ? this._setRawBody(response) + : undefined; + if (distribution.object(options.cookieJar) && rawCookies) { + let promises = rawCookies.map(async (rawCookie) => options.cookieJar.setCookie(rawCookie, url.toString())); + if (options.ignoreInvalidCookies) { + promises = promises.map(async (promise) => { + try { + await promise; + } + catch { } + }); + } + try { + await Promise.all(promises); + } + catch (error) { + if (responseRawBodyPromise) { + await responseRawBodyPromise; + } + this._beforeError(normalizeError(error)); + return; + } + } + // The above is running a promise, therefore we need to check if this request has been aborted yet again. + if (this.isAborted) { + return; + } + if (shouldFollowRedirect) { + // We're being redirected, we don't care about the response. + // It'd be best to abort the request, but we can't because + // we would have to sacrifice the TCP connection. We don't want that. + response.resume(); + this._cancelTimeouts?.(); + this._unproxyEvents?.(); + if (this.redirectUrls.length >= options.maxRedirects) { + this._beforeError(new MaxRedirectsError(this)); + return; + } + this._request = undefined; + // Reset progress for the new request. + this._downloadedSize = 0; + this._uploadedSize = 0; + const updatedOptions = new Options(undefined, undefined, this.options); + try { + // We need this in order to support UTF-8 + const redirectBuffer = external_node_buffer_.Buffer.from(redirectLocation, 'binary').toString(); + const redirectUrl = new URL(redirectBuffer, url); + const currentUnixSocketPath = getUnixSocketPath(url); + const redirectUnixSocketPath = getUnixSocketPath(redirectUrl); + if (redirectUrl.protocol === 'unix:' && redirectUnixSocketPath === undefined) { + this._beforeError(new RequestError('Cannot redirect to UNIX socket', {}, this)); + return; + } + // Relative redirects on the same socket are fine, but a redirect must not switch to a different local socket. + if (redirectUnixSocketPath !== undefined && currentUnixSocketPath !== redirectUnixSocketPath) { + this._beforeError(new RequestError('Cannot redirect to UNIX socket', {}, this)); + return; + } + // Redirecting to a different site, clear sensitive data. + // For UNIX sockets, different socket paths are also different origins. + const isDifferentOrigin = redirectUrl.origin !== url.origin + || currentUnixSocketPath !== redirectUnixSocketPath; + const serverRequestedGet = statusCode === 303 && updatedOptions.method !== 'GET' && updatedOptions.method !== 'HEAD'; + // Avoid forwarding a POST body to a different origin on historical 301/302 redirects. + const crossOriginRequestedGet = isDifferentOrigin + && (statusCode === 301 || statusCode === 302) + && updatedOptions.method === 'POST'; + const canRewrite = statusCode !== 307 && statusCode !== 308; + const userRequestedGet = updatedOptions.methodRewriting && canRewrite; + const shouldDropBody = serverRequestedGet || crossOriginRequestedGet || userRequestedGet; + if (shouldDropBody) { + updatedOptions.method = 'GET'; + this._dropBody(updatedOptions); + } + else if (isDifferentOrigin + && canRewrite + && updatedOptions.method !== 'QUERY' + && this._hasBodyForRedirect(updatedOptions)) { + this._dropBody(updatedOptions); + } + if (isDifferentOrigin) { + // On cross-origin redirects, strip sensitive headers and any credentials + // embedded in the redirect URL itself to prevent a malicious server from + // leaking them to a third party. 307/308 redirects preserve the method and replayable body per RFC; QUERY does the same on 301/302. + updatedOptions.h2session = undefined; + this._stripCrossOriginState(updatedOptions, redirectUrl); + } + else { + redirectUrl.username = updatedOptions.username; + redirectUrl.password = updatedOptions.password; + } + // Redirect URLs are resolved internally. Restore the user option before hooks run so hook mutations still honor it. + const { allowAbsoluteUrls } = updatedOptions; + try { + updatedOptions.allowAbsoluteUrls = true; + updatedOptions.url = redirectUrl; + } + finally { + updatedOptions.allowAbsoluteUrls = allowAbsoluteUrls; + } + this.redirectUrls.push(redirectUrl); + const boundaryBeforeRedirectHooks = getUrlPrefixBoundary(updatedOptions); + const bodyBeforeRedirectHooks = updatedOptions.body; + const h2sessionBeforeRedirectHooks = updatedOptions.h2session; + const preHookState = isDifferentOrigin + ? undefined + : { + ...snapshotCrossOriginState(updatedOptions), + url: new URL(updatedOptions.url), + }; + const changedState = await updatedOptions.trackStateMutations(async (changedState) => { + for (const hook of updatedOptions.hooks.beforeRedirect) { + // eslint-disable-next-line no-await-in-loop + await hook(updatedOptions, typedResponse); + } + return changedState; + }); + if (hasUrlOrPrefixUrlBoundaryChanged(updatedOptions, updatedOptions.url, boundaryBeforeRedirectHooks)) { + assertUrlHasSameOriginAsPrefixUrlIfNeeded(updatedOptions, updatedOptions.url); + } + updatedOptions.clearUnchangedCookieHeader(preHookState, changedState); + const nativeFormDataBody = this._nativeFormDataBody; + const mustReplayBodyOnRedirect = statusCode === 307 || statusCode === 308 || updatedOptions.method === 'QUERY'; + if (mustReplayBodyOnRedirect) { + const bodyUnchangedByHooks = updatedOptions.body === bodyBeforeRedirectHooks; + const wasNonReplayable = isNonReplayableBody(bodyBeforeRedirectHooks); + if (!bodyUnchangedByHooks && wasNonReplayable) { + // A hook supplied a fresh body, so dispose of the original non-replayable one. + this._destroyBody(bodyBeforeRedirectHooks); + } + else if (bodyUnchangedByHooks + && nativeFormDataBody !== undefined + && updatedOptions.body === nativeFormDataBody.body) { + // Native FormData generates a fresh stream and boundary, so re-serialize it to replay the upload. + const { body, contentType } = serializeNativeFormDataBody(nativeFormDataBody.form); + nativeFormDataBody.body = body; + updatedOptions.body = body; + if (changedState.has('content-type')) { + nativeFormDataBody.contentTypeWasGenerated = false; + } + else if (nativeFormDataBody.contentTypeWasGenerated) { + updatedOptions.setInternalHeader('content-type', contentType); + } + } + else if (bodyUnchangedByHooks + && (wasNonReplayable || (distribution.undefined(updatedOptions.body) && (this._hasWrittenBody || this._hasWritableBody)))) { + // Body-preserving redirects must replay the body, so follow the HTTP spec and other clients by failing for unchanged non-replayable bodies. Hooks may supply a fresh body. + this._dropBody(updatedOptions); + this._beforeError(new RequestError('Cannot follow redirect with a non-replayable body', {}, this)); + return; + } + } + // If a beforeRedirect hook changed the URL to a different origin, + // strip sensitive headers that were preserved for the original origin. + // When isDifferentOrigin was already true, headers were already stripped above. + if (!isDifferentOrigin) { + const state = preHookState; + const hookUrl = updatedOptions.url; + const hookChangedOrigin = !isSameOrigin(state.url, hookUrl); + if (hookChangedOrigin + && (statusCode === 301 || statusCode === 302) + && updatedOptions.method === 'POST') { + updatedOptions.method = 'GET'; + this._dropBody(updatedOptions); + } + if (hookChangedOrigin) { + if (updatedOptions.h2session === h2sessionBeforeRedirectHooks) { + updatedOptions.h2session = undefined; + } + if (canRewrite + && updatedOptions.method !== 'QUERY' + && this._hasUnchangedBodyForRedirect(updatedOptions, state, changedState)) { + this._dropBody(updatedOptions); + } + this._stripUnchangedCrossOriginState(updatedOptions, hookUrl, { + ...state, + changedState, + preserveUsername: hasExplicitCredentialInUrlChange(changedState, hookUrl, 'username') + || isCrossOriginCredentialChanged(state.url, hookUrl, 'username'), + preservePassword: hasExplicitCredentialInUrlChange(changedState, hookUrl, 'password') + || isCrossOriginCredentialChanged(state.url, hookUrl, 'password'), + }); + } + } + // Publish redirect event + publishRedirect({ + requestId: this._requestId, + fromUrl: stripUrlAuth(url), + toUrl: stripUrlAuth(updatedOptions.url), + statusCode, + }); + this.emit('redirect', updatedOptions, typedResponse); + this.options = updatedOptions; + await this._makeRequest(); + } + catch (error) { + this._beforeError(normalizeError(error)); + return; + } + return; + } + // `HTTPError`s always have `error.response.body` defined. + // Therefore, we cannot retry if `options.throwHttpErrors` is false. + // On the last retry, if `options.throwHttpErrors` is false, we would need to return the body, + // but that wouldn't be possible since the body would be already read in `error.response.body`. + if (options.isStream && options.throwHttpErrors && !isResponseOk(typedResponse)) { + this._beforeError(new HTTPError(typedResponse)); + return; + } + // Store the expected content-length from the native response for validation. + // This is the content-length before decompression, which is what actually gets transferred. + // Skip storing for responses that shouldn't have bodies per RFC 9110. + // When decompression occurs, only store if strictContentLength is enabled. + if (!hasNoBody && (!wasDecompressed || options.strictContentLength)) { + const contentLengthHeader = nativeResponse.headers['content-length']; + if (contentLengthHeader !== undefined) { + const expectedLength = Number(contentLengthHeader); + if (!Number.isNaN(expectedLength) && expectedLength >= 0) { + this._expectedContentLength = expectedLength; + } + } + } + this.emit('downloadProgress', this.downloadProgress); + response.on('readable', () => { + if (this._triggerRead) { + this._read(); + } + }); + this.on('resume', () => { + response.resume(); + }); + this.on('pause', () => { + response.pause(); + }); + if (this._noPipe) { + const captureFromResponse = response.readableEnded || responseRawBodyPromise !== undefined; + if (!captureFromResponse) { + canFinalizeResponse = true; + handleResponseEnd(); + } + const success = responseRawBodyPromise + ? await responseRawBodyPromise + : await this._setRawBody(captureFromResponse ? response : this); + if (captureFromResponse) { + canFinalizeResponse = true; + handleResponseEnd(); + } + if (success) { + this.emit('response', response); + } + return; + } + this.emit('response', response); + for (const destination of this._pipedServerResponses) { + if (destination.headersSent) { + continue; + } + for (const key in response.headers) { + if (Object.hasOwn(response.headers, key)) { + const value = response.headers[key]; + // When decompression occurred, skip content-encoding and content-length + // as they refer to the compressed data, not the decompressed stream. + if (wasDecompressed && (key === 'content-encoding' || key === 'content-length')) { + continue; + } + // Skip if value is undefined + if (value !== undefined) { + destination.setHeader(key, value); + } + } + } + destination.statusCode = statusCode; + } + if (this._triggerRead) { + this._read(); + } + canFinalizeResponse = true; + handleResponseEnd(); + } + async _setRawBody(from = this) { + try { + // Errors are emitted via the `error` event + const fromArray = await from.toArray(); + const hasNonStringChunk = fromArray.some(chunk => typeof chunk !== 'string'); + const rawBody = hasNonStringChunk + ? concatUint8Arrays(fromArray.map(chunk => typeof chunk === 'string' ? stringToUint8Array(chunk) : chunk)) + : stringToUint8Array(fromArray.join('')); + const shouldUseIncrementalDecodedBody = from === this && this._incrementalDecode !== undefined; + // On retry Request is destroyed with no error, therefore the above will successfully resolve. + // So in order to check if this was really successful, we need to check if it has been properly ended. + if (!this.isAborted && this.response) { + this.response.rawBody = rawBody; + if (from !== this) { + this._downloadedSize = rawBody.byteLength; + } + if (shouldUseIncrementalDecodedBody) { + try { + const { decoder, chunks } = this._incrementalDecode; + const finalDecodedChunk = decoder.decode(); + if (finalDecodedChunk.length > 0) { + chunks.push(finalDecodedChunk); + } + cacheDecodedBody(this.response, chunks.join('')); + } + catch { } + } + return true; + } + } + catch { } + finally { + this._incrementalDecode = undefined; + } + return false; + } + async _onResponse(response) { + try { + await this._onResponseBase(response); + } + catch (error) { + /* istanbul ignore next: better safe than sorry */ + this._beforeError(normalizeError(error)); + } + } + _onRequest(request) { + const { options } = this; + const { timeout, url } = options; + // Publish request start event + publishRequestStart({ + requestId: this._requestId, + url: getSanitizedUrl(this.options), + method: options.method, + headers: options.headers, + }); + utils_timer(request); + const { isGotHttp2Request } = request; + let timeoutDelays = timeout; + if (isGotHttp2Request) { + const { socket: _socket, ...http2TimeoutDelays } = timeout; + timeoutDelays = http2TimeoutDelays; + } + this._cancelTimeouts = timedOut(request, timeoutDelays, url); + let lastRequestError; + const responseEventName = options.cache ? 'cacheableResponse' : 'response'; + request.once(responseEventName, (response) => { + void this._onResponse(response); + }); + const emitRequestError = (error) => { + this._aborted = true; + // Force clean-up, because some packages (e.g. nock) don't do this. + request.destroy(); + const wrappedError = error instanceof timed_out_TimeoutError ? new TimeoutError(error, this.timings ?? createPreRequestErrorTimings(), this) : new RequestError(error.message, error, this); + this._beforeError(wrappedError); + }; + request.once('error', (error) => { + lastRequestError = error; + // Ignore errors from requests superseded by a redirect. + if (this._request !== request) { + return; + } + /* + Transient write errors (EPIPE, ECONNRESET) often fire during redirects when the + server closes the connection after sending the redirect response. Defer by one + microtask to let the response event make the request stale. + */ + if (isTransientWriteError(error)) { + queueMicrotask(() => { + if (this._isRequestStale(request)) { + return; + } + emitRequestError(error); + }); + return; + } + emitRequestError(error); + }); + if (!options.cache) { + request.once('close', () => { + if (this._request !== request || Boolean(request.res) || this._stopReading) { + return; + } + this._beforeError(lastRequestError ?? new ReadError({ + name: 'Error', + message: 'The server aborted pending request', + code: 'ECONNRESET', + }, this)); + }); + } + this._unproxyEvents = proxyEvents(request, this, proxiedRequestEvents); + this._request = request; + this.emit('uploadProgress', this.uploadProgress); + this._sendBody(); + this.emit('request', request); + } + _isRequestStale(request) { + return this._request !== request || Boolean(request.res) || request.destroyed || request.writableEnded; + } + async _asyncWrite(chunk, request = this) { + return new Promise((resolve, reject) => { + if (request === this) { + super.write(chunk, error => { + if (error) { + reject(error); + return; + } + resolve(); + }); + return; + } + this._writeRequest(chunk, undefined, error => { + if (error) { + reject(error); + return; + } + resolve(); + }, request); + }); + } + _sendBody() { + // Send body + const { body } = this.options; + const currentRequest = this.redirectUrls.length === 0 && !this._discardBodyWrites ? this : this._request ?? this; + if (distribution.nodeStream(body)) { + body.pipe(currentRequest); + } + else if (distribution.buffer(body)) { + // Buffer should be sent directly without conversion + this._writeBodyInChunks(body, currentRequest); + } + else if (distribution.typedArray(body)) { + // Typed arrays should be treated like buffers, not iterated over + // Create a Uint8Array view over the data (Node.js streams accept Uint8Array) + const typedArray = body; + const uint8View = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength); + this._writeBodyInChunks(uint8View, currentRequest); + } + else if (distribution.asyncIterable(body) || (distribution.iterable(body) && !distribution.string(body) && !isBuffer(body))) { + (async () => { + const isInitialRequest = currentRequest === this; + const bodyOptions = this.options; + try { + for await (const chunk of body) { + if (this.options !== bodyOptions || this.options.body !== body) { + return; + } + await this._asyncWrite(chunk, currentRequest); + if (this.options !== bodyOptions || this.options.body !== body) { + return; + } + } + if (this.options === bodyOptions && this.options.body === body) { + if (isInitialRequest) { + super.end(); + return; + } + await this._endWritableRequest(currentRequest); + } + } + catch (error) { + if (this.options !== bodyOptions || this.options.body !== body) { + return; + } + this._beforeError(normalizeError(error)); + } + })(); + } + else if (distribution.undefined(body)) { + // No body to send, end the request + if ((this._noPipe ?? false) || !this._methodCanHaveBody || currentRequest !== this) { + currentRequest.end(); + } + } + else { + // Handles string bodies (from json/form options). + this._writeBodyInChunks(stringToUint8Array(body), currentRequest); + } + } + /* + Write a body buffer in chunks to enable granular `uploadProgress` events. + + Without chunking, string/Uint8Array/TypedArray bodies are written in a single call, causing `uploadProgress` to only emit 0% and 100% with nothing in between. + + The 64 KB chunk size matches Node.js fs stream defaults. + */ + _writeBodyInChunks(buffer, currentRequest) { + const isInitialRequest = currentRequest === this; + (async () => { + let request; + try { + request = isInitialRequest ? this._request : currentRequest; + const activeRequest = request; + if (!activeRequest) { + if (isInitialRequest) { + super.end(); + } + return; + } + if (activeRequest.destroyed) { + return; + } + await this._writeChunksToRequest(buffer, activeRequest); + if (this._isRequestStale(activeRequest)) { + this._finalizeStaleChunkedWrite(activeRequest, isInitialRequest); + return; + } + if (isInitialRequest) { + super.end(); + return; + } + await this._endWritableRequest(activeRequest); + } + catch (error) { + const normalizedError = normalizeError(error); + // Transient write errors (EPIPE, ECONNRESET) are handled by the request-level + // error and close handlers. For initial redirected writes, still finalize + // writable state once the stale transition becomes observable. + if (isTransientWriteError(normalizedError)) { + if (isInitialRequest && request) { + const initialRequest = request; + let didFinalize = false; + const finalizeIfStale = () => { + if (didFinalize || !this._isRequestStale(initialRequest)) { + return; + } + didFinalize = true; + this._finalizeStaleChunkedWrite(initialRequest, true); + }; + finalizeIfStale(); + if (!didFinalize) { + initialRequest.once('response', finalizeIfStale); + queueMicrotask(finalizeIfStale); + } + } + return; + } + if (!isInitialRequest && this._isRequestStale(currentRequest)) { + return; + } + this._beforeError(normalizedError); + } + })(); + } + _finalizeStaleChunkedWrite(request, isInitialRequest) { + if (!request.destroyed && !request.writableEnded) { + request.destroy(); + } + if (isInitialRequest) { + // Finalize writable state without ending the active redirected request. + this._skipRequestEndInFinal = true; + super.end(); + } + } + _emitUploadComplete(request) { + this._bodySize = this._uploadedSize; + this.emit('uploadProgress', this.uploadProgress); + request.emit('upload-complete'); + } + async _endWritableRequest(request) { + await new Promise((resolve, reject) => { + request.end((error) => { + if (error) { + reject(error); + return; + } + if (this._request === request && !request.destroyed) { + this._emitUploadComplete(request); + } + resolve(); + }); + }); + } + _stripCrossOriginState(options, urlToClear) { + for (const header of crossOriginStripHeaders) { + options.deleteInternalHeader(header); + } + options.username = ''; + options.password = ''; + urlToClear.username = ''; + urlToClear.password = ''; + } + _stripUnchangedCrossOriginState(options, urlToClear, state) { + const headers = options.getInternalHeaders(); + for (const header of crossOriginStripHeaders) { + if (!state.changedState.has(header) && headers[header] === state.headers[header]) { + options.deleteInternalHeader(header); + } + } + if (!state.preserveUsername) { + options.username = ''; + urlToClear.username = ''; + } + if (!state.preservePassword) { + options.password = ''; + urlToClear.password = ''; + } + } + get _methodCanHaveBody() { + return !methodsWithoutBody.has(this.options.method) || (this.options.method === 'GET' && this.options.allowGetBody); + } + _canWriteBody() { + return !this._noPipe && !this.isReadonly && this._methodCanHaveBody; + } + _hasBodyForRedirect(options) { + return !distribution.undefined(options.body) || !distribution.undefined(options.json) || !distribution.undefined(options.form) || this._hasWrittenBody || this._hasWritableBody; + } + _hasUnchangedBodyForRedirect(options, state, changedState) { + return !changedState.has('body') + && !changedState.has('json') + && !changedState.has('form') + && this._hasBodyForRedirect(options) + && isBodyUnchanged(options, state); + } + _dropBody(updatedOptions) { + const { body } = this.options; + const hadOptionBody = !distribution.undefined(body) || !distribution.undefined(this.options.json) || !distribution.undefined(this.options.form); + this.options.clearBody(); + this._destroyBody(body); + if (!hadOptionBody && !this.writableEnded) { + this._skipRequestEndInFinal = true; + super.end(); + } + updatedOptions.clearBody(); + this._bodySize = undefined; + this._hasWrittenBody = false; + this._hasWritableBody = false; + } + _destroyBody(body) { + if (distribution.nodeStream(body)) { + const bodyStream = body; + bodyStream.off('error', this._onBodyError); + bodyStream.unpipe(); + bodyStream.on('error', core_noop); + bodyStream.destroy(); + } + else if (distribution.asyncIterable(body) || (distribution.iterable(body) && !distribution.string(body) && !isBuffer(body))) { + const iterableBody = body; + // Signal the iterator to clean up, but don't await it: + // the for-await loop in _sendBody exits via the options.body sentinel, + // and awaiting return() would deadlock when next() is pending. + if (typeof iterableBody.return === 'function') { + try { + const result = iterableBody.return(); + if (result instanceof Promise) { + // eslint-disable-next-line promise/prefer-await-to-then + result.catch(core_noop); + } + } + catch { } + } + } + } + _onBodyError = (error) => { + if (this._flushed) { + this._beforeError(new UploadError(error, this)); + } + else { + this.flush = async () => { + this.flush = async () => { }; + this._beforeError(new UploadError(error, this)); + }; + } + }; + async _writeChunksToRequest(buffer, request) { + const chunkSize = 65_536; // 64 KB + const isStale = () => this._isRequestStale(request); + for (const part of chunk(buffer, chunkSize)) { + if (isStale()) { + return; + } + // eslint-disable-next-line no-await-in-loop + await new Promise((resolve, reject) => { + this._writeRequest(part, undefined, error => { + if (isStale()) { + resolve(); + return; + } + if (error) { + reject(error); + } + else { + setImmediate(resolve); + } + }, request); + }); + } + } + _prepareCache(cache) { + if (cacheableStore.has(cache)) { + return; + } + const cacheableRequest = new dist(((requestOptions, handler) => { + /** + Wraps the cacheable-request handler to run beforeCache hooks. + These hooks control caching behavior by: + - Directly mutating the response object (changes apply to what gets cached) + - Returning `false` to prevent caching + - Returning `void`/`undefined` to use default caching behavior + + Hooks use direct mutation - they can modify response.headers, response.statusCode, etc. + Mutations take effect immediately and determine what gets cached. + */ + const wrappedHandler = handler + ? (response) => { + const { beforeCacheHooks, gotRequest } = requestOptions; + // Early return if no hooks - cache the original response + if (!beforeCacheHooks || beforeCacheHooks.length === 0) { + handler(response); + return; + } + try { + // Call each beforeCache hook with the response + // Hooks can directly mutate the response - mutations take effect immediately + for (const hook of beforeCacheHooks) { + const result = hook(response); + if (result === false) { + // Prevent caching by adding no-cache headers + // Mutate the response directly to add headers + response.headers['cache-control'] = 'no-cache, no-store, must-revalidate'; + response.headers.pragma = 'no-cache'; + response.headers.expires = '0'; + handler(response); + // Don't call remaining hooks - we've decided not to cache + return; + } + if (distribution.promise(result)) { + // BeforeCache hooks must be synchronous because cacheable-request's handler is synchronous + throw new TypeError('beforeCache hooks must be synchronous. The hook returned a Promise, but this hook must return synchronously. If you need async logic, use beforeRequest hook instead.'); + } + if (result !== undefined) { + // Hooks should return false or undefined only + // Mutations work directly - no need to return the response + throw new TypeError('beforeCache hook must return false or undefined. To modify the response, mutate it directly.'); + } + // Else: void/undefined = continue + } + } + catch (error) { + const normalizedError = normalizeError(error); + // Convert hook errors to RequestError and propagate + // This is consistent with how other hooks handle errors + if (gotRequest) { + gotRequest._beforeError(normalizedError instanceof RequestError ? normalizedError : new RequestError(normalizedError.message, normalizedError, gotRequest)); + // Don't call handler when error was propagated successfully + return; + } + // If gotRequest is missing, log the error to aid debugging + // We still call the handler to prevent the request from hanging + console.error('Got: beforeCache hook error (request context unavailable):', normalizedError); + // Call handler with response (potentially partially modified) + handler(response); + return; + } + // All hooks ran successfully + // Cache the response with any mutations applied + handler(response); + } + : handler; + const result = requestOptions._request(requestOptions, wrappedHandler); + // TODO: remove this when `cacheable-request` supports async request functions. + if (distribution.promise(result)) { + // We only need to implement the error handler in order to support HTTP/2 caching. + // The result will be a promise anyway. + // @ts-expect-error ignore + result.once = (event, handler) => { + if (event === 'error') { + (async () => { + try { + await result; + } + catch (error) { + handler(error); + } + })(); + } + else if (event === 'abort' || event === 'destroy') { + // The empty catch is needed here in case when + // it rejects before it's `await`ed in `_makeRequest`. + (async () => { + try { + const request = (await result); + request.once(event, handler); + } + catch { } + })(); + } + else { + /* istanbul ignore next: safety check */ + throw new Error(`Unknown HTTP/2 promise event: ${event}`); + } + return result; + }; + } + return result; + }), cache); + cacheableStore.set(cache, cacheableRequest.request()); + } + async _createCacheableRequest(url, options) { + return new Promise((resolve, reject) => { + Object.assign(options, { + protocol: url.protocol, + hostname: distribution.string(url.hostname) && url.hostname.startsWith('[') ? url.hostname.slice(1, -1) : url.hostname, + host: distribution.string(url.hostname) && url.hostname.startsWith('[') ? url.hostname.slice(1, -1) : url.hostname, + hash: url.hash === '' ? '' : (url.hash ?? null), + search: url.search === '' ? '' : (url.search ?? null), + pathname: url.pathname, + href: url.href, + path: `${url.pathname || ''}${url.search || ''}`, + ...(distribution.string(url.port) && url.port.length > 0 ? { port: Number(url.port) } : {}), + ...(url.username || url.password ? { auth: `${url.username || ''}:${url.password || ''}` } : {}), + }); + let request; + // TODO: Fix `cacheable-response`. This is ugly. + const cacheRequest = cacheableStore.get(options.cache)(options, (response) => { + void (async () => { + response._readableState.autoDestroy = false; + if (request) { + const fix = () => { + // For ResponseLike objects from cache, set complete to true if not already set. + // For real HTTP responses, copy from the underlying response. + if (response.req) { + response.complete = response.req.res.complete; + } + else if (response.complete === undefined) { + // ResponseLike from cache should have complete = true + response.complete = true; + } + }; + response.prependOnceListener('end', fix); + fix(); + (await request).emit('cacheableResponse', response); + } + resolve(response); + })(); + }); + cacheRequest.once('error', reject); + cacheRequest.once('request', (requestOrPromise) => { + request = requestOrPromise; + resolve(request); + }); + }); + } + async _makeRequest() { + const { options } = this; + const shouldDeleteGeneratedHeader = (currentHeader, generatedHeader) => currentHeader === generatedHeader || distribution.undefined(currentHeader); + const syncGeneratedHeader = (name, { currentHeader, explicitHeader, nextHeader, staleGeneratedHeader, }) => { + if (!distribution.undefined(nextHeader)) { + options.setInternalHeader(name, nextHeader); + } + else if (!distribution.undefined(explicitHeader) && currentHeader === staleGeneratedHeader) { + options.setInternalHeader(name, explicitHeader); + } + else if (shouldDeleteGeneratedHeader(currentHeader, staleGeneratedHeader)) { + options.deleteInternalHeader(name); + } + }; + const getAuthorizationHeader = (username, password, isExplicitlyOmitted) => !isExplicitlyOmitted && (username || password) + ? `Basic ${stringToBase64(`${username}:${password}`)}` + : undefined; + const sanitizeHeaders = () => { + const currentHeaders = options.getInternalHeaders(); + for (const key in currentHeaders) { + if (distribution.undefined(currentHeaders[key])) { + options.deleteInternalHeader(key); + } + else if (distribution.null(currentHeaders[key])) { + throw new TypeError(`Use \`undefined\` instead of \`null\` to delete the \`${key}\` header`); + } + else if (Array.isArray(currentHeaders[key]) && key === 'transfer-encoding') { + // Node serializes request header arrays as repeated field lines. Keep framing + // unambiguous by allowing only one transfer-encoding value here. + if (currentHeaders[key].length !== 1) { + throw new TypeError(`The \`${key}\` header must be a single value`); + } + options.setInternalHeader(key, currentHeaders[key][0]); + } + else if (Array.isArray(currentHeaders[key]) && singleValueRequestHeaders.has(key)) { + // Duplicate credential and content-length lines are not allowed on requests. + // Normalize a single-element array to match the long-supported string path. + if (currentHeaders[key].length !== 1) { + throw new TypeError(`The \`${key}\` header must be a single value`); + } + options.setInternalHeader(key, currentHeaders[key][0]); + } + } + return currentHeaders; + }; + const getCookieHeader = async (cookieJar) => { + if (!cookieJar) { + return undefined; + } + const cookieString = await cookieJar.getCookieString(options.url.toString()); + return distribution.nonEmptyString(cookieString) ? cookieString : undefined; + }; + const headers = sanitizeHeaders(); + const initialHeaders = options.getInternalHeaders(); + const authorizationWasInitiallyExplicit = options.isHeaderExplicitlySet('authorization'); + const explicitAuthorizationHeader = authorizationWasInitiallyExplicit ? initialHeaders.authorization : undefined; + const explicitCookieHeader = options.isHeaderExplicitlySet('cookie') ? initialHeaders.cookie : undefined; + const authorizationWasInitiallyOmitted = options.isHeaderExplicitlySet('authorization') && distribution.undefined(initialHeaders.authorization); + const cookieWasInitiallyOmitted = options.isHeaderExplicitlySet('cookie') && distribution.undefined(initialHeaders.cookie); + if (options.decompress && distribution.undefined(headers['accept-encoding'])) { + const encodings = ['gzip', 'deflate']; + if (supportsBrotli) { + encodings.push('br'); + } + if (core_supportsZstd) { + encodings.push('zstd'); + } + options.setInternalHeader('accept-encoding', encodings.join(', ')); + } + const { username, password } = options; + const cookieJar = options.cookieJar; + // Preserve an explicit Authorization header over URL-derived Basic auth. This keeps + // normalized single-element arrays aligned with the long-supported string behavior. + const generatedAuthorizationHeader = distribution.undefined(explicitAuthorizationHeader) + ? getAuthorizationHeader(username, password, authorizationWasInitiallyOmitted) + : undefined; + let generatedCookieHeader; + if (!distribution.undefined(generatedAuthorizationHeader)) { + options.setInternalHeader('authorization', generatedAuthorizationHeader); + } + if (!cookieWasInitiallyOmitted) { + generatedCookieHeader = await getCookieHeader(cookieJar); + if (!distribution.undefined(generatedCookieHeader)) { + options.setInternalHeader('cookie', generatedCookieHeader); + } + } + let request; + let shouldOmitRequestUrlCredentials = false; + const urlBeforeRequestHooks = options.url instanceof URL ? new URL(options.url) : undefined; + const boundaryBeforeRequestHooks = getUrlPrefixBoundary(options); + const stateBeforeRequestHooks = urlBeforeRequestHooks ? snapshotCrossOriginState(options) : undefined; + const crossOriginHookStrippedHeaders = new Set(); + const changedState = await options.trackStateMutations(async (changedState) => { + for (const hook of options.hooks.beforeRequest) { + // eslint-disable-next-line no-await-in-loop + const result = await hook(options, { retryCount: this.retryCount }); + if (!distribution.undefined(result)) { + // @ts-expect-error Skip the type mismatch to support abstract responses + request = () => result; + break; + } + } + return changedState; + }); + if (urlBeforeRequestHooks + && options.url instanceof URL + && hasUrlOrPrefixUrlBoundaryChanged(options, options.url, boundaryBeforeRequestHooks)) { + assertUrlHasSameOriginAsPrefixUrlIfNeeded(options, options.url); + } + if (urlBeforeRequestHooks + && options.url instanceof URL + && !isSameOrigin(urlBeforeRequestHooks, options.url)) { + const hookChangedState = new Set(changedState); + const currentHeaders = options.getInternalHeaders(); + const changedHeaders = {}; + for (const header of crossOriginStripHeaders) { + if (hookChangedState.has(header)) { + changedHeaders[header] = currentHeaders[header]; + } + else { + options.deleteInternalHeader(header); + crossOriginHookStrippedHeaders.add(header); + } + } + const changedOptions = { headers: changedHeaders }; + if (hookChangedState.has('url')) { + changedOptions.url = options.url; + } + if (hookChangedState.has('prefixUrl')) { + changedOptions.prefixUrl = options.prefixUrl; + } + if (hookChangedState.has('username')) { + changedOptions.username = options.username; + } + if (hookChangedState.has('password')) { + changedOptions.password = options.password; + } + options.stripSensitiveHeaders(urlBeforeRequestHooks, options.url, changedOptions); + this._discardBodyWrites = true; + this._hasWrittenBody = false; + this._hasWritableBody = false; + if (!hookChangedState.has('body') + && !hookChangedState.has('json') + && !hookChangedState.has('form') + && isBodyUnchanged(options, stateBeforeRequestHooks)) { + options.clearBody(); + this._bodySize = undefined; + } + } + if (request === undefined) { + const currentHeaders = options.getInternalHeaders(); + // `headers.authorization = undefined` / `headers.cookie = undefined` is an + // explicit opt-out. Respect that instead of regenerating values from URL + // credentials or the cookie jar later in request setup. + const isHeaderExplicitlyOmitted = (header) => options.isHeaderExplicitlySet(header) + && (Object.hasOwn(currentHeaders, header) || changedState.has(header)) + && distribution.undefined(currentHeaders[header]); + const currentAuthorizationHeader = currentHeaders.authorization; + const currentCookieHeader = currentHeaders.cookie; + // Authorization follows a small contract: + // - A concrete Authorization header is sent as-is. + // - `authorization = undefined` means omit Authorization entirely, including URL auth. + // - Deleting an Authorization header that started explicit also means omit it. + // - Otherwise, if the request did not start with explicit Authorization, Got may + // generate Basic auth from the current username/password. + const authorizationWasExplicitlyOmitted = isHeaderExplicitlyOmitted('authorization') + || (authorizationWasInitiallyExplicit + && !crossOriginHookStrippedHeaders.has('authorization') + && distribution.undefined(currentAuthorizationHeader)); + const cookieWasExplicitlyOmitted = distribution.undefined(currentCookieHeader) + && (cookieWasInitiallyOmitted || isHeaderExplicitlyOmitted('cookie')); + sanitizeHeaders(); + if (!distribution.undefined(currentHeaders['transfer-encoding']) && !distribution.undefined(currentHeaders['content-length'])) { + options.deleteInternalHeader('content-length'); + } + if (authorizationWasExplicitlyOmitted) { + shouldOmitRequestUrlCredentials = true; + options.deleteInternalHeader('authorization'); + if (changedState.has('authorization') && distribution.undefined(explicitAuthorizationHeader) && !authorizationWasInitiallyOmitted) { + delete options.headers.authorization; + } + } + const authorizationHeader = !authorizationWasInitiallyExplicit + && !authorizationWasInitiallyOmitted + && !authorizationWasExplicitlyOmitted + ? getAuthorizationHeader(options.username, options.password, authorizationWasExplicitlyOmitted) + : undefined; + const cookieJar = options.cookieJar; + if (changedState.has('authorization') && !distribution.undefined(currentAuthorizationHeader)) { + // A beforeRequest hook intentionally set the outgoing Authorization header. + } + else { + const restorableAuthorizationHeader = crossOriginHookStrippedHeaders.has('authorization') || (changedState.has('authorization') && distribution.undefined(currentAuthorizationHeader)) + ? undefined + : explicitAuthorizationHeader; + syncGeneratedHeader('authorization', { + currentHeader: currentAuthorizationHeader, + explicitHeader: restorableAuthorizationHeader, + nextHeader: authorizationHeader, + staleGeneratedHeader: generatedAuthorizationHeader, + }); + } + if (cookieWasExplicitlyOmitted) { + options.deleteInternalHeader('cookie'); + if (changedState.has('cookie') && distribution.undefined(explicitCookieHeader) && !cookieWasInitiallyOmitted) { + delete options.headers.cookie; + } + } + else if (changedState.has('cookie')) { + // A beforeRequest hook intentionally set the outgoing Cookie header. + } + else { + const cookieHeader = !cookieWasInitiallyOmitted && !cookieWasExplicitlyOmitted + ? await getCookieHeader(cookieJar) + : undefined; + const restorableCookieHeader = crossOriginHookStrippedHeaders.has('cookie') + ? undefined + : explicitCookieHeader; + syncGeneratedHeader('cookie', { + currentHeader: currentCookieHeader, + explicitHeader: restorableCookieHeader, + nextHeader: cookieHeader, + staleGeneratedHeader: generatedCookieHeader, + }); + } + } + request ??= options.getRequestFunction(); + const url = shouldOmitRequestUrlCredentials + ? new URL(stripUrlAuth(options.url)) + : options.url; + this._requestOptions = options.createNativeRequestOptions(); + if (shouldOmitRequestUrlCredentials) { + this._requestOptions.auth = undefined; + } + if (options.cache) { + this._requestOptions._request = request; + this._requestOptions.cache = options.cache; + this._requestOptions.body = options.body; + this._requestOptions.beforeCacheHooks = options.hooks.beforeCache; + this._requestOptions.gotRequest = this; + try { + this._prepareCache(options.cache); + } + catch (error) { + throw new CacheError(normalizeError(error), this); + } + } + // Cache support + const function_ = options.cache ? this._createCacheableRequest : request; + try { + // We can't do `await fn(...)`, + // because stream `error` event can be emitted before `Promise.resolve()`. + const requestFunctionStartedAt = Date.now(); + const originalRequestTimeout = options.timeout.request; + let shouldRestoreRequestTimeout = false; + let requestOrResponse = function_(url, this._requestOptions); + if (distribution.promise(requestOrResponse)) { + requestOrResponse = await requestOrResponse; + if (options.timeout.request !== undefined) { + const remainingRequestTimeout = options.timeout.request - (Date.now() - requestFunctionStartedAt); + options.timeout.request = Math.max(0, remainingRequestTimeout); + shouldRestoreRequestTimeout = true; + } + } + try { + if (is_client_request(requestOrResponse)) { + this._onRequest(requestOrResponse); + } + else if (this.writableEnded) { + void this._onResponse(requestOrResponse); + } + else { + this.once('finish', () => { + void this._onResponse(requestOrResponse); + }); + this._sendBody(); + } + } + finally { + if (shouldRestoreRequestTimeout) { + options.timeout.request = originalRequestTimeout; + } + } + } + catch (error) { + if (error instanceof types_CacheError) { + throw new CacheError(error, this); + } + throw error; + } + } + async _error(error) { + try { + // Skip calling hooks for HTTP errors when throwHttpErrors is false (Promise API only). + // See https://github.com/sindresorhus/got/issues/2103 + if (this.options && (!(error instanceof HTTPError) || this.options.throwHttpErrors)) { + const hooks = this.options.hooks.beforeError; + if (hooks.length > 0) { + for (const hook of hooks) { + // eslint-disable-next-line no-await-in-loop + error = await hook(error); + // Validate hook return value + if (!(error instanceof Error)) { + throw new TypeError(`The \`beforeError\` hook must return an Error instance. Received ${distribution.string(error) ? 'string' : String(typeof error)}.`); + } + } + // Mark this error as processed by hooks so _destroy preserves custom error types. + // Only mark non-RequestError errors, since RequestErrors are already preserved + // by the instanceof check in _destroy (line 642). + if (!(error instanceof RequestError)) { + errorsProcessedByHooks.add(error); + } + } + } + } + catch (error_) { + const normalizedError = normalizeError(error_); + error = new RequestError(normalizedError.message, normalizedError, this); + } + // Publish error event + publishError({ + requestId: this._requestId, + url: getSanitizedUrl(this.options), + error, + timings: this.timings, + }); + this.destroy(error); + // Manually emit error for Promise API to ensure it receives it. + // Node.js streams may not re-emit if an error was already emitted during retry attempts. + // Only emit for Promise API (_noPipe = true) to avoid double emissions in stream mode. + // Use process.nextTick to defer emission and allow destroy() to complete first. + // See https://github.com/sindresorhus/got/issues/1995 + if (this._noPipe) { + external_node_process_.nextTick(() => { + this.emit('error', error); + }); + } + } + _writeRequest(chunk, encoding, callback, request = this._request) { + if (!request || request.destroyed) { + // When there's no request (e.g., using cached response from beforeRequest hook), + // we still need to call the callback to allow the stream to finish properly. + callback(); + return; + } + request.write(chunk, encoding, (error) => { + // The `!destroyed` check is required to prevent `uploadProgress` being emitted after the stream was destroyed. + // The `this._request === request` check prevents stale write callbacks from a pre-redirect request from incrementing `_uploadedSize` after it's been reset. + if (!error && !request.destroyed && this._request === request) { + // For strings, encode them first to measure the actual bytes that will be sent + const bytes = typeof chunk === 'string' ? external_node_buffer_.Buffer.from(chunk, encoding) : chunk; + this._uploadedSize += byteLength(bytes); + const progress = this.uploadProgress; + if (progress.percent < 1) { + this.emit('uploadProgress', progress); + } + } + callback(error); + }); + } + /** + The remote IP address. + */ + get ip() { + return this.socket?.remoteAddress; + } + /** + Indicates whether the request has been aborted or not. + */ + get isAborted() { + return this._aborted; + } + get socket() { + return this._request?.socket ?? undefined; + } + /** + Progress event for downloading (receiving a response). + */ + get downloadProgress() { + return makeProgress(this._downloadedSize, this._responseSize); + } + /** + Progress event for uploading (sending a request). + */ + get uploadProgress() { + return makeProgress(this._uploadedSize, this._bodySize); + } + /** + The object contains the following properties: + + - `start` - Time when the request started. + - `socket` - Time when a socket was assigned to the request. + - `lookup` - Time when the DNS lookup finished. + - `connect` - Time when the socket successfully connected. + - `secureConnect` - Time when the socket securely connected. + - `upload` - Time when the request finished uploading. + - `response` - Time when the request fired `response` event. + - `end` - Time when the response fired `end` event. + - `error` - Time when the request fired `error` event. + - `abort` - Time when the request fired `abort` event. + - `phases` + - `wait` - `timings.socket - timings.start` + - `dns` - `timings.lookup - timings.socket` + - `tcp` - `timings.connect - timings.lookup` + - `tls` - `timings.secureConnect - timings.connect` + - `request` - `timings.upload - (timings.secureConnect || timings.connect)` + - `firstByte` - `timings.response - timings.upload` + - `download` - `timings.end - timings.response` + - `total` - `(timings.end || timings.error || timings.abort) - timings.start` + + If something has not been measured yet, it will be `undefined`. + + __Note__: The time is a `number` representing the milliseconds elapsed since the UNIX epoch. + */ + get timings() { + return this._request?.timings; + } + /** + Whether the response was retrieved from the cache. + */ + get isFromCache() { + return this.response?.isFromCache; + } + get reusedSocket() { + return this._request?.reusedSocket; + } + /** + Whether the stream is read-only. Returns `true` when `body`, `json`, or `form` options are provided. + */ + get isReadonly() { + return !distribution.undefined(this.options?.body) || !distribution.undefined(this.options?.json) || !distribution.undefined(this.options?.form); + } +} + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/as-promise/index.js + + + + + + + +const compressedEncodings = new Set(['gzip', 'deflate', 'br', 'zstd']); +const as_promise_proxiedRequestEvents = [ + 'request', + 'response', + 'redirect', + 'uploadProgress', + 'downloadProgress', +]; +function asPromise(firstRequest) { + let globalRequest; + let globalResponse; + const emitter = new external_node_events_.EventEmitter(); + let promiseSettled = false; + const promise = new Promise((resolve, reject) => { + const makeRequest = (retryCount, defaultOptions) => { + const request = firstRequest ?? new Request(undefined, undefined, defaultOptions); + request.retryCount = retryCount; + request._noPipe = true; + globalRequest = request; + request.once('response', (response) => { + void (async () => { + // Parse body + const contentEncoding = (response.headers['content-encoding'] ?? '').toLowerCase(); + const isCompressed = compressedEncodings.has(contentEncoding); + const { options } = request; + if (isCompressed && !options.decompress) { + response.body = response.rawBody; + } + else { + try { + response.body = parseBody(response, options.responseType, options.parseJson, options.encoding); + } + catch (error) { + // Fall back to `utf8` + try { + response.body = decodeUint8Array(response.rawBody); + } + catch (error) { + request._beforeError(new ParseError(normalizeError(error), response)); + return; + } + if (isResponseOk(response)) { + request._beforeError(normalizeError(error)); + return; + } + } + } + try { + const hooks = options.hooks.afterResponse; + for (const [index, hook] of hooks.entries()) { + const previousUrl = options.url ? new URL(options.url) : undefined; + const previousBoundary = getUrlPrefixBoundary(options); + const previousState = previousUrl ? snapshotCrossOriginState(options) : undefined; + const requestOptions = response.request.options; + const responseSnapshot = response; + // @ts-expect-error TS doesn't notice that RequestPromise is a Promise + // eslint-disable-next-line no-await-in-loop + response = await requestOptions.trackStateMutations(async (changedState) => hook(responseSnapshot, async (updatedOptions) => { + const preserveHooks = updatedOptions.preserveHooks ?? false; + const reusesRequestOptions = updatedOptions === requestOptions; + const hasExplicitBody = reusesRequestOptions + ? changedState.has('body') || changedState.has('json') || changedState.has('form') + : (Object.hasOwn(updatedOptions, 'body') && updatedOptions.body !== undefined) + || (Object.hasOwn(updatedOptions, 'json') && updatedOptions.json !== undefined) + || (Object.hasOwn(updatedOptions, 'form') && updatedOptions.form !== undefined); + const clearsCookieJar = Object.hasOwn(updatedOptions, 'cookieJar') && updatedOptions.cookieJar === undefined; + if (hasExplicitBody && !reusesRequestOptions) { + options.clearBody(); + } + if (!reusesRequestOptions && clearsCookieJar) { + options.cookieJar = undefined; + } + if (!reusesRequestOptions) { + const { url, ...updatedOptionsWithoutUrl } = updatedOptions; + options.merge(updatedOptionsWithoutUrl); + options.syncCookieHeaderAfterMerge(previousState, updatedOptionsWithoutUrl.headers); + } + options.clearUnchangedCookieHeader(previousState, reusesRequestOptions ? changedState : undefined); + const currentUrl = options.url; + if (previousUrl + && currentUrl instanceof URL + && hasUrlOrPrefixUrlBoundaryChanged(options, currentUrl, previousBoundary)) { + assertUrlHasSameOriginAsPrefixUrlIfNeeded(options, currentUrl); + } + if (!reusesRequestOptions + && updatedOptions.url === undefined + && previousUrl + && currentUrl instanceof URL + && !isSameOrigin(previousUrl, currentUrl)) { + options.stripSensitiveHeaders(previousUrl, currentUrl, updatedOptions); + if (!hasExplicitBody) { + options.clearBody(); + } + } + if (updatedOptions.url !== undefined) { + const nextUrl = reusesRequestOptions + ? options.url + : applyUrlOverride(options, updatedOptions.url, updatedOptions); + if (previousUrl) { + if (reusesRequestOptions && !isSameOrigin(previousUrl, nextUrl)) { + options.stripUnchangedCrossOriginState(previousState, changedState, { clearBody: !hasExplicitBody }); + } + else { + options.stripSensitiveHeaders(previousUrl, nextUrl, updatedOptions); + if (!isSameOrigin(previousUrl, nextUrl) && !hasExplicitBody) { + options.clearBody(); + } + } + } + } + // Remove any further hooks for that request, because we'll call them anyway. + // The loop continues. We don't want duplicates (asPromise recursion). + // Unless preserveHooks is true, in which case we keep the remaining hooks. + if (!preserveHooks) { + options.hooks.afterResponse = options.hooks.afterResponse.slice(0, index); + } + throw new RetryError(request); + })); + if (!(distribution.object(response) && distribution.number(response.statusCode) && 'body' in response)) { + throw new TypeError('The `afterResponse` hook returned an invalid value'); + } + } + } + catch (error) { + request._beforeError(normalizeError(error)); + return; + } + globalResponse = response; + if (!isResponseOk(response)) { + request._beforeError(new HTTPError(response)); + return; + } + request.destroy(); + promiseSettled = true; + resolve(request.options.resolveBodyOnly ? response.body : response); + })(); + }); + let handledFinalError = false; + const onError = (error) => { + // Route errors emitted directly on the stream (e.g., EPIPE from Node.js) + // through retry logic first, then handle them here after retries are exhausted. + // See https://github.com/sindresorhus/got/issues/1995 + if (!request._stopReading) { + request._beforeError(error); + return; + } + // Allow the manual re-emission from Request to land only once. + if (handledFinalError) { + return; + } + handledFinalError = true; + promiseSettled = true; + const { options } = request; + if (error instanceof HTTPError && !options.throwHttpErrors) { + const { response } = error; + request.destroy(); + resolve(options.resolveBodyOnly ? response.body : response); + return; + } + reject(error); + }; + // Use .on() instead of .once() to keep the listener active across retries. + // When _stopReading is false, we return early and the error gets re-emitted + // after retry logic completes, so we need this listener to remain active. + // See https://github.com/sindresorhus/got/issues/1995 + request.on('error', onError); + const previousBody = request.options?.body; + request.once('retry', (newRetryCount, error) => { + firstRequest = undefined; + // If promise already settled, don't retry + // This prevents the race condition in #1489 where a late error + // (e.g., ECONNRESET after successful response) triggers retry + // after the promise has already resolved/rejected + if (promiseSettled) { + return; + } + const newBody = request.options.body; + if (previousBody === newBody && (distribution.nodeStream(newBody) || newBody instanceof ReadableStream)) { + error.message = 'Cannot retry with consumed body stream'; + onError(error); + return; + } + // This is needed! We need to reuse `request.options` because they can get modified! + // For example, by calling `promise.json()`. + makeRequest(newRetryCount, request.options); + }); + proxyEvents(request, emitter, as_promise_proxiedRequestEvents); + if (distribution.undefined(firstRequest)) { + void request.flush(); + } + }; + makeRequest(0); + }); + promise.on = function (event, function_) { + emitter.on(event, function_); + return this; + }; + promise.once = function (event, function_) { + emitter.once(event, function_); + return this; + }; + promise.off = function (event, function_) { + emitter.off(event, function_); + return this; + }; + const shortcut = (promiseToAwait, responseType) => { + const newPromise = (async () => { + // Wait until downloading has ended + await promiseToAwait; + const { options } = globalResponse.request; + if (responseType === 'text') { + const text = decodeUint8Array(globalResponse.rawBody, options.encoding); + return (isUtf8Encoding(options.encoding) ? text.replace(/^\u{FEFF}/v, '') : text); + } + return parseBody(globalResponse, responseType, options.parseJson, options.encoding); + })(); + // eslint-disable-next-line @typescript-eslint/no-floating-promises + Object.defineProperties(newPromise, Object.getOwnPropertyDescriptors(promiseToAwait)); + return newPromise; + }; + // Note: These use `function` syntax (not arrows) to access `this` context. + // When custom handlers wrap the promise to transform errors, these methods + // are copied to the handler's promise. Using `this` ensures we await the + // handler's wrapped promise, not the original, so errors propagate correctly. + promise.json = function () { + if (globalRequest.options) { + const { headers } = globalRequest.options; + if (!globalRequest.writableFinished && !('accept' in headers)) { + headers.accept = 'application/json'; + } + } + return shortcut(this, 'json'); + }; + promise.buffer = function () { + return shortcut(this, 'buffer'); + }; + promise.text = function () { + return shortcut(this, 'text'); + }; + return promise; +} + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/create.js + + + + + +const isGotInstance = (value) => distribution.function(value); +const aliases = [ + 'get', + 'post', + 'put', + 'patch', + 'head', + 'delete', + 'query', +]; +const optionsObjectUrlErrorMessage = 'The `url` option is not supported in options objects. Pass it as the first argument instead.'; +const assertNoUrlInOptionsObject = (options) => { + if (Object.hasOwn(options, 'url')) { + throw new TypeError(optionsObjectUrlErrorMessage); + } +}; +const create = (defaults) => { + defaults = { + options: new Options(undefined, undefined, defaults.options), + handlers: [...defaults.handlers], + mutableDefaults: defaults.mutableDefaults, + }; + Object.defineProperty(defaults, 'mutableDefaults', { + enumerable: true, + configurable: false, + writable: false, + }); + const makeRequest = (url, options, defaultOptions, isStream) => { + if (distribution.plainObject(url)) { + assertNoUrlInOptionsObject(url); + } + if (distribution.plainObject(options)) { + assertNoUrlInOptionsObject(options); + } + // `isStream` is intentionally skipped by `merge()`. + // Make the flag visible to `hooks.init` for both stream call forms. + let requestInput = url; + let requestOptions = options; + if (isStream) { + if (distribution.plainObject(url)) { + requestInput = Object.defineProperties({}, Object.getOwnPropertyDescriptors(url)); + Reflect.set(requestInput, 'isStream', true); + } + else if (distribution.plainObject(options)) { + requestOptions = Object.defineProperties({}, Object.getOwnPropertyDescriptors(options)); + Reflect.set(requestOptions, 'isStream', true); + } + } + const request = new Request(requestInput, requestOptions, defaultOptions); + if (isStream && request.options) { + request.options.isStream = true; + } + let promise; + const urlBeforeHandlers = request.options?.url instanceof URL ? new URL(request.options.url) : undefined; + const boundaryBeforeHandlers = request.options ? getUrlPrefixBoundary(request.options) : undefined; + const lastHandler = (normalized) => { + if (urlBeforeHandlers + && boundaryBeforeHandlers + && normalized?.url instanceof URL + && hasUrlOrPrefixUrlBoundaryChanged(normalized, normalized.url, boundaryBeforeHandlers)) { + assertUrlHasSameOriginAsPrefixUrlIfNeeded(normalized, normalized.url); + } + // Note: `options` is `undefined` when `new Options(...)` fails + request.options = normalized; + const shouldReturnStream = normalized?.isStream ?? isStream; + request._noPipe = !shouldReturnStream; + void request.flush(); + if (shouldReturnStream) { + return request; + } + promise ??= asPromise(request); + return promise; + }; + let iteration = 0; + const iterateHandlers = (newOptions) => { + const handler = defaults.handlers[iteration++] ?? lastHandler; + const result = handler(newOptions, iterateHandlers); + if (distribution.promise(result) && !request.options?.isStream) { + promise ??= asPromise(request); + if (result !== promise) { + const descriptors = Object.getOwnPropertyDescriptors(promise); + for (const key in descriptors) { + if (key in result) { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete descriptors[key]; + } + } + // eslint-disable-next-line @typescript-eslint/no-floating-promises + Object.defineProperties(result, descriptors); + } + } + return result; + }; + return iterateHandlers(request.options); + }; + // Got interface + const got = ((url, options, defaultOptions = defaults.options) => makeRequest(url, options, defaultOptions, false)); + got.extend = (...instancesOrOptions) => { + const options = new Options(undefined, undefined, defaults.options); + const handlers = [...defaults.handlers]; + let mutableDefaults; + for (const value of instancesOrOptions) { + if (isGotInstance(value)) { + options.merge(value.defaults.options); + handlers.push(...value.defaults.handlers); + mutableDefaults = value.defaults.mutableDefaults; + } + else { + assertNoUrlInOptionsObject(value); + options.merge(value); + if (value.handlers) { + handlers.push(...value.handlers); + } + mutableDefaults = value.mutableDefaults; + } + } + return create({ + options, + handlers, + mutableDefaults: Boolean(mutableDefaults), + }); + }; + // Pagination + const paginateEach = (async function* (url, options) { + if (distribution.plainObject(url)) { + assertNoUrlInOptionsObject(url); + } + if (distribution.plainObject(options)) { + assertNoUrlInOptionsObject(options); + } + let normalizedOptions = new Options(url, options, defaults.options); + normalizedOptions.resolveBodyOnly = false; + const { pagination } = normalizedOptions; + assert.function(pagination.transform); + assert.function(pagination.shouldContinue); + assert.function(pagination.filter); + assert.function(pagination.paginate); + assert.number(pagination.countLimit); + assert.number(pagination.requestLimit); + assert.number(pagination.backoff); + const allItems = []; + let { countLimit } = pagination; + let numberOfRequests = 0; + while (numberOfRequests < pagination.requestLimit) { + if (numberOfRequests !== 0) { + // eslint-disable-next-line no-await-in-loop + await (0,promises_.setTimeout)(pagination.backoff); + } + // eslint-disable-next-line no-await-in-loop + const response = (await got(undefined, undefined, normalizedOptions)); + // eslint-disable-next-line no-await-in-loop + const parsed = await pagination.transform(response); + const currentItems = []; + assert.array(parsed); + for (const item of parsed) { + if (pagination.filter({ item, currentItems, allItems })) { + if (!pagination.shouldContinue({ item, currentItems, allItems })) { + return; + } + yield item; + if (pagination.stackAllItems) { + allItems.push(item); + } + currentItems.push(item); + if (--countLimit <= 0) { + return; + } + } + } + const requestOptions = response.request.options; + const previousUrl = requestOptions.url ? new URL(requestOptions.url) : undefined; + const previousBoundary = getUrlPrefixBoundary(requestOptions); + const previousState = previousUrl ? snapshotCrossOriginState(requestOptions) : undefined; + // eslint-disable-next-line no-await-in-loop + const [optionsToMerge, changedState] = await requestOptions.trackStateMutations(async (changedState) => [ + pagination.paginate({ + response, + currentItems, + allItems, + }), + changedState, + ]); + if (optionsToMerge === false) { + return; + } + if (optionsToMerge === response.request.options) { + normalizedOptions = response.request.options; + normalizedOptions.clearUnchangedCookieHeader(previousState, changedState); + if (previousUrl) { + const nextUrl = normalizedOptions.url; + if (nextUrl + && hasUrlOrPrefixUrlBoundaryChanged(normalizedOptions, nextUrl, previousBoundary)) { + assertUrlHasSameOriginAsPrefixUrlIfNeeded(normalizedOptions, nextUrl); + } + if (nextUrl && !isSameOrigin(previousUrl, nextUrl)) { + normalizedOptions.prefixUrl = ''; + normalizedOptions.stripUnchangedCrossOriginState(previousState, changedState); + } + } + } + else { + const paginationOptions = normalizedOptions; + const paginationUrl = paginationOptions.url instanceof URL ? new URL(paginationOptions.url) : undefined; + const paginationBoundary = getUrlPrefixBoundary(paginationOptions); + const hasExplicitBody = (Object.hasOwn(optionsToMerge, 'body') && optionsToMerge.body !== undefined) + || (Object.hasOwn(optionsToMerge, 'json') && optionsToMerge.json !== undefined) + || (Object.hasOwn(optionsToMerge, 'form') && optionsToMerge.form !== undefined); + const clearsCookieJar = Object.hasOwn(optionsToMerge, 'cookieJar') && optionsToMerge.cookieJar === undefined; + if (hasExplicitBody) { + paginationOptions.clearBody(); + } + if (clearsCookieJar) { + paginationOptions.cookieJar = undefined; + } + const { url, ...optionsToMergeWithoutUrl } = optionsToMerge; + paginationOptions.merge(optionsToMergeWithoutUrl); + paginationOptions.syncCookieHeaderAfterMerge(previousState, optionsToMergeWithoutUrl.headers); + if (paginationOptions.url instanceof URL + && hasUrlOrPrefixUrlBoundaryChanged(paginationOptions, paginationOptions.url, paginationBoundary)) { + assertUrlHasSameOriginAsPrefixUrlIfNeeded(paginationOptions, paginationOptions.url); + } + if (url === undefined + && previousUrl + && paginationOptions.url instanceof URL + && !isSameOrigin(previousUrl, paginationOptions.url)) { + paginationOptions.stripSensitiveHeaders(previousUrl, paginationOptions.url, optionsToMerge); + if (!hasExplicitBody) { + paginationOptions.clearBody(); + } + } + if (previousUrl + && paginationUrl + && !isSameOrigin(paginationUrl, previousUrl)) { + paginationOptions.stripSensitiveHeaders(paginationUrl, previousUrl, optionsToMerge); + if (!hasExplicitBody) { + paginationOptions.clearBody(); + } + } + try { + assert.any([distribution.string, distribution.urlInstance, distribution.undefined], optionsToMerge.url); + } + catch (error) { + if (error instanceof Error) { + error.message = `Option 'pagination.paginate.url': ${error.message}`; + } + throw error; + } + if (url !== undefined) { + const nextUrl = applyUrlOverride(paginationOptions, url, { + ...optionsToMerge, + baseUrl: previousUrl, + }); + if (paginationOptions.prefixUrl.toString() !== paginationBoundary.prefixUrl + || paginationOptions.allowAbsoluteUrls !== paginationBoundary.allowAbsoluteUrls) { + assertUrlHasSameOriginAsPrefixUrlIfNeeded(paginationOptions, nextUrl); + } + if (previousUrl) { + paginationOptions.stripSensitiveHeaders(previousUrl, nextUrl, optionsToMerge); + if (!isSameOrigin(previousUrl, nextUrl) && !hasExplicitBody) { + paginationOptions.clearBody(); + } + } + } + normalizedOptions = paginationOptions; + } + numberOfRequests++; + } + }); + got.paginate = paginateEach; + got.paginate.all = (async (url, options) => Array.fromAsync(paginateEach(url, options))); + // For those who like very descriptive names + got.paginate.each = paginateEach; + // Stream API + got.stream = ((url, options) => makeRequest(url, options, defaults.options, true)); + // Shortcuts + for (const method of aliases) { + got[method] = ((url, options) => got(url, { ...options, method })); + got.stream[method] = ((url, options) => makeRequest(url, { ...options, method }, defaults.options, true)); + } + if (!defaults.mutableDefaults) { + Object.freeze(defaults.handlers); + defaults.options.freeze(); + } + Object.defineProperty(got, 'defaults', { + value: defaults, + writable: false, + configurable: false, + enumerable: true, + }); + return got; +}; +/* harmony default export */ const source_create = (create); + +;// CONCATENATED MODULE: ./node_modules/got/dist/source/index.js + + +const defaults = { + options: new Options(), + handlers: [], + mutableDefaults: false, +}; +const got = source_create(defaults); +/* harmony default export */ const source = (got); + + + + + + + + + + + +/***/ }) + +}; +; \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 53e42d95f..f6675fc77 100644 --- a/dist/index.js +++ b/dist/index.js @@ -13199,582 +13199,6 @@ class ReflectionTypeCheck { exports.ReflectionTypeCheck = ReflectionTypeCheck; -/***/ }), - -/***/ 64001: -/***/ ((module, exports) => { - -"use strict"; - -/// -/// -/// -Object.defineProperty(exports, "__esModule", ({ value: true })); -const typedArrayTypeNames = [ - 'Int8Array', - 'Uint8Array', - 'Uint8ClampedArray', - 'Int16Array', - 'Uint16Array', - 'Int32Array', - 'Uint32Array', - 'Float32Array', - 'Float64Array', - 'BigInt64Array', - 'BigUint64Array' -]; -function isTypedArrayName(name) { - return typedArrayTypeNames.includes(name); -} -const objectTypeNames = [ - 'Function', - 'Generator', - 'AsyncGenerator', - 'GeneratorFunction', - 'AsyncGeneratorFunction', - 'AsyncFunction', - 'Observable', - 'Array', - 'Buffer', - 'Blob', - 'Object', - 'RegExp', - 'Date', - 'Error', - 'Map', - 'Set', - 'WeakMap', - 'WeakSet', - 'ArrayBuffer', - 'SharedArrayBuffer', - 'DataView', - 'Promise', - 'URL', - 'FormData', - 'URLSearchParams', - 'HTMLElement', - ...typedArrayTypeNames -]; -function isObjectTypeName(name) { - return objectTypeNames.includes(name); -} -const primitiveTypeNames = [ - 'null', - 'undefined', - 'string', - 'number', - 'bigint', - 'boolean', - 'symbol' -]; -function isPrimitiveTypeName(name) { - return primitiveTypeNames.includes(name); -} -// eslint-disable-next-line @typescript-eslint/ban-types -function isOfType(type) { - return (value) => typeof value === type; -} -const { toString } = Object.prototype; -const getObjectType = (value) => { - const objectTypeName = toString.call(value).slice(8, -1); - if (/HTML\w+Element/.test(objectTypeName) && is.domElement(value)) { - return 'HTMLElement'; - } - if (isObjectTypeName(objectTypeName)) { - return objectTypeName; - } - return undefined; -}; -const isObjectOfType = (type) => (value) => getObjectType(value) === type; -function is(value) { - if (value === null) { - return 'null'; - } - switch (typeof value) { - case 'undefined': - return 'undefined'; - case 'string': - return 'string'; - case 'number': - return 'number'; - case 'boolean': - return 'boolean'; - case 'function': - return 'Function'; - case 'bigint': - return 'bigint'; - case 'symbol': - return 'symbol'; - default: - } - if (is.observable(value)) { - return 'Observable'; - } - if (is.array(value)) { - return 'Array'; - } - if (is.buffer(value)) { - return 'Buffer'; - } - const tagType = getObjectType(value); - if (tagType) { - return tagType; - } - if (value instanceof String || value instanceof Boolean || value instanceof Number) { - throw new TypeError('Please don\'t use object wrappers for primitive types'); - } - return 'Object'; -} -is.undefined = isOfType('undefined'); -is.string = isOfType('string'); -const isNumberType = isOfType('number'); -is.number = (value) => isNumberType(value) && !is.nan(value); -is.bigint = isOfType('bigint'); -// eslint-disable-next-line @typescript-eslint/ban-types -is.function_ = isOfType('function'); -is.null_ = (value) => value === null; -is.class_ = (value) => is.function_(value) && value.toString().startsWith('class '); -is.boolean = (value) => value === true || value === false; -is.symbol = isOfType('symbol'); -is.numericString = (value) => is.string(value) && !is.emptyStringOrWhitespace(value) && !Number.isNaN(Number(value)); -is.array = (value, assertion) => { - if (!Array.isArray(value)) { - return false; - } - if (!is.function_(assertion)) { - return true; - } - return value.every(assertion); -}; -is.buffer = (value) => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = value) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.isBuffer) === null || _c === void 0 ? void 0 : _c.call(_b, value)) !== null && _d !== void 0 ? _d : false; }; -is.blob = (value) => isObjectOfType('Blob')(value); -is.nullOrUndefined = (value) => is.null_(value) || is.undefined(value); -is.object = (value) => !is.null_(value) && (typeof value === 'object' || is.function_(value)); -is.iterable = (value) => { var _a; return is.function_((_a = value) === null || _a === void 0 ? void 0 : _a[Symbol.iterator]); }; -is.asyncIterable = (value) => { var _a; return is.function_((_a = value) === null || _a === void 0 ? void 0 : _a[Symbol.asyncIterator]); }; -is.generator = (value) => { var _a, _b; return is.iterable(value) && is.function_((_a = value) === null || _a === void 0 ? void 0 : _a.next) && is.function_((_b = value) === null || _b === void 0 ? void 0 : _b.throw); }; -is.asyncGenerator = (value) => is.asyncIterable(value) && is.function_(value.next) && is.function_(value.throw); -is.nativePromise = (value) => isObjectOfType('Promise')(value); -const hasPromiseAPI = (value) => { - var _a, _b; - return is.function_((_a = value) === null || _a === void 0 ? void 0 : _a.then) && - is.function_((_b = value) === null || _b === void 0 ? void 0 : _b.catch); -}; -is.promise = (value) => is.nativePromise(value) || hasPromiseAPI(value); -is.generatorFunction = isObjectOfType('GeneratorFunction'); -is.asyncGeneratorFunction = (value) => getObjectType(value) === 'AsyncGeneratorFunction'; -is.asyncFunction = (value) => getObjectType(value) === 'AsyncFunction'; -// eslint-disable-next-line no-prototype-builtins, @typescript-eslint/ban-types -is.boundFunction = (value) => is.function_(value) && !value.hasOwnProperty('prototype'); -is.regExp = isObjectOfType('RegExp'); -is.date = isObjectOfType('Date'); -is.error = isObjectOfType('Error'); -is.map = (value) => isObjectOfType('Map')(value); -is.set = (value) => isObjectOfType('Set')(value); -is.weakMap = (value) => isObjectOfType('WeakMap')(value); -is.weakSet = (value) => isObjectOfType('WeakSet')(value); -is.int8Array = isObjectOfType('Int8Array'); -is.uint8Array = isObjectOfType('Uint8Array'); -is.uint8ClampedArray = isObjectOfType('Uint8ClampedArray'); -is.int16Array = isObjectOfType('Int16Array'); -is.uint16Array = isObjectOfType('Uint16Array'); -is.int32Array = isObjectOfType('Int32Array'); -is.uint32Array = isObjectOfType('Uint32Array'); -is.float32Array = isObjectOfType('Float32Array'); -is.float64Array = isObjectOfType('Float64Array'); -is.bigInt64Array = isObjectOfType('BigInt64Array'); -is.bigUint64Array = isObjectOfType('BigUint64Array'); -is.arrayBuffer = isObjectOfType('ArrayBuffer'); -is.sharedArrayBuffer = isObjectOfType('SharedArrayBuffer'); -is.dataView = isObjectOfType('DataView'); -is.enumCase = (value, targetEnum) => Object.values(targetEnum).includes(value); -is.directInstanceOf = (instance, class_) => Object.getPrototypeOf(instance) === class_.prototype; -is.urlInstance = (value) => isObjectOfType('URL')(value); -is.urlString = (value) => { - if (!is.string(value)) { - return false; - } - try { - new URL(value); // eslint-disable-line no-new - return true; - } - catch (_a) { - return false; - } -}; -// Example: `is.truthy = (value: unknown): value is (not false | not 0 | not '' | not undefined | not null) => Boolean(value);` -is.truthy = (value) => Boolean(value); -// Example: `is.falsy = (value: unknown): value is (not true | 0 | '' | undefined | null) => Boolean(value);` -is.falsy = (value) => !value; -is.nan = (value) => Number.isNaN(value); -is.primitive = (value) => is.null_(value) || isPrimitiveTypeName(typeof value); -is.integer = (value) => Number.isInteger(value); -is.safeInteger = (value) => Number.isSafeInteger(value); -is.plainObject = (value) => { - // From: https://github.com/sindresorhus/is-plain-obj/blob/main/index.js - if (toString.call(value) !== '[object Object]') { - return false; - } - const prototype = Object.getPrototypeOf(value); - return prototype === null || prototype === Object.getPrototypeOf({}); -}; -is.typedArray = (value) => isTypedArrayName(getObjectType(value)); -const isValidLength = (value) => is.safeInteger(value) && value >= 0; -is.arrayLike = (value) => !is.nullOrUndefined(value) && !is.function_(value) && isValidLength(value.length); -is.inRange = (value, range) => { - if (is.number(range)) { - return value >= Math.min(0, range) && value <= Math.max(range, 0); - } - if (is.array(range) && range.length === 2) { - return value >= Math.min(...range) && value <= Math.max(...range); - } - throw new TypeError(`Invalid range: ${JSON.stringify(range)}`); -}; -const NODE_TYPE_ELEMENT = 1; -const DOM_PROPERTIES_TO_CHECK = [ - 'innerHTML', - 'ownerDocument', - 'style', - 'attributes', - 'nodeValue' -]; -is.domElement = (value) => { - return is.object(value) && - value.nodeType === NODE_TYPE_ELEMENT && - is.string(value.nodeName) && - !is.plainObject(value) && - DOM_PROPERTIES_TO_CHECK.every(property => property in value); -}; -is.observable = (value) => { - var _a, _b, _c, _d; - if (!value) { - return false; - } - // eslint-disable-next-line no-use-extend-native/no-use-extend-native - if (value === ((_b = (_a = value)[Symbol.observable]) === null || _b === void 0 ? void 0 : _b.call(_a))) { - return true; - } - if (value === ((_d = (_c = value)['@@observable']) === null || _d === void 0 ? void 0 : _d.call(_c))) { - return true; - } - return false; -}; -is.nodeStream = (value) => is.object(value) && is.function_(value.pipe) && !is.observable(value); -is.infinite = (value) => value === Infinity || value === -Infinity; -const isAbsoluteMod2 = (remainder) => (value) => is.integer(value) && Math.abs(value % 2) === remainder; -is.evenInteger = isAbsoluteMod2(0); -is.oddInteger = isAbsoluteMod2(1); -is.emptyArray = (value) => is.array(value) && value.length === 0; -is.nonEmptyArray = (value) => is.array(value) && value.length > 0; -is.emptyString = (value) => is.string(value) && value.length === 0; -const isWhiteSpaceString = (value) => is.string(value) && !/\S/.test(value); -is.emptyStringOrWhitespace = (value) => is.emptyString(value) || isWhiteSpaceString(value); -// TODO: Use `not ''` when the `not` operator is available. -is.nonEmptyString = (value) => is.string(value) && value.length > 0; -// TODO: Use `not ''` when the `not` operator is available. -is.nonEmptyStringAndNotWhitespace = (value) => is.string(value) && !is.emptyStringOrWhitespace(value); -is.emptyObject = (value) => is.object(value) && !is.map(value) && !is.set(value) && Object.keys(value).length === 0; -// TODO: Use `not` operator here to remove `Map` and `Set` from type guard: -// - https://github.com/Microsoft/TypeScript/pull/29317 -is.nonEmptyObject = (value) => is.object(value) && !is.map(value) && !is.set(value) && Object.keys(value).length > 0; -is.emptySet = (value) => is.set(value) && value.size === 0; -is.nonEmptySet = (value) => is.set(value) && value.size > 0; -is.emptyMap = (value) => is.map(value) && value.size === 0; -is.nonEmptyMap = (value) => is.map(value) && value.size > 0; -// `PropertyKey` is any value that can be used as an object key (string, number, or symbol) -is.propertyKey = (value) => is.any([is.string, is.number, is.symbol], value); -is.formData = (value) => isObjectOfType('FormData')(value); -is.urlSearchParams = (value) => isObjectOfType('URLSearchParams')(value); -const predicateOnArray = (method, predicate, values) => { - if (!is.function_(predicate)) { - throw new TypeError(`Invalid predicate: ${JSON.stringify(predicate)}`); - } - if (values.length === 0) { - throw new TypeError('Invalid number of values'); - } - return method.call(values, predicate); -}; -is.any = (predicate, ...values) => { - const predicates = is.array(predicate) ? predicate : [predicate]; - return predicates.some(singlePredicate => predicateOnArray(Array.prototype.some, singlePredicate, values)); -}; -is.all = (predicate, ...values) => predicateOnArray(Array.prototype.every, predicate, values); -const assertType = (condition, description, value, options = {}) => { - if (!condition) { - const { multipleValues } = options; - const valuesMessage = multipleValues ? - `received values of types ${[ - ...new Set(value.map(singleValue => `\`${is(singleValue)}\``)) - ].join(', ')}` : - `received value of type \`${is(value)}\``; - throw new TypeError(`Expected value which is \`${description}\`, ${valuesMessage}.`); - } -}; -exports.assert = { - // Unknowns. - undefined: (value) => assertType(is.undefined(value), 'undefined', value), - string: (value) => assertType(is.string(value), 'string', value), - number: (value) => assertType(is.number(value), 'number', value), - bigint: (value) => assertType(is.bigint(value), 'bigint', value), - // eslint-disable-next-line @typescript-eslint/ban-types - function_: (value) => assertType(is.function_(value), 'Function', value), - null_: (value) => assertType(is.null_(value), 'null', value), - class_: (value) => assertType(is.class_(value), "Class" /* class_ */, value), - boolean: (value) => assertType(is.boolean(value), 'boolean', value), - symbol: (value) => assertType(is.symbol(value), 'symbol', value), - numericString: (value) => assertType(is.numericString(value), "string with a number" /* numericString */, value), - array: (value, assertion) => { - const assert = assertType; - assert(is.array(value), 'Array', value); - if (assertion) { - value.forEach(assertion); - } - }, - buffer: (value) => assertType(is.buffer(value), 'Buffer', value), - blob: (value) => assertType(is.blob(value), 'Blob', value), - nullOrUndefined: (value) => assertType(is.nullOrUndefined(value), "null or undefined" /* nullOrUndefined */, value), - object: (value) => assertType(is.object(value), 'Object', value), - iterable: (value) => assertType(is.iterable(value), "Iterable" /* iterable */, value), - asyncIterable: (value) => assertType(is.asyncIterable(value), "AsyncIterable" /* asyncIterable */, value), - generator: (value) => assertType(is.generator(value), 'Generator', value), - asyncGenerator: (value) => assertType(is.asyncGenerator(value), 'AsyncGenerator', value), - nativePromise: (value) => assertType(is.nativePromise(value), "native Promise" /* nativePromise */, value), - promise: (value) => assertType(is.promise(value), 'Promise', value), - generatorFunction: (value) => assertType(is.generatorFunction(value), 'GeneratorFunction', value), - asyncGeneratorFunction: (value) => assertType(is.asyncGeneratorFunction(value), 'AsyncGeneratorFunction', value), - // eslint-disable-next-line @typescript-eslint/ban-types - asyncFunction: (value) => assertType(is.asyncFunction(value), 'AsyncFunction', value), - // eslint-disable-next-line @typescript-eslint/ban-types - boundFunction: (value) => assertType(is.boundFunction(value), 'Function', value), - regExp: (value) => assertType(is.regExp(value), 'RegExp', value), - date: (value) => assertType(is.date(value), 'Date', value), - error: (value) => assertType(is.error(value), 'Error', value), - map: (value) => assertType(is.map(value), 'Map', value), - set: (value) => assertType(is.set(value), 'Set', value), - weakMap: (value) => assertType(is.weakMap(value), 'WeakMap', value), - weakSet: (value) => assertType(is.weakSet(value), 'WeakSet', value), - int8Array: (value) => assertType(is.int8Array(value), 'Int8Array', value), - uint8Array: (value) => assertType(is.uint8Array(value), 'Uint8Array', value), - uint8ClampedArray: (value) => assertType(is.uint8ClampedArray(value), 'Uint8ClampedArray', value), - int16Array: (value) => assertType(is.int16Array(value), 'Int16Array', value), - uint16Array: (value) => assertType(is.uint16Array(value), 'Uint16Array', value), - int32Array: (value) => assertType(is.int32Array(value), 'Int32Array', value), - uint32Array: (value) => assertType(is.uint32Array(value), 'Uint32Array', value), - float32Array: (value) => assertType(is.float32Array(value), 'Float32Array', value), - float64Array: (value) => assertType(is.float64Array(value), 'Float64Array', value), - bigInt64Array: (value) => assertType(is.bigInt64Array(value), 'BigInt64Array', value), - bigUint64Array: (value) => assertType(is.bigUint64Array(value), 'BigUint64Array', value), - arrayBuffer: (value) => assertType(is.arrayBuffer(value), 'ArrayBuffer', value), - sharedArrayBuffer: (value) => assertType(is.sharedArrayBuffer(value), 'SharedArrayBuffer', value), - dataView: (value) => assertType(is.dataView(value), 'DataView', value), - enumCase: (value, targetEnum) => assertType(is.enumCase(value, targetEnum), 'EnumCase', value), - urlInstance: (value) => assertType(is.urlInstance(value), 'URL', value), - urlString: (value) => assertType(is.urlString(value), "string with a URL" /* urlString */, value), - truthy: (value) => assertType(is.truthy(value), "truthy" /* truthy */, value), - falsy: (value) => assertType(is.falsy(value), "falsy" /* falsy */, value), - nan: (value) => assertType(is.nan(value), "NaN" /* nan */, value), - primitive: (value) => assertType(is.primitive(value), "primitive" /* primitive */, value), - integer: (value) => assertType(is.integer(value), "integer" /* integer */, value), - safeInteger: (value) => assertType(is.safeInteger(value), "integer" /* safeInteger */, value), - plainObject: (value) => assertType(is.plainObject(value), "plain object" /* plainObject */, value), - typedArray: (value) => assertType(is.typedArray(value), "TypedArray" /* typedArray */, value), - arrayLike: (value) => assertType(is.arrayLike(value), "array-like" /* arrayLike */, value), - domElement: (value) => assertType(is.domElement(value), "HTMLElement" /* domElement */, value), - observable: (value) => assertType(is.observable(value), 'Observable', value), - nodeStream: (value) => assertType(is.nodeStream(value), "Node.js Stream" /* nodeStream */, value), - infinite: (value) => assertType(is.infinite(value), "infinite number" /* infinite */, value), - emptyArray: (value) => assertType(is.emptyArray(value), "empty array" /* emptyArray */, value), - nonEmptyArray: (value) => assertType(is.nonEmptyArray(value), "non-empty array" /* nonEmptyArray */, value), - emptyString: (value) => assertType(is.emptyString(value), "empty string" /* emptyString */, value), - emptyStringOrWhitespace: (value) => assertType(is.emptyStringOrWhitespace(value), "empty string or whitespace" /* emptyStringOrWhitespace */, value), - nonEmptyString: (value) => assertType(is.nonEmptyString(value), "non-empty string" /* nonEmptyString */, value), - nonEmptyStringAndNotWhitespace: (value) => assertType(is.nonEmptyStringAndNotWhitespace(value), "non-empty string and not whitespace" /* nonEmptyStringAndNotWhitespace */, value), - emptyObject: (value) => assertType(is.emptyObject(value), "empty object" /* emptyObject */, value), - nonEmptyObject: (value) => assertType(is.nonEmptyObject(value), "non-empty object" /* nonEmptyObject */, value), - emptySet: (value) => assertType(is.emptySet(value), "empty set" /* emptySet */, value), - nonEmptySet: (value) => assertType(is.nonEmptySet(value), "non-empty set" /* nonEmptySet */, value), - emptyMap: (value) => assertType(is.emptyMap(value), "empty map" /* emptyMap */, value), - nonEmptyMap: (value) => assertType(is.nonEmptyMap(value), "non-empty map" /* nonEmptyMap */, value), - propertyKey: (value) => assertType(is.propertyKey(value), 'PropertyKey', value), - formData: (value) => assertType(is.formData(value), 'FormData', value), - urlSearchParams: (value) => assertType(is.urlSearchParams(value), 'URLSearchParams', value), - // Numbers. - evenInteger: (value) => assertType(is.evenInteger(value), "even integer" /* evenInteger */, value), - oddInteger: (value) => assertType(is.oddInteger(value), "odd integer" /* oddInteger */, value), - // Two arguments. - directInstanceOf: (instance, class_) => assertType(is.directInstanceOf(instance, class_), "T" /* directInstanceOf */, instance), - inRange: (value, range) => assertType(is.inRange(value, range), "in range" /* inRange */, value), - // Variadic functions. - any: (predicate, ...values) => { - return assertType(is.any(predicate, ...values), "predicate returns truthy for any value" /* any */, values, { multipleValues: true }); - }, - all: (predicate, ...values) => assertType(is.all(predicate, ...values), "predicate returns truthy for all values" /* all */, values, { multipleValues: true }) -}; -// Some few keywords are reserved, but we'll populate them for Node.js users -// See https://github.com/Microsoft/TypeScript/issues/2536 -Object.defineProperties(is, { - class: { - value: is.class_ - }, - function: { - value: is.function_ - }, - null: { - value: is.null_ - } -}); -Object.defineProperties(exports.assert, { - class: { - value: exports.assert.class_ - }, - function: { - value: exports.assert.function_ - }, - null: { - value: exports.assert.null_ - } -}); -exports["default"] = is; -// For CommonJS default export support -module.exports = is; -module.exports["default"] = is; -module.exports.assert = exports.assert; - - -/***/ }), - -/***/ 24480: -/***/ ((module, exports, __nccwpck_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -const defer_to_connect_1 = __nccwpck_require__(82114); -const util_1 = __nccwpck_require__(39023); -const nodejsMajorVersion = Number(process.versions.node.split('.')[0]); -const timer = (request) => { - if (request.timings) { - return request.timings; - } - const timings = { - start: Date.now(), - socket: undefined, - lookup: undefined, - connect: undefined, - secureConnect: undefined, - upload: undefined, - response: undefined, - end: undefined, - error: undefined, - abort: undefined, - phases: { - wait: undefined, - dns: undefined, - tcp: undefined, - tls: undefined, - request: undefined, - firstByte: undefined, - download: undefined, - total: undefined - } - }; - request.timings = timings; - const handleError = (origin) => { - const emit = origin.emit.bind(origin); - origin.emit = (event, ...args) => { - // Catches the `error` event - if (event === 'error') { - timings.error = Date.now(); - timings.phases.total = timings.error - timings.start; - origin.emit = emit; - } - // Saves the original behavior - return emit(event, ...args); - }; - }; - handleError(request); - const onAbort = () => { - timings.abort = Date.now(); - // Let the `end` response event be responsible for setting the total phase, - // unless the Node.js major version is >= 13. - if (!timings.response || nodejsMajorVersion >= 13) { - timings.phases.total = Date.now() - timings.start; - } - }; - request.prependOnceListener('abort', onAbort); - const onSocket = (socket) => { - timings.socket = Date.now(); - timings.phases.wait = timings.socket - timings.start; - if (util_1.types.isProxy(socket)) { - return; - } - const lookupListener = () => { - timings.lookup = Date.now(); - timings.phases.dns = timings.lookup - timings.socket; - }; - socket.prependOnceListener('lookup', lookupListener); - defer_to_connect_1.default(socket, { - connect: () => { - timings.connect = Date.now(); - if (timings.lookup === undefined) { - socket.removeListener('lookup', lookupListener); - timings.lookup = timings.connect; - timings.phases.dns = timings.lookup - timings.socket; - } - timings.phases.tcp = timings.connect - timings.lookup; - // This callback is called before flushing any data, - // so we don't need to set `timings.phases.request` here. - }, - secureConnect: () => { - timings.secureConnect = Date.now(); - timings.phases.tls = timings.secureConnect - timings.connect; - } - }); - }; - if (request.socket) { - onSocket(request.socket); - } - else { - request.prependOnceListener('socket', onSocket); - } - const onUpload = () => { - var _a; - timings.upload = Date.now(); - timings.phases.request = timings.upload - ((_a = timings.secureConnect) !== null && _a !== void 0 ? _a : timings.connect); - }; - const writableFinished = () => { - if (typeof request.writableFinished === 'boolean') { - return request.writableFinished; - } - // Node.js doesn't have `request.writableFinished` property - return request.finished && request.outputSize === 0 && (!request.socket || request.socket.writableLength === 0); - }; - if (writableFinished()) { - onUpload(); - } - else { - request.prependOnceListener('finish', onUpload); - } - request.prependOnceListener('response', (response) => { - timings.response = Date.now(); - timings.phases.firstByte = timings.response - timings.upload; - response.timings = timings; - handleError(response); - response.prependOnceListener('end', () => { - timings.end = Date.now(); - timings.phases.download = timings.end - timings.response; - timings.phases.total = timings.end - timings.start; - }); - response.prependOnceListener('aborted', onAbort); - }); - return timings; -}; -exports["default"] = timer; -// For CommonJS default export support -module.exports = timer; -module.exports["default"] = timer; - - /***/ }), /***/ 15183: @@ -16341,734 +15765,6 @@ exports.flatten = (...args) => { }; -/***/ }), - -/***/ 82417: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - -const { - V4MAPPED, - ADDRCONFIG, - ALL, - promises: { - Resolver: AsyncResolver - }, - lookup: dnsLookup -} = __nccwpck_require__(72250); -const {promisify} = __nccwpck_require__(39023); -const os = __nccwpck_require__(70857); - -const kCacheableLookupCreateConnection = Symbol('cacheableLookupCreateConnection'); -const kCacheableLookupInstance = Symbol('cacheableLookupInstance'); -const kExpires = Symbol('expires'); - -const supportsALL = typeof ALL === 'number'; - -const verifyAgent = agent => { - if (!(agent && typeof agent.createConnection === 'function')) { - throw new Error('Expected an Agent instance as the first argument'); - } -}; - -const map4to6 = entries => { - for (const entry of entries) { - if (entry.family === 6) { - continue; - } - - entry.address = `::ffff:${entry.address}`; - entry.family = 6; - } -}; - -const getIfaceInfo = () => { - let has4 = false; - let has6 = false; - - for (const device of Object.values(os.networkInterfaces())) { - for (const iface of device) { - if (iface.internal) { - continue; - } - - if (iface.family === 'IPv6') { - has6 = true; - } else { - has4 = true; - } - - if (has4 && has6) { - return {has4, has6}; - } - } - } - - return {has4, has6}; -}; - -const isIterable = map => { - return Symbol.iterator in map; -}; - -const ttl = {ttl: true}; -const all = {all: true}; - -class CacheableLookup { - constructor({ - cache = new Map(), - maxTtl = Infinity, - fallbackDuration = 3600, - errorTtl = 0.15, - resolver = new AsyncResolver(), - lookup = dnsLookup - } = {}) { - this.maxTtl = maxTtl; - this.errorTtl = errorTtl; - - this._cache = cache; - this._resolver = resolver; - this._dnsLookup = promisify(lookup); - - if (this._resolver instanceof AsyncResolver) { - this._resolve4 = this._resolver.resolve4.bind(this._resolver); - this._resolve6 = this._resolver.resolve6.bind(this._resolver); - } else { - this._resolve4 = promisify(this._resolver.resolve4.bind(this._resolver)); - this._resolve6 = promisify(this._resolver.resolve6.bind(this._resolver)); - } - - this._iface = getIfaceInfo(); - - this._pending = {}; - this._nextRemovalTime = false; - this._hostnamesToFallback = new Set(); - - if (fallbackDuration < 1) { - this._fallback = false; - } else { - this._fallback = true; - - const interval = setInterval(() => { - this._hostnamesToFallback.clear(); - }, fallbackDuration * 1000); - - /* istanbul ignore next: There is no `interval.unref()` when running inside an Electron renderer */ - if (interval.unref) { - interval.unref(); - } - } - - this.lookup = this.lookup.bind(this); - this.lookupAsync = this.lookupAsync.bind(this); - } - - set servers(servers) { - this.clear(); - - this._resolver.setServers(servers); - } - - get servers() { - return this._resolver.getServers(); - } - - lookup(hostname, options, callback) { - if (typeof options === 'function') { - callback = options; - options = {}; - } else if (typeof options === 'number') { - options = { - family: options - }; - } - - if (!callback) { - throw new Error('Callback must be a function.'); - } - - // eslint-disable-next-line promise/prefer-await-to-then - this.lookupAsync(hostname, options).then(result => { - if (options.all) { - callback(null, result); - } else { - callback(null, result.address, result.family, result.expires, result.ttl); - } - }, callback); - } - - async lookupAsync(hostname, options = {}) { - if (typeof options === 'number') { - options = { - family: options - }; - } - - let cached = await this.query(hostname); - - if (options.family === 6) { - const filtered = cached.filter(entry => entry.family === 6); - - if (options.hints & V4MAPPED) { - if ((supportsALL && options.hints & ALL) || filtered.length === 0) { - map4to6(cached); - } else { - cached = filtered; - } - } else { - cached = filtered; - } - } else if (options.family === 4) { - cached = cached.filter(entry => entry.family === 4); - } - - if (options.hints & ADDRCONFIG) { - const {_iface} = this; - cached = cached.filter(entry => entry.family === 6 ? _iface.has6 : _iface.has4); - } - - if (cached.length === 0) { - const error = new Error(`cacheableLookup ENOTFOUND ${hostname}`); - error.code = 'ENOTFOUND'; - error.hostname = hostname; - - throw error; - } - - if (options.all) { - return cached; - } - - return cached[0]; - } - - async query(hostname) { - let cached = await this._cache.get(hostname); - - if (!cached) { - const pending = this._pending[hostname]; - - if (pending) { - cached = await pending; - } else { - const newPromise = this.queryAndCache(hostname); - this._pending[hostname] = newPromise; - - try { - cached = await newPromise; - } finally { - delete this._pending[hostname]; - } - } - } - - cached = cached.map(entry => { - return {...entry}; - }); - - return cached; - } - - async _resolve(hostname) { - const wrap = async promise => { - try { - return await promise; - } catch (error) { - if (error.code === 'ENODATA' || error.code === 'ENOTFOUND') { - return []; - } - - throw error; - } - }; - - // ANY is unsafe as it doesn't trigger new queries in the underlying server. - const [A, AAAA] = await Promise.all([ - this._resolve4(hostname, ttl), - this._resolve6(hostname, ttl) - ].map(promise => wrap(promise))); - - let aTtl = 0; - let aaaaTtl = 0; - let cacheTtl = 0; - - const now = Date.now(); - - for (const entry of A) { - entry.family = 4; - entry.expires = now + (entry.ttl * 1000); - - aTtl = Math.max(aTtl, entry.ttl); - } - - for (const entry of AAAA) { - entry.family = 6; - entry.expires = now + (entry.ttl * 1000); - - aaaaTtl = Math.max(aaaaTtl, entry.ttl); - } - - if (A.length > 0) { - if (AAAA.length > 0) { - cacheTtl = Math.min(aTtl, aaaaTtl); - } else { - cacheTtl = aTtl; - } - } else { - cacheTtl = aaaaTtl; - } - - return { - entries: [ - ...A, - ...AAAA - ], - cacheTtl - }; - } - - async _lookup(hostname) { - try { - const entries = await this._dnsLookup(hostname, { - all: true - }); - - return { - entries, - cacheTtl: 0 - }; - } catch (_) { - return { - entries: [], - cacheTtl: 0 - }; - } - } - - async _set(hostname, data, cacheTtl) { - if (this.maxTtl > 0 && cacheTtl > 0) { - cacheTtl = Math.min(cacheTtl, this.maxTtl) * 1000; - data[kExpires] = Date.now() + cacheTtl; - - try { - await this._cache.set(hostname, data, cacheTtl); - } catch (error) { - this.lookupAsync = async () => { - const cacheError = new Error('Cache Error. Please recreate the CacheableLookup instance.'); - cacheError.cause = error; - - throw cacheError; - }; - } - - if (isIterable(this._cache)) { - this._tick(cacheTtl); - } - } - } - - async queryAndCache(hostname) { - if (this._hostnamesToFallback.has(hostname)) { - return this._dnsLookup(hostname, all); - } - - let query = await this._resolve(hostname); - - if (query.entries.length === 0 && this._fallback) { - query = await this._lookup(hostname); - - if (query.entries.length !== 0) { - // Use `dns.lookup(...)` for that particular hostname - this._hostnamesToFallback.add(hostname); - } - } - - const cacheTtl = query.entries.length === 0 ? this.errorTtl : query.cacheTtl; - await this._set(hostname, query.entries, cacheTtl); - - return query.entries; - } - - _tick(ms) { - const nextRemovalTime = this._nextRemovalTime; - - if (!nextRemovalTime || ms < nextRemovalTime) { - clearTimeout(this._removalTimeout); - - this._nextRemovalTime = ms; - - this._removalTimeout = setTimeout(() => { - this._nextRemovalTime = false; - - let nextExpiry = Infinity; - - const now = Date.now(); - - for (const [hostname, entries] of this._cache) { - const expires = entries[kExpires]; - - if (now >= expires) { - this._cache.delete(hostname); - } else if (expires < nextExpiry) { - nextExpiry = expires; - } - } - - if (nextExpiry !== Infinity) { - this._tick(nextExpiry - now); - } - }, ms); - - /* istanbul ignore next: There is no `timeout.unref()` when running inside an Electron renderer */ - if (this._removalTimeout.unref) { - this._removalTimeout.unref(); - } - } - } - - install(agent) { - verifyAgent(agent); - - if (kCacheableLookupCreateConnection in agent) { - throw new Error('CacheableLookup has been already installed'); - } - - agent[kCacheableLookupCreateConnection] = agent.createConnection; - agent[kCacheableLookupInstance] = this; - - agent.createConnection = (options, callback) => { - if (!('lookup' in options)) { - options.lookup = this.lookup; - } - - return agent[kCacheableLookupCreateConnection](options, callback); - }; - } - - uninstall(agent) { - verifyAgent(agent); - - if (agent[kCacheableLookupCreateConnection]) { - if (agent[kCacheableLookupInstance] !== this) { - throw new Error('The agent is not owned by this CacheableLookup instance'); - } - - agent.createConnection = agent[kCacheableLookupCreateConnection]; - - delete agent[kCacheableLookupCreateConnection]; - delete agent[kCacheableLookupInstance]; - } - } - - updateInterfaceInfo() { - const {_iface} = this; - - this._iface = getIfaceInfo(); - - if ((_iface.has4 && !this._iface.has4) || (_iface.has6 && !this._iface.has6)) { - this._cache.clear(); - } - } - - clear(hostname) { - if (hostname) { - this._cache.delete(hostname); - return; - } - - this._cache.clear(); - } -} - -module.exports = CacheableLookup; -module.exports["default"] = CacheableLookup; - - -/***/ }), - -/***/ 21487: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const EventEmitter = __nccwpck_require__(24434); -const urlLib = __nccwpck_require__(87016); -const normalizeUrl = __nccwpck_require__(7827); -const getStream = __nccwpck_require__(96771); -const CachePolicy = __nccwpck_require__(12203); -const Response = __nccwpck_require__(74145); -const lowercaseKeys = __nccwpck_require__(11364); -const cloneResponse = __nccwpck_require__(36358); -const Keyv = __nccwpck_require__(76018); - -class CacheableRequest { - constructor(request, cacheAdapter) { - if (typeof request !== 'function') { - throw new TypeError('Parameter `request` must be a function'); - } - - this.cache = new Keyv({ - uri: typeof cacheAdapter === 'string' && cacheAdapter, - store: typeof cacheAdapter !== 'string' && cacheAdapter, - namespace: 'cacheable-request' - }); - - return this.createCacheableRequest(request); - } - - createCacheableRequest(request) { - return (opts, cb) => { - let url; - if (typeof opts === 'string') { - url = normalizeUrlObject(urlLib.parse(opts)); - opts = {}; - } else if (opts instanceof urlLib.URL) { - url = normalizeUrlObject(urlLib.parse(opts.toString())); - opts = {}; - } else { - const [pathname, ...searchParts] = (opts.path || '').split('?'); - const search = searchParts.length > 0 ? - `?${searchParts.join('?')}` : - ''; - url = normalizeUrlObject({ ...opts, pathname, search }); - } - - opts = { - headers: {}, - method: 'GET', - cache: true, - strictTtl: false, - automaticFailover: false, - ...opts, - ...urlObjectToRequestOptions(url) - }; - opts.headers = lowercaseKeys(opts.headers); - - const ee = new EventEmitter(); - const normalizedUrlString = normalizeUrl( - urlLib.format(url), - { - stripWWW: false, - removeTrailingSlash: false, - stripAuthentication: false - } - ); - const key = `${opts.method}:${normalizedUrlString}`; - let revalidate = false; - let madeRequest = false; - - const makeRequest = opts => { - madeRequest = true; - let requestErrored = false; - let requestErrorCallback; - - const requestErrorPromise = new Promise(resolve => { - requestErrorCallback = () => { - if (!requestErrored) { - requestErrored = true; - resolve(); - } - }; - }); - - const handler = response => { - if (revalidate && !opts.forceRefresh) { - response.status = response.statusCode; - const revalidatedPolicy = CachePolicy.fromObject(revalidate.cachePolicy).revalidatedPolicy(opts, response); - if (!revalidatedPolicy.modified) { - const headers = revalidatedPolicy.policy.responseHeaders(); - response = new Response(revalidate.statusCode, headers, revalidate.body, revalidate.url); - response.cachePolicy = revalidatedPolicy.policy; - response.fromCache = true; - } - } - - if (!response.fromCache) { - response.cachePolicy = new CachePolicy(opts, response, opts); - response.fromCache = false; - } - - let clonedResponse; - if (opts.cache && response.cachePolicy.storable()) { - clonedResponse = cloneResponse(response); - - (async () => { - try { - const bodyPromise = getStream.buffer(response); - - await Promise.race([ - requestErrorPromise, - new Promise(resolve => response.once('end', resolve)) - ]); - - if (requestErrored) { - return; - } - - const body = await bodyPromise; - - const value = { - cachePolicy: response.cachePolicy.toObject(), - url: response.url, - statusCode: response.fromCache ? revalidate.statusCode : response.statusCode, - body - }; - - let ttl = opts.strictTtl ? response.cachePolicy.timeToLive() : undefined; - if (opts.maxTtl) { - ttl = ttl ? Math.min(ttl, opts.maxTtl) : opts.maxTtl; - } - - await this.cache.set(key, value, ttl); - } catch (error) { - ee.emit('error', new CacheableRequest.CacheError(error)); - } - })(); - } else if (opts.cache && revalidate) { - (async () => { - try { - await this.cache.delete(key); - } catch (error) { - ee.emit('error', new CacheableRequest.CacheError(error)); - } - })(); - } - - ee.emit('response', clonedResponse || response); - if (typeof cb === 'function') { - cb(clonedResponse || response); - } - }; - - try { - const req = request(opts, handler); - req.once('error', requestErrorCallback); - req.once('abort', requestErrorCallback); - ee.emit('request', req); - } catch (error) { - ee.emit('error', new CacheableRequest.RequestError(error)); - } - }; - - (async () => { - const get = async opts => { - await Promise.resolve(); - - const cacheEntry = opts.cache ? await this.cache.get(key) : undefined; - if (typeof cacheEntry === 'undefined') { - return makeRequest(opts); - } - - const policy = CachePolicy.fromObject(cacheEntry.cachePolicy); - if (policy.satisfiesWithoutRevalidation(opts) && !opts.forceRefresh) { - const headers = policy.responseHeaders(); - const response = new Response(cacheEntry.statusCode, headers, cacheEntry.body, cacheEntry.url); - response.cachePolicy = policy; - response.fromCache = true; - - ee.emit('response', response); - if (typeof cb === 'function') { - cb(response); - } - } else { - revalidate = cacheEntry; - opts.headers = policy.revalidationHeaders(opts); - makeRequest(opts); - } - }; - - const errorHandler = error => ee.emit('error', new CacheableRequest.CacheError(error)); - this.cache.once('error', errorHandler); - ee.on('response', () => this.cache.removeListener('error', errorHandler)); - - try { - await get(opts); - } catch (error) { - if (opts.automaticFailover && !madeRequest) { - makeRequest(opts); - } - - ee.emit('error', new CacheableRequest.CacheError(error)); - } - })(); - - return ee; - }; - } -} - -function urlObjectToRequestOptions(url) { - const options = { ...url }; - options.path = `${url.pathname || '/'}${url.search || ''}`; - delete options.pathname; - delete options.search; - return options; -} - -function normalizeUrlObject(url) { - // If url was parsed by url.parse or new URL: - // - hostname will be set - // - host will be hostname[:port] - // - port will be set if it was explicit in the parsed string - // Otherwise, url was from request options: - // - hostname or host may be set - // - host shall not have port encoded - return { - protocol: url.protocol, - auth: url.auth, - hostname: url.hostname || url.host || 'localhost', - port: url.port, - pathname: url.pathname, - search: url.search - }; -} - -CacheableRequest.RequestError = class extends Error { - constructor(error) { - super(error.message); - this.name = 'RequestError'; - Object.assign(this, error); - } -}; - -CacheableRequest.CacheError = class extends Error { - constructor(error) { - super(error.message); - this.name = 'CacheError'; - Object.assign(this, error); - } -}; - -module.exports = CacheableRequest; - - -/***/ }), - -/***/ 36358: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const PassThrough = (__nccwpck_require__(2203).PassThrough); -const mimicResponse = __nccwpck_require__(69991); - -const cloneResponse = response => { - if (!(response && response.pipe)) { - throw new TypeError('Parameter `response` must be a response stream.'); - } - - const clone = new PassThrough(); - mimicResponse(response, clone); - - return response.pipe(clone); -}; - -module.exports = cloneResponse; - - /***/ }), /***/ 97087: @@ -17954,313 +16650,6 @@ formatters.O = function (v) { }; -/***/ }), - -/***/ 21373: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - -const {Transform, PassThrough} = __nccwpck_require__(2203); -const zlib = __nccwpck_require__(43106); -const mimicResponse = __nccwpck_require__(49382); - -module.exports = response => { - const contentEncoding = (response.headers['content-encoding'] || '').toLowerCase(); - - if (!['gzip', 'deflate', 'br'].includes(contentEncoding)) { - return response; - } - - // TODO: Remove this when targeting Node.js 12. - const isBrotli = contentEncoding === 'br'; - if (isBrotli && typeof zlib.createBrotliDecompress !== 'function') { - response.destroy(new Error('Brotli is not supported on Node.js < 12')); - return response; - } - - let isEmpty = true; - - const checker = new Transform({ - transform(data, _encoding, callback) { - isEmpty = false; - - callback(null, data); - }, - - flush(callback) { - callback(); - } - }); - - const finalStream = new PassThrough({ - autoDestroy: false, - destroy(error, callback) { - response.destroy(); - - callback(error); - } - }); - - const decompressStream = isBrotli ? zlib.createBrotliDecompress() : zlib.createUnzip(); - - decompressStream.once('error', error => { - if (isEmpty && !response.readable) { - finalStream.end(); - return; - } - - finalStream.destroy(error); - }); - - mimicResponse(response, finalStream); - response.pipe(checker).pipe(decompressStream).pipe(finalStream); - - return finalStream; -}; - - -/***/ }), - -/***/ 49382: -/***/ ((module) => { - -"use strict"; - - -// We define these manually to ensure they're always copied -// even if they would move up the prototype chain -// https://nodejs.org/api/http.html#http_class_http_incomingmessage -const knownProperties = [ - 'aborted', - 'complete', - 'headers', - 'httpVersion', - 'httpVersionMinor', - 'httpVersionMajor', - 'method', - 'rawHeaders', - 'rawTrailers', - 'setTimeout', - 'socket', - 'statusCode', - 'statusMessage', - 'trailers', - 'url' -]; - -module.exports = (fromStream, toStream) => { - if (toStream._readableState.autoDestroy) { - throw new Error('The second stream must have the `autoDestroy` option set to `false`'); - } - - const fromProperties = new Set(Object.keys(fromStream).concat(knownProperties)); - - const properties = {}; - - for (const property of fromProperties) { - // Don't overwrite existing properties. - if (property in toStream) { - continue; - } - - properties[property] = { - get() { - const value = fromStream[property]; - const isFunction = typeof value === 'function'; - - return isFunction ? value.bind(fromStream) : value; - }, - set(value) { - fromStream[property] = value; - }, - enumerable: true, - configurable: false - }; - } - - Object.defineProperties(toStream, properties); - - fromStream.once('aborted', () => { - toStream.destroy(); - - toStream.emit('aborted'); - }); - - fromStream.once('close', () => { - if (fromStream.complete) { - if (toStream.readable) { - toStream.once('end', () => { - toStream.emit('close'); - }); - } else { - toStream.emit('close'); - } - } else { - toStream.emit('close'); - } - }); - - return toStream; -}; - - -/***/ }), - -/***/ 82114: -/***/ ((module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -function isTLSSocket(socket) { - return socket.encrypted; -} -const deferToConnect = (socket, fn) => { - let listeners; - if (typeof fn === 'function') { - const connect = fn; - listeners = { connect }; - } - else { - listeners = fn; - } - const hasConnectListener = typeof listeners.connect === 'function'; - const hasSecureConnectListener = typeof listeners.secureConnect === 'function'; - const hasCloseListener = typeof listeners.close === 'function'; - const onConnect = () => { - if (hasConnectListener) { - listeners.connect(); - } - if (isTLSSocket(socket) && hasSecureConnectListener) { - if (socket.authorized) { - listeners.secureConnect(); - } - else if (!socket.authorizationError) { - socket.once('secureConnect', listeners.secureConnect); - } - } - if (hasCloseListener) { - socket.once('close', listeners.close); - } - }; - if (socket.writable && !socket.connecting) { - onConnect(); - } - else if (socket.connecting) { - socket.once('connect', onConnect); - } - else if (socket.destroyed && hasCloseListener) { - listeners.close(socket._hadError); - } -}; -exports["default"] = deferToConnect; -// For CommonJS default export support -module.exports = deferToConnect; -module.exports["default"] = deferToConnect; - - -/***/ }), - -/***/ 31424: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -var once = __nccwpck_require__(55560); - -var noop = function() {}; - -var isRequest = function(stream) { - return stream.setHeader && typeof stream.abort === 'function'; -}; - -var isChildProcess = function(stream) { - return stream.stdio && Array.isArray(stream.stdio) && stream.stdio.length === 3 -}; - -var eos = function(stream, opts, callback) { - if (typeof opts === 'function') return eos(stream, null, opts); - if (!opts) opts = {}; - - callback = once(callback || noop); - - var ws = stream._writableState; - var rs = stream._readableState; - var readable = opts.readable || (opts.readable !== false && stream.readable); - var writable = opts.writable || (opts.writable !== false && stream.writable); - var cancelled = false; - - var onlegacyfinish = function() { - if (!stream.writable) onfinish(); - }; - - var onfinish = function() { - writable = false; - if (!readable) callback.call(stream); - }; - - var onend = function() { - readable = false; - if (!writable) callback.call(stream); - }; - - var onexit = function(exitCode) { - callback.call(stream, exitCode ? new Error('exited with error code: ' + exitCode) : null); - }; - - var onerror = function(err) { - callback.call(stream, err); - }; - - var onclose = function() { - process.nextTick(onclosenexttick); - }; - - var onclosenexttick = function() { - if (cancelled) return; - if (readable && !(rs && (rs.ended && !rs.destroyed))) return callback.call(stream, new Error('premature close')); - if (writable && !(ws && (ws.ended && !ws.destroyed))) return callback.call(stream, new Error('premature close')); - }; - - var onrequest = function() { - stream.req.on('finish', onfinish); - }; - - if (isRequest(stream)) { - stream.on('complete', onfinish); - stream.on('abort', onclose); - if (stream.req) onrequest(); - else stream.on('request', onrequest); - } else if (writable && !ws) { // legacy streams - stream.on('end', onlegacyfinish); - stream.on('close', onlegacyfinish); - } - - if (isChildProcess(stream)) stream.on('exit', onexit); - - stream.on('end', onend); - stream.on('finish', onfinish); - if (opts.error !== false) stream.on('error', onerror); - stream.on('close', onclose); - - return function() { - cancelled = true; - stream.removeListener('complete', onfinish); - stream.removeListener('abort', onclose); - stream.removeListener('request', onrequest); - if (stream.req) stream.req.removeListener('finish', onfinish); - stream.removeListener('end', onlegacyfinish); - stream.removeListener('close', onlegacyfinish); - stream.removeListener('finish', onfinish); - stream.removeListener('exit', onexit); - stream.removeListener('end', onend); - stream.removeListener('error', onerror); - stream.removeListener('close', onclose); - }; -}; - -module.exports = eos; - - /***/ }), /***/ 70877: @@ -18499,5565 +16888,397 @@ const fill = (start, end, step, options = {}) => { } let opts = { ...options }; - if (opts.capture === true) opts.wrap = true; - step = step || opts.step || 1; - - if (!isNumber(step)) { - if (step != null && !isObject(step)) return invalidStep(step, opts); - return fill(start, end, 1, step); - } - - if (isNumber(start) && isNumber(end)) { - return fillNumbers(start, end, step, opts); - } - - return fillLetters(start, end, Math.max(Math.abs(step), 1), opts); -}; - -module.exports = fill; - - -/***/ }), - -/***/ 60199: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const fs = __nccwpck_require__(79896); -const micromatch = __nccwpck_require__(98785); -const path = __nccwpck_require__(16928); - -module.exports = findWorkspaceRoot; - -/** - * Adapted from: - * https://github.com/yarnpkg/yarn/blob/ddf2f9ade211195372236c2f39a75b00fa18d4de/src/config.js#L612 - * @param {string} [initial] - * @return {string|null} - */ -function findWorkspaceRoot(initial) { - if (!initial) { - initial = process.cwd(); - } - let previous = null; - let current = path.normalize(initial); - - do { - const manifest = readPackageJSON(current); - const workspaces = extractWorkspaces(manifest); - - if (workspaces) { - const relativePath = path.relative(current, initial); - if (relativePath === '' || micromatch([relativePath], workspaces).length > 0) { - return current; - } else { - return null; - } - } - - previous = current; - current = path.dirname(current); - } while (current !== previous); - - return null; -} - -function extractWorkspaces(manifest) { - const workspaces = (manifest || {}).workspaces; - return (workspaces && workspaces.packages) || (Array.isArray(workspaces) ? workspaces : null); -} - -function readPackageJSON(dir) { - const file = path.join(dir, 'package.json'); - if (fs.existsSync(file)) { - return JSON.parse(fs.readFileSync(file, 'utf8')); - } - return null; -} - - -/***/ }), - -/***/ 57070: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - -const {PassThrough: PassThroughStream} = __nccwpck_require__(2203); - -module.exports = options => { - options = {...options}; - - const {array} = options; - let {encoding} = options; - const isBuffer = encoding === 'buffer'; - let objectMode = false; - - if (array) { - objectMode = !(encoding || isBuffer); - } else { - encoding = encoding || 'utf8'; - } - - if (isBuffer) { - encoding = null; - } - - const stream = new PassThroughStream({objectMode}); - - if (encoding) { - stream.setEncoding(encoding); - } - - let length = 0; - const chunks = []; - - stream.on('data', chunk => { - chunks.push(chunk); - - if (objectMode) { - length = chunks.length; - } else { - length += chunk.length; - } - }); - - stream.getBufferedValue = () => { - if (array) { - return chunks; - } - - return isBuffer ? Buffer.concat(chunks, length) : chunks.join(''); - }; - - stream.getBufferedLength = () => length; - - return stream; -}; - - -/***/ }), - -/***/ 96771: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - -const {constants: BufferConstants} = __nccwpck_require__(20181); -const pump = __nccwpck_require__(87898); -const bufferStream = __nccwpck_require__(57070); - -class MaxBufferError extends Error { - constructor() { - super('maxBuffer exceeded'); - this.name = 'MaxBufferError'; - } -} - -async function getStream(inputStream, options) { - if (!inputStream) { - return Promise.reject(new Error('Expected a stream')); - } - - options = { - maxBuffer: Infinity, - ...options - }; - - const {maxBuffer} = options; - - let stream; - await new Promise((resolve, reject) => { - const rejectPromise = error => { - // Don't retrieve an oversized buffer. - if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) { - error.bufferedData = stream.getBufferedValue(); - } - - reject(error); - }; - - stream = pump(inputStream, bufferStream(options), error => { - if (error) { - rejectPromise(error); - return; - } - - resolve(); - }); - - stream.on('data', () => { - if (stream.getBufferedLength() > maxBuffer) { - rejectPromise(new MaxBufferError()); - } - }); - }); - - return stream.getBufferedValue(); -} - -module.exports = getStream; -// TODO: Remove this for the next major release -module.exports["default"] = getStream; -module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'}); -module.exports.array = (stream, options) => getStream(stream, {...options, array: true}); -module.exports.MaxBufferError = MaxBufferError; - - -/***/ }), - -/***/ 87814: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -const types_1 = __nccwpck_require__(74707); -function createRejection(error, ...beforeErrorGroups) { - const promise = (async () => { - if (error instanceof types_1.RequestError) { - try { - for (const hooks of beforeErrorGroups) { - if (hooks) { - for (const hook of hooks) { - // eslint-disable-next-line no-await-in-loop - error = await hook(error); - } - } - } - } - catch (error_) { - error = error_; - } - } - throw error; - })(); - const returnPromise = () => promise; - promise.json = returnPromise; - promise.text = returnPromise; - promise.buffer = returnPromise; - promise.on = returnPromise; - return promise; -} -exports["default"] = createRejection; - - -/***/ }), - -/***/ 72126: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -const events_1 = __nccwpck_require__(24434); -const is_1 = __nccwpck_require__(64001); -const PCancelable = __nccwpck_require__(84533); -const types_1 = __nccwpck_require__(74707); -const parse_body_1 = __nccwpck_require__(45494); -const core_1 = __nccwpck_require__(86825); -const proxy_events_1 = __nccwpck_require__(27813); -const get_buffer_1 = __nccwpck_require__(64858); -const is_response_ok_1 = __nccwpck_require__(4350); -const proxiedRequestEvents = [ - 'request', - 'response', - 'redirect', - 'uploadProgress', - 'downloadProgress' -]; -function asPromise(normalizedOptions) { - let globalRequest; - let globalResponse; - const emitter = new events_1.EventEmitter(); - const promise = new PCancelable((resolve, reject, onCancel) => { - const makeRequest = (retryCount) => { - const request = new core_1.default(undefined, normalizedOptions); - request.retryCount = retryCount; - request._noPipe = true; - onCancel(() => request.destroy()); - onCancel.shouldReject = false; - onCancel(() => reject(new types_1.CancelError(request))); - globalRequest = request; - request.once('response', async (response) => { - var _a; - response.retryCount = retryCount; - if (response.request.aborted) { - // Canceled while downloading - will throw a `CancelError` or `TimeoutError` error - return; - } - // Download body - let rawBody; - try { - rawBody = await get_buffer_1.default(request); - response.rawBody = rawBody; - } - catch (_b) { - // The same error is caught below. - // See request.once('error') - return; - } - if (request._isAboutToError) { - return; - } - // Parse body - const contentEncoding = ((_a = response.headers['content-encoding']) !== null && _a !== void 0 ? _a : '').toLowerCase(); - const isCompressed = ['gzip', 'deflate', 'br'].includes(contentEncoding); - const { options } = request; - if (isCompressed && !options.decompress) { - response.body = rawBody; - } - else { - try { - response.body = parse_body_1.default(response, options.responseType, options.parseJson, options.encoding); - } - catch (error) { - // Fallback to `utf8` - response.body = rawBody.toString(); - if (is_response_ok_1.isResponseOk(response)) { - request._beforeError(error); - return; - } - } - } - try { - for (const [index, hook] of options.hooks.afterResponse.entries()) { - // @ts-expect-error TS doesn't notice that CancelableRequest is a Promise - // eslint-disable-next-line no-await-in-loop - response = await hook(response, async (updatedOptions) => { - const typedOptions = core_1.default.normalizeArguments(undefined, { - ...updatedOptions, - retry: { - calculateDelay: () => 0 - }, - throwHttpErrors: false, - resolveBodyOnly: false - }, options); - // Remove any further hooks for that request, because we'll call them anyway. - // The loop continues. We don't want duplicates (asPromise recursion). - typedOptions.hooks.afterResponse = typedOptions.hooks.afterResponse.slice(0, index); - for (const hook of typedOptions.hooks.beforeRetry) { - // eslint-disable-next-line no-await-in-loop - await hook(typedOptions); - } - const promise = asPromise(typedOptions); - onCancel(() => { - promise.catch(() => { }); - promise.cancel(); - }); - return promise; - }); - } - } - catch (error) { - request._beforeError(new types_1.RequestError(error.message, error, request)); - return; - } - globalResponse = response; - if (!is_response_ok_1.isResponseOk(response)) { - request._beforeError(new types_1.HTTPError(response)); - return; - } - request.destroy(); - resolve(request.options.resolveBodyOnly ? response.body : response); - }); - const onError = (error) => { - if (promise.isCanceled) { - return; - } - const { options } = request; - if (error instanceof types_1.HTTPError && !options.throwHttpErrors) { - const { response } = error; - resolve(request.options.resolveBodyOnly ? response.body : response); - return; - } - reject(error); - }; - request.once('error', onError); - const previousBody = request.options.body; - request.once('retry', (newRetryCount, error) => { - var _a, _b; - if (previousBody === ((_a = error.request) === null || _a === void 0 ? void 0 : _a.options.body) && is_1.default.nodeStream((_b = error.request) === null || _b === void 0 ? void 0 : _b.options.body)) { - onError(error); - return; - } - makeRequest(newRetryCount); - }); - proxy_events_1.default(request, emitter, proxiedRequestEvents); - }; - makeRequest(0); - }); - promise.on = (event, fn) => { - emitter.on(event, fn); - return promise; - }; - const shortcut = (responseType) => { - const newPromise = (async () => { - // Wait until downloading has ended - await promise; - const { options } = globalResponse.request; - return parse_body_1.default(globalResponse, responseType, options.parseJson, options.encoding); - })(); - Object.defineProperties(newPromise, Object.getOwnPropertyDescriptors(promise)); - return newPromise; - }; - promise.json = () => { - const { headers } = globalRequest.options; - if (!globalRequest.writableFinished && headers.accept === undefined) { - headers.accept = 'application/json'; - } - return shortcut('json'); - }; - promise.buffer = () => shortcut('buffer'); - promise.text = () => shortcut('text'); - return promise; -} -exports["default"] = asPromise; -__exportStar(__nccwpck_require__(74707), exports); - - -/***/ }), - -/***/ 66364: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -const is_1 = __nccwpck_require__(64001); -const normalizeArguments = (options, defaults) => { - if (is_1.default.null_(options.encoding)) { - throw new TypeError('To get a Buffer, set `options.responseType` to `buffer` instead'); - } - is_1.assert.any([is_1.default.string, is_1.default.undefined], options.encoding); - is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.resolveBodyOnly); - is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.methodRewriting); - is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.isStream); - is_1.assert.any([is_1.default.string, is_1.default.undefined], options.responseType); - // `options.responseType` - if (options.responseType === undefined) { - options.responseType = 'text'; - } - // `options.retry` - const { retry } = options; - if (defaults) { - options.retry = { ...defaults.retry }; - } - else { - options.retry = { - calculateDelay: retryObject => retryObject.computedValue, - limit: 0, - methods: [], - statusCodes: [], - errorCodes: [], - maxRetryAfter: undefined - }; - } - if (is_1.default.object(retry)) { - options.retry = { - ...options.retry, - ...retry - }; - options.retry.methods = [...new Set(options.retry.methods.map(method => method.toUpperCase()))]; - options.retry.statusCodes = [...new Set(options.retry.statusCodes)]; - options.retry.errorCodes = [...new Set(options.retry.errorCodes)]; - } - else if (is_1.default.number(retry)) { - options.retry.limit = retry; - } - if (is_1.default.undefined(options.retry.maxRetryAfter)) { - options.retry.maxRetryAfter = Math.min( - // TypeScript is not smart enough to handle `.filter(x => is.number(x))`. - // eslint-disable-next-line unicorn/no-fn-reference-in-iterator - ...[options.timeout.request, options.timeout.connect].filter(is_1.default.number)); - } - // `options.pagination` - if (is_1.default.object(options.pagination)) { - if (defaults) { - options.pagination = { - ...defaults.pagination, - ...options.pagination - }; - } - const { pagination } = options; - if (!is_1.default.function_(pagination.transform)) { - throw new Error('`options.pagination.transform` must be implemented'); - } - if (!is_1.default.function_(pagination.shouldContinue)) { - throw new Error('`options.pagination.shouldContinue` must be implemented'); - } - if (!is_1.default.function_(pagination.filter)) { - throw new TypeError('`options.pagination.filter` must be implemented'); - } - if (!is_1.default.function_(pagination.paginate)) { - throw new Error('`options.pagination.paginate` must be implemented'); - } - } - // JSON mode - if (options.responseType === 'json' && options.headers.accept === undefined) { - options.headers.accept = 'application/json'; - } - return options; -}; -exports["default"] = normalizeArguments; - - -/***/ }), - -/***/ 45494: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -const types_1 = __nccwpck_require__(74707); -const parseBody = (response, responseType, parseJson, encoding) => { - const { rawBody } = response; - try { - if (responseType === 'text') { - return rawBody.toString(encoding); - } - if (responseType === 'json') { - return rawBody.length === 0 ? '' : parseJson(rawBody.toString()); - } - if (responseType === 'buffer') { - return rawBody; - } - throw new types_1.ParseError({ - message: `Unknown body type '${responseType}'`, - name: 'Error' - }, response); - } - catch (error) { - throw new types_1.ParseError(error, response); - } -}; -exports["default"] = parseBody; - - -/***/ }), - -/***/ 74707: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.CancelError = exports.ParseError = void 0; -const core_1 = __nccwpck_require__(86825); -/** -An error to be thrown when server response code is 2xx, and parsing body fails. -Includes a `response` property. -*/ -class ParseError extends core_1.RequestError { - constructor(error, response) { - const { options } = response.request; - super(`${error.message} in "${options.url.toString()}"`, error, response.request); - this.name = 'ParseError'; - this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_BODY_PARSE_FAILURE' : this.code; - } -} -exports.ParseError = ParseError; -/** -An error to be thrown when the request is aborted with `.cancel()`. -*/ -class CancelError extends core_1.RequestError { - constructor(request) { - super('Promise was canceled', {}, request); - this.name = 'CancelError'; - this.code = 'ERR_CANCELED'; - } - get isCanceled() { - return true; - } -} -exports.CancelError = CancelError; -__exportStar(__nccwpck_require__(86825), exports); - - -/***/ }), - -/***/ 33024: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.retryAfterStatusCodes = void 0; -exports.retryAfterStatusCodes = new Set([413, 429, 503]); -const calculateRetryDelay = ({ attemptCount, retryOptions, error, retryAfter }) => { - if (attemptCount > retryOptions.limit) { - return 0; - } - const hasMethod = retryOptions.methods.includes(error.options.method); - const hasErrorCode = retryOptions.errorCodes.includes(error.code); - const hasStatusCode = error.response && retryOptions.statusCodes.includes(error.response.statusCode); - if (!hasMethod || (!hasErrorCode && !hasStatusCode)) { - return 0; - } - if (error.response) { - if (retryAfter) { - if (retryOptions.maxRetryAfter === undefined || retryAfter > retryOptions.maxRetryAfter) { - return 0; - } - return retryAfter; - } - if (error.response.statusCode === 413) { - return 0; - } - } - const noise = Math.random() * 100; - return ((2 ** (attemptCount - 1)) * 1000) + noise; -}; -exports["default"] = calculateRetryDelay; - - -/***/ }), - -/***/ 86825: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.UnsupportedProtocolError = exports.ReadError = exports.TimeoutError = exports.UploadError = exports.CacheError = exports.HTTPError = exports.MaxRedirectsError = exports.RequestError = exports.setNonEnumerableProperties = exports.knownHookEvents = exports.withoutBody = exports.kIsNormalizedAlready = void 0; -const util_1 = __nccwpck_require__(39023); -const stream_1 = __nccwpck_require__(2203); -const fs_1 = __nccwpck_require__(79896); -const url_1 = __nccwpck_require__(87016); -const http = __nccwpck_require__(58611); -const http_1 = __nccwpck_require__(58611); -const https = __nccwpck_require__(65692); -const http_timer_1 = __nccwpck_require__(24480); -const cacheable_lookup_1 = __nccwpck_require__(82417); -const CacheableRequest = __nccwpck_require__(21487); -const decompressResponse = __nccwpck_require__(21373); -// @ts-expect-error Missing types -const http2wrapper = __nccwpck_require__(14956); -const lowercaseKeys = __nccwpck_require__(11364); -const is_1 = __nccwpck_require__(64001); -const get_body_size_1 = __nccwpck_require__(29296); -const is_form_data_1 = __nccwpck_require__(6751); -const proxy_events_1 = __nccwpck_require__(27813); -const timed_out_1 = __nccwpck_require__(94501); -const url_to_options_1 = __nccwpck_require__(53873); -const options_to_url_1 = __nccwpck_require__(95743); -const weakable_map_1 = __nccwpck_require__(30172); -const get_buffer_1 = __nccwpck_require__(64858); -const dns_ip_version_1 = __nccwpck_require__(91037); -const is_response_ok_1 = __nccwpck_require__(4350); -const deprecation_warning_1 = __nccwpck_require__(39796); -const normalize_arguments_1 = __nccwpck_require__(66364); -const calculate_retry_delay_1 = __nccwpck_require__(33024); -let globalDnsCache; -const kRequest = Symbol('request'); -const kResponse = Symbol('response'); -const kResponseSize = Symbol('responseSize'); -const kDownloadedSize = Symbol('downloadedSize'); -const kBodySize = Symbol('bodySize'); -const kUploadedSize = Symbol('uploadedSize'); -const kServerResponsesPiped = Symbol('serverResponsesPiped'); -const kUnproxyEvents = Symbol('unproxyEvents'); -const kIsFromCache = Symbol('isFromCache'); -const kCancelTimeouts = Symbol('cancelTimeouts'); -const kStartedReading = Symbol('startedReading'); -const kStopReading = Symbol('stopReading'); -const kTriggerRead = Symbol('triggerRead'); -const kBody = Symbol('body'); -const kJobs = Symbol('jobs'); -const kOriginalResponse = Symbol('originalResponse'); -const kRetryTimeout = Symbol('retryTimeout'); -exports.kIsNormalizedAlready = Symbol('isNormalizedAlready'); -const supportsBrotli = is_1.default.string(process.versions.brotli); -exports.withoutBody = new Set(['GET', 'HEAD']); -exports.knownHookEvents = [ - 'init', - 'beforeRequest', - 'beforeRedirect', - 'beforeError', - 'beforeRetry', - // Promise-Only - 'afterResponse' -]; -function validateSearchParameters(searchParameters) { - // eslint-disable-next-line guard-for-in - for (const key in searchParameters) { - const value = searchParameters[key]; - if (!is_1.default.string(value) && !is_1.default.number(value) && !is_1.default.boolean(value) && !is_1.default.null_(value) && !is_1.default.undefined(value)) { - throw new TypeError(`The \`searchParams\` value '${String(value)}' must be a string, number, boolean or null`); - } - } -} -function isClientRequest(clientRequest) { - return is_1.default.object(clientRequest) && !('statusCode' in clientRequest); -} -const cacheableStore = new weakable_map_1.default(); -const waitForOpenFile = async (file) => new Promise((resolve, reject) => { - const onError = (error) => { - reject(error); - }; - // Node.js 12 has incomplete types - if (!file.pending) { - resolve(); - } - file.once('error', onError); - file.once('ready', () => { - file.off('error', onError); - resolve(); - }); -}); -const redirectCodes = new Set([300, 301, 302, 303, 304, 307, 308]); -const nonEnumerableProperties = [ - 'context', - 'body', - 'json', - 'form' -]; -exports.setNonEnumerableProperties = (sources, to) => { - // Non enumerable properties shall not be merged - const properties = {}; - for (const source of sources) { - if (!source) { - continue; - } - for (const name of nonEnumerableProperties) { - if (!(name in source)) { - continue; - } - properties[name] = { - writable: true, - configurable: true, - enumerable: false, - // @ts-expect-error TS doesn't see the check above - value: source[name] - }; - } - } - Object.defineProperties(to, properties); -}; -/** -An error to be thrown when a request fails. -Contains a `code` property with error class code, like `ECONNREFUSED`. -*/ -class RequestError extends Error { - constructor(message, error, self) { - var _a, _b; - super(message); - Error.captureStackTrace(this, this.constructor); - this.name = 'RequestError'; - this.code = (_a = error.code) !== null && _a !== void 0 ? _a : 'ERR_GOT_REQUEST_ERROR'; - if (self instanceof Request) { - Object.defineProperty(this, 'request', { - enumerable: false, - value: self - }); - Object.defineProperty(this, 'response', { - enumerable: false, - value: self[kResponse] - }); - Object.defineProperty(this, 'options', { - // This fails because of TS 3.7.2 useDefineForClassFields - // Ref: https://github.com/microsoft/TypeScript/issues/34972 - enumerable: false, - value: self.options - }); - } - else { - Object.defineProperty(this, 'options', { - // This fails because of TS 3.7.2 useDefineForClassFields - // Ref: https://github.com/microsoft/TypeScript/issues/34972 - enumerable: false, - value: self - }); - } - this.timings = (_b = this.request) === null || _b === void 0 ? void 0 : _b.timings; - // Recover the original stacktrace - if (is_1.default.string(error.stack) && is_1.default.string(this.stack)) { - const indexOfMessage = this.stack.indexOf(this.message) + this.message.length; - const thisStackTrace = this.stack.slice(indexOfMessage).split('\n').reverse(); - const errorStackTrace = error.stack.slice(error.stack.indexOf(error.message) + error.message.length).split('\n').reverse(); - // Remove duplicated traces - while (errorStackTrace.length !== 0 && errorStackTrace[0] === thisStackTrace[0]) { - thisStackTrace.shift(); - } - this.stack = `${this.stack.slice(0, indexOfMessage)}${thisStackTrace.reverse().join('\n')}${errorStackTrace.reverse().join('\n')}`; - } - } -} -exports.RequestError = RequestError; -/** -An error to be thrown when the server redirects you more than ten times. -Includes a `response` property. -*/ -class MaxRedirectsError extends RequestError { - constructor(request) { - super(`Redirected ${request.options.maxRedirects} times. Aborting.`, {}, request); - this.name = 'MaxRedirectsError'; - this.code = 'ERR_TOO_MANY_REDIRECTS'; - } -} -exports.MaxRedirectsError = MaxRedirectsError; -/** -An error to be thrown when the server response code is not 2xx nor 3xx if `options.followRedirect` is `true`, but always except for 304. -Includes a `response` property. -*/ -class HTTPError extends RequestError { - constructor(response) { - super(`Response code ${response.statusCode} (${response.statusMessage})`, {}, response.request); - this.name = 'HTTPError'; - this.code = 'ERR_NON_2XX_3XX_RESPONSE'; - } -} -exports.HTTPError = HTTPError; -/** -An error to be thrown when a cache method fails. -For example, if the database goes down or there's a filesystem error. -*/ -class CacheError extends RequestError { - constructor(error, request) { - super(error.message, error, request); - this.name = 'CacheError'; - this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_CACHE_ACCESS' : this.code; - } -} -exports.CacheError = CacheError; -/** -An error to be thrown when the request body is a stream and an error occurs while reading from that stream. -*/ -class UploadError extends RequestError { - constructor(error, request) { - super(error.message, error, request); - this.name = 'UploadError'; - this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_UPLOAD' : this.code; - } -} -exports.UploadError = UploadError; -/** -An error to be thrown when the request is aborted due to a timeout. -Includes an `event` and `timings` property. -*/ -class TimeoutError extends RequestError { - constructor(error, timings, request) { - super(error.message, error, request); - this.name = 'TimeoutError'; - this.event = error.event; - this.timings = timings; - } -} -exports.TimeoutError = TimeoutError; -/** -An error to be thrown when reading from response stream fails. -*/ -class ReadError extends RequestError { - constructor(error, request) { - super(error.message, error, request); - this.name = 'ReadError'; - this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_READING_RESPONSE_STREAM' : this.code; - } -} -exports.ReadError = ReadError; -/** -An error to be thrown when given an unsupported protocol. -*/ -class UnsupportedProtocolError extends RequestError { - constructor(options) { - super(`Unsupported protocol "${options.url.protocol}"`, {}, options); - this.name = 'UnsupportedProtocolError'; - this.code = 'ERR_UNSUPPORTED_PROTOCOL'; - } -} -exports.UnsupportedProtocolError = UnsupportedProtocolError; -const proxiedRequestEvents = [ - 'socket', - 'connect', - 'continue', - 'information', - 'upgrade', - 'timeout' -]; -class Request extends stream_1.Duplex { - constructor(url, options = {}, defaults) { - super({ - // This must be false, to enable throwing after destroy - // It is used for retry logic in Promise API - autoDestroy: false, - // It needs to be zero because we're just proxying the data to another stream - highWaterMark: 0 - }); - this[kDownloadedSize] = 0; - this[kUploadedSize] = 0; - this.requestInitialized = false; - this[kServerResponsesPiped] = new Set(); - this.redirects = []; - this[kStopReading] = false; - this[kTriggerRead] = false; - this[kJobs] = []; - this.retryCount = 0; - // TODO: Remove this when targeting Node.js >= 12 - this._progressCallbacks = []; - const unlockWrite = () => this._unlockWrite(); - const lockWrite = () => this._lockWrite(); - this.on('pipe', (source) => { - source.prependListener('data', unlockWrite); - source.on('data', lockWrite); - source.prependListener('end', unlockWrite); - source.on('end', lockWrite); - }); - this.on('unpipe', (source) => { - source.off('data', unlockWrite); - source.off('data', lockWrite); - source.off('end', unlockWrite); - source.off('end', lockWrite); - }); - this.on('pipe', source => { - if (source instanceof http_1.IncomingMessage) { - this.options.headers = { - ...source.headers, - ...this.options.headers - }; - } - }); - const { json, body, form } = options; - if (json || body || form) { - this._lockWrite(); - } - if (exports.kIsNormalizedAlready in options) { - this.options = options; - } - else { - try { - // @ts-expect-error Common TypeScript bug saying that `this.constructor` is not accessible - this.options = this.constructor.normalizeArguments(url, options, defaults); - } - catch (error) { - // TODO: Move this to `_destroy()` - if (is_1.default.nodeStream(options.body)) { - options.body.destroy(); - } - this.destroy(error); - return; - } - } - (async () => { - var _a; - try { - if (this.options.body instanceof fs_1.ReadStream) { - await waitForOpenFile(this.options.body); - } - const { url: normalizedURL } = this.options; - if (!normalizedURL) { - throw new TypeError('Missing `url` property'); - } - this.requestUrl = normalizedURL.toString(); - decodeURI(this.requestUrl); - await this._finalizeBody(); - await this._makeRequest(); - if (this.destroyed) { - (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.destroy(); - return; - } - // Queued writes etc. - for (const job of this[kJobs]) { - job(); - } - // Prevent memory leak - this[kJobs].length = 0; - this.requestInitialized = true; - } - catch (error) { - if (error instanceof RequestError) { - this._beforeError(error); - return; - } - // This is a workaround for https://github.com/nodejs/node/issues/33335 - if (!this.destroyed) { - this.destroy(error); - } - } - })(); - } - static normalizeArguments(url, options, defaults) { - var _a, _b, _c, _d, _e; - const rawOptions = options; - if (is_1.default.object(url) && !is_1.default.urlInstance(url)) { - options = { ...defaults, ...url, ...options }; - } - else { - if (url && options && options.url !== undefined) { - throw new TypeError('The `url` option is mutually exclusive with the `input` argument'); - } - options = { ...defaults, ...options }; - if (url !== undefined) { - options.url = url; - } - if (is_1.default.urlInstance(options.url)) { - options.url = new url_1.URL(options.url.toString()); - } - } - // TODO: Deprecate URL options in Got 12. - // Support extend-specific options - if (options.cache === false) { - options.cache = undefined; - } - if (options.dnsCache === false) { - options.dnsCache = undefined; - } - // Nice type assertions - is_1.assert.any([is_1.default.string, is_1.default.undefined], options.method); - is_1.assert.any([is_1.default.object, is_1.default.undefined], options.headers); - is_1.assert.any([is_1.default.string, is_1.default.urlInstance, is_1.default.undefined], options.prefixUrl); - is_1.assert.any([is_1.default.object, is_1.default.undefined], options.cookieJar); - is_1.assert.any([is_1.default.object, is_1.default.string, is_1.default.undefined], options.searchParams); - is_1.assert.any([is_1.default.object, is_1.default.string, is_1.default.undefined], options.cache); - is_1.assert.any([is_1.default.object, is_1.default.number, is_1.default.undefined], options.timeout); - is_1.assert.any([is_1.default.object, is_1.default.undefined], options.context); - is_1.assert.any([is_1.default.object, is_1.default.undefined], options.hooks); - is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.decompress); - is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.ignoreInvalidCookies); - is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.followRedirect); - is_1.assert.any([is_1.default.number, is_1.default.undefined], options.maxRedirects); - is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.throwHttpErrors); - is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.http2); - is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.allowGetBody); - is_1.assert.any([is_1.default.string, is_1.default.undefined], options.localAddress); - is_1.assert.any([dns_ip_version_1.isDnsLookupIpVersion, is_1.default.undefined], options.dnsLookupIpVersion); - is_1.assert.any([is_1.default.object, is_1.default.undefined], options.https); - is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.rejectUnauthorized); - if (options.https) { - is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.https.rejectUnauthorized); - is_1.assert.any([is_1.default.function_, is_1.default.undefined], options.https.checkServerIdentity); - is_1.assert.any([is_1.default.string, is_1.default.object, is_1.default.array, is_1.default.undefined], options.https.certificateAuthority); - is_1.assert.any([is_1.default.string, is_1.default.object, is_1.default.array, is_1.default.undefined], options.https.key); - is_1.assert.any([is_1.default.string, is_1.default.object, is_1.default.array, is_1.default.undefined], options.https.certificate); - is_1.assert.any([is_1.default.string, is_1.default.undefined], options.https.passphrase); - is_1.assert.any([is_1.default.string, is_1.default.buffer, is_1.default.array, is_1.default.undefined], options.https.pfx); - } - is_1.assert.any([is_1.default.object, is_1.default.undefined], options.cacheOptions); - // `options.method` - if (is_1.default.string(options.method)) { - options.method = options.method.toUpperCase(); - } - else { - options.method = 'GET'; - } - // `options.headers` - if (options.headers === (defaults === null || defaults === void 0 ? void 0 : defaults.headers)) { - options.headers = { ...options.headers }; - } - else { - options.headers = lowercaseKeys({ ...(defaults === null || defaults === void 0 ? void 0 : defaults.headers), ...options.headers }); - } - // Disallow legacy `url.Url` - if ('slashes' in options) { - throw new TypeError('The legacy `url.Url` has been deprecated. Use `URL` instead.'); - } - // `options.auth` - if ('auth' in options) { - throw new TypeError('Parameter `auth` is deprecated. Use `username` / `password` instead.'); - } - // `options.searchParams` - if ('searchParams' in options) { - if (options.searchParams && options.searchParams !== (defaults === null || defaults === void 0 ? void 0 : defaults.searchParams)) { - let searchParameters; - if (is_1.default.string(options.searchParams) || (options.searchParams instanceof url_1.URLSearchParams)) { - searchParameters = new url_1.URLSearchParams(options.searchParams); - } - else { - validateSearchParameters(options.searchParams); - searchParameters = new url_1.URLSearchParams(); - // eslint-disable-next-line guard-for-in - for (const key in options.searchParams) { - const value = options.searchParams[key]; - if (value === null) { - searchParameters.append(key, ''); - } - else if (value !== undefined) { - searchParameters.append(key, value); - } - } - } - // `normalizeArguments()` is also used to merge options - (_a = defaults === null || defaults === void 0 ? void 0 : defaults.searchParams) === null || _a === void 0 ? void 0 : _a.forEach((value, key) => { - // Only use default if one isn't already defined - if (!searchParameters.has(key)) { - searchParameters.append(key, value); - } - }); - options.searchParams = searchParameters; - } - } - // `options.username` & `options.password` - options.username = (_b = options.username) !== null && _b !== void 0 ? _b : ''; - options.password = (_c = options.password) !== null && _c !== void 0 ? _c : ''; - // `options.prefixUrl` & `options.url` - if (is_1.default.undefined(options.prefixUrl)) { - options.prefixUrl = (_d = defaults === null || defaults === void 0 ? void 0 : defaults.prefixUrl) !== null && _d !== void 0 ? _d : ''; - } - else { - options.prefixUrl = options.prefixUrl.toString(); - if (options.prefixUrl !== '' && !options.prefixUrl.endsWith('/')) { - options.prefixUrl += '/'; - } - } - if (is_1.default.string(options.url)) { - if (options.url.startsWith('/')) { - throw new Error('`input` must not start with a slash when using `prefixUrl`'); - } - options.url = options_to_url_1.default(options.prefixUrl + options.url, options); - } - else if ((is_1.default.undefined(options.url) && options.prefixUrl !== '') || options.protocol) { - options.url = options_to_url_1.default(options.prefixUrl, options); - } - if (options.url) { - if ('port' in options) { - delete options.port; - } - // Make it possible to change `options.prefixUrl` - let { prefixUrl } = options; - Object.defineProperty(options, 'prefixUrl', { - set: (value) => { - const url = options.url; - if (!url.href.startsWith(value)) { - throw new Error(`Cannot change \`prefixUrl\` from ${prefixUrl} to ${value}: ${url.href}`); - } - options.url = new url_1.URL(value + url.href.slice(prefixUrl.length)); - prefixUrl = value; - }, - get: () => prefixUrl - }); - // Support UNIX sockets - let { protocol } = options.url; - if (protocol === 'unix:') { - protocol = 'http:'; - options.url = new url_1.URL(`http://unix${options.url.pathname}${options.url.search}`); - } - // Set search params - if (options.searchParams) { - // eslint-disable-next-line @typescript-eslint/no-base-to-string - options.url.search = options.searchParams.toString(); - } - // Protocol check - if (protocol !== 'http:' && protocol !== 'https:') { - throw new UnsupportedProtocolError(options); - } - // Update `username` - if (options.username === '') { - options.username = options.url.username; - } - else { - options.url.username = options.username; - } - // Update `password` - if (options.password === '') { - options.password = options.url.password; - } - else { - options.url.password = options.password; - } - } - // `options.cookieJar` - const { cookieJar } = options; - if (cookieJar) { - let { setCookie, getCookieString } = cookieJar; - is_1.assert.function_(setCookie); - is_1.assert.function_(getCookieString); - /* istanbul ignore next: Horrible `tough-cookie` v3 check */ - if (setCookie.length === 4 && getCookieString.length === 0) { - setCookie = util_1.promisify(setCookie.bind(options.cookieJar)); - getCookieString = util_1.promisify(getCookieString.bind(options.cookieJar)); - options.cookieJar = { - setCookie, - getCookieString: getCookieString - }; - } - } - // `options.cache` - const { cache } = options; - if (cache) { - if (!cacheableStore.has(cache)) { - cacheableStore.set(cache, new CacheableRequest(((requestOptions, handler) => { - const result = requestOptions[kRequest](requestOptions, handler); - // TODO: remove this when `cacheable-request` supports async request functions. - if (is_1.default.promise(result)) { - // @ts-expect-error - // We only need to implement the error handler in order to support HTTP2 caching. - // The result will be a promise anyway. - result.once = (event, handler) => { - if (event === 'error') { - result.catch(handler); - } - else if (event === 'abort') { - // The empty catch is needed here in case when - // it rejects before it's `await`ed in `_makeRequest`. - (async () => { - try { - const request = (await result); - request.once('abort', handler); - } - catch (_a) { } - })(); - } - else { - /* istanbul ignore next: safety check */ - throw new Error(`Unknown HTTP2 promise event: ${event}`); - } - return result; - }; - } - return result; - }), cache)); - } - } - // `options.cacheOptions` - options.cacheOptions = { ...options.cacheOptions }; - // `options.dnsCache` - if (options.dnsCache === true) { - if (!globalDnsCache) { - globalDnsCache = new cacheable_lookup_1.default(); - } - options.dnsCache = globalDnsCache; - } - else if (!is_1.default.undefined(options.dnsCache) && !options.dnsCache.lookup) { - throw new TypeError(`Parameter \`dnsCache\` must be a CacheableLookup instance or a boolean, got ${is_1.default(options.dnsCache)}`); - } - // `options.timeout` - if (is_1.default.number(options.timeout)) { - options.timeout = { request: options.timeout }; - } - else if (defaults && options.timeout !== defaults.timeout) { - options.timeout = { - ...defaults.timeout, - ...options.timeout - }; - } - else { - options.timeout = { ...options.timeout }; - } - // `options.context` - if (!options.context) { - options.context = {}; - } - // `options.hooks` - const areHooksDefault = options.hooks === (defaults === null || defaults === void 0 ? void 0 : defaults.hooks); - options.hooks = { ...options.hooks }; - for (const event of exports.knownHookEvents) { - if (event in options.hooks) { - if (is_1.default.array(options.hooks[event])) { - // See https://github.com/microsoft/TypeScript/issues/31445#issuecomment-576929044 - options.hooks[event] = [...options.hooks[event]]; - } - else { - throw new TypeError(`Parameter \`${event}\` must be an Array, got ${is_1.default(options.hooks[event])}`); - } - } - else { - options.hooks[event] = []; - } - } - if (defaults && !areHooksDefault) { - for (const event of exports.knownHookEvents) { - const defaultHooks = defaults.hooks[event]; - if (defaultHooks.length > 0) { - // See https://github.com/microsoft/TypeScript/issues/31445#issuecomment-576929044 - options.hooks[event] = [ - ...defaults.hooks[event], - ...options.hooks[event] - ]; - } - } - } - // DNS options - if ('family' in options) { - deprecation_warning_1.default('"options.family" was never documented, please use "options.dnsLookupIpVersion"'); - } - // HTTPS options - if (defaults === null || defaults === void 0 ? void 0 : defaults.https) { - options.https = { ...defaults.https, ...options.https }; - } - if ('rejectUnauthorized' in options) { - deprecation_warning_1.default('"options.rejectUnauthorized" is now deprecated, please use "options.https.rejectUnauthorized"'); - } - if ('checkServerIdentity' in options) { - deprecation_warning_1.default('"options.checkServerIdentity" was never documented, please use "options.https.checkServerIdentity"'); - } - if ('ca' in options) { - deprecation_warning_1.default('"options.ca" was never documented, please use "options.https.certificateAuthority"'); - } - if ('key' in options) { - deprecation_warning_1.default('"options.key" was never documented, please use "options.https.key"'); - } - if ('cert' in options) { - deprecation_warning_1.default('"options.cert" was never documented, please use "options.https.certificate"'); - } - if ('passphrase' in options) { - deprecation_warning_1.default('"options.passphrase" was never documented, please use "options.https.passphrase"'); - } - if ('pfx' in options) { - deprecation_warning_1.default('"options.pfx" was never documented, please use "options.https.pfx"'); - } - // Other options - if ('followRedirects' in options) { - throw new TypeError('The `followRedirects` option does not exist. Use `followRedirect` instead.'); - } - if (options.agent) { - for (const key in options.agent) { - if (key !== 'http' && key !== 'https' && key !== 'http2') { - throw new TypeError(`Expected the \`options.agent\` properties to be \`http\`, \`https\` or \`http2\`, got \`${key}\``); - } - } - } - options.maxRedirects = (_e = options.maxRedirects) !== null && _e !== void 0 ? _e : 0; - // Set non-enumerable properties - exports.setNonEnumerableProperties([defaults, rawOptions], options); - return normalize_arguments_1.default(options, defaults); - } - _lockWrite() { - const onLockedWrite = () => { - throw new TypeError('The payload has been already provided'); - }; - this.write = onLockedWrite; - this.end = onLockedWrite; - } - _unlockWrite() { - this.write = super.write; - this.end = super.end; - } - async _finalizeBody() { - const { options } = this; - const { headers } = options; - const isForm = !is_1.default.undefined(options.form); - const isJSON = !is_1.default.undefined(options.json); - const isBody = !is_1.default.undefined(options.body); - const hasPayload = isForm || isJSON || isBody; - const cannotHaveBody = exports.withoutBody.has(options.method) && !(options.method === 'GET' && options.allowGetBody); - this._cannotHaveBody = cannotHaveBody; - if (hasPayload) { - if (cannotHaveBody) { - throw new TypeError(`The \`${options.method}\` method cannot be used with a body`); - } - if ([isBody, isForm, isJSON].filter(isTrue => isTrue).length > 1) { - throw new TypeError('The `body`, `json` and `form` options are mutually exclusive'); - } - if (isBody && - !(options.body instanceof stream_1.Readable) && - !is_1.default.string(options.body) && - !is_1.default.buffer(options.body) && - !is_form_data_1.default(options.body)) { - throw new TypeError('The `body` option must be a stream.Readable, string or Buffer'); - } - if (isForm && !is_1.default.object(options.form)) { - throw new TypeError('The `form` option must be an Object'); - } - { - // Serialize body - const noContentType = !is_1.default.string(headers['content-type']); - if (isBody) { - // Special case for https://github.com/form-data/form-data - if (is_form_data_1.default(options.body) && noContentType) { - headers['content-type'] = `multipart/form-data; boundary=${options.body.getBoundary()}`; - } - this[kBody] = options.body; - } - else if (isForm) { - if (noContentType) { - headers['content-type'] = 'application/x-www-form-urlencoded'; - } - this[kBody] = (new url_1.URLSearchParams(options.form)).toString(); - } - else { - if (noContentType) { - headers['content-type'] = 'application/json'; - } - this[kBody] = options.stringifyJson(options.json); - } - const uploadBodySize = await get_body_size_1.default(this[kBody], options.headers); - // See https://tools.ietf.org/html/rfc7230#section-3.3.2 - // A user agent SHOULD send a Content-Length in a request message when - // no Transfer-Encoding is sent and the request method defines a meaning - // for an enclosed payload body. For example, a Content-Length header - // field is normally sent in a POST request even when the value is 0 - // (indicating an empty payload body). A user agent SHOULD NOT send a - // Content-Length header field when the request message does not contain - // a payload body and the method semantics do not anticipate such a - // body. - if (is_1.default.undefined(headers['content-length']) && is_1.default.undefined(headers['transfer-encoding'])) { - if (!cannotHaveBody && !is_1.default.undefined(uploadBodySize)) { - headers['content-length'] = String(uploadBodySize); - } - } - } - } - else if (cannotHaveBody) { - this._lockWrite(); - } - else { - this._unlockWrite(); - } - this[kBodySize] = Number(headers['content-length']) || undefined; - } - async _onResponseBase(response) { - const { options } = this; - const { url } = options; - this[kOriginalResponse] = response; - if (options.decompress) { - response = decompressResponse(response); - } - const statusCode = response.statusCode; - const typedResponse = response; - typedResponse.statusMessage = typedResponse.statusMessage ? typedResponse.statusMessage : http.STATUS_CODES[statusCode]; - typedResponse.url = options.url.toString(); - typedResponse.requestUrl = this.requestUrl; - typedResponse.redirectUrls = this.redirects; - typedResponse.request = this; - typedResponse.isFromCache = response.fromCache || false; - typedResponse.ip = this.ip; - typedResponse.retryCount = this.retryCount; - this[kIsFromCache] = typedResponse.isFromCache; - this[kResponseSize] = Number(response.headers['content-length']) || undefined; - this[kResponse] = response; - response.once('end', () => { - this[kResponseSize] = this[kDownloadedSize]; - this.emit('downloadProgress', this.downloadProgress); - }); - response.once('error', (error) => { - // Force clean-up, because some packages don't do this. - // TODO: Fix decompress-response - response.destroy(); - this._beforeError(new ReadError(error, this)); - }); - response.once('aborted', () => { - this._beforeError(new ReadError({ - name: 'Error', - message: 'The server aborted pending request', - code: 'ECONNRESET' - }, this)); - }); - this.emit('downloadProgress', this.downloadProgress); - const rawCookies = response.headers['set-cookie']; - if (is_1.default.object(options.cookieJar) && rawCookies) { - let promises = rawCookies.map(async (rawCookie) => options.cookieJar.setCookie(rawCookie, url.toString())); - if (options.ignoreInvalidCookies) { - promises = promises.map(async (p) => p.catch(() => { })); - } - try { - await Promise.all(promises); - } - catch (error) { - this._beforeError(error); - return; - } - } - if (options.followRedirect && response.headers.location && redirectCodes.has(statusCode)) { - // We're being redirected, we don't care about the response. - // It'd be best to abort the request, but we can't because - // we would have to sacrifice the TCP connection. We don't want that. - response.resume(); - if (this[kRequest]) { - this[kCancelTimeouts](); - // eslint-disable-next-line @typescript-eslint/no-dynamic-delete - delete this[kRequest]; - this[kUnproxyEvents](); - } - const shouldBeGet = statusCode === 303 && options.method !== 'GET' && options.method !== 'HEAD'; - if (shouldBeGet || !options.methodRewriting) { - // Server responded with "see other", indicating that the resource exists at another location, - // and the client should request it from that location via GET or HEAD. - options.method = 'GET'; - if ('body' in options) { - delete options.body; - } - if ('json' in options) { - delete options.json; - } - if ('form' in options) { - delete options.form; - } - this[kBody] = undefined; - delete options.headers['content-length']; - } - if (this.redirects.length >= options.maxRedirects) { - this._beforeError(new MaxRedirectsError(this)); - return; - } - try { - // Do not remove. See https://github.com/sindresorhus/got/pull/214 - const redirectBuffer = Buffer.from(response.headers.location, 'binary').toString(); - // Handles invalid URLs. See https://github.com/sindresorhus/got/issues/604 - const redirectUrl = new url_1.URL(redirectBuffer, url); - const redirectString = redirectUrl.toString(); - decodeURI(redirectString); - // eslint-disable-next-line no-inner-declarations - function isUnixSocketURL(url) { - return url.protocol === 'unix:' || url.hostname === 'unix'; - } - if (!isUnixSocketURL(url) && isUnixSocketURL(redirectUrl)) { - this._beforeError(new RequestError('Cannot redirect to UNIX socket', {}, this)); - return; - } - // Redirecting to a different site, clear sensitive data. - if (redirectUrl.hostname !== url.hostname || redirectUrl.port !== url.port) { - if ('host' in options.headers) { - delete options.headers.host; - } - if ('cookie' in options.headers) { - delete options.headers.cookie; - } - if ('authorization' in options.headers) { - delete options.headers.authorization; - } - if (options.username || options.password) { - options.username = ''; - options.password = ''; - } - } - else { - redirectUrl.username = options.username; - redirectUrl.password = options.password; - } - this.redirects.push(redirectString); - options.url = redirectUrl; - for (const hook of options.hooks.beforeRedirect) { - // eslint-disable-next-line no-await-in-loop - await hook(options, typedResponse); - } - this.emit('redirect', typedResponse, options); - await this._makeRequest(); - } - catch (error) { - this._beforeError(error); - return; - } - return; - } - if (options.isStream && options.throwHttpErrors && !is_response_ok_1.isResponseOk(typedResponse)) { - this._beforeError(new HTTPError(typedResponse)); - return; - } - response.on('readable', () => { - if (this[kTriggerRead]) { - this._read(); - } - }); - this.on('resume', () => { - response.resume(); - }); - this.on('pause', () => { - response.pause(); - }); - response.once('end', () => { - this.push(null); - }); - this.emit('response', response); - for (const destination of this[kServerResponsesPiped]) { - if (destination.headersSent) { - continue; - } - // eslint-disable-next-line guard-for-in - for (const key in response.headers) { - const isAllowed = options.decompress ? key !== 'content-encoding' : true; - const value = response.headers[key]; - if (isAllowed) { - destination.setHeader(key, value); - } - } - destination.statusCode = statusCode; - } - } - async _onResponse(response) { - try { - await this._onResponseBase(response); - } - catch (error) { - /* istanbul ignore next: better safe than sorry */ - this._beforeError(error); - } - } - _onRequest(request) { - const { options } = this; - const { timeout, url } = options; - http_timer_1.default(request); - this[kCancelTimeouts] = timed_out_1.default(request, timeout, url); - const responseEventName = options.cache ? 'cacheableResponse' : 'response'; - request.once(responseEventName, (response) => { - void this._onResponse(response); - }); - request.once('error', (error) => { - var _a; - // Force clean-up, because some packages (e.g. nock) don't do this. - request.destroy(); - // Node.js <= 12.18.2 mistakenly emits the response `end` first. - (_a = request.res) === null || _a === void 0 ? void 0 : _a.removeAllListeners('end'); - error = error instanceof timed_out_1.TimeoutError ? new TimeoutError(error, this.timings, this) : new RequestError(error.message, error, this); - this._beforeError(error); - }); - this[kUnproxyEvents] = proxy_events_1.default(request, this, proxiedRequestEvents); - this[kRequest] = request; - this.emit('uploadProgress', this.uploadProgress); - // Send body - const body = this[kBody]; - const currentRequest = this.redirects.length === 0 ? this : request; - if (is_1.default.nodeStream(body)) { - body.pipe(currentRequest); - body.once('error', (error) => { - this._beforeError(new UploadError(error, this)); - }); - } - else { - this._unlockWrite(); - if (!is_1.default.undefined(body)) { - this._writeRequest(body, undefined, () => { }); - currentRequest.end(); - this._lockWrite(); - } - else if (this._cannotHaveBody || this._noPipe) { - currentRequest.end(); - this._lockWrite(); - } - } - this.emit('request', request); - } - async _createCacheableRequest(url, options) { - return new Promise((resolve, reject) => { - // TODO: Remove `utils/url-to-options.ts` when `cacheable-request` is fixed - Object.assign(options, url_to_options_1.default(url)); - // `http-cache-semantics` checks this - // TODO: Fix this ignore. - // @ts-expect-error - delete options.url; - let request; - // This is ugly - const cacheRequest = cacheableStore.get(options.cache)(options, async (response) => { - // TODO: Fix `cacheable-response` - response._readableState.autoDestroy = false; - if (request) { - (await request).emit('cacheableResponse', response); - } - resolve(response); - }); - // Restore options - options.url = url; - cacheRequest.once('error', reject); - cacheRequest.once('request', async (requestOrPromise) => { - request = requestOrPromise; - resolve(request); - }); - }); - } - async _makeRequest() { - var _a, _b, _c, _d, _e; - const { options } = this; - const { headers } = options; - for (const key in headers) { - if (is_1.default.undefined(headers[key])) { - // eslint-disable-next-line @typescript-eslint/no-dynamic-delete - delete headers[key]; - } - else if (is_1.default.null_(headers[key])) { - throw new TypeError(`Use \`undefined\` instead of \`null\` to delete the \`${key}\` header`); - } - } - if (options.decompress && is_1.default.undefined(headers['accept-encoding'])) { - headers['accept-encoding'] = supportsBrotli ? 'gzip, deflate, br' : 'gzip, deflate'; - } - // Set cookies - if (options.cookieJar) { - const cookieString = await options.cookieJar.getCookieString(options.url.toString()); - if (is_1.default.nonEmptyString(cookieString)) { - options.headers.cookie = cookieString; - } - } - for (const hook of options.hooks.beforeRequest) { - // eslint-disable-next-line no-await-in-loop - const result = await hook(options); - if (!is_1.default.undefined(result)) { - // @ts-expect-error Skip the type mismatch to support abstract responses - options.request = () => result; - break; - } - } - if (options.body && this[kBody] !== options.body) { - this[kBody] = options.body; - } - const { agent, request, timeout, url } = options; - if (options.dnsCache && !('lookup' in options)) { - options.lookup = options.dnsCache.lookup; - } - // UNIX sockets - if (url.hostname === 'unix') { - const matches = /(?.+?):(?.+)/.exec(`${url.pathname}${url.search}`); - if (matches === null || matches === void 0 ? void 0 : matches.groups) { - const { socketPath, path } = matches.groups; - Object.assign(options, { - socketPath, - path, - host: '' - }); - } - } - const isHttps = url.protocol === 'https:'; - // Fallback function - let fallbackFn; - if (options.http2) { - fallbackFn = http2wrapper.auto; - } - else { - fallbackFn = isHttps ? https.request : http.request; - } - const realFn = (_a = options.request) !== null && _a !== void 0 ? _a : fallbackFn; - // Cache support - const fn = options.cache ? this._createCacheableRequest : realFn; - // Pass an agent directly when HTTP2 is disabled - if (agent && !options.http2) { - options.agent = agent[isHttps ? 'https' : 'http']; - } - // Prepare plain HTTP request options - options[kRequest] = realFn; - delete options.request; - // TODO: Fix this ignore. - // @ts-expect-error - delete options.timeout; - const requestOptions = options; - requestOptions.shared = (_b = options.cacheOptions) === null || _b === void 0 ? void 0 : _b.shared; - requestOptions.cacheHeuristic = (_c = options.cacheOptions) === null || _c === void 0 ? void 0 : _c.cacheHeuristic; - requestOptions.immutableMinTimeToLive = (_d = options.cacheOptions) === null || _d === void 0 ? void 0 : _d.immutableMinTimeToLive; - requestOptions.ignoreCargoCult = (_e = options.cacheOptions) === null || _e === void 0 ? void 0 : _e.ignoreCargoCult; - // If `dnsLookupIpVersion` is not present do not override `family` - if (options.dnsLookupIpVersion !== undefined) { - try { - requestOptions.family = dns_ip_version_1.dnsLookupIpVersionToFamily(options.dnsLookupIpVersion); - } - catch (_f) { - throw new Error('Invalid `dnsLookupIpVersion` option value'); - } - } - // HTTPS options remapping - if (options.https) { - if ('rejectUnauthorized' in options.https) { - requestOptions.rejectUnauthorized = options.https.rejectUnauthorized; - } - if (options.https.checkServerIdentity) { - requestOptions.checkServerIdentity = options.https.checkServerIdentity; - } - if (options.https.certificateAuthority) { - requestOptions.ca = options.https.certificateAuthority; - } - if (options.https.certificate) { - requestOptions.cert = options.https.certificate; - } - if (options.https.key) { - requestOptions.key = options.https.key; - } - if (options.https.passphrase) { - requestOptions.passphrase = options.https.passphrase; - } - if (options.https.pfx) { - requestOptions.pfx = options.https.pfx; - } - } - try { - let requestOrResponse = await fn(url, requestOptions); - if (is_1.default.undefined(requestOrResponse)) { - requestOrResponse = fallbackFn(url, requestOptions); - } - // Restore options - options.request = request; - options.timeout = timeout; - options.agent = agent; - // HTTPS options restore - if (options.https) { - if ('rejectUnauthorized' in options.https) { - delete requestOptions.rejectUnauthorized; - } - if (options.https.checkServerIdentity) { - // @ts-expect-error - This one will be removed when we remove the alias. - delete requestOptions.checkServerIdentity; - } - if (options.https.certificateAuthority) { - delete requestOptions.ca; - } - if (options.https.certificate) { - delete requestOptions.cert; - } - if (options.https.key) { - delete requestOptions.key; - } - if (options.https.passphrase) { - delete requestOptions.passphrase; - } - if (options.https.pfx) { - delete requestOptions.pfx; - } - } - if (isClientRequest(requestOrResponse)) { - this._onRequest(requestOrResponse); - // Emit the response after the stream has been ended - } - else if (this.writable) { - this.once('finish', () => { - void this._onResponse(requestOrResponse); - }); - this._unlockWrite(); - this.end(); - this._lockWrite(); - } - else { - void this._onResponse(requestOrResponse); - } - } - catch (error) { - if (error instanceof CacheableRequest.CacheError) { - throw new CacheError(error, this); - } - throw new RequestError(error.message, error, this); - } - } - async _error(error) { - try { - for (const hook of this.options.hooks.beforeError) { - // eslint-disable-next-line no-await-in-loop - error = await hook(error); - } - } - catch (error_) { - error = new RequestError(error_.message, error_, this); - } - this.destroy(error); - } - _beforeError(error) { - if (this[kStopReading]) { - return; - } - const { options } = this; - const retryCount = this.retryCount + 1; - this[kStopReading] = true; - if (!(error instanceof RequestError)) { - error = new RequestError(error.message, error, this); - } - const typedError = error; - const { response } = typedError; - void (async () => { - if (response && !response.body) { - response.setEncoding(this._readableState.encoding); - try { - response.rawBody = await get_buffer_1.default(response); - response.body = response.rawBody.toString(); - } - catch (_a) { } - } - if (this.listenerCount('retry') !== 0) { - let backoff; - try { - let retryAfter; - if (response && 'retry-after' in response.headers) { - retryAfter = Number(response.headers['retry-after']); - if (Number.isNaN(retryAfter)) { - retryAfter = Date.parse(response.headers['retry-after']) - Date.now(); - if (retryAfter <= 0) { - retryAfter = 1; - } - } - else { - retryAfter *= 1000; - } - } - backoff = await options.retry.calculateDelay({ - attemptCount: retryCount, - retryOptions: options.retry, - error: typedError, - retryAfter, - computedValue: calculate_retry_delay_1.default({ - attemptCount: retryCount, - retryOptions: options.retry, - error: typedError, - retryAfter, - computedValue: 0 - }) - }); - } - catch (error_) { - void this._error(new RequestError(error_.message, error_, this)); - return; - } - if (backoff) { - const retry = async () => { - try { - for (const hook of this.options.hooks.beforeRetry) { - // eslint-disable-next-line no-await-in-loop - await hook(this.options, typedError, retryCount); - } - } - catch (error_) { - void this._error(new RequestError(error_.message, error, this)); - return; - } - // Something forced us to abort the retry - if (this.destroyed) { - return; - } - this.destroy(); - this.emit('retry', retryCount, error); - }; - this[kRetryTimeout] = setTimeout(retry, backoff); - return; - } - } - void this._error(typedError); - })(); - } - _read() { - this[kTriggerRead] = true; - const response = this[kResponse]; - if (response && !this[kStopReading]) { - // We cannot put this in the `if` above - // because `.read()` also triggers the `end` event - if (response.readableLength) { - this[kTriggerRead] = false; - } - let data; - while ((data = response.read()) !== null) { - this[kDownloadedSize] += data.length; - this[kStartedReading] = true; - const progress = this.downloadProgress; - if (progress.percent < 1) { - this.emit('downloadProgress', progress); - } - this.push(data); - } - } - } - // Node.js 12 has incorrect types, so the encoding must be a string - _write(chunk, encoding, callback) { - const write = () => { - this._writeRequest(chunk, encoding, callback); - }; - if (this.requestInitialized) { - write(); - } - else { - this[kJobs].push(write); - } - } - _writeRequest(chunk, encoding, callback) { - if (this[kRequest].destroyed) { - // Probably the `ClientRequest` instance will throw - return; - } - this._progressCallbacks.push(() => { - this[kUploadedSize] += Buffer.byteLength(chunk, encoding); - const progress = this.uploadProgress; - if (progress.percent < 1) { - this.emit('uploadProgress', progress); - } - }); - // TODO: What happens if it's from cache? Then this[kRequest] won't be defined. - this[kRequest].write(chunk, encoding, (error) => { - if (!error && this._progressCallbacks.length > 0) { - this._progressCallbacks.shift()(); - } - callback(error); - }); - } - _final(callback) { - const endRequest = () => { - // FIX: Node.js 10 calls the write callback AFTER the end callback! - while (this._progressCallbacks.length !== 0) { - this._progressCallbacks.shift()(); - } - // We need to check if `this[kRequest]` is present, - // because it isn't when we use cache. - if (!(kRequest in this)) { - callback(); - return; - } - if (this[kRequest].destroyed) { - callback(); - return; - } - this[kRequest].end((error) => { - if (!error) { - this[kBodySize] = this[kUploadedSize]; - this.emit('uploadProgress', this.uploadProgress); - this[kRequest].emit('upload-complete'); - } - callback(error); - }); - }; - if (this.requestInitialized) { - endRequest(); - } - else { - this[kJobs].push(endRequest); - } - } - _destroy(error, callback) { - var _a; - this[kStopReading] = true; - // Prevent further retries - clearTimeout(this[kRetryTimeout]); - if (kRequest in this) { - this[kCancelTimeouts](); - // TODO: Remove the next `if` when these get fixed: - // - https://github.com/nodejs/node/issues/32851 - if (!((_a = this[kResponse]) === null || _a === void 0 ? void 0 : _a.complete)) { - this[kRequest].destroy(); - } - } - if (error !== null && !is_1.default.undefined(error) && !(error instanceof RequestError)) { - error = new RequestError(error.message, error, this); - } - callback(error); - } - get _isAboutToError() { - return this[kStopReading]; - } - /** - The remote IP address. - */ - get ip() { - var _a; - return (_a = this.socket) === null || _a === void 0 ? void 0 : _a.remoteAddress; - } - /** - Indicates whether the request has been aborted or not. - */ - get aborted() { - var _a, _b, _c; - return ((_b = (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.destroyed) !== null && _b !== void 0 ? _b : this.destroyed) && !((_c = this[kOriginalResponse]) === null || _c === void 0 ? void 0 : _c.complete); - } - get socket() { - var _a, _b; - return (_b = (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.socket) !== null && _b !== void 0 ? _b : undefined; - } - /** - Progress event for downloading (receiving a response). - */ - get downloadProgress() { - let percent; - if (this[kResponseSize]) { - percent = this[kDownloadedSize] / this[kResponseSize]; - } - else if (this[kResponseSize] === this[kDownloadedSize]) { - percent = 1; - } - else { - percent = 0; - } - return { - percent, - transferred: this[kDownloadedSize], - total: this[kResponseSize] - }; - } - /** - Progress event for uploading (sending a request). - */ - get uploadProgress() { - let percent; - if (this[kBodySize]) { - percent = this[kUploadedSize] / this[kBodySize]; - } - else if (this[kBodySize] === this[kUploadedSize]) { - percent = 1; - } - else { - percent = 0; - } - return { - percent, - transferred: this[kUploadedSize], - total: this[kBodySize] - }; - } - /** - The object contains the following properties: - - - `start` - Time when the request started. - - `socket` - Time when a socket was assigned to the request. - - `lookup` - Time when the DNS lookup finished. - - `connect` - Time when the socket successfully connected. - - `secureConnect` - Time when the socket securely connected. - - `upload` - Time when the request finished uploading. - - `response` - Time when the request fired `response` event. - - `end` - Time when the response fired `end` event. - - `error` - Time when the request fired `error` event. - - `abort` - Time when the request fired `abort` event. - - `phases` - - `wait` - `timings.socket - timings.start` - - `dns` - `timings.lookup - timings.socket` - - `tcp` - `timings.connect - timings.lookup` - - `tls` - `timings.secureConnect - timings.connect` - - `request` - `timings.upload - (timings.secureConnect || timings.connect)` - - `firstByte` - `timings.response - timings.upload` - - `download` - `timings.end - timings.response` - - `total` - `(timings.end || timings.error || timings.abort) - timings.start` - - If something has not been measured yet, it will be `undefined`. - - __Note__: The time is a `number` representing the milliseconds elapsed since the UNIX epoch. - */ - get timings() { - var _a; - return (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.timings; - } - /** - Whether the response was retrieved from the cache. - */ - get isFromCache() { - return this[kIsFromCache]; - } - pipe(destination, options) { - if (this[kStartedReading]) { - throw new Error('Failed to pipe. The response has been emitted already.'); - } - if (destination instanceof http_1.ServerResponse) { - this[kServerResponsesPiped].add(destination); - } - return super.pipe(destination, options); - } - unpipe(destination) { - if (destination instanceof http_1.ServerResponse) { - this[kServerResponsesPiped].delete(destination); - } - super.unpipe(destination); - return this; - } -} -exports["default"] = Request; - - -/***/ }), - -/***/ 91037: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.dnsLookupIpVersionToFamily = exports.isDnsLookupIpVersion = void 0; -const conversionTable = { - auto: 0, - ipv4: 4, - ipv6: 6 -}; -exports.isDnsLookupIpVersion = (value) => { - return value in conversionTable; -}; -exports.dnsLookupIpVersionToFamily = (dnsLookupIpVersion) => { - if (exports.isDnsLookupIpVersion(dnsLookupIpVersion)) { - return conversionTable[dnsLookupIpVersion]; - } - throw new Error('Invalid DNS lookup IP version'); -}; - - -/***/ }), - -/***/ 29296: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -const fs_1 = __nccwpck_require__(79896); -const util_1 = __nccwpck_require__(39023); -const is_1 = __nccwpck_require__(64001); -const is_form_data_1 = __nccwpck_require__(6751); -const statAsync = util_1.promisify(fs_1.stat); -exports["default"] = async (body, headers) => { - if (headers && 'content-length' in headers) { - return Number(headers['content-length']); - } - if (!body) { - return 0; - } - if (is_1.default.string(body)) { - return Buffer.byteLength(body); - } - if (is_1.default.buffer(body)) { - return body.length; - } - if (is_form_data_1.default(body)) { - return util_1.promisify(body.getLength.bind(body))(); - } - if (body instanceof fs_1.ReadStream) { - const { size } = await statAsync(body.path); - if (size === 0) { - return undefined; - } - return size; - } - return undefined; -}; - - -/***/ }), - -/***/ 64858: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -// TODO: Update https://github.com/sindresorhus/get-stream -const getBuffer = async (stream) => { - const chunks = []; - let length = 0; - for await (const chunk of stream) { - chunks.push(chunk); - length += Buffer.byteLength(chunk); - } - if (Buffer.isBuffer(chunks[0])) { - return Buffer.concat(chunks, length); - } - return Buffer.from(chunks.join('')); -}; -exports["default"] = getBuffer; - - -/***/ }), - -/***/ 6751: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -const is_1 = __nccwpck_require__(64001); -exports["default"] = (body) => is_1.default.nodeStream(body) && is_1.default.function_(body.getBoundary); - - -/***/ }), - -/***/ 4350: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.isResponseOk = void 0; -exports.isResponseOk = (response) => { - const { statusCode } = response; - const limitStatusCode = response.request.options.followRedirect ? 299 : 399; - return (statusCode >= 200 && statusCode <= limitStatusCode) || statusCode === 304; -}; - - -/***/ }), - -/***/ 95743: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -/* istanbul ignore file: deprecated */ -const url_1 = __nccwpck_require__(87016); -const keys = [ - 'protocol', - 'host', - 'hostname', - 'port', - 'pathname', - 'search' -]; -exports["default"] = (origin, options) => { - var _a, _b; - if (options.path) { - if (options.pathname) { - throw new TypeError('Parameters `path` and `pathname` are mutually exclusive.'); - } - if (options.search) { - throw new TypeError('Parameters `path` and `search` are mutually exclusive.'); - } - if (options.searchParams) { - throw new TypeError('Parameters `path` and `searchParams` are mutually exclusive.'); - } - } - if (options.search && options.searchParams) { - throw new TypeError('Parameters `search` and `searchParams` are mutually exclusive.'); - } - if (!origin) { - if (!options.protocol) { - throw new TypeError('No URL protocol specified'); - } - origin = `${options.protocol}//${(_b = (_a = options.hostname) !== null && _a !== void 0 ? _a : options.host) !== null && _b !== void 0 ? _b : ''}`; - } - const url = new url_1.URL(origin); - if (options.path) { - const searchIndex = options.path.indexOf('?'); - if (searchIndex === -1) { - options.pathname = options.path; - } - else { - options.pathname = options.path.slice(0, searchIndex); - options.search = options.path.slice(searchIndex + 1); - } - delete options.path; - } - for (const key of keys) { - if (options[key]) { - url[key] = options[key].toString(); - } - } - return url; -}; - - -/***/ }), - -/***/ 27813: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -function default_1(from, to, events) { - const fns = {}; - for (const event of events) { - fns[event] = (...args) => { - to.emit(event, ...args); - }; - from.on(event, fns[event]); - } - return () => { - for (const event of events) { - from.off(event, fns[event]); - } - }; -} -exports["default"] = default_1; - - -/***/ }), - -/***/ 94501: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.TimeoutError = void 0; -const net = __nccwpck_require__(69278); -const unhandle_1 = __nccwpck_require__(89246); -const reentry = Symbol('reentry'); -const noop = () => { }; -class TimeoutError extends Error { - constructor(threshold, event) { - super(`Timeout awaiting '${event}' for ${threshold}ms`); - this.event = event; - this.name = 'TimeoutError'; - this.code = 'ETIMEDOUT'; - } -} -exports.TimeoutError = TimeoutError; -exports["default"] = (request, delays, options) => { - if (reentry in request) { - return noop; - } - request[reentry] = true; - const cancelers = []; - const { once, unhandleAll } = unhandle_1.default(); - const addTimeout = (delay, callback, event) => { - var _a; - const timeout = setTimeout(callback, delay, delay, event); - (_a = timeout.unref) === null || _a === void 0 ? void 0 : _a.call(timeout); - const cancel = () => { - clearTimeout(timeout); - }; - cancelers.push(cancel); - return cancel; - }; - const { host, hostname } = options; - const timeoutHandler = (delay, event) => { - request.destroy(new TimeoutError(delay, event)); - }; - const cancelTimeouts = () => { - for (const cancel of cancelers) { - cancel(); - } - unhandleAll(); - }; - request.once('error', error => { - cancelTimeouts(); - // Save original behavior - /* istanbul ignore next */ - if (request.listenerCount('error') === 0) { - throw error; - } - }); - request.once('close', cancelTimeouts); - once(request, 'response', (response) => { - once(response, 'end', cancelTimeouts); - }); - if (typeof delays.request !== 'undefined') { - addTimeout(delays.request, timeoutHandler, 'request'); - } - if (typeof delays.socket !== 'undefined') { - const socketTimeoutHandler = () => { - timeoutHandler(delays.socket, 'socket'); - }; - request.setTimeout(delays.socket, socketTimeoutHandler); - // `request.setTimeout(0)` causes a memory leak. - // We can just remove the listener and forget about the timer - it's unreffed. - // See https://github.com/sindresorhus/got/issues/690 - cancelers.push(() => { - request.removeListener('timeout', socketTimeoutHandler); - }); - } - once(request, 'socket', (socket) => { - var _a; - const { socketPath } = request; - /* istanbul ignore next: hard to test */ - if (socket.connecting) { - const hasPath = Boolean(socketPath !== null && socketPath !== void 0 ? socketPath : net.isIP((_a = hostname !== null && hostname !== void 0 ? hostname : host) !== null && _a !== void 0 ? _a : '') !== 0); - if (typeof delays.lookup !== 'undefined' && !hasPath && typeof socket.address().address === 'undefined') { - const cancelTimeout = addTimeout(delays.lookup, timeoutHandler, 'lookup'); - once(socket, 'lookup', cancelTimeout); - } - if (typeof delays.connect !== 'undefined') { - const timeConnect = () => addTimeout(delays.connect, timeoutHandler, 'connect'); - if (hasPath) { - once(socket, 'connect', timeConnect()); - } - else { - once(socket, 'lookup', (error) => { - if (error === null) { - once(socket, 'connect', timeConnect()); - } - }); - } - } - if (typeof delays.secureConnect !== 'undefined' && options.protocol === 'https:') { - once(socket, 'connect', () => { - const cancelTimeout = addTimeout(delays.secureConnect, timeoutHandler, 'secureConnect'); - once(socket, 'secureConnect', cancelTimeout); - }); - } - } - if (typeof delays.send !== 'undefined') { - const timeRequest = () => addTimeout(delays.send, timeoutHandler, 'send'); - /* istanbul ignore next: hard to test */ - if (socket.connecting) { - once(socket, 'connect', () => { - once(request, 'upload-complete', timeRequest()); - }); - } - else { - once(request, 'upload-complete', timeRequest()); - } - } - }); - if (typeof delays.response !== 'undefined') { - once(request, 'upload-complete', () => { - const cancelTimeout = addTimeout(delays.response, timeoutHandler, 'response'); - once(request, 'response', cancelTimeout); - }); - } - return cancelTimeouts; -}; - - -/***/ }), - -/***/ 89246: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -// When attaching listeners, it's very easy to forget about them. -// Especially if you do error handling and set timeouts. -// So instead of checking if it's proper to throw an error on every timeout ever, -// use this simple tool which will remove all listeners you have attached. -exports["default"] = () => { - const handlers = []; - return { - once(origin, event, fn) { - origin.once(event, fn); - handlers.push({ origin, event, fn }); - }, - unhandleAll() { - for (const handler of handlers) { - const { origin, event, fn } = handler; - origin.removeListener(event, fn); - } - handlers.length = 0; - } - }; -}; - - -/***/ }), - -/***/ 53873: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -const is_1 = __nccwpck_require__(64001); -exports["default"] = (url) => { - // Cast to URL - url = url; - const options = { - protocol: url.protocol, - hostname: is_1.default.string(url.hostname) && url.hostname.startsWith('[') ? url.hostname.slice(1, -1) : url.hostname, - host: url.host, - hash: url.hash, - search: url.search, - pathname: url.pathname, - href: url.href, - path: `${url.pathname || ''}${url.search || ''}` - }; - if (is_1.default.string(url.port) && url.port.length > 0) { - options.port = Number(url.port); - } - if (url.username || url.password) { - options.auth = `${url.username || ''}:${url.password || ''}`; - } - return options; -}; - - -/***/ }), - -/***/ 30172: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -class WeakableMap { - constructor() { - this.weakMap = new WeakMap(); - this.map = new Map(); - } - set(key, value) { - if (typeof key === 'object') { - this.weakMap.set(key, value); - } - else { - this.map.set(key, value); - } - } - get(key) { - if (typeof key === 'object') { - return this.weakMap.get(key); - } - return this.map.get(key); - } - has(key) { - if (typeof key === 'object') { - return this.weakMap.has(key); - } - return this.map.has(key); - } -} -exports["default"] = WeakableMap; - - -/***/ }), - -/***/ 79941: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.defaultHandler = void 0; -const is_1 = __nccwpck_require__(64001); -const as_promise_1 = __nccwpck_require__(72126); -const create_rejection_1 = __nccwpck_require__(87814); -const core_1 = __nccwpck_require__(86825); -const deep_freeze_1 = __nccwpck_require__(52949); -const errors = { - RequestError: as_promise_1.RequestError, - CacheError: as_promise_1.CacheError, - ReadError: as_promise_1.ReadError, - HTTPError: as_promise_1.HTTPError, - MaxRedirectsError: as_promise_1.MaxRedirectsError, - TimeoutError: as_promise_1.TimeoutError, - ParseError: as_promise_1.ParseError, - CancelError: as_promise_1.CancelError, - UnsupportedProtocolError: as_promise_1.UnsupportedProtocolError, - UploadError: as_promise_1.UploadError -}; -// The `delay` package weighs 10KB (!) -const delay = async (ms) => new Promise(resolve => { - setTimeout(resolve, ms); -}); -const { normalizeArguments } = core_1.default; -const mergeOptions = (...sources) => { - let mergedOptions; - for (const source of sources) { - mergedOptions = normalizeArguments(undefined, source, mergedOptions); - } - return mergedOptions; -}; -const getPromiseOrStream = (options) => options.isStream ? new core_1.default(undefined, options) : as_promise_1.default(options); -const isGotInstance = (value) => ('defaults' in value && 'options' in value.defaults); -const aliases = [ - 'get', - 'post', - 'put', - 'patch', - 'head', - 'delete' -]; -exports.defaultHandler = (options, next) => next(options); -const callInitHooks = (hooks, options) => { - if (hooks) { - for (const hook of hooks) { - hook(options); - } - } -}; -const create = (defaults) => { - // Proxy properties from next handlers - defaults._rawHandlers = defaults.handlers; - defaults.handlers = defaults.handlers.map(fn => ((options, next) => { - // This will be assigned by assigning result - let root; - const result = fn(options, newOptions => { - root = next(newOptions); - return root; - }); - if (result !== root && !options.isStream && root) { - const typedResult = result; - const { then: promiseThen, catch: promiseCatch, finally: promiseFianlly } = typedResult; - Object.setPrototypeOf(typedResult, Object.getPrototypeOf(root)); - Object.defineProperties(typedResult, Object.getOwnPropertyDescriptors(root)); - // These should point to the new promise - // eslint-disable-next-line promise/prefer-await-to-then - typedResult.then = promiseThen; - typedResult.catch = promiseCatch; - typedResult.finally = promiseFianlly; - } - return result; - })); - // Got interface - const got = ((url, options = {}, _defaults) => { - var _a, _b; - let iteration = 0; - const iterateHandlers = (newOptions) => { - return defaults.handlers[iteration++](newOptions, iteration === defaults.handlers.length ? getPromiseOrStream : iterateHandlers); - }; - // TODO: Remove this in Got 12. - if (is_1.default.plainObject(url)) { - const mergedOptions = { - ...url, - ...options - }; - core_1.setNonEnumerableProperties([url, options], mergedOptions); - options = mergedOptions; - url = undefined; - } - try { - // Call `init` hooks - let initHookError; - try { - callInitHooks(defaults.options.hooks.init, options); - callInitHooks((_a = options.hooks) === null || _a === void 0 ? void 0 : _a.init, options); - } - catch (error) { - initHookError = error; - } - // Normalize options & call handlers - const normalizedOptions = normalizeArguments(url, options, _defaults !== null && _defaults !== void 0 ? _defaults : defaults.options); - normalizedOptions[core_1.kIsNormalizedAlready] = true; - if (initHookError) { - throw new as_promise_1.RequestError(initHookError.message, initHookError, normalizedOptions); - } - return iterateHandlers(normalizedOptions); - } - catch (error) { - if (options.isStream) { - throw error; - } - else { - return create_rejection_1.default(error, defaults.options.hooks.beforeError, (_b = options.hooks) === null || _b === void 0 ? void 0 : _b.beforeError); - } - } - }); - got.extend = (...instancesOrOptions) => { - const optionsArray = [defaults.options]; - let handlers = [...defaults._rawHandlers]; - let isMutableDefaults; - for (const value of instancesOrOptions) { - if (isGotInstance(value)) { - optionsArray.push(value.defaults.options); - handlers.push(...value.defaults._rawHandlers); - isMutableDefaults = value.defaults.mutableDefaults; - } - else { - optionsArray.push(value); - if ('handlers' in value) { - handlers.push(...value.handlers); - } - isMutableDefaults = value.mutableDefaults; - } - } - handlers = handlers.filter(handler => handler !== exports.defaultHandler); - if (handlers.length === 0) { - handlers.push(exports.defaultHandler); - } - return create({ - options: mergeOptions(...optionsArray), - handlers, - mutableDefaults: Boolean(isMutableDefaults) - }); - }; - // Pagination - const paginateEach = (async function* (url, options) { - // TODO: Remove this `@ts-expect-error` when upgrading to TypeScript 4. - // Error: Argument of type 'Merge> | undefined' is not assignable to parameter of type 'Options | undefined'. - // @ts-expect-error - let normalizedOptions = normalizeArguments(url, options, defaults.options); - normalizedOptions.resolveBodyOnly = false; - const pagination = normalizedOptions.pagination; - if (!is_1.default.object(pagination)) { - throw new TypeError('`options.pagination` must be implemented'); - } - const all = []; - let { countLimit } = pagination; - let numberOfRequests = 0; - while (numberOfRequests < pagination.requestLimit) { - if (numberOfRequests !== 0) { - // eslint-disable-next-line no-await-in-loop - await delay(pagination.backoff); - } - // @ts-expect-error FIXME! - // TODO: Throw when result is not an instance of Response - // eslint-disable-next-line no-await-in-loop - const result = (await got(undefined, undefined, normalizedOptions)); - // eslint-disable-next-line no-await-in-loop - const parsed = await pagination.transform(result); - const current = []; - for (const item of parsed) { - if (pagination.filter(item, all, current)) { - if (!pagination.shouldContinue(item, all, current)) { - return; - } - yield item; - if (pagination.stackAllItems) { - all.push(item); - } - current.push(item); - if (--countLimit <= 0) { - return; - } - } - } - const optionsToMerge = pagination.paginate(result, all, current); - if (optionsToMerge === false) { - return; - } - if (optionsToMerge === result.request.options) { - normalizedOptions = result.request.options; - } - else if (optionsToMerge !== undefined) { - normalizedOptions = normalizeArguments(undefined, optionsToMerge, normalizedOptions); - } - numberOfRequests++; - } - }); - got.paginate = paginateEach; - got.paginate.all = (async (url, options) => { - const results = []; - for await (const item of paginateEach(url, options)) { - results.push(item); - } - return results; - }); - // For those who like very descriptive names - got.paginate.each = paginateEach; - // Stream API - got.stream = ((url, options) => got(url, { ...options, isStream: true })); - // Shortcuts - for (const method of aliases) { - got[method] = ((url, options) => got(url, { ...options, method })); - got.stream[method] = ((url, options) => { - return got(url, { ...options, method, isStream: true }); - }); - } - Object.assign(got, errors); - Object.defineProperty(got, 'defaults', { - value: defaults.mutableDefaults ? defaults : deep_freeze_1.default(defaults), - writable: defaults.mutableDefaults, - configurable: defaults.mutableDefaults, - enumerable: true - }); - got.mergeOptions = mergeOptions; - return got; -}; -exports["default"] = create; -__exportStar(__nccwpck_require__(29612), exports); - - -/***/ }), - -/***/ 46757: -/***/ (function(module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -const url_1 = __nccwpck_require__(87016); -const create_1 = __nccwpck_require__(79941); -const defaults = { - options: { - method: 'GET', - retry: { - limit: 2, - methods: [ - 'GET', - 'PUT', - 'HEAD', - 'DELETE', - 'OPTIONS', - 'TRACE' - ], - statusCodes: [ - 408, - 413, - 429, - 500, - 502, - 503, - 504, - 521, - 522, - 524 - ], - errorCodes: [ - 'ETIMEDOUT', - 'ECONNRESET', - 'EADDRINUSE', - 'ECONNREFUSED', - 'EPIPE', - 'ENOTFOUND', - 'ENETUNREACH', - 'EAI_AGAIN' - ], - maxRetryAfter: undefined, - calculateDelay: ({ computedValue }) => computedValue - }, - timeout: {}, - headers: { - 'user-agent': 'got (https://github.com/sindresorhus/got)' - }, - hooks: { - init: [], - beforeRequest: [], - beforeRedirect: [], - beforeRetry: [], - beforeError: [], - afterResponse: [] - }, - cache: undefined, - dnsCache: undefined, - decompress: true, - throwHttpErrors: true, - followRedirect: true, - isStream: false, - responseType: 'text', - resolveBodyOnly: false, - maxRedirects: 10, - prefixUrl: '', - methodRewriting: true, - ignoreInvalidCookies: false, - context: {}, - // TODO: Set this to `true` when Got 12 gets released - http2: false, - allowGetBody: false, - https: undefined, - pagination: { - transform: (response) => { - if (response.request.options.responseType === 'json') { - return response.body; - } - return JSON.parse(response.body); - }, - paginate: response => { - if (!Reflect.has(response.headers, 'link')) { - return false; - } - const items = response.headers.link.split(','); - let next; - for (const item of items) { - const parsed = item.split(';'); - if (parsed[1].includes('next')) { - next = parsed[0].trimStart().trim(); - next = next.slice(1, -1); - break; - } - } - if (next) { - const options = { - url: new url_1.URL(next) - }; - return options; - } - return false; - }, - filter: () => true, - shouldContinue: () => true, - countLimit: Infinity, - backoff: 0, - requestLimit: 10000, - stackAllItems: true - }, - parseJson: (text) => JSON.parse(text), - stringifyJson: (object) => JSON.stringify(object), - cacheOptions: {} - }, - handlers: [create_1.defaultHandler], - mutableDefaults: false -}; -const got = create_1.default(defaults); -exports["default"] = got; -// For CommonJS default export support -module.exports = got; -module.exports["default"] = got; -module.exports.__esModule = true; // Workaround for TS issue: https://github.com/sindresorhus/got/pull/1267 -__exportStar(__nccwpck_require__(79941), exports); -__exportStar(__nccwpck_require__(72126), exports); - - -/***/ }), - -/***/ 29612: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); - - -/***/ }), - -/***/ 52949: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -const is_1 = __nccwpck_require__(64001); -function deepFreeze(object) { - for (const value of Object.values(object)) { - if (is_1.default.plainObject(value) || is_1.default.array(value)) { - deepFreeze(value); - } - } - return Object.freeze(object); -} -exports["default"] = deepFreeze; - - -/***/ }), - -/***/ 39796: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -const alreadyWarned = new Set(); -exports["default"] = (message) => { - if (alreadyWarned.has(message)) { - return; - } - alreadyWarned.add(message); - // @ts-expect-error Missing types. - process.emitWarning(`Got: ${message}`, { - type: 'DeprecationWarning' - }); -}; - - -/***/ }), - -/***/ 39707: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - -const fs = __nccwpck_require__(79896); -const path = __nccwpck_require__(16928); -const crypto = __nccwpck_require__(76982); -const isStream = __nccwpck_require__(96543); - -const {Worker} = (() => { - try { - return __nccwpck_require__(28167); - } catch (_) { - return {}; - } -})(); - -let worker; // Lazy -let taskIdCounter = 0; -const tasks = new Map(); - -const recreateWorkerError = sourceError => { - const error = new Error(sourceError.message); - - for (const [key, value] of Object.entries(sourceError)) { - if (key !== 'message') { - error[key] = value; - } - } - - return error; -}; - -const createWorker = () => { - worker = new Worker(__nccwpck_require__.ab + "thread.js"); - - worker.on('message', message => { - const task = tasks.get(message.id); - tasks.delete(message.id); - - if (tasks.size === 0) { - worker.unref(); - } - - if (message.error === undefined) { - task.resolve(message.value); - } else { - task.reject(recreateWorkerError(message.error)); - } - }); - - worker.on('error', error => { - // Any error here is effectively an equivalent of segfault, and have no scope, so we just throw it on callback level - throw error; - }); -}; - -const taskWorker = (method, args, transferList) => new Promise((resolve, reject) => { - const id = taskIdCounter++; - tasks.set(id, {resolve, reject}); - - if (worker === undefined) { - createWorker(); - } - - worker.ref(); - worker.postMessage({id, method, args}, transferList); -}); - -const hasha = (input, options = {}) => { - let outputEncoding = options.encoding || 'hex'; - - if (outputEncoding === 'buffer') { - outputEncoding = undefined; - } - - const hash = crypto.createHash(options.algorithm || 'sha512'); - - const update = buffer => { - const inputEncoding = typeof buffer === 'string' ? 'utf8' : undefined; - hash.update(buffer, inputEncoding); - }; - - if (Array.isArray(input)) { - input.forEach(update); - } else { - update(input); - } - - return hash.digest(outputEncoding); -}; - -hasha.stream = (options = {}) => { - let outputEncoding = options.encoding || 'hex'; - - if (outputEncoding === 'buffer') { - outputEncoding = undefined; - } - - const stream = crypto.createHash(options.algorithm || 'sha512'); - stream.setEncoding(outputEncoding); - return stream; -}; - -hasha.fromStream = async (stream, options = {}) => { - if (!isStream(stream)) { - throw new TypeError('Expected a stream'); - } - - return new Promise((resolve, reject) => { - // TODO: Use `stream.pipeline` and `stream.finished` when targeting Node.js 10 - stream - .on('error', reject) - .pipe(hasha.stream(options)) - .on('error', reject) - .on('finish', function () { - resolve(this.read()); - }); - }); -}; - -if (Worker === undefined) { - hasha.fromFile = async (filePath, options) => hasha.fromStream(fs.createReadStream(filePath), options); - hasha.async = async (input, options) => hasha(input, options); -} else { - hasha.fromFile = async (filePath, {algorithm = 'sha512', encoding = 'hex'} = {}) => { - const hash = await taskWorker('hashFile', [algorithm, filePath]); - - if (encoding === 'buffer') { - return Buffer.from(hash); - } - - return Buffer.from(hash).toString(encoding); - }; - - hasha.async = async (input, {algorithm = 'sha512', encoding = 'hex'} = {}) => { - if (encoding === 'buffer') { - encoding = undefined; - } - - const hash = await taskWorker('hash', [algorithm, input]); - - if (encoding === undefined) { - return Buffer.from(hash); - } - - return Buffer.from(hash).toString(encoding); - }; -} - -hasha.fromFileSync = (filePath, options) => hasha(fs.readFileSync(filePath), options); - -module.exports = hasha; - - -/***/ }), - -/***/ 12203: -/***/ ((module) => { - -"use strict"; - -// rfc7231 6.1 -const statusCodeCacheableByDefault = new Set([ - 200, - 203, - 204, - 206, - 300, - 301, - 308, - 404, - 405, - 410, - 414, - 501, -]); - -// This implementation does not understand partial responses (206) -const understoodStatuses = new Set([ - 200, - 203, - 204, - 300, - 301, - 302, - 303, - 307, - 308, - 404, - 405, - 410, - 414, - 501, -]); - -const errorStatusCodes = new Set([ - 500, - 502, - 503, - 504, -]); - -const hopByHopHeaders = { - date: true, // included, because we add Age update Date - connection: true, - 'keep-alive': true, - 'proxy-authenticate': true, - 'proxy-authorization': true, - te: true, - trailer: true, - 'transfer-encoding': true, - upgrade: true, -}; - -const excludedFromRevalidationUpdate = { - // Since the old body is reused, it doesn't make sense to change properties of the body - 'content-length': true, - 'content-encoding': true, - 'transfer-encoding': true, - 'content-range': true, -}; - -function toNumberOrZero(s) { - const n = parseInt(s, 10); - return isFinite(n) ? n : 0; -} - -// RFC 5861 -function isErrorResponse(response) { - // consider undefined response as faulty - if(!response) { - return true - } - return errorStatusCodes.has(response.status); -} - -function parseCacheControl(header) { - const cc = {}; - if (!header) return cc; - - // TODO: When there is more than one value present for a given directive (e.g., two Expires header fields, multiple Cache-Control: max-age directives), - // the directive's value is considered invalid. Caches are encouraged to consider responses that have invalid freshness information to be stale - const parts = header.trim().split(/,/); - for (const part of parts) { - const [k, v] = part.split(/=/, 2); - cc[k.trim()] = v === undefined ? true : v.trim().replace(/^"|"$/g, ''); - } - - return cc; -} - -function formatCacheControl(cc) { - let parts = []; - for (const k in cc) { - const v = cc[k]; - parts.push(v === true ? k : k + '=' + v); - } - if (!parts.length) { - return undefined; - } - return parts.join(', '); -} - -module.exports = class CachePolicy { - constructor( - req, - res, - { - shared, - cacheHeuristic, - immutableMinTimeToLive, - ignoreCargoCult, - _fromObject, - } = {} - ) { - if (_fromObject) { - this._fromObject(_fromObject); - return; - } - - if (!res || !res.headers) { - throw Error('Response headers missing'); - } - this._assertRequestHasHeaders(req); - - this._responseTime = this.now(); - this._isShared = shared !== false; - this._cacheHeuristic = - undefined !== cacheHeuristic ? cacheHeuristic : 0.1; // 10% matches IE - this._immutableMinTtl = - undefined !== immutableMinTimeToLive - ? immutableMinTimeToLive - : 24 * 3600 * 1000; - - this._status = 'status' in res ? res.status : 200; - this._resHeaders = res.headers; - this._rescc = parseCacheControl(res.headers['cache-control']); - this._method = 'method' in req ? req.method : 'GET'; - this._url = req.url; - this._host = req.headers.host; - this._noAuthorization = !req.headers.authorization; - this._reqHeaders = res.headers.vary ? req.headers : null; // Don't keep all request headers if they won't be used - this._reqcc = parseCacheControl(req.headers['cache-control']); - - // Assume that if someone uses legacy, non-standard uncecessary options they don't understand caching, - // so there's no point stricly adhering to the blindly copy&pasted directives. - if ( - ignoreCargoCult && - 'pre-check' in this._rescc && - 'post-check' in this._rescc - ) { - delete this._rescc['pre-check']; - delete this._rescc['post-check']; - delete this._rescc['no-cache']; - delete this._rescc['no-store']; - delete this._rescc['must-revalidate']; - this._resHeaders = Object.assign({}, this._resHeaders, { - 'cache-control': formatCacheControl(this._rescc), - }); - delete this._resHeaders.expires; - delete this._resHeaders.pragma; - } - - // When the Cache-Control header field is not present in a request, caches MUST consider the no-cache request pragma-directive - // as having the same effect as if "Cache-Control: no-cache" were present (see Section 5.2.1). - if ( - res.headers['cache-control'] == null && - /no-cache/.test(res.headers.pragma) - ) { - this._rescc['no-cache'] = true; - } - } - - now() { - return Date.now(); - } - - storable() { - // The "no-store" request directive indicates that a cache MUST NOT store any part of either this request or any response to it. - return !!( - !this._reqcc['no-store'] && - // A cache MUST NOT store a response to any request, unless: - // The request method is understood by the cache and defined as being cacheable, and - ('GET' === this._method || - 'HEAD' === this._method || - ('POST' === this._method && this._hasExplicitExpiration())) && - // the response status code is understood by the cache, and - understoodStatuses.has(this._status) && - // the "no-store" cache directive does not appear in request or response header fields, and - !this._rescc['no-store'] && - // the "private" response directive does not appear in the response, if the cache is shared, and - (!this._isShared || !this._rescc.private) && - // the Authorization header field does not appear in the request, if the cache is shared, - (!this._isShared || - this._noAuthorization || - this._allowsStoringAuthenticated()) && - // the response either: - // contains an Expires header field, or - (this._resHeaders.expires || - // contains a max-age response directive, or - // contains a s-maxage response directive and the cache is shared, or - // contains a public response directive. - this._rescc['max-age'] || - (this._isShared && this._rescc['s-maxage']) || - this._rescc.public || - // has a status code that is defined as cacheable by default - statusCodeCacheableByDefault.has(this._status)) - ); - } - - _hasExplicitExpiration() { - // 4.2.1 Calculating Freshness Lifetime - return ( - (this._isShared && this._rescc['s-maxage']) || - this._rescc['max-age'] || - this._resHeaders.expires - ); - } - - _assertRequestHasHeaders(req) { - if (!req || !req.headers) { - throw Error('Request headers missing'); - } - } - - satisfiesWithoutRevalidation(req) { - this._assertRequestHasHeaders(req); - - // When presented with a request, a cache MUST NOT reuse a stored response, unless: - // the presented request does not contain the no-cache pragma (Section 5.4), nor the no-cache cache directive, - // unless the stored response is successfully validated (Section 4.3), and - const requestCC = parseCacheControl(req.headers['cache-control']); - if (requestCC['no-cache'] || /no-cache/.test(req.headers.pragma)) { - return false; - } - - if (requestCC['max-age'] && this.age() > requestCC['max-age']) { - return false; - } - - if ( - requestCC['min-fresh'] && - this.timeToLive() < 1000 * requestCC['min-fresh'] - ) { - return false; - } - - // the stored response is either: - // fresh, or allowed to be served stale - if (this.stale()) { - const allowsStale = - requestCC['max-stale'] && - !this._rescc['must-revalidate'] && - (true === requestCC['max-stale'] || - requestCC['max-stale'] > this.age() - this.maxAge()); - if (!allowsStale) { - return false; - } - } - - return this._requestMatches(req, false); - } - - _requestMatches(req, allowHeadMethod) { - // The presented effective request URI and that of the stored response match, and - return ( - (!this._url || this._url === req.url) && - this._host === req.headers.host && - // the request method associated with the stored response allows it to be used for the presented request, and - (!req.method || - this._method === req.method || - (allowHeadMethod && 'HEAD' === req.method)) && - // selecting header fields nominated by the stored response (if any) match those presented, and - this._varyMatches(req) - ); - } - - _allowsStoringAuthenticated() { - // following Cache-Control response directives (Section 5.2.2) have such an effect: must-revalidate, public, and s-maxage. - return ( - this._rescc['must-revalidate'] || - this._rescc.public || - this._rescc['s-maxage'] - ); - } - - _varyMatches(req) { - if (!this._resHeaders.vary) { - return true; - } - - // A Vary header field-value of "*" always fails to match - if (this._resHeaders.vary === '*') { - return false; - } - - const fields = this._resHeaders.vary - .trim() - .toLowerCase() - .split(/\s*,\s*/); - for (const name of fields) { - if (req.headers[name] !== this._reqHeaders[name]) return false; - } - return true; - } - - _copyWithoutHopByHopHeaders(inHeaders) { - const headers = {}; - for (const name in inHeaders) { - if (hopByHopHeaders[name]) continue; - headers[name] = inHeaders[name]; - } - // 9.1. Connection - if (inHeaders.connection) { - const tokens = inHeaders.connection.trim().split(/\s*,\s*/); - for (const name of tokens) { - delete headers[name]; - } - } - if (headers.warning) { - const warnings = headers.warning.split(/,/).filter(warning => { - return !/^\s*1[0-9][0-9]/.test(warning); - }); - if (!warnings.length) { - delete headers.warning; - } else { - headers.warning = warnings.join(',').trim(); - } - } - return headers; - } - - responseHeaders() { - const headers = this._copyWithoutHopByHopHeaders(this._resHeaders); - const age = this.age(); - - // A cache SHOULD generate 113 warning if it heuristically chose a freshness - // lifetime greater than 24 hours and the response's age is greater than 24 hours. - if ( - age > 3600 * 24 && - !this._hasExplicitExpiration() && - this.maxAge() > 3600 * 24 - ) { - headers.warning = - (headers.warning ? `${headers.warning}, ` : '') + - '113 - "rfc7234 5.5.4"'; - } - headers.age = `${Math.round(age)}`; - headers.date = new Date(this.now()).toUTCString(); - return headers; - } - - /** - * Value of the Date response header or current time if Date was invalid - * @return timestamp - */ - date() { - const serverDate = Date.parse(this._resHeaders.date); - if (isFinite(serverDate)) { - return serverDate; - } - return this._responseTime; - } - - /** - * Value of the Age header, in seconds, updated for the current time. - * May be fractional. - * - * @return Number - */ - age() { - let age = this._ageValue(); - - const residentTime = (this.now() - this._responseTime) / 1000; - return age + residentTime; - } - - _ageValue() { - return toNumberOrZero(this._resHeaders.age); - } - - /** - * Value of applicable max-age (or heuristic equivalent) in seconds. This counts since response's `Date`. - * - * For an up-to-date value, see `timeToLive()`. - * - * @return Number - */ - maxAge() { - if (!this.storable() || this._rescc['no-cache']) { - return 0; - } - - // Shared responses with cookies are cacheable according to the RFC, but IMHO it'd be unwise to do so by default - // so this implementation requires explicit opt-in via public header - if ( - this._isShared && - (this._resHeaders['set-cookie'] && - !this._rescc.public && - !this._rescc.immutable) - ) { - return 0; - } - - if (this._resHeaders.vary === '*') { - return 0; - } - - if (this._isShared) { - if (this._rescc['proxy-revalidate']) { - return 0; - } - // if a response includes the s-maxage directive, a shared cache recipient MUST ignore the Expires field. - if (this._rescc['s-maxage']) { - return toNumberOrZero(this._rescc['s-maxage']); - } - } - - // If a response includes a Cache-Control field with the max-age directive, a recipient MUST ignore the Expires field. - if (this._rescc['max-age']) { - return toNumberOrZero(this._rescc['max-age']); - } - - const defaultMinTtl = this._rescc.immutable ? this._immutableMinTtl : 0; - - const serverDate = this.date(); - if (this._resHeaders.expires) { - const expires = Date.parse(this._resHeaders.expires); - // A cache recipient MUST interpret invalid date formats, especially the value "0", as representing a time in the past (i.e., "already expired"). - if (Number.isNaN(expires) || expires < serverDate) { - return 0; - } - return Math.max(defaultMinTtl, (expires - serverDate) / 1000); - } - - if (this._resHeaders['last-modified']) { - const lastModified = Date.parse(this._resHeaders['last-modified']); - if (isFinite(lastModified) && serverDate > lastModified) { - return Math.max( - defaultMinTtl, - ((serverDate - lastModified) / 1000) * this._cacheHeuristic - ); - } - } - - return defaultMinTtl; - } - - timeToLive() { - const age = this.maxAge() - this.age(); - const staleIfErrorAge = age + toNumberOrZero(this._rescc['stale-if-error']); - const staleWhileRevalidateAge = age + toNumberOrZero(this._rescc['stale-while-revalidate']); - return Math.max(0, age, staleIfErrorAge, staleWhileRevalidateAge) * 1000; - } - - stale() { - return this.maxAge() <= this.age(); - } - - _useStaleIfError() { - return this.maxAge() + toNumberOrZero(this._rescc['stale-if-error']) > this.age(); - } - - useStaleWhileRevalidate() { - return this.maxAge() + toNumberOrZero(this._rescc['stale-while-revalidate']) > this.age(); - } - - static fromObject(obj) { - return new this(undefined, undefined, { _fromObject: obj }); - } - - _fromObject(obj) { - if (this._responseTime) throw Error('Reinitialized'); - if (!obj || obj.v !== 1) throw Error('Invalid serialization'); - - this._responseTime = obj.t; - this._isShared = obj.sh; - this._cacheHeuristic = obj.ch; - this._immutableMinTtl = - obj.imm !== undefined ? obj.imm : 24 * 3600 * 1000; - this._status = obj.st; - this._resHeaders = obj.resh; - this._rescc = obj.rescc; - this._method = obj.m; - this._url = obj.u; - this._host = obj.h; - this._noAuthorization = obj.a; - this._reqHeaders = obj.reqh; - this._reqcc = obj.reqcc; - } - - toObject() { - return { - v: 1, - t: this._responseTime, - sh: this._isShared, - ch: this._cacheHeuristic, - imm: this._immutableMinTtl, - st: this._status, - resh: this._resHeaders, - rescc: this._rescc, - m: this._method, - u: this._url, - h: this._host, - a: this._noAuthorization, - reqh: this._reqHeaders, - reqcc: this._reqcc, - }; - } - - /** - * Headers for sending to the origin server to revalidate stale response. - * Allows server to return 304 to allow reuse of the previous response. - * - * Hop by hop headers are always stripped. - * Revalidation headers may be added or removed, depending on request. - */ - revalidationHeaders(incomingReq) { - this._assertRequestHasHeaders(incomingReq); - const headers = this._copyWithoutHopByHopHeaders(incomingReq.headers); - - // This implementation does not understand range requests - delete headers['if-range']; - - if (!this._requestMatches(incomingReq, true) || !this.storable()) { - // revalidation allowed via HEAD - // not for the same resource, or wasn't allowed to be cached anyway - delete headers['if-none-match']; - delete headers['if-modified-since']; - return headers; - } - - /* MUST send that entity-tag in any cache validation request (using If-Match or If-None-Match) if an entity-tag has been provided by the origin server. */ - if (this._resHeaders.etag) { - headers['if-none-match'] = headers['if-none-match'] - ? `${headers['if-none-match']}, ${this._resHeaders.etag}` - : this._resHeaders.etag; - } - - // Clients MAY issue simple (non-subrange) GET requests with either weak validators or strong validators. Clients MUST NOT use weak validators in other forms of request. - const forbidsWeakValidators = - headers['accept-ranges'] || - headers['if-match'] || - headers['if-unmodified-since'] || - (this._method && this._method != 'GET'); - - /* SHOULD send the Last-Modified value in non-subrange cache validation requests (using If-Modified-Since) if only a Last-Modified value has been provided by the origin server. - Note: This implementation does not understand partial responses (206) */ - if (forbidsWeakValidators) { - delete headers['if-modified-since']; - - if (headers['if-none-match']) { - const etags = headers['if-none-match'] - .split(/,/) - .filter(etag => { - return !/^\s*W\//.test(etag); - }); - if (!etags.length) { - delete headers['if-none-match']; - } else { - headers['if-none-match'] = etags.join(',').trim(); - } - } - } else if ( - this._resHeaders['last-modified'] && - !headers['if-modified-since'] - ) { - headers['if-modified-since'] = this._resHeaders['last-modified']; - } - - return headers; - } - - /** - * Creates new CachePolicy with information combined from the previews response, - * and the new revalidation response. - * - * Returns {policy, modified} where modified is a boolean indicating - * whether the response body has been modified, and old cached body can't be used. - * - * @return {Object} {policy: CachePolicy, modified: Boolean} - */ - revalidatedPolicy(request, response) { - this._assertRequestHasHeaders(request); - if(this._useStaleIfError() && isErrorResponse(response)) { // I consider the revalidation request unsuccessful - return { - modified: false, - matches: false, - policy: this, - }; - } - if (!response || !response.headers) { - throw Error('Response headers missing'); - } - - // These aren't going to be supported exactly, since one CachePolicy object - // doesn't know about all the other cached objects. - let matches = false; - if (response.status !== undefined && response.status != 304) { - matches = false; - } else if ( - response.headers.etag && - !/^\s*W\//.test(response.headers.etag) - ) { - // "All of the stored responses with the same strong validator are selected. - // If none of the stored responses contain the same strong validator, - // then the cache MUST NOT use the new response to update any stored responses." - matches = - this._resHeaders.etag && - this._resHeaders.etag.replace(/^\s*W\//, '') === - response.headers.etag; - } else if (this._resHeaders.etag && response.headers.etag) { - // "If the new response contains a weak validator and that validator corresponds - // to one of the cache's stored responses, - // then the most recent of those matching stored responses is selected for update." - matches = - this._resHeaders.etag.replace(/^\s*W\//, '') === - response.headers.etag.replace(/^\s*W\//, ''); - } else if (this._resHeaders['last-modified']) { - matches = - this._resHeaders['last-modified'] === - response.headers['last-modified']; - } else { - // If the new response does not include any form of validator (such as in the case where - // a client generates an If-Modified-Since request from a source other than the Last-Modified - // response header field), and there is only one stored response, and that stored response also - // lacks a validator, then that stored response is selected for update. - if ( - !this._resHeaders.etag && - !this._resHeaders['last-modified'] && - !response.headers.etag && - !response.headers['last-modified'] - ) { - matches = true; - } - } - - if (!matches) { - return { - policy: new this.constructor(request, response), - // Client receiving 304 without body, even if it's invalid/mismatched has no option - // but to reuse a cached body. We don't have a good way to tell clients to do - // error recovery in such case. - modified: response.status != 304, - matches: false, - }; - } - - // use other header fields provided in the 304 (Not Modified) response to replace all instances - // of the corresponding header fields in the stored response. - const headers = {}; - for (const k in this._resHeaders) { - headers[k] = - k in response.headers && !excludedFromRevalidationUpdate[k] - ? response.headers[k] - : this._resHeaders[k]; - } - - const newResponse = Object.assign({}, response, { - status: this._status, - method: this._method, - headers, - }); - return { - policy: new this.constructor(request, newResponse, { - shared: this._isShared, - cacheHeuristic: this._cacheHeuristic, - immutableMinTimeToLive: this._immutableMinTtl, - }), - modified: false, - matches: true, - }; - } -}; - - -/***/ }), - -/***/ 81970: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.HttpProxyAgent = void 0; -const net = __importStar(__nccwpck_require__(69278)); -const tls = __importStar(__nccwpck_require__(64756)); -const debug_1 = __importDefault(__nccwpck_require__(2830)); -const events_1 = __nccwpck_require__(24434); -const agent_base_1 = __nccwpck_require__(98894); -const url_1 = __nccwpck_require__(87016); -const debug = (0, debug_1.default)('http-proxy-agent'); -/** - * The `HttpProxyAgent` implements an HTTP Agent subclass that connects - * to the specified "HTTP proxy server" in order to proxy HTTP requests. - */ -class HttpProxyAgent extends agent_base_1.Agent { - constructor(proxy, opts) { - super(opts); - this.proxy = typeof proxy === 'string' ? new url_1.URL(proxy) : proxy; - this.proxyHeaders = opts?.headers ?? {}; - debug('Creating new HttpProxyAgent instance: %o', this.proxy.href); - // Trim off the brackets from IPv6 addresses - const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, ''); - const port = this.proxy.port - ? parseInt(this.proxy.port, 10) - : this.proxy.protocol === 'https:' - ? 443 - : 80; - this.connectOpts = { - ...(opts ? omit(opts, 'headers') : null), - host, - port, - }; - } - addRequest(req, opts) { - req._header = null; - this.setRequestProps(req, opts); - // @ts-expect-error `addRequest()` isn't defined in `@types/node` - super.addRequest(req, opts); - } - setRequestProps(req, opts) { - const { proxy } = this; - const protocol = opts.secureEndpoint ? 'https:' : 'http:'; - const hostname = req.getHeader('host') || 'localhost'; - const base = `${protocol}//${hostname}`; - const url = new url_1.URL(req.path, base); - if (opts.port !== 80) { - url.port = String(opts.port); - } - // Change the `http.ClientRequest` instance's "path" field - // to the absolute path of the URL that will be requested. - req.path = String(url); - // Inject the `Proxy-Authorization` header if necessary. - const headers = typeof this.proxyHeaders === 'function' - ? this.proxyHeaders() - : { ...this.proxyHeaders }; - if (proxy.username || proxy.password) { - const auth = `${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`; - headers['Proxy-Authorization'] = `Basic ${Buffer.from(auth).toString('base64')}`; - } - if (!headers['Proxy-Connection']) { - headers['Proxy-Connection'] = this.keepAlive - ? 'Keep-Alive' - : 'close'; - } - for (const name of Object.keys(headers)) { - const value = headers[name]; - if (value) { - req.setHeader(name, value); - } - } - } - async connect(req, opts) { - req._header = null; - if (!req.path.includes('://')) { - this.setRequestProps(req, opts); - } - // At this point, the http ClientRequest's internal `_header` field - // might have already been set. If this is the case then we'll need - // to re-generate the string since we just changed the `req.path`. - let first; - let endOfHeaders; - debug('Regenerating stored HTTP header string for request'); - req._implicitHeader(); - if (req.outputData && req.outputData.length > 0) { - debug('Patching connection write() output buffer with updated header'); - first = req.outputData[0].data; - endOfHeaders = first.indexOf('\r\n\r\n') + 4; - req.outputData[0].data = - req._header + first.substring(endOfHeaders); - debug('Output buffer: %o', req.outputData[0].data); - } - // Create a socket connection to the proxy server. - let socket; - if (this.proxy.protocol === 'https:') { - debug('Creating `tls.Socket`: %o', this.connectOpts); - socket = tls.connect(this.connectOpts); - } - else { - debug('Creating `net.Socket`: %o', this.connectOpts); - socket = net.connect(this.connectOpts); - } - // Wait for the socket's `connect` event, so that this `callback()` - // function throws instead of the `http` request machinery. This is - // important for i.e. `PacProxyAgent` which determines a failed proxy - // connection via the `callback()` function throwing. - await (0, events_1.once)(socket, 'connect'); - return socket; - } -} -HttpProxyAgent.protocols = ['http', 'https']; -exports.HttpProxyAgent = HttpProxyAgent; -function omit(obj, ...keys) { - const ret = {}; - let key; - for (key in obj) { - if (!keys.includes(key)) { - ret[key] = obj[key]; - } - } - return ret; -} -//# sourceMappingURL=index.js.map - -/***/ }), - -/***/ 90685: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - -const EventEmitter = __nccwpck_require__(24434); -const tls = __nccwpck_require__(64756); -const http2 = __nccwpck_require__(85675); -const QuickLRU = __nccwpck_require__(15475); - -const kCurrentStreamsCount = Symbol('currentStreamsCount'); -const kRequest = Symbol('request'); -const kOriginSet = Symbol('cachedOriginSet'); -const kGracefullyClosing = Symbol('gracefullyClosing'); - -const nameKeys = [ - // `http2.connect()` options - 'maxDeflateDynamicTableSize', - 'maxSessionMemory', - 'maxHeaderListPairs', - 'maxOutstandingPings', - 'maxReservedRemoteStreams', - 'maxSendHeaderBlockLength', - 'paddingStrategy', - - // `tls.connect()` options - 'localAddress', - 'path', - 'rejectUnauthorized', - 'minDHSize', - - // `tls.createSecureContext()` options - 'ca', - 'cert', - 'clientCertEngine', - 'ciphers', - 'key', - 'pfx', - 'servername', - 'minVersion', - 'maxVersion', - 'secureProtocol', - 'crl', - 'honorCipherOrder', - 'ecdhCurve', - 'dhparam', - 'secureOptions', - 'sessionIdContext' -]; - -const getSortedIndex = (array, value, compare) => { - let low = 0; - let high = array.length; - - while (low < high) { - const mid = (low + high) >>> 1; - - /* istanbul ignore next */ - if (compare(array[mid], value)) { - // This never gets called because we use descending sort. Better to have this anyway. - low = mid + 1; - } else { - high = mid; - } - } - - return low; -}; - -const compareSessions = (a, b) => { - return a.remoteSettings.maxConcurrentStreams > b.remoteSettings.maxConcurrentStreams; -}; - -// See https://tools.ietf.org/html/rfc8336 -const closeCoveredSessions = (where, session) => { - // Clients SHOULD NOT emit new requests on any connection whose Origin - // Set is a proper subset of another connection's Origin Set, and they - // SHOULD close it once all outstanding requests are satisfied. - for (const coveredSession of where) { - if ( - // The set is a proper subset when its length is less than the other set. - coveredSession[kOriginSet].length < session[kOriginSet].length && - - // And the other set includes all elements of the subset. - coveredSession[kOriginSet].every(origin => session[kOriginSet].includes(origin)) && - - // Makes sure that the session can handle all requests from the covered session. - coveredSession[kCurrentStreamsCount] + session[kCurrentStreamsCount] <= session.remoteSettings.maxConcurrentStreams - ) { - // This allows pending requests to finish and prevents making new requests. - gracefullyClose(coveredSession); - } - } -}; - -// This is basically inverted `closeCoveredSessions(...)`. -const closeSessionIfCovered = (where, coveredSession) => { - for (const session of where) { - if ( - coveredSession[kOriginSet].length < session[kOriginSet].length && - coveredSession[kOriginSet].every(origin => session[kOriginSet].includes(origin)) && - coveredSession[kCurrentStreamsCount] + session[kCurrentStreamsCount] <= session.remoteSettings.maxConcurrentStreams - ) { - gracefullyClose(coveredSession); - } - } -}; - -const getSessions = ({agent, isFree}) => { - const result = {}; - - // eslint-disable-next-line guard-for-in - for (const normalizedOptions in agent.sessions) { - const sessions = agent.sessions[normalizedOptions]; - - const filtered = sessions.filter(session => { - const result = session[Agent.kCurrentStreamsCount] < session.remoteSettings.maxConcurrentStreams; - - return isFree ? result : !result; - }); - - if (filtered.length !== 0) { - result[normalizedOptions] = filtered; - } - } - - return result; -}; - -const gracefullyClose = session => { - session[kGracefullyClosing] = true; - - if (session[kCurrentStreamsCount] === 0) { - session.close(); - } -}; - -class Agent extends EventEmitter { - constructor({timeout = 60000, maxSessions = Infinity, maxFreeSessions = 10, maxCachedTlsSessions = 100} = {}) { - super(); - - // A session is considered busy when its current streams count - // is equal to or greater than the `maxConcurrentStreams` value. - - // A session is considered free when its current streams count - // is less than the `maxConcurrentStreams` value. - - // SESSIONS[NORMALIZED_OPTIONS] = []; - this.sessions = {}; - - // The queue for creating new sessions. It looks like this: - // QUEUE[NORMALIZED_OPTIONS][NORMALIZED_ORIGIN] = ENTRY_FUNCTION - // - // The entry function has `listeners`, `completed` and `destroyed` properties. - // `listeners` is an array of objects containing `resolve` and `reject` functions. - // `completed` is a boolean. It's set to true after ENTRY_FUNCTION is executed. - // `destroyed` is a boolean. If it's set to true, the session will be destroyed if hasn't connected yet. - this.queue = {}; - - // Each session will use this timeout value. - this.timeout = timeout; - - // Max sessions in total - this.maxSessions = maxSessions; - - // Max free sessions in total - // TODO: decreasing `maxFreeSessions` should close some sessions - this.maxFreeSessions = maxFreeSessions; - - this._freeSessionsCount = 0; - this._sessionsCount = 0; - - // We don't support push streams by default. - this.settings = { - enablePush: false - }; - - // Reusing TLS sessions increases performance. - this.tlsSessionCache = new QuickLRU({maxSize: maxCachedTlsSessions}); - } - - static normalizeOrigin(url, servername) { - if (typeof url === 'string') { - url = new URL(url); - } - - if (servername && url.hostname !== servername) { - url.hostname = servername; - } - - return url.origin; - } - - normalizeOptions(options) { - let normalized = ''; - - if (options) { - for (const key of nameKeys) { - if (options[key]) { - normalized += `:${options[key]}`; - } - } - } - - return normalized; - } - - _tryToCreateNewSession(normalizedOptions, normalizedOrigin) { - if (!(normalizedOptions in this.queue) || !(normalizedOrigin in this.queue[normalizedOptions])) { - return; - } - - const item = this.queue[normalizedOptions][normalizedOrigin]; - - // The entry function can be run only once. - // BUG: The session may be never created when: - // - the first condition is false AND - // - this function is never called with the same arguments in the future. - if (this._sessionsCount < this.maxSessions && !item.completed) { - item.completed = true; - - item(); - } - } - - getSession(origin, options, listeners) { - return new Promise((resolve, reject) => { - if (Array.isArray(listeners)) { - listeners = [...listeners]; - - // Resolve the current promise ASAP, we're just moving the listeners. - // They will be executed at a different time. - resolve(); - } else { - listeners = [{resolve, reject}]; - } - - const normalizedOptions = this.normalizeOptions(options); - const normalizedOrigin = Agent.normalizeOrigin(origin, options && options.servername); - - if (normalizedOrigin === undefined) { - for (const {reject} of listeners) { - reject(new TypeError('The `origin` argument needs to be a string or an URL object')); - } - - return; - } - - if (normalizedOptions in this.sessions) { - const sessions = this.sessions[normalizedOptions]; - - let maxConcurrentStreams = -1; - let currentStreamsCount = -1; - let optimalSession; - - // We could just do this.sessions[normalizedOptions].find(...) but that isn't optimal. - // Additionally, we are looking for session which has biggest current pending streams count. - for (const session of sessions) { - const sessionMaxConcurrentStreams = session.remoteSettings.maxConcurrentStreams; - - if (sessionMaxConcurrentStreams < maxConcurrentStreams) { - break; - } - - if (session[kOriginSet].includes(normalizedOrigin)) { - const sessionCurrentStreamsCount = session[kCurrentStreamsCount]; - - if ( - sessionCurrentStreamsCount >= sessionMaxConcurrentStreams || - session[kGracefullyClosing] || - // Unfortunately the `close` event isn't called immediately, - // so `session.destroyed` is `true`, but `session.closed` is `false`. - session.destroyed - ) { - continue; - } - - // We only need set this once. - if (!optimalSession) { - maxConcurrentStreams = sessionMaxConcurrentStreams; - } - - // We're looking for the session which has biggest current pending stream count, - // in order to minimalize the amount of active sessions. - if (sessionCurrentStreamsCount > currentStreamsCount) { - optimalSession = session; - currentStreamsCount = sessionCurrentStreamsCount; - } - } - } - - if (optimalSession) { - /* istanbul ignore next: safety check */ - if (listeners.length !== 1) { - for (const {reject} of listeners) { - const error = new Error( - `Expected the length of listeners to be 1, got ${listeners.length}.\n` + - 'Please report this to https://github.com/szmarczak/http2-wrapper/' - ); - - reject(error); - } - - return; - } - - listeners[0].resolve(optimalSession); - return; - } - } - - if (normalizedOptions in this.queue) { - if (normalizedOrigin in this.queue[normalizedOptions]) { - // There's already an item in the queue, just attach ourselves to it. - this.queue[normalizedOptions][normalizedOrigin].listeners.push(...listeners); - - // This shouldn't be executed here. - // See the comment inside _tryToCreateNewSession. - this._tryToCreateNewSession(normalizedOptions, normalizedOrigin); - return; - } - } else { - this.queue[normalizedOptions] = {}; - } - - // The entry must be removed from the queue IMMEDIATELY when: - // 1. the session connects successfully, - // 2. an error occurs. - const removeFromQueue = () => { - // Our entry can be replaced. We cannot remove the new one. - if (normalizedOptions in this.queue && this.queue[normalizedOptions][normalizedOrigin] === entry) { - delete this.queue[normalizedOptions][normalizedOrigin]; - - if (Object.keys(this.queue[normalizedOptions]).length === 0) { - delete this.queue[normalizedOptions]; - } - } - }; - - // The main logic is here - const entry = () => { - const name = `${normalizedOrigin}:${normalizedOptions}`; - let receivedSettings = false; - - try { - const session = http2.connect(origin, { - createConnection: this.createConnection, - settings: this.settings, - session: this.tlsSessionCache.get(name), - ...options - }); - session[kCurrentStreamsCount] = 0; - session[kGracefullyClosing] = false; - - const isFree = () => session[kCurrentStreamsCount] < session.remoteSettings.maxConcurrentStreams; - let wasFree = true; - - session.socket.once('session', tlsSession => { - this.tlsSessionCache.set(name, tlsSession); - }); - - session.once('error', error => { - // Listeners are empty when the session successfully connected. - for (const {reject} of listeners) { - reject(error); - } - - // The connection got broken, purge the cache. - this.tlsSessionCache.delete(name); - }); - - session.setTimeout(this.timeout, () => { - // Terminates all streams owned by this session. - // TODO: Maybe the streams should have a "Session timed out" error? - session.destroy(); - }); - - session.once('close', () => { - if (receivedSettings) { - // 1. If it wasn't free then no need to decrease because - // it has been decreased already in session.request(). - // 2. `stream.once('close')` won't increment the count - // because the session is already closed. - if (wasFree) { - this._freeSessionsCount--; - } - - this._sessionsCount--; - - // This cannot be moved to the stream logic, - // because there may be a session that hadn't made a single request. - const where = this.sessions[normalizedOptions]; - where.splice(where.indexOf(session), 1); - - if (where.length === 0) { - delete this.sessions[normalizedOptions]; - } - } else { - // Broken connection - const error = new Error('Session closed without receiving a SETTINGS frame'); - error.code = 'HTTP2WRAPPER_NOSETTINGS'; - - for (const {reject} of listeners) { - reject(error); - } - - removeFromQueue(); - } - - // There may be another session awaiting. - this._tryToCreateNewSession(normalizedOptions, normalizedOrigin); - }); - - // Iterates over the queue and processes listeners. - const processListeners = () => { - if (!(normalizedOptions in this.queue) || !isFree()) { - return; - } - - for (const origin of session[kOriginSet]) { - if (origin in this.queue[normalizedOptions]) { - const {listeners} = this.queue[normalizedOptions][origin]; - - // Prevents session overloading. - while (listeners.length !== 0 && isFree()) { - // We assume `resolve(...)` calls `request(...)` *directly*, - // otherwise the session will get overloaded. - listeners.shift().resolve(session); - } - - const where = this.queue[normalizedOptions]; - if (where[origin].listeners.length === 0) { - delete where[origin]; - - if (Object.keys(where).length === 0) { - delete this.queue[normalizedOptions]; - break; - } - } - - // We're no longer free, no point in continuing. - if (!isFree()) { - break; - } - } - } - }; - - // The Origin Set cannot shrink. No need to check if it suddenly became covered by another one. - session.on('origin', () => { - session[kOriginSet] = session.originSet; - - if (!isFree()) { - // The session is full. - return; - } - - processListeners(); - - // Close covered sessions (if possible). - closeCoveredSessions(this.sessions[normalizedOptions], session); - }); - - session.once('remoteSettings', () => { - // Fix Node.js bug preventing the process from exiting - session.ref(); - session.unref(); - - this._sessionsCount++; - - // The Agent could have been destroyed already. - if (entry.destroyed) { - const error = new Error('Agent has been destroyed'); - - for (const listener of listeners) { - listener.reject(error); - } - - session.destroy(); - return; - } - - session[kOriginSet] = session.originSet; - - { - const where = this.sessions; - - if (normalizedOptions in where) { - const sessions = where[normalizedOptions]; - sessions.splice(getSortedIndex(sessions, session, compareSessions), 0, session); - } else { - where[normalizedOptions] = [session]; - } - } - - this._freeSessionsCount += 1; - receivedSettings = true; - - this.emit('session', session); - - processListeners(); - removeFromQueue(); - - // TODO: Close last recently used (or least used?) session - if (session[kCurrentStreamsCount] === 0 && this._freeSessionsCount > this.maxFreeSessions) { - session.close(); - } - - // Check if we haven't managed to execute all listeners. - if (listeners.length !== 0) { - // Request for a new session with predefined listeners. - this.getSession(normalizedOrigin, options, listeners); - listeners.length = 0; - } - - // `session.remoteSettings.maxConcurrentStreams` might get increased - session.on('remoteSettings', () => { - processListeners(); - - // In case the Origin Set changes - closeCoveredSessions(this.sessions[normalizedOptions], session); - }); - }); - - // Shim `session.request()` in order to catch all streams - session[kRequest] = session.request; - session.request = (headers, streamOptions) => { - if (session[kGracefullyClosing]) { - throw new Error('The session is gracefully closing. No new streams are allowed.'); - } - - const stream = session[kRequest](headers, streamOptions); - - // The process won't exit until the session is closed or all requests are gone. - session.ref(); - - ++session[kCurrentStreamsCount]; - - if (session[kCurrentStreamsCount] === session.remoteSettings.maxConcurrentStreams) { - this._freeSessionsCount--; - } - - stream.once('close', () => { - wasFree = isFree(); - - --session[kCurrentStreamsCount]; - - if (!session.destroyed && !session.closed) { - closeSessionIfCovered(this.sessions[normalizedOptions], session); - - if (isFree() && !session.closed) { - if (!wasFree) { - this._freeSessionsCount++; - - wasFree = true; - } - - const isEmpty = session[kCurrentStreamsCount] === 0; - - if (isEmpty) { - session.unref(); - } - - if ( - isEmpty && - ( - this._freeSessionsCount > this.maxFreeSessions || - session[kGracefullyClosing] - ) - ) { - session.close(); - } else { - closeCoveredSessions(this.sessions[normalizedOptions], session); - processListeners(); - } - } - } - }); - - return stream; - }; - } catch (error) { - for (const listener of listeners) { - listener.reject(error); - } - - removeFromQueue(); - } - }; - - entry.listeners = listeners; - entry.completed = false; - entry.destroyed = false; - - this.queue[normalizedOptions][normalizedOrigin] = entry; - this._tryToCreateNewSession(normalizedOptions, normalizedOrigin); - }); - } - - request(origin, options, headers, streamOptions) { - return new Promise((resolve, reject) => { - this.getSession(origin, options, [{ - reject, - resolve: session => { - try { - resolve(session.request(headers, streamOptions)); - } catch (error) { - reject(error); - } - } - }]); - }); - } - - createConnection(origin, options) { - return Agent.connect(origin, options); - } - - static connect(origin, options) { - options.ALPNProtocols = ['h2']; - - const port = origin.port || 443; - const host = origin.hostname || origin.host; - - if (typeof options.servername === 'undefined') { - options.servername = host; - } - - return tls.connect(port, host, options); - } - - closeFreeSessions() { - for (const sessions of Object.values(this.sessions)) { - for (const session of sessions) { - if (session[kCurrentStreamsCount] === 0) { - session.close(); - } - } - } - } - - destroy(reason) { - for (const sessions of Object.values(this.sessions)) { - for (const session of sessions) { - session.destroy(reason); - } - } - - for (const entriesOfAuthority of Object.values(this.queue)) { - for (const entry of Object.values(entriesOfAuthority)) { - entry.destroyed = true; - } - } - - // New requests should NOT attach to destroyed sessions - this.queue = {}; - } - - get freeSessions() { - return getSessions({agent: this, isFree: true}); - } - - get busySessions() { - return getSessions({agent: this, isFree: false}); - } -} - -Agent.kCurrentStreamsCount = kCurrentStreamsCount; -Agent.kGracefullyClosing = kGracefullyClosing; - -module.exports = { - Agent, - globalAgent: new Agent() -}; - - -/***/ }), - -/***/ 99213: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - -const http = __nccwpck_require__(58611); -const https = __nccwpck_require__(65692); -const resolveALPN = __nccwpck_require__(78824); -const QuickLRU = __nccwpck_require__(15475); -const Http2ClientRequest = __nccwpck_require__(57605); -const calculateServerName = __nccwpck_require__(32850); -const urlToOptions = __nccwpck_require__(74734); - -const cache = new QuickLRU({maxSize: 100}); -const queue = new Map(); - -const installSocket = (agent, socket, options) => { - socket._httpMessage = {shouldKeepAlive: true}; - - const onFree = () => { - agent.emit('free', socket, options); - }; - - socket.on('free', onFree); - - const onClose = () => { - agent.removeSocket(socket, options); - }; - - socket.on('close', onClose); - - const onRemove = () => { - agent.removeSocket(socket, options); - socket.off('close', onClose); - socket.off('free', onFree); - socket.off('agentRemove', onRemove); - }; - - socket.on('agentRemove', onRemove); - - agent.emit('free', socket, options); -}; - -const resolveProtocol = async options => { - const name = `${options.host}:${options.port}:${options.ALPNProtocols.sort()}`; - - if (!cache.has(name)) { - if (queue.has(name)) { - const result = await queue.get(name); - return result.alpnProtocol; - } - - const {path, agent} = options; - options.path = options.socketPath; - - const resultPromise = resolveALPN(options); - queue.set(name, resultPromise); - - try { - const {socket, alpnProtocol} = await resultPromise; - cache.set(name, alpnProtocol); - - options.path = path; - - if (alpnProtocol === 'h2') { - // https://github.com/nodejs/node/issues/33343 - socket.destroy(); - } else { - const {globalAgent} = https; - const defaultCreateConnection = https.Agent.prototype.createConnection; - - if (agent) { - if (agent.createConnection === defaultCreateConnection) { - installSocket(agent, socket, options); - } else { - socket.destroy(); - } - } else if (globalAgent.createConnection === defaultCreateConnection) { - installSocket(globalAgent, socket, options); - } else { - socket.destroy(); - } - } - - queue.delete(name); - - return alpnProtocol; - } catch (error) { - queue.delete(name); - - throw error; - } - } - - return cache.get(name); -}; - -module.exports = async (input, options, callback) => { - if (typeof input === 'string' || input instanceof URL) { - input = urlToOptions(new URL(input)); - } - - if (typeof options === 'function') { - callback = options; - options = undefined; - } - - options = { - ALPNProtocols: ['h2', 'http/1.1'], - ...input, - ...options, - resolveSocket: true - }; - - if (!Array.isArray(options.ALPNProtocols) || options.ALPNProtocols.length === 0) { - throw new Error('The `ALPNProtocols` option must be an Array with at least one entry'); - } - - options.protocol = options.protocol || 'https:'; - const isHttps = options.protocol === 'https:'; - - options.host = options.hostname || options.host || 'localhost'; - options.session = options.tlsSession; - options.servername = options.servername || calculateServerName(options); - options.port = options.port || (isHttps ? 443 : 80); - options._defaultAgent = isHttps ? https.globalAgent : http.globalAgent; - - const agents = options.agent; - - if (agents) { - if (agents.addRequest) { - throw new Error('The `options.agent` object can contain only `http`, `https` or `http2` properties'); - } - - options.agent = agents[isHttps ? 'https' : 'http']; - } - - if (isHttps) { - const protocol = await resolveProtocol(options); - - if (protocol === 'h2') { - if (agents) { - options.agent = agents.http2; - } - - return new Http2ClientRequest(options, callback); - } - } - - return http.request(options, callback); -}; - -module.exports.protocolCache = cache; - - -/***/ }), - -/***/ 57605: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - -const http2 = __nccwpck_require__(85675); -const {Writable} = __nccwpck_require__(2203); -const {Agent, globalAgent} = __nccwpck_require__(90685); -const IncomingMessage = __nccwpck_require__(62156); -const urlToOptions = __nccwpck_require__(74734); -const proxyEvents = __nccwpck_require__(70118); -const isRequestPseudoHeader = __nccwpck_require__(46365); -const { - ERR_INVALID_ARG_TYPE, - ERR_INVALID_PROTOCOL, - ERR_HTTP_HEADERS_SENT, - ERR_INVALID_HTTP_TOKEN, - ERR_HTTP_INVALID_HEADER_VALUE, - ERR_INVALID_CHAR -} = __nccwpck_require__(39731); - -const { - HTTP2_HEADER_STATUS, - HTTP2_HEADER_METHOD, - HTTP2_HEADER_PATH, - HTTP2_METHOD_CONNECT -} = http2.constants; - -const kHeaders = Symbol('headers'); -const kOrigin = Symbol('origin'); -const kSession = Symbol('session'); -const kOptions = Symbol('options'); -const kFlushedHeaders = Symbol('flushedHeaders'); -const kJobs = Symbol('jobs'); - -const isValidHttpToken = /^[\^`\-\w!#$%&*+.|~]+$/; -const isInvalidHeaderValue = /[^\t\u0020-\u007E\u0080-\u00FF]/; - -class ClientRequest extends Writable { - constructor(input, options, callback) { - super({ - autoDestroy: false - }); - - const hasInput = typeof input === 'string' || input instanceof URL; - if (hasInput) { - input = urlToOptions(input instanceof URL ? input : new URL(input)); - } - - if (typeof options === 'function' || options === undefined) { - // (options, callback) - callback = options; - options = hasInput ? input : {...input}; - } else { - // (input, options, callback) - options = {...input, ...options}; - } - - if (options.h2session) { - this[kSession] = options.h2session; - } else if (options.agent === false) { - this.agent = new Agent({maxFreeSessions: 0}); - } else if (typeof options.agent === 'undefined' || options.agent === null) { - if (typeof options.createConnection === 'function') { - // This is a workaround - we don't have to create the session on our own. - this.agent = new Agent({maxFreeSessions: 0}); - this.agent.createConnection = options.createConnection; - } else { - this.agent = globalAgent; - } - } else if (typeof options.agent.request === 'function') { - this.agent = options.agent; - } else { - throw new ERR_INVALID_ARG_TYPE('options.agent', ['Agent-like Object', 'undefined', 'false'], options.agent); - } - - if (options.protocol && options.protocol !== 'https:') { - throw new ERR_INVALID_PROTOCOL(options.protocol, 'https:'); - } - - const port = options.port || options.defaultPort || (this.agent && this.agent.defaultPort) || 443; - const host = options.hostname || options.host || 'localhost'; - - // Don't enforce the origin via options. It may be changed in an Agent. - delete options.hostname; - delete options.host; - delete options.port; - - const {timeout} = options; - options.timeout = undefined; - - this[kHeaders] = Object.create(null); - this[kJobs] = []; - - this.socket = null; - this.connection = null; - - this.method = options.method || 'GET'; - this.path = options.path; - - this.res = null; - this.aborted = false; - this.reusedSocket = false; - - if (options.headers) { - for (const [header, value] of Object.entries(options.headers)) { - this.setHeader(header, value); - } - } - - if (options.auth && !('authorization' in this[kHeaders])) { - this[kHeaders].authorization = 'Basic ' + Buffer.from(options.auth).toString('base64'); - } - - options.session = options.tlsSession; - options.path = options.socketPath; - - this[kOptions] = options; - - // Clients that generate HTTP/2 requests directly SHOULD use the :authority pseudo-header field instead of the Host header field. - if (port === 443) { - this[kOrigin] = `https://${host}`; - - if (!(':authority' in this[kHeaders])) { - this[kHeaders][':authority'] = host; - } - } else { - this[kOrigin] = `https://${host}:${port}`; - - if (!(':authority' in this[kHeaders])) { - this[kHeaders][':authority'] = `${host}:${port}`; - } - } - - if (timeout) { - this.setTimeout(timeout); - } - - if (callback) { - this.once('response', callback); - } - - this[kFlushedHeaders] = false; - } - - get method() { - return this[kHeaders][HTTP2_HEADER_METHOD]; - } - - set method(value) { - if (value) { - this[kHeaders][HTTP2_HEADER_METHOD] = value.toUpperCase(); - } - } - - get path() { - return this[kHeaders][HTTP2_HEADER_PATH]; - } - - set path(value) { - if (value) { - this[kHeaders][HTTP2_HEADER_PATH] = value; - } - } - - get _mustNotHaveABody() { - return this.method === 'GET' || this.method === 'HEAD' || this.method === 'DELETE'; - } - - _write(chunk, encoding, callback) { - // https://github.com/nodejs/node/blob/654df09ae0c5e17d1b52a900a545f0664d8c7627/lib/internal/http2/util.js#L148-L156 - if (this._mustNotHaveABody) { - callback(new Error('The GET, HEAD and DELETE methods must NOT have a body')); - /* istanbul ignore next: Node.js 12 throws directly */ - return; - } - - this.flushHeaders(); - - const callWrite = () => this._request.write(chunk, encoding, callback); - if (this._request) { - callWrite(); - } else { - this[kJobs].push(callWrite); - } - } - - _final(callback) { - if (this.destroyed) { - return; - } - - this.flushHeaders(); - - const callEnd = () => { - // For GET, HEAD and DELETE - if (this._mustNotHaveABody) { - callback(); - return; - } - - this._request.end(callback); - }; - - if (this._request) { - callEnd(); - } else { - this[kJobs].push(callEnd); - } - } - - abort() { - if (this.res && this.res.complete) { - return; - } - - if (!this.aborted) { - process.nextTick(() => this.emit('abort')); - } - - this.aborted = true; - - this.destroy(); - } - - _destroy(error, callback) { - if (this.res) { - this.res._dump(); - } - - if (this._request) { - this._request.destroy(); - } - - callback(error); - } - - async flushHeaders() { - if (this[kFlushedHeaders] || this.destroyed) { - return; - } - - this[kFlushedHeaders] = true; - - const isConnectMethod = this.method === HTTP2_METHOD_CONNECT; - - // The real magic is here - const onStream = stream => { - this._request = stream; - - if (this.destroyed) { - stream.destroy(); - return; - } - - // Forwards `timeout`, `continue`, `close` and `error` events to this instance. - if (!isConnectMethod) { - proxyEvents(stream, this, ['timeout', 'continue', 'close', 'error']); - } - - // Wait for the `finish` event. We don't want to emit the `response` event - // before `request.end()` is called. - const waitForEnd = fn => { - return (...args) => { - if (!this.writable && !this.destroyed) { - fn(...args); - } else { - this.once('finish', () => { - fn(...args); - }); - } - }; - }; - - // This event tells we are ready to listen for the data. - stream.once('response', waitForEnd((headers, flags, rawHeaders) => { - // If we were to emit raw request stream, it would be as fast as the native approach. - // Note that wrapping the raw stream in a Proxy instance won't improve the performance (already tested it). - const response = new IncomingMessage(this.socket, stream.readableHighWaterMark); - this.res = response; - - response.req = this; - response.statusCode = headers[HTTP2_HEADER_STATUS]; - response.headers = headers; - response.rawHeaders = rawHeaders; - - response.once('end', () => { - if (this.aborted) { - response.aborted = true; - response.emit('aborted'); - } else { - response.complete = true; - - // Has no effect, just be consistent with the Node.js behavior - response.socket = null; - response.connection = null; - } - }); - - if (isConnectMethod) { - response.upgrade = true; - - // The HTTP1 API says the socket is detached here, - // but we can't do that so we pass the original HTTP2 request. - if (this.emit('connect', response, stream, Buffer.alloc(0))) { - this.emit('close'); - } else { - // No listeners attached, destroy the original request. - stream.destroy(); - } - } else { - // Forwards data - stream.on('data', chunk => { - if (!response._dumped && !response.push(chunk)) { - stream.pause(); - } - }); - - stream.once('end', () => { - response.push(null); - }); - - if (!this.emit('response', response)) { - // No listeners attached, dump the response. - response._dump(); - } - } - })); - - // Emits `information` event - stream.once('headers', waitForEnd( - headers => this.emit('information', {statusCode: headers[HTTP2_HEADER_STATUS]}) - )); - - stream.once('trailers', waitForEnd((trailers, flags, rawTrailers) => { - const {res} = this; - - // Assigns trailers to the response object. - res.trailers = trailers; - res.rawTrailers = rawTrailers; - })); - - const {socket} = stream.session; - this.socket = socket; - this.connection = socket; - - for (const job of this[kJobs]) { - job(); - } - - this.emit('socket', this.socket); - }; - - // Makes a HTTP2 request - if (this[kSession]) { - try { - onStream(this[kSession].request(this[kHeaders])); - } catch (error) { - this.emit('error', error); - } - } else { - this.reusedSocket = true; - - try { - onStream(await this.agent.request(this[kOrigin], this[kOptions], this[kHeaders])); - } catch (error) { - this.emit('error', error); - } - } - } - - getHeader(name) { - if (typeof name !== 'string') { - throw new ERR_INVALID_ARG_TYPE('name', 'string', name); - } - - return this[kHeaders][name.toLowerCase()]; - } - - get headersSent() { - return this[kFlushedHeaders]; - } - - removeHeader(name) { - if (typeof name !== 'string') { - throw new ERR_INVALID_ARG_TYPE('name', 'string', name); - } - - if (this.headersSent) { - throw new ERR_HTTP_HEADERS_SENT('remove'); - } - - delete this[kHeaders][name.toLowerCase()]; - } - - setHeader(name, value) { - if (this.headersSent) { - throw new ERR_HTTP_HEADERS_SENT('set'); - } - - if (typeof name !== 'string' || (!isValidHttpToken.test(name) && !isRequestPseudoHeader(name))) { - throw new ERR_INVALID_HTTP_TOKEN('Header name', name); - } - - if (typeof value === 'undefined') { - throw new ERR_HTTP_INVALID_HEADER_VALUE(value, name); - } - - if (isInvalidHeaderValue.test(value)) { - throw new ERR_INVALID_CHAR('header content', name); - } - - this[kHeaders][name.toLowerCase()] = value; - } - - setNoDelay() { - // HTTP2 sockets cannot be malformed, do nothing. - } - - setSocketKeepAlive() { - // HTTP2 sockets cannot be malformed, do nothing. - } - - setTimeout(ms, callback) { - const applyTimeout = () => this._request.setTimeout(ms, callback); - - if (this._request) { - applyTimeout(); - } else { - this[kJobs].push(applyTimeout); - } - - return this; - } + if (opts.capture === true) opts.wrap = true; + step = step || opts.step || 1; - get maxHeadersCount() { - if (!this.destroyed && this._request) { - return this._request.session.localSettings.maxHeaderListSize; - } + if (!isNumber(step)) { + if (step != null && !isObject(step)) return invalidStep(step, opts); + return fill(start, end, 1, step); + } - return undefined; - } + if (isNumber(start) && isNumber(end)) { + return fillNumbers(start, end, step, opts); + } - set maxHeadersCount(_value) { - // Updating HTTP2 settings would affect all requests, do nothing. - } -} + return fillLetters(start, end, Math.max(Math.abs(step), 1), opts); +}; -module.exports = ClientRequest; +module.exports = fill; /***/ }), -/***/ 62156: +/***/ 60199: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const {Readable} = __nccwpck_require__(2203); - -class IncomingMessage extends Readable { - constructor(socket, highWaterMark) { - super({ - highWaterMark, - autoDestroy: false - }); - - this.statusCode = null; - this.statusMessage = ''; - this.httpVersion = '2.0'; - this.httpVersionMajor = 2; - this.httpVersionMinor = 0; - this.headers = {}; - this.trailers = {}; - this.req = null; - this.aborted = false; - this.complete = false; - this.upgrade = null; - - this.rawHeaders = []; - this.rawTrailers = []; +const fs = __nccwpck_require__(79896); +const micromatch = __nccwpck_require__(98785); +const path = __nccwpck_require__(16928); - this.socket = socket; - this.connection = socket; +module.exports = findWorkspaceRoot; - this._dumped = false; - } +/** + * Adapted from: + * https://github.com/yarnpkg/yarn/blob/ddf2f9ade211195372236c2f39a75b00fa18d4de/src/config.js#L612 + * @param {string} [initial] + * @return {string|null} + */ +function findWorkspaceRoot(initial) { + if (!initial) { + initial = process.cwd(); + } + let previous = null; + let current = path.normalize(initial); - _destroy(error) { - this.req._request.destroy(error); - } + do { + const manifest = readPackageJSON(current); + const workspaces = extractWorkspaces(manifest); - setTimeout(ms, callback) { - this.req.setTimeout(ms, callback); - return this; - } + if (workspaces) { + const relativePath = path.relative(current, initial); + if (relativePath === '' || micromatch([relativePath], workspaces).length > 0) { + return current; + } else { + return null; + } + } - _dump() { - if (!this._dumped) { - this._dumped = true; + previous = current; + current = path.dirname(current); + } while (current !== previous); - this.removeAllListeners('data'); - this.resume(); - } - } + return null; +} - _read() { - if (this.req) { - this.req._request.resume(); - } - } +function extractWorkspaces(manifest) { + const workspaces = (manifest || {}).workspaces; + return (workspaces && workspaces.packages) || (Array.isArray(workspaces) ? workspaces : null); } -module.exports = IncomingMessage; +function readPackageJSON(dir) { + const file = path.join(dir, 'package.json'); + if (fs.existsSync(file)) { + return JSON.parse(fs.readFileSync(file, 'utf8')); + } + return null; +} /***/ }), -/***/ 14956: +/***/ 39707: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -const http2 = __nccwpck_require__(85675); -const agent = __nccwpck_require__(90685); -const ClientRequest = __nccwpck_require__(57605); -const IncomingMessage = __nccwpck_require__(62156); -const auto = __nccwpck_require__(99213); - -const request = (url, options, callback) => { - return new ClientRequest(url, options, callback); -}; - -const get = (url, options, callback) => { - // eslint-disable-next-line unicorn/prevent-abbreviations - const req = new ClientRequest(url, options, callback); - req.end(); - - return req; -}; - -module.exports = { - ...http2, - ClientRequest, - IncomingMessage, - ...agent, - request, - get, - auto -}; - - -/***/ }), - -/***/ 32850: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +const fs = __nccwpck_require__(79896); +const path = __nccwpck_require__(16928); +const crypto = __nccwpck_require__(76982); +const isStream = __nccwpck_require__(96543); -"use strict"; +const {Worker} = (() => { + try { + return __nccwpck_require__(28167); + } catch (_) { + return {}; + } +})(); -const net = __nccwpck_require__(69278); -/* istanbul ignore file: https://github.com/nodejs/node/blob/v13.0.1/lib/_http_agent.js */ +let worker; // Lazy +let taskIdCounter = 0; +const tasks = new Map(); -module.exports = options => { - let servername = options.host; - const hostHeader = options.headers && options.headers.host; +const recreateWorkerError = sourceError => { + const error = new Error(sourceError.message); - if (hostHeader) { - if (hostHeader.startsWith('[')) { - const index = hostHeader.indexOf(']'); - if (index === -1) { - servername = hostHeader; - } else { - servername = hostHeader.slice(1, -1); - } - } else { - servername = hostHeader.split(':', 1)[0]; + for (const [key, value] of Object.entries(sourceError)) { + if (key !== 'message') { + error[key] = value; } } - if (net.isIP(servername)) { - return ''; - } - - return servername; + return error; }; +const createWorker = () => { + worker = new Worker(__nccwpck_require__.ab + "thread.js"); -/***/ }), - -/***/ 39731: -/***/ ((module) => { - -"use strict"; + worker.on('message', message => { + const task = tasks.get(message.id); + tasks.delete(message.id); -/* istanbul ignore file: https://github.com/nodejs/node/blob/master/lib/internal/errors.js */ + if (tasks.size === 0) { + worker.unref(); + } -const makeError = (Base, key, getMessage) => { - module.exports[key] = class NodeError extends Base { - constructor(...args) { - super(typeof getMessage === 'string' ? getMessage : getMessage(args)); - this.name = `${super.name} [${key}]`; - this.code = key; + if (message.error === undefined) { + task.resolve(message.value); + } else { + task.reject(recreateWorkerError(message.error)); } - }; -}; + }); -makeError(TypeError, 'ERR_INVALID_ARG_TYPE', args => { - const type = args[0].includes('.') ? 'property' : 'argument'; + worker.on('error', error => { + // Any error here is effectively an equivalent of segfault, and have no scope, so we just throw it on callback level + throw error; + }); +}; - let valid = args[1]; - const isManyTypes = Array.isArray(valid); +const taskWorker = (method, args, transferList) => new Promise((resolve, reject) => { + const id = taskIdCounter++; + tasks.set(id, {resolve, reject}); - if (isManyTypes) { - valid = `${valid.slice(0, -1).join(', ')} or ${valid.slice(-1)}`; + if (worker === undefined) { + createWorker(); } - return `The "${args[0]}" ${type} must be ${isManyTypes ? 'one of' : 'of'} type ${valid}. Received ${typeof args[2]}`; -}); - -makeError(TypeError, 'ERR_INVALID_PROTOCOL', args => { - return `Protocol "${args[0]}" not supported. Expected "${args[1]}"`; + worker.ref(); + worker.postMessage({id, method, args}, transferList); }); -makeError(Error, 'ERR_HTTP_HEADERS_SENT', args => { - return `Cannot ${args[0]} headers after they are sent to the client`; -}); +const hasha = (input, options = {}) => { + let outputEncoding = options.encoding || 'hex'; -makeError(TypeError, 'ERR_INVALID_HTTP_TOKEN', args => { - return `${args[0]} must be a valid HTTP token [${args[1]}]`; -}); + if (outputEncoding === 'buffer') { + outputEncoding = undefined; + } -makeError(TypeError, 'ERR_HTTP_INVALID_HEADER_VALUE', args => { - return `Invalid value "${args[0]} for header "${args[1]}"`; -}); + const hash = crypto.createHash(options.algorithm || 'sha512'); -makeError(TypeError, 'ERR_INVALID_CHAR', args => { - return `Invalid character in ${args[0]} [${args[1]}]`; -}); + const update = buffer => { + const inputEncoding = typeof buffer === 'string' ? 'utf8' : undefined; + hash.update(buffer, inputEncoding); + }; + if (Array.isArray(input)) { + input.forEach(update); + } else { + update(input); + } -/***/ }), + return hash.digest(outputEncoding); +}; -/***/ 46365: -/***/ ((module) => { +hasha.stream = (options = {}) => { + let outputEncoding = options.encoding || 'hex'; -"use strict"; + if (outputEncoding === 'buffer') { + outputEncoding = undefined; + } + const stream = crypto.createHash(options.algorithm || 'sha512'); + stream.setEncoding(outputEncoding); + return stream; +}; -module.exports = header => { - switch (header) { - case ':method': - case ':scheme': - case ':authority': - case ':path': - return true; - default: - return false; +hasha.fromStream = async (stream, options = {}) => { + if (!isStream(stream)) { + throw new TypeError('Expected a stream'); } + + return new Promise((resolve, reject) => { + // TODO: Use `stream.pipeline` and `stream.finished` when targeting Node.js 10 + stream + .on('error', reject) + .pipe(hasha.stream(options)) + .on('error', reject) + .on('finish', function () { + resolve(this.read()); + }); + }); }; +if (Worker === undefined) { + hasha.fromFile = async (filePath, options) => hasha.fromStream(fs.createReadStream(filePath), options); + hasha.async = async (input, options) => hasha(input, options); +} else { + hasha.fromFile = async (filePath, {algorithm = 'sha512', encoding = 'hex'} = {}) => { + const hash = await taskWorker('hashFile', [algorithm, filePath]); -/***/ }), + if (encoding === 'buffer') { + return Buffer.from(hash); + } -/***/ 70118: -/***/ ((module) => { + return Buffer.from(hash).toString(encoding); + }; -"use strict"; + hasha.async = async (input, {algorithm = 'sha512', encoding = 'hex'} = {}) => { + if (encoding === 'buffer') { + encoding = undefined; + } + const hash = await taskWorker('hash', [algorithm, input]); -module.exports = (from, to, events) => { - for (const event of events) { - from.on(event, (...args) => to.emit(event, ...args)); - } -}; + if (encoding === undefined) { + return Buffer.from(hash); + } + return Buffer.from(hash).toString(encoding); + }; +} -/***/ }), +hasha.fromFileSync = (filePath, options) => hasha(fs.readFileSync(filePath), options); -/***/ 74734: -/***/ ((module) => { +module.exports = hasha; -"use strict"; -/* istanbul ignore file: https://github.com/nodejs/node/blob/a91293d4d9ab403046ab5eb022332e4e3d249bd3/lib/internal/url.js#L1257 */ - -module.exports = url => { - const options = { - protocol: url.protocol, - hostname: typeof url.hostname === 'string' && url.hostname.startsWith('[') ? url.hostname.slice(1, -1) : url.hostname, - host: url.host, - hash: url.hash, - search: url.search, - pathname: url.pathname, - href: url.href, - path: `${url.pathname || ''}${url.search || ''}` - }; +/***/ }), - if (typeof url.port === 'string' && url.port.length !== 0) { - options.port = Number(url.port); - } +/***/ 81970: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - if (url.username || url.password) { - options.auth = `${url.username || ''}:${url.password || ''}`; - } +"use strict"; - return options; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; }; - +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HttpProxyAgent = void 0; +const net = __importStar(__nccwpck_require__(69278)); +const tls = __importStar(__nccwpck_require__(64756)); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const events_1 = __nccwpck_require__(24434); +const agent_base_1 = __nccwpck_require__(98894); +const url_1 = __nccwpck_require__(87016); +const debug = (0, debug_1.default)('http-proxy-agent'); +/** + * The `HttpProxyAgent` implements an HTTP Agent subclass that connects + * to the specified "HTTP proxy server" in order to proxy HTTP requests. + */ +class HttpProxyAgent extends agent_base_1.Agent { + constructor(proxy, opts) { + super(opts); + this.proxy = typeof proxy === 'string' ? new url_1.URL(proxy) : proxy; + this.proxyHeaders = opts?.headers ?? {}; + debug('Creating new HttpProxyAgent instance: %o', this.proxy.href); + // Trim off the brackets from IPv6 addresses + const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, ''); + const port = this.proxy.port + ? parseInt(this.proxy.port, 10) + : this.proxy.protocol === 'https:' + ? 443 + : 80; + this.connectOpts = { + ...(opts ? omit(opts, 'headers') : null), + host, + port, + }; + } + addRequest(req, opts) { + req._header = null; + this.setRequestProps(req, opts); + // @ts-expect-error `addRequest()` isn't defined in `@types/node` + super.addRequest(req, opts); + } + setRequestProps(req, opts) { + const { proxy } = this; + const protocol = opts.secureEndpoint ? 'https:' : 'http:'; + const hostname = req.getHeader('host') || 'localhost'; + const base = `${protocol}//${hostname}`; + const url = new url_1.URL(req.path, base); + if (opts.port !== 80) { + url.port = String(opts.port); + } + // Change the `http.ClientRequest` instance's "path" field + // to the absolute path of the URL that will be requested. + req.path = String(url); + // Inject the `Proxy-Authorization` header if necessary. + const headers = typeof this.proxyHeaders === 'function' + ? this.proxyHeaders() + : { ...this.proxyHeaders }; + if (proxy.username || proxy.password) { + const auth = `${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`; + headers['Proxy-Authorization'] = `Basic ${Buffer.from(auth).toString('base64')}`; + } + if (!headers['Proxy-Connection']) { + headers['Proxy-Connection'] = this.keepAlive + ? 'Keep-Alive' + : 'close'; + } + for (const name of Object.keys(headers)) { + const value = headers[name]; + if (value) { + req.setHeader(name, value); + } + } + } + async connect(req, opts) { + req._header = null; + if (!req.path.includes('://')) { + this.setRequestProps(req, opts); + } + // At this point, the http ClientRequest's internal `_header` field + // might have already been set. If this is the case then we'll need + // to re-generate the string since we just changed the `req.path`. + let first; + let endOfHeaders; + debug('Regenerating stored HTTP header string for request'); + req._implicitHeader(); + if (req.outputData && req.outputData.length > 0) { + debug('Patching connection write() output buffer with updated header'); + first = req.outputData[0].data; + endOfHeaders = first.indexOf('\r\n\r\n') + 4; + req.outputData[0].data = + req._header + first.substring(endOfHeaders); + debug('Output buffer: %o', req.outputData[0].data); + } + // Create a socket connection to the proxy server. + let socket; + if (this.proxy.protocol === 'https:') { + debug('Creating `tls.Socket`: %o', this.connectOpts); + socket = tls.connect(this.connectOpts); + } + else { + debug('Creating `net.Socket`: %o', this.connectOpts); + socket = net.connect(this.connectOpts); + } + // Wait for the socket's `connect` event, so that this `callback()` + // function throws instead of the `http` request machinery. This is + // important for i.e. `PacProxyAgent` which determines a failed proxy + // connection via the `callback()` function throwing. + await (0, events_1.once)(socket, 'connect'); + return socket; + } +} +HttpProxyAgent.protocols = ['http', 'https']; +exports.HttpProxyAgent = HttpProxyAgent; +function omit(obj, ...keys) { + const ret = {}; + let key; + for (key in obj) { + if (!keys.includes(key)) { + ret[key] = obj[key]; + } + } + return ret; +} +//# sourceMappingURL=index.js.map /***/ }), @@ -24416,356 +17637,6 @@ isStream.transform = stream => module.exports = isStream; -/***/ }), - -/***/ 5563: -/***/ ((__unused_webpack_module, exports) => { - -//TODO: handle reviver/dehydrate function like normal -//and handle indentation, like normal. -//if anyone needs this... please send pull request. - -exports.stringify = function stringify (o) { - if('undefined' == typeof o) return o - - if(o && Buffer.isBuffer(o)) - return JSON.stringify(':base64:' + o.toString('base64')) - - if(o && o.toJSON) - o = o.toJSON() - - if(o && 'object' === typeof o) { - var s = '' - var array = Array.isArray(o) - s = array ? '[' : '{' - var first = true - - for(var k in o) { - var ignore = 'function' == typeof o[k] || (!array && 'undefined' === typeof o[k]) - if(Object.hasOwnProperty.call(o, k) && !ignore) { - if(!first) - s += ',' - first = false - if (array) { - if(o[k] == undefined) - s += 'null' - else - s += stringify(o[k]) - } else if (o[k] !== void(0)) { - s += stringify(k) + ':' + stringify(o[k]) - } - } - } - - s += array ? ']' : '}' - - return s - } else if ('string' === typeof o) { - return JSON.stringify(/^:/.test(o) ? ':' + o : o) - } else if ('undefined' === typeof o) { - return 'null'; - } else - return JSON.stringify(o) -} - -exports.parse = function (s) { - return JSON.parse(s, function (key, value) { - if('string' === typeof value) { - if(/^:base64:/.test(value)) - return Buffer.from(value.substring(8), 'base64') - else - return /^:/.test(value) ? value.substring(1) : value - } - return value - }) -} - - -/***/ }), - -/***/ 76018: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const EventEmitter = __nccwpck_require__(24434); -const JSONB = __nccwpck_require__(5563); - -const loadStore = options => { - const adapters = { - redis: '@keyv/redis', - rediss: '@keyv/redis', - mongodb: '@keyv/mongo', - mongo: '@keyv/mongo', - sqlite: '@keyv/sqlite', - postgresql: '@keyv/postgres', - postgres: '@keyv/postgres', - mysql: '@keyv/mysql', - etcd: '@keyv/etcd', - offline: '@keyv/offline', - tiered: '@keyv/tiered', - }; - if (options.adapter || options.uri) { - const adapter = options.adapter || /^[^:+]*/.exec(options.uri)[0]; - return new (require(adapters[adapter]))(options); - } - - return new Map(); -}; - -const iterableAdapters = [ - 'sqlite', - 'postgres', - 'mysql', - 'mongo', - 'redis', - 'tiered', -]; - -class Keyv extends EventEmitter { - constructor(uri, {emitErrors = true, ...options} = {}) { - super(); - this.opts = { - namespace: 'keyv', - serialize: JSONB.stringify, - deserialize: JSONB.parse, - ...((typeof uri === 'string') ? {uri} : uri), - ...options, - }; - - if (!this.opts.store) { - const adapterOptions = {...this.opts}; - this.opts.store = loadStore(adapterOptions); - } - - if (this.opts.compression) { - const compression = this.opts.compression; - this.opts.serialize = compression.serialize.bind(compression); - this.opts.deserialize = compression.deserialize.bind(compression); - } - - if (typeof this.opts.store.on === 'function' && emitErrors) { - this.opts.store.on('error', error => this.emit('error', error)); - } - - this.opts.store.namespace = this.opts.namespace; - - const generateIterator = iterator => async function * () { - for await (const [key, raw] of typeof iterator === 'function' - ? iterator(this.opts.store.namespace) - : iterator) { - const data = await this.opts.deserialize(raw); - if (this.opts.store.namespace && !key.includes(this.opts.store.namespace)) { - continue; - } - - if (typeof data.expires === 'number' && Date.now() > data.expires) { - this.delete(key); - continue; - } - - yield [this._getKeyUnprefix(key), data.value]; - } - }; - - // Attach iterators - if (typeof this.opts.store[Symbol.iterator] === 'function' && this.opts.store instanceof Map) { - this.iterator = generateIterator(this.opts.store); - } else if (typeof this.opts.store.iterator === 'function' && this.opts.store.opts - && this._checkIterableAdaptar()) { - this.iterator = generateIterator(this.opts.store.iterator.bind(this.opts.store)); - } - } - - _checkIterableAdaptar() { - return iterableAdapters.includes(this.opts.store.opts.dialect) - || iterableAdapters.findIndex(element => this.opts.store.opts.url.includes(element)) >= 0; - } - - _getKeyPrefix(key) { - return `${this.opts.namespace}:${key}`; - } - - _getKeyPrefixArray(keys) { - return keys.map(key => `${this.opts.namespace}:${key}`); - } - - _getKeyUnprefix(key) { - return key - .split(':') - .splice(1) - .join(':'); - } - - get(key, options) { - const {store} = this.opts; - const isArray = Array.isArray(key); - const keyPrefixed = isArray ? this._getKeyPrefixArray(key) : this._getKeyPrefix(key); - if (isArray && store.getMany === undefined) { - const promises = []; - for (const key of keyPrefixed) { - promises.push(Promise.resolve() - .then(() => store.get(key)) - .then(data => (typeof data === 'string') ? this.opts.deserialize(data) : (this.opts.compression ? this.opts.deserialize(data) : data)) - .then(data => { - if (data === undefined || data === null) { - return undefined; - } - - if (typeof data.expires === 'number' && Date.now() > data.expires) { - return this.delete(key).then(() => undefined); - } - - return (options && options.raw) ? data : data.value; - }), - ); - } - - return Promise.allSettled(promises) - .then(values => { - const data = []; - for (const value of values) { - data.push(value.value); - } - - return data; - }); - } - - return Promise.resolve() - .then(() => isArray ? store.getMany(keyPrefixed) : store.get(keyPrefixed)) - .then(data => (typeof data === 'string') ? this.opts.deserialize(data) : (this.opts.compression ? this.opts.deserialize(data) : data)) - .then(data => { - if (data === undefined || data === null) { - return undefined; - } - - if (isArray) { - return data.map((row, index) => { - if ((typeof row === 'string')) { - row = this.opts.deserialize(row); - } - - if (row === undefined || row === null) { - return undefined; - } - - if (typeof row.expires === 'number' && Date.now() > row.expires) { - this.delete(key[index]).then(() => undefined); - return undefined; - } - - return (options && options.raw) ? row : row.value; - }); - } - - if (typeof data.expires === 'number' && Date.now() > data.expires) { - return this.delete(key).then(() => undefined); - } - - return (options && options.raw) ? data : data.value; - }); - } - - set(key, value, ttl) { - const keyPrefixed = this._getKeyPrefix(key); - if (typeof ttl === 'undefined') { - ttl = this.opts.ttl; - } - - if (ttl === 0) { - ttl = undefined; - } - - const {store} = this.opts; - - return Promise.resolve() - .then(() => { - const expires = (typeof ttl === 'number') ? (Date.now() + ttl) : null; - if (typeof value === 'symbol') { - this.emit('error', 'symbol cannot be serialized'); - } - - value = {value, expires}; - return this.opts.serialize(value); - }) - .then(value => store.set(keyPrefixed, value, ttl)) - .then(() => true); - } - - delete(key) { - const {store} = this.opts; - if (Array.isArray(key)) { - const keyPrefixed = this._getKeyPrefixArray(key); - if (store.deleteMany === undefined) { - const promises = []; - for (const key of keyPrefixed) { - promises.push(store.delete(key)); - } - - return Promise.allSettled(promises) - .then(values => values.every(x => x.value === true)); - } - - return Promise.resolve() - .then(() => store.deleteMany(keyPrefixed)); - } - - const keyPrefixed = this._getKeyPrefix(key); - return Promise.resolve() - .then(() => store.delete(keyPrefixed)); - } - - clear() { - const {store} = this.opts; - return Promise.resolve() - .then(() => store.clear()); - } - - has(key) { - const keyPrefixed = this._getKeyPrefix(key); - const {store} = this.opts; - return Promise.resolve() - .then(async () => { - if (typeof store.has === 'function') { - return store.has(keyPrefixed); - } - - const value = await store.get(keyPrefixed); - return value !== undefined; - }); - } - - disconnect() { - const {store} = this.opts; - if (typeof store.disconnect === 'function') { - return store.disconnect(); - } - } -} - -module.exports = Keyv; - - -/***/ }), - -/***/ 11364: -/***/ ((module) => { - -"use strict"; - -module.exports = object => { - const result = {}; - - for (const [key, value] of Object.entries(object)) { - result[key.toLowerCase()] = value; - } - - return result; -}; - - /***/ }), /***/ 98785: @@ -25248,46 +18119,6 @@ micromatch.hasBraces = hasBraces; module.exports = micromatch; -/***/ }), - -/***/ 69991: -/***/ ((module) => { - -"use strict"; - - -// We define these manually to ensure they're always copied -// even if they would move up the prototype chain -// https://nodejs.org/api/http.html#http_class_http_incomingmessage -const knownProps = [ - 'destroy', - 'setTimeout', - 'socket', - 'headers', - 'trailers', - 'rawHeaders', - 'statusCode', - 'httpVersion', - 'httpVersionMinor', - 'httpVersionMajor', - 'rawTrailers', - 'statusMessage' -]; - -module.exports = (fromStream, toStream) => { - const fromProps = new Set(Object.keys(fromStream).concat(knownProps)); - - for (const prop of fromProps) { - // Don't overwrite existing properties - if (prop in toStream) { - continue; - } - - toStream[prop] = typeof fromStream[prop] === 'function' ? fromStream[prop].bind(fromStream) : fromStream[prop]; - } -}; - - /***/ }), /***/ 43772: @@ -26469,398 +19300,6 @@ function plural(ms, msAbs, n, name) { } -/***/ }), - -/***/ 7827: -/***/ ((module) => { - -"use strict"; - - -// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs -const DATA_URL_DEFAULT_MIME_TYPE = 'text/plain'; -const DATA_URL_DEFAULT_CHARSET = 'us-ascii'; - -const testParameter = (name, filters) => { - return filters.some(filter => filter instanceof RegExp ? filter.test(name) : filter === name); -}; - -const normalizeDataURL = (urlString, {stripHash}) => { - const match = /^data:(?[^,]*?),(?[^#]*?)(?:#(?.*))?$/.exec(urlString); - - if (!match) { - throw new Error(`Invalid URL: ${urlString}`); - } - - let {type, data, hash} = match.groups; - const mediaType = type.split(';'); - hash = stripHash ? '' : hash; - - let isBase64 = false; - if (mediaType[mediaType.length - 1] === 'base64') { - mediaType.pop(); - isBase64 = true; - } - - // Lowercase MIME type - const mimeType = (mediaType.shift() || '').toLowerCase(); - const attributes = mediaType - .map(attribute => { - let [key, value = ''] = attribute.split('=').map(string => string.trim()); - - // Lowercase `charset` - if (key === 'charset') { - value = value.toLowerCase(); - - if (value === DATA_URL_DEFAULT_CHARSET) { - return ''; - } - } - - return `${key}${value ? `=${value}` : ''}`; - }) - .filter(Boolean); - - const normalizedMediaType = [ - ...attributes - ]; - - if (isBase64) { - normalizedMediaType.push('base64'); - } - - if (normalizedMediaType.length !== 0 || (mimeType && mimeType !== DATA_URL_DEFAULT_MIME_TYPE)) { - normalizedMediaType.unshift(mimeType); - } - - return `data:${normalizedMediaType.join(';')},${isBase64 ? data.trim() : data}${hash ? `#${hash}` : ''}`; -}; - -const normalizeUrl = (urlString, options) => { - options = { - defaultProtocol: 'http:', - normalizeProtocol: true, - forceHttp: false, - forceHttps: false, - stripAuthentication: true, - stripHash: false, - stripTextFragment: true, - stripWWW: true, - removeQueryParameters: [/^utm_\w+/i], - removeTrailingSlash: true, - removeSingleSlash: true, - removeDirectoryIndex: false, - sortQueryParameters: true, - ...options - }; - - urlString = urlString.trim(); - - // Data URL - if (/^data:/i.test(urlString)) { - return normalizeDataURL(urlString, options); - } - - if (/^view-source:/i.test(urlString)) { - throw new Error('`view-source:` is not supported as it is a non-standard protocol'); - } - - const hasRelativeProtocol = urlString.startsWith('//'); - const isRelativeUrl = !hasRelativeProtocol && /^\.*\//.test(urlString); - - // Prepend protocol - if (!isRelativeUrl) { - urlString = urlString.replace(/^(?!(?:\w+:)?\/\/)|^\/\//, options.defaultProtocol); - } - - const urlObj = new URL(urlString); - - if (options.forceHttp && options.forceHttps) { - throw new Error('The `forceHttp` and `forceHttps` options cannot be used together'); - } - - if (options.forceHttp && urlObj.protocol === 'https:') { - urlObj.protocol = 'http:'; - } - - if (options.forceHttps && urlObj.protocol === 'http:') { - urlObj.protocol = 'https:'; - } - - // Remove auth - if (options.stripAuthentication) { - urlObj.username = ''; - urlObj.password = ''; - } - - // Remove hash - if (options.stripHash) { - urlObj.hash = ''; - } else if (options.stripTextFragment) { - urlObj.hash = urlObj.hash.replace(/#?:~:text.*?$/i, ''); - } - - // Remove duplicate slashes if not preceded by a protocol - if (urlObj.pathname) { - urlObj.pathname = urlObj.pathname.replace(/(? 0) { - let pathComponents = urlObj.pathname.split('/'); - const lastComponent = pathComponents[pathComponents.length - 1]; - - if (testParameter(lastComponent, options.removeDirectoryIndex)) { - pathComponents = pathComponents.slice(0, pathComponents.length - 1); - urlObj.pathname = pathComponents.slice(1).join('/') + '/'; - } - } - - if (urlObj.hostname) { - // Remove trailing dot - urlObj.hostname = urlObj.hostname.replace(/\.$/, ''); - - // Remove `www.` - if (options.stripWWW && /^www\.(?!www\.)(?:[a-z\-\d]{1,63})\.(?:[a-z.\-\d]{2,63})$/.test(urlObj.hostname)) { - // Each label should be max 63 at length (min: 1). - // Source: https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names - // Each TLD should be up to 63 characters long (min: 2). - // It is technically possible to have a single character TLD, but none currently exist. - urlObj.hostname = urlObj.hostname.replace(/^www\./, ''); - } - } - - // Remove query unwanted parameters - if (Array.isArray(options.removeQueryParameters)) { - for (const key of [...urlObj.searchParams.keys()]) { - if (testParameter(key, options.removeQueryParameters)) { - urlObj.searchParams.delete(key); - } - } - } - - if (options.removeQueryParameters === true) { - urlObj.search = ''; - } - - // Sort query parameters - if (options.sortQueryParameters) { - urlObj.searchParams.sort(); - } - - if (options.removeTrailingSlash) { - urlObj.pathname = urlObj.pathname.replace(/\/$/, ''); - } - - const oldUrlString = urlString; - - // Take advantage of many of the Node `url` normalizations - urlString = urlObj.toString(); - - if (!options.removeSingleSlash && urlObj.pathname === '/' && !oldUrlString.endsWith('/') && urlObj.hash === '') { - urlString = urlString.replace(/\/$/, ''); - } - - // Remove ending `/` unless removeSingleSlash is false - if ((options.removeTrailingSlash || urlObj.pathname === '/') && urlObj.hash === '' && options.removeSingleSlash) { - urlString = urlString.replace(/\/$/, ''); - } - - // Restore relative protocol, if applicable - if (hasRelativeProtocol && !options.normalizeProtocol) { - urlString = urlString.replace(/^http:\/\//, '//'); - } - - // Remove http/https - if (options.stripProtocol) { - urlString = urlString.replace(/^(?:https?:)?\/\//, ''); - } - - return urlString; -}; - -module.exports = normalizeUrl; - - -/***/ }), - -/***/ 55560: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -var wrappy = __nccwpck_require__(58264) -module.exports = wrappy(once) -module.exports.strict = wrappy(onceStrict) - -once.proto = once(function () { - Object.defineProperty(Function.prototype, 'once', { - value: function () { - return once(this) - }, - configurable: true - }) - - Object.defineProperty(Function.prototype, 'onceStrict', { - value: function () { - return onceStrict(this) - }, - configurable: true - }) -}) - -function once (fn) { - var f = function () { - if (f.called) return f.value - f.called = true - return f.value = fn.apply(this, arguments) - } - f.called = false - return f -} - -function onceStrict (fn) { - var f = function () { - if (f.called) - throw new Error(f.onceError) - f.called = true - return f.value = fn.apply(this, arguments) - } - var name = fn.name || 'Function wrapped with `once`' - f.onceError = name + " shouldn't be called more than once" - f.called = false - return f -} - - -/***/ }), - -/***/ 84533: -/***/ ((module) => { - -"use strict"; - - -class CancelError extends Error { - constructor(reason) { - super(reason || 'Promise was canceled'); - this.name = 'CancelError'; - } - - get isCanceled() { - return true; - } -} - -class PCancelable { - static fn(userFn) { - return (...arguments_) => { - return new PCancelable((resolve, reject, onCancel) => { - arguments_.push(onCancel); - // eslint-disable-next-line promise/prefer-await-to-then - userFn(...arguments_).then(resolve, reject); - }); - }; - } - - constructor(executor) { - this._cancelHandlers = []; - this._isPending = true; - this._isCanceled = false; - this._rejectOnCancel = true; - - this._promise = new Promise((resolve, reject) => { - this._reject = reject; - - const onResolve = value => { - if (!this._isCanceled || !onCancel.shouldReject) { - this._isPending = false; - resolve(value); - } - }; - - const onReject = error => { - this._isPending = false; - reject(error); - }; - - const onCancel = handler => { - if (!this._isPending) { - throw new Error('The `onCancel` handler was attached after the promise settled.'); - } - - this._cancelHandlers.push(handler); - }; - - Object.defineProperties(onCancel, { - shouldReject: { - get: () => this._rejectOnCancel, - set: boolean => { - this._rejectOnCancel = boolean; - } - } - }); - - return executor(onResolve, onReject, onCancel); - }); - } - - then(onFulfilled, onRejected) { - // eslint-disable-next-line promise/prefer-await-to-then - return this._promise.then(onFulfilled, onRejected); - } - - catch(onRejected) { - return this._promise.catch(onRejected); - } - - finally(onFinally) { - return this._promise.finally(onFinally); - } - - cancel(reason) { - if (!this._isPending || this._isCanceled) { - return; - } - - this._isCanceled = true; - - if (this._cancelHandlers.length > 0) { - try { - for (const handler of this._cancelHandlers) { - handler(); - } - } catch (error) { - this._reject(error); - return; - } - } - - if (this._rejectOnCancel) { - this._reject(new CancelError(reason)); - } - } - - get isCanceled() { - return this._isCanceled; - } -} - -Object.setPrototypeOf(PCancelable.prototype, Promise.prototype); - -module.exports = PCancelable; -module.exports.CancelError = CancelError; - - /***/ }), /***/ 14006: @@ -29285,230 +21724,6 @@ exports.wrapOutput = (input, state = {}, options = {}) => { }; -/***/ }), - -/***/ 87898: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -var once = __nccwpck_require__(55560) -var eos = __nccwpck_require__(31424) -var fs - -try { - fs = __nccwpck_require__(79896) // we only need fs to get the ReadStream and WriteStream prototypes -} catch (e) {} - -var noop = function () {} -var ancient = /^v?\.0/.test(process.version) - -var isFn = function (fn) { - return typeof fn === 'function' -} - -var isFS = function (stream) { - if (!ancient) return false // newer node version do not need to care about fs is a special way - if (!fs) return false // browser - return (stream instanceof (fs.ReadStream || noop) || stream instanceof (fs.WriteStream || noop)) && isFn(stream.close) -} - -var isRequest = function (stream) { - return stream.setHeader && isFn(stream.abort) -} - -var destroyer = function (stream, reading, writing, callback) { - callback = once(callback) - - var closed = false - stream.on('close', function () { - closed = true - }) - - eos(stream, {readable: reading, writable: writing}, function (err) { - if (err) return callback(err) - closed = true - callback() - }) - - var destroyed = false - return function (err) { - if (closed) return - if (destroyed) return - destroyed = true - - if (isFS(stream)) return stream.close(noop) // use close for fs streams to avoid fd leaks - if (isRequest(stream)) return stream.abort() // request.destroy just do .end - .abort is what we want - - if (isFn(stream.destroy)) return stream.destroy() - - callback(err || new Error('stream was destroyed')) - } -} - -var call = function (fn) { - fn() -} - -var pipe = function (from, to) { - return from.pipe(to) -} - -var pump = function () { - var streams = Array.prototype.slice.call(arguments) - var callback = isFn(streams[streams.length - 1] || noop) && streams.pop() || noop - - if (Array.isArray(streams[0])) streams = streams[0] - if (streams.length < 2) throw new Error('pump requires two streams per minimum') - - var error - var destroys = streams.map(function (stream, i) { - var reading = i < streams.length - 1 - var writing = i > 0 - return destroyer(stream, reading, writing, function (err) { - if (!error) error = err - if (err) destroys.forEach(call) - if (reading) return - destroys.forEach(call) - callback(error) - }) - }) - - return streams.reduce(pipe) -} - -module.exports = pump - - -/***/ }), - -/***/ 15475: -/***/ ((module) => { - -"use strict"; - - -class QuickLRU { - constructor(options = {}) { - if (!(options.maxSize && options.maxSize > 0)) { - throw new TypeError('`maxSize` must be a number greater than 0'); - } - - this.maxSize = options.maxSize; - this.onEviction = options.onEviction; - this.cache = new Map(); - this.oldCache = new Map(); - this._size = 0; - } - - _set(key, value) { - this.cache.set(key, value); - this._size++; - - if (this._size >= this.maxSize) { - this._size = 0; - - if (typeof this.onEviction === 'function') { - for (const [key, value] of this.oldCache.entries()) { - this.onEviction(key, value); - } - } - - this.oldCache = this.cache; - this.cache = new Map(); - } - } - - get(key) { - if (this.cache.has(key)) { - return this.cache.get(key); - } - - if (this.oldCache.has(key)) { - const value = this.oldCache.get(key); - this.oldCache.delete(key); - this._set(key, value); - return value; - } - } - - set(key, value) { - if (this.cache.has(key)) { - this.cache.set(key, value); - } else { - this._set(key, value); - } - - return this; - } - - has(key) { - return this.cache.has(key) || this.oldCache.has(key); - } - - peek(key) { - if (this.cache.has(key)) { - return this.cache.get(key); - } - - if (this.oldCache.has(key)) { - return this.oldCache.get(key); - } - } - - delete(key) { - const deleted = this.cache.delete(key); - if (deleted) { - this._size--; - } - - return this.oldCache.delete(key) || deleted; - } - - clear() { - this.cache.clear(); - this.oldCache.clear(); - this._size = 0; - } - - * keys() { - for (const [key] of this) { - yield key; - } - } - - * values() { - for (const [, value] of this) { - yield value; - } - } - - * [Symbol.iterator]() { - for (const item of this.cache) { - yield item; - } - - for (const item of this.oldCache) { - const [key] = item; - if (!this.cache.has(key)) { - yield item; - } - } - } - - get size() { - let oldCacheSize = 0; - for (const key of this.oldCache.keys()) { - if (!this.cache.has(key)) { - oldCacheSize++; - } - } - - return Math.min(this._size + oldCacheSize, this.maxSize); - } -} - -module.exports = QuickLRU; - - /***/ }), /***/ 71820: @@ -29560,99 +21775,6 @@ module.exports = quote; return module.exports;}); -/***/ }), - -/***/ 78824: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - -const tls = __nccwpck_require__(64756); - -module.exports = (options = {}, connect = tls.connect) => new Promise((resolve, reject) => { - let timeout = false; - - let socket; - - const callback = async () => { - await socketPromise; - - socket.off('timeout', onTimeout); - socket.off('error', reject); - - if (options.resolveSocket) { - resolve({alpnProtocol: socket.alpnProtocol, socket, timeout}); - - if (timeout) { - await Promise.resolve(); - socket.emit('timeout'); - } - } else { - socket.destroy(); - resolve({alpnProtocol: socket.alpnProtocol, timeout}); - } - }; - - const onTimeout = async () => { - timeout = true; - callback(); - }; - - const socketPromise = (async () => { - try { - socket = await connect(options, callback); - - socket.on('error', reject); - socket.once('timeout', onTimeout); - } catch (error) { - reject(error); - } - })(); -}); - - -/***/ }), - -/***/ 74145: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -"use strict"; - - -const Readable = (__nccwpck_require__(2203).Readable); -const lowercaseKeys = __nccwpck_require__(11364); - -class Response extends Readable { - constructor(statusCode, headers, body, url) { - if (typeof statusCode !== 'number') { - throw new TypeError('Argument `statusCode` should be a number'); - } - if (typeof headers !== 'object') { - throw new TypeError('Argument `headers` should be an object'); - } - if (!(body instanceof Buffer)) { - throw new TypeError('Argument `body` should be a buffer'); - } - if (typeof url !== 'string') { - throw new TypeError('Argument `url` should be a string'); - } - - super(); - this.statusCode = statusCode; - this.headers = lowercaseKeys(headers); - this.body = body; - this.url = url; - } - - _read() { - this.push(this.body); - this.push(null); - } -} - -module.exports = Response; - - /***/ }), /***/ 39318: @@ -60147,46 +52269,6 @@ module.exports = { } -/***/ }), - -/***/ 58264: -/***/ ((module) => { - -// Returns a wrapper function that returns a wrapped callback -// The wrapper function should do some stuff, and return a -// presumably different callback function. -// This makes sure that own properties are retained, so that -// decorations and such are not lost along the way. -module.exports = wrappy -function wrappy (fn, cb) { - if (fn && cb) return wrappy(fn)(cb) - - if (typeof fn !== 'function') - throw new TypeError('need wrapper function') - - Object.keys(fn).forEach(function (k) { - wrapper[k] = fn[k] - }) - - return wrapper - - function wrapper() { - var args = new Array(arguments.length) - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i] - } - var ret = fn.apply(this, args) - var cb = args[args.length-1] - if (typeof ret === 'function' && ret !== cb) { - Object.keys(cb).forEach(function (k) { - ret[k] = cb[k] - }) - } - return ret - } -} - - /***/ }), /***/ 42613: @@ -60221,14 +52303,6 @@ module.exports = require("crypto"); /***/ }), -/***/ 72250: -/***/ ((module) => { - -"use strict"; -module.exports = require("dns"); - -/***/ }), - /***/ 24434: /***/ ((module) => { @@ -60253,14 +52327,6 @@ module.exports = require("http"); /***/ }), -/***/ 85675: -/***/ ((module) => { - -"use strict"; -module.exports = require("http2"); - -/***/ }), - /***/ 65692: /***/ ((module) => { @@ -60421,6 +52487,14 @@ module.exports = require("node:stream"); /***/ }), +/***/ 58500: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:timers/promises"); + +/***/ }), + /***/ 41692: /***/ ((module) => { @@ -60549,14 +52623,6 @@ module.exports = require("worker_threads"); /***/ }), -/***/ 43106: -/***/ ((module) => { - -"use strict"; -module.exports = require("zlib"); - -/***/ }), - /***/ 50198: /***/ ((__unused_webpack_module, exports) => { @@ -100625,7 +92691,6 @@ __webpack_unused_export__ = defaultContentType /***/ 48102: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const got = __nccwpck_require__(46757) const debug = __nccwpck_require__(2830)('@cypress/github-action') /** @@ -100633,11 +92698,14 @@ const debug = __nccwpck_require__(2830)('@cypress/github-action') * a poor man's https://www.npmjs.com/package/wait-on. This version * is implemented using https://github.com/sindresorhus/got */ -const ping = (url, timeout) => { +const ping = async (url, timeout) => { if (!timeout) { throw new Error('Expected timeout in ms') } + // got@16 is ESM-only; dynamic import works from CommonJS + const { default: got } = await __nccwpck_require__.e(/* import() */ 849).then(__nccwpck_require__.bind(__nccwpck_require__, 20849)) + // make copy of the error codes that "got" retries on const errorCodes = [...got.defaults.options.retry.errorCodes] errorCodes.push('ESOCKETTIMEDOUT') @@ -100661,9 +92729,14 @@ const ping = (url, timeout) => { headers: { Accept: 'text/html, application/json, text/plain, */*' }, - timeout: individualPingTimeout, - errorCodes, + timeout: { + request: individualPingTimeout + }, retry: { + errorCodes, + // enforceRetryRules:false lets calculateDelay be the sole stop condition, + // matching got@11 behaviour. limit is a generous failsafe only. + enforceRetryRules: false, limit, calculateDelay({ error, attemptCount }) { if (error) { @@ -100676,10 +92749,9 @@ const ping = (url, timeout) => { ) if (elapsed > timeout) { console.error( - '%s timed out on retry %d of %d, elapsed %dms, limit %dms', + '%s timed out after %d retries, elapsed %dms, limit %dms', url, attemptCount, - limit, elapsed, timeout ) @@ -102054,6 +94126,9 @@ module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"5. /******/ return module.exports; /******/ } /******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __nccwpck_require__.m = __webpack_modules__; +/******/ /************************************************************************/ /******/ /* webpack/runtime/asset-relocator-loader */ /******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; @@ -102070,6 +94145,28 @@ module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"5. /******/ }; /******/ })(); /******/ +/******/ /* webpack/runtime/ensure chunk */ +/******/ (() => { +/******/ __nccwpck_require__.f = {}; +/******/ // This file contains only the entry chunk. +/******/ // The chunk loading function for additional chunks +/******/ __nccwpck_require__.e = (chunkId) => { +/******/ return Promise.all(Object.keys(__nccwpck_require__.f).reduce((promises, key) => { +/******/ __nccwpck_require__.f[key](chunkId, promises); +/******/ return promises; +/******/ }, [])); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/get javascript chunk filename */ +/******/ (() => { +/******/ // This function allow to reference async chunks +/******/ __nccwpck_require__.u = (chunkId) => { +/******/ // return url for filenames based on template +/******/ return "" + chunkId + ".index.js"; +/******/ }; +/******/ })(); +/******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __nccwpck_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) @@ -102086,6 +94183,48 @@ module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"5. /******/ }; /******/ })(); /******/ +/******/ /* webpack/runtime/require chunk loading */ +/******/ (() => { +/******/ // no baseURI +/******/ +/******/ // object to store loaded chunks +/******/ // "1" means "loaded", otherwise not loaded yet +/******/ var installedChunks = { +/******/ 792: 1 +/******/ }; +/******/ +/******/ // no on chunks loaded +/******/ +/******/ var installChunk = (chunk) => { +/******/ var moreModules = chunk.modules, chunkIds = chunk.ids, runtime = chunk.runtime; +/******/ for(var moduleId in moreModules) { +/******/ if(__nccwpck_require__.o(moreModules, moduleId)) { +/******/ __nccwpck_require__.m[moduleId] = moreModules[moduleId]; +/******/ } +/******/ } +/******/ if(runtime) runtime(__nccwpck_require__); +/******/ for(var i = 0; i < chunkIds.length; i++) +/******/ installedChunks[chunkIds[i]] = 1; +/******/ +/******/ }; +/******/ +/******/ // require() chunk loading for javascript +/******/ __nccwpck_require__.f.require = (chunkId, promises) => { +/******/ // "1" is the signal for "already loaded" +/******/ if(!installedChunks[chunkId]) { +/******/ if(true) { // all chunks have JS +/******/ installChunk(require("./" + __nccwpck_require__.u(chunkId))); +/******/ } else installedChunks[chunkId] = 1; +/******/ } +/******/ }; +/******/ +/******/ // no external install chunk +/******/ +/******/ // no HMR +/******/ +/******/ // no HMR manifest +/******/ })(); +/******/ /************************************************************************/ var __webpack_exports__ = {}; // @ts-check diff --git a/package-lock.json b/package-lock.json index d1f99eb7b..5d8f3326b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "argument-vector": "1.0.2", "debug": "4.4.3", "find-yarn-workspace-root": "2.0.0", - "got": "11.8.6", + "got": "16.0.0", "hasha": "5.2.2", "quote": "0.4.0", "supports-color": "9.3.1" @@ -629,6 +629,12 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@keyv/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", + "license": "MIT" + }, "node_modules/@nodable/entities": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.1.0.tgz", @@ -805,13 +811,19 @@ "@protobuf-ts/runtime": "^2.11.1" } }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "license": "MIT" + }, "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-8.1.0.tgz", + "integrity": "sha512-2SX/1jW6CIMAiebvVv5ZInoCEuWQmMyBoJXXGC6Vjakjp/fpxP5eHs7/V6WKuPEIbuK06+VpjH+vjLQhr98rDQ==", "license": "MIT", "engines": { - "node": ">=10" + "node": ">=22" }, "funding": { "url": "https://github.com/sindresorhus/is?sponsor=1" @@ -882,30 +894,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "license": "MIT", - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "license": "MIT", - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, "node_modules/@types/esrecurse": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", @@ -921,9 +909,9 @@ "license": "MIT" }, "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", "license": "MIT" }, "node_modules/@types/json-schema": { @@ -933,33 +921,16 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/node": { "version": "25.9.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.4.tgz", "integrity": "sha512-dszCsrKb5U7ZsVZBWiHFklTloVl0mSEnWH/iZXfZUlI4rzCUnsvGmgqfuVRHL54ugE7/wRuxEIXRa2iMZ+BG6g==", + "dev": true, "license": "MIT", "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, - "node_modules/@types/responselike": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@typescript-eslint/types": { "version": "8.56.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.0.tgz", @@ -1149,31 +1120,43 @@ "node": ">=8" } }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "node_modules/byte-counter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/byte-counter/-/byte-counter-0.1.0.tgz", + "integrity": "sha512-jheRLVMeUKrDBjVw2O5+k4EvR4t9wtxHL+bo/LxfkxsVeuGMy3a5SEGgXdAFA4FSzTrU8rQXQIrsZ3oBq5a0pQ==", "license": "MIT", "engines": { - "node": ">=10.6.0" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "version": "13.0.19", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-13.0.19.tgz", + "integrity": "sha512-SVXGH037+Mo1aIMO5B2UcleR43FGjFdN+M8JObSyEoQ2Mn4CODRWx28gN5jiTF0n5ItsgtIZfyargMNs8GX4kg==", "license": "MIT", "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" + "@types/http-cache-semantics": "^4.2.0", + "get-stream": "^9.0.1", + "http-cache-semantics": "^4.2.0", + "keyv": "^5.6.0", + "mimic-response": "^4.0.0", + "normalize-url": "^8.1.1", + "responselike": "^4.0.2" }, "engines": { - "node": ">=8" + "node": ">=18" + } + }, + "node_modules/cacheable-request/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" } }, "node_modules/chalk": { @@ -1243,13 +1226,13 @@ "node": ">=20.18.1" } }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "node_modules/chunk-data": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chunk-data/-/chunk-data-0.1.0.tgz", + "integrity": "sha512-zFyPtyC0SZ6Zu79b9sOYtXZcgrsXe0RpePrzRyj52hYVFG1+Rk6rBqjjOEk+GNQwc3PIX+86teQMok970pod1g==", "license": "MIT", - "dependencies": { - "mimic-response": "^1.0.0" + "engines": { + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1344,27 +1327,15 @@ } }, "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-10.0.0.tgz", + "integrity": "sha512-oj7KWToJuuxlPr7VV0vabvxEIiqNMo+q0NueIiL3XhtwC6FVOX7Hr1c0C4eD0bmf7Zr+S/dSf2xvkH3Ad6sU3Q==", "license": "MIT", "dependencies": { - "mimic-response": "^3.1.0" + "mimic-response": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "license": "MIT", - "engines": { - "node": ">=10" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1377,15 +1348,6 @@ "dev": true, "license": "MIT" }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/degenerator": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-7.0.1.tgz", @@ -1477,15 +1439,6 @@ "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -1917,15 +1870,28 @@ "license": "ISC" }, "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", "license": "MIT", "dependencies": { - "pump": "^3.0.0" + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream/node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "license": "MIT", + "engines": { + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1973,30 +1939,53 @@ } }, "node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/got/-/got-16.0.0.tgz", + "integrity": "sha512-UtzSUebtRHHAUaNB/X37X1LQgHvdSrgXUIWGUBDhLu05CYtUr9svjeN6wmG333nzdJASFUjXMOuRBjZLf8oF1w==", "license": "MIT", "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" + "@sindresorhus/is": "^8.0.0", + "byte-counter": "^0.1.0", + "cacheable-request": "^13.0.18", + "chunk-data": "^0.1.0", + "decompress-response": "^10.0.0", + "keyv": "^5.6.0", + "lowercase-keys": "^4.0.1", + "responselike": "^4.0.2", + "type-fest": "^5.6.0", + "uint8array-extras": "^1.5.0" }, "engines": { - "node": ">=10.19.0" + "node": ">=22" }, "funding": { "url": "https://github.com/sindresorhus/got?sponsor=1" } }, + "node_modules/got/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, + "node_modules/got/node_modules/type-fest": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.9.0.tgz", + "integrity": "sha512-yANm3Jr3GiJ1qgJlxGAVxTOIcEOk1rhQHamlXtnrCK7EHP4HeM9OGxtMg/W7HFdrVzw/ZWJKGVIJusVH85sLtw==", + "license": "(MIT OR CC0-1.0)", + "dependencies": { + "tagged-tag": "^1.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/hasha": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", @@ -2057,9 +2046,9 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "license": "BSD-2-Clause" }, "node_modules/http-proxy-agent": { @@ -2075,19 +2064,6 @@ "node": ">= 14" } }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "license": "MIT", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, "node_modules/https-proxy-agent": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", @@ -2267,6 +2243,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, "license": "MIT" }, "node_modules/json-schema-traverse": { @@ -2287,6 +2264,7 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, "license": "MIT", "dependencies": { "json-buffer": "3.0.1" @@ -2337,12 +2315,15 @@ } }, "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-4.0.1.tgz", + "integrity": "sha512-wI9Nui/L8VfADa/cr/7NQruaASk1k23/Uh1khQ02BCVYiiy8F4AhOGnQzJy3Fl/c44GnYSbZHv8g7EcG3kJ1Qg==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lru-cache": { @@ -2414,12 +2395,15 @@ } }, "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", "license": "MIT", "engines": { - "node": ">=4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/minimatch": { @@ -2489,12 +2473,12 @@ } }, "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.1.tgz", + "integrity": "sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==", "license": "MIT", "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2513,15 +2497,6 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -2540,15 +2515,6 @@ "node": ">= 0.8.0" } }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -2882,16 +2848,6 @@ "node": ">=10" } }, - "node_modules/pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -2902,18 +2858,6 @@ "node": ">=6" } }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/quickjs-wasi": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/quickjs-wasi/-/quickjs-wasi-2.2.0.tgz", @@ -2927,19 +2871,28 @@ "integrity": "sha512-KHp3y3xDjuBhRx+tYKOgzPnVHMRlgpn2rU450GcU4PL24r1H6ls/hfPrxDwX2pvYMlwODHI2l8WwgoV69x5rUQ==", "license": "MIT" }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "license": "MIT" - }, "node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-4.0.2.tgz", + "integrity": "sha512-cGk8IbWEAnaCpdAt1BHzJ3Ahz5ewDJa0KseTsE3qIRMJ3C698W8psM7byCeWVpd/Ha7FUYzuRVzXoKoM6nRUbA==", "license": "MIT", "dependencies": { - "lowercase-keys": "^2.0.0" + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/responselike/node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3080,6 +3033,18 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/tagged-tag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3129,6 +3094,18 @@ "node": ">=8" } }, + "node_modules/uint8array-extras": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/undici": { "version": "6.28.0", "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz", @@ -3142,6 +3119,7 @@ "version": "7.24.6", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "dev": true, "license": "MIT" }, "node_modules/universal-user-agent": { @@ -3219,12 +3197,6 @@ "node": ">=0.10.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" - }, "node_modules/xml-naming": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz", diff --git a/package.json b/package.json index d4336100b..e322728b9 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "argument-vector": "1.0.2", "debug": "4.4.3", "find-yarn-workspace-root": "2.0.0", - "got": "11.8.6", + "got": "16.0.0", "hasha": "5.2.2", "quote": "0.4.0", "supports-color": "9.3.1" diff --git a/src/ping-cli.js b/src/ping-cli.js index 19360dd35..683f7cb0e 100644 --- a/src/ping-cli.js +++ b/src/ping-cli.js @@ -10,3 +10,10 @@ if (!url) { process.exit(1) } ping(url, timeoutSeconds * 1000) + .then(() => { + console.log('%s is responding', url) + }) + .catch((err) => { + console.error('Could not connect to %s: %s', url, err.message) + process.exit(1) + }) diff --git a/src/ping.js b/src/ping.js index deed9443f..1e8c59327 100644 --- a/src/ping.js +++ b/src/ping.js @@ -1,4 +1,3 @@ -const got = require('got') const debug = require('debug')('@cypress/github-action') /** @@ -6,11 +5,14 @@ const debug = require('debug')('@cypress/github-action') * a poor man's https://www.npmjs.com/package/wait-on. This version * is implemented using https://github.com/sindresorhus/got */ -const ping = (url, timeout) => { +const ping = async (url, timeout) => { if (!timeout) { throw new Error('Expected timeout in ms') } + // got@16 is ESM-only; dynamic import works from CommonJS + const { default: got } = await import('got') + // make copy of the error codes that "got" retries on const errorCodes = [...got.defaults.options.retry.errorCodes] errorCodes.push('ESOCKETTIMEDOUT') @@ -34,9 +36,14 @@ const ping = (url, timeout) => { headers: { Accept: 'text/html, application/json, text/plain, */*' }, - timeout: individualPingTimeout, - errorCodes, + timeout: { + request: individualPingTimeout + }, retry: { + errorCodes, + // enforceRetryRules:false lets calculateDelay be the sole stop condition, + // matching got@11 behaviour. limit is a generous failsafe only. + enforceRetryRules: false, limit, calculateDelay({ error, attemptCount }) { if (error) { @@ -49,10 +56,9 @@ const ping = (url, timeout) => { ) if (elapsed > timeout) { console.error( - '%s timed out on retry %d of %d, elapsed %dms, limit %dms', + '%s timed out after %d retries, elapsed %dms, limit %dms', url, attemptCount, - limit, elapsed, timeout )