UNPKG

funval

Version:

A minimalist library for data validation using functions interfaces.

584 lines (378 loc) 12.1 kB
<h1 align="center" style="text-align:center">🦩 Funval</h1> <h4 align="center">A minimalist library for data validation using functions interfaces.</h4> <p align="center"> <a href="https://www.npmjs.org/package/funval"> <img src="http://img.shields.io/npm/v/funval.svg" alt="View On NPM"> </a> <a href="https://travis-ci.org/neuledge/computed-types"> <img src="https://travis-ci.org/neuledge/computed-types.svg?branch=funval" alt="Build Status"> </a> <a href="https://libraries.io/npm/funval/"> <img src="https://img.shields.io/librariesio/release/npm/funval" alt="Dependency Status"> </a> <a href="https://coveralls.io/github/neuledge/computed-types?branch=funval"> <img src="https://coveralls.io/repos/github/neuledge/computed-types/badge.svg?branch=funval" alt="Coverage Status" /> </a> <a href="LICENSE"> <img src="https://img.shields.io/npm/l/funval.svg" alt="License"> </a> </p> <br> <hr /> **WARNING**: This package is deprecated and no longer maintain. Please switch to it's successor: [Computed-Types](https://github.com/neuledge/computed-types). <hr /> **Funval** is a minimalist validation library that seamlessly integrates with your business logic. Using only plain functions, *Funval* knows how to validate your data and automatically generates TypeScript interfaces to reduce code duplications and complexity. ```ts function ValidNumber(input: unknown): number { const value = Number(input); if (isNaN(value)) { throw new TypeError('Invalid number'); } return value; } ``` ### Main Features - **Easy to Read** - Uses functions as types (including `String`, `Number`, `Boolean`, etc...) - **Reusable Interfaces** - Create new validator using plain functions in seconds. - **TypeScript Validation** - Detect errors during compile time. - **Function Composition** - Pipe multiple validators to generate new ones. - **Asynchronous & Synchronous Support** - Automatically detected promises. - **Pure Javascript** - Also works without TypeScript. <br> ## Install ```bash npm i funval ``` <br> ## Usage ```ts import { Schema, Optional, Or, Type, Integer, Between } from 'funval'; const UserSchema = { name: Optional(String), username: /^[a-z0-9]{3,10}$/, status: Or('active' as 'active', 'suspended' as 'suspended'), amount: input => Between(1, 50)(Integer(input)), }; const validator = Schema(UserSchema); let user: Type<typeof UserSchema>; try { user = validator({ username: 'john1', // @ts-ignore Type '"unregistered"' is not assignable to type '"active" | "suspended"'. status: 'unregistered', amount: 20, }); } catch (err) { console.error(err.message, err.paths); } ``` <br> ## Creating Validators A validator is any function that can return a value without throwing any exceptions: ```ts import * as EmailValidator from 'email-validator'; function Email(input: string): string { if (!EmailValidator.validate(input)) { throw new TypeError(`Invalid email address: "${input}"`); } return input; } ``` You can use the above validator on schemas as an `Email` type: ```ts const UserSchema = { email: Email, }; const validator = Schema(UserSchema); ``` <br> ### Asynchronous Validators Asynchronous validators are supported by returning a `Promise` (or `PromiseLike`) values: ```ts import fetch from 'node-fetch'; async function AvailableUsername(input: string): Promise<string> { const res = await fetch(`/check-username?username=${encodeURIComponent(input)}`); if (!res.ok) { throw new TypeError(`Username "${input}" is already taken`); } return input; } ``` *Funval* automatically detects promise and convert the return type of the `Validator` to promise as well: ```ts const UserSchema = { username: AvailableUsername, }; const validator = Schema(UserSchema); const user = await validator({ username: 'test' }); ``` If you prefer, you can safely convert any validator to an asynchronous validator using the `Async` helper: ```ts import { Async, Schema } from 'funval'; const UserSchema = { email: Email, }; const validator = Async(Schema(UserSchema)); // will catch instead of throwing validator({ email: 'invalid-email' }).catch(err => console.err(err)); ``` <br> ## Available Validators All the available validators ordered by type: * **Schema** - [`Schema`](#schema), [`Maybe`](#maybe), [`Optional`](#optional), [`Default`](#default), [`Required`](#required), [`Truthy`](#truthy), [`Or`](#or), [`ArrayOf`](#arrayof), [`TypeOf`](#typeof), [`Any`](#any), [`Override`](#override) [`Test`](#test) * **Comparison** - [`Equals`](#equals), [`GreaterThan`](#greaterthan), [`GreaterThanEqual`](#greaterthanequal), [`LessThan`](#lessthan), [`LessThanEqual`](#lessthanequal), [`Between`](#between) * **Strings** - [`ContentString`](#contentstring), [`TrimString`](#trimstring) [`StringRange`](#stringrange) [`StringMatch`](#stringmatch) * **Numbers** - [`Float`](#float), [`Integer`](#integer) * **Booleans** - [`Bool`](#bool) <br> ### `Schema` ```ts import { Schema } from 'funval'; declare function Schema(schema: any, error?: string | Error): Validator; ``` Validate inputs using the given schema. **Throws:** If the input does not match the given schema. <br> ### `Maybe` ```ts import { Maybe } from 'funval'; declare function Maybe(schema: any, error?: string | Error): Validator; ``` Same as [`Schema`](#schema) but ignores `undefined` or omitted inputs. **Throws:** If the input tested and does not match the given schema. <br> ### `Optional` ```ts import { Optional } from 'funval'; declare function Optional(schema: any, error?: string | Error): Validator; ``` Same as [`Schema`](#schema) but ignores `undefined`, `null` or omitted inputs. **Throws:** If the input tested and does not match the given schema. <br> ### `Default` ```ts import { Default } from 'funval'; declare function Default(schema: any, value: any): Validator; ``` Validate inputs using the given schema or use the given value if input equals to `undefined` or omitted. **Throws:** If the input tested and does not match the given schema. <br> ### `Required` ```ts import { Required } from 'funval'; declare function Required(schema: any, error?: string | Error): Validator; ``` Validate inputs using the given schema. **Throws:** If input is `undefined` or does not match the given schema. <br> ### `Truthy` ```ts import { Truthy } from 'funval'; declare function Truthy<T>(input: T): T; ``` Validate input is truthy. **Throws:** If input is not truthy. <br> ### `Or` ```ts import { Or } from 'funval'; declare function Or(...candidates: any[]): Validator; ``` Validate inputs using any of the given candidates. **Throws:** If the input does not match to any of the given schemas. <br> ### `ArrayOf` ```ts import { ArrayOf } from 'funval'; declare function ArrayOf(itemSchema: any, error?: string | Error): Validator; ``` Validate the input is an array and that each item matches the given schema. **Throws:** If the given input is not an array or one of the items not matches the item schema. <br> ### `TypeOf` ```ts import { TypeOf } from 'funval'; declare function TypeOf( typeOf: | 'string' | 'number' | 'object' | 'boolean' | 'undefined' | 'symbol' | 'bigint', error?: string | Error, ): Validator; ``` Check the input type is equals to the given type. **Throws:** If the input type is different from the given type. <br> ### `Any` ```ts import { Any } from 'funval'; declare function Any(input: any): any; ``` Allow any type of input. **Throws:** Never. <br> ### `Override` ```ts import { Override } from 'funval'; declare function Override(value: any): Validator; ``` Override any input and returns the given value. **Throws:** Never. <br> ### `Test` ```ts import { Test } from 'funval'; declare function Test<T>(test: (input: T) => unknown, error?: string | Error): Validator; ``` Return the input value as is, only if the test function returns a truthy value. **Throws:** If the test function throws or the test function return a non-truthy value. <br> ### `Equals` ```ts import { Equals } from 'funval'; declare function Equals(value: any, error?: string | Error): Validator; ``` Check the input is strictly equals to the given value. **Throws:** If the input does not equal to the given value. <br> ### `GreaterThan` ```ts import { GreaterThan } from 'funval'; declare function GreaterThan(value: any, error?: string | Error): Validator; ``` Check the input is greater than the given value. **Throws:** If the input does not greater than the given value. <br> ### `GreaterThanEqual` ```ts import { GreaterThanEqual } from 'funval'; declare function GreaterThanEqual(value: any, error?: string | Error): Validator; ``` Check the input is greater than or equals the given value. **Throws:** If the input does not greater than or equals the given value. <br> ### `LessThan` ```ts import { LessThan } from 'funval'; declare function LessThan(value: any, error?: string | Error): Validator; ``` Check the input is less than the given value. **Throws:** If the input does not less than the given value. <br> ### `LessThanEqual` ```ts import { LessThanEqual } from 'funval'; declare function LessThanEqual(value: any, error?: string | Error): Validator; ``` Check the input is less than or equals the given value. **Throws:** If the input does not less than or equals the given value. <br> ### `Between` ```ts import { Between } from 'funval'; declare function Between(minValue: any | null, maxValue: any | null, error?: string | Error): Validator; ``` Check the input is between the given boundaries. **Throws:** If the input is not between the given boundaries. <br> ### `ContentString` ```ts import { ContentString } from 'funval'; declare function ContentString(input: unknown): string; ``` Converts any input to a valid string. **Throws:** If input is either `null`, `undefined`, an object without proper `toString` implementation, empty or a whitespace string. <br> ### `TrimString` ```ts import { TrimString } from 'funval'; declare function TrimString(input: unknown): string; ``` Same as [`ContentString`](#contentstring), but `trim` the output as well. **Throws:** If input is either `null`, `undefined`, an object without proper `toString` implementation, empty or a whitespace string. <br> ### `StringRange` ```ts import { StringRange } from 'funval'; declare function StringRange( minLength: number | null, maxLength: number | null, error?: string | Error, ): Validator; ``` Converts any input to a valid string and make sure the string is in the given boundaries. **Throws:** If input is either `null`, `undefined`, an object without proper `toString` implementation, empty string, whitespace string, or string outside of the given boundaries. <br> ### `StringMatch` ```ts import { StringMatch } from 'funval'; declare function StringMatch(regex: RegEx, error?: string | Error): Validator; ``` Validate the input is matches the given regular expression. **Throws:** If input does not match the given regular expression. <br> ### `Float` ```ts import { Float } from 'funval'; declare function Float(input: unknown): number; ``` Converts any input to a valid float number. **Throws:** If the input can not convert to a valid number. <br> ### `Integer` ```ts import { Integer } from 'funval'; declare function Integer(input: unknown): number; ``` Converts any input to a valid integer number. **Throws:** If the input can not convert to a valid number or the number is not an integer. <br> ### `Bool` ```ts import { Bool } from 'funval'; declare function Bool(input: unknown): boolean; ``` Converts any input to a valid boolean. **Throws:** If the input can not convert unambiguously to a boolean. <br> ## License [MIT](LICENSE) license &copy; 2020 [Neuledge](https://neuledge.com)