@chantouchsek/validatorjs
Advanced tools
Comparing version 1.2.3 to 1.3.0
@@ -5,2 +5,26 @@ # Changelog | ||
## [1.3.0](https://github.com/chantouchsek/validatorjs/compare/v1.2.3...v1.3.0) (2023-09-20) | ||
### Features | ||
* :sparkles: added new option to accept none attribute of the message ([cec017c](https://github.com/chantouchsek/validatorjs/commit/cec017cdf0b787693672dc78f905077e708c0bc1)) | ||
* :sparkles: added nullable rule ([9ee951a](https://github.com/chantouchsek/validatorjs/commit/9ee951ae83669f2cc1c9952f2e5331314d5cf82f)) | ||
### Bug Fixes | ||
* :art: fix styling by (eslint) ([9a5ff3a](https://github.com/chantouchsek/validatorjs/commit/9a5ff3a53f832759e3d1d7cfb4e3ffc92fda54bc)) | ||
* :art: style commit self ([8ec1525](https://github.com/chantouchsek/validatorjs/commit/8ec15254444e59b0888be67cb7d46f23b62a481d)) | ||
* :beers: make test import from vite directly ([24d4869](https://github.com/chantouchsek/validatorjs/commit/24d4869f5d34b0f310044c474c2c9806630f4e4a)) | ||
* :bug: correct index of message with nested array object ([04383af](https://github.com/chantouchsek/validatorjs/commit/04383affdb53852d2d640f291b2c6464747c2d4c)) | ||
* :bug: correct test:watch ([44464ea](https://github.com/chantouchsek/validatorjs/commit/44464ea31d609e6a4e293d753b4b20af4090e78d)) | ||
* :bug: remove the private from functions ([0833d7a](https://github.com/chantouchsek/validatorjs/commit/0833d7ad95a945ca9a9d95e998ba7a7008fa9696)) | ||
* :bug: remove unused packages ([d4a55e7](https://github.com/chantouchsek/validatorjs/commit/d4a55e7083372eb1b616f0e32f511baa50566ae9)) | ||
* :bug: remove warn log ([9195487](https://github.com/chantouchsek/validatorjs/commit/919548775722eaf095e57c0254cc403fd5f4400f)) | ||
* :fire: completely remove prettier ([1ae36cd](https://github.com/chantouchsek/validatorjs/commit/1ae36cd81aefa86b06f56a5b19f089eb6034745a)) | ||
* :penicl2: remove unused const properties ([4d86528](https://github.com/chantouchsek/validatorjs/commit/4d865282d272659147be7f3411d681d60ac4fb3d)) | ||
* :rocket: use antfu/eslint-config ([3fc8d3d](https://github.com/chantouchsek/validatorjs/commit/3fc8d3d0df6ba006e0a1f94b33a9988a7f5e891a)) | ||
* **deps:** bump actions/checkout from 3 to 4 ([90b04f3](https://github.com/chantouchsek/validatorjs/commit/90b04f3a52960c4e1e62c7e586cbd027fd65687c)) | ||
### [1.2.3](https://github.com/chantouchsek/validatorjs/compare/v1.2.2...v1.2.3) (2023-08-26) | ||
@@ -7,0 +31,0 @@ |
@@ -41,5 +41,4 @@ export default class AsyncResolvers { | ||
return; | ||
if (this.isAllResolved()) { | ||
if (this.isAllResolved()) | ||
this.onResolvedAll(this.failed.length === 0); | ||
} | ||
} | ||
@@ -46,0 +45,0 @@ enableFiring(firing = true) { |
import type { SimpleObject } from './types'; | ||
export default class Errors { | ||
private errors; | ||
add(attribute: string, message: string): void; | ||
add(field: string, message: string | string[], forceUpdate?: boolean): void; | ||
missed(field: string | string[]): boolean; | ||
get(field: string | string[]): string | string[]; | ||
first(attribute: string): string | undefined; | ||
get(field: string | string[]): string[]; | ||
first(field: string | string[]): string; | ||
all(): SimpleObject<string[]>; | ||
has(field: string | string[]): boolean; | ||
fill(errors: Record<string, string[]>): void; | ||
fill(errors: SimpleObject<string[]>): void; | ||
clear(attribute?: string | string[]): void; | ||
flush(): void; | ||
onKeydown(event: KeyboardEvent): void; | ||
private _getFields; | ||
} |
@@ -1,11 +0,15 @@ | ||
import { cloneDeep, get, has, omit } from 'lodash'; | ||
import { cloneDeep, get, omit } from 'lodash'; | ||
import { is, toCamelCase, toSnakeCase } from './utils'; | ||
export default class Errors { | ||
errors = {}; | ||
add(attribute, message) { | ||
if (!this.has(attribute)) { | ||
this.errors[attribute] = []; | ||
add(field, message, forceUpdate) { | ||
const messages = Array.isArray(message) ? message : [message]; | ||
if (this.missed(field)) | ||
this.errors[field] = []; | ||
if (this.errors[field].every(s => !messages.includes(s))) | ||
this.errors[field].unshift(...messages); | ||
if (forceUpdate) { | ||
this.errors[field] = []; | ||
this.errors[field].push(...messages); | ||
} | ||
if (this.errors[attribute].indexOf(message) === -1) { | ||
this.errors[attribute].push(message); | ||
} | ||
} | ||
@@ -16,10 +20,15 @@ missed(field) { | ||
get(field) { | ||
return get(this.errors, field, []); | ||
} | ||
first(attribute) { | ||
if (this.has(attribute)) { | ||
return this.get(attribute)[0]; | ||
const fields = Array.isArray(field) ? field : [field]; | ||
for (const f of fields) { | ||
if (this.has(f)) | ||
return get(this.errors, f, []); | ||
} | ||
return undefined; | ||
return []; | ||
} | ||
first(field) { | ||
const fields = this._getFields(field); | ||
const fd = fields.find(f => f in this.errors); | ||
const value = this.get(fd ?? field); | ||
return value[0]; | ||
} | ||
all() { | ||
@@ -29,6 +38,7 @@ return this.errors; | ||
has(field) { | ||
return has(this.errors, field); | ||
const fields = this._getFields(field); | ||
return is(Object.keys(this.errors), fields); | ||
} | ||
fill(errors) { | ||
this.errors = errors; | ||
this.errors = Object.assign({}, errors); | ||
} | ||
@@ -44,2 +54,15 @@ clear(attribute) { | ||
} | ||
onKeydown(event) { | ||
const { name } = event.target; | ||
if (!name) | ||
return; | ||
this.clear(name); | ||
} | ||
_getFields(field) { | ||
const fields = []; | ||
const attributes = Array.isArray(field) ? field : [field]; | ||
for (const f of attributes) | ||
fields.push(toCamelCase(f), toSnakeCase(f)); | ||
return [...new Set(fields)].filter(Boolean); | ||
} | ||
} |
@@ -1,8 +0,7 @@ | ||
import type { LangTypes } from './types'; | ||
import type { SimpleObject } from './types'; | ||
import type { LangTypes, SimpleObject } from './types'; | ||
import Massages from './messages'; | ||
export default class I18n { | ||
static messages: Record<LangTypes, Record<string, any>>; | ||
static messages: Record<LangTypes, SimpleObject>; | ||
static _set(lang: LangTypes, rawMessages: SimpleObject): void; | ||
static _get(lang: LangTypes): Record<string, any>; | ||
static _get(lang: LangTypes): SimpleObject; | ||
static _setRuleMessage(lang: LangTypes, attribute: string, message?: string): void; | ||
@@ -9,0 +8,0 @@ static _load(lang: LangTypes): void; |
@@ -15,5 +15,4 @@ import locales from './lang'; | ||
const messages = Object.create(this.messages); | ||
if (message === undefined) { | ||
if (message === undefined) | ||
message = messages[lang].def; | ||
} | ||
messages[lang][attribute] = message; | ||
@@ -26,6 +25,6 @@ } | ||
static _make(lang) { | ||
this._load(lang); | ||
const messages = Object.create(this.messages); | ||
this._load(lang); | ||
return new Massages(messages[lang]); | ||
return new Massages(messages[lang] ?? {}); | ||
} | ||
} |
@@ -69,3 +69,3 @@ const az = { | ||
string: ' :attribute maksimum :max simvoldan ibarət ola bilər', | ||
array: " :attribute maksimum :max hədd'dən ibarət ola bilər", | ||
array: ' :attribute maksimum :max hədd\'dən ibarət ola bilər', | ||
}, | ||
@@ -78,3 +78,3 @@ mimes: ' :attribute :values tipində fayl olmalıdır', | ||
string: ' :attribute minimum :min simvoldan ibarət ola bilər', | ||
array: " :attribute minimum :min hədd'dən ibarət ola bilər", | ||
array: ' :attribute minimum :min hədd\'dən ibarət ola bilər', | ||
}, | ||
@@ -87,3 +87,3 @@ not_in: ' seçilmiş :attribute yanlışdır', | ||
required_if: ' :attribute (:other :value ikən) mütləqdir', | ||
required_unless: " :attribute (:other :values 'ə daxil ikən) mütləqdir", | ||
required_unless: ' :attribute (:other :values \'ə daxil ikən) mütləqdir', | ||
required_with: ' :attribute (:values var ikən) mütləqdir', | ||
@@ -98,3 +98,3 @@ required_with_all: ' :attribute (:values var ikən) mütləqdir', | ||
string: ' :attribute :size simvoldan ibarət olmalıdır', | ||
array: " :attribute :size hədd'dən ibarət olmalıdır", | ||
array: ' :attribute :size hədd\'dən ibarət olmalıdır', | ||
}, | ||
@@ -101,0 +101,0 @@ string: ' :attribute hərf formatında olmalıdır', |
@@ -21,3 +21,3 @@ const be = { | ||
confirmed: 'Поле :attribute не супадае з пацвярджэннем.', | ||
date: "Поле :attribute не з'яўляецца датай.", | ||
date: 'Поле :attribute не з\'яўляецца датай.', | ||
date_format: 'Поле :attribute не адпавядае фармату :format.', | ||
@@ -24,0 +24,0 @@ different: 'Палі :attribute і :other павінны адрознівацца.', |
@@ -6,3 +6,3 @@ const cy = { | ||
after_or_equal: 'The :attribute must be a date after or equal to :date.', | ||
alpha: "Dim ond llythrennau'n unig gall :attribute gynnwys.", | ||
alpha: 'Dim ond llythrennau\'n unig gall :attribute gynnwys.', | ||
alpha_dash: 'Dim ond llythrennau, rhifau a dash yn unig gall :attribute gynnwys.', | ||
@@ -20,4 +20,4 @@ alpha_num: 'Dim ond llythrennau a rhifau yn unig gall :attribute gynnwys.', | ||
}, | ||
boolean: "Rhaid i'r maes :attribute fod yn wir neu gau.", | ||
confirmed: "Nid yw'r cadarnhad :attribute yn gyfwerth.", | ||
boolean: 'Rhaid i\'r maes :attribute fod yn wir neu gau.', | ||
confirmed: 'Nid yw\'r cadarnhad :attribute yn gyfwerth.', | ||
date: 'Nid yw :attribute yn ddyddiad dilys.', | ||
@@ -73,4 +73,4 @@ date_format: 'Nid yw :attribute yn y fformat :format.', | ||
}, | ||
mimes: "Rhaid i :attribute fod yn ffeil o'r math: :values.", | ||
mimetypes: "Rhaid i :attribute fod yn ffeil o'r math: :values.", | ||
mimes: 'Rhaid i :attribute fod yn ffeil o\'r math: :values.', | ||
mimetypes: 'Rhaid i :attribute fod yn ffeil o\'r math: :values.', | ||
min: { | ||
@@ -77,0 +77,0 @@ numeric: 'Rhaid i :attribute fod o leiaf :min.', |
@@ -8,3 +8,3 @@ const fr = { | ||
between: 'La longueur du champ :attribute doit être comprise entre :min and :max.', | ||
confirmed: "Le champ :attribute n'est pas confirmé.", | ||
confirmed: 'Le champ :attribute n\'est pas confirmé.', | ||
email: 'Le champ :attribute contient un format invalide.', | ||
@@ -11,0 +11,0 @@ def: 'Le champ :attribute contient un attribut erroné.', |
@@ -9,3 +9,3 @@ const it = { | ||
confirmed: 'Il campo conferma :attribute non è uguale.', | ||
email: "Il formato dell'attributo :attribute non è valido.", | ||
email: 'Il formato dell\'attributo :attribute non è valido.', | ||
def: 'Gli attributi del campo :attribute contengono degli errori.', | ||
@@ -12,0 +12,0 @@ digits: 'Il campo :attribute deve essere di :digits cifre.', |
@@ -49,4 +49,4 @@ const km = { | ||
'form.age': 'អាយុ', | ||
name: 'ឈ្មោះ', | ||
form: { | ||
'name': 'ឈ្មោះ', | ||
'form': { | ||
name: 'ឈ្មោះ', | ||
@@ -53,0 +53,0 @@ }, |
@@ -19,3 +19,3 @@ const lt = { | ||
}, | ||
boolean: "Lauko reikšmė :attribute turi būti 'taip' arba 'ne'.", | ||
boolean: 'Lauko reikšmė :attribute turi būti \'taip\' arba \'ne\'.', | ||
confirmed: 'Lauko :attribute patvirtinimas nesutampa.', | ||
@@ -22,0 +22,0 @@ date: 'Lauko :attribute reikšmė nėra galiojanti data.', |
@@ -28,3 +28,3 @@ const ua = { | ||
present: 'Поле :attribute повинно бути присутнім (але може бути пустим).', | ||
required: "Поле :attribute обов'язкове для заповнення.", | ||
required: 'Поле :attribute обов\'язкове для заповнення.', | ||
required_if: 'Поле :attribute потрібне у випадку коли значення поля :other рівне :value.', | ||
@@ -31,0 +31,0 @@ same: 'Значеня поля :attribute повинно співпадати з :same.', |
@@ -30,3 +30,3 @@ const uk = { | ||
file: 'Поле :attribute має містити файл.', | ||
filled: "Поле :attribute є обов'язковим для заповнення.", | ||
filled: 'Поле :attribute є обов\'язковим для заповнення.', | ||
exists: 'Вибране для :attribute значення не коректне.', | ||
@@ -85,9 +85,9 @@ gt: { | ||
regex: 'Поле :attribute має хибний формат.', | ||
required: "Поле :attribute є обов'язковим для заповнення.", | ||
required_if: "Поле :attribute є обов'язковим для заповнення, коли :other є рівним :value.", | ||
required_unless: "Поле :attribute є обов'язковим для заповнення, коли :other відрізняється від :values", | ||
required_with: "Поле :attribute є обов'язковим для заповнення, коли :values вказано.", | ||
required_with_all: "Поле :attribute є обов'язковим для заповнення, коли :values вказано.", | ||
required_without: "Поле :attribute є обов'язковим для заповнення, коли :values не вказано.", | ||
required_without_all: "Поле :attribute є обов'язковим для заповнення, коли :values не вказано.", | ||
required: 'Поле :attribute є обов\'язковим для заповнення.', | ||
required_if: 'Поле :attribute є обов\'язковим для заповнення, коли :other є рівним :value.', | ||
required_unless: 'Поле :attribute є обов\'язковим для заповнення, коли :other відрізняється від :values', | ||
required_with: 'Поле :attribute є обов\'язковим для заповнення, коли :values вказано.', | ||
required_with_all: 'Поле :attribute є обов\'язковим для заповнення, коли :values вказано.', | ||
required_without: 'Поле :attribute є обов\'язковим для заповнення, коли :values не вказано.', | ||
required_without_all: 'Поле :attribute є обов\'язковим для заповнення, коли :values не вказано.', | ||
same: 'Поля :attribute та :other мають співпадати.', | ||
@@ -94,0 +94,0 @@ size: { |
import type Messages from './messages'; | ||
import type { Rule } from './rule'; | ||
import type { ValidatorOptions, VoidFunction, LangTypes, RuleType } from './types'; | ||
import type { SimpleObject } from './types'; | ||
import type { CbFunction, LangTypes, RuleType, SimpleObject, ValidatorOptions } from './types'; | ||
import Errors from './errors'; | ||
import { Manager } from './rule'; | ||
import { formatter } from './utils'; | ||
export { Errors, ValidatorOptions, LangTypes, RuleType }; | ||
export default class Validator { | ||
readonly input: SimpleObject | null; | ||
readonly messages: Messages; | ||
readonly errors: Errors; | ||
readonly rules: SimpleObject; | ||
readonly options: Partial<ValidatorOptions>; | ||
errorCount: number; | ||
hasAsync: boolean; | ||
stopOnAttributes: SimpleObject | boolean | string[] | undefined; | ||
readonly numericRules: string[]; | ||
readonly errors: Errors; | ||
readonly messages: Messages; | ||
private readonly confirmedReverse?; | ||
static lang: LangTypes; | ||
readonly numericRules: string[]; | ||
rules: Record<RuleType, any>; | ||
stopOnAttributes: SimpleObject | boolean | string[] | undefined; | ||
static attributeFormatter: (attribute: string) => string; | ||
readonly options: ValidatorOptions; | ||
static attributeFormatter: typeof formatter; | ||
static manager: Manager; | ||
private readonly confirmedReverse?; | ||
constructor(input: SimpleObject | null, rules?: Record<RuleType, any>, options?: Partial<ValidatorOptions>); | ||
constructor(input: SimpleObject | null, rules?: SimpleObject, options?: Partial<ValidatorOptions>); | ||
check(): boolean; | ||
checkAsync(passes?: boolean | (() => void), fails?: any): void; | ||
_parseRules(rules?: Record<RuleType, any>): Record<string, any>; | ||
_parseRules(rules?: SimpleObject): SimpleObject; | ||
static setMessages(lang: LangTypes, messages: SimpleObject): typeof Validator; | ||
static getMessages(lang: LangTypes): Record<string, any>; | ||
static getMessages(lang: LangTypes): SimpleObject; | ||
static useLang(lang: LangTypes): void; | ||
@@ -40,9 +40,9 @@ static getDefaultLang(): LangTypes; | ||
_shouldStopValidating(attribute: string, rulePassed: any): boolean; | ||
_parseRulesCheck(attribute: string, rulesArray: SimpleObject[] | any[] | string, parsedRules: SimpleObject, wildCardValues?: any[]): void; | ||
_parsedRulesRecurse(attribute: string, rulesArray: SimpleObject[] | any[] | string, parsedRules: SimpleObject, wildCardValues?: number[]): void; | ||
_parseRulesDefault(attribute: string, rulesArray: SimpleObject[] | any[] | string, parsedRules: SimpleObject | any, wildCardValues?: any): void; | ||
_parseRulesCheck(attribute: string, rulesArray: (SimpleObject | any | string)[], parsedRules: SimpleObject, wildCardValues?: number[]): void; | ||
_parsedRulesRecurse(attribute: string, rulesArray: (SimpleObject | any | string)[], parsedRules: SimpleObject, wildCardValues?: number[]): void; | ||
_parseRulesDefault(attribute: string, rulesArray: SimpleObject[] | any[] | string, parsedRules: SimpleObject | any, wildCardValues?: (string | number)[]): void; | ||
_prepareRulesArray(rulesArray: SimpleObject[] | any[]): SimpleObject[]; | ||
_extractRuleAndRuleValue(ruleString: string | SimpleObject): SimpleObject; | ||
_replaceWildCards(path: string, nums: string[]): string; | ||
_replaceWildCardsMessages(nums: string[]): void; | ||
_replaceWildCards(path: string, nums: (string | number)[] | undefined): string; | ||
_replaceWildCardsMessages(nums: (string | number)[] | undefined): void; | ||
_hasNumericRule(attribute: string): boolean; | ||
@@ -53,5 +53,5 @@ setAttributeNames(attributes?: SimpleObject): void; | ||
passes(passes?: () => void): boolean | void; | ||
fails(fails?: VoidFunction): boolean | void; | ||
fails(fails?: CbFunction): boolean | void; | ||
_checkAsync(funcName: string, callback?: boolean | (() => void)): boolean; | ||
validated(passes?: VoidFunction, fails?: VoidFunction): void | SimpleObject; | ||
validated(passes?: CbFunction, fails?: CbFunction): void | SimpleObject; | ||
_onlyInputWithRules(obj?: SimpleObject, keyPrefix?: string): SimpleObject; | ||
@@ -58,0 +58,0 @@ static register(name: string, fn: any, message?: string): void; |
133
dist/main.js
@@ -1,2 +0,2 @@ | ||
import { get, isArray } from 'lodash'; | ||
import { get, replace } from 'lodash'; | ||
import AsyncResolvers from './async-resolvers'; | ||
@@ -10,16 +10,18 @@ import Errors from './errors'; | ||
input; | ||
messages; | ||
errors; | ||
rules; | ||
options; | ||
errorCount; | ||
hasAsync; | ||
stopOnAttributes; | ||
numericRules = ['integer', 'numeric']; | ||
errors; | ||
messages; | ||
confirmedReverse; | ||
static lang = 'en'; | ||
numericRules = ['integer', 'numeric']; | ||
rules; | ||
stopOnAttributes; | ||
static attributeFormatter = formatter; | ||
options; | ||
static manager = new Manager(); | ||
confirmedReverse; | ||
constructor(input, rules, options = {}) { | ||
constructor(input, rules = {}, options = {}) { | ||
this.input = input; | ||
this.rules = rules; | ||
this.options = options; | ||
const lang = options.locale || Validator.getDefaultLang(); | ||
@@ -40,12 +42,11 @@ Validator.useLang(lang); | ||
const attributeRules = this.rules[attribute]; | ||
const inputValue = get(this.input, attribute); | ||
const inputValue = get(this.input ?? {}, attribute); | ||
if (this._passesOptionalCheck(attribute)) | ||
continue; | ||
for (let i = 0, len = attributeRules.length, rule, ruleOptions, rulePassed; i < len; i++) { | ||
ruleOptions = attributeRules[i]; | ||
const { name, value } = ruleOptions; | ||
rule = this.getRule(name); | ||
for (let i = 0, len = attributeRules.length; i < len; i++) { | ||
const { name, value } = attributeRules[i]; | ||
const rule = this.getRule(name); | ||
if (!this._isValidatable(rule, inputValue)) | ||
continue; | ||
rulePassed = rule.validate(inputValue, value, attribute); | ||
const rulePassed = rule.validate(inputValue, value, attribute); | ||
if (!rulePassed) { | ||
@@ -74,11 +75,9 @@ if (name === 'confirmed' && this.confirmedReverse) { | ||
const resolvedAll = (allPassed) => { | ||
if (allPassed && typeof passes === 'function') { | ||
if (allPassed && typeof passes === 'function') | ||
passes(); | ||
} | ||
else { | ||
else | ||
fails(); | ||
} | ||
}; | ||
const asyncResolvers = new AsyncResolvers(failsOne, resolvedAll); | ||
const validateRule = (inputValue, ruleOptions, attribute, rule) => { | ||
const validateRule = (inputValue, ruleOptions, rule, attribute = '') => { | ||
return () => { | ||
@@ -90,12 +89,10 @@ const resolverIndex = asyncResolvers.add(rule); | ||
for (const attribute in this.rules) { | ||
const attributeRules = this.rules[attribute]; | ||
const attributeRules = get(this.rules, attribute); | ||
const inputValue = get(this.input, attribute); | ||
if (this._passesOptionalCheck(attribute)) | ||
continue; | ||
for (let i = 0, len = attributeRules.length, rule, ruleOptions; i < len; i++) { | ||
ruleOptions = attributeRules[i]; | ||
rule = this.getRule(ruleOptions.name); | ||
if (this._isValidatable(rule, inputValue)) { | ||
validateRule(inputValue, ruleOptions, attribute, rule)(); | ||
} | ||
for (const ruleOptions of attributeRules) { | ||
const rule = this.getRule(ruleOptions.name); | ||
if (this._isValidatable(rule, inputValue)) | ||
validateRule(inputValue, ruleOptions, rule, attribute)(); | ||
} | ||
@@ -140,3 +137,3 @@ } | ||
for (const { name } of rules) { | ||
if (findRules.indexOf(name) > -1) | ||
if (findRules.includes(name)) | ||
return true; | ||
@@ -147,4 +144,4 @@ } | ||
_passesOptionalCheck(attribute) { | ||
const find = ['sometimes']; | ||
return this._hasRule(attribute, find) && !this._suppliedWithData(attribute); | ||
const findRules = ['sometimes', 'nullable']; | ||
return this._hasRule(attribute, findRules) && !this._suppliedWithData(attribute); | ||
} | ||
@@ -155,6 +152,6 @@ _suppliedWithData(attribute) { | ||
return false; | ||
if (args.length == 0 && hasOwnProperty(obj, key)) | ||
if (args.length === 0 && hasOwnProperty(obj, key)) | ||
return true; | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore | ||
// @ts-expect-error | ||
return hasNested(obj[key], ...args); | ||
@@ -164,3 +161,3 @@ } | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore | ||
// @ts-expect-error | ||
return hasNested(this.input, ...keys); | ||
@@ -172,3 +169,3 @@ } | ||
_isValidatable(rule, value) { | ||
if (isArray(value) || Validator.manager.isImplicit(rule.name)) | ||
if (Array.isArray(value) || Validator.manager.isImplicit(rule.name)) | ||
return true; | ||
@@ -187,24 +184,18 @@ return this.getRule('required').validate(value, {}); | ||
return false; | ||
if (stopOnAttributes instanceof Array) { | ||
return stopOnAttributes.indexOf(attribute) > -1; | ||
} | ||
if (Array.isArray(stopOnAttributes)) | ||
return stopOnAttributes.includes(attribute); | ||
return true; | ||
} | ||
_parseRulesCheck(attribute, rulesArray, parsedRules, wildCardValues) { | ||
if (attribute.indexOf('*') > -1) { | ||
if (attribute.includes('*')) | ||
this._parsedRulesRecurse(attribute, rulesArray, parsedRules, wildCardValues); | ||
} | ||
else { | ||
else | ||
this._parseRulesDefault(attribute, rulesArray, parsedRules, wildCardValues); | ||
} | ||
} | ||
_parsedRulesRecurse(attribute, rulesArray, parsedRules, wildCardValues = []) { | ||
const parentPath = attribute.substring(0, attribute.indexOf('*') - 1); | ||
const propertyValue = get(this.input, parentPath); | ||
if (propertyValue) { | ||
for (let propertyNumber = 0; propertyNumber < propertyValue.length; propertyNumber++) { | ||
const workingValues = wildCardValues.slice(); | ||
workingValues.push(propertyNumber); | ||
this._parseRulesCheck(attribute.replace(/\*/g, String(propertyNumber)), rulesArray, parsedRules, workingValues); | ||
} | ||
const parentValue = get(this.input, parentPath); | ||
for (let propertyNumber = 0, len = parentValue.length; propertyNumber < len; propertyNumber++) { | ||
const workingValues = [...wildCardValues, propertyNumber]; | ||
this._parseRulesCheck(replace(attribute, '*', String(propertyNumber)), rulesArray, parsedRules, workingValues); | ||
} | ||
@@ -214,8 +205,6 @@ } | ||
const attributeRules = []; | ||
if (rulesArray instanceof Array) { | ||
if (Array.isArray(rulesArray)) | ||
rulesArray = this._prepareRulesArray(rulesArray); | ||
} | ||
if (typeof rulesArray === 'string') { | ||
if (typeof rulesArray === 'string') | ||
rulesArray = rulesArray.split('|'); | ||
} | ||
for (const ruleKey of rulesArray) { | ||
@@ -236,5 +225,4 @@ const rule = this._extractRuleAndRuleValue(ruleKey); | ||
if (typeof ruleArray === 'object') { | ||
for (const rule in ruleArray) { | ||
for (const rule in ruleArray) | ||
rules.push({ name: rule, value: ruleArray[rule] }); | ||
} | ||
} | ||
@@ -253,3 +241,3 @@ else { | ||
rule.name = ruleString; | ||
if (ruleString.indexOf(':') >= 0) { | ||
if (ruleString.includes(':')) { | ||
ruleArray = ruleString.split(':'); | ||
@@ -294,36 +282,26 @@ rule.name = ruleArray[0]; | ||
const async = this._checkAsync('passes', passes); | ||
if (async) | ||
return this.checkAsync(passes); | ||
return this.check(); | ||
return async ? this.checkAsync(passes) : this.check(); | ||
} | ||
fails(fails) { | ||
const async = this._checkAsync('fails', fails); | ||
if (async) | ||
return this.checkAsync(false, fails); | ||
return !this.check(); | ||
return async ? this.checkAsync(false, fails) : !this.check(); | ||
} | ||
_checkAsync(funcName, callback) { | ||
const hasCallback = typeof callback === 'function'; | ||
if (this.hasAsync && !hasCallback) { | ||
throw funcName + ' expects a callback when async rules are being tested.'; | ||
} | ||
if (this.hasAsync && !hasCallback) | ||
throw new Error(`${funcName} expects a callback when async rules are being tested.`); | ||
return this.hasAsync || hasCallback; | ||
} | ||
validated(passes, fails) { | ||
// eslint-disable-next-line @typescript-eslint/no-this-alias | ||
const _this = this; | ||
if (this._checkAsync('passes', passes)) { | ||
return this.checkAsync(function () { | ||
if (passes && typeof passes === 'function') { | ||
passes(_this._onlyInputWithRules()); | ||
} | ||
}.bind(this), fails); | ||
return this.checkAsync(() => { | ||
if (passes && typeof passes === 'function') | ||
passes(this._onlyInputWithRules()); | ||
}, fails); | ||
} | ||
else { | ||
if (this.check()) { | ||
if (this.check()) | ||
return this._onlyInputWithRules(); | ||
} | ||
else { | ||
else | ||
throw new Error('Validation failed!'); | ||
} | ||
} | ||
@@ -336,8 +314,7 @@ } | ||
if (values[key] !== null && typeof values[key] === 'object') { | ||
values[key] = this._onlyInputWithRules(values[key], prefix + key + '.'); | ||
values[key] = this._onlyInputWithRules(values[key], `${prefix + key}.`); | ||
} | ||
else { | ||
if (values[key] === undefined || !Object.keys(this.rules).includes(prefix + key)) { | ||
if (values[key] === undefined || !Object.keys(this.rules).includes(prefix + key)) | ||
delete values[key]; | ||
} | ||
} | ||
@@ -344,0 +321,0 @@ } |
@@ -8,3 +8,3 @@ import type { Rule } from './rule'; | ||
private attributeFormatter; | ||
static replacements: any; | ||
static replacements: SimpleObject; | ||
constructor(messages: SimpleObject); | ||
@@ -18,3 +18,3 @@ static _setReplacements(): void; | ||
_getTemplate(rule: Rule): string; | ||
_replacePlaceholders(rule: Rule, template: string | any, data: SimpleObject): string; | ||
_replacePlaceholders(rule: Rule, template: string, data: SimpleObject): string; | ||
} |
@@ -1,2 +0,2 @@ | ||
import { has, snakeCase } from 'lodash'; | ||
import { get, snakeCase } from 'lodash'; | ||
import { flattenObject, toCamelCase } from './utils'; | ||
@@ -11,4 +11,2 @@ export default class Messages { | ||
this.messages = messages; | ||
this.customMessages = {}; | ||
this.attributeNames = {}; | ||
Messages._setReplacements(); | ||
@@ -118,29 +116,22 @@ } | ||
const camelCase = toCamelCase(attribute); | ||
const snakecase = snakeCase(attribute); | ||
if (has(attributeNames, camelCase) || has(attributeNames, snakecase)) { | ||
return attributeNames[snakecase] || attributeNames[camelCase]; | ||
} | ||
if (has(attributes, attribute)) { | ||
name = attributes[attribute]; | ||
} | ||
else if (this.attributeFormatter) { | ||
const _snakeCase = snakeCase(attribute); | ||
if (_snakeCase in attributeNames || camelCase in attributeNames) | ||
return attributeNames[_snakeCase] ?? attributeNames[camelCase]; | ||
if (attribute in attributes) | ||
name = get(attributes, attribute); | ||
else if (this.attributeFormatter) | ||
name = this.attributeFormatter(name); | ||
} | ||
while (name.includes('confirmation')) { | ||
name = name.replace(new RegExp('\\sconfirmation', 'g'), ''); | ||
} | ||
while (name.includes('confirmation')) | ||
name = name.replace(/\sconfirmation/g, ''); | ||
return name; | ||
} | ||
render(rule) { | ||
if (rule.customMessages) { | ||
if (rule.customMessages) | ||
return rule.customMessages; | ||
} | ||
const template = this._getTemplate(rule); | ||
let message; | ||
if (Messages.replacements[rule.name]) { | ||
if (Messages.replacements[rule.name]) | ||
message = Messages.replacements[rule.name].apply(this, [template, rule]); | ||
} | ||
else { | ||
else | ||
message = this._replacePlaceholders(rule, template, {}); | ||
} | ||
return message; | ||
@@ -154,7 +145,7 @@ } | ||
for (const format of formats) { | ||
if (has(customMessages, format)) { | ||
if (format in customMessages) { | ||
template = customMessages[format]; | ||
break; | ||
} | ||
else if (has(messages, format) && messages[format]) { | ||
else if (format in messages && messages[format]) { | ||
template = messages[format]; | ||
@@ -164,20 +155,13 @@ break; | ||
} | ||
if (typeof template === 'object') { | ||
if (typeof template === 'object') | ||
template = template[rule._getValueType()]; | ||
} | ||
return template; | ||
} | ||
_replacePlaceholders(rule, template, data) { | ||
let message = ''; | ||
let attribute; | ||
data.attribute = this._getAttributeName(rule.attribute); | ||
data[rule.name] = data[rule.name] || rule.getParameters().join(','); | ||
if (typeof template === 'string' && typeof data === 'object') { | ||
message = template; | ||
for (attribute in data) { | ||
message = message.replace(RegExp(`:${attribute}`, 'g'), data[attribute]); | ||
} | ||
} | ||
return message; | ||
const updatedData = Object.assign(data, { | ||
attribute: this._getAttributeName(rule.attribute), | ||
[rule.name]: data[rule.name] || rule.getParameters().join(','), | ||
}); | ||
return template.trim().replace(/:(\w+)/g, (_, key) => updatedData[key]); | ||
} | ||
} |
import type Validator from './main'; | ||
import type { CbFunction, SimpleObject } from './types'; | ||
export declare class Rule { | ||
readonly name: string; | ||
private readonly fn; | ||
private readonly async; | ||
attribute: string; | ||
private _customMessage; | ||
private passes; | ||
private readonly fn; | ||
readonly name: string; | ||
private callback; | ||
attribute: string; | ||
private input; | ||
private rule; | ||
private validator; | ||
static rules: any; | ||
static rules: SimpleObject; | ||
private callback; | ||
constructor(name: string, fn: VoidFunction, async: boolean); | ||
validate(input: Record<string, any> | string | number, rule: Record<string, any>, attribute?: string, callback?: null): any; | ||
_apply(input: Record<string, any> | string | number, rule: Record<string, any>, attribute: string | null, callback?: null): any; | ||
_setValidatingData(attribute: string, input: Record<string, any> | string | number, rule: any): void; | ||
getParameters(): any[]; | ||
validate(input: SimpleObject | string | number, rule: SimpleObject, attribute?: string, callback?: CbFunction): any; | ||
_apply(input: SimpleObject | string | number, rule: SimpleObject, attribute: string | null, callback?: CbFunction): any; | ||
_setValidatingData(attribute: string, input: SimpleObject | string | number, rule: any): void; | ||
getParameters(): (string | number)[]; | ||
getSize(value?: string | number | Array<string | number>): string | number; | ||
@@ -33,7 +34,7 @@ _getValueType(): "numeric" | "string"; | ||
isImplicit(name: string): boolean; | ||
register(name: string, fn: VoidFunction): void; | ||
registerImplicit(name: string, fn: VoidFunction): void; | ||
registerAsync(name: string, fn: VoidFunction): void; | ||
registerAsyncImplicit(name: string, fn: VoidFunction): void; | ||
registerMissedRuleValidator(fn: VoidFunction, message?: string): void; | ||
register(name: string, fn: CbFunction): void; | ||
registerImplicit(name: string, fn: CbFunction): void; | ||
registerAsync(name: string, fn: CbFunction): void; | ||
registerAsyncImplicit(name: string, fn: CbFunction): void; | ||
registerMissedRuleValidator(fn: CbFunction, message?: string): void; | ||
} |
100
dist/rule.js
@@ -1,16 +0,15 @@ | ||
import { get } from 'lodash'; | ||
import { get, isString } from 'lodash'; | ||
import * as rules from './rules'; | ||
import { flattenObject, isEmpty, isValidDate } from './utils'; | ||
let missedRuleValidator = function () { | ||
throw new Error('Validator `' + this.name + '` is not defined!'); | ||
throw new Error(`Validator \`${this.name}\` is not defined!`); | ||
}; | ||
let missedRuleMessage = ''; | ||
export class Rule { | ||
name; | ||
fn; | ||
async; | ||
_customMessage; | ||
passes; | ||
fn; | ||
name; | ||
callback; | ||
attribute; | ||
attribute = ''; | ||
_customMessage = undefined; | ||
passes = false; | ||
input; | ||
@@ -20,12 +19,10 @@ rule; | ||
static rules = Object.assign({}, rules); | ||
callback; | ||
constructor(name, fn, async) { | ||
this.name = name; | ||
this.fn = fn; | ||
this.passes = false; | ||
this._customMessage = undefined; | ||
this.async = async; | ||
Rule._setRules(); | ||
this.attribute = ''; | ||
} | ||
validate(input, rule, attribute = '', callback = null) { | ||
validate(input, rule, attribute = '', callback) { | ||
this._setValidatingData(attribute, input, rule); | ||
@@ -37,12 +34,10 @@ if (typeof callback === 'function') { | ||
}; | ||
if (this.async) { | ||
if (this.async) | ||
return this._apply(input, rule, attribute, handleResponse); | ||
} | ||
else { | ||
else | ||
return handleResponse(this._apply(input, rule, attribute)); | ||
} | ||
} | ||
return this._apply(input, rule, attribute); | ||
} | ||
_apply(input, rule, attribute, callback = null) { | ||
_apply(input, rule, attribute, callback) { | ||
const fn = this.isMissed() ? missedRuleValidator : this.fn; | ||
@@ -58,11 +53,11 @@ return fn.apply(this, [input, rule, attribute, callback]); | ||
let value = []; | ||
if (!isNaN(parseFloat(this.rule)) && isFinite(this.rule)) { | ||
this.rule = parseFloat(this.rule); | ||
value.push(this.rule); | ||
} | ||
if (typeof this.rule === 'string') { | ||
if (!this.rule) | ||
return value; | ||
if (isString(this.rule)) | ||
value = this.rule.split(','); | ||
} | ||
if (this.rule instanceof Array) { | ||
if (Array.isArray(this.rule)) | ||
value = this.rule; | ||
if (!Number.isNaN(Number.parseFloat(this.rule)) && Number.isFinite(this.rule)) { | ||
this.rule = Number.parseFloat(this.rule); | ||
value.push(this.rule); | ||
} | ||
@@ -73,17 +68,13 @@ return value; | ||
const input = value || this.input; | ||
if (input instanceof Array) { | ||
if (Array.isArray(input)) | ||
return input.length; | ||
} | ||
if (typeof input === 'number') { | ||
if (typeof input === 'number') | ||
return input; | ||
} | ||
if (this.validator._hasNumericRule(this.attribute)) { | ||
return parseFloat(input); | ||
} | ||
if (this.validator._hasNumericRule(this.attribute)) | ||
return Number.parseFloat(input); | ||
return input.length; | ||
} | ||
_getValueType() { | ||
if (typeof this.input === 'number' || this.validator._hasNumericRule(this.attribute)) { | ||
if (typeof this.input === 'number' || this.validator._hasNumericRule(this.attribute)) | ||
return 'numeric'; | ||
} | ||
return 'string'; | ||
@@ -111,5 +102,4 @@ } | ||
const val2 = value; | ||
if (!isValidDate(val1) || !isValidDate(val2)) { | ||
if (!isValidDate(val1) || !isValidDate(val2)) | ||
return false; | ||
} | ||
return new Date(val1).getTime() < new Date(val2).getTime(); | ||
@@ -126,5 +116,4 @@ }, | ||
req = this.getParameters(); | ||
if (get(this.validator.input, req[0]) === req[1]) { | ||
if (get(this.validator.input, req[0]) === req[1]) | ||
return this.validator.getRule('required').validate(val, {}); | ||
} | ||
return true; | ||
@@ -134,11 +123,9 @@ }, | ||
req = this.getParameters(); | ||
if (get(this.validator.input, req[0]) !== req[1]) { | ||
if (get(this.validator.input, req[0]) !== req[1]) | ||
return this.validator.getRule('required').validate(val, {}); | ||
} | ||
return true; | ||
}, | ||
required_with(val, req) { | ||
if (get(this.validator.input, req)) { | ||
if (get(this.validator.input, req)) | ||
return this.validator.getRule('required').validate(val, {}); | ||
} | ||
return true; | ||
@@ -170,3 +157,3 @@ }, | ||
return false; | ||
req = parseFloat(String(req)); | ||
req = Number.parseFloat(String(req)); | ||
const size = this.getSize(); | ||
@@ -183,7 +170,7 @@ return size === req; | ||
}, | ||
between(val, req) { | ||
between(_val, req) { | ||
req = this.getParameters(); | ||
const size = this.getSize(); | ||
const min = parseFloat(req[0]); | ||
const max = parseFloat(req[1]); | ||
const min = Number.parseFloat(req[0]); | ||
const max = Number.parseFloat(req[1]); | ||
return size >= min && size <= max; | ||
@@ -203,3 +190,3 @@ }, | ||
list = this.getParameters(); | ||
if (!isEmpty(val) && !(val instanceof Array)) { | ||
if (!isEmpty(val) && !(Array.isArray(val))) { | ||
let localValue = val; | ||
@@ -214,5 +201,5 @@ for (const li of list) { | ||
} | ||
if (val && val instanceof Array) { | ||
if (val && Array.isArray(val)) { | ||
for (const va of val) { | ||
if (list.indexOf(va) < 0) | ||
if (!list.includes(va)) | ||
return false; | ||
@@ -237,4 +224,4 @@ } | ||
}, | ||
confirmed(val, req, attribute) { | ||
const confirmedKey = attribute + '_confirmation'; | ||
confirmed(val, _req, attribute) { | ||
const confirmedKey = `${attribute}_confirmation`; | ||
return this.validator.input[confirmedKey] === val; | ||
@@ -244,3 +231,3 @@ }, | ||
const numericRule = this.validator.getRule('numeric'); | ||
return !!(numericRule.validate(val, {}) && String(val).trim().length === parseInt(req)); | ||
return !!(numericRule.validate(val, {}) && String(val).trim().length === Number.parseInt(req)); | ||
}, | ||
@@ -250,4 +237,4 @@ digits_between(val) { | ||
const req = this.getParameters(); | ||
const min = parseFloat(req[0]); | ||
const max = parseFloat(req[1]); | ||
const min = Number.parseFloat(req[0]); | ||
const max = Number.parseFloat(req[1]); | ||
return numericRule.validate(val, {}) && val >= min && val <= max; | ||
@@ -270,3 +257,3 @@ }, | ||
ip(val, req, attribute) { | ||
return Rule.rules['ipv4'](val, req, attribute) || Rule.rules['ipv6'](val, req, attribute); | ||
return Rule.rules.ipv4(val, req, attribute) || Rule.rules.ipv6(val, req, attribute); | ||
}, | ||
@@ -298,5 +285,4 @@ }; | ||
for (const rule of this.asyncRules) { | ||
if (rule === name) { | ||
if (rule === name) | ||
return true; | ||
} | ||
} | ||
@@ -306,3 +292,3 @@ return false; | ||
isImplicit(name) { | ||
return this.implicitRules.indexOf(name) > -1; | ||
return this.implicitRules.includes(name); | ||
} | ||
@@ -309,0 +295,0 @@ register(name, fn) { |
@@ -1,1 +0,1 @@ | ||
export declare const accepted: (value: string | number | boolean) => boolean; | ||
export declare function accepted(value: string | number | boolean): boolean; |
@@ -1,3 +0,3 @@ | ||
export const accepted = (value) => { | ||
export function accepted(value) { | ||
return value === 'on' || value === 'yes' || value === 1 || value === '1' || value === true; | ||
}; | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare const alpha_dash: (value: string) => boolean; | ||
export declare function alpha_dash(value: string): boolean; |
@@ -1,3 +0,3 @@ | ||
export const alpha_dash = (value) => { | ||
export function alpha_dash(value) { | ||
return /^[a-zA-Z0-9_\-]+$/.test(value); | ||
}; | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare const alpha_num: (value: string) => boolean; | ||
export declare function alpha_num(value: string): boolean; |
@@ -1,3 +0,3 @@ | ||
export const alpha_num = (value) => { | ||
export function alpha_num(value) { | ||
return /^[a-zA-Z0-9]+$/.test(value); | ||
}; | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare const alpha: (value: string) => boolean; | ||
export declare function alpha(value: string): boolean; |
@@ -1,3 +0,3 @@ | ||
export const alpha = (value) => { | ||
export function alpha(value) { | ||
return /^[a-zA-Z]+$/.test(value); | ||
}; | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare const array: (value: any) => boolean; | ||
export declare function array(value: any): boolean; |
@@ -1,3 +0,3 @@ | ||
export const array = (value) => { | ||
return value instanceof Array; | ||
}; | ||
export function array(value) { | ||
return Array.isArray(value); | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare const boolean: (value: string | number | boolean) => boolean; | ||
export declare function boolean(value: string | number | boolean): boolean; |
@@ -1,10 +0,10 @@ | ||
export const boolean = (value) => { | ||
return (value === true || | ||
value === false || | ||
value === 0 || | ||
value === 1 || | ||
value === '0' || | ||
value === '1' || | ||
value === 'true' || | ||
value === 'false'); | ||
}; | ||
export function boolean(value) { | ||
return (value === true | ||
|| value === false | ||
|| value === 0 | ||
|| value === 1 | ||
|| value === '0' | ||
|| value === '1' | ||
|| value === 'true' | ||
|| value === 'false'); | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare const email: (value: string) => boolean; | ||
export declare function email(value: string): boolean; |
@@ -1,8 +0,7 @@ | ||
export const email = (value) => { | ||
export function email(value) { | ||
let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+\.)+[a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{2,}))$/; | ||
if (re.test(value)) { | ||
if (re.test(value)) | ||
return true; | ||
} | ||
re = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; | ||
return re.test(value); | ||
}; | ||
} |
@@ -21,1 +21,2 @@ export * from './accepted'; | ||
export * from './url'; | ||
export * from './nullable'; |
@@ -21,1 +21,2 @@ export * from './accepted'; | ||
export * from './url'; | ||
export * from './nullable'; |
@@ -1,1 +0,1 @@ | ||
export declare const integer: (value: string) => boolean; | ||
export declare function integer(value: string): boolean; |
@@ -1,4 +0,3 @@ | ||
import { isArray } from 'lodash'; | ||
export const integer = (value) => { | ||
return !isArray(value) && String(parseInt(value, 10)) === String(value); | ||
}; | ||
export function integer(value) { | ||
return !Array.isArray(value) && String(Number.parseInt(value, 10)) === String(value); | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare const ipv4: (value: string | number) => boolean; | ||
export declare function ipv4(value: string | number): boolean; |
@@ -1,2 +0,2 @@ | ||
export const ipv4 = (value) => { | ||
export function ipv4(value) { | ||
if (typeof value != 'string') | ||
@@ -9,3 +9,3 @@ return false; | ||
// check 1: ipv4 address should contain 4 octets | ||
if (octets.length != 4) | ||
if (octets.length !== 4) | ||
return false; | ||
@@ -18,3 +18,3 @@ for (const oct of octets) { | ||
// check 3: each octet value should be less than 256 | ||
const octetValue = parseInt(element); | ||
const octetValue = Number.parseInt(element); | ||
if (octetValue >= 256) | ||
@@ -25,2 +25,2 @@ return false; | ||
return true; | ||
}; | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare const ipv6: (value: string | number) => boolean; | ||
export declare function ipv6(value: string | number): boolean; |
@@ -1,2 +0,2 @@ | ||
export const ipv6 = (value) => { | ||
export function ipv6(value) { | ||
if (typeof value !== 'string') | ||
@@ -6,5 +6,5 @@ return false; | ||
const er = /^[0-9a-f]+$/; | ||
// ipv6 hextets are delimited by colon | ||
// colon delimits ipv6 hextets | ||
const hextets = value.split(':'); | ||
// check 1: ipv6 should contain only one consecutive colons | ||
// check 1: ipv6 should contain only one consecutive colon | ||
const colons = value.match(/::/); | ||
@@ -14,23 +14,22 @@ const matcher = value.match(/::/g) || ''; | ||
return false; | ||
// check 2: ipv6 should not be ending or starting with colon | ||
// edge case: not with consecutive colons | ||
if (value[0] == ':' && (colons == null || colons.index != 0)) | ||
// check 2: ipv6 should not be ending or starting with a colon-edge case: not with consecutive colons | ||
if (value[0] === ':' && (colons === null || colons.index !== 0)) | ||
return false; | ||
if (value[value.length - 1] == ':' && (colons == null || colons.index != value.length - 2)) | ||
if (value[value.length - 1] === ':' && (colons == null || colons.index !== value.length - 2)) | ||
return false; | ||
// check 3: ipv6 should contain no less than 3 sector | ||
// minimum ipv6 address - ::1 | ||
if (3 > hextets.length) | ||
// minimum ipv6 address -: :1 | ||
if (hextets.length < 3) | ||
return false; | ||
// check 4: ipv6 should contain no more than 8 sectors | ||
// only 1 edge case: when first or last sector is omitted | ||
const isEdgeCase = hextets.length == 9 && colons != null && (colons.index == 0 || colons.index == value.length - 2); | ||
const isEdgeCase = hextets.length === 9 && colons != null && (colons.index === 0 || colons.index === value.length - 2); | ||
if (hextets.length > 8 && !isEdgeCase) | ||
return false; | ||
// check 5: ipv6 should contain exactly one consecutive colons if it has less than 8 sectors | ||
if (hextets.length != 8 && colons == null) | ||
// check 5: ipv6 should contain exactly one consecutive colon if it has less than 8 sectors | ||
if (hextets.length !== 8 && colons == null) | ||
return false; | ||
for (const hex of hextets) { | ||
const element = hex; | ||
if (element.length == 0) | ||
if (element.length === 0) | ||
continue; | ||
@@ -40,4 +39,4 @@ // check 6: all of hextets should contain numbers from 0 to f (in hexadecimal) | ||
return false; | ||
// check 7: all of hextet values should be less than ffff (in hexadecimal) | ||
// checking using length of hextet. lowest invalid value's length is 5. | ||
// check 7: all the hextet values should be less than ffff (in hexadecimal) | ||
// checking using length of hextet. the lowest invalid value's length is 5. | ||
// so all valid hextets are length of 4 or less | ||
@@ -48,2 +47,2 @@ if (element.length > 4) | ||
return true; | ||
}; | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare const numeric: (value: string | number | boolean) => boolean; | ||
export declare function numeric(value: string | number | boolean): boolean; |
@@ -1,5 +0,4 @@ | ||
import { isArray } from 'lodash'; | ||
import { onlyDigits } from '../utils'; | ||
export const numeric = (value) => { | ||
return onlyDigits(value) && !isArray(value); | ||
}; | ||
export function numeric(value) { | ||
return onlyDigits(value) && !Array.isArray(value); | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare const password: (value: string) => boolean; | ||
export declare function password(value: string): boolean; |
@@ -1,3 +0,3 @@ | ||
export const password = (value) => { | ||
export function password(value) { | ||
return /^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{6,16}$/.test(value); | ||
}; | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare const regex: (value: string, req: string | number | any) => any; | ||
export declare function regex(value: string, req: string | number | any): any; |
@@ -1,2 +0,2 @@ | ||
export const regex = (value, req) => { | ||
export function regex(value, req) { | ||
const mod = /[g|i|m]{1,3}$/; | ||
@@ -8,2 +8,2 @@ let flag = req.match(mod); | ||
return req.test(value); | ||
}; | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare const required: (value: any) => boolean; | ||
export declare function required(value: any): boolean; |
@@ -1,8 +0,7 @@ | ||
export const required = (value) => { | ||
export function required(value) { | ||
let str = ''; | ||
if (value === undefined || value === null) { | ||
if (value === undefined || value === null) | ||
return false; | ||
} | ||
str = String(value).replace(/\s/g, ''); | ||
return str.length > 0; | ||
}; | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare const string: (value: unknown) => boolean; | ||
export declare function string(value: unknown): boolean; |
@@ -1,3 +0,3 @@ | ||
export const string = (value) => { | ||
export function string(value) { | ||
return typeof value === 'string'; | ||
}; | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare const url: (value: string) => boolean; | ||
export declare function url(value: string): boolean; |
@@ -1,2 +0,2 @@ | ||
export const url = (value) => { | ||
export function url(value) { | ||
try { | ||
@@ -8,2 +8,2 @@ return Boolean(new URL(value)); | ||
} | ||
}; | ||
} |
export type LangTypes = 'ar' | 'az' | 'be' | 'bg' | 'bs' | 'ca' | 'cs' | 'cy' | 'da' | 'de' | 'el' | 'en' | 'es' | 'et' | 'eu' | 'fa' | 'fi' | 'fr' | 'hr' | 'hu' | 'id' | 'it' | 'ja' | 'ka' | 'km' | 'ko' | 'lt' | 'lv' | 'mk' | 'mn' | 'ms' | 'nb_NO' | 'nl' | 'pl' | 'pt' | 'pt_BR' | 'ro' | 'ru' | 'se' | 'sl' | 'sq' | 'sr' | 'sv' | 'tr' | 'ua' | 'uk' | 'uz' | 'vi' | 'zh' | 'zh_TW'; | ||
export type RuleType = 'accepted' | 'alpha' | 'alpha_dash' | 'alpha_num' | 'array' | 'boolean' | 'date' | 'email' | 'hex' | 'integer' | 'ipv4' | 'ipv6' | 'numeric' | 'password' | 'present' | 'required' | 'regex' | 'sometimes' | 'string' | 'url' | 'after' | 'after_or_equal' | 'required_if' | 'required_unless' | 'required_with' | 'required_with_all' | 'required_without' | 'required_without_all' | 'size' | 'min' | 'max' | 'between' | 'same' | 'different' | 'in' | 'not_in' | 'confirmed' | 'digits' | 'digits_between' | 'before' | 'before_or_equal' | 'ip' | string; | ||
export type SimpleObject<T = any> = Record<string, T>; | ||
export interface ValidatorOptions { | ||
locale?: LangTypes; | ||
confirmedReverse?: boolean; | ||
customMessages?: Record<string, any>; | ||
customAttributes?: Record<string, any>; | ||
customMessages?: SimpleObject<string | SimpleObject>; | ||
customAttributes?: SimpleObject<SimpleObject>; | ||
} | ||
export type VoidFunction = boolean | ((...arg: any) => any); | ||
export type SimpleObject<T = any> = Record<string, T>; | ||
export type CbFunction<R = any> = ((...arg: any) => R); |
@@ -10,21 +10,18 @@ export function leapYear(year) { | ||
if (parts[0].length === 4) { | ||
const y = parseInt(parts[0]); | ||
const m = parseInt(parts[1]); | ||
const d = parseInt(parts[2]); | ||
const y = Number.parseInt(parts[0]); | ||
const m = Number.parseInt(parts[1]); | ||
const d = Number.parseInt(parts[2]); | ||
if (m === 2) { | ||
if (leapYear(y)) { | ||
if (d > 29) { | ||
if (d > 29) | ||
return false; | ||
} | ||
} | ||
else { | ||
if (d > 28) { | ||
if (d > 28) | ||
return false; | ||
} | ||
} | ||
} | ||
if (m === 4 || m === 6 || m === 9 || m === 11) { | ||
if (d > 30) { | ||
if (d > 30) | ||
return false; | ||
} | ||
} | ||
@@ -44,6 +41,5 @@ } | ||
testDate = new Date(dateString); | ||
if (testDate.toString() === 'Invalid Date') { | ||
if (testDate.toString() === 'Invalid Date') | ||
return false; | ||
} | ||
return checkFalsePositiveDates(dateString); | ||
} |
import type { SimpleObject } from '../types'; | ||
export declare function hasOwnProperty(object?: SimpleObject | any, key?: string | number | symbol): boolean; | ||
export declare const flattenObject: (obj?: SimpleObject | any) => SimpleObject; | ||
export declare function flattenObject(obj?: SimpleObject | any): SimpleObject; | ||
export declare function isEmpty(obj: any): boolean; | ||
export declare function is(errors: string[], errorsToCheck: string[] | string): boolean; |
@@ -1,2 +0,1 @@ | ||
import { isArray } from 'lodash'; | ||
export function hasOwnProperty(object, key) { | ||
@@ -7,3 +6,3 @@ if (!object || !key) | ||
} | ||
export const flattenObject = (obj = {}) => { | ||
export function flattenObject(obj = {}) { | ||
const flattened = {}; | ||
@@ -13,3 +12,3 @@ function recurse(current, property) { | ||
return; | ||
if (Object(current) !== current || isArray(current)) { | ||
if (Object(current) !== current || Array.isArray(current)) { | ||
flattened[property] = current; | ||
@@ -21,3 +20,3 @@ } | ||
isEmpty = false; | ||
recurse(current[p], property ? property + '.' + p : p); | ||
recurse(current[p], property ? `${property}.${p}` : p); | ||
} | ||
@@ -28,7 +27,6 @@ if (isEmpty) | ||
} | ||
if (obj) { | ||
if (obj) | ||
recurse(obj); | ||
} | ||
return flattened; | ||
}; | ||
} | ||
export function isEmpty(obj) { | ||
@@ -39,3 +37,3 @@ if (typeof obj === 'number') | ||
return obj.length === 0; | ||
else if (isArray(obj)) | ||
else if (Array.isArray(obj)) | ||
return obj.length === 0; | ||
@@ -49,1 +47,4 @@ else if (typeof obj === 'object') | ||
} | ||
export function is(errors, errorsToCheck) { | ||
return Array.isArray(errorsToCheck) ? errorsToCheck.some(w => is(errors, w)) : errors.includes(errorsToCheck); | ||
} |
@@ -1,3 +0,4 @@ | ||
export declare const formatter: (attribute: string) => string; | ||
export declare function formatter(attribute: string): string; | ||
export declare function toCamelCase(s: string): string; | ||
export declare function toSnakeCase(e: string): string; | ||
export declare function onlyDigits(str: string | boolean | number): boolean; |
@@ -1,4 +0,4 @@ | ||
export const formatter = (attribute) => { | ||
export function formatter(attribute) { | ||
return attribute.replace(/[_.\[]/g, ' ').replace(/]/g, ''); | ||
}; | ||
} | ||
export function toCamelCase(s) { | ||
@@ -9,5 +9,8 @@ return s.replace(/([-_][a-z])/gi, ($1) => { | ||
} | ||
export function toSnakeCase(e) { | ||
return (e.match(/([A-Z])/g) ? e.replace(/[A-Z]/g, l => `_${l.toLowerCase()}`) : e); | ||
} | ||
export function onlyDigits(str) { | ||
const num = Number(str); | ||
return !isNaN(num) && typeof str !== 'boolean'; | ||
return !Number.isNaN(num) && typeof str !== 'boolean'; | ||
} |
{ | ||
"name": "@chantouchsek/validatorjs", | ||
"version": "1.2.3", | ||
"version": "1.3.0", | ||
"description": "The validatorjs library makes data validation in JavaScript very easy in both the browser and Node.js.", | ||
"main": "dist/main.js", | ||
"types": "dist/main.d.ts", | ||
"scripts": { | ||
"dev": "tsc -w", | ||
"clean": "rimraf dist", | ||
"build": "yarn clean && tsc", | ||
"test": "vitest --run", | ||
"test:watch": "yarn test", | ||
"test:cov": "vitest run --coverage", | ||
"release": "standard-version && git push --follow-tags origin main && yarn publish", | ||
"lint:js": "eslint --ext \".js,.ts\" --ignore-path .gitignore .", | ||
"lint:prettier": "prettier --check .", | ||
"lint": "yarn lint:js && yarn lint:prettier", | ||
"lintfix": "prettier --write --list-different . && yarn lint:js --fix", | ||
"prepare": "husky install", | ||
"typecheck": "tsc --noEmit" | ||
"author": { | ||
"name": "Chantouch Sek", | ||
"email": "chantouchsek.cs83@gmail.com", | ||
"url": "https://chantouch.me" | ||
}, | ||
"license": "MIT", | ||
"homepage": "https://github.com/chantouchsek/validatorjs#readme", | ||
"repository": { | ||
@@ -26,5 +16,5 @@ "type": "git", | ||
}, | ||
"files": [ | ||
"dist" | ||
], | ||
"bugs": { | ||
"url": "https://github.com/chantouchsek/validatorjs/issues" | ||
}, | ||
"keywords": [ | ||
@@ -35,46 +25,48 @@ "validator", | ||
], | ||
"author": { | ||
"name": "Chantouch Sek", | ||
"email": "chantouchsek.cs83@gmail.com", | ||
"url": "https://chantouch.me" | ||
}, | ||
"main": "dist/main.js", | ||
"types": "dist/main.d.ts", | ||
"files": [ | ||
"dist" | ||
], | ||
"engines": { | ||
"node": "^12.20.0 || >=14.13.0" | ||
}, | ||
"lint-staged": { | ||
"*.{js,ts}": "eslint --cache", | ||
"*.**": "prettier --check --ignore-unknown" | ||
"scripts": { | ||
"dev": "tsc -w", | ||
"clean": "rimraf dist", | ||
"build": "yarn clean && tsc", | ||
"test": "vitest --run", | ||
"test:watch": "vitest watch", | ||
"test:cov": "vitest run --coverage", | ||
"release": "standard-version && git push --follow-tags origin main && yarn publish", | ||
"lint": "eslint .", | ||
"lint:fix": "eslint . --fix", | ||
"prepare": "husky install", | ||
"typecheck": "tsc --noEmit" | ||
}, | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/chantouchsek/validatorjs/issues" | ||
"dependencies": { | ||
"lodash": "^4.17.21" | ||
}, | ||
"homepage": "https://github.com/chantouchsek/validatorjs#readme", | ||
"devDependencies": { | ||
"@commitlint/cli": "^17.6.6", | ||
"@commitlint/config-conventional": "^17.6.6", | ||
"@types/lodash": "^4.14.195", | ||
"@types/node": "^20.4.2", | ||
"@typescript-eslint/eslint-plugin": "^5.62.0", | ||
"@typescript-eslint/parser": "^5.62.0", | ||
"@vitest/coverage-v8": "^0.34.1", | ||
"eslint": "^8.45.0", | ||
"eslint-config-prettier": "^9.0.0", | ||
"eslint-plugin-import": "^2.27.5", | ||
"eslint-plugin-prettier": "^4.2.1", | ||
"eslint-plugin-promise": "^6.1.1", | ||
"@antfu/eslint-config": "^0.43.0", | ||
"@commitlint/cli": "^17.7.1", | ||
"@commitlint/config-conventional": "^17.7.0", | ||
"@types/lodash": "^4.14.198", | ||
"@types/node": "^20.6.3", | ||
"@vitest/coverage-v8": "^0.34.4", | ||
"eslint": "^8.49.0", | ||
"eslint-plugin-import": "^2.28.1", | ||
"husky": "^8.0.3", | ||
"lint-staged": "^14.0.0", | ||
"lint-staged": "^14.0.1", | ||
"node-notifier": "^10.0.1", | ||
"prettier": "^2.8.8", | ||
"rimraf": "^5.0.1", | ||
"standard-version": "^9.5.0", | ||
"ts-node": "^10.9.1", | ||
"typescript": "^5.1.6", | ||
"vitest": "^0.34.1" | ||
"typescript": "^5.2.2", | ||
"vitest": "^0.34.4" | ||
}, | ||
"dependencies": { | ||
"lodash": "^4.17.21" | ||
"lint-staged": { | ||
"*.{js,ts}": "eslint --fix" | ||
}, | ||
"engineStrict": true | ||
} |
103
README.md
@@ -8,2 +8,3 @@ # ValidatorJs | ||
[![npm](https://img.shields.io/npm/dm/@chantouchsek/validatorjs.svg?style=flat-square)](https://npmjs.com/package/@chantouchsek/validatorjs) | ||
[![code style](https://antfu.me/badge-code-style.svg)](https://github.com/antfu/eslint-config) | ||
@@ -53,3 +54,3 @@ The ValidatorJs library makes data validation in JavaScript very easy in both the browser and Node.js. This library was | ||
// ES5 | ||
let Validator = require('@chantouchsek/validatorjs') | ||
const Validator = require('@chantouchsek/validatorjs') | ||
``` | ||
@@ -83,3 +84,3 @@ | ||
```js | ||
let data = { | ||
const data = { | ||
name: 'John', | ||
@@ -90,3 +91,3 @@ email: 'johndoe@gmail.com', | ||
let rules = { | ||
const rules = { | ||
name: 'required', | ||
@@ -97,3 +98,3 @@ email: 'required|email', | ||
let validation = new Validator(data, rules) | ||
const validation = new Validator(data, rules) | ||
@@ -109,3 +110,3 @@ validation.passes() // true | ||
```js | ||
let validation = new Validator( | ||
const validation = new Validator( | ||
{ | ||
@@ -136,3 +137,3 @@ name: 'D', | ||
```js | ||
let data = { | ||
const data = { | ||
name: 'John', | ||
@@ -152,3 +153,3 @@ bio: { | ||
```js | ||
let nested = { | ||
const nested = { | ||
name: 'required', | ||
@@ -166,4 +167,4 @@ bio: { | ||
let flattened = { | ||
name: 'required', | ||
const flattened = { | ||
'name': 'required', | ||
'bio.age': 'min:18', | ||
@@ -180,3 +181,3 @@ 'bio.education.primary': 'string', | ||
```js | ||
let data = { | ||
const data = { | ||
users: [ | ||
@@ -200,3 +201,3 @@ { | ||
```js | ||
let rules = { | ||
const rules = { | ||
'users.*.name': 'required', | ||
@@ -307,6 +308,6 @@ 'users.*.bio.age': 'min:18', | ||
```js | ||
let rules = { | ||
const rules = { | ||
phone: 'required|digits|max:11', | ||
} | ||
let input = { | ||
const input = { | ||
phone: '01234567890', | ||
@@ -320,6 +321,6 @@ } | ||
```js | ||
let rules = { | ||
const rules = { | ||
phone: 'integer|max:16', | ||
} | ||
let input = { | ||
const input = { | ||
phone: '18', | ||
@@ -339,6 +340,6 @@ } | ||
```js | ||
let rules = { | ||
const rules = { | ||
phone: 'required|digits|min:11', | ||
} | ||
let input = { | ||
const input = { | ||
phone: '01234567890', | ||
@@ -352,6 +353,6 @@ } | ||
```js | ||
let rules = { | ||
const rules = { | ||
phone: 'integer|min:11', | ||
} | ||
let input = { | ||
const input = { | ||
phone: '18', | ||
@@ -371,3 +372,3 @@ } | ||
```js | ||
let rules = { | ||
const rules = { | ||
amount: 'numeric|digits:5', | ||
@@ -414,3 +415,3 @@ } | ||
```js | ||
let rules = { | ||
const rules = { | ||
email: 'sometimes|required|email', | ||
@@ -450,3 +451,3 @@ } | ||
```js | ||
let validation = new Validator( | ||
const validation = new Validator( | ||
{ | ||
@@ -471,3 +472,3 @@ name: 'Doe', | ||
```js | ||
let validation = new Validator( | ||
const validation = new Validator( | ||
{ | ||
@@ -503,3 +504,3 @@ age: 30, | ||
'telephone', | ||
function (value, requirement, attribute) { | ||
(value, requirement, attribute) => { | ||
// requirement parameter defaults to null | ||
@@ -517,3 +518,3 @@ return value.match(/^\d{3}-\d{3}-\d{4}$/) | ||
```js | ||
Validator.registerAsync('username_available', function (username, attribute, req, passes) { | ||
Validator.registerAsync('username_available', (username, attribute, req, passes) => { | ||
// do your database/api checks here etc | ||
@@ -529,3 +530,3 @@ // then call the `passes` method where appropriate: | ||
```js | ||
let validator = new Validator( | ||
const validator = new Validator( | ||
{ | ||
@@ -555,3 +556,3 @@ username: 'test123', | ||
```js | ||
let validation = new Validator( | ||
const validation = new Validator( | ||
{ | ||
@@ -574,3 +575,3 @@ name: 'John', | ||
```js | ||
let validation = new Validator( | ||
const validation = new Validator( | ||
{ | ||
@@ -595,3 +596,3 @@ name: 'John', | ||
```js | ||
let validation = new Validator( | ||
const validation = new Validator( | ||
{ | ||
@@ -645,3 +646,3 @@ name: 'John', | ||
```js | ||
let validation = new Validator(input, rules) | ||
const validation = new Validator(input, rules) | ||
validation.errors.first('email') // returns first error message for email attribute | ||
@@ -658,11 +659,11 @@ validator.errors.get('email') // returns an array of error messages for the email attribute | ||
```js | ||
let input = { | ||
const input = { | ||
name: '', | ||
} | ||
let rules = { | ||
const rules = { | ||
name: 'required', | ||
} | ||
let validation = new Validator(input, rules, { | ||
const validation = new Validator(input, rules, { | ||
required: 'You forgot to give a :attribute', | ||
@@ -677,11 +678,11 @@ }) | ||
```js | ||
let input = { | ||
const input = { | ||
username: 'myusernameistoolong', | ||
} | ||
let rules = { | ||
const rules = { | ||
username: 'max:16', | ||
} | ||
let validation = new Validator(input, rules, { | ||
const validation = new Validator(input, rules, { | ||
max: { | ||
@@ -698,7 +699,7 @@ string: 'The :attribute is too long. Max length is :max.', | ||
```js | ||
let input = { name: '', email: '' } | ||
let rules = { name: 'required', email: 'required' } | ||
const input = { name: '', email: '' } | ||
const rules = { name: 'required', email: 'required' } | ||
let validation = new Validator(input, rules, { | ||
'required.email': "Without an :attribute we can't reach you!", | ||
const validation = new Validator(input, rules, { | ||
'required.email': 'Without an :attribute we can\'t reach you!', | ||
}) | ||
@@ -726,5 +727,4 @@ | ||
) | ||
if (validator.fails()) { | ||
if (validator.fails()) | ||
validator.errors.first('form.name') // "The Userame need to be filled." | ||
} | ||
``` | ||
@@ -735,7 +735,6 @@ | ||
```js | ||
let validator = new Validator({ name: '' }, { name: 'required' }) | ||
const validator = new Validator({ name: '' }, { name: 'required' }) | ||
validator.setAttributeNames({ name: 'custom_name' }) | ||
if (validator.fails()) { | ||
if (validator.fails()) | ||
validator.errors.first('name') // "The custom_name field is required." | ||
} | ||
``` | ||
@@ -749,3 +748,3 @@ | ||
// Configure global formatter. | ||
Validator.setAttributeFormatter(function (attribute) { | ||
Validator.setAttributeFormatter((attribute) => { | ||
return attribute.replace(/_/g, ' ') | ||
@@ -755,9 +754,8 @@ }) | ||
// Or configure formatter for particular instance. | ||
let validator = new Validator({ first_name: '' }, { first_name: 'required' }) | ||
validator.setAttributeFormatter(function (attribute) { | ||
const validator = new Validator({ first_name: '' }, { first_name: 'required' }) | ||
validator.setAttributeFormatter((attribute) => { | ||
return attribute.replace(/_/g, ' ') | ||
}) | ||
if (validator.fails()) { | ||
if (validator.fails()) | ||
console.log(validator.errors.first('first_name')) // The first name field is required. | ||
} | ||
``` | ||
@@ -783,3 +781,4 @@ | ||
```js | ||
let Validator = require('validatorjs') | ||
const Validator = require('validatorjs') | ||
Validator.useLang('km') | ||
@@ -819,3 +818,3 @@ ``` | ||
```js | ||
let messages = Validator.getMessages('en') | ||
const messages = Validator.getMessages('en') | ||
messages.required = 'Whoops, :attribute field is required.' | ||
@@ -822,0 +821,0 @@ Validator.setMessages('en', messages) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
474948
16
172
12475
804