Skip to content

Commit

Permalink
Rename all decorators to lowercase (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dmitry Nikulin authored and remojansen committed Jul 6, 2017
1 parent daa36d3 commit a55234b
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 227 deletions.
40 changes: 20 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,32 @@ Please refer to the [InversifyJS documentation](https://github.com/inversify/Inv
## The Basics

### Step 1: Decorate your controllers
To use a class as a "controller" for your express app, simply add the `@Controller` decorator to the class. Similarly, decorate methods of the class to serve as request handlers.
To use a class as a "controller" for your express app, simply add the `@controller` decorator to the class. Similarly, decorate methods of the class to serve as request handlers.
The following example will declare a controller that responds to `GET /foo'.

```ts
import * as express from 'express';
import { interfaces, Controller, Get, Post, Delete } from 'inversify-express-utils';
import { injectable, inject } from 'inversify';

@Controller('/foo')
@controller('/foo')
@injectable()
export class FooController implements interfaces.Controller {

constructor( @inject('FooService') private fooService: FooService ) {}

@Get('/')
@httpGet('/')
private index(req: express.Request, res: express.Response, next: express.NextFunction): string {
return this.fooService.get(req.query.id);
}

@Get('/')
private list(@QueryParams('start') start: number, @QueryParams('count') cound: number): string {
@httpGet('/')
private list(@queryParams('start') start: number, @queryParams('count') cound: number): string {
return this.fooService.get(start, count);
}

@Post('/')
private async create(@Response() res: express.Response) {
@httpPost('/')
private async create(@response() res: express.Response) {
try {
await this.fooService.create(req.body)
res.sendStatus(201)
Expand All @@ -61,8 +61,8 @@ export class FooController implements interfaces.Controller {
}
}

@Delete('/:id')
private delete(@RequestParam("id") id: string, @Response() res: express.Response): Promise<void> {
@httpDelete('/:id')
private delete(@requestParam("id") id: string, @response() res: express.Response): Promise<void> {
return this.fooService.delete(id)
.then(() => res.sendStatus(204))
.catch((err) => {
Expand Down Expand Up @@ -181,40 +181,40 @@ let server = new InversifyExpressServer(container, null, null, app);

## Decorators

### `@Controller(path, [middleware, ...])`
### `@controller(path, [middleware, ...])`

Registers the decorated class as a controller with a root path, and optionally registers any global middleware for this controller.

### `@Method(method, path, [middleware, ...])`
### `@httpMethod(method, path, [middleware, ...])`

Registers the decorated controller method as a request handler for a particular path and method, where the method name is a valid express routing method.

### `@SHORTCUT(path, [middleware, ...])`

Shortcut decorators which are simply wrappers for `@Method`. Right now these include `@Get`, `@Post`, `@Put`, `@Patch`, `@Head`, `@Delete`, and `@All`. For anything more obscure, use `@Method` (Or make a PR :smile:).
Shortcut decorators which are simply wrappers for `@httpMethod`. Right now these include `@httpGet`, `@httpPost`, `@httpPut`, `@httpPatch`, `@httpHead`, `@httpDelete`, and `@All`. For anything more obscure, use `@httpMethod` (Or make a PR :smile:).

### `@Request()`
### `@request()`
Binds a method parameter to the request object.

### `@Response()`
### `@response()`
Binds a method parameter to the response object.

### `@RequestParam(name?: string)`
### `@requestParam(name?: string)`
Binds a method parameter to request.params object or to a specific parameter if a name is passed.

### `@QueryParam(name?: string)`
### `@queryParam(name?: string)`
Binds a method parameter to request.query or to a specific query parameter if a name is passed.

### `@RequestBody(name?: string)`
### `@requestBody(name?: string)`
Binds a method parameter to request.body or to a specific body property if a name is passed.

### `@RequestHeaders(name?: string)`
### `@requestHeaders(name?: string)`
Binds a method parameter to the request headers.

### `@Cookies()`
### `@cookies()`
Binds a method parameter to the request cookies.

### `@Next()`
### `@next()`
Binds a method parameter to the next() function.

## Examples
Expand Down
52 changes: 26 additions & 26 deletions src/decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,42 @@ import * as express from "express";
import { interfaces } from "./interfaces";
import { METADATA_KEY, PARAMETER_TYPE } from "./constants";

export function Controller(path: string, ...middleware: interfaces.Middleware[]) {
export function controller(path: string, ...middleware: interfaces.Middleware[]) {
return function (target: any) {
let metadata: interfaces.ControllerMetadata = {path, middleware, target};
Reflect.defineMetadata(METADATA_KEY.controller, metadata, target);
};
}

export function All (path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return Method("all", path, ...middleware);
export function all (path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return httpMethod("all", path, ...middleware);
}

export function Get (path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return Method("get", path, ...middleware);
export function httpGet (path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return httpMethod("get", path, ...middleware);
}

export function Post (path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return Method("post", path, ...middleware);
export function httpPost (path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return httpMethod("post", path, ...middleware);
}

export function Put (path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return Method("put", path, ...middleware);
export function httpPut (path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return httpMethod("put", path, ...middleware);
}

export function Patch (path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return Method("patch", path, ...middleware);
export function httpPatch (path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return httpMethod("patch", path, ...middleware);
}

export function Head (path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return Method("head", path, ...middleware);
export function httpHead (path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return httpMethod("head", path, ...middleware);
}

export function Delete(path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return Method("delete", path, ...middleware);
export function httpDelete(path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return httpMethod("delete", path, ...middleware);
}

export function Method(method: string, path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
export function httpMethod(method: string, path: string, ...middleware: interfaces.Middleware[]): interfaces.HandlerDecorator {
return function (target: any, key: string, value: any) {
let metadata: interfaces.ControllerMethodMetadata = {path, middleware, method, target, key};
let metadataList: interfaces.ControllerMethodMetadata[] = [];
Expand All @@ -52,23 +52,23 @@ export function Method(method: string, path: string, ...middleware: interfaces.M
};
}

export const Request = paramDecoratorFactory(PARAMETER_TYPE.REQUEST);
export const Response = paramDecoratorFactory(PARAMETER_TYPE.RESPONSE);
export const RequestParam = paramDecoratorFactory(PARAMETER_TYPE.PARAMS);
export const QueryParam = paramDecoratorFactory(PARAMETER_TYPE.QUERY);
export const RequestBody = paramDecoratorFactory(PARAMETER_TYPE.BODY);
export const RequestHeaders = paramDecoratorFactory(PARAMETER_TYPE.HEADERS);
export const Cookies = paramDecoratorFactory(PARAMETER_TYPE.COOKIES);
export const Next = paramDecoratorFactory(PARAMETER_TYPE.NEXT);
export const request = paramDecoratorFactory(PARAMETER_TYPE.REQUEST);
export const response = paramDecoratorFactory(PARAMETER_TYPE.RESPONSE);
export const requestParam = paramDecoratorFactory(PARAMETER_TYPE.PARAMS);
export const queryParam = paramDecoratorFactory(PARAMETER_TYPE.QUERY);
export const requestBody = paramDecoratorFactory(PARAMETER_TYPE.BODY);
export const requestHeaders = paramDecoratorFactory(PARAMETER_TYPE.HEADERS);
export const cookies = paramDecoratorFactory(PARAMETER_TYPE.COOKIES);
export const next = paramDecoratorFactory(PARAMETER_TYPE.NEXT);

function paramDecoratorFactory(parameterType: PARAMETER_TYPE): (name?: string) => ParameterDecorator {
return function (name?: string): ParameterDecorator {
name = name || "default";
return Params(parameterType, name);
return params(parameterType, name);
};
}

export function Params(type: PARAMETER_TYPE, parameterName: string) {
export function params(type: PARAMETER_TYPE, parameterName: string) {
return function (target: Object, methodName: string, index: number) {

let metadataList: interfaces.ControllerParameterMetadata = {};
Expand Down
40 changes: 20 additions & 20 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
import { InversifyExpressServer } from "./server";
import { Controller, Method, Get, Put, Post, Patch, Head, All, Delete,
Request, Response, RequestParam, QueryParam, RequestBody, RequestHeaders,
Cookies, Next } from "./decorators";
import { controller, httpMethod, httpGet, httpPut, httpPost, httpPatch,
httpHead, all, httpDelete, request, response, requestParam, queryParam,
requestBody, requestHeaders, cookies, next } from "./decorators";
import { TYPE } from "./constants";
import { interfaces } from "./interfaces";

export {
interfaces,
InversifyExpressServer,
Controller,
Method,
Get,
Put,
Post,
Patch,
Head,
All,
Delete,
controller,
httpMethod,
httpGet,
httpPut,
httpPost,
httpPatch,
httpHead,
all,
httpDelete,
TYPE,
Request,
Response,
RequestParam,
QueryParam,
RequestBody,
RequestHeaders,
Cookies,
Next
request,
response,
requestParam,
queryParam,
requestBody,
requestHeaders,
cookies,
next
};
81 changes: 41 additions & 40 deletions test/bugs.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { expect } from "chai";
import * as express from "express";
import { Controller, Method, Get, Request, Response, RequestParam, QueryParam } from "../src/decorators";
import { controller, httpMethod, httpGet, request, response, requestParam,
queryParam } from "../src/decorators";
import { interfaces } from "../src/interfaces";
import { METADATA_KEY, PARAMETER_TYPE } from "../src/constants";
import { InversifyExpressServer } from "../src/server";
import { Container, injectable } from "inversify";
import { TYPE } from "../src/constants";
import * as request from "supertest";
import * as supertest from "supertest";

describe("Unit Test: Previous bugs", () => {

Expand All @@ -15,24 +16,24 @@ describe("Unit Test: Previous bugs", () => {
let container = new Container();

@injectable()
@Controller("/api/test")
@controller("/api/test")
class TestController {
@Get("/")
@httpGet("/")
public get(
@Request() req: express.Request,
@Response() res: express.Response
@request() req: express.Request,
@response() res: express.Response
) {
expect(req.url).not.to.eql(undefined);
expect((req as any).setHeader).to.eql(undefined);
expect(res.setHeader).not.to.eql(undefined);
expect((res as any).url).to.eql(undefined);
res.json([{ id: 1 }, { id: 2 }]);
}
@Get("/:id")
@httpGet("/:id")
public getById(
@RequestParam("id") id: string,
@Request() req: express.Request,
@Response() res: express.Response
@requestParam("id") id: string,
@request() req: express.Request,
@response() res: express.Response
) {
expect(id).to.eql("5");
expect(req.url).not.to.eql(undefined);
Expand All @@ -47,37 +48,37 @@ describe("Unit Test: Previous bugs", () => {
let server = new InversifyExpressServer(container);
let app = server.build();

request(app).get("/api/test/")
.expect("Content-Type", /json/)
.expect(200)
.then(response1 => {
expect(Array.isArray(response1.body)).to.eql(true);
expect(response1.body[0].id).to.eql("1");
expect(response1.body[0].id).to.eql("2");
});
supertest(app).get("/api/test/")
.expect("Content-Type", /json/)
.expect(200)
.then(response1 => {
expect(Array.isArray(response1.body)).to.eql(true);
expect(response1.body[0].id).to.eql("1");
expect(response1.body[0].id).to.eql("2");
});

request(app).get("/api/test/5")
.expect("Content-Type", /json/)
.expect(200)
.then(response2 => {
expect(Array.isArray(response2.body)).to.eql(false);
expect(response2.body.id).to.eql("5");
done();
});
supertest(app).get("/api/test/5")
.expect("Content-Type", /json/)
.expect(200)
.then(response2 => {
expect(Array.isArray(response2.body)).to.eql(false);
expect(response2.body.id).to.eql("5");
done();
});

});
it("should support empty query params", (done) => {
let container = new Container();

@injectable()
@Controller("/api/test")
@controller("/api/test")
class TestController {
@Get("/")
@httpGet("/")
public get(
@Request() req: express.Request,
@Response() res: express.Response,
@QueryParam("empty") empty: string,
@QueryParam("test") test: string
@request() req: express.Request,
@response() res: express.Response,
@queryParam("empty") empty: string,
@queryParam("test") test: string
) {
return {empty: empty, test: test};
}
Expand All @@ -88,14 +89,14 @@ describe("Unit Test: Previous bugs", () => {
let server = new InversifyExpressServer(container);
let app = server.build();

request(app).get("/api/test?test=testquery")
.expect("Content-Type", /json/)
.expect(200)
.then(response1 => {
expect(response1.body.test).to.eql("testquery");
expect(response1.body.empty).to.be.undefined;
done();
});
supertest(app).get("/api/test?test=testquery")
.expect("Content-Type", /json/)
.expect(200)
.then(response1 => {
expect(response1.body.test).to.eql("testquery");
expect(response1.body.empty).to.be.undefined;
done();
});

});

Expand Down
Loading

0 comments on commit a55234b

Please sign in to comment.