Skip to content

Commit

Permalink
BREAKING CHANGE: addresses typings issues for strict mode (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
evanshortiss authored Aug 30, 2019
2 parents 63ab612 + 2225049 commit 5776fcb
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 33 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
## CHANGELOG
Date format is DD/MM/YYYY

## 3.0.0 (30/08/2019)
* Removed `fields`, `originalQuery`, `originalHeaders`, `originalBody`,
`originalParams`, and `originalFields` from `ValidatedRequest`. This simplifies
usage with TypeScript's *strict* mode.
* Added `ValidatedRequestWithRawInputsAndFields`. This is the same as
`ValidatedRequest` from versions 2.x.

## 2.0.1 (22/08/2019)
* Fixed compilation issue with TypeScript example when `strict` compiler flag is `true`.
* Updated test script to include building TypeScript example
Expand Down
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ app.get('/orders', validator.query(querySchema), (req, res) => {

## Usage (TypeScript)

For TypeScript a helper `ValidatedRequest` type is provided. This extends the
For TypeScript a helper `ValidatedRequest` and
`ValidatedRequestWithRawInputsAndFields` type is provided. This extends the
`express.Request` type and allows you to pass a schema using generics to
ensure type safety in your handler function.

Expand Down Expand Up @@ -117,11 +118,9 @@ interface HelloRequestSchema extends ValidatedRequestSchema {
app.get(
'/hello',
validator.query(querySchema),
(req, res) => {
(req: ValidatedRequest<HelloRequestSchema>, res) => {
// Woohoo, type safety and intellisense for req.query!
const vreq = req as ValidatedRequest<HelloRequestSchema>

res.end(`Hello ${vreq.query.name}!`)
res.end(`Hello ${req.query.name}!`)
}
)
```
Expand Down
30 changes: 24 additions & 6 deletions example/typescript/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as Joi from '@hapi/joi'
import formidable from 'express-formidable'
import {
ValidatedRequest,
ValidatedRequestWithRawInputsAndFields,
ValidatedRequestSchema,
createValidator,
ContainerTypes
Expand All @@ -10,18 +12,34 @@ import 'joi-extract-type'

const route = Router()
const validator = createValidator()
const querySchema = Joi.object({
const schema = Joi.object({
name: Joi.string().required()
})

interface HelloRequestSchema extends ValidatedRequestSchema {
[ContainerTypes.Query]: Joi.extractType<typeof querySchema>
interface HelloGetRequestSchema extends ValidatedRequestSchema {
[ContainerTypes.Query]: Joi.extractType<typeof schema>
}

route.get('/hello', validator.query(querySchema), (req, res) => {
const vreq = req as ValidatedRequest<HelloRequestSchema>
interface HelloPostRequestSchema extends ValidatedRequestSchema {
[ContainerTypes.Fields]: Joi.extractType<typeof schema>
}

// curl http://localhost:3030/hello/?name=express
route.get(
'/',
validator.query(schema),
(req: ValidatedRequest<HelloGetRequestSchema>, res) => {
res.end(`Hello ${req.query.name}`)
}
)

// curl -X POST -F 'name=express' http://localhost:3030/hello
route.post('/', formidable(), validator.fields(schema), (req, res) => {
const vreq = req as ValidatedRequestWithRawInputsAndFields<
HelloPostRequestSchema
>

res.end(`Hello ${vreq.query.name}`)
res.end(`Hello ${vreq.fields.name}`)
})

export default route
2 changes: 1 addition & 1 deletion example/typescript/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ app.listen(port, (err: any) => {
`Try accessing http://localhost:${port}/ping or http://localhost:${port}/hello?name=dean to get some data.\n`
)
console.log(
`Now try access hhttp://localhost:${port}/hello. You should get an error complaining that your querystring is invalid.`
`Now try access http://localhost:${port}/hello. You should get an error complaining that your querystring is invalid.`
)
})
58 changes: 47 additions & 11 deletions express-joi-validation.d.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as Joi from '@hapi/joi';
import * as Joi from '@hapi/joi'
import * as express from 'express'
import { IncomingHttpHeaders } from 'http';
import { IncomingHttpHeaders } from 'http'

/**
* Creates an instance of this module that can be used to generate middleware
* @param cfg
*/
export function createValidator (cfg? : ExpressJoiConfig): ExpressJoiInstance
export function createValidator(cfg?: ExpressJoiConfig): ExpressJoiInstance

/**
* These are the named properties on an express.Request that this module can
Expand Down Expand Up @@ -40,7 +40,25 @@ export type ValidatedRequestSchema = Record<ContainerTypes, any>
* *req.body* and others are strongly typed using your
* *ValidatedRequestSchema*
*/
export interface ValidatedRequest<T extends ValidatedRequestSchema> extends express.Request {
export interface ValidatedRequest<T extends ValidatedRequestSchema>
extends express.Request {
body: T[ContainerTypes.Body]
query: T[ContainerTypes.Query]
headers: T[ContainerTypes.Headers]
params: T[ContainerTypes.Params]
}

/**
* Use this in conjunction with *ValidatedRequestSchema* instead of
* express.Request for route handlers. This ensures *req.query*,
* *req.body* and others are strongly typed using your *ValidatedRequestSchema*
*
* This will also allow you to access the original body, params, etc. as they
* were before validation.
*/
export interface ValidatedRequestWithRawInputsAndFields<
T extends ValidatedRequestSchema
> extends express.Request {
body: T[ContainerTypes.Body]
query: T[ContainerTypes.Query]
headers: T[ContainerTypes.Headers]
Expand All @@ -54,7 +72,7 @@ export interface ValidatedRequest<T extends ValidatedRequestSchema> extends expr
}

/**
* Configuration options supportef by *createValidator(config)*
* Configuration options supported by *createValidator(config)*
*/
export interface ExpressJoiConfig {
joi?: typeof Joi
Expand All @@ -76,10 +94,28 @@ export interface ExpressJoiContainerConfig {
* calling *createValidator*
*/
export interface ExpressJoiInstance {
body (schema: Joi.Schema, cfg?: ExpressJoiContainerConfig): express.RequestHandler
query (schema: Joi.Schema, cfg?: ExpressJoiContainerConfig): express.RequestHandler
params (schema: Joi.Schema, cfg?: ExpressJoiContainerConfig): express.RequestHandler
headers (schema: Joi.Schema, cfg?: ExpressJoiContainerConfig): express.RequestHandler
fields (schema: Joi.Schema, cfg?: ExpressJoiContainerConfig): express.RequestHandler
response (schema: Joi.Schema, cfg?: ExpressJoiContainerConfig): express.RequestHandler
body(
schema: Joi.Schema,
cfg?: ExpressJoiContainerConfig
): express.RequestHandler
query(
schema: Joi.Schema,
cfg?: ExpressJoiContainerConfig
): express.RequestHandler
params(
schema: Joi.Schema,
cfg?: ExpressJoiContainerConfig
): express.RequestHandler
headers(
schema: Joi.Schema,
cfg?: ExpressJoiContainerConfig
): express.RequestHandler
fields(
schema: Joi.Schema,
cfg?: ExpressJoiContainerConfig
): express.RequestHandler
response(
schema: Joi.Schema,
cfg?: ExpressJoiContainerConfig
): express.RequestHandler
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "express-joi-validation",
"version": "2.0.1",
"version": "3.0.0",
"description": "validate express application inputs and parameters using joi",
"main": "express-joi-validation.js",
"scripts": {
Expand Down Expand Up @@ -38,6 +38,7 @@
"devDependencies": {
"@hapi/joi": "~15.0.3",
"@types/express": "~4.0.39",
"@types/express-formidable": "~1.0.4",
"@types/hapi__joi": "~15.0.2",
"@types/node": "^6.0.117",
"body-parser": "~1.18.3",
Expand Down
9 changes: 0 additions & 9 deletions tsconfig.json

This file was deleted.

0 comments on commit 5776fcb

Please sign in to comment.