diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index e76b29d..0000000 --- a/.jshintrc +++ /dev/null @@ -1,30 +0,0 @@ -{ - "node": true, - "esnext": true, - "bitwise": true, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "immed": true, - "indent": 2, - "latedef": "nofunc", - "newcap": false, - "noarg": true, - "quotmark": "single", - "regexp": true, - "undef": true, - "unused": true, - "strict": false, - "trailing": true, - "smarttabs": true, - "white": false, - "globals": { - "it": true, - "describe": true, - "before": true, - "beforeEach": true, - "after": true, - "afterEach": true, - "exports": true - } -} diff --git a/.npmignore b/.npmignore index d41ceda..bf54bc5 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,5 @@ .babelrc .editorconfig -.jshintrc .travis.yml .idea/ src/ diff --git a/example/app.js b/example/app.js index 937fb48..e9b809c 100644 --- a/example/app.js +++ b/example/app.js @@ -12,11 +12,11 @@ const knex = require('knex')({ // Clean up our data. This is optional and is here // because of our integration tests -knex.schema.dropTableIfExists('todos').then(function() { +knex.schema.dropTableIfExists('todos').then(function () { console.log('Dropped todos table'); // Initialize your table - return knex.schema.createTable('todos', function(table) { + return knex.schema.createTable('todos', function (table) { console.log('Creating todos table'); table.increments('id'); table.string('text'); @@ -44,7 +44,7 @@ app.use('/todos', knexService({ } })); -app.use(function(error, req, res, next){ +app.use(function (error, req, res, next) { res.json(error); }); diff --git a/package.json b/package.json index 0923e23..bfea806 100644 --- a/package.json +++ b/package.json @@ -39,11 +39,19 @@ "release:major": "npm version major && npm publish", "compile": "rm -rf lib/ && babel -d lib/ src/", "watch": "babel --watch -d lib/ src/", - "jshint": "jshint src/. test/. --config", + "lint": "eslint-if-supported semistandard --fix", "mocha": "mocha test/ --compilers js:babel-core/register --timeout 5000", - "test": "npm run compile && npm run jshint && npm run mocha", + "test": "npm run compile && npm run lint && npm run mocha", "example": "babel-node example/app" }, + "semistandard": { + "env": [ + "mocha" + ], + "ignore": [ + "/lib" + ] + }, "directories": { "lib": "lib" }, @@ -61,12 +69,13 @@ "babel-preset-es2015": "^6.9.0", "body-parser": "^1.14.1", "chai": "^3.4.1", + "eslint-if-supported": "^1.0.1", "feathers": "^2.0.0-pre.4", "feathers-rest": "^1.3.0", "feathers-service-tests": "^0.8.0", - "jshint": "^2.8.0", "knex": "^0.12.0", "mocha": "^3.0.0", + "semistandard": "^9.1.0", "sqlite3": "^3.1.0" } } diff --git a/src/error-handler.js b/src/error-handler.js index 2003c51..ff568eb 100644 --- a/src/error-handler.js +++ b/src/error-handler.js @@ -1,15 +1,15 @@ import errors from 'feathers-errors'; -export default function errorHandler(error) { +export default function errorHandler (error) { let feathersError = error; - //TODO (EK): Map PG, MySQL, Oracle, etc. errors + // TODO (EK): Map PG, MySQL, Oracle, etc. errors // NOTE (EK): Error codes taken from // https://www.sqlite.org/c3ref/c_abort.html if (error.code === 'SQLITE_ERROR') { - switch(error.errno) { + switch (error.errno) { case 1: case 8: case 18: @@ -32,6 +32,6 @@ export default function errorHandler(error) { break; } } - + throw feathersError; -} \ No newline at end of file +} diff --git a/src/index.js b/src/index.js index 9a289ef..8a21ea8 100644 --- a/src/index.js +++ b/src/index.js @@ -21,7 +21,7 @@ const OPERATORS = { // Create the service. class Service { - constructor(options) { + constructor (options) { if (!options) { throw new Error('Knex options have to be provided'); } @@ -39,19 +39,19 @@ class Service { this.paginate = options.paginate || {}; this.table = options.name; this.events = options.events || []; - } + } // NOTE (EK): We need this method so that we return a new query // instance each time, otherwise it will reuse the same query. - db() { + db () { return this.knex(this.table); } - extend(obj) { - return Proto.extend(obj, this); - } + extend (obj) { + return Proto.extend(obj, this); + } - knexify(query, params, parentKey) { + knexify (query, params, parentKey) { Object.keys(params || {}).forEach(key => { const value = params[key]; @@ -69,12 +69,12 @@ class Service { const self = this; return value.forEach(condition => { - query[method](function() { + query[method](function () { self.knexify(this, condition); }); }); } - + // eslint-disable-next-line no-useless-call return query[method].call(query, column, value); } @@ -82,33 +82,33 @@ class Service { }); } - _find(params, count, getFilter = filter) { + _find (params, count, getFilter = filter) { const { filters, query } = getFilter(params.query || {}); let q = this.db().select(['*']); - // $select uses a specific find syntax, so it has to come first. - if (filters.$select) { - q = this.db().select(... filters.$select); - } + // $select uses a specific find syntax, so it has to come first. + if (filters.$select) { + q = this.db().select(...filters.$select); + } // build up the knex query out of the query params this.knexify(q, query); - // Handle $sort - if (filters.$sort) { + // Handle $sort + if (filters.$sort) { Object.keys(filters.$sort).forEach(key => - q = q.orderBy(key, parseInt(filters.$sort[key], 10) === 1 ? 'asc' : 'desc')); - } + (q = q.orderBy(key, parseInt(filters.$sort[key], 10) === 1 ? 'asc' : 'desc'))); + } - // Handle $limit - if (filters.$limit) { + // Handle $limit + if (filters.$limit) { q.limit(filters.$limit); - } + } - // Handle $skip - if (filters.$skip) { + // Handle $skip + if (filters.$skip) { q.offset(filters.$skip); - } + } const executeQuery = total => { return q.then(data => { @@ -121,7 +121,7 @@ class Service { }); }; - if(count) { + if (count) { let countQuery = this.db().count(`${this.id} as total`); this.knexify(countQuery, query); @@ -130,68 +130,67 @@ class Service { } return executeQuery(); - } + } - find(params) { - const paginate = (params && typeof params.paginate !== 'undefined') ? - params.paginate : this.paginate; + find (params) { + const paginate = (params && typeof params.paginate !== 'undefined') + ? params.paginate : this.paginate; const result = this._find(params, !!paginate.default, query => filter(query, paginate) ); - if(!paginate.default) { + if (!paginate.default) { return result.then(page => page.data); } return result; } - _get(id, params) { + _get (id, params) { params.query = params.query || {}; params.query[this.id] = id; return this._find(params) .then(page => { - if(page.data.length !== 1) { + if (page.data.length !== 1) { throw new errors.NotFound(`No record found for id '${id}'`); } return page.data[0]; }).catch(errorHandler); - } + } - get(...args) { + get (...args) { return this._get(...args); } - _create(data, params) { + _create (data, params) { return this.db().insert(data, this.id).then(rows => { - const id = typeof data[this.id] !== 'undefined' ? - data[this.id] : rows[0]; + const id = typeof data[this.id] !== 'undefined' ? data[this.id] : rows[0]; return this._get(id, params); }).catch(errorHandler); } - create(data, params) { - if(Array.isArray(data)) { + create (data, params) { + if (Array.isArray(data)) { return Promise.all(data.map(current => this._create(current, params))); } return this._create(data, params); - } + } - patch(id, raw, params) { + patch (id, raw, params) { const query = Object.assign({}, params.query); const data = Object.assign({}, raw); const patchQuery = {}; - if(id !== null) { + if (id !== null) { query[this.id] = id; } // Account for potentially modified data Object.keys(query).forEach(key => { - if(query[key] !== undefined && data[key] !== undefined && + if (query[key] !== undefined && data[key] !== undefined && typeof data[key] !== 'object') { patchQuery[key] = data[key]; } else { @@ -208,8 +207,8 @@ class Service { return this._find({ query: patchQuery }).then(page => { const items = page.data; - if(id !== null) { - if(items.length === 1) { + if (id !== null) { + if (items.length === 1) { return items[0]; } else { throw new errors.NotFound(`No record found for id '${id}'`); @@ -219,10 +218,10 @@ class Service { return items; }); }).catch(errorHandler); - } + } - update(id, data, params) { - if(Array.isArray(data)) { + update (id, data, params) { + if (Array.isArray(data)) { return Promise.reject('Not replacing multiple records. Did you mean `patch`?'); } @@ -249,14 +248,14 @@ class Service { return newObject; }); }).catch(errorHandler); - } + } - remove(id, params) { + remove (id, params) { params.query = params.query || {}; // NOTE (EK): First fetch the record so that we can return // it when we delete it. - if(id !== null) { + if (id !== null) { params.query[this.id] = id; } @@ -267,8 +266,8 @@ class Service { this.knexify(query, params.query); return query.del().then(() => { - if(id !== null) { - if(items.length === 1) { + if (id !== null) { + if (items.length === 1) { return items[0]; } else { throw new errors.NotFound(`No record found for id '${id}'`); @@ -278,10 +277,10 @@ class Service { return items; }); }).catch(errorHandler); - } + } } -export default function init(options) { +export default function init (options) { return new Service(options); } diff --git a/test/index.test.js b/test/index.test.js index 73d771a..469d67e 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,5 +1,3 @@ -/*jshint expr: true*/ - import { expect } from 'chai'; import assert from 'assert'; import feathers from 'feathers'; @@ -16,7 +14,7 @@ const db = knex({ } }); -function clean() { +function clean () { return db.schema.dropTableIfExists('people') .then(() => db.schema.dropTableIfExists('people-customid')) .then(() =>