Home Reference Source

props/classes/schema.js

import SchemaError from './SchemaError.js'
import props from '../index.js'
import INTEGER from '../Integer.js'
import BOOLEAN from '../Boolean.js'
import DATE from '../Date.js'
import DECIMAL from '../Decimal.js'
import STRING from '../String.js'
import ARRAY from '../Array.js'
import OBJECT from '../Object.js'
// import TEXT from './Text.js'
const getProp = obj => {
  if (obj.isProp) return { Prop: obj }
  if (obj.isObservable) {
    return { Prop: obj }
  }
  if (typeof obj === 'string' && props[obj]) return { Prop: props[obj] }
  if (typeof obj === 'string') return { Prop: STRING, Value: obj }
  if (obj instanceof Date) return { Prop: DATE, Value: obj }
  if (typeof obj === 'number') {
    if (obj === parseInt(obj)) return { Prop: INTEGER, Value: obj }
    return { Prop: DECIMAL, Value: obj }
  }
  if (typeof obj === 'boolean') return { Prop: BOOLEAN, Value: obj }
  if (typeof obj === 'object') {
    if (Object.keys(obj).length === 1 && obj.type && props[obj.type]) {
      return { Prop: props[obj.type] }
    } else if (Object.keys(obj).length === 2 && obj.type && props[obj.type] && obj.value !== undefined) {
      return { Prop: props[obj.type], Value: obj.value }
    } else {
      return { Prop: OBJECT, Value: obj }
    }
  }
  if (obj === null) throw new SchemaError('A NULL value cannot be parsed in a Schema')
  throw new SchemaError(`Schema could not parse the entry ${obj}`)
}

const schema = s => {
  if (s instanceof Array) {
    if (!s.length) throw new SchemaError('An Array in a schema must contain a sub-schema for the containing objects')
    return s.map(i => schema(i))
  }
  if (s.isObservable) return s
  const structure = Object.keys(s).reduce((acc, key) => {
    const { Prop, Value } = getProp(s[key])
    acc[key] = { Prop, Value }
    if (acc[key].Prop === OBJECT) {
      acc[key] = schema(s[key])
    }
    return acc
  }, {})
  return structure
}
const TypeSchema = s => {
  if (s instanceof Array) {
    return s.map(TypeSchema)
  }
  if (s.isObservable) return s
  return Object.keys(s).reduce((acc, key) => {
    if (s[key] instanceof Array) {
      acc[key] = s[key].map(TypeSchema)
    } else {
      const { Prop } = s[key]
      if (!Prop) {
        acc[key] = TypeSchema(s[key])
      } else {
        acc[key] = Prop
      }
    }
    return acc
  }, {})
}
const ValueSchema = s => {
  if (s instanceof Array) {
    return s.map(ValueSchema)
  }
  return Object.keys(s).reduce((acc, key) => {
    if (s[key]) {
      if (s[key] instanceof Array) {
        acc[key] = s[key].map(ValueSchema)
      } else {
        const { Prop, Value } = s[key]
        if (!Prop) {
          acc[key] = ValueSchema(s[key])
        } else {
          acc[key] = Value
        }
      }
    }
    return acc
  }, {})
}
const TypesAndValues = s => {
  // console.log(s)
  const TAV = schema(s)
  // console.log(TAV)
  return [TypeSchema(TAV), ValueSchema(TAV)]
}
export default TypesAndValues