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

purity

v1.0.3

Published

Purity is a JSON data validation and transformation tool for web browsers and node.js

Downloads

119

Readme

Purity

Purity is a JSON data validation and transformation tool for web browsers and node.js

It can be installed via:

  • npm: npm install purity
  • bower: bower install purity

Purity, Inspired by mongoose, exposes a schema-based validation API allowing you to apply constraints and transformations to the data in your application.

For usage with express, please see the express-purity package on npm.

Quickstart Example

Most of the action happens through the Schema object.

import { Schema } from 'purity';

The following schema expects:

  • title - A non empty string.
  • tags - a comma separated string of tags which will be lowercased and split into an array.
  • comments - An array of objects with properties:
    • likes - a non negative number which defaults to 0.
    • content - a non empty string not exceeding 255 characters.
let toLowercase = v => v.toLowerCase();
let split = v => v.split(',');

const blogPostSchema = Schema({
  title: { $type: String, $required: true },
  tags: { $type: String, $transform: [toLowercase, split] },
  comments: [{
    likes: { $type: Number, $default: 0, $gte: 0 },
    content: { $type: String, $required: true }
  }]
});

Validate some data against the schema, using the callback api...

let dirtyData = {
  title: 'Stuff about lions',
  tags: 'Lions',
  comments: [
    { likes: 123, content: 'lions r cool' },
    { content: 'w/e' }
  ]
};

blogPostSchema.validate(dirtyData, (err, res) => {
  assert.equal(err, null);
  assert.equal(res, {
    title: 'Stuff about lions',
    tags: ['lions'],
    comments: [
      { likes: 123, content: 'lions r cool' },
      { likes: 0, content: 'w/e' }
    ]
  })
})

Or the promise api...

let dirtyData = {
  title: 'Spiders',
  tags: 'HAIRY,LEGS',
  comments: [{ content: 'creepy' }]
};

blogPostSchema.validate(dirtyData)
  .catch(handleError)
  .then(handleSuccess);

Errors have properties to help you make meaningful messages:

let dirtyData = {
  comments: [{ content: 'this one will fail' }]
};

blogPostSchema.validate(dirtyData, function (err, res) {
  assert(err instanceof purity.ValidationError);
  let message = `The blog ${err.path} is ${err.type}`;
  // message -> 'The blog title is missing'
})

API reference

purity.Types

An object containing the aliases of built in types

  • Types.Any - a relaxed type with no formal type checks
  • Types.Boolean
  • Types.String
  • Types.Number
  • Types.Date

purity.Schema(definiton [, options])

Create a re-usable schema to validate data against.

Arguments
  • definition A definition (usually an object) representing the expected data. Detailing type and value constraints, with optional defaults and transformations. See detailed description below for more information.
  • options - schema options
    • options.cast {Boolean} - when true, purity will attempt to cast all properties to their expected types before applying constraints.
Returns

A new Schema instance.


Schema definition

The schema definition is a representation of the constraints and transformations you would like to apply to your data.

Basics

The definition is plain Obejct with the following format:

const definition = {
  /**
   * $type is the only required field.
   * It can be one of purity.Types or an alias for a custom type.
   */
  $type: String,

  /**
   * $required flag defaults to false.
   * Setting this to true will generate errors when
   * the property is null|undefined or an empty string.
   */
  $required: true,

  /**
   * $cast flag determines whether purity will attempt to cast
   * the property to it's declared $type. this overrides schema
   * level cast options and defaults to false.
   */
  $cast: true,

  /**
   * $default can be a static value or a function which yields
   * a default value when the property is null|undefined or
   * an empty string.
   */
  $default: Date.now,

  /**
   * $transform is a mapping function or array of mapping functions
   * which will transform the data.
   */
  $transform: [v => v + 1, v => v - 1, v => 'unnecessary']

  /**
   * More options are available for the built in purity.Types
   * and for custom types which declare constraints
   */
};

const schema = Schema(definiton);

However if you only wish to enforce a type, the following is sufficient:

const schema = Schema(String);

constraints

The following additional constraints can be applied per type:

purity.Types.String

{
  // {Number} assert a minimum string length
  $minlength: 123,

  // {Number} assert a maximum string length
  $maxlength: 456,

  // {Number} assert an exact string length
  $fixedwidth: 789,

  // {RegExp} assert a regex .test()
  $regex: /(?:lions|tigers|bears|)+\soh my$/i
}

purity.Types.Number

{
  // {Number} assert greater than
  $gt: 1,

  // {Number} assert greater than || equal
  $gte: 2,

  // {Number} assert less than
  $lt: 3,

  // {Number} assert less than || equal
  $lte: 4,

  // {Number} assert equal
  $eq: 5,

  // {Number} assert not equal
  $neq: (act, opt) => act !== opt
}

purity.Types.Date

{
  // {Date|Number} assert greater than
  $gt: new Date(),

  // {Date|Number} assert less than
  $lt: Date.now()
}
Arrays

To declare an array, simply wrap the definition in square brackets [].

const schema = Schema([{ $type: Date, $required: true }]);
Nested Objects

For nested objects ...nest them

const schema = Schema({
  id: Number,
  some: {
    deeply: {
      nested: {
        data: { $type: Boolean, $default: true }
      }
    }
  }
});

purity.createDataType(options)

Declare a data custom data type to be used in a schema.

Arguments

options {Object} - with properties:

  • required:
    • aliases
  • optional:
    • check
    • cast
    • constraints

options.aliases {Any|Any[]} - Identifier(s) fot this data type. The alias(es) declared here will be looked up when used to alias a $type in a schema definition.

options.check {Function (value)} - a function which is passed the value of the property currently being processed and should return a Boolean indicating whether or not it is valid. By default this returns true.

options.cast {Function (value)} - a function which maps the value of the property currently being processed to your custom data type. Only invoked when the schema level cast or type level $cast flag is set. By default this is an identity transformation v => v.

options.constraints {Object} - an object mapping type specific constraint names to predicate functions which enforce them.

Important notes: options.check is invoked before any casting is applied. The incoming value will always be a primitive javascript value. Use this opportunity to reject data that cannot be casted.

Examples

Creating a data type

Here is an example of how you might create a data type to handle mongodb ObjectIds.

For those who don't know, an ObjectID is simply a 24 character hex string.


import { ObjectID } from 'mongodb';

purity.createDataType({
  // give the type some aliases so we
  // can refer to it in a schema definition
  aliases: [ObjectID, 'objectid'],

  // implement a quick and dirty check
  // to see if it's a valid ObjectID
  check: v => typeof v === 'string' && /[a-zA-Z0-9]{24}/.test(v),

  // provide a method to cast incoming data
  cast: v => new ObjectID(v),

  // A contrived example of adding constraints
  // we're going to check if the ObjectID
  // ends with a particualr sequence
  constraints: {
    endsWith: (value, option) => {
      // value is the incoming data.
      // option is the character we're looking for
      return value.toString().endsWith(option);
    }
  }
});

Now let's use it in a schema

const schema = Schema(ObejctID, { cast: true });

schema.validate('abcdef0123456789abcdef01', function (e, r) {
  assert.equal(r, ObejctID(abcdef0123456789abcdef01));
});

using the endsWith constraint we defined...

// we can use the other alias we provided as well
const schema = Schema({ $type: 'objectid', endsWith: '02', $cast: true });

schema.validate('abcdef0123456789abcdef01', function (e, r) {
  // the endsWith constraint causes an error
  assert(e instanceof purity.ValidationError);
});

Bugs and Features

Please log any issues or feature requests on github's issue tracker.

Version history

  • 0.x - initial release
  • 1.0.0
    • Breaking changes, please consult the new api to migrate.
    • removed array options
    • removed many mutations in favour of sequential mapping functions
    • removed cleanse alias for Schema#validate
    • added Date type
    • added ability to validate primitives and arrays as root level data

Todo:

  • Travis CI
  • browser testing
  • improve docs
  • customisation around error messages
  • add some support for array options
    • unique
    • option to ignore errors and remove elements instead
    • constraints on array length