@rosoftlab/ionic 1.0.0-alpha-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +27 -0
  2. package/esm2022/lib/components/index.mjs +4 -0
  3. package/esm2022/lib/components/rsl-ionic-crud.component/rsl-ionic-crud.component.mjs +266 -0
  4. package/esm2022/lib/components/rsl-ionic-data-table/rsl-ionic-data-table.component.mjs +292 -0
  5. package/esm2022/lib/components/rsl-ionic-grid/rsl-ionic-grid.component.mjs +269 -0
  6. package/esm2022/lib/decorators/index.mjs +3 -0
  7. package/esm2022/lib/decorators/ionic-datatable-layout.mjs +10 -0
  8. package/esm2022/lib/decorators/ionic-list.decorator.mjs +9 -0
  9. package/esm2022/lib/interfaces/index.mjs +2 -0
  10. package/esm2022/lib/interfaces/ionic-list-layout-config.mjs +2 -0
  11. package/esm2022/lib/ionic-dialog.service.mjs +51 -0
  12. package/esm2022/lib/rsl-ionic-module.module.mjs +86 -0
  13. package/esm2022/lib/translate.extension.mjs +48 -0
  14. package/esm2022/lib/types/index.mjs +2 -0
  15. package/esm2022/lib/types/repeat/repeat-section.type.mjs +135 -0
  16. package/esm2022/lib/validators/index.mjs +2 -0
  17. package/esm2022/lib/validators/must-match.mjs +12 -0
  18. package/esm2022/lib/wrappers/accordion-wrapper.component.mjs +50 -0
  19. package/esm2022/lib/wrappers/index.mjs +3 -0
  20. package/esm2022/lib/wrappers/panel-wrapper.component.mjs +37 -0
  21. package/esm2022/lib/wrappers/wrappers.module.mjs +56 -0
  22. package/esm2022/public-api.mjs +12 -0
  23. package/esm2022/rosoftlab-ionic.mjs +5 -0
  24. package/fesm2022/rosoftlab-ionic.mjs +1251 -0
  25. package/fesm2022/rosoftlab-ionic.mjs.map +1 -0
  26. package/index.d.ts +5 -0
  27. package/lib/components/index.d.ts +3 -0
  28. package/lib/components/rsl-ionic-crud.component/rsl-ionic-crud.component.d.ts +69 -0
  29. package/lib/components/rsl-ionic-data-table/rsl-ionic-data-table.component.d.ts +66 -0
  30. package/lib/components/rsl-ionic-grid/rsl-ionic-grid.component.d.ts +58 -0
  31. package/lib/decorators/index.d.ts +2 -0
  32. package/lib/decorators/ionic-datatable-layout.d.ts +7 -0
  33. package/lib/decorators/ionic-list.decorator.d.ts +2 -0
  34. package/lib/interfaces/index.d.ts +1 -0
  35. package/lib/interfaces/ionic-list-layout-config.d.ts +8 -0
  36. package/lib/ionic-dialog.service.d.ts +10 -0
  37. package/lib/rsl-ionic-module.module.d.ts +13 -0
  38. package/lib/translate.extension.d.ts +17 -0
  39. package/lib/types/index.d.ts +1 -0
  40. package/lib/types/repeat/repeat-section.type.d.ts +51 -0
  41. package/lib/validators/index.d.ts +1 -0
  42. package/lib/validators/must-match.d.ts +6 -0
  43. package/lib/wrappers/accordion-wrapper.component.d.ts +6 -0
  44. package/lib/wrappers/index.d.ts +2 -0
  45. package/lib/wrappers/panel-wrapper.component.d.ts +6 -0
  46. package/lib/wrappers/wrappers.module.d.ts +13 -0
  47. package/package.json +31 -0
  48. package/public-api.d.ts +8 -0
package/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # RslWorkspace
2
+
3
+ This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.1.3.
4
+
5
+ ## Development server
6
+
7
+ Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
8
+
9
+ ## Code scaffolding
10
+
11
+ Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
12
+
13
+ ## Build
14
+
15
+ Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
16
+
17
+ ## Running unit tests
18
+
19
+ Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
20
+
21
+ ## Running end-to-end tests
22
+
23
+ Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
24
+
25
+ ## Further help
26
+
27
+ To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
@@ -0,0 +1,4 @@
1
+ export { GenericIonicCrudComponent } from './rsl-ionic-crud.component/rsl-ionic-crud.component';
2
+ export { RslIonicDataTableComponent } from "./rsl-ionic-data-table/rsl-ionic-data-table.component";
3
+ export { RslIonicGridComponent } from './rsl-ionic-grid/rsl-ionic-grid.component';
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9yb3NvZnRsYWIvaW9uaWMvc3JjL2xpYi9jb21wb25lbnRzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLHFEQUFxRCxDQUFBO0FBQy9GLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLHVEQUF1RCxDQUFBO0FBQ2xHLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDJDQUEyQyxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgR2VuZXJpY0lvbmljQ3J1ZENvbXBvbmVudCB9IGZyb20gJy4vcnNsLWlvbmljLWNydWQuY29tcG9uZW50L3JzbC1pb25pYy1jcnVkLmNvbXBvbmVudCdcclxuZXhwb3J0IHsgUnNsSW9uaWNEYXRhVGFibGVDb21wb25lbnQgfSBmcm9tIFwiLi9yc2wtaW9uaWMtZGF0YS10YWJsZS9yc2wtaW9uaWMtZGF0YS10YWJsZS5jb21wb25lbnRcIlxyXG5leHBvcnQgeyBSc2xJb25pY0dyaWRDb21wb25lbnQgfSBmcm9tICcuL3JzbC1pb25pYy1ncmlkL3JzbC1pb25pYy1ncmlkLmNvbXBvbmVudCdcclxuIl19
@@ -0,0 +1,266 @@
1
+ import { Location } from '@angular/common';
2
+ import { Component, Injector } from '@angular/core';
3
+ import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
4
+ import { ActivatedRoute, Router } from '@angular/router';
5
+ import { FormlyJsonschema } from '@ngx-formly/core/json-schema';
6
+ import { TranslateService } from '@ngx-translate/core';
7
+ import * as _ from 'lodash';
8
+ import { Observable, from } from 'rxjs';
9
+ import { IonicDialogService } from '../../ionic-dialog.service';
10
+ import { RslIonicModuleModule } from '../../rsl-ionic-module.module';
11
+ import * as i0 from "@angular/core";
12
+ import * as i1 from "@angular/forms";
13
+ import * as i2 from "@angular/router";
14
+ import * as i3 from "../../ionic-dialog.service";
15
+ import * as i4 from "@ngx-translate/core";
16
+ import * as i5 from "@angular/common";
17
+ import * as i6 from "@ngx-formly/core/json-schema";
18
+ import * as i7 from "@ionic/angular";
19
+ import * as i8 from "@ngx-formly/core";
20
+ export class GenericIonicCrudComponent {
21
+ //#endregion
22
+ constructor(fb, router, route, dialogService, translate, location, injector, formlyJsonschema) {
23
+ this.fb = fb;
24
+ this.router = router;
25
+ this.route = route;
26
+ this.dialogService = dialogService;
27
+ this.translate = translate;
28
+ this.location = location;
29
+ this.injector = injector;
30
+ this.formlyJsonschema = formlyJsonschema;
31
+ this.isLoading = true;
32
+ this.changeUrlRoute = true;
33
+ this.options = {};
34
+ const SERVICE_TOKEN = route.snapshot.data['requiredService'];
35
+ this.modelService = this.injector.get(SERVICE_TOKEN);
36
+ this.modelService = this.injector.get(SERVICE_TOKEN);
37
+ this.confirmQuestion = this.translate.instant('General.Discard.Question');
38
+ this.confirmButton = this.translate.instant('General.Discard.ConfirmButton');
39
+ this.saveMessage = this.translate.instant('General.Save.Message');
40
+ }
41
+ ionViewWillLeave() {
42
+ this.options.resetModel();
43
+ this.baseForm.reset();
44
+ }
45
+ afterSave(model) {
46
+ return new Observable((observer) => {
47
+ observer.next(model);
48
+ observer.complete();
49
+ });
50
+ }
51
+ beforeSave(model) {
52
+ return new Observable((observer) => {
53
+ observer.next(model);
54
+ observer.complete();
55
+ });
56
+ }
57
+ ngOnInit() {
58
+ this.initForm();
59
+ }
60
+ initForm(customInclude = '', newModelId = null, model = null) {
61
+ if (model === null) {
62
+ this.modelId = this.route.snapshot.paramMap.get('id') ?? newModelId;
63
+ this.isEdit = false;
64
+ if (this.modelId) {
65
+ this.modelService.get(this.modelId, customInclude).subscribe((value) => {
66
+ this.isEdit = true;
67
+ this.generateForm(value);
68
+ });
69
+ }
70
+ else {
71
+ if (this.changeUrlRoute) {
72
+ const addUrl = this.router.createUrlTree([]).toString();
73
+ this.editRoute = this.router.createUrlTree([addUrl.replace('add', 'edit')]).toString();
74
+ }
75
+ // }
76
+ this.generateForm(this.modelService.newModel());
77
+ }
78
+ }
79
+ else {
80
+ this.modelId = model.id;
81
+ this.isEdit = true;
82
+ this.generateForm(model);
83
+ }
84
+ }
85
+ generateForm(model) {
86
+ this.isLoading = false;
87
+ this.modelId = model.id;
88
+ this.model = model;
89
+ this.origModel = _.cloneDeep(model);
90
+ ;
91
+ this.title = this.model.modelConfig.formTitle;
92
+ this.baseForm = new UntypedFormGroup({}); //= this.modelService.toFormGroup(this.fb, model);
93
+ this.afterFormGenerated();
94
+ this.fields = this.modelService.getFormlyFields(this.model);
95
+ }
96
+ afterFormGenerated() {
97
+ }
98
+ getFromGroup(formGroup = null) {
99
+ if (!formGroup)
100
+ return this.baseForm;
101
+ if (formGroup instanceof UntypedFormGroup)
102
+ return formGroup;
103
+ return this.baseForm.controls[formGroup];
104
+ }
105
+ validateAllFormFields(formGroup = null) {
106
+ const fg = this.getFromGroup(formGroup);
107
+ Object.keys(fg.controls).forEach(field => {
108
+ // console.log(field);
109
+ const control = fg.get(field);
110
+ if (control instanceof UntypedFormControl) {
111
+ control.markAsTouched({ onlySelf: true });
112
+ }
113
+ else if (control instanceof UntypedFormGroup) {
114
+ this.validateAllFormFields(control);
115
+ }
116
+ });
117
+ }
118
+ isFieldValid(field, formGroup = null) {
119
+ const fg = this.getFromGroup(formGroup);
120
+ const filedControl = fg.get(field);
121
+ return !filedControl.valid && filedControl.touched;
122
+ }
123
+ isFieldValidFromArray(arrayIndex, field, arrayName = 'formArray') {
124
+ const fieldControl = this.baseForm.get(arrayName).get([arrayIndex]).get(field);
125
+ return !fieldControl.valid && fieldControl.touched;
126
+ }
127
+ displayFieldCss(field) {
128
+ return {
129
+ 'has-error': this.isFieldValid(field),
130
+ 'has-feedback': this.isFieldValid(field)
131
+ };
132
+ }
133
+ onCancel() {
134
+ this.router.navigate([this.cancelRoute]);
135
+ }
136
+ onSave() {
137
+ this.saveModel(this.baseForm);
138
+ }
139
+ onSubmit(model) {
140
+ this.saveModel(this.baseForm);
141
+ }
142
+ saveModel(formGroup = null) {
143
+ const fg = this.getFromGroup(formGroup);
144
+ const that = this;
145
+ if (fg) {
146
+ if (fg.valid) {
147
+ this.beforeSave(this.model).subscribe(_ => {
148
+ this.modelService.save(this.model, this.modelId, this.origModel).subscribe((newModel) => {
149
+ this.model = newModel;
150
+ this.modelId = newModel.id;
151
+ if (this.editRoute) {
152
+ this.isEdit = true;
153
+ if (this.changeUrlRoute) {
154
+ const url = this.router.createUrlTree([this.editRoute, this.modelId]).toString();
155
+ this.location.replaceState(url);
156
+ }
157
+ }
158
+ this.afterSave(newModel).subscribe((val) => {
159
+ from(this.dialogService.showSaveMessage(this.saveMessage)).subscribe(d => {
160
+ this.options.updateInitialValue();
161
+ fg.markAsPristine();
162
+ });
163
+ });
164
+ }, err => {
165
+ this.serverErrors(err);
166
+ });
167
+ });
168
+ }
169
+ else {
170
+ this.validateAllFormFields(formGroup);
171
+ }
172
+ }
173
+ }
174
+ serverErrors(err) {
175
+ if (err.error) {
176
+ if (err.error.errors) {
177
+ const validationErrors = err.error.errors;
178
+ if (Array.isArray(validationErrors)) {
179
+ validationErrors.forEach(prop => {
180
+ const formControl = this.baseForm.get(this.firstCharToLowerCase(prop));
181
+ if (formControl) {
182
+ // activate the error message
183
+ formControl.setErrors({
184
+ serverError: { message: validationErrors[prop].join('\n') }
185
+ });
186
+ }
187
+ });
188
+ }
189
+ else {
190
+ const keys = Object.keys(validationErrors);
191
+ keys.forEach(prop => {
192
+ const formControl = this.baseForm.get(this.firstCharToLowerCase(prop));
193
+ if (formControl) {
194
+ // activate the error message
195
+ formControl.setErrors({
196
+ serverError: { message: validationErrors[prop].join('\n') }
197
+ });
198
+ }
199
+ });
200
+ }
201
+ }
202
+ }
203
+ }
204
+ firstCharToLowerCase(str) {
205
+ if (str.length === 0) {
206
+ return str; // Return an empty string if the input is empty
207
+ }
208
+ const firstChar = str.charAt(0).toLowerCase();
209
+ const restOfString = str.slice(1);
210
+ return firstChar + restOfString;
211
+ }
212
+ async canDeactivate() {
213
+ if (!this.baseForm.dirty) {
214
+ return true;
215
+ }
216
+ var result = await this.dialogService.confirm(this.confirmQuestion, null, this.confirmButton);
217
+ return result;
218
+ }
219
+ getFiledName(filedTranslationKey) {
220
+ return { field: this.translate.instant(filedTranslationKey) };
221
+ }
222
+ getCustomErrorMessage(error, fieldLabel) {
223
+ return '';
224
+ }
225
+ getErrorMessageFromArray(arrayIndex, field, filedTranslationKey, arrayName = 'formArray') {
226
+ const fieldControl = this.baseForm.get(arrayName).get([arrayIndex]).get(field);
227
+ return this.getErrorMessageForField(fieldControl, filedTranslationKey);
228
+ }
229
+ getErrorMessage(field, filedTranslationKey, formGroup = null) {
230
+ const fg = this.getFromGroup(formGroup);
231
+ return this.getErrorMessageForField(fg.get(field), filedTranslationKey);
232
+ }
233
+ getErrorMessageForField(fieldControl, filedTranslationKey) {
234
+ const error = fieldControl.errors;
235
+ const fieldLabel = this.translate.instant(filedTranslationKey);
236
+ let rvalue = '';
237
+ if (error !== null) {
238
+ if (error['required'] === true) {
239
+ rvalue = this.translate.instant('General.Field.Required', { field: fieldLabel });
240
+ }
241
+ if (error['minlength']) {
242
+ rvalue = this.translate.instant('General.Field.MinLength', { field: fieldLabel, requiredLength: error.minlength.requiredLength });
243
+ }
244
+ if (error['email'] === true) {
245
+ rvalue = this.translate.instant('General.Field.InvalidEmail');
246
+ }
247
+ if (error['url'] === true) {
248
+ rvalue = this.translate.instant('General.Field.InvalidUrl');
249
+ }
250
+ if (error['serverError']) {
251
+ rvalue = error['serverError'];
252
+ }
253
+ if (rvalue === '') {
254
+ rvalue = this.getCustomErrorMessage(error, fieldLabel);
255
+ }
256
+ }
257
+ return rvalue;
258
+ }
259
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: GenericIonicCrudComponent, deps: [{ token: i1.UntypedFormBuilder }, { token: i2.Router }, { token: i2.ActivatedRoute }, { token: i3.IonicDialogService }, { token: i4.TranslateService }, { token: i5.Location }, { token: i0.Injector }, { token: i6.FormlyJsonschema }], target: i0.ɵɵFactoryTarget.Component }); }
260
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: GenericIonicCrudComponent, isStandalone: true, selector: "rslc-ionic-crud", ngImport: i0, template: "<ion-header [translucent]=\"true\">\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-menu-button></ion-menu-button>\n <ion-back-button></ion-back-button>\n </ion-buttons>\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\n </ion-toolbar>\n</ion-header>\n\n<ion-content [fullscreen]=\"true\">\n <ng-container *ngIf=\"!isLoading\">\n <form [formGroup]=\"baseForm\" (ngSubmit)=\"onSubmit(model)\">\n <formly-form [form]=\"baseForm\" [fields]=\"fields\" [model]=\"model\" [options]=\"options\"></formly-form>\n </form>\n </ng-container>\n</ion-content>\n\n<ng-template #header>\n <ion-title class=\"ion-text-center\">{{title |translate}}</ion-title>\n <ion-button *ngIf=\"!isLoading\" slot=\"end\" fill=\"clear\" (click)=\"onSave()\"\n [disabled]=\"baseForm.invalid || !baseForm.dirty\">\n <ion-icon size=\"large\" name=\"save\"></ion-icon>\n </ion-button>\n</ng-template>", styles: [""], dependencies: [{ kind: "ngmodule", type: RslIonicModuleModule }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i7.IonBackButton, selector: "ion-back-button", inputs: ["color", "defaultHref", "disabled", "icon", "mode", "routerAnimation", "text", "type"] }, { kind: "component", type: i7.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i7.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i7.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i7.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i7.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i7.IonMenuButton, selector: "ion-menu-button", inputs: ["autoHide", "color", "disabled", "menu", "mode", "type"] }, { kind: "component", type: i7.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i7.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i7.IonBackButtonDelegate, selector: "ion-back-button", inputs: ["defaultHref", "routerAnimation"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i8.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "pipe", type: i4.TranslatePipe, name: "translate" }] }); }
261
+ }
262
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: GenericIonicCrudComponent, decorators: [{
263
+ type: Component,
264
+ args: [{ standalone: true, selector: 'rslc-ionic-crud', imports: [RslIonicModuleModule], template: "<ion-header [translucent]=\"true\">\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-menu-button></ion-menu-button>\n <ion-back-button></ion-back-button>\n </ion-buttons>\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\n </ion-toolbar>\n</ion-header>\n\n<ion-content [fullscreen]=\"true\">\n <ng-container *ngIf=\"!isLoading\">\n <form [formGroup]=\"baseForm\" (ngSubmit)=\"onSubmit(model)\">\n <formly-form [form]=\"baseForm\" [fields]=\"fields\" [model]=\"model\" [options]=\"options\"></formly-form>\n </form>\n </ng-container>\n</ion-content>\n\n<ng-template #header>\n <ion-title class=\"ion-text-center\">{{title |translate}}</ion-title>\n <ion-button *ngIf=\"!isLoading\" slot=\"end\" fill=\"clear\" (click)=\"onSave()\"\n [disabled]=\"baseForm.invalid || !baseForm.dirty\">\n <ion-icon size=\"large\" name=\"save\"></ion-icon>\n </ion-button>\n</ng-template>" }]
265
+ }], ctorParameters: function () { return [{ type: i1.UntypedFormBuilder }, { type: i2.Router }, { type: i2.ActivatedRoute }, { type: i3.IonicDialogService }, { type: i4.TranslateService }, { type: i5.Location }, { type: i0.Injector }, { type: i6.FormlyJsonschema }]; } });
266
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnNsLWlvbmljLWNydWQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvcm9zb2Z0bGFiL2lvbmljL3NyYy9saWIvY29tcG9uZW50cy9yc2wtaW9uaWMtY3J1ZC5jb21wb25lbnQvcnNsLWlvbmljLWNydWQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvcm9zb2Z0bGFiL2lvbmljL3NyYy9saWIvY29tcG9uZW50cy9yc2wtaW9uaWMtY3J1ZC5jb21wb25lbnQvcnNsLWlvbmljLWNydWQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFVLE1BQU0sZUFBZSxDQUFDO0FBQzVELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxrQkFBa0IsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzFGLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFekQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDaEUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFdkQsT0FBTyxLQUFLLENBQUMsTUFBTSxRQUFRLENBQUM7QUFDNUIsT0FBTyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDeEMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDaEUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sK0JBQStCLENBQUM7Ozs7Ozs7Ozs7QUFTckUsTUFBTSxPQUFPLHlCQUF5QjtJQWtCcEMsWUFBWTtJQUNaLFlBQ1MsRUFBc0IsRUFDdEIsTUFBYyxFQUNk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LEVBQUU7Z0JBQzNCLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO2FBQy9EO1lBQ0QsSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxFQUFFO2dCQUN6QixNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsMEJBQTBCLENBQUMsQ0FBQzthQUM3RDtZQUNELElBQUksS0FBSyxDQUFDLGFBQWEsQ0FBQyxFQUFFO2dCQUN4QixNQUFNLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO2FBQy9CO1lBQ0QsSUFBSSxNQUFNLEtBQUssRUFBRSxFQUFFO2dCQUNqQixNQUFNLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLEtBQUssRUFBRSxVQUFVLENBQUMsQ0FBQzthQUN4RDtTQUNGO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQzs4R0F0UVUseUJBQXlCO2tHQUF6Qix5QkFBeUIsMkVDcEJ0QyxtNkJBd0JjLHlERFBGLG9CQUFvQjs7MkZBR25CLHlCQUF5QjtrQkFSckMsU0FBUztpQ0FDSSxJQUFJLFlBQ04saUJBQWlCLFdBR2xCLENBQUMsb0JBQW9CLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBMb2NhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBDb21wb25lbnQsIEluamVjdG9yLCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFVudHlwZWRGb3JtQnVpbGRlciwgVW50eXBlZEZvcm1Db250cm9sLCBVbnR5cGVkRm9ybUdyb3VwIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUsIFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBGb3JtbHlGaWVsZENvbmZpZywgRm9ybWx5Rm9ybU9wdGlvbnMgfSBmcm9tICdAbmd4LWZvcm1seS9jb3JlJztcbmltcG9ydCB7IEZvcm1seUpzb25zY2hlbWEgfSBmcm9tICdAbmd4LWZvcm1seS9jb3JlL2pzb24tc2NoZW1hJztcbmltcG9ydCB7IFRyYW5zbGF0ZVNlcnZpY2UgfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcbmltcG9ydCB7IEJhc2VNb2RlbEZvcm1seSwgQmFzZVNlcnZpY2VGb3JtbHkgfSBmcm9tICdAcm9zb2Z0bGFiL2Zvcm1seSc7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBmcm9tIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBJb25pY0RpYWxvZ1NlcnZpY2UgfSBmcm9tICcuLi8uLi9pb25pYy1kaWFsb2cuc2VydmljZSc7XG5pbXBvcnQgeyBSc2xJb25pY01vZHVsZU1vZHVsZSB9IGZyb20gJy4uLy4uL3JzbC1pb25pYy1tb2R1bGUubW9kdWxlJztcbkBDb21wb25lbnQoe1xuICBzdGFuZGFsb25lOiB0cnVlLFxuICBzZWxlY3RvcjogJ3JzbGMtaW9uaWMtY3J1ZCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9yc2wtaW9uaWMtY3J1ZC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3JzbC1pb25pYy1jcnVkLmNvbXBvbmVudC5jc3MnXSxcbiAgaW1wb3J0czogW1JzbElvbmljTW9kdWxlTW9kdWxlXVxuXG59KVxuZXhwb3J0IGNsYXNzIEdlbmVyaWNJb25pY0NydWRDb21wb25lbnQ8VCBleHRlbmRzIEJhc2VNb2RlbEZvcm1seSwgVSBleHRlbmRzIEJhc2VTZXJ2aWNlRm9ybWx5PFQ+PiBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIGJhc2VGb3JtOiBVbnR5cGVkRm9ybUdyb3VwO1xuICBtb2RlbElkOiBzdHJpbmc7XG4gIG1vZGVsOiBUO1xuICBvcmlnTW9kZWw6IFQ7XG4gIGlzRWRpdDogYm9vbGVhbjtcbiAgaXNMb2FkaW5nID0gdHJ1ZTtcbiAgY2FuY2VsUm91dGU6IHN0cmluZztcbiAgZWRpdFJvdXRlOiBzdHJpbmc7XG4gIG1vZGVsU2VydmljZTogVVxuICBwdWJsaWMgY2hhbmdlVXJsUm91dGU6IGJvb2xlYW4gPSB0cnVlO1xuICBwdWJsaWMgdGl0bGU6IHN0cmluZztcbiAgZmllbGRzOiBGb3JtbHlGaWVsZENvbmZpZ1tdXG4gIG9wdGlvbnM6IEZvcm1seUZvcm1PcHRpb25zID0ge307XG4gIC8vI3JlZ2lvbiBEaWFsb2cgbWVzc2FnZXNcbiAgY29uZmlybVF1ZXN0aW9uOiBzdHJpbmdcbiAgY29uZmlybUJ1dHRvbjogc3RyaW5nXG4gIHNhdmVNZXNzYWdlOiBzdHJpbmdcbiAgLy8jZW5kcmVnaW9uXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyBmYjogVW50eXBlZEZvcm1CdWlsZGVyLFxuICAgIHB1YmxpYyByb3V0ZXI6IFJvdXRlcixcbiAgICBwdWJsaWMgcm91dGU6IEFjdGl2YXRlZFJvdXRlLFxuICAgIHB1YmxpYyBkaWFsb2dTZXJ2aWNlOiBJb25pY0RpYWxvZ1NlcnZpY2UsXG4gICAgcHVibGljIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcbiAgICBwdWJsaWMgbG9jYXRpb246IExvY2F0aW9uLFxuICAgIHByaXZhdGUgaW5qZWN0b3I6IEluamVjdG9yLFxuICAgIHByaXZhdGUgZm9ybWx5SnNvbnNjaGVtYTogRm9ybWx5SnNvbnNjaGVtYSxcbiAgKSB7XG5cbiAgICBjb25zdCBTRVJWSUNFX1RPS0VOID0gcm91dGUuc25hcHNob3QuZGF0YVsncmVxdWlyZWRTZXJ2aWNlJ107XG4gICAgdGhpcy5tb2RlbFNlcnZpY2UgPSB0aGlzLmluamVjdG9yLmdldDxVPig8YW55PlNFUlZJQ0VfVE9LRU4pO1xuXG4gICAgdGhpcy5tb2RlbFNlcnZpY2UgPSB0aGlzLmluamVjdG9yLmdldDxVPig8YW55PlNFUlZJQ0VfVE9LRU4pO1xuICAgIHRoaXMuY29uZmlybVF1ZXN0aW9uID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudCgnR2VuZXJhbC5EaXNjYXJkLlF1ZXN0aW9uJyk7XG4gICAgdGhpcy5jb25maXJtQnV0dG9uID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudCgnR2VuZXJhbC5EaXNjYXJkLkNvbmZpcm1CdXR0b24nKTtcbiAgICB0aGlzLnNhdmVNZXNzYWdlID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudCgnR2VuZXJhbC5TYXZlLk1lc3NhZ2UnKTtcbiAgfVxuXG4gIGlvblZpZXdXaWxsTGVhdmUoKSB7XG4gICAgdGhpcy5vcHRpb25zLnJlc2V0TW9kZWwoKVxuICAgIHRoaXMuYmFzZUZvcm0ucmVzZXQoKTtcbiAgfVxuXG4gIHB1YmxpYyBhZnRlclNhdmUobW9kZWw6IFQpOiBPYnNlcnZhYmxlPFQ+IHtcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyKSA9PiB7XG4gICAgICBvYnNlcnZlci5uZXh0KG1vZGVsKTtcbiAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgYmVmb3JlU2F2ZShtb2RlbDogVCk6IE9ic2VydmFibGU8VD4ge1xuICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZSgob2JzZXJ2ZXIpID0+IHtcbiAgICAgIG9ic2VydmVyLm5leHQobW9kZWwpO1xuICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuaW5pdEZvcm0oKTtcbiAgfVxuICBpbml0Rm9ybShjdXN0b21JbmNsdWRlOiBzdHJpbmcgPSAnJywgbmV3TW9kZWxJZDogc3RyaW5nID0gbnVsbCwgbW9kZWw6IFQgPSBudWxsKSB7XG4gICAgaWYgKG1vZGVsID09PSBudWxsKSB7XG4gICAgICB0aGlzLm1vZGVsSWQgPSB0aGlzLnJvdXRlLnNuYXBzaG90LnBhcmFtTWFwLmdldCgnaWQnKSA/PyBuZXdNb2RlbElkO1xuICAgICAgdGhpcy5pc0VkaXQgPSBmYWxzZTtcbiAgICAgIGlmICh0aGlzLm1vZGVsSWQpIHtcbiAgICAgICAgdGhpcy5tb2RlbFNlcnZpY2UuZ2V0KHRoaXMubW9kZWxJZCwgY3VzdG9tSW5jbHVkZSkuc3Vic2NyaWJlKCh2YWx1ZTogVCkgPT4ge1xuICAgICAgICAgIHRoaXMuaXNFZGl0ID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLmdlbmVyYXRlRm9ybSh2YWx1ZSlcbiAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHRoaXMuY2hhbmdlVXJsUm91dGUpIHtcbiAgICAgICAgICBjb25zdCBhZGRVcmwgPSB0aGlzLnJvdXRlci5jcmVhdGVVcmxUcmVlKFtdKS50b1N0cmluZygpO1xuICAgICAgICAgIHRoaXMuZWRpdFJvdXRlID0gdGhpcy5yb3V0ZXIuY3JlYXRlVXJsVHJlZShbYWRkVXJsLnJlcGxhY2UoJ2FkZCcsICdlZGl0JyldKS50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgICAgIC8vIH1cbiAgICAgICAgdGhpcy5nZW5lcmF0ZUZvcm0odGhpcy5tb2RlbFNlcnZpY2UubmV3TW9kZWwoKSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubW9kZWxJZCA9IG1vZGVsLmlkO1xuICAgICAgdGhpcy5pc0VkaXQgPSB0cnVlO1xuICAgICAgdGhpcy5nZW5lcmF0ZUZvcm0obW9kZWwpXG4gICAgfVxuICB9XG4gIGdlbmVyYXRlRm9ybShtb2RlbD86IFQpIHtcbiAgICB0aGlzLmlzTG9hZGluZyA9IGZhbHNlO1xuICAgIHRoaXMubW9kZWxJZCA9IG1vZGVsLmlkO1xuICAgIHRoaXMubW9kZWwgPSBtb2RlbDtcbiAgICB0aGlzLm9yaWdNb2RlbCA9IF8uY2xvbmVEZWVwKG1vZGVsKTs7XG4gICAgdGhpcy50aXRsZSA9IHRoaXMubW9kZWwubW9kZWxDb25maWcuZm9ybVRpdGxlXG4gICAgdGhpcy5iYXNlRm9ybSA9IG5ldyBVbnR5cGVkRm9ybUdyb3VwKHt9KTsvLz0gdGhpcy5tb2RlbFNlcnZpY2UudG9Gb3JtR3JvdXAodGhpcy5mYiwgbW9kZWwpO1xuICAgIHRoaXMuYWZ0ZXJGb3JtR2VuZXJhdGVkKCk7XG4gICAgdGhpcy5maWVsZHMgPSB0aGlzLm1vZGVsU2VydmljZS5nZXRGb3JtbHlGaWVsZHModGhpcy5tb2RlbClcbiAgfVxuICBwdWJsaWMgYWZ0ZXJGb3JtR2VuZXJhdGVkKCkge1xuXG4gIH1cbiAgcHJpdmF0ZSBnZXRGcm9tR3JvdXAoZm9ybUdyb3VwOiBVbnR5cGVkRm9ybUdyb3VwIHwgc3RyaW5nID0gbnVsbCk6IFVudHlwZWRGb3JtR3JvdXAge1xuICAgIGlmICghZm9ybUdyb3VwKVxuICAgICAgcmV0dXJuIHRoaXMuYmFzZUZvcm07XG4gICAgaWYgKGZvcm1Hcm91cCBpbnN0YW5jZW9mIFVudHlwZWRGb3JtR3JvdXApXG4gICAgICByZXR1cm4gZm9ybUdyb3VwO1xuICAgIHJldHVybiB0aGlzLmJhc2VGb3JtLmNvbnRyb2xzW2Zvcm1Hcm91cF0gYXMgVW50eXBlZEZvcm1Hcm91cDtcbiAgfVxuICB2YWxpZGF0ZUFsbEZvcm1GaWVsZHMoZm9ybUdyb3VwOiBVbnR5cGVkRm9ybUdyb3VwIHwgc3RyaW5nID0gbnVsbCkge1xuICAgIGNvbnN0IGZnID0gdGhpcy5nZXRGcm9tR3JvdXAoZm9ybUdyb3VwKVxuICAgIE9iamVjdC5rZXlzKGZnLmNvbnRyb2xzKS5mb3JFYWNoKGZpZWxkID0+IHtcbiAgICAgIC8vIGNvbnNvbGUubG9nKGZpZWxkKTtcbiAgICAgIGNvbnN0IGNvbnRyb2wgPSBmZy5nZXQoZmllbGQpO1xuICAgICAgaWYgKGNvbnRyb2wgaW5zdGFuY2VvZiBVbnR5cGVkRm9ybUNvbnRyb2wpIHtcbiAgICAgICAgY29udHJvbC5tYXJrQXNUb3VjaGVkKHsgb25seVNlbGY6IHRydWUgfSk7XG4gICAgICB9IGVsc2UgaWYgKGNvbnRyb2wgaW5zdGFuY2VvZiBVbnR5cGVkRm9ybUdyb3VwKSB7XG4gICAgICAgIHRoaXMudmFsaWRhdGVBbGxGb3JtRmllbGRzKGNvbnRyb2wpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG4gIGlzRmllbGRWYWxpZChmaWVsZDogc3RyaW5nLCBmb3JtR3JvdXA6IFVudHlwZWRGb3JtR3JvdXAgfCBzdHJpbmcgPSBudWxsKSB7XG4gICAgY29uc3QgZmcgPSB0aGlzLmdldEZyb21Hcm91cChmb3JtR3JvdXApXG4gICAgY29uc3QgZmlsZWRDb250cm9sID0gZmcuZ2V0KGZpZWxkKVxuICAgIHJldHVybiAhZmlsZWRDb250cm9sLnZhbGlkICYmIGZpbGVkQ29udHJvbC50b3VjaGVkO1xuICB9XG5cbiAgaXNGaWVsZFZhbGlkRnJvbUFycmF5KGFycmF5SW5kZXg6IG51bWJlciwgZmllbGQ6IHN0cmluZywgYXJyYXlOYW1lOiBzdHJpbmcgPSAnZm9ybUFycmF5Jykge1xuICAgIGNvbnN0IGZpZWxkQ29udHJvbCA9IHRoaXMuYmFzZUZvcm0uZ2V0KGFycmF5TmFtZSkuZ2V0KFthcnJheUluZGV4XSkuZ2V0KGZpZWxkKVxuICAgIHJldHVybiAhZmllbGRDb250cm9sLnZhbGlkICYmIGZpZWxkQ29udHJvbC50b3VjaGVkO1xuICB9XG5cbiAgZGlzcGxheUZpZWxkQ3NzKGZpZWxkOiBzdHJpbmcpIHtcbiAgICByZXR1cm4ge1xuICAgICAgJ2hhcy1lcnJvcic6IHRoaXMuaXNGaWVsZFZhbGlkKGZpZWxkKSxcbiAgICAgICdoYXMtZmVlZGJhY2snOiB0aGlzLmlzRmllbGRWYWxpZChmaWVsZClcbiAgICB9O1xuICB9XG4gIG9uQ2FuY2VsKCkge1xuICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFt0aGlzLmNhbmNlbFJvdXRlXSk7XG4gIH1cbiAgb25TYXZlKCkge1xuICAgIHRoaXMuc2F2ZU1vZGVsKHRoaXMuYmFzZUZvcm0pXG4gIH1cbiAgb25TdWJtaXQobW9kZWwpIHtcbiAgICB0aGlzLnNhdmVNb2RlbCh0aGlzLmJhc2VGb3JtKVxuICB9XG5cbiAgc2F2ZU1vZGVsKGZvcm1Hcm91cDogVW50eXBlZEZvcm1Hcm91cCB8IHN0cmluZyA9IG51bGwpIHtcbiAgICBjb25zdCBmZyA9IHRoaXMuZ2V0RnJvbUdyb3VwKGZvcm1Hcm91cClcbiAgICBjb25zdCB0aGF0ID0gdGhpcztcbiAgICBpZiAoZmcpIHtcbiAgICAgIGlmIChmZy52YWxpZCkge1xuICAgICAgICB0aGlzLmJlZm9yZVNhdmUodGhpcy5tb2RlbCkuc3Vic2NyaWJlKF8gPT4ge1xuICAgICAgICAgIHRoaXMubW9kZWxTZXJ2aWNlLnNhdmUodGhpcy5tb2RlbCwgdGhpcy5tb2RlbElkLCB0aGlzLm9yaWdNb2RlbCkuc3Vic2NyaWJlKFxuICAgICAgICAgICAgKG5ld01vZGVsOiBUKSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMubW9kZWwgPSBuZXdNb2RlbDtcbiAgICAgICAgICAgICAgdGhpcy5tb2RlbElkID0gbmV3TW9kZWwuaWQ7XG4gICAgICAgICAgICAgIGlmICh0aGlzLmVkaXRSb3V0ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuaXNFZGl0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jaGFuZ2VVcmxSb3V0ZSkge1xuICAgICAgICAgICAgICAgICAgY29uc3QgdXJsID0gdGhpcy5yb3V0ZXIuY3JlYXRlVXJsVHJlZShbdGhpcy5lZGl0Um91dGUsIHRoaXMubW9kZWxJZF0pLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICB0aGlzLmxvY2F0aW9uLnJlcGxhY2VTdGF0ZSh1cmwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB0aGlzLmFmdGVyU2F2ZShuZXdNb2RlbCkuc3Vic2NyaWJlKCh2YWw6IFQpID0+IHtcbiAgICAgICAgICAgICAgICBmcm9tKHRoaXMuZGlhbG9nU2VydmljZS5zaG93U2F2ZU1lc3NhZ2UodGhpcy5zYXZlTWVzc2FnZSkpLnN1YnNjcmliZShkID0+IHtcbiAgICAgICAgICAgICAgICAgIHRoaXMub3B0aW9ucy51cGRhdGVJbml0aWFsVmFsdWUoKVxuICAgICAgICAgICAgICAgICAgZmcubWFya0FzUHJpc3RpbmUoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXJyID0+IHtcbiAgICAgICAgICAgICAgdGhpcy5zZXJ2ZXJFcnJvcnMoZXJyKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy52YWxpZGF0ZUFsbEZvcm1GaWVsZHMoZm9ybUdyb3VwKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgc2VydmVyRXJyb3JzKGVycjogYW55KSB7XG4gICAgaWYgKGVyci5lcnJvcikge1xuICAgICAgaWYgKGVyci5lcnJvci5lcnJvcnMpIHtcbiAgICAgICAgY29uc3QgdmFsaWRhdGlvbkVycm9ycyA9IGVyci5lcnJvci5lcnJvcnM7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbGlkYXRpb25FcnJvcnMpKSB7XG4gICAgICAgICAgdmFsaWRhdGlvbkVycm9ycy5mb3JFYWNoKHByb3AgPT4ge1xuICAgICAgICAgICAgY29uc3QgZm9ybUNvbnRyb2wgPSB0aGlzLmJhc2VGb3JtLmdldCh0aGlzLmZpcnN0Q2hhclRvTG93ZXJDYXNlKHByb3ApKTtcbiAgICAgICAgICAgIGlmIChmb3JtQ29udHJvbCkge1xuICAgICAgICAgICAgICAvLyBhY3RpdmF0ZSB0aGUgZXJyb3IgbWVzc2FnZVxuICAgICAgICAgICAgICBmb3JtQ29udHJvbC5zZXRFcnJvcnMoe1xuICAgICAgICAgICAgICAgIHNlcnZlckVycm9yOiB7IG1lc3NhZ2U6IHZhbGlkYXRpb25FcnJvcnNbcHJvcF0uam9pbignXFxuJykgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXModmFsaWRhdGlvbkVycm9ycyk7XG4gICAgICAgICAga2V5cy5mb3JFYWNoKHByb3AgPT4ge1xuICAgICAgICAgICAgY29uc3QgZm9ybUNvbnRyb2wgPSB0aGlzLmJhc2VGb3JtLmdldCh0aGlzLmZpcnN0Q2hhclRvTG93ZXJDYXNlKHByb3ApKTtcbiAgICAgICAgICAgIGlmIChmb3JtQ29udHJvbCkge1xuICAgICAgICAgICAgICAvLyBhY3RpdmF0ZSB0aGUgZXJyb3IgbWVzc2FnZVxuICAgICAgICAgICAgICBmb3JtQ29udHJvbC5zZXRFcnJvcnMoe1xuICAgICAgICAgICAgICAgIHNlcnZlckVycm9yOiB7IG1lc3NhZ2U6IHZhbGlkYXRpb25FcnJvcnNbcHJvcF0uam9pbignXFxuJykgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuICBwcml2YXRlIGZpcnN0Q2hhclRvTG93ZXJDYXNlKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAoc3RyLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHN0cjsgLy8gUmV0dXJuIGFuIGVtcHR5IHN0cmluZyBpZiB0aGUgaW5wdXQgaXMgZW1wdHlcbiAgICB9XG5cbiAgICBjb25zdCBmaXJzdENoYXIgPSBzdHIuY2hhckF0KDApLnRvTG93ZXJDYXNlKCk7XG4gICAgY29uc3QgcmVzdE9mU3RyaW5nID0gc3RyLnNsaWNlKDEpO1xuXG4gICAgcmV0dXJuIGZpcnN0Q2hhciArIHJlc3RPZlN0cmluZztcbiAgfVxuICBhc3luYyBjYW5EZWFjdGl2YXRlKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGlmICghdGhpcy5iYXNlRm9ybS5kaXJ0eSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHZhciByZXN1bHQgPSBhd2FpdCB0aGlzLmRpYWxvZ1NlcnZpY2UuY29uZmlybSh0aGlzLmNvbmZpcm1RdWVzdGlvbiwgbnVsbCwgdGhpcy5jb25maXJtQnV0dG9uKVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgZ2V0RmlsZWROYW1lKGZpbGVkVHJhbnNsYXRpb25LZXk6IHN0cmluZykge1xuICAgIHJldHVybiB7IGZpZWxkOiB0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KGZpbGVkVHJhbnNsYXRpb25LZXkpIH07XG4gIH1cbiAgZ2V0Q3VzdG9tRXJyb3JNZXNzYWdlKGVycm9yOiBhbnksIGZpZWxkTGFiZWw6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuICcnO1xuICB9XG4gIGdldEVycm9yTWVzc2FnZUZyb21BcnJheShhcnJheUluZGV4OiBudW1iZXIsIGZpZWxkOiBzdHJpbmcsIGZpbGVkVHJhbnNsYXRpb25LZXk6IHN0cmluZywgYXJyYXlOYW1lOiBzdHJpbmcgPSAnZm9ybUFycmF5Jyk6IHN0cmluZyB7XG4gICAgY29uc3QgZmllbGRDb250cm9sID0gdGhpcy5iYXNlRm9ybS5nZXQoYXJyYXlOYW1lKS5nZXQoW2FycmF5SW5kZXhdKS5nZXQoZmllbGQpXG4gICAgcmV0dXJuIHRoaXMuZ2V0RXJyb3JNZXNzYWdlRm9yRmllbGQoZmllbGRDb250cm9sLCBmaWxlZFRyYW5zbGF0aW9uS2V5KVxuICB9XG4gIGdldEVycm9yTWVzc2FnZShmaWVsZDogc3RyaW5nLCBmaWxlZFRyYW5zbGF0aW9uS2V5OiBzdHJpbmcsIGZvcm1Hcm91cDogVW50eXBlZEZvcm1Hcm91cCB8IHN0cmluZyA9IG51bGwpOiBzdHJpbmcge1xuICAgIGNvbnN0IGZnID0gdGhpcy5nZXRGcm9tR3JvdXAoZm9ybUdyb3VwKVxuICAgIHJldHVybiB0aGlzLmdldEVycm9yTWVzc2FnZUZvckZpZWxkKGZnLmdldChmaWVsZCksIGZpbGVkVHJhbnNsYXRpb25LZXkpXG4gIH1cbiAgZ2V0RXJyb3JNZXNzYWdlRm9yRmllbGQoZmllbGRDb250cm9sOiBhbnksIGZpbGVkVHJhbnNsYXRpb25LZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgZXJyb3IgPSBmaWVsZENvbnRyb2wuZXJyb3JzO1xuICAgIGNvbnN0IGZpZWxkTGFiZWwgPSB0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KGZpbGVkVHJhbnNsYXRpb25LZXkpO1xuICAgIGxldCBydmFsdWUgPSAnJztcbiAgICBpZiAoZXJyb3IgIT09IG51bGwpIHtcbiAgICAgIGlmIChlcnJvclsncmVxdWlyZWQnXSA9PT0gdHJ1ZSkge1xuICAgICAgICBydmFsdWUgPSB0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KCdHZW5lcmFsLkZpZWxkLlJlcXVpcmVkJywgeyBmaWVsZDogZmllbGRMYWJlbCB9KTtcbiAgICAgIH1cbiAgICAgIGlmIChlcnJvclsnbWlubGVuZ3RoJ10pIHtcbiAgICAgICAgcnZhbHVlID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudCgnR2VuZXJhbC5GaWVsZC5NaW5MZW5ndGgnLCB7IGZpZWxkOiBmaWVsZExhYmVsLCByZXF1aXJlZExlbmd0aDogZXJyb3IubWlubGVuZ3RoLnJlcXVpcmVkTGVuZ3RoIH0pO1xuICAgICAgfVxuICAgICAgaWYgKGVycm9yWydlbWFpbCddID09PSB0cnVlKSB7XG4gICAgICAgIHJ2YWx1ZSA9IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoJ0dlbmVyYWwuRmllbGQuSW52YWxpZEVtYWlsJyk7XG4gICAgICB9XG4gICAgICBpZiAoZXJyb3JbJ3VybCddID09PSB0cnVlKSB7XG4gICAgICAgIHJ2YWx1ZSA9IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoJ0dlbmVyYWwuRmllbGQuSW52YWxpZFVybCcpO1xuICAgICAgfVxuICAgICAgaWYgKGVycm9yWydzZXJ2ZXJFcnJvciddKSB7XG4gICAgICAgIHJ2YWx1ZSA9IGVycm9yWydzZXJ2ZXJFcnJvciddO1xuICAgICAgfVxuICAgICAgaWYgKHJ2YWx1ZSA9PT0gJycpIHtcbiAgICAgICAgcnZhbHVlID0gdGhpcy5nZXRDdXN0b21FcnJvck1lc3NhZ2UoZXJyb3IsIGZpZWxkTGFiZWwpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcnZhbHVlO1xuICB9XG59XG4iLCI8aW9uLWhlYWRlciBbdHJhbnNsdWNlbnRdPVwidHJ1ZVwiPlxuICA8aW9uLXRvb2xiYXI+XG4gICAgPGlvbi1idXR0b25zIHNsb3Q9XCJzdGFydFwiPlxuICAgICAgPGlvbi1tZW51LWJ1dHRvbj48L2lvbi1tZW51LWJ1dHRvbj5cbiAgICAgIDxpb24tYmFjay1idXR0b24+PC9pb24tYmFjay1idXR0b24+XG4gICAgPC9pb24tYnV0dG9ucz5cbiAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImhlYWRlclwiPjwvbmctY29udGFpbmVyPlxuICA8L2lvbi10b29sYmFyPlxuPC9pb24taGVhZGVyPlxuXG48aW9uLWNvbnRlbnQgW2Z1bGxzY3JlZW5dPVwidHJ1ZVwiPlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWlzTG9hZGluZ1wiPlxuICAgIDxmb3JtIFtmb3JtR3JvdXBdPVwiYmFzZUZvcm1cIiAobmdTdWJtaXQpPVwib25TdWJtaXQobW9kZWwpXCI+XG4gICAgICA8Zm9ybWx5LWZvcm0gW2Zvcm1dPVwiYmFzZUZvcm1cIiBbZmllbGRzXT1cImZpZWxkc1wiIFttb2RlbF09XCJtb2RlbFwiIFtvcHRpb25zXT1cIm9wdGlvbnNcIj48L2Zvcm1seS1mb3JtPlxuICAgIDwvZm9ybT5cbiAgPC9uZy1jb250YWluZXI+XG48L2lvbi1jb250ZW50PlxuXG48bmctdGVtcGxhdGUgI2hlYWRlcj5cbiAgPGlvbi10aXRsZSAgY2xhc3M9XCJpb24tdGV4dC1jZW50ZXJcIj57e3RpdGxlIHx0cmFuc2xhdGV9fTwvaW9uLXRpdGxlPlxuICA8aW9uLWJ1dHRvbiAqbmdJZj1cIiFpc0xvYWRpbmdcIiBzbG90PVwiZW5kXCIgZmlsbD1cImNsZWFyXCIgKGNsaWNrKT1cIm9uU2F2ZSgpXCJcbiAgICBbZGlzYWJsZWRdPVwiYmFzZUZvcm0uaW52YWxpZCB8fCAhYmFzZUZvcm0uZGlydHlcIj5cbiAgICA8aW9uLWljb24gc2l6ZT1cImxhcmdlXCIgbmFtZT1cInNhdmVcIj48L2lvbi1pY29uPlxuICA8L2lvbi1idXR0b24+XG48L25nLXRlbXBsYXRlPiJdfQ==