rekwest 3.1.1 → 3.3.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.
- package/README.md +186 -184
- package/dist/ackn.js +2 -2
- package/dist/cookies.js +3 -0
- package/dist/file.js +4 -4
- package/dist/formdata.js +29 -15
- package/dist/index.js +57 -48
- package/dist/{helpers.js → utils.js} +77 -37
- package/package.json +14 -9
- package/src/ackn.mjs +33 -33
- package/src/cookies.mjs +4 -0
- package/src/file.mjs +2 -2
- package/src/formdata.mjs +20 -5
- package/src/index.mjs +20 -19
- package/src/{helpers.mjs → utils.mjs} +37 -13
package/README.md
CHANGED
|
@@ -1,184 +1,186 @@
|
|
|
1
|
-
The robust request library that humanity deserves 🌐
|
|
2
|
-
---
|
|
3
|
-
This package provides highly likely functional and **easy-to-use** abstraction atop of
|
|
4
|
-
native [http(s).request](https://nodejs.org/api/https.html#https_https_request_url_options_callback)
|
|
5
|
-
and [http2.request](https://nodejs.org/api/http2.html#http2_clienthttp2session_request_headers_options).
|
|
6
|
-
|
|
7
|
-
## Abstract
|
|
8
|
-
|
|
9
|
-
* Fetch-alike
|
|
10
|
-
* Cool-beans config options (with defaults)
|
|
11
|
-
* Automatic HTTP/2 support (ALPN negotiation)
|
|
12
|
-
* Automatic or opt-in body parse (with non-UTF-8 charset decoding)
|
|
13
|
-
* Automatic and simplistic `Cookies` treatment (with built-in jar)
|
|
14
|
-
* Automatic decompression (with opt-in body compression)
|
|
15
|
-
* Built-in streamable `File` & `FormData` interfaces
|
|
16
|
-
* Support redirects & retries with fine-grained tune-ups
|
|
17
|
-
* Support all legit request body types (include blobs & streams)
|
|
18
|
-
* Support both CJS and ESM module systems
|
|
19
|
-
* Fully promise-able and pipe-able
|
|
20
|
-
* Zero dependencies
|
|
21
|
-
|
|
22
|
-
## Prerequisites
|
|
23
|
-
|
|
24
|
-
* Node.js `>= 16.x`
|
|
25
|
-
|
|
26
|
-
## Installation
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
npm install rekwest --save
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### Usage
|
|
33
|
-
|
|
34
|
-
```javascript
|
|
35
|
-
import rekwest, { constants } from 'rekwest';
|
|
36
|
-
|
|
37
|
-
const {
|
|
38
|
-
HTTP2_HEADER_AUTHORIZATION,
|
|
39
|
-
HTTP2_HEADER_CONTENT_ENCODING,
|
|
40
|
-
HTTP2_METHOD_POST,
|
|
41
|
-
HTTP_STATUS_OK,
|
|
42
|
-
} = constants;
|
|
43
|
-
|
|
44
|
-
const url = 'https://somewhe.re/somewhat/endpoint';
|
|
45
|
-
|
|
46
|
-
const res = await rekwest(url, {
|
|
47
|
-
body: { celestial: 'payload' },
|
|
48
|
-
headers: {
|
|
49
|
-
[HTTP2_HEADER_AUTHORIZATION]: 'Bearer [token]',
|
|
50
|
-
[HTTP2_HEADER_CONTENT_ENCODING]: 'br', // enables: body compression
|
|
51
|
-
/** [HTTP2_HEADER_CONTENT_TYPE]
|
|
52
|
-
* is undue for
|
|
53
|
-
* Array/Blob/File/FormData/Object/URLSearchParams body types
|
|
54
|
-
* and will be set automatically, with an option to override it here
|
|
55
|
-
*/
|
|
56
|
-
},
|
|
57
|
-
method: HTTP2_METHOD_POST,
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
console.assert(res.statusCode === HTTP_STATUS_OK);
|
|
61
|
-
console.info(res.headers);
|
|
62
|
-
console.log(res.body);
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
---
|
|
66
|
-
|
|
67
|
-
```javascript
|
|
68
|
-
import rekwest, {
|
|
69
|
-
constants,
|
|
70
|
-
Blob,
|
|
71
|
-
File,
|
|
72
|
-
FormData,
|
|
73
|
-
} from 'rekwest';
|
|
74
|
-
import { Readable } from 'stream';
|
|
75
|
-
|
|
76
|
-
const {
|
|
77
|
-
HTTP2_HEADER_AUTHORIZATION,
|
|
78
|
-
HTTP2_HEADER_CONTENT_ENCODING,
|
|
79
|
-
HTTP2_METHOD_POST,
|
|
80
|
-
HTTP_STATUS_OK,
|
|
81
|
-
} = constants;
|
|
82
|
-
|
|
83
|
-
const blob = new Blob(['bits']);
|
|
84
|
-
const file = new File(['bits'], 'file.dab');
|
|
85
|
-
const readable = Readable.from('bits');
|
|
86
|
-
|
|
87
|
-
const fd = new FormData({
|
|
88
|
-
aux: Date.now(), // either [[key, value]], or kv sequenceable
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
fd.append('celestial', 'payload');
|
|
92
|
-
fd.append('blob', blob, 'blob.dab');
|
|
93
|
-
fd.append('file', file);
|
|
94
|
-
fd.append('readable', readable, 'readable.dab');
|
|
95
|
-
|
|
96
|
-
const url = 'https://somewhe.re/somewhat/endpoint';
|
|
97
|
-
|
|
98
|
-
const res = await rekwest(url, {
|
|
99
|
-
body: fd,
|
|
100
|
-
headers: {
|
|
101
|
-
[HTTP2_HEADER_AUTHORIZATION]: 'Bearer [token]',
|
|
102
|
-
[HTTP2_HEADER_CONTENT_ENCODING]: 'br', // enables: body compression
|
|
103
|
-
},
|
|
104
|
-
method: HTTP2_METHOD_POST,
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
console.assert(res.statusCode === HTTP_STATUS_OK);
|
|
108
|
-
console.info(res.headers);
|
|
109
|
-
console.log(res.body);
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### API
|
|
113
|
-
|
|
114
|
-
#### `rekwest(url[, options])`
|
|
115
|
-
|
|
116
|
-
* `url` **{string | URL}** The URL to send the request to
|
|
117
|
-
* `options` **{Object}**
|
|
118
|
-
Extends [https.RequestOptions](https://nodejs.org/api/https.html#https_https_request_url_options_callback)
|
|
119
|
-
along with
|
|
120
|
-
extra [http2.ClientSessionOptions](https://nodejs.org/api/http2.html#http2_http2_connect_authority_options_listener)
|
|
121
|
-
& [http2.ClientSessionRequestOptions](https://nodejs.org/api/http2.html#http2_clienthttp2session_request_headers_options)
|
|
122
|
-
and [tls.ConnectionOptions](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback)
|
|
123
|
-
for HTTP/2 attunes
|
|
124
|
-
* `body` **{string | Array | ArrayBuffer | ArrayBufferView | AsyncIterator | Blob | Buffer | DataView | File |
|
|
125
|
-
FormData | Iterator | Object | Readable | SharedArrayBuffer | URLSearchParams}** The body to send with the request
|
|
126
|
-
* `cookies` **{boolean | Array<[k, v]> | Cookies | Object | URLSearchParams}** `Default: true` The cookies to add to
|
|
127
|
-
the request
|
|
128
|
-
* `digest` **{boolean}** `Default: true` Controls whether to read the response stream or simply add a mixin
|
|
129
|
-
* `follow` **{number}** `Default: 20` The number of redirects to follow
|
|
130
|
-
* `h2` **{boolean}** `Default: false` Forces the use of HTTP/2 protocol
|
|
131
|
-
* `headers` **{Object}** The headers to add to the request
|
|
132
|
-
* `maxRetryAfter` **{number}** The upper limit of `retry-after` header. If unset, it will use `timeout` value
|
|
133
|
-
* `parse` **{boolean}** `Default: true` Controls whether to parse response body or simply return a buffer
|
|
134
|
-
* `redirect` **{error | follow | manual}** `Default: follow` Controls the redirect flows
|
|
135
|
-
* `retry` **{Object}** Represents the retry options
|
|
136
|
-
* `attempts` **{number}** `Default: 0` The number of retry attempts
|
|
137
|
-
* `backoffStrategy` **{string}** `Default: interval * Math.log(Math.random() * (Math.E * Math.E - Math.E) + Math.E)`
|
|
138
|
-
The backoff strategy algorithm that increases logarithmically. To fixate set value to `interval * 1`
|
|
139
|
-
* `interval` **{number}** `Default: 1e3` The initial retry interval
|
|
140
|
-
* `retryAfter` **{boolean}** `Default: true` Controls `retry-after` header receptiveness
|
|
141
|
-
* `statusCodes` **{number[]}** `Default: [429, 503]` The list of status codes to retry on
|
|
142
|
-
* `thenable` **{boolean}** `Default: false` Controls the promise resolutions
|
|
143
|
-
* `timeout` **{number}** `Default: 3e5` The number of milliseconds a request can take before termination
|
|
144
|
-
* **
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
* if `degist:
|
|
151
|
-
* `
|
|
152
|
-
|
|
153
|
-
* `
|
|
154
|
-
* `
|
|
155
|
-
* `
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
* `
|
|
159
|
-
* `
|
|
160
|
-
* `
|
|
161
|
-
* `
|
|
162
|
-
* `
|
|
163
|
-
* `
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
*
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
1
|
+
The robust request library that humanity deserves 🌐
|
|
2
|
+
---
|
|
3
|
+
This package provides highly likely functional and **easy-to-use** abstraction atop of
|
|
4
|
+
native [http(s).request](https://nodejs.org/api/https.html#https_https_request_url_options_callback)
|
|
5
|
+
and [http2.request](https://nodejs.org/api/http2.html#http2_clienthttp2session_request_headers_options).
|
|
6
|
+
|
|
7
|
+
## Abstract
|
|
8
|
+
|
|
9
|
+
* Fetch-alike
|
|
10
|
+
* Cool-beans 🫐 config options (with defaults)
|
|
11
|
+
* Automatic HTTP/2 support (ALPN negotiation)
|
|
12
|
+
* Automatic or opt-in body parse (with non-UTF-8 charset decoding)
|
|
13
|
+
* Automatic and simplistic `Cookies` treatment (with built-in jar)
|
|
14
|
+
* Automatic decompression (with opt-in body compression)
|
|
15
|
+
* Built-in streamable `File` & `FormData` interfaces
|
|
16
|
+
* Support redirects & retries with fine-grained tune-ups
|
|
17
|
+
* Support all legit request body types (include blobs & streams)
|
|
18
|
+
* Support both CJS and ESM module systems
|
|
19
|
+
* Fully promise-able and pipe-able
|
|
20
|
+
* Zero dependencies
|
|
21
|
+
|
|
22
|
+
## Prerequisites
|
|
23
|
+
|
|
24
|
+
* Node.js `>= 16.x`
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install rekwest --save
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Usage
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
import rekwest, { constants } from 'rekwest';
|
|
36
|
+
|
|
37
|
+
const {
|
|
38
|
+
HTTP2_HEADER_AUTHORIZATION,
|
|
39
|
+
HTTP2_HEADER_CONTENT_ENCODING,
|
|
40
|
+
HTTP2_METHOD_POST,
|
|
41
|
+
HTTP_STATUS_OK,
|
|
42
|
+
} = constants;
|
|
43
|
+
|
|
44
|
+
const url = 'https://somewhe.re/somewhat/endpoint';
|
|
45
|
+
|
|
46
|
+
const res = await rekwest(url, {
|
|
47
|
+
body: { celestial: 'payload' },
|
|
48
|
+
headers: {
|
|
49
|
+
[HTTP2_HEADER_AUTHORIZATION]: 'Bearer [token]',
|
|
50
|
+
[HTTP2_HEADER_CONTENT_ENCODING]: 'br', // enables: body compression
|
|
51
|
+
/** [HTTP2_HEADER_CONTENT_TYPE]
|
|
52
|
+
* is undue for
|
|
53
|
+
* Array/Blob/File/FormData/Object/URLSearchParams body types
|
|
54
|
+
* and will be set automatically, with an option to override it here
|
|
55
|
+
*/
|
|
56
|
+
},
|
|
57
|
+
method: HTTP2_METHOD_POST,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
console.assert(res.statusCode === HTTP_STATUS_OK);
|
|
61
|
+
console.info(res.headers);
|
|
62
|
+
console.log(res.body);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
import rekwest, {
|
|
69
|
+
constants,
|
|
70
|
+
Blob,
|
|
71
|
+
File,
|
|
72
|
+
FormData,
|
|
73
|
+
} from 'rekwest';
|
|
74
|
+
import { Readable } from 'node:stream';
|
|
75
|
+
|
|
76
|
+
const {
|
|
77
|
+
HTTP2_HEADER_AUTHORIZATION,
|
|
78
|
+
HTTP2_HEADER_CONTENT_ENCODING,
|
|
79
|
+
HTTP2_METHOD_POST,
|
|
80
|
+
HTTP_STATUS_OK,
|
|
81
|
+
} = constants;
|
|
82
|
+
|
|
83
|
+
const blob = new Blob(['bits']);
|
|
84
|
+
const file = new File(['bits'], 'file.dab');
|
|
85
|
+
const readable = Readable.from('bits');
|
|
86
|
+
|
|
87
|
+
const fd = new FormData({
|
|
88
|
+
aux: Date.now(), // either [[key, value]], or kv sequenceable
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
fd.append('celestial', 'payload');
|
|
92
|
+
fd.append('blob', blob, 'blob.dab');
|
|
93
|
+
fd.append('file', file);
|
|
94
|
+
fd.append('readable', readable, 'readable.dab');
|
|
95
|
+
|
|
96
|
+
const url = 'https://somewhe.re/somewhat/endpoint';
|
|
97
|
+
|
|
98
|
+
const res = await rekwest(url, {
|
|
99
|
+
body: fd,
|
|
100
|
+
headers: {
|
|
101
|
+
[HTTP2_HEADER_AUTHORIZATION]: 'Bearer [token]',
|
|
102
|
+
[HTTP2_HEADER_CONTENT_ENCODING]: 'br', // enables: body compression
|
|
103
|
+
},
|
|
104
|
+
method: HTTP2_METHOD_POST,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
console.assert(res.statusCode === HTTP_STATUS_OK);
|
|
108
|
+
console.info(res.headers);
|
|
109
|
+
console.log(res.body);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### API
|
|
113
|
+
|
|
114
|
+
#### `rekwest(url[, options])`
|
|
115
|
+
|
|
116
|
+
* `url` **{string | URL}** The URL to send the request to
|
|
117
|
+
* `options` **{Object}**
|
|
118
|
+
Extends [https.RequestOptions](https://nodejs.org/api/https.html#https_https_request_url_options_callback)
|
|
119
|
+
along with
|
|
120
|
+
extra [http2.ClientSessionOptions](https://nodejs.org/api/http2.html#http2_http2_connect_authority_options_listener)
|
|
121
|
+
& [http2.ClientSessionRequestOptions](https://nodejs.org/api/http2.html#http2_clienthttp2session_request_headers_options)
|
|
122
|
+
and [tls.ConnectionOptions](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback)
|
|
123
|
+
for HTTP/2 attunes
|
|
124
|
+
* `body` **{string | Array | ArrayBuffer | ArrayBufferView | AsyncIterator | Blob | Buffer | DataView | File |
|
|
125
|
+
FormData | Iterator | Object | Readable | SharedArrayBuffer | URLSearchParams}** The body to send with the request
|
|
126
|
+
* `cookies` **{boolean | Array<[k, v]> | Cookies | Object | URLSearchParams}** `Default: true` The cookies to add to
|
|
127
|
+
the request
|
|
128
|
+
* `digest` **{boolean}** `Default: true` Controls whether to read the response stream or simply add a mixin
|
|
129
|
+
* `follow` **{number}** `Default: 20` The number of redirects to follow
|
|
130
|
+
* `h2` **{boolean}** `Default: false` Forces the use of HTTP/2 protocol
|
|
131
|
+
* `headers` **{Object}** The headers to add to the request
|
|
132
|
+
* `maxRetryAfter` **{number}** The upper limit of `retry-after` header. If unset, it will use `timeout` value
|
|
133
|
+
* `parse` **{boolean}** `Default: true` Controls whether to parse response body or simply return a buffer
|
|
134
|
+
* `redirect` **{error | follow | manual}** `Default: follow` Controls the redirect flows
|
|
135
|
+
* `retry` **{Object}** Represents the retry options
|
|
136
|
+
* `attempts` **{number}** `Default: 0` The number of retry attempts
|
|
137
|
+
* `backoffStrategy` **{string}** `Default: interval * Math.log(Math.random() * (Math.E * Math.E - Math.E) + Math.E)`
|
|
138
|
+
The backoff strategy algorithm that increases logarithmically. To fixate set value to `interval * 1`
|
|
139
|
+
* `interval` **{number}** `Default: 1e3` The initial retry interval
|
|
140
|
+
* `retryAfter` **{boolean}** `Default: true` Controls `retry-after` header receptiveness
|
|
141
|
+
* `statusCodes` **{number[]}** `Default: [429, 503]` The list of status codes to retry on
|
|
142
|
+
* `thenable` **{boolean}** `Default: false` Controls the promise resolutions
|
|
143
|
+
* `timeout` **{number}** `Default: 3e5` The number of milliseconds a request can take before termination
|
|
144
|
+
* `trimTrailingSlashes` **{boolean}** `Default: false` Controls whether to trim trailing slashes in the URL before
|
|
145
|
+
proceed with the request
|
|
146
|
+
* **Returns:** Promise that resolves to
|
|
147
|
+
extended [http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
|
|
148
|
+
or [http2.ClientHttp2Stream](https://nodejs.org/api/http2.html#http2_class_clienthttp2stream) which is respectively
|
|
149
|
+
readable and duplex streams
|
|
150
|
+
* if `degist: true` & `parse: true`
|
|
151
|
+
* `body` **{string | Array | Buffer | Object}** The body based on its content type
|
|
152
|
+
* if `degist: false`
|
|
153
|
+
* `arrayBuffer` **{AsyncFunction}** Reads the response and returns **ArrayBuffer**
|
|
154
|
+
* `blob` **{AsyncFunction}** Reads the response and returns **Blob**
|
|
155
|
+
* `body` **{AsyncFunction}** Reads the response and returns **Buffer** if `parse: false`
|
|
156
|
+
* `json` **{AsyncFunction}** Reads the response and returns **Object**
|
|
157
|
+
* `text` **{AsyncFunction}** Reads the response and returns **String**
|
|
158
|
+
* `bodyUsed` **{boolean}** Indicates whether the response were read or not
|
|
159
|
+
* `cookies` **{undefined | Cookies}** The cookies sent and received with the response
|
|
160
|
+
* `headers` **{Object}** The headers received with the response
|
|
161
|
+
* `httpVersion` **{string}** Indicates protocol version negotiated with the server
|
|
162
|
+
* `ok` **{boolean}** Indicates if the response was successful (statusCode: **200-299**)
|
|
163
|
+
* `redirected` **{boolean}** Indicates if the response is the result of a redirect
|
|
164
|
+
* `statusCode` **{number}** Indicates the status code of the response
|
|
165
|
+
* `trailers` **{undefined | Object}** The trailer headers received with the response
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
#### `rekwest.defaults`
|
|
170
|
+
|
|
171
|
+
The object to fulfill with default [options](#rekwesturl-options)
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
#### `rekwest.stream(url[, options])`
|
|
176
|
+
|
|
177
|
+
The method with limited functionality to use with streams and/or pipes
|
|
178
|
+
|
|
179
|
+
* No automata
|
|
180
|
+
* No redirects
|
|
181
|
+
* Pass `h2: true` in options to use HTTP/2 protocol
|
|
182
|
+
* Or use `ackn({ url: URL })` method in advance to probe the available protocols
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
For more details, please check tests (coverage: **>97%**) in the repository
|
package/dist/ackn.js
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.ackn = void 0;
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var _nodeTls = require("node:tls");
|
|
7
7
|
|
|
8
8
|
const ackn = options => new Promise((resolve, reject) => {
|
|
9
9
|
const {
|
|
10
10
|
url
|
|
11
11
|
} = options;
|
|
12
|
-
const socket = (0,
|
|
12
|
+
const socket = (0, _nodeTls.connect)({ ...options,
|
|
13
13
|
ALPNProtocols: ['h2', 'http/1.1'],
|
|
14
14
|
host: url.hostname,
|
|
15
15
|
port: parseInt(url.port) || 443,
|
package/dist/cookies.js
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.Cookies = void 0;
|
|
5
5
|
|
|
6
|
+
var _utils = require("./utils.js");
|
|
7
|
+
|
|
6
8
|
class Cookies extends URLSearchParams {
|
|
7
9
|
static jar = new Map();
|
|
8
10
|
|
|
@@ -19,6 +21,7 @@ class Cookies extends URLSearchParams {
|
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
toString() {
|
|
24
|
+
(0, _utils.collate)(this, Cookies);
|
|
22
25
|
return super.toString().split('&').join('; ').trim();
|
|
23
26
|
}
|
|
24
27
|
|
package/dist/file.js
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.File = void 0;
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var _nodeBuffer = require("node:buffer");
|
|
7
7
|
|
|
8
|
-
exports.Blob =
|
|
8
|
+
exports.Blob = _nodeBuffer.Blob;
|
|
9
9
|
|
|
10
|
-
class File extends
|
|
10
|
+
class File extends _nodeBuffer.Blob {
|
|
11
11
|
static alike(instance) {
|
|
12
|
-
return [
|
|
12
|
+
return [_nodeBuffer.Blob.name, File.name].includes(instance?.constructor.name);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
#lastModified;
|
package/dist/formdata.js
CHANGED
|
@@ -3,29 +3,29 @@
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.FormData = void 0;
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var _nodeCrypto = require("node:crypto");
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var _nodeHttp = _interopRequireDefault(require("node:http2"));
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _nodeUtil = require("node:util");
|
|
11
11
|
|
|
12
12
|
var _file = require("./file.js");
|
|
13
13
|
|
|
14
|
-
var _helpers = require("./helpers.js");
|
|
15
|
-
|
|
16
14
|
var _mediatypes = require("./mediatypes.js");
|
|
17
15
|
|
|
16
|
+
var _utils = require("./utils.js");
|
|
17
|
+
|
|
18
18
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
19
|
|
|
20
20
|
const CRLF = '\r\n';
|
|
21
21
|
const {
|
|
22
22
|
HTTP2_HEADER_CONTENT_DISPOSITION,
|
|
23
23
|
HTTP2_HEADER_CONTENT_TYPE
|
|
24
|
-
} =
|
|
24
|
+
} = _nodeHttp.default.constants;
|
|
25
25
|
|
|
26
26
|
class FormData {
|
|
27
27
|
static actuate(fd) {
|
|
28
|
-
const boundary = (0,
|
|
28
|
+
const boundary = (0, _nodeCrypto.randomBytes)(24).toString('hex');
|
|
29
29
|
const contentType = `${_mediatypes.MULTIPART_FORM_DATA}; boundary=${boundary}`;
|
|
30
30
|
const prefix = `--${boundary}${CRLF}${HTTP2_HEADER_CONTENT_DISPOSITION}: form-data`;
|
|
31
31
|
|
|
@@ -44,7 +44,7 @@ class FormData {
|
|
|
44
44
|
yield encoder.encode(`${prefix}; name="${escape(normalize(name))}"${CRLF.repeat(2)}${normalize(value)}${CRLF}`);
|
|
45
45
|
} else {
|
|
46
46
|
yield encoder.encode(`${prefix}; name="${escape(normalize(name))}"${value.name ? `; filename="${escape(value.name)}"` : ''}${CRLF}${HTTP2_HEADER_CONTENT_TYPE}: ${value.type || _mediatypes.APPLICATION_OCTET_STREAM}${CRLF.repeat(2)}`);
|
|
47
|
-
yield* (0,
|
|
47
|
+
yield* (0, _utils.tap)(value);
|
|
48
48
|
yield encoder.encode(CRLF);
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -60,15 +60,15 @@ class FormData {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
static #enfoldEntry(name, value, filename) {
|
|
63
|
-
name = (0,
|
|
64
|
-
filename &&= (0,
|
|
63
|
+
name = (0, _nodeUtil.toUSVString)(name);
|
|
64
|
+
filename &&= (0, _nodeUtil.toUSVString)(filename);
|
|
65
65
|
|
|
66
66
|
if (_file.File.alike(value)) {
|
|
67
67
|
value = new _file.File([value], filename, value);
|
|
68
68
|
} else if (this.#ensureInstance(value)) {
|
|
69
69
|
value.name = filename || value.name;
|
|
70
70
|
} else {
|
|
71
|
-
value = (0,
|
|
71
|
+
value = (0, _nodeUtil.toUSVString)(value);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
return {
|
|
@@ -128,17 +128,20 @@ class FormData {
|
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
append(...args) {
|
|
131
|
+
(0, _utils.collate)(this, FormData);
|
|
131
132
|
this.#ensureArgs(args, 2, 'append');
|
|
132
133
|
this.#entries.push(this.constructor.#enfoldEntry(...args));
|
|
133
134
|
}
|
|
134
135
|
|
|
135
136
|
delete(...args) {
|
|
137
|
+
(0, _utils.collate)(this, FormData);
|
|
136
138
|
this.#ensureArgs(args, 1, 'delete');
|
|
137
|
-
const name = (0,
|
|
139
|
+
const name = (0, _nodeUtil.toUSVString)(args[0]);
|
|
138
140
|
this.#entries = this.#entries.filter(it => it.name !== name);
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
forEach(...args) {
|
|
144
|
+
(0, _utils.collate)(this, FormData);
|
|
142
145
|
this.#ensureArgs(args, 1, 'forEach');
|
|
143
146
|
const [callback, thisArg] = args;
|
|
144
147
|
|
|
@@ -148,24 +151,28 @@ class FormData {
|
|
|
148
151
|
}
|
|
149
152
|
|
|
150
153
|
get(...args) {
|
|
154
|
+
(0, _utils.collate)(this, FormData);
|
|
151
155
|
this.#ensureArgs(args, 1, 'get');
|
|
152
|
-
const name = (0,
|
|
156
|
+
const name = (0, _nodeUtil.toUSVString)(args[0]);
|
|
153
157
|
return (this.#entries.find(it => it.name === name) ?? {}).value ?? null;
|
|
154
158
|
}
|
|
155
159
|
|
|
156
160
|
getAll(...args) {
|
|
161
|
+
(0, _utils.collate)(this, FormData);
|
|
157
162
|
this.#ensureArgs(args, 1, 'getAll');
|
|
158
|
-
const name = (0,
|
|
163
|
+
const name = (0, _nodeUtil.toUSVString)(args[0]);
|
|
159
164
|
return this.#entries.filter(it => it.name === name).map(it => it.value);
|
|
160
165
|
}
|
|
161
166
|
|
|
162
167
|
has(...args) {
|
|
168
|
+
(0, _utils.collate)(this, FormData);
|
|
163
169
|
this.#ensureArgs(args, 1, 'has');
|
|
164
|
-
const name = (0,
|
|
170
|
+
const name = (0, _nodeUtil.toUSVString)(args[0]);
|
|
165
171
|
return !!this.#entries.find(it => it.name === name);
|
|
166
172
|
}
|
|
167
173
|
|
|
168
174
|
set(...args) {
|
|
175
|
+
(0, _utils.collate)(this, FormData);
|
|
169
176
|
this.#ensureArgs(args, 2, 'set');
|
|
170
177
|
const entry = this.constructor.#enfoldEntry(...args);
|
|
171
178
|
const idx = this.#entries.findIndex(it => it.name === entry.name);
|
|
@@ -178,6 +185,8 @@ class FormData {
|
|
|
178
185
|
}
|
|
179
186
|
|
|
180
187
|
*entries() {
|
|
188
|
+
(0, _utils.collate)(this, FormData);
|
|
189
|
+
|
|
181
190
|
for (const {
|
|
182
191
|
name,
|
|
183
192
|
value
|
|
@@ -187,18 +196,23 @@ class FormData {
|
|
|
187
196
|
}
|
|
188
197
|
|
|
189
198
|
*keys() {
|
|
199
|
+
(0, _utils.collate)(this, FormData);
|
|
200
|
+
|
|
190
201
|
for (const [name] of this) {
|
|
191
202
|
yield name;
|
|
192
203
|
}
|
|
193
204
|
}
|
|
194
205
|
|
|
195
206
|
*values() {
|
|
207
|
+
(0, _utils.collate)(this, FormData);
|
|
208
|
+
|
|
196
209
|
for (const [, value] of this) {
|
|
197
210
|
yield value;
|
|
198
211
|
}
|
|
199
212
|
}
|
|
200
213
|
|
|
201
214
|
[Symbol.iterator]() {
|
|
215
|
+
(0, _utils.collate)(this, FormData);
|
|
202
216
|
return this.entries();
|
|
203
217
|
}
|
|
204
218
|
|