keq 2.8.2 → 2.8.4

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,25 @@
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
+ ## [2.8.4](https://github.com/keq-request/keq/compare/v2.8.3...v2.8.4) (2024-10-20)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * esm improt error ([f23cece](https://github.com/keq-request/keq/commit/f23cece5d55c21a73deb9e9191cc52dafff35bc6))
11
+
12
+ ## [2.8.3](https://github.com/keq-request/keq/compare/v2.8.2...v2.8.3) (2024-10-20)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * esm import error ([97dbd78](https://github.com/keq-request/keq/commit/97dbd78eaa8b57a1a22e776347a90baf8f47335e))
18
+
19
+
20
+ ### Performance Improvements
21
+
22
+ * set context.retry to be deprecated ([e8b76a4](https://github.com/keq-request/keq/commit/e8b76a48a6e824892cb0eb3e8d97b36c11b07a3d))
23
+
5
24
  ## [2.8.2](https://github.com/keq-request/keq/compare/v2.8.1...v2.8.2) (2024-10-07)
6
25
 
7
26
 
package/README.md CHANGED
@@ -1,10 +1,8 @@
1
- <!-- title -->
2
1
  <p align="center" style="padding-top: 40px">
3
2
  <img src="./images/logo.svg?sanitize=true" width="120" alt="logo" />
4
3
  </p>
5
4
 
6
5
  <h1 align="center" style="text-align: center">KEQ</h1>
7
- <!-- title -->
8
6
 
9
7
  [npm]: https://www.npmjs.com/package/keq
10
8
 
@@ -14,7 +12,6 @@
14
12
  [![license](https://img.shields.io/npm/l/keq.svg?logo=github&style=for-the-badge)][npm]
15
13
  [![Codecov](https://img.shields.io/codecov/c/gh/keq-request/keq?logo=codecov&token=PLF0DT6869&style=for-the-badge)](https://codecov.io/gh/keq-request/keq)
16
14
 
17
- <!-- description -->
18
15
 
19
16
  [Fetch MDN]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch
20
17
  [Headers MDN]: https://developer.mozilla.org/en-US/docs/Web/API/Headers
@@ -22,12 +19,17 @@
22
19
  [FormData MDN]: https://developer.mozilla.org/en-US/docs/Web/API/FormData
23
20
  [URL MDN]: https://developer.mozilla.org/en-US/docs/Web/API/URL
24
21
 
22
+ [Document EN]: https://keq-request.github.io/guide/introduction
23
+ [Document CN]: https://keq-request.github.io/zh/guide/introduction
24
+
25
25
  Keq is a request API write by Typescript for flexibility, readability, and a low learning curve. It also works with Node.js!
26
26
  Keq wraps the Fetch APIs, adding chain calls and middleware functions.
27
27
 
28
- <!-- description -->
29
28
 
30
- ## Usage
29
+ [**Document**][Document EN] | [**中文文档**][Document CN]
30
+
31
+ ## Simple Usage
32
+
31
33
 
32
34
  <!-- usage -->
33
35
 
@@ -271,47 +273,6 @@ await request
271
273
  | 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
274
  | svg | image/svg+xml |
273
275
 
274
- ### resolve responseBody
275
-
276
- It was mentioned before that `Keq` will automatically parses the response body.
277
- And we can control the parsing behavior by calling `.resolveWith(method)`.
278
- There are multiple parsing methods for us to choose from
279
-
280
- | method | description |
281
- | :--------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
282
- | `.resolveWith('intelligent')` | It is the default method of `Keq`. This will returned `context.output` first if it exists. Otherwise return undefined when the response status is 204. Or return parsed response body according to the `Content-Type` of [`Response`][Response MDN]. |
283
- | `.resolveWith('response')` | Return [`Response`][Response MDN]. |
284
- | `.resolveWith('text')` | Return `response.text()`. |
285
- | `.resolveWith('json')` | Return `response.json()`. |
286
- | `.resolveWith('form-data')` | Return `response.formData()`. |
287
- | `.resolveWith('blob')` | Return `response.blob()`. |
288
- | `.resolveWith('array-buffer')` | Return `response.arrayBuffer()` |
289
-
290
- ### Request Retry
291
-
292
- No retry by default, invoke `.retry(retryTimes[, retryDelay[, retryOn]])` to set retry parameters
293
-
294
- | Parameter | Default | Description |
295
- | :--------- |:------- | :----------------------------------------------------------------------------------------------------------------------- |
296
- | retryTimes | `0` | Max number of retries per call. |
297
- | retryDelay |`0` | Initial value used to calculate the retry in milliseconds (This is still randomized following the randomization factor). |
298
- | retryOn | `(attempt, error) => !!error` | Will be called after request used to control whether the next retry runs. If it return `false`, stop retrying. |
299
-
300
- ```javascript
301
- import { request } from "keq";
302
-
303
- await request
304
- .get("http://test.com")
305
- .retry(2, 1000, (attempt, err, ctx) => {
306
- if (err) {
307
- console.log("an error throw");
308
- return true;
309
- }
310
-
311
- return false;
312
- });
313
- ```
314
-
315
276
  ### Set Request Redirect mode
316
277
 
317
278
  Follow redirect by default, invoke `.redirect(mode)` to set the redirect mode. Allow values are `"error"`, `"manual"` and `"follow"`.
@@ -337,274 +298,24 @@ await request
337
298
  .credentials("include");
338
299
  ```
339
300
 
340
- ### Keq Internal Options
341
-
342
- Invoke `.option()` add options.
343
-
344
- ```javascript
345
- import { request } from "keq";
346
-
347
- const response = await request
348
- .get("http://test.com")
349
- .option("middlewareOption", "value");
350
- ```
351
-
352
- Or as a single object:
353
-
354
- ```javascript
355
- import { request } from "keq";
356
-
357
- await request
358
- .get("http://test.com")
359
- .options({
360
- middlewareOption: "value",
361
- });
362
- ```
363
-
364
- | **Option** | **Description** |
365
- | :------------------------ | :------------------------------------------------------------------------------------------------------ |
366
- | `fetchAPI` | Replace the defaulted `fetch` function used by `Keq`. |
367
-
368
- <!-- ###### The options with **DEPRECATED** will be removed in next major version -->
369
-
370
- ### Timeout
371
-
372
- Keq has built-in timeout function.
373
-
374
- ```typescript
375
- await request
376
- .get("http://test.com")
377
- // 5000 milliseconds
378
- .timeout(5000)
379
- ```
380
-
381
- ### Flow Control
382
-
383
- Controlling the behavior of sending requests multiple times.
384
-
385
- #### Abort
386
-
387
- If the previous request was not completed, abort the last request.
388
-
389
- ```javascript
390
- import { request } from "keq";
391
-
392
- request
393
- .get("http://test.com/cat")
394
- // second args is the abort signal
395
- // this will abort the request with same signal
396
- // a unique signal will be generated, if not signal set.
397
- .followControl("abort", 'animal');
398
- .end()
399
-
400
- request
401
- .get("http://test.com/dog")
402
- // abort http://test.com/cat
403
- .followControl("abort", 'animal')
404
- .end()
405
- ```
406
-
407
- #### Serial
408
-
409
- The next request will not start until the previous request is completed.
410
-
411
- ```javascript
412
- import { request } from "keq";
413
-
414
- request
415
- .get("http://test.com/cat")
416
- // a unique signal will be generated, if signal is not set.
417
- .followControl("serial", 'animal');
418
- .end()
419
-
420
- // This request will be send after https://test.com/cat is complete
421
- request
422
- .get("http://test.com/dog")
423
- .followControl("serial", 'animal')
424
- .end()
425
- ```
426
-
427
- ### Middleware
428
-
429
- You can extend `Keq` by write/import middleware.
430
- A typical middleware might look a little like the following:
431
-
432
- ```javascript
433
- import { request } from "keq"
434
-
435
- const middleware = async (context, next) => {
436
- // equal to .retry(2)
437
- context.options.retryTimes = 2
438
-
439
- await next()
440
- const response = context.response
441
- if (!response) return
442
- const body = await response.json()
443
-
444
- // custom keq return type
445
- context.output = JSON.stringify(body)
446
- }
447
-
448
- // Global Middleware
449
- request
450
- .use(middleware)
451
-
452
- request
453
- .useRouter()
454
- /**
455
- * the middleware run when request url host is "example.com"
456
- */
457
- .host("example.com", middleware)
458
- /**
459
- * the middleware run when request url is location
460
- * It is usefully in browser.
461
- */
462
- .location(middleware)
463
- /**
464
- * the middleware run when pathname match `/api/service_name/**`.
465
- */
466
- .pathname("/api/service_name/**" middleware)
467
- /**
468
- * the middleware run when method is GET
469
- */
470
- .method('get', middleware)
471
- /**
472
- * used with keq-cli
473
- */
474
- .module('yourServiceName',middleware)
475
- /**
476
- * this middleware run when pathname start with '/api'
477
- */
478
- .route((ctx) => ctx.pathname.startsWith('/api'), middleware)
479
-
480
- await request
481
- .get("http://test.com")
482
- /**
483
- * the middleware run once
484
- */
485
- .use(middleware)
486
- ```
487
-
488
- #### request.use(middleware)
489
-
490
- Add an global middleware, The running order of middleware is related to the order of `.use()`
491
-
492
- #### request.useRouter()
493
-
494
- Middleware Router
495
-
496
- #### write an middleware
497
-
498
- Middleware should be an asnyc-function that accept two argument:
499
-
500
- | **Arguments** | **Description** |
501
- | :---------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
502
- | `ctx`(first argument) | Keq Context |
503
- | `next`(second argument) | Used to execute the next middleware. The last `next()` function will send request and bind the [`Response`][Response MDN] object to `context.res`. Don't forget to call `next()` unless you don't want to send the request. |
504
-
505
- Keq's context object has many parameters. The following lists all the built-in context attributes of `Keq`:
506
-
507
- | **Property** | **Type** |
508
- | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
509
- | `context.request` | Includes request options for [Fetch API][Fetch MDN]. |
510
- | `context.request.url` | [URL][URL MDN] Class |
511
- | `context.request.__url__` | Readonly [URL][URL MDN] Class that merged routeParams |
512
- | `context.request.method` | One of 'get', 'post', 'put', 'patch', 'head', 'delete'. |
513
- | `context.request.body` | Object, Array, string or undefined. |
514
- | `context.request.headers` | The [`Headers`][Headers MDN] Object. |
515
- | `context.request.routeParams` | The URL route params set by `.params(key, value)` |
516
- | `context.request.catch` | `catch` arguments in [Fetch API][Fetch MDN] |
517
- | `context.request.credentials` | `credentials` arguments in [Fetch API][Fetch MDN] |
518
- | `context.request.integrity` | `integrity` arguments in [Fetch API][Fetch MDN] |
519
- | `context.request.keepalive` | `keepalive` arguments in [Fetch API][Fetch MDN] |
520
- | `context.request.mode` | `mode` arguments in [Fetch API][Fetch MDN] |
521
- | `context.request.redirect` | `redirect` arguments in [Fetch API][Fetch MDN] |
522
- | `context.request.referrer` | `referrer` arguments in [Fetch API][Fetch MDN] |
523
- | `context.request.referrerPolicy` | `referrerPolicy` arguments in [Fetch API][Fetch MDN] |
524
- | `context.request.signal` | `signal` arguments in [Fetch API][Fetch MDN] |
525
- | `context.options` | It is an object includes request options.(example: `context.options.fetchAPI`). Middleware can get custom options from here. |
526
- | `context.res` | The origin [`Response`][Response MDN] Class. It will be undefined before run `await next()` or error throwed. |
527
- | `context.response` | Cloned from `ctx.res`. |
528
- | `context.output` | Custom return value of `await request()`。 It only take effect when `resolveWith` is not set or set to 'intelligent'. **This property is writeonly.** |
529
- | `content.identifier` | The unique identifier of the request's location in the code. It is used as default key of FlowControl and Cache.
530
-
531
- #### .useRouter()
532
-
533
- This is the utils used to route middleware.
534
-
535
- | **Method** |
536
- | :------------------------------------------------------- |
537
- | `.location(...middlewares)` |
538
- | `.method(method: string[, ...middlewares])` |
539
- | `.pathname(matcher: string \| Regexp[, ...middlewares])` |
540
- | `.host(host: string[, ...middlewares])` |
541
- | `.module(moduleName: string[, ...middlewares])` |
542
- | `.route(...middlewares)` |
543
-
544
- ### Create Request
545
-
546
- If you want to create a request instance, you can invoke `request.create()`:
547
-
548
- ```typescript
549
- import { createRequest } from "keq";
550
-
551
- const customRequest = createRequest();
552
-
553
- // Middleware only takes effect on customRequests
554
- customRequest.use(/** some middleware */);
555
-
556
- const body = await customRequest.get("http://test.com");
557
- ```
558
-
559
- > The gloabl request instance is created by `request.create()` too.
560
-
561
- option | description
562
- :----------------|:---------------
563
- initMiddlewares | `fetch`, `retry`, `flowController` are all implemented by middleware. you can customize the init middlewares to change behavior.
564
- baseOrigin | When sending a request without an `origin`, `origin` will set to `window.location.origin` in the browser and `"http://127.0.0.1"` in NodeJS.
565
-
566
- <!-- usage -->
567
-
568
- <!-- addition -->
569
-
570
- ## Q&A
571
-
572
- ### The diffirent between `.then()` and `.end()`
573
-
574
- Both `.then ()` and `.end ()` will send a request and return a Promise object.
575
- The difference between the two is that when called multiple times.
576
-
577
- `.then ()` actually sends only one request, no matter how many times it is called.
578
-
579
- `.end ()` will send a request for each call.
580
-
581
- ```javascript
582
- import { request } from "keq";
583
-
584
- const keq = request.get("http://test.com");
585
-
586
- keq.then(onfulfilled, onrejected);
587
- // Won't send request, and will use the last request result.
588
- keq.then(onfulfilled, onrejected);
589
-
590
- keq.end();
591
- keq.end();
592
- ```
593
-
594
- ### The diffirent between `ctx.res` and `ctx.response`
595
-
596
- `ctx.response` will allways return a new [`Response`][Response MDN] created by `ctx.res && ctx.res.clone()`. Sothat each middleware could calling `ctx.response.json()`, `ctx.response.text()`, `ctx.response.formData()`.
597
-
598
- 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`.
301
+ ### resolve responseBody
599
302
 
600
- ## See More
303
+ It was mentioned before that `Keq` will automatically parses the response body.
304
+ And we can control the parsing behavior by calling `.resolveWith(method)`.
305
+ There are multiple parsing methods for us to choose from
601
306
 
602
- Keq is inspired by SuperAgent and Koa.
307
+ | method | description |
308
+ | :--------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
309
+ | `.resolveWith('intelligent')` | It is the default method of `Keq`. This will returned `context.output` first if it exists. Otherwise return undefined when the response status is 204. Or return parsed response body according to the `Content-Type` of [`Response`][Response MDN]. |
310
+ | `.resolveWith('response')` | Return [`Response`][Response MDN]. |
311
+ | `.resolveWith('text')` | Return `response.text()`. |
312
+ | `.resolveWith('json')` | Return `response.json()`. |
313
+ | `.resolveWith('form-data')` | Return `response.formData()`. |
314
+ | `.resolveWith('blob')` | Return `response.blob()`. |
315
+ | `.resolveWith('array-buffer')` | Return `response.arrayBuffer()` |
603
316
 
604
- - [Superagent](https://visionmedia.github.io/superagent/#test-documentation)
605
- - [Koa](https://koajs.com/)
606
317
 
607
- <!-- addition -->
318
+ See more usage in the [Document][Document EN]
608
319
 
609
320
  ## Contributing & Development
610
321
 
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { isBrowser } from './is-browser';
2
+ import { isBrowser } from './is-browser.js';
3
3
  export function isBuffer(obj) {
4
4
  return isBrowser() ? false : Buffer.isBuffer(obj);
5
5
  }
@@ -1,2 +1,2 @@
1
- import type { KeqMiddleware } from '../types/keq-middleware';
1
+ import type { KeqMiddleware } from '../types/keq-middleware.js';
2
2
  export declare function fetchArgumentsMiddleware(): KeqMiddleware;
@@ -1,2 +1,2 @@
1
- import type { KeqMiddleware } from "../types/keq-middleware";
1
+ import type { KeqMiddleware } from "../types/keq-middleware.js";
2
2
  export declare function retryMiddleware(): KeqMiddleware;
@@ -1,4 +1,4 @@
1
- import type { KeqMiddleware } from "../types/keq-middleware";
1
+ import type { KeqMiddleware } from "../types/keq-middleware.js";
2
2
  import type { KeqRoute } from "../types/keq-route.js";
3
3
  export declare class KeqRouter {
4
4
  private readonly prependMiddlewares;
@@ -53,6 +53,8 @@ export interface KeqContext {
53
53
  global: KeqGlobal;
54
54
  /**
55
55
  * retry information, undefined is no retry
56
+ *
57
+ * @deprecated
56
58
  */
57
59
  retry?: {
58
60
  attempt: number;
@@ -1,4 +1,4 @@
1
- import { Exception } from '../exception/exception';
1
+ import { Exception } from '../exception/exception.js';
2
2
  export function composeRoute(routes) {
3
3
  if (!routes.length) {
4
4
  throw new Exception('At least one route');
@@ -4,16 +4,16 @@
4
4
  if (v !== undefined) module.exports = v;
5
5
  }
6
6
  else if (typeof define === "function" && define.amd) {
7
- define(["require", "exports", "./is-browser"], factory);
7
+ define(["require", "exports", "./is-browser.js"], factory);
8
8
  }
9
9
  })(function (require, exports) {
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.isBuffer = void 0;
13
13
  /* eslint-disable @typescript-eslint/no-explicit-any */
14
- const is_browser_1 = require("./is-browser");
14
+ const is_browser_js_1 = require("./is-browser.js");
15
15
  function isBuffer(obj) {
16
- return (0, is_browser_1.isBrowser)() ? false : Buffer.isBuffer(obj);
16
+ return (0, is_browser_js_1.isBrowser)() ? false : Buffer.isBuffer(obj);
17
17
  }
18
18
  exports.isBuffer = isBuffer;
19
19
  });
@@ -1,2 +1,2 @@
1
- import type { KeqMiddleware } from '../types/keq-middleware';
1
+ import type { KeqMiddleware } from '../types/keq-middleware.js';
2
2
  export declare function fetchArgumentsMiddleware(): KeqMiddleware;
@@ -1,2 +1,2 @@
1
- import type { KeqMiddleware } from "../types/keq-middleware";
1
+ import type { KeqMiddleware } from "../types/keq-middleware.js";
2
2
  export declare function retryMiddleware(): KeqMiddleware;
@@ -1,4 +1,4 @@
1
- import type { KeqMiddleware } from "../types/keq-middleware";
1
+ import type { KeqMiddleware } from "../types/keq-middleware.js";
2
2
  import type { KeqRoute } from "../types/keq-route.js";
3
3
  export declare class KeqRouter {
4
4
  private readonly prependMiddlewares;
@@ -53,6 +53,8 @@ export interface KeqContext {
53
53
  global: KeqGlobal;
54
54
  /**
55
55
  * retry information, undefined is no retry
56
+ *
57
+ * @deprecated
56
58
  */
57
59
  retry?: {
58
60
  attempt: number;
@@ -4,16 +4,16 @@
4
4
  if (v !== undefined) module.exports = v;
5
5
  }
6
6
  else if (typeof define === "function" && define.amd) {
7
- define(["require", "exports", "../exception/exception"], factory);
7
+ define(["require", "exports", "../exception/exception.js"], factory);
8
8
  }
9
9
  })(function (require, exports) {
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.composeRoute = void 0;
13
- const exception_1 = require("../exception/exception");
13
+ const exception_js_1 = require("../exception/exception.js");
14
14
  function composeRoute(routes) {
15
15
  if (!routes.length) {
16
- throw new exception_1.Exception('At least one route');
16
+ throw new exception_js_1.Exception('At least one route');
17
17
  }
18
18
  return async (ctx) => {
19
19
  const results = await Promise.all(routes.map((route) => route(ctx)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keq",
3
- "version": "2.8.2",
3
+ "version": "2.8.4",
4
4
  "description": "Request API write by Typescript for flexibility, readability, and a low learning curve.",
5
5
  "keywords": [
6
6
  "request",
@@ -68,7 +68,7 @@
68
68
  "typescript": "5.4.5",
69
69
  "typescript-transform-paths": "^3.4.7"
70
70
  },
71
- "packageManager": "pnpm@9.10.0",
71
+ "packageManager": "pnpm@9.12.2",
72
72
  "engines": {
73
73
  "node": ">=18.0.0"
74
74
  }