Repository: ViacomInc/data-point
Pull request #287 (2018-05-22 17:34:52)

Entity instances
<!--
Thanks for your interest in the project. We appreciate bugs filed and PRs submitted!

Please make sure that you are familiar with and follow the Code of Conduct for
this project (found in the CODE_OF_CONDUCT.md file).

Also, please make sure you're familiar with and follow the instructions in the
contributing guidelines (found in the CONTRIBUTING.md file).

Please fill out the information below to expedite the review and (hopefully)
merge of your pull request!

BREAKING CHANGES:

If your PR includes a breaking change, please submit it with a codemod under
data-point-codemods that will help users upgrade their codebase.

Breaking changes without a codemod will not be accepted unless a codemod is not
viable or does not apply to the specific situation.
-->

<!-- What changes are being made? (What feature/bug is being fixed here?) -->
**What**:

Enables the usage of entity instances as stand-alone reducers. Before this PR the only way to reference an entity would be through a EntityReducer id (string) that would map to an actual entity on a lookup Map Object. This PR enables the following code: 

```js
const DataPoint = require('data-point')

const { Model } = DataPoint.entities

const input = {
  a: {
    b: {
      c: [1, 2, 3]
    }
  }
}

const getMax = input => {
  return Math.max.apply(null, input)
}

const myModel = Model('myModel', {
  value: ['$a.b.c', getMax]
})

const dataPoint = DataPoint.create()

dataPoint.resolve(myModel, input).then(output => {
  // output 3
})
```

<!-- Why are these changes necessary? -->
**Why**:

DataPoint entities would only be abled to be used if registered on the datapoint instance, this created a very complex code base and would also make it hard to test. Through entity instances we can create a datapoint instance and run any instance to test it or implement it with out having to be registered.

A side effect of this approach is that entity instances get parsed on setup time, this means errors will be thrown earlier, it also redices the chance of referencing an entity that has not been registered, this error would happen on run time until it was actually executed. With instances there is no more bad referencing (there is still support to the older way of using entities, so the chances of a bad entity reference still exists if used as before)

<!-- How were these changes implemented? -->
**How**:

Created a new reducer called ReducerEntityInstance which holds a reference to an actual entity that contains its own resolver. When a reducer of this type is encountered the entity will get executed on the spot instead of having to extract the resolver logic from the registered entity types. 

<!-- Have you done all of these things?  -->
**Checklist**:
<!-- add "N/A" to the end of each line that's irrelevant to your changes -->
<!-- to check an item, place an "x" in the box like so: "- [x] Documentation" -->
- [X] Has Breaking changes
- [X] Documentation
- [X] Tests
- [X] Ready to be merged <!-- In your opinion, is this ready to be merged as soon as it's reviewed? -->
- [ ] Added username to **all-contributors** list

<!-- feel free to add additional comments -->
--------------

codecov[bot]: # [Codecov](https://codecov.io/gh/ViacomInc/data-point/pull/287?src=pr&el=h1) Report
> Merging [#287](https://codecov.io/gh/ViacomInc/data-point/pull/287?src=pr&el=desc) into [master](https://codecov.io/gh/ViacomInc/data-point/commit/a21de5b622581deeb9ddd9cdfad47796debbde30?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/ViacomInc/data-point/pull/287/graphs/tree.svg?token=LYxItnrx4i&width=650&height=150&src=pr)](https://codecov.io/gh/ViacomInc/data-point/pull/287?src=pr&el=tree)

```diff
@@          Coverage Diff          @@
##           master   #287   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files         125    128    +3     
  Lines        1779   1821   +42     
  Branches      164    172    +8     
=====================================
+ Hits         1779   1821   +42
```


| [Impacted Files](https://codecov.io/gh/ViacomInc/data-point/pull/287?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [...data-point/lib/entity-types/entity-schema/index.js](https://codecov.io/gh/ViacomInc/data-point/pull/287/diff?src=pr&el=tree#diff-cGFja2FnZXMvZGF0YS1wb2ludC9saWIvZW50aXR5LXR5cGVzL2VudGl0eS1zY2hlbWEvaW5kZXguanM=) | `100% <100%> (ø)` | :arrow_up: |
| [...ata-point/lib/entity-types/entity-model/factory.js](https://codecov.io/gh/ViacomInc/data-point/pull/287/diff?src=pr&el=tree#diff-cGFja2FnZXMvZGF0YS1wb2ludC9saWIvZW50aXR5LXR5cGVzL2VudGl0eS1tb2RlbC9mYWN0b3J5Lmpz) | `100% <100%> (ø)` | :arrow_up: |
| [...ta-point/lib/entity-types/entity-schema/factory.js](https://codecov.io/gh/ViacomInc/data-point/pull/287/diff?src=pr&el=tree#diff-cGFja2FnZXMvZGF0YS1wb2ludC9saWIvZW50aXR5LXR5cGVzL2VudGl0eS1zY2hlbWEvZmFjdG9yeS5qcw==) | `100% <100%> (ø)` | :arrow_up: |
| [...data-point/lib/entity-types/base-entity/factory.js](https://codecov.io/gh/ViacomInc/data-point/pull/287/diff?src=pr&el=tree#diff-cGFja2FnZXMvZGF0YS1wb2ludC9saWIvZW50aXR5LXR5cGVzL2Jhc2UtZW50aXR5L2ZhY3RvcnkuanM=) | `100% <100%> (ø)` | :arrow_up: |
| [...data-point/lib/entity-types/entity-hash/factory.js](https://codecov.io/gh/ViacomInc/data-point/pull/287/diff?src=pr&el=tree#diff-cGFja2FnZXMvZGF0YS1wb2ludC9saWIvZW50aXR5LXR5cGVzL2VudGl0eS1oYXNoL2ZhY3RvcnkuanM=) | `100% <100%> (ø)` | :arrow_up: |
| [...oint/lib/entity-types/entity-collection/factory.js](https://codecov.io/gh/ViacomInc/data-point/pull/287/diff?src=pr&el=tree#diff-cGFja2FnZXMvZGF0YS1wb2ludC9saWIvZW50aXR5LXR5cGVzL2VudGl0eS1jb2xsZWN0aW9uL2ZhY3RvcnkuanM=) | `100% <100%> (ø)` | :arrow_up: |
| [packages/data-point/lib/index.js](https://codecov.io/gh/ViacomInc/data-point/pull/287/diff?src=pr&el=tree#diff-cGFja2FnZXMvZGF0YS1wb2ludC9saWIvaW5kZXguanM=) | `100% <100%> (ø)` | :arrow_up: |
| [...b/reducer-types/reducer-entity-instance/resolve.js](https://codecov.io/gh/ViacomInc/data-point/pull/287/diff?src=pr&el=tree#diff-cGFja2FnZXMvZGF0YS1wb2ludC9saWIvcmVkdWNlci10eXBlcy9yZWR1Y2VyLWVudGl0eS1pbnN0YW5jZS9yZXNvbHZlLmpz) | `100% <100%> (ø)` | |
| [...s/data-point/lib/entity-types/entity-hash/index.js](https://codecov.io/gh/ViacomInc/data-point/pull/287/diff?src=pr&el=tree#diff-cGFja2FnZXMvZGF0YS1wb2ludC9saWIvZW50aXR5LXR5cGVzL2VudGl0eS1oYXNoL2luZGV4Lmpz) | `100% <100%> (ø)` | :arrow_up: |
| [...a-point/lib/entity-types/entity-transform/index.js](https://codecov.io/gh/ViacomInc/data-point/pull/287/diff?src=pr&el=tree#diff-cGFja2FnZXMvZGF0YS1wb2ludC9saWIvZW50aXR5LXR5cGVzL2VudGl0eS10cmFuc2Zvcm0vaW5kZXguanM=) | `100% <100%> (ø)` | :arrow_up: |
| ... and [21 more](https://codecov.io/gh/ViacomInc/data-point/pull/287/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/ViacomInc/data-point/pull/287?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/ViacomInc/data-point/pull/287?src=pr&el=footer). Last update [a21de5b...cd04322](https://codecov.io/gh/ViacomInc/data-point/pull/287?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

acatl: - [ ] fix entity-types/spec/factory.test.js:21 expect statement

Patch:
diff --git a/packages/data-point-express/README.md b/packages/data-point-express/README.md
index 3e4d99c..09a8f33 100644
--- a/packages/data-point-express/README.md
+++ b/packages/data-point-express/README.md
@@ -194,7 +194,7 @@ app.use('/api', service.router({
     priority: 100,
     path: '/hello-world',
     method: 'GET',
-    middleware: 'transform:HelloWorld'
+    middleware: 'reducer:HelloWorld'
   },
   addUser: {
     priority: 200,
diff --git a/packages/data-point-express/examples/as-middleware.js b/packages/data-point-express/examples/as-middleware.js
index e447cff..298b5fe 100644
--- a/packages/data-point-express/examples/as-middleware.js
+++ b/packages/data-point-express/examples/as-middleware.js
@@ -18,7 +18,7 @@ Service.create({
     app.use('/api/inspect', service.inspector())
 
     // create api routes
-    app.get('/api/hello-world', service.mapTo('transform:HelloWorld'))
+    app.get('/api/hello-world', service.mapTo('reducer:HelloWorld'))
     app.get('/api/person/:personId', service.mapTo('entry:getPerson'))
 
     app.listen(3000, err => {
diff --git a/packages/data-point-express/examples/as-router.js b/packages/data-point-express/examples/as-router.js
index 5657f8d..ab58a9e 100644
--- a/packages/data-point-express/examples/as-router.js
+++ b/packages/data-point-express/examples/as-router.js
@@ -9,12 +9,12 @@ const routes = {
   helloWorld: {
     priority: 100,
     path: '/hello-world',
-    middleware: 'transform:HelloWorld'
+    middleware: 'reducer:HelloWorld'
   },
   greet: {
     priority: 200,
     path: '/greet/:name',
-    middleware: 'transform:greet'
+    middleware: 'reducer:greet'
   },
   getPerson: {
     priority: 300,
diff --git a/packages/data-point-express/examples/entities.js b/packages/data-point-express/examples/entities.js
index 277422d..90165eb 100644
--- a/packages/data-point-express/examples/entities.js
+++ b/packages/data-point-express/examples/entities.js
@@ -1,8 +1,8 @@
 module.exports = {
-  'transform:HelloWorld': () => {
+  'reducer:HelloWorld': () => {
     return 'Hello World!!'
   },
-  'transform:greet': (input, acc) => {
+  'reducer:greet': (input, acc) => {
     return `Hello ${acc.locals.params.name}!!`
   },
   'entry:getPerson': {
diff --git a/packages/data-point-service/README.md b/packages/data-point-service/README.md
index 9a4f5ba..4fa6765 100644
--- a/packages/data-point-service/README.md
+++ b/packages/data-point-service/README.md
@@ -39,12 +39,12 @@ The Service Object holds a reference to a dataPoint instance.
 ```js
 const options = {
   entities: {
-    'transform:foo': (input, acc) => 'bar'
+    'reducer:foo': (input, acc) => 'bar'
   }
 }
 factory.create(options)
   .then((service) => {
-    return service.dataPoint.transform('transform:foo')
+    return service.dataPoint.transform('reducer:foo')
   })
   .then((output) => {
     console.log(output)
diff --git a/packages/data-point/README.md b/packages/data-point/README.md
index a583c2d..4ac5be6 100644
--- a/packages/data-point/README.md
+++ b/packages/data-point/README.md
@@ -33,6 +33,7 @@ npm install --save data-point
   - [function](#function-reducer)
   - [object](#object-reducer)
   - [entity](#entity-reducer)
+  - [entity-id](#entity-id-reducer)
   - [list](#list-reducer)
 - [Reducer Helpers](#reducer-helpers)
   - [assign](#reducer-assign)
@@ -115,81 +116,89 @@ Based on an initial feed, fetch and aggregate results from multiple remote servi
 
   ```js
   const DataPoint = require('data-point')
+
   // create DataPoint instance
   const dataPoint = DataPoint.create()
-  const { map } = DataPoint.helpers
 
-  // add entities to dataPoint instance
-  dataPoint.addEntities({
-    // remote service request
-    'request:Planet': {
-      // {value.planetId} injects the
-      // value from the accumulator
-      // creates: https://swapi.co/api/planets/1/
-      url: 'https://swapi.co/api/planets/{value.planetId}'
-    },
+  const {
+    Request,
+    Model,
+    Schema
+  } = DataPoint.entities
 
-    // model entity to resolve a Planet
-    'model:Planet': {
-      inputType: 'schema:DataInput',
-      value: [
-        // hit request:Planet data source
-        'request:Planet',
-        // map result to an object reducer
-        {
-          // map name key
-          name: '$name',
-          population: '$population',
-          // residents is an array of urls
-          // eg. https://swapi.co/api/people/1/
-          // where each url gets mapped
-          // to a model:Resident
-          residents: ['$residents', map('model:Resident')]
-        }
-      ]
-    },
+  const {
+    map
+  } = DataPoint.helpers
 
-    // model entity to resolve a Planet
-    'model:Resident': {
-      inputType: 'string',
-      value: [
-        // hit request:Resident
-        'request:Resident',
-        // extract data
-        {
-          name: '$name',
-          gender: '$gender',
-          birthYear: '$birth_year'
+  // schema to verify data input
+  const PlanetSchema = Schema('PlanetSchema', {
+    schema: {
+      type: 'object',
+      properties: {
+        planetId: {
+          $id: '/properties/planet',
+          type: 'integer'
         }
-      ]
-    },
+      }
+    }
+  })
 
-    'request:Resident': {
-      // check input is string
-      inputType: 'string',
-      url: '{value}'
-    },
+  // remote service request
+  const PlanetRequest = Request('Planet', {
+    // {value.planetId} injects the
+    // value from the accumulator
+    // creates: https://swapi.co/api/planets/1/
+    url: 'https://swapi.co/api/planets/{value.planetId}'
+  })
 
-    // schema to verify data input
-    'schema:DataInput': {
-      schema: {
-        type: 'object',
-        properties: {
-          planetId: {
-            $id: '/properties/planet',
-            type: 'integer'
-          }
-        }
+  const ResidentRequest = Request('Resident', {
+    // check input is string
+    inputType: 'string',
+    url: '{value}'
+  })
+
+  // model entity to resolve a Planet
+  const ResidentModel = Model('Resident', {
+    inputType: 'string',
+    value: [
+      // hit request:Resident
+      ResidentRequest,
+      // extract data
+      {
+        name: '$name',
+        gender: '$gender',
+        birthYear: '$birth_year'
       }
-    }
+    ]
+  })
+
+  // model entity to resolve a Planet
+  const PlanetModel = Model('Planet', {
+    inputType: PlanetSchema,
+    value: [
+      // hit request:Planet data source
+      PlanetRequest,
+      // map result to an object reducer
+      {
+        // map name key
+        name: '$name',
+        population: '$population',
+        // residents is an array of urls
+        // eg. https://swapi.co/api/people/1/
+        // where each url gets mapped
+        // to a model:Resident
+        residents: ['$residents', map(ResidentModel)]
+      }
+    ]
   })
 
   const input = {
     planetId: 1
   }
 
-  dataPoint.resolve('model:Planet', input)
+  dataPoint.resolve(PlanetModel, input)
     .then((output) => {
+      console.log(output)
       /*
       output -> 
       { 
@@ -208,7 +217,7 @@ Based on an initial feed, fetch and aggregate results from multiple remote servi
   ```
 </details>
 
-Example at: [examples/async-example.js](examples/async-example.js)
+Example at: [examples/full-example-instances.js](examples/full-example-instances.js)
 
 ## <a name="api">API</a>
 
@@ -260,7 +269,7 @@ DataPoint instance.
         foo: 'bar'
       },
       entities: {
-        'transform:HelloWorld': (input) => {
+        'reducer:HelloWorld': (input) => {
           return `hello ${input}!!`
         }
       }
@@ -443,7 +452,8 @@ Reducers are used to transform values **asynchronously**. DataPoint supports the
 2. [function](#function-reducer)
 3. [object](#object-reducer)
 4. [entity](#entity-reducer)
-5. [list](#list-reducer)
+4. [entity-id](#entity-id-reducer)
+6. [list](#list-reducer)
 
 ### <a name="path-reducer">Path Reducer</a>
 
@@ -902,7 +912,55 @@ const input = { a: 1 }
 dataPoint.resolve(reducer, input) // => {}
 ```
 
-### <a name="entity-reducer">Entity Reducer</a>
+### <a name="entity-reducer">Entity instance reducer</a>
+
+An entity instance reducer is used to apply a given entity with to the current [Accumulator](#accumulator).
+
+See the [Entities](#entities) section for information about the supported entity types.
+
+**OPTIONS**
+
+| Option | Type | Description |
+|:---|:---|:---|
+| *?* | `String` | Only execute entity if `acc.value` is not equal to `false`, `null` or `undefined`. |
+| *EntityType* | `String` | Valid Entity type. |
+| *EntityID* | `String` | Valid Entity ID. Appending `[]` will map the reducer to each element of an input array. If the current accumulator value is not an array, the reducer will return `undefined`. |
+
+<details>
+  <summary>Entity Reducer Example</summary>
+
+  ```js
+  const { 
+    Model, 
+    Request 
+  } = require('data-point').entities
+
+  const PersonRequest = Request('PersonRequest', {
+    url: 'https://swapi.co/api/people/{value}'
+  })
+
+  const PersonModel = Model('PersonModel', {
+    value: {
+      name: '$name',
+      birthYear: '$birth_year'
+    }
+  })
+
+  dataPoint
+    .resolve([PersonRequest, PersonModel], 1)
+    .then((output) => {
+      assert.deepEqual(output, {
+        name: 'Luke Skywalker',
+        birthYear: '19BBY'
+      })
+    })
+  ```
+
+</details>
+
+Example at: [examples/reducer-entity-instance.js](examples/reducer-entity-instance.js)
+
+### <a name="entity-id">Reference to registered Entity</a>
 
 An entity reducer is used to execute an entity with the current [Accumulator](#accumulator) as the input.
 
@@ -939,14 +997,14 @@ See the [Entities](#entities) section for information about the supported entity
   }
 
   dataPoint.addEntities({
-    'transform:getGreeting': '$a.b',
-    'transform:toUpperCase': toUpperCase,
+    'reducer:getGreeting': '$a.b',
+    'reducer:toUpperCase': toUpperCase,
   })
 
-  // resolve `transform:getGreeting`,
-  // pipe value to `transform:toUpperCase`
+  // resolve `reducer:getGreeting`,
+  // pipe value to `reducer:toUpperCase`
   dataPoint
-    .resolve(['transform:getGreeting | transform:toUpperCase'], input)
+    .resolve(['reducer:getGreeting | reducer:toUpperCase'], input)
     .then((output) => {
       assert.equal(output, 'HELLO WORLD')
     })
@@ -971,11 +1029,11 @@ See the [Entities](#entities) section for information about the supported entity
   }
 
   dataPoint.addEntities({
-    'transform:toUpperCase': toUpperCase
+    'reducer:toUpperCase': toUpperCase
   })
 
   dataPoint
-    .resolve(['$a | transform:toUpperCase[]'], input)
+    .resolve(['$a | reducer:toUpperCase[]'], input)
     .then((output) => {
       assert.equal(output[0], 'HELLO WORLD')
       assert.equal(output[1], 'HELLO LAIA')
@@ -1027,7 +1085,7 @@ dataPoint.addEntities({
   'request:getPerson': {
     url: 'https://swapi.co/api/people/{value}'
   },
-  'transform:getPerson': {
+  'reducer:getPerson': {
     name: '$name',
     // request:getPerson will only
     // be executed if swapiId is
@@ -1037,7 +1095,7 @@ dataPoint.addEntities({
 })
 
 dataPoint
-  .resolve('transform:getPerson[]', people)
+  .resolve('reducer:getPerson[]', people)
   .then((output) => {
     assert.deepEqual(output, [
       {
@@ -1426,14 +1484,21 @@ dataPoint.resolve(r2, input) // => { b: 1 }
 
 ## <a name="entities">Entities</a>
 
-Entities are used to transform data by composing multiple reducers. They're cached by DataPoint instances, and they can be added in two different ways:
+Entities are used to transform data by composing multiple reducers, they can be created as non-registered or registered entities.
+
+- **<a name="instance-entity-type">Instance entities</a>** - are entity objects created directly with an Entity Factory, they are meant to be used as a [entity reducer](#entity-reducer).
+- **<a name="entity-id-type">Registered entities</a>** - are entity objects which are registered and cached in a DataPoint instance, they are meant to be used as a [registered entity reducer](#entity-id-reducer).
+
+**Registered entities** may be added to DataPoint in two different ways:
 
 1. With the `DataPoint.create` method (as explained in the [setup examples](#setup-examples))
 2. With the [dataPoint.addEntities](#api-data-point-add-entities) instance method
 
-### <a name="entity-factories">Entity factories</a>
+See **[built-in entities](#built-in-entities)** for information on what each entity does.
 
-Entities can be defined with object literals, or with these factory functions:
+### <a name="instance-entity">Instance Entity</a>
+
+Entities can be created with these factory functions:
 
 ```js
 const {
@@ -1445,13 +1510,15 @@ const {
   Request,
   Control,
   Schema
-} = require('data-point').entityFactories
+} = require('data-point').entities
 ```
 
+**SYNOPSIS**
+
 Each factory has the following signature:
 
 ```js
-Factory(name:String, spec:Object):Object
+Factory(name:String, spec:Object):EntityInstance
 ```
 
 **ARGUMENTS**
@@ -1461,54 +1528,56 @@ Factory(name:String, spec:Object):Object
 | *name* | `string` | The name of the entity; this will be used to generate an entity ID with the format `<entityType>:<name>` |
 | *spec* | `Object` | The source for generating the entity |
 
-Using these factories is optional, and the following examples are equivalent:
 
-**Example #1 (with object literal)**
+**Example**
 
 ```js
-dataPoint.addEntities({
-  'model:hello-world': {
-    value: input => ({
-      hello: 'world'
-    })
-  }
-})
-```
-
-**Example #2 (with factory and assignment)**
+const DataPoint = require('data-point')
+const { Model } = DataPoint.entities
 
-```js
-const { Model } = DataPoint.entityFactories
+dataPoint = DataPoint.create()
 
-const model = Model('hello-world', {
+const HelloWorld = Model('HelloWorld', {
   value: input => ({
     hello: 'world'
   })
 })
 
-const entities = {}
-
-assert.equal(model.id, 'model:hello-world')
+// to reference it we use the actual entity instance
+dataPoint.resolve(HelloWorld, {})
+  .then(value => {
+    console.assert(value, {
+      hello: 'world'
+    })
+  })
+```
 
-entities[model.id] = model.spec
+### <a name="entity-id">Registered Entity</a>
 
-dataPoint.addEntities(entities)
-```
+You may register an entity through [DataPoint.create](#api-data-point-create) or [dataPoint.addEntities](#api-data-point-add-entities).
 
-**Example #3 (with factory and spread syntax)**
+**Example**
 
 ```js
-const { Model } = DataPoint.entityFactories
+const DataPoint = require('data-point')
 
-const model = Model('hello-world', {
-  value: input => ({
-    hello: 'world'
-  })
+dataPoint = DataPoint.create({
+  entities: {
+    'model:HelloWorld', {
+      value: input => ({
+        hello: 'world'
+      } 
+    }
+  }
 })
 
-const entities = { ...model }
-
-dataPoint.addEntities(entities)
+// to reference it we use a string with its registered id
+dataPoint.resolve('model:HelloWorld', {})
+  .then(value => {
+    console.assert(value, {
+      hello: 'world'
+    })
+  })
 ```
 
 ### <a name="entity-base-api">Entity Base API</a>
@@ -1684,7 +1753,7 @@ For backwards compatibility, the keyword **transform** can be used in place of *
 
 ```js
 dataPoint.addEntities({
-  'transform:<entityId>': Reducer
+  'reducer:<entityId>': Reducer
 })
 ```
 
@@ -3303,7 +3372,7 @@ DataPoint exposes a set of methods to help you build your own Custom Entity type
 
 ### <a name="adding-entity-types">Adding new Entity types</a>
 
-You can add custom Entity types when creating a DataPoint instance with [DataPoint.create](#api-data-point-create); you can also add them later with [dataPoint.addEntityType](#data-point-add-entity-type) and/or [dataPoint.addEntityTypes](#data-point-add-entity-types).
+You can register custom Entity types when creating a DataPoint instance with [DataPoint.create](#api-data-point-create); you can also register them later with [dataPoint.addEntityType](#data-point-add-entity-type) and/or [dataPoint.addEntityTypes](#data-point-add-entity-types).
 
 #### <a name="data-point-add-entity-types">dataPoint.addEntityType</a>
 
@@ -3352,7 +3421,7 @@ Because you are extending the base entity API, you get before, value, after, par
 This is a factory method, it receives a raw entity spec, and expects to return a new entity instance object.
 
 ```js
-function create(spec:Object):Object
+function create(name:String, spec:Object):Object
 ```
 
 #### <a name="entity-resolve">Entity.resolve</a>
@@ -3383,7 +3452,9 @@ function resolve(acc:Accumulator, resolveReducer:function):Promise<Accumulator>
   */
   function create (spec, id) {
     // create an entity instance
-    const entity = DataPoint.createEntity(RenderTemplate, spec, id)
+    const entity = mew RenderTemplate()
+    entity.spec = spec
+    entity.resolve = resolve
     // set/create template from spec.template value
     entity.template = _.template(_.defaultTo(spec.template, ''))
     return entity
@@ -3413,10 +3484,7 @@ function resolve(acc:Accumulator, resolveReducer:function):Promise<Accumulator>
   /**
   * RenderEntity API
   */
-  const RenderEntity = {
-    create,
-    resolve
-  }
+  const RenderEntity = DataPoint.createEntity('render, create)
 
   // Create DataPoint instance
   const dataPoint = DataPoint.create({
diff --git a/packages/data-point/examples/custom-entity-type.js b/packages/data-point/examples/custom-entity-type.js
index ae6a0d3..2ba5096 100644
--- a/packages/data-point/examples/custom-entity-type.js
+++ b/packages/data-point/examples/custom-entity-type.js
@@ -7,13 +7,14 @@ function RenderTemplate () {}
 
 /**
  * Entity Factory
- * @param {*} spec - Entity Specification
  * @param {string} id - Entity id
+ * @param {*} spec - Entity Specification
  * @return {RenderTemplate} RenderTemplate Instance
  */
-function create (spec, id) {
+function create (id, spec) {
   // create an entity instance
-  const entity = DataPoint.createEntity(RenderTemplate, spec, id)
+  const entity = new RenderTemplate()
+  entity.spec = spec
   // set/create template from spec.template value
   entity.template = _.template(_.defaultTo(spec.template, ''))
   return entity
@@ -45,10 +46,7 @@ function resolve (accumulator, resolveReducer) {
 /**
  * RenderEntity API
  */
-const RenderEntity = {
-  create,
-  resolve
-}
+const RenderEntity = DataPoint.createEntity('render', create, resolve)
 
 // Create DataPoint instance
 const dataPoint = DataPoint.create({
diff --git a/packages/data-point/examples/entity-model-basic.js b/packages/data-point/examples/entity-model-basic.js
index 542e5eb..c1ff7f0 100644
--- a/packages/data-point/examples/entity-model-basic.js
+++ b/packages/data-point/examples/entity-model-basic.js
@@ -1,6 +1,7 @@
 const assert = require('assert')
 const DataPoint = require('../')
-const dataPoint = DataPoint.create()
+
+const { Model } = DataPoint.entities
 
 const input = {
   a: {
@@ -18,12 +19,11 @@ const multiplyBy = number => input => {
   return input * number
 }
 
-dataPoint.addEntities({
-  'model:foo': {
-    value: ['$a.b.c', getMax, multiplyBy(10)]
-  }
+const myModel = Model('myModel', {
+  value: ['$a.b.c', getMax, multiplyBy(10)]
 })
 
-dataPoint.resolve('model:foo', input).then(output => {
+const dataPoint = DataPoint.create()
+dataPoint.resolve(myModel, input).then(output => {
   assert.equal(output, 30)
 })
diff --git a/packages/data-point/examples/full-example-instances.js b/packages/data-point/examples/full-example-instances.js
new file mode 100644
index 0000000..39ca81b
--- /dev/null
+++ b/packages/data-point/examples/full-example-instances.js
@@ -0,0 +1,96 @@
+const mocks = require('./async-example.mocks')
+const DataPoint = require('../')
+
+// create DataPoint instance
+const dataPoint = DataPoint.create()
+
+const { Request, Model, Schema } = DataPoint.entities
+
+const { map } = DataPoint.helpers
+
+// schema to verify data input
+const PlanetSchema = Schema('PlanetSchema', {
+  schema: {
+    type: 'object',
+    properties: {
+      planetId: {
+        $id: '/properties/planet',
+        type: 'integer'
+      }
+    }
+  }
+})
+
+// remote service request
+const PlanetRequest = Request('Planet', {
+  // {value.planetId} injects the
+  // value from the accumulator
+  // creates: https://swapi.co/api/planets/1/
+  url: 'https://swapi.co/api/planets/{value.planetId}'
+})
+
+const ResidentRequest = Request('Resident', {
+  // check input is string
+  inputType: 'string',
+  url: '{value}'
+})
+
+// model entity to resolve a Planet
+const ResidentModel = Model('Resident', {
+  inputType: 'string',
+  value: [
+    // hit request:Resident
+    ResidentRequest,
+    // extract data
+    {
+      name: '$name',
+      gender: '$gender',
+      birthYear: '$birth_year'
+    }
+  ]
+})
+
+// model entity to resolve a Planet
+const PlanetModel = Model('Planet', {
+  inputType: PlanetSchema,
+  value: [
+    // hit request:Planet data source
+    PlanetRequest,
+    // map result to an object reducer
+    {
+      // map name key
+      name: '$name',
+      population: '$population',
+      // residents is an array of urls
+      // eg. https://swapi.co/api/people/1/
+      // where each url gets mapped
+      // to a model:Resident
+      residents: ['$residents', map(ResidentModel)]
+    }
+  ]
+})
+
+const input = {
+  planetId: 1
+}
+
+// mock request calls
+mocks()
+
+dataPoint.resolve(PlanetModel, input).then(output => {
+  console.log(output)
+  /*
+    output ->
+    {
+      name: 'Tatooine',
+      population: 200000,
+      residents:
+      [
+        { name: 'Luke Skywalker', gender: 'male', birthYear: '19BBY' },
+        { name: 'C-3PO', gender: 'n/a', birthYear: '112BBY' },
+        { name: 'Darth Vader', gender: 'male', birthYear: '41.9BBY' },
+        ...
+      ]
+    }
+    */
+})
diff --git a/packages/data-point/examples/reducer-conditional-operator.js b/packages/data-point/examples/reducer-conditional-operator.js
index 5d96091..660cac6 100644
--- a/packages/data-point/examples/reducer-conditional-operator.js
+++ b/packages/data-point/examples/reducer-conditional-operator.js
@@ -17,7 +17,7 @@ dataPoint.addEntities({
   'request:getPerson': {
     url: 'https://swapi.co/api/people/{value}'
   },
-  'transform:getPerson': {
+  'reducer:getPerson': {
     name: '$name',
     // request:getPerson will only
     // be executed if swapiId is
@@ -28,7 +28,7 @@ dataPoint.addEntities({
 
 mockRequests()
 
-dataPoint.resolve('transform:getPerson[]', people).then(output => {
+dataPoint.resolve('reducer:getPerson[]', people).then(output => {
   assert.deepEqual(output, [
     {
       name: 'Luke Skywalker',
diff --git a/packages/data-point/examples/reducer-entity-instance.js b/packages/data-point/examples/reducer-entity-instance.js
new file mode 100644
index 0000000..c5af8b0
--- /dev/null
+++ b/packages/data-point/examples/reducer-entity-instance.js
@@ -0,0 +1,25 @@
+const assert = require('assert')
+
+const DataPoint = require('../')
+
+const { Model, Request } = DataPoint.entities
+
+const PersonRequest = Request('PersonRequest', {
+  url: 'https://swapi.co/api/people/{value}'
+})
+
+const PersonModel = Model('PersonModel', {
+  value: {
+    name: '$name',
+    birthYear: '$birth_year'
+  }
+})
+
+const dataPoint = DataPoint.create()
+
+dataPoint.resolve([PersonRequest, PersonModel], 1).then(output => {
+  assert.deepEqual(output, {
+    name: 'Luke Skywalker',
+    birthYear: '19BBY'
+  })
+})
diff --git a/packages/data-point/lib/core/core.js b/packages/data-point/lib/core/core.js
index f04516e..9bf1c48 100644
--- a/packages/data-point/lib/core/core.js
+++ b/packages/data-point/lib/core/core.js
@@ -2,7 +2,7 @@ const _ = require('lodash')
 
 const Transform = require('./transform')
 const normalizeEntities = require('./normalize-entities')
-const entities = require('../entity-types').definitions
+const entityTypeDefinitions = require('../entity-types').definitions
 
 const storeValues = require('../stores/values')
 const storeEntities = require('../stores/entities')
@@ -63,14 +63,10 @@ function create (spec) {
   manager.addEntities = addEntitiesToStore.bind(null, manager.entities)
 
   // built-in entity types
-  _.forOwn(entities, (definition, key) => {
-    manager.addEntityType(key.toLowerCase(), definition)
+  _.forOwn(entityTypeDefinitions, (entityType, key) => {
+    manager.addEntityType(key.toLowerCase(), entityType)
   })
 
-  // for backwards compatibility
-  manager.addEntityType('transform', entities.Reducer)
-  manager.addEntityType('source', entities.Request)
-
   addToStore(manager.values, options.values, true)
 
   manager.addEntityTypes(options.entityTypes, true)
diff --git a/packages/data-point/lib/entity-types/base-entity/factory.js b/packages/data-point/lib/entity-types/base-entity/factory.js
index cdaeb19..8d998bd 100644
--- a/packages/data-point/lib/entity-types/base-entity/factory.js
+++ b/packages/data-point/lib/entity-types/base-entity/factory.js
@@ -5,30 +5,76 @@ const { normalizeTypeCheckSource } = require('../../helpers/type-check-helpers')
 const createReducer = require('../../reducer-types').create
 
 /**
- * @param {Function} Factory - factory function to create the entity
- * @param {Object} spec - spec for the Entity
- * @param {string} id - Entity's id
+ * @throws When function is not valid
+ * @param {Function} resolve
+ * @returns {Boolean} true if valid
  */
-function create (Factory, spec, id) {
-  const entity = new Factory(spec)
-
-  entity.id = id
-
-  if (spec.before) {
-    entity.before = createReducer(spec.before)
+function validateResolve (resolve) {
+  if (typeof resolve !== 'function') {
+    throw new Error(
+      `"resolve" must be a function, create(type:String, factory:Function, resolve:Function)`
+    )
   }
 
-  if (spec.value) {
-    entity.value = createReducer(spec.value)
+  if (resolve.length !== 2) {
+    throw new Error(
+      '"resolve" function must have an arity of 2, resolve(accumulator:Accumulator, resolveReducer:Function)'
+    )
   }
 
-  if (spec.after) {
-    entity.after = createReducer(spec.after)
+  return true
+}
+
+/**
+ * @throws When function is not valid
+ * @param {Function} factory
+ * @returns {Boolean} true if valid
+ */
+function validateFactory (factory) {
+  if (typeof factory !== 'function') {
+    throw new Error(
+      '"factory" argument must be a function, create(type:String, factory:Function, resolve:Function)'
+    )
   }
+  if (factory.length !== 2) {
+    throw new Error(
+      '"factory" function must have an arity of 2, factory(name:String, spec:Object)'
+    )
+  }
+  return true
+}
 
-  if (spec.error) {
-    entity.error = createReducer(spec.error)
+/**
+ * NOTE: this method mutates target
+ * @param {String} name reducer name
+ * @param {Object} target entity target
+ * @param {Object} spec entity source spec
+ */
+function setReducerIfTruthy (name, target, spec) {
+  if (spec[name]) {
+    target[name] = createReducer(spec[name])
   }
+}
+
+/**
+ * @param {String} type Entity's type
+ * @param {String} name Entity's name
+ * @param {Object} entity Entity Object
+ * @returns {Object} Entity instance
+ */
+function createEntityType (type, name, entity) {
+  const spec = Object.assign({}, entity.spec, entity)
+
+  entity.entityType = type
+  entity.isEntityInstance = true
+
+  entity.name = name
+  entity.id = `${entity.entityType}:${name}`
+
+  setReducerIfTruthy('before', entity, spec)
+  setReducerIfTruthy('value', entity, spec)
+  setReducerIfTruthy('after', entity, spec)
+  setReducerIfTruthy('error', entity, spec)
 
   if (spec.inputType) {
     const inputType = normalizeTypeCheckSource(spec.inputType)
@@ -40,9 +86,67 @@ function create (Factory, spec, id) {
     entity.outputType = createReducer(outputType)
   }
 
-  entity.params = deepFreeze(defaultTo(spec.params, {}))
+  entity.params = defaultTo(spec.params, {})
+
+  return createEntityInstance(entity)
+}
+
+/**
+ * @param {Object} entity
+ * @returns {Object} entity named instance
+ */
+function createEntityInstance (entity) {
+  function EntityFactory () {}
+  Object.defineProperty(EntityFactory, 'name', {
+    value: entity.id
+  })
+
+  return deepFreeze(Object.assign(new EntityFactory(), entity))
+}
+
+/**
+ * @param {String} type Entity's type
+ * @param {Function} factory factory function to create the entity
+ * @param {Function} resolve function to resolve the entity instance
+ */
+function create (type, factory, resolve) {
+  if (arguments.length !== 3) {
+    throw new Error(
+      'Received wrong number of arguments. Try passing create(type:String, factory:Function, resolve:Function)'
+    )
+  }
+  if (typeof type !== 'string') {
+    throw new Error(
+      '"type" argument must be a string create(type:String, factory:Function, resolve:Function)'
+    )
+  }
+
+  validateFactory(factory)
+  validateResolve(resolve)
 
-  return entity
+  /**
+   * @param {String} name - Entity's name
+   * @param {Object} spec - spec for the Entity
+   * @returns {Object} Entity instance
+   */
+  return function createEntity (name, spec) {
+    let entityName = name
+    let entitySpec = spec
+    if (arguments.length === 1) {
+      entityName = 'generic'
+      entitySpec = name
+    }
+    const entity = factory(name, entitySpec)
+    entity.resolve = resolve
+    const e = createEntityType(type, entityName, entity)
+    return e
+  }
 }
 
-module.exports.create = create
+module.exports = {
+  validateResolve,
+  validateFactory,
+  createEntityType,
+  createEntityInstance,
+  create
+}
diff --git a/packages/data-point/lib/entity-types/base-entity/index.js b/packages/data-point/lib/entity-types/base-entity/index.js
index 5e2c642..a064cfe 100644
--- a/packages/data-point/lib/entity-types/base-entity/index.js
+++ b/packages/data-point/lib/entity-types/base-entity/index.js
@@ -1,6 +1,6 @@
 /*
 NOTE: exporting the resolve function here creates a circular dependency when it's
-imported by reducer-entity/resolve.js -- to avoid this problem, that file imports
+imported by reducer-entity-id/resolve.js -- to avoid this problem, that file imports
 the resolve function directly from base-entity/resolve.js
 */
 
diff --git a/packages/data-point/lib/entity-types/base-entity/resolve.js b/packages/data-point/lib/entity-types/base-entity/resolve.js
index 73cd5fb..0e651e8 100644
--- a/packages/data-point/lib/entity-types/base-entity/resolve.js
+++ b/packages/data-point/lib/entity-types/base-entity/resolve.js
@@ -73,28 +73,40 @@ function handleByPassError (error) {
 }
 
 /**
- * @param {Object} manager
+ * @param {Reducer} reducer
+ * @param {Object} entity
+ */
+function getCurrentReducer (reducer, entity) {
+  if (!reducer.spec) {
+    return utils.assign(reducer, {
+      spec: entity
+    })
+  }
+
+  return reducer
+}
+
+module.exports.getCurrentReducer = getCurrentReducer
+
+/**
  * @param {Accumulator} accumulator
- * @param {Function} reducer
+ * @param {Reducer} reducer
+ * @param {Object} entity
  * @returns {Accumulator}
  */
-function createCurrentAccumulator (manager, accumulator, reducer) {
-  // get defined source
-  const entity = manager.entities.get(reducer.id)
-
-  // set reducer's spec
-  const currentReducer = utils.assign(reducer, {
-    spec: entity,
-    options: entity.options
-  })
+function createCurrentAccumulator (accumulator, reducer, entity) {
+  const currentReducer = getCurrentReducer(reducer, entity)
+  const entityId = reducer.id
+  const uid = `${entityId}:${utils.getUID()}`
 
   // create accumulator to resolve
   const currentAccumulator = utils.assign(accumulator, {
+    uid: uid,
     context: entity,
     reducer: currentReducer,
     initialValue: accumulator.value,
-    // shortcut to reducer.spec.params
-    params: entity.params
+    params: entity.params,
+    debug: debugEntity(reducer.entityType)
   })
 
   return currentAccumulator
@@ -155,54 +167,42 @@ function typeCheck (manager, accumulator, reducer, resolveReducer) {
   return resolveReducer(manager, accumulator, reducer).return(accumulator)
 }
 
+module.exports.typeCheck = typeCheck
 /**
  * @param {Object} manager
  * @param {Function} resolveReducer
  * @param {Accumulator} accumulator
  * @param {Function} reducer
- * @param {Function} mainResolver
+ * @param {Object} entity
  * @returns {Promise<Accumulator>}
  */
-function resolveEntity (
-  manager,
-  resolveReducer,
-  accumulator,
-  reducer,
-  mainResolver
-) {
+function resolveEntity (manager, resolveReducer, accumulator, reducer, entity) {
   const currentAccumulator = createCurrentAccumulator(
-    manager,
     accumulator,
-    reducer
+    reducer,
+    entity
   )
 
   const {
-    id,
     inputType,
     before,
     after,
     outputType
   } = currentAccumulator.reducer.spec
 
-  const entityId = id
-  const uid = `${entityId}:${utils.getUID()}`
-  const accUid = utils.set(currentAccumulator, 'uid', uid)
-
-  accUid.debug = debugEntity(reducer.entityType)
-
   const trace =
     currentAccumulator.trace === true ||
-    currentAccumulator.reducer.spec.params.trace === true
+    currentAccumulator.context.params.trace === true
 
   let timeId
   if (trace === true) {
-    timeId = `⧖ ${uid}`
+    timeId = `⧖ ${currentAccumulator.uid}`
     console.time(timeId)
   }
 
-  accUid.debug(uid, '- resolve:start')
+  currentAccumulator.debug(currentAccumulator.uid, '- resolve:start')
 
-  let result = Promise.resolve(accUid)
+  let result = Promise.resolve(currentAccumulator)
 
   result = addToPromiseChain(result, inputType, acc =>
     typeCheck(manager, acc, inputType, resolveReducer)
@@ -218,7 +218,7 @@ function resolveEntity (
 
   result = result.then(acc => {
     acc.debug(acc.uid, '- resolve')
-    return mainResolver(acc, resolveReducer.bind(null, manager))
+    return entity.resolve(acc, resolveReducer.bind(null, manager))
   })
 
   result = addToPromiseChain(result, after, acc =>
@@ -273,10 +273,10 @@ module.exports.resolveEntity = resolveEntity
  * @param {Function} resolveReducer
  * @param {Accumulator} accumulator
  * @param {Function} reducer
- * @param {Function} mainResolver
+ * @param {Object} entity
  * @returns {Promise<Accumulator>}
  */
-function resolve (manager, resolveReducer, accumulator, reducer, mainResolver) {
+function resolve (manager, resolveReducer, accumulator, reducer, entity) {
   const hasEmptyConditional = reducer.hasEmptyConditional
 
   if (hasEmptyConditional && utils.isFalsy(accumulator.value)) {
@@ -284,13 +284,7 @@ function resolve (manager, resolveReducer, accumulator, reducer, mainResolver) {
   }
 
   if (!reducer.asCollection) {
-    return resolveEntity(
-      manager,
-      resolveReducer,
-      accumulator,
-      reducer,
-      mainResolver
-    )
+    return resolveEntity(manager, resolveReducer, accumulator, reducer, entity)
   }
 
   if (!Array.isArray(accumulator.value)) {
@@ -304,13 +298,7 @@ function resolve (manager, resolveReducer, accumulator, reducer, mainResolver) {
       return Promise.resolve(itemCtx)
     }
 
-    return resolveEntity(
-      manager,
-      resolveReducer,
-      itemCtx,
-      reducer,
-      mainResolver
-    )
+    return resolveEntity(manager, resolveReducer, itemCtx, reducer, entity)
   }).then(mappedResults => {
     const value = mappedResults.map(acc => acc.value)
     return utils.set(accumulator, 'value', value)
diff --git a/packages/data-point/lib/entity-types/entity-collection/factory.js b/packages/data-point/lib/entity-types/entity-collection/factory.js
index 3a3d4c0..9caf9f3 100644
--- a/packages/data-point/lib/entity-types/entity-collection/factory.js
+++ b/packages/data-point/lib/entity-types/entity-collection/factory.js
@@ -1,19 +1,13 @@
+const { resolve } = require('./resolve')
 const parseCompose = require('../parse-compose')
 const createReducer = require('../../reducer-types').create
-const createBaseEntity = require('../base-entity').create
+const BaseEntity = require('../base-entity')
 const reducerHelpers = require('../../reducer-types/reducer-helpers')
 const { validateModifiers } = require('../validate-modifiers')
 const {
   getTypeCheckSourceWithDefault
 } = require('../../helpers/type-check-helpers')
 
-/**
- * @class
- */
-function EntityCollection () {}
-
-module.exports.EntityCollection = EntityCollection
-
 const modifierKeys = ['filter', 'map', 'find']
 
 const modifiers = {
@@ -39,9 +33,9 @@ function createCompose (composeSpec) {
  * Creates new Entity Object
  * @param {Object} spec - spec
  * @param {string} id - Entity id
- * @return {EntityCollection} Entity Object
+ * @return {Object} Entity Object
  */
-function create (spec, id) {
+function create (id, spec) {
   validateModifiers(id, spec, modifierKeys.concat('compose'))
 
   const outputType = getTypeCheckSourceWithDefault(
@@ -49,15 +43,17 @@ function create (spec, id) {
     'array',
     spec.outputType
   )
-  spec = Object.assign({}, spec, { outputType })
 
-  const entity = createBaseEntity(EntityCollection, spec, id)
+  const entity = {}
+  entity.spec = spec
+  entity.outputType = outputType
+
   const compose = parseCompose.parse(id, modifierKeys, spec)
+
   if (compose.length) {
     entity.compose = createCompose(compose)
   }
-
-  return Object.freeze(entity)
+  return entity
 }
 
-module.exports.create = create
+module.exports.create = BaseEntity.create('collection', create, resolve)
diff --git a/packages/data-point/lib/entity-types/entity-collection/index.js b/packages/data-point/lib/entity-types/entity-collection/index.js
index c1ae7c8..448aec7 100644
--- a/packages/data-point/lib/entity-types/entity-collection/index.js
+++ b/packages/data-point/lib/entity-types/entity-collection/index.js
@@ -1,9 +1,1 @@
-/* eslint global-require: 0 */
-
-const factory = require('./factory')
-const resolve = require('./resolve').resolve
-
-module.exports = {
-  create: factory.create,
-  resolve: resolve
-}
+module.exports = require('./factory').create
diff --git a/packages/data-point/lib/entity-types/entity-control/factory.js b/packages/data-point/lib/entity-types/entity-control/factory.js
index c34eb55..54ef979 100644
--- a/packages/data-point/lib/entity-types/entity-control/factory.js
+++ b/packages/data-point/lib/entity-types/entity-control/factory.js
@@ -1,18 +1,9 @@
 const _ = require('lodash')
-
+const { resolve } = require('./resolve')
 const createReducer = require('../../reducer-types').create
-const createBaseEntity = require('../base-entity').create
+const BaseEntity = require('../base-entity')
 const { validateModifiers } = require('../validate-modifiers')
 
-/**
- * @class
- */
-function EntityControl () {
-  this.select = undefined
-}
-
-module.exports.EntityControl = EntityControl
-
 /**
  * map each key from spec into a reducer
  *
@@ -69,13 +60,14 @@ module.exports.parseSwitch = parseSwitch
  * Creates new Entity Object
  * @param  {Object} spec - spec
  * @param {string} id - Entity id
- * @return {EntityControl} Entity Object
+ * @return {Object} Entity Object
  */
-function create (spec, id) {
+function create (id, spec) {
   validateModifiers(id, spec, ['select'])
-  const entity = createBaseEntity(EntityControl, spec, id)
+  const entity = {}
+  entity.spec = spec
   entity.select = parseSwitch(spec)
-  return Object.freeze(entity)
+  return entity
 }
 
-module.exports.create = create
+module.exports.create = BaseEntity.create('control', create, resolve)
diff --git a/packages/data-point/lib/entity-types/entity-control/index.js b/packages/data-point/lib/entity-types/entity-control/index.js
index c1ae7c8..448aec7 100644
--- a/packages/data-point/lib/entity-types/entity-control/index.js
+++ b/packages/data-point/lib/entity-types/entity-control/index.js
@@ -1,9 +1,1 @@
-/* eslint global-require: 0 */
-
-const factory = require('./factory')
-const resolve = require('./resolve').resolve
-
-module.exports = {
-  create: factory.create,
-  resolve: resolve
-}
+module.exports = require('./factory').create
diff --git a/packages/data-point/lib/entity-types/entity-entry/factory.js b/packages/data-point/lib/entity-types/entity-entry/factory.js
index a50a106..3a88977 100644
--- a/packages/data-point/lib/entity-types/entity-entry/factory.js
+++ b/packages/data-point/lib/entity-types/entity-entry/factory.js
@@ -1,23 +1,18 @@
-const createBaseEntity = require('../base-entity').create
+const { resolve } = require('./resolve')
+const BaseEntity = require('../base-entity')
 const { validateModifiers } = require('../validate-modifiers')
 
-/**
- * @class
- */
-function EntityEntry () {}
-
-module.exports.EntityEntry = EntityEntry
-
 /**
  * Creates new Entity Object
  * @param  {Object} spec - spec
  * @param {string} id - Entity id
- * @return {EntityEntry} Entity Object
+ * @return {Object} Entity Object
  */
-function create (spec, id) {
+function create (id, spec) {
   validateModifiers(id, spec, [])
-  const entity = createBaseEntity(EntityEntry, spec, id)
-  return Object.freeze(entity)
+  const entity = {}
+  entity.spec = spec
+  return entity
 }
 
-module.exports.create = create
+module.exports.create = BaseEntity.create('entry', create, resolve)
diff --git a/packages/data-point/lib/entity-types/entity-entry/index.js b/packages/data-point/lib/entity-types/entity-entry/index.js
index c1ae7c8..448aec7 100644
--- a/packages/data-point/lib/entity-types/entity-entry/index.js
+++ b/packages/data-point/lib/entity-types/entity-entry/index.js
@@ -1,9 +1,1 @@
-/* eslint global-require: 0 */
-
-const factory = require('./factory')
-const resolve = require('./resolve').resolve
-
-module.exports = {
-  create: factory.create,
-  resolve: resolve
-}
+module.exports = require('./factory').create
diff --git a/packages/data-point/lib/entity-types/entity-hash/factory.js b/packages/data-point/lib/entity-types/entity-hash/factory.js
index 60ea752..1713adf 100644
--- a/packages/data-point/lib/entity-types/entity-hash/factory.js
+++ b/packages/data-point/lib/entity-types/entity-hash/factory.js
@@ -1,22 +1,16 @@
+const { resolve } = require('./resolve')
 const createReducer = require('../../reducer-types').create
 const deepFreeze = require('deep-freeze')
 const constant = require('lodash/constant')
 const defaultTo = require('lodash/defaultTo')
 const reducerHelpers = require('../../reducer-types/reducer-helpers')
 const parseCompose = require('../parse-compose')
-const createBaseEntity = require('../base-entity').create
+const BaseEntity = require('../base-entity')
 const { validateModifiers } = require('../validate-modifiers')
 const {
   getTypeCheckSourceWithDefault
 } = require('../../helpers/type-check-helpers')
 
-/**
- * @class
- */
-function EntityHash () {}
-
-module.exports.EntityHash = EntityHash
-
 const modifierKeys = ['omitKeys', 'pickKeys', 'mapKeys', 'addValues', 'addKeys']
 
 const modifiers = {
@@ -62,9 +56,9 @@ function createCompose (composeSpec) {
  * Creates new Entity Object
  * @param  {Object} spec - spec
  * @param {string} id - Entity id
- * @return {EntityHash} Entity Object
+ * @return {Object} Entity Object
  */
-function create (spec, id) {
+function create (id, spec) {
   validateModifiers(id, spec, modifierKeys.concat('compose'))
 
   const outputType = getTypeCheckSourceWithDefault(
@@ -72,15 +66,16 @@ function create (spec, id) {
     'object',
     spec.outputType
   )
-  spec = Object.assign({}, spec, { outputType })
 
-  const entity = createBaseEntity(EntityHash, spec, id)
+  const entity = {}
+  entity.spec = spec
+  entity.outputType = outputType
   const compose = parseCompose.parse(id, modifierKeys, spec)
   if (compose.length) {
     entity.compose = createCompose(compose)
   }
 
-  return Object.freeze(entity)
+  return entity
 }
 
-module.exports.create = create
+module.exports.create = BaseEntity.create('hash', create, resolve)
diff --git a/packages/data-point/lib/entity-types/entity-hash/index.js b/packages/data-point/lib/entity-types/entity-hash/index.js
index c1ae7c8..448aec7 100644
--- a/packages/data-point/lib/entity-types/entity-hash/index.js
+++ b/packages/data-point/lib/entity-types/entity-hash/index.js
@@ -1,9 +1,1 @@
-/* eslint global-require: 0 */
-
-const factory = require('./factory')
-const resolve = require('./resolve').resolve
-
-module.exports = {
-  create: factory.create,
-  resolve: resolve
-}
+module.exports = require('./factory').create
diff --git a/packages/data-point/lib/entity-types/entity-model/factory.js b/packages/data-point/lib/entity-types/entity-model/factory.js
index 0ab3421..4ab7ed6 100644
--- a/packages/data-point/lib/entity-types/entity-model/factory.js
+++ b/packages/data-point/lib/entity-types/entity-model/factory.js
@@ -1,21 +1,16 @@
-const createBaseEntity = require('../base-entity').create
-
-/**
- * @class
- */
-function EntityModel () {}
-
-module.exports.EntityModel = EntityModel
+const BaseEntity = require('../base-entity')
+const { resolve } = require('./resolve')
 
 /**
  * Creates new Entity Object
  * @param  {Object} spec - spec
  * @param {string} id - Entity id
- * @return {EntityModel} Entity Object
+ * @return {Object} Entity Object
  */
-function create (spec, id) {
-  const entity = createBaseEntity(EntityModel, spec, id)
-  return Object.freeze(entity)
+function create (id, spec) {
+  const entity = {}
+  entity.spec = spec
+  return entity
 }
 
-module.exports.create = create
+module.exports.create = BaseEntity.create('model', create, resolve)
diff --git a/packages/data-point/lib/entity-types/entity-model/index.js b/packages/data-point/lib/entity-types/entity-model/index.js
index c1ae7c8..448aec7 100644
--- a/packages/data-point/lib/entity-types/entity-model/index.js
+++ b/packages/data-point/lib/entity-types/entity-model/index.js
@@ -1,9 +1,1 @@
-/* eslint global-require: 0 */
-
-const factory = require('./factory')
-const resolve = require('./resolve').resolve
-
-module.exports = {
-  create: factory.create,
-  resolve: resolve
-}
+module.exports = require('./factory').create
diff --git a/packages/data-point/lib/entity-types/entity-request/factory.js b/packages/data-point/lib/entity-types/entity-request/factory.js
index 1558f3e..d9dfbfc 100644
--- a/packages/data-point/lib/entity-types/entity-request/factory.js
+++ b/packages/data-point/lib/entity-types/entity-request/factory.js
@@ -1,20 +1,9 @@
 const _ = require('lodash')
-const createBaseEntity = require('../base-entity').create
+const { resolve } = require('./resolve')
+const BaseEntity = require('../base-entity')
 const createReducer = require('../../reducer-types').create
 const { validateModifiers } = require('../validate-modifiers')
 
-/**
- * @class
- * @property {string} url
- * @property {reducer} options
- */
-function EntityRequest () {
-  this.url = undefined
-  this.options = undefined
-}
-
-module.exports.EntityRequest = EntityRequest
-
 /**
  * @return {Object}
  */
@@ -24,19 +13,23 @@ function defaultOptions () {
 
 module.exports.defaultOptions = defaultOptions
 
+/**
+ * @typedef {Array|String|Function} Reducer
+ */
+
 /**
  * creates new Request based on spec
- * @param {Object} spec - request spec
+ * @param {{url:String, options:Object, before:Reducer}} spec - request spec
  * @param {string} id - Entity id
- * @return {EntityRequest} Entity Object
+ * @return {Object} Entity Object
  */
-function create (spec, id) {
+function create (id, spec) {
   validateModifiers(id, spec, ['options', 'url'])
-  const entity = createBaseEntity(EntityRequest, spec, id)
+  const entity = {}
+  entity.spec = spec
   entity.url = _.defaultTo(spec.url, '')
   entity.options = createReducer(spec.options || defaultOptions)
-
-  return Object.freeze(entity)
+  return entity
 }
 
-module.exports.create = create
+module.exports.create = BaseEntity.create('request', create, resolve)
diff --git a/packages/data-point/lib/entity-types/entity-request/index.js b/packages/data-point/lib/entity-types/entity-request/index.js
index c1ae7c8..448aec7 100644
--- a/packages/data-point/lib/entity-types/entity-request/index.js
+++ b/packages/data-point/lib/entity-types/entity-request/index.js
@@ -1,9 +1,1 @@
-/* eslint global-require: 0 */
-
-const factory = require('./factory')
-const resolve = require('./resolve').resolve
-
-module.exports = {
-  create: factory.create,
-  resolve: resolve
-}
+module.exports = require('./factory').create
diff --git a/packages/data-point/lib/entity-types/entity-schema/factory.js b/packages/data-point/lib/entity-types/entity-schema/factory.js
index 8c8a350..d1c0a8a 100644
--- a/packages/data-point/lib/entity-types/entity-schema/factory.js
+++ b/packages/data-point/lib/entity-types/entity-schema/factory.js
@@ -1,20 +1,10 @@
 const Ajv = require('ajv')
 const _ = require('lodash')
 const deepFreeze = require('deep-freeze')
-
-const createBaseEntity = require('../base-entity').create
+const { resolve } = require('./resolve')
+const BaseEntity = require('../base-entity')
 const { validateModifiers } = require('../validate-modifiers')
 
-/**
- * @class
- */
-function EntitySchema () {
-  this.schema = undefined
-  this.options = {}
-}
-
-module.exports.EntitySchema = EntitySchema
-
 /**
  * @param {Object} schema
  * @param {Object} options
@@ -43,16 +33,18 @@ module.exports.validateSchema = validateSchema
  * @param {Object} spec - spec
  * @param {string} id - Entity id
  * @throws if spec.schema is not a valid ajv schema
- * @return {EntitySchema} Entity Object
+ * @return {Object} Entity Object
  */
-function create (spec, id) {
+function create (id, spec) {
   validateModifiers(id, spec, ['schema', 'options'])
-  const entity = createBaseEntity(EntitySchema, spec, id)
+
+  const entity = {}
+  entity.spec = spec
   entity.schema = deepFreeze(_.defaultTo(spec.schema, {}))
   entity.options = deepFreeze(_.defaultTo(spec.options, {}))
-  validateSchema(entity.schema, entity.options)
 
-  return Object.freeze(entity)
+  validateSchema(entity.schema, entity.options)
+  return entity
 }
 
-module.exports.create = create
+module.exports.create = BaseEntity.create('schema', create, resolve)
diff --git a/packages/data-point/lib/entity-types/entity-schema/index.js b/packages/data-point/lib/entity-types/entity-schema/index.js
index c1ae7c8..448aec7 100644
--- a/packages/data-point/lib/entity-types/entity-schema/index.js
+++ b/packages/data-point/lib/entity-types/entity-schema/index.js
@@ -1,9 +1,1 @@
-/* eslint global-require: 0 */
-
-const factory = require('./factory')
-const resolve = require('./resolve').resolve
-
-module.exports = {
-  create: factory.create,
-  resolve: resolve
-}
+module.exports = require('./factory').create
diff --git a/packages/data-point/lib/entity-types/entity-transform/factory.js b/packages/data-point/lib/entity-types/entity-transform/factory.js
index c1bd8df..2a38377 100644
--- a/packages/data-point/lib/entity-types/entity-transform/factory.js
+++ b/packages/data-point/lib/entity-types/entity-transform/factory.js
@@ -1,27 +1,16 @@
-const createBaseEntity = require('../base-entity').create
-
-/**
- * @class
- */
-function EntityTransform () {}
-
-module.exports.EntityTransform = EntityTransform
+const BaseEntity = require('../base-entity')
+const { resolve } = require('./resolve')
 
 /**
  * Creates new Entity Object
  * @param  {*} spec - spec
  * @param {string} id - Entity id
- * @return {EntityTransform} Entity Object
+ * @return {Object} Entity Object
  */
-function create (spec, id) {
-  const entity = createBaseEntity(
-    EntityTransform,
-    {
-      value: spec
-    },
-    id
-  )
-  return Object.freeze(entity)
+function create (id, spec) {
+  const entity = {}
+  entity.value = spec
+  return entity
 }
 
-module.exports.create = create
+module.exports.create = BaseEntity.create('reducer', create, resolve)
diff --git a/packages/data-point/lib/entity-types/entity-transform/index.js b/packages/data-point/lib/entity-types/entity-transform/index.js
index c1ae7c8..448aec7 100644
--- a/packages/data-point/lib/entity-types/entity-transform/index.js
+++ b/packages/data-point/lib/entity-types/entity-transform/index.js
@@ -1,9 +1,1 @@
-/* eslint global-require: 0 */
-
-const factory = require('./factory')
-const resolve = require('./resolve').resolve
-
-module.exports = {
-  create: factory.create,
-  resolve: resolve
-}
+module.exports = require('./factory').create
diff --git a/packages/data-point/lib/entity-types/spec/factory.js b/packages/data-point/lib/entity-types/spec/factory.js
index 96b5fcf..452eb8d 100644
--- a/packages/data-point/lib/entity-types/spec/factory.js
+++ b/packages/data-point/lib/entity-types/spec/factory.js
@@ -1,5 +1,4 @@
 const _ = require('lodash')
-const utils = require('../../utils')
 
 /**
  * parse reducer
@@ -7,32 +6,23 @@ const utils = require('../../utils')
  * @return {reducer}
  */
 function create (entitySpec, id) {
-  if (!_.isFunction(entitySpec.create)) {
+  if (!_.isFunction(entitySpec)) {
     throw new Error(
-      `Entity Module '${id}' should expose a 'create' method, instead got: ${Object.keys(
+      `Entity Factory '${id}' should be a function: ${JSON.stringify(
         entitySpec
       )}`
     )
   }
 
-  if (!_.isFunction(entitySpec.resolve)) {
+  if (entitySpec.length !== 2) {
     throw new Error(
-      `Entity Module '${id}' should expose a 'resolve' method, instead got: ${Object.keys(
-        entitySpec
-      )}`
-    )
-  }
-
-  if (entitySpec.resolve.length !== 2) {
-    throw new Error(
-      `Entity Module '${id}' 'resolve' method should have an arity of 2, instead got: ${
-        entitySpec.resolve.length
+      `Entity Factory '${id}' method should have an arity of 2, instead got: ${
+        entitySpec.length
       }`
     )
   }
 
-  const entity = utils.set(entitySpec, 'id', id)
-  return Object.freeze(entity)
+  return entitySpec
 }
 
 module.exports.create = create
diff --git a/packages/data-point/lib/index.js b/packages/data-point/lib/index.js
index f648827..e0bc870 100644
--- a/packages/data-point/lib/index.js
+++ b/packages/data-point/lib/index.js
@@ -2,9 +2,11 @@
 
 const core = require('./core')
 const helpers = require('./helpers')
+const entities = require('./entity-types').definitions
 const { createTypeCheckReducer } = require('./helpers/type-check-functions')
 
 module.exports = {
+  entities,
   create: core.create,
   helpers: helpers.helpers,
   createEntity: helpers.createEntity,
diff --git a/packages/data-point/lib/reducer-types/factory.js b/packages/data-point/lib/reducer-types/factory.js
index 9fd2a65..05c49e1 100644
--- a/packages/data-point/lib/reducer-types/factory.js
+++ b/packages/data-point/lib/reducer-types/factory.js
@@ -4,6 +4,7 @@ const util = require('util')
 const { IS_REDUCER, DEFAULT_VALUE } = require('./reducer-symbols')
 
 const ReducerEntity = require('./reducer-entity')
+const ReducerEntityId = require('./reducer-entity-id')
 const ReducerFunction = require('./reducer-function')
 const ReducerHelpers = require('./reducer-helpers')
 const ReducerList = require('./reducer-list')
@@ -12,6 +13,7 @@ const ReducerPath = require('./reducer-path')
 
 const reducerTypes = [
   ReducerEntity,
+  ReducerEntityId,
   ReducerFunction,
   ReducerHelpers,
   ReducerList,
diff --git a/packages/data-point/lib/reducer-types/reducer-entity-id/factory.js b/packages/data-point/lib/reducer-types/reducer-entity-id/factory.js
new file mode 100644
index 0000000..cf02275
--- /dev/null
+++ b/packages/data-point/lib/reducer-types/reducer-entity-id/factory.js
@@ -0,0 +1,59 @@
+const _ = require('lodash')
+
+const REDUCER_ENTITY_ID = 'ReducerEntityId'
+
+module.exports.type = REDUCER_ENTITY_ID
+
+/**
+ * Defines a entity reducer
+ * @class
+ * @property {string} type - @see reducerType
+ * @property {string} name - name of the reducer
+ * @property {string} entityType - type of entity
+ */
+function ReducerEntityId () {
+  this.type = REDUCER_ENTITY_ID
+  this.name = ''
+  this.entityType = null
+  this.asCollection = false
+  this.hasEmptyConditional = false
+}
+
+module.exports.ReducerEntityId = ReducerEntityId
+
+/**
+ * @param {*} source
+ * @returns {boolean}
+ */
+function isType (source) {
+  return (
+    _.isString(source) &&
+    source.match(/^([^$][\w.]*):([\w.-]+)(\[])?$/) !== null
+  )
+}
+
+module.exports.isType = isType
+
+/**
+ * @param {Function} createReducer
+ * @param {string} source
+ * @return {reducer}
+ */
+function create (createReducer, source) {
+  const reducer = new ReducerEntityId()
+  const tokens = source.split(':')
+
+  let entityType = tokens[0]
+  reducer.hasEmptyConditional = entityType.indexOf('?') === 0
+  reducer.entityType = entityType.replace(/^\?/, '')
+
+  let name = tokens[1]
+  reducer.asCollection = name.slice(-2) === '[]'
+  reducer.name = name.replace(/\[]$/, '')
+
+  reducer.id = `${reducer.entityType}:${reducer.name}`
+
+  return reducer
+}
+
+module.exports.create = create
diff --git a/packages/data-point/lib/reducer-types/reducer-entity-id/index.js b/packages/data-point/lib/reducer-types/reducer-entity-id/index.js
new file mode 100644
index 0000000..e4b95bc
--- /dev/null
+++ b/packages/data-point/lib/reducer-types/reducer-entity-id/index.js
@@ -0,0 +1,11 @@
+/* eslint global-require: 0 */
+
+const reducer = require('./factory')
+const resolve = require('./resolve').resolve
+
+module.exports = {
+  create: reducer.create,
+  type: reducer.type,
+  isType: reducer.isType,
+  resolve: resolve
+}
diff --git a/packages/data-point/lib/reducer-types/reducer-entity-id/resolve.js b/packages/data-point/lib/reducer-types/reducer-entity-id/resolve.js
new file mode 100644
index 0000000..cd7dbd4
--- /dev/null
+++ b/packages/data-point/lib/reducer-types/reducer-entity-id/resolve.js
@@ -0,0 +1,23 @@
+const BaseEntity = require('../../entity-types/base-entity/resolve')
+
+/**
+ * Resolve an Entity Reducer, actual entity resolution is delegated
+ * to each Entity.resolve method
+ * @param {Object} manager
+ * @param {function} resolveReducer
+ * @param {Accumulator} accumulator
+ * @param {ReducerEntityId} reducer
+ * @returns {Promise<Accumulator>}
+ */
+function resolve (manager, resolveReducer, accumulator, reducer) {
+  const entity = manager.entities.get(reducer.id)
+  return BaseEntity.resolve(
+    manager,
+    resolveReducer,
+    accumulator,
+    reducer,
+    entity
+  )
+}
+
+module.exports.resolve = resolve
diff --git a/packages/data-point/lib/reducer-types/reducer-entity/factory.js b/packages/data-point/lib/reducer-types/reducer-entity/factory.js
index 1a0bca6..fdcbee0 100644
--- a/packages/data-point/lib/reducer-types/reducer-entity/factory.js
+++ b/packages/data-point/lib/reducer-types/reducer-entity/factory.js
@@ -1,5 +1,3 @@
-const _ = require('lodash')
-
 const REDUCER_ENTITY = 'ReducerEntity'
 
 module.exports.type = REDUCER_ENTITY
@@ -26,32 +24,29 @@ module.exports.ReducerEntity = ReducerEntity
  * @returns {boolean}
  */
 function isType (source) {
-  return (
-    _.isString(source) &&
-    source.match(/^([^$][\w.]*):([\w.-]+)(\[])?$/) !== null
-  )
+  return source && source.isEntityInstance === true
 }
 
 module.exports.isType = isType
 
 /**
  * @param {Function} createReducer
- * @param {string} source
+ * @param {string} entity
  * @return {reducer}
  */
-function create (createReducer, source) {
+function create (createReducer, entity) {
   const reducer = new ReducerEntity()
-  const tokens = source.split(':')
 
-  let entityType = tokens[0]
-  reducer.hasEmptyConditional = entityType.indexOf('?') === 0
-  reducer.entityType = entityType.replace(/^\?/, '')
+  reducer.hasEmptyConditional = false
 
-  let name = tokens[1]
-  reducer.asCollection = name.slice(-2) === '[]'
-  reducer.name = name.replace(/\[]$/, '')
+  reducer.asCollection = false
 
-  reducer.id = `${reducer.entityType}:${reducer.name}`
+  reducer.id = entity.id
+  reducer.name = entity.name
+  reducer.entityType = entity.entityType
+  reducer.entity = entity
+  // for backwards compatibity with accumulator API
+  reducer.spec = entity
 
   return reducer
 }
diff --git a/packages/data-point/lib/reducer-types/reducer-entity/resolve.js b/packages/data-point/lib/reducer-types/reducer-entity/resolve.js
index 55f5976..14c0369 100644
--- a/packages/data-point/lib/reducer-types/reducer-entity/resolve.js
+++ b/packages/data-point/lib/reducer-types/reducer-entity/resolve.js
@@ -6,18 +6,16 @@ const BaseEntity = require('../../entity-types/base-entity/resolve')
  * @param {Object} manager
  * @param {function} resolveReducer
  * @param {Accumulator} accumulator
- * @param {ReducerEntity} reducer
+ * @param {ReducerEntityId} reducer
  * @returns {Promise<Accumulator>}
  */
 function resolve (manager, resolveReducer, accumulator, reducer) {
-  const reducerEntityType = reducer.entityType
-  const EntityType = manager.entityTypes.get(reducerEntityType)
   return BaseEntity.resolve(
     manager,
     resolveReducer,
     accumulator,
     reducer,
-    EntityType.resolve
+    reducer.entity
   )
 }
 
diff --git a/packages/data-point/lib/reducer-types/resolve.js b/packages/data-point/lib/reducer-types/resolve.js
index 777b0a9..fc25912 100644
--- a/packages/data-point/lib/reducer-types/resolve.js
+++ b/packages/data-point/lib/reducer-types/resolve.js
@@ -1,6 +1,7 @@
 const Promise = require('bluebird')
 
 const ReducerEntity = require('./reducer-entity')
+const ReducerEntityId = require('./reducer-entity-id')
 const ReducerFunction = require('./reducer-function')
 const ReducerList = require('./reducer-list')
 const ReducerObject = require('./reducer-object')
@@ -10,6 +11,7 @@ const { DEFAULT_VALUE } = require('./reducer-symbols')
 
 const reducers = Object.assign({}, ReducerHelpers, {
   [ReducerEntity.type]: ReducerEntity,
+  [ReducerEntityId.type]: ReducerEntityId,
   [ReducerFunction.type]: ReducerFunction,
   [ReducerList.type]: ReducerList,
   [ReducerObject.type]: ReducerObject,
diff --git a/packages/data-point/lib/stores/entities.js b/packages/data-point/lib/stores/entities.js
index 8e22875..57b4f9b 100644
--- a/packages/data-point/lib/stores/entities.js
+++ b/packages/data-point/lib/stores/entities.js
@@ -6,10 +6,9 @@ const storeManager = require('./store-manager')
  * @return {reducer}
  */
 function createEntity (entityTypes, source, id) {
-  const tokens = id.split(':')
-  const entityType = tokens[0]
-  const EntityType = entityTypes.get(entityType)
-  const entity = EntityType.create(source, id)
+  const [entityType, entityName] = id.split(':')
+  const entityFactory = entityTypes.get(entityType)
+  const entity = entityFactory(entityName, source)
   return entity
 }
 


Test patch:
diff --git a/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-double-quote.input.js b/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-double-quote.input.js
index 125d409..c4661eb 100644
--- a/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-double-quote.input.js
+++ b/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-double-quote.input.js
@@ -3,13 +3,13 @@
 
 // prettier-ignore
 const entities = {
-  'transform:a': `$.`,
-  'transform:b': `$. | foo | $.`,
-  'transform:c': `foo | bar | baz`,
-  'transform:d': "$.",
-  'transform:e': "$. | foo",
-  'transform:f': "$. | $. | $.",
-  'transform:g': "foo | bar | baz",
+  'reducer:a': `$.`,
+  'reducer:b': `$. | foo | $.`,
+  'reducer:c': `foo | bar | baz`,
+  'reducer:d': "$.",
+  'reducer:e': "$. | foo",
+  'reducer:f': "$. | $. | $.",
+  'reducer:g': "foo | bar | baz",
   nested: {
     object: {
       a: "$. | $."
diff --git a/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-double-quote.output.js b/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-double-quote.output.js
index 12624ba..6651c19 100644
--- a/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-double-quote.output.js
+++ b/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-double-quote.output.js
@@ -3,13 +3,13 @@
 
 // prettier-ignore
 const entities = {
-  'transform:a': `$`,
-  'transform:b': `$ | foo | $`,
-  'transform:c': `foo | bar | baz`,
-  'transform:d': "$",
-  'transform:e': "$ | foo",
-  'transform:f': "$ | $ | $",
-  'transform:g': "foo | bar | baz",
+  'reducer:a': `$`,
+  'reducer:b': `$ | foo | $`,
+  'reducer:c': `foo | bar | baz`,
+  'reducer:d': "$",
+  'reducer:e': "$ | foo",
+  'reducer:f': "$ | $ | $",
+  'reducer:g': "foo | bar | baz",
   nested: {
     object: {
       a: "$ | $"
diff --git a/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-single-quote.input.js b/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-single-quote.input.js
index bbe8274..f62ccdf 100644
--- a/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-single-quote.input.js
+++ b/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-single-quote.input.js
@@ -3,13 +3,13 @@
 
 // prettier-ignore
 const entities = {
-  'transform:a': `$.`,
-  'transform:b': `$. | foo | $.`,
-  'transform:c': `foo | bar | baz`,
-  'transform:d': '$.',
-  'transform:e': '$. | foo',
-  'transform:f': '$. | $. | $.',
-  'transform:g': 'foo | bar | baz',
+  'reducer:a': `$.`,
+  'reducer:b': `$. | foo | $.`,
+  'reducer:c': `foo | bar | baz`,
+  'reducer:d': '$.',
+  'reducer:e': '$. | foo',
+  'reducer:f': '$. | $. | $.',
+  'reducer:g': 'foo | bar | baz',
   nested: {
     object: {
       a: '$. | $.'
diff --git a/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-single-quote.output.js b/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-single-quote.output.js
index d56ce5a..a932265 100644
--- a/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-single-quote.output.js
+++ b/packages/data-point-codemods/transforms/__testfixtures__/change-path-reducer-accessing-root-path-single-quote.output.js
@@ -3,13 +3,13 @@
 
 // prettier-ignore
 const entities = {
-  'transform:a': `$`,
-  'transform:b': `$ | foo | $`,
-  'transform:c': `foo | bar | baz`,
-  'transform:d': '$',
-  'transform:e': '$ | foo',
-  'transform:f': '$ | $ | $',
-  'transform:g': 'foo | bar | baz',
+  'reducer:a': `$`,
+  'reducer:b': `$ | foo | $`,
+  'reducer:c': `foo | bar | baz`,
+  'reducer:d': '$',
+  'reducer:e': '$ | foo',
+  'reducer:f': '$ | $ | $',
+  'reducer:g': 'foo | bar | baz',
   nested: {
     object: {
       a: '$ | $'
diff --git a/packages/data-point-express/lib/factory.test.js b/packages/data-point-express/lib/factory.test.js
index 8b6dbd9..5324318 100644
--- a/packages/data-point-express/lib/factory.test.js
+++ b/packages/data-point-express/lib/factory.test.js
@@ -15,7 +15,7 @@ describe('create - all middleware', () => {
     console.warn = () => {}
     const options = {
       entities: {
-        'transform:hello': (value, acc) => ({
+        'reducer:hello': (value, acc) => ({
           message: `Hello ${acc.locals.params.name}`
         })
       }
@@ -44,7 +44,7 @@ describe('create - all middleware', () => {
 
   test('create middleware', done => {
     const app = new Express()
-    app.get('/hello/:name', service.mapTo('transform:hello'))
+    app.get('/hello/:name', service.mapTo('reducer:hello'))
     request(app)
       .get('/hello/darek')
       .expect('Content-Type', /json/)
@@ -64,7 +64,7 @@ describe('create - all middleware', () => {
       service.router({
         helloWorld: {
           path: '/hello/:name',
-          middleware: 'transform:hello'
+          middleware: 'reducer:hello'
         }
       })
     )
diff --git a/packages/data-point-express/lib/inspector-middleware.test.js b/packages/data-point-express/lib/inspector-middleware.test.js
index 4f78b22..d5d7967 100644
--- a/packages/data-point-express/lib/inspector-middleware.test.js
+++ b/packages/data-point-express/lib/inspector-middleware.test.js
@@ -16,13 +16,13 @@ describe('create - inspect middleware', () => {
     console.warn = () => {}
     dataPoint = DataPoint.create({
       entities: {
-        'transform:test-params': (value, acc) => ({
+        'reducer:test-params': (value, acc) => ({
           message: `Hello ${acc.locals.params.name}`
         }),
-        'transform:test-query': (value, acc) => ({
+        'reducer:test-query': (value, acc) => ({
           message: `Hello ${acc.locals.query.name}`
         }),
-        'transform:test-value': (value, acc) => ({
+        'reducer:test-value': (value, acc) => ({
           message: `Hello ${value}`
         })
       }
@@ -48,7 +48,7 @@ describe('create - inspect middleware', () => {
 
   test('it should pass query value', done => {
     const body = {
-      entityId: 'transform:test-query',
+      entityId: 'reducer:test-query',
       query: {
         name: 'Foo'
       }
@@ -70,7 +70,7 @@ describe('create - inspect middleware', () => {
 
   test('it should pass params value', done => {
     const body = {
-      entityId: 'transform:test-params',
+      entityId: 'reducer:test-params',
       params: {
         name: 'Foo'
       }
@@ -92,7 +92,7 @@ describe('create - inspect middleware', () => {
 
   test('it should pass value to transform', done => {
     const body = {
-      entityId: 'transform:test-value',
+      entityId: 'reducer:test-value',
       value: 'Foo'
     }
     const app = new Express()
@@ -118,9 +118,9 @@ describe('create - inspect middleware', () => {
       .expect('Content-Type', /json/)
       .expect(response => {
         expect(response.body).toEqual([
-          'transform:test-params',
-          'transform:test-query',
-          'transform:test-value'
+          'reducer:test-params',
+          'reducer:test-query',
+          'reducer:test-value'
         ])
       })
       .expect(200)
diff --git a/packages/data-point-express/lib/middleware.test.js b/packages/data-point-express/lib/middleware.test.js
index c91a906..c55e9e5 100644
--- a/packages/data-point-express/lib/middleware.test.js
+++ b/packages/data-point-express/lib/middleware.test.js
@@ -172,11 +172,11 @@ describe('resolveReducer', () => {
   beforeAll(() => {
     dataPoint = DataPoint.create({
       entities: {
-        'transform:string': () => `Test`,
-        'transform:object': () => ({
+        'reducer:string': () => `Test`,
+        'reducer:object': () => ({
           test: `Test`
         }),
-        'transform:value': value => `Test ${value}`
+        'reducer:value': value => `Test ${value}`
       }
     })
   })
@@ -184,7 +184,7 @@ describe('resolveReducer', () => {
   test('it should resolve text response', done => {
     const app = new Express()
     app.get('/test', (req, res) => {
-      return Middleware.resolveReducer(dataPoint, 'transform:string', {}, res)
+      return Middleware.resolveReducer(dataPoint, 'reducer:string', {}, res)
     })
     request(app)
       .get('/test')
@@ -199,7 +199,7 @@ describe('resolveReducer', () => {
   test('it should resolve object response', done => {
     const app = new Express()
     app.get('/test', (req, res) => {
-      return Middleware.resolveReducer(dataPoint, 'transform:object', {}, res)
+      return Middleware.resolveReducer(dataPoint, 'reducer:object', {}, res)
     })
     request(app)
       .get('/test')
@@ -218,7 +218,7 @@ describe('resolveReducer', () => {
     app.get('/test', (req, res) => {
       return Middleware.resolveReducer(
         dataPoint,
-        'transform:value',
+        'reducer:value',
         {},
         res,
         'TEST'
diff --git a/packages/data-point-express/lib/route-middleware.test.js b/packages/data-point-express/lib/route-middleware.test.js
index 80f1de9..ef1e0cd 100644
--- a/packages/data-point-express/lib/route-middleware.test.js
+++ b/packages/data-point-express/lib/route-middleware.test.js
@@ -14,10 +14,10 @@ describe('create - entity middleware', () => {
   beforeAll(() => {
     dataPoint = DataPoint.create({
       entities: {
-        'transform:my-test-query': (value, acc) => ({
+        'reducer:my-test-query': (value, acc) => ({
           message: `Hello ${acc.locals.query.name}`
         }),
-        'transform:my-test-params': (value, acc) => ({
+        'reducer:my-test-params': (value, acc) => ({
           message: `Hello ${acc.locals.params.name}`
         })
       }
@@ -28,7 +28,7 @@ describe('create - entity middleware', () => {
     const app = new Express()
     app.use(
       '/api/bad-entity',
-      RouteMiddleware.create(dataPoint, 'transform:unknown')
+      RouteMiddleware.create(dataPoint, 'reducer:unknown')
     )
     request(app)
       .get('/api/bad-entity')
@@ -45,7 +45,7 @@ describe('create - entity middleware', () => {
     const app = new Express()
     app.use(
       '/api/my-test-query',
-      RouteMiddleware.create(dataPoint, 'transform:my-test-query')
+      RouteMiddleware.create(dataPoint, 'reducer:my-test-query')
     )
     request(app)
       .get('/api/my-test-query?name=test')
@@ -61,7 +61,7 @@ describe('create - entity middleware', () => {
     const app = new Express()
     app.use(
       '/api/my-test-params/:name',
-      RouteMiddleware.create(dataPoint, 'transform:my-test-params')
+      RouteMiddleware.create(dataPoint, 'reducer:my-test-params')
     )
     request(app)
       .get('/api/my-test-params/test')
diff --git a/packages/data-point-express/lib/router-middleware.test.js b/packages/data-point-express/lib/router-middleware.test.js
index eaf0bbf..a7fb70f 100644
--- a/packages/data-point-express/lib/router-middleware.test.js
+++ b/packages/data-point-express/lib/router-middleware.test.js
@@ -39,7 +39,7 @@ describe('create - datapoint routes', () => {
   beforeAll(() => {
     dataPoint = DataPoint.create({
       entities: {
-        'transform:Test': (value, acc) => ({
+        'reducer:Test': (value, acc) => ({
           message: `Hello ${acc.locals.query.name}`
         })
       }
@@ -53,7 +53,7 @@ describe('create - datapoint routes', () => {
         test: {
           priority: 100,
           path: '/test',
-          middleware: 'transform:Test'
+          middleware: 'reducer:Test'
         }
       })
     )
diff --git a/packages/data-point-service/lib/data-point-factory.test.js b/packages/data-point-service/lib/data-point-factory.test.js
index b246e47..b64ac0f 100644
--- a/packages/data-point-service/lib/data-point-factory.test.js
+++ b/packages/data-point-service/lib/data-point-factory.test.js
@@ -8,7 +8,7 @@ describe('verify', () => {
     const result = DataPointFactory.verify({
       DataPoint,
       entities: {
-        'transform:foo': '$'
+        'reducer:foo': '$'
       }
     })
     expect(result).toEqual(result)
@@ -18,7 +18,7 @@ describe('verify', () => {
     expect(() => {
       DataPointFactory.verify({
         entities: {
-          'transform:foo': '$'
+          'reducer:foo': '$'
         }
       })
     }).toThrowError(/provided/)
@@ -38,7 +38,7 @@ describe('createDataPoint', () => {
     const dp = DataPointFactory.createDataPoint({
       DataPoint,
       entities: {
-        'transform:foo': '$'
+        'reducer:foo': '$'
       }
     })
 
@@ -51,7 +51,7 @@ describe('create', () => {
     return DataPointFactory.create({
       DataPoint,
       entities: {
-        'transform:foo': '$'
+        'reducer:foo': '$'
       }
     }).then(dp => {
       expect(dp).toHaveProperty('transform')
diff --git a/packages/data-point-service/lib/factory.test.js b/packages/data-point-service/lib/factory.test.js
index ded4d7b..39608bf 100644
--- a/packages/data-point-service/lib/factory.test.js
+++ b/packages/data-point-service/lib/factory.test.js
@@ -238,7 +238,7 @@ describe('create', () => {
         isRequired: false
       },
       entities: {
-        'transform:foo': '$'
+        'reducer:foo': '$'
       }
     })
       .then(service => {
@@ -272,7 +272,7 @@ describe('create', () => {
         isRequired: true
       },
       entities: {
-        'transform:foo': '$'
+        'reducer:foo': '$'
       }
     })
       .then(service => {
diff --git a/packages/data-point/lib/__snapshots__/index.test.js.snap b/packages/data-point/lib/__snapshots__/index.test.js.snap
index 0faeae3..3e2d26a 100644
--- a/packages/data-point/lib/__snapshots__/index.test.js.snap
+++ b/packages/data-point/lib/__snapshots__/index.test.js.snap
@@ -7,6 +7,16 @@ Object {
   "createReducer": [Function],
   "createReducerResolver": [Function],
   "createTypeCheckReducer": [Function],
+  "entities": Object {
+    "Collection": [Function],
+    "Control": [Function],
+    "Entry": [Function],
+    "Hash": [Function],
+    "Model": [Function],
+    "Reducer": [Function],
+    "Request": [Function],
+    "Schema": [Function],
+  },
   "entityFactories": Object {
     "Collection": [Function],
     "Control": [Function],
diff --git a/packages/data-point/lib/core/core.test.js b/packages/data-point/lib/core/core.test.js
index 8524405..b2c00e7 100644
--- a/packages/data-point/lib/core/core.test.js
+++ b/packages/data-point/lib/core/core.test.js
@@ -46,9 +46,9 @@ test('entry#transform - fail if id not found', done => {
 })
 
 describe('addEntityType', () => {
-  function createEntityFactory () {
+  function entityFactory (id, spec) {
     return {
-      create (spec) {},
+      id,
       resolve (accumulator, resolveReducer) {}
     }
   }
@@ -56,22 +56,22 @@ describe('addEntityType', () => {
   test('It should add single new entity type', () => {
     const dataPoint = core.create()
 
-    dataPoint.addEntityType('foo', createEntityFactory())
+    dataPoint.addEntityType('foo', entityFactory)
 
     const entityType = dataPoint.entityTypes.store.get('foo')
-    expect(entityType).toHaveProperty('id', 'foo')
+    expect(entityType).toEqual(entityFactory)
   })
 
   test('It should add multiple entity types', () => {
     const dataPoint = core.create()
 
     dataPoint.addEntityTypes({
-      foo: createEntityFactory(),
-      bar: createEntityFactory()
+      foo: entityFactory,
+      bar: entityFactory
     })
 
     const store = dataPoint.entityTypes.store
-    expect(store.get('foo')).toHaveProperty('id', 'foo')
-    expect(store.get('bar')).toHaveProperty('id', 'bar')
+    expect(store.get('foo')).toEqual(entityFactory)
+    expect(store.get('bar')).toEqual(entityFactory)
   })
 })
diff --git a/packages/data-point/lib/entity-types/base-entity/__snapshots__/factory.test.js.snap b/packages/data-point/lib/entity-types/base-entity/__snapshots__/factory.test.js.snap
new file mode 100644
index 0000000..39ff4d9
--- /dev/null
+++ b/packages/data-point/lib/entity-types/base-entity/__snapshots__/factory.test.js.snap
@@ -0,0 +1,46 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`create should create new entity instance 1`] = `
+bar:foo {
+  "entityType": "bar",
+  "id": "bar:foo",
+  "isEntityInstance": true,
+  "name": "foo",
+  "params": Object {},
+  "resolve": [Function],
+}
+`;
+
+exports[`create should create new entity instance with assigned name 1`] = `
+bar:myBar {
+  "entityType": "bar",
+  "id": "bar:myBar",
+  "isEntityInstance": true,
+  "name": "myBar",
+  "params": Object {},
+  "resolve": [Function],
+}
+`;
+
+exports[`create should create new entity instance with generic name 1`] = `
+bar:generic {
+  "entityType": "bar",
+  "id": "bar:generic",
+  "isEntityInstance": true,
+  "name": "generic",
+  "params": Object {},
+  "resolve": [Function],
+}
+`;
+
+exports[`create should throw error if arguments are wrong 1`] = `"Received wrong number of arguments. Try passing create(type:String, factory:Function, resolve:Function)"`;
+
+exports[`create should throw error if type argument is not string 1`] = `"\\"type\\" argument must be a string create(type:String, factory:Function, resolve:Function)"`;
+
+exports[`validateFactory should throw error if function does not match arity 1`] = `"\\"factory\\" function must have an arity of 2, factory(name:String, spec:Object)"`;
+
+exports[`validateFactory should throw error if type is not function 1`] = `"\\"factory\\" argument must be a function, create(type:String, factory:Function, resolve:Function)"`;
+
+exports[`validateResolve should throw error if function does not match arity 1`] = `"\\"resolve\\" function must have an arity of 2, resolve(accumulator:Accumulator, resolveReducer:Function)"`;
+
+exports[`validateResolve should throw error if type is not function 1`] = `"\\"resolve\\" must be a function, create(type:String, factory:Function, resolve:Function)"`;
diff --git a/packages/data-point/lib/entity-types/base-entity/factory.test.js b/packages/data-point/lib/entity-types/base-entity/factory.test.js
index 58c2bce..b8095c5 100644
--- a/packages/data-point/lib/entity-types/base-entity/factory.test.js
+++ b/packages/data-point/lib/entity-types/base-entity/factory.test.js
@@ -2,24 +2,113 @@
 
 const Factory = require('./factory')
 
-describe('Factory.create', () => {
+describe('validateResolve', () => {
+  it('should throw error if type is not function', () => {
+    expect(() => {
+      Factory.validateResolve('string')
+    }).toThrowErrorMatchingSnapshot()
+  })
+  it('should throw error if function does not match arity', () => {
+    expect(() => {
+      Factory.validateResolve(a => {})
+    }).toThrowErrorMatchingSnapshot()
+  })
+  it('should return true if validation has no errors', () => {
+    const resolver = (a, b) => {}
+    expect(Factory.validateResolve(resolver)).toEqual(true)
+  })
+})
+
+describe('validateFactory', () => {
+  it('should throw error if type is not function', () => {
+    expect(() => {
+      Factory.validateFactory('string')
+    }).toThrowErrorMatchingSnapshot()
+  })
+  it('should throw error if function does not match arity', () => {
+    expect(() => {
+      Factory.validateFactory(a => {})
+    }).toThrowErrorMatchingSnapshot()
+  })
+  it('should return true if validation has no errors', () => {
+    const resolver = (a, b) => {}
+    expect(Factory.validateFactory(resolver)).toEqual(true)
+  })
+})
+
+describe('Factory.createEntityType', () => {
   test('It should create entity defaults', () => {
-    function FooEntity () {}
-    const entity = Factory.create(
-      FooEntity,
-      {
-        before: '$',
-        value: '$',
-        error: '$',
-        after: '$'
-      },
-      'foo'
-    )
+    const resolve = (a, b) => true
+    const entitySource = {
+      resolve,
+      before: '$',
+      value: '$',
+      error: '$',
+      after: '$'
+    }
+    const entity = Factory.createEntityType('foo', 'bar', entitySource)
 
-    expect(entity).toHaveProperty('id', 'foo')
+    expect(entity).toHaveProperty('isEntityInstance', true)
+    expect(entity).toHaveProperty('id', 'foo:bar')
+    expect(entity).toHaveProperty('name', 'bar')
+    expect(entity).toHaveProperty('resolve', resolve)
     expect(entity).toHaveProperty('value.type', 'ReducerPath')
     expect(entity).toHaveProperty('error.type', 'ReducerPath')
     expect(entity).toHaveProperty('after.type', 'ReducerPath')
     expect(entity).toHaveProperty('params', {})
   })
 })
+
+describe('createEntityInstance', () => {
+  function createEntityInstance () {
+    const entity = {
+      id: 'foo:myFoo'
+    }
+    return Factory.createEntityInstance(entity)
+  }
+  it('should create an instance with overriden constructor name', () => {
+    expect(createEntityInstance().constructor.name).toEqual('foo:myFoo')
+  })
+  it('should return frozen object', () => {
+    expect(Object.isFrozen(createEntityInstance())).toEqual(true)
+  })
+})
+
+describe('create', () => {
+  const resolve = (acc, resolveReducer) => true
+  const create = (name, spec) => {
+    return {}
+  }
+  it('should throw error if arguments are wrong', () => {
+    expect(() => {
+      Factory.create()
+    }).toThrowErrorMatchingSnapshot()
+  })
+  it('should throw error if type argument is not string', () => {
+    expect(() => {
+      Factory.create(true, true, true)
+    }).toThrowErrorMatchingSnapshot()
+  })
+  it('should create Entity Factory', () => {
+    const BarFactory = Factory.create('bar', create, resolve)
+    expect(BarFactory).toBeInstanceOf(Function)
+    expect(BarFactory.length).toEqual(2)
+  })
+  it('should create new entity instance', () => {
+    const BarFactory = Factory.create('bar', create, resolve)
+    const entity = BarFactory('foo', {})
+    expect(entity).toMatchSnapshot()
+  })
+  it('should create new entity instance with generic name', () => {
+    const BarFactory = Factory.create('bar', create, resolve)
+    const entity = BarFactory({})
+    expect(entity).toMatchSnapshot()
+    expect(entity.resolve).toEqual(resolve)
+  })
+  it('should create new entity instance with assigned name', () => {
+    const BarFactory = Factory.create('bar', create, resolve)
+    const entity = BarFactory('myBar', {})
+    expect(entity).toMatchSnapshot()
+    expect(entity.resolve).toEqual(resolve)
+  })
+})
diff --git a/packages/data-point/lib/entity-types/base-entity/resolve.test.js b/packages/data-point/lib/entity-types/base-entity/resolve.test.js
index 1516d8a..4085cee 100644
--- a/packages/data-point/lib/entity-types/base-entity/resolve.test.js
+++ b/packages/data-point/lib/entity-types/base-entity/resolve.test.js
@@ -5,7 +5,8 @@ const Promise = require('bluebird')
 const ResolveEntity = require('./resolve')
 const createReducer = require('../../reducer-types').create
 const resolveReducer = require('../../reducer-types').resolve
-const createReducerEntity = require('../../reducer-types/reducer-entity').create
+const createReducerEntityId = require('../../reducer-types/reducer-entity-id')
+  .create
 
 const FixtureStore = require('../../../test/utils/fixture-store')
 const helpers = require('../../helpers')
@@ -13,6 +14,19 @@ const utils = require('../../utils')
 
 let dataPoint
 
+const resolveEntity = (entityId, input, options, resolver) => {
+  const racc = helpers.createAccumulator(input, options)
+  const reducer = createReducerEntityId(createReducer, entityId)
+  const entity = dataPoint.entities.get(entityId)
+  return ResolveEntity.resolveEntity(
+    dataPoint,
+    resolveReducer,
+    racc,
+    reducer,
+    entity
+  )
+}
+
 beforeAll(() => {
   dataPoint = FixtureStore.create()
 })
@@ -66,24 +80,47 @@ describe('ResolveEntity.resolveErrorReducers', () => {
   })
 })
 
+describe('getCurrentReducer', () => {
+  it('should return reducer as is if type=ReducerEntity', () => {
+    const reducer = {
+      spec: 'spec'
+    }
+    expect(ResolveEntity.getCurrentReducer(reducer)).toEqual(reducer)
+  })
+  it('should return decorated reducer if type!=ReducerEntity', () => {
+    const reducer = {}
+    expect(ResolveEntity.getCurrentReducer(reducer, 'spec')).toEqual({
+      spec: 'spec'
+    })
+  })
+})
+
 describe('ResolveEntity.createCurrentAccumulator', () => {
   let acc
-  beforeAll(() => {
-    const reducerEntity = createReducerEntity(createReducer, 'hash:base')
+  let spyGetUID
+  let entity
+  let reducer
+  beforeEach(() => {
+    spyGetUID = jest.spyOn(utils, 'getUID')
+    spyGetUID.mockImplementationOnce(() => 10)
+    reducer = createReducerEntityId(createReducer, 'hash:base')
+    entity = dataPoint.entities.get('hash:base')
     const accumulator = helpers.createAccumulator({
       foo: 'bar'
     })
-    acc = ResolveEntity.createCurrentAccumulator(
-      dataPoint,
-      accumulator,
-      reducerEntity
-    )
+    acc = ResolveEntity.createCurrentAccumulator(accumulator, reducer, entity)
   })
   test('It should set reducer property', () => {
-    expect(acc).toHaveProperty('reducer.spec.id', 'hash:base')
+    expect(acc).toHaveProperty('reducer')
+  })
+
+  test('It should create and set uid property', () => {
+    expect(spyGetUID).toBeCalled()
+    expect(acc).toHaveProperty('uid', 'hash:base:10')
   })
+
   test('It should context as the current Entity', () => {
-    expect(acc).toHaveProperty('context.id', 'hash:base')
+    expect(acc).toHaveProperty('context', entity)
   })
   test('It should initialValue acc.value', () => {
     expect(acc).toHaveProperty('initialValue', {
@@ -91,9 +128,10 @@ describe('ResolveEntity.createCurrentAccumulator', () => {
     })
   })
   test('It should set an initialValue for acc.params', () => {
-    expect(acc).toHaveProperty('params', {
-      base: true
-    })
+    expect(acc).toHaveProperty('params', entity.params)
+  })
+  test('It should override debug method', () => {
+    expect(acc.debug).toBeInstanceOf(Function)
   })
 })
 
@@ -137,20 +175,6 @@ describe('ResolveEntity.resolveMiddleware', () => {
 })
 
 describe('ResolveEntity.resolveEntity', () => {
-  const defaultResolver = (acc, resolveReducer) => Promise.resolve(acc)
-
-  const resolveEntity = (entityId, input, options, resolver) => {
-    const racc = helpers.createAccumulator(input, options)
-    const reducer = createReducerEntity(createReducer, entityId)
-    return ResolveEntity.resolveEntity(
-      dataPoint,
-      resolveReducer,
-      racc,
-      reducer,
-      resolver || defaultResolver
-    )
-  }
-
   test('It should resolve entity', () => {
     return resolveEntity('model:asIs', 'foo').then(acc => {
       expect(acc).toHaveProperty('value', 'foo')
@@ -221,20 +245,6 @@ describe('ResolveEntity.resolveEntity', () => {
 })
 
 describe('ResolveEntity.resolveEntity outputType', () => {
-  const defaultResolver = (acc, resolveReducer) => Promise.resolve(acc)
-
-  const resolveEntity = (entityId, input, options, resolver) => {
-    const racc = helpers.createAccumulator(input, options)
-    const reducer = createReducerEntity(createReducer, entityId)
-    return ResolveEntity.resolveEntity(
-      dataPoint,
-      resolveReducer,
-      racc,
-      reducer,
-      resolver || defaultResolver
-    )
-  }
-
   test('throws error if value does not pass typeCheck', () => {
     return resolveEntity('model:c.1', 1)
       .catch(e => e)
@@ -370,77 +380,53 @@ describe('ResolveEntity.resolveEntity outputType', () => {
 })
 
 describe('ResolveEntity.resolve', () => {
-  const resolve = resolver => (entityId, input, options) => {
+  const resolve = (entityId, input, options) => {
     const racc = helpers.createAccumulator(input, options)
-    const reducer = createReducerEntity(createReducer, entityId)
+    const reducer = createReducerEntityId(createReducer, entityId)
+    const entity = dataPoint.entities.get(reducer.id)
     return ResolveEntity.resolve(
       dataPoint,
       resolveReducer,
       racc,
       reducer,
-      resolver
+      entity
     )
   }
 
   test('It should resolve as single entity', () => {
-    const resolver = (acc, resolveReducer) => {
-      const result = utils.set(acc, 'value', 'bar')
-      return Promise.resolve(result)
-    }
-    return resolve(resolver)('model:asIs', 'foo').then(acc => {
-      expect(acc).toHaveProperty('value', 'bar')
+    return resolve('model:asIs', 'foo').then(acc => {
+      expect(acc).toHaveProperty('value', 'foo')
     })
   })
 
   test('It should resolve as collection', () => {
-    const resolver = (acc, resolveReducer) => {
-      const result = utils.set(acc, 'value', 'bar')
-      return Promise.resolve(result)
-    }
-    return resolve(resolver)('model:asIs[]', ['foo']).then(acc => {
-      expect(acc).toHaveProperty('value', ['bar'])
+    return resolve('model:asIs[]', ['foo']).then(acc => {
+      expect(acc).toHaveProperty('value', ['foo'])
     })
   })
   test('It should return undefined if accumulator is not Array', () => {
-    const resolver = (acc, resolveReducer) => {
-      return Promise.resolve(acc)
-    }
-    return resolve(resolver)('model:asIs[]', {}).then(acc => {
+    return resolve('model:asIs[]', {}).then(acc => {
       expect(acc.value).toBeUndefined()
     })
   })
   test('It should not execute resolver if flag hasEmptyConditional is true and value is empty', () => {
-    const resolver = jest.fn()
-    return resolve(resolver)('?model:asIs', undefined).then(acc => {
-      expect(resolver).not.toHaveBeenCalled()
+    return resolve('?model:asIs', undefined).then(acc => {
+      expect(acc.value).toBeUndefined()
     })
   })
 
   test('It should execute resolver if flag hasEmptyConditional is true and value is not empty', () => {
-    const resolver = (acc, resolveReducer) => {
-      const result = utils.set(acc, 'value', 'bar')
-      return Promise.resolve(result)
-    }
-    return resolve(resolver)('?model:asIs', 'foo').then(acc => {
-      expect(acc).toHaveProperty('value', 'bar')
+    return resolve('?model:asIs', 'foo').then(acc => {
+      expect(acc).toHaveProperty('value', 'foo')
     })
   })
 
   test('It should execute resolver only on non empty items of collection if hasEmptyConditional is set', () => {
-    let count = 0
-    const resolver = (acc, resolveReducer) => {
-      const result = utils.set(acc, 'value', count++)
-      return Promise.resolve(result)
-    }
-    return resolve(resolver)('?model:asIs[]', [
-      'a',
-      undefined,
-      'b',
-      null,
-      'c'
-    ]).then(acc => {
-      expect(acc).toHaveProperty('value', [0, undefined, 1, null, 2])
-    })
+    return resolve('?model:asIs[]', ['a', undefined, 'b', null, 'c']).then(
+      acc => {
+        expect(acc).toHaveProperty('value', ['a', undefined, 'b', null, 'c'])
+      }
+    )
   })
 })
 
diff --git a/packages/data-point/lib/entity-types/entity-collection/factory.test.js b/packages/data-point/lib/entity-types/entity-collection/factory.test.js
index 680676d..2b59eb9 100644
--- a/packages/data-point/lib/entity-types/entity-collection/factory.test.js
+++ b/packages/data-point/lib/entity-types/entity-collection/factory.test.js
@@ -4,7 +4,7 @@ const modelFactory = require('./factory')
 const helpers = require('../../helpers')
 
 test('modelFactory#create default', () => {
-  const result = modelFactory.create({})
+  const result = modelFactory.create('name', {})
   expect(result).not.toHaveProperty('error')
   expect(result).not.toHaveProperty('before')
   expect(result).not.toHaveProperty('after')
@@ -16,7 +16,7 @@ test('modelFactory#create default', () => {
 
 describe('parse loose modifiers', () => {
   test('modelFactory#create default | checks that an entity containing one reducer has that respective property', () => {
-    const result = modelFactory.create({
+    const result = modelFactory.create('name', {
       map: '$a'
     })
 
@@ -28,7 +28,7 @@ describe('parse loose modifiers', () => {
 
 describe('parse compose modifier', () => {
   test('parses from compose property', () => {
-    const result = modelFactory.create({
+    const result = modelFactory.create('name', {
       compose: [{ map: '$a' }]
     })
 
@@ -39,33 +39,26 @@ describe('parse compose modifier', () => {
 
   test('throw error if compose is not an array', () => {
     expect(() => {
-      modelFactory.create(
-        {
-          compose: { map: '$a' }
-        },
-        'test-id'
-      )
+      modelFactory.create('test-id', {
+        compose: { map: '$a' }
+      })
     }).toThrowErrorMatchingSnapshot()
   })
 
   test('throw error if compose is mixed with inline modifiers (map, filter, ..) ', () => {
     expect(() => {
-      modelFactory.create(
-        {
-          compose: [{ map: '$a' }],
-          map: '$a',
-          filter: '$a'
-        },
-        'test-id'
-      )
+      modelFactory.create('test-id', {
+        compose: [{ map: '$a' }],
+        map: '$a',
+        filter: '$a'
+      })
     }).toThrowErrorMatchingSnapshot()
   })
 
   test('parses multiple modifiers, respect order', () => {
-    const result = modelFactory.create({
+    const result = modelFactory.create('name', {
       compose: [{ map: '$a' }, { find: '$a' }, { filter: '$a' }]
     })
-
     expect(helpers.isReducer(result.compose)).toBe(true)
     expect(result.compose).toHaveProperty('type', 'ReducerList')
     expect(result.compose.reducers[0]).toHaveProperty('type', 'ReducerMap')
diff --git a/packages/data-point/lib/entity-types/entity-control/factory.test.js b/packages/data-point/lib/entity-types/entity-control/factory.test.js
index a546a3c..0457c23 100644
--- a/packages/data-point/lib/entity-types/entity-control/factory.test.js
+++ b/packages/data-point/lib/entity-types/entity-control/factory.test.js
@@ -3,7 +3,7 @@
 const Factory = require('./factory')
 
 test('Factory#create', () => {
-  const control = Factory.create({
+  const control = Factory.create('name', {
     select: [
       { case: '$a', do: '$b' },
       { case: '$c', do: '$d' },
@@ -20,7 +20,7 @@ test('Factory#create', () => {
 
 test('Factory#create enforce default statement', () => {
   expect(() => {
-    Factory.create({
+    Factory.create('name', {
       select: [{ case: 'a()', do: 'b()' }, { case: 'c()', do: 'd()' }]
     })
   }).toThrow(/missing|default/)
diff --git a/packages/data-point/lib/entity-types/entity-entry/factory.test.js b/packages/data-point/lib/entity-types/entity-entry/factory.test.js
index dc94d01..97490b6 100644
--- a/packages/data-point/lib/entity-types/entity-entry/factory.test.js
+++ b/packages/data-point/lib/entity-types/entity-entry/factory.test.js
@@ -3,7 +3,7 @@
 const Factory = require('./factory')
 
 test('Factory#create', () => {
-  const obj = Factory.create({
+  const obj = Factory.create('name', {
     value: ['$foo', () => {}]
   })
 
diff --git a/packages/data-point/lib/entity-types/entity-hash/factory.test.js b/packages/data-point/lib/entity-types/entity-hash/factory.test.js
index 82de386..48dd2e1 100644
--- a/packages/data-point/lib/entity-types/entity-hash/factory.test.js
+++ b/packages/data-point/lib/entity-types/entity-hash/factory.test.js
@@ -4,7 +4,7 @@ const factory = require('./factory')
 const helpers = require('../../helpers')
 
 test('factory#create default', () => {
-  const result = factory.create({})
+  const result = factory.create('name', {})
 
   expect(result).not.toHaveProperty('error')
   expect(result).not.toHaveProperty('before')
@@ -16,7 +16,7 @@ test('factory#create default', () => {
 
 describe('factory#parse loose modifiers', () => {
   test('factory#mapKeys', () => {
-    const result = factory.create({
+    const result = factory.create('name', {
       mapKeys: {
         a: '$a'
       }
@@ -27,7 +27,7 @@ describe('factory#parse loose modifiers', () => {
   })
 
   test('factory#addKeys', () => {
-    const result = factory.create({
+    const result = factory.create('name', {
       addKeys: {
         a: '$a'
       }
@@ -38,7 +38,7 @@ describe('factory#parse loose modifiers', () => {
   })
 
   test('factory#omitKeys', () => {
-    const result = factory.create({
+    const result = factory.create('name', {
       omitKeys: ['a']
     })
 
@@ -48,7 +48,7 @@ describe('factory#parse loose modifiers', () => {
   })
 
   test('factory#pickKeys', () => {
-    const result = factory.create({
+    const result = factory.create('name', {
       pickKeys: ['a']
     })
 
@@ -64,7 +64,7 @@ describe('factory#parse composed modifiers', () => {
       compose: {}
     }
     expect(() => {
-      factory.create(spec, 'hash:invalid')
+      factory.create('hash:invalid', spec)
     }).toThrowErrorMatchingSnapshot()
   })
 
@@ -78,7 +78,7 @@ describe('factory#parse composed modifiers', () => {
       ]
     }
     expect(() => {
-      factory.create(spec, 'hash:invalid')
+      factory.create('hash:invalid', spec)
     }).toThrowErrorMatchingSnapshot()
   })
 
@@ -91,12 +91,12 @@ describe('factory#parse composed modifiers', () => {
       ]
     }
     expect(() => {
-      factory.create(spec, 'hash:invalid')
+      factory.create('hash:invalid', spec)
     }).toThrowErrorMatchingSnapshot()
   })
 
   test('factory#one modifier', () => {
-    const result = factory.create({
+    const result = factory.create('name', {
       compose: [
         {
           mapKeys: {
@@ -111,7 +111,7 @@ describe('factory#parse composed modifiers', () => {
   })
 
   test('factory#multiple modifiers', () => {
-    const result = factory.create({
+    const result = factory.create('name', {
       compose: [
         {
           addKeys: {
diff --git a/packages/data-point/lib/entity-types/entity-model/factory.test.js b/packages/data-point/lib/entity-types/entity-model/factory.test.js
index 6bcca6e..969dfd8 100644
--- a/packages/data-point/lib/entity-types/entity-model/factory.test.js
+++ b/packages/data-point/lib/entity-types/entity-model/factory.test.js
@@ -3,7 +3,7 @@
 const Factory = require('./factory')
 
 test('Factory#create', () => {
-  const obj = Factory.create({
+  const obj = Factory.create('name', {
     value: ['$foo', (acc, done) => {}]
   })
 
diff --git a/packages/data-point/lib/entity-types/entity-request/factory.test.js b/packages/data-point/lib/entity-types/entity-request/factory.test.js
index ddc1cfc..c58e935 100644
--- a/packages/data-point/lib/entity-types/entity-request/factory.test.js
+++ b/packages/data-point/lib/entity-types/entity-request/factory.test.js
@@ -8,9 +8,9 @@ const { isReducer } = require('../../reducer-types')
 
 describe('create', () => {
   let request
-  beforeAll(() => {
+  beforeEach(() => {
     const requestSpec = requests['request:a0.1']
-    request = requestFactory.create(requestSpec)
+    request = requestFactory.create('name', requestSpec)
   })
   test('It should have defaults', () => {
     expect(request).toHaveProperty('id')
@@ -26,7 +26,7 @@ describe('create', () => {
     expect(isReducer(request.options)).toBe(true)
   })
   test('It should have the default options reducer', () => {
-    const newRequest = requestFactory.create(requests['request:a1.0'])
+    const newRequest = requestFactory.create('name', requests['request:a1.0'])
     expect(isReducer(newRequest.options)).toBe(true)
     expect(newRequest.options.body).toEqual(requestFactory.defaultOptions)
   })
diff --git a/packages/data-point/lib/entity-types/entity-request/resolve.test.js b/packages/data-point/lib/entity-types/entity-request/resolve.test.js
index fb48840..400c6b9 100644
--- a/packages/data-point/lib/entity-types/entity-request/resolve.test.js
+++ b/packages/data-point/lib/entity-types/entity-request/resolve.test.js
@@ -38,7 +38,8 @@ function helperMockContext (accumulatorData, reducerSource, requestName) {
     values
   })
   const reducer = ReducerFactory.create(reducerSource)
-  return ResolveEntity.createCurrentAccumulator(dataPoint, accumulator, reducer)
+  const entity = dataPoint.entities.get(reducer.id)
+  return ResolveEntity.createCurrentAccumulator(accumulator, reducer, entity)
 }
 
 beforeAll(() => {
diff --git a/packages/data-point/lib/entity-types/entity-schema/factory.test.js b/packages/data-point/lib/entity-types/entity-schema/factory.test.js
index e16cd7e..0fd726c 100644
--- a/packages/data-point/lib/entity-types/entity-schema/factory.test.js
+++ b/packages/data-point/lib/entity-types/entity-schema/factory.test.js
@@ -3,7 +3,7 @@
 const Factory = require('./factory')
 
 test('Factory#create', () => {
-  const obj = Factory.create({
+  const obj = Factory.create('name', {
     schema: {
       properties: {
         foo: { type: 'number' },
@@ -23,7 +23,7 @@ test('Factory#create', () => {
   expect(obj).toHaveProperty('params')
 
   expect(() =>
-    Factory.create({
+    Factory.create('name', {
       schema: { type: null }
     })
   ).toThrowErrorMatchingSnapshot()
diff --git a/packages/data-point/lib/entity-types/entity-transform/factory.test.js b/packages/data-point/lib/entity-types/entity-transform/factory.test.js
index c530bd5..57b5bd1 100644
--- a/packages/data-point/lib/entity-types/entity-transform/factory.test.js
+++ b/packages/data-point/lib/entity-types/entity-transform/factory.test.js
@@ -3,8 +3,8 @@
 const modelFactory = require('./factory')
 
 test('modelFactory#create default', () => {
-  const result = modelFactory.create('$a', 'test')
+  const result = modelFactory.create('test', '$a')
 
-  expect(result).toHaveProperty('id', 'test')
+  expect(result).toHaveProperty('id', 'reducer:test')
   expect(result.value).toHaveProperty('type', 'ReducerPath')
 })
diff --git a/packages/data-point/lib/entity-types/entity-transform/resolve.test.js b/packages/data-point/lib/entity-types/entity-transform/resolve.test.js
index e6df2d5..8d5dba6 100644
--- a/packages/data-point/lib/entity-types/entity-transform/resolve.test.js
+++ b/packages/data-point/lib/entity-types/entity-transform/resolve.test.js
@@ -30,7 +30,7 @@ beforeAll(() => {
 
 describe('entity.transform.value', () => {
   test('should resolve value Transform', () => {
-    return transform('transform:a0', {
+    return transform('reducer:a0', {
       message: 'hello world'
     }).then(acc => {
       expect(acc.value).toEqual('hello world')
@@ -38,7 +38,7 @@ describe('entity.transform.value', () => {
   })
 
   test('should resolve context Transform', () => {
-    return transform('transform:a1', {
+    return transform('reducer:a1', {
       message: 'hello world'
     }).then(acc => {
       expect(acc.value).toEqual('HELLO WORLD')
diff --git a/packages/data-point/lib/entity-types/integrations.test.js b/packages/data-point/lib/entity-types/integrations.test.js
index 7c38059..9e8c4d3 100644
--- a/packages/data-point/lib/entity-types/integrations.test.js
+++ b/packages/data-point/lib/entity-types/integrations.test.js
@@ -211,6 +211,16 @@ test('Entry#resolve - run schema, pass value if valid', () => {
     .then(result => expect(result.value).toBeTruthy())
 })
 
+test('Model Entity Instance', () => {
+  const Model = require('./entity-model')
+  const model = Model('myModel', {
+    value: value => value * 10
+  })
+  return dataPoint
+    .resolve(model, 10)
+    .then(result => expect(result).toEqual(100))
+})
+
 describe('trace feature', () => {
   test('trace via options parameter', () => {
     const consoleTime = console.time
diff --git a/packages/data-point/lib/entity-types/spec/__snapshots__/factory.test.js.snap b/packages/data-point/lib/entity-types/spec/__snapshots__/factory.test.js.snap
new file mode 100644
index 0000000..636ed2e
--- /dev/null
+++ b/packages/data-point/lib/entity-types/spec/__snapshots__/factory.test.js.snap
@@ -0,0 +1,5 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`reducer/reducer-entity-id#create throw if factory is not a function 1`] = `"Entity Factory 'entry:abc' should be a function: {}"`;
+
+exports[`reducer/reducer-entity-id#create throw if resolve has wrong arity 1`] = `"Entity Factory 'entry:abc' method should have an arity of 2, instead got: 0"`;
diff --git a/packages/data-point/lib/entity-types/spec/factory.test.js b/packages/data-point/lib/entity-types/spec/factory.test.js
index fbcf49c..347a211 100644
--- a/packages/data-point/lib/entity-types/spec/factory.test.js
+++ b/packages/data-point/lib/entity-types/spec/factory.test.js
@@ -4,25 +4,20 @@ const factory = require('./factory')
 
 const EntityEntry = require('../entity-entry')
 
-describe('reducer/reducer-entity#create', () => {
+describe('reducer/reducer-entity-id#create', () => {
   const stub = () => {}
-  test('throw if create is missing', () => {
+  test('throw if factory is not a function', () => {
     expect(() => {
       factory.create({}, 'entry:abc')
-    }).toThrow()
-  })
-  test('throw if resolve is missing', () => {
-    expect(() => {
-      factory.create({ create: stub }, 'entry:abc')
-    }).toThrow()
+    }).toThrowErrorMatchingSnapshot()
   })
   test('throw if resolve has wrong arity', () => {
     expect(() => {
-      factory.create({ create: stub, resolve: stub }, 'entry:abc')
-    }).toThrow()
+      factory.create(stub, 'entry:abc')
+    }).toThrowErrorMatchingSnapshot()
   })
   test('entry', () => {
     const reducer = factory.create(EntityEntry, 'entry:abc')
-    expect(reducer.id).toBe('entry:abc')
+    expect(EntityEntry).toBe(reducer)
   })
 })
diff --git a/packages/data-point/lib/reducer-types/factory.test.js b/packages/data-point/lib/reducer-types/factory.test.js
index 078895f..5af8848 100644
--- a/packages/data-point/lib/reducer-types/factory.test.js
+++ b/packages/data-point/lib/reducer-types/factory.test.js
@@ -5,7 +5,7 @@ const Factory = require('./factory')
 const ReducerPath = require('./reducer-path')
 const ReducerFunction = require('./reducer-function')
 const ReducerObject = require('./reducer-object')
-const ReducerEntity = require('./reducer-entity')
+const ReducerEntityId = require('./reducer-entity-id')
 const stubFactories = require('./reducer-helpers').stubFactories
 
 describe('reducer#create', () => {
@@ -30,7 +30,7 @@ describe('reducer#create', () => {
 
   test('create entity', () => {
     const reducer = Factory.create('fooEntity:foo.bar')
-    expect(reducer.type).toBe(ReducerEntity.type)
+    expect(reducer.type).toBe(ReducerEntityId.type)
     expect(reducer.name).toBe('foo.bar')
     expect(reducer.entityType).toBe('fooEntity')
   })
diff --git a/packages/data-point/lib/reducer-types/reducer-entity-id/factory.test.js b/packages/data-point/lib/reducer-types/reducer-entity-id/factory.test.js
new file mode 100644
index 0000000..1138db8
--- /dev/null
+++ b/packages/data-point/lib/reducer-types/reducer-entity-id/factory.test.js
@@ -0,0 +1,63 @@
+/* eslint-env jest */
+
+const factory = require('./factory')
+const createReducer = require('../index').create
+
+test('reducer/reducer-entity-id#isType', () => {
+  expect(factory.isType('a')).toBe(false)
+  expect(factory.isType('ab')).toBe(false)
+  expect(factory.isType('#ab')).toBe(false)
+  expect(factory.isType('abc')).toBe(false)
+  expect(factory.isType('ab:')).toBe(false)
+  expect(factory.isType(':ab')).toBe(false)
+  expect(factory.isType('$a:abc')).toBe(false)
+  expect(factory.isType('a-bc:abc')).toBe(false)
+  expect(factory.isType('a:abc')).toBe(true)
+  expect(factory.isType('abc:a')).toBe(true)
+  expect(factory.isType('abc:abc')).toBe(true)
+  expect(factory.isType('?abc:abc')).toBe(true)
+  expect(factory.isType('abc:ab-c-')).toBe(true)
+  expect(factory.isType('_abc:abc')).toBe(true)
+  expect(factory.isType('#abc:abc')).toBe(true)
+  expect(factory.isType('abc:abc[]')).toBe(true)
+  expect(factory.isType('abc:abc[][]')).toBe(false)
+  expect(factory.isType('abc:abc[]d')).toBe(false)
+})
+
+describe('create', function () {
+  test('default create', () => {
+    const reducer = factory.create(createReducer, 'foo:abc')
+    expect(reducer.hasEmptyConditional).toBe(false)
+    expect(reducer.asCollection).toBe(false)
+    expect(reducer.type).toBe('ReducerEntityId')
+    expect(reducer.name).toBe('abc')
+    expect(reducer.entityType).toBe('foo')
+  })
+
+  test('as collection', () => {
+    const reducer = factory.create(createReducer, 'foo:abc[]')
+    expect(reducer.asCollection).toBe(true)
+    expect(reducer.hasEmptyConditional).toBe(false)
+    expect(reducer.type).toBe('ReducerEntityId')
+    expect(reducer.name).toBe('abc')
+    expect(reducer.entityType).toBe('foo')
+  })
+
+  test('with conditional', () => {
+    const reducer = factory.create(createReducer, '?foo:abc')
+    expect(reducer.hasEmptyConditional).toBe(true)
+    expect(reducer.asCollection).toBe(false)
+    expect(reducer.type).toBe('ReducerEntityId')
+    expect(reducer.name).toBe('abc')
+    expect(reducer.entityType).toBe('foo')
+  })
+
+  test('with conditional and as collection', () => {
+    const reducer = factory.create(createReducer, '?foo:abc[]')
+    expect(reducer.hasEmptyConditional).toBe(true)
+    expect(reducer.asCollection).toBe(true)
+    expect(reducer.type).toBe('ReducerEntityId')
+    expect(reducer.name).toBe('abc')
+    expect(reducer.entityType).toBe('foo')
+  })
+})
diff --git a/packages/data-point/lib/reducer-types/reducer-entity/__snapshots__/factory.test.js.snap b/packages/data-point/lib/reducer-types/reducer-entity/__snapshots__/factory.test.js.snap
new file mode 100644
index 0000000..2a2025a
--- /dev/null
+++ b/packages/data-point/lib/reducer-types/reducer-entity/__snapshots__/factory.test.js.snap
@@ -0,0 +1,42 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`create default create 1`] = `
+ReducerEntity {
+  "asCollection": false,
+  "entity": reducer:foo {
+    "entityType": "reducer",
+    "id": "reducer:foo",
+    "isEntityInstance": true,
+    "name": "foo",
+    "params": Object {},
+    "resolve": [Function],
+    "value": ReducerPath {
+      "asCollection": false,
+      "body": [Function],
+      "name": "$",
+      "type": "ReducerPath",
+      Symbol(reducer): true,
+    },
+  },
+  "entityType": "reducer",
+  "hasEmptyConditional": false,
+  "id": "reducer:foo",
+  "name": "foo",
+  "spec": reducer:foo {
+    "entityType": "reducer",
+    "id": "reducer:foo",
+    "isEntityInstance": true,
+    "name": "foo",
+    "params": Object {},
+    "resolve": [Function],
+    "value": ReducerPath {
+      "asCollection": false,
+      "body": [Function],
+      "name": "$",
+      "type": "ReducerPath",
+      Symbol(reducer): true,
+    },
+  },
+  "type": "ReducerEntity",
+}
+`;
diff --git a/packages/data-point/lib/reducer-types/reducer-entity/factory.test.js b/packages/data-point/lib/reducer-types/reducer-entity/factory.test.js
index 687aefc..7cb7d2a 100644
--- a/packages/data-point/lib/reducer-types/reducer-entity/factory.test.js
+++ b/packages/data-point/lib/reducer-types/reducer-entity/factory.test.js
@@ -2,62 +2,21 @@
 
 const factory = require('./factory')
 const createReducer = require('../index').create
+const EntityReducer = require('../../entity-types/entity-transform')
 
-test('reducer/reducer-entity#isType', () => {
+test('isType', () => {
   expect(factory.isType('a')).toBe(false)
-  expect(factory.isType('ab')).toBe(false)
-  expect(factory.isType('#ab')).toBe(false)
-  expect(factory.isType('abc')).toBe(false)
-  expect(factory.isType('ab:')).toBe(false)
-  expect(factory.isType(':ab')).toBe(false)
-  expect(factory.isType('$a:abc')).toBe(false)
-  expect(factory.isType('a-bc:abc')).toBe(false)
-  expect(factory.isType('a:abc')).toBe(true)
-  expect(factory.isType('abc:a')).toBe(true)
-  expect(factory.isType('abc:abc')).toBe(true)
-  expect(factory.isType('?abc:abc')).toBe(true)
-  expect(factory.isType('abc:ab-c-')).toBe(true)
-  expect(factory.isType('_abc:abc')).toBe(true)
-  expect(factory.isType('#abc:abc')).toBe(true)
-  expect(factory.isType('abc:abc[]')).toBe(true)
-  expect(factory.isType('abc:abc[][]')).toBe(false)
-  expect(factory.isType('abc:abc[]d')).toBe(false)
+  expect(factory.isType({})).toBe(false)
+  expect(
+    factory.isType({
+      isEntityInstance: true
+    })
+  ).toBe(true)
 })
 
 describe('create', function () {
   test('default create', () => {
-    const reducer = factory.create(createReducer, 'foo:abc')
-    expect(reducer.hasEmptyConditional).toBe(false)
-    expect(reducer.asCollection).toBe(false)
-    expect(reducer.type).toBe('ReducerEntity')
-    expect(reducer.name).toBe('abc')
-    expect(reducer.entityType).toBe('foo')
-  })
-
-  test('as collection', () => {
-    const reducer = factory.create(createReducer, 'foo:abc[]')
-    expect(reducer.asCollection).toBe(true)
-    expect(reducer.hasEmptyConditional).toBe(false)
-    expect(reducer.type).toBe('ReducerEntity')
-    expect(reducer.name).toBe('abc')
-    expect(reducer.entityType).toBe('foo')
-  })
-
-  test('with conditional', () => {
-    const reducer = factory.create(createReducer, '?foo:abc')
-    expect(reducer.hasEmptyConditional).toBe(true)
-    expect(reducer.asCollection).toBe(false)
-    expect(reducer.type).toBe('ReducerEntity')
-    expect(reducer.name).toBe('abc')
-    expect(reducer.entityType).toBe('foo')
-  })
-
-  test('with conditional and as collection', () => {
-    const reducer = factory.create(createReducer, '?foo:abc[]')
-    expect(reducer.hasEmptyConditional).toBe(true)
-    expect(reducer.asCollection).toBe(true)
-    expect(reducer.type).toBe('ReducerEntity')
-    expect(reducer.name).toBe('abc')
-    expect(reducer.entityType).toBe('foo')
+    const reducer = factory.create(createReducer, EntityReducer('foo', '$'))
+    expect(reducer).toMatchSnapshot()
   })
 })
diff --git a/packages/data-point/lib/reducer-types/reducer-helpers/reducer-assign/resolve.test.js b/packages/data-point/lib/reducer-types/reducer-helpers/reducer-assign/resolve.test.js
index 2fcc539..139f409 100644
--- a/packages/data-point/lib/reducer-types/reducer-helpers/reducer-assign/resolve.test.js
+++ b/packages/data-point/lib/reducer-types/reducer-helpers/reducer-assign/resolve.test.js
@@ -14,7 +14,7 @@ let manager
 beforeAll(() => {
   manager = DataPoint.create({
     entities: {
-      'transform:a': () => ({
+      'reducer:a': () => ({
         b: 22,
         c: 33
       })
@@ -44,7 +44,7 @@ describe('ReducerAssign#resolve', () => {
       }
     })
 
-    const reducer = Factory.create(Reducer.create, 'transform:a')
+    const reducer = Factory.create(Reducer.create, 'reducer:a')
     return Resolve.resolve(manager, Reducer.resolve, accumulator, reducer).then(
       result => {
         expect(result.value).toEqual({
diff --git a/packages/data-point/lib/reducer-types/reducer-list/factory.test.js b/packages/data-point/lib/reducer-types/reducer-list/factory.test.js
index dfbc768..c8d8b77 100644
--- a/packages/data-point/lib/reducer-types/reducer-list/factory.test.js
+++ b/packages/data-point/lib/reducer-types/reducer-list/factory.test.js
@@ -33,7 +33,7 @@ describe('factory#create', () => {
 
     expect(result.reducers).toHaveLength(3)
     expect(result.reducers[0].type).toBe('ReducerPath')
-    expect(result.reducers[1].type).toBe('ReducerEntity')
+    expect(result.reducers[1].type).toBe('ReducerEntityId')
     expect(result.reducers[2].type).toBe('ReducerFunction')
   })
 
@@ -45,7 +45,7 @@ describe('factory#create', () => {
 
     expect(result.reducers).toHaveLength(3)
     expect(result.reducers[0].type).toBe('ReducerPath')
-    expect(result.reducers[1].type).toBe('ReducerEntity')
+    expect(result.reducers[1].type).toBe('ReducerEntityId')
     expect(result.reducers[2].type).toBe('ReducerFunction')
   })
 
@@ -58,7 +58,7 @@ describe('factory#create', () => {
 
     expect(result.reducers).toHaveLength(3)
     expect(result.reducers[0].type).toBe('ReducerPath')
-    expect(result.reducers[1].type).toBe('ReducerEntity')
+    expect(result.reducers[1].type).toBe('ReducerEntityId')
     expect(result.reducers[2].type).toBe('ReducerFunction')
   })
 })
@@ -115,7 +115,7 @@ describe('factory#create', () => {
 
     expect(result.reducers).toHaveLength(4)
     expect(result.reducers[0].type).toBe('ReducerPath')
-    expect(result.reducers[1].type).toBe('ReducerEntity')
+    expect(result.reducers[1].type).toBe('ReducerEntityId')
     expect(result.reducers[2].type).toBe('ReducerPath')
     expect(result.reducers[3].type).toBe('ReducerFunction')
   })
diff --git a/packages/data-point/lib/reducer-types/reducer-object/__snapshots__/factory.test.js.snap b/packages/data-point/lib/reducer-types/reducer-object/__snapshots__/factory.test.js.snap
index aad9a9a..d70da0a 100644
--- a/packages/data-point/lib/reducer-types/reducer-object/__snapshots__/factory.test.js.snap
+++ b/packages/data-point/lib/reducer-types/reducer-object/__snapshots__/factory.test.js.snap
@@ -101,13 +101,13 @@ Object {
             "path": Array [
               "a3",
             ],
-            "reducer": ReducerEntity {
+            "reducer": ReducerEntityId {
               "asCollection": false,
-              "entityType": "transform",
+              "entityType": "reducer",
               "hasEmptyConditional": false,
-              "id": "transform:entity-name",
+              "id": "reducer:entity-name",
               "name": "entity-name",
-              "type": "ReducerEntity",
+              "type": "ReducerEntityId",
               Symbol(reducer): true,
             },
           },
diff --git a/packages/data-point/lib/reducer-types/reducer-object/factory.test.js b/packages/data-point/lib/reducer-types/reducer-object/factory.test.js
index d68f52b..e3599f0 100644
--- a/packages/data-point/lib/reducer-types/reducer-object/factory.test.js
+++ b/packages/data-point/lib/reducer-types/reducer-object/factory.test.js
@@ -26,7 +26,7 @@ describe('ReducerObject.factory#getProps', () => {
         a2: ['$a2', () => false],
         b2: [
           {
-            a3: 'transform:entity-name',
+            a3: 'reducer:entity-name',
             b3: '$b1.b2.b3',
             c3: constant('CONSTANT')
           }
diff --git a/packages/data-point/lib/stores/entity-types.test.js b/packages/data-point/lib/stores/entity-types.test.js
index 1fff50e..5f2ee89 100644
--- a/packages/data-point/lib/stores/entity-types.test.js
+++ b/packages/data-point/lib/stores/entity-types.test.js
@@ -3,20 +3,7 @@
 const _ = require('lodash')
 const EntityType = require('./entity-types')
 
-const FooEntityType = (() => {
-  function create (spec) {
-    // body;
-  }
-
-  function resolve (accumulator, resolveReducer) {
-    // body;
-  }
-
-  return {
-    create,
-    resolve
-  }
-})()
+const FooEntityType = (id, spec) => {}
 
 let entityTypes
 
@@ -26,33 +13,24 @@ it('setup', () => {
 
 it('source#getStore', () => {
   const result = entityTypes.getStore()
-  expect.assertions(1)
   expect(_.isObject(result)).toBeTruthy()
 })
 
 it('source#add/get', () => {
   entityTypes.add('foo', FooEntityType)
-
-  const foo = entityTypes.get('foo')
-
-  expect.assertions(2)
-  expect(_.isFunction(foo.create)).toBeTruthy()
-
-  const doNotAllowOverride = _.attempt(entityTypes.add, 'foo', {})
+  const doNotAllowOverride = _.attempt(entityTypes.add, 'foo', () => {})
   expect(_.isError(doNotAllowOverride)).toBeTruthy()
 })
 
 it('source#get invalid id', () => {
   const result = _.attempt(entityTypes.get, 'DOES_NOT_EXISTS')
-  expect.assertions(1)
   expect(result instanceof Error).toBeTruthy()
 })
 
 it('source#get', () => {
   entityTypes.add('request:a1', FooEntityType)
   const result = entityTypes.get('foo')
-  expect.assertions(1)
-  expect(_.isFunction(result.create)).toBeTruthy()
+  expect(result).toEqual(FooEntityType)
 })
 
 it('teardown', () => {
diff --git a/packages/data-point/test/definitions/transform.js b/packages/data-point/test/definitions/transform.js
index 4e082cf..c56df8a 100644
--- a/packages/data-point/test/definitions/transform.js
+++ b/packages/data-point/test/definitions/transform.js
@@ -1,4 +1,4 @@
 module.exports = {
-  'transform:a0': '$message',
-  'transform:a1': ['transform:a0', value => value.toUpperCase()]
+  'reducer:a0': '$message',
+  'reducer:a1': ['reducer:a0', value => value.toUpperCase()]
 }