Skip to content

Commit 403175e

Browse files
Merge pull request #2 from typescript-package/develop
v0.0.2
2 parents c05cd60 + ed87582 commit 403175e

16 files changed

+414
-108
lines changed

README.md

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@
1616

1717
A **lightweight** TypeScript library for middleware.
1818

19-
## Features
20-
2119
## Table of contents
2220

21+
- [Features](#features)
2322
- [Installation](#installation)
2423
- [Api](#api)
24+
- Abstract
25+
- [`ContextMiddlewareBase`](#contextmiddlewarebase)
26+
- [`MiddlewareBase`](#middlewarebase)
27+
- [`MiddlewareCore`](#middlewarecore)
2528
- Class
29+
- [`ContextMiddleware`](#contextmiddleware)
2630
- [`Middleware`](#middleware)
2731
- [Contributing](#contributing)
2832
- [Support](#support)
@@ -33,6 +37,13 @@ A **lightweight** TypeScript library for middleware.
3337
- [License](#license)
3438
- [Related packages](#related-packages)
3539

40+
### Features
41+
42+
- **Core abstraction**: Class for both arguments-based (array) and object-based (context) middleware.
43+
- **Base abstraction**: Extends core abstraction with functionality to build new arguments-based middlewares.
44+
- **Concrete class**: Extension of base for initialization.
45+
- **Context middleware**: Context object-based `ContextMiddleware` base and concrete middleware built on `MiddlewareBase`.
46+
3647
## Installation
3748

3849
### 1. Install the package
@@ -43,6 +54,24 @@ npm install @typescript-package/middleware --save-peer
4354

4455
## Api
4556

57+
### `ContextMiddlewareBase`
58+
59+
```typescript
60+
import { ContextMiddlewareBase } from '@typescript-package/middleware';
61+
```
62+
63+
### `MiddlewareCore`
64+
65+
```typescript
66+
import { MiddlewareCore } from '@typescript-package/middleware';
67+
```
68+
69+
### `MiddlewareBase`
70+
71+
```typescript
72+
import { MiddlewareBase } from '@typescript-package/middleware';
73+
```
74+
4675
### `Middleware`
4776

4877
```typescript
@@ -96,6 +125,38 @@ middleware.onComplete((args) => {
96125
middleware.executeAsync({ key: 'value' });
97126
```
98127

128+
### `ContextMiddleware`
129+
130+
```typescript
131+
import { ContextMiddleware } from '@typescript-package/middleware';
132+
133+
const contextMiddleware = new ContextMiddleware<{ req: string; res?: string }>(
134+
(context, next: () => void) => {
135+
console.log('Middleware 0 executed with args:', context);
136+
next();
137+
},
138+
(context, next: () => void) => {
139+
console.log('Middleware 00 executed with args:', context);
140+
next();
141+
}
142+
);
143+
144+
contextMiddleware.use((context, next) => {
145+
console.log('Middleware 1 executed with args:', context);
146+
context.req = 'newValue';
147+
next();
148+
});
149+
150+
151+
contextMiddleware.use((context, next) => {
152+
console.log('Middleware 2 executed with args:', context);
153+
next();
154+
});
155+
156+
contextMiddleware.execute({ req: 'value' });
157+
158+
```
159+
99160
## Contributing
100161

101162
Your contributions are valued! If you'd like to contribute, please feel free to submit a pull request. Help is always appreciated.

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@typescript-package/middleware",
3-
"version": "0.0.1",
3+
"version": "0.0.2",
44
"author": "wwwdev.io <dev@wwwdev.io>",
55
"description": "A lightweight TypeScript library for middleware.",
66
"license": "MIT",
@@ -27,6 +27,10 @@
2727
"@typescript-package/middleware"
2828
],
2929
"funding": [
30+
{
31+
"type": "stripe",
32+
"url": "https://donate.stripe.com/dR614hfDZcJE3wAcMM"
33+
},
3034
{
3135
"type": "individual",
3236
"url": "https://checkout.revolut.com/pay/048b10a3-0e10-42c8-a917-e3e9cb4c8e29"

src/interface/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type { MiddlewareShape } from './middleware.shape';

src/interface/middleware.shape.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* @description The shape of a middleware system.
3+
* @export
4+
* @interface MiddlewareShape
5+
* @typedef {MiddlewareShape}
6+
* @template [Input=any] The type of the arguments passed to middleware functions.
7+
* @template [Output=any] The type of the output returned by middleware functions.
8+
* @template [Middleware=any] The type of the middleware.
9+
*/
10+
export interface MiddlewareShape<Input = any, Output = any, Middleware = any> {
11+
execute(context: Input): void;
12+
execute(...args: Input[]): void;
13+
use(middleware: Middleware): this;
14+
executeAsync(context: Input): Promise<Output>;
15+
executeAsync(...args: Input[]): Promise<Output>;
16+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Abstract.
2+
import { MiddlewareBase } from './middleware-base.abstract';
3+
// Type.
4+
import { ContextMiddlewareFunction } from '../type';
5+
/**
6+
* @description
7+
* @export
8+
* @abstract
9+
* @class ContextMiddlewareBase
10+
* @template [T=any]
11+
* @template {Function} [U=ContextMiddlewareFunction<T>]
12+
* @extends {MiddlewareBase<T, T, U>}
13+
*/
14+
export abstract class ContextMiddlewareBase<
15+
T = any,
16+
U extends Function = ContextMiddlewareFunction<T>
17+
> extends MiddlewareBase<T, T, U> {
18+
/**
19+
* @description
20+
* @public
21+
* @param {T} context
22+
*/
23+
public override execute(context: T) {
24+
return super.execute(context), this;
25+
}
26+
27+
/**
28+
* @description
29+
* @public
30+
* @async
31+
* @param {T} context
32+
* @returns {unknown}
33+
*/
34+
public override async executeAsync(context: T): Promise<T> {
35+
return super.executeAsync(context);
36+
}
37+
38+
/**
39+
* @description
40+
* @public
41+
* @param {(context: T) => void} onComplete
42+
*/
43+
public override onComplete(onComplete: (context: T) => void): void {
44+
super.onComplete(onComplete);
45+
}
46+
47+
/**
48+
* @description
49+
* @public
50+
* @param {U} middleware
51+
* @returns {this}
52+
*/
53+
public override use(middleware: U): this {
54+
return super.use(middleware);
55+
}
56+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Abstract.
2+
import { ContextMiddlewareBase } from './context-middleware-base.abstract';
3+
// Type.
4+
import { ContextMiddlewareFunction } from '../type';
5+
/**
6+
* @description
7+
* @export
8+
* @class ContextMiddleware
9+
* @template [T=any]
10+
* @template {Function} [U=ContextMiddlewareFunction<T>]
11+
* @extends {ContextMiddlewareBase<T, U>}
12+
*/
13+
export class ContextMiddleware<
14+
T = any,
15+
U extends Function = ContextMiddlewareFunction<T>
16+
> extends ContextMiddlewareBase<T, U> {}

src/lib/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1-
export { Middleware } from './middleware.class';
1+
// Class.
2+
export { Middleware } from './middleware.class';
3+
export { ContextMiddleware } from './context-middleware.class';
4+
// Abstract.
5+
export { ContextMiddlewareBase } from './context-middleware-base.abstract';
6+
export { MiddlewareBase } from './middleware-base.abstract';
7+
export { MiddlewareCore } from './middleware-core.abstract';
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Abstract.
2+
import { MiddlewareCore } from './middleware-core.abstract';
3+
// Type.
4+
import { MiddlewareFunction } from '../type';
5+
/**
6+
* @description The base abstraction for arguments middleware.
7+
* @export
8+
* @abstract
9+
* @class MiddlewareBase
10+
* @typedef {MiddlewareBase}
11+
* @template [T=any]
12+
* @template [O=T[]]
13+
* @template {Function} [U=MiddlewareFunction<T>]
14+
* @extends {MiddlewareCore<T, O, U>}
15+
*/
16+
export abstract class MiddlewareBase<
17+
T = any,
18+
O = T[],
19+
U extends Function = MiddlewareFunction<T>
20+
> extends MiddlewareCore<T, O, U> {
21+
/**
22+
* @description
23+
* @type {number}
24+
*/
25+
#index = 0;
26+
27+
/**
28+
* @description
29+
* @type {U[]}
30+
*/
31+
#middleware: U[];
32+
33+
/**
34+
* @description
35+
* @type {() => void}
36+
*/
37+
#onComplete: (args: O) => void = () => {};
38+
39+
/**
40+
* Creates an instance of `MiddlewareBase`.
41+
* @constructor
42+
* @param {...U[]} middleware
43+
*/
44+
constructor(...middleware: U[]) {
45+
super();
46+
this.#middleware = middleware;
47+
}
48+
49+
/**
50+
* @description
51+
* @public
52+
* @param {...T[]} args
53+
* @returns {this}
54+
*/
55+
public execute(...args: T[]) {
56+
return this.#index = 0,
57+
this.#next(...args),
58+
this;
59+
}
60+
61+
/**
62+
* @description
63+
* @public
64+
* @async
65+
* @param {...T[]} args
66+
* @returns {unknown}
67+
*/
68+
public override async executeAsync(...args: T[]): Promise<O> {
69+
return this.#index = 0,
70+
await this.#nextAsync(...args),
71+
this.onComplete(() => args as O),
72+
args as O;
73+
}
74+
75+
/**
76+
* @description
77+
* @public
78+
* @param {(args: T[]) => void} onComplete
79+
*/
80+
public onComplete(onComplete: (args: O) => void): void {
81+
this.#onComplete = onComplete;
82+
}
83+
84+
/**
85+
* @description
86+
* @public
87+
* @param {U} middleware
88+
* @returns {this}
89+
*/
90+
public use(middleware: U): this {
91+
return this.#middleware.push(middleware), this;
92+
}
93+
94+
/**
95+
* @description
96+
* @param {...T[]} args
97+
*/
98+
#next(...args: T[]): void {
99+
this.#index < this.#middleware.length
100+
? this.#middleware[this.#index++](args, () => this.#next(...args))
101+
: this.#onComplete(args as O);
102+
}
103+
104+
/**
105+
* @description
106+
* @async
107+
* @param {...T[]} args
108+
* @returns {*}
109+
*/
110+
async #nextAsync(...args: T[]): Promise<void> {
111+
this.#index < this.#middleware.length
112+
? await this.#middleware[this.#index++](args, () => this.#nextAsync(...args))
113+
: this.#onComplete(args as O);
114+
}
115+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Interface.
2+
import { MiddlewareShape } from "../interface/middleware.shape";
3+
/**
4+
* @description
5+
* @export
6+
* @abstract
7+
* @class MiddlewareCore
8+
* @typedef {MiddlewareCore}
9+
* @template [Input=any]
10+
* @template [Output=void]
11+
* @template [Middleware=any]
12+
* @implements {MiddlewareShape<Input, Output, Middleware>}
13+
*/
14+
export abstract class MiddlewareCore<
15+
Input = any,
16+
Output = void,
17+
Middleware = any
18+
> implements MiddlewareShape<Input, Output, Middleware> {
19+
/**
20+
* @description
21+
* @public
22+
* @abstract
23+
* @param {...Input[]} args
24+
*/
25+
public abstract execute(context: Input): this;
26+
public abstract execute(...args: Input[]): this;
27+
28+
/**
29+
* @description
30+
* @public
31+
* @abstract
32+
* @param {Middleware} middleware
33+
* @returns {this}
34+
*/
35+
public abstract use(middleware: Middleware): this;
36+
37+
public abstract executeAsync(context: Input): Promise<Output>;
38+
public abstract executeAsync(...args: Input[]): Promise<Output>;
39+
}

0 commit comments

Comments
 (0)