got 11.4.0 → 11.6.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.
Files changed (31) hide show
  1. package/dist/source/as-promise/index.d.ts +1 -3
  2. package/dist/source/as-promise/index.js +56 -117
  3. package/dist/source/as-promise/normalize-arguments.d.ts +3 -0
  4. package/dist/source/as-promise/normalize-arguments.js +78 -0
  5. package/dist/source/as-promise/parse-body.d.ts +3 -0
  6. package/dist/source/as-promise/parse-body.js +25 -0
  7. package/dist/source/as-promise/types.d.ts +235 -58
  8. package/dist/source/as-promise/types.js +29 -16
  9. package/dist/source/{as-promise → core}/calculate-retry-delay.d.ts +2 -1
  10. package/dist/source/core/calculate-retry-delay.js +29 -0
  11. package/dist/source/core/index.d.ts +851 -28
  12. package/dist/source/core/index.js +291 -55
  13. package/dist/source/core/utils/dns-ip-version.js +1 -0
  14. package/dist/source/core/utils/get-body-size.d.ts +2 -4
  15. package/dist/source/core/utils/is-form-data.d.ts +2 -2
  16. package/dist/source/core/utils/is-response-ok.d.ts +2 -0
  17. package/dist/source/core/utils/is-response-ok.js +8 -0
  18. package/dist/source/core/utils/options-to-url.d.ts +0 -1
  19. package/dist/source/core/utils/timed-out.js +1 -0
  20. package/dist/source/core/utils/url-to-options.d.ts +0 -1
  21. package/dist/source/core/utils/weakable-map.d.ts +1 -1
  22. package/dist/source/create.js +42 -13
  23. package/dist/source/index.js +16 -6
  24. package/dist/source/types.d.ts +245 -8
  25. package/dist/source/utils/deep-freeze.d.ts +1 -1
  26. package/dist/source/utils/deprecation-warning.js +1 -1
  27. package/package.json +30 -29
  28. package/readme.md +171 -35
  29. package/dist/source/as-promise/calculate-retry-delay.js +0 -38
  30. package/dist/source/as-promise/core.d.ts +0 -13
  31. package/dist/source/as-promise/core.js +0 -124
@@ -1,5 +1,3 @@
1
1
  import { NormalizedOptions, CancelableRequest } from './types';
2
- import PromisableRequest from './core';
3
- export default function asPromise<T>(options: NormalizedOptions): CancelableRequest<T>;
2
+ export default function asPromise<T>(normalizedOptions: NormalizedOptions): CancelableRequest<T>;
4
3
  export * from './types';
5
- export { PromisableRequest };
@@ -1,16 +1,24 @@
1
1
  "use strict";
2
- function __export(m) {
3
- for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
4
- }
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
5
12
  Object.defineProperty(exports, "__esModule", { value: true });
6
13
  const events_1 = require("events");
14
+ const is_1 = require("@sindresorhus/is");
7
15
  const PCancelable = require("p-cancelable");
8
- const calculate_retry_delay_1 = require("./calculate-retry-delay");
9
16
  const types_1 = require("./types");
10
- const core_1 = require("./core");
11
- exports.PromisableRequest = core_1.default;
17
+ const parse_body_1 = require("./parse-body");
18
+ const core_1 = require("../core");
12
19
  const proxy_events_1 = require("../core/utils/proxy-events");
13
20
  const get_buffer_1 = require("../core/utils/get-buffer");
21
+ const is_response_ok_1 = require("../core/utils/is-response-ok");
14
22
  const proxiedRequestEvents = [
15
23
  'request',
16
24
  'response',
@@ -18,85 +26,63 @@ const proxiedRequestEvents = [
18
26
  'uploadProgress',
19
27
  'downloadProgress'
20
28
  ];
21
- function asPromise(options) {
22
- let retryCount = 0;
29
+ function asPromise(normalizedOptions) {
23
30
  let globalRequest;
24
31
  let globalResponse;
25
32
  const emitter = new events_1.EventEmitter();
26
- const promise = new PCancelable((resolve, _reject, onCancel) => {
27
- const makeRequest = () => {
28
- // Support retries
29
- // `options.throwHttpErrors` needs to be always true,
30
- // so the HTTP errors are caught and the request is retried.
31
- // The error is **eventually** thrown if the user value is true.
32
- const { throwHttpErrors } = options;
33
- if (!throwHttpErrors) {
34
- options.throwHttpErrors = true;
35
- }
36
- // Note from @szmarczak: I think we should use `request.options` instead of the local options
37
- const request = new core_1.default(options.url, options);
33
+ const promise = new PCancelable((resolve, reject, onCancel) => {
34
+ const makeRequest = (retryCount) => {
35
+ const request = new core_1.default(undefined, normalizedOptions);
36
+ request.retryCount = retryCount;
38
37
  request._noPipe = true;
39
38
  onCancel(() => request.destroy());
40
- const reject = async (error) => {
41
- try {
42
- for (const hook of options.hooks.beforeError) {
43
- // eslint-disable-next-line no-await-in-loop
44
- error = await hook(error);
45
- }
46
- }
47
- catch (error_) {
48
- _reject(new types_1.RequestError(error_.message, error_, request));
49
- return;
50
- }
51
- _reject(error);
52
- };
39
+ onCancel.shouldReject = false;
40
+ onCancel(() => reject(new types_1.CancelError(request)));
53
41
  globalRequest = request;
54
- const onResponse = async (response) => {
42
+ request.once('response', async (response) => {
55
43
  var _a;
56
44
  response.retryCount = retryCount;
57
45
  if (response.request.aborted) {
58
46
  // Canceled while downloading - will throw a `CancelError` or `TimeoutError` error
59
47
  return;
60
48
  }
61
- const isOk = () => {
62
- const { statusCode } = response;
63
- const limitStatusCode = options.followRedirect ? 299 : 399;
64
- return (statusCode >= 200 && statusCode <= limitStatusCode) || statusCode === 304;
65
- };
66
49
  // Download body
67
50
  let rawBody;
68
51
  try {
69
52
  rawBody = await get_buffer_1.default(request);
70
53
  response.rawBody = rawBody;
71
54
  }
72
- catch (_) {
55
+ catch (_b) {
73
56
  // The same error is caught below.
74
57
  // See request.once('error')
75
58
  return;
76
59
  }
60
+ if (request._isAboutToError) {
61
+ return;
62
+ }
77
63
  // Parse body
78
64
  const contentEncoding = ((_a = response.headers['content-encoding']) !== null && _a !== void 0 ? _a : '').toLowerCase();
79
65
  const isCompressed = ['gzip', 'deflate', 'br'].includes(contentEncoding);
66
+ const { options } = request;
80
67
  if (isCompressed && !options.decompress) {
81
68
  response.body = rawBody;
82
69
  }
83
70
  else {
84
71
  try {
85
- response.body = core_1.parseBody(response, options.responseType, options.parseJson, options.encoding);
72
+ response.body = parse_body_1.default(response, options.responseType, options.parseJson, options.encoding);
86
73
  }
87
74
  catch (error) {
88
75
  // Fallback to `utf8`
89
76
  response.body = rawBody.toString();
90
- if (isOk()) {
91
- // TODO: Call `request._beforeError`, see https://github.com/nodejs/node/issues/32995
92
- reject(error);
77
+ if (is_response_ok_1.isResponseOk(response)) {
78
+ request._beforeError(error);
93
79
  return;
94
80
  }
95
81
  }
96
82
  }
97
83
  try {
98
84
  for (const [index, hook] of options.hooks.afterResponse.entries()) {
99
- // @ts-ignore TS doesn't notice that CancelableRequest is a Promise
85
+ // @ts-expect-error TS doesn't notice that CancelableRequest is a Promise
100
86
  // eslint-disable-next-line no-await-in-loop
101
87
  response = await hook(response, async (updatedOptions) => {
102
88
  const typedOptions = core_1.default.normalizeArguments(undefined, {
@@ -124,89 +110,40 @@ function asPromise(options) {
124
110
  }
125
111
  }
126
112
  catch (error) {
127
- // TODO: Call `request._beforeError`, see https://github.com/nodejs/node/issues/32995
128
- reject(new types_1.RequestError(error.message, error, request));
113
+ request._beforeError(new types_1.RequestError(error.message, error, request));
129
114
  return;
130
115
  }
131
- if (throwHttpErrors && !isOk()) {
132
- reject(new types_1.HTTPError(response));
116
+ if (!is_response_ok_1.isResponseOk(response)) {
117
+ request._beforeError(new types_1.HTTPError(response));
133
118
  return;
134
119
  }
135
120
  globalResponse = response;
136
- resolve(options.resolveBodyOnly ? response.body : response);
137
- };
138
- const onError = async (error) => {
121
+ resolve(request.options.resolveBodyOnly ? response.body : response);
122
+ });
123
+ const onError = (error) => {
139
124
  if (promise.isCanceled) {
140
125
  return;
141
126
  }
142
- if (!request.options) {
143
- reject(error);
127
+ const { options } = request;
128
+ if (error instanceof types_1.HTTPError && !options.throwHttpErrors) {
129
+ const { response } = error;
130
+ resolve(request.options.resolveBodyOnly ? response.body : response);
144
131
  return;
145
132
  }
146
- request.off('response', onResponse);
147
- let backoff;
148
- retryCount++;
149
- try {
150
- backoff = await options.retry.calculateDelay({
151
- attemptCount: retryCount,
152
- retryOptions: options.retry,
153
- error,
154
- computedValue: calculate_retry_delay_1.default({
155
- attemptCount: retryCount,
156
- retryOptions: options.retry,
157
- error,
158
- computedValue: 0
159
- })
160
- });
161
- }
162
- catch (error_) {
163
- // Don't emit the `response` event
164
- request.destroy();
165
- reject(new types_1.RequestError(error_.message, error, request));
166
- return;
167
- }
168
- if (backoff) {
169
- // Don't emit the `response` event
170
- request.destroy();
171
- const retry = async () => {
172
- options.throwHttpErrors = throwHttpErrors;
173
- try {
174
- for (const hook of options.hooks.beforeRetry) {
175
- // eslint-disable-next-line no-await-in-loop
176
- await hook(options, error, retryCount);
177
- }
178
- }
179
- catch (error_) {
180
- // Don't emit the `response` event
181
- request.destroy();
182
- reject(new types_1.RequestError(error_.message, error, request));
183
- return;
184
- }
185
- makeRequest();
186
- };
187
- setTimeout(retry, backoff);
188
- return;
189
- }
190
- // The retry has not been made
191
- retryCount--;
192
- if (error instanceof types_1.HTTPError) {
193
- // The error will be handled by the `response` event
194
- onResponse(request._response);
195
- // Reattach the error handler, because there may be a timeout later.
196
- process.nextTick(() => {
197
- request.once('error', onError);
198
- });
199
- return;
200
- }
201
- // Don't emit the `response` event
202
- request.destroy();
203
133
  reject(error);
204
134
  };
205
- request.once('response', onResponse);
206
135
  request.once('error', onError);
136
+ request.once('retry', (newRetryCount, error) => {
137
+ var _a;
138
+ if (is_1.default.nodeStream((_a = error.request) === null || _a === void 0 ? void 0 : _a.options.body)) {
139
+ onError(error);
140
+ return;
141
+ }
142
+ makeRequest(newRetryCount);
143
+ });
207
144
  proxy_events_1.default(request, emitter, proxiedRequestEvents);
208
145
  };
209
- makeRequest();
146
+ makeRequest(0);
210
147
  });
211
148
  promise.on = (event, fn) => {
212
149
  emitter.on(event, fn);
@@ -216,14 +153,16 @@ function asPromise(options) {
216
153
  const newPromise = (async () => {
217
154
  // Wait until downloading has ended
218
155
  await promise;
219
- return core_1.parseBody(globalResponse, responseType, options.parseJson, options.encoding);
156
+ const { options } = globalResponse.request;
157
+ return parse_body_1.default(globalResponse, responseType, options.parseJson, options.encoding);
220
158
  })();
221
159
  Object.defineProperties(newPromise, Object.getOwnPropertyDescriptors(promise));
222
160
  return newPromise;
223
161
  };
224
162
  promise.json = () => {
225
- if (!globalRequest.writableFinished && options.headers.accept === undefined) {
226
- options.headers.accept = 'application/json';
163
+ const { headers } = globalRequest.options;
164
+ if (!globalRequest.writableFinished && headers.accept === undefined) {
165
+ headers.accept = 'application/json';
227
166
  }
228
167
  return shortcut('json');
229
168
  };
@@ -232,4 +171,4 @@ function asPromise(options) {
232
171
  return promise;
233
172
  }
234
173
  exports.default = asPromise;
235
- __export(require("./types"));
174
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,3 @@
1
+ import { NormalizedOptions, Defaults } from './types';
2
+ declare const normalizeArguments: (options: NormalizedOptions, defaults?: Defaults | undefined) => NormalizedOptions;
3
+ export default normalizeArguments;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const is_1 = require("@sindresorhus/is");
4
+ const normalizeArguments = (options, defaults) => {
5
+ if (is_1.default.null_(options.encoding)) {
6
+ throw new TypeError('To get a Buffer, set `options.responseType` to `buffer` instead');
7
+ }
8
+ is_1.assert.any([is_1.default.string, is_1.default.undefined], options.encoding);
9
+ is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.resolveBodyOnly);
10
+ is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.methodRewriting);
11
+ is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.isStream);
12
+ is_1.assert.any([is_1.default.string, is_1.default.undefined], options.responseType);
13
+ // `options.responseType`
14
+ if (options.responseType === undefined) {
15
+ options.responseType = 'text';
16
+ }
17
+ // `options.retry`
18
+ const { retry } = options;
19
+ if (defaults) {
20
+ options.retry = { ...defaults.retry };
21
+ }
22
+ else {
23
+ options.retry = {
24
+ calculateDelay: retryObject => retryObject.computedValue,
25
+ limit: 0,
26
+ methods: [],
27
+ statusCodes: [],
28
+ errorCodes: [],
29
+ maxRetryAfter: undefined
30
+ };
31
+ }
32
+ if (is_1.default.object(retry)) {
33
+ options.retry = {
34
+ ...options.retry,
35
+ ...retry
36
+ };
37
+ options.retry.methods = [...new Set(options.retry.methods.map(method => method.toUpperCase()))];
38
+ options.retry.statusCodes = [...new Set(options.retry.statusCodes)];
39
+ options.retry.errorCodes = [...new Set(options.retry.errorCodes)];
40
+ }
41
+ else if (is_1.default.number(retry)) {
42
+ options.retry.limit = retry;
43
+ }
44
+ if (is_1.default.undefined(options.retry.maxRetryAfter)) {
45
+ options.retry.maxRetryAfter = Math.min(
46
+ // TypeScript is not smart enough to handle `.filter(x => is.number(x))`.
47
+ // eslint-disable-next-line unicorn/no-fn-reference-in-iterator
48
+ ...[options.timeout.request, options.timeout.connect].filter(is_1.default.number));
49
+ }
50
+ // `options.pagination`
51
+ if (is_1.default.object(options.pagination)) {
52
+ if (defaults) {
53
+ options.pagination = {
54
+ ...defaults.pagination,
55
+ ...options.pagination
56
+ };
57
+ }
58
+ const { pagination } = options;
59
+ if (!is_1.default.function_(pagination.transform)) {
60
+ throw new Error('`options.pagination.transform` must be implemented');
61
+ }
62
+ if (!is_1.default.function_(pagination.shouldContinue)) {
63
+ throw new Error('`options.pagination.shouldContinue` must be implemented');
64
+ }
65
+ if (!is_1.default.function_(pagination.filter)) {
66
+ throw new TypeError('`options.pagination.filter` must be implemented');
67
+ }
68
+ if (!is_1.default.function_(pagination.paginate)) {
69
+ throw new Error('`options.pagination.paginate` must be implemented');
70
+ }
71
+ }
72
+ // JSON mode
73
+ if (options.responseType === 'json' && options.headers.accept === undefined) {
74
+ options.headers.accept = 'application/json';
75
+ }
76
+ return options;
77
+ };
78
+ exports.default = normalizeArguments;
@@ -0,0 +1,3 @@
1
+ import { ResponseType, Response, ParseJsonFunction } from './types';
2
+ declare const parseBody: (response: Response, responseType: ResponseType, parseJson: ParseJsonFunction, encoding?: "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex" | undefined) => unknown;
3
+ export default parseBody;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const types_1 = require("./types");
4
+ const parseBody = (response, responseType, parseJson, encoding) => {
5
+ const { rawBody } = response;
6
+ try {
7
+ if (responseType === 'text') {
8
+ return rawBody.toString(encoding);
9
+ }
10
+ if (responseType === 'json') {
11
+ return rawBody.length === 0 ? '' : parseJson(rawBody.toString());
12
+ }
13
+ if (responseType === 'buffer') {
14
+ return Buffer.from(rawBody);
15
+ }
16
+ throw new types_1.ParseError({
17
+ message: `Unknown body type '${responseType}'`,
18
+ name: 'Error'
19
+ }, response);
20
+ }
21
+ catch (error) {
22
+ throw new types_1.ParseError(error, response);
23
+ }
24
+ };
25
+ exports.default = parseBody;