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

schema-typed

v2.2.2

Published

Schema for data modeling & validation

Downloads

295,693

Readme

schema-typed

Schema for data modeling & validation

npm GitHub Actions Coverage Status

Table of Contents

Installation

npm install schema-typed --save

Usage

Getting Started

import { SchemaModel, StringType, DateType, NumberType, ObjectType, ArrayType } from 'schema-typed';

const model = SchemaModel({
  username: StringType().isRequired('Username required'),
  email: StringType().isEmail('Email required'),
  age: NumberType('Age should be a number').range(18, 30, 'Over the age limit'),
  tags: ArrayType().of(StringType('The tag should be a string').isRequired()),
  role: ObjectType().shape({
    name: StringType().isRequired('Name required'),
    permissions: ArrayType().isRequired('Permissions required')
  })
});

const checkResult = model.check({
  username: 'foobar',
  email: '[email protected]',
  age: 40,
  tags: ['Sports', 'Games', 10],
  role: { name: 'administrator' }
});

console.log(checkResult);

checkResult return structure is:

{
  username: { hasError: false },
  email: { hasError: false },
  age: { hasError: true, errorMessage: 'Over the age limit' },
  tags: {
    hasError: true,
    array: [
      { hasError: false },
      { hasError: false },
      { hasError: true, errorMessage: 'The tag should be a string' }
    ]
  },
  role: {
    hasError: true,
    object: {
      name: { hasError: false },
      permissions: { hasError: true, errorMessage: 'Permissions required' }
    }
  }
};

Multiple verification

StringType()
  .minLength(6, "Can't be less than 6 characters")
  .maxLength(30, 'Cannot be greater than 30 characters')
  .isRequired('This field required');

Custom verification

Customize a rule with the addRule function.

If you are validating a string type of data, you can set a regular expression for custom validation by the pattern method.

const model = SchemaModel({
  field1: StringType().addRule((value, data) => {
    return /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(value);
  }, 'Please enter legal characters'),
  field2: StringType().pattern(/^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/, 'Please enter legal characters')
});

model.check({ field1: '', field2: '' });

/**
{
  field1: {
    hasError: true,
    errorMessage: 'Please enter legal characters'
  },
  field2: {
    hasError: true,
    errorMessage: 'Please enter legal characters'
  }
};
**/

Field dependency validation

  1. Use the equalTo method to verify that the values of two fields are equal.
const model = SchemaModel({
  password: StringType().isRequired(),
  confirmPassword: StringType().equalTo('password')
});
  1. Use the addRule method to create a custom validation rule.
const model = SchemaModel({
  password: StringType().isRequired(),
  confirmPassword: StringType().addRule(
    (value, data) => value === data.password,
    'Confirm password must be the same as password'
  )
});
  1. Use the proxy method to verify that a field passes, and then proxy verification of other fields.
const model = SchemaModel({
  password: StringType().isRequired().proxy(['confirmPassword']),
  confirmPassword: StringType().equalTo('password')
});

Asynchronous check

For example, verify that the mailbox is duplicated

function asyncCheckEmail(email) {
  return new Promise(resolve => {
    setTimeout(() => {
      if (email === '[email protected]') {
        resolve(false);
      } else {
        resolve(true);
      }
    }, 500);
  });
}

const model = SchemaModel({
  email: StringType()
    .isEmail('Please input the correct email address')
    .addAsyncRule((value, data) => {
      return asyncCheckEmail(value);
    }, 'Email address already exists')
    .isRequired('This field cannot be empty')
});

model.checkAsync({ email: '[email protected]' }).then(checkResult => {
  console.log(checkResult);
  /**
  {
    email: {
      hasError: true,
      errorMessage: 'Email address already exists'
    }
  };
  **/
});

Validate nested objects

Validate nested objects, which can be defined using the ObjectType().shape method. E.g:

const model = SchemaModel({
  id: NumberType().isRequired('This field required'),
  name: StringType().isRequired('This field required'),
  info: ObjectType().shape({
    email: StringType().isEmail('Should be an email'),
    age: NumberType().min(18, 'Age should be greater than 18 years old')
  })
});

const user = {
  id: 1,
  name: '',
  info: { email: 'schema-type', age: 17 }
};

model.check(data);

/**
 {
  "id": { "hasError": false },
  "name": { "hasError": true, "errorMessage": "This field required" },
  "info": {
    "hasError": true,
    "object": {
      "email": { "hasError": true, "errorMessage": "Should be an email" },
      "age": { "hasError": true, "errorMessage": "Age should be greater than 18 years old" }
    }
  }
}
*/

Combine

SchemaModel provides a static method combine that can be combined with multiple SchemaModel to return a new SchemaModel.

const model1 = SchemaModel({
  username: StringType().isRequired('This field required'),
  email: StringType().isEmail('Should be an email')
});

const model2 = SchemaModel({
  username: StringType().minLength(7, "Can't be less than 7 characters"),
  age: NumberType().range(18, 30, 'Age should be greater than 18 years old')
});

const model3 = SchemaModel({
  groupId: NumberType().isRequired('This field required')
});

const model4 = SchemaModel.combine(model1, model2, model3);

model4.check({
  username: 'foobar',
  email: '[email protected]',
  age: 40,
  groupId: 1
});

API

SchemaModel

SchemaModel is a JavaScript schema builder for data model creation and validation.

static combine(...models)

A static method for merging multiple models.

const model1 = SchemaModel({
  username: StringType().isRequired('This field required')
});

const model2 = SchemaModel({
  email: StringType().isEmail('Please input the correct email address')
});

const model3 = SchemaModel.combine(model1, model2);

check(data: object)

Check whether the data conforms to the model shape definition. Return a check result.

const model = SchemaModel({
  username: StringType().isRequired('This field required'),
  email: StringType().isEmail('Please input the correct email address')
});

model.check({
  username: 'root',
  email: '[email protected]'
});

checkAsync(data: object)

Asynchronously check whether the data conforms to the model shape definition. Return a check result.

const model = SchemaModel({
  username: StringType()
    .isRequired('This field required')
    .addRule(value => {
      return new Promise(resolve => {
        // Asynchronous processing logic
      });
    }, 'Username already exists'),
  email: StringType().isEmail('Please input the correct email address')
});

model
  .checkAsync({
    username: 'root',
    email: '[email protected]'
  })
  .then(result => {
    // Data verification result
  });

checkForField(fieldName: string, data: object, options?: { nestedObject?: boolean })

Check whether a field in the data conforms to the model shape definition. Return a check result.

const model = SchemaModel({
  username: StringType().isRequired('This field required'),
  email: StringType().isEmail('Please input the correct email address')
});

const data = {
  username: 'root'
};

model.checkForField('username', data);

checkForFieldAsync(fieldName: string, data: object, options?: { nestedObject?: boolean })

Asynchronously check whether a field in the data conforms to the model shape definition. Return a check result.

const model = SchemaModel({
  username: StringType()
    .isRequired('This field required')
    .addAsyncRule(value => {
      return new Promise(resolve => {
        // Asynchronous processing logic
      });
    }, 'Username already exists'),
  email: StringType().isEmail('Please input the correct email address')
});

const data = {
  username: 'root'
};

model.checkForFieldAsync('username', data).then(result => {
  // Data verification result
});

MixedType()

Creates a type that matches all types. All types inherit from this base type.

isRequired(errorMessage?: string, trim: boolean = true)

MixedType().isRequired('This field required');

isRequiredOrEmpty(errorMessage?: string, trim: boolean = true)

MixedType().isRequiredOrEmpty('This field required');

addRule(onValid: Function, errorMessage?: string, priority: boolean)

MixedType().addRule((value, data) => {
  return /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(value);
}, 'Please enter a legal character.');

addAsyncRule(onValid: Function, errorMessage?: string, priority: boolean)

MixedType().addAsyncRule((value, data) => {
  return new Promise(resolve => {
    // Asynchronous processing logic
  });
}, 'Please enter a legal character.');

when(condition: (schemaSpec: SchemaDeclaration<DataType, ErrorMsgType>) => Type)

Conditional validation, the return value is a new type.

const model = SchemaModel({
  option: StringType().isOneOf(['a', 'b', 'other']),
  other: StringType().when(schema => {
    const { value } = schema.option;
    return value === 'other' ? StringType().isRequired('Other required') : StringType();
  })
});

/**
{
  option: { hasError: false },
  other: { hasError: false }
}
*/
model.check({ option: 'a', other: '' });

/*
{
  option: { hasError: false },
  other: { hasError: true, errorMessage: 'Other required' }
}
*/
model.check({ option: 'other', other: '' });

Check whether a field passes the validation to determine the validation rules of another field.

const model = SchemaModel({
  password: StringType().isRequired('Password required'),
  confirmPassword: StringType().when(schema => {
    const { hasError } = schema.password.check();
    return hasError
      ? StringType()
      : StringType().addRule(
          value => value === schema.password.value,
          'The passwords are inconsistent twice'
        );
  })
});

check(value: ValueType, data?: DataType):CheckResult

const type = MixedType().addRule(v => {
  if (typeof v === 'number') {
    return true;
  }
  return false;
}, 'Please enter a valid number');

type.check('1'); //  { hasError: true, errorMessage: 'Please enter a valid number' }
type.check(1); //  { hasError: false }

checkAsync(value: ValueType, data?: DataType):Promise<CheckResult>

const type = MixedType().addRule(v => {
  return new Promise(resolve => {
    setTimeout(() => {
      if (typeof v === 'number') {
        resolve(true);
      } else {
        resolve(false);
      }
    }, 500);
  });
}, 'Please enter a valid number');

type.checkAsync('1').then(checkResult => {
  //  { hasError: true, errorMessage: 'Please enter a valid number' }
});
type.checkAsync(1).then(checkResult => {
  //  { hasError: false }
});

label(label: string)

Overrides the key name in error messages.

MixedType().label('Username');

Eg:

SchemaModel({
  first_name: StringType().label('First name'),
  age: NumberType().label('Age')
});

equalTo(fieldName: string, errorMessage?: string)

Check if the value is equal to the value of another field.

SchemaModel({
  password: StringType().isRequired(),
  confirmPassword: StringType().equalTo('password')
});

proxy(fieldNames: string[], options?: { checkIfValueExists?: boolean })

After the field verification passes, proxy verification of other fields.

  • fieldNames: The field name to be proxied.
  • options.checkIfValueExists: When the value of other fields exists, the verification is performed (default: false)
SchemaModel({
  password: StringType().isRequired().proxy(['confirmPassword']),
  confirmPassword: StringType().equalTo('password')
});

StringType(errorMessage?: string)

Define a string type. Supports all the same methods as MixedType.

isEmail(errorMessage?: string)

StringType().isEmail('Please input the correct email address');

isURL(errorMessage?: string)

StringType().isURL('Please enter the correct URL address');

isOneOf(items: string[], errorMessage?: string)

StringType().isOneOf(['Javascript', 'CSS'], 'Can only type `Javascript` and `CSS`');

containsLetter(errorMessage?: string)

StringType().containsLetter('Must contain English characters');

containsUppercaseLetter(errorMessage?: string)

StringType().containsUppercaseLetter('Must contain uppercase English characters');

containsLowercaseLetter(errorMessage?: string)

StringType().containsLowercaseLetter('Must contain lowercase English characters');

containsLetterOnly(errorMessage?: string)

StringType().containsLetterOnly('English characters that can only be included');

containsNumber(errorMessage?: string)

StringType().containsNumber('Must contain numbers');

pattern(regExp: RegExp, errorMessage?: string)

StringType().pattern(/^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/, 'Please enter legal characters');

rangeLength(minLength: number, maxLength: number, errorMessage?: string)

StringType().rangeLength(6, 30, 'The number of characters can only be between 6 and 30');

minLength(minLength: number, errorMessage?: string)

StringType().minLength(6, 'Minimum 6 characters required');

maxLength(maxLength: number, errorMessage?: string)

StringType().maxLength(30, 'The maximum is only 30 characters.');

NumberType(errorMessage?: string)

Define a number type. Supports all the same methods as MixedType.

isInteger(errorMessage?: string)

NumberType().isInteger('It can only be an integer');

isOneOf(items: number[], errorMessage?: string)

NumberType().isOneOf([5, 10, 15], 'Can only be `5`, `10`, `15`');

pattern(regExp: RegExp, errorMessage?: string)

NumberType().pattern(/^[1-9][0-9]{3}$/, 'Please enter a legal character.');

range(minLength: number, maxLength: number, errorMessage?: string)

NumberType().range(18, 40, 'Please enter a number between 18 - 40');

min(min: number, errorMessage?: string)

NumberType().min(18, 'Minimum 18');

max(max: number, errorMessage?: string)

NumberType().max(40, 'Maximum 40');

ArrayType(errorMessage?: string)

Define a array type. Supports all the same methods as MixedType.

isRequiredOrEmpty(errorMessage?: string)

ArrayType().isRequiredOrEmpty('This field required');

rangeLength(minLength: number, maxLength: number, errorMessage?: string)

ArrayType().rangeLength(1, 3, 'Choose at least one, but no more than three');

minLength(minLength: number, errorMessage?: string)

ArrayType().minLength(1, 'Choose at least one');

maxLength(maxLength: number, errorMessage?: string)

ArrayType().maxLength(3, "Can't exceed three");

unrepeatable(errorMessage?: string)

ArrayType().unrepeatable('Duplicate options cannot appear');

of(type: object)

ArrayType().of(StringType('The tag should be a string').isRequired());

DateType(errorMessage?: string)

Define a date type. Supports all the same methods as MixedType.

range(min: Date, max: Date, errorMessage?: string)

DateType().range(
  new Date('08/01/2017'),
  new Date('08/30/2017'),
  'Date should be between 08/01/2017 - 08/30/2017'
);

min(min: Date, errorMessage?: string)

DateType().min(new Date('08/01/2017'), 'Minimum date 08/01/2017');

max(max: Date, errorMessage?: string)

DateType().max(new Date('08/30/2017'), 'Maximum date 08/30/2017');

ObjectType(errorMessage?: string)

Define a object type. Supports all the same methods as MixedType.

shape(fields: object)

ObjectType().shape({
  email: StringType().isEmail('Should be an email'),
  age: NumberType().min(18, 'Age should be greater than 18 years old')
});

BooleanType(errorMessage?: string)

Define a boolean type. Supports all the same methods as MixedType.

⚠️ Notes

Default check priority:

  • 1.isRequired
  • 2.All other checks are executed in sequence

If the third argument to addRule is true, the priority of the check is as follows:

  • 1.addRule
  • 2.isRequired
  • 3.Predefined rules (if there is no isRequired, value is empty, the rule is not executed)