UNPKG

ngx-dynamic-hooks

Version:

Automatically insert live Angular components into a dynamic string of content (based on their selector or any pattern of your choice) and render the result in the DOM.

147 lines 18.7 kB
import { Injectable } from '@angular/core'; import { getParseOptionDefaults } from '../settings/options'; import * as i0 from "@angular/core"; import * as i1 from "./logger"; /** * A service for comparing two variables by value instead of by reference */ export class DeepComparer { // 1. Inputs // ----------------------------------------------------------------- constructor(logger) { this.logger = logger; } /** * Tests if two objects are equal by value * * @param a - The first object * @param b - The second object * @param compareDepth - How many levels deep to compare * @param options - The current parseOptions */ isEqual(a, b, compareDepth, options = getParseOptionDefaults()) { const aStringified = this.detailedStringify(a, compareDepth); const bStringified = this.detailedStringify(b, compareDepth); if (aStringified.result === null || bStringified.result === null) { this.logger.warn([ 'Objects could not be compared by value as one or both of them could not be stringified. Returning false. \n', 'Objects:', a, b ], options); return false; } return aStringified.result === bStringified.result; } /** * Like JSON.stringify, but stringifies additional datatypes that would have been * nulled otherwise. It also doesn't throw errors on cyclic property paths. * * If obj can't be stringified for whatever reason, returns null. * * @param obj - The object to stringify * @param depth - How many levels deep to stringify */ detailedStringify(obj, depth) { try { // Null cyclic paths const depthReached = { count: 0 }; const decylcedObj = this.decycle(obj, [], depth, depthReached); const stringified = JSON.stringify(decylcedObj, (key, value) => { // If undefined if (value === undefined) { return 'undefined'; } // If function or class if (typeof value === 'function') { return value.toString(); } // If symbol if (typeof value === 'symbol') { return value.toString(); } return value; }); return { result: stringified, depthReachedCount: depthReached.count }; } catch (e) { return { result: null, depthReachedCount: 0 }; } } /** * Travels on object and replaces cyclical references with null * * @param obj - The object to travel * @param stack - To keep track of already travelled objects * @param depth - How many levels deep to decycle * @param depthReached - An object to track the number of times the max depth was reached */ decycle(obj, stack = [], depth = 5, depthReached) { if (stack.length > depth) { depthReached.count++; return null; } if (!obj || typeof obj !== 'object' || obj instanceof Date) { return obj; } // Check if cyclical and we've traveled this obj already // // Note: Test this not by object reference, but by object PROPERTY reference/equality. If an object has identical properties, // the object is to be considered identical even if it has a different reference itself. // // Explanation: This is to prevent a sneaky bug when comparing by value and a parser returns an object as an input that contains a reference to the object holding it // (like returning the context object that contains a reference to the parent component holding the context object). // In this example, when the context object changes by reference, the old input will be compared with the new input. However, as the old input consists of // the old context object that now (through the parent component) contains a reference to the new context object, while the new input references the new context // object exclusively, the decycle function would produce different results for them if it only checked cyclical paths by reference (even if the context object // remained identical in value!) // // Though an unlikely scenario, checking cyclical paths via object properties rather than the object reference itself solves this problem. for (const stackObj of stack) { if (this.objEqualsProperties(obj, stackObj)) { return null; } } const s = stack.concat([obj]); if (Array.isArray(obj)) { const newArray = []; for (const entry of obj) { newArray.push(this.decycle(entry, s, depth, depthReached)); } return newArray; } else { const newObj = {}; for (const key of Object.keys(obj)) { newObj[key] = this.decycle(obj[key], s, depth, depthReached); } return newObj; } } /** * Returns true when all the properties of one object equal those of another object, otherwise false. * * @param a - The first object * @param b - The second object */ objEqualsProperties(a, b) { const aKeys = Object.keys(a); const bKeys = Object.keys(b); if (aKeys.length !== bKeys.length) { return false; } for (const aKey of aKeys) { if (a[aKey] !== b[aKey]) { return false; } } return true; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DeepComparer, deps: [{ token: i1.Logger }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DeepComparer, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DeepComparer, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.Logger }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVlcENvbXBhcmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWR5bmFtaWMtaG9va3Mvc3JjL2xpYi9zZXJ2aWNlcy91dGlscy9kZWVwQ29tcGFyZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUzQyxPQUFPLEVBQUUsc0JBQXNCLEVBQWdCLE1BQU0scUJBQXFCLENBQUM7OztBQVkzRTs7R0FFRztBQUlILE1BQU0sT0FBTyxZQUFZO0lBRXZCLFlBQVk7SUFDWixvRUFBb0U7SUFFcEUsWUFBb0IsTUFBYztRQUFkLFdBQU0sR0FBTixNQUFNLENBQVE7SUFDbEMsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxPQUFPLENBQUMsQ0FBTSxFQUFFLENBQU0sRUFBRSxZQUFxQixFQUFFLFVBQXdCLHNCQUFzQixFQUFFO1FBQzdGLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDN0QsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUU3RCxJQUFJLFlBQVksQ0FBQyxNQUFNLEtBQUssSUFBSSxJQUFJLFlBQVksQ0FBQyxNQUFNLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDakUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUM7Z0JBQ2YsNkdBQTZHO2dCQUM3RyxVQUFVLEVBQUUsQ0FBQyxFQUFFLENBQUM7YUFDakIsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUNaLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELE9BQU8sWUFBWSxDQUFDLE1BQU0sS0FBSyxZQUFZLENBQUMsTUFBTSxDQUFDO0lBQ3JELENBQUM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNILGlCQUFpQixDQUFDLEdBQVEs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Q0FBQztnQkFDbkMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFDL0QsQ0FBQztZQUNELE9BQU8sTUFBTSxDQUFDO1FBQ2hCLENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxtQkFBbUIsQ0FBQyxDQUFNLEVBQUUsQ0FBTTtRQUNoQyxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzdCLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFN0IsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNsQyxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFFRCxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUN4QixPQUFPLEtBQUssQ0FBQztZQUNmLENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDOytHQS9JVSxZQUFZO21IQUFaLFlBQVksY0FGWCxNQUFNOzs0RkFFUCxZQUFZO2tCQUh4QixVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gJy4vbG9nZ2VyJztcbmltcG9ydCB7IGdldFBhcnNlT3B0aW9uRGVmYXVsdHMsIFBhcnNlT3B0aW9ucyB9IGZyb20gJy4uL3NldHRpbmdzL29wdGlvbnMnO1xuXG5cbi8qKlxuICogVGhlIG9iamVjdCByZXR1cm5lZCBieSB0aGUgZGV0YWlsZWRTdHJpbmdpZnkgZnVuY3Rpb24gaW4gRGVlcENvbXBhcmVyLlxuICogQ29udGFpbnMgdGhlIHN0cmluZ2lmaWVkIHZhbHVlIGFzIHdlbGwgYXMgdGhlIG51bWJlciBvZiB0aW1lcyB0aGUgbWF4aW11bSBzdHJpbmdpZnkgZGVwdGggd2FzIHJlYWNoZWQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGV0YWlsZWRTdHJpbmdpZnlSZXN1bHQge1xuICByZXN1bHQ6IHN0cmluZ3xudWxsO1xuICBkZXB0aFJlYWNoZWRDb3VudDogbnVtYmVyO1xufVxuXG4vKipcbiAqIEEgc2VydmljZSBmb3IgY29tcGFyaW5nIHR3byB2YXJpYWJsZXMgYnkgdmFsdWUgaW5zdGVhZCBvZiBieSByZWZlcmVuY2VcbiAqL1xuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgRGVlcENvbXBhcmVyIHtcblxuICAvLyAxLiBJbnB1dHNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGxvZ2dlcjogTG9nZ2VyKSB7XG4gIH1cblxuICAvKipcbiAgICogVGVzdHMgaWYgdHdvIG9iamVjdHMgYXJlIGVxdWFsIGJ5IHZhbHVlXG4gICAqXG4gICAqIEBwYXJhbSBhIC0gVGhlIGZpcnN0IG9iamVjdFxuICAgKiBAcGFyYW0gYiAtIFRoZSBzZWNvbmQgb2JqZWN0XG4gICAqIEBwYXJhbSBjb21wYXJlRGVwdGggLSBIb3cgbWFueSBsZXZlbHMgZGVlcCB0byBjb21wYXJlXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIGN1cnJlbnQgcGFyc2VPcHRpb25zXG4gICAqL1xuICBpc0VxdWFsKGE6IGFueSwgYjogYW55LCBjb21wYXJlRGVwdGg/OiBudW1iZXIsIG9wdGlvbnM6IFBhcnNlT3B0aW9ucyA9IGdldFBhcnNlT3B0aW9uRGVmYXVsdHMoKSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGFTdHJpbmdpZmllZCA9IHRoaXMuZGV0YWlsZWRTdHJpbmdpZnkoYSwgY29tcGFyZURlcHRoKTtcbiAgICBjb25zdCBiU3RyaW5naWZpZWQgPSB0aGlzLmRldGFpbGVkU3RyaW5naWZ5KGIsIGNvbXBhcmVEZXB0aCk7XG5cbiAgICBpZiAoYVN0cmluZ2lmaWVkLnJlc3VsdCA9PT0gbnVsbCB8fCBiU3RyaW5naWZpZWQucmVzdWx0ID09PSBudWxsKSB7XG4gICAgICB0aGlzLmxvZ2dlci53YXJuKFtcbiAgICAgICAgJ09iamVjdHMgY291bGQgbm90IGJlIGNvbXBhcmVkIGJ5IHZhbHVlIGFzIG9uZSBvciBib3RoIG9mIHRoZW0gY291bGQgbm90IGJlIHN0cmluZ2lmaWVkLiBSZXR1cm5pbmcgZmFsc2UuIFxcbicsXG4gICAgICAgICdPYmplY3RzOicsIGEsIGJcbiAgICAgIF0sIG9wdGlvbnMpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiBhU3RyaW5naWZpZWQucmVzdWx0ID09PSBiU3RyaW5naWZpZWQucmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIExpa2UgSlNPTi5zdHJpbmdpZnksIGJ1dCBzdHJpbmdpZmllcyBhZGRpdGlvbmFsIGRhdGF0eXBlcyB0aGF0IHdvdWxkIGhhdmUgYmVlblxuICAgKiBudWxsZWQgb3RoZXJ3aXNlLiBJdCBhbHNvIGRvZXNuJ3QgdGhyb3cgZXJyb3JzIG9uIGN5Y2xpYyBwcm9wZXJ0eSBwYXRocy5cbiAgICpcbiAgICogSWYgb2JqIGNhbid0IGJlIHN0cmluZ2lmaWVkIGZvciB3aGF0ZXZlciByZWFzb24sIHJldHVybnMgbnVsbC5cbiAgICpcbiAgICogQHBhcmFtIG9iaiAtIFRoZSBvYmplY3QgdG8gc3RyaW5naWZ5XG4gICAqIEBwYXJhbSBkZXB0aCAtIEhvdyBtYW55IGxldmVscyBkZWVwIHRvIHN0cmluZ2lmeVxuICAgKi9cbiAgZGV0YWlsZWRTdHJpbmdpZnkob2JqOiBhbnksIGRlcHRoPzogbnVtYmVyKTogRGV0YWlsZWRTdHJpbmdpZnlSZXN1bHQge1xuICAgIHRyeSB7XG4gICAgICAvLyBOdWxsIGN5Y2xpYyBwYXRoc1xuICAgICAgY29uc3QgZGVwdGhSZWFjaGVkID0ge2NvdW50OiAwfTtcbiAgICAgIGNvbnN0IGRlY3lsY2VkT2JqID0gdGhpcy5kZWN5Y2xlKG9iaiwgW10sIGRlcHRoLCBkZXB0aFJlYWNoZWQpO1xuXG4gICAgICBjb25zdCBzdHJpbmdpZmllZCA9IEpTT04uc3RyaW5naWZ5KGRlY3lsY2VkT2JqLCAoa2V5LCB2YWx1ZSkgPT4ge1xuICAgICAgICAvLyBJZiB1bmRlZmluZWRcbiAgICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXR1cm4gJ3VuZGVmaW5lZCc7XG4gICAgICAgIH1cbiAgICAgICAgLy8gSWYgZnVuY3Rpb24gb3IgY2xhc3NcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIHJldHVybiB2YWx1ZS50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgICAgIC8vIElmIHN5bWJvbFxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJykge1xuICAgICAgICAgIHJldHVybiB2YWx1ZS50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4ge3Jlc3VsdDogc3RyaW5naWZpZWQsIGRlcHRoUmVhY2hlZENvdW50OiBkZXB0aFJlYWNoZWQuY291bnR9O1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiB7cmVzdWx0OiBudWxsLCBkZXB0aFJlYWNoZWRDb3VudDogMH07XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyYXZlbHMgb24gb2JqZWN0IGFuZCByZXBsYWNlcyBjeWNsaWNhbCByZWZlcmVuY2VzIHdpdGggbnVsbFxuICAgKlxuICAgKiBAcGFyYW0gb2JqIC0gVGhlIG9iamVjdCB0byB0cmF2ZWxcbiAgICogQHBhcmFtIHN0YWNrIC0gVG8ga2VlcCB0cmFjayBvZiBhbHJlYWR5IHRyYXZlbGxlZCBvYmplY3RzXG4gICAqIEBwYXJhbSBkZXB0aCAtIEhvdyBtYW55IGxldmVscyBkZWVwIHRvIGRlY3ljbGVcbiAgICogQHBhcmFtIGRlcHRoUmVhY2hlZCAtIEFuIG9iamVjdCB0byB0cmFjayB0aGUgbnVtYmVyIG9mIHRpbWVzIHRoZSBtYXggZGVwdGggd2FzIHJlYWNoZWRcbiAgICovXG4gIGRlY3ljbGUob2JqOiBhbnksIHN0YWNrOiBhbnlbXSA9IFtdLCBkZXB0aDogbnVtYmVyID0gNSwgZGVwdGhSZWFjaGVkOiB7IGNvdW50OiBudW1iZXI7IH0pOiBhbnkge1xuICAgIGlmIChzdGFjay5sZW5ndGggPiBkZXB0aCkge1xuICAgICAgZGVwdGhSZWFjaGVkLmNvdW50Kys7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAoIW9iaiB8fCB0eXBlb2Ygb2JqICE9PSAnb2JqZWN0JyB8fCBvYmogaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgIHJldHVybiBvYmo7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgY3ljbGljYWwgYW5kIHdlJ3ZlIHRyYXZlbGVkIHRoaXMgb2JqIGFscmVhZHlcbiAgICAvL1xuICAgIC8vIE5vdGU6IFRlc3QgdGhpcyBub3QgYnkgb2JqZWN0IHJlZmVyZW5jZSwgYnV0IGJ5IG9iamVjdCBQUk9QRVJUWSByZWZlcmVuY2UvZXF1YWxpdHkuIElmIGFuIG9iamVjdCBoYXMgaWRlbnRpY2FsIHByb3BlcnRpZXMsXG4gICAgLy8gdGhlIG9iamVjdCBpcyB0byBiZSBjb25zaWRlcmVkIGlkZW50aWNhbCBldmVuIGlmIGl0IGhhcyBhIGRpZmZlcmVudCByZWZlcmVuY2UgaXRzZWxmLlxuICAgIC8vXG4gICAgLy8gRXhwbGFuYXRpb246IFRoaXMgaXMgdG8gcHJldmVudCBhIHNuZWFreSBidWcgd2hlbiBjb21wYXJpbmcgYnkgdmFsdWUgYW5kIGEgcGFyc2VyIHJldHVybnMgYW4gb2JqZWN0IGFzIGFuIGlucHV0IHRoYXQgY29udGFpbnMgYSByZWZlcmVuY2UgdG8gdGhlIG9iamVjdCBob2xkaW5nIGl0XG4gICAgLy8gKGxpa2UgcmV0dXJuaW5nIHRoZSBjb250ZXh0IG9iamVjdCB0aGF0IGNvbnRhaW5zIGEgcmVmZXJlbmNlIHRvIHRoZSBwYXJlbnQgY29tcG9uZW50IGhvbGRpbmcgdGhlIGNvbnRleHQgb2JqZWN0KS5cbiAgICAvLyBJbiB0aGlzIGV4YW1wbGUsIHdoZW4gdGhlIGNvbnRleHQgb2JqZWN0IGNoYW5nZXMgYnkgcmVmZXJlbmNlLCB0aGUgb2xkIGlucHV0IHdpbGwgYmUgY29tcGFyZWQgd2l0aCB0aGUgbmV3IGlucHV0LiBIb3dldmVyLCBhcyB0aGUgb2xkIGlucHV0IGNvbnNpc3RzIG9mXG4gICAgLy8gdGhlIG9sZCBjb250ZXh0IG9iamVjdCB0aGF0IG5vdyAodGhyb3VnaCB0aGUgcGFyZW50IGNvbXBvbmVudCkgY29udGFpbnMgYSByZWZlcmVuY2UgdG8gdGhlIG5ldyBjb250ZXh0IG9iamVjdCwgd2hpbGUgdGhlIG5ldyBpbnB1dCByZWZlcmVuY2VzIHRoZSBuZXcgY29udGV4dFxuICAgIC8vIG9iamVjdCBleGNsdXNpdmVseSwgdGhlIGRlY3ljbGUgZnVuY3Rpb24gd291bGQgcHJvZHVjZSBkaWZmZXJlbnQgcmVzdWx0cyBmb3IgdGhlbSBpZiBpdCBvbmx5IGNoZWNrZWQgY3ljbGljYWwgcGF0aHMgYnkgcmVmZXJlbmNlIChldmVuIGlmIHRoZSBjb250ZXh0IG9iamVjdFxuICAgIC8vIHJlbWFpbmVkIGlkZW50aWNhbCBpbiB2YWx1ZSEpXG4gICAgLy9cbiAgICAvLyBUaG91Z2ggYW4gdW5saWtlbHkgc2NlbmFyaW8sIGNoZWNraW5nIGN5Y2xpY2FsIHBhdGhzIHZpYSBvYmplY3QgcHJvcGVydGllcyByYXRoZXIgdGhhbiB0aGUgb2JqZWN0IHJlZmVyZW5jZSBpdHNlbGYgc29sdmVzIHRoaXMgcHJvYmxlbS5cbiAgICBmb3IgKGNvbnN0IHN0YWNrT2JqIG9mIHN0YWNrKSB7XG4gICAgICBpZiAodGhpcy5vYmpFcXVhbHNQcm9wZXJ0aWVzKG9iaiwgc3RhY2tPYmopKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHMgPSBzdGFjay5jb25jYXQoW29ial0pO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgICAgY29uc3QgbmV3QXJyYXkgPSBbXTtcbiAgICAgIGZvciAoY29uc3QgZW50cnkgb2Ygb2JqKSB7XG4gICAgICAgIG5ld0FycmF5LnB1c2godGhpcy5kZWN5Y2xlKGVudHJ5LCBzLCBkZXB0aCwgZGVwdGhSZWFjaGVkKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3QXJyYXk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG5ld09iajogYW55ID0ge307XG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhvYmopKSB7XG4gICAgICAgIG5ld09ialtrZXldID0gdGhpcy5kZWN5Y2xlKG9ialtrZXldLCBzLCBkZXB0aCwgZGVwdGhSZWFjaGVkKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuZXdPYmo7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSB3aGVuIGFsbCB0aGUgcHJvcGVydGllcyBvZiBvbmUgb2JqZWN0IGVxdWFsIHRob3NlIG9mIGFub3RoZXIgb2JqZWN0LCBvdGhlcndpc2UgZmFsc2UuXG4gICAqXG4gICAqIEBwYXJhbSBhIC0gVGhlIGZpcnN0IG9iamVjdFxuICAgKiBAcGFyYW0gYiAtIFRoZSBzZWNvbmQgb2JqZWN0XG4gICAqL1xuICBvYmpFcXVhbHNQcm9wZXJ0aWVzKGE6IGFueSwgYjogYW55KTogYm9vbGVhbiB7XG4gICAgY29uc3QgYUtleXMgPSBPYmplY3Qua2V5cyhhKTtcbiAgICBjb25zdCBiS2V5cyA9IE9iamVjdC5rZXlzKGIpO1xuXG4gICAgaWYgKGFLZXlzLmxlbmd0aCAhPT0gYktleXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBhS2V5IG9mIGFLZXlzKSB7XG4gICAgICBpZiAoYVthS2V5XSAhPT0gYlthS2V5XSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cbiJdfQ==