@orbit/records
Version:
A flexible data access and synchronization layer.
317 lines • 50.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.recordsReferencedByOperations = exports.recordDiffs = exports.coalesceRecordOperations = void 0;
const utils_1 = require("@orbit/utils");
const record_1 = require("./record");
function markOperationToDelete(operation) {
const o = operation;
o._deleted = true;
}
function isOperationMarkedToDelete(operation) {
const o = operation;
return o._deleted === true;
}
function mergeOperations(superceded, superceding, consecutiveOps) {
var _a, _b, _c, _d;
if (superceded.options || superceding.options) {
// do not merge if one of the operations have options
return;
}
else if ((0, record_1.equalRecordIdentities)(superceded.record, superceding.record)) {
if (superceding.op === 'removeRecord') {
markOperationToDelete(superceded);
if (superceded.op === 'addRecord') {
markOperationToDelete(superceding);
}
}
else if (!isOperationMarkedToDelete(superceding) &&
(consecutiveOps || superceding.op === 'replaceAttribute')) {
if (isReplaceFieldOp(superceded.op) && isReplaceFieldOp(superceding.op)) {
if (superceded.op === 'replaceAttribute' &&
superceding.op === 'replaceAttribute' &&
superceded.attribute === superceding.attribute) {
markOperationToDelete(superceded);
}
else if (superceded.op === 'replaceRelatedRecord' &&
superceding.op === 'replaceRelatedRecord' &&
superceded.relationship === superceding.relationship) {
markOperationToDelete(superceded);
}
else if (superceded.op === 'replaceRelatedRecords' &&
superceding.op === 'replaceRelatedRecords' &&
superceded.relationship === superceding.relationship) {
markOperationToDelete(superceded);
}
else {
if (superceded.op === 'replaceAttribute') {
updateRecordReplaceAttribute(superceded.record, superceded.attribute, superceded.value);
delete superceded.attribute;
delete superceded.value;
}
else if (superceded.op === 'replaceRelatedRecord') {
updateRecordReplaceHasOne(superceded.record, superceded.relationship, superceded.relatedRecord);
delete superceded.relationship;
delete superceded.relatedRecord;
}
else if (superceded.op === 'replaceRelatedRecords') {
updateRecordReplaceHasMany(superceded.record, superceded.relationship, superceded.relatedRecords);
delete superceded.relationship;
delete superceded.relatedRecords;
}
if (superceding.op === 'replaceAttribute') {
updateRecordReplaceAttribute(superceded.record, superceding.attribute, superceding.value);
}
else if (superceding.op === 'replaceRelatedRecord') {
updateRecordReplaceHasOne(superceded.record, superceding.relationship, superceding.relatedRecord);
}
else if (superceding.op === 'replaceRelatedRecords') {
updateRecordReplaceHasMany(superceded.record, superceding.relationship, superceding.relatedRecords);
}
superceded.op = 'updateRecord';
markOperationToDelete(superceding);
}
}
else if ((superceded.op === 'addRecord' ||
superceded.op === 'updateRecord' ||
superceded.op === 'replaceRecord') &&
(superceding.op === 'updateRecord' ||
superceding.op === 'replaceRecord')) {
superceded.record = (0, record_1.mergeRecords)(superceded.record, superceding.record);
markOperationToDelete(superceding);
}
else if ((superceded.op === 'addRecord' ||
superceded.op === 'updateRecord' ||
superceded.op === 'replaceRecord') &&
isReplaceFieldOp(superceding.op)) {
if (superceding.op === 'replaceAttribute') {
updateRecordReplaceAttribute(superceded.record, superceding.attribute, superceding.value);
}
else if (superceding.op === 'replaceRelatedRecord') {
updateRecordReplaceHasOne(superceded.record, superceding.relationship, superceding.relatedRecord);
}
else if (superceding.op === 'replaceRelatedRecords') {
updateRecordReplaceHasMany(superceded.record, superceding.relationship, superceding.relatedRecords);
}
markOperationToDelete(superceding);
}
else if (superceding.op === 'addToRelatedRecords') {
if (superceded.op === 'addRecord') {
updateRecordAddToHasMany(superceded.record, superceding.relationship, superceding.relatedRecord);
markOperationToDelete(superceding);
}
else if (superceded.op === 'updateRecord' ||
superceded.op === 'replaceRecord') {
let record = superceded.record;
if ((_b = (_a = record.relationships) === null || _a === void 0 ? void 0 : _a[superceding.relationship]) === null || _b === void 0 ? void 0 : _b.data) {
updateRecordAddToHasMany(superceded.record, superceding.relationship, superceding.relatedRecord);
markOperationToDelete(superceding);
}
}
}
else if (superceding.op === 'removeFromRelatedRecords') {
if (superceded.op === 'addToRelatedRecords' &&
superceded.relationship === superceding.relationship &&
(0, record_1.equalRecordIdentities)(superceded.relatedRecord, superceding.relatedRecord)) {
markOperationToDelete(superceded);
markOperationToDelete(superceding);
}
else if (superceded.op === 'addRecord' ||
superceded.op === 'updateRecord' ||
superceded.op === 'replaceRecord') {
let record = superceded.record;
if ((_d = (_c = record.relationships) === null || _c === void 0 ? void 0 : _c[superceding.relationship]) === null || _d === void 0 ? void 0 : _d.data) {
updateRecordRemoveFromHasMany(superceded.record, superceding.relationship, superceding.relatedRecord);
markOperationToDelete(superceding);
}
}
}
}
}
else if (superceding.record && superceding.op === 'removeRecord') {
if (superceded.relatedRecord &&
(0, record_1.equalRecordIdentities)(superceded
.relatedRecord, superceding.record)) {
markOperationToDelete(superceded);
}
}
}
function isReplaceFieldOp(op) {
return (op === 'replaceAttribute' ||
op === 'replaceRelatedRecord' ||
op === 'replaceRelatedRecords');
}
function updateRecordReplaceAttribute(record, attribute, value) {
(0, utils_1.deepSet)(record, ['attributes', attribute], value);
}
function updateRecordReplaceHasOne(record, relationship, relatedRecord) {
(0, utils_1.deepSet)(record, ['relationships', relationship, 'data'], relatedRecord ? (0, record_1.cloneRecordIdentity)(relatedRecord) : null);
}
function updateRecordReplaceHasMany(record, relationship, relatedRecords) {
(0, utils_1.deepSet)(record, ['relationships', relationship, 'data'], relatedRecords.map(record_1.cloneRecordIdentity));
}
function updateRecordAddToHasMany(record, relationship, relatedRecord) {
const data = (0, utils_1.deepGet)(record, ['relationships', relationship, 'data']) || [];
data.push((0, record_1.cloneRecordIdentity)(relatedRecord));
(0, utils_1.deepSet)(record, ['relationships', relationship, 'data'], data);
}
function updateRecordRemoveFromHasMany(record, relationship, relatedRecord) {
const data = (0, utils_1.deepGet)(record, [
'relationships',
relationship,
'data'
]);
if (data) {
for (let i = 0, l = data.length; i < l; i++) {
let r = data[i];
if ((0, record_1.equalRecordIdentities)(r, relatedRecord)) {
data.splice(i, 1);
break;
}
}
}
}
/**
* Coalesces operations into a minimal set of equivalent operations.
*
* This method respects the order of the operations array and does not allow
* reordering of operations that affect relationships.
*/
function coalesceRecordOperations(operations) {
for (let i = 0, l = operations.length; i < l; i++) {
let currentOp = operations[i];
let consecutiveOps = true;
for (let j = i + 1; j < l; j++) {
let nextOp = operations[j];
mergeOperations(currentOp, nextOp, consecutiveOps);
if (isOperationMarkedToDelete(currentOp)) {
break;
}
else if (!isOperationMarkedToDelete(nextOp)) {
consecutiveOps = false;
}
}
}
return operations.filter((o) => !isOperationMarkedToDelete(o));
}
exports.coalesceRecordOperations = coalesceRecordOperations;
/**
* Determine the differences between a record and its updated version in terms
* of a set of operations.
*/
function recordDiffs(record, updatedRecord) {
var _a;
const ops = [];
if (record && updatedRecord) {
let fullRecordUpdate = false;
const recordIdentity = (0, record_1.cloneRecordIdentity)(record);
const diffRecord = { ...recordIdentity };
for (let member in updatedRecord) {
if (member !== 'id' && member !== 'type') {
let value;
let updatedValue;
switch (member) {
case 'attributes':
case 'keys':
case 'relationships':
for (let field in updatedRecord[member]) {
value = (_a = record[member]) === null || _a === void 0 ? void 0 : _a[field];
updatedValue = updatedRecord[member][field];
if (!(0, utils_1.eq)(value, updatedValue)) {
if (member === 'relationships') {
fullRecordUpdate = true;
}
(0, utils_1.deepSet)(diffRecord, [member, field], updatedValue);
}
}
break;
default:
value = record[member];
updatedValue = updatedRecord[member];
if (!(0, utils_1.eq)(updatedValue, value)) {
diffRecord[member] = updatedValue;
fullRecordUpdate = true;
}
}
}
}
// If updates consist solely of attributes and keys, update fields
// with individual operations. Otherwise, update the record as a
// whole.
if (fullRecordUpdate) {
let op = {
op: 'updateRecord',
record: diffRecord
};
ops.push(op);
}
else {
if (diffRecord.attributes) {
for (let attribute in diffRecord.attributes) {
let value = diffRecord.attributes[attribute];
let op = {
op: 'replaceAttribute',
record: recordIdentity,
attribute,
value
};
ops.push(op);
}
}
if (diffRecord.keys) {
for (let key in diffRecord.keys) {
let value = diffRecord.keys[key];
let op = {
op: 'replaceKey',
record: recordIdentity,
key,
value
};
ops.push(op);
}
}
}
}
return ops;
}
exports.recordDiffs = recordDiffs;
/**
* Returns the deduped identities of all the records directly referenced by an
* array of operations.
*/
function recordsReferencedByOperations(operations) {
const records = [];
for (let operation of operations) {
if (operation.record) {
records.push(operation.record);
if (operation.op === 'addRecord' || operation.op === 'updateRecord') {
let record = operation.record;
if (record.relationships) {
for (let relName in record.relationships) {
let rel = record.relationships[relName];
if (rel === null || rel === void 0 ? void 0 : rel.data) {
if (Array.isArray(rel.data)) {
Array.prototype.push.apply(records, rel.data);
}
else {
records.push(rel.data);
}
}
}
}
}
}
if (operation.op === 'addToRelatedRecords' ||
operation.op === 'removeFromRelatedRecords' ||
operation.op === 'replaceRelatedRecord') {
if (operation.relatedRecord) {
records.push(operation.relatedRecord);
}
}
else if (operation.op === 'replaceRelatedRecords') {
Array.prototype.push.apply(records, operation.relatedRecords);
}
}
return (0, record_1.dedupeRecordIdentities)(records);
}
exports.recordsReferencedByOperations = recordsReferencedByOperations;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3JkLW9wZXJhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZWNvcmQtb3BlcmF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHdDQUFvRDtBQUVwRCxxQ0FPa0I7QUFnSGxCLFNBQVMscUJBQXFCLENBQUMsU0FBb0I7SUFDakQsTUFBTSxDQUFDLEdBQVEsU0FBUyxDQUFDO0lBQ3pCLENBQUMsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO0FBQ3BCLENBQUM7QUFFRCxTQUFTLHlCQUF5QixDQUFDLFNBQW9CO0lBQ3JELE1BQU0sQ0FBQyxHQUFRLFNBQVMsQ0FBQztJQUN6QixPQUFPLENBQUMsQ0FBQyxRQUFRLEtBQUssSUFBSSxDQUFDO0FBQzdCLENBQUM7QUFFRCxTQUFTLGVBQWUsQ0FDdEIsVUFBMkIsRUFDM0IsV0FBNEIsRUFDNUIsY0FBdUI7O0lBRXZCLElBQUksVUFBVSxDQUFDLE9BQU8sSUFBSSxXQUFXLENBQUMsT0FBTyxFQUFFO1FBQzdDLHFEQUFxRDtRQUNyRCxPQUFPO0tBQ1I7U0FBTSxJQUFJLElBQUEsOEJBQXFCLEVBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsTUFBTSxDQUFDLEVBQUU7UUFDdkUsSUFBSSxXQUFXLENBQUMsRUFBRSxLQUFLLGNBQWMsRUFBRTtZQUNyQyxxQkFBcUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNsQyxJQUFJLFVBQVUsQ0FBQyxFQUFFLEtBQUssV0FBVyxFQUFFO2dCQUNqQyxxQkFBcUIsQ0FBQyxXQUFXLENBQUMsQ0FBQzthQUNwQztTQUNGO2FBQU0sSUFDTCxDQUFDLHlCQUF5QixDQUFDLFdBQVcsQ0FBQztZQUN2QyxDQUFDLGNBQWMsSUFBSSxXQUFXLENBQUMsRUFBRSxLQUFLLGtCQUFrQixDQUFDLEVBQ3pEO1lBQ0EsSUFBSSxnQkFBZ0IsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLElBQUksZ0JBQWdCLENBQUMsV0FBVyxDQUFD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RjtJQUVELE9BQU8sSUFBQSwrQkFBc0IsRUFBQyxPQUFPLENBQUMsQ0FBQztBQUN6QyxDQUFDO0FBdkNELHNFQXVDQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGVxLCBkZWVwR2V0LCBkZWVwU2V0IH0gZnJvbSAnQG9yYml0L3V0aWxzJztcbmltcG9ydCB7IE9wZXJhdGlvbiB9IGZyb20gJ0BvcmJpdC9kYXRhJztcbmltcG9ydCB7XG4gIEluaXRpYWxpemVkUmVjb3JkLFxuICBSZWNvcmRJZGVudGl0eSxcbiAgY2xvbmVSZWNvcmRJZGVudGl0eSxcbiAgZXF1YWxSZWNvcmRJZGVudGl0aWVzLFxuICBtZXJnZVJlY29yZHMsXG4gIGRlZHVwZVJlY29yZElkZW50aXRpZXNcbn0gZnJvbSAnLi9yZWNvcmQnO1xuXG4vKipcbiAqIEFkZCByZWNvcmQgb3BlcmF0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFkZFJlY29yZE9wZXJhdGlvbiBleHRlbmRzIE9wZXJhdGlvbiB7XG4gIG9wOiAnYWRkUmVjb3JkJztcbiAgcmVjb3JkOiBJbml0aWFsaXplZFJlY29yZDtcbn1cblxuLyoqXG4gKiBVcGRhdGUgcmVjb3JkIG9wZXJhdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBVcGRhdGVSZWNvcmRPcGVyYXRpb24gZXh0ZW5kcyBPcGVyYXRpb24ge1xuICBvcDogJ3VwZGF0ZVJlY29yZCc7XG4gIHJlY29yZDogSW5pdGlhbGl6ZWRSZWNvcmQ7XG59XG5cbi8qKlxuICogUmVtb3ZlIHJlY29yZCBvcGVyYXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVtb3ZlUmVjb3JkT3BlcmF0aW9uIGV4dGVuZHMgT3BlcmF0aW9uIHtcbiAgb3A6ICdyZW1vdmVSZWNvcmQnO1xuICByZWNvcmQ6IFJlY29yZElkZW50aXR5O1xufVxuXG4vKipcbiAqIFJlcGxhY2Uga2V5IG9wZXJhdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXBsYWNlS2V5T3BlcmF0aW9uIGV4dGVuZHMgT3BlcmF0aW9uIHtcbiAgb3A6ICdyZXBsYWNlS2V5JztcbiAgcmVjb3JkOiBSZWNvcmRJZGVudGl0eTtcbiAga2V5OiBzdHJpbmc7XG4gIHZhbHVlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUmVwbGFjZSBhdHRyaWJ1dGUgb3BlcmF0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlcGxhY2VBdHRyaWJ1dGVPcGVyYXRpb24gZXh0ZW5kcyBPcGVyYXRpb24ge1xuICBvcDogJ3JlcGxhY2VBdHRyaWJ1dGUnO1xuICByZWNvcmQ6IFJlY29yZElkZW50aXR5O1xuICBhdHRyaWJ1dGU6IHN0cmluZztcbiAgdmFsdWU6IHVua25vd247XG59XG5cbi8qKlxuICogQWRkIHRvIGhhcy1tYW55IHJlbGF0aW9uc2hpcCBvcGVyYXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWRkVG9SZWxhdGVkUmVjb3Jkc09wZXJhdGlvbiBleHRlbmRzIE9wZXJhdGlvbiB7XG4gIG9wOiAnYWRkVG9SZWxhdGVkUmVjb3Jkcyc7XG4gIHJlY29yZDogUmVjb3JkSWRlbnRpdHk7XG4gIHJlbGF0aW9uc2hpcDogc3RyaW5nO1xuICByZWxhdGVkUmVjb3JkOiBSZWNvcmRJZGVudGl0eTtcbn1cblxuLyoqXG4gKiBSZW1vdmUgZnJvbSBoYXMtbWFueSByZWxhdGlvbnNoaXAgb3BlcmF0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlbW92ZUZyb21SZWxhdGVkUmVjb3Jkc09wZXJhdGlvbiBleHRlbmRzIE9wZXJhdGlvbiB7XG4gIG9wOiAncmVtb3ZlRnJvbVJlbGF0ZWRSZWNvcmRzJztcbiAgcmVjb3JkOiBSZWNvcmRJZGVudGl0eTtcbiAgcmVsYXRpb25zaGlwOiBzdHJpbmc7XG4gIHJlbGF0ZWRSZWNvcmQ6IFJlY29yZElkZW50aXR5O1xufVxuXG4vKipcbiAqIFJlcGxhY2UgaGFzLW1hbnkgcmVsYXRpb25zaGlwIG9wZXJhdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXBsYWNlUmVsYXRlZFJlY29yZHNPcGVyYXRpb24gZXh0ZW5kcyBPcGVyYXRpb24ge1xuICBvcDogJ3JlcGxhY2VSZWxhdGVkUmVjb3Jkcyc7XG4gIHJlY29yZDogUmVjb3JkSWRlbnRpdHk7XG4gIHJlbGF0aW9uc2hpcDogc3RyaW5nO1xuICByZWxhdGVkUmVjb3JkczogUmVjb3JkSWRlbnRpdHlbXTtcbn1cblxuLyoqXG4gKiBSZXBsYWNlIGhhcy1vbmUgcmVsYXRpb25zaGlwIG9wZXJhdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXBsYWNlUmVsYXRlZFJlY29yZE9wZXJhdGlvbiBleHRlbmRzIE9wZXJhdGlvbiB7XG4gIG9wOiAncmVwbGFjZVJlbGF0ZWRSZWNvcmQnO1xuICByZWNvcmQ6IFJlY29yZElkZW50aXR5O1xuICByZWxhdGlvbnNoaXA6IHN0cmluZztcbiAgcmVsYXRlZFJlY29yZDogUmVjb3JkSWRlbnRpdHkgfCBudWxsO1xufVxuXG4vKipcbiAqIFVuaW9uIG9mIGFsbCByZWNvcmQtcmVsYXRlZCBvcGVyYXRpb25zLlxuICovXG5leHBvcnQgdHlwZSBSZWNvcmRPcGVyYXRpb24gPVxuICB8IEFkZFJlY29yZE9wZXJhdGlvblxuICB8IFVwZGF0ZVJlY29yZE9wZXJhdGlvblxuICB8IFJlbW92ZVJlY29yZE9wZXJhdGlvblxuICB8IFJlcGxhY2VLZXlPcGVyYXRpb25cbiAgfCBSZXBsYWNlQXR0cmlidXRlT3BlcmF0aW9uXG4gIHwgQWRkVG9SZWxhdGVkUmVjb3Jkc09wZXJhdGlvblxuICB8IFJlbW92ZUZyb21SZWxhdGVkUmVjb3Jkc09wZXJhdGlvblxuICB8IFJlcGxhY2VSZWxhdGVkUmVjb3Jkc09wZXJhdGlvblxuICB8IFJlcGxhY2VSZWxhdGVkUmVjb3JkT3BlcmF0aW9uO1xuXG5leHBvcnQgdHlwZSBBZGRSZWNvcmRPcGVyYXRpb25SZXN1bHQgPSBJbml0aWFsaXplZFJlY29yZDtcbmV4cG9ydCB0eXBlIFVwZGF0ZVJlY29yZE9wZXJhdGlvblJlc3VsdCA9IHVuZGVmaW5lZDtcbmV4cG9ydCB0eXBlIFJlbW92ZVJlY29yZE9wZXJhdGlvblJlc3VsdCA9IHVuZGVmaW5lZDtcbmV4cG9ydCB0eXBlIFJlcGxhY2VLZXlPcGVyYXRpb25SZXN1bHQgPSB1bmRlZmluZWQ7XG5leHBvcnQgdHlwZSBSZXBsYWNlQXR0cmlidXRlT3BlcmF0aW9uUmVzdWx0ID0gdW5kZWZpbmVkO1xuZXhwb3J0IHR5cGUgQWRkVG9SZWxhdGVkUmVjb3Jkc09wZXJhdGlvblJlc3VsdCA9IHVuZGVmaW5lZDtcbmV4cG9ydCB0eXBlIFJlbW92ZUZyb21SZWxhdGVkUmVjb3Jkc09wZXJhdGlvblJlc3VsdCA9IHVuZGVmaW5lZDtcbmV4cG9ydCB0eXBlIFJlcGxhY2VSZWxhdGVkUmVjb3Jkc09wZXJhdGlvblJlc3VsdCA9IHVuZGVmaW5lZDtcbmV4cG9ydCB0eXBlIFJlcGxhY2VSZWxhdGVkUmVjb3JkT3BlcmF0aW9uUmVzdWx0ID0gdW5kZWZpbmVkO1xuXG5leHBvcnQgdHlwZSBSZWNvcmRPcGVyYXRpb25SZXN1bHQ8VCA9IEluaXRpYWxpemVkUmVjb3JkPiA9IFQgfCB1bmRlZmluZWQ7XG5cbmZ1bmN0aW9uIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShvcGVyYXRpb246IE9wZXJhdGlvbik6IHZvaWQge1xuICBjb25zdCBvOiBhbnkgPSBvcGVyYXRpb247XG4gIG8uX2RlbGV0ZWQgPSB0cnVlO1xufVxuXG5mdW5jdGlvbiBpc09wZXJhdGlvbk1hcmtlZFRvRGVsZXRlKG9wZXJhdGlvbjogT3BlcmF0aW9uKTogYm9vbGVhbiB7XG4gIGNvbnN0IG86IGFueSA9IG9wZXJhdGlvbjtcbiAgcmV0dXJuIG8uX2RlbGV0ZWQgPT09IHRydWU7XG59XG5cbmZ1bmN0aW9uIG1lcmdlT3BlcmF0aW9ucyhcbiAgc3VwZXJjZWRlZDogUmVjb3JkT3BlcmF0aW9uLFxuICBzdXBlcmNlZGluZzogUmVjb3JkT3BlcmF0aW9uLFxuICBjb25zZWN1dGl2ZU9wczogYm9vbGVhblxuKTogdm9pZCB7XG4gIGlmIChzdXBlcmNlZGVkLm9wdGlvbnMgfHwgc3VwZXJjZWRpbmcub3B0aW9ucykge1xuICAgIC8vIGRvIG5vdCBtZXJnZSBpZiBvbmUgb2YgdGhlIG9wZXJhdGlvbnMgaGF2ZSBvcHRpb25zXG4gICAgcmV0dXJuO1xuICB9IGVsc2UgaWYgKGVxdWFsUmVjb3JkSWRlbnRpdGllcyhzdXBlcmNlZGVkLnJlY29yZCwgc3VwZXJjZWRpbmcucmVjb3JkKSkge1xuICAgIGlmIChzdXBlcmNlZGluZy5vcCA9PT0gJ3JlbW92ZVJlY29yZCcpIHtcbiAgICAgIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShzdXBlcmNlZGVkKTtcbiAgICAgIGlmIChzdXBlcmNlZGVkLm9wID09PSAnYWRkUmVjb3JkJykge1xuICAgICAgICBtYXJrT3BlcmF0aW9uVG9EZWxldGUoc3VwZXJjZWRpbmcpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoXG4gICAgICAhaXNPcGVyYXRpb25NYXJrZWRUb0RlbGV0ZShzdXBlcmNlZGluZykgJiZcbiAgICAgIChjb25zZWN1dGl2ZU9wcyB8fCBzdXBlcmNlZGluZy5vcCA9PT0gJ3JlcGxhY2VBdHRyaWJ1dGUnKVxuICAgICkge1xuICAgICAgaWYgKGlzUmVwbGFjZUZpZWxkT3Aoc3VwZXJjZWRlZC5vcCkgJiYgaXNSZXBsYWNlRmllbGRPcChzdXBlcmNlZGluZy5vcCkpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHN1cGVyY2VkZWQub3AgPT09ICdyZXBsYWNlQXR0cmlidXRlJyAmJlxuICAgICAgICAgIHN1cGVyY2VkaW5nLm9wID09PSAncmVwbGFjZUF0dHJpYnV0ZScgJiZcbiAgICAgICAgICBzdXBlcmNlZGVkLmF0dHJpYnV0ZSA9PT0gc3VwZXJjZWRpbmcuYXR0cmlidXRlXG4gICAgICAgICkge1xuICAgICAgICAgIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShzdXBlcmNlZGVkKTtcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICBzdXBlcmNlZGVkLm9wID09PSAncmVwbGFjZVJlbGF0ZWRSZWNvcmQnICYmXG4gICAgICAgICAgc3VwZXJjZWRpbmcub3AgPT09ICdyZXBsYWNlUmVsYXRlZFJlY29yZCcgJiZcbiAgICAgICAgICBzdXBlcmNlZGVkLnJlbGF0aW9uc2hpcCA9PT0gc3VwZXJjZWRpbmcucmVsYXRpb25zaGlwXG4gICAgICAgICkge1xuICAgICAgICAgIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShzdXBlcmNlZGVkKTtcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICBzdXBlcmNlZGVkLm9wID09PSAncmVwbGFjZVJlbGF0ZWRSZWNvcmRzJyAmJlxuICAgICAgICAgIHN1cGVyY2VkaW5nLm9wID09PSAncmVwbGFjZVJlbGF0ZWRSZWNvcmRzJyAmJlxuICAgICAgICAgIHN1cGVyY2VkZWQucmVsYXRpb25zaGlwID09PSBzdXBlcmNlZGluZy5yZWxhdGlvbnNoaXBcbiAgICAgICAgKSB7XG4gICAgICAgICAgbWFya09wZXJhdGlvblRvRGVsZXRlKHN1cGVyY2VkZWQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChzdXBlcmNlZGVkLm9wID09PSAncmVwbGFjZUF0dHJpYnV0ZScpIHtcbiAgICAgICAgICAgIHVwZGF0ZVJlY29yZFJlcGxhY2VBdHRyaWJ1dGUoXG4gICAgICAgICAgICAgIHN1cGVyY2VkZWQucmVjb3JkLFxuICAgICAgICAgICAgICBzdXBlcmNlZGVkLmF0dHJpYnV0ZSxcbiAgICAgICAgICAgICAgc3VwZXJjZWRlZC52YWx1ZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGRlbGV0ZSAoc3VwZXJjZWRlZCBhcyBhbnkpLmF0dHJpYnV0ZTtcbiAgICAgICAgICAgIGRlbGV0ZSBzdXBlcmNlZGVkLnZhbHVlO1xuICAgICAgICAgIH0gZWxzZSBpZiAoc3VwZXJjZWRlZC5vcCA9PT0gJ3JlcGxhY2VSZWxhdGVkUmVjb3JkJykge1xuICAgICAgICAgICAgdXBkYXRlUmVjb3JkUmVwbGFjZUhhc09uZShcbiAgICAgICAgICAgICAgc3VwZXJjZWRlZC5yZWNvcmQsXG4gICAgICAgICAgICAgIHN1cGVyY2VkZWQucmVsYXRpb25zaGlwLFxuICAgICAgICAgICAgICBzdXBlcmNlZGVkLnJlbGF0ZWRSZWNvcmRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBkZWxldGUgKHN1cGVyY2VkZWQgYXMgYW55KS5yZWxhdGlvbnNoaXA7XG4gICAgICAgICAgICBkZWxldGUgKHN1cGVyY2VkZWQgYXMgYW55KS5yZWxhdGVkUmVjb3JkO1xuICAgICAgICAgIH0gZWxzZSBpZiAoc3VwZXJjZWRlZC5vcCA9PT0gJ3JlcGxhY2VSZWxhdGVkUmVjb3JkcycpIHtcbiAgICAgICAgICAgIHVwZGF0ZVJlY29yZFJlcGxhY2VIYXNNYW55KFxuICAgICAgICAgICAgICBzdXBlcmNlZGVkLnJlY29yZCxcbiAgICAgICAgICAgICAgc3VwZXJjZWRlZC5yZWxhdGlvbnNoaXAsXG4gICAgICAgICAgICAgIHN1cGVyY2VkZWQucmVsYXRlZFJlY29yZHNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBkZWxldGUgKHN1cGVyY2VkZWQgYXMgYW55KS5yZWxhdGlvbnNoaXA7XG4gICAgICAgICAgICBkZWxldGUgKHN1cGVyY2VkZWQgYXMgYW55KS5yZWxhdGVkUmVjb3JkcztcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHN1cGVyY2VkaW5nLm9wID09PSAncmVwbGFjZUF0dHJpYnV0ZScpIHtcbiAgICAgICAgICAgIHVwZGF0ZVJlY29yZFJlcGxhY2VBdHRyaWJ1dGUoXG4gICAgICAgICAgICAgIHN1cGVyY2VkZWQucmVjb3JkLFxuICAgICAgICAgICAgICBzdXBlcmNlZGluZy5hdHRyaWJ1dGUsXG4gICAgICAgICAgICAgIHN1cGVyY2VkaW5nLnZhbHVlXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSBpZiAoc3VwZXJjZWRpbmcub3AgPT09ICdyZXBsYWNlUmVsYXRlZFJlY29yZCcpIHtcbiAgICAgICAgICAgIHVwZGF0ZVJlY29yZFJlcGxhY2VIYXNPbmUoXG4gICAgICAgICAgICAgIHN1cGVyY2VkZWQucmVjb3JkLFxuICAgICAgICAgICAgICBzdXBlcmNlZGluZy5yZWxhdGlvbnNoaXAsXG4gICAgICAgICAgICAgIHN1cGVyY2VkaW5nLnJlbGF0ZWRSZWNvcmRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIGlmIChzdXBlcmNlZGluZy5vcCA9PT0gJ3JlcGxhY2VSZWxhdGVkUmVjb3JkcycpIHtcbiAgICAgICAgICAgIHVwZGF0ZVJlY29yZFJlcGxhY2VIYXNNYW55KFxuICAgICAgICAgICAgICBzdXBlcmNlZGVkLnJlY29yZCxcbiAgICAgICAgICAgICAgc3VwZXJjZWRpbmcucmVsYXRpb25zaGlwLFxuICAgICAgICAgICAgICBzdXBlcmNlZGluZy5yZWxhdGVkUmVjb3Jkc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgc3VwZXJjZWRlZC5vcCA9ICd1cGRhdGVSZWNvcmQnO1xuICAgICAgICAgIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShzdXBlcmNlZGluZyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIChzdXBlcmNlZGVkLm9wID09PSAnYWRkUmVjb3JkJyB8fFxuICAgICAgICAgIHN1cGVyY2VkZWQub3AgPT09ICd1cGRhdGVSZWNvcmQnIHx8XG4gICAgICAgICAgKHN1cGVyY2VkZWQgYXMgYW55KS5vcCA9PT0gJ3JlcGxhY2VSZWNvcmQnKSAmJlxuICAgICAgICAoc3VwZXJjZWRpbmcub3AgPT09ICd1cGRhdGVSZWNvcmQnIHx8XG4gICAgICAgICAgKHN1cGVyY2VkaW5nIGFzIGFueSkub3AgPT09ICdyZXBsYWNlUmVjb3JkJylcbiAgICAgICkge1xuICAgICAgICBzdXBlcmNlZGVkLnJlY29yZCA9IG1lcmdlUmVjb3JkcyhzdXBlcmNlZGVkLnJlY29yZCwgc3VwZXJjZWRpbmcucmVjb3JkKTtcbiAgICAgICAgbWFya09wZXJhdGlvblRvRGVsZXRlKHN1cGVyY2VkaW5nKTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIChzdXBlcmNlZGVkLm9wID09PSAnYWRkUmVjb3JkJyB8fFxuICAgICAgICAgIHN1cGVyY2VkZWQub3AgPT09ICd1cGRhdGVSZWNvcmQnIHx8XG4gICAgICAgICAgKHN1cGVyY2VkZWQgYXMgYW55KS5vcCA9PT0gJ3JlcGxhY2VSZWNvcmQnKSAmJlxuICAgICAgICBpc1JlcGxhY2VGaWVsZE9wKHN1cGVyY2VkaW5nLm9wKVxuICAgICAgKSB7XG4gICAgICAgIGlmIChzdXBlcmNlZGluZy5vcCA9PT0gJ3JlcGxhY2VBdHRyaWJ1dGUnKSB7XG4gICAgICAgICAgdXBkYXRlUmVjb3JkUmVwbGFjZUF0dHJpYnV0ZShcbiAgICAgICAgICAgIHN1cGVyY2VkZWQucmVjb3JkLFxuICAgICAgICAgICAgc3VwZXJjZWRpbmcuYXR0cmlidXRlLFxuICAgICAgICAgICAgc3VwZXJjZWRpbmcudmFsdWVcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2UgaWYgKHN1cGVyY2VkaW5nLm9wID09PSAncmVwbGFjZVJlbGF0ZWRSZWNvcmQnKSB7XG4gICAgICAgICAgdXBkYXRlUmVjb3JkUmVwbGFjZUhhc09uZShcbiAgICAgICAgICAgIHN1cGVyY2VkZWQucmVjb3JkLFxuICAgICAgICAgICAgc3VwZXJjZWRpbmcucmVsYXRpb25zaGlwLFxuICAgICAgICAgICAgc3VwZXJjZWRpbmcucmVsYXRlZFJlY29yZFxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAoc3VwZXJjZWRpbmcub3AgPT09ICdyZXBsYWNlUmVsYXRlZFJlY29yZHMnKSB7XG4gICAgICAgICAgdXBkYXRlUmVjb3JkUmVwbGFjZUhhc01hbnkoXG4gICAgICAgICAgICBzdXBlcmNlZGVkLnJlY29yZCxcbiAgICAgICAgICAgIHN1cGVyY2VkaW5nLnJlbGF0aW9uc2hpcCxcbiAgICAgICAgICAgIHN1cGVyY2VkaW5nLnJlbGF0ZWRSZWNvcmRzXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBtYXJrT3BlcmF0aW9uVG9EZWxldGUoc3VwZXJjZWRpbmcpO1xuICAgICAgfSBlbHNlIGlmIChzdXBlcmNlZGluZy5vcCA9PT0gJ2FkZFRvUmVsYXRlZFJlY29yZHMnKSB7XG4gICAgICAgIGlmIChzdXBlcmNlZGVkLm9wID09PSAnYWRkUmVjb3JkJykge1xuICAgICAgICAgIHVwZGF0ZVJlY29yZEFkZFRvSGFzTWFueShcbiAgICAgICAgICAgIHN1cGVyY2VkZWQucmVjb3JkLFxuICAgICAgICAgICAgc3VwZXJjZWRpbmcucmVsYXRpb25zaGlwLFxuICAgICAgICAgICAgc3VwZXJjZWRpbmcucmVsYXRlZFJlY29yZFxuICAgICAgICAgICk7XG4gICAgICAgICAgbWFya09wZXJhdGlvblRvRGVsZXRlKHN1cGVyY2VkaW5nKTtcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICBzdXBlcmNlZGVkLm9wID09PSAndXBkYXRlUmVjb3JkJyB8fFxuICAgICAgICAgIChzdXBlcmNlZGVkIGFzIGFueSkub3AgPT09ICdyZXBsYWNlUmVjb3JkJ1xuICAgICAgICApIHtcbiAgICAgICAgICBsZXQgcmVjb3JkOiBJbml0aWFsaXplZFJlY29yZCA9IHN1cGVyY2VkZWQucmVjb3JkO1xuICAgICAgICAgIGlmIChyZWNvcmQucmVsYXRpb25zaGlwcz8uW3N1cGVyY2VkaW5nLnJlbGF0aW9uc2hpcF0/LmRhdGEpIHtcbiAgICAgICAgICAgIHVwZGF0ZVJlY29yZEFkZFRvSGFzTWFueShcbiAgICAgICAgICAgICAgc3VwZXJjZWRlZC5yZWNvcmQsXG4gICAgICAgICAgICAgIHN1cGVyY2VkaW5nLnJlbGF0aW9uc2hpcCxcbiAgICAgICAgICAgICAgc3VwZXJjZWRpbmcucmVsYXRlZFJlY29yZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShzdXBlcmNlZGluZyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHN1cGVyY2VkaW5nLm9wID09PSAncmVtb3ZlRnJvbVJlbGF0ZWRSZWNvcmRzJykge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgc3VwZXJjZWRlZC5vcCA9PT0gJ2FkZFRvUmVsYXRlZFJlY29yZHMnICYmXG4gICAgICAgICAgc3VwZXJjZWRlZC5yZWxhdGlvbnNoaXAgPT09IHN1cGVyY2VkaW5nLnJlbGF0aW9uc2hpcCAmJlxuICAgICAgICAgIGVxdWFsUmVjb3JkSWRlbnRpdGllcyhcbiAgICAgICAgICAgIHN1cGVyY2VkZWQucmVsYXRlZFJlY29yZCxcbiAgICAgICAgICAgIHN1cGVyY2VkaW5nLnJlbGF0ZWRSZWNvcmRcbiAgICAgICAgICApXG4gICAgICAgICkge1xuICAgICAgICAgIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShzdXBlcmNlZGVkKTtcbiAgICAgICAgICBtYXJrT3BlcmF0aW9uVG9EZWxldGUoc3VwZXJjZWRpbmcpO1xuICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgIHN1cGVyY2VkZWQub3AgPT09ICdhZGRSZWNvcmQnIHx8XG4gICAgICAgICAgc3VwZXJjZWRlZC5vcCA9PT0gJ3VwZGF0ZVJlY29yZCcgfHxcbiAgICAgICAgICAoc3VwZXJjZWRlZCBhcyBhbnkpLm9wID09PSAncmVwbGFjZVJlY29yZCdcbiAgICAgICAgKSB7XG4gICAgICAgICAgbGV0IHJlY29yZDogSW5pdGlhbGl6ZWRSZWNvcmQgPSBzdXBlcmNlZGVkLnJlY29yZDtcbiAgICAgICAgICBpZiAocmVjb3JkLnJlbGF0aW9uc2hpcHM/LltzdXBlcmNlZGluZy5yZWxhdGlvbnNoaXBdPy5kYXRhKSB7XG4gICAgICAgICAgICB1cGRhdGVSZWNvcmRSZW1vdmVGcm9tSGFzTWFueShcbiAgICAgICAgICAgICAgc3VwZXJjZWRlZC5yZWNvcmQsXG4gICAgICAgICAgICAgIHN1cGVyY2VkaW5nLnJlbGF0aW9uc2hpcCxcbiAgICAgICAgICAgICAgc3VwZXJjZWRpbmcucmVsYXRlZFJlY29yZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShzdXBlcmNlZGluZyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9IGVsc2UgaWYgKHN1cGVyY2VkaW5nLnJlY29yZCAmJiBzdXBlcmNlZGluZy5vcCA9PT0gJ3JlbW92ZVJlY29yZCcpIHtcbiAgICBpZiAoXG4gICAgICAoc3VwZXJjZWRlZCBhcyBSZXBsYWNlUmVsYXRlZFJlY29yZE9wZXJhdGlvbikucmVsYXRlZFJlY29yZCAmJlxuICAgICAgZXF1YWxSZWNvcmRJZGVudGl0aWVzKFxuICAgICAgICAoc3VwZXJjZWRlZCBhcyBSZXBsYWNlUmVsYXRlZFJlY29yZE9wZXJhdGlvbilcbiAgICAgICAgICAucmVsYXRlZFJlY29yZCBhcyBSZWNvcmRJZGVudGl0eSxcbiAgICAgICAgc3VwZXJjZWRpbmcucmVjb3JkXG4gICAgICApXG4gICAgKSB7XG4gICAgICBtYXJrT3BlcmF0aW9uVG9EZWxldGUoc3VwZXJjZWRlZCk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGlzUmVwbGFjZUZpZWxkT3Aob3A6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIG9wID09PSAncmVwbGFjZUF0dHJpYnV0ZScgfHxcbiAgICBvcCA9PT0gJ3JlcGxhY2VSZWxhdGVkUmVjb3JkJyB8fFxuICAgIG9wID09PSAncmVwbGFjZVJlbGF0ZWRSZWNvcmRzJ1xuICApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVSZWNvcmRSZXBsYWNlQXR0cmlidXRlKFxuICByZWNvcmQ6IEluaXRpYWxpemVkUmVjb3JkLFxuICBhdHRyaWJ1dGU6IHN0cmluZyxcbiAgdmFsdWU6IHVua25vd25cbikge1xuICBkZWVwU2V0KHJlY29yZCwgWydhdHRyaWJ1dGVzJywgYXR0cmlidXRlXSwgdmFsdWUpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVSZWNvcmRSZXBsYWNlSGFzT25lKFxuICByZWNvcmQ6IEluaXRpYWxpemVkUmVjb3JkLFxuICByZWxhdGlvbnNoaXA6IHN0cmluZyxcbiAgcmVsYXRlZFJlY29yZDogUmVjb3JkSWRlbnRpdHkgfCBudWxsXG4pIHtcbiAgZGVlcFNldChcbiAgICByZWNvcmQsXG4gICAgWydyZWxhdGlvbnNoaXBzJywgcmVsYXRpb25zaGlwLCAnZGF0YSddLFxuICAgIHJlbGF0ZWRSZWNvcmQgPyBjbG9uZVJlY29yZElkZW50aXR5KHJlbGF0ZWRSZWNvcmQpIDogbnVsbFxuICApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVSZWNvcmRSZXBsYWNlSGFzTWFueShcbiAgcmVjb3JkOiBJbml0aWFsaXplZFJlY29yZCxcbiAgcmVsYXRpb25zaGlwOiBzdHJpbmcsXG4gIHJlbGF0ZWRSZWNvcmRzOiBSZWNvcmRJZGVudGl0eVtdXG4pIHtcbiAgZGVlcFNldChcbiAgICByZWNvcmQsXG4gICAgWydyZWxhdGlvbnNoaXBzJywgcmVsYXRpb25zaGlwLCAnZGF0YSddLFxuICAgIHJlbGF0ZWRSZWNvcmRzLm1hcChjbG9uZVJlY29yZElkZW50aXR5KVxuICApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVSZWNvcmRBZGRUb0hhc01hbnkoXG4gIHJlY29yZDogSW5pdGlhbGl6ZWRSZWNvcmQsXG4gIHJlbGF0aW9uc2hpcDogc3RyaW5nLFxuICByZWxhdGVkUmVjb3JkOiBSZWNvcmRJZGVudGl0eVxuKSB7XG4gIGNvbnN0IGRhdGEgPSBkZWVwR2V0KHJlY29yZCwgWydyZWxhdGlvbnNoaXBzJywgcmVsYXRpb25zaGlwLCAnZGF0YSddKSB8fCBbXTtcbiAgZGF0YS5wdXNoKGNsb25lUmVjb3JkSWRlbnRpdHkocmVsYXRlZFJlY29yZCkpO1xuICBkZWVwU2V0KHJlY29yZCwgWydyZWxhdGlvbnNoaXBzJywgcmVsYXRpb25zaGlwLCAnZGF0YSddLCBkYXRhKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlUmVjb3JkUmVtb3ZlRnJvbUhhc01hbnkoXG4gIHJlY29yZDogSW5pdGlhbGl6ZWRSZWNvcmQsXG4gIHJlbGF0aW9uc2hpcDogc3RyaW5nLFxuICByZWxhdGVkUmVjb3JkOiBSZWNvcmRJZGVudGl0eVxuKSB7XG4gIGNvbnN0IGRhdGEgPSBkZWVwR2V0KHJlY29yZCwgW1xuICAgICdyZWxhdGlvbnNoaXBzJyxcbiAgICByZWxhdGlvbnNoaXAsXG4gICAgJ2RhdGEnXG4gIF0pIGFzIFJlY29yZElkZW50aXR5W107XG4gIGlmIChkYXRhKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGwgPSBkYXRhLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgbGV0IHIgPSBkYXRhW2ldO1xuICAgICAgaWYgKGVxdWFsUmVjb3JkSWRlbnRpdGllcyhyLCByZWxhdGVkUmVjb3JkKSkge1xuICAgICAgICBkYXRhLnNwbGljZShpLCAxKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ29hbGVzY2VzIG9wZXJhdGlvbnMgaW50byBhIG1pbmltYWwgc2V0IG9mIGVxdWl2YWxlbnQgb3BlcmF0aW9ucy5cbiAqXG4gKiBUaGlzIG1ldGhvZCByZXNwZWN0cyB0aGUgb3JkZXIgb2YgdGhlIG9wZXJhdGlvbnMgYXJyYXkgYW5kIGRvZXMgbm90IGFsbG93XG4gKiByZW9yZGVyaW5nIG9mIG9wZXJhdGlvbnMgdGhhdCBhZmZlY3QgcmVsYXRpb25zaGlwcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvYWxlc2NlUmVjb3JkT3BlcmF0aW9ucyhcbiAgb3BlcmF0aW9uczogUmVjb3JkT3BlcmF0aW9uW11cbik6IFJlY29yZE9wZXJhdGlvbltdIHtcbiAgZm9yIChsZXQgaSA9IDAsIGwgPSBvcGVyYXRpb25zLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIGxldCBjdXJyZW50T3AgPSBvcGVyYXRpb25zW2ldO1xuICAgIGxldCBjb25zZWN1dGl2ZU9wcyA9IHRydWU7XG5cbiAgICBmb3IgKGxldCBqID0gaSArIDE7IGogPCBsOyBqKyspIHtcbiAgICAgIGxldCBuZXh0T3AgPSBvcGVyYXRpb25zW2pdO1xuXG4gICAgICBtZXJnZU9wZXJhdGlvbnMoY3VycmVudE9wLCBuZXh0T3AsIGNvbnNlY3V0aXZlT3BzKTtcblxuICAgICAgaWYgKGlzT3BlcmF0aW9uTWFya2VkVG9EZWxldGUoY3VycmVudE9wKSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH0gZWxzZSBpZiAoIWlzT3BlcmF0aW9uTWFya2VkVG9EZWxldGUobmV4dE9wKSkge1xuICAgICAgICBjb25zZWN1dGl2ZU9wcyA9IGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBvcGVyYXRpb25zLmZpbHRlcigobykgPT4gIWlzT3BlcmF0aW9uTWFya2VkVG9EZWxldGUobykpO1xufVxuXG4vKipcbiAqIERldGVybWluZSB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBhIHJlY29yZCBhbmQgaXRzIHVwZGF0ZWQgdmVyc2lvbiBpbiB0ZXJtc1xuICogb2YgYSBzZXQgb2Ygb3BlcmF0aW9ucy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlY29yZERpZmZzKFxuICByZWNvcmQ6IEluaXRpYWxpemVkUmVjb3JkLFxuICB1cGRhdGVkUmVjb3JkOiBJbml0aWFsaXplZFJlY29yZFxuKTogUmVjb3JkT3BlcmF0aW9uW10ge1xuICBjb25zdCBvcHM6IFJlY29yZE9wZXJhdGlvbltdID0gW107XG5cbiAgaWYgKHJlY29yZCAmJiB1cGRhdGVkUmVjb3JkKSB7XG4gICAgbGV0IGZ1bGxSZWNvcmRVcGRhdGUgPSBmYWxzZTtcbiAgICBjb25zdCByZWNvcmRJZGVudGl0eSA9IGNsb25lUmVjb3JkSWRlbnRpdHkocmVjb3JkKTtcbiAgICBjb25zdCBkaWZmUmVjb3JkOiBJbml0aWFsaXplZFJlY29yZCA9IHsgLi4ucmVjb3JkSWRlbnRpdHkgfTtcblxuICAgIGZvciAobGV0IG1lbWJlciBpbiB1cGRhdGVkUmVjb3JkKSB7XG4gICAgICBpZiAobWVtYmVyICE9PSAnaWQnICYmIG1lbWJlciAhPT0gJ3R5cGUnKSB7XG4gICAgICAgIGxldCB2YWx1ZTogdW5rbm93bjtcbiAgICAgICAgbGV0IHVwZGF0ZWRWYWx1ZTogdW5rbm93bjtcblxuICAgICAgICBzd2l0Y2ggKG1lbWJlcikge1xuICAgICAgICAgIGNhc2UgJ2F0dHJpYnV0ZXMnOlxuICAgICAgICAgIGNhc2UgJ2tleXMnOlxuICAgICAgICAgIGNhc2UgJ3JlbGF0aW9uc2hpcHMnOlxuICAgICAgICAgICAgZm9yIChsZXQgZmllbGQgaW4gdXBkYXRlZFJlY29yZFttZW1iZXJdKSB7XG4gICAgICAgICAgICAgIHZhbHVlID0gcmVjb3JkW21lbWJlcl0/LltmaWVsZF07XG4gICAgICAgICAgICAgIHVwZGF0ZWRWYWx1ZSA9ICh1cGRhdGVkUmVjb3JkW21lbWJlcl0gYXMgYW55KVtmaWVsZF07XG5cbiAgICAgICAgICAgICAgaWYgKCFlcSh2YWx1ZSwgdXBkYXRlZFZhbHVlKSkge1xuICAgICAgICAgICAgICAgIGlmIChtZW1iZXIgPT09ICdyZWxhdGlvbnNoaXBzJykge1xuICAgICAgICAgICAgICAgICAgZnVsbFJlY29yZFVwZGF0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlZXBTZXQoZGlmZlJlY29yZCwgW21lbWJlciwgZmllbGRdLCB1cGRhdGVkVmFsdWUpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB2YWx1ZSA9IChyZWNvcmQgYXMgYW55KVttZW1iZXJdO1xuICAgICAgICAgICAgdXBkYXRlZFZhbHVlID0gKHVwZGF0ZWRSZWNvcmQgYXMgYW55KVttZW1iZXJdO1xuXG4gICAgICAgICAgICBpZiAoIWVxKHVwZGF0ZWRWYWx1ZSwgdmFsdWUpKSB7XG4gICAgICAgICAgICAgIChkaWZmUmVjb3JkIGFzIGFueSlbbWVtYmVyXSA9IHVwZGF0ZWRWYWx1ZTtcbiAgICAgICAgICAgICAgZnVsbFJlY29yZFVwZGF0ZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBJZiB1cGRhdGVzIGNvbnNpc3Qgc29sZWx5IG9mIGF0dHJpYnV0ZXMgYW5kIGtleXMsIHVwZGF0ZSBmaWVsZHNcbiAgICAvLyB3aXRoIGluZGl2aWR1YWwgb3BlcmF0aW9ucy4gT3RoZXJ3aXNlLCB1cGRhdGUgdGhlIHJlY29yZCBhcyBhXG4gICAgLy8gd2hvbGUuXG4gICAgaWYgKGZ1bGxSZWNvcmRVcGRhdGUpIHtcbiAgICAgIGxldCBvcDogVXBkYXRlUmVjb3JkT3BlcmF0aW9uID0ge1xuICAgICAgICBvcDogJ3VwZGF0ZVJlY29yZCcsXG4gICAgICAgIHJlY29yZDogZGlmZlJlY29yZFxuICAgICAgfTtcbiAgICAgIG9wcy5wdXNoKG9wKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGRpZmZSZWNvcmQuYXR0cmlidXRlcykge1xuICAgICAgICBmb3IgKGxldCBhdHRyaWJ1dGUgaW4gZGlmZlJlY29yZC5hdHRyaWJ1dGVzKSB7XG4gICAgICAgICAgbGV0IHZhbHVlID0gZGlmZlJlY29yZC5hdHRyaWJ1dGVzW2F0dHJpYnV0ZV07XG4gICAgICAgICAgbGV0IG9wOiBSZXBsYWNlQXR0cmlidXRlT3BlcmF0aW9uID0ge1xuICAgICAgICAgICAgb3A6ICdyZXBsYWNlQXR0cmlidXRlJyxcbiAgICAgICAgICAgIHJlY29yZDogcmVjb3JkSWRlbnRpdHksXG4gICAgICAgICAgICBhdHRyaWJ1dGUsXG4gICAgICAgICAgICB2YWx1ZVxuICAgICAgICAgIH07XG4gICAgICAgICAgb3BzLnB1c2gob3ApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZGlmZlJlY29yZC5rZXlzKSB7XG4gICAgICAgIGZvciAobGV0IGtleSBpbiBkaWZmUmVjb3JkLmtleXMpIHtcbiAgICAgICAgICBsZXQgdmFsdWUgPSBkaWZmUmVjb3JkLmtleXNba2V5XTtcbiAgICAgICAgICBsZXQgb3A6IFJlcGxhY2VLZXlPcGVyYXRpb24gPSB7XG4gICAgICAgICAgICBvcDogJ3JlcGxhY2VLZXknLFxuICAgICAgICAgICAgcmVjb3JkOiByZWNvcmRJZGVudGl0eSxcbiAgICAgICAgICAgIGtleSxcbiAgICAgICAgICAgIHZhbHVlXG4gICAgICAgICAgfTtcbiAgICAgICAgICBvcHMucHVzaChvcCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gb3BzO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGRlZHVwZWQgaWRlbnRpdGllcyBvZiBhbGwgdGhlIHJlY29yZHMgZGlyZWN0bHkgcmVmZXJlbmNlZCBieSBhblxuICogYXJyYXkgb2Ygb3BlcmF0aW9ucy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlY29yZHNSZWZlcmVuY2VkQnlPcGVyYXRpb25zKFxuICBvcGVyYXRpb25zOiBSZWNvcmRPcGVyYXRpb25bXVxuKTogUmVjb3JkSWRlbnRpdHlbXSB7XG4gIGNvbnN0IHJlY29yZHMgPSBbXTtcblxuICBmb3IgKGxldCBvcGVyYXRpb24gb2Ygb3BlcmF0aW9ucykge1xuICAgIGlmIChvcGVyYXRpb24ucmVjb3JkKSB7XG4gICAgICByZWNvcmRzLnB1c2gob3BlcmF0aW9uLnJlY29yZCk7XG5cbiAgICAgIGlmIChvcGVyYXRpb24ub3AgPT09ICdhZGRSZWNvcmQnIHx8IG9wZXJhdGlvbi5vcCA9PT0gJ3VwZGF0ZVJlY29yZCcpIHtcbiAgICAgICAgbGV0IHJlY29yZCA9IG9wZXJhdGlvbi5yZWNvcmQ7XG4gICAgICAgIGlmIChyZWNvcmQucmVsYXRpb25zaGlwcykge1xuICAgICAgICAgIGZvciAobGV0IHJlbE5hbWUgaW4gcmVjb3JkLnJlbGF0aW9uc2hpcHMpIHtcbiAgICAgICAgICAgIGxldCByZWwgPSByZWNvcmQucmVsYXRpb25zaGlwc1tyZWxOYW1lXTtcbiAgICAgICAgICAgIGlmIChyZWw/LmRhdGEpIHtcbiAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVsLmRhdGEpKSB7XG4gICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkocmVjb3JkcywgcmVsLmRhdGEpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29yZHMucHVzaChyZWwuZGF0YSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKFxuICAgICAgb3BlcmF0aW9uLm9wID09PSAnYWRkVG9SZWxhdGVkUmVjb3JkcycgfHxcbiAgICAgIG9wZXJhdGlvbi5vcCA9PT0gJ3JlbW92ZUZyb21SZWxhdGVkUmVjb3JkcycgfHxcbiAgICAgIG9wZXJhdGlvbi5vcCA9PT0gJ3JlcGxhY2VSZWxhdGVkUmVjb3JkJ1xuICAgICkge1xuICAgICAgaWYgKG9wZXJhdGlvbi5yZWxhdGVkUmVjb3JkKSB7XG4gICAgICAgIHJlY29yZHMucHVzaChvcGVyYXRpb24ucmVsYXRlZFJlY29yZCk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChvcGVyYXRpb24ub3AgPT09ICdyZXBsYWNlUmVsYXRlZFJlY29yZHMnKSB7XG4gICAgICBBcnJheS5wcm90b3R5cGUucHVz