npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

express-controllers-decorators

v1.0.1

Published

A TypeScript library for creating express controllers using decorators

Readme

@syesy12/express-controllers

A TypeScript library for creating express controllers using decorators

Features

  • TypeScript Support: Fully typed for better development experience.
  • Modular Design: Organize your Express.js routes using controllers.
  • Error Handling: Support for custom global error handler.
  • Inversion of Control: Integrate with your own IoC framework or instantiate controller classes manually.
  • Middleware Support: Apply middleware to specific routes or entire controllers.

Installation

Using npm:

npm install @syesy12/express-controllers reflect-metadata

Or using yarn:

yarn add @syesy12/express-controllers reflect-metadata

Usage

Basic Example

//./controllers/MyController.ts
import { Controller, 
  Get, 
  Post,
  Put,
  Delete,
  Patch,
  Options,
  Head,
  Body, 
  Query, 
  AbstractHttpResult, 
  HttpOkResult, 
  JsonPayload,
  PathParam
} from '@syesy12/express-controllers';

@Controller("/my-controller")
export class MyController {

  @Get("/example-get/:pathParam")
  public async get(
    @Query("param") param: string,
    @PathParam("pathParam") pathParam: string,
  ): Promise<AbstractHttpResult<JsonPayload>> {
    return new HttpOkResult(
      new JsonPayload({ message: "Get", param, pathParam })
    );
  }
  
  @Post("/example-post")
  public async post(@Body() body: any): Promise<AbstractHttpResult<JsonPayload>> {
    return new HttpOkResult(
      new JsonPayload({ message: "Post", body })
    );
  }
  
  @Put("/example-put")
  public async put(): Promise<AbstractHttpResult<JsonPayload>> {
    return new HttpOkResult(
      new JsonPayload({ message: "Put" })
    );
  }

  @Delete("/example-delete")
  public async delete(): Promise<AbstractHttpResult<JsonPayload>> {
    return new HttpOkResult(
      new JsonPayload({ message: "Delete" })
    );
  }

  @Patch("/example-patch")
  public async patch(): Promise<AbstractHttpResult<JsonPayload>> {
    return new HttpOkResult(
      new JsonPayload({ message: "Patch" })
    );
  }

  @Options("/example-options")
  public async options(): Promise<AbstractHttpResult<JsonPayload>> {
    return new HttpOkResult(
      new JsonPayload({ message: "Options" })
    );
  }

  @Head("/example-head")
  public async head(): Promise<AbstractHttpResult<JsonPayload>> {
    return new HttpOkResult(
      new JsonPayload({ message: "Head" })
    );
  }
}
//./ioc/MyControllerProvider.ts
import { IControllerProvider, ClassType } from '@syesy12/express-controllers';
export class MyControllerProvider implements IControllerProvider {
  public getController(controllerClass: ClassType): unknown {
    // Here you can implement your own logic to instantiate the controller
    // For example, using a dependency injection framework or manually.
    // Here we suppose this class has no dependencies and can be instantiated directly.
    return new controllerClass();
  }
}
//index.ts
import "reflect-metadata"; // Required for decorators to work
import express, { json } from 'express';
import { attachControllers } from '@syesy12/express-controllers';
import { MyController } from './controllers/MyController';
import { MyControllerProvider } from './ioc/MyControllerProvider';

const app = express();
app.use(json());

const port = 3000;

attachControllers({
  app,
  controllers: [MyController],
  controllerProvider: new MyControllerProvider(),
});

app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});

Global Error Handling

You can define a custom global error handler:

attachControllers({
  app,
  controllers: [MyController],
  controllerProvider: new MyControllerProvider(),
  globalErrorHandler: (err, req, res, next) => {
    if (err instanceof CustomError) {
      return res.status(400).json({ message: err.message });
    }
    next(err);
  },
});

Using With IoC Container

The only thing that changes is the MyControllerProvider implementation. For example, here you can see an implementation using microsoft/tsyringe

import { container } from "tsyringe";

export class MyControllerProvider implements IControllerProvider {
  public getController(controllerClass: ClassType): unknown {
    return container.resolve(controllerClass);
  }
}

Accessing Request and Response

In some situations, you might need to access the raw request or response objects. You can do this by using the @RequestObj() and @ResponseObj() decorators in your controller

import {
  RequestObj,
  ResponseObj,
} from '@syesy12/express-controllers';
import { Request, Response } from 'express';

@Controller("/my-controller")
export class MyController {
  @Get("/example-request-response")
  public async example(
    @RequestObj() req: Request,
    @ResponseObj() res: Response
  ): Promise<void> {
    
    res.sendStatus(200).json({
      queryParam: req.query.param,
    })
  }
}

Validating Body

You can use zod to validate the request body

import { z } from "zod";
import { json } from "express"
import { Middlewares } from "./Middlewares";

const schema = z.object({
  name: z.string(),
  age: z.number().min(0),
});

@Controller("/body-validation")
@Middlewares([json()])
class BodyValidationController {
  @Post("/")
  async bodyValidation(
    @Body(schema) body: z.infer<typeof schema>
  ) {
    console.log(body.name);
    console.log(body.age);
    return new HttpOkResult(new JsonPayload({ message: "Body is valid" }));
  }
}

Middleware

You can use the @Middlewares decorator to apply middlewares to a specific route

import { Handler } from "express"
const myMiddleware: Handler = (req, res, next) => {
  console.log("Middleware executed");
  next();
};

@Controller("/my-controller")
export class MyController {
  @Get("/example-middleware")
  @Middlewares([myMiddleware])
  public async exampleMiddleware(): Promise<AbstractHttpResult<JsonPayload>> {
    return new HttpOkResult(
      new JsonPayload({ message: "Middleware applied" })
    );
  }
}

or to an entire controller

import { Handler } from "express"
const myMiddleware: Handler = (req, res, next) => {
  console.log("Middleware executed");
  next();
};

@Controller("/my-controller")
@Middlewares([myMiddleware])
export class MyController {
  
  @Get("/example-middleware")
  public async exampleMiddleware(): Promise<AbstractHttpResult<JsonPayload>> {
    return new HttpOkResult(
      new JsonPayload({ message: "Middleware applied" })
    );
  }
}

License

This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.

Contributing

Contributions are welcome! Please follow the existing code style and ensure all tests pass before submitting a pull request