@decaf-ts/for-angular 0.0.25 → 0.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/fesm2022/decaf-ts-for-angular.mjs +1465 -1488
  2. package/fesm2022/decaf-ts-for-angular.mjs.map +1 -1
  3. package/index.d.ts +7470 -3
  4. package/package.json +14 -17
  5. package/components/component-renderer/component-renderer.component.d.ts +0 -278
  6. package/components/crud-field/crud-field.component.d.ts +0 -611
  7. package/components/crud-form/constants.d.ts +0 -5
  8. package/components/crud-form/crud-form.component.d.ts +0 -288
  9. package/components/crud-form/types.d.ts +0 -17
  10. package/components/empty-state/empty-state.component.d.ts +0 -300
  11. package/components/fieldset/fieldset.component.d.ts +0 -555
  12. package/components/filter/filter.component.d.ts +0 -514
  13. package/components/for-angular-components.module.d.ts +0 -20
  14. package/components/index.d.ts +0 -16
  15. package/components/layout/layout.component.d.ts +0 -110
  16. package/components/list/list.component.d.ts +0 -848
  17. package/components/list-item/list-item.component.d.ts +0 -390
  18. package/components/model-renderer/model-renderer.component.d.ts +0 -97
  19. package/components/pagination/constants.d.ts +0 -7
  20. package/components/pagination/pagination.component.d.ts +0 -264
  21. package/components/searchbar/searchbar.component.d.ts +0 -407
  22. package/components/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,436 +0,0 @@
1
- import { isDevMode } from '@angular/core';
2
- import { InjectableRegistryImp } from '@decaf-ts/injectable-decorators';
3
- import { Primitives } from '@decaf-ts/decorator-validation';
4
- import { getLogger } from '../for-angular-common.module';
5
- let injectableRegistry;
6
- /**
7
- * @description Retrieves the singleton instance of the injectables registry
8
- * @summary This function implements the singleton pattern for the InjectablesRegistry.
9
- * It returns the existing registry instance if one exists, or creates a new instance
10
- * if none exists. The registry is used to store and retrieve injectable dependencies
11
- * throughout the application.
12
- *
13
- * @return {InjectablesRegistry} The singleton injectables registry instance
14
- *
15
- * @function getInjectablesRegistry
16
- * @memberOf module:for-angular
17
- */
18
- export function getInjectablesRegistry() {
19
- if (!injectableRegistry)
20
- injectableRegistry = new InjectableRegistryImp();
21
- return injectableRegistry;
22
- }
23
- /**
24
- * @description Determines if the application is running in development mode
25
- * @summary This function checks whether the application is currently running in a development
26
- * environment. It uses Angular's isDevMode() function and also checks the window context
27
- * and hostname against the provided context parameter. This is useful for enabling
28
- * development-specific features or logging.
29
- *
30
- * @param {string} [context='localhost'] - The context string to check against the current environment
31
- * @return {boolean} True if the application is running in development mode, false otherwise
32
- *
33
- * @function isDevelopmentMode
34
- * @memberOf module:for-angular
35
- */
36
- export function isDevelopmentMode(context = 'localhost') {
37
- if (!context)
38
- return isDevMode();
39
- const win = getWindow();
40
- return (isDevMode() ||
41
- win?.['env']?.['CONTEXT'].toLowerCase() !== context.toLowerCase() ||
42
- win?.['location']?.hostname?.includes(context));
43
- }
44
- /**
45
- * @description Dispatches a custom event to the document window
46
- * @summary This function creates and dispatches a custom event to the browser window.
47
- * It's useful for cross-component communication or for triggering application-wide events.
48
- * The function allows specifying the event name, detail data, and additional event properties.
49
- *
50
- * @param {string} name - The name of the custom event to dispatch
51
- * @param {unknown} detail - The data to include in the event's detail property
52
- * @param {object} [props] - Optional additional properties for the custom event
53
- * @return {void}
54
- *
55
- * @function windowEventEmitter
56
- * @memberOf module:for-angular
57
- */
58
- export function windowEventEmitter(name, detail, props) {
59
- const data = Object.assign({
60
- bubbles: true,
61
- composed: true,
62
- cancelable: false,
63
- detail: detail,
64
- }, props || {});
65
- getWindow().dispatchEvent(new CustomEvent(name, data));
66
- }
67
- /**
68
- * @description Retrieves a property from the window's document object
69
- * @summary This function provides a safe way to access properties on the window's document object.
70
- * It uses the getWindowDocument function to get a reference to the document, then accesses
71
- * the specified property. This is useful for browser environment interactions that need
72
- * to access document properties.
73
- *
74
- * @param {string} key - The name of the property to retrieve from the document object
75
- * @return {any} The value of the specified property, or undefined if the document or property doesn't exist
76
- *
77
- * @function getOnWindowDocument
78
- * @memberOf module:for-angular
79
- */
80
- export function getOnWindowDocument(key) {
81
- const doc = getWindowDocument()?.[key];
82
- return doc instanceof Document ?
83
- doc : undefined;
84
- }
85
- /**
86
- * @description Retrieves the document object from the window
87
- * @summary This function provides a safe way to access the document object from the window.
88
- * It uses the getOnWindow function to retrieve the 'document' property from the window object.
89
- * This is useful for browser environment interactions that need access to the document.
90
- *
91
- * @return {Document | undefined} The window's document object, or undefined if it doesn't exist
92
- *
93
- * @function getWindowDocument
94
- * @memberOf module:for-angular
95
- */
96
- export function getWindowDocument() {
97
- return getOnWindow('document');
98
- }
99
- /**
100
- * @description Retrieves a property from the window object
101
- * @summary This function provides a safe way to access properties on the window object.
102
- * It uses the getWindow function to get a reference to the window, then accesses
103
- * the specified property. This is useful for browser environment interactions that need
104
- * to access window properties or APIs.
105
- *
106
- * @param {string} key - The name of the property to retrieve from the window object
107
- * @return {unknown | undefined} The value of the specified property, or undefined if the window or property doesn't exist
108
- *
109
- * @function getOnWindow
110
- * @memberOf module:for-angular
111
- */
112
- export function getOnWindow(key) {
113
- return getWindow()?.[key];
114
- }
115
- /**
116
- * @description Sets a property on the window object
117
- * @summary This function provides a way to set properties on the window object.
118
- * It uses the getWindow function to get a reference to the window, then sets
119
- * the specified property to the provided value. This is useful for storing
120
- * global data or functions that need to be accessible across the application.
121
- *
122
- * @param {string} key - The name of the property to set on the window object
123
- * @param {any} value - The value to assign to the property
124
- * @return {void}
125
- *
126
- * @function setOnWindow
127
- * @memberOf module:for-angular
128
- */
129
- export function setOnWindow(key, value) {
130
- getWindow()[key] = value;
131
- }
132
- /**
133
- * @description Retrieves the global window object
134
- * @summary This function provides a safe way to access the global window object.
135
- * It uses globalThis to ensure compatibility across different JavaScript environments.
136
- * This is the core function used by other window-related utility functions to
137
- * access the window object.
138
- *
139
- * @return {Window} The global window object
140
- *
141
- * @function getWindow
142
- * @memberOf module:for-angular
143
- */
144
- export function getWindow() {
145
- return globalThis?.['window'];
146
- }
147
- /**
148
- * @description Retrieves the width of the browser window
149
- * @summary This function provides a convenient way to get the current width of the browser window.
150
- * It uses the getOnWindow function to access the 'innerWidth' property of the window object.
151
- * This is useful for responsive design implementations and viewport-based calculations.
152
- *
153
- * @return {number | undefined} The current width of the browser window in pixels
154
- *
155
- * @function getWindowWidth
156
- * @memberOf module:for-angular
157
- */
158
- export function getWindowWidth() {
159
- return getOnWindow('innerWidth') || 0;
160
- }
161
- /**
162
- * @description Checks if a value is not undefined
163
- * @summary This utility function determines whether a given value is not undefined.
164
- * It's a simple wrapper that makes code more readable when checking for defined values.
165
- * The function is particularly useful for checking StringOrBoolean properties that might be undefined.
166
- *
167
- * @param {StringOrBoolean | undefined} prop - The property to check
168
- * @return {boolean} True if the property is not undefined, false otherwise
169
- *
170
- * @function isNotUndefined
171
- * @memberOf module:for-angular
172
- */
173
- export function isNotUndefined(prop) {
174
- return (prop !== undefined);
175
- }
176
- /**
177
- * @description Generates a locale string from a class name or instance
178
- * @summary This utility function converts a class name or instance into a locale string
179
- * that can be used for internationalization purposes. It handles different input types
180
- * (string, function, or object) and applies formatting rules to generate a consistent
181
- * locale identifier. For short names (less than 3 parts), it reverses the dot-separated
182
- * string. For longer names, it uses the last part as a prefix and joins the rest with
183
- * underscores.
184
- *
185
- * @param {string|FunctionLike|object} instance - The input to generate the locale from (class name, constructor, or instance)
186
- * @param {string} [suffix] - Optional string to append to the instance name before processing
187
- * @return {string} A formatted locale string derived from the input
188
- *
189
- * @function getLocaleFromClassName
190
- * @memberOf module:for-angular
191
- */
192
- export function getLocaleFromClassName(instance, suffix) {
193
- if (typeof instance !== Primitives.STRING)
194
- instance = instance.name || instance?.constructor?.name;
195
- let name = instance;
196
- if (suffix)
197
- name = `${instance}${suffix.charAt(0).toUpperCase() + suffix.slice(1)}`;
198
- name = name.replace(/_|-/g, '').replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => {
199
- if (index > 1)
200
- word = '.' + word;
201
- return word.toLowerCase();
202
- }).split('.');
203
- if (name.length < 3)
204
- return name.reverse().join('.');
205
- const preffix = name[name.length - 1];
206
- name.pop();
207
- name = name.join('_');
208
- return `${preffix}.${name}`;
209
- }
210
- /**
211
- * @description Retrieves the current locale language
212
- * @summary This utility function gets the current locale language based on the user's browser settings.
213
- * It provides a consistent way to access the user's language preference throughout the application.
214
- * The function returns the browser's navigator.language value, defaulting to 'en' if not available.
215
- *
216
- * @return {string} The current locale language (e.g., 'en', 'fr')
217
- *
218
- * @function getLocaleLanguage
219
- * @memberOf module:for-angular
220
- */
221
- export function getLocaleLanguage() {
222
- const win = getWindow();
223
- return win.navigator.language || "en";
224
- // return win?.[WINDOW_KEYS.LANGUAGE_SELECTED] || (win.navigator.language || '').split('-')[0] || "en";
225
- }
226
- /**
227
- * @description Generates a random string or number of specified length
228
- * @summary This utility function creates a random string of a specified length.
229
- * It can generate either alphanumeric strings (including uppercase and lowercase letters)
230
- * or numeric-only strings. This is useful for creating random IDs, temporary passwords,
231
- * or other random identifiers throughout the application.
232
- *
233
- * @param {number} [length=8] - The length of the random value to generate
234
- * @param {boolean} [onlyNumbers=false] - Whether to generate only numeric characters
235
- * @return {string} A randomly generated string of the specified length and character set
236
- *
237
- * @function generateRandomValue
238
- * @memberOf module:for-angular
239
- */
240
- export function generateRandomValue(length = 8, onlyNumbers = false) {
241
- const chars = onlyNumbers
242
- ? '0123456789'
243
- : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
244
- let result = '';
245
- for (let i = 0; i < length; i++)
246
- result += chars.charAt(Math.floor(Math.random() * chars.length));
247
- return result;
248
- }
249
- /**
250
- * Converts a string representation of a boolean or a boolean value to a boolean type.
251
- *
252
- * @export
253
- * @param {('true' | 'false' | boolean)} prop - The value to convert. Can be the string 'true', 'false', or a boolean.
254
- * @returns {boolean} The boolean representation of the input value. Returns true if the input is the string 'true' or boolean true, false otherwise.
255
- */
256
- export function stringToBoolean(prop) {
257
- if (typeof prop === 'string')
258
- prop = prop.toLowerCase() === 'true' ? true : false;
259
- return prop;
260
- }
261
- /**
262
- * Checks if a value is a valid Date object
263
- *
264
- * @param {(string | Date | number)} date - The value to check. Can be a Date object, a timestamp number, or a date string
265
- * @return {boolean} Returns true if the value is a valid Date object (not NaN), otherwise false
266
- */
267
- export function isValidDate(date) {
268
- try {
269
- return (date instanceof Date && !isNaN(date)) || (() => {
270
- const testRegex = new RegExp(/^\d{4}-\d{2}-\d{2}$/).test(date);
271
- if (typeof date !== Primitives.STRING || !date?.includes('T') && !testRegex)
272
- return false;
273
- date = date.split('T')[0];
274
- if (!new RegExp(/^\d{4}-\d{2}-\d{2}$/).test(date))
275
- return false;
276
- return !!(new Date(date));
277
- })();
278
- }
279
- catch (error) {
280
- getLogger(isValidDate).error(error);
281
- return false;
282
- }
283
- }
284
- /**
285
- * Formats a date into a localized string representation
286
- *
287
- * @param {(string | Date | number)} date - The date to format. Can be a Date object, a timestamp number, or a date string
288
- * @param {string} [locale] - The locale to use for formatting. If not provided, the system's locale will be used
289
- * @return {(Date | string)} A formatted date string in the format DD/MM/YYYY according to the specified locale,
290
- * or the original input as a string if the date is invalid
291
- */
292
- export function formatDate(date, locale) {
293
- if (!locale)
294
- locale = getLocaleLanguage();
295
- if (typeof date === 'string' || typeof date === 'number')
296
- date = new Date(typeof date === 'string' ? date.replace(/\//g, '-') : date);
297
- if (!isValidDate(date))
298
- return `${date}`;
299
- const r = date.toLocaleString(locale, {
300
- year: "numeric",
301
- day: "2-digit",
302
- month: '2-digit'
303
- });
304
- return r;
305
- }
306
- /**
307
- * Attempts to parse a date string, Date object, or number into a valid Date object
308
- *
309
- * @param {(string | Date | number)} date - The date to parse. Can be a Date object, a timestamp number,
310
- * or a date string in the format "DD/MM/YYYY HH:MM:SS:MS"
311
- * @return {(Date | null)} A valid Date object if parsing is successful, or null if the date is invalid
312
- * or doesn't match the expected format
313
- */
314
- export function parseToValidDate(date) {
315
- if (isValidDate(date))
316
- return date;
317
- if (!`${date}`.includes('/'))
318
- return null;
319
- const [dateString, timeString] = date.split(' ');
320
- const [day, month, year] = dateString.split('/').map(Number);
321
- const [hours, minutes, seconds, milliseconds] = timeString.split(':').map(Number);
322
- date = new Date(year, month - 1, day, hours, minutes, seconds, milliseconds);
323
- if (!isValidDate(date)) {
324
- console.warn('parseToValidDate - Invalid date format', date);
325
- return null;
326
- }
327
- return date;
328
- }
329
- /**
330
- * Maps an item object using a provided mapper object and optional additional properties.
331
- *
332
- * @param {KeyValue} item - The source object to be mapped.
333
- * @param {KeyValue} mapper - An object that defines the mapping rules. Keys represent the new property names,
334
- * and values represent the path to the corresponding values in the source object.
335
- * @param {KeyValue} [props] - Optional additional properties to be included in the mapped object.
336
- * @returns {KeyValue} A new object with properties mapped according to the mapper object and including any additional properties.
337
- */
338
- export function itemMapper(item, mapper, props) {
339
- return Object.entries(mapper).reduce((accum, [key, value]) => {
340
- const arrayValue = value.split('.');
341
- if (!value) {
342
- accum[key] = value;
343
- }
344
- else {
345
- if (arrayValue.length === 1) {
346
- accum[key] = item?.[value] || (value !== key ? value : "");
347
- }
348
- else {
349
- let val;
350
- for (const _value of arrayValue)
351
- val = !val
352
- ? item[_value]
353
- : (typeof val === 'string' ? JSON.parse(val) : val)[_value];
354
- if (isValidDate(new Date(val)))
355
- val = `${formatDate(val)}`;
356
- accum[key] = val === null || val === undefined ? value : val;
357
- }
358
- }
359
- return Object.assign({}, props || {}, accum);
360
- }, {});
361
- }
362
- /**
363
- * Maps an array of data objects using a provided mapper object.
364
- *
365
- * @template T - The type of the resulting mapped items.
366
- * @param {any[]} data - The array of data objects to be mapped.
367
- * @param {KeyValue} mapper - An object that defines the mapping rules.
368
- * @param {KeyValue} [props] - Additional properties to be included in the mapped items.
369
- *
370
- * @returns {T[]} - The array of mapped items. If an item in the original array does not have any non-null values after mapping,
371
- * the original item is returned instead.
372
- */
373
- export function dataMapper(data, mapper, props) {
374
- if (!data || !data.length)
375
- return [];
376
- return data.reduce((accum, curr) => {
377
- const item = itemMapper(curr, mapper, props);
378
- const hasValues = [...new Set(Object.values(item))].filter((value) => value).length >
379
- 0;
380
- accum.push(hasValues ? item : curr);
381
- return accum;
382
- }, []);
383
- }
384
- /**
385
- * @description Removes focus from the currently active DOM element
386
- * @summary This utility function blurs the currently focused element in the document,
387
- * effectively removing focus traps that might prevent proper navigation or keyboard
388
- * interaction. It safely accesses the document's activeElement and calls blur() if
389
- * an element is currently focused. This is useful for accessibility and user experience
390
- * improvements, particularly when closing modals or dialogs.
391
- *
392
- * @return {void}
393
- *
394
- * @function removeFocusTrap
395
- * @memberOf module:for-angular
396
- */
397
- export function removeFocusTrap() {
398
- const doc = getWindowDocument();
399
- if (doc?.activeElement)
400
- doc.activeElement?.blur();
401
- }
402
- /**
403
- * @description Cleans and normalizes whitespace in a string value
404
- * @summary This utility function trims leading and trailing whitespace from a string
405
- * and replaces multiple consecutive whitespace characters with a single space.
406
- * Optionally converts the result to lowercase for consistent text processing.
407
- * This is useful for normalizing user input, search terms, or data sanitization.
408
- *
409
- * @param {string} value - The string value to clean and normalize
410
- * @param {boolean} [lowercase=false] - Whether to convert the result to lowercase
411
- * @return {string} The cleaned and normalized string
412
- *
413
- * @function cleanSpaces
414
- * @memberOf module:for-angular
415
- */
416
- export function cleanSpaces(value = "", lowercase = false) {
417
- value = `${value}`.trim().replace(/\s+/g, ' ');
418
- return lowercase ? value.toLowerCase() : value;
419
- }
420
- /**
421
- * @description Determines if the user's system is currently in dark mode
422
- * @summary This function checks the user's color scheme preference using the CSS media query
423
- * '(prefers-color-scheme: dark)'. It returns a boolean indicating whether the system is
424
- * currently set to dark mode. This is useful for implementing theme-aware functionality
425
- * and adjusting UI elements based on the user's preferred color scheme.
426
- *
427
- * @return {Promise<boolean>} True if the system is in dark mode, false otherwise
428
- *
429
- * @function isDarkMode
430
- * @memberOf module:for-angular
431
- */
432
- export async function isDarkMode() {
433
- const { matches } = getWindow().matchMedia('(prefers-color-scheme: dark)');
434
- return matches;
435
- }
436
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2hlbHBlcnMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMxQyxPQUFPLEVBQUUscUJBQXFCLEVBQXVCLE1BQU0saUNBQWlDLENBQUM7QUFDN0YsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRzVELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUV6RCxJQUFJLGtCQUF1QyxDQUFDO0FBRTVDOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBTSxVQUFVLHNCQUFzQjtJQUNwQyxJQUFJLENBQUMsa0JBQWtCO1FBQ3JCLGtCQUFrQixHQUFHLElBQUkscUJBQXFCLEVBQUUsQ0FBQztJQUNuRCxPQUFPLGtCQUFrQixDQUFDO0FBQzVCLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLFVBQVUsaUJBQWlCLENBQUMsVUFBa0IsV0FBVztJQUM3RCxJQUFJLENBQUMsT0FBTztRQUNWLE9BQU8sU0FBUyxFQUFFLENBQUM7SUFDckIsTUFBTSxHQUFHLEdBQUcsU0FBUyxFQUFFLENBQUM7SUFDeEIsT0FBTyxDQUNMLFNBQVMsRUFBRTtRQUNYLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsV0FBVyxFQUFFLEtBQUssT0FBTyxDQUFDLFdBQVcsRUFBRTtRQUNqRSxHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUMvQyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQ2hDLElBQVksRUFDWixNQUFlLEVBQ2YsS0FBYztJQUVkLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQ3hCO1FBQ0UsT0FBTyxFQUFFLElBQUk7UUFDYixRQUFRLEVBQUUsSUFBSTtRQUNkLFVBQVUsRUFBRSxLQUFLO1FBQ2pCLE1BQU0sRUFBRSxNQUFNO0tBQ2YsRUFDRCxLQUFLLElBQUksRUFBRSxDQUNaLENBQUM7SUFDRCxTQUFTLEVBQWEsQ0FBQyxhQUFhLENBQUMsSUFBSSxXQUFXLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7QUFDckUsQ0FBQztBQUNEOzs7Ozs7Ozs7Ozs7R0FZRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxHQUFXO0lBQzdDLE1BQU0sR0FBRyxHQUFHLGlCQUFpQixFQUFFLEVBQUUsQ0FBQyxHQUFxQixDQUFDLENBQUM7SUFDekQsT0FBTyxHQUFHLFlBQVksUUFBUSxDQUFDLENBQUM7UUFDOUIsR0FBRyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDcEIsQ0FBQztBQUVEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLFVBQVUsaUJBQWlCO0lBQy9CLE9BQU8sV0FBVyxDQUFDLFVBQVUsQ0FBYSxDQUFDO0FBQzdDLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLFVBQVUsV0FBVyxDQUFDLEdBQVc7SUFDckMsT0FBTyxTQUFTLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQzVCLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsTUFBTSxVQUFVLFdBQVcsQ0FBQyxHQUFXLEVBQUUsS0FBYztJQUNyRCxTQUFTLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxLQUFLLENBQUM7QUFDM0IsQ0FBQztBQUVEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBTSxVQUFVLFNBQVM7SUFDdkIsT0FBUSxVQUF1QixFQUFFLENBQUMsUUFBUSxDQUFzQixDQUFDO0FBQ25FLENBQUM7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxVQUFVLGNBQWM7SUFDNUIsT0FBTyxXQUFXLENBQUMsWUFBWSxDQUFXLElBQUksQ0FBQyxDQUFDO0FBQ2xELENBQUM7QUFFRDs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQUMsSUFBaUM7SUFDOUQsT0FBTyxDQUFDLElBQUksS0FBSyxTQUFTLENBQVksQ0FBQztBQUN6QyxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsTUFBTSxVQUFVLHNCQUFzQixDQUNwQyxRQUEwQyxFQUMxQyxNQUFlO0lBRWYsSUFBSSxPQUFPLFFBQVEsS0FBSyxVQUFVLENBQUMsTUFBTTtRQUN2QyxRQUFRLEdBQUksUUFBeUIsQ0FBQyxJQUFJLElBQUssUUFBbUIsRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDO0lBRXhGLElBQUksSUFBSSxHQUFzQixRQUFrQixDQUFDO0lBRWpELElBQUksTUFBTTtRQUNSLElBQUksR0FBRyxHQUFHLFFBQVEsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUUxRSxJQUFJLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLHFCQUFxQixFQUFFLENBQUMsSUFBWSxFQUFFLEtBQWEsRUFBRSxFQUFFO1FBQzNGLElBQUksS0FBSyxHQUFHLENBQUM7WUFBRSxJQUFJLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQztRQUNqQyxPQUFPLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUM1QixDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFaEIsSUFBSSxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUM7UUFDakIsT0FBTyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBRWxDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUNYLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3RCLE9BQU8sR0FBRyxPQUFPLElBQUksSUFBSSxFQUFFLENBQUM7QUFDOUIsQ0FBQztBQUlEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLFVBQVUsaUJBQWlCO0lBQy9CLE1BQU0sR0FBRyxHQUFHLFNBQVMsRUFBRSxDQUFDO0lBQ3hCLE9BQVEsR0FBYyxDQUFDLFNBQVMsQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDO0lBQ2xELHVHQUF1RztBQUN6RyxDQUFDO0FBSUQ7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxTQUFpQixDQUFDLEVBQUUsY0FBdUIsS0FBSztJQUNsRixNQUFNLEtBQUssR0FBRyxXQUFXO1FBQ3ZCLENBQUMsQ0FBQyxZQUFZO1FBQ2QsQ0FBQyxDQUFDLGdFQUFnRSxDQUFDO0lBQ3JFLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQztJQUNoQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxFQUFFLENBQUMsRUFBRTtRQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUVuRSxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDO0FBR0Q7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FBQyxJQUFnQztJQUM5RCxJQUFHLE9BQU8sSUFBSSxLQUFLLFFBQVE7UUFDekIsSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO0lBQ3RELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQUdEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLFdBQVcsQ0FBQyxJQUE0QjtJQUN0RCxJQUFJLENBQUM7UUFDSCxPQUFPLENBQUMsSUFBSSxZQUFZLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUF5QixDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUMxRSxNQUFNLFNBQVMsR0FBRyxJQUFJLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFjLENBQUMsQ0FBQTtZQUN4RSxJQUFHLE9BQU8sSUFBSSxLQUFLLFVBQVUsQ0FBQyxNQUFNLElBQUksQ0FBRSxJQUFlLEVBQUUsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUztnQkFDbkYsT0FBTyxLQUFLLENBQUM7WUFFakIsSUFBSSxHQUFJLElBQWUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdkMsSUFBRyxDQUFDLElBQUksTUFBTSxDQUFDLHFCQUFxQixDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztnQkFDOUMsT0FBTyxLQUFLLENBQUM7WUFFZixPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDM0IsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNOLENBQUM7SUFBQyxPQUFNLEtBQWMsRUFBRSxDQUFDO1FBQ3ZCLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBdUIsQ0FBQyxDQUFDO1FBQ3RELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztBQUNILENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLFVBQVUsQ0FBQyxJQUE0QixFQUFFLE1BQTJCO0lBRWxGLElBQUcsQ0FBQyxNQUFNO1FBQ1IsTUFBTSxHQUFHLGlCQUFpQixFQUFFLENBQUM7SUFFL0IsSUFBRyxPQUFPLElBQUksS0FBSyxRQUFRLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUTtRQUNyRCxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsT0FBTyxJQUFJLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFOUUsSUFBRyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUM7UUFDbkIsT0FBTyxHQUFHLElBQUksRUFBWSxDQUFDO0lBQzdCLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFO1FBQ2xDLElBQUksRUFBRSxTQUFTO1FBQ2YsR0FBRyxFQUFFLFNBQVM7UUFDZCxLQUFLLEVBQUUsU0FBUztLQUNuQixDQUFDLENBQUM7SUFHSCxPQUFPLENBQUMsQ0FBQztBQUNYLENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLElBQTRCO0lBQzNELElBQUcsV0FBVyxDQUFDLElBQUksQ0FBQztRQUNsQixPQUFPLElBQVksQ0FBQztJQUV0QixJQUFHLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDO1FBQ3pCLE9BQU8sSUFBSSxDQUFDO0lBRWQsTUFBTSxDQUFDLFVBQVUsRUFBRSxVQUFVLENBQUMsR0FBSSxJQUFlLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzdELE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzdELE1BQU0sQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxZQUFZLENBQUMsR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNsRixJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLEtBQUssR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBRTdFLElBQUcsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUN0QixPQUFPLENBQUMsSUFBSSxDQUFDLHdDQUF3QyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzdELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQUdEOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxVQUFVLFVBQVUsQ0FBQyxJQUFjLEVBQUUsTUFBZ0IsRUFBRSxLQUFnQjtJQUMzRSxPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBZSxFQUFFLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUU7UUFDckUsTUFBTSxVQUFVLEdBQUksS0FBZ0IsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1gsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQztRQUNyQixDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksVUFBVSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDNUIsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDLEtBQWUsQ0FBQyxJQUFJLENBQUMsS0FBSyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN2RSxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sSUFBSSxHQUFHLENBQUM7Z0JBRVIsS0FBSyxNQUFNLE1BQU0sSUFBSSxVQUFVO29CQUM3QixHQUFHLEdBQUcsQ0FBQyxHQUFHO3dCQUNSLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO3dCQUNkLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBRWhFLElBQUksV0FBVyxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUFFLEdBQUcsR0FBRyxHQUFHLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUUzRCxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsR0FBRyxLQUFLLElBQUksSUFBSSxHQUFHLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztZQUMvRCxDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsS0FBSyxJQUFJLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMvQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDVCxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7R0FVRztBQUNILE1BQU0sVUFBVSxVQUFVLENBQUksSUFBUyxFQUFFLE1BQWdCLEVBQUUsS0FBZ0I7SUFDekUsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNO1FBQUUsT0FBTyxFQUFFLENBQUM7SUFDckMsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBVSxFQUFFLElBQUksRUFBRSxFQUFFO1FBQ3RDLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxJQUFnQixFQUFFLE1BQU0sRUFBRSxLQUFLLENBQU0sQ0FBQztRQUM5RCxNQUFNLFNBQVMsR0FDYixDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNO1lBQ3hFLENBQUMsQ0FBQztRQUNKLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BDLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ1QsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7R0FZRztBQUNILE1BQU0sVUFBVSxlQUFlO0lBQzdCLE1BQU0sR0FBRyxHQUFHLGlCQUFpQixFQUFFLENBQUM7SUFDaEMsSUFBRyxHQUFHLEVBQUUsYUFBYTtRQUNsQixHQUFHLENBQUMsYUFBNkIsRUFBRSxJQUFJLEVBQUUsQ0FBQztBQUMvQyxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sVUFBVSxXQUFXLENBQUMsUUFBZ0IsRUFBRSxFQUFFLFlBQXFCLEtBQUs7SUFDeEUsS0FBSyxHQUFHLEdBQUcsS0FBSyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztJQUMvQyxPQUFPLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7QUFDakQsQ0FBQztBQUdEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxVQUFVO0lBQzlCLE1BQU0sRUFBQyxPQUFPLEVBQUMsR0FBRyxTQUFTLEVBQUUsQ0FBQyxVQUFVLENBQUMsOEJBQThCLENBQUMsQ0FBQztJQUN6RSxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaXNEZXZNb2RlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBJbmplY3RhYmxlUmVnaXN0cnlJbXAsIEluamVjdGFibGVzUmVnaXN0cnkgfSBmcm9tICdAZGVjYWYtdHMvaW5qZWN0YWJsZS1kZWNvcmF0b3JzJztcbmltcG9ydCB7IFByaW1pdGl2ZXMgfSBmcm9tICdAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb24nO1xuaW1wb3J0IHsgS2V5VmFsdWUsIFN0cmluZ09yQm9vbGVhbiwgfSBmcm9tICcuLi9lbmdpbmUvdHlwZXMnO1xuaW1wb3J0IHsgRnVuY3Rpb25MaWtlIH0gZnJvbSAnLi4vZW5naW5lL3R5cGVzJztcbmltcG9ydCB7IGdldExvZ2dlciB9IGZyb20gJy4uL2Zvci1hbmd1bGFyLWNvbW1vbi5tb2R1bGUnO1xuXG5sZXQgaW5qZWN0YWJsZVJlZ2lzdHJ5OiBJbmplY3RhYmxlc1JlZ2lzdHJ5O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIHNpbmdsZXRvbiBpbnN0YW5jZSBvZiB0aGUgaW5qZWN0YWJsZXMgcmVnaXN0cnlcbiAqIEBzdW1tYXJ5IFRoaXMgZnVuY3Rpb24gaW1wbGVtZW50cyB0aGUgc2luZ2xldG9uIHBhdHRlcm4gZm9yIHRoZSBJbmplY3RhYmxlc1JlZ2lzdHJ5LlxuICogSXQgcmV0dXJucyB0aGUgZXhpc3RpbmcgcmVnaXN0cnkgaW5zdGFuY2UgaWYgb25lIGV4aXN0cywgb3IgY3JlYXRlcyBhIG5ldyBpbnN0YW5jZVxuICogaWYgbm9uZSBleGlzdHMuIFRoZSByZWdpc3RyeSBpcyB1c2VkIHRvIHN0b3JlIGFuZCByZXRyaWV2ZSBpbmplY3RhYmxlIGRlcGVuZGVuY2llc1xuICogdGhyb3VnaG91dCB0aGUgYXBwbGljYXRpb24uXG4gKlxuICogQHJldHVybiB7SW5qZWN0YWJsZXNSZWdpc3RyeX0gVGhlIHNpbmdsZXRvbiBpbmplY3RhYmxlcyByZWdpc3RyeSBpbnN0YW5jZVxuICpcbiAqIEBmdW5jdGlvbiBnZXRJbmplY3RhYmxlc1JlZ2lzdHJ5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1hbmd1bGFyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRJbmplY3RhYmxlc1JlZ2lzdHJ5KCk6IEluamVjdGFibGVzUmVnaXN0cnkge1xuICBpZiAoIWluamVjdGFibGVSZWdpc3RyeSlcbiAgICBpbmplY3RhYmxlUmVnaXN0cnkgPSBuZXcgSW5qZWN0YWJsZVJlZ2lzdHJ5SW1wKCk7XG4gIHJldHVybiBpbmplY3RhYmxlUmVnaXN0cnk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERldGVybWluZXMgaWYgdGhlIGFwcGxpY2F0aW9uIGlzIHJ1bm5pbmcgaW4gZGV2ZWxvcG1lbnQgbW9kZVxuICogQHN1bW1hcnkgVGhpcyBmdW5jdGlvbiBjaGVja3Mgd2hldGhlciB0aGUgYXBwbGljYXRpb24gaXMgY3VycmVudGx5IHJ1bm5pbmcgaW4gYSBkZXZlbG9wbWVudFxuICogZW52aXJvbm1lbnQuIEl0IHVzZXMgQW5ndWxhcidzIGlzRGV2TW9kZSgpIGZ1bmN0aW9uIGFuZCBhbHNvIGNoZWNrcyB0aGUgd2luZG93IGNvbnRleHRcbiAqIGFuZCBob3N0bmFtZSBhZ2FpbnN0IHRoZSBwcm92aWRlZCBjb250ZXh0IHBhcmFtZXRlci4gVGhpcyBpcyB1c2VmdWwgZm9yIGVuYWJsaW5nXG4gKiBkZXZlbG9wbWVudC1zcGVjaWZpYyBmZWF0dXJlcyBvciBsb2dnaW5nLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBbY29udGV4dD0nbG9jYWxob3N0J10gLSBUaGUgY29udGV4dCBzdHJpbmcgdG8gY2hlY2sgYWdhaW5zdCB0aGUgY3VycmVudCBlbnZpcm9ubWVudFxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgYXBwbGljYXRpb24gaXMgcnVubmluZyBpbiBkZXZlbG9wbWVudCBtb2RlLCBmYWxzZSBvdGhlcndpc2VcbiAqXG4gKiBAZnVuY3Rpb24gaXNEZXZlbG9wbWVudE1vZGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWFuZ3VsYXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRGV2ZWxvcG1lbnRNb2RlKGNvbnRleHQ6IHN0cmluZyA9ICdsb2NhbGhvc3QnKTogYm9vbGVhbiB7XG4gIGlmICghY29udGV4dClcbiAgICByZXR1cm4gaXNEZXZNb2RlKCk7XG4gIGNvbnN0IHdpbiA9IGdldFdpbmRvdygpO1xuICByZXR1cm4gKFxuICAgIGlzRGV2TW9kZSgpIHx8XG4gICAgd2luPy5bJ2VudiddPy5bJ0NPTlRFWFQnXS50b0xvd2VyQ2FzZSgpICE9PSBjb250ZXh0LnRvTG93ZXJDYXNlKCkgfHxcbiAgICB3aW4/LlsnbG9jYXRpb24nXT8uaG9zdG5hbWU/LmluY2x1ZGVzKGNvbnRleHQpXG4gICk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERpc3BhdGNoZXMgYSBjdXN0b20gZXZlbnQgdG8gdGhlIGRvY3VtZW50IHdpbmRvd1xuICogQHN1bW1hcnkgVGhpcyBmdW5jdGlvbiBjcmVhdGVzIGFuZCBkaXNwYXRjaGVzIGEgY3VzdG9tIGV2ZW50IHRvIHRoZSBicm93c2VyIHdpbmRvdy5cbiAqIEl0J3MgdXNlZnVsIGZvciBjcm9zcy1jb21wb25lbnQgY29tbXVuaWNhdGlvbiBvciBmb3IgdHJpZ2dlcmluZyBhcHBsaWNhdGlvbi13aWRlIGV2ZW50cy5cbiAqIFRoZSBmdW5jdGlvbiBhbGxvd3Mgc3BlY2lmeWluZyB0aGUgZXZlbnQgbmFtZSwgZGV0YWlsIGRhdGEsIGFuZCBhZGRpdGlvbmFsIGV2ZW50IHByb3BlcnRpZXMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgY3VzdG9tIGV2ZW50IHRvIGRpc3BhdGNoXG4gKiBAcGFyYW0ge3Vua25vd259IGRldGFpbCAtIFRoZSBkYXRhIHRvIGluY2x1ZGUgaW4gdGhlIGV2ZW50J3MgZGV0YWlsIHByb3BlcnR5XG4gKiBAcGFyYW0ge29iamVjdH0gW3Byb3BzXSAtIE9wdGlvbmFsIGFkZGl0aW9uYWwgcHJvcGVydGllcyBmb3IgdGhlIGN1c3RvbSBldmVudFxuICogQHJldHVybiB7dm9pZH1cbiAqXG4gKiBAZnVuY3Rpb24gd2luZG93RXZlbnRFbWl0dGVyXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1hbmd1bGFyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3aW5kb3dFdmVudEVtaXR0ZXIoXG4gIG5hbWU6IHN0cmluZyxcbiAgZGV0YWlsOiB1bmtub3duLFxuICBwcm9wcz86IG9iamVjdFxuKTogdm9pZCB7XG4gIGNvbnN0IGRhdGEgPSBPYmplY3QuYXNzaWduKFxuICAgIHtcbiAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICBjb21wb3NlZDogdHJ1ZSxcbiAgICAgIGNhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgZGV0YWlsOiBkZXRhaWwsXG4gICAgfSxcbiAgICBwcm9wcyB8fCB7fVxuICApO1xuICAoZ2V0V2luZG93KCkgYXMgV2luZG93KS5kaXNwYXRjaEV2ZW50KG5ldyBDdXN0b21FdmVudChuYW1lLCBkYXRhKSk7XG59XG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYSBwcm9wZXJ0eSBmcm9tIHRoZSB3aW5kb3cncyBkb2N1bWVudCBvYmplY3RcbiAqIEBzdW1tYXJ5IFRoaXMgZnVuY3Rpb24gcHJvdmlkZXMgYSBzYWZlIHdheSB0byBhY2Nlc3MgcHJvcGVydGllcyBvbiB0aGUgd2luZG93J3MgZG9jdW1lbnQgb2JqZWN0LlxuICogSXQgdXNlcyB0aGUgZ2V0V2luZG93RG9jdW1lbnQgZnVuY3Rpb24gdG8gZ2V0IGEgcmVmZXJlbmNlIHRvIHRoZSBkb2N1bWVudCwgdGhlbiBhY2Nlc3Nlc1xuICogdGhlIHNwZWNpZmllZCBwcm9wZXJ0eS4gVGhpcyBpcyB1c2VmdWwgZm9yIGJyb3dzZXIgZW52aXJvbm1lbnQgaW50ZXJhY3Rpb25zIHRoYXQgbmVlZFxuICogdG8gYWNjZXNzIGRvY3VtZW50IHByb3BlcnRpZXMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGtleSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byByZXRyaWV2ZSBmcm9tIHRoZSBkb2N1bWVudCBvYmplY3RcbiAqIEByZXR1cm4ge2FueX0gVGhlIHZhbHVlIG9mIHRoZSBzcGVjaWZpZWQgcHJvcGVydHksIG9yIHVuZGVmaW5lZCBpZiB0aGUgZG9jdW1lbnQgb3IgcHJvcGVydHkgZG9lc24ndCBleGlzdFxuICpcbiAqIEBmdW5jdGlvbiBnZXRPbldpbmRvd0RvY3VtZW50XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1hbmd1bGFyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRPbldpbmRvd0RvY3VtZW50KGtleTogc3RyaW5nKTogRG9jdW1lbnQgfCB1bmRlZmluZWQge1xuICBjb25zdCBkb2MgPSBnZXRXaW5kb3dEb2N1bWVudCgpPy5ba2V5IGFzIGtleW9mIERvY3VtZW50XTtcbiAgcmV0dXJuIGRvYyBpbnN0YW5jZW9mIERvY3VtZW50ID9cbiAgICBkb2MgOiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyB0aGUgZG9jdW1lbnQgb2JqZWN0IGZyb20gdGhlIHdpbmRvd1xuICogQHN1bW1hcnkgVGhpcyBmdW5jdGlvbiBwcm92aWRlcyBhIHNhZmUgd2F5IHRvIGFjY2VzcyB0aGUgZG9jdW1lbnQgb2JqZWN0IGZyb20gdGhlIHdpbmRvdy5cbiAqIEl0IHVzZXMgdGhlIGdldE9uV2luZG93IGZ1bmN0aW9uIHRvIHJldHJpZXZlIHRoZSAnZG9jdW1lbnQnIHByb3BlcnR5IGZyb20gdGhlIHdpbmRvdyBvYmplY3QuXG4gKiBUaGlzIGlzIHVzZWZ1bCBmb3IgYnJvd3NlciBlbnZpcm9ubWVudCBpbnRlcmFjdGlvbnMgdGhhdCBuZWVkIGFjY2VzcyB0byB0aGUgZG9jdW1lbnQuXG4gKlxuICogQHJldHVybiB7RG9jdW1lbnQgfCB1bmRlZmluZWR9IFRoZSB3aW5kb3cncyBkb2N1bWVudCBvYmplY3QsIG9yIHVuZGVmaW5lZCBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gKlxuICogQGZ1bmN0aW9uIGdldFdpbmRvd0RvY3VtZW50XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1hbmd1bGFyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRXaW5kb3dEb2N1bWVudCgpOiBEb2N1bWVudCB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBnZXRPbldpbmRvdygnZG9jdW1lbnQnKSBhcyBEb2N1bWVudDtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgcHJvcGVydHkgZnJvbSB0aGUgd2luZG93IG9iamVjdFxuICogQHN1bW1hcnkgVGhpcyBmdW5jdGlvbiBwcm92aWRlcyBhIHNhZmUgd2F5IHRvIGFjY2VzcyBwcm9wZXJ0aWVzIG9uIHRoZSB3aW5kb3cgb2JqZWN0LlxuICogSXQgdXNlcyB0aGUgZ2V0V2luZG93IGZ1bmN0aW9uIHRvIGdldCBhIHJlZmVyZW5jZSB0byB0aGUgd2luZG93LCB0aGVuIGFjY2Vzc2VzXG4gKiB0aGUgc3BlY2lmaWVkIHByb3BlcnR5LiBUaGlzIGlzIHVzZWZ1bCBmb3IgYnJvd3NlciBlbnZpcm9ubWVudCBpbnRlcmFjdGlvbnMgdGhhdCBuZWVkXG4gKiB0byBhY2Nlc3Mgd2luZG93IHByb3BlcnRpZXMgb3IgQVBJcy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIHJldHJpZXZlIGZyb20gdGhlIHdpbmRvdyBvYmplY3RcbiAqIEByZXR1cm4ge3Vua25vd24gfCB1bmRlZmluZWR9IFRoZSB2YWx1ZSBvZiB0aGUgc3BlY2lmaWVkIHByb3BlcnR5LCBvciB1bmRlZmluZWQgaWYgdGhlIHdpbmRvdyBvciBwcm9wZXJ0eSBkb2Vzbid0IGV4aXN0XG4gKlxuICogQGZ1bmN0aW9uIGdldE9uV2luZG93XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1hbmd1bGFyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRPbldpbmRvdyhrZXk6IHN0cmluZyk6IHVua25vd24gfCB1bmRlZmluZWQge1xuICByZXR1cm4gZ2V0V2luZG93KCk/LltrZXldO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTZXRzIGEgcHJvcGVydHkgb24gdGhlIHdpbmRvdyBvYmplY3RcbiAqIEBzdW1tYXJ5IFRoaXMgZnVuY3Rpb24gcHJvdmlkZXMgYSB3YXkgdG8gc2V0IHByb3BlcnRpZXMgb24gdGhlIHdpbmRvdyBvYmplY3QuXG4gKiBJdCB1c2VzIHRoZSBnZXRXaW5kb3cgZnVuY3Rpb24gdG8gZ2V0IGEgcmVmZXJlbmNlIHRvIHRoZSB3aW5kb3csIHRoZW4gc2V0c1xuICogdGhlIHNwZWNpZmllZCBwcm9wZXJ0eSB0byB0aGUgcHJvdmlkZWQgdmFsdWUuIFRoaXMgaXMgdXNlZnVsIGZvciBzdG9yaW5nXG4gKiBnbG9iYWwgZGF0YSBvciBmdW5jdGlvbnMgdGhhdCBuZWVkIHRvIGJlIGFjY2Vzc2libGUgYWNyb3NzIHRoZSBhcHBsaWNhdGlvbi5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIHNldCBvbiB0aGUgd2luZG93IG9iamVjdFxuICogQHBhcmFtIHthbnl9IHZhbHVlIC0gVGhlIHZhbHVlIHRvIGFzc2lnbiB0byB0aGUgcHJvcGVydHlcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKlxuICogQGZ1bmN0aW9uIHNldE9uV2luZG93XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1hbmd1bGFyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRPbldpbmRvdyhrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24pOiB2b2lkIHtcbiAgZ2V0V2luZG93KClba2V5XSA9IHZhbHVlO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIGdsb2JhbCB3aW5kb3cgb2JqZWN0XG4gKiBAc3VtbWFyeSBUaGlzIGZ1bmN0aW9uIHByb3ZpZGVzIGEgc2FmZSB3YXkgdG8gYWNjZXNzIHRoZSBnbG9iYWwgd2luZG93IG9iamVjdC5cbiAqIEl0IHVzZXMgZ2xvYmFsVGhpcyB0byBlbnN1cmUgY29tcGF0aWJpbGl0eSBhY3Jvc3MgZGlmZmVyZW50IEphdmFTY3JpcHQgZW52aXJvbm1lbnRzLlxuICogVGhpcyBpcyB0aGUgY29yZSBmdW5jdGlvbiB1c2VkIGJ5IG90aGVyIHdpbmRvdy1yZWxhdGVkIHV0aWxpdHkgZnVuY3Rpb25zIHRvXG4gKiBhY2Nlc3MgdGhlIHdpbmRvdyBvYmplY3QuXG4gKlxuICogQHJldHVybiB7V2luZG93fSBUaGUgZ2xvYmFsIHdpbmRvdyBvYmplY3RcbiAqXG4gKiBAZnVuY3Rpb24gZ2V0V2luZG93XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1hbmd1bGFyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRXaW5kb3coKTogV2luZG93ICYgS2V5VmFsdWUge1xuICByZXR1cm4gKGdsb2JhbFRoaXMgYXMgS2V5VmFsdWUpPy5bJ3dpbmRvdyddIGFzIFdpbmRvdyAmIEtleVZhbHVlO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIHdpZHRoIG9mIHRoZSBicm93c2VyIHdpbmRvd1xuICogQHN1bW1hcnkgVGhpcyBmdW5jdGlvbiBwcm92aWRlcyBhIGNvbnZlbmllbnQgd2F5IHRvIGdldCB0aGUgY3VycmVudCB3aWR0aCBvZiB0aGUgYnJvd3NlciB3aW5kb3cuXG4gKiBJdCB1c2VzIHRoZSBnZXRPbldpbmRvdyBmdW5jdGlvbiB0byBhY2Nlc3MgdGhlICdpbm5lcldpZHRoJyBwcm9wZXJ0eSBvZiB0aGUgd2luZG93IG9iamVjdC5cbiAqIFRoaXMgaXMgdXNlZnVsIGZvciByZXNwb25zaXZlIGRlc2lnbiBpbXBsZW1lbnRhdGlvbnMgYW5kIHZpZXdwb3J0LWJhc2VkIGNhbGN1bGF0aW9ucy5cbiAqXG4gKiBAcmV0dXJuIHtudW1iZXIgfCB1bmRlZmluZWR9IFRoZSBjdXJyZW50IHdpZHRoIG9mIHRoZSBicm93c2VyIHdpbmRvdyBpbiBwaXhlbHNcbiAqXG4gKiBAZnVuY3Rpb24gZ2V0V2luZG93V2lkdGhcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWFuZ3VsYXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFdpbmRvd1dpZHRoKCk6IG51bWJlciB7XG4gIHJldHVybiBnZXRPbldpbmRvdygnaW5uZXJXaWR0aCcpIGFzIG51bWJlciB8fCAwO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDaGVja3MgaWYgYSB2YWx1ZSBpcyAgbm90IHVuZGVmaW5lZFxuICogQHN1bW1hcnkgVGhpcyB1dGlsaXR5IGZ1bmN0aW9uIGRldGVybWluZXMgd2hldGhlciBhIGdpdmVuIHZhbHVlIGlzIG5vdCB1bmRlZmluZWQuXG4gKiBJdCdzIGEgc2ltcGxlIHdyYXBwZXIgdGhhdCBtYWtlcyBjb2RlIG1vcmUgcmVhZGFibGUgd2hlbiBjaGVja2luZyBmb3IgZGVmaW5lZCB2YWx1ZXMuXG4gKiBUaGUgZnVuY3Rpb24gaXMgcGFydGljdWxhcmx5IHVzZWZ1bCBmb3IgY2hlY2tpbmcgU3RyaW5nT3JCb29sZWFuIHByb3BlcnRpZXMgdGhhdCBtaWdodCBiZSB1bmRlZmluZWQuXG4gKlxuICogQHBhcmFtIHtTdHJpbmdPckJvb2xlYW4gfCB1bmRlZmluZWR9IHByb3AgLSBUaGUgcHJvcGVydHkgdG8gY2hlY2tcbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgdGhlIHByb3BlcnR5IGlzIG5vdCB1bmRlZmluZWQsIGZhbHNlIG90aGVyd2lzZVxuICpcbiAqIEBmdW5jdGlvbiBpc05vdFVuZGVmaW5lZFxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItYW5ndWxhclxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNOb3RVbmRlZmluZWQocHJvcDogU3RyaW5nT3JCb29sZWFuIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gIHJldHVybiAocHJvcCAhPT0gdW5kZWZpbmVkKSBhcyBib29sZWFuO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBHZW5lcmF0ZXMgYSBsb2NhbGUgc3RyaW5nIGZyb20gYSBjbGFzcyBuYW1lIG9yIGluc3RhbmNlXG4gKiBAc3VtbWFyeSBUaGlzIHV0aWxpdHkgZnVuY3Rpb24gY29udmVydHMgYSBjbGFzcyBuYW1lIG9yIGluc3RhbmNlIGludG8gYSBsb2NhbGUgc3RyaW5nXG4gKiB0aGF0IGNhbiBiZSB1c2VkIGZvciBpbnRlcm5hdGlvbmFsaXphdGlvbiBwdXJwb3Nlcy4gSXQgaGFuZGxlcyBkaWZmZXJlbnQgaW5wdXQgdHlwZXNcbiAqIChzdHJpbmcsIGZ1bmN0aW9uLCBvciBvYmplY3QpIGFuZCBhcHBsaWVzIGZvcm1hdHRpbmcgcnVsZXMgdG8gZ2VuZXJhdGUgYSBjb25zaXN0ZW50XG4gKiBsb2NhbGUgaWRlbnRpZmllci4gRm9yIHNob3J0IG5hbWVzIChsZXNzIHRoYW4gMyBwYXJ0cyksIGl0IHJldmVyc2VzIHRoZSBkb3Qtc2VwYXJhdGVkXG4gKiBzdHJpbmcuIEZvciBsb25nZXIgbmFtZXMsIGl0IHVzZXMgdGhlIGxhc3QgcGFydCBhcyBhIHByZWZpeCBhbmQgam9pbnMgdGhlIHJlc3Qgd2l0aFxuICogdW5kZXJzY29yZXMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd8RnVuY3Rpb25MaWtlfG9iamVjdH0gaW5zdGFuY2UgLSBUaGUgaW5wdXQgdG8gZ2VuZXJhdGUgdGhlIGxvY2FsZSBmcm9tIChjbGFzcyBuYW1lLCBjb25zdHJ1Y3Rvciwgb3IgaW5zdGFuY2UpXG4gKiBAcGFyYW0ge3N0cmluZ30gW3N1ZmZpeF0gLSBPcHRpb25hbCBzdHJpbmcgdG8gYXBwZW5kIHRvIHRoZSBpbnN0YW5jZSBuYW1lIGJlZm9yZSBwcm9jZXNzaW5nXG4gKiBAcmV0dXJuIHtzdHJpbmd9IEEgZm9ybWF0dGVkIGxvY2FsZSBzdHJpbmcgZGVyaXZlZCBmcm9tIHRoZSBpbnB1dFxuICpcbiAqIEBmdW5jdGlvbiBnZXRMb2NhbGVGcm9tQ2xhc3NOYW1lXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1hbmd1bGFyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRMb2NhbGVGcm9tQ2xhc3NOYW1lKFxuICBpbnN0YW5jZTogc3RyaW5nIHwgRnVuY3Rpb25MaWtlIHwgS2V5VmFsdWUsXG4gIHN1ZmZpeD86IHN0cmluZ1xuKTogc3RyaW5nIHtcbiAgaWYgKHR5cGVvZiBpbnN0YW5jZSAhPT0gUHJpbWl0aXZlcy5TVFJJTkcpXG4gICAgaW5zdGFuY2UgPSAoaW5zdGFuY2UgYXMgRnVuY3Rpb25MaWtlKS5uYW1lIHx8IChpbnN0YW5jZSBhcyBvYmplY3QpPy5jb25zdHJ1Y3Rvcj8ubmFtZTtcblxuICBsZXQgbmFtZTogc3RyaW5nIHwgc3RyaW5nW10gPSBpbnN0YW5jZSBhcyBzdHJpbmc7XG5cbiAgaWYgKHN1ZmZpeClcbiAgICBuYW1lID0gYCR7aW5zdGFuY2V9JHtzdWZmaXguY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzdWZmaXguc2xpY2UoMSl9YDtcblxuICBuYW1lID0gbmFtZS5yZXBsYWNlKC9ffC0vZywgJycpLnJlcGxhY2UoLyg/Ol5cXHd8W0EtWl18XFxiXFx3KS9nLCAod29yZDogc3RyaW5nLCBpbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICBpZiAoaW5kZXggPiAxKSB3b3JkID0gJy4nICsgd29yZDtcbiAgICAgIHJldHVybiB3b3JkLnRvTG93ZXJDYXNlKCk7XG4gICAgfSkuc3BsaXQoJy4nKTtcblxuICBpZiAobmFtZS5sZW5ndGggPCAzKVxuICAgIHJldHVybiBuYW1lLnJldmVyc2UoKS5qb2luKCcuJyk7XG5cbiAgY29uc3QgcHJlZmZpeCA9IG5hbWVbbmFtZS5sZW5ndGggLSAxXTtcbiAgbmFtZS5wb3AoKTtcbiAgbmFtZSA9IG5hbWUuam9pbignXycpO1xuICByZXR1cm4gYCR7cHJlZmZpeH0uJHtuYW1lfWA7XG59XG5cblxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIGN1cnJlbnQgbG9jYWxlIGxhbmd1YWdlXG4gKiBAc3VtbWFyeSBUaGlzIHV0aWxpdHkgZnVuY3Rpb24gZ2V0cyB0aGUgY3VycmVudCBsb2NhbGUgbGFuZ3VhZ2UgYmFzZWQgb24gdGhlIHVzZXIncyBicm93c2VyIHNldHRpbmdzLlxuICogSXQgcHJvdmlkZXMgYSBjb25zaXN0ZW50IHdheSB0byBhY2Nlc3MgdGhlIHVzZXIncyBsYW5ndWFnZSBwcmVmZXJlbmNlIHRocm91Z2hvdXQgdGhlIGFwcGxpY2F0aW9uLlxuICogVGhlIGZ1bmN0aW9uIHJldHVybnMgdGhlIGJyb3dzZXIncyBuYXZpZ2F0b3IubGFuZ3VhZ2UgdmFsdWUsIGRlZmF1bHRpbmcgdG8gJ2VuJyBpZiBub3QgYXZhaWxhYmxlLlxuICpcbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGN1cnJlbnQgbG9jYWxlIGxhbmd1YWdlIChlLmcuLCAnZW4nLCAnZnInKVxuICpcbiAqIEBmdW5jdGlvbiBnZXRMb2NhbGVMYW5ndWFnZVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItYW5ndWxhclxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0TG9jYWxlTGFuZ3VhZ2UoKTogc3RyaW5nIHtcbiAgY29uc3Qgd2luID0gZ2V0V2luZG93KCk7XG4gIHJldHVybiAod2luIGFzIFdpbmRvdykubmF2aWdhdG9yLmxhbmd1YWdlIHx8IFwiZW5cIjtcbiAgLy8gcmV0dXJuIHdpbj8uW1dJTkRPV19LRVlTLkxBTkdVQUdFX1NFTEVDVEVEXSB8fCAod2luLm5hdmlnYXRvci5sYW5ndWFnZSB8fCAnJykuc3BsaXQoJy0nKVswXSB8fCBcImVuXCI7XG59XG5cblxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBHZW5lcmF0ZXMgYSByYW5kb20gc3RyaW5nIG9yIG51bWJlciBvZiBzcGVjaWZpZWQgbGVuZ3RoXG4gKiBAc3VtbWFyeSBUaGlzIHV0aWxpdHkgZnVuY3Rpb24gY3JlYXRlcyBhIHJhbmRvbSBzdHJpbmcgb2YgYSBzcGVjaWZpZWQgbGVuZ3RoLlxuICogSXQgY2FuIGdlbmVyYXRlIGVpdGhlciBhbHBoYW51bWVyaWMgc3RyaW5ncyAoaW5jbHVkaW5nIHVwcGVyY2FzZSBhbmQgbG93ZXJjYXNlIGxldHRlcnMpXG4gKiBvciBudW1lcmljLW9ubHkgc3RyaW5ncy4gVGhpcyBpcyB1c2VmdWwgZm9yIGNyZWF0aW5nIHJhbmRvbSBJRHMsIHRlbXBvcmFyeSBwYXNzd29yZHMsXG4gKiBvciBvdGhlciByYW5kb20gaWRlbnRpZmllcnMgdGhyb3VnaG91dCB0aGUgYXBwbGljYXRpb24uXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGg9OF0gLSBUaGUgbGVuZ3RoIG9mIHRoZSByYW5kb20gdmFsdWUgdG8gZ2VuZXJhdGVcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW29ubHlOdW1iZXJzPWZhbHNlXSAtIFdoZXRoZXIgdG8gZ2VuZXJhdGUgb25seSBudW1lcmljIGNoYXJhY3RlcnNcbiAqIEByZXR1cm4ge3N0cmluZ30gQSByYW5kb21seSBnZW5lcmF0ZWQgc3RyaW5nIG9mIHRoZSBzcGVjaWZpZWQgbGVuZ3RoIGFuZCBjaGFyYWN0ZXIgc2V0XG4gKlxuICogQGZ1bmN0aW9uIGdlbmVyYXRlUmFuZG9tVmFsdWVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWFuZ3VsYXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlUmFuZG9tVmFsdWUobGVuZ3RoOiBudW1iZXIgPSA4LCBvbmx5TnVtYmVyczogYm9vbGVhbiA9IGZhbHNlKTogc3RyaW5nIHtcbiAgY29uc3QgY2hhcnMgPSBvbmx5TnVtYmVyc1xuICAgID8gJzAxMjM0NTY3ODknXG4gICAgOiAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODknO1xuICBsZXQgcmVzdWx0ID0gJyc7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspXG4gICAgcmVzdWx0ICs9IGNoYXJzLmNoYXJBdChNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBjaGFycy5sZW5ndGgpKTtcblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5cbi8qKlxuICogQ29udmVydHMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBib29sZWFuIG9yIGEgYm9vbGVhbiB2YWx1ZSB0byBhIGJvb2xlYW4gdHlwZS5cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0geygndHJ1ZScgfCAnZmFsc2UnIHwgYm9vbGVhbil9IHByb3AgLSBUaGUgdmFsdWUgdG8gY29udmVydC4gQ2FuIGJlIHRoZSBzdHJpbmcgJ3RydWUnLCAnZmFsc2UnLCBvciBhIGJvb2xlYW4uXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVGhlIGJvb2xlYW4gcmVwcmVzZW50YXRpb24gb2YgdGhlIGlucHV0IHZhbHVlLiBSZXR1cm5zIHRydWUgaWYgdGhlIGlucHV0IGlzIHRoZSBzdHJpbmcgJ3RydWUnIG9yIGJvb2xlYW4gdHJ1ZSwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc3RyaW5nVG9Cb29sZWFuKHByb3A6ICd0cnVlJyB8ICdmYWxzZScgfCBib29sZWFuKTogYm9vbGVhbiB7XG4gIGlmKHR5cGVvZiBwcm9wID09PSAnc3RyaW5nJylcbiAgICBwcm9wID0gcHJvcC50b0xvd2VyQ2FzZSgpID09PSAndHJ1ZScgPyB0cnVlIDogZmFsc2U7XG4gIHJldHVybiBwcm9wO1xufVxuXG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgdmFsdWUgaXMgYSB2YWxpZCBEYXRlIG9iamVjdFxuICpcbiAqIEBwYXJhbSB7KHN0cmluZyB8IERhdGUgfCBudW1iZXIpfSBkYXRlIC0gVGhlIHZhbHVlIHRvIGNoZWNrLiBDYW4gYmUgYSBEYXRlIG9iamVjdCwgYSB0aW1lc3RhbXAgbnVtYmVyLCBvciBhIGRhdGUgc3RyaW5nXG4gKiBAcmV0dXJuIHtib29sZWFufSBSZXR1cm5zIHRydWUgaWYgdGhlIHZhbHVlIGlzIGEgdmFsaWQgRGF0ZSBvYmplY3QgKG5vdCBOYU4pLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWREYXRlKGRhdGU6IHN0cmluZyB8IERhdGUgfCBudW1iZXIpOiBib29sZWFuIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gKGRhdGUgaW5zdGFuY2VvZiBEYXRlICYmICFpc05hTihkYXRlIGFzIHVua25vd24gYXMgbnVtYmVyKSkgfHwgKCgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RSZWdleCA9IG5ldyBSZWdFeHAoL15cXGR7NH0tXFxkezJ9LVxcZHsyfSQvKS50ZXN0KGRhdGUgYXMgc3RyaW5nKVxuICAgICAgaWYodHlwZW9mIGRhdGUgIT09IFByaW1pdGl2ZXMuU1RSSU5HIHx8ICEoZGF0ZSBhcyBzdHJpbmcpPy5pbmNsdWRlcygnVCcpICYmICF0ZXN0UmVnZXgpXG4gICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICAgZGF0ZSA9IChkYXRlIGFzIHN0cmluZykuc3BsaXQoJ1QnKVswXTtcbiAgICBpZighbmV3IFJlZ0V4cCgvXlxcZHs0fS1cXGR7Mn0tXFxkezJ9JC8pLnRlc3QoZGF0ZSkpXG4gICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICByZXR1cm4gISEobmV3IERhdGUoZGF0ZSkpO1xuICAgfSkoKTtcbiAgfSBjYXRjaChlcnJvcjogdW5rbm93bikge1xuICAgIGdldExvZ2dlcihpc1ZhbGlkRGF0ZSkuZXJyb3IoZXJyb3IgYXMgRXJyb3IgfCBzdHJpbmcpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vKipcbiAqIEZvcm1hdHMgYSBkYXRlIGludG8gYSBsb2NhbGl6ZWQgc3RyaW5nIHJlcHJlc2VudGF0aW9uXG4gKlxuICogQHBhcmFtIHsoc3RyaW5nIHwgRGF0ZSB8IG51bWJlcil9IGRhdGUgLSBUaGUgZGF0ZSB0byBmb3JtYXQuIENhbiBiZSBhIERhdGUgb2JqZWN0LCBhIHRpbWVzdGFtcCBudW1iZXIsIG9yIGEgZGF0ZSBzdHJpbmdcbiAqIEBwYXJhbSB7c3RyaW5nfSBbbG9jYWxlXSAtIFRoZSBsb2NhbGUgdG8gdXNlIGZvciBmb3JtYXR0aW5nLiBJZiBub3QgcHJvdmlkZWQsIHRoZSBzeXN0ZW0ncyBsb2NhbGUgd2lsbCBiZSB1c2VkXG4gKiBAcmV0dXJuIHsoRGF0ZSB8IHN0cmluZyl9IEEgZm9ybWF0dGVkIGRhdGUgc3RyaW5nIGluIHRoZSBmb3JtYXQgREQvTU0vWVlZWSBhY2NvcmRpbmcgdG8gdGhlIHNwZWNpZmllZCBsb2NhbGUsXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yIHRoZSBvcmlnaW5hbCBpbnB1dCBhcyBhIHN0cmluZyBpZiB0aGUgZGF0ZSBpcyBpbnZhbGlkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXREYXRlKGRhdGU6IHN0cmluZyB8IERhdGUgfCBudW1iZXIsIGxvY2FsZT86IHN0cmluZyB8IHVuZGVmaW5lZCk6IERhdGUgfCBzdHJpbmcge1xuXG4gIGlmKCFsb2NhbGUpXG4gICAgbG9jYWxlID0gZ2V0TG9jYWxlTGFuZ3VhZ2UoKTtcblxuICBpZih0eXBlb2YgZGF0ZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGRhdGUgPT09ICdudW1iZXInKVxuICAgIGRhdGUgPSBuZXcgRGF0ZSh0eXBlb2YgZGF0ZSA9PT0gJ3N0cmluZycgPyBkYXRlLnJlcGxhY2UoL1xcLy9nLCAnLScpIDogZGF0ZSk7XG5cbiAgaWYoIWlzVmFsaWREYXRlKGRhdGUpKVxuICAgIHJldHVybiBgJHtkYXRlfWAgYXMgc3RyaW5nO1xuICBjb25zdCByID0gZGF0ZS50b0xvY2FsZVN0cmluZyhsb2NhbGUsIHtcbiAgICAgIHllYXI6IFwibnVtZXJpY1wiLFxuICAgICAgZGF5OiBcIjItZGlnaXRcIixcbiAgICAgIG1vbnRoOiAnMi1kaWdpdCdcbiAgfSk7XG5cblxuICByZXR1cm4gcjtcbn1cblxuLyoqXG4gKiBBdHRlbXB0cyB0byBwYXJzZSBhIGRhdGUgc3RyaW5nLCBEYXRlIG9iamVjdCwgb3IgbnVtYmVyIGludG8gYSB2YWxpZCBEYXRlIG9iamVjdFxuICpcbiAqIEBwYXJhbSB7KHN0cmluZyB8IERhdGUgfCBudW1iZXIpfSBkYXRlIC0gVGhlIGRhdGUgdG8gcGFyc2UuIENhbiBiZSBhIERhdGUgb2JqZWN0LCBhIHRpbWVzdGFtcCBudW1iZXIsXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3IgYSBkYXRlIHN0cmluZyBpbiB0aGUgZm9ybWF0IFwiREQvTU0vWVlZWSBISDpNTTpTUzpNU1wiXG4gKiBAcmV0dXJuIHsoRGF0ZSB8IG51bGwpfSBBIHZhbGlkIERhdGUgb2JqZWN0IGlmIHBhcnNpbmcgaXMgc3VjY2Vzc2Z1bCwgb3IgbnVsbCBpZiB0aGUgZGF0ZSBpcyBpbnZhbGlkXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICBvciBkb2Vzbid0IG1hdGNoIHRoZSBleHBlY3RlZCBmb3JtYXRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlVG9WYWxpZERhdGUoZGF0ZTogc3RyaW5nIHwgRGF0ZSB8IG51bWJlcik6IERhdGUgfCBudWxsIHtcbiAgaWYoaXNWYWxpZERhdGUoZGF0ZSkpXG4gICAgcmV0dXJuIGRhdGUgYXMgRGF0ZTtcblxuICBpZighYCR7ZGF0ZX1gLmluY2x1ZGVzKCcvJykpXG4gICAgcmV0dXJuIG51bGw7XG5cbiAgY29uc3QgW2RhdGVTdHJpbmcsIHRpbWVTdHJpbmddID0gKGRhdGUgYXMgc3RyaW5nKS5zcGxpdCgnICcpO1xuICBjb25zdCBbZGF5LCBtb250aCwgeWVhcl0gPSBkYXRlU3RyaW5nLnNwbGl0KCcvJykubWFwKE51bWJlcik7XG4gIGNvbnN0IFtob3VycywgbWludXRlcywgc2Vjb25kcywgbWlsbGlzZWNvbmRzXSA9IHRpbWVTdHJpbmcuc3BsaXQoJzonKS5tYXAoTnVtYmVyKTtcbiAgZGF0ZSA9IG5ldyBEYXRlKHllYXIsIG1vbnRoIC0gMSwgZGF5LCBob3VycywgbWludXRlcywgc2Vjb25kcywgbWlsbGlzZWNvbmRzKTtcblxuICBpZighaXNWYWxpZERhdGUoZGF0ZSkpIHtcbiAgICBjb25zb2xlLndhcm4oJ3BhcnNlVG9WYWxpZERhdGUgLSBJbnZhbGlkIGRhdGUgZm9ybWF0JywgZGF0ZSk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gZGF0ZTtcbn1cblxuXG4vKipcbiAqIE1hcHMgYW4gaXRlbSBvYmplY3QgdXNpbmcgYSBwcm92aWRlZCBtYXBwZXIgb2JqZWN0IGFuZCBvcHRpb25hbCBhZGRpdGlvbmFsIHByb3BlcnRpZXMuXG4gKlxuICogQHBhcmFtIHtLZXlWYWx1ZX0gaXRlbSAtIFRoZSBzb3VyY2Ugb2JqZWN0IHRvIGJlIG1hcHBlZC5cbiAqIEBwYXJhbSB7S2V5VmFsdWV9IG1hcHBlciAtIEFuIG9iamVjdCB0aGF0IGRlZmluZXMgdGhlIG1hcHBpbmcgcnVsZXMuIEtleXMgcmVwcmVzZW50IHRoZSBuZXcgcHJvcGVydHkgbmFtZXMsXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmQgdmFsdWVzIHJlcHJlc2VudCB0aGUgcGF0aCB0byB0aGUgY29ycmVzcG9uZGluZyB2YWx1ZXMgaW4gdGhlIHNvdXJjZSBvYmplY3QuXG4gKiBAcGFyYW0ge0tleVZhbHVlfSBbcHJvcHNdIC0gT3B0aW9uYWwgYWRkaXRpb25hbCBwcm9wZXJ0aWVzIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBtYXBwZWQgb2JqZWN0LlxuICogQHJldHVybnMge0tleVZhbHVlfSBBIG5ldyBvYmplY3Qgd2l0aCBwcm9wZXJ0aWVzIG1hcHBlZCBhY2NvcmRpbmcgdG8gdGhlIG1hcHBlciBvYmplY3QgYW5kIGluY2x1ZGluZyBhbnkgYWRkaXRpb25hbCBwcm9wZXJ0aWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXRlbU1hcHBlcihpdGVtOiBLZXlWYWx1ZSwgbWFwcGVyOiBLZXlWYWx1ZSwgcHJvcHM/OiBLZXlWYWx1ZSk6IEtleVZhbHVlIHtcbiAgcmV0dXJuIE9iamVjdC5lbnRyaWVzKG1hcHBlcikucmVkdWNlKChhY2N1bTogS2V5VmFsdWUsIFtrZXksIHZhbHVlXSkgPT4ge1xuICAgIGNvbnN0IGFycmF5VmFsdWUgPSAodmFsdWUgYXMgc3RyaW5nKS5zcGxpdCgnLicpO1xuICAgIGlmICghdmFsdWUpIHtcbiAgICAgIGFjY3VtW2tleV0gPSB2YWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGFycmF5VmFsdWUubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIGFjY3VtW2tleV0gPSBpdGVtPy5bdmFsdWUgYXMgc3RyaW5nXSB8fCAodmFsdWUgIT09IGtleSA/IHZhbHVlIDogXCJcIik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsZXQgdmFsO1xuXG4gICAgICAgIGZvciAoY29uc3QgX3ZhbHVlIG9mIGFycmF5VmFsdWUpXG4gICAgICAgICAgdmFsID0gIXZhbFxuICAgICAgICAgICAgPyBpdGVtW192YWx1ZV1cbiAgICAgICAgICAgIDogKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnID8gSlNPTi5wYXJzZSh2YWwpIDogdmFsKVtfdmFsdWVdO1xuXG4gICAgICAgIGlmIChpc1ZhbGlkRGF0ZShuZXcgRGF0ZSh2YWwpKSkgdmFsID0gYCR7Zm9ybWF0RGF0ZSh2YWwpfWA7XG5cbiAgICAgICAgYWNjdW1ba2V5XSA9IHZhbCA9PT0gbnVsbCB8fCB2YWwgPT09IHVuZGVmaW5lZCA/IHZhbHVlIDogdmFsO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgcHJvcHMgfHwge30sIGFjY3VtKTtcbiAgfSwge30pO1xufVxuXG4vKipcbiAqIE1hcHMgYW4gYXJyYXkgb2YgZGF0YSBvYmplY3RzIHVzaW5nIGEgcHJvdmlkZWQgbWFwcGVyIG9iamVjdC5cbiAqXG4gKiBAdGVtcGxhdGUgVCAtIFRoZSB0eXBlIG9mIHRoZSByZXN1bHRpbmcgbWFwcGVkIGl0ZW1zLlxuICogQHBhcmFtIHthbnlbXX0gZGF0YSAtIFRoZSBhcnJheSBvZiBkYXRhIG9iamVjdHMgdG8gYmUgbWFwcGVkLlxuICogQHBhcmFtIHtLZXlWYWx1ZX0gbWFwcGVyIC0gQW4gb2JqZWN0IHRoYXQgZGVmaW5lcyB0aGUgbWFwcGluZyBydWxlcy5cbiAqIEBwYXJhbSB7S2V5VmFsdWV9IFtwcm9wc10gLSBBZGRpdGlvbmFsIHByb3BlcnRpZXMgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIG1hcHBlZCBpdGVtcy5cbiAqXG4gKiBAcmV0dXJucyB7VFtdfSAtIFRoZSBhcnJheSBvZiBtYXBwZWQgaXRlbXMuIElmIGFuIGl0ZW0gaW4gdGhlIG9yaWdpbmFsIGFycmF5IGRvZXMgbm90IGhhdmUgYW55IG5vbi1udWxsIHZhbHVlcyBhZnRlciBtYXBwaW5nLFxuICogdGhlIG9yaWdpbmFsIGl0ZW0gaXMgcmV0dXJuZWQgaW5zdGVhZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRhdGFNYXBwZXI8VD4oZGF0YTogVFtdLCBtYXBwZXI6IEtleVZhbHVlLCBwcm9wcz86IEtleVZhbHVlKTogVFtdIHtcbiAgaWYgKCFkYXRhIHx8ICFkYXRhLmxlbmd0aCkgcmV0dXJuIFtdO1xuICByZXR1cm4gZGF0YS5yZWR1Y2UoKGFjY3VtOiBUW10sIGN1cnIpID0+IHtcbiAgICBjb25zdCBpdGVtID0gaXRlbU1hcHBlcihjdXJyIGFzIEtleVZhbHVlLCBtYXBwZXIsIHByb3BzKSBhcyBUO1xuICAgIGNvbnN0IGhhc1ZhbHVlcyA9XG4gICAgICBbLi4ubmV3IFNldChPYmplY3QudmFsdWVzKGl0ZW0gYXMgVFtdKSldLmZpbHRlcigodmFsdWUpID0+IHZhbHVlKS5sZW5ndGggPlxuICAgICAgMDtcbiAgICBhY2N1bS5wdXNoKGhhc1ZhbHVlcyA/IGl0ZW0gOiBjdXJyKTtcbiAgICByZXR1cm4gYWNjdW07XG4gIH0sIFtdKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVtb3ZlcyBmb2N1cyBmcm9tIHRoZSBjdXJyZW50bHkgYWN0aXZlIERPTSBlbGVtZW50XG4gKiBAc3VtbWFyeSBUaGlzIHV0aWxpdHkgZnVuY3Rpb24gYmx1cnMgdGhlIGN1cnJlbnRseSBmb2N1c2VkIGVsZW1lbnQgaW4gdGhlIGRvY3VtZW50LFxuICogZWZmZWN0aXZlbHkgcmVtb3ZpbmcgZm9jdXMgdHJhcHMgdGhhdCBtaWdodCBwcmV2ZW50IHByb3BlciBuYXZpZ2F0aW9uIG9yIGtleWJvYXJkXG4gKiBpbnRlcmFjdGlvbi4gSXQgc2FmZWx5IGFjY2Vzc2VzIHRoZSBkb2N1bWVudCdzIGFjdGl2ZUVsZW1lbnQgYW5kIGNhbGxzIGJsdXIoKSBpZlxuICogYW4gZWxlbWVudCBpcyBjdXJyZW50bHkgZm9jdXNlZC4gVGhpcyBpcyB1c2VmdWwgZm9yIGFjY2Vzc2liaWxpdHkgYW5kIHVzZXIgZXhwZXJpZW5jZVxuICogaW1wcm92ZW1lbnRzLCBwYXJ0aWN1bGFybHkgd2hlbiBjbG9zaW5nIG1vZGFscyBvciBkaWFsb2dzLlxuICpcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKlxuICogQGZ1bmN0aW9uIHJlbW92ZUZvY3VzVHJhcFxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItYW5ndWxhclxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlRm9jdXNUcmFwKCk6IHZvaWQge1xuICBjb25zdCBkb2MgPSBnZXRXaW5kb3dEb2N1bWVudCgpO1xuICBpZihkb2M/LmFjdGl2ZUVsZW1lbnQpXG4gICAgKGRvYy5hY3RpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50KT8uYmx1cigpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDbGVhbnMgYW5kIG5vcm1hbGl6ZXMgd2hpdGVzcGFjZSBpbiBhIHN0cmluZyB2YWx1ZVxuICogQHN1bW1hcnkgVGhpcyB1dGlsaXR5IGZ1bmN0aW9uIHRyaW1zIGxlYWRpbmcgYW5kIHRyYWlsaW5nIHdoaXRlc3BhY2UgZnJvbSBhIHN0cmluZ1xuICogYW5kIHJlcGxhY2VzIG11bHRpcGxlIGNvbnNlY3V0aXZlIHdoaXRlc3BhY2UgY2hhcmFjdGVycyB3aXRoIGEgc2luZ2xlIHNwYWNlLlxuICogT3B0aW9uYWxseSBjb252ZXJ0cyB0aGUgcmVzdWx0IHRvIGxvd2VyY2FzZSBmb3IgY29uc2lzdGVudCB0ZXh0IHByb2Nlc3NpbmcuXG4gKiBUaGlzIGlzIHVzZWZ1bCBmb3Igbm9ybWFsaXppbmcgdXNlciBpbnB1dCwgc2VhcmNoIHRlcm1zLCBvciBkYXRhIHNhbml0aXphdGlvbi5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgLSBUaGUgc3RyaW5nIHZhbHVlIHRvIGNsZWFuIGFuZCBub3JtYWxpemVcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2xvd2VyY2FzZT1mYWxzZV0gLSBXaGV0aGVyIHRvIGNvbnZlcnQgdGhlIHJlc3VsdCB0byBsb3dlcmNhc2VcbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGNsZWFuZWQgYW5kIG5vcm1hbGl6ZWQgc3RyaW5nXG4gKlxuICogQGZ1bmN0aW9uIGNsZWFuU3BhY2VzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1hbmd1bGFyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGVhblNwYWNlcyh2YWx1ZTogc3RyaW5nID0gXCJcIiwgbG93ZXJjYXNlOiBib29sZWFuID0gZmFsc2UpOiBzdHJpbmcge1xuICB2YWx1ZSA9IGAke3ZhbHVlfWAudHJpbSgpLnJlcGxhY2UoL1xccysvZywgJyAnKTtcbiAgcmV0dXJuIGxvd2VyY2FzZSA/IHZhbHVlLnRvTG93ZXJDYXNlKCkgOiB2YWx1ZTtcbn1cblxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZXRlcm1pbmVzIGlmIHRoZSB1c2VyJ3Mgc3lzdGVtIGlzIGN1cnJlbnRseSBpbiBkYXJrIG1vZGVcbiAqIEBzdW1tYXJ5IFRoaXMgZnVuY3Rpb24gY2hlY2tzIHRoZSB1c2VyJ3MgY29sb3Igc2NoZW1lIHByZWZlcmVuY2UgdXNpbmcgdGhlIENTUyBtZWRpYSBxdWVyeVxuICogJyhwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyayknLiBJdCByZXR1cm5zIGEgYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIHN5c3RlbSBpc1xuICogY3VycmVudGx5IHNldCB0byBkYXJrIG1vZGUuIFRoaXMgaXMgdXNlZnVsIGZvciBpbXBsZW1lbnRpbmcgdGhlbWUtYXdhcmUgZnVuY3Rpb25hbGl0eVxuICogYW5kIGFkanVzdGluZyBVSSBlbGVtZW50cyBiYXNlZCBvbiB0aGUgdXNlcidzIHByZWZlcnJlZCBjb2xvciBzY2hlbWUuXG4gKlxuICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gVHJ1ZSBpZiB0aGUgc3lzdGVtIGlzIGluIGRhcmsgbW9kZSwgZmFsc2Ugb3RoZXJ3aXNlXG4gKlxuICogQGZ1bmN0aW9uIGlzRGFya01vZGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWFuZ3VsYXJcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGlzRGFya01vZGUoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIGNvbnN0IHttYXRjaGVzfSA9IGdldFdpbmRvdygpLm1hdGNoTWVkaWEoJyhwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyayknKTtcbiAgcmV0dXJuIG1hdGNoZXM7XG59XG4iXX0=
@@ -1,86 +0,0 @@
1
- import { TranslateHttpLoader } from '@ngx-translate/http-loader';
2
- import { forkJoin } from 'rxjs';
3
- import { map } from 'rxjs/operators';
4
- import { inject } from '@angular/core';
5
- import { cleanSpaces, getLocaleFromClassName } from '../helpers';
6
- import en from './data/en.json';
7
- import { I18N_CONFIG_TOKEN } from '../for-angular-common.module';
8
- export class I18nLoader {
9
- static loadFromHttp(http) {
10
- function getSuffix() {
11
- const today = new Date();
12
- return `.json?version=${today.getFullYear()}${today.getMonth()}${today.getDay()}`;
13
- }
14
- return new (class extends TranslateHttpLoader {
15
- getTranslation(lang) {
16
- const res = super.getTranslation(lang);
17
- return res;
18
- }
19
- })(http, './assets/i18n/', getSuffix());
20
- }
21
- }
22
- export function getLocaleContext(clazz, suffix) {
23
- return getLocaleFromClassName(clazz, suffix);
24
- }
25
- /**
26
- * @description Generates a localized string by combining locale and phrase
27
- * @summary This utility function creates a properly formatted locale string by combining
28
- * a locale identifier with a phrase. It handles edge cases such as empty phrases,
29
- * missing locales, and phrases that already include the locale prefix. This function
30
- * is useful for ensuring consistent formatting of localized strings throughout the application.
31
- *
32
- * @param {string} locale - The locale identifier (e.g., 'en', 'fr')
33
- * @param {string | undefined} phrase - The phrase to localize
34
- * @return {string} The formatted locale string, or empty string if phrase is undefined
35
- *
36
- * @function generateLocaleFromString
37
- * @memberOf module:for-angular
38
- */
39
- export function getLocaleContextByKey(locale, phrase) {
40
- if (!phrase)
41
- return locale;
42
- if (!locale || phrase.includes(`${locale}.`))
43
- return phrase;
44
- const parts = phrase.split(' ');
45
- return `${locale}.${cleanSpaces(parts.join('.'), true)}`;
46
- }
47
- export function I18nLoaderFactory(http) {
48
- const { resources, versionedSuffix } = inject(I18N_CONFIG_TOKEN, { optional: true }) ?? getI18nLoaderFactoryProviderConfig().useValue;
49
- return new MultiI18nLoader(http, resources, versionedSuffix);
50
- }
51
- export function getI18nLoaderFactoryProviderConfig(resources = [], versionedSuffix = false) {
52
- if (!Array.isArray(resources))
53
- resources = [resources];
54
- return {
55
- provide: I18N_CONFIG_TOKEN,
56
- useValue: { resources: [
57
- // { prefix: './assets/i18n/', suffix: '.json' },
58
- ...resources
59
- ], versionedSuffix }
60
- };
61
- }
62
- const libLanguage = { en };
63
- export class MultiI18nLoader {
64
- constructor(http, resources = [], versionedSuffix = false) {
65
- this.http = http;
66
- this.resources = resources;
67
- this.versionedSuffix = versionedSuffix;
68
- }
69
- getSuffix(suffix) {
70
- if (!this.versionedSuffix)
71
- return suffix;
72
- const today = new Date();
73
- return `${suffix}?version=${today.getFullYear()}${today.getMonth()}${today.getDay()}`;
74
- }
75
- getTranslation(lang) {
76
- const libKeys = libLanguage[lang] || libLanguage["en"] || {};
77
- const httpRequests$ = forkJoin(this.resources.map(config => this.http.get(`${config.prefix}${lang}${this.getSuffix(config.suffix)}`)));
78
- return httpRequests$.pipe(map(res => {
79
- return {
80
- ...libKeys,
81
- ...res.reduce((acc, current) => ({ ...acc, ...current }), {})
82
- };
83
- }));
84
- }
85
- }
86
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTG9hZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9pMThuL0xvYWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNqRSxPQUFPLEVBQUUsUUFBUSxFQUFlLE1BQU0sTUFBTSxDQUFDO0FBQzdDLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVyQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRXZDLE9BQU8sRUFBRSxXQUFXLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDakUsT0FBTyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDakUsTUFBTSxPQUFPLFVBQVU7SUFDckIsTUFBTSxDQUFDLFlBQVksQ0FBQyxJQUFnQjtRQUNsQyxTQUFTLFNBQVM7WUFDaEIsTUFBTSxLQUFLLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUN6QixPQUFPLGlCQUFpQixLQUFLLENBQUMsV0FBVyxFQUFFLEdBQUcsS0FBSyxDQUFDLFFBQVEsRUFBRSxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBWSxDQUFDO1FBQzlGLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxLQUFNLFNBQVEsbUJBQW1CO1lBQ2xDLGNBQWMsQ0FBQyxJQUFZO2dCQUNsQyxNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUN2QyxPQUFPLEdBQUcsQ0FBQztZQUNiLENBQUM7U0FDRixDQUFDLENBQUMsSUFBSSxFQUFFLGdCQUFnQixFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUM7SUFDMUMsQ0FBQztDQUNGO0FBR0QsTUFBTSxVQUFVLGdCQUFnQixDQUFDLEtBQXFDLEVBQUUsTUFB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RSxFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsR0FBRyxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7YUFDOUQsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUNILENBQUM7SUFDSixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBIdHRwQ2xpZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgVHJhbnNsYXRlTG9hZGVyLCBUcmFuc2xhdGlvbk9iamVjdCB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHsgVHJhbnNsYXRlSHR0cExvYWRlciB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2h0dHAtbG9hZGVyJztcbmltcG9ydCB7IGZvcmtKb2luLCAgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtJMThuUmVzb3VyY2VDb25maWd9IGZyb20gJy4uL2VuZ2luZS9pbnRlcmZhY2VzJztcbmltcG9ydCB7IGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRnVuY3Rpb25MaWtlIH0gZnJvbSAnLi4vZW5naW5lJztcbmltcG9ydCB7IGNsZWFuU3BhY2VzLCBnZXRMb2NhbGVGcm9tQ2xhc3NOYW1lIH0gZnJvbSAnLi4vaGVscGVycyc7XG5pbXBvcnQgZW4gZnJvbSAnLi9kYXRhL2VuLmpzb24nO1xuaW1wb3J0IHsgSTE4Tl9DT05GSUdfVE9LRU4gfSBmcm9tICcuLi9mb3ItYW5ndWxhci1jb21tb24ubW9kdWxlJztcbmV4cG9ydCBjbGFzcyBJMThuTG9hZGVyIHtcbiAgc3RhdGljIGxvYWRGcm9tSHR0cChodHRwOiBIdHRwQ2xpZW50KTogVHJhbnNsYXRlTG9hZGVyIHtcbiAgICBmdW5jdGlvbiBnZXRTdWZmaXgoKSB7XG4gICAgICBjb25zdCB0b2RheSA9IG5ldyBEYXRlKCk7XG4gICAgICByZXR1cm4gYC5qc29uP3ZlcnNpb249JHt0b2RheS5nZXRGdWxsWWVhcigpfSR7dG9kYXkuZ2V0TW9udGgoKX0ke3RvZGF5LmdldERheSgpfWAgYXMgc3RyaW5nO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgKGNsYXNzIGV4dGVuZHMgVHJhbnNsYXRlSHR0cExvYWRlciB7XG4gICAgICBvdmVycmlkZSBnZXRUcmFuc2xhdGlvbihsYW5nOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFRyYW5zbGF0aW9uT2JqZWN0PiB7XG4gICAgICAgIGNvbnN0IHJlcyA9IHN1cGVyLmdldFRyYW5zbGF0aW9uKGxhbmcpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgfVxuICAgIH0pKGh0dHAsICcuL2Fzc2V0cy9pMThuLycsIGdldFN1ZmZpeCgpKTtcbiAgfVxufVxuXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRMb2NhbGVDb250ZXh0KGNsYXp6OiBGdW5jdGlvbkxpa2UgfCBvYmplY3QgfCBzdHJpbmcsIHN1ZmZpeD86IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBnZXRMb2NhbGVGcm9tQ2xhc3NOYW1lKGNsYXp6LCBzdWZmaXgpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBHZW5lcmF0ZXMgYSBsb2NhbGl6ZWQgc3RyaW5nIGJ5IGNvbWJpbmluZyBsb2NhbGUgYW5kIHBocmFzZVxuICogQHN1bW1hcnkgVGhpcyB1dGlsaXR5IGZ1bmN0aW9uIGNyZWF0ZXMgYSBwcm9wZXJseSBmb3JtYXR0ZWQgbG9jYWxlIHN0cmluZyBieSBjb21iaW5pbmdcbiAqIGEgbG9jYWxlIGlkZW50aWZpZXIgd2l0aCBhIHBocmFzZS4gSXQgaGFuZGxlcyBlZGdlIGNhc2VzIHN1Y2ggYXMgZW1wdHkgcGhyYXNlcyxcbiAqIG1pc3NpbmcgbG9jYWxlcywgYW5kIHBocmFzZXMgdGhhdCBhbHJlYWR5IGluY2x1ZGUgdGhlIGxvY2FsZSBwcmVmaXguIFRoaXMgZnVuY3Rpb25cbiAqIGlzIHVzZWZ1bCBmb3IgZW5zdXJpbmcgY29uc2lzdGVudCBmb3JtYXR0aW5nIG9mIGxvY2FsaXplZCBzdHJpbmdzIHRocm91Z2hvdXQgdGhlIGFwcGxpY2F0aW9uLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBsb2NhbGUgLSBUaGUgbG9jYWxlIGlkZW50aWZpZXIgKGUuZy4sICdlbicsICdmcicpXG4gKiBAcGFyYW0ge3N0cmluZyB8IHVuZGVmaW5lZH0gcGhyYXNlIC0gVGhlIHBocmFzZSB0byBsb2NhbGl6ZVxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIGxvY2FsZSBzdHJpbmcsIG9yIGVtcHR5IHN0cmluZyBpZiBwaHJhc2UgaXMgdW5kZWZpbmVkXG4gKlxuICogQGZ1bmN0aW9uIGdlbmVyYXRlTG9jYWxlRnJvbVN0cmluZ1xuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItYW5ndWxhclxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0TG9jYWxlQ29udGV4dEJ5S2V5KFxuICBsb2NhbGU6IHN0cmluZyxcbiAgcGhyYXNlOiBzdHJpbmcgfCB1bmRlZmluZWRcbik6IHN0cmluZyB7XG4gIGlmICghcGhyYXNlKVxuICAgIHJldHVybiBsb2NhbGU7XG4gIGlmICghbG9jYWxlIHx8IHBocmFzZS5pbmNsdWRlcyhgJHtsb2NhbGV9LmApKVxuICAgIHJldHVybiBwaHJhc2U7XG4gIGNvbnN0IHBhcnRzID0gcGhyYXNlLnNwbGl0KCcgJyk7XG4gIHJldHVybiBgJHtsb2NhbGV9LiR7Y2xlYW5TcGFjZXMocGFydHMuam9pbignLicpLCB0cnVlKX1gO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gSTE4bkxvYWRlckZhY3RvcnkoaHR0cDogSHR0cENsaWVudCk6IFRyYW5zbGF0ZUxvYWRlciB7XG4gIGNvbnN0IHtyZXNvdXJjZXMsIHZlcnNpb25lZFN1ZmZpeH0gPSBpbmplY3QoSTE4Tl9DT05GSUdfVE9LRU4sIHsgb3B0aW9uYWw6IHRydWUgfSkgPz8gZ2V0STE4bkxvYWRlckZhY3RvcnlQcm92aWRlckNvbmZpZygpLnVzZVZhbHVlO1xuICByZXR1cm4gbmV3IE11bHRpSTE4bkxvYWRlcihodHRwLCByZXNvdXJjZXMsIHZlcnNpb25lZFN1ZmZpeCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRJMThuTG9hZGVyRmFjdG9yeVByb3ZpZGVyQ29uZmlnKHJlc291cmNlczogSTE4blJlc291cmNlQ29uZmlnIHwgSTE4blJlc291cmNlQ29uZmlnW10gPSBbXSwgdmVyc2lvbmVkU3VmZml4OiBib29sZWFuID0gZmFsc2UpIHtcbiAgaWYoIUFycmF5LmlzQXJyYXkocmVzb3VyY2VzKSlcbiAgICByZXNvdXJjZXMgPSBbcmVzb3VyY2VzXTtcbiAgcmV0dXJuIHtcbiAgICBwcm92aWRlOiBJMThOX0NPTkZJR19UT0tFTixcbiAgICB1c2VWYWx1ZTogeyByZXNvdXJjZXM6IFtcbiAgICAgIC8vIHsgcHJlZml4OiAnLi9hc3NldHMvaTE4bi8nLCBzdWZmaXg6ICcuanNvbicgfSxcbiAgICAgIC4uLnJlc291cmNlc1xuICAgIF0sIHZlcnNpb25lZFN1ZmZpeH1cbiAgfVxufVxuXG5jb25zdCBsaWJMYW5ndWFnZTogUmVjb3JkPHN0cmluZywgVHJhbnNsYXRpb25PYmplY3Q+ID0ge2VufTtcblxuZXhwb3J0IGNsYXNzIE11bHRpSTE4bkxvYWRlciBpbXBsZW1lbnRzIEkxOG5Mb2FkZXIge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGh0dHA6IEh0dHBDbGllbnQsIHByaXZhdGUgcmVzb3VyY2VzOiBJMThuUmVzb3VyY2VDb25maWdbXSA9IFtdLCBwcml2YXRlIHZlcnNpb25lZFN1ZmZpeDogYm9vbGVhbiA9IGZhbHNlKSB7fVxuXG4gIHByaXZhdGUgZ2V0U3VmZml4KHN1ZmZpeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZighdGhpcy52ZXJzaW9uZWRTdWZmaXgpXG4gICAgICByZXR1cm4gc3VmZml4O1xuICAgIGNvbnN0IHRvZGF5ID0gbmV3IERhdGUoKTtcbiAgICByZXR1cm4gYCR7c3VmZml4fT92ZXJzaW9uPSR7dG9kYXkuZ2V0RnVsbFllYXIoKX0ke3RvZGF5LmdldE1vbnRoKCl9JHt0b2RheS5nZXREYXkoKX1gIGFzIHN0cmluZztcbiAgfVxuXG4gIGdldFRyYW5zbGF0aW9uKGxhbmc6IHN0cmluZyk6IE9ic2VydmFibGU8VHJhbnNsYXRpb25PYmplY3Q+IHtcbiAgICBjb25zdCBsaWJLZXlzID0gbGliTGFuZ3VhZ2VbbGFuZ10gfHwgbGliTGFuZ3VhZ2VbXCJlblwiXSB8fCB7fTtcbiAgICBjb25zdCBodHRwUmVxdWVzdHMkID0gZm9ya0pvaW4oXG4gICAgICB0aGlzLnJlc291cmNlcy5tYXAoY29uZmlnID0+XG4gICAgICAgIHRoaXMuaHR0cC5nZXQ8VHJhbnNsYXRpb25PYmplY3Q+KFxuICAgICAgICAgIGAke2NvbmZpZy5wcmVmaXh9JHtsYW5nfSR7dGhpcy5nZXRTdWZmaXgoY29uZmlnLnN1ZmZpeCl9YFxuICAgICAgICApXG4gICAgICApXG4gICAgKTtcbiAgICByZXR1cm4gaHR0cFJlcXVlc3RzJC5waXBlKFxuICAgICAgbWFwKHJlcyA9PiB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgLi4ubGliS2V5cyxcbiAgICAgICAgICAuLi5yZXMucmVkdWNlKChhY2MsIGN1cnJlbnQpID0+ICh7IC4uLmFjYywgLi4uY3VycmVudCB9KSwge30pXG4gICAgICAgIH07XG4gICAgICB9KVxuICAgICk7XG4gIH1cbn1cbiJdfQ==