meta-controller is a library for creating NodeJs REST APIs using TypeScript decorators. It is a wrapper for the popular express framework. It's designed to be a lightweight alternative to NestJs.
Install the meta-controller package from npm.
npm install meta-controller
Create a REST API controller by using the JsonController(<route>)
decorator and define routes by using the @Route(<http method>, <path>)
decorator. Routes can be synchronous or asynchronous. Route paramaters are automatically transformed (meta-transformer) and validated (meta-validator).
@JsonController("/basic")
class WidgetController {
@Route(HttpMethod.GET)
get(): Widget {
return testWidget;
}
}
const expressApp = express();
MetaController.useExpressServer(expressApp, {
isUseCors: true,
controllerClassTypes: [
WidgetController
]
});
apiServer = http.createServer(expressApp);
apiServer.listen(4500);
Pass an instance of express to MetaController.useExpressServer()
to initialize meta-controller.
const expressApp = express();
MetaController.useExpressServer(expressApp, {
// options
});
The following initialization options are available.
Option | Description |
---|---|
isDebug | Log any errors to stdout |
routePrefix | Add a global route prefix (e.g. /api) |
isUseCors | Add CORS to all routes |
isSaveRawBody | Add the raw body to the request object (request.rawBody) |
controllerClassTypes | An array of class controllers that will be added as express routes) |
authorizationHandler | A user supplied function that determines if the request has been authorized |
currentUserHandler | A user supplied function that retrieves the user (if any) of the current request |
customErrorHandler | A global custom error handler |
globalMiddleware | Any optional global middleware |
Controllers may accept all standard REST type parameters. Parameters are automatically transformed or cast to the specified type.
@Route(HttpMethod.POST, "/body")
myRoute(@Body() widget: Widget) {
// ... business logic
}
// Example: https://localhost/api/param/5
@Route(HttpMethod.GET, "/param/:id")
myRoute(@Param("id") id: number) {
// ... business logic
}
// Example: https://localhost/api/query-param?myQueryParam=test
@Route(HttpMethod.POST, "/query-param")
myRoute(@QueryParam("myQueryParam") myQueryParam: string) {
// ... business logic
}
@Route(HttpMethod.GET, "/header-param")
myRoute(@HeaderParam("TestHeader") testHeader: string) {
// ... business logic
}
You can require authorization on a per-controller basis by specifying an authorizationHandler()
and using the @Authorization()
decorator.
const expressApp = express();
MetaController.useExpressServer(expressApp, {
authorizationHandler: (request, response, roles): boolean => {
// ... business logic
// Return true for authorized, false for unauthorized
return true;
}
});
@Authorize(["Admin"])
@JsonController("/secure")
class SecureController {
@Route(HttpMethod.GET, "/protected-route")
myRoute() {
// ... business logic
}
}
If you also add a currentUserHandler()
you can inject the current user using the CurrentUser()
decorator.
class User {
userName: string = "TestUser";
}
const testUser = new User();
const expressApp = express();
MetaController.useExpressServer(expressApp, {
currentUserHandler: (request, response): User => {
// ... business logic
return testUser;
}
});
@Route(HttpMethod.GET, "/current-user")
getCurrentUser(@CurrentUser() currentUser: User): User {
// ... business logic
return currentUser;
}
You can throw errors along with associated HTTP error codes.
@Authorize(["Admin"])
@JsonController("/secure")
class SecureController {
@Route(HttpMethod.GET, "/protected-route")
myRoute() {
throw new HttpError(HttpStatus.UNAUTHORIZED, "Unauthorized request");
}
}
If no HTTP error code is specified then meta-controller defaults to using HTTP status 500 (INTERNAL_SERVER_ERROR).
@Route(HttpMethod.POST, "/body")
myRoute(@Body() widget: Widget) {
// Returns HTTP status 500 - INTERNAL_SERVER_ERROR
throw new Error("An unknown error occurred");
}
Decorator | Type | Description |
---|---|---|
@Authorize() | Class | Controller requires authorization |
@JsonController() | Class | Create a JSON controller |
@Body() | Parameter | Inject a JSON body parameter |
@CurrentUser() | Parameter | Inject the current user |
@EncodedJwtToken() | Parameter | Inject the encoded JWT token string |
@HeaderParam() | Parameter | Inject a header from the HTTP request |
@Param() | Parameter | Inject a route parameter (e.g. /user/:id) |
@QueryParam() | Parameter | Inject a query parameter (e.g. /route?my-param=test) |
@Request() | Parameter | Inject the entire request object |
@Response() | Parameter | Inject the entire response object |
@Route(<http method, path>) | Property | Define a route on the controller |