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

check-data

Package Overview
Dependencies
Maintainers
1
Versions
75
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

check-data - npm Package Compare versions

Comparing version 4.0.1 to 4.1.0

test/common.js

17

History.md

@@ -23,9 +23,3 @@ ## 版本更新

<!-- * 新增Check.schema()验证表达式预检,帮助提前发现语法错误 × -->
<!-- * schema新增宽松模式loose()方法 × -->
<!-- * schema新增严格模式strict()方法 × -->
## 4.0.1

@@ -37,1 +31,12 @@

## 4.1.0
* 删除公用选项value
* 新增严格模式Check.strict()方法
* 新增宽松模式Check.loose()方法
* schema新增严格模式schema.strict()方法
* schema新增宽松模式schema.loose()方法

@@ -10,9 +10,22 @@ "use strict"

constructor(origin, options) {
this.origin = origin
/**
*
* @param {*} options 验证表达式
* @param {*} mode 验证模式
*/
constructor(options, mode) {
this.options = options
return this.recursion(origin, options, '')
this.mode = mode
}
/**
* 执行数据验证
* @param {*} origin 待验证原始数据
*/
run(origin) {
this.origin = origin
return this.recursion(origin, this.options, '')
}
/**
* 判断是否允许为空值,默认将undefined、 null、空字符串视为空值

@@ -55,14 +68,17 @@ * 默认值在大多数场景下适用,在出现例外时,可以在指定字段上使用ignore属性,重置对默认空值的定义

// value赋值
else if (options.value) {
data = options.value
}
// 禁止空值
else if (options.allowNull === false) {
return {
error: `${field}不能为空`
}
return { error: `值不允许为空` }
}
// 允许空值
else if (options.allowNull === true) {
return {}
}
// 严格模式下,禁止空值
else if (this.mode === 'strict') {
return { error: `值不允许为空` }
}
else {

@@ -74,11 +90,12 @@ return {}

let checks = Types[options.type]
// type为内置数据类型
if (Types[options.type]) {
if (checks) {
let checks = Types[options.type]
for (let name in options) {
let func = checks[name]
if (func) {
let check = checks[name]
if (check) {
let option = options[name]
let { error, data: subData } = func({ data, option, origin: this.origin })
let { error, data: subData } = check({ data, option, origin: this.origin })
if (error) {

@@ -97,3 +114,3 @@ return {

// 不支持的参数
// 不支持的数据类型
else {

@@ -111,3 +128,6 @@ return {

if (!Array.isArray(data)) {
// 宽松模式下,跳过空值
if (this.mode === 'loose') {
if (this.isNull(data)) return {}
}
return {

@@ -178,4 +198,8 @@ error: `${key}必须为数组类型`

if (typeof data !== 'object') {
// 宽松模式下,跳过空值
if (this.mode === 'loose') {
if (this.isNull(data)) return {}
}
return {
error: `值必须为对象`
error: `值必须为Object类型`
}

@@ -209,5 +233,3 @@ }

return {
data: dataObj
}
return { data: dataObj }

@@ -222,2 +244,6 @@ }

if (this.isNull(data)) {
// 严格模式下,禁止空值
if (this.mode === 'strict') {
return { error: "值不允许为空" }
}
return {}

@@ -258,31 +284,44 @@ }

* @param {*} options 验证表达式
* @param {Object} handler 导出数据自定义处理方法
* @param {Object} extend 导出数据扩展函数集合
* @param {String} mode 验证模式(仅供内部使用)
*/
function Check(data, options, handler = {}) {
function Check(data, options, extend = {}, mode) {
let output = new Parser(data, options)
let parser = new Parser(options, mode)
if (output.error) {
return output
let result = parser.run(data)
if (result.error) {
return result
}
// 数据扩展函数,基于已验证的数据构建新的数据结构
for (let name in handler) {
let item = handler[name]
// 使用自定义构造函数处理
for (let name in extend) {
let item = extend[name]
if (typeof item === 'function') {
item = item.call(output.data, output.data)
item = item.call(result.data, result.data)
}
output.data[name] = item
result.data[name] = item
}
// 对象空值过滤
filterNull(output.data)
filterNull(result.data)
return output
return result
}
// 严格模式
Check.strict = function (data, options, extend = {}) {
return Check(data, options, extend, 'strict')
}
// 宽松模式
Check.loose = function (data, options, extend = {}) {
return Check(data, options, extend, 'loose')
}
Check.types = symbols
/**

@@ -339,15 +378,15 @@ * 自定义数据类型扩展方法

/**
* 严格模式,禁止空值
* 严格模式
* 禁止所有空值,有值验证,无值报错
*/
schema.strict = function () {
schema.strict = function (data) {
return Check(data, options, extend, 'strict')
}
/**
* 宽松模式,用于数据更新
* 忽略所有allowNull值,有值验证,无值跳过,
* 宽松模式
* 忽略所有空值,有值验证,无值跳过,即使allowNull值为true
*/
schema.loose = function () {
schema.loose = function (data) {
return Check(data, options, extend, 'loose')
}

@@ -354,0 +393,0 @@

{
"name": "check-data",
"version": "4.0.1",
"version": "4.1.0",
"description": "JS数据验证、转换递归器",

@@ -5,0 +5,0 @@ "main": "index.js",

### Install
```
npm install check-data --save
npm install check-data
```

@@ -9,6 +9,29 @@

check-data支持常规模式、严格模式、宽松模式,默认使用常规模式。
> 引入严格模式和宽松模式的主要目的是为了弥补验证表达式的设计缺陷,在数组、对象结构中使用子表达式时无法声明节点自身是否允许为空值。
#### 常规模式
常规模式下默认只对allowNull为false的节点强制执行非空验证,默认对包含子表达式的数组、对象结构体执行强制非空验证。
#### 严格模式
严格模式下默认会为所有节点强制执行非空验证,除非明确声明allowNull为true。
#### 宽松模式
宽松模式下不会对包含子表达式的数组、对象结构体进行强制非空验证。
```js
let Check = require('check-data')
// 常规模式
let { error, data } = Check(data, options, extend)
// 严格模式
let { error, data } = Check.strict(data, options, extend)
// 宽松模式
let { error, data } = Check.loose(data, options, extend)
```

@@ -40,10 +63,12 @@

options数据验证表达式支持无限嵌套,不管你的数据层级有多深。整体数据结构与待验证数据结构基本保持一致,除了使用type对象表达式不得不增加额外的数据结构。
options数据验证表达式支持无限嵌套,不管你的数据层级有多深。
验证表达式中判断一个对象节点是否为验证选项的唯一依据是检查对象中是否包含type属性,如果没有type则被视为对象结构。
type作为验证表达式的内部保留关键字,应尽量避免在入参中包含同名的type属性,否则可能导致验证结果出现混乱。
当使用数组表达式时,需要区分单数和复数模式,单数时会共享同一个子表达式,通常用于验证具有相似结构的子集。复数时为精确匹配模式,可以完整定义每个子集。
整体数据结构与待验证数据结构基本保持一致,除了使用type对象表达式不得不增加额外的数据结构。验证表达式中判断一个对象节点是否为验证选项的唯一依据是检查对象中是否包含type属性,如果没有type则被视为对象结构。
options中支持值表达式,可以对表达式节点直接赋值,实现输入、输出的完全匹配或部分匹配,在用于对象动态断言时很方便。
当使用数组表达式时,需要区分单数和复数模式,单数时多个同级子节点会共用一个子表达式,通常用于验证具有相似数据结构的子集。复数时为精确匹配模式,可以完整定义每个子集。
#### 通用选项

@@ -53,18 +78,16 @@

* `default` * - 空值时的默认赋值
* `default` * - 空值时的默认赋值,优先级高于allowNull
* `set` *Function* - 赋值函数,用于对输入值处理后再输出赋值,函数中this指向原始数据data,当值为空时不执行(原method方法)
* `allowNull` *Boolean* - 是否允许为空,当值为false时强制进行非空验证。
* `value` * - 直接通过表达式赋值,类似于default选项,区别是不管值是否为空都将使用该值覆盖(优先级低于default,目前没有发现同时使用的应用场景)
* `set` *Function* - 赋值函数,用于对输入值处理后再输出赋值,函数中this指向原始数据data,当值为空时不执行。
* `allowNull` *Boolean* - 是否允许为空(默认将undefined和空字符串被视为空),缺省值为true。当值为false时,必须正确匹配指定的数据类型,否则会提示数据类型错误。
* `ignore` *Array* - 忽略指定的值,当存在匹配项时该字段不会被创建。如忽略空值,通过[null, ""]重新定义空值。
* `ignore` *Array* - 忽略指定的值,在字段级覆盖对默认空值的定义,如将某个指定字段的空值定义为[null, ""]
* `and` *Array、Function* - 声明节点的依赖关系,限制所有依赖的参数都不能为空。如参数a必须依赖参数b构成一个完整的数据,那么就要将参数名b加入到and数组中建立依赖关系。除了数组表达式外,还支持通过函数表达式动态生成依赖数组。
* `and` *Array、Function* - 声明依赖的参数名数组,支持数组和函数两种表达式,函数表达式用于声明指定值的依赖关系。要求依赖的所有参数都不能为空(注意:这里的and用于依赖判断,如参数a必须依赖参数b构成一个完整的数据,那么就要将参数b加入到and的数组中建立依赖关系)
* `or` *Array、Function* - 与and相似,区别是只要满足任意一个依赖不为空即可。
* `or` *Array、Function* - 与and相似,区别是只要求依赖的其中一个参数不为空即可
* `name` *String* - 节点名称,为参数名定义一个更易于理解的别名,在返回错误描述文本中会优先使用该别名替换属性名
* `name` *String* - 参数名称,为参数名定义一个更易于理解的别名,在返回错误描述文本中会优先使用该别名替换属性名
#### 专用选项

@@ -171,5 +194,5 @@

### schema验证器
### 可复用验证器
schema用于创建可复用的验证器,在环境允许的情况下应优先使用schema模式。
schema用于创建可复用的验证器,相比每次都将验证表达式作为一次性消耗品,schema是更好的选择,在环境允许的情况下应优先使用schema模式。

@@ -193,12 +216,7 @@ > schema的定义应该在应用启动时被执行,而不是运行时。目的是通过预先缓存一部分静态数据,从而减少运行时的内存和计算开销。

a: {
a1: {
type: Number,
allowNull: false
},
a2: {
type: Number,
allowNull: false
}
a1: String,
a2: String
},
b: Number,
b: 2,
c: Number,
})

@@ -364,2 +382,12 @@

```js
Check.use('int', {
type({ data }) {
if (Number.isInteger(data)) {
return { data }
} else {
return { error: '必须为int类型' }
}
},
})
let { mongoId, email, mobilePhone, int } = Check.types

@@ -374,5 +402,5 @@

{
"age": int,
"id": mongoId,
"mobilePhone": mobilePhone
"mobilePhone": mobilePhone,
"age": int
}

@@ -382,14 +410,21 @@ )

#### 混合示例
#### 综合示例
```js
// 输入数据
let sample = {
"username": "测试",
"name": "测试",
"num": "123456789987",
"time": "2017-07-07T09:53:30.000Z",
"files": ["abc.js", "334", "null", "666", , , "kkk.js"],
"ObjectId": "59c8aea808deec3fc8da56b6",
"files": ["abc.js", "334", "null", "666", "12"],
"user": {
"username": "莉莉",
"age": 18,
"address": [
{
"city": "深圳",
},
{
"city": "北京",
}
],
},

@@ -399,56 +434,70 @@ "list": [

"username": "吖吖",
"age": 16,
"age": {
"kk": [{ kkk: 666 }]
},
},
{
"username": "可可",
"age": 15,
"age": {
"kk": [
{ kkk: 666 },
{ kkk: 999 }
]
},
}
],
"auth": {
"weixin": "abc",
},
"beneficiariesName": "莉莉",
"guaranteeMoney": 2,
"money": "2",
"guaranteeFormat": 0,
"addressee": "嘟嘟",
"receiveAddress": "北京市",
"phone": "18666666666",
"phone": "18565799072",
"coupon": "uuuu",
"integral": {
"lala": 168,
"kaka": "3"
"lala": "168",
"kaka": 6,
},
"search": "深圳",
"email": "xxx@xx.xx"
"searchField": "userName",
"email": "xxx@xx.xx",
"arr": ['jjsd', 'ddd']
}
// 验证表达式
let { mongoId, email, mobilePhone } = Check.types
let { error, data } = Check(sample,
{
"username": {
"name": {
"type": String,
"name": "用户名",
"allowNull": false
},
"num": String,
"time": {
"type": Date,
"name": "时间",
"name": "名称",
"allowNull": false,
"default": "默认值"
},
"num": {
"type": Number,
"value": 666,
},
"ObjectId": mongoId,
"user": {
"username": String,
"username": "莉莉",
"age": Number,
"address": [
{
"city": String,
},
{
"city": "北京",
}
],
},
"list": [{
"username": String,
"age": Number,
}],
"auth": {
"weixin": String,
},
"beneficiariesName": String,
"guaranteeMoney": {
"list": [
{
"username": String,
"age": {
"kk": [{ kkk: Number }]
},
}
],
"money": {
"type": Number,
"in": [1, 2]
"min": 1,
"in": [1, 2],
},

@@ -461,17 +510,13 @@ "files": [{

"type": Number,
"conversion": Boolean
"to": Boolean,
},
"addressee": {
"type": String,
"value": "直接通过表达式赋值"
},
"search": String,
"addressee": String,
"search": "深圳",
"phone": {
"type": "MobilePhone"
"type": mobilePhone
},
"receiveAddress": String,
"coupon": {
"type": String,
set(value) {
return { "$gt": new Date() }
return { "$gt": value }
}

@@ -485,8 +530,13 @@ },

"type": Number,
"in": [1, 2, 3],
"allowNull": false,
"in": [1, 3, 8, 6],
}
},
"email": {
"type": 'Email',
"type": email,
set(value) {
return [value, , null, , undefined, 666]
}
},
"arr": [String],
},

@@ -496,16 +546,12 @@ {

return {
"email": email,
"integral": integral,
"test": {
a: 1,
},
"email": email
}
},
more({ email }) {
return [email]
},
xxx: 1,
yyy: 222
where({ email, integral }) {
return {
"integral": integral
}
}
}
)
```

@@ -6,67 +6,50 @@ "use strict"

Check.use('int', {
type({ data }) {
if (Number.isInteger(data)) {
return { data }
} else {
return { error: '必须为int类型' }
}
},
})
test(t => {
let { mongoId, email, mobilePhone, int } = Check.types
let { mongoId, email, mobilePhone } = Check.types
test(t => {
let sample = {
"id": "5687862c08d67e29cd000001",
"age": 28,
"email": "erer@gmail.com",
"mobile": "15855555547",
"mobileArr": [
"15855155547",
"18955535547",
"13055655547",
"18655655512",
"15055655512"
],
"mobileArr2": [
"13055656647",
"18655655512",
"15055699512",
"15855155547"
],
}
let { error, data } = Check(sample, {
"id": {
"type": mongoId,
"allowNull": false
let { error, data } = Check(sample,
{
"id": {
"type": mongoId,
"allowNull": false
},
"email": {
"type": email,
},
"mobile": {
"type": mobilePhone,
},
},
"age": {
"type": int,
"allowNull": false
},
"email": {
"type": email,
},
"mobile": {
"type": mobilePhone,
},
"mobileArr": [mobilePhone],
"mobileArr2": [
mobilePhone,
"18655655512",
mobilePhone,
{
type: mobilePhone,
"allowNull": false
}
]
})
{
xxx({ id, email }) {
return [id, email]
},
sss({ mobile }) {
return {
kkk: 1212,
mobile
}
},
ccc: 666
}
)
// console.log(data)
t.deepEqual(sample, data, error);
t.deepEqual({
id: '5687862c08d67e29cd000001',
email: 'erer@gmail.com',
mobile: '15855555547',
xxx: ['5687862c08d67e29cd000001', 'erer@gmail.com'],
sss: { kkk: 1212, mobile: '15855555547' },
ccc: 666
}, data, error);
});

@@ -10,3 +10,2 @@ "use strict"

"ObjectId": "59c8aea808deec3fc8da56b6",
"tenderEndTime": "2017-07-07T09:53:30.000Z",
"files": ["abc.js", "334", "null", "666", "12"],

@@ -57,2 +56,4 @@ "user": {

let { mongoId, email, mobilePhone } = Check.types
let { error, data } = Check(sample,

@@ -70,12 +71,5 @@ {

},
"tenderEndTime": {
"type": Date,
"name": "时间",
"allowNull": false,
},
"ObjectId": {
"type": "MongoId",
},
"ObjectId": mongoId,
"user": {
"username": String,
"username": "莉莉",
"age": Number,

@@ -87,3 +81,3 @@ "address": [

{
"city": String,
"city": "北京",
}

@@ -98,5 +92,2 @@ ],

},
},
{
"allowNull": false,
}

@@ -106,4 +97,4 @@ ],

"type": Number,
// "min": 15,
// "in": [1, 2],
"min": 1,
"in": [1, 2],
},

@@ -113,3 +104,3 @@ "files": [{

"allowNull": false,
}, false],
}],
"guaranteeFormat": {

@@ -120,8 +111,5 @@ "type": Number,

"addressee": String,
"search": {
"type": String,
// "or": ["searchField"],
},
"search": "深圳",
"phone": {
"type": "MobilePhone"
"type": mobilePhone
},

@@ -145,3 +133,3 @@ "coupon": {

"email": {
"type": 'Email',
"type": email,
set(value) {

@@ -185,6 +173,8 @@ return [value, , null, , undefined, 666]

// console.log(data)
test(t => {
t.truthy(error, data);
t.truthy(data , error);
});

@@ -6,19 +6,20 @@ "use strict"

let schema = Check.schema({
a: {
a1: {
type: Number,
allowNull: false
},
a2: {
type: Number,
allowNull: false
}
},
b: Boolean,
})
test(t => {
test('常规', t => {
let schema = Check.schema({
a: {
a1: {
type: Number,
allowNull: false
},
a2: {
type: Number,
allowNull: false
}
},
b: Boolean,
})
let sample = {

@@ -38,2 +39,66 @@ a: {

});
test('strict', t => {
let schema = Check.schema({
a: {
a1: {
type: Number
},
a2: {
type: Number,
allowNull: true
}
},
b: Boolean,
})
let sample = {
a: {
a1: 4545,
// a2: 888,
},
b: false
}
let { error, data } = schema.strict(sample)
// console.log(data)
t.deepEqual(sample, data, error);
});
test('loose', t => {
let schema = Check.schema({
a: {
a1: {
type: Number,
},
a2: {
type: Number,
allowNull: false
}
},
b: Boolean,
})
let sample = {
a: {
a1: 4545,
a2: 888,
},
b: false
}
let { error, data } = schema.loose(sample)
// console.log(data)
t.deepEqual(sample, data, error);
});

@@ -18,6 +18,7 @@ "use strict"

and({ data, option, origin }) {
// 如果option为函数,应先执行函数,将函数转为数组
// option为函数时先执行函数,将函数转为数组表达式
if (option instanceof Function) {
option = option.call(origin, data)
}
// 数组表达式
if (option instanceof Array) {

@@ -218,3 +219,4 @@ for (let name of option) {

// 合并公共方法
// 将common与内置构造函数key中方法合并
for (let key in types) {

@@ -224,2 +226,8 @@ Object.assign(types[key], common)

// 将common与Symbol key中方法合并(for/in 无法遍历symbol key,需要单独处理)
for (let name in symbols) {
let symbol = symbols[name]
Object.assign(types[symbol], common)
}
module.exports = types
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