Skip to content

Commit

Permalink
Implements InversifyJS/issues/586 (#162)
Browse files Browse the repository at this point in the history
  • Loading branch information
remojansen authored Apr 16, 2018
1 parent fee28fa commit cdb23b3
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 9 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "inversify-express-utils",
"version": "5.2.1",
"version": "5.2.2",
"description": "Some utilities for the development of express applications with Inversify",
"main": "lib/index.js",
"jsnext:main": "es/index.js",
Expand Down
8 changes: 4 additions & 4 deletions src/decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ export function httpMethod(method: string, path: string, ...middleware: interfac

let metadataList: interfaces.ControllerMethodMetadata[] = [];

if (!Reflect.hasOwnMetadata(METADATA_KEY.controllerMethod, target.constructor)) {
if (!Reflect.hasMetadata(METADATA_KEY.controllerMethod, target.constructor)) {
Reflect.defineMetadata(METADATA_KEY.controllerMethod, metadataList, target.constructor);
} else {
metadataList = Reflect.getOwnMetadata(METADATA_KEY.controllerMethod, target.constructor);
metadataList = Reflect.getMetadata(METADATA_KEY.controllerMethod, target.constructor);
}

metadataList.push(metadata);
Expand Down Expand Up @@ -116,10 +116,10 @@ export function params(type: PARAMETER_TYPE, parameterName: string) {
parameterName: parameterName,
type: type
};
if (!Reflect.hasOwnMetadata(METADATA_KEY.controllerParameter, target.constructor)) {
if (!Reflect.hasMetadata(METADATA_KEY.controllerParameter, target.constructor)) {
parameterMetadataList.unshift(parameterMetadata);
} else {
metadataList = Reflect.getOwnMetadata(METADATA_KEY.controllerParameter, target.constructor);
metadataList = Reflect.getMetadata(METADATA_KEY.controllerParameter, target.constructor);
if (metadataList.hasOwnProperty(methodName)) {
parameterMetadataList = metadataList[methodName];
}
Expand Down
2 changes: 1 addition & 1 deletion src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ export class InversifyExpressServer {
}

private _getHttpContext(req: express.Request) {
const httpContext = Reflect.getOwnMetadata(
const httpContext = Reflect.getMetadata(
METADATA_KEY.httpContext,
req
);
Expand Down
6 changes: 3 additions & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,23 @@ export function getControllersFromMetadata() {
}

export function getControllerMetadata(constructor: any) {
let controllerMetadata: interfaces.ControllerMetadata = Reflect.getOwnMetadata(
let controllerMetadata: interfaces.ControllerMetadata = Reflect.getMetadata(
METADATA_KEY.controller,
constructor
);
return controllerMetadata;
}

export function getControllerMethodMetadata(constructor: any) {
let methodMetadata: interfaces.ControllerMethodMetadata[] = Reflect.getOwnMetadata(
let methodMetadata: interfaces.ControllerMethodMetadata[] = Reflect.getMetadata(
METADATA_KEY.controllerMethod,
constructor
);
return methodMetadata;
}

export function getControllerParameterMetadata(constructor: any) {
let parameterMetadata: interfaces.ControllerParameterMetadata = Reflect.getOwnMetadata(
let parameterMetadata: interfaces.ControllerParameterMetadata = Reflect.getMetadata(
METADATA_KEY.controllerParameter,
constructor
);
Expand Down
197 changes: 197 additions & 0 deletions test/fetures/controller_inheritance.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import { expect } from "chai";
import * as express from "express";
import { interfaces } from "../../src/interfaces";
import * as bodyParser from "body-parser";
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 supertest from "supertest";
import {
controller, httpMethod, httpGet, request,
response, requestParam, queryParam, requestHeaders,
httpDelete, httpPost, httpPut, requestBody
} from "../../src/decorators";
import { cleanUpMetadata } from "../../src/utils";

function getDemoServer() {

interface Movie {
name: string;
}

let container = new Container();

@injectable()
class GenericController<T> {

@httpGet("/")
public get() {
return { status: "BASE GET!" };
}

@httpGet("/:id")
public getById(
@requestParam("id") id: string
) {
return { status: `BASE GET BY ID! ${id}` };
}

@httpPost("/")
public post(
@requestBody() body: T,
) {
return {
status: `BASE POST!`,
args: body
};
}

@httpPut("/:id")
public put(
@requestBody() body: T,
@requestParam("id") id: string
) {
return {
status: `BASE PUT! ${id}`,
args: body
};
}

@httpDelete("/:id")
public delete(
@requestParam("id") id: string
) {
return { status: `BASE DELETE! ${id}` };
}

}

@controller("/api/v1/movies")
class MoviesController extends GenericController<Movie> {

@httpDelete("/:movieId/actors/:actorId")
public deleteActor(
@requestParam("movieId") movieId: string,
@requestParam("actorId") actorId: string
) {
return { status: `DERIVED DELETE ACTOR! ${movieId} ${actorId}` };
}

}

let app = new InversifyExpressServer(container);

app.setConfig((a) => {
a.use(bodyParser.json());
a.use(bodyParser.urlencoded({ extended: true }));
});

let server = app.build();

return server;

}

describe("Derived controller", () => {

beforeEach((done) => {
cleanUpMetadata();
done();
});

it("Can access methods decorated with @httpGet from parent", (done) => {

const server = getDemoServer();

supertest(server).get("/api/v1/movies")
.expect(200)
.then(res => {
expect(res.body.status).to.eql("BASE GET!");
done();
});

});

it("Can access methods decorated with @httpGet from parent", (done) => {

const server = getDemoServer();
const id = 5;

supertest(server).get(`/api/v1/movies/${id}`)
.expect(200)
.then(res => {
expect(res.body.status).to.eql(`BASE GET BY ID! ${id}`);
done();
});

});

it("Can access methods decorated with @httpPost from parent", (done) => {

const server = getDemoServer();
const movie = { name: "The Shining" };
const status = `BASE POST!`;

supertest(server).post(`/api/v1/movies`)
.send(movie)
.set("Content-Type", "application/json")
.set("Accept", "application/json")
.expect(200)
.then(res => {
expect(res.body.status).to.eql(status);
expect(res.body.args).to.eql(movie);
done();
});

});

it("Can access methods decorated with @httpPut from parent", (done) => {

const server = getDemoServer();
const id = 5;
const movie = { name: "The Shining" };

supertest(server).put(`/api/v1/movies/${id}`)
.send(movie)
.set("Content-Type", "application/json")
.set("Accept", "application/json")
.expect(200)
.then(res => {
expect(res.body.status).to.eql(`BASE PUT! ${id}`);
expect(res.body.args).to.eql(movie);
done();
});

});

it("Can access methods decorated with @httpDelete from parent", (done) => {

const server = getDemoServer();
const id = 5;

supertest(server).delete(`/api/v1/movies/${id}`)
.expect(200)
.then(res => {
expect(res.body.status).to.eql(`BASE DELETE! ${id}`);
done();
});

});

it("Derived controller can have its own methods", (done) => {

const server = getDemoServer();
const movieId = 5;
const actorId = 3;

supertest(server).delete(`/api/v1/movies/${movieId}/actors/${actorId}`)
.expect(200)
.then(res => {
expect(res.body.status).to.eql(`DERIVED DELETE ACTOR! ${movieId} ${actorId}`);
done();
});

});

});

0 comments on commit cdb23b3

Please sign in to comment.