@orbit/records
Version:
A flexible data access and synchronization layer.
311 lines • 49.6 kB
JavaScript
import { eq, deepGet, deepSet } from '@orbit/utils';
import { cloneRecordIdentity, equalRecordIdentities, mergeRecords, dedupeRecordIdentities } from './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 (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 = 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 &&
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 &&
equalRecordIdentities(superceded
.relatedRecord, superceding.record)) {
markOperationToDelete(superceded);
}
}
}
function isReplaceFieldOp(op) {
return (op === 'replaceAttribute' ||
op === 'replaceRelatedRecord' ||
op === 'replaceRelatedRecords');
}
function updateRecordReplaceAttribute(record, attribute, value) {
deepSet(record, ['attributes', attribute], value);
}
function updateRecordReplaceHasOne(record, relationship, relatedRecord) {
deepSet(record, ['relationships', relationship, 'data'], relatedRecord ? cloneRecordIdentity(relatedRecord) : null);
}
function updateRecordReplaceHasMany(record, relationship, relatedRecords) {
deepSet(record, ['relationships', relationship, 'data'], relatedRecords.map(cloneRecordIdentity));
}
function updateRecordAddToHasMany(record, relationship, relatedRecord) {
const data = deepGet(record, ['relationships', relationship, 'data']) || [];
data.push(cloneRecordIdentity(relatedRecord));
deepSet(record, ['relationships', relationship, 'data'], data);
}
function updateRecordRemoveFromHasMany(record, relationship, relatedRecord) {
const data = deepGet(record, [
'relationships',
relationship,
'data'
]);
if (data) {
for (let i = 0, l = data.length; i < l; i++) {
let r = data[i];
if (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.
*/
export 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));
}
/**
* Determine the differences between a record and its updated version in terms
* of a set of operations.
*/
export function recordDiffs(record, updatedRecord) {
var _a;
const ops = [];
if (record && updatedRecord) {
let fullRecordUpdate = false;
const recordIdentity = 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 (!eq(value, updatedValue)) {
if (member === 'relationships') {
fullRecordUpdate = true;
}
deepSet(diffRecord, [member, field], updatedValue);
}
}
break;
default:
value = record[member];
updatedValue = updatedRecord[member];
if (!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;
}
/**
* Returns the deduped identities of all the records directly referenced by an
* array of operations.
*/
export 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 dedupeRecordIdentities(records);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3JkLW9wZXJhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZWNvcmQtb3BlcmF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUVwRCxPQUFPLEVBR0wsbUJBQW1CLEVBQ25CLHFCQUFxQixFQUNyQixZQUFZLEVBQ1osc0JBQXNCLEVBQ3ZCLE1BQU0sVUFBVSxDQUFDO0FBZ0hsQixTQUFTLHFCQUFxQixDQUFDLFNBQW9CO0lBQ2pELE1BQU0sQ0FBQyxHQUFRLFNBQVMsQ0FBQztJQUN6QixDQUFDLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztBQUNwQixDQUFDO0FBRUQsU0FBUyx5QkFBeUIsQ0FBQyxTQUFvQjtJQUNyRCxNQUFNLENBQUMsR0FBUSxTQUFTLENBQUM7SUFDekIsT0FBTyxDQUFDLENBQUMsUUFBUSxLQUFLLElBQUksQ0FBQztBQUM3QixDQUFDO0FBRUQsU0FBUyxlQUFlLENBQ3RCLFVBQTJCLEVBQzNCLFdBQTRCLEVBQzVCLGNBQXVCOztJQUV2QixJQUFJLFVBQVUsQ0FBQyxPQUFPLElBQUksV0FBVyxDQUFDLE9BQU8sRUFBRTtRQUM3QyxxREFBcUQ7UUFDckQsT0FBTztLQUNSO1NBQU0sSUFBSSxxQkFBcUIsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxNQUFNLENBQUMsRUFBRTtRQUN2RSxJQUFJLFdBQVcsQ0FBQyxFQUFFLEtBQUssY0FBYyxFQUFFO1lBQ3JDLHFCQUFxQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ2xDLElBQUksVUFBVSxDQUFDLEVBQUUsS0FBSyxXQUFXLEVBQUU7Z0JBQ2pDLHFCQUFxQixDQUFDLFdBQVcsQ0FBQyxDQUFDO2FBQ3BDO1NBQ0Y7YUFBTSxJQUNMLENBQUMseUJBQXlCLENBQUMsV0FBVyxDQUFDO1lBQ3ZDLENBQUMsY0FBYyxJQUFJ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QUM7U0FDL0Q7S0FDRjtJQUVELE9BQU8sc0JBQXNCLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDekMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGVxLCBkZWVwR2V0LCBkZWVwU2V0IH0gZnJvbSAnQG9yYml0L3V0aWxzJztcbmltcG9ydCB7IE9wZXJhdGlvbiB9IGZyb20gJ0BvcmJpdC9kYXRhJztcbmltcG9ydCB7XG4gIEluaXRpYWxpemVkUmVjb3JkLFxuICBSZWNvcmRJZGVudGl0eSxcbiAgY2xvbmVSZWNvcmRJZGVudGl0eSxcbiAgZXF1YWxSZWNvcmRJZGVudGl0aWVzLFxuICBtZXJnZVJlY29yZHMsXG4gIGRlZHVwZVJlY29yZElkZW50aXRpZXNcbn0gZnJvbSAnLi9yZWNvcmQnO1xuXG4vKipcbiAqIEFkZCByZWNvcmQgb3BlcmF0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFkZFJlY29yZE9wZXJhdGlvbiBleHRlbmRzIE9wZXJhdGlvbiB7XG4gIG9wOiAnYWRkUmVjb3JkJztcbiAgcmVjb3JkOiBJbml0aWFsaXplZFJlY29yZDtcbn1cblxuLyoqXG4gKiBVcGRhdGUgcmVjb3JkIG9wZXJhdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBVcGRhdGVSZWNvcmRPcGVyYXRpb24gZXh0ZW5kcyBPcGVyYXRpb24ge1xuICBvcDogJ3VwZGF0ZVJlY29yZCc7XG4gIHJlY29yZDogSW5pdGlhbGl6ZWRSZWNvcmQ7XG59XG5cbi8qKlxuICogUmVtb3ZlIHJlY29yZCBvcGVyYXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVtb3ZlUmVjb3JkT3BlcmF0aW9uIGV4dGVuZHMgT3BlcmF0aW9uIHtcbiAgb3A6ICdyZW1vdmVSZWNvcmQnO1xuICByZWNvcmQ6IFJlY29yZElkZW50aXR5O1xufVxuXG4vKipcbiAqIFJlcGxhY2Uga2V5IG9wZXJhdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXBsYWNlS2V5T3BlcmF0aW9uIGV4dGVuZHMgT3BlcmF0aW9uIHtcbiAgb3A6ICdyZXBsYWNlS2V5JztcbiAgcmVjb3JkOiBSZWNvcmRJZGVudGl0eTtcbiAga2V5OiBzdHJpbmc7XG4gIHZhbHVlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUmVwbGFjZSBhdHRyaWJ1dGUgb3BlcmF0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlcGxhY2VBdHRyaWJ1dGVPcGVyYXRpb24gZXh0ZW5kcyBPcGVyYXRpb24ge1xuICBvcDogJ3JlcGxhY2VBdHRyaWJ1dGUnO1xuICByZWNvcmQ6IFJlY29yZElkZW50aXR5O1xuICBhdHRyaWJ1dGU6IHN0cmluZztcbiAgdmFsdWU6IHVua25vd247XG59XG5cbi8qKlxuICogQWRkIHRvIGhhcy1tYW55IHJlbGF0aW9uc2hpcCBvcGVyYXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWRkVG9SZWxhdGVkUmVjb3Jkc09wZXJhdGlvbiBleHRlbmRzIE9wZXJhdGlvbiB7XG4gIG9wOiAnYWRkVG9SZWxhdGVkUmVjb3Jkcyc7XG4gIHJlY29yZDogUmVjb3JkSWRlbnRpdHk7XG4gIHJlbGF0aW9uc2hpcDogc3RyaW5nO1xuICByZWxhdGVkUmVjb3JkOiBSZWNvcmRJZGVudGl0eTtcbn1cblxuLyoqXG4gKiBSZW1vdmUgZnJvbSBoYXMtbWFueSByZWxhdGlvbnNoaXAgb3BlcmF0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlbW92ZUZyb21SZWxhdGVkUmVjb3Jkc09wZXJhdGlvbiBleHRlbmRzIE9wZXJhdGlvbiB7XG4gIG9wOiAncmVtb3ZlRnJvbVJlbGF0ZWRSZWNvcmRzJztcbiAgcmVjb3JkOiBSZWNvcmRJZGVudGl0eTtcbiAgcmVsYXRpb25zaGlwOiBzdHJpbmc7XG4gIHJlbGF0ZWRSZWNvcmQ6IFJlY29yZElkZW50aXR5O1xufVxuXG4vKipcbiAqIFJlcGxhY2UgaGFzLW1hbnkgcmVsYXRpb25zaGlwIG9wZXJhdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXBsYWNlUmVsYXRlZFJlY29yZHNPcGVyYXRpb24gZXh0ZW5kcyBPcGVyYXRpb24ge1xuICBvcDogJ3JlcGxhY2VSZWxhdGVkUmVjb3Jkcyc7XG4gIHJlY29yZDogUmVjb3JkSWRlbnRpdHk7XG4gIHJlbGF0aW9uc2hpcDogc3RyaW5nO1xuICByZWxhdGVkUmVjb3JkczogUmVjb3JkSWRlbnRpdHlbXTtcbn1cblxuLyoqXG4gKiBSZXBsYWNlIGhhcy1vbmUgcmVsYXRpb25zaGlwIG9wZXJhdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXBsYWNlUmVsYXRlZFJlY29yZE9wZXJhdGlvbiBleHRlbmRzIE9wZXJhdGlvbiB7XG4gIG9wOiAncmVwbGFjZVJlbGF0ZWRSZWNvcmQnO1xuICByZWNvcmQ6IFJlY29yZElkZW50aXR5O1xuICByZWxhdGlvbnNoaXA6IHN0cmluZztcbiAgcmVsYXRlZFJlY29yZDogUmVjb3JkSWRlbnRpdHkgfCBudWxsO1xufVxuXG4vKipcbiAqIFVuaW9uIG9mIGFsbCByZWNvcmQtcmVsYXRlZCBvcGVyYXRpb25zLlxuICovXG5leHBvcnQgdHlwZSBSZWNvcmRPcGVyYXRpb24gPVxuICB8IEFkZFJlY29yZE9wZXJhdGlvblxuICB8IFVwZGF0ZVJlY29yZE9wZXJhdGlvblxuICB8IFJlbW92ZVJlY29yZE9wZXJhdGlvblxuICB8IFJlcGxhY2VLZXlPcGVyYXRpb25cbiAgfCBSZXBsYWNlQXR0cmlidXRlT3BlcmF0aW9uXG4gIHwgQWRkVG9SZWxhdGVkUmVjb3Jkc09wZXJhdGlvblxuICB8IFJlbW92ZUZyb21SZWxhdGVkUmVjb3Jkc09wZXJhdGlvblxuICB8IFJlcGxhY2VSZWxhdGVkUmVjb3Jkc09wZXJhdGlvblxuICB8IFJlcGxhY2VSZWxhdGVkUmVjb3JkT3BlcmF0aW9uO1xuXG5leHBvcnQgdHlwZSBBZGRSZWNvcmRPcGVyYXRpb25SZXN1bHQgPSBJbml0aWFsaXplZFJlY29yZDtcbmV4cG9ydCB0eXBlIFVwZGF0ZVJlY29yZE9wZXJhdGlvblJlc3VsdCA9IHVuZGVmaW5lZDtcbmV4cG9ydCB0eXBlIFJlbW92ZVJlY29yZE9wZXJhdGlvblJlc3VsdCA9IHVuZGVmaW5lZDtcbmV4cG9ydCB0eXBlIFJlcGxhY2VLZXlPcGVyYXRpb25SZXN1bHQgPSB1bmRlZmluZWQ7XG5leHBvcnQgdHlwZSBSZXBsYWNlQXR0cmlidXRlT3BlcmF0aW9uUmVzdWx0ID0gdW5kZWZpbmVkO1xuZXhwb3J0IHR5cGUgQWRkVG9SZWxhdGVkUmVjb3Jkc09wZXJhdGlvblJlc3VsdCA9IHVuZGVmaW5lZDtcbmV4cG9ydCB0eXBlIFJlbW92ZUZyb21SZWxhdGVkUmVjb3Jkc09wZXJhdGlvblJlc3VsdCA9IHVuZGVmaW5lZDtcbmV4cG9ydCB0eXBlIFJlcGxhY2VSZWxhdGVkUmVjb3Jkc09wZXJhdGlvblJlc3VsdCA9IHVuZGVmaW5lZDtcbmV4cG9ydCB0eXBlIFJlcGxhY2VSZWxhdGVkUmVjb3JkT3BlcmF0aW9uUmVzdWx0ID0gdW5kZWZpbmVkO1xuXG5leHBvcnQgdHlwZSBSZWNvcmRPcGVyYXRpb25SZXN1bHQ8VCA9IEluaXRpYWxpemVkUmVjb3JkPiA9IFQgfCB1bmRlZmluZWQ7XG5cbmZ1bmN0aW9uIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShvcGVyYXRpb246IE9wZXJhdGlvbik6IHZvaWQge1xuICBjb25zdCBvOiBhbnkgPSBvcGVyYXRpb247XG4gIG8uX2RlbGV0ZWQgPSB0cnVlO1xufVxuXG5mdW5jdGlvbiBpc09wZXJhdGlvbk1hcmtlZFRvRGVsZXRlKG9wZXJhdGlvbjogT3BlcmF0aW9uKTogYm9vbGVhbiB7XG4gIGNvbnN0IG86IGFueSA9IG9wZXJhdGlvbjtcbiAgcmV0dXJuIG8uX2RlbGV0ZWQgPT09IHRydWU7XG59XG5cbmZ1bmN0aW9uIG1lcmdlT3BlcmF0aW9ucyhcbiAgc3VwZXJjZWRlZDogUmVjb3JkT3BlcmF0aW9uLFxuICBzdXBlcmNlZGluZzogUmVjb3JkT3BlcmF0aW9uLFxuICBjb25zZWN1dGl2ZU9wczogYm9vbGVhblxuKTogdm9pZCB7XG4gIGlmIChzdXBlcmNlZGVkLm9wdGlvbnMgfHwgc3VwZXJjZWRpbmcub3B0aW9ucykge1xuICAgIC8vIGRvIG5vdCBtZXJnZSBpZiBvbmUgb2YgdGhlIG9wZXJhdGlvbnMgaGF2ZSBvcHRpb25zXG4gICAgcmV0dXJuO1xuICB9IGVsc2UgaWYgKGVxdWFsUmVjb3JkSWRlbnRpdGllcyhzdXBlcmNlZGVkLnJlY29yZCwgc3VwZXJjZWRpbmcucmVjb3JkKSkge1xuICAgIGlmIChzdXBlcmNlZGluZy5vcCA9PT0gJ3JlbW92ZVJlY29yZCcpIHtcbiAgICAgIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShzdXBlcmNlZGVkKTtcbiAgICAgIGlmIChzdXBlcmNlZGVkLm9wID09PSAnYWRkUmVjb3JkJykge1xuICAgICAgICBtYXJrT3BlcmF0aW9uVG9EZWxldGUoc3VwZXJjZWRpbmcpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoXG4gICAgICAhaXNPcGVyYXRpb25NYXJrZWRUb0RlbGV0ZShzdXBlcmNlZGluZykgJiZcbiAgICAgIChjb25zZWN1dGl2ZU9wcyB8fCBzdXBlcmNlZGluZy5vcCA9PT0gJ3JlcGxhY2VBdHRyaWJ1dGUnKVxuICAgICkge1xuICAgICAgaWYgKGlzUmVwbGFjZUZpZWxkT3Aoc3VwZXJjZWRlZC5vcCkgJiYgaXNSZXBsYWNlRmllbGRPcChzdXBlcmNlZGluZy5vcCkpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHN1cGVyY2VkZWQub3AgPT09ICdyZXBsYWNlQXR0cmlidXRlJyAmJlxuICAgICAgICAgIHN1cGVyY2VkaW5nLm9wID09PSAncmVwbGFjZUF0dHJpYnV0ZScgJiZcbiAgICAgICAgICBzdXBlcmNlZGVkLmF0dHJpYnV0ZSA9PT0gc3VwZXJjZWRpbmcuYXR0cmlidXRlXG4gICAgICAgICkge1xuICAgICAgICAgIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShzdXBlcmNlZGVkKTtcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICBzdXBlcmNlZGVkLm9wID09PSAncmVwbGFjZVJlbGF0ZWRSZWNvcmQnICYmXG4gICAgICAgICAgc3VwZXJjZWRpbmcub3AgPT09ICdyZXBsYWNlUmVsYXRlZFJlY29yZCcgJiZcbiAgICAgICAgICBzdXBlcmNlZGVkLnJlbGF0aW9uc2hpcCA9PT0gc3VwZXJjZWRpbmcucmVsYXRpb25zaGlwXG4gICAgICAgICkge1xuICAgICAgICAgIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShzdXBlcmNlZGVkKTtcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICBzdXBlcmNlZGVkLm9wID09PSAncmVwbGFjZVJlbGF0ZWRSZWNvcmRzJyAmJlxuICAgICAgICAgIHN1cGVyY2VkaW5nLm9wID09PSAncmVwbGFjZVJlbGF0ZWRSZWNvcmRzJyAmJlxuICAgICAgICAgIHN1cGVyY2VkZWQucmVsYXRpb25zaGlwID09PSBzdXBlcmNlZGluZy5yZWxhdGlvbnNoaXBcbiAgICAgICAgKSB7XG4gICAgICAgICAgbWFya09wZXJhdGlvblRvRGVsZXRlKHN1cGVyY2VkZWQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChzdXBlcmNlZGVkLm9wID09PSAncmVwbGFjZUF0dHJpYnV0ZScpIHtcbiAgICAgICAgICAgIHVwZGF0ZVJlY29yZFJlcGxhY2VBdHRyaWJ1dGUoXG4gICAgICAgICAgICAgIHN1cGVyY2VkZWQucmVjb3JkLFxuICAgICAgICAgICAgICBzdXBlcmNlZGVkLmF0dHJpYnV0ZSxcbiAgICAgICAgICAgICAgc3VwZXJjZWRlZC52YWx1ZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGRlbGV0ZSAoc3VwZXJjZWRlZCBhcyBhbnkpLmF0dHJpYnV0ZTtcbiAgICAgICAgICAgIGRlbGV0ZSBzdXBlcmNlZGVkLnZhbHVlO1xuICAgICAgICAgIH0gZWxzZSBpZiAoc3VwZXJjZWRlZC5vcCA9PT0gJ3JlcGxhY2VSZWxhdGVkUmVjb3JkJykge1xuICAgICAgICAgICAgdXBkYXRlUmVjb3JkUmVwbGFjZUhhc09uZShcbiAgICAgICAgICAgICAgc3VwZXJjZWRlZC5yZWNvcmQsXG4gICAgICAgICAgICAgIHN1cGVyY2VkZWQucmVsYXRpb25zaGlwLFxuICAgICAgICAgICAgICBzdXBlcmNlZGVkLnJlbGF0ZWRSZWNvcmRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBkZWxldGUgKHN1cGVyY2VkZWQgYXMgYW55KS5yZWxhdGlvbnNoaXA7XG4gICAgICAgICAgICBkZWxldGUgKHN1cGVyY2VkZWQgYXMgYW55KS5yZWxhdGVkUmVjb3JkO1xuICAgICAgICAgIH0gZWxzZSBpZiAoc3VwZXJjZWRlZC5vcCA9PT0gJ3JlcGxhY2VSZWxhdGVkUmVjb3JkcycpIHtcbiAgICAgICAgICAgIHVwZGF0ZVJlY29yZFJlcGxhY2VIYXNNYW55KFxuICAgICAgICAgICAgICBzdXBlcmNlZGVkLnJlY29yZCxcbiAgICAgICAgICAgICAgc3VwZXJjZWRlZC5yZWxhdGlvbnNoaXAsXG4gICAgICAgICAgICAgIHN1cGVyY2VkZWQucmVsYXRlZFJlY29yZHNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBkZWxldGUgKHN1cGVyY2VkZWQgYXMgYW55KS5yZWxhdGlvbnNoaXA7XG4gICAgICAgICAgICBkZWxldGUgKHN1cGVyY2VkZWQgYXMgYW55KS5yZWxhdGVkUmVjb3JkcztcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHN1cGVyY2VkaW5nLm9wID09PSAncmVwbGFjZUF0dHJpYnV0ZScpIHtcbiAgICAgICAgICAgIHVwZGF0ZVJlY29yZFJlcGxhY2VBdHRyaWJ1dGUoXG4gICAgICAgICAgICAgIHN1cGVyY2VkZWQucmVjb3JkLFxuICAgICAgICAgICAgICBzdXBlcmNlZGluZy5hdHRyaWJ1dGUsXG4gICAgICAgICAgICAgIHN1cGVyY2VkaW5nLnZhbHVlXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSBpZiAoc3VwZXJjZWRpbmcub3AgPT09ICdyZXBsYWNlUmVsYXRlZFJlY29yZCcpIHtcbiAgICAgICAgICAgIHVwZGF0ZVJlY29yZFJlcGxhY2VIYXNPbmUoXG4gICAgICAgICAgICAgIHN1cGVyY2VkZWQucmVjb3JkLFxuICAgICAgICAgICAgICBzdXBlcmNlZGluZy5yZWxhdGlvbnNoaXAsXG4gICAgICAgICAgICAgIHN1cGVyY2VkaW5nLnJlbGF0ZWRSZWNvcmRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIGlmIChzdXBlcmNlZGluZy5vcCA9PT0gJ3JlcGxhY2VSZWxhdGVkUmVjb3JkcycpIHtcbiAgICAgICAgICAgIHVwZGF0ZVJlY29yZFJlcGxhY2VIYXNNYW55KFxuICAgICAgICAgICAgICBzdXBlcmNlZGVkLnJlY29yZCxcbiAgICAgICAgICAgICAgc3VwZXJjZWRpbmcucmVsYXRpb25zaGlwLFxuICAgICAgICAgICAgICBzdXBlcmNlZGluZy5yZWxhdGVkUmVjb3Jkc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgc3VwZXJjZWRlZC5vcCA9ICd1cGRhdGVSZWNvcmQnO1xuICAgICAgICAgIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShzdXBlcmNlZGluZyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIChzdXBlcmNlZGVkLm9wID09PSAnYWRkUmVjb3JkJyB8fFxuICAgICAgICAgIHN1cGVyY2VkZWQub3AgPT09ICd1cGRhdGVSZWNvcmQnIHx8XG4gICAgICAgICAgKHN1cGVyY2VkZWQgYXMgYW55KS5vcCA9PT0gJ3JlcGxhY2VSZWNvcmQnKSAmJlxuICAgICAgICAoc3VwZXJjZWRpbmcub3AgPT09ICd1cGRhdGVSZWNvcmQnIHx8XG4gICAgICAgICAgKHN1cGVyY2VkaW5nIGFzIGFueSkub3AgPT09ICdyZXBsYWNlUmVjb3JkJylcbiAgICAgICkge1xuICAgICAgICBzdXBlcmNlZGVkLnJlY29yZCA9IG1lcmdlUmVjb3JkcyhzdXBlcmNlZGVkLnJlY29yZCwgc3VwZXJjZWRpbmcucmVjb3JkKTtcbiAgICAgICAgbWFya09wZXJhdGlvblRvRGVsZXRlKHN1cGVyY2VkaW5nKTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIChzdXBlcmNlZGVkLm9wID09PSAnYWRkUmVjb3JkJyB8fFxuICAgICAgICAgIHN1cGVyY2VkZWQub3AgPT09ICd1cGRhdGVSZWNvcmQnIHx8XG4gICAgICAgICAgKHN1cGVyY2VkZWQgYXMgYW55KS5vcCA9PT0gJ3JlcGxhY2VSZWNvcmQnKSAmJlxuICAgICAgICBpc1JlcGxhY2VGaWVsZE9wKHN1cGVyY2VkaW5nLm9wKVxuICAgICAgKSB7XG4gICAgICAgIGlmIChzdXBlcmNlZGluZy5vcCA9PT0gJ3JlcGxhY2VBdHRyaWJ1dGUnKSB7XG4gICAgICAgICAgdXBkYXRlUmVjb3JkUmVwbGFjZUF0dHJpYnV0ZShcbiAgICAgICAgICAgIHN1cGVyY2VkZWQucmVjb3JkLFxuICAgICAgICAgICAgc3VwZXJjZWRpbmcuYXR0cmlidXRlLFxuICAgICAgICAgICAgc3VwZXJjZWRpbmcudmFsdWVcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2UgaWYgKHN1cGVyY2VkaW5nLm9wID09PSAncmVwbGFjZVJlbGF0ZWRSZWNvcmQnKSB7XG4gICAgICAgICAgdXBkYXRlUmVjb3JkUmVwbGFjZUhhc09uZShcbiAgICAgICAgICAgIHN1cGVyY2VkZWQucmVjb3JkLFxuICAgICAgICAgICAgc3VwZXJjZWRpbmcucmVsYXRpb25zaGlwLFxuICAgICAgICAgICAgc3VwZXJjZWRpbmcucmVsYXRlZFJlY29yZFxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAoc3VwZXJjZWRpbmcub3AgPT09ICdyZXBsYWNlUmVsYXRlZFJlY29yZHMnKSB7XG4gICAgICAgICAgdXBkYXRlUmVjb3JkUmVwbGFjZUhhc01hbnkoXG4gICAgICAgICAgICBzdXBlcmNlZGVkLnJlY29yZCxcbiAgICAgICAgICAgIHN1cGVyY2VkaW5nLnJlbGF0aW9uc2hpcCxcbiAgICAgICAgICAgIHN1cGVyY2VkaW5nLnJlbGF0ZWRSZWNvcmRzXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBtYXJrT3BlcmF0aW9uVG9EZWxldGUoc3VwZXJjZWRpbmcpO1xuICAgICAgfSBlbHNlIGlmIChzdXBlcmNlZGluZy5vcCA9PT0gJ2FkZFRvUmVsYXRlZFJlY29yZHMnKSB7XG4gICAgICAgIGlmIChzdXBlcmNlZGVkLm9wID09PSAnYWRkUmVjb3JkJykge1xuICAgICAgICAgIHVwZGF0ZVJlY29yZEFkZFRvSGFzTWFueShcbiAgICAgICAgICAgIHN1cGVyY2VkZWQucmVjb3JkLFxuICAgICAgICAgICAgc3VwZXJjZWRpbmcucmVsYXRpb25zaGlwLFxuICAgICAgICAgICAgc3VwZXJjZWRpbmcucmVsYXRlZFJlY29yZFxuICAgICAgICAgICk7XG4gICAgICAgICAgbWFya09wZXJhdGlvblRvRGVsZXRlKHN1cGVyY2VkaW5nKTtcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICBzdXBlcmNlZGVkLm9wID09PSAndXBkYXRlUmVjb3JkJyB8fFxuICAgICAgICAgIChzdXBlcmNlZGVkIGFzIGFueSkub3AgPT09ICdyZXBsYWNlUmVjb3JkJ1xuICAgICAgICApIHtcbiAgICAgICAgICBsZXQgcmVjb3JkOiBJbml0aWFsaXplZFJlY29yZCA9IHN1cGVyY2VkZWQucmVjb3JkO1xuICAgICAgICAgIGlmIChyZWNvcmQucmVsYXRpb25zaGlwcz8uW3N1cGVyY2VkaW5nLnJlbGF0aW9uc2hpcF0/LmRhdGEpIHtcbiAgICAgICAgICAgIHVwZGF0ZVJlY29yZEFkZFRvSGFzTWFueShcbiAgICAgICAgICAgICAgc3VwZXJjZWRlZC5yZWNvcmQsXG4gICAgICAgICAgICAgIHN1cGVyY2VkaW5nLnJlbGF0aW9uc2hpcCxcbiAgICAgICAgICAgICAgc3VwZXJjZWRpbmcucmVsYXRlZFJlY29yZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShzdXBlcmNlZGluZyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHN1cGVyY2VkaW5nLm9wID09PSAncmVtb3ZlRnJvbVJlbGF0ZWRSZWNvcmRzJykge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgc3VwZXJjZWRlZC5vcCA9PT0gJ2FkZFRvUmVsYXRlZFJlY29yZHMnICYmXG4gICAgICAgICAgc3VwZXJjZWRlZC5yZWxhdGlvbnNoaXAgPT09IHN1cGVyY2VkaW5nLnJlbGF0aW9uc2hpcCAmJlxuICAgICAgICAgIGVxdWFsUmVjb3JkSWRlbnRpdGllcyhcbiAgICAgICAgICAgIHN1cGVyY2VkZWQucmVsYXRlZFJlY29yZCxcbiAgICAgICAgICAgIHN1cGVyY2VkaW5nLnJlbGF0ZWRSZWNvcmRcbiAgICAgICAgICApXG4gICAgICAgICkge1xuICAgICAgICAgIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShzdXBlcmNlZGVkKTtcbiAgICAgICAgICBtYXJrT3BlcmF0aW9uVG9EZWxldGUoc3VwZXJjZWRpbmcpO1xuICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgIHN1cGVyY2VkZWQub3AgPT09ICdhZGRSZWNvcmQnIHx8XG4gICAgICAgICAgc3VwZXJjZWRlZC5vcCA9PT0gJ3VwZGF0ZVJlY29yZCcgfHxcbiAgICAgICAgICAoc3VwZXJjZWRlZCBhcyBhbnkpLm9wID09PSAncmVwbGFjZVJlY29yZCdcbiAgICAgICAgKSB7XG4gICAgICAgICAgbGV0IHJlY29yZDogSW5pdGlhbGl6ZWRSZWNvcmQgPSBzdXBlcmNlZGVkLnJlY29yZDtcbiAgICAgICAgICBpZiAocmVjb3JkLnJlbGF0aW9uc2hpcHM/LltzdXBlcmNlZGluZy5yZWxhdGlvbnNoaXBdPy5kYXRhKSB7XG4gICAgICAgICAgICB1cGRhdGVSZWNvcmRSZW1vdmVGcm9tSGFzTWFueShcbiAgICAgICAgICAgICAgc3VwZXJjZWRlZC5yZWNvcmQsXG4gICAgICAgICAgICAgIHN1cGVyY2VkaW5nLnJlbGF0aW9uc2hpcCxcbiAgICAgICAgICAgICAgc3VwZXJjZWRpbmcucmVsYXRlZFJlY29yZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIG1hcmtPcGVyYXRpb25Ub0RlbGV0ZShzdXBlcmNlZGluZyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9IGVsc2UgaWYgKHN1cGVyY2VkaW5nLnJlY29yZCAmJiBzdXBlcmNlZGluZy5vcCA9PT0gJ3JlbW92ZVJlY29yZCcpIHtcbiAgICBpZiAoXG4gICAgICAoc3VwZXJjZWRlZCBhcyBSZXBsYWNlUmVsYXRlZFJlY29yZE9wZXJhdGlvbikucmVsYXRlZFJlY29yZCAmJlxuICAgICAgZXF1YWxSZWNvcmRJZGVudGl0aWVzKFxuICAgICAgICAoc3VwZXJjZWRlZCBhcyBSZXBsYWNlUmVsYXRlZFJlY29yZE9wZXJhdGlvbilcbiAgICAgICAgICAucmVsYXRlZFJlY29yZCBhcyBSZWNvcmRJZGVudGl0eSxcbiAgICAgICAgc3VwZXJjZWRpbmcucmVjb3JkXG4gICAgICApXG4gICAgKSB7XG4gICAgICBtYXJrT3BlcmF0aW9uVG9EZWxldGUoc3VwZXJjZWRlZCk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGlzUmVwbGFjZUZpZWxkT3Aob3A6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIG9wID09PSAncmVwbGFjZUF0dHJpYnV0ZScgfHxcbiAgICBvcCA9PT0gJ3JlcGxhY2VSZWxhdGVkUmVjb3JkJyB8fFxuICAgIG9wID09PSAncmVwbGFjZVJlbGF0ZWRSZWNvcmRzJ1xuICApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVSZWNvcmRSZXBsYWNlQXR0cmlidXRlKFxuICByZWNvcmQ6IEluaXRpYWxpemVkUmVjb3JkLFxuICBhdHRyaWJ1dGU6IHN0cmluZyxcbiAgdmFsdWU6IHVua25vd25cbikge1xuICBkZWVwU2V0KHJlY29yZCwgWydhdHRyaWJ1dGVzJywgYXR0cmlidXRlXSwgdmFsdWUpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVSZWNvcmRSZXBsYWNlSGFzT25lKFxuICByZWNvcmQ6IEluaXRpYWxpemVkUmVjb3JkLFxuICByZWxhdGlvbnNoaXA6IHN0cmluZyxcbiAgcmVsYXRlZFJlY29yZDogUmVjb3JkSWRlbnRpdHkgfCBudWxsXG4pIHtcbiAgZGVlcFNldChcbiAgICByZWNvcmQsXG4gICAgWydyZWxhdGlvbnNoaXBzJywgcmVsYXRpb25zaGlwLCAnZGF0YSddLFxuICAgIHJlbGF0ZWRSZWNvcmQgPyBjbG9uZVJlY29yZElkZW50aXR5KHJlbGF0ZWRSZWNvcmQpIDogbnVsbFxuICApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVSZWNvcmRSZXBsYWNlSGFzTWFueShcbiAgcmVjb3JkOiBJbml0aWFsaXplZFJlY29yZCxcbiAgcmVsYXRpb25zaGlwOiBzdHJpbmcsXG4gIHJlbGF0ZWRSZWNvcmRzOiBSZWNvcmRJZGVudGl0eVtdXG4pIHtcbiAgZGVlcFNldChcbiAgICByZWNvcmQsXG4gICAgWydyZWxhdGlvbnNoaXBzJywgcmVsYXRpb25zaGlwLCAnZGF0YSddLFxuICAgIHJlbGF0ZWRSZWNvcmRzLm1hcChjbG9uZVJlY29yZElkZW50aXR5KVxuICApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVSZWNvcmRBZGRUb0hhc01hbnkoXG4gIHJlY29yZDogSW5pdGlhbGl6ZWRSZWNvcmQsXG4gIHJlbGF0aW9uc2hpcDogc3RyaW5nLFxuICByZWxhdGVkUmVjb3JkOiBSZWNvcmRJZGVudGl0eVxuKSB7XG4gIGNvbnN0IGRhdGEgPSBkZWVwR2V0KHJlY29yZCwgWydyZWxhdGlvbnNoaXBzJywgcmVsYXRpb25zaGlwLCAnZGF0YSddKSB8fCBbXTtcbiAgZGF0YS5wdXNoKGNsb25lUmVjb3JkSWRlbnRpdHkocmVsYXRlZFJlY29yZCkpO1xuICBkZWVwU2V0KHJlY29yZCwgWydyZWxhdGlvbnNoaXBzJywgcmVsYXRpb25zaGlwLCAnZGF0YSddLCBkYXRhKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlUmVjb3JkUmVtb3ZlRnJvbUhhc01hbnkoXG4gIHJlY29yZDogSW5pdGlhbGl6ZWRSZWNvcmQsXG4gIHJlbGF0aW9uc2hpcDogc3RyaW5nLFxuICByZWxhdGVkUmVjb3JkOiBSZWNvcmRJZGVudGl0eVxuKSB7XG4gIGNvbnN0IGRhdGEgPSBkZWVwR2V0KHJlY29yZCwgW1xuICAgICdyZWxhdGlvbnNoaXBzJyxcbiAgICByZWxhdGlvbnNoaXAsXG4gICAgJ2RhdGEnXG4gIF0pIGFzIFJlY29yZElkZW50aXR5W107XG4gIGlmIChkYXRhKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGwgPSBkYXRhLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgbGV0IHIgPSBkYXRhW2ldO1xuICAgICAgaWYgKGVxdWFsUmVjb3JkSWRlbnRpdGllcyhyLCByZWxhdGVkUmVjb3JkKSkge1xuICAgICAgICBkYXRhLnNwbGljZShpLCAxKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ29hbGVzY2VzIG9wZXJhdGlvbnMgaW50byBhIG1pbmltYWwgc2V0IG9mIGVxdWl2YWxlbnQgb3BlcmF0aW9ucy5cbiAqXG4gKiBUaGlzIG1ldGhvZCByZXNwZWN0cyB0aGUgb3JkZXIgb2YgdGhlIG9wZXJhdGlvbnMgYXJyYXkgYW5kIGRvZXMgbm90IGFsbG93XG4gKiByZW9yZGVyaW5nIG9mIG9wZXJhdGlvbnMgdGhhdCBhZmZlY3QgcmVsYXRpb25zaGlwcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvYWxlc2NlUmVjb3JkT3BlcmF0aW9ucyhcbiAgb3BlcmF0aW9uczogUmVjb3JkT3BlcmF0aW9uW11cbik6IFJlY29yZE9wZXJhdGlvbltdIHtcbiAgZm9yIChsZXQgaSA9IDAsIGwgPSBvcGVyYXRpb25zLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIGxldCBjdXJyZW50T3AgPSBvcGVyYXRpb25zW2ldO1xuICAgIGxldCBjb25zZWN1dGl2ZU9wcyA9IHRydWU7XG5cbiAgICBmb3IgKGxldCBqID0gaSArIDE7IGogPCBsOyBqKyspIHtcbiAgICAgIGxldCBuZXh0T3AgPSBvcGVyYXRpb25zW2pdO1xuXG4gICAgICBtZXJnZU9wZXJhdGlvbnMoY3VycmVudE9wLCBuZXh0T3AsIGNvbnNlY3V0aXZlT3BzKTtcblxuICAgICAgaWYgKGlzT3BlcmF0aW9uTWFya2VkVG9EZWxldGUoY3VycmVudE9wKSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH0gZWxzZSBpZiAoIWlzT3BlcmF0aW9uTWFya2VkVG9EZWxldGUobmV4dE9wKSkge1xuICAgICAgICBjb25zZWN1dGl2ZU9wcyA9IGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBvcGVyYXRpb25zLmZpbHRlcigobykgPT4gIWlzT3BlcmF0aW9uTWFya2VkVG9EZWxldGUobykpO1xufVxuXG4vKipcbiAqIERldGVybWluZSB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBhIHJlY29yZCBhbmQgaXRzIHVwZGF0ZWQgdmVyc2lvbiBpbiB0ZXJtc1xuICogb2YgYSBzZXQgb2Ygb3BlcmF0aW9ucy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlY29yZERpZmZzKFxuICByZWNvcmQ6IEluaXRpYWxpemVkUmVjb3JkLFxuICB1cGRhdGVkUmVjb3JkOiBJbml0aWFsaXplZFJlY29yZFxuKTogUmVjb3JkT3BlcmF0aW9uW10ge1xuICBjb25zdCBvcHM6IFJlY29yZE9wZXJhdGlvbltdID0gW107XG5cbiAgaWYgKHJlY29yZCAmJiB1cGRhdGVkUmVjb3JkKSB7XG4gICAgbGV0IGZ1bGxSZWNvcmRVcGRhdGUgPSBmYWxzZTtcbiAgICBjb25zdCByZWNvcmRJZGVudGl0eSA9IGNsb25lUmVjb3JkSWRlbnRpdHkocmVjb3JkKTtcbiAgICBjb25zdCBkaWZmUmVjb3JkOiBJbml0aWFsaXplZFJlY29yZCA9IHsgLi4ucmVjb3JkSWRlbnRpdHkgfTtcblxuICAgIGZvciAobGV0IG1lbWJlciBpbiB1cGRhdGVkUmVjb3JkKSB7XG4gICAgICBpZiAobWVtYmVyICE9PSAnaWQnICYmIG1lbWJlciAhPT0gJ3R5cGUnKSB7XG4gICAgICAgIGxldCB2YWx1ZTogdW5rbm93bjtcbiAgICAgICAgbGV0IHVwZGF0ZWRWYWx1ZTogdW5rbm93bjtcblxuICAgICAgICBzd2l0Y2ggKG1lbWJlcikge1xuICAgICAgICAgIGNhc2UgJ2F0dHJpYnV0ZXMnOlxuICAgICAgICAgIGNhc2UgJ2tleXMnOlxuICAgICAgICAgIGNhc2UgJ3JlbGF0aW9uc2hpcHMnOlxuICAgICAgICAgICAgZm9yIChsZXQgZmllbGQgaW4gdXBkYXRlZFJlY29yZFttZW1iZXJdKSB7XG4gICAgICAgICAgICAgIHZhbHVlID0gcmVjb3JkW21lbWJlcl0/LltmaWVsZF07XG4gICAgICAgICAgICAgIHVwZGF0ZWRWYWx1ZSA9ICh1cGRhdGVkUmVjb3JkW21lbWJlcl0gYXMgYW55KVtmaWVsZF07XG5cbiAgICAgICAgICAgICAgaWYgKCFlcSh2YWx1ZSwgdXBkYXRlZFZhbHVlKSkge1xuICAgICAgICAgICAgICAgIGlmIChtZW1iZXIgPT09ICdyZWxhdGlvbnNoaXBzJykge1xuICAgICAgICAgICAgICAgICAgZnVsbFJlY29yZFVwZGF0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlZXBTZXQoZGlmZlJlY29yZCwgW21lbWJlciwgZmllbGRdLCB1cGRhdGVkVmFsdWUpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB2YWx1ZSA9IChyZWNvcmQgYXMgYW55KVttZW1iZXJdO1xuICAgICAgICAgICAgdXBkYXRlZFZhbHVlID0gKHVwZGF0ZWRSZWNvcmQgYXMgYW55KVttZW1iZXJdO1xuXG4gICAgICAgICAgICBpZiAoIWVxKHVwZGF0ZWRWYWx1ZSwgdmFsdWUpKSB7XG4gICAgICAgICAgICAgIChkaWZmUmVjb3JkIGFzIGFueSlbbWVtYmVyXSA9IHVwZGF0ZWRWYWx1ZTtcbiAgICAgICAgICAgICAgZnVsbFJlY29yZFVwZGF0ZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBJZiB1cGRhdGVzIGNvbnNpc3Qgc29sZWx5IG9mIGF0dHJpYnV0ZXMgYW5kIGtleXMsIHVwZGF0ZSBmaWVsZHNcbiAgICAvLyB3aXRoIGluZGl2aWR1YWwgb3BlcmF0aW9ucy4gT3RoZXJ3aXNlLCB1cGRhdGUgdGhlIHJlY29yZCBhcyBhXG4gICAgLy8gd2hvbGUuXG4gICAgaWYgKGZ1bGxSZWNvcmRVcGRhdGUpIHtcbiAgICAgIGxldCBvcDogVXBkYXRlUmVjb3JkT3BlcmF0aW9uID0ge1xuICAgICAgICBvcDogJ3VwZGF0ZVJlY29yZCcsXG4gICAgICAgIHJlY29yZDogZGlmZlJlY29yZFxuICAgICAgfTtcbiAgICAgIG9wcy5wdXNoKG9wKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGRpZmZSZWNvcmQuYXR0cmlidXRlcykge1xuICAgICAgICBmb3IgKGxldCBhdHRyaWJ1dGUgaW4gZGlmZlJlY29yZC5hdHRyaWJ1dGVzKSB7XG4gICAgICAgICAgbGV0IHZhbHVlID0gZGlmZlJlY29yZC5hdHRyaWJ1dGVzW2F0dHJpYnV0ZV07XG4gICAgICAgICAgbGV0IG9wOiBSZXBsYWNlQXR0cmlidXRlT3BlcmF0aW9uID0ge1xuICAgICAgICAgICAgb3A6ICdyZXBsYWNlQXR0cmlidXRlJyxcbiAgICAgICAgICAgIHJlY29yZDogcmVjb3JkSWRlbnRpdHksXG4gICAgICAgICAgICBhdHRyaWJ1dGUsXG4gICAgICAgICAgICB2YWx1ZVxuICAgICAgICAgIH07XG4gICAgICAgICAgb3BzLnB1c2gob3ApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZGlmZlJlY29yZC5rZXlzKSB7XG4gICAgICAgIGZvciAobGV0IGtleSBpbiBkaWZmUmVjb3JkLmtleXMpIHtcbiAgICAgICAgICBsZXQgdmFsdWUgPSBkaWZmUmVjb3JkLmtleXNba2V5XTtcbiAgICAgICAgICBsZXQgb3A6IFJlcGxhY2VLZXlPcGVyYXRpb24gPSB7XG4gICAgICAgICAgICBvcDogJ3JlcGxhY2VLZXknLFxuICAgICAgICAgICAgcmVjb3JkOiByZWNvcmRJZGVudGl0eSxcbiAgICAgICAgICAgIGtleSxcbiAgICAgICAgICAgIHZhbHVlXG4gICAgICAgICAgfTtcbiAgICAgICAgICBvcHMucHVzaChvcCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gb3BzO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGRlZHVwZWQgaWRlbnRpdGllcyBvZiBhbGwgdGhlIHJlY29yZHMgZGlyZWN0bHkgcmVmZXJlbmNlZCBieSBhblxuICogYXJyYXkgb2Ygb3BlcmF0aW9ucy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlY29yZHNSZWZlcmVuY2VkQnlPcGVyYXRpb25zKFxuICBvcGVyYXRpb25zOiBSZWNvcmRPcGVyYXRpb25bXVxuKTogUmVjb3JkSWRlbnRpdHlbXSB7XG4gIGNvbnN0IHJlY29yZHMgPSBbXTtcblxuICBmb3IgKGxldCBvcGVyYXRpb24gb2Ygb3BlcmF0aW9ucykge1xuICAgIGlmIChvcGVyYXRpb24ucmVjb3JkKSB7XG4gICAgICByZWNvcmRzLnB1c2gob3BlcmF0aW9uLnJlY29yZCk7XG5cbiAgICAgIGlmIChvcGVyYXRpb24ub3AgPT09ICdhZGRSZWNvcmQnIHx8IG9wZXJhdGlvbi5vcCA9PT0gJ3VwZGF0ZVJlY29yZCcpIHtcbiAgICAgICAgbGV0IHJlY29yZCA9IG9wZXJhdGlvbi5yZWNvcmQ7XG4gICAgICAgIGlmIChyZWNvcmQucmVsYXRpb25zaGlwcykge1xuICAgICAgICAgIGZvciAobGV0IHJlbE5hbWUgaW4gcmVjb3JkLnJlbGF0aW9uc2hpcHMpIHtcbiAgICAgICAgICAgIGxldCByZWwgPSByZWNvcmQucmVsYXRpb25zaGlwc1tyZWxOYW1lXTtcbiAgICAgICAgICAgIGlmIChyZWw/LmRhdGEpIHtcbiAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVsLmRhdGEpKSB7XG4gICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkocmVjb3JkcywgcmVsLmRhdGEpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29yZHMucHVzaChyZWwuZGF0YSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKFxuICAgICAgb3BlcmF0aW9uLm9wID09PSAnYWRkVG9SZWxhdGVkUmVjb3JkcycgfHxcbiAgICAgIG9wZXJhdGlvbi5vcCA9PT0gJ3JlbW92ZUZyb21SZWxhdGVkUmVjb3JkcycgfHxcbiAgICAgIG9wZXJhdGlvbi5vcCA9PT0gJ3JlcGxhY2VSZWxhdGVkUmVjb3JkJ1xuICAgICkge1xuICAgICAgaWYgKG9wZXJhdGlvbi5yZWxhdGVkUmVjb3JkKSB7XG4gICAgICAgIHJlY29yZHMucHVzaChvcGVyYXRpb24ucmVsYXRlZFJlY29yZCk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChvcGVyYXRpb24ub3AgPT09ICdyZXBsYWNlUmVsYXRlZFJlY29yZHMnKSB7XG4gICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShyZWNvcmRzLCBvcGVyYXRpb24ucmVsYXRlZFJlY29yZHMpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBkZWR1cGVSZWNvcmRJZGVudGl0aWVzKHJlY29yZHMpO1xufVxuIl19