hurbis-ui-seguranca-v1-snapshot
Version:
Biblioteca de segurança para autenticação e autorização utilizando Auth0.
1,794 lines (1,528 loc) • 313 kB
JavaScript
(function() {
// Create all modules and define dependencies to make sure they exist
// and are loaded in the correct order to satisfy dependency injection
// before all nested files are concatenated by Grunt
// Modules
angular.module('angular-jwt',
[
'angular-jwt.options',
'angular-jwt.interceptor',
'angular-jwt.jwt',
'angular-jwt.authManager'
]);
angular.module('angular-jwt.authManager', [])
.provider('authManager', function () {
this.$get = ["$rootScope", "$injector", "$location", "jwtHelper", "jwtInterceptor", "jwtOptions", function ($rootScope, $injector, $location, jwtHelper, jwtInterceptor, jwtOptions) {
var config = jwtOptions.getConfig();
function invokeToken(tokenGetter) {
var token = null;
if (Array.isArray(tokenGetter)) {
token = $injector.invoke(tokenGetter, this, {options: null});
} else {
token = tokenGetter();
}
return token;
}
function invokeRedirector(redirector) {
if (Array.isArray(redirector) || angular.isFunction(redirector)) {
return $injector.invoke(redirector, config, {});
} else {
throw new Error('unauthenticatedRedirector must be a function');
}
}
function isAuthenticated() {
var token = invokeToken(config.tokenGetter);
if (token) {
return !jwtHelper.isTokenExpired(token);
}
}
$rootScope.isAuthenticated = false;
function authenticate() {
$rootScope.isAuthenticated = true;
}
function unauthenticate() {
$rootScope.isAuthenticated = false;
}
function validateToken() {
var token = invokeToken(config.tokenGetter);
if (token) {
if (!jwtHelper.isTokenExpired(token)) {
authenticate();
} else {
$rootScope.$broadcast('tokenHasExpired', token);
}
}
}
function checkAuthOnRefresh() {
if ($injector.has('$transitions')) {
var $transitions = $injector.get('$transitions');
$transitions.onStart({}, validateToken);
} else {
$rootScope.$on('$locationChangeStart', validateToken);
}
}
function redirectWhenUnauthenticated() {
$rootScope.$on('unauthenticated', function () {
invokeRedirector(config.unauthenticatedRedirector);
unauthenticate();
});
}
function verifyRoute(event, next) {
if (!next) {
return false;
}
var routeData = (next.$$route) ? next.$$route : next.data;
if (routeData && routeData.requiresLogin === true && !isAuthenticated()) {
event.preventDefault();
invokeRedirector(config.unauthenticatedRedirector);
}
}
function verifyState(transition) {
var route = transition.to();
var $state = transition.router.stateService;
if (route && route.data && route.data.requiresLogin === true && !isAuthenticated()) {
return $state.target(config.loginPath);
}
}
if ($injector.has('$transitions')) {
var $transitions = $injector.get('$transitions');
$transitions.onStart({}, verifyState);
} else {
var eventName = ($injector.has('$state')) ? '$stateChangeStart' : '$routeChangeStart';
$rootScope.$on(eventName, verifyRoute);
}
return {
authenticate: authenticate,
unauthenticate: unauthenticate,
getToken: function(){ return invokeToken(config.tokenGetter); },
redirect: function() { return invokeRedirector(config.unauthenticatedRedirector); },
checkAuthOnRefresh: checkAuthOnRefresh,
redirectWhenUnauthenticated: redirectWhenUnauthenticated,
isAuthenticated: isAuthenticated
}
}]
});
angular.module('angular-jwt.interceptor', [])
.provider('jwtInterceptor', function() {
this.urlParam;
this.authHeader;
this.authPrefix;
this.whiteListedDomains;
this.tokenGetter;
var config = this;
this.$get = ["$q", "$injector", "$rootScope", "urlUtils", "jwtOptions", function($q, $injector, $rootScope, urlUtils, jwtOptions) {
var options = angular.extend({}, jwtOptions.getConfig(), config);
function isSafe (url) {
if (!urlUtils.isSameOrigin(url) && !options.whiteListedDomains.length) {
throw new Error('As of v0.1.0, requests to domains other than the application\'s origin must be white listed. Use jwtOptionsProvider.config({ whiteListedDomains: [<domain>] }); to whitelist.')
}
var hostname = urlUtils.urlResolve(url).hostname.toLowerCase();
for (var i = 0; i < options.whiteListedDomains.length; i++) {
var domain = options.whiteListedDomains[i];
if (domain instanceof RegExp) {
if (hostname.match(domain)) {
return true;
}
} else {
if (hostname === domain.toLowerCase()) {
return true;
}
}
}
if (urlUtils.isSameOrigin(url)) {
return true;
}
return false;
}
return {
request: function (request) {
if (request.skipAuthorization || !isSafe(request.url)) {
return request;
}
if (options.urlParam) {
request.params = request.params || {};
// Already has the token in the url itself
if (request.params[options.urlParam]) {
return request;
}
} else {
request.headers = request.headers || {};
// Already has an Authorization header
if (request.headers[options.authHeader]) {
return request;
}
}
var tokenPromise = $q.when($injector.invoke(options.tokenGetter, this, {
options: request
}));
return tokenPromise.then(function(token) {
if (token) {
if (options.urlParam) {
request.params[options.urlParam] = token;
} else {
request.headers[options.authHeader] = options.authPrefix + token;
}
}
return request;
});
},
responseError: function (response) {
// handle the case where the user is not authenticated
if (response.status === 401) {
$rootScope.$broadcast('unauthenticated', response);
}
return $q.reject(response);
}
};
}]
});
angular.module('angular-jwt.jwt', [])
.service('jwtHelper', ["$window", function($window) {
this.urlBase64Decode = function(str) {
var output = str.replace(/-/g, '+').replace(/_/g, '/');
switch (output.length % 4) {
case 0: { break; }
case 2: { output += '=='; break; }
case 3: { output += '='; break; }
default: {
throw 'Illegal base64url string!';
}
}
return $window.decodeURIComponent(escape($window.atob(output))); //polyfill https://github.com/davidchambers/Base64.js
};
this.decodeToken = function(token) {
var parts = token.split('.');
if (parts.length !== 3) {
throw new Error('JWT must have 3 parts');
}
var decoded = this.urlBase64Decode(parts[1]);
if (!decoded) {
throw new Error('Cannot decode the token');
}
return angular.fromJson(decoded);
};
this.getTokenExpirationDate = function(token) {
var decoded = this.decodeToken(token);
if(typeof decoded.exp === "undefined") {
return null;
}
var d = new Date(0); // The 0 here is the key, which sets the date to the epoch
d.setUTCSeconds(decoded.exp);
return d;
};
this.isTokenExpired = function(token, offsetSeconds) {
var d = this.getTokenExpirationDate(token);
offsetSeconds = offsetSeconds || 0;
if (d === null) {
return false;
}
// Token expired?
return !(d.valueOf() > (new Date().valueOf() + (offsetSeconds * 1000)));
};
}]);
angular.module('angular-jwt.options', [])
.provider('jwtOptions', function() {
var globalConfig = {};
this.config = function(value) {
globalConfig = value;
};
this.$get = function() {
var options = {
urlParam: null,
authHeader: 'Authorization',
authPrefix: 'Bearer ',
whiteListedDomains: [],
tokenGetter: function() {
return null;
},
loginPath: '/',
unauthenticatedRedirectPath: '/',
unauthenticatedRedirector: ['$location', function($location) {
$location.path(this.unauthenticatedRedirectPath);
}]
};
function JwtOptions() {
var config = this.config = angular.extend({}, options, globalConfig);
}
JwtOptions.prototype.getConfig = function() {
return this.config;
};
return new JwtOptions();
}
});
/**
* The content from this file was directly lifted from Angular. It is
* unfortunately not a public API, so the best we can do is copy it.
*
* Angular References:
* https://github.com/angular/angular.js/issues/3299
* https://github.com/angular/angular.js/blob/d077966ff1ac18262f4615ff1a533db24d4432a7/src/ng/urlUtils.js
*/
angular.module('angular-jwt.interceptor')
.service('urlUtils', function () {
// NOTE: The usage of window and document instead of $window and $document here is
// deliberate. This service depends on the specific behavior of anchor nodes created by the
// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and
// cause us to break tests. In addition, when the browser resolves a URL for XHR, it
// doesn't know about mocked locations and resolves URLs to the real document - which is
// exactly the behavior needed here. There is little value is mocking these out for this
// service.
var urlParsingNode = document.createElement("a");
var originUrl = urlResolve(window.location.href);
/**
*
* Implementation Notes for non-IE browsers
* ----------------------------------------
* Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,
* results both in the normalizing and parsing of the URL. Normalizing means that a relative
* URL will be resolved into an absolute URL in the context of the application document.
* Parsing means that the anchor node's host, hostname, protocol, port, pathname and related
* properties are all populated to reflect the normalized URL. This approach has wide
* compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See
* http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
*
* Implementation Notes for IE
* ---------------------------
* IE <= 10 normalizes the URL when assigned to the anchor node similar to the other
* browsers. However, the parsed components will not be set if the URL assigned did not specify
* them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We
* work around that by performing the parsing in a 2nd step by taking a previously normalized
* URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the
* properties such as protocol, hostname, port, etc.
*
* References:
* http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
* http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
* http://url.spec.whatwg.org/#urlutils
* https://github.com/angular/angular.js/pull/2902
* http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
*
* @kind function
* @param {string} url The URL to be parsed.
* @description Normalizes and parses a URL.
* @returns {object} Returns the normalized URL as a dictionary.
*
* | member name | Description |
* |---------------|----------------|
* | href | A normalized version of the provided URL if it was not an absolute URL |
* | protocol | The protocol including the trailing colon |
* | host | The host and port (if the port is non-default) of the normalizedUrl |
* | search | The search params, minus the question mark |
* | hash | The hash string, minus the hash symbol
* | hostname | The hostname
* | port | The port, without ":"
* | pathname | The pathname, beginning with "/"
*
*/
function urlResolve(url) {
var href = url;
// Normalize before parse. Refer Implementation Notes on why this is
// done in two steps on IE.
urlParsingNode.setAttribute("href", href);
href = urlParsingNode.href;
urlParsingNode.setAttribute('href', href);
// urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
return {
href: urlParsingNode.href,
protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
host: urlParsingNode.host,
search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
hostname: urlParsingNode.hostname,
port: urlParsingNode.port,
pathname: (urlParsingNode.pathname.charAt(0) === '/')
? urlParsingNode.pathname
: '/' + urlParsingNode.pathname
};
}
/**
* Parse a request URL and determine whether this is a same-origin request as the application document.
*
* @param {string|object} requestUrl The url of the request as a string that will be resolved
* or a parsed URL object.
* @returns {boolean} Whether the request is for the same origin as the application document.
*/
function urlIsSameOrigin(requestUrl) {
var parsed = (angular.isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;
return (parsed.protocol === originUrl.protocol &&
parsed.host === originUrl.host);
}
return {
urlResolve: urlResolve,
isSameOrigin: urlIsSameOrigin
};
});
}());
/**
* auth0-js v9.7.3
* Author: Auth0
* Date: 2018-07-23
* License: MIT
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.auth0 = {})));
}(this, (function (exports) { 'use strict';
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var urlJoin = createCommonjsModule(function (module) {
(function (name, context, definition) {
if (module.exports) module.exports = definition();
else if (typeof undefined === 'function' && undefined.amd) undefined(definition);
else context[name] = definition();
})('urljoin', commonjsGlobal, function () {
function normalize (str, options) {
// make sure protocol is followed by two slashes
str = str.replace(/:\//g, '://');
// remove consecutive slashes
str = str.replace(/([^:\s])\/+/g, '$1/');
// remove trailing slash before parameters or hash
str = str.replace(/\/(\?|&|#[^!])/g, '$1');
// replace ? in parameters with &
str = str.replace(/(\?.+)\?/g, '$1&');
return str;
}
return function () {
var input = arguments;
var options = {};
if (typeof arguments[0] === 'object') {
// new syntax with array and options
input = arguments[0];
options = arguments[1] || {};
}
var joined = [].slice.call(input, 0).join('/');
return normalize(joined, options);
};
});
});
var utils = createCommonjsModule(function (module, exports) {
var has = Object.prototype.hasOwnProperty;
var hexTable = (function () {
var array = [];
for (var i = 0; i < 256; ++i) {
array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase());
}
return array;
}());
exports.arrayToObject = function (source, options) {
var obj = options && options.plainObjects ? Object.create(null) : {};
for (var i = 0; i < source.length; ++i) {
if (typeof source[i] !== 'undefined') {
obj[i] = source[i];
}
}
return obj;
};
exports.merge = function (target, source, options) {
if (!source) {
return target;
}
if (typeof source !== 'object') {
if (Array.isArray(target)) {
target.push(source);
} else if (typeof target === 'object') {
if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) {
target[source] = true;
}
} else {
return [target, source];
}
return target;
}
if (typeof target !== 'object') {
return [target].concat(source);
}
var mergeTarget = target;
if (Array.isArray(target) && !Array.isArray(source)) {
mergeTarget = exports.arrayToObject(target, options);
}
if (Array.isArray(target) && Array.isArray(source)) {
source.forEach(function (item, i) {
if (has.call(target, i)) {
if (target[i] && typeof target[i] === 'object') {
target[i] = exports.merge(target[i], item, options);
} else {
target.push(item);
}
} else {
target[i] = item;
}
});
return target;
}
return Object.keys(source).reduce(function (acc, key) {
var value = source[key];
if (Object.prototype.hasOwnProperty.call(acc, key)) {
acc[key] = exports.merge(acc[key], value, options);
} else {
acc[key] = value;
}
return acc;
}, mergeTarget);
};
exports.decode = function (str) {
try {
return decodeURIComponent(str.replace(/\+/g, ' '));
} catch (e) {
return str;
}
};
exports.encode = function (str) {
// This code was originally written by Brian White (mscdex) for the io.js core querystring library.
// It has been adapted here for stricter adherence to RFC 3986
if (str.length === 0) {
return str;
}
var string = typeof str === 'string' ? str : String(str);
var out = '';
for (var i = 0; i < string.length; ++i) {
var c = string.charCodeAt(i);
if (
c === 0x2D || // -
c === 0x2E || // .
c === 0x5F || // _
c === 0x7E || // ~
(c >= 0x30 && c <= 0x39) || // 0-9
(c >= 0x41 && c <= 0x5A) || // a-z
(c >= 0x61 && c <= 0x7A) // A-Z
) {
out += string.charAt(i);
continue;
}
if (c < 0x80) {
out = out + hexTable[c];
continue;
}
if (c < 0x800) {
out = out + (hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)]);
continue;
}
if (c < 0xD800 || c >= 0xE000) {
out = out + (hexTable[0xE0 | (c >> 12)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]);
continue;
}
i += 1;
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
out += hexTable[0xF0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3F)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]; // eslint-disable-line max-len
}
return out;
};
exports.compact = function (obj, references) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
var refs = references || [];
var lookup = refs.indexOf(obj);
if (lookup !== -1) {
return refs[lookup];
}
refs.push(obj);
if (Array.isArray(obj)) {
var compacted = [];
for (var i = 0; i < obj.length; ++i) {
if (obj[i] && typeof obj[i] === 'object') {
compacted.push(exports.compact(obj[i], refs));
} else if (typeof obj[i] !== 'undefined') {
compacted.push(obj[i]);
}
}
return compacted;
}
var keys = Object.keys(obj);
keys.forEach(function (key) {
obj[key] = exports.compact(obj[key], refs);
});
return obj;
};
exports.isRegExp = function (obj) {
return Object.prototype.toString.call(obj) === '[object RegExp]';
};
exports.isBuffer = function (obj) {
if (obj === null || typeof obj === 'undefined') {
return false;
}
return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
};
});
var utils_1 = utils.arrayToObject;
var utils_2 = utils.merge;
var utils_3 = utils.decode;
var utils_4 = utils.encode;
var utils_5 = utils.compact;
var utils_6 = utils.isRegExp;
var utils_7 = utils.isBuffer;
var replace = String.prototype.replace;
var percentTwenties = /%20/g;
var formats = {
'default': 'RFC3986',
formatters: {
RFC1738: function (value) {
return replace.call(value, percentTwenties, '+');
},
RFC3986: function (value) {
return value;
}
},
RFC1738: 'RFC1738',
RFC3986: 'RFC3986'
};
var arrayPrefixGenerators = {
brackets: function brackets(prefix) { // eslint-disable-line func-name-matching
return prefix + '[]';
},
indices: function indices(prefix, key) { // eslint-disable-line func-name-matching
return prefix + '[' + key + ']';
},
repeat: function repeat(prefix) { // eslint-disable-line func-name-matching
return prefix;
}
};
var toISO = Date.prototype.toISOString;
var defaults = {
delimiter: '&',
encode: true,
encoder: utils.encode,
encodeValuesOnly: false,
serializeDate: function serializeDate(date) { // eslint-disable-line func-name-matching
return toISO.call(date);
},
skipNulls: false,
strictNullHandling: false
};
var stringify = function stringify( // eslint-disable-line func-name-matching
object,
prefix,
generateArrayPrefix,
strictNullHandling,
skipNulls,
encoder,
filter,
sort,
allowDots,
serializeDate,
formatter,
encodeValuesOnly
) {
var obj = object;
if (typeof filter === 'function') {
obj = filter(prefix, obj);
} else if (obj instanceof Date) {
obj = serializeDate(obj);
} else if (obj === null) {
if (strictNullHandling) {
return encoder && !encodeValuesOnly ? encoder(prefix) : prefix;
}
obj = '';
}
if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || utils.isBuffer(obj)) {
if (encoder) {
var keyValue = encodeValuesOnly ? prefix : encoder(prefix);
return [formatter(keyValue) + '=' + formatter(encoder(obj))];
}
return [formatter(prefix) + '=' + formatter(String(obj))];
}
var values = [];
if (typeof obj === 'undefined') {
return values;
}
var objKeys;
if (Array.isArray(filter)) {
objKeys = filter;
} else {
var keys = Object.keys(obj);
objKeys = sort ? keys.sort(sort) : keys;
}
for (var i = 0; i < objKeys.length; ++i) {
var key = objKeys[i];
if (skipNulls && obj[key] === null) {
continue;
}
if (Array.isArray(obj)) {
values = values.concat(stringify(
obj[key],
generateArrayPrefix(prefix, key),
generateArrayPrefix,
strictNullHandling,
skipNulls,
encoder,
filter,
sort,
allowDots,
serializeDate,
formatter,
encodeValuesOnly
));
} else {
values = values.concat(stringify(
obj[key],
prefix + (allowDots ? '.' + key : '[' + key + ']'),
generateArrayPrefix,
strictNullHandling,
skipNulls,
encoder,
filter,
sort,
allowDots,
serializeDate,
formatter,
encodeValuesOnly
));
}
}
return values;
};
var stringify_1 = function (object, opts) {
var obj = object;
var options = opts || {};
if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') {
throw new TypeError('Encoder has to be a function.');
}
var delimiter = typeof options.delimiter === 'undefined' ? defaults.delimiter : options.delimiter;
var strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults.strictNullHandling;
var skipNulls = typeof options.skipNulls === 'boolean' ? options.skipNulls : defaults.skipNulls;
var encode = typeof options.encode === 'boolean' ? options.encode : defaults.encode;
var encoder = typeof options.encoder === 'function' ? options.encoder : defaults.encoder;
var sort = typeof options.sort === 'function' ? options.sort : null;
var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots;
var serializeDate = typeof options.serializeDate === 'function' ? options.serializeDate : defaults.serializeDate;
var encodeValuesOnly = typeof options.encodeValuesOnly === 'boolean' ? options.encodeValuesOnly : defaults.encodeValuesOnly;
if (typeof options.format === 'undefined') {
options.format = formats.default;
} else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) {
throw new TypeError('Unknown format option provided.');
}
var formatter = formats.formatters[options.format];
var objKeys;
var filter;
if (typeof options.filter === 'function') {
filter = options.filter;
obj = filter('', obj);
} else if (Array.isArray(options.filter)) {
filter = options.filter;
objKeys = filter;
}
var keys = [];
if (typeof obj !== 'object' || obj === null) {
return '';
}
var arrayFormat;
if (options.arrayFormat in arrayPrefixGenerators) {
arrayFormat = options.arrayFormat;
} else if ('indices' in options) {
arrayFormat = options.indices ? 'indices' : 'repeat';
} else {
arrayFormat = 'indices';
}
var generateArrayPrefix = arrayPrefixGenerators[arrayFormat];
if (!objKeys) {
objKeys = Object.keys(obj);
}
if (sort) {
objKeys.sort(sort);
}
for (var i = 0; i < objKeys.length; ++i) {
var key = objKeys[i];
if (skipNulls && obj[key] === null) {
continue;
}
keys = keys.concat(stringify(
obj[key],
key,
generateArrayPrefix,
strictNullHandling,
skipNulls,
encode ? encoder : null,
filter,
sort,
allowDots,
serializeDate,
formatter,
encodeValuesOnly
));
}
return keys.join(delimiter);
};
var has = Object.prototype.hasOwnProperty;
var defaults$1 = {
allowDots: false,
allowPrototypes: false,
arrayLimit: 20,
decoder: utils.decode,
delimiter: '&',
depth: 5,
parameterLimit: 1000,
plainObjects: false,
strictNullHandling: false
};
var parseValues = function parseQueryStringValues(str, options) {
var obj = {};
var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
for (var i = 0; i < parts.length; ++i) {
var part = parts[i];
var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1;
var key, val;
if (pos === -1) {
key = options.decoder(part);
val = options.strictNullHandling ? null : '';
} else {
key = options.decoder(part.slice(0, pos));
val = options.decoder(part.slice(pos + 1));
}
if (has.call(obj, key)) {
obj[key] = [].concat(obj[key]).concat(val);
} else {
obj[key] = val;
}
}
return obj;
};
var parseObject = function parseObjectRecursive(chain, val, options) {
if (!chain.length) {
return val;
}
var root = chain.shift();
var obj;
if (root === '[]') {
obj = [];
obj = obj.concat(parseObject(chain, val, options));
} else {
obj = options.plainObjects ? Object.create(null) : {};
var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
var index = parseInt(cleanRoot, 10);
if (
!isNaN(index) &&
root !== cleanRoot &&
String(index) === cleanRoot &&
index >= 0 &&
(options.parseArrays && index <= options.arrayLimit)
) {
obj = [];
obj[index] = parseObject(chain, val, options);
} else {
obj[cleanRoot] = parseObject(chain, val, options);
}
}
return obj;
};
var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
if (!givenKey) {
return;
}
// Transform dot notation to bracket notation
var key = options.allowDots ? givenKey.replace(/\.([^.[]+)/g, '[$1]') : givenKey;
// The regex chunks
var brackets = /(\[[^[\]]*])/;
var child = /(\[[^[\]]*])/g;
// Get the parent
var segment = brackets.exec(key);
var parent = segment ? key.slice(0, segment.index) : key;
// Stash the parent if it exists
var keys = [];
if (parent) {
// If we aren't using plain objects, optionally prefix keys
// that would overwrite object prototype properties
if (!options.plainObjects && has.call(Object.prototype, parent)) {
if (!options.allowPrototypes) {
return;
}
}
keys.push(parent);
}
// Loop through children appending to the array until we hit depth
var i = 0;
while ((segment = child.exec(key)) !== null && i < options.depth) {
i += 1;
if (!options.plainObjects && has.call(Object.prototype, segment[1].slice(1, -1))) {
if (!options.allowPrototypes) {
return;
}
}
keys.push(segment[1]);
}
// If there's a remainder, just add whatever is left
if (segment) {
keys.push('[' + key.slice(segment.index) + ']');
}
return parseObject(keys, val, options);
};
var parse = function (str, opts) {
var options = opts || {};
if (options.decoder !== null && options.decoder !== undefined && typeof options.decoder !== 'function') {
throw new TypeError('Decoder has to be a function.');
}
options.delimiter = typeof options.delimiter === 'string' || utils.isRegExp(options.delimiter) ? options.delimiter : defaults$1.delimiter;
options.depth = typeof options.depth === 'number' ? options.depth : defaults$1.depth;
options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : defaults$1.arrayLimit;
options.parseArrays = options.parseArrays !== false;
options.decoder = typeof options.decoder === 'function' ? options.decoder : defaults$1.decoder;
options.allowDots = typeof options.allowDots === 'boolean' ? options.allowDots : defaults$1.allowDots;
options.plainObjects = typeof options.plainObjects === 'boolean' ? options.plainObjects : defaults$1.plainObjects;
options.allowPrototypes = typeof options.allowPrototypes === 'boolean' ? options.allowPrototypes : defaults$1.allowPrototypes;
options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : defaults$1.parameterLimit;
options.strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults$1.strictNullHandling;
if (str === '' || str === null || typeof str === 'undefined') {
return options.plainObjects ? Object.create(null) : {};
}
var tempObj = typeof str === 'string' ? parseValues(str, options) : str;
var obj = options.plainObjects ? Object.create(null) : {};
// Iterate over the keys and setup the new object
var keys = Object.keys(tempObj);
for (var i = 0; i < keys.length; ++i) {
var key = keys[i];
var newObj = parseKeys(key, tempObj[key], options);
obj = utils.merge(obj, newObj, options);
}
return utils.compact(obj);
};
var lib = {
formats: formats,
parse: parse,
stringify: stringify_1
};
var componentEmitter = createCommonjsModule(function (module) {
/**
* 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){
function on() {
this.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;
};
});
/**
* Check if `obj` is an object.
*
* @param {Object} obj
* @return {Boolean}
* @api private
*/
function isObject(obj) {
return null !== obj && 'object' === typeof obj;
}
var isObject_1 = isObject;
/**
* Module of mixed-in functions shared between node and client code
*/
/**
* Expose `RequestBase`.
*/
var requestBase = RequestBase;
/**
* Initialize a new `RequestBase`.
*
* @api public
*/
function RequestBase(obj) {
if (obj) return mixin(obj);
}
/**
* Mixin the prototype properties.
*
* @param {Object} obj
* @return {Object}
* @api private
*/
function mixin(obj) {
for (var key in RequestBase.prototype) {
obj[key] = RequestBase.prototype[key];
}
return obj;
}
/**
* Clear previous timeout.
*
* @return {Request} for chaining
* @api public
*/
RequestBase.prototype.clearTimeout = function _clearTimeout(){
clearTimeout(this._timer);
clearTimeout(this._responseTimeoutTimer);
delete this._timer;
delete this._responseTimeoutTimer;
return this;
};
/**
* Override default response body parser
*
* This function will be called to convert incoming data into request.body
*
* @param {Function}
* @api public
*/
RequestBase.prototype.parse = function parse(fn){
this._parser = fn;
return this;
};
/**
* Set format of binary response body.
* In browser valid formats are 'blob' and 'arraybuffer',
* which return Blob and ArrayBuffer, respectively.
*
* In Node all values result in Buffer.
*
* Examples:
*
* req.get('/')
* .responseType('blob')
* .end(callback);
*
* @param {String} val
* @return {Request} for chaining
* @api public
*/
RequestBase.prototype.responseType = function(val){
this._responseType = val;
return this;
};
/**
* Override default request body serializer
*
* This function will be called to convert data set via .send or .attach into payload to send
*
* @param {Function}
* @api public
*/
RequestBase.prototype.serialize = function serialize(fn){
this._serializer = fn;
return this;
};
/**
* Set timeouts.
*
* - response timeout is time between sending request and receiving the first byte of the response. Includes DNS and connection time.
* - deadline is the time from start of the request to receiving response body in full. If the deadline is too short large files may not load at all on slow connections.
*
* Value of 0 or false means no timeout.
*
* @param {Number|Object} ms or {response, deadline}
* @return {Request} for chaining
* @api public
*/
RequestBase.prototype.timeout = function timeout(options){
if (!options || 'object' !== typeof options) {
this._timeout = options;
this._responseTimeout = 0;
return this;
}
for(var option in options) {
switch(option) {
case 'deadline':
this._timeout = options.deadline;
break;
case 'response':
this._responseTimeout = options.response;
break;
default:
console.warn("Unknown timeout option", option);
}
}
return this;
};
/**
* Set number of retry attempts on error.
*
* Failed requests will be retried 'count' times if timeout or err.code >= 500.
*
* @param {Number} count
* @param {Function} [fn]
* @return {Request} for chaining
* @api public
*/
RequestBase.prototype.retry = function retry(count, fn){
// Default to 1 if no count passed or true
if (arguments.length === 0 || count === true) count = 1;
if (count <= 0) count = 0;
this._maxRetries = count;
this._retries = 0;
this._retryCallback = fn;
return this;
};
var ERROR_CODES = [
'ECONNRESET',
'ETIMEDOUT',
'EADDRINFO',
'ESOCKETTIMEDOUT'
];
/**
* Determine if a request should be retried.
* (Borrowed from segmentio/superagent-retry)
*
* @param {Error} err
* @param {Response} [res]
* @returns {Boolean}
*/
RequestBase.prototype._shouldRetry = function(err, res) {
if (!this._maxRetries || this._retries++ >= this._maxRetries) {
return false;
}
if (this._retryCallback) {
try {
var override = this._retryCallback(err, res);
if (override === true) return true;
if (override === false) return false;
// undefined falls back to defaults
} catch(e) {
console.error(e);
}
}
if (res && res.status && res.status >= 500 && res.status != 501) return true;
if (err) {
if (err.code && ~ERROR_CODES.indexOf(err.code)) return true;
// Superagent timeout
if (err.timeout && err.code == 'ECONNABORTED') return true;
if (err.crossDomain) return true;
}
return false;
};
/**
* Retry request
*
* @return {Request} for chaining
* @api private
*/
RequestBase.prototype._retry = function() {
this.clearTimeout();
// node
if (this.req) {
this.req = null;
this.req = this.request();
}
this._aborted = false;
this.timedout = false;
return this._end();
};
/**
* Promise support
*
* @param {Function} resolve
* @param {Function} [reject]
* @return {Request}
*/
RequestBase.prototype.then = function then(resolve, reject) {
if (!this._fullfilledPromise) {
var self = this;
if (this._endCalled) {
console.warn("Warning: superagent request was sent twice, because both .end() and .then() were called. Never call .end() if you use promises");
}
this._fullfilledPromise = new Promise(function(innerResolve, innerReject) {
self.end(function(err, res) {
if (err) innerReject(err);
else innerResolve(res);
});
});
}
return this._fullfilledPromise.then(resolve, reject);
};
RequestBase.prototype.catch = function(cb) {
return this.then(undefined, cb);
};
/**
* Allow for extension
*/
RequestBase.prototype.use = function use(fn) {
fn(this);
return this;
};
RequestBase.prototype.ok = function(cb) {
if ('function' !== typeof cb) throw Error("Callback required");
this._okCallback = cb;
return this;
};
RequestBase.prototype._isResponseOK = function(res) {
if (!res) {
return false;
}
if (this._okCallback) {
return this._okCallback(res);
}
return res.status >= 200 && res.status < 300;
};
/**
* Get request header `field`.
* Case-insensitive.
*
* @param {String} field
* @return {String}
* @api public
*/
RequestBase.prototype.get = function(field){
return this._header[field.toLowerCase()];
};
/**
* Get case-insensitive header `field` value.
* This is a deprecated internal API. Use `.get(field)` instead.
*
* (getHeader is no longer used internally by the superagent code base)
*
* @param {String} field
* @return {String}
* @api private
* @deprecated
*/
RequestBase.prototype.getHeader = RequestBase.prototype.get;
/**
* Set header `field` to `val`, or multiple fields with one object.
* Case-insensitive.
*
* 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
*/
RequestBase.prototype.set = function(field, val){
if (isObject_1(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`.
* Case-insensitive.
*
* Example:
*
* req.get('/')
* .unset('User-Agent')
* .end(callback);
*
* @param {String} field
*/
RequestBase.prototype.unset = function(field){
delete this._header[field.toLowerCase()];
delete this.header[field];
return this;
};
/**
* Write the field `name` and `val`, or multiple fields with one object
* for "multipart/form-data" request bodies.
*
* ``` js
* request.post('/upload')
* .field('foo', 'bar')
* .end(callback);
*
* request.post('/upload')
* .field({ foo: 'bar', baz: 'qux' })
* .end(callback);
* ```
*
* @param {String|Object} name
* @param {String|Blob|File|Buffer|fs.ReadStream} val
* @return {Request} for chaining
* @api public
*/
RequestBase.prototype.field = function(name, val) {
// name should be either a string or an object.
if (null === name || undefined === name) {
throw new Error('.field(name, val) name can not be empty');
}
if (this._data) {
console.error(".field() can't be used if .send() is used. Please use only .send() or only .field() & .attach()");
}
if (isObject_1(name)) {
for (var key in name) {
this.field(key, name[key]);
}
return this;
}
if (Array.isArray(val)) {
for (var i in val) {
this.field(name, val[i]);
}
return this;
}
// val should be defined now
if (null === val || undefined === val) {
throw new Error('.field(name, val) val can not be empty');
}
if ('boolean' === typeof val) {
val = '' + val;
}
this._getFormData().append(name, val);
return this;
};
/**
* Abort the request, and clear potential timeout.
*
* @return {Request}
* @api public
*/
RequestBase.prototype.abort = function(){
if (this._aborted) {
return this;
}
this._aborted = true;
this.xhr && this.xhr.abort(); // browser
this.req && this.req.abort(); // node
this.clearTimeout();
this.emit('abort');
return this;
};
RequestBase.prototype._auth = function(user, pass, options, base64Encoder) {
switch (options.type) {
case 'basic':
this.set('Authorization', 'Basic ' + base64Encoder(user + ':' + pass));
break;
case 'auto':
this.username = user;
this.password = pass;
break;
case 'bearer': // usage would be .auth(accessToken, { type: 'bearer' })
this.set('Authorization', 'Bearer ' + user);
break;
}
return this;
};
/**
* 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
*/
RequestBase.prototype.withCredentials = function(on) {
// This is browser-only functionality. Node side is no-op.
if (on == undefined) on = true;
this._withCredentials = on;
return this;
};
/**
* Set the max redirects to `n`. Does noting in browser XHR implementation.
*
* @param {Number} n
* @return {Request} for chaining
* @api public
*/
RequestBase.prototype.redirects = function(n){
this._maxRedirects = n;
return this;
};
/**
* Maximum size of buffered response body, in bytes. Counts uncompressed size.
* Default 200MB.
*
* @param {Number} n
* @return {Request} for chaining
*/
RequestBase.prototype.maxResponseSize = function(n){
if ('number' !== typeof n) {
throw TypeError("Invalid argument");
}
this._maxResponseSize = n;
return this;
};
/**
* Convert to a plain javascript object (not JSON string) of scalar properties.
* Note as this method is designed to return a useful non-this value,
* it cannot be chained.
*
* @return {Object} describing method, url, and data of this request
* @api public
*/
RequestBase.prototype.toJSON = function() {
return {
method: this.method,
url: this.url,
data: this._data,
headers: this._header,
};
};
/**
* Send `data` as the request body, defaulting the `.type()` to "json" when
* an object is given.
*
* Examples:
*
* // 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
*/
RequestBase.prototype.send = function(data){
var isObj = isObject_1(data);
var type = this._header['content-type'];
if (this._formData) {
console.error(".send() can't be used if .attach() or .field() is used. Please use only .send() or only .field() & .attach()");
}
if (isObj && !this._data) {
if (Array