0.0.2 • Published 6 years ago

routedeck v0.0.2

Weekly downloads
4
License
MIT
Repository
github
Last release
6 years ago

routedeck

Highly productive Class and Method Decorators for TypeScript and Express. Among other features, turns async Express router methods into exception safe Express routes.

It's all about productivity; with a 60-second learning curve.

Install

npm i --save routedeck

Basic Usage

@get('/')
  async home(req: Request, res: Response, next: NextFunction) {
  res.json({ message: 'OK' });
}

Middleware:

@get('/', middleware, moreMiddleware, evenMoreMiddleware)
  async home(req: Request, res: Response, next: NextFunction) {
  res.json({ message: 'OK' });
}

You have access to the following

Decorators:

@get, @post, @put, @del, @patch, @all, @head, @options, @controller

The request methods are self-explanatory with the exception of del, use @del for delete. Beyond sending in middleware, you can also send in custom errors message. See Error Handling below.

Methods:

RouteDeck

RouteDeck - The Router You Seek

The RouteDeck method is vital. RouteDeck returns a normal express Router but built from your decorated methods. You can call this method during member declaration or in the constructor.

A Complete Router Class Example

// default-controller.ts
import { NextFunction, Request, Response, Router } from 'express';
import { get, RouteDeck } from 'routedeck';


class DefaultController {

  // IMPORTANT: Builds your router out of the decorated routes.
    router: Router = RouteDeck(this);

  @get('/')
  async home(req: Request, res: Response, next: NextFunction) {
    res.json({ message: 'Welcome' });
  }

}

// Create an instance of the class
// and export the router from that class.
export const defaultController = new DefaultController().router;

@controller

@controller prepends a list of middleware to each route in the class. While each route can have middleware, you can use @controller to add middleware to all routes in the class.

A Class using the @controller.

// default-controller.ts
import { NextFunction, Request, Response, Router } from 'express';
import { get, RouteDeck, controller } from 'routedeck';

// pass in a two middleware functions
@controller(myAuthorizeMiddleware('admin'), myLogger)
class AdminController {

  // IMPORTANT: Builds your router out of the decorated routes.
    router: Router = RouteDeck(this);

  @get('/' someMiddleware)
  async adminHome(req: Request, res: Response, next: NextFunction) {
    res.json({ message: 'Welcome Admin' });
  }

}

// Create an instance of the class and export the router
export const adminController = new AdminController().router;

In the above class, the middleware will run as follows for the / route:

  1. myAuthorizeMiddleware('admin') // From the controller
  2. myLogger // From the controller
  3. someMiddleware // From the route

Every route in the class would have the myAuthorizeMiddleware and myLogger middleware added to it.

How to use the resulting router classes

Taking the prior into consideration; in your main app.ts file:

import { defaultController } from './controllers/default';
import { adminController } from './controllers/admin';

// Setup
// etc...
// etc...

app.use('/', defaultController);
app.use('/backend', adminController);

Error Handling

Default Error Handling

Handle errors like your normally would in express. If your route has an exception it will call next() and pass in the error thereby meeting the error route method signature. For those who are not aware of this technique, I provide an example below. Just make exception handling your last rout(s) in your server.

import { defaultController } from './controllers/default';
import { adminController } from './controllers/admin';

// Setup
// etc...
// etc...

app.use('/', defaultController);
app.use('/backend', adminController);



 // 500 Logger - First Error Signature
app.use((err: any, req: Request, res: Response, next: NextFunction) => {
  console.error(err.stack);
  next(err); // next and pass the error again
});

// 500 Response - Second / next Error Signature
app.use((err: any, req: Request, res: Response, next: NextFunction) => {
  res.status(500).json({ message: '500 Server Error' });
});


//  listen ...

Note: Before moving forward it is import to note that you should always have error handing routes in your server.

Custom Error Handling

With each method decorator, you can pass in a custom error as either a string or an object as one of the parameters. Parameter order does not matter; parameters that are functions are assumed middleware, and a parameter that is a string or an object is assumed a custom error.

Note: This may appear to be a rather verbose check using typeof ―it is. However, the middleware and custom error message checks are done once per decorated route at application startup, not with each route access.

All are valid:

@get('/' 'Customer Error Message');
@get('/' middleware1, middleware2, 'Customer Error Message');
@get('/' middleware1, 'Customer Error Message', middleware2);
@get('/' 'Customer Error Message', middleware1);

In all cases above, the following is produced if an exception is encountered:

{
   "success": false,
   "error": true,
   "message": "Customer Error Message"
 }

You can use an object.

@get('/' {myError: 'Error', code:1234});
@get('/' middleware1, middleware2, {myError: 'Error', code:1234});
@get('/' middleware1, {myError: 'Error', code:1234}, middleware2);
@get('/' {myError: 'Error', code:1234}, middleware1);

The object will be the response.

{
  "myError": "Error",
  "code": 1234
  }

It all cases a 500 status code is produced.

Note: If you accidentally provide more than one custom error (string | object), routedeck will not throw an error. The last custom error found in the parameter list will be used.

So you are an expert in 60 seconds

  1. Decorate your async methods to turn them into routes
  2. You can use middleware and customer errors in your routes.
  3. Add a @controller to the class if you want to add middleware to all routes in the router for said class.
  4. Make sure you call RouteDeck(this) in your class to build and return a router.
  5. Export that router and use it like any other router, it is in fact just an express router.

I want more speed. I don't want to learn a new framework to get it.

Use routedeck!

Follow me on Twitter.