From 3f9019f3a43a4e8156a6c8cdec114d8b16893fe0 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Thu, 21 Mar 2019 15:05:53 +0900 Subject: [PATCH 01/20] Discard deprecated apis --- src/BaseController.ts | 93 +++++-------------------------- src/specs/BaseController.spec.ts | 95 -------------------------------- 2 files changed, 14 insertions(+), 174 deletions(-) diff --git a/src/BaseController.ts b/src/BaseController.ts index 1bf2af2..fcae182 100644 --- a/src/BaseController.ts +++ b/src/BaseController.ts @@ -10,12 +10,6 @@ import { RenderResultCallback, SendFileResultCallback } from './results' -import { OutgoingHttpHeaders } from 'http' - -interface HttpContext { - req: express.Request - res: express.Response -} interface Context { req: express.Request @@ -26,100 +20,41 @@ interface Context { export class BaseController { context?: Context - /* istanbul ignore next */ - get httpContext(): HttpContext | undefined { - // tslint:disable-next-line:no-console - console.warn( - 'BaseController#httpContext will be deprecated from v1.0.0. Please use BaseController#context.' - ) - if (this.context == null) return - return { - req: this.context.req, - res: this.context.res - } - } - - /* istanbul ignore next */ - get injector(): ((key: string) => any) | undefined { - // tslint:disable-next-line:no-console - console.warn( - 'BaseController#injector will be deprecated from v1.0.0. Please use BaseController#context.inject.' - ) - if (this.context == null) return - return this.context.inject - } - - /* istanbul ignore next */ - set injector(injector: ((key: string) => any) | undefined) { - // tslint:disable-next-line:no-console - console.warn( - 'BaseController#injector will be deprecated from v1.0.0. Please use BaseController#context.inject.' - ) - if (this.context != null && injector != null) { - this.context.inject = injector - } - } - - /* istanbul ignore next */ - inject(key: string): S { - // tslint:disable-next-line:no-console - console.warn( - 'BaseController#inject will be deprecated from v1.0.0. Please use BaseController#context.inject.' - ) - if (this.injector == null) throw new Error('Injector is not set.') - return this.injector(key) - } - - end( - data: D, - encoding?: string, - status?: number, - headers?: OutgoingHttpHeaders - ): EndResult { - return new EndResult(data, encoding, status, headers) + end(data: D, encoding?: string, status?: number): EndResult { + return new EndResult(data, encoding, status) } - json( - data: D, - status?: number, - headers?: OutgoingHttpHeaders - ): JSONResult { - return new JSONResult(data, status, headers) + json(data: D, status?: number): JSONResult { + return new JSONResult(data, status) } - redirect(location: string, status?: number, headers?: OutgoingHttpHeaders) { - return new RedirectResult(location, status, headers) + redirect(location: string, status?: number) { + return new RedirectResult(location, status) } render( view: string, locals?: D, callback?: RenderResultCallback, - status?: number, - headers?: OutgoingHttpHeaders + status?: number ): RenderResult { - return new RenderResult(view, locals, callback, status, headers) + return new RenderResult(view, locals, callback, status) } sendFile( filePath: string, options?: any, callback?: SendFileResultCallback, - status?: number, - headers?: OutgoingHttpHeaders + status?: number ) { - return new SendFileResult(filePath, options, callback, status, headers) + return new SendFileResult(filePath, options, callback, status) } - send( - data: D, - status?: number, - headers?: OutgoingHttpHeaders - ): SendResult { - return new SendResult(data, status, headers) + send(data: D, status?: number): SendResult { + return new SendResult(data, status) } - sendStatus(status: number, headers?: OutgoingHttpHeaders) { - return new SendStatusResult(status, headers) + sendStatus(status: number) { + return new SendStatusResult(status) } } diff --git a/src/specs/BaseController.spec.ts b/src/specs/BaseController.spec.ts index 67a2780..4b3113d 100644 --- a/src/specs/BaseController.spec.ts +++ b/src/specs/BaseController.spec.ts @@ -196,99 +196,4 @@ describe('BaseController', () => { }) }) }) - - // Deprecated from v1 - describe('#inject', () => { - it('returns a registered service from the container', async () => { - // Given - enum ServiceTypes { - MyService = 'MyService' - } - class MyService { - sayHello() { - return 'Hello' - } - } - - const container = { - [ServiceTypes.MyService]: MyService - } - @controller('/') - class HomeController extends BaseController { - @httpGet('/') - index() { - return this.inject(ServiceTypes.MyService).sayHello() - } - } - const app = tachijs({ - controllers: [HomeController], - container - }) - - // When - const response = await request(app).get('/') - - // Then - expect(response).toMatchObject({ - status: 200, - text: 'Hello' - }) - }) - - it('throws an error if no service registered for the given key', async () => { - // Given - enum ServiceTypes { - MyService = 'MyService' - } - class MyService { - sayHello() { - return 'Hello' - } - } - - @controller('/') - class HomeController extends BaseController { - @httpGet('/') - index() { - return this.inject(ServiceTypes.MyService).sayHello() - } - } - const after: ConfigSetter = expressApp => { - const errorHandler: ErrorRequestHandler = (error, req, res, next) => { - res.status(500).json({ - message: error.message - }) - } - expressApp.use(errorHandler) - } - const app = tachijs({ - controllers: [HomeController], - after - }) - - // When - const response = await request(app).get('/') - - // Then - expect(response).toMatchObject({ - status: 500, - text: JSON.stringify({ - message: 'No service is registered for "MyService" key.' - }) - }) - }) - - it('returns a registered service from the container', async () => { - // Given - expect.assertions(1) - // When - try { - baseController.inject('something') - } catch (error) { - expect(error).toMatchObject({ - message: 'Injector is not set.' - }) - } - }) - }) }) From 8877eca7d1226a24fa2ee22c25e296b4e27d7870 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Thu, 21 Mar 2019 15:13:59 +0900 Subject: [PATCH 02/20] No reflect:controller --- src/decorators/controller.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/decorators/controller.ts b/src/decorators/controller.ts index 72ff9bf..5f87517 100644 --- a/src/decorators/controller.ts +++ b/src/decorators/controller.ts @@ -1,7 +1,6 @@ -import { MetaKey } from '../consts' import { RequestHandler, RouterOptions } from 'express' -const metaKey = MetaKey.controller +const controllerMetaMap = new Map() export interface ControllerMeta { path: string @@ -12,14 +11,14 @@ export interface ControllerMeta { export function getControllerMeta( ControllerConstructor: any ): ControllerMeta | undefined { - return Reflect.getMetadata(metaKey, ControllerConstructor) + return controllerMetaMap.get(ControllerConstructor) } export function setControllerMeta( ControllerConstructor: any, meta: ControllerMeta ): void { - Reflect.defineMetadata(metaKey, meta, ControllerConstructor) + controllerMetaMap.set(ControllerConstructor, meta) } export function controller( From 86aaab0e0068c41bffe6b1a05b41999b32c82c8d Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Thu, 21 Mar 2019 15:15:22 +0900 Subject: [PATCH 03/20] No reflect: httpMethod --- src/decorators/httpMethod.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/decorators/httpMethod.ts b/src/decorators/httpMethod.ts index b50f052..827f3d3 100644 --- a/src/decorators/httpMethod.ts +++ b/src/decorators/httpMethod.ts @@ -1,7 +1,6 @@ -import { MetaKey } from '../consts' import { RequestHandler } from 'express' -const metaKey = MetaKey.httpMethod +const httpMethodMetaMap = new Map() export interface HttpMethodMeta { method: string @@ -13,7 +12,7 @@ export interface HttpMethodMeta { export type HttpMethodMetaList = HttpMethodMeta[] export function getHttpMethodMetaList(controller: any): HttpMethodMetaList { - const metaList = Reflect.getMetadata(metaKey, controller) + const metaList = httpMethodMetaMap.get(controller) if (metaList == null) return [] return metaList } @@ -22,7 +21,7 @@ export function setHttpMethodMetaList( controller: any, meta: HttpMethodMetaList ): void { - Reflect.defineMetadata(metaKey, meta, controller) + httpMethodMetaMap.set(controller, meta) } export function httpMethod( From 5535ca2c9297c8904e39feb045fcd4f3dac700ba Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Thu, 21 Mar 2019 15:19:40 +0900 Subject: [PATCH 04/20] No reflect: inject --- src/decorators/inject.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/decorators/inject.ts b/src/decorators/inject.ts index 795fae4..b662537 100644 --- a/src/decorators/inject.ts +++ b/src/decorators/inject.ts @@ -1,6 +1,4 @@ -import { MetaKey } from '../consts' - -const metaKey = MetaKey.inject +const injectMetaMap = new Map() export interface InjectMeta { index: number @@ -10,13 +8,13 @@ export interface InjectMeta { export type InjectMetaList = InjectMeta[] export function getInjectMetaList(controller: any): InjectMetaList { - const metaList = Reflect.getMetadata(metaKey, controller) + const metaList = injectMetaMap.get(controller) if (metaList == null) return [] return metaList } export function setInjectMetaList(controller: any, meta: InjectMetaList): void { - Reflect.defineMetadata(metaKey, meta, controller) + injectMetaMap.set(controller, meta) } export function inject(key: string) { From f00f82353c7b8ff6076f0379e9a1ea2c55e91158 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Thu, 21 Mar 2019 15:48:52 +0900 Subject: [PATCH 05/20] No reflect: handlerParam --- src/consts.ts | 7 ---- src/decorators/handlerParam/handlerParam.ts | 41 ++++++++++++++------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/consts.ts b/src/consts.ts index 4e0aadf..e279a60 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -1,10 +1,3 @@ -export const MetaKey = { - controller: 'tachijs:controller', - httpMethod: 'tachijs:httpMethod', - handlerParam: 'tachijs:handlerParam', - inject: 'tachijs:inject' -} - export enum HttpStatus { CONTINUE = 100, SWITCHING_PROTOCOLS = 101, diff --git a/src/decorators/handlerParam/handlerParam.ts b/src/decorators/handlerParam/handlerParam.ts index 88a5bb9..528917b 100644 --- a/src/decorators/handlerParam/handlerParam.ts +++ b/src/decorators/handlerParam/handlerParam.ts @@ -1,7 +1,11 @@ -import { MetaKey } from '../../consts' import express from 'express' -const metaKey = MetaKey.handlerParam +const reflectMetadataIsAvailable = typeof Reflect.getMetadata !== 'undefined' + +const handlerParamMetaMap = new Map< + any, + Map[]> +>() export type HandlerParamSelector = ( req: express.Request, @@ -13,7 +17,7 @@ export type HandlerParamSelector = ( export interface HandlerParamMeta { index: number selector: HandlerParamSelector - paramType: any + paramType?: any } export type HandlerParamMetaList = HandlerParamMeta[] @@ -22,7 +26,8 @@ export function getHandlerParamMetaList( controller: any, propertyKey: string ): HandlerParamMetaList { - const metaList = Reflect.getMetadata(metaKey, controller, propertyKey) + if (!handlerParamMetaMap.has(controller)) return [] + const metaList = handlerParamMetaMap.get(controller)!.get(propertyKey) if (metaList == null) return [] return metaList } @@ -32,7 +37,11 @@ export function setHandlerParamMetaList( meta: HandlerParamMetaList, propertyKey: string ): void { - Reflect.defineMetadata(metaKey, meta, controller, propertyKey) + if (!handlerParamMetaMap.has(controller)) { + handlerParamMetaMap.set(controller, new Map()) + } + const propertyKeyMetaMap = handlerParamMetaMap.get(controller)! + propertyKeyMetaMap.set(propertyKey, meta) } export function handlerParam(selector: HandlerParamSelector) { @@ -46,16 +55,20 @@ export function handlerParam(selector: HandlerParamSelector) { propertyKey ) + const handlerParamMeta: HandlerParamMeta = { + index, + selector + } + if (reflectMetadataIsAvailable) { + handlerParamMeta.paramType = Reflect.getMetadata( + 'design:paramtypes', + target, + propertyKey + )[index] + } + const meta: HandlerParamMetaList = [ - { - index, - selector, - paramType: Reflect.getMetadata( - 'design:paramtypes', - target, - propertyKey - )[index] - }, + handlerParamMeta, ...previousHandlerParamList ] From 7c91e8188f33197799c1de24c9f9a1c60e64b6d6 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Thu, 21 Mar 2019 15:49:12 +0900 Subject: [PATCH 06/20] Discard exceptions --- src/exceptions/BadGatewayException.ts | 8 -------- src/exceptions/BadRequestException.ts | 8 -------- src/exceptions/ConflictException.ts | 8 -------- src/exceptions/ForbiddenException.ts | 8 -------- src/exceptions/GatewayTimeoutException.ts | 8 -------- src/exceptions/GoneException.ts | 8 -------- src/exceptions/HttpException.ts | 10 ---------- src/exceptions/ImATeapotException.ts | 8 -------- .../InternalServerErrorException.ts | 8 -------- src/exceptions/MethodNotAllowedException.ts | 8 -------- src/exceptions/NotAcceptableException.ts | 8 -------- src/exceptions/NotFoundException.ts | 8 -------- src/exceptions/NotImplementedException.ts | 8 -------- src/exceptions/PayloadTooLargeException.ts | 8 -------- src/exceptions/RequestTimeoutException.ts | 8 -------- src/exceptions/ServiceUnavailableException.ts | 8 -------- src/exceptions/UnauthorizedException.ts | 8 -------- .../UnprocessableEntityException.ts | 8 -------- .../UnsupportedMediaTypeException.ts | 8 -------- src/exceptions/index.ts | 19 ------------------- 20 files changed, 173 deletions(-) delete mode 100644 src/exceptions/BadGatewayException.ts delete mode 100644 src/exceptions/BadRequestException.ts delete mode 100644 src/exceptions/ConflictException.ts delete mode 100644 src/exceptions/ForbiddenException.ts delete mode 100644 src/exceptions/GatewayTimeoutException.ts delete mode 100644 src/exceptions/GoneException.ts delete mode 100644 src/exceptions/HttpException.ts delete mode 100644 src/exceptions/ImATeapotException.ts delete mode 100644 src/exceptions/InternalServerErrorException.ts delete mode 100644 src/exceptions/MethodNotAllowedException.ts delete mode 100644 src/exceptions/NotAcceptableException.ts delete mode 100644 src/exceptions/NotFoundException.ts delete mode 100644 src/exceptions/NotImplementedException.ts delete mode 100644 src/exceptions/PayloadTooLargeException.ts delete mode 100644 src/exceptions/RequestTimeoutException.ts delete mode 100644 src/exceptions/ServiceUnavailableException.ts delete mode 100644 src/exceptions/UnauthorizedException.ts delete mode 100644 src/exceptions/UnprocessableEntityException.ts delete mode 100644 src/exceptions/UnsupportedMediaTypeException.ts delete mode 100644 src/exceptions/index.ts diff --git a/src/exceptions/BadGatewayException.ts b/src/exceptions/BadGatewayException.ts deleted file mode 100644 index 202e4a4..0000000 --- a/src/exceptions/BadGatewayException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class BadGatewayException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.BAD_GATEWAY) - } -} diff --git a/src/exceptions/BadRequestException.ts b/src/exceptions/BadRequestException.ts deleted file mode 100644 index 8d54af6..0000000 --- a/src/exceptions/BadRequestException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class BadRequestException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.BAD_REQUEST) - } -} diff --git a/src/exceptions/ConflictException.ts b/src/exceptions/ConflictException.ts deleted file mode 100644 index 7f311a7..0000000 --- a/src/exceptions/ConflictException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class ConflictException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.CONFLICT) - } -} diff --git a/src/exceptions/ForbiddenException.ts b/src/exceptions/ForbiddenException.ts deleted file mode 100644 index fc355f7..0000000 --- a/src/exceptions/ForbiddenException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class ForbiddenException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.FORBIDDEN) - } -} diff --git a/src/exceptions/GatewayTimeoutException.ts b/src/exceptions/GatewayTimeoutException.ts deleted file mode 100644 index 56625d8..0000000 --- a/src/exceptions/GatewayTimeoutException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class GatewayTimeoutException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.GATEWAY_TIMEOUT) - } -} diff --git a/src/exceptions/GoneException.ts b/src/exceptions/GoneException.ts deleted file mode 100644 index 5ca991c..0000000 --- a/src/exceptions/GoneException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class GoneException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.GONE) - } -} diff --git a/src/exceptions/HttpException.ts b/src/exceptions/HttpException.ts deleted file mode 100644 index 6756e1d..0000000 --- a/src/exceptions/HttpException.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { HttpStatus } from '../consts' - -export class HttpException extends Error { - constructor( - public readonly message: string, - public readonly status: number = HttpStatus.INTERNAL_SERVER_ERROR - ) { - super(message) - } -} diff --git a/src/exceptions/ImATeapotException.ts b/src/exceptions/ImATeapotException.ts deleted file mode 100644 index 9e4e5a9..0000000 --- a/src/exceptions/ImATeapotException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class ImATeapotException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.I_AM_A_TEAPOT) - } -} diff --git a/src/exceptions/InternalServerErrorException.ts b/src/exceptions/InternalServerErrorException.ts deleted file mode 100644 index f811391..0000000 --- a/src/exceptions/InternalServerErrorException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class InternalServerErrorException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.INTERNAL_SERVER_ERROR) - } -} diff --git a/src/exceptions/MethodNotAllowedException.ts b/src/exceptions/MethodNotAllowedException.ts deleted file mode 100644 index 995ad43..0000000 --- a/src/exceptions/MethodNotAllowedException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class MethodNotAllowedException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.METHOD_NOT_ALLOWED) - } -} diff --git a/src/exceptions/NotAcceptableException.ts b/src/exceptions/NotAcceptableException.ts deleted file mode 100644 index 6afb0bf..0000000 --- a/src/exceptions/NotAcceptableException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class NotAcceptableException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.NOT_ACCEPTABLE) - } -} diff --git a/src/exceptions/NotFoundException.ts b/src/exceptions/NotFoundException.ts deleted file mode 100644 index 33eda2d..0000000 --- a/src/exceptions/NotFoundException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class NotFoundException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.NOT_FOUND) - } -} diff --git a/src/exceptions/NotImplementedException.ts b/src/exceptions/NotImplementedException.ts deleted file mode 100644 index d336b57..0000000 --- a/src/exceptions/NotImplementedException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class NotImplementedException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.NOT_IMPLEMENTED) - } -} diff --git a/src/exceptions/PayloadTooLargeException.ts b/src/exceptions/PayloadTooLargeException.ts deleted file mode 100644 index cc3dbb8..0000000 --- a/src/exceptions/PayloadTooLargeException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class PayloadTooLargeException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.PAYLOAD_TOO_LARGE) - } -} diff --git a/src/exceptions/RequestTimeoutException.ts b/src/exceptions/RequestTimeoutException.ts deleted file mode 100644 index 2cca47a..0000000 --- a/src/exceptions/RequestTimeoutException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class RequestTimeoutException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.REQUEST_TIMEOUT) - } -} diff --git a/src/exceptions/ServiceUnavailableException.ts b/src/exceptions/ServiceUnavailableException.ts deleted file mode 100644 index 082359b..0000000 --- a/src/exceptions/ServiceUnavailableException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class ServiceUnavailableException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.SERVICE_UNAVAILABLE) - } -} diff --git a/src/exceptions/UnauthorizedException.ts b/src/exceptions/UnauthorizedException.ts deleted file mode 100644 index 1407879..0000000 --- a/src/exceptions/UnauthorizedException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class UnauthorizedException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.UNAUTHORIZED) - } -} diff --git a/src/exceptions/UnprocessableEntityException.ts b/src/exceptions/UnprocessableEntityException.ts deleted file mode 100644 index e19b2bb..0000000 --- a/src/exceptions/UnprocessableEntityException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class UnprocessableEntityException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.UNPROCESSABLE_ENTITY) - } -} diff --git a/src/exceptions/UnsupportedMediaTypeException.ts b/src/exceptions/UnsupportedMediaTypeException.ts deleted file mode 100644 index 8024747..0000000 --- a/src/exceptions/UnsupportedMediaTypeException.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { HttpException } from './HttpException' -import { HttpStatus } from '../consts' - -export class UnsupportedMediaTypeException extends HttpException { - constructor(public readonly message: string) { - super(message, HttpStatus.UNSUPPORTED_MEDIA_TYPE) - } -} diff --git a/src/exceptions/index.ts b/src/exceptions/index.ts deleted file mode 100644 index 4fea96a..0000000 --- a/src/exceptions/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -export * from './BadRequestException' -export * from './HttpException' -export * from './UnauthorizedException' -export * from './MethodNotAllowedException' -export * from './NotFoundException' -export * from './ForbiddenException' -export * from './NotAcceptableException' -export * from './RequestTimeoutException' -export * from './ConflictException' -export * from './GoneException' -export * from './PayloadTooLargeException' -export * from './UnsupportedMediaTypeException' -export * from './UnprocessableEntityException' -export * from './InternalServerErrorException' -export * from './NotImplementedException' -export * from './BadGatewayException' -export * from './ServiceUnavailableException' -export * from './GatewayTimeoutException' -export * from './ImATeapotException' From 08f17b855ae530a80acb9f7b626b716f1f2bc3d3 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Thu, 21 Mar 2019 16:16:57 +0900 Subject: [PATCH 07/20] Discard validation of reqBody --- package.json | 8 +- src/decorators/handlerParam/handlerParam.ts | 5 +- src/decorators/handlerParam/reqBody.ts | 13 +- src/examples/readme/index.ts | 11 +- .../handlerParamWithReflectMetadata.spec.ts | 64 +++++++++ .../decorators/handlerParam/reqBody.spec.ts | 130 ------------------ src/specs/setup.ts | 1 - 7 files changed, 72 insertions(+), 160 deletions(-) create mode 100644 src/specs/decorators/handlerParam/handlerParamWithReflectMetadata.spec.ts diff --git a/package.json b/package.json index d9ac2e5..59a1263 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "nodemon": "^1.18.9", "prettier": "^1.16.4", "pug": "^2.0.3", - "reflect-metadata": "^0.1.12", + "reflect-metadata": "^0.1.13", "rimraf": "^2.6.3", "supertest": "^3.3.0", "ts-jest": "^23.10.5", @@ -68,12 +68,6 @@ "typescript": "^3.2.2" }, "dependencies": { - "class-transformer": "^0.2.0", - "class-transformer-validator": "^0.6.0", - "class-validator": "^0.9.1", "express": "^4.16.4" - }, - "peerDependencies": { - "reflect-metadata": "^0.1.12" } } diff --git a/src/decorators/handlerParam/handlerParam.ts b/src/decorators/handlerParam/handlerParam.ts index 528917b..a6c528c 100644 --- a/src/decorators/handlerParam/handlerParam.ts +++ b/src/decorators/handlerParam/handlerParam.ts @@ -1,6 +1,7 @@ import express from 'express' -const reflectMetadataIsAvailable = typeof Reflect.getMetadata !== 'undefined' +const reflectMetadataIsAvailable = + typeof (Reflect as any).getMetadata !== 'undefined' const handlerParamMetaMap = new Map< any, @@ -60,7 +61,7 @@ export function handlerParam(selector: HandlerParamSelector) { selector } if (reflectMetadataIsAvailable) { - handlerParamMeta.paramType = Reflect.getMetadata( + handlerParamMeta.paramType = (Reflect as any).getMetadata( 'design:paramtypes', target, propertyKey diff --git a/src/decorators/handlerParam/reqBody.ts b/src/decorators/handlerParam/reqBody.ts index bd33698..9d13d2e 100644 --- a/src/decorators/handlerParam/reqBody.ts +++ b/src/decorators/handlerParam/reqBody.ts @@ -1,14 +1,7 @@ import { handlerParam } from './handlerParam' -import { transformAndValidate } from 'class-transformer-validator' -export function reqBody(validator?: any) { - const validatorIsGiven = validator != null - if (validatorIsGiven) { - return handlerParam(req => transformAndValidate(validator, req.body)) - } - return handlerParam((req, res, next, meta) => { - return meta.paramType !== Object - ? transformAndValidate(meta.paramType, req.body) - : req.body +export function reqBody() { + return handlerParam(req => { + return req.body }) } diff --git a/src/examples/readme/index.ts b/src/examples/readme/index.ts index 03b20fc..b0fa6f8 100644 --- a/src/examples/readme/index.ts +++ b/src/examples/readme/index.ts @@ -1,5 +1,4 @@ // tslint:disable:no-console -import 'reflect-metadata' // You have to import this to enable decorators. import tachijs, { ConfigSetter, controller, @@ -10,7 +9,6 @@ import tachijs, { inject, BaseController } from '../../' -import { IsString } from 'class-validator' import bodyParser from 'body-parser' enum ServiceTypes { @@ -46,12 +44,6 @@ class NotificationService { } } -// Prepare class validator -class NotifyRequestBody { - @IsString() - message: string -} - @controller('/') class HomeController extends BaseController { constructor( @@ -74,8 +66,7 @@ class HomeController extends BaseController { } @httpPost('/notify') - // Apply class validator so we can be sure body is valid - async notify(@reqBody(NotifyRequestBody) body: NotifyRequestBody) { + async notify(@reqBody() body: any) { await this.notifier.notifyMessage(body.message) return this.redirect('/') diff --git a/src/specs/decorators/handlerParam/handlerParamWithReflectMetadata.spec.ts b/src/specs/decorators/handlerParam/handlerParamWithReflectMetadata.spec.ts new file mode 100644 index 0000000..01324c5 --- /dev/null +++ b/src/specs/decorators/handlerParam/handlerParamWithReflectMetadata.spec.ts @@ -0,0 +1,64 @@ +import 'reflect-metadata' +import tachijs, { + ConfigSetter, + controller, + httpPost, + handlerParam +} from '../../../index' +import request from 'supertest' +import bodyParser from 'body-parser' + +class HomeIndexBodyDTO { + name: string + + constructor(body: unknown) { + this.name = (body as any).name != null ? (body as any).name : 'unknown' + } +} + +function validatedBody(callback: (meta: any) => void) { + return handlerParam((req, res, next, meta) => { + callback(meta) + return new HomeIndexBodyDTO(req.body) + }) +} + +describe('reqBody', () => { + it('selects req.body', async () => { + // Given + const before: ConfigSetter = expressApp => { + expressApp.use(bodyParser.json()) + } + const callback = jest.fn() + + @controller('/') + class HomeController { + @httpPost('/') + index(@validatedBody(callback) body: HomeIndexBodyDTO) { + return `Hello, ${body.name}` + } + } + const app = tachijs({ + before, + controllers: [HomeController] + }) + + // When + const response = await request(app) + .post('/') + .send({ + name: 'test' + }) + + // Then + expect(callback).toBeCalledWith({ + index: 0, + paramType: HomeIndexBodyDTO, + selector: expect.any(Function) + }) + expect(response).toMatchObject({ + status: 200, + text: 'Hello, test' + }) + }) +}) diff --git a/src/specs/decorators/handlerParam/reqBody.spec.ts b/src/specs/decorators/handlerParam/reqBody.spec.ts index 75699c1..762823c 100644 --- a/src/specs/decorators/handlerParam/reqBody.spec.ts +++ b/src/specs/decorators/handlerParam/reqBody.spec.ts @@ -6,8 +6,6 @@ import tachijs, { } from '../../../index' import request from 'supertest' import bodyParser from 'body-parser' -import { ErrorRequestHandler } from 'express' -import { IsString } from 'class-validator' describe('reqBody', () => { it('selects req.body', async () => { @@ -41,132 +39,4 @@ describe('reqBody', () => { text: 'Hello, test' }) }) - - it('selects, validates and transforms req.body(validator from param types metadata)', async () => { - // Given - const before: ConfigSetter = expressApp => { - expressApp.use(bodyParser.json()) - } - class UserDTO { - @IsString() - name: string - } - @controller('/') - class HomeController { - @httpPost('/') - index(@reqBody() user: UserDTO) { - expect(user).toBeInstanceOf(UserDTO) - return `Hello, ${user.name}` - } - } - const app = tachijs({ - before, - controllers: [HomeController] - }) - - // When - const response = await request(app) - .post('/') - .send({ - name: 'test' - }) - - // Then - expect(response).toMatchObject({ - status: 200, - text: 'Hello, test' - }) - }) - - it('selects, validates and transforms req.body(validator from decorator argument)', async () => { - // Given - const before: ConfigSetter = expressApp => { - expressApp.use(bodyParser.json()) - } - class UserDTO { - @IsString() - name: string - } - @controller('/') - class HomeController { - @httpPost('/') - index(@reqBody(UserDTO) user: UserDTO) { - expect(user).toBeInstanceOf(UserDTO) - return `Hello, ${user.name}` - } - } - const app = tachijs({ - before, - controllers: [HomeController] - }) - - // When - const response = await request(app) - .post('/') - .send({ - name: 'test' - }) - - // Then - expect(response).toMatchObject({ - status: 200, - text: 'Hello, test' - }) - }) - - it('throws when req.body is invalid', async () => { - // Given - const before: ConfigSetter = expressApp => { - expressApp.use(bodyParser.json()) - } - const after: ConfigSetter = expressApp => { - expressApp.use(((error, req, res, next) => { - if (Array.isArray(error)) { - return res.status(422).json({ - message: error.toString().trim(), - errors: error - }) - } - return next(error) - }) as ErrorRequestHandler) - } - class UserDTO { - @IsString() - name: string - } - @controller('/') - class HomeController { - @httpPost('/') - index(@reqBody() user: UserDTO) { - return `Hello, ${user.name}` - } - } - const app = tachijs({ - before, - after, - controllers: [HomeController] - }) - - // When - const response = await request(app).post('/') - - // Then - expect(response).toMatchObject({ - status: 422, - text: JSON.stringify({ - message: - 'An instance of UserDTO has failed the validation:\n - property name has failed the following constraints: isString', - errors: [ - { - target: {}, - property: 'name', - children: [], - constraints: { - isString: 'name must be a string' - } - } - ] - }) - }) - }) }) diff --git a/src/specs/setup.ts b/src/specs/setup.ts index 3f425aa..e69de29 100644 --- a/src/specs/setup.ts +++ b/src/specs/setup.ts @@ -1 +0,0 @@ -import 'reflect-metadata' From f66c1442449b3c8c0f609acb27499ccaefe910a4 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Thu, 21 Mar 2019 16:45:50 +0900 Subject: [PATCH 08/20] Handle sent response --- src/specs/decorators/controller.spec.ts | 33 +++++++++++++++++++++++-- src/tachijs.ts | 4 ++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/specs/decorators/controller.spec.ts b/src/specs/decorators/controller.spec.ts index 96283ef..3d6404b 100644 --- a/src/specs/decorators/controller.spec.ts +++ b/src/specs/decorators/controller.spec.ts @@ -1,7 +1,7 @@ import tachijs, { ConfigSetter, controller, httpGet } from '../../index' import request from 'supertest' -import { ErrorRequestHandler, RequestHandler } from 'express' -import { reqParams } from '../../decorators' +import { ErrorRequestHandler, RequestHandler, Response } from 'express' +import { reqParams, handlerParam } from '../../decorators' describe('controller', () => { it('sets path to router', async () => { @@ -143,4 +143,33 @@ describe('controller', () => { text: 'Hello, test' }) }) + + it('does not send data if response is already sent', async () => { + // Given + function injectRes() { + return handlerParam((req, res) => res) + } + @controller('/:name', [], { + mergeParams: true + }) + class HomeController { + @httpGet('/hello') + index(@injectRes() res: Response) { + res.send('Hello, test') + return 'Other thing' + } + } + const app = tachijs({ + controllers: [HomeController] + }) + + // When + const response = await request(app).get('/test/hello') + + // Then + expect(response).toMatchObject({ + status: 200, + text: 'Hello, test' + }) + }) }) diff --git a/src/tachijs.ts b/src/tachijs.ts index 8316e20..8af5198 100644 --- a/src/tachijs.ts +++ b/src/tachijs.ts @@ -121,7 +121,9 @@ class TachiJSApp { await result.execute(req, res, next) return } - res.send(result) + if (!res.finished) { + res.send(result) + } return } catch (error) { next(error) From 28b0e5c3704d1b75afad7ebb085c607a3a3828d9 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Thu, 21 Mar 2019 16:49:01 +0900 Subject: [PATCH 09/20] Update readme.md --- readme.md | 85 +++++++++++++++++++------------------------------------ 1 file changed, 29 insertions(+), 56 deletions(-) diff --git a/readme.md b/readme.md index 3c715e8..1637355 100644 --- a/readme.md +++ b/readme.md @@ -32,17 +32,16 @@ Luckily, TachiJS tackles those problems. If you have other ideas, please create ### Install tachijs ```sh -npm i tachijs reflect-metadata +npm i tachijs ``` -Add two compiler options, `experimentalDecorators` and `emitDecoratorMetadata`, to `tsconfig.json`. +Enable `experimentalDecorators` of `compilerOptions` to `tsconfig.json`. ```json { "compilerOptions": { ... "experimentalDecorators": true, - "emitDecoratorMetadata": true, ... } } @@ -261,43 +260,7 @@ We also provide `reqHeaders`, `reqCookies` and `reqSession` for `req.headers`, ` #### Body validation -`@reqBody` supports validation via `class-validator`. - -Please install `class-validator` package first. - -```sh -npm install class-validator -``` - -```ts -import { IsString } from 'class-validator' - -class PostDTO { - @IsString() - title: string - - @IsString() - content: string -} - - -@controller('/posts') -class PostController() { - @httpPost('/') - // Tachijs can access `PostDTO` via reflect-metadata. - async create(@reqBody() body: PostDTO) { - // `body` is already validated and transformed into an instance of `PostDTO`. - // So we don't need any extra validation. - const post = await Post.create({ - ...body - }) - - return { - post - } - } -} -``` +It has been deprecated from v1. We'll provide this feature as a separated module. #### Custom parameter decorators! @@ -355,19 +318,20 @@ export function cookieSetter() { } ``` -##### `design:paramtype` +##### `meta.paramType` -Moreover, tachijs exposes metadata of parameters to forth argument. So you can make your custom validator for query with `class-transformer-validator` like below. (`req.body` is also using this.) +If you are using `reflect-metadata`, tachijs exposes `paramType` to the forth argument, `meta`, of `handlerParam` from `design:paramtypes`. With this feature, you could access argument types on runtime. The below example is validating and transforming query with DTO class by class-validator. ```ts +import 'reflect-metadata' import { controller, httpGet, handlerParam } from 'tachijs' import { IsString } from 'class-validator' import { transformAndValidate } from 'class-transformer-validator' function validatedQuery() { return handlerParam((req, res, next, meta) => { - // meta.paramType is from `design:paramtypes`. - // It is `Object` if the param type is unknown or any. + // Now tachijs will expose `paramType`. + // If the param type is unknown or any, paramType will become `Object`. return meta.paramType !== Object ? transformAndValidate(meta.paramType, req.query) : req.query @@ -375,7 +339,7 @@ function validatedQuery() { } // Validator class -class SearchQuery { +class SearchQueryDTO { @IsString() title: string } @@ -384,10 +348,10 @@ class SearchQuery { class PostController { @httpGet('/search') // Provide the validator class to param type. - // tachijs can access it via `reflect-metadata`. - search(@validatedQuery() query: SearchQuery) { + search(@validatedQuery() query: SearchQueryDTO) { // Now `query` is type-safe - // because it has been validated and transformed into an instance of SearchQuery. + // because it has been validated and transformed into an instance of SearchQueryDTO. + // If validation errors happen, tachijs will pass the error into `next` so you can handle it easily by your error request handler. const { title } = query return { @@ -397,6 +361,20 @@ class PostController { } ``` +To enable it, you have to install `reflect-metadata` and to apply `emitDecoratorMetadata` of `compilerOptions` to `tsconfig.json`. + +```sh +npm i reflect-metadata +``` + +```json +{ + "compilerOptions": { + "emitDecoratorMetadata": true + } +} +``` + To know more, see `@handlerParam` api documentation below. ### Redirection, Rendering via pug and others... @@ -513,8 +491,6 @@ class HomeController { } ``` -> `#httpContext`, `#inject` and `#injector` will be deprecated from v1.0.0. Please use `#context` - #### Customize result If you want to have customized result behavior, you can do it with `BaseResult`. @@ -854,7 +830,7 @@ export type HandlerParamSelector = ( interface HandlerParamMeta { index: number selector: HandlerParamSelector - paramType: any + paramType?: any } ``` @@ -862,20 +838,17 @@ interface HandlerParamMeta { - `selector` Its selector. - `paramType` metadata from `design:paramtypes`. -#### `@reqBody(validator?: any)` +#### `@reqBody()` Inject `req.body`. -- `validator` Optional. A class with decorators of `class-validator`. tachijs will validate `req.body` with it and transform `req.body` into the validator class. If `validator` is not given but the parameter has a class validator as its param type, tachijs will use it via `reflect-metadata`. - ```ts import { controller, httpPost, reqBody } from 'tachijs' @controller('/post') class PostController { @httpPost('/') - // Identically same to `create(@reqBody(PostDTO) post: PostDTO)` - create(@reqBody() post: PostDTO) { + create(@reqBody() post: any) { ... } } From 3100866d86fd92bb14b47e320fc706dbc8a0f48f Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Thu, 21 Mar 2019 18:07:02 +0900 Subject: [PATCH 10/20] Reverse meta order of handlerParam --- src/decorators/handlerParam/handlerParam.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/decorators/handlerParam/handlerParam.ts b/src/decorators/handlerParam/handlerParam.ts index a6c528c..461cf4c 100644 --- a/src/decorators/handlerParam/handlerParam.ts +++ b/src/decorators/handlerParam/handlerParam.ts @@ -69,8 +69,8 @@ export function handlerParam(selector: HandlerParamSelector) { } const meta: HandlerParamMetaList = [ - handlerParamMeta, - ...previousHandlerParamList + ...previousHandlerParamList, + handlerParamMeta ] setHandlerParamMetaList(target.constructor, meta, propertyKey) From 0431193194a92d1879ce25dca863ceb5c979a96d Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Sat, 23 Mar 2019 18:35:34 +0900 Subject: [PATCH 11/20] Accept after middleware for controller and httpMethod decorator --- src/decorators/controller.ts | 17 +++- src/decorators/httpMethod.ts | 59 ++++++++++--- src/specs/decorators/controller.spec.ts | 41 ++++++++- src/specs/decorators/httpMethod.spec.ts | 111 +++++++++++++++++++++++- src/tachijs.ts | 27 +++--- 5 files changed, 226 insertions(+), 29 deletions(-) diff --git a/src/decorators/controller.ts b/src/decorators/controller.ts index 5f87517..665a59f 100644 --- a/src/decorators/controller.ts +++ b/src/decorators/controller.ts @@ -1,10 +1,16 @@ import { RequestHandler, RouterOptions } from 'express' +import { RequestHandlerParams } from 'express-serve-static-core' const controllerMetaMap = new Map() +interface Middleware { + before?: RequestHandlerParams[] + after?: RequestHandlerParams[] +} + export interface ControllerMeta { path: string - middlewares: RequestHandler[] + middleware: Middleware routerOptions: RouterOptions } @@ -23,13 +29,18 @@ export function setControllerMeta( export function controller( path: string, - middlewares: RequestHandler[] = [], + middleware: RequestHandler[] | Middleware = [], routerOptions: RouterOptions = {} ) { + if (Array.isArray(middleware)) { + middleware = { + before: middleware + } + } return function controllerDecorator(target: any) { const meta: ControllerMeta = { path, - middlewares, + middleware: middleware as Middleware, routerOptions } diff --git a/src/decorators/httpMethod.ts b/src/decorators/httpMethod.ts index 827f3d3..d8cfcd9 100644 --- a/src/decorators/httpMethod.ts +++ b/src/decorators/httpMethod.ts @@ -1,12 +1,17 @@ -import { RequestHandler } from 'express' +import { RequestHandlerParams } from 'express-serve-static-core' const httpMethodMetaMap = new Map() +interface MiddlewareParams { + before?: RequestHandlerParams[] + after?: RequestHandlerParams[] +} + export interface HttpMethodMeta { method: string path: string propertyKey: string - middlewares: RequestHandler[] + middleware: MiddlewareParams } export type HttpMethodMetaList = HttpMethodMeta[] @@ -27,8 +32,14 @@ export function setHttpMethodMetaList( export function httpMethod( method: string, path: string, - middlewares: RequestHandler[] = [] + middleware: RequestHandlerParams[] | MiddlewareParams = {} ) { + if (Array.isArray(middleware)) { + middleware = { + before: middleware + } + } + return function httpMethodDecorator( target: any, propertyKey: string, @@ -42,7 +53,7 @@ export function httpMethod( method, path, propertyKey, - middlewares + middleware: middleware as MiddlewareParams } ] @@ -50,34 +61,58 @@ export function httpMethod( } } -export function httpGet(path: string, middlewares?: RequestHandler[]) { +export function httpGet( + path: string, + middlewares?: RequestHandlerParams[] | MiddlewareParams +) { return httpMethod('get', path, middlewares) } -export function httpPost(path: string, middlewares?: RequestHandler[]) { +export function httpPost( + path: string, + middlewares?: RequestHandlerParams[] | MiddlewareParams +) { return httpMethod('post', path, middlewares) } -export function httpPut(path: string, middlewares?: RequestHandler[]) { +export function httpPut( + path: string, + middlewares?: RequestHandlerParams[] | MiddlewareParams +) { return httpMethod('put', path, middlewares) } -export function httpPatch(path: string, middlewares?: RequestHandler[]) { +export function httpPatch( + path: string, + middlewares?: RequestHandlerParams[] | MiddlewareParams +) { return httpMethod('patch', path, middlewares) } -export function httpDelete(path: string, middlewares?: RequestHandler[]) { +export function httpDelete( + path: string, + middlewares?: RequestHandlerParams[] | MiddlewareParams +) { return httpMethod('delete', path, middlewares) } -export function httpOptions(path: string, middlewares?: RequestHandler[]) { +export function httpOptions( + path: string, + middlewares?: RequestHandlerParams[] | MiddlewareParams +) { return httpMethod('options', path, middlewares) } -export function httpHead(path: string, middlewares?: RequestHandler[]) { +export function httpHead( + path: string, + middlewares?: RequestHandlerParams[] | MiddlewareParams +) { return httpMethod('head', path, middlewares) } -export function httpAll(path: string, middlewares?: RequestHandler[]) { +export function httpAll( + path: string, + middlewares?: RequestHandlerParams[] | MiddlewareParams +) { return httpMethod('all', path, middlewares) } diff --git a/src/specs/decorators/controller.spec.ts b/src/specs/decorators/controller.spec.ts index 3d6404b..d2a6408 100644 --- a/src/specs/decorators/controller.spec.ts +++ b/src/specs/decorators/controller.spec.ts @@ -57,7 +57,7 @@ describe('controller', () => { }) }) - it('sets middlewares', async () => { + it('sets before middleware with array', async () => { // Given const spy = jest.fn() const middleware: RequestHandler = (req, res, next) => { @@ -87,6 +87,45 @@ describe('controller', () => { expect(spy).toBeCalled() }) + it('sets middleware', async () => { + // Given + const beforeSpy = jest.fn() + const afterSpy = jest.fn() + const beforeMiddleware: RequestHandler = (req, res, next) => { + beforeSpy() + next() + } + const afterMiddleware: ErrorRequestHandler = (error, req, res, next) => { + afterSpy() + res.status(500).send('Handled') + } + + @controller('/test', { + before: [beforeMiddleware], + after: [afterMiddleware] + }) + class HomeController { + @httpGet('/') + index() { + throw new Error() + } + } + const app = tachijs({ + controllers: [HomeController] + }) + + // When + const response = await request(app).get('/test') + + // Then + expect(response).toMatchObject({ + status: 500, + text: 'Handled' + }) + expect(beforeSpy).toBeCalled() + expect(afterSpy).toBeCalled() + }) + it('sets middlewares individually', async () => { // Given const spy = jest.fn() diff --git a/src/specs/decorators/httpMethod.spec.ts b/src/specs/decorators/httpMethod.spec.ts index 97a081d..fe1247e 100644 --- a/src/specs/decorators/httpMethod.spec.ts +++ b/src/specs/decorators/httpMethod.spec.ts @@ -11,7 +11,7 @@ import tachijs, { httpAll } from '../../index' import request from 'supertest' -import { RequestHandler } from 'express' +import { RequestHandler, ErrorRequestHandler } from 'express' describe('httpMethod', () => { it(`sets get method route`, async () => { @@ -219,7 +219,47 @@ describe('httpMethod', () => { } }) - it('accepts middlewares', async () => { + it('sets middleware', async () => { + // Given + const beforeSpy = jest.fn() + const afterSpy = jest.fn() + const beforeMiddleware: RequestHandler = (req, res, next) => { + beforeSpy() + next() + } + const afterMiddleware: ErrorRequestHandler = (error, req, res, next) => { + afterSpy() + res.status(500).send('Handled') + } + + // When + @controller('/') + class HomeController { + @httpMethod('get', '/', { + before: [beforeMiddleware], + after: [afterMiddleware] + }) + index() { + throw new Error() + } + } + const app = tachijs({ + controllers: [HomeController] + }) + + // When + const response = await request(app).get('/') + + // Then + expect(response).toMatchObject({ + status: 500, + text: 'Handled' + }) + expect(beforeSpy).toBeCalled() + expect(afterSpy).toBeCalled() + }) + + it('sets before middleware if middleware is list of handlers', async () => { // Given const spy = jest.fn() const middleware: RequestHandler = (req, res, next) => { @@ -250,6 +290,73 @@ describe('httpMethod', () => { expect(spy).toBeCalled() }) + it('sets controller middleware and method middleware orderly', async () => { + // Given + const beforeControllerMiddlewareSpy = jest.fn() + const afterControllerMiddlewareSpy = jest.fn() + const beforeMethodMiddlewareSpy = jest.fn() + const afterMethodMiddlewareSpy = jest.fn() + let count = 0 + + const beforeControllerMiddleware: RequestHandler = (req, res, next) => { + beforeControllerMiddlewareSpy(++count) + next() + } + const afterControllerMiddleware: ErrorRequestHandler = ( + error, + req, + res, + next + ) => { + afterControllerMiddlewareSpy(++count) + res.status(500).send('Handled') + } + const beforeMethodMiddleware: RequestHandler = (req, res, next) => { + beforeMethodMiddlewareSpy(++count) + next() + } + const afterMethodMiddleware: ErrorRequestHandler = ( + error, + req, + res, + next + ) => { + afterMethodMiddlewareSpy(++count) + next(error) + } + + // When + @controller('/', { + before: [beforeControllerMiddleware], + after: [afterControllerMiddleware] + }) + class HomeController { + @httpMethod('get', '/', { + before: [beforeMethodMiddleware], + after: [afterMethodMiddleware] + }) + index() { + throw new Error() + } + } + const app = tachijs({ + controllers: [HomeController] + }) + + // When + const response = await request(app).get('/') + + // Then + expect(response).toMatchObject({ + status: 500, + text: 'Handled' + }) + expect(beforeControllerMiddlewareSpy).toBeCalledWith(1) + expect(beforeMethodMiddlewareSpy).toBeCalledWith(2) + expect(afterMethodMiddlewareSpy).toBeCalledWith(3) + expect(afterControllerMiddlewareSpy).toBeCalledWith(4) + }) + it('registers routes from top to bottom', async () => { // Given @controller('/') diff --git a/src/tachijs.ts b/src/tachijs.ts index 8af5198..c208734 100644 --- a/src/tachijs.ts +++ b/src/tachijs.ts @@ -9,6 +9,7 @@ import { import { BaseController } from './BaseController' import { BaseResult } from './results' import { Injector } from './Injector' +import { RequestHandlerParams } from 'express-serve-static-core' export type ConfigSetter = (app: express.Application) => void @@ -138,35 +139,39 @@ class TachiJSApp { methodMeta: HttpMethodMeta, handler: express.RequestHandler ) { - const middlewares = [ - ...controllerMeta.middlewares, - ...methodMeta.middlewares + const before: RequestHandlerParams[] = [ + ...(controllerMeta.middleware.before || []), + ...(methodMeta.middleware.before || []) + ] + const after: RequestHandlerParams[] = [ + ...(methodMeta.middleware.after || []), + ...(controllerMeta.middleware.after || []) ] switch (methodMeta.method) { case 'get': - router.get(methodMeta.path, middlewares, handler) + router.get(methodMeta.path, ...before, handler, ...after) break case 'post': - router.post(methodMeta.path, middlewares, handler) + router.post(methodMeta.path, ...before, handler, ...after) break case 'put': - router.put(methodMeta.path, middlewares, handler) + router.put(methodMeta.path, ...before, handler, ...after) break case 'patch': - router.patch(methodMeta.path, middlewares, handler) + router.patch(methodMeta.path, ...before, handler, ...after) break case 'delete': - router.delete(methodMeta.path, middlewares, handler) + router.delete(methodMeta.path, ...before, handler, ...after) break case 'options': - router.options(methodMeta.path, middlewares, handler) + router.options(methodMeta.path, ...before, handler, ...after) break case 'head': - router.head(methodMeta.path, middlewares, handler) + router.head(methodMeta.path, ...before, handler, ...after) break case 'all': - router.all(methodMeta.path, middlewares, handler) + router.all(methodMeta.path, ...before, handler, ...after) break default: throw new Error(`"${methodMeta.method}" is not a valid method.`) From fe5bc65706585d0065aa9a9749e64ad4b8e9847f Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Sat, 23 Mar 2019 18:41:22 +0900 Subject: [PATCH 12/20] Update document --- readme.md | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/readme.md b/readme.md index 1637355..f7a2f15 100644 --- a/readme.md +++ b/readme.md @@ -76,9 +76,9 @@ Now you can access [http://localhost:8000/](http://localhost:8000/). For other http methods, tachijs provides `@httpPost`, `@httpPut`, `@httpPatch`, `@httpDelete`, `@httpOptions`, `@httpHead` and `@httpAll`. -### Configuring express app(Middlewares) +### Configuring express app(Middleware) -There are lots of ways to implement express middlewares. +There are lots of ways to implement express middleware. #### Use `before` and `after` options @@ -145,9 +145,9 @@ app.use(errorHandler) app.listen(8000) ``` -#### Apply middlewares to controllers and methods +#### Apply middleware to controllers and methods -Sometimes, you might want to apply middlewares to several methods only. +Sometimes, you might want to apply middleware to several methods only. ```ts import { controller, httpGet, ForbiddenException } from 'tachijs' @@ -780,38 +780,49 @@ type ConfigSetter = (app: express.Application) => void ``` - `app` Optional. If you provide this option, tachijs will use it rather than creating new one. -- `before` Optional. You can configure express app before registering controllers for applying middlewares. +- `before` Optional. You can configure express app before registering controllers for applying middleware. - `after` Optional. You can configure express app before registering controllers for error handling. - `controllers` Optional. Array of controller classes. - `container` Optional. A place for registered services. If you want to use DI, you have to register services to here first. -### `@controller(path: string, middlewares: RequestHandler[] = [], routerOptions: RouterOptions = {})` +### `@controller(path: string, middleware: MiddlewareParams | RequestHandler[] = {}, routerOptions: RouterOptions = {})` It marks class as a controller. - `path` Target path. -- `middlewares` Optional. Array of middlewares. +- `middleware` Optional. `MiddlewareParams` or Array of middleware. + If it provided as array, tachijs will set the middleware before controller method. - `routerOptions` Optional. Express router options. -### `@httpMethod(method: string, path: string, middlewares: RequestHandler[] = [])` +#### `MiddlewareParams` + +```ts +interface MiddlewareParams { + before?: RequestHandler[] + after?: RequestHandler[] +} +``` + +### `@httpMethod(method: string, path: string, middleware: MiddlewareParams | RequestHandler[] = {})` It marks method as a request handler. - `method` Target http methods, `'get'`, `'post'`, `'put'`, `'patch'`, `'delete'`, `'options'`, `'head'` or `'all'` are available. (`'all'` means any methods.) - `path` Target path. -- `middlewares` Optional. Array of middlewares. +- `middleware` Optional. `MiddlewareParams` or Array of middleware. + If it provided as array, tachijs will set the middleware before controller method. tachijs also provides shortcuts for `@httpMethod`. -- `@httpGet(path: string, middlewares: RequestHandler[] = [])` -- `@httpPost(path: string, middlewares: RequestHandler[] = [])` -- `@httpPut(path: string, middlewares: RequestHandler[] = [])` -- `@httpPatch(path: string, middlewares: RequestHandler[] = [])` -- `@httpDelete(path: string, middlewares: RequestHandler[] = [])` -- `@httpOptions(path: string, middlewares: RequestHandler[] = [])` -- `@httpHead(path: string, middlewares: RequestHandler[] = [])` -- `@httpAll(path: string, middlewares: RequestHandler[] = [])` +- `@httpGet(path: string, middleware: MiddlewareParams | RequestHandler[] = {})` +- `@httpPost(path: string, middleware: MiddlewareParams | RequestHandler[] = {})` +- `@httpPut(path: string, middleware: MiddlewareParams | RequestHandler[] = {})` +- `@httpPatch(path: string, middleware: MiddlewareParams | RequestHandler[] = {})` +- `@httpDelete(path: string, middleware: MiddlewareParams | RequestHandler[] = {})` +- `@httpOptions(path: string, middleware: MiddlewareParams | RequestHandler[] = {})` +- `@httpHead(path: string, middleware: MiddlewareParams | RequestHandler[] = {})` +- `@httpAll(path: string, middleware: MiddlewareParams | RequestHandler[] = {})` ### `@handlerParam(selector: HandlerParamSelector)` From b2743e53287bc4a549a02e85167ed3ae272f30e6 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Sat, 23 Mar 2019 18:43:41 +0900 Subject: [PATCH 13/20] 1.0.0-0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 59a1263..241ec75 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tachijs", - "version": "0.15.1", + "version": "1.0.0-0", "description": "Highly testable dead simple web server written in Typescript", "main": "dist", "types": "types", From e2ca00728f3016cd6228805e3c5e416069efe666 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Mon, 25 Mar 2019 13:31:08 +0900 Subject: [PATCH 14/20] Move type definitions to dist --- .gitignore | 1 - package.json | 11 ++--------- tsconfig.json | 1 - 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index f34d5be..7f2a185 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ /dist -/types package-lock.json # Logs diff --git a/package.json b/package.json index 241ec75..4f09598 100644 --- a/package.json +++ b/package.json @@ -3,21 +3,14 @@ "version": "1.0.0-0", "description": "Highly testable dead simple web server written in Typescript", "main": "dist", - "types": "types", "files": [ "dist/**/*", "!dist/examples/**/*", - "!dist/specs/**/*", - "types/**/*", - "!types/examples/**/*", - "!types/specs/**/*", - "src/**/*", - "!src/examples/**/*", - "!src/specs/**/*" + "!dist/specs/**/*" ], "scripts": { "dev": "nodemon", - "build": "rimraf dist types && tsc", + "build": "rimraf dist && tsc", "format": "prettier --write 'src/**/*.ts'", "lint": "npm run lint:prettier && npm run lint:tslint", "lint:prettier": "prettier --check 'src/**/*.ts'", diff --git a/tsconfig.json b/tsconfig.json index da644b5..426fce9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -26,7 +26,6 @@ "esModuleInterop": true, "emitDecoratorMetadata": true, "declaration": true, - "declarationDir": "types", "declarationMap": true } } From 7bf81ca6a03b2438a75e2f7161c06e936688482f Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Mon, 25 Mar 2019 13:31:16 +0900 Subject: [PATCH 15/20] 1.0.0-1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4f09598..0ea15e2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tachijs", - "version": "1.0.0-0", + "version": "1.0.0-1", "description": "Highly testable dead simple web server written in Typescript", "main": "dist", "files": [ From 0449dd377c789628e0e10c73e1ddb7b9501d6bc1 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Mon, 25 Mar 2019 13:46:03 +0900 Subject: [PATCH 16/20] Fix test coverage by replacing default value for controller middleware --- src/decorators/controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/decorators/controller.ts b/src/decorators/controller.ts index 665a59f..328fb78 100644 --- a/src/decorators/controller.ts +++ b/src/decorators/controller.ts @@ -29,7 +29,7 @@ export function setControllerMeta( export function controller( path: string, - middleware: RequestHandler[] | Middleware = [], + middleware: RequestHandler[] | Middleware = {}, routerOptions: RouterOptions = {} ) { if (Array.isArray(middleware)) { From 16476e04543a1fe89417a72094ccfd82d035ae81 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Mon, 8 Jul 2019 01:16:47 +0900 Subject: [PATCH 17/20] Discard headers --- src/results/EndResult.ts | 7 +--- src/results/JSONResult.ts | 10 +----- src/results/RedirectResult.ts | 7 +--- src/results/RenderResult.ts | 7 +--- src/results/SendFileResult.ts | 7 +--- src/results/SendResult.ts | 10 +----- src/results/SendStatusResult.ts | 9 +---- src/specs/results/EndResult.spec.ts | 26 --------------- src/specs/results/JSONResult.spec.ts | 39 ---------------------- src/specs/results/RedirectResult.spec.ts | 26 --------------- src/specs/results/RenderResult.spec.ts | 29 ---------------- src/specs/results/SendFileResult.spec.ts | 32 ------------------ src/specs/results/SendResult.spec.ts | 28 ---------------- src/specs/results/SendStatusResult.spec.ts | 26 --------------- 14 files changed, 7 insertions(+), 256 deletions(-) diff --git a/src/results/EndResult.ts b/src/results/EndResult.ts index 0eb87c0..aec0a94 100644 --- a/src/results/EndResult.ts +++ b/src/results/EndResult.ts @@ -1,13 +1,11 @@ import express from 'express' import { BaseResult } from './BaseResult' -import { OutgoingHttpHeaders } from 'http' export class EndResult extends BaseResult { constructor( public readonly data: D, public readonly encoding?: string, - public readonly status: number = 200, - public readonly headers?: OutgoingHttpHeaders + public readonly status: number = 200 ) { super() } @@ -17,9 +15,6 @@ export class EndResult extends BaseResult { res: express.Response, next: express.NextFunction ) { - if (this.headers != null) { - res.set(this.headers) - } if (this.encoding != null) { return res.status(this.status).end(this.data, this.encoding) } diff --git a/src/results/JSONResult.ts b/src/results/JSONResult.ts index e803af6..cb0ab23 100644 --- a/src/results/JSONResult.ts +++ b/src/results/JSONResult.ts @@ -1,13 +1,8 @@ import express from 'express' import { BaseResult } from './BaseResult' -import { OutgoingHttpHeaders } from 'http' export class JSONResult extends BaseResult { - constructor( - public readonly data: D, - public readonly status: number = 200, - public readonly headers?: OutgoingHttpHeaders - ) { + constructor(public readonly data: D, public readonly status: number = 200) { super() } @@ -16,9 +11,6 @@ export class JSONResult extends BaseResult { res: express.Response, next: express.NextFunction ) { - if (this.headers != null) { - res.set(this.headers) - } return res.status(this.status).json(this.data) } } diff --git a/src/results/RedirectResult.ts b/src/results/RedirectResult.ts index 2e593e4..ad56a9d 100644 --- a/src/results/RedirectResult.ts +++ b/src/results/RedirectResult.ts @@ -1,12 +1,10 @@ import express from 'express' import { BaseResult } from './BaseResult' -import { OutgoingHttpHeaders } from 'http' export class RedirectResult extends BaseResult { constructor( public readonly location: string, - public readonly status?: number, - public readonly headers?: OutgoingHttpHeaders + public readonly status?: number ) { super() } @@ -16,9 +14,6 @@ export class RedirectResult extends BaseResult { res: express.Response, next: express.NextFunction ) { - if (this.headers != null) { - res.set(this.headers) - } if (this.status != null) return res.redirect(this.status, this.location) return res.redirect(this.location) } diff --git a/src/results/RenderResult.ts b/src/results/RenderResult.ts index 350b60a..d670c82 100644 --- a/src/results/RenderResult.ts +++ b/src/results/RenderResult.ts @@ -1,6 +1,5 @@ import express from 'express' import { BaseResult } from './BaseResult' -import { OutgoingHttpHeaders } from 'http' export type RenderResultCallback = ( error: Error | null, @@ -15,8 +14,7 @@ export class RenderResult extends BaseResult { public readonly view: string, public readonly locals?: L, public readonly callback?: RenderResultCallback, - public readonly status: number = 200, - public readonly headers?: OutgoingHttpHeaders + public readonly status: number = 200 ) { super() } @@ -26,9 +24,6 @@ export class RenderResult extends BaseResult { res: express.Response, next: express.NextFunction ) { - if (this.headers != null) { - res.set(this.headers) - } if (this.callback != null) { const callback = this.callback return res diff --git a/src/results/SendFileResult.ts b/src/results/SendFileResult.ts index 0ee74a2..7c40423 100644 --- a/src/results/SendFileResult.ts +++ b/src/results/SendFileResult.ts @@ -1,6 +1,5 @@ import express from 'express' import { BaseResult } from './BaseResult' -import { OutgoingHttpHeaders } from 'http' export type SendFileResultCallback = ( error: Error | null, @@ -14,8 +13,7 @@ export class SendFileResult extends BaseResult { public readonly filePath: string, public readonly options: any = {}, public readonly callback?: SendFileResultCallback, - public readonly status: number = 200, - public readonly headers?: OutgoingHttpHeaders + public readonly status: number = 200 ) { super() } @@ -25,9 +23,6 @@ export class SendFileResult extends BaseResult { res: express.Response, next: express.NextFunction ) { - if (this.headers != null) { - res.set(this.headers) - } if (this.callback != null) { const callback = this.callback return res diff --git a/src/results/SendResult.ts b/src/results/SendResult.ts index 11ee246..4afeb00 100644 --- a/src/results/SendResult.ts +++ b/src/results/SendResult.ts @@ -1,13 +1,8 @@ import express from 'express' import { BaseResult } from './BaseResult' -import { OutgoingHttpHeaders } from 'http' export class SendResult extends BaseResult { - constructor( - public readonly data: D, - public readonly status: number = 200, - public readonly headers?: OutgoingHttpHeaders - ) { + constructor(public readonly data: D, public readonly status: number = 200) { super() } @@ -16,9 +11,6 @@ export class SendResult extends BaseResult { res: express.Response, next: express.NextFunction ) { - if (this.headers != null) { - res.set(this.headers) - } return res.status(this.status).send(this.data) } } diff --git a/src/results/SendStatusResult.ts b/src/results/SendStatusResult.ts index 9c0b0d3..20f693d 100644 --- a/src/results/SendStatusResult.ts +++ b/src/results/SendStatusResult.ts @@ -1,12 +1,8 @@ import express from 'express' import { BaseResult } from './BaseResult' -import { OutgoingHttpHeaders } from 'http' export class SendStatusResult extends BaseResult { - constructor( - public readonly status: number, - public readonly headers?: OutgoingHttpHeaders - ) { + constructor(public readonly status: number) { super() } @@ -15,9 +11,6 @@ export class SendStatusResult extends BaseResult { res: express.Response, next: express.NextFunction ) { - if (this.headers != null) { - res.set(this.headers) - } return res.sendStatus(this.status) } } diff --git a/src/specs/results/EndResult.spec.ts b/src/specs/results/EndResult.spec.ts index 02bd863..773ad13 100644 --- a/src/specs/results/EndResult.spec.ts +++ b/src/specs/results/EndResult.spec.ts @@ -72,30 +72,4 @@ describe('EndResult', () => { text: 'Hello' }) }) - - it('accepts headers', async () => { - // Given - @controller('/') - class HomeController { - @httpGet('/') - index(): EndResult { - return new EndResult('Hello', undefined, undefined, { test: 'test' }) - } - } - - // When - const app = tachijs({ - controllers: [HomeController] - }) - - // Then - const response = await request(app).get('/') - expect(response).toMatchObject({ - status: 200, - text: 'Hello', - headers: { - test: 'test' - } - }) - }) }) diff --git a/src/specs/results/JSONResult.spec.ts b/src/specs/results/JSONResult.spec.ts index e72f5fc..d92a24e 100644 --- a/src/specs/results/JSONResult.spec.ts +++ b/src/specs/results/JSONResult.spec.ts @@ -71,43 +71,4 @@ describe('JSONResult', () => { }) }) }) - - it('accepts headers', async () => { - // Given - interface IndexResponseData { - message: string - } - @controller('/') - class HomeController { - @httpGet('/') - index(): JSONResult { - return new JSONResult( - { - message: 'Hello' - }, - undefined, - { test: 'test' } - ) - } - } - const app = tachijs({ - controllers: [HomeController] - }) - - // When - const response = await request(app) - .get('/') - .expect('Content-Type', /json/) - - // Then - expect(response).toMatchObject({ - status: 200, - header: { - test: 'test' - }, - text: JSON.stringify({ - message: 'Hello' - }) - }) - }) }) diff --git a/src/specs/results/RedirectResult.spec.ts b/src/specs/results/RedirectResult.spec.ts index 79bae83..c02ab8d 100644 --- a/src/specs/results/RedirectResult.spec.ts +++ b/src/specs/results/RedirectResult.spec.ts @@ -51,30 +51,4 @@ describe('RedirectResult', () => { } }) }) - - it('accepts headers', async () => { - // Given - @controller('/') - class HomeController { - @httpGet('/') - index() { - return new RedirectResult('/test', undefined, { test: 'test' }) - } - } - const app = tachijs({ - controllers: [HomeController] - }) - - // When - const response = await request(app).get('/') - - // Then - expect(response).toMatchObject({ - status: 302, - header: { - test: 'test', - location: '/test' - } - }) - }) }) diff --git a/src/specs/results/RenderResult.spec.ts b/src/specs/results/RenderResult.spec.ts index a89faaf..148a25a 100644 --- a/src/specs/results/RenderResult.spec.ts +++ b/src/specs/results/RenderResult.spec.ts @@ -139,33 +139,4 @@ describe('RenderResult', () => { text: '

Hello

' }) }) - - it('accepts status', async () => { - // Given - @controller('/') - class HomeController { - @httpGet('/') - index() { - return new RenderResult('test', undefined, undefined, undefined, { - test: 'test' - }) - } - } - const app = tachijs({ - before, - controllers: [HomeController] - }) - - // When - const response = await request(app).get('/') - - // Then - expect(response).toMatchObject({ - status: 200, - text: '

Hello

', - headers: { - test: 'test' - } - }) - }) }) diff --git a/src/specs/results/SendFileResult.spec.ts b/src/specs/results/SendFileResult.spec.ts index 0812a17..12d4c8f 100644 --- a/src/specs/results/SendFileResult.spec.ts +++ b/src/specs/results/SendFileResult.spec.ts @@ -109,36 +109,4 @@ describe('SendFileResult', () => { text: '# Test document\n' }) }) - - it('accepts headers', async () => { - // Given - @controller('/') - class HomeController { - @httpGet('/') - index() { - return new SendFileResult( - path.join(__dirname, '../dummy/files/readme.md'), - undefined, - undefined, - undefined, - { test: 'test' } - ) - } - } - const app = tachijs({ - controllers: [HomeController] - }) - - // When - const response = await request(app).get('/') - - // Then - expect(response).toMatchObject({ - status: 200, - text: '# Test document\n', - headers: { - test: 'test' - } - }) - }) }) diff --git a/src/specs/results/SendResult.spec.ts b/src/specs/results/SendResult.spec.ts index 21259bb..a090a9a 100644 --- a/src/specs/results/SendResult.spec.ts +++ b/src/specs/results/SendResult.spec.ts @@ -47,32 +47,4 @@ describe('SendResult', () => { text: 'Hello' }) }) - - it('accepts headers', async () => { - // Given - @controller('/') - class HomeController { - @httpGet('/') - index(): SendResult { - return new SendResult('Hello', undefined, { - test: 'test' - }) - } - } - const app = tachijs({ - controllers: [HomeController] - }) - - // When - const response = await request(app).get('/') - - // Then - expect(response).toMatchObject({ - status: 200, - text: 'Hello', - headers: { - test: 'test' - } - }) - }) }) diff --git a/src/specs/results/SendStatusResult.spec.ts b/src/specs/results/SendStatusResult.spec.ts index fe1bcb9..c93de45 100644 --- a/src/specs/results/SendStatusResult.spec.ts +++ b/src/specs/results/SendStatusResult.spec.ts @@ -24,30 +24,4 @@ describe('SendStatusResult', () => { text: 'OK' }) }) - - it('accepts headers', async () => { - // Given - @controller('/') - class HomeController { - @httpGet('/') - index() { - return new SendStatusResult(200, { test: 'test' }) - } - } - const app = tachijs({ - controllers: [HomeController] - }) - - // When - const response = await request(app).get('/') - - // Then - expect(response).toMatchObject({ - status: 200, - text: 'OK', - headers: { - test: 'test' - } - }) - }) }) From 7a8ca7217d0f9420666adbceee0a3dff0105fd8a Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Mon, 8 Jul 2019 13:27:56 +0900 Subject: [PATCH 18/20] Format tachijs.ts code --- src/tachijs.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tachijs.ts b/src/tachijs.ts index c208734..bfe4c25 100644 --- a/src/tachijs.ts +++ b/src/tachijs.ts @@ -54,9 +54,7 @@ class TachiJSApp { const controllerMeta = getControllerMeta(ControllerConstructor) if (controllerMeta == null) throw new Error( - `Please apply @controller decorator to "${ - ControllerConstructor.name - }".` + `Please apply @controller decorator to "${ControllerConstructor.name}".` ) const router = express.Router(controllerMeta.routerOptions) From 09e641042a3e1937a49806eb1064c166ff29ff92 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Mon, 8 Jul 2019 17:06:43 +0900 Subject: [PATCH 19/20] Change argument order of setHandlerParamMetaList Keys should come before value --- src/decorators/handlerParam/handlerParam.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/decorators/handlerParam/handlerParam.ts b/src/decorators/handlerParam/handlerParam.ts index 461cf4c..59f6181 100644 --- a/src/decorators/handlerParam/handlerParam.ts +++ b/src/decorators/handlerParam/handlerParam.ts @@ -35,8 +35,8 @@ export function getHandlerParamMetaList( export function setHandlerParamMetaList( controller: any, - meta: HandlerParamMetaList, - propertyKey: string + propertyKey: string, + meta: HandlerParamMetaList ): void { if (!handlerParamMetaMap.has(controller)) { handlerParamMetaMap.set(controller, new Map()) @@ -73,6 +73,6 @@ export function handlerParam(selector: HandlerParamSelector) { handlerParamMeta ] - setHandlerParamMetaList(target.constructor, meta, propertyKey) + setHandlerParamMetaList(target.constructor, propertyKey, meta) } } From 78156da2f0c85295700edb7cb14b435ba9f52222 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Mon, 8 Jul 2019 17:18:31 +0900 Subject: [PATCH 20/20] 1.0.0-2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0ea15e2..9d2e7e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tachijs", - "version": "1.0.0-1", + "version": "1.0.0-2", "description": "Highly testable dead simple web server written in Typescript", "main": "dist", "files": [