@npy/fetch 0.1.0 → 0.1.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 (98) hide show
  1. package/_internal/consts.cjs +4 -0
  2. package/_internal/consts.js +4 -0
  3. package/_internal/error-adapters.cjs +146 -0
  4. package/_internal/error-adapters.js +142 -0
  5. package/_internal/guards.cjs +24 -0
  6. package/_internal/guards.js +17 -0
  7. package/_internal/net.cjs +95 -0
  8. package/_internal/net.js +92 -0
  9. package/_internal/promises.cjs +18 -0
  10. package/_internal/promises.js +18 -0
  11. package/_internal/streams.cjs +37 -0
  12. package/_internal/streams.js +36 -0
  13. package/_virtual/_rolldown/runtime.cjs +23 -0
  14. package/agent-pool.cjs +78 -0
  15. package/agent-pool.js +77 -0
  16. package/agent.cjs +257 -0
  17. package/agent.js +256 -0
  18. package/body.cjs +154 -0
  19. package/body.js +151 -0
  20. package/dialers/proxy.cjs +49 -0
  21. package/dialers/proxy.js +48 -0
  22. package/dialers/tcp.cjs +70 -0
  23. package/dialers/tcp.js +67 -0
  24. package/encoding.cjs +95 -0
  25. package/encoding.js +91 -0
  26. package/errors.cjs +275 -0
  27. package/errors.js +259 -0
  28. package/fetch.cjs +117 -0
  29. package/fetch.js +115 -0
  30. package/http-client.cjs +33 -0
  31. package/http-client.js +33 -0
  32. package/index.cjs +45 -0
  33. package/index.d.cts +1 -0
  34. package/index.d.ts +1 -0
  35. package/index.js +9 -0
  36. package/io/_utils.cjs +56 -0
  37. package/io/_utils.js +51 -0
  38. package/io/buf-writer.cjs +149 -0
  39. package/io/buf-writer.js +148 -0
  40. package/io/io.cjs +135 -0
  41. package/io/io.js +134 -0
  42. package/io/readers.cjs +377 -0
  43. package/io/readers.js +373 -0
  44. package/io/writers.cjs +191 -0
  45. package/io/writers.js +190 -0
  46. package/package.json +7 -10
  47. package/src/_internal/consts.d.cts +3 -0
  48. package/src/_internal/consts.d.ts +3 -0
  49. package/src/_internal/error-adapters.d.cts +22 -0
  50. package/src/_internal/error-adapters.d.ts +22 -0
  51. package/src/_internal/guards.d.cts +13 -0
  52. package/src/_internal/guards.d.ts +13 -0
  53. package/src/_internal/net.d.cts +12 -0
  54. package/src/_internal/net.d.ts +12 -0
  55. package/src/_internal/promises.d.cts +1 -0
  56. package/src/_internal/promises.d.ts +1 -0
  57. package/src/_internal/streams.d.cts +21 -0
  58. package/src/_internal/streams.d.ts +21 -0
  59. package/src/agent-pool.d.cts +2 -0
  60. package/src/agent-pool.d.ts +2 -0
  61. package/src/agent.d.cts +3 -0
  62. package/src/agent.d.ts +3 -0
  63. package/src/body.d.cts +23 -0
  64. package/src/body.d.ts +23 -0
  65. package/src/dialers/index.d.cts +3 -0
  66. package/src/dialers/index.d.ts +3 -0
  67. package/src/dialers/proxy.d.cts +19 -0
  68. package/src/dialers/proxy.d.ts +19 -0
  69. package/src/dialers/tcp.d.cts +36 -0
  70. package/src/dialers/tcp.d.ts +36 -0
  71. package/src/encoding.d.cts +24 -0
  72. package/src/encoding.d.ts +24 -0
  73. package/src/errors.d.cts +110 -0
  74. package/src/errors.d.ts +110 -0
  75. package/src/fetch.d.cts +36 -0
  76. package/src/fetch.d.ts +36 -0
  77. package/src/http-client.d.cts +23 -0
  78. package/src/http-client.d.ts +23 -0
  79. package/src/index.d.cts +7 -0
  80. package/src/index.d.ts +7 -0
  81. package/src/io/_utils.d.cts +10 -0
  82. package/src/io/_utils.d.ts +10 -0
  83. package/src/io/buf-writer.d.cts +13 -0
  84. package/src/io/buf-writer.d.ts +13 -0
  85. package/src/io/io.d.cts +5 -0
  86. package/src/io/io.d.ts +5 -0
  87. package/src/io/readers.d.cts +199 -0
  88. package/src/io/readers.d.ts +199 -0
  89. package/src/io/writers.d.cts +22 -0
  90. package/src/io/writers.d.ts +22 -0
  91. package/src/types/agent.d.cts +128 -0
  92. package/src/types/agent.d.ts +128 -0
  93. package/src/types/dialer.d.cts +27 -0
  94. package/src/types/dialer.d.ts +27 -0
  95. package/src/types/index.d.cts +2 -0
  96. package/src/types/index.d.ts +2 -0
  97. package/tests/test-utils.d.cts +8 -0
  98. package/tests/test-utils.d.ts +8 -0
@@ -0,0 +1,148 @@
1
+ import { u8 } from "@fuman/utils";
2
+ //#region src/io/buf-writer.ts
3
+ var DEFAULT_BUF_SIZE = 4096;
4
+ var MIN_BUF_SIZE = 16;
5
+ var BufWriter = class {
6
+ #buffer;
7
+ #writable;
8
+ #writePos = 0;
9
+ #error = null;
10
+ #pending = [];
11
+ #pendingBytes = 0;
12
+ #lastWrite = null;
13
+ constructor(writable, size = DEFAULT_BUF_SIZE) {
14
+ if (size < MIN_BUF_SIZE) size = MIN_BUF_SIZE;
15
+ this.#buffer = u8.alloc(size);
16
+ this.#writable = writable;
17
+ }
18
+ get bufferSize() {
19
+ return this.#buffer.byteLength;
20
+ }
21
+ get buffered() {
22
+ return this.#pendingBytes + this.#writePos;
23
+ }
24
+ get available() {
25
+ return this.#buffer.byteLength - this.#writePos;
26
+ }
27
+ reset(writable) {
28
+ this.#error = null;
29
+ this.#writePos = 0;
30
+ this.#pending.length = 0;
31
+ this.#pendingBytes = 0;
32
+ this.#lastWrite = null;
33
+ this.#writable = writable;
34
+ }
35
+ writeSync(bytes) {
36
+ if (this.#error) throw this.#error;
37
+ if (bytes < 0) throw new RangeError("bytes must be >= 0");
38
+ if (this.#lastWrite) throw new Error("disposeWriteSync must be called before the next writeSync");
39
+ if (bytes === 0) {
40
+ const empty = this.#buffer.subarray(this.#writePos, this.#writePos);
41
+ this.#lastWrite = {
42
+ buf: empty,
43
+ size: 0,
44
+ internal: true
45
+ };
46
+ return empty;
47
+ }
48
+ if (bytes > this.available && this.#writePos > 0) {
49
+ const copy = u8.allocWith(this.#buffer.subarray(0, this.#writePos));
50
+ this.#pending.push(copy);
51
+ this.#pendingBytes += copy.length;
52
+ this.#writePos = 0;
53
+ }
54
+ if (bytes <= this.#buffer.byteLength) {
55
+ if (bytes > this.available) {
56
+ const copy = u8.allocWith(this.#buffer.subarray(0, this.#writePos));
57
+ this.#pending.push(copy);
58
+ this.#pendingBytes += copy.length;
59
+ this.#writePos = 0;
60
+ }
61
+ const start = this.#writePos;
62
+ const end = start + bytes;
63
+ const slice = this.#buffer.subarray(start, end);
64
+ this.#writePos = end;
65
+ this.#lastWrite = {
66
+ buf: slice,
67
+ size: bytes,
68
+ internal: true
69
+ };
70
+ return slice;
71
+ }
72
+ const chunk = u8.alloc(bytes);
73
+ this.#lastWrite = {
74
+ buf: chunk,
75
+ size: bytes,
76
+ internal: false
77
+ };
78
+ return chunk;
79
+ }
80
+ disposeWriteSync(written) {
81
+ const lw = this.#lastWrite;
82
+ if (!lw) return;
83
+ const w = written ?? lw.size;
84
+ if (w < 0 || w > lw.size) throw new RangeError(`written out of bounds: ${w} (0..${lw.size})`);
85
+ if (lw.internal) this.#writePos -= lw.size - w;
86
+ else if (w > 0) {
87
+ const chunk = w === lw.size ? lw.buf : lw.buf.subarray(0, w);
88
+ this.#pending.push(chunk);
89
+ this.#pendingBytes += chunk.length;
90
+ }
91
+ this.#lastWrite = null;
92
+ }
93
+ async #flushPending() {
94
+ if (this.#error) throw this.#error;
95
+ if (this.#lastWrite) throw new Error("disposeWriteSync must be called before flush/write");
96
+ while (this.#pending.length > 0) {
97
+ const chunk = this.#pending[0];
98
+ try {
99
+ await this.#writable.write(chunk);
100
+ } catch (e) {
101
+ this.#error = e;
102
+ throw e;
103
+ }
104
+ this.#pending.shift();
105
+ this.#pendingBytes -= chunk.length;
106
+ }
107
+ }
108
+ async flush() {
109
+ await this.#flushPending();
110
+ if (this.#error) throw this.#error;
111
+ if (this.#writePos === 0) return;
112
+ try {
113
+ await this.#writable.write(this.#buffer.subarray(0, this.#writePos));
114
+ } catch (e) {
115
+ this.#error = e;
116
+ throw e;
117
+ }
118
+ this.#writePos = 0;
119
+ }
120
+ async write(bytes) {
121
+ if (this.#error) throw this.#error;
122
+ if (!bytes.length) return;
123
+ await this.#flushPending();
124
+ if (this.#writePos === 0 && bytes.length >= this.#buffer.byteLength) {
125
+ try {
126
+ await this.#writable.write(bytes);
127
+ } catch (e) {
128
+ this.#error = e;
129
+ throw e;
130
+ }
131
+ return;
132
+ }
133
+ let off = 0;
134
+ while (off < bytes.length) {
135
+ if (this.available === 0) {
136
+ await this.flush();
137
+ continue;
138
+ }
139
+ const toCopy = Math.min(this.available, bytes.length - off);
140
+ this.#buffer.set(bytes.subarray(off, off + toCopy), this.#writePos);
141
+ this.#writePos += toCopy;
142
+ off += toCopy;
143
+ if (this.#writePos === this.#buffer.byteLength) await this.flush();
144
+ }
145
+ }
146
+ };
147
+ //#endregion
148
+ export { BufWriter };
package/io/io.cjs ADDED
@@ -0,0 +1,135 @@
1
+ const require_encoding = require("../encoding.cjs");
2
+ const require_streams = require("../_internal/streams.cjs");
3
+ const require__utils = require("./_utils.cjs");
4
+ const require_readers = require("./readers.cjs");
5
+ const require_writers = require("./writers.cjs");
6
+ //#region src/io/io.ts
7
+ function parseStatusLine(line) {
8
+ const m = /^HTTP\/(\d+)\.(\d+)\s+(\d{3})(?:\s+(.*))?$/.exec(line);
9
+ if (!m) throw new Error(`Invalid HTTP status line: ${line}`);
10
+ const major = Number(m[1]);
11
+ const minor = Number(m[2]);
12
+ const status = Number(m[3]);
13
+ if (!Number.isFinite(major) || !Number.isFinite(minor) || !Number.isFinite(status)) throw new Error(`Invalid HTTP status line: ${line}`);
14
+ return {
15
+ major,
16
+ minor,
17
+ status,
18
+ statusText: m[4] ?? ""
19
+ };
20
+ }
21
+ async function readResponse(conn, options = {}, shouldIgnoreBody, onDone) {
22
+ const lr = new require_readers.LineReader(conn, options);
23
+ const finalize = (() => {
24
+ let called = false;
25
+ return (reusable) => {
26
+ if (called) return;
27
+ called = true;
28
+ queueMicrotask(() => onDone?.(reusable));
29
+ };
30
+ })();
31
+ let statusLine;
32
+ let headers;
33
+ for (;;) {
34
+ const line = await lr.readLine();
35
+ if (line === null) throw new Error("Unexpected EOF while reading status line");
36
+ const parsed = parseStatusLine(line);
37
+ const hdrs = await lr.readHeaders(options);
38
+ if (parsed.status >= 100 && parsed.status < 200) {
39
+ if (parsed.status === 101) throw new Error("HTTP/1.1 protocol upgrades not supported");
40
+ continue;
41
+ }
42
+ statusLine = parsed;
43
+ headers = hdrs;
44
+ break;
45
+ }
46
+ const { major, minor, status, statusText } = statusLine;
47
+ const connectionTokens = require__utils.splitTokens(headers.get("connection"));
48
+ const hasClose = connectionTokens.includes("close");
49
+ const hasKeepAlive = connectionTokens.includes("keep-alive");
50
+ const keepAliveOk = !(major === 1 && minor === 0) || hasKeepAlive;
51
+ const ignoreBody = shouldIgnoreBody(status);
52
+ const te = require__utils.parseTransferEncoding(headers);
53
+ let chunked = false;
54
+ let contentLength = null;
55
+ if (!ignoreBody) if (te.has) {
56
+ chunked = te.chunked;
57
+ contentLength = null;
58
+ headers.delete("content-length");
59
+ } else {
60
+ chunked = false;
61
+ contentLength = require__utils.parseContentLength(headers);
62
+ }
63
+ const reusable = keepAliveOk && !hasClose && (ignoreBody || chunked || contentLength != null);
64
+ if (ignoreBody) {
65
+ finalize(reusable);
66
+ return new Response(null, {
67
+ status,
68
+ statusText,
69
+ headers
70
+ });
71
+ }
72
+ if (chunked) headers.delete("content-length");
73
+ const reader = chunked ? new require_readers.ChunkedBodyReader(lr, options) : new require_readers.BodyReader(lr, contentLength ?? -1, options);
74
+ let body = new ReadableStream({
75
+ type: "bytes",
76
+ async pull(controller) {
77
+ const byob = controller.byobRequest;
78
+ const view = byob?.view ? new Uint8Array(byob.view.buffer, byob.view.byteOffset, byob.view.byteLength) : new Uint8Array(new ArrayBuffer(options.highWaterMark ?? 16 * 1024));
79
+ try {
80
+ const n = await reader.read(view);
81
+ if (n === 0) {
82
+ byob?.respond(0);
83
+ controller.close();
84
+ finalize(reusable);
85
+ return;
86
+ }
87
+ if (byob) byob.respond(n);
88
+ else controller.enqueue(view.subarray(0, n));
89
+ } catch (err) {
90
+ controller.error(err);
91
+ finalize(false);
92
+ }
93
+ },
94
+ cancel() {
95
+ finalize(false);
96
+ }
97
+ });
98
+ try {
99
+ if (te.has && te.codings.length > 0) {
100
+ const decodedTe = require_encoding.decodeStream(body, te.codings);
101
+ if (decodedTe !== body) {
102
+ if (te.chunked) headers.set("transfer-encoding", "chunked");
103
+ else headers.delete("transfer-encoding");
104
+ headers.delete("content-length");
105
+ }
106
+ body = decodedTe;
107
+ }
108
+ const decompress = options.decompress !== false;
109
+ const contentEncoding = headers.get("content-encoding") ?? void 0;
110
+ if (decompress && contentEncoding) {
111
+ const decodedCe = require_encoding.decodeStream(body, contentEncoding);
112
+ if (decodedCe !== body) {
113
+ headers.delete("content-encoding");
114
+ headers.delete("content-length");
115
+ }
116
+ body = decodedCe;
117
+ }
118
+ const maxDecoded = require__utils.parseMaxBytes(options.maxDecodedBodySize);
119
+ if (maxDecoded != null) body = body.pipeThrough(new require_streams.MaxBytesTransformStream(maxDecoded));
120
+ } catch (err) {
121
+ finalize(false);
122
+ throw err;
123
+ }
124
+ return new Response(body, {
125
+ status,
126
+ statusText,
127
+ headers
128
+ });
129
+ }
130
+ async function writeRequest(conn, req, options = {}) {
131
+ await require_writers.createRequestWriter(conn, options).write(req);
132
+ }
133
+ //#endregion
134
+ exports.readResponse = readResponse;
135
+ exports.writeRequest = writeRequest;
package/io/io.js ADDED
@@ -0,0 +1,134 @@
1
+ import { decodeStream } from "../encoding.js";
2
+ import { MaxBytesTransformStream } from "../_internal/streams.js";
3
+ import { parseContentLength, parseMaxBytes, parseTransferEncoding, splitTokens } from "./_utils.js";
4
+ import { BodyReader, ChunkedBodyReader, LineReader } from "./readers.js";
5
+ import { createRequestWriter } from "./writers.js";
6
+ //#region src/io/io.ts
7
+ function parseStatusLine(line) {
8
+ const m = /^HTTP\/(\d+)\.(\d+)\s+(\d{3})(?:\s+(.*))?$/.exec(line);
9
+ if (!m) throw new Error(`Invalid HTTP status line: ${line}`);
10
+ const major = Number(m[1]);
11
+ const minor = Number(m[2]);
12
+ const status = Number(m[3]);
13
+ if (!Number.isFinite(major) || !Number.isFinite(minor) || !Number.isFinite(status)) throw new Error(`Invalid HTTP status line: ${line}`);
14
+ return {
15
+ major,
16
+ minor,
17
+ status,
18
+ statusText: m[4] ?? ""
19
+ };
20
+ }
21
+ async function readResponse(conn, options = {}, shouldIgnoreBody, onDone) {
22
+ const lr = new LineReader(conn, options);
23
+ const finalize = (() => {
24
+ let called = false;
25
+ return (reusable) => {
26
+ if (called) return;
27
+ called = true;
28
+ queueMicrotask(() => onDone?.(reusable));
29
+ };
30
+ })();
31
+ let statusLine;
32
+ let headers;
33
+ for (;;) {
34
+ const line = await lr.readLine();
35
+ if (line === null) throw new Error("Unexpected EOF while reading status line");
36
+ const parsed = parseStatusLine(line);
37
+ const hdrs = await lr.readHeaders(options);
38
+ if (parsed.status >= 100 && parsed.status < 200) {
39
+ if (parsed.status === 101) throw new Error("HTTP/1.1 protocol upgrades not supported");
40
+ continue;
41
+ }
42
+ statusLine = parsed;
43
+ headers = hdrs;
44
+ break;
45
+ }
46
+ const { major, minor, status, statusText } = statusLine;
47
+ const connectionTokens = splitTokens(headers.get("connection"));
48
+ const hasClose = connectionTokens.includes("close");
49
+ const hasKeepAlive = connectionTokens.includes("keep-alive");
50
+ const keepAliveOk = !(major === 1 && minor === 0) || hasKeepAlive;
51
+ const ignoreBody = shouldIgnoreBody(status);
52
+ const te = parseTransferEncoding(headers);
53
+ let chunked = false;
54
+ let contentLength = null;
55
+ if (!ignoreBody) if (te.has) {
56
+ chunked = te.chunked;
57
+ contentLength = null;
58
+ headers.delete("content-length");
59
+ } else {
60
+ chunked = false;
61
+ contentLength = parseContentLength(headers);
62
+ }
63
+ const reusable = keepAliveOk && !hasClose && (ignoreBody || chunked || contentLength != null);
64
+ if (ignoreBody) {
65
+ finalize(reusable);
66
+ return new Response(null, {
67
+ status,
68
+ statusText,
69
+ headers
70
+ });
71
+ }
72
+ if (chunked) headers.delete("content-length");
73
+ const reader = chunked ? new ChunkedBodyReader(lr, options) : new BodyReader(lr, contentLength ?? -1, options);
74
+ let body = new ReadableStream({
75
+ type: "bytes",
76
+ async pull(controller) {
77
+ const byob = controller.byobRequest;
78
+ const view = byob?.view ? new Uint8Array(byob.view.buffer, byob.view.byteOffset, byob.view.byteLength) : new Uint8Array(new ArrayBuffer(options.highWaterMark ?? 16 * 1024));
79
+ try {
80
+ const n = await reader.read(view);
81
+ if (n === 0) {
82
+ byob?.respond(0);
83
+ controller.close();
84
+ finalize(reusable);
85
+ return;
86
+ }
87
+ if (byob) byob.respond(n);
88
+ else controller.enqueue(view.subarray(0, n));
89
+ } catch (err) {
90
+ controller.error(err);
91
+ finalize(false);
92
+ }
93
+ },
94
+ cancel() {
95
+ finalize(false);
96
+ }
97
+ });
98
+ try {
99
+ if (te.has && te.codings.length > 0) {
100
+ const decodedTe = decodeStream(body, te.codings);
101
+ if (decodedTe !== body) {
102
+ if (te.chunked) headers.set("transfer-encoding", "chunked");
103
+ else headers.delete("transfer-encoding");
104
+ headers.delete("content-length");
105
+ }
106
+ body = decodedTe;
107
+ }
108
+ const decompress = options.decompress !== false;
109
+ const contentEncoding = headers.get("content-encoding") ?? void 0;
110
+ if (decompress && contentEncoding) {
111
+ const decodedCe = decodeStream(body, contentEncoding);
112
+ if (decodedCe !== body) {
113
+ headers.delete("content-encoding");
114
+ headers.delete("content-length");
115
+ }
116
+ body = decodedCe;
117
+ }
118
+ const maxDecoded = parseMaxBytes(options.maxDecodedBodySize);
119
+ if (maxDecoded != null) body = body.pipeThrough(new MaxBytesTransformStream(maxDecoded));
120
+ } catch (err) {
121
+ finalize(false);
122
+ throw err;
123
+ }
124
+ return new Response(body, {
125
+ status,
126
+ statusText,
127
+ headers
128
+ });
129
+ }
130
+ async function writeRequest(conn, req, options = {}) {
131
+ await createRequestWriter(conn, options).write(req);
132
+ }
133
+ //#endregion
134
+ export { readResponse, writeRequest };