├── .editorconfig
├── .github
└── workflows
│ └── tests.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── biome.json
├── docs
├── README.md
└── api-reference
│ ├── .nojekyll
│ ├── README.md
│ └── classes
│ └── Composer.md
├── logo.svg
├── package-lock.json
├── package.json
├── rollup.config.js
├── src
├── compose.ts
├── composer.ts
├── helpers.ts
├── index.ts
├── snippets.ts
└── types.ts
├── test
├── benchmark.bench.ts
├── composer.test.ts
├── middleware.test.ts
└── snippets.test.ts
└── tsconfig.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | end_of_line = lf
6 | indent_style = space
7 | indent_size = 4
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.{yaml,yml}]
13 | indent_size = 2
14 |
15 | [*.md]
16 | trim_trailing_whitespace = false
17 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: Middleware-IO CI
2 |
3 | on: [ push, pull_request ]
4 |
5 | jobs:
6 | test:
7 | runs-on: ubuntu-latest
8 | strategy:
9 | matrix:
10 | node-version:
11 | # - 14.x
12 | # - 16.x
13 | - 18.x
14 | - 20.x
15 | - 22.x
16 | steps:
17 | - uses: actions/checkout@v4
18 | - name: Use Node.js ${{ matrix.node-version }}
19 | uses: actions/setup-node@v4
20 | with:
21 | node-version: ${{ matrix.node-version }}
22 | - run: npm ci
23 | - run: npm run build
24 | - run: npm run test
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | *.log
3 |
4 | # Dependency directories
5 | node_modules/
6 |
7 | # Build
8 | lib/
9 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 | Please refer to the changelog in [GitHub Releases](https://github.com/negezor/middleware-io/releases)
3 |
4 | ## [2.8.0] - 2021.06.10
5 | ### Breaking Change
6 | - Drop support Node.JS 10
7 |
8 | ## [2.7.0] - 2021.06.10
9 | ### Feature
10 | - Using [exports](https://nodejs.org/api/packages.html#packages_package_entry_points) in `package.json`
11 |
12 | ### Updated
13 | - Updated dev dependencies
14 | - Updated generated docs
15 |
16 | ## [2.6.0] - 2021.03.28
17 | ### Updated
18 | - Now uses `UnknownObject` instead of `object` type
19 | - Updated dev dependencies
20 | - Updated generated docs
21 |
22 | ## [2.5.0] - 2020.02.21
23 | ### Added
24 | - Composer now has an inherited generic
25 |
26 | ### Updated
27 | - Compose correspond koa-compose
28 | - Updated dev dependencies
29 | - Updated generated docs
30 |
31 | ## [2.4.0] - 2020.01.20
32 | ### BREAKING CHNAGE
33 | - In snippets `getBeforeMiddleware` and `getEnforceMiddleware` the order of the arguments has changed
34 | - Composer now requires generic with object restriction
35 |
36 | ### Fixed
37 | - Multiple next calls in compose now throw an asynchronous error
38 | - In snippets `getBeforeMiddleware`, `getAfterMiddleware`, `getEnforceMiddleware` and `getConcurrencyMiddleware` an error will be thrown for several calls next
39 | - Comments typos fixed
40 |
41 | ### Updated
42 | - Types `NextMiddlewareReturn` and `MiddlewareReturn` now unknown instead of any
43 | - Updated dev dependencies
44 | - Updated generated docs
45 |
46 | ## [2.3.0] - 2020.01.03
47 | ### Added
48 | - Added `builder` static method for `Composer`
49 | - Added `length` getter for `Composer`
50 |
51 | ### Updated
52 | - Updated generated docs
53 |
54 | ## [2.2.0] - 2020.01.03
55 | ### BREAKING CHNAGE
56 | - Drop support `Node.js 8`
57 |
58 | ### Added
59 | - Added `clone` method for `Composer`
60 |
61 | ### Fixed
62 | - Snippet `stopMiddleware` now return `Promise`
63 |
64 | ### Updated
65 | - Updated dev dependencies
66 | - Updated generated docs
67 | - Updated TypeScript config
68 |
69 | ## [2.1.0] - 2019.10.06
70 | ### Added
71 | - Added `getCaughtMiddleware` snippet
72 | - Added tests for `getCaughtMiddleware` and `getLazyMiddleware`
73 |
74 | ### Fixed
75 | - Fixed missing cache in `getLazyMiddleware`
76 | - Fixed example in README.md
77 |
78 | ### Updated
79 | - Updated dev dependencies
80 | - Updated generated docs
81 |
82 | ## [2.0.0] - 2019.06.19
83 | ### Added
84 | - Added `Composer`, a simple middleware compose builder
85 | - Added `getLazyMiddleware`, `getTapMiddleware`, `getForkMiddleware`, `getEnforceMiddleware`, `getConcurrencyMiddleware` snippets
86 | - Added mini-optimization for `compose`
87 | - Added tests for snippets
88 | - Added tests for `Composer`
89 |
90 | ### Updated
91 | - Rewrited code with full types
92 | - Now using eslint instead of tslint
93 | - Rewritten benchmark with matcha on benchmark.js
94 |
95 | ### Major
96 | - Export compose by default
97 | - Deleted `MiddlewareStatus`, use compose
98 |
99 | ## [1.0.0] - 2019.01.13
100 | ### Added
101 | - Added compose functions
102 | - Added snippets middleware
103 |
104 | ### Updated
105 | - Switch to TypeScript
106 |
107 | ### Major
108 | - Delete multiple input contexts
109 | - Usage only array for added middleware
110 |
111 | ## [0.0.8] - 2018.09.11
112 | ### Added
113 | - Added length
114 | - Added custom tag in toString()
115 |
116 | ### Updated
117 | - Updated dependencies
118 | - Improved build
119 |
120 | ## [0.0.7] - 2018.07.25
121 | ### Updated
122 | - Updated dependencies
123 | - Migrating to jest
124 | - Optimization of the status
125 |
126 | ## [0.0.6] - 2018.04.11
127 | ### Added
128 | - Support `--experimental-modules`
129 | - Using [rollupjs](https://github.com/rollup/rollup) for build
130 |
131 | ### Updated
132 | - Refactoring
133 |
134 | ## [0.0.5] - 2018.03.01
135 | ### Updated
136 | - Switch CLRF to LF
137 |
138 | ## [0.0.4] - 2018.02.24
139 | ### Updated
140 | - All dependencies
141 | - Now mjs files are used
142 | - Fixed README.md install
143 |
144 | ## [0.0.1] - 2017.10.29
145 | ### Added
146 | - Initial commit
147 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019-2024 Negezor
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |

2 |
3 |
4 |
5 |
6 |
7 |
8 | > **Middleware-IO** - Modern middleware on Promise
9 |
10 | | 📖 [Documentation](docs/) |
11 | |---------------------------|
12 |
13 | ## Features
14 |
15 | 1. **Self-Sufficient.** The library has zero dependencies.
16 | 2. **Reliable.** The library is written in **TypeScript** and covered by tests.
17 | 3. **Modern.** The library comes with native ESM support
18 | 3. **Powerful.** Supports following additional features:
19 | - The library has enough built-in snippets;
20 | - The middleware chain builder;
21 |
22 | ## Installation
23 | > **[Node.js](https://nodejs.org/) 12.0.0 or newer is required**
24 |
25 | - **Using `npm`** (recommended)
26 | ```shell
27 | npm i middleware-io
28 | ```
29 | - **Using `Yarn`**
30 | ```shell
31 | yarn add middleware-io
32 | ```
33 | - **Using `pnpm`**
34 | ```shell
35 | pnpm add middleware-io
36 | ```
37 |
38 | ## Example usage
39 |
40 | ```js
41 | import { compose } from 'middleware-io';
42 |
43 | const composedMiddleware = compose([
44 | async (context, next) => {
45 | // Step 1
46 |
47 | await next();
48 |
49 | // Step 4
50 |
51 | // Print the current date from the next middleware
52 | console.log(context.now);
53 | },
54 | async (context, next) => {
55 | // Step 2
56 |
57 | context.now = Date.now();
58 |
59 | await next();
60 |
61 | // Step 3
62 | }
63 | ]);
64 |
65 | composedMiddleware({}, () => { /* Last handler (next) */ })
66 | .then(() => {
67 | console.log('Middleware finished work');
68 | })
69 | .catch(console.error);
70 | ```
71 |
--------------------------------------------------------------------------------
/biome.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
3 | "formatter": {
4 | "indentStyle": "space",
5 | "indentWidth": 4,
6 | "lineWidth": 120,
7 | "lineEnding": "lf"
8 | },
9 | "javascript": {
10 | "formatter": {
11 | "quoteStyle": "single",
12 | "semicolons": "always",
13 | "arrowParentheses": "asNeeded"
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Middleware IO Docs
2 |
3 | | 📖 [API Reference](api-reference/) |
4 | |------------------------------------ |
5 |
--------------------------------------------------------------------------------
/docs/api-reference/.nojekyll:
--------------------------------------------------------------------------------
1 | TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false.
--------------------------------------------------------------------------------
/docs/api-reference/README.md:
--------------------------------------------------------------------------------
1 | middleware-io
2 |
3 | # middleware-io
4 |
5 | ## Table of contents
6 |
7 | ### References
8 |
9 | - [default](README.md#default)
10 |
11 | ### Classes
12 |
13 | - [Composer](classes/Composer.md)
14 |
15 | ### Type Aliases
16 |
17 | - [BranchMiddlewareCondition](README.md#branchmiddlewarecondition)
18 | - [BranchMiddlewareConditionFunction](README.md#branchmiddlewareconditionfunction)
19 | - [CaughtMiddlewareHandler](README.md#caughtmiddlewarehandler)
20 | - [LazyMiddlewareFactory](README.md#lazymiddlewarefactory)
21 | - [Middleware](README.md#middleware)
22 | - [MiddlewareReturn](README.md#middlewarereturn)
23 | - [NextMiddleware](README.md#nextmiddleware)
24 | - [NextMiddlewareReturn](README.md#nextmiddlewarereturn)
25 | - [UnknownObject](README.md#unknownobject)
26 |
27 | ### Functions
28 |
29 | - [compose](README.md#compose)
30 | - [getAfterMiddleware](README.md#getaftermiddleware)
31 | - [getBeforeMiddleware](README.md#getbeforemiddleware)
32 | - [getBranchMiddleware](README.md#getbranchmiddleware)
33 | - [getCaughtMiddleware](README.md#getcaughtmiddleware)
34 | - [getConcurrencyMiddleware](README.md#getconcurrencymiddleware)
35 | - [getEnforceMiddleware](README.md#getenforcemiddleware)
36 | - [getFilterMiddleware](README.md#getfiltermiddleware)
37 | - [getForkMiddleware](README.md#getforkmiddleware)
38 | - [getLazyMiddleware](README.md#getlazymiddleware)
39 | - [getOptionalMiddleware](README.md#getoptionalmiddleware)
40 | - [getTapMiddleware](README.md#gettapmiddleware)
41 | - [noopNext](README.md#noopnext)
42 | - [skipMiddleware](README.md#skipmiddleware)
43 | - [stopMiddleware](README.md#stopmiddleware)
44 |
45 | ## References
46 |
47 | ### default
48 |
49 | Renames and re-exports [compose](README.md#compose)
50 |
51 | ## Type Aliases
52 |
53 | ### BranchMiddlewareCondition
54 |
55 | Ƭ **BranchMiddlewareCondition**\<`T`\>: [`BranchMiddlewareConditionFunction`](README.md#branchmiddlewareconditionfunction)\<`T`\> \| `boolean`
56 |
57 | Possible types for branch condition
58 |
59 | #### Type parameters
60 |
61 | | Name |
62 | | :------ |
63 | | `T` |
64 |
65 | #### Defined in
66 |
67 | [types.ts:34](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/types.ts#L34)
68 |
69 | ___
70 |
71 | ### BranchMiddlewareConditionFunction
72 |
73 | Ƭ **BranchMiddlewareConditionFunction**\<`T`\>: (`context`: `T`) => `Promise`\<`boolean`\> \| `boolean`
74 |
75 | Asynchronous function for branch condition
76 |
77 | #### Type parameters
78 |
79 | | Name |
80 | | :------ |
81 | | `T` |
82 |
83 | #### Type declaration
84 |
85 | ▸ (`context`): `Promise`\<`boolean`\> \| `boolean`
86 |
87 | ##### Parameters
88 |
89 | | Name | Type |
90 | | :------ | :------ |
91 | | `context` | `T` |
92 |
93 | ##### Returns
94 |
95 | `Promise`\<`boolean`\> \| `boolean`
96 |
97 | #### Defined in
98 |
99 | [types.ts:29](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/types.ts#L29)
100 |
101 | ___
102 |
103 | ### CaughtMiddlewareHandler
104 |
105 | Ƭ **CaughtMiddlewareHandler**\<`T`\>: (`context`: `T`, `error`: `Error`) => [`MiddlewareReturn`](README.md#middlewarereturn)
106 |
107 | Handler for catching errors in middleware chains
108 |
109 | #### Type parameters
110 |
111 | | Name |
112 | | :------ |
113 | | `T` |
114 |
115 | #### Type declaration
116 |
117 | ▸ (`context`, `error`): [`MiddlewareReturn`](README.md#middlewarereturn)
118 |
119 | ##### Parameters
120 |
121 | | Name | Type |
122 | | :------ | :------ |
123 | | `context` | `T` |
124 | | `error` | `Error` |
125 |
126 | ##### Returns
127 |
128 | [`MiddlewareReturn`](README.md#middlewarereturn)
129 |
130 | #### Defined in
131 |
132 | [types.ts:44](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/types.ts#L44)
133 |
134 | ___
135 |
136 | ### LazyMiddlewareFactory
137 |
138 | Ƭ **LazyMiddlewareFactory**\<`T`\>: (`context`: `T`) => `Promise`\<[`Middleware`](README.md#middleware)\<`T`\>\> \| [`Middleware`](README.md#middleware)\<`T`\>
139 |
140 | Asynchronous factory to create middleware
141 |
142 | #### Type parameters
143 |
144 | | Name |
145 | | :------ |
146 | | `T` |
147 |
148 | #### Type declaration
149 |
150 | ▸ (`context`): `Promise`\<[`Middleware`](README.md#middleware)\<`T`\>\> \| [`Middleware`](README.md#middleware)\<`T`\>
151 |
152 | ##### Parameters
153 |
154 | | Name | Type |
155 | | :------ | :------ |
156 | | `context` | `T` |
157 |
158 | ##### Returns
159 |
160 | `Promise`\<[`Middleware`](README.md#middleware)\<`T`\>\> \| [`Middleware`](README.md#middleware)\<`T`\>
161 |
162 | #### Defined in
163 |
164 | [types.ts:39](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/types.ts#L39)
165 |
166 | ___
167 |
168 | ### Middleware
169 |
170 | Ƭ **Middleware**\<`T`\>: (`context`: `T`, `next`: [`NextMiddleware`](README.md#nextmiddleware)) => [`MiddlewareReturn`](README.md#middlewarereturn)
171 |
172 | Basic middleware
173 |
174 | #### Type parameters
175 |
176 | | Name |
177 | | :------ |
178 | | `T` |
179 |
180 | #### Type declaration
181 |
182 | ▸ (`context`, `next`): [`MiddlewareReturn`](README.md#middlewarereturn)
183 |
184 | ##### Parameters
185 |
186 | | Name | Type |
187 | | :------ | :------ |
188 | | `context` | `T` |
189 | | `next` | [`NextMiddleware`](README.md#nextmiddleware) |
190 |
191 | ##### Returns
192 |
193 | [`MiddlewareReturn`](README.md#middlewarereturn)
194 |
195 | #### Defined in
196 |
197 | [types.ts:24](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/types.ts#L24)
198 |
199 | ___
200 |
201 | ### MiddlewareReturn
202 |
203 | Ƭ **MiddlewareReturn**: `unknown`
204 |
205 | Returns the type of response middleware
206 |
207 | #### Defined in
208 |
209 | [types.ts:14](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/types.ts#L14)
210 |
211 | ___
212 |
213 | ### NextMiddleware
214 |
215 | Ƭ **NextMiddleware**: () => `Promise`\<[`NextMiddlewareReturn`](README.md#nextmiddlewarereturn)\>
216 |
217 | Call the next middleware from the chain
218 |
219 | #### Type declaration
220 |
221 | ▸ (): `Promise`\<[`NextMiddlewareReturn`](README.md#nextmiddlewarereturn)\>
222 |
223 | ##### Returns
224 |
225 | `Promise`\<[`NextMiddlewareReturn`](README.md#nextmiddlewarereturn)\>
226 |
227 | #### Defined in
228 |
229 | [types.ts:9](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/types.ts#L9)
230 |
231 | ___
232 |
233 | ### NextMiddlewareReturn
234 |
235 | Ƭ **NextMiddlewareReturn**: `unknown`
236 |
237 | Returns the type of response middleware
238 |
239 | #### Defined in
240 |
241 | [types.ts:4](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/types.ts#L4)
242 |
243 | ___
244 |
245 | ### UnknownObject
246 |
247 | Ƭ **UnknownObject**: `Record`\<`string`, `unknown`\>
248 |
249 | Instead of object
250 |
251 | #### Defined in
252 |
253 | [types.ts:19](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/types.ts#L19)
254 |
255 | ## Functions
256 |
257 | ### compose
258 |
259 | ▸ **compose**\<`T`\>(`middlewares`): [`Middleware`](README.md#middleware)\<`T`\>
260 |
261 | Compose an array of middleware handlers into a single handler
262 |
263 | #### Type parameters
264 |
265 | | Name |
266 | | :------ |
267 | | `T` |
268 |
269 | #### Parameters
270 |
271 | | Name | Type | Description |
272 | | :------ | :------ | :------ |
273 | | `middlewares` | [`Middleware`](README.md#middleware)\<`T`\>[] | The array of middleware |
274 |
275 | #### Returns
276 |
277 | [`Middleware`](README.md#middleware)\<`T`\>
278 |
279 | Composed middleware
280 |
281 | #### Defined in
282 |
283 | [compose.ts:12](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/compose.ts#L12)
284 |
285 | ___
286 |
287 | ### getAfterMiddleware
288 |
289 | ▸ **getAfterMiddleware**\<`T`\>(`middleware`, `afterMiddleware`): [`Middleware`](README.md#middleware)\<`T`\>
290 |
291 | Runs the second middleware after the main
292 |
293 | Example:
294 |
295 | ```ts
296 | getAfterMiddleware(
297 | sendSecureData,
298 | clearSecurityData
299 | );
300 | ```
301 |
302 | #### Type parameters
303 |
304 | | Name |
305 | | :------ |
306 | | `T` |
307 |
308 | #### Parameters
309 |
310 | | Name | Type |
311 | | :------ | :------ |
312 | | `middleware` | [`Middleware`](README.md#middleware)\<`T`\> |
313 | | `afterMiddleware` | [`Middleware`](README.md#middleware)\<`T`\> |
314 |
315 | #### Returns
316 |
317 | [`Middleware`](README.md#middleware)\<`T`\>
318 |
319 | #### Defined in
320 |
321 | [snippets.ts:192](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/snippets.ts#L192)
322 |
323 | ___
324 |
325 | ### getBeforeMiddleware
326 |
327 | ▸ **getBeforeMiddleware**\<`T`\>(`beforeMiddleware`, `middleware`): [`Middleware`](README.md#middleware)\<`T`\>
328 |
329 | Runs the second middleware before the main
330 |
331 | Example:
332 |
333 | ```ts
334 | getBeforeMiddleware(
335 | myMockMiddleware,
336 | ouputUserData
337 | );
338 | ```
339 |
340 | #### Type parameters
341 |
342 | | Name |
343 | | :------ |
344 | | `T` |
345 |
346 | #### Parameters
347 |
348 | | Name | Type |
349 | | :------ | :------ |
350 | | `beforeMiddleware` | [`Middleware`](README.md#middleware)\<`T`\> |
351 | | `middleware` | [`Middleware`](README.md#middleware)\<`T`\> |
352 |
353 | #### Returns
354 |
355 | [`Middleware`](README.md#middleware)\<`T`\>
356 |
357 | #### Defined in
358 |
359 | [snippets.ts:170](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/snippets.ts#L170)
360 |
361 | ___
362 |
363 | ### getBranchMiddleware
364 |
365 | ▸ **getBranchMiddleware**\<`T`\>(`condition`, `trueMiddleware`, `falseMiddleware`): [`Middleware`](README.md#middleware)\<`T`\>
366 |
367 | By condition splits the middleware
368 |
369 | Example:
370 |
371 | ```ts
372 | getBranchMiddleware(
373 | async context => context.is('Content-Type', 'json'),
374 | myBodyParser.json(),
375 | myBodyParser.urlencoded()
376 | );
377 | ```
378 |
379 | Static condition
380 |
381 | ```ts
382 | getBranchMiddleware(
383 | process.env.NODE_ENV === 'production',
384 | logger.loggedContextToFile(),
385 | logger.loggedContextToConsole()
386 | );
387 | ```
388 |
389 | #### Type parameters
390 |
391 | | Name |
392 | | :------ |
393 | | `T` |
394 |
395 | #### Parameters
396 |
397 | | Name | Type |
398 | | :------ | :------ |
399 | | `condition` | [`BranchMiddlewareCondition`](README.md#branchmiddlewarecondition)\<`T`\> |
400 | | `trueMiddleware` | [`Middleware`](README.md#middleware)\<`T`\> |
401 | | `falseMiddleware` | [`Middleware`](README.md#middleware)\<`T`\> |
402 |
403 | #### Returns
404 |
405 | [`Middleware`](README.md#middleware)\<`T`\>
406 |
407 | #### Defined in
408 |
409 | [snippets.ts:109](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/snippets.ts#L109)
410 |
411 | ___
412 |
413 | ### getCaughtMiddleware
414 |
415 | ▸ **getCaughtMiddleware**\<`T`\>(`errorHandler`): [`Middleware`](README.md#middleware)\<`T`\>
416 |
417 | Catches errors in the middleware chain
418 |
419 | Example:
420 | ```js
421 | getCaughtMiddleware((context, error) => {
422 | if (error instanceof NetworkError) {
423 | return context.send('Sorry, network issues 😔');
424 | }
425 |
426 | throw error;
427 | })
428 | ```
429 |
430 | Without a snippet, it would look like this:
431 |
432 | ```js
433 | async (context, next) => {
434 | try {
435 | await next();
436 | } catch (error) {
437 | if (error instanceof NetworkError) {
438 | return context.send('Sorry, network issues 😔');
439 | }
440 |
441 | throw error;
442 | }
443 | };
444 | ```
445 |
446 | #### Type parameters
447 |
448 | | Name |
449 | | :------ |
450 | | `T` |
451 |
452 | #### Parameters
453 |
454 | | Name | Type |
455 | | :------ | :------ |
456 | | `errorHandler` | [`CaughtMiddlewareHandler`](README.md#caughtmiddlewarehandler)\<`T`\> |
457 |
458 | #### Returns
459 |
460 | [`Middleware`](README.md#middleware)\<`T`\>
461 |
462 | #### Defined in
463 |
464 | [snippets.ts:262](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/snippets.ts#L262)
465 |
466 | ___
467 |
468 | ### getConcurrencyMiddleware
469 |
470 | ▸ **getConcurrencyMiddleware**\<`T`\>(`middlewares`): [`Middleware`](README.md#middleware)\<`T`\>
471 |
472 | Concurrently launches middleware,
473 | the chain will continue if `next()` is called in all middlewares
474 |
475 | **Warning: Error interrupts all others**
476 |
477 | Example:
478 |
479 | ```ts
480 | getConcurrencyMiddleware(
481 | initializeUser,
482 | initializeSession,
483 | initializeDatabase
484 | );
485 | ```
486 |
487 | #### Type parameters
488 |
489 | | Name |
490 | | :------ |
491 | | `T` |
492 |
493 | #### Parameters
494 |
495 | | Name | Type |
496 | | :------ | :------ |
497 | | `middlewares` | [`Middleware`](README.md#middleware)\<`T`\>[] |
498 |
499 | #### Returns
500 |
501 | [`Middleware`](README.md#middleware)\<`T`\>
502 |
503 | #### Defined in
504 |
505 | [snippets.ts:288](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/snippets.ts#L288)
506 |
507 | ___
508 |
509 | ### getEnforceMiddleware
510 |
511 | ▸ **getEnforceMiddleware**\<`T`\>(`beforeMiddleware`, `middleware`, `afterMiddleware`): [`Middleware`](README.md#middleware)\<`T`\>
512 |
513 | Runs middleware before and after the main
514 |
515 | Example:
516 |
517 | ```ts
518 | getEnforceMiddleware(
519 | prepareData,
520 | sendData,
521 | clearData
522 | );
523 |
524 | #### Type parameters
525 |
526 | | Name |
527 | | :------ |
528 | | `T` |
529 |
530 | #### Parameters
531 |
532 | | Name | Type |
533 | | :------ | :------ |
534 | | `beforeMiddleware` | [`Middleware`](README.md#middleware)\<`T`\> |
535 | | `middleware` | [`Middleware`](README.md#middleware)\<`T`\> |
536 | | `afterMiddleware` | [`Middleware`](README.md#middleware)\<`T`\> |
537 |
538 | #### Returns
539 |
540 | [`Middleware`](README.md#middleware)\<`T`\>
541 |
542 | #### Defined in
543 |
544 | [snippets.ts:214](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/snippets.ts#L214)
545 |
546 | ___
547 |
548 | ### getFilterMiddleware
549 |
550 | ▸ **getFilterMiddleware**\<`T`\>(`condition`, `filterMiddleware`): [`Middleware`](README.md#middleware)\<`T`\>
551 |
552 | Conditionally runs middleware or stops the chain
553 |
554 | Example:
555 |
556 | ```ts
557 | getFilterMiddleware(
558 | context => context.authorized,
559 | middlewareForAuthorized
560 | );
561 | ```
562 |
563 | #### Type parameters
564 |
565 | | Name |
566 | | :------ |
567 | | `T` |
568 |
569 | #### Parameters
570 |
571 | | Name | Type |
572 | | :------ | :------ |
573 | | `condition` | [`BranchMiddlewareCondition`](README.md#branchmiddlewarecondition)\<`T`\> |
574 | | `filterMiddleware` | [`Middleware`](README.md#middleware)\<`T`\> |
575 |
576 | #### Returns
577 |
578 | [`Middleware`](README.md#middleware)\<`T`\>
579 |
580 | #### Defined in
581 |
582 | [snippets.ts:152](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/snippets.ts#L152)
583 |
584 | ___
585 |
586 | ### getForkMiddleware
587 |
588 | ▸ **getForkMiddleware**\<`T`\>(`middleware`): [`Middleware`](README.md#middleware)\<`T`\>
589 |
590 | Runs the middleware at the next event loop and force call `next()`
591 |
592 | Example:
593 |
594 | ```ts
595 | getForkMiddleware((context) => {
596 | statisticsMiddlewares(context).catch(console.error);
597 | });
598 | ```
599 |
600 | #### Type parameters
601 |
602 | | Name |
603 | | :------ |
604 | | `T` |
605 |
606 | #### Parameters
607 |
608 | | Name | Type |
609 | | :------ | :------ |
610 | | `middleware` | [`Middleware`](README.md#middleware)\<`T`\> |
611 |
612 | #### Returns
613 |
614 | [`Middleware`](README.md#middleware)\<`T`\>
615 |
616 | #### Defined in
617 |
618 | [snippets.ts:79](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/snippets.ts#L79)
619 |
620 | ___
621 |
622 | ### getLazyMiddleware
623 |
624 | ▸ **getLazyMiddleware**\<`T`\>(`factory`): [`Middleware`](README.md#middleware)\<`T`\>
625 |
626 | Lazily asynchronously gets middleware
627 |
628 | Example:
629 |
630 | ```ts
631 | getLazyMiddleware(async (context) => {
632 | const route = await getSomeRoute(context.path) // Promise;
633 |
634 | return route;
635 | });
636 | ```
637 |
638 | #### Type parameters
639 |
640 | | Name |
641 | | :------ |
642 | | `T` |
643 |
644 | #### Parameters
645 |
646 | | Name | Type |
647 | | :------ | :------ |
648 | | `factory` | [`LazyMiddlewareFactory`](README.md#lazymiddlewarefactory)\<`T`\> |
649 |
650 | #### Returns
651 |
652 | [`Middleware`](README.md#middleware)\<`T`\>
653 |
654 | #### Defined in
655 |
656 | [snippets.ts:36](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/snippets.ts#L36)
657 |
658 | ___
659 |
660 | ### getOptionalMiddleware
661 |
662 | ▸ **getOptionalMiddleware**\<`T`\>(`condition`, `optionalMiddleware`): [`Middleware`](README.md#middleware)\<`T`\>
663 |
664 | Conditionally runs optional middleware or skips middleware
665 |
666 | Example:
667 |
668 | ```ts
669 | getOptionalMiddleware(
670 | context => context.user.isAdmin,
671 | addFieldsForAdmin
672 | );
673 | ```
674 |
675 | #### Type parameters
676 |
677 | | Name |
678 | | :------ |
679 | | `T` |
680 |
681 | #### Parameters
682 |
683 | | Name | Type |
684 | | :------ | :------ |
685 | | `condition` | [`BranchMiddlewareCondition`](README.md#branchmiddlewarecondition)\<`T`\> |
686 | | `optionalMiddleware` | [`Middleware`](README.md#middleware)\<`T`\> |
687 |
688 | #### Returns
689 |
690 | [`Middleware`](README.md#middleware)\<`T`\>
691 |
692 | #### Defined in
693 |
694 | [snippets.ts:135](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/snippets.ts#L135)
695 |
696 | ___
697 |
698 | ### getTapMiddleware
699 |
700 | ▸ **getTapMiddleware**\<`T`\>(`middleware`): [`Middleware`](README.md#middleware)\<`T`\>
701 |
702 | Runs the middleware and force call `next()`
703 |
704 | Example:
705 |
706 | ```ts
707 | getTapMiddleware((context) => {
708 | console.log('Context', context);
709 | });
710 | ```
711 |
712 | #### Type parameters
713 |
714 | | Name |
715 | | :------ |
716 | | `T` |
717 |
718 | #### Parameters
719 |
720 | | Name | Type |
721 | | :------ | :------ |
722 | | `middleware` | [`Middleware`](README.md#middleware)\<`T`\> |
723 |
724 | #### Returns
725 |
726 | [`Middleware`](README.md#middleware)\<`T`\>
727 |
728 | #### Defined in
729 |
730 | [snippets.ts:60](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/snippets.ts#L60)
731 |
732 | ___
733 |
734 | ### noopNext
735 |
736 | ▸ **noopNext**(): `Promise`\<`unknown`\>
737 |
738 | Noop for call `next()` in middleware
739 |
740 | #### Returns
741 |
742 | `Promise`\<`unknown`\>
743 |
744 | #### Defined in
745 |
746 | [helpers.ts:30](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/helpers.ts#L30)
747 |
748 | ___
749 |
750 | ### skipMiddleware
751 |
752 | ▸ **skipMiddleware**\<`T`\>(`context`, `next`): `Promise`\<`unknown`\>
753 |
754 | Call `next()` in middleware
755 |
756 | #### Type parameters
757 |
758 | | Name |
759 | | :------ |
760 | | `T` |
761 |
762 | #### Parameters
763 |
764 | | Name | Type |
765 | | :------ | :------ |
766 | | `context` | `T` |
767 | | `next` | [`NextMiddleware`](README.md#nextmiddleware) |
768 |
769 | #### Returns
770 |
771 | `Promise`\<`unknown`\>
772 |
773 | #### Defined in
774 |
775 | [snippets.ts:16](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/snippets.ts#L16)
776 |
777 | ___
778 |
779 | ### stopMiddleware
780 |
781 | ▸ **stopMiddleware**\<`T`\>(`context`, `next`): `Promise`\<`void`\>
782 |
783 | Does not call `next()` in middleware
784 |
785 | #### Type parameters
786 |
787 | | Name |
788 | | :------ |
789 | | `T` |
790 |
791 | #### Parameters
792 |
793 | | Name | Type |
794 | | :------ | :------ |
795 | | `context` | `T` |
796 | | `next` | [`NextMiddleware`](README.md#nextmiddleware) |
797 |
798 | #### Returns
799 |
800 | `Promise`\<`void`\>
801 |
802 | #### Defined in
803 |
804 | [snippets.ts:21](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/snippets.ts#L21)
805 |
--------------------------------------------------------------------------------
/docs/api-reference/classes/Composer.md:
--------------------------------------------------------------------------------
1 | [middleware-io](../README.md) / Composer
2 |
3 | # Class: Composer\
4 |
5 | A simple middleware compose builder
6 |
7 | ## Type parameters
8 |
9 | | Name | Type |
10 | | :------ | :------ |
11 | | `T` | extends [`UnknownObject`](../README.md#unknownobject) |
12 | | `R` | `T` |
13 |
14 | ## Table of contents
15 |
16 | ### Constructors
17 |
18 | - [constructor](Composer.md#constructor)
19 |
20 | ### Properties
21 |
22 | - [middlewares](Composer.md#middlewares)
23 |
24 | ### Accessors
25 |
26 | - [length](Composer.md#length)
27 |
28 | ### Methods
29 |
30 | - [after](Composer.md#after)
31 | - [before](Composer.md#before)
32 | - [branch](Composer.md#branch)
33 | - [caught](Composer.md#caught)
34 | - [clone](Composer.md#clone)
35 | - [compose](Composer.md#compose)
36 | - [concurrency](Composer.md#concurrency)
37 | - [enforce](Composer.md#enforce)
38 | - [filter](Composer.md#filter)
39 | - [fork](Composer.md#fork)
40 | - [lazy](Composer.md#lazy)
41 | - [optional](Composer.md#optional)
42 | - [tap](Composer.md#tap)
43 | - [use](Composer.md#use)
44 | - [builder](Composer.md#builder)
45 |
46 | ## Constructors
47 |
48 | ### constructor
49 |
50 | • **new Composer**\<`T`, `R`\>(): [`Composer`](Composer.md)\<`T`, `R`\>
51 |
52 | #### Type parameters
53 |
54 | | Name | Type |
55 | | :------ | :------ |
56 | | `T` | extends [`UnknownObject`](../README.md#unknownobject) |
57 | | `R` | `T` |
58 |
59 | #### Returns
60 |
61 | [`Composer`](Composer.md)\<`T`, `R`\>
62 |
63 | ## Properties
64 |
65 | ### middlewares
66 |
67 | • `Protected` **middlewares**: [`Middleware`](../README.md#middleware)\<`R`\>[] = `[]`
68 |
69 | #### Defined in
70 |
71 | [composer.ts:30](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L30)
72 |
73 | ## Accessors
74 |
75 | ### length
76 |
77 | • `get` **length**(): `number`
78 |
79 | The number of middleware installed in Composer
80 |
81 | #### Returns
82 |
83 | `number`
84 |
85 | #### Defined in
86 |
87 | [composer.ts:42](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L42)
88 |
89 | ## Methods
90 |
91 | ### after
92 |
93 | ▸ **after**\<`V`\>(`middleware`, `afterMiddleware`): [`Composer`](Composer.md)\<`T` & `V`, `R`\>
94 |
95 | Runs the second middleware after the main
96 |
97 | #### Type parameters
98 |
99 | | Name | Type |
100 | | :------ | :------ |
101 | | `V` | [`UnknownObject`](../README.md#unknownobject) |
102 |
103 | #### Parameters
104 |
105 | | Name | Type |
106 | | :------ | :------ |
107 | | `middleware` | [`Middleware`](../README.md#middleware)\<`T` & `V`\> |
108 | | `afterMiddleware` | [`Middleware`](../README.md#middleware)\<`T` & `V`\> |
109 |
110 | #### Returns
111 |
112 | [`Composer`](Composer.md)\<`T` & `V`, `R`\>
113 |
114 | #### Defined in
115 |
116 | [composer.ts:141](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L141)
117 |
118 | ___
119 |
120 | ### before
121 |
122 | ▸ **before**\<`V`\>(`beforeMiddleware`, `middleware`): [`Composer`](Composer.md)\<`T` & `V`, `R`\>
123 |
124 | Runs the second middleware before the main
125 |
126 | #### Type parameters
127 |
128 | | Name | Type |
129 | | :------ | :------ |
130 | | `V` | [`UnknownObject`](../README.md#unknownobject) |
131 |
132 | #### Parameters
133 |
134 | | Name | Type |
135 | | :------ | :------ |
136 | | `beforeMiddleware` | [`Middleware`](../README.md#middleware)\<`T` & `V`\> |
137 | | `middleware` | [`Middleware`](../README.md#middleware)\<`T` & `V`\> |
138 |
139 | #### Returns
140 |
141 | [`Composer`](Composer.md)\<`T` & `V`, `R`\>
142 |
143 | #### Defined in
144 |
145 | [composer.ts:131](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L131)
146 |
147 | ___
148 |
149 | ### branch
150 |
151 | ▸ **branch**\<`V`\>(`condition`, `trueMiddleware`, `falseMiddleware`): [`Composer`](Composer.md)\<`T` & `V`, `R`\>
152 |
153 | By condition splits the middleware
154 |
155 | #### Type parameters
156 |
157 | | Name | Type |
158 | | :------ | :------ |
159 | | `V` | [`UnknownObject`](../README.md#unknownobject) |
160 |
161 | #### Parameters
162 |
163 | | Name | Type |
164 | | :------ | :------ |
165 | | `condition` | [`BranchMiddlewareCondition`](../README.md#branchmiddlewarecondition)\<`T` & `V`\> |
166 | | `trueMiddleware` | [`Middleware`](../README.md#middleware)\<`T` & `V`\> |
167 | | `falseMiddleware` | [`Middleware`](../README.md#middleware)\<`T` & `V`\> |
168 |
169 | #### Returns
170 |
171 | [`Composer`](Composer.md)\<`T` & `V`, `R`\>
172 |
173 | #### Defined in
174 |
175 | [composer.ts:92](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L92)
176 |
177 | ___
178 |
179 | ### caught
180 |
181 | ▸ **caught**\<`V`\>(`errorHandler`): [`Composer`](Composer.md)\<`T` & `V`, `R`\>
182 |
183 | Catches errors in the middleware chain
184 |
185 | #### Type parameters
186 |
187 | | Name | Type |
188 | | :------ | :------ |
189 | | `V` | [`UnknownObject`](../README.md#unknownobject) |
190 |
191 | #### Parameters
192 |
193 | | Name | Type |
194 | | :------ | :------ |
195 | | `errorHandler` | [`CaughtMiddlewareHandler`](../README.md#caughtmiddlewarehandler)\<`T` & `V`\> |
196 |
197 | #### Returns
198 |
199 | [`Composer`](Composer.md)\<`T` & `V`, `R`\>
200 |
201 | #### Defined in
202 |
203 | [composer.ts:162](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L162)
204 |
205 | ___
206 |
207 | ### clone
208 |
209 | ▸ **clone**(): [`Composer`](Composer.md)\<`T`, `R`\>
210 |
211 | Clones a composer object
212 |
213 | #### Returns
214 |
215 | [`Composer`](Composer.md)\<`T`, `R`\>
216 |
217 | #### Defined in
218 |
219 | [composer.ts:49](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L49)
220 |
221 | ___
222 |
223 | ### compose
224 |
225 | ▸ **compose**(): [`Middleware`](../README.md#middleware)\<`R`\>
226 |
227 | Compose middleware handlers into a single handler
228 |
229 | #### Returns
230 |
231 | [`Middleware`](../README.md#middleware)\<`R`\>
232 |
233 | #### Defined in
234 |
235 | [composer.ts:177](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L177)
236 |
237 | ___
238 |
239 | ### concurrency
240 |
241 | ▸ **concurrency**\<`V`\>(`middlewares`): [`Composer`](Composer.md)\<`T` & `V`, `R`\>
242 |
243 | Concurrently launches middleware,
244 | the chain will continue if `next()` is called in all middlewares
245 |
246 | #### Type parameters
247 |
248 | | Name | Type |
249 | | :------ | :------ |
250 | | `V` | [`UnknownObject`](../README.md#unknownobject) |
251 |
252 | #### Parameters
253 |
254 | | Name | Type |
255 | | :------ | :------ |
256 | | `middlewares` | [`Middleware`](../README.md#middleware)\<`T` & `V`\>[] |
257 |
258 | #### Returns
259 |
260 | [`Composer`](Composer.md)\<`T` & `V`, `R`\>
261 |
262 | #### Defined in
263 |
264 | [composer.ts:170](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L170)
265 |
266 | ___
267 |
268 | ### enforce
269 |
270 | ▸ **enforce**\<`V`\>(`beforeMiddleware`, `middleware`, `afterMiddleware`): [`Composer`](Composer.md)\<`T` & `V`, `R`\>
271 |
272 | Runs middleware before and after the main
273 |
274 | #### Type parameters
275 |
276 | | Name | Type |
277 | | :------ | :------ |
278 | | `V` | [`UnknownObject`](../README.md#unknownobject) |
279 |
280 | #### Parameters
281 |
282 | | Name | Type |
283 | | :------ | :------ |
284 | | `beforeMiddleware` | [`Middleware`](../README.md#middleware)\<`T` & `V`\> |
285 | | `middleware` | [`Middleware`](../README.md#middleware)\<`T` & `V`\> |
286 | | `afterMiddleware` | [`Middleware`](../README.md#middleware)\<`T` & `V`\> |
287 |
288 | #### Returns
289 |
290 | [`Composer`](Composer.md)\<`T` & `V`, `R`\>
291 |
292 | #### Defined in
293 |
294 | [composer.ts:151](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L151)
295 |
296 | ___
297 |
298 | ### filter
299 |
300 | ▸ **filter**\<`V`\>(`condition`, `filterMiddleware`): [`Composer`](Composer.md)\<`T` & `V`, `R`\>
301 |
302 | Conditionally runs middleware or stops the chain
303 |
304 | #### Type parameters
305 |
306 | | Name | Type |
307 | | :------ | :------ |
308 | | `V` | [`UnknownObject`](../README.md#unknownobject) |
309 |
310 | #### Parameters
311 |
312 | | Name | Type |
313 | | :------ | :------ |
314 | | `condition` | [`BranchMiddlewareCondition`](../README.md#branchmiddlewarecondition)\<`T` & `V`\> |
315 | | `filterMiddleware` | [`Middleware`](../README.md#middleware)\<`T` & `V`\> |
316 |
317 | #### Returns
318 |
319 | [`Composer`](Composer.md)\<`T` & `V`, `R`\>
320 |
321 | #### Defined in
322 |
323 | [composer.ts:121](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L121)
324 |
325 | ___
326 |
327 | ### fork
328 |
329 | ▸ **fork**\<`V`\>(`middleware`): [`Composer`](Composer.md)\<`T` & `V`, `R`\>
330 |
331 | Runs the middleware at the next event loop and force call `next()`
332 |
333 | #### Type parameters
334 |
335 | | Name | Type |
336 | | :------ | :------ |
337 | | `V` | [`UnknownObject`](../README.md#unknownobject) |
338 |
339 | #### Parameters
340 |
341 | | Name | Type |
342 | | :------ | :------ |
343 | | `middleware` | [`Middleware`](../README.md#middleware)\<`T` & `V`\> |
344 |
345 | #### Returns
346 |
347 | [`Composer`](Composer.md)\<`T` & `V`, `R`\>
348 |
349 | #### Defined in
350 |
351 | [composer.ts:85](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L85)
352 |
353 | ___
354 |
355 | ### lazy
356 |
357 | ▸ **lazy**\<`V`\>(`factory`): [`Composer`](Composer.md)\<`T` & `V`, `R`\>
358 |
359 | Lazily asynchronously gets middleware
360 |
361 | #### Type parameters
362 |
363 | | Name | Type |
364 | | :------ | :------ |
365 | | `V` | [`UnknownObject`](../README.md#unknownobject) |
366 |
367 | #### Parameters
368 |
369 | | Name | Type |
370 | | :------ | :------ |
371 | | `factory` | [`LazyMiddlewareFactory`](../README.md#lazymiddlewarefactory)\<`T` & `V`\> |
372 |
373 | #### Returns
374 |
375 | [`Composer`](Composer.md)\<`T` & `V`, `R`\>
376 |
377 | #### Defined in
378 |
379 | [composer.ts:71](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L71)
380 |
381 | ___
382 |
383 | ### optional
384 |
385 | ▸ **optional**\<`V`\>(`condition`, `optionalMiddleware`): [`Composer`](Composer.md)\<`T` & `V`, `R`\>
386 |
387 | Conditionally runs optional middleware or skips middleware
388 |
389 | #### Type parameters
390 |
391 | | Name | Type |
392 | | :------ | :------ |
393 | | `V` | [`UnknownObject`](../README.md#unknownobject) |
394 |
395 | #### Parameters
396 |
397 | | Name | Type |
398 | | :------ | :------ |
399 | | `condition` | [`BranchMiddlewareCondition`](../README.md#branchmiddlewarecondition)\<`T` & `V`\> |
400 | | `optionalMiddleware` | [`Middleware`](../README.md#middleware)\<`T` & `V`\> |
401 |
402 | #### Returns
403 |
404 | [`Composer`](Composer.md)\<`T` & `V`, `R`\>
405 |
406 | #### Defined in
407 |
408 | [composer.ts:111](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L111)
409 |
410 | ___
411 |
412 | ### tap
413 |
414 | ▸ **tap**\<`V`\>(`middleware`): [`Composer`](Composer.md)\<`T` & `V`, `R`\>
415 |
416 | Runs the middleware and force call `next()`
417 |
418 | #### Type parameters
419 |
420 | | Name | Type |
421 | | :------ | :------ |
422 | | `V` | [`UnknownObject`](../README.md#unknownobject) |
423 |
424 | #### Parameters
425 |
426 | | Name | Type |
427 | | :------ | :------ |
428 | | `middleware` | [`Middleware`](../README.md#middleware)\<`T` & `V`\> |
429 |
430 | #### Returns
431 |
432 | [`Composer`](Composer.md)\<`T` & `V`, `R`\>
433 |
434 | #### Defined in
435 |
436 | [composer.ts:78](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L78)
437 |
438 | ___
439 |
440 | ### use
441 |
442 | ▸ **use**\<`V`\>(`middleware`): [`Composer`](Composer.md)\<`T` & `V`, `R`\>
443 |
444 | Adds middleware to the chain
445 |
446 | #### Type parameters
447 |
448 | | Name | Type |
449 | | :------ | :------ |
450 | | `V` | [`UnknownObject`](../README.md#unknownobject) |
451 |
452 | #### Parameters
453 |
454 | | Name | Type |
455 | | :------ | :------ |
456 | | `middleware` | [`Middleware`](../README.md#middleware)\<`T` & `V`\> |
457 |
458 | #### Returns
459 |
460 | [`Composer`](Composer.md)\<`T` & `V`, `R`\>
461 |
462 | #### Defined in
463 |
464 | [composer.ts:60](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L60)
465 |
466 | ___
467 |
468 | ### builder
469 |
470 | ▸ **builder**\<`Context`\>(): [`Composer`](Composer.md)\<`Context`, `Context`\>
471 |
472 | Invokes a new instance of the Composer class
473 |
474 | #### Type parameters
475 |
476 | | Name | Type |
477 | | :------ | :------ |
478 | | `Context` | extends [`UnknownObject`](../README.md#unknownobject) |
479 |
480 | #### Returns
481 |
482 | [`Composer`](Composer.md)\<`Context`, `Context`\>
483 |
484 | #### Defined in
485 |
486 | [composer.ts:35](https://github.com/negezor/middleware-io/blob/cfc102d315382709d9f9d43771812ee5ab488e62/src/composer.ts#L35)
487 |
--------------------------------------------------------------------------------
/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "middleware-io",
3 | "version": "2.8.1",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "middleware-io",
9 | "version": "2.8.1",
10 | "license": "MIT",
11 | "devDependencies": {
12 | "@biomejs/biome": "^1.8.1",
13 | "@types/node": "^20.14.2",
14 | "rollup": "^4.18.0",
15 | "rollup-plugin-typescript2": "^0.36.0",
16 | "tinybench": "^2.8.0",
17 | "tsx": "^4.15.5",
18 | "typedoc": "^0.25.13",
19 | "typedoc-plugin-markdown": "^4.0.3",
20 | "typescript": "^5.4.5"
21 | },
22 | "engines": {
23 | "node": ">=12.0.0"
24 | }
25 | },
26 | "node_modules/@biomejs/biome": {
27 | "version": "1.8.1",
28 | "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.8.1.tgz",
29 | "integrity": "sha512-fQXGfvq6DIXem12dGQCM2tNF+vsNHH1qs3C7WeOu75Pd0trduoTmoO7G4ntLJ2qDs5wuw981H+cxQhi1uHnAtA==",
30 | "dev": true,
31 | "hasInstallScript": true,
32 | "license": "MIT OR Apache-2.0",
33 | "bin": {
34 | "biome": "bin/biome"
35 | },
36 | "engines": {
37 | "node": ">=14.21.3"
38 | },
39 | "funding": {
40 | "type": "opencollective",
41 | "url": "https://opencollective.com/biome"
42 | },
43 | "optionalDependencies": {
44 | "@biomejs/cli-darwin-arm64": "1.8.1",
45 | "@biomejs/cli-darwin-x64": "1.8.1",
46 | "@biomejs/cli-linux-arm64": "1.8.1",
47 | "@biomejs/cli-linux-arm64-musl": "1.8.1",
48 | "@biomejs/cli-linux-x64": "1.8.1",
49 | "@biomejs/cli-linux-x64-musl": "1.8.1",
50 | "@biomejs/cli-win32-arm64": "1.8.1",
51 | "@biomejs/cli-win32-x64": "1.8.1"
52 | }
53 | },
54 | "node_modules/@biomejs/cli-darwin-arm64": {
55 | "version": "1.8.1",
56 | "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.8.1.tgz",
57 | "integrity": "sha512-XLiB7Uu6GALIOBWzQ2aMD0ru4Ly5/qSeQF7kk3AabzJ/kwsEWSe33iVySBP/SS2qv25cgqNiLksjGcw2bHT3mw==",
58 | "cpu": [
59 | "arm64"
60 | ],
61 | "dev": true,
62 | "license": "MIT OR Apache-2.0",
63 | "optional": true,
64 | "os": [
65 | "darwin"
66 | ],
67 | "engines": {
68 | "node": ">=14.21.3"
69 | }
70 | },
71 | "node_modules/@biomejs/cli-darwin-x64": {
72 | "version": "1.8.1",
73 | "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.8.1.tgz",
74 | "integrity": "sha512-uMTSxVLMfqkBVqyc25hSn83jBbp+wtWjzM/pHFlKXt3htJuw7FErVGW0nmQ9Sxa9vJ7GcqoltLMl28VQRIMYzg==",
75 | "cpu": [
76 | "x64"
77 | ],
78 | "dev": true,
79 | "license": "MIT OR Apache-2.0",
80 | "optional": true,
81 | "os": [
82 | "darwin"
83 | ],
84 | "engines": {
85 | "node": ">=14.21.3"
86 | }
87 | },
88 | "node_modules/@biomejs/cli-linux-arm64": {
89 | "version": "1.8.1",
90 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.8.1.tgz",
91 | "integrity": "sha512-3SzZRuC/9Oi2P2IBNPsEj0KXxSXUEYRR2kfRF/Ve8QAfGgrt4qnwuWd6QQKKN5R+oYH691qjm+cXBKEcrP1v/Q==",
92 | "cpu": [
93 | "arm64"
94 | ],
95 | "dev": true,
96 | "license": "MIT OR Apache-2.0",
97 | "optional": true,
98 | "os": [
99 | "linux"
100 | ],
101 | "engines": {
102 | "node": ">=14.21.3"
103 | }
104 | },
105 | "node_modules/@biomejs/cli-linux-arm64-musl": {
106 | "version": "1.8.1",
107 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.8.1.tgz",
108 | "integrity": "sha512-UQ8Wc01J0wQL+5AYOc7qkJn20B4PZmQL1KrmDZh7ot0DvD6aX4+8mmfd/dG5b6Zjo/44QvCKcvkFGCMRYuhWZA==",
109 | "cpu": [
110 | "arm64"
111 | ],
112 | "dev": true,
113 | "license": "MIT OR Apache-2.0",
114 | "optional": true,
115 | "os": [
116 | "linux"
117 | ],
118 | "engines": {
119 | "node": ">=14.21.3"
120 | }
121 | },
122 | "node_modules/@biomejs/cli-linux-x64": {
123 | "version": "1.8.1",
124 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.8.1.tgz",
125 | "integrity": "sha512-AeBycVdNrTzsyYKEOtR2R0Ph0hCD0sCshcp2aOnfGP0hCZbtFg09D0SdKLbyzKntisY41HxKVrydYiaApp+2uw==",
126 | "cpu": [
127 | "x64"
128 | ],
129 | "dev": true,
130 | "license": "MIT OR Apache-2.0",
131 | "optional": true,
132 | "os": [
133 | "linux"
134 | ],
135 | "engines": {
136 | "node": ">=14.21.3"
137 | }
138 | },
139 | "node_modules/@biomejs/cli-linux-x64-musl": {
140 | "version": "1.8.1",
141 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.8.1.tgz",
142 | "integrity": "sha512-fYbP/kNu/rtZ4kKzWVocIdqZOtBSUEg9qUhZaao3dy3CRzafR6u6KDtBeSCnt47O+iLnks1eOR1TUxzr5+QuqA==",
143 | "cpu": [
144 | "x64"
145 | ],
146 | "dev": true,
147 | "license": "MIT OR Apache-2.0",
148 | "optional": true,
149 | "os": [
150 | "linux"
151 | ],
152 | "engines": {
153 | "node": ">=14.21.3"
154 | }
155 | },
156 | "node_modules/@biomejs/cli-win32-arm64": {
157 | "version": "1.8.1",
158 | "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.8.1.tgz",
159 | "integrity": "sha512-6tEd1H/iFKpgpE3OIB7oNgW5XkjiVMzMRPL8zYoZ036YfuJ5nMYm9eB9H/y81+8Z76vL48fiYzMPotJwukGPqQ==",
160 | "cpu": [
161 | "arm64"
162 | ],
163 | "dev": true,
164 | "license": "MIT OR Apache-2.0",
165 | "optional": true,
166 | "os": [
167 | "win32"
168 | ],
169 | "engines": {
170 | "node": ">=14.21.3"
171 | }
172 | },
173 | "node_modules/@biomejs/cli-win32-x64": {
174 | "version": "1.8.1",
175 | "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.8.1.tgz",
176 | "integrity": "sha512-g2H31jJzYmS4jkvl6TiyEjEX+Nv79a5km/xn+5DARTp5MBFzC9gwceusSSB2AkJKqZzY131AiACAWjKrVt5Ijw==",
177 | "cpu": [
178 | "x64"
179 | ],
180 | "dev": true,
181 | "license": "MIT OR Apache-2.0",
182 | "optional": true,
183 | "os": [
184 | "win32"
185 | ],
186 | "engines": {
187 | "node": ">=14.21.3"
188 | }
189 | },
190 | "node_modules/@esbuild/aix-ppc64": {
191 | "version": "0.21.5",
192 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
193 | "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
194 | "cpu": [
195 | "ppc64"
196 | ],
197 | "dev": true,
198 | "license": "MIT",
199 | "optional": true,
200 | "os": [
201 | "aix"
202 | ],
203 | "engines": {
204 | "node": ">=12"
205 | }
206 | },
207 | "node_modules/@esbuild/android-arm": {
208 | "version": "0.21.5",
209 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
210 | "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
211 | "cpu": [
212 | "arm"
213 | ],
214 | "dev": true,
215 | "license": "MIT",
216 | "optional": true,
217 | "os": [
218 | "android"
219 | ],
220 | "engines": {
221 | "node": ">=12"
222 | }
223 | },
224 | "node_modules/@esbuild/android-arm64": {
225 | "version": "0.21.5",
226 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
227 | "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
228 | "cpu": [
229 | "arm64"
230 | ],
231 | "dev": true,
232 | "license": "MIT",
233 | "optional": true,
234 | "os": [
235 | "android"
236 | ],
237 | "engines": {
238 | "node": ">=12"
239 | }
240 | },
241 | "node_modules/@esbuild/android-x64": {
242 | "version": "0.21.5",
243 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
244 | "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
245 | "cpu": [
246 | "x64"
247 | ],
248 | "dev": true,
249 | "license": "MIT",
250 | "optional": true,
251 | "os": [
252 | "android"
253 | ],
254 | "engines": {
255 | "node": ">=12"
256 | }
257 | },
258 | "node_modules/@esbuild/darwin-arm64": {
259 | "version": "0.21.5",
260 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
261 | "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
262 | "cpu": [
263 | "arm64"
264 | ],
265 | "dev": true,
266 | "license": "MIT",
267 | "optional": true,
268 | "os": [
269 | "darwin"
270 | ],
271 | "engines": {
272 | "node": ">=12"
273 | }
274 | },
275 | "node_modules/@esbuild/darwin-x64": {
276 | "version": "0.21.5",
277 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
278 | "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
279 | "cpu": [
280 | "x64"
281 | ],
282 | "dev": true,
283 | "license": "MIT",
284 | "optional": true,
285 | "os": [
286 | "darwin"
287 | ],
288 | "engines": {
289 | "node": ">=12"
290 | }
291 | },
292 | "node_modules/@esbuild/freebsd-arm64": {
293 | "version": "0.21.5",
294 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
295 | "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
296 | "cpu": [
297 | "arm64"
298 | ],
299 | "dev": true,
300 | "license": "MIT",
301 | "optional": true,
302 | "os": [
303 | "freebsd"
304 | ],
305 | "engines": {
306 | "node": ">=12"
307 | }
308 | },
309 | "node_modules/@esbuild/freebsd-x64": {
310 | "version": "0.21.5",
311 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
312 | "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
313 | "cpu": [
314 | "x64"
315 | ],
316 | "dev": true,
317 | "license": "MIT",
318 | "optional": true,
319 | "os": [
320 | "freebsd"
321 | ],
322 | "engines": {
323 | "node": ">=12"
324 | }
325 | },
326 | "node_modules/@esbuild/linux-arm": {
327 | "version": "0.21.5",
328 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
329 | "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
330 | "cpu": [
331 | "arm"
332 | ],
333 | "dev": true,
334 | "license": "MIT",
335 | "optional": true,
336 | "os": [
337 | "linux"
338 | ],
339 | "engines": {
340 | "node": ">=12"
341 | }
342 | },
343 | "node_modules/@esbuild/linux-arm64": {
344 | "version": "0.21.5",
345 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
346 | "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
347 | "cpu": [
348 | "arm64"
349 | ],
350 | "dev": true,
351 | "license": "MIT",
352 | "optional": true,
353 | "os": [
354 | "linux"
355 | ],
356 | "engines": {
357 | "node": ">=12"
358 | }
359 | },
360 | "node_modules/@esbuild/linux-ia32": {
361 | "version": "0.21.5",
362 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
363 | "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
364 | "cpu": [
365 | "ia32"
366 | ],
367 | "dev": true,
368 | "license": "MIT",
369 | "optional": true,
370 | "os": [
371 | "linux"
372 | ],
373 | "engines": {
374 | "node": ">=12"
375 | }
376 | },
377 | "node_modules/@esbuild/linux-loong64": {
378 | "version": "0.21.5",
379 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
380 | "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
381 | "cpu": [
382 | "loong64"
383 | ],
384 | "dev": true,
385 | "license": "MIT",
386 | "optional": true,
387 | "os": [
388 | "linux"
389 | ],
390 | "engines": {
391 | "node": ">=12"
392 | }
393 | },
394 | "node_modules/@esbuild/linux-mips64el": {
395 | "version": "0.21.5",
396 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
397 | "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
398 | "cpu": [
399 | "mips64el"
400 | ],
401 | "dev": true,
402 | "license": "MIT",
403 | "optional": true,
404 | "os": [
405 | "linux"
406 | ],
407 | "engines": {
408 | "node": ">=12"
409 | }
410 | },
411 | "node_modules/@esbuild/linux-ppc64": {
412 | "version": "0.21.5",
413 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
414 | "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
415 | "cpu": [
416 | "ppc64"
417 | ],
418 | "dev": true,
419 | "license": "MIT",
420 | "optional": true,
421 | "os": [
422 | "linux"
423 | ],
424 | "engines": {
425 | "node": ">=12"
426 | }
427 | },
428 | "node_modules/@esbuild/linux-riscv64": {
429 | "version": "0.21.5",
430 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
431 | "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
432 | "cpu": [
433 | "riscv64"
434 | ],
435 | "dev": true,
436 | "license": "MIT",
437 | "optional": true,
438 | "os": [
439 | "linux"
440 | ],
441 | "engines": {
442 | "node": ">=12"
443 | }
444 | },
445 | "node_modules/@esbuild/linux-s390x": {
446 | "version": "0.21.5",
447 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
448 | "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
449 | "cpu": [
450 | "s390x"
451 | ],
452 | "dev": true,
453 | "license": "MIT",
454 | "optional": true,
455 | "os": [
456 | "linux"
457 | ],
458 | "engines": {
459 | "node": ">=12"
460 | }
461 | },
462 | "node_modules/@esbuild/linux-x64": {
463 | "version": "0.21.5",
464 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
465 | "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
466 | "cpu": [
467 | "x64"
468 | ],
469 | "dev": true,
470 | "license": "MIT",
471 | "optional": true,
472 | "os": [
473 | "linux"
474 | ],
475 | "engines": {
476 | "node": ">=12"
477 | }
478 | },
479 | "node_modules/@esbuild/netbsd-x64": {
480 | "version": "0.21.5",
481 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
482 | "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
483 | "cpu": [
484 | "x64"
485 | ],
486 | "dev": true,
487 | "license": "MIT",
488 | "optional": true,
489 | "os": [
490 | "netbsd"
491 | ],
492 | "engines": {
493 | "node": ">=12"
494 | }
495 | },
496 | "node_modules/@esbuild/openbsd-x64": {
497 | "version": "0.21.5",
498 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
499 | "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
500 | "cpu": [
501 | "x64"
502 | ],
503 | "dev": true,
504 | "license": "MIT",
505 | "optional": true,
506 | "os": [
507 | "openbsd"
508 | ],
509 | "engines": {
510 | "node": ">=12"
511 | }
512 | },
513 | "node_modules/@esbuild/sunos-x64": {
514 | "version": "0.21.5",
515 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
516 | "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
517 | "cpu": [
518 | "x64"
519 | ],
520 | "dev": true,
521 | "license": "MIT",
522 | "optional": true,
523 | "os": [
524 | "sunos"
525 | ],
526 | "engines": {
527 | "node": ">=12"
528 | }
529 | },
530 | "node_modules/@esbuild/win32-arm64": {
531 | "version": "0.21.5",
532 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
533 | "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
534 | "cpu": [
535 | "arm64"
536 | ],
537 | "dev": true,
538 | "license": "MIT",
539 | "optional": true,
540 | "os": [
541 | "win32"
542 | ],
543 | "engines": {
544 | "node": ">=12"
545 | }
546 | },
547 | "node_modules/@esbuild/win32-ia32": {
548 | "version": "0.21.5",
549 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
550 | "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
551 | "cpu": [
552 | "ia32"
553 | ],
554 | "dev": true,
555 | "license": "MIT",
556 | "optional": true,
557 | "os": [
558 | "win32"
559 | ],
560 | "engines": {
561 | "node": ">=12"
562 | }
563 | },
564 | "node_modules/@esbuild/win32-x64": {
565 | "version": "0.21.5",
566 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
567 | "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
568 | "cpu": [
569 | "x64"
570 | ],
571 | "dev": true,
572 | "license": "MIT",
573 | "optional": true,
574 | "os": [
575 | "win32"
576 | ],
577 | "engines": {
578 | "node": ">=12"
579 | }
580 | },
581 | "node_modules/@rollup/pluginutils": {
582 | "version": "4.2.1",
583 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
584 | "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==",
585 | "dev": true,
586 | "license": "MIT",
587 | "dependencies": {
588 | "estree-walker": "^2.0.1",
589 | "picomatch": "^2.2.2"
590 | },
591 | "engines": {
592 | "node": ">= 8.0.0"
593 | }
594 | },
595 | "node_modules/@rollup/rollup-android-arm-eabi": {
596 | "version": "4.18.0",
597 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz",
598 | "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==",
599 | "cpu": [
600 | "arm"
601 | ],
602 | "dev": true,
603 | "license": "MIT",
604 | "optional": true,
605 | "os": [
606 | "android"
607 | ]
608 | },
609 | "node_modules/@rollup/rollup-android-arm64": {
610 | "version": "4.18.0",
611 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz",
612 | "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==",
613 | "cpu": [
614 | "arm64"
615 | ],
616 | "dev": true,
617 | "license": "MIT",
618 | "optional": true,
619 | "os": [
620 | "android"
621 | ]
622 | },
623 | "node_modules/@rollup/rollup-darwin-arm64": {
624 | "version": "4.18.0",
625 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz",
626 | "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==",
627 | "cpu": [
628 | "arm64"
629 | ],
630 | "dev": true,
631 | "license": "MIT",
632 | "optional": true,
633 | "os": [
634 | "darwin"
635 | ]
636 | },
637 | "node_modules/@rollup/rollup-darwin-x64": {
638 | "version": "4.18.0",
639 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz",
640 | "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==",
641 | "cpu": [
642 | "x64"
643 | ],
644 | "dev": true,
645 | "license": "MIT",
646 | "optional": true,
647 | "os": [
648 | "darwin"
649 | ]
650 | },
651 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
652 | "version": "4.18.0",
653 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz",
654 | "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==",
655 | "cpu": [
656 | "arm"
657 | ],
658 | "dev": true,
659 | "license": "MIT",
660 | "optional": true,
661 | "os": [
662 | "linux"
663 | ]
664 | },
665 | "node_modules/@rollup/rollup-linux-arm-musleabihf": {
666 | "version": "4.18.0",
667 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz",
668 | "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==",
669 | "cpu": [
670 | "arm"
671 | ],
672 | "dev": true,
673 | "license": "MIT",
674 | "optional": true,
675 | "os": [
676 | "linux"
677 | ]
678 | },
679 | "node_modules/@rollup/rollup-linux-arm64-gnu": {
680 | "version": "4.18.0",
681 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz",
682 | "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==",
683 | "cpu": [
684 | "arm64"
685 | ],
686 | "dev": true,
687 | "license": "MIT",
688 | "optional": true,
689 | "os": [
690 | "linux"
691 | ]
692 | },
693 | "node_modules/@rollup/rollup-linux-arm64-musl": {
694 | "version": "4.18.0",
695 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz",
696 | "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==",
697 | "cpu": [
698 | "arm64"
699 | ],
700 | "dev": true,
701 | "license": "MIT",
702 | "optional": true,
703 | "os": [
704 | "linux"
705 | ]
706 | },
707 | "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
708 | "version": "4.18.0",
709 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz",
710 | "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==",
711 | "cpu": [
712 | "ppc64"
713 | ],
714 | "dev": true,
715 | "license": "MIT",
716 | "optional": true,
717 | "os": [
718 | "linux"
719 | ]
720 | },
721 | "node_modules/@rollup/rollup-linux-riscv64-gnu": {
722 | "version": "4.18.0",
723 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz",
724 | "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==",
725 | "cpu": [
726 | "riscv64"
727 | ],
728 | "dev": true,
729 | "license": "MIT",
730 | "optional": true,
731 | "os": [
732 | "linux"
733 | ]
734 | },
735 | "node_modules/@rollup/rollup-linux-s390x-gnu": {
736 | "version": "4.18.0",
737 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz",
738 | "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==",
739 | "cpu": [
740 | "s390x"
741 | ],
742 | "dev": true,
743 | "license": "MIT",
744 | "optional": true,
745 | "os": [
746 | "linux"
747 | ]
748 | },
749 | "node_modules/@rollup/rollup-linux-x64-gnu": {
750 | "version": "4.18.0",
751 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz",
752 | "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==",
753 | "cpu": [
754 | "x64"
755 | ],
756 | "dev": true,
757 | "license": "MIT",
758 | "optional": true,
759 | "os": [
760 | "linux"
761 | ]
762 | },
763 | "node_modules/@rollup/rollup-linux-x64-musl": {
764 | "version": "4.18.0",
765 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz",
766 | "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==",
767 | "cpu": [
768 | "x64"
769 | ],
770 | "dev": true,
771 | "license": "MIT",
772 | "optional": true,
773 | "os": [
774 | "linux"
775 | ]
776 | },
777 | "node_modules/@rollup/rollup-win32-arm64-msvc": {
778 | "version": "4.18.0",
779 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz",
780 | "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==",
781 | "cpu": [
782 | "arm64"
783 | ],
784 | "dev": true,
785 | "license": "MIT",
786 | "optional": true,
787 | "os": [
788 | "win32"
789 | ]
790 | },
791 | "node_modules/@rollup/rollup-win32-ia32-msvc": {
792 | "version": "4.18.0",
793 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz",
794 | "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==",
795 | "cpu": [
796 | "ia32"
797 | ],
798 | "dev": true,
799 | "license": "MIT",
800 | "optional": true,
801 | "os": [
802 | "win32"
803 | ]
804 | },
805 | "node_modules/@rollup/rollup-win32-x64-msvc": {
806 | "version": "4.18.0",
807 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz",
808 | "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==",
809 | "cpu": [
810 | "x64"
811 | ],
812 | "dev": true,
813 | "license": "MIT",
814 | "optional": true,
815 | "os": [
816 | "win32"
817 | ]
818 | },
819 | "node_modules/@types/estree": {
820 | "version": "1.0.5",
821 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
822 | "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
823 | "dev": true,
824 | "license": "MIT"
825 | },
826 | "node_modules/@types/node": {
827 | "version": "20.14.2",
828 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz",
829 | "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==",
830 | "dev": true,
831 | "license": "MIT",
832 | "dependencies": {
833 | "undici-types": "~5.26.4"
834 | }
835 | },
836 | "node_modules/ansi-sequence-parser": {
837 | "version": "1.1.1",
838 | "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz",
839 | "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==",
840 | "dev": true,
841 | "license": "MIT"
842 | },
843 | "node_modules/balanced-match": {
844 | "version": "1.0.2",
845 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
846 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
847 | "dev": true,
848 | "license": "MIT"
849 | },
850 | "node_modules/brace-expansion": {
851 | "version": "2.0.1",
852 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
853 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
854 | "dev": true,
855 | "license": "MIT",
856 | "dependencies": {
857 | "balanced-match": "^1.0.0"
858 | }
859 | },
860 | "node_modules/commondir": {
861 | "version": "1.0.1",
862 | "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
863 | "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
864 | "dev": true,
865 | "license": "MIT"
866 | },
867 | "node_modules/esbuild": {
868 | "version": "0.21.5",
869 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
870 | "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
871 | "dev": true,
872 | "hasInstallScript": true,
873 | "license": "MIT",
874 | "bin": {
875 | "esbuild": "bin/esbuild"
876 | },
877 | "engines": {
878 | "node": ">=12"
879 | },
880 | "optionalDependencies": {
881 | "@esbuild/aix-ppc64": "0.21.5",
882 | "@esbuild/android-arm": "0.21.5",
883 | "@esbuild/android-arm64": "0.21.5",
884 | "@esbuild/android-x64": "0.21.5",
885 | "@esbuild/darwin-arm64": "0.21.5",
886 | "@esbuild/darwin-x64": "0.21.5",
887 | "@esbuild/freebsd-arm64": "0.21.5",
888 | "@esbuild/freebsd-x64": "0.21.5",
889 | "@esbuild/linux-arm": "0.21.5",
890 | "@esbuild/linux-arm64": "0.21.5",
891 | "@esbuild/linux-ia32": "0.21.5",
892 | "@esbuild/linux-loong64": "0.21.5",
893 | "@esbuild/linux-mips64el": "0.21.5",
894 | "@esbuild/linux-ppc64": "0.21.5",
895 | "@esbuild/linux-riscv64": "0.21.5",
896 | "@esbuild/linux-s390x": "0.21.5",
897 | "@esbuild/linux-x64": "0.21.5",
898 | "@esbuild/netbsd-x64": "0.21.5",
899 | "@esbuild/openbsd-x64": "0.21.5",
900 | "@esbuild/sunos-x64": "0.21.5",
901 | "@esbuild/win32-arm64": "0.21.5",
902 | "@esbuild/win32-ia32": "0.21.5",
903 | "@esbuild/win32-x64": "0.21.5"
904 | }
905 | },
906 | "node_modules/estree-walker": {
907 | "version": "2.0.2",
908 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
909 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
910 | "dev": true,
911 | "license": "MIT"
912 | },
913 | "node_modules/find-cache-dir": {
914 | "version": "3.3.2",
915 | "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
916 | "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
917 | "dev": true,
918 | "license": "MIT",
919 | "dependencies": {
920 | "commondir": "^1.0.1",
921 | "make-dir": "^3.0.2",
922 | "pkg-dir": "^4.1.0"
923 | },
924 | "engines": {
925 | "node": ">=8"
926 | },
927 | "funding": {
928 | "url": "https://github.com/avajs/find-cache-dir?sponsor=1"
929 | }
930 | },
931 | "node_modules/find-up": {
932 | "version": "4.1.0",
933 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
934 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
935 | "dev": true,
936 | "license": "MIT",
937 | "dependencies": {
938 | "locate-path": "^5.0.0",
939 | "path-exists": "^4.0.0"
940 | },
941 | "engines": {
942 | "node": ">=8"
943 | }
944 | },
945 | "node_modules/fs-extra": {
946 | "version": "10.1.0",
947 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
948 | "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
949 | "dev": true,
950 | "license": "MIT",
951 | "dependencies": {
952 | "graceful-fs": "^4.2.0",
953 | "jsonfile": "^6.0.1",
954 | "universalify": "^2.0.0"
955 | },
956 | "engines": {
957 | "node": ">=12"
958 | }
959 | },
960 | "node_modules/fsevents": {
961 | "version": "2.3.3",
962 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
963 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
964 | "dev": true,
965 | "hasInstallScript": true,
966 | "license": "MIT",
967 | "optional": true,
968 | "os": [
969 | "darwin"
970 | ],
971 | "engines": {
972 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
973 | }
974 | },
975 | "node_modules/get-tsconfig": {
976 | "version": "4.7.5",
977 | "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz",
978 | "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==",
979 | "dev": true,
980 | "license": "MIT",
981 | "dependencies": {
982 | "resolve-pkg-maps": "^1.0.0"
983 | },
984 | "funding": {
985 | "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
986 | }
987 | },
988 | "node_modules/graceful-fs": {
989 | "version": "4.2.11",
990 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
991 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
992 | "dev": true,
993 | "license": "ISC"
994 | },
995 | "node_modules/jsonc-parser": {
996 | "version": "3.2.1",
997 | "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
998 | "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
999 | "dev": true,
1000 | "license": "MIT"
1001 | },
1002 | "node_modules/jsonfile": {
1003 | "version": "6.1.0",
1004 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
1005 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
1006 | "dev": true,
1007 | "license": "MIT",
1008 | "dependencies": {
1009 | "universalify": "^2.0.0"
1010 | },
1011 | "optionalDependencies": {
1012 | "graceful-fs": "^4.1.6"
1013 | }
1014 | },
1015 | "node_modules/locate-path": {
1016 | "version": "5.0.0",
1017 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
1018 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
1019 | "dev": true,
1020 | "license": "MIT",
1021 | "dependencies": {
1022 | "p-locate": "^4.1.0"
1023 | },
1024 | "engines": {
1025 | "node": ">=8"
1026 | }
1027 | },
1028 | "node_modules/lunr": {
1029 | "version": "2.3.9",
1030 | "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
1031 | "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==",
1032 | "dev": true,
1033 | "license": "MIT"
1034 | },
1035 | "node_modules/make-dir": {
1036 | "version": "3.1.0",
1037 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
1038 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
1039 | "dev": true,
1040 | "license": "MIT",
1041 | "dependencies": {
1042 | "semver": "^6.0.0"
1043 | },
1044 | "engines": {
1045 | "node": ">=8"
1046 | },
1047 | "funding": {
1048 | "url": "https://github.com/sponsors/sindresorhus"
1049 | }
1050 | },
1051 | "node_modules/make-dir/node_modules/semver": {
1052 | "version": "6.3.1",
1053 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
1054 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
1055 | "dev": true,
1056 | "license": "ISC",
1057 | "bin": {
1058 | "semver": "bin/semver.js"
1059 | }
1060 | },
1061 | "node_modules/marked": {
1062 | "version": "4.3.0",
1063 | "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz",
1064 | "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==",
1065 | "dev": true,
1066 | "license": "MIT",
1067 | "bin": {
1068 | "marked": "bin/marked.js"
1069 | },
1070 | "engines": {
1071 | "node": ">= 12"
1072 | }
1073 | },
1074 | "node_modules/minimatch": {
1075 | "version": "9.0.4",
1076 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
1077 | "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
1078 | "dev": true,
1079 | "license": "ISC",
1080 | "dependencies": {
1081 | "brace-expansion": "^2.0.1"
1082 | },
1083 | "engines": {
1084 | "node": ">=16 || 14 >=14.17"
1085 | },
1086 | "funding": {
1087 | "url": "https://github.com/sponsors/isaacs"
1088 | }
1089 | },
1090 | "node_modules/p-limit": {
1091 | "version": "2.3.0",
1092 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
1093 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
1094 | "dev": true,
1095 | "license": "MIT",
1096 | "dependencies": {
1097 | "p-try": "^2.0.0"
1098 | },
1099 | "engines": {
1100 | "node": ">=6"
1101 | },
1102 | "funding": {
1103 | "url": "https://github.com/sponsors/sindresorhus"
1104 | }
1105 | },
1106 | "node_modules/p-locate": {
1107 | "version": "4.1.0",
1108 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
1109 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
1110 | "dev": true,
1111 | "license": "MIT",
1112 | "dependencies": {
1113 | "p-limit": "^2.2.0"
1114 | },
1115 | "engines": {
1116 | "node": ">=8"
1117 | }
1118 | },
1119 | "node_modules/p-try": {
1120 | "version": "2.2.0",
1121 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
1122 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
1123 | "dev": true,
1124 | "license": "MIT",
1125 | "engines": {
1126 | "node": ">=6"
1127 | }
1128 | },
1129 | "node_modules/path-exists": {
1130 | "version": "4.0.0",
1131 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
1132 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
1133 | "dev": true,
1134 | "license": "MIT",
1135 | "engines": {
1136 | "node": ">=8"
1137 | }
1138 | },
1139 | "node_modules/picomatch": {
1140 | "version": "2.3.1",
1141 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
1142 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
1143 | "dev": true,
1144 | "license": "MIT",
1145 | "engines": {
1146 | "node": ">=8.6"
1147 | },
1148 | "funding": {
1149 | "url": "https://github.com/sponsors/jonschlinkert"
1150 | }
1151 | },
1152 | "node_modules/pkg-dir": {
1153 | "version": "4.2.0",
1154 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
1155 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
1156 | "dev": true,
1157 | "license": "MIT",
1158 | "dependencies": {
1159 | "find-up": "^4.0.0"
1160 | },
1161 | "engines": {
1162 | "node": ">=8"
1163 | }
1164 | },
1165 | "node_modules/resolve-pkg-maps": {
1166 | "version": "1.0.0",
1167 | "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
1168 | "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
1169 | "dev": true,
1170 | "license": "MIT",
1171 | "funding": {
1172 | "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
1173 | }
1174 | },
1175 | "node_modules/rollup": {
1176 | "version": "4.18.0",
1177 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz",
1178 | "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==",
1179 | "dev": true,
1180 | "license": "MIT",
1181 | "dependencies": {
1182 | "@types/estree": "1.0.5"
1183 | },
1184 | "bin": {
1185 | "rollup": "dist/bin/rollup"
1186 | },
1187 | "engines": {
1188 | "node": ">=18.0.0",
1189 | "npm": ">=8.0.0"
1190 | },
1191 | "optionalDependencies": {
1192 | "@rollup/rollup-android-arm-eabi": "4.18.0",
1193 | "@rollup/rollup-android-arm64": "4.18.0",
1194 | "@rollup/rollup-darwin-arm64": "4.18.0",
1195 | "@rollup/rollup-darwin-x64": "4.18.0",
1196 | "@rollup/rollup-linux-arm-gnueabihf": "4.18.0",
1197 | "@rollup/rollup-linux-arm-musleabihf": "4.18.0",
1198 | "@rollup/rollup-linux-arm64-gnu": "4.18.0",
1199 | "@rollup/rollup-linux-arm64-musl": "4.18.0",
1200 | "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0",
1201 | "@rollup/rollup-linux-riscv64-gnu": "4.18.0",
1202 | "@rollup/rollup-linux-s390x-gnu": "4.18.0",
1203 | "@rollup/rollup-linux-x64-gnu": "4.18.0",
1204 | "@rollup/rollup-linux-x64-musl": "4.18.0",
1205 | "@rollup/rollup-win32-arm64-msvc": "4.18.0",
1206 | "@rollup/rollup-win32-ia32-msvc": "4.18.0",
1207 | "@rollup/rollup-win32-x64-msvc": "4.18.0",
1208 | "fsevents": "~2.3.2"
1209 | }
1210 | },
1211 | "node_modules/rollup-plugin-typescript2": {
1212 | "version": "0.36.0",
1213 | "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.36.0.tgz",
1214 | "integrity": "sha512-NB2CSQDxSe9+Oe2ahZbf+B4bh7pHwjV5L+RSYpCu7Q5ROuN94F9b6ioWwKfz3ueL3KTtmX4o2MUH2cgHDIEUsw==",
1215 | "dev": true,
1216 | "license": "MIT",
1217 | "dependencies": {
1218 | "@rollup/pluginutils": "^4.1.2",
1219 | "find-cache-dir": "^3.3.2",
1220 | "fs-extra": "^10.0.0",
1221 | "semver": "^7.5.4",
1222 | "tslib": "^2.6.2"
1223 | },
1224 | "peerDependencies": {
1225 | "rollup": ">=1.26.3",
1226 | "typescript": ">=2.4.0"
1227 | }
1228 | },
1229 | "node_modules/semver": {
1230 | "version": "7.6.2",
1231 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
1232 | "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
1233 | "dev": true,
1234 | "license": "ISC",
1235 | "bin": {
1236 | "semver": "bin/semver.js"
1237 | },
1238 | "engines": {
1239 | "node": ">=10"
1240 | }
1241 | },
1242 | "node_modules/shiki": {
1243 | "version": "0.14.7",
1244 | "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz",
1245 | "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==",
1246 | "dev": true,
1247 | "license": "MIT",
1248 | "dependencies": {
1249 | "ansi-sequence-parser": "^1.1.0",
1250 | "jsonc-parser": "^3.2.0",
1251 | "vscode-oniguruma": "^1.7.0",
1252 | "vscode-textmate": "^8.0.0"
1253 | }
1254 | },
1255 | "node_modules/tinybench": {
1256 | "version": "2.8.0",
1257 | "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz",
1258 | "integrity": "sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==",
1259 | "dev": true,
1260 | "license": "MIT"
1261 | },
1262 | "node_modules/tslib": {
1263 | "version": "2.6.3",
1264 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
1265 | "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
1266 | "dev": true,
1267 | "license": "0BSD"
1268 | },
1269 | "node_modules/tsx": {
1270 | "version": "4.15.5",
1271 | "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.15.5.tgz",
1272 | "integrity": "sha512-iKi8jQ2VBmZ2kU/FkGkL2OSHBHsazsUzsdC/W/RwhKIEsIoZ1alCclZHP5jGfNHEaEWUJFM1GquzCf+4db3b0w==",
1273 | "dev": true,
1274 | "license": "MIT",
1275 | "dependencies": {
1276 | "esbuild": "~0.21.4",
1277 | "get-tsconfig": "^4.7.5"
1278 | },
1279 | "bin": {
1280 | "tsx": "dist/cli.mjs"
1281 | },
1282 | "engines": {
1283 | "node": ">=18.0.0"
1284 | },
1285 | "optionalDependencies": {
1286 | "fsevents": "~2.3.3"
1287 | }
1288 | },
1289 | "node_modules/typedoc": {
1290 | "version": "0.25.13",
1291 | "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.13.tgz",
1292 | "integrity": "sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ==",
1293 | "dev": true,
1294 | "license": "Apache-2.0",
1295 | "dependencies": {
1296 | "lunr": "^2.3.9",
1297 | "marked": "^4.3.0",
1298 | "minimatch": "^9.0.3",
1299 | "shiki": "^0.14.7"
1300 | },
1301 | "bin": {
1302 | "typedoc": "bin/typedoc"
1303 | },
1304 | "engines": {
1305 | "node": ">= 16"
1306 | },
1307 | "peerDependencies": {
1308 | "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x"
1309 | }
1310 | },
1311 | "node_modules/typedoc-plugin-markdown": {
1312 | "version": "4.0.3",
1313 | "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.0.3.tgz",
1314 | "integrity": "sha512-0tZbeVGGCd4+lpoIX+yHWgUfyaLZCQCgJOpuVdTtOtD3+jKaedJ4sl/tkNaYBPeWVKiyDkSHfGuHkq53jlzIFg==",
1315 | "dev": true,
1316 | "license": "MIT",
1317 | "peerDependencies": {
1318 | "typedoc": "0.25.x"
1319 | }
1320 | },
1321 | "node_modules/typescript": {
1322 | "version": "5.4.5",
1323 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
1324 | "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
1325 | "dev": true,
1326 | "license": "Apache-2.0",
1327 | "bin": {
1328 | "tsc": "bin/tsc",
1329 | "tsserver": "bin/tsserver"
1330 | },
1331 | "engines": {
1332 | "node": ">=14.17"
1333 | }
1334 | },
1335 | "node_modules/undici-types": {
1336 | "version": "5.26.5",
1337 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
1338 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
1339 | "dev": true,
1340 | "license": "MIT"
1341 | },
1342 | "node_modules/universalify": {
1343 | "version": "2.0.1",
1344 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
1345 | "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
1346 | "dev": true,
1347 | "license": "MIT",
1348 | "engines": {
1349 | "node": ">= 10.0.0"
1350 | }
1351 | },
1352 | "node_modules/vscode-oniguruma": {
1353 | "version": "1.7.0",
1354 | "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
1355 | "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==",
1356 | "dev": true,
1357 | "license": "MIT"
1358 | },
1359 | "node_modules/vscode-textmate": {
1360 | "version": "8.0.0",
1361 | "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz",
1362 | "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==",
1363 | "dev": true,
1364 | "license": "MIT"
1365 | }
1366 | }
1367 | }
1368 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "middleware-io",
3 | "version": "2.8.1",
4 | "description": "Modern middleware with promises and status",
5 | "license": "MIT",
6 | "author": {
7 | "name": "Vladlen (Negezor)",
8 | "email": "negezor@gmail.com"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/negezor/middleware-io.git"
13 | },
14 | "homepage": "https://github.com/negezor/middleware-io#readme",
15 | "bugs": "https://github.com/negezor/middleware-io/issues",
16 | "keywords": [
17 | "typescript",
18 | "middleware",
19 | "compose",
20 | "ware",
21 | "promise",
22 | "async",
23 | "await",
24 | "modern",
25 | "es2015",
26 | "es6",
27 | "es7",
28 | "cjs",
29 | "esm",
30 | "js"
31 | ],
32 | "files": [
33 | "lib"
34 | ],
35 | "main": "./lib/index.js",
36 | "types": "./lib/index.d.ts",
37 | "exports": {
38 | ".": {
39 | "types": "./lib/index.d.ts",
40 | "import": "./lib/index.mjs",
41 | "require": "./lib/index.js"
42 | }
43 | },
44 | "sideEffects": false,
45 | "engines": {
46 | "node": ">=12.0.0"
47 | },
48 | "devDependencies": {
49 | "@biomejs/biome": "^1.8.1",
50 | "@types/node": "^20.14.2",
51 | "rollup": "^4.18.0",
52 | "rollup-plugin-typescript2": "^0.36.0",
53 | "tinybench": "^2.8.0",
54 | "tsx": "^4.15.5",
55 | "typedoc": "^0.25.13",
56 | "typedoc-plugin-markdown": "^4.0.3",
57 | "typescript": "^5.4.5"
58 | },
59 | "scripts": {
60 | "prepare": "npm run rollup:build && npm run test",
61 | "build": "npm run rollup:build",
62 | "watch": "npm run rollup:watch",
63 | "clean": "rm -rf lib",
64 | "rollup:build": "NODE_ENV=production rollup --bundleConfigAsCjs -c rollup.config.js",
65 | "rollup:watch": "npm run rollup:build -- --watch",
66 | "test": "npm run test:node && npm run lint",
67 | "test:bench": "node --import tsx test/benchmark.bench.ts",
68 | "test:node": "node --import tsx --test test/*.test.ts",
69 | "lint": "npm run lint:biome",
70 | "lint:biome": "biome lint --apply ./src",
71 | "docs:generate": "typedoc --plugin typedoc-plugin-markdown --out docs/api-reference --excludeExternals --readme none src"
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import typescript from 'rollup-plugin-typescript2';
2 |
3 | import { tmpdir } from 'os';
4 | import { builtinModules } from 'module';
5 | import { join as pathJoin } from 'path';
6 |
7 | import pkg from './package.json';
8 |
9 | const cacheRoot = pathJoin(tmpdir(), '.rpt2_cache');
10 |
11 | const CORE_MODULE_RE = /(^_|\/)/;
12 | const coreModules = builtinModules.filter(name => (
13 | !CORE_MODULE_RE.test(name)
14 | ));
15 |
16 | const src = pathJoin(__dirname, 'src');
17 | const lib = pathJoin(__dirname, 'lib');
18 |
19 | export default {
20 | input: pathJoin(src, 'index.ts'),
21 | plugins: [
22 | typescript({
23 | cacheRoot,
24 |
25 | declarationDir: lib,
26 |
27 | tsconfigOverride: {
28 | outDir: lib,
29 | rootDir: src,
30 | include: [src]
31 | }
32 | })
33 | ],
34 | external: [
35 | ...Object.keys(pkg.dependencies || {}),
36 | ...Object.keys(pkg.peerDependencies || {}),
37 | ...coreModules
38 | ],
39 | output: [
40 | {
41 | file: pathJoin(lib, 'index.js'),
42 | format: 'cjs',
43 | exports: 'named'
44 | },
45 | {
46 | file: pathJoin(lib, 'index.mjs'),
47 | format: 'esm'
48 | }
49 | ]
50 | };
51 |
--------------------------------------------------------------------------------
/src/compose.ts:
--------------------------------------------------------------------------------
1 | import type { Middleware, MiddlewareReturn, NextMiddleware, NextMiddlewareReturn } from './types';
2 |
3 | import { assertMiddlewares } from './helpers';
4 |
5 | /**
6 | * Compose an array of middleware handlers into a single handler
7 | *
8 | * @param middlewares - The array of middleware
9 | *
10 | * @returns Composed middleware
11 | */
12 | export function compose(middlewares: Middleware[]): Middleware {
13 | assertMiddlewares(middlewares);
14 |
15 | return (context: T, next?: NextMiddleware): Promise => {
16 | let lastIndex = -1;
17 |
18 | const nextDispatch = (index: number): Promise => {
19 | if (index <= lastIndex) {
20 | return Promise.reject(new Error('next() called multiple times'));
21 | }
22 |
23 | lastIndex = index;
24 |
25 | const middleware = middlewares.length !== index ? middlewares[index] : next;
26 |
27 | if (!middleware) {
28 | return Promise.resolve();
29 | }
30 |
31 | try {
32 | return Promise.resolve(
33 | middleware(context, (): Promise => nextDispatch(index + 1)),
34 | );
35 | } catch (error) {
36 | return Promise.reject(error);
37 | }
38 | };
39 |
40 | return nextDispatch(0);
41 | };
42 | }
43 |
--------------------------------------------------------------------------------
/src/composer.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | BranchMiddlewareCondition,
3 | CaughtMiddlewareHandler,
4 | LazyMiddlewareFactory,
5 | Middleware,
6 | UnknownObject,
7 | } from './types';
8 |
9 | import { compose } from './compose';
10 | import {
11 | getAfterMiddleware,
12 | getBeforeMiddleware,
13 | getBranchMiddleware,
14 | getCaughtMiddleware,
15 | getConcurrencyMiddleware,
16 | getEnforceMiddleware,
17 | getFilterMiddleware,
18 | getForkMiddleware,
19 | getLazyMiddleware,
20 | getOptionalMiddleware,
21 | getTapMiddleware,
22 | } from './snippets';
23 |
24 | import { assertMiddleware } from './helpers';
25 |
26 | /**
27 | * A simple middleware compose builder
28 | */
29 | export class Composer {
30 | protected middlewares: Middleware[] = [];
31 |
32 | /**
33 | * Invokes a new instance of the Composer class
34 | */
35 | public static builder(): Composer {
36 | return new Composer();
37 | }
38 |
39 | /**
40 | * The number of middleware installed in Composer
41 | */
42 | public get length(): number {
43 | return this.middlewares.length;
44 | }
45 |
46 | /**
47 | * Clones a composer object
48 | */
49 | public clone(): Composer {
50 | const composer = new Composer();
51 |
52 | composer.middlewares = [...this.middlewares];
53 |
54 | return composer;
55 | }
56 |
57 | /**
58 | * Adds middleware to the chain
59 | */
60 | public use(middleware: Middleware): Composer {
61 | assertMiddleware(middleware);
62 |
63 | this.middlewares.push(middleware);
64 |
65 | return this;
66 | }
67 |
68 | /**
69 | * Lazily asynchronously gets middleware
70 | */
71 | public lazy(factory: LazyMiddlewareFactory): Composer {
72 | return this.use(getLazyMiddleware(factory));
73 | }
74 |
75 | /**
76 | * Runs the middleware and force call `next()`
77 | */
78 | public tap(middleware: Middleware): Composer {
79 | return this.use(getTapMiddleware(middleware));
80 | }
81 |
82 | /**
83 | * Runs the middleware at the next event loop and force call `next()`
84 | */
85 | public fork(middleware: Middleware): Composer {
86 | return this.use(getForkMiddleware(middleware));
87 | }
88 |
89 | /**
90 | * By condition splits the middleware
91 | */
92 | public branch(
93 | condition: BranchMiddlewareCondition,
94 |
95 | trueMiddleware: Middleware,
96 | falseMiddleware: Middleware,
97 | ): Composer {
98 | return this.use(
99 | getBranchMiddleware(
100 | condition,
101 |
102 | trueMiddleware,
103 | falseMiddleware,
104 | ),
105 | );
106 | }
107 |
108 | /**
109 | * Conditionally runs optional middleware or skips middleware
110 | */
111 | public optional(
112 | condition: BranchMiddlewareCondition,
113 | optionalMiddleware: Middleware,
114 | ): Composer {
115 | return this.use(getOptionalMiddleware(condition, optionalMiddleware));
116 | }
117 |
118 | /**
119 | * Conditionally runs middleware or stops the chain
120 | */
121 | public filter(
122 | condition: BranchMiddlewareCondition,
123 | filterMiddleware: Middleware,
124 | ): Composer {
125 | return this.use(getFilterMiddleware(condition, filterMiddleware));
126 | }
127 |
128 | /**
129 | * Runs the second middleware before the main
130 | */
131 | public before(
132 | beforeMiddleware: Middleware,
133 | middleware: Middleware,
134 | ): Composer {
135 | return this.use(getBeforeMiddleware(middleware, beforeMiddleware));
136 | }
137 |
138 | /**
139 | * Runs the second middleware after the main
140 | */
141 | public after(
142 | middleware: Middleware,
143 | afterMiddleware: Middleware,
144 | ): Composer {
145 | return this.use(getAfterMiddleware(middleware, afterMiddleware));
146 | }
147 |
148 | /**
149 | * Runs middleware before and after the main
150 | */
151 | public enforce(
152 | beforeMiddleware: Middleware,
153 | middleware: Middleware,
154 | afterMiddleware: Middleware,
155 | ): Composer {
156 | return this.use(getEnforceMiddleware(middleware, beforeMiddleware, afterMiddleware));
157 | }
158 |
159 | /**
160 | * Catches errors in the middleware chain
161 | */
162 | public caught(errorHandler: CaughtMiddlewareHandler): Composer {
163 | return this.use(getCaughtMiddleware(errorHandler));
164 | }
165 |
166 | /**
167 | * Concurrently launches middleware,
168 | * the chain will continue if `next()` is called in all middlewares
169 | */
170 | public concurrency(middlewares: Middleware[]): Composer {
171 | return this.use(getConcurrencyMiddleware(middlewares));
172 | }
173 |
174 | /**
175 | * Compose middleware handlers into a single handler
176 | */
177 | public compose(): Middleware {
178 | return compose([...this.middlewares]);
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/src/helpers.ts:
--------------------------------------------------------------------------------
1 | import type { Middleware, NextMiddleware } from './types';
2 |
3 | export function assertMiddleware(middleware: unknown): asserts middleware is Middleware {
4 | if (typeof middleware !== 'function') {
5 | throw new TypeError('Middleware must be composed of function!');
6 | }
7 | }
8 |
9 | export function assertMiddlewares(middlewares: unknown[]): asserts middlewares is Middleware[] {
10 | middlewares.forEach(assertMiddleware);
11 | }
12 |
13 | export const wrapMiddlewareNextCall = async (context: T, middleware: Middleware): Promise => {
14 | let called = false;
15 |
16 | await middleware(context, async (): Promise => {
17 | if (called) {
18 | throw new Error('next() called multiple times');
19 | }
20 |
21 | called = true;
22 | });
23 |
24 | return called;
25 | };
26 |
27 | /**
28 | * Noop for call `next()` in middleware
29 | */
30 | export const noopNext: NextMiddleware = (): Promise => Promise.resolve();
31 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { compose } from './compose';
2 |
3 | export * from './types';
4 | export * from './snippets';
5 |
6 | export { noopNext } from './helpers';
7 |
8 | export { Composer } from './composer';
9 |
10 | export { compose };
11 |
12 | export default compose;
13 |
--------------------------------------------------------------------------------
/src/snippets.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | BranchMiddlewareCondition,
3 | CaughtMiddlewareHandler,
4 | LazyMiddlewareFactory,
5 | Middleware,
6 | MiddlewareReturn,
7 | NextMiddleware,
8 | NextMiddlewareReturn,
9 | } from './types';
10 |
11 | import { noopNext, wrapMiddlewareNextCall } from './helpers';
12 |
13 | /**
14 | * Call `next()` in middleware
15 | */
16 | export const skipMiddleware = (context: T, next: NextMiddleware): Promise => next();
17 |
18 | /**
19 | * Does not call `next()` in middleware
20 | */
21 | export const stopMiddleware = (context: T, next: NextMiddleware): Promise => Promise.resolve();
22 |
23 | /**
24 | * Lazily asynchronously gets middleware
25 | *
26 | * Example:
27 | *
28 | * ```ts
29 | * getLazyMiddleware(async (context) => {
30 | * const route = await getSomeRoute(context.path) // Promise;
31 | *
32 | * return route;
33 | * });
34 | * ```
35 | */
36 | export const getLazyMiddleware = (factory: LazyMiddlewareFactory): Middleware => {
37 | let middleware: Middleware | undefined;
38 |
39 | return async (context: T, next: NextMiddleware): Promise => {
40 | if (middleware === undefined) {
41 | middleware = await factory(context);
42 | }
43 |
44 | return middleware(context, next);
45 | };
46 | };
47 |
48 | /**
49 | * Runs the middleware and force call `next()`
50 | *
51 | * Example:
52 | *
53 | * ```ts
54 | * getTapMiddleware((context) => {
55 | * console.log('Context', context);
56 | * });
57 | * ```
58 | */
59 | export const getTapMiddleware =
60 | (middleware: Middleware): Middleware =>
61 | async (context: T, next: NextMiddleware): Promise => {
62 | await middleware(context, noopNext);
63 |
64 | return next();
65 | };
66 |
67 | /**
68 | * Runs the middleware at the next event loop and force call `next()`
69 | *
70 | * Example:
71 | *
72 | * ```ts
73 | * getForkMiddleware((context) => {
74 | * statisticsMiddlewares(context).catch(console.error);
75 | * });
76 | * ```
77 | */
78 | export const getForkMiddleware =
79 | (middleware: Middleware): Middleware =>
80 | (context: T, next: NextMiddleware): Promise => {
81 | setImmediate(middleware, context, noopNext);
82 |
83 | return next();
84 | };
85 |
86 | /**
87 | * By condition splits the middleware
88 | *
89 | * Example:
90 | *
91 | * ```ts
92 | * getBranchMiddleware(
93 | * async context => context.is('Content-Type', 'json'),
94 | * myBodyParser.json(),
95 | * myBodyParser.urlencoded()
96 | * );
97 | * ```
98 | *
99 | * Static condition
100 | *
101 | * ```ts
102 | * getBranchMiddleware(
103 | * process.env.NODE_ENV === 'production',
104 | * logger.loggedContextToFile(),
105 | * logger.loggedContextToConsole()
106 | * );
107 | * ```
108 | */
109 | export const getBranchMiddleware = (
110 | condition: BranchMiddlewareCondition,
111 |
112 | trueMiddleware: Middleware,
113 | falseMiddleware: Middleware,
114 | ): Middleware => {
115 | if (typeof condition !== 'function') {
116 | return condition ? trueMiddleware : falseMiddleware;
117 | }
118 |
119 | return async (context: T, next: NextMiddleware): Promise =>
120 | (await condition(context)) ? trueMiddleware(context, next) : falseMiddleware(context, next);
121 | };
122 |
123 | /**
124 | * Conditionally runs optional middleware or skips middleware
125 | *
126 | * Example:
127 | *
128 | * ```ts
129 | * getOptionalMiddleware(
130 | * context => context.user.isAdmin,
131 | * addFieldsForAdmin
132 | * );
133 | * ```
134 | */
135 | export const getOptionalMiddleware = (
136 | condition: BranchMiddlewareCondition,
137 | optionalMiddleware: Middleware,
138 | ): Middleware => getBranchMiddleware(condition, optionalMiddleware, skipMiddleware);
139 |
140 | /**
141 | * Conditionally runs middleware or stops the chain
142 | *
143 | * Example:
144 | *
145 | * ```ts
146 | * getFilterMiddleware(
147 | * context => context.authorized,
148 | * middlewareForAuthorized
149 | * );
150 | * ```
151 | */
152 | export const getFilterMiddleware = (
153 | condition: BranchMiddlewareCondition,
154 | filterMiddleware: Middleware,
155 | ): Middleware => getBranchMiddleware(condition, filterMiddleware, stopMiddleware);
156 |
157 | /**
158 | * Runs the second middleware before the main
159 | *
160 | * Example:
161 | *
162 | * ```ts
163 | * getBeforeMiddleware(
164 | * myMockMiddleware,
165 | * ouputUserData
166 | * );
167 | * ```
168 | */
169 | export const getBeforeMiddleware =
170 | (beforeMiddleware: Middleware, middleware: Middleware): Middleware =>
171 | async (context: T, next: NextMiddleware): Promise => {
172 | const called = await wrapMiddlewareNextCall(context, beforeMiddleware);
173 |
174 | if (called) {
175 | return middleware(context, next);
176 | }
177 | };
178 |
179 | /**
180 | * Runs the second middleware after the main
181 | *
182 | * Example:
183 | *
184 | * ```ts
185 | * getAfterMiddleware(
186 | * sendSecureData,
187 | * clearSecurityData
188 | * );
189 | * ```
190 | */
191 | export const getAfterMiddleware =
192 | (middleware: Middleware, afterMiddleware: Middleware): Middleware =>
193 | async (context: T, next: NextMiddleware): Promise => {
194 | const called = await wrapMiddlewareNextCall(context, middleware);
195 |
196 | if (called) {
197 | return afterMiddleware(context, next);
198 | }
199 | };
200 |
201 | /**
202 | * Runs middleware before and after the main
203 | *
204 | * Example:
205 | *
206 | * ```ts
207 | * getEnforceMiddleware(
208 | * prepareData,
209 | * sendData,
210 | * clearData
211 | * );
212 | */
213 | export const getEnforceMiddleware =
214 | (beforeMiddleware: Middleware, middleware: Middleware, afterMiddleware: Middleware): Middleware =>
215 | async (context: T, next: NextMiddleware): Promise => {
216 | const beforeCalled = await wrapMiddlewareNextCall(context, beforeMiddleware);
217 |
218 | if (!beforeCalled) {
219 | return;
220 | }
221 |
222 | const middlewareCalled = await wrapMiddlewareNextCall(context, middleware);
223 |
224 | if (!middlewareCalled) {
225 | return;
226 | }
227 |
228 | return afterMiddleware(context, next);
229 | };
230 |
231 | /**
232 | * Catches errors in the middleware chain
233 | *
234 | * Example:
235 | * ```js
236 | * getCaughtMiddleware((context, error) => {
237 | * if (error instanceof NetworkError) {
238 | * return context.send('Sorry, network issues 😔');
239 | * }
240 | *
241 | * throw error;
242 | * })
243 | * ```
244 | *
245 | * Without a snippet, it would look like this:
246 | *
247 | * ```js
248 | * async (context, next) => {
249 | * try {
250 | * await next();
251 | * } catch (error) {
252 | * if (error instanceof NetworkError) {
253 | * return context.send('Sorry, network issues 😔');
254 | * }
255 | *
256 | * throw error;
257 | * }
258 | * };
259 | * ```
260 | */
261 | export const getCaughtMiddleware =
262 | (errorHandler: CaughtMiddlewareHandler): Middleware =>
263 | async (context: T, next: NextMiddleware): Promise => {
264 | try {
265 | await next();
266 | } catch (error) {
267 | return errorHandler(context, error as Error);
268 | }
269 | };
270 |
271 | /**
272 | * Concurrently launches middleware,
273 | * the chain will continue if `next()` is called in all middlewares
274 | *
275 | * **Warning: Error interrupts all others**
276 | *
277 | * Example:
278 | *
279 | * ```ts
280 | * getConcurrencyMiddleware(
281 | * initializeUser,
282 | * initializeSession,
283 | * initializeDatabase
284 | * );
285 | * ```
286 | */
287 | export const getConcurrencyMiddleware =
288 | (middlewares: Middleware[]): Middleware =>
289 | async (context: T, next: NextMiddleware): Promise => {
290 | const concurrencies = await Promise.all(
291 | middlewares.map((middleware): Promise => wrapMiddlewareNextCall(context, middleware)),
292 | );
293 |
294 | if (concurrencies.every(Boolean)) {
295 | return next();
296 | }
297 | };
298 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Returns the type of response middleware
3 | */
4 | export type NextMiddlewareReturn = unknown;
5 |
6 | /**
7 | * Call the next middleware from the chain
8 | */
9 | export type NextMiddleware = () => Promise;
10 |
11 | /**
12 | * Returns the type of response middleware
13 | */
14 | export type MiddlewareReturn = unknown;
15 |
16 | /**
17 | * Instead of object
18 | */
19 | export type UnknownObject = Record;
20 |
21 | /**
22 | * Basic middleware
23 | */
24 | export type Middleware = (context: T, next: NextMiddleware) => MiddlewareReturn;
25 |
26 | /**
27 | * Asynchronous function for branch condition
28 | */
29 | export type BranchMiddlewareConditionFunction = (context: T) => Promise | boolean;
30 |
31 | /**
32 | * Possible types for branch condition
33 | */
34 | export type BranchMiddlewareCondition = BranchMiddlewareConditionFunction | boolean;
35 |
36 | /**
37 | * Asynchronous factory to create middleware
38 | */
39 | export type LazyMiddlewareFactory = (context: T) => Promise> | Middleware;
40 |
41 | /**
42 | * Handler for catching errors in middleware chains
43 | */
44 | export type CaughtMiddlewareHandler = (context: T, error: Error) => MiddlewareReturn;
45 |
--------------------------------------------------------------------------------
/test/benchmark.bench.ts:
--------------------------------------------------------------------------------
1 | import { Bench, type Fn } from 'tinybench';
2 |
3 | import { type Middleware, compose, noopNext } from '..';
4 |
5 | const numberFormat = (number: number) => (
6 | new Intl.NumberFormat('en-US').format(number)
7 | );
8 |
9 | const makeSuite = ({ name }: { name: string }) => {
10 | const suite = new Bench({
11 | iterations: 30,
12 | });
13 |
14 | suite.addEventListener('start', () => {
15 | process.stdout.write(`${name}\n\n`.padStart(name.length + 8));
16 | });
17 |
18 | suite.addEventListener('cycle', ({ task }) => {
19 | // biome-ignore lint/style/noNonNullAssertion: after cycle task.result always exist
20 | const { hz, rme } = task.result!;
21 | const text = `${task.name} » ${numberFormat(Number(hz.toFixed(hz < 100 ? 2 : 0)))} op/s ±${rme.toFixed(2)}%\n`;
22 |
23 | process.stdout.clearLine(0);
24 | process.stdout.cursorTo(0);
25 | process.stdout.write(text.padStart(text.length + 8));
26 | })
27 |
28 |
29 | suite.addEventListener('complete', () => {
30 | process.stdout.write('\n');
31 | });
32 |
33 | return {
34 | add: (testName: string, options: { fn: Fn }) => {
35 | suite.add(testName, options.fn, {
36 | ...options,
37 |
38 | beforeAll() {
39 | const text = `wait » ${testName}`;
40 |
41 | process.stdout.write(text.padStart(testName.length + 17));
42 | },
43 | });
44 | },
45 | run: suite.run.bind(suite),
46 | };
47 | };
48 |
49 | const composeSuite = makeSuite({
50 | name: 'Compose',
51 | });
52 |
53 | for (let exp = 0; exp <= 10; exp += 1) {
54 | const count = 2 ** exp;
55 |
56 | const logic = async () => true;
57 |
58 | const fn: Middleware = async (ctx, next) => {
59 | await logic();
60 | await next();
61 | await logic();
62 | };
63 |
64 | const middlewares = Array(count).fill(fn);
65 |
66 | const middleware = compose(middlewares);
67 |
68 | composeSuite.add(`(fn * ${count})`, {
69 | fn: () => (
70 | middleware({}, noopNext)
71 | ),
72 | });
73 | }
74 |
75 | (async () => {
76 | for (const benchmark of [composeSuite]) {
77 | await benchmark.run();
78 | }
79 | })();
80 |
--------------------------------------------------------------------------------
/test/composer.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, it } from 'node:test';
2 | import { match, ok, deepStrictEqual, strictEqual } from 'node:assert';
3 |
4 | import { Composer, noopNext } from '..';
5 |
6 | /**
7 | * Delay N-ms
8 | *
9 | * @param {Number} delayed
10 | *
11 | * @return {Promise}
12 | */
13 | const delay = (delayed: number): Promise => (
14 | new Promise((resolve): void => {
15 | setTimeout(resolve, delayed);
16 | })
17 | );
18 |
19 | describe('Composer', (): void => {
20 | it('should work', async (): Promise => {
21 | const out: number[] = [];
22 |
23 | const composer = new Composer();
24 |
25 | composer.use(async (ctx, next): Promise => {
26 | out.push(1);
27 |
28 | await delay(1);
29 | await next();
30 | await delay(1);
31 |
32 | out.push(6);
33 | });
34 |
35 | composer.use(async (ctx, next): Promise => {
36 | out.push(2);
37 |
38 | await delay(1);
39 | await next();
40 | await delay(1);
41 |
42 | out.push(5);
43 | });
44 |
45 | composer.use(async (ctx, next): Promise => {
46 | out.push(3);
47 |
48 | await delay(1);
49 | await next();
50 | await delay(1);
51 |
52 | out.push(4);
53 | });
54 |
55 | const middleware = composer.compose();
56 |
57 | await middleware({}, noopNext);
58 |
59 | deepStrictEqual(out, [1, 2, 3, 4, 5, 6]);
60 | });
61 |
62 | it('should keep the context', async (): Promise => {
63 | const context = {};
64 |
65 | const composer = new Composer();
66 |
67 | composer.use(async (ctx, next): Promise => {
68 | await next();
69 |
70 | strictEqual(ctx, context);
71 | });
72 |
73 | composer.use(async (ctx, next): Promise => {
74 | await next();
75 |
76 | strictEqual(ctx, context);
77 | });
78 |
79 | composer.use(async (ctx, next): Promise => {
80 | await next();
81 |
82 | strictEqual(ctx, context);
83 | });
84 |
85 | const middleware = composer.compose();
86 |
87 | await middleware(context, noopNext);
88 | });
89 |
90 | it('should work with 0 middleware', async (): Promise => {
91 | const middleware = (new Composer()).compose();
92 |
93 | await middleware({}, noopNext);
94 | });
95 |
96 | it('should reject on errors in middleware', async (): Promise => {
97 | const composer = new Composer>();
98 |
99 | composer.use(async (ctx, next): Promise => {
100 | ctx.now = Date.now();
101 |
102 | await next();
103 | });
104 |
105 | composer.use(async (): Promise => {
106 | throw new Error();
107 | });
108 |
109 | const middleware = composer.compose();
110 |
111 | try {
112 | await middleware({}, noopNext);
113 | } catch (error) {
114 | ok(error instanceof Error);
115 |
116 | return;
117 | }
118 |
119 | throw new Error();
120 | });
121 |
122 | it('should only accept middleware as functions', (): void => {
123 | try {
124 | // @ts-expect-error cause test
125 | (new Composer()).use(null);
126 |
127 | throw new Error('Middleware must be composed of functions');
128 | } catch (error) {
129 | ok(error instanceof TypeError);
130 | }
131 | });
132 |
133 | it('composer should be cloned', async (): Promise => {
134 | type CloneContext = {
135 | baseValue?: boolean;
136 | value: 'first' | 'second' | 'default';
137 | }
138 |
139 | const baseComposer = new Composer();
140 |
141 | baseComposer.use((context, next) => {
142 | context.baseValue = true;
143 |
144 | return next();
145 | });
146 |
147 | const firstComposer = baseComposer.clone()
148 | .use((context, next) => {
149 | context.value = 'first';
150 |
151 | return next();
152 | });
153 |
154 | const secondComposer = baseComposer.clone()
155 | .use((context, next) => {
156 | context.value = 'second';
157 |
158 | return next();
159 | });
160 |
161 | const baseContext = { value: 'default' } as CloneContext;
162 | const firstContext = { value: 'default' } as CloneContext;
163 | const secondContext = { value: 'default' } as CloneContext;
164 |
165 | await baseComposer.compose()(baseContext, noopNext);
166 | await firstComposer.compose()(firstContext, noopNext);
167 | await secondComposer.compose()(secondContext, noopNext);
168 |
169 | deepStrictEqual(baseContext, {
170 | baseValue: true,
171 | value: 'default',
172 | });
173 |
174 | deepStrictEqual(firstContext, {
175 | baseValue: true,
176 | value: 'first',
177 | });
178 |
179 | deepStrictEqual(secondContext, {
180 | baseValue: true,
181 | value: 'second',
182 | });
183 | });
184 |
185 | it('should correctly display the number of middleware', (): void => {
186 | const composer = new Composer();
187 |
188 | strictEqual(composer.length, 0);
189 |
190 | composer.tap(() => { });
191 |
192 | strictEqual(composer.length, 1);
193 |
194 | composer.tap(() => { });
195 |
196 | strictEqual(composer.length, 2);
197 | });
198 |
199 | it('should create new instance of the Composer class', (): void => {
200 | const composer = Composer.builder<{ test: 'test' }>();
201 |
202 | composer.use((context) => {
203 | if (context.test === 'test') {
204 | // ...
205 | }
206 | });
207 |
208 | strictEqual(composer.length, 1);
209 | ok(composer instanceof Composer);
210 | });
211 |
212 | it('should throw if next() is called multiple times', async (): Promise => {
213 | const composer = new Composer();
214 |
215 | composer.use(async (ctx, next): Promise => {
216 | await next();
217 | });
218 |
219 | composer.use(async (ctx, next): Promise => {
220 | await next();
221 | await next();
222 | });
223 |
224 | composer.use(async (ctx, next): Promise => {
225 | await next();
226 | });
227 |
228 | const middleware = composer.compose();
229 |
230 | try {
231 | await middleware({}, noopNext);
232 | // @ts-expect-error cause test
233 | } catch ({ message }) {
234 | match(message, /multiple times/);
235 |
236 | return;
237 | }
238 |
239 | throw new Error('next() called multiple times');
240 | });
241 | });
242 |
--------------------------------------------------------------------------------
/test/middleware.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, it } from 'node:test';
2 | import { deepStrictEqual, match, ok, strictEqual } from 'node:assert';
3 |
4 | import { compose, noopNext } from '..';
5 |
6 | /**
7 | * Delay N-ms
8 | *
9 | * @param {Number} delayed
10 | *
11 | * @return {Promise}
12 | */
13 | const delay = (delayed: number): Promise => (
14 | new Promise((resolve): void => {
15 | setTimeout(resolve, delayed);
16 | })
17 | );
18 |
19 | describe('compose', (): void => {
20 | it('should work', async (): Promise => {
21 | const out: number[] = [];
22 |
23 | const middleware = compose([
24 | async (ctx, next): Promise => {
25 | out.push(1);
26 |
27 | await delay(1);
28 | await next();
29 | await delay(1);
30 |
31 | out.push(6);
32 | },
33 | async (ctx, next): Promise => {
34 | out.push(2);
35 |
36 | await delay(1);
37 | await next();
38 | await delay(1);
39 |
40 | out.push(5);
41 | },
42 | async (ctx, next): Promise => {
43 | out.push(3);
44 |
45 | await delay(1);
46 | await next();
47 | await delay(1);
48 |
49 | out.push(4);
50 | },
51 | ]);
52 |
53 | await middleware(out, noopNext);
54 |
55 | deepStrictEqual(out, [1, 2, 3, 4, 5, 6]);
56 | });
57 |
58 | it('should keep the context', async (): Promise => {
59 | const context = {};
60 |
61 | const middleware = compose([
62 | async (ctx, next): Promise => {
63 | await next();
64 |
65 | strictEqual(ctx, context);
66 | },
67 | async (ctx, next): Promise => {
68 | await next();
69 |
70 | strictEqual(ctx, context);
71 | },
72 | async (ctx, next): Promise => {
73 | await next();
74 |
75 | strictEqual(ctx, context);
76 | },
77 | ]);
78 |
79 | await middleware(context, noopNext);
80 | });
81 |
82 | it('should work with 0 middleware', async (): Promise => {
83 | const middleware = compose([]);
84 |
85 | await middleware({}, noopNext);
86 | });
87 |
88 | it('should reject on errors in middleware', async (): Promise => {
89 | const middleware = compose>([
90 | async (ctx, next): Promise => {
91 | ctx.now = Date.now();
92 |
93 | await next();
94 | },
95 | async (): Promise => {
96 | throw new Error();
97 | },
98 | ]);
99 |
100 | try {
101 | await middleware({}, noopNext);
102 | } catch (error) {
103 | ok(error instanceof Error);
104 |
105 | return;
106 | }
107 |
108 | throw new Error();
109 | });
110 |
111 | it('should only accept middleware as functions', (): void => {
112 | try {
113 | // @ts-expect-error cause test
114 | compose([null]);
115 |
116 | throw new Error('Middleware must be composed of functions');
117 | } catch (error) {
118 | ok(error instanceof TypeError);
119 | }
120 | });
121 |
122 | it('should throw if next() is called multiple times', async (): Promise => {
123 | const middleware = compose([
124 | async (ctx, next): Promise => {
125 | await next();
126 | },
127 | async (ctx, next): Promise => {
128 | await next();
129 | await next();
130 | },
131 | async (ctx, next): Promise => {
132 | await next();
133 | },
134 | ]);
135 |
136 | try {
137 | await middleware({}, noopNext);
138 | // @ts-expect-error cause error
139 | } catch ({ message }) {
140 | match(message, /multiple times/);
141 |
142 | return;
143 | }
144 |
145 | throw new Error('next() called multiple times');
146 | });
147 | });
148 |
--------------------------------------------------------------------------------
/test/snippets.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, mock } from 'node:test';
2 | import { deepStrictEqual, ok, strictEqual } from 'node:assert';
3 |
4 | import {
5 | Middleware,
6 | NextMiddleware,
7 |
8 | noopNext,
9 | getLazyMiddleware,
10 | getTapMiddleware,
11 | getForkMiddleware,
12 | getBranchMiddleware,
13 | getOptionalMiddleware,
14 | getBeforeMiddleware,
15 | getAfterMiddleware,
16 | getEnforceMiddleware,
17 | getConcurrencyMiddleware,
18 | getFilterMiddleware,
19 | getCaughtMiddleware,
20 | } from '..';
21 |
22 | const makeContext = (): { shouldTrue: boolean; shouldFalse: boolean } => ({
23 | shouldTrue: true,
24 | shouldFalse: false,
25 | });
26 |
27 | type ContextType = ReturnType;
28 |
29 | describe('Snippets', (): void => {
30 | describe('getLazyMiddleware', (): void => {
31 | it('should work with function', async (): Promise => {
32 | const lazyContext = makeContext();
33 |
34 | const nextMock = mock.fn(noopNext);
35 | const middlewareMock = mock.fn(
36 | (factoryContext: ContextType): Middleware => {
37 | strictEqual(factoryContext, lazyContext);
38 |
39 | return async (context: ContextType, next: NextMiddleware): Promise => {
40 | strictEqual(context, lazyContext);
41 |
42 | await next();
43 | };
44 | },
45 | );
46 |
47 | const lazyMiddleware = getLazyMiddleware(middlewareMock);
48 |
49 | await lazyMiddleware(lazyContext, nextMock);
50 |
51 | strictEqual(middlewareMock.mock.callCount(), 1);
52 | strictEqual(nextMock.mock.callCount(), 1);
53 | });
54 |
55 | it('should factory be called once', async (): Promise => {
56 | const lazyContext = makeContext();
57 |
58 | const nextMock = mock.fn(noopNext);
59 | const middlewareMock = mock.fn(
60 | (factoryContext: ContextType): Middleware => {
61 | ok(factoryContext === lazyContext);
62 |
63 | return async (context: ContextType, next: NextMiddleware): Promise => {
64 | ok(context === lazyContext);
65 |
66 | await next();
67 | };
68 | },
69 | );
70 |
71 | const lazyMiddleware = getLazyMiddleware(middlewareMock);
72 |
73 | const CALLED_TIMES = 10;
74 | for (let i = 0; i < CALLED_TIMES; i += 1) {
75 | await lazyMiddleware(lazyContext, nextMock);
76 | }
77 |
78 | strictEqual(middlewareMock.mock.callCount(), 1);
79 | strictEqual(nextMock.mock.callCount(), CALLED_TIMES);
80 | });
81 | });
82 |
83 | describe('getTapMiddleware', (): void => {
84 | it('should runs with force next()', async (): Promise => {
85 | const tapContext = makeContext();
86 |
87 | const nextMock = mock.fn(noopNext);
88 | const middlewareMock = mock.fn(
89 | async (context: ContextType): Promise => {
90 | ok(context === tapContext);
91 | },
92 | );
93 |
94 | const tapMiddleware = getTapMiddleware(middlewareMock);
95 |
96 | await tapMiddleware(tapContext, nextMock);
97 |
98 | strictEqual(middlewareMock.mock.callCount(), 1);
99 | strictEqual(nextMock.mock.callCount(), 1);
100 | });
101 | });
102 |
103 | describe('getForkMiddleware', (): void => {
104 | it('should runs with force next()', async (): Promise => {
105 | const forkContext = makeContext();
106 |
107 | const nextMock = mock.fn(noopNext);
108 | const middlewareMock = mock.fn(
109 | async (context: ContextType, next: NextMiddleware): Promise => {
110 | ok(context === forkContext);
111 |
112 | await next();
113 | },
114 | );
115 |
116 | const forkMiddleware = getForkMiddleware(middlewareMock);
117 |
118 | await forkMiddleware(forkContext, nextMock);
119 |
120 | strictEqual(middlewareMock.mock.callCount(), 0);
121 | strictEqual(nextMock.mock.callCount(), 1);
122 |
123 | await new Promise((resolve: Function): void => {
124 | setImmediate((): void => {
125 | strictEqual(middlewareMock.mock.callCount(), 1);
126 |
127 | resolve();
128 | });
129 | });
130 | });
131 | });
132 |
133 | describe('getBranchMiddleware', (): void => {
134 | it('should runs with static condition', async (): Promise => {
135 | const branchContext = makeContext();
136 |
137 | const nextMock = mock.fn(noopNext);
138 |
139 | const trueMiddlewareMock = mock.fn(
140 | async (context: ContextType, next: NextMiddleware): Promise => {
141 | ok(context === branchContext);
142 |
143 | await next();
144 | },
145 | );
146 |
147 | const falseMiddlewareMock = mock.fn(
148 | async (context: ContextType, next: NextMiddleware): Promise => {
149 | ok(context === branchContext);
150 |
151 | await next();
152 | },
153 | );
154 |
155 | const trueMiddleware = getBranchMiddleware(
156 | true,
157 | trueMiddlewareMock,
158 | falseMiddlewareMock,
159 | );
160 |
161 | const falseMiddleware = getBranchMiddleware(
162 | false,
163 | trueMiddlewareMock,
164 | falseMiddlewareMock,
165 | );
166 |
167 | await trueMiddleware(branchContext, nextMock);
168 | await falseMiddleware(branchContext, nextMock);
169 |
170 | strictEqual(trueMiddlewareMock.mock.callCount(), 1);
171 | strictEqual(falseMiddlewareMock.mock.callCount(), 1);
172 | strictEqual(nextMock.mock.callCount(), 2);
173 | });
174 |
175 | it('should runs with dynamic condition', async (): Promise => {
176 | const branchContext = makeContext();
177 |
178 | const nextMock = mock.fn(noopNext);
179 |
180 | const trueMiddlewareMock = mock.fn(
181 | async (context: ContextType, next: NextMiddleware): Promise => {
182 | ok(context === branchContext);
183 |
184 | await next();
185 | },
186 | );
187 |
188 | const falseMiddlewareMock = mock.fn(
189 | async (context: ContextType, next: NextMiddleware): Promise => {
190 | ok(context === branchContext);
191 |
192 | await next();
193 | },
194 | );
195 |
196 | const trueMiddleware = getBranchMiddleware(
197 | mock.fn(() => true),
198 | trueMiddlewareMock,
199 | falseMiddlewareMock,
200 | );
201 |
202 | const falseMiddleware = getBranchMiddleware(
203 | mock.fn(() => false),
204 | trueMiddlewareMock,
205 | falseMiddlewareMock,
206 | );
207 |
208 | await trueMiddleware(branchContext, nextMock);
209 | await falseMiddleware(branchContext, nextMock);
210 |
211 | strictEqual(trueMiddlewareMock.mock.callCount(), 1);
212 | strictEqual(falseMiddlewareMock.mock.callCount(), 1);
213 | strictEqual(nextMock.mock.callCount(), 2);
214 | });
215 | });
216 |
217 | describe('getOptionalMiddleware', (): void => {
218 | it('should runs with static condition', async (): Promise => {
219 | const optionalContext = makeContext();
220 |
221 | const nextMock = mock.fn(noopNext);
222 |
223 | const middlewareMock = mock.fn(
224 | async (context: ContextType, next: NextMiddleware): Promise => {
225 | ok(context === optionalContext);
226 |
227 | await next();
228 | },
229 | );
230 |
231 | const trueMiddleware = getOptionalMiddleware(
232 | true,
233 | middlewareMock,
234 | );
235 |
236 | const falseMiddleware = getOptionalMiddleware(
237 | false,
238 | middlewareMock,
239 | );
240 |
241 | await trueMiddleware(optionalContext, nextMock);
242 | await falseMiddleware(optionalContext, nextMock);
243 |
244 | strictEqual(middlewareMock.mock.callCount(), 1);
245 | strictEqual(nextMock.mock.callCount(), 2);
246 | });
247 |
248 | it('should runs with dynamic condition', async (): Promise => {
249 | const optionalContext = makeContext();
250 |
251 | const nextMock = mock.fn(noopNext);
252 |
253 | const middlewareMock = mock.fn(
254 | async (context: ContextType, next: NextMiddleware): Promise => {
255 | ok(context === optionalContext);
256 |
257 | await next();
258 | },
259 | );
260 |
261 | const trueMiddleware = getOptionalMiddleware(
262 | mock.fn(() => true),
263 | middlewareMock,
264 | );
265 |
266 | const falseMiddleware = getOptionalMiddleware(
267 | mock.fn(() => false),
268 | middlewareMock,
269 | );
270 |
271 | await trueMiddleware(optionalContext, nextMock);
272 | await falseMiddleware(optionalContext, nextMock);
273 |
274 | strictEqual(middlewareMock.mock.callCount(), 1);
275 | strictEqual(nextMock.mock.callCount(), 2);
276 | });
277 | });
278 |
279 | describe('getFilterMiddleware', (): void => {
280 | it('should runs with static condition', async (): Promise => {
281 | const filterContext = makeContext();
282 |
283 | const nextMock = mock.fn(noopNext);
284 |
285 | const middlewareMock = mock.fn(
286 | async (context: ContextType, next: NextMiddleware): Promise => {
287 | ok(context === filterContext);
288 |
289 | await next();
290 | },
291 | );
292 |
293 | const trueMiddleware = getFilterMiddleware(
294 | true,
295 | middlewareMock,
296 | );
297 |
298 | const falseMiddleware = getFilterMiddleware(
299 | false,
300 | middlewareMock,
301 | );
302 |
303 | await trueMiddleware(filterContext, nextMock);
304 | await falseMiddleware(filterContext, nextMock);
305 |
306 | strictEqual(middlewareMock.mock.callCount(), 1);
307 | strictEqual(nextMock.mock.callCount(), 1);
308 | });
309 |
310 | it('should runs with dynamic condition', async (): Promise => {
311 | const filterContext = makeContext();
312 |
313 | const nextMock = mock.fn(noopNext);
314 |
315 | const middlewareMock = mock.fn(
316 | async (context: ContextType, next: NextMiddleware): Promise => {
317 | ok(context === filterContext);
318 |
319 | await next();
320 | },
321 | );
322 |
323 | const trueMiddleware = getFilterMiddleware(
324 | mock.fn(() => true),
325 | middlewareMock,
326 | );
327 |
328 | const falseMiddleware = getFilterMiddleware(
329 | mock.fn(() => false),
330 | middlewareMock,
331 | );
332 |
333 | await trueMiddleware(filterContext, nextMock);
334 | await falseMiddleware(filterContext, nextMock);
335 |
336 | strictEqual(middlewareMock.mock.callCount(), 1);
337 | strictEqual(nextMock.mock.callCount(), 1);
338 | });
339 | });
340 |
341 | describe('getBeforeMiddleware', (): void => {
342 | it('should runs before middleware', async (): Promise => {
343 | const beforeContext = makeContext();
344 |
345 | const nextMock = mock.fn(noopNext);
346 |
347 | const beforeMiddlewareMock = mock.fn(
348 | async (context: ContextType, next: NextMiddleware): Promise => {
349 | ok(context === beforeContext);
350 |
351 | strictEqual(middlewareMock.mock.callCount(), 0);
352 |
353 | await next();
354 | },
355 | );
356 |
357 | const middlewareMock = mock.fn(
358 | async (context: ContextType, next: NextMiddleware): Promise => {
359 | ok(context === beforeContext);
360 |
361 | strictEqual(beforeMiddlewareMock.mock.callCount(), 1);
362 |
363 | await next();
364 | },
365 | );
366 |
367 | const beforeMiddleware = getBeforeMiddleware(
368 | beforeMiddlewareMock,
369 | middlewareMock,
370 | );
371 |
372 | await beforeMiddleware(beforeContext, nextMock);
373 |
374 | strictEqual(middlewareMock.mock.callCount(), 1);
375 | strictEqual(nextMock.mock.callCount(), 1);
376 | });
377 | });
378 |
379 | describe('getAfterMiddleware', (): void => {
380 | it('should runs after middleware', async (): Promise => {
381 | const afterContext = makeContext();
382 |
383 | const nextMock = mock.fn(noopNext);
384 |
385 | const middlewareMock = mock.fn(
386 | async (context: ContextType, next: NextMiddleware): Promise => {
387 | ok(context === afterContext);
388 | strictEqual(afterMiddlewareMock.mock.callCount(), 0);
389 |
390 | await next();
391 | },
392 | );
393 |
394 | const afterMiddlewareMock = mock.fn(
395 | async (context: ContextType, next: NextMiddleware): Promise => {
396 | ok(context === afterContext);
397 | strictEqual(middlewareMock.mock.callCount(), 1);
398 |
399 | await next();
400 | },
401 | );
402 |
403 | const afterMiddleware = getAfterMiddleware(
404 | middlewareMock,
405 | afterMiddlewareMock,
406 | );
407 |
408 | await afterMiddleware(afterContext, nextMock);
409 |
410 | strictEqual(middlewareMock.mock.callCount(), 1);
411 | strictEqual(nextMock.mock.callCount(), 1);
412 | });
413 | });
414 |
415 | describe('getEnforceMiddleware', (): void => {
416 | it('should runs enforce middleware', async (): Promise => {
417 | const enforceContext = makeContext();
418 |
419 | const nextMock = mock.fn(noopNext);
420 |
421 | const beforeMiddlewareMock = mock.fn(
422 | async (context: ContextType, next: NextMiddleware): Promise => {
423 | ok(context === enforceContext);
424 |
425 | strictEqual(middlewareMock.mock.callCount(), 0);
426 | strictEqual(afterMiddlewareMock.mock.callCount(), 0);
427 |
428 | await next();
429 | },
430 | );
431 |
432 | const middlewareMock = mock.fn(
433 | async (context: ContextType, next: NextMiddleware): Promise => {
434 | ok(context === enforceContext);
435 |
436 | strictEqual(beforeMiddlewareMock.mock.callCount(), 1);
437 | strictEqual(afterMiddlewareMock.mock.callCount(), 0);
438 |
439 | await next();
440 | },
441 | );
442 |
443 | const afterMiddlewareMock = mock.fn(
444 | async (context: ContextType, next: NextMiddleware): Promise => {
445 | ok(context === enforceContext);
446 |
447 | strictEqual(middlewareMock.mock.callCount(), 1);
448 | strictEqual(beforeMiddlewareMock.mock.callCount(), 1);
449 |
450 | await next();
451 | },
452 | );
453 |
454 | const enforceMiddleware = getEnforceMiddleware(
455 | beforeMiddlewareMock,
456 | middlewareMock,
457 | afterMiddlewareMock,
458 | );
459 |
460 | await enforceMiddleware(enforceContext, nextMock);
461 |
462 | strictEqual(middlewareMock.mock.callCount(), 1);
463 | strictEqual(nextMock.mock.callCount(), 1);
464 | });
465 | });
466 |
467 | describe('getCaughtMiddleware', (): void => {
468 | it('should work with error', async (): Promise => {
469 | const caughtContext = makeContext();
470 |
471 | const caughtError = new Error('Test error');
472 | const nextMock = mock.fn(() => {
473 | throw caughtError;
474 | });
475 |
476 | const handlerMock = mock.fn(
477 | (context: ContextType, error: Error): void => {
478 | ok(context === caughtContext);
479 | strictEqual(error, caughtError);
480 | },
481 | );
482 |
483 | const caughtMiddleware = getCaughtMiddleware(handlerMock);
484 |
485 | await caughtMiddleware(caughtContext, nextMock);
486 |
487 | strictEqual(handlerMock.mock.callCount(), 1);
488 | strictEqual(nextMock.mock.callCount(), 1);
489 | });
490 |
491 | it('should work without error', async (): Promise => {
492 | const caughtContext = makeContext();
493 |
494 | const nextMock = mock.fn(noopNext);
495 | const handlerMock = mock.fn((): void => {});
496 |
497 | const caughtMiddleware = getCaughtMiddleware(handlerMock);
498 |
499 | await caughtMiddleware(caughtContext, nextMock);
500 |
501 | strictEqual(handlerMock.mock.callCount(), 0);
502 | strictEqual(nextMock.mock.callCount(), 1);
503 | });
504 | });
505 |
506 | describe('getConcurrencyMiddleware', (): void => {
507 | it('should runs concurrency middleware', async (): Promise => {
508 | const concurrencyContext = makeContext();
509 |
510 | concurrencyContext.shouldTrue = false;
511 | concurrencyContext.shouldFalse = true;
512 |
513 | deepStrictEqual(concurrencyContext, {
514 | shouldTrue: false,
515 | shouldFalse: true,
516 | });
517 |
518 | const nextMock = mock.fn(noopNext);
519 |
520 | const firstMiddlewareMock = mock.fn(
521 | async (context: ContextType, next: NextMiddleware): Promise => {
522 | ok(context === concurrencyContext);
523 |
524 | concurrencyContext.shouldTrue = true;
525 |
526 | await next();
527 | },
528 | );
529 |
530 | const secondMiddlewareMock = mock.fn(
531 | async (context: ContextType, next: NextMiddleware): Promise => {
532 | ok(context === concurrencyContext);
533 |
534 | concurrencyContext.shouldFalse = false;
535 |
536 | await next();
537 | },
538 | );
539 |
540 | const enforceMiddleware = getConcurrencyMiddleware([
541 | firstMiddlewareMock as Middleware,
542 | secondMiddlewareMock as Middleware,
543 | ]);
544 |
545 | await enforceMiddleware(concurrencyContext, nextMock);
546 |
547 | deepStrictEqual(concurrencyContext, {
548 | shouldTrue: true,
549 | shouldFalse: false,
550 | });
551 |
552 | strictEqual(firstMiddlewareMock.mock.callCount(), 1);
553 | strictEqual(secondMiddlewareMock.mock.callCount(), 1);
554 | strictEqual(nextMock.mock.callCount(), 1);
555 | });
556 | });
557 | });
558 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "module": "ESNext",
5 | "moduleResolution": "node",
6 | "declaration": true,
7 | "sourceMap": false,
8 | "strict": true
9 | }
10 | }
11 |
--------------------------------------------------------------------------------