Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

express-form

Package Overview
Dependencies
Maintainers
2
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

express-form - npm Package Compare versions

Comparing version 0.8.1 to 0.10.0

test/mocha.opts

6

Changelog.md
# express-form changelog
## v0.10.0 (2013/10/23)
* add support for asynchronous custom validators/filters
## v0.8.1 (2013/02/21)
* cast to string for string-specific filters to prevent errors
## v0.8.0 (2013/02/16)

@@ -4,0 +10,0 @@ * use express 3.x for peer and dev dependencies

77

lib/field.js

@@ -7,2 +7,3 @@ var validator = require("validator")

, object = require("object-additions").object
, async = require("async")
, utils = require("./utils");

@@ -28,3 +29,3 @@

this.run = function (source, form, options) {
this.run = function (source, form, options, cb) {
var self = this

@@ -43,17 +44,40 @@ , errors = []

function runStack(foo) {
function runStack(foo, cb) {
stack.forEach(function (proc) {
var result = proc(foo, source); // Pass source for "equals" proc.
if (result.valid) return;
async.eachSeries(stack, function(proc, cb) {
if (proc.length == 3) {
// run the async validator/filter
return proc(foo, source, function(err, result) {
if (err) {
errors.push(err.message.replace("%s", fieldLabel));
return cb(null);
}
// filters return values
if (result != null) {
foo = result
}
cb(null);
});
}
// run the sync validator/filter
var result = proc(foo, source);
if (result.valid) return cb(null);
if (result.error) {
// If this field is not required and it doesn't have a value, ignore error.
if (!utils.hasValue(value) && !self.__required) return;
if (!utils.hasValue(value) && !self.__required) return cb(null);
return errors.push(result.error.replace("%s", fieldLabel));
errors.push(result.error.replace("%s", fieldLabel));
return cb(null);
}
foo = result;
cb(null);
}, function(err) {
cb(null, foo);
});
return foo;
}

@@ -64,12 +88,15 @@

if (!Array.isArray(value)) value = [value];
value = value.map(runStack);
async.mapSeries(value, runStack, function(err, value) {
utils.setProp(property, form, value);
cb(null, errors);
});
} else {
if (Array.isArray(value)) value = value[0];
value = runStack(value);
runStack(value, function(err, value) {
utils.setProp(property, form, value);
cb(null, errors);
});
}
utils.setProp(property, form, value);
if (errors.length) return errors;
};

@@ -99,3 +126,21 @@ }

Field.prototype.custom = function(func, message) {
// custom function is async
if (func.length == 3) {
return this.add(function(value, source, cb) {
func(value, source, function(err, result) {
if (err) return cb(new Error(message || err.message || "%s is invalid"));
// functions that return values are filters
if (result != null) return cb(null, result);
// value passed validator
cb(null, null);
});
});
}
// custom function is sync
return this.add(function (value, source) {
try {

@@ -109,3 +154,5 @@ var result = func(value, source);

// value passed validator
return { valid: true };
});

@@ -112,0 +159,0 @@ };

38

lib/form.js

@@ -7,3 +7,4 @@ /*!

var utils = require("./utils")
var async = require("async")
, utils = require("./utils")
, Field = require("./field");

@@ -86,21 +87,28 @@

routines.forEach(function (routine) {
var result = routine.run(mergedSource, req.form, options);
//routines.forEach(function (routine) {
async.each(routines, function(routine, cb) {
routine.run(mergedSource, req.form, options, function(err, result) {
// return early if no errors
if (!Array.isArray(result) || !result.length) return cb(null);
var errors = req.form.errors = req.form.errors || []
, name = routine.name;
if (!Array.isArray(result) || !result.length) return;
map[name] = map[name] || [];
result.forEach(function (error) {
errors.push(error);
map[name].push(error);
});
var errors = req.form.errors = req.form.errors || []
, name = routine.name;
cb(null);
});
}, function(err) {
map[name] = map[name] || [];
if (options.flashErrors) req.form.flashErrors();
if (next) next();
result.forEach(function (error) {
errors.push(error);
map[name].push(error);
});
});
if (options.flashErrors) req.form.flashErrors();
if (next) next();
}

@@ -107,0 +115,0 @@ }

@@ -5,3 +5,3 @@ {

"description": "Form validation and data filtering for Express",
"version": "0.8.1",
"version": "0.10.0",
"homepage": "http://dandean.github.com/express-form",

@@ -25,3 +25,4 @@ "repository": {

"validator": "0.4.x",
"object-additions": ">= 0.5.0"
"object-additions": ">= 0.5.0",
"async": "~0.2.9"
},

@@ -32,4 +33,5 @@ "peerDependencies": {

"devDependencies": {
"expresso": "~0.9.2",
"express": "3.x"
"mocha": "~1.13.0",
"express": "3.x",
"request": "~2.27.0"
},

@@ -41,6 +43,6 @@ "main": "index",

"scripts": {
"test": "expresso"
"test": "mocha"
},
"engines": {
"node": ">=0.4.0"
"node": ">=0.8.0"
},

@@ -47,0 +49,0 @@ "licenses": [

@@ -0,1 +1,3 @@

# express-form
Express Form provides data filtering and validation as route middleware to your Express applications.

@@ -5,67 +7,75 @@

**express 2.x: use express-form 0.7.x**
## Install
**express 3.x: use express-form 0.8.x**
* **Express 2.x** `npm install express-form@0.9.x`
Usage:
------
* **Express 3.x** `npm install express-form@0.10.x`
var form = require("express-form"),
field = form.field;
## Usage
var app = express.createServer();
```js
var express = require('express'),
form = require('express-form'),
field = form.field;
var app = express();
app.configure(function() {
app.use(express.bodyDecoder());
app.use(app.router);
});
app.configure(function() {
app.use(express.bodyDecoder());
app.use(app.router);
});
app.post(
app.post(
// Route
'/user',
// Route
'/user',
// Form filter and validation middleware
form(
field("username").trim().required().is(/^[a-z]+$/),
field("password").trim().required().is(/^[0-9]+$/),
field("email").trim().isEmail()
),
// Form filter and validation middleware
form(
field("username").trim().required().is(/^[a-z]+$/),
field("password").trim().required().is(/^[0-9]+$/),
field("email").trim().isEmail()
),
// Express request-handler now receives filtered and validated data
function(req, res){
if (!req.form.isValid) {
// Handle errors
console.log(req.form.errors);
// Express request-handler now receives filtered and validated data
function(req, res){
if (!req.form.isValid) {
// Handle errors
console.log(req.form.errors);
} else {
// Or, use filtered form data from the form object:
console.log("Username:", req.form.username);
console.log("Password:", req.form.password);
console.log("Email:", req.form.email);
}
}
);
} else {
// Or, use filtered form data from the form object:
console.log("Username:", req.form.username);
console.log("Password:", req.form.password);
console.log("Email:", req.form.email);
}
}
);
Documentation:
--------------
app.listen(3000);
```
## Documentation
### Module
The Express Form **module** returns an Express [Route Middleware](http://expressjs.com/guide.html#Route-Middleware) function. You specify filtering and validation by passing filters and validators as arguments to the main module function. For example:
`express-form` returns an `express` [Route Middleware](http://expressjs.com/guide.html#Route-Middleware) function.
You specify filtering and validation by passing filters and validators as
arguments to the main module function. For example:
var form = require("express-form");
```js
var form = require("express-form");
app.post('/user',
// Express Form Route Middleware: trims whitespace off of
// the `username` field.
form(form.field("username").trim()),
// standard Express handler
function(req, res) {
// ...
}
);
app.post('/user',
// Express Form Route Middleware: trims whitespace off of
// the `username` field.
form(form.field("username").trim()),
// standard Express handler
function(req, res) {
// ...
}
);
```

@@ -76,17 +86,29 @@ ### Fields

field(fieldname[, label]);
```
field(fieldname[, label]);
```
You can access nested properties with either dot or square-bracket notation.
field("post.content").minLength(50),
field("post[user][id]").isInt(),
field("post.super.nested.property").required()
Simply specifying a property like this, makes sure it exists. So, even if `req.body.post` was undefined, `req.form.post.content` would be defined. This helps avoid any unwanted errors in your code.
```js
field("post.content").minLength(50),
field("post[user][id]").isInt(),
field("post.super.nested.property").required()
```
Simply specifying a property like this, makes sure it exists. So, even if `req.body.post` was undefined,
`req.form.post.content` would be defined. This helps avoid any unwanted errors in your code.
The API is chainable, so you can keep calling filter/validator methods one after the other:
filter("username").trim().toLower().truncate(5).required().isAlphanumeric()
```js
filter("username")
.required()
.trim()
.toLower()
.truncate(5)
.isAlphanumeric()
```
#### Filter API:
### Filter API:

@@ -128,3 +150,3 @@ Type Coercion

#### Validator API:
### Validator API:

@@ -299,2 +321,34 @@ **Validation messages**: each validator has its own default validation message.

});
Validator based value on another field of the incoming source being validated
field("sport", "favorite sport").custom(function(value, source) {
if (!source.country) {
throw new Error('unable to validate %s');
}
switch (source.country) {
case 'US':
if (value !=== 'baseball') {
throw new Error('America likes baseball');
}
break;
case 'UK':
if (value !=== 'football') {
throw new Error('UK likes football');
}
break;
}
});
Asynchronous custom validator (3 argument function signature)
form.field('username').custom(function(value, source, callback) {
username.check(value, function(err) {
if (err) return callback(new Error('Invalid %s'));
callback(null);
});
});

@@ -351,11 +405,4 @@

Installation:
-------------
### Credits
npm install express-form
Credits
-------
Currently, Express Form uses many of the validation and filtering functions provided by Chris O'Hara's [node-validator](https://github.com/chriso/node-validator).

@@ -7,2 +7,3 @@ var assert = require("assert"),

http = require("http"),
request = require("request"),
app = express();

@@ -20,3 +21,2 @@

app.configure(function() {

@@ -27,3 +27,3 @@ app.use(express.bodyParser());

module.exports = {
'express : middleware : valid-form': function() {
'express : middleware : valid-form': function(done) {
app.post(

@@ -44,19 +44,20 @@ '/user',

}
);
assert.response(app,
{
url: '/user',
method: 'POST',
body: JSON.stringify({
username: " dandean \n\n\t",
password: " 12345 "
}),
headers: { 'Content-Type': 'application/json' }
},
{ status: 200 }
);
request.post({
url: 'http://localhost:3000/user',
method: 'POST',
body: JSON.stringify({
username: " dandean \n\n\t",
password: " 12345 "
}),
headers: { 'Content-Type': 'application/json' }
}, function(err, res, body) {
assert.ifError(err);
assert.strictEqual(res.statusCode, 200);
done();
});
},
'express : middleware : merged-data': function() {
'express : middleware : merged-data': function(done) {
app.post(

@@ -82,17 +83,18 @@ '/user/:id',

}
);
assert.response(app,
{
url: '/user/5?stuff=things&id=overridden',
method: 'POST',
body: JSON.stringify({
id: "overridden by url param",
stuff: "overridden by query param",
rad: "cool"
}),
headers: { 'Content-Type': 'application/json' }
},
{ status: 200 }
);
request({
url: 'http://localhost:3000/user/5?stuff=things&id=overridden',
method: 'POST',
body: JSON.stringify({
id: "overridden by url param",
stuff: "overridden by query param",
rad: "cool"
}),
headers: { 'Content-Type': 'application/json' }
}, function(err, res, body) {
assert.ifError(err);
assert.strictEqual(res.statusCode, 200);
done();
});
}

@@ -99,0 +101,0 @@

@@ -571,2 +571,97 @@ var assert = require("assert"),

"validation: custom : async": function(done) {
var request = { body: { field1: "value1", field2: "value2" }};
var next = function next() {
assert.strictEqual(request.form.isValid, false);
assert.strictEqual(request.form.errors.length, 1);
assert.strictEqual(request.form.errors[0], 'Invalid field1');
done();
};
form(validate("field1").custom(function(value, source, callback) {
process.nextTick(function() {
assert.strictEqual(value, 'value1');
callback(new Error("Invalid %s"));
});
}))(request, {}, next);
},
"validation : custom : async : success": function(done) {
var request = { body: { field1: "value1", field2: "value2" }};
var callbackCalled = false;
var next = function next() {
assert.strictEqual(callbackCalled, true);
assert.strictEqual(request.form.isValid, true);
assert.strictEqual(request.form.errors.length, 0);
done();
};
form(validate("field1").custom(function(value, source, callback) {
process.nextTick(function() {
assert.strictEqual(value, 'value1');
callbackCalled = true;
callback(null);
});
}))(request, {}, next);
},
"validation : custom : async : chaining": function(done) {
var request = { body: { field1: "value1", field2: "value2" }};
var callbackCalled = 0;
var next = function next() {
assert.strictEqual(callbackCalled, 2);
assert.strictEqual(request.form.isValid, false);
assert.strictEqual(request.form.errors.length, 2);
assert.strictEqual(request.form.errors[0], 'Fail! field1');
assert.strictEqual(request.form.errors[1], 'yes sync custom funcs still work !! field1');
done();
};
form(validate("field1")
.custom(function(value, source, callback) {
process.nextTick(function() {
++callbackCalled;
callback(null);
});
})
.custom(function(value, source, callback) {
process.nextTick(function() {
++callbackCalled;
callback(new Error('Fail! %s'));
});
})
.custom(function(value, source) {
throw new Error('yes sync custom funcs still work !! %s');
})
)(request, {}, next);
},
"validation : custom : async : multiple fields": function(done) {
var request = { body: { field1: "value1", field2: "value2" }};
var callbackCalled = 0;
var next = function next() {
assert.strictEqual(callbackCalled, 2);
assert.strictEqual(request.form.isValid, false);
assert.strictEqual(request.form.errors.length, 2);
assert.strictEqual(request.form.errors[0], 'field1 error');
assert.strictEqual(request.form.errors[1], 'field2 error');
done();
};
form(
validate("field1").custom(function(value, source, callback) {
process.nextTick(function() {
++callbackCalled;
assert.strictEqual(value, 'value1')
callback(new Error('%s error'));
});
}),
validate("field2").custom(function(value, source, callback) {
process.nextTick(function() {
++callbackCalled;
assert.strictEqual(value, 'value2');
callback(new Error('%s error'));
});
})
)(request, {}, next);
},
"validation : request.form property-pollution": function() {

@@ -573,0 +668,0 @@ var request = { body: { }};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc