valia
Version:
A runtime data validator in TypeScript with advanced type inference, built-in validation functions, and seamless integration for server and client environments.
417 lines (339 loc) β’ 13.1 kB
Markdown
# Valia · [](https://www.npmjs.com/package/valia)
Runtime data validator witten in TypeScript.
β‘ **Powerful and Smart Validation** β Seamlessly integrates into **server** and **client** environments.
π§ **Advanced Type Inference** β With advanced type inference, you can retrieve a type that strictly adheres to your schema definition. Combined with **Type Guards**,
this ensures that the validated dataβs type is **precisely inferred**, allowing you to handle your data **safely and reliably** across your application.
π¦ **Built-in Validation** β Standard functions like `isEmail`, `isUuid`, and more to handle common validation needs effortlessly, while ensuring industry-standard compliance, saving you from writing tedious custom validators π.
## Table of Contents
- [Schema](#schema)
- [Instance](#instance)
- [Definition](#definition)
- [Testers](#testers)
- [String](#string-1)
- [Object](#object)
- [Tools](#tools)
- [String](#string-2)
## Getting started
```
npm install valia
```
```ts
import { Schema, SchemaInfer } from 'valia';
const userSchema = new Schema({
type: "struct",
struct: {
name: { type: "string" },
role: {
type: "string",
enum: ["ADMIN", "WORKER", "CUSTOMER"]
}
}
});
type UserSchema = SchemaInfer<typeof userSchema>;
let data: unknown = { name: "Tintin", role: "ADMIN" };
if (userSchema.validate(data) {
/*
The data type is now:
data: {
name: string;
role: "ADMIN" | "WORKER" | "CUSTOMER";
}
*/
console.log(data);
}
```
<br/><br/>
# Schema
## Instance
|Property / Method|Description|
|--|--|
|`criteria` |Property representing the mounted validation criteria.|
|`validate()`|Validates the provided data against the schema. A boolean is returned. This function is a type guard, so if it returns true, the value passed as a parameter will be of the type defined by your schema.<br/>[Learn more about type guards](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates)|
|`evaluate()`|Validates the provided data against the schema. An object is returned with the value passed as a parameter and the rejection status. If the reject status is null, then the returned value will have the type defined by your schema.|
```ts
criteria: MountedCriteria<T>;
validate(value: unknown): value is GuardedCriteria<T>;
evaluate(value: unknown): { reject: SchemaReject, value: null } | { reject: null, value: GuardedCriteria<T> };
```
```ts
interface SchemaReject {
path: {
explicit: [],
implicit: []
};
code: string;
type: string;
label: string | undefined;
message: string | undefined;
};
```
#### Exemple :
> [!NOTE]
> The `criteria` properties of schemas are mounted only once, even if you use them in another schema.
> This can be useful if memory is an important consideration for you or if you plan to create many sub-schemas.
```ts
const nameFormat = new Schema({
label: "NAME_FORMAT",
type: "string",
min: 3,
max: 32
});
const ageFormat = new Schema({
label: "AGE_FORMAT",
type: "number",
min: 13,
max: 128
});
const userSchema = new Schema({
type: "struct",
struct: {
name: nameFormat.criteria,
age: ageFormat.criteria
}
});
let data = { name: "Waitron", age: 200 };
const { reject } = userSchema.evaluate(data);
console.log(reject);
```
```
{
path: {
explicit: ['struct', 'age'],
implicit: ['&', 'age']
},
code: 'VALUE_SUPERIOR_MAX',
type: 'number',
label: 'AGE_FORMAT',
message: undefined
}
```
## Definition
[Number](#number) β’ [String](#string) β’ [Boolean](#boolean) β’ [Struct](#struct) β’
[Record](#record) β’ [Tuple](#tuple) β’ [Array](#array) β’ [Union](#union) β’ [Symbol](#symbol)
> [!NOTE]
> The order of property definitions in the arrays is the same as when executing the tests by the checker.
### Global
|Property|Type|Default|Description|
|--|--|--|--|
|`nullable?` |`boolean`|`false`|Allows `null`|
|`undefinable?`|`boolean`|`false`|Allows `undefined`|
|`label?` |`string` | |String that will be returned in the reject object. Ideal for adding your own error codes, for example.|
|`message?` |`string` | |String that will be returned in the reject object.|
```ts
const schema = new Schema({
type: "string",
optional: true,
label: "OPTIONAL_STRING"
});
```
### Number
|Property<br/><img width="auto"/>|Type<br/><img width="310"/>|Description<br/><img width="auto"/>|
|--|--|--|
|`type` |`"number"` |Type name|
|`min?` |`number` |Minimum value accepted|
|`max?` |`number` |Maximum value accepted|
|`enum?` |`number[]\|Record<string\|number, number>`|Restrict the value to the items of an array, the values of an object, or the values of a TypeScript Enum.|
|`custom?`|`(x: number) => boolean` |Customized test function|
```ts
const schema = new Schema({
type: "number",
min: 0,
max: 50,
custom(x) {
return (x % 2 === 0);
}
});
```
### String
|Property<br/><img width="auto"/>|Type<img width="320"/>|Default<br/><img width="auto"/>|Description<br/><img width="auto"/>|
|--|--|--|--|
|`type` |`"string"` | |Type name|
|`empty?` |`boolean` |`true`|If the string can be empty|
|`min?` |`number` | |Minimum length accepted|
|`max?` |`number` | |Maximum length accepted|
|`enum?` |`string[]\|Record<string\|number, string>`| |Restrict the value to the items of an array, the values of an object, or the values of a TypeScript Enum.|
|`regex?` |`RegExp` | |A native regex|
|`tester?`|`{ name: string, params: object}` | |Allows you to directly apply a test that you will find [here](#string-1), with its parameters if necessary.|
|`custom?`|`(x: string) => boolean` | |Customized test function|
```ts
const schema = new Schema({
type: "string",
min: 0,
max: 6,
empty: false,
tester: { name: "isAscii" }
});
```
### Boolean
|Property|Type|Default|Description|
|--|--|--|--|
|`type`|`"boolean"`||Type name|
```ts
const schema = new Schema({
type: "boolean"
});
```
### Struct
|Property|Type|Description|
|--|--|--|
|`type` |`"struct"` |Type name|
|`optional?` |`Array<string \| symbol>` |Array of optional keys|
|`struct` |`{`<br/>` [key: string \| symbol]:`<br/>` SetableCriteria \| SetableStruct;`<br/>`}`|The object's keys represent the expected keys<br/>and the attributes represent the expected types.<br/>By default, the keys are considered required.|
```ts
const schema = new Schema({
type: "struct",
optional: ["description"],
struct: {
name: { type: "string", max: 20 },
price: { type: "number", min: 0.1 },
description: {
brand: { type: "string", max: 40 },
color: { type: "string", enum: ["BLACK", "WHITE"] }
}
}
});
```
### Record
|Property|Type|Default|Description|
|--|--|--|--|
|`type` |`"record"` | |Type name|
|`empty?`|`boolean` |`false`|If the object can be empty|
|`min?` |`number` | |Minimum properties accepted|
|`max?` |`number` | |Maximum properties accepted|
|`key` |`Criteria<string \| symbol>`| |Criteria of key|
|`value` |`Criteria` | |Criteria of value|
```ts
const schema = new Schema({
type: "record",
max: 10,
key: { type: "string" },
value: { type: "number" }
});
```
### Tuple
|Property|Type|Default|Description|
|--|--|--|--|
|`type` |`"tuple"` ||Type name|
|`tuple` |`[Criteria, ...Criteria[]]`||Criteria of the tuple items|
```ts
const schema = new Schema({
type: "tuple",
tuple: [{ type: "string" }, { type: "number" }
});
```
### Array
|Property|Type|Default|Description|
|--|--|--|--|
|`type` |`"array"` | |Type name|
|`empty?`|`boolean` |`false`|If the array can be empty|
|`min?` |`number` | |Minimum items accepted|
|`max?` |`number` | |Maximum items accepted|
|`item` |`Criteria`| |Criteria of the array items|
```ts
const schema = new Schema({
type: "array",
empty: true,
tuple: [{ type: "string" }, { type: "number" }]
});
```
### Union
|Property|Type|Default|Description|
|--|--|--|--|
|`type` |`"union"` ||Type name|
|`union` |`[Criteria, ...Criteria[]]`||Array in which the possible criteria are listed|
```ts
const schema = new Schema({
type: "array",
item: { type: "union", union: [{ type: "string"}, { type: "number" }]
});
```
### Symbol
|Property|Type|Default|Description|
|--|--|--|--|
|`type` |`"symbol"`||Type name|
|`symbol?`|`symbol` ||Symbol to check|
```ts
const mySymbol = Symbol("enjoy");
const schema = new Schema({
type: "symbol",
symbol: mySymbol
});
```
<br/><br/>
# Testers
### String
|Function|Description|
|--|--|
|`isAscii` |Check if all characters of the string are in the ASCII table.|
|`isIp` |See **isIpV4** and **isIpV6**|
|`isIpV4` |**Standard:** No standard|
|`isIpV6` |**Standard:** No standard|
|`isEmail` |**Standard:** RFC 5321|
|`isDomain` |**Standard:** RFC 1035|
|`isDataURL` |**Standard:** RFC 2397|
|`isUuid` |**Standard:** RFC 9562|
|`isBase16` |**Standard:** RFC 4648|
|`isBase32` |**Standard:** RFC 4648|
|`isBase32Hex`|**Standard:** RFC 4648|
|`isBase64` |**Standard:** RFC 4648|
|`isBase64Url`|**Standard:** RFC 4648|
<br/>
```ts
isIp(str:string, params: IsIpParams): boolean;
```
|Parameter|Description|
|--|--|
|`prefix?: boolean`|Must have a prefix at the end of the IP address indicating the subnet mask.<br/>(e.g., `192.168.0.1/22`)|
<br/>
```ts
isEmail(str:string, params: IsEmailParams): boolean;
```
|Parameter|Description|
|--|--|
|`allowQuotedString?: boolean` |Allows a string enclosed in quotes in the first part of the email address.|
|`allowAddressLiteral?: boolean`|Allows an IPv4 or IPv6 address in place of the domain name.|
<br/>
```ts
isDataURL(str:string, params: IsDataUrlParams): boolean;
```
|Parameter|Description|
|--|--|
|`type?: string` |Specifies the type of media, corresponding to the **image** type in the example.<br/>(e.g., `data:image/gif;base64,R0lGODdhMA`)|
|`subtype?: string[]`|Specifies the sub-type of media, corresponding to the **gif** sub-type in the example.<br/>(e.g., `data:image/gif;base64,R0lGODdhMA`)|
<br/>
```ts
isUuid(str: string, params?: IsUuidParams): boolean;
```
|Parameter|Description|
|--|--|
|`version?: 1\|2\|3\|4\|5\|6\|7`|The version you wish to validate. By default, all versions are validated.|
<br/>
### Object
|Function|Description|
|--|--|
|`isObject` |Checks if it is an object.|
|`isBasicObject` |Checks if it is an object and if it has a prototype of `Object.prototype` or `null`.|
|`isPlainObject` |Checks if it is an object, if it has a prototype of `Object.prototype` or `null`, and if it contains only keys of type `string` or `symbol`.|
|`isArray` |Checks if it is an array.|
|`isFunction` |Checks if it is an function.|
|`isBasicFunction` |Checks if it is a function but not an async, generator or async generator function. For example, an function like `async () => void` will return false.|
|`isAsyncFunction` |Checks if it is an async function.|
|`isGeneratorFunction` |Checks if it is an generator function.|
|`isAsyncGeneratorFunction`|Checks if it is an async generator function.|
<br/><br/>
# Tools
### String
|Function|Description|
|--|--|
|`base16ToBase64`|**Standard :** RFC 4648<br/>Conversion of a string from **base16** to a string in **base64** or **base64Url**.<br/>The input does not need to be in the standard, but the output will be.|
|`base16ToBase32`|**Standard :** RFC 4648<br/>Conversion of a string from **base16** to a string in **base32** or **base32Hex**.<br/>The input does not need to be in the standard, but the output will be.|
|`base64ToBase16`|**Standard :** RFC 4648<br/>Conversion of a string from **base64** or **base64Url** to a string in **base16**.<br/>The input does not need to be in the standard, but the output will be.|
|`base32ToBase16`|**Standard :** RFC 4648<br/>Conversion of a string from **base32** or **base32Hex** to a string in **base16**.<br/>The input does not need to be in the standard, but the output will be.|
```ts
base16ToBase64(input: string, to: "B64" | "B64URL" = "B64", padding: boolean = true): string;
base16ToBase32(input: string, to: "B16" | "B16HEX" = "B16", padding: boolean = true): string;
base64ToBase16(input: string, from: "B64" | "B64URL" = "B64"): string;
base32ToBase16(input: string, from: "B16" | "B16HEX" = "B16") => string;
```
<br/><br/>
Developed in France with passion π«π·