UNPKG

svogv

Version:

A decorator based approach for model driven forms, including an advanced DataGrid and a TreeView component.

124 lines 18.9 kB
import { Injectable, Inject } from '@angular/core'; import { Validators, FormBuilder } from '@angular/forms'; import { validateRange } from './validators/range.validator'; import { validateCompare } from './validators/compare.validator'; /** * The form validator service creates a {@link FormGroup} object from a viewmodel. If the viewmodel * has been decorated with validation decorators the validators are created accordingly. * * The simplest way is creating a class with properties and add decorators, such as * {@link StringLength}. The service will than create a {@link FormGroup} that contains a}validator * of type {@link StringLength} for the property the decorator is written}on. * * The decorators provide properties for additional information, such as a custom error message. * */ export class FormValidatorService { constructor(fb) { this.fb = fb; } /** * Call this method to actually create the FormGroup object. Provide a valid model type. * * @param target A valid model type. * @returns A FormGroup with validators */ build(target) { const valGroup = {}; const errGroup = {}; let form; let targetInstance; if (target) { // the cast is just to suppress TS errors and shows it's intentionally try { targetInstance = new target(); } catch (ex) { console.error('Invalid viewmodel for FormValidatorService'); } } if (targetInstance) { // tslint:disable-next-line:forin for (const propName in targetInstance) { const validators = new Array(); const errmsgs = new Object(); const isRequired = `__isRequired__${propName}` in target.prototype; if (isRequired) { (errmsgs)['required'] = target.prototype[`__errRequired__${propName}`]; validators.push(Validators.required); } const hasMaxLength = `__hasMaxLength__${propName}` in target.prototype; if (hasMaxLength) { (errmsgs)['maxlength'] = target.prototype[`__errMaxLength__${propName}`]; const maxLength = parseInt(target.prototype[`__hasMaxLength__${propName}`], 10); validators.push(Validators.maxLength(maxLength)); } const hasMinLength = `__hasMinLength__${propName}` in target.prototype; if (hasMinLength) { (errmsgs)['minlength'] = target.prototype[`__errMinLength__${propName}`]; const minLength = parseInt(target.prototype[`__hasMinLength__${propName}`], 10); validators.push(Validators.minLength(minLength)); } const hasPattern = `__hasPattern__${propName}` in target.prototype; if (hasPattern) { (errmsgs)['pattern'] = target.prototype[`__errPattern__${propName}`]; const pattern = new RegExp(target.prototype[`__hasPattern__${propName}`]); validators.push(Validators.pattern(pattern)); } const hasRangeFrom = `__hasRangeFrom__${propName}` in target.prototype; const hasRangeTo = `__hasRangeTo__${propName}` in target.prototype; if (hasRangeFrom || hasRangeTo) { (errmsgs)['range'] = target.prototype[`__errRange__${propName}`]; let f = Number(target.prototype[`__hasRangeFrom__${propName}`]); let t = Number(target.prototype[`__hasRangeTo__${propName}`]); if (!f && !t) { // If NaN assume Date f = Date.parse(f.toString()); t = Date.parse(t.toString()); } validators.push(validateRange(f, t)); } const hasCompare = `__hasCompareProperty__${propName}` in target.prototype; if (hasCompare) { (errmsgs)['compare'] = target.prototype[`__errCompareProperty__${propName}`]; const compare = target.prototype[`__withCompare__${propName}`]; validators.push(validateCompare(compare)); } if (validators.length === 0) { // even if there is no validator we need to add the property to the group (valGroup)[propName] = [target[propName]]; } if (validators.length === 1) { (valGroup)[propName] = [target[propName] || '', validators[0]]; } if (validators.length >= 1) { (valGroup)[propName] = [target[propName] || '', Validators.compose(validators)]; } (errGroup)[propName] = errmsgs; } // create form group form = this.fb.group(valGroup); // forward the model to the editors for easy access to other decorators // the cast is just to suppress TS errors and shows it's intentionally (form)['__editorModel__'] = targetInstance; // register controls and add messages // tslint:disable-next-line:forin for (const propName in errGroup) { const ctrl = form.controls[propName]; if (!ctrl) { continue; // control might not be in the form } (form.controls[propName])['messages'] = (errGroup)[propName]; } } // return FormGroup for immediate usage return form; } } FormValidatorService.decorators = [ { type: Injectable } ]; FormValidatorService.ctorParameters = () => [ { type: FormBuilder, decorators: [{ type: Inject, args: [FormBuilder,] }] } ]; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybXZhbGlkYXRvci5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Ii4uLy4uLy4uL3Byb2plY3RzL3N2b2d2L3NyYy8iLCJzb3VyY2VzIjpbImxpYi9zZXJ2aWNlcy9mb3JtdmFsaWRhdG9yLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQWEsTUFBTSxnQkFBZ0IsQ0FBQztBQUVwRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDN0QsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRWpFOzs7Ozs7Ozs7O0dBVUc7QUFFSCxNQUFNLE9BQU8sb0JBQW9CO0lBRy9CLFlBQWlDLEVBQWU7UUFDOUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDZixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxLQUFLLENBQUMsTUFBVztRQUN0QixNQUFNLFFBQVEsR0FBUSxFQUFFLENBQUM7UUFDekIsTUFBTSxRQUFRLEdBQVEsRUFBRSxDQUFDO1FBQ3pCLElBQUksSUFBZSxDQUFDO1FBQ3BCLElBQUksY0FBbUIsQ0FBQztRQUN4QixJQUFJLE1BQU0sRUFBRTtZQUNWLHNFQUFzRTtZQUN0RSxJQUFJO2dCQUNGLGNBQWMsR0FBRyxJQUFJLE1BQU0sRUFBRSxDQUFDO2FBQy9CO1lBQUMsT0FBTyxFQUFFLEVBQUU7Z0JBQ1gsT0FBTyxDQUFDLEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO2FBQzdEO1NBQ0Y7UUFDRCxJQUFJLGNBQWMsRUFBRTtZQUNsQixpQ0FBaUM7WUFDakMsS0FBSyxNQUFNLFFBQVEsSUFBSSxjQUFjLEVBQUU7Z0JBQ3JDLE1BQU0sVUFBVSxHQUFHLElBQUksS0FBSyxFQUFPLENBQUM7Z0JBQ3BDLE1BQU0sT0FBTyxHQUFHLElBQUksTUFB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QVUsQ0FBQyxDQUFDLENBQUM7aUJBQ2pGO2dCQUNELENBQUMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsT0FBTyxDQUFDO2FBQ2hDO1lBQ0Qsb0JBQW9CO1lBQ3BCLElBQUksR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMvQix1RUFBdUU7WUFDdkUsc0VBQXNFO1lBQ3RFLENBQUMsSUFBSSxDQUFDLENBQUMsaUJBQWlCLENBQUMsR0FBRyxjQUFjLENBQUM7WUFDM0MscUNBQXFDO1lBQ3JDLGlDQUFpQztZQUNqQyxLQUFLLE1BQU0sUUFBUSxJQUFJLFFBQVEsRUFBRTtnQkFDL0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDckMsSUFBSSxDQUFDLElBQUksRUFBRTtvQkFDVCxTQUFTLENBQUMsbUNBQW1DO2lCQUM5QztnQkFDRCxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQzlEO1NBQ0Y7UUFDRCx1Q0FBdUM7UUFDdkMsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDOzs7WUF2R0YsVUFBVTs7O1lBaEJVLFdBQVcsdUJBb0JqQixNQUFNLFNBQUMsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIEluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgVmFsaWRhdG9ycywgRm9ybUJ1aWxkZXIsIEZvcm1Hcm91cCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuaW1wb3J0IHsgdmFsaWRhdGVSYW5nZSB9IGZyb20gJy4vdmFsaWRhdG9ycy9yYW5nZS52YWxpZGF0b3InO1xuaW1wb3J0IHsgdmFsaWRhdGVDb21wYXJlIH0gZnJvbSAnLi92YWxpZGF0b3JzL2NvbXBhcmUudmFsaWRhdG9yJztcblxuLyoqXG4gKiBUaGUgZm9ybSB2YWxpZGF0b3Igc2VydmljZSBjcmVhdGVzIGEge0BsaW5rIEZvcm1Hcm91cH0gb2JqZWN0IGZyb20gYSB2aWV3bW9kZWwuIElmIHRoZSB2aWV3bW9kZWxcbiAqIGhhcyBiZWVuIGRlY29yYXRlZCB3aXRoIHZhbGlkYXRpb24gZGVjb3JhdG9ycyB0aGUgdmFsaWRhdG9ycyBhcmUgY3JlYXRlZCBhY2NvcmRpbmdseS5cbiAqXG4gKiBUaGUgc2ltcGxlc3Qgd2F5IGlzIGNyZWF0aW5nIGEgY2xhc3Mgd2l0aCBwcm9wZXJ0aWVzIGFuZCBhZGQgZGVjb3JhdG9ycywgc3VjaCBhc1xuICoge0BsaW5rIFN0cmluZ0xlbmd0aH0uIFRoZSBzZXJ2aWNlIHdpbGwgdGhhbiBjcmVhdGUgYSB7QGxpbmsgRm9ybUdyb3VwfSB0aGF0IGNvbnRhaW5zIGF9dmFsaWRhdG9yXG4gKiBvZiB0eXBlIHtAbGluayBTdHJpbmdMZW5ndGh9IGZvciB0aGUgcHJvcGVydHkgdGhlIGRlY29yYXRvciBpcyB3cml0dGVufW9uLlxuICpcbiAqIFRoZSBkZWNvcmF0b3JzIHByb3ZpZGUgcHJvcGVydGllcyBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiwgc3VjaCBhcyBhIGN1c3RvbSBlcnJvciBtZXNzYWdlLlxuICpcbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEZvcm1WYWxpZGF0b3JTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBmYjogRm9ybUJ1aWxkZXI7XG5cbiAgY29uc3RydWN0b3IoQEluamVjdChGb3JtQnVpbGRlcikgZmI6IEZvcm1CdWlsZGVyKSB7XG4gICAgdGhpcy5mYiA9IGZiO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGwgdGhpcyBtZXRob2QgdG8gYWN0dWFsbHkgY3JlYXRlIHRoZSBGb3JtR3JvdXAgb2JqZWN0LiBQcm92aWRlIGEgdmFsaWQgbW9kZWwgdHlwZS5cbiAgICpcbiAgICogQHBhcmFtIHRhcmdldCBBIHZhbGlkIG1vZGVsIHR5cGUuXG4gICAqIEByZXR1cm5zIEEgRm9ybUdyb3VwIHdpdGggdmFsaWRhdG9yc1xuICAgKi9cbiAgcHVibGljIGJ1aWxkKHRhcmdldDogYW55KTogRm9ybUdyb3VwIHtcbiAgICBjb25zdCB2YWxHcm91cDogYW55ID0ge307XG4gICAgY29uc3QgZXJyR3JvdXA6IGFueSA9IHt9O1xuICAgIGxldCBmb3JtOiBGb3JtR3JvdXA7XG4gICAgbGV0IHRhcmdldEluc3RhbmNlOiBhbnk7XG4gICAgaWYgKHRhcmdldCkge1xuICAgICAgLy8gdGhlIGNhc3QgaXMganVzdCB0byBzdXBwcmVzcyBUUyBlcnJvcnMgYW5kIHNob3dzIGl0J3MgaW50ZW50aW9uYWxseVxuICAgICAgdHJ5IHtcbiAgICAgICAgdGFyZ2V0SW5zdGFuY2UgPSBuZXcgdGFyZ2V0KCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdJbnZhbGlkIHZpZXdtb2RlbCBmb3IgRm9ybVZhbGlkYXRvclNlcnZpY2UnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHRhcmdldEluc3RhbmNlKSB7XG4gICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6Zm9yaW5cbiAgICAgIGZvciAoY29uc3QgcHJvcE5hbWUgaW4gdGFyZ2V0SW5zdGFuY2UpIHtcbiAgICAgICAgY29uc3QgdmFsaWRhdG9ycyA9IG5ldyBBcnJheTxhbnk+KCk7XG4gICAgICAgIGNvbnN0IGVycm1zZ3MgPSBuZXcgT2JqZWN0KCk7XG4gICAgICAgIGNvbnN0IGlzUmVxdWlyZWQgPSBgX19pc1JlcXVpcmVkX18ke3Byb3BOYW1lfWAgaW4gdGFyZ2V0LnByb3RvdHlwZTtcbiAgICAgICAgaWYgKGlzUmVxdWlyZWQpIHtcbiAgICAgICAgICAoZXJybXNncylbJ3JlcXVpcmVkJ10gPSB0YXJnZXQucHJvdG90eXBlW2BfX2VyclJlcXVpcmVkX18ke3Byb3BOYW1lfWBdO1xuICAgICAgICAgIHZhbGlkYXRvcnMucHVzaChWYWxpZGF0b3JzLnJlcXVpcmVkKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBoYXNNYXhMZW5ndGggPSBgX19oYXNNYXhMZW5ndGhfXyR7cHJvcE5hbWV9YCBpbiB0YXJnZXQucHJvdG90eXBlO1xuICAgICAgICBpZiAoaGFzTWF4TGVuZ3RoKSB7XG4gICAgICAgICAgKGVycm1zZ3MpWydtYXhsZW5ndGgnXSA9IHRhcmdldC5wcm90b3R5cGVbYF9fZXJyTWF4TGVuZ3RoX18ke3Byb3BOYW1lfWBdO1xuICAgICAgICAgIGNvbnN0IG1heExlbmd0aCA9IHBhcnNlSW50KHRhcmdldC5wcm90b3R5cGVbYF9faGFzTWF4TGVuZ3RoX18ke3Byb3BOYW1lfWBdLCAxMCk7XG4gICAgICAgICAgdmFsaWRhdG9ycy5wdXNoKFZhbGlkYXRvcnMubWF4TGVuZ3RoKG1heExlbmd0aCkpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGhhc01pbkxlbmd0aCA9IGBfX2hhc01pbkxlbmd0aF9fJHtwcm9wTmFtZX1gIGluIHRhcmdldC5wcm90b3R5cGU7XG4gICAgICAgIGlmIChoYXNNaW5MZW5ndGgpIHtcbiAgICAgICAgICAoZXJybXNncylbJ21pbmxlbmd0aCddID0gdGFyZ2V0LnByb3RvdHlwZVtgX19lcnJNaW5MZW5ndGhfXyR7cHJvcE5hbWV9YF07XG4gICAgICAgICAgY29uc3QgbWluTGVuZ3RoID0gcGFyc2VJbnQodGFyZ2V0LnByb3RvdHlwZVtgX19oYXNNaW5MZW5ndGhfXyR7cHJvcE5hbWV9YF0sIDEwKTtcbiAgICAgICAgICB2YWxpZGF0b3JzLnB1c2goVmFsaWRhdG9ycy5taW5MZW5ndGgobWluTGVuZ3RoKSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaGFzUGF0dGVybiA9IGBfX2hhc1BhdHRlcm5fXyR7cHJvcE5hbWV9YCBpbiB0YXJnZXQucHJvdG90eXBlO1xuICAgICAgICBpZiAoaGFzUGF0dGVybikge1xuICAgICAgICAgIChlcnJtc2dzKVsncGF0dGVybiddID0gdGFyZ2V0LnByb3RvdHlwZVtgX19lcnJQYXR0ZXJuX18ke3Byb3BOYW1lfWBdO1xuICAgICAgICAgIGNvbnN0IHBhdHRlcm4gPSBuZXcgUmVnRXhwKHRhcmdldC5wcm90b3R5cGVbYF9faGFzUGF0dGVybl9fJHtwcm9wTmFtZX1gXSk7XG4gICAgICAgICAgdmFsaWRhdG9ycy5wdXNoKFZhbGlkYXRvcnMucGF0dGVybihwYXR0ZXJuKSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaGFzUmFuZ2VGcm9tID0gYF9faGFzUmFuZ2VGcm9tX18ke3Byb3BOYW1lfWAgaW4gdGFyZ2V0LnByb3RvdHlwZTtcbiAgICAgICAgY29uc3QgaGFzUmFuZ2VUbyA9IGBfX2hhc1JhbmdlVG9fXyR7cHJvcE5hbWV9YCBpbiB0YXJnZXQucHJvdG90eXBlO1xuICAgICAgICBpZiAoaGFzUmFuZ2VGcm9tIHx8IGhhc1JhbmdlVG8pIHtcbiAgICAgICAgICAoZXJybXNncylbJ3JhbmdlJ10gPSB0YXJnZXQucHJvdG90eXBlW2BfX2VyclJhbmdlX18ke3Byb3BOYW1lfWBdO1xuICAgICAgICAgIGxldCBmOiBudW1iZXIgfCBEYXRlID0gTnVtYmVyKHRhcmdldC5wcm90b3R5cGVbYF9faGFzUmFuZ2VGcm9tX18ke3Byb3BOYW1lfWBdKTtcbiAgICAgICAgICBsZXQgdDogbnVtYmVyIHwgRGF0ZSA9IE51bWJlcih0YXJnZXQucHJvdG90eXBlW2BfX2hhc1JhbmdlVG9fXyR7cHJvcE5hbWV9YF0pO1xuICAgICAgICAgIGlmICghZiAmJiAhdCkge1xuICAgICAgICAgICAgLy8gSWYgTmFOIGFzc3VtZSBEYXRlXG4gICAgICAgICAgICBmID0gRGF0ZS5wYXJzZShmLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgdCA9IERhdGUucGFyc2UodC50b1N0cmluZygpKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFsaWRhdG9ycy5wdXNoKHZhbGlkYXRlUmFuZ2UoZiwgdCkpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGhhc0NvbXBhcmUgPSBgX19oYXNDb21wYXJlUHJvcGVydHlfXyR7cHJvcE5hbWV9YCBpbiB0YXJnZXQucHJvdG90eXBlO1xuICAgICAgICBpZiAoaGFzQ29tcGFyZSkge1xuICAgICAgICAgIChlcnJtc2dzKVsnY29tcGFyZSddID0gdGFyZ2V0LnByb3RvdHlwZVtgX19lcnJDb21wYXJlUHJvcGVydHlfXyR7cHJvcE5hbWV9YF07XG4gICAgICAgICAgY29uc3QgY29tcGFyZSA9IHRhcmdldC5wcm90b3R5cGVbYF9fd2l0aENvbXBhcmVfXyR7cHJvcE5hbWV9YF07XG4gICAgICAgICAgdmFsaWRhdG9ycy5wdXNoKHZhbGlkYXRlQ29tcGFyZShjb21wYXJlKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbGlkYXRvcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgLy8gZXZlbiBpZiB0aGVyZSBpcyBubyB2YWxpZGF0b3Igd2UgbmVlZCB0byBhZGQgdGhlIHByb3BlcnR5IHRvIHRoZSBncm91cFxuICAgICAgICAgICh2YWxHcm91cClbcHJvcE5hbWVdID0gW3RhcmdldFtwcm9wTmFtZV1dO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWxpZGF0b3JzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICh2YWxHcm91cClbcHJvcE5hbWVdID0gW3RhcmdldFtwcm9wTmFtZV0gfHwgJycsIHZhbGlkYXRvcnNbMF1dO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWxpZGF0b3JzLmxlbmd0aCA+PSAxKSB7XG4gICAgICAgICAgKHZhbEdyb3VwKVtwcm9wTmFtZV0gPSBbdGFyZ2V0W3Byb3BOYW1lXSB8fCAnJywgVmFsaWRhdG9ycy5jb21wb3NlKHZhbGlkYXRvcnMpXTtcbiAgICAgICAgfVxuICAgICAgICAoZXJyR3JvdXApW3Byb3BOYW1lXSA9IGVycm1zZ3M7XG4gICAgICB9XG4gICAgICAvLyBjcmVhdGUgZm9ybSBncm91cFxuICAgICAgZm9ybSA9IHRoaXMuZmIuZ3JvdXAodmFsR3JvdXApO1xuICAgICAgLy8gZm9yd2FyZCB0aGUgbW9kZWwgdG8gdGhlIGVkaXRvcnMgZm9yIGVhc3kgYWNjZXNzIHRvIG90aGVyIGRlY29yYXRvcnNcbiAgICAgIC8vIHRoZSBjYXN0IGlzIGp1c3QgdG8gc3VwcHJlc3MgVFMgZXJyb3JzIGFuZCBzaG93cyBpdCdzIGludGVudGlvbmFsbHlcbiAgICAgIChmb3JtKVsnX19lZGl0b3JNb2RlbF9fJ10gPSB0YXJnZXRJbnN0YW5jZTtcbiAgICAgIC8vIHJlZ2lzdGVyIGNvbnRyb2xzIGFuZCBhZGQgbWVzc2FnZXNcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpmb3JpblxuICAgICAgZm9yIChjb25zdCBwcm9wTmFtZSBpbiBlcnJHcm91cCkge1xuICAgICAgICBjb25zdCBjdHJsID0gZm9ybS5jb250cm9sc1twcm9wTmFtZV07XG4gICAgICAgIGlmICghY3RybCkge1xuICAgICAgICAgIGNvbnRpbnVlOyAvLyBjb250cm9sIG1pZ2h0IG5vdCBiZSBpbiB0aGUgZm9ybVxuICAgICAgICB9XG4gICAgICAgIChmb3JtLmNvbnRyb2xzW3Byb3BOYW1lXSlbJ21lc3NhZ2VzJ10gPSAoZXJyR3JvdXApW3Byb3BOYW1lXTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gcmV0dXJuIEZvcm1Hcm91cCBmb3IgaW1tZWRpYXRlIHVzYWdlXG4gICAgcmV0dXJuIGZvcm07XG4gIH1cbn1cbiJdfQ==