routify-hapi-controllers
A TypesScript or ES7 decorators library that generates Hapi routes for controllers based on decorators.
Dependencies
First and foremost your project needs Typescript
or at least support to ES7 Decorators.
Main libraries you need for it to work:
Hapi 16
npm install hapi@16.1.0 --save
// For Typescript you also need
npm install @types/hapi --save-dev
Inversify
Needed for dependency injection.
npm install inversify --save
// For Typescript you also need
npm install @types/inversify --save-dev
It is actually possible to use the library without Inversify instantiating the controllers and their dependencies by hand and loading the routes for the controllers individually.
Reflect-Metadata
A polyfill for reflection necessary for both Inversify to work and for this library's decorators.
npm install reflect-metadata --save
// For Typescript you also need
npm install @types/reflect-metadata --save-dev
Getting Started
First install the library:
npm install routify-hapi-controllers --save
This library already has typings built-in.
Load Reflect Metadata
In your main TS or JS file load reflect-metadata
, it has to be before every other dependencies.
app.ts (example)
import 'reflect-metadata';
import { Server } from 'hapi';
(...)
Setup your first Controller
For a controller you need to implement the IController
interface (if in Typescript), load the Controller
decorator as well as Inversify's injectable
decorators and the method decorators.
import { injectable } from 'inversify';
import { Controller, Get, Post } from 'routify-hapi-controllers';
@injectable()
@Controller('/v1/lemmings'/* , { (Optional Hapi route config for all endpoints) } */)
export default class LemmingsController {
@Get()
public get(request: Request) {
// Results in "GET /v1/lemmings"
}
@Get('/alive')
public getAlive(request: Request) {
// Results in "GET /v1/lemmings/alive"
}
@Post('/explode')
public postExplode(request: Request) {
// Results in "POST /v1/lemmings/explode"
}
}
You can have the optional Hapi config in individual endpoints as well, they are merged with the controller's configs for that endpoint.
You can also have automatically resolved dependencies in your controllers, check out Inversify's documentation for that.
If you don't want to use inversify, you can get rid of the @injectable
decorator.
Register your Controller (and dependencies)
You can do this anywhere, but it's probably better to have a file dedicated to that as your list of registrations might become big.
di.container.ts (or whatever)
import { Container } from 'inversify';
import LemmingsController from './controllers/lemmings.controller';
import { TYPES, registerController, IController } from 'routify-hapi-controllers';
const container = new Container();
// You can either register the controller using the inversify bind function:
container.bind<IController>(TYPES.CONTROLLER).to(LemmingsController);
// Or alternatively you can register with our helper function that makes things look nicer.
registerController(container, LemmingsController);
Load your routes
server.ts
import 'reflect-metadata'; // This was loaded in the first step.
import { container } from './di.container.ts';
import { retrieveAllRoutes } from 'routify-hapi-controllers';
// This will retrieve all routes for all of the registered Controllers
const routes = retrieveAllRoutes(container);
/*
Alternatively, if you didn't use Inversify, you can load the routes for specific Controllers.
const lemmingsController = new LemmingsController();
const potatoController = new PotatoController();
const routes = [
...getRoutesFromController(lemmingsController),
...getRoutesFromController(potatoController)
];
*/