@orbit/memory
Version:
Orbit source for managing in-memory records.
337 lines • 50.8 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;
};
var MemorySource_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MemorySource = void 0;
const core_1 = require("@orbit/core");
const data_1 = require("@orbit/data");
const records_1 = require("@orbit/records");
const utils_1 = require("@orbit/utils");
const memory_cache_1 = require("./memory-cache");
const { assert, deprecate } = core_1.Orbit;
let MemorySource = MemorySource_1 = class MemorySource extends records_1.RecordSource {
constructor(settings) {
var _a, _b, _c, _d, _e, _f, _g, _h;
const { keyMap, schema, base } = settings;
settings.name = (_a = settings.name) !== null && _a !== void 0 ? _a : 'memory';
super(settings);
this._transforms = {};
this._transformInverses = {};
this.transformLog.on('clear', this._logCleared.bind(this));
this.transformLog.on('truncate', this._logTruncated.bind(this));
this.transformLog.on('rollback', this._logRolledback.bind(this));
let cacheSettings = (_b = settings.cacheSettings) !== null && _b !== void 0 ? _b : {};
cacheSettings.schema = schema;
cacheSettings.keyMap = keyMap;
(_c = cacheSettings.queryBuilder) !== null && _c !== void 0 ? _c : (cacheSettings.queryBuilder = this.queryBuilder);
(_d = cacheSettings.transformBuilder) !== null && _d !== void 0 ? _d : (cacheSettings.transformBuilder = this.transformBuilder);
(_e = cacheSettings.defaultQueryOptions) !== null && _e !== void 0 ? _e : (cacheSettings.defaultQueryOptions = this.defaultQueryOptions);
(_f = cacheSettings.defaultTransformOptions) !== null && _f !== void 0 ? _f : (cacheSettings.defaultTransformOptions = this.defaultTransformOptions);
(_g = cacheSettings.autoValidate) !== null && _g !== void 0 ? _g : (cacheSettings.autoValidate = settings.autoValidate);
if (cacheSettings.autoValidate !== false &&
cacheSettings.validatorFor === undefined &&
cacheSettings.validators === undefined) {
cacheSettings.validatorFor = this._validatorFor;
}
if (base) {
this._base = base;
this._forkPoint = base.transformLog.head;
cacheSettings.base = base.cache;
}
const cacheClass = (_h = settings.cacheClass) !== null && _h !== void 0 ? _h : memory_cache_1.MemoryCache;
this._cache = new cacheClass(cacheSettings);
}
get cache() {
return this._cache;
}
get base() {
return this._base;
}
get forkPoint() {
return this._forkPoint;
}
async upgrade() {
this._cache.upgrade();
}
/////////////////////////////////////////////////////////////////////////////
// Syncable interface implementation
/////////////////////////////////////////////////////////////////////////////
async _sync(transform) {
if (!this.transformLog.contains(transform.id)) {
this._applyTransform(transform);
await this.transformed([transform]);
}
}
/////////////////////////////////////////////////////////////////////////////
// Updatable interface implementation
/////////////////////////////////////////////////////////////////////////////
async _update(transform, hints) {
let results;
const response = {};
if (!this.transformLog.contains(transform.id)) {
results = this._applyTransform(transform);
response.transforms = [transform];
}
if (hints === null || hints === void 0 ? void 0 : hints.data) {
if (Array.isArray(transform.operations)) {
assert('MemorySource#update: `hints.data` must be an array if `transform.operations` is an array', Array.isArray(hints.data));
response.data = hints.data.map((h) => this._retrieveOperationResult(h));
}
else {
response.data = this._retrieveOperationResult(hints.data);
}
}
else if (results) {
response.data = results;
}
if (hints === null || hints === void 0 ? void 0 : hints.details) {
response.details = hints.details;
}
return response;
}
/////////////////////////////////////////////////////////////////////////////
// Queryable interface implementation
/////////////////////////////////////////////////////////////////////////////
async _query(query, hints) {
let response;
if (hints === null || hints === void 0 ? void 0 : hints.data) {
response = {};
if (Array.isArray(query.expressions)) {
assert('MemorySource#query: `hints.data` must be an array if `query.expressions` is an array', Array.isArray(hints.data));
response.data = hints.data.map((h) => this._retrieveQueryExpressionResult(h));
}
else {
response.data = this._retrieveQueryExpressionResult(hints.data);
}
}
else {
response = this._cache.query(query, {
fullResponse: true
});
}
if (hints === null || hints === void 0 ? void 0 : hints.details) {
response.details = hints.details;
}
return response;
}
/////////////////////////////////////////////////////////////////////////////
// Public methods
/////////////////////////////////////////////////////////////////////////////
/**
* Create a clone, or "fork", from a "base" source.
*
* The forked source will have the same `schema` and `keyMap` as its base source.
* The forked source's cache will start with the same immutable document as
* the base source. Its contents and log will evolve independently.
*
* @returns The forked source.
*/
fork(settings = {}) {
var _a, _b, _c, _d, _e;
// required settings
settings.base = this;
settings.schema = this.schema;
settings.keyMap = this.keyMap;
// customizable settings
(_a = settings.queryBuilder) !== null && _a !== void 0 ? _a : (settings.queryBuilder = this._queryBuilder);
(_b = settings.transformBuilder) !== null && _b !== void 0 ? _b : (settings.transformBuilder = this._transformBuilder);
(_c = settings.defaultQueryOptions) !== null && _c !== void 0 ? _c : (settings.defaultQueryOptions = this._defaultQueryOptions);
(_d = settings.defaultTransformOptions) !== null && _d !== void 0 ? _d : (settings.defaultTransformOptions = this._defaultTransformOptions);
if (settings.autoValidate !== false) {
(_e = settings.validatorFor) !== null && _e !== void 0 ? _e : (settings.validatorFor = this._validatorFor);
if (settings.autoValidate === undefined &&
settings.validatorFor === undefined) {
settings.autoValidate = false;
}
}
return new MemorySource_1(settings);
}
async merge(forkedSource, options) {
let { coalesce, sinceTransformId, transformOptions, ...remainingOptions } = options !== null && options !== void 0 ? options : {};
let requestOptions;
if (transformOptions) {
deprecate('In MemorySource#merge, passing `transformOptions` nested within `options` is deprecated. Instead, include them directly alongside other options.');
requestOptions = transformOptions;
}
else {
requestOptions = (remainingOptions !== null && remainingOptions !== void 0 ? remainingOptions : {});
}
let ops = [];
if (forkedSource.cache.isTrackingUpdateOperations) {
ops = forkedSource.cache.getAllUpdateOperations();
}
else {
let transforms;
if (sinceTransformId) {
deprecate('In MemorySource#merge, passing `sinceTransformId` is deprecated. Instead, call `update` with a custom transform/operations.');
transforms = forkedSource.getTransformsSince(sinceTransformId);
}
else {
transforms = forkedSource.getAllTransforms();
}
transforms.forEach((t) => {
Array.prototype.push.apply(ops, (0, utils_1.toArray)(t.operations));
});
}
if (coalesce !== false) {
ops = (0, records_1.coalesceRecordOperations)(ops);
}
if (requestOptions.fullResponse) {
return this.update(ops, requestOptions);
}
else {
return this.update(ops, requestOptions);
}
}
/**
* Rebase works similarly to a git rebase:
*
* After a source is forked, there is a parent- and a child-source. Both may
* be updated with transforms. When `childSource.rebase()` is called, the
* child source's state will be reset to match the current state of its
* parent, and then any locally made transforms will be replayed on the child
* source.
*/
rebase() {
const base = this._base;
if (!base) {
throw new core_1.Assertion('A `base` source must be defined for `rebase` to work');
}
// reset the state of the cache to match the base cache
this.cache.reset();
// replay all locally made transforms
this.getAllTransforms().forEach((t) => this._applyTransform(t));
// reset the fork point
this._forkPoint = base.transformLog.head;
}
/**
* Reset the source's cache and transform log to its initial state, which will
* be either empty or a matching its `base`, if it has one.
*/
async reset() {
// reset the state of the cache (which will match a base cache, if present)
this.cache.reset();
// reset the fork point
this._forkPoint = this._base ? this._base.transformLog.head : undefined;
// clear the transform log, which in turn will clear any tracked transforms
await this.transformLog.clear();
}
/**
* Rolls back the source to a particular `transformId`.
*
* `relativePosition` can be a positive or negative integer used to specify a
* position relative to `transformId`.
*/
rollback(transformId, relativePosition = 0) {
return this.transformLog.rollback(transformId, relativePosition);
}
/**
* Returns all logged transforms since a particular `transformId`.
*/
getTransformsSince(transformId) {
return this.transformLog
.after(transformId)
.map((id) => this._transforms[id]);
}
/**
* @deprecated since v0.17, call `getTransformsSince` instead
*/
transformsSince(transformId) {
deprecate('MemorySource#transformsSince has been deprecated. Please call `source.getTransformsSince(tranformId)` instead.');
return this.getTransformsSince(transformId);
}
/**
* Returns all logged transforms.
*/
getAllTransforms() {
return this.transformLog.entries.map((id) => this._transforms[id]);
}
/**
* @deprecated since v0.17, call `getAllTransforms` instead
*/
allTransforms() {
deprecate('MemorySource#allTransforms has been deprecated. Please call `source.getAllTransforms()` instead.');
return this.getAllTransforms();
}
getTransform(transformId) {
return this._transforms[transformId];
}
getInverseOperations(transformId) {
return this._transformInverses[transformId];
}
get defaultQueryOptions() {
return super.defaultQueryOptions;
}
set defaultQueryOptions(options) {
super.defaultQueryOptions = this._cache.defaultQueryOptions = options;
}
get defaultTransformOptions() {
return super.defaultTransformOptions;
}
set defaultTransformOptions(options) {
this._defaultTransformOptions = this._cache.defaultTransformOptions = options;
}
/////////////////////////////////////////////////////////////////////////////
// Protected methods
/////////////////////////////////////////////////////////////////////////////
_retrieveQueryExpressionResult(result) {
if (Array.isArray(result)) {
return this._cache.getRecordsSync(result);
}
else if (result) {
return this._cache.getRecordSync(result);
}
else {
return result;
}
}
_retrieveOperationResult(result) {
if (result) {
return this._cache.getRecordSync(result);
}
else {
return result;
}
}
_applyTransform(transform) {
var _a;
const { data, details } = this.cache.update(transform, {
fullResponse: true
});
this._transforms[transform.id] = transform;
this._transformInverses[transform.id] = (_a = details === null || details === void 0 ? void 0 : details.inverseOperations) !== null && _a !== void 0 ? _a : [];
return data;
}
_clearTransformFromHistory(transformId) {
delete this._transforms[transformId];
delete this._transformInverses[transformId];
}
_logCleared() {
this._transforms = {};
this._transformInverses = {};
}
_logTruncated(transformId, relativePosition, removed) {
removed.forEach((id) => this._clearTransformFromHistory(id));
}
_logRolledback(transformId, relativePosition, removed) {
removed.reverse().forEach((id) => {
const inverseOperations = this._transformInverses[id];
if (inverseOperations) {
this.cache.update(inverseOperations);
}
this._clearTransformFromHistory(id);
});
}
};
MemorySource = MemorySource_1 = __decorate([
data_1.syncable,
data_1.queryable,
data_1.updatable
], MemorySource);
exports.MemorySource = MemorySource;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtb3J5LXNvdXJjZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tZW1vcnktc291cmNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQSxzQ0FBK0M7QUFDL0Msc0NBVXFCO0FBRXJCLDRDQWlCd0I7QUFDeEIsd0NBQTZDO0FBQzdDLGlEQUl3QjtBQUV4QixNQUFNLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxHQUFHLFlBQUssQ0FBQztBQTRDcEMsSUFBYSxZQUFZLG9CQUF6QixNQUFhLFlBUVgsU0FBUSxzQkFBNEI7SUFZcEMsWUFBWSxRQUF3RDs7UUFDbEUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsUUFBUSxDQUFDO1FBRTFDLFFBQVEsQ0FBQyxJQUFJLEdBQUcsTUFBQSxRQUFRLENBQUMsSUFBSSxtQ0FBSSxRQUFRLENBQUM7UUFFMUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRWhCLElBQUksQ0FBQyxXQUFXLEdBQUcsRUFBRSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxFQUFFLENBQUM7UUFFN0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDM0QsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDaEUsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFFakUsSUFBSSxhQUFhLEdBQ2YsTUFBQSxRQUFRLENBQUMsYUFBYSxtQ0FBSSxFQUFFLENBQUM7UUFDL0IsYUFBYSxDQUFDLE1B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QUFDLE9BQU8sRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFO1lBQy9CLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3RELElBQUksaUJBQWlCLEVBQUU7Z0JBQ3JCLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7YUFDdEM7WUFDRCxJQUFJLENBQUMsMEJBQTBCLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0YsQ0FBQTtBQTVkWSxZQUFZO0lBSHhCLGVBQVE7SUFDUixnQkFBUztJQUNULGdCQUFTO0dBQ0csWUFBWSxDQTRkeEI7QUE1ZFksb0NBQVkiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBc3NlcnRpb24sIE9yYml0IH0gZnJvbSAnQG9yYml0L2NvcmUnO1xuaW1wb3J0IHtcbiAgRGVmYXVsdFJlcXVlc3RPcHRpb25zLFxuICBGdWxsUmVxdWVzdE9wdGlvbnMsXG4gIEZ1bGxSZXNwb25zZSxcbiAgcXVlcnlhYmxlLFxuICBSZXF1ZXN0T3B0aW9ucyxcbiAgUmVzZXR0YWJsZSxcbiAgUmVzcG9uc2VIaW50cyxcbiAgc3luY2FibGUsXG4gIHVwZGF0YWJsZVxufSBmcm9tICdAb3JiaXQvZGF0YSc7XG5pbXBvcnQgeyBSZWNvcmRDYWNoZVVwZGF0ZURldGFpbHMgfSBmcm9tICdAb3JiaXQvcmVjb3JkLWNhY2hlJztcbmltcG9ydCB7XG4gIGNvYWxlc2NlUmVjb3JkT3BlcmF0aW9ucyxcbiAgUmVjb3JkT3BlcmF0aW9uLFxuICBSZWNvcmRPcGVyYXRpb25SZXN1bHQsXG4gIFJlY29yZFF1ZXJ5LFxuICBSZWNvcmRRdWVyeWFibGUsXG4gIFJlY29yZFF1ZXJ5QnVpbGRlcixcbiAgUmVjb3JkUXVlcnlFeHByZXNzaW9uUmVzdWx0LFxuICBSZWNvcmRRdWVyeVJlc3VsdCxcbiAgUmVjb3JkU291cmNlLFxuICBSZWNvcmRTb3VyY2VRdWVyeU9wdGlvbnMsXG4gIFJlY29yZFNvdXJjZVNldHRpbmdzLFxuICBSZWNvcmRTeW5jYWJsZSxcbiAgUmVjb3JkVHJhbnNmb3JtLFxuICBSZWNvcmRUcmFuc2Zvcm1CdWlsZGVyLFxuICBSZWNvcmRUcmFuc2Zvcm1SZXN1bHQsXG4gIFJlY29yZFVwZGF0YWJsZVxufSBmcm9tICdAb3JiaXQvcmVjb3Jkcyc7XG5pbXBvcnQgeyBEaWN0LCB0b0FycmF5IH0gZnJvbSAnQG9yYml0L3V0aWxzJztcbmltcG9ydCB7XG4gIE1lbW9yeUNhY2hlLFxuICBNZW1vcnlDYWNoZUNsYXNzLFxuICBNZW1vcnlDYWNoZVNldHRpbmdzXG59IGZyb20gJy4vbWVtb3J5LWNhY2hlJztcblxuY29uc3QgeyBhc3NlcnQsIGRlcHJlY2F0ZSB9ID0gT3JiaXQ7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWVtb3J5U291cmNlU2V0dGluZ3M8XG4gIFFPIGV4dGVuZHMgUmVxdWVzdE9wdGlvbnMgPSBSZWNvcmRTb3VyY2VRdWVyeU9wdGlvbnMsXG4gIFRPIGV4dGVuZHMgUmVxdWVzdE9wdGlvbnMgPSBSZXF1ZXN0T3B0aW9ucyxcbiAgUUIgPSBSZWNvcmRRdWVyeUJ1aWxkZXIsXG4gIFRCID0gUmVjb3JkVHJhbnNmb3JtQnVpbGRlcixcbiAgUVJEID0gdW5rbm93bixcbiAgVFJEIGV4dGVuZHMgUmVjb3JkQ2FjaGVVcGRhdGVEZXRhaWxzID0gUmVjb3JkQ2FjaGVVcGRhdGVEZXRhaWxzXG4+IGV4dGVuZHMgUmVjb3JkU291cmNlU2V0dGluZ3M8UU8sIFRPLCBRQiwgVEI+IHtcbiAgYmFzZT86IE1lbW9yeVNvdXJjZTxRTywgVE8sIFFCLCBUQiwgUVJELCBUUkQ+O1xuICBjYWNoZUNsYXNzPzogTWVtb3J5Q2FjaGVDbGFzczxRTywgVE8sIFFCLCBUQiwgUVJELCBUUkQ+O1xuICBjYWNoZVNldHRpbmdzPzogUGFydGlhbDxNZW1vcnlDYWNoZVNldHRpbmdzPFFPLCBUTywgUUIsIFRCLCBRUkQsIFRSRD4+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1lbW9yeVNvdXJjZU1lcmdlT3B0aW9ucyB7XG4gIGNvYWxlc2NlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQGRlcHJlY2F0ZWQgc2luY2UgdjAuMTdcbiAgICovXG4gIHNpbmNlVHJhbnNmb3JtSWQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIHNpbmNlIHYwLjE3LCBpbmNsdWRlIHRyYW5zZm9ybSBvcHRpb25zIGFsb25nc2lkZSBtZXJnZSBvcHRpb25zIGluc3RlYWRcbiAgICovXG4gIHRyYW5zZm9ybU9wdGlvbnM/OiBSZXF1ZXN0T3B0aW9ucztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNZW1vcnlTb3VyY2U8XG4gIFFPIGV4dGVuZHMgUmVxdWVzdE9wdGlvbnMgPSBSZWNvcmRTb3VyY2VRdWVyeU9wdGlvbnMsXG4gIFRPIGV4dGVuZHMgUmVxdWVzdE9wdGlvbnMgPSBSZXF1ZXN0T3B0aW9ucyxcbiAgUUIgPSBSZWNvcmRRdWVyeUJ1aWxkZXIsXG4gIFRCID0gUmVjb3JkVHJhbnNmb3JtQnVpbGRlcixcbiAgUVJEID0gdW5rbm93bixcbiAgVFJEIGV4dGVuZHMgUmVjb3JkQ2FjaGVVcGRhdGVEZXRhaWxzID0gUmVjb3JkQ2FjaGVVcGRhdGVEZXRhaWxzXG4+IGV4dGVuZHMgUmVjb3JkU291cmNlPFFPLCBUTywgUUIsIFRCPixcbiAgICBSZWNvcmRTeW5jYWJsZSxcbiAgICBSZWNvcmRRdWVyeWFibGU8UVJELCBRQiwgUU8+LFxuICAgIFJlY29yZFVwZGF0YWJsZTxUUkQsIFRCLCBUTz4ge31cblxuQHN5bmNhYmxlXG5AcXVlcnlhYmxlXG5AdXBkYXRhYmxlXG5leHBvcnQgY2xhc3MgTWVtb3J5U291cmNlPFxuICAgIFFPIGV4dGVuZHMgUmVxdWVzdE9wdGlvbnMgPSBSZWNvcmRTb3VyY2VRdWVyeU9wdGlvbnMsXG4gICAgVE8gZXh0ZW5kcyBSZXF1ZXN0T3B0aW9ucyA9IFJlcXVlc3RPcHRpb25zLFxuICAgIFFCID0gUmVjb3JkUXVlcnlCdWlsZGVyLFxuICAgIFRCID0gUmVjb3JkVHJhbnNmb3JtQnVpbGRlcixcbiAgICBRUkQgPSB1bmtub3duLFxuICAgIFRSRCBleHRlbmRzIFJlY29yZENhY2hlVXBkYXRlRGV0YWlscyA9IFJlY29yZENhY2hlVXBkYXRlRGV0YWlsc1xuICA+XG4gIGV4dGVuZHMgUmVjb3JkU291cmNlPFFPLCBUTywgUUIsIFRCPlxuICBpbXBsZW1lbnRzXG4gICAgUmVjb3JkU3luY2FibGUsXG4gICAgUmVjb3JkUXVlcnlhYmxlPFFSRCwgUUIsIFFPPixcbiAgICBSZWNvcmRVcGRhdGFibGU8VFJELCBUQiwgVE8+LFxuICAgIFJlc2V0dGFibGUge1xuICBwcm90ZWN0ZWQgX2NhY2hlOiBNZW1vcnlDYWNoZTxRTywgVE8sIFFCLCBUQiwgUVJELCBUUkQ+O1xuICBwcm90ZWN0ZWQgX2Jhc2U/OiBNZW1vcnlTb3VyY2U8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPjtcbiAgcHJvdGVjdGVkIF9mb3JrUG9pbnQ/OiBzdHJpbmc7XG4gIHByb3RlY3RlZCBfdHJhbnNmb3JtczogRGljdDxSZWNvcmRUcmFuc2Zvcm0+O1xuICBwcm90ZWN0ZWQgX3RyYW5zZm9ybUludmVyc2VzOiBEaWN0PFJlY29yZE9wZXJhdGlvbltdPjtcblxuICBjb25zdHJ1Y3RvcihzZXR0aW5nczogTWVtb3J5U291cmNlU2V0dGluZ3M8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPikge1xuICAgIGNvbnN0IHsga2V5TWFwLCBzY2hlbWEsIGJhc2UgfSA9IHNldHRpbmdzO1xuXG4gICAgc2V0dGluZ3MubmFtZSA9IHNldHRpbmdzLm5hbWUgPz8gJ21lbW9yeSc7XG5cbiAgICBzdXBlcihzZXR0aW5ncyk7XG5cbiAgICB0aGlzLl90cmFuc2Zvcm1zID0ge307XG4gICAgdGhpcy5fdHJhbnNmb3JtSW52ZXJzZXMgPSB7fTtcblxuICAgIHRoaXMudHJhbnNmb3JtTG9nLm9uKCdjbGVhcicsIHRoaXMuX2xvZ0NsZWFyZWQuYmluZCh0aGlzKSk7XG4gICAgdGhpcy50cmFuc2Zvcm1Mb2cub24oJ3RydW5jYXRlJywgdGhpcy5fbG9nVHJ1bmNhdGVkLmJpbmQodGhpcykpO1xuICAgIHRoaXMudHJhbnNmb3JtTG9nLm9uKCdyb2xsYmFjaycsIHRoaXMuX2xvZ1JvbGxlZGJhY2suYmluZCh0aGlzKSk7XG5cbiAgICBsZXQgY2FjaGVTZXR0aW5nczogUGFydGlhbDxNZW1vcnlDYWNoZVNldHRpbmdzPFFPLCBUTywgUUIsIFRCLCBRUkQsIFRSRD4+ID1cbiAgICAgIHNldHRpbmdzLmNhY2hlU2V0dGluZ3MgPz8ge307XG4gICAgY2FjaGVTZXR0aW5ncy5zY2hlbWEgPSBzY2hlbWE7XG4gICAgY2FjaGVTZXR0aW5ncy5rZXlNYXAgPSBrZXlNYXA7XG4gICAgY2FjaGVTZXR0aW5ncy5xdWVyeUJ1aWxkZXIgPz89IHRoaXMucXVlcnlCdWlsZGVyO1xuICAgIGNhY2hlU2V0dGluZ3MudHJhbnNmb3JtQnVpbGRlciA/Pz0gdGhpcy50cmFuc2Zvcm1CdWlsZGVyO1xuICAgIGNhY2hlU2V0dGluZ3MuZGVmYXVsdFF1ZXJ5T3B0aW9ucyA/Pz0gdGhpcy5kZWZhdWx0UXVlcnlPcHRpb25zO1xuICAgIGNhY2hlU2V0dGluZ3MuZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnMgPz89IHRoaXMuZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnM7XG4gICAgY2FjaGVTZXR0aW5ncy5hdXRvVmFsaWRhdGUgPz89IHNldHRpbmdzLmF1dG9WYWxpZGF0ZTtcblxuICAgIGlmIChcbiAgICAgIGNhY2hlU2V0dGluZ3MuYXV0b1ZhbGlkYXRlICE9PSBmYWxzZSAmJlxuICAgICAgY2FjaGVTZXR0aW5ncy52YWxpZGF0b3JGb3IgPT09IHVuZGVmaW5lZCAmJlxuICAgICAgY2FjaGVTZXR0aW5ncy52YWxpZGF0b3JzID09PSB1bmRlZmluZWRcbiAgICApIHtcbiAgICAgIGNhY2hlU2V0dGluZ3MudmFsaWRhdG9yRm9yID0gdGhpcy5fdmFsaWRhdG9yRm9yO1xuICAgIH1cblxuICAgIGlmIChiYXNlKSB7XG4gICAgICB0aGlzLl9iYXNlID0gYmFzZTtcbiAgICAgIHRoaXMuX2ZvcmtQb2ludCA9IGJhc2UudHJhbnNmb3JtTG9nLmhlYWQ7XG4gICAgICBjYWNoZVNldHRpbmdzLmJhc2UgPSBiYXNlLmNhY2hlO1xuICAgIH1cblxuICAgIGNvbnN0IGNhY2hlQ2xhc3MgPSBzZXR0aW5ncy5jYWNoZUNsYXNzID8/IE1lbW9yeUNhY2hlO1xuICAgIHRoaXMuX2NhY2hlID0gbmV3IGNhY2hlQ2xhc3MoXG4gICAgICBjYWNoZVNldHRpbmdzIGFzIE1lbW9yeUNhY2hlU2V0dGluZ3M8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPlxuICAgICk7XG4gIH1cblxuICBnZXQgY2FjaGUoKTogTWVtb3J5Q2FjaGU8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPiB7XG4gICAgcmV0dXJuIHRoaXMuX2NhY2hlO1xuICB9XG5cbiAgZ2V0IGJhc2UoKTogTWVtb3J5U291cmNlPFFPLCBUTywgUUIsIFRCLCBRUkQsIFRSRD4gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9iYXNlO1xuICB9XG5cbiAgZ2V0IGZvcmtQb2ludCgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9mb3JrUG9pbnQ7XG4gIH1cblxuICBhc3luYyB1cGdyYWRlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuX2NhY2hlLnVwZ3JhZGUoKTtcbiAgfVxuXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gIC8vIFN5bmNhYmxlIGludGVyZmFjZSBpbXBsZW1lbnRhdGlvblxuICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gIGFzeW5jIF9zeW5jKHRyYW5zZm9ybTogUmVjb3JkVHJhbnNmb3JtKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLnRyYW5zZm9ybUxvZy5jb250YWlucyh0cmFuc2Zvcm0uaWQpKSB7XG4gICAgICB0aGlzLl9hcHBseVRyYW5zZm9ybSh0cmFuc2Zvcm0pO1xuICAgICAgYXdhaXQgdGhpcy50cmFuc2Zvcm1lZChbdHJhbnNmb3JtXSk7XG4gICAgfVxuICB9XG5cbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgLy8gVXBkYXRhYmxlIGludGVyZmFjZSBpbXBsZW1lbnRhdGlvblxuICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gIGFzeW5jIF91cGRhdGUoXG4gICAgdHJhbnNmb3JtOiBSZWNvcmRUcmFuc2Zvcm0sXG4gICAgaGludHM/OiBSZXNwb25zZUhpbnRzPFJlY29yZFRyYW5zZm9ybVJlc3VsdCwgVFJEPlxuICApOiBQcm9taXNlPEZ1bGxSZXNwb25zZTxSZWNvcmRUcmFuc2Zvcm1SZXN1bHQsIFRSRCwgUmVjb3JkT3BlcmF0aW9uPj4ge1xuICAgIGxldCByZXN1bHRzOiBSZWNvcmRUcmFuc2Zvcm1SZXN1bHQ7XG4gICAgY29uc3QgcmVzcG9uc2U6IEZ1bGxSZXNwb25zZTxcbiAgICAgIFJlY29yZFRyYW5zZm9ybVJlc3VsdCxcbiAgICAgIFRSRCxcbiAgICAgIFJlY29yZE9wZXJhdGlvblxuICAgID4gPSB7fTtcblxuICAgIGlmICghdGhpcy50cmFuc2Zvcm1Mb2cuY29udGFpbnModHJhbnNmb3JtLmlkKSkge1xuICAgICAgcmVzdWx0cyA9IHRoaXMuX2FwcGx5VHJhbnNmb3JtKHRyYW5zZm9ybSk7XG4gICAgICByZXNwb25zZS50cmFuc2Zvcm1zID0gW3RyYW5zZm9ybV07XG4gICAgfVxuXG4gICAgaWYgKGhpbnRzPy5kYXRhKSB7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh0cmFuc2Zvcm0ub3BlcmF0aW9ucykpIHtcbiAgICAgICAgYXNzZXJ0KFxuICAgICAgICAgICdNZW1vcnlTb3VyY2UjdXBkYXRlOiBgaGludHMuZGF0YWAgbXVzdCBiZSBhbiBhcnJheSBpZiBgdHJhbnNmb3JtLm9wZXJhdGlvbnNgIGlzIGFuIGFycmF5JyxcbiAgICAgICAgICBBcnJheS5pc0FycmF5KGhpbnRzLmRhdGEpXG4gICAgICAgICk7XG5cbiAgICAgICAgcmVzcG9uc2UuZGF0YSA9IChoaW50cy5kYXRhIGFzIFJlY29yZE9wZXJhdGlvblJlc3VsdFtdKS5tYXAoKGgpID0+XG4gICAgICAgICAgdGhpcy5fcmV0cmlldmVPcGVyYXRpb25SZXN1bHQoaClcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3BvbnNlLmRhdGEgPSB0aGlzLl9yZXRyaWV2ZU9wZXJhdGlvblJlc3VsdChcbiAgICAgICAgICBoaW50cy5kYXRhIGFzIFJlY29yZE9wZXJhdGlvblJlc3VsdFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocmVzdWx0cykge1xuICAgICAgcmVzcG9uc2UuZGF0YSA9IHJlc3VsdHM7XG4gICAgfVxuXG4gICAgaWYgKGhpbnRzPy5kZXRhaWxzKSB7XG4gICAgICByZXNwb25zZS5kZXRhaWxzID0gaGludHMuZGV0YWlscztcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzcG9uc2U7XG4gIH1cblxuICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAvLyBRdWVyeWFibGUgaW50ZXJmYWNlIGltcGxlbWVudGF0aW9uXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbiAgYXN5bmMgX3F1ZXJ5KFxuICAgIHF1ZXJ5OiBSZWNvcmRRdWVyeSxcbiAgICBoaW50cz86IFJlc3BvbnNlSGludHM8UmVjb3JkUXVlcnlSZXN1bHQsIFFSRD5cbiAgKTogUHJvbWlzZTxGdWxsUmVzcG9uc2U8UmVjb3JkUXVlcnlSZXN1bHQsIFFSRCwgUmVjb3JkT3BlcmF0aW9uPj4ge1xuICAgIGxldCByZXNwb25zZTogRnVsbFJlc3BvbnNlPFJlY29yZFF1ZXJ5UmVzdWx0LCBRUkQsIFJlY29yZE9wZXJhdGlvbj47XG5cbiAgICBpZiAoaGludHM/LmRhdGEpIHtcbiAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShxdWVyeS5leHByZXNzaW9ucykpIHtcbiAgICAgICAgYXNzZXJ0KFxuICAgICAgICAgICdNZW1vcnlTb3VyY2UjcXVlcnk6IGBoaW50cy5kYXRhYCBtdXN0IGJlIGFuIGFycmF5IGlmIGBxdWVyeS5leHByZXNzaW9uc2AgaXMgYW4gYXJyYXknLFxuICAgICAgICAgIEFycmF5LmlzQXJyYXkoaGludHMuZGF0YSlcbiAgICAgICAgKTtcblxuICAgICAgICByZXNwb25zZS5kYXRhID0gKGhpbnRzLmRhdGEgYXMgUmVjb3JkUXVlcnlFeHByZXNzaW9uUmVzdWx0W10pLm1hcCgoaCkgPT5cbiAgICAgICAgICB0aGlzLl9yZXRyaWV2ZVF1ZXJ5RXhwcmVzc2lvblJlc3VsdChoKVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzcG9uc2UuZGF0YSA9IHRoaXMuX3JldHJpZXZlUXVlcnlFeHByZXNzaW9uUmVzdWx0KFxuICAgICAgICAgIGhpbnRzLmRhdGEgYXMgUmVjb3JkUXVlcnlFeHByZXNzaW9uUmVzdWx0XG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3BvbnNlID0gdGhpcy5fY2FjaGUucXVlcnkocXVlcnksIHtcbiAgICAgICAgZnVsbFJlc3BvbnNlOiB0cnVlXG4gICAgICB9IGFzIEZ1bGxSZXF1ZXN0T3B0aW9uczxRTz4pO1xuICAgIH1cblxuICAgIGlmIChoaW50cz8uZGV0YWlscykge1xuICAgICAgcmVzcG9uc2UuZGV0YWlscyA9IGhpbnRzLmRldGFpbHM7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3BvbnNlO1xuICB9XG5cbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgLy8gUHVibGljIG1ldGhvZHNcbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICAvKipcbiAgICogQ3JlYXRlIGEgY2xvbmUsIG9yIFwiZm9ya1wiLCBmcm9tIGEgXCJiYXNlXCIgc291cmNlLlxuICAgKlxuICAgKiBUaGUgZm9ya2VkIHNvdXJjZSB3aWxsIGhhdmUgdGhlIHNhbWUgYHNjaGVtYWAgYW5kIGBrZXlNYXBgIGFzIGl0cyBiYXNlIHNvdXJjZS5cbiAgICogVGhlIGZvcmtlZCBzb3VyY2UncyBjYWNoZSB3aWxsIHN0YXJ0IHdpdGggdGhlIHNhbWUgaW1tdXRhYmxlIGRvY3VtZW50IGFzXG4gICAqIHRoZSBiYXNlIHNvdXJjZS4gSXRzIGNvbnRlbnRzIGFuZCBsb2cgd2lsbCBldm9sdmUgaW5kZXBlbmRlbnRseS5cbiAgICpcbiAgICogQHJldHVybnMgVGhlIGZvcmtlZCBzb3VyY2UuXG4gICAqL1xuICBmb3JrKFxuICAgIHNldHRpbmdzOiBQYXJ0aWFsPE1lbW9yeVNvdXJjZVNldHRpbmdzPFFPLCBUTywgUUIsIFRCLCBRUkQsIFRSRD4+ID0ge31cbiAgKTogTWVtb3J5U291cmNlPFFPLCBUTywgUUIsIFRCLCBRUkQsIFRSRD4ge1xuICAgIC8vIHJlcXVpcmVkIHNldHRpbmdzXG4gICAgc2V0dGluZ3MuYmFzZSA9IHRoaXM7XG4gICAgc2V0dGluZ3Muc2NoZW1hID0gdGhpcy5zY2hlbWE7XG4gICAgc2V0dGluZ3Mua2V5TWFwID0gdGhpcy5rZXlNYXA7XG5cbiAgICAvLyBjdXN0b21pemFibGUgc2V0dGluZ3NcbiAgICBzZXR0aW5ncy5xdWVyeUJ1aWxkZXIgPz89IHRoaXMuX3F1ZXJ5QnVpbGRlcjtcbiAgICBzZXR0aW5ncy50cmFuc2Zvcm1CdWlsZGVyID8/PSB0aGlzLl90cmFuc2Zvcm1CdWlsZGVyO1xuICAgIHNldHRpbmdzLmRlZmF1bHRRdWVyeU9wdGlvbnMgPz89IHRoaXMuX2RlZmF1bHRRdWVyeU9wdGlvbnM7XG4gICAgc2V0dGluZ3MuZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnMgPz89IHRoaXMuX2RlZmF1bHRUcmFuc2Zvcm1PcHRpb25zO1xuICAgIGlmIChzZXR0aW5ncy5hdXRvVmFsaWRhdGUgIT09IGZhbHNlKSB7XG4gICAgICBzZXR0aW5ncy52YWxpZGF0b3JGb3IgPz89IHRoaXMuX3ZhbGlkYXRvckZvcjtcbiAgICAgIGlmIChcbiAgICAgICAgc2V0dGluZ3MuYXV0b1ZhbGlkYXRlID09PSB1bmRlZmluZWQgJiZcbiAgICAgICAgc2V0dGluZ3MudmFsaWRhdG9yRm9yID09PSB1bmRlZmluZWRcbiAgICAgICkge1xuICAgICAgICBzZXR0aW5ncy5hdXRvVmFsaWRhdGUgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IE1lbW9yeVNvdXJjZTxRTywgVE8sIFFCLCBUQiwgUVJELCBUUkQ+KFxuICAgICAgc2V0dGluZ3MgYXMgTWVtb3J5U291cmNlU2V0dGluZ3M8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPlxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogTWVyZ2UgdHJhbnNmb3JtcyBmcm9tIGEgZm9ya2VkIHNvdXJjZSBiYWNrIGludG8gYSBiYXNlIHNvdXJjZS5cbiAgICpcbiAgICogQnkgZGVmYXVsdCwgYWxsIG9mIHRoZSBvcGVyYXRpb25zIGZyb20gYWxsIG9mIHRoZSB0cmFuc2Zvcm1zIGluIHRoZSBmb3JrZWRcbiAgICogc291cmNlJ3MgaGlzdG9yeSB3aWxsIGJlIHJlZHVjZWQgaW50byBhIHNpbmdsZSB0cmFuc2Zvcm0uIEEgc3Vic2V0IG9mXG4gICAqIG9wZXJhdGlvbnMgY2FuIGJlIHNlbGVjdGVkIGJ5IHNwZWNpZnlpbmcgdGhlIGBzaW5jZVRyYW5zZm9ybUlkYCBvcHRpb24uXG4gICAqXG4gICAqIFRoZSBgY29hbGVzY2VgIG9wdGlvbiBjb250cm9scyB3aGV0aGVyIG9wZXJhdGlvbnMgYXJlIGNvYWxlc2NlZCBpbnRvIGFcbiAgICogbWluaW1hbCBlcXVpdmFsZW50IHNldCBiZWZvcmUgYmVpbmcgcmVkdWNlZCBpbnRvIGEgdHJhbnNmb3JtLlxuICAgKlxuICAgKiBAcGFyYW0gZm9ya2VkU291cmNlIC0gVGhlIHNvdXJjZSB0byBtZXJnZS5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBNZXJnZSBvcHRpb25zXG4gICAqIEByZXR1cm5zIFRoZSByZXN1bHQgb2YgY2FsbGluZyBgdXBkYXRlKClgIHdpdGggdGhlIGZvcmtlZCB0cmFuc2Zvcm1zLlxuICAgKi9cbiAgbWVyZ2U8UmVxdWVzdERhdGEgZXh0ZW5kcyBSZWNvcmRUcmFuc2Zvcm1SZXN1bHQgPSBSZWNvcmRUcmFuc2Zvcm1SZXN1bHQ+KFxuICAgIGZvcmtlZFNvdXJjZTogTWVtb3J5U291cmNlPFFPLCBUTywgUUIsIFRCLCBRUkQsIFRSRD4sXG4gICAgb3B0aW9ucz86IERlZmF1bHRSZXF1ZXN0T3B0aW9uczxUTz4gJiBNZW1vcnlTb3VyY2VNZXJnZU9wdGlvbnNcbiAgKTogUHJvbWlzZTxSZXF1ZXN0RGF0YT47XG4gIG1lcmdlPFJlcXVlc3REYXRhIGV4dGVuZHMgUmVjb3JkVHJhbnNmb3JtUmVzdWx0ID0gUmVjb3JkVHJhbnNmb3JtUmVzdWx0PihcbiAgICBmb3JrZWRTb3VyY2U6IE1lbW9yeVNvdXJjZTxRTywgVE8sIFFCLCBUQiwgUVJELCBUUkQ+LFxuICAgIG9wdGlvbnM6IEZ1bGxSZXF1ZXN0T3B0aW9uczxUTz4gJiBNZW1vcnlTb3VyY2VNZXJnZU9wdGlvbnNcbiAgKTogUHJvbWlzZTxGdWxsUmVzcG9uc2U8UmVxdWVzdERhdGEsIFRSRCwgUmVjb3JkT3BlcmF0aW9uPj47XG4gIGFzeW5jIG1lcmdlPFxuICAgIFJlcXVlc3REYXRhIGV4dGVuZHMgUmVjb3JkVHJhbnNmb3JtUmVzdWx0ID0gUmVjb3JkVHJhbnNmb3JtUmVzdWx0XG4gID4oXG4gICAgZm9ya2VkU291cmNlOiBNZW1vcnlTb3VyY2U8UU8sIFRPLCBRQiwgVEIsIFFSRCwgVFJEPixcbiAgICBvcHRpb25zPzogVE8gJiBNZW1vcnlTb3VyY2VNZXJnZU9wdGlvbnNcbiAgKTogUHJvbWlzZTxcbiAgICBSZWNvcmRUcmFuc2Zvcm1SZXN1bHQgfCBGdWxsUmVzcG9uc2U8UmVxdWVzdERhdGEsIFRSRCwgUmVjb3JkT3BlcmF0aW9uPlxuICA+IHtcbiAgICBsZXQgeyBjb2FsZXNjZSwgc2luY2VUcmFuc2Zvcm1JZCwgdHJhbnNmb3JtT3B0aW9ucywgLi4ucmVtYWluaW5nT3B0aW9ucyB9ID1cbiAgICAgIG9wdGlvbnMgPz8ge307XG5cbiAgICBsZXQgcmVxdWVzdE9wdGlvbnM6IFRPO1xuICAgIGlmICh0cmFuc2Zvcm1PcHRpb25zKSB7XG4gICAgICBkZXByZWNhdGUoXG4gICAgICAgICdJbiBNZW1vcnlTb3VyY2UjbWVyZ2UsIHBhc3NpbmcgYHRyYW5zZm9ybU9wdGlvbnNgIG5lc3RlZCB3aXRoaW4gYG9wdGlvbnNgIGlzIGRlcHJlY2F0ZWQuIEluc3RlYWQsIGluY2x1ZGUgdGhlbSBkaXJlY3RseSBhbG9uZ3NpZGUgb3RoZXIgb3B0aW9ucy4nXG4gICAgICApO1xuICAgICAgcmVxdWVzdE9wdGlvbnMgPSB0cmFuc2Zvcm1PcHRpb25zIGFzIFRPO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXF1ZXN0T3B0aW9ucyA9IChyZW1haW5pbmdPcHRpb25zID8/IHt9KSBhcyBUTztcbiAgICB9XG5cbiAgICBsZXQgb3BzOiBSZWNvcmRPcGVyYXRpb25bXSA9IFtdO1xuXG4gICAgaWYgKGZvcmtlZFNvdXJjZS5jYWNoZS5pc1RyYWNraW5nVXBkYXRlT3BlcmF0aW9ucykge1xuICAgICAgb3BzID0gZm9ya2VkU291cmNlLmNhY2hlLmdldEFsbFVwZGF0ZU9wZXJhdGlvbnMoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHRyYW5zZm9ybXM6IFJlY29yZFRyYW5zZm9ybVtdO1xuICAgICAgaWYgKHNpbmNlVHJhbnNmb3JtSWQpIHtcbiAgICAgICAgZGVwcmVjYXRlKFxuICAgICAgICAgICdJbiBNZW1vcnlTb3VyY2UjbWVyZ2UsIHBhc3NpbmcgYHNpbmNlVHJhbnNmb3JtSWRgIGlzIGRlcHJlY2F0ZWQuIEluc3RlYWQsIGNhbGwgYHVwZGF0ZWAgd2l0aCBhIGN1c3RvbSB0cmFuc2Zvcm0vb3BlcmF0aW9ucy4nXG4gICAgICAgICk7XG4gICAgICAgIHRyYW5zZm9ybXMgPSBmb3JrZWRTb3VyY2UuZ2V0VHJhbnNmb3Jtc1NpbmNlKHNpbmNlVHJhbnNmb3JtSWQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJhbnNmb3JtcyA9IGZvcmtlZFNvdXJjZS5nZXRBbGxUcmFuc2Zvcm1zKCk7XG4gICAgICB9XG5cbiAgICAgIHRyYW5zZm9ybXMuZm9yRWFjaCgodCkgPT4ge1xuICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvcHMsIHRvQXJyYXkodC5vcGVyYXRpb25zKSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoY29hbGVzY2UgIT09IGZhbHNlKSB7XG4gICAgICBvcHMgPSBjb2FsZXNjZVJlY29yZE9wZXJhdGlvbnMob3BzKTtcbiAgICB9XG5cbiAgICBpZiAocmVxdWVzdE9wdGlvbnMuZnVsbFJlc3BvbnNlKSB7XG4gICAgICByZXR1cm4gdGhpcy51cGRhdGU8UmVxdWVzdERhdGE+KFxuICAgICAgICBvcHMsXG4gICAgICAgIHJlcXVlc3RPcHRpb25zIGFzIEZ1bGxSZXF1ZXN0T3B0aW9uczxUTz5cbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLnVwZGF0ZTxSZXF1ZXN0RGF0YT4oXG4gICAgICAgIG9wcyxcbiAgICAgICAgcmVxdWVzdE9wdGlvbnMgYXMgRGVmYXVsdFJlcXVlc3RPcHRpb25zPFRPPlxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmViYXNlIHdvcmtzIHNpbWlsYXJseSB0byBhIGdpdCByZWJhc2U6XG4gICAqXG4gICAqIEFmdGVyIGEgc291cmNlIGlzIGZvcmtlZCwgdGhlcmUgaXMgYSBwYXJlbnQtIGFuZCBhIGNoaWxkLXNvdXJjZS4gQm90aCBtYXlcbiAgICogYmUgdXBkYXRlZCB3aXRoIHRyYW5zZm9ybXMuIFdoZW4gYGNoaWxkU291cmNlLnJlYmFzZSgpYCBpcyBjYWxsZWQsIHRoZVxuICAgKiBjaGlsZCBzb3VyY2UncyBzdGF0ZSB3aWxsIGJlIHJlc2V0IHRvIG1hdGNoIHRoZSBjdXJyZW50IHN0YXRlIG9mIGl0c1xuICAgKiBwYXJlbnQsIGFuZCB0aGVuIGFueSBsb2NhbGx5IG1hZGUgdHJhbnNmb3JtcyB3aWxsIGJlIHJlcGxheWVkIG9uIHRoZSBjaGlsZFxuICAgKiBzb3VyY2UuXG4gICAqL1xuICByZWJhc2UoKTogdm9pZCB7XG4gICAgY29uc3QgYmFzZSA9IHRoaXMuX2Jhc2U7XG5cbiAgICBpZiAoIWJhc2UpIHtcbiAgICAgIHRocm93IG5ldyBBc3NlcnRpb24oXG4gICAgICAgICdBIGBiYXNlYCBzb3VyY2UgbXVzdCBiZSBkZWZpbmVkIGZvciBgcmViYXNlYCB0byB3b3JrJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyByZXNldCB0aGUgc3RhdGUgb2YgdGhlIGNhY2hlIHRvIG1hdGNoIHRoZSBiYXNlIGNhY2hlXG4gICAgdGhpcy5jYWNoZS5yZXNldCgpO1xuXG4gICAgLy8gcmVwbGF5IGFsbCBsb2NhbGx5IG1hZGUgdHJhbnNmb3Jtc1xuICAgIHRoaXMuZ2V0QWxsVHJhbnNmb3JtcygpLmZvckVhY2goKHQpID0+IHRoaXMuX2FwcGx5VHJhbnNmb3JtKHQpKTtcblxuICAgIC8vIHJlc2V0IHRoZSBmb3JrIHBvaW50XG4gICAgdGhpcy5fZm9ya1BvaW50ID0gYmFzZS50cmFuc2Zvcm1Mb2cuaGVhZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldCB0aGUgc291cmNlJ3MgY2FjaGUgYW5kIHRyYW5zZm9ybSBsb2cgdG8gaXRzIGluaXRpYWwgc3RhdGUsIHdoaWNoIHdpbGxcbiAgICogYmUgZWl0aGVyIGVtcHR5IG9yIGEgbWF0Y2hpbmcgaXRzIGBiYXNlYCwgaWYgaXQgaGFzIG9uZS5cbiAgICovXG4gIGFzeW5jIHJlc2V0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIHJlc2V0IHRoZSBzdGF0ZSBvZiB0aGUgY2FjaGUgKHdoaWNoIHdpbGwgbWF0Y2ggYSBiYXNlIGNhY2hlLCBpZiBwcmVzZW50KVxuICAgIHRoaXMuY2FjaGUucmVzZXQoKTtcblxuICAgIC8vIHJlc2V0IHRoZSBmb3JrIHBvaW50XG4gICAgdGhpcy5fZm9ya1BvaW50ID0gdGhpcy5fYmFzZSA/IHRoaXMuX2Jhc2UudHJhbnNmb3JtTG9nLmhlYWQgOiB1bmRlZmluZWQ7XG5cbiAgICAvLyBjbGVhciB0aGUgdHJhbnNmb3JtIGxvZywgd2hpY2ggaW4gdHVybiB3aWxsIGNsZWFyIGFueSB0cmFja2VkIHRyYW5zZm9ybXNcbiAgICBhd2FpdCB0aGlzLnRyYW5zZm9ybUxvZy5jbGVhcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJvbGxzIGJhY2sgdGhlIHNvdXJjZSB0byBhIHBhcnRpY3VsYXIgYHRyYW5zZm9ybUlkYC5cbiAgICpcbiAgICogYHJlbGF0aXZlUG9zaXRpb25gIGNhbiBiZSBhIHBvc2l0aXZlIG9yIG5lZ2F0aXZlIGludGVnZXIgdXNlZCB0byBzcGVjaWZ5IGFcbiAgICogcG9zaXRpb24gcmVsYXRpdmUgdG8gYHRyYW5zZm9ybUlkYC5cbiAgICovXG4gIHJvbGxiYWNrKHRyYW5zZm9ybUlkOiBzdHJpbmcsIHJlbGF0aXZlUG9zaXRpb24gPSAwKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMudHJhbnNmb3JtTG9nLnJvbGxiYWNrKHRyYW5zZm9ybUlkLCByZWxhdGl2ZVBvc2l0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFsbCBsb2dnZWQgdHJhbnNmb3JtcyBzaW5jZSBhIHBhcnRpY3VsYXIgYHRyYW5zZm9ybUlkYC5cbiAgICovXG4gIGdldFRyYW5zZm9ybXNTaW5jZSh0cmFuc2Zvcm1JZDogc3RyaW5nKTogUmVjb3JkVHJhbnNmb3JtW10ge1xuICAgIHJldHVybiB0aGlzLnRyYW5zZm9ybUxvZ1xuICAgICAgLmFmdGVyKHRyYW5zZm9ybUlkKVxuICAgICAgLm1hcCgoaWQpID0+IHRoaXMuX3RyYW5zZm9ybXNbaWRdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVwcmVjYXRlZCBzaW5jZSB2MC4xNywgY2FsbCBgZ2V0VHJhbnNmb3Jtc1NpbmNlYCBpbnN0ZWFkXG4gICAqL1xuICB0cmFuc2Zvcm1zU2luY2UodHJhbnNmb3JtSWQ6IHN0cmluZyk6IFJlY29yZFRyYW5zZm9ybVtdIHtcbiAgICBkZXByZWNhdGUoXG4gICAgICAnTWVtb3J5U291cmNlI3RyYW5zZm9ybXNTaW5jZSBoYXMgYmVlbiBkZXByZWNhdGVkLiBQbGVhc2UgY2FsbCBgc291cmNlLmdldFRyYW5zZm9ybXNTaW5jZSh0cmFuZm9ybUlkKWAgaW5zdGVhZC4nXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5nZXRUcmFuc2Zvcm1zU2luY2UodHJhbnNmb3JtSWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYWxsIGxvZ2dlZCB0cmFuc2Zvcm1zLlxuICAgKi9cbiAgZ2V0QWxsVHJhbnNmb3JtcygpOiBSZWNvcmRUcmFuc2Zvcm1bXSB7XG4gICAgcmV0dXJuIHRoaXMudHJhbnNmb3JtTG9nLmVudHJpZXMubWFwKChpZCkgPT4gdGhpcy5fdHJhbnNmb3Jtc1tpZF0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIHNpbmNlIHYwLjE3LCBjYWxsIGBnZXRBbGxUcmFuc2Zvcm1zYCBpbnN0ZWFkXG4gICAqL1xuICBhbGxUcmFuc2Zvcm1zKCk6IFJlY29yZFRyYW5zZm9ybVtdIHtcbiAgICBkZXByZWNhdGUoXG4gICAgICAnTWVtb3J5U291cmNlI2FsbFRyYW5zZm9ybXMgaGFzIGJlZW4gZGVwcmVjYXRlZC4gUGxlYXNlIGNhbGwgYHNvdXJjZS5nZXRBbGxUcmFuc2Zvcm1zKClgIGluc3RlYWQuJ1xuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QWxsVHJhbnNmb3JtcygpO1xuICB9XG5cbiAgZ2V0VHJhbnNmb3JtKHRyYW5zZm9ybUlkOiBzdHJpbmcpOiBSZWNvcmRUcmFuc2Zvcm0ge1xuICAgIHJldHVybiB0aGlzLl90cmFuc2Zvcm1zW3RyYW5zZm9ybUlkXTtcbiAgfVxuXG4gIGdldEludmVyc2VPcGVyYXRpb25zKHRyYW5zZm9ybUlkOiBzdHJpbmcpOiBSZWNvcmRPcGVyYXRpb25bXSB7XG4gICAgcmV0dXJuIHRoaXMuX3RyYW5zZm9ybUludmVyc2VzW3RyYW5zZm9ybUlkXTtcbiAgfVxuXG4gIGdldCBkZWZhdWx0UXVlcnlPcHRpb25zKCk6IERlZmF1bHRSZXF1ZXN0T3B0aW9uczxRTz4gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiBzdXBlci5kZWZhdWx0UXVlcnlPcHRpb25zO1xuICB9XG5cbiAgc2V0IGRlZmF1bHRRdWVyeU9wdGlvbnMob3B0aW9uczogRGVmYXVsdFJlcXVlc3RPcHRpb25zPFFPPiB8IHVuZGVmaW5lZCkge1xuICAgIHN1cGVyLmRlZmF1bHRRdWVyeU9wdGlvbnMgPSB0aGlzLl9jYWNoZS5kZWZhdWx0UXVlcnlPcHRpb25zID0gb3B0aW9ucztcbiAgfVxuXG4gIGdldCBkZWZhdWx0VHJhbnNmb3JtT3B0aW9ucygpOiBEZWZhdWx0UmVxdWVzdE9wdGlvbnM8VE8+IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gc3VwZXIuZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnM7XG4gIH1cblxuICBzZXQgZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnMob3B0aW9uczogRGVmYXVsdFJlcXVlc3RPcHRpb25zPFRPPiB8IHVuZGVmaW5lZCkge1xuICAgIHRoaXMuX2RlZmF1bHRUcmFuc2Zvcm1PcHRpb25zID0gdGhpcy5fY2FjaGUuZGVmYXVsdFRyYW5zZm9ybU9wdGlvbnMgPSBvcHRpb25zO1xuICB9XG5cbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgLy8gUHJvdGVjdGVkIG1ldGhvZHNcbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICBwcm90ZWN0ZWQgX3JldHJpZXZlUXVlcnlFeHByZXNzaW9uUmVzdWx0KFxuICAgIHJlc3VsdDogUmVjb3JkUXVlcnlFeHByZXNzaW9uUmVzdWx0XG4gICk6IFJlY29yZFF1ZXJ5RXhwcmVzc2lvblJlc3VsdCB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkocmVzdWx0KSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2NhY2hlLmdldFJlY29yZHNTeW5jKHJlc3VsdCk7XG4gICAgfSBlbHNlIGlmIChyZXN1bHQpIHtcbiAgICAgIHJldHVybiB0aGlzLl9jYWNoZS5nZXRSZWNvcmRTeW5jKHJlc3VsdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIF9yZXRyaWV2ZU9wZXJhdGlvblJlc3VsdChcbiAgICByZXN1bHQ6IFJlY29yZE9wZXJhdGlvblJlc3VsdFxuICApOiBSZWNvcmRPcGVyYXRpb25SZXN1bHQge1xuICAgIGlmIChyZXN1bHQpIHtcbiAgICAgIHJldHVybiB0aGlzLl9jYWNoZS5nZXRSZWNvcmRTeW5jKHJlc3VsdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIF9hcHBseVRyYW5zZm9ybSh0cmFuc2Zvcm06IFJlY29yZFRyYW5zZm9ybSk6IFJlY29yZFRyYW5zZm9ybVJlc3VsdCB7XG4gICAgY29uc3QgeyBkYXRhLCBkZXRhaWxzIH0gPSB0aGlzLmNhY2hlLnVwZGF0ZSh0cmFuc2Zvcm0sIHtcbiAgICAgIGZ1bGxSZXNwb25zZTogdHJ1ZVxuICAgIH0gYXMgRnVsbFJlcXVlc3RPcHRpb25zPFRPPik7XG4gICAgdGhpcy5fdHJhbnNmb3Jtc1t0cmFuc2Zvcm0uaWRdID0gdHJhbnNmb3JtO1xuICAgIHRoaXMuX3RyYW5zZm9ybUludmVyc2VzW3RyYW5zZm9ybS5pZF0gPSBkZXRhaWxzPy5pbnZlcnNlT3BlcmF0aW9ucyA/PyBbXTtcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuXG4gIHByb3RlY3RlZCBfY2xlYXJUcmFuc2Zvcm1Gcm9tSGlzdG9yeSh0cmFuc2Zvcm1JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgZGVsZXRlIHRoaXMuX3RyYW5zZm9ybXNbdHJhbnNmb3JtSWRdO1xuICAgIGRlbGV0ZSB0aGlzLl90cmFuc2Zvcm1JbnZlcnNlc1t0cmFuc2Zvcm1JZF07XG4gIH1cblxuICBwcm90ZWN0ZWQgX2xvZ0NsZWFyZWQoKTogdm9pZCB7XG4gICAgdGhpcy5fdHJhbnN