Socket
Socket
Sign inDemoInstall

skadi

Package Overview
Dependencies
10
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    skadi

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


Version published
Maintainers
1
Install size
1.64 MB
Created

Readme

Source

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

FAQs

Last updated on 11 Jan 2023

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc