keq 2.5.1 → 2.5.3
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 +20 -0
- package/README.md +5 -5
- package/dist/esm/src/constant.d.ts +1 -0
- package/dist/esm/src/constant.js +1 -0
- package/dist/esm/src/core.js +6 -1
- package/dist/esm/src/middlewares/retry-middleware.js +11 -7
- package/dist/esm/src/router/keq-router.js +8 -8
- package/dist/esm/src/types/keq-context.d.ts +12 -1
- package/dist/esm/src/types/keq-context.js +1 -1
- package/dist/esm/src/util/compose-middleware.js +41 -2
- package/dist/umd/src/constant.d.ts +1 -0
- package/dist/umd/src/constant.js +2 -1
- package/dist/umd/src/core.js +5 -0
- package/dist/umd/src/middlewares/retry-middleware.js +12 -8
- package/dist/umd/src/router/keq-router.js +8 -8
- package/dist/umd/src/types/keq-context.d.ts +12 -1
- package/dist/umd/src/util/compose-middleware.js +42 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
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.5.3](https://github.com/keq-request/keq/compare/v2.5.2...v2.5.3) (2024-05-23)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* retryTimes avoids throw errors caused by NaN ([a5ece3f](https://github.com/keq-request/keq/commit/a5ece3f8afec3c58d2daa3c5e1a2f85fae044665))
|
|
11
|
+
|
|
12
|
+
## [2.5.2](https://github.com/keq-request/keq/compare/v2.5.1...v2.5.2) (2024-05-22)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* composeMiddleware should not change parameters ([131c1d4](https://github.com/keq-request/keq/commit/131c1d42227eeda2d42436c5285426bf3f787df0))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Performance Improvements
|
|
21
|
+
|
|
22
|
+
* avoid duplication of compose middleware ([c4e5cc1](https://github.com/keq-request/keq/commit/c4e5cc161d94b2440768c778489ee5ac1bb07484))
|
|
23
|
+
* warn for incorrect invoke next() ([f4b418f](https://github.com/keq-request/keq/commit/f4b418f28e3df07bad0c03e2aca811ed6254e57c)), closes [#74](https://github.com/keq-request/keq/issues/74)
|
|
24
|
+
|
|
5
25
|
## [2.5.1](https://github.com/keq-request/keq/compare/v2.5.0...v2.5.1) (2024-05-21)
|
|
6
26
|
|
|
7
27
|
|
package/README.md
CHANGED
|
@@ -291,11 +291,11 @@ There are multiple parsing methods for us to choose from
|
|
|
291
291
|
|
|
292
292
|
No retry by default, invoke `.retry(retryTimes[, retryDelay[, retryOn]])` to set retry parameters
|
|
293
293
|
|
|
294
|
-
| Parameter
|
|
295
|
-
| :--------- | :----------------------------------------------------------------------------------------------------------------------- |
|
|
296
|
-
| retryTimes | Max number of retries per call. |
|
|
297
|
-
| retryDelay | Initial value used to calculate the retry in milliseconds (This is still randomized following the randomization factor). |
|
|
298
|
-
| retryOn | Will be called after request used to control whether the next retry runs. If it return `false`, stop retrying. |
|
|
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
299
|
|
|
300
300
|
```javascript
|
|
301
301
|
import { request } from "keq";
|
package/dist/esm/src/constant.js
CHANGED
package/dist/esm/src/core.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { URL } from 'whatwg-url';
|
|
2
2
|
import { Exception } from "./exception/exception.js";
|
|
3
3
|
import { clone } from "./util/clone.js";
|
|
4
|
-
import { OUTPUT_PROPERTY } from './constant.js';
|
|
4
|
+
import { NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from './constant.js';
|
|
5
5
|
import { composeMiddleware } from './util/compose-middleware.js';
|
|
6
6
|
import { shadowClone } from './util/shadow-clone.js';
|
|
7
7
|
/**
|
|
@@ -59,6 +59,11 @@ export class Core {
|
|
|
59
59
|
};
|
|
60
60
|
const options = shadowClone(this.__options__);
|
|
61
61
|
const ctx = {
|
|
62
|
+
[NEXT_INVOKED_PROPERTY]: {
|
|
63
|
+
finished: false,
|
|
64
|
+
entryNextTimes: 0,
|
|
65
|
+
outNextTimes: 0,
|
|
66
|
+
},
|
|
62
67
|
request: requestContext,
|
|
63
68
|
options,
|
|
64
69
|
global: this.__global__,
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { NEXT_INVOKED_PROPERTY } from "../constant.js";
|
|
1
2
|
function sleep(ms) {
|
|
2
3
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3
4
|
}
|
|
4
5
|
export function retryMiddleware() {
|
|
5
6
|
return async function retryMiddleware(ctx, next) {
|
|
6
|
-
const retryTimes =
|
|
7
|
+
const retryTimes = Number.isInteger(ctx.options.retryTimes)
|
|
8
|
+
? ctx.options.retryTimes + 1
|
|
9
|
+
: 1;
|
|
7
10
|
const retryDelay = (attempt, error, ctx) => {
|
|
8
11
|
if (typeof ctx.options.retryDelay === 'function') {
|
|
9
12
|
return ctx.options.retryDelay(attempt, error, ctx);
|
|
@@ -11,9 +14,11 @@ export function retryMiddleware() {
|
|
|
11
14
|
else if (typeof ctx.options.retryDelay === 'number') {
|
|
12
15
|
return ctx.options.retryDelay;
|
|
13
16
|
}
|
|
14
|
-
return
|
|
17
|
+
return 0;
|
|
15
18
|
};
|
|
16
|
-
const retryOn = typeof ctx.options.retryOn === 'function'
|
|
19
|
+
const retryOn = typeof ctx.options.retryOn === 'function'
|
|
20
|
+
? ctx.options.retryOn
|
|
21
|
+
: (attempt, error) => !!error;
|
|
17
22
|
// Avoid multiple middleware from being added repeatedly
|
|
18
23
|
ctx.options = {
|
|
19
24
|
...ctx.options,
|
|
@@ -24,6 +29,8 @@ export function retryMiddleware() {
|
|
|
24
29
|
for (let i = 0; i < retryTimes; i++) {
|
|
25
30
|
let err = null;
|
|
26
31
|
try {
|
|
32
|
+
ctx[NEXT_INVOKED_PROPERTY].entryNextTimes = 0;
|
|
33
|
+
ctx[NEXT_INVOKED_PROPERTY].outNextTimes = 0;
|
|
27
34
|
await next();
|
|
28
35
|
}
|
|
29
36
|
catch (e) {
|
|
@@ -34,14 +41,11 @@ export function retryMiddleware() {
|
|
|
34
41
|
throw err;
|
|
35
42
|
break;
|
|
36
43
|
}
|
|
37
|
-
if (retryOn
|
|
44
|
+
if (retryOn(i, err, ctx) === false) {
|
|
38
45
|
if (err)
|
|
39
46
|
throw err;
|
|
40
47
|
break;
|
|
41
48
|
}
|
|
42
|
-
else if (!retryOn && !err) {
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
49
|
const delay = retryDelay(i, err, ctx);
|
|
46
50
|
if (delay > 0)
|
|
47
51
|
await sleep(delay);
|
|
@@ -10,15 +10,15 @@ export class KeqRouter {
|
|
|
10
10
|
this.prependMiddlewares = prependMiddlewares;
|
|
11
11
|
}
|
|
12
12
|
route(route, ...middlewares) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
if (middlewares.length === 0)
|
|
14
|
+
return this;
|
|
15
|
+
const m = middlewares.length > 1 ? composeMiddleware(middlewares) : middlewares[0];
|
|
16
|
+
this.prependMiddlewares.push(async (ctx, next) => {
|
|
17
|
+
if (route(ctx))
|
|
18
|
+
await m(ctx, next);
|
|
19
|
+
else
|
|
18
20
|
await next();
|
|
19
|
-
|
|
20
|
-
};
|
|
21
|
-
this.prependMiddlewares.push(middleware);
|
|
21
|
+
});
|
|
22
22
|
return this;
|
|
23
23
|
}
|
|
24
24
|
host(host, ...middlewares) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { URL } from 'whatwg-url';
|
|
2
|
-
import { OUTPUT_PROPERTY } from "../constant";
|
|
2
|
+
import { NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from "../constant";
|
|
3
3
|
import { KeqRequestBody } from './keq-request-body';
|
|
4
4
|
import { KeqRequestMethod } from './keq-request-method';
|
|
5
5
|
import { KeqOptionsParameter } from './keq-options.js';
|
|
@@ -23,6 +23,17 @@ export interface KeqRequestContext {
|
|
|
23
23
|
signal?: AbortSignal | null;
|
|
24
24
|
}
|
|
25
25
|
export interface KeqContext {
|
|
26
|
+
/**
|
|
27
|
+
* Middleware invoker counter
|
|
28
|
+
*
|
|
29
|
+
* to prevent someone from calling next
|
|
30
|
+
* multiple times or forgetting to write await
|
|
31
|
+
*/
|
|
32
|
+
[NEXT_INVOKED_PROPERTY]: {
|
|
33
|
+
finished: boolean;
|
|
34
|
+
entryNextTimes: number;
|
|
35
|
+
outNextTimes: number;
|
|
36
|
+
};
|
|
26
37
|
options: KeqContextOptions;
|
|
27
38
|
/**
|
|
28
39
|
* Fetch API Arguments
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import { OUTPUT_PROPERTY } from "../constant";
|
|
1
|
+
import { NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from "../constant";
|
|
@@ -1,12 +1,51 @@
|
|
|
1
1
|
import { Exception } from "../exception/exception.js";
|
|
2
|
+
import { NEXT_INVOKED_PROPERTY } from "../constant.js";
|
|
2
3
|
export function composeMiddleware(middlewares) {
|
|
3
4
|
if (!middlewares.length) {
|
|
4
5
|
throw new Exception('At least one middleware');
|
|
5
6
|
}
|
|
6
|
-
const middleware = middlewares
|
|
7
|
+
const middleware = [...middlewares]
|
|
7
8
|
.reverse()
|
|
8
9
|
.reduce(function (prev, curr) {
|
|
9
|
-
return (ctx, next) =>
|
|
10
|
+
return async (ctx, next) => {
|
|
11
|
+
const invoked = {
|
|
12
|
+
finished: false,
|
|
13
|
+
entryNextTimes: 0,
|
|
14
|
+
outNextTimes: 0,
|
|
15
|
+
};
|
|
16
|
+
const context = new Proxy(ctx, {
|
|
17
|
+
get(target, property) {
|
|
18
|
+
if (property === NEXT_INVOKED_PROPERTY) {
|
|
19
|
+
return invoked;
|
|
20
|
+
}
|
|
21
|
+
// @ts-ignore
|
|
22
|
+
return target[property];
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
await curr(context, async () => {
|
|
26
|
+
if (invoked.finished) {
|
|
27
|
+
throw new Exception([
|
|
28
|
+
`next() should not invoke after ${curr.toString()} middleware finished.`,
|
|
29
|
+
].join(''));
|
|
30
|
+
}
|
|
31
|
+
if (invoked.entryNextTimes > 1) {
|
|
32
|
+
console.warn(`next() had be invoke multiple times at ${curr.toString()} middleware`);
|
|
33
|
+
}
|
|
34
|
+
invoked.entryNextTimes += 1;
|
|
35
|
+
await prev(ctx, next);
|
|
36
|
+
invoked.outNextTimes += 1;
|
|
37
|
+
});
|
|
38
|
+
invoked.finished = true;
|
|
39
|
+
if (invoked.entryNextTimes === 0) {
|
|
40
|
+
console.warn(`next() is not invoked at ${curr.toString()}.`);
|
|
41
|
+
}
|
|
42
|
+
if (invoked.entryNextTimes !== invoked.outNextTimes) {
|
|
43
|
+
throw new Exception([
|
|
44
|
+
`next() should be invoke before ${curr.toString()} middleware finish.`,
|
|
45
|
+
'Maybe you forgot to await when calling next().',
|
|
46
|
+
].join(''));
|
|
47
|
+
}
|
|
48
|
+
};
|
|
10
49
|
});
|
|
11
50
|
return middleware;
|
|
12
51
|
}
|
package/dist/umd/src/constant.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
})(function (require, exports) {
|
|
10
10
|
"use strict";
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.OUTPUT_PROPERTY = void 0;
|
|
12
|
+
exports.NEXT_INVOKED_PROPERTY = exports.OUTPUT_PROPERTY = void 0;
|
|
13
13
|
exports.OUTPUT_PROPERTY = Symbol('outputProperty');
|
|
14
|
+
exports.NEXT_INVOKED_PROPERTY = Symbol('nextInvokedProperty');
|
|
14
15
|
});
|
package/dist/umd/src/core.js
CHANGED
|
@@ -71,6 +71,11 @@
|
|
|
71
71
|
};
|
|
72
72
|
const options = (0, shadow_clone_js_1.shadowClone)(this.__options__);
|
|
73
73
|
const ctx = {
|
|
74
|
+
[constant_js_1.NEXT_INVOKED_PROPERTY]: {
|
|
75
|
+
finished: false,
|
|
76
|
+
entryNextTimes: 0,
|
|
77
|
+
outNextTimes: 0,
|
|
78
|
+
},
|
|
74
79
|
request: requestContext,
|
|
75
80
|
options,
|
|
76
81
|
global: this.__global__,
|
|
@@ -4,18 +4,21 @@
|
|
|
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.js"], factory);
|
|
8
8
|
}
|
|
9
9
|
})(function (require, exports) {
|
|
10
10
|
"use strict";
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.retryMiddleware = void 0;
|
|
13
|
+
const constant_js_1 = require("../constant.js");
|
|
13
14
|
function sleep(ms) {
|
|
14
15
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
15
16
|
}
|
|
16
17
|
function retryMiddleware() {
|
|
17
18
|
return async function retryMiddleware(ctx, next) {
|
|
18
|
-
const retryTimes =
|
|
19
|
+
const retryTimes = Number.isInteger(ctx.options.retryTimes)
|
|
20
|
+
? ctx.options.retryTimes + 1
|
|
21
|
+
: 1;
|
|
19
22
|
const retryDelay = (attempt, error, ctx) => {
|
|
20
23
|
if (typeof ctx.options.retryDelay === 'function') {
|
|
21
24
|
return ctx.options.retryDelay(attempt, error, ctx);
|
|
@@ -23,9 +26,11 @@
|
|
|
23
26
|
else if (typeof ctx.options.retryDelay === 'number') {
|
|
24
27
|
return ctx.options.retryDelay;
|
|
25
28
|
}
|
|
26
|
-
return
|
|
29
|
+
return 0;
|
|
27
30
|
};
|
|
28
|
-
const retryOn = typeof ctx.options.retryOn === 'function'
|
|
31
|
+
const retryOn = typeof ctx.options.retryOn === 'function'
|
|
32
|
+
? ctx.options.retryOn
|
|
33
|
+
: (attempt, error) => !!error;
|
|
29
34
|
// Avoid multiple middleware from being added repeatedly
|
|
30
35
|
ctx.options = {
|
|
31
36
|
...ctx.options,
|
|
@@ -36,6 +41,8 @@
|
|
|
36
41
|
for (let i = 0; i < retryTimes; i++) {
|
|
37
42
|
let err = null;
|
|
38
43
|
try {
|
|
44
|
+
ctx[constant_js_1.NEXT_INVOKED_PROPERTY].entryNextTimes = 0;
|
|
45
|
+
ctx[constant_js_1.NEXT_INVOKED_PROPERTY].outNextTimes = 0;
|
|
39
46
|
await next();
|
|
40
47
|
}
|
|
41
48
|
catch (e) {
|
|
@@ -46,14 +53,11 @@
|
|
|
46
53
|
throw err;
|
|
47
54
|
break;
|
|
48
55
|
}
|
|
49
|
-
if (retryOn
|
|
56
|
+
if (retryOn(i, err, ctx) === false) {
|
|
50
57
|
if (err)
|
|
51
58
|
throw err;
|
|
52
59
|
break;
|
|
53
60
|
}
|
|
54
|
-
else if (!retryOn && !err) {
|
|
55
|
-
break;
|
|
56
|
-
}
|
|
57
61
|
const delay = retryDelay(i, err, ctx);
|
|
58
62
|
if (delay > 0)
|
|
59
63
|
await sleep(delay);
|
|
@@ -22,15 +22,15 @@
|
|
|
22
22
|
this.prependMiddlewares = prependMiddlewares;
|
|
23
23
|
}
|
|
24
24
|
route(route, ...middlewares) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
if (middlewares.length === 0)
|
|
26
|
+
return this;
|
|
27
|
+
const m = middlewares.length > 1 ? (0, compose_middleware_js_1.composeMiddleware)(middlewares) : middlewares[0];
|
|
28
|
+
this.prependMiddlewares.push(async (ctx, next) => {
|
|
29
|
+
if (route(ctx))
|
|
30
|
+
await m(ctx, next);
|
|
31
|
+
else
|
|
30
32
|
await next();
|
|
31
|
-
|
|
32
|
-
};
|
|
33
|
-
this.prependMiddlewares.push(middleware);
|
|
33
|
+
});
|
|
34
34
|
return this;
|
|
35
35
|
}
|
|
36
36
|
host(host, ...middlewares) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { URL } from 'whatwg-url';
|
|
2
|
-
import { OUTPUT_PROPERTY } from "../constant";
|
|
2
|
+
import { NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from "../constant";
|
|
3
3
|
import { KeqRequestBody } from './keq-request-body';
|
|
4
4
|
import { KeqRequestMethod } from './keq-request-method';
|
|
5
5
|
import { KeqOptionsParameter } from './keq-options.js';
|
|
@@ -23,6 +23,17 @@ export interface KeqRequestContext {
|
|
|
23
23
|
signal?: AbortSignal | null;
|
|
24
24
|
}
|
|
25
25
|
export interface KeqContext {
|
|
26
|
+
/**
|
|
27
|
+
* Middleware invoker counter
|
|
28
|
+
*
|
|
29
|
+
* to prevent someone from calling next
|
|
30
|
+
* multiple times or forgetting to write await
|
|
31
|
+
*/
|
|
32
|
+
[NEXT_INVOKED_PROPERTY]: {
|
|
33
|
+
finished: boolean;
|
|
34
|
+
entryNextTimes: number;
|
|
35
|
+
outNextTimes: number;
|
|
36
|
+
};
|
|
26
37
|
options: KeqContextOptions;
|
|
27
38
|
/**
|
|
28
39
|
* Fetch API Arguments
|
|
@@ -4,21 +4,60 @@
|
|
|
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.js"], factory);
|
|
7
|
+
define(["require", "exports", "../exception/exception.js", "../constant.js"], factory);
|
|
8
8
|
}
|
|
9
9
|
})(function (require, exports) {
|
|
10
10
|
"use strict";
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.composeMiddleware = void 0;
|
|
13
13
|
const exception_js_1 = require("../exception/exception.js");
|
|
14
|
+
const constant_js_1 = require("../constant.js");
|
|
14
15
|
function composeMiddleware(middlewares) {
|
|
15
16
|
if (!middlewares.length) {
|
|
16
17
|
throw new exception_js_1.Exception('At least one middleware');
|
|
17
18
|
}
|
|
18
|
-
const middleware = middlewares
|
|
19
|
+
const middleware = [...middlewares]
|
|
19
20
|
.reverse()
|
|
20
21
|
.reduce(function (prev, curr) {
|
|
21
|
-
return (ctx, next) =>
|
|
22
|
+
return async (ctx, next) => {
|
|
23
|
+
const invoked = {
|
|
24
|
+
finished: false,
|
|
25
|
+
entryNextTimes: 0,
|
|
26
|
+
outNextTimes: 0,
|
|
27
|
+
};
|
|
28
|
+
const context = new Proxy(ctx, {
|
|
29
|
+
get(target, property) {
|
|
30
|
+
if (property === constant_js_1.NEXT_INVOKED_PROPERTY) {
|
|
31
|
+
return invoked;
|
|
32
|
+
}
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
return target[property];
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
await curr(context, async () => {
|
|
38
|
+
if (invoked.finished) {
|
|
39
|
+
throw new exception_js_1.Exception([
|
|
40
|
+
`next() should not invoke after ${curr.toString()} middleware finished.`,
|
|
41
|
+
].join(''));
|
|
42
|
+
}
|
|
43
|
+
if (invoked.entryNextTimes > 1) {
|
|
44
|
+
console.warn(`next() had be invoke multiple times at ${curr.toString()} middleware`);
|
|
45
|
+
}
|
|
46
|
+
invoked.entryNextTimes += 1;
|
|
47
|
+
await prev(ctx, next);
|
|
48
|
+
invoked.outNextTimes += 1;
|
|
49
|
+
});
|
|
50
|
+
invoked.finished = true;
|
|
51
|
+
if (invoked.entryNextTimes === 0) {
|
|
52
|
+
console.warn(`next() is not invoked at ${curr.toString()}.`);
|
|
53
|
+
}
|
|
54
|
+
if (invoked.entryNextTimes !== invoked.outNextTimes) {
|
|
55
|
+
throw new exception_js_1.Exception([
|
|
56
|
+
`next() should be invoke before ${curr.toString()} middleware finish.`,
|
|
57
|
+
'Maybe you forgot to await when calling next().',
|
|
58
|
+
].join(''));
|
|
59
|
+
}
|
|
60
|
+
};
|
|
22
61
|
});
|
|
23
62
|
return middleware;
|
|
24
63
|
}
|