rekwest 7.0.3 → 7.1.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
@@ -140,6 +140,7 @@ console.log(res.body);
140
140
  * `h2` **{boolean}** `Default: false` Forces the use of HTTP/2 protocol
141
141
  * `headers` **{Object}** The headers to add to the request
142
142
  * `maxRetryAfter` **{number}** The upper limit of `retry-after` header. If unset, it will use `timeout` value
143
+ * `params` **{Object}** The search params to add to the `url`
143
144
  * `parse` **{boolean}** `Default: true` Controls whether to parse response body or return a buffer
144
145
  * `redirect` **{error | follow | manual}** `Default: follow` Controls the redirect flows
145
146
  * `retry` **{Object}** Represents the retry options
package/dist/ackn.cjs CHANGED
@@ -13,7 +13,7 @@ const ackn = options => new Promise((resolve, reject) => {
13
13
  ...options,
14
14
  ALPNProtocols: ['h2', 'http/1.1'],
15
15
  host: url.hostname,
16
- port: parseInt(url.port) || 443,
16
+ port: parseInt(url.port, 10) || 443,
17
17
  servername: url.hostname
18
18
  }, () => {
19
19
  socket.off('error', reject);
package/dist/cookies.cjs CHANGED
@@ -10,12 +10,12 @@ const lifetimeCap = 3456e7; // pragma: 400 days
10
10
  class Cookies extends URLSearchParams {
11
11
  static #finalizers = new Set();
12
12
  static jar = new Map();
13
- static #register(target, value) {
14
- const finalizer = new FinalizationRegistry(heldValue => {
15
- clearTimeout(heldValue);
13
+ static #register(target, val) {
14
+ const finalizer = new FinalizationRegistry(heldVal => {
15
+ clearTimeout(heldVal);
16
16
  this.#finalizers.delete(finalizer);
17
17
  });
18
- finalizer.register(target, value);
18
+ finalizer.register(target, val);
19
19
  this.#finalizers.add(finalizer);
20
20
  }
21
21
  #chronometry = new Map();
@@ -34,10 +34,10 @@ class Cookies extends URLSearchParams {
34
34
  }
35
35
  const [cookie, ...attrs] = it.split(';').map(it => it.trim());
36
36
  const ttl = {};
37
- for (const val of attrs) {
38
- if (/(?:expires|max-age)=/i.test(val)) {
39
- const [key, value] = val.toLowerCase().split('=');
40
- const ms = Number.isFinite(Number(value)) ? value * 1e3 : Date.parse(value) - Date.now();
37
+ for (const attr of attrs) {
38
+ if (/(?:expires|max-age)=/i.test(attr)) {
39
+ const [key, val] = attr.toLowerCase().split('=');
40
+ const ms = Number.isFinite(Number(val)) ? val * 1e3 : Date.parse(val) - Date.now();
41
41
  ttl[(0, _utils.toCamelCase)(key)] = Math.min(ms, lifetimeCap);
42
42
  }
43
43
  }
package/dist/formdata.cjs CHANGED
@@ -27,12 +27,12 @@ class FormData {
27
27
  contentType,
28
28
  async *[Symbol.asyncIterator]() {
29
29
  const encoder = new TextEncoder();
30
- for (const [name, value] of fd) {
31
- if (value.constructor === String) {
32
- yield encoder.encode(`${prefix}; name="${escape(redress(name))}"${CRLF.repeat(2)}${redress(value)}${CRLF}`);
30
+ for (const [name, val] of fd) {
31
+ if (val.constructor === String) {
32
+ yield encoder.encode(`${prefix}; name="${escape(redress(name))}"${CRLF.repeat(2)}${redress(val)}${CRLF}`);
33
33
  } else {
34
- yield encoder.encode(`${prefix}; name="${escape(redress(name))}"${value.name ? `; filename="${escape(value.name)}"` : ''}${CRLF}${HTTP2_HEADER_CONTENT_TYPE}: ${value.type || _mediatypes.APPLICATION_OCTET_STREAM}${CRLF.repeat(2)}`);
35
- yield* (0, _utils.tap)(value);
34
+ yield encoder.encode(`${prefix}; name="${escape(redress(name))}"${val.name ? `; filename="${escape(val.name)}"` : ''}${CRLF}${HTTP2_HEADER_CONTENT_TYPE}: ${val.type || _mediatypes.APPLICATION_OCTET_STREAM}${CRLF.repeat(2)}`);
35
+ yield* (0, _utils.tap)(val);
36
36
  yield new Uint8Array([13, 10]);
37
37
  }
38
38
  }
@@ -40,8 +40,8 @@ class FormData {
40
40
  }
41
41
  };
42
42
  }
43
- static alike(value) {
44
- return FormData.name === value?.[Symbol.toStringTag];
43
+ static alike(val) {
44
+ return FormData.name === val?.[Symbol.toStringTag];
45
45
  }
46
46
  static #enfoldEntry(name, value, filename) {
47
47
  name = (0, _nodeUtil.toUSVString)(name);
@@ -59,8 +59,8 @@ class FormData {
59
59
  value
60
60
  };
61
61
  }
62
- static #ensureInstance(value) {
63
- return (0, _utils.isFileLike)(value) || Object(value) === value && Reflect.has(value, Symbol.asyncIterator);
62
+ static #ensureInstance(val) {
63
+ return (0, _utils.isFileLike)(val) || Object(val) === val && Reflect.has(val, Symbol.asyncIterator);
64
64
  }
65
65
  #entries = [];
66
66
  get [Symbol.toStringTag]() {
@@ -78,8 +78,8 @@ class FormData {
78
78
  } else if (!Reflect.has(input, Symbol.iterator)) {
79
79
  input = Object.entries(input);
80
80
  }
81
- for (const [key, value] of input) {
82
- this.append(key, value);
81
+ for (const [key, val] of input) {
82
+ this.append(key, val);
83
83
  }
84
84
  }
85
85
  }
@@ -163,8 +163,8 @@ class FormData {
163
163
  }
164
164
  *values() {
165
165
  (0, _utils.brandCheck)(this, FormData);
166
- for (const [, value] of this) {
167
- yield value;
166
+ for (const [, val] of this) {
167
+ yield val;
168
168
  }
169
169
  }
170
170
  [Symbol.iterator]() {
package/dist/index.cjs CHANGED
@@ -160,20 +160,20 @@ Reflect.defineProperty(rekwest, 'defaults', {
160
160
  get() {
161
161
  return _config.default.defaults;
162
162
  },
163
- set(value) {
164
- _config.default.defaults = (0, _utils.copyWithMerge)(_config.default.defaults, value);
163
+ set(val) {
164
+ _config.default.defaults = (0, _utils.cloneWith)(_config.default.defaults, val);
165
165
  }
166
166
  });
167
167
  Reflect.defineProperty(rekwest, 'extend', {
168
168
  enumerable: true,
169
169
  value(options) {
170
- return (url, opts) => rekwest(url, (0, _utils.copyWithMerge)(options, opts));
170
+ return (url, opts) => rekwest(url, (0, _utils.cloneWith)(options, opts));
171
171
  }
172
172
  });
173
173
  Reflect.defineProperty(rekwest, 'stream', {
174
174
  enumerable: true,
175
175
  value(url, options) {
176
- options = (0, _preflight.preflight)((0, _validation.validation)((0, _utils.normalize)(url, (0, _utils.copyWithMerge)({}, options, {
176
+ options = (0, _preflight.preflight)((0, _validation.validation)((0, _utils.normalize)(url, (0, _utils.cloneWith)({}, options, {
177
177
  headers: {
178
178
  [HTTP2_HEADER_CONTENT_TYPE]: _mediatypes2.APPLICATION_OCTET_STREAM
179
179
  },
package/dist/retries.cjs CHANGED
@@ -16,7 +16,7 @@ const {
16
16
  HTTP2_METHOD_GET,
17
17
  HTTP2_METHOD_HEAD
18
18
  } = _nodeHttp.default.constants;
19
- const retries = (ex, options) => {
19
+ const retries = (err, options) => {
20
20
  const {
21
21
  body,
22
22
  maxRetryAfter,
@@ -27,19 +27,19 @@ const retries = (ex, options) => {
27
27
  if (retry?.attempts > 0) {
28
28
  if (![HTTP2_METHOD_GET, HTTP2_METHOD_HEAD].includes(method) && (0, _utils.isPipeStream)(body) && !(0, _nodeStream.isReadable)(body)) {
29
29
  throw new _errors.RequestError('Request stream already read.', {
30
- cause: ex
30
+ cause: err
31
31
  });
32
32
  }
33
- if (retry.errorCodes?.includes(ex.code) || retry.statusCodes?.includes(ex.statusCode)) {
33
+ if (retry.errorCodes?.includes(err.code) || retry.statusCodes?.includes(err.statusCode)) {
34
34
  let {
35
35
  interval
36
36
  } = retry;
37
- if (retry.retryAfter && ex.headers?.[HTTP2_HEADER_RETRY_AFTER]) {
38
- interval = ex.headers[HTTP2_HEADER_RETRY_AFTER];
37
+ if (retry.retryAfter && err.headers?.[HTTP2_HEADER_RETRY_AFTER]) {
38
+ interval = err.headers[HTTP2_HEADER_RETRY_AFTER];
39
39
  interval = Math.abs(Number(interval) * 1e3 || new Date(interval) - Date.now()) || 0;
40
40
  if (interval > maxRetryAfter) {
41
41
  throw new _errors.RequestError(`Maximum '${HTTP2_HEADER_RETRY_AFTER}' limit exceeded: ${interval} ms.`, {
42
- cause: ex
42
+ cause: err
43
43
  });
44
44
  }
45
45
  } else {
package/dist/transfer.cjs CHANGED
@@ -38,9 +38,9 @@ const transfer = async options => {
38
38
  }
39
39
  try {
40
40
  options = await (0, _transform.transform)((0, _preflight.preflight)(options));
41
- } catch (ex) {
41
+ } catch (err) {
42
42
  options.createConnection?.().destroy();
43
- throw ex;
43
+ throw err;
44
44
  }
45
45
  const promise = new Promise((resolve, reject) => {
46
46
  let client, req;
@@ -70,18 +70,18 @@ const transfer = async options => {
70
70
  res.body = await res.body();
71
71
  }
72
72
  return res;
73
- } catch (ex) {
74
- const result = (0, _retries.retries)(ex, options);
73
+ } catch (err) {
74
+ const result = (0, _retries.retries)(err, options);
75
75
  if (result) {
76
76
  return result;
77
77
  }
78
- if (digest && !redirected && ex.body) {
79
- ex.body = await ex.body();
78
+ if (digest && !redirected && err.body) {
79
+ err.body = await err.body();
80
80
  }
81
81
  if (!thenable) {
82
- throw ex;
82
+ throw err;
83
83
  } else {
84
- return ex;
84
+ return err;
85
85
  }
86
86
  }
87
87
  };
package/dist/utils.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.stripHeaders = exports.snoop = exports.sameOrigin = exports.normalizeHeaders = exports.normalize = exports.merge = exports.isReadableStream = exports.isPipeStream = exports.isFileLike = exports.dispatch = exports.copyWithMerge = exports.brandCheck = exports.augment = void 0;
6
+ exports.stripHeaders = exports.snoop = exports.sameOrigin = exports.normalizeHeaders = exports.normalize = exports.isReadableStream = exports.isPipeStream = exports.isFileLike = exports.dispatch = exports.deepMerge = exports.cloneWith = exports.brandCheck = exports.augment = exports.addSearchParams = void 0;
7
7
  exports.tap = tap;
8
8
  exports.unwind = exports.toCamelCase = void 0;
9
9
  var _nodeBuffer = require("node:buffer");
@@ -17,6 +17,19 @@ const {
17
17
  HTTP2_HEADER_ACCEPT_ENCODING,
18
18
  HTTP2_HEADER_STATUS
19
19
  } = _nodeHttp.default.constants;
20
+ const addSearchParams = (url, params = {}) => {
21
+ for (const [key, val] of Object.entries(params)) {
22
+ if (Array.isArray(val)) {
23
+ for (const v of val) {
24
+ url.searchParams.append(key, v);
25
+ }
26
+ } else {
27
+ url.searchParams.set(key, val);
28
+ }
29
+ }
30
+ return url;
31
+ };
32
+ exports.addSearchParams = addSearchParams;
20
33
  const augment = (res, headers, options) => {
21
34
  const {
22
35
  h2
@@ -45,20 +58,36 @@ const augment = (res, headers, options) => {
45
58
  });
46
59
  };
47
60
  exports.augment = augment;
48
- const brandCheck = (value, ctor) => {
49
- if (!(value instanceof ctor)) {
61
+ const brandCheck = (val, ctor) => {
62
+ if (!(val instanceof ctor)) {
50
63
  throw new TypeError('Illegal invocation.');
51
64
  }
52
65
  };
53
66
  exports.brandCheck = brandCheck;
54
- const copyWithMerge = (target, ...rest) => {
67
+ const cloneWith = (target, ...rest) => {
55
68
  target = structuredClone(target);
56
69
  if (!rest.length) {
57
70
  return target;
58
71
  }
59
- return merge(target, ...rest);
72
+ return deepMerge(target, ...rest);
73
+ };
74
+ exports.cloneWith = cloneWith;
75
+ const deepMerge = (target, ...rest) => {
76
+ rest = rest.filter(it => Object(it) === it);
77
+ for (const source of rest) {
78
+ for (const key of Object.getOwnPropertyNames(source)) {
79
+ const sv = source[key];
80
+ const tv = target[key];
81
+ if (Object(sv) === sv && Object(tv) === tv) {
82
+ target[key] = deepMerge(tv, sv);
83
+ continue;
84
+ }
85
+ target[key] = source[key];
86
+ }
87
+ }
88
+ return target;
60
89
  };
61
- exports.copyWithMerge = copyWithMerge;
90
+ exports.deepMerge = deepMerge;
62
91
  const dispatch = (req, {
63
92
  body
64
93
  }) => {
@@ -69,37 +98,21 @@ const dispatch = (req, {
69
98
  }
70
99
  };
71
100
  exports.dispatch = dispatch;
72
- const isFileLike = value => {
73
- return [_nodeBuffer.Blob, _nodeBuffer.File].some(it => value instanceof it);
101
+ const isFileLike = val => {
102
+ return [_nodeBuffer.Blob, _nodeBuffer.File].some(it => val instanceof it);
74
103
  };
75
104
  exports.isFileLike = isFileLike;
76
- const isPipeStream = value => {
77
- return value instanceof _nodeStream.Readable;
105
+ const isPipeStream = val => {
106
+ return val instanceof _nodeStream.Readable;
78
107
  };
79
108
  exports.isPipeStream = isPipeStream;
80
- const isReadableStream = value => {
81
- return value instanceof ReadableStream;
109
+ const isReadableStream = val => {
110
+ return val instanceof ReadableStream;
82
111
  };
83
112
  exports.isReadableStream = isReadableStream;
84
- const merge = (target, ...rest) => {
85
- rest = rest.filter(it => Object(it) === it);
86
- for (const source of rest) {
87
- for (const key of Object.getOwnPropertyNames(source)) {
88
- const sv = source[key];
89
- const tv = target[key];
90
- if (Object(sv) === sv && Object(tv) === tv) {
91
- target[key] = merge(tv, sv);
92
- continue;
93
- }
94
- target[key] = source[key];
95
- }
96
- }
97
- return target;
98
- };
99
- exports.merge = merge;
100
113
  const normalize = (url, options = {}) => {
101
114
  if (!options.redirected) {
102
- options = copyWithMerge(_config.default.defaults, options);
115
+ options = cloneWith(_config.default.defaults, options);
103
116
  }
104
117
  if (options.trimTrailingSlashes) {
105
118
  url = `${url}`.replace(/(?<!:)\/+/g, '/');
@@ -110,25 +123,25 @@ const normalize = (url, options = {}) => {
110
123
  return Object.assign(options, {
111
124
  headers: normalizeHeaders(options.headers),
112
125
  method: options.method.toUpperCase(),
113
- url: new URL(url, options.baseURL)
126
+ url: addSearchParams(new URL(url, options.baseURL), options.params)
114
127
  });
115
128
  };
116
129
  exports.normalize = normalize;
117
130
  const normalizeHeaders = headers => {
118
- const collector = {};
119
- for (const [key, value] of Object.entries(headers ?? {})) {
131
+ const acc = {};
132
+ for (const [key, val] of Object.entries(headers ?? {})) {
120
133
  const name = key.toLowerCase();
121
- collector[key] = value;
134
+ acc[key] = val;
122
135
  if (key === HTTP2_HEADER_ACCEPT_ENCODING && !_config.isZstdSupported) {
123
- const stripped = value.replace(/\s?zstd,?/gi, '').trim();
136
+ const stripped = val.replace(/\s?zstd,?/gi, '').trim();
124
137
  if (stripped) {
125
- collector[key] = stripped;
138
+ acc[key] = stripped;
126
139
  } else {
127
- Reflect.deleteProperty(collector, name);
140
+ Reflect.deleteProperty(acc, name);
128
141
  }
129
142
  }
130
143
  }
131
- return collector;
144
+ return acc;
132
145
  };
133
146
  exports.normalizeHeaders = normalizeHeaders;
134
147
  const sameOrigin = (a, b) => a.protocol === b.protocol && a.hostname === b.hostname && a.port === b.port;
@@ -150,13 +163,13 @@ const stripHeaders = (headers = {}, names = []) => {
150
163
  return Object.fromEntries(Object.entries(headers).filter(([key]) => !names.has(key.toLowerCase())));
151
164
  };
152
165
  exports.stripHeaders = stripHeaders;
153
- async function* tap(value) {
154
- if (Reflect.has(value, Symbol.asyncIterator)) {
155
- yield* value;
156
- } else if (value.stream) {
157
- yield* value.stream();
166
+ async function* tap(val) {
167
+ if (Reflect.has(val, Symbol.asyncIterator)) {
168
+ yield* val;
169
+ } else if (val.stream) {
170
+ yield* val.stream();
158
171
  } else {
159
- yield await value.arrayBuffer();
172
+ yield await val.arrayBuffer();
160
173
  }
161
174
  }
162
175
  const toCamelCase = str => str?.toLowerCase().replace(/\p{Punctuation}.|\p{White_Space}./gu, val => val.replace(/\p{Punctuation}+|\p{White_Space}+/gu, '').toUpperCase());
package/package.json CHANGED
@@ -11,11 +11,10 @@
11
11
  "devDependencies": {
12
12
  "@babel/cli": "^7.28.6",
13
13
  "@babel/core": "^7.29.0",
14
- "@babel/eslint-parser": "^7.28.6",
15
14
  "@babel/preset-env": "^7.29.0",
16
15
  "c8": "^10.1.3",
17
- "eslint": "^9.39.2",
18
- "eslint-config-ultra-refined": "^3.8.5",
16
+ "eslint": "^10.0.0",
17
+ "eslint-config-ultra-refined": "^4.0.1",
19
18
  "mocha": "^11.7.5"
20
19
  },
21
20
  "engines": {
@@ -72,5 +71,5 @@
72
71
  "test:cover": "c8 --include=src --reporter=lcov --reporter=text npm test"
73
72
  },
74
73
  "type": "module",
75
- "version": "7.0.3"
74
+ "version": "7.1.0"
76
75
  }
package/src/ackn.js CHANGED
@@ -9,7 +9,7 @@ export const ackn = (options) => new Promise((resolve, reject) => {
9
9
  'http/1.1',
10
10
  ],
11
11
  host: url.hostname,
12
- port: parseInt(url.port) || 443,
12
+ port: parseInt(url.port, 10) || 443,
13
13
  servername: url.hostname,
14
14
  }, () => {
15
15
  socket.off('error', reject);
package/src/cookies.js CHANGED
@@ -10,13 +10,13 @@ export class Cookies extends URLSearchParams {
10
10
  static #finalizers = new Set();
11
11
  static jar = new Map();
12
12
 
13
- static #register(target, value) {
14
- const finalizer = new FinalizationRegistry((heldValue) => {
15
- clearTimeout(heldValue);
13
+ static #register(target, val) {
14
+ const finalizer = new FinalizationRegistry((heldVal) => {
15
+ clearTimeout(heldVal);
16
16
  this.#finalizers.delete(finalizer);
17
17
  });
18
18
 
19
- finalizer.register(target, value);
19
+ finalizer.register(target, val);
20
20
  this.#finalizers.add(finalizer);
21
21
  }
22
22
 
@@ -36,10 +36,10 @@ export class Cookies extends URLSearchParams {
36
36
  const [cookie, ...attrs] = it.split(';').map((it) => it.trim());
37
37
  const ttl = {};
38
38
 
39
- for (const val of attrs) {
40
- if (/(?:expires|max-age)=/i.test(val)) {
41
- const [key, value] = val.toLowerCase().split('=');
42
- const ms = Number.isFinite(Number(value)) ? value * 1e3 : Date.parse(value) - Date.now();
39
+ for (const attr of attrs) {
40
+ if (/(?:expires|max-age)=/i.test(attr)) {
41
+ const [key, val] = attr.toLowerCase().split('=');
42
+ const ms = Number.isFinite(Number(val)) ? val * 1e3 : Date.parse(val) - Date.now();
43
43
 
44
44
  ttl[toCamelCase(key)] = Math.min(ms, lifetimeCap);
45
45
  }
package/src/formdata.js CHANGED
@@ -33,20 +33,20 @@ export class FormData {
33
33
  async* [Symbol.asyncIterator]() {
34
34
  const encoder = new TextEncoder();
35
35
 
36
- for (const [name, value] of fd) {
37
- if (value.constructor === String) {
36
+ for (const [name, val] of fd) {
37
+ if (val.constructor === String) {
38
38
  yield encoder.encode(`${ prefix }; name="${
39
39
  escape(redress(name))
40
- }"${ CRLF.repeat(2) }${ redress(value) }${ CRLF }`);
40
+ }"${ CRLF.repeat(2) }${ redress(val) }${ CRLF }`);
41
41
  } else {
42
42
  yield encoder.encode(`${ prefix }; name="${
43
43
  escape(redress(name))
44
- }"${ value.name ? `; filename="${ escape(value.name) }"` : '' }${ CRLF }${
44
+ }"${ val.name ? `; filename="${ escape(val.name) }"` : '' }${ CRLF }${
45
45
  HTTP2_HEADER_CONTENT_TYPE
46
46
  }: ${
47
- value.type || APPLICATION_OCTET_STREAM
47
+ val.type || APPLICATION_OCTET_STREAM
48
48
  }${ CRLF.repeat(2) }`);
49
- yield* tap(value);
49
+ yield* tap(val);
50
50
  yield new Uint8Array([
51
51
  13,
52
52
  10,
@@ -59,8 +59,8 @@ export class FormData {
59
59
  };
60
60
  }
61
61
 
62
- static alike(value) {
63
- return FormData.name === value?.[Symbol.toStringTag];
62
+ static alike(val) {
63
+ return FormData.name === val?.[Symbol.toStringTag];
64
64
  }
65
65
 
66
66
  static #enfoldEntry(name, value, filename) {
@@ -82,8 +82,8 @@ export class FormData {
82
82
  };
83
83
  }
84
84
 
85
- static #ensureInstance(value) {
86
- return isFileLike(value) || (Object(value) === value && Reflect.has(value, Symbol.asyncIterator));
85
+ static #ensureInstance(val) {
86
+ return isFileLike(val) || (Object(val) === val && Reflect.has(val, Symbol.asyncIterator));
87
87
  }
88
88
 
89
89
  #entries = [];
@@ -110,8 +110,8 @@ export class FormData {
110
110
  input = Object.entries(input);
111
111
  }
112
112
 
113
- for (const [key, value] of input) {
114
- this.append(key, value);
113
+ for (const [key, val] of input) {
114
+ this.append(key, val);
115
115
  }
116
116
  }
117
117
  }
@@ -226,8 +226,8 @@ export class FormData {
226
226
 
227
227
  * values() {
228
228
  brandCheck(this, FormData);
229
- for (const [, value] of this) {
230
- yield value;
229
+ for (const [, val] of this) {
230
+ yield val;
231
231
  }
232
232
  }
233
233
 
package/src/index.js CHANGED
@@ -8,7 +8,7 @@ import { preflight } from './preflight.js';
8
8
  import { transfer } from './transfer.js';
9
9
  import {
10
10
  augment,
11
- copyWithMerge,
11
+ cloneWith,
12
12
  normalize,
13
13
  snoop,
14
14
  } from './utils.js';
@@ -41,20 +41,20 @@ export default function rekwest(url, options) {
41
41
  Reflect.defineProperty(rekwest, 'defaults', {
42
42
  enumerable: true,
43
43
  get() { return config.defaults; },
44
- set(value) { config.defaults = copyWithMerge(config.defaults, value); },
44
+ set(val) { config.defaults = cloneWith(config.defaults, val); },
45
45
  });
46
46
 
47
47
  Reflect.defineProperty(rekwest, 'extend', {
48
48
  enumerable: true,
49
49
  value(options) {
50
- return (url, opts) => rekwest(url, copyWithMerge(options, opts));
50
+ return (url, opts) => rekwest(url, cloneWith(options, opts));
51
51
  },
52
52
  });
53
53
 
54
54
  Reflect.defineProperty(rekwest, 'stream', {
55
55
  enumerable: true,
56
56
  value(url, options) {
57
- options = preflight(validation(normalize(url, copyWithMerge({}, options, {
57
+ options = preflight(validation(normalize(url, cloneWith({}, options, {
58
58
  headers: { [HTTP2_HEADER_CONTENT_TYPE]: APPLICATION_OCTET_STREAM },
59
59
  redirect: requestRedirect.manual,
60
60
  }))));
package/src/retries.js CHANGED
@@ -11,7 +11,7 @@ const {
11
11
  HTTP2_METHOD_HEAD,
12
12
  } = http2.constants;
13
13
 
14
- export const retries = (ex, options) => {
14
+ export const retries = (err, options) => {
15
15
  const { body, maxRetryAfter, method, retry, url } = options;
16
16
 
17
17
  if (retry?.attempts > 0) {
@@ -19,19 +19,19 @@ export const retries = (ex, options) => {
19
19
  HTTP2_METHOD_GET,
20
20
  HTTP2_METHOD_HEAD,
21
21
  ].includes(method) && isPipeStream(body) && !isReadable(body)) {
22
- throw new RequestError('Request stream already read.', { cause: ex });
22
+ throw new RequestError('Request stream already read.', { cause: err });
23
23
  }
24
24
 
25
- if (retry.errorCodes?.includes(ex.code) || retry.statusCodes?.includes(ex.statusCode)) {
25
+ if (retry.errorCodes?.includes(err.code) || retry.statusCodes?.includes(err.statusCode)) {
26
26
  let { interval } = retry;
27
27
 
28
- if (retry.retryAfter && ex.headers?.[HTTP2_HEADER_RETRY_AFTER]) {
29
- interval = ex.headers[HTTP2_HEADER_RETRY_AFTER];
28
+ if (retry.retryAfter && err.headers?.[HTTP2_HEADER_RETRY_AFTER]) {
29
+ interval = err.headers[HTTP2_HEADER_RETRY_AFTER];
30
30
  interval = Math.abs(Number(interval) * 1e3 || new Date(interval) - Date.now()) || 0;
31
31
  if (interval > maxRetryAfter) {
32
32
  throw new RequestError(
33
33
  `Maximum '${ HTTP2_HEADER_RETRY_AFTER }' limit exceeded: ${ interval } ms.`,
34
- { cause: ex },
34
+ { cause: err },
35
35
  );
36
36
  }
37
37
  } else {
package/src/transfer.js CHANGED
@@ -34,9 +34,9 @@ export const transfer = async (options) => {
34
34
 
35
35
  try {
36
36
  options = await transform(preflight(options));
37
- } catch (ex) {
37
+ } catch (err) {
38
38
  options.createConnection?.().destroy();
39
- throw ex;
39
+ throw err;
40
40
  }
41
41
 
42
42
  const promise = new Promise((resolve, reject) => {
@@ -72,21 +72,21 @@ export const transfer = async (options) => {
72
72
  }
73
73
 
74
74
  return res;
75
- } catch (ex) {
76
- const result = retries(ex, options);
75
+ } catch (err) {
76
+ const result = retries(err, options);
77
77
 
78
78
  if (result) {
79
79
  return result;
80
80
  }
81
81
 
82
- if (digest && !redirected && ex.body) {
83
- ex.body = await ex.body();
82
+ if (digest && !redirected && err.body) {
83
+ err.body = await err.body();
84
84
  }
85
85
 
86
86
  if (!thenable) {
87
- throw ex;
87
+ throw err;
88
88
  } else {
89
- return ex;
89
+ return err;
90
90
  }
91
91
  }
92
92
  };
package/src/utils.js CHANGED
@@ -15,6 +15,20 @@ const {
15
15
  HTTP2_HEADER_STATUS,
16
16
  } = http2.constants;
17
17
 
18
+ export const addSearchParams = (url, params = {}) => {
19
+ for (const [key, val] of Object.entries(params)) {
20
+ if (Array.isArray(val)) {
21
+ for (const v of val) {
22
+ url.searchParams.append(key, v);
23
+ }
24
+ } else {
25
+ url.searchParams.set(key, val);
26
+ }
27
+ }
28
+
29
+ return url;
30
+ };
31
+
18
32
  export const augment = (res, headers, options) => {
19
33
  const { h2 } = options;
20
34
 
@@ -46,45 +60,22 @@ export const augment = (res, headers, options) => {
46
60
  });
47
61
  };
48
62
 
49
- export const brandCheck = (value, ctor) => {
50
- if (!(value instanceof ctor)) {
63
+ export const brandCheck = (val, ctor) => {
64
+ if (!(val instanceof ctor)) {
51
65
  throw new TypeError('Illegal invocation.');
52
66
  }
53
67
  };
54
68
 
55
- export const copyWithMerge = (target, ...rest) => {
69
+ export const cloneWith = (target, ...rest) => {
56
70
  target = structuredClone(target);
57
71
  if (!rest.length) {
58
72
  return target;
59
73
  }
60
74
 
61
- return merge(target, ...rest);
62
- };
63
-
64
- export const dispatch = (req, { body }) => {
65
- if (isReadable(body)) {
66
- body.pipe(req);
67
- } else {
68
- req.end(body);
69
- }
70
- };
71
-
72
- export const isFileLike = (value) => {
73
- return [
74
- Blob,
75
- File,
76
- ].some((it) => value instanceof it);
77
- };
78
-
79
- export const isPipeStream = (value) => {
80
- return value instanceof Readable;
81
- };
82
-
83
- export const isReadableStream = (value) => {
84
- return value instanceof ReadableStream;
75
+ return deepMerge(target, ...rest);
85
76
  };
86
77
 
87
- export const merge = (target, ...rest) => {
78
+ export const deepMerge = (target, ...rest) => {
88
79
  rest = rest.filter((it) => Object(it) === it);
89
80
  for (const source of rest) {
90
81
  for (const key of Object.getOwnPropertyNames(source)) {
@@ -92,7 +83,7 @@ export const merge = (target, ...rest) => {
92
83
  const tv = target[key];
93
84
 
94
85
  if (Object(sv) === sv && Object(tv) === tv) {
95
- target[key] = merge(tv, sv);
86
+ target[key] = deepMerge(tv, sv);
96
87
  continue;
97
88
  }
98
89
 
@@ -103,9 +94,32 @@ export const merge = (target, ...rest) => {
103
94
  return target;
104
95
  };
105
96
 
97
+ export const dispatch = (req, { body }) => {
98
+ if (isReadable(body)) {
99
+ body.pipe(req);
100
+ } else {
101
+ req.end(body);
102
+ }
103
+ };
104
+
105
+ export const isFileLike = (val) => {
106
+ return [
107
+ Blob,
108
+ File,
109
+ ].some((it) => val instanceof it);
110
+ };
111
+
112
+ export const isPipeStream = (val) => {
113
+ return val instanceof Readable;
114
+ };
115
+
116
+ export const isReadableStream = (val) => {
117
+ return val instanceof ReadableStream;
118
+ };
119
+
106
120
  export const normalize = (url, options = {}) => {
107
121
  if (!options.redirected) {
108
- options = copyWithMerge(config.defaults, options);
122
+ options = cloneWith(config.defaults, options);
109
123
  }
110
124
 
111
125
  if (options.trimTrailingSlashes) {
@@ -119,30 +133,30 @@ export const normalize = (url, options = {}) => {
119
133
  return Object.assign(options, {
120
134
  headers: normalizeHeaders(options.headers),
121
135
  method: options.method.toUpperCase(),
122
- url: new URL(url, options.baseURL),
136
+ url: addSearchParams(new URL(url, options.baseURL), options.params),
123
137
  });
124
138
  };
125
139
 
126
140
  export const normalizeHeaders = (headers) => {
127
- const collector = {};
141
+ const acc = {};
128
142
 
129
- for (const [key, value] of Object.entries(headers ?? {})) {
143
+ for (const [key, val] of Object.entries(headers ?? {})) {
130
144
  const name = key.toLowerCase();
131
145
 
132
- collector[key] = value;
146
+ acc[key] = val;
133
147
 
134
148
  if (key === HTTP2_HEADER_ACCEPT_ENCODING && !isZstdSupported) {
135
- const stripped = value.replace(/\s?zstd,?/gi, '').trim();
149
+ const stripped = val.replace(/\s?zstd,?/gi, '').trim();
136
150
 
137
151
  if (stripped) {
138
- collector[key] = stripped;
152
+ acc[key] = stripped;
139
153
  } else {
140
- Reflect.deleteProperty(collector, name);
154
+ Reflect.deleteProperty(acc, name);
141
155
  }
142
156
  }
143
157
  }
144
158
 
145
- return collector;
159
+ return acc;
146
160
  };
147
161
 
148
162
  export const sameOrigin = (a, b) => a.protocol === b.protocol && a.hostname === b.hostname && a.port === b.port;
@@ -169,13 +183,13 @@ export const stripHeaders = (headers = {}, names = []) => {
169
183
  );
170
184
  };
171
185
 
172
- export async function* tap(value) {
173
- if (Reflect.has(value, Symbol.asyncIterator)) {
174
- yield* value;
175
- } else if (value.stream) {
176
- yield* value.stream();
186
+ export async function* tap(val) {
187
+ if (Reflect.has(val, Symbol.asyncIterator)) {
188
+ yield* val;
189
+ } else if (val.stream) {
190
+ yield* val.stream();
177
191
  } else {
178
- yield await value.arrayBuffer();
192
+ yield await val.arrayBuffer();
179
193
  }
180
194
  }
181
195