Repository: TechnologyAdvice/obey
Pull request #32 (2016-03-09 21:59:45)

Generators to Creators
Changing the naming `generator` to `creator` to avoid confusion with native JavaScript [Generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) 


Patch:
diff --git a/API.md b/API.md
index 44875bf..0cc3a35 100644
--- a/API.md
+++ b/API.md
@@ -1,8 +1,8 @@
 ## Objects
 
 <dl>
-<dt><a href="#generators">generators</a> : <code>object</code></dt>
-<dd><p>Generators allow for methods which generate values during validation when a
+<dt><a href="#creators">creators</a> : <code>object</code></dt>
+<dd><p>Creators allow for methods which create values during validation when a
 value is not supplied</p>
 </dd>
 <dt><a href="#obey">obey</a> : <code>object</code></dt>
@@ -23,19 +23,10 @@ data during validation</p>
 </dd>
 </dl>
 
-## Constants
-
-<dl>
-<dt><a href="#addErrors">addErrors</a></dt>
-<dd><p>Adds the error array from a ValidationError&#39;s collection into a parent context&#39;s
-existing collection. This function is curried.</p>
-</dd>
-</dl>
-
 ## Functions
 
 <dl>
-<dt><a href="#getMessages">getMessages(msgObjs)</a> ⇒ <code>Array</code></dt>
+<dt><a href="#getMessages">getMessages(msgObjs)</a> ⇒ <code>Array.&lt;string&gt;</code></dt>
 <dd><p>Compiles array items into string error messages</p>
 </dd>
 <dt><a href="#ValidationError">ValidationError(message)</a></dt>
@@ -49,51 +40,50 @@ existing collection. This function is curried.</p>
 </dd>
 </dl>
 
-<a name="generators"></a>
-## generators : <code>object</code>
-Generators allow for methods which generate values during validation when a
+<a name="creators"></a>
+## creators : <code>object</code>
+Creators allow for methods which create values during validation when a
 value is not supplied
 
 **Kind**: global namespace  
 
-* [generators](#generators) : <code>object</code>
-    * [.lib](#generators.lib)
-    * [.execute(def, key, value)](#generators.execute) ⇒ <code>function</code>
-    * [.add(name, fn)](#generators.add)
+* [creators](#creators) : <code>object</code>
+    * [.lib](#creators.lib)
+    * [.execute(def, value)](#creators.execute) ⇒ <code>function</code>
+    * [.add(name, fn)](#creators.add)
 
-<a name="generators.lib"></a>
-### generators.lib
-**Kind**: static property of <code>[generators](#generators)</code>  
+<a name="creators.lib"></a>
+### creators.lib
+**Kind**: static property of <code>[creators](#creators)</code>  
 **Properties**
 
 | Name | Type | Description |
 | --- | --- | --- |
-| Library | <code>Object</code> | of generators |
+| Library | <code>Object</code> | of creators |
 
-<a name="generators.execute"></a>
-### generators.execute(def, key, value) ⇒ <code>function</code>
-Execute method calls the appropriate generator and returns the method or
-throws and error if the generator does not exist
+<a name="creators.execute"></a>
+### creators.execute(def, value) ⇒ <code>function</code>
+Execute method calls the appropriate creator and returns the method or
+throws and error if the creator does not exist
 
-**Kind**: static method of <code>[generators](#generators)</code>  
-**Returns**: <code>function</code> - The generator function  
+**Kind**: static method of <code>[creators](#creators)</code>  
+**Returns**: <code>function</code> - The creator function  
 
 | Param | Type | Description |
 | --- | --- | --- |
 | def | <code>Object</code> | The property configuration |
-| key | <code>String</code> | The key name of the property |
 | value | <code>\*</code> | The value being validated |
 
-<a name="generators.add"></a>
-### generators.add(name, fn)
-Adds a generator to the library
+<a name="creators.add"></a>
+### creators.add(name, fn)
+Adds a creator to the library
 
-**Kind**: static method of <code>[generators](#generators)</code>  
+**Kind**: static method of <code>[creators](#creators)</code>  
 
 | Param | Type | Description |
 | --- | --- | --- |
-| name | <code>String</code> | The name of the generator |
-| fn | <code>function</code> | The generator's method |
+| name | <code>string</code> | The name of the creator |
+| fn | <code>function</code> | The creator's method |
 
 <a name="obey"></a>
 ## obey : <code>object</code>
@@ -104,10 +94,10 @@ well as the API for all other modules
 
 * [obey](#obey) : <code>object</code>
     * [.rule(def)](#obey.rule) ⇒ <code>Object</code>
-    * [.model(obj, (strict))](#obey.model) ⇒ <code>Object</code>
+    * [.model(obj, [strict])](#obey.model) ⇒ <code>Object</code>
     * [.type(name, handler)](#obey.type)
     * [.modifier(name, fn)](#obey.modifier)
-    * [.generator(name, fn)](#obey.generator)
+    * [.creator(name, fn)](#obey.creator)
 
 <a name="obey.rule"></a>
 ### obey.rule(def) ⇒ <code>Object</code>
@@ -120,15 +110,15 @@ Returns a composed rule from a definition object
 | def | <code>Object</code> | The rule definition |
 
 <a name="obey.model"></a>
-### obey.model(obj, (strict)) ⇒ <code>Object</code>
+### obey.model(obj, [strict]) ⇒ <code>Object</code>
 Returns a composed model from a definition object
 
 **Kind**: static method of <code>[obey](#obey)</code>  
 
-| Param | Type | Description |
-| --- | --- | --- |
-| obj | <code>Object</code> | The definition object |
-| (strict) | <code>Boolean</code> | Whether or not to enforce strict validation |
+| Param | Type | Default | Description |
+| --- | --- | --- | --- |
+| obj | <code>Object</code> |  | The definition object |
+| [strict] | <code>boolean</code> | <code>true</code> | Whether or not to enforce strict validation |
 
 <a name="obey.type"></a>
 ### obey.type(name, handler)
@@ -138,7 +128,7 @@ Creates and stores (or replaces) a type
 
 | Param | Type | Description |
 | --- | --- | --- |
-| name | <code>String</code> | The name of the type |
+| name | <code>string</code> | The name of the type |
 | handler | <code>Object</code> &#124; <code>function</code> | The type method or object of methods |
 
 <a name="obey.modifier"></a>
@@ -149,19 +139,19 @@ Creates and stores a modifier
 
 | Param | Type | Description |
 | --- | --- | --- |
-| name | <code>String</code> | The modifier's name |
+| name | <code>string</code> | The modifier's name |
 | fn | <code>function</code> | The method for the modifier |
 
-<a name="obey.generator"></a>
-### obey.generator(name, fn)
-Creates and stores a generator
+<a name="obey.creator"></a>
+### obey.creator(name, fn)
+Creates and stores a creator
 
 **Kind**: static method of <code>[obey](#obey)</code>  
 
 | Param | Type | Description |
 | --- | --- | --- |
-| name | <code>String</code> | The generator's name |
-| fn | <code>function</code> | The method for the generator |
+| name | <code>string</code> | The creator's name |
+| fn | <code>function</code> | The method for the creator |
 
 <a name="modifiers"></a>
 ## modifiers : <code>object</code>
@@ -172,7 +162,7 @@ when validation occurs
 
 * [modifiers](#modifiers) : <code>object</code>
     * [.lib](#modifiers.lib)
-    * [.execute(def, key, value)](#modifiers.execute) ⇒ <code>function</code>
+    * [.execute(def, value)](#modifiers.execute) ⇒ <code>function</code>
     * [.add(name, fn)](#modifiers.add)
 
 <a name="modifiers.lib"></a>
@@ -185,7 +175,7 @@ when validation occurs
 | Library | <code>Object</code> | of modifiers |
 
 <a name="modifiers.execute"></a>
-### modifiers.execute(def, key, value) ⇒ <code>function</code>
+### modifiers.execute(def, value) ⇒ <code>function</code>
 Execute method calls the appropriate modifier and passes in the value or
 throws an error if the modifier does not exist
 
@@ -195,7 +185,6 @@ throws an error if the modifier does not exist
 | Param | Type | Description |
 | --- | --- | --- |
 | def | <code>Object</code> | The property configuration |
-| key | <code>String</code> | The key name of the property |
 | value | <code>\*</code> | The value being validated |
 
 <a name="modifiers.add"></a>
@@ -206,7 +195,7 @@ Adds new modifier to the library
 
 | Param | Type | Description |
 | --- | --- | --- |
-| name | <code>String</code> | The name of the modifier |
+| name | <code>string</code> | The name of the modifier |
 | fn | <code>function</code> | The modifier's method |
 
 <a name="rules"></a>
@@ -219,7 +208,7 @@ properties during validation
 * [rules](#rules) : <code>object</code>
     * [.props](#rules.props)
     * [.makeValidate(def)](#rules.makeValidate)
-    * [.validate(def, data, (key))](#rules.validate)
+    * [.validate(def, data, [key], [errors], [rejectOnFail])](#rules.validate) ⇒ <code>Promise.&lt;\*&gt;</code>
     * [.build(def)](#rules.build) ⇒ <code>Object</code>
 
 <a name="rules.props"></a>
@@ -242,17 +231,21 @@ Binds rule definition in validate method
 | def | <code>Object</code> | The rule definition object |
 
 <a name="rules.validate"></a>
-### rules.validate(def, data, (key))
+### rules.validate(def, data, [key], [errors], [rejectOnFail]) ⇒ <code>Promise.&lt;\*&gt;</code>
 Iterates over the properties present in the rule definition and sets the
 appropriate bindings to required methods
 
 **Kind**: static method of <code>[rules](#rules)</code>  
+**Returns**: <code>Promise.&lt;\*&gt;</code> - Resolves with the resulting data, with any defaults, creators, and modifiers applied.
+Rejects with a ValidationError if applicable.  
 
-| Param | Type | Description |
-| --- | --- | --- |
-| def | <code>Object</code> | The rule definition object |
-| data | <code>\*</code> | The data (value) to validate |
-| (key) | <code>String</code> | Key for tracking parent in nested iterations |
+| Param | Type | Default | Description |
+| --- | --- | --- | --- |
+| def | <code>Object</code> |  | The rule definition object |
+| data | <code>\*</code> |  | The data (value) to validate |
+| [key] | <code>string</code> &#124; <code>null</code> | <code>null</code> | Key for tracking parent in nested iterations |
+| [errors] | <code>Array.&lt;{type: string, sub: string, key: string, value: \*, message: string}&gt;</code> | <code>[]</code> | An error array to which any additional error objects will be added. If not specified, a new array will be created. |
+| [rejectOnFail] | <code>boolean</code> | <code>true</code> | If true, resulting promise will reject if the errors array is not empty; otherwise ValidationErrors will not cause a rejection |
 
 <a name="rules.build"></a>
 ### rules.build(def) ⇒ <code>Object</code>
@@ -274,9 +267,9 @@ data during validation
 * [types](#types) : <code>object</code>
     * [.strategies](#types.strategies)
     * [.checkSubType(def)](#types.checkSubType) ⇒ <code>Object</code>
-    * [.validate(def, key, value)](#types.validate) ⇒ <code>\*</code>
-    * [.add(name, handler, fn)](#types.add)
-    * [.check(type, val)](#types.check) ⇒ <code>Object</code>
+    * [.validate(def, value, key, errors)](#types.validate) ⇒ <code>\*</code> &#124; <code>Promise.&lt;\*&gt;</code>
+    * [.add(name, handler)](#types.add)
+    * [.check(context)](#types.check) ⇒ <code>Promise.&lt;\*&gt;</code>
 
 <a name="types.strategies"></a>
 ### types.strategies
@@ -298,65 +291,52 @@ Checks for and applies sub-type to definition
 | def | <code>Object</code> | The rule defintion |
 
 <a name="types.validate"></a>
-### types.validate(def, key, value) ⇒ <code>\*</code>
+### types.validate(def, value, key, errors) ⇒ <code>\*</code> &#124; <code>Promise.&lt;\*&gt;</code>
 Sets up the `fail` method and handles `empty` or `undefined` values. If neither
 empty or undefined, calls the appropriate `type` and executes validation
 
 **Kind**: static method of <code>[types](#types)</code>  
-**Returns**: <code>\*</code> - The value if empty or undefined, check method if value requires type validation  
+**Returns**: <code>\*</code> &#124; <code>Promise.&lt;\*&gt;</code> - The value if empty or undefined, check method if value requires type validation  
 
 | Param | Type | Description |
 | --- | --- | --- |
 | def | <code>Object</code> | The property configuration |
-| key | <code>String</code> | The key name of the property |
 | value | <code>\*</code> | The value being validated |
+| key | <code>string</code> | The key name of the property |
+| errors | <code>Array.&lt;{type: string, sub: (string\|number), key: string, value: \*, message: string}&gt;</code> | An error array to which any additional error objects will be added |
 
 <a name="types.add"></a>
-### types.add(name, handler, fn)
+### types.add(name, handler)
 Add (or override) a type in the library
 
 **Kind**: static method of <code>[types](#types)</code>  
 
 | Param | Type | Description |
 | --- | --- | --- |
-| name | <code>String</code> | The name of the type |
-| handler | <code>Object</code> &#124; <code>function</code> |  |
-| fn | <code>String</code> | The type strategy method |
+| name | <code>string</code> | The name of the type |
+| handler | <code>Object</code> &#124; <code>function</code> | The type strategy method |
 
 <a name="types.check"></a>
-### types.check(type, val) ⇒ <code>Object</code>
+### types.check(context) ⇒ <code>Promise.&lt;\*&gt;</code>
 Ensures that the strategy exists, loads if not already in memory, then ensures
 subtype and returns the applied type strategy
 
 **Kind**: static method of <code>[types](#types)</code>  
-**Returns**: <code>Object</code> - The type execution function promise resolution  
-
-| Param | Type | Description |
-| --- | --- | --- |
-| type | <code>String</code> | The type to check |
-| val | <code>\*</code> | The value to check |
-
-<a name="addErrors"></a>
-## addErrors
-Adds the error array from a ValidationError's collection into a parent context's
-existing collection. This function is curried.
-
-**Kind**: global constant  
+**Returns**: <code>Promise.&lt;\*&gt;</code> - Resolves with the provided data, possibly modified by the type strategy  
 
 | Param | Type | Description |
 | --- | --- | --- |
-| context | <code>Object</code> | An Obey type context |
-| err | <code>[ValidationError](#ValidationError)</code> | An error to merge with the context's error stack |
+| context | <code>Object</code> | A type context |
 
 <a name="getMessages"></a>
-## getMessages(msgObjs) ⇒ <code>Array</code>
+## getMessages(msgObjs) ⇒ <code>Array.&lt;string&gt;</code>
 Compiles array items into string error messages
 
 **Kind**: global function  
 
 | Param | Type | Description |
 | --- | --- | --- |
-| msgObjs | <code>Array</code> | Original array of error message objects |
+| msgObjs | <code>Array.&lt;{type: string, sub: (string\|number), key: string, value: \*, message: string}&gt;</code> | Original array of error message objects |
 
 <a name="ValidationError"></a>
 ## ValidationError(message)
@@ -366,7 +346,7 @@ Creates ValidationError object for throwing
 
 | Param | Type | Description |
 | --- | --- | --- |
-| message | <code>Array</code> | Raw array of error objects |
+| message | <code>Array.&lt;{type: string, sub: (string\|number), key: string, value: \*, message: string}&gt;</code> | Raw array of error objects |
 
 <a name="validateByKeys"></a>
 ## validateByKeys(context, keyPrefix) ⇒ <code>Promise.&lt;Object&gt;</code>
diff --git a/README.md b/README.md
index 308b8f2..359bc70 100644
--- a/README.md
+++ b/README.md
@@ -24,8 +24,8 @@ Asynchronous Data Modelling and Validation.
     - [Adding Type with Subs](#adding-type-with-subs)
 - [Modifiers](#modifiers)
   - [Creating Modifiers](#creating-modifiers)
-- [Generators](#generators)
-  - [Creating Generators](#creating-generators)
+- [Creators](#creators)
+  - [Creating Creators](#creating-creators)
 - [Strict Mode](#strict-mode)
 - [Asynchronous Validation](#asynchronous-validation)
 - [Contributing](#contributing)
@@ -61,7 +61,7 @@ const firstName = obey.rule({ type: 'string', min: 2, max: 45, required: true })
 import obey from 'obey'
 
 const userModel = obey.model({
-  id: { type: 'uuid', generator: 'uuid', required: true },
+  id: { type: 'uuid', creator: 'uuid', required: true },
   email: { type: 'email', required: true },
   password: { type: 'string', modifier: 'encryptPassword', required: true },
   fname: { type: 'string', description: 'First Name' },
@@ -133,7 +133,7 @@ When setting definitions for rules or model properties, the following are suppor
 * `keys`: Property of `object` type, indicates nested object properties
 * `values`: Defines value specification for arrays or key-independent objects
 * `modifier`: uses a method and accepts a passed value to modify or transform data, see [Modifiers](#modifiers)
-* `generator`: uses a method to create a default value if no value is supplied, see [Generators](#generators)
+* `creator`: uses a method to create a default value if no value is supplied, see [Creators](#creators)
 * `empty`: Set to `true` allows empty string or array, (default `false`)
 * `default`: The default value if no value specified
 * `min`: The minimum character length for a string, lowest number, or minimum items in array
@@ -241,27 +241,27 @@ When the model is validated, the value in any fields with the `upperCase` modifi
 
 Similar to types, modifiers may be synchronous (returning a value) or asynchronous (returning a promise).
 
-## Generators
+## Creators
 
-> Generators allow custom methods to return values which set the value similar to the `default` property. When validating, if a value is not provided the generator assigned will be used to set the value.
+> Creators allow custom methods to return values which set the value similar to the `default` property. When validating, if a value is not provided the creator assigned will be used to set the value.
 
-### Creating Generators
+### Creating Creators
 
-Generators can be added to the Obey lib with the `obey.generator` method:
+Creators can be added to the Obey lib with the `obey.creator` method:
 
 ```javascript
-obey.generator('timestamp', () => new Date().getTime())
+obey.creator('timestamp', () => new Date().getTime())
 ```
 
-The above example would add a generator named `timestamp` which could be assigned as shown below:
+The above example would add a creator named `timestamp` which could be assigned as shown below:
 
 ```javascript
-created: { type: 'number', generator: 'timestamp' }
+created: { type: 'number', creator: 'timestamp' }
 ```
 
-When the model is validated, if no `created` property is provided the `timestamp` generator will assign the property a UTC timestamp.
+When the model is validated, if no `created` property is provided the `timestamp` creator will assign the property a UTC timestamp.
 
-Similar to modifiers, generators may be synchronous (returning a value) or asynchronous (returning a promise).
+Similar to modifiers, creators may be synchronous (returning a value) or asynchronous (returning a promise).
 
 ## Strict Mode
 
@@ -281,7 +281,7 @@ const model = obey.model({ /* definition */ }, false)
 
 ## Asynchronous Validation
 
-The goal with Obey is to provide more than just standard type/regex checks against data to validate values and models. The ability to write both synchronous and asynchronous checks, generators, and modifiers, and include data coercion in the validation simplifies the process of validation and checking before moving onto data source interactions.
+The goal with Obey is to provide more than just standard type/regex checks against data to validate values and models. The ability to write both synchronous and asynchronous checks, creators, and modifiers, and include data coercion in the validation simplifies the process of validation and checking before moving onto data source interactions.
 
 Additionally, with the widespread use of promises, this structure fits well in the scheme of data processing in general:
 
diff --git a/src/creators.js b/src/creators.js
new file mode 100644
index 0000000..64f85bc
--- /dev/null
+++ b/src/creators.js
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015 TechnologyAdvice
+ */
+
+/**
+ * Creators allow for methods which create values during validation when a
+ * value is not supplied
+ * @namespace creators
+ */
+const creators = {
+  /**
+   * @memberof creators
+   * @property {Object} Library of creators
+   */
+  lib: {},
+
+  /**
+   * Execute method calls the appropriate creator and returns the method or
+   * throws and error if the creator does not exist
+   * @memberof creators
+   * @param {Object} def The property configuration
+   * @param {*} value The value being validated
+   * @returns {function} The creator function
+   */
+  execute: function(def, value) {
+    if (value !== undefined) return value
+    if (creators.lib[def.creator]) return creators.lib[def.creator]()
+    throw new Error(`creator '${def.creator}' does not exist`)
+  },
+
+  /**
+   * Adds a creator to the library
+   * @memberof creators
+   * @param {string} name The name of the creator
+   * @param {function} fn The creator's method
+   */
+  add: (name, fn) => {
+    if (typeof name !== 'string') throw new Error('creator name should be a string')
+    if (typeof fn !== 'function') throw new Error('creator method should be a function')
+    creators.lib[name] = fn
+  }
+}
+
+export default creators
diff --git a/src/generators.js b/src/generators.js
deleted file mode 100644
index 15f71c7..0000000
--- a/src/generators.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2015 TechnologyAdvice
- */
-
-/**
- * Generators allow for methods which generate values during validation when a
- * value is not supplied
- * @namespace generators
- */
-const generators = {
-  /**
-   * @memberof generators
-   * @property {Object} Library of generators
-   */
-  lib: {},
-
-  /**
-   * Execute method calls the appropriate generator and returns the method or
-   * throws and error if the generator does not exist
-   * @memberof generators
-   * @param {Object} def The property configuration
-   * @param {String} key The key name of the property
-   * @param {*} value The value being validated
-   * @returns {Function} The generator function
-   */
-  execute: function(def, key, value) {
-    if (value !== undefined) return value
-    if (generators.lib[def.generator]) return generators.lib[def.generator]()
-    throw new Error(`Generator '${def.generator}' does not exist`)
-  },
-
-  /**
-   * Adds a generator to the library
-   * @memberof generators
-   * @param {String} name The name of the generator
-   * @param {Function} fn The generator's method
-   */
-  add: (name, fn) => {
-    if (typeof name !== 'string') throw new Error('Generator name should be a string')
-    if (typeof fn !== 'function') throw new Error('Generator method should be a function')
-    generators.lib[name] = fn
-  }
-}
-
-export default generators
diff --git a/src/index.js b/src/index.js
index 039889c..15949ec 100644
--- a/src/index.js
+++ b/src/index.js
@@ -5,7 +5,7 @@
 import rules from './rules'
 import types from './types'
 import modifiers from './modifiers'
-import generators from './generators'
+import creators from './creators'
 import validators from './lib/validators'
 import ValidationError from './lib/error'
 
@@ -18,7 +18,7 @@ export default {
   /**
    * API, exposes modules to make lib API accessible
    */
-  rules, types, modifiers, generators, validators, ValidationError,
+  rules, types, modifiers, creators, validators, ValidationError,
 
   /**
    * Returns a composed rule from a definition object
@@ -32,7 +32,7 @@ export default {
    * Returns a composed model from a definition object
    * @memberof obey
    * @param {Object} obj The definition object
-   * @param {Boolean} (strict) Whether or not to enforce strict validation
+   * @param {boolean} [strict=true] Whether or not to enforce strict validation
    * @returns {Object}
    */
   model: (obj, strict = true) => rules.build({ type: 'object', keys: obj, strict }),
@@ -40,24 +40,24 @@ export default {
   /**
    * Creates and stores (or replaces) a type
    * @memberof obey
-   * @param {String} name The name of the type
-   * @param {Object|Function} handler The type method or object of methods
+   * @param {string} name The name of the type
+   * @param {Object|function} handler The type method or object of methods
    */
   type: (name, handler) => types.add(name, handler),
 
   /**
    * Creates and stores a modifier
    * @memberof obey
-   * @param {String} name The modifier's name
-   * @param {Function} fn The method for the modifier
+   * @param {string} name The modifier's name
+   * @param {function} fn The method for the modifier
    */
   modifier: (name, fn) => modifiers.add(name, fn),
 
   /**
-   * Creates and stores a generator
+   * Creates and stores a creator
    * @memberof obey
-   * @param {String} name The generator's name
-   * @param {Function} fn The method for the generator
+   * @param {string} name The creator's name
+   * @param {function} fn The method for the creator
    */
-  generator: (name, fn) => generators.add(name, fn)
+  creator: (name, fn) => creators.add(name, fn)
 }
diff --git a/src/lib/error.js b/src/lib/error.js
index 02468b6..349229f 100644
--- a/src/lib/error.js
+++ b/src/lib/error.js
@@ -4,8 +4,9 @@
 
 /**
  * Compiles array items into string error messages
- * @param {Array} msgObjs Original array of error message objects
- * @returns {Array}
+ * @param {Array<{type: string, sub: string|number, key: string, value: *, message: string}>} msgObjs Original array
+ * of error message objects
+ * @returns {Array<string>}
  */
 const getMessages = (msgObjs) => {
   const messages = []
@@ -17,7 +18,8 @@ const getMessages = (msgObjs) => {
 
 /**
  * Creates ValidationError object for throwing
- * @param {Array} message Raw array of error objects
+ * @param {Array<{type: string, sub: string|number, key: string, value: *, message: string}>} message Raw array of
+ * error objects
  */
 function ValidationError(message) {
   Object.defineProperty(this, 'name', { value: 'ValidationError' })
@@ -26,9 +28,7 @@ function ValidationError(message) {
   Error.captureStackTrace(this, this.name)
 }
 
-/**
- * Creates instance of ValidationError as Error object
- */
+// Creates instance of ValidationError as Error object
 ValidationError.prototype = Object.create(Error.prototype)
 ValidationError.prototype.constructor = ValidationError
 
diff --git a/src/lib/validators.js b/src/lib/validators.js
index 0cf9b33..8960d82 100644
--- a/src/lib/validators.js
+++ b/src/lib/validators.js
@@ -6,58 +6,63 @@ const validators = {
   /**
    * Validator default method, used by model
    * @param {Object} def The property configuration
-   * @param {String} key The key name of the property
    * @param {*} value The value being validated
    */
-  default: function(def, key, value) {
+  default: function(def, value) {
     return value || def.default
   },
 
   /**
    * Validator allowed method, used by model
    * @param {Object} def The property configuration
-   * @param {String} key The key name of the property
    * @param {*} value The value being validated
+   * @param {string} key The key name of the property
+   * @param {Array<{type: string, sub: string|number, key: string, value: *, message: string}>} errors An error array
+   * to which any additional error objects will be added
    */
-  allow: function(def, key, value) {
+  allow: function(def, value, key, errors) {
     const type = 'allow'
     const sub = def.allow
     if (Array.isArray(def.allow) && def.allow.indexOf(value) === -1) {
-      this.errors.push({ type, sub, key, value, message: `Value '${value}' is not allowed` })
+      errors.push({ type, sub, key, value, message: `Value '${value}' is not allowed` })
     } else if (!Array.isArray(def.allow) && def.allow !== value) {
-      this.errors.push({ type, sub, key, value, message: `Value '${value}' is not allowed` })
+      errors.push({ type, sub, key, value, message: `Value '${value}' is not allowed` })
     }
   },
 
   /**
    * Validator min method, used by model
    * @param {Object} def The property configuration
-   * @param {String} key The key name of the property
    * @param {*} value The value being validated
+   * @param {string} key The key name of the property
+   * @param {Array<{type: string, sub: string|number, key: string, value: *, message: string}>} errors An error array
+   * to which any additional error objects will be added
    */
-  min: function(def, key, value) {
+  min: function(def, value, key, errors) {
     const type = 'min'
     const sub = def.min
     if (Array.isArray(value) || typeof value === 'string' && value.length < def.min) {
-      this.errors.push({ type, sub, key, value, message: `Length must be greater than ${def.min}` })
+      errors.push({ type, sub, key, value, message: `Length must be greater than ${def.min}` })
     } else if (typeof value === 'number' && value < def.min) {
-      this.errors.push({ type, sub, key, value, message: `Value must be greater than ${def.min}` })
+      errors.push({ type, sub, key, value, message: `Value must be greater than ${def.min}` })
     }
   },
 
   /**
    * Validator max method, used by model
    * @param {Object} def The property configuration
-   * @param {String} key The key name of the property
    * @param {*} value The value being validated
+   * @param {string} key The key name of the property
+   * @param {Array<{type: string, sub: string|number, key: string, value: *, message: string}>} errors An error array
+   * to which any additional error objects will be added
    */
-  max: function(def, key, value) {
+  max: function(def, value, key, errors) {
     const type = 'max'
     const sub = def.max
     if (Array.isArray(value) || typeof value === 'string' && value.length > def.max) {
-      this.errors.push({ type, sub, key, value, message: `Length must be less than ${def.max}` })
+      errors.push({ type, sub, key, value, message: `Length must be less than ${def.max}` })
     } else if (typeof value === 'number' && value > def.max) {
-      this.errors.push({ type, sub, key, value, message: `Value must be less than ${def.max}` })
+      errors.push({ type, sub, key, value, message: `Value must be less than ${def.max}` })
     }
   }
 }
diff --git a/src/modifiers.js b/src/modifiers.js
index c7da7ed..518eadd 100644
--- a/src/modifiers.js
+++ b/src/modifiers.js
@@ -19,11 +19,10 @@ const modifiers = {
    * throws an error if the modifier does not exist
    * @memberof modifiers
    * @param {Object} def The property configuration
-   * @param {String} key The key name of the property
    * @param {*} value The value being validated
-   * @returns {Function} The modifier function
+   * @returns {function} The modifier function
    */
-  execute: function(def, key, value) {
+  execute: function(def, value) {
     if (modifiers.lib[def.modifier]) return modifiers.lib[def.modifier](value)
     throw new Error(`Modifier '${def.modifier}' does not exist`)
   },
@@ -31,8 +30,8 @@ const modifiers = {
   /**
    * Adds new modifier to the library
    * @memberof modifiers
-   * @param {String} name The name of the modifier
-   * @param {Function} fn The modifier's method
+   * @param {string} name The name of the modifier
+   * @param {function} fn The modifier's method
    */
   add: (name, fn) => {
     if (typeof name !== 'string') throw new Error('Modifier name should be a string')
diff --git a/src/rules.js b/src/rules.js
index 5755c3f..4c39fd0 100644
--- a/src/rules.js
+++ b/src/rules.js
@@ -3,7 +3,7 @@
  */
 import types from './types'
 import modifiers from './modifiers'
-import generators from './generators'
+import creators from './creators'
 import Promise from 'bluebird'
 import validators from './lib/validators'
 import ValidationError from './lib/error'
@@ -13,7 +13,7 @@ import ValidationError from './lib/error'
  * Defines all definition property checks available
  */
 const allProps = {
-  generator: { name: 'generator', fn: generators.execute },
+  creator: { name: 'creator', fn: creators.execute },
   default: { name: 'default', fn: validators.default },
   modifier: { name: 'modifier', fn: modifiers.execute },
   allow: { name: 'allow', fn: validators.allow },
@@ -35,7 +35,7 @@ const rules = {
   props: {
     // Default props
     default: [
-      allProps.generator,
+      allProps.creator,
       allProps.default,
       allProps.modifier,
       allProps.allow,
@@ -45,7 +45,7 @@ const rules = {
     ],
     // When no value/undefined
     noVal: [
-      allProps.generator,
+      allProps.creator,
       allProps.default,
       allProps.modifier
     ]
@@ -64,24 +64,31 @@ const rules = {
    * @memberof rules
    * @param {Object} def The rule definition object
    * @param {*} data The data (value) to validate
-   * @param {String} (key) Key for tracking parent in nested iterations
+   * @param {string|null} [key=null] Key for tracking parent in nested iterations
+   * @param {Array<{type: string, sub: string, key: string, value: *, message: string}>} [errors=[]] An error array
+   * to which any additional error objects will be added. If not specified, a new array will be created.
+   * @param {boolean} [rejectOnFail=true] If true, resulting promise will reject if the errors array is not empty;
+   * otherwise ValidationErrors will not cause a rejection
+   * @returns {Promise.<*>} Resolves with the resulting data, with any defaults, creators, and modifiers applied.
+   * Rejects with a ValidationError if applicable.
    */
-  validate: (def, data, key = null) => {
+  validate: (def, data, key = null, errors = [], rejectOnFail = true) => {
     let curData = data
-    const context = { errors: [] }
     const props = !def.required && data === undefined ? rules.props.noVal : rules.props.default
     if (!def.type) throw new Error('Model properties must define a \'type\'')
     let chain = Promise.resolve(data)
     props.forEach(prop => {
       if (def.hasOwnProperty(prop.name)) {
-        chain = chain.then(prop.fn.bind(context, def, key)).then(res => {
-          if (res !== undefined) curData = res
-          return curData
-        })
+        chain = chain
+          .then(val => prop.fn(def, val, key, errors))
+          .then(res => {
+            if (res !== undefined) curData = res
+            return curData
+          })
       }
     })
     return chain.then(res => {
-      if (context.errors.length > 0) throw new ValidationError(context.errors)
+      if (rejectOnFail && errors.length > 0) throw new ValidationError(errors)
       return res
     })
   },
diff --git a/src/types.js b/src/types.js
index b048a4f..0a98ec2 100644
--- a/src/types.js
+++ b/src/types.js
@@ -37,14 +37,16 @@ const types = {
    * empty or undefined, calls the appropriate `type` and executes validation
    * @memberof types
    * @param {Object} def The property configuration
-   * @param {String} key The key name of the property
    * @param {*} value The value being validated
-   * @returns {*} The value if empty or undefined, check method if value requires type validation
+   * @param {string} key The key name of the property
+   * @param {Array<{type: string, sub: string|number, key: string, value: *, message: string}>} errors An error array
+   * to which any additional error objects will be added
+   * @returns {*|Promise.<*>} The value if empty or undefined, check method if value requires type validation
    */
-  validate: function(def, key, value) {
+  validate: function(def, value, key, errors) {
     const parsedDef = types.checkSubType(def)
     const fail = message => {
-      this.errors.push({ type: def.type, sub: def.sub, key, value, message })
+      errors.push({ type: def.type, sub: def.sub, key, value, message })
     }
     // Handle `empty` prop for string values
     if (def.empty && typeof value === 'string' && def.type !== 'array' && value.length === 0) {
@@ -52,19 +54,18 @@ const types = {
     }
     // Don't run if undefined on required
     if (def.required && value === undefined) {
-      this.errors.push({ type: 'required', sub: 'default', key, value, message: `Property '${key}' is required` })
+      errors.push({ type: 'required', sub: 'default', key, value, message: `Property '${key}' is required` })
       return value
     }
     // Execute check
-    return types.check({ def: parsedDef, key, value, fail, errors: this.errors })
+    return types.check({ def: parsedDef, key, value, fail, errors })
   },
 
   /**
    * Add (or override) a type in the library
    * @memberof types
-   * @param {String} name The name of the type
-   * @param {Object|Function} handler
-   * @param {String} fn The type strategy method
+   * @param {string} name The name of the type
+   * @param {Object|function} handler The type strategy method
    */
   add: (name, handler) => {
     types.strategies[name] = _.isFunction(handler) ? { default: handler } : handler
@@ -74,12 +75,14 @@ const types = {
    * Ensures that the strategy exists, loads if not already in memory, then ensures
    * subtype and returns the applied type strategy
    * @memberof types
-   * @param {String} type The type to check
-   * @param {*} val The value to check
-   * @returns {Object} The type execution function promise resolution
+   * @param {{def: Object, key: string, value: *, fail: function, errors: Array<{Object}>}} context A type context
+   * @returns {Promise.<*>} Resolves with the provided data, possibly modified by the type strategy
    */
   check: context => {
     if (!types.strategies[context.def.type]) {
+      if (context.def.type.match(/[\/\\]/)) {
+        throw new Error(`Illegal type name: ${context.def.type}`)
+      }
       try {
         types.strategies[context.def.type] = require(`./types/${context.def.type}`).default
       } catch (e) {
diff --git a/src/types/array.js b/src/types/array.js
index 746a4f3..c02df7f 100644
--- a/src/types/array.js
+++ b/src/types/array.js
@@ -1,6 +1,5 @@
 import rules from '../rules'
 import Promise from 'bluebird'
-import ValidationError from '../lib/error'
 
 const array = {
   default: context => {
@@ -19,12 +18,7 @@ const array = {
     // Specific array sub-validation
     if (!context.def.values) return true
     const promises = context.value.map((elem, idx) => {
-      return rules.validate(context.def.values, elem, `${context.key}[${idx}]`)
-        .catch(ValidationError, err => {
-          err.collection.forEach(error => {
-            context.errors.push(error)
-          })
-        })
+      return rules.validate(context.def.values, elem, `${context.key}[${idx}]`, context.errors, false)
     })
     return Promise.all(promises)
   }
diff --git a/src/types/object.js b/src/types/object.js
index cc8860b..656744e 100644
--- a/src/types/object.js
+++ b/src/types/object.js
@@ -1,19 +1,6 @@
 import _ from 'lodash'
 import rules from '../rules'
 import Promise from 'bluebird'
-import ValidationError from '../lib/error'
-
-/**
- * Adds the error array from a ValidationError's collection into a parent context's
- * existing collection. This function is curried.
- * @param {Object} context An Obey type context
- * @param {ValidationError} err An error to merge with the context's error stack
- */
-const addErrors = _.curry((context, err) => {
-  err.collection.forEach(error => {
-    context.errors.push(error)
-  })
-})
 
 /**
  * Validates an object using the definition's `keys` property
@@ -26,12 +13,11 @@ const validateByKeys = (context, keyPrefix) => {
   const missingKeys = []
   const promises = {}
   _.forOwn(context.def.keys, (keyDef, key) => {
-    promises[key] = rules.validate(keyDef, context.value[key], `${keyPrefix}${key}`)
+    promises[key] = rules.validate(keyDef, context.value[key], `${keyPrefix}${key}`, context.errors, false)
       .then(val => {
         if (!context.value.hasOwnProperty(key) && val === undefined) missingKeys.push(key)
         return val
       })
-      .catch(ValidationError, addErrors(context))
   })
   // Check undefined keys
   const strictMode = !context.def.hasOwnProperty('strict') || context.def.strict
@@ -59,8 +45,7 @@ const validateByKeys = (context, keyPrefix) => {
 const validateByValues = (context, keyPrefix) => {
   const promises = {}
   _.forOwn(context.value, (val, key) => {
-    promises[key] = rules.validate(context.def.values, val, `${keyPrefix}${key}`)
-      .catch(ValidationError, addErrors(context))
+    promises[key] = rules.validate(context.def.values, val, `${keyPrefix}${key}`, context.errors, false)
   })
   return Promise.props(promises)
 }


Test patch:
diff --git a/test/fixtures/creators.js b/test/fixtures/creators.js
new file mode 100644
index 0000000..5d86b1d
--- /dev/null
+++ b/test/fixtures/creators.js
@@ -0,0 +1,8 @@
+export default {
+  synchronous: {
+    name: { type: 'string', creator: 'syncCreator' }
+  },
+  asynchronous: {
+    name: { type: 'string', creator: 'asyncCreator' }
+  }
+}
diff --git a/test/fixtures/generators.js b/test/fixtures/generators.js
deleted file mode 100644
index 697945d..0000000
--- a/test/fixtures/generators.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export default {
-  synchronous: {
-    name: { type: 'string', generator: 'syncGenerator' }
-  },
-  asynchronous: {
-    name: { type: 'string', generator: 'asyncGenerator' }
-  }
-}
diff --git a/test/integration/generators.spec.js b/test/integration/creators.spec.js
similarity index 60%
rename from test/integration/generators.spec.js
rename to test/integration/creators.spec.js
index f5fdce4..8fee16b 100644
--- a/test/integration/generators.spec.js
+++ b/test/integration/creators.spec.js
@@ -1,25 +1,25 @@
 /* global describe, it, expect, afterEach */
 import obey from 'src/index'
-import generators from 'src/generators'
-import modelFixtures from 'test/fixtures/generators'
+import creators from 'src/creators'
+import modelFixtures from 'test/fixtures/creators'
 
-describe('integration:generators', () => {
+describe('integration:creators', () => {
   afterEach(() => {
-    generators.lib = {}
+    creators.lib = {}
   })
   describe('synchronous', () => {
-    it('generates a value synchronously when property has no value', () => {
+    it('creates a value synchronously when property has no value', () => {
       const testModel = obey.model(modelFixtures.synchronous)
-      obey.generator('syncGenerator', () => 'foo')
+      obey.creator('syncCreator', () => 'foo')
       return testModel.validate({}).then(res => {
         expect(res.name).to.equal('foo')
       })
     })
   })
   describe('asynchronous', () => {
-    it('generates a value asynchronously when property has no value', () => {
+    it('creates a value asynchronously when property has no value', () => {
       const testModel = obey.model(modelFixtures.asynchronous)
-      obey.generator('asyncGenerator', () => {
+      obey.creator('asyncCreator', () => {
         return new Promise((resolve) => {
           setTimeout(() => resolve('foo'), 300)
         })
diff --git a/test/src/creators.spec.js b/test/src/creators.spec.js
new file mode 100644
index 0000000..63c704a
--- /dev/null
+++ b/test/src/creators.spec.js
@@ -0,0 +1,35 @@
+/* global describe, it, expect, afterEach */
+import creators from 'src/creators'
+
+describe('creators', () => {
+  afterEach(() => {
+    creators.lib = {}
+  })
+  describe('execute', () => {
+    it('returns the original value if defined', () => {
+      const actual = creators.execute({}, 'bar')
+      expect(actual).to.equal('bar')
+    })
+    it('returns the modifier method if exists', () => {
+      creators.add('test', () => 'foo')
+      const actual = creators.execute({ creator: 'test' }, 'foo')
+      expect(actual).to.be.a.function
+    })
+    it('throws an error if the creator does not exist', () => {
+      expect(creators.execute.bind(null, { creator: 'nope'})).to.throw('creator \'nope\' does not exist')
+    })
+  })
+  describe('add', () => {
+    it('adds a new creator to the lib', () => {
+      creators.add('test', () => 'foo')
+      expect(creators.lib).to.have.property('test')
+      expect(creators.lib.test).to.be.a.function
+    })
+    it('throws an error if the creator name is not a string', () => {
+      expect(creators.add.bind(null, true, () => 'foo')).to.throw('creator name should be a string')
+    })
+    it('throws an error if the creator method is not a function', () => {
+      expect(creators.add.bind(null, 'foo', undefined)).to.throw('creator method should be a function')
+    })
+  })
+})
diff --git a/test/src/generators.spec.js b/test/src/generators.spec.js
deleted file mode 100644
index 009480e..0000000
--- a/test/src/generators.spec.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/* global describe, it, expect, afterEach */
-import generators from 'src/generators'
-
-describe('generators', () => {
-  afterEach(() => {
-    generators.lib = {}
-  })
-  describe('execute', () => {
-    it('returns the original value if defined', () => {
-      const actual = generators.execute({}, 'foo', 'bar')
-      expect(actual).to.equal('bar')
-    })
-    it('returns the modifier method if exists', () => {
-      generators.add('test', () => 'foo')
-      const actual = generators.execute({ generator: 'test' }, 'foo')
-      expect(actual).to.be.a.function
-    })
-    it('throws an error if the generator does not exist', () => {
-      expect(generators.execute.bind(null, { generator: 'nope'})).to.throw('Generator \'nope\' does not exist')
-    })
-  })
-  describe('add', () => {
-    it('adds a new generator to the lib', () => {
-      generators.add('test', () => 'foo')
-      expect(generators.lib).to.have.property('test')
-      expect(generators.lib.test).to.be.a.function
-    })
-    it('throws an error if the generator name is not a string', () => {
-      expect(generators.add.bind(null, true, () => 'foo')).to.throw('Generator name should be a string')
-    })
-    it('throws an error if the generator method is not a function', () => {
-      expect(generators.add.bind(null, 'foo', undefined)).to.throw('Generator method should be a function')
-    })
-  })
-})
diff --git a/test/src/index.spec.js b/test/src/index.spec.js
index 2fa8f60..be1b435 100644
--- a/test/src/index.spec.js
+++ b/test/src/index.spec.js
@@ -4,7 +4,7 @@ import obey from 'src/index'
 import rules from 'src/rules'
 import types from 'src/types'
 import modifiers from 'src/modifiers'
-import generators from 'src/generators'
+import creators from 'src/creators'
 
 describe('obey', () => {
   describe('rule', () => {
@@ -42,12 +42,12 @@ describe('obey', () => {
       expect(modifiers.add).to.be.called
     })
   })
-  describe('generator', () => {
-    before(() => sinon.spy(generators, 'add'))
-    after(() => { generators.add.restore() })
-    it('adds a new generator to the obey library', () => {
-      obey.generator('name', () => _.noop())
-      expect(generators.add).to.be.called
+  describe('creator', () => {
+    before(() => sinon.spy(creators, 'add'))
+    after(() => { creators.add.restore() })
+    it('adds a new creator to the obey library', () => {
+      obey.creator('name', () => _.noop())
+      expect(creators.add).to.be.called
     })
   })
 })
diff --git a/test/src/lib/validators.spec.js b/test/src/lib/validators.spec.js
index 02cf735..8c1d3c0 100644
--- a/test/src/lib/validators.spec.js
+++ b/test/src/lib/validators.spec.js
@@ -2,23 +2,23 @@
 import validators from 'src/lib/validators'
 
 describe('validators', () => {
-  let mockThis = { errors: [] }
-  afterEach(() => {
-    mockThis.errors = []
+  let mockErrors
+  beforeEach(() => {
+    mockErrors = []
   })
   describe('default', () => {
     it('sets a default value from the def if no value is set', () => {
       const def = {
         default: 'foo'
       }
-      const actual = validators.default(def, 'test', undefined)
+      const actual = validators.default(def, undefined)
       expect(actual).to.equal('foo')
     })
     it('uses the value if it is already set', () => {
       const def = {
         default: 'foo'
       }
-      const actual = validators.default(def, 'test', 'bar')
+      const actual = validators.default(def, 'bar')
       expect(actual).to.equal('bar')
     })
   })
@@ -27,22 +27,22 @@ describe('validators', () => {
       const def = {
         allow: [ 'foo', 'bar' ]
       }
-      validators.allow.call(mockThis, def, 'test', 'foo')
-      expect(mockThis.errors.length).to.equal(0)
+      validators.allow(def, 'foo', 'test', mockErrors)
+      expect(mockErrors.length).to.equal(0)
     })
     it('passes if value is in allow (single)', () => {
       const def = {
         allow: 'foo'
       }
-      validators.allow.call(mockThis, def, 'test', 'foo')
-      expect(mockThis.errors.length).to.equal(0)
+      validators.allow(def, 'foo', 'test', mockErrors)
+      expect(mockErrors.length).to.equal(0)
     })
     it('creates an error object if value is not in allow (array)', () => {
       const def = {
         allow: [ 'foo', 'bar' ]
       }
-      validators.allow.call(mockThis, def, 'test', 'fizz')
-      expect(mockThis.errors[0]).to.deep.equal({
+      validators.allow(def, 'fizz', 'test', mockErrors)
+      expect(mockErrors[0]).to.deep.equal({
         type: 'allow',
         sub: [ 'foo', 'bar' ],
         key: 'test',
@@ -54,8 +54,8 @@ describe('validators', () => {
       const def = {
         allow: 'foo'
       }
-      validators.allow.call(mockThis, def, 'test', 'bar')
-      expect(mockThis.errors[0]).to.deep.equal({
+      validators.allow(def, 'bar', 'test', mockErrors)
+      expect(mockErrors[0]).to.deep.equal({
         type: 'allow',
         sub: 'foo',
         key: 'test',
@@ -67,8 +67,8 @@ describe('validators', () => {
   describe('min', () => {
     it('creates an error object if array length is less than def min', () => {
       const def = { min: 3 }
-      validators.min.call(mockThis, def, 'test', [ 'foo' ])
-      expect(mockThis.errors[0]).to.deep.equal({
+      validators.min(def, [ 'foo' ], 'test', mockErrors)
+      expect(mockErrors[0]).to.deep.equal({
         type: 'min',
         sub: 3,
         key: 'test',
@@ -78,8 +78,8 @@ describe('validators', () => {
     })
     it('creates an error object if string length is less than def min', () => {
       const def = { min: 5 }
-      validators.min.call(mockThis, def, 'test', 'foo')
-      expect(mockThis.errors[0]).to.deep.equal({
+      validators.min(def, 'foo', 'test', mockErrors)
+      expect(mockErrors[0]).to.deep.equal({
         type: 'min',
         sub: 5,
         key: 'test',
@@ -89,8 +89,8 @@ describe('validators', () => {
     })
     it('creates an error object if number is less than def min', () => {
       const def = { min: 10 }
-      validators.min.call(mockThis, def, 'test', 5)
-      expect(mockThis.errors[0]).to.deep.equal({
+      validators.min(def, 5, 'test', mockErrors)
+      expect(mockErrors[0]).to.deep.equal({
         type: 'min',
         sub: 10,
         key: 'test',
@@ -102,8 +102,8 @@ describe('validators', () => {
   describe('max', () => {
     it('creates an error object if array length is greater than def max', () => {
       const def = { max: 1 }
-      validators.max.call(mockThis, def, 'test', [ 'foo', 'bar' ])
-      expect(mockThis.errors[0]).to.deep.equal({
+      validators.max(def, [ 'foo', 'bar' ], 'test', mockErrors)
+      expect(mockErrors[0]).to.deep.equal({
         type: 'max',
         sub: 1,
         key: 'test',
@@ -113,8 +113,8 @@ describe('validators', () => {
     })
     it('creates an error object if string length is greater than def max', () => {
       const def = { max: 2 }
-      validators.max.call(mockThis, def, 'test', 'foo')
-      expect(mockThis.errors[0]).to.deep.equal({
+      validators.max(def, 'foo', 'test', mockErrors)
+      expect(mockErrors[0]).to.deep.equal({
         type: 'max',
         sub: 2,
         key: 'test',
@@ -124,8 +124,8 @@ describe('validators', () => {
     })
     it('creates an error object if number is greater than def max', () => {
       const def = { max: 5 }
-      validators.max.call(mockThis, def, 'test', 10)
-      expect(mockThis.errors[0]).to.deep.equal({
+      validators.max(def, 10, 'test', mockErrors)
+      expect(mockErrors[0]).to.deep.equal({
         type: 'max',
         sub: 5,
         key: 'test',
diff --git a/test/src/types.spec.js b/test/src/types.spec.js
index a045b1a..aebc2dc 100644
--- a/test/src/types.spec.js
+++ b/test/src/types.spec.js
@@ -19,7 +19,7 @@ describe('types', () => {
       expect(actual).to.be.a.function
     })
     it('allows an empty string to pass (via return) when empty flag is set', () => {
-      const actual = types.validate.call({ errors: [] }, { type: 'string', empty: true }, 'foo', '')
+      const actual = types.validate.call({ errors: [] }, { type: 'string', empty: true }, '', 'foo')
       expect(actual).to.equal('')
     })
   })
@@ -56,5 +56,9 @@ describe('types', () => {
       context.def.sub = 'nope'
       expect(types.check.bind(null, context)).to.throw('Type \'string:nope\' does not exist')
     })
+    it('throws an error if the type contains path characters', () => {
+      context.def.type = '../creators'
+      expect(types.check.bind(null, context)).to.throw('Illegal type name: ../creators')
+    })
   })
 })