UNPKG

5.35 kBJavaScriptView Raw
1/**
2 * @copyright Copyright (c) 2019 Maxim Khorin <maksimovichu@gmail.com>
3 */
4'use strict';
5
6const Base = require('../base/Base');
7
8module.exports = class Validator extends Base {
9
10 static getConstants () {
11 return {
12 BUILTIN: {
13 'boolean': require('./BooleanValidator'),
14 'checkbox': require('./CheckboxValidator'),
15 'compare': require('./CompareValidator'),
16 'date': require('./DateValidator'),
17 'default': require('./DefaultValueValidator'),
18 'each': require('./EachValidator'),
19 'email': require('./EmailValidator'),
20 'exist': require('./ExistValidator'),
21 'file': require('./FileValidator'),
22 'filter': require('./FilterValidator'),
23 'image': require('./ImageValidator'),
24 'inline': require('./InlineValidator'),
25 'id': require('./IdValidator'),
26 'ip': require('./IpValidator'),
27 'json': require('./JsonValidator'),
28 'number': require('./NumberValidator'),
29 'range': require('./RangeValidator'),
30 'regex': require('./RegexValidator'),
31 'required': require('./RequiredValidator'),
32 'relation': require('./RelationValidator'),
33 'safe': require('./SafeValidator'),
34 'spawn': require('./SpawnValidator'),
35 'string': require('./StringValidator'),
36 'unique': require('./UniqueValidator'),
37 'unsafe': require('./UnsafeValidator'),
38 'url': require('./UrlValidator')
39 }
40 };
41 }
42
43 static createValidator (type, model, attrs, config = {}) {
44 if (Object.prototype.hasOwnProperty.call(this.BUILTIN, type)) {
45 type = this.BUILTIN[type];
46 } else if (typeof type === 'function' || typeof model[type] === 'function') {
47 if (!(type.prototype instanceof Validator)) {
48 config.method = type;
49 type = this.BUILTIN.inline;
50 }
51 } else if (type) {
52 Object.assign(config, type);
53 type = type.Class;
54 }
55 if (!type || !(type.prototype instanceof Validator)) {
56 throw new Error('Invalid type');
57 }
58 config.attrs = Array.isArray(attrs) ? attrs : [attrs];
59 config.module = model.module;
60 return new type(config);
61 }
62
63 constructor (config) {
64 super({
65 // on: [] // only scenarios
66 // except: [] // excepted scenarios
67 attrs: [],
68 skipOnError: true,
69 skipOnAnyError: false,
70 skipOnEmpty: true,
71 when: null, // (model, attr) => false/true
72 isEmpty: null, // value => false/true
73 messageSource: 'app',
74 defaultMessageSource: 'areto',
75 ...config
76 });
77 }
78
79 createMessage (message, defaultMessage, params) {
80 if (message instanceof Message) {
81 return message.addParams(params);
82 }
83 if (message) {
84 return new Message(message, params, this.messageSource);
85 }
86 if (defaultMessage instanceof Message) {
87 return defaultMessage.addParams(params);
88 }
89 return new Message(defaultMessage, params, this.defaultMessageSource);
90 }
91
92 async validateModel (model, attrs) {
93 attrs = Array.isArray(attrs)
94 ? ArrayHelper.intersect(attrs, this.attrs)
95 : this.attrs;
96 attrs = attrs.filter(attr => {
97 return (!this.skipOnAnyError || !model.hasError())
98 && (!this.skipOnError || !model.hasError(attr))
99 && (!this.skipOnEmpty || !this.isEmptyValue(model.get(attr)))
100 && (typeof this.when !== 'function' || this.when(model, attr));
101 });
102 for (const attr of attrs) {
103 await this.validateAttr(attr, model);
104 }
105 }
106
107 async validateAttr (attr, model) {
108 const message = await this.validateValue(model.get(attr));
109 if (message) {
110 this.addError(model, attr, message);
111 }
112 }
113
114 validateValue () {
115 throw new Error('Need to override');
116 }
117
118 isActive (scenario) {
119 return scenario
120 ? (!this.except || !this.except.includes(scenario)) && (!this.on || this.on.includes(scenario))
121 : !this.on;
122 }
123
124 isEmptyValue (value) {
125 return typeof this.isEmpty === 'function'
126 ? this.isEmpty(value)
127 : value === undefined || value === null || value === '';
128 }
129
130 addError (model, attr, message) {
131 const value = model.get(attr);
132 message.addParams({
133 attr: model.getAttrLabel(attr),
134 value: Array.isArray(value) ? value.join() : value
135 });
136 model.addError(attr, message);
137 }
138
139 log () {
140 CommonHelper.log(this.module, this.constructor.name, ...arguments);
141 }
142};
143module.exports.init();
144
145const CommonHelper = require('../helper/CommonHelper');
146const ArrayHelper = require('../helper/ArrayHelper');
147const Message = require('../i18n/Message');
\No newline at end of file