Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0c1bb7d
commit 6a5dfbd
Showing
53 changed files
with
707 additions
and
3,214 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# EditorConfig is awesome: http://EditorConfig.org | ||
|
||
# top-most EditorConfig file | ||
root = true | ||
|
||
[*] | ||
end_of_line = lf | ||
indent_style = space | ||
indent_size = 2 | ||
max_line_length = 120 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
.nyc_output |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"env": { | ||
"commonjs": true, | ||
"es6": true, | ||
"node": true, | ||
"jest": true | ||
}, | ||
"extends": ["airbnb-base"], | ||
"globals": { | ||
"Atomics": "readonly", | ||
"SharedArrayBuffer": "readonly" | ||
}, | ||
"parserOptions": { | ||
"ecmaVersion": 2018 | ||
}, | ||
"rules": { | ||
"arrow-parens": 0, | ||
"eslint-disable-next": 0 | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
name: Node.js CI | ||
|
||
on: [push] | ||
|
||
jobs: | ||
build: | ||
|
||
runs-on: ubuntu-latest | ||
|
||
strategy: | ||
matrix: | ||
node-version: [8.x, 10.x, 12.x] | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Use Node.js ${{ matrix.node-version }} | ||
uses: actions/setup-node@v1 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
- run: npm install | ||
- run: npm run build --if-present | ||
- run: npm run coverage | ||
env: | ||
CI: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
v12.13.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
const http = require('http'); | ||
const Joi = require('@hapi/joi'); | ||
|
||
const evOptions = { | ||
context: null, | ||
status: 400, | ||
statusText: http.STATUS_CODES[400], | ||
}; | ||
|
||
// validate status.. | ||
const evSchema = Joi.object({ | ||
context: Joi.boolean(), | ||
status: Joi.number(), | ||
}); | ||
|
||
const mergeEvOptions = (options) => { | ||
const status = options.status || evOptions.status; | ||
return { ...evOptions, options, statusText: http.STATUS_CODES[status] }; | ||
}; | ||
|
||
exports.mergeEvOptions = mergeEvOptions; | ||
exports.evSchema = evSchema; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,101 +1,41 @@ | ||
'use strict'; | ||
var Joi = require('@hapi/joi'); | ||
var assignIn = require('lodash/assignIn'); | ||
var find = require('lodash/find'); | ||
var defaults = require('lodash/defaults'); | ||
var ValidationError = require('./validation-error'); | ||
const Joi = require('@hapi/joi'); | ||
|
||
var defaultOptions = { | ||
contextRequest: false, | ||
allowUnknownHeaders: true, | ||
allowUnknownBody: true, | ||
allowUnknownQuery: true, | ||
allowUnknownParams: true, | ||
allowUnknownCookies: true, | ||
status: 400, | ||
statusText: 'Bad Request' | ||
}; | ||
var globalOptions = {}; | ||
|
||
// maps the corresponding request object to an `express-validation` option | ||
var unknownMap = { | ||
headers: 'allowUnknownHeaders', | ||
body: 'allowUnknownBody', | ||
query: 'allowUnknownQuery', | ||
params: 'allowUnknownParams', | ||
cookies: 'allowUnknownCookies' | ||
}; | ||
|
||
exports = module.exports = function expressValidation (schema) { | ||
if (!schema) throw new Error('Please provide a validation schema'); | ||
|
||
return function (req, res, next) { | ||
var errors = []; | ||
|
||
// Set default options | ||
var options = defaults({}, schema.options || {}, globalOptions, defaultOptions); | ||
|
||
// NOTE: mutates `errors` | ||
['headers', 'body', 'query', 'params', 'cookies'].forEach(function (key) { | ||
var allowUnknown = options[unknownMap[key]]; | ||
var entireContext = options.contextRequest ? req : null; | ||
if (schema[key]) validate(errors, req[key], schema[key], key, allowUnknown, entireContext); | ||
}); | ||
const ExpressValidationError = require('./validation-error'); | ||
const { mergeJoiOptions, validateJoiSchema, joiSchema } = require('./joi'); | ||
const { mergeEvOptions, evSchema } = require('./ev-options'); | ||
const { parameters } = require('./parameters'); | ||
const { handleMutation } = require('./mutation'); | ||
|
||
if (errors && errors.length === 0) return next(); | ||
exports.validate = (schema = {}, options = {}, joi = {}) => { | ||
Joi.assert(schema, joiSchema); | ||
Joi.assert(options, evSchema); | ||
|
||
return next(new ValidationError(errors, options)); | ||
}; | ||
}; | ||
return async (request, response, next) => { | ||
const evOptions = mergeEvOptions(options); | ||
const joiOptions = mergeJoiOptions(joi, options.context, request); | ||
|
||
exports.ValidationError = ValidationError; | ||
const validate = (parameter) => schema[parameter].validateAsync(request[parameter], joiOptions) | ||
.then(result => handleMutation(request[parameter], result.value)) | ||
.catch(errors => ({ [parameter]: errors.details })); | ||
|
||
exports.options = function (opts) { | ||
if (!opts) { | ||
globalOptions = {}; | ||
return; | ||
} | ||
const promises = parameters | ||
.filter(parameter => request[parameter] && schema[parameter]) | ||
.map(parameter => validate(parameter)); | ||
|
||
globalOptions = defaults({}, globalOptions, opts); | ||
}; | ||
const results = await Promise.all(promises); | ||
|
||
/** | ||
* validate checks the current `Request` for validations | ||
* NOTE: mutates `request` in case the object is valid. | ||
*/ | ||
function validate (errObj, request, schema, location, allowUnknown, context) { | ||
if (!request || !schema) return; | ||
|
||
var joiOptions = { | ||
context: context || request, | ||
allowUnknown: allowUnknown, | ||
abortEarly: false | ||
}; | ||
const errors = results | ||
.filter(item => item) | ||
.reduce((a, b) => a.concat(b), []); | ||
|
||
Joi.validate(request, schema, joiOptions, function (errors, value) { | ||
if (!errors || errors.details.length === 0) { | ||
assignIn(request, value); // joi responses are parsed into JSON | ||
return; | ||
if (errors && errors.length > 0) { | ||
return next(new ExpressValidationError(errors[0], evOptions)); | ||
} | ||
errors.details.forEach(function (error) { | ||
var errorExists = find(errObj, function (item) { | ||
if (item && item.field === error.path && item.location === location) { | ||
item.messages.push(error.message); | ||
item.types.push(error.type); | ||
return item; | ||
} | ||
return; | ||
}); | ||
|
||
if (!errorExists) { | ||
errObj.push({ | ||
field: error.path, | ||
location: location, | ||
messages: [error.message], | ||
types: [error.type] | ||
}); | ||
} | ||
|
||
}); | ||
}); | ||
return next(); | ||
}; | ||
}; | ||
|
||
exports.ExpressValidationError = ExpressValidationError; | ||
exports.validateJoiSchema = validateJoiSchema; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
const Joi = require('@hapi/joi'); | ||
const { parameters } = require('./parameters'); | ||
|
||
const schema = parameters | ||
.reduce((result, item) => ({ ...result, [item]: Joi.any() }), {}); | ||
|
||
const joiSchema = Joi.object(schema).required().min(1).max(6); | ||
|
||
const validateJoiSchema = (schemas) => { | ||
schemas.forEach(sc => Joi.assert(sc, joiSchema)); | ||
}; | ||
|
||
const mergeJoiOptions = (joi, ctx, request) => { | ||
const context = ctx ? request : null; | ||
return { ...joi, warnings: true, context }; | ||
}; | ||
|
||
exports.validateJoiSchema = validateJoiSchema; | ||
exports.joiSchema = joiSchema; | ||
exports.mergeJoiOptions = mergeJoiOptions; | ||
|
||
// Joi.object({ context: Joi.boolean() }); | ||
// exports.sourceSchema = Joi.string().valid(...parameters); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
exports.handleMutation = (request, value) => { | ||
Object.keys(value).forEach(parameter => { | ||
if (request[parameter] === undefined) { | ||
Object.defineProperty(request, parameter, { value: value[parameter], enumerable: true }); | ||
} | ||
}); | ||
|
||
return null; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
exports.parameters = [ | ||
'headers', | ||
'params', | ||
'query', | ||
'cookies', | ||
'signedCookies', | ||
'body', | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
|
||
// console.log(errors); | ||
|
||
// errors.details.forEach(function (error) { | ||
// const errorExists = errObj.find(function (item) { | ||
// if (item && item.field === error.path && item.location === location) { | ||
// console.log('----', item); | ||
// item.messages.push(error.message); | ||
// item.types.push(error.type); | ||
// return item; | ||
// } | ||
// return; | ||
// }); | ||
|
||
// if (!errorExists) { | ||
// errObj.push({ | ||
// field: error.path, | ||
// location: location, | ||
// messages: [error.message], | ||
// types: [error.type] | ||
// }); | ||
// } | ||
// // console.log('errObj', errObj); | ||
// }); | ||
// }); | ||
|
||
|
||
// if (this.flatten) { | ||
// return this.errors.map(item => item.messages).reduce((a, b) => a.concat(b), []); | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,25 @@ | ||
'use strict'; | ||
var map = require('lodash/map'); | ||
var flatten = require('lodash/flatten'); | ||
|
||
function ValidationError (errors, options) { | ||
this.name = 'ValidationError'; | ||
this.message = 'validation error'; | ||
function ExpressValidationError(errors, options) { | ||
// console.log(errors) | ||
this.name = 'ExpressValidationError'; | ||
this.message = 'Express validation error'; | ||
this.errors = errors; | ||
this.flatten = options.flatten; | ||
this.status = options.status; | ||
this.statusText = options.statusText; | ||
}; | ||
ValidationError.prototype = Object.create(Error.prototype); | ||
Error.captureStackTrace(this, ExpressValidationError); | ||
} | ||
|
||
ExpressValidationError.prototype = Object.create(Error.prototype); | ||
|
||
ValidationError.prototype.toString = function () { | ||
ExpressValidationError.prototype.toString = function toString() { | ||
return JSON.stringify(this.toJSON()); | ||
}; | ||
|
||
ValidationError.prototype.toJSON = function () { | ||
if (this.flatten) return flatten(map(this.errors, 'messages')); | ||
ExpressValidationError.prototype.toJSON = function toJSON() { | ||
return { | ||
status: this.status, | ||
statusText: this.statusText, | ||
errors: this.errors | ||
errors: this.errors, | ||
}; | ||
}; | ||
|
||
module.exports = ValidationError; | ||
module.exports = ExpressValidationError; |
File renamed without changes.
File renamed without changes.
Oops, something went wrong.