diff --git a/package.json b/package.json index f3e940e274..c413334417 100644 --- a/package.json +++ b/package.json @@ -35,10 +35,15 @@ "release:prerelease": "npm version prerelease && npm publish --tag pegasus", "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 --opts mocha.opts", "coverage": "istanbul cover _mocha -- --opts mocha.opts", - "test": "npm run compile && npm run jshint && npm run coverage && nsp check" + "test": "npm run compile && npm run lint && npm run coverage && nsp check" + }, + "semistandard": { + "env": [ + "mocha" + ] }, "engines": { "node": ">= 0.10.0", @@ -59,6 +64,7 @@ "babel-plugin-add-module-exports": "^0.2.0", "babel-preset-es2015": "^6.3.13", "body-parser": "^1.13.2", + "eslint-if-supported": "^1.0.1", "feathers-rest": "^1.1.0", "feathers-socketio": "^1.1.0", "istanbul": "^1.1.0-alpha.1", @@ -67,6 +73,7 @@ "nsp": "^2.2.0", "q": "^1.0.1", "request": "^2.x", + "semistandard": "^9.1.0", "socket.io-client": "^1.4.6" }, "browser": { diff --git a/src/application.js b/src/application.js index 35bcf7e8f0..8192845eb1 100644 --- a/src/application.js +++ b/src/application.js @@ -10,7 +10,7 @@ const Proto = Uberproto.extend({ }); export default { - init() { + init () { Object.assign(this, { methods, mixins: mixins(), @@ -20,13 +20,13 @@ export default { }); }, - service(location, service, options = {}) { + service (location, service, options = {}) { location = stripSlashes(location); - if(!service) { + if (!service) { const current = this.services[location]; - if(typeof current === 'undefined' && typeof this.defaultService === 'function') { + if (typeof current === 'undefined' && typeof this.defaultService === 'function') { return this.service(location, this.defaultService(location), options); } @@ -40,7 +40,7 @@ export default { // Add all the mixins this.mixins.forEach(fn => fn.call(this, protoService)); - if(typeof protoService._setup === 'function') { + if (typeof protoService._setup === 'function') { protoService._setup(this, location); } @@ -58,8 +58,9 @@ export default { return (this.services[location] = protoService); }, - use(location) { - let service, middleware = Array.from(arguments) + use (location) { + let service; + let middleware = Array.from(arguments) .slice(1) .reduce(function (middleware, arg) { if (typeof arg === 'function') { @@ -80,7 +81,7 @@ export default { ); // Check for service (any object with at least one service method) - if(hasMethod(['handle', 'set']) || !hasMethod(this.methods.concat('setup'))) { + if (hasMethod(['handle', 'set']) || !hasMethod(this.methods.concat('setup'))) { return this._super.apply(this, arguments); } @@ -90,7 +91,7 @@ export default { return this; }, - setup() { + setup () { // Setup each service (pass the app so that they can look up other services etc.) Object.keys(this.services).forEach(path => { const service = this.services[path]; @@ -110,13 +111,13 @@ export default { // That just takes a function in order to keep Feathers plugin configuration easier. // Environment specific configurations should be done as suggested in the 4.x migration guide: // https://github.com/visionmedia/express/wiki/Migrating-from-3.x-to-4.x - configure(fn){ + configure (fn) { fn.call(this); return this; }, - listen() { + listen () { const server = this._super.apply(this, arguments); this.setup(server); diff --git a/src/client/express.js b/src/client/express.js index da942385f7..6fb9c4701f 100644 --- a/src/client/express.js +++ b/src/client/express.js @@ -1,42 +1,42 @@ import { EventEmitter } from 'events'; import Proto from 'uberproto'; -export default function() { +export default function () { const app = { settings: {}, - get(name) { + get (name) { return this.settings[name]; }, - set(name, value) { + set (name, value) { this.settings[name] = value; return this; }, - disable(name) { + disable (name) { this.settings[name] = false; return this; }, - disabled(name) { + disabled (name) { return !this.settings[name]; }, - enable(name) { + enable (name) { this.settings[name] = true; return this; }, - enabled(name) { + enabled (name) { return !!this.settings[name]; }, - use() { + use () { throw new Error('Middleware functions can not be used in the Feathers client'); }, - listen() { + listen () { return {}; } }; diff --git a/src/client/index.js b/src/client/index.js index 7860ab7651..e2f7778d88 100644 --- a/src/client/index.js +++ b/src/client/index.js @@ -1,8 +1,8 @@ import feathers from '../feathers'; import express from './express'; -export default function createApplication(... args) { - return feathers(express(... args)); +export default function createApplication (...args) { + return feathers(express(...args)); } createApplication.version = '2.0.1'; diff --git a/src/feathers.js b/src/feathers.js index 09a02e1d1c..82ca9b196d 100644 --- a/src/feathers.js +++ b/src/feathers.js @@ -7,7 +7,7 @@ import Application from './application'; * @return {Function} * @api public */ -export default function createApplication(app) { +export default function createApplication (app) { Proto.mixin(Application, app); app.init(); return app; diff --git a/src/index.js b/src/index.js index e14acfea44..4b8e9097d2 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,10 @@ -if(!global._babelPolyfill) { require('babel-polyfill'); } +if (!global._babelPolyfill) { require('babel-polyfill'); } import express from 'express'; import feathers from './feathers'; -export default function createApplication(... args) { - return feathers(express(... args)); +export default function createApplication (...args) { + return feathers(express(...args)); } // Expose all express methods (like express.engine()) diff --git a/src/mixins/event.js b/src/mixins/event.js index 3dede8e681..43431ec654 100644 --- a/src/mixins/event.js +++ b/src/mixins/event.js @@ -10,17 +10,17 @@ const eventMappings = { patch: 'patched' }; -function upperCase(name) { +function upperCase (name) { return name.charAt(0).toUpperCase() + name.substring(1); } -export default function(service) { +export default function (service) { const app = this; const isEmitter = typeof service.on === 'function' && typeof service.emit === 'function'; const emitter = service._rubberDuck = rubberduck.emitter(service); - if(typeof service.mixin === 'function' && !isEmitter) { + if (typeof service.mixin === 'function' && !isEmitter) { service.mixin(EventEmitter.prototype); } diff --git a/src/mixins/index.js b/src/mixins/index.js index 3b980ce572..3be3c95d72 100644 --- a/src/mixins/index.js +++ b/src/mixins/index.js @@ -1,4 +1,4 @@ -export default function() { +export default function () { const mixins = [ require('./promise'), require('./event'), @@ -6,8 +6,8 @@ export default function() { ]; // Override push to make sure that normalize is always the last - mixins.push = function() { - const args = [ this.length - 1, 0].concat(Array.from(arguments)); + mixins.push = function () { + const args = [this.length - 1, 0].concat(Array.from(arguments)); this.splice.apply(this, args); return this.length; }; diff --git a/src/mixins/normalizer.js b/src/mixins/normalizer.js index 8a6efca378..45cef9767c 100644 --- a/src/mixins/normalizer.js +++ b/src/mixins/normalizer.js @@ -5,8 +5,8 @@ export default function (service) { const mixin = {}; this.methods.forEach(method => { - if(typeof service[method] === 'function') { - mixin[method] = function() { + if (typeof service[method] === 'function') { + mixin[method] = function () { return this._super.apply(this, getArguments(method, arguments)); }; } diff --git a/src/mixins/promise.js b/src/mixins/promise.js index a6c3c5e2a3..6ccb65b079 100644 --- a/src/mixins/promise.js +++ b/src/mixins/promise.js @@ -1,13 +1,13 @@ -function isPromise(result) { +function isPromise (result) { return typeof result !== 'undefined' && typeof result.then === 'function'; } -function wrapper() { +function wrapper () { const result = this._super.apply(this, arguments); const callback = arguments[arguments.length - 1]; - if(typeof callback === 'function' && isPromise(result)) { + if (typeof callback === 'function' && isPromise(result)) { result.then(data => callback(null, data), error => callback(error)); } return result; @@ -18,7 +18,7 @@ export default function (service) { const mixin = {}; this.methods.forEach(method => { - if(typeof service[method] === 'function') { + if (typeof service[method] === 'function') { mixin[method] = wrapper; } }); diff --git a/test/application.test.js b/test/application.test.js index 707791c871..ecc98c47cf 100644 --- a/test/application.test.js +++ b/test/application.test.js @@ -28,14 +28,14 @@ describe('Feathers application', () => { try { app.use('/dummy', {}, {}); assert.ok(false, 'Should never get here'); - } catch(e) { + } catch (e) { assert.equal(e.message, 'invalid arg passed to app.use'); } }); it('Register services and look them up with and without leading and trailing slashes.', () => { const dummyService = { - find() { + find () { // No need to implement this } }; @@ -60,10 +60,10 @@ describe('Feathers application', () => { assert.ok(!app.service('/todos/')); - app.defaultService = function(path) { + app.defaultService = function (path) { assert.equal(path, 'todos'); return { - get(id) { + get (id) { return Promise.resolve({ id, description: `You have to do ${id}!` }); @@ -82,18 +82,18 @@ describe('Feathers application', () => { it('Registers a service, wraps it, runs service.setup(), and adds the event and Promise mixin', done => { const dummyService = { - setup(app, path){ + setup (app, path) { this.path = path; }, - create(data) { + create (data) { return Promise.resolve(data); } }; const app = feathers().use('/dummy', dummyService); const wrappedService = app.service('dummy'); - const server = app.listen(7887, function(){ + const server = app.listen(7887, function () { app.use('/dumdum', dummyService); const dynamicService = app.service('dumdum'); @@ -117,7 +117,7 @@ describe('Feathers application', () => { it('Initializes REST and SocketIO providers.', function (done) { const todoService = { - get(name, params, callback) { + get (name, params, callback) { callback(null, { id: name, description: `You have to do ${name}!` @@ -133,11 +133,17 @@ describe('Feathers application', () => { const socket = io.connect('http://localhost:6999'); request('http://localhost:6999/todo/dishes', (error, response, body) => { + if (error) { + done(error); + } assert.ok(response.statusCode === 200, 'Got OK status code'); const data = JSON.parse(body); assert.equal(data.description, 'You have to do dishes!'); socket.emit('todo::get', 'laundry', {}, function (error, data) { + if (error) { + done(error); + } assert.equal(data.description, 'You have to do laundry!'); socket.disconnect(); @@ -149,7 +155,7 @@ describe('Feathers application', () => { it('Uses custom middleware. (#21)', done => { const todoService = { - get(name, params) { + get (name, params) { return Promise.resolve({ id: name, description: `You have to do ${name}!`, @@ -171,12 +177,18 @@ describe('Feathers application', () => { const server = app.listen(6995).on('listening', () => { request('http://localhost:6995/todo/dishes', (error, response, body) => { + if (error) { + done(error); + } assert.ok(response.statusCode === 200, 'Got OK status code'); const data = JSON.parse(body); assert.equal(data.preService, 'pre-service middleware', 'Pre-service middleware updated response'); assert.equal(response.headers['post-service'], 'dishes', 'Post-service middleware updated response'); request('http://localhost:6995/otherTodo/dishes', (error, response, body) => { + if (error) { + done(error); + } assert.ok(response.statusCode === 200, 'Got OK status code'); const data = JSON.parse(body); assert.ok(!data.preService && !response.headers['post-service'], 'Custom middleware not run for different service.'); @@ -192,7 +204,7 @@ describe('Feathers application', () => { process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; const todoService = { - get(name, params, callback) { + get (name, params, callback) { callback(null, { id: name, description: `You have to do ${name}!` @@ -225,11 +237,17 @@ describe('Feathers application', () => { strictSSL: false, rejectUnhauthorized: false }, function (error, response, body) { + if (error) { + done(error); + } assert.ok(response.statusCode === 200, 'Got OK status code'); const data = JSON.parse(body); assert.equal(data.description, 'You have to do dishes!'); socket.emit('secureTodos::get', 'laundry', {}, function (error, data) { + if (error) { + done(error); + } assert.equal(data.description, 'You have to do laundry!'); socket.disconnect(); @@ -243,11 +261,11 @@ describe('Feathers application', () => { it('Returns the value of a promise. (#41)', function (done) { let original = {}; const todoService = { - get(name) { + get (name) { original = { id: name, q: true, - description: `You have to do ${name }!` + description: `You have to do ${name}!` }; return Promise.resolve(original); } @@ -259,6 +277,9 @@ describe('Feathers application', () => { const server = app.listen(6880).on('listening', function () { request('http://localhost:6880/todo/dishes', (error, response, body) => { + if (error) { + done(error); + } assert.ok(response.statusCode === 200, 'Got OK status code'); assert.deepEqual(original, JSON.parse(body)); server.close(done); @@ -268,7 +289,7 @@ describe('Feathers application', () => { it('Calls _setup in order to set up custom routes with higher priority. (#86)', done => { const todoService = { - get(name) { + get (name) { return Promise.resolve({ id: name, q: true, @@ -276,8 +297,8 @@ describe('Feathers application', () => { }); }, - _setup(app, path) { - app.get(`/${path}/count`, function(req, res) { + _setup (app, path) { + app.get(`/${path}/count`, function (req, res) { res.json({ counter: 10 }); }); } @@ -289,11 +310,17 @@ describe('Feathers application', () => { const server = app.listen(8999).on('listening', function () { request('http://localhost:8999/todo/dishes', (error, response, body) => { + if (error) { + done(error); + } assert.ok(response.statusCode === 200, 'Got OK status code'); const data = JSON.parse(body); assert.equal(data.description, 'You have to do dishes!'); request('http://localhost:8999/todo/count', (error, response, body) => { + if (error) { + done(error); + } assert.ok(response.statusCode === 200, 'Got OK status code'); const data = JSON.parse(body); assert.equal(data.counter, 10); @@ -303,13 +330,13 @@ describe('Feathers application', () => { }); }); - it('mixins are unique to one application', function() { + it('mixins are unique to one application', function () { const app = feathers(); - app.mixins.push(function() {}); + app.mixins.push(function () {}); assert.equal(app.mixins.length, 4); const otherApp = feathers(); - otherApp.mixins.push(function() {}); + otherApp.mixins.push(function () {}); assert.equal(otherApp.mixins.length, 4); }); @@ -317,7 +344,7 @@ describe('Feathers application', () => { const app = feathers(); app.use('/setup-only', { - setup(_app, path) { + setup (_app, path) { assert.equal(_app, app); assert.equal(path, 'setup-only'); done(); @@ -329,7 +356,7 @@ describe('Feathers application', () => { it('Event punching happens after normalization (#150)', done => { const todoService = { - create(data) { + create (data) { return Promise.resolve(data); } }; diff --git a/test/client.test.js b/test/client.test.js index 8cfe459dc0..9ec3eff84e 100644 --- a/test/client.test.js +++ b/test/client.test.js @@ -13,9 +13,9 @@ describe('Feathers universal client', () => { const app = feathers(); try { - app.use(function() {}); + app.use(function () {}); assert.ok(false, 'Should never get here'); - } catch(e) { + } catch (e) { assert.equal(e.message, 'Middleware functions can not be used in the Feathers client'); } }); @@ -37,11 +37,11 @@ describe('Feathers universal client', () => { it('Registers a service, wraps it, runs service.setup(), and adds the event and Promise mixin', done => { const dummyService = { - setup(app, path){ + setup (app, path) { this.path = path; }, - create(data) { + create (data) { return Promise.resolve(data); } }; diff --git a/test/distributed.test.js b/test/distributed.test.js index cd5e557761..bfbf6b5363 100644 --- a/test/distributed.test.js +++ b/test/distributed.test.js @@ -11,7 +11,7 @@ describe('Distributed Feathers applications test', () => { const app = feathers() .configure(socketio()) .use('todos', { - create(data) { + create (data) { data.id = 42; return Promise.resolve(data); } @@ -28,8 +28,8 @@ describe('Distributed Feathers applications test', () => { .configure(rest()) .use('todos', remoteApp.service('todos')); - beta.listen(9999, function() { - beta.service('todos').on('created', function(newTodo) { + beta.listen(9999, function () { + beta.service('todos').on('created', function (newTodo) { assert.deepEqual(newTodo, { id: 42, text: 'Created on alpha server', diff --git a/test/mixins/event.test.js b/test/mixins/event.test.js index d26b50b0e1..e89130ea4a 100644 --- a/test/mixins/event.test.js +++ b/test/mixins/event.test.js @@ -8,7 +8,7 @@ const create = Proto.create; describe('Event mixin', () => { it('initializes', () => { const FixtureService = Proto.extend({ - setup(arg) { + setup (arg) { return `Original setup: ${arg}`; } }); @@ -24,7 +24,7 @@ describe('Event mixin', () => { assert.ok(instance._rubberDuck instanceof EventEmitter); const existingMethodsService = { - setup(arg) { + setup (arg) { return `Original setup from object: ${arg}`; } }; @@ -37,7 +37,7 @@ describe('Event mixin', () => { it('serviceError', function (done) { var FixtureService = Proto.extend({ - create(data, params, cb) { + create (data, params, cb) { cb(new Error('Something went wrong')); } }); @@ -82,12 +82,17 @@ describe('Event mixin', () => { name: 'Tester' }, { custom: 'value' - }, (error, data) => assert.equal(data.id, 10)); + }, (error, data) => { + if (error) { + done(error); + } + assert.equal(data.id, 10); + }); }); it('updated', done => { const FixtureService = Proto.extend({ - update(id, data, params, cb) { + update (id, data, params, cb) { setTimeout(function () { cb(null, { id: id, @@ -115,13 +120,16 @@ describe('Event mixin', () => { }, { custom: 'value' }, function (error, data) { + if (error) { + done(error); + } assert.equal(data.id, 12); }); }); it('removed', done => { const FixtureService = Proto.extend({ - remove(id, params, cb) { + remove (id, params, cb) { setTimeout(function () { cb(null, { id: id @@ -144,6 +152,9 @@ describe('Event mixin', () => { instance.remove(27, { custom: 'value' }, function (error, data) { + if (error) { + done(error); + } assert.equal(data.id, 27); }); }); @@ -152,10 +163,10 @@ describe('Event mixin', () => { const fixture = [ { id: 0 }, { id: 1 }, - { id: 2 }, + { id: 2 } ]; const FixtureService = Proto.extend({ - create(data, params, cb) { + create (data, params, cb) { setTimeout(function () { cb(null, fixture); }, 20); @@ -170,7 +181,7 @@ describe('Event mixin', () => { instance.on('created', function (data) { assert.equal(data.id, counter); counter++; - if(counter === fixture.length) { + if (counter === fixture.length) { done(); } }); @@ -181,7 +192,7 @@ describe('Event mixin', () => { it('does not punch when service has an events list (#118)', done => { const FixtureService = Proto.extend({ events: [ 'created' ], - create(data, params, cb) { + create (data, params, cb) { setTimeout(function () { cb(null, { id: 10, @@ -205,33 +216,36 @@ describe('Event mixin', () => { instance.create({ name: 'Tester' }, {}, function (error, data) { + if (error) { + done(error); + } assert.equal(data.id, 10); instance.emit('created', { custom: 'event' }); }); }); it('sets hook.app', done => { - const FixtureService = Proto.extend({ - update(id, data, params, cb) { - setTimeout(function () { - cb(null, { - id: id, - name: data.name - }); - }, 20); - } - }); - - const instance = create.call(FixtureService); - const dummyApp = { isApp: true }; - - mixinEvent.call(dummyApp, instance); - - instance.on('updated', function (data, hook) { - assert.deepEqual(hook.app, dummyApp); - done(); - }); - - instance.update(12, { name: 'Updated tester' }, {}, function () {}); + const FixtureService = Proto.extend({ + update (id, data, params, cb) { + setTimeout(function () { + cb(null, { + id: id, + name: data.name + }); + }, 20); + } + }); + + const instance = create.call(FixtureService); + const dummyApp = { isApp: true }; + + mixinEvent.call(dummyApp, instance); + + instance.on('updated', function (data, hook) { + assert.deepEqual(hook.app, dummyApp); + done(); + }); + + instance.update(12, { name: 'Updated tester' }, {}, function () {}); }); }); diff --git a/test/mixins/normalizer.test.js b/test/mixins/normalizer.test.js index 57b4ff92a3..8b6e1a69cf 100644 --- a/test/mixins/normalizer.test.js +++ b/test/mixins/normalizer.test.js @@ -6,7 +6,7 @@ import mixins from '../../src/mixins'; describe('Argument normalizer mixin', () => { it('normalizer mixin is always the last to run', () => { const arr = mixins(); - const dummy = function() { }; + const dummy = function () { }; assert.equal(arr.length, 3); @@ -22,7 +22,7 @@ describe('Argument normalizer mixin', () => { it('normalizes .find without a callback', done => { const context = { methods: ['find'] }; const FixtureService = Proto.extend({ - find(params, callback) { + find (params, callback) { assert.ok(typeof callback === 'function'); assert.equal(params.test, 'Here'); done(); @@ -39,7 +39,7 @@ describe('Argument normalizer mixin', () => { it('normalizes .update without params and callback', done => { const context = { methods: ['update'] }; const FixtureService = Proto.extend({ - update(id, data, params, callback) { + update (id, data, params, callback) { assert.equal(id, 1); assert.ok(typeof callback === 'function'); assert.deepEqual(data, { test: 'Here' }); diff --git a/test/mixins/promise.test.js b/test/mixins/promise.test.js index c4ef065ffd..2456092261 100644 --- a/test/mixins/promise.test.js +++ b/test/mixins/promise.test.js @@ -21,6 +21,9 @@ describe('Promises/A+ mixin', () => { const instance = create.call(FixtureService); instance.get('dishes', {}, function (error, data) { + if (error) { + done(error); + } assert.deepEqual(data, { id: 'dishes', description: 'You have to do dishes' @@ -50,11 +53,11 @@ describe('Promises/A+ mixin', () => { }); }); - it('does not try to call the callback if it does not exist', function(done) { + it('does not try to call the callback if it does not exist', function (done) { // A dummy context (this will normally be the application) const context = { methods: ['create'] }; const FixtureService = Proto.extend({ - create(data) { + create (data) { return Promise.resolve(data); } });