0xc14m1z/regler

View on GitHub
src/object/shape/index.js

Summary

Maintainability
A
0 mins
Test Coverage
import Validator from '../../validator'

import throwIf from '../../helpers/throwIf'

const NO_SCHEMA =
  'The shape schema must be provided'

const INVALID_SCHEMA =
  'The shape schema must be an object'

function shape(schema) {
  throwIf(
    schema === undefined,
    TypeError, NO_SCHEMA
  )

  throwIf(
    typeof schema !== 'object'
    || schema === null
    || schema instanceof Array,
    TypeError, INVALID_SCHEMA
  )

  this.test = testWith(schema)
  this.report = reportWith(schema)

  return this
}

function testWith(schema) {
  return function test(value) {
    if ( !this.parent.test(value) ) return false
    return Object.entries(schema).reduce(testPropertyWith(value), true)
  }
}

function reportWith(schema) {
  return function report(value) {
    if ( this.test(value) ) return false

    const parentReport = this.parent.report(value)
    if ( parentReport ) return parentReport

    return Object.entries(schema).reduce(reportPropertyWith(value), {})
  }
}

function testPropertyWith(value) {
  return function testProperty(result, [property, validator]) {
    if ( !value.hasOwnProperty(property) ) return result
    return result && validator.test(value[property])
  }
}

function reportPropertyWith(value) {
  return function reportProperty(errors, [property, validator]) {
    if ( !value.hasOwnProperty(property) ) return errors

    const propertyValue = value[property]

    if ( validator.test(propertyValue) ) return errors
    errors[property] = validator.report(propertyValue)

    return errors
  }
}

export default Validator.make(shape)