verdaccio
Version:
A lightweight private npm proxy registry
716 lines (574 loc) • 65.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getUserAgent = getUserAgent;
exports.convertPayloadToBase64 = convertPayloadToBase64;
exports.validateName = validateName;
exports.validatePackage = validatePackage;
exports.isObject = isObject;
exports.validateMetadata = validateMetadata;
exports.combineBaseUrl = combineBaseUrl;
exports.extractTarballFromUrl = extractTarballFromUrl;
exports.convertDistRemoteToLocalTarballUrls = convertDistRemoteToLocalTarballUrls;
exports.getLocalRegistryTarballUri = getLocalRegistryTarballUri;
exports.tagVersion = tagVersion;
exports.getVersion = getVersion;
exports.parseAddress = parseAddress;
exports.semverSort = semverSort;
exports.normalizeDistTags = normalizeDistTags;
exports.parseInterval = parseInterval;
exports.getWebProtocol = getWebProtocol;
exports.getLatestVersion = getLatestVersion;
exports.parseConfigFile = parseConfigFile;
exports.folderExists = folderExists;
exports.fileExists = fileExists;
exports.sortByName = sortByName;
exports.addScope = addScope;
exports.deleteProperties = deleteProperties;
exports.addGravatarSupport = addGravatarSupport;
exports.parseReadme = parseReadme;
exports.buildToken = buildToken;
exports.getVersionFromTarball = getVersionFromTarball;
exports.formatAuthor = formatAuthor;
exports.isHTTPProtocol = isHTTPProtocol;
exports.pad = pad;
exports.mask = mask;
exports.encodeScopedUri = encodeScopedUri;
exports.hasDiffOneKey = hasDiffOneKey;
exports.isVersionValid = isVersionValid;
exports.isRelatedToDeprecation = isRelatedToDeprecation;
exports.ErrorCode = void 0;
var _fs = _interopRequireDefault(require("fs"));
var _assert = _interopRequireDefault(require("assert"));
var _url = _interopRequireDefault(require("url"));
var _lodash = _interopRequireDefault(require("lodash"));
var _semver = _interopRequireDefault(require("semver"));
var _jsYaml = _interopRequireDefault(require("js-yaml"));
var _readme = _interopRequireDefault(require("@verdaccio/readme"));
var _commonsApi = require("@verdaccio/commons-api");
var _user = require("../utils/user");
var _constants = require("./constants");
var _storageUtils = require("./storage-utils");
var _logger = require("./logger");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-var-requires
require('pkginfo')(module);
const pkgVersion = module.exports.version;
const pkgName = module.exports.name;
function getUserAgent() {
(0, _assert.default)(_lodash.default.isString(pkgName));
(0, _assert.default)(_lodash.default.isString(pkgVersion));
return `${pkgName}/${pkgVersion}`;
}
function convertPayloadToBase64(payload) {
return Buffer.from(payload, 'base64');
}
/**
* From normalize-package-data/lib/fixer.js
* @param {*} name the package name
* @return {Boolean} whether is valid or not
*/
function validateName(name) {
if (_lodash.default.isString(name) === false) {
return false;
}
const normalizedName = name.toLowerCase();
/**
* Some context about the first regex
* - npm used to have a different tarball naming system.
* eg: http://registry.npmjs.com/thirty-two
* https://registry.npmjs.org/thirty-two/-/thirty-two@0.0.1.tgz
* The file name thirty-two@0.0.1.tgz, the version and the pkg name was separated by an at (@)
* while nowadays the naming system is based in dashes
* https://registry.npmjs.org/verdaccio/-/verdaccio-1.4.0.tgz
*
* more info here: https://github.com/rlidwka/sinopia/issues/75
*/
return !(!normalizedName.match(/^[-a-zA-Z0-9_.!~*'()@]+$/) || normalizedName.startsWith('.') || // ".bin", etc.
['node_modules', '__proto__', 'favicon.ico'].includes(normalizedName));
}
/**
* Validate a package.
* @return {Boolean} whether the package is valid or not
*/
function validatePackage(name) {
const nameList = name.split('/', 2);
if (nameList.length === 1) {
// normal package
return validateName(nameList[0]);
} // scoped package
return nameList[0][0] === '@' && validateName(nameList[0].slice(1)) && validateName(nameList[1]);
}
/**
* Check whether an element is an Object
* @param {*} obj the element
* @return {Boolean}
*/
function isObject(obj) {
return _lodash.default.isObject(obj) && _lodash.default.isNull(obj) === false && _lodash.default.isArray(obj) === false;
}
/**
* Validate the package metadata, add additional properties whether are missing within
* the metadata properties.
* @param {*} object
* @param {*} name
* @return {Object} the object with additional properties as dist-tags ad versions
*/
function validateMetadata(object, name) {
(0, _assert.default)(isObject(object), 'not a json object');
_assert.default.strictEqual(object.name, name);
if (!isObject(object[_constants.DIST_TAGS])) {
object[_constants.DIST_TAGS] = {};
}
if (!isObject(object['versions'])) {
object['versions'] = {};
}
if (!isObject(object['time'])) {
object['time'] = {};
}
return object;
}
/**
* Create base url for registry.
* @return {String} base registry url
*/
function combineBaseUrl(protocol, host, prefix) {
const result = `${protocol}://${host}`;
const prefixOnlySlash = prefix === '/';
if (prefix && !prefixOnlySlash) {
if (prefix.endsWith('/')) {
prefix = prefix.slice(0, -1);
}
if (prefix.startsWith('/')) {
return `${result}${prefix}`;
}
return prefix;
}
return result;
}
function extractTarballFromUrl(url) {
// @ts-ignore
return _url.default.parse(url).pathname.replace(/^.*\//, '');
}
/**
* Iterate a packages's versions and filter each original tarball url.
* @param {*} pkg
* @param {*} req
* @param {*} config
* @return {String} a filtered package
*/
function convertDistRemoteToLocalTarballUrls(pkg, req, urlPrefix) {
for (const ver in pkg.versions) {
if (Object.prototype.hasOwnProperty.call(pkg.versions, ver)) {
const distName = pkg.versions[ver].dist;
if (_lodash.default.isNull(distName) === false && _lodash.default.isNull(distName.tarball) === false) {
distName.tarball = getLocalRegistryTarballUri(distName.tarball, pkg.name, req, urlPrefix);
}
}
}
return pkg;
}
/**
* Filter a tarball url.
* @param {*} uri
* @return {String} a parsed url
*/
function getLocalRegistryTarballUri(uri, pkgName, req, urlPrefix) {
const currentHost = req.headers.host;
if (!currentHost) {
return uri;
}
const tarballName = extractTarballFromUrl(uri);
const headers = req.headers;
const protocol = getWebProtocol(req.get(_constants.HEADERS.FORWARDED_PROTO), req.protocol);
const domainRegistry = combineBaseUrl(protocol, headers.host, urlPrefix);
return `${domainRegistry}/${encodeScopedUri(pkgName)}/-/${tarballName}`;
}
/**
* Create a tag for a package
* @param {*} data
* @param {*} version
* @param {*} tag
* @return {Boolean} whether a package has been tagged
*/
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) {
// $FlowFixMe
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;
}
/**
* Detect running protocol (http or https)
*/
function getWebProtocol(headerProtocol, protocol) {
if (typeof headerProtocol === 'string' && headerProtocol !== '') {
const commaIndex = headerProtocol.indexOf(',');
return commaIndex > 0 ? headerProtocol.substr(0, commaIndex) : headerProtocol;
}
return protocol;
}
function getLatestVersion(pkgInfo) {
return pkgInfo[_constants.DIST_TAGS].latest;
}
const ErrorCode = {
getConflict: _commonsApi.getConflict,
getBadData: _commonsApi.getBadData,
getBadRequest: _commonsApi.getBadRequest,
getInternalError: _commonsApi.getInternalError,
getUnauthorized: _commonsApi.getUnauthorized,
getForbidden: _commonsApi.getForbidden,
getServiceUnavailable: _commonsApi.getServiceUnavailable,
getNotFound: _commonsApi.getNotFound,
getCode: _commonsApi.getCode
};
exports.ErrorCode = ErrorCode;
function parseConfigFile(configPath) {
try {
if (/\.ya?ml$/i.test(configPath)) {
return _jsYaml.default.safeLoad(_fs.default.readFileSync(configPath, _constants.CHARACTER_ENCODING.UTF8));
}
return require(configPath);
} catch (e) {
if (e.code !== 'MODULE_NOT_FOUND') {
e.message = _constants.APP_ERROR.CONFIG_NOT_VALID;
}
throw new Error(e);
}
}
/**
* 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;
}
function addGravatarSupport(pkgInfo, online = true) {
const pkgInfoCopy = _objectSpread({}, pkgInfo);
const author = _lodash.default.get(pkgInfo, 'latest.author', null);
const contributors = (0, _storageUtils.normalizeContributors)(_lodash.default.get(pkgInfo, 'latest.contributors', []));
const maintainers = _lodash.default.get(pkgInfo, 'latest.maintainers', []); // for author.
if (author && _lodash.default.isObject(author)) {
const {
email
} = author;
pkgInfoCopy.latest.author.avatar = (0, _user.generateGravatarUrl)(email, online);
}
if (author && _lodash.default.isString(author)) {
pkgInfoCopy.latest.author = {
avatar: _user.GENERIC_AVATAR,
email: '',
author
};
} // for contributors
if (_lodash.default.isEmpty(contributors) === false) {
pkgInfoCopy.latest.contributors = contributors.map(contributor => {
if (isObject(contributor)) {
contributor.avatar = (0, _user.generateGravatarUrl)(contributor.email, online);
} else if (_lodash.default.isString(contributor)) {
contributor = {
avatar: _user.GENERIC_AVATAR,
email: contributor,
name: contributor
};
}
return contributor;
});
} // for maintainers
if (_lodash.default.isEmpty(maintainers) === false) {
pkgInfoCopy.latest.maintainers = maintainers.map(maintainer => {
maintainer.avatar = (0, _user.generateGravatarUrl)(maintainer.email, online);
return maintainer;
});
}
return pkgInfoCopy;
}
/**
* parse package readme - markdown/ascii
* @param {String} packageName name of package
* @param {String} readme package readme
* @return {String} converted html template
*/
function parseReadme(packageName, readme) {
if (_lodash.default.isEmpty(readme) === false) {
return (0, _readme.default)(readme);
} // logs readme not found error
_logger.logger.error({
packageName
}, '@{packageName}: No readme found');
return (0, _readme.default)('ERROR: No README data found!');
}
function buildToken(type, token) {
return `${_lodash.default.capitalize(type)} ${token}`;
}
/**
* return package version from tarball name
* @param {String} name
* @returns {String}
*/
function getVersionFromTarball(name) {
// FIXME: we know the regex is valid, but we should improve this part as ts suggest
// @ts-ignore
return /.+-(\d.+)\.tgz/.test(name) ? name.match(/.+-(\d.+)\.tgz/)[1] : undefined;
}
/**
* Formats author field for webui.
* @see https://docs.npmjs.com/files/package.json#author
* @param {string|object|undefined} author
*/
function formatAuthor(author) {
let authorDetails = {
name: _constants.DEFAULT_USER,
email: '',
url: ''
};
if (_lodash.default.isNil(author)) {
return authorDetails;
}
if (_lodash.default.isString(author)) {
authorDetails = _objectSpread(_objectSpread({}, authorDetails), {}, {
name: author
});
}
if (_lodash.default.isObject(author)) {
authorDetails = _objectSpread(_objectSpread({}, authorDetails), author);
}
return authorDetails;
}
/**
* Check if URI is starting with "http://", "https://" or "//"
* @param {string} uri
*/
function isHTTPProtocol(uri) {
return /^(https?:)?\/\//.test(uri);
}
/**
* Apply whitespaces based on the length
* @param {*} str the log message
* @return {String}
*/
function pad(str, max) {
if (str.length < max) {
return str + ' '.repeat(max - str.length);
}
return str;
}
/**
* 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;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvdXRpbHMudHMiXSwibmFtZXMiOlsicmVxdWlyZSIsIm1vZHVsZSIsInBrZ1ZlcnNpb24iLCJleHBvcnRzIiwidmVyc2lvbiIsInBrZ05hbWUiLCJuYW1lIiwiZ2V0VXNlckFnZW50IiwiXyIsImlzU3RyaW5nIiwiY29udmVydFBheWxvYWRUb0Jhc2U2NCIsInBheWxvYWQiLCJCdWZmZXIiLCJmcm9tIiwidmFsaWRhdGVOYW1lIiwibm9ybWFsaXplZE5hbWUiLCJ0b0xvd2VyQ2FzZSIsIm1hdGNoIiwic3RhcnRzV2l0aCIsImluY2x1ZGVzIiwidmFsaWRhdGVQYWNrYWdlIiwibmFtZUxpc3QiLCJzcGxpdCIsImxlbmd0aCIsInNsaWNlIiwiaXNPYmplY3QiLCJvYmoiLCJpc051bGwiLCJpc0FycmF5IiwidmFsaWRhdGVNZXRhZGF0YSIsIm9iamVjdCIsImFzc2VydCIsInN0cmljdEVxdWFsIiwiRElTVF9UQUdTIiwiY29tYmluZUJhc2VVcmwiLCJwcm90b2NvbCIsImhvc3QiLCJwcmVmaXgiLCJyZXN1bHQiLCJwcmVmaXhPbmx5U2xhc2giLCJlbmRzV2l0aCIsImV4dHJhY3RUYXJiYWxsRnJvbVVybCIsInVybCIsIlVSTCIsInBhcnNlIiwicGF0aG5hbWUiLCJyZXBsYWNlIiwiY29udmVydERpc3RSZW1vdGVUb0xvY2FsVGFyYmFsbFVybHMiLCJwa2ciLCJyZXEiLCJ1cmxQcmVmaXgiLCJ2ZXIiLCJ2ZXJzaW9ucyIsIk9iamVjdCIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImRpc3ROYW1lIiwiZGlzdCIsInRhcmJhbGwiLCJnZXRMb2NhbFJlZ2lzdHJ5VGFyYmFsbFVyaSIsInVyaSIsImN1cnJlbnRIb3N0IiwiaGVhZGVycyIsInRhcmJhbGxOYW1lIiwiZ2V0V2ViUHJvdG9jb2wiLCJnZXQiLCJIRUFERVJTIiwiRk9SV0FSREVEX1BST1RPIiwiZG9tYWluUmVnaXN0cnkiLCJlbmNvZGVTY29wZWRVcmkiLCJ0YWdWZXJzaW9uIiwiZGF0YSIsInRhZyIsInNlbXZlciIsImdldFZlcnNpb24iLCJpc05pbCIsInZlcnNpb25JdGVtIiwiY29tcGFyZSIsImVyciIsInVuZGVmaW5lZCIsInBhcnNlQWRkcmVzcyIsInVybEFkZHJlc3MiLCJ1cmxQYXR0ZXJuIiwiZXhlYyIsInByb3RvIiwiREVGQVVMVF9QUk9UT0NPTCIsIkRFRkFVTFRfRE9NQUlOIiwicG9ydCIsIkRFRkFVTFRfUE9SVCIsInBhdGgiLCJzZW12ZXJTb3J0IiwibGlzdFZlcnNpb25zIiwiZmlsdGVyIiwieCIsImxvZ2dlciIsIndhcm4iLCJzb3J0IiwiY29tcGFyZUxvb3NlIiwibWFwIiwiU3RyaW5nIiwibm9ybWFsaXplRGlzdFRhZ3MiLCJzb3J0ZWQiLCJsYXRlc3QiLCJrZXlzIiwicG9wIiwicGFyc2VJbnRlcnZhbFRhYmxlIiwibXMiLCJzIiwibSIsImgiLCJkIiwidyIsIk0iLCJ5IiwicGFyc2VJbnRlcnZhbCIsImludGVydmFsIiwibGFzdF9zdWZmaXgiLCJJbmZpbml0eSIsImZvckVhY2giLCJFcnJvciIsIk51bWJlciIsImhlYWRlclByb3RvY29sIiwiY29tbWFJbmRleCIsImluZGV4T2YiLCJzdWJzdHIiLCJnZXRMYXRlc3RWZXJzaW9uIiwicGtnSW5mbyIsIkVycm9yQ29kZSIsImdldENvbmZsaWN0IiwiZ2V0QmFkRGF0YSIsImdldEJhZFJlcXVlc3QiLCJnZXRJbnRlcm5hbEVycm9yIiwiZ2V0VW5hdXRob3JpemVkIiwiZ2V0Rm9yYmlkZGVuIiwiZ2V0U2VydmljZVVuYXZhaWxhYmxlIiwiZ2V0Tm90Rm91bmQiLCJnZXRDb2RlIiwicGFyc2VDb25maWdGaWxlIiwiY29uZmlnUGF0aCIsInRlc3QiLCJZQU1MIiwic2FmZUxvYWQiLCJmcyIsInJlYWRGaWxlU3luYyIsIkNIQVJBQ1RFUl9FTkNPRElORyIsIlVURjgiLCJlIiwiY29kZSIsIm1lc3NhZ2UiLCJBUFBfRVJST1IiLCJDT05GSUdfTk9UX1ZBTElEIiwiZm9sZGVyRXhpc3RzIiwic3RhdCIsInN0YXRTeW5jIiwiaXNEaXJlY3RvcnkiLCJmaWxlRXhpc3RzIiwiaXNGaWxlIiwic29ydEJ5TmFtZSIsInBhY2thZ2VzIiwib3JkZXJBc2NlbmRpbmciLCJhIiwiYiIsImNvbXBhcmF0b3JOYW1lcyIsImFkZFNjb3BlIiwic2NvcGUiLCJwYWNrYWdlTmFtZSIsImRlbGV0ZVByb3BlcnRpZXMiLCJwcm9wZXJ0aWVzVG9EZWxldGUiLCJvYmplY3RJdGVtIiwicHJvcGVydHkiLCJhZGRHcmF2YXRhclN1cHBvcnQiLCJvbmxpbmUiLCJwa2dJbmZvQ29weSIsImF1dGhvciIsImNvbnRyaWJ1dG9ycyIsIm1haW50YWluZXJzIiwiZW1haWwiLCJhdmF0YXIiLCJHRU5FUklDX0FWQVRBUiIsImlzRW1wdHkiLCJjb250cmlidXRvciIsIm1haW50YWluZXIiLCJwYXJzZVJlYWRtZSIsInJlYWRtZSIsImVycm9yIiwiYnVpbGRUb2tlbiIsInR5cGUiLCJ0b2tlbiIsImNhcGl0YWxpemUiLCJnZXRWZXJzaW9uRnJvbVRhcmJhbGwiLCJmb3JtYXRBdXRob3IiLCJhdXRob3JEZXRhaWxzIiwiREVGQVVMVF9VU0VSIiwiaXNIVFRQUHJvdG9jb2wiLCJwYWQiLCJzdHIiLCJtYXgiLCJyZXBlYXQiLCJtYXNrIiwiY2hhck51bSIsImhhc0RpZmZPbmVLZXkiLCJpc1ZlcnNpb25WYWxpZCIsInBhY2thZ2VNZXRhIiwicGFja2FnZVZlcnNpb24iLCJoYXNWZXJzaW9uIiwiaGFzTWF0Y2hWZXJzaW9uIiwiaXNSZWxhdGVkVG9EZXByZWNhdGlvbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUdBOztBQUNBOztBQUNBOztBQUVBOztBQUNBOztBQUNBOztBQUNBOztBQUlBOztBQVdBOztBQUVBOztBQVdBOztBQUVBOzs7Ozs7Ozs7O0FBRUE7QUFDQTtBQUNBQSxPQUFPLENBQUMsU0FBRCxDQUFQLENBQW1CQyxNQUFuQjs7QUFDQSxNQUFNQyxVQUFVLEdBQUdE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QyxDQUEyQ3lMLGNBQTNDLENBQXhCO0FBQ0EsU0FBT0UsZUFBUDtBQUNEOztBQUVNLFNBQVNDLHNCQUFULENBQWdDaEYsT0FBaEMsRUFBMkQ7QUFDaEUsUUFBTTtBQUFFM0UsSUFBQUE7QUFBRixNQUFlMkUsT0FBckI7O0FBQ0EsT0FBSyxNQUFNM0gsT0FBWCxJQUFzQmdELFFBQXRCLEVBQWdDO0FBQzlCLFFBQUlDLE1BQU0sQ0FBQ0MsU0FBUCxDQUFpQkMsY0FBakIsQ0FBZ0NDLElBQWhDLENBQXFDSixRQUFRLENBQUNoRCxPQUFELENBQTdDLEVBQXdELFlBQXhELENBQUosRUFBMkU7QUFDekUsYUFBTyxJQUFQO0FBQ0Q7QUFDRjs7QUFDRCxTQUFPLEtBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQHByZXR0aWVyXG4gKi9cbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgVVJMIGZyb20gJ3VybCc7XG5pbXBvcnQgeyBJbmNvbWluZ0h0dHBIZWFkZXJzIH0gZnJvbSAnaHR0cDInO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBzZW12ZXIgZnJvbSAnc2VtdmVyJztcbmltcG9ydCBZQU1MIGZyb20gJ2pzLXlhbWwnO1xuaW1wb3J0IHNhbml0aXp5UmVhZG1lIGZyb20gJ0B2ZXJkYWNjaW8vcmVhZG1lJztcblxuaW1wb3J0IHsgUGFja2FnZSwgVmVyc2lvbiwgQXV0aG9yIH0gZnJvbSAnQHZlcmRhY2Npby90eXBlcyc7XG5pbXBvcnQgeyBSZXF1ZXN0IH0gZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQge1xuICBnZXRDb25mbGljdCxcbiAgZ2V0QmFkRGF0YSxcbiAgZ2V0QmFkUmVxdWVzdCxcbiAgZ2V0SW50ZXJuYWxFcnJvcixcbiAgZ2V0VW5hdXRob3JpemVkLFxuICBnZXRGb3JiaWRkZW4sXG4gIGdldFNlcnZpY2VVbmF2YWlsYWJsZSxcbiAgZ2V0Tm90Rm91bmQsXG4gIGdldENvZGVcbn0gZnJvbSAnQHZlcmRhY2Npby9jb21tb25zLWFwaSc7XG5pbXBvcnQgeyBnZW5lcmF0ZUdyYXZhdGFyVXJsLCBHRU5FUklDX0FWQVRBUiB9IGZyb20gJy4uL3V0aWxzL3VzZXInO1xuaW1wb3J0IHsgU3RyaW5nVmFsdWUsIEF1dGhvckF2YXRhciB9IGZyb20gJy4uLy4uL3R5cGVzJztcbmltcG9ydCB7XG4gIEFQUF9FUlJPUixcbiAgREVGQVVMVF9QT1JULFxuICBERUZBVUxUX0RPTUFJTixcbiAgREVGQVVMVF9QUk9UT0NPTCxcbiAgQ0hBUkFDVEVSX0VOQ09ESU5HLFxuICBIRUFERVJTLFxuICBESVNUX1RBR1MsXG4gIERFRkFVTFRfVVNFUlxufSBmcm9tICcuL2NvbnN0YW50cyc7XG5cbmltcG9ydCB7IG5vcm1hbGl6ZUNvbnRyaWJ1dG9ycyB9IGZyb20gJy4vc3RvcmFnZS11dGlscyc7XG5cbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyJztcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby12YXItcmVxdWlyZXNcbnJlcXVpcmUoJ3BrZ2luZm8nKShtb2R1bGUpO1xuY29uc3QgcGtnVmVyc2lvbiA9IG1vZHVsZS5leHBvcnRzLnZlcnNpb247XG5jb25zdCBwa2dOYW1lID0gbW9kdWxlLmV4cG9ydHMubmFtZTtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldFVzZXJBZ2VudCgpOiBzdHJpbmcge1xuICBhc3NlcnQoXy5pc1N0cmluZyhwa2dOYW1lKSk7XG4gIGFzc2VydChfLmlzU3RyaW5nKHBrZ1ZlcnNpb24pKTtcbiAgcmV0dXJuIGAke3BrZ05hbWV9LyR7cGtnVmVyc2lvbn1gO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29udmVydFBheWxvYWRUb0Jhc2U2NChwYXlsb2FkOiBzdHJpbmcpOiBCdWZmZXIge1xuICByZXR1cm4gQnVmZmVyLmZyb20ocGF5bG9hZCwgJ2Jhc2U2NCcpO1xufVxuXG4vKipcbiAqIEZyb20gbm9ybWFsaXplLXBhY2thZ2UtZGF0YS9saWIvZml4ZXIuanNcbiAqIEBwYXJhbSB7Kn0gbmFtZSAgdGhlIHBhY2thZ2UgbmFtZVxuICogQHJldHVybiB7Qm9vbGVhbn0gd2hldGhlciBpcyB2YWxpZCBvciBub3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlTmFtZShuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgaWYgKF8uaXNTdHJpbmcobmFtZSkgPT09IGZhbHNlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3Qgbm9ybWFsaXplZE5hbWU6IHN0cmluZyA9IG5hbWUudG9Mb3dlckNhc2UoKTtcblxuICAvKipcbiAgICogU29tZSBjb250ZXh0IGFib3V0IHRoZSBmaXJzdCByZWdleFxuICAgKiAtIG5wbSB1c2VkIHRvIGhhdmUgYSBkaWZmZXJlbnQgdGFyYmFsbCBuYW1pbmcgc3lzdGVtLlxuICAgKiBlZzogaHR0cDovL3JlZ2lzdHJ5Lm5wbWpzLmNvbS90aGlydHktdHdvXG4gICAqIGh0dHBzOi8vcmVnaXN0cnkubnBtanMub3JnL3RoaXJ0eS10d28vLS90aGlydHktdHdvQDAuMC4xLnRnelxuICAgKiBUaGUgZmlsZSBuYW1lIHRoaXJ0eS10d29AMC4wLjEudGd6LCB0aGUgdmVyc2lvbiBhbmQgdGhlIHBrZyBuYW1lIHdhcyBzZXBhcmF0ZWQgYnkgYW4gYXQgKEApXG4gICAqIHdoaWxlIG5vd2FkYXlzIHRoZSBuYW1pbmcgc3lzdGVtIGlzIGJhc2VkIGluIGRhc2hlc1xuICAgKiBodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy92ZXJkYWNjaW8vLS92ZXJkYWNjaW8tMS40LjAudGd6XG4gICAqXG4gICAqIG1vcmUgaW5mbyBoZXJlOiBodHRwczovL2dpdGh1Yi5jb20vcmxpZHdrYS9zaW5vcGlhL2lzc3Vlcy83NVxuICAgKi9cbiAgcmV0dXJuICEoXG4gICAgIW5vcm1hbGl6ZWROYW1lLm1hdGNoKC9eWy1hLXpBLVowLTlfLiF+KicoKUBdKyQvKSB8fFxuICAgIG5vcm1hbGl6ZWROYW1lLnN0YXJ0c1dpdGgoJy4nKSB8fCAvLyBcIi5iaW5cIiwgZXRjLlxuICAgIFsnbm9kZV9tb2R1bGVzJywgJ19fcHJvdG9fXycsICdmYXZpY29uLmljbyddLmluY2x1ZGVzKG5vcm1hbGl6ZWROYW1lKVxuICApO1xufVxuXG4vKipcbiAqIFZhbGlkYXRlIGEgcGFja2FnZS5cbiAqIEByZXR1cm4ge0Jvb2xlYW59IHdoZXRoZXIgdGhlIHBhY2thZ2UgaXMgdmFsaWQgb3Igbm90XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVBhY2thZ2UobmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IG5hbWVMaXN0ID0gbmFtZS5zcGxpdCgnLycsIDIpO1xuICBpZiAobmFtZUxpc3QubGVuZ3RoID09PSAxKSB7XG4gICAgLy8gbm9ybWFsIHBhY2thZ2VcbiAgICByZXR1cm4gdmFsaWRhdGVOYW1lKG5hbWVMaXN0WzBdKTtcbiAgfVxuICAvLyBzY29wZWQgcGFja2FnZVxuICByZXR1cm4gbmFtZUxpc3RbMF1bMF0gPT09ICdAJyAmJiB2YWxpZGF0ZU5hbWUobmFtZUxpc3RbMF0uc2xpY2UoMSkpICYmIHZhbGlkYXRlTmFtZShuYW1lTGlzdFsxXSk7XG59XG5cbi8qKlxuICogQ2hlY2sgd2hldGhlciBhbiBlbGVtZW50IGlzIGFuIE9iamVjdFxuICogQHBhcmFtIHsqfSBvYmogdGhlIGVsZW1lbnRcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc09iamVjdChvYmo6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gXy5pc09iamVjdChvYmopICYmIF8uaXNOdWxsKG9iaikgPT09IGZhbHNlICYmIF8uaXNBcnJheShvYmopID09PSBmYWxzZTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZSB0aGUgcGFja2FnZSBtZXRhZGF0YSwgYWRkIGFkZGl0aW9uYWwgcHJvcGVydGllcyB3aGV0aGVyIGFyZSBtaXNzaW5nIHdpdGhpblxuICogdGhlIG1ldGFkYXRhIHByb3BlcnRpZXMuXG4gKiBAcGFyYW0geyp9IG9iamVjdFxuICogQHBhcmFtIHsqfSBuYW1lXG4gKiBAcmV0dXJuIHtPYmplY3R9IHRoZSBvYmplY3Qgd2l0aCBhZGRpdGlvbmFsIHByb3BlcnRpZXMgYXMgZGlzdC10YWdzIGFkIHZlcnNpb25zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZU1ldGFkYXRhKG9iamVjdDogUGFja2FnZSwgbmFtZTogc3RyaW5nKTogUGFja2FnZSB7XG4gIGFzc2VydChpc09iamVjdChvYmplY3QpLCAnbm90IGEganNvbiBvYmplY3QnKTtcbiAgYXNzZXJ0LnN0cmljdEVxdWFsKG9iamVjdC5uYW1lLCBuYW1lKTtcblxuICBpZiAoIWlzT2JqZWN0KG9iamVjdFtESVNUX1RBR1NdKSkge1xuICAgIG9iamVjdFtESVNUX1RBR1NdID0ge307XG4gIH1cblxuICBpZiAoIWlzT2JqZWN0KG9iamVjdFsndmVyc2lvbnMnXSkpIHtcbiAgICBvYmplY3RbJ3ZlcnNpb25zJ10gPSB7fTtcbiAgfVxuXG4gIGlmICghaXNPYmplY3Qob2JqZWN0Wyd0aW1lJ10pKSB7XG4gICAgb2JqZWN0Wyd0aW1lJ10gPSB7fTtcbiAgfVxuXG4gIHJldHVybiBvYmplY3Q7XG59XG5cbi8qKlxuICogQ3JlYXRlIGJhc2UgdXJsIGZvciByZWdpc3RyeS5cbiAqIEByZXR1cm4ge1N0cmluZ30gYmFzZSByZWdpc3RyeSB1cmxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbWJpbmVCYXNlVXJsKFxuICBwcm90b2NvbDogc3RyaW5nLFxuICBob3N0OiBzdHJpbmcgfCB2b2lkLFxuICBwcmVmaXg/OiBzdHJpbmcgfCB2b2lkXG4pOiBzdHJpbmcge1xuICBjb25zdCByZXN1bHQgPSBgJHtwcm90b2NvbH06Ly8ke2hvc3R9YDtcblxuICBjb25zdCBwcmVmaXhPbmx5U2xhc2ggPSBwcmVmaXggPT09ICcvJztcbiAgaWYgKHByZWZpeCAmJiAhcHJlZml4T25seVNsYXNoKSB7XG4gICAgaWYgKHByZWZpeC5lbmRzV2l0aCgnLycpKSB7XG4gICAgICBwcmVmaXggPSBwcmVmaXguc2xpY2UoMCwgLTEpO1xuICAgIH1cblxuICAgIGlmIChwcmVmaXguc3RhcnRzV2l0aCgnLycpKSB7XG4gICAgICByZXR1cm4gYCR7cmVzdWx0fSR7cHJlZml4fWA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByZWZpeDtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0VGFyYmFsbEZyb21VcmwodXJsOiBzdHJpbmcpOiBzdHJpbmcge1xuICAvLyBAdHMtaWdub3JlXG4gIHJldHVybiBVUkwucGFyc2UodXJsKS5wYXRobmFtZS5yZXBsYWNlKC9eLipcXC8vLCAnJyk7XG59XG5cbi8qKlxuICogSXRlcmF0ZSBhIHBhY2thZ2VzJ3MgdmVyc2lvbnMgYW5kIGZpbHRlciBlYWNoIG9yaWdpbmFsIHRhcmJhbGwgdXJsLlxuICogQHBhcmFtIHsqfSBwa2dcbiAqIEBwYXJhbSB7Kn0gcmVxXG4gKiBAcGFyYW0geyp9IGNvbmZpZ1xuICogQHJldHVybiB7U3RyaW5nfSBhIGZpbHRlcmVkIHBhY2thZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbnZlcnREaXN0UmVtb3RlVG9Mb2NhbFRhcmJhbGxVcmxzKFxuICBwa2c6IFBhY2thZ2UsXG4gIHJlcTogUmVxdWVzdCxcbiAgdXJsUHJlZml4OiBzdHJpbmcgfCB2b2lkXG4pOiBQYWNrYWdlIHtcbiAgZm9yIChjb25zdCB2ZXIgaW4gcGtnLnZlcnNpb25zKSB7XG4gICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChwa2cudmVyc2lvbnMsIHZlcikpIHtcbiAgICAgIGNvbnN0IGRpc3ROYW1lID0gcGtnLnZlcnNpb25zW3Zlcl0uZGlzdDtcblxuICAgICAgaWYgKF8uaXNOdWxsKGRpc3ROYW1lKSA9PT0gZmFsc2UgJiYgXy5pc051bGwoZGlzdE5hbWUudGFyYmFsbCkgPT09IGZhbHNlKSB7XG4gICAgICAgIGRpc3ROYW1lLnRhcmJhbGwgPSBnZXRMb2NhbFJlZ2lzdHJ5VGFyYmFsbFVyaShkaXN0TmFtZS50YXJiYWxsLCBwa2cubmFtZSwgcmVxLCB1cmxQcmVmaXgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gcGtnO1xufVxuXG4vKipcbiAqIEZpbHRlciBhIHRhcmJhbGwgdXJsLlxuICogQHBhcmFtIHsqfSB1cmlcbiAqIEByZXR1cm4ge1N0cmluZ30gYSBwYXJzZWQgdXJsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRMb2NhbFJlZ2lzdHJ5VGFyYmFsbFVyaShcbiAgdXJpOiBzdHJpbmcsXG4gIHBrZ05hbWU6IHN0cmluZyxcbiAgcmVxOiBSZXF1ZXN0LFxuICB1cmxQcmVmaXg6IHN0cmluZyB8IHZvaWRcbik6IHN0cmluZyB7XG4gIGNvbnN0IGN1cnJlbnRIb3N0ID0gcmVxLmhlYWRlcnMuaG9zdDtcblxuICBpZiAoIWN1cnJlbnRIb3N0KSB7XG4gICAgcmV0dXJuIHVyaTtcbiAgfVxuICBjb25zdCB0YXJiYWxsTmFtZSA9IGV4dHJhY3RUYXJiYWxsRnJvbVVybCh1cmkpO1xuICBjb25zdCBoZWFkZXJzID0gcmVxLmhlYWRlcnMgYXMgSW5jb21pbmdIdHRwSGVhZGVycztcbiAgY29uc3QgcHJvdG9jb2wgPSBnZXRXZWJQcm90b2NvbChyZXEuZ2V0KEhFQURFUlMuRk9SV0FSREVEX1BST1RPKSwgcmVxLnByb3RvY29sKTtcbiAgY29uc3QgZG9tYWluUmVnaXN0cnkgPSBjb21iaW5lQmFzZVVybChwcm90b2NvbCwgaGVhZGVycy5ob3N0LCB1cmxQcmVmaXgpO1xuXG4gIHJldHVybiBgJHtkb21haW5SZWdpc3RyeX0vJHtlbmNvZGVTY29wZWRVcmkocGtnTmFtZSl9Ly0vJHt0YXJiYWxsTmFtZX1gO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIHRhZyBmb3IgYSBwYWNrYWdlXG4gKiBAcGFyYW0geyp9IGRhdGFcbiAqIEBwYXJhbSB7Kn0gdmVyc2lvblxuICogQHBhcmFtIHsqfSB0YWdcbiAqIEByZXR1cm4ge0Jvb2xlYW59IHdoZXRoZXIgYSBwYWNrYWdlIGhhcyBiZWVuIHRhZ2dlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gdGFnVmVyc2lvbihkYXRhOiBQYWNrYWdlLCB2ZXJzaW9uOiBzdHJpbmcsIHRhZzogU3RyaW5nVmFsdWUpOiBib29sZWFuIHtcbiAgaWYgKHRhZyAmJiBkYXRhW0RJU1RfVEFHU11bdGFnXSAhPT0gdmVyc2lv