diff --git a/README.md b/README.md index 99cb4c1..977c7c3 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ $ npm install parameter --save - `options.translate` - translate function - `options.validateRoot` - config whether to validate the passed in value must be a object, default to `false`. - `options.convert` - convert primitive params to specific type, default to `false`. + - `optinos.widelyUndefined` - convert empty string(`''`), NaN, Null to undefined, this option can make `rule.required` more powerful, default to `false`.__This may change the original input params__. - `validate(rule, value)` - validate the `value` conforms to `rule`. return an array of errors if break rule. - `addRule(type, check)` - add custom rules. - `type` - rule type, required and must be string type. @@ -79,6 +80,7 @@ var errors = parameter.validate(rule, data); - `required` - if `required` is set to false, this property can be null or undefined. default to `true`. - `type` - The type of property, every type has it's own rule for the validate. - `convertType` - Make parameter convert the input param to the specific type, support `int`, `number`, `string` and `boolean`, also support a function to customize your own convert method. +- `default` - The default value of property, once the property is allowed non-required and missed, parameter will use this as the default value. __This may change the original input params__. __Note: you can combile require and type end with a notation `?` like: `int?` or `string?` to specific both type and non-required.__ diff --git a/index.js b/index.js index 0ccfb82..b2f83d3 100644 --- a/index.js +++ b/index.js @@ -32,6 +32,7 @@ class Parameter { if (opts.validateRoot) this.validateRoot = true; if (opts.convert) this.convert = true; + if (opts.widelyUndefined) this.widelyUndefined = true; } t() { @@ -70,6 +71,13 @@ class Parameter { for (var key in rules) { var rule = formatRule(rules[key]); var value = obj[key]; + + // treat null / '' / NaN as undefined + if (this.widelyUndefined && + (value === '' || value === null || Number.isNaN(value))) { + value = obj[key] = undefined; + } + var has = value !== null && value !== undefined; if (!has) { @@ -80,6 +88,10 @@ class Parameter { code: this.t('missing_field') }); } + // support default value + if (rule.default) { + obj[key] = rule.default; + } continue; } diff --git a/test/index.test.js b/test/index.test.js index bcdae50..99c98e0 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -13,6 +13,10 @@ var parameterWithConvert = new Parameter({ convert: true, }); +var parameterWithWidelyUndefined = new Parameter({ + widelyUndefined: true, +}); + describe('parameter', function () { describe('required', function () { it('should required work fine', function () { @@ -1015,4 +1019,81 @@ describe('validate with options.convert', function() { should.not.exist(res); value.int.should.equal(1); }); + + describe('validate with options.widelyUndefined', function () { + it('should convert null / NaN / "" to undefiend', function() { + var value = { + number: NaN, + string: '', + date: null, + foo: 'test string', + bar: 123, + }; + var res = parameterWithWidelyUndefined.validate({ + number: 'number?', + string: 'string?', + date: 'date?', + foo: 'string', + bar: 'int', + }, value); + should.not.exist(res); + value.should.eql({ + number: undefined, + string: undefined, + date: undefined, + foo: 'test string', + bar: 123, + }); + }); + }); + + describe('default', function() { + it('should default work', function () { + var value = { + string: '', + foo: null, + bar: 123, + }; + var res = parameter.validate({ + string: { type: 'string?', default: 'string' }, + foo: { type: 'string?', default: 'foo' }, + bar: { type: 'int?', default: 1200 }, + hello: { type: 'string?', default: 'world' }, + }, value); + should.not.exist(res); + value.should.eql({ + string: '', // notice: string '' is not undefined here + foo: 'foo', + bar: 123, + hello: 'world', + }); + }); + + it('should default work with widelyUndefined', function() { + var value = { + number: NaN, + string: '', + date: null, + foo: 'test string', + bar: 123, + }; + var res = parameterWithWidelyUndefined.validate({ + number: { type: 'number?', default: 100 }, + string: { type: 'string?', default: 'string' }, + date: { type: 'date?', default: 100 }, + foo: { type: 'string?', default: 'foo' }, + bar: { type: 'int?', default: 1200 }, + hello: { type: 'string?', default: 'world' }, + }, value); + should.not.exist(res); + value.should.eql({ + number: 100, + string: 'string', + date: 100, + foo: 'test string', + bar: 123, + hello: 'world', + }); + }); + }); });