@npy/fetch 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/_internal/decode-stream-error.cjs +18 -0
- package/_internal/decode-stream-error.d.cts +11 -0
- package/_internal/decode-stream-error.d.ts +11 -0
- package/_internal/decode-stream-error.js +18 -0
- package/_internal/error-mapping.cjs +44 -0
- package/_internal/error-mapping.d.cts +15 -0
- package/_internal/error-mapping.d.ts +15 -0
- package/_internal/error-mapping.js +41 -0
- package/_internal/guards.cjs +5 -6
- package/{src/_internal → _internal}/guards.d.cts +2 -0
- package/{src/_internal → _internal}/guards.d.ts +2 -0
- package/_internal/guards.js +5 -7
- package/{src/_internal → _internal}/net.d.cts +1 -2
- package/{src/_internal → _internal}/net.d.ts +1 -2
- package/_internal/symbols.cjs +4 -0
- package/_internal/symbols.d.cts +1 -0
- package/_internal/symbols.d.ts +1 -0
- package/_internal/symbols.js +4 -0
- package/agent-pool.cjs +23 -5
- package/agent-pool.d.cts +2 -0
- package/agent-pool.d.ts +2 -0
- package/agent-pool.js +23 -5
- package/agent.cjs +17 -14
- package/agent.js +17 -14
- package/body.cjs +10 -59
- package/body.d.cts +12 -0
- package/body.d.ts +12 -0
- package/body.js +11 -60
- package/dialers/proxy.cjs +7 -0
- package/{src/dialers → dialers}/proxy.d.cts +11 -3
- package/{src/dialers → dialers}/proxy.d.ts +11 -3
- package/dialers/proxy.js +7 -0
- package/dialers/tcp.cjs +22 -0
- package/{src/dialers → dialers}/tcp.d.cts +23 -2
- package/{src/dialers → dialers}/tcp.d.ts +23 -2
- package/dialers/tcp.js +22 -0
- package/encoding.cjs +32 -13
- package/encoding.d.cts +35 -0
- package/encoding.d.ts +35 -0
- package/encoding.js +32 -13
- package/fetch.cjs +279 -43
- package/fetch.d.cts +58 -0
- package/fetch.d.ts +58 -0
- package/fetch.js +278 -43
- package/http-client.cjs +47 -5
- package/http-client.d.cts +39 -0
- package/http-client.d.ts +39 -0
- package/http-client.js +47 -5
- package/index.cjs +7 -3
- package/index.d.cts +14 -1
- package/index.d.ts +14 -1
- package/index.js +6 -4
- package/io/io.cjs +68 -4
- package/{src/io → io}/io.d.cts +1 -1
- package/{src/io → io}/io.d.ts +1 -1
- package/io/io.js +68 -4
- package/io/readers.cjs +14 -54
- package/io/readers.d.cts +69 -0
- package/io/readers.d.ts +69 -0
- package/io/readers.js +14 -54
- package/io/writers.cjs +10 -5
- package/{src/io → io}/writers.d.cts +1 -1
- package/{src/io → io}/writers.d.ts +1 -1
- package/io/writers.js +11 -6
- package/package.json +18 -2
- package/types/agent.d.cts +72 -0
- package/types/agent.d.ts +72 -0
- package/{src/types → types}/dialer.d.cts +3 -0
- package/{src/types → types}/dialer.d.ts +3 -0
- package/_internal/error-adapters.cjs +0 -146
- package/_internal/error-adapters.js +0 -142
- package/src/_internal/error-adapters.d.cts +0 -22
- package/src/_internal/error-adapters.d.ts +0 -22
- package/src/agent-pool.d.cts +0 -2
- package/src/agent-pool.d.ts +0 -2
- package/src/body.d.cts +0 -23
- package/src/body.d.ts +0 -23
- package/src/encoding.d.cts +0 -24
- package/src/encoding.d.ts +0 -24
- package/src/fetch.d.cts +0 -36
- package/src/fetch.d.ts +0 -36
- package/src/http-client.d.cts +0 -23
- package/src/http-client.d.ts +0 -23
- package/src/index.d.cts +0 -7
- package/src/index.d.ts +0 -7
- package/src/io/readers.d.cts +0 -199
- package/src/io/readers.d.ts +0 -199
- package/src/types/agent.d.cts +0 -128
- package/src/types/agent.d.ts +0 -128
- package/tests/test-utils.d.cts +0 -8
- package/tests/test-utils.d.ts +0 -8
- /package/{src/_internal → _internal}/consts.d.cts +0 -0
- /package/{src/_internal → _internal}/consts.d.ts +0 -0
- /package/{src/_internal → _internal}/promises.d.cts +0 -0
- /package/{src/_internal → _internal}/promises.d.ts +0 -0
- /package/{src/_internal → _internal}/streams.d.cts +0 -0
- /package/{src/_internal → _internal}/streams.d.ts +0 -0
- /package/{src/agent.d.cts → agent.d.cts} +0 -0
- /package/{src/agent.d.ts → agent.d.ts} +0 -0
- /package/{src/dialers → dialers}/index.d.cts +0 -0
- /package/{src/dialers → dialers}/index.d.ts +0 -0
- /package/{src/errors.d.cts → errors.d.cts} +0 -0
- /package/{src/errors.d.ts → errors.d.ts} +0 -0
- /package/{src/io → io}/_utils.d.cts +0 -0
- /package/{src/io → io}/_utils.d.ts +0 -0
- /package/{src/io → io}/buf-writer.d.cts +0 -0
- /package/{src/io → io}/buf-writer.d.ts +0 -0
- /package/{src/types → types}/index.d.cts +0 -0
- /package/{src/types → types}/index.d.ts +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/_internal/decode-stream-error.ts
|
|
2
|
+
/**
|
|
3
|
+
* Internal sentinel thrown when a decompression stream fails.
|
|
4
|
+
*
|
|
5
|
+
* Tagged at the source (inside createDecoder) so that error classifiers
|
|
6
|
+
* can use `instanceof` instead of heuristics on error messages or codes.
|
|
7
|
+
* Never exposed in the public API — callers receive ResponseDecodeError.
|
|
8
|
+
*/
|
|
9
|
+
var DecodeStreamError = class extends Error {
|
|
10
|
+
cause;
|
|
11
|
+
constructor(cause) {
|
|
12
|
+
super("Response decode failed", { cause });
|
|
13
|
+
this.name = "DecodeStreamError";
|
|
14
|
+
this.cause = cause;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
exports.DecodeStreamError = DecodeStreamError;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal sentinel thrown when a decompression stream fails.
|
|
3
|
+
*
|
|
4
|
+
* Tagged at the source (inside createDecoder) so that error classifiers
|
|
5
|
+
* can use `instanceof` instead of heuristics on error messages or codes.
|
|
6
|
+
* Never exposed in the public API — callers receive ResponseDecodeError.
|
|
7
|
+
*/
|
|
8
|
+
export declare class DecodeStreamError extends Error {
|
|
9
|
+
readonly cause: unknown;
|
|
10
|
+
constructor(cause: unknown);
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal sentinel thrown when a decompression stream fails.
|
|
3
|
+
*
|
|
4
|
+
* Tagged at the source (inside createDecoder) so that error classifiers
|
|
5
|
+
* can use `instanceof` instead of heuristics on error messages or codes.
|
|
6
|
+
* Never exposed in the public API — callers receive ResponseDecodeError.
|
|
7
|
+
*/
|
|
8
|
+
export declare class DecodeStreamError extends Error {
|
|
9
|
+
readonly cause: unknown;
|
|
10
|
+
constructor(cause: unknown);
|
|
11
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/_internal/decode-stream-error.ts
|
|
2
|
+
/**
|
|
3
|
+
* Internal sentinel thrown when a decompression stream fails.
|
|
4
|
+
*
|
|
5
|
+
* Tagged at the source (inside createDecoder) so that error classifiers
|
|
6
|
+
* can use `instanceof` instead of heuristics on error messages or codes.
|
|
7
|
+
* Never exposed in the public API — callers receive ResponseDecodeError.
|
|
8
|
+
*/
|
|
9
|
+
var DecodeStreamError = class extends Error {
|
|
10
|
+
cause;
|
|
11
|
+
constructor(cause) {
|
|
12
|
+
super("Response decode failed", { cause });
|
|
13
|
+
this.name = "DecodeStreamError";
|
|
14
|
+
this.cause = cause;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { DecodeStreamError };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const require_decode_stream_error = require("./decode-stream-error.cjs");
|
|
2
|
+
const require_errors = require("../errors.cjs");
|
|
3
|
+
//#region src/_internal/error-mapping.ts
|
|
4
|
+
/** Casts or converts the unknown into an Error */
|
|
5
|
+
function unknownToError(err) {
|
|
6
|
+
if (err instanceof Error) return err;
|
|
7
|
+
if (typeof err === "string") return new Error(err);
|
|
8
|
+
return new Error("unknown error", { cause: err });
|
|
9
|
+
}
|
|
10
|
+
function isAbortOrTimeoutError(error) {
|
|
11
|
+
if (!error || typeof error !== "object") return false;
|
|
12
|
+
const name = String(error.name ?? "");
|
|
13
|
+
return name === "AbortError" || name === "TimeoutError";
|
|
14
|
+
}
|
|
15
|
+
function toConnectError(error, { signal, context, timedOut }) {
|
|
16
|
+
if (error instanceof require_errors.FetchError) return error;
|
|
17
|
+
if (timedOut || signal?.reason?.name === "TimeoutError") return new require_errors.ConnectTimeoutError(unknownToError(error), context, "Connection timeout");
|
|
18
|
+
if (signal?.aborted || isAbortOrTimeoutError(error)) return new require_errors.RequestAbortedError(unknownToError(signal?.reason ?? error ?? new DOMException("This operation was aborted", "AbortError")), context, "The request was aborted while connecting");
|
|
19
|
+
return new require_errors.ConnectionError(unknownToError(error), context, "Connection failed");
|
|
20
|
+
}
|
|
21
|
+
function toSendError(error, { signal, context, phase }) {
|
|
22
|
+
if (error instanceof require_errors.FetchError) return error;
|
|
23
|
+
if (signal?.aborted || isAbortOrTimeoutError(error)) return new require_errors.RequestAbortedError(unknownToError(signal?.reason ?? error ?? new DOMException("This operation was aborted", "AbortError")), context, phase === "body" ? "The request was aborted while reading the response body" : "The request was aborted");
|
|
24
|
+
const cause = unknownToError(error);
|
|
25
|
+
if (phase === "request") return new require_errors.RequestWriteError(cause, context);
|
|
26
|
+
if (phase === "response") return new require_errors.ResponseHeaderError(cause, context);
|
|
27
|
+
if (error instanceof require_decode_stream_error.DecodeStreamError) return new require_errors.ResponseDecodeError(unknownToError(error.cause), context);
|
|
28
|
+
return new require_errors.ResponseBodyError(cause, context);
|
|
29
|
+
}
|
|
30
|
+
function toWebFetchError(error, signal) {
|
|
31
|
+
if (signal?.aborted) return signal.reason ?? new DOMException("This operation was aborted", "AbortError");
|
|
32
|
+
if (error instanceof DOMException || error instanceof TypeError) return error;
|
|
33
|
+
return new TypeError("fetch failed", { cause: unknownToError(error) });
|
|
34
|
+
}
|
|
35
|
+
function toWebBodyReadError(error, signal) {
|
|
36
|
+
if (signal?.aborted) return signal.reason ?? new DOMException("This operation was aborted", "AbortError");
|
|
37
|
+
if (error instanceof DOMException || error instanceof TypeError || error instanceof RangeError) return error;
|
|
38
|
+
return new TypeError("Failed to read response body", { cause: unknownToError(error) });
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
exports.toConnectError = toConnectError;
|
|
42
|
+
exports.toSendError = toSendError;
|
|
43
|
+
exports.toWebBodyReadError = toWebBodyReadError;
|
|
44
|
+
exports.toWebFetchError = toWebFetchError;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FetchError, FetchErrorContext } from '../errors';
|
|
2
|
+
/** Casts or converts the unknown into an Error */
|
|
3
|
+
export declare function unknownToError(err: unknown): Error;
|
|
4
|
+
export declare function toConnectError(error: unknown, { signal, context, timedOut, }: {
|
|
5
|
+
signal?: AbortSignal;
|
|
6
|
+
context?: FetchErrorContext;
|
|
7
|
+
timedOut?: boolean;
|
|
8
|
+
}): FetchError;
|
|
9
|
+
export declare function toSendError(error: unknown, { signal, context, phase, }: {
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
context?: FetchErrorContext;
|
|
12
|
+
phase: "request" | "response" | "body";
|
|
13
|
+
}): FetchError;
|
|
14
|
+
export declare function toWebFetchError(error: unknown, signal?: AbortSignal): unknown;
|
|
15
|
+
export declare function toWebBodyReadError(error: unknown, signal?: AbortSignal): unknown;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FetchError, FetchErrorContext } from '../errors';
|
|
2
|
+
/** Casts or converts the unknown into an Error */
|
|
3
|
+
export declare function unknownToError(err: unknown): Error;
|
|
4
|
+
export declare function toConnectError(error: unknown, { signal, context, timedOut, }: {
|
|
5
|
+
signal?: AbortSignal;
|
|
6
|
+
context?: FetchErrorContext;
|
|
7
|
+
timedOut?: boolean;
|
|
8
|
+
}): FetchError;
|
|
9
|
+
export declare function toSendError(error: unknown, { signal, context, phase, }: {
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
context?: FetchErrorContext;
|
|
12
|
+
phase: "request" | "response" | "body";
|
|
13
|
+
}): FetchError;
|
|
14
|
+
export declare function toWebFetchError(error: unknown, signal?: AbortSignal): unknown;
|
|
15
|
+
export declare function toWebBodyReadError(error: unknown, signal?: AbortSignal): unknown;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { DecodeStreamError } from "./decode-stream-error.js";
|
|
2
|
+
import { ConnectTimeoutError, ConnectionError, FetchError, RequestAbortedError, RequestWriteError, ResponseBodyError, ResponseDecodeError, ResponseHeaderError } from "../errors.js";
|
|
3
|
+
//#region src/_internal/error-mapping.ts
|
|
4
|
+
/** Casts or converts the unknown into an Error */
|
|
5
|
+
function unknownToError(err) {
|
|
6
|
+
if (err instanceof Error) return err;
|
|
7
|
+
if (typeof err === "string") return new Error(err);
|
|
8
|
+
return new Error("unknown error", { cause: err });
|
|
9
|
+
}
|
|
10
|
+
function isAbortOrTimeoutError(error) {
|
|
11
|
+
if (!error || typeof error !== "object") return false;
|
|
12
|
+
const name = String(error.name ?? "");
|
|
13
|
+
return name === "AbortError" || name === "TimeoutError";
|
|
14
|
+
}
|
|
15
|
+
function toConnectError(error, { signal, context, timedOut }) {
|
|
16
|
+
if (error instanceof FetchError) return error;
|
|
17
|
+
if (timedOut || signal?.reason?.name === "TimeoutError") return new ConnectTimeoutError(unknownToError(error), context, "Connection timeout");
|
|
18
|
+
if (signal?.aborted || isAbortOrTimeoutError(error)) return new RequestAbortedError(unknownToError(signal?.reason ?? error ?? new DOMException("This operation was aborted", "AbortError")), context, "The request was aborted while connecting");
|
|
19
|
+
return new ConnectionError(unknownToError(error), context, "Connection failed");
|
|
20
|
+
}
|
|
21
|
+
function toSendError(error, { signal, context, phase }) {
|
|
22
|
+
if (error instanceof FetchError) return error;
|
|
23
|
+
if (signal?.aborted || isAbortOrTimeoutError(error)) return new RequestAbortedError(unknownToError(signal?.reason ?? error ?? new DOMException("This operation was aborted", "AbortError")), context, phase === "body" ? "The request was aborted while reading the response body" : "The request was aborted");
|
|
24
|
+
const cause = unknownToError(error);
|
|
25
|
+
if (phase === "request") return new RequestWriteError(cause, context);
|
|
26
|
+
if (phase === "response") return new ResponseHeaderError(cause, context);
|
|
27
|
+
if (error instanceof DecodeStreamError) return new ResponseDecodeError(unknownToError(error.cause), context);
|
|
28
|
+
return new ResponseBodyError(cause, context);
|
|
29
|
+
}
|
|
30
|
+
function toWebFetchError(error, signal) {
|
|
31
|
+
if (signal?.aborted) return signal.reason ?? new DOMException("This operation was aborted", "AbortError");
|
|
32
|
+
if (error instanceof DOMException || error instanceof TypeError) return error;
|
|
33
|
+
return new TypeError("fetch failed", { cause: unknownToError(error) });
|
|
34
|
+
}
|
|
35
|
+
function toWebBodyReadError(error, signal) {
|
|
36
|
+
if (signal?.aborted) return signal.reason ?? new DOMException("This operation was aborted", "AbortError");
|
|
37
|
+
if (error instanceof DOMException || error instanceof TypeError || error instanceof RangeError) return error;
|
|
38
|
+
return new TypeError("Failed to read response body", { cause: unknownToError(error) });
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { toConnectError, toSendError, toWebBodyReadError, toWebFetchError };
|
package/_internal/guards.cjs
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
2
|
let node_stream = require("node:stream");
|
|
3
3
|
//#region src/_internal/guards.ts
|
|
4
|
-
var isReadable = (object) => node_stream.Readable.isReadable(object);
|
|
4
|
+
var isReadable = (object) => Boolean(node_stream.Readable.isReadable(object));
|
|
5
5
|
var isIterable = (object) => typeof object?.[Symbol.asyncIterator] === "function" || typeof object?.[Symbol.iterator] === "function";
|
|
6
|
-
var isMultipartFormDataStream = (object) => typeof object?.getBoundary === "function" && typeof object?.hasKnownLength === "function" && typeof object?.getLengthSync === "function" && node_stream.Readable.isReadable(object);
|
|
6
|
+
var isMultipartFormDataStream = (object) => typeof object?.getBoundary === "function" && typeof object?.hasKnownLength === "function" && typeof object?.getLengthSync === "function" && Boolean(node_stream.Readable.isReadable(object));
|
|
7
7
|
var isFormData = (object) => typeof object === "object" && typeof object?.append === "function" && typeof object?.set === "function" && typeof object?.get === "function" && typeof object?.getAll === "function" && typeof object?.delete === "function" && typeof object?.keys === "function" && typeof object?.values === "function" && typeof object?.entries === "function" && typeof object?.constructor === "function" && object?.[Symbol.toStringTag] === "FormData";
|
|
8
8
|
var isURLSearchParameters = (object) => typeof object === "object" && typeof object?.append === "function" && typeof object?.delete === "function" && typeof object?.get === "function" && typeof object?.getAll === "function" && typeof object?.has === "function" && typeof object?.set === "function" && typeof object?.sort === "function" && object?.[Symbol.toStringTag] === "URLSearchParams";
|
|
9
9
|
var isReadableStream = (object) => typeof object === "object" && typeof object?.getReader === "function" && typeof object?.cancel === "function" && typeof object?.tee === "function";
|
|
10
|
+
var isFumanReadable = (object) => typeof object?.read === "function" && typeof object?.close === "function" && !isReadable(object) && !isReadableStream(object);
|
|
10
11
|
var isBlob = (object) => {
|
|
11
|
-
if (typeof object === "object" && typeof object
|
|
12
|
-
const tag = object[Symbol.toStringTag];
|
|
13
|
-
return typeof tag === "string" && (tag.startsWith("Blob") || tag.startsWith("File"));
|
|
14
|
-
}
|
|
12
|
+
if (typeof object === "object" && object !== null && typeof object.arrayBuffer === "function" && typeof object.size === "number" && typeof object.slice === "function" && typeof object.stream === "function" && typeof object.text === "function" && typeof object.type === "string") return true;
|
|
15
13
|
return false;
|
|
16
14
|
};
|
|
17
15
|
//#endregion
|
|
18
16
|
exports.isBlob = isBlob;
|
|
19
17
|
exports.isFormData = isFormData;
|
|
18
|
+
exports.isFumanReadable = isFumanReadable;
|
|
20
19
|
exports.isIterable = isIterable;
|
|
21
20
|
exports.isMultipartFormDataStream = isMultipartFormDataStream;
|
|
22
21
|
exports.isReadable = isReadable;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Readable } from 'node:stream';
|
|
2
|
+
import { IClosable, IReadable } from '@fuman/io';
|
|
2
3
|
export interface FormDataPolyfill extends Readable {
|
|
3
4
|
getBoundary(): string;
|
|
4
5
|
getLengthSync(): number;
|
|
@@ -10,4 +11,5 @@ export declare const isMultipartFormDataStream: (object: any) => object is FormD
|
|
|
10
11
|
export declare const isFormData: (object: any) => object is FormData;
|
|
11
12
|
export declare const isURLSearchParameters: (object: any) => object is URLSearchParams;
|
|
12
13
|
export declare const isReadableStream: (object: any) => object is ReadableStream;
|
|
14
|
+
export declare const isFumanReadable: (object: any) => object is IReadable & IClosable;
|
|
13
15
|
export declare const isBlob: (object: any) => object is Blob;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Readable } from 'node:stream';
|
|
2
|
+
import { IClosable, IReadable } from '@fuman/io';
|
|
2
3
|
export interface FormDataPolyfill extends Readable {
|
|
3
4
|
getBoundary(): string;
|
|
4
5
|
getLengthSync(): number;
|
|
@@ -10,4 +11,5 @@ export declare const isMultipartFormDataStream: (object: any) => object is FormD
|
|
|
10
11
|
export declare const isFormData: (object: any) => object is FormData;
|
|
11
12
|
export declare const isURLSearchParameters: (object: any) => object is URLSearchParams;
|
|
12
13
|
export declare const isReadableStream: (object: any) => object is ReadableStream;
|
|
14
|
+
export declare const isFumanReadable: (object: any) => object is IReadable & IClosable;
|
|
13
15
|
export declare const isBlob: (object: any) => object is Blob;
|
package/_internal/guards.js
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { Readable } from "node:stream";
|
|
2
2
|
//#region src/_internal/guards.ts
|
|
3
|
-
var isReadable = (object) => Readable.isReadable(object);
|
|
3
|
+
var isReadable = (object) => Boolean(Readable.isReadable(object));
|
|
4
4
|
var isIterable = (object) => typeof object?.[Symbol.asyncIterator] === "function" || typeof object?.[Symbol.iterator] === "function";
|
|
5
|
-
var isMultipartFormDataStream = (object) => typeof object?.getBoundary === "function" && typeof object?.hasKnownLength === "function" && typeof object?.getLengthSync === "function" && Readable.isReadable(object);
|
|
5
|
+
var isMultipartFormDataStream = (object) => typeof object?.getBoundary === "function" && typeof object?.hasKnownLength === "function" && typeof object?.getLengthSync === "function" && Boolean(Readable.isReadable(object));
|
|
6
6
|
var isFormData = (object) => typeof object === "object" && typeof object?.append === "function" && typeof object?.set === "function" && typeof object?.get === "function" && typeof object?.getAll === "function" && typeof object?.delete === "function" && typeof object?.keys === "function" && typeof object?.values === "function" && typeof object?.entries === "function" && typeof object?.constructor === "function" && object?.[Symbol.toStringTag] === "FormData";
|
|
7
7
|
var isURLSearchParameters = (object) => typeof object === "object" && typeof object?.append === "function" && typeof object?.delete === "function" && typeof object?.get === "function" && typeof object?.getAll === "function" && typeof object?.has === "function" && typeof object?.set === "function" && typeof object?.sort === "function" && object?.[Symbol.toStringTag] === "URLSearchParams";
|
|
8
8
|
var isReadableStream = (object) => typeof object === "object" && typeof object?.getReader === "function" && typeof object?.cancel === "function" && typeof object?.tee === "function";
|
|
9
|
+
var isFumanReadable = (object) => typeof object?.read === "function" && typeof object?.close === "function" && !isReadable(object) && !isReadableStream(object);
|
|
9
10
|
var isBlob = (object) => {
|
|
10
|
-
if (typeof object === "object" && typeof object
|
|
11
|
-
const tag = object[Symbol.toStringTag];
|
|
12
|
-
return typeof tag === "string" && (tag.startsWith("Blob") || tag.startsWith("File"));
|
|
13
|
-
}
|
|
11
|
+
if (typeof object === "object" && object !== null && typeof object.arrayBuffer === "function" && typeof object.size === "number" && typeof object.slice === "function" && typeof object.stream === "function" && typeof object.text === "function" && typeof object.type === "string") return true;
|
|
14
12
|
return false;
|
|
15
13
|
};
|
|
16
14
|
//#endregion
|
|
17
|
-
export { isBlob, isFormData, isIterable, isMultipartFormDataStream, isReadable, isReadableStream, isURLSearchParameters };
|
|
15
|
+
export { isBlob, isFormData, isFumanReadable, isIterable, isMultipartFormDataStream, isReadable, isReadableStream, isURLSearchParameters };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConnectFunction, TcpEndpoint, TlsUpgradeFunction } from '@fuman/net';
|
|
2
2
|
import { NodeTlsConnectOptions, NodeTlsUpgradeOptions, TcpConnection, TlsConnection } from '@fuman/node';
|
|
3
|
-
type WithSignal<T = {}> = T & {
|
|
3
|
+
export type WithSignal<T = {}> = T & {
|
|
4
4
|
signal?: AbortSignal;
|
|
5
5
|
};
|
|
6
6
|
export interface AbortError extends Error {
|
|
@@ -9,4 +9,3 @@ export interface AbortError extends Error {
|
|
|
9
9
|
export declare const connectTcp: ConnectFunction<WithSignal<TcpEndpoint>, TcpConnection>;
|
|
10
10
|
export declare const connectTls: ConnectFunction<WithSignal<NodeTlsConnectOptions>, TlsConnection>;
|
|
11
11
|
export declare const upgradeTls: TlsUpgradeFunction<WithSignal<NodeTlsUpgradeOptions>, TcpConnection, TlsConnection>;
|
|
12
|
-
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConnectFunction, TcpEndpoint, TlsUpgradeFunction } from '@fuman/net';
|
|
2
2
|
import { NodeTlsConnectOptions, NodeTlsUpgradeOptions, TcpConnection, TlsConnection } from '@fuman/node';
|
|
3
|
-
type WithSignal<T = {}> = T & {
|
|
3
|
+
export type WithSignal<T = {}> = T & {
|
|
4
4
|
signal?: AbortSignal;
|
|
5
5
|
};
|
|
6
6
|
export interface AbortError extends Error {
|
|
@@ -9,4 +9,3 @@ export interface AbortError extends Error {
|
|
|
9
9
|
export declare const connectTcp: ConnectFunction<WithSignal<TcpEndpoint>, TcpConnection>;
|
|
10
10
|
export declare const connectTls: ConnectFunction<WithSignal<NodeTlsConnectOptions>, TlsConnection>;
|
|
11
11
|
export declare const upgradeTls: TlsUpgradeFunction<WithSignal<NodeTlsUpgradeOptions>, TcpConnection, TlsConnection>;
|
|
12
|
-
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const bodyErrorMapperSymbol: unique symbol;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const bodyErrorMapperSymbol: unique symbol;
|
package/agent-pool.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require("./_virtual/_rolldown/runtime.cjs");
|
|
2
|
-
const require_tcp = require("./dialers/tcp.cjs");
|
|
3
2
|
const require_errors = require("./errors.cjs");
|
|
4
3
|
const require_agent = require("./agent.cjs");
|
|
4
|
+
const require_tcp = require("./dialers/tcp.cjs");
|
|
5
5
|
let generic_pool = require("generic-pool");
|
|
6
6
|
//#region src/agent-pool.ts
|
|
7
7
|
var defaultEvictionInterval = 1e4;
|
|
@@ -40,13 +40,14 @@ function createAgentPool(baseUrl, options = {}) {
|
|
|
40
40
|
min
|
|
41
41
|
});
|
|
42
42
|
let releaseAgentFns = [];
|
|
43
|
+
let closePromise;
|
|
43
44
|
async function send(sendOptions) {
|
|
44
45
|
let agent;
|
|
45
46
|
let agentReleased = false;
|
|
46
47
|
const releaseAgentFn = async (forceClose = false) => {
|
|
47
48
|
if (!agent || agentReleased) return;
|
|
48
49
|
agentReleased = true;
|
|
49
|
-
releaseAgentFns = releaseAgentFns.filter((
|
|
50
|
+
releaseAgentFns = releaseAgentFns.filter((release) => release !== releaseAgentFn);
|
|
50
51
|
if (forceClose) agent.close();
|
|
51
52
|
if (pool.isBorrowedResource(agent)) await pool.release(agent);
|
|
52
53
|
};
|
|
@@ -62,9 +63,26 @@ function createAgentPool(baseUrl, options = {}) {
|
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
async function close() {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
if (closePromise) return closePromise;
|
|
67
|
+
const promise = (async () => {
|
|
68
|
+
const pendingReleases = releaseAgentFns;
|
|
69
|
+
releaseAgentFns = [];
|
|
70
|
+
const errors = (await Promise.allSettled([...pendingReleases.map((release) => release(true)), (async () => {
|
|
71
|
+
try {
|
|
72
|
+
await pool.drain();
|
|
73
|
+
} finally {
|
|
74
|
+
await pool.clear();
|
|
75
|
+
}
|
|
76
|
+
})()])).flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
77
|
+
if (errors.length === 1) throw errors[0];
|
|
78
|
+
if (errors.length > 1) throw new AggregateError(errors, "Failed to close agent pool cleanly");
|
|
79
|
+
})();
|
|
80
|
+
closePromise = promise;
|
|
81
|
+
try {
|
|
82
|
+
await promise;
|
|
83
|
+
} finally {
|
|
84
|
+
if (closePromise === promise) closePromise = void 0;
|
|
85
|
+
}
|
|
68
86
|
}
|
|
69
87
|
return {
|
|
70
88
|
[Symbol.asyncDispose]: close,
|
package/agent-pool.d.cts
ADDED
package/agent-pool.d.ts
ADDED
package/agent-pool.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AutoDialer } from "./dialers/tcp.js";
|
|
2
1
|
import { UnsupportedProtocolError } from "./errors.js";
|
|
3
2
|
import { createAgent } from "./agent.js";
|
|
3
|
+
import { AutoDialer } from "./dialers/tcp.js";
|
|
4
4
|
import { createPool } from "generic-pool";
|
|
5
5
|
//#region src/agent-pool.ts
|
|
6
6
|
var defaultEvictionInterval = 1e4;
|
|
@@ -39,13 +39,14 @@ function createAgentPool(baseUrl, options = {}) {
|
|
|
39
39
|
min
|
|
40
40
|
});
|
|
41
41
|
let releaseAgentFns = [];
|
|
42
|
+
let closePromise;
|
|
42
43
|
async function send(sendOptions) {
|
|
43
44
|
let agent;
|
|
44
45
|
let agentReleased = false;
|
|
45
46
|
const releaseAgentFn = async (forceClose = false) => {
|
|
46
47
|
if (!agent || agentReleased) return;
|
|
47
48
|
agentReleased = true;
|
|
48
|
-
releaseAgentFns = releaseAgentFns.filter((
|
|
49
|
+
releaseAgentFns = releaseAgentFns.filter((release) => release !== releaseAgentFn);
|
|
49
50
|
if (forceClose) agent.close();
|
|
50
51
|
if (pool.isBorrowedResource(agent)) await pool.release(agent);
|
|
51
52
|
};
|
|
@@ -61,9 +62,26 @@ function createAgentPool(baseUrl, options = {}) {
|
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
64
|
async function close() {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
if (closePromise) return closePromise;
|
|
66
|
+
const promise = (async () => {
|
|
67
|
+
const pendingReleases = releaseAgentFns;
|
|
68
|
+
releaseAgentFns = [];
|
|
69
|
+
const errors = (await Promise.allSettled([...pendingReleases.map((release) => release(true)), (async () => {
|
|
70
|
+
try {
|
|
71
|
+
await pool.drain();
|
|
72
|
+
} finally {
|
|
73
|
+
await pool.clear();
|
|
74
|
+
}
|
|
75
|
+
})()])).flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
76
|
+
if (errors.length === 1) throw errors[0];
|
|
77
|
+
if (errors.length > 1) throw new AggregateError(errors, "Failed to close agent pool cleanly");
|
|
78
|
+
})();
|
|
79
|
+
closePromise = promise;
|
|
80
|
+
try {
|
|
81
|
+
await promise;
|
|
82
|
+
} finally {
|
|
83
|
+
if (closePromise === promise) closePromise = void 0;
|
|
84
|
+
}
|
|
67
85
|
}
|
|
68
86
|
return {
|
|
69
87
|
[Symbol.asyncDispose]: close,
|
package/agent.cjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
require("./_virtual/_rolldown/runtime.cjs");
|
|
2
2
|
const require_errors = require("./errors.cjs");
|
|
3
|
-
const
|
|
3
|
+
const require_error_mapping = require("./_internal/error-mapping.cjs");
|
|
4
4
|
const require_promises = require("./_internal/promises.cjs");
|
|
5
|
+
const require_symbols = require("./_internal/symbols.cjs");
|
|
5
6
|
const require_io = require("./io/io.cjs");
|
|
6
7
|
let _fuman_utils = require("@fuman/utils");
|
|
7
8
|
//#region src/agent.ts
|
|
@@ -104,9 +105,7 @@ function createAgent(dialer, baseUrl, options = {}) {
|
|
|
104
105
|
let timedOut = false;
|
|
105
106
|
let timeoutId;
|
|
106
107
|
const abortController = new AbortController();
|
|
107
|
-
const onAbort = () =>
|
|
108
|
-
abortController.abort(signal?.reason);
|
|
109
|
-
};
|
|
108
|
+
const onAbort = () => abortController.abort(signal?.reason);
|
|
110
109
|
const cleanup = () => {
|
|
111
110
|
if (timeoutId !== void 0) {
|
|
112
111
|
clearTimeout(timeoutId);
|
|
@@ -142,7 +141,7 @@ function createAgent(dialer, baseUrl, options = {}) {
|
|
|
142
141
|
conn = nextConn;
|
|
143
142
|
return nextConn;
|
|
144
143
|
} catch (error) {
|
|
145
|
-
throw
|
|
144
|
+
throw require_error_mapping.toConnectError(error, {
|
|
146
145
|
signal,
|
|
147
146
|
timedOut,
|
|
148
147
|
context: createBaseErrorContext()
|
|
@@ -154,7 +153,7 @@ function createAgent(dialer, baseUrl, options = {}) {
|
|
|
154
153
|
})();
|
|
155
154
|
return withSignal(connectPromise, signal);
|
|
156
155
|
}
|
|
157
|
-
async function
|
|
156
|
+
async function executeRequest(sendOptions, mapBodyError) {
|
|
158
157
|
assertUsable();
|
|
159
158
|
const url = typeof sendOptions.url === "string" ? new URL(sendOptions.url) : sendOptions.url;
|
|
160
159
|
const method = sendOptions.method.toUpperCase();
|
|
@@ -198,7 +197,7 @@ function createAgent(dialer, baseUrl, options = {}) {
|
|
|
198
197
|
signal: sendOptions.signal
|
|
199
198
|
}, writerOptions), sendOptions.signal);
|
|
200
199
|
} catch (error) {
|
|
201
|
-
throw
|
|
200
|
+
throw require_error_mapping.toSendError(error, {
|
|
202
201
|
signal: sendOptions.signal,
|
|
203
202
|
context: errorContext,
|
|
204
203
|
phase: "request"
|
|
@@ -211,19 +210,15 @@ function createAgent(dialer, baseUrl, options = {}) {
|
|
|
211
210
|
response = await withSignal(require_io.readResponse(activeConn, readerOptions, shouldIgnoreBody, (reusable) => {
|
|
212
211
|
sendOptions.signal?.removeEventListener("abort", abortListener);
|
|
213
212
|
finalize(reusable);
|
|
214
|
-
}), sendOptions.signal);
|
|
213
|
+
}, mapBodyError), sendOptions.signal);
|
|
215
214
|
} catch (error) {
|
|
216
|
-
throw
|
|
215
|
+
throw require_error_mapping.toSendError(error, {
|
|
217
216
|
signal: sendOptions.signal,
|
|
218
217
|
context: errorContext,
|
|
219
218
|
phase: "response"
|
|
220
219
|
});
|
|
221
220
|
}
|
|
222
|
-
return
|
|
223
|
-
signal: sendOptions.signal,
|
|
224
|
-
context: errorContext,
|
|
225
|
-
phase: "body"
|
|
226
|
-
}));
|
|
221
|
+
return response;
|
|
227
222
|
} catch (error) {
|
|
228
223
|
sendOptions.signal?.removeEventListener("abort", abortListener);
|
|
229
224
|
if (activeConn) {
|
|
@@ -236,6 +231,14 @@ function createAgent(dialer, baseUrl, options = {}) {
|
|
|
236
231
|
throw error;
|
|
237
232
|
}
|
|
238
233
|
}
|
|
234
|
+
async function send(sendOptions) {
|
|
235
|
+
const errorContext = createRequestErrorContext(typeof sendOptions.url === "string" ? new URL(sendOptions.url) : sendOptions.url, sendOptions.method.toUpperCase());
|
|
236
|
+
return executeRequest(sendOptions, sendOptions[require_symbols.bodyErrorMapperSymbol] ?? ((error) => require_error_mapping.toSendError(error, {
|
|
237
|
+
signal: sendOptions.signal,
|
|
238
|
+
context: errorContext,
|
|
239
|
+
phase: "body"
|
|
240
|
+
})));
|
|
241
|
+
}
|
|
239
242
|
return {
|
|
240
243
|
[Symbol.dispose]: forceClose,
|
|
241
244
|
close: forceClose,
|
package/agent.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AgentBusyError, AgentClosedError, OriginMismatchError, RequestAbortedError, UnsupportedAlpnProtocolError, UnsupportedMethodError, UnsupportedProtocolError } from "./errors.js";
|
|
2
|
-
import {
|
|
2
|
+
import { toConnectError, toSendError } from "./_internal/error-mapping.js";
|
|
3
3
|
import { raceSignal } from "./_internal/promises.js";
|
|
4
|
+
import { bodyErrorMapperSymbol } from "./_internal/symbols.js";
|
|
4
5
|
import { readResponse, writeRequest } from "./io/io.js";
|
|
5
6
|
import { Deferred } from "@fuman/utils";
|
|
6
7
|
//#region src/agent.ts
|
|
@@ -103,9 +104,7 @@ function createAgent(dialer, baseUrl, options = {}) {
|
|
|
103
104
|
let timedOut = false;
|
|
104
105
|
let timeoutId;
|
|
105
106
|
const abortController = new AbortController();
|
|
106
|
-
const onAbort = () =>
|
|
107
|
-
abortController.abort(signal?.reason);
|
|
108
|
-
};
|
|
107
|
+
const onAbort = () => abortController.abort(signal?.reason);
|
|
109
108
|
const cleanup = () => {
|
|
110
109
|
if (timeoutId !== void 0) {
|
|
111
110
|
clearTimeout(timeoutId);
|
|
@@ -141,7 +140,7 @@ function createAgent(dialer, baseUrl, options = {}) {
|
|
|
141
140
|
conn = nextConn;
|
|
142
141
|
return nextConn;
|
|
143
142
|
} catch (error) {
|
|
144
|
-
throw
|
|
143
|
+
throw toConnectError(error, {
|
|
145
144
|
signal,
|
|
146
145
|
timedOut,
|
|
147
146
|
context: createBaseErrorContext()
|
|
@@ -153,7 +152,7 @@ function createAgent(dialer, baseUrl, options = {}) {
|
|
|
153
152
|
})();
|
|
154
153
|
return withSignal(connectPromise, signal);
|
|
155
154
|
}
|
|
156
|
-
async function
|
|
155
|
+
async function executeRequest(sendOptions, mapBodyError) {
|
|
157
156
|
assertUsable();
|
|
158
157
|
const url = typeof sendOptions.url === "string" ? new URL(sendOptions.url) : sendOptions.url;
|
|
159
158
|
const method = sendOptions.method.toUpperCase();
|
|
@@ -197,7 +196,7 @@ function createAgent(dialer, baseUrl, options = {}) {
|
|
|
197
196
|
signal: sendOptions.signal
|
|
198
197
|
}, writerOptions), sendOptions.signal);
|
|
199
198
|
} catch (error) {
|
|
200
|
-
throw
|
|
199
|
+
throw toSendError(error, {
|
|
201
200
|
signal: sendOptions.signal,
|
|
202
201
|
context: errorContext,
|
|
203
202
|
phase: "request"
|
|
@@ -210,19 +209,15 @@ function createAgent(dialer, baseUrl, options = {}) {
|
|
|
210
209
|
response = await withSignal(readResponse(activeConn, readerOptions, shouldIgnoreBody, (reusable) => {
|
|
211
210
|
sendOptions.signal?.removeEventListener("abort", abortListener);
|
|
212
211
|
finalize(reusable);
|
|
213
|
-
}), sendOptions.signal);
|
|
212
|
+
}, mapBodyError), sendOptions.signal);
|
|
214
213
|
} catch (error) {
|
|
215
|
-
throw
|
|
214
|
+
throw toSendError(error, {
|
|
216
215
|
signal: sendOptions.signal,
|
|
217
216
|
context: errorContext,
|
|
218
217
|
phase: "response"
|
|
219
218
|
});
|
|
220
219
|
}
|
|
221
|
-
return
|
|
222
|
-
signal: sendOptions.signal,
|
|
223
|
-
context: errorContext,
|
|
224
|
-
phase: "body"
|
|
225
|
-
}));
|
|
220
|
+
return response;
|
|
226
221
|
} catch (error) {
|
|
227
222
|
sendOptions.signal?.removeEventListener("abort", abortListener);
|
|
228
223
|
if (activeConn) {
|
|
@@ -235,6 +230,14 @@ function createAgent(dialer, baseUrl, options = {}) {
|
|
|
235
230
|
throw error;
|
|
236
231
|
}
|
|
237
232
|
}
|
|
233
|
+
async function send(sendOptions) {
|
|
234
|
+
const errorContext = createRequestErrorContext(typeof sendOptions.url === "string" ? new URL(sendOptions.url) : sendOptions.url, sendOptions.method.toUpperCase());
|
|
235
|
+
return executeRequest(sendOptions, sendOptions[bodyErrorMapperSymbol] ?? ((error) => toSendError(error, {
|
|
236
|
+
signal: sendOptions.signal,
|
|
237
|
+
context: errorContext,
|
|
238
|
+
phase: "body"
|
|
239
|
+
})));
|
|
240
|
+
}
|
|
238
241
|
return {
|
|
239
242
|
[Symbol.dispose]: forceClose,
|
|
240
243
|
close: forceClose,
|