UNPKG

ngx-object-diff

Version:

An Angular 2+ library to compare and show object differences.

359 lines 33.6 kB
/** * @fileoverview added by tsickle * Generated from: lib/ngx-object-diff.service.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Injectable, SecurityContext } from '@angular/core'; import { DomSanitizer } from "@angular/platform-browser"; import * as i0 from "@angular/core"; import * as i1 from "@angular/platform-browser"; export class NgxObjectDiffService { /** * @param {?} sanitizer */ constructor(sanitizer) { this.sanitizer = sanitizer; this.openChar = '{'; this.closeChar = '}'; } /* service methods */ /** * @param {?} char * @return {?} */ setOpenChar(char) { this.openChar = char; } /** * @param {?} char * @return {?} */ setCloseChar(char) { this.closeChar = char; } /** * diff between object a and b * @param {?} a * @param {?} b * @param {?=} shallow * @param {?=} isOwn * @return {?} */ diff(a, b, shallow, isOwn) { if (a === b) { return this.equalObj(a); } /** @type {?} */ let diffValue = {}; /** @type {?} */ let equal = true; for (let key in a) { if ((!isOwn && key in b) || (isOwn && typeof b != 'undefined' && b.hasOwnProperty(key))) { if (a[key] === b[key]) { diffValue[key] = this.equalObj(a[key]); } else { if (!shallow && this.isValidAttr(a[key], b[key])) { /** @type {?} */ let valueDiff = this.diff(a[key], b[key], shallow, isOwn); if (valueDiff.changed == 'equal') { diffValue[key] = this.equalObj(a[key]); } else { equal = false; diffValue[key] = valueDiff; } } else { equal = false; diffValue[key] = { changed: 'primitive change', removed: a[key], added: b[key] }; } } } else { equal = false; diffValue[key] = { changed: 'removed', value: a[key] }; } } for (let key in b) { if ((!isOwn && !(key in a)) || (isOwn && typeof a != 'undefined' && !a.hasOwnProperty(key))) { equal = false; diffValue[key] = { changed: 'added', value: b[key] }; } } if (equal) { return this.equalObj(a); } else { return { changed: 'object change', value: diffValue }; } } /** * compare and build the difference of two objects taking only its own properties into account * @param {?} a * @param {?} b * @param {?=} shallow * @return {?} */ diffOwnProperties(a, b, shallow) { return this.diff(a, b, shallow, true); } /** * Convert to a readable xml/html Json structure * @param {?} changes * @param {?=} shallow * @return {?} */ toJsonView(changes, shallow) { return this.formatToJsonXMLString(changes, shallow); } /** * Convert to a readable xml/html Json structure * @param {?} object * @param {?=} shallow * @return {?} */ objToJsonView(object, shallow) { return this.formatObjToJsonXMLString(object, shallow); } /** * Convert to a readable xml/html Json structure * @param {?} changes * @param {?=} shallow * @return {?} */ toJsonDiffView(changes, shallow) { return this.formatChangesToXMLString(changes, shallow); } /** * Convert to a readable xml/html Json structure * Convert to a readable xml/html Json structure * @private * @param {?} obj * @param {?} shallow * @return {?} */ formatObjToJsonXMLString(obj, shallow) { return this.sanitizer.bypassSecurityTrustHtml(this.inspect(obj, shallow)); } /** * Convert to a readable xml/html Json structure * @private * @param {?} changes * @param {?=} shallow * @return {?} */ formatToJsonXMLString(changes, shallow) { /** @type {?} */ let properties = []; /** @type {?} */ let diff = changes.value; if (changes.changed == 'equal') { return this.sanitizer.sanitize(SecurityContext.HTML, this.sanitizer.bypassSecurityTrustHtml(this.inspect(diff, shallow))); } for (let key in diff) { properties.push(this.formatChange(key, diff[key], shallow)); } return this.sanitizer.sanitize(SecurityContext.HTML, this.sanitizer.bypassSecurityTrustHtml('<span>' + this.openChar + '</span>\n<div class="diff-level">' + properties.join('<span>,</span>\n') + '\n</div><span>' + this.closeChar + '</span>')); } /** * @private * @param {?} changes * @param {?=} shallow * @return {?} */ formatChangesToXMLString(changes, shallow) { /** @type {?} */ var properties = []; if (changes.changed == 'equal') { return ''; } /** @type {?} */ var diff = changes.value; for (var key in diff) { /** @type {?} */ var changed = diff[key].changed; if (changed !== 'equal') properties.push(this.formatChange(key, diff[key], shallow, true)); } return this.sanitizer.sanitize(SecurityContext.HTML, this.sanitizer.bypassSecurityTrustHtml('<span>' + this.openChar + '</span>\n<div class="diff-level">' + properties.join('<span>,</span>\n') + '\n</div><span>' + this.closeChar + '</span>')); } /** * @private * @param {?} key * @param {?} diffItem * @param {?} shallow * @param {?=} diffOnly * @return {?} */ formatChange(key, diffItem, shallow, diffOnly) { /** @type {?} */ var changed = diffItem.changed; /** @type {?} */ var property; switch (changed) { case 'equal': property = (this.stringifyObjectKey(this.escapeHTML(key)) + '<span>: </span>' + this.inspect(diffItem.value)); break; case 'removed': property = ('<del class="diff">' + this.stringifyObjectKey(this.escapeHTML(key)) + '<span>: </span>' + this.inspect(diffItem.value) + '</del>'); break; case 'added': property = ('<ins class="diff">' + this.stringifyObjectKey(this.escapeHTML(key)) + '<span>: </span>' + this.inspect(diffItem.value) + '</ins>'); break; case 'primitive change': /** @type {?} */ var prefix = this.stringifyObjectKey(this.escapeHTML(key)) + '<span>: </span>'; property = ('<del class="diff diff-key">' + prefix + this.inspect(diffItem.removed) + '</del><span>,</span>\n' + '<ins class="diff diff-key">' + prefix + this.inspect(diffItem.added) + '</ins>'); break; case 'object change': property = shallow ? '' : (this.stringifyObjectKey(key) + '<span>: </span>' + (diffOnly ? this.formatChangesToXMLString(diffItem) : this.formatToJsonXMLString(diffItem))); break; } return property; } /** * @private * @param {?} obj * @param {?=} shallow * @return {?} */ inspect(obj, shallow) { return this._inspect('', obj, shallow); } /** * @see http://jsperf.com/continuation-passing-style/3 * @private * @param {?} accumulator * @param {?} obj * @param {?=} shallow * @return {?} */ _inspect(accumulator, obj, shallow) { switch (typeof obj) { case 'object': if (!obj) { accumulator += 'null'; break; } if (shallow) { accumulator += '[object]'; break; } /** @type {?} */ let keys = Object.keys(obj); /** @type {?} */ let length = keys.length; if (length === 0) { accumulator += '<span>' + this.openChar + this.closeChar + '</span>'; } else { accumulator += '<span>' + this.openChar + '</span>\n<div class="diff-level">'; for (let i = 0; i < length; i++) { /** @type {?} */ let key = keys[i]; accumulator = this._inspect(accumulator + this.stringifyObjectKey(this.escapeHTML(key)) + '<span>: </span>', obj[key]); if (i < length - 1) { accumulator += '<span>,</span>\n'; } } accumulator += '\n</div><span>' + this.closeChar + '</span>'; } break; case 'string': accumulator += JSON.stringify(this.escapeHTML(obj)); break; case 'undefined': accumulator += 'undefined'; break; default: accumulator += this.escapeHTML(String(obj)); break; } return accumulator; } /** * @private * @param {?} key * @return {?} */ stringifyObjectKey(key) { return /^[a-z0-9_$]*$/i.test(key) ? key : JSON.stringify(key); } /** * @private * @param {?} string * @return {?} */ escapeHTML(string) { return string.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;'); } /** * @private * @param {?} obj * @return {?} */ equalObj(obj) { return { changed: 'equal', value: obj }; } /** * @private * @param {?} a * @param {?} b * @return {?} */ isValidAttr(a, b) { /** @type {?} */ let typeA = typeof a; /** @type {?} */ let typeB = typeof b; return (a && b && (typeA == 'object' || typeA == 'function') && (typeB == 'object' || typeB == 'function')); } } NgxObjectDiffService.decorators = [ { type: Injectable, args: [{ providedIn: 'root' },] } ]; /** @nocollapse */ NgxObjectDiffService.ctorParameters = () => [ { type: DomSanitizer } ]; /** @nocollapse */ NgxObjectDiffService.ngInjectableDef = i0.ɵɵdefineInjectable({ factory: function NgxObjectDiffService_Factory() { return new NgxObjectDiffService(i0.ɵɵinject(i1.DomSanitizer)); }, token: NgxObjectDiffService, providedIn: "root" }); if (false) { /** * @type {?} * @private */ NgxObjectDiffService.prototype.openChar; /** * @type {?} * @private */ NgxObjectDiffService.prototype.closeChar; /** * @type {?} * @private */ NgxObjectDiffService.prototype.sanitizer; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LW9iamVjdC1kaWZmLnNlcnZpY2UuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtb2JqZWN0LWRpZmYvIiwic291cmNlcyI6WyJsaWIvbmd4LW9iamVjdC1kaWZmLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxPQUFPLEVBQUMsVUFBVSxFQUFFLGVBQWUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUMxRCxPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0sMkJBQTJCLENBQUM7OztBQUt2RCxNQUFNLE9BQU8sb0JBQW9COzs7O0lBSy9CLFlBQW9CLFNBQXVCO1FBQXZCLGNBQVMsR0FBVCxTQUFTLENBQWM7UUFIbkMsYUFBUSxHQUFHLEdBQUcsQ0FBQztRQUNmLGNBQVMsR0FBRyxHQUFHLENBQUM7SUFFdUIsQ0FBQzs7Ozs7O0lBT3pDLFdBQVcsQ0FBQyxJQUFZO1FBQzdCLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO0lBQ3ZCLENBQUM7Ozs7O0lBS00sWUFBWSxDQUFDLElBQVk7UUFDOUIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7SUFDeEIsQ0FBQzs7Ozs7Ozs7O0lBVU0sSUFBSSxDQUFDLENBQVMsRUFBRSxDQUFTLEVBQUUsT0FBaUIsRUFBRSxLQUFlO1FBRWxFLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUNYLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUN6Qjs7WUFFRyxTQUFTLEdBQUcsRUFBRTs7WUFDZCxLQUFLLEdBQUcsSUFBSTtRQUVoQixLQUFLLElBQUksR0FBRyxJQUFJLENBQUMsRUFBRTtZQUNqQixJQUFJLENBQUMsQ0FBQyxLQUFLLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLE9BQU8sQ0FBQyxJQUFJLFdBQVcsSUFBSSxDQUFDLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUU7Z0JBQ3ZGLElBQUksQ0FB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LE9BQU8sQ0FBQzs7WUFDaEIsS0FBSyxHQUFHLE9BQU8sQ0FBQztRQUNwQixPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxRQUFRLElBQUksS0FBSyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLFFBQVEsSUFBSSxLQUFLLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQztJQUM5RyxDQUFDOzs7WUFyVUYsVUFBVSxTQUFDO2dCQUNWLFVBQVUsRUFBRSxNQUFNO2FBQ25COzs7O1lBSk8sWUFBWTs7Ozs7Ozs7SUFPbEIsd0NBQXVCOzs7OztJQUN2Qix5Q0FBd0I7Ozs7O0lBRVoseUNBQStCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtJbmplY3RhYmxlLCBTZWN1cml0eUNvbnRleHR9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtEb21TYW5pdGl6ZXJ9IGZyb20gXCJAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyXCI7XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIE5neE9iamVjdERpZmZTZXJ2aWNlIHtcblxuICBwcml2YXRlIG9wZW5DaGFyID0gJ3snO1xuICBwcml2YXRlIGNsb3NlQ2hhciA9ICd9JztcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNhbml0aXplcjogRG9tU2FuaXRpemVyKSB7IH1cblxuICAvKiBzZXJ2aWNlIG1ldGhvZHMgKi9cblxuICAvKipcbiAgICogQHBhcmFtIGNoYXJcbiAgICovXG4gIHB1YmxpYyBzZXRPcGVuQ2hhcihjaGFyOiBzdHJpbmcpIHtcbiAgICB0aGlzLm9wZW5DaGFyID0gY2hhcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0gY2hhclxuICAgKi9cbiAgcHVibGljIHNldENsb3NlQ2hhcihjaGFyOiBzdHJpbmcpIHtcbiAgICB0aGlzLmNsb3NlQ2hhciA9IGNoYXI7XG4gIH1cblxuICAvKipcbiAgICogZGlmZiBiZXR3ZWVuIG9iamVjdCBhIGFuZCBiXG4gICAqIEBwYXJhbSBhXG4gICAqIEBwYXJhbSBiXG4gICAqIEBwYXJhbSBzaGFsbG93XG4gICAqIEBwYXJhbSBpc093blxuICAgKiBAcmV0dXJuXG4gICAqL1xuICBwdWJsaWMgZGlmZihhOiBPYmplY3QsIGI6IE9iamVjdCwgc2hhbGxvdz86IGJvb2xlYW4sIGlzT3duPzogYm9vbGVhbikge1xuXG4gICAgaWYgKGEgPT09IGIpIHtcbiAgICAgIHJldHVybiB0aGlzLmVxdWFsT2JqKGEpO1xuICAgIH1cblxuICAgIGxldCBkaWZmVmFsdWUgPSB7fTtcbiAgICBsZXQgZXF1YWwgPSB0cnVlO1xuXG4gICAgZm9yIChsZXQga2V5IGluIGEpIHtcbiAgICAgIGlmICgoIWlzT3duICYmIGtleSBpbiBiKSB8fCAoaXNPd24gJiYgdHlwZW9mIGIgIT0gJ3VuZGVmaW5lZCcgJiYgYi5oYXNPd25Qcm9wZXJ0eShrZXkpKSkge1xuICAgICAgICBpZiAoYVtrZXldID09PSBiW2tleV0pIHtcbiAgICAgICAgICBkaWZmVmFsdWVba2V5XSA9IHRoaXMuZXF1YWxPYmooYVtrZXldKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoIXNoYWxsb3cgJiYgdGhpcy5pc1ZhbGlkQXR0cihhW2tleV0sIGJba2V5XSkpIHtcbiAgICAgICAgICAgIGxldCB2YWx1ZURpZmYgPSB0aGlzLmRpZmYoYVtrZXldLCBiW2tleV0sIHNoYWxsb3csIGlzT3duKTtcbiAgICAgICAgICAgIGlmICh2YWx1ZURpZmYuY2hhbmdlZCA9PSAnZXF1YWwnKSB7XG4gICAgICAgICAgICAgIGRpZmZWYWx1ZVtrZXldID0gdGhpcy5lcXVhbE9iaihhW2tleV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZXF1YWwgPSBmYWxzZTtcbiAgICAgICAgICAgICAgZGlmZlZhbHVlW2tleV0gPSB2YWx1ZURpZmY7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVxdWFsID0gZmFsc2U7XG4gICAgICAgICAgICBkaWZmVmFsdWVba2V5XSA9IHtcbiAgICAgICAgICAgICAgY2hhbmdlZDogJ3ByaW1pdGl2ZSBjaGFuZ2UnLFxuICAgICAgICAgICAgICByZW1vdmVkOiBhW2tleV0sXG4gICAgICAgICAgICAgIGFkZGVkOiBiW2tleV1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVxdWFsID0gZmFsc2U7XG4gICAgICAgIGRpZmZWYWx1ZVtrZXldID0ge1xuICAgICAgICAgIGNoYW5nZWQ6ICdyZW1vdmVkJyxcbiAgICAgICAgICB2YWx1ZTogYVtrZXldXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgaW4gYikge1xuICAgICAgaWYgKCghaXNPd24gJiYgIShrZXkgaW4gYSkpIHx8IChpc093biAmJiB0eXBlb2YgYSAhPSAndW5kZWZpbmVkJyAmJiAhYS5oYXNPd25Qcm9wZXJ0eShrZXkpKSkge1xuICAgICAgICBlcXVhbCA9IGZhbHNlO1xuICAgICAgICBkaWZmVmFsdWVba2V5XSA9IHtcbiAgICAgICAgICBjaGFuZ2VkOiAnYWRkZWQnLFxuICAgICAgICAgIHZhbHVlOiBiW2tleV1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChlcXVhbCkge1xuICAgICAgcmV0dXJuIHRoaXMuZXF1YWxPYmooYSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNoYW5nZWQ6ICdvYmplY3QgY2hhbmdlJyxcbiAgICAgICAgdmFsdWU6IGRpZmZWYWx1ZVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBjb21wYXJlIGFuZCBidWlsZCB0aGUgZGlmZmVyZW5jZSBvZiB0d28gb2JqZWN0cyB0YWtpbmcgb25seSBpdHMgb3duIHByb3BlcnRpZXMgaW50byBhY2NvdW50XG4gICAqIEBwYXJhbSBhXG4gICAqIEBwYXJhbSBiXG4gICAqIEBwYXJhbSBzaGFsbG93XG4gICAqL1xuICBwdWJsaWMgZGlmZk93blByb3BlcnRpZXMoYTogT2JqZWN0LCBiOiBPYmplY3QsIHNoYWxsb3c/OiBib29sZWFuKSB7XG4gICAgcmV0dXJuIHRoaXMuZGlmZihhLCBiLCBzaGFsbG93LCB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IHRvIGEgcmVhZGFibGUgeG1sL2h0bWwgSnNvbiBzdHJ1Y3R1cmVcbiAgICogQHBhcmFtIGNoYW5nZXNcbiAgICogQHJldHVyblxuICAgKiBAcGFyYW0gc2hhbGxvd1xuICAgKi9cbiAgcHVibGljIHRvSnNvblZpZXcoY2hhbmdlcywgc2hhbGxvdz86Ym9vbGVhbikge1xuICAgIHJldHVybiB0aGlzLmZvcm1hdFRvSnNvblhNTFN0cmluZyhjaGFuZ2VzLCBzaGFsbG93KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IHRvIGEgcmVhZGFibGUgeG1sL2h0bWwgSnNvbiBzdHJ1Y3R1cmVcbiAgICogQHJldHVyblxuICAgKiBAcGFyYW0gb2JqXG4gICAqIEBwYXJhbSBzaGFsbG93XG4gICAqL1xuICBwdWJsaWMgb2JqVG9Kc29uVmlldyhvYmplY3Qsc2hhbGxvdz86Ym9vbGVhbik6IE9iamVjdHtcbiAgICByZXR1cm4gdGhpcy5mb3JtYXRPYmpUb0pzb25YTUxTdHJpbmcob2JqZWN0LHNoYWxsb3cpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnQgdG8gYSByZWFkYWJsZSB4bWwvaHRtbCBKc29uIHN0cnVjdHVyZVxuICAgKiBAcGFyYW0gY2hhbmdlc1xuICAgKiBAcmV0dXJuXG4gICAqIEBwYXJhbSBzaGFsbG93XG4gICAqL1xuICBwdWJsaWMgdG9Kc29uRGlmZlZpZXcoY2hhbmdlcywgc2hhbGxvdz86IGJvb2xlYW4pIDogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5mb3JtYXRDaGFuZ2VzVG9YTUxTdHJpbmcoY2hhbmdlcywgc2hhbGxvdyk7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCB0byBhIHJlYWRhYmxlIHhtbC9odG1sIEpzb24gc3RydWN0dXJlXG4gICAqIENvbnZlcnQgdG8gYSByZWFkYWJsZSB4bWwvaHRtbCBKc29uIHN0cnVjdHVyZVxuICAgKiBAcmV0dXJuXG4gICAqIEBwYXJhbSBvYmpcbiAgICogQHBhcmFtIHNoYWxsb3dcbiAgICovXG4gIHByaXZhdGUgZm9ybWF0T2JqVG9Kc29uWE1MU3RyaW5nKG9iaiwgc2hhbGxvdykge1xuICAgIHJldHVybiB0aGlzLnNhbml0aXplci5ieXBhc3NTZWN1cml0eVRydXN0SHRtbCh0aGlzLmluc3BlY3Qob2JqLCBzaGFsbG93KSk7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCB0byBhIHJlYWRhYmxlIHhtbC9odG1sIEpzb24gc3RydWN0dXJlXG4gICAqIEBwYXJhbSBjaGFuZ2VzXG4gICAqIEByZXR1cm5cbiAgICogQHBhcmFtIHNoYWxsb3dcbiAgICovXG4gIHByaXZhdGUgZm9ybWF0VG9Kc29uWE1MU3RyaW5nKGNoYW5nZXMsIHNoYWxsb3c/OmJvb2xlYW4pIHtcbiAgICBsZXQgcHJvcGVydGllcyA9IFtdO1xuXG4gICAgbGV0IGRpZmYgPSBjaGFuZ2VzLnZhbHVlO1xuICAgIGlmIChjaGFuZ2VzLmNoYW5nZWQgPT0gJ2VxdWFsJykge1xuICAgICAgcmV0dXJuIHRoaXMuc2FuaXRpemVyLnNhbml0aXplKFNlY3VyaXR5Q29udGV4dC5IVE1MLHRoaXMuc2FuaXRpemVyLmJ5cGFzc1NlY3VyaXR5VHJ1c3RIdG1sKHRoaXMuaW5zcGVjdChkaWZmLCBzaGFsbG93KSkpO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBpbiBkaWZmKSB7XG4gICAgICBwcm9wZXJ0aWVzLnB1c2godGhpcy5mb3JtYXRDaGFuZ2Uoa2V5LCBkaWZmW2tleV0sIHNoYWxsb3cpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zYW5pdGl6ZXIuc2FuaXRpemUoU2VjdXJpdHlDb250ZXh0LkhUTUwsdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdEh0bWwoJzxzcGFuPicgKyB0aGlzLm9wZW5DaGFyICsgJzwvc3Bhbj5cXG48ZGl2IGNsYXNzPVwiZGlmZi1sZXZlbFwiPicgKyBwcm9wZXJ0aWVzLmpvaW4oJzxzcGFuPiw8L3NwYW4+XFxuJykgKyAnXFxuPC9kaXY+PHNwYW4+JyArIHRoaXMuY2xvc2VDaGFyICsgJzwvc3Bhbj4nKSk7XG5cbiAgfVxuXG5cbiAgcHJpdmF0ZSBmb3JtYXRDaGFuZ2VzVG9YTUxTdHJpbmcoY2hhbmdlcywgc2hhbGxvdz86IGJvb2xlYW4pIHtcbiAgICB2YXIgcHJvcGVydGllcyA9IFtdO1xuXG4gICAgaWYgKGNoYW5nZXMuY2hhbmdlZCA9PSAnZXF1YWwnKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgdmFyIGRpZmYgPSBjaGFuZ2VzLnZhbHVlO1xuXG4gICAgZm9yICh2YXIga2V5IGluIGRpZmYpIHtcbiAgICAgIHZhciBjaGFuZ2VkID0gZGlmZltrZXldLmNoYW5nZWQ7XG4gICAgICBpZiAoY2hhbmdlZCAhPT0gJ2VxdWFsJylcbiAgICAgICAgcHJvcGVydGllcy5wdXNoKHRoaXMuZm9ybWF0Q2hhbmdlKGtleSwgZGlmZltrZXldLCBzaGFsbG93LCB0cnVlKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc2FuaXRpemVyLnNhbml0aXplKFNlY3VyaXR5Q29udGV4dC5IVE1MLHRoaXMuc2FuaXRpemVyLmJ5cGFzc1NlY3VyaXR5VHJ1c3RIdG1sKCc8c3Bhbj4nICsgdGhpcy5vcGVuQ2hhciArICc8L3NwYW4+XFxuPGRpdiBjbGFzcz1cImRpZmYtbGV2ZWxcIj4nICsgcHJvcGVydGllcy5qb2luKCc8c3Bhbj4sPC9zcGFuPlxcbicpICsgJ1xcbjwvZGl2PjxzcGFuPicgKyB0aGlzLmNsb3NlQ2hhciArICc8L3NwYW4+JykpO1xuXG4gIH1cblxuXG4gIC8qKlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBkaWZmSXRlbVxuICAgKiBAcmV0dXJuc1xuICAgKiBAcGFyYW0gc2hhbGxvd1xuICAgKiBAcGFyYW0gZGlmZk9ubHlcbiAgICovXG4gIHByaXZhdGUgZm9ybWF0Q2hhbmdlKGtleSwgZGlmZkl0ZW0sIHNoYWxsb3c6IGJvb2xlYW4sIGRpZmZPbmx5Pykge1xuICAgIHZhciBjaGFuZ2VkID0gZGlmZkl0ZW0uY2hhbmdlZDtcbiAgICB2YXIgcHJvcGVydHk7XG4gICAgc3dpdGNoIChjaGFuZ2VkKSB7XG4gICAgICBjYXNlICdlcXVhbCc6XG4gICAgICAgIHByb3BlcnR5ID0gKHRoaXMuc3RyaW5naWZ5T2JqZWN0S2V5KHRoaXMuZXNjYXBlSFRNTChrZXkpKSArICc8c3Bhbj46IDwvc3Bhbj4nICsgdGhpcy5pbnNwZWN0KGRpZmZJdGVtLnZhbHVlKSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdyZW1vdmVkJzpcbiAgICAgICAgcHJvcGVydHkgPSAoJzxkZWwgY2xhc3M9XCJkaWZmXCI+JyArIHRoaXMuc3RyaW5naWZ5T2JqZWN0S2V5KHRoaXMuZXNjYXBlSFRNTChrZXkpKSArICc8c3Bhbj46IDwvc3Bhbj4nICsgdGhpcy5pbnNwZWN0KGRpZmZJdGVtLnZhbHVlKSArICc8L2RlbD4nKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ2FkZGVkJzpcbiAgICAgICAgcHJvcGVydHkgPSAoJzxpbnMgY2xhc3M9XCJkaWZmXCI+JyArIHRoaXMuc3RyaW5naWZ5T2JqZWN0S2V5KHRoaXMuZXNjYXBlSFRNTChrZXkpKSArICc8c3Bhbj46IDwvc3Bhbj4nICsgdGhpcy5pbnNwZWN0KGRpZmZJdGVtLnZhbHVlKSArICc8L2lucz4nKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ3ByaW1pdGl2ZSBjaGFuZ2UnOlxuICAgICAgICB2YXIgcHJlZml4ID0gdGhpcy5zdHJpbmdpZnlPYmplY3RLZXkodGhpcy5lc2NhcGVIVE1MKGtleSkpICsgJzxzcGFuPjogPC9zcGFuPic7XG4gICAgICAgIHByb3BlcnR5ID0gKFxuICAgICAgICAgICc8ZGVsIGNsYXNzPVwiZGlmZiBkaWZmLWtleVwiPicgKyBwcmVmaXggKyB0aGlzLmluc3BlY3QoZGlmZkl0ZW0ucmVtb3ZlZCkgKyAnPC9kZWw+PHNwYW4+LDwvc3Bhbj5cXG4nICtcbiAgICAgICAgICAnPGlucyBjbGFzcz1cImRpZmYgZGlmZi1rZXlcIj4nICsgcHJlZml4ICsgdGhpcy5pbnNwZWN0KGRpZmZJdGVtLmFkZGVkKSArICc8L2lucz4nKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ29iamVjdCBjaGFuZ2UnOlxuICAgICAgICBwcm9wZXJ0eSA9IHNoYWxsb3cgPyAnJyA6ICh0aGlzLnN0cmluZ2lmeU9iamVjdEtleShrZXkpICsgJzxzcGFuPjogPC9zcGFuPicgKyAoZGlmZk9ubHkgPyB0aGlzLmZvcm1hdENoYW5nZXNUb1hNTFN0cmluZyhkaWZmSXRlbSkgOiB0aGlzLmZvcm1hdFRvSnNvblhNTFN0cmluZyhkaWZmSXRlbSkpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb3BlcnR5O1xuICB9XG5cblxuICAvKipcbiAgICogQHBhcmFtIG9ialxuICAgKiBAcmV0dXJuXG4gICAqIEBwYXJhbSBzaGFsbG93XG4gICAqL1xuICBwcml2YXRlIGluc3BlY3Qob2JqLCBzaGFsbG93PzogYm9vbGVhbikge1xuICAgIHJldHVybiB0aGlzLl9pbnNwZWN0KCcnLCBvYmosIHNoYWxsb3cpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSBhY2N1bXVsYXRvclxuICAgKiBAcGFyYW0gb2JqXG4gICAqIEBzZWUgaHR0cDovL2pzcGVyZi5jb20vY29udGludWF0aW9uLXBhc3Npbmctc3R5bGUvM1xuICAgKiBAcmV0dXJuXG4gICAqIEBwYXJhbSBzaGFsbG93XG4gICAqL1xuICBwcml2YXRlIF9pbnNwZWN0KGFjY3VtdWxhdG9yOiBzdHJpbmcsIG9iajogT2JqZWN0LCBzaGFsbG93Pykge1xuICAgIHN3aXRjaCAodHlwZW9mIG9iaikge1xuICAgICAgY2FzZSAnb2JqZWN0JzpcbiAgICAgICAgaWYgKCFvYmopIHtcbiAgICAgICAgICBhY2N1bXVsYXRvciArPSAnbnVsbCc7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNoYWxsb3cpIHtcbiAgICAgICAgICBhY2N1bXVsYXRvciArPSAnW29iamVjdF0nO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGxldCBrZXlzID0gT2JqZWN0LmtleXMob2JqKTtcbiAgICAgICAgbGV0IGxlbmd0aCA9IGtleXMubGVuZ3RoO1xuICAgICAgICBpZiAobGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgYWNjdW11bGF0b3IgKz0gJzxzcGFuPicgKyB0aGlzLm9wZW5DaGFyICsgdGhpcy5jbG9zZUNoYXIgKyAnPC9zcGFuPic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYWNjdW11bGF0b3IgKz0gJzxzcGFuPicgKyB0aGlzLm9wZW5DaGFyICsgJzwvc3Bhbj5cXG48ZGl2IGNsYXNzPVwiZGlmZi1sZXZlbFwiPic7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGV0IGtleSA9IGtleXNbaV07XG4gICAgICAgICAgICBhY2N1bXVsYXRvciA9IHRoaXMuX2luc3BlY3QoYWNjdW11bGF0b3IgKyB0aGlzLnN0cmluZ2lmeU9iamVjdEtleSh0aGlzLmVzY2FwZUhUTUwoa2V5KSkgKyAnPHNwYW4+OiA8L3NwYW4+Jywgb2JqW2tleV0pO1xuICAgICAgICAgICAgaWYgKGkgPCBsZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgIGFjY3VtdWxhdG9yICs9ICc8c3Bhbj4sPC9zcGFuPlxcbic7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGFjY3VtdWxhdG9yICs9ICdcXG48L2Rpdj48c3Bhbj4nICsgdGhpcy5jbG9zZUNoYXIgKyAnPC9zcGFuPidcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgICAgYWNjdW11bGF0b3IgKz0gSlNPTi5zdHJpbmdpZnkodGhpcy5lc2NhcGVIVE1MKG9iaikpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAndW5kZWZpbmVkJzpcbiAgICAgICAgYWNjdW11bGF0b3IgKz0gJ3VuZGVmaW5lZCc7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBhY2N1bXVsYXRvciArPSB0aGlzLmVzY2FwZUhUTUwoU3RyaW5nKG9iaikpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICB9XG5cblxuICAvKipcbiAgICogQHBhcmFtIGtleVxuICAgKiBAcmV0dXJuXG4gICAqL1xuICBwcml2YXRlIHN0cmluZ2lmeU9iamVjdEtleShrZXkpIDogc3RyaW5ne1xuICAgIHJldHVybiAvXlthLXowLTlfJF0qJC9pLnRlc3Qoa2V5KSA/XG4gICAgICBrZXkgOlxuICAgICAgSlNPTi5zdHJpbmdpZnkoa2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0gc3RyaW5nXG4gICAqIEByZXR1cm5cbiAgICovXG4gIHByaXZhdGUgZXNjYXBlSFRNTChzdHJpbmcpIHtcbiAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoLyYvZywgJyZhbXA7JykucmVwbGFjZSgvPC9nLCAnJmx0OycpLnJlcGxhY2UoLz4vZywgJyZndDsnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0gb2JqXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBwcml2YXRlIGVxdWFsT2JqKG9iaikge1xuICAgIHJldHVybiB7XG4gICAgICBjaGFuZ2VkOiAnZXF1YWwnLFxuICAgICAgdmFsdWU6IG9ialxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0gYVxuICAgKiBAcGFyYW0gYlxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgcHJpdmF0ZSBpc1ZhbGlkQXR0cihhOiBPYmplY3QsIGI6IE9iamVjdCk6IGJvb2xlYW4ge1xuICAgIGxldCB0eXBlQSA9IHR5cGVvZiBhO1xuICAgIGxldCB0eXBlQiA9IHR5cGVvZiBiO1xuICAgIHJldHVybiAoYSAmJiBiICYmICh0eXBlQSA9PSAnb2JqZWN0JyB8fCB0eXBlQSA9PSAnZnVuY3Rpb24nKSAmJiAodHlwZUIgPT0gJ29iamVjdCcgfHwgdHlwZUIgPT0gJ2Z1bmN0aW9uJykpO1xuICB9XG59XG4iXX0=