verdaccio
Version:
A lightweight private npm proxy registry
354 lines (338 loc) • 34.7 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ErrorCode = void 0;
exports.addScope = addScope;
Object.defineProperty(exports, "buildToken", {
enumerable: true,
get: function () {
return _utils.buildToken;
}
});
exports.deleteProperties = deleteProperties;
exports.encodeScopedUri = encodeScopedUri;
exports.fileExists = fileExists;
exports.folderExists = folderExists;
exports.getVersion = getVersion;
exports.hasDiffOneKey = hasDiffOneKey;
exports.hasLogin = hasLogin;
exports.isObject = void 0;
exports.isObjectOrArray = isObjectOrArray;
exports.isRelatedToDeprecation = isRelatedToDeprecation;
exports.isVersionValid = isVersionValid;
exports.mask = mask;
exports.normalizeDistTags = normalizeDistTags;
exports.parseAddress = parseAddress;
Object.defineProperty(exports, "parseConfigFile", {
enumerable: true,
get: function () {
return _config.parseConfigFile;
}
});
exports.parseInterval = parseInterval;
exports.parseReadme = parseReadme;
exports.semverSort = semverSort;
exports.sortByName = sortByName;
exports.tagVersion = tagVersion;
var _fs = _interopRequireDefault(require("fs"));
var _lodash = _interopRequireDefault(require("lodash"));
var _semver = _interopRequireDefault(require("semver"));
var _config = require("@verdaccio/config");
var _core = require("@verdaccio/core");
var _utils = require("@verdaccio/utils");
var _constants = require("./constants");
var _logger = require("./logger");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// eslint-disable-next-line max-len
const {
getBadData,
getBadRequest,
getCode,
getConflict,
getForbidden,
getInternalError,
getNotFound,
getServiceUnavailable,
getUnauthorized
} = _core.errorUtils;
/**
* Check whether an element is an Object
* @param {*} obj the element
* @return {Boolean}
*/
const isObject = exports.isObject = _core.validationUtils.isObject;
/**
* @deprecated not used un v6
*/
function isObjectOrArray(obj) {
return _lodash.default.isObject(obj) && _lodash.default.isNull(obj) === false;
}
function tagVersion(data, version, tag) {
if (tag && data[_constants.DIST_TAGS][tag] !== version && _semver.default.parse(version, true)) {
// valid version - store
data[_constants.DIST_TAGS][tag] = version;
return true;
}
return false;
}
/**
* Gets version from a package object taking into account semver weirdness.
* @return {String} return the semantic version of a package
*/
function getVersion(pkg, version) {
// this condition must allow cast
if (_lodash.default.isNil(pkg.versions[version]) === false) {
return pkg.versions[version];
}
try {
version = _semver.default.parse(version, true);
for (const versionItem in pkg.versions) {
if (version.compare(_semver.default.parse(versionItem, true)) === 0) {
return pkg.versions[versionItem];
}
}
} catch (err) {
return undefined;
}
}
/**
* Parse an internet address
* Allow:
- https:localhost:1234 - protocol + host + port
- localhost:1234 - host + port
- 1234 - port
- http::1234 - protocol + port
- https://localhost:443/ - full url + https
- http://[::1]:443/ - ipv6
- unix:/tmp/http.sock - unix sockets
- https://unix:/tmp/http.sock - unix sockets (https)
* @param {*} urlAddress the internet address definition
* @return {Object|Null} literal object that represent the address parsed
*/
function parseAddress(urlAddress) {
//
// TODO: refactor it to something more reasonable?
//
// protocol : // ( host )|( ipv6 ): port /
let urlPattern = /^((https?):(\/\/)?)?((([^\/:]*)|\[([^\[\]]+)\]):)?(\d+)\/?$/.exec(urlAddress);
if (urlPattern) {
return {
proto: urlPattern[2] || _constants.DEFAULT_PROTOCOL,
host: urlPattern[6] || urlPattern[7] || _constants.DEFAULT_DOMAIN,
port: urlPattern[8] || _constants.DEFAULT_PORT
};
}
urlPattern = /^((https?):(\/\/)?)?unix:(.*)$/.exec(urlAddress);
if (urlPattern) {
return {
proto: urlPattern[2] || _constants.DEFAULT_PROTOCOL,
path: urlPattern[4]
};
}
return null;
}
/**
* Function filters out bad semver versions and sorts the array.
* @return {Array} sorted Array
*/
function semverSort(listVersions) {
return listVersions.filter(function (x) {
if (!_semver.default.parse(x, true)) {
_logger.logger.warn({
ver: x
}, 'ignoring bad version @{ver}');
return false;
}
return true;
})
// FIXME: it seems the @types/semver do not handle a legitimate method named 'compareLoose'
// @ts-ignore
.sort(_semver.default.compareLoose).map(String);
}
/**
* Flatten arrays of tags.
* @param {*} data
*/
function normalizeDistTags(pkg) {
let sorted;
if (!pkg[_constants.DIST_TAGS].latest) {
// overwrite latest with highest known version based on semver sort
sorted = semverSort(Object.keys(pkg.versions));
if (sorted && sorted.length) {
pkg[_constants.DIST_TAGS].latest = sorted.pop();
}
}
for (const tag in pkg[_constants.DIST_TAGS]) {
if (_lodash.default.isArray(pkg[_constants.DIST_TAGS][tag])) {
if (pkg[_constants.DIST_TAGS][tag].length) {
// sort array
// FIXME: this is clearly wrong, we need to research why this is like this.
// @ts-ignore
sorted = semverSort(pkg[_constants.DIST_TAGS][tag]);
if (sorted.length) {
// use highest version based on semver sort
pkg[_constants.DIST_TAGS][tag] = sorted.pop();
}
} else {
delete pkg[_constants.DIST_TAGS][tag];
}
} else if (_lodash.default.isString(pkg[_constants.DIST_TAGS][tag])) {
if (!_semver.default.parse(pkg[_constants.DIST_TAGS][tag], true)) {
// if the version is invalid, delete the dist-tag entry
delete pkg[_constants.DIST_TAGS][tag];
}
}
}
}
const parseIntervalTable = {
'': 1000,
ms: 1,
s: 1000,
m: 60 * 1000,
h: 60 * 60 * 1000,
d: 86400000,
w: 7 * 86400000,
M: 30 * 86400000,
y: 365 * 86400000
};
/**
* Parse an internal string to number
* @param {*} interval
* @return {Number}
*/
function parseInterval(interval) {
if (typeof interval === 'number') {
return interval * 1000;
}
let result = 0;
let last_suffix = Infinity;
interval.split(/\s+/).forEach(function (x) {
if (!x) {
return;
}
const m = x.match(/^((0|[1-9][0-9]*)(\.[0-9]+)?)(ms|s|m|h|d|w|M|y|)$/);
if (!m || parseIntervalTable[m[4]] >= last_suffix || m[4] === '' && last_suffix !== Infinity) {
throw Error('invalid interval: ' + interval);
}
last_suffix = parseIntervalTable[m[4]];
result += Number(m[1]) * parseIntervalTable[m[4]];
});
return result;
}
const ErrorCode = exports.ErrorCode = {
getConflict,
getBadData,
getBadRequest,
getInternalError,
getUnauthorized,
getForbidden,
getServiceUnavailable,
getNotFound,
getCode
};
/**
* Check whether the path already exist.
* @param {String} path
* @return {Boolean}
*/
function folderExists(path) {
try {
const stat = _fs.default.statSync(path);
return stat.isDirectory();
} catch (_) {
return false;
}
}
/**
* Check whether the file already exist.
* @param {String} path
* @return {Boolean}
*/
function fileExists(path) {
try {
const stat = _fs.default.statSync(path);
return stat.isFile();
} catch (_) {
return false;
}
}
function sortByName(packages, orderAscending = true) {
return packages.slice().sort(function (a, b) {
const comparatorNames = a.name.toLowerCase() < b.name.toLowerCase();
return orderAscending ? comparatorNames ? -1 : 1 : comparatorNames ? 1 : -1;
});
}
function addScope(scope, packageName) {
return `@${scope}/${packageName}`;
}
function deleteProperties(propertiesToDelete, objectItem) {
_lodash.default.forEach(propertiesToDelete, property => {
delete objectItem[property];
});
return objectItem;
}
/**
* parse package readme - markdown/ascii
* @param {String} packageName name of package
* @param {String} readme package readme
* @return {String} converted html template
*/
// TODO: rename, does not parse anymore
function parseReadme(packageName, readme) {
if (_lodash.default.isEmpty(readme) === false) {
return readme;
}
// logs readme not found error
_logger.logger.info({
packageName
}, '@{packageName}: No readme found');
return 'ERROR: No README data found!';
}
/**
* return a masquerade string with its first and last {charNum} and three dots in between.
* @param {String} str
* @param {Number} charNum
* @returns {String}
*/
function mask(str, charNum = 3) {
return `${str.substr(0, charNum)}...${str.substr(-charNum)}`;
}
function encodeScopedUri(packageName) {
return packageName.replace(/\//g, '%2f');
}
function hasDiffOneKey(versions) {
return Object.keys(versions).length !== 1;
}
function isVersionValid(packageMeta, packageVersion) {
const hasVersion = typeof packageVersion !== 'undefined';
if (!hasVersion) {
return false;
}
const hasMatchVersion = Object.keys(packageMeta.versions).includes(packageVersion);
return hasMatchVersion;
}
function isRelatedToDeprecation(pkgInfo) {
const {
versions
} = pkgInfo;
for (const version in versions) {
if (Object.prototype.hasOwnProperty.call(versions[version], 'deprecated')) {
return true;
}
}
return false;
}
/**
*
* @param config
* @deprecated use @verdaccio/middleware
* @returns
*/
function hasLogin(config) {
var _config$web, _config$web2;
// FIXME: types are not yet on the library verdaccio/monorepo
// @ts-ignore
return _lodash.default.isNil(config === null || config === void 0 ? void 0 : (_config$web = config.web) === null || _config$web === void 0 ? void 0 : _config$web.login) || (config === null || config === void 0 ? void 0 : (_config$web2 = config.web) === null || _config$web2 === void 0 ? void 0 : _config$web2.login) === true;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZnMiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9sb2Rhc2giLCJfc2VtdmVyIiwiX2NvbmZpZyIsIl9jb3JlIiwiX3V0aWxzIiwiX2NvbnN0YW50cyIsIl9sb2dnZXIiLCJlIiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJnZXRCYWREYXRhIiwiZ2V0QmFkUmVxdWVzdCIsImdldENvZGUiLCJnZXRDb25mbGljdCIsImdldEZvcmJpZGRlbiIsImdldEludGVybmFsRXJyb3IiLCJnZXROb3RGb3VuZCIsImdldFNlcnZpY2VVbmF2YWlsYWJsZSIsImdldFVuYXV0aG9yaXplZCIsImVycm9yVXRpbHMiLCJpc09iamVjdCIsImV4cG9ydHMiLCJ2YWxpZGF0aW9uVXRpbHMiLCJpc09iamVjdE9yQXJyYXkiLCJvYmoiLCJfIiwiaXNOdWxsIiwidGFnVmVyc2lvbiIsImRhdGEiLCJ2ZXJzaW9uIiwidGFnIiwiRElTVF9UQUdTIiwic2VtdmVyIiwicGFyc2UiLCJnZXRWZXJzaW9uIiwicGtnIiwiaXNOaWwiLCJ2ZXJzaW9ucyIsInZlcnNpb25JdGVtIiwiY29tcGFyZSIsImVyciIsInVuZGVmaW5lZCIsInBhcnNlQWRkcmVzcyIsInVybEFkZHJlc3MiLCJ1cmxQYXR0ZXJuIiwiZXhlYyIsInByb3RvIiwiREVGQVVMVF9QUk9UT0NPTCIsImhvc3QiLCJERUZBVUxUX0RPTUFJTiIsInBvcnQiLCJERUZBVUxUX1BPUlQiLCJwYXRoIiwic2VtdmVyU29ydCIsImxpc3RWZXJzaW9ucyIsImZpbHRlciIsIngiLCJsb2dnZXIiLCJ3YXJuIiwidmVyIiwic29ydCIsImNvbXBhcmVMb29zZSIsIm1hcCIsIlN0cmluZyIsIm5vcm1hbGl6ZURpc3RUYWdzIiwic29ydGVkIiwibGF0ZXN0IiwiT2JqZWN0Iiwia2V5cyIsImxlbmd0aCIsInBvcCIsImlzQXJyYXkiLCJpc1N0cmluZyIsInBhcnNlSW50ZXJ2YWxUYWJsZSIsIm1zIiwicyIsIm0iLCJoIiwiZCIsInciLCJNIiwieSIsInBhcnNlSW50ZXJ2YWwiLCJpbnRlcnZhbCIsInJlc3VsdCIsImxhc3Rfc3VmZml4IiwiSW5maW5pdHkiLCJzcGxpdCIsImZvckVhY2giLCJtYXRjaCIsIkVycm9yIiwiTnVtYmVyIiwiRXJyb3JDb2RlIiwiZm9sZGVyRXhpc3RzIiwic3RhdCIsImZzIiwic3RhdFN5bmMiLCJpc0RpcmVjdG9yeSIsImZpbGVFeGlzdHMiLCJpc0ZpbGUiLCJzb3J0QnlOYW1lIiwicGFja2FnZXMiLCJvcmRlckFzY2VuZGluZyIsInNsaWNlIiwiYSIsImIiLCJjb21wYXJhdG9yTmFtZXMiLCJuYW1lIiwidG9Mb3dlckNhc2UiLCJhZGRTY29wZSIsInNjb3BlIiwicGFja2FnZU5hbWUiLCJkZWxldGVQcm9wZXJ0aWVzIiwicHJvcGVydGllc1RvRGVsZXRlIiwib2JqZWN0SXRlbSIsInByb3BlcnR5IiwicGFyc2VSZWFkbWUiLCJyZWFkbWUiLCJpc0VtcHR5IiwiaW5mbyIsIm1hc2siLCJzdHIiLCJjaGFyTnVtIiwic3Vic3RyIiwiZW5jb2RlU2NvcGVkVXJpIiwicmVwbGFjZSIsImhhc0RpZmZPbmVLZXkiLCJpc1ZlcnNpb25WYWxpZCIsInBhY2thZ2VNZXRhIiwicGFja2FnZVZlcnNpb24iLCJoYXNWZXJzaW9uIiwiaGFzTWF0Y2hWZXJzaW9uIiwiaW5jbHVkZXMiLCJpc1JlbGF0ZWRUb0RlcHJlY2F0aW9uIiwicGtnSW5mbyIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImhhc0xvZ2luIiwiY29uZmlnIiwiX2NvbmZpZyR3ZWIiLCJfY29uZmlnJHdlYjIiLCJ3ZWIiLCJsb2dpbiJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvdXRpbHMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGZzIGZyb20gJ2ZzJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgc2VtdmVyIGZyb20gJ3NlbXZlcic7XG5cbmltcG9ydCB7IHBhcnNlQ29uZmlnRmlsZSB9IGZyb20gJ0B2ZXJkYWNjaW8vY29uZmlnJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBtYXgtbGVuXG5pbXBvcnQgeyBlcnJvclV0aWxzLCB2YWxpZGF0aW9uVXRpbHMgfSBmcm9tICdAdmVyZGFjY2lvL2NvcmUnO1xuaW1wb3J0IHsgU3RyaW5nVmFsdWUgfSBmcm9tICdAdmVyZGFjY2lvL3R5cGVzJztcbmltcG9ydCB7IENvbmZpZywgTWFuaWZlc3QsIFZlcnNpb24gfSBmcm9tICdAdmVyZGFjY2lvL3R5cGVzJztcbmltcG9ydCB7IGJ1aWxkVG9rZW4gYXMgYnVpbGRUb2tlblV0aWwgfSBmcm9tICdAdmVyZGFjY2lvL3V0aWxzJztcblxuaW1wb3J0IHsgREVGQVVMVF9ET01BSU4sIERFRkFVTFRfUE9SVCwgREVGQVVMVF9QUk9UT0NPTCwgRElTVF9UQUdTIH0gZnJvbSAnLi9jb25zdGFudHMnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXInO1xuXG5jb25zdCB7XG4gIGdldEJhZERhdGEsXG4gIGdldEJhZFJlcXVlc3QsXG4gIGdldENvZGUsXG4gIGdldENvbmZsaWN0LFxuICBnZXRGb3JiaWRkZW4sXG4gIGdldEludGVybmFsRXJyb3IsXG4gIGdldE5vdEZvdW5kLFxuICBnZXRTZXJ2aWNlVW5hdmFpbGFibGUsXG4gIGdldFVuYXV0aG9yaXplZCxcbn0gPSBlcnJvclV0aWxzO1xuXG4vKipcbiAqIENoZWNrIHdoZXRoZXIgYW4gZWxlbWVudCBpcyBhbiBPYmplY3RcbiAqIEBwYXJhbSB7Kn0gb2JqIHRoZSBlbGVtZW50XG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICovXG5leHBvcnQgY29uc3QgaXNPYmplY3QgPSB2YWxpZGF0aW9uVXRpbHMuaXNPYmplY3Q7XG5cbi8qKlxuICogQGRlcHJlY2F0ZWQgbm90IHVzZWQgdW4gdjZcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzT2JqZWN0T3JBcnJheShvYmo6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gXy5pc09iamVjdChvYmopICYmIF8uaXNOdWxsKG9iaikgPT09IGZhbHNlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdGFnVmVyc2lvbihkYXRhOiBNYW5pZmVzdCwgdmVyc2lvbjogc3RyaW5nLCB0YWc6IFN0cmluZ1ZhbHVlKTogYm9vbGVhbiB7XG4gIGlmICh0YWcgJiYgZGF0YVtESVNUX1RBR1NdW3RhZ10gIT09IHZlcnNpb24gJiYgc2VtdmVyLnBhcnNlKHZlcnNpb24sIHRydWUpKSB7XG4gICAgLy8gdmFsaWQgdmVyc2lvbiAtIHN0b3JlXG4gICAgZGF0YVtESVNUX1RBR1NdW3RhZ10gPSB2ZXJzaW9uO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBHZXRzIHZlcnNpb24gZnJvbSBhIHBhY2thZ2Ugb2JqZWN0IHRha2luZyBpbnRvIGFjY291bnQgc2VtdmVyIHdlaXJkbmVzcy5cbiAqIEByZXR1cm4ge1N0cmluZ30gcmV0dXJuIHRoZSBzZW1hbnRpYyB2ZXJzaW9uIG9mIGEgcGFja2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VmVyc2lvbihwa2c6IE1hbmlmZXN0LCB2ZXJzaW9uOiBhbnkpOiBWZXJzaW9uIHwgdm9pZCB7XG4gIC8vIHRoaXMgY29uZGl0aW9uIG11c3QgYWxsb3cgY2FzdFxuICBpZiAoXy5pc05pbChwa2cudmVyc2lvbnNbdmVyc2lvbl0pID09PSBmYWxzZSkge1xuICAgIHJldHVybiBwa2cudmVyc2lvbnNbdmVyc2lvbl07XG4gIH1cblxuICB0cnkge1xuICAgIHZlcnNpb24gPSBzZW12ZXIucGFyc2UodmVyc2lvbiwgdHJ1ZSk7XG4gICAgZm9yIChjb25zdCB2ZXJzaW9uSXRlbSBpbiBwa2cudmVyc2lvbnMpIHtcbiAgICAgIGlmICh2ZXJzaW9uLmNvbXBhcmUoc2VtdmVyLnBhcnNlKHZlcnNpb25JdGVtLCB0cnVlKSkgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHBrZy52ZXJzaW9uc1t2ZXJzaW9uSXRlbV07XG4gICAgICB9XG4gICAgfVxuICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuLyoqXG4gKiBQYXJzZSBhbiBpbnRlcm5ldCBhZGRyZXNzXG4gKiBBbGxvdzpcbiAtIGh0dHBzOmxvY2FsaG9zdDoxMjM0ICAgICAgICAtIHByb3RvY29sICsgaG9zdCArIHBvcnRcbiAtIGxvY2FsaG9zdDoxMjM0ICAgICAgICAgICAgICAtIGhvc3QgKyBwb3J0XG4gLSAxMjM0ICAgICAgICAgICAgICAgICAgICAgICAgLSBwb3J0XG4gLSBodHRwOjoxMjM0ICAgICAgICAgICAgICAgICAgLSBwcm90b2NvbCArIHBvcnRcbiAtIGh0dHBzOi8vbG9jYWxob3N0OjQ0My8gICAgICAtIGZ1bGwgdXJsICsgaHR0cHNcbiAtIGh0dHA6Ly9bOjoxXTo0NDMvICAgICAgICAgICAtIGlwdjZcbiAtIHVuaXg6L3RtcC9odHRwLnNvY2sgICAgICAgICAtIHVuaXggc29ja2V0c1xuIC0gaHR0cHM6Ly91bml4Oi90bXAvaHR0cC5zb2NrIC0gdW5peCBzb2NrZXRzIChodHRwcylcbiAqIEBwYXJhbSB7Kn0gdXJsQWRkcmVzcyB0aGUgaW50ZXJuZXQgYWRkcmVzcyBkZWZpbml0aW9uXG4gKiBAcmV0dXJuIHtPYmplY3R8TnVsbH0gbGl0ZXJhbCBvYmplY3QgdGhhdCByZXByZXNlbnQgdGhlIGFkZHJlc3MgcGFyc2VkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUFkZHJlc3ModXJsQWRkcmVzczogYW55KTogYW55IHtcbiAgLy9cbiAgLy8gVE9ETzogcmVmYWN0b3IgaXQgdG8gc29tZXRoaW5nIG1vcmUgcmVhc29uYWJsZT9cbiAgLy9cbiAgLy8gICAgICAgIHByb3RvY29sIDogIC8vICAgICAgKCAgaG9zdCAgKXwoICAgIGlwdjYgICAgICk6ICBwb3J0ICAvXG4gIGxldCB1cmxQYXR0ZXJuID0gL14oKGh0dHBzPyk6KFxcL1xcLyk/KT8oKChbXlxcLzpdKil8XFxbKFteXFxbXFxdXSspXFxdKTopPyhcXGQrKVxcLz8kLy5leGVjKHVybEFkZHJlc3MpO1xuXG4gIGlmICh1cmxQYXR0ZXJuKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHByb3RvOiB1cmxQYXR0ZXJuWzJdIHx8IERFRkFVTFRfUFJPVE9DT0wsXG4gICAgICBob3N0OiB1cmxQYXR0ZXJuWzZdIHx8IHVybFBhdHRlcm5bN10gfHwgREVGQVVMVF9ET01BSU4sXG4gICAgICBwb3J0OiB1cmxQYXR0ZXJuWzhdIHx8IERFRkFVTFRfUE9SVCxcbiAgICB9O1xuICB9XG5cbiAgdXJsUGF0dGVybiA9IC9eKChodHRwcz8pOihcXC9cXC8pPyk/dW5peDooLiopJC8uZXhlYyh1cmxBZGRyZXNzKTtcblxuICBpZiAodXJsUGF0dGVybikge1xuICAgIHJldHVybiB7XG4gICAgICBwcm90bzogdXJsUGF0dGVyblsyXSB8fCBERUZBVUxUX1BST1RPQ09MLFxuICAgICAgcGF0aDogdXJsUGF0dGVybls0XSxcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogRnVuY3Rpb24gZmlsdGVycyBvdXQgYmFkIHNlbXZlciB2ZXJzaW9ucyBhbmQgc29ydHMgdGhlIGFycmF5LlxuICogQHJldHVybiB7QXJyYXl9IHNvcnRlZCBBcnJheVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VtdmVyU29ydChsaXN0VmVyc2lvbnM6IHN0cmluZ1tdKTogc3RyaW5nW10ge1xuICByZXR1cm4gKFxuICAgIGxpc3RWZXJzaW9uc1xuICAgICAgLmZpbHRlcihmdW5jdGlvbiAoeCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoIXNlbXZlci5wYXJzZSh4LCB0cnVlKSkge1xuICAgICAgICAgIGxvZ2dlci53YXJuKHsgdmVyOiB4IH0sICdpZ25vcmluZyBiYWQgdmVyc2lvbiBAe3Zlcn0nKTtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9KVxuICAgICAgLy8gRklYTUU6IGl0IHNlZW1zIHRoZSBAdHlwZXMvc2VtdmVyIGRvIG5vdCBoYW5kbGUgYSBsZWdpdGltYXRlIG1ldGhvZCBuYW1lZCAnY29tcGFyZUxvb3NlJ1xuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgLnNvcnQoc2VtdmVyLmNvbXBhcmVMb29zZSlcbiAgICAgIC5tYXAoU3RyaW5nKVxuICApO1xufVxuXG4vKipcbiAqIEZsYXR0ZW4gYXJyYXlzIG9mIHRhZ3MuXG4gKiBAcGFyYW0geyp9IGRhdGFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5vcm1hbGl6ZURpc3RUYWdzKHBrZzogTWFuaWZlc3QpOiB2b2lkIHtcbiAgbGV0IHNvcnRlZDtcbiAgaWYgKCFwa2dbRElTVF9UQUdTXS5sYXRlc3QpIHtcbiAgICAvLyBvdmVyd3JpdGUgbGF0ZXN0IHdpdGggaGlnaGVzdCBrbm93biB2ZXJzaW9uIGJhc2VkIG9uIHNlbXZlciBzb3J0XG4gICAgc29ydGVkID0gc2VtdmVyU29ydChPYmplY3Qua2V5cyhwa2cudmVyc2lvbnMpKTtcbiAgICBpZiAoc29ydGVkICYmIHNvcnRlZC5sZW5ndGgpIHtcbiAgICAgIHBrZ1tESVNUX1RBR1NdLmxhdGVzdCA9IHNvcnRlZC5wb3AoKTtcbiAgICB9XG4gIH1cblxuICBmb3IgKGNvbnN0IHRhZyBpbiBwa2dbRElTVF9UQUdTXSkge1xuICAgIGlmIChfLmlzQXJyYXkocGtnW0RJU1RfVEFHU11bdGFnXSkpIHtcbiAgICAgIGlmIChwa2dbRElTVF9UQUdTXVt0YWddLmxlbmd0aCkge1xuICAgICAgICAvLyBzb3J0IGFycmF5XG4gICAgICAgIC8vIEZJWE1FOiB0aGlzIGlzIGNsZWFybHkgd3JvbmcsIHdlIG5lZWQgdG8gcmVzZWFyY2ggd2h5IHRoaXMgaXMgbGlrZSB0aGlzLlxuICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgIHNvcnRlZCA9IHNlbXZlclNvcnQocGtnW0RJU1RfVEFHU11bdGFnXSk7XG4gICAgICAgIGlmIChzb3J0ZWQubGVuZ3RoKSB7XG4gICAgICAgICAgLy8gdXNlIGhpZ2hlc3QgdmVyc2lvbiBiYXNlZCBvbiBzZW12ZXIgc29ydFxuICAgICAgICAgIHBrZ1tESVNUX1RBR1NdW3RhZ10gPSBzb3J0ZWQucG9wKCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlbGV0ZSBwa2dbRElTVF9UQUdTXVt0YWddO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoXy5pc1N0cmluZyhwa2dbRElTVF9UQUdTXVt0YWddKSkge1xuICAgICAgaWYgKCFzZW12ZXIucGFyc2UocGtnW0RJU1RfVEFHU11bdGFnXSwgdHJ1ZSkpIHtcbiAgICAgICAgLy8gaWYgdGhlIHZlcnNpb24gaXMgaW52YWxpZCwgZGVsZXRlIHRoZSBkaXN0LXRhZyBlbnRyeVxuICAgICAgICBkZWxldGUgcGtnW0RJU1RfVEFHU11bdGFnXTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuY29uc3QgcGFyc2VJbnRlcnZhbFRhYmxlID0ge1xuICAnJzogMTAwMCxcbiAgbXM6IDEsXG4gIHM6IDEwMDAsXG4gIG06IDYwICogMTAwMCxcbiAgaDogNjAgKiA2MCAqIDEwMDAsXG4gIGQ6IDg2NDAwMDAwLFxuICB3OiA3ICogODY0MDAwMDAsXG4gIE06IDMwICogODY0MDAwMDAsXG4gIHk6IDM2NSAqIDg2NDAwMDAwLFxufTtcblxuLyoqXG4gKiBQYXJzZSBhbiBpbnRlcm5hbCBzdHJpbmcgdG8gbnVtYmVyXG4gKiBAcGFyYW0geyp9IGludGVydmFsXG4gKiBAcmV0dXJuIHtOdW1iZXJ9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUludGVydmFsKGludGVydmFsOiBhbnkpOiBudW1iZXIge1xuICBpZiAodHlwZW9mIGludGVydmFsID09PSAnbnVtYmVyJykge1xuICAgIHJldHVybiBpbnRlcnZhbCAqIDEwMDA7XG4gIH1cbiAgbGV0IHJlc3VsdCA9IDA7XG4gIGxldCBsYXN0X3N1ZmZpeCA9IEluZmluaXR5O1xuICBpbnRlcnZhbC5zcGxpdCgvXFxzKy8pLmZvckVhY2goZnVuY3Rpb24gKHgpOiB2b2lkIHtcbiAgICBpZiAoIXgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgbSA9IHgubWF0Y2goL14oKDB8WzEtOV1bMC05XSopKFxcLlswLTldKyk/KShtc3xzfG18aHxkfHd8TXx5fCkkLyk7XG4gICAgaWYgKFxuICAgICAgIW0gfHxcbiAgICAgIHBhcnNlSW50ZXJ2YWxUYWJsZVttWzRdXSA+PSBsYXN0X3N1ZmZpeCB8fFxuICAgICAgKG1bNF0gPT09ICcnICYmIGxhc3Rfc3VmZml4ICE9PSBJbmZpbml0eSlcbiAgICApIHtcbiAgICAgIHRocm93IEVycm9yKCdpbnZhbGlkIGludGVydmFsOiAnICsgaW50ZXJ2YWwpO1xuICAgIH1cbiAgICBsYXN0X3N1ZmZpeCA9IHBhcnNlSW50ZXJ2YWxUYWJsZVttWzRdXTtcbiAgICByZXN1bHQgKz0gTnVtYmVyKG1bMV0pICogcGFyc2VJbnRlcnZhbFRhYmxlW21bNF1dO1xuICB9KTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0IGNvbnN0IEVycm9yQ29kZSA9IHtcbiAgZ2V0Q29uZmxpY3QsXG4gIGdldEJhZERhdGEsXG4gIGdldEJhZFJlcXVlc3QsXG4gIGdldEludGVybmFsRXJyb3IsXG4gIGdldFVuYXV0aG9yaXplZCxcbiAgZ2V0Rm9yYmlkZGVuLFxuICBnZXRTZXJ2aWNlVW5hdmFpbGFibGUsXG4gIGdldE5vdEZvdW5kLFxuICBnZXRDb2RlLFxufTtcblxuLyoqXG4gKiBDaGVjayB3aGV0aGVyIHRoZSBwYXRoIGFscmVhZHkgZXhpc3QuXG4gKiBAcGFyYW0ge1N0cmluZ30gcGF0aFxuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZvbGRlckV4aXN0cyhwYXRoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBzdGF0ID0gZnMuc3RhdFN5bmMocGF0aCk7XG4gICAgcmV0dXJuIHN0YXQuaXNEaXJlY3RvcnkoKTtcbiAgfSBjYXRjaCAoXzogYW55KSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbi8qKlxuICogQ2hlY2sgd2hldGhlciB0aGUgZmlsZSBhbHJlYWR5IGV4aXN0LlxuICogQHBhcmFtIHtTdHJpbmd9IHBhdGhcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaWxlRXhpc3RzKHBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICB0cnkge1xuICAgIGNvbnN0IHN0YXQgPSBmcy5zdGF0U3luYyhwYXRoKTtcbiAgICByZXR1cm4gc3RhdC5pc0ZpbGUoKTtcbiAgfSBjYXRjaCAoXzogYW55KSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzb3J0QnlOYW1lKHBhY2thZ2VzOiBhbnlbXSwgb3JkZXJBc2NlbmRpbmc6IGJvb2xlYW4gfCB2b2lkID0gdHJ1ZSk6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIHBhY2thZ2VzLnNsaWNlKCkuc29ydChmdW5jdGlvbiAoYSwgYik6IG51bWJlciB7XG4gICAgY29uc3QgY29tcGFyYXRvck5hbWVzID0gYS5uYW1lLnRvTG93ZXJDYXNlKCkgPCBiLm5hbWUudG9Mb3dlckNhc2UoKTtcblxuICAgIHJldHVybiBvcmRlckFzY2VuZGluZyA/IChjb21wYXJhdG9yTmFtZXMgPyAtMSA6IDEpIDogY29tcGFyYXRvck5hbWVzID8gMSA6IC0xO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFkZFNjb3BlKHNjb3BlOiBzdHJpbmcsIHBhY2thZ2VOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYEAke3Njb3BlfS8ke3BhY2thZ2VOYW1lfWA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWxldGVQcm9wZXJ0aWVzKHByb3BlcnRpZXNUb0RlbGV0ZTogc3RyaW5nW10sIG9iamVjdEl0ZW06IGFueSk6IGFueSB7XG4gIF8uZm9yRWFjaChwcm9wZXJ0aWVzVG9EZWxldGUsIChwcm9wZXJ0eSk6IGFueSA9PiB7XG4gICAgZGVsZXRlIG9iamVjdEl0ZW1bcHJvcGVydHldO1xuICB9KTtcblxuICByZXR1cm4gb2JqZWN0SXRlbTtcbn1cblxuLyoqXG4gKiBwYXJzZSBwYWNrYWdlIHJlYWRtZSAtIG1hcmtkb3duL2FzY2lpXG4gKiBAcGFyYW0ge1N0cmluZ30gcGFja2FnZU5hbWUgbmFtZSBvZiBwYWNrYWdlXG4gKiBAcGFyYW0ge1N0cmluZ30gcmVhZG1lIHBhY2thZ2UgcmVhZG1lXG5cbiAqIEByZXR1cm4ge1N0cmluZ30gY29udmVydGVkIGh0bWwgdGVtcGxhdGVcbiAqL1xuLy8gVE9ETzogcmVuYW1lLCBkb2VzIG5vdCBwYXJzZSBhbnltb3JlXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VSZWFkbWUocGFja2FnZU5hbWU6IHN0cmluZywgcmVhZG1lOiBzdHJpbmcpOiBzdHJpbmcgfCB2b2lkIHtcbiAgaWYgKF8uaXNFbXB0eShyZWFkbWUpID09PSBmYWxzZSkge1xuICAgIHJldHVybiByZWFkbWU7XG4gIH1cblxuICAvLyBsb2dzIHJlYWRtZSBub3QgZm91bmQgZXJyb3JcbiAgbG9nZ2VyLmluZm8oeyBwYWNrYWdlTmFtZSB9LCAnQHtwYWNrYWdlTmFtZX06IE5vIHJlYWRtZSBmb3VuZCcpO1xuXG4gIHJldHVybiAnRVJST1I6IE5vIFJFQURNRSBkYXRhIGZvdW5kISc7XG59XG5cbi8qKlxuICogcmV0dXJuIGEgbWFzcXVlcmFkZSBzdHJpbmcgd2l0aCBpdHMgZmlyc3QgYW5kIGxhc3Qge2NoYXJOdW19IGFuZCB0aHJlZSBkb3RzIGluIGJldHdlZW4uXG4gKiBAcGFyYW0ge1N0cmluZ30gc3RyXG4gKiBAcGFyYW0ge051bWJlcn0gY2hhck51bVxuICogQHJldHVybnMge1N0cmluZ31cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hc2soc3RyOiBzdHJpbmcsIGNoYXJOdW0gPSAzKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAke3N0ci5zdWJzdHIoMCwgY2hhck51bSl9Li4uJHtzdHIuc3Vic3RyKC1jaGFyTnVtKX1gO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZW5jb2RlU2NvcGVkVXJpKHBhY2thZ2VOYW1lKTogc3RyaW5nIHtcbiAgcmV0dXJuIHBhY2thZ2VOYW1lLnJlcGxhY2UoL1xcLy9nLCAnJTJmJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNEaWZmT25lS2V5KHZlcnNpb25zKTogYm9vbGVhbiB7XG4gIHJldHVybiBPYmplY3Qua2V5cyh2ZXJzaW9ucykubGVuZ3RoICE9PSAxO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNWZXJzaW9uVmFsaWQocGFja2FnZU1ldGEsIHBhY2thZ2VWZXJzaW9uKTogYm9vbGVhbiB7XG4gIGNvbnN0IGhhc1ZlcnNpb24gPSB0eXBlb2YgcGFja2FnZVZlcnNpb24gIT09ICd1bmRlZmluZWQnO1xuICBpZiAoIWhhc1ZlcnNpb24pIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdCBoYXNNYXRjaFZlcnNpb24gPSBPYmplY3Qua2V5cyhwYWNrYWdlTWV0YS52ZXJzaW9ucykuaW5jbHVkZXMocGFja2FnZVZlcnNpb24pO1xuICByZXR1cm4gaGFzTWF0Y2hWZXJzaW9uO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNSZWxhdGVkVG9EZXByZWNhdGlvbihwa2dJbmZvOiBNYW5pZmVzdCk6IGJvb2xlYW4ge1xuICBjb25zdCB7IHZlcnNpb25zIH0gPSBwa2dJbmZvO1xuICBmb3IgKGNvbnN0IHZlcnNpb24gaW4gdmVyc2lvbnMpIHtcbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHZlcnNpb25zW3ZlcnNpb25dLCAnZGVwcmVjYXRlZCcpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG4vKipcbiAqXG4gKiBAcGFyYW0gY29uZmlnXG4gKiBAZGVwcmVjYXRlZCB1c2UgQHZlcmRhY2Npby9taWRkbGV3YXJlXG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzTG9naW4oY29uZmlnOiBDb25maWcpIHtcbiAgLy8gRklYTUU6IHR5cGVzIGFyZSBub3QgeWV0IG9uIHRoZSBsaWJyYXJ5IHZlcmRhY2Npby9tb25vcmVwb1xuICAvLyBAdHMtaWdub3JlXG4gIHJldHVybiBfLmlzTmlsKGNvbmZpZz8ud2ViPy5sb2dpbikgfHwgY29uZmlnPy53ZWI/LmxvZ2luID09PSB0cnVlO1xufVxuXG5leHBvcnQgeyBidWlsZFRva2VuVXRpbCBhcyBidWlsZFRva2VuLCBwYXJzZUNvbmZpZ0ZpbGUgfTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxJQUFBQSxHQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxPQUFBLEdBQUFGLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBRSxPQUFBLEdBQUFILHNCQUFBLENBQUFDLE9BQUE7QUFFQSxJQUFBRyxPQUFBLEdBQUFILE9BQUE7QUFFQSxJQUFBSSxLQUFBLEdBQUFKLE9BQUE7QUFHQSxJQUFBSyxNQUFBLEdBQUFMLE9BQUE7QUFFQSxJQUFBTSxVQUFBLEdBQUFOLE9BQUE7QUFDQSxJQUFBTyxPQUFBLEdBQUFQLE9BQUE7QUFBa0MsU0FBQUQsdUJBQUFTLENBQUEsV0FBQUEsQ0FBQSxJQUFBQSxDQUFBLENBQUFDLFVBQUEsR0FBQUQsQ0FBQSxLQUFBRSxPQUFBLEVBQUFGLENBQUE7QUFQbEM7O0FBU0EsTUFBTTtFQUNKRyxVQUFVO0VBQ1ZDLGFBQWE7RUFDYkMsT0FBTztFQUNQQyxXQUFXO0VBQ1hDLFlBQVk7RUFDWkMsZ0JBQWdCO0VBQ2hCQyxXQUFXO0VBQ1hDLHFCQUFxQjtFQUNyQkM7QUFDRixDQUFDLEdBQUdDLGdCQUFVOztBQUVkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTyxNQUFNQyxRQUFRLEdBQUFDLE9BQUEsQ0FBQUQsUUFBQSxHQUFHRSxxQkFBZSxDQUFDRixRQUFROztBQUVoRDtBQUNBO0FBQ0E7QUFDTyxTQUFTRyxlQUFlQSxDQUFDQyxHQUFRLEVBQVc7RUFDakQsT0FBT0MsZUFBQyxDQUFDTCxR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
;