verdaccio
Version:
A lightweight private npm proxy registry
630 lines (501 loc) • 68 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _assert = _interopRequireDefault(require("assert"));
var _stream = _interopRequireDefault(require("stream"));
var _lodash = _interopRequireDefault(require("lodash"));
var _async = _interopRequireDefault(require("async"));
var _streams = require("@verdaccio/streams");
var _logger = require("../lib/logger");
var _upStorage = _interopRequireDefault(require("./up-storage"));
var _search = _interopRequireDefault(require("./search"));
var _constants = require("./constants");
var _localStorage = _interopRequireDefault(require("./local-storage"));
var _storageUtils = require("./storage-utils");
var _uplinkUtil = require("./uplink-util");
var _metadataUtils = require("./metadata-utils");
var _utils = require("./utils");
var _configUtils = require("./config-utils");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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; }
class Storage {
constructor(config) {
_defineProperty(this, "localStorage", void 0);
_defineProperty(this, "config", void 0);
_defineProperty(this, "logger", void 0);
_defineProperty(this, "uplinks", void 0);
_defineProperty(this, "filters", void 0);
this.config = config;
this.uplinks = (0, _uplinkUtil.setupUpLinks)(config);
this.logger = _logger.logger.child();
this.filters = []; // @ts-ignore
this.localStorage = null;
}
init(config, filters = []) {
this.filters = filters;
this.localStorage = new _localStorage.default(this.config, _logger.logger);
return this.localStorage.getSecret(config);
}
/**
* Add a {name} package to a system
Function checks if package with the same name is available from uplinks.
If it isn't, we create package locally
Used storages: local (write) && uplinks
*/
async addPackage(name, metadata, callback) {
try {
await (0, _storageUtils.checkPackageLocal)(name, this.localStorage);
await (0, _storageUtils.checkPackageRemote)(name, this._isAllowPublishOffline(), this._syncUplinksMetadata.bind(this));
await (0, _storageUtils.publishPackage)(name, metadata, this.localStorage);
callback();
} catch (err) {
callback(err);
}
}
_isAllowPublishOffline() {
return typeof this.config.publish !== 'undefined' && _lodash.default.isBoolean(this.config.publish.allow_offline) && this.config.publish.allow_offline;
}
readTokens(filter) {
return this.localStorage.readTokens(filter);
}
saveToken(token) {
return this.localStorage.saveToken(token);
}
deleteToken(user, tokenKey) {
return this.localStorage.deleteToken(user, tokenKey);
}
/**
* Add a new version of package {name} to a system
Used storages: local (write)
*/
addVersion(name, version, metadata, tag, callback) {
this.localStorage.addVersion(name, version, metadata, tag, callback);
}
/**
* Tags a package version with a provided tag
Used storages: local (write)
*/
mergeTags(name, tagHash, callback) {
this.localStorage.mergeTags(name, tagHash, callback);
}
/**
* Change an existing package (i.e. unpublish one version)
Function changes a package info from local storage and all uplinks with write access./
Used storages: local (write)
*/
changePackage(name, metadata, revision, callback) {
this.localStorage.changePackage(name, metadata, revision, callback);
}
/**
* Remove a package from a system
Function removes a package from local storage
Used storages: local (write)
*/
removePackage(name, callback) {
this.localStorage.removePackage(name, callback); // update the indexer
_search.default.remove(name);
}
/**
Remove a tarball from a system
Function removes a tarball from local storage.
Tarball in question should not be linked to in any existing
versions, i.e. package version should be unpublished first.
Used storage: local (write)
*/
removeTarball(name, filename, revision, callback) {
this.localStorage.removeTarball(name, filename, revision, callback);
}
/**
* Upload a tarball for {name} package
Function is synchronous and returns a WritableStream
Used storages: local (write)
*/
addTarball(name, filename) {
return this.localStorage.addTarball(name, filename);
}
/**
Get a tarball from a storage for {name} package
Function is synchronous and returns a ReadableStream
Function tries to read tarball locally, if it fails then it reads package
information in order to figure out where we can get this tarball from
Used storages: local || uplink (just one)
*/
getTarball(name, filename) {
const readStream = new _streams.ReadTarball({});
readStream.abort = function () {};
const self = this; // if someone requesting tarball, it means that we should already have some
// information about it, so fetching package info is unnecessary
// trying local first
// flow: should be IReadTarball
let localStream = self.localStorage.getTarball(name, filename);
let isOpen = false;
localStream.on('error', err => {
if (isOpen || err.status !== _constants.HTTP_STATUS.NOT_FOUND) {
return readStream.emit('error', err);
} // local reported 404
const err404 = err;
localStream.abort();
localStream = null; // we force for garbage collector
self.localStorage.getPackageMetadata(name, (err, info) => {
if (_lodash.default.isNil(err) && info._distfiles && _lodash.default.isNil(info._distfiles[filename]) === false) {
// information about this file exists locally
serveFile(info._distfiles[filename]);
} else {
// we know nothing about this file, trying to get information elsewhere
self._syncUplinksMetadata(name, info, {}, (err, info) => {
if (_lodash.default.isNil(err) === false) {
return readStream.emit('error', err);
}
if (_lodash.default.isNil(info._distfiles) || _lodash.default.isNil(info._distfiles[filename])) {
return readStream.emit('error', err404);
}
serveFile(info._distfiles[filename]);
});
}
});
});
localStream.on('content-length', function (v) {
readStream.emit('content-length', v);
});
localStream.on('open', function () {
isOpen = true;
localStream.pipe(readStream);
});
return readStream;
/**
* Fetch and cache local/remote packages.
* @param {Object} file define the package shape
*/
function serveFile(file) {
let uplink = null;
for (const uplinkId in self.uplinks) {
if ((0, _configUtils.hasProxyTo)(name, uplinkId, self.config.packages)) {
uplink = self.uplinks[uplinkId];
}
}
if (uplink == null) {
uplink = new _upStorage.default({
url: file.url,
cache: true,
_autogenerated: true
}, self.config);
}
let savestream = null;
if (uplink.config.cache) {
savestream = self.localStorage.addTarball(name, filename);
}
let on_open = function () {
// prevent it from being called twice
on_open = function () {};
const rstream2 = uplink.fetchTarball(file.url);
rstream2.on('error', function (err) {
if (savestream) {
savestream.abort();
}
savestream = null;
readStream.emit('error', err);
});
rstream2.on('end', function () {
if (savestream) {
savestream.done();
}
});
rstream2.on('content-length', function (v) {
readStream.emit('content-length', v);
if (savestream) {
savestream.emit('content-length', v);
}
});
rstream2.pipe(readStream);
if (savestream) {
rstream2.pipe(savestream);
}
};
if (savestream) {
savestream.on('open', function () {
on_open();
});
savestream.on('error', function (err) {
self.logger.warn({
err: err,
fileName: file
}, 'error saving file @{fileName}: @{err.message}\n@{err.stack}');
if (savestream) {
savestream.abort();
}
savestream = null;
on_open();
});
} else {
on_open();
}
}
}
/**
Retrieve a package metadata for {name} package
Function invokes localStorage.getPackage and uplink.get_package for every
uplink with proxy_access rights against {name} and combines results
into one json object
Used storages: local && uplink (proxy_access)
* @param {object} options
* @property {string} options.name Package Name
* @property {object} options.req Express `req` object
* @property {boolean} options.keepUpLinkData keep up link info in package meta, last update, etc.
* @property {function} options.callback Callback for receive data
*/
getPackage(options) {
this.localStorage.getPackageMetadata(options.name, (err, data) => {
if (err && (!err.status || err.status >= _constants.HTTP_STATUS.INTERNAL_ERROR)) {
// report internal errors right away
return options.callback(err);
}
this._syncUplinksMetadata(options.name, data, {
req: options.req,
uplinksLook: options.uplinksLook
}, function getPackageSynUpLinksCallback(err, result, uplinkErrors) {
if (err) {
return options.callback(err);
}
(0, _utils.normalizeDistTags)((0, _storageUtils.cleanUpLinksRef)(options.keepUpLinkData, result)); // npm can throw if this field doesn't exist
result._attachments = {};
options.callback(null, result, uplinkErrors);
});
});
}
/**
Retrieve remote and local packages more recent than {startkey}
Function streams all packages from all uplinks first, and then
local packages.
Note that local packages could override registry ones just because
they appear in JSON last. That's a trade-off we make to avoid
memory issues.
Used storages: local && uplink (proxy_access)
* @param {*} startkey
* @param {*} options
* @return {Stream}
*/
search(startkey, options) {
const self = this; // stream to write a tarball
const stream = new _stream.default.PassThrough({
objectMode: true
});
_async.default.eachSeries(Object.keys(this.uplinks), function (up_name, cb) {
// shortcut: if `local=1` is supplied, don't call uplinks
if (options.req.query.local !== undefined) {
return cb();
} // search by keyword for each uplink
const lstream = self.uplinks[up_name].search(options); // join streams
lstream.pipe(stream, {
end: false
});
lstream.on('error', function (err) {
self.logger.error({
err: err
}, 'uplink error: @{err.message}');
cb();
cb = function () {};
});
lstream.on('end', function () {
cb();
cb = function () {};
});
stream.abort = function () {
if (lstream.abort) {
lstream.abort();
}
cb();
cb = function () {};
};
}, // executed after all series
function () {
// attach a local search results
const lstream = self.localStorage.search(startkey, options);
stream.abort = function () {
lstream.abort();
};
lstream.pipe(stream, {
end: true
});
lstream.on('error', function (err) {
self.logger.error({
err: err
}, 'search error: @{err.message}');
stream.end();
});
});
return stream;
}
/**
* Retrieve only private local packages
* @param {*} callback
*/
getLocalDatabase(callback) {
const self = this;
this.localStorage.storagePlugin.get((err, locals) => {
if (err) {
callback(err);
}
const packages = [];
const getPackage = function (itemPkg) {
self.localStorage.getPackageMetadata(locals[itemPkg], function (err, pkgMetadata) {
if (_lodash.default.isNil(err)) {
const latest = pkgMetadata[_constants.DIST_TAGS].latest;
if (latest && pkgMetadata.versions[latest]) {
const version = pkgMetadata.versions[latest];
const timeList = pkgMetadata.time;
const time = timeList[latest]; // @ts-ignore
version.time = time; // Add for stars api
// @ts-ignore
version.users = pkgMetadata.users;
packages.push(version);
} else {
self.logger.warn({
package: locals[itemPkg]
}, 'package @{package} does not have a "latest" tag?');
}
}
if (itemPkg >= locals.length - 1) {
callback(null, packages);
} else {
getPackage(itemPkg + 1);
}
});
};
if (locals.length) {
getPackage(0);
} else {
callback(null, []);
}
});
}
/**
* Function fetches package metadata from uplinks and synchronizes it with local data
if package is available locally, it MUST be provided in pkginfo
returns callback(err, result, uplink_errors)
*/
_syncUplinksMetadata(name, packageInfo, options, callback) {
let found = true;
const self = this;
const upLinks = [];
const hasToLookIntoUplinks = _lodash.default.isNil(options.uplinksLook) || options.uplinksLook;
if (!packageInfo) {
found = false;
packageInfo = (0, _storageUtils.generatePackageTemplate)(name);
}
for (const uplink in this.uplinks) {
if ((0, _configUtils.hasProxyTo)(name, uplink, this.config.packages) && hasToLookIntoUplinks) {
upLinks.push(this.uplinks[uplink]);
}
}
_async.default.map(upLinks, (upLink, cb) => {
const _options = Object.assign({}, options);
const upLinkMeta = packageInfo._uplinks[upLink.upname];
if ((0, _utils.isObject)(upLinkMeta)) {
const fetched = upLinkMeta.fetched;
if (fetched && Date.now() - fetched < upLink.maxage) {
return cb();
}
_options.etag = upLinkMeta.etag;
}
upLink.getRemoteMetadata(name, _options, (err, upLinkResponse, eTag) => {
if (err && err.remoteStatus === 304) {
upLinkMeta.fetched = Date.now();
}
if (err || !upLinkResponse) {
return cb(null, [err || _utils.ErrorCode.getInternalError('no data')]);
}
try {
(0, _utils.validateMetadata)(upLinkResponse, name);
} catch (err) {
self.logger.error({
sub: 'out',
err: err
}, 'package.json validating error @{!err.message}\n@{err.stack}');
return cb(null, [err]);
}
packageInfo._uplinks[upLink.upname] = {
etag: eTag,
fetched: Date.now()
};
packageInfo.time = (0, _storageUtils.mergeUplinkTimeIntoLocal)(packageInfo, upLinkResponse);
(0, _uplinkUtil.updateVersionsHiddenUpLink)(upLinkResponse.versions, upLink);
try {
(0, _metadataUtils.mergeVersions)(packageInfo, upLinkResponse);
} catch (err) {
self.logger.error({
sub: 'out',
err: err
}, 'package.json parsing error @{!err.message}\n@{err.stack}');
return cb(null, [err]);
} // if we got to this point, assume that the correct package exists
// on the uplink
found = true;
cb();
});
}, // @ts-ignore
(err, upLinksErrors) => {
(0, _assert.default)(!err && Array.isArray(upLinksErrors)); // Check for connection timeout or reset errors with uplink(s)
// (these should be handled differently from the package not being found)
if (!found) {
let uplinkTimeoutError;
for (let i = 0; i < upLinksErrors.length; i++) {
if (upLinksErrors[i]) {
for (let j = 0; j < upLinksErrors[i].length; j++) {
if (upLinksErrors[i][j]) {
const code = upLinksErrors[i][j].code;
if (code === 'ETIMEDOUT' || code === 'ESOCKETTIMEDOUT' || code === 'ECONNRESET') {
uplinkTimeoutError = true;
break;
}
}
}
}
}
if (uplinkTimeoutError) {
return callback(_utils.ErrorCode.getServiceUnavailable(), null, upLinksErrors);
}
return callback(_utils.ErrorCode.getNotFound(_constants.API_ERROR.NO_PACKAGE), null, upLinksErrors);
}
if (upLinks.length === 0) {
return callback(null, packageInfo);
}
self.localStorage.updateVersions(name, packageInfo, async (err, packageJsonLocal) => {
if (err) {
return callback(err);
} // Any error here will cause a 404, like an uplink error. This is likely the right thing to do
// as a broken filter is a security risk.
const filterErrors = []; // This MUST be done serially and not in parallel as they modify packageJsonLocal
for (const filter of self.filters) {
try {
// These filters can assume it's save to modify packageJsonLocal and return it directly for
// performance (i.e. need not be pure)
packageJsonLocal = await filter.filter_metadata(packageJsonLocal);
} catch (err) {
filterErrors.push(err);
}
}
callback(null, packageJsonLocal, _lodash.default.concat(upLinksErrors, filterErrors));
});
});
}
/**
* Set a hidden value for each version.
* @param {Array} versions list of version
* @param {String} upLink uplink name
* @private
*/
_updateVersionsHiddenUpLink(versions, upLink) {
for (const i in versions) {
if (Object.prototype.hasOwnProperty.call(versions, i)) {
const version = versions[i]; // holds a "hidden" value to be used by the package storage.
// $FlowFixMe
version[Symbol.for('__verdaccio_uplink')] = upLink.upname;
}
}
}
}
var _default = Storage;
exports.default = _default;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvc3RvcmFnZS50cyJdLCJuYW1lcyI6WyJTdG9yYWdlIiwiY29uc3RydWN0b3IiLCJjb25maWciLCJ1cGxpbmtzIiwibG9nZ2VyIiwiY2hpbGQiLCJmaWx0ZXJzIiwibG9jYWxTdG9yYWdlIiwiaW5pdCIsIkxvY2FsU3RvcmFnZSIsImdldFNlY3JldCIsImFkZFBhY2thZ2UiLCJuYW1lIiwibWV0YWRhdGEiLCJjYWxsYmFjayIsIl9pc0FsbG93UHVibGlzaE9mZmxpbmUiLCJfc3luY1VwbGlua3NNZXRhZGF0YSIsImJpbmQiLCJlcnIiLCJwdWJsaXNoIiwiXyIsImlzQm9vbGVhbiIsImFsbG93X29mZmxpbmUiLCJyZWFkVG9rZW5zIiwiZmlsdGVyIiwic2F2ZVRva2VuIiwidG9rZW4iLCJkZWxldGVUb2tlbiIsInVzZXIiLCJ0b2tlbktleSIsImFkZFZlcnNpb24iLCJ2ZXJzaW9uIiwidGFnIiwibWVyZ2VUYWdzIiwidGFnSGFzaCIsImNoYW5nZVBhY2thZ2UiLCJyZXZpc2lvbiIsInJlbW92ZVBhY2thZ2UiLCJTZWFyY2giLCJyZW1vdmUiLCJyZW1vdmVUYXJiYWxsIiwiZmlsZW5hbWUiLCJhZGRUYXJiYWxsIiwiZ2V0VGFyYmFsbCIsInJlYWRTdHJlYW0iLCJSZWFkVGFyYmFsbCIsImFib3J0Iiwic2VsZiIsImxvY2FsU3RyZWFtIiwiaXNPcGVuIiwib24iLCJzdGF0dXMiLCJIVFRQX1NUQVRVUyIsIk5PVF9GT1VORCIsImVtaXQiLCJlcnI0MDQiLCJnZXRQYWNrYWdlTWV0YWRhdGEiLCJpbmZvIiwiaXNOaWwiLCJfZGlzdGZpbGVzIiwic2VydmVGaWxlIiwidiIsInBpcGUiLCJmaWxlIiwidXBsaW5rIiwidXBsaW5rSWQiLCJwYWNrYWdlcyIsIlByb3h5U3RvcmFnZSIsInVybCIsImNhY2hlIiwiX2F1dG9nZW5lcmF0ZWQiLCJzYXZlc3RyZWFtIiwib25fb3BlbiIsInJzdHJlYW0yIiwiZmV0Y2hUYXJiYWxsIiwiZG9uZSIsIndhcm4iLCJmaWxlTmFtZSIsImdldFBhY2thZ2UiLCJvcHRpb25zIiwiZGF0YSIsIklOVEVSTkFMX0VSUk9SIiwicmVxIiwidXBsaW5rc0xvb2siLCJnZXRQYWNrYWdlU3luVXBMaW5rc0NhbGxiYWNrIiwicmVzdWx0IiwidXBsaW5rRXJyb3JzIiwia2VlcFVwTGlua0RhdGEiLCJfYXR0YWNobWVudHMiLCJzZWFyY2giLCJzdGFydGtleSIsInN0cmVhbSIsIlN0cmVhbSIsIlBhc3NUaHJvdWdoIiwib2JqZWN0TW9kZSIsImFzeW5jIiwiZWFjaFNlcmllcyIsIk9iamVjdCIsImtleXMiLCJ1cF9uYW1lIiwiY2IiLCJxdWVyeSIsImxvY2FsIiwidW5kZWZpbmVkIiwibHN0cmVhbSIsImVuZCIsImVycm9yIiwiZ2V0TG9jYWxEYXRhYmFzZSIsInN0b3JhZ2VQbHVnaW4iLCJnZXQiLCJsb2NhbHMiLCJpdGVtUGtnIiwicGtnTWV0YWRhdGEiLCJsYXRlc3QiLCJESVNUX1RBR1MiLCJ2ZXJzaW9ucyIsInRpbWVMaXN0IiwidGltZSIsInVzZXJzIiwicHVzaCIsInBhY2thZ2UiLCJsZW5ndGgiLCJwYWNrYWdlSW5mbyIsImZvdW5kIiwidXBMaW5rcyIsImhhc1RvTG9va0ludG9VcGxpbmtzIiwibWFwIiwidXBMaW5rIiwiX29wdGlvbnMiLCJhc3NpZ24iLCJ1cExpbmtNZXRhIiwiX3VwbGlua3MiLCJ1cG5hbWUiLCJmZXRjaGVkIiwiRGF0ZSIsIm5vdyIsIm1heGFnZSIsImV0YWciLCJnZXRSZW1vdGVNZXRhZGF0YSIsInVwTGlua1Jlc3BvbnNlIiwiZVRhZyIsInJlbW90ZVN0YXR1cyIsIkVycm9yQ29kZSIsImdldEludGVybmFsRXJyb3IiLCJzdWIiLCJ1cExpbmtzRXJyb3JzIiwiQXJyYXkiLCJpc0FycmF5IiwidXBsaW5rVGltZW91dEVycm9yIiwiaSIsImoiLCJjb2RlIiwiZ2V0U2VydmljZVVuYXZhaWxhYmxlIiwiZ2V0Tm90Rm91bmQiLCJBUElfRVJST1IiLCJOT19QQUNLQUdFIiwidXBkYXRlVmVyc2lvbnMiLCJwYWNrYWdlSnNvbkxvY2FsIiwiZmlsdGVyRXJyb3JzIiwiZmlsdGVyX21ldGFkYXRhIiwiY29uY2F0IiwiX3VwZGF0ZVZlcnNpb25zSGlkZGVuVXBMaW5rIiwicHJvdG90eXBlIiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiU3ltYm9sIiwiZm9yIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBeUJBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQVFBOztBQUNBOztBQUNBOztBQUNBOzs7Ozs7QUFFQSxNQUFNQSxPQUFOLENBQXlDO0FBT2hDQyxFQUFBQSxXQUFXLENBQUNDLE1BQUQsRUFBaUI7QUFBQTs7QUFBQTs7QUFBQTs7QUFBQTs7QUFBQTs7QUFDakMsU0FBS0EsTUFBTCxHQUFjQSxNQUFkO0FBQ0EsU0FBS0MsT0FBTCxHQUFlLDhCQUFhRCxNQUFiLENBQWY7QUFDQSxTQUFLRSxNQUFMLEdBQWNBLGVBQU9DLEtBQVAsRUFBZDtBQUNBLFNBQUtDLE9BQUwsR0FBZSxFQUFmLENBSmlDLENBS2pDOztBQUNBLFNBQUtDLFlBQUwsR0FBb0IsSUFBcEI7QUFDRDs7QUFFTUMsRUFBQUEsSUFBSSxDQUFDTixNQUFELEVBQWlCSSxPQUF1QixHQUFHLEVBQTNDLEVBQWdFO0FBQ3pFLFNBQUtBLE9BQUwsR0FBZUEsT0FBZjtBQUNBLFNBQUtDLFlBQUwsR0FBb0IsSUFBSUUscUJBQUosQ0FBaUIsS0FBS1AsTUFBdEIsRUFBOEJFLGNBQTlCLENBQXBCO0FBRUEsV0FBTyxLQUFLRyxZQUFMLENBQWtCRyxTQUFsQixDQUE0QlIsTUFBNUIsQ0FBUDtBQUNEO0FBRUQ7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDeUIsUUFBVlMsVUFBVSxDQUFDQyxJQUFELEVBQWVDLFFBQWYsRUFBOEJDLFFBQTlCLEVBQWlFO0FBQ3RGLFFBQUk7QUFDRixZQUFNLHFDQUFrQkYsSUFBbEIsRUFBd0IsS0FBS0wsWUFBN0IsQ0FBTjtBQUNBLFlBQU0sc0NB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QUFDa0MsQ0FBRCxDQUF4QixDQURxRCxDQUdyRDtBQUNBOztBQUNBdEgsUUFBQUEsT0FBTyxDQUFDc0ksTUFBTSxDQUFDQyxHQUFQLENBQVcsb0JBQVgsQ0FBRCxDQUFQLEdBQTRDdkMsTUFBTSxDQUFDSyxNQUFuRDtBQUNEO0FBQ0Y7QUFDRjs7QUFsbEJzQzs7ZUFxbEIxQnBJLE8iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgU3RyZWFtIGZyb20gJ3N0cmVhbSc7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IGFzeW5jLCB7IEFzeW5jUmVzdWx0QXJyYXlDYWxsYmFjayB9IGZyb20gJ2FzeW5jJztcbmltcG9ydCB7IFJlYWRUYXJiYWxsIH0gZnJvbSAnQHZlcmRhY2Npby9zdHJlYW1zJztcbmltcG9ydCB7XG4gIElSZWFkVGFyYmFsbCxcbiAgSVVwbG9hZFRhcmJhbGwsXG4gIFZlcnNpb25zLFxuICBQYWNrYWdlLFxuICBDb25maWcsXG4gIE1lcmdlVGFncyxcbiAgVmVyc2lvbixcbiAgRGlzdEZpbGUsXG4gIENhbGxiYWNrLFxuICBMb2dnZXJcbn0gZnJvbSAnQHZlcmRhY2Npby90eXBlcyc7XG5pbXBvcnQgeyBHZW5lcmljQm9keSwgVG9rZW5GaWx0ZXIsIFRva2VuIH0gZnJvbSAnQHZlcmRhY2Npby90eXBlcyc7XG5pbXBvcnQgeyBWZXJkYWNjaW9FcnJvciB9IGZyb20gJ0B2ZXJkYWNjaW8vY29tbW9ucy1hcGknO1xuaW1wb3J0IHtcbiAgSVN0b3JhZ2UsXG4gIElQcm94eSxcbiAgSVN0b3JhZ2VIYW5kbGVyLFxuICBQcm94eUxpc3QsXG4gIFN0cmluZ1ZhbHVlLFxuICBJR2V0UGFja2FnZU9wdGlvbnMsXG4gIElTeW5jVXBsaW5rcyxcbiAgSVBsdWdpbkZpbHRlcnNcbn0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi4vbGliL2xvZ2dlcic7XG5pbXBvcnQgUHJveHlTdG9yYWdlIGZyb20gJy4vdXAtc3RvcmFnZSc7XG5pbXBvcnQgU2VhcmNoIGZyb20gJy4vc2VhcmNoJztcbmltcG9ydCB7IEFQSV9FUlJPUiwgSFRUUF9TVEFUVVMsIERJU1RfVEFHUyB9IGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCBMb2NhbFN0b3JhZ2UgZnJvbSAnLi9sb2NhbC1zdG9yYWdlJztcbmltcG9ydCB7XG4gIGNoZWNrUGFja2FnZUxvY2FsLFxuICBwdWJsaXNoUGFja2FnZSxcbiAgY2hlY2tQYWNrYWdlUmVtb3RlLFxuICBjbGVhblVwTGlua3NSZWYsXG4gIG1lcmdlVXBsaW5rVGltZUludG9Mb2NhbCxcbiAgZ2VuZXJhdGVQYWNrYWdlVGVtcGxhdGVcbn0gZnJvbSAnLi9zdG9yYWdlLXV0aWxzJztcbmltcG9ydCB7IHNldHVwVXBMaW5rcywgdXBkYXRlVmVyc2lvbnNIaWRkZW5VcExpbmsgfSBmcm9tICcuL3VwbGluay11dGlsJztcbmltcG9ydCB7IG1lcmdlVmVyc2lvbnMgfSBmcm9tICcuL21ldGFkYXRhLXV0aWxzJztcbmltcG9ydCB7IEVycm9yQ29kZSwgbm9ybWFsaXplRGlzdFRhZ3MsIHZhbGlkYXRlTWV0YWRhdGEsIGlzT2JqZWN0IH0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQgeyBoYXNQcm94eVRvIH0gZnJvbSAnLi9jb25maWctdXRpbHMnO1xuXG5jbGFzcyBTdG9yYWdlIGltcGxlbWVudHMgSVN0b3JhZ2VIYW5kbGVyIHtcbiAgcHVibGljIGxvY2FsU3RvcmFnZTogSVN0b3JhZ2U7XG4gIHB1YmxpYyBjb25maWc6IENvbmZpZztcbiAgcHVibGljIGxvZ2dlcjogTG9nZ2VyO1xuICBwdWJsaWMgdXBsaW5rczogUHJveHlMaXN0O1xuICBwdWJsaWMgZmlsdGVyczogSVBsdWdpbkZpbHRlcnM7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKGNvbmZpZzogQ29uZmlnKSB7XG4gICAgdGhpcy5jb25maWcgPSBjb25maWc7XG4gICAgdGhpcy51cGxpbmtzID0gc2V0dXBVcExpbmtzKGNvbmZpZyk7XG4gICAgdGhpcy5sb2dnZXIgPSBsb2dnZXIuY2hpbGQoKTtcbiAgICB0aGlzLmZpbHRlcnMgPSBbXTtcbiAgICAvLyBAdHMtaWdub3JlXG4gICAgdGhpcy5sb2NhbFN0b3JhZ2UgPSBudWxsO1xuICB9XG5cbiAgcHVibGljIGluaXQoY29uZmlnOiBDb25maWcsIGZpbHRlcnM6IElQbHVnaW5GaWx0ZXJzID0gW10pOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHRoaXMuZmlsdGVycyA9IGZpbHRlcnM7XG4gICAgdGhpcy5sb2NhbFN0b3JhZ2UgPSBuZXcgTG9jYWxTdG9yYWdlKHRoaXMuY29uZmlnLCBsb2dnZXIpO1xuXG4gICAgcmV0dXJuIHRoaXMubG9jYWxTdG9yYWdlLmdldFNlY3JldChjb25maWcpO1xuICB9XG5cbiAgLyoqXG4gICAqICBBZGQgYSB7bmFtZX0gcGFja2FnZSB0byBhIHN5c3RlbVxuICAgRnVuY3Rpb24gY2hlY2tzIGlmIHBhY2thZ2Ugd2l0aCB0aGUgc2FtZSBuYW1lIGlzIGF2YWlsYWJsZSBmcm9tIHVwbGlua3MuXG4gICBJZiBpdCBpc24ndCwgd2UgY3JlYXRlIHBhY2thZ2UgbG9jYWxseVxuICAgVXNlZCBzdG9yYWdlczogbG9jYWwgKHdyaXRlKSAmJiB1cGxpbmtzXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgYWRkUGFja2FnZShuYW1lOiBzdHJpbmcsIG1ldGFkYXRhOiBhbnksIGNhbGxiYWNrOiBGdW5jdGlvbik6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBjaGVja1BhY2thZ2VMb2NhbChuYW1lLCB0aGlzLmxvY2FsU3RvcmFnZSk7XG4gICAgICBhd2FpdCBjaGVja1BhY2thZ2VSZW1vdGUoXG4gICAgICAgIG5hbWUsXG4gICAgICAgIHRoaXMuX2lzQWxsb3dQdWJsaXNoT2ZmbGluZSgpLFxuICAgICAgICB0aGlzLl9zeW5jVXBsaW5rc01ldGFkYXRhLmJpbmQodGhpcylcbiAgICAgICk7XG4gICAgICBhd2FpdCBwdWJsaXNoUGFja2FnZShuYW1lLCBtZXRhZGF0YSwgdGhpcy5sb2NhbFN0b3JhZ2UgYXMgSVN0b3JhZ2UpO1xuICAgICAgY2FsbGJhY2soKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfaXNBbGxvd1B1Ymxpc2hPZmZsaW5lKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAoXG4gICAgICB0eXBlb2YgdGhpcy5jb25maWcucHVibGlzaCAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIF8uaXNCb29sZWFuKHRoaXMuY29uZmlnLnB1Ymxpc2guYWxsb3dfb2ZmbGluZSkgJiZcbiAgICAgIHRoaXMuY29uZmlnLnB1Ymxpc2guYWxsb3dfb2ZmbGluZVxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgcmVhZFRva2VucyhmaWx0ZXI6IFRva2VuRmlsdGVyKTogUHJvbWlzZTxUb2tlbltdPiB7XG4gICAgcmV0dXJuIHRoaXMubG9jYWxTdG9yYWdlLnJlYWRUb2tlbnMoZmlsdGVyKTtcbiAgfVxuXG4gIHB1YmxpYyBzYXZlVG9rZW4odG9rZW46IFRva2VuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMubG9jYWxTdG9yYWdlLnNhdmVUb2tlbih0b2tlbik7XG4gIH1cblxuICBwdWJsaWMgZGVsZXRlVG9rZW4odXNlcjogc3RyaW5nLCB0b2tlbktleTogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5sb2NhbFN0b3JhZ2UuZGVsZXRlVG9rZW4odXNlciwgdG9rZW5LZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIG5ldyB2ZXJzaW9uIG9mIHBhY2thZ2Uge25hbWV9IHRvIGEgc3lzdGVtXG4gICBVc2VkIHN0b3JhZ2VzOiBsb2NhbCAod3JpdGUpXG4gICAqL1xuICBwdWJsaWMgYWRkVmVyc2lvbihcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgdmVyc2lvbjogc3RyaW5nLFxuICAgIG1ldGFkYXRhOiBWZXJzaW9uLFxuICAgIHRhZzogU3RyaW5nVmFsdWUsXG4gICAgY2FsbGJhY2s6IENhbGxiYWNrXG4gICk6IHZvaWQge1xuICAgIHRoaXMubG9jYWxTdG9yYWdlLmFkZFZlcnNpb24obmFtZSwgdmVyc2lvbiwgbWV0YWRhdGEsIHRhZywgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFRhZ3MgYSBwYWNrYWdlIHZlcnNpb24gd2l0aCBhIHByb3ZpZGVkIHRhZ1xuICAgVXNlZCBzdG9yYWdlczogbG9jYWwgKHdyaXRlKVxuICAgKi9cbiAgcHVibGljIG1lcmdlVGFncyhuYW1lOiBzdHJpbmcsIHRhZ0hhc2g6IE1lcmdlVGFncywgY2FsbGJhY2s6IENhbGxiYWNrKTogdm9pZCB7XG4gICAgdGhpcy5sb2NhbFN0b3JhZ2UubWVyZ2VUYWdzKG5hbWUsIHRhZ0hhc2gsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGFuZ2UgYW4gZXhpc3RpbmcgcGFja2FnZSAoaS5lLiB1bnB1Ymxpc2ggb25lIHZlcnNpb24pXG4gICBGdW5jdGlvbiBjaGFuZ2VzIGEgcGFja2FnZSBpbmZvIGZyb20gbG9jYWwgc3RvcmFnZSBhbmQgYWxsIHVwbGlua3Mgd2l0aCB3cml0ZSBhY2Nlc3MuL1xuICAgVXNlZCBzdG9yYWdlczogbG9jYWwgKHdyaXRlKVxuICAgKi9cbiAgcHVibGljIGNoYW5nZVBhY2thZ2UoXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIG1ldGFkYXRhOiBQYWNrYWdlLFxuICAgIHJldmlzaW9uOiBzdHJpbmcsXG4gICAgY2FsbGJhY2s6IENhbGxiYWNrXG4gICk6IHZvaWQge1xuICAgIHRoaXMubG9jYWxTdG9yYWdlLmNoYW5nZVBhY2thZ2UobmFtZSwgbWV0YWRhdGEsIHJldmlzaW9uLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIGEgcGFja2FnZSBmcm9tIGEgc3lzdGVtXG4gICBGdW5jdGlvbiByZW1vdmVzIGEgcGFja2FnZSBmcm9tIGxvY2FsIHN0b3JhZ2VcbiAgIFVzZWQgc3RvcmFnZXM6IGxvY2FsICh3cml0ZSlcbiAgICovXG4gIHB1YmxpYyByZW1vdmVQYWNrYWdlKG5hbWU6IHN0cmluZywgY2FsbGJhY2s6IENhbGxiYWNrKTogdm9pZCB7XG4gICAgdGhpcy5sb2NhbFN0b3JhZ2UucmVtb3ZlUGFja2FnZShuYW1lLCBjYWxsYmFjayk7XG4gICAgLy8gdXBkYXRlIHRoZSBpbmRleGVyXG4gICAgU2VhcmNoLnJlbW92ZShuYW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgUmVtb3ZlIGEgdGFyYmFsbCBmcm9tIGEgc3lzdGVtXG4gICBGdW5jdGlvbiByZW1vdmVzIGEgdGFyYmFsbCBmcm9tIGxvY2FsIHN0b3JhZ2UuXG4gICBUYXJiYWxsIGluIHF1ZXN0aW9uIHNob3VsZCBub3QgYmUgbGlua2VkIHRvIGluIGFueSBleGlzdGluZ1xuICAgdmVyc2lvbnMsIGkuZS4gcGFja2FnZSB2ZXJzaW9uIHNob3VsZCBiZSB1bnB1Ymxpc2hlZCBmaXJzdC5cbiAgIFVzZWQgc3RvcmFnZTogbG9jYWwgKHdyaXRlKVxuICAgKi9cbiAgcHVibGljIHJlbW92ZVRhcmJhbGwobmFtZTogc3RyaW5nLCBmaWxlbmFtZTogc3RyaW5nLCByZXZpc2lvbjogc3RyaW5nLCBjYWxsYmFjazogQ2FsbGJhY2spOiB2b2lkIHtcbiAgICB0aGlzLmxvY2FsU3RvcmFnZS5yZW1vdmVUYXJiYWxsKG5hbWUsIGZpbGVuYW1lLCByZXZpc2lvbiwgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwbG9hZCBhIHRhcmJhbGwgZm9yIHtuYW1lfSBwYWNrYWdlXG4gICBGdW5jdGlvbiBpcyBzeW5jaHJvbm91cyBhbmQgcmV0dXJucyBhIFdyaXRhYmxlU3RyZWFtXG4gICBVc2VkIHN0b3JhZ2VzOiBsb2NhbCAod3JpdGUpXG4gICAqL1xuICBwdWJsaWMgYWRkVGFyYmFsbChuYW1lOiBzdHJpbmcsIGZpbGVuYW1lOiBzdHJpbmcpOiBJVXBsb2FkVGFyYmFsbCB7XG4gICAgcmV0dXJuIHRoaXMubG9jYWxTdG9yYWdlLmFkZFRhcmJhbGwobmFtZSwgZmlsZW5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICBHZXQgYSB0YXJiYWxsIGZyb20gYSBzdG9yYWdlIGZvciB7bmFtZX0gcGFja2FnZVxuICAgRnVuY3Rpb24gaXMgc3luY2hyb25vdXMgYW5kIHJldHVybnMgYSBSZWFkYWJsZVN0cmVhbVxuICAgRnVuY3Rpb24gdHJpZXMgdG8gcmVhZCB0YXJiYWxsIGxvY2FsbHksIGlmIGl0IGZhaWxzIHRoZW4gaXQgcmVhZHMgcGFja2FnZVxuICAgaW5mb3JtYXRpb24gaW4gb3JkZXIgdG8gZmlndXJlIG91dCB3aGVyZSB3ZSBjYW4gZ2V0IHRoaXMgdGFyYmFsbCBmcm9tXG4gICBVc2VkIHN0b3JhZ2VzOiBsb2NhbCB8fCB1cGxpbmsgKGp1c3Qgb25lKVxuICAgKi9cbiAgcHVibGljIGdldFRhcmJhbGwobmFtZTogc3RyaW5nLCBmaWxlbmFtZTogc3RyaW5nKTogSVJlYWRUYXJiYWxsIHtcbiAgICBjb25zdCByZWFkU3RyZWFtID0gbmV3IFJlYWRUYXJiYWxsKHt9KTtcbiAgICByZWFkU3RyZWFtLmFib3J0ID0gZnVuY3Rpb24gKCkge307XG5cbiAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgIC8vIGlmIHNvbWVvbmUgcmVxdWVzdGluZyB0YXJiYWxsLCBpdCBtZWFucyB0aGF0IHdlIHNob3VsZCBhbHJlYWR5IGhhdmUgc29tZVxuICAgIC8vIGluZm9ybWF0aW9uIGFib3V0IGl0LCBzbyBmZXRjaGluZyBwYWNrYWdlIGluZm8gaXMgdW5uZWNlc3NhcnlcblxuICAgIC8vIHRyeWluZyBsb2NhbCBmaXJzdFxuICAgIC8vIGZsb3c6IHNob3VsZCBiZSBJUmVhZFRhcmJhbGxcbiAgICBsZXQgbG9jYWxTdHJlYW06IGFueSA9IHNlbGYubG9jYWxTdG9yYWdlLmdldFRhcmJhbGwobmFtZSwgZmlsZW5hbWUpO1xuICAgIGxldCBpc09wZW4gPSBmYWxzZTtcbiAgICBsb2NhbFN0cmVhbS5vbignZXJyb3InLCAoZXJyKTogYW55ID0+IHtcbiAgICAgIGlmIChpc09wZW4gfHwgZXJyLnN0YXR1cyAhPT0gSFRUUF9TVEFUVVMuTk9UX0ZPVU5EKSB7XG4gICAgICAgIHJldHVybiByZWFkU3RyZWFtLmVtaXQoJ2Vycm9yJywgZXJyKTtcbiAgICAgIH1cblxuICAgICAgLy8gbG9jYWwgcmVwb3J0ZWQgNDA0XG4gICAgICBjb25zdCBlcnI0MDQgPSBlcnI7XG4gICAgICBsb2NhbFN0cmVhbS5hYm9ydCgpO1xuICAgICAgbG9jYWxTdHJlYW0gPSBudWxsOyAvLyB3ZSBmb3JjZSBmb3IgZ2FyYmFnZSBjb2xsZWN0b3JcbiAgICAgIHNlbGYubG9jYWxTdG9yYWdlLmdldFBhY2thZ2VNZXRhZGF0YShuYW1lLCAoZXJyLCBpbmZvOiBQYWNrYWdlKTogdm9pZCA9PiB7XG4gICAgICAgIGlmIChfLmlzTmlsKGVycikgJiYgaW5mby5fZGlzdGZpbGVzICYmIF8uaXNOaWwoaW5mby5fZGlzdGZpbGVzW2ZpbGVuYW1lXSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgLy8gaW5mb3JtYXRpb24gYWJvdXQgdGhpcyBmaWxlIGV4aXN0cyBsb2NhbGx5XG4gICAgICAgICAgc2VydmVGaWxlKGluZm8uX2Rpc3RmaWxlc1tmaWxlbmFtZV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIHdlIGtub3cgbm90aGluZyBhYm91dCB0aGlzIGZpbGUsIHRyeWluZyB0byBnZXQgaW5mb3JtYXRpb24gZWxzZXdoZXJlXG4gICAgICAgICAgc2VsZi5fc3luY1VwbGlua3NNZXRhZGF0YShuYW1lLCBpbmZvLCB7fSwgKGVyciwgaW5mbzogUGFja2FnZSk6IGFueSA9PiB7XG4gICAgICAgICAgICBpZiAoXy5pc05pbChlcnIpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICByZXR1cm4gcmVhZFN0cmVhbS5lbWl0KCdlcnJvcicsIGVycik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoXy5pc05pbChpbmZvLl9kaXN0ZmlsZXMpIHx8IF8uaXNOaWwoaW5mby5fZGlzdGZpbGVzW2ZpbGVuYW1lXSkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlYWRTdHJlYW0uZW1pdCgnZXJyb3InLCBlcnI0MDQpO1xuICAgICAgICAg