@orbit/jsonapi
Version:
JSON:API support for Orbit.
265 lines (263 loc) • 41.5 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { Orbit, Assertion } from '@orbit/core';
import { pullable, pushable, queryable, updatable, TransformNotAllowed, QueryNotAllowed } from '@orbit/data';
import { RecordSource } from '@orbit/records';
import { JSONAPIRequestProcessor } from './jsonapi-request-processor';
import { JSONAPIURLBuilder } from './jsonapi-url-builder';
import { QueryRequestProcessors, getQueryRequests } from './lib/query-requests';
import { TransformRequestProcessors, getTransformRequests } from './lib/transform-requests';
const { deprecate } = Orbit;
/**
Source for accessing a JSON API compliant RESTful API with a network fetch
request.
If a single transform or query requires more than one fetch request,
requests will be performed sequentially and resolved together. From the
perspective of Orbit, these operations will all succeed or fail together. The
`maxRequestsPerTransform` and `maxRequestsPerQuery` settings allow limits to be
set on this behavior. These settings should be set to `1` if your client/server
configuration is unable to resolve partially successful transforms / queries.
@class JSONAPISource
@extends Source
*/
let JSONAPISource = class JSONAPISource extends RecordSource {
constructor(settings) {
settings.name = settings.name || 'jsonapi';
super(settings);
let { name, maxRequestsPerTransform, maxRequestsPerQuery, namespace, host, defaultFetchSettings, allowedContentTypes, serializerFor, serializerClassFor, serializerSettingsFor, SerializerClass, RequestProcessorClass, URLBuilderClass, keyMap } = settings;
if (this.schema === undefined) {
throw new Assertion("JSONAPISource's `schema` must be specified in the `settings` passed to its constructor");
}
if (this._defaultQueryOptions === undefined) {
this._defaultQueryOptions = {};
}
if (this._defaultTransformOptions === undefined) {
this._defaultTransformOptions = {};
}
// Parallelize query requests by default (but not transform requests)
if (this._defaultQueryOptions.parallelRequests === undefined) {
this._defaultQueryOptions.parallelRequests = true;
}
if (maxRequestsPerTransform !== undefined) {
deprecate("The 'maxRequestsPerTransform' setting for 'JSONAPSource' has been deprecated in favor of 'defaultTransformOptions.maxRequests'.");
this._defaultTransformOptions.maxRequests = maxRequestsPerTransform;
}
if (maxRequestsPerQuery !== undefined) {
deprecate("The 'maxRequestsPerQuery' setting for 'JSONAPSource' has been deprecated in favor of 'defaultQueryOptions.maxRequests'.");
this._defaultQueryOptions.maxRequests = maxRequestsPerQuery;
}
RequestProcessorClass = RequestProcessorClass || JSONAPIRequestProcessor;
this.requestProcessor = new RequestProcessorClass({
sourceName: name,
serializerFor,
serializerClassFor,
serializerSettingsFor,
SerializerClass,
URLBuilderClass: URLBuilderClass || JSONAPIURLBuilder,
allowedContentTypes,
defaultFetchSettings,
namespace,
host,
schema: this.schema,
keyMap
});
}
/**
* Deprecated in favor of `defaultTransformOptions.maxRequests`
*
* @deprecated since v0.17, remove in v0.18
*/
get maxRequestsPerTransform() {
var _a;
deprecate("The 'maxRequestsPerTransform' property for 'JSONAPSource' has been deprecated in favor of 'defaultTransformOptions.maxRequests'.");
return (_a = this._defaultTransformOptions) === null || _a === void 0 ? void 0 : _a.maxRequests;
}
/**
* Deprecated in favor of `defaultTransformOptions.maxRequests`
*
* @deprecated since v0.17, remove in v0.18
*/
set maxRequestsPerTransform(val) {
deprecate("The 'maxRequestsPerTransform' property for 'JSONAPSource' has been deprecated in favor of 'defaultTransformOptions.maxRequests'.");
if (this._defaultTransformOptions === undefined) {
this._defaultTransformOptions = {};
}
this._defaultTransformOptions.maxRequests = val;
}
/**
* Deprecated in favor of `defaultQueryOptions.maxRequests`
*
* @deprecated since v0.17, remove in v0.18
*/
get maxRequestsPerQuery() {
var _a;
deprecate("The 'maxRequestsPerQuery' property for 'JSONAPSource' has been deprecated in favor of 'defaultQueryOptions.maxRequests'.");
return (_a = this._defaultQueryOptions) === null || _a === void 0 ? void 0 : _a.maxRequests;
}
/**
* Deprecated in favor of `defaultQueryOptions.maxRequests`
*
* @deprecated since v0.17, remove in v0.18
*/
set maxRequestsPerQuery(val) {
deprecate("The 'maxRequestsPerQuery' property for 'JSONAPSource' has been deprecated in favor of 'defaultQueryOptions.maxRequests'.");
if (this._defaultQueryOptions === undefined) {
this._defaultQueryOptions = {};
}
this._defaultQueryOptions.maxRequests = val;
}
/////////////////////////////////////////////////////////////////////////////
// Pushable interface implementation
/////////////////////////////////////////////////////////////////////////////
async _push(transform) {
if (this.transformLog.contains(transform.id)) {
return {};
}
const responses = await this.processTransformRequests(transform);
const details = [];
const transforms = [];
for (let response of responses) {
if (response.transforms) {
Array.prototype.push.apply(transforms, response.transforms);
}
if (response.details) {
details.push(response.details);
}
}
return {
transforms: [transform, ...transforms],
details
};
}
/////////////////////////////////////////////////////////////////////////////
// Pullable interface implementation
/////////////////////////////////////////////////////////////////////////////
async _pull(query) {
const responses = await this.processQueryRequests(query);
const details = [];
const transforms = [];
for (let response of responses) {
if (response.transforms) {
Array.prototype.push.apply(transforms, response.transforms);
}
if (response.details) {
details.push(response.details);
}
}
return {
transforms,
details
};
}
/////////////////////////////////////////////////////////////////////////////
// Queryable interface implementation
/////////////////////////////////////////////////////////////////////////////
async _query(query) {
const responses = await this.processQueryRequests(query);
const details = [];
const transforms = [];
const data = [];
for (let response of responses) {
if (response.transforms) {
Array.prototype.push.apply(transforms, response.transforms);
}
if (response.details) {
details.push(response.details);
}
data.push(response.data);
}
return {
data: Array.isArray(query.expressions) ? data : data[0],
details,
transforms
};
}
/////////////////////////////////////////////////////////////////////////////
// Updatable interface implementation
/////////////////////////////////////////////////////////////////////////////
async _update(transform) {
if (this.transformLog.contains(transform.id)) {
return {};
}
const responses = await this.processTransformRequests(transform);
const details = [];
const transforms = [];
const data = [];
for (let response of responses) {
if (response.transforms) {
Array.prototype.push.apply(transforms, response.transforms);
}
if (response.details) {
details.push(response.details);
}
data.push(response.data);
}
return {
data: Array.isArray(transform.operations) ? data : data[0],
details,
transforms: [transform, ...transforms]
};
}
getQueryRequestProcessor(request) {
return QueryRequestProcessors[request.op];
}
getTransformRequestProcessor(request) {
return TransformRequestProcessors[request.op];
}
async processQueryRequests(query) {
const options = this.getQueryOptions(query);
const requests = getQueryRequests(this.requestProcessor, query);
if ((options === null || options === void 0 ? void 0 : options.maxRequests) !== undefined &&
requests.length > options.maxRequests) {
throw new QueryNotAllowed(`This query requires ${requests.length} requests, which exceeds the specified limit of ${options.maxRequests} requests per query.`, query);
}
if (options === null || options === void 0 ? void 0 : options.parallelRequests) {
return Promise.all(requests.map((request) => {
const processor = this.getQueryRequestProcessor(request);
return processor(this.requestProcessor, request);
}));
}
else {
const responses = [];
for (let request of requests) {
const processor = this.getQueryRequestProcessor(request);
responses.push(await processor(this.requestProcessor, request));
}
return responses;
}
}
async processTransformRequests(transform) {
const options = this.getTransformOptions(transform);
const requests = getTransformRequests(this.requestProcessor, transform);
if ((options === null || options === void 0 ? void 0 : options.maxRequests) !== undefined &&
requests.length > options.maxRequests) {
throw new TransformNotAllowed(`This transform requires ${requests.length} requests, which exceeds the specified limit of ${options.maxRequests} requests per transform.`, transform);
}
if (options === null || options === void 0 ? void 0 : options.parallelRequests) {
return Promise.all(requests.map((request) => {
const processor = this.getTransformRequestProcessor(request);
return processor(this.requestProcessor, request);
}));
}
else {
const responses = [];
for (let request of requests) {
const processor = this.getTransformRequestProcessor(request);
responses.push(await processor(this.requestProcessor, request));
}
return responses;
}
}
};
JSONAPISource = __decorate([
pullable,
pushable,
queryable,
updatable
], JSONAPISource);
export { JSONAPISource };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianNvbmFwaS1zb3VyY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvanNvbmFwaS1zb3VyY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsT0FBTyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDL0MsT0FBTyxFQUVMLFFBQVEsRUFDUixRQUFRLEVBQ1IsU0FBUyxFQUNULFNBQVMsRUFDVCxtQkFBbUIsRUFDbkIsZUFBZSxFQUdoQixNQUFNLGFBQWEsQ0FBQztBQUNyQixPQUFPLEVBQ0wsWUFBWSxFQWdCYixNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFDTCx1QkFBdUIsRUFHeEIsTUFBTSw2QkFBNkIsQ0FBQztBQUtyQyxPQUFPLEVBQ0wsaUJBQWlCLEVBRWxCLE1BQU0sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxFQUVMLHNCQUFzQixFQUV0QixnQkFBZ0IsRUFFakIsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBRUwsMEJBQTBCLEVBRTFCLG9CQUFvQixFQUVyQixNQUFNLDBCQUEwQixDQUFDO0FBUWxDLE1BQU0sRUFBRSxTQUFTLEVBQUUsR0FBRyxLQUFLLENBQUM7QUFnRTVCOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFLSCxJQUFhLGFBQWEsR0FBMUIsTUFBYSxhQU1YLFNBQVEsWUFBNEI7SUFRcEMsWUFBWSxRQUErQztRQUN6RCxRQUFRLENBQUMsSUFBSSxHQUFHLFFBQVEsQ0FBQyxJQUFJLElBQUksU0FBUyxDQUFDO1FBRTNDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUVoQixJQUFJLEVBQ0YsSUFBSSxFQUNKLHVCQUF1QixFQUN2QixtQkFBbUIsRUFDbkIsU0FBUyxFQUNULElBQUksRUFDSixvQkFBb0IsRUFDcEIsbUJBQW1CLEVBQ25CLGFBQWEsRUFDYixrQkFBa0IsRUFDbEIscUJBQXFCLEVBQ3JCLGVBQWUsRUFDZixxQkFBcUIsRUFDckIsZUFBZSxFQUNmLE1BQU0sRUFDUCxHQUFHLFFBQVEsQ0FBQztRQUViLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUU7WUFDN0IsTUFBTSxJQUFJLFNBQVMsQ0FDakIseUZBQXlGLENBQzFGLENBQUM7U0FDSDtRQUVELElBQUksSUFBSSxDQUFDLG9CQUFvQixLQUFLLFNBQVMsRUFBRTtZQUMzQyxJQUFJLENBQUMsb0JBQW9CLEdBQUcsRUFBK0IsQ0FBQztTQUM3RDtRQUNELElBQUksSUFBSSxDQUFDLHdCQUF3QixLQUFLLFNBQVMsRUFBRTtZQUMvQyxJQUFJLENBQUMsd0JBQXdCLEdBQUcsRUFBK0IsQ0FBQztTQUNqRTtRQUVELHFFQUFxRTtRQUNyRSxJQUFJLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxnQkFBZ0IsS0FBSyxTQUFTLEVBQUU7WUFDNUQsSUFBSSxDQUFDLG9CQUFvQixDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztTQUNuRDtRQUVELElBQUksdUJBQXVCLEtBQUssU0FBUyxFQUFFO1lBQ3pDLFNBQVMsQ0FDUCxpSUFBaUksQ0FDbEksQ0FBQztZQUNGLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxXQUFXLEdBQUcsdUJBQXVCLENBQUM7U0FDckU7UUFDRCxJQUFJLG1CQUFtQixLQUFLLFNBQVMsRUFBRTtZQUNyQyxTQUFTLENBQ1AseUhBQXlILENBQzFILENBQUM7WUFDRixJQUFJLENBQUMsb0JBQW9CLENBQUMsV0FBVyxHQUFHLG1CQUFtQixDQUFDO1NBQzdEO1FBRUQscUJBQXFCLEdBQUcscUJBQXFCLElBQUksdUJBQXVCLENBQUM7UUFDekUsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUkscUJBQXFCLENBQUM7WUFDaEQsVUFBVSxFQUFFLElBQUk7WUFDaEIsYUFBYTtZQUNiLGtCQUFrQjtZQUNsQixxQkFBcUI7WUFDckIsZUFBZTtZQUNmLGVBQWUsRUFBRSxlQUFlLElBQUksaUJBQWlCO1lBQ3JELG1CQUFtQjtZQUNuQixvQkFBb0I7WUFDcEIsU0FBUztZQUNULElBQUk7WUFDSixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07WUFDbkIsTUFBTTtTQUNQLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsSUFBSSx1QkFBdUI7O1FBQ3pCLFNBQVMsQ0FDUCxrSUFBa0ksQ0FDbkksQ0FBQztRQUNGLE9BQU8sTUFBQSxJQUFJLENBQUMsd0JBQXdCLDBDQUFFLFdBQVcsQ0FBQztJQUNwRCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILElBQUksdUJBQXVCLENBQUMsR0FBdUI7UUFDakQsU0FBUyxDQUNQLGtJQUFrSSxDQUNuSSxDQUFDO1FBQ0YsSUFBSSxJQUFJLENBQUMsd0JBQXdCLEtBQUssU0FBUyxFQUFFO1lBQy9DLElBQUksQ0FBQyx3QkFBd0IsR0FBRyxFQUErQixDQUFDO1NBQ2pFO1FBQ0QsSUFBSSxDQUFDLHdCQUF3QixDQUFDLFdBQVcsR0FBRyxHQUFHLENBQUM7SUFDbEQsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxJQUFJLG1CQUFtQjs7UUFDckIsU0FBUyxDQUNQLDBIQUEwSCxDQUMzSCxDQUFDO1FBQ0YsT0FBTyxNQUFBLElBQUksQ0FBQyxvQkFBb0IsMENBQUUsV0FBVyxDQUFDO0lBQ2hELENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsSUFBSSxtQkFBbUIsQ0FBQyxHQUF1QjtRQUM3QyxTQUFTLENBQ1AsMEhBQTBILENBQzNILENBQUM7UUFDRixJQUFJLElBQUksQ0FBQyxvQkFBb0IsS0FBSyxTQUFTLEVBQUU7WUFDM0MsSUFBSSxDQUFDLG9CQUFvQixHQUFHLEVBQStCLENBQUM7U0FDN0Q7UUFDRCxJQUFJLENBQUMsb0JBQW9CLENBQUMsV0FBVyxHQUFHLEdBQUcsQ0FBQztJQUM5QyxDQUFDO0lBRUQsNkVBQTZFO0lBQzdFLG9DQUFvQztJQUNwQyw2RUFBNkU7SUFFN0UsS0FBSyxDQUFDLEtBQUssQ0FDVCxTQUEwQjtRQUUxQixJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsRUFBRTtZQUM1QyxPQUFPLEVBQUUsQ0FBQztTQUNYO1FBRUQsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsd0JBQXdCLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDakUsTUFBTSxPQUFPLEdBQXNCLEVBQUUsQ0FBQztRQUN0QyxNQUFNLFVBQVUsR0FBc0IsRUFBRSxDQUFDO1FBRXpDLEtBQUssSUFBSSxRQUFRLElBQUksU0FBUyxFQUFFO1lBQzlCLElBQUksUUFBUSxDQUFDLFVBQVUsRUFBRTtnQkFDdkIsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUM7YUFDN0Q7WUFDRCxJQUFJLFFBQVEsQ0FBQyxPQUFPLEVBQUU7Z0JBQ3BCLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2FBQ2hDO1NBQ0Y7UUFFRCxPQUFPO1lBQ0wsVUFBVSxFQUFFLENBQUMsU0FBUyxFQUFFLEdBQUcsVUFBVSxDQUFDO1lBQ3RDLE9BQU87U0FDUixDQUFDO0lBQ0osQ0FBQztJQUVELDZFQUE2RTtJQUM3RSxvQ0FBb0M7SUFDcEMsNkVBQTZFO0lBRTdFLEtBQUssQ0FBQyxLQUFLLENBQ1QsS0FBa0I7UUFFbEIsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsb0JBQW9CLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekQsTUFBTSxPQUFPLEdBQXNCLEVBQUUsQ0FBQztRQUN0QyxNQUFNLFVBQVUsR0FBc0IsRUFBRSxDQUFDO1FBRXpDLEtBQUssSUFBSSxRQUFRLElBQUksU0FBUyxFQUFFO1lBQzlCLElBQUksUUFBUSxDQUFDLFVBQVUsRUFBRTtnQkFDdkIsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUM7YUFDN0Q7WUFDRCxJQUFJLFFBQVEsQ0FBQyxPQUFPLEVBQUU7Z0JBQ3BCLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2FBQ2hDO1NBQ0Y7UUFFRCxPQUFPO1lBQ0wsVUFBVTtZQUNWLE9BQU87U0FDUixDQUFDO0lBQ0osQ0FBQztJQUVELDZFQUE2RTtJQUM3RSxxQ0FBcUM7SUFDckMsNkVBQTZFO0lBRTdFLEtBQUssQ0FBQyxNQUFNLENBQ1YsS0FBa0I7UUFJbEIsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsb0JBQW9CLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekQsTUFBTSxPQUFPLEdBQXNCLEVBQUUsQ0FBQztRQUN0QyxNQUFNLFVBQVUsR0FBc0IsRUFBRSxDQUFDO1FBQ3pDLE1BQU0sSUFBSSxHQUFrQyxFQUFFLENBQUM7UUFFL0MsS0FBSyxJQUFJLFFBQVEsSUFBSSxTQUFTLEVBQUU7WUFDOUIsSUFBSSxRQUFRLENBQUMsVUFBVSxFQUFFO2dCQUN2QixLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQzthQUM3RDtZQUNELElBQUksUUFBUSxDQUFDLE9BQU8sRUFBRTtnQkFDcEIsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7YUFDaEM7WUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUMxQjtRQUVELE9BQU87WUFDTCxJQUFJLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUN2RCxPQUFPO1lBQ1AsVUFBVTtTQUNYLENBQUM7SUFDSixDQUFDO0lBRUQsNkVBQTZFO0lBQzdFLHFDQUFxQztJQUNyQyw2RUFBNkU7SUFFN0UsS0FBSyxDQUFDLE9BQU8sQ0FDWCxTQUEwQjtRQUkxQixJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsRUFBRTtZQUM1QyxPQUFPLEVBQUUsQ0FBQztTQUNYO1FBRUQsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsd0JBQXdCLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDakUsTUFBTSxPQUFPLEdBQXNCLEVBQUUsQ0FBQztRQUN0QyxNQUFNLFVBQVUsR0FBc0IsRUFBRSxDQUFDO1FBQ3pDLE1BQU0sSUFBSSxHQUE0QixFQUFFLENBQUM7UUFFekMsS0FBSyxJQUFJLFFBQVEsSUFBSSxTQUFTLEVBQUU7WUFDOUIsSUFBSSxRQUFRLENBQUMsVUFBVSxFQUFFO2dCQUN2QixLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQzthQUM3RDtZQUNELElBQUksUUFBUSxDQUFDLE9BQU8sRUFBRTtnQkFDcEIsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7YUFDaEM7WUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUMxQjtRQUVELE9BQU87WUFDTCxJQUFJLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUMxRCxPQUFPO1lBQ1AsVUFBVSxFQUFFLENBQUMsU0FBUyxFQUFFLEdBQUcsVUFBVSxDQUFDO1NBQ3ZDLENBQUM7SUFDSixDQUFDO0lBRVMsd0JBQXdCLENBQ2hDLE9BQTJCO1FBRTNCLE9BQU8sc0JBQXNCLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFUyw0QkFBNEIsQ0FDcEMsT0FBK0I7UUFFL0IsT0FBTywwQkFBMEIsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUVTLEtBQUssQ0FBQyxvQkFBb0IsQ0FDbEMsS0FBa0I7UUFFbEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM1QyxNQUFNLFFBQVEsR0FBRyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDaEUsSUFDRSxDQUFBLE9BQU8sYUFBUCxPQUFPLHVCQUFQLE9BQU8sQ0FBRSxXQUFXLE1BQUssU0FBUztZQUNsQyxRQUFRLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxXQUFXLEVBQ3JDO1lBQ0EsTUFBTSxJQUFJLGVBQWUsQ0FDdkIsdUJBQXVCLFFBQVEsQ0FBQyxNQUFNLG1EQUFtRCxPQUFPLENBQUMsV0FBVyxzQkFBc0IsRUFDbEksS0FBSyxDQUNOLENBQUM7U0FDSDtRQUVELElBQUksT0FBTyxhQUFQLE9BQU8sdUJBQVAsT0FBTyxDQUFFLGdCQUFnQixFQUFFO1lBQzdCLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FDaEIsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO2dCQUN2QixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsd0JBQXdCLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ3pELE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUNuRCxDQUFDLENBQUMsQ0FDSCxDQUFDO1NBQ0g7YUFBTTtZQUNMLE1BQU0sU0FBUyxHQUFHLEVBQUUsQ0FBQztZQUNyQixLQUFLLElBQUksT0FBTyxJQUFJLFFBQVEsRUFBRTtnQkFDNUIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLHdCQUF3QixDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUN6RCxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sU0FBUyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO2FBQ2pFO1lBQ0QsT0FBTyxTQUFTLENBQUM7U0FDbEI7SUFDSCxDQUFDO0lBRVMsS0FBSyxDQUFDLHdCQUF3QixDQUN0QyxTQUEwQjtRQUUxQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDcEQsTUFBTSxRQUFRLEdBQUcsb0JBQW9CLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ3hFLElBQ0UsQ0FBQSxPQUFPLGFBQVAsT0FBTyx1QkFBUCxPQUFPLENBQUUsV0FBVyxNQUFLLFNBQVM7WUFDbEMsUUFBUSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsV0FBVyxFQUNyQztZQUNBLE1BQU0sSUFBSSxtQkFBbUIsQ0FDM0IsMkJBQTJCLFFBQVEsQ0FBQyxNQUFNLG1EQUFtRCxPQUFPLENBQUMsV0FBVywwQkFBMEIsRUFDMUksU0FBUyxDQUNWLENBQUM7U0FDSDtRQUVELElBQUksT0FBTyxhQUFQLE9BQU8sdUJBQVAsT0FBTyxDQUFFLGdCQUFnQixFQUFFO1lBQzdCLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FDaEIsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO2dCQUN2QixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsNEJBQTRCLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQzdELE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUNuRCxDQUFDLENBQUMsQ0FDSCxDQUFDO1NBQ0g7YUFBTTtZQUNMLE1BQU0sU0FBUyxHQUFHLEVBQUUsQ0FBQztZQUNyQixLQUFLLElBQUksT0FBTyxJQUFJLFFBQVEsRUFBRTtnQkFDNUIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLDRCQUE0QixDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUM3RCxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sU0FBUyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO2FBQ2pFO1lBQ0QsT0FBTyxTQUFTLENBQUM7U0FDbEI7SUFDSCxDQUFDO0NBQ0YsQ0FBQTtBQS9VWSxhQUFhO0lBSnpCLFFBQVE7SUFDUixRQUFRO0lBQ1IsU0FBUztJQUNULFNBQVM7R0FDRyxhQUFhLENBK1V6QjtTQS9VWSxhQUFhIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgT3JiaXQsIEFzc2VydGlvbiB9IGZyb20gJ0BvcmJpdC9jb3JlJztcbmltcG9ydCB7XG4gIFJlcXVlc3RPcHRpb25zLFxuICBwdWxsYWJsZSxcbiAgcHVzaGFibGUsXG4gIHF1ZXJ5YWJsZSxcbiAgdXBkYXRhYmxlLFxuICBUcmFuc2Zvcm1Ob3RBbGxvd2VkLFxuICBRdWVyeU5vdEFsbG93ZWQsXG4gIEZ1bGxSZXNwb25zZSxcbiAgRGVmYXVsdFJlcXVlc3RPcHRpb25zXG59IGZyb20gJ0BvcmJpdC9kYXRhJztcbmltcG9ydCB7XG4gIFJlY29yZFNvdXJjZSxcbiAgUmVjb3JkU291cmNlU2V0dGluZ3MsXG4gIFJlY29yZFB1bGxhYmxlLFxuICBSZWNvcmRQdXNoYWJsZSxcbiAgUmVjb3JkUXVlcnlhYmxlLFxuICBSZWNvcmRVcGRhdGFibGUsXG4gIFJlY29yZE9wZXJhdGlvbixcbiAgUmVjb3JkVHJhbnNmb3JtLFxuICBSZWNvcmRRdWVyeSxcbiAgUmVjb3JkUXVlcnlFeHByZXNzaW9uUmVzdWx0LFxuICBSZWNvcmRPcGVyYXRpb25SZXN1bHQsXG4gIFJlY29yZFF1ZXJ5UmVzdWx0LFxuICBSZWNvcmRUcmFuc2Zvcm1SZXN1bHQsXG4gIFJlY29yZFNvdXJjZVF1ZXJ5T3B0aW9ucyxcbiAgUmVjb3JkUXVlcnlCdWlsZGVyLFxuICBSZWNvcmRUcmFuc2Zvcm1CdWlsZGVyXG59IGZyb20gJ0BvcmJpdC9yZWNvcmRzJztcbmltcG9ydCB7XG4gIEpTT05BUElSZXF1ZXN0UHJvY2Vzc29yLFxuICBKU09OQVBJUmVxdWVzdFByb2Nlc3NvclNldHRpbmdzLFxuICBGZXRjaFNldHRpbmdzXG59IGZyb20gJy4vanNvbmFwaS1yZXF1ZXN0LXByb2Nlc3Nvcic7XG5pbXBvcnQge1xuICBKU09OQVBJU2VyaWFsaXplcixcbiAgSlNPTkFQSVNlcmlhbGl6ZXJTZXR0aW5nc1xufSBmcm9tICcuL2pzb25hcGktc2VyaWFsaXplcic7XG5pbXBvcnQge1xuICBKU09OQVBJVVJMQnVpbGRlcixcbiAgSlNPTkFQSVVSTEJ1aWxkZXJTZXR0aW5nc1xufSBmcm9tICcuL2pzb25hcGktdXJsLWJ1aWxkZXInO1xuaW1wb3J0IHtcbiAgUXVlcnlSZXF1ZXN0UHJvY2Vzc29yLFxuICBRdWVyeVJlcXVlc3RQcm9jZXNzb3JzLFxuICBSZWNvcmRRdWVyeVJlcXVlc3QsXG4gIGdldFF1ZXJ5UmVxdWVzdHMsXG4gIFF1ZXJ5UmVxdWVzdFByb2Nlc3NvclJlc3BvbnNlXG59IGZyb20gJy4vbGliL3F1ZXJ5LXJlcXVlc3RzJztcbmltcG9ydCB7XG4gIFRyYW5zZm9ybVJlcXVlc3RQcm9jZXNzb3IsXG4gIFRyYW5zZm9ybVJlcXVlc3RQcm9jZXNzb3JzLFxuICBSZWNvcmRUcmFuc2Zvcm1SZXF1ZXN0LFxuICBnZXRUcmFuc2Zvcm1SZXF1ZXN0cyxcbiAgVHJhbnNmb3JtUmVxdWVzdFByb2Nlc3NvclJlc3BvbnNlXG59IGZyb20gJy4vbGliL3RyYW5zZm9ybS1yZXF1ZXN0cyc7XG5pbXBvcnQge1xuICBTZXJpYWxpemVyQ2xhc3NGb3JGbixcbiAgU2VyaWFsaXplclNldHRpbmdzRm9yRm4sXG4gIFNlcmlhbGl6ZXJGb3JGblxufSBmcm9tICdAb3JiaXQvc2VyaWFsaXplcnMnO1xuaW1wb3J0IHsgSlNPTkFQSVJlc3BvbnNlIH0gZnJvbSAnLi9qc29uYXBpLXJlc3BvbnNlJztcblxuY29uc3QgeyBkZXByZWNhdGUgfSA9IE9yYml0O1xuXG5pbnRlcmZhY2UgSlNPTkFQSVNoYXJlZFJlcXVlc3RPcHRpb25zIHtcbiAgbWF4UmVxdWVzdHM/OiBudW1iZXI7XG4gIHBhcmFsbGVsUmVxdWVzdHM/OiBib29sZWFuO1xufVxuZXhwb3J0IGludGVyZmFjZSBKU09OQVBJUXVlcnlPcHRpb25zXG4gIGV4dGVuZHMgUmVjb3JkU291cmNlUXVlcnlPcHRpb25zLFxuICAgIEpTT05BUElTaGFyZWRSZXF1ZXN0T3B0aW9ucyB7fVxuXG5leHBvcnQgaW50ZXJmYWNlIEpTT05BUElUcmFuc2Zvcm1PcHRpb25zXG4gIGV4dGVuZHMgUmVxdWVzdE9wdGlvbnMsXG4gICAgSlNPTkFQSVNoYXJlZFJlcXVlc3RPcHRpb25zIHt9XG5cbmV4cG9ydCBpbnRlcmZhY2UgSlNPTkFQSVNvdXJjZVNldHRpbmdzPFxuICBRTyBleHRlbmRzIEpTT05BUElRdWVyeU9wdGlvbnMgPSBKU09OQVBJUXVlcnlPcHRpb25zLFxuICBUTyBleHRlbmRzIEpTT05BUElUcmFuc2Zvcm1PcHRpb25zID0gSlNPTkFQSVRyYW5zZm9ybU9wdGlvbnMsXG4gIFFCID0gUmVjb3JkUXVlcnlCdWlsZGVyLFxuICBUQiA9IFJlY29yZFRyYW5zZm9ybUJ1aWxkZXJcbj4gZXh0ZW5kcyBSZWNvcmRTb3VyY2VTZXR0aW5nczxRTywgVE8sIFFCLCBUQj4ge1xuICAvKipcbiAgICogRGVwcmVjYXRlZCBpbiBmYXZvciBvZiBgZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnMubWF4UmVxdWVzdHNgXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIHNpbmNlIHYwLjE3LCByZW1vdmUgaW4gdjAuMThcbiAgICovXG4gIG1heFJlcXVlc3RzUGVyVHJhbnNmb3JtPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBEZXByZWNhdGVkIGluIGZhdm9yIG9mIGBkZWZhdWx0UXVlcnlPcHRpb25zLm1heFJlcXVlc3RzYFxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBzaW5jZSB2MC4xNywgcmVtb3ZlIGluIHYwLjE4XG4gICAqL1xuICBtYXhSZXF1ZXN0c1BlclF1ZXJ5PzogbnVtYmVyO1xuXG4gIG5hbWU/OiBzdHJpbmc7XG4gIG5hbWVzcGFjZT86IHN0cmluZztcbiAgaG9zdD86IHN0cmluZztcbiAgZGVmYXVsdEZldGNoU2V0dGluZ3M/OiBGZXRjaFNldHRpbmdzO1xuICBhbGxvd2VkQ29udGVudFR5cGVzPzogc3RyaW5nW107XG4gIHNlcmlhbGl6ZXJGb3I/OiBTZXJpYWxpemVyRm9yRm47XG4gIHNlcmlhbGl6ZXJDbGFzc0Zvcj86IFNlcmlhbGl6ZXJDbGFzc0ZvckZuO1xuICBzZXJpYWxpemVyU2V0dGluZ3NGb3I/OiBTZXJpYWxpemVyU2V0dGluZ3NGb3JGbjtcbiAgU2VyaWFsaXplckNsYXNzPzogbmV3IChcbiAgICBzZXR0aW5nczogSlNPTkFQSVNlcmlhbGl6ZXJTZXR0aW5nc1xuICApID0+IEpTT05BUElTZXJpYWxpemVyO1xuICBSZXF1ZXN0UHJvY2Vzc29yQ2xhc3M/OiBuZXcgKFxuICAgIHNldHRpbmdzOiBKU09OQVBJUmVxdWVzdFByb2Nlc3NvclNldHRpbmdzXG4gICkgPT4gSlNPTkFQSVJlcXVlc3RQcm9jZXNzb3I7XG4gIFVSTEJ1aWxkZXJDbGFzcz86IG5ldyAoXG4gICAgc2V0dGluZ3M6IEpTT05BUElVUkxCdWlsZGVyU2V0dGluZ3NcbiAgKSA9PiBKU09OQVBJVVJMQnVpbGRlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBKU09OQVBJU291cmNlPFxuICBRTyBleHRlbmRzIEpTT05BUElRdWVyeU9wdGlvbnMgPSBKU09OQVBJUXVlcnlPcHRpb25zLFxuICBUTyBleHRlbmRzIEpTT05BUElUcmFuc2Zvcm1PcHRpb25zID0gSlNPTkFQSVRyYW5zZm9ybU9wdGlvbnMsXG4gIFFCID0gUmVjb3JkUXVlcnlCdWlsZGVyLFxuICBUQiA9IFJlY29yZFRyYW5zZm9ybUJ1aWxkZXJcbj4gZXh0ZW5kcyBSZWNvcmRTb3VyY2U8UU8sIFRPLCBRQiwgVEI+LFxuICAgIFJlY29yZFB1bGxhYmxlPEpTT05BUElSZXNwb25zZVtdPixcbiAgICBSZWNvcmRQdXNoYWJsZTxKU09OQVBJUmVzcG9uc2VbXT4sXG4gICAgUmVjb3JkUXVlcnlhYmxlPEpTT05BUElSZXNwb25zZVtdLCBRQiwgUU8+LFxuICAgIFJlY29yZFVwZGF0YWJsZTxKU09OQVBJUmVzcG9uc2VbXSwgVEIsIFRPPiB7fVxuXG4vKipcbiBTb3VyY2UgZm9yIGFjY2Vzc2luZyBhIEpTT04gQVBJIGNvbXBsaWFudCBSRVNUZnVsIEFQSSB3aXRoIGEgbmV0d29yayBmZXRjaFxuIHJlcXVlc3QuXG5cbiBJZiBhIHNpbmdsZSB0cmFuc2Zvcm0gb3IgcXVlcnkgcmVxdWlyZXMgbW9yZSB0aGFuIG9uZSBmZXRjaCByZXF1ZXN0LFxuIHJlcXVlc3RzIHdpbGwgYmUgcGVyZm9ybWVkIHNlcXVlbnRpYWxseSBhbmQgcmVzb2x2ZWQgdG9nZXRoZXIuIEZyb20gdGhlXG4gcGVyc3BlY3RpdmUgb2YgT3JiaXQsIHRoZXNlIG9wZXJhdGlvbnMgd2lsbCBhbGwgc3VjY2VlZCBvciBmYWlsIHRvZ2V0aGVyLiBUaGVcbiBgbWF4UmVxdWVzdHNQZXJUcmFuc2Zvcm1gIGFuZCBgbWF4UmVxdWVzdHNQZXJRdWVyeWAgc2V0dGluZ3MgYWxsb3cgbGltaXRzIHRvIGJlXG4gc2V0IG9uIHRoaXMgYmVoYXZpb3IuIFRoZXNlIHNldHRpbmdzIHNob3VsZCBiZSBzZXQgdG8gYDFgIGlmIHlvdXIgY2xpZW50L3NlcnZlclxuIGNvbmZpZ3VyYXRpb24gaXMgdW5hYmxlIHRvIHJlc29sdmUgcGFydGlhbGx5IHN1Y2Nlc3NmdWwgdHJhbnNmb3JtcyAvIHF1ZXJpZXMuXG5cbiBAY2xhc3MgSlNPTkFQSVNvdXJjZVxuIEBleHRlbmRzIFNvdXJjZVxuICovXG5AcHVsbGFibGVcbkBwdXNoYWJsZVxuQHF1ZXJ5YWJsZVxuQHVwZGF0YWJsZVxuZXhwb3J0IGNsYXNzIEpTT05BUElTb3VyY2U8XG4gICAgUU8gZXh0ZW5kcyBKU09OQVBJUXVlcnlPcHRpb25zID0gSlNPTkFQSVF1ZXJ5T3B0aW9ucyxcbiAgICBUTyBleHRlbmRzIEpTT05BUElUcmFuc2Zvcm1PcHRpb25zID0gSlNPTkFQSVRyYW5zZm9ybU9wdGlvbnMsXG4gICAgUUIgPSBSZWNvcmRRdWVyeUJ1aWxkZXIsXG4gICAgVEIgPSBSZWNvcmRUcmFuc2Zvcm1CdWlsZGVyXG4gID5cbiAgZXh0ZW5kcyBSZWNvcmRTb3VyY2U8UU8sIFRPLCBRQiwgVEI+XG4gIGltcGxlbWVudHNcbiAgICBSZWNvcmRQdWxsYWJsZTxKU09OQVBJUmVzcG9uc2VbXT4sXG4gICAgUmVjb3JkUHVzaGFibGU8SlNPTkFQSVJlc3BvbnNlW10+LFxuICAgIFJlY29yZFF1ZXJ5YWJsZTxKU09OQVBJUmVzcG9uc2VbXSwgUUIsIFFPPixcbiAgICBSZWNvcmRVcGRhdGFibGU8SlNPTkFQSVJlc3BvbnNlW10sIFRCLCBUTz4ge1xuICByZXF1ZXN0UHJvY2Vzc29yOiBKU09OQVBJUmVxdWVzdFByb2Nlc3NvcjtcblxuICBjb25zdHJ1Y3RvcihzZXR0aW5nczogSlNPTkFQSVNvdXJjZVNldHRpbmdzPFFPLCBUTywgUUIsIFRCPikge1xuICAgIHNldHRpbmdzLm5hbWUgPSBzZXR0aW5ncy5uYW1lIHx8ICdqc29uYXBpJztcblxuICAgIHN1cGVyKHNldHRpbmdzKTtcblxuICAgIGxldCB7XG4gICAgICBuYW1lLFxuICAgICAgbWF4UmVxdWVzdHNQZXJUcmFuc2Zvcm0sXG4gICAgICBtYXhSZXF1ZXN0c1BlclF1ZXJ5LFxuICAgICAgbmFtZXNwYWNlLFxuICAgICAgaG9zdCxcbiAgICAgIGRlZmF1bHRGZXRjaFNldHRpbmdzLFxuICAgICAgYWxsb3dlZENvbnRlbnRUeXBlcyxcbiAgICAgIHNlcmlhbGl6ZXJGb3IsXG4gICAgICBzZXJpYWxpemVyQ2xhc3NGb3IsXG4gICAgICBzZXJpYWxpemVyU2V0dGluZ3NGb3IsXG4gICAgICBTZXJpYWxpemVyQ2xhc3MsXG4gICAgICBSZXF1ZXN0UHJvY2Vzc29yQ2xhc3MsXG4gICAgICBVUkxCdWlsZGVyQ2xhc3MsXG4gICAgICBrZXlNYXBcbiAgICB9ID0gc2V0dGluZ3M7XG5cbiAgICBpZiAodGhpcy5zY2hlbWEgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEFzc2VydGlvbihcbiAgICAgICAgXCJKU09OQVBJU291cmNlJ3MgYHNjaGVtYWAgbXVzdCBiZSBzcGVjaWZpZWQgaW4gdGhlICBgc2V0dGluZ3NgIHBhc3NlZCB0byBpdHMgY29uc3RydWN0b3JcIlxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fZGVmYXVsdFF1ZXJ5T3B0aW9ucyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLl9kZWZhdWx0UXVlcnlPcHRpb25zID0ge30gYXMgRGVmYXVsdFJlcXVlc3RPcHRpb25zPFFPPjtcbiAgICB9XG4gICAgaWYgKHRoaXMuX2RlZmF1bHRUcmFuc2Zvcm1PcHRpb25zID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuX2RlZmF1bHRUcmFuc2Zvcm1PcHRpb25zID0ge30gYXMgRGVmYXVsdFJlcXVlc3RPcHRpb25zPFRPPjtcbiAgICB9XG5cbiAgICAvLyBQYXJhbGxlbGl6ZSBxdWVyeSByZXF1ZXN0cyBieSBkZWZhdWx0IChidXQgbm90IHRyYW5zZm9ybSByZXF1ZXN0cylcbiAgICBpZiAodGhpcy5fZGVmYXVsdFF1ZXJ5T3B0aW9ucy5wYXJhbGxlbFJlcXVlc3RzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuX2RlZmF1bHRRdWVyeU9wdGlvbnMucGFyYWxsZWxSZXF1ZXN0cyA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKG1heFJlcXVlc3RzUGVyVHJhbnNmb3JtICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGRlcHJlY2F0ZShcbiAgICAgICAgXCJUaGUgJ21heFJlcXVlc3RzUGVyVHJhbnNmb3JtJyBzZXR0aW5nIGZvciAnSlNPTkFQU291cmNlJyBoYXMgYmVlbiBkZXByZWNhdGVkIGluIGZhdm9yIG9mICdkZWZhdWx0VHJhbnNmb3JtT3B0aW9ucy5tYXhSZXF1ZXN0cycuXCJcbiAgICAgICk7XG4gICAgICB0aGlzLl9kZWZhdWx0VHJhbnNmb3JtT3B0aW9ucy5tYXhSZXF1ZXN0cyA9IG1heFJlcXVlc3RzUGVyVHJhbnNmb3JtO1xuICAgIH1cbiAgICBpZiAobWF4UmVxdWVzdHNQZXJRdWVyeSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBkZXByZWNhdGUoXG4gICAgICAgIFwiVGhlICdtYXhSZXF1ZXN0c1BlclF1ZXJ5JyBzZXR0aW5nIGZvciAnSlNPTkFQU291cmNlJyBoYXMgYmVlbiBkZXByZWNhdGVkIGluIGZhdm9yIG9mICdkZWZhdWx0UXVlcnlPcHRpb25zLm1heFJlcXVlc3RzJy5cIlxuICAgICAgKTtcbiAgICAgIHRoaXMuX2RlZmF1bHRRdWVyeU9wdGlvbnMubWF4UmVxdWVzdHMgPSBtYXhSZXF1ZXN0c1BlclF1ZXJ5O1xuICAgIH1cblxuICAgIFJlcXVlc3RQcm9jZXNzb3JDbGFzcyA9IFJlcXVlc3RQcm9jZXNzb3JDbGFzcyB8fCBKU09OQVBJUmVxdWVzdFByb2Nlc3NvcjtcbiAgICB0aGlzLnJlcXVlc3RQcm9jZXNzb3IgPSBuZXcgUmVxdWVzdFByb2Nlc3NvckNsYXNzKHtcbiAgICAgIHNvdXJjZU5hbWU6IG5hbWUsXG4gICAgICBzZXJpYWxpemVyRm9yLFxuICAgICAgc2VyaWFsaXplckNsYXNzRm9yLFxuICAgICAgc2VyaWFsaXplclNldHRpbmdzRm9yLFxuICAgICAgU2VyaWFsaXplckNsYXNzLFxuICAgICAgVVJMQnVpbGRlckNsYXNzOiBVUkxCdWlsZGVyQ2xhc3MgfHwgSlNPTkFQSVVSTEJ1aWxkZXIsXG4gICAgICBhbGxvd2VkQ29udGVudFR5cGVzLFxuICAgICAgZGVmYXVsdEZldGNoU2V0dGluZ3MsXG4gICAgICBuYW1lc3BhY2UsXG4gICAgICBob3N0LFxuICAgICAgc2NoZW1hOiB0aGlzLnNjaGVtYSxcbiAgICAgIGtleU1hcFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIERlcHJlY2F0ZWQgaW4gZmF2b3Igb2YgYGRlZmF1bHRUcmFuc2Zvcm1PcHRpb25zLm1heFJlcXVlc3RzYFxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBzaW5jZSB2MC4xNywgcmVtb3ZlIGluIHYwLjE4XG4gICAqL1xuICBnZXQgbWF4UmVxdWVzdHNQZXJUcmFuc2Zvcm0oKTogbnVtYmVyIHwgdW5kZWZpbmVkIHtcbiAgICBkZXByZWNhdGUoXG4gICAgICBcIlRoZSAnbWF4UmVxdWVzdHNQZXJUcmFuc2Zvcm0nIHByb3BlcnR5IGZvciAnSlNPTkFQU291cmNlJyBoYXMgYmVlbiBkZXByZWNhdGVkIGluIGZhdm9yIG9mICdkZWZhdWx0VHJhbnNmb3JtT3B0aW9ucy5tYXhSZXF1ZXN0cycuXCJcbiAgICApO1xuICAgIHJldHVybiB0aGlzLl9kZWZhdWx0VHJhbnNmb3JtT3B0aW9ucz8ubWF4UmVxdWVzdHM7XG4gIH1cblxuICAvKipcbiAgICogRGVwcmVjYXRlZCBpbiBmYXZvciBvZiBgZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnMubWF4UmVxdWVzdHNgXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIHNpbmNlIHYwLjE3LCByZW1vdmUgaW4gdjAuMThcbiAgICovXG4gIHNldCBtYXhSZXF1ZXN0c1BlclRyYW5zZm9ybSh2YWw6IG51bWJlciB8IHVuZGVmaW5lZCkge1xuICAgIGRlcHJlY2F0ZShcbiAgICAgIFwiVGhlICdtYXhSZXF1ZXN0c1BlclRyYW5zZm9ybScgcHJvcGVydHkgZm9yICdKU09OQVBTb3VyY2UnIGhhcyBiZWVuIGRlcHJlY2F0ZWQgaW4gZmF2b3Igb2YgJ2RlZmF1bHRUcmFuc2Zvcm1PcHRpb25zLm1heFJlcXVlc3RzJy5cIlxuICAgICk7XG4gICAgaWYgKHRoaXMuX2RlZmF1bHRUcmFuc2Zvcm1PcHRpb25zID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuX2RlZmF1bHRUcmFuc2Zvcm1PcHRpb25zID0ge30gYXMgRGVmYXVsdFJlcXVlc3RPcHRpb25zPFRPPjtcbiAgICB9XG4gICAgdGhpcy5fZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnMubWF4UmVxdWVzdHMgPSB2YWw7XG4gIH1cblxuICAvKipcbiAgICogRGVwcmVjYXRlZCBpbiBmYXZvciBvZiBgZGVmYXVsdFF1ZXJ5T3B0aW9ucy5tYXhSZXF1ZXN0c2BcbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgc2luY2UgdjAuMTcsIHJlbW92ZSBpbiB2MC4xOFxuICAgKi9cbiAgZ2V0IG1heFJlcXVlc3RzUGVyUXVlcnkoKTogbnVtYmVyIHwgdW5kZWZpbmVkIHtcbiAgICBkZXByZWNhdGUoXG4gICAgICBcIlRoZSAnbWF4UmVxdWVzdHNQZXJRdWVyeScgcHJvcGVydHkgZm9yICdKU09OQVBTb3VyY2UnIGhhcyBiZWVuIGRlcHJlY2F0ZWQgaW4gZmF2b3Igb2YgJ2RlZmF1bHRRdWVyeU9wdGlvbnMubWF4UmVxdWVzdHMnLlwiXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5fZGVmYXVsdFF1ZXJ5T3B0aW9ucz8ubWF4UmVxdWVzdHM7XG4gIH1cblxuICAvKipcbiAgICogRGVwcmVjYXRlZCBpbiBmYXZvciBvZiBgZGVmYXVsdFF1ZXJ5T3B0aW9ucy5tYXhSZXF1ZXN0c2BcbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgc2luY2UgdjAuMTcsIHJlbW92ZSBpbiB2MC4xOFxuICAgKi9cbiAgc2V0IG1heFJlcXVlc3RzUGVyUXVlcnkodmFsOiBudW1iZXIgfCB1bmRlZmluZWQpIHtcbiAgICBkZXByZWNhdGUoXG4gICAgICBcIlRoZSAnbWF4UmVxdWVzdHNQZXJRdWVyeScgcHJvcGVydHkgZm9yICdKU09OQVBTb3VyY2UnIGhhcyBiZWVuIGRlcHJlY2F0ZWQgaW4gZmF2b3Igb2YgJ2RlZmF1bHRRdWVyeU9wdGlvbnMubWF4UmVxdWVzdHMnLlwiXG4gICAgKTtcbiAgICBpZiAodGhpcy5fZGVmYXVsdFF1ZXJ5T3B0aW9ucyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLl9kZWZhdWx0UXVlcnlPcHRpb25zID0ge30gYXMgRGVmYXVsdFJlcXVlc3RPcHRpb25zPFFPPjtcbiAgICB9XG4gICAgdGhpcy5fZGVmYXVsdFF1ZXJ5T3B0aW9ucy5tYXhSZXF1ZXN0cyA9IHZhbDtcbiAgfVxuXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gIC8vIFB1c2hhYmxlIGludGVyZmFjZSBpbXBsZW1lbnRhdGlvblxuICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gIGFzeW5jIF9wdXNoKFxuICAgIHRyYW5zZm9ybTogUmVjb3JkVHJhbnNmb3JtXG4gICk6IFByb21pc2U8RnVsbFJlc3BvbnNlPHVuZGVmaW5lZCwgSlNPTkFQSVJlc3BvbnNlW10sIFJlY29yZE9wZXJhdGlvbj4+IHtcbiAgICBpZiAodGhpcy50cmFuc2Zvcm1Mb2cuY29udGFpbnModHJhbnNmb3JtLmlkKSkge1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH1cblxuICAgIGNvbnN0IHJlc3BvbnNlcyA9IGF3YWl0IHRoaXMucHJvY2Vzc1RyYW5zZm9ybVJlcXVlc3RzKHRyYW5zZm9ybSk7XG4gICAgY29uc3QgZGV0YWlsczogSlNPTkFQSVJlc3BvbnNlW10gPSBbXTtcbiAgICBjb25zdCB0cmFuc2Zvcm1zOiBSZWNvcmRUcmFuc2Zvcm1bXSA9IFtdO1xuXG4gICAgZm9yIChsZXQgcmVzcG9uc2Ugb2YgcmVzcG9uc2VzKSB7XG4gICAgICBpZiAocmVzcG9uc2UudHJhbnNmb3Jtcykge1xuICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseSh0cmFuc2Zvcm1zLCByZXNwb25zZS50cmFuc2Zvcm1zKTtcbiAgICAgIH1cbiAgICAgIGlmIChyZXNwb25zZS5kZXRhaWxzKSB7XG4gICAgICAgIGRldGFpbHMucHVzaChyZXNwb25zZS5kZXRhaWxzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdHJhbnNmb3JtczogW3RyYW5zZm9ybSwgLi4udHJhbnNmb3Jtc10sXG4gICAgICBkZXRhaWxzXG4gICAgfTtcbiAgfVxuXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gIC8vIFB1bGxhYmxlIGludGVyZmFjZSBpbXBsZW1lbnRhdGlvblxuICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gIGFzeW5jIF9wdWxsKFxuICAgIHF1ZXJ5OiBSZWNvcmRRdWVyeVxuICApOiBQcm9taXNlPEZ1bGxSZXNwb25zZTx1bmRlZmluZWQsIEpTT05BUElSZXNwb25zZVtdLCBSZWNvcmRPcGVyYXRpb24+PiB7XG4gICAgY29uc3QgcmVzcG9uc2VzID0gYXdhaXQgdGhpcy5wcm9jZXNzUXVlcnlSZXF1ZXN0cyhxdWVyeSk7XG4gICAgY29uc3QgZGV0YWlsczogSlNPTkFQSVJlc3BvbnNlW10gPSBbXTtcbiAgICBjb25zdCB0cmFuc2Zvcm1zOiBSZWNvcmRUcmFuc2Zvcm1bXSA9IFtdO1xuXG4gICAgZm9yIChsZXQgcmVzcG9uc2Ugb2YgcmVzcG9uc2VzKSB7XG4gICAgICBpZiAocmVzcG9uc2UudHJhbnNmb3Jtcykge1xuICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseSh0cmFuc2Zvcm1zLCByZXNwb25zZS50cmFuc2Zvcm1zKTtcbiAgICAgIH1cbiAgICAgIGlmIChyZXNwb25zZS5kZXRhaWxzKSB7XG4gICAgICAgIGRldGFpbHMucHVzaChyZXNwb25zZS5kZXRhaWxzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdHJhbnNmb3JtcyxcbiAgICAgIGRldGFpbHNcbiAgICB9O1xuICB9XG5cbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgLy8gUXVlcnlhYmxlIGludGVyZmFjZSBpbXBsZW1lbnRhdGlvblxuICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gIGFzeW5jIF9xdWVyeShcbiAgICBxdWVyeTogUmVjb3JkUXVlcnlcbiAgKTogUHJvbWlzZTxcbiAgICBGdWxsUmVzcG9uc2U8UmVjb3JkUXVlcnlSZXN1bHQsIEpTT05BUElSZXNwb25zZVtdLCBSZWNvcmRPcGVyYXRpb24+XG4gID4ge1xuICAgIGNvbnN0IHJlc3BvbnNlcyA9IGF3YWl0IHRoaXMucHJvY2Vzc1F1ZXJ5UmVxdWVzdHMocXVlcnkpO1xuICAgIGNvbnN0IGRldGFpbHM6IEpTT05BUElSZXNwb25zZVtdID0gW107XG4gICAgY29uc3QgdHJhbnNmb3JtczogUmVjb3JkVHJhbnNmb3JtW10gPSBbXTtcbiAgICBjb25zdCBkYXRhOiBSZWNvcmRRdWVyeUV4cHJlc3Npb25SZXN1bHRbXSA9IFtdO1xuXG4gICAgZm9yIChsZXQgcmVzcG9uc2Ugb2YgcmVzcG9uc2VzKSB7XG4gICAgICBpZiAocmVzcG9uc2UudHJhbnNmb3Jtcykge1xuICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseSh0cmFuc2Zvcm1zLCByZXNwb25zZS50cmFuc2Zvcm1zKTtcbiAgICAgIH1cbiAgICAgIGlmIChyZXNwb25zZS5kZXRhaWxzKSB7XG4gICAgICAgIGRldGFpbHMucHVzaChyZXNwb25zZS5kZXRhaWxzKTtcbiAgICAgIH1cbiAgICAgIGRhdGEucHVzaChyZXNwb25zZS5kYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0YTogQXJyYXkuaXNBcnJheShxdWVyeS5leHByZXNzaW9ucykgPyBkYXRhIDogZGF0YVswXSxcbiAgICAgIGRldGFpbHMsXG4gICAgICB0cmFuc2Zvcm1zXG4gICAgfTtcbiAgfVxuXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gIC8vIFVwZGF0YWJsZSBpbnRlcmZhY2UgaW1wbGVtZW50YXRpb25cbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICBhc3luYyBfdXBkYXRlKFxuICAgIHRyYW5zZm9ybTogUmVjb3JkVHJhbnNmb3JtXG4gICk6IFByb21pc2U8XG4gICAgRnVsbFJlc3BvbnNlPFJlY29yZFRyYW5zZm9ybVJlc3VsdCwgSlNPTkFQSVJlc3BvbnNlW10sIFJlY29yZE9wZXJhdGlvbj5cbiAgPiB7XG4gICAgaWYgKHRoaXMudHJhbnNmb3JtTG9nLmNvbnRhaW5zKHRyYW5zZm9ybS5pZCkpIHtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG5cbiAgICBjb25zdCByZXNwb25zZXMgPSBhd2FpdCB0aGlzLnByb2Nlc3NUcmFuc2Zvcm1SZXF1ZXN0cyh0cmFuc2Zvcm0pO1xuICAgIGNvbnN0IGRldGFpbHM6IEpTT05BUElSZXNwb25zZVtdID0gW107XG4gICAgY29uc3QgdHJhbnNmb3JtczogUmVjb3JkVHJhbnNmb3JtW10gPSBbXTtcbiAgICBjb25zdCBkYXRhOiBSZWNvcmRPcGVyYXRpb25SZXN1bHRbXSA9IFtdO1xuXG4gICAgZm9yIChsZXQgcmVzcG9uc2Ugb2YgcmVzcG9uc2VzKSB7XG4gICAgICBpZiAocmVzcG9uc2UudHJhbnNmb3Jtcykge1xuICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseSh0cmFuc2Zvcm1zLCByZXNwb25zZS50cmFuc2Zvcm1zKTtcbiAgICAgIH1cbiAgICAgIGlmIChyZXNwb25zZS5kZXRhaWxzKSB7XG4gICAgICAgIGRldGFpbHMucHVzaChyZXNwb25zZS5kZXRhaWxzKTtcbiAgICAgIH1cbiAgICAgIGRhdGEucHVzaChyZXNwb25zZS5kYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0YTogQXJyYXkuaXNBcnJheSh0cmFuc2Zvcm0ub3BlcmF0aW9ucykgPyBkYXRhIDogZGF0YVswXSxcbiAgICAgIGRldGFpbHMsXG4gICAgICB0cmFuc2Zvcm1zOiBbdHJhbnNmb3JtLCAuLi50cmFuc2Zvcm1zXVxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0UXVlcnlSZXF1ZXN0UHJvY2Vzc29yKFxuICAgIHJlcXVlc3Q6IFJlY29yZFF1ZXJ5UmVxdWVzdFxuICApOiBRdWVyeVJlcXVlc3RQcm9jZXNzb3Ige1xuICAgIHJldHVybiBRdWVyeVJlcXVlc3RQcm9jZXNzb3JzW3JlcXVlc3Qub3BdO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldFRyYW5zZm9ybVJlcXVlc3RQcm9jZXNzb3IoXG4gICAgcmVxdWVzdDogUmVjb3JkVHJhbnNmb3JtUmVxdWVzdFxuICApOiBUcmFuc2Zvcm1SZXF1ZXN0UHJvY2Vzc29yIHtcbiAgICByZXR1cm4gVHJhbnNmb3JtUmVxdWVzdFByb2Nlc3NvcnNbcmVxdWVzdC5vcF07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgcHJvY2Vzc1F1ZXJ5UmVxdWVzdHMoXG4gICAgcXVlcnk6IFJlY29yZFF1ZXJ5XG4gICk6IFByb21pc2U8UXVlcnlSZXF1ZXN0UHJvY2Vzc29yUmVzcG9uc2VbXT4ge1xuICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLmdldFF1ZXJ5T3B0aW9ucyhxdWVyeSk7XG4gICAgY29uc3QgcmVxdWVzdHMgPSBnZXRRdWVyeVJlcXVlc3RzKHRoaXMucmVxdWVzdFByb2Nlc3NvciwgcXVlcnkpO1xuICAgIGlmIChcbiAgICAgIG9wdGlvbnM/Lm1heFJlcXVlc3RzICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIHJlcXVlc3RzLmxlbmd0aCA+IG9wdGlvbnMubWF4UmVxdWVzdHNcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBRdWVyeU5vdEFsbG93ZWQoXG4gICAgICAgIGBUaGlzIHF1ZXJ5IHJlcXVpcmVzICR7cmVxdWVzdHMubGVuZ3RofSByZXF1ZXN0cywgd2hpY2ggZXhjZWVkcyB0aGUgc3BlY2lmaWVkIGxpbWl0IG9mICR7b3B0aW9ucy5tYXhSZXF1ZXN0c30gcmVxdWVzdHMgcGVyIHF1ZXJ5LmAsXG4gICAgICAgIHF1ZXJ5XG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zPy5wYXJhbGxlbFJlcXVlc3RzKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5hbGwoXG4gICAgICAgIHJlcXVlc3RzLm1hcCgocmVxdWVzdCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHByb2Nlc3NvciA9IHRoaXMuZ2V0UXVlcnlSZXF1ZXN0UHJvY2Vzc29yKHJlcXVlc3QpO1xuICAgICAgICAgIHJldHVybiBwcm9jZXNzb3IodGhpcy5yZXF1ZXN0UHJvY2Vzc29yLCByZXF1ZXN0KTtcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlcyA9IFtdO1xuICAgICAgZm9yIChsZXQgcmVxdWVzdCBvZiByZXF1ZXN0cykge1xuICAgICAgICBjb25zdCBwcm9jZXNzb3IgPSB0aGlzLmdldFF1ZXJ5UmVxdWVzdFByb2Nlc3NvcihyZXF1ZXN0KTtcbiAgICAgICAgcmVzcG9uc2VzLnB1c2goYXdhaXQgcHJvY2Vzc29yKHRoaXMucmVxdWVzdFByb2Nlc3NvciwgcmVxdWVzdCkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3BvbnNlcztcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgcHJvY2Vzc1RyYW5zZm9ybVJlcXVlc3RzKFxuICAgIHRyYW5zZm9ybTogUmVjb3JkVHJhbnNmb3JtXG4gICk6IFByb21pc2U8VHJhbnNmb3JtUmVxdWVzdFByb2Nlc3NvclJlc3BvbnNlW10+IHtcbiAgICBjb25zdCBvcHRpb25zID0gdGhpcy5nZXRUcmFuc2Zvcm1PcHRpb25zKHRyYW5zZm9ybSk7XG4gICAgY29uc3QgcmVxdWVzdHMgPSBnZXRUcmFuc2Zvcm1SZXF1ZXN0cyh0aGlzLnJlcXVlc3RQcm9jZXNzb3IsIHRyYW5zZm9ybSk7XG4gICAgaWYgKFxuICAgICAgb3B0aW9ucz8ubWF4UmVxdWVzdHMgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgcmVxdWVzdHMubGVuZ3RoID4gb3B0aW9ucy5tYXhSZXF1ZXN0c1xuICAgICkge1xuICAgICAgdGhyb3cgbmV3IFRyYW5zZm9ybU5vdEFsbG93ZWQoXG4gICAgICAgIGBUaGlzIHRyYW5zZm9ybSByZXF1aXJlcyAke3JlcXVlc3RzLmxlbmd0aH0gcmVxdWVzdHMsIHdoaWNoIGV4Y2VlZHMgdGhlIHNwZWNpZmllZCBsaW1pdCBvZiAke29wdGlvbnMubWF4UmVxdWVzdHN9IHJlcXVlc3RzIHBlciB0cmFuc2Zvcm0uYCxcbiAgICAgICAgdHJhbnNmb3JtXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zPy5wYXJhbGxlbFJlcXVlc3RzKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5hbGwoXG4gICAgICAgIHJlcXVlc3RzLm1hcCgocmVxdWVzdCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHByb2Nlc3NvciA9IHRoaXMuZ2V0VHJhbnNmb3JtUmVxdWVzdFByb2Nlc3NvcihyZXF1ZXN0KTtcbiAgICAgICAgICByZXR1cm4gcHJvY2Vzc29yKHRoaXMucmVxdWVzdFByb2Nlc3NvciwgcmVxdWVzdCk7XG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCByZXNwb25zZXMgPSBbXTtcbiAgICAgIGZvciAobGV0IHJlcXVlc3Qgb2YgcmVxdWVzdHMpIHtcbiAgICAgICAgY29uc3QgcHJvY2Vzc29yID0gdGhpcy5nZXRUcmFuc2Zvcm1SZXF1ZXN0UHJvY2Vzc29yKHJlcXVlc3QpO1xuICAgICAgICByZXNwb25zZXMucHVzaChhd2FpdCBwcm9jZXNzb3IodGhpcy5yZXF1ZXN0UHJvY2Vzc29yLCByZXF1ZXN0KSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzcG9uc2VzO1xuICAgIH1cbiAgfVxufVxuIl19