create-nestjs-middleware-module
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
npm i create-nestjs-middleware-module
or
yarn add create-nestjs-middleware-module
Usage
Let's imaging you have some middleware factory, for example, simple logger:
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:
import { createModule } from 'create-nestjs-middleware-module';
import { Options, createResponseDurationLoggerMiddleware } from './middleware';
export const TimingModule = createModule<Options>(createResponseDurationLoggerMiddleware);
That's it, your module is ready. Let's see what API it has:
import { TimingModule } from './timing-module';
import { MyController } from './my.controller';
@Module({
imports: [
TimingModule.forRoot({ maxDuration: 1000 }),
TimingModule.forRoot({
maxDuration: 1000,
forRoutes: [MyController],
exclude: [{ method: RequestMethod.ALL, path: 'always-fast' }],
}),
TimingModule.forRootAsync({
useFactory: async () => {
return { maxDuration: 1000 }
}
}),
TimingModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (config: ConfigService) => {
return { maxDuration: config.maxDurationForAPIHandler }
}
}),
TimingModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (config: ConfigService) => {
return {
maxDuration: config.maxDurationForAPIHandler
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 and nestjs-cookie-session packages
Notes
createModule
callback function can return not only one middleware, but array of it.
import { createModule } from 'create-nestjs-middleware-module';
interface Options {
}
createModule<Options>((options) => {
function firstMidlleware() { }
function secondMidlleware() { }
return [firstMidlleware, secondMidlleware]
});
- 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<Options>
, then forRoot()
could be called without arguments and without TS error. In such case createModule
callback function will be called with empty object {}
.
import { createModule, FacadeModuleStaticOptional } from 'create-nestjs-middleware-module';
interface Options {
maxDuration?: number;
}
createModule<Options>((options) => {
typeof options
return (request, response, next) => {
next();
};
}) as FacadeModuleStaticOptional<Options>;
- For better developer experience of end-users of your module you can also export interfaces of
forRoot
and forRootAsync
argument:
import {
AsyncOptions,
SyncOptions,
} from 'create-nestjs-middleware-module';
interface Options {
}
export type MyModuleOptions = SyncOptions<Options>;
export type MyModuleAsyncOptions = AsyncOptions<Options>;
- 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.