npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

nutso

v5.0.2

Published

a typesafe validation library for typescript

Downloads

867

Readme

nutso 🦸🏼‍♂️

Build Status code style: prettier npm version MIT license

A typesafe validation library for typescript!

Both Schema and Result are typesafe! So it's basically Schema<T> and Result<T> 🦸🏼‍♂️

Objective

  • Typesafe
  • Zero dependencies
  • Super Fast
  • Run everywhere (browser & nodejs)

Concept

The idea behind this library is to create a schema from a typescript type. The schema should reflect the structure of the type and should be in sync with it. If the type changes, the typescript compiler should force the schema to be updated, such that you get all the goodness of compile time typechecking for your schema files as well.

  • Writing the Schema is super simple and there is just one 1 mandatory type information for each field.
  • By default each field in the schema is required, if you want to make a field optional, then use the optional: true flag to mark it as optional.
{
  type: "number" | "string" | "date" | "boolean" | "array" | "object";
}

T

T is the type defined in typescript

// type or interface or class
type Customer = {
  name: string;
  dob: Date;
  height: number;
};

Schema < T >

Schema is the validation definition you write for the type T. It is typesafe, so it's super easy to write the schema as the IDE will guide you though the definition for every field. You will literally feel like magic defining the schema. And each time you update T, you will get compiler errors to notify of potential issues with your schema.

  • type is the only required information for each field. Because nutso uses type inference, the type field can only be the type of the field. So you can't go wrong here.

Optional fields in T are optional in schema as well.

const customerSchema: Schema<Customer> = {
  type: "object",
  properties: {
    name: {
      type: "string",
      minLength: 3,
      maxLength: 24,
    },
    dob: {
      type: "date",
    },
    height: {
      type: "number",
      min: 0.1,
      max: 7.5,
    },
  },
};

Result < T >

The result returned by nutso is also typesafe, meaning you will be able to access the validation result and the errorMessage in a type-safe way. You will feel absolutely in control when using the validation result. And again, because it's typesafe as well, when you update the schema, typescript will help you to fix your result where ever you have used it. voila!

const customer: Customer = {
  name: "John Appleseed",
  dob: new Date(), // just born
  height: 3.2,
};

const result: Result<Customer> = validate(customer, customerSchema);
console.log(JSON.stringify(result, null, 2));

The above validation will produce the following output:

{
  "isValid": true,
  "errorMessage": "",
  "properties": {
    "name": {
      "isValid": true,
      "errorMessage": "",
      "errorPath": []
    },
    "dob": {
      "isValid": true,
      "errorMessage": "",
      "errorPath": []
    },
    "height": {
      "isValid": true,
      "errorMessage": "",
      "errorPath": []
    }
  },
  "fieldPath": []
}

The beauty of the Result<T> is the fact that it's typesafe as well.

So you could access the validation result using the following notation:

const result: Result<Customer> = validate(customer, customerSchema);

result.isValid;
result.properties.name.isValid;
result.properties.age.isValid;
result.properties.height.errorMessage;

Validators

Common Fields

The following fields are applicable for all data types.

| name | type | default | description | | -------- | --------- | ------- | --------------------------------------------------------- | | type | string | - | The value of this has to match the data type of the field | | optional | boolean \| function | false | Specify if the field is optional |

When an object is marked as optional in the Schema and if it's undefined, then the object is valid, so the Result will not have the properties field populated for those fields.

Look at the following example:

type Customer = {
  name: string;
  address?: {
    city: string;
  };
};

const obj: Customer = { name: "John" };

const schema: Schema<Customer> = {
  type: "object",
  properties: {
    name: {
      type: "string",
      minLength: 3,
    },
    address: {
      type: "object",
      optional: true,
      properties: {
        city: {
          type: "string",
        },
      },
    },
  },
};

const result = vaildate(obj, schema);

result.properties.address.isValid === true;
result.properties.address.properties === {}; // is empty

String validators

The following validators are applicable for string data type.

| name | type | default | description | | ------------ | ---------- | ------- | -------------------------------------------- | | type | string | - | The value of this has to be 'string' | | minLength | number | - | Minimum length of the string | | maxLength | number | - | Maximum length of the string | | pattern | regex | - | A valid js regex to match against the string | | validationFn | function | - | Validation Function |

Number validators

The following validators are applicable for number data type.

| name | type | default | description | | ------------ | ---------- | ------- | -------------------------------------------- | | type | string | - | The value of this has to be 'number' | | min | number | - | Minimum allowed value of the number | | max | number | - | Maximum allowed value of the number | | pattern | regex | - | A valid js regex to match against the number | | validationFn | function | - | Validation Function |

Date validators

The following validators are applicable for Date data type.

| name | type | default | description | | ------------ | ---------- | ------- | ------------------------------------------- | | type | string | - | The value of this has to be date | | validationFn | function | - | Validation Function |

No other validators are present for date at the moment, it is WIP. Please create an issue if you need specific validators for date.

Boolean validators

The following validators are applicable for Boolean data type.

| name | type | default | description | | ------------ | ---------- | ------- | ------------------------------------------- | | type | string | - | The value of this has to be boolean | | validationFn | function | - | Validation Function |

No other validators are present for date at the moment, it is WIP. Please create an issue if you need specific validators for date.

Array validators

The following validators are applicable for Array data type.

| name | type | default | description | | -------- | ------------- | ------- | ------------------------------------------------- | | type | string | - | The value of this has to be array | | minItems | number | - | The minimun number of items required in the array | | maxItems | number | - | The maximum number of items allowed in the array | | items | Schema<T,R> | - | The schema of the item present in the array |

Example:

type Colors = string[];
const favColors: Colors = ["blue", "green", "black"];
const colorsSchema: Schema<Colors> = {
  type: "array",
  minItems: 3,
  maxItems: 10,
  items: {
    type: "string",
    minLength: 5, // blue will fail
  },
};

Optional Flag (as a function)

The optional flag is supported for all data types and it could either be a boolean or a function. Let's take the following example, in which the endIsoMonth is required, if the tenure is not current.

export type Tenure = {
  startIsoMonth: string;
  endIsoMonth?: string;
  isCurrent: boolean;
};

export const tenureSchema: Schema<Tenure> = {
  type: "object",
  properties: {
    startIsoMonth: {
      type: "string",
      optional: false
    },
    endIsoMonth: {
      type: "string",
      optional: (args) => {
        // this is typesafe too!
        if (args.parent?.isCurrent) return true;
        return false;
      },
    },
    isCurrent: {
      type: "boolean",
    },
  },
};

Validation Function

This is arguably the most powerful feature of nutso. The could solve any of your validation requirements with ease.

export type ValidationFn<T, R, P> = (args: { value: T; parent: P; root: R }) => ValidatorFnResult | void;
  • If the valid is valid then validationFunction should return undefined

Check this TestUsecaseLoginForm test case for an example.

Right now validation function is supported only for the following types, but it will be soon supported on all types.

  • string
  • number
  • date
  • boolean
  • object

Applications

  • Nutso can be used in the UI for form validation and the error messages could be displayed to the users using static typesafe access to the error message.
  • Can aso be used on the server to validate incoming objects against the schema.

You can defind the schema along side your models and use it both on the client and server.

Notes

  • Follows JSON Schema terminology whereever possible [https://json-schema.org/specification.html]

TODO

  • Tuple support
  • Object valiation with circular reference
  • Custom validation function for other data types