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

schisma

v0.10.1

Published

Schema validator, conformer, and object creator

Downloads

5

Readme

Schisma

Schisma is a zero-dependency object schema creator, validator, conformer, and object instantizer.

Features

Schema Creation

Creation of new schemas is easy.

const schisma = require('schisma')

let mySchema = schisma({
  name: String,
  age: {
    $type: Number,
    $default: () => new Date%104,
  },
  owns: {
    apples: Number,
    cats: [{
      hairless: Boolean,
      age: {
        $type: Number,
        $validate: (v) => {
          if (v > 38) {
            return {expected: '<=38', received: v}
          }
        },
      },
    }],
  },
})

Schema Definition Format

Objects passed to schisma can be declared a variety of ways.

  • As a primitive type.
  • As a null value.
  • As a containing object.
  • As a schisma-style object.
  • As a Schisma instance.
  • As an Array of any of the previous.
Primitive Types

The simplest way of declaring the value a key is supposed to represent is with a primitive type.

{
  name: String,
  age:  Number,
}
Null Value

Null values can be used to declare a field to be null or, if as part of a $typeof Array, that it can be null or otherwise.

{
  alwaysNull: null,
  age: {
    $typeof: [Number, null]
  }
}
Containing Objects

Objects can be used to compose more complex schemas. The key-value pairs can use any of the standard methods outlined earlier.

{
  mouse: {
    manufacturer: String,
    buttons: Number,
    dpi: Number,
  },
}
Regular expression key matching

Regular expressions can also be used via the special $/ key prefix. These allow schemas to receive arbitrary keys that map to concrete types. The value of these regex keys must always be an array of desired types.

{
  "$/.*": [Number],
}

Multiple regular expressions can be used. Matching attempts will be done in order of declaration.

{
  "$/*": [Number],
  "$/(.*)key": [String],
}

Regular keys may be mixed freely and take priority over regex matching.

{
  "$/*": [Number],
  "$/(.*)key": [String],
  myProperty: Boolean,
}
Schisma-style Object

A Schisma-style object can also be used.

{
  $type: Number,
  $default: 20,
}
{
  $typeof: [Number, String],
  $default: 20,
}

Unlike the other value declarations, schisma-style objects are how you can provide validation and default value generation.

  • $type - May be a primitive type, an array, or another object, as per the schisma formatting rules.
  • $typeof [] - An array of any of the types allowed within $type. This limits the given field/object's type to be one of the provided types. If $type and $typeof are used in the same declaration, $type will be ignored.
  • [$default] <Any|Function> - The default value to use when inserting a value or generating a default object. If it is a function, then the return value of said function is used.
  • [$required] - Whether the value should be considered as required for validation and conforming. Defaults to true
  • [$validate] <Function(value,where)> - The function used to validate the value. May return an object that is merged with the resulting SchismaError with any of the following fields. Additionally, if a plain string is returned, it is used as the message field.
    • [value] - The value of the entry. Defaults to the object's original value
    • [where] - Where in the tree the error occurred. Defaults to the full object path
    • [message] - Message of the error.
    • [expected] - Type expected to be seen.
    • [received] - Received type instead of the expected type.
{
  mouse: {
    manufacturer: {
      $type: String,
      $default: "Grojitech",
      $validate: v => {
        switch(v) {
          case 'Grojitech':
          case 'Bricoshift':
          case 'Tacerr':
          case 'Loresair:
            return
          default:
            return {expected: 'Grojitech, Bricoshift, Tacerr, or Loresair'}
        }
      },
    },
    buttons: {
      $type: Number,
      $default: () => { return new Date%2400 },
      $validate: v => {
        if (v < 1 || v > 10) {
          return {expected: 'greater than 1 and less than 10'}
        }
      }
    },
    dpi: {
      $type: Number,
      $required: true,
    }
  },
}
Schisma Instance

Schisma instances can also be used as values.

let ChildSchema = schisma({
  childPropA: Number,
  childPropB: String,
})

let ParentSchema = schisma({
  child: ChildSchema,
  children: [ChildSchema],
})

Schema Validation

A Schisma object can be used to validate provided objects.

let myPersonhood = {
  name: 'OXXO',
  height: 180,
  owns: {
    cats: [
      {
        hairless: true,
        age: 400,
      },
      {
        hairless: false,
        age: 10,
      },
      {
        hairless: 'maybe',
        age: 20,
      },
    ],
  },
}

mySchema.validate(myPersonhood)
/* Returns:
[
  SchismaResult { code: 'missing key', where: 'age' },
  SchismaResult { code: 'missing key', where: 'owns.apples' },
  SchismaResult {
    code: 'no match',
    where: 'owns.cats.2.hairless',
    expected: [Function: Boolean],
    received: 'string',
    value: 'maybe',
    __typeIndex: 0
  },
  SchismaResult {
    code: 'invalid',
    where: 'owns.cats.0.age',
    expected: '<=38',
    received: 400,
    value: 400
  },
  SchismaResult {
    code: 'unexpected key',
    where: 'height',
    received: 180
  }
]
*/

Options can also be passed to validate.

| option | value | default | description |-|-|-|-| | ignoreUnexpected | Boolean | false | Ignores unexpected object keys. | ignoreRequired | Boolean | false | Ignores required object keys. | ignoreShortArrays | Boolean | true | Ignores arrays that are shorter than the schema's array. | ignoreLongArrays | Boolean | true | Ignores arrays that are longer than the schema's array. | flattenErrors | Boolean | true | Flattens all errors to return as a single array rather than heirarchically. | filterNonErrors | Boolean | true | Filters out non error results.

mySchema.validate(myPersonhood, {ignoreUnexpected: true, ignoreRequired: true})
/* Returns:
[
  SchismaResult {
    code: 'no match',
    where: 'owns.cats.2.hairless',
    expected: [Function: Boolean],
    received: 'string',
    value: 'maybe',
    __typeIndex: 0
  },
  SchismaResult {
    code: 'invalid',
    where: 'owns.cats.0.age',
    expected: '<=38',
    received: 400,
    value: 400
  }
]
*/

Schema Conforming

Schisma can also conform an object to itself.

let conformedPerson = mySchema.conform(myPersonhood)
/* Returns:
{ name: 'OXXO',
  age: 89,
  owns:
   { apples: 0,
     cats:
      [ { hairless: true, age: 400 },
        { hairless: false, age: 10 },
        { hairless: true, age: 20 } ] } }
*/

Just like validate, conform can also take options to adjust the output.

| option | value | default | description |-|-|-|-| | removeUnexpected | Boolean | true | Removes unexpected object keys. | insertMissing | Boolean | true | Inserts missing object keys with default values. | growArrays | Boolean | false | Grow arrays to match the length of the schema's array. | shrinkArrays | Boolean | false | Shrink arrays to match the length of the schema's array. | populateArrays | Boolean | false | Populate empty arrays with default instances of their schema elements.

let conformedPerson2 = mySchema.conform(myPersonhood, {removeUnexpected: false, insertMissing: false})
/* Returns:
{ name: 'OXXO',
  owns:
   { cats:
      [ { hairless: true, age: 400 },
        { hairless: false, age: 10 },
        { hairless: true, age: 20 } ] },
  height: 180 }
*/

Schema Default Object Creation

Schisma can create a default object that conforms to its schema.

let newPerson = mySchema.create()
/* Returns:
{ name: '', age: 75, owns: { apples: 0, cats: [] } }
*/

Just like validate and conform, create can take options to adjust object creation.

| option | value | default | description |-|-|-|-| | populateArrays | Boolean | false | Populate arrays with default instances of their schema elements.

let newPerson = mySchema.create({populateArrays: false})
/* Returns:
{ name: '',
  age: 81,
  owns: { apples: 0, cats: [ { hairless: false, age: 0 } ] } }
*/