@verdaccio/canary 6.3.2-canary.404363f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +38 -0
- package/bin/verdaccio +3 -0
- package/bin/verdaccio-canary +3 -0
- package/build/api/debug/index.js +28 -0
- package/build/api/endpoint/api/dist-tags.js +77 -0
- package/build/api/endpoint/api/package.js +103 -0
- package/build/api/endpoint/api/ping.js +13 -0
- package/build/api/endpoint/api/publish.js +359 -0
- package/build/api/endpoint/api/search.js +107 -0
- package/build/api/endpoint/api/star.js +73 -0
- package/build/api/endpoint/api/stars.js +42 -0
- package/build/api/endpoint/api/user.js +84 -0
- package/build/api/endpoint/api/v1/profile.js +69 -0
- package/build/api/endpoint/api/v1/search.js +181 -0
- package/build/api/endpoint/api/v1/token.js +140 -0
- package/build/api/endpoint/api/whoami.js +15 -0
- package/build/api/endpoint/index.js +58 -0
- package/build/api/index.js +105 -0
- package/build/api/middleware.js +56 -0
- package/build/api/web/api/index.js +31 -0
- package/build/api/web/api/package.js +165 -0
- package/build/api/web/api/search.js +53 -0
- package/build/api/web/api/user.js +70 -0
- package/build/api/web/api/utils.js +14 -0
- package/build/api/web/html/favicon.ico +0 -0
- package/build/api/web/index.js +96 -0
- package/build/index.js +76 -0
- package/build/lib/auth-utils.js +16 -0
- package/build/lib/bootstrap.js +167 -0
- package/build/lib/cli/cli.js +26 -0
- package/build/lib/cli/commands/info.js +26 -0
- package/build/lib/cli/commands/init.js +78 -0
- package/build/lib/cli/commands/version.js +17 -0
- package/build/lib/cli/utils.js +14 -0
- package/build/lib/cli.js +16 -0
- package/build/lib/config.js +22 -0
- package/build/lib/constants.js +121 -0
- package/build/lib/experiments.js +29 -0
- package/build/lib/local-storage.js +760 -0
- package/build/lib/logger/index.js +21 -0
- package/build/lib/metadata-utils.js +39 -0
- package/build/lib/run-server.js +122 -0
- package/build/lib/storage-utils.js +282 -0
- package/build/lib/storage.js +676 -0
- package/build/lib/up-storage.js +605 -0
- package/build/lib/uplink-util.js +36 -0
- package/build/lib/utils.js +265 -0
- package/conf/.gitkeep +0 -0
- package/index.js +1 -0
- package/package.json +156 -0
- package/security.txt +5 -0
- package/systemd/verdaccio.service +11 -0
|
@@ -0,0 +1,676 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _assert = _interopRequireDefault(require("assert"));
|
|
8
|
+
var _async = _interopRequireDefault(require("async"));
|
|
9
|
+
var _debug = _interopRequireDefault(require("debug"));
|
|
10
|
+
var _lodash = _interopRequireDefault(require("lodash"));
|
|
11
|
+
var _stream = _interopRequireDefault(require("stream"));
|
|
12
|
+
var _config = require("@verdaccio/config");
|
|
13
|
+
var _core = require("@verdaccio/core");
|
|
14
|
+
var _loaders = require("@verdaccio/loaders");
|
|
15
|
+
var _localStorageLegacy = _interopRequireDefault(require("@verdaccio/local-storage-legacy"));
|
|
16
|
+
var _searchIndexer = require("@verdaccio/search-indexer");
|
|
17
|
+
var _streams = require("@verdaccio/streams");
|
|
18
|
+
var _logger = require("../lib/logger");
|
|
19
|
+
var _constants = require("./constants");
|
|
20
|
+
var _localStorage = _interopRequireDefault(require("./local-storage"));
|
|
21
|
+
var _metadataUtils = require("./metadata-utils");
|
|
22
|
+
var _storageUtils = require("./storage-utils");
|
|
23
|
+
var _upStorage = _interopRequireDefault(require("./up-storage"));
|
|
24
|
+
var _uplinkUtil = require("./uplink-util");
|
|
25
|
+
var _utils = require("./utils");
|
|
26
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
27
|
+
const debug = (0, _debug.default)('verdaccio:storage');
|
|
28
|
+
class Storage {
|
|
29
|
+
constructor(config) {
|
|
30
|
+
this.config = config;
|
|
31
|
+
this.uplinks = (0, _uplinkUtil.setupUpLinks)(config);
|
|
32
|
+
this.logger = _logger.logger;
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
34
|
+
// @ts-ignore
|
|
35
|
+
this.localStorage = null;
|
|
36
|
+
}
|
|
37
|
+
async init(config, filters) {
|
|
38
|
+
if (this.localStorage === null) {
|
|
39
|
+
this.filters = filters;
|
|
40
|
+
const storageInstance = await this.loadStorage(config, this.logger);
|
|
41
|
+
this.localStorage = new _localStorage.default(this.config, _logger.logger, storageInstance);
|
|
42
|
+
await this.localStorage.getSecret(config);
|
|
43
|
+
debug('initialization completed');
|
|
44
|
+
} else {
|
|
45
|
+
debug('storage has been already initialized');
|
|
46
|
+
}
|
|
47
|
+
if (!this.filters) {
|
|
48
|
+
this.filters = await (0, _loaders.asyncLoadPlugin)(this.config.filters, {
|
|
49
|
+
config: this.config,
|
|
50
|
+
logger: this.logger
|
|
51
|
+
}, plugin => {
|
|
52
|
+
return typeof plugin.filter_metadata !== 'undefined';
|
|
53
|
+
}, true, this.config?.serverSettings?.pluginPrefix, _core.PLUGIN_CATEGORY.FILTER);
|
|
54
|
+
debug('filters available %o', this.filters.length);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async loadStorage(config, logger) {
|
|
58
|
+
const Storage = await this.loadStorePlugin();
|
|
59
|
+
if (_lodash.default.isNil(Storage)) {
|
|
60
|
+
(0, _assert.default)(this.config.storage, 'CONFIG: storage path not defined');
|
|
61
|
+
debug('no custom storage found, loading default storage @verdaccio/local-storage');
|
|
62
|
+
const localStorage = new _localStorageLegacy.default(config, logger);
|
|
63
|
+
logger.info({
|
|
64
|
+
name: '@verdaccio/local-storage',
|
|
65
|
+
pluginCategory: _core.PLUGIN_CATEGORY.STORAGE
|
|
66
|
+
}, 'plugin @{name} successfully loaded (@{pluginCategory})');
|
|
67
|
+
return localStorage;
|
|
68
|
+
}
|
|
69
|
+
return Storage;
|
|
70
|
+
}
|
|
71
|
+
async loadStorePlugin() {
|
|
72
|
+
const plugins = await (0, _loaders.asyncLoadPlugin)(this.config.store, {
|
|
73
|
+
config: this.config,
|
|
74
|
+
logger: this.logger
|
|
75
|
+
}, plugin => {
|
|
76
|
+
return typeof plugin.getPackageStorage !== 'undefined';
|
|
77
|
+
}, true, this.config?.serverSettings?.pluginPrefix, _core.PLUGIN_CATEGORY.STORAGE);
|
|
78
|
+
if (plugins.length > 1) {
|
|
79
|
+
this.logger.warn('more than one storage plugins has been detected, multiple storage are not supported, one will be selected automatically');
|
|
80
|
+
}
|
|
81
|
+
return _lodash.default.head(plugins);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Add a {name} package to a system
|
|
86
|
+
Function checks if package with the same name is available from uplinks.
|
|
87
|
+
If it isn't, we create package locally
|
|
88
|
+
Used storages: local (write) && uplinks
|
|
89
|
+
*/
|
|
90
|
+
async addPackage(name, metadata, callback) {
|
|
91
|
+
try {
|
|
92
|
+
await (0, _storageUtils.checkPackageLocal)(name, this.localStorage);
|
|
93
|
+
await (0, _storageUtils.checkPackageRemote)(name, this._isAllowPublishOffline(), this._syncUplinksMetadata.bind(this));
|
|
94
|
+
await (0, _storageUtils.publishPackage)(name, metadata, this.localStorage);
|
|
95
|
+
callback();
|
|
96
|
+
} catch (err) {
|
|
97
|
+
callback(err);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
_isAllowPublishOffline() {
|
|
101
|
+
return typeof this.config.publish !== 'undefined' && _lodash.default.isBoolean(this.config.publish.allow_offline) && this.config.publish.allow_offline;
|
|
102
|
+
}
|
|
103
|
+
readTokens(filter) {
|
|
104
|
+
return this.localStorage.readTokens(filter);
|
|
105
|
+
}
|
|
106
|
+
saveToken(token) {
|
|
107
|
+
return this.localStorage.saveToken(token);
|
|
108
|
+
}
|
|
109
|
+
deleteToken(user, tokenKey) {
|
|
110
|
+
return this.localStorage.deleteToken(user, tokenKey);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Add a new version of package {name} to a system
|
|
115
|
+
Used storages: local (write)
|
|
116
|
+
*/
|
|
117
|
+
addVersion(name, version, metadata, tag, callback) {
|
|
118
|
+
this.localStorage.addVersion(name, version, metadata, tag, callback);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Tags a package version with a provided tag
|
|
123
|
+
Used storages: local (write)
|
|
124
|
+
*/
|
|
125
|
+
mergeTags(name, tagHash, callback) {
|
|
126
|
+
this.localStorage.mergeTags(name, tagHash, callback);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Change an existing package (i.e. unpublish one version)
|
|
131
|
+
Function changes a package info from local storage and all uplinks with write access./
|
|
132
|
+
Used storages: local (write)
|
|
133
|
+
*/
|
|
134
|
+
changePackage(name, metadata, revision, callback) {
|
|
135
|
+
this.localStorage.changePackage(name, metadata, revision, callback);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Remove a package from a system
|
|
140
|
+
Function removes a package from local storage
|
|
141
|
+
Used storages: local (write)
|
|
142
|
+
*/
|
|
143
|
+
removePackage(name, callback) {
|
|
144
|
+
this.localStorage.removePackage(name, callback);
|
|
145
|
+
// update the indexer
|
|
146
|
+
_searchIndexer.SearchMemoryIndexer.remove(name).catch(reason => {
|
|
147
|
+
debug('indexer has failed on remove item %o', reason);
|
|
148
|
+
_logger.logger.error('indexer has failed on remove item');
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
Remove a tarball from a system
|
|
154
|
+
Function removes a tarball from local storage.
|
|
155
|
+
Tarball in question should not be linked to in any existing
|
|
156
|
+
versions, i.e. package version should be unpublished first.
|
|
157
|
+
Used storage: local (write)
|
|
158
|
+
*/
|
|
159
|
+
removeTarball(name, filename, revision, callback) {
|
|
160
|
+
this.localStorage.removeTarball(name, filename, revision, callback);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Upload a tarball for {name} package
|
|
165
|
+
Function is synchronous and returns a WritableStream
|
|
166
|
+
Used storages: local (write)
|
|
167
|
+
*/
|
|
168
|
+
addTarball(name, filename) {
|
|
169
|
+
return this.localStorage.addTarball(name, filename);
|
|
170
|
+
}
|
|
171
|
+
hasLocalTarball(name, filename) {
|
|
172
|
+
const self = this;
|
|
173
|
+
return new Promise((resolve, reject) => {
|
|
174
|
+
let localStream = self.localStorage.getTarball(name, filename);
|
|
175
|
+
let isOpen = false;
|
|
176
|
+
localStream.on('error', err => {
|
|
177
|
+
if (isOpen || err.status !== _constants.HTTP_STATUS.NOT_FOUND) {
|
|
178
|
+
reject(err);
|
|
179
|
+
}
|
|
180
|
+
// local reported 404 or request was aborted already
|
|
181
|
+
if (localStream) {
|
|
182
|
+
localStream.abort();
|
|
183
|
+
localStream = null;
|
|
184
|
+
}
|
|
185
|
+
resolve(false);
|
|
186
|
+
});
|
|
187
|
+
localStream.on('open', function () {
|
|
188
|
+
isOpen = true;
|
|
189
|
+
localStream.abort();
|
|
190
|
+
localStream = null;
|
|
191
|
+
resolve(true);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
Get a tarball from a storage for {name} package
|
|
198
|
+
Function is synchronous and returns a ReadableStream
|
|
199
|
+
Function tries to read tarball locally, if it fails then it reads package
|
|
200
|
+
information in order to figure out where we can get this tarball from
|
|
201
|
+
Used storages: local || uplink (just one)
|
|
202
|
+
*/
|
|
203
|
+
getTarball(name, filename) {
|
|
204
|
+
const readStream = new _streams.ReadTarball({});
|
|
205
|
+
readStream.abort = function () {};
|
|
206
|
+
const self = this;
|
|
207
|
+
|
|
208
|
+
// Check if the tarball is allowed by filter plugins before serving.
|
|
209
|
+
// Filters may block specific versions, so we verify the tarball's version
|
|
210
|
+
// still exists in the filtered metadata.
|
|
211
|
+
this._isTarballAllowedByFilters(name, filename).then(async allowed => {
|
|
212
|
+
if (!allowed) {
|
|
213
|
+
readStream.emit('error', _utils.ErrorCode.getNotFound(_constants.API_ERROR.NO_PACKAGE));
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// trying local first
|
|
218
|
+
let localStream = self.localStorage.getTarball(name, filename);
|
|
219
|
+
let isOpen = false;
|
|
220
|
+
localStream.on('error', err => {
|
|
221
|
+
if (isOpen || err.status !== _constants.HTTP_STATUS.NOT_FOUND) {
|
|
222
|
+
return readStream.emit('error', err);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// local reported 404
|
|
226
|
+
const err404 = err;
|
|
227
|
+
localStream.abort();
|
|
228
|
+
localStream = null; // we force for garbage collector
|
|
229
|
+
|
|
230
|
+
const lookupFromUplinks = info => {
|
|
231
|
+
self._syncUplinksMetadata(name, info, {}, (syncErr, syncInfo) => {
|
|
232
|
+
if (_lodash.default.isNil(syncErr) === false) {
|
|
233
|
+
return readStream.emit('error', syncErr);
|
|
234
|
+
}
|
|
235
|
+
if (_lodash.default.isNil(syncInfo._distfiles) || _lodash.default.isNil(syncInfo._distfiles[filename])) {
|
|
236
|
+
return readStream.emit('error', err404);
|
|
237
|
+
}
|
|
238
|
+
serveFile(syncInfo._distfiles[filename]);
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
self.localStorage.getPackageMetadataAsync(name).then(info => {
|
|
242
|
+
if (info._distfiles && _lodash.default.isNil(info._distfiles[filename]) === false) {
|
|
243
|
+
// information about this file exists locally
|
|
244
|
+
serveFile(info._distfiles[filename]);
|
|
245
|
+
} else {
|
|
246
|
+
// we know nothing about this file, trying to get information elsewhere
|
|
247
|
+
lookupFromUplinks(info);
|
|
248
|
+
}
|
|
249
|
+
}, () => {
|
|
250
|
+
// we know nothing about this file, trying to get information elsewhere
|
|
251
|
+
lookupFromUplinks(null);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
localStream.on('content-length', function (v) {
|
|
255
|
+
readStream.emit('content-length', v);
|
|
256
|
+
});
|
|
257
|
+
localStream.on('open', function () {
|
|
258
|
+
isOpen = true;
|
|
259
|
+
localStream.pipe(readStream);
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
return readStream;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Fetch and cache local/remote packages.
|
|
266
|
+
* @param {Object} file define the package shape
|
|
267
|
+
*/
|
|
268
|
+
function serveFile(file) {
|
|
269
|
+
let uplink = null;
|
|
270
|
+
for (const uplinkId in self.uplinks) {
|
|
271
|
+
if ((0, _config.hasProxyTo)(name, uplinkId, self.config.packages)) {
|
|
272
|
+
uplink = self.uplinks[uplinkId];
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (uplink == null) {
|
|
276
|
+
uplink = new _upStorage.default({
|
|
277
|
+
url: file.url,
|
|
278
|
+
cache: true,
|
|
279
|
+
_autogenerated: true
|
|
280
|
+
}, self.config);
|
|
281
|
+
}
|
|
282
|
+
let savestream = null;
|
|
283
|
+
if (uplink.config.cache) {
|
|
284
|
+
savestream = self.localStorage.addTarball(name, filename);
|
|
285
|
+
}
|
|
286
|
+
let on_open = function () {
|
|
287
|
+
// prevent it from being called twice
|
|
288
|
+
on_open = function () {};
|
|
289
|
+
const rstream2 = uplink.fetchTarball(file.url);
|
|
290
|
+
rstream2.on('error', function (err) {
|
|
291
|
+
if (savestream) {
|
|
292
|
+
savestream.abort();
|
|
293
|
+
}
|
|
294
|
+
savestream = null;
|
|
295
|
+
readStream.emit('error', err);
|
|
296
|
+
});
|
|
297
|
+
rstream2.on('end', function () {
|
|
298
|
+
if (savestream) {
|
|
299
|
+
savestream.done();
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
rstream2.on('content-length', function (v) {
|
|
303
|
+
readStream.emit('content-length', v);
|
|
304
|
+
if (savestream) {
|
|
305
|
+
savestream.emit('content-length', v);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
rstream2.pipe(readStream);
|
|
309
|
+
if (savestream) {
|
|
310
|
+
rstream2.pipe(savestream);
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
if (savestream) {
|
|
314
|
+
savestream.on('open', function () {
|
|
315
|
+
on_open();
|
|
316
|
+
});
|
|
317
|
+
savestream.on('error', function (err) {
|
|
318
|
+
self.logger.warn({
|
|
319
|
+
err: err,
|
|
320
|
+
fileName: file
|
|
321
|
+
}, 'error saving file @{fileName}: @{err.message}\n@{err.stack}');
|
|
322
|
+
if (savestream) {
|
|
323
|
+
savestream.abort();
|
|
324
|
+
}
|
|
325
|
+
savestream = null;
|
|
326
|
+
on_open();
|
|
327
|
+
});
|
|
328
|
+
} else {
|
|
329
|
+
on_open();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
Retrieve a package metadata for {name} package
|
|
336
|
+
Function invokes localStorage.getPackage and uplink.get_package for every
|
|
337
|
+
uplink with proxy_access rights against {name} and combines results
|
|
338
|
+
into one json object
|
|
339
|
+
Used storages: local && uplink (proxy_access)
|
|
340
|
+
* @param {object} options
|
|
341
|
+
* @property {string} options.name Package Name
|
|
342
|
+
* @property {object} options.req Express `req` object
|
|
343
|
+
* @property {boolean} options.keepUpLinkData keep up link info in package meta, last update, etc.
|
|
344
|
+
* @property {function} options.callback Callback for receive data
|
|
345
|
+
*/
|
|
346
|
+
getPackage(options) {
|
|
347
|
+
this.localStorage.getPackageMetadata(options.name, (err, data) => {
|
|
348
|
+
if (err && (!err.status || err.status >= _constants.HTTP_STATUS.INTERNAL_ERROR)) {
|
|
349
|
+
// report internal errors right away
|
|
350
|
+
return options.callback(err);
|
|
351
|
+
}
|
|
352
|
+
this._syncUplinksMetadata(options.name, data, {
|
|
353
|
+
req: options.req,
|
|
354
|
+
uplinksLook: options.uplinksLook
|
|
355
|
+
}, function getPackageSynUpLinksCallback(err, result, uplinkErrors) {
|
|
356
|
+
if (err) {
|
|
357
|
+
return options.callback(err);
|
|
358
|
+
}
|
|
359
|
+
(0, _utils.normalizeDistTags)((0, _storageUtils.cleanUpLinksRef)(options.keepUpLinkData, result));
|
|
360
|
+
|
|
361
|
+
// npm can throw if this field doesn't exist
|
|
362
|
+
result._attachments = {};
|
|
363
|
+
if (options.abbreviated === true) {
|
|
364
|
+
options.callback(null, (0, _storageUtils.convertAbbreviatedManifest)(result), uplinkErrors);
|
|
365
|
+
} else {
|
|
366
|
+
options.callback(null, result, uplinkErrors);
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
Retrieve remote and local packages more recent than {startkey}
|
|
374
|
+
Function streams all packages from all uplinks first, and then
|
|
375
|
+
local packages.
|
|
376
|
+
Note that local packages could override registry ones just because
|
|
377
|
+
they appear in JSON last. That's a trade-off we make to avoid
|
|
378
|
+
memory issues.
|
|
379
|
+
Used storages: local && uplink (proxy_access)
|
|
380
|
+
* @param {*} startkey
|
|
381
|
+
* @param {*} options
|
|
382
|
+
* @return {Stream}
|
|
383
|
+
*/
|
|
384
|
+
search(startkey, options) {
|
|
385
|
+
const self = this;
|
|
386
|
+
const searchStream = new _stream.default.PassThrough({
|
|
387
|
+
objectMode: true
|
|
388
|
+
});
|
|
389
|
+
_async.default.eachSeries(Object.keys(this.uplinks), function (up_name, cb) {
|
|
390
|
+
// shortcut: if `local=1` is supplied, don't call uplinks
|
|
391
|
+
if (options.req?.query?.local !== undefined) {
|
|
392
|
+
return cb();
|
|
393
|
+
}
|
|
394
|
+
_logger.logger.info(`search for uplink ${up_name}`);
|
|
395
|
+
// search by keyword for each uplink
|
|
396
|
+
const uplinkStream = self.uplinks[up_name].search(options);
|
|
397
|
+
// join uplink stream with streams PassThrough
|
|
398
|
+
uplinkStream.pipe(searchStream, {
|
|
399
|
+
end: false
|
|
400
|
+
});
|
|
401
|
+
uplinkStream.on('error', function (err) {
|
|
402
|
+
self.logger.error({
|
|
403
|
+
err: err
|
|
404
|
+
}, 'uplink error: @{err.message}');
|
|
405
|
+
cb();
|
|
406
|
+
// to avoid call callback more than once
|
|
407
|
+
cb = function () {};
|
|
408
|
+
});
|
|
409
|
+
uplinkStream.on('end', function () {
|
|
410
|
+
cb();
|
|
411
|
+
// to avoid call callback more than once
|
|
412
|
+
cb = function () {};
|
|
413
|
+
});
|
|
414
|
+
searchStream.abort = function () {
|
|
415
|
+
if (uplinkStream.abort) {
|
|
416
|
+
uplinkStream.abort();
|
|
417
|
+
}
|
|
418
|
+
cb();
|
|
419
|
+
// to avoid call callback more than once
|
|
420
|
+
cb = function () {};
|
|
421
|
+
};
|
|
422
|
+
},
|
|
423
|
+
// executed after all series
|
|
424
|
+
function () {
|
|
425
|
+
// attach a local search results
|
|
426
|
+
const localSearchStream = self.localStorage.search(startkey, options);
|
|
427
|
+
searchStream.abort = function () {
|
|
428
|
+
localSearchStream.abort();
|
|
429
|
+
};
|
|
430
|
+
localSearchStream.pipe(searchStream, {
|
|
431
|
+
end: true
|
|
432
|
+
});
|
|
433
|
+
localSearchStream.on('error', function (err) {
|
|
434
|
+
self.logger.error({
|
|
435
|
+
err: err
|
|
436
|
+
}, 'search error: @{err.message}');
|
|
437
|
+
searchStream.end();
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
return searchStream;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Retrieve only private local packages
|
|
445
|
+
* @param {*} callback
|
|
446
|
+
*/
|
|
447
|
+
getLocalDatabase(callback) {
|
|
448
|
+
this.localStorage.storagePlugin.get((err, locals) => {
|
|
449
|
+
if (err) {
|
|
450
|
+
return callback(err);
|
|
451
|
+
}
|
|
452
|
+
this._collectLocalPackages(locals).then(packages => callback(null, packages), err => callback(err));
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Read each local package name, apply filters, and collect the latest version.
|
|
458
|
+
*/
|
|
459
|
+
async _collectLocalPackages(locals) {
|
|
460
|
+
const packages = [];
|
|
461
|
+
for (const name of locals) {
|
|
462
|
+
try {
|
|
463
|
+
const pkgMetadata = await this.localStorage.getPackageMetadataAsync(name);
|
|
464
|
+
const {
|
|
465
|
+
filteredPackage
|
|
466
|
+
} = await this._applyFilters(pkgMetadata);
|
|
467
|
+
const latest = filteredPackage[_constants.DIST_TAGS]?.latest;
|
|
468
|
+
if (latest && filteredPackage.versions[latest]) {
|
|
469
|
+
const version = filteredPackage.versions[latest];
|
|
470
|
+
const timeList = filteredPackage.time;
|
|
471
|
+
const time = timeList[latest];
|
|
472
|
+
// @ts-ignore
|
|
473
|
+
version.time = time;
|
|
474
|
+
|
|
475
|
+
// Add for stars api
|
|
476
|
+
// @ts-ignore
|
|
477
|
+
version.users = filteredPackage.users;
|
|
478
|
+
packages.push(version);
|
|
479
|
+
} else {
|
|
480
|
+
this.logger.warn({
|
|
481
|
+
package: name
|
|
482
|
+
}, 'package @{package} does not have a "latest" tag?');
|
|
483
|
+
}
|
|
484
|
+
} catch (err) {
|
|
485
|
+
this.logger.error({
|
|
486
|
+
err,
|
|
487
|
+
package: name
|
|
488
|
+
}, 'error reading package @{package}');
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return packages;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Function fetches package metadata from uplinks and synchronizes it with local data
|
|
496
|
+
if package is available locally, it MUST be provided in pkginfo
|
|
497
|
+
returns callback(err, result, uplink_errors)
|
|
498
|
+
*/
|
|
499
|
+
_syncUplinksMetadata(name, packageInfo, options, callback) {
|
|
500
|
+
let found = true;
|
|
501
|
+
const self = this;
|
|
502
|
+
const upLinks = [];
|
|
503
|
+
const hasToLookIntoUplinks = _lodash.default.isNil(options.uplinksLook) || options.uplinksLook;
|
|
504
|
+
if (!packageInfo) {
|
|
505
|
+
found = false;
|
|
506
|
+
packageInfo = (0, _storageUtils.generatePackageTemplate)(name);
|
|
507
|
+
}
|
|
508
|
+
for (const uplink in this.uplinks) {
|
|
509
|
+
if ((0, _config.hasProxyTo)(name, uplink, this.config.packages) && hasToLookIntoUplinks) {
|
|
510
|
+
upLinks.push(this.uplinks[uplink]);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
_async.default.map(upLinks, (upLink, cb) => {
|
|
514
|
+
const _options = Object.assign({}, options);
|
|
515
|
+
const upLinkMeta = packageInfo._uplinks[upLink.upname];
|
|
516
|
+
if ((0, _utils.isObject)(upLinkMeta)) {
|
|
517
|
+
const fetched = upLinkMeta.fetched;
|
|
518
|
+
if (fetched && Date.now() - fetched < upLink.maxage) {
|
|
519
|
+
return cb();
|
|
520
|
+
}
|
|
521
|
+
_options.etag = upLinkMeta.etag;
|
|
522
|
+
}
|
|
523
|
+
upLink.getRemoteMetadata(name, _options, (err, upLinkResponse, eTag) => {
|
|
524
|
+
if (err && err.remoteStatus === 304) {
|
|
525
|
+
upLinkMeta.fetched = Date.now();
|
|
526
|
+
}
|
|
527
|
+
if (err || !upLinkResponse) {
|
|
528
|
+
return cb(null, [err || _utils.ErrorCode.getInternalError('no data')]);
|
|
529
|
+
}
|
|
530
|
+
try {
|
|
531
|
+
upLinkResponse = _core.validationUtils.normalizeMetadata(upLinkResponse, name);
|
|
532
|
+
} catch (err) {
|
|
533
|
+
self.logger.error({
|
|
534
|
+
sub: 'out',
|
|
535
|
+
err: err
|
|
536
|
+
}, 'package.json validating error @{!err.message}\n@{err.stack}');
|
|
537
|
+
return cb(null, [err]);
|
|
538
|
+
}
|
|
539
|
+
packageInfo._uplinks[upLink.upname] = {
|
|
540
|
+
etag: eTag,
|
|
541
|
+
fetched: Date.now()
|
|
542
|
+
};
|
|
543
|
+
packageInfo = (0, _storageUtils.mergeUplinkTimeIntoLocal)(packageInfo, upLinkResponse);
|
|
544
|
+
(0, _uplinkUtil.updateVersionsHiddenUpLink)(upLinkResponse.versions, upLink);
|
|
545
|
+
try {
|
|
546
|
+
(0, _metadataUtils.mergeVersions)(packageInfo, upLinkResponse);
|
|
547
|
+
} catch (err) {
|
|
548
|
+
self.logger.error({
|
|
549
|
+
sub: 'out',
|
|
550
|
+
err: err
|
|
551
|
+
}, 'package.json parsing error @{!err.message}\n@{err.stack}');
|
|
552
|
+
return cb(null, [err]);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// if we got to this point, assume that the correct package exists
|
|
556
|
+
// on the uplink
|
|
557
|
+
found = true;
|
|
558
|
+
cb();
|
|
559
|
+
});
|
|
560
|
+
},
|
|
561
|
+
// @ts-ignore
|
|
562
|
+
async (err, upLinksErrors) => {
|
|
563
|
+
(0, _assert.default)(!err && Array.isArray(upLinksErrors));
|
|
564
|
+
|
|
565
|
+
// Check for connection timeout or reset errors with uplink(s)
|
|
566
|
+
// (these should be handled differently from the package not being found)
|
|
567
|
+
if (!found) {
|
|
568
|
+
let uplinkTimeoutError;
|
|
569
|
+
for (let i = 0; i < upLinksErrors.length; i++) {
|
|
570
|
+
if (upLinksErrors[i]) {
|
|
571
|
+
for (let j = 0; j < upLinksErrors[i].length; j++) {
|
|
572
|
+
if (upLinksErrors[i][j]) {
|
|
573
|
+
const code = upLinksErrors[i][j].code;
|
|
574
|
+
if (code === 'ETIMEDOUT' || code === 'ESOCKETTIMEDOUT' || code === 'ECONNRESET') {
|
|
575
|
+
uplinkTimeoutError = true;
|
|
576
|
+
break;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
if (uplinkTimeoutError) {
|
|
583
|
+
return callback(_utils.ErrorCode.getServiceUnavailable(), null, upLinksErrors);
|
|
584
|
+
}
|
|
585
|
+
return callback(_utils.ErrorCode.getNotFound(_constants.API_ERROR.NO_PACKAGE), null, upLinksErrors);
|
|
586
|
+
}
|
|
587
|
+
if (upLinks.length === 0) {
|
|
588
|
+
const {
|
|
589
|
+
filteredPackage,
|
|
590
|
+
filterErrors
|
|
591
|
+
} = await self._applyFilters(packageInfo);
|
|
592
|
+
return callback(null, filteredPackage, filterErrors);
|
|
593
|
+
}
|
|
594
|
+
try {
|
|
595
|
+
const packageJsonLocal = await self.localStorage.updateVersionsAsync(name, packageInfo);
|
|
596
|
+
const {
|
|
597
|
+
filteredPackage,
|
|
598
|
+
filterErrors
|
|
599
|
+
} = await self._applyFilters(packageJsonLocal);
|
|
600
|
+
callback(null, filteredPackage, _lodash.default.concat(upLinksErrors, filterErrors));
|
|
601
|
+
} catch (err) {
|
|
602
|
+
callback(err);
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Apply all configured filter plugins to a package manifest sequentially.
|
|
609
|
+
* Each filter's output is passed as input to the next filter.
|
|
610
|
+
* Returns the filtered manifest and any errors that occurred.
|
|
611
|
+
*/
|
|
612
|
+
async _applyFilters(packageInfo) {
|
|
613
|
+
const filterErrors = [];
|
|
614
|
+
let filteredPackage = packageInfo;
|
|
615
|
+
for (const filter of this.filters ?? []) {
|
|
616
|
+
try {
|
|
617
|
+
filteredPackage = await filter.filter_metadata(filteredPackage);
|
|
618
|
+
} catch (err) {
|
|
619
|
+
filterErrors.push(err);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
return {
|
|
623
|
+
filteredPackage,
|
|
624
|
+
filterErrors
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Check if a tarball should be served based on filter plugins.
|
|
630
|
+
* Looks up package metadata, applies filters, and verifies the tarball
|
|
631
|
+
* still belongs to an allowed version.
|
|
632
|
+
*/
|
|
633
|
+
async _isTarballAllowedByFilters(name, filename) {
|
|
634
|
+
if (!this.filters?.length) {
|
|
635
|
+
return true;
|
|
636
|
+
}
|
|
637
|
+
try {
|
|
638
|
+
const pkgMetadata = await this.localStorage.getPackageMetadataAsync(name);
|
|
639
|
+
const {
|
|
640
|
+
filteredPackage
|
|
641
|
+
} = await this._applyFilters(pkgMetadata);
|
|
642
|
+
return Object.values(filteredPackage.versions || {}).some(version => version.dist?.tarball?.endsWith('/' + filename));
|
|
643
|
+
} catch (err) {
|
|
644
|
+
if (err?.status === _constants.HTTP_STATUS.NOT_FOUND) {
|
|
645
|
+
// Package not yet cached locally — the request will fall through to uplinks.
|
|
646
|
+
debug('package %o not cached locally, skipping tarball filter check', name);
|
|
647
|
+
} else {
|
|
648
|
+
this.logger.error({
|
|
649
|
+
package: name,
|
|
650
|
+
fileName: filename,
|
|
651
|
+
err
|
|
652
|
+
}, 'error checking filters for tarball @{fileName} of package @{package}: @{err.message}');
|
|
653
|
+
}
|
|
654
|
+
return true;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* Set a hidden value for each version.
|
|
660
|
+
* @param {Array} versions list of version
|
|
661
|
+
* @param {String} upLink uplink name
|
|
662
|
+
* @private
|
|
663
|
+
*/
|
|
664
|
+
_updateVersionsHiddenUpLink(versions, upLink) {
|
|
665
|
+
for (const i in versions) {
|
|
666
|
+
if (Object.prototype.hasOwnProperty.call(versions, i)) {
|
|
667
|
+
const version = versions[i];
|
|
668
|
+
|
|
669
|
+
// holds a "hidden" value to be used by the package storage.
|
|
670
|
+
version[Symbol.for('__verdaccio_uplink')] = upLink.upname;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
var _default = exports.default = Storage;
|
|
676
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfYXNzZXJ0IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfYXN5bmMiLCJfZGVidWciLCJfbG9kYXNoIiwiX3N0cmVhbSIsIl9jb25maWciLCJfY29yZSIsIl9sb2FkZXJzIiwiX2xvY2FsU3RvcmFnZUxlZ2FjeSIsIl9zZWFyY2hJbmRleGVyIiwiX3N0cmVhbXMiLCJfbG9nZ2VyIiwiX2NvbnN0YW50cyIsIl9sb2NhbFN0b3JhZ2UiLCJfbWV0YWRhdGFVdGlscyIsIl9zdG9yYWdlVXRpbHMiLCJfdXBTdG9yYWdlIiwiX3VwbGlua1V0aWwiLCJfdXRpbHMiLCJlIiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJkZWJ1ZyIsImJ1aWxkRGVidWciLCJTdG9yYWdlIiwiY29uc3RydWN0b3IiLCJjb25maWciLCJ1cGxpbmtzIiwic2V0dXBVcExpbmtzIiwibG9nZ2VyIiwibG9jYWxTdG9yYWdlIiwiaW5pdCIsImZpbHRlcnMiLCJzdG9yYWdlSW5zdGFuY2UiLCJsb2FkU3RvcmFnZSIsIkxvY2FsU3RvcmFnZSIsImdldFNlY3JldCIsImFzeW5jTG9hZFBsdWdpbiIsInBsdWdpbiIsImZpbHRlcl9tZXRhZGF0YSIsInNlcnZlclNldHRpbmdzIiwicGx1Z2luUHJlZml4IiwiUExVR0lOX0NBVEVHT1JZIiwiRklMVEVSIiwibGVuZ3RoIiwibG9hZFN0b3JlUGx1Z2luIiwiXyIsImlzTmlsIiwiYXNzZXJ0Iiwic3RvcmFnZSIsIkxvY2FsRGF0YWJhc2VQbHVnaW4iLCJpbmZvIiwibmFtZSIsInBsdWdpbkNhdGVnb3J5IiwiU1RPUkFHRSIsInBsdWdpbnMiLCJzdG9yZSIsImdldFBhY2thZ2VTdG9yYWdlIiwid2FybiIsImhlYWQiLCJhZGRQYWNrYWdlIiwibWV0YWRhdGEiLCJjYWxsYmFjayIsImNoZWNrUGFja2FnZUxvY2FsIiwiY2hlY2tQYWNrYWdlUmVtb3RlIiwiX2lzQWxsb3dQdWJsaXNoT2ZmbGluZSIsIl9zeW5jVXBsaW5rc01ldGFkYXRhIiwiYmluZCIsInB1Ymxpc2hQYWNrYWdlIiwiZXJyIiwicHVibGlzaCIsImlzQm9vbGVhbiIsImFsbG93X29mZmxpbmUiLCJyZWFkVG9rZW5zIiwiZmlsdGVyIiwic2F2ZVRva2VuIiwidG9rZW4iLCJkZWxldGVUb2tlbiIsInVzZXIiLCJ0b2tlbktleSIsImFkZFZlcnNpb24iLCJ2ZXJzaW9uIiwidGFnIiwibWVyZ2VUYWdzIiwidGFnSGFzaCIsImNoYW5nZVBhY2thZ2UiLCJyZXZpc2lvbiIsInJlbW92ZVBhY2thZ2UiLCJTZWFyY2hNZW1vcnlJbmRleGVyIiwicmVtb3ZlIiwiY2F0Y2giLCJyZWFzb24iLCJlcnJvciIsInJlbW92ZVRhcmJhbGwiLCJmaWxlbmFtZSIsImFkZFRhcmJhbGwiLCJoYXNMb2NhbFRhcmJhbGwiLCJzZWxmIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWplY3QiLCJsb2NhbFN0cmVhbSIsImdldFRhcmJhbGwiLCJpc09wZW4iLCJvbiIsInN0YXR1cyIsIkhUVFBfU1RBVFVTIiwiTk9UX0ZPVU5EIiwiYWJvcnQiLCJyZWFkU3RyZWFtIiwiUmVhZFRhcmJhbGwiLCJfaXNUYXJiYWxsQWxsb3dlZEJ5RmlsdGVycyIsInRoZW4iLCJhbGxvd2VkIiwiZW1pdCIsIkVycm9yQ29kZSIsImdldE5vdEZvdW5kIiwiQVBJX0VSUk9SIiwiTk9fUEFDS0FHRSIsImVycjQwNCIsImxvb2t1cEZyb21VcGxpbmtzIiwic3luY0VyciIsInN5bmNJbmZvIiwiX2Rpc3RmaWxlcyIsInNlcnZlRmlsZSIsImdldFBhY2thZ2VNZXRhZGF0YUFzeW5jIiwidiIsInBpcGUiLCJmaWxlIiwidXBsaW5rIiwidXBsaW5rSWQiLCJoYXNQcm94eVRvIiwicGFja2FnZXMiLCJQcm94eVN0b3JhZ2UiLCJ1cmwiLCJjYWNoZSIsIl9hdXRvZ2VuZXJhdGVkIiwic2F2ZXN0cmVhbSIsIm9uX29wZW4iLCJyc3RyZWFtMiIsImZldGNoVGFyYmFsbCIsImRvbmUiLCJmaWxlTmFtZSIsImdldFBhY2thZ2UiLCJvcHRpb25zIiwiZ2V0UGFja2FnZU1ldGFkYXRhIiwiZGF0YSIsIklOVEVSTkFMX0VSUk9SIiwicmVxIiwidXBsaW5rc0xvb2siLCJnZXRQYWNrYWdlU3luVXBMaW5rc0NhbGxiYWNrIiwicmVzdWx0IiwidXBsaW5rRXJyb3JzIiwibm9ybWFsaXplRGlzdFRhZ3MiLCJjbGVhblVwTGlua3NSZWYiLCJrZWVwVXBMaW5rRGF0YSIsIl9hdHRhY2htZW50cyIsImFiYnJldmlhdGVkIiwiY29udmVydEFiYnJldmlhdGVkTWFuaWZlc3QiLCJzZWFyY2giLCJzdGFydGtleSIsInNlYXJjaFN0cmVhbSIsIlN0cmVhbSIsIlBhc3NUaHJvdWdoIiwib2JqZWN0TW9kZSIsImFzeW5jIiwiZWFjaFNlcmllcyIsIk9iamVjdCIsImtleXMiLCJ1cF9uYW1lIiwiY2IiLCJxdWVyeSIsImxvY2FsIiwidW5kZWZpbmVkIiwidXBsaW5rU3RyZWFtIiwiZW5kIiwibG9jYWxTZWFyY2hTdHJlYW0iLCJnZXRMb2NhbERhdGFiYXNlIiwic3RvcmFnZVBsdWdpbiIsImdldCIsImxvY2FscyIsIl9jb2xsZWN0TG9jYWxQYWNrYWdlcyIsInBrZ01ldGFkYXRhIiwiZmlsdGVyZWRQYWNrYWdlIiwiX2FwcGx5RmlsdGVycyIsImxhdGVzdCIsIkRJU1RfVEFHUyIsInZlcnNpb25zIiwidGltZUxpc3QiLCJ0aW1lIiwidXNlcnMiLCJwdXNoIiwicGFja2FnZSIsInBhY2thZ2VJbmZvIiwiZm91bmQiLCJ1cExpbmtzIiwiaGFzVG9Mb29rSW50b1VwbGlua3MiLCJnZW5lcmF0ZVBhY2thZ2VUZW1wbGF0ZSIsIm1hcCIsInVwTGluayIsIl9vcHRpb25zIiwiYXNzaWduIiwidXBMaW5rTWV0YSIsIl91cGxpbmtzIiwidXBuYW1lIiwiaXNPYmplY3QiLCJmZXRjaGVkIiwiRGF0ZSIsIm5vdyIsIm1heGFnZSIsImV0YWciLCJnZXRSZW1vdGVNZXRhZGF0YSIsInVwTGlua1Jlc3BvbnNlIiwiZVRhZyIsInJlbW90ZVN0YXR1cyIsImdldEludGVybmFsRXJyb3IiLCJ2YWxpZGF0aW9uVXRpbHMiLCJub3JtYWxpemVNZXRhZGF0YSIsInN1YiIsIm1lcmdlVXBsaW5rVGltZUludG9Mb2NhbCIsInVwZGF0ZVZlcnNpb25zSGlkZGVuVXBMaW5rIiwibWVyZ2VWZXJzaW9ucyIsInVwTGlua3NFcnJvcnMiLCJBcnJheSIsImlzQXJyYXkiLCJ1cGxpbmtUaW1lb3V0RXJyb3IiLCJpIiwiaiIsImNvZGUiLCJnZXRTZXJ2aWNlVW5hdmFpbGFibGUiLCJmaWx0ZXJFcnJvcnMiLCJwYWNrYWdlSnNvbkxvY2FsIiwidXBkYXRlVmVyc2lvbnNBc3luYyIsImNvbmNhdCIsInZhbHVlcyIsInNvbWUiLCJkaXN0IiwidGFyYmFsbCIsImVuZHNXaXRoIiwiX3VwZGF0ZVZlcnNpb25zSGlkZGVuVXBMaW5rIiwicHJvdG90eXBlIiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiU3ltYm9sIiwiZm9yIiwiX2RlZmF1bHQiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9zdG9yYWdlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCBhc3luYyBmcm9tICdhc3luYyc7XG5pbXBvcnQgYnVpbGREZWJ1ZyBmcm9tICdkZWJ1Zyc7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IFN0cmVhbSBmcm9tICdzdHJlYW0nO1xuXG5pbXBvcnQgeyBoYXNQcm94eVRvIH0gZnJvbSAnQHZlcmRhY2Npby9jb25maWcnO1xuaW1wb3J0IHsgUExVR0lOX0NBVEVHT1JZLCBwbHVnaW5VdGlscywgdmFsaWRhdGlvblV0aWxzIH0gZnJvbSAnQHZlcmRhY2Npby9jb3JlJztcbmltcG9ydCB7IGFzeW5jTG9hZFBsdWdpbiB9IGZyb20gJ0B2ZXJkYWNjaW8vbG9hZGVycyc7XG5pbXBvcnQgTG9jYWxEYXRhYmFzZVBsdWdpbiBmcm9tICdAdmVyZGFjY2lvL2xvY2FsLXN0b3JhZ2UtbGVnYWN5JztcbmltcG9ydCB7IFNlYXJjaE1lbW9yeUluZGV4ZXIgfSBmcm9tICdAdmVyZGFjY2lvL3NlYXJjaC1pbmRleGVyJztcbmltcG9ydCB7IFJlYWRUYXJiYWxsIH0gZnJvbSAnQHZlcmRhY2Npby9zdHJlYW1zJztcbmltcG9ydCB7XG4gIENhbGxiYWNrLFxuICBDb25maWcsXG4gIERpc3RGaWxlLFxuICBMb2dnZXIsXG4gIE1hbmlmZXN0LFxuICBNZXJnZVRhZ3MsXG4gIFZlcnNpb24sXG4gIFZlcnNpb25zLFxufSBmcm9tICdAdmVyZGFjY2lvL3R5cGVzJztcbmltcG9ydCB7IEdlbmVyaWNCb2R5LCBUb2tlbiwgVG9rZW5GaWx0ZXIgfSBmcm9tICdAdmVyZGFjY2lvL3R5cGVzJztcblxuaW1wb3J0IHsgU3RvcmFnZVBsdWdpbkxlZ2FjeSB9IGZyb20gJy4uLy4uL3R5cGVzL2N1c3RvbSc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi9saWIvbG9nZ2VyJztcbmltcG9ydCB7IElQbHVnaW5GaWx0ZXJzLCBJU3luY1VwbGlua3MsIFN0cmluZ1ZhbHVlIH0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHsgQVBJX0VSUk9SLCBESVNUX1RBR1MsIEhUVFBfU1RBVFVTIH0gZnJvbSAnLi9jb25zdGFudHMnO1xuaW1wb3J0IExvY2FsU3RvcmFnZSwgeyBTdG9yYWdlUGx1Z2luIH0gZnJvbSAnLi9sb2NhbC1zdG9yYWdlJztcbmltcG9ydCB7IG1lcmdlVmVyc2lvbnMgfSBmcm9tICcuL21ldGFkYXRhLXV0aWxzJztcbmltcG9ydCB7XG4gIGNoZWNrUGFja2FnZUxvY2FsLFxuICBjaGVja1BhY2thZ2VSZW1vdGUsXG4gIGNsZWFuVXBMaW5rc1JlZixcbiAgY29udmVydEFiYnJldmlhdGVkTWFuaWZlc3QsXG4gIGdlbmVyYXRlUGFja2FnZVRlbXBsYXRlLFxuICBtZXJnZVVwbGlua1RpbWVJbnRvTG9jYWwsXG4gIHB1Ymxpc2hQYWNrYWdlLFxufSBmcm9tICcuL3N0b3JhZ2UtdXRpbHMnO1xuaW1wb3J0IFByb3h5U3RvcmFnZSBmcm9tICcuL3VwLXN0b3JhZ2UnO1xuaW1wb3J0IHsgc2V0dXBVcExpbmtzLCB1cGRhdGVWZXJzaW9uc0hpZGRlblVwTGluayB9IGZyb20gJy4vdXBsaW5rLXV0aWwnO1xuaW1wb3J0IHsgRXJyb3JDb2RlLCBpc09iamVjdCwgbm9ybWFsaXplRGlzdFRhZ3MgfSBmcm9tICcuL3V0aWxzJztcblxuY29uc3QgZGVidWcgPSBidWlsZERlYnVnKCd2ZXJkYWNjaW86c3RvcmFnZScpO1xuXG5jbGFzcyBTdG9yYWdlIHtcbiAgcHVibGljIGxvY2FsU3RvcmFnZTogTG9jYWxTdG9yYWdlO1xuICBwdWJsaWMgY29uZmlnOiBDb25maWc7XG4gIHB1YmxpYyBsb2dnZXI6IExvZ2dlcjtcbiAgcHVibGljIHVwbGlua3M6IFJlY29yZDxzdHJpbmcsIFByb3h5U3RvcmFnZT47XG4gIHB1YmxpYyBmaWx0ZXJzOiBJUGx1Z2luRmlsdGVycyB8IHVuZGVmaW5lZDtcblxuICBwdWJsaWMgY29uc3RydWN0b3IoY29uZmlnOiBDb25maWcpIHtcbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcbiAgICB0aGlzLnVwbGlua3MgPSBzZXR1cFVwTGlua3MoY29uZmlnKTtcbiAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlcjtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50XG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIHRoaXMubG9jYWxTdG9yYWdlID0gbnVsbDtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBpbml0KGNvbmZpZzogQ29uZmlnLCBmaWx0ZXJzPzogSVBsdWdpbkZpbHRlcnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5sb2NhbFN0b3JhZ2UgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuZmlsdGVycyA9IGZpbHRlcnM7XG4gICAgICBjb25zdCBzdG9yYWdlSW5zdGFuY2UgPSBhd2FpdCB0aGlzLmxvYWRTdG9yYWdlKGNvbmZpZywgdGhpcy5sb2dnZXIpO1xuICAgICAgdGhpcy5sb2NhbFN0b3JhZ2UgPSBuZXcgTG9jYWxTdG9yYWdlKHRoaXMuY29uZmlnLCBsb2dnZXIsIHN0b3JhZ2VJbnN0YW5jZSk7XG4gICAgICBhd2FpdCB0aGlzLmxvY2FsU3RvcmFnZS5nZXRTZWNyZXQoY29uZmlnKTtcbiAgICAgIGRlYnVnKCdpbml0aWFsaXphdGlvbiBjb21wbGV0ZWQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVidWcoJ3N0b3JhZ2UgaGFzIGJlZW4gYWxyZWFkeSBpbml0aWFsaXplZCcpO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5maWx0ZXJzKSB7XG4gICAgICB0aGlzLmZpbHRlcnMgPSBhd2FpdCBhc3luY0xvYWRQbHVnaW48cGx1Z2luVXRpbHMuTWFuaWZlc3RGaWx0ZXI8dW5rbm93bj4+KFxuICAgICAgICB0aGlzLmNvbmZpZy5maWx0ZXJzLFxuICAgICAgICB7XG4gICAgICAgICAgY29uZmlnOiB0aGlzLmNvbmZpZyxcbiAgICAgICAgICBsb2dnZXI6IHRoaXMubG9nZ2VyLFxuICAgICAgICB9LFxuICAgICAgICAocGx1Z2luOiBwbHVnaW5VdGlscy5NYW5pZmVzdEZpbHRlcjxDb25maWc+KSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHR5cGVvZiBwbHVnaW4uZmlsdGVyX21ldGFkYXRhICE9PSAndW5kZWZpbmVkJztcbiAgICAgICAgfSxcbiAgICAgICAgdHJ1ZSxcbiAgICAgICAgdGhpcy5jb25maWc/LnNlcnZlclNldHRpbmdzPy5wbHVnaW5QcmVmaXgsXG4gICAgICAgIFBMVUdJTl9DQVRFR09SWS5GSUxURVJcbiAgICAgICk7XG4gICAgICBkZWJ1ZygnZmlsdGVycyBhdmFpbGFibGUgJW8nLCB0aGlzLmZpbHRlcnMubGVuZ3RoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGxvYWRTdG9yYWdlKGNvbmZpZzogQ29uZmlnLCBsb2dnZXI6IExvZ2dlcik6IFByb21pc2U8U3RvcmFnZVBsdWdpbj4ge1xuICAgIGNvbnN0IFN0b3JhZ2UgPSBhd2FpdCB0aGlzLmxvYWRTdG9yZVBsdWdpbigpO1xuICAgIGlmIChfLmlzTmlsKFN0b3JhZ2UpKSB7XG4gICAgICBhc3NlcnQodGhpcy5jb25maWcuc3RvcmFnZSwgJ0NPTkZJRzogc3RvcmFnZSBwYXRoIG5vdCBkZWZpbmVkJyk7XG4gICAgICBkZWJ1Zygnbm8gY3VzdG9tIHN0b3JhZ2UgZm91bmQsIGxvYWRpbmcgZGVmYXVsdCBzdG9yYWdlIEB2ZXJkYWNjaW8vbG9jYWwtc3RvcmFnZScpO1xuICAgICAgY29uc3QgbG9jYWxTdG9yYWdlID0gbmV3IExvY2FsRGF0YWJhc2VQbHVnaW4oY29uZmlnLCBsb2dnZXIpO1xuICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgIHsgbmFtZTogJ0B2ZXJkYWNjaW8vbG9jYWwtc3RvcmFnZScsIHBsdWdpbkNhdGVnb3J5OiBQTFVHSU5fQ0FURUdPUlkuU1RPUkFHRSB9LFxuICAgICAgICAncGx1Z2luIEB7bmFtZX0gc3VjY2Vzc2Z1bGx5IGxvYWRlZCAoQHtwbHVnaW5DYXRlZ29yeX0pJ1xuICAgICAgKTtcbiAgICAgIHJldHVybiBsb2NhbFN0b3JhZ2U7XG4gICAgfVxuICAgIHJldHVybiBTdG9yYWdlIGFzIFN0b3JhZ2VQbHVnaW47XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGxvYWRTdG9yZVBsdWdpbigpOiBQcm9taXNlPFN0b3JhZ2VQbHVnaW5MZWdhY3k8Q29uZmlnPiB8IHVuZGVmaW5lZD4ge1xuICAgIGNvbnN0IHBsdWdpbnM6IFN0b3JhZ2VQbHVnaW5MZWdhY3k8Q29uZmlnPltdID0gYXdhaXQgYXN5bmNMb2FkUGx1Z2luPFxuICAgICAgcGx1Z2luVXRpbHMuU3RvcmFnZTx1bmtub3duPlxuICAgID4oXG4gICAgICB0aGlzLmNvbmZpZy5zdG9yZSxcbiAgICAgIHtcbiAgICAgICAgY29uZmlnOiB0aGlzLmNvbmZpZyxcbiAgICAgICAgbG9nZ2VyOiB0aGlzLmxvZ2dlcixcbiAgICAgIH0sXG4gICAgICAocGx1Z2luKSA9PiB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgcGx1Z2luLmdldFBhY2thZ2VTdG9yYWdlICE9PSAndW5kZWZpbmVkJztcbiAgICAgIH0sXG4gICAgICB0cnVlLFxuICAgICAgdGhpcy5jb25maWc/LnNlcnZlclNldHRpbmdzPy5wbHVnaW5QcmVmaXgsXG4gICAgICBQTFVHSU5fQ0FURUdPUlkuU1RPUkFHRVxuICAgICk7XG5cbiAgICBpZiAocGx1Z2lucy5sZW5ndGggPiAxKSB7XG4gICAgICB0aGlzLmxvZ2dlci53YXJuKFxuICAgICAgICAnbW9yZSB0aGFuIG9uZSBzdG9yYWdlIHBsdWdpbnMgaGFzIGJlZW4gZGV0ZWN0ZWQsIG11bHRpcGxlIHN0b3JhZ2UgYXJlIG5vdCBzdXBwb3J0ZWQsIG9uZSB3aWxsIGJlIHNlbGVjdGVkIGF1dG9tYXRpY2FsbHknXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBfLmhlYWQocGx1Z2lucyk7XG4gIH1cblxuICAvKipcbiAgICogIEFkZCBhIHtuYW1lfSBwYWNrYWdlIHRvIGEgc3lzdGVtXG4gICBGdW5jdGlvbiBjaGVja3MgaWYgcGFja2FnZSB3aXRoIHRoZSBzYW1lIG5hbWUgaXMgYXZhaWxhYmxlIGZyb20gdXBsaW5rcy5cbiAgIElmIGl0IGlzbid0LCB3ZSBjcmVhdGUgcGFja2FnZSBsb2NhbGx5XG4gICBVc2VkIHN0b3JhZ2VzOiBsb2NhbCAod3JpdGUpICYmIHVwbGlua3NcbiAgICovXG4gIHB1YmxpYyBhc3luYyBhZGRQYWNrYWdlKG5hbWU6IHN0cmluZywgbWV0YWRhdGE6IGFueSwgY2FsbGJhY2s6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBjaGVja1BhY2thZ2VMb2NhbChuYW1lLCB0aGlzLmxvY2FsU3RvcmFnZSk7XG4gICAgICBhd2FpdCBjaGVja1BhY2thZ2VSZW1vdGUoXG4gICAgICAgIG5hbWUsXG4gICAgICAgIHRoaXMuX2lzQWxsb3dQdWJsaXNoT2ZmbGluZSgpLFxuICAgICAgICB0aGlzLl9zeW5jVXBsaW5rc01ldGFkYXRhLmJpbmQodGhpcylcbiAgICAgICk7XG4gICAgICBhd2FpdCBwdWJsaXNoUGFja2FnZShuYW1lLCBtZXRhZGF0YSwgdGhpcy5sb2NhbFN0b3JhZ2UpO1xuICAgICAgY2FsbGJhY2soKTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgY2FsbGJhY2soZXJyKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9pc0FsbG93UHVibGlzaE9mZmxpbmUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIHR5cGVvZiB0aGlzLmNvbmZpZy5wdWJsaXNoICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgXy5pc0Jvb2xlYW4odGhpcy5jb25maWcucHVibGlzaC5hbGxvd19vZmZsaW5lKSAmJlxuICAgICAgdGhpcy5jb25maWcucHVibGlzaC5hbGxvd19vZmZsaW5lXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyByZWFkVG9rZW5zKGZpbHRlcjogVG9rZW5GaWx0ZXIpOiBQcm9taXNlPFRva2VuW10+IHtcbiAgICByZXR1cm4gdGhpcy5sb2NhbFN0b3JhZ2UucmVhZFRva2VucyhmaWx0ZXIpO1xuICB9XG5cbiAgcHVibGljIHNhdmVUb2tlbih0b2tlbjogVG9rZW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5sb2NhbFN0b3JhZ2Uuc2F2ZVRva2VuKHRva2VuKTtcbiAgfVxuXG4gIHB1YmxpYyBkZWxldGVUb2tlbih1c2VyOiBzdHJpbmcsIHRva2VuS2V5OiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgIHJldHVybiB0aGlzLmxvY2FsU3RvcmFnZS5kZWxldGVUb2tlbih1c2VyLCB0b2tlbktleSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgbmV3IHZlcnNpb24gb2YgcGFja2FnZSB7bmFtZX0gdG8gYSBzeXN0ZW1cbiAgIFVzZWQgc3RvcmFnZXM6IGxvY2FsICh3cml0ZSlcbiAgICovXG4gIHB1YmxpYyBhZGRWZXJzaW9uKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICB2ZXJzaW9uOiBzdHJpbmcsXG4gICAgbWV0YWRhdGE6IFZlcnNpb24sXG4gICAgdGFnOiBTdHJpbmdWYWx1ZSxcbiAgICBjYWxsYmFjazogQ2FsbGJhY2tcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5sb2NhbFN0b3JhZ2UuYWRkVmVyc2lvbihuYW1lLCB2ZXJzaW9uLCBtZXRhZGF0YSwgdGFnLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogVGFncyBhIHBhY2thZ2UgdmVyc2lvbiB3aXRoIGEgcHJvdmlkZWQgdGFnXG4gICBVc2VkIHN0b3JhZ2VzOiBsb2NhbCAod3JpdGUpXG4gICAqL1xuICBwdWJsaWMgbWVyZ2VUYWdzKG5hbWU6IHN0cmluZywgdGFnSGFzaDogTWVyZ2VUYWdzLCBjYWxsYmFjazogQ2FsbGJhY2spOiB2b2lkIHtcbiAgICB0aGlzLmxvY2FsU3RvcmFnZS5tZXJnZVRhZ3MobmFtZSwgdGFnSGFzaCwgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIENoYW5nZSBhbiBleGlzdGluZyBwYWNrYWdlIChpLmUuIHVucHVibGlzaCBvbmUgdmVyc2lvbilcbiAgIEZ1bmN0aW9uIGNoYW5nZXMgYSBwYWNrYWdlIGluZm8gZnJvbSBsb2NhbCBzdG9yYWdlIGFuZCBhbGwgdXBsaW5rcyB3aXRoIHdyaXRlIGFjY2Vzcy4vXG4gICBVc2VkIHN0b3JhZ2VzOiBsb2NhbCAod3JpdGUpXG4gICAqL1xuICBwdWJsaWMgY2hhbmdlUGFja2FnZShcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgbWV0YWRhdGE6IE1hbmlmZXN0LFxuICAgIHJldmlzaW9uOiBzdHJpbmcsXG4gICAgY2FsbGJhY2s6IENhbGxiYWNrXG4gICk6IHZvaWQge1xuICAgIHRoaXMubG9jYWxTdG9yYWdlLmNoYW5nZVBhY2thZ2UobmFtZSwgbWV0YWRhdGEsIHJldmlzaW9uLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIGEgcGFja2FnZSBmcm9tIGEgc3lzdGVtXG4gICBGdW5jdGlvbiByZW1vdmVzIGEgcGFja2FnZSBmcm9tIGxvY2FsIHN0b3JhZ2VcbiAgIFVzZWQgc3RvcmFnZXM6IGxvY2FsICh3cml0ZSlcbiAgICovXG4gIHB1YmxpYyByZW1vdmVQYWNrYWdlKG5hbWU6IHN0cmluZywgY2FsbGJhY2s6IENhbGxiYWNrKTogdm9pZCB7XG4gICAgdGhpcy5sb2NhbFN0b3JhZ2UucmVtb3ZlUGFja2FnZShuYW1lLCBjYWxsYmFjayk7XG4gICAgLy8gdXBkYXRlIHRoZSBpbmRleGVyXG4gICAgU2VhcmNoTWVtb3J5SW5kZXhlci5yZW1vdmUobmFtZSkuY2F0Y2goKHJlYXNvbikgPT4ge1xuICAgICAgZGVidWcoJ2luZGV4ZXIgaGFzIGZhaWxlZCBvbiByZW1vdmUgaXRlbSAlbycsIHJlYXNvbik7XG4gICAgICBsb2dnZXIuZXJyb3IoJ2luZGV4ZXIgaGFzIGZhaWxlZCBvbiByZW1vdmUgaXRlbScpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICBSZW1vdmUgYSB0YXJiYWxsIGZyb20gYSBzeXN0ZW1cbiAgIEZ1bmN0aW9uIHJlbW92ZXMgYSB0YXJiYWxsIGZyb20gbG9jYWwgc3RvcmFnZS5cbiAgIFRhcmJhbGwgaW4gcXVlc3Rpb24gc2hvdWxkIG5vdCBiZSBsaW5rZWQgdG8gaW4gYW55IGV4aXN0aW5nXG4gICB2ZXJzaW9ucywgaS5lLiBwYWNrYWdlIHZlcnNpb24gc2hvdWxkIGJlIHVucHVibGlzaGVkIGZpcnN0LlxuICAgVXNlZCBzdG9yYWdlOiBsb2NhbCAod3JpdGUpXG4gICAqL1xuICBwdWJsaWMgcmVtb3ZlVGFyYmFsbChuYW1lOiBzdHJpbmcsIGZpbGVuYW1lOiBzdHJpbmcsIHJldmlzaW9uOiBzdHJpbmcsIGNhbGxiYWNrOiBDYWxsYmFjayk6IHZvaWQge1xuICAgIHRoaXMubG9jYWxTdG9yYWdlLnJlbW92ZVRhcmJhbGwobmFtZSwgZmlsZW5hbWUsIHJldmlzaW9uLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogVXBsb2FkIGEgdGFyYmFsbCBmb3Ige25hbWV9IHBhY2thZ2VcbiAgIEZ1bmN0aW9uIGlzIHN5bmNocm9ub3VzIGFuZCByZXR1cm5zIGEgV3JpdGFibGVTdHJlYW1cbiAgIFVzZWQgc3RvcmFnZXM6IGxvY2FsICh3cml0ZSlcbiAgICovXG4gIHB1YmxpYyBhZGRUYXJiYWxsKG5hbWU6IHN0cmluZywgZmlsZW5hbWU6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmxvY2FsU3RvcmFnZS5hZGRUYXJiYWxsKG5hbWUsIGZpbGVuYW1lKTtcbiAgfVxuXG4gIHB1YmxpYyBoYXNMb2NhbFRhcmJhbGwobmFtZTogc3RyaW5nLCBmaWxlbmFtZTogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPGJvb2xlYW4+KChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIGxldCBsb2NhbFN0cmVhbTogYW55ID0gc2VsZi5sb2NhbFN0b3JhZ2UuZ2V0VGFyYmFsbChuYW1lLCBmaWxlbmFtZSk7XG4gICAgICBsZXQgaXNPcGVuID0gZmFsc2U7XG4gICAgICBsb2NhbFN0cmVhbS5vbignZXJyb3InLCAoZXJyKTogYW55ID0+IHtcbiAgICAgICAgaWYgKGlzT3BlbiB8fCBlcnIuc3RhdHVzICE9PSBIVFRQX1NUQVRVUy5OT1RfRk9VTkQpIHtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBsb2NhbCByZXBvcnRlZCA0MDQgb3IgcmVxdWVzdCB3YXMgYWJvcnRlZCBhbHJlYWR5XG4gICAgICAgIGlmIChsb2NhbFN0cmVhbSkge1xuICAgICAgICAgIGxvY2FsU3RyZWFtLmFib3J0KCk7XG4gICAgICAgICAgbG9jYWxTdHJlYW0gPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJlc29sdmUoZmFsc2UpO1xuICAgICAgfSk7XG4gICAgICBsb2NhbFN0cmVhbS5vbignb3BlbicsIGZ1bmN0aW9uICgpOiB2b2lkIHtcbiAgICAgICAgaXNPcGVuID0gdHJ1ZTtcbiAgICAgICAgbG9jYWxTdHJlYW0uYWJvcnQoKTtcbiAgICAgICAgbG9jYWxTdHJlYW0gPSBudWxsO1xuICAgICAgICByZXNvbHZlKHRydWUpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgIEdldCBhIHRhcmJhbGwgZnJvbSBhIHN0b3JhZ2UgZm9yIHtuYW1lfSBwYWNrYWdlXG4gICBGdW5jdGlvbiBpcyBzeW5jaHJvbm91cyBhbmQgcmV0dXJucyBhIFJlYWRhYmxlU3RyZWFtXG4gICBGdW5jdGlvbiB0cmllcyB0byByZWFkIHRhcmJhbGwgbG9jYWxseSwgaWYgaXQgZmFpbHMgdGhlbiBpdCByZWFkcyBwYWNrYWdlXG4gICBpbmZvcm1hdGlvbiBpbiBvcmRlciB0byBmaWd1cmUgb3V0IHdoZXJlIHdlIGNhbiBnZXQgdGhpcyB0YXJiYWxsIGZyb21cbiAgIFVzZWQgc3RvcmFnZXM6IGxvY2FsIHx8IHVwbGluayAoanVzdCBvbmUpXG4gICAqL1xuICBwdWJsaWMgZ2V0VGFyYmFsbChuYW1lOiBzdHJpbmcsIGZpbGVuYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCByZWFkU3RyZWFtID0gbmV3IFJlYWRUYXJiYWxsKHt9KTtcbiAgICByZWFkU3RyZWFtLmFib3J0ID0gZnVuY3Rpb24gKCkge307XG5cbiAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgIC8vIENoZWNrIGlmIHRoZSB0YXJiYWxsIGlzIGFsbG93ZWQgYnkgZmlsdGVyIHBsdWdpbnMgYmVmb3JlIHNlcnZpbmcuXG4gICAgLy8gRmlsdGVycyBtYXkgYmxvY2sgc3BlY2lmaWMgdmVyc2lvbnMsIHNvIHdlIHZlcmlmeSB0aGUgdGFyYmFsbCdzIHZlcnNpb25cbiAgICAvLyBzdGlsbCBleGlzdHMgaW4gdGhlIGZpbHRlcmVkIG1ldGFkYXRhLlxuICAgIHRoaXMuX2lzVGFyYmFsbEFsbG93ZWRCeUZpbHRlcnMobmFtZSwgZmlsZW5hbWUpLnRoZW4oYXN5bmMgKGFsbG93ZWQpID0+IHtcbiAgICAgIGlmICghYWxsb3dlZCkge1xuICAgICAgICByZWFkU3RyZWFtLmVtaXQoJ2Vycm9yJywgRXJyb3JDb2RlLmdldE5vdEZvdW5kKEFQSV9FUlJPUi5OT19QQUNLQUdFKSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gdHJ5aW5nIGxvY2FsIGZpcnN0XG4gICAgICBsZXQgbG9jYWxTdHJlYW06IGFueSA9IHNlbGYubG9jYWxTdG9yYWdlLmdldFRhcmJhbGwobmFtZSwgZmlsZW5hbWUpO1xuICAgICAgbGV0IGlzT3BlbiA9IGZhbHNlO1xuICAgICAgbG9jYWxTdHJlYW0ub24oJ2Vycm9yJywgKGVycik6IGFueSA9PiB7XG4gICAgICAgIGlmIChpc09wZW4gfHwgZXJyLnN0YXR1cyAhPT0gSFRUUF9TVEFUVVMuTk9UX0ZPVU5EKSB7XG4gICAgICAgICAgcmV0dXJuIHJlYWRTdHJlYW0uZW1pdCgnZXJyb3InLCBlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gbG9jYWwgcmVwb3J0ZWQgNDA0XG4gICAgICAgIGNvbnN0IGVycjQwNCA9IGVycjtcbiAgICAgICAgbG9jYWxTdHJlYW0uYWJvcnQoKTtcbiAgICAgICAgbG9jYWxTdHJlYW0gPSBudWxsOyAvLyB3ZSBmb3JjZSBmb3IgZ2FyYmFnZSBjb2xsZWN0b3JcblxuICAgICAgICBjb25zdCBsb29rdXBGcm9tVXBsaW5rcyA9IChpbmZvOiBNYW5pZmVzdCB8IG51bGwpOiB2b2lkID0+IHtcbiAgICAgICAgICBzZWxmLl9zeW5jVXBsaW5rc01ldGFkYXRhKFxuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIGluZm8gYXMgTWFuaWZlc3QsXG4gICAgICAgICAgICB7fSxcbiAgICAgICAgICAgIChzeW5jRXJyLCBzeW5jSW5mbzogTWFuaWZlc3QpOiBhbnkgPT4ge1xuICAgICAgICAgICAgICBpZiAoXy5pc05pbChzeW5jRXJyKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVhZFN0cmVhbS5lbWl0KCdlcnJvcicsIHN5bmNFcnIpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChfLmlzTmlsKHN5bmNJbmZvLl9kaXN0ZmlsZXMpIHx8IF8uaXNOaWwoc3luY0luZm8uX2Rpc3RmaWxlc1tmaWxlbmFtZV0pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlYWRTdHJlYW0uZW1pdCgnZXJyb3InLCBlcnI0MDQpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHNlcnZlRmlsZShzeW5jSW5mby5fZGlzdGZpbGVzW2ZpbGVuYW1lXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfTtcblxuICAgICAgICBzZWxmLmxvY2FsU3RvcmFnZS5nZXRQYWNrYWdlTWV0YWRhdGFBc3luYyhuYW1lKS50aGVuKFxuICAgICAgICAgIChpbmZvKSA9PiB7XG4gICAgICAgICAgICBpZiAoaW5mby5fZGlzdGZpbGVzICYmIF8uaXNOaWwoaW5mby5fZGlzdGZpbGVzW2ZpbGVuYW1lXSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgIC8vIGluZm9ybWF0aW9uIGFib3V0IHRoaXMgZmlsZSBleGlzdHMgbG9jYWxseVxuICAgICAgICAgICAgICBzZXJ2ZUZpbGUoaW5mby5fZGlzdGZpbGVzW2ZpbGVuYW1lXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyB3ZSBrbm93IG5vdGhpbmcgYWJvdXQgdGhpcyBmaWxlLCB0cnlpbmcgdG8gZ2V0IGluZm9ybWF0aW9uIGVsc2V3aGVyZVxuICAgICAgICAgICAgICBsb29rdXBGcm9tVXBsaW5rcyhpbmZvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgIC8vIHdlIGtub3cgbm90aGluZyBhYm91dCB0aGlzIGZpbGUsIHRyeWluZyB0byBnZXQgaW5mb3JtYXRpb24gZWxzZXdoZXJlXG4gICAgICAgICAgICBsb29rdXBGcm9tVXBsaW5rcyhudWxsKTtcbiAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICAgIGxvY2FsU3RyZWFtLm9uKCdjb250ZW50LWxlbmd0aCcsIGZ1bmN0aW9uICh2KTogdm9pZCB7XG4gICAgICAgIHJlYWRTdHJlYW0uZW1pdCgnY29udGVudC1sZW5ndGgnLCB2KTtcbiAgICAgIH0pO1xuICAgICAgbG9jYWxTdHJlYW0ub24oJ29wZW4nLCBmdW5jdGlvbiAoKTogdm9pZCB7XG4gICAgICAgIGlzT3BlbiA9IHRydWU7XG4gICAgICAgIGxvY2FsU3RyZWFtLnBpcGUocmVhZFN0cmVhbSk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHJldHVybiByZWFkU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2ggYW5kIGNhY2hlIGxvY2FsL3JlbW90ZSBwYWNrYWdlcy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gZmlsZSBkZWZpbmUgdGhlIHBhY2thZ2Ugc2hhcGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzZXJ2ZUZpbGUoZmlsZTogRGlzdEZpbGUpOiB2b2lkIHtcbiAgICAgIGxldCB1cGxpbms6IGFueSA9IG51bGw7XG5cbiAgICAgIGZvciAoY29uc3QgdXBsaW5rSWQgaW4gc2VsZi51cGxpbmtzKSB7XG4gICAgICAgIGlmIChoYXNQcm94eVRvKG5hbWUsIHVwbGlua0lkLCBzZWxmLmNvbmZpZy5wYWNrYWdlcykpIHtcbiAgICAgICAgICB1cGxpbmsgPSBzZWxmLnVwbGlua3NbdXBsaW5rSWRdO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICh1cGxpbmsgPT0gbnVsbCkge1xuICAgICAgICB1cGxpbmsgPSBuZXcgUHJveHlTdG9yYWdlKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHVybDogZmlsZS51cmwsXG4gICAgICAgICAgICBjYWNoZTogdHJ1ZSxcbiAgICAgICAgICAgIF9hdXRvZ2VuZXJhdGVkOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgc2VsZi5jb25maWdcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgbGV0IHNhdmVzdHJlYW06IGFueSA9IG51bGw7XG4gICAgICBpZiAodXBsaW5rLmNvbmZpZy5jYWNoZSkge1xuICAgICAgICBzYXZlc3RyZWFtID0gc2VsZi5sb2NhbFN0b3JhZ2UuYWRkVGFyYmFsbChuYW1lLCBmaWxlbmFtZSk7XG4gICAgICB9XG5cbiAgICAgIGxldCBvbl9vcGVuID0gZnVuY3Rpb24gKCk6IHZvaWQge1xuICAgICAgICAvLyBwcmV2ZW50IGl0IGZyb20gYmVpbmcgY2FsbGVkIHR3aWNlXG4gICAgICAgIG9uX29wZW4gPSBmdW5jdGlvbiAoKSB7fTtcbiAgICAgICAgY29uc3QgcnN0cmVhbTIgPSB1cGxpbmsuZmV0Y2hUYXJiYWxsKGZpbGUudXJsKTtcbiAgICAgICAgcnN0cmVhbTIub24oJ2Vycm9yJywgZnVuY3Rpb24gKGVycik6IHZvaWQge1xuICAgICAgICAgIGlmIChzYXZlc3RyZWFtKSB7XG4gICAgICAgICAgICBzYXZlc3RyZWFtLmFib3J0KCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHNhdmVzdHJlYW0gPSBudWxsO1xuICAgICAgICAgIHJlYWRTdHJlYW0uZW1pdCgnZXJyb3InLCBlcnIpO1xuICAgICAgICB9KTtcbiAgICAgICAgcnN0cmVhbTIub24oJ2VuZCcsIGZ1bmN0aW9uICgpOiB2b2lkIHtcbiAgICAgICAgICBpZiAoc2F2ZXN0cmVhbSkge1xuICAgICAgICAgICAgc2F2ZXN0cmVhbS5kb25lKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICByc3RyZWFtMi5vbignY29udGVudC1sZW5ndGgnLCBmdW5jdGlvbiAodik6IHZvaWQge1xuICAgICAgICAgIHJlYWRTdHJlYW0uZW1pdCgnY29udGVudC1sZW5ndGgnLCB2KTtcbiAgICAgICAgICBpZiAoc2F2ZXN0cmVhbSkge1xuICAgICAgICAgICAgc2F2ZXN0cmVhbS5lbWl0KCdjb250ZW50LWxlbmd0aCcsIHYpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJzdHJlYW0yLnBpcGUocmVhZFN0cmVhbSk7XG4gICAgICAgIGlmIChzYXZlc3RyZWFtKSB7XG4gICAgICAgICAgcnN0cmVhbTIucGlwZShzYXZlc3RyZWFtKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgaWYgKHNhdmVzdHJlYW0pIHtcbiAgICAgICAgc2F2ZXN0cmVhbS5vbignb3BlbicsIGZ1bmN0aW9uICgpOiB2b2lkIHtcbiAgICAgICAgICBvbl9vcGVuKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNhdmVzdHJlYW0ub24oJ2Vycm9yJywgZnVuY3Rpb24gKGVycik6IHZvaWQge1xuICAgICAgICAgIHNlbGYubG9nZ2VyLndhcm4oXG4gICAgICAgICAgICB7IGVycjogZXJyLCBmaWxlTmFtZTogZmlsZSB9LFxuICAgICAgICAgICAgJ2Vycm9yIHNhdmluZyBmaWxlIEB7ZmlsZU5hbWV9OiBAe2Vyci5tZXNzYWdlfVxcbkB7ZXJyLnN0YWNrfSdcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChzYXZlc3RyZWFtKSB7XG4gICAgICAgICAgICBzYXZlc3RyZWFtLmFib3J0KCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHNhdmVzdHJlYW0gPSBudWxsO1xuICAgICAgICAgIG9uX29wZW4oKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvbl9vcGVuKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICBSZXRyaWV2ZSBhIHBhY2thZ2UgbWV0YWRhdGEgZm9yIHtuYW1lfSBwYWNrYWdlXG4gICBGdW5jdGlvbiBpbnZva2VzIGxvY2FsU3RvcmFnZS5nZXRQYWNrYWdlIGFuZCB1cGxpbmsuZ2V0X3BhY2thZ2UgZm9yIGV2ZXJ5XG4gICB1cGxpbmsgd2l0aCBwcm94eV9hY2Nlc3MgcmlnaHRzIGFnYWluc3Qge25hbWV9IGFuZCBjb21iaW5lcyByZXN1bHRzXG4gICBpbnRvIG9uZSBqc29uIG9iamVjdFxuICAgVXNlZCBzdG9yYWdlczogbG9jYWwgJiYgdXBsaW5rIChwcm94eV9hY2Nlc3MpXG5cbiAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IG9wdGlvbnMubmFtZSBQYWNrYWdlIE5hbWVcbiAgICogQHByb3BlcnR5IHtvYmplY3R9ICBvcHRpb25zLnJlcSBFeHByZXNzIGByZXFgIG9iamVjdFxuICAgKiBAcHJvcGVydHkge2Jvb2xlYW59IG9wdGlvbnMua2VlcFVwTGlua0RhdGEga2VlcCB1cCBsaW5rIGluZm8gaW4gcGFja2FnZSBtZXRhLCBsYXN0IHVwZGF0ZSwgZXRjLlxuICAgKiBAcHJvcGVydHkge2Z1bmN0aW9ufSBvcHRpb25zLmNhbGxiYWNrIENhbGxiYWNrIGZvciByZWNlaXZlIGRhdGFcbiAgICovXG4gIHB1YmxpYyBnZXRQYWNrYWdlKG9wdGlvbnMpOiB2b2lkIHtcbiAgICB0aGlzLmxvY2FsU3RvcmFnZS5nZXRQYWNrYWdlTWV0YWRhdGEob3B0aW9ucy5uYW1lLCAoZXJyLCBkYXRhKTogdm9pZCA9PiB7XG4gICAgICBpZiAoZXJyICYmICghZXJyLnN0YXR1cyB8fCBlcnIuc3RhdHVzID49IEhUVFBfU1RBVFVTLklOVEVSTkFMX0VSUk9SKSkge1xuICAgICAgICAvLyByZXBvcnQgaW50ZXJuYWwgZXJyb3JzIHJpZ2h0IGF3YXlcbiAgICAgICAgcmV0dXJuIG9wdGlvbnMuY2FsbGJhY2soZXJyKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fc3luY1VwbGlua3NNZXRhZGF0YShcbiAgICAgICAgb3B0aW9ucy5uYW1lLFxuICAgICAgICBkYXRhLFxuICAgICAgICB7IHJlcTogb3B0aW9ucy5yZXEsIHVwbGlua3NMb29rOiBvcHRpb25zLnVwbGlua3NMb29rIH0sXG4gICAgICAgIGZ1bmN0aW9uIGdldFBhY2thZ2VTeW5VcExpbmtzQ2FsbGJhY2soZXJyLCByZXN1bHQ6IE1hbmlmZXN0LCB1cGxpbmtFcnJvcnMpOiB2b2lkIHtcbiAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICByZXR1cm4gb3B0aW9ucy5jYWxsYmFjayhlcnIpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIG5vcm1hbGl6ZURpc3RUYWdzKGNsZWFuVXBMaW5rc1JlZihvcHRpb25zLmtlZXBVcExpbmtEYXRhLCByZXN1bHQpKTtcblxuICAgICAgICAgIC8vIG5wbSBjYW4gdGhyb3cgaWYgdGhpcyBmaWVsZCBkb2Vzbid0IGV4aXN0XG4gICAgICAgICAgcmVzdWx0Ll9hdHRhY2htZW50cyA9IHt9O1xuICAgICAgICAgIGlmIChvcHRpb25zLmFiYnJldmlhdGVkID09PSB0cnVlKSB7XG4gICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKG51bGwsIGNvbnZlcnRBYmJyZXZpYXRlZE1hbmlmZXN0KHJlc3VsdCksIHVwbGlua0Vycm9ycyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG9wdGlvbnMuY2FsbGJhY2sobnVsbCwgcmVzdWx0LCB1cGxpbmtFcnJvcnMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgUmV0cmlldmUgcmVtb3RlIGFuZCBsb2NhbCBwYWNrYWdlcyBtb3JlIHJlY2VudCB0aGFuIHtzdGFydGtleX1cbiAgIEZ1bmN0aW9uIHN0cmVhbXMgYWxsIHBhY2thZ2VzIGZyb20gYWxsIHVwbGlua3MgZmlyc3QsIGFuZCB0aGVuXG4gICBsb2NhbCBwYWNrYWdlcy5cbiAgIE5vdGUgdGhhdCBsb2NhbCBwYWNrYWdlcyBjb3VsZCBvdmVycmlkZSByZWdpc3RyeSBvbmVzIGp1c3QgYmVjYXVzZVxuICAgdGhleSBhcHBlYXIgaW4gSlNPTiBsYXN0LiBUaGF0J3MgYSB0cmFkZS1vZmYgd2UgbWFrZSB0byBhdm9pZFxuICAgbWVtb3J5IGlzc3Vlcy5cbiAgIFVzZWQgc3RvcmFnZXM6IGxvY2FsICYmIHVwbGluayAocHJveHlfYWNjZXNzKVxuICAgKiBAcGFyYW0geyp9IHN0YXJ0a2V5XG4gICAqIEBwYXJhbSB7Kn0gb3B0aW9uc1xuICAgKiBAcmV0dXJuIHtTdHJlYW19XG4gICAqL1xuICBwdWJsaWMgc2VhcmNoKHN0YXJ0a2V5OiBzdHJpbmcsIG9wdGlvbnM6IGFueSkge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIGNvbnN0IHNlYXJjaFN0cmVhbTogYW55ID0gbmV3IFN0cmVhbS5QYXNzVGhyb3VnaCh7IG9iamVjdE1vZGU6IHRydWUgfSk7XG4gICAgYXN5bmMuZWFjaFNlcmllcyhcbiAgICAgIE9iamVjdC5rZXlzKHRoaXMudXBsaW5rcyksXG4gICAgICBmdW5jdGlvbiAodXBfbmFtZSwgY2IpOiB2b2lkIHtcbiAgICAgICAgLy8gc2hvcnRjdXQ6IGlmIGBsb2NhbD0xYCBpcyBzdXBwbGllZCwgZG9uJ3QgY2FsbCB1cGxpbmtzXG4gICAgICAgIGlmIChvcHRpb25zLnJlcT8ucXVlcnk/LmxvY2FsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXR1cm4gY2IoKTtcbiAgICAgICAgfVxuICAgICAgICBsb2dnZXIuaW5mbyhgc2VhcmNoIGZvciB1cGxpbmsgJHt1cF9uYW1lfWApO1xuICAgICAgICAvLyBzZWFyY2ggYnkga2V5d29yZCBmb3IgZWFjaCB1cGxpbmtcbiAgICAgICAgY29uc3QgdXBsaW5rU3RyZWFtID0gc2VsZi51cGxpbmtzW3VwX25hbWVdLnNlYXJjaChvcHRpb25zKTtcbiAgICAgICAgLy8gam9pbiB1cGxpbmsgc3RyZWFtIHdpdGggc3RyZWFtcyBQYXNzVGhyb3VnaFxuICAgICAgICB1cGxpbmtTdHJlYW0ucGlwZShzZWFyY2hTdHJlYW0sIHsgZW5kOiBmYWxzZSB9KTtcbiAgICAgICAgdXBsaW5rU3RyZWFtLm9uKCdlcnJvcicsIGZ1bmN0aW9uIChlcnIpOiB2b2lkIHtcbiAgICAgICAgICBzZWxmLmxvZ2dlci5lcnJvcih7IGVycjogZXJyIH0sICd1cGxpbmsgZXJyb3I6IEB7ZXJyLm1lc3NhZ2V9Jyk7XG4gICAgICAgICAgY2IoKTtcbiAgICAgICAgICAvLyB0byBhdm9pZCBjYWxsIGNhbGxiYWNrIG1vcmUgdGhhbiBvbmNlXG4gICAgICAgICAgY2IgPSBmdW5jdGlvbiAoKTogdm9pZCB7fTtcbiAgICAgICAgfSk7XG4gICAgICAgIHVwbGlua1N0cmVhbS5vbignZW5kJywgZnVuY3Rpb24gKCk6IHZvaWQge1xuICAgICAgICAgIGNiKCk7XG4gICAgICAgICAgLy8gdG8gYXZvaWQgY2FsbCBjYWxsYmFjayBtb3JlIHRoYW4gb25jZVxuICAgICAgICAgIGNiID0gZnVuY3Rpb24gKCk6IHZvaWQge307XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNlYXJjaFN0cmVhbS5hYm9ydCA9IGZ1bmN0aW9uICgpOiB2b2lkIHtcbiAgICAgICAgICBpZiAodXBsaW5rU3RyZWFtLmFib3J0KSB7XG4gICAgICAgICAgICB1cGxpbmtTdHJlYW0uYWJvcnQoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY2IoKTtcbiAgICAgICAgICAvLyB0byBhdm9pZCBjYWxsIGNhbGxiYWNrIG1vcmUgdGhhbiBvbmNlXG4gICAgICAgICAgY2IgPSBmdW5jdGlvbiAoKTogdm9pZCB7fTtcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgICAvLyBleGVjdXRlZCBhZnRlciBhbGwgc2VyaWVzXG4gICAgICBmdW5jdGlvbiAoKTogdm9pZCB7XG4gICAgICAgIC8vIGF0dGFjaCBhIGxvY2FsIHNlYXJjaCByZXN1bHRzXG4gICAgICAgIGNvbnN0IGxvY2FsU2VhcmNoU3RyZWFtID0gc2VsZi5sb2NhbFN0b3JhZ2Uuc2VhcmNoKHN0YXJ0a2V5LCBvcHRpb25zKTtcbiAgICAgICAgc2VhcmNoU3RyZWFtLmFib3J0ID0gZnVuY3Rpb24gKCk6IHZvaWQge1xuICAgICAgICAgIGxvY2FsU2VhcmNoU3RyZWFtLmFib3J0KCk7XG4gICAgICAgIH07XG4gICAgICAgIGxvY2FsU2VhcmNoU3RyZWFtLnBpcGUoc2VhcmNoU3RyZWFtLCB7IGVuZDogdHJ1ZSB9KTtcbiAgICAgICAgbG9jYWxTZWFyY2hTdHJlYW0ub24oJ2Vycm9yJywgZnVuY3Rpb24gKGVycjogYW55KTogdm9pZCB7XG4gICAgICAgICAgc2VsZi5sb2dnZXIuZXJyb3IoeyBlcnI6IGVyciB9LCAnc2VhcmNoIGVycm9yOiBAe2Vyci5tZXNzYWdlfScpO1xuICAgICAgICAgIHNlYXJjaFN0cmVhbS5lbmQoKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgKTtcblxuICAgIHJldHVybiBzZWFyY2hTdHJlYW07XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmUgb25seSBwcml2YXRlIGxvY2FsIHBhY2thZ2VzXG4gICAqIEBwYXJhbSB7Kn0gY2FsbGJhY2tcbiAgICovXG4gIHB1YmxpYyBnZXRMb2NhbERhdGFiYXNlKGNhbGxiYWNrOiBDYWxsYmFjayk6IHZvaWQge1xuICAgIHRoaXMubG9jYWxTdG9yYWdlLnN0b3JhZ2VQbHVnaW4uZ2V0KChlcnIsIGxvY2Fscyk6IHZvaWQgPT4ge1xuICAgICAgaWYgKGVycikge1xuICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fY29sbGVjdExvY2FsUGFja2FnZXMobG9jYWxzKS50aGVuKFxuICAgICAgICAocGFja2FnZXMpID0+IGNhbGxiYWNrKG51bGwsIHBhY2thZ2VzKSxcbiAgICAgICAgKGVycikgPT4gY2FsbGJhY2soZXJyKVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWFkIGVhY2ggbG9jYWwgcGFja2FnZSBuYW1lLCBhcHBseSBmaWx0ZXJzLCBhbmQgY29sbGVjdCB0aGUgbGF0ZXN0IHZlcnNpb24uXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIF9jb2xsZWN0TG9jYWxQYWNrYWdlcyhsb2NhbHM6IHN0cmluZ1tdKTogUHJvbWlzZTxWZXJzaW9uW10+IHtcbiAgICBjb25zdCBwYWNrYWdlczogVmVyc2lvbltdID0gW107XG4gICAgZm9yIChjb25zdCBuYW1lIG9mIGxvY2Fscykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcGtnTWV0YWRhdGEgPSBhd2FpdCB0aGlzLmxvY2FsU3RvcmFnZS5nZXRQYWNrYWdlTWV0YWRhdGFBc3luYyhuYW1lKTtcbiAgICAgICAgY29uc3QgeyBmaWx0ZXJlZFBhY2thZ2UgfSA9IGF3YWl0IHRoaXMuX2FwcGx5RmlsdGVycyhwa2dNZXRhZGF0YSk7XG4gICAgICAgIGNvbnN0IGxhdGVzdCA9IGZpbHRlcmVkUGFja2FnZVtESVNUX1RBR1NdPy5sYXRlc3Q7XG4gICAgICAgIGlmIChsYXRlc3QgJiYgZmlsdGVyZWRQYWNrYWdlLnZlcnNpb25zW2xhdGVzdF0pIHtcbiAgICAgICAgICBjb25zdCB2ZXJzaW9uOiBWZXJzaW9uID0gZmlsdGVyZWRQYWNrYWdlLnZlcnNpb25zW2xhdGVzdF07XG4gICAgICAgICAgY29uc3QgdGltZUxpc3QgPSBmaWx0ZXJlZFBhY2thZ2UudGltZSBhcyBHZW5lcmljQm9keTtcbiAgICAgICAgICBjb25zdCB0aW1lID0gdGltZUxpc3RbbGF0ZXN0XTtcbiAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgdmVyc2lvbi50aW1lID0gdGltZTtcblxuICAgICAgICAgIC8vIEFkZCBmb3Igc3RhcnMgYXBpXG4gICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgIHZlcnNpb24udXNlcnMgPSBmaWx0ZXJlZFBhY2thZ2UudXNlcnM7XG5cbiAgICAgICAgICBwYWNrYWdlcy5wdXNoKHZlcnNpb24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oeyBwYWNrYWdlOiBuYW1lIH0sICdwYWNrYWdlIEB7cGFja2FnZX0gZG9lcyBub3QgaGF2ZSBhIFwibGF0ZXN0XCIgdGFnPycpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoeyBlcnIsIHBhY2thZ2U6IG5hbWUgfSwgJ2Vycm9yIHJlYWRpbmcgcGFja2FnZSBAe3BhY2thZ2V9Jyk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwYWNrYWdlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBGdW5jdGlvbiBmZXRjaGVzIHBhY2thZ2UgbWV0YWRhdGEgZnJvbSB1cGxpbmtzIGFuZCBzeW5jaHJvbml6ZXMgaXQgd2l0aCBsb2NhbCBkYXRhXG4gICBpZiBwYWNrYWdlIGlzIGF2YWlsYWJsZSBsb2NhbGx5LCBpdCBNVVNUIGJlIHByb3ZpZGVkIGluIHBrZ2luZm9cbiAgIHJldHVybnMgY2FsbGJhY2soZXJyLCByZXN1bHQsIHVwbGlua19lcnJvcnMpXG4gICAqL1xuICBwdWJsaWMgX3N5bmNVcGxpbmtzTWV0YWRhdGEoXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIHBhY2thZ2VJbmZvOiBNYW5pZmVzdCxcbiAgICBvcHRpb25zOiBJU3luY1VwbGlua3MsXG4gICAgY2FsbGJhY2s6IENhbGxiYWNrXG4gICk6IHZvaWQge1xuICAgIGxldCBmb3VuZCA9IHRydWU7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgY29uc3QgdXBMaW5rczogUHJveHlTdG9yYWdlW10gPSBbXTtcbiAgICBjb25zdCBoYXNUb0xvb2tJbnRvVXBsaW5rcyA9IF8uaXNOaWwob3B0aW9ucy51cGxpbmtzTG9vaykgfHwgb3B0aW9ucy51cGxpbmtzTG9vaztcblxuICAgIGlmICghcGFja2FnZUluZm8pIHtcbiAgICAgIGZvdW5kID0gZmFsc2U7XG4gICAgICBwYWNrYWdlSW5mbyA9IGdlbmVyYXRlUGFja2FnZVRlbXBsYXRlKG5hbWUpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgdXBsaW5rIGluIHRoaXMudXBsaW5rcykge1xuICAgICAgaWYgKGhhc1Byb3h5VG8obmFtZSwgdXBsaW5rLCB0aGlzLmNvbmZpZy5wYWNrYWdlcykgJiYgaGFzVG9Mb29rSW50b1VwbGlua3MpIHtcbiAgICAgICAgdXBMaW5rcy5wdXNoKHRoaXMudXBsaW5rc1t1cGxpbmtdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYy5tYXAoXG4gICAgICB1cExpbmtzLFxuICAgICAgKHVwTGluazogUHJveHlTdG9yYWdlLCBjYik6IHZvaWQgPT4ge1xuICAgICAgICBjb25zdCBfb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIG9wdGlvbnMpO1xuICAgICAgICBjb25zdCB1cExpbmtNZXRhID0gcGFja2FnZUluZm8uX3VwbGlua3NbdXBMaW5rLnVwbmFtZV07XG5cbiAgICAgICAgaWYgKGlzT2JqZWN0KHVwTGlua01ldGEpKSB7XG4gICAgICAgICAgY29uc3QgZmV0Y2hlZCA9IHVwTGlua01ldGEuZmV0Y2hlZDtcblxuICAgICAgICAgIGlmIChmZXRjaGVkICYmIERhdGUubm93KCkgLSBmZXRjaGVkIDwgdXBMaW5rLm1heGFnZSkge1xuICAgICAgICAgICAgcmV0dXJuIGNiKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgX29wdGlvbnMuZXRhZyA9IHVwTGlua01ldGEuZXRhZztcbiAgICAgICAgfVxuXG4gICAgICAgIHVwTGluay5nZXRSZW1vdGVNZXRhZGF0YShuYW1lLCBfb3B0aW9ucywgKGVyciwgdXBMaW5rUmVzcG9uc2UsIGVUYWcpOiB2b2lkID0+IHtcbiAgICAgICAgICBpZiAoZXJyICYmIGVyci5yZW1vdGVTdGF0dXMgPT09IDMwNCkge1xuICAgICAgICAgICAgdXBMaW5rTWV0YS5mZXRjaGVkID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoZXJyIHx8ICF1cExpbmtSZXNwb25zZSkge1xuICAgICAgICAgICAgcmV0dXJuIGNiKG51bGwsIFtlcnIgfHwgRXJyb3JDb2RlLmdldEludGVybmFsRXJyb3IoJ25vIGRhdGEnKV0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB1cExpbmtSZXNwb25zZSA9IHZhbGlkYXRpb25VdGlscy5ub3JtYWxpemVNZXRhZGF0YSh1cExpbmtSZXNwb25zZSwgbmFtZSk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBzZWxmLmxvZ2dlci5lcnJvcihcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHN1YjogJ291dCcsXG4gICAgICAgICAgICAgICAgZXJyOiBlcnIsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICdwYWNrYWdlLmpzb24gdmFsaWRhdGluZyBlcnJvciBAeyFlcnIubWVzc2FnZX1cXG5Ae2Vyci5zdGFja30nXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIGNiKG51bGwsIFtlcnJdKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBwYWNrYWdlSW5mby5fdXBsaW5rc1t1cExpbmsudXBuYW1lXSA9IHtcbiAgICAgICAgICAgIGV0YWc6IGVUYWcsXG4gICAgICAgICAgICBmZXRjaGVkOiBEYXRlLm5vdygpLFxuICAgICAgICAgIH07XG5cbiAgICAgICAgICBwYWNrYWdlSW5mbyA9IG1lcmdlVXBsaW5rVGltZUludG9Mb2NhbChwYWNrYWdlSW5mbywgdXBMaW5rUmVzcG9uc2UpO1xuXG4gICAgICAgICAgdXBkYXRlVmVyc2lvbnNIaWRkZW5VcExpbmsodXBMaW5rUmVzcG9uc2UudmVyc2lvbnMsIHVwTGluayk7XG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgbWVyZ2VWZXJzaW9ucyhwYWNrYWdlSW5mbywgdXBMaW5rUmVzcG9uc2UpO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgc2VsZi5sb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBzdWI6ICdvdXQnLFxuICAgICAgICAgICAgICAgIGVycjogZXJyLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAncGFja2FnZS5qc29uIHBhcnNpbmcgZXJyb3IgQHshZXJyLm1lc3NhZ2V9XFxuQHtlcnIuc3RhY2t9J1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiBjYihudWxsLCBbZXJyXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gaWYgd2UgZ290IHRvIHRoaXMgcG9pbnQsIGFzc3VtZSB0aGF0IHRoZSBjb3JyZWN0IHBhY2thZ2UgZXhpc3RzXG4gICAgICAgICAgLy8gb24gdGhlIHVwbGlua1xuICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICBjYigpO1xuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICBhc3luYyAoZXJyOiBFcnJvciwgdXBMaW5rc0Vycm9yczogYW55KTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIGFzc2VydCghZXJyICYmIEFycmF5LmlzQXJyYXkodXBMaW5rc0Vycm9ycykpO1xuXG4gICAgICAgIC8vIENoZWNrIGZvciBjb25uZWN0aW9uIHRpbWVvdXQgb3IgcmVzZXQgZXJyb3JzIHdpdGggdXBsaW5rKHMpXG4gICAgICAgIC8vICh0aGVzZSBzaG91bGQgYmUgaGFuZGxlZCBkaWZmZXJlbnRseSBmcm9tIHRoZSBwYWNrYWdlIG5vdCBiZWluZyBmb3VuZClcbiAgICAgICAgaWYgKCFmb3VuZCkge1xuICAgICAgICAgIGxldCB1cGxpbmtUaW1lb3V0RXJyb3I7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB1cExpbmtzRXJyb3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodXBMaW5rc0Vycm9yc1tpXSkge1xuICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHVwTGlua3NFcnJvcnNbaV0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBpZiAodXBMaW5rc0Vycm9yc1tpXVtqXSkge1xuICAgICAgICAgICAgICAgICAgY29uc3QgY29kZSA9IHVwTGlua3NFcnJvcnNbaV1bal0uY29kZTtcbiAgICAgICAgICAgICAgICAgIGlmIChjb2RlID09PSAnRVRJTUVET1VUJyB8fCBjb2RlID09PSAnRVNPQ0tFVFRJTUVET1VUJyB8fCBjb2RlID09PSAnRUNPTk5SRVNFVCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdXBsaW5rVGltZW91dEVycm9yID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHVwbGlua1RpbWVvdXRFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKEVycm9yQ29kZS5nZXRTZXJ2aWNlVW5hdmFpbGFibGUoKSwgbnVsbCwgdXBMaW5rc0Vycm9ycyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBjYWxsYmFjayhFcnJvckNvZGUuZ2V0Tm90Rm91bmQoQVBJX0VSUk9SLk5PX1BBQ0tBR0UpLCBudWxsLCB1cExpbmtzRXJyb3JzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh1cExpbmtzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGNvbnN0IHsgZmlsdGVyZWRQYWNrYWdlLCBmaWx0ZXJFcnJvcnMgfSA9IGF3YWl0IHNlbGYuX2FwcGx5RmlsdGVycyhcbiAgICAgICAgICAgIHBhY2thZ2VJbmZvIGFzIE1hbmlmZXN0XG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgZmlsdGVyZWRQYWNrYWdlLCBmaWx0ZXJFcnJvcnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBwYWNrYWdlSnNvbkxvY2FsID0gYXdhaXQgc2VsZi5sb2NhbFN0b3JhZ2UudXBkYXRlVmVyc2lvbnNBc3luYyhuYW1lLCBwYWNrYWdlSW5mbyk7XG4gICAgICAgICAgY29uc3QgeyBmaWx0ZXJlZFBhY2thZ2UsIGZpbHRlckVycm9ycyB9ID0gYXdhaXQgc2VsZi5fYXBwbHlGaWx0ZXJzKHBhY2thZ2VKc29uTG9jYWwpO1xuICAgICAgICAgIGNhbGxiYWNrKG51bGwsIGZpbHRlcmVkUGFja2FnZSwgXy5jb25jYXQodXBMaW5rc0Vycm9ycywgZmlsdGVyRXJyb3JzKSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGx5IGFsbCBjb25maWd1cmVkIGZpbHRlciBwbHVnaW5zIHRvIGEgcGFja2FnZSBtYW5pZmVzdCBzZXF1ZW50aWFsbHkuXG4gICAqIEVhY2ggZmlsdGVyJ3Mgb3V0cHV0IGlzIHBhc3NlZCBhcyBpbnB1dCB0byB0aGUgbmV4dCBmaWx0ZXIuXG4gICAqIFJldHVybnMgdGhlIGZpbHRlcmVkIG1hbmlmZXN0IGFuZCBhbnkgZXJyb3JzIHRoYXQgb2NjdXJyZWQuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIF9hcHBseUZpbHRlcnMoXG4gICAgcGFja2FnZUluZm86IE1hbmlmZXN0XG4gICk6IFByb21pc2U8eyBmaWx0ZXJlZFBhY2thZ2U6IE1hbmlmZXN0OyBmaWx0ZXJFcnJvcnM6IEVycm9yW10gfT4ge1xuICAgIGNvbnN0IGZpbHRlckVycm9yczogRXJyb3JbXSA9IFtdO1xuICAgIGxldCBmaWx0ZXJlZFBhY2thZ2UgPSBwYWNrYWdlSW5mbztcbiAgICBmb3IgKGNvbnN0IGZpbHRlciBvZiB0aGlzLmZpbHRlcnMgPz8gW10pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGZpbHRlcmVkUGFja2FnZSA9IGF3YWl0IGZpbHRlci5maWx0ZXJfbWV0YWRhdGEoZmlsdGVyZWRQYWNrYWdlKTtcbiAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgIGZpbHRlckVycm9ycy5wdXNoKGVycik7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IGZpbHRlcmVkUGFja2FnZSwgZmlsdGVyRXJyb3JzIH07XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgYSB0YXJiYWxsIHNob3VsZCBiZSBzZXJ2ZWQgYmFzZWQgb24gZmlsdGVyIHBsdWdpbnMuXG4gICAqIExvb2tzIHVwIHBhY2thZ2UgbWV0YWRhdGEsIGFwcGxpZXMgZmlsdGVycywgYW5kIHZlcmlmaWVzIHRoZSB0YXJiYWxsXG4gICAqIHN0aWxsIGJlbG9uZ3MgdG8gYW4gYWxsb3dlZCB2ZXJzaW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBfaXNUYXJiYWxsQWxsb3dlZEJ5RmlsdGVycyhuYW1lOiBzdHJpbmcsIGZpbGVuYW1lOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAoIXRoaXMuZmlsdGVycz8ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcGtnTWV0YWRhdGEgPSBhd2FpdCB0aGlzLmxvY2FsU3RvcmFnZS5nZXRQYWNrYWdlTWV0YWRhdGFBc3luYyhuYW1lKTtcbiAgICAgIGNvbnN0IHsgZmlsdGVyZWRQYWNrYWdlIH0gPSBhd2FpdCB0aGlzLl9hcHBseUZpbHRlcnMocGtnTWV0YWRhdGEpO1xuICAgICAgcmV0dXJuIE9iamVjdC52YWx1ZXMoZmlsdGVyZWRQYWNrYWdlLnZlcnNpb25zIHx8IHt9KS5zb21lKCh2ZXJzaW9uKSA9PlxuICAgICAgICAodmVyc2lvbiBhcyBWZXJzaW9uKS5kaXN0Py50YXJiYWxsPy5lbmRzV2l0aCgnLycgKyBmaWxlbmFtZSlcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgIGlmIChlcnI/LnN0YXR1cyA9PT0gSFRUUF9TVEFUVVMuTk9UX0ZPVU5EKSB7XG4gICAgICAgIC8vIFBhY2thZ2Ugbm90IHlldCBjYWNoZWQgbG9jYWxseSDigJQgdGhlIHJlcXVlc3Qgd2lsbCBmYWxsIHRocm91Z2ggdG8gdXBsaW5rcy5cbiAgICAgICAgZGVidWcoJ3BhY2thZ2UgJW8gbm90IGNhY2hlZCBsb2NhbGx5LCBza2lwcGluZyB0YXJiYWxsIGZpbHRlciBjaGVjaycsIG5hbWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoXG4gICAgICAgICAgeyBwYWNrYWdlOiBuYW1lLCBmaWxlTmFtZTogZmlsZW5hbWUsIGVyciB9LFxuICAgICAgICAgICdlcnJvciBjaGVja2luZyBmaWx0ZXJzIGZvciB0YXJiYWxsIEB7ZmlsZU5hbWV9IG9mIHBhY2thZ2UgQHtwYWNrYWdlfTogQHtlcnIubWVzc2FnZX0nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0IGEgaGlkZGVuIHZhbHVlIGZvciBlYWNoIHZlcnNpb24uXG4gICAqIEBwYXJhbSB7QXJyYXl9IHZlcnNpb25zIGxpc3Qgb2YgdmVyc2lvblxuICAgKiBAcGFyYW0ge1N0cmluZ30gdXBMaW5rIHVwbGluayBuYW1lXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwdWJsaWMgX3VwZGF0ZVZlcnNpb25zSGlkZGVuVXBMaW5rKHZlcnNpb25zOiBWZXJzaW9ucywgdXBMaW5rOiBQcm94eVN0b3JhZ2UpOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IGkgaW4gdmVyc2lvbnMpIHtcbiAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodmVyc2lvbnMsIGkpKSB7XG4gICAgICAgIGNvbnN0IHZlcnNpb24gPSB2ZXJzaW9uc1tpXTtcblxuICAgICAgICAvLyBob2xkcyBhIFwiaGlkZGVuXCIgdmFsdWUgdG8gYmUgdXNlZCBieSB0aGUgcGFja2FnZSBzdG9yYWdlLlxuICAgICAgICB2ZXJzaW9uW1N5bWJvbC5mb3IoJ19fdmVyZGFjY2lvX3VwbGluaycpXSA9IHVwTGluay51cG5hbWU7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFN0b3JhZ2U7XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLElBQUFBLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLE1BQUEsR0FBQUYsc0JBQUEsQ0FB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
|