@decaf-ts/for-angular 0.0.25 → 0.0.27

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 +1486 -1505
  2. package/fesm2022/decaf-ts-for-angular.mjs.map +1 -1
  3. package/index.d.ts +7482 -3
  4. package/package.json +15 -18
  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/stepped-form/stepped-form.component.d.ts +0 -255
  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/stepped-form/stepped-form.component.mjs +0 -306
  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 -85
  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,376 +0,0 @@
1
- import { RenderingEngine } from '@decaf-ts/ui-decorators';
2
- import { AngularEngineKeys } from './constants';
3
- import { InternalError } from '@decaf-ts/db-decorators';
4
- import { reflectComponentType, } from '@angular/core';
5
- import { NgxFormService } from './NgxFormService';
6
- import { isDevelopmentMode } from '../helpers';
7
- /**
8
- * @description Angular implementation of the RenderingEngine with enhanced features
9
- * @summary This class extends the base RenderingEngine to provide Angular-specific rendering capabilities
10
- * with additional features compared to NgxRenderingEngine. It handles the conversion of field definitions
11
- * to Angular components, manages component registration, and provides utilities for component creation
12
- * and input handling. This implementation uses Angular's newer component APIs.
13
- *
14
- * @template AngularFieldDefinition - Type for Angular-specific field definitions
15
- * @template AngularDynamicOutput - Type for Angular-specific component output
16
- *
17
- * @class NgxRenderingEngine
18
- * @example
19
- * ```typescript
20
- * const engine = NgxRenderingEngine.get();
21
- * engine.initialize();
22
- * const output = engine.render(myModel, {}, viewContainerRef, injector, templateRef);
23
- * ```
24
- *
25
- * @mermaid
26
- * sequenceDiagram
27
- * participant Client
28
- * participant Engine as NgxRenderingEngine
29
- * participant Components as RegisteredComponents
30
- *
31
- * Client->>Engine: get()
32
- * Client->>Engine: initialize()
33
- * Client->>Engine: render(model, props, vcr, injector, tpl)
34
- * Engine->>Engine: toFieldDefinition(model, props)
35
- * Engine->>Engine: fromFieldDefinition(fieldDef, vcr, injector, tpl)
36
- * Engine->>Components: components(fieldDef.tag)
37
- * Components-->>Engine: component constructor
38
- * Engine->>Engine: createComponent(component, inputs, metadata, vcr, injector, template)
39
- * Engine-->>Client: return AngularDynamicOutput
40
- */
41
- export class NgxRenderingEngine extends RenderingEngine {
42
- /**
43
- * @description Current operation context for component visibility control
44
- * @summary Static property that stores the current operation being performed,
45
- * which is used to determine component visibility through the 'hidden' property.
46
- * Components can specify operations where they should be hidden, and this property
47
- * provides the context for those visibility checks. The value is typically extracted
48
- * from the global properties during the rendering process.
49
- *
50
- * @private
51
- * @static
52
- * @type {string | undefined}
53
- */
54
- static { this._operation = undefined; }
55
- static { this._projectable = true; }
56
- static { this._parentProps = undefined; }
57
- /**
58
- * @description Constructs a new NgxRenderingEngine instance
59
- * @summary Initializes a new instance of the Angular rendering engine by calling the parent
60
- * constructor with the 'angular' engine type identifier. This constructor sets up the base
61
- * rendering engine functionality with Angular-specific configurations and prepares the
62
- * instance for component registration and rendering operations.
63
- *
64
- * @constructor
65
- */
66
- constructor() {
67
- super('angular');
68
- }
69
- /**
70
- * @description Converts a field definition to an Angular component output
71
- * @summary This private method takes a field definition and creates the corresponding Angular component.
72
- * It handles component instantiation, input property mapping, and child component rendering.
73
- * The method validates input properties against the component's metadata and processes
74
- * child components recursively.
75
- *
76
- * @param {FieldDefinition<AngularFieldDefinition>} fieldDef - The field definition to convert
77
- * @param {ViewContainerRef} vcr - The view container reference for component creation
78
- * @param {Injector} injector - The Angular injector for dependency injection
79
- * @param {TemplateRef<any>} tpl - The template reference for content projection
80
- * @param {string} registryFormId - Form identifier for the component renderer
81
- * @return {AngularDynamicOutput} The Angular component output with component reference and inputs
82
- *
83
- * @mermaid
84
- * sequenceDiagram
85
- * participant Method as fromFieldDefinition
86
- * participant Components as NgxRenderingEngine.components
87
- * participant Angular as Angular Core
88
- * participant Process as processChild
89
- *
90
- * Method->>Components: components(fieldDef.tag)
91
- * Components-->>Method: component constructor
92
- * Method->>Angular: reflectComponentType(component)
93
- * Angular-->>Method: componentMetadata
94
- * Method->>Method: Validate input properties
95
- * Method->>Method: Create result object
96
- * alt Has children
97
- * Method->>Process: Process children recursively
98
- * Process->>Method: Return processed children
99
- * Method->>Angular: Create embedded view
100
- * Method->>Method: Create component instance
101
- * end
102
- * Method-->>Caller: return AngularDynamicOutput
103
- */
104
- fromFieldDefinition(fieldDef, vcr, injector, tpl, registryFormId = Date.now().toString(36).toUpperCase()) {
105
- const cmp = fieldDef?.['component'] || NgxRenderingEngine.components(fieldDef.tag);
106
- const component = cmp.constructor;
107
- const componentMetadata = reflectComponentType(component);
108
- if (!componentMetadata) {
109
- throw new InternalError(`Metadata for component ${fieldDef.tag} not found.`);
110
- }
111
- const { inputs: possibleInputs } = componentMetadata;
112
- const inputs = { ...fieldDef.props };
113
- const unmappedKeys = Object.keys(inputs).filter(input => {
114
- const isMapped = possibleInputs.find(({ propName }) => propName === input);
115
- if (!isMapped)
116
- delete inputs[input];
117
- return !isMapped;
118
- });
119
- if (unmappedKeys.length > 0 && isDevelopmentMode())
120
- console.warn(`Unmapped input properties for component ${fieldDef.tag}: ${unmappedKeys.join(', ')}`);
121
- const operation = NgxRenderingEngine._operation;
122
- const hiddenOn = inputs?.hidden || [];
123
- if (hiddenOn.includes(operation))
124
- return { inputs, injector };
125
- const result = {
126
- component,
127
- inputs,
128
- injector,
129
- };
130
- if (fieldDef.rendererId)
131
- result.inputs['rendererId'] = fieldDef.rendererId;
132
- // process children
133
- if (fieldDef.children?.length) {
134
- if (!NgxRenderingEngine._parentProps && inputs?.pages)
135
- NgxRenderingEngine._parentProps = { pages: inputs?.pages };
136
- result.children = fieldDef.children.map((child) => {
137
- if (child?.children?.length) {
138
- child.children = child.children.filter(c => {
139
- const hiddenOn = c?.props?.hidden || [];
140
- if (!hiddenOn.includes(operation))
141
- return c;
142
- });
143
- }
144
- NgxFormService.addControlFromProps(registryFormId, child.props, { ...inputs, ...NgxRenderingEngine._parentProps || {} });
145
- return this.fromFieldDefinition(child, vcr, injector, tpl, registryFormId);
146
- });
147
- }
148
- // generating DOM
149
- const projectable = NgxRenderingEngine._projectable;
150
- vcr.clear();
151
- const template = !projectable ? [] : vcr.createEmbeddedView(tpl, injector).rootNodes;
152
- const hasChildren = Object.values(possibleInputs).some(({ propName }) => propName === 'children');
153
- const hasModel = Object.values(possibleInputs).some(({ propName }) => propName === 'children');
154
- const componentInputs = Object.assign(inputs, (hasModel ? { model: this._model } : {}), (hasChildren ? { children: fieldDef?.['children'] || [] } : {}));
155
- const componentInstance = NgxRenderingEngine.createComponent(component, componentInputs, componentMetadata, vcr, injector, template);
156
- result.instance = NgxRenderingEngine._instance = componentInstance.instance;
157
- return result;
158
- }
159
- /**
160
- * @description Creates an Angular component instance
161
- * @summary This static utility method creates an Angular component instance with the specified
162
- * inputs and template. It uses Angular's component creation API to instantiate the component
163
- * and then sets the input properties using the provided metadata.
164
- *
165
- * @param {Type<unknown>} component - The component type to create
166
- * @param {KeyValue} [inputs={}] - The input properties to set on the component
167
- * @param {ComponentMirror<unknown>} metadata - The component metadata for input validation
168
- * @param {ViewContainerRef} vcr - The view container reference for component creation
169
- * @param {Injector} injector - The Angular injector for dependency injection
170
- * @param {Node[]} [template=[]] - The template nodes to project into the component
171
- * @return {ComponentRef<unknown>} The created component reference
172
- */
173
- static createComponent(component, inputs = {}, metadata, vcr, injector, template = []) {
174
- const componentInstance = vcr.createComponent(component, {
175
- environmentInjector: injector,
176
- projectableNodes: [template],
177
- });
178
- this.setInputs(componentInstance, inputs, metadata);
179
- return componentInstance;
180
- }
181
- /**
182
- * @description Extracts decorator metadata from a model
183
- * @summary This method provides access to the field definition generated from a model's
184
- * decorators. It's a convenience wrapper around the toFieldDefinition method that
185
- * converts a model to a field definition based on its decorators and the provided
186
- * global properties.
187
- *
188
- * @param {Model} model - The model to extract decorators from
189
- * @param {Record<string, unknown>} globalProps - Global properties to include in the field definition
190
- * @return {FieldDefinition<AngularFieldDefinition>} The field definition generated from the model
191
- */
192
- getDecorators(model, globalProps) {
193
- return this.toFieldDefinition(model, globalProps);
194
- }
195
- /**
196
- * @description Destroys the current engine instance
197
- * @summary This static method clears the current instance reference, effectively
198
- * destroying the singleton instance of the rendering engine. This can be used
199
- * to reset the engine state or to prepare for a new instance creation.
200
- *
201
- * @return {Promise<void>} A promise that resolves when the instance is destroyed
202
- */
203
- static async destroy(formId) {
204
- if (formId)
205
- NgxFormService.removeRegistry(formId);
206
- NgxRenderingEngine._instance = undefined;
207
- NgxRenderingEngine._parentProps = undefined;
208
- }
209
- /**
210
- * @description Renders a model into an Angular component output
211
- * @summary This method takes a model and converts it to an Angular component output.
212
- * It first stores a reference to the model, then converts it to a field definition
213
- * using the base RenderingEngine's toFieldDefinition method, and finally converts
214
- * that field definition to an Angular component output using fromFieldDefinition.
215
- *
216
- * @template M - Type extending Model
217
- * @param {M} model - The model to render
218
- * @param {Record<string, unknown>} globalProps - Global properties to pass to the component
219
- * @param {ViewContainerRef} vcr - The view container reference for component creation
220
- * @param {Injector} injector - The Angular injector for dependency injection
221
- * @param {TemplateRef<any>} tpl - The template reference for content projection
222
- * @return {AngularDynamicOutput} The Angular component output with component reference and inputs
223
- *
224
- * @mermaid
225
- * sequenceDiagram
226
- * participant Client as Client Code
227
- * participant Render as render method
228
- * participant ToField as toFieldDefinition
229
- * participant FromField as fromFieldDefinition
230
- *
231
- * Client->>Render: render(model, globalProps, vcr, injector, tpl)
232
- * Render->>Render: Store model reference
233
- * Render->>ToField: toFieldDefinition(model, globalProps)
234
- * ToField-->>Render: fieldDef
235
- * Render->>FromField: fromFieldDefinition(fieldDef, vcr, injector, tpl)
236
- * FromField-->>Render: AngularDynamicOutput
237
- * Render-->>Client: return AngularDynamicOutput
238
- */
239
- render(model, globalProps, vcr, injector, tpl, projectable = true) {
240
- let result;
241
- try {
242
- this._model = model;
243
- NgxRenderingEngine._projectable = projectable;
244
- const formId = Date.now().toString(36).toUpperCase();
245
- const fieldDef = this.toFieldDefinition(model, globalProps);
246
- const props = fieldDef.props;
247
- if (!NgxRenderingEngine._operation)
248
- NgxRenderingEngine._operation = props?.['operation'] || undefined;
249
- const formGroup = NgxFormService.createForm(formId, props);
250
- result = this.fromFieldDefinition(fieldDef, vcr, injector, tpl, formId);
251
- result.instance['formGroup'] = formGroup;
252
- NgxRenderingEngine.destroy(formId);
253
- }
254
- catch (e) {
255
- throw new InternalError(`Failed to render Model ${model.constructor.name}: ${e}`);
256
- }
257
- return result;
258
- }
259
- /**
260
- * @description Initializes the rendering engine
261
- * @summary This method initializes the rendering engine. It checks if the engine is already initialized
262
- * and sets the initialized flag to true. This method is called before the engine is used
263
- * to ensure it's properly set up for rendering operations.
264
- *
265
- * @return {Promise<void>} A promise that resolves when initialization is complete
266
- */
267
- async initialize() {
268
- if (this.initialized)
269
- return;
270
- // ValidatableByType[]
271
- this.initialized = true;
272
- }
273
- /**
274
- * @description Registers a component with the rendering engine
275
- * @summary This static method registers a component constructor with the rendering engine
276
- * under a specific name. It initializes the components registry if needed and throws
277
- * an error if a component is already registered under the same name to prevent
278
- * accidental overrides.
279
- *
280
- * @param {string} name - The name to register the component under
281
- * @param {Constructor<unknown>} constructor - The component constructor
282
- * @return {void}
283
- */
284
- static registerComponent(name, constructor) {
285
- if (!this._components)
286
- this._components = {};
287
- if (name in this._components)
288
- throw new InternalError(`Component already registered under ${name}`);
289
- this._components[name] = {
290
- constructor: constructor,
291
- };
292
- }
293
- /**
294
- * @description Retrieves registered components from the rendering engine
295
- * @summary This static method retrieves either all registered components or a specific component
296
- * by its selector. When called without a selector, it returns an array of all registered
297
- * components. When called with a selector, it returns the specific component if found,
298
- * or throws an error if the component is not registered.
299
- *
300
- * @param {string} [selector] - Optional selector to retrieve a specific component
301
- * @return {Object|Array} Either a specific component or an array of all components
302
- */
303
- static components(selector) {
304
- if (!selector)
305
- return Object.values(this._components);
306
- if (!(selector in this._components))
307
- throw new InternalError(`No Component registered under ${selector}`);
308
- return this._components[selector];
309
- }
310
- /**
311
- * @description Generates a key for reflection metadata
312
- * @summary This static method generates a key for reflection metadata by prefixing the input key
313
- * with the Angular engine's reflection prefix. This is used for storing and retrieving
314
- * metadata in a namespaced way to avoid conflicts with other metadata.
315
- *
316
- * @param {string} key - The base key to prefix
317
- * @return {string} The prefixed key for reflection metadata
318
- */
319
- static key(key) {
320
- return `${AngularEngineKeys.REFLECT}${key}`;
321
- }
322
- /**
323
- * @description Sets input properties on a component instance
324
- * @summary This static utility method sets input properties on a component instance
325
- * based on the provided inputs object and component metadata. It handles both simple
326
- * values and nested objects, recursively processing object properties. The method
327
- * validates each input against the component's metadata to ensure only valid inputs
328
- * are set.
329
- *
330
- * @param {ComponentRef<unknown>} component - The component reference to set inputs on
331
- * @param {KeyValue} inputs - The input properties to set
332
- * @param {ComponentMirror<unknown>} metadata - The component metadata for input validation
333
- * @return {void}
334
- *
335
- * @mermaid
336
- * sequenceDiagram
337
- * participant Caller
338
- * participant SetInputs as setInputs
339
- * participant Parse as parseInputValue
340
- * participant Component as ComponentRef
341
- *
342
- * Caller->>SetInputs: setInputs(component, inputs, metadata)
343
- * SetInputs->>SetInputs: Iterate through inputs
344
- * loop For each input
345
- * SetInputs->>SetInputs: Check if input exists in metadata
346
- * alt Input is 'props'
347
- * SetInputs->>Parse: parseInputValue(component, value)
348
- * Parse->>Parse: Recursively process nested objects
349
- * Parse->>Component: setInput(key, value)
350
- * else Input is valid
351
- * SetInputs->>Component: setInput(key, value)
352
- * end
353
- * end
354
- */
355
- static setInputs(component, inputs, metadata) {
356
- function parseInputValue(component, input) {
357
- Object.keys(input).forEach(key => {
358
- const value = input[key];
359
- if (typeof value === 'object' && !!value)
360
- return parseInputValue(component, value);
361
- component.setInput(key, value);
362
- });
363
- }
364
- Object.entries(inputs).forEach(([key, value]) => {
365
- const prop = metadata.inputs.find((item) => item.propName === key);
366
- if (prop) {
367
- if (key === 'props')
368
- parseInputValue(component, value);
369
- // if(key === 'locale' && !value)
370
- // value = getLocaleFromClassName(this._componentName);
371
- component.setInput(key, value);
372
- }
373
- });
374
- }
375
- }
376
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTmd4UmVuZGVyaW5nRW5naW5lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9lbmdpbmUvTmd4UmVuZGVyaW5nRW5naW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBbUIsZUFBZSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHM0UsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRWhELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN4RCxPQUFPLEVBS0wsb0JBQW9CLEdBSXJCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFL0M7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWlDRztBQUNILE1BQU0sT0FBTyxrQkFBbUIsU0FBUSxlQUE2RDtJQTRCbkc7Ozs7Ozs7Ozs7O09BV0c7YUFDWSxlQUFVLEdBQXVCLFNBQVMsQ0FBQzthQWlCM0MsaUJBQVksR0FBWSxJQUFJLENBQUE7YUFHNUIsaUJBQVksR0FBeUIsU0FBUyxDQUFDO0lBRzlEOzs7Ozs7OztPQVFHO0lBQ0g7UUFDRSxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDbkIsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O09Ba0NHO0lBQ0ssbUJBQW1CLENBQ3pCLFFBQWlELEVBQ2pELEdBQXFCLEVBQ3JCLFFBQWtCLEVBQ2xCLEdBQXlCLEVBQ3pCLGlCQUF5QixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRTtRQUU5RCxNQUFNLEdBQUcsR0FBSSxRQUFxQixFQUFFLENBQUMsV0FBVyxDQUFDLElBQUksa0JBQWtCLENBQUMsVUFBVSxDQUFD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LElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7Z0JBQy9CLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDekIsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksQ0FBQyxDQUFDLEtBQUs7b0JBQ3RDLE9BQU8sZUFBZSxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDM0MsU0FBUyxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDakMsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFO1lBQzlDLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBMEIsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsS0FBSyxHQUFHLENBQUMsQ0FBQztZQUN6RixJQUFJLElBQUksRUFBRSxDQUFDO2dCQUNULElBQUksR0FBRyxLQUFLLE9BQU87b0JBQ2pCLGVBQWUsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7Z0JBQ3BDLGlDQUFpQztnQkFDakMseURBQXlEO2dCQUN6RCxTQUFTLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNqQyxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRmllbGREZWZpbml0aW9uLCBSZW5kZXJpbmdFbmdpbmUgfSBmcm9tICdAZGVjYWYtdHMvdWktZGVjb3JhdG9ycyc7XG5pbXBvcnQgeyBBbmd1bGFyRmllbGREZWZpbml0aW9uLCBLZXlWYWx1ZSB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgQW5ndWxhckR5bmFtaWNPdXRwdXQgfSBmcm9tICcuL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgQW5ndWxhckVuZ2luZUtleXMgfSBmcm9tICcuL2NvbnN0YW50cyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTW9kZWwgfSBmcm9tICdAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb24nO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciB9IGZyb20gJ0BkZWNhZi10cy9kYi1kZWNvcmF0b3JzJztcbmltcG9ydCB7XG4gIENvbXBvbmVudE1pcnJvcixcbiAgQ29tcG9uZW50UmVmLFxuICBFbnZpcm9ubWVudEluamVjdG9yLFxuICBJbmplY3RvcixcbiAgcmVmbGVjdENvbXBvbmVudFR5cGUsXG4gIFRlbXBsYXRlUmVmLFxuICBUeXBlLFxuICBWaWV3Q29udGFpbmVyUmVmLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE5neEZvcm1TZXJ2aWNlIH0gZnJvbSAnLi9OZ3hGb3JtU2VydmljZSc7XG5pbXBvcnQgeyBpc0RldmVsb3BtZW50TW9kZSB9IGZyb20gJy4uL2hlbHBlcnMnO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBbmd1bGFyIGltcGxlbWVudGF0aW9uIG9mIHRoZSBSZW5kZXJpbmdFbmdpbmUgd2l0aCBlbmhhbmNlZCBmZWF0dXJlc1xuICogQHN1bW1hcnkgVGhpcyBjbGFzcyBleHRlbmRzIHRoZSBiYXNlIFJlbmRlcmluZ0VuZ2luZSB0byBwcm92aWRlIEFuZ3VsYXItc3BlY2lmaWMgcmVuZGVyaW5nIGNhcGFiaWxpdGllc1xuICogd2l0aCBhZGRpdGlvbmFsIGZlYXR1cmVzIGNvbXBhcmVkIHRvIE5neFJlbmRlcmluZ0VuZ2luZS4gSXQgaGFuZGxlcyB0aGUgY29udmVyc2lvbiBvZiBmaWVsZCBkZWZpbml0aW9uc1xuICogdG8gQW5ndWxhciBjb21wb25lbnRzLCBtYW5hZ2VzIGNvbXBvbmVudCByZWdpc3RyYXRpb24sIGFuZCBwcm92aWRlcyB1dGlsaXRpZXMgZm9yIGNvbXBvbmVudCBjcmVhdGlvblxuICogYW5kIGlucHV0IGhhbmRsaW5nLiBUaGlzIGltcGxlbWVudGF0aW9uIHVzZXMgQW5ndWxhcidzIG5ld2VyIGNvbXBvbmVudCBBUElzLlxuICpcbiAqIEB0ZW1wbGF0ZSBBbmd1bGFyRmllbGREZWZpbml0aW9uIC0gVHlwZSBmb3IgQW5ndWxhci1zcGVjaWZpYyBmaWVsZCBkZWZpbml0aW9uc1xuICogQHRlbXBsYXRlIEFuZ3VsYXJEeW5hbWljT3V0cHV0IC0gVHlwZSBmb3IgQW5ndWxhci1zcGVjaWZpYyBjb21wb25lbnQgb3V0cHV0XG4gKlxuICogQGNsYXNzIE5neFJlbmRlcmluZ0VuZ2luZVxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGVuZ2luZSA9IE5neFJlbmRlcmluZ0VuZ2luZS5nZXQoKTtcbiAqIGVuZ2luZS5pbml0aWFsaXplKCk7XG4gKiBjb25zdCBvdXRwdXQgPSBlbmdpbmUucmVuZGVyKG15TW9kZWwsIHt9LCB2aWV3Q29udGFpbmVyUmVmLCBpbmplY3RvciwgdGVtcGxhdGVSZWYpO1xuICogYGBgXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgRW5naW5lIGFzIE5neFJlbmRlcmluZ0VuZ2luZVxuICogICBwYXJ0aWNpcGFudCBDb21wb25lbnRzIGFzIFJlZ2lzdGVyZWRDb21wb25lbnRzXG4gKlxuICogICBDbGllbnQtPj5FbmdpbmU6IGdldCgpXG4gKiAgIENsaWVudC0+PkVuZ2luZTogaW5pdGlhbGl6ZSgpXG4gKiAgIENsaWVudC0+PkVuZ2luZTogcmVuZGVyKG1vZGVsLCBwcm9wcywgdmNyLCBpbmplY3RvciwgdHBsKVxuICogICBFbmdpbmUtPj5FbmdpbmU6IHRvRmllbGREZWZpbml0aW9uKG1vZGVsLCBwcm9wcylcbiAqICAgRW5naW5lLT4+RW5naW5lOiBmcm9tRmllbGREZWZpbml0aW9uKGZpZWxkRGVmLCB2Y3IsIGluamVjdG9yLCB0cGwpXG4gKiAgIEVuZ2luZS0+PkNvbXBvbmVudHM6IGNvbXBvbmVudHMoZmllbGREZWYudGFnKVxuICogICBDb21wb25lbnRzLS0+PkVuZ2luZTogY29tcG9uZW50IGNvbnN0cnVjdG9yXG4gKiAgIEVuZ2luZS0+PkVuZ2luZTogY3JlYXRlQ29tcG9uZW50KGNvbXBvbmVudCwgaW5wdXRzLCBtZXRhZGF0YSwgdmNyLCBpbmplY3RvciwgdGVtcGxhdGUpXG4gKiAgIEVuZ2luZS0tPj5DbGllbnQ6IHJldHVybiBBbmd1bGFyRHluYW1pY091dHB1dFxuICovXG5leHBvcnQgY2xhc3MgTmd4UmVuZGVyaW5nRW5naW5lIGV4dGVuZHMgUmVuZGVyaW5nRW5naW5lPEFuZ3VsYXJGaWVsZERlZmluaXRpb24sIEFuZ3VsYXJEeW5hbWljT3V0cHV0PiB7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWdpc3RyeSBvZiBjb21wb25lbnRzIGF2YWlsYWJsZSBmb3IgcmVuZGVyaW5nXG4gICAqIEBzdW1tYXJ5IFN0YXRpYyByZWdpc3RyeSB0aGF0IHN0b3JlcyBhbGwgcmVnaXN0ZXJlZCBjb21wb25lbnRzIGluZGV4ZWQgYnkgdGhlaXIgc2VsZWN0b3IgbmFtZS5cbiAgICogRWFjaCBjb21wb25lbnQgZW50cnkgY29udGFpbnMgYSBjb25zdHJ1Y3RvciByZWZlcmVuY2UgdGhhdCBjYW4gYmUgdXNlZCB0byBpbnN0YW50aWF0ZVxuICAgKiB0aGUgY29tcG9uZW50IGR1cmluZyB0aGUgcmVuZGVyaW5nIHByb2Nlc3MuIFRoaXMgcmVnaXN0cnkgaXMgc2hhcmVkIGFjcm9zcyBhbGwgaW5zdGFuY2VzXG4gICAqIG9mIHRoZSByZW5kZXJpbmcgZW5naW5lIGFuZCBpcyBwb3B1bGF0ZWQgdGhyb3VnaCB0aGUgcmVnaXN0ZXJDb21wb25lbnQgbWV0aG9kLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAc3RhdGljXG4gICAqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCB7IGNvbnN0cnVjdG9yOiBDb25zdHJ1Y3Rvcjx1bmtub3duPiB9Pn1cbiAgICovXG4gIHByaXZhdGUgc3RhdGljIF9jb21wb25lbnRzOiBSZWNvcmQ8c3RyaW5nLCB7IGNvbnN0cnVjdG9yOiBDb25zdHJ1Y3Rvcjx1bmtub3duPiB9PjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEN1cnJlbnRseSBhY3RpdmUgbW9kZWwgYmVpbmcgcmVuZGVyZWRcbiAgICogQHN1bW1hcnkgU3RvcmVzIGEgcmVmZXJlbmNlIHRvIHRoZSBtb2RlbCBpbnN0YW5jZSB0aGF0IGlzIGN1cnJlbnRseSBiZWluZyBwcm9jZXNzZWRcbiAgICogYnkgdGhlIHJlbmRlcmluZyBlbmdpbmUuIFRoaXMgcHJvcGVydHkgaXMgc2V0IGR1cmluZyB0aGUgcmVuZGVyIG1ldGhvZCBleGVjdXRpb25cbiAgICogYW5kIGlzIHVzZWQgdGhyb3VnaG91dCB0aGUgcmVuZGVyaW5nIGxpZmVjeWNsZSB0byBhY2Nlc3MgbW9kZWwgZGF0YSBhbmQgbWV0YWRhdGEuXG4gICAqIFRoZSBkZWZpbml0ZSBhc3NpZ25tZW50IGFzc2VydGlvbiAoISkgaXMgdXNlZCBiZWNhdXNlIHRoaXMgcHJvcGVydHkgaXMgYWx3YXlzXG4gICAqIGluaXRpYWxpemVkIGJlZm9yZSB1c2Ugd2l0aGluIHRoZSByZW5kZXIgbWV0aG9kLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAdHlwZSB7TW9kZWx9XG4gICAqL1xuICBwcml2YXRlIF9tb2RlbCE6IE1vZGVsO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3VycmVudCBvcGVyYXRpb24gY29udGV4dCBmb3IgY29tcG9uZW50IHZpc2liaWxpdHkgY29udHJvbFxuICAgKiBAc3VtbWFyeSBTdGF0aWMgcHJvcGVydHkgdGhhdCBzdG9yZXMgdGhlIGN1cnJlbnQgb3BlcmF0aW9uIGJlaW5nIHBlcmZvcm1lZCxcbiAgICogd2hpY2ggaXMgdXNlZCB0byBkZXRlcm1pbmUgY29tcG9uZW50IHZpc2liaWxpdHkgdGhyb3VnaCB0aGUgJ2hpZGRlbicgcHJvcGVydHkuXG4gICAqIENvbXBvbmVudHMgY2FuIHNwZWNpZnkgb3BlcmF0aW9ucyB3aGVyZSB0aGV5IHNob3VsZCBiZSBoaWRkZW4sIGFuZCB0aGlzIHByb3BlcnR5XG4gICAqIHByb3ZpZGVzIHRoZSBjb250ZXh0IGZvciB0aG9zZSB2aXNpYmlsaXR5IGNoZWNrcy4gVGhlIHZhbHVlIGlzIHR5cGljYWxseSBleHRyYWN0ZWRcbiAgICogZnJvbSB0aGUgZ2xvYmFsIHByb3BlcnRpZXMgZHVyaW5nIHRoZSByZW5kZXJpbmcgcHJvY2Vzcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHN0YXRpY1xuICAgKiBAdHlwZSB7c3RyaW5nIHwgdW5kZWZpbmVkfVxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgX29wZXJhdGlvbjogc3RyaW5nIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVmZXJlbmNlIHRvIHRoZSBjdXJyZW50bHkgYWN0aXZlIGNvbXBvbmVudCBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBTdGF0aWMgcHJvcGVydHkgdGhhdCBtYWludGFpbnMgYSByZWZlcmVuY2UgdG8gdGhlIG1vc3QgcmVjZW50bHkgY3JlYXRlZFxuICAgKiBjb21wb25lbnQgaW5zdGFuY2UuIFRoaXMgaXMgdXNlZCBpbnRlcm5hbGx5IGZvciBjb21wb25lbnQgbGlmZWN5Y2xlIG1hbmFnZW1lbnRcbiAgICogYW5kIGNhbiBiZSBjbGVhcmVkIHRocm91Z2ggdGhlIGRlc3Ryb3kgbWV0aG9kLiBUaGUgcmVmZXJlbmNlIGFsbG93cyBhY2Nlc3MgdG9cbiAgICogdGhlIGFjdGl2ZSBjb21wb25lbnQgaW5zdGFuY2UgZm9yIG9wZXJhdGlvbnMgdGhhdCBuZWVkIHRvIGludGVyYWN0IHdpdGggdGhlXG4gICAqIGN1cnJlbnRseSByZW5kZXJlZCBjb21wb25lbnQuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBzdGF0aWNcbiAgICogQHR5cGUge1R5cGU8dW5rbm93bj4gfCB1bmRlZmluZWR9XG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBfaW5zdGFuY2U6IFR5cGU8dW5rbm93bj4gfCB1bmRlZmluZWQ7XG5cblxuICBwcml2YXRlIHN0YXRpYyBfcHJvamVjdGFibGU6IGJvb2xlYW4gPSB0cnVlXG5cblxuICBwcml2YXRlIHN0YXRpYyBfcGFyZW50UHJvcHM6IEtleVZhbHVlIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDb25zdHJ1Y3RzIGEgbmV3IE5neFJlbmRlcmluZ0VuZ2luZSBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXplcyBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgQW5ndWxhciByZW5kZXJpbmcgZW5naW5lIGJ5IGNhbGxpbmcgdGhlIHBhcmVudFxuICAgKiBjb25zdHJ1Y3RvciB3aXRoIHRoZSAnYW5ndWxhcicgZW5naW5lIHR5cGUgaWRlbnRpZmllci4gVGhpcyBjb25zdHJ1Y3RvciBzZXRzIHVwIHRoZSBiYXNlXG4gICAqIHJlbmRlcmluZyBlbmdpbmUgZnVuY3Rpb25hbGl0eSB3aXRoIEFuZ3VsYXItc3BlY2lmaWMgY29uZmlndXJhdGlvbnMgYW5kIHByZXBhcmVzIHRoZVxuICAgKiBpbnN0YW5jZSBmb3IgY29tcG9uZW50IHJlZ2lzdHJhdGlvbiBhbmQgcmVuZGVyaW5nIG9wZXJhdGlvbnMuXG4gICAqXG4gICAqIEBjb25zdHJ1Y3RvclxuICAgKi9cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoJ2FuZ3VsYXInKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29udmVydHMgYSBmaWVsZCBkZWZpbml0aW9uIHRvIGFuIEFuZ3VsYXIgY29tcG9uZW50IG91dHB1dFxuICAgKiBAc3VtbWFyeSBUaGlzIHByaXZhdGUgbWV0aG9kIHRha2VzIGEgZmllbGQgZGVmaW5pdGlvbiBhbmQgY3JlYXRlcyB0aGUgY29ycmVzcG9uZGluZyBBbmd1bGFyIGNvbXBvbmVudC5cbiAgICogSXQgaGFuZGxlcyBjb21wb25lbnQgaW5zdGFudGlhdGlvbiwgaW5wdXQgcHJvcGVydHkgbWFwcGluZywgYW5kIGNoaWxkIGNvbXBvbmVudCByZW5kZXJpbmcuXG4gICAqIFRoZSBtZXRob2QgdmFsaWRhdGVzIGlucHV0IHByb3BlcnRpZXMgYWdhaW5zdCB0aGUgY29tcG9uZW50J3MgbWV0YWRhdGEgYW5kIHByb2Nlc3Nlc1xuICAgKiBjaGlsZCBjb21wb25lbnRzIHJlY3Vyc2l2ZWx5LlxuICAgKlxuICAgKiBAcGFyYW0ge0ZpZWxkRGVmaW5pdGlvbjxBbmd1bGFyRmllbGREZWZpbml0aW9uPn0gZmllbGREZWYgLSBUaGUgZmllbGQgZGVmaW5pdGlvbiB0byBjb252ZXJ0XG4gICAqIEBwYXJhbSB7Vmlld0NvbnRhaW5lclJlZn0gdmNyIC0gVGhlIHZpZXcgY29udGFpbmVyIHJlZmVyZW5jZSBmb3IgY29tcG9uZW50IGNyZWF0aW9uXG4gICAqIEBwYXJhbSB7SW5qZWN0b3J9IGluamVjdG9yIC0gVGhlIEFuZ3VsYXIgaW5qZWN0b3IgZm9yIGRlcGVuZGVuY3kgaW5qZWN0aW9uXG4gICAqIEBwYXJhbSB7VGVtcGxhdGVSZWY8YW55Pn0gdHBsIC0gVGhlIHRlbXBsYXRlIHJlZmVyZW5jZSBmb3IgY29udGVudCBwcm9qZWN0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByZWdpc3RyeUZvcm1JZCAtIEZvcm0gaWRlbnRpZmllciBmb3IgdGhlIGNvbXBvbmVudCByZW5kZXJlclxuICAgKiBAcmV0dXJuIHtBbmd1bGFyRHluYW1pY091dHB1dH0gVGhlIEFuZ3VsYXIgY29tcG9uZW50IG91dHB1dCB3aXRoIGNvbXBvbmVudCByZWZlcmVuY2UgYW5kIGlucHV0c1xuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBNZXRob2QgYXMgZnJvbUZpZWxkRGVmaW5pdGlvblxuICAgKiAgIHBhcnRpY2lwYW50IENvbXBvbmVudHMgYXMgTmd4UmVuZGVyaW5nRW5naW5lLmNvbXBvbmVudHNcbiAgICogICBwYXJ0aWNpcGFudCBBbmd1bGFyIGFzIEFuZ3VsYXIgQ29yZVxuICAgKiAgIHBhcnRpY2lwYW50IFByb2Nlc3MgYXMgcHJvY2Vzc0NoaWxkXG4gICAqXG4gICAqICAgTWV0aG9kLT4+Q29tcG9uZW50czogY29tcG9uZW50cyhmaWVsZERlZi50YWcpXG4gICAqICAgQ29tcG9uZW50cy0tPj5NZXRob2Q6IGNvbXBvbmVudCBjb25zdHJ1Y3RvclxuICAgKiAgIE1ldGhvZC0+PkFuZ3VsYXI6IHJlZmxlY3RDb21wb25lbnRUeXBlKGNvbXBvbmVudClcbiAgICogICBBbmd1bGFyLS0+Pk1ldGhvZDogY29tcG9uZW50TWV0YWRhdGFcbiAgICogICBNZXRob2QtPj5NZXRob2Q6IFZhbGlkYXRlIGlucHV0IHByb3BlcnRpZXNcbiAgICogICBNZXRob2QtPj5NZXRob2Q6IENyZWF0ZSByZXN1bHQgb2JqZWN0XG4gICAqICAgYWx0IEhhcyBjaGlsZHJlblxuICAgKiAgICAgTWV0aG9kLT4+UHJvY2VzczogUHJvY2VzcyBjaGlsZHJlbiByZWN1cnNpdmVseVxuICAgKiAgICAgUHJvY2Vzcy0+Pk1ldGhvZDogUmV0dXJuIHByb2Nlc3NlZCBjaGlsZHJlblxuICAgKiAgICAgTWV0aG9kLT4+QW5ndWxhcjogQ3JlYXRlIGVtYmVkZGVkIHZpZXdcbiAgICogICAgIE1ldGhvZC0+Pk1ldGhvZDogQ3JlYXRlIGNvbXBvbmVudCBpbnN0YW5jZVxuICAgKiAgIGVuZFxuICAgKiAgIE1ldGhvZC0tPj5DYWxsZXI6IHJldHVybiBBbmd1bGFyRHluYW1pY091dHB1dFxuICAgKi9cbiAgcHJpdmF0ZSBmcm9tRmllbGREZWZpbml0aW9uKFxuICAgIGZpZWxkRGVmOiBGaWVsZERlZmluaXRpb248QW5ndWxhckZpZWxkRGVmaW5pdGlvbj4sXG4gICAgdmNyOiBWaWV3Q29udGFpbmVyUmVmLFxuICAgIGluamVjdG9yOiBJbmplY3RvcixcbiAgICB0cGw6IFRlbXBsYXRlUmVmPHVua25vd24+LFxuICAgIHJlZ2lzdHJ5Rm9ybUlkOiBzdHJpbmcgPSBEYXRlLm5vdygpLnRvU3RyaW5nKDM2KS50b1VwcGVyQ2FzZSgpLFxuICApOiBBbmd1bGFyRHluYW1pY091dHB1dCB7XG4gICAgY29uc3QgY21wID0gKGZpZWxkRGVmIGFzIEtleVZhbHVlKT8uWydjb21wb25lbnQnXSB8fCBOZ3hSZW5kZXJpbmdFbmdpbmUuY29tcG9uZW50cyhmaWVsZERlZi50YWcpO1xuICAgIGNvbnN0IGNvbXBvbmVudCA9IGNtcC5jb25zdHJ1Y3RvciBhcyB1bmtub3duIGFzIFR5cGU8dW5rbm93bj47XG5cbiAgICBjb25zdCBjb21wb25lbnRNZXRhZGF0YSA9IHJlZmxlY3RDb21wb25lbnRUeXBlKGNvbXBvbmVudCk7XG4gICAgaWYgKCFjb21wb25lbnRNZXRhZGF0YSkge1xuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYE1ldGFkYXRhIGZvciBjb21wb25lbnQgJHtmaWVsZERlZi50YWd9IG5vdCBmb3VuZC5gKTtcbiAgICB9XG5cbiAgICBjb25zdCB7IGlucHV0czogcG9zc2libGVJbnB1dHMgfSA9IGNvbXBvbmVudE1ldGFkYXRhO1xuICAgIGNvbnN0IGlucHV0cyA9IHsgLi4uZmllbGREZWYucHJvcHMgfTtcblxuICAgIGNvbnN0IHVubWFwcGVkS2V5cyA9IE9iamVjdC5rZXlzKGlucHV0cykuZmlsdGVyKGlucHV0ID0+IHtcbiAgICAgIGNvbnN0IGlzTWFwcGVkID0gcG9zc2libGVJbnB1dHMuZmluZCgoeyBwcm9wTmFtZSB9KSA9PiBwcm9wTmFtZSA9PT0gaW5wdXQpO1xuICAgICAgaWYgKCFpc01hcHBlZCkgZGVsZXRlIGlucHV0c1tpbnB1dF07XG4gICAgICByZXR1cm4gIWlzTWFwcGVkO1xuICAgIH0pO1xuXG4gICAgaWYgKHVubWFwcGVkS2V5cy5sZW5ndGggPiAwICYmIGlzRGV2ZWxvcG1lbnRNb2RlKCkpXG4gICAgICBjb25zb2xlLndhcm4oYFVubWFwcGVkIGlucHV0IHByb3BlcnRpZXMgZm9yIGNvbXBvbmVudCAke2ZpZWxkRGVmLnRhZ306ICR7dW5tYXBwZWRLZXlzLmpvaW4oJywgJyl9YCk7XG5cbiAgICBjb25zdCBvcGVyYXRpb24gPSBOZ3hSZW5kZXJpbmdFbmdpbmUuX29wZXJhdGlvbjtcblxuICAgIGNvbnN0IGhpZGRlbk9uID0gaW5wdXRzPy5oaWRkZW4gfHwgW107XG4gICAgaWYoKGhpZGRlbk9uIGFzIHN0cmluZ1tdKS5pbmNsdWRlcyhvcGVyYXRpb24gYXMgc3RyaW5nKSlcbiAgICAgIHJldHVybiB7aW5wdXRzLCBpbmplY3Rvcn07XG5cbiAgICBjb25zdCByZXN1bHQ6IEFuZ3VsYXJEeW5hbWljT3V0cHV0ID0ge1xuICAgICAgY29tcG9uZW50LFxuICAgICAgaW5wdXRzLFxuICAgICAgaW5qZWN0b3IsXG4gICAgfTtcblxuICAgIGlmIChmaWVsZERlZi5yZW5kZXJlcklkKVxuICAgICAgKHJlc3VsdC5pbnB1dHMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pWydyZW5kZXJlcklkJ10gPSBmaWVsZERlZi5yZW5kZXJlcklkO1xuXG4gICAgLy8gcHJvY2VzcyBjaGlsZHJlblxuICAgIGlmIChmaWVsZERlZi5jaGlsZHJlbj8ubGVuZ3RoKSB7XG4gICAgICBpZighTmd4UmVuZGVyaW5nRW5naW5lLl9wYXJlbnRQcm9wcyAmJiBpbnB1dHM/LnBhZ2VzKVxuICAgICAgICBOZ3hSZW5kZXJpbmdFbmdpbmUuX3BhcmVudFByb3BzID0ge3BhZ2VzOiBpbnB1dHM/LnBhZ2VzfTtcbiAgICAgIHJlc3VsdC5jaGlsZHJlbiA9IGZpZWxkRGVmLmNoaWxkcmVuLm1hcCgoY2hpbGQpID0+IHtcbiAgICAgICAgaWYoY2hpbGQ/LmNoaWxkcmVuPy5sZW5ndGgpIHtcbiAgICAgICAgICBjaGlsZC5jaGlsZHJlbiA9IGNoaWxkLmNoaWxkcmVuLmZpbHRlcihjID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGhpZGRlbk9uID0gYz8ucHJvcHM/LmhpZGRlbiB8fCBbXTtcbiAgICAgICAgICAgIGlmKCEoaGlkZGVuT24gYXMgc3RyaW5nW10pLmluY2x1ZGVzKG9wZXJhdGlvbiBhcyBzdHJpbmcpKVxuICAgICAgICAgICAgICByZXR1cm4gY1xuICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICAgICAgTmd4Rm9ybVNlcnZpY2UuYWRkQ29udHJvbEZyb21Qcm9wcyhyZWdpc3RyeUZvcm1JZCwgY2hpbGQucHJvcHMsIHsuLi5pbnB1dHMsIC4uLk5neFJlbmRlcmluZ0VuZ2luZS5fcGFyZW50UHJvcHMgfHwge319KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZnJvbUZpZWxkRGVmaW5pdGlvbihjaGlsZCwgdmNyLCBpbmplY3RvciwgdHBsLCByZWdpc3RyeUZvcm1JZCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBnZW5lcmF0aW5nIERPTVxuICAgIGNvbnN0IHByb2plY3RhYmxlID0gTmd4UmVuZGVyaW5nRW5naW5lLl9wcm9qZWN0YWJsZTtcbiAgICB2Y3IuY2xlYXIoKTtcbiAgICBjb25zdCB0ZW1wbGF0ZSA9ICFwcm9qZWN0YWJsZSA/IFtdIDogdmNyLmNyZWF0ZUVtYmVkZGVkVmlldyh0cGwsIGluamVjdG9yKS5yb290Tm9kZXM7XG4gICAgY29uc3QgaGFzQ2hpbGRyZW4gPSBPYmplY3QudmFsdWVzKHBvc3NpYmxlSW5wdXRzKS5zb21lKCh7cHJvcE5hbWV9KSA9PiBwcm9wTmFtZSA9PT0gJ2NoaWxkcmVuJyk7XG4gICAgY29uc3QgaGFzTW9kZWwgPSBPYmplY3QudmFsdWVzKHBvc3NpYmxlSW5wdXRzKS5zb21lKCh7cHJvcE5hbWV9KSA9PiBwcm9wTmFtZSA9PT0gJ2NoaWxkcmVuJyk7XG4gICAgY29uc3QgY29tcG9uZW50SW5wdXRzID0gIE9iamVjdC5hc3NpZ24oaW5wdXRzLFxuICAgICAgICAoIGhhc01vZGVsID8geyBtb2RlbDogdGhpcy5fbW9kZWwgfSA6IHsgfSksXG4gICAgICAgICggaGFzQ2hpbGRyZW4gPyB7IGNoaWxkcmVuOiBmaWVsZERlZj8uWydjaGlsZHJlbiddIHx8IFtdIH0gOiB7fSkpO1xuICAgIGNvbnN0IGNvbXBvbmVudEluc3RhbmNlID0gTmd4UmVuZGVyaW5nRW5naW5lLmNyZWF0ZUNvbXBvbmVudChcbiAgICAgIGNvbXBvbmVudCxcbiAgICAgIGNvbXBvbmVudElucHV0cyxcbiAgICAgIGNvbXBvbmVudE1ldGFkYXRhLFxuICAgICAgdmNyLFxuICAgICAgaW5qZWN0b3IsXG4gICAgICB0ZW1wbGF0ZSxcbiAgICApO1xuICAgIHJlc3VsdC5pbnN0YW5jZSA9IE5neFJlbmRlcmluZ0VuZ2luZS5faW5zdGFuY2UgPSBjb21wb25lbnRJbnN0YW5jZS5pbnN0YW5jZSBhcyBUeXBlPHVua25vd24+O1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhbiBBbmd1bGFyIGNvbXBvbmVudCBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBUaGlzIHN0YXRpYyB1dGlsaXR5IG1ldGhvZCBjcmVhdGVzIGFuIEFuZ3VsYXIgY29tcG9uZW50IGluc3RhbmNlIHdpdGggdGhlIHNwZWNpZmllZFxuICAgKiBpbnB1dHMgYW5kIHRlbXBsYXRlLiBJdCB1c2VzIEFuZ3VsYXIncyBjb21wb25lbnQgY3JlYXRpb24gQVBJIHRvIGluc3RhbnRpYXRlIHRoZSBjb21wb25lbnRcbiAgICogYW5kIHRoZW4gc2V0cyB0aGUgaW5wdXQgcHJvcGVydGllcyB1c2luZyB0aGUgcHJvdmlkZWQgbWV0YWRhdGEuXG4gICAqXG4gICAqIEBwYXJhbSB7VHlwZTx1bmtub3duPn0gY29tcG9uZW50IC0gVGhlIGNvbXBvbmVudCB0eXBlIHRvIGNyZWF0ZVxuICAgKiBAcGFyYW0ge0tleVZhbHVlfSBbaW5wdXRzPXt9XSAtIFRoZSBpbnB1dCBwcm9wZXJ0aWVzIHRvIHNldCBvbiB0aGUgY29tcG9uZW50XG4gICAqIEBwYXJhbSB7Q29tcG9uZW50TWlycm9yPHVua25vd24+fSBtZXRhZGF0YSAtIFRoZSBjb21wb25lbnQgbWV0YWRhdGEgZm9yIGlucHV0IHZhbGlkYXRpb25cbiAgICogQHBhcmFtIHtWaWV3Q29udGFpbmVyUmVmfSB2Y3IgLSBUaGUgdmlldyBjb250YWluZXIgcmVmZXJlbmNlIGZvciBjb21wb25lbnQgY3JlYXRpb25cbiAgICogQHBhcmFtIHtJbmplY3Rvcn0gaW5qZWN0b3IgLSBUaGUgQW5ndWxhciBpbmplY3RvciBmb3IgZGVwZW5kZW5jeSBpbmplY3Rpb25cbiAgICogQHBhcmFtIHtOb2RlW119IFt0ZW1wbGF0ZT1bXV0gLSBUaGUgdGVtcGxhdGUgbm9kZXMgdG8gcHJvamVjdCBpbnRvIHRoZSBjb21wb25lbnRcbiAgICogQHJldHVybiB7Q29tcG9uZW50UmVmPHVua25vd24+fSBUaGUgY3JlYXRlZCBjb21wb25lbnQgcmVmZXJlbmNlXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlQ29tcG9uZW50KGNvbXBvbmVudDogVHlwZTx1bmtub3duPiwgaW5wdXRzOiBLZXlWYWx1ZSA9IHt9LCBtZXRhZGF0YTogQ29tcG9uZW50TWlycm9yPHVua25vd24+LCB2Y3I6IFZpZXdDb250YWluZXJSZWYsIGluamVjdG9yOiBJbmplY3RvciwgdGVtcGxhdGU6IE5vZGVbXSA9IFtdKTogQ29tcG9uZW50UmVmPHVua25vd24+IHtcbiAgICBjb25zdCBjb21wb25lbnRJbnN0YW5jZSA9IHZjci5jcmVhdGVDb21wb25lbnQoY29tcG9uZW50IGFzIFR5cGU8dW5rbm93bj4sIHtcbiAgICAgIGVudmlyb25tZW50SW5qZWN0b3I6IGluamVjdG9yIGFzIEVudmlyb25tZW50SW5qZWN0b3IsXG4gICAgICBwcm9qZWN0YWJsZU5vZGVzOiBbdGVtcGxhdGVdLFxuICAgIH0pO1xuICAgIHRoaXMuc2V0SW5wdXRzKGNvbXBvbmVudEluc3RhbmNlLCBpbnB1dHMsIG1ldGFkYXRhKTtcbiAgICByZXR1cm4gY29tcG9uZW50SW5zdGFuY2U7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV4dHJhY3RzIGRlY29yYXRvciBtZXRhZGF0YSBmcm9tIGEgbW9kZWxcbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgcHJvdmlkZXMgYWNjZXNzIHRvIHRoZSBmaWVsZCBkZWZpbml0aW9uIGdlbmVyYXRlZCBmcm9tIGEgbW9kZWwnc1xuICAgKiBkZWNvcmF0b3JzLiBJdCdzIGEgY29udmVuaWVuY2Ugd3JhcHBlciBhcm91bmQgdGhlIHRvRmllbGREZWZpbml0aW9uIG1ldGhvZCB0aGF0XG4gICAqIGNvbnZlcnRzIGEgbW9kZWwgdG8gYSBmaWVsZCBkZWZpbml0aW9uIGJhc2VkIG9uIGl0cyBkZWNvcmF0b3JzIGFuZCB0aGUgcHJvdmlkZWRcbiAgICogZ2xvYmFsIHByb3BlcnRpZXMuXG4gICAqXG4gICAqIEBwYXJhbSB7TW9kZWx9IG1vZGVsIC0gVGhlIG1vZGVsIHRvIGV4dHJhY3QgZGVjb3JhdG9ycyBmcm9tXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgdW5rbm93bj59IGdsb2JhbFByb3BzIC0gR2xvYmFsIHByb3BlcnRpZXMgdG8gaW5jbHVkZSBpbiB0aGUgZmllbGQgZGVmaW5pdGlvblxuICAgKiBAcmV0dXJuIHtGaWVsZERlZmluaXRpb248QW5ndWxhckZpZWxkRGVmaW5pdGlvbj59IFRoZSBmaWVsZCBkZWZpbml0aW9uIGdlbmVyYXRlZCBmcm9tIHRoZSBtb2RlbFxuICAgKi9cbiAgZ2V0RGVjb3JhdG9ycyhtb2RlbDogTW9kZWwsIGdsb2JhbFByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEZpZWxkRGVmaW5pdGlvbjxBbmd1bGFyRmllbGREZWZpbml0aW9uPiB7XG4gICAgcmV0dXJuIHRoaXMudG9GaWVsZERlZmluaXRpb24obW9kZWwsIGdsb2JhbFByb3BzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGVzdHJveXMgdGhlIGN1cnJlbnQgZW5naW5lIGluc3RhbmNlXG4gICAqIEBzdW1tYXJ5IFRoaXMgc3RhdGljIG1ldGhvZCBjbGVhcnMgdGhlIGN1cnJlbnQgaW5zdGFuY2UgcmVmZXJlbmNlLCBlZmZlY3RpdmVseVxuICAgKiBkZXN0cm95aW5nIHRoZSBzaW5nbGV0b24gaW5zdGFuY2Ugb2YgdGhlIHJlbmRlcmluZyBlbmdpbmUuIFRoaXMgY2FuIGJlIHVzZWRcbiAgICogdG8gcmVzZXQgdGhlIGVuZ2luZSBzdGF0ZSBvciB0byBwcmVwYXJlIGZvciBhIG5ldyBpbnN0YW5jZSBjcmVhdGlvbi5cbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgaW5zdGFuY2UgaXMgZGVzdHJveWVkXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZGVzdHJveShmb3JtSWQ/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZihmb3JtSWQpXG4gICAgICBOZ3hGb3JtU2VydmljZS5yZW1vdmVSZWdpc3RyeShmb3JtSWQpO1xuICAgIE5neFJlbmRlcmluZ0VuZ2luZS5faW5zdGFuY2UgPSB1bmRlZmluZWQ7XG4gICAgTmd4UmVuZGVyaW5nRW5naW5lLl9wYXJlbnRQcm9wcyA9IHVuZGVmaW5lZDtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZW5kZXJzIGEgbW9kZWwgaW50byBhbiBBbmd1bGFyIGNvbXBvbmVudCBvdXRwdXRcbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgdGFrZXMgYSBtb2RlbCBhbmQgY29udmVydHMgaXQgdG8gYW4gQW5ndWxhciBjb21wb25lbnQgb3V0cHV0LlxuICAgKiBJdCBmaXJzdCBzdG9yZXMgYSByZWZlcmVuY2UgdG8gdGhlIG1vZGVsLCB0aGVuIGNvbnZlcnRzIGl0IHRvIGEgZmllbGQgZGVmaW5pdGlvblxuICAgKiB1c2luZyB0aGUgYmFzZSBSZW5kZXJpbmdFbmdpbmUncyB0b0ZpZWxkRGVmaW5pdGlvbiBtZXRob2QsIGFuZCBmaW5hbGx5IGNvbnZlcnRzXG4gICAqIHRoYXQgZmllbGQgZGVmaW5pdGlvbiB0byBhbiBBbmd1bGFyIGNvbXBvbmVudCBvdXRwdXQgdXNpbmcgZnJvbUZpZWxkRGVmaW5pdGlvbi5cbiAgICpcbiAgICogQHRlbXBsYXRlIE0gLSBUeXBlIGV4dGVuZGluZyBNb2RlbFxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIHRvIHJlbmRlclxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIHVua25vd24+fSBnbG9iYWxQcm9wcyAtIEdsb2JhbCBwcm9wZXJ0aWVzIHRvIHBhc3MgdG8gdGhlIGNvbXBvbmVudFxuICAgKiBAcGFyYW0ge1ZpZXdDb250YWluZXJSZWZ9IHZjciAtIFRoZSB2aWV3IGNvbnRhaW5lciByZWZlcmVuY2UgZm9yIGNvbXBvbmVudCBjcmVhdGlvblxuICAgKiBAcGFyYW0ge0luamVjdG9yfSBpbmplY3RvciAtIFRoZSBBbmd1bGFyIGluamVjdG9yIGZvciBkZXBlbmRlbmN5IGluamVjdGlvblxuICAgKiBAcGFyYW0ge1RlbXBsYXRlUmVmPGFueT59IHRwbCAtIFRoZSB0ZW1wbGF0ZSByZWZlcmVuY2UgZm9yIGNvbnRlbnQgcHJvamVjdGlvblxuICAgKiBAcmV0dXJuIHtBbmd1bGFyRHluYW1pY091dHB1dH0gVGhlIEFuZ3VsYXIgY29tcG9uZW50IG91dHB1dCB3aXRoIGNvbXBvbmVudCByZWZlcmVuY2UgYW5kIGlucHV0c1xuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDbGllbnQgYXMgQ2xpZW50IENvZGVcbiAgICogICBwYXJ0aWNpcGFudCBSZW5kZXIgYXMgcmVuZGVyIG1ldGhvZFxuICAgKiAgIHBhcnRpY2lwYW50IFRvRmllbGQgYXMgdG9GaWVsZERlZmluaXRpb25cbiAgICogICBwYXJ0aWNpcGFudCBGcm9tRmllbGQgYXMgZnJvbUZpZWxkRGVmaW5pdGlvblxuICAgKlxuICAgKiAgIENsaWVudC0+PlJlbmRlcjogcmVuZGVyKG1vZGVsLCBnbG9iYWxQcm9wcywgdmNyLCBpbmplY3RvciwgdHBsKVxuICAgKiAgIFJlbmRlci0+PlJlbmRlcjogU3RvcmUgbW9kZWwgcmVmZXJlbmNlXG4gICAqICAgUmVuZGVyLT4+VG9GaWVsZDogdG9GaWVsZERlZmluaXRpb24obW9kZWwsIGdsb2JhbFByb3BzKVxuICAgKiAgIFRvRmllbGQtLT4+UmVuZGVyOiBmaWVsZERlZlxuICAgKiAgIFJlbmRlci0+PkZyb21GaWVsZDogZnJvbUZpZWxkRGVmaW5pdGlvbihmaWVsZERlZiwgdmNyLCBpbmplY3RvciwgdHBsKVxuICAgKiAgIEZyb21GaWVsZC0tPj5SZW5kZXI6IEFuZ3VsYXJEeW5hbWljT3V0cHV0XG4gICAqICAgUmVuZGVyLS0+PkNsaWVudDogcmV0dXJuIEFuZ3VsYXJEeW5hbWljT3V0cHV0XG4gICAqL1xuICBvdmVycmlkZSByZW5kZXI8TSBleHRlbmRzIE1vZGVsPihcbiAgICBtb2RlbDogTSxcbiAgICBnbG9iYWxQcm9wczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgdmNyOiBWaWV3Q29udGFpbmVyUmVmLFxuICAgIGluamVjdG9yOiBJbmplY3RvcixcbiAgICB0cGw6IFRlbXBsYXRlUmVmPHVua25vd24+LFxuICAgIHByb2plY3RhYmxlOiBib29sZWFuID0gdHJ1ZSxcbiAgKTogQW5ndWxhckR5bmFtaWNPdXRwdXQge1xuICAgIGxldCByZXN1bHQ6IEFuZ3VsYXJEeW5hbWljT3V0cHV0O1xuICAgIHRyeSB7XG5cbiAgICAgIHRoaXMuX21vZGVsID0gbW9kZWw7XG4gICAgICBOZ3hSZW5kZXJpbmdFbmdpbmUuX3Byb2plY3RhYmxlID0gcHJvamVjdGFibGU7XG5cbiAgICAgIGNvbnN0IGZvcm1JZCA9IERhdGUubm93KCkudG9TdHJpbmcoMzYpLnRvVXBwZXJDYXNlKCk7XG4gICAgICBjb25zdCBmaWVsZERlZiA9IHRoaXMudG9GaWVsZERlZmluaXRpb24obW9kZWwsIGdsb2JhbFByb3BzKTtcbiAgICAgIGNvbnN0IHByb3BzID0gZmllbGREZWYucHJvcHMgYXMgS2V5VmFsdWU7XG4gICAgICBpZighTmd4UmVuZGVyaW5nRW5naW5lLl9vcGVyYXRpb24pXG4gICAgICAgIE5neFJlbmRlcmluZ0VuZ2luZS5fb3BlcmF0aW9uID0gcHJvcHM/Llsnb3BlcmF0aW9uJ10gfHwgdW5kZWZpbmVkO1xuICAgICAgY29uc3QgZm9ybUdyb3VwICA9IE5neEZvcm1TZXJ2aWNlLmNyZWF0ZUZvcm0oZm9ybUlkLCBwcm9wcyk7XG4gICAgICByZXN1bHQgPSB0aGlzLmZyb21GaWVsZERlZmluaXRpb24oZmllbGREZWYsIHZjciwgaW5qZWN0b3IsIHRwbCwgZm9ybUlkKTtcblxuICAgICAgKHJlc3VsdCEuaW5zdGFuY2UhIGFzIEtleVZhbHVlKVsnZm9ybUdyb3VwJ10gPSBmb3JtR3JvdXA7XG4gICAgICBOZ3hSZW5kZXJpbmdFbmdpbmUuZGVzdHJveShmb3JtSWQpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICBgRmFpbGVkIHRvIHJlbmRlciBNb2RlbCAke21vZGVsLmNvbnN0cnVjdG9yLm5hbWV9OiAke2V9YCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgdGhlIHJlbmRlcmluZyBlbmdpbmVcbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgaW5pdGlhbGl6ZXMgdGhlIHJlbmRlcmluZyBlbmdpbmUuIEl0IGNoZWNrcyBpZiB0aGUgZW5naW5lIGlzIGFscmVhZHkgaW5pdGlhbGl6ZWRcbiAgICogYW5kIHNldHMgdGhlIGluaXRpYWxpemVkIGZsYWcgdG8gdHJ1ZS4gVGhpcyBtZXRob2QgaXMgY2FsbGVkIGJlZm9yZSB0aGUgZW5naW5lIGlzIHVzZWRcbiAgICogdG8gZW5zdXJlIGl0J3MgcHJvcGVybHkgc2V0IHVwIGZvciByZW5kZXJpbmcgb3BlcmF0aW9ucy5cbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBpbml0aWFsaXphdGlvbiBpcyBjb21wbGV0ZVxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgaW5pdGlhbGl6ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5pbml0aWFsaXplZClcbiAgICAgIHJldHVybjtcbiAgICAvLyBWYWxpZGF0YWJsZUJ5VHlwZVtdXG4gICAgdGhpcy5pbml0aWFsaXplZCA9IHRydWU7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlZ2lzdGVycyBhIGNvbXBvbmVudCB3aXRoIHRoZSByZW5kZXJpbmcgZW5naW5lXG4gICAqIEBzdW1tYXJ5IFRoaXMgc3RhdGljIG1ldGhvZCByZWdpc3RlcnMgYSBjb21wb25lbnQgY29uc3RydWN0b3Igd2l0aCB0aGUgcmVuZGVyaW5nIGVuZ2luZVxuICAgKiB1bmRlciBhIHNwZWNpZmljIG5hbWUuIEl0IGluaXRpYWxpemVzIHRoZSBjb21wb25lbnRzIHJlZ2lzdHJ5IGlmIG5lZWRlZCBhbmQgdGhyb3dzXG4gICAqIGFuIGVycm9yIGlmIGEgY29tcG9uZW50IGlzIGFscmVhZHkgcmVnaXN0ZXJlZCB1bmRlciB0aGUgc2FtZSBuYW1lIHRvIHByZXZlbnRcbiAgICogYWNjaWRlbnRhbCBvdmVycmlkZXMuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIG5hbWUgdG8gcmVnaXN0ZXIgdGhlIGNvbXBvbmVudCB1bmRlclxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPHVua25vd24+fSBjb25zdHJ1Y3RvciAtIFRoZSBjb21wb25lbnQgY29uc3RydWN0b3JcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIHN0YXRpYyByZWdpc3RlckNvbXBvbmVudChuYW1lOiBzdHJpbmcsIGNvbnN0cnVjdG9yOiBDb25zdHJ1Y3Rvcjx1bmtub3duPik6IHZvaWQge1xuICAgIGlmICghdGhpcy5fY29tcG9uZW50cykgdGhpcy5fY29tcG9uZW50cyA9IHt9O1xuICAgIGlmIChuYW1lIGluIHRoaXMuX2NvbXBvbmVudHMpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgQ29tcG9uZW50IGFscmVhZHkgcmVnaXN0ZXJlZCB1bmRlciAke25hbWV9YCk7XG4gICAgdGhpcy5fY29tcG9uZW50c1tuYW1lXSA9IHtcbiAgICAgIGNvbnN0cnVjdG9yOiBjb25zdHJ1Y3RvcixcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgcmVnaXN0ZXJlZCBjb21wb25lbnRzIGZyb20gdGhlIHJlbmRlcmluZyBlbmdpbmVcbiAgICogQHN1bW1hcnkgVGhpcyBzdGF0aWMgbWV0aG9kIHJldHJpZXZlcyBlaXRoZXIgYWxsIHJlZ2lzdGVyZWQgY29tcG9uZW50cyBvciBhIHNwZWNpZmljIGNvbXBvbmVudFxuICAgKiBieSBpdHMgc2VsZWN0b3IuIFdoZW4gY2FsbGVkIHdpdGhvdXQgYSBzZWxlY3RvciwgaXQgcmV0dXJucyBhbiBhcnJheSBvZiBhbGwgcmVnaXN0ZXJlZFxuICAgKiBjb21wb25lbnRzLiBXaGVuIGNhbGxlZCB3aXRoIGEgc2VsZWN0b3IsIGl0IHJldHVybnMgdGhlIHNwZWNpZmljIGNvbXBvbmVudCBpZiBmb3VuZCxcbiAgICogb3IgdGhyb3dzIGFuIGVycm9yIGlmIHRoZSBjb21wb25lbnQgaXMgbm90IHJlZ2lzdGVyZWQuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbc2VsZWN0b3JdIC0gT3B0aW9uYWwgc2VsZWN0b3IgdG8gcmV0cmlldmUgYSBzcGVjaWZpYyBjb21wb25lbnRcbiAgICogQHJldHVybiB7T2JqZWN0fEFycmF5fSBFaXRoZXIgYSBzcGVjaWZpYyBjb21wb25lbnQgb3IgYW4gYXJyYXkgb2YgYWxsIGNvbXBvbmVudHNcbiAgICovXG4gIHN0YXRpYyBjb21wb25lbnRzKHNlbGVjdG9yPzogc3RyaW5nKTogb2JqZWN0IHwgc3RyaW5nW10ge1xuICAgIGlmICghc2VsZWN0b3IpIHJldHVybiBPYmplY3QudmFsdWVzKHRoaXMuX2NvbXBvbmVudHMpO1xuICAgIGlmICghKHNlbGVjdG9yIGluIHRoaXMuX2NvbXBvbmVudHMpKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYE5vIENvbXBvbmVudCByZWdpc3RlcmVkIHVuZGVyICR7c2VsZWN0b3J9YCk7XG4gICAgcmV0dXJuIHRoaXMuX2NvbXBvbmVudHNbc2VsZWN0b3JdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZW5lcmF0ZXMgYSBrZXkgZm9yIHJlZmxlY3Rpb24gbWV0YWRhdGFcbiAgICogQHN1bW1hcnkgVGhpcyBzdGF0aWMgbWV0aG9kIGdlbmVyYXRlcyBhIGtleSBmb3IgcmVmbGVjdGlvbiBtZXRhZGF0YSBieSBwcmVmaXhpbmcgdGhlIGlucHV0IGtleVxuICAgKiB3aXRoIHRoZSBBbmd1bGFyIGVuZ2luZSdzIHJlZmxlY3Rpb24gcHJlZml4LiBUaGlzIGlzIHVzZWQgZm9yIHN0b3JpbmcgYW5kIHJldHJpZXZpbmdcbiAgICogbWV0YWRhdGEgaW4gYSBuYW1lc3BhY2VkIHdheSB0byBhdm9pZCBjb25mbGljdHMgd2l0aCBvdGhlciBtZXRhZGF0YS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSAtIFRoZSBiYXNlIGtleSB0byBwcmVmaXhcbiAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgcHJlZml4ZWQga2V5IGZvciByZWZsZWN0aW9uIG1ldGFkYXRhXG4gICAqL1xuICBzdGF0aWMgb3ZlcnJpZGUga2V5KGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7QW5ndWxhckVuZ2luZUtleXMuUkVGTEVDVH0ke2tleX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIGlucHV0IHByb3BlcnRpZXMgb24gYSBjb21wb25lbnQgaW5zdGFuY2VcbiAgICogQHN1bW1hcnkgVGhpcyBzdGF0aWMgdXRpbGl0eSBtZXRob2Qgc2V0cyBpbnB1dCBwcm9wZXJ0aWVzIG9uIGEgY29tcG9uZW50IGluc3RhbmNlXG4gICAqIGJhc2VkIG9uIHRoZSBwcm92aWRlZCBpbnB1dHMgb2JqZWN0IGFuZCBjb21wb25lbnQgbWV0YWRhdGEuIEl0IGhhbmRsZXMgYm90aCBzaW1wbGVcbiAgICogdmFsdWVzIGFuZCBuZXN0ZWQgb2JqZWN0cywgcmVjdXJzaXZlbHkgcHJvY2Vzc2luZyBvYmplY3QgcHJvcGVydGllcy4gVGhlIG1ldGhvZFxuICAgKiB2YWxpZGF0ZXMgZWFjaCBpbnB1dCBhZ2FpbnN0IHRoZSBjb21wb25lbnQncyBtZXRhZGF0YSB0byBlbnN1cmUgb25seSB2YWxpZCBpbnB1dHNcbiAgICogYXJlIHNldC5cbiAgICpcbiAgICogQHBhcmFtIHtDb21wb25lbnRSZWY8dW5rbm93bj59IGNvbXBvbmVudCAtIFRoZSBjb21wb25lbnQgcmVmZXJlbmNlIHRvIHNldCBpbnB1dHMgb25cbiAgICogQHBhcmFtIHtLZXlWYWx1ZX0gaW5wdXRzIC0gVGhlIGlucHV0IHByb3BlcnRpZXMgdG8gc2V0XG4gICAqIEBwYXJhbSB7Q29tcG9uZW50TWlycm9yPHVua25vd24+fSBtZXRhZGF0YSAtIFRoZSBjb21wb25lbnQgbWV0YWRhdGEgZm9yIGlucHV0IHZhbGlkYXRpb25cbiAgICogQHJldHVybiB7dm9pZH1cbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gICAqICAgcGFydGljaXBhbnQgU2V0SW5wdXRzIGFzIHNldElucHV0c1xuICAgKiAgIHBhcnRpY2lwYW50IFBhcnNlIGFzIHBhcnNlSW5wdXRWYWx1ZVxuICAgKiAgIHBhcnRpY2lwYW50IENvbXBvbmVudCBhcyBDb21wb25lbnRSZWZcbiAgICpcbiAgICogICBDYWxsZXItPj5TZXRJbnB1dHM6IHNldElucHV0cyhjb21wb25lbnQsIGlucHV0cywgbWV0YWRhdGEpXG4gICAqICAgU2V0SW5wdXRzLT4+U2V0SW5wdXRzOiBJdGVyYXRlIHRocm91Z2ggaW5wdXRzXG4gICAqICAgbG9vcCBGb3IgZWFjaCBpbnB1dFxuICAgKiAgICAgU2V0SW5wdXRzLT4+U2V0SW5wdXRzOiBDaGVjayBpZiBpbnB1dCBleGlzdHMgaW4gbWV0YWRhdGFcbiAgICogICAgIGFsdCBJbnB1dCBpcyAncHJvcHMnXG4gICAqICAgICAgIFNldElucHV0cy0+PlBhcnNlOiBwYXJzZUlucHV0VmFsdWUoY29tcG9uZW50LCB2YWx1ZSlcbiAgICogICAgICAgUGFyc2UtPj5QYXJzZTogUmVjdXJzaXZlbHkgcHJvY2VzcyBuZXN0ZWQgb2JqZWN0c1xuICAgKiAgICAgICBQYXJzZS0+PkNvbXBvbmVudDogc2V0SW5wdXQoa2V5LCB2YWx1ZSlcbiAgICogICAgIGVsc2UgSW5wdXQgaXMgdmFsaWRcbiAgICogICAgICAgU2V0SW5wdXRzLT4+Q29tcG9uZW50OiBzZXRJbnB1dChrZXksIHZhbHVlKVxuICAgKiAgICAgZW5kXG4gICAqICAgZW5kXG4gICAqL1xuICBzdGF0aWMgc2V0SW5wdXRzKGNvbXBvbmVudDogQ29tcG9uZW50UmVmPHVua25vd24+LCBpbnB1dHM6IEtleVZhbHVlLCBtZXRhZGF0YTogQ29tcG9uZW50TWlycm9yPHVua25vd24+KTogdm9pZCB7XG4gICAgZnVuY3Rpb24gcGFyc2VJbnB1dFZhbHVlKGNvbXBvbmVudDogQ29tcG9uZW50UmVmPHVua25vd24+LCBpbnB1dDogS2V5VmFsdWUpIHtcbiAgICAgIE9iamVjdC5rZXlzKGlucHV0KS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gaW5wdXRba2V5XTtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgISF2YWx1ZSlcbiAgICAgICAgICByZXR1cm4gcGFyc2VJbnB1dFZhbHVlKGNvbXBvbmVudCwgdmFsdWUpO1xuICAgICAgICBjb21wb25lbnQuc2V0SW5wdXQoa2V5LCB2YWx1ZSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBPYmplY3QuZW50cmllcyhpbnB1dHMpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgY29uc3QgcHJvcCA9IG1ldGFkYXRhLmlucHV0cy5maW5kKChpdGVtOiB7IHByb3BOYW1lOiBzdHJpbmcgfSkgPT4gaXRlbS5wcm9wTmFtZSA9PT0ga2V5KTtcbiAgICAgIGlmIChwcm9wKSB7XG4gICAgICAgIGlmIChrZXkgPT09ICdwcm9wcycpXG4gICAgICAgICAgcGFyc2VJbnB1dFZhbHVlKGNvbXBvbmVudCwgdmFsdWUpO1xuICAgICAgICAvLyBpZihrZXkgPT09ICdsb2NhbGUnICYmICF2YWx1ZSlcbiAgICAgICAgLy8gICB2YWx1ZSA9IGdldExvY2FsZUZyb21DbGFzc05hbWUodGhpcy5fY29tcG9uZW50TmFtZSk7XG4gICAgICAgIGNvbXBvbmVudC5zZXRJbnB1dChrZXksIHZhbHVlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuIl19
@@ -1,106 +0,0 @@
1
- import { FormControl, FormGroup } from '@angular/forms';
2
- import { ComparisonValidationKeys, DEFAULT_PATTERNS, PathProxyEngine, Validation, ValidationKeys, } from '@decaf-ts/decorator-validation';
3
- import { parseValueByType } from '@decaf-ts/ui-decorators';
4
- import { AngularEngineKeys } from './constants';
5
- import { NgxRenderingEngine } from './NgxRenderingEngine';
6
- /**
7
- *
8
- * Resolves the correct validator key and its associated properties based on the input key and type.
9
- *
10
- * When the validation key is TYPE, it's necessary to resolve the actual validator based on the
11
- * field's type (e.g., 'password', 'email', 'url') instead of using the generic getValidator("type") logic.
12
- * This allows directly invoking specific validators like getValidator('password'), ensuring the correct
13
- * behavior for type-based validation.
14
- *
15
- * @param key - The validation key (e.g., 'type', 'required', etc.).
16
- * @param value - The value that needs be provided to the validator.
17
- * @param type - The field's declared type.
18
- * @returns An object containing the resolved validator key and its corresponding props.
19
- */
20
- const resolveValidatorKeyProps = (key, value, type) => {
21
- const patternValidators = {
22
- [ValidationKeys.PASSWORD]: DEFAULT_PATTERNS.PASSWORD.CHAR8_ONE_OF_EACH,
23
- [ValidationKeys.EMAIL]: DEFAULT_PATTERNS.EMAIL,
24
- [ValidationKeys.URL]: DEFAULT_PATTERNS.URL,
25
- };
26
- const isTypeBased = key === ValidationKeys.TYPE && Object.keys(patternValidators).includes(type);
27
- const validatorKey = isTypeBased ? type : key;
28
- const props = {
29
- // [validatorKey]: (!isTypeBased && key === 'type') ? parseType(type) : value,
30
- [validatorKey]: (!isTypeBased && validatorKey === ValidationKeys.TYPE) ? NgxRenderingEngine.get().translate(value, false) : value,
31
- // Email, Password, and URL are validated using the "pattern" key
32
- ...(isTypeBased && { [ValidationKeys.PATTERN]: patternValidators[type] }),
33
- };
34
- return { validatorKey, props };
35
- };
36
- export class ValidatorFactory {
37
- static spawn(fieldProps, key) {
38
- if (!Validation.keys().includes(key))
39
- throw new Error('Unsupported custom validation');
40
- const validatorFn = (control) => {
41
- const { type } = fieldProps;
42
- const { validatorKey, props } = resolveValidatorKeyProps(key, fieldProps[key], type);
43
- const validator = Validation.get(validatorKey);
44
- // parseValueByType does not support undefined values
45
- const value = typeof control.value !== 'undefined'
46
- ? parseValueByType(type, control.value, fieldProps)
47
- : undefined;
48
- // Create a proxy to enable access to parent and child values
49
- let proxy = ValidatorFactory.createProxy({});
50
- if (Object.values(ComparisonValidationKeys).includes(key)) {
51
- const parent = control instanceof FormGroup ? control : control[AngularEngineKeys.PARENT];
52
- proxy = ValidatorFactory.createProxy(parent);
53
- }
54
- let errs;
55
- try {
56
- if (!props['types'] && !props['customTypes'])
57
- props['types'] = props['type'];
58
- errs = validator.hasErrors(value, props, proxy);
59
- }
60
- catch (e) {
61
- errs = `${key} validator failed to validate: ${e}`;
62
- console.warn(errs);
63
- }
64
- return errs ? { [validatorKey]: true } : null;
65
- };
66
- Object.defineProperty(validatorFn, 'name', {
67
- value: `${key}Validator`,
68
- });
69
- return validatorFn;
70
- }
71
- /**
72
- * @summary Creates a proxy wrapper for an Angular AbstractControl to assist with custom validation logic.
73
- * @description Returns a structured proxy object that simulates a hierarchical tree of form values.
74
- * Enables Validators handling method to access parent and child properties using consistent dot-notation in Angular forms.
75
- *
76
- * @param {AbstractControl} control - The control to wrap in a proxy.
77
- * @returns {PathProxy<unknown>} A proxy object exposing form values and enabling recursive parent access.
78
- */
79
- static createProxy(control) {
80
- return PathProxyEngine.create(control, {
81
- getValue(target, prop) {
82
- if (target instanceof FormControl)
83
- return target.value;
84
- if (target instanceof FormGroup) {
85
- const control = target.controls[prop];
86
- return control instanceof FormControl ? control.value : control;
87
- }
88
- // const value = target[prop];
89
- // if (value instanceof FormControl)
90
- // return value.value;
91
- //
92
- // if (value instanceof FormGroup) {
93
- // const control = value.controls[prop];
94
- // return control instanceof FormControl ? control.value : control;
95
- // }
96
- return target?.[prop];
97
- },
98
- getParent: function (target) {
99
- return target?.['_parent'];
100
- },
101
- ignoreUndefined: true,
102
- ignoreNull: true,
103
- });
104
- }
105
- }
106
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVmFsaWRhdG9yRmFjdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvZW5naW5lL1ZhbGlkYXRvckZhY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFtQixXQUFXLEVBQUUsU0FBUyxFQUFpQyxNQUFNLGdCQUFnQixDQUFDO0FBQ3hHLE9BQU8sRUFDTCx3QkFBd0IsRUFDeEIsZ0JBQWdCLEVBRWhCLGVBQWUsRUFDZixVQUFVLEVBQ1YsY0FBYyxHQUVmLE1BQU0sZ0NBQWdDLENBQUM7QUFDeEMsT0FBTyxFQUFtQixnQkFBZ0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzVFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVoRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUsxRDs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsTUFBTSx3QkFBd0IsR0FBRyxDQUFDLEdBQVcsRUFBRSxLQUFjLEVBQUUsSUFBWSxFQUd6RSxFQUFFO0lBQ0YsTUFBTSxpQkFBaUIsR0FBNEI7UUFDakQsQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLEVBQUUsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLGlCQUFpQjtRQUN0RSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsRUFBRSxnQkFBZ0IsQ0FBQyxLQUFLO1FBQzlDLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxFQUFFLGdCQUFnQixDQUFDLEdBQUc7S0FDM0MsQ0FBQztJQUNGLE1BQU0sV0FBVyxHQUFHLEdBQUcsS0FBSyxjQUFjLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDakcsTUFBTSxZQUFZLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUM5QyxN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LEVBQUUsR0FBRyxHQUFHLFdBQVc7U0FDekIsQ0FBQyxDQUFDO1FBRUgsT0FBTyxXQUFXLENBQUM7SUFDckIsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQXdCO1FBQ3pDLE9BQU8sZUFBZSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7WUFDckMsUUFBUSxDQUFDLE1BQXVCLEVBQUUsSUFBWTtnQkFDNUMsSUFBSSxNQUFNLFlBQVksV0FBVztvQkFDL0IsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDO2dCQUV0QixJQUFJLE1BQU0sWUFBWSxTQUFTLEVBQUUsQ0FBQztvQkFDaEMsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDdEMsT0FBTyxPQUFPLFlBQVksV0FBVyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7Z0JBQ2xFLENBQUM7Z0JBRUQsOEJBQThCO2dCQUM5QixvQ0FBb0M7Z0JBQ3BDLHdCQUF3QjtnQkFDeEIsRUFBRTtnQkFDRixvQ0FBb0M7Z0JBQ3BDLDBDQUEwQztnQkFDMUMscUVBQXFFO2dCQUNyRSxJQUFJO2dCQUVKLE9BQVEsTUFBbUIsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3RDLENBQUM7WUFDRCxTQUFTLEVBQUUsVUFBUyxNQUF1QjtnQkFDekMsT0FBTyxNQUFNLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUM3QixDQUFDO1lBQ0QsZUFBZSxFQUFFLElBQUk7WUFDckIsVUFBVSxFQUFFLElBQUk7U0FDakIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBGb3JtQ29udHJvbCwgRm9ybUdyb3VwLCBWYWxpZGF0aW9uRXJyb3JzLCBWYWxpZGF0b3JGbiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7XG4gIENvbXBhcmlzb25WYWxpZGF0aW9uS2V5cyxcbiAgREVGQVVMVF9QQVRURVJOUyxcbiAgUGF0aFByb3h5LFxuICBQYXRoUHJveHlFbmdpbmUsXG4gIFZhbGlkYXRpb24sXG4gIFZhbGlkYXRpb25LZXlzLFxuICBWYWxpZGF0b3IsXG59IGZyb20gJ0BkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvbic7XG5pbXBvcnQgeyBGaWVsZFByb3BlcnRpZXMsIHBhcnNlVmFsdWVCeVR5cGUgfSBmcm9tICdAZGVjYWYtdHMvdWktZGVjb3JhdG9ycyc7XG5pbXBvcnQgeyBBbmd1bGFyRW5naW5lS2V5cyB9IGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCB7IEtleVZhbHVlIH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBOZ3hSZW5kZXJpbmdFbmdpbmUgfSBmcm9tICcuL05neFJlbmRlcmluZ0VuZ2luZSc7XG5cblxudHlwZSBDb21wYXJpc29uVmFsaWRhdGlvbktleSA9IHR5cGVvZiBDb21wYXJpc29uVmFsaWRhdGlvbktleXNba2V5b2YgdHlwZW9mIENvbXBhcmlzb25WYWxpZGF0aW9uS2V5c107XG5cbi8qKlxuICpcbiAqIFJlc29sdmVzIHRoZSBjb3JyZWN0IHZhbGlkYXRvciBrZXkgYW5kIGl0cyBhc3NvY2lhdGVkIHByb3BlcnRpZXMgYmFzZWQgb24gdGhlIGlucHV0IGtleSBhbmQgdHlwZS5cbiAqXG4gKiBXaGVuIHRoZSB2YWxpZGF0aW9uIGtleSBpcyBUWVBFLCBpdCdzIG5lY2Vzc2FyeSB0byByZXNvbHZlIHRoZSBhY3R1YWwgdmFsaWRhdG9yIGJhc2VkIG9uIHRoZVxuICogZmllbGQncyB0eXBlIChlLmcuLCAncGFzc3dvcmQnLCAnZW1haWwnLCAndXJsJykgaW5zdGVhZCBvZiB1c2luZyB0aGUgZ2VuZXJpYyBnZXRWYWxpZGF0b3IoXCJ0eXBlXCIpIGxvZ2ljLlxuICogVGhpcyBhbGxvd3MgZGlyZWN0bHkgaW52b2tpbmcgc3BlY2lmaWMgdmFsaWRhdG9ycyBsaWtlIGdldFZhbGlkYXRvcigncGFzc3dvcmQnKSwgZW5zdXJpbmcgdGhlIGNvcnJlY3RcbiAqIGJlaGF2aW9yIGZvciB0eXBlLWJhc2VkIHZhbGlkYXRpb24uXG4gKlxuICogQHBhcmFtIGtleSAtIFRoZSB2YWxpZGF0aW9uIGtleSAoZS5nLiwgJ3R5cGUnLCAncmVxdWlyZWQnLCBldGMuKS5cbiAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB0aGF0IG5lZWRzIGJlIHByb3ZpZGVkIHRvIHRoZSB2YWxpZGF0b3IuXG4gKiBAcGFyYW0gdHlwZSAtIFRoZSBmaWVsZCdzIGRlY2xhcmVkIHR5cGUuXG4gKiBAcmV0dXJucyBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgcmVzb2x2ZWQgdmFsaWRhdG9yIGtleSBhbmQgaXRzIGNvcnJlc3BvbmRpbmcgcHJvcHMuXG4gKi9cbmNvbnN0IHJlc29sdmVWYWxpZGF0b3JLZXlQcm9wcyA9IChrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24sIHR5cGU6IHN0cmluZyk6IHtcbiAgdmFsaWRhdG9yS2V5OiBzdHJpbmc7XG4gIHByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn0gPT4ge1xuICBjb25zdCBwYXR0ZXJuVmFsaWRhdG9yczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7XG4gICAgW1ZhbGlkYXRpb25LZXlzLlBBU1NXT1JEXTogREVGQVVMVF9QQVRURVJOUy5QQVNTV09SRC5DSEFSOF9PTkVfT0ZfRUFDSCxcbiAgICBbVmFsaWRhdGlvbktleXMuRU1BSUxdOiBERUZBVUxUX1BBVFRFUk5TLkVNQUlMLFxuICAgIFtWYWxpZGF0aW9uS2V5cy5VUkxdOiBERUZBVUxUX1BBVFRFUk5TLlVSTCxcbiAgfTtcbiAgY29uc3QgaXNUeXBlQmFzZWQgPSBrZXkgPT09IFZhbGlkYXRpb25LZXlzLlRZUEUgJiYgT2JqZWN0LmtleXMocGF0dGVyblZhbGlkYXRvcnMpLmluY2x1ZGVzKHR5cGUpO1xuICBjb25zdCB2YWxpZGF0b3JLZXkgPSBpc1R5cGVCYXNlZCA/IHR5cGUgOiBrZXk7XG4gIGNvbnN0IHByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHtcbiAgICAvLyBbdmFsaWRhdG9yS2V5XTogKCFpc1R5cGVCYXNlZCAmJiBrZXkgPT09ICd0eXBlJykgPyBwYXJzZVR5cGUodHlwZSkgOiB2YWx1ZSxcbiAgICBbdmFsaWRhdG9yS2V5XTogKCFpc1R5cGVCYXNlZCAmJiB2YWxpZGF0b3JLZXkgPT09IFZhbGlkYXRpb25LZXlzLlRZUEUpID8gTmd4UmVuZGVyaW5nRW5naW5lLmdldCgpLnRyYW5zbGF0ZSh2YWx1ZSBhcyBzdHJpbmcsIGZhbHNlKSA6IHZhbHVlLFxuICAgIC8vIEVtYWlsLCBQYXNzd29yZCwgYW5kIFVSTCBhcmUgdmFsaWRhdGVkIHVzaW5nIHRoZSBcInBhdHRlcm5cIiBrZXlcbiAgICAuLi4oaXNUeXBlQmFzZWQgJiYgeyBbVmFsaWRhdGlvbktleXMuUEFUVEVSTl0gOiBwYXR0ZXJuVmFsaWRhdG9yc1t0eXBlXSB9KSxcbiAgfTtcblxuICByZXR1cm4geyB2YWxpZGF0b3JLZXksIHByb3BzIH07XG59O1xuXG5cbmV4cG9ydCBjbGFzcyBWYWxpZGF0b3JGYWN0b3J5IHtcbiAgc3RhdGljIHNwYXduKGZpZWxkUHJvcHM6IEZpZWxkUHJvcGVydGllcywga2V5OiBzdHJpbmcpOiBWYWxpZGF0b3JGbiB7XG4gICAgaWYgKCFWYWxpZGF0aW9uLmtleXMoKS5pbmNsdWRlcyhrZXkpKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBjdXN0b20gdmFsaWRhdGlvbicpO1xuXG4gICAgY29uc3QgdmFsaWRhdG9yRm46IFZhbGlkYXRvckZuID0gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCk6IFZhbGlkYXRpb25FcnJvcnMgfCBudWxsID0+IHtcbiAgICAgIGNvbnN0IHsgdHlwZSB9ID0gZmllbGRQcm9wcztcbiAgICAgIGNvbnN0IHsgdmFsaWRhdG9yS2V5LCBwcm9wcyB9ID0gcmVzb2x2ZVZhbGlkYXRvcktleVByb3BzKGtleSwgZmllbGRQcm9wc1trZXkgYXMga2V5b2YgRmllbGRQcm9wZXJ0aWVzXSwgdHlwZSk7XG4gICAgICBjb25zdCB2YWxpZGF0b3IgPSBWYWxpZGF0aW9uLmdldCh2YWxpZGF0b3JLZXkpIGFzIFZhbGlkYXRvcjtcblxuICAgICAgLy8gcGFyc2VWYWx1ZUJ5VHlwZSBkb2VzIG5vdCBzdXBwb3J0IHVuZGVmaW5lZCB2YWx1ZXNcbiAgICAgIGNvbnN0IHZhbHVlID0gdHlwZW9mIGNvbnRyb2wudmFsdWUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgID8gcGFyc2VWYWx1ZUJ5VHlwZSh0eXBlLCBjb250cm9sLnZhbHVlLCBmaWVsZFByb3BzKVxuICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgLy8gQ3JlYXRlIGEgcHJveHkgdG8gZW5hYmxlIGFjY2VzcyB0byBwYXJlbnQgYW5kIGNoaWxkIHZhbHVlc1xuICAgICAgbGV0IHByb3h5OiBQYXRoUHJveHk8dW5rbm93bj4gPSBWYWxpZGF0b3JGYWN0b3J5LmNyZWF0ZVByb3h5KHt9IGFzIEFic3RyYWN0Q29udHJvbCk7XG4gICAgICBpZiAoT2JqZWN0LnZhbHVlcyhDb21wYXJpc29uVmFsaWRhdGlvbktleXMpLmluY2x1ZGVzKGtleSBhcyBDb21wYXJpc29uVmFsaWRhdGlvbktleSkpIHtcbiAgICAgICAgY29uc3QgcGFyZW50OiBGb3JtR3JvdXAgPSBjb250cm9sIGluc3RhbmNlb2YgRm9ybUdyb3VwID8gY29udHJvbCA6IChjb250cm9sIGFzIEtleVZhbHVlKVtBbmd1bGFyRW5naW5lS2V5cy5QQVJFTlRdO1xuICAgICAgICBwcm94eSA9IFZhbGlkYXRvckZhY3RvcnkuY3JlYXRlUHJveHkocGFyZW50KSBhcyBQYXRoUHJveHk8dW5rbm93bj47XG4gICAgICB9XG5cbiAgICAgIGxldCBlcnJzOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICB0cnkge1xuICAgICAgICBpZighcHJvcHNbJ3R5cGVzJ10gJiYgIXByb3BzWydjdXN0b21UeXBlcyddKVxuICAgICAgICAgIHByb3BzWyd0eXBlcyddID0gcHJvcHNbJ3R5cGUnXTtcbiAgICAgICAgZXJycyA9IHZhbGlkYXRvci5oYXNFcnJvcnModmFsdWUsIHByb3BzLCBwcm94eSk7XG4gICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgIGVycnMgPSBgJHtrZXl9IHZhbGlkYXRvciBmYWlsZWQgdG8gdmFsaWRhdGU6ICR7ZX1gO1xuICAgICAgICBjb25zb2xlLndhcm4oZXJycyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBlcnJzID8geyBbdmFsaWRhdG9yS2V5XTogdHJ1ZSB9IDogbnVsbDtcbiAgICB9O1xuXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHZhbGlkYXRvckZuLCAnbmFtZScsIHtcbiAgICAgIHZhbHVlOiBgJHtrZXl9VmFsaWRhdG9yYCxcbiAgICB9KTtcblxuICAgIHJldHVybiB2YWxpZGF0b3JGbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBDcmVhdGVzIGEgcHJveHkgd3JhcHBlciBmb3IgYW4gQW5ndWxhciBBYnN0cmFjdENvbnRyb2wgdG8gYXNzaXN0IHdpdGggY3VzdG9tIHZhbGlkYXRpb24gbG9naWMuXG4gICAqIEBkZXNjcmlwdGlvbiBSZXR1cm5zIGEgc3RydWN0dXJlZCBwcm94eSBvYmplY3QgdGhhdCBzaW11bGF0ZXMgYSBoaWVyYXJjaGljYWwgdHJlZSBvZiBmb3JtIHZhbHVlcy5cbiAgICogRW5hYmxlcyBWYWxpZGF0b3JzIGhhbmRsaW5nIG1ldGhvZCB0byBhY2Nlc3MgcGFyZW50IGFuZCBjaGlsZCBwcm9wZXJ0aWVzIHVzaW5nIGNvbnNpc3RlbnQgZG90LW5vdGF0aW9uIGluIEFuZ3VsYXIgZm9ybXMuXG4gICAqXG4gICAqIEBwYXJhbSB7QWJzdHJhY3RDb250cm9sfSBjb250cm9sIC0gVGhlIGNvbnRyb2wgdG8gd3JhcCBpbiBhIHByb3h5LlxuICAgKiBAcmV0dXJucyB7UGF0aFByb3h5PHVua25vd24+fSBBIHByb3h5IG9iamVjdCBleHBvc2luZyBmb3JtIHZhbHVlcyBhbmQgZW5hYmxpbmcgcmVjdXJzaXZlIHBhcmVudCBhY2Nlc3MuXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlUHJveHkoY29udHJvbDogQWJzdHJhY3RDb250cm9sKTogUGF0aFByb3h5PHVua25vd24+IHtcbiAgICByZXR1cm4gUGF0aFByb3h5RW5naW5lLmNyZWF0ZShjb250cm9sLCB7XG4gICAgICBnZXRWYWx1ZSh0YXJnZXQ6IEFic3RyYWN0Q29udHJvbCwgcHJvcDogc3RyaW5nKTogdW5rbm93biB7XG4gICAgICAgIGlmICh0YXJnZXQgaW5zdGFuY2VvZiBGb3JtQ29udHJvbClcbiAgICAgICAgICByZXR1cm4gdGFyZ2V0LnZhbHVlO1xuXG4gICAgICAgIGlmICh0YXJnZXQgaW5zdGFuY2VvZiBGb3JtR3JvdXApIHtcbiAgICAgICAgICBjb25zdCBjb250cm9sID0gdGFyZ2V0LmNvbnRyb2xzW3Byb3BdO1xuICAgICAgICAgIHJldHVybiBjb250cm9sIGluc3RhbmNlb2YgRm9ybUNvbnRyb2wgPyBjb250cm9sLnZhbHVlIDogY29udHJvbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNvbnN0IHZhbHVlID0gdGFyZ2V0W3Byb3BdO1xuICAgICAgICAvLyBpZiAodmFsdWUgaW5zdGFuY2VvZiBGb3JtQ29udHJvbClcbiAgICAgICAgLy8gICByZXR1cm4gdmFsdWUudmFsdWU7XG4gICAgICAgIC8vXG4gICAgICAgIC8vIGlmICh2YWx1ZSBpbnN0YW5jZW9mIEZvcm1Hcm91cCkge1xuICAgICAgICAvLyAgIGNvbnN0IGNvbnRyb2wgPSB2YWx1ZS5jb250cm9sc1twcm9wXTtcbiAgICAgICAgLy8gICByZXR1cm4gY29udHJvbCBpbnN0YW5jZW9mIEZvcm1Db250cm9sID8gY29udHJvbC52YWx1ZSA6IGNvbnRyb2w7XG4gICAgICAgIC8vIH1cblxuICAgICAgICByZXR1cm4gKHRhcmdldCBhcyBLZXlWYWx1ZSk/Lltwcm9wXTtcbiAgICAgIH0sXG4gICAgICBnZXRQYXJlbnQ6IGZ1bmN0aW9uKHRhcmdldDogQWJzdHJhY3RDb250cm9sKSAge1xuICAgICAgICByZXR1cm4gdGFyZ2V0Py5bJ19wYXJlbnQnXTtcbiAgICAgIH0sXG4gICAgICBpZ25vcmVVbmRlZmluZWQ6IHRydWUsXG4gICAgICBpZ25vcmVOdWxsOiB0cnVlLFxuICAgIH0pO1xuICB9XG59XG4iXX0=