<commit_before># ![Speck](http://i.imgur.com/UMjf7SI.jpg)

## Speck - Let you create your domain entities with reactive validation based on [React](https://github.com/facebook/react) [propTypes](https://facebook.github.io/react/docs/reusable-components.html)

[![Build Status](https://travis-ci.org/scup/speck.svg?branch=master)](https://travis-ci.org/scup/speck)

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

* [Installing](#installing)
* [Using](#using)
* [Examples](#examples)

### Installing
    $ npm install speck-entity


### Using

#### Sample Entities
```javascript
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
```javascript
const niceInstance = new MyEntity();
console.log(niceInstance.toJSON()); // { field: undefined, otherField: 10 }
console.log(niceInstance.errors); // {}
```

#### Validations
```javascript
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
```javascript
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
```javascript
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
```javascript
const anotherInstance = new MyEntity({ field: 'myString', fake: 'fake' });
console.log(anotherInstance.toJSON()); // { field: 'myString', otherField: 10 }
```
To understand the validators [React PropTypes](https://facebook.github.io/react/docs/reusable-components.html)

### Well known issues
  - Create helpers for relationships validations(Like, mininum, maximum)
  - Create identifier and equal comparison

### Contextual validation
```javascript
  class FakeEntityWithExcludeContext extends Speck {<commit_msg>updates README.md to show the user of builder<commit_after># ![Speck](http://i.imgur.com/UMjf7SI.jpg)

## Speck - Let you create your domain entities with reactive validation based on [React](https://github.com/facebook/react) [propTypes](https://facebook.github.io/react/docs/reusable-components.html)

[![Build Status](https://travis-ci.org/scup/speck.svg?branch=master)](https://travis-ci.org/scup/speck)

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

* [Installing](#installing)
* [Using](#using)
* [Examples](#examples)

### Installing
    $ npm install speck-entity


### Using

#### Sample Entities
```javascript
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
```javascript
const niceInstance = new MyEntity();
console.log(niceInstance.toJSON()); // { field: undefined, otherField: 10 }
console.log(niceInstance.errors); // {}
```

#### Validations
```javascript
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
```javascript
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
```javascript
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 }
```
#### Hetrogeneous Types using builder
If you have a use case where you have a property whose values can be a list of multiple Types
like 
```javascript
    const elementList = {
        elements: [{
          type: 'product',
          name: true,
          price:  true
        }, {
          type: 'default',
          isDefault: true
        }]
      };
```
In such cases you can define a builder as follows:
```javascript
class ElementList extends Speck {}
ElementList.SCHEMA = {
  elements: {
    validator: noop,
    builder: (dataList) => dataList.map(data => {
      if (data.type === 'product') return new ProductEntity(data);
      if (data.type === 'default') return new FakeEntityWithBoolean(data);
    })
  }
};
```
By defining builder you tell Speck Entity that you take the responsibility of instansitating and 
returning a new object of the type which suits you the best. 
This is a powerful concept as it lets users dynamically create new types on the fly.
#### Clean unexpected values
```javascript
const anotherInstance = new MyEntity({ field: 'myString', fake: 'fake' });
console.log(anotherInstance.toJSON()); // { field: 'myString', otherField: 10 }
```
To understand the validators [React PropTypes](https://facebook.github.io/react/docs/reusable-components.html)

### Well known issues
  - Create helpers for relationships validations(Like, mininum, maximum)
  - Create identifier and equal comparison

### Contextual validation
```javascript
  class FakeEntityWithExcludeContext extends Speck {
{'fraction_non_alphanumeric': 0.14421356818494566, 'fraction_numerical': 0.004678684464015412, 'mean_word_length': 4.125528913963328, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 10, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3559774', 'n_tokens_mistral': 2178, 'n_tokens_neox': 2108, 'n_words': 609}