got 11.5.2 → 11.7.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/dist/source/as-promise/index.d.ts +1 -3
- package/dist/source/as-promise/index.js +44 -125
- package/dist/source/as-promise/normalize-arguments.d.ts +3 -0
- package/dist/source/as-promise/normalize-arguments.js +78 -0
- package/dist/source/as-promise/parse-body.d.ts +3 -0
- package/dist/source/as-promise/parse-body.js +25 -0
- package/dist/source/as-promise/types.d.ts +206 -24
- package/dist/source/as-promise/types.js +18 -7
- package/dist/source/{as-promise → core}/calculate-retry-delay.d.ts +2 -1
- package/dist/source/core/calculate-retry-delay.js +29 -0
- package/dist/source/core/index.d.ts +823 -5
- package/dist/source/core/index.js +250 -58
- package/dist/source/core/utils/is-response-ok.d.ts +2 -0
- package/dist/source/core/utils/is-response-ok.js +8 -0
- package/dist/source/create.js +16 -7
- package/dist/source/index.js +3 -2
- package/dist/source/types.d.ts +240 -1
- package/package.json +20 -16
- package/readme.md +234 -21
- package/dist/source/as-promise/calculate-retry-delay.js +0 -38
- package/dist/source/as-promise/core.d.ts +0 -13
- package/dist/source/as-promise/core.js +0 -127
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
import { NormalizedOptions, CancelableRequest } from './types';
|
|
2
|
-
|
|
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 };
|
|
@@ -7,18 +7,18 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
7
7
|
o[k2] = m[k];
|
|
8
8
|
}));
|
|
9
9
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
-
for (var p in m) if (p !== "default" && !
|
|
10
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.PromisableRequest = void 0;
|
|
14
13
|
const events_1 = require("events");
|
|
14
|
+
const is_1 = require("@sindresorhus/is");
|
|
15
15
|
const PCancelable = require("p-cancelable");
|
|
16
|
-
const calculate_retry_delay_1 = require("./calculate-retry-delay");
|
|
17
16
|
const types_1 = require("./types");
|
|
18
|
-
const
|
|
19
|
-
|
|
17
|
+
const parse_body_1 = require("./parse-body");
|
|
18
|
+
const core_1 = require("../core");
|
|
20
19
|
const proxy_events_1 = require("../core/utils/proxy-events");
|
|
21
20
|
const get_buffer_1 = require("../core/utils/get-buffer");
|
|
21
|
+
const is_response_ok_1 = require("../core/utils/is-response-ok");
|
|
22
22
|
const proxiedRequestEvents = [
|
|
23
23
|
'request',
|
|
24
24
|
'response',
|
|
@@ -26,53 +26,26 @@ const proxiedRequestEvents = [
|
|
|
26
26
|
'uploadProgress',
|
|
27
27
|
'downloadProgress'
|
|
28
28
|
];
|
|
29
|
-
function asPromise(
|
|
30
|
-
let retryCount = 0;
|
|
29
|
+
function asPromise(normalizedOptions) {
|
|
31
30
|
let globalRequest;
|
|
32
31
|
let globalResponse;
|
|
33
32
|
const emitter = new events_1.EventEmitter();
|
|
34
|
-
const promise = new PCancelable((resolve,
|
|
35
|
-
const makeRequest = () => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// so the HTTP errors are caught and the request is retried.
|
|
39
|
-
// The error is **eventually** thrown if the user value is true.
|
|
40
|
-
const { throwHttpErrors } = options;
|
|
41
|
-
if (!throwHttpErrors) {
|
|
42
|
-
options.throwHttpErrors = true;
|
|
43
|
-
}
|
|
44
|
-
// Note from @szmarczak: I think we should use `request.options` instead of the local options
|
|
45
|
-
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;
|
|
46
37
|
request._noPipe = true;
|
|
47
38
|
onCancel(() => request.destroy());
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
for (const hook of options.hooks.beforeError) {
|
|
52
|
-
// eslint-disable-next-line no-await-in-loop
|
|
53
|
-
error = await hook(error);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
catch (error_) {
|
|
57
|
-
_reject(new types_1.RequestError(error_.message, error_, request));
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
_reject(error);
|
|
61
|
-
})();
|
|
62
|
-
};
|
|
39
|
+
onCancel.shouldReject = false;
|
|
40
|
+
onCancel(() => reject(new types_1.CancelError(request)));
|
|
63
41
|
globalRequest = request;
|
|
64
|
-
|
|
42
|
+
request.once('response', async (response) => {
|
|
65
43
|
var _a;
|
|
66
44
|
response.retryCount = retryCount;
|
|
67
45
|
if (response.request.aborted) {
|
|
68
46
|
// Canceled while downloading - will throw a `CancelError` or `TimeoutError` error
|
|
69
47
|
return;
|
|
70
48
|
}
|
|
71
|
-
const isOk = () => {
|
|
72
|
-
const { statusCode } = response;
|
|
73
|
-
const limitStatusCode = options.followRedirect ? 299 : 399;
|
|
74
|
-
return (statusCode >= 200 && statusCode <= limitStatusCode) || statusCode === 304;
|
|
75
|
-
};
|
|
76
49
|
// Download body
|
|
77
50
|
let rawBody;
|
|
78
51
|
try {
|
|
@@ -84,22 +57,25 @@ function asPromise(options) {
|
|
|
84
57
|
// See request.once('error')
|
|
85
58
|
return;
|
|
86
59
|
}
|
|
60
|
+
if (request._isAboutToError) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
87
63
|
// Parse body
|
|
88
64
|
const contentEncoding = ((_a = response.headers['content-encoding']) !== null && _a !== void 0 ? _a : '').toLowerCase();
|
|
89
65
|
const isCompressed = ['gzip', 'deflate', 'br'].includes(contentEncoding);
|
|
66
|
+
const { options } = request;
|
|
90
67
|
if (isCompressed && !options.decompress) {
|
|
91
68
|
response.body = rawBody;
|
|
92
69
|
}
|
|
93
70
|
else {
|
|
94
71
|
try {
|
|
95
|
-
response.body =
|
|
72
|
+
response.body = parse_body_1.default(response, options.responseType, options.parseJson, options.encoding);
|
|
96
73
|
}
|
|
97
74
|
catch (error) {
|
|
98
75
|
// Fallback to `utf8`
|
|
99
76
|
response.body = rawBody.toString();
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
reject(error);
|
|
77
|
+
if (is_response_ok_1.isResponseOk(response)) {
|
|
78
|
+
request._beforeError(error);
|
|
103
79
|
return;
|
|
104
80
|
}
|
|
105
81
|
}
|
|
@@ -134,99 +110,40 @@ function asPromise(options) {
|
|
|
134
110
|
}
|
|
135
111
|
}
|
|
136
112
|
catch (error) {
|
|
137
|
-
|
|
138
|
-
reject(new types_1.RequestError(error.message, error, request));
|
|
113
|
+
request._beforeError(new types_1.RequestError(error.message, error, request));
|
|
139
114
|
return;
|
|
140
115
|
}
|
|
141
|
-
if (
|
|
142
|
-
|
|
116
|
+
if (!is_response_ok_1.isResponseOk(response)) {
|
|
117
|
+
request._beforeError(new types_1.HTTPError(response));
|
|
143
118
|
return;
|
|
144
119
|
}
|
|
145
120
|
globalResponse = response;
|
|
146
|
-
resolve(options.resolveBodyOnly ? response.body : response);
|
|
147
|
-
};
|
|
148
|
-
const onError =
|
|
121
|
+
resolve(request.options.resolveBodyOnly ? response.body : response);
|
|
122
|
+
});
|
|
123
|
+
const onError = (error) => {
|
|
149
124
|
if (promise.isCanceled) {
|
|
150
125
|
return;
|
|
151
126
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
request.off('response', onResponse);
|
|
157
|
-
let gotUnexpectedError = false;
|
|
158
|
-
const onUnexpectedError = (error) => {
|
|
159
|
-
gotUnexpectedError = true;
|
|
160
|
-
reject(error);
|
|
161
|
-
};
|
|
162
|
-
// If this is an HTTP error, then it can throw again with `ECONNRESET` or `Parse Error`
|
|
163
|
-
request.once('error', onUnexpectedError);
|
|
164
|
-
let backoff;
|
|
165
|
-
retryCount++;
|
|
166
|
-
try {
|
|
167
|
-
backoff = await options.retry.calculateDelay({
|
|
168
|
-
attemptCount: retryCount,
|
|
169
|
-
retryOptions: options.retry,
|
|
170
|
-
error,
|
|
171
|
-
computedValue: calculate_retry_delay_1.default({
|
|
172
|
-
attemptCount: retryCount,
|
|
173
|
-
retryOptions: options.retry,
|
|
174
|
-
error,
|
|
175
|
-
computedValue: 0
|
|
176
|
-
})
|
|
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
|
-
// Another error was thrown already
|
|
186
|
-
if (gotUnexpectedError) {
|
|
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);
|
|
187
131
|
return;
|
|
188
132
|
}
|
|
189
|
-
request.off('error', onUnexpectedError);
|
|
190
|
-
if (backoff) {
|
|
191
|
-
// Don't emit the `response` event
|
|
192
|
-
request.destroy();
|
|
193
|
-
const retry = async () => {
|
|
194
|
-
options.throwHttpErrors = throwHttpErrors;
|
|
195
|
-
try {
|
|
196
|
-
for (const hook of options.hooks.beforeRetry) {
|
|
197
|
-
// eslint-disable-next-line no-await-in-loop
|
|
198
|
-
await hook(options, error, retryCount);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
catch (error_) {
|
|
202
|
-
// Don't emit the `response` event
|
|
203
|
-
request.destroy();
|
|
204
|
-
reject(new types_1.RequestError(error_.message, error, request));
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
makeRequest();
|
|
208
|
-
};
|
|
209
|
-
setTimeout(retry, backoff);
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
// The retry has not been made
|
|
213
|
-
retryCount--;
|
|
214
|
-
if (error instanceof types_1.HTTPError) {
|
|
215
|
-
// The error will be handled by the `response` event
|
|
216
|
-
void onResponse(request._response);
|
|
217
|
-
// Reattach the error handler, because there may be a timeout later.
|
|
218
|
-
request.once('error', onError);
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
// Don't emit the `response` event
|
|
222
|
-
request.destroy();
|
|
223
133
|
reject(error);
|
|
224
134
|
};
|
|
225
|
-
request.once('response', onResponse);
|
|
226
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
|
+
});
|
|
227
144
|
proxy_events_1.default(request, emitter, proxiedRequestEvents);
|
|
228
145
|
};
|
|
229
|
-
makeRequest();
|
|
146
|
+
makeRequest(0);
|
|
230
147
|
});
|
|
231
148
|
promise.on = (event, fn) => {
|
|
232
149
|
emitter.on(event, fn);
|
|
@@ -236,14 +153,16 @@ function asPromise(options) {
|
|
|
236
153
|
const newPromise = (async () => {
|
|
237
154
|
// Wait until downloading has ended
|
|
238
155
|
await promise;
|
|
239
|
-
|
|
156
|
+
const { options } = globalResponse.request;
|
|
157
|
+
return parse_body_1.default(globalResponse, responseType, options.parseJson, options.encoding);
|
|
240
158
|
})();
|
|
241
159
|
Object.defineProperties(newPromise, Object.getOwnPropertyDescriptors(promise));
|
|
242
160
|
return newPromise;
|
|
243
161
|
};
|
|
244
162
|
promise.json = () => {
|
|
245
|
-
|
|
246
|
-
|
|
163
|
+
const { headers } = globalRequest.options;
|
|
164
|
+
if (!globalRequest.writableFinished && headers.accept === undefined) {
|
|
165
|
+
headers.accept = 'application/json';
|
|
247
166
|
}
|
|
248
167
|
return shortcut('json');
|
|
249
168
|
};
|
|
@@ -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 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;
|
|
@@ -1,53 +1,225 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import PCancelable = require('p-cancelable');
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import Request, { Options, Response, RequestError, RequestEvents } from '../core';
|
|
4
|
+
/**
|
|
5
|
+
All parsing methods supported by Got.
|
|
6
|
+
*/
|
|
5
7
|
export declare type ResponseType = 'json' | 'buffer' | 'text';
|
|
6
|
-
export interface RetryObject {
|
|
7
|
-
attemptCount: number;
|
|
8
|
-
retryOptions: RequiredRetryOptions;
|
|
9
|
-
error: TimeoutError | RequestError;
|
|
10
|
-
computedValue: number;
|
|
11
|
-
}
|
|
12
|
-
export declare type RetryFunction = (retryObject: RetryObject) => number | Promise<number>;
|
|
13
|
-
export interface RequiredRetryOptions {
|
|
14
|
-
limit: number;
|
|
15
|
-
methods: Method[];
|
|
16
|
-
statusCodes: number[];
|
|
17
|
-
errorCodes: string[];
|
|
18
|
-
calculateDelay: RetryFunction;
|
|
19
|
-
maxRetryAfter?: number;
|
|
20
|
-
}
|
|
21
8
|
export interface PaginationOptions<T, R> {
|
|
9
|
+
/**
|
|
10
|
+
All options accepted by `got.paginate()`.
|
|
11
|
+
*/
|
|
22
12
|
pagination?: {
|
|
13
|
+
/**
|
|
14
|
+
A function that transform [`Response`](#response) into an array of items.
|
|
15
|
+
This is where you should do the parsing.
|
|
16
|
+
|
|
17
|
+
@default response => JSON.parse(response.body)
|
|
18
|
+
*/
|
|
23
19
|
transform?: (response: Response<R>) => Promise<T[]> | T[];
|
|
20
|
+
/**
|
|
21
|
+
Checks whether the item should be emitted or not.
|
|
22
|
+
|
|
23
|
+
@default (item, allItems, currentItems) => true
|
|
24
|
+
*/
|
|
24
25
|
filter?: (item: T, allItems: T[], currentItems: T[]) => boolean;
|
|
26
|
+
/**
|
|
27
|
+
The function takes three arguments:
|
|
28
|
+
- `response` - The current response object.
|
|
29
|
+
- `allItems` - An array of the emitted items.
|
|
30
|
+
- `currentItems` - Items from the current response.
|
|
31
|
+
|
|
32
|
+
It should return an object representing Got options pointing to the next page.
|
|
33
|
+
The options are merged automatically with the previous request, therefore the options returned `pagination.paginate(...)` must reflect changes only.
|
|
34
|
+
If there are no more pages, `false` should be returned.
|
|
35
|
+
|
|
36
|
+
@example
|
|
37
|
+
```
|
|
38
|
+
const got = require('got');
|
|
39
|
+
|
|
40
|
+
(async () => {
|
|
41
|
+
const limit = 10;
|
|
42
|
+
|
|
43
|
+
const items = got.paginate('https://example.com/items', {
|
|
44
|
+
searchParams: {
|
|
45
|
+
limit,
|
|
46
|
+
offset: 0
|
|
47
|
+
},
|
|
48
|
+
pagination: {
|
|
49
|
+
paginate: (response, allItems, currentItems) => {
|
|
50
|
+
const previousSearchParams = response.request.options.searchParams;
|
|
51
|
+
const previousOffset = previousSearchParams.get('offset');
|
|
52
|
+
|
|
53
|
+
if (currentItems.length < limit) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
searchParams: {
|
|
59
|
+
...previousSearchParams,
|
|
60
|
+
offset: Number(previousOffset) + limit,
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
console.log('Items from all pages:', items);
|
|
68
|
+
})();
|
|
69
|
+
```
|
|
70
|
+
*/
|
|
25
71
|
paginate?: (response: Response<R>, allItems: T[], currentItems: T[]) => Options | false;
|
|
72
|
+
/**
|
|
73
|
+
Checks whether the pagination should continue.
|
|
74
|
+
|
|
75
|
+
For example, if you need to stop **before** emitting an entry with some flag, you should use `(item, allItems, currentItems) => !item.flag`.
|
|
76
|
+
If you want to stop **after** emitting the entry, you should use `(item, allItems, currentItems) => allItems.some(entry => entry.flag)` instead.
|
|
77
|
+
|
|
78
|
+
@default (item, allItems, currentItems) => true
|
|
79
|
+
*/
|
|
26
80
|
shouldContinue?: (item: T, allItems: T[], currentItems: T[]) => boolean;
|
|
81
|
+
/**
|
|
82
|
+
The maximum amount of items that should be emitted.
|
|
83
|
+
|
|
84
|
+
@default Infinity
|
|
85
|
+
*/
|
|
27
86
|
countLimit?: number;
|
|
87
|
+
/**
|
|
88
|
+
Milliseconds to wait before the next request is triggered.
|
|
89
|
+
|
|
90
|
+
@default 0
|
|
91
|
+
*/
|
|
28
92
|
backoff?: number;
|
|
93
|
+
/**
|
|
94
|
+
The maximum amount of request that should be triggered.
|
|
95
|
+
Retries on failure are not counted towards this limit.
|
|
96
|
+
|
|
97
|
+
For example, it can be helpful during development to avoid an infinite number of requests.
|
|
98
|
+
|
|
99
|
+
@default 10000
|
|
100
|
+
*/
|
|
29
101
|
requestLimit?: number;
|
|
102
|
+
/**
|
|
103
|
+
Defines how the parameter `allItems` in pagination.paginate, pagination.filter and pagination.shouldContinue is managed.
|
|
104
|
+
When set to `false`, the parameter `allItems` is always an empty array.
|
|
105
|
+
|
|
106
|
+
This option can be helpful to save on memory usage when working with a large dataset.
|
|
107
|
+
*/
|
|
30
108
|
stackAllItems?: boolean;
|
|
31
109
|
};
|
|
32
110
|
}
|
|
33
|
-
export declare type BeforeRetryHook = (options: NormalizedOptions, error?: RequestError, retryCount?: number) => void | Promise<void>;
|
|
34
111
|
export declare type AfterResponseHook = (response: Response, retryWithMergedOptions: (options: Options) => CancelableRequest<Response>) => Response | CancelableRequest<Response> | Promise<Response | CancelableRequest<Response>>;
|
|
35
112
|
export declare namespace PromiseOnly {
|
|
36
113
|
interface Hooks {
|
|
37
|
-
|
|
114
|
+
/**
|
|
115
|
+
Called with [response object](#response) and a retry function.
|
|
116
|
+
Calling the retry function will trigger `beforeRetry` hooks.
|
|
117
|
+
|
|
118
|
+
Each function should return the response.
|
|
119
|
+
This is especially useful when you want to refresh an access token.
|
|
120
|
+
|
|
121
|
+
__Note__: When using streams, this hook is ignored.
|
|
122
|
+
|
|
123
|
+
@example
|
|
124
|
+
```
|
|
125
|
+
const got = require('got');
|
|
126
|
+
|
|
127
|
+
const instance = got.extend({
|
|
128
|
+
hooks: {
|
|
129
|
+
afterResponse: [
|
|
130
|
+
(response, retryWithMergedOptions) => {
|
|
131
|
+
if (response.statusCode === 401) { // Unauthorized
|
|
132
|
+
const updatedOptions = {
|
|
133
|
+
headers: {
|
|
134
|
+
token: getNewToken() // Refresh the access token
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// Save for further requests
|
|
139
|
+
instance.defaults.options = got.mergeOptions(instance.defaults.options, updatedOptions);
|
|
140
|
+
|
|
141
|
+
// Make a new retry
|
|
142
|
+
return retryWithMergedOptions(updatedOptions);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// No changes otherwise
|
|
146
|
+
return response;
|
|
147
|
+
}
|
|
148
|
+
],
|
|
149
|
+
beforeRetry: [
|
|
150
|
+
(options, error, retryCount) => {
|
|
151
|
+
// This will be called on `retryWithMergedOptions(...)`
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
},
|
|
155
|
+
mutableDefaults: true
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
*/
|
|
38
159
|
afterResponse?: AfterResponseHook[];
|
|
39
160
|
}
|
|
40
161
|
interface Options extends PaginationOptions<unknown, unknown> {
|
|
162
|
+
/**
|
|
163
|
+
The parsing method.
|
|
164
|
+
|
|
165
|
+
The promise also has `.text()`, `.json()` and `.buffer()` methods which return another Got promise for the parsed body.
|
|
166
|
+
|
|
167
|
+
It's like setting the options to `{responseType: 'json', resolveBodyOnly: true}` but without affecting the main Got promise.
|
|
168
|
+
|
|
169
|
+
__Note__: When using streams, this option is ignored.
|
|
170
|
+
|
|
171
|
+
@example
|
|
172
|
+
```
|
|
173
|
+
(async () => {
|
|
174
|
+
const responsePromise = got(url);
|
|
175
|
+
const bufferPromise = responsePromise.buffer();
|
|
176
|
+
const jsonPromise = responsePromise.json();
|
|
177
|
+
|
|
178
|
+
const [response, buffer, json] = Promise.all([responsePromise, bufferPromise, jsonPromise]);
|
|
179
|
+
// `response` is an instance of Got Response
|
|
180
|
+
// `buffer` is an instance of Buffer
|
|
181
|
+
// `json` is an object
|
|
182
|
+
})();
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
@example
|
|
186
|
+
```
|
|
187
|
+
// This
|
|
188
|
+
const body = await got(url).json();
|
|
189
|
+
|
|
190
|
+
// is semantically the same as this
|
|
191
|
+
const body = await got(url, {responseType: 'json', resolveBodyOnly: true});
|
|
192
|
+
```
|
|
193
|
+
*/
|
|
41
194
|
responseType?: ResponseType;
|
|
195
|
+
/**
|
|
196
|
+
When set to `true` the promise will return the Response body instead of the Response object.
|
|
197
|
+
|
|
198
|
+
@default false
|
|
199
|
+
*/
|
|
42
200
|
resolveBodyOnly?: boolean;
|
|
43
|
-
|
|
201
|
+
/**
|
|
202
|
+
Returns a `Stream` instead of a `Promise`.
|
|
203
|
+
This is equivalent to calling `got.stream(url, options?)`.
|
|
204
|
+
|
|
205
|
+
@default false
|
|
206
|
+
*/
|
|
44
207
|
isStream?: boolean;
|
|
208
|
+
/**
|
|
209
|
+
[Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data.
|
|
210
|
+
|
|
211
|
+
To get a [`Buffer`](https://nodejs.org/api/buffer.html), you need to set `responseType` to `buffer` instead.
|
|
212
|
+
Don't set this option to `null`.
|
|
213
|
+
|
|
214
|
+
__Note__: This doesn't affect streams! Instead, you need to do `got.stream(...).setEncoding(encoding)`.
|
|
215
|
+
|
|
216
|
+
@default 'utf-8'
|
|
217
|
+
*/
|
|
45
218
|
encoding?: BufferEncoding;
|
|
46
219
|
}
|
|
47
220
|
interface NormalizedOptions {
|
|
48
221
|
responseType: ResponseType;
|
|
49
222
|
resolveBodyOnly: boolean;
|
|
50
|
-
retry: RequiredRetryOptions;
|
|
51
223
|
isStream: boolean;
|
|
52
224
|
encoding?: BufferEncoding;
|
|
53
225
|
pagination?: Required<PaginationOptions<unknown, unknown>['pagination']>;
|
|
@@ -55,20 +227,30 @@ export declare namespace PromiseOnly {
|
|
|
55
227
|
interface Defaults {
|
|
56
228
|
responseType: ResponseType;
|
|
57
229
|
resolveBodyOnly: boolean;
|
|
58
|
-
retry: RequiredRetryOptions;
|
|
59
230
|
isStream: boolean;
|
|
60
231
|
pagination?: Required<PaginationOptions<unknown, unknown>['pagination']>;
|
|
61
232
|
}
|
|
62
|
-
type HookEvent = '
|
|
233
|
+
type HookEvent = 'afterResponse';
|
|
63
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
An error to be thrown when server response code is 2xx, and parsing body fails.
|
|
237
|
+
Includes a `response` property.
|
|
238
|
+
*/
|
|
64
239
|
export declare class ParseError extends RequestError {
|
|
65
240
|
readonly response: Response;
|
|
66
241
|
constructor(error: Error, response: Response);
|
|
67
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
An error to be thrown when the request is aborted with `.cancel()`.
|
|
245
|
+
*/
|
|
246
|
+
export declare class CancelError extends RequestError {
|
|
247
|
+
readonly response: Response;
|
|
248
|
+
constructor(request: Request);
|
|
249
|
+
get isCanceled(): boolean;
|
|
250
|
+
}
|
|
68
251
|
export interface CancelableRequest<T extends Response | Response['body'] = Response['body']> extends PCancelable<T>, RequestEvents<CancelableRequest<T>> {
|
|
69
252
|
json: <ReturnType>() => CancelableRequest<ReturnType>;
|
|
70
253
|
buffer: () => CancelableRequest<Buffer>;
|
|
71
254
|
text: () => CancelableRequest<string>;
|
|
72
255
|
}
|
|
73
|
-
export { CancelError };
|
|
74
256
|
export * from '../core';
|