Skip to content
A small, simple and fast JS validator. Like, wow thats fast. πŸš€
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.circleci When - conditional validation Jun 30, 2019
.github Sample PR template Jul 4, 2019
benchmark Bump lodash from 4.17.11 to 4.17.14 in /benchmark Jul 11, 2019
src Replacing min()/max() with greaterThan()/lessThan() + atLeast()/atMost() Jul 17, 2019
.gitignore Benchmarks against yup Jun 30, 2019
.prettierrc Initial commit Jun 25, 2019
CHANGELOG Release 0.8.1 Jul 9, 2019
CODE_OF_CONDUCT.md
CONTRIBUTING.md Added CONTRIBUTING.md Jul 2, 2019
LICENSE Initial commit Jun 25, 2019
README.md Replacing min()/max() with greaterThan()/lessThan() + atLeast()/atMost() Jul 17, 2019
jest.config.js Initial commit Jun 25, 2019
nodemon.json Initial commit Jun 25, 2019
package.json Bump @types/node from 12.6.3 to 12.6.6 Jul 17, 2019
tsconfig.json Building for multiple modules Jul 4, 2019
tslint.json v0.5.0: Object extend Jun 29, 2019
yarn.lock Bump @types/node from 12.6.3 to 12.6.6 Jul 17, 2019

README.md

Nope πŸ™…

codebeat badge CircleCI Fast Version size gzip

A small, simple and fast JS validator. Like, wow thats fast. πŸš€

Nope's API is heavily inspired stolen from Yup but Nope attempts to be much smaller and much faster. To achieve this Nope only allows for synchronous data validation which should cover most of the use cases.

Note that instead of throwing errors Nope simply returns the error object and if there are no errors it returns undefined.

Typescript definitions included. πŸš€

Usage

To start using Nope simply do

yarn add nope-validator

or

npm install -S nope-validator
// const Nope = require('nope-validator'); // or
// const { Nope } = require('nope-validator'); // or
import Nope from 'nope-validator';
// create a schema

const UserSchema = Nope.object().shape({
  name: Nope.string()
    .atLeast(5, 'Please provide a longer name')
    .atMost(255, 'Name is too long!'),
  email: Nope.string()
    .email()
    .required(),
  confirmEmail: Nope.string()
    .oneOf([Nope.ref('email')])
    .requried(),
});

UserSchema.validate({
  name: 'John',
  email: 'me@gmail.com',
  confirmEmail: 'me@gmail.com',
}); // returns an error object { name: 'Please provide a longer name '};
UserSchema.validate({
  name: 'Jonathan Livingston',
  email: 'me@gmail.com',
  confirmEmail: 'me@gmail.com',
}); // returns undefined since there are no errors

API

  • Primitives (String, Number, Date, Boolean)

    • when(key: string | string[], conditionObject: { is: boolean | ((...args: any) => boolean), then: NopeSchema, othervise: NopeSchema }) - Conditional validation of a key.

    • The first param is the set of keys (or a single key) that the is predicate should run on.

    • The is param can be set to simply true or false (which will run the .every method on the values and assert the against the passed is) or a predicate that will decide what schema will be active in that moment.

    • const schema = Nope.object().shape({
        check: Nope.boolean().required(),
        test: Nope.string().when('check', {
          is: true,
          then: Nope.string()
            .atLeast(5, 'minError')
            .required(),
          otherwise: Nope.string()
            .atMost(5)
            .required(),
        }),
      });
      
      schema.validate({
        check: true,
        test: 'test',
      }); // { test: 'minError' }
      // or as a predicate
      const schema2 = Nope.object().shape({
        check: Nope.boolean(),
        check2: Nope.boolean(),
        test: Nope.string().when(['check', 'check2'], {
          is: (check, check2) => check && check2,
          then: Nope.string()
            .atLeast(5, 'minError')
            .required(),
          otherwise: Nope.string()
            .atMost(5)
            .required(),
        }),
      });
      schema.validate({
        check: true,
        check2: false,
        test: 'testing',
      }); // { test: 'maxError' }
    • oneOf(options: string | ref[], message: string) - Asserts if the entry is one of the defined options

    • Nope.string()
        .oneOf(['a', 'b', 'c'])
        .validate('b'); // returns undefined
      
      Nope.string()
        .oneOf(['a', 'b', 'c'])
        .validate('d'); // returns the error message
    • notOneOf(options: number | ref[], message: string) - Asserts if the entry is one of the defined options

    • Nope.string()
        .notOneOf([1, 2, 3])
        .validate(5); // returns undefined
      
      Nope.string()
        .notOneOf([1, 2, 3])
        .validate(2); // returns the error message
    • required(message: string) - Asserts if the entry is not nil

    • Nope.string()
        .required()
        .validate('b'); // returns undefined
      
      Nope.string()
        .required()
        .validate(); // returns the error message
    • test(rule: (entry: string) => string | undefined) - Add a custom rule

    • Nope.string()
        .test(a => (a === '42' ? undefined : 'Must be 42'))
        .validate('42'); // returns undefined
      
      Nope.string()
        .test(a => (a === '42' ? undefined : 'Must be 42'))
        .validate('41'); // returns the error message
    • validate(entry: string | undefined | null) - Runs the rule chain against an entry

  • String

    • regex(regex: RegExp, message: string) - Asserts if the entry matches the pattern

    • Nope.string()
        .regex(/abc/i)
        .validate('abc'); // returns undefined
      
      Nope.string()
        .regex(/abc/i)
        .validate('123'); // returns the error message
    • url(message: string) - Asserts if the entry is a valid URL

    • Nope.string()
        .url()
        .validate('http://google.com'); // returns undefined
      
      Nope.string()
        .url()
        .validate('http:google.com'); // returns the error message
    • email(message: string) - Asserts if the entry is a valid email

    • Nope.string()
        .email()
        .validate('test@gmail.com'); // returns undefined
      
      Nope.string()
        .email()
        .validate('testgmail.com'); // returns the error message
    • min(length: number, message: string) - deprecated: alias for greaterThan

    • max(length: number, message: string) - deprecated: alias for lessThan

    • greaterThan(length: number, message: string) - Asserts if the entry is smaller than a threshold

    • Nope.string()
        .greaterThan(4)
        .validate('https'); // returns undefined
      
      Nope.string()
        .greaterThan(4)
        .validate('http'); // returns the error message
    • lessThan(length: number, message: string) - Asserts if the entry is greater than a threshold

    • Nope.string()
        .lessThan(4)
        .validate('url'); // returns undefined
      
      Nope.string()
        .lessThan(4)
        .validate('http'); // returns the error message
  • Number

    • integer(message: string) - Asserts if the entry is an integer

    • Nope.number()
        .integer('error message')
        .validate(2); // returns undefined
      
      Nope.number()
        .integer('error message')
        .validate(4.2); // returns the error message
    • min(size: number, message: string) - deprecated: alias for greaterThan

    • max(size: number, message: string) - deprecated: alias for lessThan

    • greaterThan(size: number, message: string) - Asserts if the entry is smaller than a threshold

    • Nope.number()
        .greaterThan(1, 'error message')
        .validate(2); // returns undefined
      
      Nope.number()
        .greaterThan(1, 'error message')
        .validate(1); // returns the error message
    • lessThan(size: number, message: string) - Asserts if the entry is greater than a threshold

    • Nope.number()
        .lessThan(1, 'error message')
        .validate(-1); // returns undefined
      
      Nope.number()
        .lessThan(1, 'error message')
        .validate(2); // returns the error message
    • positive(message: string) - Asserts if the entry is positive

    • Nope.number()
        .positive('error message')
        .validate(42); // returns undefined
      
      Nope.number()
        .positive('error message')
        .validate(-42); // returns the error message
    • negative(message: string) - Asserts if the entry is negative

    • Nope.number()
        .negative('error message')
        .validate(-42); // returns undefined
      
      Nope.number()
        .negative('error message')
        .validate(42); // returns the error message
  • Date

    • before(date: string | number | Date, message: string) - Asserts if the entry is before a certain date

    • Nope.date()
        .before('2019-01-01')
        .validate('2018-31-12'); // returns undefined
      
      Nope.date()
        .before('2019-01-01')
        .validate('2019-01-02'); // returns the error message
    • after(date: string | number | Date, message: string) - Asserts if the entry is after a certain date

    • Nope.date()
        .after('2019-01-01')
        .validate('2018-02-01'); // returns undefined
      
      Nope.date()
        .after('2019-01-01')
        .validate('2018-31-12'); // returns the error message
  • Boolean

    • true(message: string) - Asserts if the entry is true

    • Nope.boolean()
        .true()
        .validate(true); // returns undefined
      
      Nope.boolean()
        .true()
        .validate(false); // returns the error message
    • false(message: string) - Asserts if the entry is false

    • Nope.boolean()
        .false()
        .validate(false); // returns undefined
      
      Nope.boolean()
        .false()
        .validate(true); // returns the error message
  • Object

    • shape(shape: object) - Sets the shape which of the object. Use name as keys and Nope validators as values

    • const schema = Nope.object().shape({
        name: Nope.string()
          .atMost(15)
          .required(),
        email: Nope.string()
          .email('Please provide a valid email')
          .required(),
      });
      
      const errors = schema.validate({
        name: 'Test',
        email: 'invalidemail',
      });
      
      console.log(errors); // { email: 'Please provide a valid email', }
    • extend(Base: NopeObject) - Extends the schema of an already defined NopeObject

    • const baseSchema = Nope.object().shape({
        password: Nope.string().atLeast(5),
        confirmPassword: Nope.string()
          .oneOf([Nope.ref('password')], "Passwords don't match")
          .required(),
      });
      
      const userSchema = Nope.object()
        .extend(baseSchema)
        .shape({
          name: Nope.string()
            .atLeast(4)
            .required(),
        });
      
      userSchema.validate({
        name: 'Jonathan',
        password: 'birdybird',
        confirmPassworod: 'burdyburd',
      }); // returns { confirmPassword: 'Passwords don\'t match' }
    • noUnknown(message: string) - Return an error message if the entry contains keys that are not defined in the schema

    • const schema = Nope.object().shape({
        name: Nope.string().atLeast(5),
      }).noUnknown('no unknown keys');
      
      schema.validate({
        name: 'Jonathan',
        password: 'birdybird',
      }); // returns 'no unknown keys';
    • validate(entry: object) - Runs the rule chain against an entry

  • Reference - allows the schema to reference other values in the provided entry

    • const schema = Nope.object().shape({
        email: Nope.string()
          .email()
          .atMost(255)
          .required(),
        confirmEmail: Nope.string().oneOf([Nope.ref('email')], 'Must match the first email'),
      });
      
      const errors = schema.validate({
        email: 'me@gmail.com',
        confirmEmail: 'you@gmail.com',
      });
      console.log(errors); // { confirmEmail: 'Must match the first email' }
      
      const noerrors = schema.validate({
        email: 'me@gmail.com',
        confirmEmail: 'me@gmail.com',
      });
      
      console.log(noerrors); // undefined

Usage with Formik

Instead of passing it through the validationSchema prop, you should call Nope's validate on the validate prop as shown in the example below.

const schema = Nope.object().shape({
  email: Nope.string()
    .email()
    .atMost(255)
    .required(),
  password: Nope.string()
    .atLeast(8)
    .atMost(64)
    .required(),
});

<Formik
  initialValues={{ email: '', password: '' }}
  validate={values => schema.validate(values)}
  onSubmit={values => console.log('Submitted', values)}
>
  {() => (
    <Form>
      <Field type="email" name="email" />
      <ErrorMessage name="email" component="div" />
      <Field type="password" name="password" />
      <ErrorMessage name="password" component="div" />
      <button type="submit">Submit</button>
    </Form>
  )}
</Formik>;

Benchmark

nope x 941,878 ops/sec Β±0.37% (94 runs sampled)
yup x 6,566 ops/sec Β±3.24% (90 runs sampled)

I'll add tests against other validation libraries as well.

The benchmark results can be found in the benchmark/ folder along with the specs and the code that was used for the benchmark.

You can’t perform that action at this time.