UNPKG

chainscript

Version:
2,140 lines (1,779 loc) 58.6 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("bitcore"), require("bitcore-message")); else if(typeof define === 'function' && define.amd) define(["bitcore", "bitcore-message"], factory); else if(typeof exports === 'object') exports["chainscript"] = factory(require("bitcore"), require("bitcore-message")); else root["chainscript"] = factory(root["Bitcore"], root["BitcoreMessage"]); })(this, function(__WEBPACK_EXTERNAL_MODULE_6__, __WEBPACK_EXTERNAL_MODULE_7__) { return /******/ (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__) { 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var _Chainscript = __webpack_require__(1); var _Chainscript2 = _interopRequireDefault(_Chainscript); exports['default'] = _Chainscript2['default']; module.exports = exports['default']; /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; exports.__esModule = true; 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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _superagent = __webpack_require__(2); var _superagent2 = _interopRequireDefault(_superagent); var _objectPath = __webpack_require__(5); var _objectPath2 = _interopRequireDefault(_objectPath); var _bitcore = __webpack_require__(6); var _bitcoreMessage = __webpack_require__(7); var _bitcoreMessage2 = _interopRequireDefault(_bitcoreMessage); var _utilsClone = __webpack_require__(8); var _utilsClone2 = _interopRequireDefault(_utilsClone); var _utilsDeepEquals = __webpack_require__(9); var _utilsDeepEquals2 = _interopRequireDefault(_utilsDeepEquals); var _utilsPromisify = __webpack_require__(13); var _utilsPromisify2 = _interopRequireDefault(_utilsPromisify); var Chainscript = (function () { _createClass(Chainscript, null, [{ key: 'EXECUTE_URL', value: 'http://agent.chainscript.io/execute', enumerable: true }, { key: 'SNAPSHOTS_URL', value: 'https://chainscript.firebaseio.com/snapshots/', /** * Loads a script from an existing uuid * * @param {string} uuid The uuid of the script * @param {bool} [immutable=false] Whether to create an immutable instance * @returns {Promise} A promise that resolves with a new Chainscript */ enumerable: true }, { key: 'load', value: function value(uuid) { var immutable = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; var req = _superagent2['default'].get(Chainscript.SNAPSHOTS_URL + uuid.replace(/:/g, '-') + '.json').set('Accept', 'application/json'); return _utilsPromisify2['default'](req.end.bind(req))().then(function (res) { if (!res.ok) { throw new Error(res.text); } if (!res.body) { throw new Error('Not found'); } return new Chainscript(_utilsClone2['default'](res.body), immutable); }); }, /** * Construct a new chainscript. * * @param {Object | string} [script={}] The initial script * @param {bool} [immutable=false] Whether to create an immutable instance */ enumerable: true }]); function Chainscript() { var script = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; var immutable = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; _classCallCheck(this, Chainscript); // Clone the script for safety this.script = _utilsClone2['default'](script); this.immutable = immutable; if (!immutable) { this.initial = _utilsClone2['default'](script); } } /** * Returns the script as JSON. * * @returns {Object} JSON representation of the script */ Chainscript.prototype.toJSON = function toJSON() { // Clone the script for safety return _utilsClone2['default'](this.script); }; /** * Clones the script. * * @returns {Chainscript} A clone of the script */ Chainscript.prototype.clone = function clone() { var copy = new Chainscript(this.script, this.immutable); if (!this.immutable) { copy.initial = _utilsClone2['default'](this.initial); } return copy; }; /** * Run the script. * * @returns {Promise} A promise that resolves with a new Chainscript */ Chainscript.prototype.run = function run() { var _this = this; if (!this.immutable) { var initialContent = _objectPath2['default'].get(this.initial, 'body.content'); var currentContent = _objectPath2['default'].get(this.script, 'body.content'); if (!_utilsDeepEquals2['default'](initialContent, currentContent)) { this.script.body = this.script.body || {}; this.script.body.content = initialContent; this.delta(currentContent, true); } } var req = _superagent2['default'].post(Chainscript.EXECUTE_URL).send(this.script).set('Accept', 'application/json'); return _utilsPromisify2['default'](req.end.bind(req))().then(function (res) { if (!res.ok) { throw new Error(res.text); } if (!res.body) { throw new Error('Not found'); } if (_this.immutable) { return new Chainscript(res.body, true); } _this.script = res.body; _this.initial = _utilsClone2['default'](_this.script); return _this; }); }; /** * Returns the value at specified path. */ Chainscript.prototype.get = function get(path) { var value = _objectPath2['default'].get(this.script, path); if (typeof value === 'undefined') { return undefined; } if (this.immutable) { return _utilsClone2['default'](value); } return value; }; /** * Sets the value at specified path. * * @param {string} path The path of the key to set * @param {any} value The value * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.set = function set(path, value) { var script = undefined; if (this.immutable) { script = _utilsClone2['default'](this.script); } else { script = this.script; } _objectPath2['default'].set(script, path, value); if (this.immutable) { return new Chainscript(script, true); } return this; }; /** * Adds a snapshot command * * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.snapshot = function snapshot() { return this.set('x_chainscript.snapshots_enabled', true).addCommand({ snapshot: {} }); }; /** * Adds an update command * * @param {Object} updates An object with updates to apply * @param {bool} [first=false] Whether to put the command first * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.update = function update(updates) { var first = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; return this.addCommand({ update: updates }, first); }; /** * Adds a notarize command * * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.notarize = function notarize() { return this.addCommand({ notarize: {} }); }; /** * Adds a send email command * * @param {string} to Destination email address * @param {string} [subject] Subject * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.email = function email(to, subject) { if (subject) { return this.addCommand({ send_email: { to: to, subject: subject } }); } return this.addCommand({ send_email: { to: to } }); }; /** * Adds an update command to change the content at specified path. * * @param {function} fn A function that changes the content * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.change = function change(fn) { var next = _utilsClone2['default'](this.get('body.content')); fn(next); return this.delta(next); }; /** * Adds an update command to change the content to the given content. * * @param {Object} next The new content * @param {bool} [first=false] Whether to put the command first * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.delta = function delta(next) { var first = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; var prev = this.get('body.content'); if (typeof prev === 'object' && prev && typeof next === 'object' && next) { Object.keys(prev).forEach(function (s) { if (typeof next[s] === 'undefined') { next[s] = null; } else if (_utilsDeepEquals2['default'](prev[s], next[s])) { delete next[s]; } }); } return this.update(next, first); }; /** * Adds a sign content command. * * @param {string} wif A private key in WIF format * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.sign = function sign(wif) { var _sign_content; var digest = _objectPath2['default'].get(this.script, 'body.x_meta.content_digest'); if (typeof digest === 'undefined') { throw new Error('Content has no digest'); } var privateKey = _bitcore.PrivateKey.fromWIF(wif); var address = privateKey.toPublicKey().toAddress().toString(); var message = new _bitcoreMessage2['default'](digest); var signature = message.sign(privateKey); return this.addCommand({ sign_content: (_sign_content = {}, _sign_content[address] = { digest: digest, signature: signature }, _sign_content) }); }; Chainscript.prototype.getNumCommands = function getNumCommands() { if (typeof this.script.execute === 'undefined') { return 0; } return Object.keys(this.script.execute).length; }; Chainscript.prototype.addCommand = function addCommand(command) { var first = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; var index = first ? 0 : this.getNumCommands(); var script = undefined; if (this.immutable) { script = _utilsClone2['default'](this.script); } else { script = this.script; } script.execute = script.execute || {}; if (first) { (function () { var tmp = {}; Object.keys(script.execute).forEach(function (s) { tmp[parseInt(s, 10) + 1] = script.execute[s]; }); script.execute = tmp; })(); } script.execute[index] = command; if (this.immutable) { return new Chainscript(script, true); } return this; }; return Chainscript; })(); exports['default'] = Chainscript; module.exports = exports['default']; /***/ }, /* 2 */ /***/ function(module, exports, __webpack_require__) { /** * Module dependencies. */ var Emitter = __webpack_require__(3); var reduce = __webpack_require__(4); /** * Root reference for iframes. */ var root; if (typeof window !== 'undefined') { // Browser window root = window; } else if (typeof self !== 'undefined') { // Web Worker root = self; } else { // Other environments root = this; } /** * Noop. */ function noop(){}; /** * Check if `obj` is a host object, * we don't want to serialize these :) * * TODO: future proof, move to compoent land * * @param {Object} obj * @return {Boolean} * @api private */ function isHost(obj) { var str = {}.toString.call(obj); switch (str) { case '[object File]': case '[object Blob]': case '[object FormData]': return true; default: return false; } } /** * Determine XHR. */ request.getXHR = function () { if (root.XMLHttpRequest && (!root.location || 'file:' != root.location.protocol || !root.ActiveXObject)) { return new XMLHttpRequest; } else { try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {} try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {} try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {} try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {} } return false; }; /** * Removes leading and trailing whitespace, added to support IE. * * @param {String} s * @return {String} * @api private */ var trim = ''.trim ? function(s) { return s.trim(); } : function(s) { return s.replace(/(^\s*|\s*$)/g, ''); }; /** * Check if `obj` is an object. * * @param {Object} obj * @return {Boolean} * @api private */ function isObject(obj) { return obj === Object(obj); } /** * Serialize the given `obj`. * * @param {Object} obj * @return {String} * @api private */ function serialize(obj) { if (!isObject(obj)) return obj; var pairs = []; for (var key in obj) { if (null != obj[key]) { pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])); } } return pairs.join('&'); } /** * Expose serialization method. */ request.serializeObject = serialize; /** * Parse the given x-www-form-urlencoded `str`. * * @param {String} str * @return {Object} * @api private */ function parseString(str) { var obj = {}; var pairs = str.split('&'); var parts; var pair; for (var i = 0, len = pairs.length; i < len; ++i) { pair = pairs[i]; parts = pair.split('='); obj[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]); } return obj; } /** * Expose parser. */ request.parseString = parseString; /** * Default MIME type map. * * superagent.types.xml = 'application/xml'; * */ request.types = { html: 'text/html', json: 'application/json', xml: 'application/xml', urlencoded: 'application/x-www-form-urlencoded', 'form': 'application/x-www-form-urlencoded', 'form-data': 'application/x-www-form-urlencoded' }; /** * Default serialization map. * * superagent.serialize['application/xml'] = function(obj){ * return 'generated xml here'; * }; * */ request.serialize = { 'application/x-www-form-urlencoded': serialize, 'application/json': JSON.stringify }; /** * Default parsers. * * superagent.parse['application/xml'] = function(str){ * return { object parsed from str }; * }; * */ request.parse = { 'application/x-www-form-urlencoded': parseString, 'application/json': JSON.parse }; /** * Parse the given header `str` into * an object containing the mapped fields. * * @param {String} str * @return {Object} * @api private */ function parseHeader(str) { var lines = str.split(/\r?\n/); var fields = {}; var index; var line; var field; var val; lines.pop(); // trailing CRLF for (var i = 0, len = lines.length; i < len; ++i) { line = lines[i]; index = line.indexOf(':'); field = line.slice(0, index).toLowerCase(); val = trim(line.slice(index + 1)); fields[field] = val; } return fields; } /** * Return the mime type for the given `str`. * * @param {String} str * @return {String} * @api private */ function type(str){ return str.split(/ *; */).shift(); }; /** * Return header field parameters. * * @param {String} str * @return {Object} * @api private */ function params(str){ return reduce(str.split(/ *; */), function(obj, str){ var parts = str.split(/ *= */) , key = parts.shift() , val = parts.shift(); if (key && val) obj[key] = val; return obj; }, {}); }; /** * Initialize a new `Response` with the given `xhr`. * * - set flags (.ok, .error, etc) * - parse header * * Examples: * * Aliasing `superagent` as `request` is nice: * * request = superagent; * * We can use the promise-like API, or pass callbacks: * * request.get('/').end(function(res){}); * request.get('/', function(res){}); * * Sending data can be chained: * * request * .post('/user') * .send({ name: 'tj' }) * .end(function(res){}); * * Or passed to `.send()`: * * request * .post('/user') * .send({ name: 'tj' }, function(res){}); * * Or passed to `.post()`: * * request * .post('/user', { name: 'tj' }) * .end(function(res){}); * * Or further reduced to a single call for simple cases: * * request * .post('/user', { name: 'tj' }, function(res){}); * * @param {XMLHTTPRequest} xhr * @param {Object} options * @api private */ function Response(req, options) { options = options || {}; this.req = req; this.xhr = this.req.xhr; // responseText is accessible only if responseType is '' or 'text' and on older browsers this.text = ((this.req.method !='HEAD' && (this.xhr.responseType === '' || this.xhr.responseType === 'text')) || typeof this.xhr.responseType === 'undefined') ? this.xhr.responseText : null; this.statusText = this.req.xhr.statusText; this.setStatusProperties(this.xhr.status); this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders()); // getAllResponseHeaders sometimes falsely returns "" for CORS requests, but // getResponseHeader still works. so we get content-type even if getting // other headers fails. this.header['content-type'] = this.xhr.getResponseHeader('content-type'); this.setHeaderProperties(this.header); this.body = this.req.method != 'HEAD' ? this.parseBody(this.text ? this.text : this.xhr.response) : null; } /** * Get case-insensitive `field` value. * * @param {String} field * @return {String} * @api public */ Response.prototype.get = function(field){ return this.header[field.toLowerCase()]; }; /** * Set header related properties: * * - `.type` the content type without params * * A response of "Content-Type: text/plain; charset=utf-8" * will provide you with a `.type` of "text/plain". * * @param {Object} header * @api private */ Response.prototype.setHeaderProperties = function(header){ // content-type var ct = this.header['content-type'] || ''; this.type = type(ct); // params var obj = params(ct); for (var key in obj) this[key] = obj[key]; }; /** * Force given parser * * Sets the body parser no matter type. * * @param {Function} * @api public */ Response.prototype.parse = function(fn){ this.parser = fn; return this; }; /** * Parse the given body `str`. * * Used for auto-parsing of bodies. Parsers * are defined on the `superagent.parse` object. * * @param {String} str * @return {Mixed} * @api private */ Response.prototype.parseBody = function(str){ var parse = this.parser || request.parse[this.type]; return parse && str && (str.length || str instanceof Object) ? parse(str) : null; }; /** * Set flags such as `.ok` based on `status`. * * For example a 2xx response will give you a `.ok` of __true__ * whereas 5xx will be __false__ and `.error` will be __true__. The * `.clientError` and `.serverError` are also available to be more * specific, and `.statusType` is the class of error ranging from 1..5 * sometimes useful for mapping respond colors etc. * * "sugar" properties are also defined for common cases. Currently providing: * * - .noContent * - .badRequest * - .unauthorized * - .notAcceptable * - .notFound * * @param {Number} status * @api private */ Response.prototype.setStatusProperties = function(status){ // handle IE9 bug: http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request if (status === 1223) { status = 204; } var type = status / 100 | 0; // status / class this.status = this.statusCode = status; this.statusType = type; // basics this.info = 1 == type; this.ok = 2 == type; this.clientError = 4 == type; this.serverError = 5 == type; this.error = (4 == type || 5 == type) ? this.toError() : false; // sugar this.accepted = 202 == status; this.noContent = 204 == status; this.badRequest = 400 == status; this.unauthorized = 401 == status; this.notAcceptable = 406 == status; this.notFound = 404 == status; this.forbidden = 403 == status; }; /** * Return an `Error` representative of this response. * * @return {Error} * @api public */ Response.prototype.toError = function(){ var req = this.req; var method = req.method; var url = req.url; var msg = 'cannot ' + method + ' ' + url + ' (' + this.status + ')'; var err = new Error(msg); err.status = this.status; err.method = method; err.url = url; return err; }; /** * Expose `Response`. */ request.Response = Response; /** * Initialize a new `Request` with the given `method` and `url`. * * @param {String} method * @param {String} url * @api public */ function Request(method, url) { var self = this; Emitter.call(this); this._query = this._query || []; this.method = method; this.url = url; this.header = {}; this._header = {}; this.on('end', function(){ var err = null; var res = null; try { res = new Response(self); } catch(e) { err = new Error('Parser is unable to parse the response'); err.parse = true; err.original = e; return self.callback(err); } self.emit('response', res); if (err) { return self.callback(err, res); } if (res.status >= 200 && res.status < 300) { return self.callback(err, res); } var new_err = new Error(res.statusText || 'Unsuccessful HTTP response'); new_err.original = err; new_err.response = res; new_err.status = res.status; self.callback(new_err, res); }); } /** * Mixin `Emitter`. */ Emitter(Request.prototype); /** * Allow for extension */ Request.prototype.use = function(fn) { fn(this); return this; } /** * Set timeout to `ms`. * * @param {Number} ms * @return {Request} for chaining * @api public */ Request.prototype.timeout = function(ms){ this._timeout = ms; return this; }; /** * Clear previous timeout. * * @return {Request} for chaining * @api public */ Request.prototype.clearTimeout = function(){ this._timeout = 0; clearTimeout(this._timer); return this; }; /** * Abort the request, and clear potential timeout. * * @return {Request} * @api public */ Request.prototype.abort = function(){ if (this.aborted) return; this.aborted = true; this.xhr.abort(); this.clearTimeout(); this.emit('abort'); return this; }; /** * Set header `field` to `val`, or multiple fields with one object. * * Examples: * * req.get('/') * .set('Accept', 'application/json') * .set('X-API-Key', 'foobar') * .end(callback); * * req.get('/') * .set({ Accept: 'application/json', 'X-API-Key': 'foobar' }) * .end(callback); * * @param {String|Object} field * @param {String} val * @return {Request} for chaining * @api public */ Request.prototype.set = function(field, val){ if (isObject(field)) { for (var key in field) { this.set(key, field[key]); } return this; } this._header[field.toLowerCase()] = val; this.header[field] = val; return this; }; /** * Remove header `field`. * * Example: * * req.get('/') * .unset('User-Agent') * .end(callback); * * @param {String} field * @return {Request} for chaining * @api public */ Request.prototype.unset = function(field){ delete this._header[field.toLowerCase()]; delete this.header[field]; return this; }; /** * Get case-insensitive header `field` value. * * @param {String} field * @return {String} * @api private */ Request.prototype.getHeader = function(field){ return this._header[field.toLowerCase()]; }; /** * Set Content-Type to `type`, mapping values from `request.types`. * * Examples: * * superagent.types.xml = 'application/xml'; * * request.post('/') * .type('xml') * .send(xmlstring) * .end(callback); * * request.post('/') * .type('application/xml') * .send(xmlstring) * .end(callback); * * @param {String} type * @return {Request} for chaining * @api public */ Request.prototype.type = function(type){ this.set('Content-Type', request.types[type] || type); return this; }; /** * Set Accept to `type`, mapping values from `request.types`. * * Examples: * * superagent.types.json = 'application/json'; * * request.get('/agent') * .accept('json') * .end(callback); * * request.get('/agent') * .accept('application/json') * .end(callback); * * @param {String} accept * @return {Request} for chaining * @api public */ Request.prototype.accept = function(type){ this.set('Accept', request.types[type] || type); return this; }; /** * Set Authorization field value with `user` and `pass`. * * @param {String} user * @param {String} pass * @return {Request} for chaining * @api public */ Request.prototype.auth = function(user, pass){ var str = btoa(user + ':' + pass); this.set('Authorization', 'Basic ' + str); return this; }; /** * Add query-string `val`. * * Examples: * * request.get('/shoes') * .query('size=10') * .query({ color: 'blue' }) * * @param {Object|String} val * @return {Request} for chaining * @api public */ Request.prototype.query = function(val){ if ('string' != typeof val) val = serialize(val); if (val) this._query.push(val); return this; }; /** * Write the field `name` and `val` for "multipart/form-data" * request bodies. * * ``` js * request.post('/upload') * .field('foo', 'bar') * .end(callback); * ``` * * @param {String} name * @param {String|Blob|File} val * @return {Request} for chaining * @api public */ Request.prototype.field = function(name, val){ if (!this._formData) this._formData = new root.FormData(); this._formData.append(name, val); return this; }; /** * Queue the given `file` as an attachment to the specified `field`, * with optional `filename`. * * ``` js * request.post('/upload') * .attach(new Blob(['<a id="a"><b id="b">hey!</b></a>'], { type: "text/html"})) * .end(callback); * ``` * * @param {String} field * @param {Blob|File} file * @param {String} filename * @return {Request} for chaining * @api public */ Request.prototype.attach = function(field, file, filename){ if (!this._formData) this._formData = new root.FormData(); this._formData.append(field, file, filename); return this; }; /** * Send `data`, defaulting the `.type()` to "json" when * an object is given. * * Examples: * * // querystring * request.get('/search') * .end(callback) * * // multiple data "writes" * request.get('/search') * .send({ search: 'query' }) * .send({ range: '1..5' }) * .send({ order: 'desc' }) * .end(callback) * * // manual json * request.post('/user') * .type('json') * .send('{"name":"tj"}) * .end(callback) * * // auto json * request.post('/user') * .send({ name: 'tj' }) * .end(callback) * * // manual x-www-form-urlencoded * request.post('/user') * .type('form') * .send('name=tj') * .end(callback) * * // auto x-www-form-urlencoded * request.post('/user') * .type('form') * .send({ name: 'tj' }) * .end(callback) * * // defaults to x-www-form-urlencoded * request.post('/user') * .send('name=tobi') * .send('species=ferret') * .end(callback) * * @param {String|Object} data * @return {Request} for chaining * @api public */ Request.prototype.send = function(data){ var obj = isObject(data); var type = this.getHeader('Content-Type'); // merge if (obj && isObject(this._data)) { for (var key in data) { this._data[key] = data[key]; } } else if ('string' == typeof data) { if (!type) this.type('form'); type = this.getHeader('Content-Type'); if ('application/x-www-form-urlencoded' == type) { this._data = this._data ? this._data + '&' + data : data; } else { this._data = (this._data || '') + data; } } else { this._data = data; } if (!obj || isHost(data)) return this; if (!type) this.type('json'); return this; }; /** * Invoke the callback with `err` and `res` * and handle arity check. * * @param {Error} err * @param {Response} res * @api private */ Request.prototype.callback = function(err, res){ var fn = this._callback; this.clearTimeout(); fn(err, res); }; /** * Invoke callback with x-domain error. * * @api private */ Request.prototype.crossDomainError = function(){ var err = new Error('Origin is not allowed by Access-Control-Allow-Origin'); err.crossDomain = true; this.callback(err); }; /** * Invoke callback with timeout error. * * @api private */ Request.prototype.timeoutError = function(){ var timeout = this._timeout; var err = new Error('timeout of ' + timeout + 'ms exceeded'); err.timeout = timeout; this.callback(err); }; /** * Enable transmission of cookies with x-domain requests. * * Note that for this to work the origin must not be * using "Access-Control-Allow-Origin" with a wildcard, * and also must set "Access-Control-Allow-Credentials" * to "true". * * @api public */ Request.prototype.withCredentials = function(){ this._withCredentials = true; return this; }; /** * Initiate request, invoking callback `fn(res)` * with an instanceof `Response`. * * @param {Function} fn * @return {Request} for chaining * @api public */ Request.prototype.end = function(fn){ var self = this; var xhr = this.xhr = request.getXHR(); var query = this._query.join('&'); var timeout = this._timeout; var data = this._formData || this._data; // store callback this._callback = fn || noop; // state change xhr.onreadystatechange = function(){ if (4 != xhr.readyState) return; // In IE9, reads to any property (e.g. status) off of an aborted XHR will // result in the error "Could not complete the operation due to error c00c023f" var status; try { status = xhr.status } catch(e) { status = 0; } if (0 == status) { if (self.timedout) return self.timeoutError(); if (self.aborted) return; return self.crossDomainError(); } self.emit('end'); }; // progress var handleProgress = function(e){ if (e.total > 0) { e.percent = e.loaded / e.total * 100; } self.emit('progress', e); }; if (this.hasListeners('progress')) { xhr.onprogress = handleProgress; } try { if (xhr.upload && this.hasListeners('progress')) { xhr.upload.onprogress = handleProgress; } } catch(e) { // Accessing xhr.upload fails in IE from a web worker, so just pretend it doesn't exist. // Reported here: // https://connect.microsoft.com/IE/feedback/details/837245/xmlhttprequest-upload-throws-invalid-argument-when-used-from-web-worker-context } // timeout if (timeout && !this._timer) { this._timer = setTimeout(function(){ self.timedout = true; self.abort(); }, timeout); } // querystring if (query) { query = request.serializeObject(query); this.url += ~this.url.indexOf('?') ? '&' + query : '?' + query; } // initiate request xhr.open(this.method, this.url, true); // CORS if (this._withCredentials) xhr.withCredentials = true; // body if ('GET' != this.method && 'HEAD' != this.method && 'string' != typeof data && !isHost(data)) { // serialize stuff var contentType = this.getHeader('Content-Type'); var serialize = request.serialize[contentType ? contentType.split(';')[0] : '']; if (serialize) data = serialize(data); } // set header fields for (var field in this.header) { if (null == this.header[field]) continue; xhr.setRequestHeader(field, this.header[field]); } // send stuff this.emit('request', this); xhr.send(data); return this; }; /** * Faux promise support * * @param {Function} fulfill * @param {Function} reject * @return {Request} */ Request.prototype.then = function (fulfill, reject) { return this.end(function(err, res) { err ? reject(err) : fulfill(res); }); } /** * Expose `Request`. */ request.Request = Request; /** * Issue a request: * * Examples: * * request('GET', '/users').end(callback) * request('/users').end(callback) * request('/users', callback) * * @param {String} method * @param {String|Function} url or callback * @return {Request} * @api public */ function request(method, url) { // callback if ('function' == typeof url) { return new Request('GET', method).end(url); } // url first if (1 == arguments.length) { return new Request('GET', method); } return new Request(method, url); } /** * GET `url` with optional callback `fn(res)`. * * @param {String} url * @param {Mixed|Function} data or fn * @param {Function} fn * @return {Request} * @api public */ request.get = function(url, data, fn){ var req = request('GET', url); if ('function' == typeof data) fn = data, data = null; if (data) req.query(data); if (fn) req.end(fn); return req; }; /** * HEAD `url` with optional callback `fn(res)`. * * @param {String} url * @param {Mixed|Function} data or fn * @param {Function} fn * @return {Request} * @api public */ request.head = function(url, data, fn){ var req = request('HEAD', url); if ('function' == typeof data) fn = data, data = null; if (data) req.send(data); if (fn) req.end(fn); return req; }; /** * DELETE `url` with optional callback `fn(res)`. * * @param {String} url * @param {Function} fn * @return {Request} * @api public */ request.del = function(url, fn){ var req = request('DELETE', url); if (fn) req.end(fn); return req; }; /** * PATCH `url` with optional `data` and callback `fn(res)`. * * @param {String} url * @param {Mixed} data * @param {Function} fn * @return {Request} * @api public */ request.patch = function(url, data, fn){ var req = request('PATCH', url); if ('function' == typeof data) fn = data, data = null; if (data) req.send(data); if (fn) req.end(fn); return req; }; /** * POST `url` with optional `data` and callback `fn(res)`. * * @param {String} url * @param {Mixed} data * @param {Function} fn * @return {Request} * @api public */ request.post = function(url, data, fn){ var req = request('POST', url); if ('function' == typeof data) fn = data, data = null; if (data) req.send(data); if (fn) req.end(fn); return req; }; /** * PUT `url` with optional `data` and callback `fn(res)`. * * @param {String} url * @param {Mixed|Function} data or fn * @param {Function} fn * @return {Request} * @api public */ request.put = function(url, data, fn){ var req = request('PUT', url); if ('function' == typeof data) fn = data, data = null; if (data) req.send(data); if (fn) req.end(fn); return req; }; /** * Expose `request`. */ module.exports = request; /***/ }, /* 3 */ /***/ function(module, exports) { /** * Expose `Emitter`. */ module.exports = Emitter; /** * Initialize a new `Emitter`. * * @api public */ function Emitter(obj) { if (obj) return mixin(obj); }; /** * Mixin the emitter properties. * * @param {Object} obj * @return {Object} * @api private */ function mixin(obj) { for (var key in Emitter.prototype) { obj[key] = Emitter.prototype[key]; } return obj; } /** * Listen on the given `event` with `fn`. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.on = Emitter.prototype.addEventListener = function(event, fn){ this._callbacks = this._callbacks || {}; (this._callbacks[event] = this._callbacks[event] || []) .push(fn); return this; }; /** * Adds an `event` listener that will be invoked a single * time then automatically removed. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.once = function(event, fn){ var self = this; this._callbacks = this._callbacks || {}; function on() { self.off(event, on); fn.apply(this, arguments); } on.fn = fn; this.on(event, on); return this; }; /** * Remove the given callback for `event` or all * registered callbacks. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function(event, fn){ this._callbacks = this._callbacks || {}; // all if (0 == arguments.length) { this._callbacks = {}; return this; } // specific event var callbacks = this._callbacks[event]; if (!callbacks) return this; // remove all handlers if (1 == arguments.length) { delete this._callbacks[event]; return this; } // remove specific handler var cb; for (var i = 0; i < callbacks.length; i++) { cb = callbacks[i]; if (cb === fn || cb.fn === fn) { callbacks.splice(i, 1); break; } } return this; }; /** * Emit `event` with the given args. * * @param {String} event * @param {Mixed} ... * @return {Emitter} */ Emitter.prototype.emit = function(event){ this._callbacks = this._callbacks || {}; var args = [].slice.call(arguments, 1) , callbacks = this._callbacks[event]; if (callbacks) { callbacks = callbacks.slice(0); for (var i = 0, len = callbacks.length; i < len; ++i) { callbacks[i].apply(this, args); } } return this; }; /** * Return array of callbacks for `event`. * * @param {String} event * @return {Array} * @api public */ Emitter.prototype.listeners = function(event){ this._callbacks = this._callbacks || {}; return this._callbacks[event] || []; }; /** * Check if this emitter has `event` handlers. * * @param {String} event * @return {Boolean} * @api public */ Emitter.prototype.hasListeners = function(event){ return !! this.listeners(event).length; }; /***/ }, /* 4 */ /***/ function(module, exports) { /** * Reduce `arr` with `fn`. * * @param {Array} arr * @param {Function} fn * @param {Mixed} initial * * TODO: combatible error handling? */ module.exports = function(arr, fn, initial){ var idx = 0; var len = arr.length; var curr = arguments.length == 3 ? initial : arr[idx++]; while (idx < len) { curr = fn.call(null, curr, arr[idx], ++idx, arr); } return curr; }; /***/ }, /* 5 */ /***/ function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (root, factory){ 'use strict'; /*istanbul ignore next:cant test*/ if (typeof module === 'object' && typeof module.exports === 'object') { module.exports = factory(); } else if (true) { // AMD. Register as an anonymous module. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); } else { // Browser globals root.objectPath = factory(); } })(this, function(){ 'use strict'; var toStr = Object.prototype.toString, _hasOwnProperty = Object.prototype.hasOwnProperty; function isEmpty(value){ if (!value) { return true; } if (isArray(value) && value.length === 0) { return true; } else if (!isString(value)) { for (var i in value) { if (_hasOwnProperty.call(value, i)) { return false; } } return true; } return false; } function toString(type){ return toStr.call(type); } function isNumber(value){ return typeof value === 'number' || toString(value) === "[object Number]"; } function isString(obj){ return typeof obj === 'string' || toString(obj) === "[object String]"; } function isObject(obj){ return typeof obj === 'object' && toString(obj) === "[object Object]"; } function isArray(obj){ return typeof obj === 'object' && typeof obj.length === 'number' && toString(obj) === '[object Array]'; } function isBoolean(obj){ return typeof obj === 'boolean' || toString(obj) === '[object Boolean]'; } function getKey(key){ var intKey = parseInt(key); if (intKey.toString() === key) { return intKey; } return key; } function set(obj, path, value, doNotReplace){ if (isNumber(path)) { path = [path]; } if (isEmpty(path)) { return obj; } if (isString(path)) { return set(obj, path.split('.').map(getKey), value, doNotReplace); } var currentPath = path[0]; if (path.length === 1) { var oldVal = obj[currentPath]; if (oldVal === void 0 || !doNotReplace) { obj[currentPath] = value; } return oldVal; } if (obj[currentPath] === void 0) { //check if we assume an array if(isNumber(path[1])) { obj[currentPath] = []; } else { obj[currentPath] = {}; } } return set(obj[currentPath], path.slice(1), value, doNotReplace); } function del(obj, path) { if (isNumber(path)) { path = [path]; } if (isEmpty(obj)) { return void 0; } if (isEmpty(path)) { return obj; } if(isString(path)) { return del(obj, path.split('.')); } var currentPath = getKey(path[0]); var oldVal = obj[currentPath]; if(path.length === 1) { if (oldVal !== void 0) { if (isArray(obj)) { obj.splice(currentPath, 1); } else { delete obj[currentPath]; } } } else { if (obj[currentPath] !== void 0) { return del(obj[currentPath], path.slice(1)); } } return obj; } var objectPath = function(obj) { return Object.keys(objectPath).reduce(function(proxy, prop) { if (typeof objectPath[prop] === 'function') { proxy[prop] = objectPath[prop].bind(objectPath, obj); } return proxy; }, {}); }; objectPath.has = function (obj, path) { if (isEmpty(obj)) { return false; } if (isNumber(path)) { path = [path]; } else if (isString(path)) { path = path.split('.'); } if (isEmpty(path) || path.length === 0) { return false; } for (var i = 0; i < path.length; i++) { var j = path[i]; if ((isObject(obj) || isArray(obj)) && _hasOwnProperty.call(obj, j)) { obj = obj[j]; } else { return false; } } return true; }; objectPath.ensureExists = function (obj, path, value){ return set(obj, path, value, true); }; objectPath.set = function (obj, path, value, doNotReplace){ return set(obj, path, value, doNotReplace); }; objectPath.insert = function (obj, path, value, at){ var arr = objectPath.get(obj, path); at = ~~at; if (!isArray(arr)) { arr = []; objectPath.set(obj, path, arr); } arr.splice(at, 0, value); }; objectPath.empty = function(obj, path) { if (isEmpty(path)) { return obj; } if (isEmpty(obj)) { return void 0; } var value, i; if (!(value = objectPath.get(obj, path))) { return obj; } if (isString(value)) { return objectPath.set(obj, path, ''); } else if (isBoolean(value)) { return objectPath.set(obj, path, false); } else if (isNumber(value)) { return objectPath.set(obj, path, 0); } else if (isArray(value)) { value.length = 0; } else if (isObject(value)) { for (i in value) { if (_hasOwnProperty.call(value, i)) { delete value[i]; } } } else { return objectPath.set(obj, path, null); } }; objectPath.push = function (obj, path /*, values */){ var arr = objectPath.get(obj, path); if (!isArray(arr)) { arr = []; objectPath.set(obj, path, arr); } arr.push.apply(arr, Array.prototype.slice.call(arguments, 2)); }; objectPath.coalesce = function (obj, paths, defaultValue) { var value; for (var i = 0, len = paths.length; i < len; i++) { if ((value = objectPath.get(obj, paths[i])) !== void 0) { return value; } } return defaultValue; }; objectPath.get = function (obj, path, defaultValue){ if (isNumber(path)) { path = [path]; } if (isEmpty(path)) { return obj; } if (isEmpty(obj)) { return defaultValue; } if (isString(path)) { return objectPath.get(obj, path.split('.'), defaultValue); } var currentPath = getKey(path[0]); if (path.length === 1) { if (obj[currentPath] === void 0) { return defaultValue; } return obj[currentPath]; } return objectPath.get(obj[currentPath], path.slice(1), defaultValue); }; objectPath.del = function(obj, path) { return del(obj, path); }; return objectPath; }); /***/ }, /* 6 */ /***/ function(module, exports) { module.exports = __WEBPACK_EXTERNAL_MODULE_6__; /***/ }, /* 7 */ /***/ function(module, exports) { module.exports = __WEBPACK_EXTERNAL_MODULE_7__; /***/ }, /* 8 */ /***/ function(module, exports) { "use strict"; exports.__esModule = true; exports["default"] = clone; function clone(obj) { return JSON.parse(JSON.stringify(obj)); } module.exports = exports["default"]; /***/ }, /* 9 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; exports.__esModule = true; exports['default'] = deepEquals; var _jsonHash = __webpack_require__(10); function deepEquals(a, b) { return a === b || _jsonHash.digest(a) === _jsonHash.digest(b); } module.exports = exports['default']; /***/ }, /* 10 */ /***/ function(module, e