@npy/fetch 0.1.3 → 0.1.4
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/LICENSE +21 -0
- package/_internal/consts.cjs +4 -0
- package/_internal/consts.d.cts +3 -0
- package/_internal/consts.d.ts +3 -0
- package/_internal/consts.js +4 -0
- package/_internal/decode-stream-error.cjs +18 -0
- package/{src/_internal/decode-stream-error.ts → _internal/decode-stream-error.d.cts} +2 -7
- 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 +23 -0
- package/_internal/guards.d.cts +15 -0
- package/_internal/guards.d.ts +15 -0
- package/_internal/guards.js +15 -0
- package/_internal/net.cjs +95 -0
- package/_internal/net.d.cts +11 -0
- package/_internal/net.d.ts +11 -0
- package/_internal/net.js +92 -0
- package/_internal/promises.cjs +18 -0
- package/_internal/promises.d.cts +1 -0
- package/_internal/promises.d.ts +1 -0
- package/_internal/promises.js +18 -0
- package/_internal/streams.cjs +37 -0
- package/_internal/streams.d.cts +21 -0
- package/_internal/streams.d.ts +21 -0
- package/_internal/streams.js +36 -0
- 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/_virtual/_rolldown/runtime.cjs +23 -0
- package/agent-pool.cjs +96 -0
- package/agent-pool.d.cts +2 -0
- package/agent-pool.d.ts +2 -0
- package/agent-pool.js +95 -0
- package/agent.cjs +260 -0
- package/agent.d.cts +3 -0
- package/agent.d.ts +3 -0
- package/agent.js +259 -0
- package/body.cjs +105 -0
- package/body.d.cts +12 -0
- package/body.d.ts +12 -0
- package/body.js +102 -0
- package/dialers/index.d.cts +3 -0
- package/dialers/index.d.ts +3 -0
- package/dialers/proxy.cjs +56 -0
- package/dialers/proxy.d.cts +27 -0
- package/dialers/proxy.d.ts +27 -0
- package/dialers/proxy.js +55 -0
- package/dialers/tcp.cjs +92 -0
- package/dialers/tcp.d.cts +57 -0
- package/dialers/tcp.d.ts +57 -0
- package/dialers/tcp.js +89 -0
- package/encoding.cjs +114 -0
- package/encoding.d.cts +35 -0
- package/encoding.d.ts +35 -0
- package/encoding.js +110 -0
- package/errors.cjs +275 -0
- package/errors.d.cts +110 -0
- package/errors.d.ts +110 -0
- package/errors.js +259 -0
- package/fetch.cjs +353 -0
- package/fetch.d.cts +58 -0
- package/fetch.d.ts +58 -0
- package/fetch.js +350 -0
- package/http-client.cjs +75 -0
- package/http-client.d.cts +39 -0
- package/http-client.d.ts +39 -0
- package/http-client.js +75 -0
- package/index.cjs +49 -0
- package/index.d.cts +14 -0
- package/index.d.ts +14 -0
- package/index.js +11 -0
- package/io/_utils.cjs +56 -0
- package/io/_utils.d.cts +10 -0
- package/io/_utils.d.ts +10 -0
- package/io/_utils.js +51 -0
- package/io/buf-writer.cjs +149 -0
- package/io/buf-writer.d.cts +13 -0
- package/io/buf-writer.d.ts +13 -0
- package/io/buf-writer.js +148 -0
- package/io/io.cjs +199 -0
- package/io/io.d.cts +5 -0
- package/io/io.d.ts +5 -0
- package/io/io.js +198 -0
- package/io/readers.cjs +337 -0
- package/io/readers.d.cts +69 -0
- package/io/readers.d.ts +69 -0
- package/io/readers.js +333 -0
- package/io/writers.cjs +196 -0
- package/io/writers.d.cts +22 -0
- package/io/writers.d.ts +22 -0
- package/io/writers.js +195 -0
- package/package.json +30 -25
- package/{src/types/agent.ts → types/agent.d.cts} +21 -47
- package/types/agent.d.ts +72 -0
- package/{src/types/dialer.ts → types/dialer.d.cts} +9 -19
- package/types/dialer.d.ts +30 -0
- package/types/index.d.cts +2 -0
- package/types/index.d.ts +2 -0
- package/bun.lock +0 -68
- package/examples/custom-proxy-client.ts +0 -32
- package/examples/http-client.ts +0 -47
- package/examples/proxy.ts +0 -16
- package/examples/simple.ts +0 -15
- package/src/_internal/consts.ts +0 -3
- package/src/_internal/error-mapping.ts +0 -160
- package/src/_internal/guards.ts +0 -78
- package/src/_internal/net.ts +0 -173
- package/src/_internal/promises.ts +0 -22
- package/src/_internal/streams.ts +0 -52
- package/src/_internal/symbols.ts +0 -1
- package/src/agent-pool.ts +0 -157
- package/src/agent.ts +0 -408
- package/src/body.ts +0 -179
- package/src/dialers/index.ts +0 -3
- package/src/dialers/proxy.ts +0 -102
- package/src/dialers/tcp.ts +0 -162
- package/src/encoding.ts +0 -222
- package/src/errors.ts +0 -357
- package/src/fetch.ts +0 -626
- package/src/http-client.ts +0 -111
- package/src/index.ts +0 -14
- package/src/io/_utils.ts +0 -82
- package/src/io/buf-writer.ts +0 -183
- package/src/io/io.ts +0 -322
- package/src/io/readers.ts +0 -576
- package/src/io/writers.ts +0 -331
- package/src/types/index.ts +0 -2
- package/tests/agent-pool.test.ts +0 -111
- package/tests/agent.test.ts +0 -134
- package/tests/body.test.ts +0 -228
- package/tests/errors.test.ts +0 -152
- package/tests/fetch.test.ts +0 -421
- package/tests/io-options.test.ts +0 -127
- package/tests/multipart.test.ts +0 -348
- package/tests/test-utils.ts +0 -335
- package/tsconfig.json +0 -15
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 matheus fernandes
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -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;
|
|
@@ -5,12 +5,7 @@
|
|
|
5
5
|
* can use `instanceof` instead of heuristics on error messages or codes.
|
|
6
6
|
* Never exposed in the public API — callers receive ResponseDecodeError.
|
|
7
7
|
*/
|
|
8
|
-
export class DecodeStreamError extends Error {
|
|
8
|
+
export declare class DecodeStreamError extends Error {
|
|
9
9
|
readonly cause: unknown;
|
|
10
|
-
|
|
11
|
-
constructor(cause: unknown) {
|
|
12
|
-
super("Response decode failed", { cause });
|
|
13
|
-
this.name = "DecodeStreamError";
|
|
14
|
-
this.cause = cause;
|
|
15
|
-
}
|
|
10
|
+
constructor(cause: unknown);
|
|
16
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 };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
let node_stream = require("node:stream");
|
|
3
|
+
//#region src/_internal/guards.ts
|
|
4
|
+
var isReadable = (object) => Boolean(node_stream.Readable.isReadable(object));
|
|
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" && Boolean(node_stream.Readable.isReadable(object));
|
|
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
|
+
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
|
+
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);
|
|
11
|
+
var isBlob = (object) => {
|
|
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;
|
|
13
|
+
return false;
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
exports.isBlob = isBlob;
|
|
17
|
+
exports.isFormData = isFormData;
|
|
18
|
+
exports.isFumanReadable = isFumanReadable;
|
|
19
|
+
exports.isIterable = isIterable;
|
|
20
|
+
exports.isMultipartFormDataStream = isMultipartFormDataStream;
|
|
21
|
+
exports.isReadable = isReadable;
|
|
22
|
+
exports.isReadableStream = isReadableStream;
|
|
23
|
+
exports.isURLSearchParameters = isURLSearchParameters;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
2
|
+
import { IClosable, IReadable } from '@fuman/io';
|
|
3
|
+
export interface FormDataPolyfill extends Readable {
|
|
4
|
+
getBoundary(): string;
|
|
5
|
+
getLengthSync(): number;
|
|
6
|
+
hasKnownLength(): boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare const isReadable: (object: any) => object is Readable;
|
|
9
|
+
export declare const isIterable: (object: any) => object is AsyncIterable<any> | Iterable<any>;
|
|
10
|
+
export declare const isMultipartFormDataStream: (object: any) => object is FormDataPolyfill;
|
|
11
|
+
export declare const isFormData: (object: any) => object is FormData;
|
|
12
|
+
export declare const isURLSearchParameters: (object: any) => object is URLSearchParams;
|
|
13
|
+
export declare const isReadableStream: (object: any) => object is ReadableStream;
|
|
14
|
+
export declare const isFumanReadable: (object: any) => object is IReadable & IClosable;
|
|
15
|
+
export declare const isBlob: (object: any) => object is Blob;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
2
|
+
import { IClosable, IReadable } from '@fuman/io';
|
|
3
|
+
export interface FormDataPolyfill extends Readable {
|
|
4
|
+
getBoundary(): string;
|
|
5
|
+
getLengthSync(): number;
|
|
6
|
+
hasKnownLength(): boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare const isReadable: (object: any) => object is Readable;
|
|
9
|
+
export declare const isIterable: (object: any) => object is AsyncIterable<any> | Iterable<any>;
|
|
10
|
+
export declare const isMultipartFormDataStream: (object: any) => object is FormDataPolyfill;
|
|
11
|
+
export declare const isFormData: (object: any) => object is FormData;
|
|
12
|
+
export declare const isURLSearchParameters: (object: any) => object is URLSearchParams;
|
|
13
|
+
export declare const isReadableStream: (object: any) => object is ReadableStream;
|
|
14
|
+
export declare const isFumanReadable: (object: any) => object is IReadable & IClosable;
|
|
15
|
+
export declare const isBlob: (object: any) => object is Blob;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Readable } from "node:stream";
|
|
2
|
+
//#region src/_internal/guards.ts
|
|
3
|
+
var isReadable = (object) => Boolean(Readable.isReadable(object));
|
|
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" && Boolean(Readable.isReadable(object));
|
|
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
|
+
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
|
+
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);
|
|
10
|
+
var isBlob = (object) => {
|
|
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;
|
|
12
|
+
return false;
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
export { isBlob, isFormData, isFumanReadable, isIterable, isMultipartFormDataStream, isReadable, isReadableStream, isURLSearchParameters };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
let node_net = require("node:net");
|
|
3
|
+
let node_tls = require("node:tls");
|
|
4
|
+
let _fuman_node = require("@fuman/node");
|
|
5
|
+
//#region src/_internal/net.ts
|
|
6
|
+
function toAbortError(reason) {
|
|
7
|
+
if (reason instanceof Error && reason.name === "AbortError") return reason;
|
|
8
|
+
const message = reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "The operation was aborted";
|
|
9
|
+
if (typeof DOMException !== "undefined") return new DOMException(message, "AbortError");
|
|
10
|
+
const error = new Error(message);
|
|
11
|
+
error.name = "AbortError";
|
|
12
|
+
return error;
|
|
13
|
+
}
|
|
14
|
+
function throwIfAborted(signal) {
|
|
15
|
+
if (signal?.aborted) throw toAbortError(signal.reason);
|
|
16
|
+
}
|
|
17
|
+
async function withSocketSignal(createSocket, wrapConnection, signal, readyEvent = "connect", onFailureCleanup) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
throwIfAborted(signal);
|
|
20
|
+
const socket = createSocket();
|
|
21
|
+
let settled = false;
|
|
22
|
+
const cleanup = () => {
|
|
23
|
+
socket.removeListener("error", onError);
|
|
24
|
+
socket.removeListener("timeout", onError);
|
|
25
|
+
socket.removeListener(readyEvent, onReady);
|
|
26
|
+
signal?.removeEventListener("abort", onAbort);
|
|
27
|
+
};
|
|
28
|
+
const safeCleanup = () => {
|
|
29
|
+
try {
|
|
30
|
+
onFailureCleanup?.();
|
|
31
|
+
} catch {}
|
|
32
|
+
};
|
|
33
|
+
const resolveOnce = (value) => {
|
|
34
|
+
if (settled) return;
|
|
35
|
+
settled = true;
|
|
36
|
+
cleanup();
|
|
37
|
+
resolve(value);
|
|
38
|
+
};
|
|
39
|
+
const rejectOnce = (error) => {
|
|
40
|
+
if (settled) return;
|
|
41
|
+
settled = true;
|
|
42
|
+
cleanup();
|
|
43
|
+
reject(error);
|
|
44
|
+
};
|
|
45
|
+
const onError = (error) => {
|
|
46
|
+
safeCleanup();
|
|
47
|
+
rejectOnce(error);
|
|
48
|
+
};
|
|
49
|
+
const onAbort = () => {
|
|
50
|
+
const error = toAbortError(signal?.reason);
|
|
51
|
+
safeCleanup();
|
|
52
|
+
rejectOnce(error);
|
|
53
|
+
try {
|
|
54
|
+
socket.destroy(error);
|
|
55
|
+
} catch {}
|
|
56
|
+
};
|
|
57
|
+
const onReady = () => {
|
|
58
|
+
resolveOnce(wrapConnection(socket));
|
|
59
|
+
};
|
|
60
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
61
|
+
socket.on("error", onError);
|
|
62
|
+
socket.on("timeout", onError);
|
|
63
|
+
socket.on(readyEvent, onReady);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
var connectTcp = async ({ address, port, signal }) => {
|
|
67
|
+
return withSocketSignal(() => (0, node_net.createConnection)({
|
|
68
|
+
host: address,
|
|
69
|
+
port
|
|
70
|
+
}), (socket) => new _fuman_node.TcpConnection(socket), signal);
|
|
71
|
+
};
|
|
72
|
+
var connectTls = async (options) => {
|
|
73
|
+
const { address, port, signal, sni, caCerts, alpnProtocols, extraOptions } = options;
|
|
74
|
+
return withSocketSignal(() => (0, node_tls.connect)({
|
|
75
|
+
host: address,
|
|
76
|
+
port,
|
|
77
|
+
ca: caCerts,
|
|
78
|
+
ALPNProtocols: alpnProtocols,
|
|
79
|
+
servername: sni,
|
|
80
|
+
...extraOptions
|
|
81
|
+
}), (socket) => new _fuman_node.TlsConnection(socket), signal, "secureConnect");
|
|
82
|
+
};
|
|
83
|
+
var upgradeTls = async (conn, options) => {
|
|
84
|
+
return withSocketSignal(() => (0, node_tls.connect)({
|
|
85
|
+
socket: conn.socket,
|
|
86
|
+
ca: options.caCerts,
|
|
87
|
+
ALPNProtocols: options.alpnProtocols,
|
|
88
|
+
servername: options.sni,
|
|
89
|
+
...options.extraOptions
|
|
90
|
+
}), (socket) => new _fuman_node.TlsConnection(socket), options.signal, "secureConnect", () => conn.close());
|
|
91
|
+
};
|
|
92
|
+
//#endregion
|
|
93
|
+
exports.connectTcp = connectTcp;
|
|
94
|
+
exports.connectTls = connectTls;
|
|
95
|
+
exports.upgradeTls = upgradeTls;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ConnectFunction, TcpEndpoint, TlsUpgradeFunction } from '@fuman/net';
|
|
2
|
+
import { NodeTlsConnectOptions, NodeTlsUpgradeOptions, TcpConnection, TlsConnection } from '@fuman/node';
|
|
3
|
+
export type WithSignal<T = {}> = T & {
|
|
4
|
+
signal?: AbortSignal;
|
|
5
|
+
};
|
|
6
|
+
export interface AbortError extends Error {
|
|
7
|
+
name: "AbortError";
|
|
8
|
+
}
|
|
9
|
+
export declare const connectTcp: ConnectFunction<WithSignal<TcpEndpoint>, TcpConnection>;
|
|
10
|
+
export declare const connectTls: ConnectFunction<WithSignal<NodeTlsConnectOptions>, TlsConnection>;
|
|
11
|
+
export declare const upgradeTls: TlsUpgradeFunction<WithSignal<NodeTlsUpgradeOptions>, TcpConnection, TlsConnection>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ConnectFunction, TcpEndpoint, TlsUpgradeFunction } from '@fuman/net';
|
|
2
|
+
import { NodeTlsConnectOptions, NodeTlsUpgradeOptions, TcpConnection, TlsConnection } from '@fuman/node';
|
|
3
|
+
export type WithSignal<T = {}> = T & {
|
|
4
|
+
signal?: AbortSignal;
|
|
5
|
+
};
|
|
6
|
+
export interface AbortError extends Error {
|
|
7
|
+
name: "AbortError";
|
|
8
|
+
}
|
|
9
|
+
export declare const connectTcp: ConnectFunction<WithSignal<TcpEndpoint>, TcpConnection>;
|
|
10
|
+
export declare const connectTls: ConnectFunction<WithSignal<NodeTlsConnectOptions>, TlsConnection>;
|
|
11
|
+
export declare const upgradeTls: TlsUpgradeFunction<WithSignal<NodeTlsUpgradeOptions>, TcpConnection, TlsConnection>;
|
package/_internal/net.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { createConnection } from "node:net";
|
|
2
|
+
import { connect } from "node:tls";
|
|
3
|
+
import { TcpConnection, TlsConnection } from "@fuman/node";
|
|
4
|
+
//#region src/_internal/net.ts
|
|
5
|
+
function toAbortError(reason) {
|
|
6
|
+
if (reason instanceof Error && reason.name === "AbortError") return reason;
|
|
7
|
+
const message = reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "The operation was aborted";
|
|
8
|
+
if (typeof DOMException !== "undefined") return new DOMException(message, "AbortError");
|
|
9
|
+
const error = new Error(message);
|
|
10
|
+
error.name = "AbortError";
|
|
11
|
+
return error;
|
|
12
|
+
}
|
|
13
|
+
function throwIfAborted(signal) {
|
|
14
|
+
if (signal?.aborted) throw toAbortError(signal.reason);
|
|
15
|
+
}
|
|
16
|
+
async function withSocketSignal(createSocket, wrapConnection, signal, readyEvent = "connect", onFailureCleanup) {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
throwIfAborted(signal);
|
|
19
|
+
const socket = createSocket();
|
|
20
|
+
let settled = false;
|
|
21
|
+
const cleanup = () => {
|
|
22
|
+
socket.removeListener("error", onError);
|
|
23
|
+
socket.removeListener("timeout", onError);
|
|
24
|
+
socket.removeListener(readyEvent, onReady);
|
|
25
|
+
signal?.removeEventListener("abort", onAbort);
|
|
26
|
+
};
|
|
27
|
+
const safeCleanup = () => {
|
|
28
|
+
try {
|
|
29
|
+
onFailureCleanup?.();
|
|
30
|
+
} catch {}
|
|
31
|
+
};
|
|
32
|
+
const resolveOnce = (value) => {
|
|
33
|
+
if (settled) return;
|
|
34
|
+
settled = true;
|
|
35
|
+
cleanup();
|
|
36
|
+
resolve(value);
|
|
37
|
+
};
|
|
38
|
+
const rejectOnce = (error) => {
|
|
39
|
+
if (settled) return;
|
|
40
|
+
settled = true;
|
|
41
|
+
cleanup();
|
|
42
|
+
reject(error);
|
|
43
|
+
};
|
|
44
|
+
const onError = (error) => {
|
|
45
|
+
safeCleanup();
|
|
46
|
+
rejectOnce(error);
|
|
47
|
+
};
|
|
48
|
+
const onAbort = () => {
|
|
49
|
+
const error = toAbortError(signal?.reason);
|
|
50
|
+
safeCleanup();
|
|
51
|
+
rejectOnce(error);
|
|
52
|
+
try {
|
|
53
|
+
socket.destroy(error);
|
|
54
|
+
} catch {}
|
|
55
|
+
};
|
|
56
|
+
const onReady = () => {
|
|
57
|
+
resolveOnce(wrapConnection(socket));
|
|
58
|
+
};
|
|
59
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
60
|
+
socket.on("error", onError);
|
|
61
|
+
socket.on("timeout", onError);
|
|
62
|
+
socket.on(readyEvent, onReady);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
var connectTcp = async ({ address, port, signal }) => {
|
|
66
|
+
return withSocketSignal(() => createConnection({
|
|
67
|
+
host: address,
|
|
68
|
+
port
|
|
69
|
+
}), (socket) => new TcpConnection(socket), signal);
|
|
70
|
+
};
|
|
71
|
+
var connectTls = async (options) => {
|
|
72
|
+
const { address, port, signal, sni, caCerts, alpnProtocols, extraOptions } = options;
|
|
73
|
+
return withSocketSignal(() => connect({
|
|
74
|
+
host: address,
|
|
75
|
+
port,
|
|
76
|
+
ca: caCerts,
|
|
77
|
+
ALPNProtocols: alpnProtocols,
|
|
78
|
+
servername: sni,
|
|
79
|
+
...extraOptions
|
|
80
|
+
}), (socket) => new TlsConnection(socket), signal, "secureConnect");
|
|
81
|
+
};
|
|
82
|
+
var upgradeTls = async (conn, options) => {
|
|
83
|
+
return withSocketSignal(() => connect({
|
|
84
|
+
socket: conn.socket,
|
|
85
|
+
ca: options.caCerts,
|
|
86
|
+
ALPNProtocols: options.alpnProtocols,
|
|
87
|
+
servername: options.sni,
|
|
88
|
+
...options.extraOptions
|
|
89
|
+
}), (socket) => new TlsConnection(socket), options.signal, "secureConnect", () => conn.close());
|
|
90
|
+
};
|
|
91
|
+
//#endregion
|
|
92
|
+
export { connectTcp, connectTls, upgradeTls };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/_internal/promises.ts
|
|
2
|
+
function raceSignal(promise, signal) {
|
|
3
|
+
return Promise.race([promise, new Promise((_, reject) => {
|
|
4
|
+
function onAbort() {
|
|
5
|
+
reject(signal.reason);
|
|
6
|
+
}
|
|
7
|
+
if (signal.aborted) onAbort();
|
|
8
|
+
else {
|
|
9
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
10
|
+
function cleanup() {
|
|
11
|
+
signal.removeEventListener("abort", onAbort);
|
|
12
|
+
}
|
|
13
|
+
promise.then(cleanup, cleanup);
|
|
14
|
+
}
|
|
15
|
+
})]);
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
exports.raceSignal = raceSignal;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function raceSignal<T>(promise: PromiseLike<T>, signal: AbortSignal): Promise<T>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function raceSignal<T>(promise: PromiseLike<T>, signal: AbortSignal): Promise<T>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/_internal/promises.ts
|
|
2
|
+
function raceSignal(promise, signal) {
|
|
3
|
+
return Promise.race([promise, new Promise((_, reject) => {
|
|
4
|
+
function onAbort() {
|
|
5
|
+
reject(signal.reason);
|
|
6
|
+
}
|
|
7
|
+
if (signal.aborted) onAbort();
|
|
8
|
+
else {
|
|
9
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
10
|
+
function cleanup() {
|
|
11
|
+
signal.removeEventListener("abort", onAbort);
|
|
12
|
+
}
|
|
13
|
+
promise.then(cleanup, cleanup);
|
|
14
|
+
}
|
|
15
|
+
})]);
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { raceSignal };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//#region src/_internal/streams.ts
|
|
2
|
+
/**
|
|
3
|
+
* Create a ReadableStream from a Uint8Array.
|
|
4
|
+
*
|
|
5
|
+
* The stream will emit the entire byte array as a single chunk,
|
|
6
|
+
* then close immediately.
|
|
7
|
+
*
|
|
8
|
+
* @param bytes - The byte array to wrap.
|
|
9
|
+
* @returns A ReadableStream that emits the bytes.
|
|
10
|
+
*/
|
|
11
|
+
function bytesToStream(bytes) {
|
|
12
|
+
return new ReadableStream({ start(controller) {
|
|
13
|
+
controller.enqueue(bytes);
|
|
14
|
+
controller.close();
|
|
15
|
+
} });
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A TransformStream that limits the total number of bytes passed through.
|
|
19
|
+
*
|
|
20
|
+
* It accumulates the byte count from incoming chunks and enqueues them
|
|
21
|
+
* if the total remains within the limit; otherwise, it errors.
|
|
22
|
+
*
|
|
23
|
+
* @param maxBytes - The maximum allowed bytes before erroring.
|
|
24
|
+
*/
|
|
25
|
+
var MaxBytesTransformStream = class extends TransformStream {
|
|
26
|
+
constructor(maxBytes) {
|
|
27
|
+
if (!(maxBytes >= 0)) throw new TypeError("maxBytes must be a non-negative number");
|
|
28
|
+
let bytesRead = 0;
|
|
29
|
+
super({ transform: (chunk, ctrl) => {
|
|
30
|
+
if ((bytesRead += chunk.length) <= maxBytes) ctrl.enqueue(chunk);
|
|
31
|
+
else ctrl.error(/* @__PURE__ */ new Error("Response too large"));
|
|
32
|
+
} });
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
//#endregion
|
|
36
|
+
exports.MaxBytesTransformStream = MaxBytesTransformStream;
|
|
37
|
+
exports.bytesToStream = bytesToStream;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a ReadableStream from a Uint8Array.
|
|
3
|
+
*
|
|
4
|
+
* The stream will emit the entire byte array as a single chunk,
|
|
5
|
+
* then close immediately.
|
|
6
|
+
*
|
|
7
|
+
* @param bytes - The byte array to wrap.
|
|
8
|
+
* @returns A ReadableStream that emits the bytes.
|
|
9
|
+
*/
|
|
10
|
+
export declare function bytesToStream(bytes: Uint8Array): ReadableStream<Uint8Array<ArrayBufferLike>>;
|
|
11
|
+
/**
|
|
12
|
+
* A TransformStream that limits the total number of bytes passed through.
|
|
13
|
+
*
|
|
14
|
+
* It accumulates the byte count from incoming chunks and enqueues them
|
|
15
|
+
* if the total remains within the limit; otherwise, it errors.
|
|
16
|
+
*
|
|
17
|
+
* @param maxBytes - The maximum allowed bytes before erroring.
|
|
18
|
+
*/
|
|
19
|
+
export declare class MaxBytesTransformStream extends TransformStream<Uint8Array, Uint8Array> {
|
|
20
|
+
constructor(maxBytes: number);
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a ReadableStream from a Uint8Array.
|
|
3
|
+
*
|
|
4
|
+
* The stream will emit the entire byte array as a single chunk,
|
|
5
|
+
* then close immediately.
|
|
6
|
+
*
|
|
7
|
+
* @param bytes - The byte array to wrap.
|
|
8
|
+
* @returns A ReadableStream that emits the bytes.
|
|
9
|
+
*/
|
|
10
|
+
export declare function bytesToStream(bytes: Uint8Array): ReadableStream<Uint8Array<ArrayBufferLike>>;
|
|
11
|
+
/**
|
|
12
|
+
* A TransformStream that limits the total number of bytes passed through.
|
|
13
|
+
*
|
|
14
|
+
* It accumulates the byte count from incoming chunks and enqueues them
|
|
15
|
+
* if the total remains within the limit; otherwise, it errors.
|
|
16
|
+
*
|
|
17
|
+
* @param maxBytes - The maximum allowed bytes before erroring.
|
|
18
|
+
*/
|
|
19
|
+
export declare class MaxBytesTransformStream extends TransformStream<Uint8Array, Uint8Array> {
|
|
20
|
+
constructor(maxBytes: number);
|
|
21
|
+
}
|