diff --git a/packages/xo-lib/.jshintrc b/packages/xo-lib/.jshintrc deleted file mode 100644 index 9e30c8a86..000000000 --- a/packages/xo-lib/.jshintrc +++ /dev/null @@ -1,93 +0,0 @@ -{ - // Julien Fontanet JSHint configuration - // https://gist.github.com/julien-f/8095615 - // - // Changes from defaults: - // - all enforcing options (except `++` & `--`) enabled - // - single quotes - // - indentation set to 2 instead of 4 - // - almost all relaxing options disabled - // - environments are set to Node.js - // - // See http://jshint.com/docs/ for more details - - "maxerr" : 50, // {int} Maximum error before stopping - - // Enforcing - "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) - "camelcase" : true, // true: Identifiers must be in camelCase - "curly" : true, // true: Require {} for every new block or scope - "eqeqeq" : true, // true: Require triple equals (===) for comparison - "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() - "freeze" : true, // true: Prohibit overwriting prototypes of native objects (Array, Date, ...) - "immed" : true, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` - "indent" : 2, // {int} Number of spaces to use for indentation - "latedef" : true, // true: Require variables/functions to be defined before being used - "newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()` - "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` - "noempty" : true, // true: Prohibit use of empty blocks - "nonbsp" : true, // true: Prohibit use of non breakable spaces - "nonew" : true, // true: Prohibit use of constructors for side-effects (without assignment) - "plusplus" : false, // true: Prohibit use of `++` & `--` - "quotmark" : "single", // Quotation mark consistency: - // false : do nothing (default) - // true : ensure whatever is used is consistent - // "single" : require single quotes - // "double" : require double quotes - "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) - "unused" : true, // true: Require all defined variables be used - "strict" : false, // true: Requires all functions run in ES5 Strict Mode - "maxcomplexity" : 7, // {int} Max cyclomatic complexity per function - "maxdepth" : 3, // {int} Max depth of nested blocks (within functions) - "maxlen" : 80, // {int} Max number of characters per line - "maxparams" : 4, // {int} Max number of formal params allowed per function - "maxstatements" : 20, // {int} Max number statements per function - - // Relaxing - "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) - "boss" : false, // true: Tolerate assignments where comparisons would be expected - "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. - "eqnull" : false, // true: Tolerate use of `== null` - "esnext" : true, // true: Allow ES.next (ES6) syntax (ex: `const`) - "evil" : false, // true: Tolerate use of `eval` and `new Function()` - "expr" : false, // true: Tolerate `ExpressionStatement` as Programs - "funcscope" : false, // true: Tolerate defining variables inside control statements - "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict') - "iterator" : false, // true: Tolerate using the `__iterator__` property - "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block - "laxbreak" : false, // true: Tolerate possibly unsafe line breakings - "laxcomma" : false, // true: Tolerate comma-first style coding - "loopfunc" : false, // true: Tolerate functions being defined in loops - "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) - // (ex: `for each`, multiple try/catch, function expression…) - "multistr" : false, // true: Tolerate multi-line strings - "notypeof" : false, // true: Tolerate typeof comparison with unknown values. - "proto" : false, // true: Tolerate using the `__proto__` property - "scripturl" : false, // true: Tolerate script-targeted URLs - "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` - "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation - "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` - "validthis" : false, // true: Tolerate using this in a non-constructor function - "noyield" : false, // true: Tolerate generators without yields - - // Environments - "browser" : false, // Web Browser (window, document, etc) - "browserify" : false, // Browserify (node.js code in the browser) - "couch" : false, // CouchDB - "devel" : false, // Development/debugging (alert, confirm, etc) - "dojo" : false, // Dojo Toolkit - "jquery" : false, // jQuery - "mocha" : false, // mocha - "mootools" : false, // MooTools - "node" : true, // Node.js - "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) - "phantom" : false, // PhantomJS - "prototypejs" : false, // Prototype and Scriptaculous - "rhino" : false, // Rhino - "worker" : false, // Web Workers - "wsh" : false, // Windows Scripting Host - "yui" : false, // Yahoo User Interface - - // Custom Globals - "globals" : {} // additional predefined global variables -} diff --git a/packages/xo-lib/api.js b/packages/xo-lib/api.js index b1b7e0b00..501883920 100644 --- a/packages/xo-lib/api.js +++ b/packages/xo-lib/api.js @@ -1,132 +1,132 @@ -'use strict'; +'use strict' -//==================================================================== +// =================================================================== -var Bluebird = require('bluebird'); -var EventEmitter = require('events').EventEmitter; -var inherits = require('util').inherits; -var jsonRpc = require('json-rpc'); -var MethodNotFound = require('json-rpc/errors').MethodNotFound; -var startsWith = require('lodash.startswith'); -var WebSocket = require('ws'); +var Bluebird = require('bluebird') +var EventEmitter = require('events').EventEmitter +var inherits = require('util').inherits +var jsonRpc = require('json-rpc') +var MethodNotFound = require('json-rpc/errors').MethodNotFound +var startsWith = require('lodash.startswith') +var WebSocket = require('ws') -var ConnectionError = require('./connection-error'); -var fixUrl = require('./fix-url'); +var ConnectionError = require('./connection-error') +var fixUrl = require('./fix-url') -//==================================================================== +// =================================================================== -function getCurrentUrl() { +function getCurrentUrl () { /* global window: false */ if (typeof window === undefined) { - throw new Error('cannot get current URL'); + throw new Error('cannot get current URL') } - return String(window.location); + return String(window.location) } -function makeDeferred() { - var resolve, reject; +function makeDeferred () { + var resolve, reject var promise = new Bluebird(function (resolve_, reject_) { - resolve = resolve_; - reject = reject_; - }); + resolve = resolve_ + reject = reject_ + }) return { promise: promise, reject: reject, - resolve: resolve, - }; + resolve: resolve + } } -//-------------------------------------------------------------------- +// ------------------------------------------------------------------- // Low level interface to XO. -function Api(url) { +function Api (url) { // Super constructor. - EventEmitter.call(this); + EventEmitter.call(this) // Fix the URL (ensure correct protocol and /api/ path). - this._url = fixUrl(url || getCurrentUrl()); + this._url = fixUrl(url || getCurrentUrl()) // Will contains the WebSocket. - this._socket = null; + this._socket = null // The JSON-RPC server. - var this_ = this; + var this_ = this this._jsonRpc = jsonRpc.createServer(function (message) { if (message.type === 'notification') { - this_.emit('notification', message); + this_.emit('notification', message) } else { // This object does not support requests. - throw new MethodNotFound(message.method); + throw new MethodNotFound(message.method) } }).on('data', function (message) { - this_._socket.send(JSON.stringify(message)); - }); + this_._socket.send(JSON.stringify(message)) + }) } -inherits(Api, EventEmitter); +inherits(Api, EventEmitter) Api.prototype.close = function () { if (this._socket) { - this._socket.close(); + this._socket.close() } -}; +} Api.prototype.connect = Bluebird.method(function () { if (this._socket) { - return; + return } - var deferred = makeDeferred(); + var deferred = makeDeferred() - var opts = {}; + var opts = {} if (startsWith(this._url, 'wss')) { // Due to imperfect TLS implementation in XO-Server. - opts.rejectUnauthorized = false; + opts.rejectUnauthorized = false } - var socket = this._socket = new WebSocket(this._url, '', opts); + var socket = this._socket = new WebSocket(this._url, '', opts) // Used to avoid binding listeners to this object. - var this_ = this; + var this_ = this // When the socket opens, send any queued requests. socket.addEventListener('open', function () { // Resolves the promise. - deferred.resolve(); + deferred.resolve() - this_.emit('connected'); - }); + this_.emit('connected') + }) socket.addEventListener('message', function (message) { - this_._jsonRpc.write(message.data); - }); + this_._jsonRpc.write(message.data) + }) socket.addEventListener('close', function () { - this_._socket = null; + this_._socket = null - this_._jsonRpc.failPendingRequests(new ConnectionError()); + this_._jsonRpc.failPendingRequests(new ConnectionError()) // Only emit this event if connected before. if (deferred.promise.isFulfilled()) { - this_.emit('disconnected'); + this_.emit('disconnected') } - }); + }) socket.addEventListener('error', function (error) { // Fails the connect promise if possible. - deferred.reject(error); - }); + deferred.reject(error) + }) - return deferred.promise; -}); + return deferred.promise +}) Api.prototype.call = function (method, params) { - var jsonRpc = this._jsonRpc; + var jsonRpc = this._jsonRpc return this.connect().then(function () { - return jsonRpc.request(method, params); - }); -}; + return jsonRpc.request(method, params) + }) +} -module.exports = Api; +module.exports = Api diff --git a/packages/xo-lib/back-off.js b/packages/xo-lib/back-off.js index 3f6834df0..d79610c31 100644 --- a/packages/xo-lib/back-off.js +++ b/packages/xo-lib/back-off.js @@ -1,76 +1,76 @@ -'use strict'; +'use strict' -//==================================================================== +// =================================================================== -var Bluebird = require('bluebird'); +var Bluebird = require('bluebird') -//==================================================================== +// =================================================================== -function returnThis() { +function returnThis () { /* jshint validthis: true */ - return this; + return this } // Returns an iterator to the Fibonacci sequence. -function fibonacci(start) { - var prev = 0; - var curr = start || 1; +function fibonacci (start) { + var prev = 0 + var curr = start || 1 var iterator = { next: function () { - var tmp = curr; - curr += prev; - prev = tmp; + var tmp = curr + curr += prev + prev = tmp return { done: false, - value: prev, - }; - }, - }; + value: prev + } + } + } // Make the iterator a true iterable (ES6). if (typeof Symbol !== 'undefined') { - iterator[Symbol.iterator] = returnThis; + iterator[Symbol.iterator] = returnThis } - return iterator; + return iterator } -//==================================================================== +// =================================================================== -function defaultGenerator() { - return fibonacci(1e3); +function defaultGenerator () { + return fibonacci(1e3) } -function BackOff(opts) { +function BackOff (opts) { if (!opts) { - opts = {}; + opts = {} } - this._attempts = 0; - this._generator = opts.generator || defaultGenerator; - this._iterator = this._generator(); - this._maxAttempts = opts.maxAttempts || Infinity; + this._attempts = 0 + this._generator = opts.generator || defaultGenerator + this._iterator = this._generator() + this._maxAttempts = opts.maxAttempts || Infinity } BackOff.prototype.wait = function () { - var maxAttempts = this._maxAttempts; + var maxAttempts = this._maxAttempts if (this._attempts++ > maxAttempts) { return Bluebird.reject(new Error( - 'maximum attempts reached (' + maxAttempts +')' - )); + 'maximum attempts reached (' + maxAttempts + ')' + )) } - return Bluebird.delay(this._iterator.next().value); -}; + return Bluebird.delay(this._iterator.next().value) +} BackOff.prototype.reset = function () { - this._attempts = 0; - this._iterator = this._generator(); -}; + this._attempts = 0 + this._iterator = this._generator() +} -//==================================================================== +// =================================================================== -module.exports = BackOff; +module.exports = BackOff diff --git a/packages/xo-lib/collection.js b/packages/xo-lib/collection.js index 5340c5c82..7bf279b4f 100644 --- a/packages/xo-lib/collection.js +++ b/packages/xo-lib/collection.js @@ -1,160 +1,160 @@ -'use strict'; +'use strict' -//==================================================================== +// =================================================================== -var forEach = require('lodash.foreach'); -var indexOf = require('lodash.indexof'); +var forEach = require('lodash.foreach') +var indexOf = require('lodash.indexof') -//==================================================================== +// =================================================================== -function deleteProperties(obj) { +function deleteProperties (obj) { /* jshint forin: false */ - var prop; + var prop for (prop in obj) { - delete obj[prop]; + delete obj[prop] } } -//==================================================================== +// =================================================================== -function defaultKey(item) { - return item.id || item._id || item; +function defaultKey (item) { + return item.id || item._id || item } -//==================================================================== +// =================================================================== -function getAll() { +function getAll () { /* jshint validthis: true */ - return this._data; + return this._data } -function getIndexes() { +function getIndexes () { /* jshint validthis: true */ - return this._indexes; + return this._indexes } -function Collection(opts) { +function Collection (opts) { if (!opts) { - opts = {}; + opts = {} } - this._key = opts.key || defaultKey; + this._key = opts.key || defaultKey - this._indexes = Object.create(null); + this._indexes = Object.create(null) if (opts.indexes) { forEach(opts.indexes, function (field) { - this[field] = Object.create(null); - }, this._indexes); + this[field] = Object.create(null) + }, this._indexes) } - this._data = Object.create(null); + this._data = Object.create(null) // Expose public properties. Object.defineProperties(this, { all: { enumerable: true, - get: getAll, + get: getAll }, indexes: { enumerable: true, - get: getIndexes, - }, - }); + get: getIndexes + } + }) } Collection.prototype.clear = function () { - deleteProperties(this._data); - forEach(this._indexes, deleteProperties); -}; + deleteProperties(this._data) + forEach(this._indexes, deleteProperties) +} -function unsetItemFromIndex(index, field) { +function unsetItemFromIndex (index, field) { /* jshint validthis: true */ - var prop = this[field]; + var prop = this[field] if (!prop) { - return; + return } - var items = index[prop]; + var items = index[prop] - var i = indexOf(items, this); + var i = indexOf(items, this) if (i === -1) { - return; + return } // The index contains only this one item for this prop. if (items.length === 1) { - delete index[prop]; - return; + delete index[prop] + return } // Remove this item. - items.splice(i, 1); + items.splice(i, 1) } // Internal unset method. -function unset(item, key) { +function unset (item, key) { /* jshint validthis: true */ - delete this._data[key]; + delete this._data[key] - forEach(this._indexes, unsetItemFromIndex, item); + forEach(this._indexes, unsetItemFromIndex, item) } -function setItemToIndex(index, field) { +function setItemToIndex (index, field) { /* jshint validthis: true */ - var prop = this[field]; + var prop = this[field] if (!prop) { - return; + return } - var items = index[prop]; + var items = index[prop] if (items) { // Update the items list. - items.push(this); + items.push(this) } else { // Create the items list. - index[prop] = [this]; + index[prop] = [this] } } Collection.prototype.set = function (item) { - var key = this._key(item); + var key = this._key(item) if (!key) { // Ignore empty keys. - return; + return } - var previous = this._data[key]; + var previous = this._data[key] if (previous) { - unset.call(this, previous, key); + unset.call(this, previous, key) } - this._data[key] = item; - forEach(this._indexes, setItemToIndex, item); -}; + this._data[key] = item + forEach(this._indexes, setItemToIndex, item) +} Collection.prototype.unset = function (item) { - var key = this._key(item); - item = this._data[key]; + var key = this._key(item) + item = this._data[key] if (!item) { - return; + return } - unset.call(this, item, this._key(item)); -}; + unset.call(this, item, this._key(item)) +} Collection.prototype.setMultiple = function (items) { - forEach(items, this.set, this); -}; -Collection.prototype.unsetMultiple = function (items) { - forEach(items, this.unset, this); -}; - -//==================================================================== - -function createCollection(opts) { - return new Collection(opts); + forEach(items, this.set, this) } -module.exports = createCollection; +Collection.prototype.unsetMultiple = function (items) { + forEach(items, this.unset, this) +} + +// =================================================================== + +function createCollection (opts) { + return new Collection(opts) +} +module.exports = createCollection diff --git a/packages/xo-lib/connection-error.js b/packages/xo-lib/connection-error.js index 79f959f7f..a0f6ab1a0 100644 --- a/packages/xo-lib/connection-error.js +++ b/packages/xo-lib/connection-error.js @@ -1,9 +1,9 @@ -'use strict'; +'use strict' -//==================================================================== +// =================================================================== -var makeError = require('make-error'); +var makeError = require('make-error') -//==================================================================== +// =================================================================== -module.exports = makeError('ConnectionError'); +module.exports = makeError('ConnectionError') diff --git a/packages/xo-lib/example.js b/packages/xo-lib/example.js index f6fbedcec..d87727dec 100644 --- a/packages/xo-lib/example.js +++ b/packages/xo-lib/example.js @@ -1,34 +1,36 @@ -var xoLib = require('./'); +'use strict' + +var xoLib = require('./') var xo = new xoLib.Xo({ - url: 'localhost:9000', -}); + url: 'localhost:9000' +}) xo.call('acl.get', {}).then(function (result) { - console.log('baz', result); -}).catch(function (error) { - console.log('error', error) -}); - -xo.signIn({ - email: 'admin@admin.net', - password: 'admin', -}).then(function () { - console.log('foo', xo.user); -}).catch(function (error) { - console.log('error', error) -}); - -xo.signIn({ - email: 'tom', - password: 'tom', -}).then(function () { - console.log('bar', xo.user); -}).catch(function (error) { - console.log('error', error) -}); - -xo.call('acl.get', {}).then(function (result) { - console.log('plop', result); + console.log('baz', result) +}).catch(function (error) { + console.log('error', error) +}) + +xo.signIn({ + email: 'admin@admin.net', + password: 'admin' +}).then(function () { + console.log('foo', xo.user) +}).catch(function (error) { + console.log('error', error) +}) + +xo.signIn({ + email: 'tom', + password: 'tom' +}).then(function () { + console.log('bar', xo.user) +}).catch(function (error) { + console.log('error', error) +}) + +xo.call('acl.get', {}).then(function (result) { + console.log('plop', result) }).catch(function (error) { console.log('error', error) }) diff --git a/packages/xo-lib/fix-url.js b/packages/xo-lib/fix-url.js index 6ed8c5bae..d767d5589 100644 --- a/packages/xo-lib/fix-url.js +++ b/packages/xo-lib/fix-url.js @@ -1,21 +1,21 @@ -'use strict'; +'use strict' -//==================================================================== +// =================================================================== // Fix URL if necessary. -var URL_RE = /^(?:(?:http|ws)(s)?:\/\/)?(.*?)\/*(?:\/api\/)?(\?.*?)?(?:#.*)?$/; -function fixUrl(url) { - var matches = URL_RE.exec(url); - var isSecure = !!matches[1]; - var hostAndPath = matches[2]; - var search = matches[3]; +var URL_RE = /^(?:(?:http|ws)(s)?:\/\/)?(.*?)\/*(?:\/api\/)?(\?.*?)?(?:#.*)?$/ +function fixUrl (url) { + var matches = URL_RE.exec(url) + var isSecure = !!matches[1] + var hostAndPath = matches[2] + var search = matches[3] return [ isSecure ? 'wss' : 'ws', '://', hostAndPath, '/api/', - search, - ].join(''); + search + ].join('') } -module.exports = fixUrl; +module.exports = fixUrl diff --git a/packages/xo-lib/fix-url.spec.js b/packages/xo-lib/fix-url.spec.js index 7ab89d920..2ff751050 100644 --- a/packages/xo-lib/fix-url.spec.js +++ b/packages/xo-lib/fix-url.spec.js @@ -1,48 +1,48 @@ -'use strict'; +'use strict' -//==================================================================== +// =================================================================== -var expect = require('must'); +var expect = require('must') -//==================================================================== +// =================================================================== -/* jshint mocha: true */ +/* eslint-env mocha */ describe('fixUrl()', function () { - var fixUrl = require('./fix-url'); + var fixUrl = require('./fix-url') describe('protocol', function () { it('is added if missing', function () { - expect(fixUrl('localhost/api/')).to.equal('ws://localhost/api/'); - }); + expect(fixUrl('localhost/api/')).to.equal('ws://localhost/api/') + }) it('HTTP(s) is converted to WS(s)', function () { - expect(fixUrl('http://localhost/api/')).to.equal('ws://localhost/api/'); - expect(fixUrl('https://localhost/api/')).to.equal('wss://localhost/api/'); - }); + expect(fixUrl('http://localhost/api/')).to.equal('ws://localhost/api/') + expect(fixUrl('https://localhost/api/')).to.equal('wss://localhost/api/') + }) it('is not added if already present', function () { - expect(fixUrl('ws://localhost/api/')).to.equal('ws://localhost/api/'); - expect(fixUrl('wss://localhost/api/')).to.equal('wss://localhost/api/'); - }); - }); + expect(fixUrl('ws://localhost/api/')).to.equal('ws://localhost/api/') + expect(fixUrl('wss://localhost/api/')).to.equal('wss://localhost/api/') + }) + }) describe('/api/ path', function () { it('is added if missing', function () { - expect(fixUrl('ws://localhost')).to.equal('ws://localhost/api/'); - expect(fixUrl('ws://localhost/')).to.equal('ws://localhost/api/'); - }); + expect(fixUrl('ws://localhost')).to.equal('ws://localhost/api/') + expect(fixUrl('ws://localhost/')).to.equal('ws://localhost/api/') + }) it('is not added if already present', function () { - expect(fixUrl('ws://localhost/api/')).to.equal('ws://localhost/api/'); - }); + expect(fixUrl('ws://localhost/api/')).to.equal('ws://localhost/api/') + }) it('removes the hash part', function () { - expect(fixUrl('ws://localhost/#foo')).to.equal('ws://localhost/api/'); - }); + expect(fixUrl('ws://localhost/#foo')).to.equal('ws://localhost/api/') + }) it('conserve the search part', function () { - expect(fixUrl('ws://localhost/?foo')).to.equal('ws://localhost/api/?foo'); - }); - }); -}); + expect(fixUrl('ws://localhost/?foo')).to.equal('ws://localhost/api/?foo') + }) + }) +}) diff --git a/packages/xo-lib/index.js b/packages/xo-lib/index.js index eb097768f..695713bfd 100644 --- a/packages/xo-lib/index.js +++ b/packages/xo-lib/index.js @@ -1,7 +1,7 @@ -'use strict'; +'use strict' // Expose Bluebird for now to ease integration (e.g. with Angular.js). -exports.setScheduler = require('bluebird').setScheduler; +exports.setScheduler = require('bluebird').setScheduler -exports.Api = require('./api'); -exports.Xo = require('./xo'); +exports.Api = require('./api') +exports.Xo = require('./xo') diff --git a/packages/xo-lib/package.json b/packages/xo-lib/package.json index 41caf92c4..5741386cf 100644 --- a/packages/xo-lib/package.json +++ b/packages/xo-lib/package.json @@ -19,10 +19,12 @@ "node": ">=0.8.0" }, "scripts": { - "test": "mocha *.spec.js" + "test": "standard && mocha '*.spec.js'" }, "dependencies": { "bluebird": "^2.9.6", + "event-to-promise": "^0.3.2", + "exec-promise": "^0.5.1", "json-rpc": "git://github.com/julien-f/js-json-rpc#v0.3.1", "lodash.assign": "^3.0.0", "lodash.foreach": "^3.0.1", @@ -30,10 +32,12 @@ "lodash.isstring": "^3.0.0", "lodash.startswith": "^3.0.0", "make-error": "^0.3.0", + "pw": "0.0.4", "ws": "^0.7.1" }, "devDependencies": { "mocha": "^2.1.0", - "must": "^0.12.0" + "must": "^0.12.0", + "standard": "*" } } diff --git a/packages/xo-lib/session-error.js b/packages/xo-lib/session-error.js index fe5970f54..19c54f400 100644 --- a/packages/xo-lib/session-error.js +++ b/packages/xo-lib/session-error.js @@ -1,9 +1,9 @@ -'use strict'; +'use strict' -//==================================================================== +// =================================================================== -var makeError = require('make-error'); +var makeError = require('make-error') -//==================================================================== +// =================================================================== -module.exports = makeError('SessionError'); +module.exports = makeError('SessionError') diff --git a/packages/xo-lib/xo.js b/packages/xo-lib/xo.js index ab69cc6ac..7d149a2c2 100644 --- a/packages/xo-lib/xo.js +++ b/packages/xo-lib/xo.js @@ -1,99 +1,99 @@ -'use strict'; +'use strict' -//==================================================================== +// =================================================================== -var Bluebird = require('bluebird'); -var isString = require('lodash.isstring'); -var startsWith = require('lodash.startswith'); +var Bluebird = require('bluebird') +var isString = require('lodash.isstring') +var startsWith = require('lodash.startswith') -var Api = require('./api'); -var BackOff = require('./back-off'); -var ConnectionError = require('./connection-error'); -var createCollection = require('./collection'); -var SessionError = require('./session-error'); +var Api = require('./api') +var BackOff = require('./back-off') +var ConnectionError = require('./connection-error') +var createCollection = require('./collection') +var SessionError = require('./session-error') -//==================================================================== +// =================================================================== -function makeStandaloneDeferred() { - var resolve, reject; +function makeStandaloneDeferred () { + var resolve, reject var promise = new Bluebird(function (resolve_, reject_) { - resolve = resolve_; - reject = reject_; - }); - promise.resolve = resolve; - promise.reject = reject; + resolve = resolve_ + reject = reject_ + }) + promise.resolve = resolve + promise.reject = reject - return promise; + return promise } -function noop() {} +function noop () {} -//==================================================================== +// =================================================================== -function Xo(opts) { +function Xo (opts) { if (!opts) { - opts = {}; + opts = {} } else if (isString(opts)) { opts = { - url: opts, - }; + url: opts + } } - //------------------------------------------------------------------ + // ----------------------------------------------------------------- - var api = new Api(opts.url); + var api = new Api(opts.url) api.on('connected', function () { - this._backOff.reset(); - this.status = 'connected'; + this._backOff.reset() + this.status = 'connected' - this._tryToOpenSession(); - }.bind(this)); + this._tryToOpenSession() + }.bind(this)) api.on('disconnected', function () { - this._closeSession(); - this._connect(); - }.bind(this)); + this._closeSession() + this._connect() + }.bind(this)) api.on('notification', function (notification) { if (notification.method !== 'all') { - return; + return } var method = ( notification.params.type === 'exit' ? 'unset' : 'set' - ) + 'Multiple'; + ) + 'Multiple' - this.objects[method](notification.params.items); - }.bind(this)); + this.objects[method](notification.params.items) + }.bind(this)) - //------------------------------------------------------------------ + // ----------------------------------------------------------------- this.objects = createCollection({ indexes: [ 'ref', 'type', - 'UUID', + 'UUID' ], key: function (item) { - return item.UUID || item.ref; - }, - }); - this.status = 'disconnected'; - this.user = null; + return item.UUID || item.ref + } + }) + this.status = 'disconnected' + this.user = null - this._api = api; - this._backOff = new BackOff(); - this._credentials = opts.creadentials; - this._session = makeStandaloneDeferred(); - this._signIn = null; + this._api = api + this._backOff = new BackOff() + this._credentials = opts.creadentials + this._session = makeStandaloneDeferred() + this._signIn = null - //------------------------------------------------------------------ + // ----------------------------------------------------------------- - this._connect(); + this._connect() } Xo.prototype.call = function (method, params) { @@ -102,35 +102,35 @@ Xo.prototype.call = function (method, params) { if (startsWith(method, 'session.')) { return Bluebird.reject( new Error('session.*() methods are disabled from this interface') - ); + ) } return this._session.bind(this).then(function () { - return this._api.call(method, params); + return this._api.call(method, params) }).catch(ConnectionError, SessionError, function () { // Automatically requeue this call. - return this.call(method, params); - }); -}; + return this.call(method, params) + }) +} Xo.prototype.signIn = function (credentials) { - this.signOut(); + this.signOut() - this._credentials = credentials; - this._signIn = makeStandaloneDeferred(); + this._credentials = credentials + this._signIn = makeStandaloneDeferred() - this._tryToOpenSession(); + this._tryToOpenSession() - return this._signIn; -}; + return this._signIn +} Xo.prototype.signOut = function () { - this._closeSession(); - this._credentials = null; + this._closeSession() + this._credentials = null - var signIn = this._signIn; + var signIn = this._signIn if (signIn && signIn.isPending()) { - signIn.reject(new SessionError('sign in aborted')); + signIn.reject(new SessionError('sign in aborted')) } return this.status === 'connected' ? @@ -140,31 +140,30 @@ Xo.prototype.signOut = function () { // Always return a promise. Bluebird.resolve() - ; -}; +} -Xo.prototype._connect = function _connect() { - this.status = 'connecting'; +Xo.prototype._connect = function _connect () { + this.status = 'connecting' return this._api.connect().bind(this).catch(function (error) { - console.warn('could not connect:', error); + console.warn('could not connect:', error) - return this._backOff.wait().bind(this).then(_connect); - }); -}; + return this._backOff.wait().bind(this).then(_connect) + }) +} Xo.prototype._closeSession = function () { if (!this._session.isPending()) { - this._session = makeStandaloneDeferred(); + this._session = makeStandaloneDeferred() } - this.user = null; -}; + this.user = null +} Xo.prototype._tryToOpenSession = function () { - var credentials = this._credentials; + var credentials = this._credentials if (!credentials || this.status !== 'connected') { - return; + return } this._api.call( @@ -174,33 +173,33 @@ Xo.prototype._tryToOpenSession = function () { credentials ).bind(this).then( function (user) { - this.user = user; + this.user = user this._api.call('xo.getAllObjects').bind(this).then(function (objects) { - this.objects.clear(); - this.objects.setMultiple(objects); - }); + this.objects.clear() + this.objects.setMultiple(objects) + }) // Validate the sign in. - var signIn = this._signIn; + var signIn = this._signIn if (signIn) { - signIn.resolve(); + signIn.resolve() } // Open the session. - this._session.resolve(); + this._session.resolve() }, function (error) { // Reject the sign in. - var signIn = this._signIn; + var signIn = this._signIn if (signIn) { - signIn.reject(error); + signIn.reject(error) } } - ); -}; + ) +} -//==================================================================== +// =================================================================== -module.exports = Xo; +module.exports = Xo