UNPKG

starmapjs

Version:

Starmap makes client-side Waterline/Sails easy!

1,638 lines (1,432 loc) 1.59 MB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.starmap = f()}})(function(){var define,module,exports;return (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})({1:[function(require,module,exports){ var Promise = require('bluebird'); var _ = require('lodash'); var utils = require('./utils'); var EventEmitter = require('events').EventEmitter; var util = require('util'); var publicModel = require('./publicModel'); var modelItem = require('./modelItem'); /** * An actual model that syncs with the server * * This object contains the internal model representation, and updates any * objects bound to it. * * @param {object} io the socket.io object * @param {string} name * @param itemDef {object?} * @param modelDef {object?} * @param filter {object?} * @constructor */ function Model(io, name, itemDef, modelDef, filter) { EventEmitter.call(this); //name = name.toLowerCase(); this.io = io; this.name = name; this.url = utils.resolveName(name); this.itemDef = itemDef || {}; this.modelDef = modelDef || {}; this.filter = filter || {}; this.children = []; this.eventHandlers = {}; this.bindings = []; this.value = publicModel(this, new Promise(function(resolve, reject) { this.on('ready', resolve()); }.bind(this))); this.on('created', this._onCreated.bind(this)); this.on('updated', this._onUpdated.bind(this)); this.on('destroyed', this._onDestroyed.bind(this)); io.socket.on(name, function(message) { this.emit(message.verb, message); }.bind(this)); this.refresh().then(function() { this.emit('ready'); }.bind(this)); } util.inherits(Model, EventEmitter); module.exports = Model; Model.prototype._addItem = function(child) { if (this.value.indexOf(child) !== -1) return; this.value._push(child); }; Model.prototype._removeItem = function(child) { var index = this.value.indexOf(child); if (index !== -1) this.value._splice(index, 1); }; Model.prototype._removeAll = function() { while (this.value.length) this.value._pop(); }; /** * Triggered when a new item is added to the model * * @param {Object} message * @private */ Model.prototype._onCreated = function(message) { var newChild = modelItem(message.data, this); this.childMatches(newChild).then(function(matches) { if (matches) this._addItem(newChild); }.bind(this)); }; /** * Triggered when an item is modified * * @param {Object} message * @private */ Model.prototype._onUpdated = function(message) { var itemWithId = this.value.itemById(message.id); if (itemWithId) itemWithId.update(message.data, false); }; /** * Triggered when an item is destroyed * * @param {Object} message * @private */ Model.prototype._onDestroyed = function(message) { var itemWithId = this.value.itemById(message.id); if(itemWithId) this._removeItem(itemWithId); }; /** * Finds if a child matches the filter for this model instance * * @param {Object} child */ Model.prototype.childMatches = function(child) { return Promise.resolve((function() { // if they are not the same model, they do not match if (child.model.name !== this.name) return false; // if they are the same model and the model doesn't have a filter, they match if (_.isEqual(this.filter, {})) return true; // otherwise compare the filter return child.matches(this.filter); }.bind(this)())); }; /** * Re-fetches all items and adds them * * @returns {Model} */ Model.prototype.refresh = function() { return utils.socketGet(this.io, this.url, this.filter).then(function(data) { var dat = _.isArray(data) ? data : [data]; this._removeAll(); for (var i = 0; i < dat.length; i++) { this._addItem(modelItem(dat[i], this)); } }.bind(this)); }; /** * Saves all items in the model * */ Model.prototype.save = function() { _.forEach(this.value, function(item) { item.save(); }); }; },{"./modelItem":4,"./publicModel":5,"./utils":6,"bluebird":7,"events":8,"lodash":13,"util":12}],2:[function(require,module,exports){ /** * Internally gets a model */ var _ = require('lodash'); var Model = require('./Model'); var utils = require('./utils'); var modelCache = {}; var isSubscribed = {}; /** * Creates or gets a model from the cache * * @param io * @param {string} name the model name * @param {object?} itemDef * @param {object?} modelDef * @param {object?} filter * @returns {object} */ module.exports = function(io, name, itemDef, modelDef, filter) { filter = filter || {}; name = name.toLowerCase(); var cacheName = name + JSON.stringify(filter); if (_.has(modelCache, cacheName)) { var model = modelCache[cacheName]; // allow modification of itemDef and modelDef after a model has been fetched if (itemDef) { model.itemDef = itemDef; model.refresh(); } if (modelDef) model.modelDef = modelDef; return model.value; } var mdl = new Model(io, name, itemDef, modelDef, filter); if (!isSubscribed[name]) { utils.socketGet(io, mdl.url); isSubscribed[name] = true; } modelCache[cacheName] = mdl; return mdl.value; }; },{"./Model":1,"./utils":6,"lodash":13}],3:[function(require,module,exports){ /** * Starmap - easy database manipulation with Sails * * @preserve */ var Promise = require('bluebird'); var _ = require('lodash'); var gm = require('./getModel'); var utils = require('./utils'); function get(io) { /** * Creates or updates a model definition * * @param {string} name * @param itemDef {object?} the item definition * @param modelDef {object?} the model definition * @returns {object} the model */ function getModel(name, itemDef, modelDef) { return gm(io, name, itemDef, modelDef); } getModel.model = getModel; /** * Creates a new instance of the model * * @param {string} name * @param {object?} props * @returns {object} */ getModel.create = function(name, props) { return getModel(name).create(props); }; /** * Finds all matching items. * The same as .model(name).find(filter) * * @param {string} name * @param filter * @returns {Promise} */ getModel.find = function(name, filter) { return getModel(name).find(filter); }; /** * Finds a single matching item * The same as .model(name).findOne(filter) * * @param {string} name * @param filter * @returns {Promise} */ getModel.findOne = function(name, filter) { return getModel(name).findOne(filter); }; /** * * * @param func * @param subProps * @returns {*} */ getModel.calculate = utils.createCalculateProperty; return getModel; } if (window.io) module.exports = get(window.io); else module.exports = get; // for testing window.starmap = module.exports; },{"./getModel":2,"./utils":6,"bluebird":7,"lodash":13}],4:[function(require,module,exports){ var _ = require('lodash'); var utils = require('./utils'); var Promise = require('bluebird'); /** * Updates the model to represent the given data * * @param {object} item * @param {Model} model * @param {object} data the data to add to the model * @param {object?} funcParams parameters to pass to any precalc functions * @returns {Promise} */ function update(item, model, data, funcParams) { var working = []; var definedByData = []; _.forEach(data, function(value, key) { if (_.isFunction(value)) { working.push(Promise.resolve(value()).then(function(val) { item[key] = val; })); } else item[key] = value; definedByData.push(value); }); _.forEach(model.itemDef, function(value, key) { if (value && value.__precalc) { var func = value.__precalc, previousVal = data[key]; working.push(Promise.resolve(func.call(item, previousVal, funcParams || {})).then(function(val) { item[key] = (val && val._stWrapped) ? val.val : val; })); } // if the property has not been set from the itemDef yet. This allows item def properties to be changed else if (!_.has(item, key) || definedByData.indexOf(key) !== -1) item[key] = value; }); return Promise.all(working); } /** * Gets properties to be synced with the server * * @param {object} item * @param {Model} model * @param {object?} props * @returns {object} */ function serverProperties(item, model, props) { var result = {}; var toRefresh = []; _.forEach(props || item, function(val, key) { if (val == null) return; if (val._isModelItem) { result[key] = val.id; toRefresh.push(val); } else if (_.isArray(val)) { result[key] = _.map(val, function(item) { if (item._isModelItem) { toRefresh.push(item); return item.id; } return item; }); } else if (_.has(model.itemDef, key)) { if (_.has(model.itemDef[key], '__connection')) result[key] = val; } else result[key] = val; }); return { properties: result, refresh: toRefresh }; } /** * Creates the item on the server * * @param {object} item * @param {Model} model * @param {object?} data * @returns {Promise} */ function create(item, model, data) { var serverProps = serverProperties(item, model, data).properties; return utils.socketPut(model.io, model.url + '/create/', serverProps).then(function(response) { _.merge(serverProps, response); return update(item, model, serverProps); }).then(function() { // Refresh all items that were referenced - some of their properties might change return Promise.all(_.map(serverProps.refresh, function(item) { return item.refresh(); })); }); } /** * A single model item that is synced with the server * * @param {object} data * @param {Model} model */ function modelItem(data, model) { var res = {}; utils.defineProperties(res, { _isModelItem: { value: true }, model: { value: model.value }, update: { value: function(data, sync) { if (sync == null) sync = true; return update(res, model, data).then(function() { if (!sync) return; return res.save(); }); } }, save: { value: function() { if (_.has(res, 'id')) { var props = serverProperties(res, model); return utils.socketPost(model.io, model.url + '/update/' + res.id, props.properties).then(function() { return Promise.all(_.map(props.refresh, function(item) { return item.refresh(); })); }); } return create(res, model); } }, refresh: { value: function() { if (!_.has(res, 'id')) return create(res, model); return utils.socketGet(model.io, model.url + '/' + res.id).then(function(data) { return update(res, model, data, { noRefresh: true }); }); } }, delete: { value: function() { model._removeItem(res); return utils.socketDelete(model.io, model.url, { id: res.id }); } }, matches: { value: function(query) { return utils.socketGet(model.io, model.url, query).then(function(r) { for (var i = 0; i < r.length; i++) { if (r[i].id === res.id) return true; } return false; }); } }, then: { value: function() { return res.ready.then.apply(res.ready, arguments); } }, catch: { value: function() { return res.ready.catch.apply(res.ready, arguments); } } }); res.ready = Promise.resolve(); update(res, model, data || {}); return res; } module.exports = modelItem; },{"./utils":6,"bluebird":7,"lodash":13}],5:[function(require,module,exports){ var Promise = require('bluebird'); var _ = require('lodash'); var utils = require('./utils'); var getModel = require('./getModel'); var modelItem = require('./modelItem'); var arrayPop = Array.prototype.pop, arrayPush = Array.prototype.push, arrayShift = Array.prototype.shift, arraySplice = Array.prototype.splice, arrayUnshift = Array.prototype.unshift, arraySlice = Array.prototype.slice; /** * Creates a public model object * * @param {Model} model * @param {Promise} readyPromise * @returns {Array} the public object */ function publicModel(model, readyPromise) { var res = []; function find(filter) { var mergedFilter = _.merge({}, model.filter, filter); var filteredModel = getModel(model.io, model.name, model.itemDef, model.modelDef, mergedFilter); if (model.children.indexOf(filteredModel) === -1) model.children.push(filteredModel); return filteredModel; } function getByIds(ids) { var items = []; for (var i = 0; i < res.length; i++) { if (ids.indexOf(res[i].id) !== -1) items.push(res[i]); } return items; } utils.defineProperties(res, { _isModel: { value: true }, name: { value: model.name }, ready: { value: readyPromise }, create: { value: function(props) { props = props || {}; var item = modelItem(props, model); item.ready = item.update(props).then(function() { model._addItem(item); }); return item; } }, itemById: { value: function(id) { for (var i = 0; i < this.length; i++) { if (this[i].id === id) return this[i]; } return false; } }, find: { value: find }, filter: { value: find }, findOne: { value: function(filter) { return find(filter).then(function(val) { if (val.length) return val[0]; return false; }); } }, refresh: { value: function() { return Promise.all(_.map(this, function(item) { return item.refresh(); })); } }, then: { value: function() { return readyPromise.then.apply(readyPromise, arguments); } }, catch: { value: function() { return readyPromise.catch.apply(readyPromise, arguments); } }, /** * Override array modification properties */ _pop: { value: arrayPop }, pop: { value: function() { var lastItem = arrayPop.call(this); lastItem.delete(); return lastItem; } }, _push: { value: arrayPush }, push: { value: function() { for (var i = 0; i < arguments.length; i++) { this.create(arguments[i]); } return this.length; } }, _shift: { value: arrayShift }, shift: { value: function() { var firstItem = arrayShift.call(this); firstItem.delete(); return firstItem; } }, _splice: { value: arraySplice }, splice: { value: function(start, deleteCount) { var items = _.map(arraySlice.call(arguments, 2), function(itm) { var item = modelItem(itm, model); item.ready = item.update(itm); return item; }); items.unshift(start, deleteCount); var removed = arraySplice.apply(this, items); for (var i = 0; i < removed.length; i++) removed.delete(); return removed; } }, _unshift: { value: arrayUnshift }, unshift: { value: function() { return arrayUnshift.apply(this, _.map(arguments, function(itm) { var item = modelItem(itm, model); item.ready = item.update(itm); return item; })); } }, __connection: { value: model.name } }); //Object.defineProperties(res, ); _.merge(res, utils.createCalculateProperty(function(previous, flags) { if (!previous) return; var isArray = _.isArray(previous), prevId; if (isArray) { prevId = _.map(previous, function(val) { if (_.isNumber(val)) return val; return val.id; }); } else prevId = [_.isNumber(previous) ? previous : previous.id]; return readyPromise.then(function() { var itms = getByIds(prevId); function getItems() { if (isArray) return { _stWrapped: true, val: itms}; return { _stWrapped: true, val: itms.length ? itms[0] : null }; } if (!flags.noRefresh) { return Promise.all(_.map(itms, function(item) { return item.refresh(); })).then(getItems); } return getItems(); }); }.bind(this))); return res; } module.exports = publicModel; },{"./getModel":2,"./modelItem":4,"./utils":6,"bluebird":7,"lodash":13}],6:[function(require,module,exports){ var _ = require('lodash'); /** * Converts the model name to a path * * TODO: this might not be neccessary * * @param {string} name * @returns {string} */ exports.resolveName = function(name) { var prefixIndex = name.indexOf('/'), prefix = ''; if (prefixIndex !== -1) { prefix = name.substring(0, prefixIndex) + '/'; name = name.substring(prefixIndex + 1); } return '/' + prefix + name; }; var requestId = 0; function promisifySocket(fName) { return function(io, url, additional) { var rid = requestId++; return (new Promise(function(resolve, reject) { io.socket[fName](url, additional, function (response) { if (response.error) reject(response.error); else if (_.isString(response)) reject(new Error(response)); else resolve(response); }); })); } } exports.socketGet = promisifySocket("get"); exports.socketPost = promisifySocket("post"); exports.socketPut = promisifySocket("put"); exports.socketDelete = promisifySocket("delete"); exports.defineProperties = (function() { if (Object.defineProperties) return Object.defineProperties; return function(base, obj) { _.extend(base, _.mapValues(obj, function(val) { return val.value; })); } }()); exports.createCalculateProperty = function(func, subProps) { return _.merge({ __precalc: func }, subProps); }; },{"lodash":13}],7:[function(require,module,exports){ (function (process,global){ /* @preserve * The MIT License (MIT) * * 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. * */ /** * bluebird build version 2.9.27 * Features enabled: core, race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, cancel, using, filter, any, each, timers */ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Promise=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof _dereq_=="function"&&_dereq_;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 _dereq_=="function"&&_dereq_;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise) { var SomePromiseArray = Promise._SomePromiseArray; function any(promises) { var ret = new SomePromiseArray(promises); var promise = ret.promise(); ret.setHowMany(1); ret.setUnwrap(); ret.init(); return promise; } Promise.any = function (promises) { return any(promises); }; Promise.prototype.any = function () { return any(this); }; }; },{}],2:[function(_dereq_,module,exports){ "use strict"; var firstLineError; try {throw new Error(); } catch (e) {firstLineError = e;} var schedule = _dereq_("./schedule.js"); var Queue = _dereq_("./queue.js"); var util = _dereq_("./util.js"); function Async() { this._isTickUsed = false; this._lateQueue = new Queue(16); this._normalQueue = new Queue(16); this._trampolineEnabled = true; var self = this; this.drainQueues = function () { self._drainQueues(); }; this._schedule = schedule.isStatic ? schedule(this.drainQueues) : schedule; } Async.prototype.disableTrampolineIfNecessary = function() { if (util.hasDevTools) { this._trampolineEnabled = false; } }; Async.prototype.enableTrampoline = function() { if (!this._trampolineEnabled) { this._trampolineEnabled = true; this._schedule = function(fn) { setTimeout(fn, 0); }; } }; Async.prototype.haveItemsQueued = function () { return this._normalQueue.length() > 0; }; Async.prototype.throwLater = function(fn, arg) { if (arguments.length === 1) { arg = fn; fn = function () { throw arg; }; } var domain = this._getDomain(); if (domain !== undefined) fn = domain.bind(fn); if (typeof setTimeout !== "undefined") { setTimeout(function() { fn(arg); }, 0); } else try { this._schedule(function() { fn(arg); }); } catch (e) { throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/m3OTXk\u000a"); } }; Async.prototype._getDomain = function() {}; if (!true) { if (util.isNode) { var EventsModule = _dereq_("events"); var domainGetter = function() { var domain = process.domain; if (domain === null) return undefined; return domain; }; if (EventsModule.usingDomains) { Async.prototype._getDomain = domainGetter; } else { var descriptor = Object.getOwnPropertyDescriptor(EventsModule, "usingDomains"); if (descriptor) { if (!descriptor.configurable) { process.on("domainsActivated", function() { Async.prototype._getDomain = domainGetter; }); } else { var usingDomains = false; Object.defineProperty(EventsModule, "usingDomains", { configurable: false, enumerable: true, get: function() { return usingDomains; }, set: function(value) { if (usingDomains || !value) return; usingDomains = true; Async.prototype._getDomain = domainGetter; util.toFastProperties(process); process.emit("domainsActivated"); } }); } } } } } function AsyncInvokeLater(fn, receiver, arg) { var domain = this._getDomain(); if (domain !== undefined) fn = domain.bind(fn); this._lateQueue.push(fn, receiver, arg); this._queueTick(); } function AsyncInvoke(fn, receiver, arg) { var domain = this._getDomain(); if (domain !== undefined) fn = domain.bind(fn); this._normalQueue.push(fn, receiver, arg); this._queueTick(); } function AsyncSettlePromises(promise) { var domain = this._getDomain(); if (domain !== undefined) { var fn = domain.bind(promise._settlePromises); this._normalQueue.push(fn, promise, undefined); } else { this._normalQueue._pushOne(promise); } this._queueTick(); } if (!util.hasDevTools) { Async.prototype.invokeLater = AsyncInvokeLater; Async.prototype.invoke = AsyncInvoke; Async.prototype.settlePromises = AsyncSettlePromises; } else { Async.prototype.invokeLater = function (fn, receiver, arg) { if (this._trampolineEnabled) { AsyncInvokeLater.call(this, fn, receiver, arg); } else { setTimeout(function() { fn.call(receiver, arg); }, 100); } }; Async.prototype.invoke = function (fn, receiver, arg) { if (this._trampolineEnabled) { AsyncInvoke.call(this, fn, receiver, arg); } else { setTimeout(function() { fn.call(receiver, arg); }, 0); } }; Async.prototype.settlePromises = function(promise) { if (this._trampolineEnabled) { AsyncSettlePromises.call(this, promise); } else { setTimeout(function() { promise._settlePromises(); }, 0); } }; } Async.prototype.invokeFirst = function (fn, receiver, arg) { var domain = this._getDomain(); if (domain !== undefined) fn = domain.bind(fn); this._normalQueue.unshift(fn, receiver, arg); this._queueTick(); }; Async.prototype._drainQueue = function(queue) { while (queue.length() > 0) { var fn = queue.shift(); if (typeof fn !== "function") { fn._settlePromises(); continue; } var receiver = queue.shift(); var arg = queue.shift(); fn.call(receiver, arg); } }; Async.prototype._drainQueues = function () { this._drainQueue(this._normalQueue); this._reset(); this._drainQueue(this._lateQueue); }; Async.prototype._queueTick = function () { if (!this._isTickUsed) { this._isTickUsed = true; this._schedule(this.drainQueues); } }; Async.prototype._reset = function () { this._isTickUsed = false; }; module.exports = new Async(); module.exports.firstLineError = firstLineError; },{"./queue.js":28,"./schedule.js":31,"./util.js":38,"events":39}],3:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, INTERNAL, tryConvertToPromise) { var rejectThis = function(_, e) { this._reject(e); }; var targetRejected = function(e, context) { context.promiseRejectionQueued = true; context.bindingPromise._then(rejectThis, rejectThis, null, this, e); }; var bindingResolved = function(thisArg, context) { this._setBoundTo(thisArg); if (this._isPending()) { this._resolveCallback(context.target); } }; var bindingRejected = function(e, context) { if (!context.promiseRejectionQueued) this._reject(e); }; Promise.prototype.bind = function (thisArg) { var maybePromise = tryConvertToPromise(thisArg); var ret = new Promise(INTERNAL); ret._propagateFrom(this, 1); var target = this._target(); if (maybePromise instanceof Promise) { var context = { promiseRejectionQueued: false, promise: ret, target: target, bindingPromise: maybePromise }; target._then(INTERNAL, targetRejected, ret._progress, ret, context); maybePromise._then( bindingResolved, bindingRejected, ret._progress, ret, context); } else { ret._setBoundTo(thisArg); ret._resolveCallback(target); } return ret; }; Promise.prototype._setBoundTo = function (obj) { if (obj !== undefined) { this._bitField = this._bitField | 131072; this._boundTo = obj; } else { this._bitField = this._bitField & (~131072); } }; Promise.prototype._isBound = function () { return (this._bitField & 131072) === 131072; }; Promise.bind = function (thisArg, value) { var maybePromise = tryConvertToPromise(thisArg); var ret = new Promise(INTERNAL); if (maybePromise instanceof Promise) { maybePromise._then(function(thisArg) { ret._setBoundTo(thisArg); ret._resolveCallback(value); }, ret._reject, ret._progress, ret, null); } else { ret._setBoundTo(thisArg); ret._resolveCallback(value); } return ret; }; }; },{}],4:[function(_dereq_,module,exports){ "use strict"; var old; if (typeof Promise !== "undefined") old = Promise; function noConflict() { try { if (Promise === bluebird) Promise = old; } catch (e) {} return bluebird; } var bluebird = _dereq_("./promise.js")(); bluebird.noConflict = noConflict; module.exports = bluebird; },{"./promise.js":23}],5:[function(_dereq_,module,exports){ "use strict"; var cr = Object.create; if (cr) { var callerCache = cr(null); var getterCache = cr(null); callerCache[" size"] = getterCache[" size"] = 0; } module.exports = function(Promise) { var util = _dereq_("./util.js"); var canEvaluate = util.canEvaluate; var isIdentifier = util.isIdentifier; var getMethodCaller; var getGetter; if (!true) { var makeMethodCaller = function (methodName) { return new Function("ensureMethod", " \n\ return function(obj) { \n\ 'use strict' \n\ var len = this.length; \n\ ensureMethod(obj, 'methodName'); \n\ switch(len) { \n\ case 1: return obj.methodName(this[0]); \n\ case 2: return obj.methodName(this[0], this[1]); \n\ case 3: return obj.methodName(this[0], this[1], this[2]); \n\ case 0: return obj.methodName(); \n\ default: \n\ return obj.methodName.apply(obj, this); \n\ } \n\ }; \n\ ".replace(/methodName/g, methodName))(ensureMethod); }; var makeGetter = function (propertyName) { return new Function("obj", " \n\ 'use strict'; \n\ return obj.propertyName; \n\ ".replace("propertyName", propertyName)); }; var getCompiled = function(name, compiler, cache) { var ret = cache[name]; if (typeof ret !== "function") { if (!isIdentifier(name)) { return null; } ret = compiler(name); cache[name] = ret; cache[" size"]++; if (cache[" size"] > 512) { var keys = Object.keys(cache); for (var i = 0; i < 256; ++i) delete cache[keys[i]]; cache[" size"] = keys.length - 256; } } return ret; }; getMethodCaller = function(name) { return getCompiled(name, makeMethodCaller, callerCache); }; getGetter = function(name) { return getCompiled(name, makeGetter, getterCache); }; } function ensureMethod(obj, methodName) { var fn; if (obj != null) fn = obj[methodName]; if (typeof fn !== "function") { var message = "Object " + util.classString(obj) + " has no method '" + util.toString(methodName) + "'"; throw new Promise.TypeError(message); } return fn; } function caller(obj) { var methodName = this.pop(); var fn = ensureMethod(obj, methodName); return fn.apply(obj, this); } Promise.prototype.call = function (methodName) { var $_len = arguments.length;var args = new Array($_len - 1); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];} if (!true) { if (canEvaluate) { var maybeCaller = getMethodCaller(methodName); if (maybeCaller !== null) { return this._then( maybeCaller, undefined, undefined, args, undefined); } } } args.push(methodName); return this._then(caller, undefined, undefined, args, undefined); }; function namedGetter(obj) { return obj[this]; } function indexedGetter(obj) { var index = +this; if (index < 0) index = Math.max(0, index + obj.length); return obj[index]; } Promise.prototype.get = function (propertyName) { var isIndex = (typeof propertyName === "number"); var getter; if (!isIndex) { if (canEvaluate) { var maybeGetter = getGetter(propertyName); getter = maybeGetter !== null ? maybeGetter : namedGetter; } else { getter = namedGetter; } } else { getter = indexedGetter; } return this._then(getter, undefined, undefined, propertyName, undefined); }; }; },{"./util.js":38}],6:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise) { var errors = _dereq_("./errors.js"); var async = _dereq_("./async.js"); var CancellationError = errors.CancellationError; Promise.prototype._cancel = function (reason) { if (!this.isCancellable()) return this; var parent; var promiseToReject = this; while ((parent = promiseToReject._cancellationParent) !== undefined && parent.isCancellable()) { promiseToReject = parent; } this._unsetCancellable(); promiseToReject._target()._rejectCallback(reason, false, true); }; Promise.prototype.cancel = function (reason) { if (!this.isCancellable()) return this; if (reason === undefined) reason = new CancellationError(); async.invokeLater(this._cancel, this, reason); return this; }; Promise.prototype.cancellable = function () { if (this._cancellable()) return this; async.enableTrampoline(); this._setCancellable(); this._cancellationParent = undefined; return this; }; Promise.prototype.uncancellable = function () { var ret = this.then(); ret._unsetCancellable(); return ret; }; Promise.prototype.fork = function (didFulfill, didReject, didProgress) { var ret = this._then(didFulfill, didReject, didProgress, undefined, undefined); ret._setCancellable(); ret._cancellationParent = undefined; return ret; }; }; },{"./async.js":2,"./errors.js":13}],7:[function(_dereq_,module,exports){ "use strict"; module.exports = function() { var async = _dereq_("./async.js"); var util = _dereq_("./util.js"); var bluebirdFramePattern = /[\\\/]bluebird[\\\/]js[\\\/](main|debug|zalgo|instrumented)/; var stackFramePattern = null; var formatStack = null; var indentStackFrames = false; var warn; function CapturedTrace(parent) { this._parent = parent; var length = this._length = 1 + (parent === undefined ? 0 : parent._length); captureStackTrace(this, CapturedTrace); if (length > 32) this.uncycle(); } util.inherits(CapturedTrace, Error); CapturedTrace.prototype.uncycle = function() { var length = this._length; if (length < 2) return; var nodes = []; var stackToIndex = {}; for (var i = 0, node = this; node !== undefined; ++i) { nodes.push(node); node = node._parent; } length = this._length = i; for (var i = length - 1; i >= 0; --i) { var stack = nodes[i].stack; if (stackToIndex[stack] === undefined) { stackToIndex[stack] = i; } } for (var i = 0; i < length; ++i) { var currentStack = nodes[i].stack; var index = stackToIndex[currentStack]; if (index !== undefined && index !== i) { if (index > 0) { nodes[index - 1]._parent = undefined; nodes[index - 1]._length = 1; } nodes[i]._parent = undefined; nodes[i]._length = 1; var cycleEdgeNode = i > 0 ? nodes[i - 1] : this; if (index < length - 1) { cycleEdgeNode._parent = nodes[index + 1]; cycleEdgeNode._parent.uncycle(); cycleEdgeNode._length = cycleEdgeNode._parent._length + 1; } else { cycleEdgeNode._parent = undefined; cycleEdgeNode._length = 1; } var currentChildLength = cycleEdgeNode._length + 1; for (var j = i - 2; j >= 0; --j) { nodes[j]._length = currentChildLength; currentChildLength++; } return; } } }; CapturedTrace.prototype.parent = function() { return this._parent; }; CapturedTrace.prototype.hasParent = function() { return this._parent !== undefined; }; CapturedTrace.prototype.attachExtraTrace = function(error) { if (error.__stackCleaned__) return; this.uncycle(); var parsed = CapturedTrace.parseStackAndMessage(error); var message = parsed.message; var stacks = [parsed.stack]; var trace = this; while (trace !== undefined) { stacks.push(cleanStack(trace.stack.split("\n"))); trace = trace._parent; } removeCommonRoots(stacks); removeDuplicateOrEmptyJumps(stacks); util.notEnumerableProp(error, "stack", reconstructStack(message, stacks)); util.notEnumerableProp(error, "__stackCleaned__", true); }; function reconstructStack(message, stacks) { for (var i = 0; i < stacks.length - 1; ++i) { stacks[i].push("From previous event:"); stacks[i] = stacks[i].join("\n"); } if (i < stacks.length) { stacks[i] = stacks[i].join("\n"); } return message + "\n" + stacks.join("\n"); } function removeDuplicateOrEmptyJumps(stacks) { for (var i = 0; i < stacks.length; ++i) { if (stacks[i].length === 0 || ((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) { stacks.splice(i, 1); i--; } } } function removeCommonRoots(stacks) { var current = stacks[0]; for (var i = 1; i < stacks.length; ++i) { var prev = stacks[i]; var currentLastIndex = current.length - 1; var currentLastLine = current[currentLastIndex]; var commonRootMeetPoint = -1; for (var j = prev.length - 1; j >= 0; --j) { if (prev[j] === currentLastLine) { commonRootMeetPoint = j; break; } } for (var j = commonRootMeetPoint; j >= 0; --j) { var line = prev[j]; if (current[currentLastIndex] === line) { current.pop(); currentLastIndex--; } else { break; } } current = prev; } } function cleanStack(stack) { var ret = []; for (var i = 0; i < stack.length; ++i) { var line = stack[i]; var isTraceLine = stackFramePattern.test(line) || " (No stack trace)" === line; var isInternalFrame = isTraceLine && shouldIgnore(line); if (isTraceLine && !isInternalFrame) { if (indentStackFrames && line.charAt(0) !== " ") { line = " " + line; } ret.push(line); } } return ret; } function stackFramesAsArray(error) { var stack = error.stack.replace(/\s+$/g, "").split("\n"); for (var i = 0; i < stack.length; ++i) { var line = stack[i]; if (" (No stack trace)" === line || stackFramePattern.test(line)) { break; } } if (i > 0) { stack = stack.slice(i); } return stack; } CapturedTrace.parseStackAndMessage = function(error) { var stack = error.stack; var message = error.toString(); stack = typeof stack === "string" && stack.length > 0 ? stackFramesAsArray(error) : [" (No stack trace)"]; return { message: message, stack: cleanStack(stack) }; }; CapturedTrace.formatAndLogError = function(error, title) { if (typeof console !== "undefined") { var message; if (typeof error === "object" || typeof error === "function") { var stack = error.stack; message = title + formatStack(stack, error); } else { message = title + String(error); } if (typeof warn === "function") { warn(message); } else if (typeof console.log === "function" || typeof console.log === "object") { console.log(message); } } }; CapturedTrace.unhandledRejection = function (reason) { CapturedTrace.formatAndLogError(reason, "^--- With additional stack trace: "); }; CapturedTrace.isSupported = function () { return typeof captureStackTrace === "function"; }; CapturedTrace.fireRejectionEvent = function(name, localHandler, reason, promise) { var localEventFired = false; try { if (typeof localHandler === "function") { localEventFired = true; if (name === "rejectionHandled") { localHandler(promise); } else { localHandler(reason, promise); } } } catch (e) { async.throwLater(e); } var globalEventFired = false; try { globalEventFired = fireGlobalEvent(name, reason, promise); } catch (e) { globalEventFired = true; async.throwLater(e); } var domEventFired = false; if (fireDomEvent) { try { domEventFired = fireDomEvent(name.toLowerCase(), { reason: reason, promise: promise }); } catch (e) { domEventFired = true; async.throwLater(e); } } if (!globalEventFired && !localEventFired && !domEventFired && name === "unhandledRejection") { CapturedTrace.formatAndLogError(reason, "Unhandled rejection "); } }; 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) + "..."; } var shouldIgnore = function() { return false; }; var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/; function parseLineInfo(line) { var matches = line.match(parseLineInfoRegex); if (matches) { return { fileName: matches[1], line: parseInt(matches[2], 10) }; } } CapturedTrace.setBounds = function(firstLineError, lastLineError) { if (!CapturedTrace.isSupported()) return; var firstStackLines = firstLineError.stack.split("\n"); var lastStackLines = lastLineError.stack.split("\n"); var firstIndex = -1; var lastIndex = -1; var firstFileName; var lastFileName; for (var i = 0; i < firstStackLines.length; ++i) { var result = parseLineInfo(firstStackLines[i]); if (result) { firstFileName = result.fileName; firstIndex = result.line; break; } } for (var i = 0; i < lastStackLines.length; ++i) { var result = parseLineInfo(lastStackLines[i]); if (result) { lastFileName = result.fileName; lastIndex = result.line; break; } } if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName || firstFileName !== lastFileName || firstIndex >= lastIndex) { return; } shouldIgnore = function(line) { if (bluebirdFramePattern.test(line)) return true; var info = parseLineInfo(line); if (info) { if (info.fileName === firstFileName && (firstIndex <= info.line && info.line <= lastIndex)) { return true; } } return false; }; }; var captureStackTrace = (function stackDetection() { var v8stackFramePattern = /^\s*at\s*/; var v8stackFormatter = function(stack, error) { if (typeof stack === "string") return stack; if (error.name !== undefined && error.message !== undefined) { return error.toString(); } return formatNonError(error); }; if (typeof Error.stackTraceLimit === "number" && typeof Error.captureStackTrace === "function") { Error.stackTraceLimit = Error.stackTraceLimit + 6; stackFramePattern = v8stackFramePattern; formatStack = v8stackFormatter; var captureStackTrace = Error.captureStackTrace; shouldIgnore = function(line) { return bluebirdFramePattern.test(line); }; return function(receiver, ignoreUntil) { Error.stackTraceLimit = Error.stackTraceLimit + 6; captureStackTrace(receiver, ignoreUntil); Error.stackTraceLimit = Error.stackTraceLimit - 6; }; } var err = new Error(); if (typeof err.stack === "string" && err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) { stackFramePattern = /@/; formatStack = v8stackFormatter; indentStackFrames = true; return function captureStackTrace(o) { o.stack = new Error().stack; }; } var hasStackAfterThrow; try { throw new Error(); } catch(e) { hasStackAfterThrow = ("stack" in e); } if (!("stack" in err) && hasStackAfterThrow) { stackFramePattern = v8stackFramePattern; formatStack = v8stackFormatter; return function captureStackTrace(o) { Error.stackTraceLimit = Error.stackTraceLimit + 6; try { throw new Error(); } catch(e) { o.stack = e.stack; } Error.stackTraceLimit = Error.stackTraceLimit - 6; }; } formatStack = function(stack, error) { if (typeof stack === "string") return stack; if ((typeof error === "object" || typeof error === "function") && error.name !== undefined && error.message !== undefined) { return error.toString(); } return formatNonError(error); }; return null; })([]); var fireDomEvent; var fireGlobalEvent = (function() { if (util.isNode) { return function(name, reason, promise) { if (name === "rejectionHandled") { return process.emit(name, promise); } else { return process.emit(name, reason, promise); } }; } else { var customEventWorks = false; var anyEventWorks = true; try { va