UNPKG

@orbit/records

Version:

A flexible data access and synchronization layer.

311 lines 49.6 kB
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