rekwest 4.5.6 → 5.0.0
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 +34 -11
- package/dist/formdata.js +6 -6
- package/dist/index.js +23 -19
- package/dist/transform.js +4 -4
- package/dist/utils.js +31 -20
- package/package.json +9 -9
- package/src/formdata.mjs +6 -5
- package/src/index.mjs +8 -5
- package/src/transform.mjs +10 -6
- package/src/utils.mjs +37 -25
- package/dist/file.js +0 -44
- package/src/file.mjs +0 -49
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ and [http2.request](https://nodejs.org/api/http2.html#clienthttp2sessionrequesth
|
|
|
12
12
|
* Automatic or opt-in body parse (with non-UTF-8 charset decoding)
|
|
13
13
|
* Automatic and simplistic `Cookies` treatment (with built-in **jar** & **ttl**)
|
|
14
14
|
* Automatic decompression (with opt-in body compression)
|
|
15
|
-
* Built-in streamable `
|
|
15
|
+
* Built-in streamable `FormData` interface
|
|
16
16
|
* Support redirects & retries with fine-grained tune-ups
|
|
17
17
|
* Support all legit request body types (include blobs & streams)
|
|
18
18
|
* Support both CJS and ESM module systems
|
|
@@ -21,7 +21,7 @@ and [http2.request](https://nodejs.org/api/http2.html#clienthttp2sessionrequesth
|
|
|
21
21
|
|
|
22
22
|
## Prerequisites
|
|
23
23
|
|
|
24
|
-
* Node.js `>=
|
|
24
|
+
* Node.js `>= 18.13.0`
|
|
25
25
|
|
|
26
26
|
## Installation
|
|
27
27
|
|
|
@@ -65,13 +65,13 @@ console.log(res.body);
|
|
|
65
65
|
---
|
|
66
66
|
|
|
67
67
|
```javascript
|
|
68
|
+
import { Readable } from 'node:stream';
|
|
68
69
|
import rekwest, {
|
|
69
70
|
constants,
|
|
70
71
|
Blob,
|
|
71
72
|
File,
|
|
72
73
|
FormData,
|
|
73
74
|
} from 'rekwest';
|
|
74
|
-
import { Readable } from 'node:stream';
|
|
75
75
|
|
|
76
76
|
const {
|
|
77
77
|
HTTP2_HEADER_AUTHORIZATION,
|
|
@@ -122,7 +122,8 @@ console.log(res.body);
|
|
|
122
122
|
for HTTP/2 attunes
|
|
123
123
|
* `baseURL` **{string | URL}** The base URL to use in cases where `url` is a relative URL
|
|
124
124
|
* `body` **{string | Array | ArrayBuffer | ArrayBufferView | AsyncIterator | Blob | Buffer | DataView | File |
|
|
125
|
-
FormData | Iterator | Object | Readable | SharedArrayBuffer | URLSearchParams}** The body to send
|
|
125
|
+
FormData | Iterator | Object | Readable | ReadableStream | SharedArrayBuffer | URLSearchParams}** The body to send
|
|
126
|
+
with the request
|
|
126
127
|
* `cookies` **{boolean | Array<[k, v]> | Array<string\> | Cookies | Object | URLSearchParams}** `Default: true` The
|
|
127
128
|
cookies to add to
|
|
128
129
|
the request
|
|
@@ -172,13 +173,13 @@ console.log(res.body);
|
|
|
172
173
|
|
|
173
174
|
#### `rekwest.defaults`
|
|
174
175
|
|
|
175
|
-
The object to fulfill with default [options](#rekwesturl-options)
|
|
176
|
+
The object to fulfill with default [options](#rekwesturl-options).
|
|
176
177
|
|
|
177
178
|
---
|
|
178
179
|
|
|
179
180
|
#### `rekwest.extend(options)`
|
|
180
181
|
|
|
181
|
-
The method to extend default [options](#rekwesturl-options) per instance
|
|
182
|
+
The method to extend default [options](#rekwesturl-options) per instance.
|
|
182
183
|
|
|
183
184
|
```javascript
|
|
184
185
|
import rekwest, { constants } from 'rekwest';
|
|
@@ -207,13 +208,35 @@ console.log(res.body);
|
|
|
207
208
|
|
|
208
209
|
#### `rekwest.stream(url[, options])`
|
|
209
210
|
|
|
210
|
-
The method with limited functionality to use with streams and/or pipes
|
|
211
|
+
The method with limited functionality to use with streams and/or pipes.
|
|
211
212
|
|
|
212
|
-
* No automata
|
|
213
|
-
* No redirects
|
|
213
|
+
* No automata (redirects & retries)
|
|
214
214
|
* Pass `h2: true` in options to use HTTP/2 protocol
|
|
215
|
-
* Use `ackn({ url: URL })` method
|
|
215
|
+
* Use `ackn({ url: URL })` method in advance to check the available protocols
|
|
216
|
+
|
|
217
|
+
```javascript
|
|
218
|
+
import fs from 'node:fs';
|
|
219
|
+
import { pipeline } from 'node:stream/promises';
|
|
220
|
+
import rekwest, {
|
|
221
|
+
ackn,
|
|
222
|
+
constants,
|
|
223
|
+
normalize,
|
|
224
|
+
} from 'rekwest';
|
|
225
|
+
|
|
226
|
+
const {
|
|
227
|
+
HTTP2_METHOD_POST,
|
|
228
|
+
} = constants;
|
|
229
|
+
|
|
230
|
+
const url = new URL('https://somewhe.re/somewhat/endpoint');
|
|
231
|
+
const options = await ackn({ url });
|
|
232
|
+
|
|
233
|
+
await pipeline(
|
|
234
|
+
fs.createReadStream('input.dab'),
|
|
235
|
+
rekwest.stream(url, { ...options, method: HTTP2_METHOD_POST }),
|
|
236
|
+
fs.createWriteStream('output.dab'),
|
|
237
|
+
);
|
|
238
|
+
```
|
|
216
239
|
|
|
217
240
|
---
|
|
218
241
|
|
|
219
|
-
For more details, please check tests (coverage: **>97%**) in the repository
|
|
242
|
+
For more details, please check tests (coverage: **>97%**) in the repository.
|
package/dist/formdata.js
CHANGED
|
@@ -4,10 +4,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.FormData = void 0;
|
|
7
|
+
var _nodeBuffer = require("node:buffer");
|
|
7
8
|
var _nodeCrypto = require("node:crypto");
|
|
8
9
|
var _nodeHttp = _interopRequireDefault(require("node:http2"));
|
|
9
10
|
var _nodeUtil = require("node:util");
|
|
10
|
-
var _file = require("./file");
|
|
11
11
|
var _mediatypes = require("./mediatypes");
|
|
12
12
|
var _utils = require("./utils");
|
|
13
13
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -22,7 +22,7 @@ class FormData {
|
|
|
22
22
|
const contentType = `${_mediatypes.MULTIPART_FORM_DATA}; boundary=${boundary}`;
|
|
23
23
|
const prefix = `--${boundary}${CRLF}${HTTP2_HEADER_CONTENT_DISPOSITION}: form-data`;
|
|
24
24
|
const escape = str => str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22');
|
|
25
|
-
const redress =
|
|
25
|
+
const redress = str => str.replace(/\r?\n|\r/g, CRLF);
|
|
26
26
|
return {
|
|
27
27
|
contentType,
|
|
28
28
|
async *[Symbol.asyncIterator]() {
|
|
@@ -41,14 +41,14 @@ class FormData {
|
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
static alike(instance) {
|
|
44
|
-
return
|
|
44
|
+
return FormData.name === instance?.[Symbol.toStringTag];
|
|
45
45
|
}
|
|
46
46
|
static #enfoldEntry(name, value, filename) {
|
|
47
47
|
name = (0, _nodeUtil.toUSVString)(name);
|
|
48
48
|
filename &&= (0, _nodeUtil.toUSVString)(filename);
|
|
49
|
-
if (
|
|
49
|
+
if ((0, _utils.isFileLike)(value)) {
|
|
50
50
|
filename ??= value.name || 'blob';
|
|
51
|
-
value = new
|
|
51
|
+
value = new _nodeBuffer.File([value], filename, value);
|
|
52
52
|
} else if (this.#ensureInstance(value)) {
|
|
53
53
|
value.name = filename;
|
|
54
54
|
} else {
|
|
@@ -60,7 +60,7 @@ class FormData {
|
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
static #ensureInstance(value) {
|
|
63
|
-
return
|
|
63
|
+
return (0, _utils.isFileLike)(value) || value === Object(value) && Reflect.has(value, Symbol.asyncIterator);
|
|
64
64
|
}
|
|
65
65
|
#entries = [];
|
|
66
66
|
get [Symbol.toStringTag]() {
|
package/dist/index.js
CHANGED
|
@@ -5,8 +5,22 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
var _exportNames = {
|
|
7
7
|
constants: true,
|
|
8
|
-
mediatypes: true
|
|
8
|
+
mediatypes: true,
|
|
9
|
+
Blob: true,
|
|
10
|
+
File: true
|
|
9
11
|
};
|
|
12
|
+
Object.defineProperty(exports, "Blob", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _nodeBuffer.Blob;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "File", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _nodeBuffer.File;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
10
24
|
Object.defineProperty(exports, "constants", {
|
|
11
25
|
enumerable: true,
|
|
12
26
|
get: function () {
|
|
@@ -31,8 +45,9 @@ Object.keys(_constants).forEach(function (key) {
|
|
|
31
45
|
});
|
|
32
46
|
});
|
|
33
47
|
var _defaults = _interopRequireDefault(require("./defaults"));
|
|
34
|
-
var
|
|
35
|
-
|
|
48
|
+
var _mediatypes2 = _interopRequireWildcard(require("./mediatypes"));
|
|
49
|
+
var _mediatypes = _mediatypes2;
|
|
50
|
+
exports.mediatypes = _mediatypes2;
|
|
36
51
|
var _preflight = require("./preflight");
|
|
37
52
|
var _transfer = require("./transfer");
|
|
38
53
|
var _utils = require("./utils");
|
|
@@ -59,6 +74,7 @@ Object.keys(_validation).forEach(function (key) {
|
|
|
59
74
|
}
|
|
60
75
|
});
|
|
61
76
|
});
|
|
77
|
+
var _nodeBuffer = require("node:buffer");
|
|
62
78
|
var _ackn = require("./ackn");
|
|
63
79
|
Object.keys(_ackn).forEach(function (key) {
|
|
64
80
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -95,18 +111,6 @@ Object.keys(_errors).forEach(function (key) {
|
|
|
95
111
|
}
|
|
96
112
|
});
|
|
97
113
|
});
|
|
98
|
-
var _file = require("./file");
|
|
99
|
-
Object.keys(_file).forEach(function (key) {
|
|
100
|
-
if (key === "default" || key === "__esModule") return;
|
|
101
|
-
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
102
|
-
if (key in exports && exports[key] === _file[key]) return;
|
|
103
|
-
Object.defineProperty(exports, key, {
|
|
104
|
-
enumerable: true,
|
|
105
|
-
get: function () {
|
|
106
|
-
return _file[key];
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
114
|
var _formdata = require("./formdata");
|
|
111
115
|
Object.keys(_formdata).forEach(function (key) {
|
|
112
116
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -146,21 +150,21 @@ Reflect.defineProperty(rekwest, 'defaults', {
|
|
|
146
150
|
return _defaults.default.stash;
|
|
147
151
|
},
|
|
148
152
|
set(value) {
|
|
149
|
-
_defaults.default.stash = (0, _utils.
|
|
153
|
+
_defaults.default.stash = (0, _utils.copyWithMerge)(_defaults.default.stash, value);
|
|
150
154
|
}
|
|
151
155
|
});
|
|
152
156
|
Reflect.defineProperty(rekwest, 'extend', {
|
|
153
157
|
enumerable: true,
|
|
154
158
|
value(options) {
|
|
155
|
-
return (url, opts) => rekwest(url, (0, _utils.
|
|
159
|
+
return (url, opts) => rekwest(url, (0, _utils.copyWithMerge)(options, opts));
|
|
156
160
|
}
|
|
157
161
|
});
|
|
158
162
|
Reflect.defineProperty(rekwest, 'stream', {
|
|
159
163
|
enumerable: true,
|
|
160
164
|
value(url, options) {
|
|
161
|
-
options = (0, _preflight.preflight)((0, _validation.validation)((0, _utils.normalize)(url, (0, _utils.
|
|
165
|
+
options = (0, _preflight.preflight)((0, _validation.validation)((0, _utils.normalize)(url, (0, _utils.copyWithMerge)({}, options, {
|
|
162
166
|
headers: {
|
|
163
|
-
[HTTP2_HEADER_CONTENT_TYPE]:
|
|
167
|
+
[HTTP2_HEADER_CONTENT_TYPE]: _mediatypes2.APPLICATION_OCTET_STREAM
|
|
164
168
|
},
|
|
165
169
|
redirect: _constants.requestRedirect.manual
|
|
166
170
|
}))));
|
package/dist/transform.js
CHANGED
|
@@ -8,7 +8,6 @@ var _nodeHttp = _interopRequireDefault(require("node:http2"));
|
|
|
8
8
|
var _nodeStream = require("node:stream");
|
|
9
9
|
var _consumers = require("node:stream/consumers");
|
|
10
10
|
var _nodeUtil = require("node:util");
|
|
11
|
-
var _file = require("./file");
|
|
12
11
|
var _formdata = require("./formdata");
|
|
13
12
|
var _mediatypes = require("./mediatypes");
|
|
14
13
|
var _utils = require("./utils");
|
|
@@ -26,12 +25,12 @@ const transform = async options => {
|
|
|
26
25
|
if (!body) {
|
|
27
26
|
return options;
|
|
28
27
|
}
|
|
29
|
-
if (
|
|
28
|
+
if ((0, _utils.isFileLike)(body)) {
|
|
30
29
|
headers = {
|
|
31
30
|
[HTTP2_HEADER_CONTENT_LENGTH]: body.size,
|
|
32
31
|
[HTTP2_HEADER_CONTENT_TYPE]: body.type || _mediatypes.APPLICATION_OCTET_STREAM
|
|
33
32
|
};
|
|
34
|
-
body =
|
|
33
|
+
body = body.stream();
|
|
35
34
|
} else if (_formdata.FormData.alike(body)) {
|
|
36
35
|
body = _formdata.FormData.actuate(body);
|
|
37
36
|
headers = {
|
|
@@ -58,7 +57,8 @@ const transform = async options => {
|
|
|
58
57
|
}
|
|
59
58
|
const encodings = options.headers[HTTP2_HEADER_CONTENT_ENCODING];
|
|
60
59
|
if (body === Object(body) && (Reflect.has(body, Symbol.asyncIterator) || !Array.isArray(body) && Reflect.has(body, Symbol.iterator))) {
|
|
61
|
-
body =
|
|
60
|
+
body = (0, _nodeStream.isReadable)(body) ? (0, _utils.isReadableStream)(body) ? _nodeStream.Readable.fromWeb(body) : body : _nodeStream.Readable.from(body);
|
|
61
|
+
body = encodings ? (0, _utils.compress)(body, encodings) : body;
|
|
62
62
|
} else if (encodings) {
|
|
63
63
|
body = await (0, _consumers.buffer)((0, _utils.compress)(_nodeStream.Readable.from(body), encodings));
|
|
64
64
|
}
|
package/dist/utils.js
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.sameOrigin = exports.normalize = exports.merge = exports.maxRetryAfterError = exports.maxRetryAfter = exports.dispatch = exports.decompress = exports.compress = exports.brandCheck = exports.affix = exports.admix = void 0;
|
|
6
|
+
exports.sameOrigin = exports.normalize = exports.merge = exports.maxRetryAfterError = exports.maxRetryAfter = exports.isReadableStream = exports.isFileLike = exports.dispatch = exports.decompress = exports.copyWithMerge = exports.compress = exports.brandCheck = exports.affix = exports.admix = void 0;
|
|
7
7
|
exports.tap = tap;
|
|
8
8
|
exports.unwind = exports.toCamelCase = void 0;
|
|
9
|
+
var _nodeBuffer = require("node:buffer");
|
|
9
10
|
var _nodeHttp = _interopRequireDefault(require("node:http2"));
|
|
10
11
|
var _nodeStream = require("node:stream");
|
|
11
12
|
var _nodeZlib = _interopRequireDefault(require("node:zlib"));
|
|
@@ -80,6 +81,14 @@ const compress = (readable, encodings = '') => {
|
|
|
80
81
|
return (0, _nodeStream.pipeline)(readable, ...encoders, () => void 0);
|
|
81
82
|
};
|
|
82
83
|
exports.compress = compress;
|
|
84
|
+
const copyWithMerge = (target, ...rest) => {
|
|
85
|
+
target = structuredClone(target);
|
|
86
|
+
if (!rest.length) {
|
|
87
|
+
return target;
|
|
88
|
+
}
|
|
89
|
+
return merge(target, ...rest);
|
|
90
|
+
};
|
|
91
|
+
exports.copyWithMerge = copyWithMerge;
|
|
83
92
|
const decompress = (readable, encodings = '') => {
|
|
84
93
|
const decoders = [];
|
|
85
94
|
encodings = unwind(encodings);
|
|
@@ -109,35 +118,37 @@ const dispatch = ({
|
|
|
109
118
|
}
|
|
110
119
|
};
|
|
111
120
|
exports.dispatch = dispatch;
|
|
121
|
+
const isFileLike = instance => {
|
|
122
|
+
return [_nodeBuffer.Blob.name, _nodeBuffer.File.name].includes(instance?.[Symbol.toStringTag]);
|
|
123
|
+
};
|
|
124
|
+
exports.isFileLike = isFileLike;
|
|
125
|
+
const isReadableStream = instance => {
|
|
126
|
+
return ReadableStream.name === instance?.[Symbol.toStringTag];
|
|
127
|
+
};
|
|
128
|
+
exports.isReadableStream = isReadableStream;
|
|
112
129
|
const maxRetryAfter = Symbol('maxRetryAfter');
|
|
113
130
|
exports.maxRetryAfter = maxRetryAfter;
|
|
114
131
|
const maxRetryAfterError = (interval, options) => new _errors.RequestError(`Maximum '${HTTP2_HEADER_RETRY_AFTER}' limit exceeded: ${interval} ms.`, options);
|
|
115
132
|
exports.maxRetryAfterError = maxRetryAfterError;
|
|
116
|
-
const merge = (target
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
acc[key] = merge(acc[key], val);
|
|
126
|
-
} else {
|
|
127
|
-
acc[key] = val;
|
|
128
|
-
}
|
|
129
|
-
} else {
|
|
130
|
-
acc[key] = val;
|
|
133
|
+
const merge = (target, ...rest) => {
|
|
134
|
+
rest = rest.filter(it => it === Object(it));
|
|
135
|
+
for (const source of rest) {
|
|
136
|
+
for (const key of Object.getOwnPropertyNames(source)) {
|
|
137
|
+
const sv = source[key];
|
|
138
|
+
const tv = target[key];
|
|
139
|
+
if (Object(sv) === sv && Object(tv) === tv) {
|
|
140
|
+
target[key] = merge(tv, sv);
|
|
141
|
+
continue;
|
|
131
142
|
}
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
}
|
|
143
|
+
target[key] = source[key];
|
|
144
|
+
}
|
|
145
|
+
}
|
|
135
146
|
return target;
|
|
136
147
|
};
|
|
137
148
|
exports.merge = merge;
|
|
138
149
|
const normalize = (url, options = {}) => {
|
|
139
150
|
if (!options.redirected) {
|
|
140
|
-
options =
|
|
151
|
+
options = copyWithMerge(_defaults.default.stash, options);
|
|
141
152
|
}
|
|
142
153
|
if (options.trimTrailingSlashes) {
|
|
143
154
|
url = `${url}`.replace(/(?<!:)\/+/g, '/');
|
package/package.json
CHANGED
|
@@ -8,18 +8,18 @@
|
|
|
8
8
|
"url": "https://github.com/bricss/rekwest/issues"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
|
-
"@babel/cli": "^7.22.
|
|
12
|
-
"@babel/core": "^7.22.
|
|
13
|
-
"@babel/eslint-parser": "^7.22.
|
|
14
|
-
"@babel/preset-env": "^7.22.
|
|
15
|
-
"c8": "^8.0.
|
|
16
|
-
"eslint": "^8.
|
|
17
|
-
"eslint-config-ultra-refined": "^2.
|
|
11
|
+
"@babel/cli": "^7.22.15",
|
|
12
|
+
"@babel/core": "^7.22.20",
|
|
13
|
+
"@babel/eslint-parser": "^7.22.15",
|
|
14
|
+
"@babel/preset-env": "^7.22.20",
|
|
15
|
+
"c8": "^8.0.1",
|
|
16
|
+
"eslint": "^8.50.0",
|
|
17
|
+
"eslint-config-ultra-refined": "^2.18.0",
|
|
18
18
|
"mocha": "^10.2.0"
|
|
19
19
|
},
|
|
20
20
|
"description": "The robust request library that humanity deserves 🌐",
|
|
21
21
|
"engines": {
|
|
22
|
-
"node": ">=
|
|
22
|
+
"node": ">=18.13.0"
|
|
23
23
|
},
|
|
24
24
|
"exports": {
|
|
25
25
|
"import": "./src/index.mjs",
|
|
@@ -69,5 +69,5 @@
|
|
|
69
69
|
"test:bail": "mocha --bail",
|
|
70
70
|
"test:cover": "c8 --include=src --reporter=lcov --reporter=text npm test"
|
|
71
71
|
},
|
|
72
|
-
"version": "
|
|
72
|
+
"version": "5.0.0"
|
|
73
73
|
}
|
package/src/formdata.mjs
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import { File } from 'node:buffer';
|
|
1
2
|
import { randomBytes } from 'node:crypto';
|
|
2
3
|
import http2 from 'node:http2';
|
|
3
4
|
import { toUSVString } from 'node:util';
|
|
4
|
-
import { File } from './file.mjs';
|
|
5
5
|
import {
|
|
6
6
|
APPLICATION_OCTET_STREAM,
|
|
7
7
|
MULTIPART_FORM_DATA,
|
|
8
8
|
} from './mediatypes.mjs';
|
|
9
9
|
import {
|
|
10
10
|
brandCheck,
|
|
11
|
+
isFileLike,
|
|
11
12
|
tap,
|
|
12
13
|
} from './utils.mjs';
|
|
13
14
|
|
|
@@ -25,7 +26,7 @@ export class FormData {
|
|
|
25
26
|
const prefix = `--${ boundary }${ CRLF }${ HTTP2_HEADER_CONTENT_DISPOSITION }: form-data`;
|
|
26
27
|
|
|
27
28
|
const escape = (str) => str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22');
|
|
28
|
-
const redress = (
|
|
29
|
+
const redress = (str) => str.replace(/\r?\n|\r/g, CRLF);
|
|
29
30
|
|
|
30
31
|
return {
|
|
31
32
|
contentType,
|
|
@@ -59,14 +60,14 @@ export class FormData {
|
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
static alike(instance) {
|
|
62
|
-
return
|
|
63
|
+
return FormData.name === instance?.[Symbol.toStringTag];
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
static #enfoldEntry(name, value, filename) {
|
|
66
67
|
name = toUSVString(name);
|
|
67
68
|
filename &&= toUSVString(filename);
|
|
68
69
|
|
|
69
|
-
if (
|
|
70
|
+
if (isFileLike(value)) {
|
|
70
71
|
filename ??= value.name || 'blob';
|
|
71
72
|
value = new File([value], filename, value);
|
|
72
73
|
} else if (this.#ensureInstance(value)) {
|
|
@@ -82,7 +83,7 @@ export class FormData {
|
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
static #ensureInstance(value) {
|
|
85
|
-
return
|
|
86
|
+
return isFileLike(value) || (value === Object(value) && Reflect.has(value, Symbol.asyncIterator));
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
#entries = [];
|
package/src/index.mjs
CHANGED
|
@@ -9,18 +9,21 @@ import { transfer } from './transfer.mjs';
|
|
|
9
9
|
import {
|
|
10
10
|
admix,
|
|
11
11
|
affix,
|
|
12
|
-
|
|
12
|
+
copyWithMerge,
|
|
13
13
|
normalize,
|
|
14
14
|
} from './utils.mjs';
|
|
15
15
|
import { validation } from './validation.mjs';
|
|
16
16
|
|
|
17
|
+
export {
|
|
18
|
+
Blob,
|
|
19
|
+
File,
|
|
20
|
+
} from 'node:buffer';
|
|
17
21
|
export { constants } from 'node:http2';
|
|
18
22
|
|
|
19
23
|
export * from './ackn.mjs';
|
|
20
24
|
export * from './constants.mjs';
|
|
21
25
|
export * from './cookies.mjs';
|
|
22
26
|
export * from './errors.mjs';
|
|
23
|
-
export * from './file.mjs';
|
|
24
27
|
export * from './formdata.mjs';
|
|
25
28
|
export * as mediatypes from './mediatypes.mjs';
|
|
26
29
|
export * from './mixin.mjs';
|
|
@@ -38,20 +41,20 @@ export default function rekwest(url, options) {
|
|
|
38
41
|
Reflect.defineProperty(rekwest, 'defaults', {
|
|
39
42
|
enumerable: true,
|
|
40
43
|
get() { return defaults.stash; },
|
|
41
|
-
set(value) { defaults.stash =
|
|
44
|
+
set(value) { defaults.stash = copyWithMerge(defaults.stash, value); },
|
|
42
45
|
});
|
|
43
46
|
|
|
44
47
|
Reflect.defineProperty(rekwest, 'extend', {
|
|
45
48
|
enumerable: true,
|
|
46
49
|
value(options) {
|
|
47
|
-
return (url, opts) => rekwest(url,
|
|
50
|
+
return (url, opts) => rekwest(url, copyWithMerge(options, opts));
|
|
48
51
|
},
|
|
49
52
|
});
|
|
50
53
|
|
|
51
54
|
Reflect.defineProperty(rekwest, 'stream', {
|
|
52
55
|
enumerable: true,
|
|
53
56
|
value(url, options) {
|
|
54
|
-
options = preflight(validation(normalize(url,
|
|
57
|
+
options = preflight(validation(normalize(url, copyWithMerge({}, options, {
|
|
55
58
|
headers: { [HTTP2_HEADER_CONTENT_TYPE]: APPLICATION_OCTET_STREAM },
|
|
56
59
|
redirect: requestRedirect.manual,
|
|
57
60
|
}))));
|
package/src/transform.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import http2 from 'node:http2';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
isReadable,
|
|
4
|
+
Readable,
|
|
5
|
+
} from 'node:stream';
|
|
3
6
|
import { buffer } from 'node:stream/consumers';
|
|
4
7
|
import { types } from 'node:util';
|
|
5
|
-
import { File } from './file.mjs';
|
|
6
8
|
import { FormData } from './formdata.mjs';
|
|
7
9
|
import {
|
|
8
10
|
APPLICATION_FORM_URLENCODED,
|
|
@@ -11,7 +13,8 @@ import {
|
|
|
11
13
|
} from './mediatypes.mjs';
|
|
12
14
|
import {
|
|
13
15
|
compress,
|
|
14
|
-
|
|
16
|
+
isFileLike,
|
|
17
|
+
isReadableStream,
|
|
15
18
|
} from './utils.mjs';
|
|
16
19
|
|
|
17
20
|
const {
|
|
@@ -27,12 +30,12 @@ export const transform = async (options) => {
|
|
|
27
30
|
return options;
|
|
28
31
|
}
|
|
29
32
|
|
|
30
|
-
if (
|
|
33
|
+
if (isFileLike(body)) {
|
|
31
34
|
headers = {
|
|
32
35
|
[HTTP2_HEADER_CONTENT_LENGTH]: body.size,
|
|
33
36
|
[HTTP2_HEADER_CONTENT_TYPE]: body.type || APPLICATION_OCTET_STREAM,
|
|
34
37
|
};
|
|
35
|
-
body =
|
|
38
|
+
body = body.stream();
|
|
36
39
|
} else if (FormData.alike(body)) {
|
|
37
40
|
body = FormData.actuate(body);
|
|
38
41
|
headers = { [HTTP2_HEADER_CONTENT_TYPE]: body.contentType };
|
|
@@ -56,7 +59,8 @@ export const transform = async (options) => {
|
|
|
56
59
|
|
|
57
60
|
if (body === Object(body)
|
|
58
61
|
&& (Reflect.has(body, Symbol.asyncIterator) || (!Array.isArray(body) && Reflect.has(body, Symbol.iterator)))) {
|
|
59
|
-
body =
|
|
62
|
+
body = isReadable(body) ? (isReadableStream(body) ? Readable.fromWeb(body) : body) : Readable.from(body);
|
|
63
|
+
body = encodings ? compress(body, encodings) : body;
|
|
60
64
|
} else if (encodings) {
|
|
61
65
|
body = await buffer(compress(Readable.from(body), encodings));
|
|
62
66
|
}
|
package/src/utils.mjs
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Blob,
|
|
3
|
+
File,
|
|
4
|
+
} from 'node:buffer';
|
|
1
5
|
import http2 from 'node:http2';
|
|
2
6
|
import { pipeline } from 'node:stream';
|
|
3
7
|
import zlib from 'node:zlib';
|
|
@@ -82,6 +86,15 @@ export const compress = (readable, encodings = '') => {
|
|
|
82
86
|
return pipeline(readable, ...encoders, () => void 0);
|
|
83
87
|
};
|
|
84
88
|
|
|
89
|
+
export const copyWithMerge = (target, ...rest) => {
|
|
90
|
+
target = structuredClone(target);
|
|
91
|
+
if (!rest.length) {
|
|
92
|
+
return target;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return merge(target, ...rest);
|
|
96
|
+
};
|
|
97
|
+
|
|
85
98
|
export const decompress = (readable, encodings = '') => {
|
|
86
99
|
const decoders = [];
|
|
87
100
|
|
|
@@ -112,6 +125,17 @@ export const dispatch = ({ body }, req) => {
|
|
|
112
125
|
}
|
|
113
126
|
};
|
|
114
127
|
|
|
128
|
+
export const isFileLike = (instance) => {
|
|
129
|
+
return [
|
|
130
|
+
Blob.name,
|
|
131
|
+
File.name,
|
|
132
|
+
].includes(instance?.[Symbol.toStringTag]);
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export const isReadableStream = (instance) => {
|
|
136
|
+
return ReadableStream.name === instance?.[Symbol.toStringTag];
|
|
137
|
+
};
|
|
138
|
+
|
|
115
139
|
export const maxRetryAfter = Symbol('maxRetryAfter');
|
|
116
140
|
|
|
117
141
|
export const maxRetryAfterError = (
|
|
@@ -119,40 +143,28 @@ export const maxRetryAfterError = (
|
|
|
119
143
|
options,
|
|
120
144
|
) => new RequestError(`Maximum '${ HTTP2_HEADER_RETRY_AFTER }' limit exceeded: ${ interval } ms.`, options);
|
|
121
145
|
|
|
122
|
-
export const merge = (target
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
146
|
+
export const merge = (target, ...rest) => {
|
|
147
|
+
rest = rest.filter((it) => it === Object(it));
|
|
148
|
+
for (const source of rest) {
|
|
149
|
+
for (const key of Object.getOwnPropertyNames(source)) {
|
|
150
|
+
const sv = source[key];
|
|
151
|
+
const tv = target[key];
|
|
127
152
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
acc[key]?.constructor,
|
|
132
|
-
val?.constructor,
|
|
133
|
-
].every((it) => [
|
|
134
|
-
Array,
|
|
135
|
-
Object,
|
|
136
|
-
].includes(it))) {
|
|
137
|
-
if (acc[key]?.constructor === val.constructor) {
|
|
138
|
-
acc[key] = merge(acc[key], val);
|
|
139
|
-
} else {
|
|
140
|
-
acc[key] = val;
|
|
141
|
-
}
|
|
142
|
-
} else {
|
|
143
|
-
acc[key] = val;
|
|
153
|
+
if (Object(sv) === sv && Object(tv) === tv) {
|
|
154
|
+
target[key] = merge(tv, sv);
|
|
155
|
+
continue;
|
|
144
156
|
}
|
|
145
157
|
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
}
|
|
158
|
+
target[key] = source[key];
|
|
159
|
+
}
|
|
160
|
+
}
|
|
149
161
|
|
|
150
162
|
return target;
|
|
151
163
|
};
|
|
152
164
|
|
|
153
165
|
export const normalize = (url, options = {}) => {
|
|
154
166
|
if (!options.redirected) {
|
|
155
|
-
options =
|
|
167
|
+
options = copyWithMerge(defaults.stash, options);
|
|
156
168
|
}
|
|
157
169
|
|
|
158
170
|
if (options.trimTrailingSlashes) {
|
package/dist/file.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
Object.defineProperty(exports, "Blob", {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: function () {
|
|
9
|
-
return _nodeBuffer.Blob;
|
|
10
|
-
}
|
|
11
|
-
});
|
|
12
|
-
exports.File = void 0;
|
|
13
|
-
var _nodeBuffer = require("node:buffer");
|
|
14
|
-
var _nodeUtil = require("node:util");
|
|
15
|
-
class File extends _nodeBuffer.Blob {
|
|
16
|
-
static alike(instance) {
|
|
17
|
-
return [_nodeBuffer.Blob.name, File.name].includes(instance?.constructor.name);
|
|
18
|
-
}
|
|
19
|
-
#lastModified;
|
|
20
|
-
#name;
|
|
21
|
-
get [Symbol.toStringTag]() {
|
|
22
|
-
return this.constructor.name;
|
|
23
|
-
}
|
|
24
|
-
get lastModified() {
|
|
25
|
-
return this.#lastModified;
|
|
26
|
-
}
|
|
27
|
-
get name() {
|
|
28
|
-
return this.#name;
|
|
29
|
-
}
|
|
30
|
-
constructor(...args) {
|
|
31
|
-
const len = args.length;
|
|
32
|
-
if (len < 2) {
|
|
33
|
-
throw new TypeError(`Failed to construct '${File.name}': 2 arguments required, but only ${len} present.`);
|
|
34
|
-
}
|
|
35
|
-
const [bits, name, options = {}] = args;
|
|
36
|
-
const {
|
|
37
|
-
lastModified = Date.now()
|
|
38
|
-
} = options;
|
|
39
|
-
super(bits, options);
|
|
40
|
-
this.#lastModified = +lastModified ? lastModified : 0;
|
|
41
|
-
this.#name = (0, _nodeUtil.toUSVString)(name);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
exports.File = File;
|
package/src/file.mjs
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { Blob } from 'node:buffer';
|
|
2
|
-
import { toUSVString } from 'node:util';
|
|
3
|
-
|
|
4
|
-
export { Blob } from 'node:buffer';
|
|
5
|
-
|
|
6
|
-
export class File extends Blob {
|
|
7
|
-
|
|
8
|
-
static alike(instance) {
|
|
9
|
-
return [
|
|
10
|
-
Blob.name,
|
|
11
|
-
File.name,
|
|
12
|
-
].includes(instance?.constructor.name);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
#lastModified;
|
|
16
|
-
#name;
|
|
17
|
-
|
|
18
|
-
get [Symbol.toStringTag]() {
|
|
19
|
-
return this.constructor.name;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
get lastModified() {
|
|
23
|
-
return this.#lastModified;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
get name() {
|
|
27
|
-
return this.#name;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
constructor(...args) {
|
|
31
|
-
const len = args.length;
|
|
32
|
-
|
|
33
|
-
if (len < 2) {
|
|
34
|
-
throw new TypeError(`Failed to construct '${
|
|
35
|
-
File.name
|
|
36
|
-
}': 2 arguments required, but only ${ len } present.`);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const [bits, name, options = {}] = args;
|
|
40
|
-
const {
|
|
41
|
-
lastModified = Date.now(),
|
|
42
|
-
} = options;
|
|
43
|
-
|
|
44
|
-
super(bits, options);
|
|
45
|
-
this.#lastModified = +lastModified ? lastModified : 0;
|
|
46
|
-
this.#name = toUSVString(name);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
}
|