Configurable NestJS Middleware Module Creator
raw JSON →create-nestjs-middleware-module is a lightweight utility library designed to simplify the integration and configuration of Express or Fastify middleware into NestJS applications. It abstracts away the boilerplate of implementing `NestModule` and `MiddlewareConsumer` by providing a `createModule` function, allowing developers to define middleware factories that can accept options. The library currently supports NestJS versions 8 through 11 and requires Node.js >=18.0.0. It aims to provide an idiomatic NestJS way to encapsulate middleware logic within a modular structure, enabling configuration via `forRoot` or `forRootAsync` methods, and offering fine-grained control over routing, similar to NestJS's built-in `MiddlewareConfigProxy`. Its current stable version is 0.4.0, with releases occurring as needed to maintain compatibility with new NestJS versions.
Common errors
error TypeError: Cannot read properties of undefined (reading 'forRoot') ↓
createModule has been called with the middleware factory. Double-check the import path from 'create-nestjs-middleware-module' and verify the export name of your custom module. If the error occurs when calling forRoot() without arguments, ensure FacadeModuleStaticOptional type assertion is used. error Error: Nest can't resolve dependencies of the XModule (?). Please make sure that the argument at index [0] is available in the XModule context. ↓
createModule's configuration (if supported by a future API), made available globally, or refactor your middleware to receive only configuration options directly. error TS2345: Argument of type '(req: Request, res: Response, next: NextFunction) => void' is not assignable to parameter of type 'MiddlewareFactory<T>'. ↓
options parameter of type T (or void if no options are expected) and returns either a single middleware function (req, res, next) => void or an array of such functions. Verify the T generic type argument passed to createModule matches your Options interface. Warnings
breaking Version 0.3.0 dropped support for NestJS versions older than 8 and Node.js versions older than 16. Ensure your project meets these minimum requirements before upgrading. ↓
gotcha When using `createModule` with optional configurations, it's recommended to cast the result to `FacadeModuleStaticOptional<Options>` to allow calling `forRoot()` without arguments. Without this, TypeScript will require an empty object even if options are truly optional. ↓
gotcha This library supports both Express and Fastify platforms; however, not all middleware created for one platform will inherently work with the other. Ensure your custom middleware functions are compatible with the NestJS platform adapter you are using. ↓
breaking NestJS v11 introduced changes to how middleware registered in global modules is executed, now always running first regardless of dependency graph position. While this library simplifies middleware creation, be aware of the overall middleware execution order in NestJS v11+ applications. ↓
Install
npm install create-nestjs-middleware-module yarn add create-nestjs-middleware-module pnpm add create-nestjs-middleware-module Imports
- createModule wrong
const { createModule } = require('create-nestjs-middleware-module');correctimport { createModule } from 'create-nestjs-middleware-module'; - FacadeModuleStaticOptional
import { createModule, FacadeModuleStaticOptional } from 'create-nestjs-middleware-module'; - SyncOptions
import { SyncOptions } from 'create-nestjs-middleware-module'; - AsyncOptions
import { AsyncOptions } from 'create-nestjs-middleware-module';
Quickstart
import { Module, NestModule, MiddlewareConsumer, INestApplication } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { Request, Response, NextFunction } from 'express';
import { createModule, FacadeModuleStaticOptional } from 'create-nestjs-middleware-module';
// 1. Define your middleware factory and its options
interface LoggerMiddlewareOptions {
prefix?: string;
}
function createCustomLoggerMiddleware(options?: LoggerMiddlewareOptions) {
const prefix = options?.prefix || 'APP';
return (req: Request, res: Response, next: NextFunction) => {
console.log(`[${prefix}] Request: ${req.method} ${req.url}`);
next();
};
}
// 2. Create your NestJS module using createModule
export const CustomLoggerModule = createModule<LoggerMiddlewareOptions>(
createCustomLoggerMiddleware
) as FacadeModuleStaticOptional<LoggerMiddlewareOptions>;
// 3. Use the module in your main application
@Module({
imports: [
// Example: Configure with options
CustomLoggerModule.forRoot({
prefix: 'API',
forRoutes: ['/data*'] // Apply to routes starting with /data
}),
// Example: Use without options (requires FacadeModuleStaticOptional assertion)
CustomLoggerModule.forRoot(), // Apply to all routes by default
],
controllers: [],
providers: [],
})
class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
// Additional NestJS native middleware configuration if needed
// For instance, if you want to exclude specific paths from the CustomLoggerModule's default application
// consumer
// .apply(SomeOtherMiddleware)
// .exclude('/admin*')
// .forRoutes('*');
}
}
async function bootstrap() {
const app: INestApplication = await NestFactory.create(AppModule);
await app.listen(process.env.PORT || 3000);
console.log(`Application is running on: ${await app.getUrl()}`);
}
// To run this example, you would typically have an Express/Fastify adapter configured
// and a controller responding to /data* or other routes.
bootstrap();