Skip to content

Latest commit

 

History

History
160 lines (134 loc) · 5.04 KB

README.md

File metadata and controls

160 lines (134 loc) · 5.04 KB

Speck

Speck - Let you create your domain entities with reactive validation based on React propTypes

Build Status

This package let you create entities with schema validation based on React PropTypes.

Installing

$ npm install speck-entity

Using

Sample Entities

import { PropTypes } from 'react';
import Speck from 'speck-entity';

class MyEntity extends Speck {
  static SCHEMA = {
    field: PropTypes.string,
    otherField: {
      validator: PropTypes.number,
      defaultValue: 10
    }
  }
}

class FatherEntity extends Speck {
  static SCHEMA = {
    children: {
      validator: PropTypes.arrayOf(PropTypes.instanceOf(MyEntity)),
      type: MyEntity
    }
  }
}

Get default values

const niceInstance = new MyEntity();
console.log(niceInstance.toJSON()); // { field: undefined, otherField: 10 }
console.log(niceInstance.errors); // {}

Validations

const buggedInstance = new MyEntity({ field: 10, otherField: 'value' });
console.log(buggedInstance.toJSON()); // { field: 10, otherField: 'value' }
console.log(buggedInstance.errors); /* or buggedInstance.getErrors() -- but... getErrors also includes children errors
  {
    field: {
      errors: [ 'Invalid undefined `field` of type `number` supplied to `MyEntityEntity`, expected `string`.' ]
    },
    otherField: {
      errors: [ 'Invalid undefined `otherField` of type `string` supplied to `MyEntityEntity`, expected `number`.' ]
    }
  }
*/

Validate on change value

const otherInstance = new MyEntity({ field: 'myString' });
console.log(otherInstance.errors); // {}
console.log(otherInstance.valid); // true

otherInstance.field = 1;
console.log(otherInstance.errors); // {field: { errors: [ 'Invalid undefined `field` of type `number` supplied to `MyEntityEntity`, expected `string`.' ] }}
console.log(otherInstance.valid); // false

Parse children to Entity

const fatherInstance = new FatherEntity({
  children: [{
    field: 'A',
    otherField: 2
  }, {
    field: 'B',
    otherField: 3
  }]  
})
console.log(fatherInstance.children[0]); //An instance of MyEntity
console.log(fatherInstance.children[1].toJSON());
//{ field: 'B', otherField: 3 }

Clean unexpected values

const anotherInstance = new MyEntity({ field: 'myString', fake: 'fake' });
console.log(anotherInstance.toJSON()); // { field: 'myString', otherField: 10 }

To understand the validators React PropTypes

Well known issues

  • Create helpers for relationships validations(Like, mininum, maximum)
  • Create identifier and equal comparison

Contextual validation

  class FakeEntityWithExcludeContext extends Speck {
      static SCHEMA = {
          id: PropTypes.number.isRequired,
          requiredProp1: PropTypes.number.isRequired,
          requiredProp2: PropTypes.number.isRequired,
          requiredProp3: PropTypes.number.isRequired
      }

      static CONTEXTS = {
        create: { exclude: [ 'requiredProp2', 'requiredProp3' ] },
        edit: { include: [ 'id', 'requiredProp1', 'requiredProp2' ] }
      }
  }

   const myEntity = new FakeEntityWithIncludeContext({ id: 1 });
   console.log(anotherInstance.validateContext('create'));  //{ requiredProp1: { errors: [ ... ] } }
   console.log(anotherInstance.validateContext('edit'));  //{ requiredProp1: { errors: [ ... ] }, requiredProp2: { errors: [ ... ] } }

Each context (create and edit in example above), could have include property OR exclude, the include property receives the properties that will be validated in this context, and the exclude property represents the properties that will be ignored on validation.

In the example, the create context, will only check the 'requiredProp1' and 'requiredProp2' fields, and the edit context will check 'requiredProp1', 'requiredProp2' and 'id' properties.

You can't combine include and exclude in the same context definition

##Custom validation You can validate your entity adding the property in fields and setting the new validator

  class Entity extends Speck {
    static SCHEMA = {
      id: PropTypes.number.isRequired,
      requiredProp1: PropTypes.number.isRequired
    }

    static CONTEXTS = {
      create: {
        fields: {
          requiredProp1: (obj, field) => {
            if(obj[field] === -1) return new Error('Error -1');
          }
        }
      }
    }
  }

  const entity = new Entity({
    id: 1,
    requiredProp1: -1
  });

  const contextValidated = entity.validateContext('create');
  console.log(entity.errors.requiredProp1); // undefined
  console.log(contextValidated.requiredProp1); // { errors: [Error: Error -1] }