Use standard code style.

This commit is contained in:
Julien Fontanet 2015-04-17 13:35:33 +02:00
parent c539dd5570
commit 6fa2e79c1c
12 changed files with 346 additions and 434 deletions

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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')

View File

@ -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)
})

View File

@ -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

View File

@ -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')
})
})
})

View File

@ -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')

View File

@ -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": "*"
}
}

View File

@ -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')

View File

@ -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