keq 1.9.0 → 1.10.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [1.10.1](https://www.github.com/keq-request/keq/compare/v1.10.0...v1.10.1) (2023-05-17)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * keq crashes when the response body does not match content-type ([f0bc15e](https://www.github.com/keq-request/keq/commit/f0bc15e3f02b76dfa975791f78d566eeccb32adc))
11
+
12
+ ## [1.10.0](https://www.github.com/keq-request/keq/compare/v1.9.0...v1.10.0) (2022-11-22)
13
+
14
+
15
+ ### Features
16
+
17
+ * add .mode() and .credentials() ([73f1cc2](https://www.github.com/keq-request/keq/commit/73f1cc202b34658474f325a3bbbdd4f876d1b4f2))
18
+ * add .redirect(mode) ([094549b](https://www.github.com/keq-request/keq/commit/094549b4ff6b8a64f9506a0f2b99ca8b51656b57))
19
+
5
20
  ## [1.9.0](https://www.github.com/keq-request/keq/compare/v1.8.9...v1.9.0) (2022-10-19)
6
21
 
7
22
 
package/README.md CHANGED
@@ -12,8 +12,6 @@
12
12
  [![dependencies](https://img.shields.io/david/keq-request/keq.svg?style=flat-square)](https://www.npmjs.com/package/keq)
13
13
  [![coveralls](https://img.shields.io/coveralls/github/keq-request/keq.svg?style=flat-square)](https://coveralls.io/github/keq-request/keq)
14
14
 
15
-
16
-
17
15
  <!-- description -->
18
16
  [Headers MDN]: https://developer.mozilla.org/en-US/docs/Web/API/Headers
19
17
  [Response MDN]: https://developer.mozilla.org/en-US/docs/Web/API/Response
@@ -86,7 +84,6 @@ await request.del('https://example.com/search')
86
84
  and return `body` of [`Response`][Response MDN] by defaulted.
87
85
  Add option `resolveWithFullResponse` to get the origin [`Response`][Response MDN] Object.
88
86
 
89
-
90
87
  ```javascript
91
88
  import { request } from 'keq'
92
89
 
@@ -97,8 +94,7 @@ const response = await request
97
94
  const body = await response.json()
98
95
  ```
99
96
 
100
- ###### `Keq` won't auto parse body, if response.status is 204. The HTTP 204 No Content success status response code indicates that server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation.
101
-
97
+ ###### `Keq` won't auto parse body, if response.status is 204. The HTTP 204 No Content success status response code indicates that server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation
102
98
 
103
99
  ### Setting header fields
104
100
 
@@ -175,7 +171,6 @@ await request
175
171
  .params({ searchKey: 'keq' })
176
172
  ```
177
173
 
178
-
179
174
  ### JSON Request
180
175
 
181
176
  A typical JSON POST request might look a little like the following,
@@ -203,6 +198,7 @@ await request.post('/user')
203
198
  .send({ name:"tj", pet:"tobi" })
204
199
  .send('pet=tobi')
205
200
  ```
201
+
206
202
  To send the data as `application/x-www-form-urlencoded` simply invoke `.type()` with "form".
207
203
  When passed an `string` to `.send()`, it will auto set `Content-Type` to `application/x-www-form-urlencoded`.
208
204
 
@@ -239,7 +235,6 @@ await request.post('/user')
239
235
  .attach('image', imageBlobOrBuffer)
240
236
  ```
241
237
 
242
-
243
238
  ### Setting the Content-Type
244
239
 
245
240
  The obvious solution is to use the .set() method:
@@ -271,7 +266,6 @@ form-data | multipart/form-data
271
266
  jpeg, bmp, apng, gif, x-icon, png, webp, tiff | image/jpeg, image/bmp, image/apng, image/gif, image/x-icon, image/png, image/webp, image/tiff
272
267
  svg | image/svg+xml
273
268
 
274
-
275
269
  ### Serializing request body
276
270
 
277
271
  Keq will automatically serialize JSON and forms.
@@ -315,6 +309,30 @@ await request
315
309
  .retry(2, 1000, () => {})
316
310
  ```
317
311
 
312
+ ### Set Request Redirect mode
313
+
314
+ Follow redirect by default, invoke `.redirect(mode)` to set the redirect mode. Allow values are `"error"`, `"manual"` and `"follow"`.
315
+
316
+ ```javascript
317
+ import { request } from 'keq'
318
+
319
+ await request
320
+ .get('http://test.com')
321
+ .redirect('manual')
322
+ ```
323
+
324
+ ### Set Request Credentials And Mode
325
+
326
+ These two parameters are used to control cross-domain requests.
327
+
328
+ ```javascript
329
+ import { request } from 'keq'
330
+
331
+ await request
332
+ .get('http://test.com')
333
+ .mode('cors')
334
+ .credentials('include')
335
+ ```
318
336
 
319
337
  ### Keq Internal Options
320
338
 
@@ -349,7 +367,7 @@ await request
349
367
  `resolveWithOriginalResponse` | **DEPRECATED** Get the origin [`Response`][Response MDN]
350
368
  `highWaterMark` | **DEPRECATED** The maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource. [See more in node-fetch](https://github.com/node-fetch/node-fetch#custom-highwatermark)
351
369
 
352
- ###### The options with **DEPRECATED** will be removed in next major version.
370
+ ###### The options with **DEPRECATED** will be removed in next major version
353
371
 
354
372
  ### Middleware
355
373
 
@@ -437,6 +455,7 @@ This is the utils used to mount middleware.
437
455
  **Function** | **Description**
438
456
  :--------------------------------------------|:---------------------------------------------
439
457
  `mount.location()` | Mount to Location. Useful in the browser
458
+ `mount.method(method: string) | Mount to the method.
440
459
  `mount.pathname(matcher: string \| Regexp)` | Mount to the pathname that match the `matcher`. `string` can be [`glob`](https://www.npmjs.com/package/picomatch).
441
460
  `mount.host(host: string)` | Mount to the Host.
442
461
 
@@ -444,7 +463,6 @@ This is the utils used to mount middleware.
444
463
 
445
464
  If you want to create a request instance, you can invoke `request.create()`:
446
465
 
447
-
448
466
  ```typescript
449
467
  import { request } from 'keq'
450
468
 
@@ -493,7 +511,6 @@ keq.end()
493
511
 
494
512
  What's more, The `.formData()` function isn't existed in `Response` returned by `node-fetch`. keq will append it to `Response` after clone, if in `NodeJS`.
495
513
 
496
-
497
514
  ## See More
498
515
 
499
516
  Keq is inspired by SuperAgent and Koa.
@@ -508,7 +525,6 @@ Support code development on patron.
508
525
  [![patron](https://c5.patreon.com/external/logo/become_a_patron_button@2x.png)](https://www.patreon.com/bePatron?u=22478507)
509
526
  <!-- addition -->
510
527
 
511
-
512
528
  ## Contributing & Development
513
529
 
514
530
  If there is any doubt, it is very welcome to discuss the issue together.
@@ -0,0 +1 @@
1
+ export declare const OUTPUT_PROPERTY: unique symbol;
@@ -0,0 +1 @@
1
+ export const OUTPUT_PROPERTY = Symbol('outputProperty');
package/es/src/keq.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { SerializeBodyFn, RequestMethod, Options, BuildInOptions, OptionsWithFullResponse, OptionsWithoutFullResponse, Middleware, MiddlewareMatcher, ShorthandContentType, RetryCallback } from "./types";
2
+ import { BuildInOptions, Middleware, MiddlewareMatcher, Options, OptionsWithFullResponse, OptionsWithoutFullResponse, RequestMethod, RetryCallback, SerializeBodyFn, ShorthandContentType } from "./types";
3
3
  import { KeqURL } from './keq-url';
4
4
  export declare class Keq<T> {
5
5
  private requestPromise?;
@@ -64,6 +64,9 @@ export declare class Keq<T> {
64
64
  */
65
65
  retry(retryTime: number, retryCallback?: RetryCallback): Keq<T>;
66
66
  retry(retryTime: number, initialRetryTime: number, retryCallback?: RetryCallback): Keq<T>;
67
+ redirect(mode: RequestRedirect): Keq<T>;
68
+ mode(mode: RequestMode): Keq<T>;
69
+ credentials(mode: RequestCredentials): Keq<T>;
67
70
  private fetch;
68
71
  private run;
69
72
  end(): Promise<T>;
package/es/src/keq.js CHANGED
@@ -7,12 +7,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { clone } from "./util/clone";
11
10
  import { Exception, FileExpectedException, OverwriteArrayBodyException, UnknownContentTypeException, } from "./exception";
12
- import { sleep, inferContentTypeByBody, fixContentType, getBoundaryByContentType, parseFormData, serializeBody, } from "./util";
11
+ import { File, Headers, Response, btoa, fetch, } from "./polyfill";
12
+ import { fixContentType, getBoundaryByContentType, inferContentTypeByBody, parseFormData, serializeBody, sleep, } from "./util";
13
+ import { clone } from "./util/clone";
14
+ import { OUTPUT_PROPERTY } from './constant';
15
+ import { compose, matchHost, matchMiddleware } from './middleware';
13
16
  import { isBlob, isBrowser, isFormData } from './util/is';
14
- import { Response, Headers, File, fetch, btoa, } from "./polyfill";
15
- import { matchHost, matchMiddleware, compose } from './middleware';
16
17
  export class Keq {
17
18
  constructor(urlObj, method, middlewares) {
18
19
  this.headers = new Headers();
@@ -213,6 +214,18 @@ export class Keq {
213
214
  }
214
215
  return this;
215
216
  }
217
+ redirect(mode) {
218
+ this.opts = Object.assign(Object.assign({}, this.opts), { redirect: mode });
219
+ return this;
220
+ }
221
+ mode(mode) {
222
+ this.opts = Object.assign(Object.assign({}, this.opts), { mode });
223
+ return this;
224
+ }
225
+ credentials(mode) {
226
+ this.opts = Object.assign(Object.assign({}, this.opts), { credentials: mode });
227
+ return this;
228
+ }
216
229
  fetch(ctx) {
217
230
  return __awaiter(this, void 0, void 0, function* () {
218
231
  const uri = ctx.request.url.toPath();
@@ -223,6 +236,7 @@ export class Keq {
223
236
  if (ctx.options.highWaterMark) {
224
237
  fetchOptions['highWaterMark'] = ctx.options.highWaterMark;
225
238
  }
239
+ // if (ctx.options.)
226
240
  const res = yield ctx.options.fetchAPI(uri, fetchOptions);
227
241
  function resFromData() {
228
242
  return __awaiter(this, void 0, void 0, function* () {
@@ -260,30 +274,10 @@ export class Keq {
260
274
  });
261
275
  },
262
276
  });
263
- if (ctx.options.resolveWithFullResponse) {
264
- ctx.output = ctx.response;
265
- }
266
- else if (ctx.options.resolveWithOriginalResponse) {
267
- ctx.output = ctx.res;
268
- }
269
- else if (res.status === 204) {
270
- // 204: NO CONTENT
271
- ctx.output = ctx.response && ctx.response.body;
272
- }
273
- else {
274
- const contentType = res.headers.get('content-type') || '';
275
- if (contentType.includes('application/json'))
276
- ctx.output = ctx.response && (yield ctx.response.json());
277
- else if (contentType.includes('multipart/form-data'))
278
- ctx.output = ctx.response && (yield ctx.response.formData());
279
- else if (contentType.includes('plain/text'))
280
- ctx.output = ctx.response && (yield ctx.response.text());
281
- else
282
- ctx.output = ctx.response && ctx.response.body;
283
- }
284
277
  });
285
278
  }
286
279
  run() {
280
+ var _a, _b;
287
281
  return __awaiter(this, void 0, void 0, function* () {
288
282
  const headers = new Headers();
289
283
  this.headers.forEach((value, key) => {
@@ -306,10 +300,19 @@ export class Keq {
306
300
  };
307
301
  if (this.opts.redirect)
308
302
  request.options.redirect = this.opts.redirect;
303
+ if (this.opts.mode)
304
+ request.options.mode = this.opts.mode;
305
+ if (this.opts.credentials)
306
+ request.options.credentials = this.opts.credentials;
309
307
  const ctx = {
310
308
  request,
311
309
  options: clone(Object.assign(Object.assign({}, this.opts), { fetchAPI: this.opts.fetchAPI || fetch })),
312
- output: undefined,
310
+ get output() {
311
+ throw new Exception('output property is write-only');
312
+ },
313
+ set output(value) {
314
+ this[OUTPUT_PROPERTY] = value;
315
+ },
313
316
  get url() {
314
317
  return this.request.url;
315
318
  },
@@ -347,7 +350,40 @@ export class Keq {
347
350
  const middleware = compose([...this.middlewares, this.fetch.bind(this)]);
348
351
  // eslint-disable-next-line @typescript-eslint/no-empty-function
349
352
  yield middleware(ctx, () => __awaiter(this, void 0, void 0, function* () { }));
350
- return ctx.output;
353
+ let output = ctx[OUTPUT_PROPERTY];
354
+ if (!(OUTPUT_PROPERTY in ctx)) {
355
+ if (ctx.options.resolveWithFullResponse) {
356
+ output = ctx.response;
357
+ }
358
+ else if (ctx.options.resolveWithOriginalResponse) {
359
+ output = ctx.res;
360
+ }
361
+ else if (((_a = ctx.response) === null || _a === void 0 ? void 0 : _a.status) === 204) {
362
+ // 204: NO CONTENT
363
+ output = ctx.response && ctx.response.body;
364
+ }
365
+ else {
366
+ const contentType = ((_b = ctx.response) === null || _b === void 0 ? void 0 : _b.headers.get('content-type')) || '';
367
+ try {
368
+ if (contentType.includes('application/json')) {
369
+ output = ctx.response && (yield ctx.response.json());
370
+ }
371
+ else if (contentType.includes('multipart/form-data')) {
372
+ output = ctx.response && (yield ctx.response.formData());
373
+ }
374
+ else if (contentType.includes('plain/text')) {
375
+ output = ctx.response && (yield ctx.response.text());
376
+ }
377
+ else {
378
+ output = ctx.response && ctx.response.body;
379
+ }
380
+ }
381
+ catch (e) {
382
+ console.warn('Failed to auto parse response body', e);
383
+ }
384
+ }
385
+ }
386
+ return output;
351
387
  });
352
388
  }
353
389
  end() {
@@ -1,7 +1,8 @@
1
+ import { OUTPUT_PROPERTY } from "../constant";
1
2
  import { KeqURL } from '../keq-url';
2
3
  import { KeqBody } from './keq-body';
3
- import { RequestMethod } from './request-method';
4
4
  import { Options } from './options';
5
+ import { RequestMethod } from './request-method';
5
6
  export interface RequestContext {
6
7
  url: KeqURL;
7
8
  method: RequestMethod;
@@ -14,6 +15,7 @@ export interface Context {
14
15
  res?: Response;
15
16
  /** the result get by user */
16
17
  output: any;
18
+ [OUTPUT_PROPERTY]?: any;
17
19
  options: Required<Pick<Options, 'fetchAPI'>> & Options;
18
20
  /** delegate res */
19
21
  response?: Response;
@@ -1 +1 @@
1
- export {};
1
+ import { OUTPUT_PROPERTY } from "../constant";
@@ -17,7 +17,19 @@ export interface BuildInOptions {
17
17
  *
18
18
  * @defaulted 'follow'
19
19
  */
20
- redirect?: 'follow' | 'error' | 'manual';
20
+ redirect?: RequestRedirect;
21
+ /**
22
+ * Indicates whether the user agent should send
23
+ * or receive cookies from the other domain in the case of cross-origin requests.
24
+ * https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials
25
+ */
26
+ credentials?: RequestCredentials;
27
+ /**
28
+ * Determine if cross-origin requests lead to valid responses,
29
+ * and which properties of the response are readable.
30
+ * https://developer.mozilla.org/en-US/docs/Web/API/Request/mode
31
+ */
32
+ mode?: RequestMode;
21
33
  /**
22
34
  * get original object, defaulted `false`
23
35
  * resolveWithFullResponse has a higher priority than resolveWithOriginalResponse
@@ -0,0 +1 @@
1
+ export declare const OUTPUT_PROPERTY: unique symbol;
@@ -0,0 +1,14 @@
1
+ (function (factory) {
2
+ if (typeof module === "object" && typeof module.exports === "object") {
3
+ var v = factory(require, exports);
4
+ if (v !== undefined) module.exports = v;
5
+ }
6
+ else if (typeof define === "function" && define.amd) {
7
+ define(["require", "exports"], factory);
8
+ }
9
+ })(function (require, exports) {
10
+ "use strict";
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.OUTPUT_PROPERTY = void 0;
13
+ exports.OUTPUT_PROPERTY = Symbol('outputProperty');
14
+ });
package/lib/src/keq.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { SerializeBodyFn, RequestMethod, Options, BuildInOptions, OptionsWithFullResponse, OptionsWithoutFullResponse, Middleware, MiddlewareMatcher, ShorthandContentType, RetryCallback } from "./types";
2
+ import { BuildInOptions, Middleware, MiddlewareMatcher, Options, OptionsWithFullResponse, OptionsWithoutFullResponse, RequestMethod, RetryCallback, SerializeBodyFn, ShorthandContentType } from "./types";
3
3
  import { KeqURL } from './keq-url';
4
4
  export declare class Keq<T> {
5
5
  private requestPromise?;
@@ -64,6 +64,9 @@ export declare class Keq<T> {
64
64
  */
65
65
  retry(retryTime: number, retryCallback?: RetryCallback): Keq<T>;
66
66
  retry(retryTime: number, initialRetryTime: number, retryCallback?: RetryCallback): Keq<T>;
67
+ redirect(mode: RequestRedirect): Keq<T>;
68
+ mode(mode: RequestMode): Keq<T>;
69
+ credentials(mode: RequestCredentials): Keq<T>;
67
70
  private fetch;
68
71
  private run;
69
72
  end(): Promise<T>;
package/lib/src/keq.js CHANGED
@@ -13,18 +13,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
13
13
  if (v !== undefined) module.exports = v;
14
14
  }
15
15
  else if (typeof define === "function" && define.amd) {
16
- define(["require", "exports", "./util/clone", "./exception", "./util", "./util/is", "./polyfill", "./middleware"], factory);
16
+ define(["require", "exports", "./exception", "./polyfill", "./util", "./util/clone", "./constant", "./middleware", "./util/is"], factory);
17
17
  }
18
18
  })(function (require, exports) {
19
19
  "use strict";
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.Keq = void 0;
22
- const clone_1 = require("./util/clone");
23
22
  const exception_1 = require("./exception");
24
- const util_1 = require("./util");
25
- const is_1 = require("./util/is");
26
23
  const polyfill_1 = require("./polyfill");
24
+ const util_1 = require("./util");
25
+ const clone_1 = require("./util/clone");
26
+ const constant_1 = require("./constant");
27
27
  const middleware_1 = require("./middleware");
28
+ const is_1 = require("./util/is");
28
29
  class Keq {
29
30
  constructor(urlObj, method, middlewares) {
30
31
  this.headers = new polyfill_1.Headers();
@@ -225,6 +226,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
225
226
  }
226
227
  return this;
227
228
  }
229
+ redirect(mode) {
230
+ this.opts = Object.assign(Object.assign({}, this.opts), { redirect: mode });
231
+ return this;
232
+ }
233
+ mode(mode) {
234
+ this.opts = Object.assign(Object.assign({}, this.opts), { mode });
235
+ return this;
236
+ }
237
+ credentials(mode) {
238
+ this.opts = Object.assign(Object.assign({}, this.opts), { credentials: mode });
239
+ return this;
240
+ }
228
241
  fetch(ctx) {
229
242
  return __awaiter(this, void 0, void 0, function* () {
230
243
  const uri = ctx.request.url.toPath();
@@ -235,6 +248,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
235
248
  if (ctx.options.highWaterMark) {
236
249
  fetchOptions['highWaterMark'] = ctx.options.highWaterMark;
237
250
  }
251
+ // if (ctx.options.)
238
252
  const res = yield ctx.options.fetchAPI(uri, fetchOptions);
239
253
  function resFromData() {
240
254
  return __awaiter(this, void 0, void 0, function* () {
@@ -272,30 +286,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
272
286
  });
273
287
  },
274
288
  });
275
- if (ctx.options.resolveWithFullResponse) {
276
- ctx.output = ctx.response;
277
- }
278
- else if (ctx.options.resolveWithOriginalResponse) {
279
- ctx.output = ctx.res;
280
- }
281
- else if (res.status === 204) {
282
- // 204: NO CONTENT
283
- ctx.output = ctx.response && ctx.response.body;
284
- }
285
- else {
286
- const contentType = res.headers.get('content-type') || '';
287
- if (contentType.includes('application/json'))
288
- ctx.output = ctx.response && (yield ctx.response.json());
289
- else if (contentType.includes('multipart/form-data'))
290
- ctx.output = ctx.response && (yield ctx.response.formData());
291
- else if (contentType.includes('plain/text'))
292
- ctx.output = ctx.response && (yield ctx.response.text());
293
- else
294
- ctx.output = ctx.response && ctx.response.body;
295
- }
296
289
  });
297
290
  }
298
291
  run() {
292
+ var _a, _b;
299
293
  return __awaiter(this, void 0, void 0, function* () {
300
294
  const headers = new polyfill_1.Headers();
301
295
  this.headers.forEach((value, key) => {
@@ -318,10 +312,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
318
312
  };
319
313
  if (this.opts.redirect)
320
314
  request.options.redirect = this.opts.redirect;
315
+ if (this.opts.mode)
316
+ request.options.mode = this.opts.mode;
317
+ if (this.opts.credentials)
318
+ request.options.credentials = this.opts.credentials;
321
319
  const ctx = {
322
320
  request,
323
321
  options: (0, clone_1.clone)(Object.assign(Object.assign({}, this.opts), { fetchAPI: this.opts.fetchAPI || polyfill_1.fetch })),
324
- output: undefined,
322
+ get output() {
323
+ throw new exception_1.Exception('output property is write-only');
324
+ },
325
+ set output(value) {
326
+ this[constant_1.OUTPUT_PROPERTY] = value;
327
+ },
325
328
  get url() {
326
329
  return this.request.url;
327
330
  },
@@ -359,7 +362,40 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
359
362
  const middleware = (0, middleware_1.compose)([...this.middlewares, this.fetch.bind(this)]);
360
363
  // eslint-disable-next-line @typescript-eslint/no-empty-function
361
364
  yield middleware(ctx, () => __awaiter(this, void 0, void 0, function* () { }));
362
- return ctx.output;
365
+ let output = ctx[constant_1.OUTPUT_PROPERTY];
366
+ if (!(constant_1.OUTPUT_PROPERTY in ctx)) {
367
+ if (ctx.options.resolveWithFullResponse) {
368
+ output = ctx.response;
369
+ }
370
+ else if (ctx.options.resolveWithOriginalResponse) {
371
+ output = ctx.res;
372
+ }
373
+ else if (((_a = ctx.response) === null || _a === void 0 ? void 0 : _a.status) === 204) {
374
+ // 204: NO CONTENT
375
+ output = ctx.response && ctx.response.body;
376
+ }
377
+ else {
378
+ const contentType = ((_b = ctx.response) === null || _b === void 0 ? void 0 : _b.headers.get('content-type')) || '';
379
+ try {
380
+ if (contentType.includes('application/json')) {
381
+ output = ctx.response && (yield ctx.response.json());
382
+ }
383
+ else if (contentType.includes('multipart/form-data')) {
384
+ output = ctx.response && (yield ctx.response.formData());
385
+ }
386
+ else if (contentType.includes('plain/text')) {
387
+ output = ctx.response && (yield ctx.response.text());
388
+ }
389
+ else {
390
+ output = ctx.response && ctx.response.body;
391
+ }
392
+ }
393
+ catch (e) {
394
+ console.warn('Failed to auto parse response body', e);
395
+ }
396
+ }
397
+ }
398
+ return output;
363
399
  });
364
400
  }
365
401
  end() {
@@ -1,7 +1,8 @@
1
+ import { OUTPUT_PROPERTY } from "../constant";
1
2
  import { KeqURL } from '../keq-url';
2
3
  import { KeqBody } from './keq-body';
3
- import { RequestMethod } from './request-method';
4
4
  import { Options } from './options';
5
+ import { RequestMethod } from './request-method';
5
6
  export interface RequestContext {
6
7
  url: KeqURL;
7
8
  method: RequestMethod;
@@ -14,6 +15,7 @@ export interface Context {
14
15
  res?: Response;
15
16
  /** the result get by user */
16
17
  output: any;
18
+ [OUTPUT_PROPERTY]?: any;
17
19
  options: Required<Pick<Options, 'fetchAPI'>> & Options;
18
20
  /** delegate res */
19
21
  response?: Response;
@@ -4,9 +4,10 @@
4
4
  if (v !== undefined) module.exports = v;
5
5
  }
6
6
  else if (typeof define === "function" && define.amd) {
7
- define(["require", "exports"], factory);
7
+ define(["require", "exports", "../constant"], factory);
8
8
  }
9
9
  })(function (require, exports) {
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
+ const constant_1 = require("../constant");
12
13
  });
@@ -17,7 +17,19 @@ export interface BuildInOptions {
17
17
  *
18
18
  * @defaulted 'follow'
19
19
  */
20
- redirect?: 'follow' | 'error' | 'manual';
20
+ redirect?: RequestRedirect;
21
+ /**
22
+ * Indicates whether the user agent should send
23
+ * or receive cookies from the other domain in the case of cross-origin requests.
24
+ * https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials
25
+ */
26
+ credentials?: RequestCredentials;
27
+ /**
28
+ * Determine if cross-origin requests lead to valid responses,
29
+ * and which properties of the response are readable.
30
+ * https://developer.mozilla.org/en-US/docs/Web/API/Request/mode
31
+ */
32
+ mode?: RequestMode;
21
33
  /**
22
34
  * get original object, defaulted `false`
23
35
  * resolveWithFullResponse has a higher priority than resolveWithOriginalResponse
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "main": "lib/src/index.js",
4
4
  "module": "es/src/index.js",
5
5
  "types": "lib/src/index.d.ts",
6
- "version": "1.9.0",
6
+ "version": "1.10.1",
7
7
  "license": "MIT",
8
8
  "scripts": {
9
9
  "test": "npm run clean && npm run build:test && nyc ava",