cannery-adapter-rest
Version:
The Cannery REST adapter
1,860 lines (1,498 loc) • 56.4 kB
JavaScript
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(global) {'use strict';
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var ajax = __webpack_require__(1);
var debug = __webpack_require__(17)('cannery-adapter-rest');
var adapterOptions = Symbol();
var endpointState = {};
var endpointResolver = {};
var storage = global.sessionStorage || {};
var RestAdapter = function () {
function RestAdapter() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var routes = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
_classCallCheck(this, RestAdapter);
this.routes = routes;
this[adapterOptions] = options;
}
_createClass(RestAdapter, [{
key: 'buildCacheKey',
value: function buildCacheKey(url) {
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var key = this.getUrl(url);
if (options.qs) {
key += '-' + JSON.stringify(options.qs);
}
if (options.headers) {
key += '-' + JSON.stringify(options.headers);
}
return key;
}
}, {
key: 'getRoutePath',
value: function getRoutePath(model) {
var routeArray = [model.constructor.name];
var child = model;
while (child.getParent()) {
routeArray.push(child.getParent().constructor.name);
child = child.getParent();
}
return routeArray.reverse().join('/');
}
}, {
key: 'parseOverrideRoute',
value: function parseOverrideRoute(uri, model) {
var parents = [];
var child = model;
while (child.getParent()) {
parents.push(child.getParent().id);
child = child.getParent();
}
uri = uri.replace(/{id}/g, model.id);
for (var i = 0; i < parents.length; i++) {
uri = uri.replace('{parents[' + i + ']}', parents[i]);
}
return uri;
}
}, {
key: 'getOverrideRoute',
value: function getOverrideRoute(requestType, model) {
var path = this.getRoutePath(model);
debug('ROUTE', requestType, path);
if (this.routes[path] && this.routes[path][requestType]) {
return this.parseOverrideRoute(this.routes[path][requestType], model);
}
}
}, {
key: 'buildNestedUrl',
value: function buildNestedUrl(url, child) {
var parent = child.getParent();
url = child.getName() + '/' + child.id + '/' + url;
if (parent) {
return this.buildNestedUrl(url, parent);
} else {
return url;
}
}
}, {
key: 'create',
value: function create(model, options) {
var url = this.getCreateRoute(model);
var requestOptions = this.createOptions(model, options);
requestOptions.body = this.getBody(model);
return ajax('POST', url, requestOptions).then(this.formatFetchResponse.bind(this));
}
}, {
key: 'createOptions',
value: function createOptions(model, options) {
options = options || {};
return Object.assign({}, {
qs: options.qs,
body: options.body,
headers: Object.assign({}, this[adapterOptions].headers, options.headers)
});
}
}, {
key: 'createOptionsWithEtags',
value: function createOptionsWithEtags(model, options, cacheKey) {
var requestOptions = this.createOptions(model, options);
//requestOptions.headers['If-None-Match'] = storage[`cannery-e-${cacheKey}`];
return requestOptions;
}
}, {
key: 'destroy',
value: function destroy(model, options) {
var url = this.getDestroyRoute(model);
var requestOptions = this.createOptions(model, options);
requestOptions.body = model.toJSON();
return ajax('DELETE', url, requestOptions).then(this.parseResponse.bind(this));
}
}, {
key: 'fetch',
value: function fetch(model) {
var _this = this;
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var url = this.getFetchRoute(model);
var cacheKey = this.buildCacheKey(url, options);
var requestOptions = this.createOptionsWithEtags(model, options, cacheKey);
if (endpointState[url] === 'fetching' || endpointState[url] === 'fetched') {
return endpointResolver[url];
}
endpointState[url] = 'fetching';
endpointResolver[url] = ajax('GET', url, requestOptions).then(function (response) {
return _this.formatFetchResponse(response, cacheKey);
}).then(function (response) {
endpointState[url] = 'fetched';
return response;
});
return endpointResolver[url];
}
}, {
key: 'fetchWithin',
value: function fetchWithin(model, parent) {
var _this2 = this;
var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
var url = this.getFetchWithinRoute(model, parent);
var cacheKey = this.buildCacheKey(url, options);
var requestOptions = this.createOptionsWithEtags(model, options, cacheKey);
if (endpointState[url] === 'fetching' || endpointState[url] === 'fetched') {
return endpointResolver[url];
}
endpointState[url] = 'fetching';
endpointResolver[url] = ajax('GET', this.getUrl(url), requestOptions).then(function (response) {
return _this2.formatFetchResponse(response, cacheKey);
}).then(function (response) {
endpointState[url] = 'fetched';
return response;
});
return endpointResolver[url];
}
}, {
key: 'findAll',
value: function findAll(Model) {
var _this3 = this;
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var url = this.getFindAllRoute(Model);
var cacheKey = this.buildCacheKey(url, options);
var requestOptions = this.createOptionsWithEtags(null, options, cacheKey);
return ajax('GET', url, requestOptions).then(function (response) {
return _this3.formatFindAllResponse(response, cacheKey);
});
}
}, {
key: 'findAllWithin',
value: function findAllWithin(Model, parent) {
var _this4 = this;
var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
var url = this.getFindAllWithinRoute(Model, parent);
var cacheKey = this.buildCacheKey(url, options);
var requestOptions = this.createOptionsWithEtags(parent, options, cacheKey);
return ajax('GET', this.getUrl(url), requestOptions).then(function (response) {
return _this4.formatFindAllResponse(response, cacheKey);
});
}
}, {
key: 'formatFetchResponse',
value: function formatFetchResponse(response, cacheKey) {
var body = this.parseResponse(response, cacheKey);
var envelope = this.getOptions().envelope;
return envelope ? body[envelope] : body;
}
}, {
key: 'formatFindAllResponse',
value: function formatFindAllResponse(response, cacheKey) {
var body = this.parseResponse(response, cacheKey);
var envelope = this.getOptions().arrayEnvelope;
return envelope ? body[envelope] : body;
}
}, {
key: 'getBody',
value: function getBody(model) {
return JSON.stringify(model.toJSON());
}
}, {
key: 'getCreateRoute',
value: function getCreateRoute(model) {
return this.getOverrideRoute('create', model) || this.getSingleFetchUrl(model);
}
}, {
key: 'getDestroyRoute',
value: function getDestroyRoute(model) {
return this.getOverrideRoute('destroy', model) || this.getSingleFetchUrl(model);
}
}, {
key: 'getFetchRoute',
value: function getFetchRoute(model) {
return this.getOverrideRoute('fetch', model) || this.getFetchUrl(model.getName(), model.id);
}
}, {
key: 'getFetchWithinRoute',
value: function getFetchWithinRoute(model, parent) {
return this.getOverrideRoute('fetch', model) || this.buildNestedUrl(model.getName(), parent);
}
}, {
key: 'getFindAllRoute',
value: function getFindAllRoute(Model) {
return this.getOverrideRoute('findAll', new Model()) || this.getUrl(new Model().getName());
}
}, {
key: 'getFindAllWithinRoute',
value: function getFindAllWithinRoute(Model, parent) {
var overrideModel = new Model();
overrideModel.getParent = function () {
return parent;
};
return this.getOverrideRoute('findAll', overrideModel) || this.buildNestedUrl(new Model().getName(), parent);
}
}, {
key: 'getUpdateRoute',
value: function getUpdateRoute(model) {
return this.getOverrideRoute('update', model) || this.getSingleFetchUrl(model);
}
}, {
key: 'getUrl',
value: function getUrl(url) {
var _getOptions = this.getOptions();
var urlRoot = _getOptions.urlRoot;
return '' + (urlRoot || '') + url;
}
}, {
key: 'getFetchUrl',
value: function getFetchUrl(url, id) {
if (id) {
return this.getUrl(url) + '/' + id;
}
return this.getUrl(url);
}
}, {
key: 'getSingleFetchUrl',
value: function getSingleFetchUrl(model) {
var parent = model.getParent();
var parentUrl = parent ? parent.getName() + '/' + parent.id + '/' : '';
return this.getFetchUrl(parentUrl + model.getName(), model.id);
}
}, {
key: 'getOptions',
value: function getOptions() {
return this[adapterOptions];
}
}, {
key: 'getResponseBody',
value: function getResponseBody(response, cacheKey) {
var cachedData = storage['cannery-d-' + cacheKey];
if (response.statusCode === 304 && cachedData) {
return cachedData;
}
if (response.headers.etag) {
storage['cannery-e-' + cacheKey] = response.headers.etag;
storage['cannery-d-' + cacheKey] = response.getBody();
}
return response.getBody();
}
}, {
key: 'parseResponse',
value: function parseResponse(response, cacheKey) {
var body = this.getResponseBody(response, cacheKey);
try {
return JSON.parse(body);
} catch (e) {
return {};
}
}
}, {
key: 'update',
value: function update(model) {
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var url = this.getUpdateRoute(model);
var requestOptions = this.createOptions(model, options);
requestOptions.body = this.getBody(model);
return ajax('PUT', url, requestOptions).then(this.formatFetchResponse.bind(this));
}
}]);
return RestAdapter;
}();
module.exports = RestAdapter;
/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
var Promise = __webpack_require__(2);
var Response = __webpack_require__(10);
var handleQs = __webpack_require__(11);
module.exports = doRequest;
function doRequest(method, url, options, callback) {
var result = new Promise(function (resolve, reject) {
var xhr = new window.XMLHttpRequest();
// check types of arguments
if (typeof method !== 'string') {
throw new TypeError('The method must be a string.');
}
if (typeof url !== 'string') {
throw new TypeError('The URL/path must be a string.');
}
if (typeof options === 'function') {
callback = options;
options = {};
}
if (options === null || options === undefined) {
options = {};
}
if (typeof options !== 'object') {
throw new TypeError('Options must be an object (or null).');
}
if (typeof callback !== 'function') {
callback = undefined;
}
method = method.toUpperCase();
options.headers = options.headers || {};
function attempt(n) {
doRequest(method, url, {
qs: options.qs,
headers: options.headers,
timeout: options.timeout
}).nodeify(function (err, res) {
var retry = err || res.statusCode >= 400;
if (typeof options.retry === 'function') {
retry = options.retry(err, res, n + 1);
}
if (n >= (options.maxRetries | 5)) {
retry = false;
}
if (retry) {
var delay = options.retryDelay;
if (typeof options.retryDelay === 'function') {
delay = options.retryDelay(err, res, n + 1);
}
delay = delay || 200;
setTimeout(function () {
attempt(n + 1);
}, delay);
} else {
if (err) reject(err);
else resolve(res);
}
});
}
if (options.retry && method === 'GET') {
return attempt(0);
}
// handle cross domain
var match;
var crossDomain = !!((match = /^([\w-]+:)?\/\/([^\/]+)/.exec(options.uri)) && (match[2] != window.location.host));
if (!crossDomain) options.headers['X-Requested-With'] = 'XMLHttpRequest';
// handle query string
if (options.qs) {
url = handleQs(url, options.qs);
}
// handle json body
if (options.json) {
options.body = JSON.stringify(options.json);
options.headers['Content-Type'] = 'application/json';
}
if (options.timeout) {
xhr.timeout = options.timeout;
var start = Date.now();
xhr.ontimeout = function () {
var duration = Date.now() - start;
var err = new Error('Request timed out after ' + duration + 'ms');
err.timeout = true;
err.duration = duration;
reject(err);
};
}
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
var headers = {};
xhr.getAllResponseHeaders().split('\r\n').forEach(function (header) {
var h = header.split(':');
if (h.length > 1) {
headers[h[0].toLowerCase()] = h.slice(1).join(':').trim();
}
});
var res = new Response(xhr.status, headers, xhr.responseText);
res.url = url;
resolve(res);
}
};
// method, url, async
xhr.open(method, url, true);
for (var name in options.headers) {
xhr.setRequestHeader(name, options.headers[name]);
}
// avoid sending empty string (#319)
xhr.send(options.body ? options.body : null);
});
result.getBody = function () {
return result.then(function (res) { return res.getBody(); });
};
return result.nodeify(callback);
}
/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
module.exports = __webpack_require__(3)
__webpack_require__(7)
__webpack_require__(8)
__webpack_require__(9)
/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
var asap = __webpack_require__(4)
module.exports = Promise;
function Promise(fn) {
if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new')
if (typeof fn !== 'function') throw new TypeError('not a function')
var state = null
var value = null
var deferreds = []
var self = this
this.then = function(onFulfilled, onRejected) {
return new self.constructor(function(resolve, reject) {
handle(new Handler(onFulfilled, onRejected, resolve, reject))
})
}
function handle(deferred) {
if (state === null) {
deferreds.push(deferred)
return
}
asap(function() {
var cb = state ? deferred.onFulfilled : deferred.onRejected
if (cb === null) {
(state ? deferred.resolve : deferred.reject)(value)
return
}
var ret
try {
ret = cb(value)
}
catch (e) {
deferred.reject(e)
return
}
deferred.resolve(ret)
})
}
function resolve(newValue) {
try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.')
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
var then = newValue.then
if (typeof then === 'function') {
doResolve(then.bind(newValue), resolve, reject)
return
}
}
state = true
value = newValue
finale()
} catch (e) { reject(e) }
}
function reject(newValue) {
state = false
value = newValue
finale()
}
function finale() {
for (var i = 0, len = deferreds.length; i < len; i++)
handle(deferreds[i])
deferreds = null
}
doResolve(fn, resolve, reject)
}
function Handler(onFulfilled, onRejected, resolve, reject){
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null
this.onRejected = typeof onRejected === 'function' ? onRejected : null
this.resolve = resolve
this.reject = reject
}
/**
* Take a potentially misbehaving resolver function and make sure
* onFulfilled and onRejected are only called once.
*
* Makes no guarantees about asynchrony.
*/
function doResolve(fn, onFulfilled, onRejected) {
var done = false;
try {
fn(function (value) {
if (done) return
done = true
onFulfilled(value)
}, function (reason) {
if (done) return
done = true
onRejected(reason)
})
} catch (ex) {
if (done) return
done = true
onRejected(ex)
}
}
/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(process, setImmediate) {
// Use the fastest possible means to execute a task in a future turn
// of the event loop.
// linked list of tasks (single, with head node)
var head = {task: void 0, next: null};
var tail = head;
var flushing = false;
var requestFlush = void 0;
var isNodeJS = false;
function flush() {
/* jshint loopfunc: true */
while (head.next) {
head = head.next;
var task = head.task;
head.task = void 0;
var domain = head.domain;
if (domain) {
head.domain = void 0;
domain.enter();
}
try {
task();
} catch (e) {
if (isNodeJS) {
// In node, uncaught exceptions are considered fatal errors.
// Re-throw them synchronously to interrupt flushing!
// Ensure continuation if the uncaught exception is suppressed
// listening "uncaughtException" events (as domains does).
// Continue in next event to avoid tick recursion.
if (domain) {
domain.exit();
}
setTimeout(flush, 0);
if (domain) {
domain.enter();
}
throw e;
} else {
// In browsers, uncaught exceptions are not fatal.
// Re-throw them asynchronously to avoid slow-downs.
setTimeout(function() {
throw e;
}, 0);
}
}
if (domain) {
domain.exit();
}
}
flushing = false;
}
if (typeof process !== "undefined" && process.nextTick) {
// Node.js before 0.9. Note that some fake-Node environments, like the
// Mocha test runner, introduce a `process` global without a `nextTick`.
isNodeJS = true;
requestFlush = function () {
process.nextTick(flush);
};
} else if (typeof setImmediate === "function") {
// In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
if (typeof window !== "undefined") {
requestFlush = setImmediate.bind(window, flush);
} else {
requestFlush = function () {
setImmediate(flush);
};
}
} else if (typeof MessageChannel !== "undefined") {
// modern browsers
// http://www.nonblocking.io/2011/06/windownexttick.html
var channel = new MessageChannel();
channel.port1.onmessage = flush;
requestFlush = function () {
channel.port2.postMessage(0);
};
} else {
// old browsers
requestFlush = function () {
setTimeout(flush, 0);
};
}
function asap(task) {
tail = tail.next = {
task: task,
domain: isNodeJS && process.domain,
next: null
};
if (!flushing) {
flushing = true;
requestFlush();
}
};
module.exports = asap;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5), __webpack_require__(6).setImmediate))
/***/ },
/* 5 */
/***/ function(module, exports) {
// shim for using process in browser
var process = module.exports = {};
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = setTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
clearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
setTimeout(drainQueue, 0);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
/***/ },
/* 6 */
/***/ function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(setImmediate, clearImmediate) {var nextTick = __webpack_require__(5).nextTick;
var apply = Function.prototype.apply;
var slice = Array.prototype.slice;
var immediateIds = {};
var nextImmediateId = 0;
// DOM APIs, for completeness
exports.setTimeout = function() {
return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);
};
exports.setInterval = function() {
return new Timeout(apply.call(setInterval, window, arguments), clearInterval);
};
exports.clearTimeout =
exports.clearInterval = function(timeout) { timeout.close(); };
function Timeout(id, clearFn) {
this._id = id;
this._clearFn = clearFn;
}
Timeout.prototype.unref = Timeout.prototype.ref = function() {};
Timeout.prototype.close = function() {
this._clearFn.call(window, this._id);
};
// Does not start the time, just sets up the members needed.
exports.enroll = function(item, msecs) {
clearTimeout(item._idleTimeoutId);
item._idleTimeout = msecs;
};
exports.unenroll = function(item) {
clearTimeout(item._idleTimeoutId);
item._idleTimeout = -1;
};
exports._unrefActive = exports.active = function(item) {
clearTimeout(item._idleTimeoutId);
var msecs = item._idleTimeout;
if (msecs >= 0) {
item._idleTimeoutId = setTimeout(function onTimeout() {
if (item._onTimeout)
item._onTimeout();
}, msecs);
}
};
// That's not how node.js implements it but the exposed api is the same.
exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) {
var id = nextImmediateId++;
var args = arguments.length < 2 ? false : slice.call(arguments, 1);
immediateIds[id] = true;
nextTick(function onNextTick() {
if (immediateIds[id]) {
// fn.call() is faster so we optimize for the common use-case
// @see http://jsperf.com/call-apply-segu
if (args) {
fn.apply(null, args);
} else {
fn.call(null);
}
// Prevent ids from leaking
exports.clearImmediate(id);
}
});
return id;
};
exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) {
delete immediateIds[id];
};
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(6).setImmediate, __webpack_require__(6).clearImmediate))
/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
var Promise = __webpack_require__(3)
var asap = __webpack_require__(4)
module.exports = Promise
Promise.prototype.done = function (onFulfilled, onRejected) {
var self = arguments.length ? this.then.apply(this, arguments) : this
self.then(null, function (err) {
asap(function () {
throw err
})
})
}
/***/ },
/* 8 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
//This file contains the ES6 extensions to the core Promises/A+ API
var Promise = __webpack_require__(3)
var asap = __webpack_require__(4)
module.exports = Promise
/* Static Functions */
function ValuePromise(value) {
this.then = function (onFulfilled) {
if (typeof onFulfilled !== 'function') return this
return new Promise(function (resolve, reject) {
asap(function () {
try {
resolve(onFulfilled(value))
} catch (ex) {
reject(ex);
}
})
})
}
}
ValuePromise.prototype = Promise.prototype
var TRUE = new ValuePromise(true)
var FALSE = new ValuePromise(false)
var NULL = new ValuePromise(null)
var UNDEFINED = new ValuePromise(undefined)
var ZERO = new ValuePromise(0)
var EMPTYSTRING = new ValuePromise('')
Promise.resolve = function (value) {
if (value instanceof Promise) return value
if (value === null) return NULL
if (value === undefined) return UNDEFINED
if (value === true) return TRUE
if (value === false) return FALSE
if (value === 0) return ZERO
if (value === '') return EMPTYSTRING
if (typeof value === 'object' || typeof value === 'function') {
try {
var then = value.then
if (typeof then === 'function') {
return new Promise(then.bind(value))
}
} catch (ex) {
return new Promise(function (resolve, reject) {
reject(ex)
})
}
}
return new ValuePromise(value)
}
Promise.all = function (arr) {
var args = Array.prototype.slice.call(arr)
return new Promise(function (resolve, reject) {
if (args.length === 0) return resolve([])
var remaining = args.length
function res(i, val) {
try {
if (val && (typeof val === 'object' || typeof val === 'function')) {
var then = val.then
if (typeof then === 'function') {
then.call(val, function (val) { res(i, val) }, reject)
return
}
}
args[i] = val
if (--remaining === 0) {
resolve(args);
}
} catch (ex) {
reject(ex)
}
}
for (var i = 0; i < args.length; i++) {
res(i, args[i])
}
})
}
Promise.reject = function (value) {
return new Promise(function (resolve, reject) {
reject(value);
});
}
Promise.race = function (values) {
return new Promise(function (resolve, reject) {
values.forEach(function(value){
Promise.resolve(value).then(resolve, reject);
})
});
}
/* Prototype Methods */
Promise.prototype['catch'] = function (onRejected) {
return this.then(null, onRejected);
}
/***/ },
/* 9 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
//This file contains then/promise specific extensions that are only useful for node.js interop
var Promise = __webpack_require__(3)
var asap = __webpack_require__(4)
module.exports = Promise
/* Static Functions */
Promise.denodeify = function (fn, argumentCount) {
argumentCount = argumentCount || Infinity
return function () {
var self = this
var args = Array.prototype.slice.call(arguments)
return new Promise(function (resolve, reject) {
while (args.length && args.length > argumentCount) {
args.pop()
}
args.push(function (err, res) {
if (err) reject(err)
else resolve(res)
})
var res = fn.apply(self, args)
if (res && (typeof res === 'object' || typeof res === 'function') && typeof res.then === 'function') {
resolve(res)
}
})
}
}
Promise.nodeify = function (fn) {
return function () {
var args = Array.prototype.slice.call(arguments)
var callback = typeof args[args.length - 1] === 'function' ? args.pop() : null
var ctx = this
try {
return fn.apply(this, arguments).nodeify(callback, ctx)
} catch (ex) {
if (callback === null || typeof callback == 'undefined') {
return new Promise(function (resolve, reject) { reject(ex) })
} else {
asap(function () {
callback.call(ctx, ex)
})
}
}
}
}
Promise.prototype.nodeify = function (callback, ctx) {
if (typeof callback != 'function') return this
this.then(function (value) {
asap(function () {
callback.call(ctx, null, value)
})
}, function (err) {
asap(function () {
callback.call(ctx, err)
})
})
}
/***/ },
/* 10 */
/***/ function(module, exports) {
'use strict';
module.exports = Response;
/**
* A response from a web request
*
* @param {Number} statusCode
* @param {Object} headers
* @param {Buffer} body
* @param {String} url
*/
function Response(statusCode, headers, body, url) {
if (typeof statusCode !== 'number') {
throw new TypeError('statusCode must be a number but was ' + (typeof statusCode));
}
if (headers === null) {
throw new TypeError('headers cannot be null');
}
if (typeof headers !== 'object') {
throw new TypeError('headers must be an object but was ' + (typeof headers));
}
this.statusCode = statusCode;
this.headers = {};
for (var key in headers) {
this.headers[key.toLowerCase()] = headers[key];
}
this.body = body;
this.url = url;
}
Response.prototype.getBody = function (encoding) {
if (this.statusCode >= 300) {
var err = new Error('Server responded with status code '
+ this.statusCode + ':\n' + this.body.toString());
err.statusCode = this.statusCode;
err.headers = this.headers;
err.body = this.body;
err.url = this.url;
throw err;
}
return encoding ? this.body.toString(encoding) : this.body;
};
/***/ },
/* 11 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
var parse = __webpack_require__(12).parse;
var stringify = __webpack_require__(12).stringify;
module.exports = handleQs;
function handleQs(url, query) {
url = url.split('?');
var start = url[0];
var qs = (url[1] || '').split('#')[0];
var end = url[1] && url[1].split('#').length > 1 ? '#' + url[1].split('#')[1] : '';
var baseQs = parse(qs);
for (var i in query) {
baseQs[i] = query[i];
}
qs = stringify(baseQs);
if (qs !== '') {
qs = '?' + qs;
}
return start + qs + end;
}
/***/ },
/* 12 */
/***/ function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(13);
/***/ },
/* 13 */
/***/ function(module, exports, __webpack_require__) {
// Load modules
var Stringify = __webpack_require__(14);
var Parse = __webpack_require__(16);
// Declare internals
var internals = {};
module.exports = {
stringify: Stringify,
parse: Parse
};
/***/ },
/* 14 */
/***/ function(module, exports, __webpack_require__) {
// Load modules
var Utils = __webpack_require__(15);
// Declare internals
var internals = {
delimiter: '&',
arrayPrefixGenerators: {
brackets: function (prefix, key) {
return prefix + '[]';
},
indices: function (prefix, key) {
return prefix + '[' + key + ']';
},
repeat: function (prefix, key) {
return prefix;
}
}
};
internals.stringify = function (obj, prefix, generateArrayPrefix) {
if (Utils.isBuffer(obj)) {
obj = obj.toString();
}
else if (obj instanceof Date) {
obj = obj.toISOString();
}
else if (obj === null) {
obj = '';
}
if (typeof obj === 'string' ||
typeof obj === 'number' ||
typeof obj === 'boolean') {
return [encodeURIComponent(prefix) + '=' + encodeURIComponent(obj)];
}
var values = [];
if (typeof obj === 'undefined') {
return values;
}
var objKeys = Object.keys(obj);
for (var i = 0, il = objKeys.length; i < il; ++i) {
var key = objKeys[i];
if (Array.isArray(obj)) {
values = values.concat(internals.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix));
}
else {
values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix));
}
}
return values;
};
module.exports = function (obj, options) {
options = options || {};
var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter;
var keys = [];
if (typeof obj !== 'object' ||
obj === null) {
return '';
}
var arrayFormat;
if (options.arrayFormat in internals.arrayPrefixGenerators) {
arrayFormat = options.arrayFormat;
}
else if ('indices' in options) {
arrayFormat = options.indices ? 'indices' : 'repeat';
}
else {
arrayFormat = 'indices';
}
var generateArrayPrefix = internals.arrayPrefixGenerators[arrayFormat];
var objKeys = Object.keys(obj);
for (var i = 0, il = objKeys.length; i < il; ++i) {
var key = objKeys[i];
keys = keys.concat(internals.stringify(obj[key], key, generateArrayPrefix));
}
return keys.join(delimiter);
};
/***/ },
/* 15 */
/***/ function(module, exports) {
// Load modules
// Declare internals
var internals = {};
exports.arrayToObject = function (source) {
var obj = {};
for (var i = 0, il = source.length; i < il; ++i) {
if (typeof source[i] !== 'undefined') {
obj[i] = source[i];
}
}
return obj;
};
exports.merge = function (target, source) {
if (!source) {
return target;
}
if (typeof source !== 'object') {
if (Array.isArray(target)) {
target.push(source);
}
else {
target[source] = true;
}
return target;
}
if (typeof target !== 'object') {
target = [target].concat(source);
return target;
}
if (Array.isArray(target) &&
!Array.isArray(source)) {
target = exports.arrayToObject(target);
}
var keys = Object.keys(source);
for (var k = 0, kl = keys.length; k < kl; ++k) {
var key = keys[k];
var value = source[key];
if (!target[key]) {
target[key] = value;
}
else {
target[key] = exports.merge(target[key], value);
}
}
return target;
};
exports.decode = function (str) {
try {
return decodeURIComponent(str.replace(/\+/g, ' '));
} catch (e) {
return str;
}
};
exports.compact = function (obj, refs) {
if (typeof obj !== 'object' ||
obj === null) {
return obj;
}
refs = refs || [];
var lookup = refs.indexOf(obj);
if (lookup !== -1) {
return refs[lookup];
}
refs.push(obj);
if (Array.isArray(obj)) {
var compacted = [];
for (var i = 0, il = obj.length; i < il; ++i) {
if (typeof obj[i] !== 'undefined') {
compacted.push(obj[i]);
}
}
return compacted;
}
var keys = Object.keys(obj);
for (i = 0, il = keys.length; i < il; ++i) {
var key = keys[i];
obj[key] = exports.compact(obj[key], refs);
}
return obj;
};
exports.isRegExp = function (obj) {
return Object.prototype.toString.call(obj) === '[object RegExp]';
};
exports.isBuffer = function (obj) {
if (obj === null ||
typeof obj === 'undefined') {
return false;
}
return !!(obj.constructor &&
obj.constructor.isBuffer &&
obj.constructor.isBuffer(obj));
};
/***/ },
/* 16 */
/***/ function(module, exports, __webpack_require__) {
// Load modules
var Utils = __webpack_require__(15);
// Declare internals
var internals = {
delimiter: '&',
depth: 5,
arrayLimit: 20,
parameterLimit: 1000
};
internals.parseValues = function (str, options) {
var obj = {};
var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
for (var i = 0, il = parts.length; i < il; ++i) {
var part = parts[i];
var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1;
if (pos === -1) {
obj[Utils.decode(part)] = '';
}
else {
var key = Utils.decode(part.slice(0, pos));
var val = Utils.decode(part.slice(pos + 1));
if (!Object.prototype.hasOwnProperty.call(obj, key)) {
obj[key] = val;
}
else {
obj[key] = [].concat(obj[key]).concat(val);
}
}
}
return obj;
};
internals.parseObject = function (chain, val, options) {
if (!chain.length) {
return val;
}
var root = chain.shift();
var obj = {};
if (root === '[]') {
obj = [];
obj = obj.concat(internals.parseObject(chain, val, options));
}
else {
var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root;
var index = parseInt(cleanRoot, 10);
var indexString = '' + index;
if (!isNaN(index) &&
root !== cleanRoot &&
indexString === cleanRoot &&
index >= 0 &&
index <= options.arrayLimit) {
obj = [];
obj[index] = internals.parseObject(chain, val, options);
}
else {
obj[cleanRoot] = internals.parseObject(chain, val, options);
}
}
return obj;
};
internals.parseKeys = function (key, val, options) {
if (!key) {
return;
}
// The regex chunks
var parent = /^([^\[\]]*)/;
var child = /(\[[^\[\]]*\])/g;
// Get the parent
var segment = parent.exec(key);
// Don't allow them to overwrite object prototype properties
if (Object.prototype.hasOwnProperty(segment[1])) {
return;
}
// Stash the parent if it exists
var keys = [];
if (segment[1]) {
keys.push(segment[1]);
}
// Loop through children appending to the array until we hit depth
var i = 0;
while ((segment = child.exec(key)) !== null && i < options.depth) {
++i;
if (!Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g, ''))) {
keys.push(segment[1]);
}
}
// If there's a remainder, just add whatever is left
if (segment) {
keys.push('[' + key.slice(segment.index) + ']');
}
return internals.parseObject(keys, val, options);
};
module.exports = function (str, options) {
if (str === '' ||
str === null ||
typeof str === 'undefined') {
return {};
}
options = options || {};
options.delimiter = typeof options.delimiter === 'string' || Utils.isRegExp(options.delimiter) ? options.delimiter : internals.delimiter;
options.depth = typeof options.depth === 'number' ? options.depth : internals.depth;
options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : internals.arrayLimit;
options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : internals.parameterLimit;
var tempObj = typeof str === 'string' ? internals.parseValues(str, options) : str;
var obj = {};
// Iterate over the keys and setup the new object
var keys = Object.keys(tempObj);
for (var i = 0, il = keys.length; i < il; ++i) {
var key = keys[i];
var newObj = internals.parseKeys(key, tempObj[key], options);
obj = Utils.merge(obj, newObj);
}
return Utils.compact(obj);
};
/***/ },
/* 17 */
/***/ function(module, exports, __webpack_require__) {
/**
* This is the web browser implementation of `debug()`.
*
* Expose `debug()` as the module.
*/
exports = module.exports = __webpack_require__(18);
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.storage = 'undefined' != typeof chrome
&& 'undefined' != typeof chrome.storage
? chrome.storage.local
: localstorage();
/**
* Colors.
*/
exports.colors = [
'lightseagreen',
'forestgreen',
'goldenrod',
'dodgerblue',
'darkorchid',
'crimson'
];
/**
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
* and the Firebug extension (any Firefox version) are known
* to support "%c" CSS customizations.
*
* TODO: add a `localStorage` variable to explicitly enable/disable colors
*/
function useColors() {
// is webkit? http://stackoverflow.com/a/16459606/376773
return ('WebkitAppearance' in document.documentElement.style) ||
// is firebug? http://stackoverflow.com/a/398120/376773
(window.console && (console.firebug || (console.exception && console.table))) ||
// is firefox >= v31?
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
(navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
}
/**
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
*/
exports.formatters.j = function(v) {
return JSON.stringify(v);
};
/**
* Colorize log arguments if enabled.
*
* @api public
*/
function formatArgs() {
var args = arguments;
var useColors = this.useColors;
args[0] = (useColors ? '%c' : '')
+ this.namespace
+ (useColors ? ' %c' : ' ')
+ args[0]
+ (useColors ? '%c ' : ' ')
+ '+' + exports.humanize(this.diff);
if (!useColors) return args;
var c = 'color: ' + this.color;
args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
// the final "%c" is somewhat tricky, because there could be other
// arguments passed either before or after the %c, so we need to
// figure out the correct index to insert the CSS into
var index = 0;
var lastC = 0;
args[0].replace(/%[a-z%]/g, function(match) {
if ('%%' === match) return;
index++;
if ('%c' === match) {
// we only are interested in the *last* %c
// (the user may have provided their own)
lastC = index;
}
});
args.splice(lastC, 0, c);
return args;
}
/**
* Invokes `console.log()` when available.
* No-op when `console.log` is not a "function".
*
* @api public
*/
function log() {
// this hackery is required for IE8/9, where
// the `console.log` function doesn't have 'apply'
return 'object' === typeof console
&& console.log
&& Function.prototype.apply.call(console.log, console, arguments);
}
/**
* Save `namespaces`.
*
* @param {String} namespaces
* @api private
*/
function save(namespaces) {
try {
if (null == namespaces) {
exports.storage.removeItem('debug');
} else {
exports.storage.debug = namespaces;
}
} catch(e) {}
}
/**
* Load `namespaces`.
*
* @return {String} returns the previously persisted debug modes
* @api private
*/
function load() {
var r;
try {
r = exports.storage.debug;
} catch(e) {}
return r;
}
/**
* Enable namespaces listed in `localStorage.debug` initially.
*/
exports.enable(load());
/**
* Localstorage attempts to return the localstorage.
*
* This is necessary because safari throws
* when a user disables cookies/localstorage
* and you attempt to access it.
*
* @return {LocalStorage}
* @api private
*/
function localstorage(){
try {
return window.localStorage;
} catch (e) {}
}
/***/ },
/* 18 */
/***/ function(module, exports, __webpack_require__) {
/**
* This is the common logic for both the Node.js and web browser
* implementations of `debug()`.
*
* Expose `debug()` as the module.
*/
exports = module.exports = debug;
exports.coerce = coerce;
exports.disable = disable;
exports.enable = enable;
exports.enabled = enabled;
exports.humanize = __webpack_require__(19);
/**
* The curren