@orbit/jsonapi
Version:
JSON:API support for Orbit.
268 lines (266 loc) • 41.3 kB
JavaScript
"use strict";
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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.JSONAPISource = void 0;
const core_1 = require("@orbit/core");
const data_1 = require("@orbit/data");
const records_1 = require("@orbit/records");
const jsonapi_request_processor_1 = require("./jsonapi-request-processor");
const jsonapi_url_builder_1 = require("./jsonapi-url-builder");
const query_requests_1 = require("./lib/query-requests");
const transform_requests_1 = require("./lib/transform-requests");
const { deprecate } = core_1.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 records_1.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 core_1.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 || jsonapi_request_processor_1.JSONAPIRequestProcessor;
this.requestProcessor = new RequestProcessorClass({
sourceName: name,
serializerFor,
serializerClassFor,
serializerSettingsFor,
SerializerClass,
URLBuilderClass: URLBuilderClass || jsonapi_url_builder_1.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 query_requests_1.QueryRequestProcessors[request.op];
}
getTransformRequestProcessor(request) {
return transform_requests_1.TransformRequestProcessors[request.op];
}
async processQueryRequests(query) {
const options = this.getQueryOptions(query);
const requests = (0, query_requests_1.getQueryRequests)(this.requestProcessor, query);
if ((options === null || options === void 0 ? void 0 : options.maxRequests) !== undefined &&
requests.length > options.maxRequests) {
throw new data_1.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 = (0, transform_requests_1.getTransformRequests)(this.requestProcessor, transform);
if ((options === null || options === void 0 ? void 0 : options.maxRequests) !== undefined &&
requests.length > options.maxRequests) {
throw new data_1.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([
data_1.pullable,
data_1.pushable,
data_1.queryable,
data_1.updatable
], JSONAPISource);
exports.JSONAPISource = JSONAPISource;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianNvbmFwaS1zb3VyY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvanNvbmFwaS1zb3VyY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUEsc0NBQStDO0FBQy9DLHNDQVVxQjtBQUNyQiw0Q0FpQndCO0FBQ3hCLDJFQUlxQztBQUtyQywrREFHK0I7QUFDL0IseURBTThCO0FBQzlCLGlFQU1rQztBQVFsQyxNQUFNLEVBQUUsU0FBUyxFQUFFLEdBQUcsWUFBSyxDQUFDO0FBZ0U1Qjs7Ozs7Ozs7Ozs7OztHQWFHO0FBS0gsSUFBYSxhQUFhLEdBQTFCLE1BQWEsYUFNWCxTQUFRLHNCQUE0QjtJQVFwQyxZQUFZLFFBQStDO1FBQ3pELFFBQVEsQ0FBQyxJQUFJLEdBQUcsUUFBUSxDQUFDLElBQUksSUFBSSxTQUFTLENBQUM7UUFFM0MsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRWhCLElBQUksRUFDRixJQUFJLEVBQ0osdUJBQXVCLEVBQ3ZCLG1CQUFtQixFQUNuQixTQUFTLEVBQ1QsSUFBSSxFQUNKLG9CQUFvQixFQUNwQixtQkFBbUIsRUFDbkIsYUFBYSxFQUNiLGtCQUFrQixFQUNsQixxQkFBcUIsRUFDckIsZUFBZSxFQUNmLHFCQUFxQixFQUNyQixlQUFlLEVBQ2YsTUFBTSxFQUNQLEdBQUcsUUFBUSxDQUFDO1FBRWIsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRTtZQUM3QixNQUFNLElBQUksZ0JBQVMsQ0FDakIseUZBQXlGLENBQzFGLENBQUM7U0FDSDtRQUVELElBQUksSUFBSSxDQUFDLG9CQUFvQixLQUFLLFNBQVMsRUFBRTtZQUMzQyxJQUFJLENBQUMsb0JBQW9CLEdBQUcsRUFBK0IsQ0FBQztTQUM3RDtRQUNELElBQUksSUFBSSxDQUFDLHdCQUF3QixLQUFLLFNBQVMsRUFBRTtZQUMvQyxJQUFJLENBQUMsd0JBQXdCLEdBQUcsRUFBK0IsQ0FBQztTQUNqRTtRQUVELHFFQUFx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QUFTLENBQ1YsQ0FBQztTQUNIO1FBRUQsSUFBSSxPQUFPLGFBQVAsT0FBTyx1QkFBUCxPQUFPLENBQUUsZ0JBQWdCLEVBQUU7WUFDN0IsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUNoQixRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUU7Z0JBQ3ZCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDN0QsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ25ELENBQUMsQ0FBQyxDQUNILENBQUM7U0FDSDthQUFNO1lBQ0wsTUFBTSxTQUFTLEdBQUcsRUFBRSxDQUFDO1lBQ3JCLEtBQUssSUFBSSxPQUFPLElBQUksUUFBUSxFQUFFO2dCQUM1QixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsNEJBQTRCLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQzdELFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxTQUFTLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7YUFDakU7WUFDRCxPQUFPLFNBQVMsQ0FBQztTQUNsQjtJQUNILENBQUM7Q0FDRixDQUFBO0FBL1VZLGFBQWE7SUFKekIsZUFBUTtJQUNSLGVBQVE7SUFDUixnQkFBUztJQUNULGdCQUFTO0dBQ0csYUFBYSxDQStVekI7QUEvVVksc0NBQWEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBPcmJpdCwgQXNzZXJ0aW9uIH0gZnJvbSAnQG9yYml0L2NvcmUnO1xuaW1wb3J0IHtcbiAgUmVxdWVzdE9wdGlvbnMsXG4gIHB1bGxhYmxlLFxuICBwdXNoYWJsZSxcbiAgcXVlcnlhYmxlLFxuICB1cGRhdGFibGUsXG4gIFRyYW5zZm9ybU5vdEFsbG93ZWQsXG4gIFF1ZXJ5Tm90QWxsb3dlZCxcbiAgRnVsbFJlc3BvbnNlLFxuICBEZWZhdWx0UmVxdWVzdE9wdGlvbnNcbn0gZnJvbSAnQG9yYml0L2RhdGEnO1xuaW1wb3J0IHtcbiAgUmVjb3JkU291cmNlLFxuICBSZWNvcmRTb3VyY2VTZXR0aW5ncyxcbiAgUmVjb3JkUHVsbGFibGUsXG4gIFJlY29yZFB1c2hhYmxlLFxuICBSZWNvcmRRdWVyeWFibGUsXG4gIFJlY29yZFVwZGF0YWJsZSxcbiAgUmVjb3JkT3BlcmF0aW9uLFxuICBSZWNvcmRUcmFuc2Zvcm0sXG4gIFJlY29yZFF1ZXJ5LFxuICBSZWNvcmRRdWVyeUV4cHJlc3Npb25SZXN1bHQsXG4gIFJlY29yZE9wZXJhdGlvblJlc3VsdCxcbiAgUmVjb3JkUXVlcnlSZXN1bHQsXG4gIFJlY29yZFRyYW5zZm9ybVJlc3VsdCxcbiAgUmVjb3JkU291cmNlUXVlcnlPcHRpb25zLFxuICBSZWNvcmRRdWVyeUJ1aWxkZXIsXG4gIFJlY29yZFRyYW5zZm9ybUJ1aWxkZXJcbn0gZnJvbSAnQG9yYml0L3JlY29yZHMnO1xuaW1wb3J0IHtcbiAgSlNPTkFQSVJlcXVlc3RQcm9jZXNzb3IsXG4gIEpTT05BUElSZXF1ZXN0UHJvY2Vzc29yU2V0dGluZ3MsXG4gIEZldGNoU2V0dGluZ3Ncbn0gZnJvbSAnLi9qc29uYXBpLXJlcXVlc3QtcHJvY2Vzc29yJztcbmltcG9ydCB7XG4gIEpTT05BUElTZXJpYWxpemVyLFxuICBKU09OQVBJU2VyaWFsaXplclNldHRpbmdzXG59IGZyb20gJy4vanNvbmFwaS1zZXJpYWxpemVyJztcbmltcG9ydCB7XG4gIEpTT05BUElVUkxCdWlsZGVyLFxuICBKU09OQVBJVVJMQnVpbGRlclNldHRpbmdzXG59IGZyb20gJy4vanNvbmFwaS11cmwtYnVpbGRlcic7XG5pbXBvcnQge1xuICBRdWVyeVJlcXVlc3RQcm9jZXNzb3IsXG4gIFF1ZXJ5UmVxdWVzdFByb2Nlc3NvcnMsXG4gIFJlY29yZFF1ZXJ5UmVxdWVzdCxcbiAgZ2V0UXVlcnlSZXF1ZXN0cyxcbiAgUXVlcnlSZXF1ZXN0UHJvY2Vzc29yUmVzcG9uc2Vcbn0gZnJvbSAnLi9saWIvcXVlcnktcmVxdWVzdHMnO1xuaW1wb3J0IHtcbiAgVHJhbnNmb3JtUmVxdWVzdFByb2Nlc3NvcixcbiAgVHJhbnNmb3JtUmVxdWVzdFByb2Nlc3NvcnMsXG4gIFJlY29yZFRyYW5zZm9ybVJlcXVlc3QsXG4gIGdldFRyYW5zZm9ybVJlcXVlc3RzLFxuICBUcmFuc2Zvcm1SZXF1ZXN0UHJvY2Vzc29yUmVzcG9uc2Vcbn0gZnJvbSAnLi9saWIvdHJhbnNmb3JtLXJlcXVlc3RzJztcbmltcG9ydCB7XG4gIFNlcmlhbGl6ZXJDbGFzc0ZvckZuLFxuICBTZXJpYWxpemVyU2V0dGluZ3NGb3JGbixcbiAgU2VyaWFsaXplckZvckZuXG59IGZyb20gJ0BvcmJpdC9zZXJpYWxpemVycyc7XG5pbXBvcnQgeyBKU09OQVBJUmVzcG9uc2UgfSBmcm9tICcuL2pzb25hcGktcmVzcG9uc2UnO1xuXG5jb25zdCB7IGRlcHJlY2F0ZSB9ID0gT3JiaXQ7XG5cbmludGVyZmFjZSBKU09OQVBJU2hhcmVkUmVxdWVzdE9wdGlvbnMge1xuICBtYXhSZXF1ZXN0cz86IG51bWJlcjtcbiAgcGFyYWxsZWxSZXF1ZXN0cz86IGJvb2xlYW47XG59XG5leHBvcnQgaW50ZXJmYWNlIEpTT05BUElRdWVyeU9wdGlvbnNcbiAgZXh0ZW5kcyBSZWNvcmRTb3VyY2VRdWVyeU9wdGlvbnMsXG4gICAgSlNPTkFQSVNoYXJlZFJlcXVlc3RPcHRpb25zIHt9XG5cbmV4cG9ydCBpbnRlcmZhY2UgSlNPTkFQSVRyYW5zZm9ybU9wdGlvbnNcbiAgZXh0ZW5kcyBSZXF1ZXN0T3B0aW9ucyxcbiAgICBKU09OQVBJU2hhcmVkUmVxdWVzdE9wdGlvbnMge31cblxuZXhwb3J0IGludGVyZmFjZSBKU09OQVBJU291cmNlU2V0dGluZ3M8XG4gIFFPIGV4dGVuZHMgSlNPTkFQSVF1ZXJ5T3B0aW9ucyA9IEpTT05BUElRdWVyeU9wdGlvbnMsXG4gIFRPIGV4dGVuZHMgSlNPTkFQSVRyYW5zZm9ybU9wdGlvbnMgPSBKU09OQVBJVHJhbnNmb3JtT3B0aW9ucyxcbiAgUUIgPSBSZWNvcmRRdWVyeUJ1aWxkZXIsXG4gIFRCID0gUmVjb3JkVHJhbnNmb3JtQnVpbGRlclxuPiBleHRlbmRzIFJlY29yZFNvdXJjZVNldHRpbmdzPFFPLCBUTywgUUIsIFRCPiB7XG4gIC8qKlxuICAgKiBEZXByZWNhdGVkIGluIGZhdm9yIG9mIGBkZWZhdWx0VHJhbnNmb3JtT3B0aW9ucy5tYXhSZXF1ZXN0c2BcbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgc2luY2UgdjAuMTcsIHJlbW92ZSBpbiB2MC4xOFxuICAgKi9cbiAgbWF4UmVxdWVzdHNQZXJUcmFuc2Zvcm0/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIERlcHJlY2F0ZWQgaW4gZmF2b3Igb2YgYGRlZmF1bHRRdWVyeU9wdGlvbnMubWF4UmVxdWVzdHNgXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIHNpbmNlIHYwLjE3LCByZW1vdmUgaW4gdjAuMThcbiAgICovXG4gIG1heFJlcXVlc3RzUGVyUXVlcnk/OiBudW1iZXI7XG5cbiAgbmFtZT86IHN0cmluZztcbiAgbmFtZXNwYWNlPzogc3RyaW5nO1xuICBob3N0Pzogc3RyaW5nO1xuICBkZWZhdWx0RmV0Y2hTZXR0aW5ncz86IEZldGNoU2V0dGluZ3M7XG4gIGFsbG93ZWRDb250ZW50VHlwZXM/OiBzdHJpbmdbXTtcbiAgc2VyaWFsaXplckZvcj86IFNlcmlhbGl6ZXJGb3JGbjtcbiAgc2VyaWFsaXplckNsYXNzRm9yPzogU2VyaWFsaXplckNsYXNzRm9yRm47XG4gIHNlcmlhbGl6ZXJTZXR0aW5nc0Zvcj86IFNlcmlhbGl6ZXJTZXR0aW5nc0ZvckZuO1xuICBTZXJpYWxpemVyQ2xhc3M/OiBuZXcgKFxuICAgIHNldHRpbmdzOiBKU09OQVBJU2VyaWFsaXplclNldHRpbmdzXG4gICkgPT4gSlNPTkFQSVNlcmlhbGl6ZXI7XG4gIFJlcXVlc3RQcm9jZXNzb3JDbGFzcz86IG5ldyAoXG4gICAgc2V0dGluZ3M6IEpTT05BUElSZXF1ZXN0UHJvY2Vzc29yU2V0dGluZ3NcbiAgKSA9PiBKU09OQVBJUmVxdWVzdFByb2Nlc3NvcjtcbiAgVVJMQnVpbGRlckNsYXNzPzogbmV3IChcbiAgICBzZXR0aW5nczogSlNPTkFQSVVSTEJ1aWxkZXJTZXR0aW5nc1xuICApID0+IEpTT05BUElVUkxCdWlsZGVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEpTT05BUElTb3VyY2U8XG4gIFFPIGV4dGVuZHMgSlNPTkFQSVF1ZXJ5T3B0aW9ucyA9IEpTT05BUElRdWVyeU9wdGlvbnMsXG4gIFRPIGV4dGVuZHMgSlNPTkFQSVRyYW5zZm9ybU9wdGlvbnMgPSBKU09OQVBJVHJhbnNmb3JtT3B0aW9ucyxcbiAgUUIgPSBSZWNvcmRRdWVyeUJ1aWxkZXIsXG4gIFRCID0gUmVjb3JkVHJhbnNmb3JtQnVpbGRlclxuPiBleHRlbmRzIFJlY29yZFNvdXJjZTxRTywgVE8sIFFCLCBUQj4sXG4gICAgUmVjb3JkUHVsbGFibGU8SlNPTkFQSVJlc3BvbnNlW10+LFxuICAgIFJlY29yZFB1c2hhYmxlPEpTT05BUElSZXNwb25zZVtdPixcbiAgICBSZWNvcmRRdWVyeWFibGU8SlNPTkFQSVJlc3BvbnNlW10sIFFCLCBRTz4sXG4gICAgUmVjb3JkVXBkYXRhYmxlPEpTT05BUElSZXNwb25zZVtdLCBUQiwgVE8+IHt9XG5cbi8qKlxuIFNvdXJjZSBmb3IgYWNjZXNzaW5nIGEgSlNPTiBBUEkgY29tcGxpYW50IFJFU1RmdWwgQVBJIHdpdGggYSBuZXR3b3JrIGZldGNoXG4gcmVxdWVzdC5cblxuIElmIGEgc2luZ2xlIHRyYW5zZm9ybSBvciBxdWVyeSByZXF1aXJlcyBtb3JlIHRoYW4gb25lIGZldGNoIHJlcXVlc3QsXG4gcmVxdWVzdHMgd2lsbCBiZSBwZXJmb3JtZWQgc2VxdWVudGlhbGx5IGFuZCByZXNvbHZlZCB0b2dldGhlci4gRnJvbSB0aGVcbiBwZXJzcGVjdGl2ZSBvZiBPcmJpdCwgdGhlc2Ugb3BlcmF0aW9ucyB3aWxsIGFsbCBzdWNjZWVkIG9yIGZhaWwgdG9nZXRoZXIuIFRoZVxuIGBtYXhSZXF1ZXN0c1BlclRyYW5zZm9ybWAgYW5kIGBtYXhSZXF1ZXN0c1BlclF1ZXJ5YCBzZXR0aW5ncyBhbGxvdyBsaW1pdHMgdG8gYmVcbiBzZXQgb24gdGhpcyBiZWhhdmlvci4gVGhlc2Ugc2V0dGluZ3Mgc2hvdWxkIGJlIHNldCB0byBgMWAgaWYgeW91ciBjbGllbnQvc2VydmVyXG4gY29uZmlndXJhdGlvbiBpcyB1bmFibGUgdG8gcmVzb2x2ZSBwYXJ0aWFsbHkgc3VjY2Vzc2Z1bCB0cmFuc2Zvcm1zIC8gcXVlcmllcy5cblxuIEBjbGFzcyBKU09OQVBJU291cmNlXG4gQGV4dGVuZHMgU291cmNlXG4gKi9cbkBwdWxsYWJsZVxuQHB1c2hhYmxlXG5AcXVlcnlhYmxlXG5AdXBkYXRhYmxlXG5leHBvcnQgY2xhc3MgSlNPTkFQSVNvdXJjZTxcbiAgICBRTyBleHRlbmRzIEpTT05BUElRdWVyeU9wdGlvbnMgPSBKU09OQVBJUXVlcnlPcHRpb25zLFxuICAgIFRPIGV4dGVuZHMgSlNPTkFQSVRyYW5zZm9ybU9wdGlvbnMgPSBKU09OQVBJVHJhbnNmb3JtT3B0aW9ucyxcbiAgICBRQiA9IFJlY29yZFF1ZXJ5QnVpbGRlcixcbiAgICBUQiA9IFJlY29yZFRyYW5zZm9ybUJ1aWxkZXJcbiAgPlxuICBleHRlbmRzIFJlY29yZFNvdXJjZTxRTywgVE8sIFFCLCBUQj5cbiAgaW1wbGVtZW50c1xuICAgIFJlY29yZFB1bGxhYmxlPEpTT05BUElSZXNwb25zZVtdPixcbiAgICBSZWNvcmRQdXNoYWJsZTxKU09OQVBJUmVzcG9uc2VbXT4sXG4gICAgUmVjb3JkUXVlcnlhYmxlPEpTT05BUElSZXNwb25zZVtdLCBRQiwgUU8+LFxuICAgIFJlY29yZFVwZGF0YWJsZTxKU09OQVBJUmVzcG9uc2VbXSwgVEIsIFRPPiB7XG4gIHJlcXVlc3RQcm9jZXNzb3I6IEpTT05BUElSZXF1ZXN0UHJvY2Vzc29yO1xuXG4gIGNvbnN0cnVjdG9yKHNldHRpbmdzOiBKU09OQVBJU291cmNlU2V0dGluZ3M8UU8sIFRPLCBRQiwgVEI+KSB7XG4gICAgc2V0dGluZ3MubmFtZSA9IHNldHRpbmdzLm5hbWUgfHwgJ2pzb25hcGknO1xuXG4gICAgc3VwZXIoc2V0dGluZ3MpO1xuXG4gICAgbGV0IHtcbiAgICAgIG5hbWUsXG4gICAgICBtYXhSZXF1ZXN0c1BlclRyYW5zZm9ybSxcbiAgICAgIG1heFJlcXVlc3RzUGVyUXVlcnksXG4gICAgICBuYW1lc3BhY2UsXG4gICAgICBob3N0LFxuICAgICAgZGVmYXVsdEZldGNoU2V0dGluZ3MsXG4gICAgICBhbGxvd2VkQ29udGVudFR5cGVzLFxuICAgICAgc2VyaWFsaXplckZvcixcbiAgICAgIHNlcmlhbGl6ZXJDbGFzc0ZvcixcbiAgICAgIHNlcmlhbGl6ZXJTZXR0aW5nc0ZvcixcbiAgICAgIFNlcmlhbGl6ZXJDbGFzcyxcbiAgICAgIFJlcXVlc3RQcm9jZXNzb3JDbGFzcyxcbiAgICAgIFVSTEJ1aWxkZXJDbGFzcyxcbiAgICAgIGtleU1hcFxuICAgIH0gPSBzZXR0aW5ncztcblxuICAgIGlmICh0aGlzLnNjaGVtYSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgQXNzZXJ0aW9uKFxuICAgICAgICBcIkpTT05BUElTb3VyY2UncyBgc2NoZW1hYCBtdXN0IGJlIHNwZWNpZmllZCBpbiB0aGUgIGBzZXR0aW5nc2AgcGFzc2VkIHRvIGl0cyBjb25zdHJ1Y3RvclwiXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9kZWZhdWx0UXVlcnlPcHRpb25zID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuX2RlZmF1bHRRdWVyeU9wdGlvbnMgPSB7fSBhcyBEZWZhdWx0UmVxdWVzdE9wdGlvbnM8UU8+O1xuICAgIH1cbiAgICBpZiAodGhpcy5fZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5fZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnMgPSB7fSBhcyBEZWZhdWx0UmVxdWVzdE9wdGlvbnM8VE8+O1xuICAgIH1cblxuICAgIC8vIFBhcmFsbGVsaXplIHF1ZXJ5IHJlcXVlc3RzIGJ5IGRlZmF1bHQgKGJ1dCBub3QgdHJhbnNmb3JtIHJlcXVlc3RzKVxuICAgIGlmICh0aGlzLl9kZWZhdWx0UXVlcnlPcHRpb25zLnBhcmFsbGVsUmVxdWVzdHMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5fZGVmYXVsdFF1ZXJ5T3B0aW9ucy5wYXJhbGxlbFJlcXVlc3RzID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAobWF4UmVxdWVzdHNQZXJUcmFuc2Zvcm0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgZGVwcmVjYXRlKFxuICAgICAgICBcIlRoZSAnbWF4UmVxdWVzdHNQZXJUcmFuc2Zvcm0nIHNldHRpbmcgZm9yICdKU09OQVBTb3VyY2UnIGhhcyBiZWVuIGRlcHJlY2F0ZWQgaW4gZmF2b3Igb2YgJ2RlZmF1bHRUcmFuc2Zvcm1PcHRpb25zLm1heFJlcXVlc3RzJy5cIlxuICAgICAgKTtcbiAgICAgIHRoaXMuX2RlZmF1bHRUcmFuc2Zvcm1PcHRpb25zLm1heFJlcXVlc3RzID0gbWF4UmVxdWVzdHNQZXJUcmFuc2Zvcm07XG4gICAgfVxuICAgIGlmIChtYXhSZXF1ZXN0c1BlclF1ZXJ5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGRlcHJlY2F0ZShcbiAgICAgICAgXCJUaGUgJ21heFJlcXVlc3RzUGVyUXVlcnknIHNldHRpbmcgZm9yICdKU09OQVBTb3VyY2UnIGhhcyBiZWVuIGRlcHJlY2F0ZWQgaW4gZmF2b3Igb2YgJ2RlZmF1bHRRdWVyeU9wdGlvbnMubWF4UmVxdWVzdHMnLlwiXG4gICAgICApO1xuICAgICAgdGhpcy5fZGVmYXVsdFF1ZXJ5T3B0aW9ucy5tYXhSZXF1ZXN0cyA9IG1heFJlcXVlc3RzUGVyUXVlcnk7XG4gICAgfVxuXG4gICAgUmVxdWVzdFByb2Nlc3NvckNsYXNzID0gUmVxdWVzdFByb2Nlc3NvckNsYXNzIHx8IEpTT05BUElSZXF1ZXN0UHJvY2Vzc29yO1xuICAgIHRoaXMucmVxdWVzdFByb2Nlc3NvciA9IG5ldyBSZXF1ZXN0UHJvY2Vzc29yQ2xhc3Moe1xuICAgICAgc291cmNlTmFtZTogbmFtZSxcbiAgICAgIHNlcmlhbGl6ZXJGb3IsXG4gICAgICBzZXJpYWxpemVyQ2xhc3NGb3IsXG4gICAgICBzZXJpYWxpemVyU2V0dGluZ3NGb3IsXG4gICAgICBTZXJpYWxpemVyQ2xhc3MsXG4gICAgICBVUkxCdWlsZGVyQ2xhc3M6IFVSTEJ1aWxkZXJDbGFzcyB8fCBKU09OQVBJVVJMQnVpbGRlcixcbiAgICAgIGFsbG93ZWRDb250ZW50VHlwZXMsXG4gICAgICBkZWZhdWx0RmV0Y2hTZXR0aW5ncyxcbiAgICAgIG5hbWVzcGFjZSxcbiAgICAgIGhvc3QsXG4gICAgICBzY2hlbWE6IHRoaXMuc2NoZW1hLFxuICAgICAga2V5TWFwXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRGVwcmVjYXRlZCBpbiBmYXZvciBvZiBgZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnMubWF4UmVxdWVzdHNgXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIHNpbmNlIHYwLjE3LCByZW1vdmUgaW4gdjAuMThcbiAgICovXG4gIGdldCBtYXhSZXF1ZXN0c1BlclRyYW5zZm9ybSgpOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICAgIGRlcHJlY2F0ZShcbiAgICAgIFwiVGhlICdtYXhSZXF1ZXN0c1BlclRyYW5zZm9ybScgcHJvcGVydHkgZm9yICdKU09OQVBTb3VyY2UnIGhhcyBiZWVuIGRlcHJlY2F0ZWQgaW4gZmF2b3Igb2YgJ2RlZmF1bHRUcmFuc2Zvcm1PcHRpb25zLm1heFJlcXVlc3RzJy5cIlxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuX2RlZmF1bHRUcmFuc2Zvcm1PcHRpb25zPy5tYXhSZXF1ZXN0cztcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXByZWNhdGVkIGluIGZhdm9yIG9mIGBkZWZhdWx0VHJhbnNmb3JtT3B0aW9ucy5tYXhSZXF1ZXN0c2BcbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgc2luY2UgdjAuMTcsIHJlbW92ZSBpbiB2MC4xOFxuICAgKi9cbiAgc2V0IG1heFJlcXVlc3RzUGVyVHJhbnNmb3JtKHZhbDogbnVtYmVyIHwgdW5kZWZpbmVkKSB7XG4gICAgZGVwcmVjYXRlKFxuICAgICAgXCJUaGUgJ21heFJlcXVlc3RzUGVyVHJhbnNmb3JtJyBwcm9wZXJ0eSBmb3IgJ0pTT05BUFNvdXJjZScgaGFzIGJlZW4gZGVwcmVjYXRlZCBpbiBmYXZvciBvZiAnZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnMubWF4UmVxdWVzdHMnLlwiXG4gICAgKTtcbiAgICBpZiAodGhpcy5fZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5fZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnMgPSB7fSBhcyBEZWZhdWx0UmVxdWVzdE9wdGlvbnM8VE8+O1xuICAgIH1cbiAgICB0aGlzLl9kZWZhdWx0VHJhbnNmb3JtT3B0aW9ucy5tYXhSZXF1ZXN0cyA9IHZhbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXByZWNhdGVkIGluIGZhdm9yIG9mIGBkZWZhdWx0UXVlcnlPcHRpb25zLm1heFJlcXVlc3RzYFxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBzaW5jZSB2MC4xNywgcmVtb3ZlIGluIHYwLjE4XG4gICAqL1xuICBnZXQgbWF4UmVxdWVzdHNQZXJRdWVyeSgpOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICAgIGRlcHJlY2F0ZShcbiAgICAgIFwiVGhlICdtYXhSZXF1ZXN0c1BlclF1ZXJ5JyBwcm9wZXJ0eSBmb3IgJ0pTT05BUFNvdXJjZScgaGFzIGJlZW4gZGVwcmVjYXRlZCBpbiBmYXZvciBvZiAnZGVmYXVsdFF1ZXJ5T3B0aW9ucy5tYXhSZXF1ZXN0cycuXCJcbiAgICApO1xuICAgIHJldHVybiB0aGlzLl9kZWZhdWx0UXVlcnlPcHRpb25zPy5tYXhSZXF1ZXN0cztcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXByZWNhdGVkIGluIGZhdm9yIG9mIGBkZWZhdWx0UXVlcnlPcHRpb25zLm1heFJlcXVlc3RzYFxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBzaW5jZSB2MC4xNywgcmVtb3ZlIGluIHYwLjE4XG4gICAqL1xuICBzZXQgbWF4UmVxdWVzdHNQZXJRdWVyeSh2YWw6IG51bWJlciB8IHVuZGVmaW5lZCkge1xuICAgIGRlcHJlY2F0ZShcbiAgICAgIFwiVGhlICdtYXhSZXF1ZXN0c1BlclF1ZXJ5JyBwcm9wZXJ0eSBmb3IgJ0pTT05BUFNvdXJjZScgaGFzIGJlZW4gZGVwcmVjYXRlZCBpbiBmYXZvciBvZiAnZGVmYXVsdFF1ZXJ5T3B0aW9ucy5tYXhSZXF1ZXN0cycuXCJcbiAgICApO1xuICAgIGlmICh0aGlzLl9kZWZhdWx0UXVlcnlPcHRpb25zID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuX2RlZmF1bHRRdWVyeU9wdGlvbnMgPSB7fSBhcyBEZWZhdWx0UmVxdWVzdE9wdGlvbnM8UU8+O1xuICAgIH1cbiAgICB0aGlzLl9kZWZhdWx0UXVlcnlPcHRpb25zLm1heFJlcXVlc3RzID0gdmFsO1xuICB9XG5cbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgLy8gUHVzaGFibGUgaW50ZXJmYWNlIGltcGxlbWVudGF0aW9uXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbiAgYXN5bmMgX3B1c2goXG4gICAgdHJhbnNmb3JtOiBSZWNvcmRUcmFuc2Zvcm1cbiAgKTogUHJvbWlzZTxGdWxsUmVzcG9uc2U8dW5kZWZpbmVkLCBKU09OQVBJUmVzcG9uc2VbXSwgUmVjb3JkT3BlcmF0aW9uPj4ge1xuICAgIGlmICh0aGlzLnRyYW5zZm9ybUxvZy5jb250YWlucyh0cmFuc2Zvcm0uaWQpKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuXG4gICAgY29uc3QgcmVzcG9uc2VzID0gYXdhaXQgdGhpcy5wcm9jZXNzVHJhbnNmb3JtUmVxdWVzdHModHJhbnNmb3JtKTtcbiAgICBjb25zdCBkZXRhaWxzOiBKU09OQVBJUmVzcG9uc2VbXSA9IFtdO1xuICAgIGNvbnN0IHRyYW5zZm9ybXM6IFJlY29yZFRyYW5zZm9ybVtdID0gW107XG5cbiAgICBmb3IgKGxldCByZXNwb25zZSBvZiByZXNwb25zZXMpIHtcbiAgICAgIGlmIChyZXNwb25zZS50cmFuc2Zvcm1zKSB7XG4gICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KHRyYW5zZm9ybXMsIHJlc3BvbnNlLnRyYW5zZm9ybXMpO1xuICAgICAgfVxuICAgICAgaWYgKHJlc3BvbnNlLmRldGFpbHMpIHtcbiAgICAgICAgZGV0YWlscy5wdXNoKHJlc3BvbnNlLmRldGFpbHMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICB0cmFuc2Zvcm1zOiBbdHJhbnNmb3JtLCAuLi50cmFuc2Zvcm1zXSxcbiAgICAgIGRldGFpbHNcbiAgICB9O1xuICB9XG5cbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgLy8gUHVsbGFibGUgaW50ZXJmYWNlIGltcGxlbWVudGF0aW9uXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbiAgYXN5bmMgX3B1bGwoXG4gICAgcXVlcnk6IFJlY29yZFF1ZXJ5XG4gICk6IFByb21pc2U8RnVsbFJlc3BvbnNlPHVuZGVmaW5lZCwgSlNPTkFQSVJlc3BvbnNlW10sIFJlY29yZE9wZXJhdGlvbj4+IHtcbiAgICBjb25zdCByZXNwb25zZXMgPSBhd2FpdCB0aGlzLnByb2Nlc3NRdWVyeVJlcXVlc3RzKHF1ZXJ5KTtcbiAgICBjb25zdCBkZXRhaWxzOiBKU09OQVBJUmVzcG9uc2VbXSA9IFtdO1xuICAgIGNvbnN0IHRyYW5zZm9ybXM6IFJlY29yZFRyYW5zZm9ybVtdID0gW107XG5cbiAgICBmb3IgKGxldCByZXNwb25zZSBvZiByZXNwb25zZXMpIHtcbiAgICAgIGlmIChyZXNwb25zZS50cmFuc2Zvcm1zKSB7XG4gICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KHRyYW5zZm9ybXMsIHJlc3BvbnNlLnRyYW5zZm9ybXMpO1xuICAgICAgfVxuICAgICAgaWYgKHJlc3BvbnNlLmRldGFpbHMpIHtcbiAgICAgICAgZGV0YWlscy5wdXNoKHJlc3BvbnNlLmRldGFpbHMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICB0cmFuc2Zvcm1zLFxuICAgICAgZGV0YWlsc1xuICAgIH07XG4gIH1cblxuICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAvLyBRdWVyeWFibGUgaW50ZXJmYWNlIGltcGxlbWVudGF0aW9uXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbiAgYXN5bmMgX3F1ZXJ5KFxuICAgIHF1ZXJ5OiBSZWNvcmRRdWVyeVxuICApOiBQcm9taXNlPFxuICAgIEZ1bGxSZXNwb25zZTxSZWNvcmRRdWVyeVJlc3VsdCwgSlNPTkFQSVJlc3BvbnNlW10sIFJlY29yZE9wZXJhdGlvbj5cbiAgPiB7XG4gICAgY29uc3QgcmVzcG9uc2VzID0gYXdhaXQgdGhpcy5wcm9jZXNzUXVlcnlSZXF1ZXN0cyhxdWVyeSk7XG4gICAgY29uc3QgZGV0YWlsczogSlNPTkFQSVJlc3BvbnNlW10gPSBbXTtcbiAgICBjb25zdCB0cmFuc2Zvcm1zOiBSZWNvcmRUcmFuc2Zvcm1bXSA9IFtdO1xuICAgIGNvbnN0IGRhdGE6IFJlY29yZFF1ZXJ5RXhwcmVzc2lvblJlc3VsdFtdID0gW107XG5cbiAgICBmb3IgKGxldCByZXNwb25zZSBvZiByZXNwb25zZXMpIHtcbiAgICAgIGlmIChyZXNwb25zZS50cmFuc2Zvcm1zKSB7XG4gICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KHRyYW5zZm9ybXMsIHJlc3BvbnNlLnRyYW5zZm9ybXMpO1xuICAgICAgfVxuICAgICAgaWYgKHJlc3BvbnNlLmRldGFpbHMpIHtcbiAgICAgICAgZGV0YWlscy5wdXNoKHJlc3BvbnNlLmRldGFpbHMpO1xuICAgICAgfVxuICAgICAgZGF0YS5wdXNoKHJlc3BvbnNlLmRhdGEpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiBBcnJheS5pc0FycmF5KHF1ZXJ5LmV4cHJlc3Npb25zKSA/IGRhdGEgOiBkYXRhWzBdLFxuICAgICAgZGV0YWlscyxcbiAgICAgIHRyYW5zZm9ybXNcbiAgICB9O1xuICB9XG5cbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgLy8gVXBkYXRhYmxlIGludGVyZmFjZSBpbXBsZW1lbnRhdGlvblxuICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gIGFzeW5jIF91cGRhdGUoXG4gICAgdHJhbnNmb3JtOiBSZWNvcmRUcmFuc2Zvcm1cbiAgKTogUHJvbWlzZTxcbiAgICBGdWxsUmVzcG9uc2U8UmVjb3JkVHJhbnNmb3JtUmVzdWx0LCBKU09OQVBJUmVzcG9uc2VbXSwgUmVjb3JkT3BlcmF0aW9uPlxuICA+IHtcbiAgICBpZiAodGhpcy50cmFuc2Zvcm1Mb2cuY29udGFpbnModHJhbnNmb3JtLmlkKSkge1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH1cblxuICAgIGNvbnN0IHJlc3BvbnNlcyA9IGF3YWl0IHRoaXMucHJvY2Vzc1RyYW5zZm9ybVJlcXVlc3RzKHRyYW5zZm9ybSk7XG4gICAgY29uc3QgZGV0YWlsczogSlNPTkFQSVJlc3BvbnNlW10gPSBbXTtcbiAgICBjb25zdCB0cmFuc2Zvcm1zOiBSZWNvcmRUcmFuc2Zvcm1bXSA9IFtdO1xuICAgIGNvbnN0IGRhdGE6IFJlY29yZE9wZXJhdGlvblJlc3VsdFtdID0gW107XG5cbiAgICBmb3IgKGxldCByZXNwb25zZSBvZiByZXNwb25zZXMpIHtcbiAgICAgIGlmIChyZXNwb25zZS50cmFuc2Zvcm1zKSB7XG4gICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KHRyYW5zZm9ybXMsIHJlc3BvbnNlLnRyYW5zZm9ybXMpO1xuICAgICAgfVxuICAgICAgaWYgKHJlc3BvbnNlLmRldGFpbHMpIHtcbiAgICAgICAgZGV0YWlscy5wdXNoKHJlc3BvbnNlLmRldGFpbHMpO1xuICAgICAgfVxuICAgICAgZGF0YS5wdXNoKHJlc3BvbnNlLmRhdGEpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiBBcnJheS5pc0FycmF5KHRyYW5zZm9ybS5vcGVyYXRpb25zKSA/IGRhdGEgOiBkYXRhWzBdLFxuICAgICAgZGV0YWlscyxcbiAgICAgIHRyYW5zZm9ybXM6IFt0cmFuc2Zvcm0sIC4uLnRyYW5zZm9ybXNdXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRRdWVyeVJlcXVlc3RQcm9jZXNzb3IoXG4gICAgcmVxdWVzdDogUmVjb3JkUXVlcnlSZXF1ZXN0XG4gICk6IFF1ZXJ5UmVxdWVzdFByb2Nlc3NvciB7XG4gICAgcmV0dXJuIFF1ZXJ5UmVxdWVzdFByb2Nlc3NvcnNbcmVxdWVzdC5vcF07XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0VHJhbnNmb3JtUmVxdWVzdFByb2Nlc3NvcihcbiAgICByZXF1ZXN0OiBSZWNvcmRUcmFuc2Zvcm1SZXF1ZXN0XG4gICk6IFRyYW5zZm9ybVJlcXVlc3RQcm9jZXNzb3Ige1xuICAgIHJldHVybiBUcmFuc2Zvcm1SZXF1ZXN0UHJvY2Vzc29yc1tyZXF1ZXN0Lm9wXTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBwcm9jZXNzUXVlcnlSZXF1ZXN0cyhcbiAgICBxdWVyeTogUmVjb3JkUXVlcnlcbiAgKTogUHJvbWlzZTxRdWVyeVJlcXVlc3RQcm9jZXNzb3JSZXNwb25zZVtdPiB7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMuZ2V0UXVlcnlPcHRpb25zKHF1ZXJ5KTtcbiAgICBjb25zdCByZXF1ZXN0cyA9IGdldFF1ZXJ5UmVxdWVzdHModGhpcy5yZXF1ZXN0UHJvY2Vzc29yLCBxdWVyeSk7XG4gICAgaWYgKFxuICAgICAgb3B0aW9ucz8ubWF4UmVxdWVzdHMgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgcmVxdWVzdHMubGVuZ3RoID4gb3B0aW9ucy5tYXhSZXF1ZXN0c1xuICAgICkge1xuICAgICAgdGhyb3cgbmV3IFF1ZXJ5Tm90QWxsb3dlZChcbiAgICAgICAgYFRoaXMgcXVlcnkgcmVxdWlyZXMgJHtyZXF1ZXN0cy5sZW5ndGh9IHJlcXVlc3RzLCB3aGljaCBleGNlZWRzIHRoZSBzcGVjaWZpZWQgbGltaXQgb2YgJHtvcHRpb25zLm1heFJlcXVlc3RzfSByZXF1ZXN0cyBwZXIgcXVlcnkuYCxcbiAgICAgICAgcXVlcnlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnM/LnBhcmFsbGVsUmVxdWVzdHMpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLmFsbChcbiAgICAgICAgcmVxdWVzdHMubWFwKChyZXF1ZXN0KSA9PiB7XG4gICAgICAgICAgY29uc3QgcHJvY2Vzc29yID0gdGhpcy5nZXRRdWVyeVJlcXVlc3RQcm9jZXNzb3IocmVxdWVzdCk7XG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3Nvcih0aGlzLnJlcXVlc3RQcm9jZXNzb3IsIHJlcXVlc3QpO1xuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcmVzcG9uc2VzID0gW107XG4gICAgICBmb3IgKGxldCByZXF1ZXN0IG9mIHJlcXVlc3RzKSB7XG4gICAgICAgIGNvbnN0IHByb2Nlc3NvciA9IHRoaXMuZ2V0UXVlcnlSZXF1ZXN0UHJvY2Vzc29yKHJlcXVlc3QpO1xuICAgICAgICByZXNwb25zZXMucHVzaChhd2FpdCBwcm9jZXNzb3IodGhpcy5yZXF1ZXN0UHJvY2Vzc29yLCByZXF1ZXN0KSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzcG9uc2VzO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBwcm9jZXNzVHJhbnNmb3JtUmVxdWVzdHMoXG4gICAgdHJhbnNmb3JtOiBSZWNvcmRUcmFuc2Zvcm1cbiAgKTogUHJvbWlzZTxUcmFuc2Zvcm1SZXF1ZXN0UHJvY2Vzc29yUmVzcG9uc2VbXT4ge1xuICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLmdldFRyYW5zZm9ybU9wdGlvbnModHJhbnNmb3JtKTtcbiAgICBjb25zdCByZXF1ZXN0cyA9IGdldFRyYW5zZm9ybVJlcXVlc3RzKHRoaXMucmVxdWVzdFByb2Nlc3NvciwgdHJhbnNmb3JtKTtcbiAgICBpZiAoXG4gICAgICBvcHRpb25zPy5tYXhSZXF1ZXN0cyAhPT0gdW5kZWZpbmVkICYmXG4gICAgICByZXF1ZXN0cy5sZW5ndGggPiBvcHRpb25zLm1heFJlcXVlc3RzXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgVHJhbnNmb3JtTm90QWxsb3dlZChcbiAgICAgICAgYFRoaXMgdHJhbnNmb3JtIHJlcXVpcmVzICR7cmVxdWVzdHMubGVuZ3RofSByZXF1ZXN0cywgd2hpY2ggZXhjZWVkcyB0aGUgc3BlY2lmaWVkIGxpbWl0IG9mICR7b3B0aW9ucy5tYXhSZXF1ZXN0c30gcmVxdWVzdHMgcGVyIHRyYW5zZm9ybS5gLFxuICAgICAgICB0cmFuc2Zvcm1cbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnM/LnBhcmFsbGVsUmVxdWVzdHMpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLmFsbChcbiAgICAgICAgcmVxdWVzdHMubWFwKChyZXF1ZXN0KSA9PiB7XG4gICAgICAgICAgY29uc3QgcHJvY2Vzc29yID0gdGhpcy5nZXRUcmFuc2Zvcm1SZXF1ZXN0UHJvY2Vzc29yKHJlcXVlc3QpO1xuICAgICAgICAgIHJldHVybiBwcm9jZXNzb3IodGhpcy5yZXF1ZXN0UHJvY2Vzc29yLCByZXF1ZXN0KTtcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlcyA9IFtdO1xuICAgICAgZm9yIChsZXQgcmVxdWVzdCBvZiByZXF1ZXN0cykge1xuICAgICAgICBjb25zdCBwcm9jZXNzb3IgPSB0aGlzLmdldFRyYW5zZm9ybVJlcXVlc3RQcm9jZXNzb3IocmVxdWVzdCk7XG4gICAgICAgIHJlc3BvbnNlcy5wdXNoKGF3YWl0IHByb2Nlc3Nvcih0aGlzLnJlcXVlc3RQcm9jZXNzb3IsIHJlcXVlc3QpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXNwb25zZXM7XG4gICAgfVxuICB9XG59XG4iXX0=