@rosoftlab/ionic 1.0.0-alpha-19 → 1.0.1-alpha-3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. package/fesm2022/rosoftlab-ionic.mjs +41 -43
  2. package/fesm2022/rosoftlab-ionic.mjs.map +1 -1
  3. package/package.json +5 -7
  4. package/esm2022/lib/components/index.mjs +0 -5
  5. package/esm2022/lib/components/rsl-ionic-crud.component/rsl-ionic-crud.component.mjs +0 -266
  6. package/esm2022/lib/components/rsl-ionic-data-table/rsl-ionic-data-table.component.mjs +0 -292
  7. package/esm2022/lib/components/rsl-ionic-grid/rsl-ionic-grid.component.mjs +0 -269
  8. package/esm2022/lib/components/rsl-ionic-sm-buttons/ionic-sm-buttons.component.mjs +0 -65
  9. package/esm2022/lib/decorators/index.mjs +0 -3
  10. package/esm2022/lib/decorators/ionic-datatable-layout.mjs +0 -10
  11. package/esm2022/lib/decorators/ionic-list.decorator.mjs +0 -9
  12. package/esm2022/lib/interfaces/index.mjs +0 -2
  13. package/esm2022/lib/interfaces/ionic-list-layout-config.mjs +0 -2
  14. package/esm2022/lib/ionic-dialog.service.mjs +0 -51
  15. package/esm2022/lib/rsl-ionic-module.module.mjs +0 -96
  16. package/esm2022/lib/translate.extension.mjs +0 -48
  17. package/esm2022/lib/types/index.mjs +0 -2
  18. package/esm2022/lib/types/repeat/repeat-section.type.mjs +0 -135
  19. package/esm2022/lib/types/repeat-datatable/repeat-datatable.component.mjs +0 -190
  20. package/esm2022/lib/validators/index.mjs +0 -2
  21. package/esm2022/lib/validators/must-match.mjs +0 -12
  22. package/esm2022/lib/wrappers/accordion-wrapper.component.mjs +0 -50
  23. package/esm2022/lib/wrappers/index.mjs +0 -3
  24. package/esm2022/lib/wrappers/panel-wrapper.component.mjs +0 -37
  25. package/esm2022/lib/wrappers/wrappers.module.mjs +0 -59
  26. package/esm2022/public-api.mjs +0 -12
  27. package/esm2022/rosoftlab-ionic.mjs +0 -5
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@rosoftlab/ionic",
3
- "version": "1.0.0-alpha-19",
3
+ "version": "1.0.1-alpha-3",
4
4
  "peerDependencies": {
5
- "@angular/common": "^18.2.9",
5
+ "@angular/common": "^19.1.3",
6
6
  "@angular/core": "^18.2.9",
7
7
  "@ngx-formly/core": "^6.3.0",
8
8
  "@ionic/angular": "7.7.1",
9
9
  "@swimlane/ngx-datatable": "^20.1.0",
10
- "@rosoftlab/core": "1.0.0-alpha-19",
11
- "@rosoftlab/formly": "1.0.0-alpha-19",
12
- "@rosoftlab/statemachine": "1.0.0-alpha-19"
10
+ "@rosoftlab/core": "1.0.1-alpha-3",
11
+ "@rosoftlab/formly": "1.0.1-alpha-3",
12
+ "@rosoftlab/statemachine": "1.0.1-alpha-3"
13
13
  },
14
14
  "dependencies": {
15
15
  "tslib": "^2.6.2"
@@ -25,8 +25,6 @@
25
25
  },
26
26
  ".": {
27
27
  "types": "./index.d.ts",
28
- "esm2022": "./esm2022/rosoftlab-ionic.mjs",
29
- "esm": "./esm2022/rosoftlab-ionic.mjs",
30
28
  "default": "./fesm2022/rosoftlab-ionic.mjs"
31
29
  }
32
30
  }
@@ -1,5 +0,0 @@
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
- export { RslIonicSmButtonsComponent } from './rsl-ionic-sm-buttons/ionic-sm-buttons.component';
5
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9yb3NvZnRsYWIvaW9uaWMvc3JjL2xpYi9jb21wb25lbnRzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLHFEQUFxRCxDQUFBO0FBQy9GLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLHVEQUF1RCxDQUFBO0FBQ2xHLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDJDQUEyQyxDQUFBO0FBQ2pGLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLG1EQUFtRCxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgR2VuZXJpY0lvbmljQ3J1ZENvbXBvbmVudCB9IGZyb20gJy4vcnNsLWlvbmljLWNydWQuY29tcG9uZW50L3JzbC1pb25pYy1jcnVkLmNvbXBvbmVudCdcclxuZXhwb3J0IHsgUnNsSW9uaWNEYXRhVGFibGVDb21wb25lbnQgfSBmcm9tIFwiLi9yc2wtaW9uaWMtZGF0YS10YWJsZS9yc2wtaW9uaWMtZGF0YS10YWJsZS5jb21wb25lbnRcIlxyXG5leHBvcnQgeyBSc2xJb25pY0dyaWRDb21wb25lbnQgfSBmcm9tICcuL3JzbC1pb25pYy1ncmlkL3JzbC1pb25pYy1ncmlkLmNvbXBvbmVudCdcclxuZXhwb3J0IHsgUnNsSW9uaWNTbUJ1dHRvbnNDb21wb25lbnQgfSBmcm9tICcuL3JzbC1pb25pYy1zbS1idXR0b25zL2lvbmljLXNtLWJ1dHRvbnMuY29tcG9uZW50J1xyXG4iXX0=
@@ -1,266 +0,0 @@
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: "18.2.9", 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: "18.2.9", type: GenericIonicCrudComponent, isStandalone: true, selector: "rslc-ionic-crud", ngImport: i0, template: "<ion-header [translucent]=\"true\">\r\n <ion-toolbar>\r\n <ion-buttons slot=\"start\">\r\n <ion-menu-button></ion-menu-button>\r\n <ion-back-button></ion-back-button>\r\n </ion-buttons>\r\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\r\n </ion-toolbar>\r\n</ion-header>\r\n\r\n<ion-content [fullscreen]=\"true\">\r\n <ng-container *ngIf=\"!isLoading\">\r\n <form [formGroup]=\"baseForm\" (ngSubmit)=\"onSubmit(model)\">\r\n <formly-form [form]=\"baseForm\" [fields]=\"fields\" [model]=\"model\" [options]=\"options\"></formly-form>\r\n </form>\r\n </ng-container>\r\n</ion-content>\r\n\r\n<ng-template #header>\r\n <ion-title class=\"ion-text-center\">{{title |translate}}</ion-title>\r\n <ion-button *ngIf=\"!isLoading\" slot=\"end\" fill=\"clear\" (click)=\"onSave()\"\r\n [disabled]=\"baseForm.invalid || !baseForm.dirty\">\r\n <ion-icon size=\"large\" name=\"save\"></ion-icon>\r\n </ion-button>\r\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.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: "component", type: i7.IonBackButton, selector: "ion-back-button" }, { 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: "18.2.9", ngImport: i0, type: GenericIonicCrudComponent, decorators: [{
263
- type: Component,
264
- args: [{ standalone: true, selector: 'rslc-ionic-crud', imports: [RslIonicModuleModule], template: "<ion-header [translucent]=\"true\">\r\n <ion-toolbar>\r\n <ion-buttons slot=\"start\">\r\n <ion-menu-button></ion-menu-button>\r\n <ion-back-button></ion-back-button>\r\n </ion-buttons>\r\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\r\n </ion-toolbar>\r\n</ion-header>\r\n\r\n<ion-content [fullscreen]=\"true\">\r\n <ng-container *ngIf=\"!isLoading\">\r\n <form [formGroup]=\"baseForm\" (ngSubmit)=\"onSubmit(model)\">\r\n <formly-form [form]=\"baseForm\" [fields]=\"fields\" [model]=\"model\" [options]=\"options\"></formly-form>\r\n </form>\r\n </ng-container>\r\n</ion-content>\r\n\r\n<ng-template #header>\r\n <ion-title class=\"ion-text-center\">{{title |translate}}</ion-title>\r\n <ion-button *ngIf=\"!isLoading\" slot=\"end\" fill=\"clear\" (click)=\"onSave()\"\r\n [disabled]=\"baseForm.invalid || !baseForm.dirty\">\r\n <ion-icon size=\"large\" name=\"save\"></ion-icon>\r\n </ion-button>\r\n</ng-template>" }]
265
- }], ctorParameters: () => [{ 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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QUM7WUFDRCxJQUFJLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO2dCQUN2QixNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMseUJBQXlCLEVBQUUsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLGNBQWMsRUFBRSxLQUFLLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUM7WUFDcEksQ0FBQztZQUNELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUM1QixNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsNEJBQTRCLENBQUMsQ0FBQztZQUNoRSxDQUFDO1lBQ0QsSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7Z0JBQzFCLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1lBQzlELENBQUM7WUFDRCxJQUFJLEtBQUssQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO2dCQUN6QixNQUFNLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ2hDLENBQUM7WUFDRCxJQUFJLE1BQU0sS0FBSyxFQUFFLEVBQUUsQ0FBQztnQkFDbEIsTUFBTSxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDekQsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDOzhHQXRRVSx5QkFBeUI7a0dBQXpCLHlCQUF5QiwyRUNwQnRDLG05QkF3QmMseUREUEYsb0JBQW9COzsyRkFHbkIseUJBQXlCO2tCQVJyQyxTQUFTO2lDQUNJLElBQUksWUFDTixpQkFBaUIsV0FHbEIsQ0FBQyxvQkFBb0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IExvY2F0aW9uIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHsgQ29tcG9uZW50LCBJbmplY3RvciwgT25Jbml0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFVudHlwZWRGb3JtQnVpbGRlciwgVW50eXBlZEZvcm1Db250cm9sLCBVbnR5cGVkRm9ybUdyb3VwIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcclxuaW1wb3J0IHsgRm9ybWx5RmllbGRDb25maWcsIEZvcm1seUZvcm1PcHRpb25zIH0gZnJvbSAnQG5neC1mb3JtbHkvY29yZSc7XHJcbmltcG9ydCB7IEZvcm1seUpzb25zY2hlbWEgfSBmcm9tICdAbmd4LWZvcm1seS9jb3JlL2pzb24tc2NoZW1hJztcclxuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xyXG5pbXBvcnQgeyBCYXNlTW9kZWxGb3JtbHksIEJhc2VTZXJ2aWNlRm9ybWx5IH0gZnJvbSAnQHJvc29mdGxhYi9mb3JtbHknO1xyXG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XHJcbmltcG9ydCB7IE9ic2VydmFibGUsIGZyb20gfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgSW9uaWNEaWFsb2dTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vaW9uaWMtZGlhbG9nLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBSc2xJb25pY01vZHVsZU1vZHVsZSB9IGZyb20gJy4uLy4uL3JzbC1pb25pYy1tb2R1bGUubW9kdWxlJztcclxuQENvbXBvbmVudCh7XHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBzZWxlY3RvcjogJ3JzbGMtaW9uaWMtY3J1ZCcsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL3JzbC1pb25pYy1jcnVkLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9yc2wtaW9uaWMtY3J1ZC5jb21wb25lbnQuY3NzJ10sXHJcbiAgaW1wb3J0czogW1JzbElvbmljTW9kdWxlTW9kdWxlXVxyXG5cclxufSlcclxuZXhwb3J0IGNsYXNzIEdlbmVyaWNJb25pY0NydWRDb21wb25lbnQ8VCBleHRlbmRzIEJhc2VNb2RlbEZvcm1seSwgVSBleHRlbmRzIEJhc2VTZXJ2aWNlRm9ybWx5PFQ+PiBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcbiAgYmFzZUZvcm06IFVudHlwZWRGb3JtR3JvdXA7XHJcbiAgbW9kZWxJZDogc3RyaW5nO1xyXG4gIG1vZGVsOiBUO1xyXG4gIG9yaWdNb2RlbDogVDtcclxuICBpc0VkaXQ6IGJvb2xlYW47XHJcbiAgaXNMb2FkaW5nID0gdHJ1ZTtcclxuICBjYW5jZWxSb3V0ZTogc3RyaW5nO1xyXG4gIGVkaXRSb3V0ZTogc3RyaW5nO1xyXG4gIG1vZGVsU2VydmljZTogVVxyXG4gIHB1YmxpYyBjaGFuZ2VVcmxSb3V0ZTogYm9vbGVhbiA9IHRydWU7XHJcbiAgcHVibGljIHRpdGxlOiBzdHJpbmc7XHJcbiAgZmllbGRzOiBGb3JtbHlGaWVsZENvbmZpZ1tdXHJcbiAgb3B0aW9uczogRm9ybWx5Rm9ybU9wdGlvbnMgPSB7fTtcclxuICAvLyNyZWdpb24gRGlhbG9nIG1lc3NhZ2VzXHJcbiAgY29uZmlybVF1ZXN0aW9uOiBzdHJpbmdcclxuICBjb25maXJtQnV0dG9uOiBzdHJpbmdcclxuICBzYXZlTWVzc2FnZTogc3RyaW5nXHJcbiAgLy8jZW5kcmVnaW9uXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwdWJsaWMgZmI6IFVudHlwZWRGb3JtQnVpbGRlcixcclxuICAgIHB1YmxpYyByb3V0ZXI6IFJvdXRlcixcclxuICAgIHB1YmxpYyByb3V0ZTogQWN0aXZhdGVkUm91dGUsXHJcbiAgICBwdWJsaWMgZGlhbG9nU2VydmljZTogSW9uaWNEaWFsb2dTZXJ2aWNlLFxyXG4gICAgcHVibGljIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcclxuICAgIHB1YmxpYyBsb2NhdGlvbjogTG9jYXRpb24sXHJcbiAgICBwcml2YXRlIGluamVjdG9yOiBJbmplY3RvcixcclxuICAgIHByaXZhdGUgZm9ybWx5SnNvbnNjaGVtYTogRm9ybWx5SnNvbnNjaGVtYSxcclxuICApIHtcclxuXHJcbiAgICBjb25zdCBTRVJWSUNFX1RPS0VOID0gcm91dGUuc25hcHNob3QuZGF0YVsncmVxdWlyZWRTZXJ2aWNlJ107XHJcbiAgICB0aGlzLm1vZGVsU2VydmljZSA9IHRoaXMuaW5qZWN0b3IuZ2V0PFU+KDxhbnk+U0VSVklDRV9UT0tFTik7XHJcblxyXG4gICAgdGhpcy5tb2RlbFNlcnZpY2UgPSB0aGlzLmluamVjdG9yLmdldDxVPig8YW55PlNFUlZJQ0VfVE9LRU4pO1xyXG4gICAgdGhpcy5jb25maXJtUXVlc3Rpb24gPSB0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KCdHZW5lcmFsLkRpc2NhcmQuUXVlc3Rpb24nKTtcclxuICAgIHRoaXMuY29uZmlybUJ1dHRvbiA9IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoJ0dlbmVyYWwuRGlzY2FyZC5Db25maXJtQnV0dG9uJyk7XHJcbiAgICB0aGlzLnNhdmVNZXNzYWdlID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudCgnR2VuZXJhbC5TYXZlLk1lc3NhZ2UnKTtcclxuICB9XHJcblxyXG4gIGlvblZpZXdXaWxsTGVhdmUoKSB7XHJcbiAgICB0aGlzLm9wdGlvbnMucmVzZXRNb2RlbCgpXHJcbiAgICB0aGlzLmJhc2VGb3JtLnJlc2V0KCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYWZ0ZXJTYXZlKG1vZGVsOiBUKTogT2JzZXJ2YWJsZTxUPiB7XHJcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyKSA9PiB7XHJcbiAgICAgIG9ic2VydmVyLm5leHQobW9kZWwpO1xyXG4gICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYmVmb3JlU2F2ZShtb2RlbDogVCk6IE9ic2VydmFibGU8VD4ge1xyXG4gICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlKChvYnNlcnZlcikgPT4ge1xyXG4gICAgICBvYnNlcnZlci5uZXh0KG1vZGVsKTtcclxuICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICB0aGlzLmluaXRGb3JtKCk7XHJcbiAgfVxyXG4gIGluaXRGb3JtKGN1c3RvbUluY2x1ZGU6IHN0cmluZyA9ICcnLCBuZXdNb2RlbElkOiBzdHJpbmcgPSBudWxsLCBtb2RlbDogVCA9IG51bGwpIHtcclxuICAgIGlmIChtb2RlbCA9PT0gbnVsbCkge1xyXG4gICAgICB0aGlzLm1vZGVsSWQgPSB0aGlzLnJvdXRlLnNuYXBzaG90LnBhcmFtTWFwLmdldCgnaWQnKSA/PyBuZXdNb2RlbElkO1xyXG4gICAgICB0aGlzLmlzRWRpdCA9IGZhbHNlO1xyXG4gICAgICBpZiAodGhpcy5tb2RlbElkKSB7XHJcbiAgICAgICAgdGhpcy5tb2RlbFNlcnZpY2UuZ2V0KHRoaXMubW9kZWxJZCwgY3VzdG9tSW5jbHVkZSkuc3Vic2NyaWJlKCh2YWx1ZTogVCkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5pc0VkaXQgPSB0cnVlO1xyXG4gICAgICAgICAgdGhpcy5nZW5lcmF0ZUZvcm0odmFsdWUpXHJcbiAgICAgICAgfVxyXG4gICAgICAgICk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgaWYgKHRoaXMuY2hhbmdlVXJsUm91dGUpIHtcclxuICAgICAgICAgIGNvbnN0IGFkZFVybCA9IHRoaXMucm91dGVyLmNyZWF0ZVVybFRyZWUoW10pLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgICB0aGlzLmVkaXRSb3V0ZSA9IHRoaXMucm91dGVyLmNyZWF0ZVVybFRyZWUoW2FkZFVybC5yZXBsYWNlKCdhZGQnLCAnZWRpdCcpXSkudG9TdHJpbmcoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gfVxyXG4gICAgICAgIHRoaXMuZ2VuZXJhdGVGb3JtKHRoaXMubW9kZWxTZXJ2aWNlLm5ld01vZGVsKCkpO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLm1vZGVsSWQgPSBtb2RlbC5pZDtcclxuICAgICAgdGhpcy5pc0VkaXQgPSB0cnVlO1xyXG4gICAgICB0aGlzLmdlbmVyYXRlRm9ybShtb2RlbClcclxuICAgIH1cclxuICB9XHJcbiAgZ2VuZXJhdGVGb3JtKG1vZGVsPzogVCkge1xyXG4gICAgdGhpcy5pc0xvYWRpbmcgPSBmYWxzZTtcclxuICAgIHRoaXMubW9kZWxJZCA9IG1vZGVsLmlkO1xyXG4gICAgdGhpcy5tb2RlbCA9IG1vZGVsO1xyXG4gICAgdGhpcy5vcmlnTW9kZWwgPSBfLmNsb25lRGVlcChtb2RlbCk7O1xyXG4gICAgdGhpcy50aXRsZSA9IHRoaXMubW9kZWwubW9kZWxDb25maWcuZm9ybVRpdGxlXHJcbiAgICB0aGlzLmJhc2VGb3JtID0gbmV3IFVudHlwZWRGb3JtR3JvdXAoe30pOy8vPSB0aGlzLm1vZGVsU2VydmljZS50b0Zvcm1Hcm91cCh0aGlzLmZiLCBtb2RlbCk7XHJcbiAgICB0aGlzLmFmdGVyRm9ybUdlbmVyYXRlZCgpO1xyXG4gICAgdGhpcy5maWVsZHMgPSB0aGlzLm1vZGVsU2VydmljZS5nZXRGb3JtbHlGaWVsZHModGhpcy5tb2RlbClcclxuICB9XHJcbiAgcHVibGljIGFmdGVyRm9ybUdlbmVyYXRlZCgpIHtcclxuXHJcbiAgfVxyXG4gIHByaXZhdGUgZ2V0RnJvbUdyb3VwKGZvcm1Hcm91cDogVW50eXBlZEZvcm1Hcm91cCB8IHN0cmluZyA9IG51bGwpOiBVbnR5cGVkRm9ybUdyb3VwIHtcclxuICAgIGlmICghZm9ybUdyb3VwKVxyXG4gICAgICByZXR1cm4gdGhpcy5iYXNlRm9ybTtcclxuICAgIGlmIChmb3JtR3JvdXAgaW5zdGFuY2VvZiBVbnR5cGVkRm9ybUdyb3VwKVxyXG4gICAgICByZXR1cm4gZm9ybUdyb3VwO1xyXG4gICAgcmV0dXJuIHRoaXMuYmFzZUZvcm0uY29udHJvbHNbZm9ybUdyb3VwXSBhcyBVbnR5cGVkRm9ybUdyb3VwO1xyXG4gIH1cclxuICB2YWxpZGF0ZUFsbEZvcm1GaWVsZHMoZm9ybUdyb3VwOiBVbnR5cGVkRm9ybUdyb3VwIHwgc3RyaW5nID0gbnVsbCkge1xyXG4gICAgY29uc3QgZmcgPSB0aGlzLmdldEZyb21Hcm91cChmb3JtR3JvdXApXHJcbiAgICBPYmplY3Qua2V5cyhmZy5jb250cm9scykuZm9yRWFjaChmaWVsZCA9PiB7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKGZpZWxkKTtcclxuICAgICAgY29uc3QgY29udHJvbCA9IGZnLmdldChmaWVsZCk7XHJcbiAgICAgIGlmIChjb250cm9sIGluc3RhbmNlb2YgVW50eXBlZEZvcm1Db250cm9sKSB7XHJcbiAgICAgICAgY29udHJvbC5tYXJrQXNUb3VjaGVkKHsgb25seVNlbGY6IHRydWUgfSk7XHJcbiAgICAgIH0gZWxzZSBpZiAoY29udHJvbCBpbnN0YW5jZW9mIFVudHlwZWRGb3JtR3JvdXApIHtcclxuICAgICAgICB0aGlzLnZhbGlkYXRlQWxsRm9ybUZpZWxkcyhjb250cm9sKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG4gIGlzRmllbGRWYWxpZChmaWVsZDogc3RyaW5nLCBmb3JtR3JvdXA6IFVudHlwZWRGb3JtR3JvdXAgfCBzdHJpbmcgPSBudWxsKSB7XHJcbiAgICBjb25zdCBmZyA9IHRoaXMuZ2V0RnJvbUdyb3VwKGZvcm1Hcm91cClcclxuICAgIGNvbnN0IGZpbGVkQ29udHJvbCA9IGZnLmdldChmaWVsZClcclxuICAgIHJldHVybiAhZmlsZWRDb250cm9sLnZhbGlkICYmIGZpbGVkQ29udHJvbC50b3VjaGVkO1xyXG4gIH1cclxuXHJcbiAgaXNGaWVsZFZhbGlkRnJvbUFycmF5KGFycmF5SW5kZXg6IG51bWJlciwgZmllbGQ6IHN0cmluZywgYXJyYXlOYW1lOiBzdHJpbmcgPSAnZm9ybUFycmF5Jykge1xyXG4gICAgY29uc3QgZmllbGRDb250cm9sID0gdGhpcy5iYXNlRm9ybS5nZXQoYXJyYXlOYW1lKS5nZXQoW2FycmF5SW5kZXhdKS5nZXQoZmllbGQpXHJcbiAgICByZXR1cm4gIWZpZWxkQ29udHJvbC52YWxpZCAmJiBmaWVsZENvbnRyb2wudG91Y2hlZDtcclxuICB9XHJcblxyXG4gIGRpc3BsYXlGaWVsZENzcyhmaWVsZDogc3RyaW5nKSB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAnaGFzLWVycm9yJzogdGhpcy5pc0ZpZWxkVmFsaWQoZmllbGQpLFxyXG4gICAgICAnaGFzLWZlZWRiYWNrJzogdGhpcy5pc0ZpZWxkVmFsaWQoZmllbGQpXHJcbiAgICB9O1xyXG4gIH1cclxuICBvbkNhbmNlbCgpIHtcclxuICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFt0aGlzLmNhbmNlbFJvdXRlXSk7XHJcbiAgfVxyXG4gIG9uU2F2ZSgpIHtcclxuICAgIHRoaXMuc2F2ZU1vZGVsKHRoaXMuYmFzZUZvcm0pXHJcbiAgfVxyXG4gIG9uU3VibWl0KG1vZGVsKSB7XHJcbiAgICB0aGlzLnNhdmVNb2RlbCh0aGlzLmJhc2VGb3JtKVxyXG4gIH1cclxuXHJcbiAgc2F2ZU1vZGVsKGZvcm1Hcm91cDogVW50eXBlZEZvcm1Hcm91cCB8IHN0cmluZyA9IG51bGwpIHtcclxuICAgIGNvbnN0IGZnID0gdGhpcy5nZXRGcm9tR3JvdXAoZm9ybUdyb3VwKVxyXG4gICAgY29uc3QgdGhhdCA9IHRoaXM7XHJcbiAgICBpZiAoZmcpIHtcclxuICAgICAgaWYgKGZnLnZhbGlkKSB7XHJcbiAgICAgICAgdGhpcy5iZWZvcmVTYXZlKHRoaXMubW9kZWwpLnN1YnNjcmliZShfID0+IHtcclxuICAgICAgICAgIHRoaXMubW9kZWxTZXJ2aWNlLnNhdmUodGhpcy5tb2RlbCwgdGhpcy5tb2RlbElkLCB0aGlzLm9yaWdNb2RlbCkuc3Vic2NyaWJlKFxyXG4gICAgICAgICAgICAobmV3TW9kZWw6IFQpID0+IHtcclxuICAgICAgICAgICAgICB0aGlzLm1vZGVsID0gbmV3TW9kZWw7XHJcbiAgICAgICAgICAgICAgdGhpcy5tb2RlbElkID0gbmV3TW9kZWwuaWQ7XHJcbiAgICAgICAgICAgICAgaWYgKHRoaXMuZWRpdFJvdXRlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmlzRWRpdCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jaGFuZ2VVcmxSb3V0ZSkge1xyXG4gICAgICAgICAgICAgICAgICBjb25zdCB1cmwgPSB0aGlzLnJvdXRlci5jcmVhdGVVcmxUcmVlKFt0aGlzLmVkaXRSb3V0ZSwgdGhpcy5tb2RlbElkXSkudG9TdHJpbmcoKTtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5sb2NhdGlvbi5yZXBsYWNlU3RhdGUodXJsKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgdGhpcy5hZnRlclNhdmUobmV3TW9kZWwpLnN1YnNjcmliZSgodmFsOiBUKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBmcm9tKHRoaXMuZGlhbG9nU2VydmljZS5zaG93U2F2ZU1lc3NhZ2UodGhpcy5zYXZlTWVzc2FnZSkpLnN1YnNjcmliZShkID0+IHtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5vcHRpb25zLnVwZGF0ZUluaXRpYWxWYWx1ZSgpXHJcbiAgICAgICAgICAgICAgICAgIGZnLm1hcmtBc1ByaXN0aW5lKCk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgZXJyID0+IHtcclxuICAgICAgICAgICAgICB0aGlzLnNlcnZlckVycm9ycyhlcnIpXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMudmFsaWRhdGVBbGxGb3JtRmllbGRzKGZvcm1Hcm91cCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbiAgc2VydmVyRXJyb3JzKGVycjogYW55KSB7XHJcbiAgICBpZiAoZXJyLmVycm9yKSB7XHJcbiAgICAgIGlmIChlcnIuZXJyb3IuZXJyb3JzKSB7XHJcbiAgICAgICAgY29uc3QgdmFsaWRhdGlvbkVycm9ycyA9IGVyci5lcnJvci5lcnJvcnM7XHJcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsaWRhdGlvbkVycm9ycykpIHtcclxuICAgICAgICAgIHZhbGlkYXRpb25FcnJvcnMuZm9yRWFjaChwcm9wID0+IHtcclxuICAgICAgICAgICAgY29uc3QgZm9ybUNvbnRyb2wgPSB0aGlzLmJhc2VGb3JtLmdldCh0aGlzLmZpcnN0Q2hhclRvTG93ZXJDYXNlKHByb3ApKTtcclxuICAgICAgICAgICAgaWYgKGZvcm1Db250cm9sKSB7XHJcbiAgICAgICAgICAgICAgLy8gYWN0aXZhdGUgdGhlIGVycm9yIG1lc3NhZ2VcclxuICAgICAgICAgICAgICBmb3JtQ29udHJvbC5zZXRFcnJvcnMoe1xyXG4gICAgICAgICAgICAgICAgc2VydmVyRXJyb3I6IHsgbWVzc2FnZTogdmFsaWRhdGlvbkVycm9yc1twcm9wXS5qb2luKCdcXG4nKSB9XHJcbiAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXModmFsaWRhdGlvbkVycm9ycyk7XHJcbiAgICAgICAgICBrZXlzLmZvckVhY2gocHJvcCA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IGZvcm1Db250cm9sID0gdGhpcy5iYXNlRm9ybS5nZXQodGhpcy5maXJzdENoYXJUb0xvd2VyQ2FzZShwcm9wKSk7XHJcbiAgICAgICAgICAgIGlmIChmb3JtQ29udHJvbCkge1xyXG4gICAgICAgICAgICAgIC8vIGFjdGl2YXRlIHRoZSBlcnJvciBtZXNzYWdlXHJcbiAgICAgICAgICAgICAgZm9ybUNvbnRyb2wuc2V0RXJyb3JzKHtcclxuICAgICAgICAgICAgICAgIHNlcnZlckVycm9yOiB7IG1lc3NhZ2U6IHZhbGlkYXRpb25FcnJvcnNbcHJvcF0uam9pbignXFxuJykgfVxyXG4gICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbiAgcHJpdmF0ZSBmaXJzdENoYXJUb0xvd2VyQ2FzZShzdHI6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBpZiAoc3RyLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICByZXR1cm4gc3RyOyAvLyBSZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGlmIHRoZSBpbnB1dCBpcyBlbXB0eVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGZpcnN0Q2hhciA9IHN0ci5jaGFyQXQoMCkudG9Mb3dlckNhc2UoKTtcclxuICAgIGNvbnN0IHJlc3RPZlN0cmluZyA9IHN0ci5zbGljZSgxKTtcclxuXHJcbiAgICByZXR1cm4gZmlyc3RDaGFyICsgcmVzdE9mU3RyaW5nO1xyXG4gIH1cclxuICBhc3luYyBjYW5EZWFjdGl2YXRlKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xyXG4gICAgaWYgKCF0aGlzLmJhc2VGb3JtLmRpcnR5KSB7XHJcbiAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG4gICAgdmFyIHJlc3VsdCA9IGF3YWl0IHRoaXMuZGlhbG9nU2VydmljZS5jb25maXJtKHRoaXMuY29uZmlybVF1ZXN0aW9uLCBudWxsLCB0aGlzLmNvbmZpcm1CdXR0b24pXHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG4gIH1cclxuICBnZXRGaWxlZE5hbWUoZmlsZWRUcmFuc2xhdGlvbktleTogc3RyaW5nKSB7XHJcbiAgICByZXR1cm4geyBmaWVsZDogdGhpcy50cmFuc2xhdGUuaW5zdGFudChmaWxlZFRyYW5zbGF0aW9uS2V5KSB9O1xyXG4gIH1cclxuICBnZXRDdXN0b21FcnJvck1lc3NhZ2UoZXJyb3I6IGFueSwgZmllbGRMYWJlbDogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIHJldHVybiAnJztcclxuICB9XHJcbiAgZ2V0RXJyb3JNZXNzYWdlRnJvbUFycmF5KGFycmF5SW5kZXg6IG51bWJlciwgZmllbGQ6IHN0cmluZywgZmlsZWRUcmFuc2xhdGlvbktleTogc3RyaW5nLCBhcnJheU5hbWU6IHN0cmluZyA9ICdmb3JtQXJyYXknKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGZpZWxkQ29udHJvbCA9IHRoaXMuYmFzZUZvcm0uZ2V0KGFycmF5TmFtZSkuZ2V0KFthcnJheUluZGV4XSkuZ2V0KGZpZWxkKVxyXG4gICAgcmV0dXJuIHRoaXMuZ2V0RXJyb3JNZXNzYWdlRm9yRmllbGQoZmllbGRDb250cm9sLCBmaWxlZFRyYW5zbGF0aW9uS2V5KVxyXG4gIH1cclxuICBnZXRFcnJvck1lc3NhZ2UoZmllbGQ6IHN0cmluZywgZmlsZWRUcmFuc2xhdGlvbktleTogc3RyaW5nLCBmb3JtR3JvdXA6IFVudHlwZWRGb3JtR3JvdXAgfCBzdHJpbmcgPSBudWxsKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGZnID0gdGhpcy5nZXRGcm9tR3JvdXAoZm9ybUdyb3VwKVxyXG4gICAgcmV0dXJuIHRoaXMuZ2V0RXJyb3JNZXNzYWdlRm9yRmllbGQoZmcuZ2V0KGZpZWxkKSwgZmlsZWRUcmFuc2xhdGlvbktleSlcclxuICB9XHJcbiAgZ2V0RXJyb3JNZXNzYWdlRm9yRmllbGQoZmllbGRDb250cm9sOiBhbnksIGZpbGVkVHJhbnNsYXRpb25LZXk6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBlcnJvciA9IGZpZWxkQ29udHJvbC5lcnJvcnM7XHJcbiAgICBjb25zdCBmaWVsZExhYmVsID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudChmaWxlZFRyYW5zbGF0aW9uS2V5KTtcclxuICAgIGxldCBydmFsdWUgPSAnJztcclxuICAgIGlmIChlcnJvciAhPT0gbnVsbCkge1xyXG4gICAgICBpZiAoZXJyb3JbJ3JlcXVpcmVkJ10gPT09IHRydWUpIHtcclxuICAgICAgICBydmFsdWUgPSB0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KCdHZW5lcmFsLkZpZWxkLlJlcXVpcmVkJywgeyBmaWVsZDogZmllbGRMYWJlbCB9KTtcclxuICAgICAgfVxyXG4gICAgICBpZiAoZXJyb3JbJ21pbmxlbmd0aCddKSB7XHJcbiAgICAgICAgcnZhbHVlID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudCgnR2VuZXJhbC5GaWVsZC5NaW5MZW5ndGgnLCB7IGZpZWxkOiBmaWVsZExhYmVsLCByZXF1aXJlZExlbmd0aDogZXJyb3IubWlubGVuZ3RoLnJlcXVpcmVkTGVuZ3RoIH0pO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChlcnJvclsnZW1haWwnXSA9PT0gdHJ1ZSkge1xyXG4gICAgICAgIHJ2YWx1ZSA9IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoJ0dlbmVyYWwuRmllbGQuSW52YWxpZEVtYWlsJyk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGVycm9yWyd1cmwnXSA9PT0gdHJ1ZSkge1xyXG4gICAgICAgIHJ2YWx1ZSA9IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoJ0dlbmVyYWwuRmllbGQuSW52YWxpZFVybCcpO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChlcnJvclsnc2VydmVyRXJyb3InXSkge1xyXG4gICAgICAgIHJ2YWx1ZSA9IGVycm9yWydzZXJ2ZXJFcnJvciddO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChydmFsdWUgPT09ICcnKSB7XHJcbiAgICAgICAgcnZhbHVlID0gdGhpcy5nZXRDdXN0b21FcnJvck1lc3NhZ2UoZXJyb3IsIGZpZWxkTGFiZWwpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcnZhbHVlO1xyXG4gIH1cclxufVxyXG4iLCI8aW9uLWhlYWRlciBbdHJhbnNsdWNlbnRdPVwidHJ1ZVwiPlxyXG4gIDxpb24tdG9vbGJhcj5cclxuICAgIDxpb24tYnV0dG9ucyBzbG90PVwic3RhcnRcIj5cclxuICAgICAgPGlvbi1tZW51LWJ1dHRvbj48L2lvbi1tZW51LWJ1dHRvbj5cclxuICAgICAgPGlvbi1iYWNrLWJ1dHRvbj48L2lvbi1iYWNrLWJ1dHRvbj5cclxuICAgIDwvaW9uLWJ1dHRvbnM+XHJcbiAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImhlYWRlclwiPjwvbmctY29udGFpbmVyPlxyXG4gIDwvaW9uLXRvb2xiYXI+XHJcbjwvaW9uLWhlYWRlcj5cclxuXHJcbjxpb24tY29udGVudCBbZnVsbHNjcmVlbl09XCJ0cnVlXCI+XHJcbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpc0xvYWRpbmdcIj5cclxuICAgIDxmb3JtIFtmb3JtR3JvdXBdPVwiYmFzZUZvcm1cIiAobmdTdWJtaXQpPVwib25TdWJtaXQobW9kZWwpXCI+XHJcbiAgICAgIDxmb3JtbHktZm9ybSBbZm9ybV09XCJiYXNlRm9ybVwiIFtmaWVsZHNdPVwiZmllbGRzXCIgW21vZGVsXT1cIm1vZGVsXCIgW29wdGlvbnNdPVwib3B0aW9uc1wiPjwvZm9ybWx5LWZvcm0+XHJcbiAgICA8L2Zvcm0+XHJcbiAgPC9uZy1jb250YWluZXI+XHJcbjwvaW9uLWNvbnRlbnQ+XHJcblxyXG48bmctdGVtcGxhdGUgI2hlYWRlcj5cclxuICA8aW9uLXRpdGxlICBjbGFzcz1cImlvbi10ZXh0LWNlbnRlclwiPnt7dGl0bGUgfHRyYW5zbGF0ZX19PC9pb24tdGl0bGU+XHJcbiAgPGlvbi1idXR0b24gKm5nSWY9XCIhaXNMb2FkaW5nXCIgc2xvdD1cImVuZFwiIGZpbGw9XCJjbGVhclwiIChjbGljayk9XCJvblNhdmUoKVwiXHJcbiAgICBbZGlzYWJsZWRdPVwiYmFzZUZvcm0uaW52YWxpZCB8fCAhYmFzZUZvcm0uZGlydHlcIj5cclxuICAgIDxpb24taWNvbiBzaXplPVwibGFyZ2VcIiBuYW1lPVwic2F2ZVwiPjwvaW9uLWljb24+XHJcbiAgPC9pb24tYnV0dG9uPlxyXG48L25nLXRlbXBsYXRlPiJdfQ==