@depup/got 14.6.6-depup.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +36 -0
  2. package/changes.json +30 -0
  3. package/dist/source/as-promise/index.d.ts +3 -0
  4. package/dist/source/as-promise/index.js +204 -0
  5. package/dist/source/as-promise/types.d.ts +37 -0
  6. package/dist/source/as-promise/types.js +17 -0
  7. package/dist/source/core/calculate-retry-delay.d.ts +4 -0
  8. package/dist/source/core/calculate-retry-delay.js +29 -0
  9. package/dist/source/core/diagnostics-channel.d.ts +89 -0
  10. package/dist/source/core/diagnostics-channel.js +49 -0
  11. package/dist/source/core/errors.d.ts +102 -0
  12. package/dist/source/core/errors.js +147 -0
  13. package/dist/source/core/index.d.ts +192 -0
  14. package/dist/source/core/index.js +1339 -0
  15. package/dist/source/core/options.d.ts +1564 -0
  16. package/dist/source/core/options.js +1838 -0
  17. package/dist/source/core/parse-link-header.d.ts +4 -0
  18. package/dist/source/core/parse-link-header.js +33 -0
  19. package/dist/source/core/response.d.ts +109 -0
  20. package/dist/source/core/response.js +41 -0
  21. package/dist/source/core/timed-out.d.ts +31 -0
  22. package/dist/source/core/timed-out.js +136 -0
  23. package/dist/source/core/utils/defer-to-connect.d.ts +9 -0
  24. package/dist/source/core/utils/defer-to-connect.js +44 -0
  25. package/dist/source/core/utils/get-body-size.d.ts +2 -0
  26. package/dist/source/core/utils/get-body-size.js +37 -0
  27. package/dist/source/core/utils/is-client-request.d.ts +4 -0
  28. package/dist/source/core/utils/is-client-request.js +4 -0
  29. package/dist/source/core/utils/is-form-data.d.ts +7 -0
  30. package/dist/source/core/utils/is-form-data.js +4 -0
  31. package/dist/source/core/utils/is-unix-socket-url.d.ts +17 -0
  32. package/dist/source/core/utils/is-unix-socket-url.js +25 -0
  33. package/dist/source/core/utils/options-to-url.d.ts +12 -0
  34. package/dist/source/core/utils/options-to-url.js +48 -0
  35. package/dist/source/core/utils/proxy-events.d.ts +2 -0
  36. package/dist/source/core/utils/proxy-events.js +15 -0
  37. package/dist/source/core/utils/timer.d.ts +31 -0
  38. package/dist/source/core/utils/timer.js +162 -0
  39. package/dist/source/core/utils/unhandle.d.ts +10 -0
  40. package/dist/source/core/utils/unhandle.js +20 -0
  41. package/dist/source/core/utils/url-to-options.d.ts +14 -0
  42. package/dist/source/core/utils/url-to-options.js +22 -0
  43. package/dist/source/core/utils/weakable-map.d.ts +7 -0
  44. package/dist/source/core/utils/weakable-map.js +24 -0
  45. package/dist/source/create.d.ts +3 -0
  46. package/dist/source/create.js +188 -0
  47. package/dist/source/index.d.ts +16 -0
  48. package/dist/source/index.js +22 -0
  49. package/dist/source/types.d.ts +314 -0
  50. package/dist/source/types.js +1 -0
  51. package/license +9 -0
  52. package/package.json +197 -0
  53. package/readme.md +478 -0
@@ -0,0 +1,4 @@
1
+ export default function parseLinkHeader(link: string): {
2
+ reference: string;
3
+ parameters: Record<string, string>;
4
+ }[];
@@ -0,0 +1,33 @@
1
+ export default function parseLinkHeader(link) {
2
+ const parsed = [];
3
+ const items = link.split(',');
4
+ for (const item of items) {
5
+ // https://tools.ietf.org/html/rfc5988#section-5
6
+ const [rawUriReference, ...rawLinkParameters] = item.split(';');
7
+ const trimmedUriReference = rawUriReference.trim();
8
+ // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
9
+ if (trimmedUriReference[0] !== '<' || trimmedUriReference.at(-1) !== '>') {
10
+ throw new Error(`Invalid format of the Link header reference: ${trimmedUriReference}`);
11
+ }
12
+ const reference = trimmedUriReference.slice(1, -1);
13
+ const parameters = {};
14
+ if (rawLinkParameters.length === 0) {
15
+ throw new Error(`Unexpected end of Link header parameters: ${rawLinkParameters.join(';')}`);
16
+ }
17
+ for (const rawParameter of rawLinkParameters) {
18
+ const trimmedRawParameter = rawParameter.trim();
19
+ const center = trimmedRawParameter.indexOf('=');
20
+ if (center === -1) {
21
+ throw new Error(`Failed to parse Link header: ${link}`);
22
+ }
23
+ const name = trimmedRawParameter.slice(0, center).trim();
24
+ const value = trimmedRawParameter.slice(center + 1).trim();
25
+ parameters[name] = value;
26
+ }
27
+ parsed.push({
28
+ reference,
29
+ parameters,
30
+ });
31
+ }
32
+ return parsed;
33
+ }
@@ -0,0 +1,109 @@
1
+ import type { Buffer } from 'node:buffer';
2
+ import type { IncomingMessageWithTimings, Timings } from './utils/timer.js';
3
+ import { RequestError } from './errors.js';
4
+ import type { ParseJsonFunction, ResponseType } from './options.js';
5
+ import type Request from './index.js';
6
+ export type PlainResponse = {
7
+ /**
8
+ The original request URL.
9
+ */
10
+ requestUrl: URL;
11
+ /**
12
+ The redirect URLs.
13
+ */
14
+ redirectUrls: URL[];
15
+ /**
16
+ - `options` - The Got options that were set on this request.
17
+
18
+ __Note__: This is not a [http.ClientRequest](https://nodejs.org/api/http.html#http_class_http_clientrequest).
19
+ */
20
+ request: Request;
21
+ /**
22
+ The remote IP address.
23
+
24
+ This is hopefully a temporary limitation, see [lukechilds/cacheable-request#86](https://web.archive.org/web/20220804165050/https://github.com/jaredwray/cacheable-request/issues/86).
25
+
26
+ __Note__: Not available when the response is cached.
27
+ */
28
+ ip?: string;
29
+ /**
30
+ Whether the response was retrieved from the cache.
31
+ */
32
+ isFromCache: boolean;
33
+ /**
34
+ The status code of the response.
35
+ */
36
+ statusCode: number;
37
+ /**
38
+ The request URL or the final URL after redirects.
39
+ */
40
+ url: string;
41
+ /**
42
+ The object contains the following properties:
43
+
44
+ - `start` - Time when the request started.
45
+ - `socket` - Time when a socket was assigned to the request.
46
+ - `lookup` - Time when the DNS lookup finished.
47
+ - `connect` - Time when the socket successfully connected.
48
+ - `secureConnect` - Time when the socket securely connected.
49
+ - `upload` - Time when the request finished uploading.
50
+ - `response` - Time when the request fired `response` event.
51
+ - `end` - Time when the response fired `end` event.
52
+ - `error` - Time when the request fired `error` event.
53
+ - `abort` - Time when the request fired `abort` event.
54
+ - `phases`
55
+ - `wait` - `timings.socket - timings.start`
56
+ - `dns` - `timings.lookup - timings.socket`
57
+ - `tcp` - `timings.connect - timings.lookup`
58
+ - `tls` - `timings.secureConnect - timings.connect`
59
+ - `request` - `timings.upload - (timings.secureConnect || timings.connect)`
60
+ - `firstByte` - `timings.response - timings.upload`
61
+ - `download` - `timings.end - timings.response`
62
+ - `total` - `(timings.end || timings.error || timings.abort) - timings.start`
63
+
64
+ If something has not been measured yet, it will be `undefined`.
65
+
66
+ __Note__: The time is a `number` representing the milliseconds elapsed since the UNIX epoch.
67
+ */
68
+ timings: Timings;
69
+ /**
70
+ The number of times the request was retried.
71
+ */
72
+ retryCount: number;
73
+ /**
74
+ The raw result of the request.
75
+ */
76
+ rawBody?: Buffer;
77
+ /**
78
+ The result of the request.
79
+ */
80
+ body?: unknown;
81
+ /**
82
+ Whether the response was successful.
83
+
84
+ __Note__: Got throws automatically when `response.ok` is `false` and `throwHttpErrors` is `true`.
85
+ */
86
+ ok: boolean;
87
+ } & IncomingMessageWithTimings;
88
+ export type Response<T = unknown> = {
89
+ /**
90
+ The result of the request.
91
+ */
92
+ body: T;
93
+ /**
94
+ The raw result of the request.
95
+ */
96
+ rawBody: Buffer;
97
+ } & PlainResponse;
98
+ export declare const isResponseOk: (response: PlainResponse) => boolean;
99
+ /**
100
+ An error to be thrown when server response code is 2xx, and parsing body fails.
101
+ Includes a `response` property.
102
+ */
103
+ export declare class ParseError extends RequestError {
104
+ name: string;
105
+ code: string;
106
+ readonly response: Response;
107
+ constructor(error: Error, response: Response);
108
+ }
109
+ export declare const parseBody: (response: Response, responseType: ResponseType, parseJson: ParseJsonFunction, encoding?: BufferEncoding) => unknown;
@@ -0,0 +1,41 @@
1
+ import { RequestError } from './errors.js';
2
+ export const isResponseOk = (response) => {
3
+ const { statusCode } = response;
4
+ const { followRedirect } = response.request.options;
5
+ const shouldFollow = typeof followRedirect === 'function' ? followRedirect(response) : followRedirect;
6
+ const limitStatusCode = shouldFollow ? 299 : 399;
7
+ return (statusCode >= 200 && statusCode <= limitStatusCode) || statusCode === 304;
8
+ };
9
+ /**
10
+ An error to be thrown when server response code is 2xx, and parsing body fails.
11
+ Includes a `response` property.
12
+ */
13
+ export class ParseError extends RequestError {
14
+ name = 'ParseError';
15
+ code = 'ERR_BODY_PARSE_FAILURE';
16
+ constructor(error, response) {
17
+ const { options } = response.request;
18
+ super(`${error.message} in "${options.url.toString()}"`, error, response.request);
19
+ }
20
+ }
21
+ export const parseBody = (response, responseType, parseJson, encoding) => {
22
+ const { rawBody } = response;
23
+ try {
24
+ if (responseType === 'text') {
25
+ return rawBody.toString(encoding);
26
+ }
27
+ if (responseType === 'json') {
28
+ return rawBody.length === 0 ? '' : parseJson(rawBody.toString(encoding));
29
+ }
30
+ if (responseType === 'buffer') {
31
+ return rawBody;
32
+ }
33
+ }
34
+ catch (error) {
35
+ throw new ParseError(error, response);
36
+ }
37
+ throw new ParseError({
38
+ message: `Unknown body type '${responseType}'`,
39
+ name: 'Error',
40
+ }, response);
41
+ };
@@ -0,0 +1,31 @@
1
+ import type { ClientRequest } from 'node:http';
2
+ declare const reentry: unique symbol;
3
+ type TimedOutOptions = {
4
+ host?: string;
5
+ hostname?: string;
6
+ protocol?: string;
7
+ };
8
+ export type Delays = {
9
+ lookup?: number;
10
+ socket?: number;
11
+ connect?: number;
12
+ secureConnect?: number;
13
+ send?: number;
14
+ response?: number;
15
+ read?: number;
16
+ request?: number;
17
+ };
18
+ export type ErrorCode = 'ETIMEDOUT' | 'ECONNRESET' | 'EADDRINUSE' | 'ECONNREFUSED' | 'EPIPE' | 'ENOTFOUND' | 'ENETUNREACH' | 'EAI_AGAIN';
19
+ export declare class TimeoutError extends Error {
20
+ event: string;
21
+ name: string;
22
+ code: ErrorCode;
23
+ constructor(threshold: number, event: string);
24
+ }
25
+ export default function timedOut(request: ClientRequest, delays: Delays, options: TimedOutOptions): () => void;
26
+ declare module 'http' {
27
+ interface ClientRequest {
28
+ [reentry]?: boolean;
29
+ }
30
+ }
31
+ export {};
@@ -0,0 +1,136 @@
1
+ import net from 'node:net';
2
+ import unhandler from './utils/unhandle.js';
3
+ const reentry = Symbol('reentry');
4
+ const noop = () => { };
5
+ export class TimeoutError extends Error {
6
+ event;
7
+ name = 'TimeoutError';
8
+ code = 'ETIMEDOUT';
9
+ constructor(threshold, event) {
10
+ super(`Timeout awaiting '${event}' for ${threshold}ms`);
11
+ this.event = event;
12
+ }
13
+ }
14
+ export default function timedOut(request, delays, options) {
15
+ if (reentry in request) {
16
+ return noop;
17
+ }
18
+ request[reentry] = true;
19
+ const cancelers = [];
20
+ const { once, unhandleAll } = unhandler();
21
+ const handled = new Map();
22
+ const addTimeout = (delay, callback, event) => {
23
+ const timeout = setTimeout(callback, delay, delay, event);
24
+ timeout.unref?.();
25
+ const cancel = () => {
26
+ handled.set(event, true);
27
+ clearTimeout(timeout);
28
+ };
29
+ cancelers.push(cancel);
30
+ return cancel;
31
+ };
32
+ const { host, hostname } = options;
33
+ const timeoutHandler = (delay, event) => {
34
+ // Use setTimeout to allow for any cancelled events to be handled first,
35
+ // to prevent firing any TimeoutError unneeded when the event loop is busy or blocked
36
+ setTimeout(() => {
37
+ if (!handled.has(event)) {
38
+ request.destroy(new TimeoutError(delay, event));
39
+ }
40
+ }, 0);
41
+ };
42
+ const cancelTimeouts = () => {
43
+ for (const cancel of cancelers) {
44
+ cancel();
45
+ }
46
+ unhandleAll();
47
+ };
48
+ request.once('error', error => {
49
+ cancelTimeouts();
50
+ // Save original behavior
51
+ /* istanbul ignore next */
52
+ if (request.listenerCount('error') === 0) {
53
+ throw error;
54
+ }
55
+ });
56
+ if (delays.request !== undefined) {
57
+ const cancelTimeout = addTimeout(delays.request, timeoutHandler, 'request');
58
+ once(request, 'response', (response) => {
59
+ once(response, 'end', cancelTimeout);
60
+ });
61
+ }
62
+ if (delays.socket !== undefined) {
63
+ const { socket } = delays;
64
+ const socketTimeoutHandler = () => {
65
+ timeoutHandler(socket, 'socket');
66
+ };
67
+ request.setTimeout(socket, socketTimeoutHandler);
68
+ // `request.setTimeout(0)` causes a memory leak.
69
+ // We can just remove the listener and forget about the timer - it's unreffed.
70
+ // See https://github.com/sindresorhus/got/issues/690
71
+ cancelers.push(() => {
72
+ request.removeListener('timeout', socketTimeoutHandler);
73
+ });
74
+ }
75
+ const hasLookup = delays.lookup !== undefined;
76
+ const hasConnect = delays.connect !== undefined;
77
+ const hasSecureConnect = delays.secureConnect !== undefined;
78
+ const hasSend = delays.send !== undefined;
79
+ if (hasLookup || hasConnect || hasSecureConnect || hasSend) {
80
+ once(request, 'socket', (socket) => {
81
+ const { socketPath } = request;
82
+ /* istanbul ignore next: hard to test */
83
+ if (socket.connecting) {
84
+ const hasPath = Boolean(socketPath ?? net.isIP(hostname ?? host ?? '') !== 0);
85
+ if (hasLookup && !hasPath && socket.address().address === undefined) {
86
+ const cancelTimeout = addTimeout(delays.lookup, timeoutHandler, 'lookup');
87
+ once(socket, 'lookup', cancelTimeout);
88
+ }
89
+ if (hasConnect) {
90
+ const timeConnect = () => addTimeout(delays.connect, timeoutHandler, 'connect');
91
+ if (hasPath) {
92
+ once(socket, 'connect', timeConnect());
93
+ }
94
+ else {
95
+ once(socket, 'lookup', (error) => {
96
+ if (error === null) {
97
+ once(socket, 'connect', timeConnect());
98
+ }
99
+ });
100
+ }
101
+ }
102
+ if (hasSecureConnect && options.protocol === 'https:') {
103
+ once(socket, 'connect', () => {
104
+ const cancelTimeout = addTimeout(delays.secureConnect, timeoutHandler, 'secureConnect');
105
+ once(socket, 'secureConnect', cancelTimeout);
106
+ });
107
+ }
108
+ }
109
+ if (hasSend) {
110
+ const timeRequest = () => addTimeout(delays.send, timeoutHandler, 'send');
111
+ /* istanbul ignore next: hard to test */
112
+ if (socket.connecting) {
113
+ once(socket, 'connect', () => {
114
+ once(request, 'upload-complete', timeRequest());
115
+ });
116
+ }
117
+ else {
118
+ once(request, 'upload-complete', timeRequest());
119
+ }
120
+ }
121
+ });
122
+ }
123
+ if (delays.response !== undefined) {
124
+ once(request, 'upload-complete', () => {
125
+ const cancelTimeout = addTimeout(delays.response, timeoutHandler, 'response');
126
+ once(request, 'response', cancelTimeout);
127
+ });
128
+ }
129
+ if (delays.read !== undefined) {
130
+ once(request, 'response', (response) => {
131
+ const cancelTimeout = addTimeout(delays.read, timeoutHandler, 'read');
132
+ once(response, 'end', cancelTimeout);
133
+ });
134
+ }
135
+ return cancelTimeouts;
136
+ }
@@ -0,0 +1,9 @@
1
+ import type { Socket } from 'node:net';
2
+ import type { TLSSocket } from 'node:tls';
3
+ type Listeners = {
4
+ connect?: () => void;
5
+ secureConnect?: () => void;
6
+ close?: (hadError: boolean) => void;
7
+ };
8
+ declare const deferToConnect: (socket: TLSSocket | Socket, fn: Listeners | (() => void)) => void;
9
+ export default deferToConnect;
@@ -0,0 +1,44 @@
1
+ function isTlsSocket(socket) {
2
+ return 'encrypted' in socket;
3
+ }
4
+ const deferToConnect = (socket, fn) => {
5
+ let listeners;
6
+ if (typeof fn === 'function') {
7
+ const connect = fn;
8
+ listeners = { connect };
9
+ }
10
+ else {
11
+ listeners = fn;
12
+ }
13
+ const hasConnectListener = typeof listeners.connect === 'function';
14
+ const hasSecureConnectListener = typeof listeners.secureConnect === 'function';
15
+ const hasCloseListener = typeof listeners.close === 'function';
16
+ const onConnect = () => {
17
+ if (hasConnectListener) {
18
+ listeners.connect();
19
+ }
20
+ if (isTlsSocket(socket) && hasSecureConnectListener) {
21
+ if (socket.authorized) {
22
+ listeners.secureConnect();
23
+ }
24
+ else {
25
+ // Wait for secureConnect event (even if authorization fails, we need the timing)
26
+ socket.once('secureConnect', listeners.secureConnect);
27
+ }
28
+ }
29
+ if (hasCloseListener) {
30
+ socket.once('close', listeners.close);
31
+ }
32
+ };
33
+ if (socket.writable && !socket.connecting) {
34
+ onConnect();
35
+ }
36
+ else if (socket.connecting) {
37
+ socket.once('connect', onConnect);
38
+ }
39
+ else if (socket.destroyed && hasCloseListener) {
40
+ const hadError = '_hadError' in socket ? Boolean(socket._hadError) : false;
41
+ listeners.close(hadError);
42
+ }
43
+ };
44
+ export default deferToConnect;
@@ -0,0 +1,2 @@
1
+ import type { ClientRequestArgs } from 'node:http';
2
+ export default function getBodySize(body: unknown, headers: ClientRequestArgs['headers']): Promise<number | undefined>;
@@ -0,0 +1,37 @@
1
+ import { promisify } from 'node:util';
2
+ import is from '@sindresorhus/is';
3
+ import isFormData from './is-form-data.js';
4
+ export default async function getBodySize(body, headers) {
5
+ if (headers && 'content-length' in headers) {
6
+ return Number(headers['content-length']);
7
+ }
8
+ if (!body) {
9
+ return 0;
10
+ }
11
+ if (is.string(body)) {
12
+ return new TextEncoder().encode(body).byteLength;
13
+ }
14
+ if (is.buffer(body)) {
15
+ return body.length;
16
+ }
17
+ if (is.typedArray(body)) {
18
+ return body.byteLength;
19
+ }
20
+ if (isFormData(body)) {
21
+ try {
22
+ return await promisify(body.getLength.bind(body))();
23
+ }
24
+ catch (error) {
25
+ const typedError = error;
26
+ throw new Error('Cannot determine content-length for form-data with stream(s) of unknown length. '
27
+ + 'This is a limitation of the `form-data` package. '
28
+ + 'To fix this, either:\n'
29
+ + '1. Use the `knownLength` option when appending streams:\n'
30
+ + ' form.append(\'file\', stream, {knownLength: 12345});\n'
31
+ + '2. Switch to spec-compliant FormData (formdata-node package)\n'
32
+ + 'See: https://github.com/form-data/form-data#alternative-submission-methods\n'
33
+ + `Original error: ${typedError.message}`);
34
+ }
35
+ }
36
+ return undefined;
37
+ }
@@ -0,0 +1,4 @@
1
+ import type { Writable, Readable } from 'node:stream';
2
+ import type { ClientRequest } from 'node:http';
3
+ declare function isClientRequest(clientRequest: Writable | Readable): clientRequest is ClientRequest;
4
+ export default isClientRequest;
@@ -0,0 +1,4 @@
1
+ function isClientRequest(clientRequest) {
2
+ return clientRequest.writable && !clientRequest.writableEnded;
3
+ }
4
+ export default isClientRequest;
@@ -0,0 +1,7 @@
1
+ import type { Readable } from 'node:stream';
2
+ type FormData = {
3
+ getBoundary: () => string;
4
+ getLength: (callback: (error: Error | null, length: number) => void) => void;
5
+ } & Readable;
6
+ export default function isFormData(body: unknown): body is FormData;
7
+ export {};
@@ -0,0 +1,4 @@
1
+ import is from '@sindresorhus/is';
2
+ export default function isFormData(body) {
3
+ return is.nodeStream(body) && is.function(body.getBoundary);
4
+ }
@@ -0,0 +1,17 @@
1
+ export default function isUnixSocketURL(url: URL): boolean;
2
+ /**
3
+ Extract the socket path from a UNIX socket URL.
4
+
5
+ @example
6
+ ```
7
+ getUnixSocketPath(new URL('http://unix/foo:/path'));
8
+ //=> '/foo'
9
+
10
+ getUnixSocketPath(new URL('unix:/foo:/path'));
11
+ //=> '/foo'
12
+
13
+ getUnixSocketPath(new URL('http://example.com'));
14
+ //=> undefined
15
+ ```
16
+ */
17
+ export declare function getUnixSocketPath(url: URL): string | undefined;
@@ -0,0 +1,25 @@
1
+ // eslint-disable-next-line @typescript-eslint/naming-convention
2
+ export default function isUnixSocketURL(url) {
3
+ return url.protocol === 'unix:' || url.hostname === 'unix';
4
+ }
5
+ /**
6
+ Extract the socket path from a UNIX socket URL.
7
+
8
+ @example
9
+ ```
10
+ getUnixSocketPath(new URL('http://unix/foo:/path'));
11
+ //=> '/foo'
12
+
13
+ getUnixSocketPath(new URL('unix:/foo:/path'));
14
+ //=> '/foo'
15
+
16
+ getUnixSocketPath(new URL('http://example.com'));
17
+ //=> undefined
18
+ ```
19
+ */
20
+ export function getUnixSocketPath(url) {
21
+ if (!isUnixSocketURL(url)) {
22
+ return undefined;
23
+ }
24
+ return /(?<socketPath>.+?):(?<path>.+)/.exec(`${url.pathname}${url.search}`)?.groups?.socketPath;
25
+ }
@@ -0,0 +1,12 @@
1
+ export type URLOptions = {
2
+ href?: string;
3
+ protocol?: string;
4
+ host?: string;
5
+ hostname?: string;
6
+ port?: string | number;
7
+ pathname?: string;
8
+ search?: string;
9
+ searchParams?: unknown;
10
+ path?: string;
11
+ };
12
+ export default function optionsToUrl(origin: string, options: URLOptions): URL;
@@ -0,0 +1,48 @@
1
+ const keys = [
2
+ 'protocol',
3
+ 'host',
4
+ 'hostname',
5
+ 'port',
6
+ 'pathname',
7
+ 'search',
8
+ ];
9
+ export default function optionsToUrl(origin, options) {
10
+ if (options.path) {
11
+ if (options.pathname) {
12
+ throw new TypeError('Parameters `path` and `pathname` are mutually exclusive.');
13
+ }
14
+ if (options.search) {
15
+ throw new TypeError('Parameters `path` and `search` are mutually exclusive.');
16
+ }
17
+ if (options.searchParams) {
18
+ throw new TypeError('Parameters `path` and `searchParams` are mutually exclusive.');
19
+ }
20
+ }
21
+ if (options.search && options.searchParams) {
22
+ throw new TypeError('Parameters `search` and `searchParams` are mutually exclusive.');
23
+ }
24
+ if (!origin) {
25
+ if (!options.protocol) {
26
+ throw new TypeError('No URL protocol specified');
27
+ }
28
+ origin = `${options.protocol}//${options.hostname ?? options.host ?? ''}`;
29
+ }
30
+ const url = new URL(origin);
31
+ if (options.path) {
32
+ const searchIndex = options.path.indexOf('?');
33
+ if (searchIndex === -1) {
34
+ options.pathname = options.path;
35
+ }
36
+ else {
37
+ options.pathname = options.path.slice(0, searchIndex);
38
+ options.search = options.path.slice(searchIndex + 1);
39
+ }
40
+ delete options.path;
41
+ }
42
+ for (const key of keys) {
43
+ if (options[key]) {
44
+ url[key] = options[key].toString();
45
+ }
46
+ }
47
+ return url;
48
+ }
@@ -0,0 +1,2 @@
1
+ import type { EventEmitter } from 'node:events';
2
+ export default function proxyEvents(from: EventEmitter, to: EventEmitter, events: Readonly<string[]>): () => void;
@@ -0,0 +1,15 @@
1
+ export default function proxyEvents(from, to, events) {
2
+ const eventFunctions = {};
3
+ for (const event of events) {
4
+ const eventFunction = (...arguments_) => {
5
+ to.emit(event, ...arguments_);
6
+ };
7
+ eventFunctions[event] = eventFunction;
8
+ from.on(event, eventFunction);
9
+ }
10
+ return () => {
11
+ for (const [event, eventFunction] of Object.entries(eventFunctions)) {
12
+ from.off(event, eventFunction);
13
+ }
14
+ };
15
+ }
@@ -0,0 +1,31 @@
1
+ import type { ClientRequest, IncomingMessage } from 'node:http';
2
+ export type Timings = {
3
+ start: number;
4
+ socket?: number;
5
+ lookup?: number;
6
+ connect?: number;
7
+ secureConnect?: number;
8
+ upload?: number;
9
+ response?: number;
10
+ end?: number;
11
+ error?: number;
12
+ abort?: number;
13
+ phases: {
14
+ wait?: number;
15
+ dns?: number;
16
+ tcp?: number;
17
+ tls?: number;
18
+ request?: number;
19
+ firstByte?: number;
20
+ download?: number;
21
+ total?: number;
22
+ };
23
+ };
24
+ export type ClientRequestWithTimings = ClientRequest & {
25
+ timings?: Timings;
26
+ };
27
+ export type IncomingMessageWithTimings = IncomingMessage & {
28
+ timings?: Timings;
29
+ };
30
+ declare const timer: (request: ClientRequestWithTimings) => Timings;
31
+ export default timer;