From d3671b620f6a44fa4d26180007eaadab7e188dd5 Mon Sep 17 00:00:00 2001 From: vincent178 Date: Wed, 14 Dec 2016 12:03:35 +0800 Subject: [PATCH 1/2] add response-view decorator --- .gitignore | 5 +++- src/constants/metadata-keys.ts | 1 + src/controllers/endpoint.ts | 32 ++++++++++++-------- src/decorators/index.ts | 3 +- src/decorators/response-view.ts | 13 ++++++++ test/endpoint.spec.ts | 53 +++++++++++++++++++++++++++++---- test/helper/FakeResponse.ts | 5 ++++ test/helper/TestInstance.ts | 5 ++++ 8 files changed, 97 insertions(+), 20 deletions(-) create mode 100644 src/decorators/response-view.ts diff --git a/.gitignore b/.gitignore index 41e9e907cbb..286fb147041 100644 --- a/.gitignore +++ b/.gitignore @@ -47,4 +47,7 @@ test/spec/*.js.map /stderr /es6/ /lib/ -/dts/ \ No newline at end of file +/dts/ + +.vscode + diff --git a/src/constants/metadata-keys.ts b/src/constants/metadata-keys.ts index e24302495b5..3235dc7919c 100644 --- a/src/constants/metadata-keys.ts +++ b/src/constants/metadata-keys.ts @@ -2,6 +2,7 @@ export const CONTROLLER_URL = "tsed:controller:url"; export const CONTROLLER_DEPEDENCIES = "ted:controller:depedencies"; export const ENDPOINT_ARGS = "tsed:endpoint"; +export const ENDPOINT_VIEW = "tsed:endpoint:view"; // INJECTION META TO CONTROLLER METHOD export const INJECT_PARAMS = "tsed:inject:params"; diff --git a/src/controllers/endpoint.ts b/src/controllers/endpoint.ts index 475eebe96fa..2ba4f53d737 100644 --- a/src/controllers/endpoint.ts +++ b/src/controllers/endpoint.ts @@ -1,5 +1,5 @@ import * as Express from "express"; -import {INJECT_PARAMS, EXPRESS_REQUEST, EXPRESS_RESPONSE, EXPRESS_NEXT_FN} from "../constants/metadata-keys"; +import {INJECT_PARAMS, EXPRESS_REQUEST, EXPRESS_RESPONSE, EXPRESS_NEXT_FN, ENDPOINT_VIEW} from "../constants/metadata-keys"; import Metadata from "../metadata/metadata"; import {IInvokableScope} from "../interfaces/InvokableScope"; import {BadRequest} from "ts-httpexceptions"; @@ -161,12 +161,8 @@ export class Endpoint { } }) - .then( - data => this.send(data, request, response, next, this.hasImpliciteNextFunction(instance)), - err => { - next(err); - } - ); + .then(data => this.send(instance, data, {request, response, next})) + .catch(err => next(err)); }; /** @@ -175,7 +171,7 @@ export class Endpoint { * @param localScope * @returns {(any|any)[]} */ - private getParameters(instance, localScope): any[] { + private getParameters(instance, localScope: IInvokableScope): any[] { const requestService = InjectorService.get(RequestService); @@ -237,14 +233,24 @@ export class Endpoint { /** * Format data and send it to the client. + * @param instance * @param data - * @param request - * @param response - * @param next - * @param impliciteNext + * @param localScope * @returns {any} */ - private send = (data, request, response, next, impliciteNext) => { + private send = (instance, data, localScope: IInvokableScope) => { + + const impliciteNext = this.hasImpliciteNextFunction(instance); + const request = localScope.request; + const response = localScope.response; + const next = localScope.next; + + const viewPath = Metadata.get(ENDPOINT_VIEW, instance, this.methodClassName); + + if (viewPath !== undefined) { + response.render(viewPath, data); + return data; + } // preset status code if (request.method === "POST") { diff --git a/src/decorators/index.ts b/src/decorators/index.ts index 1774630f093..491777015ae 100644 --- a/src/decorators/index.ts +++ b/src/decorators/index.ts @@ -9,4 +9,5 @@ export * from "./next"; export * from "./header"; export * from "./use"; export * from "./controller"; -export * from "./service"; \ No newline at end of file +export * from "./service"; +export * from "./response-view"; \ No newline at end of file diff --git a/src/decorators/response-view.ts b/src/decorators/response-view.ts new file mode 100644 index 00000000000..39b2f5b3fbe --- /dev/null +++ b/src/decorators/response-view.ts @@ -0,0 +1,13 @@ +import {ENDPOINT_VIEW} from "../constants/metadata-keys"; +import Metadata from "../metadata/metadata"; + +export function ResponseView(viewPath: string): Function { + + return (target: Function, targetKey: string, descriptor: TypedPropertyDescriptor): TypedPropertyDescriptor => { + + Metadata.set(ENDPOINT_VIEW, viewPath, target, targetKey); + + return descriptor; + }; +} + diff --git a/test/endpoint.spec.ts b/test/endpoint.spec.ts index 2b8639753e0..6a7e18bd3fb 100644 --- a/test/endpoint.spec.ts +++ b/test/endpoint.spec.ts @@ -210,42 +210,58 @@ describe("Endpoint :", () => { describe('Endpoint.send()', () => { it('should send response (boolean)', () => { + const instance = fakeController.getInstance(); const endpoint: any = new Endpoint(fakeController, 'myMethodThrowException'); const fakeRequest = new FakeRequest(); const fakeResponse = new FakeResponse(); const next = () => {}; - const result = endpoint.send(true, fakeRequest, fakeResponse, next); + endpoint.send(instance, true, { + request: fakeRequest, + response: fakeResponse, + next + }); expect(fakeResponse._body).to.be.a('string'); expect(fakeResponse._body).to.equal('true'); }); it('should send response (number)', () => { + const instance = fakeController.getInstance(); const endpoint: any = new Endpoint(fakeController, 'myMethodThrowException'); const fakeRequest = new FakeRequest(); const fakeResponse = new FakeResponse(); const next = () => {}; - const result = endpoint.send(1, fakeRequest, fakeResponse, next); + endpoint.send(instance, 1, { + request: fakeRequest, + response: fakeResponse, + next + }); expect(fakeResponse._body).to.be.a('string'); expect(fakeResponse._body).to.equal('1'); }); it('should send response (null)', () => { + const instance = fakeController.getInstance(); const endpoint: any = new Endpoint(fakeController, 'myMethodThrowException'); const fakeRequest = new FakeRequest(); const fakeResponse = new FakeResponse(); const next = () => {}; - const result = endpoint.send(null, fakeRequest, fakeResponse, next); + endpoint.send(instance, null, { + request: fakeRequest, + response: fakeResponse, + next + }); expect(fakeResponse._body).to.be.a('string'); expect(fakeResponse._body).to.equal('null'); }); it('should send response (date)', () => { + const instance = fakeController.getInstance(); const endpoint: any = new Endpoint(fakeController, 'myMethodThrowException'); const fakeRequest = new FakeRequest(); const fakeResponse = new FakeResponse(); @@ -253,7 +269,11 @@ describe("Endpoint :", () => { const date = new Date(); - const result = endpoint.send(date, fakeRequest, fakeResponse, next); + endpoint.send(instance, date, { + request: fakeRequest, + response: fakeResponse, + next + }); expect(fakeResponse._body).to.be.a('string'); expect(fakeResponse._headers).to.contains('Content-Type:text/json'); @@ -262,6 +282,7 @@ describe("Endpoint :", () => { }); it('should send response (object)', () => { + const instance = fakeController.getInstance(); const endpoint: any = new Endpoint(fakeController, 'myMethodThrowException'); const fakeRequest = new FakeRequest(); fakeRequest.method = 'POST'; @@ -271,13 +292,35 @@ describe("Endpoint :", () => { const obj = {test:'1', test2: new Date()}; - const result = endpoint.send(obj, fakeRequest, fakeResponse, next); + endpoint.send(instance, obj, { + request: fakeRequest, + response: fakeResponse, + next + }); expect(fakeResponse._body).to.be.a('string'); expect(fakeResponse._headers).to.contains('Content-Type:text/json'); expect(fakeResponse._body).to.equal(JSON.stringify(obj)); }); + + it('should render response (html)', () => { + const instance = fakeController.getInstance(); + const endpoint: any = new Endpoint(fakeController, 'myMethodAnnotated4'); + const fakeRequest = new FakeRequest(); + const fakeResponse = new FakeResponse(); + const next = () => {}; + const obj = {test: "test"}; + + endpoint.send(instance, {test: "test"}, { + request: fakeRequest, + response: fakeResponse, + next + }); + + expect(fakeResponse._body).to.be.a('string'); + expect(fakeResponse._body).to.equal("home" + obj.toString()); + }); }) }); \ No newline at end of file diff --git a/test/helper/FakeResponse.ts b/test/helper/FakeResponse.ts index 014a47fc0e7..35c5c3455a4 100644 --- a/test/helper/FakeResponse.ts +++ b/test/helper/FakeResponse.ts @@ -19,6 +19,11 @@ export class FakeResponse { public send(value: any) { this._body = '' + value; } + + public render(viewPath: string, data: Object) { + this._body = viewPath + data; + } + /** * * @param value diff --git a/test/helper/TestInstance.ts b/test/helper/TestInstance.ts index cea2903d2bf..fb31a64e5f6 100644 --- a/test/helper/TestInstance.ts +++ b/test/helper/TestInstance.ts @@ -4,6 +4,7 @@ import {Next} from '../../src/decorators/next'; import {Response} from '../../src/decorators/response'; import {BodyParams, PathParams, CookiesParams, QueryParams} from '../../src/decorators/params'; import {Required} from '../../src/decorators/required'; +import {ResponseView} from "../../src/decorators/response-view"; export class TestInstance { @@ -60,6 +61,10 @@ export class TestInstance { } + @ResponseView("home") + myMethodAnnotated4() { + } + /** * * @param request From b0fc1f328f3d5077d1ff4e30c50f54a0bee707f6 Mon Sep 17 00:00:00 2001 From: vincent178 Date: Wed, 14 Dec 2016 12:33:36 +0800 Subject: [PATCH 2/2] add logger for @ResponseView --- src/controllers/endpoint.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/controllers/endpoint.ts b/src/controllers/endpoint.ts index 2ba4f53d737..16450561f09 100644 --- a/src/controllers/endpoint.ts +++ b/src/controllers/endpoint.ts @@ -6,6 +6,7 @@ import {BadRequest} from "ts-httpexceptions"; import {InjectorService, RequestService} from "../services"; import InjectParams from "../metadata/inject-params"; import {BAD_REQUEST_REQUIRED} from "../constants/errors-msgs"; +import {$log} from "ts-log-debug"; export const METHODS = [ "all", "checkout", "connect", @@ -248,6 +249,7 @@ export class Endpoint { const viewPath = Metadata.get(ENDPOINT_VIEW, instance, this.methodClassName); if (viewPath !== undefined) { + $log.info(`[TSED] @ResponseView render ${viewPath}`); response.render(viewPath, data); return data; }