routing-controllers

repository·develop·Indexed 26 days ago

https://github.com/typestack/routing-controllers

A TypeScript library for creating structured, declarative, class-based controllers for Express and Koa using decorators. It features built-in support for parameter injection (@Param, @Body, @QueryParam), automatic request validation via class-validator, class-transformer integration, interceptors, and role-based authorization using the @Authorized decorator.

Tokens
19.5K
Snippets
51
Records
88
Agent score
86%

What's inside routing-controllers

  1. Quickstart: Create a Controller and Express Server

    develop

    Follow these steps to set up a basic RESTful API using routing-controllers and Express.

    1. Define a controller class using decorators like @Controller, @Get, @Post, @Param, and @Body.
    2. Initialize the server using createExpressServer and pass the controllers in the configuration object.
    3. Start the server using the standard .listen() method.
    import { createExpressServer } from 'routing-controllers';
    import { Controller, Param, Body, Get, Post, Put, Delete } from 'routing-controllers';
    
    @Controller()
    export class UserController {
      @Get('/users')
      getAll() {
        return 'This action returns all users';
      }
    
      @Get('/users/:id')
      getOne(@Param('id') id: number) {
        return 'This action returns user #' + id;
      }
    
      @Post('/users')
      post(@Body() user: any) {
        return 'Saving user...';
      }
    
      @Put('/users/:id')
      put(@Param('id') id: number, @Body() user: any) {
        return 'Updating a user...';
      }
    
      @Delete('/users/:id')
      remove(@Param('id') id: number) {
        return 'Removing user...';
      }
    }
    
    const app = createExpressServer({
      controllers: [UserController],
    });
    
    app.listen(3000);
  2. Quickstart with Express.js

    develop

    You can create controller classes with methods as actions that handle requests. routing-controllers will automatically register these routes in your Express or Koa server.

    1. Define a controller using decorators like @Controller, @Get, @Post, etc.
    2. Use createExpressServer to instantiate the app and register your controllers.
    3. Start the server using the returned Express instance.
    import 'reflect-metadata';
    import { createExpressServer } from 'routing-controllers';
    import { Controller, Param, Body, Get, Post, Put, Delete } from 'routing-controllers';
    
    @Controller()
    export class UserController {
      @Get('/users')
      getAll() {
        return 'This action returns all users';
      }
    
      @Get('/users/:id')
      getOne(@Param('id') id: number) {
        return 'This action returns user #' + id;
      }
    
      @Post('/users')
      post(@Body() user: any) {
        return 'Saving user...';
      }
    
      @Put('/users/:id')
      put(@Param('id') id: number, @Body() user: any) {
        return 'Updating a user...';
      }
    
      @Delete('/users/:id')
      remove(@Param('id') id: number) {
        return 'Removing user...';
      }
    }
    
    const app = createExpressServer({
      controllers: [UserController],
    });
    
    app.listen(3000);
  3. Quickstart: Create a Controller and Server

    develop

    You can create controllers using classes and decorators, then register them using createExpressServer (for Express) or createKoaServer (for Koa).

    Note: You must import reflect-metadata at the very beginning of your application entry point.

    // 1. Define a Controller (UserController.ts)
    import { Controller, Param, Body, Get, Post, Put, Delete } from 'routing-controllers';
    
    @Controller()
    export class UserController {
      @Get('/users')
      getAll() {
        return 'This action returns all users';
      }
    
      @Get('/users/:id')
      getOne(@Param('id') id: number) {
        return 'This action returns user #' + id;
      }
    
      @Post('/users')
      post(@Body() user: any) {
        return 'Saving user...';
      }
    
      @Put('/users/:id')
      put(@Param('id') id: number, @Body() user: any) {
        return 'Updating a user...';
      }
    
      @Delete('/users/:id')
      remove(@Param('id') id: number) {
        return 'Removing user...';
      }
    }
    
    // 2. Create the Server (app.ts)
    import 'reflect-metadata';
    import { createExpressServer } from 'routing-controllers';
    import { UserController } from './UserController';
    
    const app = createExpressServer({
      controllers: [UserController],
    });
    
    app.listen(3000);
  4. Use existing Express or Koa middleware

    develop

    You can apply existing middleware to specific actions, entire controllers, or globally.

    Per-action middleware

    Use @UseBefore(middleware) to run middleware before the action, or @UseAfter(middleware) to run it after.

    Per-controller middleware

    Apply @UseBefore or @UseAfter at the class level to affect all actions within that controller.

    Global middleware

    To apply middleware to every request, register it during the server bootstrap process using the middlewares option in createExpressServer or useExpressServer.

    // Per-action
    @Get("/users/:id")
    @UseBefore(compression())
    getOne(@Param("id") id: number) {
        // ...
    }
    
    // Per-controller
    @Controller()
    @UseBefore(compression())
    export class UserController {}
    
    // Global
    const app = createExpressServer({
      controllers: [UserController],
      middlewares: [LoggingMiddleware],
    });
  5. Implement Controller Inheritance

    develop

    You can use the template method pattern to reuse CRUD operations or other logic across multiple controllers by using an abstract base class. Controllers can extend this base class to inherit decorated methods.

    @Controller(`/product`)
    class ProductController extends AbstractControllerTemplate {}
    @Controller(`/category`)
    class CategoryController extends AbstractControllerTemplate {}
    
    abstract class AbstractControllerTemplate {
      @Post()
      public create() {}
    
      @Get()
      public read() {}
    
      @Put()
      public update() {}
    
      @Delete()
      public delete() {}
    }
  6. Enable class transformation for request parameters

    develop

    By default, routing-controllers uses class-transformer to instantiate classes when parsing request data (e.g., @Body, @Param, @QueryParam).

    If you specify a class type in your method signature, routing-controllers will create an actual instance of that class rather than a plain literal object. This allows you to use class methods on the parsed data.

    • To enable: Set classTransformer: true in createExpressServer (this is the default behavior).
    • To disable: Set classTransformer: false in createExpressServer.
    import { createExpressServer, Controller, Body } from 'routing-controllers';
    
    class User {
      firstName: string;
      lastName: string;
      getName(): string {
        return this.lastName + ' ' + this.firstName;
      }
    }
    
    @Controller()
    export class UserController {
      @Post("/")
      post(@Body() user: User) {
        // 'user' is an instance of User, so getName() is available
        console.log('saving user ' + user.getName());
      }
    }
    
    createExpressServer({
      classTransformer: true,
      controllers: [UserController],
    }).listen(3000);
  7. Integrate a Dependency Injection (DI) Container

    develop

    You can inject services into controllers, middlewares, and error handlers by setting up a DI container during application bootstrap using useContainer.

    When using typedi, ensure you decorate your Controllers with @Service() so the container can instantiate them.

    For other IoC providers (like inversify), implement the IocAdapter interface and pass it to useContainer.

    // Example with TypeDI
    import { createExpressServer, useContainer } from 'routing-controllers';
    import { Container } from 'typedi';
    import path from 'path';
    
    useContainer(Container);
    
    createExpressServer({
      controllers: [path.join(__dirname, '/controllers/*.js')],
      middlewares: [path.join(__dirname, '/middlewares/*.js')],
      interceptors: [path.join(__dirname, '/interceptors/*.js')],
    }).listen(3000);
    
    @Controller()
    @Service()
    export class UsersController {
      constructor(private userRepository: UserRepository) {}
    }
  8. Use interceptors to transform response data

    develop

    Interceptors allow you to modify or replace the data returned by a controller action. You can use them per-action via @UseInterceptor, per-controller, or globally via the @Interceptor decorator.

    Interceptor function

    Pass a function directly to @UseInterceptor. The function receives the action and the content (the original return value).

    Interceptor class

    Implement the InterceptorInterface and use the intercept(action: Action, content: any) method to return the transformed content.

    // Function Interceptor
    @Get("/users")
    @UseInterceptor(function(action: Action, content: any) {
        return content.replace(/Mike/gi, "Michael");
    })
    getOne() {
        return "Hello, I am Mike!";
    }
    
    // Class Interceptor
    import { Interceptor, InterceptorInterface, Action } from 'routing-controllers';
    
    export class NameCorrectionInterceptor implements InterceptorInterface {
      intercept(action: Action, content: any) {
        return content.replace(/Mike/gi, 'Michael');
      }
    }
    
    @UseInterceptor(NameCorrectionInterceptor)
    @Get("/users")
    getOne() {
        return "Hello, I am Mike!";
    }
  9. Enable or disable automatic parameter validation

    develop

    Routing-controllers uses class-validator to automatically validate incoming request data against class definitions. This feature is enabled by default.

    To disable global validation, set validation: false in createExpressServer.

    To enable validation for a specific parameter, use the validate: true option within the parameter decorator (e.g., @Body({ validate: true })).

    When validation fails, routing-controllers catches the error and returns a 400 status code to the client with detailed validation error messages.

    import { createExpressServer } from 'routing-controllers';
    
    // Disable global validation
    createExpressServer({
      validation: false,
    }).listen(3000);
    
    // Enable validation for a specific parameter
    @Post("/login")
    login(@Body({ validate: true }) user: User) {}
  10. Configure Auto-validating Action Parameters

    develop

    By default, routing-controllers integrates with class-validator to automatically validate action parameters. If a parameter does not satisfy the decorators defined on its class, a 400 Bad Request is returned with a detailed validation errors array.

    • Global Disable: Pass validation: false to createExpressServer.
    • Local Enable: Use the validate: true option within a parameter decorator (e.g., @Body({ validate: true })).
    • Supported Decorators: This works with @Body, @Param, @QueryParam, @BodyParam, and others.
    • Custom Options: You can pass global validation config via createExpressServer({ validation: ... }) or local settings via @Body({ validate: localOptions }).
    import { createExpressServer } from 'routing-controllers';
    
    // Disable validation globally
    createExpressServer({
      validation: false,
    }).listen(3000);
    
    // Enable validation locally for a specific parameter
    @Post("/login")
    login(@Body({ validate: true }) user: User) {}
    
    // Example User class with class-validator decorators
    export class User {
      @IsEmail()
      email: string;
    
      @MinLength(6)
      password: string;
    }