New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

value-validator

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

value-validator - npm Package Compare versions

Comparing version
0.0.0
to
1.0.0
.npmignore

Sorry, the diff of this file is not supported yet

+10
language: node_js
node_js:
# - "0.10"
# - "0.11"
# - "4.2"
# - "5.0"
# - "5.1"
# - "5.2"
# - "5.3"
- "6"
# Test against this version of Node.js
environment:
matrix:
# - nodejs_version: "0.6" # not supported by appveyor
# - nodejs_version: "0.8" # not supported by appveyor
# - nodejs_version: "0.10"
# - nodejs_version: "0.11"
# - nodejs_version: "4"
# - nodejs_version: "5"
- nodejs_version: "6"
# Install scripts. (runs after repo cloning)
install:
# Get the latest stable version of Node.js or io.js
- ps: Install-Product node $env:nodejs_version
# install modules
- npm install
# Post-install test scripts.
test_script:
# Output useful info for debugging.
- node --version
- npm --version
- npm test
# Don't actually build.
build: off

Sorry, the diff of this file is not supported yet

[![Build Status](https://travis-ci.org/kaelzhang/value-validator.svg?branch=master)](https://travis-ci.org/kaelzhang/value-validator)
<!-- optional appveyor tst
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/kaelzhang/value-validator?branch=master&svg=true)](https://ci.appveyor.com/project/kaelzhang/value-validator)
-->
<!-- optional npm version
[![NPM version](https://badge.fury.io/js/value-validator.svg)](http://badge.fury.io/js/value-validator)
-->
<!-- optional npm downloads
[![npm module downloads per month](http://img.shields.io/npm/dm/value-validator.svg)](https://www.npmjs.org/package/value-validator)
-->
<!-- optional dependency status
[![Dependency Status](https://david-dm.org/kaelzhang/value-validator.svg)](https://david-dm.org/kaelzhang/value-validator)
-->
# value-validator
## Install
```sh
$ npm install value-validator --save
```
## Usage
```js
const Validator = require('value-validator')
const validator = new Validator([
/.{4,}/,
/^[a-z0-9_]+$/i,
function (v) {
const done = this.async()
asyncCheckExists(v, exists => {
if (exists) {
return done(new Error(`username "${v}" already exists.`))
}
done(null)
})
}
])
validator.validate('foo', (err, pass) => {
err // null
pass // false, to short
})
validator.validate('foo.bar', (err, pass) => {
err // null
pass // false, only letters, numbers and underscores.
})
validator.validate('steve', (err, pass) => {
err // maybe `new Error('username "steve" already exists.')`
pass // false
})
validator.validate('cook', (err, pass) => {
// maybe "cook" is a valid username
err // null
pass // true
})
```
## new Validator(rule, options)
- **rule** `RegExp|function()|String|Array.<mixed>` rule could be a regular expression, a function, a string (validator preset), or an array of mixed-type of the former three.
### Sync Function-type `rule`
The function should accept only one argument, which is the value to be validated.
If the function returns a `Boolean`, it indicates whether the validation is passed, and the `err` will be `null`
```js
const validator = new Validator(v => v > 10)
validator.validate(5, (err, pass) => {
err // null
pass // false
})
```
If the function returns an `Error`, it means the validation fails, and the error will passed to the callback function of `validate(v, callback)` as the first parameter `err`.
```js
const validator = new Validator(v => {
if (v > 10) {
return true
}
return new Error('should larger than 10')
})
validator.validate(5, (err, pass) => {
err // new Error('should larger than 10')
pass // false
})
```
### Async validator
To define an asynchronous validator, we need to use the common [this.async()](https://www.npmjs.com/package/wrap-as-async) style.
See the first example.
## Validator Presets
Validator presets are pre-defined abbreviation of a certain validation, or a set of validations.
```js
Validator.registerPresets({
// To define a function-typed preset
unique: function (v) {
const done = this.async()
asyncCheckExists(v, exists => {
if (exists) {
return done(new Error(`username "${v}" already exists.`))
}
done(null)
})
},
min4: /.{4,}/,
// A preset could be a set of presets.
username: [
'min4',
/^[a-z0-9_]+$/i,
'unique'
]
})
// Then we could use `username` as the test rule.
const validator = new Validator('username')
```
## License
MIT
[{
test: RegExp,
message: String
}]
{}
'use strict'
const make_array = require('make-array')
const wrap = require('wrap-as-async')
const async = require('async')
const util = require('util')
class Validator {
constructor (rules, {
codec = default_codec
} = {}) {
this._codec = codec
this._context = null
this._rules = []
make_array(rules).forEach((rule) => {
this.add(rule)
})
}
context (context) {
this._context = context
return this
}
add (rule) {
this._add(rule)
return this
}
validate (v, callback) {
async.everySeries(this._rules, (tester, done) => {
const isAsync = tester.call(
this._context, v,
(err, pass) => {
err = typeof err === 'string'
? new Error(err)
: err || null
pass = determine_pass(err, pass)
done(err, pass)
}
)
}, (err, pass) => {
// async.everySeries sets `pass` as `undefined`
// if there is an error encountered.
callback(err, determine_pass(err, pass))
})
}
// @returns {function()} wrapped
_add (rule) {
if (typeof rule === 'string') {
return this._decodePreset(rule)
}
this._rules.push(this._wrapRule(rule))
}
_wrapRule (rule) {
if (typeof rule === 'function') {
return wrap(rule)
}
if (util.isRegExp(rule)) {
return wrap((v) => {
return rule.test(v)
})
}
const str = rule && rule.toString
? rule.toString()
: ''
throw new Error(`value-validator: invalid rule "${str}"`)
}
_decodePreset (rule) {
return this._codec(rule)
.forEach(({name, args}) => {
const preset = Validator.PRESETS[name]
if (!preset) {
throw new Error(`value-validator: unknown preset "${name}".`)
}
if (typeof preset === 'function') {
this._rules.push(this._wrapWithArgs(preset, args))
return
}
// if a preset is a set,
// then ignore args
if (util.isArray(preset)) {
preset.forEach(this._add, this)
}
})
}
_wrapWithArgs (method, args) {
// The first argument is the value
const expectedArgLength = method.length - 1
const wrapped = wrap(method)
if (expectedArgLength !== args.length) {
const message = expectedArgLength === 1
? `one argument`
: `${argLength} arguments.`
throw new Error(
`value-validator: preset "${name}" only accepts ${message}`
)
}
return function (v, callback) {
const realArgs = [v, ...args, callback]
return wrapped.apply(this, realArgs)
}
}
}
// @returns {Boolean}
function determine_pass (err, pass) {
return err
? false
: pass === false
? false
: true
}
function default_codec (tester) {
return tester.split('|')
.filter((tester) => {
return !!tester.trim()
})
.map((tester) => {
tester = tester.trim()
const index = tester.indexOf(':')
if (!~index) {
return {
name: tester,
args: []
}
}
const name = tester.slice(0, index).trim()
const args = tester.slice(index + 1)
.split(',')
.map((arg) => arg.trim())
return {
name,
args
}
})
}
Validator.PRESETS = {}
// Registers a global preset
Validator.registerPreset = (name, preset) => {
if (name in Validator.PRESETS) {
throw new Error(`value-validator: preset "${name}" defined.`)
}
if (typeof preset !== 'function' && !util.isArray(preset)) {
throw new TypeError(
`value-validator: preset only accepts function or array.`
)
}
Validator.PRESETS[name] = preset
return Validator
}
Validator.registerPresets = (map) => {
let key
for (key in map) {
Validator.registerPreset(key, map[key])
}
return Validator
}
module.exports = Validator
const test = require('ava')
const Validator = require('..')
Validator.registerPresets({
'min-length': (v, min) => {
return v.length >= Number(min)
},
'max-length': (v, max) => {
return v.length <= Number(max)
},
mobile: (v) => {
return /1\d{10}/.test(v)
},
username: function (v) {
const done = this.async()
setTimeout(() => {
if (v === 'foo') {
return done('foo already taken')
}
done(null)
}, 10)
},
between: (v, min, max) => {
return v.length >= Number(min) && v.length <= Number(max)
},
'min-length-6-username': [
'min-length:6',
'username'
]
})
test.cb('simple global preset', t => {
new Validator('mobile').validate('18800001111', (err, result) => {
t.is(err, null)
t.is(result, true)
t.end()
})
})
test.cb('preset with arguments', t => {
new Validator('max-length:3').validate('1234', (err, result) => {
t.is(err, null)
t.is(result, false)
t.end()
})
})
test.cb('preset with improper length of arguments', t => {
try {
new Validator('max-length:1,2')
} catch (e) {
t.end()
return
}
t.fail('it should throw an error.')
t.end()
})
test.cb('multiple presets, [1, 3] test "12"', t => {
new Validator('max-length:3|min-length:1').validate('12', (err, result) => {
t.is(err, null)
t.is(result, true)
t.end()
})
})
test.cb('multiple presets, [1, 3] test "1234"', t => {
new Validator('max-length:3|min-length:1').validate('1234', (err, result) => {
t.is(err, null)
t.is(result, false)
t.end()
})
})
test.cb('multiple presets, [1, 3] test ""', t => {
new Validator('max-length:3|min-length:1').validate('', (err, result) => {
t.is(err, null)
t.is(result, false)
t.end()
})
})
test.cb('async preset, min:6, and username, foo, fail', t => {
new Validator('min-length:6|username').validate('foo', (err, result) => {
t.is(err, null)
t.is(result, false)
t.end()
})
})
test.cb('min-length-6-username, foo, fail', t => {
new Validator('min-length-6-username').validate('foo', (err, result) => {
t.is(err, null)
t.is(result, false)
t.end()
})
})
test.cb('async preset, min:3, and username, foo, fail', t => {
new Validator('min-length:3|username').validate('foo', (err, result) => {
t.is(err instanceof Error, true)
t.is(err.message, 'foo already taken')
t.is(result, false)
t.end()
})
})
test.cb('async preset, min:3, and username, bar, success', t => {
new Validator('min-length:3|username').validate('bar', (err, result) => {
t.is(err, null)
t.is(result, true)
t.end()
})
})
test.cb('preset with multiple arguments', t => {
new Validator('between:2,6').validate('1234', (err, result) => {
t.is(err, null)
t.is(result, true)
t.end()
})
})
const ava = require('ava')
const Validator = require('..')
const cases = [
{
test: /\d{2,6}/,
value: '1234'
},
{
test: /1\d{10}/,
value: '1880000',
pass: false
},
{
title: 'function, returns boolean, fail',
test: (v) => {
return v > 10
},
value: 5,
pass: false
},
{
title: 'function, returns boolean, pass',
test: (v) => {
return v > 10
},
value: 11
},
{
title: 'async function, pass',
test: function (v) {
const done = this.async()
setTimeout(() => {
if (v < 0) {
return done(null)
}
done('not minus')
}, 10)
},
error: 'not minus',
pass: false
},
{
title: 'function, returns Error',
test: (v) => {
if (v > 10) {
return true
}
return new Error('a')
},
error: 'a',
pass: false
},
{
title: 'array tester',
test: [
/\d{11}/,
/1\d{10}/
],
value: '08800001111',
pass: false
}
]
cases.forEach((c) => {
const {
title,
test,
value,
error,
pass,
only
} = c
const result = pass === false
? false
: true
const description = title
|| `${test.toString()}, ${value}, ${error ? 'fail' : 'pass'}`
const _test = only
? ava.only.cb
: ava.cb
_test(description, t => {
let v
try {
v = new Validator(test)
} catch (e) {
console.error(e)
t.fail()
t.end()
return
}
v.validate(value, (err, success) => {
t.is(success, result)
if (err) {
t.is(err.message, error)
} else {
t.is(err, null)
}
t.end()
})
})
})
+35
-1

@@ -1,1 +0,35 @@

{"name": "value-validator", "version": "0.0.0", "description": "", "main": "index.js", "scripts": {}, "license": "MIT"}
{
"name": "value-validator",
"version": "1.0.0",
"description": "Low-level rule manager for validating values.",
"main": "./src",
"scripts": {
"test": "ava --verbose --timeout=10s"
},
"repository": {
"type": "git",
"url": "git://github.com/kaelzhang/value-validator.git"
},
"keywords": [
"value-validator",
"validator",
"regexp",
"async"
],
"engines": {
"node": ">=0.10.0"
},
"author": "kaelzhang",
"license": "MIT",
"bugs": {
"url": "https://github.com/kaelzhang/value-validator/issues"
},
"devDependencies": {
"ava": "^0.16.0"
},
"dependencies": {
"async": "^2.0.1",
"make-array": "^1.0.1",
"wrap-as-async": "^1.2.2"
}
}