From c39c855ba520ceea165a3c0b9bdace15b492b89a Mon Sep 17 00:00:00 2001
From: David Luecke <daff@neyeon.com>
Date: Fri, 28 Dec 2018 11:02:09 -0800
Subject: [PATCH] Upgrade to @feathersjs/adapter-commons and latest common
 service features (#181)

* Start migration to @feathersjs/adapter-commons

* Finalize refactoring to adapter-commons

* Force remove to always work

* Command typo

* Update error handling and finalize docs
---
 .gitignore           |   2 +-
 .travis.yml          |   4 +-
 README.md            |  20 +-
 lib/error-handler.js |  58 ++-
 lib/hooks.js         |  14 +-
 lib/index.js         | 270 ++++++-------
 package-lock.json    | 917 +++++++++++++++++++------------------------
 package.json         |  25 +-
 test/index.test.js   | 370 +++++++++--------
 9 files changed, 754 insertions(+), 926 deletions(-)

diff --git a/.gitignore b/.gitignore
index 2f5fd7a..2df86c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,4 +30,4 @@ node_modules
 .lock-wscript
 
 dist/
-*.sqlite
+*.sqlite*
diff --git a/.travis.yml b/.travis.yml
index 75571ed..0379dac 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
 language: node_js
 node_js:
-  - 10
-  - 6
+  - 'node'
+  - 8
 sudo: false
 install: npm install
diff --git a/README.md b/README.md
index 1ca6ea1..4b5cfda 100644
--- a/README.md
+++ b/README.md
@@ -56,6 +56,8 @@ __Options:__
 - `id` (*optional*, default: `'id'`) - The name of the id field property.
 - `events` (*optional*) - A list of [custom service events](https://docs.feathersjs.com/api/events.html#custom-events) sent by this service
 - `paginate` (*optional*) - A [pagination object](https://docs.feathersjs.com/api/databases/common.html#pagination) containing a `default` and `max` page size
+- `multi` (*optional*) - Allow `create` with arrays and `update` and `remove` with `id` `null` to change multiple items. Can be `true` for all methods or an array of allowed methods (e.g. `[ 'remove', 'create' ]`)
+- `whitelist` (*optional*) - A list of additional query parameters to allow (e..g `[ '$regex', '$geoNear' ]`). Default is the supported `operators`
 
 ### `adapter.createQuery(query)`
 
@@ -281,8 +283,24 @@ app.service('mesages').hooks({
 });
 ```
 
+### Error handling
+
+As of version 4.0.0 `feathers-knex` only throws [Feathers Errors](https://docs.feathersjs.com/api/errors.html) with the message. On the server, the original error can be retrieved through a secure symbol via  `error[require('feathers-knex').ERROR]`
+
+```js
+const { ERROR } = require('feathers-knex');
+
+try {
+  await sequelizeService.doSomething();
+} catch(error) {
+  // error is a FeathersError with just the message
+  // Safely retrieve the Knex error
+  const knexError = error[ERROR];
+}
+```
+
 ## License
 
-Copyright (c) 2016
+Copyright (c) 2019
 
 Licensed under the [MIT license](LICENSE).
diff --git a/lib/error-handler.js b/lib/error-handler.js
index c46467c..0aefe04 100644
--- a/lib/error-handler.js
+++ b/lib/error-handler.js
@@ -1,28 +1,25 @@
 const errors = require('@feathersjs/errors');
+const ERROR = Symbol('feathers-knex/error');
 
 module.exports = function errorHandler (error) {
+  const { message } = error;
   let feathersError = error;
 
-  // TODO (EK): Map PG, Oracle, etc. errors
-
-  // NOTE: SQLState values from
-  // https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-error-sqlstates.html
-
   if (error.sqlState && error.sqlState.length) {
     // remove SQLSTATE marker (#) and pad/truncate SQLSTATE to 5 chars
-    let sqlState = ('00000' + error.sqlState.replace('#', '')).slice(-5);
+    const sqlState = ('00000' + error.sqlState.replace('#', '')).slice(-5);
 
     switch (sqlState.slice(0, 2)) {
       case '02':
-        feathersError = new errors.NotFound(error);
+        feathersError = new errors.NotFound(message);
         break;
       case '28':
-        feathersError = new errors.Forbidden(error);
+        feathersError = new errors.Forbidden(message);
         break;
       case '08':
       case '0A':
       case '0K':
-        feathersError = new errors.Unavailable(error);
+        feathersError = new errors.Unavailable(message);
         break;
       case '20':
       case '21':
@@ -33,44 +30,39 @@ module.exports = function errorHandler (error) {
       case '40':
       case '42':
       case '70':
-        feathersError = new errors.BadRequest(error);
+        feathersError = new errors.BadRequest(message);
         break;
       default:
-        feathersError = new errors.GeneralError(error);
+        feathersError = new errors.GeneralError(message);
     }
-  }
-
-  // NOTE (EK): Error codes taken from
-  // https://www.sqlite.org/c3ref/c_abort.html
-
-  if (error.code === 'SQLITE_ERROR') {
+  } else if (error.code === 'SQLITE_ERROR') {
+    // NOTE (EK): Error codes taken from
+    // https://www.sqlite.org/c3ref/c_abort.html
     switch (error.errno) {
       case 1:
       case 8:
       case 18:
       case 19:
       case 20:
-        feathersError = new errors.BadRequest(error);
+        feathersError = new errors.BadRequest(message);
         break;
       case 2:
-        feathersError = new errors.Unavailable(error);
+        feathersError = new errors.Unavailable(message);
         break;
       case 3:
       case 23:
-        feathersError = new errors.Forbidden(error);
+        feathersError = new errors.Forbidden(message);
         break;
       case 12:
-        feathersError = new errors.NotFound(error);
+        feathersError = new errors.NotFound(message);
         break;
       default:
-        feathersError = new errors.GeneralError(error);
+        feathersError = new errors.GeneralError(message);
         break;
     }
-  }
-
-  // NOTE: Error codes taken from
-  // https://www.postgresql.org/docs/9.6/static/errcodes-appendix.html
-  if (typeof error.code === 'string' && error.severity && error.routine) {
+  } else if (typeof error.code === 'string' && error.severity && error.routine) {
+    // NOTE: Error codes taken from
+    // https://www.postgresql.org/docs/9.6/static/errcodes-appendix.html
     // Omit query information
     const messages = error.message.split('-');
     error.message = messages[messages.length - 1];
@@ -78,21 +70,25 @@ module.exports = function errorHandler (error) {
     switch (error.code.slice(0, 2)) {
       case '22':
       case '23':
-        feathersError = new errors.BadRequest(error);
+        feathersError = new errors.BadRequest(message);
         break;
       case '28':
-        feathersError = new errors.Forbidden(error);
+        feathersError = new errors.Forbidden(message);
         break;
       case '3D':
       case '3F':
       case '42':
-        feathersError = new errors.Unprocessable(error);
+        feathersError = new errors.Unprocessable(message);
         break;
       default:
-        feathersError = new errors.GeneralError(error);
+        feathersError = new errors.GeneralError(message);
         break;
     }
+  } else if (!(error instanceof errors.FeathersError)) {
+    feathersError = new errors.GeneralError(message);
   }
 
+  feathersError[ERROR] = error;
+
   throw feathersError;
 };
diff --git a/lib/hooks.js b/lib/hooks.js
index 585e040..3ba50ca 100644
--- a/lib/hooks.js
+++ b/lib/hooks.js
@@ -1,10 +1,10 @@
 const debug = require('debug')('feathers-knex-transaction');
 
-const RollbackReason = function(error) {
+const RollbackReason = function (error) {
   this.error = error;
 };
 
-const start = (options) => {
+const start = () => {
   return hook => new Promise(resolve => {
     if (!hook.service.Model || typeof hook.service.Model.transaction !== 'function') {
       return resolve(hook);
@@ -33,10 +33,10 @@ const start = (options) => {
   });
 };
 
-const end = (options) => {
+const end = () => {
   return hook => {
     if (hook.params.transaction) {
-      const { promise, trx, id, count } = hook.params.transaction;
+      const { trx, id, count } = hook.params.transaction;
 
       if (count > 0) {
         hook.params.transaction.count -= 1;
@@ -46,7 +46,6 @@ const end = (options) => {
       hook.params.transaction = undefined;
 
       return trx.commit()
-        .then(() => promise)
         .then(() => debug('finished transaction %s with success', id))
         .then(() => hook);
     }
@@ -54,13 +53,12 @@ const end = (options) => {
   };
 };
 
-const rollback = (options) => {
+const rollback = () => {
   return hook => {
     if (hook.params.transaction) {
-      const { promise, trx, id } = hook.params.transaction;
+      const { trx, id } = hook.params.transaction;
       return trx.rollback(new RollbackReason(hook.error))
         .then(() => debug('rolling back transaction %s', id))
-        .then(() => promise)
         .then(() => hook);
     }
     return hook;
diff --git a/lib/index.js b/lib/index.js
index 15995fb..8d61986 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -1,5 +1,5 @@
-const Proto = require('uberproto');
-const { filterQuery } = require('@feathersjs/commons');
+const { _ } = require('@feathersjs/commons');
+const { AdapterService } = require('@feathersjs/adapter-commons');
 const isPlainObject = require('is-plain-object');
 const errors = require('@feathersjs/errors');
 
@@ -26,13 +26,9 @@ const OPERATORS = {
 };
 
 // Create the service.
-class Service {
+class Service extends AdapterService {
   constructor (options) {
-    if (!options) {
-      throw new Error('Knex options have to be provided');
-    }
-
-    if (!options.Model) {
+    if (!options || !options.Model) {
       throw new Error('You must provide a Model (the initialized knex object)');
     }
 
@@ -40,16 +36,27 @@ class Service {
       throw new Error('No table name specified.');
     }
 
-    this.knex = this.Model = options.Model;
-    this.id = options.id || 'id';
-    this.paginate = options.paginate || {};
+    const { whitelist = [] } = options;
+
+    super(Object.assign({
+      id: 'id',
+      whitelist: whitelist.concat([ '$like', '$ilike', '$and' ])
+    }, options));
+
     this.table = options.name;
     this.schema = options.schema;
-    this.events = options.events || [];
+  }
+
+  get Model () {
+    return this.options.Model;
+  }
+
+  get knex () {
+    return this.Model;
   }
 
   get fullName () {
-    return (this.schema) ? `${this.schema}.${this.table}` : this.table;
+    return this.schema ? `${this.schema}.${this.table}` : this.table;
   }
 
   // NOTE (EK): We need this method so that we return a new query
@@ -59,17 +66,13 @@ class Service {
     if (params.transaction) {
       const { trx, id } = params.transaction;
       debug('ran %s with transaction %s', fullName, id);
-      return (schema) ? trx.withSchema(schema).table(table) : trx(table);
+      return schema ? trx.withSchema(schema).table(table) : trx(table);
     }
-    return (schema) ? knex.withSchema(schema).table(table) : knex(table);
-  }
-
-  extend (obj) {
-    return Proto.extend(obj, this);
+    return schema ? knex.withSchema(schema).table(table) : knex(table);
   }
 
   init (opts, cb) {
-    const k = this.knex;
+    const k = this.Model;
     const { table, schema, fullName } = this;
 
     return k.schema.hasTable(fullName).then(exists => {
@@ -114,20 +117,24 @@ class Service {
         return query[method].call(query, column, value);
       }
 
-      return operator === '=' ? query.where(column, value) : query.where(column, operator, value);
+      return operator === '=' ? query.where(column, value)
+        : query.where(column, operator, value);
     });
+
+    return query;
   }
 
   createQuery (params = {}) {
     const { schema, table, id } = this;
-    const { filters, query } = filterQuery(params.query || {});
+    const { filters, query } = this.filterQuery(params);
     let q = this.db(params);
 
-    if (schema) { q = q.withSchema(schema).from(`${table} as ${table}`); }
+    if (schema) {
+      q = q.withSchema(schema).from(`${table} as ${table}`);
+    }
 
-    q = (filters.$select)
-      // $select uses a specific find syntax, so it has to come first.
-      ? q.select(...filters.$select.concat(`${table}.${id}`))
+    // $select uses a specific find syntax, so it has to come first.
+    q = filters.$select ? q.select(...filters.$select.concat(`${table}.${id}`))
       : q.select([`${table}.*`]);
 
     // build up the knex query out of the query params
@@ -143,8 +150,8 @@ class Service {
     return q;
   }
 
-  _find (params, count, getFilter = filterQuery) {
-    const { filters, query } = getFilter(params.query || {});
+  _find (params) {
+    const { filters, query, paginate } = this.filterQuery(params);
     const q = params.knex ? params.knex.clone() : this.createQuery(params);
 
     // Handle $limit
@@ -162,126 +169,96 @@ class Service {
       }
     }
 
-    let executeQuery = total => {
-      return q.then(data => {
-        return {
-          total: parseInt(total, 10),
-          limit: filters.$limit,
-          skip: filters.$skip || 0,
-          data
-        };
-      });
-    };
+    let executeQuery = total => q.then(data => {
+      return {
+        total: parseInt(total, 10),
+        limit: filters.$limit,
+        skip: filters.$skip || 0,
+        data
+      };
+    });
 
     if (filters.$limit === 0) {
-      executeQuery = total => {
-        return Promise.resolve({
-          total: parseInt(total, 10),
-          limit: filters.$limit,
-          skip: filters.$skip || 0,
-          data: []
-        });
-      };
+      executeQuery = total => Promise.resolve({
+        total: parseInt(total, 10),
+        limit: filters.$limit,
+        skip: filters.$skip || 0,
+        data: []
+      });
     }
 
-    if (count) {
-      let countQuery =
-        (params.knex || this.db(params))
-          .clone()
-          .clearSelect()
-          .clearOrder()
-          .count(`${this.table}.${this.id} as total`);
+    if (paginate && paginate.default) {
+      let countQuery = (params.knex || this.db(params))
+        .clone().clearSelect().clearOrder()
+        .count(`${this.table}.${this.id} as total`);
 
-      if (!params.knex) { this.knexify(countQuery, query); }
+      if (!params.knex) {
+        this.knexify(countQuery, query);
+      }
 
-      return countQuery.then(count => count[0] ? count[0].total : 0).then(executeQuery).catch(errorHandler);
+      return countQuery.then(count => count[0] ? count[0].total : 0)
+        .then(executeQuery)
+        .catch(errorHandler);
     }
 
-    return executeQuery().catch(errorHandler);
+    return executeQuery().then(page => page.data).catch(errorHandler);
   }
 
-  find (params) {
-    const paginate = (params && typeof params.paginate !== 'undefined') ? params.paginate : this.paginate;
-    const result = this._find(params, !!paginate.default,
-      query => filterQuery(query, paginate)
-    );
+  _findOrGet (id, params) {
+    const findParams = Object.assign({}, params, {
+      paginate: false,
+      query: Object.assign({}, params.query)
+    });
 
-    if (!paginate.default) {
-      return result.then(page => page.data);
+    if (id === null) {
+      return this._find(findParams);
     }
 
-    return result;
-  }
-
-  _get (id, params) {
-    const query = Object.assign({}, params.query);
+    findParams.query[this.id] = id;
 
-    query[this.id] = id;
-
-    return this._find(Object.assign({}, params, { query }))
-      .then(page => {
-        if (page.data.length !== 1) {
-          throw new errors.NotFound(`No record found for id '${id}'`);
-        }
-
-        return page.data[0];
-      }).catch(errorHandler);
+    return this._find(findParams);
   }
 
-  get (...args) {
-    return this._get(...args);
-  }
+  _get (id, params) {
+    return this._findOrGet(id, params).then(data => {
+      if (data.length !== 1) {
+        throw new errors.NotFound(`No record found for id '${id}'`);
+      }
 
-  _create (data, params) {
-    return this.db(params).insert(data, this.id).then(rows => {
-      const id = typeof data[this.id] !== 'undefined' ? data[this.id] : rows[0];
-      return this._get(id, params);
+      return data[0];
     }).catch(errorHandler);
   }
 
-  create (data, params) {
+  _create (data, params) {
     if (Array.isArray(data)) {
       return Promise.all(data.map(current => this._create(current, params)));
     }
 
-    return this._create(data, params);
-  }
+    return this.db(params).insert(data, this.id).then(rows => {
+      const id = data[this.id] !== undefined ? data[this.id] : rows[0];
 
-  patch (id, raw, params) {
-    const query = filterQuery(params.query || {}).query;
-    const data = Object.assign({}, raw);
-    const mapIds = page => page.data.map(current => current[this.id]);
+      return this._get(id, params);
+    }).catch(errorHandler);
+  }
 
+  _patch (id, raw, params) {
+    // Do not allow to patch the id
+    const data = _.omit(raw, this.id);
     // By default we will just query for the one id. For multi patch
     // we create a list of the ids of all items that will be changed
     // to re-query them after the update
-    const ids = id === null ? this._find(params)
-      .then(mapIds) : Promise.resolve([ id ]);
-
-    if (id !== null) {
-      query[this.id] = id;
-    }
-
-    const q = this.db(params);
-
-    this.knexify(q, query);
-
-    delete data[this.id];
-
-    return ids.then(idList => {
-      // Create a new query that re-queries all ids that
-      // were originally changed
+    return this._findOrGet(id, Object.assign({}, params, {
+      query: _.extend({}, params.query, { $select: [ this.id ] })
+    })).then(results => {
+      const idList = results.map(current => current[this.id]);
+      const query = { [this.id]: { $in: idList } };
+      const q = this.knexify(this.db(params), query);
       const findParams = Object.assign({}, params, {
-        query: {
-          [this.id]: { $in: idList },
-          $select: params.query && params.query.$select
-        }
+        query: Object.assign({}, params.query, query)
       });
 
       return q.update(data).then(() => {
-        return this._find(findParams).then(page => {
-          const items = page.data;
-
+        return this._find(findParams).then(items => {
           if (id !== null) {
             if (items.length === 1) {
               return items[0];
@@ -296,60 +273,40 @@ class Service {
     }).catch(errorHandler);
   }
 
-  update (id, data, params) {
-    if (Array.isArray(data)) {
-      return Promise.reject(errors.BadRequest('Not replacing multiple records. Did you mean `patch`?'));
-    }
-
-    // NOTE (EK): First fetch the old record so
-    // that we can fill any existing keys that the
-    // client isn't updating with null;
+  _update (id, data, params) {
     return this._get(id, params).then(oldData => {
-      let newObject = {};
-
-      for (var key of Object.keys(oldData)) {
-        if (data[key] === undefined) {
-          newObject[key] = null;
-        } else {
-          newObject[key] = data[key];
+      const newObject = Object.keys(oldData).reduce((result, key) => {
+        if (key !== this.id) { // We don't want the id field to be changed
+          result[key] = data[key] === undefined ? null : data[key];
         }
-      }
 
-      // NOTE (EK): Delete id field so we don't update it
-      delete newObject[this.id];
+        return result;
+      }, {});
 
-      return this.db(params).update(newObject).where(this.id, id).then(() => {
-        // NOTE (EK): Restore the id field so we can return it to the client
-        newObject[this.id] = id;
-        return newObject;
-      });
+      return this.db(params).update(newObject).where(this.id, id).then(() =>
+        this._get(id, params)
+      );
     }).catch(errorHandler);
   }
 
-  remove (id, params) {
-    params.query = Object.assign({}, params.query);
-
-    // NOTE (EK): First fetch the record so that we can return
-    // it when we delete it.
-    if (id !== null) {
-      params.query[this.id] = id;
-    }
-
-    return this._find(params).then(page => {
-      const items = page.data;
-      const { query } = filterQuery(params.query || {});
+  _remove (id, params) {
+    return this._findOrGet(id, params).then(items => {
+      const { query } = this.filterQuery(params);
       const q = this.db(params);
+      const idList = items.map(current => current[this.id]);
+
+      query[this.id] = { $in: idList };
 
       // build up the knex query out of the query params
       this.knexify(q, query);
 
-      return q.del().then(() => {
+      return q.del().then((...args) => {
         if (id !== null) {
           if (items.length === 1) {
             return items[0];
-          } else {
-            throw new errors.NotFound(`No record found for id '${id}'`);
           }
+
+          throw new errors.NotFound(`No record found for id '${id}'`);
         }
 
         return items;
@@ -362,5 +319,8 @@ module.exports = function init (options) {
   return new Service(options);
 };
 
-module.exports.hooks = hooks;
-module.exports.Service = Service;
+Object.assign(module.exports, {
+  hooks,
+  Service,
+  ERROR: errorHandler.ERROR
+});
diff --git a/package-lock.json b/package-lock.json
index 223b31e..124da01 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,69 +5,76 @@
   "requires": true,
   "dependencies": {
     "@babel/polyfill": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.0.0.tgz",
-      "integrity": "sha512-dnrMRkyyr74CRelJwvgnnSUDh2ge2NCTyHVwpOdvRMHtJUyxLtMAfhBN3s64pY41zdw0kgiLPh6S20eb1NcX6Q==",
+      "version": "7.2.5",
+      "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.2.5.tgz",
+      "integrity": "sha512-8Y/t3MWThtMLYr0YNC/Q76tqN1w30+b0uQMeFUYauG2UGTR19zyUtFrAzT23zNtBxPp+LbE5E/nwV/q/r3y6ug==",
       "dev": true,
       "requires": {
         "core-js": "^2.5.7",
-        "regenerator-runtime": "^0.11.1"
+        "regenerator-runtime": "^0.12.0"
+      },
+      "dependencies": {
+        "regenerator-runtime": {
+          "version": "0.12.1",
+          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
+          "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==",
+          "dev": true
+        }
+      }
+    },
+    "@feathersjs/adapter-commons": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/@feathersjs/adapter-commons/-/adapter-commons-1.0.6.tgz",
+      "integrity": "sha512-Qp5h0QP8CpHWBZttCV5vp8C8jrylSd7fqt2WlFwnWL8HLa1CVZOuKw77TaB4u7RPYOljFwp/3OxKDwl/WzVD7g==",
+      "requires": {
+        "@feathersjs/commons": "^4.0.0",
+        "@feathersjs/errors": "^3.3.5"
       }
     },
     "@feathersjs/commons": {
-      "version": "1.4.4",
-      "resolved": "https://registry.npmjs.org/@feathersjs/commons/-/commons-1.4.4.tgz",
-      "integrity": "sha512-ZPpzyZA3CPfoa9AuFv3BJUI/ubzaaXixp8T/pqeMFPT6DOaU/6oF7lz1RxwimzfJNna4gy/HByt0EoLSI3BKWg=="
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/@feathersjs/commons/-/commons-4.0.0.tgz",
+      "integrity": "sha512-hyCLse4RiNt7WLPQ0KSudjoVnwiRykhYzIZdtDon9i2usPaoYkFw/fEYZrkE5HVB+sUTwphZoZ1oOntRk1MShg=="
     },
     "@feathersjs/errors": {
-      "version": "3.3.4",
-      "resolved": "https://registry.npmjs.org/@feathersjs/errors/-/errors-3.3.4.tgz",
-      "integrity": "sha512-yA/HXSWgLiK4ngFslCHxcvnt+gek4fUhJcwpix9Z1jpTnCWW5WqtNxUfUqE1Fj8wKq0Y6VPSaQtE+RZcgryDQQ==",
+      "version": "3.3.5",
+      "resolved": "https://registry.npmjs.org/@feathersjs/errors/-/errors-3.3.5.tgz",
+      "integrity": "sha512-Nc4SxKJ7xQk5RZ3M68/Oj5c2uB/VrUATd4dLEdSGHf9j+qvajZVmBPjqDPYfY4IeTnYNhvwTmuyCulD0bCL4ZQ==",
       "requires": {
         "debug": "^4.0.0"
       }
     },
     "@feathersjs/express": {
-      "version": "1.2.7",
-      "resolved": "https://registry.npmjs.org/@feathersjs/express/-/express-1.2.7.tgz",
-      "integrity": "sha512-V+Tvg6X+GiANKwyUD6tYRnTjvFBgJhqVC5bqE/Wzd62PvJAn5p5yYZhWadT6b0Jirm2b5YA9kFNcPibb3MfWjA==",
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/@feathersjs/express/-/express-1.3.0.tgz",
+      "integrity": "sha512-IBjjY5x8iGQkZpAGQe7AYlEkhhwPOfx0wDf1Ben0EXwKFWLs+hkux9CJN2yQGRG61k9g8VVc79F4639FWrm3Mw==",
       "dev": true,
       "requires": {
-        "@feathersjs/commons": "^3.0.1",
-        "@feathersjs/errors": "^3.3.4",
+        "@feathersjs/commons": "^4.0.0",
+        "@feathersjs/errors": "^3.3.5",
         "debug": "^4.0.0",
         "express": "^4.16.2",
         "uberproto": "^2.0.0"
-      },
-      "dependencies": {
-        "@feathersjs/commons": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/@feathersjs/commons/-/commons-3.0.1.tgz",
-          "integrity": "sha512-wo2boFwbKqm53h/Wv2F+ggiTxSFOPaCupa6VHujJle/RZrox5On6zbaoO0B1yFZbj1tCJ6kT2IDpFg9StHL0oA==",
-          "dev": true
-        }
       }
     },
     "@feathersjs/feathers": {
-      "version": "3.2.3",
-      "resolved": "https://registry.npmjs.org/@feathersjs/feathers/-/feathers-3.2.3.tgz",
-      "integrity": "sha512-T51XlcE+HkAG7nfFMoqRU+bLxPhIYGygAiWQ0Fmc5vOsYtCZlj1AGjJWVL8iX7k2HQgFI2mdinWPoFb2rui03A==",
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/@feathersjs/feathers/-/feathers-3.3.0.tgz",
+      "integrity": "sha512-vi70lwECER0KNZGKZMOg7oPt7OAToRjfpqORc//TJkOR5EOXEH5eFvKvWbZ8wLyuLB3OFlv7iUoufFlMvG19DA==",
       "dev": true,
       "requires": {
-        "@feathersjs/commons": "^3.0.1",
+        "@feathersjs/commons": "^4.0.0",
         "debug": "^4.0.0",
         "events": "^3.0.0",
         "uberproto": "^2.0.2"
-      },
-      "dependencies": {
-        "@feathersjs/commons": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/@feathersjs/commons/-/commons-3.0.1.tgz",
-          "integrity": "sha512-wo2boFwbKqm53h/Wv2F+ggiTxSFOPaCupa6VHujJle/RZrox5On6zbaoO0B1yFZbj1tCJ6kT2IDpFg9StHL0oA==",
-          "dev": true
-        }
       }
     },
+    "@types/bluebird": {
+      "version": "3.5.25",
+      "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.25.tgz",
+      "integrity": "sha512-yfhIBix+AIFTmYGtkC0Bi+XGjSkOINykqKvO/Wqdz/DuXlAKK7HmhLAXdPIGsV4xzKcL3ev/zYc4yLNo+OvGaw==",
+      "dev": true
+    },
     "abbrev": {
       "version": "1.0.9",
       "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz",
@@ -85,49 +92,38 @@
       }
     },
     "acorn": {
-      "version": "5.7.3",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
-      "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
+      "version": "6.0.4",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz",
+      "integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==",
       "dev": true
     },
     "acorn-jsx": {
-      "version": "3.0.1",
-      "resolved": "http://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
-      "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
-      "dev": true,
-      "requires": {
-        "acorn": "^3.0.4"
-      },
-      "dependencies": {
-        "acorn": {
-          "version": "3.3.0",
-          "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
-          "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
-          "dev": true
-        }
-      }
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
+      "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==",
+      "dev": true
     },
     "ajv": {
-      "version": "5.5.2",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
-      "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+      "version": "6.6.2",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz",
+      "integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==",
       "dev": true,
       "requires": {
-        "co": "^4.6.0",
-        "fast-deep-equal": "^1.0.0",
+        "fast-deep-equal": "^2.0.1",
         "fast-json-stable-stringify": "^2.0.0",
-        "json-schema-traverse": "^0.3.0"
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
       }
     },
     "ajv-keywords": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
-      "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
+      "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=",
       "dev": true
     },
     "ansi-escapes": {
       "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
+      "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
       "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==",
       "dev": true
     },
@@ -203,7 +199,7 @@
     },
     "array-flatten": {
       "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+      "resolved": "http://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
       "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
       "dev": true
     },
@@ -223,33 +219,12 @@
       "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==",
       "dev": true
     },
-    "array-union": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
-      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
-      "dev": true,
-      "requires": {
-        "array-uniq": "^1.0.1"
-      }
-    },
-    "array-uniq": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
-      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
-      "dev": true
-    },
     "array-unique": {
       "version": "0.3.2",
       "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
       "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
       "dev": true
     },
-    "arrify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
-      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
-      "dev": true
-    },
     "asn1": {
       "version": "0.2.4",
       "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
@@ -489,9 +464,9 @@
       }
     },
     "bluebird": {
-      "version": "3.5.2",
-      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz",
-      "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==",
+      "version": "3.5.3",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
+      "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==",
       "dev": true
     },
     "body-parser": {
@@ -574,12 +549,6 @@
       "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
       "dev": true
     },
-    "buffer-from": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
-      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
-      "dev": true
-    },
     "builtin-modules": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
@@ -620,7 +589,7 @@
     },
     "callsites": {
       "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
+      "resolved": "http://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
       "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
       "dev": true
     },
@@ -728,12 +697,6 @@
       "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
       "dev": true
     },
-    "co": {
-      "version": "4.6.0",
-      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
-      "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
-      "dev": true
-    },
     "code-point-at": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
@@ -793,18 +756,6 @@
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
       "dev": true
     },
-    "concat-stream": {
-      "version": "1.6.2",
-      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
-      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
-      "dev": true,
-      "requires": {
-        "buffer-from": "^1.0.0",
-        "inherits": "^2.0.3",
-        "readable-stream": "^2.2.2",
-        "typedarray": "^0.0.6"
-      }
-    },
     "console-control-strings": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
@@ -819,7 +770,7 @@
     },
     "content-disposition": {
       "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+      "resolved": "http://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
       "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=",
       "dev": true
     },
@@ -848,9 +799,9 @@
       "dev": true
     },
     "core-js": {
-      "version": "2.5.7",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
-      "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==",
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.1.tgz",
+      "integrity": "sha512-L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg==",
       "dev": true
     },
     "core-util-is": {
@@ -860,12 +811,14 @@
       "dev": true
     },
     "cross-spawn": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
-      "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+      "version": "6.0.5",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
       "dev": true,
       "requires": {
-        "lru-cache": "^4.0.1",
+        "nice-try": "^1.0.4",
+        "path-key": "^2.0.1",
+        "semver": "^5.5.0",
         "shebang-command": "^1.2.0",
         "which": "^1.2.9"
       }
@@ -880,16 +833,16 @@
       }
     },
     "debug": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
-      "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+      "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
       "requires": {
         "ms": "^2.1.1"
       }
     },
     "debug-log": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz",
+      "resolved": "http://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz",
       "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=",
       "dev": true
     },
@@ -980,32 +933,25 @@
       }
     },
     "deglob": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.1.tgz",
-      "integrity": "sha512-2kjwuGGonL7gWE1XU4Fv79+vVzpoQCl0V+boMwWtOQJV2AGDabCwez++nB1Nli/8BabAfZQ/UuHPlp6AymKdWw==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/deglob/-/deglob-3.1.0.tgz",
+      "integrity": "sha512-al10l5QAYaM/PeuXkAr1Y9AQz0LCtWsnJG23pIgh44hDxHFOj36l6qvhfjnIWBYwZOqM1fXUFV9tkjL7JPdGvw==",
       "dev": true,
       "requires": {
         "find-root": "^1.0.0",
         "glob": "^7.0.5",
-        "ignore": "^3.0.9",
+        "ignore": "^5.0.0",
         "pkg-config": "^1.1.0",
         "run-parallel": "^1.1.2",
         "uniq": "^1.0.1"
-      }
-    },
-    "del": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
-      "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
-      "dev": true,
-      "requires": {
-        "globby": "^5.0.0",
-        "is-path-cwd": "^1.0.0",
-        "is-path-in-cwd": "^1.0.0",
-        "object-assign": "^4.0.1",
-        "pify": "^2.0.0",
-        "pinkie-promise": "^2.0.0",
-        "rimraf": "^2.2.8"
+      },
+      "dependencies": {
+        "ignore": {
+          "version": "5.0.4",
+          "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.0.4.tgz",
+          "integrity": "sha512-WLsTMEhsQuXpCiG173+f3aymI43SXa+fB1rSfbzyP4GkPP+ZFVuO0/3sFUGNBtifisPeDcl/uD/Y2NxZ7xFq4g==",
+          "dev": true
+        }
       }
     },
     "delayed-stream": {
@@ -1123,6 +1069,12 @@
         "is-symbol": "^1.0.2"
       }
     },
+    "es6-object-assign": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
+      "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=",
+      "dev": true
+    },
     "escape-html": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -1136,48 +1088,49 @@
       "dev": true
     },
     "eslint": {
-      "version": "4.18.2",
-      "resolved": "http://registry.npmjs.org/eslint/-/eslint-4.18.2.tgz",
-      "integrity": "sha512-qy4i3wODqKMYfz9LUI8N2qYDkHkoieTbiHpMrYUI/WbjhXJQr7lI4VngixTgaG+yHX+NBCv7nW4hA0ShbvaNKw==",
+      "version": "5.4.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.4.0.tgz",
+      "integrity": "sha512-UIpL91XGex3qtL6qwyCQJar2j3osKxK9e3ano3OcGEIRM4oWIpCkDg9x95AXEC2wMs7PnxzOkPZ2gq+tsMS9yg==",
       "dev": true,
       "requires": {
-        "ajv": "^5.3.0",
-        "babel-code-frame": "^6.22.0",
+        "ajv": "^6.5.0",
+        "babel-code-frame": "^6.26.0",
         "chalk": "^2.1.0",
-        "concat-stream": "^1.6.0",
-        "cross-spawn": "^5.1.0",
+        "cross-spawn": "^6.0.5",
         "debug": "^3.1.0",
         "doctrine": "^2.1.0",
-        "eslint-scope": "^3.7.1",
+        "eslint-scope": "^4.0.0",
+        "eslint-utils": "^1.3.1",
         "eslint-visitor-keys": "^1.0.0",
-        "espree": "^3.5.2",
-        "esquery": "^1.0.0",
+        "espree": "^4.0.0",
+        "esquery": "^1.0.1",
         "esutils": "^2.0.2",
         "file-entry-cache": "^2.0.0",
         "functional-red-black-tree": "^1.0.1",
         "glob": "^7.1.2",
-        "globals": "^11.0.1",
-        "ignore": "^3.3.3",
+        "globals": "^11.7.0",
+        "ignore": "^4.0.2",
         "imurmurhash": "^0.1.4",
-        "inquirer": "^3.0.6",
-        "is-resolvable": "^1.0.0",
-        "js-yaml": "^3.9.1",
+        "inquirer": "^5.2.0",
+        "is-resolvable": "^1.1.0",
+        "js-yaml": "^3.11.0",
         "json-stable-stringify-without-jsonify": "^1.0.1",
         "levn": "^0.3.0",
-        "lodash": "^4.17.4",
-        "minimatch": "^3.0.2",
+        "lodash": "^4.17.5",
+        "minimatch": "^3.0.4",
         "mkdirp": "^0.5.1",
         "natural-compare": "^1.4.0",
         "optionator": "^0.8.2",
         "path-is-inside": "^1.0.2",
         "pluralize": "^7.0.0",
         "progress": "^2.0.0",
+        "regexpp": "^2.0.0",
         "require-uncached": "^1.0.3",
-        "semver": "^5.3.0",
+        "semver": "^5.5.0",
         "strip-ansi": "^4.0.0",
-        "strip-json-comments": "~2.0.1",
-        "table": "4.0.2",
-        "text-table": "~0.2.0"
+        "strip-json-comments": "^2.0.1",
+        "table": "^4.0.3",
+        "text-table": "^0.2.0"
       },
       "dependencies": {
         "ansi-regex": {
@@ -1216,9 +1169,9 @@
           }
         },
         "globals": {
-          "version": "11.8.0",
-          "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz",
-          "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==",
+          "version": "11.9.0",
+          "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz",
+          "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==",
           "dev": true
         },
         "has-flag": {
@@ -1248,21 +1201,21 @@
       }
     },
     "eslint-config-semistandard": {
-      "version": "12.0.1",
-      "resolved": "https://registry.npmjs.org/eslint-config-semistandard/-/eslint-config-semistandard-12.0.1.tgz",
-      "integrity": "sha512-4zaPW5uRFasf2uRZkE19Y+W84KBV3q+oyWYOsgUN+5DQXE5HCsh7ZxeWDXxozk7NPycGm0kXcsJzLe5GZ1jCeg==",
+      "version": "13.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-config-semistandard/-/eslint-config-semistandard-13.0.0.tgz",
+      "integrity": "sha512-ZuImKnf/9LeZjr6dtRJ0zEdQbjBwXu0PJR3wXJXoQeMooICMrYPyD70O1tIA9Ng+wutgLjB7UXvZOKYPvzHg+w==",
       "dev": true
     },
     "eslint-config-standard": {
-      "version": "11.0.0",
-      "resolved": "http://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz",
-      "integrity": "sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw==",
+      "version": "12.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz",
+      "integrity": "sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ==",
       "dev": true
     },
     "eslint-config-standard-jsx": {
-      "version": "5.0.0",
-      "resolved": "http://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-5.0.0.tgz",
-      "integrity": "sha512-rLToPAEqLMPBfWnYTu6xRhm2OWziS2n40QFqJ8jAM8NSVzeVKTa3nclhsU4DpPJQRY60F34Oo1wi/71PN/eITg==",
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-6.0.2.tgz",
+      "integrity": "sha512-D+YWAoXw+2GIdbMBRAzWwr1ZtvnSf4n4yL0gKGg7ShUOGXkSOLerI17K4F6LdQMJPNMoWYqepzQD/fKY+tXNSg==",
       "dev": true
     },
     "eslint-import-resolver-node": {
@@ -1319,22 +1272,32 @@
         }
       }
     },
+    "eslint-plugin-es": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz",
+      "integrity": "sha512-XfFmgFdIUDgvaRAlaXUkxrRg5JSADoRC8IkKLc/cISeR3yHVMefFHQZpcyXXEUUPHfy5DwviBcrfqlyqEwlQVw==",
+      "dev": true,
+      "requires": {
+        "eslint-utils": "^1.3.0",
+        "regexpp": "^2.0.1"
+      }
+    },
     "eslint-plugin-import": {
-      "version": "2.8.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz",
-      "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==",
+      "version": "2.14.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz",
+      "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==",
       "dev": true,
       "requires": {
-        "builtin-modules": "^1.1.1",
         "contains-path": "^0.1.0",
         "debug": "^2.6.8",
         "doctrine": "1.5.0",
         "eslint-import-resolver-node": "^0.3.1",
-        "eslint-module-utils": "^2.1.1",
+        "eslint-module-utils": "^2.2.0",
         "has": "^1.0.1",
-        "lodash.cond": "^4.3.0",
+        "lodash": "^4.17.4",
         "minimatch": "^3.0.3",
-        "read-pkg-up": "^2.0.0"
+        "read-pkg-up": "^2.0.0",
+        "resolve": "^1.6.0"
       },
       "dependencies": {
         "debug": {
@@ -1348,7 +1311,7 @@
         },
         "doctrine": {
           "version": "1.5.0",
-          "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
+          "resolved": "http://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
           "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
           "dev": true,
           "requires": {
@@ -1365,51 +1328,60 @@
       }
     },
     "eslint-plugin-node": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz",
-      "integrity": "sha512-Q/Cc2sW1OAISDS+Ji6lZS2KV4b7ueA/WydVWd1BECTQwVvfQy5JAi3glhINoKzoMnfnuRgNP+ZWKrGAbp3QDxw==",
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-7.0.1.tgz",
+      "integrity": "sha512-lfVw3TEqThwq0j2Ba/Ckn2ABdwmL5dkOgAux1rvOk6CO7A6yGyPI2+zIxN6FyNkp1X1X/BSvKOceD6mBWSj4Yw==",
       "dev": true,
       "requires": {
-        "ignore": "^3.3.6",
+        "eslint-plugin-es": "^1.3.1",
+        "eslint-utils": "^1.3.1",
+        "ignore": "^4.0.2",
         "minimatch": "^3.0.4",
-        "resolve": "^1.3.3",
-        "semver": "^5.4.1"
+        "resolve": "^1.8.1",
+        "semver": "^5.5.0"
       }
     },
     "eslint-plugin-promise": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz",
-      "integrity": "sha512-YQzM6TLTlApAr7Li8vWKR+K3WghjwKcYzY0d2roWap4SLK+kzuagJX/leTetIDWsFcTFnKNJXWupDCD6aZkP2Q==",
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz",
+      "integrity": "sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg==",
       "dev": true
     },
     "eslint-plugin-react": {
-      "version": "7.6.1",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.6.1.tgz",
-      "integrity": "sha512-30aMOHWX/DOaaLJVBHz6RMvYM2qy5GH63+y2PLFdIrYe4YLtODFmT3N1YA7ZqUnaBweVbedr4K4cqxOlWAPjIw==",
+      "version": "7.11.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz",
+      "integrity": "sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw==",
       "dev": true,
       "requires": {
-        "doctrine": "^2.0.2",
-        "has": "^1.0.1",
+        "array-includes": "^3.0.3",
+        "doctrine": "^2.1.0",
+        "has": "^1.0.3",
         "jsx-ast-utils": "^2.0.1",
-        "prop-types": "^15.6.0"
+        "prop-types": "^15.6.2"
       }
     },
     "eslint-plugin-standard": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz",
-      "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz",
+      "integrity": "sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA==",
       "dev": true
     },
     "eslint-scope": {
-      "version": "3.7.3",
-      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz",
-      "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz",
+      "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==",
       "dev": true,
       "requires": {
         "esrecurse": "^4.1.0",
         "estraverse": "^4.1.1"
       }
     },
+    "eslint-utils": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
+      "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==",
+      "dev": true
+    },
     "eslint-visitor-keys": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
@@ -1417,13 +1389,14 @@
       "dev": true
     },
     "espree": {
-      "version": "3.5.4",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
-      "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz",
+      "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==",
       "dev": true,
       "requires": {
-        "acorn": "^5.5.0",
-        "acorn-jsx": "^3.0.0"
+        "acorn": "^6.0.2",
+        "acorn-jsx": "^5.0.0",
+        "eslint-visitor-keys": "^1.0.0"
       }
     },
     "esprima": {
@@ -1698,9 +1671,9 @@
       "dev": true
     },
     "fast-deep-equal": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
-      "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
       "dev": true
     },
     "fast-json-stable-stringify": {
@@ -1715,53 +1688,6 @@
       "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
       "dev": true
     },
-    "feathers-service-tests": {
-      "version": "0.10.2",
-      "resolved": "https://registry.npmjs.org/feathers-service-tests/-/feathers-service-tests-0.10.2.tgz",
-      "integrity": "sha1-Pdt/ZoiZqGD5UH8OlU4jY4PlKQQ=",
-      "dev": true,
-      "requires": {
-        "chai": "^3.4.0",
-        "request": "^2.75.0",
-        "request-promise": "^4.0.0"
-      },
-      "dependencies": {
-        "chai": {
-          "version": "3.5.0",
-          "resolved": "http://registry.npmjs.org/chai/-/chai-3.5.0.tgz",
-          "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=",
-          "dev": true,
-          "requires": {
-            "assertion-error": "^1.0.1",
-            "deep-eql": "^0.1.3",
-            "type-detect": "^1.0.0"
-          }
-        },
-        "deep-eql": {
-          "version": "0.1.3",
-          "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz",
-          "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=",
-          "dev": true,
-          "requires": {
-            "type-detect": "0.1.1"
-          },
-          "dependencies": {
-            "type-detect": {
-              "version": "0.1.1",
-              "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz",
-              "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=",
-              "dev": true
-            }
-          }
-        },
-        "type-detect": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz",
-          "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=",
-          "dev": true
-        }
-      }
-    },
     "figures": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
@@ -1875,9 +1801,9 @@
       }
     },
     "fined": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz",
-      "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.1.tgz",
+      "integrity": "sha512-jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g==",
       "dev": true,
       "requires": {
         "expand-tilde": "^2.0.2",
@@ -1888,20 +1814,20 @@
       }
     },
     "flagged-respawn": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz",
-      "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz",
+      "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==",
       "dev": true
     },
     "flat-cache": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
-      "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
+      "version": "1.3.4",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz",
+      "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==",
       "dev": true,
       "requires": {
         "circular-json": "^0.3.1",
-        "del": "^2.0.2",
         "graceful-fs": "^4.1.2",
+        "rimraf": "~2.6.2",
         "write": "^0.2.1"
       }
     },
@@ -1927,25 +1853,14 @@
       "dev": true
     },
     "form-data": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
-      "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+      "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
       "dev": true,
       "requires": {
         "asynckit": "^0.4.0",
-        "combined-stream": "1.0.6",
+        "combined-stream": "^1.0.6",
         "mime-types": "^2.1.12"
-      },
-      "dependencies": {
-        "combined-stream": {
-          "version": "1.0.6",
-          "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
-          "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
-          "dev": true,
-          "requires": {
-            "delayed-stream": "~1.0.0"
-          }
-        }
       }
     },
     "forwarded": {
@@ -2023,7 +1938,7 @@
         },
         "string-width": {
           "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+          "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
           "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
           "dev": true,
           "requires": {
@@ -2105,24 +2020,10 @@
       "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
       "dev": true
     },
-    "globby": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
-      "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
-      "dev": true,
-      "requires": {
-        "array-union": "^1.0.1",
-        "arrify": "^1.0.0",
-        "glob": "^7.0.3",
-        "object-assign": "^4.0.1",
-        "pify": "^2.0.0",
-        "pinkie-promise": "^2.0.0"
-      }
-    },
     "graceful-fs": {
-      "version": "4.1.11",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
-      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+      "version": "4.1.15",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
+      "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
       "dev": true
     },
     "growl": {
@@ -2167,12 +2068,12 @@
       "dev": true
     },
     "har-validator": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz",
-      "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==",
+      "version": "5.1.3",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+      "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
       "dev": true,
       "requires": {
-        "ajv": "^5.3.0",
+        "ajv": "^6.5.5",
         "har-schema": "^2.0.0"
       }
     },
@@ -2298,9 +2199,9 @@
       }
     },
     "ignore": {
-      "version": "3.3.10",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
-      "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+      "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
       "dev": true
     },
     "ignore-walk": {
@@ -2341,22 +2242,21 @@
       "dev": true
     },
     "inquirer": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
-      "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
+      "version": "5.2.0",
+      "resolved": "http://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz",
+      "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==",
       "dev": true,
       "requires": {
         "ansi-escapes": "^3.0.0",
         "chalk": "^2.0.0",
         "cli-cursor": "^2.1.0",
         "cli-width": "^2.0.0",
-        "external-editor": "^2.0.4",
+        "external-editor": "^2.1.0",
         "figures": "^2.0.0",
         "lodash": "^4.3.0",
         "mute-stream": "0.0.7",
         "run-async": "^2.2.0",
-        "rx-lite": "^4.0.8",
-        "rx-lite-aggregates": "^4.0.8",
+        "rxjs": "^5.5.2",
         "string-width": "^2.1.0",
         "strip-ansi": "^4.0.0",
         "through": "^2.3.6"
@@ -2447,7 +2347,7 @@
     },
     "is-accessor-descriptor": {
       "version": "0.1.6",
-      "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+      "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
       "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
       "dev": true,
       "requires": {
@@ -2494,7 +2394,7 @@
     },
     "is-data-descriptor": {
       "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+      "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
       "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
       "dev": true,
       "requires": {
@@ -2593,30 +2493,6 @@
         }
       }
     },
-    "is-path-cwd": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
-      "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
-      "dev": true
-    },
-    "is-path-in-cwd": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
-      "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
-      "dev": true,
-      "requires": {
-        "is-path-inside": "^1.0.0"
-      }
-    },
-    "is-path-inside": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
-      "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
-      "dev": true,
-      "requires": {
-        "path-is-inside": "^1.0.1"
-      }
-    },
     "is-plain-object": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@@ -2870,7 +2746,7 @@
     },
     "jsesc": {
       "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
+      "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
       "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
       "dev": true
     },
@@ -2887,9 +2763,9 @@
       "dev": true
     },
     "json-schema-traverse": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
-      "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
       "dev": true
     },
     "json-stable-stringify-without-jsonify": {
@@ -2932,12 +2808,13 @@
       "dev": true
     },
     "knex": {
-      "version": "0.16.0",
-      "resolved": "https://registry.npmjs.org/knex/-/knex-0.16.0.tgz",
-      "integrity": "sha512-+TiL02P00GEmdwpKRfgOaRGaI29KeTcvAT7os1jeWMPMnzu8g/C3O4CZ1LXtLo5V1oatUzJcPKBqWATPgS20ng==",
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/knex/-/knex-0.16.3.tgz",
+      "integrity": "sha512-jGTOBW8b7exaBPfCKJSlv5q320IvWw9hEdtnURtbb0k3HusfZrR4UYiEewem8Nl7VqJILoCj99SjCK3W54UNPg==",
       "dev": true,
       "requires": {
         "@babel/polyfill": "^7.0.0",
+        "@types/bluebird": "^3.5.25",
         "bluebird": "^3.5.3",
         "chalk": "2.4.1",
         "commander": "^2.19.0",
@@ -2964,12 +2841,6 @@
             "color-convert": "^1.9.0"
           }
         },
-        "bluebird": {
-          "version": "3.5.3",
-          "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
-          "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==",
-          "dev": true
-        },
         "chalk": {
           "version": "2.4.1",
           "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
@@ -2987,6 +2858,15 @@
           "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
           "dev": true
         },
+        "debug": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
+          "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
         "has-flag": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -3080,12 +2960,6 @@
       "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
       "dev": true
     },
-    "lodash.cond": {
-      "version": "4.5.2",
-      "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz",
-      "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=",
-      "dev": true
-    },
     "loose-envify": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -3095,16 +2969,6 @@
         "js-tokens": "^3.0.0 || ^4.0.0"
       }
     },
-    "lru-cache": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
-      "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
-      "dev": true,
-      "requires": {
-        "pseudomap": "^1.0.2",
-        "yallist": "^2.1.2"
-      }
-    },
     "make-iterator": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz",
@@ -3131,7 +2995,7 @@
     },
     "media-typer": {
       "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+      "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
       "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
       "dev": true
     },
@@ -3175,18 +3039,18 @@
       "dev": true
     },
     "mime-db": {
-      "version": "1.36.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz",
-      "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==",
+      "version": "1.37.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
+      "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==",
       "dev": true
     },
     "mime-types": {
-      "version": "2.1.20",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
-      "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==",
+      "version": "2.1.21",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz",
+      "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==",
       "dev": true,
       "requires": {
-        "mime-db": "~1.36.0"
+        "mime-db": "~1.37.0"
       }
     },
     "mimic-fn": {
@@ -3211,27 +3075,19 @@
       "dev": true
     },
     "minipass": {
-      "version": "2.3.4",
-      "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.4.tgz",
-      "integrity": "sha512-mlouk1OHlaUE8Odt1drMtG1bAJA4ZA6B/ehysgV0LUIrDHdKgo1KorZq3pK0b/7Z7LJIQ12MNM6aC+Tn6lUZ5w==",
+      "version": "2.3.5",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz",
+      "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
       "dev": true,
       "requires": {
         "safe-buffer": "^5.1.2",
         "yallist": "^3.0.0"
-      },
-      "dependencies": {
-        "yallist": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz",
-          "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=",
-          "dev": true
-        }
       }
     },
     "minizlib": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.1.tgz",
-      "integrity": "sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz",
+      "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==",
       "dev": true,
       "requires": {
         "minipass": "^2.2.1"
@@ -3414,6 +3270,12 @@
       "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
       "dev": true
     },
+    "nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+      "dev": true
+    },
     "node-pre-gyp": {
       "version": "0.10.3",
       "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz",
@@ -3649,13 +3511,13 @@
     },
     "os-homedir": {
       "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+      "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
       "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
       "dev": true
     },
     "os-tmpdir": {
       "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
       "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
       "dev": true
     },
@@ -3742,7 +3604,7 @@
     },
     "path-is-absolute": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
       "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
       "dev": true
     },
@@ -3752,6 +3614,12 @@
       "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
       "dev": true
     },
+    "path-key": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+      "dev": true
+    },
     "path-parse": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
@@ -3808,7 +3676,7 @@
     },
     "pify": {
       "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+      "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
       "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
       "dev": true
     },
@@ -3927,9 +3795,9 @@
       "dev": true
     },
     "progress": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
-      "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=",
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+      "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
       "dev": true
     },
     "prop-types": {
@@ -3952,22 +3820,16 @@
         "ipaddr.js": "1.8.0"
       }
     },
-    "pseudomap": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
-      "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
-      "dev": true
-    },
     "psl": {
-      "version": "1.1.29",
-      "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
-      "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==",
+      "version": "1.1.31",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
+      "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==",
       "dev": true
     },
     "punycode": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
-      "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
       "dev": true
     },
     "qs": {
@@ -4086,6 +3948,12 @@
         "safe-regex": "^1.1.0"
       }
     },
+    "regexpp": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
+      "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
+      "dev": true
+    },
     "repeat-element": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
@@ -4135,30 +4003,9 @@
         "uuid": "^3.3.2"
       }
     },
-    "request-promise": {
-      "version": "4.2.2",
-      "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.2.tgz",
-      "integrity": "sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ=",
-      "dev": true,
-      "requires": {
-        "bluebird": "^3.5.0",
-        "request-promise-core": "1.1.1",
-        "stealthy-require": "^1.1.0",
-        "tough-cookie": ">=2.3.3"
-      }
-    },
-    "request-promise-core": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz",
-      "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=",
-      "dev": true,
-      "requires": {
-        "lodash": "^4.13.1"
-      }
-    },
     "require-uncached": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
+      "resolved": "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
       "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
       "dev": true,
       "requires": {
@@ -4167,12 +4014,12 @@
       }
     },
     "resolve": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
-      "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz",
+      "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==",
       "dev": true,
       "requires": {
-        "path-parse": "^1.0.5"
+        "path-parse": "^1.0.6"
       }
     },
     "resolve-dir": {
@@ -4237,19 +4084,13 @@
       "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==",
       "dev": true
     },
-    "rx-lite": {
-      "version": "4.0.8",
-      "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
-      "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
-      "dev": true
-    },
-    "rx-lite-aggregates": {
-      "version": "4.0.8",
-      "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
-      "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
+    "rxjs": {
+      "version": "5.5.12",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz",
+      "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==",
       "dev": true,
       "requires": {
-        "rx-lite": "*"
+        "symbol-observable": "1.0.1"
       }
     },
     "safe-buffer": {
@@ -4260,7 +4101,7 @@
     },
     "safe-regex": {
       "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+      "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
       "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
       "dev": true,
       "requires": {
@@ -4280,21 +4121,21 @@
       "dev": true
     },
     "semistandard": {
-      "version": "12.0.1",
-      "resolved": "https://registry.npmjs.org/semistandard/-/semistandard-12.0.1.tgz",
-      "integrity": "sha512-+FBRXBCi8GC1Nivc4ruw2KXER31bE1lrNyESo7prn2Sv9I9+H/Iqpt0NOtlV/GUxq34AgJwJViBUpA3/PUGqOw==",
+      "version": "13.0.1",
+      "resolved": "https://registry.npmjs.org/semistandard/-/semistandard-13.0.1.tgz",
+      "integrity": "sha512-2GkuX4BsoMEYoufJYRz8/ERbYDfgOO3yP29IBaoXtxl202azlkV1MsFyoSFiM6GBUfL7MSUxSy38KfM9oDAE2g==",
       "dev": true,
       "requires": {
-        "eslint": "~4.18.0",
-        "eslint-config-semistandard": "12.0.1",
-        "eslint-config-standard": "11.0.0",
-        "eslint-config-standard-jsx": "5.0.0",
-        "eslint-plugin-import": "~2.8.0",
-        "eslint-plugin-node": "~6.0.0",
-        "eslint-plugin-promise": "~3.6.0",
-        "eslint-plugin-react": "~7.6.1",
-        "eslint-plugin-standard": "~3.0.1",
-        "standard-engine": "~8.0.0"
+        "eslint": "~5.4.0",
+        "eslint-config-semistandard": "13.0.0",
+        "eslint-config-standard": "12.0.0",
+        "eslint-config-standard-jsx": "6.0.2",
+        "eslint-plugin-import": "~2.14.0",
+        "eslint-plugin-node": "~7.0.1",
+        "eslint-plugin-promise": "~4.0.0",
+        "eslint-plugin-react": "~7.11.1",
+        "eslint-plugin-standard": "~4.0.0",
+        "standard-engine": "~10.0.0"
       }
     },
     "semver": {
@@ -4403,6 +4244,36 @@
       "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
       "dev": true
     },
+    "shelljs": {
+      "version": "0.8.3",
+      "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz",
+      "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.0.0",
+        "interpret": "^1.0.0",
+        "rechoir": "^0.6.2"
+      }
+    },
+    "shx": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.2.tgz",
+      "integrity": "sha512-aS0mWtW3T2sHAenrSrip2XGv39O9dXIFUqxAEWHEOS1ePtGIBavdPJY1kE2IHl14V/4iCbUiNDPGdyYTtmhSoA==",
+      "dev": true,
+      "requires": {
+        "es6-object-assign": "^1.0.3",
+        "minimist": "^1.2.0",
+        "shelljs": "^0.8.1"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true
+        }
+      }
+    },
     "signal-exit": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
@@ -4566,9 +4437,9 @@
       "dev": true
     },
     "spdx-correct": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz",
-      "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
+      "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
       "dev": true,
       "requires": {
         "spdx-expression-parse": "^3.0.0",
@@ -4592,9 +4463,9 @@
       }
     },
     "spdx-license-ids": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz",
-      "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz",
+      "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==",
       "dev": true
     },
     "split-string": {
@@ -4608,14 +4479,14 @@
     },
     "sprintf-js": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
       "dev": true
     },
     "sqlite3": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.0.2.tgz",
-      "integrity": "sha512-51ferIRwYOhzUEtogqOa/y9supADlAht98bF/gbIi6WkzRJX6Yioldxbzj1MV4yV+LgdKD/kkHwFTeFXOG4htA==",
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.0.4.tgz",
+      "integrity": "sha512-CO8vZMyUXBPC+E3iXOCc7Tz2pAdq5BWfLcQmOokCOZW5S5sZ/paijiPOCdvzpdP83RroWHYa5xYlVqCxSqpnQg==",
       "dev": true,
       "requires": {
         "nan": "~2.10.0",
@@ -4624,9 +4495,9 @@
       }
     },
     "sshpk": {
-      "version": "1.15.1",
-      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz",
-      "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==",
+      "version": "1.16.0",
+      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz",
+      "integrity": "sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==",
       "dev": true,
       "requires": {
         "asn1": "~0.2.3",
@@ -4641,12 +4512,12 @@
       }
     },
     "standard-engine": {
-      "version": "8.0.1",
-      "resolved": "http://registry.npmjs.org/standard-engine/-/standard-engine-8.0.1.tgz",
-      "integrity": "sha512-LA531C3+nljom/XRvdW/hGPXwmilRkaRkENhO3FAGF1Vtq/WtCXzgmnc5S6vUHHsgv534MRy02C1ikMwZXC+tw==",
+      "version": "10.0.0",
+      "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-10.0.0.tgz",
+      "integrity": "sha512-91BjmzIRZbFmyOY73R6vaDd/7nw5qDWsfpJW5/N+BCXFgmvreyfrRg7oBSu4ihL0gFGXfnwCImJm6j+sZDQQyw==",
       "dev": true,
       "requires": {
-        "deglob": "^2.1.0",
+        "deglob": "^3.0.0",
         "get-stdin": "^6.0.0",
         "minimist": "^1.1.0",
         "pkg-conf": "^2.0.0"
@@ -4687,12 +4558,6 @@
       "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==",
       "dev": true
     },
-    "stealthy-require": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
-      "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=",
-      "dev": true
-    },
     "string-width": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
@@ -4722,7 +4587,7 @@
     },
     "string_decoder": {
       "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
       "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
       "dev": true,
       "requires": {
@@ -4755,18 +4620,24 @@
     },
     "supports-color": {
       "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+      "resolved": "http://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
       "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
       "dev": true
     },
+    "symbol-observable": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
+      "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=",
+      "dev": true
+    },
     "table": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
-      "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
+      "version": "4.0.3",
+      "resolved": "http://registry.npmjs.org/table/-/table-4.0.3.tgz",
+      "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==",
       "dev": true,
       "requires": {
-        "ajv": "^5.2.3",
-        "ajv-keywords": "^2.1.0",
+        "ajv": "^6.0.1",
+        "ajv-keywords": "^3.0.0",
         "chalk": "^2.1.0",
         "lodash": "^4.17.4",
         "slice-ansi": "1.0.0",
@@ -4811,26 +4682,18 @@
       }
     },
     "tar": {
-      "version": "4.4.6",
-      "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.6.tgz",
-      "integrity": "sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg==",
+      "version": "4.4.8",
+      "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz",
+      "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==",
       "dev": true,
       "requires": {
-        "chownr": "^1.0.1",
+        "chownr": "^1.1.1",
         "fs-minipass": "^1.2.5",
-        "minipass": "^2.3.3",
-        "minizlib": "^1.1.0",
+        "minipass": "^2.3.4",
+        "minizlib": "^1.1.1",
         "mkdirp": "^0.5.0",
         "safe-buffer": "^5.1.2",
         "yallist": "^3.0.2"
-      },
-      "dependencies": {
-        "yallist": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz",
-          "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=",
-          "dev": true
-        }
       }
     },
     "tarn": {
@@ -4925,6 +4788,14 @@
       "requires": {
         "psl": "^1.1.24",
         "punycode": "^1.4.1"
+      },
+      "dependencies": {
+        "punycode": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+          "dev": true
+        }
       }
     },
     "trim-right": {
@@ -4973,16 +4844,11 @@
         "mime-types": "~2.1.18"
       }
     },
-    "typedarray": {
-      "version": "0.0.6",
-      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
-      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
-      "dev": true
-    },
     "uberproto": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/uberproto/-/uberproto-2.0.4.tgz",
-      "integrity": "sha512-c/5xjTcztW9XVhrkCycHQRBIAxww5JpDKk/q0zc2tVdQn6ZQvnChWgLvQaWAT1Al5JvRyvloUI15ad41m6dYwg=="
+      "integrity": "sha512-c/5xjTcztW9XVhrkCycHQRBIAxww5JpDKk/q0zc2tVdQn6ZQvnChWgLvQaWAT1Al5JvRyvloUI15ad41m6dYwg==",
+      "dev": true
     },
     "uglify-js": {
       "version": "3.4.9",
@@ -5097,6 +4963,15 @@
         }
       }
     },
+    "uri-js": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+      "dev": true,
+      "requires": {
+        "punycode": "^2.1.0"
+      }
+    },
     "urix": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
@@ -5128,9 +5003,9 @@
       "dev": true
     },
     "v8flags": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz",
-      "integrity": "sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==",
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz",
+      "integrity": "sha512-MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==",
       "dev": true,
       "requires": {
         "homedir-polyfill": "^1.0.1"
@@ -5209,9 +5084,9 @@
       "dev": true
     },
     "yallist": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
-      "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
+      "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
       "dev": true
     }
   }
diff --git a/package.json b/package.json
index f351129..6bb3701 100644
--- a/package.json
+++ b/package.json
@@ -40,7 +40,7 @@
     "mocha": "mocha --opts mocha.opts",
     "test": "npm run lint && npm run coverage",
     "example": "babel-node example/app",
-    "coverage": "istanbul cover node_modules/mocha/bin/_mocha -- --opts mocha.opts"
+    "coverage": "shx rm -rf *.sqlite && istanbul cover node_modules/mocha/bin/_mocha -- --opts mocha.opts"
   },
   "semistandard": {
     "env": [
@@ -51,26 +51,23 @@
     "lib": "lib"
   },
   "dependencies": {
-    "@feathersjs/commons": "^1.4.1",
-    "@feathersjs/errors": "^3.3.4",
+    "@feathersjs/adapter-commons": "^1.0.6",
+    "@feathersjs/commons": "^4.0.0",
+    "@feathersjs/errors": "^3.3.5",
     "debug": "^4.1.0",
-    "is-plain-object": "^2.0.4",
-    "uberproto": "^2.0.4"
-  },
-  "peerDependencies": {
-    "knex": "^0.15.2"
+    "is-plain-object": "^2.0.4"
   },
   "devDependencies": {
-    "@feathersjs/express": "^1.2.7",
-    "@feathersjs/feathers": "^3.2.3",
+    "@feathersjs/express": "^1.3.0",
+    "@feathersjs/feathers": "^3.3.0",
     "body-parser": "^1.18.3",
     "chai": "^4.2.0",
     "chai-as-promised": "^7.1.1",
-    "feathers-service-tests": "^0.10.2",
     "istanbul": "^1.1.0-alpha.1",
-    "knex": "^0.16.0",
+    "knex": "^0.16.2",
     "mocha": "^5.2.0",
-    "semistandard": "^12.0.1",
-    "sqlite3": "^4.0.2"
+    "semistandard": "^13.0.1",
+    "shx": "^0.3.2",
+    "sqlite3": "^4.0.4"
   }
 }
diff --git a/test/index.test.js b/test/index.test.js
index b2746e4..b29ab9c 100644
--- a/test/index.test.js
+++ b/test/index.test.js
@@ -1,13 +1,72 @@
 const chai = require('chai');
 const chaiAsPromised = require('chai-as-promised');
-const assert = require('assert');
 const feathers = require('@feathersjs/feathers');
 const knex = require('knex');
 
-const { base } = require('feathers-service-tests');
+const adapterTests = require('@feathersjs/adapter-commons/tests');
 const errors = require('@feathersjs/errors');
 
 const service = require('../lib');
+const testSuite = adapterTests([
+  '.options',
+  '.events',
+  '._get',
+  '._find',
+  '._create',
+  '._update',
+  '._patch',
+  '._remove',
+  '.get',
+  '.get + $select',
+  '.get + id + query',
+  '.get + NotFound',
+  '.find',
+  '.remove',
+  '.remove + $select',
+  '.remove + id + query',
+  '.remove + multi',
+  '.update',
+  '.update + $select',
+  '.update + id + query',
+  '.update + NotFound',
+  '.patch',
+  '.patch + $select',
+  '.patch + id + query',
+  '.patch multiple',
+  '.patch multi query',
+  '.patch + NotFound',
+  '.create',
+  '.create + $select',
+  '.create multi',
+  'internal .find',
+  'internal .get',
+  'internal .create',
+  'internal .update',
+  'internal .patch',
+  'internal .remove',
+  '.find + equal',
+  '.find + equal multiple',
+  '.find + $sort',
+  '.find + $sort + string',
+  '.find + $limit',
+  '.find + $limit 0',
+  '.find + $skip',
+  '.find + $select',
+  '.find + $or',
+  '.find + $in',
+  '.find + $nin',
+  '.find + $lt',
+  '.find + $lte',
+  '.find + $gt',
+  '.find + $gte',
+  '.find + $ne',
+  '.find + $gt + $lt + $sort',
+  '.find + $or nested + $sort',
+  '.find + paginate',
+  '.find + paginate + $limit + $skip',
+  '.find + paginate + $limit 0',
+  '.find + paginate + params'
+]);
 
 chai.use(chaiAsPromised);
 const { expect } = chai;
@@ -55,7 +114,7 @@ function clean () {
     db.schema.dropTableIfExists(people.fullName).then(() => {
       return people.init({}, (table) => {
         table.increments('id');
-        table.string('name');
+        table.string('name').notNullable();
         table.integer('age');
         table.integer('time');
         table.boolean('created');
@@ -63,7 +122,7 @@ function clean () {
       });
     }),
     db.schema.dropTableIfExists(peopleId.fullName).then(() => {
-      return peopleId.init({}, (table) => {
+      return peopleId.init({}, table => {
         table.increments('customid');
         table.string('name');
         table.integer('age');
@@ -73,7 +132,7 @@ function clean () {
       });
     }),
     db.schema.dropTableIfExists(users.fullName).then(() => {
-      return users.init({}, (table) => {
+      return users.init({}, table => {
         table.increments('id');
         table.string('name');
         table.integer('age');
@@ -90,20 +149,6 @@ function attachSchema () {
   return db.schema.raw(`attach database '${schemaName}.sqlite' as ${schemaName}`);
 }
 
-function customQuery () {
-  return (context) => {
-    const { params, service } = context;
-    const query = service.createQuery(params);
-
-    // do something with query here
-    query.orderBy('name', 'desc');
-    // console.log(query.toSQL().toNative());
-
-    context.params.knex = query;
-    return context;
-  };
-}
-
 describe('Feathers Knex Service', () => {
   const app = feathers()
     .hooks({
@@ -114,6 +159,7 @@ describe('Feathers Knex Service', () => {
     .use('/people', people)
     .use('people-customid', peopleId)
     .use('/users', users);
+  const peopleService = app.service('people');
 
   before(attachSchema);
   before(clean);
@@ -123,7 +169,7 @@ describe('Feathers Knex Service', () => {
     describe('when missing options', () => {
       it('throws an error', () =>
         expect(service.bind(null))
-          .to.throw('Knex options have to be provided')
+          .to.throw('You must provide a Model (the initialized knex object)')
       );
     });
 
@@ -142,81 +188,55 @@ describe('Feathers Knex Service', () => {
     });
   });
 
-  describe('Common functionality', () => {
-    it('is CommonJS compatible', () =>
-      assert.equal(typeof require('../lib'), 'function')
-    );
-
-    base(app, errors, 'people');
-    base(app, errors, 'people-customid', 'customid');
-
-    describe('database schema support', () => {
-      base(app, errors, 'users');
-    });
-  });
+  describe('$like method', () => {
+    let charlie;
 
-  describe('custom queries', () => {
-    before(clean);
-    before(() => {
-      app.hooks({});
-      app.service('people').hooks({
-        before: {
-          find: customQuery()
-        }
+    beforeEach(async () => {
+      charlie = await peopleService.create({
+        name: 'Charlie Brown',
+        age: 10
       });
-      app.service('users').hooks({
-        before: {
-          find: customQuery()
-        }
-      });
-    });
-    after(clean);
-    after(() => {
-      app.hooks({
-        before: transaction.start(),
-        after: transaction.end(),
-        error: transaction.rollback()
-      });
-      app.service('people').hooks({});
-      app.service('users').hooks({});
     });
 
-    base(app, errors, 'people');
+    afterEach(() => peopleService.remove(charlie.id));
 
-    describe('database schema support', () => {
-      base(app, errors, 'users');
-    });
-  });
-
-  describe('$like method', () => {
-    beforeEach(() => app.service('/people').create({
-      name: 'Charlie Brown',
-      age: 10
-    }));
-
-    it('$like in query', () => {
-      return app.service('/people').find({
+    it('$like in query', async () => {
+      const data = await peopleService.find({
         query: { name: { $like: '%lie%' } }
-      }).then(data => {
-        expect(data[0].name).to.be.equal('Charlie Brown');
       });
+
+      expect(data[0].name).to.be.equal('Charlie Brown');
     });
   });
 
   describe('adapter specifics', () => {
-    it('$or works properly (#120)', () => {
-      app.service('/people').create([{
-        name: 'Dave',
-        age: 23
-      }, {
-        name: 'Dave',
-        age: 32
-      }, {
-        name: 'Dada',
-        age: 1
-      }]);
-
-      return app.service('/people').find({
+    let daves;
+
+    beforeEach(async () => {
+      daves = await Promise.all([
+        peopleService.create({
+          name: 'Ageless',
+          age: null
+        }),
+        peopleService.create({
+          name: 'Dave',
+          age: 32
+        }),
+        peopleService.create({
+          name: 'Dada',
+          age: 1
+        })
+      ]);
+    });
+
+    afterEach(async () => Promise.all([
+      peopleService.remove(daves[0].id),
+      peopleService.remove(daves[1].id),
+      peopleService.remove(daves[2].id)
+    ]).catch(() => {}));
+
+    it('$or works properly (#120)', async () => {
+      const data = await peopleService.find({
         query: {
           name: 'Dave',
           $or: [{
@@ -225,133 +245,73 @@ describe('Feathers Knex Service', () => {
             age: 32
           }]
         }
-      }).then(data => {
-        expect(data.length).to.equal(1);
-        expect(data[0].name).to.be.equal('Dave');
-        expect(data[0].age).to.be.equal(32);
-        app.service('/people').remove(null);
       });
+
+      expect(data.length).to.equal(1);
+      expect(data[0].name).to.be.equal('Dave');
+      expect(data[0].age).to.be.equal(32);
     });
 
-    it('$and works properly', () => {
-      app.service('/people').create([{
-        name: 'Dave',
-        age: 23
-      }, {
-        name: 'Dave',
-        age: 32
-      }, {
-        name: 'Dada',
-        age: 1
-      }]);
-
-      return app.service('/people').find({
+    it('$and works properly', async () => {
+      const data = await peopleService.find({
         query: {
           $and: [{
             $or: [
-              {name: 'Dave'},
-              {name: 'Dada'}
+              { name: 'Dave' },
+              { name: 'Dada' }
             ]
           }, {
-            age: {$lt: 23}
+            age: { $lt: 23 }
           }]
         }
-      }).then(data => {
-        expect(data.length).to.equal(1);
-        expect(data[0].name).to.be.equal('Dada');
-        expect(data[0].age).to.be.equal(1);
-        app.service('/people').remove(null);
       });
+
+      expect(data.length).to.equal(1);
+      expect(data[0].name).to.be.equal('Dada');
+      expect(data[0].age).to.be.equal(1);
     });
 
-    it('where conditions support NULL values properly', () => {
-      app.service('/people').create([{
-        name: 'Dave without age',
-        age: null
-      }, {
-        name: 'Dave',
-        age: 32
-      }, {
-        name: 'Dada',
-        age: 1
-      }]);
-
-      return app.service('/people').find({
+    it('where conditions support NULL values properly', async () => {
+      const data = await peopleService.find({
         query: {
           age: null
         }
-      }).then(data => {
-        expect(data.length).to.equal(1);
-        expect(data[0].name).to.be.equal('Dave without age');
-        expect(data[0].age).to.be.equal(null);
-        app.service('/people').remove(null);
       });
+
+      expect(data.length).to.equal(1);
+      expect(data[0].name).to.be.equal('Ageless');
+      expect(data[0].age).to.be.equal(null);
     });
 
-    it('where conditions support NOT NULL case properly', () => {
-      app.service('/people').create([{
-        name: 'Dave without age',
-        age: null
-      }, {
-        name: 'Dave',
-        age: 32
-      }, {
-        name: 'Dada',
-        age: 1
-      }]);
-
-      return app.service('/people').find({
+    it('where conditions support NOT NULL case properly', async () => {
+      const data = await peopleService.find({
         query: {
-          age: {$ne: null}
+          age: { $ne: null }
         }
-      }).then(data => {
-        expect(data.length).to.equal(2);
-        expect(data[0].name).to.not.be.equal('Dave without age');
-        expect(data[0].age).to.not.be.equal(null);
-        expect(data[1].name).to.not.be.equal('Dave without age');
-        expect(data[1].age).to.not.be.equal(null);
-        app.service('/people').remove(null);
       });
+
+      expect(data.length).to.equal(2);
+      expect(data[0].name).to.not.be.equal('Ageless');
+      expect(data[0].age).to.not.be.equal(null);
+      expect(data[1].name).to.not.be.equal('Ageless');
+      expect(data[1].age).to.not.be.equal(null);
     });
 
-    it('where conditions support NULL values within AND conditions', () => {
-      app.service('/people').create([{
-        name: 'Dave',
-        age: null
-      }, {
-        name: 'Dave',
-        age: 32
-      }, {
-        name: 'Dada',
-        age: 1
-      }]);
-
-      return app.service('/people').find({
+    it('where conditions support NULL values within AND conditions', async () => {
+      const data = await peopleService.find({
         query: {
           age: null,
-          name: 'Dave'
+          name: 'Ageless'
         }
-      }).then(data => {
-        expect(data.length).to.equal(1);
-        expect(data[0].name).to.be.equal('Dave');
-        expect(data[0].age).to.be.equal(null);
-        app.service('/people').remove(null);
       });
+
+      expect(data.length).to.equal(1);
+      expect(data[0].name).to.be.equal('Ageless');
+      expect(data[0].age).to.be.equal(null);
     });
 
-    it('where conditions support NULL values within OR conditions', () => {
-      app.service('/people').create([{
-        name: 'Dave without age',
-        age: null
-      }, {
-        name: 'Dave',
-        age: 32
-      }, {
-        name: 'Dada',
-        age: 1
-      }]);
-
-      return app.service('/people').find({
+    it('where conditions support NULL values within OR conditions', async () => {
+      const data = await peopleService.find({
         query: {
           $or: [
             {
@@ -362,18 +322,33 @@ describe('Feathers Knex Service', () => {
             }
           ]
         }
-      }).then(data => {
-        expect(data.length).to.equal(2);
-        expect(data[0].name).not.be.equal('Dave');
-        expect(data[0].age).not.be.equal(32);
-        expect(data[1].name).not.be.equal('Dave');
-        expect(data[1].age).not.be.equal(32);
-        app.service('/people').remove(null);
       });
+
+      expect(data.length).to.equal(2);
+      expect(data[0].name).not.be.equal('Dave');
+      expect(data[0].age).not.be.equal(32);
+      expect(data[1].name).not.be.equal('Dave');
+      expect(data[1].age).not.be.equal(32);
+    });
+
+    it('attaches the SQL error', async () => {
+      try {
+        await peopleService.create({});
+        expect(false);
+      } catch (error) {
+        expect(error.name).to.equal('GeneralError');
+        expect(error[service.ERROR]);
+      }
     });
   });
 
   describe('hooks', () => {
+    const people2 = service({
+      Model: db,
+      name: 'people2',
+      events: [ 'testing' ]
+    });
+
     const app2 = feathers()
       .hooks({
         before: transaction.start(),
@@ -390,12 +365,21 @@ describe('Feathers Knex Service', () => {
         ],
         error: transaction.rollback()
       })
-      .use('/people', people);
+      .use('/people', people2);
 
-    it('does fail on unsuccessful commit', () => {
-      return expect(
-        app2.service('/people').create({name: 'Foo'})
-      ).to.eventually.be.rejected;
+    it('does fail on unsuccessful commit', async () => {
+      const message = 'Should never get here';
+
+      try {
+        await app2.service('/people').create({ name: 'Foo' });
+        throw new Error(message);
+      } catch (error) {
+        expect(error.message !== message);
+      }
     });
   });
+
+  testSuite(app, errors, 'users');
+  testSuite(app, errors, 'people');
+  testSuite(app, errors, 'people-customid', 'customid');
 });