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

skadi

v3.0.0

Published

A validation and object sanitizer based on is-my-json-valid

Downloads

1,489

Readme

skadi

npm version Dependency Status devDependency Status Build Status Coverage Status Code Climate JavaScript Style Guide

A simple object validator/sanitizer based on is-my-json-valid - supports some useful shorthands as well.

Installation

npm install skadi --save

Usage

// Import
const { createValidator, ValidationError } = require('skadi')

// Create a validator using a JSON-schema.
const myValidator = createValidator({
  type: 'object',
  additionalProperties: false,
  properties: {
    name: {
      type: 'string',
      required: true,
    },
  },
})

// Use it
const input = {
  name: 'Test',
  otherStuffThatIsNotRelevant: 'hehe',
}

const result = myValidator(input)
// << { name: 'Test' }

When used like above, validation errors will throw.

try {
  myValidator({ anInvalid: 'object', because: 'it has no name' })
} catch (err) {
  console.log(err instanceof ValidationError) // << true
  console.log(err.errors) // << [{ field: 'name', message: 'is required' }]
}

Alternative usage:

const context = myValidator.context({})
console.log(context.valid()) // << false
console.log(context.errors) // << [{ field: 'name', message: 'is required' }]

const anotherContext = myValidator.context({ name: 'Skadi', other: 'stuff' })
console.log(anotherContext.valid()) // << true
console.log(anotherContext.pick()) // << { name: 'Skadi' }

// We can add errors manually..
anotherContext.errors.push({ field: 'name', message: 'Too cool, man' })
console.log(anotherContext.valid()) // << false

Use Case: custom, async validation.

Because you can add errors manually, custom validation becomes easy (JSON-schema does not allow this).

Here's an example that makes the validator async.

// Factory function that returns a validator.
// It takes a db so we can look up a user.
function createMyAwesomeValidator(db) {
  const validator = createValidator({
    type: 'object',
    properties: {
      username: 'string!', // shortcut, see https://github.com/yanick/json-schema-shorthand#required-property
    },
  })

  return (objToValidate) => {
    const context = validator.context(objToValidate)

    // Check if username is taken. This is async.
    return db.users
      .findWhere({ username: objToValidate.username })
      .then((user) => {
        if (!user) {
          context.errors.push({
            field: 'username',
            message: 'This username is taken!',
          })
        }

        // .end() will do the same as calling
        // validator(obj) directly: sanitize and return the object
        // if successful, throw if not.
        return context.end()
      })
  }
}

// Create our validator..
const myAwesomeValidator = createMyAwesomeValidator(someDbModule)
myAwesomeValidator({ username: 'Skadi' })
  .then((user) => {
    // Success! We now have a sanitized user.
  })
  .catch((err) => {
    // Could be a validation error.
    console.log(err instanceof ValidationError)
  })

Why not just use validator.filter from is-my-json-valid?

Because it mutates the object rather than returning a new one.

Examples

Check the example/ directory, there's an index.js that you can run with node example/index.js.

Top-level API

The skadi object exports 3 things:

  • createValidator: the meat of the package.
  • createPicker: used internally, but could be useful to you.
  • ValidationError: thrown when you've got too much confidence.

createValidator

Given a JSON-schema, will create a validator function.

The 2nd argument is an options object which are passed to is-my-json-valid, with the exception of createError which can be specified to tell Skadi how to throw a validation error.

additionalProperties in JSON-schema means that validation should fail, but Skadi will rewrite the schema so it won't - instead, we filter out unwanted properties after validating. You don't really have to understand this.

const myValidator = createValidator(
  {
    /* schema */
  },
  {
    // -- the following are default options --

    // tells `is-my-json-valid` to validate as much as possible before failing
    greedy: true,
    // tells `is-my-json-valid` to provide some more info on each error
    verbose: true,
    // tells Skadi to throw the result of this function; gets passed the validation errors.
    createError: (validationErrors) => new ValidationError(validationErrors),
  }
)

// This...
myValidator({ some: 'object' })

// Is the *exact same* as...
myValidator.context({ some: 'object' }).end()

createPicker

Given a JSON-schema, will create a picker function used to filter out unwanted properties. Used internally in createValidator.

The function returned takes an object to pick from, and returns a new object with the unwanted properties filtered out.

const myPicker = skadi.createPicker({
  additionalProperties: false,
  properties: {
    name: {
      type: 'string',
    },
  },
})

myPicker({ name: 'Skadi', other: 'stuff' })
// << { name: 'Skadi' }

ValidationError

Thrown when using validator() or validator.context({}).end().

Contains an errors array.

Validation Context object

When using validator.context(obj), a validation context is returned. This is what you get:

  • errors: An array of { field, message }. You can push and pop from it as you see fit. See the async validation use case for an example of how/why you'd want to do this.
  • valid(): Very simply checks the length of errors, and returns true if there are none, and false when there are errors. Does not throw.
  • pick(): Returns a sanitized version of the object passed to context().
  • end(): If valid() returns false, will throw a ValidationError which will contain the errors array. If everything is smooth, returns a sanitized object (using pick()).

Changelog

  • 2.0.2
    • Fix additionalProperties TS typing regression. I need to stop noobing it up.
  • 2.0.1
    • Fix required TS typing regression.
  • 2.0.0
    • Bumped Node engine version to >=10.
    • Add JSONSchemaV6 schema type definition.
    • Update packages.
  • 1.6.0
    • Pick props from oneOf, anyOf, allOf and items when sanitizing.
  • 1.5.1
    • Add more fields to Schema typing.
  • 1.5.0
    • Add createError option to customize the error being thrown.
  • 1.4.0
    • Improved TypeScript type defs
  • 1.3.0
    • Added TypeScript definitions.
  • 1.2.0
    • Updated json-schema-shorthand to 0.2.0, which adds support for the type! shortcut.
  • 1.1.2
    • Added support for allOf, oneOf and not picking.
  • 1.1.1
    • Make it actually be greedy by default, dammit.
  • 1.1.0
    • Added support for passing options to is-my-json-valid.
    • Greedy mode on by default.
  • 1.0.0
    • Added support for JSON Schema Shorthands.
    • Switched to StandardJS style guide.
  • 0.2.0
    • First real release.

Author

Jeff Hansen - @Jeffijoe