Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/iamolegga/create-nestjs-middleware-module

NestJS configured middleware module made simple
https://github.com/iamolegga/create-nestjs-middleware-module

middleware nest nestjs

Last synced: 1 day ago
JSON representation

NestJS configured middleware module made simple

Awesome Lists containing this project

README

        

create-nestjs-middleware-module



npm


npm


GitHub branch checks state





Known Vulnerabilities


Libraries.io

Dependabot
Supported platforms: Express & Fastify

NestJS configured middleware module made simple

## What is it?

It is a tiny helper library that helps you create simple _idiomatic_ **NestJS** module based on `Express`/`Fastify` middleware in just a few lines of code with routing out of the box.

## Install

```sh
npm i create-nestjs-middleware-module
```

or

```sh
yarn add create-nestjs-middleware-module
```

## Usage

Let's imaging you have some middleware factory, for example, simple logger:

```ts
export interface Options {
maxDuration: number
}

export function createResponseDurationLoggerMiddleware(opts: Options) {
return (request, response, next) => {
const start = Date.now();

response.on('finish', () => {
const message = `${request.method} ${request.path} - ${duration}ms`;

const duration = Date.now() - start;

if (duration > maxDuration) {
console.warn(message);
} else {
console.log(message);
}
});

next();
};
}
```

And you want to create an idiomatic NestJS module based on that middleware. Just pass this middleware factory to `createModule` function:

```ts
import { createModule } from 'create-nestjs-middleware-module';
import { Options, createResponseDurationLoggerMiddleware } from './middleware';

export const TimingModule = createModule(createResponseDurationLoggerMiddleware);
```

That's it, your module is ready. Let's see what API it has:

```ts
import { TimingModule } from './timing-module';
import { MyController } from './my.controller';

@Module({
imports: [

// 1. `.forRoot()` method accept params satisfying `Options` interface
TimingModule.forRoot({ maxDuration: 1000 }),

// 2. `.forRoot()` method accept additional optional routing params
TimingModule.forRoot({
maxDuration: 1000,

// both `forRoutes` and `exclude` properties are optional
// and has the same API as NestJS buil-in `MiddlewareConfigProxy`
// @see https://docs.nestjs.com/middleware#applying-middleware
forRoutes: [MyController],
exclude: [{ method: RequestMethod.ALL, path: 'always-fast' }],
}),

// 3. `.forRootAsync()` method with only factory
TimingModule.forRootAsync({
useFactory: async () => {
return { maxDuration: 1000 }
}
}),

// 4. `.forRootAsync()` method with dependencies
TimingModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (config: ConfigService) => {
return { maxDuration: config.maxDurationForAPIHandler }
}
}),

// 5. `.forRootAsync()` method with routing
TimingModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (config: ConfigService) => {
return {
maxDuration: config.maxDurationForAPIHandler

// both `forRoutes` and `exclude` properties are optional
// and has the same API as NestJS buil-in `MiddlewareConfigProxy`
// @see https://docs.nestjs.com/middleware#applying-middleware
forRoutes: [MyController],
exclude: [{ method: RequestMethod.ALL, path: 'always-fast' }],
};
}
}),
]
controllers: [MyController /*, ... */]
})
class App {}
```

## More examples

See examples of usage in `__tests__` folder or [nestjs-session](https://github.com/iamolegga/nestjs-session/blob/master/src/index.ts) and [nestjs-cookie-session](https://github.com/iamolegga/nestjs-cookie-session/blob/master/src/index.ts) packages

## Notes

1. `createModule` callback function can return not only one middleware, but array of it.

```ts
import { createModule } from 'create-nestjs-middleware-module';

interface Options {
// ...
}

createModule((options) => {
function firstMidlleware() { /* ... */ }
function secondMidlleware() { /* ... */ }
return [firstMidlleware, secondMidlleware]
});
```

2. If your `Options` interface has not __required__ properties it can be frustrating to force end-users of your module to call `forRoot({})`, and for better developer expirience you can cast `createModule(...)` result to `FacadeModuleStaticOptional`, then `forRoot()` could be called without arguments and without TS error. In such case `createModule` callback function will be called with empty object `{}`.

```ts
import { createModule, FacadeModuleStaticOptional } from 'create-nestjs-middleware-module';

interface Options {
maxDuration?: number;
}

createModule((options) => {
typeof options // always "object" even if not passed to `forRoot()`

return (request, response, next) => {
// ...
next();
};
}) as FacadeModuleStaticOptional;
```

3. For better developer experience of end-users of your module you can also export interfaces of `forRoot` and `forRootAsync` argument:

```ts
import {
AsyncOptions,
SyncOptions,
} from 'create-nestjs-middleware-module';

interface Options {
// ...
}

export type MyModuleOptions = SyncOptions;

export type MyModuleAsyncOptions = AsyncOptions;
```

4. This library is tested against `express` and `fastify`. But you should be aware that middlewares of `express` are not always work with `fastify` and vise versa. Sometimes you can check platforms internally. Sometimes maybe it's better to create 2 separate modules for each platform. It's up to you.

Do you use this library?
Don't be shy to give it a star! ★

Also if you are into NestJS you might be interested in one of my other NestJS libs.