Giter Site home page Giter Site logo

osv's Introduction

osv - Object Schema Validation

npm GitHub

This library can be used for validating JavaScript objects or other data types like numbers, strings, booleans or arrays. It is very strongly inspired by @hapijs/joi and mongoose schema validation.

import OSV from 'osv';

const schema = OSV.schema({
  users: OSV.array({
    required: true,
    item: OSV.schema({
      username: OSV.string({
        required: true,
        empty: false,
      }),
      role: OSV.string({
        required: true,
        oneOf: ['owner', 'admin', 'subscriber'],
      }),
    }),
  }),
});

const obj = {
  users: [
    {
      username: 'tomato12',
      role: 'owner',
    },
    {
      username: 'apple56',
      role: 'admin',
    },
  ],
}

// asynchronous

const resultAsync = schema.validate(obj); // Promise<Data>

resultAsync
  .then(value => {
    console.log(value); // the validated value
  })
  .catch(e => {
    console.error(e); // ValidationError
  });

// synchronous

const resultSync = schema.validateSync(obj); // { value?: Data, error?: ValidationError, exec: () => Promise<Data> }

resultSync.exec()
  .then(value => {
    console.log(value); // the validated value

    /*
      {
        users: [
          {
            username: 'tomato12',
            role: 'owner',
          },
          {
            username: 'apple56',
            role: 'admin',
          },
        ],
      }
    */
  })
  .catch(e => {
    console.error(e); // ValidationError
  });

Installation

$ npm install --save osv

or

$ yarn add osv

API

This library is able to validate arrays, booleans, numbers, strings and of course objects.

By default, all specified keys of an object are optional. If a key is missing in an object but it has an object with additional keys as its value, a plain object will be added (see examples).

ObjectSchema

// types
type Validator<Data> = BaseSchemaType | ObjectSchema<Data>;

interface DefinitionObject<Data> {
  [path: string]: DefinitionObject<Data> | Validator<Data>;
}

type Definition<Data> = DefinitionObject<Data> | Validator<Data>;

Simply define your object schema and create an ObjectSchema instance.

import OSV, { OSVTypeRef } from 'osv';

interface User {
  id: string;
  username: string;
  role: 'owner' | 'admin' | 'subscriber';
  followers: {
    id: string;
  }[];
}

const definition: OSVTypeRef.Schema.Definition<User> = {
  username: OSV.string({
    required: true,
    empty: false,
  }),
  role: OSV.string({
    required: true,
    oneOf: ['owner', 'admin', 'subscriber'],
  }),
  followers: OSV.array({
    item: OSV.schema({
      id: OSV.string({ required: true, empty: false }),
    }),
  }),
};

const schema = OSV.schema<User>(definition);

After that you can validate objects. The validate method returns a Promise which resolves to the validated data if successful. Otherwise it rejects with a ValidationError.

The validateSync method returns an object with the following schema:

// Data: the data type of the validated value
type ValidationResult<Data> = {
  value?: Data;
  error?: ValidationError;
  exec: () => Promise<Data>;
}
const user1 = {
  username: 'tomato',
  role: 'owner',
  followers: [{
    id: 'apple',
  }],
};

// async

schema.validate(user1)
  .then((user) => {
    // use validated user
    const username = user.username;
  });

// sync

const result = schema.validate(user1);

console.log(result.value, result.error);

const user2 = {
  username: 'tomato',
  role: 'author',
  followers: [{
    id: 'apple',
  }],
};

schema.validate(user1)
  .catch((e) => {
    // ValidationError
    // e.message: 'There was an error while validating: string/not-allowed'
    // e.code: 'string/not-allowed'
    // e.path: 'role'
    // value: 'author'
  });

You can also omit specific paths during checking. These are just transfered onto the result value the way they are on the initial value. A whitelist and a blacklist are both optional.

interface ObjectSchemaValidationOptions {
  check?: {
    whitelist?: string[]; // all paths that should be checked,
    blacklist?: string[]; // all paths that shouldn't be checked
  };
}

schema.validate({
  username: 'tomato',
  role: 'owner',
  followers: [{
    id: undefined,
  }],
}, {
  check: {
    blacklist: ['followers.id'],
  }
}) // succeeds
  .then((user) => {
    // use validated user
    const username = user.username;
    const firstFollowerId = user.followers[0].id; // -> undefined
  });

BaseSchemaType - ObjectSchema.Types.Base

This is the schema type which all others extend from.

Options

Option Path Info Type Default
required? if a value is required or not `boolean <D = any>(value: any, data: D) => boolean`
pre?.validate? run before every validation, returns value <D = any>(value: any, data: D) => any;
post?.validate? run after every validation, returns value <D = any>(value: any, data: D) => any;

ArraySchemaType - OSV.array(options) - ObjectSchema.Types.Array

Options

Everything from BaseSchemaType and ...

Option Path Info Type Default
item array item object schema ObjectSchema
allowNull? allow null as a valid value boolean
min? at least ... items number
max? ... items at maximum number
length? exact ... items number

BooleanSchemaType - OSV.boolean(options) - ObjectSchema.Types.Boolean

Options

Everything from BaseSchemaType and ...

Option Path Info Type Default
allowNull? allow null as a valid value boolean

CustomSchemaType - OSV.custom(options) - ObjectSchema.Types.Custom

Options

Everything from BaseSchemaType and ...

Option Path Info Type Default
validate custom validation callback see options or callback type

NumberSchemaType - OSV.number(options) - ObjectSchema.Types.Number

Options

Everything from BaseSchemaType and ...

Option Path Info Type Default
allowNull? allow null as a valid value boolean
min? value has to be ... at least number
max? value has to be ... at maximum number
greater? value has to be greater than ... number
less? value has to be less than ... number
integer? value has to be an integer boolean
positive? value has to be positive boolean
negative? value has to be negative boolean

OptionalSchemaType - OSV.optional(options) - ObjectSchema.Types.Optional

Options

Everything from BaseSchemaType and ...

Option Path Info Type Default
item array item object schema ObjectSchema
allowNull? allow null as a valid value boolean

StringSchemaType - OSV.string(options) - ObjectSchema.Types.String

Options

Everything from BaseSchemaType and ...

Option Path Info Type Default
allowNull? allow null as a valid value boolean
empty? value is allowed to have a length of 0 boolean true
oneOf? value is allowed to be one of values string[]
regex? value has to match regex RegExp
length? value has to be of length number
minLength? value has to be longer than minLength number
maxLength? value has to be shorter than maxLength number

UnionSchemaType - OSV.union(options) - ObjectSchema.Types.Union

Options

Everything from BaseSchemaType and ...

Option Path Info Type Default
schemas array of ObjectSchemas which to use for validation ObjectSchema[]
allowNull? allow null as a valid value boolean
resolve? get index of schema in schemas array to use for validation. otherwise all schemas are tried. (data: any) => number

Example

interface TestSchema {
  id: string;
  username: string;
  email: string;
  info: {
    person: {
      firstName?: string;
      lastName?: string;
    };
  };
  followers: string[];
}

const schema = OSV.schema<TestSchema>({
  id: OSV.string({ required: true }),
  username: OSV.string({ required: true }),
  email: OSV.string({ required: true }),
  info: {
    person: {
      firstName: OSV.string(),
      lastName: OSV.string(),
    },
  },
  followers: OSV.array({
    item: OSV.schema(OSV.string({ required: true })),
  }),
});

schema.validate({
  id: '123456',
  username: 'foo',
  email: '[email protected]',
  followers: ['222222'],
})
  .then((result) => {
    // result:
    /*
      {
        id: '123456',
        username: 'foo',
        email: '[email protected]',
        info: {
          person: {},
        },
        followers: ['222222'],
      }
    */
  });

Contributing

PR welcome. This repository uses git flow.

Commit format: ACTION: message.

Example: ADD: tests for schema types & object schema validator.
Action words could be e.g. ADD, REFACTOR, RENAME or REMOVE.

License

MIT License

osv's People

Contributors

florianstahr avatar

Stargazers

 avatar

Watchers

 avatar

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.