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

@chantouchsek/validatorjs

Package Overview
Dependencies
Maintainers
1
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@chantouchsek/validatorjs - npm Package Compare versions

Comparing version 1.2.3 to 1.3.0

dist/rules/nullable.d.ts

24

CHANGELOG.md

@@ -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 @@

3

dist/async-resolvers.js

@@ -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;

@@ -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;
}

@@ -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
}

@@ -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)

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc