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

struct-js

v1.1.5

Published

`struct.js` is a military-grade validation library, with focus on fluent type definition and precise error reporting.

Downloads

4

Readme

Welcome

struct.js is a military-grade validation library, with focus on fluent type definition and precise error reporting.

npm install struct-js

Terminology

A validator is a Function that returns either exactly true or the precise description of all errors.

For simple values, the description is a String. For containers, the description is a mapping of keys to their individual error description.

function equalsOne(object) {
  return (object === 1) ? true : `Expected 1, not ${object}`
}

A struct is an object where each key is:

  • A built-in type (String, Number, Boolean, or Date)
  • A validator function (equalsOne)
  • An array with a struct as its only element ([ String ])
  • An object with a struct as its values ({ name: String })
const userStruct = {
  name: {
    first: String,
    last: String
  },

  height: Number,
  birth: Date,
  flags: [ Boolean ]
}

Validate

validate(object, struct) is the generic validator. It will verify that an object matches a struct, and return either true or a description.

import { validate } from 'struct-js'

validate("hello", String) // true
validate(123, String)     // "This should be of type String, not Number"

Let's see struct.validate handle an invalid userStruct:

let invalidUser = {
  name: {
    first: false,
    last: 1234
  },

  height: new Date(),
  birth: NaN,
  flags: [ true, 'not a flag', true ]
}

validate(invalidUser, userStruct)
{
  name: {
    first: 'This should be of type String, not Boolean',
    last: 'This should be of type String, not Number'
  },

  height: 'This should be of type Number, not Date',
  birth: 'This should be of type Date, not Number',

  flags: { '1': 'This should be of type Boolean, not String' }
}

validate() has two cousins:

  • isValid() returns true or false:

      isValid('string', String) // true
      isValid(1, String)        // false
  • requireValid() throws a ValidationError if not true:

      try {
        requireValid(1, String)
    
      } catch(ve) {
        console.log(ve.details) // the validation result
        console.log(ve.message)
        console.log(ve.stack)
      }

Advanced Validators

The recommended pattern for creating advanced validators is to use a factory, a function that given parameters returns a validator. For example, a more generic version of equalsOne:

function equals(number) {
  return (object) =>
    (object === number) ? true : `Expected ${number}, not ${object}`
}

struct.js alredy comes with some useful factories. import them from the module.

optional

optional(struct) allows an object to be null or undefined, validating it against struct if not.

const struct = {
  unimportant: optional(String)
}

validate({ unimportant: 'nothing' }, struct) // true
validate({ unimportant: null }, struct)      // true
validate({}, struct)                         // true

instanceOf

instanceOf(Class) verifies an object is an insance of a Class.

class X {}

const struct = {
  'x': instanceOf(X)
}

validate({ x: new X() }, struct) // true
validate({ x: 'what?' }, struct)
{ x: 'This should be of type X, not String' }

oneOf

oneOf(...structs) validates an object against many structs, returning true if any validation is successful, an array of error descriptions otherwise.

const struct = {
  secretCode: oneOf(String, Number)
}

validate({ secretCode: 123 }, struct) // true
validate({ secretCode: null }, struct)
{
  secretCode:  [
    'This should be of type String, not null',
    'This should be of type Number, not null'
  ]
}

allOf

allOf(...structs) validates an object against many structs, returning true only if all validations are successful, an array of error descriptions otherwise.

const struct = {
  name: allOf(String, minLength(4))
}

validate({ name: 'John' }, struct) // true
validate({ name: '!' }, struct)
{
  name:  [ 'This should be have length >= 4, not 1' ]
}

inEnum

inEnum(validValues) ensures an object is found in an array of validValues.

const struct = {
  status: inEnum([ 'draft', 'sent', 'deleted' ])
}

validate({ status: 'draft' }, struct) // true
validate({ status: 'other' }, struct)
{
  status: 'This should be one of [draft,sent,deleted], not other'
}

mapOf

mapOf(struct) ensures an object is a mapping of keys to struct values, returning true if every own property passes validation, or a map of keys to errors if not.

const struct = mapOf({ name: String })

validate({ bob: { name: "Bob" } }, struct) // true
validate({ bob: { foo: 1 } }, struct)
{
  "bob": {
    "name": "This should be of type String, not undefined",
    "foo": "This property should not be present"
  }
}

Usage patterns

struct.js can be extremely effective at controlling code complexity and ensuring correctness. Here are some patterns to explore.

Named structs

Assign names to structs, and compose them into complex type definitions:

const userStruct = {
  name: String,
  age : Number
}

const groupStruct = {
  leader : userStruct,
  members: [ userStruct ]
}