got 10.6.0 → 10.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.
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { Merge } from 'type-fest';
2
+ import { Merge, Except } from 'type-fest';
3
3
  import { ProxyStream } from './as-stream';
4
4
  import * as errors from './errors';
5
5
  import { CancelableRequest, Defaults, ExtendOptions, HandlerFunction, NormalizedOptions, Options, Response, URLOrOptions, PaginationOptions } from './types';
@@ -51,9 +51,11 @@ export interface GotRequestMethod {
51
51
  isStream: true;
52
52
  }>): ProxyStream<T>;
53
53
  }
54
+ export declare type GotPaginateOptions<T> = Except<Options, keyof PaginationOptions<unknown>> & PaginationOptions<T>;
55
+ export declare type URLOrGotPaginateOptions<T> = string | GotPaginateOptions<T>;
54
56
  export interface GotPaginate {
55
- <T>(url: URLOrOptions & PaginationOptions<T>, options?: Options & PaginationOptions<T>): AsyncIterableIterator<T>;
56
- all<T>(url: URLOrOptions & PaginationOptions<T>, options?: Options & PaginationOptions<T>): Promise<T[]>;
57
+ <T>(url: URLOrGotPaginateOptions<T>, options?: GotPaginateOptions<T>): AsyncIterableIterator<T>;
58
+ all<T>(url: URLOrGotPaginateOptions<T>, options?: GotPaginateOptions<T>): Promise<T[]>;
57
59
  }
58
60
  export interface Got extends Record<HTTPAlias, GotRequestMethod>, GotRequestMethod {
59
61
  stream: GotStream;
@@ -111,19 +111,21 @@ const create = (defaults) => {
111
111
  const result = await got(normalizedOptions);
112
112
  // eslint-disable-next-line no-await-in-loop
113
113
  const parsed = await pagination.transform(result);
114
+ const current = [];
114
115
  for (const item of parsed) {
115
- if (pagination.filter(item, all)) {
116
- if (!pagination.shouldContinue(item, all)) {
116
+ if (pagination.filter(item, all, current)) {
117
+ if (!pagination.shouldContinue(item, all, current)) {
117
118
  return;
118
119
  }
119
120
  yield item;
120
121
  all.push(item);
122
+ current.push(item);
121
123
  if (all.length === pagination.countLimit) {
122
124
  return;
123
125
  }
124
126
  }
125
127
  }
126
- const optionsToMerge = pagination.paginate(result);
128
+ const optionsToMerge = pagination.paginate(result, all, current);
127
129
  if (optionsToMerge === false) {
128
130
  return;
129
131
  }
@@ -72,6 +72,9 @@ const defaults = {
72
72
  context: {},
73
73
  _pagination: {
74
74
  transform: (response) => {
75
+ if (response.request.options.responseType === 'json') {
76
+ return response.body;
77
+ }
75
78
  return JSON.parse(response.body);
76
79
  },
77
80
  paginate: response => {
@@ -104,9 +104,9 @@ export declare type DefaultOptions = Merge<Required<Except<GotOptions, 'hooks' |
104
104
  export interface PaginationOptions<T> {
105
105
  _pagination?: {
106
106
  transform?: (response: Response) => Promise<T[]> | T[];
107
- filter?: (item: T, allItems: T[]) => boolean;
108
- paginate?: (response: Response) => Options | false;
109
- shouldContinue?: (item: T, allItems: T[]) => boolean;
107
+ filter?: (item: T, allItems: T[], currentItems: T[]) => boolean;
108
+ paginate?: (response: Response, allItems: T[], currentItems: T[]) => Options | false;
109
+ shouldContinue?: (item: T, allItems: T[], currentItems: T[]) => boolean;
110
110
  countLimit?: number;
111
111
  };
112
112
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "got",
3
- "version": "10.6.0",
3
+ "version": "10.7.0",
4
4
  "description": "Human-friendly and powerful HTTP request library for Node.js",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/got",
@@ -94,7 +94,6 @@
94
94
  "types": "dist/source",
95
95
  "sideEffects": false,
96
96
  "browser": {
97
- "decompress-response": false,
98
97
  "electron": false
99
98
  },
100
99
  "ava": {
package/readme.md CHANGED
@@ -190,13 +190,16 @@ Type: `string | Buffer | stream.Readable` or [`form-data` instance](https://gith
190
190
 
191
191
  **Note #3:** If you provide a payload with the `GET` or `HEAD` method, it will throw a `TypeError` unless the method is `GET` and the `allowGetBody` option is set to `true`.
192
192
 
193
+ **Note #4:** This option is not enumerable and will not be merged with the instance defaults.
194
+
193
195
  The `content-length` header will be automatically set if `body` is a `string` / `Buffer` / `fs.createReadStream` instance / [`form-data` instance](https://github.com/form-data/form-data), and `content-length` and `transfer-encoding` are not manually set in `options.headers`.
194
196
 
195
197
  ###### json
196
198
 
197
199
  Type: `object | Array | number | string | boolean | null` *(JSON-serializable values)*
198
200
 
199
- **Note:** If you provide this option, `got.stream()` will be read-only.
201
+ **Note #1:** If you provide this option, `got.stream()` will be read-only.
202
+ **Note #2:** This option is not enumerable and will not be merged with the instance defaults.
200
203
 
201
204
  JSON body. If the `Content-Type` header is not set, it will be set to `application/json`.
202
205
 
@@ -217,7 +220,7 @@ const instance = got.extend({
217
220
  hooks: {
218
221
  beforeRequest: [
219
222
  options => {
220
- if (!options.context && !options.context.token) {
223
+ if (!options.context || !options.context.token) {
221
224
  throw new Error('Token required');
222
225
  }
223
226
 
@@ -248,21 +251,35 @@ Default: `'text'`
248
251
 
249
252
  The parsing method. Can be `'text'`, `'json'` or `'buffer'`.
250
253
 
251
- The promise also has `.text()`, `.json()` and `.buffer()` methods which sets this and the `resolveBodyOnly` option automatically.
254
+ The promise also has `.text()`, `.json()` and `.buffer()` methods which return another Got promise for the parsed body.\
255
+ It's like setting the options to `{responseType: 'json', resolveBodyOnly: true}` but without affecting the main Got promise.
252
256
 
253
257
  Example:
254
258
 
259
+ ```js
260
+ (async () => {
261
+ const responsePromise = got(url);
262
+ const bufferPromise = responsePromise.buffer();
263
+ const jsonPromise = responsePromise.json();
264
+
265
+ const [response, buffer, json] = Promise.all([responsePromise, bufferPromise, jsonPromise]);
266
+ // `response` is an instance of Got Response
267
+ // `buffer` is an instance of Buffer
268
+ // `json` is an object
269
+ })();
270
+ ```
271
+
255
272
  ```js
256
273
  // This
257
274
  const body = await got(url).json();
258
275
 
259
- // is the same as this
276
+ // is semantically the same as this
260
277
  const body = await got(url, {responseType: 'json', resolveBodyOnly: true});
261
278
  ```
262
279
 
263
280
  ###### resolveBodyOnly
264
281
 
265
- Type: `string`\
282
+ Type: `boolean`\
266
283
  Default: `false`
267
284
 
268
285
  When set to `true` the promise will return the [Response body](#body-1) instead of the [Response](#response) object.
@@ -307,7 +324,8 @@ To get a [`Buffer`](https://nodejs.org/api/buffer.html), you need to set [`respo
307
324
 
308
325
  Type: `object | true`
309
326
 
310
- **Note:** If you provide this option, `got.stream()` will be read-only.
327
+ **Note #1:** If you provide this option, `got.stream()` will be read-only.
328
+ **Note #2:** This option is not enumerable and will not be merged with the instance defaults.
311
329
 
312
330
  The form body is converted to query string using [`(new URLSearchParams(object)).toString()`](https://nodejs.org/api/url.html#url_constructor_new_urlsearchparams_obj).
313
331
 
@@ -560,7 +578,7 @@ got.post('https://example.com', {
560
578
  hooks: {
561
579
  beforeRetry: [
562
580
  (options, error, retryCount) => {
563
- if (error.statusCode === 413) { // Payload too large
581
+ if (error.response.statusCode === 413) { // Payload too large
564
582
  options.body = getNewBody();
565
583
  }
566
584
  }
@@ -636,7 +654,7 @@ got('https://api.github.com/some-endpoint', {
636
654
  const {response} = error;
637
655
  if (response && response.body) {
638
656
  error.name = 'GitHubError';
639
- error.message = `${response.body.message} (${error.statusCode})`;
657
+ error.message = `${response.body.message} (${response.statusCode})`;
640
658
  }
641
659
 
642
660
  return error;
@@ -664,23 +682,64 @@ A function that transform [`Response`](#response) into an array of items. This i
664
682
  Type: `Function`\
665
683
  Default: [`Link` header logic](source/index.ts)
666
684
 
667
- A function that returns an object representing Got options pointing to the next page. If there are no more pages, `false` should be returned.
685
+ The function takes three arguments:
686
+ - `response` - The current response object.
687
+ - `allItems` - An array of the emitted items.
688
+ - `currentItems` - Items from the current response.
689
+
690
+ It should return an object representing Got options pointing to the next page. If there are no more pages, `false` should be returned.
691
+
692
+ For example, if you want to stop when the response contains less items than expected, you can use something like this:
693
+
694
+ ```js
695
+ const got = require('got');
696
+
697
+ (async () => {
698
+ const limit = 10;
699
+
700
+ const items = got.paginate('https://example.com/items', {
701
+ searchParams: {
702
+ limit,
703
+ offset: 0
704
+ },
705
+ _pagination: {
706
+ paginate: (response, allItems, currentItems) => {
707
+ const previousSearchParams = response.request.options.searchParams;
708
+ const {offset: previousOffset} = previousSearchParams;
709
+
710
+ if (currentItems.length < limit) {
711
+ return false;
712
+ }
713
+
714
+ return {
715
+ searchParams: {
716
+ ...previousSearchParams,
717
+ offset: previousOffset + limit,
718
+ }
719
+ };
720
+ }
721
+ }
722
+ });
723
+
724
+ console.log('Items from all pages:', items);
725
+ })();
726
+ ```
668
727
 
669
728
  ###### \_pagination.filter
670
729
 
671
730
  Type: `Function`\
672
- Default: `(item, allItems) => true`
731
+ Default: `(item, allItems, currentItems) => true`
673
732
 
674
733
  Checks whether the item should be emitted or not.
675
734
 
676
735
  ###### \_pagination.shouldContinue
677
736
 
678
737
  Type: `Function`\
679
- Default: `(item, allItems) => true`
738
+ Default: `(item, allItems, currentItems) => true`
680
739
 
681
740
  Checks whether the pagination should continue.
682
741
 
683
- For example, if you need to stop **before** emitting an entry with some flag, you should use `(item, allItems) => !item.flag`. If you want to stop **after** emitting the entry, you should use `(item, allItems) => allItems.some(entry => entry.flag)` instead.
742
+ For example, if you need to stop **before** emitting an entry with some flag, you should use `(item, allItems, currentItems) => !item.flag`. If you want to stop **after** emitting the entry, you should use `(item, allItems, currentItems) => allItems.some(entry => entry.flag)` instead.
684
743
 
685
744
  ###### \_pagination.countLimit
686
745
 
@@ -1012,6 +1071,14 @@ Options are deeply merged to a new object. The value of each key is determined a
1012
1071
  - If the parent property is a plain `object` too, both values are merged recursively into a new `object`.
1013
1072
  - Otherwise, only the new value is deeply cloned.
1014
1073
  - If the new property is an `Array`, it overwrites the old one with a deep clone of the new property.
1074
+ - Properties that are not enumerable, such as `context`, `body`, `json`, and `form`, will not be merged.
1075
+ ```js
1076
+ const a = {json: {cat: 'meow'}};
1077
+ const b = {json: {cow: 'moo'}};
1078
+
1079
+ got.mergeOptions(a, b);
1080
+ //=> {json: {cow: 'moo'}}
1081
+ ```
1015
1082
  - Otherwise, the new value is assigned to the key.
1016
1083
 
1017
1084
  #### got.defaults