@decaf-ts/ui-decorators 0.4.6 → 0.5.1

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 (44) hide show
  1. package/README.md +74 -31
  2. package/dist/ui-decorators.cjs +614 -0
  3. package/dist/ui-decorators.esm.cjs +591 -0
  4. package/lib/esm/index.d.ts +1 -1
  5. package/lib/esm/index.js +2 -3
  6. package/lib/esm/model/Renderable.js +1 -2
  7. package/lib/esm/model/decorators.js +1 -2
  8. package/lib/esm/model/index.js +1 -2
  9. package/lib/esm/model/model.js +1 -2
  10. package/lib/esm/model/overrides.js +1 -2
  11. package/lib/esm/ui/Rendering.js +7 -4
  12. package/lib/esm/ui/constants.d.ts +6 -0
  13. package/lib/esm/ui/constants.js +29 -24
  14. package/lib/esm/ui/decorators.js +1 -2
  15. package/lib/esm/ui/errors.js +1 -2
  16. package/lib/esm/ui/index.js +1 -2
  17. package/lib/esm/ui/interfaces.js +1 -2
  18. package/lib/esm/ui/types.d.ts +7 -0
  19. package/lib/esm/ui/types.js +2 -3
  20. package/lib/esm/ui/utils.d.ts +1 -1
  21. package/lib/esm/ui/utils.js +2 -3
  22. package/lib/index.cjs +2 -1
  23. package/lib/index.d.ts +1 -1
  24. package/lib/model/Renderable.cjs +1 -0
  25. package/lib/model/decorators.cjs +3 -2
  26. package/lib/model/index.cjs +1 -0
  27. package/lib/model/model.cjs +1 -0
  28. package/lib/model/overrides.cjs +2 -1
  29. package/lib/ui/Rendering.cjs +6 -1
  30. package/lib/ui/constants.cjs +28 -21
  31. package/lib/ui/constants.d.ts +6 -0
  32. package/lib/ui/decorators.cjs +1 -0
  33. package/lib/ui/errors.cjs +1 -0
  34. package/lib/ui/index.cjs +1 -0
  35. package/lib/ui/interfaces.cjs +1 -0
  36. package/lib/ui/types.cjs +2 -0
  37. package/lib/ui/types.d.ts +7 -0
  38. package/lib/ui/utils.cjs +2 -1
  39. package/lib/ui/utils.d.ts +1 -1
  40. package/package.json +36 -38
  41. package/dist/esm/ui-decorators.bundle.min.esm.js +0 -2
  42. package/dist/esm/ui-decorators.bundle.min.esm.js.LICENSE.txt +0 -14
  43. package/dist/ui-decorators.bundle.min.js +0 -2
  44. package/dist/ui-decorators.bundle.min.js.LICENSE.txt +0 -14
@@ -0,0 +1,614 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@decaf-ts/decorator-validation'), require('@decaf-ts/reflection'), require('@decaf-ts/db-decorators'), require('reflect-metadata')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', '@decaf-ts/decorator-validation', '@decaf-ts/reflection', '@decaf-ts/db-decorators', 'reflect-metadata'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["ui-decorators"] = {}, global.decoratorValidation, global.reflection, global.dbDecorators));
5
+ })(this, (function (exports, decoratorValidation, reflection, dbDecorators) { 'use strict';
6
+
7
+ /**
8
+ * @enum UIKeys
9
+ * @category Constants
10
+ */
11
+ const UIKeys = {
12
+ REFLECT: `${decoratorValidation.ModelKeys.REFLECT}.ui.`,
13
+ UIMODEL: "uimodel",
14
+ RENDERED_BY: "rendered-by",
15
+ ELEMENT: "element",
16
+ PROP: "prop",
17
+ NAME: "name",
18
+ NAME_PREFIX: "input-",
19
+ CUSTOM_PROPS: "customValidationProps",
20
+ TYPE: "type",
21
+ SUB_TYPE: "subtype",
22
+ HIDDEN: "hidden",
23
+ FORMAT: "format",
24
+ READ_ONLY: "readonly",
25
+ REQUIRED: decoratorValidation.ValidationKeys.REQUIRED,
26
+ MIN: decoratorValidation.ValidationKeys.MIN,
27
+ MIN_LENGTH: decoratorValidation.ValidationKeys.MIN_LENGTH,
28
+ MAX: decoratorValidation.ValidationKeys.MAX,
29
+ MAX_LENGTH: decoratorValidation.ValidationKeys.MAX_LENGTH,
30
+ PATTERN: decoratorValidation.ValidationKeys.PATTERN,
31
+ URL: decoratorValidation.ValidationKeys.URL,
32
+ STEP: decoratorValidation.ValidationKeys.STEP,
33
+ DATE: decoratorValidation.ValidationKeys.DATE,
34
+ EMAIL: decoratorValidation.ValidationKeys.EMAIL,
35
+ PASSWORD: decoratorValidation.ValidationKeys.PASSWORD,
36
+ EQUALS: decoratorValidation.ValidationKeys.EQUALS,
37
+ DIFF: decoratorValidation.ValidationKeys.DIFF,
38
+ LESS_THAN: decoratorValidation.ValidationKeys.LESS_THAN,
39
+ LESS_THAN_OR_EQUAL: decoratorValidation.ValidationKeys.LESS_THAN_OR_EQUAL,
40
+ GREATER_THAN: decoratorValidation.ValidationKeys.GREATER_THAN,
41
+ GREATER_THAN_OR_EQUAL: decoratorValidation.ValidationKeys.GREATER_THAN_OR_EQUAL,
42
+ };
43
+ const ValidatableByType = {
44
+ [UIKeys.EMAIL]: decoratorValidation.EmailValidator,
45
+ [UIKeys.URL]: decoratorValidation.URLValidator,
46
+ [UIKeys.DATE]: decoratorValidation.DateValidator,
47
+ [UIKeys.PASSWORD]: decoratorValidation.PasswordValidator,
48
+ };
49
+ /**
50
+ * @constant ValidatableByAttribute
51
+ *
52
+ * @memberOf ui-decorators-web.ui
53
+ */
54
+ const ValidatableByAttribute = {
55
+ [UIKeys.REQUIRED]: decoratorValidation.RequiredValidator,
56
+ [UIKeys.MIN]: decoratorValidation.MinValidator,
57
+ [UIKeys.MAX]: decoratorValidation.MaxValidator,
58
+ [UIKeys.STEP]: decoratorValidation.StepValidator,
59
+ [UIKeys.MIN_LENGTH]: decoratorValidation.MinLengthValidator,
60
+ [UIKeys.MAX_LENGTH]: decoratorValidation.MaxLengthValidator,
61
+ [UIKeys.PATTERN]: decoratorValidation.PatternValidator,
62
+ [UIKeys.EQUALS]: decoratorValidation.EqualsValidator,
63
+ [UIKeys.DIFF]: decoratorValidation.DiffValidator,
64
+ [UIKeys.LESS_THAN]: decoratorValidation.LessThanValidator,
65
+ [UIKeys.LESS_THAN_OR_EQUAL]: decoratorValidation.LessThanOrEqualValidator,
66
+ [UIKeys.GREATER_THAN]: decoratorValidation.GreaterThanValidator,
67
+ [UIKeys.GREATER_THAN_OR_EQUAL]: decoratorValidation.GreaterThanOrEqualValidator,
68
+ };
69
+ const HTML5DateFormat = "yyyy-MM-dd";
70
+ const HTML5InputTypes = {
71
+ BUTTON: "button",
72
+ CHECKBOX: "checkbox",
73
+ COLOR: "color",
74
+ DATE: UIKeys.DATE,
75
+ DATETIME_LOCAL: "datetime-local",
76
+ EMAIL: UIKeys.EMAIL,
77
+ FILE: "file",
78
+ HIDDEN: "hidden",
79
+ IMAGE: "image",
80
+ MONTH: "month",
81
+ NUMBER: "number",
82
+ PASSWORD: UIKeys.PASSWORD,
83
+ RADIO: "radio",
84
+ RANGE: "range",
85
+ RESET: "reset",
86
+ SEARCH: "search",
87
+ SUBMIT: "submit",
88
+ TEL: "tel",
89
+ TEXT: "text",
90
+ TIME: "time",
91
+ URL: UIKeys.URL,
92
+ WEEK: "week",
93
+ };
94
+ const HTML5CheckTypes = [
95
+ HTML5InputTypes.CHECKBOX,
96
+ HTML5InputTypes.RADIO,
97
+ ];
98
+
99
+ class RenderingError extends dbDecorators.BaseError {
100
+ constructor(msg) {
101
+ super(RenderingError.name, msg);
102
+ }
103
+ }
104
+
105
+ /**
106
+ * @function formatByType
107
+ *
108
+ * @memberOf ui-decorators-web.ui
109
+ */
110
+ function formatByType(type, value, ...args) {
111
+ if (type === UIKeys.DATE) {
112
+ const format = args.shift() || HTML5DateFormat;
113
+ return decoratorValidation.formatDate(new Date(value), format);
114
+ }
115
+ return value;
116
+ }
117
+ function parseValueByType(type, value, fieldProps) {
118
+ let result = undefined;
119
+ switch (type) {
120
+ case HTML5InputTypes.NUMBER:
121
+ result = parseToNumber(value);
122
+ break;
123
+ case HTML5InputTypes.DATE: {
124
+ const format = fieldProps.format;
125
+ result =
126
+ typeof value === decoratorValidation.ReservedModels.NUMBER
127
+ ? new Date(value)
128
+ : value
129
+ ? format
130
+ ? decoratorValidation.parseDate(format, value)
131
+ : new Date(value)
132
+ : undefined;
133
+ break;
134
+ }
135
+ default:
136
+ result =
137
+ typeof value === decoratorValidation.ReservedModels.STRING
138
+ ? escapeHtml(value)
139
+ : result;
140
+ }
141
+ if (typeof result === "undefined") {
142
+ throw new dbDecorators.InternalError(`Failed to parse value of type ${type} from ${typeof value} - ${value}`);
143
+ }
144
+ return result;
145
+ }
146
+ function parseToNumber(value) {
147
+ if (typeof value === "number" && !isNaN(value))
148
+ return value;
149
+ const parsed = Number(value);
150
+ if (!isNaN(parsed))
151
+ return parsed;
152
+ return undefined;
153
+ }
154
+ function escapeHtml(value) {
155
+ if (!value)
156
+ return value;
157
+ const tagsToReplace = {
158
+ "&": "&",
159
+ "<": "&lt;",
160
+ ">": "&gt;",
161
+ };
162
+ return `${value}`.replace(/[&<>]/g, (tag) => {
163
+ return tagsToReplace[tag] || tag;
164
+ });
165
+ }
166
+ function revertHtml(value) {
167
+ const tagsToReplace = {
168
+ "&amp;": "&",
169
+ "&lt;": "<",
170
+ "&gt;": ">",
171
+ };
172
+ return `${value}`.replace(/&lt;|&gt;|&amp;/g, (tag) => {
173
+ return tagsToReplace[tag] || tag;
174
+ });
175
+ }
176
+ function generateUIModelID(model) {
177
+ let id;
178
+ try {
179
+ id = dbDecorators.findModelId(model);
180
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
181
+ }
182
+ catch (e) {
183
+ id = Date.now();
184
+ }
185
+ const name = model.constructor.name;
186
+ return `${name}-${id}`;
187
+ }
188
+
189
+ /**
190
+ * @description Abstract class for rendering UI components based on model metadata.
191
+ * @summary The RenderingEngine class provides a framework for converting model metadata into UI field definitions.
192
+ * It handles the translation of model properties to UI elements, applies validation rules, and manages different rendering flavors.
193
+ * This class is designed to be extended by specific rendering implementations.
194
+ *
195
+ * @template T The type of the rendering result, defaults to void
196
+ * @template R The type of the field definition, defaults to FieldDefinition<T>
197
+ *
198
+ * @param {string} flavour - The flavor of the rendering engine.
199
+ *
200
+ * @class RenderingEngine
201
+ */
202
+ class RenderingEngine {
203
+ /**
204
+ * @description Cache for storing rendering engine instances or constructors.
205
+ * @private
206
+ * @static
207
+ */
208
+ static { this.cache = {}; }
209
+ constructor(flavour) {
210
+ this.flavour = flavour;
211
+ /**
212
+ * Flag indicating whether the rendering engine has been initialized.
213
+ */
214
+ this.initialized = false;
215
+ RenderingEngine.register(this);
216
+ console.log(`decaf's ${flavour} rendering engine loaded`);
217
+ }
218
+ /**
219
+ * @description Translates between model types and HTML input types.
220
+ * @summary Converts model data types to appropriate HTML input types and vice versa.
221
+ *
222
+ * @param {string} key - The key to translate.
223
+ * @param {boolean} [toView=true] - Direction of translation (true for model to view, false for view to model).
224
+ * @returns {string} The translated type.
225
+ */
226
+ translate(key, toView = true) {
227
+ if (toView) {
228
+ switch (key) {
229
+ case decoratorValidation.ReservedModels.STRING:
230
+ return HTML5InputTypes.TEXT;
231
+ case decoratorValidation.ReservedModels.NUMBER:
232
+ case decoratorValidation.ReservedModels.BIGINT:
233
+ return HTML5InputTypes.NUMBER;
234
+ case decoratorValidation.ReservedModels.BOOLEAN:
235
+ return HTML5InputTypes.CHECKBOX;
236
+ case decoratorValidation.ReservedModels.DATE:
237
+ return HTML5InputTypes.DATE;
238
+ }
239
+ }
240
+ else {
241
+ switch (key) {
242
+ case HTML5InputTypes.TEXT:
243
+ case HTML5InputTypes.EMAIL:
244
+ case HTML5InputTypes.COLOR:
245
+ case HTML5InputTypes.PASSWORD:
246
+ case HTML5InputTypes.TEL:
247
+ case HTML5InputTypes.URL:
248
+ return decoratorValidation.ReservedModels.STRING;
249
+ case HTML5InputTypes.NUMBER:
250
+ return decoratorValidation.ReservedModels.NUMBER;
251
+ case HTML5InputTypes.CHECKBOX:
252
+ return decoratorValidation.ReservedModels.BOOLEAN;
253
+ case HTML5InputTypes.DATE:
254
+ case HTML5InputTypes.DATETIME_LOCAL:
255
+ case HTML5InputTypes.TIME:
256
+ return decoratorValidation.ReservedModels.DATE;
257
+ }
258
+ }
259
+ return key;
260
+ }
261
+ /**
262
+ * @description Checks if a type is validatable by its nature.
263
+ * @summary Determines if a given UI key represents a type that is inherently validatable.
264
+ *
265
+ * @param {string} key - The UI key to check.
266
+ * @returns {boolean} True if the type is validatable, false otherwise.
267
+ */
268
+ isValidatableByType(key) {
269
+ return Object.keys(ValidatableByType).includes(key);
270
+ }
271
+ /**
272
+ * @description Checks if a type is validatable by attribute.
273
+ * @summary Determines if a given UI key represents a validation that can be applied as an attribute.
274
+ *
275
+ * @param {string} key - The UI key to check.
276
+ * @returns {boolean} True if the type is validatable by attribute, false otherwise.
277
+ */
278
+ isValidatableByAttribute(key) {
279
+ return Object.keys(ValidatableByAttribute).includes(key);
280
+ }
281
+ /**
282
+ * @description Converts validation metadata to an attribute value.
283
+ * @summary Transforms validation metadata into a value suitable for use as an HTML attribute.
284
+ *
285
+ * @param {string} key - The validation key.
286
+ * @param {ValidationMetadata} value - The validation metadata.
287
+ * @returns {string | number | boolean} The converted attribute value.
288
+ * @throws {Error} If the given key is not validatable by attribute.
289
+ */
290
+ toAttributeValue(key, value) {
291
+ if (!Object.keys(ValidatableByAttribute).includes(key))
292
+ throw new Error(`Invalid attribute key "${key}". Expected one of: ${Object.keys(ValidatableByAttribute).join(", ")}.`);
293
+ return key === UIKeys.REQUIRED
294
+ ? true
295
+ : Object.values(decoratorValidation.ComparisonValidationKeys).includes(key)
296
+ ? value.propertyToCompare
297
+ : value[key];
298
+ }
299
+ /**
300
+ * @description Converts a model to a field definition.
301
+ * @summary Processes a model instance, extracting UI-related metadata and validation rules to create a field definition.
302
+ *
303
+ * @template M Type extending Model
304
+ * @template T Type referencing the specific Rendering engine field properties/inputs
305
+ * @param {M} model - The model instance to convert.
306
+ * @param {Record<string, unknown>} [globalProps={}] - Global properties to apply to all child elements.
307
+ * @param {boolean} [generateId=true] - Flag indicating whether to populate the rendererId property.
308
+ * @returns {FieldDefinition<T>} A field definition object representing the UI structure of the model.
309
+ * @throws {RenderingError} If no UI definitions are set for the model or if there are invalid decorators.
310
+ *
311
+ * @mermaid
312
+ * sequenceDiagram
313
+ * participant C as Client
314
+ * participant RE as RenderingEngine
315
+ * participant R as Reflection
316
+ * participant M as Model
317
+ * C->>RE: toFieldDefinition(model, globalProps)
318
+ * RE->>R: getMetadata(UIKeys.UIMODEL, model.constructor)
319
+ * R-->>RE: UIModelMetadata
320
+ * RE->>R: getAllPropertyDecorators(model, UIKeys.REFLECT)
321
+ * R-->>RE: Record<string, DecoratorMetadata[]>
322
+ * RE->>R: getAllPropertyDecorators(model, ValidationKeys.REFLECT)
323
+ * R-->>RE: Record<string, DecoratorMetadata<ValidationMetadata>[]>
324
+ * loop For each property
325
+ * RE->>RE: Process UI decorators
326
+ * RE->>RE: Apply validation rules
327
+ * end
328
+ * RE-->>C: FieldDefinition<T>
329
+ */
330
+ toFieldDefinition(model, globalProps = {}, generateId = true) {
331
+ const classDecorator = Reflect.getMetadata(RenderingEngine.key(UIKeys.UIMODEL), model.constructor) ||
332
+ Reflect.getMetadata(RenderingEngine.key(UIKeys.UIMODEL), decoratorValidation.Model.get(model.constructor.name));
333
+ if (!classDecorator)
334
+ throw new RenderingError(`No ui definitions set for model ${model.constructor.name}. Did you use @uimodel?`);
335
+ const { tag, props } = classDecorator;
336
+ const uiDecorators = reflection.Reflection.getAllPropertyDecorators(model, UIKeys.REFLECT);
337
+ let children;
338
+ if (uiDecorators) {
339
+ const validationDecorators = reflection.Reflection.getAllPropertyDecorators(model, decoratorValidation.ValidationKeys.REFLECT);
340
+ for (const key in uiDecorators) {
341
+ const decs = uiDecorators[key];
342
+ if (decs.length !== 2)
343
+ throw new RenderingError(`Only one type of decoration is allowed. Please choose between @uiprop and @uielement`);
344
+ const dec = decs[1]; // Ignore 0, its the design:type
345
+ if (!dec)
346
+ throw new RenderingError(`No decorator found`);
347
+ switch (dec.key) {
348
+ case UIKeys.PROP:
349
+ dec.props;
350
+ break;
351
+ case UIKeys.ELEMENT: {
352
+ children = children || [];
353
+ const childDefinition = {
354
+ tag: dec.props.tag,
355
+ props: Object.assign({}, dec.props.props, globalProps),
356
+ };
357
+ const validationDecs = validationDecorators[key];
358
+ const typeDec = validationDecs.shift();
359
+ for (const dec of validationDecs) {
360
+ if (this.isValidatableByAttribute(dec.key)) {
361
+ childDefinition.props[this.translate(dec.key)] =
362
+ this.toAttributeValue(dec.key, dec.props);
363
+ continue;
364
+ }
365
+ if (this.isValidatableByType(dec.key)) {
366
+ if (dec.key === HTML5InputTypes.DATE) {
367
+ childDefinition.props[UIKeys.FORMAT] =
368
+ dec.props.format || HTML5DateFormat;
369
+ }
370
+ childDefinition.props[UIKeys.TYPE] = dec.key;
371
+ continue;
372
+ }
373
+ console.log(dec);
374
+ }
375
+ if (!childDefinition.props[UIKeys.TYPE]) {
376
+ const basicType = typeDec.props.name;
377
+ childDefinition.props[UIKeys.TYPE] = this.translate(basicType.toLowerCase(), true);
378
+ }
379
+ childDefinition.props.value = formatByType(childDefinition.props[UIKeys.TYPE], model[key], childDefinition.props[UIKeys.FORMAT]);
380
+ children.push(childDefinition);
381
+ break;
382
+ }
383
+ default:
384
+ throw new RenderingError(`Invalid key: ${dec.key}`);
385
+ }
386
+ }
387
+ }
388
+ const result = {
389
+ tag: tag,
390
+ props: Object.assign({}, props, globalProps),
391
+ children: children,
392
+ };
393
+ if (generateId) {
394
+ result.rendererId = generateUIModelID(model);
395
+ }
396
+ return result;
397
+ }
398
+ /**
399
+ * @description Registers a rendering engine instance.
400
+ * @summary Adds a rendering engine to the static cache and sets it as the current engine.
401
+ *
402
+ * @param {RenderingEngine<unknown, unknown>} engine - The rendering engine to register.
403
+ * @throws {InternalError} If an engine with the same flavor already exists.
404
+ *
405
+ * @static
406
+ */
407
+ static register(engine) {
408
+ if (engine.flavour in this.cache)
409
+ throw new dbDecorators.InternalError(`Rendering engine under ${engine.flavour} already exists`);
410
+ this.cache[engine.flavour] = engine;
411
+ this.current = engine;
412
+ }
413
+ /**
414
+ * @description Retrieves or initializes a rendering engine.
415
+ * @summary Gets an existing engine instance or creates and initializes a new one if given a constructor.
416
+ *
417
+ * @template O The type of the rendering engine output
418
+ * @param {Constructor<RenderingEngine<O>> | RenderingEngine<O>} obj - The engine instance or constructor.
419
+ * @returns {RenderingEngine<O>} The initialized rendering engine.
420
+ *
421
+ * @private
422
+ * @static
423
+ */
424
+ static getOrBoot(obj) {
425
+ if (obj instanceof RenderingEngine)
426
+ return obj;
427
+ const engine = new obj();
428
+ engine.initialize(); // make the booting async. use the initialized flag to control it
429
+ return engine;
430
+ }
431
+ /**
432
+ * @description Retrieves a rendering engine by flavor.
433
+ * @summary Gets the current rendering engine or a specific one by flavor.
434
+ *
435
+ * @template O The type of the rendering engine output
436
+ * @param {string} [flavour] - The flavor of the rendering engine to retrieve.
437
+ * @returns {RenderingEngine<O>} The requested rendering engine.
438
+ * @throws {InternalError} If the requested flavor does not exist.
439
+ *
440
+ * @static
441
+ */
442
+ static get(flavour) {
443
+ if (!flavour)
444
+ return this.getOrBoot(this.current);
445
+ if (!(flavour in this.cache))
446
+ throw new dbDecorators.InternalError(`Rendering engine under ${flavour} does not exist`);
447
+ return this.getOrBoot(this.cache[flavour]);
448
+ }
449
+ /**
450
+ * @description Renders a model using the appropriate rendering engine.
451
+ * @summary Determines the correct rendering engine for a model and invokes its render method.
452
+ *
453
+ * @template M Type extending Model
454
+ * @param {M} model - The model to render.
455
+ * @param {...any[]} args - Additional arguments to pass to the render method.
456
+ * @returns {any} The result of the rendering process.
457
+ * @throws {InternalError} If no registered model is found.
458
+ *
459
+ * @static
460
+ */
461
+ static render(model, ...args) {
462
+ const constructor = decoratorValidation.Model.get(model.constructor.name);
463
+ if (!constructor)
464
+ throw new dbDecorators.InternalError("No model registered found");
465
+ const flavour = Reflect.getMetadata(RenderingEngine.key(UIKeys.RENDERED_BY), constructor);
466
+ // @ts-expect-error for the var args type check
467
+ return RenderingEngine.get(flavour).render(model, ...args);
468
+ }
469
+ /**
470
+ * @description Generates a metadata key for UI-related properties.
471
+ * @summary Prefixes a given key with the UI reflection prefix.
472
+ *
473
+ * @param {string} key - The key to prefix.
474
+ * @returns {string} The prefixed key.
475
+ *
476
+ * @static
477
+ */
478
+ static key(key) {
479
+ return `${UIKeys.REFLECT}${key}`;
480
+ }
481
+ }
482
+
483
+ /**
484
+ * Tags the model as a uimodel, giving it the 'render' method
485
+ *
486
+ * @param {string} [tag] optional param. will render the provided elment wrapping the attribute uielements
487
+ * @param {{}} [props] optional param. Attributes to be passed to the tag element
488
+ * @param {function(any): void} [instanceCallback] optional callback returning the instance after creation for additional logic
489
+ *
490
+ * @decorator uimodel
491
+ *
492
+ * @mermaid
493
+ * sequenceDiagram
494
+ * participant System
495
+ * participant uimodel
496
+ * participant constructor
497
+ * participant instance
498
+ * System->>uimodel:do(constructor)
499
+ * uimodel->>constructor: Executes the constructor
500
+ * constructor->>uimodel: returns instance
501
+ * uimodel->>instance: adds the render method
502
+ * uimodel->>System: returns UIModel instance
503
+ *
504
+ * @category Decorators
505
+ */
506
+ function uimodel(tag, props) {
507
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
508
+ return (original, propertyKey) => {
509
+ const meta = {
510
+ tag: tag || original.name,
511
+ props: props,
512
+ };
513
+ return reflection.metadata(RenderingEngine.key(UIKeys.UIMODEL), meta)(original);
514
+ };
515
+ }
516
+ function renderedBy(engine) {
517
+ return reflection.apply(reflection.metadata(RenderingEngine.key(UIKeys.RENDERED_BY), engine));
518
+ }
519
+
520
+ decoratorValidation.Model.prototype.render = function (...args) {
521
+ return RenderingEngine.render(this, ...args);
522
+ };
523
+
524
+ /**
525
+ * @namespace ui-decorators.ui.decorators
526
+ * @memberOf ui-decorators.ui
527
+ */
528
+ function hideOn(...operations) {
529
+ return decoratorValidation.propMetadata(RenderingEngine.key(UIKeys.HIDDEN), operations);
530
+ }
531
+ function hidden() {
532
+ return hideOn(dbDecorators.OperationKeys.CREATE, dbDecorators.OperationKeys.READ, dbDecorators.OperationKeys.UPDATE, dbDecorators.OperationKeys.DELETE);
533
+ }
534
+ /**
535
+ * Adds the UIElement definition as metadata to the property, allowing it to be read by any {@link RenderStrategy}
536
+ *
537
+ * @param {string} tag The component/HTML element tag name
538
+ * @param {{}} [props] The properties to pass to that component/HTML Element
539
+ * @param serialize
540
+ *
541
+ * @decorator uielement
542
+ *
543
+ * @category Decorators
544
+ * @subcategory ui-decorators
545
+ */
546
+ function uielement(tag, props, serialize = false) {
547
+ return (original, propertyKey) => {
548
+ const metadata = {
549
+ tag: tag,
550
+ serialize: serialize,
551
+ props: Object.assign({
552
+ name: propertyKey,
553
+ }, props || {}),
554
+ };
555
+ return decoratorValidation.propMetadata(RenderingEngine.key(UIKeys.ELEMENT), metadata)(original, propertyKey);
556
+ };
557
+ }
558
+ /**
559
+ * Adds the UIProp definition as metadata to the property, allowing it to be read by any {@link RenderStrategy}
560
+ *
561
+ * this requires a '@uimodel' with a defined tag
562
+ *
563
+ * @param {string} [propName] the property name that will be passed to the component. defaults to the PropertyKey
564
+ *
565
+ * @decorator uiprop
566
+ *
567
+ * @category Decorators
568
+ * @subcategory ui-decorators
569
+ */
570
+ function uiprop(propName = undefined, stringify = false) {
571
+ return (target, propertyKey) => {
572
+ const metadata = {
573
+ name: propName || propertyKey,
574
+ stringify: stringify,
575
+ };
576
+ decoratorValidation.propMetadata(RenderingEngine.key(UIKeys.PROP), metadata)(target, propertyKey);
577
+ };
578
+ }
579
+
580
+ /**
581
+ * @module ui-decorators
582
+ */
583
+ /**
584
+ * @summary stores the current package version
585
+ * @description this is how you should document a constant
586
+ * @const VERSION
587
+ * @memberOf module:ui-decorators
588
+ */
589
+ const VERSION = "##VERSION##";
590
+
591
+ exports.HTML5CheckTypes = HTML5CheckTypes;
592
+ exports.HTML5DateFormat = HTML5DateFormat;
593
+ exports.HTML5InputTypes = HTML5InputTypes;
594
+ exports.RenderingEngine = RenderingEngine;
595
+ exports.RenderingError = RenderingError;
596
+ exports.UIKeys = UIKeys;
597
+ exports.VERSION = VERSION;
598
+ exports.ValidatableByAttribute = ValidatableByAttribute;
599
+ exports.ValidatableByType = ValidatableByType;
600
+ exports.escapeHtml = escapeHtml;
601
+ exports.formatByType = formatByType;
602
+ exports.generateUIModelID = generateUIModelID;
603
+ exports.hidden = hidden;
604
+ exports.hideOn = hideOn;
605
+ exports.parseToNumber = parseToNumber;
606
+ exports.parseValueByType = parseValueByType;
607
+ exports.renderedBy = renderedBy;
608
+ exports.revertHtml = revertHtml;
609
+ exports.uielement = uielement;
610
+ exports.uimodel = uimodel;
611
+ exports.uiprop = uiprop;
612
+
613
+ }));
614
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidWktZGVjb3JhdG9ycy5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy91aS9jb25zdGFudHMudHMiLCIuLi9zcmMvdWkvZXJyb3JzLnRzIiwiLi4vc3JjL3VpL3V0aWxzLnRzIiwiLi4vc3JjL3VpL1JlbmRlcmluZy50cyIsIi4uL3NyYy9tb2RlbC9kZWNvcmF0b3JzLnRzIiwiLi4vc3JjL21vZGVsL292ZXJyaWRlcy50cyIsIi4uL3NyYy91aS9kZWNvcmF0b3JzLnRzIiwiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbnN0cnVjdG9yLFxuICBEYXRlVmFsaWRhdG9yLFxuICBEaWZmVmFsaWRhdG9yLFxuICBFbWFpbFZhbGlkYXRvcixcbiAgRXF1YWxzVmFsaWRhdG9yLFxuICBHcmVhdGVyVGhhbk9yRXF1YWxWYWxpZGF0b3IsXG4gIEdyZWF0ZXJUaGFuVmFsaWRhdG9yLFxuICBMZXNzVGhhbk9yRXF1YWxWYWxpZGF0b3IsXG4gIExlc3NUaGFuVmFsaWRhdG9yLFxuICBNYXhMZW5ndGhWYWxpZGF0b3IsXG4gIE1heFZhbGlkYXRvcixcbiAgTWluTGVuZ3RoVmFsaWRhdG9yLFxuICBNaW5WYWxpZGF0b3IsXG4gIE1vZGVsS2V5cyxcbiAgUGFzc3dvcmRWYWxpZGF0b3IsXG4gIFBhdHRlcm5WYWxpZGF0b3IsXG4gIFJlcXVpcmVkVmFsaWRhdG9yLFxuICBTdGVwVmFsaWRhdG9yLFxuICBVUkxWYWxpZGF0b3IsXG4gIFZhbGlkYXRpb25LZXlzLFxuICBWYWxpZGF0b3IsXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcblxuLyoqXG4gKiBAZW51bSBVSUtleXNcbiAqIEBjYXRlZ29yeSBDb25zdGFudHNcbiAqL1xuZXhwb3J0IGNvbnN0IFVJS2V5cyA9IHtcbiAgUkVGTEVDVDogYCR7TW9kZWxLZXlzLlJFRkxFQ1R9LnVpLmAsXG4gIFVJTU9ERUw6IFwidWltb2RlbFwiLFxuICBSRU5ERVJFRF9CWTogXCJyZW5kZXJlZC1ieVwiLFxuICBFTEVNRU5UOiBcImVsZW1lbnRcIixcbiAgUFJPUDogXCJwcm9wXCIsXG4gIE5BTUU6IFwibmFtZVwiLFxuICBOQU1FX1BSRUZJWDogXCJpbnB1dC1cIixcbiAgQ1VTVE9NX1BST1BTOiBcImN1c3RvbVZhbGlkYXRpb25Qcm9wc1wiLFxuXG4gIFRZUEU6IFwidHlwZVwiLFxuICBTVUJfVFlQRTogXCJzdWJ0eXBlXCIsXG5cbiAgSElEREVOOiBcImhpZGRlblwiLFxuICBGT1JNQVQ6IFwiZm9ybWF0XCIsXG5cbiAgUkVBRF9PTkxZOiBcInJlYWRvbmx5XCIsXG4gIFJFUVVJUkVEOiBWYWxpZGF0aW9uS2V5cy5SRVFVSVJFRCxcbiAgTUlOOiBWYWxpZGF0aW9uS2V5cy5NSU4sXG4gIE1JTl9MRU5HVEg6IFZhbGlkYXRpb25LZXlzLk1JTl9MRU5HVEgsXG4gIE1BWDogVmFsaWRhdGlvbktleXMuTUFYLFxuICBNQVhfTEVOR1RIOiBWYWxpZGF0aW9uS2V5cy5NQVhfTEVOR1RILFxuICBQQVRURVJOOiBWYWxpZGF0aW9uS2V5cy5QQVRURVJOLFxuICBVUkw6IFZhbGlkYXRpb25LZXlzLlVSTCxcbiAgU1RFUDogVmFsaWRhdGlvbktleXMuU1RFUCxcbiAgREFURTogVmFsaWRhdGlvbktleXMuREFURSxcbiAgRU1BSUw6IFZhbGlkYXRpb25LZXlzLkVNQUlMLFxuICBQQVNTV09SRDogVmFsaWRhdGlvbktleXMuUEFTU1dPUkQsXG4gIEVRVUFMUzogVmFsaWRhdGlvbktleXMuRVFVQUxTLFxuICBESUZGOiBWYWxpZGF0aW9uS2V5cy5ESUZGLFxuICBMRVNTX1RIQU46IFZhbGlkYXRpb25LZXlzLkxFU1NfVEhBTixcbiAgTEVTU19USEFOX09SX0VRVUFMOiBWYWxpZGF0aW9uS2V5cy5MRVNTX1RIQU5fT1JfRVFVQUwsXG4gIEdSRUFURVJfVEhBTjogVmFsaWRhdGlvbktleXMuR1JFQVRFUl9USEFOLFxuICBHUkVBVEVSX1RIQU5fT1JfRVFVQUw6IFZhbGlkYXRpb25LZXlzLkdSRUFURVJfVEhBTl9PUl9FUVVBTCxcbn07XG5cbmV4cG9ydCBjb25zdCBWYWxpZGF0YWJsZUJ5VHlwZTogUmVjb3JkPHN0cmluZywgQ29uc3RydWN0b3I8VmFsaWRhdG9yPj4gPSB7XG4gIFtVSUtleXMuRU1BSUxdOiBFbWFpbFZhbGlkYXRvcixcbiAgW1VJS2V5cy5VUkxdOiBVUkxWYWxpZGF0b3IsXG4gIFtVSUtleXMuREFURV06IERhdGVWYWxpZGF0b3IsXG4gIFtVSUtleXMuUEFTU1dPUkRdOiBQYXNzd29yZFZhbGlkYXRvcixcbn07XG5cbi8qKlxuICogQGNvbnN0YW50IFZhbGlkYXRhYmxlQnlBdHRyaWJ1dGVcbiAqXG4gKiBAbWVtYmVyT2YgdWktZGVjb3JhdG9ycy13ZWIudWlcbiAqL1xuZXhwb3J0IGNvbnN0IFZhbGlkYXRhYmxlQnlBdHRyaWJ1dGU6IFJlY29yZDxzdHJpbmcsIENvbnN0cnVjdG9yPFZhbGlkYXRvcj4+ID0ge1xuICBbVUlLZXlzLlJFUVVJUkVEXTogUmVxdWlyZWRWYWxpZGF0b3IsXG4gIFtVSUtleXMuTUlOXTogTWluVmFsaWRhdG9yLFxuICBbVUlLZXlzLk1BWF06IE1heFZhbGlkYXRvcixcbiAgW1VJS2V5cy5TVEVQXTogU3RlcFZhbGlkYXRvcixcbiAgW1VJS2V5cy5NSU5fTEVOR1RIXTogTWluTGVuZ3RoVmFsaWRhdG9yLFxuICBbVUlLZXlzLk1BWF9MRU5HVEhdOiBNYXhMZW5ndGhWYWxpZGF0b3IsXG4gIFtVSUtleXMuUEFUVEVSTl06IFBhdHRlcm5WYWxpZGF0b3IsXG4gIFtVSUtleXMuRVFVQUxTXTogRXF1YWxzVmFsaWRhdG9yLFxuICBbVUlLZXlzLkRJRkZdOiBEaWZmVmFsaWRhdG9yLFxuICBbVUlLZXlzLkxFU1NfVEhBTl06IExlc3NUaGFuVmFsaWRhdG9yLFxuICBbVUlLZXlzLkxFU1NfVEhBTl9PUl9FUVVBTF06IExlc3NUaGFuT3JFcXVhbFZhbGlkYXRvcixcbiAgW1VJS2V5cy5HUkVBVEVSX1RIQU5dOiBHcmVhdGVyVGhhblZhbGlkYXRvcixcbiAgW1VJS2V5cy5HUkVBVEVSX1RIQU5fT1JfRVFVQUxdOiBHcmVhdGVyVGhhbk9yRXF1YWxWYWxpZGF0b3IsXG59O1xuXG5leHBvcnQgY29uc3QgSFRNTDVEYXRlRm9ybWF0ID0gXCJ5eXl5LU1NLWRkXCI7XG5cbmV4cG9ydCBjb25zdCBIVE1MNUlucHV0VHlwZXMgPSB7XG4gIEJVVFRPTjogXCJidXR0b25cIixcbiAgQ0hFQ0tCT1g6IFwiY2hlY2tib3hcIixcbiAgQ09MT1I6IFwiY29sb3JcIixcbiAgREFURTogVUlLZXlzLkRBVEUsXG4gIERBVEVUSU1FX0xPQ0FMOiBcImRhdGV0aW1lLWxvY2FsXCIsXG4gIEVNQUlMOiBVSUtleXMuRU1BSUwsXG4gIEZJTEU6IFwiZmlsZVwiLFxuICBISURERU46IFwiaGlkZGVuXCIsXG4gIElNQUdFOiBcImltYWdlXCIsXG4gIE1PTlRIOiBcIm1vbnRoXCIsXG4gIE5VTUJFUjogXCJudW1iZXJcIixcbiAgUEFTU1dPUkQ6IFVJS2V5cy5QQVNTV09SRCxcbiAgUkFESU86IFwicmFkaW9cIixcbiAgUkFOR0U6IFwicmFuZ2VcIixcbiAgUkVTRVQ6IFwicmVzZXRcIixcbiAgU0VBUkNIOiBcInNlYXJjaFwiLFxuICBTVUJNSVQ6IFwic3VibWl0XCIsXG4gIFRFTDogXCJ0ZWxcIixcbiAgVEVYVDogXCJ0ZXh0XCIsXG4gIFRJTUU6IFwidGltZVwiLFxuICBVUkw6IFVJS2V5cy5VUkwsXG4gIFdFRUs6IFwid2Vla1wiLFxufTtcblxuZXhwb3J0IGNvbnN0IEhUTUw1Q2hlY2tUeXBlcyA9IFtcbiAgSFRNTDVJbnB1dFR5cGVzLkNIRUNLQk9YLFxuICBIVE1MNUlucHV0VHlwZXMuUkFESU8sXG5dO1xuIiwiaW1wb3J0IHsgQmFzZUVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5cbmV4cG9ydCBjbGFzcyBSZW5kZXJpbmdFcnJvciBleHRlbmRzIEJhc2VFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihSZW5kZXJpbmdFcnJvci5uYW1lLCBtc2cpO1xuICB9XG59XG4iLCJpbXBvcnQge1xuICBmb3JtYXREYXRlLFxuICBNb2RlbCxcbiAgcGFyc2VEYXRlLFxuICBSZXNlcnZlZE1vZGVscyxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgSFRNTDVEYXRlRm9ybWF0LCBIVE1MNUlucHV0VHlwZXMsIFVJS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgZmluZE1vZGVsSWQsIEludGVybmFsRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcbmltcG9ydCB7IEZpZWxkUHJvcGVydGllcyB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogQGZ1bmN0aW9uIGZvcm1hdEJ5VHlwZVxuICpcbiAqIEBtZW1iZXJPZiB1aS1kZWNvcmF0b3JzLXdlYi51aVxuICovXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0QnlUeXBlKFxuICB0eXBlOiBhbnksXG4gIHZhbHVlOiBhbnksXG4gIC4uLmFyZ3M6IHVua25vd25bXVxuKTogc3RyaW5nIHwgbnVtYmVyIHtcbiAgaWYgKHR5cGUgPT09IFVJS2V5cy5EQVRFKSB7XG4gICAgY29uc3QgZm9ybWF0OiBzdHJpbmcgPSAoYXJncy5zaGlmdCgpIGFzIHN0cmluZykgfHwgSFRNTDVEYXRlRm9ybWF0O1xuICAgIHJldHVybiBmb3JtYXREYXRlKG5ldyBEYXRlKHZhbHVlKSwgZm9ybWF0KTtcbiAgfVxuICByZXR1cm4gdmFsdWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVZhbHVlQnlUeXBlKFxuICB0eXBlOiBzdHJpbmcsXG4gIHZhbHVlOiBzdHJpbmcgfCBudW1iZXIsXG4gIGZpZWxkUHJvcHM6IEZpZWxkUHJvcGVydGllc1xuKTogc3RyaW5nIHwgbnVtYmVyIHwgRGF0ZSB7XG4gIGxldCByZXN1bHQ6IHN0cmluZyB8IG51bWJlciB8IERhdGUgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLk5VTUJFUjpcbiAgICAgIHJlc3VsdCA9IHBhcnNlVG9OdW1iZXIodmFsdWUpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBIVE1MNUlucHV0VHlwZXMuREFURToge1xuICAgICAgY29uc3QgZm9ybWF0OiBzdHJpbmcgfCB1bmRlZmluZWQgPSBmaWVsZFByb3BzLmZvcm1hdDtcbiAgICAgIHJlc3VsdCA9XG4gICAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gUmVzZXJ2ZWRNb2RlbHMuTlVNQkVSXG4gICAgICAgICAgPyBuZXcgRGF0ZSh2YWx1ZSlcbiAgICAgICAgICA6IHZhbHVlXG4gICAgICAgICAgICA/IGZvcm1hdFxuICAgICAgICAgICAgICA/IHBhcnNlRGF0ZShmb3JtYXQsIHZhbHVlKVxuICAgICAgICAgICAgICA6IG5ldyBEYXRlKHZhbHVlKVxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgZGVmYXVsdDpcbiAgICAgIHJlc3VsdCA9XG4gICAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gUmVzZXJ2ZWRNb2RlbHMuU1RSSU5HXG4gICAgICAgICAgPyBlc2NhcGVIdG1sKHZhbHVlIGFzIHN0cmluZylcbiAgICAgICAgICA6IHJlc3VsdDtcbiAgfVxuICBpZiAodHlwZW9mIHJlc3VsdCA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgYEZhaWxlZCB0byBwYXJzZSB2YWx1ZSBvZiB0eXBlICR7dHlwZX0gZnJvbSAke3R5cGVvZiB2YWx1ZX0gLSAke3ZhbHVlfWBcbiAgICApO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVRvTnVtYmVyKHZhbHVlOiBzdHJpbmcgfCBudW1iZXIpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIiAmJiAhaXNOYU4odmFsdWUpKSByZXR1cm4gdmFsdWU7XG5cbiAgY29uc3QgcGFyc2VkID0gTnVtYmVyKHZhbHVlKTtcbiAgaWYgKCFpc05hTihwYXJzZWQpKSByZXR1cm4gcGFyc2VkO1xuXG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlc2NhcGVIdG1sKHZhbHVlOiBzdHJpbmcpIHtcbiAgaWYgKCF2YWx1ZSkgXG4gICAgcmV0dXJuIHZhbHVlO1xuXG4gIGNvbnN0IHRhZ3NUb1JlcGxhY2U6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgXCImXCI6IFwiJmFtcDtcIixcbiAgICBcIjxcIjogXCImbHQ7XCIsXG4gICAgXCI+XCI6IFwiJmd0O1wiLFxuICB9O1xuICByZXR1cm4gYCR7dmFsdWV9YC5yZXBsYWNlKC9bJjw+XS9nLCAodGFnKSA9PiB7XG4gICAgcmV0dXJuIHRhZ3NUb1JlcGxhY2VbdGFnXSB8fCB0YWc7XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmV2ZXJ0SHRtbCh2YWx1ZTogc3RyaW5nKSB7XG4gIGNvbnN0IHRhZ3NUb1JlcGxhY2U6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgXCImYW1wO1wiOiBcIiZcIixcbiAgICBcIiZsdDtcIjogXCI8XCIsXG4gICAgXCImZ3Q7XCI6IFwiPlwiLFxuICB9O1xuXG4gIHJldHVybiBgJHt2YWx1ZX1gLnJlcGxhY2UoLyZsdDt8Jmd0O3wmYW1wOy9nLCAodGFnKSA9PiB7XG4gICAgcmV0dXJuIHRhZ3NUb1JlcGxhY2VbdGFnXSB8fCB0YWc7XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVVSU1vZGVsSUQ8TSBleHRlbmRzIE1vZGVsPihtb2RlbDogTSkge1xuICBsZXQgaWQ6IHN0cmluZyB8IG51bWJlcjtcbiAgdHJ5IHtcbiAgICBpZCA9IGZpbmRNb2RlbElkKG1vZGVsKTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICBpZCA9IERhdGUubm93KCk7XG4gIH1cbiAgY29uc3QgbmFtZSA9IG1vZGVsLmNvbnN0cnVjdG9yLm5hbWU7XG4gIHJldHVybiBgJHtuYW1lfS0ke2lkfWA7XG59XG4iLCJpbXBvcnQgeyBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQge1xuICBDb21wYXJpc29uVmFsaWRhdGlvbktleXMsXG4gIENvbnN0cnVjdG9yLFxuICBNb2RlbCxcbiAgTW9kZWxDb25zdHJ1Y3RvcixcbiAgUmVzZXJ2ZWRNb2RlbHMsXG4gIFZhbGlkYXRpb25LZXlzLFxuICBWYWxpZGF0aW9uTWV0YWRhdGEsXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7XG4gIEhUTUw1RGF0ZUZvcm1hdCxcbiAgSFRNTDVJbnB1dFR5cGVzLFxuICBVSUtleXMsXG4gIFZhbGlkYXRhYmxlQnlBdHRyaWJ1dGUsXG4gIFZhbGlkYXRhYmxlQnlUeXBlLFxufSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7XG4gIEZpZWxkRGVmaW5pdGlvbixcbiAgRmllbGRQcm9wZXJ0aWVzLFxuICBVSUVsZW1lbnRNZXRhZGF0YSxcbiAgVUlNb2RlbE1ldGFkYXRhLFxuICBVSVByb3BNZXRhZGF0YSxcbn0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IFJlbmRlcmluZ0Vycm9yIH0gZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQgeyBSZWZsZWN0aW9uLCBEZWNvcmF0b3JNZXRhZGF0YSB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuaW1wb3J0IHsgZm9ybWF0QnlUeXBlLCBnZW5lcmF0ZVVJTW9kZWxJRCB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEFic3RyYWN0IGNsYXNzIGZvciByZW5kZXJpbmcgVUkgY29tcG9uZW50cyBiYXNlZCBvbiBtb2RlbCBtZXRhZGF0YS5cbiAqIEBzdW1tYXJ5IFRoZSBSZW5kZXJpbmdFbmdpbmUgY2xhc3MgcHJvdmlkZXMgYSBmcmFtZXdvcmsgZm9yIGNvbnZlcnRpbmcgbW9kZWwgbWV0YWRhdGEgaW50byBVSSBmaWVsZCBkZWZpbml0aW9ucy5cbiAqIEl0IGhhbmRsZXMgdGhlIHRyYW5zbGF0aW9uIG9mIG1vZGVsIHByb3BlcnRpZXMgdG8gVUkgZWxlbWVudHMsIGFwcGxpZXMgdmFsaWRhdGlvbiBydWxlcywgYW5kIG1hbmFnZXMgZGlmZmVyZW50IHJlbmRlcmluZyBmbGF2b3JzLlxuICogVGhpcyBjbGFzcyBpcyBkZXNpZ25lZCB0byBiZSBleHRlbmRlZCBieSBzcGVjaWZpYyByZW5kZXJpbmcgaW1wbGVtZW50YXRpb25zLlxuICpcbiAqIEB0ZW1wbGF0ZSBUIFRoZSB0eXBlIG9mIHRoZSByZW5kZXJpbmcgcmVzdWx0LCBkZWZhdWx0cyB0byB2b2lkXG4gKiBAdGVtcGxhdGUgUiBUaGUgdHlwZSBvZiB0aGUgZmllbGQgZGVmaW5pdGlvbiwgZGVmYXVsdHMgdG8gRmllbGREZWZpbml0aW9uPFQ+XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGZsYXZvdXIgLSBUaGUgZmxhdm9yIG9mIHRoZSByZW5kZXJpbmcgZW5naW5lLlxuICpcbiAqIEBjbGFzcyBSZW5kZXJpbmdFbmdpbmVcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFJlbmRlcmluZ0VuZ2luZTxUID0gdm9pZCwgUiA9IEZpZWxkRGVmaW5pdGlvbjxUPj4ge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENhY2hlIGZvciBzdG9yaW5nIHJlbmRlcmluZyBlbmdpbmUgaW5zdGFuY2VzIG9yIGNvbnN0cnVjdG9ycy5cbiAgICogQHByaXZhdGVcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgY2FjaGU6IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgfCBDb25zdHJ1Y3RvcjxSZW5kZXJpbmdFbmdpbmU8dW5rbm93biwgdW5rbm93bj4+XG4gICAgfCBSZW5kZXJpbmdFbmdpbmU8dW5rbm93biwgdW5rbm93bj5cbiAgPiA9IHt9O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIGN1cnJlbnRseSBhY3RpdmUgcmVuZGVyaW5nIGVuZ2luZS5cbiAgICogQHByaXZhdGVcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgY3VycmVudDpcbiAgICB8IENvbnN0cnVjdG9yPFJlbmRlcmluZ0VuZ2luZTx1bmtub3duLCB1bmtub3duPj5cbiAgICB8IFJlbmRlcmluZ0VuZ2luZTx1bmtub3duLCB1bmtub3duPjtcblxuICAvKipcbiAgICogRmxhZyBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIHJlbmRlcmluZyBlbmdpbmUgaGFzIGJlZW4gaW5pdGlhbGl6ZWQuXG4gICAqL1xuICBwcm90ZWN0ZWQgaW5pdGlhbGl6ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IocmVhZG9ubHkgZmxhdm91cjogc3RyaW5nKSB7XG4gICAgUmVuZGVyaW5nRW5naW5lLnJlZ2lzdGVyKHRoaXMpO1xuICAgIGNvbnNvbGUubG9nKGBkZWNhZidzICR7Zmxhdm91cn0gcmVuZGVyaW5nIGVuZ2luZSBsb2FkZWRgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW5pdGlhbGl6ZXMgdGhlIHJlbmRlcmluZyBlbmdpbmUuXG4gICAqIEBzdW1tYXJ5IEFic3RyYWN0IG1ldGhvZCB0byBiZSBpbXBsZW1lbnRlZCBieSBzdWJjbGFzc2VzIGZvciBzcGVjaWZpYyBpbml0aWFsaXphdGlvbiBsb2dpYy5cbiAgICpcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyBuZWVkZWQgZm9yIGluaXRpYWxpemF0aW9uLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBpbml0aWFsaXphdGlvbiBpcyBjb21wbGV0ZS5cbiAgICpcbiAgICogQGFic3RyYWN0XG4gICAqL1xuICBhYnN0cmFjdCBpbml0aWFsaXplKC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTx2b2lkPjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRyYW5zbGF0ZXMgYmV0d2VlbiBtb2RlbCB0eXBlcyBhbmQgSFRNTCBpbnB1dCB0eXBlcy5cbiAgICogQHN1bW1hcnkgQ29udmVydHMgbW9kZWwgZGF0YSB0eXBlcyB0byBhcHByb3ByaWF0ZSBIVE1MIGlucHV0IHR5cGVzIGFuZCB2aWNlIHZlcnNhLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIGtleSB0byB0cmFuc2xhdGUuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW3RvVmlldz10cnVlXSAtIERpcmVjdGlvbiBvZiB0cmFuc2xhdGlvbiAodHJ1ZSBmb3IgbW9kZWwgdG8gdmlldywgZmFsc2UgZm9yIHZpZXcgdG8gbW9kZWwpLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgdHJhbnNsYXRlZCB0eXBlLlxuICAgKi9cbiAgdHJhbnNsYXRlKGtleTogc3RyaW5nLCB0b1ZpZXc6IGJvb2xlYW4gPSB0cnVlKTogc3RyaW5nIHtcbiAgICBpZiAodG9WaWV3KSB7XG4gICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICBjYXNlIFJlc2VydmVkTW9kZWxzLlNUUklORzpcbiAgICAgICAgICByZXR1cm4gSFRNTDVJbnB1dFR5cGVzLlRFWFQ7XG4gICAgICAgIGNhc2UgUmVzZXJ2ZWRNb2RlbHMuTlVNQkVSOlxuICAgICAgICBjYXNlIFJlc2VydmVkTW9kZWxzLkJJR0lOVDpcbiAgICAgICAgICByZXR1cm4gSFRNTDVJbnB1dFR5cGVzLk5VTUJFUjtcbiAgICAgICAgY2FzZSBSZXNlcnZlZE1vZGVscy5CT09MRUFOOlxuICAgICAgICAgIHJldHVybiBIVE1MNUlucHV0VHlwZXMuQ0hFQ0tCT1g7XG4gICAgICAgIGNhc2UgUmVzZXJ2ZWRNb2RlbHMuREFURTpcbiAgICAgICAgICByZXR1cm4gSFRNTDVJbnB1dFR5cGVzLkRBVEU7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLlRFWFQ6XG4gICAgICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLkVNQUlMOlxuICAgICAgICBjYXNlIEhUTUw1SW5wdXRUeXBlcy5DT0xPUjpcbiAgICAgICAgY2FzZSBIVE1MNUlucHV0VHlwZXMuUEFTU1dPUkQ6XG4gICAgICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLlRFTDpcbiAgICAgICAgY2FzZSBIVE1MNUlucHV0VHlwZXMuVVJMOlxuICAgICAgICAgIHJldHVybiBSZXNlcnZlZE1vZGVscy5TVFJJTkc7XG4gICAgICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLk5VTUJFUjpcbiAgICAgICAgICByZXR1cm4gUmVzZXJ2ZWRNb2RlbHMuTlVNQkVSO1xuICAgICAgICBjYXNlIEhUTUw1SW5wdXRUeXBlcy5DSEVDS0JPWDpcbiAgICAgICAgICByZXR1cm4gUmVzZXJ2ZWRNb2RlbHMuQk9PTEVBTjtcbiAgICAgICAgY2FzZSBIVE1MNUlucHV0VHlwZXMuREFURTpcbiAgICAgICAgY2FzZSBIVE1MNUlucHV0VHlwZXMuREFURVRJTUVfTE9DQUw6XG4gICAgICAgIGNhc2UgSFRNTDVJbnB1dFR5cGVzLlRJTUU6XG4gICAgICAgICAgcmV0dXJuIFJlc2VydmVkTW9kZWxzLkRBVEU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBrZXk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENoZWNrcyBpZiBhIHR5cGUgaXMgdmFsaWRhdGFibGUgYnkgaXRzIG5hdHVyZS5cbiAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyBpZiBhIGdpdmVuIFVJIGtleSByZXByZXNlbnRzIGEgdHlwZSB0aGF0IGlzIGluaGVyZW50bHkgdmFsaWRhdGFibGUuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUgVUkga2V5IHRvIGNoZWNrLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdHlwZSBpcyB2YWxpZGF0YWJsZSwgZmFsc2Ugb3RoZXJ3aXNlLlxuICAgKi9cbiAgcHJvdGVjdGVkIGlzVmFsaWRhdGFibGVCeVR5cGUoa2V5OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gT2JqZWN0LmtleXMoVmFsaWRhdGFibGVCeVR5cGUpLmluY2x1ZGVzKGtleSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENoZWNrcyBpZiBhIHR5cGUgaXMgdmFsaWRhdGFibGUgYnkgYXR0cmlidXRlLlxuICAgKiBAc3VtbWFyeSBEZXRlcm1pbmVzIGlmIGEgZ2l2ZW4gVUkga2V5IHJlcHJlc2VudHMgYSB2YWxpZGF0aW9uIHRoYXQgY2FuIGJlIGFwcGxpZWQgYXMgYW4gYXR0cmlidXRlLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIFVJIGtleSB0byBjaGVjay5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHR5cGUgaXMgdmFsaWRhdGFibGUgYnkgYXR0cmlidXRlLCBmYWxzZSBvdGhlcndpc2UuXG4gICAqL1xuICBwcm90ZWN0ZWQgaXNWYWxpZGF0YWJsZUJ5QXR0cmlidXRlKGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKFZhbGlkYXRhYmxlQnlBdHRyaWJ1dGUpLmluY2x1ZGVzKGtleSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENvbnZlcnRzIHZhbGlkYXRpb24gbWV0YWRhdGEgdG8gYW4gYXR0cmlidXRlIHZhbHVlLlxuICAgKiBAc3VtbWFyeSBUcmFuc2Zvcm1zIHZhbGlkYXRpb24gbWV0YWRhdGEgaW50byBhIHZhbHVlIHN1aXRhYmxlIGZvciB1c2UgYXMgYW4gSFRNTCBhdHRyaWJ1dGUuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUgdmFsaWRhdGlvbiBrZXkuXG4gICAqIEBwYXJhbSB7VmFsaWRhdGlvbk1ldGFkYXRhfSB2YWx1ZSAtIFRoZSB2YWxpZGF0aW9uIG1ldGFkYXRhLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbn0gVGhlIGNvbnZlcnRlZCBhdHRyaWJ1dGUgdmFsdWUuXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgZ2l2ZW4ga2V5IGlzIG5vdCB2YWxpZGF0YWJsZSBieSBhdHRyaWJ1dGUuXG4gICAqL1xuICBwcm90ZWN0ZWQgdG9BdHRyaWJ1dGVWYWx1ZShcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsaWRhdGlvbk1ldGFkYXRhXG4gICk6IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4ge1xuICAgIGlmICghT2JqZWN0LmtleXMoVmFsaWRhdGFibGVCeUF0dHJpYnV0ZSkuaW5jbHVkZXMoa2V5KSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEludmFsaWQgYXR0cmlidXRlIGtleSBcIiR7a2V5fVwiLiBFeHBlY3RlZCBvbmUgb2Y6ICR7T2JqZWN0LmtleXMoVmFsaWRhdGFibGVCeUF0dHJpYnV0ZSkuam9pbihcIiwgXCIpfS5gXG4gICAgICApO1xuXG4gICAgcmV0dXJuIGtleSA9PT0gVUlLZXlzLlJFUVVJUkVEXG4gICAgICA/IHRydWVcbiAgICAgIDogT2JqZWN0LnZhbHVlcyhDb21wYXJpc29uVmFsaWRhdGlvbktleXMpLmluY2x1ZGVzKGtleSBhcyBhbnkpXG4gICAgICAgID8gdmFsdWUucHJvcGVydHlUb0NvbXBhcmVcbiAgICAgICAgOiB2YWx1ZVtrZXldO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDb252ZXJ0cyBhIG1vZGVsIHRvIGEgZmllbGQgZGVmaW5pdGlvbi5cbiAgICogQHN1bW1hcnkgUHJvY2Vzc2VzIGEgbW9kZWwgaW5zdGFuY2UsIGV4dHJhY3RpbmcgVUktcmVsYXRlZCBtZXRhZGF0YSBhbmQgdmFsaWRhdGlvbiBydWxlcyB0byBjcmVhdGUgYSBmaWVsZCBkZWZpbml0aW9uLlxuICAgKlxuICAgKiBAdGVtcGxhdGUgTSBUeXBlIGV4dGVuZGluZyBNb2RlbFxuICAgKiBAdGVtcGxhdGUgVCBUeXBlIHJlZmVyZW5jaW5nIHRoZSBzcGVjaWZpYyBSZW5kZXJpbmcgZW5naW5lIGZpZWxkIHByb3BlcnRpZXMvaW5wdXRzXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgdG8gY29udmVydC5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gW2dsb2JhbFByb3BzPXt9XSAtIEdsb2JhbCBwcm9wZXJ0aWVzIHRvIGFwcGx5IHRvIGFsbCBjaGlsZCBlbGVtZW50cy5cbiAgICogQHBhcmFtIHtib29sZWFufSBbZ2VuZXJhdGVJZD10cnVlXSAtIEZsYWcgaW5kaWNhdGluZyB3aGV0aGVyIHRvIHBvcHVsYXRlIHRoZSByZW5kZXJlcklkIHByb3BlcnR5LlxuICAgKiBAcmV0dXJucyB7RmllbGREZWZpbml0aW9uPFQ+fSBBIGZpZWxkIGRlZmluaXRpb24gb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgVUkgc3RydWN0dXJlIG9mIHRoZSBtb2RlbC5cbiAgICogQHRocm93cyB7UmVuZGVyaW5nRXJyb3J9IElmIG5vIFVJIGRlZmluaXRpb25zIGFyZSBzZXQgZm9yIHRoZSBtb2RlbCBvciBpZiB0aGVyZSBhcmUgaW52YWxpZCBkZWNvcmF0b3JzLlxuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogIHBhcnRpY2lwYW50IEMgYXMgQ2xpZW50XG4gICAqICBwYXJ0aWNpcGFudCBSRSBhcyBSZW5kZXJpbmdFbmdpbmVcbiAgICogIHBhcnRpY2lwYW50IFIgYXMgUmVmbGVjdGlvblxuICAgKiAgcGFydGljaXBhbnQgTSBhcyBNb2RlbFxuICAgKiAgQy0+PlJFOiB0b0ZpZWxkRGVmaW5pdGlvbihtb2RlbCwgZ2xvYmFsUHJvcHMpXG4gICAqICBSRS0+PlI6IGdldE1ldGFkYXRhKFVJS2V5cy5VSU1PREVMLCBtb2RlbC5jb25zdHJ1Y3RvcilcbiAgICogIFItLT4+UkU6IFVJTW9kZWxNZXRhZGF0YVxuICAgKiAgUkUtPj5SOiBnZXRBbGxQcm9wZXJ0eURlY29yYXRvcnMobW9kZWwsIFVJS2V5cy5SRUZMRUNUKVxuICAgKiAgUi0tPj5SRTogUmVjb3JkPHN0cmluZywgRGVjb3JhdG9yTWV0YWRhdGFbXT5cbiAgICogIFJFLT4+UjogZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzKG1vZGVsLCBWYWxpZGF0aW9uS2V5cy5SRUZMRUNUKVxuICAgKiAgUi0tPj5SRTogUmVjb3JkPHN0cmluZywgRGVjb3JhdG9yTWV0YWRhdGE8VmFsaWRhdGlvbk1ldGFkYXRhPltdPlxuICAgKiAgbG9vcCBGb3IgZWFjaCBwcm9wZXJ0eVxuICAgKiAgICBSRS0+PlJFOiBQcm9jZXNzIFVJIGRlY29yYXRvcnNcbiAgICogICAgUkUtPj5SRTogQXBwbHkgdmFsaWRhdGlvbiBydWxlc1xuICAgKiAgZW5kXG4gICAqICBSRS0tPj5DOiBGaWVsZERlZmluaXRpb248VD5cbiAgICovXG4gIHByb3RlY3RlZCB0b0ZpZWxkRGVmaW5pdGlvbjxNIGV4dGVuZHMgTW9kZWw+KFxuICAgIG1vZGVsOiBNLFxuICAgIGdsb2JhbFByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9LFxuICAgIGdlbmVyYXRlSWQ6IGJvb2xlYW4gPSB0cnVlXG4gICk6IEZpZWxkRGVmaW5pdGlvbjxUPiB7XG4gICAgY29uc3QgY2xhc3NEZWNvcmF0b3I6IFVJTW9kZWxNZXRhZGF0YSA9XG4gICAgICBSZWZsZWN0LmdldE1ldGFkYXRhKFxuICAgICAgICBSZW5kZXJpbmdFbmdpbmUua2V5KFVJS2V5cy5VSU1PREVMKSxcbiAgICAgICAgbW9kZWwuY29uc3RydWN0b3JcbiAgICAgICkgfHxcbiAgICAgIFJlZmxlY3QuZ2V0TWV0YWRhdGEoXG4gICAgICAgIFJlbmRlcmluZ0VuZ2luZS5rZXkoVUlLZXlzLlVJTU9ERUwpLFxuICAgICAgICBNb2RlbC5nZXQobW9kZWwuY29uc3RydWN0b3IubmFtZSkgYXMgYW55XG4gICAgICApO1xuXG4gICAgaWYgKCFjbGFzc0RlY29yYXRvcilcbiAgICAgIHRocm93IG5ldyBSZW5kZXJpbmdFcnJvcihcbiAgICAgICAgYE5vIHVpIGRlZmluaXRpb25zIHNldCBmb3IgbW9kZWwgJHttb2RlbC5jb25zdHJ1Y3Rvci5uYW1lfS4gRGlkIHlvdSB1c2UgQHVpbW9kZWw/YFxuICAgICAgKTtcblxuICAgIGNvbnN0IHsgdGFnLCBwcm9wcyB9ID0gY2xhc3NEZWNvcmF0b3I7XG5cbiAgICBjb25zdCB1aURlY29yYXRvcnM6IFJlY29yZDxzdHJpbmcsIERlY29yYXRvck1ldGFkYXRhW10+ID1cbiAgICAgIFJlZmxlY3Rpb24uZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzKG1vZGVsLCBVSUtleXMuUkVGTEVDVCkgYXMgUmVjb3JkPFxuICAgICAgICBzdHJpbmcsXG4gICAgICAgIERlY29yYXRvck1ldGFkYXRhW11cbiAgICAgID47XG4gICAgbGV0IGNoaWxkcmVuOiBGaWVsZERlZmluaXRpb248UmVjb3JkPHN0cmluZywgYW55Pj5bXSB8IHVuZGVmaW5lZDtcbiAgICBjb25zdCBjaGlsZFByb3BzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG5cbiAgICBpZiAodWlEZWNvcmF0b3JzKSB7XG4gICAgICBjb25zdCB2YWxpZGF0aW9uRGVjb3JhdG9yczogUmVjb3JkPFxuICAgICAgICBzdHJpbmcsXG4gICAgICAgIERlY29yYXRvck1ldGFkYXRhPFZhbGlkYXRpb25NZXRhZGF0YT5bXVxuICAgICAgPiA9IFJlZmxlY3Rpb24uZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzKFxuICAgICAgICBtb2RlbCxcbiAgICAgICAgVmFsaWRhdGlvbktleXMuUkVGTEVDVFxuICAgICAgKSBhcyBSZWNvcmQ8c3RyaW5nLCBEZWNvcmF0b3JNZXRhZGF0YTxWYWxpZGF0aW9uTWV0YWRhdGE+W10+O1xuXG4gICAgICBmb3IgKGNvbnN0IGtleSBpbiB1aURlY29yYXRvcnMpIHtcbiAgICAgICAgY29uc3QgZGVjcyA9IHVpRGVjb3JhdG9yc1trZXldO1xuICAgICAgICBpZiAoZGVjcy5sZW5ndGggIT09IDIpXG4gICAgICAgICAgdGhyb3cgbmV3IFJlbmRlcmluZ0Vycm9yKFxuICAgICAgICAgICAgYE9ubHkgb25lIHR5cGUgb2YgZGVjb3JhdGlvbiBpcyBhbGxvd2VkLiBQbGVhc2UgY2hvb3NlIGJldHdlZW4gQHVpcHJvcCBhbmQgQHVpZWxlbWVudGBcbiAgICAgICAgICApO1xuICAgICAgICBjb25zdCBkZWMgPSBkZWNzWzFdOyAvLyBJZ25vcmUgMCwgaXRzIHRoZSBkZXNpZ246dHlwZVxuICAgICAgICBpZiAoIWRlYykgdGhyb3cgbmV3IFJlbmRlcmluZ0Vycm9yKGBObyBkZWNvcmF0b3IgZm91bmRgKTtcbiAgICAgICAgc3dpdGNoIChkZWMua2V5KSB7XG4gICAgICAgICAgY2FzZSBVSUtleXMuUFJPUDpcbiAgICAgICAgICAgIGNoaWxkUHJvcHNba2V5XSA9IGRlYy5wcm9wcyBhcyBVSVByb3BNZXRhZGF0YTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgVUlLZXlzLkVMRU1FTlQ6IHtcbiAgICAgICAgICAgIGNoaWxkcmVuID0gY2hpbGRyZW4gfHwgW107XG4gICAgICAgICAgICBjb25zdCBjaGlsZERlZmluaXRpb246IEZpZWxkRGVmaW5pdGlvbjxSZWNvcmQ8c3RyaW5nLCBhbnk+PiA9IHtcbiAgICAgICAgICAgICAgdGFnOiAoZGVjLnByb3BzIGFzIFVJRWxlbWVudE1ldGFkYXRhKS50YWcsXG4gICAgICAgICAgICAgIHByb3BzOiBPYmplY3QuYXNzaWduKFxuICAgICAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgICAgIChkZWMucHJvcHMgYXMgVUlFbGVtZW50TWV0YWRhdGEpLnByb3BzIGFzIGFueSxcbiAgICAgICAgICAgICAgICBnbG9iYWxQcm9wc1xuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3QgdmFsaWRhdGlvbkRlY3M6IERlY29yYXRvck1ldGFkYXRhPFZhbGlkYXRpb25NZXRhZGF0YT5bXSA9XG4gICAgICAgICAgICAgIHZhbGlkYXRpb25EZWNvcmF0b3JzW1xuICAgICAgICAgICAgICAgIGtleVxuICAgICAgICAgICAgICBdIGFzIERlY29yYXRvck1ldGFkYXRhPFZhbGlkYXRpb25NZXRhZGF0YT5bXTtcblxuICAgICAgICAgICAgY29uc3QgdHlwZURlYzogRGVjb3JhdG9yTWV0YWRhdGFPYmplY3QgPVxuICAgICAgICAgICAgICB2YWxpZGF0aW9uRGVjcy5zaGlmdCgpIGFzIERlY29yYXRvck1ldGFkYXRhO1xuICAgICAgICAgICAgZm9yIChjb25zdCBkZWMgb2YgdmFsaWRhdGlvbkRlY3MpIHtcbiAgICAgICAgICAgICAgaWYgKHRoaXMuaXNWYWxpZGF0YWJsZUJ5QXR0cmlidXRlKGRlYy5rZXkpKSB7XG4gICAgICAgICAgICAgICAgY2hpbGREZWZpbml0aW9uLnByb3BzW3RoaXMudHJhbnNsYXRlKGRlYy5rZXkpXSA9XG4gICAgICAgICAgICAgICAgICB0aGlzLnRvQXR0cmlidXRlVmFsdWUoZGVjLmtleSwgZGVjLnByb3BzKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAodGhpcy5pc1ZhbGlkYXRhYmxlQnlUeXBlKGRlYy5rZXkpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRlYy5rZXkgPT09IEhUTUw1SW5wdXRUeXBlcy5EQVRFKSB7XG4gICAgICAgICAgICAgICAgICBjaGlsZERlZmluaXRpb24ucHJvcHNbVUlLZXlzLkZPUk1BVF0gPVxuICAgICAgICAgICAgICAgICAgICBkZWMucHJvcHMuZm9ybWF0IHx8IEhUTUw1RGF0ZUZvcm1hdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2hpbGREZWZpbml0aW9uLnByb3BzW1VJS2V5cy5UWVBFXSA9IGRlYy5rZXk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY29uc29sZS5sb2coZGVjKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFjaGlsZERlZmluaXRpb24ucHJvcHNbVUlLZXlzLlRZUEVdKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGJhc2ljVHlwZSA9ICh0eXBlRGVjLnByb3BzIGFzIHsgbmFtZTogc3RyaW5nIH0pLm5hbWU7XG4gICAgICAgICAgICAgIGNoaWxkRGVmaW5pdGlvbi5wcm9wc1tVSUtleXMuVFlQRV0gPSB0aGlzLnRyYW5zbGF0ZShcbiAgICAgICAgICAgICAgICBiYXNpY1R5cGUudG9Mb3dlckNhc2UoKSxcbiAgICAgICAgICAgICAgICB0cnVlXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNoaWxkRGVmaW5pdGlvbi5wcm9wcy52YWx1ZSA9IGZvcm1hdEJ5VHlwZShcbiAgICAgICAgICAgICAgY2hpbGREZWZpbml0aW9uLnByb3BzW1VJS2V5cy5UWVBFXSxcbiAgICAgICAgICAgICAgbW9kZWxba2V5IGFzIGtleW9mIE1dLFxuICAgICAgICAgICAgICBjaGlsZERlZmluaXRpb24ucHJvcHNbVUlLZXlzLkZPUk1BVF1cbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGNoaWxkcmVuLnB1c2goY2hpbGREZWZpbml0aW9uKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IFJlbmRlcmluZ0Vycm9yKGBJbnZhbGlkIGtleTogJHtkZWMua2V5fWApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgcmVzdWx0OiBGaWVsZERlZmluaXRpb248VD4gPSB7XG4gICAgICB0YWc6IHRhZyxcbiAgICAgIHByb3BzOiBPYmplY3QuYXNzaWduKHt9LCBwcm9wcywgZ2xvYmFsUHJvcHMpIGFzIFQgJiBGaWVsZFByb3BlcnRpZXMsXG4gICAgICBjaGlsZHJlbjogY2hpbGRyZW4gYXMgRmllbGREZWZpbml0aW9uPGFueT5bXSxcbiAgICB9O1xuXG4gICAgaWYgKGdlbmVyYXRlSWQpIHtcbiAgICAgIHJlc3VsdC5yZW5kZXJlcklkID0gZ2VuZXJhdGVVSU1vZGVsSUQobW9kZWwpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlbmRlcnMgYSBtb2RlbCB3aXRoIGdsb2JhbCBwcm9wZXJ0aWVzIGFuZCBhZGRpdGlvbmFsIGFyZ3VtZW50cy5cbiAgICogQHN1bW1hcnkgQWJzdHJhY3QgbWV0aG9kIHRvIGJlIGltcGxlbWVudGVkIGJ5IHN1YmNsYXNzZXMgdG8gZGVmaW5lIHNwZWNpZmljIHJlbmRlcmluZyBiZWhhdmlvci5cbiAgICpcbiAgICogQHRlbXBsYXRlIE0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAgICogQHRlbXBsYXRlIFIgUmVuZGVyaW5nIGVuZ2luZSBpbXBsZW1lbnRhdGlvbiBzcGVjaWZpYyBvdXRwdXQgdHlwZVxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIHRvIGJlIHJlbmRlcmVkLlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIHVua25vd24+fSBnbG9iYWxQcm9wcyAtIEdsb2JhbCBwcm9wZXJ0aWVzIHRvIGJlIGFwcGxpZWQgdG8gYWxsIGVsZW1lbnRzIGR1cmluZyByZW5kZXJpbmcuXG4gICAqIEBwYXJhbSB7Li4uYW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0aGF0IG1heSBiZSByZXF1aXJlZCBmb3Igc3BlY2lmaWMgcmVuZGVyaW5nIGltcGxlbWVudGF0aW9ucy5cbiAgICogQHJldHVybnMge1J9IFRoZSByZW5kZXJlZCByZXN1bHQsIHR5cGUgZGVwZW5kcyBvbiB0aGUgc3BlY2lmaWMgaW1wbGVtZW50YXRpb24uXG4gICAqXG4gICAqIEBhYnN0cmFjdFxuICAgKi9cbiAgYWJzdHJhY3QgcmVuZGVyPE0gZXh0ZW5kcyBNb2RlbD4oXG4gICAgbW9kZWw6IE0sXG4gICAgZ2xvYmFsUHJvcHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFI7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWdpc3RlcnMgYSByZW5kZXJpbmcgZW5naW5lIGluc3RhbmNlLlxuICAgKiBAc3VtbWFyeSBBZGRzIGEgcmVuZGVyaW5nIGVuZ2luZSB0byB0aGUgc3RhdGljIGNhY2hlIGFuZCBzZXRzIGl0IGFzIHRoZSBjdXJyZW50IGVuZ2luZS5cbiAgICpcbiAgICogQHBhcmFtIHtSZW5kZXJpbmdFbmdpbmU8dW5rbm93biwgdW5rbm93bj59IGVuZ2luZSAtIFRoZSByZW5kZXJpbmcgZW5naW5lIHRvIHJlZ2lzdGVyLlxuICAgKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBJZiBhbiBlbmdpbmUgd2l0aCB0aGUgc2FtZSBmbGF2b3IgYWxyZWFkeSBleGlzdHMuXG4gICAqXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIHN0YXRpYyByZWdpc3RlcihlbmdpbmU6IFJlbmRlcmluZ0VuZ2luZTx1bmtub3duLCB1bmtub3duPikge1xuICAgIGlmIChlbmdpbmUuZmxhdm91ciBpbiB0aGlzLmNhY2hlKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBSZW5kZXJpbmcgZW5naW5lIHVuZGVyICR7ZW5naW5lLmZsYXZvdXJ9IGFscmVhZHkgZXhpc3RzYFxuICAgICAgKTtcbiAgICB0aGlzLmNhY2hlW2VuZ2luZS5mbGF2b3VyXSA9IGVuZ2luZTtcbiAgICB0aGlzLmN1cnJlbnQgPSBlbmdpbmU7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBvciBpbml0aWFsaXplcyBhIHJlbmRlcmluZyBlbmdpbmUuXG4gICAqIEBzdW1tYXJ5IEdldHMgYW4gZXhpc3RpbmcgZW5naW5lIGluc3RhbmNlIG9yIGNyZWF0ZXMgYW5kIGluaXRpYWxpemVzIGEgbmV3IG9uZSBpZiBnaXZlbiBhIGNvbnN0cnVjdG9yLlxuICAgKlxuICAgKiBAdGVtcGxhdGUgTyBUaGUgdHlwZSBvZiB0aGUgcmVuZGVyaW5nIGVuZ2luZSBvdXRwdXRcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxSZW5kZXJpbmdFbmdpbmU8Tz4+IHwgUmVuZGVyaW5nRW5naW5lPE8+fSBvYmogLSBUaGUgZW5naW5lIGluc3RhbmNlIG9yIGNvbnN0cnVjdG9yLlxuICAgKiBAcmV0dXJucyB7UmVuZGVyaW5nRW5naW5lPE8+fSBUaGUgaW5pdGlhbGl6ZWQgcmVuZGVyaW5nIGVuZ2luZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0T3JCb290PE8+KFxuICAgIG9iajogQ29uc3RydWN0b3I8UmVuZGVyaW5nRW5naW5lPE8+PiB8IFJlbmRlcmluZ0VuZ2luZTxPPlxuICApOiBSZW5kZXJpbmdFbmdpbmU8Tz4ge1xuICAgIGlmIChvYmogaW5zdGFuY2VvZiBSZW5kZXJpbmdFbmdpbmUpIHJldHVybiBvYmogYXMgUmVuZGVyaW5nRW5naW5lPE8+O1xuICAgIGNvbnN0IGVuZ2luZTogUmVuZGVyaW5nRW5naW5lPE8+ID0gbmV3IG9iaigpO1xuICAgIGVuZ2luZS5pbml0aWFsaXplKCk7IC8vIG1ha2UgdGhlIGJvb3RpbmcgYXN5bmMuIHVzZSB0aGUgaW5pdGlhbGl6ZWQgZmxhZyB0byBjb250cm9sIGl0XG4gICAgcmV0dXJuIGVuZ2luZSBhcyBSZW5kZXJpbmdFbmdpbmU8Tz47XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIHJlbmRlcmluZyBlbmdpbmUgYnkgZmxhdm9yLlxuICAgKiBAc3VtbWFyeSBHZXRzIHRoZSBjdXJyZW50IHJlbmRlcmluZyBlbmdpbmUgb3IgYSBzcGVjaWZpYyBvbmUgYnkgZmxhdm9yLlxuICAgKlxuICAgKiBAdGVtcGxhdGUgTyBUaGUgdHlwZSBvZiB0aGUgcmVuZGVyaW5nIGVuZ2luZSBvdXRwdXRcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtmbGF2b3VyXSAtIFRoZSBmbGF2b3Igb2YgdGhlIHJlbmRlcmluZyBlbmdpbmUgdG8gcmV0cmlldmUuXG4gICAqIEByZXR1cm5zIHtSZW5kZXJpbmdFbmdpbmU8Tz59IFRoZSByZXF1ZXN0ZWQgcmVuZGVyaW5nIGVuZ2luZS5cbiAgICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gSWYgdGhlIHJlcXVlc3RlZCBmbGF2b3IgZG9lcyBub3QgZXhpc3QuXG4gICAqXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIHN0YXRpYyBnZXQ8Tz4oZmxhdm91cj86IHN0cmluZyk6IFJlbmRlcmluZ0VuZ2luZTxPPiB7XG4gICAgaWYgKCFmbGF2b3VyKVxuICAgICAgcmV0dXJuIHRoaXMuZ2V0T3JCb290PE8+KFxuICAgICAgICB0aGlzLmN1cnJlbnQgYXMgQ29uc3RydWN0b3I8UmVuZGVyaW5nRW5naW5lPE8+PiB8IFJlbmRlcmluZ0VuZ2luZTxPPlxuICAgICAgKTtcbiAgICBpZiAoIShmbGF2b3VyIGluIHRoaXMuY2FjaGUpKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBSZW5kZXJpbmcgZW5naW5lIHVuZGVyICR7Zmxhdm91cn0gZG9lcyBub3QgZXhpc3RgXG4gICAgICApO1xuICAgIHJldHVybiB0aGlzLmdldE9yQm9vdDxPPihcbiAgICAgIHRoaXMuY2FjaGVbZmxhdm91cl0gYXNcbiAgICAgICAgfCBDb25zdHJ1Y3RvcjxSZW5kZXJpbmdFbmdpbmU8Tz4+XG4gICAgICAgIHwgUmVuZGVyaW5nRW5naW5lPE8+XG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVuZGVycyBhIG1vZGVsIHVzaW5nIHRoZSBhcHByb3ByaWF0ZSByZW5kZXJpbmcgZW5naW5lLlxuICAgKiBAc3VtbWFyeSBEZXRlcm1pbmVzIHRoZSBjb3JyZWN0IHJlbmRlcmluZyBlbmdpbmUgZm9yIGEgbW9kZWwgYW5kIGludm9rZXMgaXRzIHJlbmRlciBtZXRob2QuXG4gICAqXG4gICAqIEB0ZW1wbGF0ZSBNIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgdG8gcmVuZGVyLlxuICAgKiBAcGFyYW0gey4uLmFueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgcmVuZGVyIG1ldGhvZC5cbiAgICogQHJldHVybnMge2FueX0gVGhlIHJlc3VsdCBvZiB0aGUgcmVuZGVyaW5nIHByb2Nlc3MuXG4gICAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IElmIG5vIHJlZ2lzdGVyZWQgbW9kZWwgaXMgZm91bmQuXG4gICAqXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIHN0YXRpYyByZW5kZXI8TSBleHRlbmRzIE1vZGVsPihtb2RlbDogTSwgLi4uYXJnczogYW55W10pOiBhbnkge1xuICAgIGNvbnN0IGNvbnN0cnVjdG9yID0gTW9kZWwuZ2V0KG1vZGVsLmNvbnN0cnVjdG9yLm5hbWUpO1xuICAgIGlmICghY29uc3RydWN0b3IpIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiTm8gbW9kZWwgcmVnaXN0ZXJlZCBmb3VuZFwiKTtcbiAgICBjb25zdCBmbGF2b3VyID0gUmVmbGVjdC5nZXRNZXRhZGF0YShcbiAgICAgIFJlbmRlcmluZ0VuZ2luZS5rZXkoVUlLZXlzLlJFTkRFUkVEX0JZKSxcbiAgICAgIGNvbnN0cnVjdG9yIGFzIE1vZGVsQ29uc3RydWN0b3I8TW9kZWw+XG4gICAgKTtcblxuICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgZm9yIHRoZSB2YXIgYXJncyB0eXBlIGNoZWNrXG4gICAgcmV0dXJuIFJlbmRlcmluZ0VuZ2luZS5nZXQoZmxhdm91cikucmVuZGVyKG1vZGVsLCAuLi5hcmdzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2VuZXJhdGVzIGEgbWV0YWRhdGEga2V5IGZvciBVSS1yZWxhdGVkIHByb3BlcnRpZXMuXG4gICAqIEBzdW1tYXJ5IFByZWZpeGVzIGEgZ2l2ZW4ga2V5IHdpdGggdGhlIFVJIHJlZmxlY3Rpb24gcHJlZml4LlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIGtleSB0byBwcmVmaXguXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBwcmVmaXhlZCBrZXkuXG4gICAqXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIHN0YXRpYyBrZXkoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBgJHtVSUtleXMuUkVGTEVDVH0ke2tleX1gO1xuICB9XG59XG4iLCJpbXBvcnQgeyBVSUtleXMgfSBmcm9tIFwiLi4vdWkvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBhcHBseSwgbWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL3JlZmxlY3Rpb25cIjtcbmltcG9ydCB7IFJlbmRlcmluZ0VuZ2luZSB9IGZyb20gXCIuLi91aS9SZW5kZXJpbmdcIjtcbmltcG9ydCB7IFVJTW9kZWxNZXRhZGF0YSB9IGZyb20gXCIuLi91aS90eXBlc1wiO1xuXG4vKipcbiAqIFRhZ3MgdGhlIG1vZGVsIGFzIGEgdWltb2RlbCwgZ2l2aW5nIGl0IHRoZSAncmVuZGVyJyBtZXRob2RcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gW3RhZ10gb3B0aW9uYWwgcGFyYW0uIHdpbGwgcmVuZGVyIHRoZSBwcm92aWRlZCBlbG1lbnQgd3JhcHBpbmcgdGhlIGF0dHJpYnV0ZSB1aWVsZW1lbnRzXG4gKiBAcGFyYW0ge3t9fSBbcHJvcHNdIG9wdGlvbmFsIHBhcmFtLiBBdHRyaWJ1dGVzIHRvIGJlIHBhc3NlZCB0byB0aGUgdGFnIGVsZW1lbnRcbiAqIEBwYXJhbSB7ZnVuY3Rpb24oYW55KTogdm9pZH0gW2luc3RhbmNlQ2FsbGJhY2tdIG9wdGlvbmFsIGNhbGxiYWNrIHJldHVybmluZyB0aGUgaW5zdGFuY2UgYWZ0ZXIgY3JlYXRpb24gZm9yIGFkZGl0aW9uYWwgbG9naWNcbiAqXG4gKiBAZGVjb3JhdG9yIHVpbW9kZWxcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IFN5c3RlbVxuICogICBwYXJ0aWNpcGFudCB1aW1vZGVsXG4gKiAgIHBhcnRpY2lwYW50IGNvbnN0cnVjdG9yXG4gKiAgIHBhcnRpY2lwYW50IGluc3RhbmNlXG4gKiAgIFN5c3RlbS0+PnVpbW9kZWw6ZG8oY29uc3RydWN0b3IpXG4gKiAgIHVpbW9kZWwtPj5jb25zdHJ1Y3RvcjogRXhlY3V0ZXMgdGhlIGNvbnN0cnVjdG9yXG4gKiAgIGNvbnN0cnVjdG9yLT4+dWltb2RlbDogcmV0dXJucyBpbnN0YW5jZVxuICogICB1aW1vZGVsLT4+aW5zdGFuY2U6IGFkZHMgdGhlIHJlbmRlciBtZXRob2RcbiAqICAgdWltb2RlbC0+PlN5c3RlbTogcmV0dXJucyBVSU1vZGVsIGluc3RhbmNlXG4gKlxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVpbW9kZWwodGFnPzogc3RyaW5nLCBwcm9wcz86IFJlY29yZDxzdHJpbmcsIGFueT4pIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICByZXR1cm4gKG9yaWdpbmFsOiBhbnksIHByb3BlcnR5S2V5PzogYW55KSA9PiB7XG4gICAgY29uc3QgbWV0YTogVUlNb2RlbE1ldGFkYXRhID0ge1xuICAgICAgdGFnOiB0YWcgfHwgb3JpZ2luYWwubmFtZSxcbiAgICAgIHByb3BzOiBwcm9wcyxcbiAgICB9O1xuICAgIHJldHVybiBtZXRhZGF0YShSZW5kZXJpbmdFbmdpbmUua2V5KFVJS2V5cy5VSU1PREVMKSwgbWV0YSkob3JpZ2luYWwpO1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyZWRCeShlbmdpbmU6IHN0cmluZykge1xuICByZXR1cm4gYXBwbHkobWV0YWRhdGEoUmVuZGVyaW5nRW5naW5lLmtleShVSUtleXMuUkVOREVSRURfQlkpLCBlbmdpbmUpKTtcbn1cbiIsImltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgUmVuZGVyaW5nRW5naW5lIH0gZnJvbSBcIi4uL3VpL1JlbmRlcmluZ1wiO1xuXG5Nb2RlbC5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gPE0gZXh0ZW5kcyBNb2RlbD4odGhpczogTSwgLi4uYXJnczogYW55W10pIHtcbiAgcmV0dXJuIFJlbmRlcmluZ0VuZ2luZS5yZW5kZXIodGhpcywgLi4uYXJncyk7XG59O1xuIiwiaW1wb3J0IFwicmVmbGVjdC1tZXRhZGF0YVwiO1xuaW1wb3J0IHsgVUlLZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBwcm9wTWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDcnVkT3BlcmF0aW9uS2V5cywgVUlFbGVtZW50TWV0YWRhdGEsIFVJUHJvcE1ldGFkYXRhIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IFJlbmRlcmluZ0VuZ2luZSB9IGZyb20gXCIuL1JlbmRlcmluZ1wiO1xuaW1wb3J0IHsgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuXG4vKipcbiAqIEBuYW1lc3BhY2UgdWktZGVjb3JhdG9ycy51aS5kZWNvcmF0b3JzXG4gKiBAbWVtYmVyT2YgdWktZGVjb3JhdG9ycy51aVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBoaWRlT24oLi4ub3BlcmF0aW9uczogQ3J1ZE9wZXJhdGlvbktleXNbXSkge1xuICByZXR1cm4gcHJvcE1ldGFkYXRhPENydWRPcGVyYXRpb25LZXlzW10+KFxuICAgIFJlbmRlcmluZ0VuZ2luZS5rZXkoVUlLZXlzLkhJRERFTiksXG4gICAgb3BlcmF0aW9uc1xuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGlkZGVuKCkge1xuICByZXR1cm4gaGlkZU9uKFxuICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgIE9wZXJhdGlvbktleXMuUkVBRCxcbiAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICBPcGVyYXRpb25LZXlzLkRFTEVURVxuICApO1xufVxuXG4vKipcbiAqIEFkZHMgdGhlIFVJRWxlbWVudCBkZWZpbml0aW9uIGFzIG1ldGFkYXRhIHRvIHRoZSBwcm9wZXJ0eSwgYWxsb3dpbmcgaXQgdG8gYmUgcmVhZCBieSBhbnkge0BsaW5rIFJlbmRlclN0cmF0ZWd5fVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0YWcgVGhlIGNvbXBvbmVudC9IVE1MIGVsZW1lbnQgdGFnIG5hbWVcbiAqIEBwYXJhbSB7e319IFtwcm9wc10gVGhlIHByb3BlcnRpZXMgdG8gcGFzcyB0byB0aGF0IGNvbXBvbmVudC9IVE1MIEVsZW1lbnRcbiAqIEBwYXJhbSBzZXJpYWxpemVcbiAqXG4gKiBAZGVjb3JhdG9yIHVpZWxlbWVudFxuICpcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKiBAc3ViY2F0ZWdvcnkgdWktZGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gdWllbGVtZW50KFxuICB0YWc6IHN0cmluZyxcbiAgcHJvcHM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICBzZXJpYWxpemU6IGJvb2xlYW4gPSBmYWxzZVxuKSB7XG4gIHJldHVybiAob3JpZ2luYWw6IGFueSwgcHJvcGVydHlLZXk/OiBhbnkpID0+IHtcbiAgICBjb25zdCBtZXRhZGF0YTogVUlFbGVtZW50TWV0YWRhdGEgPSB7XG4gICAgICB0YWc6IHRhZyxcbiAgICAgIHNlcmlhbGl6ZTogc2VyaWFsaXplLFxuICAgICAgcHJvcHM6IE9iamVjdC5hc3NpZ24oXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBwcm9wZXJ0eUtleSxcbiAgICAgICAgfSxcbiAgICAgICAgcHJvcHMgfHwge31cbiAgICAgICksXG4gICAgfTtcblxuICAgIHJldHVybiBwcm9wTWV0YWRhdGEoUmVuZGVyaW5nRW5naW5lLmtleShVSUtleXMuRUxFTUVOVCksIG1ldGFkYXRhKShcbiAgICAgIG9yaWdpbmFsLFxuICAgICAgcHJvcGVydHlLZXlcbiAgICApO1xuICB9O1xufVxuXG4vKipcbiAqIEFkZHMgdGhlIFVJUHJvcCBkZWZpbml0aW9uIGFzIG1ldGFkYXRhIHRvIHRoZSBwcm9wZXJ0eSwgYWxsb3dpbmcgaXQgdG8gYmUgcmVhZCBieSBhbnkge0BsaW5rIFJlbmRlclN0cmF0ZWd5fVxuICpcbiAqIHRoaXMgcmVxdWlyZXMgYSAnQHVpbW9kZWwnIHdpdGggYSBkZWZpbmVkIHRhZ1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBbcHJvcE5hbWVdIHRoZSBwcm9wZXJ0eSBuYW1lIHRoYXQgd2lsbCBiZSBwYXNzZWQgdG8gdGhlIGNvbXBvbmVudC4gZGVmYXVsdHMgdG8gdGhlIFByb3BlcnR5S2V5XG4gKlxuICogQGRlY29yYXRvciB1aXByb3BcbiAqXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICogQHN1YmNhdGVnb3J5IHVpLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVpcHJvcChcbiAgcHJvcE5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZCxcbiAgc3RyaW5naWZ5OiBib29sZWFuID0gZmFsc2Vcbikge1xuICByZXR1cm4gKHRhcmdldDogYW55LCBwcm9wZXJ0eUtleTogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgbWV0YWRhdGE6IFVJUHJvcE1ldGFkYXRhID0ge1xuICAgICAgbmFtZTogcHJvcE5hbWUgfHwgcHJvcGVydHlLZXksXG4gICAgICBzdHJpbmdpZnk6IHN0cmluZ2lmeSxcbiAgICB9O1xuICAgIHByb3BNZXRhZGF0YShSZW5kZXJpbmdFbmdpbmUua2V5KFVJS2V5cy5QUk9QKSwgbWV0YWRhdGEpKFxuICAgICAgdGFyZ2V0LFxuICAgICAgcHJvcGVydHlLZXlcbiAgICApO1xuICB9O1xufVxuIiwiLyoqXG4gKiBAbW9kdWxlIHVpLWRlY29yYXRvcnNcbiAqL1xuXG5leHBvcnQgKiBmcm9tIFwiLi9tb2RlbFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vdWlcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBzdG9yZXMgdGhlIGN1cnJlbnQgcGFja2FnZSB2ZXJzaW9uXG4gKiBAZGVzY3JpcHRpb24gdGhpcyBpcyBob3cgeW91IHNob3VsZCBkb2N1bWVudCBhIGNvbnN0YW50XG4gKiBAY29uc3QgVkVSU0lPTlxuICogQG1lbWJlck9mIG1vZHVsZTp1aS1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gXCIjI1ZFUlNJT04jI1wiO1xuIl0sIm5hbWVzIjpbIk1vZGVsS2V5cyIsIlZhbGlkYXRpb25LZXlzIiwiRW1haWxWYWxpZGF0b3IiLCJVUkxWYWxpZGF0b3IiLCJEYXRlVmFsaWRhdG9yIiwiUGFzc3dvcmRWYWxpZGF0b3IiLCJSZXF1aXJlZFZhbGlkYXRvciIsIk1pblZhbGlkYXRvciIsIk1heFZhbGlkYXRvciIsIlN0ZXBWYWxpZGF0b3IiLCJNaW5MZW5ndGhWYWxpZGF0b3IiLCJNYXhMZW5ndGhWYWxpZGF0b3IiLCJQYXR0ZXJuVmFsaWRhdG9yIiwiRXF1YWxzVmFsaWRhdG9yIiwiRGlmZlZhbGlkYXRvciIsIkxlc3NUaGFuVmFsaWRhdG9yIiwiTGVzc1RoYW5PckVxdWFsVmFsaWRhdG9yIiwiR3JlYXRlclRoYW5WYWxpZGF0b3IiLCJHcmVhdGVyVGhhbk9yRXF1YWxWYWxpZGF0b3IiLCJCYXNlRXJyb3IiLCJmb3JtYXREYXRlIiwiUmVzZXJ2ZWRNb2RlbHMiLCJwYXJzZURhdGUiLCJJbnRlcm5hbEVycm9yIiwiZmluZE1vZGVsSWQiLCJDb21wYXJpc29uVmFsaWRhdGlvbktleXMiLCJNb2RlbCIsIlJlZmxlY3Rpb24iLCJtZXRhZGF0YSIsImFwcGx5Iiwi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