seanpmaxwell / overnight

TypeScript decorators for the ExpressJS Server.
MIT License
878 stars 40 forks source link

Enable Merge Params on the Router #12

Closed cecilia-sanare closed 5 years ago

cecilia-sanare commented 5 years ago

Description

Currently it's impossible to specify parameters at the controller-level.

Which would be useful for routes nested under other controllers.

ProviderController = /providers
ProviderController.get = /:provider_name

InstallationController = /providers/:provider_name/installation
InstallationController.post = /:id

Example

import { Request, Response } from 'express';
import { Controller, Get } from '@overnightjs/core';

@Controller('health/:test')
export class HealthRoute {

  @Get(':id')
  public async get(req: Request, res: Response): Promise<any> {
    // Actual
    // {
    //   "id": "some-other-value"
    // }

    // Expected
    // {
    //   "test": "some-value",
    //   "id": "some-other-value"
    // }
    return res.status(200).json(req.params);
  }
}

Workaround

import PromiseRouter from 'express-promise-router';
import { Server as OvernightServer } from '@overnightjs/core';
import { HealthRoute } from './routes/routes';

export class ExpressServer extends OvernightServer {
  private server: Server;

  public constructor() {
    super();

    // We're basically wrapping out Router and passing in the params we want ourselves.
    this.addControllers([new HealthRoute()], () => PromiseRouter({
      mergeParams: true
    }));
  }

  public listen(port: number): void {
    this.app.listen(port, () => {
      console.log(`Started server on port: ${port}`);
    });
  }
}
seanpmaxwell commented 5 years ago

Your feature request has been fulfilled. OvernightJS now supports both nested controllers with the @Children decorator and adding options to controllers with the @ClassOptions decorator. Here's an example:

import { Controller, Get, Children, ClassOptions } from '@overnightjs/core';
import { Logger } from '@overnightjs/logger';
import { Request, Response } from 'express';
import { OK } from 'http-status-codes';
import { GrandChild1Controller } from './grandchildren/GrandChild1Controller';
import { GrandChild2Controller } from './grandchildren/GrandChild2Controller';
import { GrandChild3Controller } from './grandchildren/GrandChild3Controller';

@Controller('child-b1/:name')
@ClassOptions({mergeParams: true})
@Children([
    new GrandChild1Controller(),
    new GrandChild2Controller(),
    new GrandChild3Controller(),
])
export class ChildB1Controller {

    @Get()
    private get(req: Request, res: Response) {
        const message = 'Hi I\'m the child B1 controller';
        Logger.Info(message);
        Logger.Info(req.params, true);
        return res.status(OK).json({message});
    }
}