sc0ttj / component

A tiny library for isomorphic JavaScript components
MIT License
2 stars 1 forks source link

State schema validation (a shitty propTypes) #5

Closed sc0ttj closed 4 years ago

sc0ttj commented 4 years ago

React has PropTypes, there are various JSON schema validator things around..

Here is a super simple, tiny, stupid one:


var schema = {
  id: "number",
  list: "array",
  name: "string",
  age: age => typeof age === "number" & age > 17 && age < 130,
  foo: {
    baz: "string"
  }
}

var obj = { id: 1, name: "bob", age: 300, list: { one: "two" }, foo: { bar: "thing" } }

var validator = function validator(obj, schema) {

  Object.entries(schema).forEach(item => {
    var key = item[0]
    var val = obj[key]

    var keyType = typeof obj[key]
    var expectedType = schema[key]

    if (expectedType === "array") {
      if (!Array.isArray(val)) {
        errs.push({ key: key, expected: "array", got: keyType})
      }
    }

    // if we have object, call validator on it
    else if (keyType === "object" && !Array.isArray(val)) {
      validator(obj[key], schema[key])
      return false
    }

    // if we have a function, it's a custom validator func, should return true/false
    else if (typeof expectedType === "function") {
      if (!schema[key](val)) {
        errs.push({ key: key, expected: true, got: false})
      }
    }

    // if we have a string, it should be the name of the expected type in the schema
    else if (keyType !== expectedType.toLowerCase()) {
      errs.push({ key: key, expected: schema[key], got: keyType})
    }

  })
  return errs
}

var errs = []
errs = validator(obj, schema)

if (errs.length < 1) {
  console.log('YEEEEHH.. it validated!')
} else {
  console.error('errors after validation', errs)
}

This can be used as a propTypes style add-on for component, to validate the state against a given schema.

The API for Component would be something like this:

var { Component, validator } = require("@scottjarvis/component")
Component.validator = validator

var myComponent = new Component({ some: state })

myComponent.schema = { ... }

myComponent.setState({ ...items: [ 1, 2, 3] })  

// If a schema was defined, setState() will perform validation of the given 
// state against the schema, and will not set state or re-render if validation fails.
sc0ttj commented 4 years ago

Created an npm package for validation of JS objects: https://github.com/sc0ttj/validator

^ can use that in Component..

sc0ttj commented 4 years ago

DONE