pouchdb-replication-stream
Version:
PouchDB/CouchDB replication as a stream
1,495 lines (1,330 loc) • 2.76 MB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"/Users/nolan/workspace/pouchdb-replication-stream/lib/index.js":[function(require,module,exports){
'use strict';
var utils = require('./pouch-utils');
var version = require('./version');
var ldj = require('ldjson-stream');
var through = require('through2').obj;
var pick = require('lodash/object/pick');
var toBufferStream = require('./to-buffer-stream');
var DEFAULT_BATCH_SIZE = 50;
// params to the replicate() API that the user is allowed to specify
var ALLOWED_PARAMS = [
'batch_size',
'batches_limit',
'filter',
'doc_ids',
'query_params',
'since',
'view'
];
exports.adapters = {};
exports.adapters.writableStream = require('./writable-stream');
exports.plugin = require('pouch-stream');
exports.plugin.dump = utils.toPromise(function (writableStream, opts, callback) {
var self = this;
/* istanbul ignore else */
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
var PouchDB = self.constructor;
var output = new PouchDB(self._db_name, {
adapter: 'writableStream'
});
output.setupStream(writableStream);
var chain = self.info().then(function (info) {
var header = {
version: version,
db_type: self.type(),
start_time: new Date().toJSON(),
db_info: info
};
writableStream.write(JSON.stringify(header) + '\n');
opts = pick(opts, ALLOWED_PARAMS);
if (!opts.batch_size) {
opts.batch_size = DEFAULT_BATCH_SIZE;
}
return self.replicate.to(output, opts);
}).then(function () {
return output.close();
}).then(function () {
callback(null, {ok: true});
});
/* istanbul ignore next */
function onErr(err) {
callback(err);
}
chain.catch(onErr);
});
exports.plugin.load = utils.toPromise(function (readableStream, opts, callback) {
/* istanbul ignore else */
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
var batchSize;
/* istanbul ignore if */
if ('batch_size' in opts) {
batchSize = opts.batch_size;
} else {
batchSize = DEFAULT_BATCH_SIZE;
}
var queue = [];
readableStream.pipe(toBufferStream()).pipe(ldj.parse()).pipe(through(function (data, _, next) {
if (!data.docs) {
return next();
}
// lets smooth it out
data.docs.forEach(function (doc) {
this.push(doc);
}, this);
next();
}))
.pipe(through(function (doc, _, next) {
queue.push(doc);
if (queue.length >= batchSize) {
this.push(queue);
queue = [];
}
next();
}, function (next) {
if (queue.length) {
this.push(queue);
}
next();
}))
.pipe(this.createWriteStream({new_edits: false}))
.on('error', callback)
.on('finish', function () {
callback(null, {ok: true});
});
});
/* istanbul ignore next */
if (typeof window !== 'undefined' && window.PouchDB) {
window.PouchDB.plugin(exports.plugin);
window.PouchDB.adapter('writableStream', exports.adapters.writableStream);
}
},{"./pouch-utils":"/Users/nolan/workspace/pouchdb-replication-stream/lib/pouch-utils.js","./to-buffer-stream":"/Users/nolan/workspace/pouchdb-replication-stream/lib/to-buffer-stream.js","./version":"/Users/nolan/workspace/pouchdb-replication-stream/lib/version.js","./writable-stream":"/Users/nolan/workspace/pouchdb-replication-stream/lib/writable-stream.js","ldjson-stream":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/ldjson-stream/index.js","lodash/object/pick":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/lodash/object/pick.js","pouch-stream":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/pouch-stream/index.js","through2":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/through2/through2.js"}],"/Users/nolan/workspace/pouchdb-replication-stream/lib/pouch-utils.js":[function(require,module,exports){
(function (process){
'use strict';
var Promise = require('pouchdb/extras/promise');
/* istanbul ignore next */
exports.once = function (fun) {
var called = false;
return exports.getArguments(function (args) {
if (called) {
console.trace();
throw new Error('once called more than once');
} else {
called = true;
fun.apply(this, args);
}
});
};
/* istanbul ignore next */
exports.getArguments = function (fun) {
return function () {
var len = arguments.length;
var args = new Array(len);
var i = -1;
while (++i < len) {
args[i] = arguments[i];
}
return fun.call(this, args);
};
};
/* istanbul ignore next */
exports.toPromise = function (func) {
//create the function we will be returning
return exports.getArguments(function (args) {
var self = this;
var tempCB = (typeof args[args.length - 1] === 'function') ? args.pop() : false;
// if the last argument is a function, assume its a callback
var usedCB;
if (tempCB) {
// if it was a callback, create a new callback which calls it,
// but do so async so we don't trap any errors
usedCB = function (err, resp) {
process.nextTick(function () {
tempCB(err, resp);
});
};
}
var promise = new Promise(function (fulfill, reject) {
try {
var callback = exports.once(function (err, mesg) {
if (err) {
reject(err);
} else {
fulfill(mesg);
}
});
// create a callback for this invocation
// apply the function in the orig context
args.push(callback);
func.apply(self, args);
} catch (e) {
reject(e);
}
});
// if there is a callback, call it back
if (usedCB) {
promise.then(function (result) {
usedCB(null, result);
}, usedCB);
}
promise.cancel = function () {
return this;
};
return promise;
});
};
exports.inherits = require('inherits');
}).call(this,require('_process'))
},{"_process":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/process/browser.js","inherits":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/inherits/inherits_browser.js","pouchdb/extras/promise":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/pouchdb/extras/promise.js"}],"/Users/nolan/workspace/pouchdb-replication-stream/lib/to-buffer-stream.js":[function(require,module,exports){
(function (Buffer){
'use strict';
var through = require('through2').obj;
module.exports = function () {
return through(function (chunk, _, next) {
// this only applies in the browser
/* istanbul ignore next */
if (!(chunk instanceof Buffer) && Buffer.isBuffer(chunk)) {
chunk = new Buffer(chunk);
}
this.push(chunk);
next();
});
};
}).call(this,require("buffer").Buffer)
},{"buffer":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/buffer/index.js","through2":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/through2/through2.js"}],"/Users/nolan/workspace/pouchdb-replication-stream/lib/version.js":[function(require,module,exports){
module.exports = require('./../package.json').version;
},{"./../package.json":"/Users/nolan/workspace/pouchdb-replication-stream/package.json"}],"/Users/nolan/workspace/pouchdb-replication-stream/lib/writable-stream.js":[function(require,module,exports){
(function (process){
'use strict';
var utils = require('./pouch-utils');
var Promise = require('pouchdb/extras/promise');
var ERROR_REV_CONFLICT = {
status: 409,
name: 'conflict',
message: 'Document update conflict'
};
var ldj = require('ldjson-stream');
var ERROR_MISSING_DOC = {
status: 404,
name: 'not_found',
message: 'missing'
};
function WritableStreamPouch(opts, callback) {
var api = this;
api.instanceId = Math.random().toString();
api.ldj = ldj.serialize();
api.localStore = {};
api.originalName = opts.name;
// TODO: I would pass this in as a constructor opt, but
// PouchDB changed how it clones in 5.0.0 so this broke
api.setupStream = function (stream) {
api.ldj.pipe(stream);
};
/* istanbul ignore next */
api.type = function () {
return 'writableStream';
};
api._id = utils.toPromise(function (callback) {
callback(null, api.instanceId);
});
api._bulkDocs = function (req, opts, callback) {
var docs = req.docs;
var self = this;
/* istanbul ignore else */
if (opts.new_edits === false) {
// assume we're only getting this with new_edits=false,
// since this adapter is just a replication target
this.ldj.write({docs: docs}, function () {
callback(null, docs.map(function (doc) {
return {
ok: true,
id: doc._id,
rev: doc._rev
};
}));
});
} else {
// writing local docs for replication
Promise.all(docs.map(function (doc) {
self.localStore[doc._id] = doc;
})).then(function (res) {
callback(null, res);
}).catch(function (err) {
callback(err);
});
}
};
api._getRevisionTree = function (docId, callback) {
process.nextTick(function () {
callback(ERROR_MISSING_DOC);
});
};
api._close = function (callback) {
this.ldj.end(callback);
};
api._getLocal = function (id, callback) {
var self = this;
process.nextTick(function () {
var existingDoc = self.localStore[id];
/* istanbul ignore else */
if (existingDoc) {
callback(null, existingDoc);
} else {
callback(ERROR_MISSING_DOC);
}
});
};
api._putLocal = function (doc, opts, callback) {
var self = this;
/* istanbul ignore else */
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
delete doc._revisions; // ignore this, trust the rev
var oldRev = doc._rev;
var id = doc._id;
var newRev;
if (!oldRev) {
newRev = doc._rev = '0-1';
} else {
newRev = doc._rev = '0-' + (parseInt(oldRev.split('-')[1], 10) + 1);
}
process.nextTick(function () {
var existingDoc = self.localStore[id];
/* istanbul ignore if */
if (existingDoc && oldRev !== existingDoc._rev) {
callback(ERROR_REV_CONFLICT);
} else {
self.localStore[id] = doc;
var done = function () {
callback(null, {ok: true, id: id, rev: newRev});
};
/* istanbul ignore else */
if ('last_seq' in doc) {
self.ldj.write({seq: doc.last_seq}, done);
} else {
done();
}
}
});
};
/* istanbul ignore next */
api._removeLocal = function (doc, callback) {
var self = this;
process.nextTick(function () {
var existingDoc = self.localStore[doc._id];
if (existingDoc && doc._rev !== existingDoc._rev) {
callback(ERROR_REV_CONFLICT);
} else {
delete self.localStore[doc._id];
callback(null, {ok: true, id: doc._id, rev: '0-0'});
}
});
};
api._destroy = function (opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
WritableStreamPouch.Changes.removeAllListeners(api.originalName);
process.nextTick(function () {
callback(null, {'ok': true});
});
};
process.nextTick(function () {
callback(null, api);
});
}
WritableStreamPouch.valid = function () {
return true;
};
module.exports = WritableStreamPouch;
}).call(this,require('_process'))
},{"./pouch-utils":"/Users/nolan/workspace/pouchdb-replication-stream/lib/pouch-utils.js","_process":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/process/browser.js","ldjson-stream":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/ldjson-stream/index.js","pouchdb/extras/promise":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/pouchdb/extras/promise.js"}],"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/argsarray/index.js":[function(require,module,exports){
'use strict';
module.exports = argsArray;
function argsArray(fun) {
return function () {
var len = arguments.length;
if (len) {
var args = [];
var i = -1;
while (++i < len) {
args[i] = arguments[i];
}
return fun.call(this, args);
} else {
return fun.call(this, []);
}
};
}
},{}],"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/assertion-error/index.js":[function(require,module,exports){
/*!
* assertion-error
* Copyright(c) 2013 Jake Luer <jake@qualiancy.com>
* MIT Licensed
*/
/*!
* Return a function that will copy properties from
* one object to another excluding any originally
* listed. Returned function will create a new `{}`.
*
* @param {String} excluded properties ...
* @return {Function}
*/
function exclude () {
var excludes = [].slice.call(arguments);
function excludeProps (res, obj) {
Object.keys(obj).forEach(function (key) {
if (!~excludes.indexOf(key)) res[key] = obj[key];
});
}
return function extendExclude () {
var args = [].slice.call(arguments)
, i = 0
, res = {};
for (; i < args.length; i++) {
excludeProps(res, args[i]);
}
return res;
};
};
/*!
* Primary Exports
*/
module.exports = AssertionError;
/**
* ### AssertionError
*
* An extension of the JavaScript `Error` constructor for
* assertion and validation scenarios.
*
* @param {String} message
* @param {Object} properties to include (optional)
* @param {callee} start stack function (optional)
*/
function AssertionError (message, _props, ssf) {
var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON')
, props = extend(_props || {});
// default values
this.message = message || 'Unspecified AssertionError';
this.showDiff = false;
// copy from properties
for (var key in props) {
this[key] = props[key];
}
// capture stack trace
ssf = ssf || arguments.callee;
if (ssf && Error.captureStackTrace) {
Error.captureStackTrace(this, ssf);
} else {
this.stack = new Error().stack;
}
}
/*!
* Inherit from Error.prototype
*/
AssertionError.prototype = Object.create(Error.prototype);
/*!
* Statically set name
*/
AssertionError.prototype.name = 'AssertionError';
/*!
* Ensure correct constructor
*/
AssertionError.prototype.constructor = AssertionError;
/**
* Allow errors to be converted to JSON for static transfer.
*
* @param {Boolean} include stack (default: `true`)
* @return {Object} object that can be `JSON.stringify`
*/
AssertionError.prototype.toJSON = function (stack) {
var extend = exclude('constructor', 'toJSON', 'stack')
, props = extend({ name: this.name }, this);
// include stack if exists and not turned off
if (false !== stack && this.stack) {
props.stack = this.stack;
}
return props;
};
},{}],"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/base64-js/lib/b64.js":[function(require,module,exports){
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
;(function (exports) {
'use strict';
var Arr = (typeof Uint8Array !== 'undefined')
? Uint8Array
: Array
var PLUS = '+'.charCodeAt(0)
var SLASH = '/'.charCodeAt(0)
var NUMBER = '0'.charCodeAt(0)
var LOWER = 'a'.charCodeAt(0)
var UPPER = 'A'.charCodeAt(0)
var PLUS_URL_SAFE = '-'.charCodeAt(0)
var SLASH_URL_SAFE = '_'.charCodeAt(0)
function decode (elt) {
var code = elt.charCodeAt(0)
if (code === PLUS ||
code === PLUS_URL_SAFE)
return 62 // '+'
if (code === SLASH ||
code === SLASH_URL_SAFE)
return 63 // '/'
if (code < NUMBER)
return -1 //no match
if (code < NUMBER + 10)
return code - NUMBER + 26 + 26
if (code < UPPER + 26)
return code - UPPER
if (code < LOWER + 26)
return code - LOWER + 26
}
function b64ToByteArray (b64) {
var i, j, l, tmp, placeHolders, arr
if (b64.length % 4 > 0) {
throw new Error('Invalid string. Length must be a multiple of 4')
}
// the number of equal signs (place holders)
// if there are two placeholders, than the two characters before it
// represent one byte
// if there is only one, then the three characters before it represent 2 bytes
// this is just a cheap hack to not do indexOf twice
var len = b64.length
placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
// base64 is 4/3 + up to two characters of the original data
arr = new Arr(b64.length * 3 / 4 - placeHolders)
// if there are placeholders, only get up to the last complete 4 chars
l = placeHolders > 0 ? b64.length - 4 : b64.length
var L = 0
function push (v) {
arr[L++] = v
}
for (i = 0, j = 0; i < l; i += 4, j += 3) {
tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
push((tmp & 0xFF0000) >> 16)
push((tmp & 0xFF00) >> 8)
push(tmp & 0xFF)
}
if (placeHolders === 2) {
tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
push(tmp & 0xFF)
} else if (placeHolders === 1) {
tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
push((tmp >> 8) & 0xFF)
push(tmp & 0xFF)
}
return arr
}
function uint8ToBase64 (uint8) {
var i,
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
output = "",
temp, length
function encode (num) {
return lookup.charAt(num)
}
function tripletToBase64 (num) {
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
}
// go through the array every three bytes, we'll deal with trailing stuff later
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
output += tripletToBase64(temp)
}
// pad the end with zeros, but make sure to not forget the extra bytes
switch (extraBytes) {
case 1:
temp = uint8[uint8.length - 1]
output += encode(temp >> 2)
output += encode((temp << 4) & 0x3F)
output += '=='
break
case 2:
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
output += encode(temp >> 10)
output += encode((temp >> 4) & 0x3F)
output += encode((temp << 2) & 0x3F)
output += '='
break
}
return output
}
exports.toByteArray = b64ToByteArray
exports.fromByteArray = uint8ToBase64
}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
},{}],"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/any.js":[function(require,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, Promise$_CreatePromiseArray, PromiseArray) {
var SomePromiseArray = require("./some_promise_array.js")(PromiseArray);
function Promise$_Any(promises, useBound) {
var ret = Promise$_CreatePromiseArray(
promises,
SomePromiseArray,
useBound === true && promises._isBound()
? promises._boundTo
: void 0
);
var promise = ret.promise();
if (promise.isRejected()) {
return promise;
}
ret.setHowMany(1);
ret.setUnwrap();
ret.init();
return promise;
}
Promise.any = function Promise$Any(promises) {
return Promise$_Any(promises, false);
};
Promise.prototype.any = function Promise$any() {
return Promise$_Any(this, true);
};
};
},{"./some_promise_array.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/some_promise_array.js"}],"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/async.js":[function(require,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
var schedule = require("./schedule.js");
var Queue = require("./queue.js");
var errorObj = require("./util.js").errorObj;
var tryCatch1 = require("./util.js").tryCatch1;
var process = require("./global.js").process;
function Async() {
this._isTickUsed = false;
this._length = 0;
this._lateBuffer = new Queue();
this._functionBuffer = new Queue(25000 * 3);
var self = this;
this.consumeFunctionBuffer = function Async$consumeFunctionBuffer() {
self._consumeFunctionBuffer();
};
}
Async.prototype.haveItemsQueued = function Async$haveItemsQueued() {
return this._length > 0;
};
Async.prototype.invokeLater = function Async$invokeLater(fn, receiver, arg) {
if (process !== void 0 &&
process.domain != null &&
!fn.domain) {
fn = process.domain.bind(fn);
}
this._lateBuffer.push(fn, receiver, arg);
this._queueTick();
};
Async.prototype.invoke = function Async$invoke(fn, receiver, arg) {
if (process !== void 0 &&
process.domain != null &&
!fn.domain) {
fn = process.domain.bind(fn);
}
var functionBuffer = this._functionBuffer;
functionBuffer.push(fn, receiver, arg);
this._length = functionBuffer.length();
this._queueTick();
};
Async.prototype._consumeFunctionBuffer =
function Async$_consumeFunctionBuffer() {
var functionBuffer = this._functionBuffer;
while(functionBuffer.length() > 0) {
var fn = functionBuffer.shift();
var receiver = functionBuffer.shift();
var arg = functionBuffer.shift();
fn.call(receiver, arg);
}
this._reset();
this._consumeLateBuffer();
};
Async.prototype._consumeLateBuffer = function Async$_consumeLateBuffer() {
var buffer = this._lateBuffer;
while(buffer.length() > 0) {
var fn = buffer.shift();
var receiver = buffer.shift();
var arg = buffer.shift();
var res = tryCatch1(fn, receiver, arg);
if (res === errorObj) {
this._queueTick();
if (fn.domain != null) {
fn.domain.emit("error", res.e);
}
else {
throw res.e;
}
}
}
};
Async.prototype._queueTick = function Async$_queue() {
if (!this._isTickUsed) {
schedule(this.consumeFunctionBuffer);
this._isTickUsed = true;
}
};
Async.prototype._reset = function Async$_reset() {
this._isTickUsed = false;
this._length = 0;
};
module.exports = new Async();
},{"./global.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/global.js","./queue.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/queue.js","./schedule.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/schedule.js","./util.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/util.js"}],"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/bluebird.js":[function(require,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
var Promise = require("./promise.js")();
module.exports = Promise;
},{"./promise.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/promise.js"}],"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/call_get.js":[function(require,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise) {
Promise.prototype.call = function Promise$call(propertyName) {
var $_len = arguments.length;var args = new Array($_len - 1); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];}
return this._then(function(obj) {
return obj[propertyName].apply(obj, args);
},
void 0,
void 0,
void 0,
void 0
);
};
function Promise$getter(obj) {
var prop = typeof this === "string"
? this
: ("" + this);
return obj[prop];
}
Promise.prototype.get = function Promise$get(propertyName) {
return this._then(
Promise$getter,
void 0,
void 0,
propertyName,
void 0
);
};
};
},{}],"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/cancel.js":[function(require,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, INTERNAL) {
var errors = require("./errors.js");
var async = require("./async.js");
var CancellationError = errors.CancellationError;
Promise.prototype._cancel = function Promise$_cancel() {
if (!this.isCancellable()) return this;
var parent;
var promiseToReject = this;
while ((parent = promiseToReject._cancellationParent) !== void 0 &&
parent.isCancellable()) {
promiseToReject = parent;
}
var err = new CancellationError();
promiseToReject._attachExtraTrace(err);
promiseToReject._rejectUnchecked(err);
};
Promise.prototype.cancel = function Promise$cancel() {
if (!this.isCancellable()) return this;
async.invokeLater(this._cancel, this, void 0);
return this;
};
Promise.prototype.cancellable = function Promise$cancellable() {
if (this._cancellable()) return this;
this._setCancellable();
this._cancellationParent = void 0;
return this;
};
Promise.prototype.uncancellable = function Promise$uncancellable() {
var ret = new Promise(INTERNAL);
ret._setTrace(this);
ret._follow(this);
ret._unsetCancellable();
if (this._isBound()) ret._setBoundTo(this._boundTo);
return ret;
};
Promise.prototype.fork =
function Promise$fork(didFulfill, didReject, didProgress) {
var ret = this._then(didFulfill, didReject, didProgress,
void 0, void 0);
ret._setCancellable();
ret._cancellationParent = void 0;
return ret;
};
};
},{"./async.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/async.js","./errors.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/errors.js"}],"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/captured_trace.js":[function(require,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function() {
var inherits = require("./util.js").inherits;
var defineProperty = require("./es5.js").defineProperty;
var rignore = new RegExp(
"\\b(?:[a-zA-Z0-9.]+\\$_\\w+|" +
"tryCatch(?:1|2|Apply)|new \\w*PromiseArray|" +
"\\w*PromiseArray\\.\\w*PromiseArray|" +
"setTimeout|CatchFilter\\$_\\w+|makeNodePromisified|processImmediate|" +
"process._tickCallback|nextTick|Async\\$\\w+)\\b"
);
var rtraceline = null;
var formatStack = null;
function formatNonError(obj) {
var str;
if (typeof obj === "function") {
str = "[function " +
(obj.name || "anonymous") +
"]";
}
else {
str = obj.toString();
var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/;
if (ruselessToString.test(str)) {
try {
var newStr = JSON.stringify(obj);
str = newStr;
}
catch(e) {
}
}
if (str.length === 0) {
str = "(empty array)";
}
}
return ("(<" + snip(str) + ">, no stack trace)");
}
function snip(str) {
var maxChars = 41;
if (str.length < maxChars) {
return str;
}
return str.substr(0, maxChars - 3) + "...";
}
function CapturedTrace(ignoreUntil, isTopLevel) {
this.captureStackTrace(CapturedTrace, isTopLevel);
}
inherits(CapturedTrace, Error);
CapturedTrace.prototype.captureStackTrace =
function CapturedTrace$captureStackTrace(ignoreUntil, isTopLevel) {
captureStackTrace(this, ignoreUntil, isTopLevel);
};
CapturedTrace.possiblyUnhandledRejection =
function CapturedTrace$PossiblyUnhandledRejection(reason) {
if (typeof console === "object") {
var message;
if (typeof reason === "object" || typeof reason === "function") {
var stack = reason.stack;
message = "Possibly unhandled " + formatStack(stack, reason);
}
else {
message = "Possibly unhandled " + String(reason);
}
if (typeof console.error === "function" ||
typeof console.error === "object") {
console.error(message);
}
else if (typeof console.log === "function" ||
typeof console.log === "object") {
console.log(message);
}
}
};
CapturedTrace.combine = function CapturedTrace$Combine(current, prev) {
var curLast = current.length - 1;
for (var i = prev.length - 1; i >= 0; --i) {
var line = prev[i];
if (current[curLast] === line) {
current.pop();
curLast--;
}
else {
break;
}
}
current.push("From previous event:");
var lines = current.concat(prev);
var ret = [];
for (var i = 0, len = lines.length; i < len; ++i) {
if ((rignore.test(lines[i]) ||
(i > 0 && !rtraceline.test(lines[i])) &&
lines[i] !== "From previous event:")
) {
continue;
}
ret.push(lines[i]);
}
return ret;
};
CapturedTrace.isSupported = function CapturedTrace$IsSupported() {
return typeof captureStackTrace === "function";
};
var captureStackTrace = (function stackDetection() {
if (typeof Error.stackTraceLimit === "number" &&
typeof Error.captureStackTrace === "function") {
rtraceline = /^\s*at\s*/;
formatStack = function(stack, error) {
if (typeof stack === "string") return stack;
if (error.name !== void 0 &&
error.message !== void 0) {
return error.name + ". " + error.message;
}
return formatNonError(error);
};
var captureStackTrace = Error.captureStackTrace;
return function CapturedTrace$_captureStackTrace(
receiver, ignoreUntil) {
captureStackTrace(receiver, ignoreUntil);
};
}
var err = new Error();
if (typeof err.stack === "string" &&
typeof "".startsWith === "function" &&
(err.stack.startsWith("stackDetection@")) &&
stackDetection.name === "stackDetection") {
defineProperty(Error, "stackTraceLimit", {
writable: true,
enumerable: false,
configurable: false,
value: 25
});
rtraceline = /@/;
var rline = /[@\n]/;
formatStack = function(stack, error) {
if (typeof stack === "string") {
return (error.name + ". " + error.message + "\n" + stack);
}
if (error.name !== void 0 &&
error.message !== void 0) {
return error.name + ". " + error.message;
}
return formatNonError(error);
};
return function captureStackTrace(o) {
var stack = new Error().stack;
var split = stack.split(rline);
var len = split.length;
var ret = "";
for (var i = 0; i < len; i += 2) {
ret += split[i];
ret += "@";
ret += split[i + 1];
ret += "\n";
}
o.stack = ret;
};
}
else {
formatStack = function(stack, error) {
if (typeof stack === "string") return stack;
if ((typeof error === "object" ||
typeof error === "function") &&
error.name !== void 0 &&
error.message !== void 0) {
return error.name + ". " + error.message;
}
return formatNonError(error);
};
return null;
}
})();
return CapturedTrace;
};
},{"./es5.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/es5.js","./util.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/util.js"}],"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/catch_filter.js":[function(require,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(NEXT_FILTER) {
var util = require("./util.js");
var errors = require("./errors.js");
var tryCatch1 = util.tryCatch1;
var errorObj = util.errorObj;
var keys = require("./es5.js").keys;
var TypeError = errors.TypeError;
function CatchFilter(instances, callback, promise) {
this._instances = instances;
this._callback = callback;
this._promise = promise;
}
function CatchFilter$_safePredicate(predicate, e) {
var safeObject = {};
var retfilter = tryCatch1(predicate, safeObject, e);
if (retfilter === errorObj) return retfilter;
var safeKeys = keys(safeObject);
if (safeKeys.length) {
errorObj.e = new TypeError(
"Catch filter must inherit from Error "
+ "or be a simple predicate function");
return errorObj;
}
return retfilter;
}
CatchFilter.prototype.doFilter = function CatchFilter$_doFilter(e) {
var cb = this._callback;
var promise = this._promise;
var boundTo = promise._isBound() ? promise._boundTo : void 0;
for (var i = 0, len = this._instances.length; i < len; ++i) {
var item = this._instances[i];
var itemIsErrorType = item === Error ||
(item != null && item.prototype instanceof Error);
if (itemIsErrorType && e instanceof item) {
var ret = tryCatch1(cb, boundTo, e);
if (ret === errorObj) {
NEXT_FILTER.e = ret.e;
return NEXT_FILTER;
}
return ret;
} else if (typeof item === "function" && !itemIsErrorType) {
var shouldHandle = CatchFilter$_safePredicate(item, e);
if (shouldHandle === errorObj) {
var trace = errors.canAttach(errorObj.e)
? errorObj.e
: new Error(errorObj.e + "");
this._promise._attachExtraTrace(trace);
e = errorObj.e;
break;
} else if (shouldHandle) {
var ret = tryCatch1(cb, boundTo, e);
if (ret === errorObj) {
NEXT_FILTER.e = ret.e;
return NEXT_FILTER;
}
return ret;
}
}
}
NEXT_FILTER.e = e;
return NEXT_FILTER;
};
return CatchFilter;
};
},{"./errors.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/errors.js","./es5.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/es5.js","./util.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/util.js"}],"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/direct_resolve.js":[function(require,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
var util = require("./util.js");
var isPrimitive = util.isPrimitive;
var wrapsPrimitiveReceiver = util.wrapsPrimitiveReceiver;
module.exports = function(Promise) {
var returner = function Promise$_returner() {
return this;
};
var thrower = function Promise$_thrower() {
throw this;
};
var wrapper = function Promise$_wrapper(value, action) {
if (action === 1) {
return function Promise$_thrower() {
throw value;
};
}
else if (action === 2) {
return function Promise$_returner() {
return value;
};
}
};
Promise.prototype["return"] =
Promise.prototype.thenReturn =
function Promise$thenReturn(value) {
if (wrapsPrimitiveReceiver && isPrimitive(value)) {
return this._then(
wrapper(value, 2),
void 0,
void 0,
void 0,
void 0
);
}
return this._then(returner, void 0, void 0, value, void 0);
};
Promise.prototype["throw"] =
Promise.prototype.thenThrow =
function Promise$thenThrow(reason) {
if (wrapsPrimitiveReceiver && isPrimitive(reason)) {
return this._then(
wrapper(reason, 1),
void 0,
void 0,
void 0,
void 0
);
}
return this._then(thrower, void 0, void 0, reason, void 0);
};
};
},{"./util.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/util.js"}],"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/errors.js":[function(require,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
var global = require("./global.js");
var Objectfreeze = require("./es5.js").freeze;
var util = require("./util.js");
var inherits = util.inherits;
var notEnumerableProp = util.notEnumerableProp;
var Error = global.Error;
function markAsOriginatingFromRejection(e) {
try {
notEnumerableProp(e, "isAsync", true);
}
catch(ignore) {}
}
function originatesFromRejection(e) {
if (e == null) return false;
return ((e instanceof RejectionError) ||
e["isAsync"] === true);
}
function isError(obj) {
return obj instanceof Error;
}
function canAttach(obj) {
return isError(obj);
}
function subError(nameProperty, defaultMessage) {
function SubError(message) {
if (!(this instanceof SubError)) return new SubError(message);
this.message = typeof message === "string" ? message : defaultMessage;
this.name = nameProperty;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
inherits(SubError, Error);
return SubError;
}
var TypeError = global.TypeError;
if (typeof TypeError !== "function") {
TypeError = subError("TypeError", "type error");
}
var RangeError = global.RangeError;
if (typeof RangeError !== "function") {
RangeError = subError("RangeError", "range error");
}
var CancellationError = subError("CancellationError", "cancellation error");
var TimeoutError = subError("TimeoutError", "timeout error");
function RejectionError(message) {
this.name = "RejectionError";
this.message = message;
this.cause = message;
this.isAsync = true;
if (message instanceof Error) {
this.message = message.message;
this.stack = message.stack;
}
else if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
inherits(RejectionError, Error);
var key = "__BluebirdErrorTypes__";
var errorTypes = global[key];
if (!errorTypes) {
errorTypes = Objectfreeze({
CancellationError: CancellationError,
TimeoutError: TimeoutError,
RejectionError: RejectionError
});
notEnumerableProp(global, key, errorTypes);
}
module.exports = {
Error: Error,
TypeError: TypeError,
RangeError: RangeError,
CancellationError: errorTypes.CancellationError,
RejectionError: errorTypes.RejectionError,
TimeoutError: errorTypes.TimeoutError,
originatesFromRejection: originatesFromRejection,
markAsOriginatingFromRejection: markAsOriginatingFromRejection,
canAttach: canAttach
};
},{"./es5.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/es5.js","./global.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/global.js","./util.js":"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/util.js"}],"/Users/nolan/workspace/pouchdb-replication-stream/node_modules/bluebird/js/main/errors_api_rejection.js":[function(require,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in th