npm package: @fulminate/router
Description: Class-based views (controllers) for using with Express and TypeScript.
Author: Sergey Orlov
Latest version: 2.0.3

# Fulminate Class-Based View Router

This package introduces class-based views (controllers) for Express.js. Designed to be used with TypeScript.
Heavily inspired by Django's class based views.
This is a full revision of previously published Fulminate Router. To install current version:

`npm i --save @fulminate/router`

To use the deprecated version, install it with:

`npm i @fulminate/router@1.1.6`

## Migration guide (1.x.x to 2.x.x)

No migration. Its a 100% redone package.

## Example of use:

You first need to wire up the server. Fulminate class-based views wrap up Express server. If you've already started
working with Express, you can simply inject your code into Fulminate CBV without rewriting.

### Creating brand-new express server with Fulminate Router

```typescript
import * as morgan from 'morgan';
import { FulminateRouter } from '@fulminate/router';

const fS = new FulminateRouter();
// Provide paths and names of your Fulminate CBV files to make the router automatically require them.
// NOTE: You can provide strings, arrays of strings, regexes and arrays of regexes.
fS.registerViews(__dirname, [ /\/*.controller.js$/ ]);
fS.wireUp();

const server = fS.getServer();

// Add any required dependencies
// NOTE: Body and cookie parsers are already injected into Fulminate Router.
server.use(morgan('dev'));

// Set up view engine
server.set('view engine', 'ejs')
  .set('views', './')
  .engine('.html', require('ejs').renderFile)
;

server.listen(3000);
```

### Injecting existing Express server into Fulminate Router

```typescript
import * as express from 'express';
import * as morgan from 'morgan';
import { FulminateRouter } from '@fulminate/router';

const server = express();

server.use(morgan('dev'));

// Set up view engine
server.set('view engine', 'ejs')
  .set('views', './')
  .engine('.html', require('ejs').renderFile)
;

const fS = new FulminateRouter(server);
fS.registerViews(__dirname, [ /\/*.controller.js$/ ]);
fS.wireUp();

const server = fS.getServer();

// NOTE: You need to listen to the server taken from Fulminate Router.
fS.getServer().listen(3000);
```

### Examples of view classes

```typescript
import { Body, ClassBasedView, GetCookies, GetHeaders, QueryParams, RequestParams, SetCookie, SetHeader } from '@fulminate/class-based-view';

// View marked 'asJson: true' will return JSON.
@ClassBasedView({
  route: '/',
  asJson: true,
})
// Set response headers
@SetHeader({ key: 'X-Powered-By', value: 'Someone_Else' })
@SetHeader({ key: 'Authorization', value: 'ThisIsToken' })
export class TestView {
  // Decorated variables will not be listed in the response object and are meant to be used internally.
  @GetCookies()
  private _cookies: object;
  
  // To visually simplify the code, use 'private' for non-enumerable values and 'public' for enumerable ones.
  public title = 'TestView works!';
  
  // To make decorated variables enumerable, simply use a getter.
  // NOTE: You need to target at least 'es5' in tsconfig to be able to use getters.
  public get cookies(): object {
    return this._cookies;
  }
}

// Provide the route, marking request parameters with colons (':').
// NOTE: Template logic only works if you set up view engine.
@ClassBasedView({
  route: '/:param',
  template: 'index.html',
})
export class Test2View {
  // Set cookies (name of the variable is used as a cookie name and its value is used as cookie value).
  @SetCookie() cookieTheAnswer = '42';
  @SetCookie() whatsHerName = 'noname';
  
  public title: string;

  // Get access to request headers
  @GetHeaders()
  private headers: object;
  
  // Get query params
  // NOTE: Providing 'required' option to decorators will cause an error if the required data does not exist on request object.
  @QueryParams({ required: true })
  private queryParams: object;
  
  // Explicitly define which cookie or cookies are required
  @GetCookies({ required: true, explicitly: [ 'cookieTheAnswer' ]})
  private cookies: object;
  
  // Get request params
  // NOTE: Request params must also be present in the route option of @ClassBasedView decorator.
  @RequestParams()
  private requestParams: object;

  // Adjust values in the constructor.
  public constructor() {
    this.title = 'Test2View works!'
  }
}

// Define HTTP methods other than GET.
// NOTE: case-insensitive.
@ClassBasedView({
  route: '/',
  method: 'POST',
  asJson: true,
})
export class TestPostView {
  public name: string = "TestPostView works!";

  // Get the body of the request
  @Body()
  private body;
}
```