diff --git a/API.md b/API.md index 6b8cff004..d0651371f 100755 --- a/API.md +++ b/API.md @@ -1,3 +1,134 @@ +### Introduction + +**joi** lets you describe your data using a simple, intuitive, and readable language. Like the rest of the [hapi ecosystem](https://hapi.dev) it fits in, **joi** allows you to describe your data for both input and output validation, as part of a hapi HTTP server or standalone. + +#### Example + +```js +const Joi = require('@hapi/joi'); + +const schema = Joi.object({ + username: Joi.string() + .alphanum() + .min(3) + .max(30) + .required(), + + password: Joi.string() + .pattern(/^[a-zA-Z0-9]{3,30}$/), + + repeat_password: Joi.ref('password'), + + access_token: [ + Joi.string(), + Joi.number() + ], + + birth_year: Joi.number() + .integer() + .min(1900) + .max(2013), + + email: Joi.string() + .email({ minDomainSegments: 2, tlds: { allow: ['com', 'net'] } }) +}) + .with('username', 'birth_year') + .xor('password', 'access_token') + .with('password', 'repeat_password'); + + +schema.validate({ username: 'abc', birth_year: 1994 }); +// -> { value: { username: 'abc', birth_year: 1994 } } + +schema.validate({}); +// -> { value: {}, error: '"username" is required' } + +// Also - + +try { + const value = await schema.validateAsync({ username: 'abc', birth_year: 1994 }); +} +catch (err) { } +``` + +The above schema defines the following constraints: +* `username` + * a required string + * must contain only alphanumeric characters + * at least 3 characters long but no more than 30 + * must be accompanied by `birth_year` +* `password` + * an optional string + * must satisfy the custom regex pattern + * cannot appear together with `access_token` + * must be accompanied by `repeat_password` and equal to it +* `access_token` + * an optional, unconstrained string or number +* `birth_year` + * an integer between 1900 and 2013 +* `email` + * a valid email address string + * must have two domain parts e.g. `example.com` + * TLD must be `.com` or `.net` + +### General Usage + +Usage is a two steps process: + +First, a schema is constructed using the provided types and constraints: + +```js +const schema = Joi.object({ + a: Joi.string() +}); +``` + +Note that **joi** schema objects are immutable which means every additional rule added (e.g. +`.min(5)`) will return a new schema object. + +Second, the value is validated against the defined schema: + +```js +const { error, value } = schema.validate({ a: 'a string' }); +``` + +If the input is valid, then the `error` will be `null`. If the input is invalid, `error` is assigned +a [`ValidationError`](https://github.com/hapijs/joi/blob/master/API.md#validationerror) object +providing more information. + +The schema can be a plain JavaScript object where every key is assigned a **joi** type, or it can be a **joi** type directly: + +```js +const schema = Joi.string().min(10); +``` + +If the schema is a **joi** type, the `schema.validate(value)` can be called directly on the type. When passing a non-type schema object, +the module converts it internally to an object() type equivalent to: + +```js +const schema = Joi.object().keys({ + a: Joi.string() +}); +``` + +When validating a schema: + +* Values (or keys in case of objects) are optional by default. + + ```js + Joi.string().validate(undefined); // validates fine + ``` + + To disallow this behavior, you can either set the schema as `required()`, or set `presence` to `"required"` when passing `options`: + + ```js + Joi.string().required().validate(undefined); + // or + Joi.string().validate(undefined, /* options */ { presence: "required" }); + ``` + +* Strings are utf-8 encoded by default. +* Rules are defined in an additive fashion and evaluated in order, first the inclusive rules, then the exclusive rules. ### `assert(value, schema, [message], [options])` @@ -2965,11 +3096,11 @@ const custom = Joi.extend((joi) => { 'million.round': '"{{#label}}" must be a round number', 'million.dividable': '"{{#label}}" must be dividable by {{#q}}' }, - coerce(schema, value, helpers) { + coerce(value, helpers) { // Only called when prefs.convert is true - if (schema.$_getRule('round')) { + if (helpers.schema.$_getRule('round')) { return { value: Math.round(value) }; } }, diff --git a/README.md b/README.md index a6fdbe5fe..94f46ef3a 100755 --- a/README.md +++ b/README.md @@ -2,142 +2,15 @@ # @hapi/joi -The most powerful schema description language and data validator for JavaScript. +#### The most powerful schema description language and data validator for JavaScript. -[![Build Status](https://travis-ci.org/hapijs/joi.svg?branch=master)](https://travis-ci.org/hapijs/joi) +**joi** is part of the **hapi** ecosystem and was designed to work seamlessly with the [hapi web framework](https://hapi.dev) and its other components (but works great on its own or with other frameworks). If you are using a different web framework and find this module useful, check out [hapi](https://hapi.dev) – they work even better together. -## Introduction +### Visit the [hapi.dev](https://hapi.dev) Developer Portal for tutorials, documentation, and support -**joi** lets you describe your data using a simple, intuitive, and readable language. Like the rest of the [hapi ecosystem](https://hapi.dev) it fits in, **joi** allows you to describe your data for both input and output validation, as part of a hapi HTTP server or standalone. +## Useful resources -## API - -See the detailed [API Reference](https://hapi.dev/family/joi/). - -## Example - -```js -const Joi = require('@hapi/joi'); - -const schema = Joi.object({ - username: Joi.string() - .alphanum() - .min(3) - .max(30) - .required(), - - password: Joi.string() - .pattern(/^[a-zA-Z0-9]{3,30}$/), - - repeat_password: Joi.ref('password'), - - access_token: [ - Joi.string(), - Joi.number() - ], - - birth_year: Joi.number() - .integer() - .min(1900) - .max(2013), - - email: Joi.string() - .email({ minDomainSegments: 2, tlds: { allow: ['com', 'net'] } }) -}) - .with('username', 'birth_year') - .xor('password', 'access_token') - .with('password', 'repeat_password'); - - -schema.validate({ username: 'abc', birth_year: 1994 }); -// -> { value: { username: 'abc', birth_year: 1994 } } - -schema.validate({}); -// -> { value: {}, error: '"username" is required' } - -// Also - - -try { - const value = await schema.validateAsync({ username: 'abc', birth_year: 1994 }); -} -catch (err) { } -``` - -The above schema defines the following constraints: -* `username` - * a required string - * must contain only alphanumeric characters - * at least 3 characters long but no more than 30 - * must be accompanied by `birth_year` -* `password` - * an optional string - * must satisfy the custom regex pattern - * cannot appear together with `access_token` - * must be accompanied by `repeat_password` and equal to it -* `access_token` - * an optional, unconstrained string or number -* `birth_year` - * an integer between 1900 and 2013 -* `email` - * a valid email address string - * must have two domain parts e.g. `example.com` - * TLD must be `.com` or `.net` - -## Usage - -Usage is a two steps process: - -First, a schema is constructed using the provided types and constraints: - -```js -const schema = Joi.object({ - a: Joi.string() -}); -``` - -Note that **joi** schema objects are immutable which means every additional rule added (e.g. -`.min(5)`) will return a new schema object. - -Second, the value is validated against the defined schema: - -```js -const { error, value } = schema.validate({ a: 'a string' }); -``` - -If the input is valid, then the `error` will be `null`. If the input is invalid, `error` is assigned -a [`ValidationError`](https://github.com/hapijs/joi/blob/master/API.md#validationerror) object -providing more information. - -The schema can be a plain JavaScript object where every key is assigned a **joi** type, or it can be a **joi** type directly: - -```js -const schema = Joi.string().min(10); -``` - -If the schema is a **joi** type, the `schema.validate(value)` can be called directly on the type. When passing a non-type schema object, -the module converts it internally to an object() type equivalent to: - -```js -const schema = Joi.object().keys({ - a: Joi.string() -}); -``` - -When validating a schema: - -* Values (or keys in case of objects) are optional by default. - - ```js - Joi.string().validate(undefined); // validates fine - ``` - - To disallow this behavior, you can either set the schema as `required()`, or set `presence` to `"required"` when passing `options`: - - ```js - Joi.string().required().validate(undefined); - // or - Joi.string().validate(undefined, /* options */ { presence: "required" }); - ``` - -* Strings are utf-8 encoded by default. -* Rules are defined in an additive fashion and evaluated in order, first the inclusive rules, then the exclusive rules. +- [Documentation and API](https://hapi.dev/family/joi/) +- [Versions status](https://hapi.dev/resources/status/) +- [Project policies](https://hapi.dev/policies/) +- [Free and commercial support options](https://hapi.dev/support/) diff --git a/test/modify.js b/test/modify.js index 6d615b266..b65087ef0 100755 --- a/test/modify.js +++ b/test/modify.js @@ -722,9 +722,9 @@ describe('Modify', () => { const custom = Joi.extend({ type: 'special', - coerce(schema, value, helpers) { + coerce(value, helpers) { - const swap = schema.$_getFlag('swap'); + const swap = helpers.schema.$_getFlag('swap'); if (swap && swap.$_match(value, helpers.state.nest(swap), helpers.prefs)) {