Coder Social home page Coder Social logo

ftonato / nope-validator Goto Github PK

View Code? Open in Web Editor NEW
349.0 9.0 15.0 2.34 MB

A small, simple, and fast JS validator. Like, wow that's fast. ๐Ÿš€

Home Page: https://www.npmjs.com/package/nope-validator

License: MIT License

JavaScript 1.87% TypeScript 98.07% Shell 0.06%
javascript schema object validation form-validation typescript forms form validator

nope-validator's Introduction

Nope ๐Ÿ™…

CircleCI Fast Version size gzip

This project was created by the awesome Bruno Vego - @bvego, and is currently maintained by @ftonato and the community.


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: Nope is not a plug-and-play replacement for Yup, in some cases at least.

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

For more details on what's available in Nope, check out the documentation.

Typescript definitions included. โœจ

Getting started

To start using Nope simply do

yarn add nope-validator

or

npm install -S nope-validator

or (even), do you wanna to try it online?

// import the dependency on your app

// 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')])
    .required(),
});

UserSchema.validate({
  name: 'John',
  email: '[email protected]',
  confirmEmail: '[email protected]',
}); // returns an error object { name: 'Please provide a longer name '};

UserSchema.validate({
  name: 'Jonathan Livingston',
  email: '[email protected]',
  confirmEmail: '[email protected]',
}); // returns undefined since there are no errors

Usage with react-hook-form

Huge thanks to the RHF team for making a resolver for nope, enabling you to use nope as a validator in your RHF-controlled forms.

import { nopeResolver } from '@hookform/resolvers/nope';
import { useForm } from 'react-hook-form';
import * as Nope from 'nope-validator';

const schema = Nope.object().shape({
  username: Nope.string().required(),
  password: Nope.string().required(),
});

function Component({ onSubmit }) {
  const {
    register,
    formState: { errors },
    handleSubmit,
  } = useForm({
    resolver: nopeResolver(schema),
  });

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('username')} />
      {errors.username && <div>{errors.username.message}</div>}

      <input {...register('password')} />
      {errors.password && <div>{errors.password.message}</div>}

      <button type="submit">submit</button>
    </form>
  );
}

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.

import { Formik } from 'formik';
import * as Nope from 'nope-validator';

const schema = Nope.object().shape({
  username: Nope.string().required(),
  password: Nope.string().required(),
});

function Component({ onSubmit }) {
  return (
    <Formik
      initialValues={{ username: '', password: '' }}
      validate={(values) => schema.validate(values)}
      onSubmit={(values) => console.log('Submitted', values)}
    >
      {() => (
        <Form>
          <Field type="username" name="username" />
          <ErrorMessage name="username" component="div" />

          <Field type="password" name="password" />
          <ErrorMessage name="password" component="div" />

          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  );
}

Contribute

Information describing how to contribute can be found here ๐ŸŽ‰

License

MIT

nope-validator's People

Contributors

aamanzi avatar bvego avatar dependabot-preview[bot] avatar dependabot[bot] avatar fossabot avatar ftonato avatar jcolakk avatar jnaputi253 avatar kuzmycz avatar wonderpanda avatar xddz9 avatar yuvalkasay avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nope-validator's Issues

Is it possible to infer the type of an object schema?

Question

I'd like to be able to get a type / interface from an object type, similar to the way Zod does it. Zod is quite heavy, and I dig the lightweight approach here. This should not impact the bundle size or performance, because it's all in TS.

Another example from Superstruct

Something like:

import Nope from 'nope-validator'

const userSchema = Nope.object().shape({
  name: Nope.string().atMost(15).required(),
  email: Nope.string().email("Please provide a valid email").required(),
  favoriteColor: Nope.string()
});

type User = Nope.infer<typeof userSchema>  // { name: string; email: string; favoriteColor?: string }

Were the docs unclear about it?

Nothing mentioned, that I could find.

๐Ÿ›  nope-validator v2.0.0

This is a proposal for the new version of the library: v2.0.0 which implies a complete change (refactoring) of how the data is returned by the library.

The current behaviour is quite simple:

const Nope = require("nope-validator")

const schema = Nope.string().email().required()

schema.validate('[email protected]') // ๐ŸŸข returns undefined since there are no errors

schema.validate('invalid-email') // ๐Ÿ”ด returns a string message with the error: "Input is not a valid email"

There is absolutely nothing wrong with this pattern, however as we are thinking of implementing transformers (handlers for input data), we assumed that it would make more sense to return something different that could benefit users.

So the API return was defined to meet all possible needs, returning not only the error but also the input data and the data that was transformed, as follows:

Key Description
data returns always exactly the input data
transformed returns the transformed data (if any transformation has taken place), otherwise it returns the input data
errors returns an empty array (if there are no errors), otherwise it returns an array of errors

Let's see what the return should look like for both cases (success/error):

๐ŸŸข Success scenario (no errors will be returned)

const Nope = require("nope-validator")

const schema = Nope.string().trim().toLowerCase();
const { data, transformed, errors } = schema.validate('  NOPE-validation  ');

/*
  {
    data: '  NOPE-validation  ',
    transformed : 'nope-validation',
    errors: [ ]
  }
*/

๐Ÿ”ด Failure scenario (a errors list will be returned)

const Nope = require("nope-validator")

const schema = Nope.string().url('url-error-message');
const { data, transformed, errors } = schema.validate('http://');

/*
  {
    data: 'http://',
    transformed : 'http://',
    errors: ['url-error-message']
  }
*/

You may be wondering, but what are the transformers? And the truth is that currently we don't have many defined, only one that was introduced last week (trim #824), however another one has already been requested, it is the case of (default #641), and along with the new version, we plan to release others, like: (toLowerCase, toUpperCase, round.floor**, round.ceil, round.trunc and round.round).

** By the way, round a.k.a. Math['type'].


If you have any ideas/suggestions or if you'd like to contribute to the release of the new version, feel free to reply in this thread and I'll explain how you can. If you want to keep up with the work in progress, keep an eye on the branch where the temp work is being done: https://github.com/ftonato/nope-validator/tree/feat/nope-2.0.0.

Thanks for your attention ๐ŸŽˆ

[Suggestion] add benchmark action to comment on each PR

Question

I was wondering if it makes sense to add an action to run the benchmark for each pull-request, so we can identify if we want or not to merge the change (if it doesn't turn the solution into something so bad, what do you think?

Idea:

  • We run the action to test if everthing still working
  • We run the benchmark/index.ts file and grab all info and send as a comment on the PR, then we can easly understand if make sense or not to merge

Validating schema more than once gives different results

Describe the bug
Validating the same schema more than once gives different results

To Reproduce
Steps to reproduce the behavior:

import Nope from 'nope-validator/lib/cjs'

const schema = Nope.object().shape({
  email: Nope.string().email(),
})

let resp = schema.validate({
  email: '[email protected]',
})
console.log(resp) // undefined
resp = schema.validate({
  email: '[email protected]',
})
console.log(resp) // { email: 'Input is not a valid email' }
resp = schema.validate({
  email: '[email protected]',
})
console.log(resp) // undefined
resp = schema.validate({
  email: '[email protected]',
})
console.log(resp) // { email: 'Input is not a valid email' }

Expected behavior

{ email: 'Input is not a valid email' }
{ email: 'Input is not a valid email' }
{ email: 'Input is not a valid email' }
{ email: 'Input is not a valid email' }

Environment (please complete the following information):
Node 12.4

.trim() functionality

Hi)
Would be great to have .trim() function in validation, like Yup has
Or is there another way in nope-validator to do it right now?

required

Describe the bug
The current definition of required is that the value is undefined or null. The correct definition of required is that the value is not empty. That is not one of

  • undefined

  • null

  • String(value).trim().length > 0

To Reproduce
const value = {value: ''}
const v = Nope.object.shape({value: Nope.string().required('value is required)})
const result = v.validate(value)

// result => undefined

Expected behavior

result = {value: 'value is required'}

Additional context

Add default option

For example:

const foo = Nope.object().shape({
        bar: Nope
               .string()
	       .default("bar"),
});

With Yup one can do that with every type (not just string). Would it be possible to add to Nope?

shape() validation crash on undefined

Describe the bug

Nope.object().shape({a: Nope.string()}).validate(undefined);
TypeError: Cannot read property 'validate' of undefined

Nope.object().shape({a: Nope.string()}).validate();
TypeError: Cannot read property 'validate' of undefined

Expected behavior
It should return undefined like other items validation eg

Nope.array().of(Nope.string()).validate();
undefined

Using ref with primitive methods

Question
Is there any way to use ref with primitive methods like this?

const obj = object().shape({
  start: number(),
  end: number().moreThan(ref('start')),
}),

Were the docs unclear about it?

  • yes. docs say only primitive value can be used

utils.ts: every

Question
I've noticed that utils.ts features the function every that is pretty much the same as Array.prototype.every. Is it on purpose?

I've seen people avoiding Array.prototype.every because they think it's something from the newer ES versions and may be incompatible with the older browsers. But in fact this method was introduced in ES5, the same spec version that introduced Array.prototype.filter

Were the docs unclear about it?

  • N/A, that's the question about the source code

min() is broken (or just confusing)

Description
Nope.string().min(i) and Nope.number().min(i) aren't working as expected.

To Reproduce
Sandbox: https://codesandbox.io/s/intelligent-feistel-2c3wb

Expected behavior
abc should be a valid string().min(3) and 20 should be a valid number().min(20).

Documentation states:

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

It seems that min() currently asserts if the entry is smaller than or equal to a threshold.

Environment
Chrome, nope-validator 0.8.1

Add validateAt and validateAtSync

Is your feature request related to a problem? Please describe.
Make is possible to configure a huge schema, but only validate parts of it.

Describe the solution if you have an idea how it should look like
Let me call validateSyncAt(path) to validate only that path.

Describe alternatives you've considered
First define schema for single field field, and use that variable when defining "global" schema. Then it should be possible to both call validate on the variable or the whole schema separately. (I'm going to try this out now)

Additional context
ref: https://github.com/jquense/yup#mixedvalidateatpath-string-value-any-options-object-promiseany-validationerror

Optional validation

Question

  • I have a schema that looks like this:
const schema = Nope.object().shape({
    name: Nope.string().required(),
    in_use_from: Nope.date().required(),
    address: Nope.object().shape({
        type: Nope.string().required(),
        virtual: Nope.object().shape({
            url: Nope.string().required(),
        }),
        physical: Nope.object().shape({
            site: Nope.object().shape({
                suite: Nope.string().required(),
                street: Nope.string().required(),
                suburb: Nope.string().required(),
                post_code: Nope.string().required(),
                state: Nope.string().required(),
                phone: Nope.string().required(),
            }),
            post: Nope.object().shape({
                suite: Nope.string().required(),
                street: Nope.string().required(),
                suburb: Nope.string().required(),
                post_code: Nope.string().required(),
                state: Nope.string().required(),
                phone: Nope.string().required(),
            })
        })
    })
})

address.type will either be a string 'physical' or 'virtual'.
I want to have the address.virtual object to be validated if address.type == 'virtual', and address.physical to be ignore.
If address.type == 'physical' then I want to have address.physical validated, while the address.virtual part of the validation is ignored.
How can I achieve this with Nope?

Were the docs unclear about it?

  • yes, there are not enough examples on the more complex uses

Cannot use with ES modules due to package.json

Describe the bug
Due to nope's package.json not having "type": "module", when I try to use nope-validator with es modules I get an error SyntaxError: Cannot use import statement outside a module. My project does indeed have "type": "module" in its own package.json, the error I get only shows up when importing from 'nope-validator'. If I go to node_modules/nope-validator/package.json and just add the type field, everything works fine (but I think it wouldn't work anymore if I decided to switch to commonJs).

To reproduce
Steps to reproduce the behavior:
Create a fresh npm project, add "type": "module" to your "package.json"; Run npm install -S nope-validator ; Let the entry point be index.js. Open index.js and write:

import Nope from 'nope-validator'

Run node index.js.

Expected behavior
I expected it not to throw any errors.

Environment:

  • Node version: v16.16.0

No validation on nested schema/data

Describe the bug
A Nope.object won't be validated when inside of a shape. This is useful for validating nested form input, as I am writing a resolver for react-hook-form here: react-hook-form/resolvers#18

To Reproduce
https://codesandbox.io/s/kind-water-4hso5?file=/src/index.js

The return value will be undefined, when it should be along the lines of ShapeError => user.name is missing!

Expected behavior
If you nest shapes, the nested shape fields should be validated.

Nested Object validation doesn't allow for undefined field

Describe the bug
I'm using react hook form and trying to use the functionality where you can nest objects. The use case is for one field that contains several related checkboxes. When validating a nested object an uncaught error is thrown because entry is undefined on line 56 of NopeObject.js.

To Reproduce
Steps to reproduce the behavior:
Include the code and entry

Validation code:

Nope.object().shape({
    email: Nope.string().email().required(),
    options: Nope.object({
        a: Nope.boolean(),
        b: Nope.boolean()
    })
})

Entry Example 1:

{
    email: [email protected]
}

Entry Example 2:

{
    email: [email protected],
    options: {
        a: true,
        b: false
    }
}

Expected behavior
The above should skip undefined when validating objects that aren't required. Required functionality would also be nice if possible for NopeObject.js.

Environment (please complete the following information):

  • Browser/Node version
    Chrome/v14.15.0

Additional context
The optional object in our case is a legal requirement. Based on another field this field will show. That's why it would be nice to have this check if the object is undefined on the line mentioned above.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.