ngx-object-diff
Version:
An Angular 2+ library to compare and show object differences.
359 lines • 33.6 kB
JavaScript
/**
* @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, '&').replace(/</g, '<').replace(/>/g, '>');
}
/**
* @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=