ask
Version:
A simple, chainable way to construct HTTP requests in Node or the browser
1,869 lines (1,559 loc) • 286 kB
JavaScript
!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.Ask=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 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 asArray = require('as-array');
var slash = require('slasher');
var request = require('httpify');
var join = require('join-path');
var Promise = require('promise');
var deap = require('deap');
var Emitter = require('tiny-emitter');
var proto = require('./lib/proto');
var mockRequestResponse = require('./lib/mock-request-response');
var clone = deap.clone;
var extend = deap.extend;
var HTTP_METHODS = 'GET POST PUT DELETE PATCH OPTIONS'.split(' ');
//
function Ask (options) {
if (!(this instanceof Ask)) return new Ask(options);
if (!options) options = {};
this.origin(options.origin);
this.headers = clone(options.headers);
this.xhrOptions = clone(options.xhrOptions);
this.events = new Emitter();
this.resources = {};
// Set up http method mocks
this.mocks = {};
HTTP_METHODS.forEach(function (method) {
this.mocks[method.toLowerCase()] = {};
}, this);
}
Ask.HTTP_METHODS = HTTP_METHODS;
Ask.join = join;
proto.mixInto(Ask.prototype);
Ask.prototype._rawHttp = function (options) {
var self = this;
return request(options, function (err, response) {
self.events.emit('response', {
error: err,
response: response
});
if (err || response.statusCode >= 400) {
self.events.emit('response:error', err || response);
}
if (!err) {
self.events.emit('response:success', response);
}
});
};
Ask.prototype.promise = function (callback) {
return new Promise(callback);
};
Ask.prototype.asPromise = function (data) {
return this.promise(function (resolve) {
resolve(data);
});
};
Ask.prototype.asRejectedPromise = function (data) {
return this.promise(function (resolve, reject) {
reject(data);
});
};
Ask.prototype.mock = function (method, pathname, mockObject) {
if (mockObject === undefined) return this.mocks[method.toLowerCase()][slash(pathname)];
return this.mocks[method.toLowerCase()][slash(pathname)] = mockObject;
};
Ask.prototype.http = function (method) {
var self = this;
var rawHttp = this._rawHttp.bind(this);
var uri = rest(asArray(arguments)).join('/');
// New resource object
var resource = function (params) {
var resourceObject = {
url: resource.url(),
method: method,
headers: resource.headers
};
if (typeof params === 'object') {
resourceObject.json = true;
resourceObject.body = params;
}
else if (typeof params === 'string') {
resourceObject.body = params;
}
// Should this resource be mocked, or real?
// It is ensured that you can define the mock before
// or after the resource is defined
var mock = self.mock(method, uri);
if (mock) {
mock.request = {
body: params,
method: method,
pathname: slash(uri),
headers: resource.headers
};
return mock.fn()();
}
else {
return rawHttp(extend(resourceObject, resource.xhrOptions || {}));
}
};
resource._uri = uri;
resource.attributes = clone(this.attributes);
resource.headers = clone(this.headers);
resource.xhrOptions = clone(this.xhrOptions);
resource.queries = clone(this.queries);
resource.extend = function () {
var extended = clone(resource);
extended._uri = join(resource._uri + '/' + asArray(arguments).join('/'));
return extended;
};
proto.mixInto(resource);
// Store resources
this.resources[resource.url()] = resource;
return resource;
};
Ask.prototype.when = function (method, pathname) {
var mockedRequest = mockRequestResponse(this, method, pathname);
return this.mock(method, pathname, mockedRequest);
};
// Create help http verb functions
Ask.HTTP_METHODS.forEach(function (method) {
Ask.prototype[method.toLowerCase()] = function () {
var args = asArray(arguments);
args.unshift(method);
return this.http.apply(this, args);
};
});
function rest (arr) {
return arr.slice(1);
}
//
module.exports = Ask;
},{"./lib/mock-request-response":2,"./lib/proto":3,"as-array":4,"deap":15,"httpify":18,"join-path":27,"promise":36,"slasher":42,"tiny-emitter":45}],2:[function(require,module,exports){
module.exports = function (context, method, pathname) {
return {
context: context,
method: method,
pathname: pathname,
body: null,
statusCode: 200,
headers: {},
respond: function (body) {
this.body = body;
this.context.mock(this.method, this.pathname, this);
return this;
},
status: function (code) {
if (code === undefined) return this.statusCode;
this.statusCode = code;
return this;
},
header: function (name, value) {
if (value === undefined) return this.headers[name.toLowerCase()];
this.headers[name.toLowerCase()] = value;
return this;
},
// Custom function to return when a mock is present
fn: function () {
var self = this;
return function () {
var status = self.statusCode;
if (status === 0 || (status >= 400 && status < 600)) {
return context.asRejectedPromise(self);
}
return context.asPromise(self);
};
}
};
};
},{}],3:[function(require,module,exports){
var mix = require('mix-into');
var join = require('join-path');
var extend = require('deap').extend;
// Proto mixin
module.exports = mix({
origin: function (origin) {
if (!this.attributes) this.attributes = {};
if (!origin) return this.attributes.origin;
this.attributes.origin = origin;
return this;
},
header: function (name, value) {
if (!this.headers) this.headers = {};
if (typeof name === 'object') {
extend(this.headers, name);
return this;
}
if (name && !value) return this.headers[name];
this.headers[name] = value;
return this;
},
query: function (name, value) {
if (!this.queries) this.queries = {};
// Parse query string
if (!name && !value) return parseQueryString(this.queries);
// Add values from an object
if (typeof name === 'object') {
extend(this.queries, name);
return this;
}
if (name && !value) return this.queries[name];
this.queries[name] = value;
return this;
},
xhrOption: function (name, value) {
if (!this.xhrOptions) this.xhrOptions = {};
if (name && !value) return this.xhrOptions[name];
this.xhrOptions[name] = value;
return this;
},
url: function () {
var url = this._uri;
if (this.origin()) url = join(this.origin(), this._uri);
// Add query string
if (Object.keys(this.queries || {}).length > 0) {
var connector = (url.indexOf('?') > -1) ? '&' : '?';
url = url + connector + this.query();
}
return url || '/';
}
});
function parseQueryString (queryObject) {
var qs = [];
Object
.keys(queryObject)
.forEach(function (key) {
var value = queryObject[key];
if (value) qs.push(key + '=' + value);
}, this);
return qs.join('&');
}
},{"deap":15,"join-path":27,"mix-into":32}],4:[function(require,module,exports){
var isArgs = require('lodash.isarguments');
var isObject = require('lodash.isobject');
var values = require('lodash.values');
module.exports = function (data, convertObject) {
if (!data) {
data = [];
}
if (isArgs(data)) {
data = [].splice.call(data, 0);
}
if (isObject(data) && convertObject) {
data = values(data);
}
return Array.isArray(data)
? data
: [data];
};
},{"lodash.isarguments":5,"lodash.isobject":6,"lodash.values":8}],5:[function(require,module,exports){
/**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="npm" -o ./npm/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** `Object#toString` result shortcuts */
var argsClass = '[object Arguments]';
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/**
* Checks if `value` is an `arguments` object.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
* @example
*
* (function() { return _.isArguments(arguments); })(1, 2, 3);
* // => true
*
* _.isArguments([1, 2, 3]);
* // => false
*/
function isArguments(value) {
return value && typeof value == 'object' && typeof value.length == 'number' &&
toString.call(value) == argsClass || false;
}
module.exports = isArguments;
},{}],6:[function(require,module,exports){
/**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="npm" -o ./npm/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var objectTypes = require('lodash._objecttypes');
/**
* Checks if `value` is the language type of Object.
* (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is an object, else `false`.
* @example
*
* _.isObject({});
* // => true
*
* _.isObject([1, 2, 3]);
* // => true
*
* _.isObject(1);
* // => false
*/
function isObject(value) {
// check if the value is the ECMAScript language type of Object
// http://es5.github.io/#x8
// and avoid a V8 bug
// http://code.google.com/p/v8/issues/detail?id=2291
return !!(value && objectTypes[typeof value]);
}
module.exports = isObject;
},{"lodash._objecttypes":7}],7:[function(require,module,exports){
/**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="npm" -o ./npm/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** Used to determine if values are of the language type Object */
var objectTypes = {
'boolean': false,
'function': true,
'object': true,
'number': false,
'string': false,
'undefined': false
};
module.exports = objectTypes;
},{}],8:[function(require,module,exports){
/**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="npm" -o ./npm/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var keys = require('lodash.keys');
/**
* Creates an array composed of the own enumerable property values of `object`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property values.
* @example
*
* _.values({ 'one': 1, 'two': 2, 'three': 3 });
* // => [1, 2, 3] (property order is not guaranteed across environments)
*/
function values(object) {
var index = -1,
props = keys(object),
length = props.length,
result = Array(length);
while (++index < length) {
result[index] = object[props[index]];
}
return result;
}
module.exports = values;
},{"lodash.keys":9}],9:[function(require,module,exports){
/**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="npm" -o ./npm/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isNative = require('lodash._isnative'),
isObject = require('lodash.isobject'),
shimKeys = require('lodash._shimkeys');
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys;
/**
* Creates an array composed of the own enumerable property names of an object.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property names.
* @example
*
* _.keys({ 'one': 1, 'two': 2, 'three': 3 });
* // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
*/
var keys = !nativeKeys ? shimKeys : function(object) {
if (!isObject(object)) {
return [];
}
return nativeKeys(object);
};
module.exports = keys;
},{"lodash._isnative":10,"lodash._shimkeys":11,"lodash.isobject":6}],10:[function(require,module,exports){
/**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="npm" -o ./npm/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/** Used to detect if a method is native */
var reNative = RegExp('^' +
String(toString)
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
.replace(/toString| for [^\]]+/g, '.*?') + '$'
);
/**
* Checks if `value` is a native function.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a native function, else `false`.
*/
function isNative(value) {
return typeof value == 'function' && reNative.test(value);
}
module.exports = isNative;
},{}],11:[function(require,module,exports){
/**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="npm" -o ./npm/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var objectTypes = require('lodash._objecttypes');
/** Used for native method references */
var objectProto = Object.prototype;
/** Native method shortcuts */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* A fallback implementation of `Object.keys` which produces an array of the
* given object's own enumerable property names.
*
* @private
* @type Function
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property names.
*/
var shimKeys = function(object) {
var index, iterable = object, result = [];
if (!iterable) return result;
if (!(objectTypes[typeof object])) return result;
for (index in iterable) {
if (hasOwnProperty.call(iterable, index)) {
result.push(index);
}
}
return result
};
module.exports = shimKeys;
},{"lodash._objecttypes":12}],12:[function(require,module,exports){
module.exports=require(7)
},{"/Users/scott/www/divshot/ask/node_modules/as-array/node_modules/lodash.isobject/node_modules/lodash._objecttypes/index.js":7}],13:[function(require,module,exports){
(function (process){
// Copyright Joyent, Inc. and other Node contributors.
//
// 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:
//
// 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.
// resolves . and .. elements in a path array with directory names there
// must be no slashes, empty elements, or device names (c:\) in the array
// (so also no leading and trailing slashes - it does not distinguish
// relative and absolute paths)
function normalizeArray(parts, allowAboveRoot) {
// if the path tries to go above the root, `up` ends up > 0
var up = 0;
for (var i = parts.length - 1; i >= 0; i--) {
var last = parts[i];
if (last === '.') {
parts.splice(i, 1);
} else if (last === '..') {
parts.splice(i, 1);
up++;
} else if (up) {
parts.splice(i, 1);
up--;
}
}
// if the path is allowed to go above the root, restore leading ..s
if (allowAboveRoot) {
for (; up--; up) {
parts.unshift('..');
}
}
return parts;
}
// Split a filename into [root, dir, basename, ext], unix version
// 'root' is just a slash, or nothing.
var splitPathRe =
/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
var splitPath = function(filename) {
return splitPathRe.exec(filename).slice(1);
};
// path.resolve([from ...], to)
// posix version
exports.resolve = function() {
var resolvedPath = '',
resolvedAbsolute = false;
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
var path = (i >= 0) ? arguments[i] : process.cwd();
// Skip empty and invalid entries
if (typeof path !== 'string') {
throw new TypeError('Arguments to path.resolve must be strings');
} else if (!path) {
continue;
}
resolvedPath = path + '/' + resolvedPath;
resolvedAbsolute = path.charAt(0) === '/';
}
// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)
// Normalize the path
resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
return !!p;
}), !resolvedAbsolute).join('/');
return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
};
// path.normalize(path)
// posix version
exports.normalize = function(path) {
var isAbsolute = exports.isAbsolute(path),
trailingSlash = substr(path, -1) === '/';
// Normalize the path
path = normalizeArray(filter(path.split('/'), function(p) {
return !!p;
}), !isAbsolute).join('/');
if (!path && !isAbsolute) {
path = '.';
}
if (path && trailingSlash) {
path += '/';
}
return (isAbsolute ? '/' : '') + path;
};
// posix version
exports.isAbsolute = function(path) {
return path.charAt(0) === '/';
};
// posix version
exports.join = function() {
var paths = Array.prototype.slice.call(arguments, 0);
return exports.normalize(filter(paths, function(p, index) {
if (typeof p !== 'string') {
throw new TypeError('Arguments to path.join must be strings');
}
return p;
}).join('/'));
};
// path.relative(from, to)
// posix version
exports.relative = function(from, to) {
from = exports.resolve(from).substr(1);
to = exports.resolve(to).substr(1);
function trim(arr) {
var start = 0;
for (; start < arr.length; start++) {
if (arr[start] !== '') break;
}
var end = arr.length - 1;
for (; end >= 0; end--) {
if (arr[end] !== '') break;
}
if (start > end) return [];
return arr.slice(start, end - start + 1);
}
var fromParts = trim(from.split('/'));
var toParts = trim(to.split('/'));
var length = Math.min(fromParts.length, toParts.length);
var samePartsLength = length;
for (var i = 0; i < length; i++) {
if (fromParts[i] !== toParts[i]) {
samePartsLength = i;
break;
}
}
var outputParts = [];
for (var i = samePartsLength; i < fromParts.length; i++) {
outputParts.push('..');
}
outputParts = outputParts.concat(toParts.slice(samePartsLength));
return outputParts.join('/');
};
exports.sep = '/';
exports.delimiter = ':';
exports.dirname = function(path) {
var result = splitPath(path),
root = result[0],
dir = result[1];
if (!root && !dir) {
// No dirname whatsoever
return '.';
}
if (dir) {
// It has a dirname, strip trailing slash
dir = dir.substr(0, dir.length - 1);
}
return root + dir;
};
exports.basename = function(path, ext) {
var f = splitPath(path)[2];
// TODO: make this comparison case-insensitive on windows?
if (ext && f.substr(-1 * ext.length) === ext) {
f = f.substr(0, f.length - ext.length);
}
return f;
};
exports.extname = function(path) {
return splitPath(path)[3];
};
function filter (xs, f) {
if (xs.filter) return xs.filter(f);
var res = [];
for (var i = 0; i < xs.length; i++) {
if (f(xs[i], i, xs)) res.push(xs[i]);
}
return res;
}
// String.prototype.substr - negative index don't work in IE8
var substr = 'ab'.substr(-1) === 'b'
? function (str, start, len) { return str.substr(start, len) }
: function (str, start, len) {
if (start < 0) start = str.length + start;
return str.substr(start, len);
}
;
}).call(this,require('_process'))
},{"_process":14}],14:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
process.nextTick = (function () {
var canSetImmediate = typeof window !== 'undefined'
&& window.setImmediate;
var canMutationObserver = typeof window !== 'undefined'
&& window.MutationObserver;
var canPost = typeof window !== 'undefined'
&& window.postMessage && window.addEventListener
;
if (canSetImmediate) {
return function (f) { return window.setImmediate(f) };
}
var queue = [];
if (canMutationObserver) {
var hiddenDiv = document.createElement("div");
var observer = new MutationObserver(function () {
var queueList = queue.slice();
queue.length = 0;
queueList.forEach(function (fn) {
fn();
});
});
observer.observe(hiddenDiv, { attributes: true });
return function nextTick(fn) {
if (!queue.length) {
hiddenDiv.setAttribute('yes', 'no');
}
queue.push(fn);
};
}
if (canPost) {
window.addEventListener('message', function (ev) {
var source = ev.source;
if ((source === window || source === null) && ev.data === 'process-tick') {
ev.stopPropagation();
if (queue.length > 0) {
var fn = queue.shift();
fn();
}
}
}, true);
return function nextTick(fn) {
queue.push(fn);
window.postMessage('process-tick', '*');
};
}
return function nextTick(fn) {
setTimeout(fn, 0);
};
})();
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
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');
};
// TODO(shtylman)
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
},{}],15:[function(require,module,exports){
var lib = require('./lib/deap');
var deap = module.exports = lib.extend;
deap(deap, {
clone: lib.clone,
extend: lib.extend,
update: lib.update,
merge: lib.merge,
cloneShallow: lib.cloneShallow,
extendShallow: lib.extendShallow,
updateShallow: lib.updateShallow,
mergeShallow: lib.mergeShallow
});
},{"./lib/deap":16}],16:[function(require,module,exports){
var typeOf = require('./typeof'),
slice = Array.prototype.slice;
module.exports = {
clone: deepClone,
cloneShallow: clone,
extend: deepExtend,
extendShallow: extend,
update: deepUpdate,
updateShallow: update,
merge: deepMerge,
mergeShallow: merge
};
function clone(val) {
switch(typeOf(val)) {
case 'object':
var args = slice.call(arguments);
args.unshift({});
return extend.apply(null, args);
case 'array':
return [].concat(val);
case 'date':
return new Date(val.getTime());
case 'regexp':
return new RegExp(val);
default:
return val;
}
}
function deepClone(val) {
switch(typeOf(val)) {
case 'object':
var args = slice.call(arguments);
args.unshift({});
return deepExtend.apply(null, args);
case 'array':
return val.map(function(v) { return deepClone(v); });
default:
return clone(val);
}
}
function extend(a, b /*, [b2..n] */) {
slice.call(arguments, 1).forEach(function(b) {
Object.keys(b).forEach(function(p) {
a[p] = b[p];
});
});
return a;
}
function deepExtend(a, b /*, [b2..n] */) {
slice.call(arguments, 1).forEach(function(b) {
Object.keys(b).forEach(function(p) {
if(typeOf(b[p]) === 'object' && typeOf(a[p]) === 'object')
deepExtend(a[p], b[p]);
else
a[p] = deepClone(b[p]);
});
});
return a;
}
function update(a, b /*, [b2..n] */) {
slice.call(arguments, 1).forEach(function(b) {
Object.keys(b).forEach(function(p) {
if(a.hasOwnProperty(p)) a[p] = b[p];
});
});
return a;
}
function deepUpdate(a, b /*, [b2..n] */) {
slice.call(arguments, 1).forEach(function(b) {
var ap, bp, ta, tb;
Object.keys(b).forEach(function(p) {
if(a.hasOwnProperty(p)) {
ap = a[p];
bp = b[p];
ta = typeOf(ap);
tb = typeOf(bp);
if(tb === 'object' && ta === 'object')
deepUpdate(ap, bp);
else if(tb === 'array' && ta === 'array') {
ap.length = 0;
ap.push.apply(ap, bp.map(function(v) { return deepClone(v); }));
} else
a[p] = deepClone(bp);
}
});
});
return a;
}
function merge(a, b /*, [b2..n] */) {
slice.call(arguments, 1).forEach(function(b) {
Object.keys(b).forEach(function(p) {
if(!a.hasOwnProperty(p)) a[p] = b[p];
});
});
return a;
}
function deepMerge(a, b /*, [b2..n] */) {
slice.call(arguments, 1).forEach(function(b) {
var ap, bp, ta, tb;
Object.keys(b).forEach(function(p) {
ap = a[p];
bp = b[p];
ta = typeOf(ap);
tb = typeOf(bp);
if(tb === 'object' && ta === 'object')
deepMerge(ap, bp);
else if(!a.hasOwnProperty(p))
a[p] = deepClone(bp);
});
});
return a;
}
},{"./typeof":17}],17:[function(require,module,exports){
module.exports = function(obj) {
var t = typeof obj;
if(t !== 'object') return t;
// typeof null == 'object' so check seperately
if(obj === null) return 'null';
// typeof new Array|String|Number|Boolean|RegExp == 'object' so check seperately
switch(obj.constructor) {
case Array: return 'array';
case String: return 'string';
case Number: return 'number';
case Boolean: return 'boolean';
case RegExp: return 'regexp';
case Date: return 'date';
}
return 'object';
};
},{}],18:[function(require,module,exports){
var Promise = require('promise');
var request = require('request');
module.exports = function (options, callback) {
return new Promise(function (resolve, reject) {
request(options, function (err, response, body) {
var status = (response) ? response.statusCode : 0;
callback = callback || function () {};
if (err) {
callback(err);
reject(err);
return
}
try{
response.body = JSON.parse(body);
}
catch (e) {}
if (status >= 400 && status < 600) {
callback(null, response);
reject(response);
return
}
callback(null, response);
resolve(response);
});
});
};
},{"promise":36,"request":19}],19:[function(require,module,exports){
var request = require('xhr');
// Wrapper to make the features more similiar between
// request and xhr
module.exports = function (options, callback) {
callback = callback || function () {};
// Set up for Request module
if (options.data && !window) options.form = options.data;
// Set up for xhr module
if (options.form && window) {
options.body = (typeof options.form === 'object')
? JSON.stringify(options.form)
: options.form;
}
if (options.data) {
options.body = (typeof options.data === 'object')
? JSON.stringify(options.data)
: options.data;
}
if (options.url && window) options.uri = options.url;
if (window) options.cors = options.withCredentials;
return request(options, callback);
};
},{"xhr":20}],20:[function(require,module,exports){
var window = require("global/window")
var once = require("once")
var parseHeaders = require('parse-headers')
var messages = {
"0": "Internal XMLHttpRequest Error",
"4": "4xx Client Error",
"5": "5xx Server Error"
}
var XHR = window.XMLHttpRequest || noop
var XDR = "withCredentials" in (new XHR()) ? XHR : window.XDomainRequest
module.exports = createXHR
function createXHR(options, callback) {
if (typeof options === "string") {
options = { uri: options }
}
options = options || {}
callback = once(callback)
var xhr = options.xhr || null
if (!xhr) {
if (options.cors || options.useXDR) {
xhr = new XDR()
}else{
xhr = new XHR()
}
}
var uri = xhr.url = options.uri || options.url
var method = xhr.method = options.method || "GET"
var body = options.body || options.data
var headers = xhr.headers = options.headers || {}
var sync = !!options.sync
var isJson = false
var key
var load = options.response ? loadResponse : loadXhr
if ("json" in options) {
isJson = true
headers["Accept"] = "application/json"
if (method !== "GET" && method !== "HEAD") {
headers["Content-Type"] = "application/json"
body = JSON.stringify(options.json)
}
}
xhr.onreadystatechange = readystatechange
xhr.onload = load
xhr.onerror = error
// IE9 must have onprogress be set to a unique function.
xhr.onprogress = function () {
// IE must die
}
// hate IE
xhr.ontimeout = noop
xhr.open(method, uri, !sync)
//backward compatibility
if (options.withCredentials || (options.cors && options.withCredentials !== false)) {
xhr.withCredentials = true
}
// Cannot set timeout with sync request
if (!sync) {
xhr.timeout = "timeout" in options ? options.timeout : 5000
}
if (xhr.setRequestHeader) {
for(key in headers){
if(headers.hasOwnProperty(key)){
xhr.setRequestHeader(key, headers[key])
}
}
} else if (options.headers) {
throw new Error("Headers cannot be set on an XDomainRequest object")
}
if ("responseType" in options) {
xhr.responseType = options.responseType
}
if ("beforeSend" in options &&
typeof options.beforeSend === "function"
) {
options.beforeSend(xhr)
}
xhr.send(body)
return xhr
function readystatechange() {
if (xhr.readyState === 4) {
load()
}
}
function getBody() {
// Chrome with requestType=blob throws errors arround when even testing access to responseText
var body = null
if (xhr.response) {
body = xhr.response
} else if (xhr.responseType === 'text' || !xhr.responseType) {
body = xhr.responseText || xhr.responseXML
}
if (isJson) {
try {
body = JSON.parse(body)
} catch (e) {}
}
return body
}
function getStatusCode() {
return xhr.status === 1223 ? 204 : xhr.status
}
// if we're getting a none-ok statusCode, build & return an error
function errorFromStatusCode(status, body) {
var error = null
if (status === 0 || (status >= 400 && status < 600)) {
var message = (typeof body === "string" ? body : false) ||
messages[String(status).charAt(0)]
error = new Error(message)
error.statusCode = status
}
return error
}
// will load the data & process the response in a special response object
function loadResponse() {
var status = getStatusCode()
var body = getBody()
var error = errorFromStatusCode(status, body)
var response = {
body: body,
statusCode: status,
statusText: xhr.statusText,
raw: xhr
}
if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE
response.headers = parseHeaders(xhr.getAllResponseHeaders())
} else {
response.headers = {}
}
callback(error, response, response.body)
}
// will load the data and add some response properties to the source xhr
// and then respond with that
function loadXhr() {
var status = getStatusCode()
var error = errorFromStatusCode(status)
xhr.status = xhr.statusCode = status
xhr.body = getBody()
xhr.headers = parseHeaders(xhr.getAllResponseHeaders())
callback(error, xhr, xhr.body)
}
function error(evt) {
callback(evt, xhr)
}
}
function noop() {}
},{"global/window":21,"once":22,"parse-headers":26}],21:[function(require,module,exports){
(function (global){
if (typeof window !== "undefined") {
module.exports = window;
} else if (typeof global !== "undefined") {
module.exports = global;
} else if (typeof self !== "undefined"){
module.exports = self;
} else {
module.exports = {};
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],22:[function(require,module,exports){
module.exports = once
once.proto = once(function () {
Object.defineProperty(Function.prototype, 'once', {
value: function () {
return once(this)
},
configurable: true
})
})
function once (fn) {
var called = false
return function () {
if (called) return
called = true
return fn.apply(this, arguments)
}
}
},{}],23:[function(require,module,exports){
var isFunction = require('is-function')
module.exports = forEach
var toString = Object.prototype.toString
var hasOwnProperty = Object.prototype.hasOwnProperty
function forEach(list, iterator, context) {
if (!isFunction(iterator)) {
throw new TypeError('iterator must be a function')
}
if (arguments.length < 3) {
context = this
}
if (toString.call(list) === '[object Array]')
forEachArray(list, iterator, context)
else if (typeof list === 'string')
forEachString(list, iterator, context)
else
forEachObject(list, iterator, context)
}
function forEachArray(array, iterator, context) {
for (var i = 0, len = array.length; i < len; i++) {
if (hasOwnProperty.call(array, i)) {
iterator.call(context, array[i], i, array)
}
}
}
function forEachString(string, iterator, context) {
for (var i = 0, len = string.length; i < len; i++) {
// no such thing as a sparse string.
iterator.call(context, string.charAt(i), i, string)
}
}
function forEachObject(object, iterator, context) {
for (var k in object) {
if (hasOwnProperty.call(object, k)) {
iterator.call(context, object[k], k, object)
}
}
}
},{"is-function":24}],24:[function(require,module,exports){
module.exports = isFunction
var toString = Object.prototype.toString
function isFunction (fn) {
var string = toString.call(fn)
return string === '[object Function]' ||
(typeof fn === 'function' && string !== '[object RegExp]') ||
(typeof window !== 'undefined' &&
// IE8 and below
(fn === window.setTimeout ||
fn === window.alert ||
fn === window.confirm ||
fn === window.prompt))
};
},{}],25:[function(require,module,exports){
exports = module.exports = trim;
function trim(str){
return str.replace(/^\s*|\s*$/g, '');
}
exports.left = function(str){
return str.replace(/^\s*/, '');
};
exports.right = function(str){
return str.replace(/\s*$/, '');
};
},{}],26:[function(require,module,exports){
var trim = require('trim')
, forEach = require('for-each')
, isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
}
module.exports = function (headers) {
if (!headers)
return {}
var result = {}
forEach(
trim(headers).split('\n')
, function (row) {
var index = row.indexOf(':')
, key = trim(row.slice(0, index)).toLowerCase()
, value = trim(row.slice(index + 1))
if (typeof(result[key]) === 'undefined') {
result[key] = value
} else if (isArray(result[key])) {
result[key].push(value)
} else {
result[key] = [ result[key], value ]
}
}
)
return result
}
},{"for-each":23,"trim":25}],27:[function(require,module,exports){
var path = require('path');
var urlJoin = require('url-join');
var asArray = require('as-array');
var _isUrl = require('is-url');
var exports = module.exports = function () {
var paths = asArray(arguments)
.map(replaceUndefined);
return isUrl(paths[0])
? urlJoin.apply(urlJoin, paths)
: path.join.apply(path, paths);
};
var isUrl = exports.isUrl = function (url) {
return _isUrl(url)
|| url === 'http://'
|| url === 'https://'
|| url === 'ftp://';
};
var replaceUndefined = exports.replaceUndefined = function (p, idx, paths) {
return (p == undefined || p == null)
? isUrl(paths[0]) ? '/' : path.sep
: p;
}
},{"as-array":28,"is-url":30,"path":13,"url-join":31}],28:[function(require,module,exports){
var isArgs = require('lodash.isarguments');
module.exports = function (data) {
if (!data) data = [];
if (isArgs(data)) data = [].splice.call(data, 0);
return Array.isArray(data)
? data
: [data];
};
},{"lodash.isarguments":29}],29:[function(require,module,exports){
module.exports=require(5)
},{"/Users/scott/www/divshot/ask/node_modules/as-array/node_modules/lodash.isarguments/index.js":5}],30:[function(require,module,exports){
/**
* Expose `isUrl`.
*/
module.exports = isUrl;
/**
* Matcher.
*/
var matcher = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/;
/**
* Loosely validate a URL `string`.
*
* @param {String} string
* @return {Boolean}
*/
function isUrl(string){
return matcher.test(string);
}
},{}],31:[function(require,module,exports){
function normalize (str) {
return str
.replace(/[\/]+/g, '/')
.replace(/\/\?/g, '?')
.replace(/\/\#/g, '#')
.replace(/\:\//g, '://');
}
module.exports = function () {
var joined = [].slice.call(arguments, 0).join('/');
return normalize(joined);
};
},{}],32:[function(require,module,exports){
var clone = require('deap').clone;
var mix = function (source) {
return new Mix(source);
};
var Mix = function (source) {
this.source = source;
};
Mix.prototype.into = function (target) {
target = target || {};
var keys = Object.keys(this.source);
var len = keys.length;
var i = 0;
var key;
var val;
for (i; i < len; i += 1) {
key = keys[i]
val = this.source[key];
if (target[key] === undefined) target[key] = this.source[key];
}
if (target.mixInto === undefined) target.mixInto = mixInto;
return target;
};
Mix.prototype.intoClone = function (target) {
return this.into(clone(target));
};
Mix.prototype.mixInto = function (target) {
return this.into(target);
};
Mix.prototype.create = function () {
return clone(this.source);
};
function mixInto (source) {
return mix(this).into(source);
}
module.exports = mix;
},{"deap":33}],33:[function(require,module,exports){
module.exports=require(15)
},{"./lib/deap":34,"/Users/scott/www/divshot/ask/node_modules/deap/index.js":15}],34:[function(require,module,exports){
module.exports=require(16)
},{"./typeof":35,"/Users/scott/www/divshot/ask/node_modules/deap/lib/deap.js":16}],35:[function(require,module,exports){
module.exports=require(17)
},{"/Users/scott/www/divshot/ask/node_modules/deap/lib/typeof.js":17}],36:[function(require,module,exports){
'use strict';
module.exports = require('./lib/core.js')
require('./lib/done.js')
require('./lib/es6-extensions.js')
require('./lib/node-extensions.js')
},{"./lib/core.js":37,"./lib/done.js":38,"./lib/es6-extensions.js":39,"./lib/node-extensions.js":40}],37:[function(require,module,exports){
'use strict';
var asap = require('asap')
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)
}
}
},{"asap":41}],38:[function(require,module,exports){
'use strict';
var Promise = require('./core.js')
var asap = require('asap')
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
})
})
}
},{"./core.js":37,"asap":41}],39:[function(require,module,exports){
'use strict';
//This file contains the ES6 extensions to the core Promises/A+ API
var Promise = require('./core.js')
var asap = require('asap')
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);
}
},{"./core.js":37,"asap":41}],40:[function(require,module,exports){
'use strict';
//This file contains then/promise specific extensions that are only useful for node.js interop
var Promise = require('./core.js')
var asap = require('asap')
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,