Skip to content

Commit

Permalink
Discard validation of reqBody
Browse files Browse the repository at this point in the history
  • Loading branch information
Rokt33r committed Mar 21, 2019
1 parent 3500b7a commit 15473d4
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 160 deletions.
8 changes: 1 addition & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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"
}
}
5 changes: 3 additions & 2 deletions src/decorators/handlerParam/handlerParam.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -60,7 +61,7 @@ export function handlerParam<T>(selector: HandlerParamSelector<T>) {
selector
}
if (reflectMetadataIsAvailable) {
handlerParamMeta.paramType = Reflect.getMetadata(
handlerParamMeta.paramType = (Reflect as any).getMetadata(
'design:paramtypes',
target,
propertyKey
Expand Down
13 changes: 3 additions & 10 deletions src/decorators/handlerParam/reqBody.ts
Original file line number Diff line number Diff line change
@@ -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
})
}
11 changes: 1 addition & 10 deletions src/examples/readme/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// tslint:disable:no-console
import 'reflect-metadata' // You have to import this to enable decorators.
import tachijs, {
ConfigSetter,
controller,
Expand All @@ -10,7 +9,6 @@ import tachijs, {
inject,
BaseController
} from '../../'
import { IsString } from 'class-validator'
import bodyParser from 'body-parser'

enum ServiceTypes {
Expand Down Expand Up @@ -46,12 +44,6 @@ class NotificationService {
}
}

// Prepare class validator
class NotifyRequestBody {
@IsString()
message: string
}

@controller('/')
class HomeController extends BaseController {
constructor(
Expand All @@ -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('/')
Expand Down
Original file line number Diff line number Diff line change
@@ -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'
})
})
})
130 changes: 0 additions & 130 deletions src/specs/decorators/handlerParam/reqBody.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down Expand Up @@ -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'
}
}
]
})
})
})
})
1 change: 0 additions & 1 deletion src/specs/setup.ts
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
import 'reflect-metadata'

0 comments on commit 15473d4

Please sign in to comment.