UNPKG

71.6 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const tslib_1 = require("tslib");
4const asynciterablex_1 = require("@reactivex/ix-es2015-cjs/asynciterable/asynciterablex");
5const flatmap_1 = require("@reactivex/ix-es2015-cjs/asynciterable/pipe/flatmap");
6const toobservable_1 = require("@reactivex/ix-es2015-cjs/asynciterable/toobservable");
7const lodash_1 = tslib_1.__importDefault(require("lodash"));
8const rxjs_1 = require("rxjs");
9const operators_1 = require("rxjs/operators");
10const tapable_1 = require("tapable");
11const args = tslib_1.__importStar(require("./args"));
12const errors_1 = require("./errors");
13const sc_1 = require("./sc");
14/**
15 * Main entrypoint to the `@neo-one/client` APIs. The `Client` class abstracts away user accounts and even how those accounts are provided to your dapp, for example, they might come from an extension like NEX, dapp browser like nOS or through some other integration.
16 *
17 * See the [Client APIs](https://neo-one.io/docs/client-apis) chapter of the main guide for more information.
18 */
19class Client {
20 constructor(providersIn) {
21 this.reset$ = new rxjs_1.BehaviorSubject(undefined);
22 this.hooks = {
23 beforeRelay: new tapable_1.AsyncParallelHook(['beforeRelay']),
24 relayError: new tapable_1.AsyncParallelHook(['error']),
25 afterRelay: new tapable_1.AsyncParallelHook(['transaction']),
26 beforeConfirmed: new tapable_1.AsyncParallelHook(['transaction']),
27 confirmedError: new tapable_1.AsyncParallelHook(['transaction', 'error']),
28 afterConfirmed: new tapable_1.AsyncParallelHook(['transaction', 'receipt']),
29 afterCall: new tapable_1.AsyncParallelHook(['receipt']),
30 callError: new tapable_1.AsyncParallelHook(['error']),
31 };
32 const providersArray = Object.values(providersIn);
33 const providerIn = providersArray.find((provider) => provider.getCurrentUserAccount() !== undefined) ||
34 providersArray[0];
35 if (providerIn === undefined) {
36 throw new Error('At least one provider is required');
37 }
38 this.providers$ = new rxjs_1.BehaviorSubject(providersIn);
39 this.selectedProvider$ = new rxjs_1.BehaviorSubject(providerIn);
40 this.currentUserAccount$ = this.selectedProvider$.pipe(operators_1.switchMap((provider) => provider.currentUserAccount$));
41 this.userAccounts$ = this.providers$.pipe(operators_1.switchMap((providers) => rxjs_1.combineLatest(Object.values(providers).map((provider) => provider.userAccounts$))), operators_1.map((accountss) => accountss.reduce((acc, accounts) => acc.concat(accounts), [])));
42 this.networks$ = this.providers$.pipe(operators_1.switchMap((providers) => rxjs_1.combineLatest(Object.values(providers).map((provider) => provider.networks$))), operators_1.map((networkss) => [...new Set(networkss.reduce((acc, networks) => acc.concat(networks), []))]));
43 this.currentNetworkInternal$ = new rxjs_1.BehaviorSubject(providerIn.getNetworks()[0]);
44 rxjs_1.combineLatest([this.currentUserAccount$, this.selectedProvider$])
45 .pipe(operators_1.map(([currentAccount, provider]) => {
46 if (currentAccount !== undefined) {
47 return currentAccount.id.network;
48 }
49 const mainNetwork = provider.getNetworks().find((network) => network === 'main');
50 return mainNetwork === undefined ? provider.getNetworks()[0] : mainNetwork;
51 }))
52 .subscribe(this.currentNetworkInternal$);
53 this.currentNetwork$ = this.currentNetworkInternal$.pipe(operators_1.distinctUntilChanged());
54 if (this.getCurrentUserAccount() === undefined) {
55 this.userAccounts$
56 .pipe(operators_1.filter((accounts) => accounts.length > 0), operators_1.take(1))
57 .toPromise()
58 .then(async (accounts) => {
59 const account = accounts[0];
60 if (this.getCurrentUserAccount() === undefined && account !== undefined) {
61 await this.selectUserAccount(account.id);
62 }
63 })
64 /* istanbul ignore next */
65 .catch(() => {
66 // Just ignore errors here.
67 });
68 }
69 this.block$ = this.reset$.pipe(operators_1.switchMap(() => this.currentNetwork$.pipe(operators_1.switchMap((network) => new rxjs_1.Observable((observer) => toobservable_1.toObservable(this.getNetworkProvider(network).iterBlocks(network)).subscribe(observer)).pipe(operators_1.map((block) => ({ block, network })))))), operators_1.multicast(() => new rxjs_1.ReplaySubject(1)), operators_1.refCount());
70 this.accountState$ = rxjs_1.combineLatest([this.currentUserAccount$, this.block$]).pipe(operators_1.switchMap(async ([currentUserAccount]) => {
71 if (currentUserAccount === undefined) {
72 return undefined;
73 }
74 const account = await this.getNetworkProvider(currentUserAccount.id.network).getAccount(currentUserAccount.id.network, currentUserAccount.id.address);
75 return { currentUserAccount, account };
76 }), operators_1.distinctUntilChanged((a, b) => lodash_1.default.isEqual(a, b)), operators_1.multicast(() => new rxjs_1.ReplaySubject(1)), operators_1.refCount());
77 }
78 /**
79 * The configured `UserAccountProvider`s for this `Client` instance.
80 */
81 get providers() {
82 return this.providers$.getValue();
83 }
84 /**
85 * Get the details of the `UserAccount` for a given `UserAccountID`.
86 *
87 * @param idIn `UserAccountID` to find the `UserAccount` for
88 * @returns `UserAccount` or throws an `UnknownAccountError` if one could not be found.
89 */
90 getUserAccount(idIn) {
91 const id = args.assertUserAccountID('id', idIn);
92 const provider = this.getProvider({ from: id });
93 const account = provider
94 .getUserAccounts()
95 .find((acct) => acct.id.network === id.network && acct.id.address === id.address);
96 if (account === undefined) {
97 /* istanbul ignore next */
98 throw new errors_1.UnknownAccountError(id.address);
99 }
100 return account;
101 }
102 /**
103 * Sets a `UserAccountID` as the currently selected `UserAccountID`.
104 *
105 * @param idIn `UserAccountID` to select, or `undefined` to deselect the current `UserAccountID`.
106 */
107 async selectUserAccount(idIn) {
108 const id = args.assertNullableUserAccountID('id', idIn);
109 const provider = this.getProvider({ from: id });
110 await provider.selectUserAccount(id);
111 this.selectedProvider$.next(provider);
112 }
113 /**
114 * Sets a `NetworkType` as the currently selected `NetworkType`.
115 *
116 * @param networkIn `NetworkType` to select.
117 */
118 async selectNetwork(networkIn) {
119 const network = args.assertString('network', networkIn);
120 const provider = this.getNetworkProvider(network);
121 const account = provider.getCurrentUserAccount();
122 if (account === undefined) {
123 const accounts = provider.getUserAccounts();
124 if (accounts.length > 0) {
125 await provider.selectUserAccount(accounts[0].id);
126 }
127 }
128 this.selectedProvider$.next(provider);
129 }
130 /**
131 * @returns `Promise` which resolves to the `UserAccountFeatures` supported by the given `UserAccountID`.
132 */
133 async getSupportedFeatures(idIn) {
134 const id = args.assertUserAccountID('id', idIn);
135 const provider = this.getProvider({ from: id });
136 return {
137 delete: provider.deleteUserAccount !== undefined,
138 updateName: provider.updateUserAccountName !== undefined,
139 };
140 }
141 /**
142 * Deletes the `UserAccountID` from its underlying provider. Throws an `DeleteUserAccountUnsupportedError` if the operation is unsupported.
143 *
144 * Users should check `getSupportedFeatures` before calling this method.
145 */
146 async deleteUserAccount(idIn) {
147 const id = args.assertUserAccountID('id', idIn);
148 const provider = this.getProvider({ from: id });
149 if (provider.deleteUserAccount === undefined) {
150 throw new errors_1.DeleteUserAccountUnsupportedError(id);
151 }
152 await provider.deleteUserAccount(id);
153 }
154 /**
155 * Updates the name of the `UserAccountID` in the underlying provider. Throws an `UpdateUserAccountUnsupportedError` if the operation is unsupported.
156 *
157 * Users should check `getSupportedFeatures` before calling this method.
158 */
159 async updateUserAccountName(options) {
160 const { id, name } = args.assertUpdateAccountNameOptions('options', options);
161 const provider = this.getProvider({ from: id });
162 if (provider.updateUserAccountName === undefined) {
163 throw new errors_1.UpdateUserAccountUnsupportedError(id);
164 }
165 await provider.updateUserAccountName({ id, name });
166 }
167 /**
168 * @returns the currently selected `UserAccount` or `undefined` if there are no `UserAccount`s.
169 */
170 getCurrentUserAccount() {
171 return this.selectedProvider$.getValue().getCurrentUserAccount();
172 }
173 /**
174 * @returns the currently selected `NetworkType`
175 */
176 getCurrentNetwork() {
177 return this.currentNetworkInternal$.getValue();
178 }
179 /**
180 * @returns a list of all available `UserAccount`s
181 */
182 getUserAccounts() {
183 return Object.values(this.providers).reduce((acc, provider) => acc.concat(provider.getUserAccounts()), []);
184 }
185 /**
186 * @returns a list of all available `NetworkType`s
187 */
188 getNetworks() {
189 const providers = Object.values(this.providers);
190 return [...new Set(providers.reduce((acc, provider) => acc.concat(provider.getNetworks()), []))];
191 }
192 /**
193 * Constructs a `SmartContract` instance for the provided `definition` backed by this `Client` instance.
194 */
195 smartContract(definition) {
196 return sc_1.createSmartContract({
197 definition: args.assertSmartContractDefinition('definition', definition),
198 client: this,
199 });
200 }
201 async transfer(...argsIn) {
202 const { transfers, options } = this.getTransfersOptions(argsIn);
203 await this.applyBeforeRelayHook(options);
204 return this.addTransactionHooks(this.getProvider(options).transfer(transfers, options));
205 }
206 /**
207 * Claim all available unclaimed `GAS` for the currently selected account (or the specified `from` `UserAccountID`).
208 */
209 async claim(optionsIn) {
210 const options = args.assertTransactionOptions('options', optionsIn);
211 await this.applyBeforeRelayHook(options);
212 return this.addTransactionHooks(this.getProvider(options).claim(options));
213 }
214 /**
215 * @returns `Promise` which resolves to an `Account` object for the provided `UserAccountID`.
216 */
217 async getAccount(id, monitor) {
218 return this.getNetworkProvider(id.network).getAccount(id.network, id.address, monitor);
219 }
220 /**
221 * @internal
222 */
223 __iterActionsRaw(network, options) {
224 const provider = this.getNetworkProvider(network);
225 if (provider.iterActionsRaw !== undefined) {
226 return provider.iterActionsRaw(network, options);
227 }
228 return asynciterablex_1.AsyncIterableX.from(provider.iterBlocks(network, options)).pipe(flatmap_1.flatMap(async (block) => {
229 const actions = lodash_1.default.flatten(block.transactions.map((transaction) => {
230 if (transaction.type === 'InvocationTransaction') {
231 return [...transaction.invocationData.actions];
232 }
233 return [];
234 }));
235 return asynciterablex_1.AsyncIterableX.of(...actions);
236 }));
237 }
238 /**
239 * @internal
240 */
241 async __invoke(contract, method, params, paramsZipped, verify, optionsIn, sourceMaps = Promise.resolve({})) {
242 const options = optionsIn === undefined ? {} : optionsIn;
243 await this.applyBeforeRelayHook(options);
244 return this.addTransactionHooks(this.getProvider(options).invoke(contract, method, params, paramsZipped, verify, options, sourceMaps));
245 }
246 /**
247 * @internal
248 */
249 async __invokeSend(contract, method, params, paramsZipped, transfer, optionsIn, sourceMaps = Promise.resolve({})) {
250 const options = optionsIn === undefined ? {} : optionsIn;
251 await this.applyBeforeRelayHook(options);
252 return this.addTransactionHooks(this.getProvider(options).invokeSend(contract, method, params, paramsZipped, transfer, options, sourceMaps));
253 }
254 /**
255 * @internal
256 */
257 async __invokeCompleteSend(contract, method, params, paramsZipped, hash, optionsIn, sourceMaps = Promise.resolve({})) {
258 const options = optionsIn === undefined ? {} : optionsIn;
259 await this.applyBeforeRelayHook(options);
260 return this.addTransactionHooks(this.getProvider(options).invokeCompleteSend(contract, method, params, paramsZipped, hash, options, sourceMaps));
261 }
262 /**
263 * @internal
264 */
265 async __invokeRefundAssets(contract, method, params, paramsZipped, hash, optionsIn, sourceMaps = Promise.resolve({})) {
266 const options = optionsIn === undefined ? {} : optionsIn;
267 await this.applyBeforeRelayHook(options);
268 return this.addTransactionHooks(this.getProvider(options).invokeRefundAssets(contract, method, params, paramsZipped, hash, options, sourceMaps));
269 }
270 /**
271 * @internal
272 */
273 async __invokeClaim(contract, method, params, paramsZipped, optionsIn, sourceMaps = Promise.resolve({})) {
274 const options = optionsIn === undefined ? {} : optionsIn;
275 await this.applyBeforeRelayHook(options);
276 return this.addTransactionHooks(this.getProvider(options).invokeClaim(contract, method, params, paramsZipped, options, sourceMaps));
277 }
278 /**
279 * @internal
280 */
281 async __call(network, contract, method, params, monitor) {
282 try {
283 const receipt = await this.getNetworkProvider(network).call(network, contract, method, params, monitor);
284 await this.hooks.afterCall.promise(receipt);
285 return receipt;
286 }
287 catch (error) {
288 await this.hooks.callError.promise(error);
289 throw error;
290 }
291 }
292 /**
293 * @internal
294 */
295 reset() {
296 this.reset$.next(undefined);
297 }
298 getProvider(options = {}) {
299 const { from } = options;
300 if (from === undefined) {
301 return this.selectedProvider$.getValue();
302 }
303 const providers = Object.values(this.providers);
304 const accountProvider = providers.find((provider) => provider
305 .getUserAccounts()
306 .some((account) => account.id.network === from.network && account.id.address === from.address));
307 if (accountProvider === undefined) {
308 throw new errors_1.UnknownAccountError(from.address);
309 }
310 return accountProvider;
311 }
312 getNetworkProvider(network) {
313 const providers = Object.values(this.providers);
314 const accountProvider = providers.find((provider) => provider.getNetworks().some((providerNetwork) => providerNetwork === network));
315 if (accountProvider === undefined) {
316 throw new errors_1.UnknownNetworkError(network);
317 }
318 return accountProvider;
319 }
320 async applyBeforeRelayHook(options) {
321 try {
322 await this.hooks.beforeRelay.promise(options);
323 }
324 catch (_a) {
325 // do nothing
326 }
327 }
328 async addTransactionHooks(res) {
329 return res
330 .then(async (result) => {
331 try {
332 await this.hooks.afterRelay.promise(result.transaction);
333 }
334 catch (_a) {
335 // do nothing
336 }
337 // tslint:disable-next-line prefer-object-spread
338 return Object.assign({}, result, {
339 // tslint:disable-next-line no-unnecessary-type-annotation
340 confirmed: async (options) => {
341 try {
342 await this.hooks.beforeConfirmed.promise(result.transaction);
343 }
344 catch (_a) {
345 // do nothing
346 }
347 try {
348 const receipt = await result.confirmed(options);
349 try {
350 await this.hooks.afterConfirmed.promise(result.transaction, receipt);
351 }
352 catch (_b) {
353 // do nothing
354 }
355 return receipt;
356 }
357 catch (error) {
358 try {
359 await this.hooks.confirmedError.promise(result.transaction, error);
360 }
361 catch (_c) {
362 // do nothing
363 }
364 throw error;
365 }
366 },
367 });
368 })
369 .catch(async (error) => {
370 await this.hooks.relayError.promise(error);
371 throw error;
372 });
373 }
374 getTransfersOptions(argsIn) {
375 let transfers;
376 let options;
377 if (argsIn.length >= 3) {
378 transfers = [
379 {
380 amount: argsIn[0],
381 asset: argsIn[1],
382 to: argsIn[2],
383 },
384 ];
385 options = argsIn[3];
386 }
387 else {
388 transfers = argsIn[0];
389 options = argsIn[1];
390 }
391 return {
392 transfers: args.assertTransfers('transfers', transfers),
393 options: args.assertTransactionOptions('options', options),
394 };
395 }
396}
397exports.Client = Client;
398
399//# sourceMappingURL=data:application/json;charset=utf8;base64,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bnQuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLy8gPHJlZmVyZW5jZSB0eXBlcz1cIkByZWFjdGl2ZXgvaXgtZXMyMDE1LWNqc1wiIC8+XG4vLyB0c2xpbnQ6ZGlzYWJsZSBtZW1iZXItb3JkZXJpbmcgcmVhZG9ubHktYXJyYXkgbm8tYW55XG5pbXBvcnQge1xuICBBY2NvdW50LFxuICBBZGRyZXNzU3RyaW5nLFxuICBCbG9jayxcbiAgQ2xhaW1UcmFuc2FjdGlvbixcbiAgR2V0T3B0aW9ucyxcbiAgSGFzaDI1NlN0cmluZyxcbiAgSW52b2NhdGlvblRyYW5zYWN0aW9uLFxuICBJbnZva2VTZW5kVW5zYWZlUmVjZWl2ZVRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgSXRlck9wdGlvbnMsXG4gIE5ldHdvcmtUeXBlLFxuICBQYXJhbSxcbiAgUmF3QWN0aW9uLFxuICBSYXdDYWxsUmVjZWlwdCxcbiAgUmF3SW52b2tlUmVjZWlwdCxcbiAgU2NyaXB0QnVpbGRlclBhcmFtLFxuICBTbWFydENvbnRyYWN0RGVmaW5pdGlvbixcbiAgU291cmNlTWFwcyxcbiAgVHJhbnNhY3Rpb24sXG4gIFRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgVHJhbnNhY3Rpb25SZWNlaXB0LFxuICBUcmFuc2FjdGlvblJlc3VsdCxcbiAgVHJhbnNmZXIsXG4gIFVwZGF0ZUFjY291bnROYW1lT3B0aW9ucyxcbiAgVXNlckFjY291bnQsXG4gIFVzZXJBY2NvdW50SUQsXG4gIFVzZXJBY2NvdW50UHJvdmlkZXIsXG4gIFVzZXJBY2NvdW50UHJvdmlkZXJzLFxufSBmcm9tICdAbmVvLW9uZS9jbGllbnQtY29tbW9uJztcbmltcG9ydCB7IE1vbml0b3IgfSBmcm9tICdAbmVvLW9uZS9tb25pdG9yJztcbmltcG9ydCB7IEFzeW5jSXRlcmFibGVYIH0gZnJvbSAnQHJlYWN0aXZleC9peC1lczIwMTUtY2pzL2FzeW5jaXRlcmFibGUvYXN5bmNpdGVyYWJsZXgnO1xuaW1wb3J0IHsgZmxhdE1hcCB9IGZyb20gJ0ByZWFjdGl2ZXgvaXgtZXMyMDE1LWNqcy9hc3luY2l0ZXJhYmxlL3BpcGUvZmxhdG1hcCc7XG5pbXBvcnQgeyB0b09ic2VydmFibGUgfSBmcm9tICdAcmVhY3RpdmV4L2l4LWVzMjAxNS1janMvYXN5bmNpdGVyYWJsZS90b29ic2VydmFibGUnO1xuaW1wb3J0IEJpZ051bWJlciBmcm9tICdiaWdudW1iZXIuanMnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgY29tYmluZUxhdGVzdCwgT2JzZXJ2YWJsZSwgT2JzZXJ2ZXIsIFJlcGxheVN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGRpc3RpbmN0VW50aWxDaGFuZ2VkLCBmaWx0ZXIsIG1hcCwgbXVsdGljYXN0LCByZWZDb3VudCwgc3dpdGNoTWFwLCB0YWtlIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQXN5bmNQYXJhbGxlbEhvb2sgfSBmcm9tICd0YXBhYmxlJztcbmltcG9ydCAqIGFzIGFyZ3MgZnJvbSAnLi9hcmdzJztcbmltcG9ydCB7XG4gIERlbGV0ZVVzZXJBY2NvdW50VW5zdXBwb3J0ZWRFcnJvcixcbiAgVW5rbm93bkFjY291bnRFcnJvcixcbiAgVW5rbm93bk5ldHdvcmtFcnJvcixcbiAgVXBkYXRlVXNlckFjY291bnRVbnN1cHBvcnRlZEVycm9yLFxufSBmcm9tICcuL2Vycm9ycyc7XG5pbXBvcnQgeyBjcmVhdGVTbWFydENvbnRyYWN0IH0gZnJvbSAnLi9zYyc7XG5pbXBvcnQgeyBTbWFydENvbnRyYWN0LCBTbWFydENvbnRyYWN0QW55IH0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogT2JqZWN0IHdoaWNoIGNvbnRhaW5zIHRoZSBwb2ludHMgdGhhdCBjYW4gYmUgaG9va2VkIGludG8gb24gdGhlIGBDbGllbnRgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENsaWVudEhvb2tzIHtcbiAgLyoqXG4gICAqIENhbGxlZCBiZWZvcmUgdGhlIGBUcmFuc2FjdGlvbmAgaXMgcmVsYXllZC5cbiAgICovXG4gIHJlYWRvbmx5IGJlZm9yZVJlbGF5OiBBc3luY1BhcmFsbGVsSG9vazxUcmFuc2FjdGlvbk9wdGlvbnM+O1xuICAvKipcbiAgICogQ2FsbGVkIHdoZW4gdGhlcmUgaXMgYW4gYEVycm9yYCB0aHJvd24gZHVyaW5nIHJlbGF5aW5nIGEgYFRyYW5zYWN0aW9uYC5cbiAgICovXG4gIHJlYWRvbmx5IHJlbGF5RXJyb3I6IEFzeW5jUGFyYWxsZWxIb29rPEVycm9yPjtcbiAgLyoqXG4gICAqIENhbGxlZCBhZnRlciBzdWNjZXNzZnVsbHkgcmVsYXlpbmcgYSBgVHJhbnNhY3Rpb25gLlxuICAgKi9cbiAgcmVhZG9ubHkgYWZ0ZXJSZWxheTogQXN5bmNQYXJhbGxlbEhvb2s8VHJhbnNhY3Rpb24+O1xuICAvKipcbiAgICogQ2FsbGVkIHdoZW4gdGhlIGBjb25maXJtZWRgIG1ldGhvZCBvZiBhIGBUcmFuc2FjdGlvblJlc3VsdGAgaXMgaW52b2tlZC5cbiAgICovXG4gIHJlYWRvbmx5IGJlZm9yZUNvbmZpcm1lZDogQXN5bmNQYXJhbGxlbEhvb2s8VHJhbnNhY3Rpb24+O1xuICAvKipcbiAgICogQ2FsbGVkIHdoZW4gdGhlcmUgaXMgYW4gYEVycm9yYCB0aHJvd24gZHVyaW5nIHRoZSBgY29uZmlybWVkYCBtZXRob2Qgb2YgYSBgVHJhbnNhY3Rpb25SZXN1bHRgLlxuICAgKi9cbiAgcmVhZG9ubHkgY29uZmlybWVkRXJyb3I6IEFzeW5jUGFyYWxsZWxIb29rPFRyYW5zYWN0aW9uLCBFcnJvcj47XG4gIC8qKlxuICAgKiBDYWxsZWQgYWZ0ZXIgdGhlIGBjb25maXJtZWRgIG1ldGhvZCBvZiBhIGBUcmFuc2FjdGlvblJlc3VsdGAgcmVzb2x2ZXMuXG4gICAqL1xuICByZWFkb25seSBhZnRlckNvbmZpcm1lZDogQXN5bmNQYXJhbGxlbEhvb2s8VHJhbnNhY3Rpb24sIFRyYW5zYWN0aW9uUmVjZWlwdD47XG4gIC8qKlxuICAgKiBDYWxsZWQgYWZ0ZXIgYSBjb25zdGFudCBtZXRob2QgaXMgaW52b2tlZC5cbiAgICovXG4gIHJlYWRvbmx5IGFmdGVyQ2FsbDogQXN5bmNQYXJhbGxlbEhvb2s8UmF3Q2FsbFJlY2VpcHQ+O1xuICAvKipcbiAgICogQ2FsbGVkIHdoZW4gYW4gYEVycm9yYCBpcyB0aHJvd24gZnJvbSBhIGNvbnN0YW50IG1ldGhvZCBpbnZvY2F0aW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgY2FsbEVycm9yOiBBc3luY1BhcmFsbGVsSG9vazxFcnJvcj47XG59XG5cbi8qKlxuICogUHJvcGVydGllcyByZXByZXNlbnQgZmVhdHVyZXMgdGhhdCBhIGdpdmVuIGBVc2VyQWNjb3VudElEYCBzdXBwb3J0cy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBVc2VyQWNjb3VudEZlYXR1cmVzIHtcbiAgLyoqXG4gICAqIGB0cnVlYCBpZiB0aGUgYFVzZXJBY2NvdW50SURgIGNhbiBiZSBkZWxldGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgZGVsZXRlOiBib29sZWFuO1xuICAvKipcbiAgICogYHRydWVgIGlmIHRoZSBgbmFtZWAgb2YgdGhlIGBVc2VyQWNjb3VudGAgYXNzb2NpYXRlZCB3aXRoIHRoZSBgVXNlckFjY291bnRJRGAgY2FuIGJlIHVwZGF0ZWQuXG4gICAqL1xuICByZWFkb25seSB1cGRhdGVOYW1lOiBib29sZWFuO1xufVxuXG4vKipcbiAqIGBDbGllbnQjYmxvY2skYCBgT2JzZXJ2YWJsZWAgaXRlbS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCbG9ja0VudHJ5IHtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgYmxvY2suXG4gICAqL1xuICByZWFkb25seSBibG9jazogQmxvY2s7XG4gIC8qKlxuICAgKiBOZXR3b3JrIG9mIHRoZSBibG9jay5cbiAgICovXG4gIHJlYWRvbmx5IG5ldHdvcms6IE5ldHdvcmtUeXBlO1xufVxuXG4vKipcbiAqIGBDbGllbnQjYWNjb3VudFN0YXRlJGAgYE9ic2VydmFibGVgIGl0ZW0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWNjb3VudFN0YXRlRW50cnkge1xuICAvKipcbiAgICogQ3VycmVudGx5IHNlbGVjdGVkIGBVc2VyQWNjb3VudGBcbiAgICovXG4gIHJlYWRvbmx5IGN1cnJlbnRVc2VyQWNjb3VudDogVXNlckFjY291bnQ7XG4gIC8qKlxuICAgKiBCbG9ja2NoYWluIGFjY291bnQgaW5mbyBmb3IgYGN1cnJlbnRVc2VyQWNjb3VudGBcbiAgICovXG4gIHJlYWRvbmx5IGFjY291bnQ6IEFjY291bnQ7XG59XG5cbi8qKlxuICogTWFpbiBlbnRyeXBvaW50IHRvIHRoZSBgQG5lby1vbmUvY2xpZW50YCBBUElzLiBUaGUgYENsaWVudGAgY2xhc3MgYWJzdHJhY3RzIGF3YXkgdXNlciBhY2NvdW50cyBhbmQgZXZlbiBob3cgdGhvc2UgYWNjb3VudHMgYXJlIHByb3ZpZGVkIHRvIHlvdXIgZGFwcCwgZm9yIGV4YW1wbGUsIHRoZXkgbWlnaHQgY29tZSBmcm9tIGFuIGV4dGVuc2lvbiBsaWtlIE5FWCwgZGFwcCBicm93c2VyIGxpa2Ugbk9TIG9yIHRocm91Z2ggc29tZSBvdGhlciBpbnRlZ3JhdGlvbi5cbiAqXG4gKiBTZWUgdGhlIFtDbGllbnQgQVBJc10oaHR0cHM6Ly9uZW8tb25lLmlvL2RvY3MvY2xpZW50LWFwaXMpIGNoYXB0ZXIgb2YgdGhlIG1haW4gZ3VpZGUgZm9yIG1vcmUgaW5mb3JtYXRpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBDbGllbnQ8XG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby1hbnlcbiAgVFVzZXJBY2NvdW50UHJvdmlkZXIgZXh0ZW5kcyBVc2VyQWNjb3VudFByb3ZpZGVyID0gYW55LFxuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tYW55XG4gIFRVc2VyQWNjb3VudFByb3ZpZGVycyBleHRlbmRzIFVzZXJBY2NvdW50UHJvdmlkZXJzPFRVc2VyQWNjb3VudFByb3ZpZGVyPiA9IGFueVxuPiB7XG4gIC8qKlxuICAgKiBIb29rIGludG8gdGhlIGxpZmVjeWNsZSBvZiB2YXJpb3VzIHJlcXVlc3RzLiBDYW4gYmUgdXNlZCB0byBhdXRvbWF0aWNhbGx5IGFkZCBsb2dnaW5nLCBvciBwYXJhbWV0ZXIgdHJhbnNmb3JtYXRpb25zIGFjcm9zcyB0aGUgYXBwbGljYXRpb24sIGZvciBleGFtcGxlLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGhvb2tzOiBDbGllbnRIb29rcztcbiAgLyoqXG4gICAqIEVtaXRzIGEgdmFsdWUgd2hlbmV2ZXIgYSBuZXcgdXNlciBhY2NvdW50IGlzIHNlbGVjdGVkLlxuICAgKlxuICAgKiBJbW1lZGlhdGVseSBlbWl0cyB0aGUgbGF0ZXN0IHZhbHVlIHdoZW4gc3Vic2NyaWJlZCB0by5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBjdXJyZW50VXNlckFjY291bnQkOiBPYnNlcnZhYmxlPFVzZXJBY2NvdW50IHwgdW5kZWZpbmVkPjtcbiAgLyoqXG4gICAqIEVtaXRzIGEgdmFsdWUgd2hlbmV2ZXIgYSBuZXcgbGlzdCBvZiB1c2VyIGFjY291bnRzIGlzIGF2YWlsYWJsZS5cbiAgICpcbiAgICogSW1tZWRpYXRlbHkgZW1pdHMgdGhlIGxhdGVzdCB2YWx1ZSB3aGVuIHN1YnNjcmliZWQgdG8uXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdXNlckFjY291bnRzJDogT2JzZXJ2YWJsZTxyZWFkb25seSBVc2VyQWNjb3VudFtdPjtcbiAgLyoqXG4gICAqIEVtaXRzIGEgdmFsdWUgd2hlbmV2ZXIgYSBuZXcgbmV0d29yayBpcyBzZWxlY3RlZC5cbiAgICpcbiAgICogSW1tZWRpYXRlbHkgZW1pdHMgdGhlIGxhdGVzdCB2YWx1ZSB3aGVuIHN1YnNjcmliZWQgdG8uXG4gICAqL1xuXG4gIHB1YmxpYyByZWFkb25seSBjdXJyZW50TmV0d29yayQ6IE9ic2VydmFibGU8TmV0d29ya1R5cGU+O1xuICAvKipcbiAgICogRW1pdHMgYSB2YWx1ZSB3aGVuZXZlciBhIG5ldyBsaXN0IG9mIG5ldHdvcmtzIHVzZXIgYWNjb3VudCBpcyBhdmFpbGFibGUuXG4gICAqXG4gICAqIEltbWVkaWF0ZWx5IGVtaXRzIHRoZSBsYXRlc3QgdmFsdWUgd2hlbiBzdWJzY3JpYmVkIHRvLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IG5ldHdvcmtzJDogT2JzZXJ2YWJsZTxyZWFkb25seSBOZXR3b3JrVHlwZVtdPjtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHByb3ZpZGVycyQ6IEJlaGF2aW9yU3ViamVjdDxUVXNlckFjY291bnRQcm92aWRlcnM+O1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgc2VsZWN0ZWRQcm92aWRlciQ6IEJlaGF2aW9yU3ViamVjdDxUVXNlckFjY291bnRQcm92aWRlcj47XG4gIHByaXZhdGUgcmVhZG9ubHkgY3VycmVudE5ldHdvcmtJbnRlcm5hbCQ6IEJlaGF2aW9yU3ViamVjdDxOZXR3b3JrVHlwZT47XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVzZXQkID0gbmV3IEJlaGF2aW9yU3ViamVjdDx2b2lkPih1bmRlZmluZWQpO1xuXG4gIC8qKlxuICAgKiBFbWl0cyBhIHZhbHVlIHdoZW5ldmVyIGEgYmxvY2sgaXMgcGVyc2lzdGVkIHRvIHRoZSBibG9ja2NoYWluLlxuICAgKlxuICAgKiBJbW1lZGlhdGVseSBlbWl0cyB0aGUgbGF0ZXN0IGJsb2NrL25ldHdvcmsgd2hlbiBzdWJzY3JpYmVkIHRvLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGJsb2NrJDogT2JzZXJ2YWJsZTxCbG9ja0VudHJ5PjtcblxuICAvKipcbiAgICogRW1pdHMgYSB2YWx1ZSB3aGVuZXZlciBhIG5ldyB1c2VyIGFjY291bnQgaXMgc2VsZWN0ZWQgYW5kIHdoZW5ldmVyIGEgYmxvY2sgaXMgcGVyc2lzdGVkIHRvIHRoZSBibG9ja2NoYWluLlxuICAgKlxuICAgKiBJbW1lZGlhdGVseSBlbWl0cyB0aGUgbGF0ZXN0IHZhbHVlIHdoZW4gc3Vic2NyaWJlZCB0by5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBhY2NvdW50U3RhdGUkOiBPYnNlcnZhYmxlPEFjY291bnRTdGF0ZUVudHJ5IHwgdW5kZWZpbmVkPjtcblxuICBwdWJsaWMgY29uc3RydWN0b3IocHJvdmlkZXJzSW46IFRVc2VyQWNjb3VudFByb3ZpZGVycykge1xuICAgIHRoaXMuaG9va3MgPSB7XG4gICAgICBiZWZvcmVSZWxheTogbmV3IEFzeW5jUGFyYWxsZWxIb29rKFsnYmVmb3JlUmVsYXknXSksXG4gICAgICByZWxheUVycm9yOiBuZXcgQXN5bmNQYXJhbGxlbEhvb2soWydlcnJvciddKSxcbiAgICAgIGFmdGVyUmVsYXk6IG5ldyBBc3luY1BhcmFsbGVsSG9vayhbJ3RyYW5zYWN0aW9uJ10pLFxuICAgICAgYmVmb3JlQ29uZmlybWVkOiBuZXcgQXN5bmNQYXJhbGxlbEhvb2soWyd0cmFuc2FjdGlvbiddKSxcbiAgICAgIGNvbmZpcm1lZEVycm9yOiBuZXcgQXN5bmNQYXJhbGxlbEhvb2soWyd0cmFuc2FjdGlvbicsICdlcnJvciddKSxcbiAgICAgIGFmdGVyQ29uZmlybWVkOiBuZXcgQXN5bmNQYXJhbGxlbEhvb2soWyd0cmFuc2FjdGlvbicsICdyZWNlaXB0J10pLFxuICAgICAgYWZ0ZXJDYWxsOiBuZXcgQXN5bmNQYXJhbGxlbEhvb2soWydyZWNlaXB0J10pLFxuICAgICAgY2FsbEVycm9yOiBuZXcgQXN5bmNQYXJhbGxlbEhvb2soWydlcnJvciddKSxcbiAgICB9O1xuICAgIGNvbnN0IHByb3ZpZGVyc0FycmF5ID0gT2JqZWN0LnZhbHVlcyhwcm92aWRlcnNJbik7XG4gICAgY29uc3QgcHJvdmlkZXJJbiA9XG4gICAgICBwcm92aWRlcnNBcnJheS5maW5kKChwcm92aWRlcikgPT4gcHJvdmlkZXIuZ2V0Q3VycmVudFVzZXJBY2NvdW50KCkgIT09IHVuZGVmaW5lZCkgfHxcbiAgICAgIChwcm92aWRlcnNBcnJheVswXSBhcyBUVXNlckFjY291bnRQcm92aWRlciB8IHVuZGVmaW5lZCk7XG4gICAgaWYgKHByb3ZpZGVySW4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBdCBsZWFzdCBvbmUgcHJvdmlkZXIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICB0aGlzLnByb3ZpZGVycyQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0KHByb3ZpZGVyc0luKTtcbiAgICB0aGlzLnNlbGVjdGVkUHJvdmlkZXIkID0gbmV3IEJlaGF2aW9yU3ViamVjdChwcm92aWRlckluKTtcblxuICAgIHRoaXMuY3VycmVudFVzZXJBY2NvdW50JCA9IHRoaXMuc2VsZWN0ZWRQcm92aWRlciQucGlwZShzd2l0Y2hNYXAoKHByb3ZpZGVyKSA9PiBwcm92aWRlci5jdXJyZW50VXNlckFjY291bnQkKSk7XG5cbiAgICB0aGlzLnVzZXJBY2NvdW50cyQgPSB0aGlzLnByb3ZpZGVycyQucGlwZShcbiAgICAgIHN3aXRjaE1hcCgocHJvdmlkZXJzKSA9PiBjb21iaW5lTGF0ZXN0KE9iamVjdC52YWx1ZXMocHJvdmlkZXJzKS5tYXAoKHByb3ZpZGVyKSA9PiBwcm92aWRlci51c2VyQWNjb3VudHMkKSkpLFxuICAgICAgbWFwKChhY2NvdW50c3MpID0+IGFjY291bnRzcy5yZWR1Y2UoKGFjYywgYWNjb3VudHMpID0+IGFjYy5jb25jYXQoYWNjb3VudHMpLCBbXSkpLFxuICAgICk7XG5cbiAgICB0aGlzLm5ldHdvcmtzJCA9IHRoaXMucHJvdmlkZXJzJC5waXBlKFxuICAgICAgc3dpdGNoTWFwKChwcm92aWRlcnMpID0+IGNvbWJpbmVMYXRlc3QoT2JqZWN0LnZhbHVlcyhwcm92aWRlcnMpLm1hcCgocHJvdmlkZXIpID0+IHByb3ZpZGVyLm5ldHdvcmtzJCkpKSxcbiAgICAgIG1hcCgobmV0d29ya3NzKSA9PiBbLi4ubmV3IFNldChuZXR3b3Jrc3MucmVkdWNlKChhY2MsIG5ldHdvcmtzKSA9PiBhY2MuY29uY2F0KG5ldHdvcmtzKSwgW10pKV0pLFxuICAgICk7XG5cbiAgICB0aGlzLmN1cnJlbnROZXR3b3JrSW50ZXJuYWwkID0gbmV3IEJlaGF2aW9yU3ViamVjdChwcm92aWRlckluLmdldE5ldHdvcmtzKClbMF0pO1xuICAgIGNvbWJpbmVMYXRlc3QoW3RoaXMuY3VycmVudFVzZXJBY2NvdW50JCwgdGhpcy5zZWxlY3RlZFByb3ZpZGVyJF0pXG4gICAgICAucGlwZShcbiAgICAgICAgbWFwKChbY3VycmVudEFjY291bnQsIHByb3ZpZGVyXSkgPT4ge1xuICAgICAgICAgIGlmIChjdXJyZW50QWNjb3VudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gY3VycmVudEFjY291bnQuaWQubmV0d29yaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBtYWluTmV0d29yayA9IHByb3ZpZGVyLmdldE5ldHdvcmtzKCkuZmluZCgobmV0d29yaykgPT4gbmV0d29yayA9PT0gJ21haW4nKTtcblxuICAgICAgICAgIHJldHVybiBtYWluTmV0d29yayA9PT0gdW5kZWZpbmVkID8gcHJvdmlkZXIuZ2V0TmV0d29ya3MoKVswXSA6IG1haW5OZXR3b3JrO1xuICAgICAgICB9KSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUodGhpcy5jdXJyZW50TmV0d29ya0ludGVybmFsJCk7XG4gICAgdGhpcy5jdXJyZW50TmV0d29yayQgPSB0aGlzLmN1cnJlbnROZXR3b3JrSW50ZXJuYWwkLnBpcGUoZGlzdGluY3RVbnRpbENoYW5nZWQoKSk7XG5cbiAgICBpZiAodGhpcy5nZXRDdXJyZW50VXNlckFjY291bnQoKSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLnVzZXJBY2NvdW50cyRcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgZmlsdGVyKChhY2NvdW50cykgPT4gYWNjb3VudHMubGVuZ3RoID4gMCksXG4gICAgICAgICAgdGFrZSgxKSxcbiAgICAgICAgKVxuICAgICAgICAudG9Qcm9taXNlKClcbiAgICAgICAgLnRoZW4oYXN5bmMgKGFjY291bnRzKSA9PiB7XG4gICAgICAgICAgY29uc3QgYWNjb3VudCA9IGFjY291bnRzWzBdIGFzIFVzZXJBY2NvdW50IHwgdW5kZWZpbmVkO1xuICAgICAgICAgIGlmICh0aGlzLmdldEN1cnJlbnRVc2VyQWNjb3VudCgpID09PSB1bmRlZmluZWQgJiYgYWNjb3VudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnNlbGVjdFVzZXJBY2NvdW50KGFjY291bnQuaWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgLmNhdGNoKCgpID0+IHtcbiAgICAgICAgICAvLyBKdXN0IGlnbm9yZSBlcnJvcnMgaGVyZS5cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy5ibG9jayQgPSB0aGlzLnJlc2V0JC5waXBlKFxuICAgICAgc3dpdGNoTWFwKCgpID0+XG4gICAgICAgIHRoaXMuY3VycmVudE5ldHdvcmskLnBpcGUoXG4gICAgICAgICAgc3dpdGNoTWFwKChuZXR3b3JrKSA9PlxuICAgICAgICAgICAgbmV3IE9ic2VydmFibGUoKG9ic2VydmVyOiBPYnNlcnZlcjxCbG9jaz4pID0+XG4gICAgICAgICAgICAgIHRvT2JzZXJ2YWJsZSh0aGlzLmdldE5ldHdvcmtQcm92aWRlcihuZXR3b3JrKS5pdGVyQmxvY2tzKG5ldHdvcmspKS5zdWJzY3JpYmUob2JzZXJ2ZXIpLFxuICAgICAgICAgICAgKS5waXBlKG1hcCgoYmxvY2spID0+ICh7IGJsb2NrLCBuZXR3b3JrIH0pKSksXG4gICAgICAgICAgKSxcbiAgICAgICAgKSxcbiAgICAgICksXG4gICAgICBtdWx0aWNhc3QoKCkgPT4gbmV3IFJlcGxheVN1YmplY3Q8QmxvY2tFbnRyeT4oMSkpLFxuICAgICAgcmVmQ291bnQoKSxcbiAgICApO1xuICAgIHRoaXMuYWNjb3VudFN0YXRlJCA9IGNvbWJpbmVMYXRlc3QoW3RoaXMuY3VycmVudFVzZXJBY2NvdW50JCwgdGhpcy5ibG9jayRdKS5waXBlKFxuICAgICAgc3dpdGNoTWFwKGFzeW5jIChbY3VycmVudFVzZXJBY2NvdW50XSkgPT4ge1xuICAgICAgICBpZiAoY3VycmVudFVzZXJBY2NvdW50ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYWNjb3VudCA9IGF3YWl0IHRoaXMuZ2V0TmV0d29ya1Byb3ZpZGVyKGN1cnJlbnRVc2VyQWNjb3VudC5pZC5uZXR3b3JrKS5nZXRBY2NvdW50KFxuICAgICAgICAgIGN1cnJlbnRVc2VyQWNjb3VudC5pZC5uZXR3b3JrLFxuICAgICAgICAgIGN1cnJlbnRVc2VyQWNjb3VudC5pZC5hZGRyZXNzLFxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiB7IGN1cnJlbnRVc2VyQWNjb3VudCwgYWNjb3VudCB9O1xuICAgICAgfSksXG4gICAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgoYSwgYikgPT4gXy5pc0VxdWFsKGEsIGIpKSxcbiAgICAgIG11bHRpY2FzdCgoKSA9PiBuZXcgUmVwbGF5U3ViamVjdDxBY2NvdW50U3RhdGVFbnRyeSB8IHVuZGVmaW5lZD4oMSkpLFxuICAgICAgcmVmQ291bnQoKSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBjb25maWd1cmVkIGBVc2VyQWNjb3VudFByb3ZpZGVyYHMgZm9yIHRoaXMgYENsaWVudGAgaW5zdGFuY2UuXG4gICAqL1xuICBwdWJsaWMgZ2V0IHByb3ZpZGVycygpOiBUVXNlckFjY291bnRQcm92aWRlcnMge1xuICAgIHJldHVybiB0aGlzLnByb3ZpZGVycyQuZ2V0VmFsdWUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGRldGFpbHMgb2YgdGhlIGBVc2VyQWNjb3VudGAgZm9yIGEgZ2l2ZW4gYFVzZXJBY2NvdW50SURgLlxuICAgKlxuICAgKiBAcGFyYW0gaWRJbiBgVXNlckFjY291bnRJRGAgdG8gZmluZCB0aGUgYFVzZXJBY2NvdW50YCBmb3JcbiAgICogQHJldHVybnMgYFVzZXJBY2NvdW50YCBvciB0aHJvd3MgYW4gYFVua25vd25BY2NvdW50RXJyb3JgIGlmIG9uZSBjb3VsZCBub3QgYmUgZm91bmQuXG4gICAqL1xuICBwdWJsaWMgZ2V0VXNlckFjY291bnQoaWRJbjogVXNlckFjY291bnRJRCk6IFVzZXJBY2NvdW50IHtcbiAgICBjb25zdCBpZCA9IGFyZ3MuYXNzZXJ0VXNlckFjY291bnRJRCgnaWQnLCBpZEluKTtcbiAgICBjb25zdCBwcm92aWRlciA9IHRoaXMuZ2V0UHJvdmlkZXIoeyBmcm9tOiBpZCB9KTtcbiAgICBjb25zdCBhY2NvdW50ID0gcHJvdmlkZXJcbiAgICAgIC5nZXRVc2VyQWNjb3VudHMoKVxuICAgICAgLmZpbmQoKGFjY3QpID0+IGFjY3QuaWQubmV0d29yayA9PT0gaWQubmV0d29yayAmJiBhY2N0LmlkLmFkZHJlc3MgPT09IGlkLmFkZHJlc3MpO1xuXG4gICAgaWYgKGFjY291bnQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHRocm93IG5ldyBVbmtub3duQWNjb3VudEVycm9yKGlkLmFkZHJlc3MpO1xuICAgIH1cblxuICAgIHJldHVybiBhY2NvdW50O1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYSBgVXNlckFjY291bnRJRGAgYXMgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBgVXNlckFjY291bnRJRGAuXG4gICAqXG4gICAqIEBwYXJhbSBpZEluIGBVc2VyQWNjb3VudElEYCB0byBzZWxlY3QsIG9yIGB1bmRlZmluZWRgIHRvIGRlc2VsZWN0IHRoZSBjdXJyZW50IGBVc2VyQWNjb3VudElEYC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBzZWxlY3RVc2VyQWNjb3VudChpZEluPzogVXNlckFjY291bnRJRCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGlkID0gYXJncy5hc3NlcnROdWxsYWJsZVVzZXJBY2NvdW50SUQoJ2lkJywgaWRJbik7XG4gICAgY29uc3QgcHJvdmlkZXIgPSB0aGlzLmdldFByb3ZpZGVyKHsgZnJvbTogaWQgfSk7XG4gICAgYXdhaXQgcHJvdmlkZXIuc2VsZWN0VXNlckFjY291bnQoaWQpO1xuICAgIHRoaXMuc2VsZWN0ZWRQcm92aWRlciQubmV4dChwcm92aWRlcik7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBhIGBOZXR3b3JrVHlwZWAgYXMgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBgTmV0d29ya1R5cGVgLlxuICAgKlxuICAgKiBAcGFyYW0gbmV0d29ya0luIGBOZXR3b3JrVHlwZWAgdG8gc2VsZWN0LlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHNlbGVjdE5ldHdvcmsobmV0d29ya0luOiBOZXR3b3JrVHlwZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG5ldHdvcmsgPSBhcmdzLmFzc2VydFN0cmluZygnbmV0d29yaycsIG5ldHdvcmtJbik7XG4gICAgY29uc3QgcHJvdmlkZXIgPSB0aGlzLmdldE5ldHdvcmtQcm92aWRlcihuZXR3b3JrKTtcbiAgICBjb25zdCBhY2NvdW50ID0gcHJvdmlkZXIuZ2V0Q3VycmVudFVzZXJBY2NvdW50KCk7XG4gICAgaWYgKGFjY291bnQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgYWNjb3VudHMgPSBwcm92aWRlci5nZXRVc2VyQWNjb3VudHMoKTtcbiAgICAgIGlmIChhY2NvdW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGF3YWl0IHByb3ZpZGVyLnNlbGVjdFVzZXJBY2NvdW50KGFjY291bnRzWzBdLmlkKTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5zZWxlY3RlZFByb3ZpZGVyJC5uZXh0KHByb3ZpZGVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyBgUHJvbWlzZWAgd2hpY2ggcmVzb2x2ZXMgdG8gdGhlIGBVc2VyQWNjb3VudEZlYXR1cmVzYCBzdXBwb3J0ZWQgYnkgdGhlIGdpdmVuIGBVc2VyQWNjb3VudElEYC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBnZXRTdXBwb3J0ZWRGZWF0dXJlcyhpZEluOiBVc2VyQWNjb3VudElEKTogUHJvbWlzZTxVc2VyQWNjb3VudEZlYXR1cmVzPiB7XG4gICAgY29uc3QgaWQgPSBhcmdzLmFzc2VydFVzZXJBY2NvdW50SUQoJ2lkJywgaWRJbik7XG4gICAgY29uc3QgcHJvdmlkZXIgPSB0aGlzLmdldFByb3ZpZGVyKHsgZnJvbTogaWQgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGVsZXRlOiBwcm92aWRlci5kZWxldGVVc2VyQWNjb3VudCAhPT0gdW5kZWZpbmVkLFxuICAgICAgdXBkYXRlTmFtZTogcHJvdmlkZXIudXBkYXRlVXNlckFjY291bnROYW1lICE9PSB1bmRlZmluZWQsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBgVXNlckFjY291bnRJRGAgZnJvbSBpdHMgdW5kZXJseWluZyBwcm92aWRlci4gVGhyb3dzIGFuIGBEZWxldGVVc2VyQWNjb3VudFVuc3VwcG9ydGVkRXJyb3JgIGlmIHRoZSBvcGVyYXRpb24gaXMgdW5zdXBwb3J0ZWQuXG4gICAqXG4gICAqIFVzZXJzIHNob3VsZCBjaGVjayBgZ2V0U3VwcG9ydGVkRmVhdHVyZXNgIGJlZm9yZSBjYWxsaW5nIHRoaXMgbWV0aG9kLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGRlbGV0ZVVzZXJBY2NvdW50KGlkSW46IFVzZXJBY2NvdW50SUQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBpZCA9IGFyZ3MuYXNzZXJ0VXNlckFjY291bnRJRCgnaWQnLCBpZEluKTtcbiAgICBjb25zdCBwcm92aWRlciA9IHRoaXMuZ2V0UHJvdmlkZXIoeyBmcm9tOiBpZCB9KTtcbiAgICBpZiAocHJvdmlkZXIuZGVsZXRlVXNlckFjY291bnQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IERlbGV0ZVVzZXJBY2NvdW50VW5zdXBwb3J0ZWRFcnJvcihpZCk7XG4gICAgfVxuXG4gICAgYXdhaXQgcHJvdmlkZXIuZGVsZXRlVXNlckFjY291bnQoaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgdGhlIG5hbWUgb2YgdGhlIGBVc2VyQWNjb3VudElEYCBpbiB0aGUgdW5kZXJseWluZyBwcm92aWRlci4gVGhyb3dzIGFuIGBVcGRhdGVVc2VyQWNjb3VudFVuc3VwcG9ydGVkRXJyb3JgIGlmIHRoZSBvcGVyYXRpb24gaXMgdW5zdXBwb3J0ZWQuXG4gICAqXG4gICAqIFVzZXJzIHNob3VsZCBjaGVjayBgZ2V0U3VwcG9ydGVkRmVhdHVyZXNgIGJlZm9yZSBjYWxsaW5nIHRoaXMgbWV0aG9kLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHVwZGF0ZVVzZXJBY2NvdW50TmFtZShvcHRpb25zOiBVcGRhdGVBY2NvdW50TmFtZU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IGlkLCBuYW1lIH0gPSBhcmdzLmFzc2VydFVwZGF0ZUFjY291bnROYW1lT3B0aW9ucygnb3B0aW9ucycsIG9wdGlvbnMpO1xuICAgIGNvbnN0IHByb3ZpZGVyID0gdGhpcy5nZXRQcm92aWRlcih7IGZyb206IGlkIH0pO1xuICAgIGlmIChwcm92aWRlci51cGRhdGVVc2VyQWNjb3VudE5hbWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IFVwZGF0ZVVzZXJBY2NvdW50VW5zdXBwb3J0ZWRFcnJvcihpZCk7XG4gICAgfVxuXG4gICAgYXdhaXQgcHJvdmlkZXIudXBkYXRlVXNlckFjY291bnROYW1lKHsgaWQsIG5hbWUgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBgVXNlckFjY291bnRgIG9yIGB1bmRlZmluZWRgIGlmIHRoZXJlIGFyZSBubyBgVXNlckFjY291bnRgcy5cbiAgICovXG4gIHB1YmxpYyBnZXRDdXJyZW50VXNlckFjY291bnQoKTogVXNlckFjY291bnQgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnNlbGVjdGVkUHJvdmlkZXIkLmdldFZhbHVlKCkuZ2V0Q3VycmVudFVzZXJBY2NvdW50KCk7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBgTmV0d29ya1R5cGVgXG4gICAqL1xuICBwdWJsaWMgZ2V0Q3VycmVudE5ldHdvcmsoKTogTmV0d29ya1R5cGUge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnROZXR3b3JrSW50ZXJuYWwkLmdldFZhbHVlKCk7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMgYSBsaXN0IG9mIGFsbCBhdmFpbGFibGUgYFVzZXJBY2NvdW50YHNcbiAgICovXG4gIHB1YmxpYyBnZXRVc2VyQWNjb3VudHMoKTogcmVhZG9ubHkgVXNlckFjY291bnRbXSB7XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5wcm92aWRlcnMpLnJlZHVjZShcbiAgICAgIChhY2M6IFVzZXJBY2NvdW50W10sIHByb3ZpZGVyKSA9PiBhY2MuY29uY2F0KHByb3ZpZGVyLmdldFVzZXJBY2NvdW50cygpKSxcbiAgICAgIFtdLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMgYSBsaXN0IG9mIGFsbCBhdmFpbGFibGUgYE5ldHdvcmtUeXBlYHNcbiAgICovXG4gIHB1YmxpYyBnZXROZXR3b3JrcygpOiByZWFkb25seSBOZXR3b3JrVHlwZVtdIHtcbiAgICBjb25zdCBwcm92aWRlcnMgPSBPYmplY3QudmFsdWVzKHRoaXMucHJvdmlkZXJzKTtcblxuICAgIHJldHVybiBbLi4ubmV3IFNldChwcm92aWRlcnMucmVkdWNlKChhY2M6IE5ldHdvcmtUeXBlW10sIHByb3ZpZGVyKSA9PiBhY2MuY29uY2F0KHByb3ZpZGVyLmdldE5ldHdvcmtzKCkpLCBbXSkpXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgYFNtYXJ0Q29udHJhY3RgIGluc3RhbmNlIGZvciB0aGUgcHJvdmlkZWQgYGRlZmluaXRpb25gIGJhY2tlZCBieSB0aGlzIGBDbGllbnRgIGluc3RhbmNlLlxuICAgKi9cbiAgcHVibGljIHNtYXJ0Q29udHJhY3Q8VCBleHRlbmRzIFNtYXJ0Q29udHJhY3Q8YW55LCBhbnk+ID0gU21hcnRDb250cmFjdEFueT4oZGVmaW5pdGlvbjogU21hcnRDb250cmFjdERlZmluaXRpb24pOiBUIHtcbiAgICByZXR1cm4gY3JlYXRlU21hcnRDb250cmFjdCh7XG4gICAgICBkZWZpbml0aW9uOiBhcmdzLmFzc2VydFNtYXJ0Q29udHJhY3REZWZpbml0aW9uKCdkZWZpbml0aW9uJywgZGVmaW5pdGlvbiksXG4gICAgICBjbGllbnQ6IHRoaXMsXG4gICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tYW55XG4gICAgfSkgYXMgYW55O1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYW5zZmVyIG5hdGl2ZSBhc3NldHMgaW4gdGhlIHNwZWNpZmllZCBhbW91bnQocykgdG8gdGhlIHNwZWNpZmllZCBBZGRyZXNzKGVzKS5cbiAgICpcbiAgICogQWNjZXB0cyBlaXRoZXIgYSBzaW5nbGUgdHJhbnNmZXIgb3IgYW4gYXJyYXkgb2YgdHJhbnNmZXIgb2JqZWN0cy5cbiAgICpcbiAgICogTm90ZSB0aGF0IHdlIHVzZSBhbiBgSW52b2NhdGlvblRyYW5zYWN0aW9uYCBmb3IgdHJhbnNmZXJzIGluIG9yZGVyIHRvIHJlZHVjZSB0aGUgb3ZlcmFsbCBidW5kbGUgc2l6ZSBzaW5jZSB0aGV5IGNhbiBiZSB1c2VkIGVxdWl2YWxlbnRseSB0byBgQ29udHJhY3RUcmFuc2FjdGlvbmBzLlxuICAgKlxuICAgKiBAcmV0dXJucyBgUHJvbWlzZTxUcmFuc2FjdGlvblJlc3VsdDxUcmFuc2FjdGlvblJlY2VpcHQsIEludm9jYXRpb25UcmFuc2FjdGlvbj4+YC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyB0cmFuc2ZlcihcbiAgICBhbW91bnQ6IEJpZ051bWJlcixcbiAgICBhc3NldDogSGFzaDI1NlN0cmluZyxcbiAgICB0bzogQWRkcmVzc1N0cmluZyxcbiAgICBvcHRpb25zPzogVHJhbnNhY3Rpb25PcHRpb25zLFxuICApOiBQcm9taXNlPFRyYW5zYWN0aW9uUmVzdWx0PFRyYW5zYWN0aW9uUmVjZWlwdCwgSW52b2NhdGlvblRyYW5zYWN0aW9uPj47XG4gIHB1YmxpYyBhc3luYyB0cmFuc2Zlcih0cmFuc2ZlcnM6IHJlYWRvbmx5IFRyYW5zZmVyW10sIG9wdGlvbnM/OiBUcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPFRyYW5zYWN0aW9uUmVzdWx0PjtcbiAgcHVibGljIGFzeW5jIHRyYW5zZmVyKC4uLmFyZ3NJbjogYW55W10pOiBQcm9taXNlPFRyYW5zYWN0aW9uUmVzdWx0PiB7XG4gICAgY29uc3QgeyB0cmFuc2ZlcnMsIG9wdGlvbnMgfSA9IHRoaXMuZ2V0VHJhbnNmZXJzT3B0aW9ucyhhcmdzSW4pO1xuICAgIGF3YWl0IHRoaXMuYXBwbHlCZWZvcmVSZWxheUhvb2sob3B0aW9ucyk7XG5cbiAgICByZXR1cm4gdGhpcy5hZGRUcmFuc2FjdGlvbkhvb2tzKHRoaXMuZ2V0UHJvdmlkZXIob3B0aW9ucykudHJhbnNmZXIodHJhbnNmZXJzLCBvcHRpb25zKSk7XG4gIH1cblxuICAvKipcbiAgICogQ2xhaW0gYWxsIGF2YWlsYWJsZSB1bmNsYWltZWQgYEdBU2AgZm9yIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgYWNjb3VudCAob3IgdGhlIHNwZWNpZmllZCBgZnJvbWAgYFVzZXJBY2NvdW50SURgKS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBjbGFpbShvcHRpb25zSW4/OiBUcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPFRyYW5zYWN0aW9uUmVzdWx0PFRyYW5zYWN0aW9uUmVjZWlwdCwgQ2xhaW1UcmFuc2FjdGlvbj4+IHtcbiAgICBjb25zdCBvcHRpb25zID0gYXJncy5hc3NlcnRUcmFuc2FjdGlvbk9wdGlvbnMoJ29wdGlvbnMnLCBvcHRpb25zSW4pO1xuICAgIGF3YWl0IHRoaXMuYXBwbHlCZWZvcmVSZWxheUhvb2sob3B0aW9ucyk7XG5cbiAgICByZXR1cm4gdGhpcy5hZGRUcmFuc2FjdGlvbkhvb2tzKHRoaXMuZ2V0UHJvdmlkZXIob3B0aW9ucykuY2xhaW0ob3B0aW9ucykpO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIGBQcm9taXNlYCB3aGljaCByZXNvbHZlcyB0byBhbiBgQWNjb3VudGAgb2JqZWN0IGZvciB0aGUgcHJvdmlkZWQgYFVzZXJBY2NvdW50SURgLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGdldEFjY291bnQoaWQ6IFVzZXJBY2NvdW50SUQsIG1vbml0b3I/OiBNb25pdG9yKTogUHJvbWlzZTxBY2NvdW50PiB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0TmV0d29ya1Byb3ZpZGVyKGlkLm5ldHdvcmspLmdldEFjY291bnQoaWQubmV0d29yaywgaWQuYWRkcmVzcywgbW9uaXRvcik7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX19pdGVyQWN0aW9uc1JhdyhuZXR3b3JrOiBOZXR3b3JrVHlwZSwgb3B0aW9ucz86IEl0ZXJPcHRpb25zKTogQXN5bmNJdGVyYWJsZTxSYXdBY3Rpb24+IHtcbiAgICBjb25zdCBwcm92aWRlciA9IHRoaXMuZ2V0TmV0d29ya1Byb3ZpZGVyKG5ldHdvcmspO1xuICAgIGlmIChwcm92aWRlci5pdGVyQWN0aW9uc1JhdyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcHJvdmlkZXIuaXRlckFjdGlvbnNSYXcobmV0d29yaywgb3B0aW9ucyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEFzeW5jSXRlcmFibGVYLmZyb20ocHJvdmlkZXIuaXRlckJsb2NrcyhuZXR3b3JrLCBvcHRpb25zKSkucGlwZTxSYXdBY3Rpb24+KFxuICAgICAgZmxhdE1hcChhc3luYyAoYmxvY2spID0+IHtcbiAgICAgICAgY29uc3QgYWN0aW9ucyA9IF8uZmxhdHRlbihcbiAgICAgICAgICBibG9jay50cmFuc2FjdGlvbnMubWFwKCh0cmFuc2FjdGlvbikgPT4ge1xuICAgICAgICAgICAgaWYgKHRyYW5zYWN0aW9uLnR5cGUgPT09ICdJbnZvY2F0aW9uVHJhbnNhY3Rpb24nKSB7XG4gICAgICAgICAgICAgIHJldHVybiBbLi4udHJhbnNhY3Rpb24uaW52b2NhdGlvbkRhdGEuYWN0aW9uc107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgKTtcblxuICAgICAgICByZXR1cm4gQXN5bmNJdGVyYWJsZVgub2YoLi4uYWN0aW9ucyk7XG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIGFzeW5jIF9faW52b2tlKFxuICAgIGNvbnRyYWN0OiBBZGRyZXNzU3RyaW5nLFxuICAgIG1ldGhvZDogc3RyaW5nLFxuICAgIHBhcmFtczogUmVhZG9ubHlBcnJheTxTY3JpcHRCdWlsZGVyUGFyYW0gfCB1bmRlZmluZWQ+LFxuICAgIHBhcmFtc1ppcHBlZDogUmVhZG9ubHlBcnJheTxyZWFkb25seSBbc3RyaW5nLCBQYXJhbSB8IHVuZGVmaW5lZF0+LFxuICAgIHZlcmlmeTogYm9vbGVhbixcbiAgICBvcHRpb25zSW4/OiBJbnZva2VTZW5kVW5zYWZlUmVjZWl2ZVRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgICBzb3VyY2VNYXBzOiBQcm9taXNlPFNvdXJjZU1hcHM+ID0gUHJvbWlzZS5yZXNvbHZlKHt9KSxcbiAgKTogUHJvbWlzZTxUcmFuc2FjdGlvblJlc3VsdDxSYXdJbnZva2VSZWNlaXB0LCBJbnZvY2F0aW9uVHJhbnNhY3Rpb24+PiB7XG4gICAgY29uc3Qgb3B0aW9ucyA9IG9wdGlvbnNJbiA9PT0gdW5kZWZpbmVkID8ge30gOiBvcHRpb25zSW47XG4gICAgYXdhaXQgdGhpcy5hcHBseUJlZm9yZVJlbGF5SG9vayhvcHRpb25zKTtcblxuICAgIHJldHVybiB0aGlzLmFkZFRyYW5zYWN0aW9uSG9va3MoXG4gICAgICB0aGlzLmdldFByb3ZpZGVyKG9wdGlvbnMpLmludm9rZShjb250cmFjdCwgbWV0aG9kLCBwYXJhbXMsIHBhcmFtc1ppcHBlZCwgdmVyaWZ5LCBvcHRpb25zLCBzb3VyY2VNYXBzKSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIGFzeW5jIF9faW52b2tlU2VuZChcbiAgICBjb250cmFjdDogQWRkcmVzc1N0cmluZyxcbiAgICBtZXRob2Q6IHN0cmluZyxcbiAgICBwYXJhbXM6IFJlYWRvbmx5QXJyYXk8U2NyaXB0QnVpbGRlclBhcmFtIHwgdW5kZWZpbmVkPixcbiAgICBwYXJhbXNaaXBwZWQ6IFJlYWRvbmx5QXJyYXk8cmVhZG9ubHkgW3N0cmluZywgUGFyYW0gfCB1bmRlZmluZWRdPixcbiAgICB0cmFuc2ZlcjogVHJhbnNmZXIsXG4gICAgb3B0aW9uc0luPzogVHJhbnNhY3Rpb25PcHRpb25zLFxuICAgIHNvdXJjZU1hcHM6IFByb21pc2U8U291cmNlTWFwcz4gPSBQcm9taXNlLnJlc29sdmUoe30pLFxuICApOiBQcm9taXNlPFRyYW5zYWN0aW9uUmVzdWx0PFJhd0ludm9rZVJlY2VpcHQsIEludm9jYXRpb25UcmFuc2FjdGlvbj4+IHtcbiAgICBjb25zdCBvcHRpb25zID0gb3B0aW9uc0luID09PSB1bmRlZmluZWQgPyB7fSA6IG9wdGlvbnNJbjtcbiAgICBhd2FpdCB0aGlzLmFwcGx5QmVmb3JlUmVsYXlIb29rKG9wdGlvbnMpO1xuXG4gICAgcmV0dXJuIHRoaXMuYWRkVHJhbnNhY3Rpb25Ib29rcyhcbiAgICAgIHRoaXMuZ2V0UHJvdmlkZXIob3B0aW9ucykuaW52b2tlU2VuZChjb250cmFjdCwgbWV0aG9kLCBwYXJhbXMsIHBhcmFtc1ppcHBlZCwgdHJhbnNmZXIsIG9wdGlvbnMsIHNvdXJjZU1hcHMpLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgX19pbnZva2VDb21wbGV0ZVNlbmQoXG4gICAgY29udHJhY3Q6IEFkZHJlc3NTdHJpbmcsXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgcGFyYW1zOiBSZWFkb25seUFycmF5PFNjcmlwdEJ1aWxkZXJQYXJhbSB8IHVuZGVmaW5lZD4sXG4gICAgcGFyYW1zWmlwcGVkOiBSZWFkb25seUFycmF5PHJlYWRvbmx5IFtzdHJpbmcsIFBhcmFtIHwgdW5kZWZpbmVkXT4sXG4gICAgaGFzaDogSGFzaDI1NlN0cmluZyxcbiAgICBvcHRpb25zSW4/OiBUcmFuc2FjdGlvbk9wdGlvbnMsXG4gICAgc291cmNlTWFwczogUHJvbWlzZTxTb3VyY2VNYXBzPiA9IFByb21pc2UucmVzb2x2ZSh7fSksXG4gICk6IFByb21pc2U8VHJhbnNhY3Rpb25SZXN1bHQ8UmF3SW52b2tlUmVjZWlwdCwgSW52b2NhdGlvblRyYW5zYWN0aW9uPj4ge1xuICAgIGNvbnN0IG9wdGlvbnMgPSBvcHRpb25zSW4gPT09IHVuZGVmaW5lZCA/IHt9IDogb3B0aW9uc0luO1xuICAgIGF3YWl0IHRoaXMuYXBwbHlCZWZvcmVSZWxheUhvb2sob3B0aW9ucyk7XG5cbiAgICByZXR1cm4gdGhpcy5hZGRUcmFuc2FjdGlvbkhvb2tzKFxuICAgICAgdGhpcy5nZXRQcm92aWRlcihvcHRpb25zKS5pbnZva2VDb21wbGV0ZVNlbmQoY29udHJhY3QsIG1ldGhvZCwgcGFyYW1zLCBwYXJhbXNaaXBwZWQsIGhhc2gsIG9wdGlvbnMsIHNvdXJjZU1hcHMpLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgX19pbnZva2VSZWZ1bmRBc3NldHMoXG4gICAgY29udHJhY3Q6IEFkZHJlc3NTdHJpbmcsXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgcGFyYW1zOiBSZWFkb25seUFycmF5PFNjcmlwdEJ1aWxkZXJQYXJhbSB8IHVuZGVmaW5lZD4sXG4gICAgcGFyYW1zWmlwcGVkOiBSZWFkb25seUFycmF5PHJlYWRvbmx5IFtzdHJpbmcsIFBhcmFtIHwgdW5kZWZpbmVkXT4sXG4gICAgaGFzaDogSGFzaDI1NlN0cmluZyxcbiAgICBvcHRpb25zSW4/OiBUcmFuc2FjdGlvbk9wdGlvbnMsXG4gICAgc291cmNlTWFwczogUHJvbWlzZTxTb3VyY2VNYXBzPiA9IFByb21pc2UucmVzb2x2ZSh7fSksXG4gICk6IFByb21pc2U8VHJhbnNhY3Rpb25SZXN1bHQ8UmF3SW52b2tlUmVjZWlwdCwgSW52b2NhdGlvblRyYW5zYWN0aW9uPj4ge1xuICAgIGNvbnN0IG9wdGlvbnMgPSBvcHRpb25zSW4gPT09IHVuZGVmaW5lZCA/IHt9IDogb3B0aW9uc0luO1xuICAgIGF3YWl0IHRoaXMuYXBwbHlCZWZvcmVSZWxheUhvb2sob3B0aW9ucyk7XG5cbiAgICByZXR1cm4gdGhpcy5hZGRUcmFuc2FjdGlvbkhvb2tzKFxuICAgICAgdGhpcy5nZXRQcm92aWRlcihvcHRpb25zKS5pbnZva2VSZWZ1bmRBc3NldHMoY29udHJhY3QsIG1ldGhvZCwgcGFyYW1zLCBwYXJhbXNaaXBwZWQsIGhhc2gsIG9wdGlvbnMsIHNvdXJjZU1hcHMpLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgX19pbnZva2VDbGFpbShcbiAgICBjb250cmFjdDogQWRkcmVzc1N0cmluZyxcbiAgICBtZXRob2Q6IHN0cmluZyxcbiAgICBwYXJhbXM6IFJlYWRvbmx5QXJyYXk8U2NyaXB0QnVpbGRlclBhcmFtIHwgdW5kZWZpbmVkPixcbiAgICBwYXJhbXNaaXBwZWQ6IFJlYWRvbmx5QXJyYXk8cmVhZG9ubHkgW3N0cmluZywgUGFyYW0gfCB1bmRlZmluZWRdPixcbiAgICBvcHRpb25zSW4/OiBUcmFuc2FjdGlvbk9wdGlvbnMsXG4gICAgc291cmNlTWFwczogUHJvbWlzZTxTb3VyY2VNYXBzPiA9IFByb21pc2UucmVzb2x2ZSh7fSksXG4gICk6IFByb21pc2U8VHJhbnNhY3Rpb25SZXN1bHQ8VHJhbnNhY3Rpb25SZWNlaXB0LCBDbGFpbVRyYW5zYWN0aW9uPj4ge1xuICAgIGNvbnN0IG9wdGlvbnMgPSBvcHRpb25zSW4gPT09IHVuZGVmaW5lZCA/IHt9IDogb3B0aW9uc0luO1xuICAgIGF3YWl0IHRoaXMuYXBwbHlCZWZvcmVSZWxheUhvb2sob3B0aW9ucyk7XG5cbiAgICByZXR1cm4gdGhpcy5hZGRUcmFuc2FjdGlvbkhvb2tzKFxuICAgICAgdGhpcy5nZXRQcm92aWRlcihvcHRpb25zKS5pbnZva2VDbGFpbShjb250cmFjdCwgbWV0aG9kLCBwYXJhbXMsIHBhcmFtc1ppcHBlZCwgb3B0aW9ucywgc291cmNlTWFwcyksXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1YmxpYyBhc3luYyBfX2NhbGwoXG4gICAgbmV0d29yazogTmV0d29ya1R5cGUsXG4gICAgY29udHJhY3Q6IEFkZHJlc3NTdHJpbmcsXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgcGFyYW1zOiBSZWFkb25seUFycmF5PFNjcmlwdEJ1aWxkZXJQYXJhbSB8IHVuZGVmaW5lZD4sXG4gICAgbW9uaXRvcj86IE1vbml0b3IsXG4gICk6IFByb21pc2U8UmF3Q2FsbFJlY2VpcHQ+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVjZWlwdCA9IGF3YWl0IHRoaXMuZ2V0TmV0d29ya1Byb3ZpZGVyKG5ldHdvcmspLmNhbGwobmV0d29yaywgY29udHJhY3QsIG1ldGhvZCwgcGFyYW1zLCBtb25pdG9yKTtcbiAgICAgIGF3YWl0IHRoaXMuaG9va3MuYWZ0ZXJDYWxsLnByb21pc2UocmVjZWlwdCk7XG5cbiAgICAgIHJldHVybiByZWNlaXB0O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBhd2FpdCB0aGlzLmhvb2tzLmNhbGxFcnJvci5wcm9taXNlKGVycm9yKTtcblxuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIHJlc2V0KCk6IHZvaWQge1xuICAgIHRoaXMucmVzZXQkLm5leHQodW5kZWZpbmVkKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRQcm92aWRlcihvcHRpb25zOiBUcmFuc2FjdGlvbk9wdGlvbnMgPSB7fSk6IFRVc2VyQWNjb3VudFByb3ZpZGVyIHtcbiAgICBjb25zdCB7IGZyb20gfSA9IG9wdGlvbnM7XG4gICAgaWYgKGZyb20gPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWRQcm92aWRlciQuZ2V0VmFsdWUoKTtcbiAgICB9XG5cbiAgICBjb25zdCBwcm92aWRlcnMgPSBPYmplY3QudmFsdWVzKHRoaXMucHJvdmlkZXJzKTtcbiAgICBjb25zdCBhY2NvdW50UHJvdmlkZXIgPSBwcm92aWRlcnMuZmluZCgocHJvdmlkZXIpID0+XG4gICAgICBwcm92aWRlclxuICAgICAgICAuZ2V0VXNlckFjY291bnRzKClcbiAgICAgICAgLnNvbWUoKGFjY291bnQpID0+IGFjY291bnQuaWQubmV0d29yayA9PT0gZnJvbS5uZXR3b3JrICYmIGFjY291bnQuaWQuYWRkcmVzcyA9PT0gZnJvbS5hZGRyZXNzKSxcbiAgICApO1xuXG4gICAgaWYgKGFjY291bnRQcm92aWRlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgVW5rbm93bkFjY291bnRFcnJvcihmcm9tLmFkZHJlc3MpO1xuICAgIH1cblxuICAgIHJldHVybiBhY2NvdW50UHJvdmlkZXI7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0TmV0d29ya1Byb3ZpZGVyKG5ldHdvcms6IE5ldHdvcmtUeXBlKTogVFVzZXJBY2NvdW50UHJvdmlkZXIge1xuICAgIGNvbnN0IHByb3ZpZGVycyA9IE9iamVjdC52YWx1ZXModGhpcy5wcm92aWRlcnMpO1xuICAgIGNvbnN0IGFjY291bnRQcm92aWRlciA9IHByb3ZpZGVycy5maW5kKChwcm92aWRlcikgPT5cbiAgICAgIHByb3ZpZGVyLmdldE5ldHdvcmtzKCkuc29tZSgocHJvdmlkZXJOZXR3b3JrKSA9PiBwcm92aWRlck5ldHdvcmsgPT09IG5ldHdvcmspLFxuICAgICk7XG5cbiAgICBpZiAoYWNjb3VudFByb3ZpZGVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBVbmtub3duTmV0d29ya0Vycm9yKG5ldHdvcmspO1xuICAgIH1cblxuICAgIHJldHVybiBhY2NvdW50UHJvdmlkZXI7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgYXBwbHlCZWZvcmVSZWxheUhvb2sob3B0aW9uczogVHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuaG9va3MuYmVmb3JlUmVsYXkucHJvbWlzZShvcHRpb25zKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgYWRkVHJhbnNhY3Rpb25Ib29rczxUVHJhbnNhY3Rpb25SZXN1bHQgZXh0ZW5kcyBUcmFuc2FjdGlvblJlc3VsdD4oXG4gICAgcmVzOiBQcm9taXNlPFRUcmFuc2FjdGlvblJlc3VsdD4sXG4gICk6IFByb21pc2U8VFRyYW5zYWN0aW9uUmVzdWx0PiB7XG4gICAgcmV0dXJuIHJlc1xuICAgICAgLnRoZW4oYXN5bmMgKHJlc3VsdCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuaG9va3MuYWZ0ZXJSZWxheS5wcm9taXNlKHJlc3VsdC50cmFuc2FjdGlvbik7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBwcmVmZXItb2JqZWN0LXNwcmVhZFxuICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgcmVzdWx0LCB7XG4gICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLXVubmVjZXNzYXJ5LXR5cGUtYW5ub3RhdGlvblxuICAgICAgICAgIGNvbmZpcm1lZDogYXN5bmMgKG9wdGlvbnM/OiBHZXRPcHRpb25zKSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBhd2FpdCB0aGlzLmhvb2tzLmJlZm9yZUNvbmZpcm1lZC5wcm9taXNlKHJlc3VsdC50cmFuc2FjdGlvbik7XG4gICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgLy8gZG8gbm90aGluZ1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgY29uc3QgcmVjZWlwdCA9IGF3YWl0IHJlc3VsdC5jb25maXJtZWQob3B0aW9ucyk7XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5ob29rcy5hZnRlckNvbmZpcm1lZC5wcm9taXNlKHJlc3VsdC50cmFuc2FjdGlvbiwgcmVjZWlwdCk7XG4gICAgICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHJldHVybiByZWNlaXB0O1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmhvb2tzLmNvbmZpcm1lZEVycm9yLnByb21pc2UocmVzdWx0LnRyYW5zYWN0aW9uLCBlcnJvcik7XG4gICAgICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChhc3luYyAoZXJyb3IpID0+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5ob29rcy5yZWxheUVycm9yLnByb21pc2UoZXJyb3IpO1xuXG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0VHJhbnNmZXJzT3B0aW9ucyhcbiAgICBhcmdzSW46IHJlYWRvbmx5IGFueVtdLFxuICApOiB7XG4gICAgcmVhZG9ubHkgdHJhbnNmZXJzOiByZWFkb25seSBUcmFuc2ZlcltdO1xuICAgIHJlYWRvbmx5IG9wdGlvbnM6IFRyYW5zYWN0aW9uT3B0aW9ucztcbiAgfSB7XG4gICAgbGV0IHRyYW5zZmVycztcbiAgICBsZXQgb3B0aW9ucztcbiAgICBpZiAoYXJnc0luLmxlbmd0aCA+PSAzKSB7XG4gICAgICB0cmFuc2ZlcnMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBhbW91bnQ6IGFyZ3NJblswXSxcbiAgICAgICAgICBhc3NldDogYXJnc0luWzFdLFxuICAgICAgICAgIHRvOiBhcmdzSW5bMl0sXG4gICAgICAgIH0sXG4gICAgICBdO1xuXG4gICAgICBvcHRpb25zID0gYXJnc0luWzNdO1xuICAgIH0gZWxzZSB7XG4gICAgICB0cmFuc2ZlcnMgPSBhcmdzSW5bMF07XG4gICAgICBvcHRpb25zID0gYXJnc0luWzFdO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICB0cmFuc2ZlcnM6IGFyZ3MuYXNzZXJ0VHJhbnNmZXJzKCd0cmFuc2ZlcnMnLCB0cmFuc2ZlcnMpLFxuICAgICAgb3B0aW9uczogYXJncy5hc3NlcnRUcmFuc2FjdGlvbk9wdGlvbnMoJ29wdGlvbnMnLCBvcHRpb25zKSxcbiAgICB9O1xuICB9XG59XG4iXX0=