1.0.0 • Published 4 years ago

osv v1.0.0

Weekly downloads
8
License
MIT
Repository
github
Last release
4 years ago

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 PathInfoTypeDefault
required?if a value is required or notboolean | <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 PathInfoTypeDefault
itemarray item object schemaObjectSchema
allowNull?allow null as a valid valueboolean
min?at least ... itemsnumber
max?... items at maximumnumber
length?exact ... itemsnumber

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

Options

Everything from BaseSchemaType and ...

Option PathInfoTypeDefault
allowNull?allow null as a valid valueboolean

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

Options

Everything from BaseSchemaType and ...

Option PathInfoTypeDefault
validatecustom validation callbacksee options or callback type

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

Options

Everything from BaseSchemaType and ...

Option PathInfoTypeDefault
allowNull?allow null as a valid valueboolean
min?value has to be ... at leastnumber
max?value has to be ... at maximumnumber
greater?value has to be greater than ...number
less?value has to be less than ...number
integer?value has to be an integerboolean
positive?value has to be positiveboolean
negative?value has to be negativeboolean

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

Options

Everything from BaseSchemaType and ...

Option PathInfoTypeDefault
itemarray item object schemaObjectSchema
allowNull?allow null as a valid valueboolean

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

Options

Everything from BaseSchemaType and ...

Option PathInfoTypeDefault
allowNull?allow null as a valid valueboolean
empty?value is allowed to have a length of 0booleantrue
oneOf?value is allowed to be one of valuesstring[]
regex?value has to match regexRegExp
length?value has to be of lengthnumber
minLength?value has to be longer than minLengthnumber
maxLength?value has to be shorter than maxLengthnumber

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

Options

Everything from BaseSchemaType and ...

Option PathInfoTypeDefault
schemasarray of ObjectSchemas which to use for validationObjectSchema[]
allowNull?allow null as a valid valueboolean
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: 'foo@bar.com',
  followers: ['222222'],
})
  .then((result) => {
    // result:
    /*
      {
        id: '123456',
        username: 'foo',
        email: 'foo@bar.com',
        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

1.0.0

4 years ago

0.2.10

5 years ago

0.2.9

5 years ago

0.2.8

5 years ago

0.2.7

5 years ago

0.2.6

5 years ago

0.2.5

5 years ago

0.2.4

5 years ago

0.2.3

5 years ago

0.2.2

5 years ago

0.2.1

5 years ago

0.2.0

5 years ago

0.1.1

5 years ago

0.1.0

5 years ago