From 4b8e190ea50b732e151d5d1dfd5b41caed203ffc Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Wed, 5 Jun 2024 13:18:06 -0700 Subject: [PATCH] Update detsys-ts (#102) --- dist/index.js | 3719 +++++++++++++++++++++++++++++++++++++++++++++++- pnpm-lock.yaml | 37 +- 2 files changed, 3684 insertions(+), 72 deletions(-) diff --git a/dist/index.js b/dist/index.js index 721e0af..e14909a 100644 --- a/dist/index.js +++ b/dist/index.js @@ -46449,7 +46449,7 @@ module.exports = self => { const tls = __nccwpck_require__(4404); const http = __nccwpck_require__(3685); const https = __nccwpck_require__(5687); -const JSStreamSocket = __nccwpck_require__(8679); +const JSStreamSocket = __nccwpck_require__(3595); const {globalAgent} = __nccwpck_require__(1840); const UnexpectedStatusCodeError = __nccwpck_require__(8859); const initialize = __nccwpck_require__(4031); @@ -46638,7 +46638,7 @@ module.exports = Http2OverHttp2; const {Agent} = __nccwpck_require__(1840); -const JSStreamSocket = __nccwpck_require__(8679); +const JSStreamSocket = __nccwpck_require__(3595); const UnexpectedStatusCodeError = __nccwpck_require__(8859); const initialize = __nccwpck_require__(4031); @@ -46907,7 +46907,7 @@ module.exports = header => { /***/ }), -/***/ 8679: +/***/ 3595: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { @@ -79881,7 +79881,7 @@ function wrappy (fn, cb) { var builder, defaults, escapeCDATA, requiresCDATA, wrapCDATA, hasProp = {}.hasOwnProperty; - builder = __nccwpck_require__(3595); + builder = __nccwpck_require__(9399); defaults = (__nccwpck_require__(4617).defaults); @@ -84788,7 +84788,7 @@ function wrappy (fn, cb) { /***/ }), -/***/ 3595: +/***/ 9399: /***/ (function(module, __unused_webpack_exports, __nccwpck_require__) { // Generated by CoffeeScript 1.12.7 @@ -89321,10 +89321,6 @@ var external_node_util_ = __nccwpck_require__(7261); var external_os_ = __nccwpck_require__(2037); ;// CONCATENATED MODULE: external "node:crypto" const external_node_crypto_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:crypto"); -;// CONCATENATED MODULE: external "node:dns/promises" -const external_node_dns_promises_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:dns/promises"); -// EXTERNAL MODULE: ./node_modules/.pnpm/@actions+cache@3.2.4/node_modules/@actions/cache/lib/cache.js -var cache = __nccwpck_require__(6878); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@sindresorhus+is@6.3.1/node_modules/@sindresorhus/is/dist/index.js const typedArrayTypeNames = [ 'Int8Array', @@ -90756,7 +90752,7 @@ class PCancelable { Object.setPrototypeOf(PCancelable.prototype, Promise.prototype); -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/errors.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/core/errors.js // A hacky check to prevent circular references. function isRequest(x) { @@ -92846,13 +92842,13 @@ getContentLength_fn = function() { }; -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/is-form-data.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/core/utils/is-form-data.js function is_form_data_isFormData(body) { return dist.nodeStream(body) && dist.function_(body.getBoundary); } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/get-body-size.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/core/utils/get-body-size.js @@ -92876,7 +92872,7 @@ async function getBodySize(body, headers) { return undefined; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/proxy-events.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/core/utils/proxy-events.js function proxyEvents(from, to, events) { const eventFunctions = {}; for (const event of events) { @@ -92895,7 +92891,7 @@ function proxyEvents(from, to, events) { ;// CONCATENATED MODULE: external "node:net" const external_node_net_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:net"); -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/unhandle.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/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, @@ -92917,7 +92913,7 @@ function unhandle() { }; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/timed-out.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/core/timed-out.js const reentry = Symbol('reentry'); @@ -93048,7 +93044,7 @@ function timedOut(request, delays, options) { return cancelTimeouts; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/url-to-options.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/core/utils/url-to-options.js function urlToOptions(url) { // Cast to URL @@ -93072,7 +93068,7 @@ function urlToOptions(url) { return options; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/weakable-map.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/core/utils/weakable-map.js class WeakableMap { weakMap; map; @@ -93102,7 +93098,7 @@ class WeakableMap { } } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/calculate-retry-delay.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/core/calculate-retry-delay.js const calculateRetryDelay = ({ attemptCount, retryOptions, error, retryAfter, computedValue, }) => { if (error.name === 'RetryError') { return 1; @@ -93589,7 +93585,7 @@ class CacheableLookup { // EXTERNAL MODULE: ./node_modules/.pnpm/http2-wrapper@2.2.1/node_modules/http2-wrapper/source/index.js var http2_wrapper_source = __nccwpck_require__(9695); -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/parse-link-header.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/core/parse-link-header.js function parseLinkHeader(link) { const parsed = []; const items = link.split(','); @@ -93624,7 +93620,7 @@ function parseLinkHeader(link) { return parsed; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/options.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/core/options.js @@ -95261,7 +95257,7 @@ class Options { } } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/response.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/core/response.js const isResponseOk = (response) => { const { statusCode } = response; @@ -95304,19 +95300,19 @@ const parseBody = (response, responseType, parseJson, encoding) => { }, response); }; -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/is-client-request.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/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); -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/is-unix-socket-url.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/core/utils/is-unix-socket-url.js // eslint-disable-next-line @typescript-eslint/naming-convention function isUnixSocketURL(url) { return url.protocol === 'unix:' || url.hostname === 'unix'; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/index.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/core/index.js @@ -96320,7 +96316,7 @@ class Request extends external_node_stream_.Duplex { } } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/as-promise/types.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/as-promise/types.js /** An error to be thrown when the request is aborted with `.cancel()`. @@ -96339,7 +96335,7 @@ class types_CancelError extends RequestError { } } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/as-promise/index.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/as-promise/index.js @@ -96505,7 +96501,7 @@ function asPromise(firstRequest) { return promise; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/create.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/create.js @@ -96690,7 +96686,7 @@ const create = (defaults) => { }; /* harmony default export */ const source_create = (create); -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/index.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.4.0/node_modules/got/dist/source/index.js const defaults = { @@ -96713,13 +96709,17 @@ const got = source_create(defaults); +;// CONCATENATED MODULE: external "node:dns/promises" +const external_node_dns_promises_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:dns/promises"); +// EXTERNAL MODULE: ./node_modules/.pnpm/@actions+cache@3.2.4/node_modules/@actions/cache/lib/cache.js +var cache = __nccwpck_require__(6878); ;// CONCATENATED MODULE: external "node:child_process" const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:child_process"); ;// CONCATENATED MODULE: external "node:stream/promises" const external_node_stream_promises_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:stream/promises"); ;// CONCATENATED MODULE: external "node:zlib" const external_node_zlib_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:zlib"); -;// CONCATENATED MODULE: ./node_modules/.pnpm/github.com+DeterminateSystems+detsys-ts@7916bffbfacbe63ee24c4bf8649de649bd04f7b0_62jecunnyhcc7cqvpxd4fea3mu/node_modules/detsys-ts/dist/index.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/github.com+DeterminateSystems+detsys-ts@dd1509475ee7fee37677b858b67aa96ef37a7531_5xj7muga2pf2jza4obzcpzufey/node_modules/detsys-ts/dist/index.js var __defProp = Object.defineProperty; var __export = (target, all) => { for (var name in all) @@ -97037,6 +97037,7 @@ function stringifyError(e) { // src/ids-host.ts + var DEFAULT_LOOKUP = "_detsys_ids._tcp.install.determinate.systems."; var ALLOWED_SUFFIXES = [ ".install.determinate.systems", @@ -97044,11 +97045,56 @@ var ALLOWED_SUFFIXES = [ ]; var DEFAULT_IDS_HOST = "https://install.determinate.systems"; var LOOKUP = process.env["IDS_LOOKUP"] ?? DEFAULT_LOOKUP; +var DEFAULT_TIMEOUT = 3e4; var IdsHost = class { constructor(idsProjectName, diagnosticsSuffix, runtimeDiagnosticsUrl) { this.idsProjectName = idsProjectName; this.diagnosticsSuffix = diagnosticsSuffix; this.runtimeDiagnosticsUrl = runtimeDiagnosticsUrl; + this.client = void 0; + } + async getGot(recordFailoverCallback) { + if (this.client === void 0) { + this.client = got_dist_source.extend({ + timeout: { + request: DEFAULT_TIMEOUT + }, + retry: { + limit: (await this.getUrlsByPreference()).length, + methods: ["GET", "HEAD"] + }, + hooks: { + beforeRetry: [ + async (error3, retryCount) => { + const prevUrl = await this.getRootUrl(); + this.markCurrentHostBroken(); + const nextUrl = await this.getRootUrl(); + if (recordFailoverCallback !== void 0) { + recordFailoverCallback(prevUrl, nextUrl); + } + core.info( + `Retrying after error ${error3.code}, retry #: ${retryCount}` + ); + } + ], + beforeRequest: [ + async (options) => { + const currentUrl = options.url; + if (this.isUrlSubjectToDynamicUrls(currentUrl)) { + const newUrl = new URL(currentUrl); + const url = await this.getRootUrl(); + newUrl.host = url.host; + options.url = newUrl; + core.debug(`Transmuted ${currentUrl} into ${newUrl}`); + } else { + core.debug(`No transmutations on ${currentUrl}`); + } + } + ] + } + }); + } + return this.client; } markCurrentHostBroken() { this.prioritizedURLs?.shift(); @@ -97056,6 +97102,17 @@ var IdsHost = class { setPrioritizedUrls(urls) { this.prioritizedURLs = urls; } + isUrlSubjectToDynamicUrls(url) { + if (url.origin === DEFAULT_IDS_HOST) { + return true; + } + for (const suffix of ALLOWED_SUFFIXES) { + if (url.host.endsWith(suffix)) { + return true; + } + } + return false; + } async getDynamicRootUrl() { const idsHost = process.env["IDS_HOST"]; if (idsHost !== void 0) { @@ -97376,7 +97433,6 @@ function noisilyGetInput(suffix, legacyPrefix) { - var EVENT_EXCEPTION = "exception"; var EVENT_ARTIFACT_CACHE_HIT = "artifact_cache_hit"; var EVENT_ARTIFACT_CACHE_MISS = "artifact_cache_miss"; @@ -97424,21 +97480,6 @@ var DetSysAction = class { this.features = {}; this.featureEventMetadata = {}; this.events = []; - this.client = got_dist_source.extend({ - retry: { - limit: 3, - methods: ["GET", "HEAD"] - }, - hooks: { - beforeRetry: [ - (error3, retryCount) => { - core.info( - `Retrying after error ${error3.code}, retry #: ${retryCount}` - ); - } - ] - } - }); this.facts = { $lib: "idslib", $lib_version: version, @@ -97622,6 +97663,14 @@ var DetSysAction = class { await this.complete(); } } + async getClient() { + return await this.idsHost.getGot((prevUrl, nextUrl) => { + this.recordEvent("ids-failover", { + previousUrl: prevUrl.toString(), + nextUrl: nextUrl.toString() + }); + }); + } async checkIn() { const checkin = await this.requestCheckIn(); if (checkin === void 0) { @@ -97698,7 +97747,7 @@ var DetSysAction = class { "correlation", JSON.stringify(this.identity) ); - return await this.client.get(checkInUrl, { + return (await this.getClient()).get(checkInUrl, { timeout: { request: CHECK_IN_ENDPOINT_TIMEOUT_MS } @@ -97734,7 +97783,7 @@ var DetSysAction = class { "correlation", JSON.stringify(this.identity) ); - const versionCheckup = await this.client.head(correlatedUrl); + const versionCheckup = await (await this.getClient()).head(correlatedUrl); if (versionCheckup.headers.etag) { const v = versionCheckup.headers.etag; this.addFact(FACT_SOURCE_URL_ETAG, v); @@ -97753,7 +97802,7 @@ var DetSysAction = class { `No match from the cache, re-fetching from the redirect: ${versionCheckup.url}` ); const destFile = this.getTemporaryName(); - const fetchStream = this.client.stream(versionCheckup.url); + const fetchStream = (await this.getClient()).stream(versionCheckup.url); await (0,external_node_stream_promises_namespaceObject.pipeline)( fetchStream, (0,external_node_fs_namespaceObject.createWriteStream)(destFile, { @@ -97971,32 +98020,16 @@ var DetSysAction = class { events: this.events }; try { - await this.client.post(diagnosticsUrl, { + await (await this.getClient()).post(diagnosticsUrl, { json: batch, timeout: { request: DIAGNOSTIC_ENDPOINT_TIMEOUT_MS } }); - } catch (e) { + } catch (err) { core.debug( - `Error submitting diagnostics event: ${stringifyError2(e)}` + `Error submitting diagnostics event to ${diagnosticsUrl}: ${stringifyError2(err)}` ); - this.idsHost.markCurrentHostBroken(); - const secondaryDiagnosticsUrl = await this.idsHost.getDiagnosticsUrl(); - if (secondaryDiagnosticsUrl !== void 0) { - try { - await this.client.post(secondaryDiagnosticsUrl, { - json: batch, - timeout: { - request: DIAGNOSTIC_ENDPOINT_TIMEOUT_MS - } - }); - } catch (err) { - core.debug( - `Error submitting diagnostics event to secondary host (${secondaryDiagnosticsUrl}): ${stringifyError2(err)}` - ); - } - } } this.events = []; } @@ -98030,6 +98063,3556 @@ function makeOptionsConfident(actionOptions) { * Copyright (c) 2018-2020 [Samuel Carreira] */ //# sourceMappingURL=index.js.map +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/errors.js + +// A hacky check to prevent circular references. +function errors_isRequest(x) { + return dist.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 errors_RequestError extends Error { + input; + code; + stack; + response; + request; + timings; + constructor(message, error, self) { + super(message, { cause: error }); + Error.captureStackTrace(this, this.constructor); + this.name = 'RequestError'; + this.code = error.code ?? 'ERR_GOT_REQUEST_ERROR'; + this.input = error.input; + if (errors_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 (dist.string(error.stack) && dist.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')}`; + } + } +} +/** +An error to be thrown when the server redirects you more than ten times. +Includes a `response` property. +*/ +class errors_MaxRedirectsError extends errors_RequestError { + constructor(request) { + super(`Redirected ${request.options.maxRedirects} times. Aborting.`, {}, request); + this.name = 'MaxRedirectsError'; + this.code = 'ERR_TOO_MANY_REDIRECTS'; + } +} +/** +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. +*/ +// TODO: Change `HTTPError` to `HTTPError` in the next major version to enforce type usage. +// eslint-disable-next-line @typescript-eslint/naming-convention +class errors_HTTPError extends errors_RequestError { + constructor(response) { + super(`Response code ${response.statusCode} (${response.statusMessage})`, {}, response.request); + this.name = 'HTTPError'; + this.code = 'ERR_NON_2XX_3XX_RESPONSE'; + } +} +/** +An error to be thrown when a cache method fails. +For example, if the database goes down or there's a filesystem error. +*/ +class errors_CacheError extends errors_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; + } +} +/** +An error to be thrown when the request body is a stream and an error occurs while reading from that stream. +*/ +class errors_UploadError extends errors_RequestError { + constructor(error, request) { + super(error.message, error, request); + this.name = 'UploadError'; + this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_UPLOAD' : this.code; + } +} +/** +An error to be thrown when the request is aborted due to a timeout. +Includes an `event` and `timings` property. +*/ +class errors_TimeoutError extends errors_RequestError { + timings; + event; + constructor(error, timings, request) { + super(error.message, error, request); + this.name = 'TimeoutError'; + this.event = error.event; + this.timings = timings; + } +} +/** +An error to be thrown when reading from response stream fails. +*/ +class errors_ReadError extends errors_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; + } +} +/** +An error which always triggers a new retry when thrown. +*/ +class errors_RetryError extends errors_RequestError { + constructor(request) { + super('Retrying', {}, request); + this.name = 'RetryError'; + this.code = 'ERR_RETRYING'; + } +} +/** +An error to be thrown when the request is aborted by AbortController. +*/ +class errors_AbortError extends errors_RequestError { + constructor(request) { + super('This operation was aborted.', {}, request); + this.code = 'ERR_ABORTED'; + this.name = 'AbortError'; + } +} + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/is-form-data.js + +function utils_is_form_data_isFormData(body) { + return dist.nodeStream(body) && dist.function_(body.getBoundary); +} + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/get-body-size.js + + + + +async function get_body_size_getBodySize(body, headers) { + if (headers && 'content-length' in headers) { + return Number(headers['content-length']); + } + if (!body) { + return 0; + } + if (dist.string(body)) { + return external_node_buffer_namespaceObject.Buffer.byteLength(body); + } + if (dist.buffer(body)) { + return body.length; + } + if (utils_is_form_data_isFormData(body)) { + return (0,external_node_util_.promisify)(body.getLength.bind(body))(); + } + return undefined; +} + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/proxy-events.js +function proxy_events_proxyEvents(from, to, events) { + const eventFunctions = {}; + for (const event of events) { + const eventFunction = (...arguments_) => { + to.emit(event, ...arguments_); + }; + eventFunctions[event] = eventFunction; + from.on(event, eventFunction); + } + return () => { + for (const [event, eventFunction] of Object.entries(eventFunctions)) { + from.off(event, eventFunction); + } + }; +} + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/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_unhandle() { + const handlers = []; + return { + once(origin, event, function_) { + origin.once(event, function_); + handlers.push({ origin, event, fn: function_ }); + }, + unhandleAll() { + for (const handler of handlers) { + const { origin, event, fn } = handler; + origin.removeListener(event, fn); + } + handlers.length = 0; + }, + }; +} + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/timed-out.js + + +const timed_out_reentry = Symbol('reentry'); +const core_timed_out_noop = () => { }; +class core_timed_out_TimeoutError extends Error { + event; + code; + constructor(threshold, event) { + super(`Timeout awaiting '${event}' for ${threshold}ms`); + this.event = event; + this.name = 'TimeoutError'; + this.code = 'ETIMEDOUT'; + } +} +function timed_out_timedOut(request, delays, options) { + if (timed_out_reentry in request) { + return core_timed_out_noop; + } + request[timed_out_reentry] = true; + const cancelers = []; + const { once, unhandleAll } = unhandle_unhandle(); + const addTimeout = (delay, callback, event) => { + const timeout = setTimeout(callback, delay, delay, event); + timeout.unref?.(); + const cancel = () => { + clearTimeout(timeout); + }; + cancelers.push(cancel); + return cancel; + }; + const { host, hostname } = options; + const timeoutHandler = (delay, event) => { + request.destroy(new core_timed_out_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; + } + }); + 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_namespaceObject.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/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/url-to-options.js + +function url_to_options_urlToOptions(url) { + // Cast to URL + url = url; + const options = { + protocol: url.protocol, + hostname: dist.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 (dist.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; +} + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/weakable-map.js +class weakable_map_WeakableMap { + weakMap; + map; + 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); + } +} + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/calculate-retry-delay.js +const calculate_retry_delay_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 `options.request.timeout` + if (retryAfter > computedValue) { + return 0; + } + return 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 core_calculate_retry_delay = (calculate_retry_delay_calculateRetryDelay); + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/parse-link-header.js +function parse_link_header_parseLinkHeader(link) { + const parsed = []; + const items = link.split(','); + for (const item of items) { + // https://tools.ietf.org/html/rfc5988#section-5 + const [rawUriReference, ...rawLinkParameters] = item.split(';'); + 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 (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/.pnpm/got@14.3.0/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 [options_major, options_minor] = external_node_process_.versions.node.split('.').map(Number); +function options_validateSearchParameters(searchParameters) { + // eslint-disable-next-line guard-for-in + for (const key in searchParameters) { + const value = searchParameters[key]; + assert.any([dist.string, dist.number, dist.boolean, dist.null_, dist.undefined], value); + } +} +const options_globalCache = new Map(); +let options_globalDnsCache; +const options_getGlobalDnsCache = () => { + if (options_globalDnsCache) { + return options_globalDnsCache; + } + options_globalDnsCache = new CacheableLookup(); + return options_globalDnsCache; +}; +const options_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: [], + afterResponse: [], + }, + followRedirect: true, + maxRedirects: 10, + cache: undefined, + throwHttpErrors: true, + username: '', + password: '', + http2: false, + allowGetBody: 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', + ], + 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, + }, + localAddress: undefined, + method: 'GET', + createConnection: undefined, + cacheOptions: { + shared: undefined, + cacheHeuristic: undefined, + immutableMinTimeToLive: undefined, + ignoreCargoCult: undefined, + }, + https: { + alpnProtocols: undefined, + rejectUnauthorized: undefined, + checkServerIdentity: 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, + }, + 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 = parse_link_header_parseLinkHeader(rawLinkHeader); + const next = parsed.find(entry => entry.parameters.rel === 'next' || entry.parameters.rel === '"next"'); + if (next) { + return { + url: new URL(next.reference, response.url), + }; + } + 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, +}; +const options_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], + afterResponse: [...hooks.afterResponse], + }, + searchParams: internals.searchParams ? new URLSearchParams(internals.searchParams) : undefined, + pagination: { ...internals.pagination }, + }; + if (result.url !== undefined) { + result.prefixUrl = ''; + } + return result; +}; +const options_cloneRaw = (raw) => { + const { hooks, retry } = raw; + const result = { ...raw }; + if (dist.object(raw.context)) { + result.context = { ...raw.context }; + } + if (dist.object(raw.cacheOptions)) { + result.cacheOptions = { ...raw.cacheOptions }; + } + if (dist.object(raw.https)) { + result.https = { ...raw.https }; + } + if (dist.object(raw.cacheOptions)) { + result.cacheOptions = { ...result.cacheOptions }; + } + if (dist.object(raw.agent)) { + result.agent = { ...raw.agent }; + } + if (dist.object(raw.headers)) { + result.headers = { ...raw.headers }; + } + if (dist.object(retry)) { + result.retry = { ...retry }; + if (dist.array(retry.errorCodes)) { + result.retry.errorCodes = [...retry.errorCodes]; + } + if (dist.array(retry.methods)) { + result.retry.methods = [...retry.methods]; + } + if (dist.array(retry.statusCodes)) { + result.retry.statusCodes = [...retry.statusCodes]; + } + } + if (dist.object(raw.timeout)) { + result.timeout = { ...raw.timeout }; + } + if (dist.object(hooks)) { + result.hooks = { + ...hooks, + }; + if (dist.array(hooks.init)) { + result.hooks.init = [...hooks.init]; + } + if (dist.array(hooks.beforeRequest)) { + result.hooks.beforeRequest = [...hooks.beforeRequest]; + } + if (dist.array(hooks.beforeError)) { + result.hooks.beforeError = [...hooks.beforeError]; + } + if (dist.array(hooks.beforeRedirect)) { + result.hooks.beforeRedirect = [...hooks.beforeRedirect]; + } + if (dist.array(hooks.beforeRetry)) { + result.hooks.beforeRetry = [...hooks.beforeRetry]; + } + if (dist.array(hooks.afterResponse)) { + result.hooks.afterResponse = [...hooks.afterResponse]; + } + } + // TODO: raw.searchParams + if (dist.object(raw.pagination)) { + result.pagination = { ...raw.pagination }; + } + return result; +}; +const options_getHttp2TimeoutOption = (internals) => { + const delays = [internals.timeout.socket, internals.timeout.connect, internals.timeout.lookup, internals.timeout.request, internals.timeout.secureConnect].filter(delay => typeof delay === 'number'); + if (delays.length > 0) { + return Math.min(...delays); + } + return undefined; +}; +const options_init = (options, withOptions, self) => { + const initHooks = options.hooks?.init; + if (initHooks) { + for (const hook of initHooks) { + hook(withOptions, self); + } + } +}; +class options_Options { + _unixOptions; + _internals; + _merging; + _init; + constructor(input, options, defaults) { + assert.any([dist.string, dist.urlInstance, dist.object, dist.undefined], input); + assert.any([dist.object, dist.undefined], options); + assert.any([dist.object, dist.undefined], defaults); + if (input instanceof options_Options || options instanceof options_Options) { + throw new TypeError('The defaults must be passed as the third argument'); + } + this._internals = options_cloneInternals(defaults?._internals ?? defaults ?? options_defaultInternals); + this._init = [...(defaults?._init ?? [])]; + this._merging = false; + this._unixOptions = undefined; + // 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 */ + try { + if (dist.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_Options) { + for (const init of options._init) { + this.merge(init); + } + return; + } + options = options_cloneRaw(options); + options_init(this, options, this); + options_init(options, options, this); + this._merging = true; + // Always merge `isStream` first + if ('isStream' in options) { + this.isStream = options.isStream; + } + try { + let push = false; + for (const key in options) { + // `got.extend()` options + if (key === 'mutableDefaults' || key === 'handlers') { + continue; + } + // Never merge `url` + if (key === 'url') { + 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. + The main purpose of this is to [support HTTP2 using a wrapper](https://github.com/szmarczak/http2-wrapper). + + @default http.request | https.request + */ + get request() { + return this._internals.request; + } + set request(value) { + assert.any([dist.function_, dist.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 [`http2wrapper.Agent`](https://github.com/szmarczak/http2-wrapper#new-http2agentoptions) instance. + 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. + + 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) { + assert.plainObject(value); + // eslint-disable-next-line guard-for-in + for (const key in value) { + if (!(key in this._internals.agent)) { + throw new TypeError(`Unexpected agent option: ${key}`); + } + // @ts-expect-error - No idea why `value[key]` doesn't work here. + assert.any([dist.object, dist.undefined], value[key]); + } + if (this._merging) { + Object.assign(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 `Buffer`. + 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) { + assert.plainObject(value); + // eslint-disable-next-line guard-for-in + for (const key in value) { + if (!(key in this._internals.timeout)) { + throw new Error(`Unexpected timeout option: ${key}`); + } + // @ts-expect-error - No idea why `value[key]` doesn't work here. + assert.any([dist.number, dist.undefined], value[key]); + } + if (this._merging) { + Object.assign(this._internals.timeout, value); + } + else { + this._internals.timeout = { ...value }; + } + } + /** + When specified, `prefixUrl` will be prepended to `url`. + The prefix can be any valid URL, either relative or absolute. + A trailing slash `/` is optional - one will be added automatically. + + __Note__: `prefixUrl` will be ignored if the `url` argument is a URL instance. + + __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) { + assert.any([dist.string, dist.urlInstance], value); + if (value === '') { + this._internals.prefixUrl = ''; + return; + } + value = value.toString(); + if (!value.endsWith('/')) { + value += '/'; + } + if (this._internals.prefixUrl && this._internals.url) { + const { href } = this._internals.url; + this._internals.url.href = value + href.slice(this._internals.prefixUrl.length); + } + this._internals.prefixUrl = value; + } + /** + __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` / `Buffer` / [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) / [`form-data` instance](https://github.com/form-data/form-data), 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`. + */ + get body() { + return this._internals.body; + } + set body(value) { + assert.any([dist.string, dist.buffer, dist.nodeStream, dist.generator, dist.asyncGenerator, lib_isFormData, dist.undefined], value); + if (dist.nodeStream(value)) { + assert.truthy(value.readable); + } + if (value !== undefined) { + assert.undefined(this._internals.form); + assert.undefined(this._internals.json); + } + this._internals.body = value; + } + /** + 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) { + assert.any([dist.plainObject, dist.undefined], value); + if (value !== undefined) { + assert.undefined(this._internals.body); + assert.undefined(this._internals.json); + } + this._internals.form = value; + } + /** + JSON body. If the `Content-Type` header is not set, it will be set to `application/json`. + + __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; + } + /** + 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) { + assert.any([dist.string, dist.urlInstance, dist.undefined], value); + if (value === undefined) { + this._internals.url = undefined; + return; + } + if (dist.string(value) && value.startsWith('/')) { + throw new Error('`url` must not start with a slash'); + } + const urlString = `${this.prefixUrl}${value.toString()}`; + const url = new URL(urlString); + this._internals.url = url; + 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; + } + if (url.hostname === 'unix') { + if (!this._internals.enableUnixSockets) { + throw new Error('Using UNIX domain sockets but option `enableUnixSockets` is not enabled'); + } + const matches = /(?.+?):(?.+)/.exec(`${url.pathname}${url.search}`); + if (matches?.groups) { + const { socketPath, path } = matches.groups; + this._unixOptions = { + socketPath, + path, + host: '', + }; + } + else { + this._unixOptions = undefined; + } + return; + } + this._unixOptions = 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) { + assert.any([dist.object, dist.undefined], value); + if (value === undefined) { + this._internals.cookieJar = undefined; + return; + } + let { setCookie, getCookieString } = value; + assert.function_(setCookie); + assert.function_(getCookieString); + /* istanbul ignore next: Horrible `tough-cookie` v3 check */ + if (setCookie.length === 4 && getCookieString.length === 0) { + setCookie = (0,external_node_util_.promisify)(setCookie.bind(value)); + getCookieString = (0,external_node_util_.promisify)(getCookieString.bind(value)); + this._internals.cookieJar = { + setCookie, + getCookieString: getCookieString, + }; + } + 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) { + assert.object(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; + } + if (this._internals.searchParams === undefined) { + this._internals.searchParams = new URLSearchParams(); + } + return this._internals.searchParams; + } + set searchParams(value) { + assert.any([dist.string, dist.object, dist.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 (dist.string(value)) { + updated = new URLSearchParams(value); + } + else if (value instanceof URLSearchParams) { + updated = value; + } + else { + options_validateSearchParameters(value); + updated = new URLSearchParams(); + // eslint-disable-next-line guard-for-in + for (const key in value) { + 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) { + url.search = searchParameters.toString(); + } + else { + this._internals.searchParams = searchParameters; + } + } + get searchParameters() { + throw new Error('The `searchParameters` option does not exist. Use `searchParams` instead.'); + } + set searchParameters(_value) { + throw new Error('The `searchParameters` option does not exist. Use `searchParams` instead.'); + } + get dnsLookup() { + return this._internals.dnsLookup; + } + set dnsLookup(value) { + assert.any([dist.function_, dist.undefined], value); + this._internals.dnsLookup = value; + } + /** + An instance of [`CacheableLookup`](https://github.com/szmarczak/cacheable-lookup) used for making DNS lookups. + Useful when making lots of requests to different *public* hostnames. + + `CacheableLookup` uses `dns.resolver4(..)` and `dns.resolver6(...)` under the hood and fall backs to `dns.lookup(...)` when the first two fail, which may lead to additional delay. + + __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) { + assert.any([dist.object, dist.boolean, dist.undefined], value); + if (value === true) { + this._internals.dnsCache = options_getGlobalDnsCache(); + } + else if (value === false) { + this._internals.dnsCache = undefined; + } + else { + 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) { + Object.assign(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); + // eslint-disable-next-line guard-for-in + for (const knownHookEvent in value) { + if (!(knownHookEvent in this._internals.hooks)) { + throw new Error(`Unexpected hook event: ${knownHookEvent}`); + } + const typedKnownHookEvent = knownHookEvent; + const hooks = value[typedKnownHookEvent]; + assert.any([dist.array, dist.undefined], hooks); + if (hooks) { + for (const hook of hooks) { + assert.function_(hook); + } + } + if (this._merging) { + if (hooks) { + // @ts-expect-error FIXME + this._internals.hooks[typedKnownHookEvent].push(...hooks); + } + } + else { + if (!hooks) { + throw new Error(`Missing hook event: ${knownHookEvent}`); + } + // @ts-expect-error FIXME + 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`. + + @default true + */ + get followRedirect() { + return this._internals.followRedirect; + } + set followRedirect(value) { + assert.any([dist.boolean, dist.function_], value); + this._internals.followRedirect = value; + } + get followRedirects() { + throw new TypeError('The `followRedirects` option does not exist. Use `followRedirect` instead.'); + } + set followRedirects(_value) { + throw new TypeError('The `followRedirects` option does not exist. Use `followRedirect` instead.'); + } + /** + 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) { + assert.any([dist.object, dist.string, dist.boolean, dist.undefined], value); + if (value === true) { + this._internals.cache = options_globalCache; + } + else if (value === false) { + this._internals.cache = undefined; + } + else { + this._internals.cache = 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; + } + } + 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; + } + } + /** + If set to `true`, Got will additionally accept HTTP2 requests. + + It will choose either HTTP/1.1 or HTTP/2 depending on the ALPN protocol. + + __Note__: This option requires Node.js 15.10.0 or newer as HTTP/2 support on older Node.js versions is very buggy. + + __Note__: Overriding `options.request` will disable HTTP2 support. + + @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. + However, the [HTTP/2 specification](https://tools.ietf.org/html/rfc7540#section-8.1.3) says that `An HTTP GET request includes request header fields and no payload body`, therefore when using the HTTP/2 protocol this option will have no effect. + 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; + } + /** + Request headers. + + Existing headers will be overwritten. Headers set to `undefined` will be omitted. + + @default {} + */ + get headers() { + return this._internals.headers; + } + set headers(value) { + assert.plainObject(value); + if (this._merging) { + Object.assign(this._internals.headers, lowercaseKeys(value)); + } + else { + this._internals.headers = lowercaseKeys(value); + } + } + /** + 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. + Setting `methodRewriting` to `true` will also rewrite `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). + + 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) { + assert.plainObject(value); + assert.any([dist.function_, dist.undefined], value.calculateDelay); + assert.any([dist.number, dist.undefined], value.maxRetryAfter); + assert.any([dist.number, dist.undefined], value.limit); + assert.any([dist.array, dist.undefined], value.methods); + assert.any([dist.array, dist.undefined], value.statusCodes); + assert.any([dist.array, dist.undefined], value.errorCodes); + assert.any([dist.number, dist.undefined], value.noise); + if (value.noise && Math.abs(value.noise) > 100) { + throw new Error(`The maximum acceptable retry noise is +/- 100ms, got ${value.noise}`); + } + for (const key in value) { + if (!(key in this._internals.retry)) { + throw new Error(`Unexpected retry option: ${key}`); + } + } + if (this._merging) { + Object.assign(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) { + assert.any([dist.string, dist.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) { + assert.any([dist.function_, dist.undefined], value); + this._internals.createConnection = value; + } + /** + From `http-cache-semantics` + + @default {} + */ + get cacheOptions() { + return this._internals.cacheOptions; + } + set cacheOptions(value) { + assert.plainObject(value); + assert.any([dist.boolean, dist.undefined], value.shared); + assert.any([dist.number, dist.undefined], value.cacheHeuristic); + assert.any([dist.number, dist.undefined], value.immutableMinTimeToLive); + assert.any([dist.boolean, dist.undefined], value.ignoreCargoCult); + for (const key in value) { + if (!(key in this._internals.cacheOptions)) { + throw new Error(`Cache option \`${key}\` does not exist`); + } + } + if (this._merging) { + Object.assign(this._internals.cacheOptions, value); + } + else { + this._internals.cacheOptions = { ...value }; + } + } + /** + Options for the advanced HTTPS API. + */ + get https() { + return this._internals.https; + } + set https(value) { + assert.plainObject(value); + assert.any([dist.boolean, dist.undefined], value.rejectUnauthorized); + assert.any([dist.function_, dist.undefined], value.checkServerIdentity); + assert.any([dist.string, dist.object, dist.array, dist.undefined], value.certificateAuthority); + assert.any([dist.string, dist.object, dist.array, dist.undefined], value.key); + assert.any([dist.string, dist.object, dist.array, dist.undefined], value.certificate); + assert.any([dist.string, dist.undefined], value.passphrase); + assert.any([dist.string, dist.buffer, dist.array, dist.undefined], value.pfx); + assert.any([dist.array, dist.undefined], value.alpnProtocols); + assert.any([dist.string, dist.undefined], value.ciphers); + assert.any([dist.string, dist.buffer, dist.undefined], value.dhparam); + assert.any([dist.string, dist.undefined], value.signatureAlgorithms); + assert.any([dist.string, dist.undefined], value.minVersion); + assert.any([dist.string, dist.undefined], value.maxVersion); + assert.any([dist.boolean, dist.undefined], value.honorCipherOrder); + assert.any([dist.number, dist.undefined], value.tlsSessionLifetime); + assert.any([dist.string, dist.undefined], value.ecdhCurve); + assert.any([dist.string, dist.buffer, dist.array, dist.undefined], value.certificateRevocationLists); + for (const key in value) { + if (!(key in this._internals.https)) { + throw new Error(`HTTPS option \`${key}\` does not exist`); + } + } + if (this._merging) { + Object.assign(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 [`Buffer`](https://nodejs.org/api/buffer.html), 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 Buffer, set `options.responseType` to `buffer` instead'); + } + assert.any([dist.string, dist.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`. + This is equivalent to calling `got.stream(url, options?)`. + + @default false + */ + 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 Buffer + // `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 === undefined) { + this._internals.responseType = 'text'; + return; + } + 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) { + Object.assign(this._internals.pagination, value); + } + else { + this._internals.pagination = value; + } + } + get auth() { + throw new Error('Parameter `auth` is deprecated. Use `username` / `password` instead.'); + } + set auth(_value) { + throw new Error('Parameter `auth` is deprecated. Use `username` / `password` instead.'); + } + 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) { + assert.any([dist.number, dist.undefined], value); + this._internals.maxHeaderSize = value; + } + get enableUnixSockets() { + return this._internals.enableUnixSockets; + } + set enableUnixSockets(value) { + assert.boolean(value); + this._internals.enableUnixSockets = 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; + let agent; + if (url.protocol === 'https:') { + agent = internals.http2 ? internals.agent : internals.agent.https; + } + else { + agent = internals.agent.http; + } + const { https } = internals; + let { pfx } = https; + if (dist.array(pfx) && dist.plainObject(pfx[0])) { + pfx = pfx.map(object => ({ + buf: object.buffer, + passphrase: object.passphrase, + })); + } + return { + ...internals.cacheOptions, + ...this._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: https.pfx, + rejectUnauthorized: https.rejectUnauthorized, + checkServerIdentity: https.checkServerIdentity ?? external_node_tls_namespaceObject.checkServerIdentity, + 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, + // 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, + timeout: internals.http2 ? options_getHttp2TimeoutOption(internals) : undefined, + // HTTP/2 options + h2session: internals.h2session, + }; + } + getRequestFunction() { + const url = this._internals.url; + const { request } = this._internals; + if (!request && url) { + return this.getFallbackRequestFunction(); + } + return request; + } + getFallbackRequestFunction() { + const url = this._internals.url; + if (!url) { + return; + } + if (url.protocol === 'https:') { + if (this._internals.http2) { + if (options_major < 15 || (options_major === 15 && options_minor < 10)) { + const error = new Error('To use the `http2` option, install Node.js 15.10.0 or above'); + error.code = 'EUNSUPPORTED'; + throw error; + } + return http2_wrapper_source.auto; + } + return external_node_https_namespaceObject.request; + } + return external_node_http_namespaceObject.request; + } + freeze() { + const options = this._internals; + Object.freeze(options); + Object.freeze(options.hooks); + Object.freeze(options.hooks.afterResponse); + 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); + } +} + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/response.js + +const response_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 response_ParseError extends errors_RequestError { + constructor(error, response) { + const { options } = response.request; + super(`${error.message} in "${options.url.toString()}"`, error, response.request); + this.name = 'ParseError'; + this.code = 'ERR_BODY_PARSE_FAILURE'; + } +} +const response_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(encoding)); + } + if (responseType === 'buffer') { + return rawBody; + } + } + catch (error) { + throw new response_ParseError(error, response); + } + throw new response_ParseError({ + message: `Unknown body type '${responseType}'`, + name: 'Error', + }, response); +}; + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/is-client-request.js +function is_client_request_isClientRequest(clientRequest) { + return clientRequest.writable && !clientRequest.writableEnded; +} +/* harmony default export */ const utils_is_client_request = (is_client_request_isClientRequest); + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/is-unix-socket-url.js +// eslint-disable-next-line @typescript-eslint/naming-convention +function is_unix_socket_url_isUnixSocketURL(url) { + return url.protocol === 'unix:' || url.hostname === 'unix'; +} + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/index.js + + + + + + + + + + + + + + + + + + + + + + +const core_supportsBrotli = dist.string(external_node_process_.versions.brotli); +const core_methodsWithoutBody = new Set(['GET', 'HEAD']); +const core_cacheableStore = new weakable_map_WeakableMap(); +const core_redirectCodes = new Set([300, 301, 302, 303, 304, 307, 308]); +const core_proxiedRequestEvents = [ + 'socket', + 'connect', + 'continue', + 'information', + 'upgrade', +]; +const source_core_noop = () => { }; +class core_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; + _stopRetry; + _downloadedSize; + _uploadedSize; + _stopReading; + _pipedServerResponses; + _request; + _responseSize; + _bodySize; + _unproxyEvents; + _isFromCache; + _cannotHaveBody; + _triggerRead; + _cancelTimeouts; + _removeListeners; + _nativeResponse; + _flushed; + _aborted; + // We need this because `this._request` if `undefined` when using cache + _requestInitialized; + 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._downloadedSize = 0; + this._uploadedSize = 0; + this._stopReading = false; + this._pipedServerResponses = new Set(); + this._cannotHaveBody = false; + this._unproxyEvents = source_core_noop; + this._triggerRead = false; + this._cancelTimeouts = source_core_noop; + this._removeListeners = source_core_noop; + this._jobs = []; + this._flushed = false; + this._requestInitialized = false; + this._aborted = false; + this.redirectUrls = []; + this.retryCount = 0; + this._stopRetry = source_core_noop; + this.on('pipe', (source) => { + if (source?.headers) { + Object.assign(this.options.headers, source.headers); + } + }); + 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_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; + } + catch (error) { + const { options } = error; + if (options) { + this.options = options; + } + this.flush = async () => { + this.flush = async () => { }; + this.destroy(error); + }; + 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 (dist.nodeStream(body)) { + body.once('error', error => { + if (this._flushed) { + this._beforeError(new errors_UploadError(error, this)); + } + else { + this.flush = async () => { + this.flush = async () => { }; + this._beforeError(new errors_UploadError(error, this)); + }; + } + }); + } + if (this.options.signal) { + const abort = () => { + this.destroy(new errors_AbortError(this)); + }; + if (this.options.signal.aborted) { + abort(); + } + else { + this.options.signal.addEventListener('abort', abort); + this._removeListeners = () => { + this.options.signal?.removeEventListener('abort', abort); + }; + } + } + } + async flush() { + if (this._flushed) { + return; + } + this._flushed = true; + try { + await this._finalizeBody(); + if (this.destroyed) { + return; + } + 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(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 errors_RequestError)) { + error = new errors_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. + // + // Furthermore, Node.js 16 `response.destroy()` doesn't immediately destroy the socket, + // but makes the response unreadable. So we additionally need to check `response.readable`. + if (response?.readable && !response.rawBody && !this._request?.socket?.destroyed) { + // @types/node has incorrect typings. `setEncoding` accepts `null` as well. + response.setEncoding(this.readableEncoding); + const success = await this._setRawBody(response); + if (success) { + response.body = response.rawBody.toString(); + } + } + 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; + } + } + const retryOptions = options.retry; + backoff = await retryOptions.calculateDelay({ + attemptCount, + retryOptions, + error: typedError, + retryAfter, + computedValue: core_calculate_retry_delay({ + attemptCount, + retryOptions, + error: typedError, + retryAfter, + computedValue: retryOptions.maxRetryAfter ?? options.timeout.request ?? Number.POSITIVE_INFINITY, + }), + }); + } + catch (error_) { + void this._error(new errors_RequestError(error_.message, error_, 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; + } + 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_) { + void this._error(new errors_RequestError(error_.message, error, this)); + return; + } + // Something forced us to abort the retry + if (this.destroyed) { + return; + } + this.destroy(); + this.emit('retry', this.retryCount + 1, error, (updatedOptions) => { + const request = new core_Request(options.url, 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 + const progress = this.downloadProgress; + if (progress.percent < 1) { + this.emit('downloadProgress', progress); + } + this.push(data); + } + } + } + _write(chunk, encoding, callback) { + const write = () => { + this._writeRequest(chunk, encoding, callback); + }; + if (this._requestInitialized) { + write(); + } + else { + this._jobs.push(write); + } + } + _final(callback) { + const endRequest = () => { + // We need to check if `this._request` is present, + // because it isn't when we use cache. + if (!this._request || this._request.destroyed) { + callback(); + return; + } + this._request.end((error) => { + // The request has been destroyed before `_final` finished. + // See https://github.com/nodejs/node/issues/39356 + if (this._request._writableState?.errored) { + return; + } + if (!error) { + this._bodySize = this._uploadedSize; + this.emit('uploadProgress', this.uploadProgress); + this._request.emit('upload-complete'); + } + callback(error); + }); + }; + 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._removeListeners(); + if (this.options) { + const { body } = this.options; + if (dist.nodeStream(body)) { + body.destroy(); + } + } + if (this._request) { + this._request.destroy(); + } + if (error !== null && !dist.undefined(error) && !(error instanceof errors_RequestError)) { + error = new errors_RequestError(error.message, error, this); + } + callback(error); + } + pipe(destination, options) { + if (destination instanceof external_node_http_namespaceObject.ServerResponse) { + this._pipedServerResponses.add(destination); + } + return super.pipe(destination, options); + } + unpipe(destination) { + if (destination instanceof external_node_http_namespaceObject.ServerResponse) { + this._pipedServerResponses.delete(destination); + } + super.unpipe(destination); + return this; + } + async _finalizeBody() { + const { options } = this; + const { headers } = options; + const isForm = !dist.undefined(options.form); + // eslint-disable-next-line @typescript-eslint/naming-convention + const isJSON = !dist.undefined(options.json); + const isBody = !dist.undefined(options.body); + const cannotHaveBody = core_methodsWithoutBody.has(options.method) && !(options.method === 'GET' && options.allowGetBody); + this._cannotHaveBody = cannotHaveBody; + if (isForm || isJSON || isBody) { + if (cannotHaveBody) { + throw new TypeError(`The \`${options.method}\` method cannot be used with a body`); + } + // Serialize body + const noContentType = !dist.string(headers['content-type']); + if (isBody) { + // Body is spec-compliant FormData + if (lib_isFormData(options.body)) { + const encoder = new FormDataEncoder(options.body); + if (noContentType) { + headers['content-type'] = encoder.headers['Content-Type']; + } + if ('Content-Length' in encoder.headers) { + headers['content-length'] = encoder.headers['Content-Length']; + } + options.body = encoder.encode(); + } + // Special case for https://github.com/form-data/form-data + if (utils_is_form_data_isFormData(options.body) && noContentType) { + headers['content-type'] = `multipart/form-data; boundary=${options.body.getBoundary()}`; + } + } + 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 = await get_body_size_getBodySize(options.body, 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 (dist.undefined(headers['content-length']) && dist.undefined(headers['transfer-encoding']) && !cannotHaveBody && !dist.undefined(uploadBodySize)) { + headers['content-length'] = String(uploadBodySize); + } + } + if (options.responseType === 'json' && !('accept' in options.headers)) { + options.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; + this._nativeResponse = response; + if (options.decompress) { + response = decompress_response(response); + } + const statusCode = response.statusCode; + const typedResponse = response; + typedResponse.statusMessage = typedResponse.statusMessage ?? external_node_http_namespaceObject.STATUS_CODES[statusCode]; + typedResponse.url = options.url.toString(); + typedResponse.requestUrl = this.requestUrl; + typedResponse.redirectUrls = this.redirectUrls; + typedResponse.request = this; + typedResponse.isFromCache = this._nativeResponse.fromCache ?? false; + typedResponse.ip = this.ip; + typedResponse.retryCount = this.retryCount; + typedResponse.ok = response_isResponseOk(typedResponse); + this._isFromCache = typedResponse.isFromCache; + this._responseSize = Number(response.headers['content-length']) || undefined; + this.response = typedResponse; + response.once('end', () => { + this._responseSize = this._downloadedSize; + this.emit('downloadProgress', this.downloadProgress); + }); + response.once('error', (error) => { + this._aborted = true; + // Force clean-up, because some packages don't do this. + // TODO: Fix decompress-response + response.destroy(); + this._beforeError(new errors_ReadError(error, this)); + }); + response.once('aborted', () => { + this._aborted = true; + this._beforeError(new errors_ReadError({ + name: 'Error', + message: 'The server aborted pending request', + code: 'ECONNRESET', + }, this)); + }); + this.emit('downloadProgress', this.downloadProgress); + const rawCookies = response.headers['set-cookie']; + if (dist.object(options.cookieJar) && rawCookies) { + let promises = rawCookies.map(async (rawCookie) => options.cookieJar.setCookie(rawCookie, url.toString())); + if (options.ignoreInvalidCookies) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + promises = promises.map(async (promise) => { + try { + await promise; + } + catch { } + }); + } + try { + await Promise.all(promises); + } + catch (error) { + this._beforeError(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 (response.headers.location && core_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. + const shouldFollow = typeof options.followRedirect === 'function' ? options.followRedirect(typedResponse) : options.followRedirect; + if (shouldFollow) { + response.resume(); + this._cancelTimeouts(); + this._unproxyEvents(); + if (this.redirectUrls.length >= options.maxRedirects) { + this._beforeError(new errors_MaxRedirectsError(this)); + return; + } + this._request = undefined; + const updatedOptions = new options_Options(undefined, undefined, this.options); + const serverRequestedGet = statusCode === 303 && updatedOptions.method !== 'GET' && updatedOptions.method !== 'HEAD'; + const canRewrite = statusCode !== 307 && statusCode !== 308; + const userRequestedGet = updatedOptions.methodRewriting && canRewrite; + if (serverRequestedGet || userRequestedGet) { + updatedOptions.method = 'GET'; + updatedOptions.body = undefined; + updatedOptions.json = undefined; + updatedOptions.form = undefined; + delete updatedOptions.headers['content-length']; + } + try { + // We need this in order to support UTF-8 + const redirectBuffer = external_node_buffer_namespaceObject.Buffer.from(response.headers.location, 'binary').toString(); + const redirectUrl = new URL(redirectBuffer, url); + if (!is_unix_socket_url_isUnixSocketURL(url) && is_unix_socket_url_isUnixSocketURL(redirectUrl)) { + this._beforeError(new errors_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 updatedOptions.headers) { + delete updatedOptions.headers.host; + } + if ('cookie' in updatedOptions.headers) { + delete updatedOptions.headers.cookie; + } + if ('authorization' in updatedOptions.headers) { + delete updatedOptions.headers.authorization; + } + if (updatedOptions.username || updatedOptions.password) { + updatedOptions.username = ''; + updatedOptions.password = ''; + } + } + else { + redirectUrl.username = updatedOptions.username; + redirectUrl.password = updatedOptions.password; + } + this.redirectUrls.push(redirectUrl); + updatedOptions.prefixUrl = ''; + updatedOptions.url = redirectUrl; + for (const hook of updatedOptions.hooks.beforeRedirect) { + // eslint-disable-next-line no-await-in-loop + await hook(updatedOptions, typedResponse); + } + this.emit('redirect', updatedOptions, typedResponse); + this.options = updatedOptions; + await this._makeRequest(); + } + catch (error) { + this._beforeError(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 && !response_isResponseOk(typedResponse)) { + this._beforeError(new errors_HTTPError(typedResponse)); + return; + } + response.on('readable', () => { + if (this._triggerRead) { + this._read(); + } + }); + this.on('resume', () => { + response.resume(); + }); + this.on('pause', () => { + response.pause(); + }); + response.once('end', () => { + this.push(null); + }); + if (this._noPipe) { + const success = await this._setRawBody(); + if (success) { + this.emit('response', response); + } + return; + } + this.emit('response', response); + for (const destination of this._pipedServerResponses) { + 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 _setRawBody(from = this) { + if (from.readableEnded) { + return false; + } + try { + // Errors are emitted via the `error` event + const rawBody = await buffer_getStreamAsBuffer(from); + // TODO: Switch to this: + // let rawBody = await from.toArray(); + // rawBody = Buffer.concat(rawBody); + // On retry Request is destroyed with no error, therefore the above will successfully resolve. + // So in order to check if this was really successfull, we need to check if it has been properly ended. + if (!this.isAborted) { + this.response.rawBody = rawBody; + return true; + } + } + catch { } + return false; + } + 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; + dist_source(request); + if (this.options.http2) { + // Unset stream timeout, as the `timeout` option was used only for connection timeout. + request.setTimeout(0); + } + this._cancelTimeouts = timed_out_timedOut(request, timeout, url); + const responseEventName = options.cache ? 'cacheableResponse' : 'response'; + request.once(responseEventName, (response) => { + void this._onResponse(response); + }); + request.once('error', (error) => { + this._aborted = true; + // Force clean-up, because some packages (e.g. nock) don't do this. + request.destroy(); + error = error instanceof core_timed_out_TimeoutError ? new errors_TimeoutError(error, this.timings, this) : new errors_RequestError(error.message, error, this); + this._beforeError(error); + }); + this._unproxyEvents = proxy_events_proxyEvents(request, this, core_proxiedRequestEvents); + this._request = request; + this.emit('uploadProgress', this.uploadProgress); + this._sendBody(); + this.emit('request', request); + } + async _asyncWrite(chunk) { + return new Promise((resolve, reject) => { + super.write(chunk, error => { + if (error) { + reject(error); + return; + } + resolve(); + }); + }); + } + _sendBody() { + // Send body + const { body } = this.options; + const currentRequest = this.redirectUrls.length === 0 ? this : this._request ?? this; + if (dist.nodeStream(body)) { + body.pipe(currentRequest); + } + else if (dist.generator(body) || dist.asyncGenerator(body)) { + (async () => { + try { + for await (const chunk of body) { + await this._asyncWrite(chunk); + } + super.end(); + } + catch (error) { + this._beforeError(error); + } + })(); + } + else if (!dist.undefined(body)) { + this._writeRequest(body, undefined, () => { }); + currentRequest.end(); + } + else if (this._cannotHaveBody || this._noPipe) { + currentRequest.end(); + } + } + _prepareCache(cache) { + if (!core_cacheableStore.has(cache)) { + const cacheableRequest = new cacheable_request_dist(((requestOptions, handler) => { + const result = requestOptions._request(requestOptions, handler); + // TODO: remove this when `cacheable-request` supports async request functions. + if (dist.promise(result)) { + // We only need to implement the error handler in order to support HTTP2 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') { + // 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 { } + })(); + } + else { + /* istanbul ignore next: safety check */ + throw new Error(`Unknown HTTP2 promise event: ${event}`); + } + return result; + }; + } + return result; + }), cache); + core_cacheableStore.set(cache, cacheableRequest.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_urlToOptions(url)); + let request; + // TODO: Fix `cacheable-response`. This is ugly. + const cacheRequest = core_cacheableStore.get(options.cache)(options, async (response) => { + response._readableState.autoDestroy = false; + if (request) { + const fix = () => { + if (response.req) { + response.complete = response.req.res.complete; + } + }; + response.prependOnceListener('end', fix); + fix(); + (await request).emit('cacheableResponse', response); + } + resolve(response); + }); + cacheRequest.once('error', reject); + cacheRequest.once('request', async (requestOrPromise) => { + request = requestOrPromise; + resolve(request); + }); + }); + } + async _makeRequest() { + const { options } = this; + const { headers, username, password } = options; + const cookieJar = options.cookieJar; + for (const key in headers) { + if (dist.undefined(headers[key])) { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete headers[key]; + } + else if (dist.null_(headers[key])) { + throw new TypeError(`Use \`undefined\` instead of \`null\` to delete the \`${key}\` header`); + } + } + if (options.decompress && dist.undefined(headers['accept-encoding'])) { + headers['accept-encoding'] = core_supportsBrotli ? 'gzip, deflate, br' : 'gzip, deflate'; + } + if (username || password) { + const credentials = external_node_buffer_namespaceObject.Buffer.from(`${username}:${password}`).toString('base64'); + headers.authorization = `Basic ${credentials}`; + } + // Set cookies + if (cookieJar) { + const cookieString = await cookieJar.getCookieString(options.url.toString()); + if (dist.nonEmptyString(cookieString)) { + headers.cookie = cookieString; + } + } + // Reset `prefixUrl` + options.prefixUrl = ''; + let request; + for (const hook of options.hooks.beforeRequest) { + // eslint-disable-next-line no-await-in-loop + const result = await hook(options); + if (!dist.undefined(result)) { + // @ts-expect-error Skip the type mismatch to support abstract responses + request = () => result; + break; + } + } + request ||= options.getRequestFunction(); + const url = options.url; + this._requestOptions = options.createNativeRequestOptions(); + if (options.cache) { + this._requestOptions._request = request; + this._requestOptions.cache = options.cache; + this._requestOptions.body = options.body; + this._prepareCache(options.cache); + } + // 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()`. + let requestOrResponse = function_(url, this._requestOptions); + if (dist.promise(requestOrResponse)) { + requestOrResponse = await requestOrResponse; + } + // Fallback + if (dist.undefined(requestOrResponse)) { + requestOrResponse = options.getFallbackRequestFunction()(url, this._requestOptions); + if (dist.promise(requestOrResponse)) { + requestOrResponse = await requestOrResponse; + } + } + if (utils_is_client_request(requestOrResponse)) { + this._onRequest(requestOrResponse); + } + else if (this.writable) { + this.once('finish', () => { + void this._onResponse(requestOrResponse); + }); + this._sendBody(); + } + else { + void this._onResponse(requestOrResponse); + } + } + catch (error) { + if (error instanceof types_CacheError) { + throw new errors_CacheError(error, this); + } + throw error; + } + } + async _error(error) { + try { + if (error instanceof errors_HTTPError && !this.options.throwHttpErrors) { + // This branch can be reached only when using the Promise API + // Skip calling the hooks on purpose. + // See https://github.com/sindresorhus/got/issues/2103 + } + else { + for (const hook of this.options.hooks.beforeError) { + // eslint-disable-next-line no-await-in-loop + error = await hook(error); + } + } + } + catch (error_) { + error = new errors_RequestError(error_.message, error_, this); + } + this.destroy(error); + } + _writeRequest(chunk, encoding, callback) { + if (!this._request || this._request.destroyed) { + // Probably the `ClientRequest` instance will throw + return; + } + this._request.write(chunk, encoding, (error) => { + // The `!destroyed` check is required to prevent `uploadProgress` being emitted after the stream was destroyed + if (!error && !this._request.destroyed) { + this._uploadedSize += external_node_buffer_namespaceObject.Buffer.byteLength(chunk, encoding); + 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() { + let percent; + if (this._responseSize) { + percent = this._downloadedSize / this._responseSize; + } + else if (this._responseSize === this._downloadedSize) { + percent = 1; + } + else { + percent = 0; + } + return { + percent, + transferred: this._downloadedSize, + total: this._responseSize, + }; + } + /** + Progress event for uploading (sending a request). + */ + get uploadProgress() { + let percent; + if (this._bodySize) { + percent = this._uploadedSize / this._bodySize; + } + else if (this._bodySize === this._uploadedSize) { + percent = 1; + } + else { + percent = 0; + } + return { + percent, + transferred: this._uploadedSize, + total: 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._isFromCache; + } + get reusedSocket() { + return this._request?.reusedSocket; + } +} + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/as-promise/types.js + +/** +An error to be thrown when the request is aborted with `.cancel()`. +*/ +class as_promise_types_CancelError extends errors_RequestError { + constructor(request) { + super('Promise was canceled', {}, request); + this.name = 'CancelError'; + this.code = 'ERR_CANCELED'; + } + /** + Whether the promise is canceled. + */ + get isCanceled() { + return true; + } +} + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/as-promise/index.js + + + + + + + + +const source_as_promise_proxiedRequestEvents = [ + 'request', + 'response', + 'redirect', + 'uploadProgress', + 'downloadProgress', +]; +function as_promise_asPromise(firstRequest) { + let globalRequest; + let globalResponse; + let normalizedOptions; + const emitter = new external_node_events_.EventEmitter(); + const promise = new PCancelable((resolve, reject, onCancel) => { + onCancel(() => { + globalRequest.destroy(); + }); + onCancel.shouldReject = false; + onCancel(() => { + reject(new as_promise_types_CancelError(globalRequest)); + }); + const makeRequest = (retryCount) => { + // Errors when a new request is made after the promise settles. + // Used to detect a race condition. + // See https://github.com/sindresorhus/got/issues/1489 + onCancel(() => { }); + const request = firstRequest ?? new core_Request(undefined, undefined, normalizedOptions); + request.retryCount = retryCount; + request._noPipe = true; + globalRequest = request; + request.once('response', async (response) => { + // Parse body + const contentEncoding = (response.headers['content-encoding'] ?? '').toLowerCase(); + const isCompressed = contentEncoding === 'gzip' || contentEncoding === 'deflate' || contentEncoding === 'br'; + const { options } = request; + if (isCompressed && !options.decompress) { + response.body = response.rawBody; + } + else { + try { + response.body = response_parseBody(response, options.responseType, options.parseJson, options.encoding); + } + catch (error) { + // Fall back to `utf8` + try { + response.body = response.rawBody.toString(); + } + catch (error) { + request._beforeError(new response_ParseError(error, response)); + return; + } + if (response_isResponseOk(response)) { + request._beforeError(error); + return; + } + } + } + try { + const hooks = options.hooks.afterResponse; + for (const [index, hook] of hooks.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) => { + options.merge(updatedOptions); + options.prefixUrl = ''; + if (updatedOptions.url) { + options.url = updatedOptions.url; + } + // Remove any further hooks for that request, because we'll call them anyway. + // The loop continues. We don't want duplicates (asPromise recursion). + options.hooks.afterResponse = options.hooks.afterResponse.slice(0, index); + throw new errors_RetryError(request); + }); + if (!(dist.object(response) && dist.number(response.statusCode) && !dist.nullOrUndefined(response.body))) { + throw new TypeError('The `afterResponse` hook returned an invalid value'); + } + } + } + catch (error) { + request._beforeError(error); + return; + } + globalResponse = response; + if (!response_isResponseOk(response)) { + request._beforeError(new errors_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 errors_HTTPError && !options.throwHttpErrors) { + const { response } = error; + request.destroy(); + resolve(request.options.resolveBodyOnly ? response.body : response); + return; + } + reject(error); + }; + request.once('error', onError); + const previousBody = request.options?.body; + request.once('retry', (newRetryCount, error) => { + firstRequest = undefined; + const newBody = request.options.body; + if (previousBody === newBody && dist.nodeStream(newBody)) { + 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()`. + normalizedOptions = request.options; + makeRequest(newRetryCount); + }); + proxy_events_proxyEvents(request, emitter, source_as_promise_proxiedRequestEvents); + if (dist.undefined(firstRequest)) { + void request.flush(); + } + }; + makeRequest(0); + }); + promise.on = (event, function_) => { + emitter.on(event, function_); + return promise; + }; + promise.off = (event, function_) => { + emitter.off(event, function_); + return promise; + }; + const shortcut = (responseType) => { + const newPromise = (async () => { + // Wait until downloading has ended + await promise; + const { options } = globalResponse.request; + return response_parseBody(globalResponse, responseType, options.parseJson, options.encoding); + })(); + // eslint-disable-next-line @typescript-eslint/no-floating-promises + Object.defineProperties(newPromise, Object.getOwnPropertyDescriptors(promise)); + return newPromise; + }; + promise.json = () => { + if (globalRequest.options) { + const { headers } = globalRequest.options; + if (!globalRequest.writableFinished && !('accept' in headers)) { + headers.accept = 'application/json'; + } + } + return shortcut('json'); + }; + promise.buffer = () => shortcut('buffer'); + promise.text = () => shortcut('text'); + return promise; +} + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/create.js + + + + +// The `delay` package weighs 10KB (!) +const create_delay = async (ms) => new Promise(resolve => { + setTimeout(resolve, ms); +}); +const create_isGotInstance = (value) => dist.function_(value); +const create_aliases = [ + 'get', + 'post', + 'put', + 'patch', + 'head', + 'delete', +]; +const create_create = (defaults) => { + defaults = { + options: new options_Options(undefined, undefined, defaults.options), + handlers: [...defaults.handlers], + mutableDefaults: defaults.mutableDefaults, + }; + Object.defineProperty(defaults, 'mutableDefaults', { + enumerable: true, + configurable: false, + writable: false, + }); + // Got interface + const got = ((url, options, defaultOptions = defaults.options) => { + const request = new core_Request(url, options, defaultOptions); + let promise; + const lastHandler = (normalized) => { + // Note: `options` is `undefined` when `new Options(...)` fails + request.options = normalized; + request._noPipe = !normalized.isStream; + void request.flush(); + if (normalized.isStream) { + return request; + } + promise ||= as_promise_asPromise(request); + return promise; + }; + let iteration = 0; + const iterateHandlers = (newOptions) => { + const handler = defaults.handlers[iteration++] ?? lastHandler; + const result = handler(newOptions, iterateHandlers); + if (dist.promise(result) && !request.options.isStream) { + promise ||= as_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); + result.cancel = promise.cancel; + } + } + return result; + }; + return iterateHandlers(request.options); + }); + got.extend = (...instancesOrOptions) => { + const options = new options_Options(undefined, undefined, defaults.options); + const handlers = [...defaults.handlers]; + let mutableDefaults; + for (const value of instancesOrOptions) { + if (create_isGotInstance(value)) { + options.merge(value.defaults.options); + handlers.push(...value.defaults.handlers); + mutableDefaults = value.defaults.mutableDefaults; + } + else { + options.merge(value); + if (value.handlers) { + handlers.push(...value.handlers); + } + mutableDefaults = value.mutableDefaults; + } + } + return create_create({ + options, + handlers, + mutableDefaults: Boolean(mutableDefaults), + }); + }; + // Pagination + const paginateEach = (async function* (url, options) { + let normalizedOptions = new options_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 create_delay(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 optionsToMerge = pagination.paginate({ + response, + currentItems, + allItems, + }); + if (optionsToMerge === false) { + return; + } + if (optionsToMerge === response.request.options) { + normalizedOptions = response.request.options; + } + else { + normalizedOptions.merge(optionsToMerge); + assert.any([dist.urlInstance, dist.undefined], optionsToMerge.url); + if (optionsToMerge.url !== undefined) { + normalizedOptions.prefixUrl = ''; + normalizedOptions.url = optionsToMerge.url; + } + } + 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 create_aliases) { + got[method] = ((url, options) => got(url, { ...options, method })); + got.stream[method] = ((url, options) => got(url, { ...options, method, isStream: 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 dist_source_create = (create_create); + +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/index.js + + +const source_defaults = { + options: new options_Options(), + handlers: [], + mutableDefaults: false, +}; +const source_got = dist_source_create(source_defaults); +/* harmony default export */ const node_modules_got_dist_source = (source_got); +// TODO: Remove this in the next major version. + + + + + + + + + + + + ;// CONCATENATED MODULE: ./dist/index.js // src/index.ts @@ -98130,7 +101713,7 @@ var NixInstallerAction = class extends DetSysAction { feat.payload ); try { - const resp = await got_dist_source.get(url, { + const resp = await node_modules_got_dist_source.get(url, { timeout: { request: timeoutMs } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 610bc8b..ed76fbc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ dependencies: version: 5.1.1 detsys-ts: specifier: github:DeterminateSystems/detsys-ts - version: github.com/DeterminateSystems/detsys-ts/7916bffbfacbe63ee24c4bf8649de649bd04f7b0 + version: github.com/DeterminateSystems/detsys-ts/dd1509475ee7fee37677b858b67aa96ef37a7531 got: specifier: ^14.3.0 version: 14.3.0 @@ -3245,6 +3245,26 @@ packages: responselike: 3.0.0 dev: false + /got@14.4.0: + resolution: + { + integrity: sha512-baa2HMfREJ9UQSXOPwWe0DNK+FT8Okcxe9kmTJvaetv2q/MUxq0qFzEnfSbxo+wj45/QioGcH5ZhuT9VBIPJ5Q==, + } + engines: { node: ">=20" } + dependencies: + "@sindresorhus/is": 6.3.1 + "@szmarczak/http-timer": 5.0.1 + cacheable-lookup: 7.0.0 + cacheable-request: 12.0.1 + decompress-response: 6.0.0 + form-data-encoder: 4.0.2 + get-stream: 8.0.1 + http2-wrapper: 2.2.1 + lowercase-keys: 3.0.0 + p-cancelable: 4.0.1 + responselike: 3.0.0 + dev: false + /graceful-fs@4.2.11: resolution: { @@ -5114,6 +5134,14 @@ packages: engines: { node: ">=10" } dev: true + /type-fest@4.19.0: + resolution: + { + integrity: sha512-CN2l+hWACRiejlnr68vY0/7734Kzu+9+TOslUXbSCQ1ruY9XIHDBSceVXCcHm/oXrdzhtLMMdJEKfemf1yXiZQ==, + } + engines: { node: ">=16" } + dev: false + /typed-array-buffer@1.0.2: resolution: { @@ -5435,10 +5463,10 @@ packages: engines: { node: ">=10" } dev: true - github.com/DeterminateSystems/detsys-ts/7916bffbfacbe63ee24c4bf8649de649bd04f7b0: + github.com/DeterminateSystems/detsys-ts/dd1509475ee7fee37677b858b67aa96ef37a7531: resolution: { - tarball: https://codeload.github.com/DeterminateSystems/detsys-ts/tar.gz/7916bffbfacbe63ee24c4bf8649de649bd04f7b0, + tarball: https://codeload.github.com/DeterminateSystems/detsys-ts/tar.gz/dd1509475ee7fee37677b858b67aa96ef37a7531, } name: detsys-ts version: 1.0.0 @@ -5446,7 +5474,8 @@ packages: "@actions/cache": 3.2.4 "@actions/core": 1.10.1 "@actions/exec": 1.1.1 - got: 14.3.0 + got: 14.4.0 + type-fest: 4.19.0 transitivePeerDependencies: - encoding dev: false