rekwest 4.4.4 → 4.5.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 CHANGED
@@ -1,8 +1,8 @@
1
1
  The robust request library that humanity deserves 🌐
2
2
  ---
3
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).
4
+ native [http(s).request](https://nodejs.org/api/https.html#httpsrequesturl-options-callback)
5
+ and [http2.request](https://nodejs.org/api/http2.html#clienthttp2sessionrequestheaders-options).
6
6
 
7
7
  ## Abstract
8
8
 
@@ -10,7 +10,7 @@ and [http2.request](https://nodejs.org/api/http2.html#http2_clienthttp2session_r
10
10
  * Cool-beans 🫐 config options (with defaults)
11
11
  * Automatic HTTP/2 support (ALPN negotiation)
12
12
  * Automatic or opt-in body parse (with non-UTF-8 charset decoding)
13
- * Automatic and simplistic `Cookies` treatment (with built-in jar)
13
+ * Automatic and simplistic `Cookies` treatment (with built-in **jar** & **ttl**)
14
14
  * Automatic decompression (with opt-in body compression)
15
15
  * Built-in streamable `File` & `FormData` interfaces
16
16
  * Support redirects & retries with fine-grained tune-ups
@@ -115,17 +115,17 @@ console.log(res.body);
115
115
 
116
116
  * `url` **{string | URL}** The URL to send the request to
117
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)
118
+ Extends [http(s).RequestOptions](https://nodejs.org/api/https.html#httpsrequesturl-options-callback) along with
119
+ extra [http2.ClientSessionOptions](https://nodejs.org/api/http2.html#http2connectauthority-options-listener)
120
+ & [http2.ClientSessionRequestOptions](https://nodejs.org/api/http2.html#clienthttp2sessionrequestheaders-options)
121
+ and [tls.ConnectionOptions](https://nodejs.org/api/tls.html#tlsconnectoptions-callback)
123
122
  for HTTP/2 attunes
124
123
  * `baseURL` **{string | URL}** The base URL to use in cases where `url` is a relative URL
125
124
  * `body` **{string | Array | ArrayBuffer | ArrayBufferView | AsyncIterator | Blob | Buffer | DataView | File |
126
125
  FormData | Iterator | Object | Readable | SharedArrayBuffer | URLSearchParams}** The body to send with the request
127
126
  * `cookies` **{boolean | Array<[k, v]> | Cookies | Object | URLSearchParams}** `Default: true` The cookies to add to
128
127
  the request
128
+ * `cookiesTTL` **{boolean}** `Default: false` Controls enablement of TTL for the cookies cache
129
129
  * `credentials` **{include | omit | same-origin}** `Default: same-origin` Controls credentials in case of cross-origin
130
130
  redirects
131
131
  * `digest` **{boolean}** `Default: true` Controls whether to read the response stream or simply add a mixin
@@ -142,13 +142,13 @@ console.log(res.body);
142
142
  * `interval` **{number}** `Default: 1e3` The initial retry interval
143
143
  * `retryAfter` **{boolean}** `Default: true` Controls `retry-after` header receptiveness
144
144
  * `statusCodes` **{number[]}** `Default: [429, 503]` The list of status codes to retry on
145
+ * `stripTrailingSlash` **{boolean}** `Default: false` Controls whether to strip trailing slash at the end of the URL
145
146
  * `thenable` **{boolean}** `Default: false` Controls the promise resolutions
146
147
  * `timeout` **{number}** `Default: 3e5` The number of milliseconds a request can take before termination
147
- * `trimTrailingSlashes` **{boolean}** `Default: false` Controls whether to trim trailing slashes in the URL before
148
- proceed with the request
148
+ * `trimTrailingSlashes` **{boolean}** `Default: false` Controls whether to trim trailing slashes within the URL
149
149
  * **Returns:** Promise that resolves to
150
- extended [http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
151
- or [http2.ClientHttp2Stream](https://nodejs.org/api/http2.html#http2_class_clienthttp2stream) which is respectively
150
+ extended [http.IncomingMessage](https://nodejs.org/api/http.html#class-httpincomingmessage)
151
+ or [http2.ClientHttp2Stream](https://nodejs.org/api/http2.html#class-clienthttp2stream) which is respectively
152
152
  readable and duplex streams
153
153
  * if `degist: true` & `parse: true`
154
154
  * `body` **{string | Array | Buffer | Object}** The body based on its content type
package/dist/cookies.js CHANGED
@@ -5,14 +5,52 @@ exports.Cookies = void 0;
5
5
  var _utils = require("./utils");
6
6
  class Cookies extends URLSearchParams {
7
7
  static jar = new Map();
8
+ #chronometry = new Map();
8
9
  get [Symbol.toStringTag]() {
9
10
  return this.constructor.name;
10
11
  }
11
- constructor(input) {
12
+ constructor(input, {
13
+ cookiesTTL
14
+ } = {
15
+ cookiesTTL: false
16
+ }) {
12
17
  if (Array.isArray(input) && input.every(it => !Array.isArray(it))) {
13
- input = input.join(';').split(';').filter(it => !/\b(?:Domain|Expires|HttpOnly|Max-Age|Path|SameParty|SameSite|Secure)\b/i.test(it)).map(it => it.trim()).join('&');
18
+ input = input.map(it => {
19
+ if (!cookiesTTL) {
20
+ return [it.split(';').at(0).trim()];
21
+ }
22
+ const [cookie, ...attrs] = it.split(';').map(it => it.trim());
23
+ const ttl = attrs.reduce((acc, val) => {
24
+ if (/(?:Expires|Max-Age)=/i.test(val)) {
25
+ const [key, value] = val.toLowerCase().split('=');
26
+ acc[(0, _utils.toCamelCase)(key)] = !Number.isNaN(Number(value)) ? value * 1e3 : Date.parse(value) - Date.now();
27
+ }
28
+ return acc;
29
+ }, {});
30
+ return [cookie.replace(/\u0022/g, ''), Object.keys(ttl).length ? ttl : null];
31
+ });
32
+ }
33
+ super(Array.isArray(input) ? input.map(it => it.at(0)).join('&') : input);
34
+ if (Array.isArray(input) && cookiesTTL) {
35
+ input.filter(it => it.at(1)).forEach(([cookie, ttl]) => {
36
+ cookie = cookie.split('=').at(0);
37
+ if (this.#chronometry.has(cookie)) {
38
+ clearTimeout(this.#chronometry.get(cookie));
39
+ this.#chronometry.delete(cookie);
40
+ }
41
+ const {
42
+ expires,
43
+ maxAge
44
+ } = ttl;
45
+ [maxAge, expires].filter(it => Number.isInteger(it)).some(ms => {
46
+ const tid = setTimeout(() => {
47
+ this.#chronometry.delete(cookie);
48
+ this.delete(cookie);
49
+ }, Math.max(ms, 0));
50
+ return this.#chronometry.set(cookie, tid);
51
+ });
52
+ });
14
53
  }
15
- super(input);
16
54
  }
17
55
  toString() {
18
56
  (0, _utils.brandCheck)(this, Cookies);
package/dist/defaults.js CHANGED
@@ -12,6 +12,7 @@ const {
12
12
  HTTP_STATUS_TOO_MANY_REQUESTS
13
13
  } = _nodeHttp.default.constants;
14
14
  const stash = {
15
+ cookiesTTL: false,
15
16
  credentials: _constants.requestCredentials.sameOrigin,
16
17
  digest: true,
17
18
  follow: 20,
@@ -33,6 +34,7 @@ const stash = {
33
34
  retryAfter: true,
34
35
  statusCodes: [HTTP_STATUS_TOO_MANY_REQUESTS, HTTP_STATUS_SERVICE_UNAVAILABLE]
35
36
  },
37
+ stripTrailingSlash: false,
36
38
  thenable: false,
37
39
  timeout: 3e5,
38
40
  trimTrailingSlashes: false
package/dist/formdata.js CHANGED
@@ -167,6 +167,7 @@ class FormData {
167
167
  }
168
168
  }
169
169
  [Symbol.iterator]() {
170
+ (0, _utils.brandCheck)(this, FormData);
170
171
  return this.entries();
171
172
  }
172
173
  }
package/dist/index.js CHANGED
@@ -23,6 +23,7 @@ var _defaults = _interopRequireDefault(require("./defaults"));
23
23
  var _mediatypes = _interopRequireWildcard(require("./mediatypes"));
24
24
  exports.mediatypes = _mediatypes;
25
25
  var _preflight = require("./preflight");
26
+ var _transfer = require("./transfer");
26
27
  var _utils = require("./utils");
27
28
  Object.keys(_utils).forEach(function (key) {
28
29
  if (key === "default" || key === "__esModule") return;
@@ -86,7 +87,7 @@ const {
86
87
  HTTP2_HEADER_CONTENT_TYPE
87
88
  } = _nodeHttp2.default.constants;
88
89
  function rekwest(url, options) {
89
- return (0, _utils.transfer)((0, _validation.validation)((0, _utils.normalize)(url, options)), rekwest);
90
+ return (0, _transfer.transfer)((0, _validation.validation)((0, _utils.normalize)(url, options)), rekwest);
90
91
  }
91
92
  Reflect.defineProperty(rekwest, 'defaults', {
92
93
  enumerable: true,
@@ -46,11 +46,15 @@ const postflight = (req, res, options, {
46
46
  (0, _utils.admix)(res, headers, options);
47
47
  if (cookies !== false && res.headers[HTTP2_HEADER_SET_COOKIE]) {
48
48
  if (_cookies.Cookies.jar.has(url.origin)) {
49
- new _cookies.Cookies(res.headers[HTTP2_HEADER_SET_COOKIE]).forEach(function (val, key) {
50
- this.set(key, val);
51
- }, _cookies.Cookies.jar.get(url.origin));
49
+ const cookie = new _cookies.Cookies(res.headers[HTTP2_HEADER_SET_COOKIE], options);
50
+ _cookies.Cookies.jar.get(url.origin).forEach((val, key) => {
51
+ if (!cookie.has(key)) {
52
+ cookie.set(key, val);
53
+ }
54
+ });
55
+ _cookies.Cookies.jar.set(url.origin, cookie);
52
56
  } else {
53
- _cookies.Cookies.jar.set(url.origin, new _cookies.Cookies(res.headers[HTTP2_HEADER_SET_COOKIE]));
57
+ _cookies.Cookies.jar.set(url.origin, new _cookies.Cookies(res.headers[HTTP2_HEADER_SET_COOKIE], options));
54
58
  }
55
59
  }
56
60
  Reflect.defineProperty(res, 'cookies', {
package/dist/preflight.js CHANGED
@@ -31,14 +31,18 @@ const preflight = options => {
31
31
  options.endStream = [HTTP2_METHOD_GET, HTTP2_METHOD_HEAD].includes(method);
32
32
  }
33
33
  if (cookies !== false) {
34
- let cookie = _cookies.Cookies.jar.get(url.origin);
34
+ let cookie = _cookies.Cookies.jar.has(url.origin);
35
35
  if (cookies === Object(cookies) && [_constants.requestCredentials.include, _constants.requestCredentials.sameOrigin].includes(credentials)) {
36
36
  if (cookie) {
37
- new _cookies.Cookies(cookies).forEach(function (val, key) {
38
- this.set(key, val);
39
- }, cookie);
37
+ cookie = new _cookies.Cookies(cookies, options);
38
+ _cookies.Cookies.jar.get(url.origin).forEach((val, key) => {
39
+ if (!cookie.has(key)) {
40
+ cookie.set(key, val);
41
+ }
42
+ });
43
+ _cookies.Cookies.jar.set(url.origin, cookie);
40
44
  } else {
41
- cookie = new _cookies.Cookies(cookies);
45
+ cookie = new _cookies.Cookies(cookies, options);
42
46
  _cookies.Cookies.jar.set(url.origin, cookie);
43
47
  }
44
48
  }
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.transfer = void 0;
5
+ var _nodeHttp = _interopRequireDefault(require("node:http"));
6
+ var _nodeHttp2 = _interopRequireDefault(require("node:http2"));
7
+ var _nodeHttps = _interopRequireDefault(require("node:https"));
8
+ var _promises = require("node:timers/promises");
9
+ var _ackn = require("./ackn");
10
+ var _errors = require("./errors");
11
+ var _postflight = require("./postflight");
12
+ var _preflight = require("./preflight");
13
+ var _transform = require("./transform");
14
+ var _utils = require("./utils");
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
+ const {
17
+ HTTP2_HEADER_RETRY_AFTER
18
+ } = _nodeHttp2.default.constants;
19
+ const transfer = async (options, overact) => {
20
+ const {
21
+ digest,
22
+ redirected,
23
+ thenable,
24
+ url
25
+ } = options;
26
+ if (options.follow === 0) {
27
+ throw new _errors.RequestError(`Maximum redirect reached at: ${url.href}`);
28
+ }
29
+ if (url.protocol === 'https:') {
30
+ options = !options.h2 ? await (0, _ackn.ackn)(options) : {
31
+ ...options,
32
+ createConnection: null,
33
+ protocol: url.protocol
34
+ };
35
+ } else if (Reflect.has(options, 'alpnProtocol')) {
36
+ ['alpnProtocol', 'createConnection', 'h2', 'protocol'].forEach(it => Reflect.deleteProperty(options, it));
37
+ }
38
+ try {
39
+ options = await (0, _transform.transform)((0, _preflight.preflight)(options));
40
+ } catch (ex) {
41
+ options.createConnection?.().destroy();
42
+ throw ex;
43
+ }
44
+ const promise = new Promise((resolve, reject) => {
45
+ let client, req;
46
+ if (options.h2) {
47
+ client = _nodeHttp2.default.connect(url.origin, options);
48
+ req = client.request(options.headers, options);
49
+ } else {
50
+ const {
51
+ request
52
+ } = url.protocol === 'http:' ? _nodeHttp.default : _nodeHttps.default;
53
+ req = request(url, options);
54
+ }
55
+ (0, _utils.affix)(client, req, options);
56
+ req.once('error', reject);
57
+ req.once('frameError', reject);
58
+ req.once('goaway', reject);
59
+ req.once('response', res => (0, _postflight.postflight)(req, res, options, {
60
+ reject,
61
+ resolve
62
+ }));
63
+ (0, _utils.dispatch)(options, req);
64
+ });
65
+ try {
66
+ const res = await promise;
67
+ if (digest && !redirected) {
68
+ res.body = await res.body();
69
+ }
70
+ return res;
71
+ } catch (ex) {
72
+ const {
73
+ maxRetryAfter,
74
+ retry
75
+ } = options;
76
+ if (retry?.attempts && retry?.statusCodes.includes(ex.statusCode)) {
77
+ let {
78
+ interval
79
+ } = retry;
80
+ if (retry.retryAfter && ex.headers[HTTP2_HEADER_RETRY_AFTER]) {
81
+ interval = ex.headers[HTTP2_HEADER_RETRY_AFTER];
82
+ interval = Number(interval) * 1000 || new Date(interval) - Date.now();
83
+ if (interval > maxRetryAfter) {
84
+ throw (0, _utils.maxRetryAfterError)(interval, {
85
+ cause: ex
86
+ });
87
+ }
88
+ } else {
89
+ interval = new Function('interval', `return Math.ceil(${retry.backoffStrategy});`)(interval);
90
+ }
91
+ retry.attempts--;
92
+ retry.interval = interval;
93
+ return (0, _promises.setTimeout)(interval).then(() => overact(url, options));
94
+ }
95
+ if (digest && !redirected && ex.body) {
96
+ ex.body = await ex.body();
97
+ }
98
+ if (!thenable) {
99
+ throw ex;
100
+ } else {
101
+ return ex;
102
+ }
103
+ }
104
+ };
105
+ exports.transfer = transfer;
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.transform = void 0;
5
+ var _nodeHttp = _interopRequireDefault(require("node:http2"));
6
+ var _nodeStream = require("node:stream");
7
+ var _consumers = require("node:stream/consumers");
8
+ var _nodeUtil = require("node:util");
9
+ var _file = require("./file");
10
+ var _formdata = require("./formdata");
11
+ var _mediatypes = require("./mediatypes");
12
+ var _utils = require("./utils");
13
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
+ const {
15
+ HTTP2_HEADER_CONTENT_ENCODING,
16
+ HTTP2_HEADER_CONTENT_LENGTH,
17
+ HTTP2_HEADER_CONTENT_TYPE
18
+ } = _nodeHttp.default.constants;
19
+ const transform = async options => {
20
+ let {
21
+ body,
22
+ headers
23
+ } = options;
24
+ if (!body) {
25
+ return options;
26
+ }
27
+ if (_file.File.alike(body)) {
28
+ headers = {
29
+ [HTTP2_HEADER_CONTENT_LENGTH]: body.size,
30
+ [HTTP2_HEADER_CONTENT_TYPE]: body.type || _mediatypes.APPLICATION_OCTET_STREAM
31
+ };
32
+ body = body.stream();
33
+ } else if (_formdata.FormData.alike(body)) {
34
+ body = _formdata.FormData.actuate(body);
35
+ headers = {
36
+ [HTTP2_HEADER_CONTENT_TYPE]: body.contentType
37
+ };
38
+ } else if (!Buffer.isBuffer(body)) {
39
+ if (_nodeUtil.types.isAnyArrayBuffer(body)) {
40
+ body = Buffer.from(body);
41
+ } else if (_nodeUtil.types.isArrayBufferView(body)) {
42
+ body = Buffer.from(body.buffer, body.byteOffset, body.byteLength);
43
+ } else if (body === Object(body) && !Reflect.has(body, Symbol.asyncIterator)) {
44
+ if (body.constructor === URLSearchParams) {
45
+ headers = {
46
+ [HTTP2_HEADER_CONTENT_TYPE]: _mediatypes.APPLICATION_FORM_URLENCODED
47
+ };
48
+ body = body.toString();
49
+ } else if (!(!Array.isArray(body) && Reflect.has(body, Symbol.iterator))) {
50
+ headers = {
51
+ [HTTP2_HEADER_CONTENT_TYPE]: _mediatypes.APPLICATION_JSON
52
+ };
53
+ body = JSON.stringify(body);
54
+ }
55
+ }
56
+ }
57
+ const encodings = options.headers[HTTP2_HEADER_CONTENT_ENCODING];
58
+ if (body === Object(body) && (Reflect.has(body, Symbol.asyncIterator) || !Array.isArray(body) && Reflect.has(body, Symbol.iterator))) {
59
+ body = encodings ? (0, _utils.compress)(_nodeStream.Readable.from(body), encodings) : _nodeStream.Readable.from(body);
60
+ } else if (encodings) {
61
+ body = await (0, _consumers.buffer)((0, _utils.compress)(_nodeStream.Readable.from(body), encodings));
62
+ }
63
+ Object.assign(options.headers, {
64
+ ...headers,
65
+ ...(!body[Symbol.asyncIterator] && {
66
+ [HTTP2_HEADER_CONTENT_LENGTH]: Buffer.byteLength(body)
67
+ }),
68
+ ...(options.headers[HTTP2_HEADER_CONTENT_TYPE] && {
69
+ [HTTP2_HEADER_CONTENT_TYPE]: options.headers[HTTP2_HEADER_CONTENT_TYPE]
70
+ })
71
+ });
72
+ return {
73
+ ...options,
74
+ body
75
+ };
76
+ };
77
+ exports.transform = transform;
package/dist/utils.js CHANGED
@@ -3,31 +3,17 @@
3
3
  exports.__esModule = true;
4
4
  exports.sameOrigin = exports.normalize = exports.merge = exports.maxRetryAfterError = exports.maxRetryAfter = exports.dispatch = exports.decompress = exports.compress = exports.brandCheck = exports.affix = exports.admix = void 0;
5
5
  exports.tap = tap;
6
- exports.unwind = exports.transform = exports.transfer = void 0;
7
- var _nodeHttp = _interopRequireDefault(require("node:http"));
8
- var _nodeHttp2 = _interopRequireDefault(require("node:http2"));
9
- var _nodeHttps = _interopRequireDefault(require("node:https"));
6
+ exports.unwind = exports.toCamelCase = void 0;
7
+ var _nodeHttp = _interopRequireDefault(require("node:http2"));
10
8
  var _nodeStream = require("node:stream");
11
- var _consumers = require("node:stream/consumers");
12
- var _promises = require("node:timers/promises");
13
- var _nodeUtil = require("node:util");
14
9
  var _nodeZlib = _interopRequireDefault(require("node:zlib"));
15
- var _ackn = require("./ackn");
16
10
  var _defaults = _interopRequireDefault(require("./defaults"));
17
11
  var _errors = require("./errors");
18
- var _file = require("./file");
19
- var _formdata = require("./formdata");
20
- var _mediatypes = require("./mediatypes");
21
- var _postflight = require("./postflight");
22
- var _preflight = require("./preflight");
23
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24
13
  const {
25
- HTTP2_HEADER_CONTENT_ENCODING,
26
- HTTP2_HEADER_CONTENT_LENGTH,
27
- HTTP2_HEADER_CONTENT_TYPE,
28
14
  HTTP2_HEADER_RETRY_AFTER,
29
15
  HTTP2_HEADER_STATUS
30
- } = _nodeHttp2.default.constants;
16
+ } = _nodeHttp.default.constants;
31
17
  const admix = (res, headers, options) => {
32
18
  const {
33
19
  h2
@@ -154,6 +140,9 @@ const normalize = (url, options = {}) => {
154
140
  if (options.trimTrailingSlashes) {
155
141
  url = `${url}`.replace(/(?<!:)\/+/g, '/');
156
142
  }
143
+ if (options.stripTrailingSlash) {
144
+ url = `${url}`.replace(/\/$|\/(?=#)|\/(?=\?)/g, '');
145
+ }
157
146
  url = new URL(url, options.baseURL);
158
147
  return Object.assign(options, {
159
148
  url
@@ -171,151 +160,7 @@ async function* tap(value) {
171
160
  yield await value.arrayBuffer();
172
161
  }
173
162
  }
174
- const transfer = async (options, overact) => {
175
- const {
176
- digest,
177
- redirected,
178
- thenable,
179
- url
180
- } = options;
181
- if (options.follow === 0) {
182
- throw new _errors.RequestError(`Maximum redirect reached at: ${url.href}`);
183
- }
184
- if (url.protocol === 'https:') {
185
- options = !options.h2 ? await (0, _ackn.ackn)(options) : {
186
- ...options,
187
- createConnection: null,
188
- protocol: url.protocol
189
- };
190
- } else if (Reflect.has(options, 'alpnProtocol')) {
191
- ['alpnProtocol', 'createConnection', 'h2', 'protocol'].forEach(it => Reflect.deleteProperty(options, it));
192
- }
193
- try {
194
- options = await transform((0, _preflight.preflight)(options));
195
- } catch (ex) {
196
- options.createConnection?.().destroy();
197
- throw ex;
198
- }
199
- const promise = new Promise((resolve, reject) => {
200
- let client, req;
201
- if (options.h2) {
202
- client = _nodeHttp2.default.connect(url.origin, options);
203
- req = client.request(options.headers, options);
204
- } else {
205
- const {
206
- request
207
- } = url.protocol === 'http:' ? _nodeHttp.default : _nodeHttps.default;
208
- req = request(url, options);
209
- }
210
- affix(client, req, options);
211
- req.once('error', reject);
212
- req.once('frameError', reject);
213
- req.once('goaway', reject);
214
- req.once('response', res => (0, _postflight.postflight)(req, res, options, {
215
- reject,
216
- resolve
217
- }));
218
- dispatch(options, req);
219
- });
220
- try {
221
- const res = await promise;
222
- if (digest && !redirected) {
223
- res.body = await res.body();
224
- }
225
- return res;
226
- } catch (ex) {
227
- const {
228
- maxRetryAfter,
229
- retry
230
- } = options;
231
- if (retry?.attempts && retry?.statusCodes.includes(ex.statusCode)) {
232
- let {
233
- interval
234
- } = retry;
235
- if (retry.retryAfter && ex.headers[HTTP2_HEADER_RETRY_AFTER]) {
236
- interval = ex.headers[HTTP2_HEADER_RETRY_AFTER];
237
- interval = Number(interval) * 1000 || new Date(interval) - Date.now();
238
- if (interval > maxRetryAfter) {
239
- throw maxRetryAfterError(interval, {
240
- cause: ex
241
- });
242
- }
243
- } else {
244
- interval = new Function('interval', `return Math.ceil(${retry.backoffStrategy});`)(interval);
245
- }
246
- retry.attempts--;
247
- retry.interval = interval;
248
- return (0, _promises.setTimeout)(interval).then(() => overact(url, options));
249
- }
250
- if (digest && !redirected && ex.body) {
251
- ex.body = await ex.body();
252
- }
253
- if (!thenable) {
254
- throw ex;
255
- } else {
256
- return ex;
257
- }
258
- }
259
- };
260
- exports.transfer = transfer;
261
- const transform = async options => {
262
- let {
263
- body,
264
- headers
265
- } = options;
266
- if (!body) {
267
- return options;
268
- }
269
- if (_file.File.alike(body)) {
270
- headers = {
271
- [HTTP2_HEADER_CONTENT_LENGTH]: body.size,
272
- [HTTP2_HEADER_CONTENT_TYPE]: body.type || _mediatypes.APPLICATION_OCTET_STREAM
273
- };
274
- body = body.stream();
275
- } else if (_formdata.FormData.alike(body)) {
276
- body = _formdata.FormData.actuate(body);
277
- headers = {
278
- [HTTP2_HEADER_CONTENT_TYPE]: body.contentType
279
- };
280
- } else if (!Buffer.isBuffer(body)) {
281
- if (_nodeUtil.types.isAnyArrayBuffer(body)) {
282
- body = Buffer.from(body);
283
- } else if (_nodeUtil.types.isArrayBufferView(body)) {
284
- body = Buffer.from(body.buffer, body.byteOffset, body.byteLength);
285
- } else if (body === Object(body) && !Reflect.has(body, Symbol.asyncIterator)) {
286
- if (body.constructor === URLSearchParams) {
287
- headers = {
288
- [HTTP2_HEADER_CONTENT_TYPE]: _mediatypes.APPLICATION_FORM_URLENCODED
289
- };
290
- body = body.toString();
291
- } else if (!(!Array.isArray(body) && Reflect.has(body, Symbol.iterator))) {
292
- headers = {
293
- [HTTP2_HEADER_CONTENT_TYPE]: _mediatypes.APPLICATION_JSON
294
- };
295
- body = JSON.stringify(body);
296
- }
297
- }
298
- }
299
- const encodings = options.headers[HTTP2_HEADER_CONTENT_ENCODING];
300
- if (body === Object(body) && (Reflect.has(body, Symbol.asyncIterator) || !Array.isArray(body) && Reflect.has(body, Symbol.iterator))) {
301
- body = encodings ? compress(_nodeStream.Readable.from(body), encodings) : _nodeStream.Readable.from(body);
302
- } else if (encodings) {
303
- body = await (0, _consumers.buffer)(compress(_nodeStream.Readable.from(body), encodings));
304
- }
305
- Object.assign(options.headers, {
306
- ...headers,
307
- ...(!body[Symbol.asyncIterator] && {
308
- [HTTP2_HEADER_CONTENT_LENGTH]: Buffer.byteLength(body)
309
- }),
310
- ...(options.headers[HTTP2_HEADER_CONTENT_TYPE] && {
311
- [HTTP2_HEADER_CONTENT_TYPE]: options.headers[HTTP2_HEADER_CONTENT_TYPE]
312
- })
313
- });
314
- return {
315
- ...options,
316
- body
317
- };
318
- };
319
- exports.transform = transform;
163
+ const toCamelCase = str => str?.toLowerCase().replace(/\p{Punctuation}.|\p{White_Space}./gu, val => val.replace(/\p{Punctuation}+|\p{White_Space}+/gu, '').toUpperCase());
164
+ exports.toCamelCase = toCamelCase;
320
165
  const unwind = encodings => encodings.split(',').map(it => it.trim());
321
166
  exports.unwind = unwind;
package/package.json CHANGED
@@ -11,10 +11,10 @@
11
11
  "@babel/cli": "^7.21.5",
12
12
  "@babel/core": "^7.22.1",
13
13
  "@babel/eslint-parser": "^7.21.8",
14
- "@babel/preset-env": "^7.22.2",
15
- "c8": "^7.13.0",
14
+ "@babel/preset-env": "^7.22.4",
15
+ "c8": "^7.14.0",
16
16
  "eslint": "^8.41.0",
17
- "eslint-config-ultra-refined": "^2.14.0",
17
+ "eslint-config-ultra-refined": "^2.15.0",
18
18
  "mocha": "^10.2.0"
19
19
  },
20
20
  "description": "The robust request library that humanity deserves 🌐",
@@ -67,5 +67,5 @@
67
67
  "test:bail": "mocha --bail",
68
68
  "test:cover": "c8 --include=src --reporter=lcov --reporter=text npm test"
69
69
  },
70
- "version": "4.4.4"
70
+ "version": "4.5.0"
71
71
  }