UNPKG

21.9 kBMarkdownView Raw
1# Validation Library
2
3[![NPM version][npm-image]][npm-url]
4[![build status][travis-image]][travis-url]
5[![Known Vulnerabilities](https://snyk.io/test/npm/node-input-validator/badge.svg)](https://snyk.io/test/npm/node-input-validator)
6[![Coverage Status][codecov-img]][codecov-url]
7[![David deps][david-image]][david-url]
8[![node version][node-image]][node-url]
9
10[travis-image]: https://api.travis-ci.org/bitnbytesio/node-input-validator.svg?branch=master
11[travis-url]: https://travis-ci.org/bitnbytesio/node-input-validator?branch=master
12
13[codecov-img]: https://codecov.io/gh/bitnbytesio/node-input-validator/branch/master/graph/badge.svg
14[codecov-url]: https://codecov.io/gh/bitnbytesio/node-input-validator
15
16[david-image]: https://david-dm.org/bitnbytesio/node-input-validator.svg?style=flat-square&branch=master
17[david-url]: https://david-dm.org/bitnbytesio/node-input-validator?branch=master
18
19[npm-image]: https://img.shields.io/npm/v/node-input-validator.svg?style=flat-square
20[npm-url]: https://www.npmjs.com/package/node-input-validator
21[node-image]: https://img.shields.io/badge/node.js-%3E=_8.16-green.svg?style=flat-square
22[node-url]: http://nodejs.org/download/
23
24Validation library for node.js
25
26NIV (Node Input Validator) is a validation library for node.js. You can also extend library to add custom rules.
27
28**Note**: For use case of any rule, please check test cases, If you have any doubt or confusion with documentation or rule behaviour.
29
30## Installation
31
32```shell
33npm i node-input-validator
34```
35
36## Features
37
38- large collection of rules
39- add your own custom rules
40- supports nested inputs
41- declare rules as strings or array
42- post validation rules
43- modify or add new messages in your own language
44- change attribute names globally or locally
45- current supported languages: English, Persian(farsi)
46
47## Usage
48
49- [Example](#simple-example)
50- [With express](#with-in-express-application)
51- [With async/await](#with-async-await)
52- [Koa middleware](#for-koa2)
53- [Object validation examples](#objects-validation)
54- [Array validation examples](#array-validation)
55- [Add/Modify messages](#add-or-modify-messages)
56- [Change default language examples](#set-default-language)
57- [Toggle multiple errors](#toggle-multiple-errors-support)
58- [Change attribute names in messages examples](#set-attribute-nicecustom-name)
59- [Add custom rules](#add-your-own-custom-validation-rules)
60- [Rules](#rules)
61
62### Simple Example
63
64```javascript
65const { Validator } = require('node-input-validator');
66
67const v = new Validator(
68 { name: '' },
69 { name: 'required|minLength:5' },
70);
71
72v.check().then(function (matched) {
73 console.log(matched);
74 console.log(v.errors);
75});
76```
77
78### With in express application
79
80```javascript
81const { Validator } = require('node-input-validator');
82
83app.post('login', function (req, res) {
84 const v = new Validator(req.body, {
85 email: 'required|email',
86 password: 'required'
87 });
88
89 v.check().then((matched) => {
90 if (!matched) {
91 res.status(422).send(v.errors);
92 }
93 });
94});
95```
96
97### With async-await
98
99```javascript
100const { Validator } = require('node-input-validator');
101
102router.post('login', async (ctx) => {
103 const v = new Validator(ctx.request.body, {
104 email: 'required|email',
105 password: 'required'
106 });
107
108 const matched = await v.check();
109
110 if (!matched) {
111 ctx.status = 422;
112 ctx.body = v.errors;
113 return;
114 }
115});
116```
117
118### For Koa2
119
120#### Attach koa middleware
121
122```javascript
123const niv = require('node-input-validator');
124
125// keep this under your error handler
126app.use(niv.koa());
127```
128
129#### Then in controller
130
131```javascript
132// if validation fails, this will auto abort request with status code 422 and errors in body
133await ctx.validate({
134 name: 'required|maxLength:50',
135 username: 'required|maxLength:15',
136 email: 'required|email',
137 password: 'required'
138});
139
140// validation passes
141// do some code
142```
143
144#### With custom inputs
145
146```javascript
147// if validation fails, this will auto abort request with status code 422 and errors in body
148await ctx.validate({
149 name: 'required|maxLength:50',
150 username: 'required|maxLength:15',
151 email: 'required|email',
152 password: 'required'
153}, ctx.request.body);
154
155// validation passes
156// do some code
157```
158
159#### With custom inputs and custom messages
160
161```javascript
162// if validation fails, this will auto abort request with status code 422 and errors in body
163await ctx.validate({
164 name: 'required|maxLength:50',
165 username: 'required|maxLength:15',
166 email: 'required|email',
167 password: 'required'
168}, ctx.request.body, { email: 'E-mail is required' });
169
170// validation passes
171// do some code
172```
173
174#### In case you wants control over validator, Then use
175
176```javascript
177// if validation fails, this will auto abort request with status code 422 and errors in body
178const v = await ctx.validator(ctx.request.body, {
179 name: 'required|maxLength:50',
180 username: 'required|maxLength:15',
181 email: 'required|email',
182 password: 'required'
183});
184
185// in case validation fails
186if (v.fails()) {
187 ctx.status = 422;
188 ctx.body = v.errors;
189 return;
190}
191
192// do some code
193```
194
195##### This method (ctx.validator(inputs, rules, messages={})) also support same options as like ctx.validate
196
197### Objects Validation
198
199#### Example 1
200
201```javascript
202const v = new Validator(
203 {
204 product: {
205 id: '1',
206 name: '',
207 price: '',
208 active: 'yes',
209 }
210 },
211 {
212 'product': 'required|object',
213 'product.id': 'required|integer',
214 'product.name': 'required',
215 'product.price': 'required|integer',
216 'product.active': 'required|integer'
217 },
218);
219
220const matched = await v.check();
221```
222
223### Array Validation
224
225#### Example 1
226
227```javascript
228let v = new Validator(
229 {
230 roles: ['admin', 'manager', 'member']
231 },
232 {
233 'roles': 'required|array',
234 'roles.*': 'required|string'
235 },
236);
237
238let matched = await v.check();
239```
240
241#### Example 2
242
243```javascript
244let v = new Validator(
245 {
246 plan: [
247 { price: '25', title: 'OK' },
248 { price: '', title: '' },
249 { price: '30' },
250 { price: '', title: 'Title' }
251 ]
252 },
253 {
254 'plan': 'required|array',
255 'plan.*.price': 'required|integer',
256 'plan.*.title': 'required'
257 },
258);
259let matched = await v.check();
260```
261
262### Add or Modify messages
263
264Placeholder in messages, :attribute will be replaced with field/attribute name, :value with field value and :arg0, :arg1 ...n with arguments passed to rule.
265
266#### Add/Update rule based messages
267
268```javascript
269const niv = require('node-input-validator');
270/**
271 * @param {Object} messages
272 * @param {string?=en} language
273 */
274niv.extendMessages({
275 required: 'The :attribute field must not be empty.',
276 email: 'E-mail must be a valid email address.',
277 even: 'The value of the field must be even number.',
278 status: 'Invalid status'
279}, 'en');
280```
281
282#### Add custom messages
283
284```javascript
285const niv = require('node-input-validator');
286//Note: Default language is English (en).
287niv.customMessages({
288 'username.required': 'When username attribute required rule failed.',
289 username: 'Default message for username attribute.'
290});
291```
292
293#### for message in another language
294
295You can easliy add messages in another language.
296
297```javascript
298const niv = require('node-input-validator');
299niv.extendMessages({
300 required: ':attribute ਫੀਲਡ ਖਾਲੀ ਨਹੀਂ ਹੋਣਾ ਚਾਹੀਦਾ.',
301}, 'pb');
302```
303
304### Set default language
305
306```javascript
307const niv = require('node-input-validator');
308niv.setLang('pb');
309```
310
311### Toggle Multiple Errors Support
312
313By default, Validator will run in bailable mode ie. break if some rule failed. You can change this behaviour:
314
315#### Globally
316
317```javascript
318const niv = require('node-input-validator');
319niv.bailable(false);
320```
321
322Now instead of breaking, it will continues apply other rules.
323
324#### Errors example
325
326```javascript
327{
328 name: [
329 {
330 rule: 'minLength',
331 message: '...',
332 },
333 {
334 rule: 'alpha',
335 message: '...',
336 }
337 ]
338}
339```
340
341#### Locally
342
343To toggle multiple errors on specific instance only.
344
345```javascript
346const niv = require('node-input-validator');
347const v = new niv.Validator(inputs, rules);
348v.bail(false);
349```
350
351### Set attribute nice/custom name
352
353You can also declare Nice Names / Custom Attributes names.
354
355```javascript
356const niv = require('node-input-validator');
357niv.niceNames({
358 phone: 'phone number',
359 dob: 'Date of Birth'
360});
361```
362
363If your are editing other languages, set lang parameter.
364
365```javascript
366const niv = require('node-input-validator');
367niv.niceNames({
368 phone: 'phone number',
369 dob: 'Date of Birth'
370},'fa');
371```
372
373In error messages you will get "phone number" instead of phone. For Example: In case required rule failed, Error message will be: The phone number field is mandatory.
374
375#### For current instance only
376
377```javascript
378const niv = require('node-input-validator');
379
380const v = new niv.Validator(inputs, rules);
381v.niceNames({
382 phone: 'phone number',
383 dob: 'Date of Birth'
384});
385```
386
387This will only change attribute names for current instance.
388
389### Add your own custom validation rules
390
391```javascript
392// second params will be the instance of Validator
393niv.extend('even', ({ value }) => {
394 if ((parseInt(value) % 2) == 0) {
395 return true;
396 }
397 return false;
398});
399```
400
401#### Example of using other fileds in rule
402
403```javascript
404const niv = require('node-input-validator');
405
406niv.extend('sumOfFields', ({ value, args }, validator) => {
407 if (args.length !== 2) {
408 throw new Error('Invalid seed for rule sumOfFields');
409 }
410
411 const anotherValue = Number(validator.inputs[args[0]]);
412
413 const eq = Number(args[1]);
414
415 if ((Number(value) + anotherValue) !== eq) {
416 return false;
417 }
418
419 return true;
420});
421
422let v = new niv.Validator(
423 { num1: '50', num2: '50' },
424 { num1: 'sumOfFields:num2,100|required' },
425);
426
427let matched = await v.check();
428
429assert.equal(matched, true);
430```
431
432#### Example of using async rules
433
434```javascript
435// use this rules as unique:seed
436// unique:<Mongoose Model>,<Field Name>,<ID to Ignore, This is optional>
437
438const niv = require('node-input-validator');
439const mongoose = require('mongoose');
440
441niv.extend('unique', async ({ value, args }) => {
442 // default field is email in this example
443 const filed = args[1] || 'email';
444
445 let condition = {};
446
447 condition[filed] = value;
448
449 // add ignore condition
450 if (args[2]) {
451 condition['_id'] = { $ne: mongoose.Types.ObjectId(args[2]) };
452 }
453
454 let emailExist = await mongoose.model(args[0]).findOne(condition).select(field);
455
456 // email already exists
457 if (emailExist) {
458 return false;
459 }
460
461 return true;
462});
463
464// example usage of upper extended rule
465
466new niv.Validator({
467 email: 'required|email|unique:User,email'
468}, inputs);
469
470// in case to ignore specific id
471
472new niv.Validator({
473 email: 'required|email|unique:User,email,5c2f29e9cefa7718a54f8ff1'
474}, inputs);
475```
476
477## Rules
478
479You can check test cases for rule usage/examples.
480
481**required**
482The field under validation cannot be left blank.
483
484```javascript
485// should fail
486new Validator(
487 { name: '' },
488 { name: 'required' },
489);
490```
491
492**requiredIf:field,value**
493The field under validation cannot be left blank, if provided seed value equals to provided value seed.
494
495```javascript
496// requiredIf rule validation fails, becoz email cannot be left blank if age is 16
497new Validator(
498 { email: '', age: '16' },
499 { email: 'requiredIf:age,16' },
500);
501```
502
503**requiredNotIf:field,value**
504The field under validation may left blank, if provided seed value equals to provided value seed.
505
506```javascript
507// requiredNotIf rule validation fails, becoz transport must be present in case age is not 16
508new Validator(
509 { transport: '', age: '15' },
510 { transport: 'requiredNotIf:age,16' },
511);
512```
513
514**requiredWith:field**
515**requiredWith:field,field,field**
516 The field under validation may required in case provided seed present.
517
518```javascript
519// requiredWith rule validation fails, becoz email must in case age present.
520new Validator(
521 { email: '', age: '17' },
522 { email: 'requiredWith:age' },
523);
524```
525
526**requiredWithout:field**
527**requiredWithout:field,field,field**
528The field under validation may left blank in case provided seed present.
529
530```javascript
531// requiredWithout rule validation fails, becoz email is must in case phone,pan not provided.
532new Validator(
533 { email: '', username: '' },
534 { email: 'requiredWithout:phone,pan', username: 'requiredWithout:email' },
535);
536```
537
538**accepted**
539The field under validation must be yes, on, 1, or true.
540
541**accepted:seeds**
542The field under validation must be accepted if value exists in provided seed.
543
544**after:YYYY-MM-DD**
545The field under validation must be date after provided seed.
546
547```javascript
548new Validator(
549 { joining: '' },
550 { joining: 'required|after:2018-02-10' },
551);
552```
553
554**alpha**
555The field under validation must be entirely alphabetic characters.
556
557**alphaDash**
558The field under validation may have alpha-numeric characters, as well as dashes and underscores.
559
560**alphaNumeric**
561The field under validation only contains letters and numbers.
562
563**array**
564The field under validation must be an array.
565
566**arrayUnique**
567<sub>Added in: v3.5</sub>
568The field under validation must be an array and must contains unique values. No need to use array rule. This rule will take care of that.
569
570**arrayUniqueObjects:attributes**
571<sub>Added in: v3.5</sub>
572The field under validation must be an array and should have objects with unique attributes as per seed. No need to use array rule. This rule will take care of that.
573
574**ascii**
575The field under validation only contains ascii characters.
576
577**base64**
578The field under validation must be valid base64 encoded string.
579
580**between:min,max**
581The field under validation must be betwwen min and max seed. This will work with number valus as well as with arrays using array count.
582
583**boolean**
584**boolean:custom**
585The field under validation must be boolean (true, false, 'true', 'false', 0, 1, '0', '1') or in custom seed.
586
587**contains:value**
588The field under validation must contains provided seeds.
589
590```javascript
591let v = new Validator({bio:'My profile is: example.com'}, {bio:'required|contains:profile'});
592```
593
594**creditCard**
595The field under validation must be valid credit card string.
596
597**date**
598The field under validation must be a valid date (YYYY-MM-DD).
599
600**dateAfterToday:number,unit**
601The field under validation must be a valid date after provided seed.
602
603```javascript
604new Validator(
605 { expiry: '2019-02-28' },
606 { expiry: 'required|dateAfterToday:2,days' },
607);
608```
609
610see moment docs(https://momentjs.com/docs/#/manipulating/add/) for supported units.
611
612**dateBeforeToday:number,unit**
613The field under validation must be a valid date before provided seed.
614
615```javascript
616let v = new Validator({valid:'2019-02-28'}, {valid:'required|dateBeforeToday:2,months'});
617```
618
619**dateFormat:format**
620The field under validation must match the given date format.
621
622Note: use array of rules style declaration to deal with colon (:) in time formats.
623
624```javascript
625new Validator(
626 { dob: '' },
627 { dob: 'required|dateFormat:YYYY-MM-DD' },
628);
629```
630
631Check https://momentjs.com/docs/ for supported formats
632
633**dateiso**
634<sub>Added in: v3.6</sub>
635The field under validation must be a valid iso date.
636
637**datetime**
638<sub>Added in: v3.6</sub>
639The field under validation must match YYYY-MM-DD HH:mm:ss format.
640
641**decimal**
642The field under validation must be a decimal value.
643
644**digits:length**
645The field under validation must be numeric and must have an exact length.
646
647**digitsBetween:min,max**
648The field under validation must have a length between provided min and max values.
649
650**domain**
651The field under validation must a qualified domain.
652
653**dimensions:seed**
654<sub>Added in: v3.7</sub>
655The image under validation must meet the dimension constraints as specified by in seed.
656
657```js
658new Validator(
659 req.body,
660 { file: 'dimensions:minWidth=50,minHeight=50' },
661);
662
663const matched = await v.check();
664
665assert.equal(matched, false);
666```
667
668Note: image mimes validation is required before.
669
670Available constraints are: minWidth, maxWidth, minHeight, maxHeight, width, height.
671
672**email**
673The field under validation must be formatted as an e-mail address.
674
675**equals**
676The field under validation must be equal to given value.
677
678**gt:another_field**
679<sub>Added in: v3.4</sub>
680The field under validation must be greater then another field value. This rule is for Numbers comparision.
681
682**gte:another_field**
683<sub>Added in: v3.4</sub>
684The field under validation must be greater or equals to another field value. This rule is for Numbers comparision.
685
686**hash:algo**
687The field under validation must be a valid hash as per provided seed.
688
689```javascript
690new Validator(
691 {
692 id: 'fd1baf48377a9f644f9af89abbee29f6'
693 },
694 {
695 id: 'required|hash:md5'
696 },
697);
698```
699
700Supported algorithms: md4, md5, sha1, sha256, sha384, sha512, ripemd128, ripemd160, tiger128, tiger160, tiger192, crc32, crc32b.
701
702**hex**
703The field under validation must be valid hex.
704
705**hexColor**
706The field under validation must be valid hex color code.
707
708**in:a,b...n**
709The field under validation must exist in the given list of values.
710
711```javascript
712new Validator(
713 { status: '' },
714 { status: 'required|in:active,inactive,blocked' },
715);
716```
717
718**integer**
719The field under validation must be an integer.
720
721**ip**
722The field under validation must be an IP address.
723
724**iso8601**
725The field under validation must be valid Iso8601 date.
726
727**json**
728The field under validation must be a valid JSON string.
729
730**length:max**
731**length:max,min**
732<sub>Added in: v3.5</sub>
733The field under validation must be less then or equals to max seed provided in rule. In case of min,max seed, field under validation must be less or equals to max seed and less then min seed. Can only be used with strings|arrays or any other object that supports length (str.length) property.
734
735**latLong**
736The field under validation must be a valid latitude-longitude coordinate.
737
738**lengthBetween:min,max**
739The field under validation value length must be between provided values.
740
741```javascript
742let v = new Validator({age:''}, {age:'required|between:17,30'});
743```
744
745**lt:another_field**
746<sub>Added in: v3.4</sub>
747The field under validation must be less then another field value. This rule is for Numbers comparision.
748
749**lte:another_field**
750<sub>Added in: v3.4</sub>
751The field under validation must be less or equals to another field value. This rule is for Numbers comparision.
752
753**macAddress**
754The field under validation should be a valid Mac Address.
755
756**max:seed**
757The field under validation must be less than given value.
758
759```javascript
760new Validator(
761 { age: '' },
762 { age: 'required|max:35' },
763);
764```
765
766**maxLength:seed**
767The length of field under validation should be less than given value.
768
769```javascript
770new Validator(
771 { username: '' },
772 { username: 'required|max:10' },
773);
774```
775
776**mime:seed**
777The file under validation must have a MIME type corresponding to one of the listed extensions.
778
779```javascript
780new Validator(
781 req.body,
782 { file: 'required|mime:jpg,png' },
783);
784```
785
786**min**
787The field under validation must be greater than given value.
788
789**minLength**
790The length of field under validation should be greater than given value.
791
792**mongoId**
793The field under validation should be a valid MongoDB ID.
794
795**notContains:seed**
796The field under validation may not contains provided seeds.
797
798**notIn:seeds**
799The field under validation must not exist in the given list of values.
800
801**nullable**
802The field under validation is required only is not left empty.
803
804**numeric**
805The field under validation must be numeric.
806
807**phoneNumber**
808The field under validation must be a valid phone number.
809
810**regex**
811The field under validation must match the given regular expression.
812
813Note: Currently regex rules break on using colon (:) or pipe delimiters. Use array of rules style declaration instead of string.
814
815```javascript
816new Validator(
817 req.body,
818 { username: ['required', 'regex:[a-z]'] },
819 { password: 'required|same:confirm_password' },
820);
821```
822
823**same**
824The given field must match the field under validation.
825
826**size:max**
827**size:max,min**
828The file field under validation must have a file size matching the given maximum value or should be between size range.
829Supported unit sufix: b(Bytes),kb/k(KilloBytes),mb/m(MegaBytes),gb/g(GigaBytes).
830
831```javascript
832// in below case, image file size should be under 4kb limit
833new Validator({image:''}, {image:'required|size:4kb'});
834```
835
836```javascript
837// in below case, image file size should be between 1kb - 4kb
838new Validator({image:''}, {image:'required|size:4kb,1kb'});
839```
840
841```javascript
842new Validator({video:''}, {video:'required|size:10mb'});
843```
844
845**sometimes**
846The field under validation is required if present.
847
848**string**
849The field under validation must be string.
850
851**url**
852The field under validation must be a valid URL.
853
854**Post Rules**
855There is set of rules which can be used to validate constraints of whole input, rather than validity of singular fields.
856
857```javascript
858const v = new Validator(
859 { name: '' },
860 { '*': 'any:name,surname' },
861);
862
863v.check().then(function (matched) {
864 console.log(matched);
865 console.log(v.errors);
866});
867```
868
869Post validator errors are returned in the `*` key. There is also possibility to add custom function as validator
870with help of `addPostRule` method. Function will be called in context of validator object with input as parameter.
871
872```javascript
873const v = new Validator(
874 { username: 'arnold', password: 'arnold123' },
875 { username: 'required', password: 'required' },
876);
877
878v.addPostRule((provider) => {
879 if (provider.inputs.password.indexOf(provider.inputs.username) >= 0) {
880 provider.error('password', 'custom', 'Password cannot contain username');
881 }
882});
883```
884
885**any**
886Any of the fields must be present in input.
887
888**all**
889All of the fields must be present in input.
890
891### Typescript Support
892
893Partial Support.