diff options
author | RaindropsSys <contact@minteck.org> | 2023-04-06 22:18:28 +0200 |
---|---|---|
committer | RaindropsSys <contact@minteck.org> | 2023-04-06 22:18:28 +0200 |
commit | 83354b2b88218090988dd6e526b0a2505b57e0f1 (patch) | |
tree | e3c73c38a122a78bb7e66fbb99056407edd9d4b9 /includes/external/addressbook/node_modules/got/dist/source | |
parent | 47b8f2299a483024c4a6a8876af825a010954caa (diff) | |
download | pluralconnect-83354b2b88218090988dd6e526b0a2505b57e0f1.tar.gz pluralconnect-83354b2b88218090988dd6e526b0a2505b57e0f1.tar.bz2 pluralconnect-83354b2b88218090988dd6e526b0a2505b57e0f1.zip |
Updated 5 files and added 1110 files (automated)
Diffstat (limited to 'includes/external/addressbook/node_modules/got/dist/source')
42 files changed, 5832 insertions, 0 deletions
diff --git a/includes/external/addressbook/node_modules/got/dist/source/as-promise/index.d.ts b/includes/external/addressbook/node_modules/got/dist/source/as-promise/index.d.ts new file mode 100644 index 0000000..e560880 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/as-promise/index.d.ts @@ -0,0 +1,3 @@ +import Request from '../core/index.js'; +import { type CancelableRequest } from './types.js'; +export default function asPromise<T>(firstRequest?: Request): CancelableRequest<T>; diff --git a/includes/external/addressbook/node_modules/got/dist/source/as-promise/index.js b/includes/external/addressbook/node_modules/got/dist/source/as-promise/index.js new file mode 100644 index 0000000..d91fd09 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/as-promise/index.js @@ -0,0 +1,158 @@ +import { EventEmitter } from 'node:events'; +import is from '@sindresorhus/is'; +import PCancelable from 'p-cancelable'; +import { HTTPError, RetryError, } from '../core/errors.js'; +import Request from '../core/index.js'; +import { parseBody, isResponseOk } from '../core/response.js'; +import proxyEvents from '../core/utils/proxy-events.js'; +import { CancelError } from './types.js'; +const proxiedRequestEvents = [ + 'request', + 'response', + 'redirect', + 'uploadProgress', + 'downloadProgress', +]; +export default function asPromise(firstRequest) { + let globalRequest; + let globalResponse; + let normalizedOptions; + const emitter = new EventEmitter(); + const promise = new PCancelable((resolve, reject, onCancel) => { + onCancel(() => { + globalRequest.destroy(); + }); + onCancel.shouldReject = false; + onCancel(() => { + reject(new 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 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 = parseBody(response, options.responseType, options.parseJson, options.encoding); + } + catch (error) { + // Fall back to `utf8` + response.body = response.rawBody.toString(); + if (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 RetryError(request); + }); + if (!(is.object(response) && is.number(response.statusCode) && !is.nullOrUndefined(response.body))) { + throw new TypeError('The `afterResponse` hook returned an invalid value'); + } + } + } + catch (error) { + request._beforeError(error); + return; + } + globalResponse = response; + if (!isResponseOk(response)) { + request._beforeError(new 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 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 && is.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); + }); + proxyEvents(request, emitter, proxiedRequestEvents); + if (is.undefined(firstRequest)) { + void request.flush(); + } + }; + makeRequest(0); + }); + promise.on = (event, fn) => { + emitter.on(event, fn); + return promise; + }; + promise.off = (event, fn) => { + emitter.off(event, fn); + return promise; + }; + const shortcut = (responseType) => { + const newPromise = (async () => { + // Wait until downloading has ended + await promise; + const { options } = globalResponse.request; + return 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; +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/as-promise/types.d.ts b/includes/external/addressbook/node_modules/got/dist/source/as-promise/types.d.ts new file mode 100644 index 0000000..929ce09 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/as-promise/types.d.ts @@ -0,0 +1,38 @@ +/// <reference types="node" resolution-mode="require"/> +import type { Buffer } from 'node:buffer'; +import type PCancelable from 'p-cancelable'; +import { RequestError } from '../core/errors.js'; +import type Request from '../core/index.js'; +import type { RequestEvents } from '../core/index.js'; +import type { Response } from '../core/response.js'; +/** +An error to be thrown when the request is aborted with `.cancel()`. +*/ +export declare class CancelError extends RequestError { + readonly response: Response; + constructor(request: Request); + /** + Whether the promise is canceled. + */ + get isCanceled(): boolean; +} +export interface CancelableRequest<T extends Response | Response['body'] = Response['body']> extends PCancelable<T>, RequestEvents<CancelableRequest<T>> { + /** + A shortcut method that gives a Promise returning a JSON object. + + It is semantically the same as settings `options.resolveBodyOnly` to `true` and `options.responseType` to `'json'`. + */ + json: <ReturnType>() => CancelableRequest<ReturnType>; + /** + A shortcut method that gives a Promise returning a [Buffer](https://nodejs.org/api/buffer.html). + + It is semantically the same as settings `options.resolveBodyOnly` to `true` and `options.responseType` to `'buffer'`. + */ + buffer: () => CancelableRequest<Buffer>; + /** + A shortcut method that gives a Promise returning a string. + + It is semantically the same as settings `options.resolveBodyOnly` to `true` and `options.responseType` to `'text'`. + */ + text: () => CancelableRequest<string>; +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/as-promise/types.js b/includes/external/addressbook/node_modules/got/dist/source/as-promise/types.js new file mode 100644 index 0000000..eda617e --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/as-promise/types.js @@ -0,0 +1,17 @@ +import { RequestError } from '../core/errors.js'; +/** +An error to be thrown when the request is aborted with `.cancel()`. +*/ +export class CancelError extends RequestError { + constructor(request) { + super('Promise was canceled', {}, request); + this.name = 'CancelError'; + this.code = 'ERR_CANCELED'; + } + /** + Whether the promise is canceled. + */ + get isCanceled() { + return true; + } +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/calculate-retry-delay.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/calculate-retry-delay.d.ts new file mode 100644 index 0000000..c38ae4d --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/calculate-retry-delay.d.ts @@ -0,0 +1,4 @@ +import type { RetryFunction } from './options.js'; +type Returns<T extends (...args: any) => unknown, V> = (...args: Parameters<T>) => V; +declare const calculateRetryDelay: Returns<RetryFunction, number>; +export default calculateRetryDelay; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/calculate-retry-delay.js b/includes/external/addressbook/node_modules/got/dist/source/core/calculate-retry-delay.js new file mode 100644 index 0000000..5407da8 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/calculate-retry-delay.js @@ -0,0 +1,29 @@ +const calculateRetryDelay = ({ attemptCount, retryOptions, error, retryAfter, computedValue, }) => { + if (error.name === 'RetryError') { + return 1; + } + if (attemptCount > retryOptions.limit) { + return 0; + } + const hasMethod = retryOptions.methods.includes(error.options.method); + const hasErrorCode = retryOptions.errorCodes.includes(error.code); + const hasStatusCode = error.response && retryOptions.statusCodes.includes(error.response.statusCode); + if (!hasMethod || (!hasErrorCode && !hasStatusCode)) { + return 0; + } + if (error.response) { + if (retryAfter) { + // In this case `computedValue` is `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; +}; +export default calculateRetryDelay; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/errors.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/errors.d.ts new file mode 100644 index 0000000..735d4d2 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/errors.d.ts @@ -0,0 +1,90 @@ +/// <reference types="node" resolution-mode="require"/> +import type { Timings } from '@szmarczak/http-timer'; +import type Options from './options.js'; +import type { TimeoutError as TimedOutTimeoutError } from './timed-out.js'; +import type { PlainResponse, Response } from './response.js'; +import type Request from './index.js'; +type Error = NodeJS.ErrnoException; +/** +An error to be thrown when a request fails. +Contains a `code` property with error class code, like `ECONNREFUSED`. +*/ +export declare class RequestError extends Error { + input?: string; + code: string; + stack: string; + readonly options: Options; + readonly response?: Response; + readonly request?: Request; + readonly timings?: Timings; + constructor(message: string, error: Partial<Error & { + code?: string; + }>, self: Request | Options); +} +/** +An error to be thrown when the server redirects you more than ten times. +Includes a `response` property. +*/ +export declare class MaxRedirectsError extends RequestError { + readonly response: Response; + readonly request: Request; + readonly timings: Timings; + constructor(request: Request); +} +/** +An error to be thrown when the server response code is not 2xx nor 3xx if `options.followRedirect` is `true`, but always except for 304. +Includes a `response` property. +*/ +export declare class HTTPError extends RequestError { + readonly response: Response; + readonly request: Request; + readonly timings: Timings; + constructor(response: PlainResponse); +} +/** +An error to be thrown when a cache method fails. +For example, if the database goes down or there's a filesystem error. +*/ +export declare class CacheError extends RequestError { + readonly request: Request; + constructor(error: Error, request: Request); +} +/** +An error to be thrown when the request body is a stream and an error occurs while reading from that stream. +*/ +export declare class UploadError extends RequestError { + readonly request: Request; + constructor(error: Error, request: Request); +} +/** +An error to be thrown when the request is aborted due to a timeout. +Includes an `event` and `timings` property. +*/ +export declare class TimeoutError extends RequestError { + readonly request: Request; + readonly timings: Timings; + readonly event: string; + constructor(error: TimedOutTimeoutError, timings: Timings, request: Request); +} +/** +An error to be thrown when reading from response stream fails. +*/ +export declare class ReadError extends RequestError { + readonly request: Request; + readonly response: Response; + readonly timings: Timings; + constructor(error: Error, request: Request); +} +/** +An error which always triggers a new retry when thrown. +*/ +export declare class RetryError extends RequestError { + constructor(request: Request); +} +/** +An error to be thrown when the request is aborted by AbortController. +*/ +export declare class AbortError extends RequestError { + constructor(request: Request); +} +export {}; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/errors.js b/includes/external/addressbook/node_modules/got/dist/source/core/errors.js new file mode 100644 index 0000000..f8e1c98 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/errors.js @@ -0,0 +1,178 @@ +import is from '@sindresorhus/is'; +// A hacky check to prevent circular references. +function isRequest(x) { + return is.object(x) && '_onResponse' in x; +} +/** +An error to be thrown when a request fails. +Contains a `code` property with error class code, like `ECONNREFUSED`. +*/ +export class RequestError extends Error { + constructor(message, error, self) { + super(message); + Object.defineProperty(this, "input", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "code", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "stack", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "response", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "request", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "timings", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Error.captureStackTrace(this, this.constructor); + this.name = 'RequestError'; + this.code = error.code ?? 'ERR_GOT_REQUEST_ERROR'; + this.input = error.input; + if (isRequest(self)) { + Object.defineProperty(this, 'request', { + enumerable: false, + value: self, + }); + Object.defineProperty(this, 'response', { + enumerable: false, + value: self.response, + }); + this.options = self.options; + } + else { + this.options = self; + } + this.timings = this.request?.timings; + // Recover the original stacktrace + if (is.string(error.stack) && is.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. +*/ +export class MaxRedirectsError extends 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. +*/ +// eslint-disable-next-line @typescript-eslint/naming-convention +export class HTTPError extends RequestError { + constructor(response) { + super(`Response code ${response.statusCode} (${response.statusMessage})`, {}, response.request); + this.name = 'HTTPError'; + this.code = 'ERR_NON_2XX_3XX_RESPONSE'; + } +} +/** +An error to be thrown when a cache method fails. +For example, if the database goes down or there's a filesystem error. +*/ +export class CacheError extends RequestError { + constructor(error, request) { + super(error.message, error, request); + this.name = 'CacheError'; + this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_CACHE_ACCESS' : this.code; + } +} +/** +An error to be thrown when the request body is a stream and an error occurs while reading from that stream. +*/ +export class UploadError extends RequestError { + constructor(error, request) { + super(error.message, error, request); + this.name = 'UploadError'; + this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_UPLOAD' : this.code; + } +} +/** +An error to be thrown when the request is aborted due to a timeout. +Includes an `event` and `timings` property. +*/ +export class TimeoutError extends RequestError { + constructor(error, timings, request) { + super(error.message, error, request); + Object.defineProperty(this, "timings", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "event", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + this.name = 'TimeoutError'; + this.event = error.event; + this.timings = timings; + } +} +/** +An error to be thrown when reading from response stream fails. +*/ +export class ReadError extends RequestError { + constructor(error, request) { + super(error.message, error, request); + this.name = 'ReadError'; + this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_READING_RESPONSE_STREAM' : this.code; + } +} +/** +An error which always triggers a new retry when thrown. +*/ +export class RetryError extends 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. +*/ +export class AbortError extends RequestError { + constructor(request) { + super('This operation was aborted.', {}, request); + this.code = 'ERR_ABORTED'; + this.name = 'AbortError'; + } +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/index.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/index.d.ts new file mode 100644 index 0000000..c041758 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/index.d.ts @@ -0,0 +1,191 @@ +/// <reference types="node" resolution-mode="require"/> +/// <reference types="node" resolution-mode="require"/> +/// <reference types="node" resolution-mode="require"/> +/// <reference types="node" resolution-mode="require"/> +/// <reference types="node" resolution-mode="require"/> +import { Duplex } from 'node:stream'; +import { URL } from 'node:url'; +import type { ClientRequest } from 'node:http'; +import type { Socket } from 'node:net'; +import type { Timings } from '@szmarczak/http-timer'; +import Options from './options.js'; +import { type PlainResponse, type Response } from './response.js'; +import { RequestError } from './errors.js'; +type Error = NodeJS.ErrnoException; +export type Progress = { + percent: number; + transferred: number; + total?: number; +}; +export type GotEventFunction<T> = +/** +`request` event to get the request object of the request. + + __Tip__: You can use `request` event to abort requests. + +@example +``` +import got from 'got'; + +got.stream('https://github.com') + .on('request', request => setTimeout(() => request.destroy(), 50)); +``` +*/ +((name: 'request', listener: (request: ClientRequest) => void) => T) +/** +The `response` event to get the response object of the final request. +*/ + & (<R extends Response>(name: 'response', listener: (response: R) => void) => T) +/** +The `redirect` event to get the response object of a redirect. The second argument is options for the next request to the redirect location. +*/ + & (<R extends Response, N extends Options>(name: 'redirect', listener: (response: R, nextOptions: N) => void) => T) +/** +Progress events for uploading (sending a request) and downloading (receiving a response). +The `progress` argument is an object like: + +``` +{ + percent: 0.1, + transferred: 1024, + total: 10240 +} +``` + +If the `content-length` header is missing, `total` will be `undefined`. + +@example +``` +import got from 'got'; + +const response = await got('https://sindresorhus.com') + .on('downloadProgress', progress => { + // Report download progress + }) + .on('uploadProgress', progress => { + // Report upload progress + }); + +console.log(response); +``` +*/ + & ((name: 'uploadProgress' | 'downloadProgress', listener: (progress: Progress) => void) => T) +/** +To enable retrying on a Got stream, it is required to have a `retry` handler attached. + +When this event is emitted, you should reset the stream you were writing to and prepare the body again. + +See `got.options.retry` for more information. +*/ + & ((name: 'retry', listener: (retryCount: number, error: RequestError) => void) => T); +export type RequestEvents<T> = { + on: GotEventFunction<T>; + once: GotEventFunction<T>; + off: GotEventFunction<T>; +}; +type UrlType = ConstructorParameters<typeof Options>[0]; +type OptionsType = ConstructorParameters<typeof Options>[1]; +type DefaultsType = ConstructorParameters<typeof Options>[2]; +export default class Request extends Duplex implements RequestEvents<Request> { + ['constructor']: typeof Request; + _noPipe?: boolean; + options: Options; + response?: PlainResponse; + requestUrl?: URL; + redirectUrls: URL[]; + retryCount: number; + private _requestOptions; + private _stopRetry; + private _downloadedSize; + private _uploadedSize; + private _stopReading; + private readonly _pipedServerResponses; + private _request?; + private _responseSize?; + private _bodySize?; + private _unproxyEvents; + private _isFromCache?; + private _cannotHaveBody; + private _triggerRead; + private _jobs; + private _cancelTimeouts; + private readonly _removeListeners; + private _nativeResponse?; + private _flushed; + private _aborted; + private _requestInitialized; + constructor(url: UrlType, options?: OptionsType, defaults?: DefaultsType); + flush(): Promise<void>; + _beforeError(error: Error): void; + _read(): void; + _write(chunk: unknown, encoding: BufferEncoding | undefined, callback: (error?: Error | null) => void): void; + _final(callback: (error?: Error | null) => void): void; + _destroy(error: Error | null, callback: (error: Error | null) => void): void; + pipe<T extends NodeJS.WritableStream>(destination: T, options?: { + end?: boolean; + }): T; + unpipe<T extends NodeJS.WritableStream>(destination: T): this; + private _finalizeBody; + private _onResponseBase; + private _setRawBody; + private _onResponse; + private _onRequest; + private _asyncWrite; + private _sendBody; + private _prepareCache; + private _createCacheableRequest; + private _makeRequest; + private _error; + private _writeRequest; + /** + The remote IP address. + */ + get ip(): string | undefined; + /** + Indicates whether the request has been aborted or not. + */ + get isAborted(): boolean; + get socket(): Socket | undefined; + /** + Progress event for downloading (receiving a response). + */ + get downloadProgress(): Progress; + /** + Progress event for uploading (sending a request). + */ + get uploadProgress(): Progress; + /** + 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(): Timings | undefined; + /** + Whether the response was retrieved from the cache. + */ + get isFromCache(): boolean | undefined; + get reusedSocket(): boolean | undefined; +} +export {}; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/index.js b/includes/external/addressbook/node_modules/got/dist/source/core/index.js new file mode 100644 index 0000000..4f0bfd3 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/index.js @@ -0,0 +1,1124 @@ +import process from 'node:process'; +import { Buffer } from 'node:buffer'; +import { Duplex } from 'node:stream'; +import { URL, URLSearchParams } from 'node:url'; +import http, { ServerResponse } from 'node:http'; +import timer from '@szmarczak/http-timer'; +import CacheableRequest, { CacheError as CacheableCacheError, } from 'cacheable-request'; +import decompressResponse from 'decompress-response'; +import is from '@sindresorhus/is'; +import { buffer as getBuffer } from 'get-stream'; +import { FormDataEncoder, isFormData as isFormDataLike } from 'form-data-encoder'; +import getBodySize from './utils/get-body-size.js'; +import isFormData from './utils/is-form-data.js'; +import proxyEvents from './utils/proxy-events.js'; +import timedOut, { TimeoutError as TimedOutTimeoutError } from './timed-out.js'; +import urlToOptions from './utils/url-to-options.js'; +import WeakableMap from './utils/weakable-map.js'; +import calculateRetryDelay from './calculate-retry-delay.js'; +import Options from './options.js'; +import { isResponseOk } from './response.js'; +import isClientRequest from './utils/is-client-request.js'; +import isUnixSocketURL from './utils/is-unix-socket-url.js'; +import { RequestError, ReadError, MaxRedirectsError, HTTPError, TimeoutError, UploadError, CacheError, AbortError, } from './errors.js'; +const supportsBrotli = is.string(process.versions.brotli); +const methodsWithoutBody = new Set(['GET', 'HEAD']); +const cacheableStore = new WeakableMap(); +const redirectCodes = new Set([300, 301, 302, 303, 304, 307, 308]); +const proxiedRequestEvents = [ + 'socket', + 'connect', + 'continue', + 'information', + 'upgrade', +]; +const noop = () => { }; +export default class Request extends Duplex { + 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, + }); + // @ts-expect-error - Ignoring for now. + Object.defineProperty(this, 'constructor', { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_noPipe", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + // @ts-expect-error https://github.com/microsoft/TypeScript/issues/9568 + Object.defineProperty(this, "options", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "response", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "requestUrl", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "redirectUrls", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "retryCount", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_stopRetry", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_downloadedSize", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_uploadedSize", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_stopReading", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_pipedServerResponses", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_request", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_responseSize", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_bodySize", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_unproxyEvents", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_isFromCache", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_cannotHaveBody", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_triggerRead", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_cancelTimeouts", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_removeListeners", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_nativeResponse", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_flushed", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_aborted", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + // We need this because `this._request` if `undefined` when using cache + Object.defineProperty(this, "_requestInitialized", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + this._downloadedSize = 0; + this._uploadedSize = 0; + this._stopReading = false; + this._pipedServerResponses = new Set(); + this._cannotHaveBody = false; + this._unproxyEvents = noop; + this._triggerRead = false; + this._cancelTimeouts = noop; + this._removeListeners = noop; + this._jobs = []; + this._flushed = false; + this._requestInitialized = false; + this._aborted = false; + this.redirectUrls = []; + this.retryCount = 0; + this._stopRetry = 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(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 (is.nodeStream(body)) { + body.once('error', error => { + if (this._flushed) { + this._beforeError(new UploadError(error, this)); + } + else { + this.flush = async () => { + this.flush = async () => { }; + this._beforeError(new UploadError(error, this)); + }; + } + }); + } + if (this.options.signal) { + const abort = () => { + this.destroy(new 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 RequestError)) { + error = new RequestError(error.message, error, this); + } + const typedError = error; + void (async () => { + // Node.js parser is really weird. + // It emits post-request Parse Errors on the same instance as previous request. WTF. + // Therefore we need to check if it has been destroyed as well. + // + // 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: calculateRetryDelay({ + attemptCount, + retryOptions, + error: typedError, + retryAfter, + computedValue: retryOptions.maxRetryAfter ?? options.timeout.request ?? Number.POSITIVE_INFINITY, + }), + }); + } + catch (error_) { + void this._error(new 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 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 Request(options.url, updatedOptions, options); + request.retryCount = this.retryCount + 1; + 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 (is.nodeStream(body)) { + body.destroy(); + } + } + if (this._request) { + this._request.destroy(); + } + if (error !== null && !is.undefined(error) && !(error instanceof RequestError)) { + error = new RequestError(error.message, error, this); + } + callback(error); + } + pipe(destination, options) { + if (destination instanceof ServerResponse) { + this._pipedServerResponses.add(destination); + } + return super.pipe(destination, options); + } + unpipe(destination) { + if (destination instanceof ServerResponse) { + this._pipedServerResponses.delete(destination); + } + super.unpipe(destination); + return this; + } + async _finalizeBody() { + const { options } = this; + const { headers } = options; + const isForm = !is.undefined(options.form); + // eslint-disable-next-line @typescript-eslint/naming-convention + const isJSON = !is.undefined(options.json); + const isBody = !is.undefined(options.body); + const cannotHaveBody = 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 = !is.string(headers['content-type']); + if (isBody) { + // Body is spec-compliant FormData + if (isFormDataLike(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 (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 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 (is.undefined(headers['content-length']) && is.undefined(headers['transfer-encoding']) && !cannotHaveBody && !is.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 = decompressResponse(response); + } + const statusCode = response.statusCode; + const typedResponse = response; + typedResponse.statusMessage = typedResponse.statusMessage ?? http.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 = 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 ReadError(error, this)); + }); + response.once('aborted', () => { + this._aborted = true; + this._beforeError(new ReadError({ + name: 'Error', + message: 'The server aborted pending request', + code: 'ECONNRESET', + }, this)); + }); + this.emit('downloadProgress', this.downloadProgress); + const rawCookies = response.headers['set-cookie']; + if (is.object(options.cookieJar) && rawCookies) { + let promises = rawCookies.map(async (rawCookie) => options.cookieJar.setCookie(rawCookie, url.toString())); + if (options.ignoreInvalidCookies) { + promises = promises.map(async (promise) => { + try { + await promise; + } + catch { } + }); + } + try { + await Promise.all(promises); + } + catch (error) { + 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 (options.followRedirect && response.headers.location && redirectCodes.has(statusCode)) { + // We're being redirected, we don't care about the response. + // It'd be best to abort the request, but we can't because + // we would have to sacrifice the TCP connection. We don't want that. + response.resume(); + this._cancelTimeouts(); + this._unproxyEvents(); + if (this.redirectUrls.length >= options.maxRedirects) { + this._beforeError(new MaxRedirectsError(this)); + return; + } + this._request = undefined; + const updatedOptions = new 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 = Buffer.from(response.headers.location, 'binary').toString(); + const redirectUrl = new URL(redirectBuffer, url); + if (!isUnixSocketURL(url) && isUnixSocketURL(redirectUrl)) { + this._beforeError(new RequestError('Cannot redirect to UNIX socket', {}, this)); + return; + } + // Redirecting to a different site, clear sensitive data. + if (redirectUrl.hostname !== url.hostname || redirectUrl.port !== url.port) { + if ('host' in 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 && !isResponseOk(typedResponse)) { + this._beforeError(new 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 getBuffer(from); + // 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; + timer(request); + if (this.options.http2) { + // Unset stream timeout, as the `timeout` option was used only for connection timeout. + request.setTimeout(0); + } + this._cancelTimeouts = 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 TimedOutTimeoutError ? new TimeoutError(error, this.timings, this) : new RequestError(error.message, error, this); + this._beforeError(error); + }); + this._unproxyEvents = proxyEvents(request, this, 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 (is.nodeStream(body)) { + body.pipe(currentRequest); + } + else if (is.generator(body) || is.asyncGenerator(body)) { + (async () => { + try { + for await (const chunk of body) { + await this._asyncWrite(chunk); + } + super.end(); + } + catch (error) { + this._beforeError(error); + } + })(); + } + else if (!is.undefined(body)) { + this._writeRequest(body, undefined, () => { }); + currentRequest.end(); + } + else if (this._cannotHaveBody || this._noPipe) { + currentRequest.end(); + } + } + _prepareCache(cache) { + if (!cacheableStore.has(cache)) { + const cacheableRequest = new CacheableRequest(((requestOptions, handler) => { + const result = requestOptions._request(requestOptions, handler); + // TODO: remove this when `cacheable-request` supports async request functions. + if (is.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 + // eslint-disable-next-line @typescript-eslint/promise-function-async + 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); + 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, urlToOptions(url)); + let request; + // TODO: Fix `cacheable-response`. This is ugly. + const cacheRequest = 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 (is.undefined(headers[key])) { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete headers[key]; + } + else if (is.null_(headers[key])) { + throw new TypeError(`Use \`undefined\` instead of \`null\` to delete the \`${key}\` header`); + } + } + if (options.decompress && is.undefined(headers['accept-encoding'])) { + headers['accept-encoding'] = supportsBrotli ? 'gzip, deflate, br' : 'gzip, deflate'; + } + if (username || password) { + const credentials = Buffer.from(`${username}:${password}`).toString('base64'); + headers.authorization = `Basic ${credentials}`; + } + // Set cookies + if (cookieJar) { + const cookieString = await cookieJar.getCookieString(options.url.toString()); + if (is.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 (!is.undefined(result)) { + // @ts-expect-error Skip the type mismatch to support abstract responses + request = () => result; + break; + } + } + if (!request) { + 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 fn = options.cache ? this._createCacheableRequest : request; + try { + // We can't do `await fn(...)`, + // because stream `error` event can be emitted before `Promise.resolve()`. + let requestOrResponse = fn(url, this._requestOptions); + if (is.promise(requestOrResponse)) { + requestOrResponse = await requestOrResponse; + } + // Fallback + if (is.undefined(requestOrResponse)) { + requestOrResponse = options.getFallbackRequestFunction()(url, this._requestOptions); + if (is.promise(requestOrResponse)) { + requestOrResponse = await requestOrResponse; + } + } + if (isClientRequest(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 CacheableCacheError) { + throw new CacheError(error, this); + } + throw error; + } + } + async _error(error) { + try { + if (error instanceof 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 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 += 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; + } +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/options.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/options.d.ts new file mode 100644 index 0000000..e6d6788 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/options.d.ts @@ -0,0 +1,1255 @@ +/// <reference types="node" resolution-mode="require"/> +/// <reference types="node" resolution-mode="require"/> +/// <reference types="node" resolution-mode="require"/> +/// <reference types="node" resolution-mode="require"/> +/// <reference types="node" resolution-mode="require"/> +/// <reference types="node" resolution-mode="require"/> +/// <reference types="node" resolution-mode="require"/> +/// <reference types="node" resolution-mode="require"/> +/// <reference types="node" resolution-mode="require"/> +import type { Buffer } from 'node:buffer'; +import { URL, URLSearchParams } from 'node:url'; +import { checkServerIdentity } from 'node:tls'; +import http from 'node:http'; +import https from 'node:https'; +import type { Readable } from 'node:stream'; +import type { Socket } from 'node:net'; +import type { SecureContextOptions, DetailedPeerCertificate } from 'node:tls'; +import type { Agent as HttpAgent, ClientRequest } from 'node:http'; +import type { RequestOptions as HttpsRequestOptions, Agent as HttpsAgent } from 'node:https'; +import CacheableLookup from 'cacheable-lookup'; +import http2wrapper, { type ClientHttp2Session } from 'http2-wrapper'; +import type { FormDataLike } from 'form-data-encoder'; +import type { StorageAdapter } from 'cacheable-request'; +import type ResponseLike from 'responselike'; +import type { IncomingMessageWithTimings } from '@szmarczak/http-timer'; +import type { CancelableRequest } from '../as-promise/types.js'; +import type { PlainResponse, Response } from './response.js'; +import type { RequestError } from './errors.js'; +import type { Delays } from './timed-out.js'; +type Promisable<T> = T | Promise<T>; +export type DnsLookupIpVersion = undefined | 4 | 6; +type Except<ObjectType, KeysType extends keyof ObjectType> = Pick<ObjectType, Exclude<keyof ObjectType, KeysType>>; +export type NativeRequestOptions = HttpsRequestOptions & CacheOptions & { + checkServerIdentity?: CheckServerIdentityFunction; +}; +type AcceptableResponse = IncomingMessageWithTimings | ResponseLike; +type AcceptableRequestResult = Promisable<AcceptableResponse | ClientRequest> | undefined; +export type RequestFunction = (url: URL, options: NativeRequestOptions, callback?: (response: AcceptableResponse) => void) => AcceptableRequestResult; +export type Agents = { + http?: HttpAgent | false; + https?: HttpsAgent | false; + http2?: unknown | false; +}; +export type Headers = Record<string, string | string[] | undefined>; +export type ToughCookieJar = { + getCookieString: ((currentUrl: string, options: Record<string, unknown>, cb: (error: Error | null, cookies: string) => void) => void) & ((url: string, callback: (error: Error | null, cookieHeader: string) => void) => void); + setCookie: ((cookieOrString: unknown, currentUrl: string, options: Record<string, unknown>, cb: (error: Error | null, cookie: unknown) => void) => void) & ((rawCookie: string, url: string, callback: (error: Error | null, result: unknown) => void) => void); +}; +export type PromiseCookieJar = { + getCookieString: (url: string) => Promise<string>; + setCookie: (rawCookie: string, url: string) => Promise<unknown>; +}; +export type InitHook = (init: OptionsInit, self: Options) => void; +export type BeforeRequestHook = (options: Options) => Promisable<void | Response | ResponseLike>; +export type BeforeRedirectHook = (updatedOptions: Options, plainResponse: PlainResponse) => Promisable<void>; +export type BeforeErrorHook = (error: RequestError) => Promisable<RequestError>; +export type BeforeRetryHook = (error: RequestError, retryCount: number) => Promisable<void>; +export type AfterResponseHook<ResponseType = unknown> = (response: Response<ResponseType>, retryWithMergedOptions: (options: OptionsInit) => never) => Promisable<Response | CancelableRequest<Response>>; +/** +All available hooks of Got. +*/ +export type Hooks = { + /** + Called with the plain request options, right before their normalization. + + The second argument represents the current `Options` instance. + + @default [] + + **Note:** + > - This hook must be synchronous. + + **Note:** + > - This is called every time options are merged. + + **Note:** + > - The `options` object may not have the `url` property. To modify it, use a `beforeRequest` hook instead. + + **Note:** + > - This hook is called when a new instance of `Options` is created. + > - Do not confuse this with the creation of `Request` or `got(…)`. + + **Note:** + > - When using `got(url)` or `got(url, undefined, defaults)` this hook will **not** be called. + + This is especially useful in conjunction with `got.extend()` when the input needs custom handling. + + For example, this can be used to fix typos to migrate from older versions faster. + + @example + ``` + import got from 'got'; + + const instance = got.extend({ + hooks: { + init: [ + plain => { + if ('followRedirects' in plain) { + plain.followRedirect = plain.followRedirects; + delete plain.followRedirects; + } + } + ] + } + }); + + // Normally, the following would throw: + const response = await instance( + 'https://example.com', + { + followRedirects: true + } + ); + + // There is no option named `followRedirects`, but we correct it in an `init` hook. + ``` + + Or you can create your own option and store it in a context: + + ``` + import got from 'got'; + + const instance = got.extend({ + hooks: { + init: [ + (plain, options) => { + if ('secret' in plain) { + options.context.secret = plain.secret; + delete plain.secret; + } + } + ], + beforeRequest: [ + options => { + options.headers.secret = options.context.secret; + } + ] + } + }); + + const {headers} = await instance( + 'https://httpbin.org/anything', + { + secret: 'passphrase' + } + ).json(); + + console.log(headers.Secret); + //=> 'passphrase' + ``` + */ + init: InitHook[]; + /** + Called right before making the request with `options.createNativeRequestOptions()`. + + This hook is especially useful in conjunction with `got.extend()` when you want to sign your request. + + @default [] + + **Note:** + > - Got will make no further changes to the request before it is sent. + + **Note:** + > - Changing `options.json` or `options.form` has no effect on the request. You should change `options.body` instead. If needed, update the `options.headers` accordingly. + + @example + ``` + import got from 'got'; + + const response = await got.post( + 'https://httpbin.org/anything', + { + json: {payload: 'old'}, + hooks: { + beforeRequest: [ + options => { + options.body = JSON.stringify({payload: 'new'}); + options.headers['content-length'] = options.body.length.toString(); + } + ] + } + } + ); + ``` + + **Tip:** + > - You can indirectly override the `request` function by early returning a [`ClientRequest`-like](https://nodejs.org/api/http.html#http_class_http_clientrequest) instance or a [`IncomingMessage`-like](https://nodejs.org/api/http.html#http_class_http_incomingmessage) instance. This is very useful when creating a custom cache mechanism. + > - [Read more about this tip](https://github.com/sindresorhus/got/blob/main/documentation/cache.md#advanced-caching-mechanisms). + */ + beforeRequest: BeforeRequestHook[]; + /** + The equivalent of `beforeRequest` but when redirecting. + + @default [] + + **Tip:** + > - This is especially useful when you want to avoid dead sites. + + @example + ``` + import got from 'got'; + + const response = await got('https://example.com', { + hooks: { + beforeRedirect: [ + (options, response) => { + if (options.hostname === 'deadSite') { + options.hostname = 'fallbackSite'; + } + } + ] + } + }); + ``` + */ + beforeRedirect: BeforeRedirectHook[]; + /** + Called with a `RequestError` instance. The error is passed to the hook right before it's thrown. + + This is especially useful when you want to have more detailed errors. + + @default [] + + ``` + import got from 'got'; + + await got('https://api.github.com/repos/sindresorhus/got/commits', { + responseType: 'json', + hooks: { + beforeError: [ + error => { + const {response} = error; + if (response && response.body) { + error.name = 'GitHubError'; + error.message = `${response.body.message} (${response.statusCode})`; + } + + return error; + } + ] + } + }); + ``` + */ + beforeError: BeforeErrorHook[]; + /** + The equivalent of `beforeError` but when retrying. Additionally, there is a second argument `retryCount`, the current retry number. + + @default [] + + **Note:** + > - When using the Stream API, this hook is ignored. + + **Note:** + > - When retrying, the `beforeRequest` hook is called afterwards. + + **Note:** + > - If no retry occurs, the `beforeError` hook is called instead. + + This hook is especially useful when you want to retrieve the cause of a retry. + + @example + ``` + import got from 'got'; + + await got('https://httpbin.org/status/500', { + hooks: { + beforeRetry: [ + (error, retryCount) => { + console.log(`Retrying [${retryCount}]: ${error.code}`); + // Retrying [1]: ERR_NON_2XX_3XX_RESPONSE + } + ] + } + }); + ``` + */ + beforeRetry: BeforeRetryHook[]; + /** + Each function should return the response. This is especially useful when you want to refresh an access token. + + @default [] + + **Note:** + > - When using the Stream API, this hook is ignored. + + **Note:** + > - Calling the `retryWithMergedOptions` function will trigger `beforeRetry` hooks. If the retry is successful, all remaining `afterResponse` hooks will be called. In case of an error, `beforeRetry` hooks will be called instead. + Meanwhile the `init`, `beforeRequest` , `beforeRedirect` as well as already executed `afterResponse` hooks will be skipped. + + @example + ``` + import got from 'got'; + + const instance = got.extend({ + hooks: { + afterResponse: [ + (response, retryWithMergedOptions) => { + // Unauthorized + if (response.statusCode === 401) { + // Refresh the access token + const updatedOptions = { + headers: { + token: getNewToken() + } + }; + + // Update the defaults + instance.defaults.options.merge(updatedOptions); + + // Make a new retry + return retryWithMergedOptions(updatedOptions); + } + + // No changes otherwise + return response; + } + ], + beforeRetry: [ + error => { + // This will be called on `retryWithMergedOptions(...)` + } + ] + }, + mutableDefaults: true + }); + ``` + */ + afterResponse: AfterResponseHook[]; +}; +export type ParseJsonFunction = (text: string) => unknown; +export type StringifyJsonFunction = (object: unknown) => string; +/** +All available HTTP request methods provided by Got. +*/ +export type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'HEAD' | 'DELETE' | 'OPTIONS' | 'TRACE' | 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete' | 'options' | 'trace'; +export type RetryObject = { + attemptCount: number; + retryOptions: RetryOptions; + error: RequestError; + computedValue: number; + retryAfter?: number; +}; +export type RetryFunction = (retryObject: RetryObject) => Promisable<number>; +/** +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:__ Got does not retry on `POST` by default. +__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. +*/ +export type RetryOptions = { + limit: number; + methods: Method[]; + statusCodes: number[]; + errorCodes: string[]; + calculateDelay: RetryFunction; + backoffLimit: number; + noise: number; + maxRetryAfter?: number; +}; +export type CreateConnectionFunction = (options: NativeRequestOptions, oncreate: (error: NodeJS.ErrnoException, socket: Socket) => void) => Socket; +export type CheckServerIdentityFunction = (hostname: string, certificate: DetailedPeerCertificate) => NodeJS.ErrnoException | void; +export type CacheOptions = { + shared?: boolean; + cacheHeuristic?: number; + immutableMinTimeToLive?: number; + ignoreCargoCult?: boolean; +}; +type PfxObject = { + buffer: string | Buffer; + passphrase?: string | undefined; +}; +type PfxType = string | Buffer | Array<string | Buffer | PfxObject> | undefined; +export type HttpsOptions = { + alpnProtocols?: string[]; + rejectUnauthorized?: NativeRequestOptions['rejectUnauthorized']; + checkServerIdentity?: CheckServerIdentityFunction; + /** + Override the default Certificate Authorities ([from Mozilla](https://ccadb-public.secure.force.com/mozilla/IncludedCACertificateReport)). + + @example + ``` + // Single Certificate Authority + await got('https://example.com', { + https: { + certificateAuthority: fs.readFileSync('./my_ca.pem') + } + }); + ``` + */ + certificateAuthority?: SecureContextOptions['ca']; + /** + Private keys in [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) format. + + [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) allows the option of private keys being encrypted. + Encrypted keys will be decrypted with `options.https.passphrase`. + + Multiple keys with different passphrases can be provided as an array of `{pem: <string | Buffer>, passphrase: <string>}` + */ + key?: SecureContextOptions['key']; + /** + [Certificate chains](https://en.wikipedia.org/wiki/X.509#Certificate_chains_and_cross-certification) in [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) format. + + One cert chain should be provided per private key (`options.https.key`). + + When providing multiple cert chains, they do not have to be in the same order as their private keys in `options.https.key`. + + If the intermediate certificates are not provided, the peer will not be able to validate the certificate, and the handshake will fail. + */ + certificate?: SecureContextOptions['cert']; + /** + The passphrase to decrypt the `options.https.key` (if different keys have different passphrases refer to `options.https.key` documentation). + */ + passphrase?: SecureContextOptions['passphrase']; + pfx?: PfxType; + ciphers?: SecureContextOptions['ciphers']; + honorCipherOrder?: SecureContextOptions['honorCipherOrder']; + minVersion?: SecureContextOptions['minVersion']; + maxVersion?: SecureContextOptions['maxVersion']; + signatureAlgorithms?: SecureContextOptions['sigalgs']; + tlsSessionLifetime?: SecureContextOptions['sessionTimeout']; + dhparam?: SecureContextOptions['dhparam']; + ecdhCurve?: SecureContextOptions['ecdhCurve']; + certificateRevocationLists?: SecureContextOptions['crl']; +}; +export type PaginateData<BodyType, ElementType> = { + response: Response<BodyType>; + currentItems: ElementType[]; + allItems: ElementType[]; +}; +export type FilterData<ElementType> = { + item: ElementType; + currentItems: ElementType[]; + allItems: ElementType[]; +}; +/** +All options accepted by `got.paginate()`. +*/ +export type PaginationOptions<ElementType, BodyType> = { + /** + A function that transform [`Response`](#response) into an array of items. + This is where you should do the parsing. + + @default response => JSON.parse(response.body) + */ + transform?: (response: Response<BodyType>) => Promise<ElementType[]> | ElementType[]; + /** + Checks whether the item should be emitted or not. + + @default ({item, currentItems, allItems}) => true + */ + filter?: (data: FilterData<ElementType>) => boolean; + /** + The function takes an object with the following properties: + - `response` - The current response object. + - `currentItems` - Items from the current response. + - `allItems` - An empty array, unless `pagination.stackAllItems` is set to `true`, in which case, it's an array of the emitted items. + + It should return an object representing Got options pointing to the next page. The options are merged automatically with the previous request, therefore the options returned `pagination.paginate(...)` must reflect changes only. If there are no more pages, `false` should be returned. + + @example + ``` + import got from 'got'; + + const limit = 10; + + const items = got.paginate('https://example.com/items', { + searchParams: { + limit, + offset: 0 + }, + pagination: { + paginate: ({response, currentItems}) => { + const previousSearchParams = response.request.options.searchParams; + const previousOffset = previousSearchParams.get('offset'); + + if (currentItems.length < limit) { + return false; + } + + return { + searchParams: { + ...previousSearchParams, + offset: Number(previousOffset) + limit, + } + }; + } + } + }); + + console.log('Items from all pages:', items); + ``` + */ + paginate?: (data: PaginateData<BodyType, ElementType>) => OptionsInit | false; + /** + Checks whether the pagination should continue. + + For example, if you need to stop **before** emitting an entry with some flag, you should use `({item}) => !item.flag`. + + If you want to stop **after** emitting the entry, you should use + `({item, allItems}) => allItems.some(item => item.flag)` instead. + + @default ({item, currentItems, allItems}) => true + */ + shouldContinue?: (data: FilterData<ElementType>) => boolean; + /** + The maximum amount of items that should be emitted. + + @default Infinity + */ + countLimit?: number; + /** + Milliseconds to wait before the next request is triggered. + + @default 0 + */ + backoff?: number; + /** + The maximum amount of request that should be triggered. + Retries on failure are not counted towards this limit. + + For example, it can be helpful during development to avoid an infinite number of requests. + + @default 10000 + */ + requestLimit?: number; + /** + Defines how the property `allItems` in `pagination.paginate`, `pagination.filter` and `pagination.shouldContinue` is managed. + + By default, the property `allItems` is always an empty array. This setting can be helpful to save on memory usage when working with a large dataset. + + When set to `true`, the property `allItems` is an array of the emitted items. + + @default false + */ + stackAllItems?: boolean; +}; +export type SearchParameters = Record<string, string | number | boolean | null | undefined>; +/** +All parsing methods supported by Got. +*/ +export type ResponseType = 'json' | 'buffer' | 'text'; +type OptionsToSkip = 'searchParameters' | 'followRedirects' | 'auth' | 'toJSON' | 'merge' | 'createNativeRequestOptions' | 'getRequestFunction' | 'getFallbackRequestFunction' | 'freeze'; +export type InternalsType = Except<Options, OptionsToSkip>; +export type OptionsError = NodeJS.ErrnoException & { + options?: Options; +}; +export type OptionsInit = Except<Partial<InternalsType>, 'hooks' | 'retry'> & { + hooks?: Partial<Hooks>; + retry?: Partial<RetryOptions>; +}; +export default class Options { + private _unixOptions?; + private _internals; + private _merging; + private readonly _init; + constructor(input?: string | URL | OptionsInit, options?: OptionsInit, defaults?: Options); + merge(options?: OptionsInit | Options): void; + /** + 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(): RequestFunction | undefined; + set request(value: RequestFunction | undefined); + /** + 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(): Agents; + set agent(value: Agents); + get h2session(): ClientHttp2Session | undefined; + set h2session(value: ClientHttp2Session | undefined); + /** + 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(): boolean; + set decompress(value: boolean); + /** + 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(): Delays; + set timeout(value: Delays); + /** + 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(): string | URL; + set prefixUrl(value: string | URL); + /** + __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(): string | Buffer | Readable | Generator | AsyncGenerator | FormDataLike | undefined; + set body(value: string | Buffer | Readable | Generator | AsyncGenerator | FormDataLike | undefined); + /** + 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(): Record<string, any> | undefined; + set form(value: Record<string, any> | undefined); + /** + 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(): unknown; + set json(value: unknown); + /** + 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(): string | URL | undefined; + set url(value: string | URL | 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(): PromiseCookieJar | ToughCookieJar | undefined; + set cookieJar(value: PromiseCookieJar | ToughCookieJar | undefined); + /** + You can abort the `request` using [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController). + + *Requires Node.js 16 or later.* + + @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(): any | undefined; + set signal(value: any | undefined); + /** + Ignore invalid cookies instead of throwing an error. + Only useful when the `cookieJar` option has been set. Not recommended. + + @default false + */ + get ignoreInvalidCookies(): boolean; + set ignoreInvalidCookies(value: boolean); + /** + 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(): string | SearchParameters | URLSearchParams | undefined; + set searchParams(value: string | SearchParameters | URLSearchParams | undefined); + get searchParameters(): unknown; + set searchParameters(_value: unknown); + get dnsLookup(): CacheableLookup['lookup'] | undefined; + set dnsLookup(value: CacheableLookup['lookup'] | undefined); + /** + 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(): CacheableLookup | boolean | undefined; + set dnsCache(value: CacheableLookup | boolean | undefined); + /** + 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(): Record<string, unknown>; + set context(value: Record<string, unknown>); + /** + Hooks allow modifications during the request lifecycle. + Hook functions may be async and are run serially. + */ + get hooks(): Hooks; + set hooks(value: Hooks); + /** + Defines if redirect responses should be followed automatically. + + 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(): boolean; + set followRedirect(value: boolean); + get followRedirects(): unknown; + set followRedirects(_value: unknown); + /** + If exceeded, the request will be aborted and a `MaxRedirectsError` will be thrown. + + @default 10 + */ + get maxRedirects(): number; + set maxRedirects(value: number); + /** + A cache adapter instance for storing cached response data. + + @default false + */ + get cache(): string | StorageAdapter | boolean | undefined; + set cache(value: string | StorageAdapter | boolean | undefined); + /** + 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(): boolean; + set throwHttpErrors(value: boolean); + get username(): string; + set username(value: string); + get password(): string; + set password(value: string); + /** + 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(): boolean; + set http2(value: boolean); + /** + 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(): boolean; + set allowGetBody(value: boolean); + /** + Request headers. + + Existing headers will be overwritten. Headers set to `undefined` will be omitted. + + @default {} + */ + get headers(): Headers; + set headers(value: Headers); + /** + 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(): boolean; + set methodRewriting(value: boolean); + /** + Indicates which DNS record family to use. + + Values: + - `undefined`: IPv4 (if present) or IPv6 + - `4`: Only IPv4 + - `6`: Only IPv6 + + @default undefined + */ + get dnsLookupIpVersion(): DnsLookupIpVersion; + set dnsLookupIpVersion(value: DnsLookupIpVersion); + /** + 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(): ParseJsonFunction; + set parseJson(value: ParseJsonFunction); + /** + 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(): StringifyJsonFunction; + set stringifyJson(value: StringifyJsonFunction); + /** + 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(): Partial<RetryOptions>; + set retry(value: Partial<RetryOptions>); + /** + From `http.RequestOptions`. + + The IP address used to send the request from. + */ + get localAddress(): string | undefined; + set localAddress(value: string | undefined); + /** + The HTTP method used to make the request. + + @default 'GET' + */ + get method(): Method; + set method(value: Method); + get createConnection(): CreateConnectionFunction | undefined; + set createConnection(value: CreateConnectionFunction | undefined); + /** + From `http-cache-semantics` + + @default {} + */ + get cacheOptions(): CacheOptions; + set cacheOptions(value: CacheOptions); + /** + Options for the advanced HTTPS API. + */ + get https(): HttpsOptions; + set https(value: HttpsOptions); + /** + [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(): BufferEncoding | undefined; + set encoding(value: BufferEncoding | undefined); + /** + When set to `true` the promise will return the Response body instead of the Response object. + + @default false + */ + get resolveBodyOnly(): boolean; + set resolveBodyOnly(value: boolean); + /** + Returns a `Stream` instead of a `Promise`. + This is equivalent to calling `got.stream(url, options?)`. + + @default false + */ + get isStream(): boolean; + set isStream(value: boolean); + /** + 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(): ResponseType; + set responseType(value: ResponseType); + get pagination(): PaginationOptions<unknown, unknown>; + set pagination(value: PaginationOptions<unknown, unknown>); + get auth(): unknown; + set auth(_value: unknown); + get setHost(): boolean; + set setHost(value: boolean); + get maxHeaderSize(): number | undefined; + set maxHeaderSize(value: number | undefined); + get enableUnixSockets(): boolean; + set enableUnixSockets(value: boolean); + toJSON(): { + headers: Headers; + timeout: Delays; + request: RequestFunction | undefined; + username: string; + password: string; + json: unknown; + retry: Partial<RetryOptions>; + agent: Agents; + h2session: http2wrapper.ClientHttp2Session | undefined; + decompress: boolean; + prefixUrl: string | URL; + body: string | Readable | Buffer | Generator<unknown, any, unknown> | AsyncGenerator<unknown, any, unknown> | FormDataLike | undefined; + form: Record<string, any> | undefined; + url: string | URL | undefined; + cookieJar: PromiseCookieJar | ToughCookieJar | undefined; + signal: any; + ignoreInvalidCookies: boolean; + searchParams: string | SearchParameters | URLSearchParams | undefined; + dnsLookup: { + (hostname: string, family: import("cacheable-lookup").IPFamily, callback: (error: NodeJS.ErrnoException | null, address: string, family: import("cacheable-lookup").IPFamily) => void): void; + (hostname: string, callback: (error: NodeJS.ErrnoException | null, address: string, family: import("cacheable-lookup").IPFamily) => void): void; + (hostname: string, options: import("cacheable-lookup").LookupOptions & { + all: true; + }, callback: (error: NodeJS.ErrnoException | null, result: readonly import("cacheable-lookup").EntryObject[]) => void): void; + (hostname: string, options: import("cacheable-lookup").LookupOptions, callback: (error: NodeJS.ErrnoException | null, address: string, family: import("cacheable-lookup").IPFamily) => void): void; + } | undefined; + dnsCache: boolean | CacheableLookup | undefined; + context: Record<string, unknown>; + hooks: Hooks; + followRedirect: boolean; + maxRedirects: number; + cache: string | boolean | StorageAdapter | undefined; + throwHttpErrors: boolean; + http2: boolean; + allowGetBody: boolean; + methodRewriting: boolean; + dnsLookupIpVersion: DnsLookupIpVersion; + parseJson: ParseJsonFunction; + stringifyJson: StringifyJsonFunction; + localAddress: string | undefined; + method: Method; + createConnection: CreateConnectionFunction | undefined; + cacheOptions: CacheOptions; + https: HttpsOptions; + encoding: BufferEncoding | undefined; + resolveBodyOnly: boolean; + isStream: boolean; + responseType: ResponseType; + pagination: PaginationOptions<unknown, unknown>; + setHost: boolean; + maxHeaderSize: number | undefined; + enableUnixSockets: boolean; + }; + createNativeRequestOptions(): { + ALPNProtocols: string[] | undefined; + ca: string | Buffer | (string | Buffer)[] | undefined; + cert: string | Buffer | (string | Buffer)[] | undefined; + key: string | Buffer | (string | Buffer | import("tls").KeyObject)[] | undefined; + passphrase: string | undefined; + pfx: PfxType; + rejectUnauthorized: boolean | undefined; + checkServerIdentity: typeof checkServerIdentity | CheckServerIdentityFunction; + ciphers: string | undefined; + honorCipherOrder: boolean | undefined; + minVersion: import("tls").SecureVersion | undefined; + maxVersion: import("tls").SecureVersion | undefined; + sigalgs: string | undefined; + sessionTimeout: number | undefined; + dhparam: string | Buffer | undefined; + ecdhCurve: string | undefined; + crl: string | Buffer | (string | Buffer)[] | undefined; + lookup: { + (hostname: string, family: import("cacheable-lookup").IPFamily, callback: (error: NodeJS.ErrnoException | null, address: string, family: import("cacheable-lookup").IPFamily) => void): void; + (hostname: string, callback: (error: NodeJS.ErrnoException | null, address: string, family: import("cacheable-lookup").IPFamily) => void): void; + (hostname: string, options: import("cacheable-lookup").LookupOptions & { + all: true; + }, callback: (error: NodeJS.ErrnoException | null, result: readonly import("cacheable-lookup").EntryObject[]) => void): void; + (hostname: string, options: import("cacheable-lookup").LookupOptions, callback: (error: NodeJS.ErrnoException | null, address: string, family: import("cacheable-lookup").IPFamily) => void): void; + } | undefined; + family: DnsLookupIpVersion; + agent: false | Agents | http.Agent | undefined; + setHost: boolean; + method: Method; + maxHeaderSize: number | undefined; + localAddress: string | undefined; + headers: Headers; + createConnection: CreateConnectionFunction | undefined; + timeout: number | undefined; + h2session: http2wrapper.ClientHttp2Session | undefined; + _defaultAgent?: http.Agent | undefined; + auth?: string | null | undefined; + defaultPort?: string | number | undefined; + hints?: number | undefined; + host?: string | null | undefined; + hostname?: string | null | undefined; + insecureHTTPParser?: boolean | undefined; + localPort?: number | undefined; + path?: string | null | undefined; + port?: string | number | null | undefined; + protocol?: string | null | undefined; + signal?: AbortSignal | undefined; + socketPath?: string | undefined; + uniqueHeaders?: (string | string[])[] | undefined; + clientCertEngine?: string | undefined; + privateKeyEngine?: string | undefined; + privateKeyIdentifier?: string | undefined; + secureOptions?: number | undefined; + secureProtocol?: string | undefined; + sessionIdContext?: string | undefined; + ticketKeys?: Buffer | undefined; + servername?: string | undefined; + shared?: boolean | undefined; + cacheHeuristic?: number | undefined; + immutableMinTimeToLive?: number | undefined; + ignoreCargoCult?: boolean | undefined; + }; + getRequestFunction(): RequestFunction | typeof https.request | undefined; + getFallbackRequestFunction(): RequestFunction | typeof https.request | undefined; + freeze(): void; +} +export {}; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/options.js b/includes/external/addressbook/node_modules/got/dist/source/core/options.js new file mode 100644 index 0000000..571c4a0 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/options.js @@ -0,0 +1,1653 @@ +import process from 'node:process'; +import { promisify, inspect } from 'node:util'; +import { URL, URLSearchParams } from 'node:url'; +import { checkServerIdentity } from 'node:tls'; +// DO NOT use destructuring for `https.request` and `http.request` as it's not compatible with `nock`. +import http from 'node:http'; +import https from 'node:https'; +import is, { assert } from '@sindresorhus/is'; +import lowercaseKeys from 'lowercase-keys'; +import CacheableLookup from 'cacheable-lookup'; +import http2wrapper from 'http2-wrapper'; +import { isFormData } from 'form-data-encoder'; +import parseLinkHeader from './parse-link-header.js'; +const [major, minor] = process.versions.node.split('.').map(Number); +function validateSearchParameters(searchParameters) { + // eslint-disable-next-line guard-for-in + for (const key in searchParameters) { + const value = searchParameters[key]; + assert.any([is.string, is.number, is.boolean, is.null_, is.undefined], value); + } +} +const globalCache = new Map(); +let globalDnsCache; +const getGlobalDnsCache = () => { + if (globalDnsCache) { + return globalDnsCache; + } + globalDnsCache = new CacheableLookup(); + return globalDnsCache; +}; +const defaultInternals = { + request: undefined, + agent: { + http: undefined, + https: undefined, + http2: undefined, + }, + h2session: undefined, + decompress: true, + timeout: { + connect: undefined, + lookup: undefined, + read: undefined, + request: undefined, + response: undefined, + secureConnect: undefined, + send: undefined, + socket: undefined, + }, + prefixUrl: '', + body: undefined, + form: undefined, + json: undefined, + cookieJar: undefined, + ignoreInvalidCookies: false, + searchParams: undefined, + dnsLookup: undefined, + dnsCache: undefined, + context: {}, + hooks: { + init: [], + beforeRequest: [], + beforeError: [], + beforeRedirect: [], + beforeRetry: [], + 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 = 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: 10000, + stackAllItems: false, + }, + setHost: true, + maxHeaderSize: undefined, + signal: undefined, + enableUnixSockets: true, +}; +const cloneInternals = (internals) => { + const { hooks, retry } = internals; + const result = { + ...internals, + context: { ...internals.context }, + cacheOptions: { ...internals.cacheOptions }, + https: { ...internals.https }, + agent: { ...internals.agent }, + headers: { ...internals.headers }, + retry: { + ...retry, + errorCodes: [...retry.errorCodes], + methods: [...retry.methods], + statusCodes: [...retry.statusCodes], + }, + timeout: { ...internals.timeout }, + hooks: { + init: [...hooks.init], + beforeRequest: [...hooks.beforeRequest], + beforeError: [...hooks.beforeError], + beforeRedirect: [...hooks.beforeRedirect], + beforeRetry: [...hooks.beforeRetry], + afterResponse: [...hooks.afterResponse], + }, + searchParams: internals.searchParams ? new URLSearchParams(internals.searchParams) : undefined, + pagination: { ...internals.pagination }, + }; + if (result.url !== undefined) { + result.prefixUrl = ''; + } + return result; +}; +const cloneRaw = (raw) => { + const { hooks, retry } = raw; + const result = { ...raw }; + if (is.object(raw.context)) { + result.context = { ...raw.context }; + } + if (is.object(raw.cacheOptions)) { + result.cacheOptions = { ...raw.cacheOptions }; + } + if (is.object(raw.https)) { + result.https = { ...raw.https }; + } + if (is.object(raw.cacheOptions)) { + result.cacheOptions = { ...result.cacheOptions }; + } + if (is.object(raw.agent)) { + result.agent = { ...raw.agent }; + } + if (is.object(raw.headers)) { + result.headers = { ...raw.headers }; + } + if (is.object(retry)) { + result.retry = { ...retry }; + if (is.array(retry.errorCodes)) { + result.retry.errorCodes = [...retry.errorCodes]; + } + if (is.array(retry.methods)) { + result.retry.methods = [...retry.methods]; + } + if (is.array(retry.statusCodes)) { + result.retry.statusCodes = [...retry.statusCodes]; + } + } + if (is.object(raw.timeout)) { + result.timeout = { ...raw.timeout }; + } + if (is.object(hooks)) { + result.hooks = { + ...hooks, + }; + if (is.array(hooks.init)) { + result.hooks.init = [...hooks.init]; + } + if (is.array(hooks.beforeRequest)) { + result.hooks.beforeRequest = [...hooks.beforeRequest]; + } + if (is.array(hooks.beforeError)) { + result.hooks.beforeError = [...hooks.beforeError]; + } + if (is.array(hooks.beforeRedirect)) { + result.hooks.beforeRedirect = [...hooks.beforeRedirect]; + } + if (is.array(hooks.beforeRetry)) { + result.hooks.beforeRetry = [...hooks.beforeRetry]; + } + if (is.array(hooks.afterResponse)) { + result.hooks.afterResponse = [...hooks.afterResponse]; + } + } + // TODO: raw.searchParams + if (is.object(raw.pagination)) { + result.pagination = { ...raw.pagination }; + } + return result; +}; +const 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 init = (options, withOptions, self) => { + const initHooks = options.hooks?.init; + if (initHooks) { + for (const hook of initHooks) { + hook(withOptions, self); + } + } +}; +export default class Options { + constructor(input, options, defaults) { + Object.defineProperty(this, "_unixOptions", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_internals", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_merging", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "_init", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + assert.any([is.string, is.urlInstance, is.object, is.undefined], input); + assert.any([is.object, is.undefined], options); + assert.any([is.object, is.undefined], defaults); + if (input instanceof Options || options instanceof Options) { + throw new TypeError('The defaults must be passed as the third argument'); + } + this._internals = cloneInternals(defaults?._internals ?? defaults ?? 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 (is.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) { + for (const init of options._init) { + this.merge(init); + } + return; + } + options = cloneRaw(options); + init(this, options, this); + 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'. + this[key] = options[key]; + 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([is.function_, is.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([is.object, is.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([is.number, is.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([is.string, is.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([is.string, is.buffer, is.nodeStream, is.generator, is.asyncGenerator, isFormData, is.undefined], value); + if (is.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([is.plainObject, is.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([is.string, is.urlInstance, is.undefined], value); + if (value === undefined) { + this._internals.url = undefined; + return; + } + if (is.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 = /(?<socketPath>.+?):(?<path>.+)/.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([is.object, is.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 = promisify(setCookie.bind(value)); + getCookieString = 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). + + *Requires Node.js 16 or later.* + + @example + ``` + import got from 'got'; + + const abortController = new AbortController(); + + const request = got('https://httpbin.org/anything', { + signal: abortController.signal + }); + + setTimeout(() => { + abortController.abort(); + }, 100); + ``` + */ + // TODO: Replace `any` with `AbortSignal` when targeting Node 16. + get signal() { + return this._internals.signal; + } + // TODO: Replace `any` with `AbortSignal` when targeting Node 16. + 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([is.string, is.object, is.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 (is.string(value)) { + updated = new URLSearchParams(value); + } + else if (value instanceof URLSearchParams) { + updated = value; + } + else { + 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([is.function_, is.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([is.object, is.boolean, is.undefined], value); + if (value === true) { + this._internals.dnsCache = 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([is.array, is.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]; + } + } + } + /** + Defines if redirect responses should be followed automatically. + + 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.boolean(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([is.object, is.string, is.boolean, is.undefined], value); + if (value === true) { + this._internals.cache = 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([is.function_, is.undefined], value.calculateDelay); + assert.any([is.number, is.undefined], value.maxRetryAfter); + assert.any([is.number, is.undefined], value.limit); + assert.any([is.array, is.undefined], value.methods); + assert.any([is.array, is.undefined], value.statusCodes); + assert.any([is.array, is.undefined], value.errorCodes); + assert.any([is.number, is.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([is.string, is.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([is.function_, is.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([is.boolean, is.undefined], value.shared); + assert.any([is.number, is.undefined], value.cacheHeuristic); + assert.any([is.number, is.undefined], value.immutableMinTimeToLive); + assert.any([is.boolean, is.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([is.boolean, is.undefined], value.rejectUnauthorized); + assert.any([is.function_, is.undefined], value.checkServerIdentity); + assert.any([is.string, is.object, is.array, is.undefined], value.certificateAuthority); + assert.any([is.string, is.object, is.array, is.undefined], value.key); + assert.any([is.string, is.object, is.array, is.undefined], value.certificate); + assert.any([is.string, is.undefined], value.passphrase); + assert.any([is.string, is.buffer, is.array, is.undefined], value.pfx); + assert.any([is.array, is.undefined], value.alpnProtocols); + assert.any([is.string, is.undefined], value.ciphers); + assert.any([is.string, is.buffer, is.undefined], value.dhparam); + assert.any([is.string, is.undefined], value.signatureAlgorithms); + assert.any([is.string, is.undefined], value.minVersion); + assert.any([is.string, is.undefined], value.maxVersion); + assert.any([is.boolean, is.undefined], value.honorCipherOrder); + assert.any([is.number, is.undefined], value.tlsSessionLifetime); + assert.any([is.string, is.undefined], value.ecdhCurve); + assert.any([is.string, is.buffer, is.array, is.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([is.string, is.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([is.number, is.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 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 (is.array(pfx) && is.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 ?? 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 ? 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 (major < 15 || (major === 15 && 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 http2wrapper.auto; + } + return https.request; + } + return http.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); + } +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/parse-link-header.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/parse-link-header.d.ts new file mode 100644 index 0000000..595e561 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/parse-link-header.d.ts @@ -0,0 +1,4 @@ +export default function parseLinkHeader(link: string): { + reference: string; + parameters: Record<string, string>; +}[]; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/parse-link-header.js b/includes/external/addressbook/node_modules/got/dist/source/core/parse-link-header.js new file mode 100644 index 0000000..898a6a2 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/parse-link-header.js @@ -0,0 +1,33 @@ +export default function 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[trimmedUriReference.length - 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; +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/response.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/response.d.ts new file mode 100644 index 0000000..4ea3629 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/response.d.ts @@ -0,0 +1,110 @@ +/// <reference types="node" resolution-mode="require"/> +/// <reference types="node" resolution-mode="require"/> +import type { Buffer } from 'node:buffer'; +import type { URL } from 'node:url'; +import type { IncomingMessageWithTimings, Timings } from '@szmarczak/http-timer'; +import { RequestError } from './errors.js'; +import type { ParseJsonFunction, ResponseType } from './options.js'; +import type Request from './index.js'; +export type PlainResponse = { + /** + The original request URL. + */ + requestUrl: URL; + /** + The redirect URLs. + */ + redirectUrls: URL[]; + /** + - `options` - The Got options that were set on this request. + + __Note__: This is not a [http.ClientRequest](https://nodejs.org/api/http.html#http_class_http_clientrequest). + */ + request: Request; + /** + The remote IP address. + + This is hopefully a temporary limitation, see [lukechilds/cacheable-request#86](https://github.com/lukechilds/cacheable-request/issues/86). + + __Note__: Not available when the response is cached. + */ + ip?: string; + /** + Whether the response was retrieved from the cache. + */ + isFromCache: boolean; + /** + The status code of the response. + */ + statusCode: number; + /** + The request URL or the final URL after redirects. + */ + url: string; + /** + 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. + */ + timings: Timings; + /** + The number of times the request was retried. + */ + retryCount: number; + /** + The raw result of the request. + */ + rawBody?: Buffer; + /** + The result of the request. + */ + body?: unknown; + /** + Whether the response was successful. + + __Note__: Got throws automatically when `response.ok` is `false` and `throwHttpErrors` is `true`. + */ + ok: boolean; +} & IncomingMessageWithTimings; +export type Response<T = unknown> = { + /** + The result of the request. + */ + body: T; + /** + The raw result of the request. + */ + rawBody: Buffer; +} & PlainResponse; +export declare const isResponseOk: (response: PlainResponse) => boolean; +/** +An error to be thrown when server response code is 2xx, and parsing body fails. +Includes a `response` property. +*/ +export declare class ParseError extends RequestError { + readonly response: Response; + constructor(error: Error, response: Response); +} +export declare const parseBody: (response: Response, responseType: ResponseType, parseJson: ParseJsonFunction, encoding?: BufferEncoding) => unknown; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/response.js b/includes/external/addressbook/node_modules/got/dist/source/core/response.js new file mode 100644 index 0000000..06c4610 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/response.js @@ -0,0 +1,39 @@ +import { RequestError } from './errors.js'; +export const isResponseOk = (response) => { + const { statusCode } = response; + const limitStatusCode = response.request.options.followRedirect ? 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. +*/ +export class ParseError extends 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'; + } +} +export const parseBody = (response, responseType, parseJson, encoding) => { + const { rawBody } = response; + try { + if (responseType === 'text') { + return rawBody.toString(encoding); + } + if (responseType === 'json') { + return rawBody.length === 0 ? '' : parseJson(rawBody.toString(encoding)); + } + if (responseType === 'buffer') { + return rawBody; + } + } + catch (error) { + throw new ParseError(error, response); + } + throw new ParseError({ + message: `Unknown body type '${responseType}'`, + name: 'Error', + }, response); +}; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/timed-out.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/timed-out.d.ts new file mode 100644 index 0000000..845684c --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/timed-out.d.ts @@ -0,0 +1,30 @@ +import type { ClientRequest } from 'node:http'; +declare const reentry: unique symbol; +type TimedOutOptions = { + host?: string; + hostname?: string; + protocol?: string; +}; +export type Delays = { + lookup?: number; + socket?: number; + connect?: number; + secureConnect?: number; + send?: number; + response?: number; + read?: number; + request?: number; +}; +export type ErrorCode = 'ETIMEDOUT' | 'ECONNRESET' | 'EADDRINUSE' | 'ECONNREFUSED' | 'EPIPE' | 'ENOTFOUND' | 'ENETUNREACH' | 'EAI_AGAIN'; +export declare class TimeoutError extends Error { + event: string; + code: ErrorCode; + constructor(threshold: number, event: string); +} +export default function timedOut(request: ClientRequest, delays: Delays, options: TimedOutOptions): () => void; +declare module 'http' { + interface ClientRequest { + [reentry]?: boolean; + } +} +export {}; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/timed-out.js b/includes/external/addressbook/node_modules/got/dist/source/core/timed-out.js new file mode 100644 index 0000000..500f748 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/timed-out.js @@ -0,0 +1,138 @@ +import net from 'node:net'; +import unhandler from './utils/unhandle.js'; +const reentry = Symbol('reentry'); +const noop = () => { }; +export class TimeoutError extends Error { + constructor(threshold, event) { + super(`Timeout awaiting '${event}' for ${threshold}ms`); + Object.defineProperty(this, "event", { + enumerable: true, + configurable: true, + writable: true, + value: event + }); + Object.defineProperty(this, "code", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + this.name = 'TimeoutError'; + this.code = 'ETIMEDOUT'; + } +} +export default function timedOut(request, delays, options) { + if (reentry in request) { + return noop; + } + request[reentry] = true; + const cancelers = []; + const { once, unhandleAll } = unhandler(); + 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 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 (typeof delays.request !== 'undefined') { + const cancelTimeout = addTimeout(delays.request, timeoutHandler, 'request'); + once(request, 'response', (response) => { + once(response, 'end', cancelTimeout); + }); + } + if (typeof 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 = typeof delays.lookup !== 'undefined'; + const hasConnect = typeof delays.connect !== 'undefined'; + const hasSecureConnect = typeof delays.secureConnect !== 'undefined'; + const hasSend = typeof 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 ?? net.isIP(hostname ?? host ?? '') !== 0); + if (hasLookup && !hasPath && typeof 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 (typeof delays.response !== 'undefined') { + once(request, 'upload-complete', () => { + const cancelTimeout = addTimeout(delays.response, timeoutHandler, 'response'); + once(request, 'response', cancelTimeout); + }); + } + if (typeof delays.read !== 'undefined') { + once(request, 'response', (response) => { + const cancelTimeout = addTimeout(delays.read, timeoutHandler, 'read'); + once(response, 'end', cancelTimeout); + }); + } + return cancelTimeouts; +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/get-body-size.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/utils/get-body-size.d.ts new file mode 100644 index 0000000..3030691 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/get-body-size.d.ts @@ -0,0 +1,3 @@ +/// <reference types="node" resolution-mode="require"/> +import type { ClientRequestArgs } from 'node:http'; +export default function getBodySize(body: unknown, headers: ClientRequestArgs['headers']): Promise<number | undefined>; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/get-body-size.js b/includes/external/addressbook/node_modules/got/dist/source/core/utils/get-body-size.js new file mode 100644 index 0000000..9a85c64 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/get-body-size.js @@ -0,0 +1,22 @@ +import { Buffer } from 'node:buffer'; +import { promisify } from 'node:util'; +import is from '@sindresorhus/is'; +import isFormData from './is-form-data.js'; +export default async function getBodySize(body, headers) { + if (headers && 'content-length' in headers) { + return Number(headers['content-length']); + } + if (!body) { + return 0; + } + if (is.string(body)) { + return Buffer.byteLength(body); + } + if (is.buffer(body)) { + return body.length; + } + if (isFormData(body)) { + return promisify(body.getLength.bind(body))(); + } + return undefined; +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-client-request.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-client-request.d.ts new file mode 100644 index 0000000..5e67ff0 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-client-request.d.ts @@ -0,0 +1,5 @@ +/// <reference types="node" resolution-mode="require"/> +import type { Writable, Readable } from 'node:stream'; +import type { ClientRequest } from 'node:http'; +declare function isClientRequest(clientRequest: Writable | Readable): clientRequest is ClientRequest; +export default isClientRequest; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-client-request.js b/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-client-request.js new file mode 100644 index 0000000..da80b68 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-client-request.js @@ -0,0 +1,4 @@ +function isClientRequest(clientRequest) { + return clientRequest.writable && !clientRequest.writableEnded; +} +export default isClientRequest; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-form-data.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-form-data.d.ts new file mode 100644 index 0000000..ed0805f --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-form-data.d.ts @@ -0,0 +1,8 @@ +/// <reference types="node" resolution-mode="require"/> +import type { Readable } from 'node:stream'; +type FormData = { + getBoundary: () => string; + getLength: (callback: (error: Error | null, length: number) => void) => void; +} & Readable; +export default function isFormData(body: unknown): body is FormData; +export {}; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-form-data.js b/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-form-data.js new file mode 100644 index 0000000..13a7823 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-form-data.js @@ -0,0 +1,4 @@ +import is from '@sindresorhus/is'; +export default function isFormData(body) { + return is.nodeStream(body) && is.function_(body.getBoundary); +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-unix-socket-url.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-unix-socket-url.d.ts new file mode 100644 index 0000000..ee3f162 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-unix-socket-url.d.ts @@ -0,0 +1,3 @@ +/// <reference types="node" resolution-mode="require"/> +import type { URL } from 'url'; +export default function isUnixSocketURL(url: URL): boolean; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-unix-socket-url.js b/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-unix-socket-url.js new file mode 100644 index 0000000..46f7348 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/is-unix-socket-url.js @@ -0,0 +1,4 @@ +// eslint-disable-next-line @typescript-eslint/naming-convention +export default function isUnixSocketURL(url) { + return url.protocol === 'unix:' || url.hostname === 'unix'; +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/options-to-url.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/utils/options-to-url.d.ts new file mode 100644 index 0000000..86b853f --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/options-to-url.d.ts @@ -0,0 +1,14 @@ +/// <reference types="node" resolution-mode="require"/> +import { URL } from 'node:url'; +export type URLOptions = { + href?: string; + protocol?: string; + host?: string; + hostname?: string; + port?: string | number; + pathname?: string; + search?: string; + searchParams?: unknown; + path?: string; +}; +export default function optionsToUrl(origin: string, options: URLOptions): URL; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/options-to-url.js b/includes/external/addressbook/node_modules/got/dist/source/core/utils/options-to-url.js new file mode 100644 index 0000000..46346a7 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/options-to-url.js @@ -0,0 +1,50 @@ +/* istanbul ignore file: deprecated */ +import { URL } from 'node:url'; +const keys = [ + 'protocol', + 'host', + 'hostname', + 'port', + 'pathname', + 'search', +]; +export default function optionsToUrl(origin, options) { + if (options.path) { + if (options.pathname) { + throw new TypeError('Parameters `path` and `pathname` are mutually exclusive.'); + } + if (options.search) { + throw new TypeError('Parameters `path` and `search` are mutually exclusive.'); + } + if (options.searchParams) { + throw new TypeError('Parameters `path` and `searchParams` are mutually exclusive.'); + } + } + if (options.search && options.searchParams) { + throw new TypeError('Parameters `search` and `searchParams` are mutually exclusive.'); + } + if (!origin) { + if (!options.protocol) { + throw new TypeError('No URL protocol specified'); + } + origin = `${options.protocol}//${options.hostname ?? options.host ?? ''}`; + } + const url = new URL(origin); + if (options.path) { + const searchIndex = options.path.indexOf('?'); + if (searchIndex === -1) { + options.pathname = options.path; + } + else { + options.pathname = options.path.slice(0, searchIndex); + options.search = options.path.slice(searchIndex + 1); + } + delete options.path; + } + for (const key of keys) { + if (options[key]) { + url[key] = options[key].toString(); + } + } + return url; +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/proxy-events.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/utils/proxy-events.d.ts new file mode 100644 index 0000000..cbc818a --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/proxy-events.d.ts @@ -0,0 +1,3 @@ +/// <reference types="node" resolution-mode="require"/> +import type { EventEmitter } from 'node:events'; +export default function proxyEvents(from: EventEmitter, to: EventEmitter, events: Readonly<string[]>): () => void; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/proxy-events.js b/includes/external/addressbook/node_modules/got/dist/source/core/utils/proxy-events.js new file mode 100644 index 0000000..d3d2f2d --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/proxy-events.js @@ -0,0 +1,15 @@ +export default function proxyEvents(from, to, events) { + const eventFunctions = {}; + for (const event of events) { + const eventFunction = (...args) => { + to.emit(event, ...args); + }; + eventFunctions[event] = eventFunction; + from.on(event, eventFunction); + } + return () => { + for (const [event, eventFunction] of Object.entries(eventFunctions)) { + from.off(event, eventFunction); + } + }; +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/unhandle.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/utils/unhandle.d.ts new file mode 100644 index 0000000..c494576 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/unhandle.d.ts @@ -0,0 +1,11 @@ +/// <reference types="node" resolution-mode="require"/> +import type { EventEmitter } from 'node:events'; +type Origin = EventEmitter; +type Event = string | symbol; +type Fn = (...args: any[]) => void; +type Unhandler = { + once: (origin: Origin, event: Event, fn: Fn) => void; + unhandleAll: () => void; +}; +export default function unhandle(): Unhandler; +export {}; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/unhandle.js b/includes/external/addressbook/node_modules/got/dist/source/core/utils/unhandle.js new file mode 100644 index 0000000..0312706 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/unhandle.js @@ -0,0 +1,20 @@ +// 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. +export default function unhandle() { + const handlers = []; + return { + once(origin, event, fn) { + origin.once(event, fn); + handlers.push({ origin, event, fn }); + }, + unhandleAll() { + for (const handler of handlers) { + const { origin, event, fn } = handler; + origin.removeListener(event, fn); + } + handlers.length = 0; + }, + }; +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/url-to-options.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/utils/url-to-options.d.ts new file mode 100644 index 0000000..e3ae8be --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/url-to-options.d.ts @@ -0,0 +1,15 @@ +/// <reference types="node" resolution-mode="require"/> +import type { URL, UrlWithStringQuery } from 'node:url'; +export type LegacyUrlOptions = { + protocol: string; + hostname: string; + host: string; + hash: string | null; + search: string | null; + pathname: string; + href: string; + path: string; + port?: number; + auth?: string; +}; +export default function urlToOptions(url: URL | UrlWithStringQuery): LegacyUrlOptions; diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/url-to-options.js b/includes/external/addressbook/node_modules/got/dist/source/core/utils/url-to-options.js new file mode 100644 index 0000000..959dd69 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/url-to-options.js @@ -0,0 +1,22 @@ +import is from '@sindresorhus/is'; +export default function urlToOptions(url) { + // Cast to URL + url = url; + const options = { + protocol: url.protocol, + hostname: is.string(url.hostname) && url.hostname.startsWith('[') ? url.hostname.slice(1, -1) : url.hostname, + host: url.host, + hash: url.hash, + search: url.search, + pathname: url.pathname, + href: url.href, + path: `${url.pathname || ''}${url.search || ''}`, + }; + if (is.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; +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/weakable-map.d.ts b/includes/external/addressbook/node_modules/got/dist/source/core/utils/weakable-map.d.ts new file mode 100644 index 0000000..9e3466c --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/weakable-map.d.ts @@ -0,0 +1,8 @@ +export default class WeakableMap<K, V> { + weakMap: WeakMap<Record<string, unknown>, V>; + map: Map<K, V>; + constructor(); + set(key: K, value: V): void; + get(key: K): V | undefined; + has(key: K): boolean; +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/core/utils/weakable-map.js b/includes/external/addressbook/node_modules/got/dist/source/core/utils/weakable-map.js new file mode 100644 index 0000000..805ad76 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/core/utils/weakable-map.js @@ -0,0 +1,38 @@ +export default class WeakableMap { + constructor() { + Object.defineProperty(this, "weakMap", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "map", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + 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); + } +} diff --git a/includes/external/addressbook/node_modules/got/dist/source/create.d.ts b/includes/external/addressbook/node_modules/got/dist/source/create.d.ts new file mode 100644 index 0000000..ce0f4b6 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/create.d.ts @@ -0,0 +1,3 @@ +import type { Got, InstanceDefaults } from './types.js'; +declare const create: (defaults: InstanceDefaults) => Got; +export default create; diff --git a/includes/external/addressbook/node_modules/got/dist/source/create.js b/includes/external/addressbook/node_modules/got/dist/source/create.js new file mode 100644 index 0000000..fb14e49 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/create.js @@ -0,0 +1,187 @@ +import is, { assert } from '@sindresorhus/is'; +import asPromise from './as-promise/index.js'; +import Request from './core/index.js'; +import Options from './core/options.js'; +// The `delay` package weighs 10KB (!) +const delay = async (ms) => new Promise(resolve => { + setTimeout(resolve, ms); +}); +const isGotInstance = (value) => is.function_(value); +const aliases = [ + 'get', + 'post', + 'put', + 'patch', + 'head', + 'delete', +]; +const create = (defaults) => { + defaults = { + options: new Options(undefined, undefined, defaults.options), + handlers: [...defaults.handlers], + mutableDefaults: defaults.mutableDefaults, + }; + Object.defineProperty(defaults, 'mutableDefaults', { + enumerable: true, + configurable: false, + writable: false, + }); + // Got interface + const got = ((url, options, defaultOptions = defaults.options) => { + const request = new 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; + } + if (!promise) { + promise = asPromise(request); + } + return promise; + }; + let iteration = 0; + const iterateHandlers = (newOptions) => { + const handler = defaults.handlers[iteration++] ?? lastHandler; + const result = handler(newOptions, iterateHandlers); + if (is.promise(result) && !request.options.isStream) { + if (!promise) { + 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(undefined, undefined, defaults.options); + const handlers = [...defaults.handlers]; + let mutableDefaults; + for (const value of instancesOrOptions) { + if (isGotInstance(value)) { + options.merge(value.defaults.options); + handlers.push(...value.defaults.handlers); + mutableDefaults = value.defaults.mutableDefaults; + } + else { + options.merge(value); + if (value.handlers) { + handlers.push(...value.handlers); + } + mutableDefaults = value.mutableDefaults; + } + } + return create({ + options, + handlers, + mutableDefaults: Boolean(mutableDefaults), + }); + }; + // Pagination + const paginateEach = (async function* (url, options) { + let normalizedOptions = new Options(url, options, defaults.options); + normalizedOptions.resolveBodyOnly = false; + const { pagination } = normalizedOptions; + assert.function_(pagination.transform); + assert.function_(pagination.shouldContinue); + assert.function_(pagination.filter); + assert.function_(pagination.paginate); + assert.number(pagination.countLimit); + assert.number(pagination.requestLimit); + assert.number(pagination.backoff); + const allItems = []; + let { countLimit } = pagination; + let numberOfRequests = 0; + while (numberOfRequests < pagination.requestLimit) { + if (numberOfRequests !== 0) { + // eslint-disable-next-line no-await-in-loop + await 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([is.urlInstance, is.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 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; +}; +export default create; diff --git a/includes/external/addressbook/node_modules/got/dist/source/index.d.ts b/includes/external/addressbook/node_modules/got/dist/source/index.d.ts new file mode 100644 index 0000000..9447c9a --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/index.d.ts @@ -0,0 +1,15 @@ +declare const got: import("./types.js").Got; +export default got; +export { got }; +export { default as Options } from './core/options.js'; +export * from './core/options.js'; +export * from './core/response.js'; +export type { default as Request } from './core/index.js'; +export * from './core/index.js'; +export * from './core/errors.js'; +export type { Delays } from './core/timed-out.js'; +export { default as calculateRetryDelay } from './core/calculate-retry-delay.js'; +export * from './as-promise/types.js'; +export * from './types.js'; +export { default as create } from './create.js'; +export { default as parseLinkHeader } from './core/parse-link-header.js'; diff --git a/includes/external/addressbook/node_modules/got/dist/source/index.js b/includes/external/addressbook/node_modules/got/dist/source/index.js new file mode 100644 index 0000000..4056297 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/index.js @@ -0,0 +1,20 @@ +import create from './create.js'; +import Options from './core/options.js'; +const defaults = { + options: new Options(), + handlers: [], + mutableDefaults: false, +}; +const got = create(defaults); +export default got; +export { got }; +export { default as Options } from './core/options.js'; +export * from './core/options.js'; +export * from './core/response.js'; +export * from './core/index.js'; +export * from './core/errors.js'; +export { default as calculateRetryDelay } from './core/calculate-retry-delay.js'; +export * from './as-promise/types.js'; +export * from './types.js'; +export { default as create } from './create.js'; +export { default as parseLinkHeader } from './core/parse-link-header.js'; diff --git a/includes/external/addressbook/node_modules/got/dist/source/types.d.ts b/includes/external/addressbook/node_modules/got/dist/source/types.d.ts new file mode 100644 index 0000000..3b76442 --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/types.d.ts @@ -0,0 +1,263 @@ +/// <reference types="node" resolution-mode="require"/> +/// <reference types="node" resolution-mode="require"/> +import type { Buffer } from 'node:buffer'; +import type { URL } from 'node:url'; +import type { CancelableRequest } from './as-promise/types.js'; +import type { Response } from './core/response.js'; +import type Options from './core/options.js'; +import type { PaginationOptions, OptionsInit } from './core/options.js'; +import type Request from './core/index.js'; +type Except<ObjectType, KeysType extends keyof ObjectType> = Pick<ObjectType, Exclude<keyof ObjectType, KeysType>>; +type Merge<FirstType, SecondType> = Except<FirstType, Extract<keyof FirstType, keyof SecondType>> & SecondType; +/** +Defaults for each Got instance. +*/ +export type InstanceDefaults = { + /** + An object containing the default options of Got. + */ + options: Options; + /** + An array of functions. You execute them directly by calling `got()`. + They are some sort of "global hooks" - these functions are called first. + The last handler (*it's hidden*) is either `asPromise` or `asStream`, depending on the `options.isStream` property. + + @default [] + */ + handlers: HandlerFunction[]; + /** + A read-only boolean describing whether the defaults are mutable or not. + If set to `true`, you can update headers over time, for example, update an access token when it expires. + + @default false + */ + mutableDefaults: boolean; +}; +/** +A Request object returned by calling Got, or any of the Got HTTP alias request functions. +*/ +export type GotReturn = Request | CancelableRequest; +/** +A function to handle options and returns a Request object. +It acts sort of like a "global hook", and will be called before any actual request is made. +*/ +export type HandlerFunction = <T extends GotReturn>(options: Options, next: (options: Options) => T) => T | Promise<T>; +/** +The options available for `got.extend()`. +*/ +export type ExtendOptions = { + /** + An array of functions. You execute them directly by calling `got()`. + They are some sort of "global hooks" - these functions are called first. + The last handler (*it's hidden*) is either `asPromise` or `asStream`, depending on the `options.isStream` property. + + @default [] + */ + handlers?: HandlerFunction[]; + /** + A read-only boolean describing whether the defaults are mutable or not. + If set to `true`, you can update headers over time, for example, update an access token when it expires. + + @default false + */ + mutableDefaults?: boolean; +} & OptionsInit; +export type OptionsOfTextResponseBody = Merge<OptionsInit, { + isStream?: false; + resolveBodyOnly?: false; + responseType?: 'text'; +}>; +export type OptionsOfJSONResponseBody = Merge<OptionsInit, { + isStream?: false; + resolveBodyOnly?: false; + responseType?: 'json'; +}>; +export type OptionsOfBufferResponseBody = Merge<OptionsInit, { + isStream?: false; + resolveBodyOnly?: false; + responseType: 'buffer'; +}>; +export type OptionsOfUnknownResponseBody = Merge<OptionsInit, { + isStream?: false; + resolveBodyOnly?: false; +}>; +export type StrictOptions = Except<OptionsInit, 'isStream' | 'responseType' | 'resolveBodyOnly'>; +export type StreamOptions = Merge<OptionsInit, { + isStream?: true; +}>; +type ResponseBodyOnly = { + resolveBodyOnly: true; +}; +export type OptionsWithPagination<T = unknown, R = unknown> = Merge<OptionsInit, { + pagination?: PaginationOptions<T, R>; +}>; +/** +An instance of `got.paginate`. +*/ +export type GotPaginate = { + /** + Same as `GotPaginate.each`. + */ + <T, R = unknown>(url: string | URL, options?: OptionsWithPagination<T, R>): AsyncIterableIterator<T>; + /** + Same as `GotPaginate.each`. + */ + <T, R = unknown>(options?: OptionsWithPagination<T, R>): AsyncIterableIterator<T>; + /** + Returns an async iterator. + + See pagination.options for more pagination options. + + @example + ``` + import got from 'got'; + + const countLimit = 10; + + const pagination = got.paginate('https://api.github.com/repos/sindresorhus/got/commits', { + pagination: {countLimit} + }); + + console.log(`Printing latest ${countLimit} Got commits (newest to oldest):`); + + for await (const commitData of pagination) { + console.log(commitData.commit.message); + } + ``` + */ + each: (<T, R = unknown>(url: string | URL, options?: OptionsWithPagination<T, R>) => AsyncIterableIterator<T>) & (<T, R = unknown>(options?: OptionsWithPagination<T, R>) => AsyncIterableIterator<T>); + /** + Returns a Promise for an array of all results. + + See pagination.options for more pagination options. + + @example + ``` + import got from 'got'; + + const countLimit = 10; + + const results = await got.paginate.all('https://api.github.com/repos/sindresorhus/got/commits', { + pagination: {countLimit} + }); + + console.log(`Printing latest ${countLimit} Got commits (newest to oldest):`); + console.log(results); + ``` + */ + all: (<T, R = unknown>(url: string | URL, options?: OptionsWithPagination<T, R>) => Promise<T[]>) & (<T, R = unknown>(options?: OptionsWithPagination<T, R>) => Promise<T[]>); +}; +export type GotRequestFunction = { + (url: string | URL, options?: OptionsOfTextResponseBody): CancelableRequest<Response<string>>; + <T>(url: string | URL, options?: OptionsOfJSONResponseBody): CancelableRequest<Response<T>>; + (url: string | URL, options?: OptionsOfBufferResponseBody): CancelableRequest<Response<Buffer>>; + (url: string | URL, options?: OptionsOfUnknownResponseBody): CancelableRequest<Response>; + (options: OptionsOfTextResponseBody): CancelableRequest<Response<string>>; + <T>(options: OptionsOfJSONResponseBody): CancelableRequest<Response<T>>; + (options: OptionsOfBufferResponseBody): CancelableRequest<Response<Buffer>>; + (options: OptionsOfUnknownResponseBody): CancelableRequest<Response>; + (url: string | URL, options?: (Merge<OptionsOfTextResponseBody, ResponseBodyOnly>)): CancelableRequest<string>; + <T>(url: string | URL, options?: (Merge<OptionsOfJSONResponseBody, ResponseBodyOnly>)): CancelableRequest<T>; + (url: string | URL, options?: (Merge<OptionsOfBufferResponseBody, ResponseBodyOnly>)): CancelableRequest<Buffer>; + (options: (Merge<OptionsOfTextResponseBody, ResponseBodyOnly>)): CancelableRequest<string>; + <T>(options: (Merge<OptionsOfJSONResponseBody, ResponseBodyOnly>)): CancelableRequest<T>; + (options: (Merge<OptionsOfBufferResponseBody, ResponseBodyOnly>)): CancelableRequest<Buffer>; + (url: string | URL, options?: Merge<OptionsInit, { + isStream: true; + }>): Request; + (options: Merge<OptionsInit, { + isStream: true; + }>): Request; + (url: string | URL, options?: OptionsInit): CancelableRequest | Request; + (options: OptionsInit): CancelableRequest | Request; + (url: undefined, options: undefined, defaults: Options): CancelableRequest | Request; +}; +/** +All available HTTP request methods provided by Got. +*/ +export type HTTPAlias = 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete'; +type GotStreamFunction = ((url?: string | URL, options?: Merge<OptionsInit, { + isStream?: true; +}>) => Request) & ((options?: Merge<OptionsInit, { + isStream?: true; +}>) => Request); +/** +An instance of `got.stream()`. +*/ +export type GotStream = GotStreamFunction & Record<HTTPAlias, GotStreamFunction>; +/** +An instance of `got`. +*/ +export type Got = { + /** + Sets `options.isStream` to `true`. + + Returns a [duplex stream](https://nodejs.org/api/stream.html#stream_class_stream_duplex) with additional events: + - request + - response + - redirect + - uploadProgress + - downloadProgress + - error + */ + stream: GotStream; + /** + Returns an async iterator. + + See pagination.options for more pagination options. + + @example + ``` + import got from 'got'; + + const countLimit = 10; + + const pagination = got.paginate('https://api.github.com/repos/sindresorhus/got/commits', { + pagination: {countLimit} + }); + + console.log(`Printing latest ${countLimit} Got commits (newest to oldest):`); + + for await (const commitData of pagination) { + console.log(commitData.commit.message); + } + ``` + */ + paginate: GotPaginate; + /** + The Got defaults used in that instance. + */ + defaults: InstanceDefaults; + /** + Configure a new `got` instance with default `options`. + The `options` are merged with the parent instance's `defaults.options` using `got.mergeOptions`. + You can access the resolved options with the `.defaults` property on the instance. + + Additionally, `got.extend()` accepts two properties from the `defaults` object: `mutableDefaults` and `handlers`. + + It is also possible to merges many instances into a single one: + - options are merged using `got.mergeOptions()` (including hooks), + - handlers are stored in an array (you can access them through `instance.defaults.handlers`). + + @example + ``` + import got from 'got'; + + const client = got.extend({ + prefixUrl: 'https://example.com', + headers: { + 'x-unicorn': 'rainbow' + } + }); + + client.get('demo'); + + // HTTP Request => + // GET /demo HTTP/1.1 + // Host: example.com + // x-unicorn: rainbow + ``` + */ + extend: (...instancesOrOptions: Array<Got | ExtendOptions>) => Got; +} & Record<HTTPAlias, GotRequestFunction> & GotRequestFunction; +export {}; diff --git a/includes/external/addressbook/node_modules/got/dist/source/types.js b/includes/external/addressbook/node_modules/got/dist/source/types.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/includes/external/addressbook/node_modules/got/dist/source/types.js @@ -0,0 +1 @@ +export {}; |