keq 2.0.8 → 2.1.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 (100) hide show
  1. package/.vscode/settings.json +5 -0
  2. package/CHANGELOG.md +8 -0
  3. package/README.md +90 -21
  4. package/dist/esm/src/core.d.ts +2 -1
  5. package/dist/esm/src/core.js +14 -2
  6. package/dist/esm/src/create-request.js +19 -40
  7. package/dist/esm/src/index.d.ts +21 -13
  8. package/dist/esm/src/index.js +11 -4
  9. package/dist/esm/src/keq.d.ts +4 -2
  10. package/dist/esm/src/keq.js +13 -0
  11. package/dist/esm/src/middlewares/abort-flow-control-middleware.d.ts +2 -0
  12. package/dist/esm/src/middlewares/abort-flow-control-middleware.js +26 -0
  13. package/dist/esm/src/middlewares/fetch-arguments-middleware.js +9 -0
  14. package/dist/esm/src/middlewares/serial-flow-control-middleware.d.ts +2 -0
  15. package/dist/esm/src/middlewares/serial-flow-control-middleware.js +20 -0
  16. package/dist/esm/src/router/keq-host-route.d.ts +2 -0
  17. package/dist/esm/src/router/keq-host-route.js +3 -0
  18. package/dist/esm/src/router/keq-location-route.d.ts +2 -0
  19. package/dist/esm/src/router/keq-location-route.js +4 -0
  20. package/dist/esm/src/router/keq-method-route.d.ts +2 -0
  21. package/dist/esm/src/router/keq-method-route.js +3 -0
  22. package/dist/esm/src/router/keq-module-route.d.ts +2 -0
  23. package/dist/esm/src/router/keq-module-route.js +7 -0
  24. package/dist/esm/src/router/keq-pathname-route.d.ts +2 -0
  25. package/dist/esm/src/router/keq-pathname-route.js +4 -0
  26. package/dist/esm/src/router/keq-router.d.ts +10 -5
  27. package/dist/esm/src/router/keq-router.js +34 -5
  28. package/dist/esm/src/types/keq-context.d.ts +2 -0
  29. package/dist/esm/src/types/keq-flow-control.d.ts +7 -0
  30. package/dist/esm/src/types/keq-options.d.ts +3 -0
  31. package/dist/esm/src/types/keq-request.d.ts +4 -4
  32. package/dist/esm/src/types/keq-route.d.ts +2 -0
  33. package/dist/esm/src/types/keq-route.js +1 -0
  34. package/dist/esm/src/{middleware.d.ts → util/compose-middleware.d.ts} +1 -1
  35. package/dist/esm/src/{middleware.js → util/compose-middleware.js} +1 -2
  36. package/dist/esm/src/util/compose-route.d.ts +2 -0
  37. package/dist/esm/src/util/compose-route.js +10 -0
  38. package/dist/esm/src/util/get-unique-code-identifier.d.ts +1 -0
  39. package/dist/esm/src/util/get-unique-code-identifier.js +7 -0
  40. package/dist/umd/src/core.d.ts +2 -1
  41. package/dist/umd/src/core.js +16 -4
  42. package/dist/umd/src/create-request.js +20 -41
  43. package/dist/umd/src/index.d.ts +21 -13
  44. package/dist/umd/src/index.js +24 -10
  45. package/dist/umd/src/keq.d.ts +4 -2
  46. package/dist/umd/src/keq.js +14 -1
  47. package/dist/umd/src/middlewares/abort-flow-control-middleware.d.ts +2 -0
  48. package/dist/umd/src/middlewares/abort-flow-control-middleware.js +40 -0
  49. package/dist/umd/src/middlewares/fetch-arguments-middleware.js +9 -0
  50. package/dist/umd/src/middlewares/serial-flow-control-middleware.d.ts +2 -0
  51. package/dist/umd/src/middlewares/serial-flow-control-middleware.js +57 -0
  52. package/dist/umd/src/router/keq-host-route.d.ts +2 -0
  53. package/dist/umd/src/router/keq-host-route.js +17 -0
  54. package/dist/umd/src/router/keq-location-route.d.ts +2 -0
  55. package/dist/umd/src/router/keq-location-route.js +18 -0
  56. package/dist/umd/src/router/keq-method-route.d.ts +2 -0
  57. package/dist/umd/src/router/keq-method-route.js +17 -0
  58. package/dist/umd/src/router/keq-module-route.d.ts +2 -0
  59. package/dist/umd/src/router/keq-module-route.js +21 -0
  60. package/dist/umd/src/router/keq-pathname-route.d.ts +2 -0
  61. package/dist/umd/src/router/keq-pathname-route.js +18 -0
  62. package/dist/umd/src/router/keq-router.d.ts +10 -5
  63. package/dist/umd/src/router/keq-router.js +35 -6
  64. package/dist/umd/src/types/keq-context.d.ts +2 -0
  65. package/dist/umd/src/types/keq-flow-control.d.ts +7 -0
  66. package/dist/umd/src/types/keq-options.d.ts +3 -0
  67. package/dist/umd/src/types/keq-request.d.ts +4 -4
  68. package/dist/umd/src/types/keq-route.d.ts +2 -0
  69. package/dist/umd/src/types/keq-route.js +12 -0
  70. package/dist/umd/src/{middleware.d.ts → util/compose-middleware.d.ts} +1 -1
  71. package/dist/umd/src/{middleware.js → util/compose-middleware.js} +2 -3
  72. package/dist/umd/src/util/compose-route.d.ts +2 -0
  73. package/dist/umd/src/util/compose-route.js +24 -0
  74. package/dist/umd/src/util/get-unique-code-identifier.d.ts +1 -0
  75. package/dist/umd/src/util/get-unique-code-identifier.js +21 -0
  76. package/package.json +3 -2
  77. package/dist/esm/src/router/keq-host-router.d.ts +0 -7
  78. package/dist/esm/src/router/keq-host-router.js +0 -19
  79. package/dist/esm/src/router/keq-location-router.d.ts +0 -6
  80. package/dist/esm/src/router/keq-location-router.js +0 -18
  81. package/dist/esm/src/router/keq-method-router.d.ts +0 -8
  82. package/dist/esm/src/router/keq-method-router.js +0 -19
  83. package/dist/esm/src/router/keq-module-router.d.ts +0 -7
  84. package/dist/esm/src/router/keq-module-router.js +0 -23
  85. package/dist/esm/src/router/keq-pathname-router.d.ts +0 -7
  86. package/dist/esm/src/router/keq-pathname-router.js +0 -20
  87. package/dist/esm/src/types/router-map.d.ts +0 -9
  88. package/dist/umd/src/router/keq-host-router.d.ts +0 -7
  89. package/dist/umd/src/router/keq-host-router.js +0 -33
  90. package/dist/umd/src/router/keq-location-router.d.ts +0 -6
  91. package/dist/umd/src/router/keq-location-router.js +0 -32
  92. package/dist/umd/src/router/keq-method-router.d.ts +0 -8
  93. package/dist/umd/src/router/keq-method-router.js +0 -33
  94. package/dist/umd/src/router/keq-module-router.d.ts +0 -7
  95. package/dist/umd/src/router/keq-module-router.js +0 -37
  96. package/dist/umd/src/router/keq-pathname-router.d.ts +0 -7
  97. package/dist/umd/src/router/keq-pathname-router.js +0 -34
  98. package/dist/umd/src/types/router-map.d.ts +0 -9
  99. /package/dist/esm/src/types/{router-map.js → keq-flow-control.js} +0 -0
  100. /package/dist/umd/src/types/{router-map.js → keq-flow-control.js} +0 -0
@@ -0,0 +1,5 @@
1
+ {
2
+ "[markdown]": {
3
+ "editor.formatOnSave": false
4
+ }
5
+ }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
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.1.0](https://github.com/keq-request/keq/compare/v2.0.8...v2.1.0) (2024-01-05)
6
+
7
+
8
+ ### Features
9
+
10
+ * add .route to Router ([dc27057](https://github.com/keq-request/keq/commit/dc27057b3c85ab8a52fe51892f4aa5792f53898d))
11
+ * flow control function for sending multiple requests ([5d24adf](https://github.com/keq-request/keq/commit/5d24adffaf26181ebd296b97ea3062514354f7e0))
12
+
5
13
  ## [2.0.8](https://github.com/keq-request/keq/compare/v2.0.7...v2.0.8) (2024-01-02)
6
14
 
7
15
 
package/README.md CHANGED
@@ -113,10 +113,12 @@ You may also pass an object or `Headers` to set several fields in a single call:
113
113
  ```javascript
114
114
  import { request } from "keq";
115
115
 
116
- await request.get("/search").set({
117
- "X-Origin-Host": "https://example.com",
118
- Accept: "application/json",
119
- });
116
+ await request
117
+ .get("/search")
118
+ .set({
119
+ "X-Origin-Host": "https://example.com",
120
+ Accept: "application/json",
121
+ });
120
122
  ```
121
123
 
122
124
  ### Request query
@@ -153,7 +155,9 @@ The follwing will produce the path `/search/keq`.
153
155
  ```javascript
154
156
  import { request } from "keq";
155
157
 
156
- await request.get("/search/:searchKey").params("searchKey", "keq");
158
+ await request
159
+ .get("/search/:searchKey")
160
+ .params("searchKey", "keq");
157
161
  ```
158
162
 
159
163
  Or as a single object:
@@ -161,7 +165,9 @@ Or as a single object:
161
165
  ```javascript
162
166
  import { request } from "keq";
163
167
 
164
- await request.get("/search/:searchKey").params({ searchKey: "keq" });
168
+ await request
169
+ .get("/search/:searchKey")
170
+ .params({ searchKey: "keq" });
165
171
  ```
166
172
 
167
173
  ### JSON Request
@@ -251,7 +257,9 @@ or simply the extension name such as "xml", "json", "png", etc:
251
257
  ```javascript
252
258
  import { request } from "keq";
253
259
 
254
- await request.post("/user").type("json");
260
+ await request
261
+ .post("/user")
262
+ .type("json");
255
263
  ```
256
264
 
257
265
  | **Shorthand** | **Mime Type** |
@@ -276,14 +284,16 @@ No retry by default, invoke `.retry(retryTimes[, retryDelay[, retryOn]])` to set
276
284
  ```javascript
277
285
  import { request } from "keq";
278
286
 
279
- await request.get("http://test.com").retry(2, 1000, (attempt, err, ctx) => {
280
- if (err) {
281
- console.log("an error throw");
282
- return true;
283
- }
284
-
285
- return false;
286
- });
287
+ await request
288
+ .get("http://test.com")
289
+ .retry(2, 1000, (attempt, err, ctx) => {
290
+ if (err) {
291
+ console.log("an error throw");
292
+ return true;
293
+ }
294
+
295
+ return false;
296
+ });
287
297
  ```
288
298
 
289
299
  ### Set Request Redirect mode
@@ -293,7 +303,9 @@ Follow redirect by default, invoke `.redirect(mode)` to set the redirect mode. A
293
303
  ```javascript
294
304
  import { request } from "keq";
295
305
 
296
- await request.get("http://test.com").redirect("manual");
306
+ await request
307
+ .get("http://test.com")
308
+ .redirect("manual");
297
309
  ```
298
310
 
299
311
  ### Set Request Credentials And Mode
@@ -303,7 +315,10 @@ These two parameters are used to control cross-domain requests.
303
315
  ```javascript
304
316
  import { request } from "keq";
305
317
 
306
- await request.get("http://test.com").mode("cors").credentials("include");
318
+ await request
319
+ .get("http://test.com")
320
+ .mode("cors")
321
+ .credentials("include");
307
322
  ```
308
323
 
309
324
  ### Keq Internal Options
@@ -328,10 +343,12 @@ Or as a single object:
328
343
  ```javascript
329
344
  import { request } from "keq";
330
345
 
331
- await request.get("http://test.com").options({
332
- resolveWithFullResponse: true,
333
- middlewareOption: "value",
334
- });
346
+ await request
347
+ .get("http://test.com")
348
+ .options({
349
+ resolveWithFullResponse: true,
350
+ middlewareOption: "value",
351
+ });
335
352
  ```
336
353
 
337
354
  | **Option** | **Description** |
@@ -341,6 +358,53 @@ await request.get("http://test.com").options({
341
358
 
342
359
  <!-- ###### The options with **DEPRECATED** will be removed in next major version -->
343
360
 
361
+ ### Flow Control
362
+
363
+ Controlling the behavior of sending requests multiple times.
364
+
365
+ #### Abort
366
+
367
+ If the previous request was not completed, abort the last request.
368
+
369
+ ```javascript
370
+ import { request } from "keq";
371
+
372
+ request
373
+ .get("http://test.com/cat")
374
+ // second args is the abort signal
375
+ // this will abort the request with same signal
376
+ // a unique signal will be generated, if not signal set.
377
+ .followControl("abort", 'animal');
378
+ .end()
379
+
380
+ request
381
+ .get("http://test.com/dog")
382
+ // abort http://test.com/cat
383
+ .followControl("abort", 'animal')
384
+ .end()
385
+ ```
386
+
387
+ #### Serial
388
+
389
+ The next request will not start until the previous request is completed.
390
+
391
+ ```javascript
392
+ import { request } from "keq";
393
+
394
+ request
395
+ .get("http://test.com/cat")
396
+ // a unique signal will be generated, if signal is not set.
397
+ .followControl("serial", 'animal');
398
+ .end()
399
+
400
+ // This request will be send after https://test.com/cat is complete
401
+ request
402
+ .get("http://test.com/dog")
403
+ .followControl("serial", 'animal')
404
+ .end()
405
+ ```
406
+
407
+
344
408
  ### Middleware
345
409
 
346
410
  You can extend `Keq` by write/import middleware.
@@ -389,6 +453,10 @@ request
389
453
  * used with keq-cli
390
454
  */
391
455
  .module('yourServiceName',middleware)
456
+ /**
457
+ * this middleware run when pathname start with '/api'
458
+ */
459
+ .route((ctx) => ctx.pathname.startsWith('/api'), middleware)
392
460
 
393
461
  await request
394
462
  .get("http://test.com")
@@ -450,6 +518,7 @@ This is the utils used to route middleware.
450
518
  | `.pathname(matcher: string \| Regexp[, ...middlewares])` |
451
519
  | `.host(host: string[, ...middlewares])` |
452
520
  | `.module(moduleName: string[, ...middlewares])` |
521
+ | `.route(...middlewares)` |
453
522
 
454
523
  ### Create Request
455
524
 
@@ -9,10 +9,11 @@ import { KeqRequestInit } from './types/keq-request-init';
9
9
  export declare class Core<T> {
10
10
  private requestPromise?;
11
11
  protected requestContext: KeqRequestContext;
12
+ protected __global__: Record<string, any>;
12
13
  protected __prepend_middlewares__: KeqMiddleware[];
13
14
  protected __append_middlewares__: KeqMiddleware[];
14
15
  protected __options__: KeqOptions;
15
- constructor(url: (URL | globalThis.URL), init: KeqRequestInit);
16
+ constructor(url: (URL | globalThis.URL), init: KeqRequestInit, global?: Record<string, any>);
16
17
  prependMiddlewares(...middlewares: KeqMiddleware[]): this;
17
18
  appendMiddlewares(...middlewares: KeqMiddleware[]): this;
18
19
  private run;
@@ -2,7 +2,7 @@ import { URL } from 'whatwg-url';
2
2
  import { Exception } from "./exception/exception";
3
3
  import { clone } from "./util/clone";
4
4
  import { OUTPUT_PROPERTY } from './constant';
5
- import { composeMiddleware } from './middleware';
5
+ import { composeMiddleware } from './util/compose-middleware';
6
6
  import { shadowClone } from './util/shadow-clone';
7
7
  /**
8
8
  * @description Keq 核心 API,发送请求必要的原子化的API
@@ -10,10 +10,12 @@ import { shadowClone } from './util/shadow-clone';
10
10
  export class Core {
11
11
  requestPromise;
12
12
  requestContext;
13
+ __global__;
13
14
  __prepend_middlewares__ = [];
14
15
  __append_middlewares__ = [];
15
16
  __options__ = { resolveWithFullResponse: false };
16
- constructor(url, init) {
17
+ constructor(url, init, global = {}) {
18
+ this.__global__ = global;
17
19
  this.requestContext = {
18
20
  method: 'get',
19
21
  headers: new Headers(),
@@ -42,11 +44,21 @@ export class Core {
42
44
  headers,
43
45
  routeParams: shadowClone(this.requestContext.routeParams),
44
46
  body: clone(this.requestContext.body),
47
+ cache: this.requestContext.cache,
48
+ credentials: this.requestContext.credentials,
49
+ integrity: this.requestContext.integrity,
50
+ keepalive: this.requestContext.keepalive,
51
+ mode: this.requestContext.mode,
52
+ redirect: this.requestContext.redirect,
53
+ referrer: this.requestContext.referrer,
54
+ referrerPolicy: this.requestContext.referrerPolicy,
55
+ signal: this.requestContext.signal,
45
56
  };
46
57
  const options = shadowClone(this.__options__);
47
58
  const ctx = {
48
59
  request: requestContext,
49
60
  options,
61
+ global: this.__global__,
50
62
  get output() {
51
63
  throw new Exception('output property is write-only');
52
64
  },
@@ -1,62 +1,41 @@
1
1
  /* eslint-disable @typescript-eslint/no-unsafe-return */
2
2
  import { URL } from 'whatwg-url';
3
- import { KeqHostRouter } from "./router/keq-host-router";
4
- import { KeqLocationRouter } from "./router/keq-location-router";
5
- import { KeqMethodRouter } from "./router/keq-method-router";
6
- import { KeqModuleRouter } from "./router/keq-module-router";
7
- import { KeqPathnameRouter } from "./router/keq-pathname-router";
8
3
  import { isBrowser } from './is/is-browser';
9
4
  import { Keq } from './keq';
5
+ import { abortFlowControlMiddleware } from './middlewares/abort-flow-control-middleware.js';
10
6
  import { fetchArgumentsMiddleware } from './middlewares/fetch-arguments-middleware';
11
7
  import { fetchMiddleware } from './middlewares/fetch-middleware';
12
8
  import { proxyResponseMiddleware } from './middlewares/proxy-response-middleware';
13
9
  import { retryMiddleware } from './middlewares/retry-middleware';
10
+ import { serialFlowControlMiddleware } from './middlewares/serial-flow-control-middleware.js';
11
+ import { KeqRouter } from './router/keq-router.js';
14
12
  export function createRequest(options) {
15
13
  let baseOrigin = options?.baseOrigin;
16
14
  if (isBrowser() && !baseOrigin)
17
15
  baseOrigin = location.origin;
18
16
  const appendMiddlewares = options?.initMiddlewares ? [...options.initMiddlewares] : [
17
+ serialFlowControlMiddleware(),
18
+ abortFlowControlMiddleware(),
19
19
  proxyResponseMiddleware(),
20
20
  fetchArgumentsMiddleware(),
21
21
  retryMiddleware(),
22
22
  fetchMiddleware(),
23
23
  ];
24
24
  const prependMiddlewares = [];
25
+ /**
26
+ * share data between requests, used to implement flowControl
27
+ * @description 跨请求共享数据,用于实现 flowControl的功能
28
+ */
29
+ const global = {};
25
30
  const formatUrl = (url) => {
26
31
  if (typeof url === 'string') {
27
32
  return new URL(url, baseOrigin);
28
33
  }
29
34
  return new URL(url.href);
30
35
  };
31
- const routerMap = {
32
- host: (host, ...middlewares) => {
33
- const route = new KeqHostRouter(host, middlewares);
34
- prependMiddlewares.push(route.routes());
35
- return routerMap;
36
- },
37
- method: (method, ...middlewares) => {
38
- const route = new KeqMethodRouter(method, middlewares);
39
- prependMiddlewares.push(route.routes());
40
- return routerMap;
41
- },
42
- pathname: (pathname, ...middlewares) => {
43
- const route = new KeqPathnameRouter(pathname, middlewares);
44
- prependMiddlewares.push(route.routes());
45
- return routerMap;
46
- },
47
- location: (...middlewares) => {
48
- const route = new KeqLocationRouter(middlewares);
49
- prependMiddlewares.push(route.routes());
50
- return routerMap;
51
- },
52
- module: (moduleName, ...middlewares) => {
53
- const route = new KeqModuleRouter(moduleName, middlewares);
54
- prependMiddlewares.push(route.routes());
55
- return routerMap;
56
- },
57
- };
36
+ const router = new KeqRouter(prependMiddlewares);
58
37
  const request = function (url, init) {
59
- const keq = new Keq(formatUrl(url), init);
38
+ const keq = new Keq(formatUrl(url), { ...init }, global);
60
39
  keq.appendMiddlewares(...appendMiddlewares);
61
40
  keq.prependMiddlewares(...prependMiddlewares);
62
41
  return keq;
@@ -65,41 +44,41 @@ export function createRequest(options) {
65
44
  baseOrigin = origin;
66
45
  };
67
46
  request.useRouter = function useRouter() {
68
- return routerMap;
47
+ return router;
69
48
  };
70
49
  request.get = function (url) {
71
- const keq = new Keq(formatUrl(url), { method: 'get' });
50
+ const keq = new Keq(formatUrl(url), { method: 'get' }, global);
72
51
  keq.appendMiddlewares(...appendMiddlewares);
73
52
  keq.prependMiddlewares(...prependMiddlewares);
74
53
  return keq;
75
54
  };
76
55
  request.put = function (url) {
77
- const keq = new Keq(formatUrl(url), { method: 'put' });
56
+ const keq = new Keq(formatUrl(url), { method: 'put' }, global);
78
57
  keq.appendMiddlewares(...appendMiddlewares);
79
58
  keq.prependMiddlewares(...prependMiddlewares);
80
59
  return keq;
81
60
  };
82
61
  request.delete = function (url) {
83
- const keq = new Keq(formatUrl(url), { method: 'delete' });
62
+ const keq = new Keq(formatUrl(url), { method: 'delete' }, global);
84
63
  keq.appendMiddlewares(...appendMiddlewares);
85
64
  keq.prependMiddlewares(...prependMiddlewares);
86
65
  return keq;
87
66
  };
88
67
  request.del = request.delete;
89
68
  request.post = function (url) {
90
- const keq = new Keq(formatUrl(url), { method: 'post' });
69
+ const keq = new Keq(formatUrl(url), { method: 'post' }, global);
91
70
  keq.appendMiddlewares(...appendMiddlewares);
92
71
  keq.prependMiddlewares(...prependMiddlewares);
93
72
  return keq;
94
73
  };
95
74
  request.head = function (url) {
96
- const keq = new Keq(formatUrl(url), { method: 'head' });
75
+ const keq = new Keq(formatUrl(url), { method: 'head' }, global);
97
76
  keq.appendMiddlewares(...appendMiddlewares);
98
77
  keq.prependMiddlewares(...prependMiddlewares);
99
78
  return keq;
100
79
  };
101
80
  request.patch = function (url) {
102
- const keq = new Keq(formatUrl(url), { method: 'patch' });
81
+ const keq = new Keq(formatUrl(url), { method: 'patch' }, global);
103
82
  keq.appendMiddlewares(...appendMiddlewares);
104
83
  keq.prependMiddlewares(...prependMiddlewares);
105
84
  return keq;
@@ -1,13 +1,21 @@
1
- export { createRequest } from './create-request';
2
- export { Keq } from './keq';
3
- export { composeMiddleware } from './middleware';
4
- export { request } from './request';
5
- export { KeqContext } from './types/keq-context';
6
- export { KeqMiddleware } from './types/keq-middleware';
7
- export { KeqNext } from './types/keq-next';
8
- export { KeqOptions } from './types/keq-options';
9
- export { KeqRequest } from './types/keq-request';
10
- export { KeqRequestBody } from './types/keq-request-body';
11
- export { KeqRequestInit } from './types/keq-request-init';
12
- export { KeqRetryDelay } from './types/keq-retry-delay';
13
- export { KeqRetryOn } from './types/keq-retry-on';
1
+ export { createRequest } from './create-request.js';
2
+ export { Keq } from './keq.js';
3
+ export { request } from './request.js';
4
+ export { composeMiddleware } from './util/compose-middleware.js';
5
+ export { composeRoute } from './util/compose-route.js';
6
+ export { KeqContext } from './types/keq-context.js';
7
+ export { KeqMiddleware } from './types/keq-middleware.js';
8
+ export { KeqNext } from './types/keq-next.js';
9
+ export { KeqOptions } from './types/keq-options.js';
10
+ export { KeqRequestBody } from './types/keq-request-body.js';
11
+ export { KeqRequestInit } from './types/keq-request-init.js';
12
+ export { KeqRequest } from './types/keq-request.js';
13
+ export { KeqRetryDelay } from './types/keq-retry-delay.js';
14
+ export { KeqRetryOn } from './types/keq-retry-on.js';
15
+ export { KeqRoute } from './types/keq-route.js';
16
+ export { keqHostRoute } from './router/keq-host-route.js';
17
+ export { keqLocationRoute } from './router/keq-location-route.js';
18
+ export { keqMethodRoute } from './router/keq-method-route.js';
19
+ export { keqModuleRoute } from './router/keq-module-route.js';
20
+ export { keqPathnameRoute } from './router/keq-pathname-route.js';
21
+ export { KeqRouter } from './router/keq-router.js';
@@ -1,4 +1,11 @@
1
- export { createRequest } from './create-request';
2
- export { Keq } from './keq';
3
- export { composeMiddleware } from './middleware';
4
- export { request } from './request';
1
+ export { createRequest } from './create-request.js';
2
+ export { Keq } from './keq.js';
3
+ export { request } from './request.js';
4
+ export { composeMiddleware } from './util/compose-middleware.js';
5
+ export { composeRoute } from './util/compose-route.js';
6
+ export { keqHostRoute } from './router/keq-host-route.js';
7
+ export { keqLocationRoute } from './router/keq-location-route.js';
8
+ export { keqMethodRoute } from './router/keq-method-route.js';
9
+ export { keqModuleRoute } from './router/keq-module-route.js';
10
+ export { keqPathnameRoute } from './router/keq-pathname-route.js';
11
+ export { KeqRouter } from './router/keq-router.js';
@@ -1,5 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { Core } from './core';
3
+ import { KeqFlowControlMode, KeqFlowControlSignal } from './types/keq-flow-control.js';
3
4
  import { KeqMiddleware } from './types/keq-middleware';
4
5
  import { KeqBuildInOptions, KeqOptions, KeqOptionsWithFullResponse, KeqOptionsWithoutFullResponse } from './types/keq-options';
5
6
  import { KeqRequestBody } from './types/keq-request-body';
@@ -11,11 +12,11 @@ import { ShorthandContentType } from './types/shorthand-content-type';
11
12
  */
12
13
  export declare class Keq<T> extends Core<T> {
13
14
  use(...middlewares: KeqMiddleware[]): this;
14
- option(key: 'resolveWithFullResponse', value?: true): Core<Response>;
15
+ option(key: 'resolveWithFullResponse', value?: true): Keq<Response>;
15
16
  option<K extends keyof KeqBuildInOptions>(key: K, value?: KeqBuildInOptions[K]): this;
16
17
  option(key: string, value?: any): this;
17
18
  options(opts: KeqOptionsWithoutFullResponse): this;
18
- options(opts: KeqOptionsWithFullResponse): Core<Response>;
19
+ options(opts: KeqOptionsWithFullResponse): Keq<Response>;
19
20
  options(opts: KeqOptions): this;
20
21
  /**
21
22
  * Set request header
@@ -67,4 +68,5 @@ export declare class Keq<T> extends Core<T> {
67
68
  redirect(mod: RequestRedirect): this;
68
69
  credentials(mod: RequestCredentials): this;
69
70
  mode(mod: RequestMode): this;
71
+ flowControl(mode: KeqFlowControlMode, signal?: KeqFlowControlSignal): this;
70
72
  }
@@ -9,6 +9,7 @@ import { isUrlSearchParams } from './is/is-url-search-params';
9
9
  import { assignKeqRequestBody } from './util/assign-keq-request-body';
10
10
  import { base64Encode } from './util/base64';
11
11
  import { fixContentType } from './util/fix-content-type';
12
+ import { getUniqueCodeIdentifier } from './util/get-unique-code-identifier.js';
12
13
  /**
13
14
  * @description Keq 扩展 API,人性化的常用的API
14
15
  */
@@ -176,4 +177,16 @@ export class Keq extends Core {
176
177
  this.requestContext.mode = mod;
177
178
  return this;
178
179
  }
180
+ flowControl(mode, signal) {
181
+ const sig = signal ? signal : getUniqueCodeIdentifier(1);
182
+ if (!sig) {
183
+ throw new Exception('please set signal to .flowControl()');
184
+ }
185
+ const flowControl = {
186
+ mode,
187
+ signal: sig,
188
+ };
189
+ this.option('flowControl', flowControl);
190
+ return this;
191
+ }
179
192
  }
@@ -0,0 +1,2 @@
1
+ import { KeqMiddleware } from "../types/keq-middleware.js";
2
+ export declare function abortFlowControlMiddleware(): KeqMiddleware;
@@ -0,0 +1,26 @@
1
+ export function abortFlowControlMiddleware() {
2
+ return async (ctx, next) => {
3
+ if (!ctx.options.flowControl || ctx.options.flowControl.mode !== 'abort') {
4
+ await next();
5
+ return;
6
+ }
7
+ if (ctx.request.signal) {
8
+ console.warn('[keq] request signal had be set manual, abort follow control will not take effect');
9
+ await next();
10
+ return;
11
+ }
12
+ const { signal } = ctx.options.flowControl;
13
+ const key = typeof signal === 'string' ? signal : signal(ctx);
14
+ if (!ctx.global.abortFlowControl)
15
+ ctx.global.abortFlowControl = {};
16
+ if (ctx.global.abortFlowControl[key]) {
17
+ const abortController = ctx.global.abortFlowControl[key];
18
+ abortController.abort('abort flow control');
19
+ }
20
+ const abortController = new AbortController();
21
+ ctx.global.abortFlowControl[key] = abortController;
22
+ ctx.request.signal = abortController.signal;
23
+ await next();
24
+ ctx.global.abortFlowControl[key] = undefined;
25
+ };
26
+ }
@@ -75,6 +75,15 @@ export function fetchArgumentsMiddleware() {
75
75
  method: request.method.toUpperCase(),
76
76
  headers: request.headers,
77
77
  body: compileBody(ctx),
78
+ cache: request.cache,
79
+ credentials: request.credentials,
80
+ integrity: request.integrity,
81
+ keepalive: request.keepalive,
82
+ mode: request.mode,
83
+ redirect: request.redirect,
84
+ referrer: request.referrer,
85
+ referrerPolicy: request.referrerPolicy,
86
+ signal: request.signal,
78
87
  };
79
88
  ctx.fetchArguments = [url, requestInit];
80
89
  await next();
@@ -0,0 +1,2 @@
1
+ import { KeqMiddleware } from "../types/keq-middleware.js";
2
+ export declare function serialFlowControlMiddleware(): KeqMiddleware;
@@ -0,0 +1,20 @@
1
+ import * as fastq from 'fastq';
2
+ export function serialFlowControlMiddleware() {
3
+ return async (ctx, next) => {
4
+ if (!ctx.options.flowControl || ctx.options.flowControl.mode !== 'serial') {
5
+ await next();
6
+ return;
7
+ }
8
+ const { signal } = ctx.options.flowControl;
9
+ const key = typeof signal === 'string' ? signal : signal(ctx);
10
+ if (!ctx.global.serialFlowControl)
11
+ ctx.global.serialFlowControl = {};
12
+ if (!ctx.global.serialFlowControl[key]) {
13
+ ctx.global.serialFlowControl[key] = fastq.promise(async (next) => {
14
+ await next();
15
+ }, 1);
16
+ }
17
+ const queue = ctx.global.serialFlowControl[key];
18
+ await queue.push(next);
19
+ };
20
+ }
@@ -0,0 +1,2 @@
1
+ import { KeqRoute } from "../types/keq-route.js";
2
+ export declare function keqHostRoute(host: string): KeqRoute;
@@ -0,0 +1,3 @@
1
+ export function keqHostRoute(host) {
2
+ return (ctx) => ctx.request.url.host === host;
3
+ }
@@ -0,0 +1,2 @@
1
+ import { KeqRoute } from "../types/keq-route.js";
2
+ export declare function keqLocationRoute(): KeqRoute;
@@ -0,0 +1,4 @@
1
+ import { isBrowser } from "../is/is-browser.js";
2
+ export function keqLocationRoute() {
3
+ return (ctx) => isBrowser() && ctx.request.url.host === window.location.host;
4
+ }
@@ -0,0 +1,2 @@
1
+ import { KeqRoute } from "../types/keq-route.js";
2
+ export declare function keqMethodRoute(method: any): KeqRoute;
@@ -0,0 +1,3 @@
1
+ export function keqMethodRoute(method) {
2
+ return (ctx) => ctx.request.method.toLowerCase() === method.toLowerCase();
3
+ }
@@ -0,0 +1,2 @@
1
+ import { KeqRoute } from "../types/keq-route.js";
2
+ export declare function keqModuleRoute(moduleName: string): KeqRoute;
@@ -0,0 +1,7 @@
1
+ import { Exception } from "../exception/exception.js";
2
+ export function keqModuleRoute(moduleName) {
3
+ if (!moduleName) {
4
+ throw new Exception('Module name should not be empty');
5
+ }
6
+ return (ctx) => ctx.options.module?.name === moduleName;
7
+ }
@@ -0,0 +1,2 @@
1
+ import { KeqRoute } from "../types/keq-route.js";
2
+ export declare function keqPathnameRoute(pathname: string): KeqRoute;
@@ -0,0 +1,4 @@
1
+ import { minimatch } from 'minimatch';
2
+ export function keqPathnameRoute(pathname) {
3
+ return (ctx) => minimatch(ctx.request.url.pathname, pathname);
4
+ }
@@ -1,7 +1,12 @@
1
1
  import { KeqMiddleware } from "../types/keq-middleware";
2
- export declare abstract class KeqRouter {
3
- protected middlewares: KeqMiddleware[];
4
- constructor(middlewares: KeqMiddleware[]);
5
- use(middleware: KeqMiddleware, ...middlewares: KeqMiddleware[]): this;
6
- abstract routes(): KeqMiddleware;
2
+ import { KeqRoute } from "../types/keq-route.js";
3
+ export declare class KeqRouter {
4
+ private readonly prependMiddlewares;
5
+ constructor(prependMiddlewares?: KeqMiddleware[]);
6
+ route(route: KeqRoute, ...middlewares: KeqMiddleware[]): this;
7
+ host(host: string, ...middlewares: KeqMiddleware[]): this;
8
+ method(method: string, ...middlewares: KeqMiddleware[]): this;
9
+ pathname(pathname: string, ...middlewares: KeqMiddleware[]): this;
10
+ location(...middlewares: KeqMiddleware[]): this;
11
+ module(moduleName: string, ...middlewares: KeqMiddleware[]): this;
7
12
  }