@decaf-ts/for-angular 0.0.24 → 0.0.26

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 (78) hide show
  1. package/fesm2022/decaf-ts-for-angular.mjs +1512 -1517
  2. package/fesm2022/decaf-ts-for-angular.mjs.map +1 -1
  3. package/index.d.ts +7470 -3
  4. package/package.json +14 -17
  5. package/components/component-renderer/component-renderer.component.d.ts +0 -278
  6. package/components/crud-field/crud-field.component.d.ts +0 -611
  7. package/components/crud-form/constants.d.ts +0 -5
  8. package/components/crud-form/crud-form.component.d.ts +0 -288
  9. package/components/crud-form/types.d.ts +0 -17
  10. package/components/empty-state/empty-state.component.d.ts +0 -300
  11. package/components/fieldset/fieldset.component.d.ts +0 -555
  12. package/components/filter/filter.component.d.ts +0 -514
  13. package/components/for-angular-components.module.d.ts +0 -20
  14. package/components/index.d.ts +0 -16
  15. package/components/layout/layout.component.d.ts +0 -110
  16. package/components/list/list.component.d.ts +0 -848
  17. package/components/list-item/list-item.component.d.ts +0 -390
  18. package/components/model-renderer/model-renderer.component.d.ts +0 -97
  19. package/components/pagination/constants.d.ts +0 -7
  20. package/components/pagination/pagination.component.d.ts +0 -264
  21. package/components/searchbar/searchbar.component.d.ts +0 -407
  22. package/components/steped-form/steped-form.component.d.ts +0 -243
  23. package/directives/collapsable.directive.d.ts +0 -9
  24. package/directives/index.d.ts +0 -1
  25. package/engine/DynamicModule.d.ts +0 -17
  26. package/engine/NgxBaseComponent.d.ts +0 -541
  27. package/engine/NgxCrudFormField.d.ts +0 -123
  28. package/engine/NgxFormService.d.ts +0 -601
  29. package/engine/NgxRenderingEngine.d.ts +0 -282
  30. package/engine/ValidatorFactory.d.ts +0 -15
  31. package/engine/constants.d.ts +0 -168
  32. package/engine/decorators.d.ts +0 -25
  33. package/engine/index.d.ts +0 -18
  34. package/engine/interfaces.d.ts +0 -271
  35. package/engine/types.d.ts +0 -200
  36. package/esm2022/components/component-renderer/component-renderer.component.mjs +0 -321
  37. package/esm2022/components/crud-field/crud-field.component.mjs +0 -518
  38. package/esm2022/components/crud-form/constants.mjs +0 -14
  39. package/esm2022/components/crud-form/crud-form.component.mjs +0 -259
  40. package/esm2022/components/crud-form/types.mjs +0 -2
  41. package/esm2022/components/empty-state/empty-state.component.mjs +0 -345
  42. package/esm2022/components/fieldset/fieldset.component.mjs +0 -677
  43. package/esm2022/components/filter/filter.component.mjs +0 -700
  44. package/esm2022/components/for-angular-components.module.mjs +0 -84
  45. package/esm2022/components/index.mjs +0 -20
  46. package/esm2022/components/layout/layout.component.mjs +0 -150
  47. package/esm2022/components/list/list.component.mjs +0 -1238
  48. package/esm2022/components/list-item/list-item.component.mjs +0 -405
  49. package/esm2022/components/model-renderer/model-renderer.component.mjs +0 -144
  50. package/esm2022/components/pagination/constants.mjs +0 -2
  51. package/esm2022/components/pagination/pagination.component.mjs +0 -321
  52. package/esm2022/components/searchbar/searchbar.component.mjs +0 -491
  53. package/esm2022/components/steped-form/steped-form.component.mjs +0 -291
  54. package/esm2022/decaf-ts-for-angular.mjs +0 -5
  55. package/esm2022/directives/collapsable.directive.mjs +0 -29
  56. package/esm2022/directives/index.mjs +0 -2
  57. package/esm2022/engine/DynamicModule.mjs +0 -18
  58. package/esm2022/engine/NgxBaseComponent.mjs +0 -541
  59. package/esm2022/engine/NgxCrudFormField.mjs +0 -137
  60. package/esm2022/engine/NgxFormService.mjs +0 -917
  61. package/esm2022/engine/NgxRenderingEngine.mjs +0 -376
  62. package/esm2022/engine/ValidatorFactory.mjs +0 -106
  63. package/esm2022/engine/constants.mjs +0 -170
  64. package/esm2022/engine/decorators.mjs +0 -38
  65. package/esm2022/engine/index.mjs +0 -19
  66. package/esm2022/engine/interfaces.mjs +0 -4
  67. package/esm2022/engine/types.mjs +0 -2
  68. package/esm2022/for-angular-common.module.mjs +0 -84
  69. package/esm2022/helpers/index.mjs +0 -13
  70. package/esm2022/helpers/utils.mjs +0 -436
  71. package/esm2022/i18n/Loader.mjs +0 -86
  72. package/esm2022/i18n/data/en.json +0 -80
  73. package/esm2022/public-apis.mjs +0 -15
  74. package/for-angular-common.module.d.ts +0 -50
  75. package/helpers/index.d.ts +0 -12
  76. package/helpers/utils.d.ts +0 -279
  77. package/i18n/Loader.d.ts +0 -43
  78. package/public-apis.d.ts +0 -14
@@ -1,345 +0,0 @@
1
- import { __decorate, __metadata } from "tslib";
2
- import { Component, inject, Input } from '@angular/core';
3
- import { IonCard, IonCardContent, IonIcon, } from '@ionic/angular/standalone';
4
- import * as allIcons from 'ionicons/icons';
5
- import { addIcons } from 'ionicons';
6
- import { Dynamic } from '../../engine';
7
- import { stringToBoolean } from '../../helpers';
8
- import { NgxBaseComponent } from '../../engine/NgxBaseComponent';
9
- import { DomSanitizer } from '@angular/platform-browser';
10
- import { TranslatePipe, TranslateService } from '@ngx-translate/core';
11
- import { Router } from '@angular/router';
12
- import * as i0 from "@angular/core";
13
- /**
14
- * @description Component for displaying empty state messages with optional actions.
15
- * @summary This component provides a standardized way to display empty state messages
16
- * when no data is available or when a user needs to take an action to populate content.
17
- * It includes customizable title, subtitle, icon, and action button elements that can be
18
- * styled and configured through input properties. The component supports localization
19
- * and can trigger navigation or custom actions when the button is clicked.
20
- *
21
- * @mermaid
22
- * classDiagram
23
- * class EmptyStateComponent {
24
- * +string title
25
- * +string titleColor
26
- * +string subtitle
27
- * +string subtitleColor
28
- * +StringOrBoolean showIcon
29
- * +string icon
30
- * +string iconSize
31
- * +string iconColor
32
- * +string|Function buttonLink
33
- * +string buttonText
34
- * +string buttonFill
35
- * +string buttonColor
36
- * +string buttonSize
37
- * +string searchValue
38
- * -Router Router
39
- * +ngOnInit()
40
- * +handleClick()
41
- * }
42
- * EmptyStateComponent --|> NgxBaseComponent
43
- * EmptyStateComponent --|> OnInit
44
- *
45
- * @extends {NgxBaseComponent}
46
- * @implements {OnInit}
47
- */
48
- let EmptyStateComponent = class EmptyStateComponent extends NgxBaseComponent {
49
- /**
50
- * @description Creates an instance of EmptyStateComponent.
51
- * @summary Initializes a new EmptyStateComponent by calling the parent class constructor
52
- * with the component name for logging and identification purposes. This component provides
53
- * a standardized way to display empty state messages with optional icons and action buttons.
54
- *
55
- * @memberOf EmptyStateComponent
56
- */
57
- constructor() {
58
- super("EmptyStateComponent");
59
- /**
60
- * @description The main title displayed in the empty state.
61
- * @summary Specifies the primary message to show in the empty state component.
62
- * This text is typically used to inform the user about why they're seeing an empty view.
63
- * If translatable is true, this will be processed through the localization system.
64
- *
65
- * @type {string}
66
- * @default "title"
67
- * @memberOf EmptyStateComponent
68
- */
69
- this.title = "title";
70
- /**
71
- * @description The color of the title text.
72
- * @summary Specifies the color for the title text using the application's color system.
73
- * The value should correspond to a color variable defined in the application's theme.
74
- * The component will automatically prefix this with "color-" to create the CSS class.
75
- *
76
- * @type {string}
77
- * @default 'gray-6'
78
- * @memberOf EmptyStateComponent
79
- */
80
- this.titleColor = 'gray-6';
81
- /**
82
- * @description The secondary message displayed in the empty state.
83
- * @summary Provides additional context or instructions below the main title.
84
- * This text is typically used to guide the user on what actions they can take.
85
- * If translatable is true, this will be processed through the localization system.
86
- *
87
- * @type {string | undefined}
88
- * @memberOf EmptyStateComponent
89
- */
90
- this.subtitle = "";
91
- /**
92
- * @description The color of the subtitle text.
93
- * @summary Specifies the color for the subtitle text using the application's color system.
94
- * The value should correspond to a color variable defined in the application's theme.
95
- * The component will automatically prefix this with "color-" to create the CSS class.
96
- *
97
- * @type {string}
98
- * @default 'gray-4'
99
- * @memberOf EmptyStateComponent
100
- */
101
- this.subtitleColor = 'gray-4';
102
- /**
103
- * @description Controls whether the icon is displayed.
104
- * @summary Determines if the visual icon should be shown in the empty state.
105
- * This can be provided as a boolean or a string that will be converted to a boolean.
106
- * Icons help visually communicate the empty state context to users.
107
- *
108
- * @type {StringOrBoolean}
109
- * @default true
110
- * @memberOf EmptyStateComponent
111
- */
112
- this.showIcon = true;
113
- /**
114
- * @description The name of the icon to display.
115
- * @summary Specifies which icon to show when showIcon is true.
116
- * The component uses the icon system defined in the application,
117
- * and this value should correspond to an available icon name.
118
- *
119
- * @type {string}
120
- * @default "ti-info-square-rounded"
121
- * @memberOf EmptyStateComponent
122
- */
123
- this.icon = "ti-info-square-rounded";
124
- /**
125
- * @description The size of the displayed icon.
126
- * @summary Controls the size of the icon shown in the empty state.
127
- * Can be either 'large' or 'small' to accommodate different layout needs.
128
- *
129
- * @type {'large' | 'small' | undefined}
130
- * @default 'large'
131
- * @memberOf EmptyStateComponent
132
- */
133
- this.iconSize = 'large';
134
- /**
135
- * @description The color of the displayed icon.
136
- * @summary Specifies the color for the icon using Ionic's predefined color system.
137
- * This allows the icon to match the application's color scheme.
138
- *
139
- * @type {PredefinedColors | undefined}
140
- * @default 'medium'
141
- * @memberOf EmptyStateComponent
142
- */
143
- this.iconColor = 'medium';
144
- /**
145
- * @description The fill style of the action button.
146
- * @summary Controls the visual style of the button using Ionic's button fill options.
147
- * 'solid' creates a button with a solid background, 'outline' creates a button with
148
- * just a border, and 'clear' creates a button with no background or border.
149
- *
150
- * @type {'clear' | 'solid' | 'outline'}
151
- * @default 'solid'
152
- * @memberOf EmptyStateComponent
153
- */
154
- this.buttonFill = 'solid';
155
- /**
156
- * @description The color of the action button.
157
- * @summary Specifies the color for the button using Ionic's color system.
158
- * This allows the button to match the application's color scheme.
159
- *
160
- * @type {string}
161
- * @default 'primary'
162
- * @memberOf EmptyStateComponent
163
- */
164
- this.buttonColor = 'primary';
165
- /**
166
- * @description The size of the action button.
167
- * @summary Controls the size of the button shown in the empty state.
168
- * Can be 'large', 'small', or 'default' to accommodate different layout needs.
169
- *
170
- * @type {'large' | 'small' | 'default'}
171
- * @default 'default'
172
- * @memberOf EmptyStateComponent
173
- */
174
- this.buttonSize = 'default';
175
- /**
176
- * @description Service for handling navigation operations.
177
- * @summary Injected service that provides methods for navigating between routes.
178
- * This service is used when the buttonLink is a string URL to navigate to that location.
179
- *
180
- * @private
181
- * @type {Router}
182
- * @memberOf EmptyStateComponent
183
- */
184
- this.router = inject(Router);
185
- this.sanitizer = inject(DomSanitizer);
186
- this.translate = inject(TranslateService);
187
- addIcons(allIcons);
188
- }
189
- /**
190
- * @description Initializes the component after Angular first displays the data-bound properties.
191
- * @summary Sets up the component by processing boolean inputs, applying localization to text
192
- * elements if translation is enabled, and formatting CSS classes for title and subtitle colors.
193
- * This method prepares the component for user interaction by ensuring all properties are
194
- * properly initialized and localized.
195
- *
196
- * @mermaid
197
- * sequenceDiagram
198
- * participant A as Angular Lifecycle
199
- * participant E as EmptyStateComponent
200
- *
201
- * A->>E: ngOnInit()
202
- * E->>E: Process translatable flag
203
- * E->>E: Process showIcon flag
204
- * E->>E: Get locale settings
205
- * alt translatable is true
206
- * E->>E: Localize title
207
- * E->>E: Localize subtitle
208
- * E->>E: Localize buttonText
209
- * end
210
- * E->>E: Format title CSS class
211
- * E->>E: Format subtitle CSS class
212
- *
213
- * @return {Promise<void>}
214
- * @memberOf EmptyStateComponent
215
- */
216
- async ngOnInit() {
217
- this.initialize();
218
- this.translatable = stringToBoolean(this.translatable);
219
- this.showIcon = stringToBoolean(this.showIcon);
220
- this.locale = this.getLocale(this.translatable);
221
- // if(this.translatable) {
222
- // this.title = generateLocaleFromString(this.locale, this.title);
223
- // this.subtitle = generateLocaleFromString(this.locale, this.subtitle);
224
- // this.buttonText = generateLocaleFromString(this.locale, this.buttonText);
225
- // }
226
- this.titleColor = `dcf-title color-${this.titleColor}`;
227
- this.subtitleColor = `dcf-subtitle color-${this.titleColor}`;
228
- if (this.searchValue && this.translatable)
229
- this.searchSubtitle = await this.getSearchSubtitle(this.subtitle);
230
- }
231
- /**
232
- * @description Handles click events on the action button.
233
- * @summary This method is triggered when the user clicks the action button in the empty state
234
- * component. It supports three navigation patterns: 1) no action when buttonLink is not provided,
235
- * 2) custom function execution when buttonLink is a function, and 3) navigation to a specific URL
236
- * when buttonLink is a string. This flexibility allows the empty state to trigger various actions
237
- * based on the context in which it's used.
238
- *
239
- * @mermaid
240
- * sequenceDiagram
241
- * participant U as User
242
- * participant E as EmptyStateComponent
243
- * participant N as Router
244
- *
245
- * U->>E: Click action button
246
- * E->>E: handleClick()
247
- * alt buttonLink is not provided
248
- * E-->>U: Return false (no action)
249
- * else buttonLink is a function
250
- * E->>E: Execute buttonLink function
251
- * E-->>U: Return function result
252
- * else buttonLink is a URL string
253
- * E->>N: navigateForward(buttonLink)
254
- * N-->>E: Return navigation result
255
- * E-->>U: Return navigation result
256
- * end
257
- *
258
- * @return {boolean | void | Promise<boolean>}
259
- * - false if no action is taken
260
- * - The result of the buttonLink function if it's a function
261
- * - A Promise resolving to the navigation result if buttonLink is a URL
262
- * @memberOf EmptyStateComponent
263
- */
264
- handleClick() {
265
- const fn = this.buttonLink;
266
- if (!fn)
267
- return false;
268
- if (fn instanceof Function)
269
- return fn();
270
- this.router.navigate([fn]);
271
- }
272
- /**
273
- * @description Generates a localized and sanitized subtitle for search results.
274
- * @summary This method takes a content string, typically the subtitle, and processes it
275
- * through the translation service. It replaces a placeholder ('value0') with the actual
276
- * search value, then sanitizes the result to safely use as HTML. This is particularly
277
- * useful for displaying dynamic, localized messages in the empty state when a search
278
- * yields no results.
279
- *
280
- * @param {string} content - The content string to be translated and processed
281
- * @return {Promise<SafeHtml>} A promise that resolves to a sanitized HTML string
282
- *
283
- * @mermaid
284
- * sequenceDiagram
285
- * participant E as EmptyStateComponent
286
- * participant T as TranslateService
287
- * participant S as DomSanitizer
288
- *
289
- * E->>T: instant(content, {'value0': searchValue})
290
- * T-->>E: Return translated string
291
- * E->>S: bypassSecurityTrustHtml(translatedString)
292
- * S-->>E: Return sanitized SafeHtml
293
- *
294
- * @memberOf EmptyStateComponent
295
- */
296
- async getSearchSubtitle(content) {
297
- const result = await this.translate.instant(content, { 'value0': this.searchValue });
298
- return this.sanitizer.bypassSecurityTrustHtml(result);
299
- }
300
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: EmptyStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
301
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: EmptyStateComponent, isStandalone: true, selector: "ngx-decaf-empty-state", inputs: { title: "title", titleColor: "titleColor", subtitle: "subtitle", subtitleColor: "subtitleColor", showIcon: "showIcon", icon: "icon", iconSize: "iconSize", iconColor: "iconColor", buttonLink: "buttonLink", buttonText: "buttonText", buttonFill: "buttonFill", buttonColor: "buttonColor", buttonSize: "buttonSize", searchValue: "searchValue" }, usesInheritance: true, ngImport: i0, template: "\n<ion-card [id]=\"uid\" [class]=\"className\">\n <ion-card-content>\n @if(icon && showIcon) {\n <div class=\"dcf-icon-container\">\n <ion-icon\n name=\"alert-circle-outline\"\n size=\"large\"\n color=\"danger\"\n />\n </div>\n }\n @if(title) {\n <h5 [class]=\"titleColor\" [innerHTML]=\"title\"></h5>\n }\n @if(subtitle) {\n @if(!searchValue) {\n <p [class]=\"subtitleColor\" [innerHTML]=\"subtitle\"></p>\n } @else {\n <p [class]=\"subtitleColor\" [innerHTML]=\"searchSubtitle\"></p>\n }\n }\n @if(buttonLink && buttonText) {\n <div>\n <ion-button\n [size]=\"buttonSize\"\n [fill]=\"buttonFill\"\n [color]=\"buttonColor\"\n (click)=\"handleClick()\">\n {{ buttonText }}\n </ion-button>\n </div>\n }\n </ion-card-content>\n</ion-card>\n", styles: ["ion-card{text-align:center}ion-card ion-button{margin-top:.75rem}ion-card ion-icon{font-size:2.5rem}ion-card .dcf-icon-container{transform:scale(1.25);opacity:.75;margin-top:1.25rem!important;margin-bottom:.5rem!important}ion-card .dcf-ititle{font-weight:600!important;color:var(--dcf-color-gray-6)!important}ion-card .dcf-isubtitle{font-weight:500!important}\n"], dependencies: [{ kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
302
- };
303
- EmptyStateComponent = __decorate([
304
- Dynamic(),
305
- __metadata("design:paramtypes", [])
306
- ], EmptyStateComponent);
307
- export { EmptyStateComponent };
308
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: EmptyStateComponent, decorators: [{
309
- type: Component,
310
- args: [{ selector: 'ngx-decaf-empty-state', standalone: true, imports: [
311
- TranslatePipe,
312
- IonCard,
313
- IonCardContent,
314
- IonIcon
315
- ], template: "\n<ion-card [id]=\"uid\" [class]=\"className\">\n <ion-card-content>\n @if(icon && showIcon) {\n <div class=\"dcf-icon-container\">\n <ion-icon\n name=\"alert-circle-outline\"\n size=\"large\"\n color=\"danger\"\n />\n </div>\n }\n @if(title) {\n <h5 [class]=\"titleColor\" [innerHTML]=\"title\"></h5>\n }\n @if(subtitle) {\n @if(!searchValue) {\n <p [class]=\"subtitleColor\" [innerHTML]=\"subtitle\"></p>\n } @else {\n <p [class]=\"subtitleColor\" [innerHTML]=\"searchSubtitle\"></p>\n }\n }\n @if(buttonLink && buttonText) {\n <div>\n <ion-button\n [size]=\"buttonSize\"\n [fill]=\"buttonFill\"\n [color]=\"buttonColor\"\n (click)=\"handleClick()\">\n {{ buttonText }}\n </ion-button>\n </div>\n }\n </ion-card-content>\n</ion-card>\n", styles: ["ion-card{text-align:center}ion-card ion-button{margin-top:.75rem}ion-card ion-icon{font-size:2.5rem}ion-card .dcf-icon-container{transform:scale(1.25);opacity:.75;margin-top:1.25rem!important;margin-bottom:.5rem!important}ion-card .dcf-ititle{font-weight:600!important;color:var(--dcf-color-gray-6)!important}ion-card .dcf-isubtitle{font-weight:500!important}\n"] }]
316
- }], ctorParameters: () => [], propDecorators: { title: [{
317
- type: Input
318
- }], titleColor: [{
319
- type: Input
320
- }], subtitle: [{
321
- type: Input
322
- }], subtitleColor: [{
323
- type: Input
324
- }], showIcon: [{
325
- type: Input
326
- }], icon: [{
327
- type: Input
328
- }], iconSize: [{
329
- type: Input
330
- }], iconColor: [{
331
- type: Input
332
- }], buttonLink: [{
333
- type: Input
334
- }], buttonText: [{
335
- type: Input
336
- }], buttonFill: [{
337
- type: Input
338
- }], buttonColor: [{
339
- type: Input
340
- }], buttonSize: [{
341
- type: Input
342
- }], searchValue: [{
343
- type: Input
344
- }] } });
345
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW1wdHktc3RhdGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL2VtcHR5LXN0YXRlL2VtcHR5LXN0YXRlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9lbXB0eS1zdGF0ZS9lbXB0eS1zdGF0ZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFXLE1BQU0sZUFBZSxDQUFDO0FBQ2xFLE9BQU8sRUFDTCxPQUFPLEVBQ1AsY0FBYyxFQUNkLE9BQU8sR0FDUixNQUNJLDJCQUEyQixDQUFDO0FBQ2pDLE9BQU8sS0FBSyxRQUFRLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0MsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUNwQyxPQUFPLEVBQUUsT0FBTyxFQUFtQixNQUFNLGNBQWMsQ0FBQztBQUN4RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2hELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxZQUFZLEVBQVksTUFBTSwyQkFBMkIsQ0FBQztBQUNuRSxPQUFPLEVBQUUsYUFBYSxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFdEUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDOztBQUd6Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtDRztBQWVJLElBQU0sbUJBQW1CLEdBQXpCLE1BQU0sbUJBQW9CLFNBQVEsZ0JBQWdCO0lBa012RDs7Ozs7OztPQU9HO0lBQ0g7UUFDRSxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQztRQXpNL0I7Ozs7Ozs7OztXQVNHO1FBRUgsVUFBSyxHQUFX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LCtFQUNkLE9BQU87O0FBSUUsbUJBQW1CO0lBZC9CLE9BQU8sRUFBRTs7R0FjRyxtQkFBbUIsQ0FvVS9COzs0RkFwVVksbUJBQW1CO2tCQWIvQixTQUFTOytCQUNFLHVCQUF1QixjQUdyQixJQUFJLFdBQ1A7d0JBQ1AsYUFBYTt3QkFDYixPQUFPO3dCQUNQLGNBQWM7d0JBQ2QsT0FBTztxQkFDUjt3REFnQkQsS0FBSztzQkFESixLQUFLO2dCQWNOLFVBQVU7c0JBRFQsS0FBSztnQkFhTixRQUFRO3NCQURQLEtBQUs7Z0JBY04sYUFBYTtzQkFEWixLQUFLO2dCQWNOLFFBQVE7c0JBRFAsS0FBSztnQkFjTixJQUFJO3NCQURILEtBQUs7Z0JBYU4sUUFBUTtzQkFEUCxLQUFLO2dCQWFOLFNBQVM7c0JBRFIsS0FBSztnQkFhTixVQUFVO3NCQURULEtBQUs7Z0JBYU4sVUFBVTtzQkFEVCxLQUFLO2dCQWNOLFVBQVU7c0JBRFQsS0FBSztnQkFhTixXQUFXO3NCQURWLEtBQUs7Z0JBYU4sVUFBVTtzQkFEVCxLQUFLO2dCQWFOLFdBQVc7c0JBRFYsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgaW5qZWN0LCBJbnB1dCwgT25Jbml0ICB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgSW9uQ2FyZCxcbiAgSW9uQ2FyZENvbnRlbnQsXG4gIElvbkljb24sXG59XG5mcm9tICdAaW9uaWMvYW5ndWxhci9zdGFuZGFsb25lJztcbmltcG9ydCAqIGFzIGFsbEljb25zIGZyb20gJ2lvbmljb25zL2ljb25zJztcbmltcG9ydCB7IGFkZEljb25zIH0gZnJvbSAnaW9uaWNvbnMnO1xuaW1wb3J0IHsgRHluYW1pYywgU3RyaW5nT3JCb29sZWFuIH0gZnJvbSAnLi4vLi4vZW5naW5lJztcbmltcG9ydCB7IHN0cmluZ1RvQm9vbGVhbiB9IGZyb20gJy4uLy4uL2hlbHBlcnMnO1xuaW1wb3J0IHsgTmd4QmFzZUNvbXBvbmVudCB9IGZyb20gJy4uLy4uL2VuZ2luZS9OZ3hCYXNlQ29tcG9uZW50JztcbmltcG9ydCB7IERvbVNhbml0aXplciwgU2FmZUh0bWwgfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyJztcbmltcG9ydCB7IFRyYW5zbGF0ZVBpcGUsIFRyYW5zbGF0ZVNlcnZpY2UgfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcbmltcG9ydCB7IEZ1bmN0aW9uTGlrZSB9IGZyb20gJy4uLy4uL2VuZ2luZS90eXBlcyc7XG5pbXBvcnQgeyBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuXG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvbXBvbmVudCBmb3IgZGlzcGxheWluZyBlbXB0eSBzdGF0ZSBtZXNzYWdlcyB3aXRoIG9wdGlvbmFsIGFjdGlvbnMuXG4gKiBAc3VtbWFyeSBUaGlzIGNvbXBvbmVudCBwcm92aWRlcyBhIHN0YW5kYXJkaXplZCB3YXkgdG8gZGlzcGxheSBlbXB0eSBzdGF0ZSBtZXNzYWdlc1xuICogd2hlbiBubyBkYXRhIGlzIGF2YWlsYWJsZSBvciB3aGVuIGEgdXNlciBuZWVkcyB0byB0YWtlIGFuIGFjdGlvbiB0byBwb3B1bGF0ZSBjb250ZW50LlxuICogSXQgaW5jbHVkZXMgY3VzdG9taXphYmxlIHRpdGxlLCBzdWJ0aXRsZSwgaWNvbiwgYW5kIGFjdGlvbiBidXR0b24gZWxlbWVudHMgdGhhdCBjYW4gYmVcbiAqIHN0eWxlZCBhbmQgY29uZmlndXJlZCB0aHJvdWdoIGlucHV0IHByb3BlcnRpZXMuIFRoZSBjb21wb25lbnQgc3VwcG9ydHMgbG9jYWxpemF0aW9uXG4gKiBhbmQgY2FuIHRyaWdnZXIgbmF2aWdhdGlvbiBvciBjdXN0b20gYWN0aW9ucyB3aGVuIHRoZSBidXR0b24gaXMgY2xpY2tlZC5cbiAqXG4gKiBAbWVybWFpZFxuICogY2xhc3NEaWFncmFtXG4gKiAgIGNsYXNzIEVtcHR5U3RhdGVDb21wb25lbnQge1xuICogICAgICtzdHJpbmcgdGl0bGVcbiAqICAgICArc3RyaW5nIHRpdGxlQ29sb3JcbiAqICAgICArc3RyaW5nIHN1YnRpdGxlXG4gKiAgICAgK3N0cmluZyBzdWJ0aXRsZUNvbG9yXG4gKiAgICAgK1N0cmluZ09yQm9vbGVhbiBzaG93SWNvblxuICogICAgICtzdHJpbmcgaWNvblxuICogICAgICtzdHJpbmcgaWNvblNpemVcbiAqICAgICArc3RyaW5nIGljb25Db2xvclxuICogICAgICtzdHJpbmd8RnVuY3Rpb24gYnV0dG9uTGlua1xuICogICAgICtzdHJpbmcgYnV0dG9uVGV4dFxuICogICAgICtzdHJpbmcgYnV0dG9uRmlsbFxuICogICAgICtzdHJpbmcgYnV0dG9uQ29sb3JcbiAqICAgICArc3RyaW5nIGJ1dHRvblNpemVcbiAqICAgICArc3RyaW5nIHNlYXJjaFZhbHVlXG4gKiAgICAgLVJvdXRlciBSb3V0ZXJcbiAqICAgICArbmdPbkluaXQoKVxuICogICAgICtoYW5kbGVDbGljaygpXG4gKiAgIH1cbiAqICAgRW1wdHlTdGF0ZUNvbXBvbmVudCAtLXw+IE5neEJhc2VDb21wb25lbnRcbiAqICAgRW1wdHlTdGF0ZUNvbXBvbmVudCAtLXw+IE9uSW5pdFxuICpcbiAqIEBleHRlbmRzIHtOZ3hCYXNlQ29tcG9uZW50fVxuICogQGltcGxlbWVudHMge09uSW5pdH1cbiAqL1xuQER5bmFtaWMoKVxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWRlY2FmLWVtcHR5LXN0YXRlJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2VtcHR5LXN0YXRlLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vZW1wdHktc3RhdGUuY29tcG9uZW50LnNjc3MnXSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIFRyYW5zbGF0ZVBpcGUsXG4gICAgSW9uQ2FyZCxcbiAgICBJb25DYXJkQ29udGVudCxcbiAgICBJb25JY29uXG4gIF1cblxufSlcbmV4cG9ydCBjbGFzcyBFbXB0eVN0YXRlQ29tcG9uZW50IGV4dGVuZHMgTmd4QmFzZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbWFpbiB0aXRsZSBkaXNwbGF5ZWQgaW4gdGhlIGVtcHR5IHN0YXRlLlxuICAgKiBAc3VtbWFyeSBTcGVjaWZpZXMgdGhlIHByaW1hcnkgbWVzc2FnZSB0byBzaG93IGluIHRoZSBlbXB0eSBzdGF0ZSBjb21wb25lbnQuXG4gICAqIFRoaXMgdGV4dCBpcyB0eXBpY2FsbHkgdXNlZCB0byBpbmZvcm0gdGhlIHVzZXIgYWJvdXQgd2h5IHRoZXkncmUgc2VlaW5nIGFuIGVtcHR5IHZpZXcuXG4gICAqIElmIHRyYW5zbGF0YWJsZSBpcyB0cnVlLCB0aGlzIHdpbGwgYmUgcHJvY2Vzc2VkIHRocm91Z2ggdGhlIGxvY2FsaXphdGlvbiBzeXN0ZW0uXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBkZWZhdWx0IFwidGl0bGVcIlxuICAgKiBAbWVtYmVyT2YgRW1wdHlTdGF0ZUNvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgdGl0bGU6IHN0cmluZyA9IFwidGl0bGVcIjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBjb2xvciBvZiB0aGUgdGl0bGUgdGV4dC5cbiAgICogQHN1bW1hcnkgU3BlY2lmaWVzIHRoZSBjb2xvciBmb3IgdGhlIHRpdGxlIHRleHQgdXNpbmcgdGhlIGFwcGxpY2F0aW9uJ3MgY29sb3Igc3lzdGVtLlxuICAgKiBUaGUgdmFsdWUgc2hvdWxkIGNvcnJlc3BvbmQgdG8gYSBjb2xvciB2YXJpYWJsZSBkZWZpbmVkIGluIHRoZSBhcHBsaWNhdGlvbidzIHRoZW1lLlxuICAgKiBUaGUgY29tcG9uZW50IHdpbGwgYXV0b21hdGljYWxseSBwcmVmaXggdGhpcyB3aXRoIFwiY29sb3ItXCIgdG8gY3JlYXRlIHRoZSBDU1MgY2xhc3MuXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqIEBkZWZhdWx0ICdncmF5LTYnXG4gICAqIEBtZW1iZXJPZiBFbXB0eVN0YXRlQ29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICB0aXRsZUNvbG9yID0gJ2dyYXktNic7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgc2Vjb25kYXJ5IG1lc3NhZ2UgZGlzcGxheWVkIGluIHRoZSBlbXB0eSBzdGF0ZS5cbiAgICogQHN1bW1hcnkgUHJvdmlkZXMgYWRkaXRpb25hbCBjb250ZXh0IG9yIGluc3RydWN0aW9ucyBiZWxvdyB0aGUgbWFpbiB0aXRsZS5cbiAgICogVGhpcyB0ZXh0IGlzIHR5cGljYWxseSB1c2VkIHRvIGd1aWRlIHRoZSB1c2VyIG9uIHdoYXQgYWN0aW9ucyB0aGV5IGNhbiB0YWtlLlxuICAgKiBJZiB0cmFuc2xhdGFibGUgaXMgdHJ1ZSwgdGhpcyB3aWxsIGJlIHByb2Nlc3NlZCB0aHJvdWdoIHRoZSBsb2NhbGl6YXRpb24gc3lzdGVtLlxuICAgKlxuICAgKiBAdHlwZSB7c3RyaW5nIHwgdW5kZWZpbmVkfVxuICAgKiBAbWVtYmVyT2YgRW1wdHlTdGF0ZUNvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgc3VidGl0bGU6IHN0cmluZyA9IFwiXCI7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgY29sb3Igb2YgdGhlIHN1YnRpdGxlIHRleHQuXG4gICAqIEBzdW1tYXJ5IFNwZWNpZmllcyB0aGUgY29sb3IgZm9yIHRoZSBzdWJ0aXRsZSB0ZXh0IHVzaW5nIHRoZSBhcHBsaWNhdGlvbidzIGNvbG9yIHN5c3RlbS5cbiAgICogVGhlIHZhbHVlIHNob3VsZCBjb3JyZXNwb25kIHRvIGEgY29sb3IgdmFyaWFibGUgZGVmaW5lZCBpbiB0aGUgYXBwbGljYXRpb24ncyB0aGVtZS5cbiAgICogVGhlIGNvbXBvbmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgcHJlZml4IHRoaXMgd2l0aCBcImNvbG9yLVwiIHRvIGNyZWF0ZSB0aGUgQ1NTIGNsYXNzLlxuICAgKlxuICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgKiBAZGVmYXVsdCAnZ3JheS00J1xuICAgKiBAbWVtYmVyT2YgRW1wdHlTdGF0ZUNvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgc3VidGl0bGVDb2xvcjogc3RyaW5nID0gJ2dyYXktNCc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDb250cm9scyB3aGV0aGVyIHRoZSBpY29uIGlzIGRpc3BsYXllZC5cbiAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyBpZiB0aGUgdmlzdWFsIGljb24gc2hvdWxkIGJlIHNob3duIGluIHRoZSBlbXB0eSBzdGF0ZS5cbiAgICogVGhpcyBjYW4gYmUgcHJvdmlkZWQgYXMgYSBib29sZWFuIG9yIGEgc3RyaW5nIHRoYXQgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gYSBib29sZWFuLlxuICAgKiBJY29ucyBoZWxwIHZpc3VhbGx5IGNvbW11bmljYXRlIHRoZSBlbXB0eSBzdGF0ZSBjb250ZXh0IHRvIHVzZXJzLlxuICAgKlxuICAgKiBAdHlwZSB7U3RyaW5nT3JCb29sZWFufVxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqIEBtZW1iZXJPZiBFbXB0eVN0YXRlQ29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBzaG93SWNvbjogU3RyaW5nT3JCb29sZWFuID0gdHJ1ZTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBuYW1lIG9mIHRoZSBpY29uIHRvIGRpc3BsYXkuXG4gICAqIEBzdW1tYXJ5IFNwZWNpZmllcyB3aGljaCBpY29uIHRvIHNob3cgd2hlbiBzaG93SWNvbiBpcyB0cnVlLlxuICAgKiBUaGUgY29tcG9uZW50IHVzZXMgdGhlIGljb24gc3lzdGVtIGRlZmluZWQgaW4gdGhlIGFwcGxpY2F0aW9uLFxuICAgKiBhbmQgdGhpcyB2YWx1ZSBzaG91bGQgY29ycmVzcG9uZCB0byBhbiBhdmFpbGFibGUgaWNvbiBuYW1lLlxuICAgKlxuICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgKiBAZGVmYXVsdCBcInRpLWluZm8tc3F1YXJlLXJvdW5kZWRcIlxuICAgKiBAbWVtYmVyT2YgRW1wdHlTdGF0ZUNvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgaWNvbjogc3RyaW5nID0gXCJ0aS1pbmZvLXNxdWFyZS1yb3VuZGVkXCI7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgc2l6ZSBvZiB0aGUgZGlzcGxheWVkIGljb24uXG4gICAqIEBzdW1tYXJ5IENvbnRyb2xzIHRoZSBzaXplIG9mIHRoZSBpY29uIHNob3duIGluIHRoZSBlbXB0eSBzdGF0ZS5cbiAgICogQ2FuIGJlIGVpdGhlciAnbGFyZ2UnIG9yICdzbWFsbCcgdG8gYWNjb21tb2RhdGUgZGlmZmVyZW50IGxheW91dCBuZWVkcy5cbiAgICpcbiAgICogQHR5cGUgeydsYXJnZScgfCAnc21hbGwnIHwgdW5kZWZpbmVkfVxuICAgKiBAZGVmYXVsdCAnbGFyZ2UnXG4gICAqIEBtZW1iZXJPZiBFbXB0eVN0YXRlQ29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBpY29uU2l6ZT86ICdsYXJnZScgfCAnc21hbGwnID0gJ2xhcmdlJztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBjb2xvciBvZiB0aGUgZGlzcGxheWVkIGljb24uXG4gICAqIEBzdW1tYXJ5IFNwZWNpZmllcyB0aGUgY29sb3IgZm9yIHRoZSBpY29uIHVzaW5nIElvbmljJ3MgcHJlZGVmaW5lZCBjb2xvciBzeXN0ZW0uXG4gICAqIFRoaXMgYWxsb3dzIHRoZSBpY29uIHRvIG1hdGNoIHRoZSBhcHBsaWNhdGlvbidzIGNvbG9yIHNjaGVtZS5cbiAgICpcbiAgICogQHR5cGUge1ByZWRlZmluZWRDb2xvcnMgfCB1bmRlZmluZWR9XG4gICAqIEBkZWZhdWx0ICdtZWRpdW0nXG4gICAqIEBtZW1iZXJPZiBFbXB0eVN0YXRlQ29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBpY29uQ29sb3I/OiBzdHJpbmcgPSAnbWVkaXVtJztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBuYXZpZ2F0aW9uIHRhcmdldCBvciBhY3Rpb24gZm9yIHRoZSBidXR0b24uXG4gICAqIEBzdW1tYXJ5IFNwZWNpZmllcyB3aGVyZSB0aGUgYnV0dG9uIHNob3VsZCBuYXZpZ2F0ZSB0byB3aGVuIGNsaWNrZWQgb3Igd2hhdCBmdW5jdGlvblxuICAgKiBpdCBzaG91bGQgZXhlY3V0ZS4gVGhpcyBjYW4gYmUgZWl0aGVyIGEgVVJMIHN0cmluZyBvciBhIGZ1bmN0aW9uIHRoYXQgaGFuZGxlcyBuYXZpZ2F0aW9uLlxuICAgKiBXaGVuIG5vdCBwcm92aWRlZCwgdGhlIGJ1dHRvbiB3aWxsIG5vdCBwZXJmb3JtIGFueSBhY3Rpb24uXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmcgfCBGdW5jdGlvbkxpa2UgfCB1bmRlZmluZWR9XG4gICAqIEBtZW1iZXJPZiBFbXB0eVN0YXRlQ29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBidXR0b25MaW5rPzogc3RyaW5nIHwgRnVuY3Rpb25MaWtlO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHRleHQgZGlzcGxheWVkIG9uIHRoZSBhY3Rpb24gYnV0dG9uLlxuICAgKiBAc3VtbWFyeSBTcGVjaWZpZXMgdGhlIGxhYmVsIGZvciB0aGUgYWN0aW9uIGJ1dHRvbiBpbiB0aGUgZW1wdHkgc3RhdGUuXG4gICAqIElmIHRyYW5zbGF0YWJsZSBpcyB0cnVlLCB0aGlzIHdpbGwgYmUgcHJvY2Vzc2VkIHRocm91Z2ggdGhlIGxvY2FsaXphdGlvbiBzeXN0ZW0uXG4gICAqIElmIG5vdCBwcm92aWRlZCwgdGhlIGJ1dHRvbiB3aWxsIG5vdCBkaXNwbGF5IGFueSB0ZXh0LlxuICAgKlxuICAgKiBAdHlwZSB7c3RyaW5nIHwgdW5kZWZpbmVkfVxuICAgKiBAbWVtYmVyT2YgRW1wdHlTdGF0ZUNvbXBvbmVudFxuICAgKi9cbiAgQElucHV0KClcbiAgYnV0dG9uVGV4dD86IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBmaWxsIHN0eWxlIG9mIHRoZSBhY3Rpb24gYnV0dG9uLlxuICAgKiBAc3VtbWFyeSBDb250cm9scyB0aGUgdmlzdWFsIHN0eWxlIG9mIHRoZSBidXR0b24gdXNpbmcgSW9uaWMncyBidXR0b24gZmlsbCBvcHRpb25zLlxuICAgKiAnc29saWQnIGNyZWF0ZXMgYSBidXR0b24gd2l0aCBhIHNvbGlkIGJhY2tncm91bmQsICdvdXRsaW5lJyBjcmVhdGVzIGEgYnV0dG9uIHdpdGhcbiAgICoganVzdCBhIGJvcmRlciwgYW5kICdjbGVhcicgY3JlYXRlcyBhIGJ1dHRvbiB3aXRoIG5vIGJhY2tncm91bmQgb3IgYm9yZGVyLlxuICAgKlxuICAgKiBAdHlwZSB7J2NsZWFyJyB8ICdzb2xpZCcgfCAnb3V0bGluZSd9XG4gICAqIEBkZWZhdWx0ICdzb2xpZCdcbiAgICogQG1lbWJlck9mIEVtcHR5U3RhdGVDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIGJ1dHRvbkZpbGw6ICdjbGVhcicgfCAnc29saWQnIHwgJ291dGxpbmUnID0gICdzb2xpZCc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgY29sb3Igb2YgdGhlIGFjdGlvbiBidXR0b24uXG4gICAqIEBzdW1tYXJ5IFNwZWNpZmllcyB0aGUgY29sb3IgZm9yIHRoZSBidXR0b24gdXNpbmcgSW9uaWMncyBjb2xvciBzeXN0ZW0uXG4gICAqIFRoaXMgYWxsb3dzIHRoZSBidXR0b24gdG8gbWF0Y2ggdGhlIGFwcGxpY2F0aW9uJ3MgY29sb3Igc2NoZW1lLlxuICAgKlxuICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgKiBAZGVmYXVsdCAncHJpbWFyeSdcbiAgICogQG1lbWJlck9mIEVtcHR5U3RhdGVDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIGJ1dHRvbkNvbG9yOiBzdHJpbmcgPSAgJ3ByaW1hcnknO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHNpemUgb2YgdGhlIGFjdGlvbiBidXR0b24uXG4gICAqIEBzdW1tYXJ5IENvbnRyb2xzIHRoZSBzaXplIG9mIHRoZSBidXR0b24gc2hvd24gaW4gdGhlIGVtcHR5IHN0YXRlLlxuICAgKiBDYW4gYmUgJ2xhcmdlJywgJ3NtYWxsJywgb3IgJ2RlZmF1bHQnIHRvIGFjY29tbW9kYXRlIGRpZmZlcmVudCBsYXlvdXQgbmVlZHMuXG4gICAqXG4gICAqIEB0eXBlIHsnbGFyZ2UnIHwgJ3NtYWxsJyB8ICdkZWZhdWx0J31cbiAgICogQGRlZmF1bHQgJ2RlZmF1bHQnXG4gICAqIEBtZW1iZXJPZiBFbXB0eVN0YXRlQ29tcG9uZW50XG4gICAqL1xuICBASW5wdXQoKVxuICBidXR0b25TaXplOiAnbGFyZ2UnIHwgJ3NtYWxsJyB8ICdkZWZhdWx0JyA9ICAnZGVmYXVsdCc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgc2VhcmNoIHZhbHVlIHRoYXQgcmVzdWx0ZWQgaW4gbm8gcmVzdWx0cy5cbiAgICogQHN1bW1hcnkgV2hlbiB0aGUgZW1wdHkgc3RhdGUgaXMgc2hvd24gZHVlIHRvIGEgc2VhcmNoIHdpdGggbm8gcmVzdWx0cyxcbiAgICogdGhpcyBwcm9wZXJ0eSBjYW4gaG9sZCB0aGUgc2VhcmNoIHRlcm0gdGhhdCB3YXMgdXNlZC4gVGhpcyBjYW4gYmUgZGlzcGxheWVkXG4gICAqIGluIHRoZSBlbXB0eSBzdGF0ZSBtZXNzYWdlIHRvIHByb3ZpZGUgY29udGV4dCB0byB0aGUgdXNlci5cbiAgICpcbiAgICogQHR5cGUge3N0cmluZ31cbiAgICogQG1lbWJlck9mIEVtcHR5U3RhdGVDb21wb25lbnRcbiAgICovXG4gIEBJbnB1dCgpXG4gIHNlYXJjaFZhbHVlITogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2VydmljZSBmb3IgaGFuZGxpbmcgbmF2aWdhdGlvbiBvcGVyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBJbmplY3RlZCBzZXJ2aWNlIHRoYXQgcHJvdmlkZXMgbWV0aG9kcyBmb3IgbmF2aWdhdGluZyBiZXR3ZWVuIHJvdXRlcy5cbiAgICogVGhpcyBzZXJ2aWNlIGlzIHVzZWQgd2hlbiB0aGUgYnV0dG9uTGluayBpcyBhIHN0cmluZyBVUkwgdG8gbmF2aWdhdGUgdG8gdGhhdCBsb2NhdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHR5cGUge1JvdXRlcn1cbiAgICogQG1lbWJlck9mIEVtcHR5U3RhdGVDb21wb25lbnRcbiAgICovXG4gIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIgPSBpbmplY3QoUm91dGVyKTtcblxuICBwcml2YXRlIHNhbml0aXplcjogRG9tU2FuaXRpemVyID0gaW5qZWN0KERvbVNhbml0aXplcik7XG5cbiAgcHJpdmF0ZSB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2UgPSBpbmplY3QoVHJhbnNsYXRlU2VydmljZSk7XG5cbiAgc2VhcmNoU3VidGl0bGUhOiBTYWZlSHRtbFxuXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIEVtcHR5U3RhdGVDb21wb25lbnQuXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpemVzIGEgbmV3IEVtcHR5U3RhdGVDb21wb25lbnQgYnkgY2FsbGluZyB0aGUgcGFyZW50IGNsYXNzIGNvbnN0cnVjdG9yXG4gICAqIHdpdGggdGhlIGNvbXBvbmVudCBuYW1lIGZvciBsb2dnaW5nIGFuZCBpZGVudGlmaWNhdGlvbiBwdXJwb3Nlcy4gVGhpcyBjb21wb25lbnQgcHJvdmlkZXNcbiAgICogYSBzdGFuZGFyZGl6ZWQgd2F5IHRvIGRpc3BsYXkgZW1wdHkgc3RhdGUgbWVzc2FnZXMgd2l0aCBvcHRpb25hbCBpY29ucyBhbmQgYWN0aW9uIGJ1dHRvbnMuXG4gICAqXG4gICAqIEBtZW1iZXJPZiBFbXB0eVN0YXRlQ29tcG9uZW50XG4gICAqL1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcihcIkVtcHR5U3RhdGVDb21wb25lbnRcIik7XG4gICAgYWRkSWNvbnMoYWxsSWNvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyB0aGUgY29tcG9uZW50IGFmdGVyIEFuZ3VsYXIgZmlyc3QgZGlzcGxheXMgdGhlIGRhdGEtYm91bmQgcHJvcGVydGllcy5cbiAgICogQHN1bW1hcnkgU2V0cyB1cCB0aGUgY29tcG9uZW50IGJ5IHByb2Nlc3NpbmcgYm9vbGVhbiBpbnB1dHMsIGFwcGx5aW5nIGxvY2FsaXphdGlvbiB0byB0ZXh0XG4gICAqIGVsZW1lbnRzIGlmIHRyYW5zbGF0aW9uIGlzIGVuYWJsZWQsIGFuZCBmb3JtYXR0aW5nIENTUyBjbGFzc2VzIGZvciB0aXRsZSBhbmQgc3VidGl0bGUgY29sb3JzLlxuICAgKiBUaGlzIG1ldGhvZCBwcmVwYXJlcyB0aGUgY29tcG9uZW50IGZvciB1c2VyIGludGVyYWN0aW9uIGJ5IGVuc3VyaW5nIGFsbCBwcm9wZXJ0aWVzIGFyZVxuICAgKiBwcm9wZXJseSBpbml0aWFsaXplZCBhbmQgbG9jYWxpemVkLlxuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBBIGFzIEFuZ3VsYXIgTGlmZWN5Y2xlXG4gICAqICAgcGFydGljaXBhbnQgRSBhcyBFbXB0eVN0YXRlQ29tcG9uZW50XG4gICAqXG4gICAqICAgQS0+PkU6IG5nT25Jbml0KClcbiAgICogICBFLT4+RTogUHJvY2VzcyB0cmFuc2xhdGFibGUgZmxhZ1xuICAgKiAgIEUtPj5FOiBQcm9jZXNzIHNob3dJY29uIGZsYWdcbiAgICogICBFLT4+RTogR2V0IGxvY2FsZSBzZXR0aW5nc1xuICAgKiAgIGFsdCB0cmFuc2xhdGFibGUgaXMgdHJ1ZVxuICAgKiAgICAgRS0+PkU6IExvY2FsaXplIHRpdGxlXG4gICAqICAgICBFLT4+RTogTG9jYWxpemUgc3VidGl0bGVcbiAgICogICAgIEUtPj5FOiBMb2NhbGl6ZSBidXR0b25UZXh0XG4gICAqICAgZW5kXG4gICAqICAgRS0+PkU6IEZvcm1hdCB0aXRsZSBDU1MgY2xhc3NcbiAgICogICBFLT4+RTogRm9ybWF0IHN1YnRpdGxlIENTUyBjbGFzc1xuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICAgKiBAbWVtYmVyT2YgRW1wdHlTdGF0ZUNvbXBvbmVudFxuICAgKi9cbiAgYXN5bmMgbmdPbkluaXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5pbml0aWFsaXplKCk7XG4gICAgdGhpcy50cmFuc2xhdGFibGUgPSBzdHJpbmdUb0Jvb2xlYW4odGhpcy50cmFuc2xhdGFibGUpO1xuICAgIHRoaXMuc2hvd0ljb24gPSBzdHJpbmdUb0Jvb2xlYW4odGhpcy5zaG93SWNvbik7XG4gICAgdGhpcy5sb2NhbGUgPSB0aGlzLmdldExvY2FsZSh0aGlzLnRyYW5zbGF0YWJsZSk7XG5cbiAgICAvLyBpZih0aGlzLnRyYW5zbGF0YWJsZSkge1xuICAgIC8vICAgdGhpcy50aXRsZSA9IGdlbmVyYXRlTG9jYWxlRnJvbVN0cmluZyh0aGlzLmxvY2FsZSwgdGhpcy50aXRsZSk7XG4gICAgLy8gICB0aGlzLnN1YnRpdGxlID0gZ2VuZXJhdGVMb2NhbGVGcm9tU3RyaW5nKHRoaXMubG9jYWxlLCB0aGlzLnN1YnRpdGxlKTtcbiAgICAvLyAgIHRoaXMuYnV0dG9uVGV4dCA9IGdlbmVyYXRlTG9jYWxlRnJvbVN0cmluZyh0aGlzLmxvY2FsZSwgdGhpcy5idXR0b25UZXh0KTtcbiAgICAvLyB9XG5cbiAgICB0aGlzLnRpdGxlQ29sb3IgPSBgZGNmLXRpdGxlIGNvbG9yLSR7dGhpcy50aXRsZUNvbG9yfWA7XG4gICAgdGhpcy5zdWJ0aXRsZUNvbG9yID0gYGRjZi1zdWJ0aXRsZSBjb2xvci0ke3RoaXMudGl0bGVDb2xvcn1gO1xuXG4gICAgaWYodGhpcy5zZWFyY2hWYWx1ZSAmJiB0aGlzLnRyYW5zbGF0YWJsZSlcbiAgICAgIHRoaXMuc2VhcmNoU3VidGl0bGUgPSBhd2FpdCB0aGlzLmdldFNlYXJjaFN1YnRpdGxlKHRoaXMuc3VidGl0bGUgYXMgc3RyaW5nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBjbGljayBldmVudHMgb24gdGhlIGFjdGlvbiBidXR0b24uXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIGlzIHRyaWdnZXJlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyB0aGUgYWN0aW9uIGJ1dHRvbiBpbiB0aGUgZW1wdHkgc3RhdGVcbiAgICogY29tcG9uZW50LiBJdCBzdXBwb3J0cyB0aHJlZSBuYXZpZ2F0aW9uIHBhdHRlcm5zOiAxKSBubyBhY3Rpb24gd2hlbiBidXR0b25MaW5rIGlzIG5vdCBwcm92aWRlZCxcbiAgICogMikgY3VzdG9tIGZ1bmN0aW9uIGV4ZWN1dGlvbiB3aGVuIGJ1dHRvbkxpbmsgaXMgYSBmdW5jdGlvbiwgYW5kIDMpIG5hdmlnYXRpb24gdG8gYSBzcGVjaWZpYyBVUkxcbiAgICogd2hlbiBidXR0b25MaW5rIGlzIGEgc3RyaW5nLiBUaGlzIGZsZXhpYmlsaXR5IGFsbG93cyB0aGUgZW1wdHkgc3RhdGUgdG8gdHJpZ2dlciB2YXJpb3VzIGFjdGlvbnNcbiAgICogYmFzZWQgb24gdGhlIGNvbnRleHQgaW4gd2hpY2ggaXQncyB1c2VkLlxuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXJcbiAgICogICBwYXJ0aWNpcGFudCBFIGFzIEVtcHR5U3RhdGVDb21wb25lbnRcbiAgICogICBwYXJ0aWNpcGFudCBOIGFzIFJvdXRlclxuICAgKlxuICAgKiAgIFUtPj5FOiBDbGljayBhY3Rpb24gYnV0dG9uXG4gICAqICAgRS0+PkU6IGhhbmRsZUNsaWNrKClcbiAgICogICBhbHQgYnV0dG9uTGluayBpcyBub3QgcHJvdmlkZWRcbiAgICogICAgIEUtLT4+VTogUmV0dXJuIGZhbHNlIChubyBhY3Rpb24pXG4gICAqICAgZWxzZSBidXR0b25MaW5rIGlzIGEgZnVuY3Rpb25cbiAgICogICAgIEUtPj5FOiBFeGVjdXRlIGJ1dHRvbkxpbmsgZnVuY3Rpb25cbiAgICogICAgIEUtLT4+VTogUmV0dXJuIGZ1bmN0aW9uIHJlc3VsdFxuICAgKiAgIGVsc2UgYnV0dG9uTGluayBpcyBhIFVSTCBzdHJpbmdcbiAgICogICAgIEUtPj5OOiBuYXZpZ2F0ZUZvcndhcmQoYnV0dG9uTGluaylcbiAgICogICAgIE4tLT4+RTogUmV0dXJuIG5hdmlnYXRpb24gcmVzdWx0XG4gICAqICAgICBFLS0+PlU6IFJldHVybiBuYXZpZ2F0aW9uIHJlc3VsdFxuICAgKiAgIGVuZFxuICAgKlxuICAgKiBAcmV0dXJuIHtib29sZWFuIHwgdm9pZCB8IFByb21pc2U8Ym9vbGVhbj59XG4gICAqICAgLSBmYWxzZSBpZiBubyBhY3Rpb24gaXMgdGFrZW5cbiAgICogICAtIFRoZSByZXN1bHQgb2YgdGhlIGJ1dHRvbkxpbmsgZnVuY3Rpb24gaWYgaXQncyBhIGZ1bmN0aW9uXG4gICAqICAgLSBBIFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBuYXZpZ2F0aW9uIHJlc3VsdCBpZiBidXR0b25MaW5rIGlzIGEgVVJMXG4gICAqIEBtZW1iZXJPZiBFbXB0eVN0YXRlQ29tcG9uZW50XG4gICAqL1xuICBoYW5kbGVDbGljaygpOiBib29sZWFuIHwgdm9pZCB8IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGZuID0gdGhpcy5idXR0b25MaW5rO1xuICAgIGlmKCFmbilcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICBpZihmbiBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgICAgcmV0dXJuIGZuKCk7XG4gICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW2ZuIGFzIHN0cmluZ10pO1xuICB9XG5cblxuIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2VuZXJhdGVzIGEgbG9jYWxpemVkIGFuZCBzYW5pdGl6ZWQgc3VidGl0bGUgZm9yIHNlYXJjaCByZXN1bHRzLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCB0YWtlcyBhIGNvbnRlbnQgc3RyaW5nLCB0eXBpY2FsbHkgdGhlIHN1YnRpdGxlLCBhbmQgcHJvY2Vzc2VzIGl0XG4gICAqIHRocm91Z2ggdGhlIHRyYW5zbGF0aW9uIHNlcnZpY2UuIEl0IHJlcGxhY2VzIGEgcGxhY2Vob2xkZXIgKCd2YWx1ZTAnKSB3aXRoIHRoZSBhY3R1YWxcbiAgICogc2VhcmNoIHZhbHVlLCB0aGVuIHNhbml0aXplcyB0aGUgcmVzdWx0IHRvIHNhZmVseSB1c2UgYXMgSFRNTC4gVGhpcyBpcyBwYXJ0aWN1bGFybHlcbiAgICogdXNlZnVsIGZvciBkaXNwbGF5aW5nIGR5bmFtaWMsIGxvY2FsaXplZCBtZXNzYWdlcyBpbiB0aGUgZW1wdHkgc3RhdGUgd2hlbiBhIHNlYXJjaFxuICAgKiB5aWVsZHMgbm8gcmVzdWx0cy5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNvbnRlbnQgLSBUaGUgY29udGVudCBzdHJpbmcgdG8gYmUgdHJhbnNsYXRlZCBhbmQgcHJvY2Vzc2VkXG4gICAqIEByZXR1cm4ge1Byb21pc2U8U2FmZUh0bWw+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIHNhbml0aXplZCBIVE1MIHN0cmluZ1xuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBFIGFzIEVtcHR5U3RhdGVDb21wb25lbnRcbiAgICogICBwYXJ0aWNpcGFudCBUIGFzIFRyYW5zbGF0ZVNlcnZpY2VcbiAgICogICBwYXJ0aWNpcGFudCBTIGFzIERvbVNhbml0aXplclxuICAgKlxuICAgKiAgIEUtPj5UOiBpbnN0YW50KGNvbnRlbnQsIHsndmFsdWUwJzogc2VhcmNoVmFsdWV9KVxuICAgKiAgIFQtLT4+RTogUmV0dXJuIHRyYW5zbGF0ZWQgc3RyaW5nXG4gICAqICAgRS0+PlM6IGJ5cGFzc1NlY3VyaXR5VHJ1c3RIdG1sKHRyYW5zbGF0ZWRTdHJpbmcpXG4gICAqICAgUy0tPj5FOiBSZXR1cm4gc2FuaXRpemVkIFNhZmVIdG1sXG4gICAqXG4gICAqIEBtZW1iZXJPZiBFbXB0eVN0YXRlQ29tcG9uZW50XG4gICAqL1xuICBhc3luYyBnZXRTZWFyY2hTdWJ0aXRsZShjb250ZW50OiBzdHJpbmcpOiBQcm9taXNlPFNhZmVIdG1sPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy50cmFuc2xhdGUuaW5zdGFudChjb250ZW50LCB7J3ZhbHVlMCc6IHRoaXMuc2VhcmNoVmFsdWV9KTtcbiAgICByZXR1cm4gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdEh0bWwocmVzdWx0KTtcbiAgfVxufVxuIiwiXG48aW9uLWNhcmQgW2lkXT1cInVpZFwiIFtjbGFzc109XCJjbGFzc05hbWVcIj5cbiAgPGlvbi1jYXJkLWNvbnRlbnQ+XG4gICAgQGlmKGljb24gJiYgc2hvd0ljb24pIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJkY2YtaWNvbi1jb250YWluZXJcIj5cbiAgICAgICAgPGlvbi1pY29uXG4gICAgICAgICAgbmFtZT1cImFsZXJ0LWNpcmNsZS1vdXRsaW5lXCJcbiAgICAgICAgICBzaXplPVwibGFyZ2VcIlxuICAgICAgICAgIGNvbG9yPVwiZGFuZ2VyXCJcbiAgICAgICAgICAvPlxuICAgICAgPC9kaXY+XG4gICAgfVxuICAgIEBpZih0aXRsZSkge1xuICAgICAgPGg1IFtjbGFzc109XCJ0aXRsZUNvbG9yXCIgW2lubmVySFRNTF09XCJ0aXRsZVwiPjwvaDU+XG4gICAgfVxuICAgIEBpZihzdWJ0aXRsZSkge1xuICAgICAgQGlmKCFzZWFyY2hWYWx1ZSkge1xuICAgICAgICA8cCBbY2xhc3NdPVwic3VidGl0bGVDb2xvclwiIFtpbm5lckhUTUxdPVwic3VidGl0bGVcIj48L3A+XG4gICAgICB9IEBlbHNlIHtcbiAgICAgICAgPHAgW2NsYXNzXT1cInN1YnRpdGxlQ29sb3JcIiBbaW5uZXJIVE1MXT1cInNlYXJjaFN1YnRpdGxlXCI+PC9wPlxuICAgICAgfVxuICAgIH1cbiAgICBAaWYoYnV0dG9uTGluayAmJiBidXR0b25UZXh0KSB7XG4gICAgICA8ZGl2PlxuICAgICAgICA8aW9uLWJ1dHRvblxuICAgICAgICAgIFtzaXplXT1cImJ1dHRvblNpemVcIlxuICAgICAgICAgIFtmaWxsXT1cImJ1dHRvbkZpbGxcIlxuICAgICAgICAgIFtjb2xvcl09XCJidXR0b25Db2xvclwiXG4gICAgICAgICAgKGNsaWNrKT1cImhhbmRsZUNsaWNrKClcIj5cbiAgICAgICAgICB7eyAgYnV0dG9uVGV4dCB9fVxuICAgICAgICA8L2lvbi1idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICB9XG4gIDwvaW9uLWNhcmQtY29udGVudD5cbjwvaW9uLWNhcmQ+XG4iXX0=