Validasaur is Deno validation library slightly inspired by Laravel Validation.
Examples
Basic Usage
Write your example.ts
like this:
import { validate } from "https://deno.land/x/validasaur/src/mod.ts";
import { required, isNumber } from "https://deno.land/x/validasaur/src/rules.ts";
const inputs = {
name: "",
age: "20"
};
const [ passes, errors ] = await validate(inputs, {
name: required,
age: [required, isNumber]
});
console.log({ passes, errors });
Run code above with:
deno run example.ts
And this is the result:
{
"passes": false,
"errors": {
"name": {
"required": "name is required"
},
"age": {
"isNumber": "age must be a number"
}
}
}
Formatting Errors
If you want a simpler error message,
you can use flattenMessages
or firstMessages
to format error messages.
For example:
import { validate, flattenMessages, firstMessages } from "https://deno.land/x/validasaur/src/mod.ts";
import { required, isNumber } from "https://deno.land/x/validasaur/src/rules.ts";
const inputs = {
name: "",
age: "20"
};
const [ passes, errors ] = await validate(inputs, {
name: required,
age: [required, isNumber]
});
const firstErrors = firstMessages(errors);
const flattenErrors = flattenMessages(errors);
// Show the difference
console.log({
defaultErrors: errors,
firstErrors,
flattenErrors
});
Result:
{
"defaultErrors": {
"name": {
"required": "name is required"
},
"age": {
"isNumber": "age must be a number"
}
},
"firstErrors": {
"name": "name is required",
"age": "age must be a number"
},
"flattenErrors": {
"name.required": "name is required",
"age.isNumber": "age must be a number",
"name": "name is required",
"age": "age must be a number"
}
}
Custom Error Message
import { validate, flattenMessages } from "https://deno.land/x/validasaur/src/mod.ts";
import {
required,
isNumber,
isString,
validateArray,
validateObject
} from "https://deno.land/x/validasaur/src/rules.ts";
const inputs = {
name: "",
age: '12',
};
const [passes, errors] = await validate(inputs, {
name: required,
age: [required, isNumber],
}, {
messages: {
"name": "Nama tidak boleh kosong",
"age.required": "Usia tidak boleh kosong",
"age.isNumber": "Usia harus berupa angka",
// Use this if you want same message for any rule fail
// "age": "Usia tidak valid"
},
});
console.log({ passes, errors });
Result:
{
"passes": false,
"errors": {
"name": {
"required": "Nama tidak boleh kosong"
},
"age": {
"isNumber": "Usia harus berupa angka"
}
}
}
Validating Array and Object
import { validate, flattenMessages } from "https://deno.land/x/validasaur/src/mod.ts";
import {
required,
isNumber,
isString,
validateArray,
validateObject
} from "https://deno.land/x/validasaur/src/rules.ts";
const inputs = {
name: "",
age: "20",
skills: ["PHP", "Node.js", 0, "Deno"],
address: {
street: null,
city: "Jakarta",
country: "Indonesia",
}
};
const [ passes, errors ] = await validate(inputs, {
name: required,
age: [required, isNumber],
// validateArray(required: boolean, rules: Rule[])
skills: validateArray(true, [isString]),
// validateObject(required: boolean, rules: ValidationRule)
address: validateObject(true, {
street: required,
city: required,
country: required,
}),
});
const flattenErrors = flattenMessages(errors);
console.log({ passes, flattenErrors });
Result:
{
"passes": false,
"flattenErrors": {
"name.required": "name is required",
"age.isNumber": "age must be a number",
"skills.2.isString": "2 must be a string",
"address.street.required": "street is required",
"name": "name is required",
"age": "age must be a number",
"skills.2": "2 must be a string",
"address.street": "street is required"
}
}
Available Rules
required
Value under this field should not be null
, undefined
, or an empty string (""
).
- Invalid values:
null
,undefined
,""
- Valid values:
"0"
,[]
,{}
,0
, etc.
fileExists(pathPrefix: string)
Value under this field must be existed file.
For example you have file /var/www/media/image.jpg
in your file system:
const [ passes, errors ] = await validate({
file1: "image.jpg",
file2: "image.jpg",
file3: "not-image.txt"
}, {
file1: fileExists("/var/www/media"), // << this will be fail because it check "/var/www/mediaimage.jpg"
file2: fileExists("/var/www/media/"), // << this will be pass
file3: fileExists("/var/www/media/"), // << this will be fail because it check "/var/www/media/not-image.txt" that is not exists
})
isArray
Value under this field must be an array.
- Invalid values:
""
,10
,0.5
, etc. - Valid values:
[]
,[1, 2, 3]
,[{x: 10}, {x: 12}]
, etc.
isBool
Value under this field must be a boolean.
- Invalid values:
""
,10
,0.5
, etc. - Valid values:
true
andfalse
.
isEmail
Value under this field must be valid email address.
- Invalid values:
"someone name"
,123
,foo.bar.baz
,foo@bar@baz
, etc. - Valid values:
"someone@mail.com"
,"someone@mail.co.id"
,"someone@[1.2.3.4]"
, etc.
isFloat
Value under this field must be a float number.
- Invalid values:
"0.1"
,[]
,0
,1
,123
, etc. - Valid values:
0.1
,1.2
,12.345
, etc.
isIn(allowedValues: PrimitiveTypes[])
Value under this field must be one of allowed values.
Example:
const [ passes, errors ] = await validate({
value1: "yes",
value2: "no",
value3: "maybe"
}, {
value1: isIn(["yes", "no"]), // passes
value2: isIn(["yes", "no"]), // passes
value3: isIn(["yes", "no"]), // fail
})
isInt
Value under this field must be an integer.
- Invalid values:
0.5
,"123"
, etc. - Valid values:
0
,123
, etc.
isNumber
Value under this field must be a float or an integer.
- Invalid values:
"1"
,"1.5"
, etc. - Valid values:
1
,1.5
, etc.
isNumeric
Same as asNumber
, but it allows numeric string.
- Invalid values:
"1.0abc"
,"x.1"
, etc. - Valid values:
1
,1.5
,"2"
,"2.5"
, etc.
isString
Value under this field must be a string.
- Invalid values:
1
,1.5
, etc. - Valid values:
"1"
,"1.5"
,"foo"
, etc.
lengthBetween(minLength: number, maxLength: number)
Value under this field must be a string that has char length between minLength
and maxLength
.
Example:
const [ passes, errors ] = await validate({
value1: 'foo',
value2: 'foobar',
value3: 'fo',
value4: 'foobars',
}, {
value1: lengthBetween(3, 6), // passes
value2: lengthBetween(3, 6), // passes
value3: lengthBetween(3, 6), // fail
value4: lengthBetween(3, 6), // fail
})
match(regex: RegExp, trim: boolean = false)
Value under this field must be a string that match with given regex
.
const [ passes, errors ] = await validate({
value1: 'foo$',
value2: '$foo',
value3: 'foo1',
value4: 'foo2',
value5: ' foo3',
value6: ' foo4',
}, {
value1: match(/^[a-z0-9]{4}$/), // fail
value2: match(/^[a-z0-9]{4}$/), // fail
value3: match(/^[a-z0-9]{4}$/), // passes
value4: match(/^[a-z0-9]{4}$/), // passes
value5: match(/^[a-z0-9]{4}$/), // fail
value6: match(/^[a-z0-9]{4}$/, true), // passes after trim
})
maxLength(minValue: number)
Value under this field must be a string that has char length lower or equals maxValue
.
Example:
const [ passes, errors ] = await validate({
value1: 'foobarbaz',
value2: 'foobar',
}, {
value1: maxLength(6), // fail
value2: maxLength(6), // passes
})
maxNumber(maxValue: number)
Value under this field should be a number that is not higher than maxValue
.
Example:
const [ passes, errors ] = await validate({
value1: 6,
value2: 5.01,
value3: 5,
value4: 4
}, {
value1: maxNumber(5), // fail
value2: maxNumber(5), // fail
value3: maxNumber(5), // passes
value4: maxNumber(5), // passes
})
minLength(minValue: number)
Value under this field must be a string that has char length higher or equals minValue
.
Example:
const [ passes, errors ] = await validate({
value1: 'foo',
value2: 'foobar',
}, {
value1: minLength(6), // fail
value2: minLength(6), // passes
})
minNumber(minValue: number)
Value under this field should be a number that is not lower than minValue
.
Example:
const [ passes, errors ] = await validate({
value1: 1,
value2: 4.99,
value3: 5,
value4: 5.01,
}, {
value1: minNumber(5), // fail
value2: minNumber(5), // fail
value3: minNumber(5), // passes
value4: minNumber(5), // passes
})
notIn(disallowedValues: PrimitiveTypes[])
Value under this field must not be one of disallowed values.
Example:
const [ passes, errors ] = await validate({
value1: "yes",
value2: "no",
value3: "maybe"
}, {
value1: notIn(["yes", "no"]), // fail
value2: notIn(["yes", "no"]), // fail
value3: notIn(["yes", "no"]), // passes
})
notNull
Value under this field must not be null
.
numberBetween(minValue: number, maxValue: number)
Value under this field must be a number between minValue
and maxValue
.
const [ passes, errors ] = await validate({
value1: 5,
value2: 10,
value3: 4.99,
value4: 10.01,
}, {
value1: numberBetween(5, 10), // passes
value2: numberBetween(5, 10), // passes
value3: numberBetween(5, 10), // fail
value4: numberBetween(5, 10), // fail
})
TODOS
-
isUrl
rule. -
isIpAddress
rule. -
isIpv4
rule. -
isIpv6
rule. -
startsWith
rule to check string prefix. -
endsWith
rule to check string postfix. - add more examples to documentation.