@decaf-ts/logging 0.3.26 → 0.3.28

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 (71) hide show
  1. package/README.md +3 -1
  2. package/dist/logging.cjs +2 -2086
  3. package/dist/logging.cjs.map +1 -0
  4. package/dist/logging.js +2 -0
  5. package/dist/logging.js.map +1 -0
  6. package/lib/LoggedClass.cjs +1 -1
  7. package/lib/LoggedClass.js.map +1 -0
  8. package/lib/constants.cjs +1 -1
  9. package/lib/constants.js.map +1 -0
  10. package/lib/decorators.cjs +1 -1
  11. package/lib/decorators.js.map +1 -0
  12. package/lib/environment.cjs +1 -1
  13. package/lib/environment.js.map +1 -0
  14. package/lib/esm/LoggedClass.js +1 -1
  15. package/lib/esm/LoggedClass.js.map +1 -0
  16. package/lib/esm/constants.js +1 -1
  17. package/lib/esm/constants.js.map +1 -0
  18. package/lib/esm/decorators.js +1 -1
  19. package/lib/esm/decorators.js.map +1 -0
  20. package/lib/esm/environment.js +1 -1
  21. package/lib/esm/environment.js.map +1 -0
  22. package/lib/esm/filters/LogFilter.js +1 -1
  23. package/lib/esm/filters/LogFilter.js.map +1 -0
  24. package/lib/esm/filters/PatternFilter.js +1 -1
  25. package/lib/esm/filters/PatternFilter.js.map +1 -0
  26. package/lib/esm/filters/index.js +1 -1
  27. package/lib/esm/filters/index.js.map +1 -0
  28. package/lib/esm/index.js +3 -3
  29. package/lib/esm/index.js.map +1 -0
  30. package/lib/esm/logging.js +1 -1
  31. package/lib/esm/logging.js.map +1 -0
  32. package/lib/esm/text.js +1 -1
  33. package/lib/esm/text.js.map +1 -0
  34. package/lib/esm/time.js +1 -1
  35. package/lib/esm/time.js.map +1 -0
  36. package/lib/esm/types.js +1 -1
  37. package/lib/esm/types.js.map +1 -0
  38. package/lib/esm/utils.js +1 -1
  39. package/lib/esm/utils.js.map +1 -0
  40. package/lib/esm/web.js +1 -1
  41. package/lib/esm/web.js.map +1 -0
  42. package/lib/esm/winston/index.js +1 -1
  43. package/lib/esm/winston/index.js.map +1 -0
  44. package/lib/esm/winston/winston.js +1 -1
  45. package/lib/esm/winston/winston.js.map +1 -0
  46. package/lib/filters/LogFilter.cjs +1 -1
  47. package/lib/filters/LogFilter.js.map +1 -0
  48. package/lib/filters/PatternFilter.cjs +1 -1
  49. package/lib/filters/PatternFilter.js.map +1 -0
  50. package/lib/filters/index.cjs +1 -1
  51. package/lib/filters/index.js.map +1 -0
  52. package/lib/index.cjs +3 -3
  53. package/lib/index.js.map +1 -0
  54. package/lib/logging.cjs +1 -1
  55. package/lib/logging.js.map +1 -0
  56. package/lib/text.cjs +1 -1
  57. package/lib/text.js.map +1 -0
  58. package/lib/time.cjs +1 -1
  59. package/lib/time.js.map +1 -0
  60. package/lib/types.cjs +1 -1
  61. package/lib/types.js.map +1 -0
  62. package/lib/utils.cjs +1 -1
  63. package/lib/utils.js.map +1 -0
  64. package/lib/web.cjs +1 -1
  65. package/lib/web.js.map +1 -0
  66. package/lib/winston/index.cjs +1 -1
  67. package/lib/winston/index.js.map +1 -0
  68. package/lib/winston/winston.cjs +1 -1
  69. package/lib/winston/winston.js.map +1 -0
  70. package/package.json +1 -1
  71. package/dist/logging.esm.cjs +0 -2044
package/dist/logging.cjs CHANGED
@@ -1,2086 +1,2 @@
1
- (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('styled-string-builder'), require('typed-object-accumulator'), require('tslib')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'styled-string-builder', 'typed-object-accumulator', 'tslib'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.logging = {}, global.styledStringBuilder, global.typedObjectAccumulator, global.tslib));
5
- })(this, (function (exports, styledStringBuilder, typedObjectAccumulator, tslib) { 'use strict';
6
-
7
- /**
8
- * @description Global key used to store environment variables in browser contexts.
9
- * @summary Enables the logging environment helpers to locate serialized environment configuration on `globalThis`.
10
- * @const BrowserEnvKey
11
- * @type {string}
12
- * @memberOf module:Logging
13
- */
14
- const BrowserEnvKey = "ENV";
15
- /**
16
- * @description Delimiter used for composing nested environment variable names.
17
- * @summary Joins parent and child keys when mapping object paths to ENV strings.
18
- * @const ENV_PATH_DELIMITER
19
- * @type {string}
20
- * @memberOf module:Logging
21
- */
22
- const ENV_PATH_DELIMITER = "__";
23
- /**
24
- * @description Default prefix and suffix used for template placeholders.
25
- * @summary Provides wrapper strings applied when interpolating messages with {@link patchPlaceholders}.
26
- * @const DefaultPlaceholderWrappers
27
- * @type {string[]}
28
- * @memberOf module:Logging
29
- */
30
- const DefaultPlaceholderWrappers = ["${", "}"];
31
- /**
32
- * @description Enum for log levels.
33
- * @summary Defines different levels of logging for the application.
34
- * @enum {string}
35
- * @readonly
36
- * @memberOf module:Logging
37
- */
38
- exports.LogLevel = void 0;
39
- (function (LogLevel) {
40
- /** @description Benchmark events that capture performance metrics. */
41
- LogLevel["benchmark"] = "benchmark";
42
- /** @description Error events that indicate failures requiring attention. */
43
- LogLevel["error"] = "error";
44
- /** @description Warning events that may indicate issues. */
45
- LogLevel["warn"] = "warn";
46
- /** @description Informational events describing normal operation. */
47
- LogLevel["info"] = "info";
48
- /** @description Verbose diagnostic information for detailed tracing. */
49
- LogLevel["verbose"] = "verbose";
50
- /** @description Debug or trace details aimed at developers. */
51
- LogLevel["debug"] = "debug";
52
- /** @description trace details aimed at developers */
53
- LogLevel["trace"] = "trace";
54
- /** @description Extremely chatty or playful log entries. */
55
- LogLevel["silly"] = "silly";
56
- })(exports.LogLevel || (exports.LogLevel = {}));
57
- /**
58
- * @description Numeric values associated with log levels.
59
- * @summary Provides a numeric representation of log levels for comparison and filtering.
60
- * @typedef {Object} NumericLogLevelsShape
61
- * @property {number} benchmark - Numeric value for benchmark level (0).
62
- * @property {number} error - Numeric value for error level (2).
63
- * @property {number} info - Numeric value for info level (4).
64
- * @property {number} verbose - Numeric value for verbose level (6).
65
- * @property {number} debug - Numeric value for debug level (7).
66
- * @property {number} silly - Numeric value for silly level (9).
67
- * @memberOf module:Logging
68
- */
69
- /**
70
- * @description Numeric values associated with log levels.
71
- * @summary Provides a numeric representation of log levels for comparison and filtering.
72
- * @const NumericLogLevels
73
- * @type {NumericLogLevelsShape}
74
- * @memberOf module:Logging
75
- */
76
- const NumericLogLevels = {
77
- benchmark: 0,
78
- error: 3,
79
- warn: 6,
80
- info: 9,
81
- verbose: 12,
82
- debug: 15,
83
- trace: 18,
84
- silly: 21,
85
- };
86
- /**
87
- * @description Enum for logging output modes.
88
- * @summary Defines different output formats for log messages.
89
- * @enum {string}
90
- * @memberOf module:Logging
91
- */
92
- exports.LoggingMode = void 0;
93
- (function (LoggingMode) {
94
- /** Raw text format for human readability */
95
- LoggingMode["RAW"] = "raw";
96
- /** JSON format for machine parsing */
97
- LoggingMode["JSON"] = "json";
98
- })(exports.LoggingMode || (exports.LoggingMode = {}));
99
- /**
100
- * @description Default theme for styling log output.
101
- * @summary Defines the default color and style settings for various components of log messages.
102
- * @typedef {Theme} DefaultTheme
103
- * @property {Object} class - Styling for class names.
104
- * @property {number} class.fg - Foreground color code for class names (34).
105
- * @property {Object} id - Styling for identifiers.
106
- * @property {number} id.fg - Foreground color code for identifiers (36).
107
- * @property {Object} stack - Styling for stack traces (empty object).
108
- * @property {Object} timestamp - Styling for timestamps (empty object).
109
- * @property {Object} message - Styling for different types of messages.
110
- * @property {Object} message.error - Styling for error messages.
111
- * @property {number} message.error.fg - Foreground color code for error messages (31).
112
- * @property {Object} method - Styling for method names (empty object).
113
- * @property {Object} logLevel - Styling for different log levels.
114
- * @property {Object} logLevel.error - Styling for error level logs.
115
- * @property {number} logLevel.error.fg - Foreground color code for error level logs (31).
116
- * @property {string[]} logLevel.error.style - Style attributes for error level logs (["bold"]).
117
- * @property {Object} logLevel.info - Styling for info level logs (empty object).
118
- * @property {Object} logLevel.verbose - Styling for verbose level logs (empty object).
119
- * @property {Object} logLevel.debug - Styling for debug level logs.
120
- * @property {number} logLevel.debug.fg - Foreground color code for debug level logs (33).
121
- * @const DefaultTheme
122
- * @memberOf module:Logging
123
- */
124
- const DefaultTheme = {
125
- app: {},
126
- separator: {},
127
- class: {
128
- fg: 34,
129
- },
130
- id: {
131
- fg: 36,
132
- },
133
- stack: {},
134
- timestamp: {},
135
- message: {
136
- error: {
137
- fg: 31,
138
- },
139
- },
140
- method: {},
141
- logLevel: {
142
- benchmark: {
143
- fg: 32,
144
- style: ["bold"],
145
- },
146
- error: {
147
- fg: 31,
148
- style: ["bold"],
149
- },
150
- info: {
151
- fg: 34,
152
- style: ["bold"],
153
- },
154
- verbose: {
155
- fg: 34,
156
- style: ["bold"],
157
- },
158
- debug: {
159
- fg: 33,
160
- style: ["bold"],
161
- },
162
- trace: {
163
- fg: 33,
164
- style: ["bold"],
165
- },
166
- silly: {
167
- fg: 33,
168
- style: ["bold"],
169
- },
170
- },
171
- };
172
- /**
173
- * @description Default configuration for logging.
174
- * @summary Defines the default settings for the logging system, including verbosity, log level, styling, and timestamp format.
175
- * @const DefaultLoggingConfig
176
- * @typedef {LoggingConfig} DefaultLoggingConfig
177
- * @property {number} verbose - Verbosity level (0).
178
- * @property {LogLevel} level - Default log level (LogLevel.info).
179
- * @property {boolean} logLevel - Whether to display log level in output (true).
180
- * @property {LoggingMode} mode - Output format mode (LoggingMode.RAW).
181
- * @property {boolean} style - Whether to apply styling to log output (false).
182
- * @property {string} separator - Separator between log components (" - ").
183
- * @property {boolean} timestamp - Whether to include timestamps in log messages (true).
184
- * @property {string} timestampFormat - Format for timestamps ("HH:mm:ss.SSS").
185
- * @property {boolean} context - Whether to include context information in log messages (true).
186
- * @property {Theme} theme - The theme to use for styling log messages (DefaultTheme).
187
- * @memberOf module:Logging
188
- */
189
- const DefaultLoggingConfig = {
190
- env: "development",
191
- verbose: 0,
192
- level: exports.LogLevel.info,
193
- logLevel: true,
194
- style: false,
195
- contextSeparator: ".",
196
- separator: "-",
197
- timestamp: true,
198
- timestampFormat: "HH:mm:ss.SSS",
199
- context: true,
200
- format: exports.LoggingMode.RAW,
201
- pattern: "{level} [{timestamp}] {app} {context} {separator} {message} {stack}",
202
- theme: DefaultTheme,
203
- };
204
-
205
- /**
206
- * @description Pads the end of a string with a specified character.
207
- * @summary Extends the input string to a specified length by adding a padding character to the end.
208
- * If the input string is already longer than the specified length, it is returned unchanged.
209
- *
210
- * @param {string} str - The input string to be padded.
211
- * @param {number} length - The desired total length of the resulting string.
212
- * @param {string} [char=" "] - The character to use for padding. Defaults to a space.
213
- * @return {string} The padded string.
214
- * @throws {Error} If the padding character is not exactly one character long.
215
- *
216
- * @function padEnd
217
- *
218
- * @memberOf module:Logging
219
- */
220
- function padEnd(str, length, char = " ") {
221
- if (char.length !== 1)
222
- throw new Error("Invalid character length for padding. must be one!");
223
- return str.padEnd(length, char);
224
- }
225
- /**
226
- * @description Replaces placeholders in a string with provided values.
227
- * @summary Interpolates a string by replacing placeholders of the form ${variableName}
228
- * with corresponding values from the provided object. If a placeholder doesn't have
229
- * a corresponding value, it is left unchanged in the string.
230
- *
231
- * @param {string} input - The input string containing placeholders to be replaced.
232
- * @param {Record<string, number | string>} values - An object containing key-value pairs for replacement.
233
- * @param prefix
234
- * @param suffix
235
- * @param flags
236
- * @return {string} The interpolated string with placeholders replaced by their corresponding values.
237
- *
238
- * @function patchPlaceholders
239
- *
240
- * @mermaid
241
- * sequenceDiagram
242
- * participant Caller
243
- * participant patchString
244
- * participant String.replace
245
- * Caller->>patchString: Call with input and values
246
- * patchString->>String.replace: Call with regex and replacement function
247
- * String.replace->>patchString: Return replaced string
248
- * patchString-->>Caller: Return patched string
249
- *
250
- * @memberOf module:Logging
251
- */
252
- function patchPlaceholders(input, values, prefix = DefaultPlaceholderWrappers[0], suffix = DefaultPlaceholderWrappers[1], flags = "g") {
253
- const placeholders = Object.entries(values).reduce((acc, [key, val]) => {
254
- acc[`${prefix}${key}${suffix}`] = val;
255
- return acc;
256
- }, {});
257
- return patchString(input, placeholders, flags);
258
- }
259
- /**
260
- * @description Replaces occurrences of keys with their corresponding values in a string.
261
- * @summary Iterates through a set of key-value pairs and replaces all occurrences of each key
262
- * in the input string with its corresponding value. Supports regular expression flags for customized replacement.
263
- *
264
- * @param {string} input - The input string in which replacements will be made.
265
- * @param {Record<string, number | string>} values - An object containing key-value pairs for replacement.
266
- * @param {string} [flags="g"] - Regular expression flags to control the replacement behavior.
267
- * @return {string} The string with all specified replacements applied.
268
- *
269
- * @function patchString
270
- *
271
- * @memberOf module:Logging
272
- */
273
- function patchString(input, values, flags = "g") {
274
- Object.entries(values).forEach(([key, val]) => {
275
- const regexp = new RegExp(escapeRegExp(key), flags);
276
- input = input.replace(regexp, val);
277
- });
278
- return input;
279
- }
280
- /**
281
- * @description Converts a string to camelCase.
282
- * @summary Transforms the input string into camelCase format, where words are joined without spaces
283
- * and each word after the first starts with a capital letter.
284
- *
285
- * @param {string} text - The input string to be converted.
286
- * @return {string} The input string converted to camelCase.
287
- *
288
- * @function toCamelCase
289
- *
290
- * @memberOf module:Logging
291
- */
292
- function toCamelCase(text) {
293
- return text
294
- .replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => index === 0 ? word.toLowerCase() : word.toUpperCase())
295
- .replace(/\s+/g, "");
296
- }
297
- /**
298
- * @description Converts a string to ENVIRONMENT_VARIABLE format.
299
- * @summary Transforms the input string into uppercase with words separated by underscores,
300
- * typically used for environment variable names.
301
- *
302
- * @param {string} text - The input string to be converted.
303
- * @return {string} The input string converted to ENVIRONMENT_VARIABLE format.
304
- *
305
- * @function toENVFormat
306
- *
307
- * @memberOf module:Logging
308
- */
309
- function toENVFormat(text) {
310
- return toSnakeCase(text).toUpperCase();
311
- }
312
- /**
313
- * @description Converts a string to snake_case.
314
- * @summary Transforms the input string into lowercase with words separated by underscores.
315
- *
316
- * @param {string} text - The input string to be converted.
317
- * @return {string} The input string converted to snake_case.
318
- *
319
- * @function toSnakeCase
320
- *
321
- * @memberOf module:Logging
322
- */
323
- function toSnakeCase(text) {
324
- return text
325
- .replace(/([a-z])([A-Z])/g, "$1_$2")
326
- .replace(/[\s-]+/g, "_")
327
- .toLowerCase();
328
- }
329
- /**
330
- * @description Converts a string to kebab-case.
331
- * @summary Transforms the input string into lowercase with words separated by hyphens.
332
- *
333
- * @param {string} text - The input string to be converted.
334
- * @return {string} The input string converted to kebab-case.
335
- *
336
- * @function toKebabCase
337
- *
338
- * @memberOf module:Logging
339
- */
340
- function toKebabCase(text) {
341
- return text
342
- .replace(/([a-z])([A-Z])/g, "$1-$2")
343
- .replace(/[\s_]+/g, "-")
344
- .toLowerCase();
345
- }
346
- /**
347
- * @description Converts a string to PascalCase.
348
- * @summary Transforms the input string into PascalCase format, where words are joined without spaces
349
- * and each word starts with a capital letter.
350
- *
351
- * @param {string} text - The input string to be converted.
352
- * @return {string} The input string converted to PascalCase.
353
- *
354
- * @function toPascalCase
355
- *
356
- * @memberOf module:Logging
357
- */
358
- function toPascalCase(text) {
359
- return text
360
- .replace(/(?:^\w|[A-Z]|\b\w)/g, (word) => word.toUpperCase())
361
- .replace(/\s+/g, "");
362
- }
363
- /**
364
- * @description Escapes special characters in a string for use in a regular expression.
365
- * @summary Adds backslashes before characters that have special meaning in regular expressions,
366
- * allowing the string to be used as a literal match in a RegExp.
367
- *
368
- * @param {string} string - The string to escape for regular expression use.
369
- * @return {string} The escaped string safe for use in regular expressions.
370
- *
371
- * @function escapeRegExp
372
- *
373
- * @memberOf module:Logging
374
- */
375
- function escapeRegExp(string) {
376
- return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
377
- }
378
- /**
379
- * @summary Util function to provide string format functionality similar to C#'s string.format
380
- *
381
- * @param {string} string
382
- * @param {Array<string | number> | Record<string, any>} [args] replacements made by order of appearance (replacement0 wil replace {0} and so on)
383
- * @return {string} formatted string
384
- *
385
- * @function sf
386
- * @memberOf module:Logging
387
- */
388
- function sf(string, ...args) {
389
- if (args.length > 1) {
390
- if (!args.every((arg) => typeof arg === "string" || typeof arg === "number"))
391
- throw new Error(`Only string and number arguments are supported for multiple replacements.`);
392
- }
393
- if (args.length === 1 && typeof args[0] === "object") {
394
- const obj = args[0];
395
- return Object.entries(obj).reduce((acc, [key, val]) => {
396
- return acc.replace(new RegExp(`\\{${key}\\}`, "g"), function () {
397
- return val;
398
- });
399
- }, string);
400
- }
401
- return string.replace(/{(\d+)}/g, function (match, number) {
402
- return typeof args[number] !== "undefined"
403
- ? args[number].toString()
404
- : "undefined";
405
- });
406
- }
407
- /**
408
- * @summary Util function to provide string format functionality similar to C#'s string.format
409
- *
410
- * @see sf
411
- *
412
- * @deprecated
413
- * @function stringFormat
414
- * @memberOf module:Logging
415
- */
416
- const stringFormat = sf;
417
-
418
- /**
419
- * @description Determines if the current environment is a browser by checking the prototype chain of the global object.
420
- * @summary Checks if the code is running in a browser environment.
421
- * @return {boolean} True if the environment is a browser, false otherwise.
422
- * @function isBrowser
423
- * @memberOf module:Logging
424
- */
425
- function isBrowser() {
426
- return (Object.getPrototypeOf(Object.getPrototypeOf(globalThis)) !==
427
- Object.prototype);
428
- }
429
-
430
- /**
431
- * @description Environment accumulator that lazily reads from runtime sources.
432
- * @summary Extends {@link ObjectAccumulator} to merge configuration objects while resolving values from Node or browser environment variables on demand.
433
- * @template T
434
- * @class Environment
435
- * @example
436
- * const Config = Environment.accumulate({ logging: { level: "info" } });
437
- * console.log(Config.logging.level);
438
- * console.log(String(Config.logging.level)); // => LOGGING__LEVEL key when serialized
439
- * @mermaid
440
- * sequenceDiagram
441
- * participant Client
442
- * participant Env as Environment
443
- * participant Process as process.env
444
- * participant Browser as globalThis.ENV
445
- * Client->>Env: accumulate(partialConfig)
446
- * Env->>Env: expand(values)
447
- * Client->>Env: Config.logging.level
448
- * alt Browser runtime
449
- * Env->>Browser: lookup ENV key
450
- * Browser-->>Env: resolved value
451
- * else Node runtime
452
- * Env->>Process: lookup ENV key
453
- * Process-->>Env: resolved value
454
- * end
455
- * Env-->>Client: merged value
456
- */
457
- const EmptyValue = Symbol("EnvironmentEmpty");
458
- const ModelSymbol = Symbol("EnvironmentModel");
459
- class Environment extends typedObjectAccumulator.ObjectAccumulator {
460
- /**
461
- * @static
462
- * @protected
463
- * @description A factory function for creating Environment instances.
464
- * @summary Defines how new instances of the Environment class should be created.
465
- * @return {Environment<any>} A new instance of the Environment class.
466
- */
467
- static { this.factory = () => new Environment(); }
468
- constructor() {
469
- super();
470
- Object.defineProperty(this, ModelSymbol, {
471
- value: {},
472
- writable: true,
473
- enumerable: false,
474
- configurable: false,
475
- });
476
- }
477
- /**
478
- * @description Retrieves a value from the runtime environment.
479
- * @summary Handles browser and Node.js environments by normalizing keys and parsing values.
480
- * @param {string} k - Key to resolve from the environment.
481
- * @return {unknown} Value resolved from the environment or `undefined` when absent.
482
- */
483
- fromEnv(k) {
484
- let env;
485
- if (isBrowser()) {
486
- env =
487
- globalThis[BrowserEnvKey] || {};
488
- }
489
- else {
490
- env = globalThis.process.env;
491
- k = toENVFormat(k);
492
- }
493
- return this.parseEnvValue(env[k]);
494
- }
495
- /**
496
- * @description Converts stringified environment values into native types.
497
- * @summary Interprets booleans and numbers while leaving other types unchanged.
498
- * @param {unknown} val - Raw value retrieved from the environment.
499
- * @return {unknown} Parsed value converted to boolean, number, or left as-is.
500
- */
501
- parseEnvValue(val) {
502
- if (typeof val !== "string")
503
- return val;
504
- if (val === "true")
505
- return true;
506
- if (val === "false")
507
- return false;
508
- const result = parseFloat(val);
509
- if (!isNaN(result))
510
- return result;
511
- return val;
512
- }
513
- /**
514
- * @description Expands an object into the environment.
515
- * @summary Defines lazy properties that first consult runtime variables before falling back to seeded values.
516
- * @template V - Type of the object being expanded.
517
- * @param {V} value - Object to expose through environment getters and setters.
518
- * @return {void}
519
- */
520
- expand(value) {
521
- Object.entries(value).forEach(([k, v]) => {
522
- Environment.mergeModel(this[ModelSymbol], k, v);
523
- Object.defineProperty(this, k, {
524
- get: () => {
525
- const fromEnv = this.fromEnv(k);
526
- if (typeof fromEnv !== "undefined")
527
- return fromEnv;
528
- if (v && typeof v === "object") {
529
- return Environment.buildEnvProxy(v, [k]);
530
- }
531
- // If the model provides an empty string, mark with EmptyValue so instance proxy can return undefined without enabling key composition
532
- if (v === "") {
533
- return EmptyValue;
534
- }
535
- return v;
536
- },
537
- set: (val) => {
538
- v = val;
539
- },
540
- configurable: true,
541
- enumerable: true,
542
- });
543
- });
544
- }
545
- /**
546
- * @description Returns a proxy enforcing required environment variables.
547
- * @summary Accessing a property that resolves to `undefined` or an empty string when declared in the model throws an error.
548
- * @return {this} Proxy of the environment enforcing required variables.
549
- */
550
- orThrow() {
551
- // eslint-disable-next-line @typescript-eslint/no-this-alias
552
- const base = this;
553
- const modelRoot = base[ModelSymbol];
554
- const buildKey = (path) => path.map((segment) => toENVFormat(segment)).join(ENV_PATH_DELIMITER);
555
- const readRuntime = (key) => Environment.readRuntimeEnv(key);
556
- const parseRuntime = (raw) => typeof raw !== "undefined" ? this.parseEnvValue(raw) : undefined;
557
- const missing = (key, empty = false) => Environment.missingEnvError(key, empty);
558
- const createNestedProxy = (model, path) => {
559
- const handler = {
560
- get(_target, prop) {
561
- if (typeof prop !== "string")
562
- return undefined;
563
- const nextPath = [...path, prop];
564
- const envKey = buildKey(nextPath);
565
- const runtimeRaw = readRuntime(envKey);
566
- if (typeof runtimeRaw === "string" && runtimeRaw.length === 0)
567
- throw missing(envKey, true);
568
- const runtimeValue = parseRuntime(runtimeRaw);
569
- if (typeof runtimeValue !== "undefined") {
570
- if (typeof runtimeValue === "string" && runtimeValue.length === 0)
571
- throw missing(envKey, true);
572
- return runtimeValue;
573
- }
574
- const hasProp = model && Object.prototype.hasOwnProperty.call(model, prop);
575
- if (!hasProp)
576
- throw missing(envKey);
577
- const modelValue = model[prop];
578
- if (typeof modelValue === "undefined")
579
- return undefined;
580
- if (modelValue === "")
581
- throw missing(envKey);
582
- if (modelValue &&
583
- typeof modelValue === "object" &&
584
- !Array.isArray(modelValue)) {
585
- return createNestedProxy(modelValue, nextPath);
586
- }
587
- return modelValue;
588
- },
589
- ownKeys() {
590
- return model ? Reflect.ownKeys(model) : [];
591
- },
592
- getOwnPropertyDescriptor(_target, prop) {
593
- if (!model)
594
- return undefined;
595
- if (Object.prototype.hasOwnProperty.call(model, prop)) {
596
- return {
597
- enumerable: true,
598
- configurable: true,
599
- };
600
- }
601
- return undefined;
602
- },
603
- };
604
- return new Proxy({}, handler);
605
- };
606
- const handler = {
607
- get(target, prop, receiver) {
608
- if (typeof prop !== "string")
609
- return Reflect.get(target, prop, receiver);
610
- const hasModelProp = Object.prototype.hasOwnProperty.call(modelRoot, prop);
611
- if (!hasModelProp)
612
- return Reflect.get(target, prop, receiver);
613
- const envKey = buildKey([prop]);
614
- const runtimeRaw = readRuntime(envKey);
615
- if (typeof runtimeRaw === "string" && runtimeRaw.length === 0)
616
- throw missing(envKey, true);
617
- const runtimeValue = parseRuntime(runtimeRaw);
618
- if (typeof runtimeValue !== "undefined") {
619
- if (typeof runtimeValue === "string" && runtimeValue.length === 0)
620
- throw missing(envKey, true);
621
- return runtimeValue;
622
- }
623
- const modelValue = modelRoot[prop];
624
- if (modelValue &&
625
- typeof modelValue === "object" &&
626
- !Array.isArray(modelValue)) {
627
- return createNestedProxy(modelValue, [prop]);
628
- }
629
- if (typeof modelValue === "undefined")
630
- return Reflect.get(target, prop, receiver);
631
- const actual = Reflect.get(target, prop);
632
- if (typeof actual === "undefined" || actual === "")
633
- throw missing(envKey, actual === "");
634
- return actual;
635
- },
636
- };
637
- return new Proxy(base, handler);
638
- }
639
- /**
640
- * @protected
641
- * @static
642
- * @description Retrieves or creates the singleton instance of the Environment class.
643
- * @summary Ensures only one {@link Environment} instance is created, wrapping it in a proxy to compose ENV keys on demand.
644
- * @template E
645
- * @param {...unknown[]} args - Arguments forwarded to the factory when instantiating the singleton.
646
- * @return {E} Singleton environment instance.
647
- */
648
- static instance(...args) {
649
- if (!Environment._instance) {
650
- const base = Environment.factory(...args);
651
- const proxied = new Proxy(base, {
652
- get(target, prop, receiver) {
653
- const value = Reflect.get(target, prop, receiver);
654
- if (value === EmptyValue)
655
- return undefined;
656
- // If the property exists on the instance but resolves to undefined, return undefined (no proxy)
657
- if (typeof prop === "string" &&
658
- Object.prototype.hasOwnProperty.call(target, prop)) {
659
- if (typeof value === "undefined")
660
- return undefined;
661
- }
662
- if (typeof value !== "undefined")
663
- return value;
664
- if (typeof prop === "string") {
665
- // Avoid interfering with logging config lookups for optional fields like 'app'
666
- if (prop === "app")
667
- return undefined;
668
- return Environment.buildEnvProxy(undefined, [prop]);
669
- }
670
- return value;
671
- },
672
- });
673
- Environment._instance = proxied;
674
- }
675
- return Environment._instance;
676
- }
677
- /**
678
- * @static
679
- * @description Accumulates the given value into the environment.
680
- * @summary Adds new properties, hiding raw descriptors to avoid leaking enumeration semantics.
681
- * @template T
682
- * @template V
683
- * @param {V} value - Object to merge into the environment.
684
- * @return {Environment} Updated environment reference.
685
- */
686
- static accumulate(value) {
687
- const instance = Environment.instance();
688
- Object.keys(instance).forEach((key) => {
689
- const desc = Object.getOwnPropertyDescriptor(instance, key);
690
- if (desc && desc.configurable && desc.enumerable) {
691
- Object.defineProperty(instance, key, {
692
- ...desc,
693
- enumerable: false,
694
- });
695
- }
696
- });
697
- return instance.accumulate(value);
698
- }
699
- /**
700
- * @description Retrieves a value using a dot-path key from the accumulated environment.
701
- * @summary Delegates to the singleton instance to access stored configuration.
702
- * @param {string} key - Key to resolve from the environment store.
703
- * @return {unknown} Stored value corresponding to the provided key.
704
- */
705
- static get(key) {
706
- return Environment._instance.get(key);
707
- }
708
- /**
709
- * @description Builds a proxy that composes environment keys for nested properties.
710
- * @summary Allows chained property access to emit uppercase ENV identifiers while honoring existing runtime overrides.
711
- * @param {any} current - Seed model segment used when projecting nested structures.
712
- * @param {string[]} path - Accumulated path segments leading to the proxy.
713
- * @return {any} Proxy that resolves environment values or composes additional proxies for deeper paths.
714
- */
715
- static buildEnvProxy(current, path) {
716
- const buildKey = (p) => p.map((seg) => toENVFormat(seg)).join(ENV_PATH_DELIMITER);
717
- // Helper to read from the active environment given a composed key
718
- const readEnv = (key) => {
719
- return Environment.readRuntimeEnv(key);
720
- };
721
- const handler = {
722
- get(_target, prop) {
723
- if (prop === Symbol.toPrimitive) {
724
- return () => buildKey(path);
725
- }
726
- if (prop === "toString") {
727
- return () => buildKey(path);
728
- }
729
- if (prop === "valueOf") {
730
- return () => buildKey(path);
731
- }
732
- if (typeof prop === "symbol")
733
- return undefined;
734
- const hasProp = !!current && Object.prototype.hasOwnProperty.call(current, prop);
735
- const nextModel = hasProp ? current[prop] : undefined;
736
- const nextPath = [...path, prop];
737
- const composedKey = buildKey(nextPath);
738
- // If an ENV value exists for this path, return it directly
739
- const envValue = readEnv(composedKey);
740
- if (typeof envValue !== "undefined")
741
- return envValue;
742
- // Otherwise, if the model has an object at this path, keep drilling with a proxy
743
- const isNextObject = nextModel && typeof nextModel === "object";
744
- if (isNextObject)
745
- return Environment.buildEnvProxy(nextModel, nextPath);
746
- // If the model marks this leaf as an empty string, treat as undefined (no proxy)
747
- if (hasProp && nextModel === "")
748
- return undefined;
749
- // If the model explicitly contains the property with value undefined, treat as undefined (no proxy)
750
- if (hasProp && typeof nextModel === "undefined")
751
- return undefined;
752
- // Always return a proxy for further path composition when no ENV value;
753
- // do not surface primitive model defaults here (this API is for key composition).
754
- return Environment.buildEnvProxy(undefined, nextPath);
755
- },
756
- ownKeys() {
757
- return current ? Reflect.ownKeys(current) : [];
758
- },
759
- getOwnPropertyDescriptor(_t, p) {
760
- if (!current)
761
- return undefined;
762
- if (Object.prototype.hasOwnProperty.call(current, p)) {
763
- return { enumerable: true, configurable: true };
764
- }
765
- return undefined;
766
- },
767
- };
768
- const target = {};
769
- return new Proxy(target, handler);
770
- }
771
- /**
772
- * @static
773
- * @description Retrieves the keys of the environment, optionally converting them to ENV format.
774
- * @summary Gets all keys in the environment, with an option to format them for environment variables.
775
- * @param {boolean} [toEnv=true] - Whether to convert the keys to ENV format.
776
- * @return {string[]} An array of keys from the environment.
777
- */
778
- static keys(toEnv = true) {
779
- return Environment.instance()
780
- .keys()
781
- .map((k) => (toEnv ? toENVFormat(k) : k));
782
- }
783
- static mergeModel(model, key, value) {
784
- if (!model)
785
- return;
786
- if (value && typeof value === "object" && !Array.isArray(value)) {
787
- const existing = model[key];
788
- const target = existing && typeof existing === "object" && !Array.isArray(existing)
789
- ? existing
790
- : {};
791
- model[key] = target;
792
- Object.entries(value).forEach(([childKey, childValue]) => {
793
- Environment.mergeModel(target, childKey, childValue);
794
- });
795
- return;
796
- }
797
- model[key] = value;
798
- }
799
- static readRuntimeEnv(key) {
800
- if (isBrowser()) {
801
- const env = globalThis[BrowserEnvKey];
802
- return env ? env[key] : undefined;
803
- }
804
- return globalThis?.process?.env?.[key];
805
- }
806
- static missingEnvError(key, empty) {
807
- const suffix = empty ? "an empty string" : "undefined";
808
- return new Error(`Environment variable ${key} is required but was ${suffix}.`);
809
- }
810
- }
811
- /**
812
- * @description Singleton environment instance seeded with default logging configuration.
813
- * @summary Combines {@link DefaultLoggingConfig} with runtime environment variables to provide consistent logging defaults across platforms.
814
- * @const LoggedEnvironment
815
- * @memberOf module:Logging
816
- */
817
- const LoggedEnvironment = Environment.accumulate(Object.assign({}, DefaultLoggingConfig, {
818
- env: (isBrowser() && globalThis[BrowserEnvKey]
819
- ? globalThis[BrowserEnvKey]["NODE_ENV"]
820
- : globalThis.process.env["NODE_ENV"]) || "development",
821
- }));
822
-
823
- /**
824
- * @description A minimal logger implementation.
825
- * @summary MiniLogger is a lightweight logging class that implements the Logger interface.
826
- * It provides basic logging functionality with support for different log levels, verbosity,
827
- * context-aware logging, and customizable formatting.
828
- * @param {string} context - The context (typically class name) this logger is associated with
829
- * @param {Partial<LoggingConfig>} conf - Optional configuration to override global settings
830
- * @class MiniLogger
831
- * @example
832
- * // Create a new logger for a class
833
- * const logger = new MiniLogger('MyClass');
834
- *
835
- * // Log messages at different levels
836
- * logger.info('This is an info message');
837
- * logger.debug('This is a debug message');
838
- * logger.error('Something went wrong');
839
- *
840
- * // Create a child logger for a specific method
841
- * const methodLogger = logger.for('myMethod');
842
- * methodLogger.verbose('Detailed information', 2);
843
- *
844
- * // Log with custom configuration
845
- * logger.for('specialMethod', { style: true }).info('Styled message');
846
- */
847
- class MiniLogger {
848
- constructor(context, conf) {
849
- this.context = context;
850
- this.conf = conf;
851
- }
852
- config(key) {
853
- if (this.conf && key in this.conf)
854
- return this.conf[key];
855
- return Logging.getConfig()[key];
856
- }
857
- /**
858
- * @description Creates a child logger for a specific method or context
859
- * @summary Returns a new logger instance with the current context extended by the specified method name
860
- * @param {string | Function} method - The method name or function to create a logger for
861
- * @param {Partial<LoggingConfig>} config - Optional configuration to override settings
862
- * @param {...any[]} args - Additional arguments to pass to the logger factory
863
- * @return {Logger} A new logger instance for the specified method
864
- */
865
- for(method, config,
866
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
867
- ...args) {
868
- if (!config && typeof method === "object") {
869
- config = method;
870
- method = undefined;
871
- }
872
- else {
873
- method = method
874
- ? typeof method === "string"
875
- ? method
876
- : method.name
877
- : undefined;
878
- }
879
- return new Proxy(this, {
880
- get: (target, p, receiver) => {
881
- const result = Reflect.get(target, p, receiver);
882
- if (p === "config") {
883
- return new Proxy(this.config, {
884
- get: (target, p) => {
885
- if (config && p in config)
886
- return config[p];
887
- return Reflect.get(target, p, receiver);
888
- },
889
- });
890
- }
891
- if (p === "context" && method) {
892
- return [result, method].join(".");
893
- }
894
- return result;
895
- },
896
- });
897
- }
898
- /**
899
- * @description Creates a formatted log string
900
- * @summary Generates a log string with timestamp, colored log level, context, and message
901
- * @param {LogLevel} level - The log level for this message
902
- * @param {StringLike | Error} message - The message to log or an Error object
903
- * @param {string} [error] - Optional error to extract stack trace to include in the log
904
- * @return {string} A formatted log string with all components
905
- */
906
- createLog(level, message, error) {
907
- const log = {};
908
- const style = this.config("style");
909
- const separator = this.config("separator");
910
- const app = this.config("app");
911
- if (app)
912
- log.app = style
913
- ? Logging.theme(app, "app", level)
914
- : app;
915
- if (separator)
916
- log.separator = style
917
- ? Logging.theme(separator, "separator", level)
918
- : separator;
919
- if (this.config("timestamp")) {
920
- const date = new Date().toISOString();
921
- const timestamp = style ? Logging.theme(date, "timestamp", level) : date;
922
- log.timestamp = timestamp;
923
- }
924
- if (this.config("logLevel")) {
925
- const lvl = style
926
- ? Logging.theme(level, "logLevel", level)
927
- : level;
928
- log.level = lvl.toUpperCase();
929
- }
930
- if (this.config("context")) {
931
- const context = style
932
- ? Logging.theme(this.context, "class", level)
933
- : this.context;
934
- log.context = context;
935
- }
936
- if (this.config("correlationId")) {
937
- {
938
- const id = style
939
- ? Logging.theme(this.config("correlationId").toString(), "id", level)
940
- : this.config("correlationId").toString();
941
- log.correlationId = id;
942
- }
943
- }
944
- const msg = style
945
- ? Logging.theme(typeof message === "string" ? message : message.message, "message", level)
946
- : typeof message === "string"
947
- ? message
948
- : message.message;
949
- log.message = msg;
950
- if (error || message instanceof Error) {
951
- const stack = style
952
- ? Logging.theme((error?.stack || message.stack), "stack", level)
953
- : error?.stack || "";
954
- log.stack = ` | ${(error || message).message} - Stack trace:\n${stack}`;
955
- }
956
- switch (this.config("format")) {
957
- case "json":
958
- return JSON.stringify(log);
959
- case "raw":
960
- return this.config("pattern")
961
- .split(" ")
962
- .map((s) => {
963
- if (!s.match(/\{.*?}/g))
964
- return s;
965
- const formattedS = sf(s, log);
966
- if (formattedS !== s)
967
- return formattedS;
968
- return undefined;
969
- })
970
- .filter((s) => s)
971
- .join(" ");
972
- default:
973
- throw new Error(`Unsupported logging format: ${this.config("format")}`);
974
- }
975
- }
976
- /**
977
- * @description Logs a message with the specified log level
978
- * @summary Checks if the message should be logged based on the current log level,
979
- * then uses the appropriate console method to output the formatted log
980
- * @param {LogLevel} level - The log level of the message
981
- * @param {StringLike | Error} msg - The message to be logged or an Error object
982
- * @param {string} [error] - Optional stack trace to include in the log
983
- * @return {void}
984
- */
985
- log(level, msg, error) {
986
- const confLvl = this.config("level");
987
- if (NumericLogLevels[confLvl] < NumericLogLevels[level])
988
- return;
989
- let method;
990
- switch (level) {
991
- case exports.LogLevel.benchmark:
992
- method = console.log;
993
- break;
994
- case exports.LogLevel.info:
995
- method = console.log;
996
- break;
997
- case exports.LogLevel.verbose:
998
- case exports.LogLevel.debug:
999
- method = console.debug;
1000
- break;
1001
- case exports.LogLevel.error:
1002
- method = console.error;
1003
- break;
1004
- case exports.LogLevel.trace:
1005
- method = console.trace;
1006
- break;
1007
- case exports.LogLevel.silly:
1008
- method = console.trace;
1009
- break;
1010
- default:
1011
- throw new Error("Invalid log level");
1012
- }
1013
- method(this.createLog(level, msg, error));
1014
- }
1015
- /**
1016
- * @description Logs a message at the benchmark level
1017
- * @summary Logs a message at the benchmark level if the current verbosity setting allows it
1018
- * @param {StringLike} msg - The message to be logged
1019
- * @return {void}
1020
- */
1021
- benchmark(msg) {
1022
- this.log(exports.LogLevel.benchmark, msg);
1023
- }
1024
- /**
1025
- * @description Logs a message at the silly level
1026
- * @summary Logs a message at the silly level if the current verbosity setting allows it
1027
- * @param {StringLike} msg - The message to be logged
1028
- * @param {number} [verbosity=0] - The verbosity level of the message
1029
- * @return {void}
1030
- */
1031
- silly(msg, verbosity = 0) {
1032
- if (this.config("verbose") >= verbosity)
1033
- this.log(exports.LogLevel.verbose, msg);
1034
- }
1035
- /**
1036
- * @description Logs a message at the verbose level
1037
- * @summary Logs a message at the verbose level if the current verbosity setting allows it
1038
- * @param {StringLike} msg - The message to be logged
1039
- * @param {number} [verbosity=0] - The verbosity level of the message
1040
- * @return {void}
1041
- */
1042
- verbose(msg, verbosity = 0) {
1043
- if (this.config("verbose") >= verbosity)
1044
- this.log(exports.LogLevel.verbose, msg);
1045
- }
1046
- /**
1047
- * @description Logs a message at the info level
1048
- * @summary Logs a message at the info level for general application information
1049
- * @param {StringLike} msg - The message to be logged
1050
- * @return {void}
1051
- */
1052
- info(msg) {
1053
- this.log(exports.LogLevel.info, msg);
1054
- }
1055
- /**
1056
- * @description Logs a message at the debug level
1057
- * @summary Logs a message at the debug level for detailed troubleshooting information
1058
- * @param {StringLike} msg - The message to be logged
1059
- * @return {void}
1060
- */
1061
- debug(msg) {
1062
- this.log(exports.LogLevel.debug, msg);
1063
- }
1064
- /**
1065
- * @description Logs a message at the error level
1066
- * @summary Logs a message at the error level for errors and exceptions
1067
- * @param {StringLike | Error} msg - The message to be logged or an Error object
1068
- * @param e
1069
- * @return {void}
1070
- */
1071
- error(msg, e) {
1072
- this.log(exports.LogLevel.error, msg, e);
1073
- }
1074
- /**
1075
- * @description Logs a message at the error level
1076
- * @summary Logs a message at the error level for errors and exceptions
1077
- * @param {StringLike} msg - The message to be logged or an Error object
1078
- * @return {void}
1079
- */
1080
- warn(msg) {
1081
- this.log(exports.LogLevel.warn, msg);
1082
- }
1083
- /**
1084
- * @description Logs a message at the error level
1085
- * @summary Logs a message at the error level for errors and exceptions
1086
- * @param {StringLike} msg - The message to be logged or an Error object
1087
- * @return {void}
1088
- */
1089
- trace(msg) {
1090
- this.log(exports.LogLevel.trace, msg);
1091
- }
1092
- /**
1093
- * @description Updates the logger configuration
1094
- * @summary Merges the provided configuration with the existing configuration
1095
- * @param {Partial<LoggingConfig>} config - The configuration options to apply
1096
- * @return {void}
1097
- */
1098
- setConfig(config) {
1099
- this.conf = { ...(this.conf || {}), ...config };
1100
- }
1101
- }
1102
- /**
1103
- * @description A static class for managing logging operations
1104
- * @summary The Logging class provides a centralized logging mechanism with support for
1105
- * different log levels, verbosity, and styling. It uses a singleton pattern to maintain a global
1106
- * logger instance and allows creating specific loggers for different classes and methods.
1107
- * @class Logging
1108
- * @example
1109
- * // Set global configuration
1110
- * Logging.setConfig({ level: LogLevel.debug, style: true });
1111
- *
1112
- * // Get a logger for a specific class
1113
- * const logger = Logging.for('MyClass');
1114
- *
1115
- * // Log messages at different levels
1116
- * logger.info('Application started');
1117
- * logger.debug('Processing data...');
1118
- *
1119
- * // Log with context
1120
- * const methodLogger = Logging.for('MyClass.myMethod');
1121
- * methodLogger.verbose('Detailed operation information', 1);
1122
- *
1123
- * // Log errors
1124
- * try {
1125
- * // some operation
1126
- * } catch (error) {
1127
- * logger.error(error);
1128
- * }
1129
- * @mermaid
1130
- * classDiagram
1131
- * class Logger {
1132
- * <<interface>>
1133
- * +for(method, config, ...args)
1134
- * +silly(msg, verbosity)
1135
- * +verbose(msg, verbosity)
1136
- * +info(msg)
1137
- * +debug(msg)
1138
- * +error(msg)
1139
- * +setConfig(config)
1140
- * }
1141
- *
1142
- * class Logging {
1143
- * -global: Logger
1144
- * -_factory: LoggerFactory
1145
- * -_config: LoggingConfig
1146
- * +setFactory(factory)
1147
- * +setConfig(config)
1148
- * +getConfig()
1149
- * +get()
1150
- * +verbose(msg, verbosity)
1151
- * +info(msg)
1152
- * +debug(msg)
1153
- * +silly(msg)
1154
- * +error(msg)
1155
- * +for(object, config, ...args)
1156
- * +because(reason, id)
1157
- * +theme(text, type, loggerLevel, template)
1158
- * }
1159
- *
1160
- * class MiniLogger {
1161
- * +constructor(context, conf?)
1162
- * }
1163
- *
1164
- * Logging ..> Logger : creates
1165
- * Logging ..> MiniLogger : creates by default
1166
- */
1167
- class Logging {
1168
- /**
1169
- * @description Factory function for creating logger instances
1170
- * @summary A function that creates new Logger instances. By default, it creates a MiniLogger.
1171
- */
1172
- static { this._factory = (object, config) => {
1173
- return new MiniLogger(object, config);
1174
- }; }
1175
- static { this._config = LoggedEnvironment; }
1176
- constructor() { }
1177
- /**
1178
- * @description Sets the factory function for creating logger instances
1179
- * @summary Allows customizing how logger instances are created
1180
- * @param {LoggerFactory} factory - The factory function to use for creating loggers
1181
- * @return {void}
1182
- */
1183
- static setFactory(factory) {
1184
- Logging._factory = factory;
1185
- }
1186
- /**
1187
- * @description Updates the global logging configuration
1188
- * @summary Allows updating the global logging configuration with new settings
1189
- * @param {Partial<LoggingConfig>} config - The configuration options to apply
1190
- * @return {void}
1191
- */
1192
- static setConfig(config) {
1193
- Object.entries(config).forEach(([k, v]) => {
1194
- this._config[k] = v;
1195
- });
1196
- }
1197
- /**
1198
- * @description Gets a copy of the current global logging configuration
1199
- * @summary Returns a copy of the current global logging configuration
1200
- * @return {LoggingConfig} A copy of the current configuration
1201
- */
1202
- static getConfig() {
1203
- return this._config;
1204
- }
1205
- /**
1206
- * @description Retrieves or creates the global logger instance.
1207
- * @summary Returns the existing global logger or creates a new one if it doesn't exist.
1208
- *
1209
- * @return The global VerbosityLogger instance.
1210
- */
1211
- static get() {
1212
- this.global = this.global ? this.global : this._factory("Logging");
1213
- return this.global;
1214
- }
1215
- /**
1216
- * @description Logs a verbose message.
1217
- * @summary Delegates the verbose logging to the global logger instance.
1218
- *
1219
- * @param msg - The message to be logged.
1220
- * @param verbosity - The verbosity level of the message (default: 0).
1221
- */
1222
- static verbose(msg, verbosity = 0) {
1223
- return this.get().verbose(msg, verbosity);
1224
- }
1225
- /**
1226
- * @description Logs an info message.
1227
- * @summary Delegates the info logging to the global logger instance.
1228
- *
1229
- * @param msg - The message to be logged.
1230
- */
1231
- static info(msg) {
1232
- return this.get().info(msg);
1233
- }
1234
- /**
1235
- * @description Logs an info message.
1236
- * @summary Delegates the info logging to the global logger instance.
1237
- *
1238
- * @param msg - The message to be logged.
1239
- */
1240
- static trace(msg) {
1241
- return this.get().trace(msg);
1242
- }
1243
- /**
1244
- * @description Logs a debug message.
1245
- * @summary Delegates the debug logging to the global logger instance.
1246
- *
1247
- * @param msg - The message to be logged.
1248
- */
1249
- static debug(msg) {
1250
- return this.get().debug(msg);
1251
- }
1252
- /**
1253
- * @description Logs a benchmark message.
1254
- * @summary Delegates the benchmark logging to the global logger instance.
1255
- *
1256
- * @param msg - The message to be logged.
1257
- */
1258
- static benchmark(msg) {
1259
- return this.get().benchmark(msg);
1260
- }
1261
- /**
1262
- * @description Logs a silly message.
1263
- * @summary Delegates the debug logging to the global logger instance.
1264
- *
1265
- * @param msg - The message to be logged.
1266
- */
1267
- static silly(msg) {
1268
- return this.get().silly(msg);
1269
- }
1270
- /**
1271
- * @description Logs a silly message.
1272
- * @summary Delegates the debug logging to the global logger instance.
1273
- *
1274
- * @param msg - The message to be logged.
1275
- */
1276
- static warn(msg) {
1277
- return this.get().warn(msg);
1278
- }
1279
- /**
1280
- * @description Logs an error message.
1281
- * @summary Delegates the error logging to the global logger instance.
1282
- *
1283
- * @param msg - The message to be logged.
1284
- * @param e
1285
- */
1286
- static error(msg, e) {
1287
- return this.get().error(msg, e);
1288
- }
1289
- /**
1290
- * @description Creates a logger for a specific object or context
1291
- * @summary Creates a new logger instance for the given object or context using the factory function
1292
- * @param {LoggingContext} object - The object, class, or context to create a logger for
1293
- * @param {Partial<LoggingConfig>} [config] - Optional configuration to override global settings
1294
- * @param {...any} args - Additional arguments to pass to the logger factory
1295
- * @return {Logger} A new logger instance for the specified object or context
1296
- */
1297
- static for(object, config, ...args) {
1298
- object =
1299
- typeof object === "string"
1300
- ? object
1301
- : object.constructor
1302
- ? object.constructor.name
1303
- : object.name;
1304
- return this._factory(object, config, ...args);
1305
- }
1306
- /**
1307
- * @description Creates a logger for a specific reason or correlation context
1308
- * @summary Utility to quickly create a logger labeled with a free-form reason and optional identifier
1309
- * so that ad-hoc operations can be traced without tying the logger to a class or method name.
1310
- * @param {string} reason - A textual reason or context label for this logger instance
1311
- * @param {string} [id] - Optional identifier to help correlate related log entries
1312
- * @return {Logger} A new logger instance labeled with the provided reason and id
1313
- */
1314
- static because(reason, id) {
1315
- return this._factory(reason, this._config, id);
1316
- }
1317
- /**
1318
- * @description Applies theme styling to text
1319
- * @summary Applies styling (colors, formatting) to text based on the theme configuration
1320
- * @param {string} text - The text to style
1321
- * @param {string} type - The type of element to style (e.g., "class", "message", "logLevel")
1322
- * @param {LogLevel} loggerLevel - The log level to use for styling
1323
- * @param {Theme} [template=DefaultTheme] - The theme to use for styling
1324
- * @return {string} The styled text
1325
- * @mermaid
1326
- * sequenceDiagram
1327
- * participant Caller
1328
- * participant Theme as Logging.theme
1329
- * participant Apply as apply function
1330
- * participant Style as styled-string-builder
1331
- *
1332
- * Caller->>Theme: theme(text, type, loggerLevel)
1333
- * Theme->>Theme: Check if styling is enabled
1334
- * alt styling disabled
1335
- * Theme-->>Caller: return original text
1336
- * else styling enabled
1337
- * Theme->>Theme: Get theme for type
1338
- * alt theme not found
1339
- * Theme-->>Caller: return original text
1340
- * else theme found
1341
- * Theme->>Theme: Determine actual theme based on log level
1342
- * Theme->>Apply: Apply each style property
1343
- * Apply->>Style: Apply colors and formatting
1344
- * Style-->>Apply: Return styled text
1345
- * Apply-->>Theme: Return styled text
1346
- * Theme-->>Caller: Return final styled text
1347
- * end
1348
- * end
1349
- */
1350
- static theme(text, type, loggerLevel, template = DefaultTheme) {
1351
- if (!this._config.style)
1352
- return text;
1353
- function apply(txt, option, value) {
1354
- try {
1355
- const t = txt;
1356
- let c = styledStringBuilder.style(t);
1357
- function applyColor(val, isBg = false) {
1358
- let f = isBg ? c.background : c.foreground;
1359
- if (!Array.isArray(val)) {
1360
- return f.call(c, value);
1361
- }
1362
- switch (val.length) {
1363
- case 1:
1364
- f = isBg ? c.bgColor256 : c.color256;
1365
- return f(val[0]);
1366
- case 3:
1367
- f = isBg ? c.bgRgb : c.rgb;
1368
- return c.rgb(val[0], val[1], val[2]);
1369
- default:
1370
- console.error(`Not a valid color option: ${option}`);
1371
- return styledStringBuilder.style(t);
1372
- }
1373
- }
1374
- function applyStyle(v) {
1375
- if (typeof v === "number") {
1376
- c = c.style(v);
1377
- }
1378
- else {
1379
- c = c[v];
1380
- }
1381
- }
1382
- switch (option) {
1383
- case "bg":
1384
- case "fg":
1385
- return applyColor(value).text;
1386
- case "style":
1387
- if (Array.isArray(value)) {
1388
- value.forEach(applyStyle);
1389
- }
1390
- else {
1391
- applyStyle(value);
1392
- }
1393
- return c.text;
1394
- default:
1395
- console.error(`Not a valid theme option: ${option}`);
1396
- return t;
1397
- }
1398
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1399
- }
1400
- catch (e) {
1401
- console.error(`Error applying style: ${option} with value ${value}`);
1402
- return txt;
1403
- }
1404
- }
1405
- const individualTheme = template[type];
1406
- if (!individualTheme || !Object.keys(individualTheme).length) {
1407
- return text;
1408
- }
1409
- let actualTheme = individualTheme;
1410
- const logLevels = Object.assign({}, exports.LogLevel);
1411
- if (Object.keys(individualTheme)[0] in logLevels)
1412
- actualTheme =
1413
- individualTheme[loggerLevel] || {};
1414
- return Object.keys(actualTheme).reduce((acc, key) => {
1415
- const val = actualTheme[key];
1416
- if (val)
1417
- return apply(acc, key, val);
1418
- return acc;
1419
- }, text);
1420
- }
1421
- }
1422
-
1423
- /**
1424
- * @description Base class that provides a ready-to-use logger instance.
1425
- * @summary Supplies inheriting classes with a lazily created, context-aware {@link Logger} via the protected `log` getter, promoting consistent structured logging without manual wiring.
1426
- * @class LoggedClass
1427
- * @example
1428
- * class UserService extends LoggedClass {
1429
- * create(user: User) {
1430
- * this.log.info(`Creating user ${user.id}`);
1431
- * }
1432
- * }
1433
- *
1434
- * const svc = new UserService();
1435
- * svc.create({ id: "42" });
1436
- * @mermaid
1437
- * sequenceDiagram
1438
- * participant Client
1439
- * participant Instance as Subclass Instance
1440
- * participant Getter as LoggedClass.log
1441
- * participant Logging as Logging
1442
- * participant Logger as Logger
1443
- *
1444
- * Client->>Instance: call someMethod()
1445
- * Instance->>Getter: access this.log
1446
- * Getter->>Logging: Logging.for(this)
1447
- * Logging-->>Getter: return Logger
1448
- * Getter-->>Instance: return Logger
1449
- * Instance->>Logger: info/debug/error(...)
1450
- */
1451
- class LoggedClass {
1452
- /**
1453
- * @description Lazily provides a context-aware logger for the current instance.
1454
- * @summary Calls {@link Logging.for} with the subclass instance to obtain a logger whose context matches the subclass name.
1455
- * @return {Logger} Logger bound to the subclass context.
1456
- */
1457
- get log() {
1458
- if (!this._log)
1459
- this._log = Logging.for(this);
1460
- return this._log;
1461
- }
1462
- constructor() { }
1463
- }
1464
-
1465
- /**
1466
- * @description Base class for message filters that plug into the logging pipeline.
1467
- * @summary Extends {@link LoggedClass} to supply a scoped logger and defines the contract required by {@link LoggingFilter} implementers that transform or drop log messages before emission.
1468
- * @class LogFilter
1469
- * @example
1470
- * class RedactSecretsFilter extends LogFilter {
1471
- * filter(config: LoggingConfig, message: string): string {
1472
- * return message.replace(/secret/gi, "***");
1473
- * }
1474
- * }
1475
- *
1476
- * const filter = new RedactSecretsFilter();
1477
- * filter.filter({ ...DefaultLoggingConfig, verbose: 0 }, "secret token");
1478
- * @mermaid
1479
- * sequenceDiagram
1480
- * participant Logger
1481
- * participant Filter as LogFilter
1482
- * participant Impl as ConcreteFilter
1483
- * participant Output
1484
- * Logger->>Filter: filter(config, message, context)
1485
- * Filter->>Impl: delegate to subclass implementation
1486
- * Impl-->>Filter: transformed message
1487
- * Filter-->>Output: return filtered message
1488
- */
1489
- class LogFilter extends LoggedClass {
1490
- /**
1491
- * @description Scoped logger that excludes other filters from the chain.
1492
- * @summary Returns a child logger dedicated to the filter, preventing recursive filter invocation when emitting diagnostic messages.
1493
- * @return {Logger} Context-aware logger for the filter instance.
1494
- */
1495
- get log() {
1496
- return super.log.for(this, { filters: [] });
1497
- }
1498
- }
1499
-
1500
- function safeNow() {
1501
- // Prefer performance.now when available
1502
- if (typeof globalThis !== "undefined" &&
1503
- typeof globalThis.performance?.now === "function") {
1504
- return () => globalThis.performance.now();
1505
- }
1506
- // Node: use process.hrtime.bigint for higher precision if available
1507
- if (typeof process !== "undefined" &&
1508
- typeof process.hrtime?.bigint === "function") {
1509
- return () => {
1510
- const ns = process.hrtime.bigint(); // nanoseconds
1511
- return Number(ns) / 1_000_000; // to ms
1512
- };
1513
- }
1514
- // Fallback
1515
- return () => Date.now();
1516
- }
1517
- /**
1518
- * @description High-resolution clock accessor returning milliseconds.
1519
- * @summary Chooses the most precise timer available in the current runtime, preferring `performance.now` or `process.hrtime.bigint`.
1520
- * @return {number} Milliseconds elapsed according to the best available clock.
1521
- */
1522
- const now = safeNow();
1523
- /**
1524
- * @description High-resolution stopwatch with pause, resume, and lap tracking.
1525
- * @summary Tracks elapsed time using the highest precision timer available, supports pausing, resuming, and recording labeled laps for diagnostics and benchmarking.
1526
- * @param {boolean} [autoStart=false] - When true, the stopwatch starts immediately upon construction.
1527
- * @class StopWatch
1528
- * @example
1529
- * const sw = new StopWatch(true);
1530
- * // ... work ...
1531
- * const lap = sw.lap("phase 1");
1532
- * sw.pause();
1533
- * console.log(`Elapsed: ${lap.totalMs}ms`);
1534
- * @mermaid
1535
- * sequenceDiagram
1536
- * participant Client
1537
- * participant StopWatch
1538
- * participant Clock as now()
1539
- * Client->>StopWatch: start()
1540
- * StopWatch->>Clock: now()
1541
- * Clock-->>StopWatch: timestamp
1542
- * Client->>StopWatch: lap()
1543
- * StopWatch->>Clock: now()
1544
- * Clock-->>StopWatch: timestamp
1545
- * StopWatch-->>Client: Lap
1546
- * Client->>StopWatch: pause()
1547
- * StopWatch->>Clock: now()
1548
- * Clock-->>StopWatch: timestamp
1549
- */
1550
- class StopWatch {
1551
- constructor(autoStart = false) {
1552
- this._startMs = null;
1553
- this._elapsedMs = 0;
1554
- this._running = false;
1555
- this._laps = [];
1556
- this._lastLapTotalMs = 0;
1557
- if (autoStart)
1558
- this.start();
1559
- }
1560
- /**
1561
- * @description Indicates whether the stopwatch is actively running.
1562
- * @summary Returns `true` when timing is in progress and `false` when paused or stopped.
1563
- * @return {boolean} Current running state.
1564
- */
1565
- get running() {
1566
- return this._running;
1567
- }
1568
- /**
1569
- * @description Elapsed time captured by the stopwatch.
1570
- * @summary Computes the total elapsed time in milliseconds, including the current session if running.
1571
- * @return {number} Milliseconds elapsed since the stopwatch started.
1572
- */
1573
- get elapsedMs() {
1574
- if (!this._running || this._startMs == null)
1575
- return this._elapsedMs;
1576
- return this._elapsedMs + (now() - this._startMs);
1577
- }
1578
- /**
1579
- * @description Starts timing if the stopwatch is not already running.
1580
- * @summary Records the current timestamp and transitions the stopwatch into the running state.
1581
- * @return {this} Fluent reference to the stopwatch.
1582
- */
1583
- start() {
1584
- if (!this._running) {
1585
- this._running = true;
1586
- this._startMs = now();
1587
- }
1588
- return this;
1589
- }
1590
- /**
1591
- * @description Pauses timing and accumulates elapsed milliseconds.
1592
- * @summary Captures the partial duration, updates the accumulator, and keeps the stopwatch ready to resume later.
1593
- * @return {this} Fluent reference to the stopwatch.
1594
- */
1595
- pause() {
1596
- if (this._running && this._startMs != null) {
1597
- this._elapsedMs += now() - this._startMs;
1598
- this._startMs = null;
1599
- this._running = false;
1600
- }
1601
- return this;
1602
- }
1603
- /**
1604
- * @description Resumes timing after a pause.
1605
- * @summary Captures a fresh start timestamp while keeping previous elapsed time intact.
1606
- * @return {this} Fluent reference to the stopwatch.
1607
- */
1608
- resume() {
1609
- if (!this._running) {
1610
- this._running = true;
1611
- this._startMs = now();
1612
- }
1613
- return this;
1614
- }
1615
- /**
1616
- * @description Stops timing and returns the total elapsed milliseconds.
1617
- * @summary Invokes {@link StopWatch.pause} to consolidate elapsed time, leaving the stopwatch in a non-running state.
1618
- * @return {number} Milliseconds accumulated across all runs.
1619
- */
1620
- stop() {
1621
- this.pause();
1622
- return this._elapsedMs;
1623
- }
1624
- /**
1625
- * @description Resets the stopwatch state while optionally continuing to run.
1626
- * @summary Clears elapsed time and lap history, preserving whether the stopwatch should continue ticking.
1627
- * @return {this} Fluent reference to the stopwatch.
1628
- */
1629
- reset() {
1630
- const wasRunning = this._running;
1631
- this._startMs = wasRunning ? now() : null;
1632
- this._elapsedMs = 0;
1633
- this._laps = [];
1634
- this._lastLapTotalMs = 0;
1635
- return this;
1636
- }
1637
- /**
1638
- * @description Records a lap split since the stopwatch started or since the previous lap.
1639
- * @summary Stores the lap metadata, updates cumulative tracking, and returns the newly created {@link Lap}.
1640
- * @param {string} [label] - Optional label describing the lap.
1641
- * @return {Lap} Lap snapshot capturing incremental and cumulative timings.
1642
- */
1643
- lap(label) {
1644
- const total = this.elapsedMs;
1645
- const ms = total - this._lastLapTotalMs;
1646
- const lap = {
1647
- index: this._laps.length,
1648
- label,
1649
- ms,
1650
- totalMs: total,
1651
- };
1652
- this._laps.push(lap);
1653
- this._lastLapTotalMs = total;
1654
- return lap;
1655
- }
1656
- /**
1657
- * @description Retrieves the recorded lap history.
1658
- * @summary Returns the internal lap array as a read-only view to prevent external mutation.
1659
- * @return {Lap[]} Laps captured by the stopwatch.
1660
- */
1661
- get laps() {
1662
- return this._laps;
1663
- }
1664
- /**
1665
- * @description Formats the elapsed time in a human-readable representation.
1666
- * @summary Uses {@link formatMs} to produce an `hh:mm:ss.mmm` string for display and logging.
1667
- * @return {string} Elapsed time formatted for presentation.
1668
- */
1669
- toString() {
1670
- return formatMs(this.elapsedMs);
1671
- }
1672
- /**
1673
- * @description Serializes the stopwatch state.
1674
- * @summary Provides a JSON-friendly snapshot including running state, elapsed time, and lap details.
1675
- * @return {{running: boolean, elapsedMs: number, laps: Lap[]}} Serializable stopwatch representation.
1676
- */
1677
- toJSON() {
1678
- return {
1679
- running: this._running,
1680
- elapsedMs: this.elapsedMs,
1681
- laps: this._laps.slice(),
1682
- };
1683
- }
1684
- }
1685
- /**
1686
- * @description Formats milliseconds into `hh:mm:ss.mmm`.
1687
- * @summary Breaks the duration into hours, minutes, seconds, and milliseconds, returning a zero-padded string.
1688
- * @param {number} ms - Milliseconds to format.
1689
- * @return {string} Formatted duration string.
1690
- * @function formatMs
1691
- * @memberOf module:Logging
1692
- * @mermaid
1693
- * sequenceDiagram
1694
- * participant Caller
1695
- * participant Formatter as formatMs
1696
- * Caller->>Formatter: formatMs(ms)
1697
- * Formatter->>Formatter: derive hours/minutes/seconds
1698
- * Formatter->>Formatter: pad segments
1699
- * Formatter-->>Caller: hh:mm:ss.mmm
1700
- */
1701
- function formatMs(ms) {
1702
- const sign = ms < 0 ? "-" : "";
1703
- const abs = Math.abs(ms);
1704
- const hours = Math.floor(abs / 3_600_000);
1705
- const minutes = Math.floor((abs % 3_600_000) / 60_000);
1706
- const seconds = Math.floor((abs % 60_000) / 1000);
1707
- const millis = Math.floor(abs % 1000);
1708
- const pad = (n, w) => n.toString().padStart(w, "0");
1709
- return `${sign}${pad(hours, 2)}:${pad(minutes, 2)}:${pad(seconds, 2)}.${pad(millis, 3)}`;
1710
- }
1711
-
1712
- /**
1713
- * @description Method decorator for logging function calls.
1714
- * @summary Wraps class methods to automatically log entry, exit, timing, and optional custom messages at a configurable {@link LogLevel}.
1715
- * @param {LogLevel} level - Log level applied to the generated log statements (defaults to `LogLevel.info`).
1716
- * @param {number} [verbosity=0] - Verbosity threshold required for the entry log to appear.
1717
- * @param {ArgFormatFunction} [entryMessage] - Formatter invoked with the original method arguments to describe the invocation.
1718
- * @param {ReturnFormatFunction} [exitMessage] - Optional formatter that describes the outcome or failure of the call.
1719
- * @return {function(any, any, PropertyDescriptor): void} Method decorator proxy that injects logging behavior.
1720
- * @function log
1721
- * @mermaid
1722
- * sequenceDiagram
1723
- * participant Client
1724
- * participant Decorator as log decorator
1725
- * participant Method as Original Method
1726
- * participant Logger as Logging instance
1727
- *
1728
- * Client->>Decorator: call decorated method
1729
- * Decorator->>Logger: log method call
1730
- * Decorator->>Method: call original method
1731
- * alt result is Promise
1732
- * Method-->>Decorator: return Promise
1733
- * Decorator->>Decorator: attach then handler
1734
- * Note over Decorator: Promise resolves
1735
- * Decorator->>Logger: log benchmark (if enabled)
1736
- * Decorator-->>Client: return result
1737
- * else result is not Promise
1738
- * Method-->>Decorator: return result
1739
- * Decorator->>Logger: log benchmark (if enabled)
1740
- * Decorator-->>Client: return result
1741
- * end
1742
- * @category Method Decorators
1743
- */
1744
- function log(level = exports.LogLevel.info, verbosity = 0, entryMessage = (...args) => `called with ${args}`, exitMessage) {
1745
- return function log(target, propertyKey, descriptor) {
1746
- if (!descriptor || typeof descriptor === "number")
1747
- throw new Error(`Logging decoration only applies to methods`);
1748
- const logger = target instanceof LoggedClass
1749
- ? target["log"].for(target[propertyKey])
1750
- : Logging.for(target).for(target[propertyKey]);
1751
- const method = logger[level].bind(logger);
1752
- const originalMethod = descriptor.value;
1753
- descriptor.value = new Proxy(originalMethod, {
1754
- apply(fn, thisArg, args) {
1755
- method(entryMessage(...args), verbosity);
1756
- try {
1757
- const result = Reflect.apply(fn, thisArg, args);
1758
- if (result instanceof Promise) {
1759
- return result
1760
- .then((r) => {
1761
- if (exitMessage)
1762
- method(exitMessage(undefined, r));
1763
- return r;
1764
- })
1765
- .catch((e) => {
1766
- if (exitMessage)
1767
- logger.error(exitMessage(e));
1768
- throw e;
1769
- });
1770
- }
1771
- if (exitMessage)
1772
- method(exitMessage(undefined, result));
1773
- return result;
1774
- }
1775
- catch (err) {
1776
- if (exitMessage)
1777
- logger.error(exitMessage(err));
1778
- throw err;
1779
- }
1780
- },
1781
- });
1782
- return descriptor;
1783
- };
1784
- }
1785
- /**
1786
- * @description Method decorator that records execution time at the benchmark level.
1787
- * @summary Wraps the target method to emit {@link Logger.benchmark} entries capturing completion time or failure latency.
1788
- * @return {function(any, any, PropertyDescriptor): void} Method decorator proxy that benchmarks the original implementation.
1789
- * @function benchmark
1790
- * @mermaid
1791
- * sequenceDiagram
1792
- * participant Caller
1793
- * participant Decorator as benchmark
1794
- * participant Method as Original Method
1795
- * Caller->>Decorator: invoke()
1796
- * Decorator->>Method: Reflect.apply(...)
1797
- * alt Promise result
1798
- * Method-->>Decorator: Promise
1799
- * Decorator->>Decorator: attach then()
1800
- * Decorator->>Decorator: log completion duration
1801
- * else Synchronous result
1802
- * Method-->>Decorator: value
1803
- * Decorator->>Decorator: log completion duration
1804
- * end
1805
- * Decorator-->>Caller: return result
1806
- * @category Method Decorators
1807
- */
1808
- function benchmark() {
1809
- return function benchmark(target, propertyKey, descriptor) {
1810
- if (!descriptor || typeof descriptor === "number")
1811
- throw new Error(`benchmark decoration only applies to methods`);
1812
- const logger = target instanceof LoggedClass
1813
- ? target["log"].for(target[propertyKey])
1814
- : Logging.for(target).for(target[propertyKey]);
1815
- const originalMethod = descriptor.value;
1816
- descriptor.value = new Proxy(originalMethod, {
1817
- apply(fn, thisArg, args) {
1818
- const start = now();
1819
- try {
1820
- const result = Reflect.apply(fn, thisArg, args);
1821
- if (result instanceof Promise) {
1822
- return result
1823
- .then((r) => {
1824
- logger.benchmark(`completed in ${now() - start}ms`);
1825
- return r;
1826
- })
1827
- .catch((e) => {
1828
- logger.benchmark(`failed in ${now() - start}ms`);
1829
- throw e;
1830
- });
1831
- }
1832
- logger.benchmark(`completed in ${now() - start}ms`);
1833
- return result;
1834
- }
1835
- catch (err) {
1836
- logger.benchmark(`failed in ${now() - start}ms`);
1837
- throw err;
1838
- }
1839
- },
1840
- });
1841
- return descriptor;
1842
- };
1843
- }
1844
- /**
1845
- * @description Method decorator for logging function calls with debug level.
1846
- * @summary Convenience wrapper around {@link log} that logs using `LogLevel.debug`.
1847
- * @return {function(any, any, PropertyDescriptor): void} Debug-level logging decorator.
1848
- * @function debug
1849
- * @category Method Decorators
1850
- */
1851
- function debug() {
1852
- return log(exports.LogLevel.debug, 0, (...args) => `called with ${args}`, (e, result) => e
1853
- ? `Failed with: ${e}`
1854
- : result
1855
- ? `Completed with ${JSON.stringify(result)}`
1856
- : "completed");
1857
- }
1858
- /**
1859
- * @description Method decorator for logging function calls with info level.
1860
- * @summary Convenience wrapper around {@link log} that logs using `LogLevel.info`.
1861
- * @return {function(any, any, PropertyDescriptor): void} Info-level logging decorator.
1862
- * @function info
1863
- * @category Method Decorators
1864
- */
1865
- function info() {
1866
- return log(exports.LogLevel.info);
1867
- }
1868
- /**
1869
- * @description Method decorator for logging function calls with silly level.
1870
- * @summary Convenience wrapper around {@link log} that logs using `LogLevel.silly`.
1871
- * @return {function(any, any, PropertyDescriptor): void} Silly-level logging decorator.
1872
- * @function silly
1873
- * @category Method Decorators
1874
- */
1875
- function silly() {
1876
- return log(exports.LogLevel.silly);
1877
- }
1878
- /**
1879
- * @description Method decorator for logging function calls with trace level.
1880
- * @summary Convenience wrapper around {@link log} that logs using `LogLevel.trace`.
1881
- * @return {function(any, any, PropertyDescriptor): void} Trace-level logging decorator.
1882
- * @function trace
1883
- * @category Method Decorators
1884
- */
1885
- function trace() {
1886
- return log(exports.LogLevel.trace);
1887
- }
1888
- /**
1889
- * @description Method decorator for logging function calls with verbose level.
1890
- * @summary Convenience wrapper around {@link log} that logs using `LogLevel.verbose` with configurable verbosity and optional benchmarking.
1891
- * @param {number|boolean} verbosity - Verbosity level for log filtering or flag to enable benchmarking.
1892
- * @return {function(any, any,PropertyDescriptor): void} Verbose logging decorator.
1893
- * @function verbose
1894
- * @category Method Decorators
1895
- */
1896
- function verbose(verbosity = 0) {
1897
- if (!verbosity) {
1898
- verbosity = 0;
1899
- }
1900
- return log(exports.LogLevel.verbose, verbosity);
1901
- }
1902
- /**
1903
- * @description Creates a decorator that makes a method non-configurable.
1904
- * @summary Prevents overriding by marking the method descriptor as non-configurable, throwing if applied to non-method targets.
1905
- * @return {function(object, any, PropertyDescriptor): PropertyDescriptor|undefined} Decorator that hardens the method descriptor.
1906
- * @function final
1907
- * @category Method Decorators
1908
- */
1909
- function final() {
1910
- return (target, propertyKey, descriptor) => {
1911
- if (!descriptor)
1912
- throw new Error("final decorator can only be used on methods");
1913
- if (descriptor?.configurable) {
1914
- descriptor.configurable = false;
1915
- }
1916
- return descriptor;
1917
- };
1918
- }
1919
-
1920
- /**
1921
- * @description Filter that patches log messages using regular expressions.
1922
- * @summary Applies a configured {@link RegExp} and replacement strategy to redact, mask, or restructure log payloads before they are emitted.
1923
- * @param {RegExp} regexp - Expression used to detect sensitive or formatted text.
1924
- * @param {string|ReplacementFunction} replacement - Replacement string or callback invoked for each match.
1925
- * @class PatternFilter
1926
- * @example
1927
- * const filter = new PatternFilter(/token=[^&]+/g, "token=***");
1928
- * const sanitized = filter.filter(config, "token=123&user=tom", []);
1929
- * // sanitized === "token=***&user=tom"
1930
- * @mermaid
1931
- * sequenceDiagram
1932
- * participant Logger
1933
- * participant Filter as PatternFilter
1934
- * participant RegExp
1935
- * Logger->>Filter: filter(config, message, context)
1936
- * Filter->>RegExp: execute match()
1937
- * alt match found
1938
- * RegExp-->>Filter: captures
1939
- * Filter->>RegExp: replace(message, replacement)
1940
- * RegExp-->>Filter: transformed message
1941
- * else no match
1942
- * RegExp-->>Filter: null
1943
- * end
1944
- * Filter-->>Logger: sanitized message
1945
- */
1946
- class PatternFilter extends LogFilter {
1947
- constructor(regexp, replacement) {
1948
- super();
1949
- this.regexp = regexp;
1950
- this.replacement = replacement;
1951
- }
1952
- /**
1953
- * @description Ensures deterministic RegExp matching.
1954
- * @summary Runs the configured expression, then resets its state so repeated invocations behave consistently.
1955
- * @param {string} message - Message to test for matches.
1956
- * @return {RegExpExecArray|null} Match result or null when no match is found.
1957
- */
1958
- match(message) {
1959
- const match = this.regexp.exec(message);
1960
- this.regexp.lastIndex = 0;
1961
- return match;
1962
- }
1963
- /**
1964
- * @description Applies the replacement strategy to the incoming message.
1965
- * @summary Executes {@link PatternFilter.match} and, when a match is found, replaces every occurrence using the configured replacement handler.
1966
- * @param {LoggingConfig} config - Active logging configuration (unused but part of the filter contract).
1967
- * @param {string} message - Message to be sanitized.
1968
- * @param {string[]} context - Context entries associated with the log event.
1969
- * @return {string} Sanitized log message.
1970
- */
1971
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1972
- filter(config, message, context) {
1973
- const log = this.log.for(this.filter);
1974
- const match = this.match(message);
1975
- if (!match)
1976
- return message;
1977
- try {
1978
- return message.replace(this.regexp, this.replacement);
1979
- }
1980
- catch (e) {
1981
- log.error(`PatternFilter replacement error: ${e}`);
1982
- }
1983
- return "";
1984
- }
1985
- }
1986
- tslib.__decorate([
1987
- final(),
1988
- tslib.__metadata("design:type", Function),
1989
- tslib.__metadata("design:paramtypes", [String]),
1990
- tslib.__metadata("design:returntype", void 0)
1991
- ], PatternFilter.prototype, "match", null);
1992
-
1993
- function isClass(value) {
1994
- if (typeof value !== "function")
1995
- return false;
1996
- // 1) Native ES class? (fast path)
1997
- // e.g., "class Foo { ... }" → source starts with "class"
1998
- try {
1999
- const src = Function.prototype.toString.call(value);
2000
- if (/^\s*class[\s{]/.test(src))
2001
- return true;
2002
- }
2003
- catch {
2004
- // Some environments may block .toString; ignore and continue.
2005
- }
2006
- // 2) Has a prototype at all? (filters out arrow funcs, bound funcs)
2007
- const protoDesc = Object.getOwnPropertyDescriptor(value, "prototype");
2008
- if (!protoDesc || !protoDesc.value)
2009
- return false;
2010
- // 3) In native classes, the "prototype" property is non-writable.
2011
- // (In plain functions, it's writable.) This is a strong signal.
2012
- if (protoDesc.writable === false)
2013
- return true;
2014
- // 4) Classic constructor or transpiled class:
2015
- // Must have its own "constructor" and at least one prototype method.
2016
- const proto = value.prototype;
2017
- if (!Object.prototype.hasOwnProperty.call(proto, "constructor"))
2018
- return false;
2019
- const names = Object.getOwnPropertyNames(proto).filter((n) => n !== "constructor");
2020
- return names.length > 0;
2021
- }
2022
-
2023
- /**
2024
- * @description Comprehensive logging toolkit for browser and Node environments.
2025
- * @summary Exposes {@link Logging} and {@link MiniLogger} for runtime logging, decorators such as {@link log} for method instrumentation, and utilities like {@link PatternFilter}, {@link StopWatch}, and {@link LoggedEnvironment} to build configurable, theme-aware log pipelines.
2026
- * @module Logging
2027
- */
2028
- /**
2029
- * @description Current package version string.
2030
- * @summary Stores the package version for diagnostics and compatibility checks.
2031
- * @const VERSION
2032
- * @type {string}
2033
- * @memberOf module:Logging
2034
- */
2035
- const VERSION = "0.3.25";
2036
- /**
2037
- * @description Current package version string.
2038
- * @summary Stores the package version for diagnostics and compatibility checks.
2039
- * @const PACKAGE_NAME
2040
- * @type {string}
2041
- * @memberOf module:Logging
2042
- */
2043
- const PACKAGE_NAME = "@decaf-ts/logging";
2044
-
2045
- exports.BrowserEnvKey = BrowserEnvKey;
2046
- exports.DefaultLoggingConfig = DefaultLoggingConfig;
2047
- exports.DefaultPlaceholderWrappers = DefaultPlaceholderWrappers;
2048
- exports.DefaultTheme = DefaultTheme;
2049
- exports.ENV_PATH_DELIMITER = ENV_PATH_DELIMITER;
2050
- exports.Environment = Environment;
2051
- exports.LogFilter = LogFilter;
2052
- exports.LoggedClass = LoggedClass;
2053
- exports.LoggedEnvironment = LoggedEnvironment;
2054
- exports.Logging = Logging;
2055
- exports.MiniLogger = MiniLogger;
2056
- exports.NumericLogLevels = NumericLogLevels;
2057
- exports.PACKAGE_NAME = PACKAGE_NAME;
2058
- exports.PatternFilter = PatternFilter;
2059
- exports.StopWatch = StopWatch;
2060
- exports.VERSION = VERSION;
2061
- exports.benchmark = benchmark;
2062
- exports.debug = debug;
2063
- exports.escapeRegExp = escapeRegExp;
2064
- exports.final = final;
2065
- exports.formatMs = formatMs;
2066
- exports.info = info;
2067
- exports.isBrowser = isBrowser;
2068
- exports.isClass = isClass;
2069
- exports.log = log;
2070
- exports.now = now;
2071
- exports.padEnd = padEnd;
2072
- exports.patchPlaceholders = patchPlaceholders;
2073
- exports.patchString = patchString;
2074
- exports.sf = sf;
2075
- exports.silly = silly;
2076
- exports.stringFormat = stringFormat;
2077
- exports.toCamelCase = toCamelCase;
2078
- exports.toENVFormat = toENVFormat;
2079
- exports.toKebabCase = toKebabCase;
2080
- exports.toPascalCase = toPascalCase;
2081
- exports.toSnakeCase = toSnakeCase;
2082
- exports.trace = trace;
2083
- exports.verbose = verbose;
2084
-
2085
- }));
2086
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nZ2luZy5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb25zdGFudHMudHMiLCIuLi9zcmMvdGV4dC50cyIsIi4uL3NyYy93ZWIudHMiLCIuLi9zcmMvZW52aXJvbm1lbnQudHMiLCIuLi9zcmMvbG9nZ2luZy50cyIsIi4uL3NyYy9Mb2dnZWRDbGFzcy50cyIsIi4uL3NyYy9maWx0ZXJzL0xvZ0ZpbHRlci50cyIsIi4uL3NyYy90aW1lLnRzIiwiLi4vc3JjL2RlY29yYXRvcnMudHMiLCIuLi9zcmMvZmlsdGVycy9QYXR0ZXJuRmlsdGVyLnRzIiwiLi4vc3JjL3V0aWxzLnRzIiwiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IExvZ2dpbmdDb25maWcsIFRoZW1lIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gR2xvYmFsIGtleSB1c2VkIHRvIHN0b3JlIGVudmlyb25tZW50IHZhcmlhYmxlcyBpbiBicm93c2VyIGNvbnRleHRzLlxuICogQHN1bW1hcnkgRW5hYmxlcyB0aGUgbG9nZ2luZyBlbnZpcm9ubWVudCBoZWxwZXJzIHRvIGxvY2F0ZSBzZXJpYWxpemVkIGVudmlyb25tZW50IGNvbmZpZ3VyYXRpb24gb24gYGdsb2JhbFRoaXNgLlxuICogQGNvbnN0IEJyb3dzZXJFbnZLZXlcbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAbWVtYmVyT2YgbW9kdWxlOkxvZ2dpbmdcbiAqL1xuZXhwb3J0IGNvbnN0IEJyb3dzZXJFbnZLZXkgPSBcIkVOVlwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWxpbWl0ZXIgdXNlZCBmb3IgY29tcG9zaW5nIG5lc3RlZCBlbnZpcm9ubWVudCB2YXJpYWJsZSBuYW1lcy5cbiAqIEBzdW1tYXJ5IEpvaW5zIHBhcmVudCBhbmQgY2hpbGQga2V5cyB3aGVuIG1hcHBpbmcgb2JqZWN0IHBhdGhzIHRvIEVOViBzdHJpbmdzLlxuICogQGNvbnN0IEVOVl9QQVRIX0RFTElNSVRFUlxuICogQHR5cGUge3N0cmluZ31cbiAqIEBtZW1iZXJPZiBtb2R1bGU6TG9nZ2luZ1xuICovXG5leHBvcnQgY29uc3QgRU5WX1BBVEhfREVMSU1JVEVSID0gXCJfX1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IHByZWZpeCBhbmQgc3VmZml4IHVzZWQgZm9yIHRlbXBsYXRlIHBsYWNlaG9sZGVycy5cbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIHdyYXBwZXIgc3RyaW5ncyBhcHBsaWVkIHdoZW4gaW50ZXJwb2xhdGluZyBtZXNzYWdlcyB3aXRoIHtAbGluayBwYXRjaFBsYWNlaG9sZGVyc30uXG4gKiBAY29uc3QgRGVmYXVsdFBsYWNlaG9sZGVyV3JhcHBlcnNcbiAqIEB0eXBlIHtzdHJpbmdbXX1cbiAqIEBtZW1iZXJPZiBtb2R1bGU6TG9nZ2luZ1xuICovXG5leHBvcnQgY29uc3QgRGVmYXVsdFBsYWNlaG9sZGVyV3JhcHBlcnMgPSBbXCIke1wiLCBcIn1cIl07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVudW0gZm9yIGxvZyBsZXZlbHMuXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGRpZmZlcmVudCBsZXZlbHMgb2YgbG9nZ2luZyBmb3IgdGhlIGFwcGxpY2F0aW9uLlxuICogQGVudW0ge3N0cmluZ31cbiAqIEByZWFkb25seVxuICogQG1lbWJlck9mIG1vZHVsZTpMb2dnaW5nXG4gKi9cbmV4cG9ydCBlbnVtIExvZ0xldmVsIHtcbiAgLyoqIEBkZXNjcmlwdGlvbiBCZW5jaG1hcmsgZXZlbnRzIHRoYXQgY2FwdHVyZSBwZXJmb3JtYW5jZSBtZXRyaWNzLiAqL1xuICBiZW5jaG1hcmsgPSBcImJlbmNobWFya1wiLFxuICAvKiogQGRlc2NyaXB0aW9uIEVycm9yIGV2ZW50cyB0aGF0IGluZGljYXRlIGZhaWx1cmVzIHJlcXVpcmluZyBhdHRlbnRpb24uICovXG4gIGVycm9yID0gXCJlcnJvclwiLFxuICAvKiogQGRlc2NyaXB0aW9uIFdhcm5pbmcgZXZlbnRzIHRoYXQgbWF5IGluZGljYXRlIGlzc3Vlcy4gKi9cbiAgd2FybiA9IFwid2FyblwiLFxuICAvKiogQGRlc2NyaXB0aW9uIEluZm9ybWF0aW9uYWwgZXZlbnRzIGRlc2NyaWJpbmcgbm9ybWFsIG9wZXJhdGlvbi4gKi9cbiAgaW5mbyA9IFwiaW5mb1wiLFxuICAvKiogQGRlc2NyaXB0aW9uIFZlcmJvc2UgZGlhZ25vc3RpYyBpbmZvcm1hdGlvbiBmb3IgZGV0YWlsZWQgdHJhY2luZy4gKi9cbiAgdmVyYm9zZSA9IFwidmVyYm9zZVwiLFxuICAvKiogQGRlc2NyaXB0aW9uIERlYnVnIG9yIHRyYWNlIGRldGFpbHMgYWltZWQgYXQgZGV2ZWxvcGVycy4gKi9cbiAgZGVidWcgPSBcImRlYnVnXCIsXG4gIC8qKiBAZGVzY3JpcHRpb24gdHJhY2UgZGV0YWlscyBhaW1lZCBhdCBkZXZlbG9wZXJzICovXG4gIHRyYWNlID0gXCJ0cmFjZVwiLFxuICAvKiogQGRlc2NyaXB0aW9uIEV4dHJlbWVseSBjaGF0dHkgb3IgcGxheWZ1bCBsb2cgZW50cmllcy4gKi9cbiAgc2lsbHkgPSBcInNpbGx5XCIsXG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE51bWVyaWMgdmFsdWVzIGFzc29jaWF0ZWQgd2l0aCBsb2cgbGV2ZWxzLlxuICogQHN1bW1hcnkgUHJvdmlkZXMgYSBudW1lcmljIHJlcHJlc2VudGF0aW9uIG9mIGxvZyBsZXZlbHMgZm9yIGNvbXBhcmlzb24gYW5kIGZpbHRlcmluZy5cbiAqIEB0eXBlZGVmIHtPYmplY3R9IE51bWVyaWNMb2dMZXZlbHNTaGFwZVxuICogQHByb3BlcnR5IHtudW1iZXJ9IGJlbmNobWFyayAtIE51bWVyaWMgdmFsdWUgZm9yIGJlbmNobWFyayBsZXZlbCAoMCkuXG4gKiBAcHJvcGVydHkge251bWJlcn0gZXJyb3IgLSBOdW1lcmljIHZhbHVlIGZvciBlcnJvciBsZXZlbCAoMikuXG4gKiBAcHJvcGVydHkge251bWJlcn0gaW5mbyAtIE51bWVyaWMgdmFsdWUgZm9yIGluZm8gbGV2ZWwgKDQpLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IHZlcmJvc2UgLSBOdW1lcmljIHZhbHVlIGZvciB2ZXJib3NlIGxldmVsICg2KS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBkZWJ1ZyAtIE51bWVyaWMgdmFsdWUgZm9yIGRlYnVnIGxldmVsICg3KS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBzaWxseSAtIE51bWVyaWMgdmFsdWUgZm9yIHNpbGx5IGxldmVsICg5KS5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6TG9nZ2luZ1xuICovXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBOdW1lcmljIHZhbHVlcyBhc3NvY2lhdGVkIHdpdGggbG9nIGxldmVscy5cbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIGEgbnVtZXJpYyByZXByZXNlbnRhdGlvbiBvZiBsb2cgbGV2ZWxzIGZvciBjb21wYXJpc29uIGFuZCBmaWx0ZXJpbmcuXG4gKiBAY29uc3QgTnVtZXJpY0xvZ0xldmVsc1xuICogQHR5cGUge051bWVyaWNMb2dMZXZlbHNTaGFwZX1cbiAqIEBtZW1iZXJPZiBtb2R1bGU6TG9nZ2luZ1xuICovXG5leHBvcnQgY29uc3QgTnVtZXJpY0xvZ0xldmVscyA9IHtcbiAgYmVuY2htYXJrOiAwLFxuICBlcnJvcjogMyxcbiAgd2FybjogNixcbiAgaW5mbzogOSxcbiAgdmVyYm9zZTogMTIsXG4gIGRlYnVnOiAxNSxcbiAgdHJhY2U6IDE4LFxuICBzaWxseTogMjEsXG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFbnVtIGZvciBsb2dnaW5nIG91dHB1dCBtb2Rlcy5cbiAqIEBzdW1tYXJ5IERlZmluZXMgZGlmZmVyZW50IG91dHB1dCBmb3JtYXRzIGZvciBsb2cgbWVzc2FnZXMuXG4gKiBAZW51bSB7c3RyaW5nfVxuICogQG1lbWJlck9mIG1vZHVsZTpMb2dnaW5nXG4gKi9cbmV4cG9ydCBlbnVtIExvZ2dpbmdNb2RlIHtcbiAgLyoqIFJhdyB0ZXh0IGZvcm1hdCBmb3IgaHVtYW4gcmVhZGFiaWxpdHkgKi9cbiAgUkFXID0gXCJyYXdcIixcbiAgLyoqIEpTT04gZm9ybWF0IGZvciBtYWNoaW5lIHBhcnNpbmcgKi9cbiAgSlNPTiA9IFwianNvblwiLFxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IHRoZW1lIGZvciBzdHlsaW5nIGxvZyBvdXRwdXQuXG4gKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSBkZWZhdWx0IGNvbG9yIGFuZCBzdHlsZSBzZXR0aW5ncyBmb3IgdmFyaW91cyBjb21wb25lbnRzIG9mIGxvZyBtZXNzYWdlcy5cbiAqIEB0eXBlZGVmIHtUaGVtZX0gRGVmYXVsdFRoZW1lXG4gKiBAcHJvcGVydHkge09iamVjdH0gY2xhc3MgLSBTdHlsaW5nIGZvciBjbGFzcyBuYW1lcy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBjbGFzcy5mZyAtIEZvcmVncm91bmQgY29sb3IgY29kZSBmb3IgY2xhc3MgbmFtZXMgKDM0KS5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBpZCAtIFN0eWxpbmcgZm9yIGlkZW50aWZpZXJzLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IGlkLmZnIC0gRm9yZWdyb3VuZCBjb2xvciBjb2RlIGZvciBpZGVudGlmaWVycyAoMzYpLlxuICogQHByb3BlcnR5IHtPYmplY3R9IHN0YWNrIC0gU3R5bGluZyBmb3Igc3RhY2sgdHJhY2VzIChlbXB0eSBvYmplY3QpLlxuICogQHByb3BlcnR5IHtPYmplY3R9IHRpbWVzdGFtcCAtIFN0eWxpbmcgZm9yIHRpbWVzdGFtcHMgKGVtcHR5IG9iamVjdCkuXG4gKiBAcHJvcGVydHkge09iamVjdH0gbWVzc2FnZSAtIFN0eWxpbmcgZm9yIGRpZmZlcmVudCB0eXBlcyBvZiBtZXNzYWdlcy5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBtZXNzYWdlLmVycm9yIC0gU3R5bGluZyBmb3IgZXJyb3IgbWVzc2FnZXMuXG4gKiBAcHJvcGVydHkge251bWJlcn0gbWVzc2FnZS5lcnJvci5mZyAtIEZvcmVncm91bmQgY29sb3IgY29kZSBmb3IgZXJyb3IgbWVzc2FnZXMgKDMxKS5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBtZXRob2QgLSBTdHlsaW5nIGZvciBtZXRob2QgbmFtZXMgKGVtcHR5IG9iamVjdCkuXG4gKiBAcHJvcGVydHkge09iamVjdH0gbG9nTGV2ZWwgLSBTdHlsaW5nIGZvciBkaWZmZXJlbnQgbG9nIGxldmVscy5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBsb2dMZXZlbC5lcnJvciAtIFN0eWxpbmcgZm9yIGVycm9yIGxldmVsIGxvZ3MuXG4gKiBAcHJvcGVydHkge251bWJlcn0gbG9nTGV2ZWwuZXJyb3IuZmcgLSBGb3JlZ3JvdW5kIGNvbG9yIGNvZGUgZm9yIGVycm9yIGxldmVsIGxvZ3MgKDMxKS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nW119IGxvZ0xldmVsLmVycm9yLnN0eWxlIC0gU3R5bGUgYXR0cmlidXRlcyBmb3IgZXJyb3IgbGV2ZWwgbG9ncyAoW1wiYm9sZFwiXSkuXG4gKiBAcHJvcGVydHkge09iamVjdH0gbG9nTGV2ZWwuaW5mbyAtIFN0eWxpbmcgZm9yIGluZm8gbGV2ZWwgbG9ncyAoZW1wdHkgb2JqZWN0KS5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBsb2dMZXZlbC52ZXJib3NlIC0gU3R5bGluZyBmb3IgdmVyYm9zZSBsZXZlbCBsb2dzIChlbXB0eSBvYmplY3QpLlxuICogQHByb3BlcnR5IHtPYmplY3R9IGxvZ0xldmVsLmRlYnVnIC0gU3R5bGluZyBmb3IgZGVidWcgbGV2ZWwgbG9ncy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBsb2dMZXZlbC5kZWJ1Zy5mZyAtIEZvcmVncm91bmQgY29sb3IgY29kZSBmb3IgZGVidWcgbGV2ZWwgbG9ncyAoMzMpLlxuICogQGNvbnN0IERlZmF1bHRUaGVtZVxuICogQG1lbWJlck9mIG1vZHVsZTpMb2dnaW5nXG4gKi9cbmV4cG9ydCBjb25zdCBEZWZhdWx0VGhlbWU6IFRoZW1lID0ge1xuICBhcHA6IHt9LFxuICBzZXBhcmF0b3I6IHt9LFxuICBjbGFzczoge1xuICAgIGZnOiAzNCxcbiAgfSxcbiAgaWQ6IHtcbiAgICBmZzogMzYsXG4gIH0sXG4gIHN0YWNrOiB7fSxcbiAgdGltZXN0YW1wOiB7fSxcbiAgbWVzc2FnZToge1xuICAgIGVycm9yOiB7XG4gICAgICBmZzogMzEsXG4gICAgfSxcbiAgfSxcbiAgbWV0aG9kOiB7fSxcbiAgbG9nTGV2ZWw6IHtcbiAgICBiZW5jaG1hcms6IHtcbiAgICAgIGZnOiAzMixcbiAgICAgIHN0eWxlOiBbXCJib2xkXCJdLFxuICAgIH0sXG4gICAgZXJyb3I6IHtcbiAgICAgIGZnOiAzMSxcbiAgICAgIHN0eWxlOiBbXCJib2xkXCJdLFxuICAgIH0sXG4gICAgaW5mbzoge1xuICAgICAgZmc6IDM0LFxuICAgICAgc3R5bGU6IFtcImJvbGRcIl0sXG4gICAgfSxcbiAgICB2ZXJib3NlOiB7XG4gICAgICBmZzogMzQsXG4gICAgICBzdHlsZTogW1wiYm9sZFwiXSxcbiAgICB9LFxuICAgIGRlYnVnOiB7XG4gICAgICBmZzogMzMsXG4gICAgICBzdHlsZTogW1wiYm9sZFwiXSxcbiAgICB9LFxuICAgIHRyYWNlOiB7XG4gICAgICBmZzogMzMsXG4gICAgICBzdHlsZTogW1wiYm9sZFwiXSxcbiAgICB9LFxuICAgIHNpbGx5OiB7XG4gICAgICBmZzogMzMsXG4gICAgICBzdHlsZTogW1wiYm9sZFwiXSxcbiAgICB9LFxuICB9LFxufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVmYXVsdCBjb25maWd1cmF0aW9uIGZvciBsb2dnaW5nLlxuICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgZGVmYXVsdCBzZXR0aW5ncyBmb3IgdGhlIGxvZ2dpbmcgc3lzdGVtLCBpbmNsdWRpbmcgdmVyYm9zaXR5LCBsb2cgbGV2ZWwsIHN0eWxpbmcsIGFuZCB0aW1lc3RhbXAgZm9ybWF0LlxuICogQGNvbnN0IERlZmF1bHRMb2dnaW5nQ29uZmlnXG4gKiBAdHlwZWRlZiB7TG9nZ2luZ0NvbmZpZ30gRGVmYXVsdExvZ2dpbmdDb25maWdcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSB2ZXJib3NlIC0gVmVyYm9zaXR5IGxldmVsICgwKS5cbiAqIEBwcm9wZXJ0eSB7TG9nTGV2ZWx9IGxldmVsIC0gRGVmYXVsdCBsb2cgbGV2ZWwgKExvZ0xldmVsLmluZm8pLlxuICogQHByb3BlcnR5IHtib29sZWFufSBsb2dMZXZlbCAtIFdoZXRoZXIgdG8gZGlzcGxheSBsb2cgbGV2ZWwgaW4gb3V0cHV0ICh0cnVlKS5cbiAqIEBwcm9wZXJ0eSB7TG9nZ2luZ01vZGV9IG1vZGUgLSBPdXRwdXQgZm9ybWF0IG1vZGUgKExvZ2dpbmdNb2RlLlJBVykuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IHN0eWxlIC0gV2hldGhlciB0byBhcHBseSBzdHlsaW5nIHRvIGxvZyBvdXRwdXQgKGZhbHNlKS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBzZXBhcmF0b3IgLSBTZXBhcmF0b3IgYmV0d2VlbiBsb2cgY29tcG9uZW50cyAoXCIgLSBcIikuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IHRpbWVzdGFtcCAtIFdoZXRoZXIgdG8gaW5jbHVkZSB0aW1lc3RhbXBzIGluIGxvZyBtZXNzYWdlcyAodHJ1ZSkuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdGltZXN0YW1wRm9ybWF0IC0gRm9ybWF0IGZvciB0aW1lc3RhbXBzIChcIkhIOm1tOnNzLlNTU1wiKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gY29udGV4dCAtIFdoZXRoZXIgdG8gaW5jbHVkZSBjb250ZXh0IGluZm9ybWF0aW9uIGluIGxvZyBtZXNzYWdlcyAodHJ1ZSkuXG4gKiBAcHJvcGVydHkge1RoZW1lfSB0aGVtZSAtIFRoZSB0aGVtZSB0byB1c2UgZm9yIHN0eWxpbmcgbG9nIG1lc3NhZ2VzIChEZWZhdWx0VGhlbWUpLlxuICogQG1lbWJlck9mIG1vZHVsZTpMb2dnaW5nXG4gKi9cbmV4cG9ydCBjb25zdCBEZWZhdWx0TG9nZ2luZ0NvbmZpZzogTG9nZ2luZ0NvbmZpZyA9IHtcbiAgZW52OiBcImRldmVsb3BtZW50XCIsXG4gIHZlcmJvc2U6IDAsXG4gIGxldmVsOiBMb2dMZXZlbC5pbmZvLFxuICBsb2dMZXZlbDogdHJ1ZSxcbiAgc3R5bGU6IGZhbHNlLFxuICBjb250ZXh0U2VwYXJhdG9yOiBcIi5cIixcbiAgc2VwYXJhdG9yOiBcIi1cIixcbiAgdGltZXN0YW1wOiB0cnVlLFxuICB0aW1lc3RhbXBGb3JtYXQ6IFwiSEg6bW06c3MuU1NTXCIsXG4gIGNvbnRleHQ6IHRydWUsXG4gIGZvcm1hdDogTG9nZ2luZ01vZGUuUkFXLFxuICBwYXR0ZXJuOlxuICAgIFwie2xldmVsfSBbe3RpbWVzdGFtcH1dIHthcHB9IHtjb250ZXh0fSB7c2VwYXJhdG9yfSB7bWVzc2FnZX0ge3N0YWNrfVwiLFxuICB0aGVtZTogRGVmYXVsdFRoZW1lLFxufTtcbiIsImltcG9ydCB7IERlZmF1bHRQbGFjZWhvbGRlcldyYXBwZXJzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFBhZHMgdGhlIGVuZCBvZiBhIHN0cmluZyB3aXRoIGEgc3BlY2lmaWVkIGNoYXJhY3Rlci5cbiAqIEBzdW1tYXJ5IEV4dGVuZHMgdGhlIGlucHV0IHN0cmluZyB0byBhIHNwZWNpZmllZCBsZW5ndGggYnkgYWRkaW5nIGEgcGFkZGluZyBjaGFyYWN0ZXIgdG8gdGhlIGVuZC5cbiAqIElmIHRoZSBpbnB1dCBzdHJpbmcgaXMgYWxyZWFkeSBsb25nZXIgdGhhbiB0aGUgc3BlY2lmaWVkIGxlbmd0aCwgaXQgaXMgcmV0dXJuZWQgdW5jaGFuZ2VkLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgLSBUaGUgaW5wdXQgc3RyaW5nIHRvIGJlIHBhZGRlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBsZW5ndGggLSBUaGUgZGVzaXJlZCB0b3RhbCBsZW5ndGggb2YgdGhlIHJlc3VsdGluZyBzdHJpbmcuXG4gKiBAcGFyYW0ge3N0cmluZ30gW2NoYXI9XCIgXCJdIC0gVGhlIGNoYXJhY3RlciB0byB1c2UgZm9yIHBhZGRpbmcuIERlZmF1bHRzIHRvIGEgc3BhY2UuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBwYWRkZWQgc3RyaW5nLlxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYWRkaW5nIGNoYXJhY3RlciBpcyBub3QgZXhhY3RseSBvbmUgY2hhcmFjdGVyIGxvbmcuXG4gKlxuICogQGZ1bmN0aW9uIHBhZEVuZFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6TG9nZ2luZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gcGFkRW5kKFxuICBzdHI6IHN0cmluZyxcbiAgbGVuZ3RoOiBudW1iZXIsXG4gIGNoYXI6IHN0cmluZyA9IFwiIFwiXG4pOiBzdHJpbmcge1xuICBpZiAoY2hhci5sZW5ndGggIT09IDEpXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBjaGFyYWN0ZXIgbGVuZ3RoIGZvciBwYWRkaW5nLiBtdXN0IGJlIG9uZSFcIik7XG4gIHJldHVybiBzdHIucGFkRW5kKGxlbmd0aCwgY2hhcik7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlcGxhY2VzIHBsYWNlaG9sZGVycyBpbiBhIHN0cmluZyB3aXRoIHByb3ZpZGVkIHZhbHVlcy5cbiAqIEBzdW1tYXJ5IEludGVycG9sYXRlcyBhIHN0cmluZyBieSByZXBsYWNpbmcgcGxhY2Vob2xkZXJzIG9mIHRoZSBmb3JtICR7dmFyaWFibGVOYW1lfVxuICogd2l0aCBjb3JyZXNwb25kaW5nIHZhbHVlcyBmcm9tIHRoZSBwcm92aWRlZCBvYmplY3QuIElmIGEgcGxhY2Vob2xkZXIgZG9lc24ndCBoYXZlXG4gKiBhIGNvcnJlc3BvbmRpbmcgdmFsdWUsIGl0IGlzIGxlZnQgdW5jaGFuZ2VkIGluIHRoZSBzdHJpbmcuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGlucHV0IC0gVGhlIGlucHV0IHN0cmluZyBjb250YWluaW5nIHBsYWNlaG9sZGVycyB0byBiZSByZXBsYWNlZC5cbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgbnVtYmVyIHwgc3RyaW5nPn0gdmFsdWVzIC0gQW4gb2JqZWN0IGNvbnRhaW5pbmcga2V5LXZhbHVlIHBhaXJzIGZvciByZXBsYWNlbWVudC5cbiAqIEBwYXJhbSBwcmVmaXhcbiAqIEBwYXJhbSBzdWZmaXhcbiAqIEBwYXJhbSBmbGFnc1xuICogQHJldHVybiB7c3RyaW5nfSBUaGUgaW50ZXJwb2xhdGVkIHN0cmluZyB3aXRoIHBsYWNlaG9sZGVycyByZXBsYWNlZCBieSB0aGVpciBjb3JyZXNwb25kaW5nIHZhbHVlcy5cbiAqXG4gKiBAZnVuY3Rpb24gcGF0Y2hQbGFjZWhvbGRlcnNcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBwYXRjaFN0cmluZ1xuICogICBwYXJ0aWNpcGFudCBTdHJpbmcucmVwbGFjZVxuICogICBDYWxsZXItPj5wYXRjaFN0cmluZzogQ2FsbCB3aXRoIGlucHV0IGFuZCB2YWx1ZXNcbiAqICAgcGF0Y2hTdHJpbmctPj5TdHJpbmcucmVwbGFjZTogQ2FsbCB3aXRoIHJlZ2V4IGFuZCByZXBsYWNlbWVudCBmdW5jdGlvblxuICogICBTdHJpbmcucmVwbGFjZS0+PnBhdGNoU3RyaW5nOiBSZXR1cm4gcmVwbGFjZWQgc3RyaW5nXG4gKiAgIHBhdGNoU3RyaW5nLS0+PkNhbGxlcjogUmV0dXJuIHBhdGNoZWQgc3RyaW5nXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTpMb2dnaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXRjaFBsYWNlaG9sZGVycyhcbiAgaW5wdXQ6IHN0cmluZyxcbiAgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXIgfCBzdHJpbmc+LFxuICBwcmVmaXg6IHN0cmluZyA9IERlZmF1bHRQbGFjZWhvbGRlcldyYXBwZXJzWzBdLFxuICBzdWZmaXg6IHN0cmluZyA9IERlZmF1bHRQbGFjZWhvbGRlcldyYXBwZXJzWzFdLFxuICBmbGFnczogc3RyaW5nID0gXCJnXCJcbik6IHN0cmluZyB7XG4gIGNvbnN0IHBsYWNlaG9sZGVycyA9IE9iamVjdC5lbnRyaWVzKHZhbHVlcykucmVkdWNlKFxuICAgIChhY2M6IFJlY29yZDxzdHJpbmcsIGFueT4sIFtrZXksIHZhbF0pID0+IHtcbiAgICAgIGFjY1tgJHtwcmVmaXh9JHtrZXl9JHtzdWZmaXh9YF0gPSB2YWw7XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sXG4gICAge31cbiAgKTtcbiAgcmV0dXJuIHBhdGNoU3RyaW5nKGlucHV0LCBwbGFjZWhvbGRlcnMsIGZsYWdzKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVwbGFjZXMgb2NjdXJyZW5jZXMgb2Yga2V5cyB3aXRoIHRoZWlyIGNvcnJlc3BvbmRpbmcgdmFsdWVzIGluIGEgc3RyaW5nLlxuICogQHN1bW1hcnkgSXRlcmF0ZXMgdGhyb3VnaCBhIHNldCBvZiBrZXktdmFsdWUgcGFpcnMgYW5kIHJlcGxhY2VzIGFsbCBvY2N1cnJlbmNlcyBvZiBlYWNoIGtleVxuICogaW4gdGhlIGlucHV0IHN0cmluZyB3aXRoIGl0cyBjb3JyZXNwb25kaW5nIHZhbHVlLiBTdXBwb3J0cyByZWd1bGFyIGV4cHJlc3Npb24gZmxhZ3MgZm9yIGN1c3RvbWl6ZWQgcmVwbGFjZW1lbnQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGlucHV0IC0gVGhlIGlucHV0IHN0cmluZyBpbiB3aGljaCByZXBsYWNlbWVudHMgd2lsbCBiZSBtYWRlLlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBudW1iZXIgfCBzdHJpbmc+fSB2YWx1ZXMgLSBBbiBvYmplY3QgY29udGFpbmluZyBrZXktdmFsdWUgcGFpcnMgZm9yIHJlcGxhY2VtZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IFtmbGFncz1cImdcIl0gLSBSZWd1bGFyIGV4cHJlc3Npb24gZmxhZ3MgdG8gY29udHJvbCB0aGUgcmVwbGFjZW1lbnQgYmVoYXZpb3IuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBzdHJpbmcgd2l0aCBhbGwgc3BlY2lmaWVkIHJlcGxhY2VtZW50cyBhcHBsaWVkLlxuICpcbiAqIEBmdW5jdGlvbiBwYXRjaFN0cmluZ1xuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6TG9nZ2luZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gcGF0Y2hTdHJpbmcoXG4gIGlucHV0OiBzdHJpbmcsXG4gIHZhbHVlczogUmVjb3JkPHN0cmluZywgbnVtYmVyIHwgc3RyaW5nPixcbiAgZmxhZ3M6IHN0cmluZyA9IFwiZ1wiXG4pOiBzdHJpbmcge1xuICBPYmplY3QuZW50cmllcyh2YWx1ZXMpLmZvckVhY2goKFtrZXksIHZhbF0pID0+IHtcbiAgICBjb25zdCByZWdleHAgPSBuZXcgUmVnRXhwKGVzY2FwZVJlZ0V4cChrZXkpLCBmbGFncyk7XG4gICAgaW5wdXQgPSBpbnB1dC5yZXBsYWNlKHJlZ2V4cCwgdmFsIGFzIHN0cmluZyk7XG4gIH0pO1xuICByZXR1cm4gaW5wdXQ7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvbnZlcnRzIGEgc3RyaW5nIHRvIGNhbWVsQ2FzZS5cbiAqIEBzdW1tYXJ5IFRyYW5zZm9ybXMgdGhlIGlucHV0IHN0cmluZyBpbnRvIGNhbWVsQ2FzZSBmb3JtYXQsIHdoZXJlIHdvcmRzIGFyZSBqb2luZWQgd2l0aG91dCBzcGFjZXNcbiAqIGFuZCBlYWNoIHdvcmQgYWZ0ZXIgdGhlIGZpcnN0IHN0YXJ0cyB3aXRoIGEgY2FwaXRhbCBsZXR0ZXIuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBUaGUgaW5wdXQgc3RyaW5nIHRvIGJlIGNvbnZlcnRlZC5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGlucHV0IHN0cmluZyBjb252ZXJ0ZWQgdG8gY2FtZWxDYXNlLlxuICpcbiAqIEBmdW5jdGlvbiB0b0NhbWVsQ2FzZVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6TG9nZ2luZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gdG9DYW1lbENhc2UodGV4dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHRleHRcbiAgICAucmVwbGFjZSgvKD86Xlxcd3xbQS1aXXxcXGJcXHcpL2csICh3b3JkLCBpbmRleCkgPT5cbiAgICAgIGluZGV4ID09PSAwID8gd29yZC50b0xvd2VyQ2FzZSgpIDogd29yZC50b1VwcGVyQ2FzZSgpXG4gICAgKVxuICAgIC5yZXBsYWNlKC9cXHMrL2csIFwiXCIpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDb252ZXJ0cyBhIHN0cmluZyB0byBFTlZJUk9OTUVOVF9WQVJJQUJMRSBmb3JtYXQuXG4gKiBAc3VtbWFyeSBUcmFuc2Zvcm1zIHRoZSBpbnB1dCBzdHJpbmcgaW50byB1cHBlcmNhc2Ugd2l0aCB3b3JkcyBzZXBhcmF0ZWQgYnkgdW5kZXJzY29yZXMsXG4gKiB0eXBpY2FsbHkgdXNlZCBmb3IgZW52aXJvbm1lbnQgdmFyaWFibGUgbmFtZXMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBUaGUgaW5wdXQgc3RyaW5nIHRvIGJlIGNvbnZlcnRlZC5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGlucHV0IHN0cmluZyBjb252ZXJ0ZWQgdG8gRU5WSVJPTk1FTlRfVkFSSUFCTEUgZm9ybWF0LlxuICpcbiAqIEBmdW5jdGlvbiB0b0VOVkZvcm1hdFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6TG9nZ2luZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gdG9FTlZGb3JtYXQodGV4dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHRvU25ha2VDYXNlKHRleHQpLnRvVXBwZXJDYXNlKCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvbnZlcnRzIGEgc3RyaW5nIHRvIHNuYWtlX2Nhc2UuXG4gKiBAc3VtbWFyeSBUcmFuc2Zvcm1zIHRoZSBpbnB1dCBzdHJpbmcgaW50byBsb3dlcmNhc2Ugd2l0aCB3b3JkcyBzZXBhcmF0ZWQgYnkgdW5kZXJzY29yZXMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBUaGUgaW5wdXQgc3RyaW5nIHRvIGJlIGNvbnZlcnRlZC5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGlucHV0IHN0cmluZyBjb252ZXJ0ZWQgdG8gc25ha2VfY2FzZS5cbiAqXG4gKiBAZnVuY3Rpb24gdG9TbmFrZUNhc2VcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOkxvZ2dpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvU25ha2VDYXNlKHRleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiB0ZXh0XG4gICAgLnJlcGxhY2UoLyhbYS16XSkoW0EtWl0pL2csIFwiJDFfJDJcIilcbiAgICAucmVwbGFjZSgvW1xccy1dKy9nLCBcIl9cIilcbiAgICAudG9Mb3dlckNhc2UoKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ29udmVydHMgYSBzdHJpbmcgdG8ga2ViYWItY2FzZS5cbiAqIEBzdW1tYXJ5IFRyYW5zZm9ybXMgdGhlIGlucHV0IHN0cmluZyBpbnRvIGxvd2VyY2FzZSB3aXRoIHdvcmRzIHNlcGFyYXRlZCBieSBoeXBoZW5zLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IC0gVGhlIGlucHV0IHN0cmluZyB0byBiZSBjb252ZXJ0ZWQuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBpbnB1dCBzdHJpbmcgY29udmVydGVkIHRvIGtlYmFiLWNhc2UuXG4gKlxuICogQGZ1bmN0aW9uIHRvS2ViYWJDYXNlXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTpMb2dnaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b0tlYmFiQ2FzZSh0ZXh0OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gdGV4dFxuICAgIC5yZXBsYWNlKC8oW2Etel0pKFtBLVpdKS9nLCBcIiQxLSQyXCIpXG4gICAgLnJlcGxhY2UoL1tcXHNfXSsvZywgXCItXCIpXG4gICAgLnRvTG93ZXJDYXNlKCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvbnZlcnRzIGEgc3RyaW5nIHRvIFBhc2NhbENhc2UuXG4gKiBAc3VtbWFyeSBUcmFuc2Zvcm1zIHRoZSBpbnB1dCBzdHJpbmcgaW50byBQYXNjYWxDYXNlIGZvcm1hdCwgd2hlcmUgd29yZHMgYXJlIGpvaW5lZCB3aXRob3V0IHNwYWNlc1xuICogYW5kIGVhY2ggd29yZCBzdGFydHMgd2l0aCBhIGNhcGl0YWwgbGV0dGVyLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IC0gVGhlIGlucHV0IHN0cmluZyB0byBiZSBjb252ZXJ0ZWQuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBpbnB1dCBzdHJpbmcgY29udmVydGVkIHRvIFBhc2NhbENhc2UuXG4gKlxuICogQGZ1bmN0aW9uIHRvUGFzY2FsQ2FzZVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6TG9nZ2luZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gdG9QYXNjYWxDYXNlKHRleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiB0ZXh0XG4gICAgLnJlcGxhY2UoLyg/Ol5cXHd8W0EtWl18XFxiXFx3KS9nLCAod29yZCkgPT4gd29yZC50b1VwcGVyQ2FzZSgpKVxuICAgIC5yZXBsYWNlKC9cXHMrL2csIFwiXCIpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFc2NhcGVzIHNwZWNpYWwgY2hhcmFjdGVycyBpbiBhIHN0cmluZyBmb3IgdXNlIGluIGEgcmVndWxhciBleHByZXNzaW9uLlxuICogQHN1bW1hcnkgQWRkcyBiYWNrc2xhc2hlcyBiZWZvcmUgY2hhcmFjdGVycyB0aGF0IGhhdmUgc3BlY2lhbCBtZWFuaW5nIGluIHJlZ3VsYXIgZXhwcmVzc2lvbnMsXG4gKiBhbGxvd2luZyB0aGUgc3RyaW5nIHRvIGJlIHVzZWQgYXMgYSBsaXRlcmFsIG1hdGNoIGluIGEgUmVnRXhwLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgLSBUaGUgc3RyaW5nIHRvIGVzY2FwZSBmb3IgcmVndWxhciBleHByZXNzaW9uIHVzZS5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGVzY2FwZWQgc3RyaW5nIHNhZmUgZm9yIHVzZSBpbiByZWd1bGFyIGV4cHJlc3Npb25zLlxuICpcbiAqIEBmdW5jdGlvbiBlc2NhcGVSZWdFeHBcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOkxvZ2dpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVzY2FwZVJlZ0V4cChzdHJpbmc6IHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1suKis/XiR7fSgpfFtcXF1cXFxcXS9nLCBcIlxcXFwkJlwiKTsgLy8gJCYgbWVhbnMgdGhlIHdob2xlIG1hdGNoZWQgc3RyaW5nXG59XG5cbi8qKlxuICogQHN1bW1hcnkgVXRpbCBmdW5jdGlvbiB0byBwcm92aWRlIHN0cmluZyBmb3JtYXQgZnVuY3Rpb25hbGl0eSBzaW1pbGFyIHRvIEMjJ3Mgc3RyaW5nLmZvcm1hdFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmdcbiAqIEBwYXJhbSB7QXJyYXk8c3RyaW5nIHwgbnVtYmVyPiB8IFJlY29yZDxzdHJpbmcsIGFueT59IFthcmdzXSByZXBsYWNlbWVudHMgbWFkZSBieSBvcmRlciBvZiBhcHBlYXJhbmNlIChyZXBsYWNlbWVudDAgd2lsIHJlcGxhY2UgezB9IGFuZCBzbyBvbilcbiAqIEByZXR1cm4ge3N0cmluZ30gZm9ybWF0dGVkIHN0cmluZ1xuICpcbiAqIEBmdW5jdGlvbiBzZlxuICogQG1lbWJlck9mIG1vZHVsZTpMb2dnaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZihcbiAgc3RyaW5nOiBzdHJpbmcsXG4gIC4uLmFyZ3M6IChzdHJpbmcgfCBudW1iZXIgfCBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtdXG4pIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID4gMSkge1xuICAgIGlmIChcbiAgICAgICFhcmdzLmV2ZXJ5KChhcmcpID0+IHR5cGVvZiBhcmcgPT09IFwic3RyaW5nXCIgfHwgdHlwZW9mIGFyZyA9PT0gXCJudW1iZXJcIilcbiAgICApXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBPbmx5IHN0cmluZyBhbmQgbnVtYmVyIGFyZ3VtZW50cyBhcmUgc3VwcG9ydGVkIGZvciBtdWx0aXBsZSByZXBsYWNlbWVudHMuYFxuICAgICAgKTtcbiAgfVxuXG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMSAmJiB0eXBlb2YgYXJnc1swXSA9PT0gXCJvYmplY3RcIikge1xuICAgIGNvbnN0IG9iaiA9IGFyZ3NbMF0gYXMgUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICByZXR1cm4gT2JqZWN0LmVudHJpZXMob2JqKS5yZWR1Y2UoKGFjYywgW2tleSwgdmFsXSkgPT4ge1xuICAgICAgcmV0dXJuIGFjYy5yZXBsYWNlKG5ldyBSZWdFeHAoYFxcXFx7JHtrZXl9XFxcXH1gLCBcImdcIiksIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgIH0pO1xuICAgIH0sIHN0cmluZyk7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL3soXFxkKyl9L2csIGZ1bmN0aW9uIChtYXRjaCwgbnVtYmVyKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBhcmdzW251bWJlcl0gIT09IFwidW5kZWZpbmVkXCJcbiAgICAgID8gYXJnc1tudW1iZXJdLnRvU3RyaW5nKClcbiAgICAgIDogXCJ1bmRlZmluZWRcIjtcbiAgfSk7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgVXRpbCBmdW5jdGlvbiB0byBwcm92aWRlIHN0cmluZyBmb3JtYXQgZnVuY3Rpb25hbGl0eSBzaW1pbGFyIHRvIEMjJ3Mgc3RyaW5nLmZvcm1hdFxuICpcbiAqIEBzZWUgc2ZcbiAqXG4gKiBAZGVwcmVjYXRlZFxuICogQGZ1bmN0aW9uIHN0cmluZ0Zvcm1hdFxuICogQG1lbWJlck9mIG1vZHVsZTpMb2dnaW5nXG4gKi9cbmV4cG9ydCBjb25zdCBzdHJpbmdGb3JtYXQgPSBzZjtcbiIsIi8qKlxuICogQGRlc2NyaXB0aW9uIERldGVybWluZXMgaWYgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQgaXMgYSBicm93c2VyIGJ5IGNoZWNraW5nIHRoZSBwcm90b3R5cGUgY2hhaW4gb2YgdGhlIGdsb2JhbCBvYmplY3QuXG4gKiBAc3VtbWFyeSBDaGVja3MgaWYgdGhlIGNvZGUgaXMgcnVubmluZyBpbiBhIGJyb3dzZXIgZW52aXJvbm1lbnQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBlbnZpcm9ubWVudCBpcyBhIGJyb3dzZXIsIGZhbHNlIG90aGVyd2lzZS5cbiAqIEBmdW5jdGlvbiBpc0Jyb3dzZXJcbiAqIEBtZW1iZXJPZiBtb2R1bGU6TG9nZ2luZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNCcm93c2VyKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIE9iamVjdC5nZXRQcm90b3R5cGVPZihPYmplY3QuZ2V0UHJvdG90eXBlT2YoZ2xvYmFsVGhpcykpICE9PVxuICAgIE9iamVjdC5wcm90b3R5cGVcbiAgKTtcbn1cbiIsImltcG9ydCB7IE9iamVjdEFjY3VtdWxhdG9yIH0gZnJvbSBcInR5cGVkLW9iamVjdC1hY2N1bXVsYXRvclwiO1xuaW1wb3J0IHsgdG9FTlZGb3JtYXQgfSBmcm9tIFwiLi90ZXh0XCI7XG5pbXBvcnQgeyBpc0Jyb3dzZXIgfSBmcm9tIFwiLi93ZWJcIjtcbmltcG9ydCB7XG4gIEJyb3dzZXJFbnZLZXksXG4gIERlZmF1bHRMb2dnaW5nQ29uZmlnLFxuICBFTlZfUEFUSF9ERUxJTUlURVIsXG59IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBGYWN0b3J5IHR5cGUgZm9yIGNyZWF0aW5nIEVudmlyb25tZW50IGluc3RhbmNlcy5cbiAqIEBzdW1tYXJ5IERlc2NyaWJlcyBmYWN0b3JpZXMgdGhhdCBjb25zdHJ1Y3Qge0BsaW5rIEVudmlyb25tZW50fSBkZXJpdmF0aXZlcyB3aXRoIGN1c3RvbSBpbml0aWFsaXphdGlvbi5cbiAqIEB0ZW1wbGF0ZSBUIC0gVGhlIHR5cGUgb2Ygb2JqZWN0IHRoZSBFbnZpcm9ubWVudCB3aWxsIGFjY3VtdWxhdGUuXG4gKiBAdGVtcGxhdGUgRSAtIFRoZSBzcGVjaWZpYyBFbnZpcm9ubWVudCB0eXBlIHRvIGJlIGNyZWF0ZWQsIGV4dGVuZGluZyBFbnZpcm9ubWVudDxUPi5cbiAqIEB0eXBlZGVmIHtmdW5jdGlvbih1bmtub3duW10pOiBFfSBFbnZpcm9ubWVudEZhY3RvcnlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6TG9nZ2luZ1xuICovXG5leHBvcnQgdHlwZSBFbnZpcm9ubWVudEZhY3Rvcnk8VCBleHRlbmRzIG9iamVjdCwgRSBleHRlbmRzIEVudmlyb25tZW50PFQ+PiA9IChcbiAgLi4uYXJnczogdW5rbm93bltdXG4pID0+IEU7XG5cbmV4cG9ydCB0eXBlIEVudmlyb25tZW50SW5zdGFuY2U8VCBleHRlbmRzIG9iamVjdD4gPSBFbnZpcm9ubWVudDxUPiAmXG4gIFQgJiB7IG9yVGhyb3coKTogRW52aXJvbm1lbnRJbnN0YW5jZTxUPiB9O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFbnZpcm9ubWVudCBhY2N1bXVsYXRvciB0aGF0IGxhemlseSByZWFkcyBmcm9tIHJ1bnRpbWUgc291cmNlcy5cbiAqIEBzdW1tYXJ5IEV4dGVuZHMge0BsaW5rIE9iamVjdEFjY3VtdWxhdG9yfSB0byBtZXJnZSBjb25maWd1cmF0aW9uIG9iamVjdHMgd2hpbGUgcmVzb2x2aW5nIHZhbHVlcyBmcm9tIE5vZGUgb3IgYnJvd3NlciBlbnZpcm9ubWVudCB2YXJpYWJsZXMgb24gZGVtYW5kLlxuICogQHRlbXBsYXRlIFRcbiAqIEBjbGFzcyBFbnZpcm9ubWVudFxuICogQGV4YW1wbGVcbiAqIGNvbnN0IENvbmZpZyA9IEVudmlyb25tZW50LmFjY3VtdWxhdGUoeyBsb2dnaW5nOiB7IGxldmVsOiBcImluZm9cIiB9IH0pO1xuICogY29uc29sZS5sb2coQ29uZmlnLmxvZ2dpbmcubGV2ZWwpO1xuICogY29uc29sZS5sb2coU3RyaW5nKENvbmZpZy5sb2dnaW5nLmxldmVsKSk7IC8vID0+IExPR0dJTkdfX0xFVkVMIGtleSB3aGVuIHNlcmlhbGl6ZWRcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IEVudiBhcyBFbnZpcm9ubWVudFxuICogICBwYXJ0aWNpcGFudCBQcm9jZXNzIGFzIHByb2Nlc3MuZW52XG4gKiAgIHBhcnRpY2lwYW50IEJyb3dzZXIgYXMgZ2xvYmFsVGhpcy5FTlZcbiAqICAgQ2xpZW50LT4+RW52OiBhY2N1bXVsYXRlKHBhcnRpYWxDb25maWcpXG4gKiAgIEVudi0+PkVudjogZXhwYW5kKHZhbHVlcylcbiAqICAgQ2xpZW50LT4+RW52OiBDb25maWcubG9nZ2luZy5sZXZlbFxuICogICBhbHQgQnJvd3NlciBydW50aW1lXG4gKiAgICAgRW52LT4+QnJvd3NlcjogbG9va3VwIEVOViBrZXlcbiAqICAgICBCcm93c2VyLS0+PkVudjogcmVzb2x2ZWQgdmFsdWVcbiAqICAgZWxzZSBOb2RlIHJ1bnRpbWVcbiAqICAgICBFbnYtPj5Qcm9jZXNzOiBsb29rdXAgRU5WIGtleVxuICogICAgIFByb2Nlc3MtLT4+RW52OiByZXNvbHZlZCB2YWx1ZVxuICogICBlbmRcbiAqICAgRW52LS0+PkNsaWVudDogbWVyZ2VkIHZhbHVlXG4gKi9cbmNvbnN0IEVtcHR5VmFsdWUgPSBTeW1ib2woXCJFbnZpcm9ubWVudEVtcHR5XCIpO1xuY29uc3QgTW9kZWxTeW1ib2wgPSBTeW1ib2woXCJFbnZpcm9ubWVudE1vZGVsXCIpO1xuXG5leHBvcnQgY2xhc3MgRW52aXJvbm1lbnQ8VCBleHRlbmRzIG9iamVjdD4gZXh0ZW5kcyBPYmplY3RBY2N1bXVsYXRvcjxUPiB7XG4gIC8qKlxuICAgKiBAc3RhdGljXG4gICAqIEBwcm90ZWN0ZWRcbiAgICogQGRlc2NyaXB0aW9uIEEgZmFjdG9yeSBmdW5jdGlvbiBmb3IgY3JlYXRpbmcgRW52aXJvbm1lbnQgaW5zdGFuY2VzLlxuICAgKiBAc3VtbWFyeSBEZWZpbmVzIGhvdyBuZXcgaW5zdGFuY2VzIG9mIHRoZSBFbnZpcm9ubWVudCBjbGFzcyBzaG91bGQgYmUgY3JlYXRlZC5cbiAgICogQHJldHVybiB7RW52aXJvbm1lbnQ8YW55Pn0gQSBuZXcgaW5zdGFuY2Ugb2YgdGhlIEVudmlyb25tZW50IGNsYXNzLlxuICAgKi9cbiAgcHJvdGVjdGVkIHN0YXRpYyBmYWN0b3J5OiBFbnZpcm9ubWVudEZhY3Rvcnk8YW55LCBhbnk+ID1cbiAgICAoKTogRW52aXJvbm1lbnQ8YW55PiA9PiBuZXcgRW52aXJvbm1lbnQoKTtcblxuICAvKipcbiAgICogQHN0YXRpY1xuICAgKiBAcHJpdmF0ZVxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHNpbmdsZXRvbiBpbnN0YW5jZSBvZiB0aGUgRW52aXJvbm1lbnQgY2xhc3MuXG4gICAqIEB0eXBlIHtFbnZpcm9ubWVudDxhbnk+fVxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgX2luc3RhbmNlOiBFbnZpcm9ubWVudDxhbnk+O1xuXG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCBNb2RlbFN5bWJvbCwge1xuICAgICAgdmFsdWU6IHt9LFxuICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIHZhbHVlIGZyb20gdGhlIHJ1bnRpbWUgZW52aXJvbm1lbnQuXG4gICAqIEBzdW1tYXJ5IEhhbmRsZXMgYnJvd3NlciBhbmQgTm9kZS5qcyBlbnZpcm9ubWVudHMgYnkgbm9ybWFsaXppbmcga2V5cyBhbmQgcGFyc2luZyB2YWx1ZXMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrIC0gS2V5IHRvIHJlc29sdmUgZnJvbSB0aGUgZW52aXJvbm1lbnQuXG4gICAqIEByZXR1cm4ge3Vua25vd259IFZhbHVlIHJlc29sdmVkIGZyb20gdGhlIGVudmlyb25tZW50IG9yIGB1bmRlZmluZWRgIHdoZW4gYWJzZW50LlxuICAgKi9cbiAgcHJvdGVjdGVkIGZyb21FbnYoazogc3RyaW5nKSB7XG4gICAgbGV0IGVudjogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgaWYgKGlzQnJvd3NlcigpKSB7XG4gICAgICBlbnYgPVxuICAgICAgICAoXG4gICAgICAgICAgZ2xvYmFsVGhpcyBhcyB0eXBlb2YgZ2xvYmFsVGhpcyAmIHtcbiAgICAgICAgICAgIFtCcm93c2VyRW52S2V5XTogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICAgICAgICB9XG4gICAgICAgIClbQnJvd3NlckVudktleV0gfHwge307XG4gICAgfSBlbHNlIHtcbiAgICAgIGVudiA9IGdsb2JhbFRoaXMucHJvY2Vzcy5lbnY7XG4gICAgICBrID0gdG9FTlZGb3JtYXQoayk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnBhcnNlRW52VmFsdWUoZW52W2tdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29udmVydHMgc3RyaW5naWZpZWQgZW52aXJvbm1lbnQgdmFsdWVzIGludG8gbmF0aXZlIHR5cGVzLlxuICAgKiBAc3VtbWFyeSBJbnRlcnByZXRzIGJvb2xlYW5zIGFuZCBudW1iZXJzIHdoaWxlIGxlYXZpbmcgb3RoZXIgdHlwZXMgdW5jaGFuZ2VkLlxuICAgKiBAcGFyYW0ge3Vua25vd259IHZhbCAtIFJhdyB2YWx1ZSByZXRyaWV2ZWQgZnJvbSB0aGUgZW52aXJvbm1lbnQuXG4gICAqIEByZXR1cm4ge3Vua25vd259IFBhcnNlZCB2YWx1ZSBjb252ZXJ0ZWQgdG8gYm9vbGVhbiwgbnVtYmVyLCBvciBsZWZ0IGFzLWlzLlxuICAgKi9cbiAgcHJvdGVjdGVkIHBhcnNlRW52VmFsdWUodmFsOiB1bmtub3duKSB7XG4gICAgaWYgKHR5cGVvZiB2YWwgIT09IFwic3RyaW5nXCIpIHJldHVybiB2YWw7XG4gICAgaWYgKHZhbCA9PT0gXCJ0cnVlXCIpIHJldHVybiB0cnVlO1xuICAgIGlmICh2YWwgPT09IFwiZmFsc2VcIikgcmV0dXJuIGZhbHNlO1xuICAgIGNvbnN0IHJlc3VsdCA9IHBhcnNlRmxvYXQodmFsKTtcbiAgICBpZiAoIWlzTmFOKHJlc3VsdCkpIHJldHVybiByZXN1bHQ7XG4gICAgcmV0dXJuIHZhbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXhwYW5kcyBhbiBvYmplY3QgaW50byB0aGUgZW52aXJvbm1lbnQuXG4gICAqIEBzdW1tYXJ5IERlZmluZXMgbGF6eSBwcm9wZXJ0aWVzIHRoYXQgZmlyc3QgY29uc3VsdCBydW50aW1lIHZhcmlhYmxlcyBiZWZvcmUgZmFsbGluZyBiYWNrIHRvIHNlZWRlZCB2YWx1ZXMuXG4gICAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBvZiB0aGUgb2JqZWN0IGJlaW5nIGV4cGFuZGVkLlxuICAgKiBAcGFyYW0ge1Z9IHZhbHVlIC0gT2JqZWN0IHRvIGV4cG9zZSB0aHJvdWdoIGVudmlyb25tZW50IGdldHRlcnMgYW5kIHNldHRlcnMuXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgZXhwYW5kPFYgZXh0ZW5kcyBvYmplY3Q+KHZhbHVlOiBWKTogdm9pZCB7XG4gICAgT2JqZWN0LmVudHJpZXModmFsdWUpLmZvckVhY2goKFtrLCB2XSkgPT4ge1xuICAgICAgRW52aXJvbm1lbnQubWVyZ2VNb2RlbCgodGhpcyBhcyBhbnkpW01vZGVsU3ltYm9sXSwgaywgdik7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgaywge1xuICAgICAgICBnZXQ6ICgpID0+IHtcbiAgICAgICAgICBjb25zdCBmcm9tRW52ID0gdGhpcy5mcm9tRW52KGspO1xuICAgICAgICAgIGlmICh0eXBlb2YgZnJvbUVudiAhPT0gXCJ1bmRlZmluZWRcIikgcmV0dXJuIGZyb21FbnY7XG4gICAgICAgICAgaWYgKHYgJiYgdHlwZW9mIHYgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgIHJldHVybiBFbnZpcm9ubWVudC5idWlsZEVudlByb3h5KHYgYXMgYW55LCBba10pO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBJZiB0aGUgbW9kZWwgcHJvdmlkZXMgYW4gZW1wdHkgc3RyaW5nLCBtYXJrIHdpdGggRW1wdHlWYWx1ZSBzbyBpbnN0YW5jZSBwcm94eSBjYW4gcmV0dXJuIHVuZGVmaW5lZCB3aXRob3V0IGVuYWJsaW5nIGtleSBjb21wb3NpdGlvblxuICAgICAgICAgIGlmICh2ID09PSBcIlwiKSB7XG4gICAgICAgICAgICByZXR1cm4gRW1wdHlWYWx1ZSBhcyB1bmtub3duIGFzIFZba2V5b2YgVl07XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB2O1xuICAgICAgICB9LFxuICAgICAgICBzZXQ6ICh2YWw6IFZba2V5b2YgVl0pID0+IHtcbiAgICAgICAgICB2ID0gdmFsO1xuICAgICAgICB9LFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0dXJucyBhIHByb3h5IGVuZm9yY2luZyByZXF1aXJlZCBlbnZpcm9ubWVudCB2YXJpYWJsZXMuXG4gICAqIEBzdW1tYXJ5IEFjY2Vzc2luZyBhIHByb3BlcnR5IHRoYXQgcmVzb2x2ZXMgdG8gYHVuZGVmaW5lZGAgb3IgYW4gZW1wdHkgc3RyaW5nIHdoZW4gZGVjbGFyZWQgaW4gdGhlIG1vZGVsIHRocm93cyBhbiBlcnJvci5cbiAgICogQHJldHVybiB7dGhpc30gUHJveHkgb2YgdGhlIGVudmlyb25tZW50IGVuZm9yY2luZyByZXF1aXJlZCB2YXJpYWJsZXMuXG4gICAqL1xuICBvclRocm93KCk6IEVudmlyb25tZW50SW5zdGFuY2U8VD4ge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdGhpcy1hbGlhc1xuICAgIGNvbnN0IGJhc2UgPSB0aGlzO1xuICAgIGNvbnN0IG1vZGVsUm9vdCA9IChiYXNlIGFzIGFueSlbTW9kZWxTeW1ib2xdIGFzIFJlY29yZDxzdHJpbmcsIGFueT47XG4gICAgY29uc3QgYnVpbGRLZXkgPSAocGF0aDogc3RyaW5nW10pID0+XG4gICAgICBwYXRoLm1hcCgoc2VnbWVudCkgPT4gdG9FTlZGb3JtYXQoc2VnbWVudCkpLmpvaW4oRU5WX1BBVEhfREVMSU1JVEVSKTtcbiAgICBjb25zdCByZWFkUnVudGltZSA9IChrZXk6IHN0cmluZykgPT4gRW52aXJvbm1lbnQucmVhZFJ1bnRpbWVFbnYoa2V5KTtcbiAgICBjb25zdCBwYXJzZVJ1bnRpbWUgPSAocmF3OiB1bmtub3duKSA9PlxuICAgICAgdHlwZW9mIHJhdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHRoaXMucGFyc2VFbnZWYWx1ZShyYXcpIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgbWlzc2luZyA9IChrZXk6IHN0cmluZywgZW1wdHk6IGJvb2xlYW4gPSBmYWxzZSkgPT5cbiAgICAgIEVudmlyb25tZW50Lm1pc3NpbmdFbnZFcnJvcihrZXksIGVtcHR5KTtcblxuICAgIGNvbnN0IGNyZWF0ZU5lc3RlZFByb3h5ID0gKG1vZGVsOiBhbnksIHBhdGg6IHN0cmluZ1tdKTogYW55ID0+IHtcbiAgICAgIGNvbnN0IGhhbmRsZXI6IFByb3h5SGFuZGxlcjxhbnk+ID0ge1xuICAgICAgICBnZXQoX3RhcmdldCwgcHJvcCkge1xuICAgICAgICAgIGlmICh0eXBlb2YgcHJvcCAhPT0gXCJzdHJpbmdcIikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICBjb25zdCBuZXh0UGF0aCA9IFsuLi5wYXRoLCBwcm9wXTtcbiAgICAgICAgICBjb25zdCBlbnZLZXkgPSBidWlsZEtleShuZXh0UGF0aCk7XG4gICAgICAgICAgY29uc3QgcnVudGltZVJhdyA9IHJlYWRSdW50aW1lKGVudktleSk7XG4gICAgICAgICAgaWYgKHR5cGVvZiBydW50aW1lUmF3ID09PSBcInN0cmluZ1wiICYmIHJ1bnRpbWVSYXcubGVuZ3RoID09PSAwKVxuICAgICAgICAgICAgdGhyb3cgbWlzc2luZyhlbnZLZXksIHRydWUpO1xuICAgICAgICAgIGNvbnN0IHJ1bnRpbWVWYWx1ZSA9IHBhcnNlUnVudGltZShydW50aW1lUmF3KTtcbiAgICAgICAgICBpZiAodHlwZW9mIHJ1bnRpbWVWYWx1ZSAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBydW50aW1lVmFsdWUgPT09IFwic3RyaW5nXCIgJiYgcnVudGltZVZhbHVlLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgICAgdGhyb3cgbWlzc2luZyhlbnZLZXksIHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuIHJ1bnRpbWVWYWx1ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBoYXNQcm9wID1cbiAgICAgICAgICAgIG1vZGVsICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2RlbCwgcHJvcCk7XG4gICAgICAgICAgaWYgKCFoYXNQcm9wKSB0aHJvdyBtaXNzaW5nKGVudktleSk7XG5cbiAgICAgICAgICBjb25zdCBtb2RlbFZhbHVlID0gbW9kZWxbcHJvcF07XG4gICAgICAgICAgaWYgKHR5cGVvZiBtb2RlbFZhbHVlID09PSBcInVuZGVmaW5lZFwiKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgIGlmIChtb2RlbFZhbHVlID09PSBcIlwiKSB0aHJvdyBtaXNzaW5nKGVudktleSk7XG5cbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBtb2RlbFZhbHVlICYmXG4gICAgICAgICAgICB0eXBlb2YgbW9kZWxWYWx1ZSA9PT0gXCJvYmplY3RcIiAmJlxuICAgICAgICAgICAgIUFycmF5LmlzQXJyYXkobW9kZWxWYWx1ZSlcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVOZXN0ZWRQcm94eShtb2RlbFZhbHVlLCBuZXh0UGF0aCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIG1vZGVsVmFsdWU7XG4gICAgICAgIH0sXG4gICAgICAgIG93bktleXMoKSB7XG4gICAgICAgICAgcmV0dXJuIG1vZGVsID8gUmVmbGVjdC5vd25LZXlzKG1vZGVsKSA6IFtdO1xuICAgICAgICB9LFxuICAgICAgICBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoX3RhcmdldCwgcHJvcCkge1xuICAgICAgICAgIGlmICghbW9kZWwpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2RlbCwgcHJvcCkpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIH0gYXMgUHJvcGVydHlEZXNjcmlwdG9yO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9LFxuICAgICAgfTtcbiAgICAgIHJldHVybiBuZXcgUHJveHkoe30sIGhhbmRsZXIpO1xuICAgIH07XG5cbiAgICBjb25zdCBoYW5kbGVyOiBQcm94eUhhbmRsZXI8YW55PiA9IHtcbiAgICAgIGdldCh0YXJnZXQsIHByb3AsIHJlY2VpdmVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcHJvcCAhPT0gXCJzdHJpbmdcIilcbiAgICAgICAgICByZXR1cm4gUmVmbGVjdC5nZXQodGFyZ2V0LCBwcm9wLCByZWNlaXZlcik7XG4gICAgICAgIGNvbnN0IGhhc01vZGVsUHJvcCA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChcbiAgICAgICAgICBtb2RlbFJvb3QsXG4gICAgICAgICAgcHJvcFxuICAgICAgICApO1xuICAgICAgICBpZiAoIWhhc01vZGVsUHJvcCkgcmV0dXJuIFJlZmxlY3QuZ2V0KHRhcmdldCwgcHJvcCwgcmVjZWl2ZXIpO1xuXG4gICAgICAgIGNvbnN0IGVudktleSA9IGJ1aWxkS2V5KFtwcm9wXSk7XG4gICAgICAgIGNvbnN0IHJ1bnRpbWVSYXcgPSByZWFkUnVudGltZShlbnZLZXkpO1xuICAgICAgICBpZiAodHlwZW9mIHJ1bnRpbWVSYXcgPT09IFwic3RyaW5nXCIgJiYgcnVudGltZVJhdy5sZW5ndGggPT09IDApXG4gICAgICAgICAgdGhyb3cgbWlzc2luZyhlbnZLZXksIHRydWUpO1xuICAgICAgICBjb25zdCBydW50aW1lVmFsdWUgPSBwYXJzZVJ1bnRpbWUocnVudGltZVJhdyk7XG4gICAgICAgIGlmICh0eXBlb2YgcnVudGltZVZhbHVlICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBydW50aW1lVmFsdWUgPT09IFwic3RyaW5nXCIgJiYgcnVudGltZVZhbHVlLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHRocm93IG1pc3NpbmcoZW52S2V5LCB0cnVlKTtcbiAgICAgICAgICByZXR1cm4gcnVudGltZVZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbW9kZWxWYWx1ZSA9IG1vZGVsUm9vdFtwcm9wXTtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIG1vZGVsVmFsdWUgJiZcbiAgICAgICAgICB0eXBlb2YgbW9kZWxWYWx1ZSA9PT0gXCJvYmplY3RcIiAmJlxuICAgICAgICAgICFBcnJheS5pc0FycmF5KG1vZGVsVmFsdWUpXG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybiBjcmVhdGVOZXN0ZWRQcm94eShtb2RlbFZhbHVlLCBbcHJvcF0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBtb2RlbFZhbHVlID09PSBcInVuZGVmaW5lZFwiKVxuICAgICAgICAgIHJldHVybiBSZWZsZWN0LmdldCh0YXJnZXQsIHByb3AsIHJlY2VpdmVyKTtcblxuICAgICAgICBjb25zdCBhY3R1YWwgPSBSZWZsZWN0LmdldCh0YXJnZXQsIHByb3ApO1xuICAgICAgICBpZiAodHlwZW9mIGFjdHVhbCA9PT0gXCJ1bmRlZmluZWRcIiB8fCBhY3R1YWwgPT09IFwiXCIpXG4gICAgICAgICAgdGhyb3cgbWlzc2luZyhlbnZLZXksIGFjdHVhbCA9PT0gXCJcIik7XG5cbiAgICAgICAgcmV0dXJuIGFjdHVhbDtcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIHJldHVybiBuZXcgUHJveHkoYmFzZSwgaGFuZGxlcikgYXMgRW52aXJvbm1lbnRJbnN0YW5jZTxUPjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvdGVjdGVkXG4gICAqIEBzdGF0aWNcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBvciBjcmVhdGVzIHRoZSBzaW5nbGV0b24gaW5zdGFuY2Ugb2YgdGhlIEVudmlyb25tZW50IGNsYXNzLlxuICAgKiBAc3VtbWFyeSBFbnN1cmVzIG9ubHkgb25lIHtAbGluayBFbnZpcm9ubWVudH0gaW5zdGFuY2UgaXMgY3JlYXRlZCwgd3JhcHBpbmcgaXQgaW4gYSBwcm94eSB0byBjb21wb3NlIEVOViBrZXlzIG9uIGRlbWFuZC5cbiAgICogQHRlbXBsYXRlIEVcbiAgICogQHBhcmFtIHsuLi51bmtub3duW119IGFyZ3MgLSBBcmd1bWVudHMgZm9yd2FyZGVkIHRvIHRoZSBmYWN0b3J5IHdoZW4gaW5zdGFudGlhdGluZyB0aGUgc2luZ2xldG9uLlxuICAgKiBAcmV0dXJuIHtFfSBTaW5nbGV0b24gZW52aXJvbm1lbnQgaW5zdGFuY2UuXG4gICAqL1xuICBwcm90ZWN0ZWQgc3RhdGljIGluc3RhbmNlPEUgZXh0ZW5kcyBFbnZpcm9ubWVudDxhbnk+PihcbiAgICAuLi5hcmdzOiB1bmtub3duW11cbiAgKTogRSB7XG4gICAgaWYgKCFFbnZpcm9ubWVudC5faW5zdGFuY2UpIHtcbiAgICAgIGNvbnN0IGJhc2UgPSBFbnZpcm9ubWVudC5mYWN0b3J5KC4uLmFyZ3MpIGFzIEU7XG4gICAgICBjb25zdCBwcm94aWVkID0gbmV3IFByb3h5KGJhc2UgYXMgYW55LCB7XG4gICAgICAgIGdldCh0YXJnZXQsIHByb3AsIHJlY2VpdmVyKSB7XG4gICAgICAgICAgY29uc3QgdmFsdWUgPSBSZWZsZWN0LmdldCh0YXJnZXQsIHByb3AsIHJlY2VpdmVyKTtcbiAgICAgICAgICBpZiAodmFsdWUgPT09IEVtcHR5VmFsdWUpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgLy8gSWYgdGhlIHByb3BlcnR5IGV4aXN0cyBvbiB0aGUgaW5zdGFuY2UgYnV0IHJlc29sdmVzIHRvIHVuZGVmaW5lZCwgcmV0dXJuIHVuZGVmaW5lZCAobm8gcHJveHkpXG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgdHlwZW9mIHByb3AgPT09IFwic3RyaW5nXCIgJiZcbiAgICAgICAgICAgIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0YXJnZXQsIHByb3ApXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcInVuZGVmaW5lZFwiKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSBcInVuZGVmaW5lZFwiKSByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgaWYgKHR5cGVvZiBwcm9wID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAvLyBBdm9pZCBpbnRlcmZlcmluZyB3aXRoIGxvZ2dpbmcgY29uZmlnIGxvb2t1cHMgZm9yIG9wdGlvbmFsIGZpZWxkcyBsaWtlICdhcHAnXG4gICAgICAgICAgICBpZiAocHJvcCA9PT0gXCJhcHBcIikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHJldHVybiBFbnZpcm9ubWVudC5idWlsZEVudlByb3h5KHVuZGVmaW5lZCwgW3Byb3BdKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICBFbnZpcm9ubWVudC5faW5zdGFuY2UgPSBwcm94aWVkIGFzIGFueTtcbiAgICB9XG4gICAgcmV0dXJuIEVudmlyb25tZW50Ll9pbnN0YW5jZSBhcyBFO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdGF0aWNcbiAgICogQGRlc2NyaXB0aW9uIEFjY3VtdWxhdGVzIHRoZSBnaXZlbiB2YWx1ZSBpbnRvIHRoZSBlbnZpcm9ubWVudC5cbiAgICogQHN1bW1hcnkgQWRkcyBuZXcgcHJvcGVydGllcywgaGlkaW5nIHJhdyBkZXNjcmlwdG9ycyB0byBhdm9pZCBsZWFraW5nIGVudW1lcmF0aW9uIHNlbWFudGljcy5cbiAgICogQHRlbXBsYXRlIFRcbiAgICogQHRlbXBsYXRlIFZcbiAgICogQHBhcmFtIHtWfSB2YWx1ZSAtIE9iamVjdCB0byBtZXJnZSBpbnRvIHRoZSBlbnZpcm9ubWVudC5cbiAgICogQHJldHVybiB7RW52aXJvbm1lbnR9IFVwZGF0ZWQgZW52aXJvbm1lbnQgcmVmZXJlbmNlLlxuICAgKi9cbiAgc3RhdGljIGFjY3VtdWxhdGU8ViBleHRlbmRzIG9iamVjdCwgVEJhc2UgZXh0ZW5kcyBvYmplY3QgPSBvYmplY3Q+KFxuICAgIHZhbHVlOiBWXG4gICk6IEVudmlyb25tZW50SW5zdGFuY2U8VEJhc2UgJiBWPiB7XG4gICAgY29uc3QgaW5zdGFuY2UgPSBFbnZpcm9ubWVudC5pbnN0YW5jZTxFbnZpcm9ubWVudDxUQmFzZSAmIFY+PigpO1xuICAgIE9iamVjdC5rZXlzKGluc3RhbmNlIGFzIGFueSkuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICBjb25zdCBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihpbnN0YW5jZSBhcyBhbnksIGtleSk7XG4gICAgICBpZiAoZGVzYyAmJiBkZXNjLmNvbmZpZ3VyYWJsZSAmJiBkZXNjLmVudW1lcmFibGUpIHtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGluc3RhbmNlIGFzIGFueSwga2V5LCB7XG4gICAgICAgICAgLi4uZGVzYyxcbiAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGluc3RhbmNlLmFjY3VtdWxhdGUodmFsdWUpIGFzIHVua25vd24gYXMgRW52aXJvbm1lbnRJbnN0YW5jZTxcbiAgICAgIFRCYXNlICZcbiAgICAgICAgVlxuICAgID47XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIHZhbHVlIHVzaW5nIGEgZG90LXBhdGgga2V5IGZyb20gdGhlIGFjY3VtdWxhdGVkIGVudmlyb25tZW50LlxuICAgKiBAc3VtbWFyeSBEZWxlZ2F0ZXMgdG8gdGhlIHNpbmdsZXRvbiBpbnN0YW5jZSB0byBhY2Nlc3Mgc3RvcmVkIGNvbmZpZ3VyYXRpb24uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBLZXkgdG8gcmVzb2x2ZSBmcm9tIHRoZSBlbnZpcm9ubWVudCBzdG9yZS5cbiAgICogQHJldHVybiB7dW5rbm93bn0gU3RvcmVkIHZhbHVlIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHByb3ZpZGVkIGtleS5cbiAgICovXG4gIHN0YXRpYyBnZXQoa2V5OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gRW52aXJvbm1lbnQuX2luc3RhbmNlLmdldChrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBCdWlsZHMgYSBwcm94eSB0aGF0IGNvbXBvc2VzIGVudmlyb25tZW50IGtleXMgZm9yIG5lc3RlZCBwcm9wZXJ0aWVzLlxuICAgKiBAc3VtbWFyeSBBbGxvd3MgY2hhaW5lZCBwcm9wZXJ0eSBhY2Nlc3MgdG8gZW1pdCB1cHBlcmNhc2UgRU5WIGlkZW50aWZpZXJzIHdoaWxlIGhvbm9yaW5nIGV4aXN0aW5nIHJ1bnRpbWUgb3ZlcnJpZGVzLlxuICAgKiBAcGFyYW0ge2FueX0gY3VycmVudCAtIFNlZWQgbW9kZWwgc2VnbWVudCB1c2VkIHdoZW4gcHJvamVjdGluZyBuZXN0ZWQgc3RydWN0dXJlcy5cbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gcGF0aCAtIEFjY3VtdWxhdGVkIHBhdGggc2VnbWVudHMgbGVhZGluZyB0byB0aGUgcHJveHkuXG4gICAqIEByZXR1cm4ge2FueX0gUHJveHkgdGhhdCByZXNvbHZlcyBlbnZpcm9ubWVudCB2YWx1ZXMgb3IgY29tcG9zZXMgYWRkaXRpb25hbCBwcm94aWVzIGZvciBkZWVwZXIgcGF0aHMuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBidWlsZEVudlByb3h5KGN1cnJlbnQ6IGFueSwgcGF0aDogc3RyaW5nW10pOiBhbnkge1xuICAgIGNvbnN0IGJ1aWxkS2V5ID0gKHA6IHN0cmluZ1tdKSA9PlxuICAgICAgcC5tYXAoKHNlZykgPT4gdG9FTlZGb3JtYXQoc2VnKSkuam9pbihFTlZfUEFUSF9ERUxJTUlURVIpO1xuXG4gICAgLy8gSGVscGVyIHRvIHJlYWQgZnJvbSB0aGUgYWN0aXZlIGVudmlyb25tZW50IGdpdmVuIGEgY29tcG9zZWQga2V5XG4gICAgY29uc3QgcmVhZEVudiA9IChrZXk6IHN0cmluZyk6IHVua25vd24gPT4ge1xuICAgICAgcmV0dXJuIEVudmlyb25tZW50LnJlYWRSdW50aW1lRW52KGtleSk7XG4gICAgfTtcblxuICAgIGNvbnN0IGhhbmRsZXI6IFByb3h5SGFuZGxlcjxhbnk+ID0ge1xuICAgICAgZ2V0KF90YXJnZXQsIHByb3A6IHN0cmluZyB8IHN5bWJvbCkge1xuICAgICAgICBpZiAocHJvcCA9PT0gU3ltYm9sLnRvUHJpbWl0aXZlKSB7XG4gICAgICAgICAgcmV0dXJuICgpID0+IGJ1aWxkS2V5KHBhdGgpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwcm9wID09PSBcInRvU3RyaW5nXCIpIHtcbiAgICAgICAgICByZXR1cm4gKCkgPT4gYnVpbGRLZXkocGF0aCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHByb3AgPT09IFwidmFsdWVPZlwiKSB7XG4gICAgICAgICAgcmV0dXJuICgpID0+IGJ1aWxkS2V5KHBhdGgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgcHJvcCA9PT0gXCJzeW1ib2xcIikgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgICBjb25zdCBoYXNQcm9wID1cbiAgICAgICAgICAhIWN1cnJlbnQgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGN1cnJlbnQsIHByb3ApO1xuICAgICAgICBjb25zdCBuZXh0TW9kZWwgPSBoYXNQcm9wID8gKGN1cnJlbnQgYXMgYW55KVtwcm9wXSA6IHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgbmV4dFBhdGggPSBbLi4ucGF0aCwgcHJvcF07XG4gICAgICAgIGNvbnN0IGNvbXBvc2VkS2V5ID0gYnVpbGRLZXkobmV4dFBhdGgpO1xuXG4gICAgICAgIC8vIElmIGFuIEVOViB2YWx1ZSBleGlzdHMgZm9yIHRoaXMgcGF0aCwgcmV0dXJuIGl0IGRpcmVjdGx5XG4gICAgICAgIGNvbnN0IGVudlZhbHVlID0gcmVhZEVudihjb21wb3NlZEtleSk7XG4gICAgICAgIGlmICh0eXBlb2YgZW52VmFsdWUgIT09IFwidW5kZWZpbmVkXCIpIHJldHVybiBlbnZWYWx1ZTtcblxuICAgICAgICAvLyBPdGhlcndpc2UsIGlmIHRoZSBtb2RlbCBoYXMgYW4gb2JqZWN0IGF0IHRoaXMgcGF0aCwga2VlcCBkcmlsbGluZyB3aXRoIGEgcHJveHlcbiAgICAgICAgY29uc3QgaXNOZXh0T2JqZWN0ID0gbmV4dE1vZGVsICYmIHR5cGVvZiBuZXh0TW9kZWwgPT09IFwib2JqZWN0XCI7XG4gICAgICAgIGlmIChpc05leHRPYmplY3QpIHJldHVybiBFbnZpcm9ubWVudC5idWlsZEVudlByb3h5KG5leHRNb2RlbCwgbmV4dFBhdGgpO1xuXG4gICAgICAgIC8vIElmIHRoZSBtb2RlbCBtYXJrcyB0aGlzIGxlYWYgYXMgYW4gZW1wdHkgc3RyaW5nLCB0cmVhdCBhcyB1bmRlZmluZWQgKG5vIHByb3h5KVxuICAgICAgICBpZiAoaGFzUHJvcCAmJiBuZXh0TW9kZWwgPT09IFwiXCIpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIC8vIElmIHRoZSBtb2RlbCBleHBsaWNpdGx5IGNvbnRhaW5zIHRoZSBwcm9wZXJ0eSB3aXRoIHZhbHVlIHVuZGVmaW5lZCwgdHJlYXQgYXMgdW5kZWZpbmVkIChubyBwcm94eSlcbiAgICAgICAgaWYgKGhhc1Byb3AgJiYgdHlwZW9mIG5leHRNb2RlbCA9PT0gXCJ1bmRlZmluZWRcIikgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgICAvLyBBbHdheXMgcmV0dXJuIGEgcHJveHkgZm9yIGZ1cnRoZXIgcGF0aCBjb21wb3NpdGlvbiB3aGVuIG5vIEVOViB2YWx1ZTtcbiAgICAgICAgLy8gZG8gbm90IHN1cmZhY2UgcHJpbWl0aXZlIG1vZGVsIGRlZmF1bHRzIGhlcmUgKHRoaXMgQVBJIGlzIGZvciBrZXkgY29tcG9zaXRpb24pLlxuICAgICAgICByZXR1cm4gRW52aXJvbm1lbnQuYnVpbGRFbnZQcm94eSh1bmRlZmluZWQsIG5leHRQYXRoKTtcbiAgICAgIH0sXG4gICAgICBvd25LZXlzKCkge1xuICAgICAgICByZXR1cm4gY3VycmVudCA/IFJlZmxlY3Qub3duS2V5cyhjdXJyZW50KSA6IFtdO1xuICAgICAgfSxcbiAgICAgIGdldE93blByb3BlcnR5RGVzY3JpcHRvcihfdCwgcCkge1xuICAgICAgICBpZiAoIWN1cnJlbnQpIHJldHVybiB1bmRlZmluZWQgYXMgYW55O1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGN1cnJlbnQsIHApKSB7XG4gICAgICAgICAgcmV0dXJuIHsgZW51bWVyYWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gYXMgUHJvcGVydHlEZXNjcmlwdG9yO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQgYXMgYW55O1xuICAgICAgfSxcbiAgICB9O1xuXG4gICAgY29uc3QgdGFyZ2V0ID0ge30gYXMgYW55O1xuICAgIHJldHVybiBuZXcgUHJveHkodGFyZ2V0LCBoYW5kbGVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3RhdGljXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIGtleXMgb2YgdGhlIGVudmlyb25tZW50LCBvcHRpb25hbGx5IGNvbnZlcnRpbmcgdGhlbSB0byBFTlYgZm9ybWF0LlxuICAgKiBAc3VtbWFyeSBHZXRzIGFsbCBrZXlzIGluIHRoZSBlbnZpcm9ubWVudCwgd2l0aCBhbiBvcHRpb24gdG8gZm9ybWF0IHRoZW0gZm9yIGVudmlyb25tZW50IHZhcmlhYmxlcy5cbiAgICogQHBhcmFtIHtib29sZWFufSBbdG9FbnY9dHJ1ZV0gLSBXaGV0aGVyIHRvIGNvbnZlcnQgdGhlIGtleXMgdG8gRU5WIGZvcm1hdC5cbiAgICogQHJldHVybiB7c3RyaW5nW119IEFuIGFycmF5IG9mIGtleXMgZnJvbSB0aGUgZW52aXJvbm1lbnQuXG4gICAqL1xuICBzdGF0aWMga2V5cyh0b0VudjogYm9vbGVhbiA9IHRydWUpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIEVudmlyb25tZW50Lmluc3RhbmNlKClcbiAgICAgIC5rZXlzKClcbiAgICAgIC5tYXAoKGspID0+ICh0b0VudiA/IHRvRU5WRm9ybWF0KGspIDogaykpO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgbWVyZ2VNb2RlbChcbiAgICBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogYW55XG4gICkge1xuICAgIGlmICghbW9kZWwpIHJldHVybjtcbiAgICBpZiAodmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiICYmICFBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgY29uc3QgZXhpc3RpbmcgPSBtb2RlbFtrZXldO1xuICAgICAgY29uc3QgdGFyZ2V0ID1cbiAgICAgICAgZXhpc3RpbmcgJiYgdHlwZW9mIGV4aXN0aW5nID09PSBcIm9iamVjdFwiICYmICFBcnJheS5pc0FycmF5KGV4aXN0aW5nKVxuICAgICAgICAgID8gZXhpc3RpbmdcbiAgICAgICAgICA6IHt9O1xuICAgICAgbW9kZWxba2V5XSA9IHRhcmdldDtcbiAgICAgIE9iamVjdC5lbnRyaWVzKHZhbHVlKS5mb3JFYWNoKChbY2hpbGRLZXksIGNoaWxkVmFsdWVdKSA9PiB7XG4gICAgICAgIEVudmlyb25tZW50Lm1lcmdlTW9kZWwodGFyZ2V0LCBjaGlsZEtleSwgY2hpbGRWYWx1ZSk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbW9kZWxba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZFJ1bnRpbWVFbnYoa2V5OiBzdHJpbmcpOiB1bmtub3duIHtcbiAgICBpZiAoaXNCcm93c2VyKCkpIHtcbiAgICAgIGNvbnN0IGVudiA9IChcbiAgICAgICAgZ2xvYmFsVGhpcyBhcyB0eXBlb2YgZ2xvYmFsVGhpcyAmIHtcbiAgICAgICAgICBbQnJvd3NlckVudktleV0/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgICAgfVxuICAgICAgKVtCcm93c2VyRW52S2V5XTtcbiAgICAgIHJldHVybiBlbnYgPyBlbnZba2V5XSA6IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIChnbG9iYWxUaGlzIGFzIGFueSk/LnByb2Nlc3M/LmVudj8uW2tleV07XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBtaXNzaW5nRW52RXJyb3Ioa2V5OiBzdHJpbmcsIGVtcHR5OiBib29sZWFuKTogRXJyb3Ige1xuICAgIGNvbnN0IHN1ZmZpeCA9IGVtcHR5ID8gXCJhbiBlbXB0eSBzdHJpbmdcIiA6IFwidW5kZWZpbmVkXCI7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihcbiAgICAgIGBFbnZpcm9ubWVudCB2YXJpYWJsZSAke2tleX0gaXMgcmVxdWlyZWQgYnV0IHdhcyAke3N1ZmZpeH0uYFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU2luZ2xldG9uIGVudmlyb25tZW50IGluc3RhbmNlIHNlZWRlZCB3aXRoIGRlZmF1bHQgbG9nZ2luZyBjb25maWd1cmF0aW9uLlxuICogQHN1bW1hcnkgQ29tYmluZXMge0BsaW5rIERlZmF1bHRMb2dnaW5nQ29uZmlnfSB3aXRoIHJ1bnRpbWUgZW52aXJvbm1lbnQgdmFyaWFibGVzIHRvIHByb3ZpZGUgY29uc2lzdGVudCBsb2dnaW5nIGRlZmF1bHRzIGFjcm9zcyBwbGF0Zm9ybXMuXG4gKiBAY29uc3QgTG9nZ2VkRW52aXJvbm1lbnRcbiAqIEBtZW1iZXJPZiBtb2R1bGU6TG9nZ2luZ1xuICovXG5leHBvcnQgY29uc3QgTG9nZ2VkRW52aXJvbm1lbnQgPSBFbnZpcm9ubWVudC5hY2N1bXVsYXRlKFxuICBPYmplY3QuYXNzaWduKHt9LCBEZWZhdWx0TG9nZ2luZ0NvbmZpZywge1xuICAgIGVudjpcbiAgICAgIChpc0Jyb3dzZXIoKSAmJiAoZ2xvYmFsVGhpcyBhcyBhbnkpW0Jyb3dzZXJFbnZLZXldXG4gICAgICAgID8gKGdsb2JhbFRoaXMgYXMgYW55KVtCcm93c2VyRW52S2V5XVtcIk5PREVfRU5WXCJdXG4gICAgICAgIDogKGdsb2JhbFRoaXMgYXMgYW55KS5wcm9jZXNzLmVudltcIk5PREVfRU5WXCJdKSB8fCBcImRldmVsb3BtZW50XCIsXG4gIH0pXG4pO1xuIiwiaW1wb3J0IHtcbiAgTG9nZ2VyRmFjdG9yeSxcbiAgTG9nZ2luZ0NvbmZpZyxcbiAgTG9nZ2luZ0NvbnRleHQsXG4gIFN0cmluZ0xpa2UsXG4gIFRoZW1lLFxuICBUaGVtZU9wdGlvbixcbiAgVGhlbWVPcHRpb25CeUxvZ0xldmVsLFxuICBMb2dnZXIsXG59IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBDb2xvcml6ZU9wdGlvbnMsIHN0eWxlLCBTdHlsZWRTdHJpbmcgfSBmcm9tIFwic3R5bGVkLXN0cmluZy1idWlsZGVyXCI7XG5pbXBvcnQgeyBEZWZhdWx0VGhlbWUsIExvZ0xldmVsLCBOdW1lcmljTG9nTGV2ZWxzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBzZiB9IGZyb20gXCIuL3RleHRcIjtcbmltcG9ydCB7IExvZ2dlZEVudmlyb25tZW50IH0gZnJvbSBcIi4vZW52aXJvbm1lbnRcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQSBtaW5pbWFsIGxvZ2dlciBpbXBsZW1lbnRhdGlvbi5cbiAqIEBzdW1tYXJ5IE1pbmlMb2dnZXIgaXMgYSBsaWdodHdlaWdodCBsb2dnaW5nIGNsYXNzIHRoYXQgaW1wbGVtZW50cyB0aGUgTG9nZ2VyIGludGVyZmFjZS5cbiAqIEl0IHByb3ZpZGVzIGJhc2ljIGxvZ2dpbmcgZnVuY3Rpb25hbGl0eSB3aXRoIHN1cHBvcnQgZm9yIGRpZmZlcmVudCBsb2cgbGV2ZWxzLCB2ZXJib3NpdHksXG4gKiBjb250ZXh0LWF3YXJlIGxvZ2dpbmcsIGFuZCBjdXN0b21pemFibGUgZm9ybWF0dGluZy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjb250ZXh0IC0gVGhlIGNvbnRleHQgKHR5cGljYWxseSBjbGFzcyBuYW1lKSB0aGlzIGxvZ2dlciBpcyBhc3NvY2lhdGVkIHdpdGhcbiAqIEBwYXJhbSB7UGFydGlhbDxMb2dnaW5nQ29uZmlnPn0gY29uZiAtIE9wdGlvbmFsIGNvbmZpZ3VyYXRpb24gdG8gb3ZlcnJpZGUgZ2xvYmFsIHNldHRpbmdzXG4gKiBAY2xhc3MgTWluaUxvZ2dlclxuICogQGV4YW1wbGVcbiAqIC8vIENyZWF0ZSBhIG5ldyBsb2dnZXIgZm9yIGEgY2xhc3NcbiAqIGNvbnN0IGxvZ2dlciA9IG5ldyBNaW5pTG9nZ2VyKCdNeUNsYXNzJyk7XG4gKlxuICogLy8gTG9nIG1lc3NhZ2VzIGF0IGRpZmZlcmVudCBsZXZlbHNcbiAqIGxvZ2dlci5pbmZvKCdUaGlzIGlzIGFuIGluZm8gbWVzc2FnZScpO1xuICogbG9nZ2VyLmRlYnVnKCdUaGlzIGlzIGEgZGVidWcgbWVzc2FnZScpO1xuICogbG9nZ2VyLmVycm9yKCdTb21ldGhpbmcgd2VudCB3cm9uZycpO1xuICpcbiAqIC8vIENyZWF0ZSBhIGNoaWxkIGxvZ2dlciBmb3IgYSBzcGVjaWZpYyBtZXRob2RcbiAqIGNvbnN0IG1ldGhvZExvZ2dlciA9IGxvZ2dlci5mb3IoJ215TWV0aG9kJyk7XG4gKiBtZXRob2RMb2dnZXIudmVyYm9zZSgnRGV0YWlsZWQgaW5mb3JtYXRpb24nLCAyKTtcbiAqXG4gKiAvLyBMb2cgd2l0aCBjdXN0b20gY29uZmlndXJhdGlvblxuICogbG9nZ2VyLmZvcignc3BlY2lhbE1ldGhvZCcsIHsgc3R5bGU6IHRydWUgfSkuaW5mbygnU3R5bGVkIG1lc3NhZ2UnKTtcbiAqL1xuZXhwb3J0IGNsYXNzIE1pbmlMb2dnZXIgaW1wbGVtZW50cyBMb2dnZXIge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgY29udGV4dDogc3RyaW5nLFxuICAgIHByb3RlY3RlZCBjb25mPzogUGFydGlhbDxMb2dnaW5nQ29uZmlnPlxuICApIHt9XG5cbiAgcHJvdGVjdGVkIGNvbmZpZyhcbiAgICBrZXk6IGtleW9mIExvZ2dpbmdDb25maWdcbiAgKTogTG9nZ2luZ0NvbmZpZ1trZXlvZiBMb2dnaW5nQ29uZmlnXSB7XG4gICAgaWYgKHRoaXMuY29uZiAmJiBrZXkgaW4gdGhpcy5jb25mKSByZXR1cm4gdGhpcy5jb25mW2tleV07XG4gICAgcmV0dXJuIExvZ2dpbmcuZ2V0Q29uZmlnKClba2V5XTtcbiAgfVxuXG4gIGZvcihtZXRob2Q6IHN0cmluZyB8ICgoLi4uYXJnczogYW55W10pID0+IGFueSkpOiBMb2dnZXI7XG4gIGZvcihjb25maWc6IFBhcnRpYWw8TG9nZ2luZ0NvbmZpZz4pOiBMb2dnZXI7XG4gIGZvcihcbiAgICBtZXRob2Q6IHN0cmluZyB8ICgoLi4uYXJnczogYW55W10pID0+IGFueSkgfCBQYXJ0aWFsPExvZ2dpbmdDb25maWc+LFxuICAgIGNvbmZpZzogUGFydGlhbDxMb2dnaW5nQ29uZmlnPixcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBMb2dnZXI7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIGNoaWxkIGxvZ2dlciBmb3IgYSBzcGVjaWZpYyBtZXRob2Qgb3IgY29udGV4dFxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIGEgbmV3IGxvZ2dlciBpbnN0YW5jZSB3aXRoIHRoZSBjdXJyZW50IGNvbnRleHQgZXh0ZW5kZWQgYnkgdGhlIHNwZWNpZmllZCBtZXRob2QgbmFtZVxuICAgKiBAcGFyYW0ge3N0cmluZyB8IEZ1bmN0aW9ufSBtZXRob2QgLSBUaGUgbWV0aG9kIG5hbWUgb3IgZnVuY3Rpb24gdG8gY3JlYXRlIGEgbG9nZ2VyIGZvclxuICAgKiBAcGFyYW0ge1BhcnRpYWw8TG9nZ2luZ0NvbmZpZz59IGNvbmZpZyAtIE9wdGlvbmFsIGNvbmZpZ3VyYXRpb24gdG8gb3ZlcnJpZGUgc2V0dGluZ3NcbiAgICogQHBhcmFtIHsuLi5hbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIGxvZ2dlciBmYWN0b3J5XG4gICAqIEByZXR1cm4ge0xvZ2dlcn0gQSBuZXcgbG9nZ2VyIGluc3RhbmNlIGZvciB0aGUgc3BlY2lmaWVkIG1ldGhvZFxuICAgKi9cbiAgZm9yKFxuICAgIG1ldGhvZD86IHN0cmluZyB8ICgoLi4uYXJnczogYW55W10pID0+IGFueSkgfCBQYXJ0aWFsPExvZ2dpbmdDb25maWc+LFxuICAgIGNvbmZpZz86IFBhcnRpYWw8TG9nZ2luZ0NvbmZpZz4sXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IExvZ2dlciB7XG4gICAgaWYgKCFjb25maWcgJiYgdHlwZW9mIG1ldGhvZCA9PT0gXCJvYmplY3RcIikge1xuICAgICAgY29uZmlnID0gbWV0aG9kO1xuICAgICAgbWV0aG9kID0gdW5kZWZpbmVkO1xuICAgIH0gZWxzZSB7XG4gICAgICBtZXRob2QgPSBtZXRob2RcbiAgICAgICAgPyB0eXBlb2YgbWV0aG9kID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgPyBtZXRob2RcbiAgICAgICAgICA6IChtZXRob2QgYXMgYW55KS5uYW1lXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgUHJveHkodGhpcywge1xuICAgICAgZ2V0OiAodGFyZ2V0OiB0eXBlb2YgdGhpcywgcDogc3RyaW5nIHwgc3ltYm9sLCByZWNlaXZlcjogYW55KSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IFJlZmxlY3QuZ2V0KHRhcmdldCwgcCwgcmVjZWl2ZXIpO1xuICAgICAgICBpZiAocCA9PT0gXCJjb25maWdcIikge1xuICAgICAgICAgIHJldHVybiBuZXcgUHJveHkodGhpcy5jb25maWcsIHtcbiAgICAgICAgICAgIGdldDogKHRhcmdldDogdHlwZW9mIHRoaXMuY29uZmlnLCBwOiBzdHJpbmcgfCBzeW1ib2wpID0+IHtcbiAgICAgICAgICAgICAgaWYgKGNvbmZpZyAmJiBwIGluIGNvbmZpZylcbiAgICAgICAgICAgICAgICByZXR1cm4gY29uZmlnW3AgYXMga2V5b2YgTG9nZ2luZ0NvbmZpZ107XG4gICAgICAgICAgICAgIHJldHVybiBSZWZsZWN0LmdldCh0YXJnZXQsIHAsIHJlY2VpdmVyKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHAgPT09IFwiY29udGV4dFwiICYmIG1ldGhvZCkge1xuICAgICAgICAgIHJldHVybiBbcmVzdWx0LCBtZXRob2RdLmpvaW4oXCIuXCIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgZm9ybWF0dGVkIGxvZyBzdHJpbmdcbiAgICogQHN1bW1hcnkgR2VuZXJhdGVzIGEgbG9nIHN0cmluZyB3aXRoIHRpbWVzdGFtcCwgY29sb3JlZCBsb2cgbGV2ZWwsIGNvbnRleHQsIGFuZCBtZXNzYWdlXG4gICAqIEBwYXJhbSB7TG9nTGV2ZWx9IGxldmVsIC0gVGhlIGxvZyBsZXZlbCBmb3IgdGhpcyBtZXNzYWdlXG4gICAqIEBwYXJhbSB7U3RyaW5nTGlrZSB8IEVycm9yfSBtZXNzYWdlIC0gVGhlIG1lc3NhZ2UgdG8gbG9nIG9yIGFuIEVycm9yIG9iamVjdFxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2Vycm9yXSAtIE9wdGlvbmFsIGVycm9yIHRvIGV4dHJhY3Qgc3RhY2sgdHJhY2UgdG8gaW5jbHVkZSBpbiB0aGUgbG9nXG4gICAqIEByZXR1cm4ge3N0cmluZ30gQSBmb3JtYXR0ZWQgbG9nIHN0cmluZyB3aXRoIGFsbCBjb21wb25lbnRzXG4gICAqL1xuICBwcm90ZWN0ZWQgY3JlYXRlTG9nKFxuICAgIGxldmVsOiBMb2dMZXZlbCxcbiAgICBtZXNzYWdlOiBTdHJpbmdMaWtlIHwgRXJyb3IsXG4gICAgZXJyb3I/OiBFcnJvclxuICApOiBzdHJpbmcge1xuICAgIGNvbnN0IGxvZzogUmVjb3JkPFxuICAgICAgfCBcInRpbWVzdGFtcFwiXG4gICAgICB8IFwibGV2ZWxcIlxuICAgICAgfCBcImNvbnRleHRcIlxuICAgICAgfCBcImNvcnJlbGF0aW9uSWRcIlxuICAgICAgfCBcIm1lc3NhZ2VcIlxuICAgICAgfCBcInNlcGFyYXRvclwiXG4gICAgICB8IFwic3RhY2tcIlxuICAgICAgfCBcImFwcFwiLFxuICAgICAgc3RyaW5nXG4gICAgPiA9IHt9IGFzIGFueTtcbiAgICBjb25zdCBzdHlsZSA9IHRoaXMuY29uZmlnKFwic3R5bGVcIik7XG4gICAgY29uc3Qgc2VwYXJhdG9yID0gdGhpcy5jb25maWcoXCJzZXBhcmF0b3JcIik7XG4gICAgY29uc3QgYXBwID0gdGhpcy5jb25maWcoXCJhcHBcIik7XG4gICAgaWYgKGFwcClcbiAgICAgIGxvZy5hcHAgPSBzdHlsZVxuICAgICAgICA/IExvZ2dpbmcudGhlbWUoYXBwIGFzIHN0cmluZywgXCJhcHBcIiwgbGV2ZWwpXG4gICAgICAgIDogKGFwcCBhcyBzdHJpbmcpO1xuXG4gICAgaWYgKHNlcGFyYXRvcilcbiAgICAgIGxvZy5zZXBhcmF0b3IgPSBzdHlsZVxuICAgICAgICA/IExvZ2dpbmcudGhlbWUoc2VwYXJhdG9yIGFzIHN0cmluZywgXCJzZXBhcmF0b3JcIiwgbGV2ZWwpXG4gICAgICAgIDogKHNlcGFyYXRvciBhcyBzdHJpbmcpO1xuXG4gICAgaWYgKHRoaXMuY29uZmlnKFwidGltZXN0YW1wXCIpKSB7XG4gICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpO1xuICAgICAgY29uc3QgdGltZXN0YW1wID0gc3R5bGUgPyBMb2dnaW5nLnRoZW1lKGRhdGUsIFwidGltZXN0YW1wXCIsIGxldmVsKSA6IGRhdGU7XG4gICAgICBsb2cudGltZXN0YW1wID0gdGltZXN0YW1wO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbmZpZyhcImxvZ0xldmVsXCIpKSB7XG4gICAgICBjb25zdCBsdmw6IHN0cmluZyA9IHN0eWxlXG4gICAgICAgID8gTG9nZ2luZy50aGVtZShsZXZlbCwgXCJsb2dMZXZlbFwiLCBsZXZlbClcbiAgICAgICAgOiBsZXZlbDtcbiAgICAgIGxvZy5sZXZlbCA9IGx2bC50b1VwcGVyQ2FzZSgpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbmZpZyhcImNvbnRleHRcIikpIHtcbiAgICAgIGNvbnN0IGNvbnRleHQ6IHN0cmluZyA9IHN0eWxlXG4gICAgICAgID8gTG9nZ2luZy50aGVtZSh0aGlzLmNvbnRleHQsIFwiY2xhc3NcIiwgbGV2ZWwpXG4gICAgICAgIDogdGhpcy5jb250ZXh0O1xuICAgICAgbG9nLmNvbnRleHQgPSBjb250ZXh0O1xuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbmZpZyhcImNvcnJlbGF0aW9uSWRcIikpIHtcbiAgICAgIHtcbiAgICAgICAgY29uc3QgaWQ6IHN0cmluZyA9IHN0eWxlXG4gICAgICAgICAgPyBMb2dnaW5nLnRoZW1lKHRoaXMuY29uZmlnKFwiY29ycmVsYXRpb25JZFwiKSEudG9TdHJpbmcoKSwgXCJpZFwiLCBsZXZlbClcbiAgICAgICAgICA6IHRoaXMuY29uZmlnKFwiY29ycmVsYXRpb25JZFwiKSEudG9TdHJpbmcoKTtcbiAgICAgICAgbG9nLmNvcnJlbGF0aW9uSWQgPSBpZDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBtc2c6IHN0cmluZyA9IHN0eWxlXG4gICAgICA/IExvZ2dpbmcudGhlbWUoXG4gICAgICAgICAgdHlwZW9mIG1lc3NhZ2UgPT09IFwic3RyaW5nXCIgPyBtZXNzYWdlIDogKG1lc3NhZ2UgYXMgRXJyb3IpLm1lc3NhZ2UsXG4gICAgICAgICAgXCJtZXNzYWdlXCIsXG4gICAgICAgICAgbGV2ZWxcbiAgICAgICAgKVxuICAgICAgOiB0eXBlb2YgbWVzc2FnZSA9PT0gXCJzdHJpbmdcIlxuICAgICAgICA/IG1lc3NhZ2VcbiAgICAgICAgOiAobWVzc2FnZSBhcyBFcnJvcikubWVzc2FnZTtcbiAgICBsb2cubWVzc2FnZSA9IG1zZztcbiAgICBpZiAoZXJyb3IgfHwgbWVzc2FnZSBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICBjb25zdCBzdGFjayA9IHN0eWxlXG4gICAgICAgID8gTG9nZ2luZy50aGVtZShcbiAgICAgICAgICAgIChlcnJvcj8uc3RhY2sgfHwgKG1lc3NhZ2UgYXMgRXJyb3IpLnN0YWNrKSBhcyBzdHJpbmcsXG4gICAgICAgICAgICBcInN0YWNrXCIsXG4gICAgICAgICAgICBsZXZlbFxuICAgICAgICAgIClcbiAgICAgICAgOiBlcnJvcj8uc3RhY2sgfHwgXCJcIjtcbiAgICAgIGxvZy5zdGFjayA9IGAgfCAkeyhlcnJvciB8fCAobWVzc2FnZSBhcyBFcnJvcikpLm1lc3NhZ2V9IC0gU3RhY2sgdHJhY2U6XFxuJHtzdGFja31gO1xuICAgIH1cblxuICAgIHN3aXRjaCAodGhpcy5jb25maWcoXCJmb3JtYXRcIikpIHtcbiAgICAgIGNhc2UgXCJqc29uXCI6XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShsb2cpO1xuICAgICAgY2FzZSBcInJhd1wiOlxuICAgICAgICByZXR1cm4gKHRoaXMuY29uZmlnKFwicGF0dGVyblwiKSBhcyBzdHJpbmcpXG4gICAgICAgICAgLnNwbGl0KFwiIFwiKVxuICAgICAgICAgIC5tYXAoKHMpID0+IHtcbiAgICAgICAgICAgIGlmICghcy5tYXRjaCgvXFx7Lio/fS9nKSkgcmV0dXJuIHM7XG4gICAgICAgICAgICBjb25zdCBmb3JtYXR0ZWRTID0gc2YocywgbG9nKTtcbiAgICAgICAgICAgIGlmIChmb3JtYXR0ZWRTICE9PSBzKSByZXR1cm4gZm9ybWF0dGVkUztcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAuZmlsdGVyKChzKSA9PiBzKVxuICAgICAgICAgIC5qb2luKFwiIFwiKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgbG9nZ2luZyBmb3JtYXQ6ICR7dGhpcy5jb25maWcoXCJmb3JtYXRcIil9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMb2dzIGEgbWVzc2FnZSB3aXRoIHRoZSBzcGVjaWZpZWQgbG9nIGxldmVsXG4gICAqIEBzdW1tYXJ5IENoZWNrcyBpZiB0aGUgbWVzc2FnZSBzaG91bGQgYmUgbG9nZ2VkIGJhc2VkIG9uIHRoZSBjdXJyZW50IGxvZyBsZXZlbCxcbiAgICogdGhlbiB1c2VzIHRoZSBhcHByb3ByaWF0ZSBjb25zb2xlIG1ldGhvZCB0byBvdXRwdXQgdGhlIGZvcm1hdHRlZCBsb2dcbiAgICogQHBhcmFtIHtMb2dMZXZlbH0gbGV2ZWwgLSBUaGUgbG9nIGxldmVsIG9mIHRoZSBtZXNzYWdlXG4gICAqIEBwYXJhbSB7U3RyaW5nTGlrZSB8IEVycm9yfSBtc2cgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWQgb3IgYW4gRXJyb3Igb2JqZWN0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbZXJyb3JdIC0gT3B0aW9uYWwgc3RhY2sgdHJhY2UgdG8gaW5jbHVkZSBpbiB0aGUgbG9nXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBwcm90ZWN0ZWQgbG9nKGxldmVsOiBMb2dMZXZlbCwgbXNnOiBTdHJpbmdMaWtlIHwgRXJyb3IsIGVycm9yPzogRXJyb3IpOiB2b2lkIHtcbiAgICBjb25zdCBjb25mTHZsID0gdGhpcy5jb25maWcoXCJsZXZlbFwiKSBhcyBMb2dMZXZlbDtcbiAgICBpZiAoTnVtZXJpY0xvZ0xldmVsc1tjb25mTHZsXSA8IE51bWVyaWNMb2dMZXZlbHNbbGV2ZWxdKSByZXR1cm47XG4gICAgbGV0IG1ldGhvZDtcbiAgICBzd2l0Y2ggKGxldmVsKSB7XG4gICAgICBjYXNlIExvZ0xldmVsLmJlbmNobWFyazpcbiAgICAgICAgbWV0aG9kID0gY29uc29sZS5sb2c7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBMb2dMZXZlbC5pbmZvOlxuICAgICAgICBtZXRob2QgPSBjb25zb2xlLmxvZztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIExvZ0xldmVsLnZlcmJvc2U6XG4gICAgICBjYXNlIExvZ0xldmVsLmRlYnVnOlxuICAgICAgICBtZXRob2QgPSBjb25zb2xlLmRlYnVnO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTG9nTGV2ZWwuZXJyb3I6XG4gICAgICAgIG1ldGhvZCA9IGNvbnNvbGUuZXJyb3I7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBMb2dMZXZlbC50cmFjZTpcbiAgICAgICAgbWV0aG9kID0gY29uc29sZS50cmFjZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIExvZ0xldmVsLnNpbGx5OlxuICAgICAgICBtZXRob2QgPSBjb25zb2xlLnRyYWNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgbG9nIGxldmVsXCIpO1xuICAgIH1cbiAgICBtZXRob2QodGhpcy5jcmVhdGVMb2cobGV2ZWwsIG1zZywgZXJyb3IpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTG9ncyBhIG1lc3NhZ2UgYXQgdGhlIGJlbmNobWFyayBsZXZlbFxuICAgKiBAc3VtbWFyeSBMb2dzIGEgbWVzc2FnZSBhdCB0aGUgYmVuY2htYXJrIGxldmVsIGlmIHRoZSBjdXJyZW50IHZlcmJvc2l0eSBzZXR0aW5nIGFsbG93cyBpdFxuICAgKiBAcGFyYW0ge1N0cmluZ0xpa2V9IG1zZyAtIFRoZSBtZXNzYWdlIHRvIGJlIGxvZ2dlZFxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgYmVuY2htYXJrKG1zZzogU3RyaW5nTGlrZSk6IHZvaWQge1xuICAgIHRoaXMubG9nKExvZ0xldmVsLmJlbmNobWFyaywgbXNnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTG9ncyBhIG1lc3NhZ2UgYXQgdGhlIHNpbGx5IGxldmVsXG4gICAqIEBzdW1tYXJ5IExvZ3MgYSBtZXNzYWdlIGF0IHRoZSBzaWxseSBsZXZlbCBpZiB0aGUgY3VycmVudCB2ZXJib3NpdHkgc2V0dGluZyBhbGxvd3MgaXRcbiAgICogQHBhcmFtIHtTdHJpbmdMaWtlfSBtc2cgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWRcbiAgICogQHBhcmFtIHtudW1iZXJ9IFt2ZXJib3NpdHk9MF0gLSBUaGUgdmVyYm9zaXR5IGxldmVsIG9mIHRoZSBtZXNzYWdlXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBzaWxseShtc2c6IFN0cmluZ0xpa2UsIHZlcmJvc2l0eTogbnVtYmVyID0gMCk6IHZvaWQge1xuICAgIGlmICgodGhpcy5jb25maWcoXCJ2ZXJib3NlXCIpIGFzIG51bWJlcikgPj0gdmVyYm9zaXR5KVxuICAgICAgdGhpcy5sb2coTG9nTGV2ZWwudmVyYm9zZSwgbXNnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTG9ncyBhIG1lc3NhZ2UgYXQgdGhlIHZlcmJvc2UgbGV2ZWxcbiAgICogQHN1bW1hcnkgTG9ncyBhIG1lc3NhZ2UgYXQgdGhlIHZlcmJvc2UgbGV2ZWwgaWYgdGhlIGN1cnJlbnQgdmVyYm9zaXR5IHNldHRpbmcgYWxsb3dzIGl0XG4gICAqIEBwYXJhbSB7U3RyaW5nTGlrZX0gbXNnIC0gVGhlIG1lc3NhZ2UgdG8gYmUgbG9nZ2VkXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbdmVyYm9zaXR5PTBdIC0gVGhlIHZlcmJvc2l0eSBsZXZlbCBvZiB0aGUgbWVzc2FnZVxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgdmVyYm9zZShtc2c6IFN0cmluZ0xpa2UsIHZlcmJvc2l0eTogbnVtYmVyID0gMCk6IHZvaWQge1xuICAgIGlmICgodGhpcy5jb25maWcoXCJ2ZXJib3NlXCIpIGFzIG51bWJlcikgPj0gdmVyYm9zaXR5KVxuICAgICAgdGhpcy5sb2coTG9nTGV2ZWwudmVyYm9zZSwgbXNnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTG9ncyBhIG1lc3NhZ2UgYXQgdGhlIGluZm8gbGV2ZWxcbiAgICogQHN1bW1hcnkgTG9ncyBhIG1lc3NhZ2UgYXQgdGhlIGluZm8gbGV2ZWwgZm9yIGdlbmVyYWwgYXBwbGljYXRpb24gaW5mb3JtYXRpb25cbiAgICogQHBhcmFtIHtTdHJpbmdMaWtlfSBtc2cgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWRcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIGluZm8obXNnOiBTdHJpbmdMaWtlKTogdm9pZCB7XG4gICAgdGhpcy5sb2coTG9nTGV2ZWwuaW5mbywgbXNnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTG9ncyBhIG1lc3NhZ2UgYXQgdGhlIGRlYnVnIGxldmVsXG4gICAqIEBzdW1tYXJ5IExvZ3MgYSBtZXNzYWdlIGF0IHRoZSBkZWJ1ZyBsZXZlbCBmb3IgZGV0YWlsZWQgdHJvdWJsZXNob290aW5nIGluZm9ybWF0aW9uXG4gICAqIEBwYXJhbSB7U3RyaW5nTGlrZX0gbXNnIC0gVGhlIG1lc3NhZ2UgdG8gYmUgbG9nZ2VkXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBkZWJ1Zyhtc2c6IFN0cmluZ0xpa2UpOiB2b2lkIHtcbiAgICB0aGlzLmxvZyhMb2dMZXZlbC5kZWJ1ZywgbXNnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTG9ncyBhIG1lc3NhZ2UgYXQgdGhlIGVycm9yIGxldmVsXG4gICAqIEBzdW1tYXJ5IExvZ3MgYSBtZXNzYWdlIGF0IHRoZSBlcnJvciBsZXZlbCBmb3IgZXJyb3JzIGFuZCBleGNlcHRpb25zXG4gICAqIEBwYXJhbSB7U3RyaW5nTGlrZSB8IEVycm9yfSBtc2cgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWQgb3IgYW4gRXJyb3Igb2JqZWN0XG4gICAqIEBwYXJhbSBlXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBlcnJvcihtc2c6IFN0cmluZ0xpa2UgfCBFcnJvciwgZT86IEVycm9yKTogdm9pZCB7XG4gICAgdGhpcy5sb2coTG9nTGV2ZWwuZXJyb3IsIG1zZywgZSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExvZ3MgYSBtZXNzYWdlIGF0IHRoZSBlcnJvciBsZXZlbFxuICAgKiBAc3VtbWFyeSBMb2dzIGEgbWVzc2FnZSBhdCB0aGUgZXJyb3IgbGV2ZWwgZm9yIGVycm9ycyBhbmQgZXhjZXB0aW9uc1xuICAgKiBAcGFyYW0ge1N0cmluZ0xpa2V9IG1zZyAtIFRoZSBtZXNzYWdlIHRvIGJlIGxvZ2dlZCBvciBhbiBFcnJvciBvYmplY3RcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIHdhcm4obXNnOiBTdHJpbmdMaWtlKTogdm9pZCB7XG4gICAgdGhpcy5sb2coTG9nTGV2ZWwud2FybiwgbXNnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTG9ncyBhIG1lc3NhZ2UgYXQgdGhlIGVycm9yIGxldmVsXG4gICAqIEBzdW1tYXJ5IExvZ3MgYSBtZXNzYWdlIGF0IHRoZSBlcnJvciBsZXZlbCBmb3IgZXJyb3JzIGFuZCBleGNlcHRpb25zXG4gICAqIEBwYXJhbSB7U3RyaW5nTGlrZX0gbXNnIC0gVGhlIG1lc3NhZ2UgdG8gYmUgbG9nZ2VkIG9yIGFuIEVycm9yIG9iamVjdFxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgdHJhY2UobXNnOiBTdHJpbmdMaWtlKTogdm9pZCB7XG4gICAgdGhpcy5sb2coTG9nTGV2ZWwudHJhY2UsIG1zZyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgdGhlIGxvZ2dlciBjb25maWd1cmF0aW9uXG4gICAqIEBzdW1tYXJ5IE1lcmdlcyB0aGUgcHJvdmlkZWQgY29uZmlndXJhdGlvbiB3aXRoIHRoZSBleGlzdGluZyBjb25maWd1cmF0aW9uXG4gICAqIEBwYXJhbSB7UGFydGlhbDxMb2dnaW5nQ29uZmlnPn0gY29uZmlnIC0gVGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyB0byBhcHBseVxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgc2V0Q29uZmlnKGNvbmZpZzogUGFydGlhbDxMb2dnaW5nQ29uZmlnPik6IHZvaWQge1xuICAgIHRoaXMuY29uZiA9IHsgLi4uKHRoaXMuY29uZiB8fCB7fSksIC4uLmNvbmZpZyB9O1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEEgc3RhdGljIGNsYXNzIGZvciBtYW5hZ2luZyBsb2dnaW5nIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IFRoZSBMb2dnaW5nIGNsYXNzIHByb3ZpZGVzIGEgY2VudHJhbGl6ZWQgbG9nZ2luZyBtZWNoYW5pc20gd2l0aCBzdXBwb3J0IGZvclxuICogZGlmZmVyZW50IGxvZyBsZXZlbHMsIHZlcmJvc2l0eSwgYW5kIHN0eWxpbmcuIEl0IHVzZXMgYSBzaW5nbGV0b24gcGF0dGVybiB0byBtYWludGFpbiBhIGdsb2JhbFxuICogbG9nZ2VyIGluc3RhbmNlIGFuZCBhbGxvd3MgY3JlYXRpbmcgc3BlY2lmaWMgbG9nZ2VycyBmb3IgZGlmZmVyZW50IGNsYXNzZXMgYW5kIG1ldGhvZHMuXG4gKiBAY2xhc3MgTG9nZ2luZ1xuICogQGV4YW1wbGVcbiAqIC8vIFNldCBnbG9iYWwgY29uZmlndXJhdGlvblxuICogTG9nZ2luZy5zZXRDb25maWcoeyBsZXZlbDogTG9nTGV2ZWwuZGVidWcsIHN0eWxlOiB0cnVlIH0pO1xuICpcbiAqIC8vIEdldCBhIGxvZ2dlciBmb3IgYSBzcGVjaWZpYyBjbGFzc1xuICogY29uc3QgbG9nZ2VyID0gTG9nZ2luZy5mb3IoJ015Q2xhc3MnKTtcbiAqXG4gKiAvLyBMb2cgbWVzc2FnZXMgYXQgZGlmZmVyZW50IGxldmVsc1xuICogbG9nZ2VyLmluZm8oJ0FwcGxpY2F0aW9uIHN0YXJ0ZWQnKTtcbiAqIGxvZ2dlci5kZWJ1ZygnUHJvY2Vzc2luZyBkYXRhLi4uJyk7XG4gKlxuICogLy8gTG9nIHdpdGggY29udGV4dFxuICogY29uc3QgbWV0aG9kTG9nZ2VyID0gTG9nZ2luZy5mb3IoJ015Q2xhc3MubXlNZXRob2QnKTtcbiAqIG1ldGhvZExvZ2dlci52ZXJib3NlKCdEZXRhaWxlZCBvcGVyYXRpb24gaW5mb3JtYXRpb24nLCAxKTtcbiAqXG4gKiAvLyBMb2cgZXJyb3JzXG4gKiB0cnkge1xuICogICAvLyBzb21lIG9wZXJhdGlvblxuICogfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgbG9nZ2VyLmVycm9yKGVycm9yKTtcbiAqIH1cbiAqIEBtZXJtYWlkXG4gKiBjbGFzc0RpYWdyYW1cbiAqICAgY2xhc3MgTG9nZ2VyIHtcbiAqICAgICA8PGludGVyZmFjZT4+XG4gKiAgICAgK2ZvcihtZXRob2QsIGNvbmZpZywgLi4uYXJncylcbiAqICAgICArc2lsbHkobXNnLCB2ZXJib3NpdHkpXG4gKiAgICAgK3ZlcmJvc2UobXNnLCB2ZXJib3NpdHkpXG4gKiAgICAgK2luZm8obXNnKVxuICogICAgICtkZWJ1Zyhtc2cpXG4gKiAgICAgK2Vycm9yKG1zZylcbiAqICAgICArc2V0Q29uZmlnKGNvbmZpZylcbiAqICAgfVxuICpcbiAqICAgY2xhc3MgTG9nZ2luZyB7XG4gKiAgICAgLWdsb2JhbDogTG9nZ2VyXG4gKiAgICAgLV9mYWN0b3J5OiBMb2dnZXJGYWN0b3J5XG4gKiAgICAgLV9jb25maWc6IExvZ2dpbmdDb25maWdcbiAqICAgICArc2V0RmFjdG9yeShmYWN0b3J5KVxuICogICAgICtzZXRDb25maWcoY29uZmlnKVxuICogICAgICtnZXRDb25maWcoKVxuICogICAgICtnZXQoKVxuICogICAgICt2ZXJib3NlKG1zZywgdmVyYm9zaXR5KVxuICogICAgICtpbmZvKG1zZylcbiAqICAgICArZGVidWcobXNnKVxuICogICAgICtzaWxseShtc2cpXG4gKiAgICAgK2Vycm9yKG1zZylcbiAqICAgICArZm9yKG9iamVjdCwgY29uZmlnLCAuLi5hcmdzKVxuICogICAgICtiZWNhdXNlKHJlYXNvbiwgaWQpXG4gKiAgICAgK3RoZW1lKHRleHQsIHR5cGUsIGxvZ2dlckxldmVsLCB0ZW1wbGF0ZSlcbiAqICAgfVxuICpcbiAqICAgY2xhc3MgTWluaUxvZ2dlciB7XG4gKiAgICAgK2NvbnN0cnVjdG9yKGNvbnRleHQsIGNvbmY/KVxuICogICB9XG4gKlxuICogICBMb2dnaW5nIC4uPiBMb2dnZXIgOiBjcmVhdGVzXG4gKiAgIExvZ2dpbmcgLi4+IE1pbmlMb2dnZXIgOiBjcmVhdGVzIGJ5IGRlZmF1bHRcbiAqL1xuZXhwb3J0IGNsYXNzIExvZ2dpbmcge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBnbG9iYWwgbG9nZ2VyIGluc3RhbmNlXG4gICAqIEBzdW1tYXJ5IEEgc2luZ2xldG9uIGluc3RhbmNlIG9mIExvZ2dlciB1c2VkIGZvciBnbG9iYWwgbG9nZ2luZ1xuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZ2xvYmFsPzogTG9nZ2VyO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRmFjdG9yeSBmdW5jdGlvbiBmb3IgY3JlYXRpbmcgbG9nZ2VyIGluc3RhbmNlc1xuICAgKiBAc3VtbWFyeSBBIGZ1bmN0aW9uIHRoYXQgY3JlYXRlcyBuZXcgTG9nZ2VyIGluc3RhbmNlcy4gQnkgZGVmYXVsdCwgaXQgY3JlYXRlcyBhIE1pbmlMb2dnZXIuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBfZmFjdG9yeTogTG9nZ2VyRmFjdG9yeSA9IChcbiAgICBvYmplY3Q6IHN0cmluZyxcbiAgICBjb25maWc/OiBQYXJ0aWFsPExvZ2dpbmdDb25maWc+XG4gICkgPT4ge1xuICAgIHJldHVybiBuZXcgTWluaUxvZ2dlcihvYmplY3QsIGNvbmZpZyk7XG4gIH07XG5cbiAgcHJpdmF0ZSBzdGF0aWMgX2NvbmZpZzogdHlwZW9mIExvZ2dlZEVudmlyb25tZW50ID0gTG9nZ2VkRW52aXJvbm1lbnQ7XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBmYWN0b3J5IGZ1bmN0aW9uIGZvciBjcmVhdGluZyBsb2dnZXIgaW5zdGFuY2VzXG4gICAqIEBzdW1tYXJ5IEFsbG93cyBjdXN0b21pemluZyBob3cgbG9nZ2VyIGluc3RhbmNlcyBhcmUgY3JlYXRlZFxuICAgKiBAcGFyYW0ge0xvZ2dlckZhY3Rvcnl9IGZhY3RvcnkgLSBUaGUgZmFjdG9yeSBmdW5jdGlvbiB0byB1c2UgZm9yIGNyZWF0aW5nIGxvZ2dlcnNcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIHN0YXRpYyBzZXRGYWN0b3J5KGZhY3Rvcnk6IExvZ2dlckZhY3RvcnkpIHtcbiAgICBMb2dnaW5nLl9mYWN0b3J5ID0gZmFjdG9yeTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyB0aGUgZ2xvYmFsIGxvZ2dpbmcgY29uZmlndXJhdGlvblxuICAgKiBAc3VtbWFyeSBBbGxvd3MgdXBkYXRpbmcgdGhlIGdsb2JhbCBsb2dnaW5nIGNvbmZpZ3VyYXRpb24gd2l0aCBuZXcgc2V0dGluZ3NcbiAgICogQHBhcmFtIHtQYXJ0aWFsPExvZ2dpbmdDb25maWc+fSBjb25maWcgLSBUaGUgY29uZmlndXJhdGlvbiBvcHRpb25zIHRvIGFwcGx5XG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBzdGF0aWMgc2V0Q29uZmlnKGNvbmZpZzogUGFydGlhbDxMb2dnaW5nQ29uZmlnPik6IHZvaWQge1xuICAgIE9iamVjdC5lbnRyaWVzKGNvbmZpZykuZm9yRWFjaCgoW2ssIHZdKSA9PiB7XG4gICAgICAodGhpcy5fY29uZmlnIGFzIGFueSlba10gPSB2IGFzIGFueTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyBhIGNvcHkgb2YgdGhlIGN1cnJlbnQgZ2xvYmFsIGxvZ2dpbmcgY29uZmlndXJhdGlvblxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIGEgY29weSBvZiB0aGUgY3VycmVudCBnbG9iYWwgbG9nZ2luZyBjb25maWd1cmF0aW9uXG4gICAqIEByZXR1cm4ge0xvZ2dpbmdDb25maWd9IEEgY29weSBvZiB0aGUgY3VycmVudCBjb25maWd1cmF0aW9uXG4gICAqL1xuICBzdGF0aWMgZ2V0Q29uZmlnKCk6IHR5cGVvZiBMb2dnZWRFbnZpcm9ubWVudCB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIG9yIGNyZWF0ZXMgdGhlIGdsb2JhbCBsb2dnZXIgaW5zdGFuY2UuXG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIGV4aXN0aW5nIGdsb2JhbCBsb2dnZXIgb3IgY3JlYXRlcyBhIG5ldyBvbmUgaWYgaXQgZG9lc24ndCBleGlzdC5cbiAgICpcbiAgICogQHJldHVybiBUaGUgZ2xvYmFsIFZlcmJvc2l0eUxvZ2dlciBpbnN0YW5jZS5cbiAgICovXG4gIHN0YXRpYyBnZXQoKTogTG9nZ2VyIHtcbiAgICB0aGlzLmdsb2JhbCA9IHRoaXMuZ2xvYmFsID8gdGhpcy5nbG9iYWwgOiB0aGlzLl9mYWN0b3J5KFwiTG9nZ2luZ1wiKTtcbiAgICByZXR1cm4gdGhpcy5nbG9iYWw7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExvZ3MgYSB2ZXJib3NlIG1lc3NhZ2UuXG4gICAqIEBzdW1tYXJ5IERlbGVnYXRlcyB0aGUgdmVyYm9zZSBsb2dnaW5nIHRvIHRoZSBnbG9iYWwgbG9nZ2VyIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0gbXNnIC0gVGhlIG1lc3NhZ2UgdG8gYmUgbG9nZ2VkLlxuICAgKiBAcGFyYW0gdmVyYm9zaXR5IC0gVGhlIHZlcmJvc2l0eSBsZXZlbCBvZiB0aGUgbWVzc2FnZSAoZGVmYXVsdDogMCkuXG4gICAqL1xuICBzdGF0aWMgdmVyYm9zZShtc2c6IFN0cmluZ0xpa2UsIHZlcmJvc2l0eTogbnVtYmVyID0gMCk6IHZvaWQge1xuICAgIHJldHVybiB0aGlzLmdldCgpLnZlcmJvc2UobXNnLCB2ZXJib3NpdHkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMb2dzIGFuIGluZm8gbWVzc2FnZS5cbiAgICogQHN1bW1hcnkgRGVsZWdhdGVzIHRoZSBpbmZvIGxvZ2dpbmcgdG8gdGhlIGdsb2JhbCBsb2dnZXIgaW5zdGFuY2UuXG4gICAqXG4gICAqIEBwYXJhbSBtc2cgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWQuXG4gICAqL1xuICBzdGF0aWMgaW5mbyhtc2c6IFN0cmluZ0xpa2UpOiB2b2lkIHtcbiAgICByZXR1cm4gdGhpcy5nZXQoKS5pbmZvKG1zZyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExvZ3MgYW4gaW5mbyBtZXNzYWdlLlxuICAgKiBAc3VtbWFyeSBEZWxlZ2F0ZXMgdGhlIGluZm8gbG9nZ2luZyB0byB0aGUgZ2xvYmFsIGxvZ2dlciBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIG1zZyAtIFRoZSBtZXNzYWdlIHRvIGJlIGxvZ2dlZC5cbiAgICovXG4gIHN0YXRpYyB0cmFjZShtc2c6IFN0cmluZ0xpa2UpOiB2b2lkIHtcbiAgICByZXR1cm4gdGhpcy5nZXQoKS50cmFjZShtc2cpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMb2dzIGEgZGVidWcgbWVzc2FnZS5cbiAgICogQHN1bW1hcnkgRGVsZWdhdGVzIHRoZSBkZWJ1ZyBsb2dnaW5nIHRvIHRoZSBnbG9iYWwgbG9nZ2VyIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0gbXNnIC0gVGhlIG1lc3NhZ2UgdG8gYmUgbG9nZ2VkLlxuICAgKi9cbiAgc3RhdGljIGRlYnVnKG1zZzogU3RyaW5nTGlrZSk6IHZvaWQge1xuICAgIHJldHVybiB0aGlzLmdldCgpLmRlYnVnKG1zZyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExvZ3MgYSBiZW5jaG1hcmsgbWVzc2FnZS5cbiAgICogQHN1bW1hcnkgRGVsZWdhdGVzIHRoZSBiZW5jaG1hcmsgbG9nZ2luZyB0byB0aGUgZ2xvYmFsIGxvZ2dlciBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIG1zZyAtIFRoZSBtZXNzYWdlIHRvIGJlIGxvZ2dlZC5cbiAgICovXG4gIHN0YXRpYyBiZW5jaG1hcmsobXNnOiBTdHJpbmdMaWtlKTogdm9pZCB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KCkuYmVuY2htYXJrKG1zZyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExvZ3MgYSBzaWxseSBtZXNzYWdlLlxuICAgKiBAc3VtbWFyeSBEZWxlZ2F0ZXMgdGhlIGRlYnVnIGxvZ2dpbmcgdG8gdGhlIGdsb2JhbCBsb2dnZXIgaW5zdGFuY2UuXG4gICAqXG4gICAqIEBwYXJhbSBtc2cgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWQuXG4gICAqL1xuICBzdGF0aWMgc2lsbHkobXNnOiBTdHJpbmdMaWtlKTogdm9pZCB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KCkuc2lsbHkobXNnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTG9ncyBhIHNpbGx5IG1lc3NhZ2UuXG4gICAqIEBzdW1tYXJ5IERlbGVnYXRlcyB0aGUgZGVidWcgbG9nZ2luZyB0byB0aGUgZ2xvYmFsIGxvZ2dlciBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIG1zZyAtIFRoZSBtZXNzYWdlIHRvIGJlIGxvZ2dlZC5cbiAgICovXG4gIHN0YXRpYyB3YXJuKG1zZzogU3RyaW5nTGlrZSk6IHZvaWQge1xuICAgIHJldHVybiB0aGlzLmdldCgpLndhcm4obXNnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTG9ncyBhbiBlcnJvciBtZXNzYWdlLlxuICAgKiBAc3VtbWFyeSBEZWxlZ2F0ZXMgdGhlIGVycm9yIGxvZ2dpbmcgdG8gdGhlIGdsb2JhbCBsb2dnZXIgaW5zdGFuY2UuXG4gICAqXG4gICAqIEBwYXJhbSBtc2cgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWQuXG4gICAqIEBwYXJhbSBlXG4gICAqL1xuICBzdGF0aWMgZXJyb3IobXNnOiBTdHJpbmdMaWtlLCBlPzogRXJyb3IpOiB2b2lkIHtcbiAgICByZXR1cm4gdGhpcy5nZXQoKS5lcnJvcihtc2csIGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbG9nZ2VyIGZvciBhIHNwZWNpZmljIG9iamVjdCBvciBjb250ZXh0XG4gICAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBuZXcgbG9nZ2VyIGluc3RhbmNlIGZvciB0aGUgZ2l2ZW4gb2JqZWN0IG9yIGNvbnRleHQgdXNpbmcgdGhlIGZhY3RvcnkgZnVuY3Rpb25cbiAgICogQHBhcmFtIHtMb2dnaW5nQ29udGV4dH0gb2JqZWN0IC0gVGhlIG9iamVjdCwgY2xhc3MsIG9yIGNvbnRleHQgdG8gY3JlYXRlIGEgbG9nZ2VyIGZvclxuICAgKiBAcGFyYW0ge1BhcnRpYWw8TG9nZ2luZ0NvbmZpZz59IFtjb25maWddIC0gT3B0aW9uYWwgY29uZmlndXJhdGlvbiB0byBvdmVycmlkZSBnbG9iYWwgc2V0dGluZ3NcbiAgICogQHBhcmFtIHsuLi5hbnl9IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBsb2dnZXIgZmFjdG9yeVxuICAgKiBAcmV0dXJuIHtMb2dnZXJ9IEEgbmV3IGxvZ2dlciBpbnN0YW5jZSBmb3IgdGhlIHNwZWNpZmllZCBvYmplY3Qgb3IgY29udGV4dFxuICAgKi9cbiAgc3RhdGljIGZvcihcbiAgICBvYmplY3Q6IExvZ2dpbmdDb250ZXh0LFxuICAgIGNvbmZpZz86IFBhcnRpYWw8TG9nZ2luZ0NvbmZpZz4sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogTG9nZ2VyIHtcbiAgICBvYmplY3QgPVxuICAgICAgdHlwZW9mIG9iamVjdCA9PT0gXCJzdHJpbmdcIlxuICAgICAgICA/IG9iamVjdFxuICAgICAgICA6IG9iamVjdC5jb25zdHJ1Y3RvclxuICAgICAgICAgID8gb2JqZWN0LmNvbnN0cnVjdG9yLm5hbWVcbiAgICAgICAgICA6IG9iamVjdC5uYW1lO1xuICAgIHJldHVybiB0aGlzLl9mYWN0b3J5KG9iamVjdCwgY29uZmlnLCAuLi5hcmdzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIGxvZ2dlciBmb3IgYSBzcGVjaWZpYyByZWFzb24gb3IgY29ycmVsYXRpb24gY29udGV4dFxuICAgKiBAc3VtbWFyeSBVdGlsaXR5IHRvIHF1aWNrbHkgY3JlYXRlIGEgbG9nZ2VyIGxhYmVsZWQgd2l0aCBhIGZyZWUtZm9ybSByZWFzb24gYW5kIG9wdGlvbmFsIGlkZW50aWZpZXJcbiAgICogc28gdGhhdCBhZC1ob2Mgb3BlcmF0aW9ucyBjYW4gYmUgdHJhY2VkIHdpdGhvdXQgdHlpbmcgdGhlIGxvZ2dlciB0byBhIGNsYXNzIG9yIG1ldGhvZCBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcmVhc29uIC0gQSB0ZXh0dWFsIHJlYXNvbiBvciBjb250ZXh0IGxhYmVsIGZvciB0aGlzIGxvZ2dlciBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2lkXSAtIE9wdGlvbmFsIGlkZW50aWZpZXIgdG8gaGVscCBjb3JyZWxhdGUgcmVsYXRlZCBsb2cgZW50cmllc1xuICAgKiBAcmV0dXJuIHtMb2dnZXJ9IEEgbmV3IGxvZ2dlciBpbnN0YW5jZSBsYWJlbGVkIHdpdGggdGhlIHByb3ZpZGVkIHJlYXNvbiBhbmQgaWRcbiAgICovXG4gIHN0YXRpYyBiZWNhdXNlKHJlYXNvbjogc3RyaW5nLCBpZD86IHN0cmluZyk6IExvZ2dlciB7XG4gICAgcmV0dXJuIHRoaXMuX2ZhY3RvcnkocmVhc29uLCB0aGlzLl9jb25maWcsIGlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXBwbGllcyB0aGVtZSBzdHlsaW5nIHRvIHRleHRcbiAgICogQHN1bW1hcnkgQXBwbGllcyBzdHlsaW5nIChjb2xvcnMsIGZvcm1hdHRpbmcpIHRvIHRleHQgYmFzZWQgb24gdGhlIHRoZW1lIGNvbmZpZ3VyYXRpb25cbiAgICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBUaGUgdGV4dCB0byBzdHlsZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdHlwZSAtIFRoZSB0eXBlIG9mIGVsZW1lbnQgdG8gc3R5bGUgKGUuZy4sIFwiY2xhc3NcIiwgXCJtZXNzYWdlXCIsIFwibG9nTGV2ZWxcIilcbiAgICogQHBhcmFtIHtMb2dMZXZlbH0gbG9nZ2VyTGV2ZWwgLSBUaGUgbG9nIGxldmVsIHRvIHVzZSBmb3Igc3R5bGluZ1xuICAgKiBAcGFyYW0ge1RoZW1lfSBbdGVtcGxhdGU9RGVmYXVsdFRoZW1lXSAtIFRoZSB0aGVtZSB0byB1c2UgZm9yIHN0eWxpbmdcbiAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgc3R5bGVkIHRleHRcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gICAqICAgcGFydGljaXBhbnQgVGhlbWUgYXMgTG9nZ2luZy50aGVtZVxuICAgKiAgIHBhcnRpY2lwYW50IEFwcGx5IGFzIGFwcGx5IGZ1bmN0aW9uXG4gICAqICAgcGFydGljaXBhbnQgU3R5bGUgYXMgc3R5bGVkLXN0cmluZy1idWlsZGVyXG4gICAqXG4gICAqICAgQ2FsbGVyLT4+VGhlbWU6IHRoZW1lKHRleHQsIHR5cGUsIGxvZ2dlckxldmVsKVxuICAgKiAgIFRoZW1lLT4+VGhlbWU6IENoZWNrIGlmIHN0eWxpbmcgaXMgZW5hYmxlZFxuICAgKiAgIGFsdCBzdHlsaW5nIGRpc2FibGVkXG4gICAqICAgICBUaGVtZS0tPj5DYWxsZXI6IHJldHVybiBvcmlnaW5hbCB0ZXh0XG4gICAqICAgZWxzZSBzdHlsaW5nIGVuYWJsZWRcbiAgICogICAgIFRoZW1lLT4+VGhlbWU6IEdldCB0aGVtZSBmb3IgdHlwZVxuICAgKiAgICAgYWx0IHRoZW1lIG5vdCBmb3VuZFxuICAgKiAgICAgICBUaGVtZS0tPj5DYWxsZXI6IHJldHVybiBvcmlnaW5hbCB0ZXh0XG4gICAqICAgICBlbHNlIHRoZW1lIGZvdW5kXG4gICAqICAgICAgIFRoZW1lLT4+VGhlbWU6IERldGVybWluZSBhY3R1YWwgdGhlbWUgYmFzZWQgb24gbG9nIGxldmVsXG4gICAqICAgICAgIFRoZW1lLT4+QXBwbHk6IEFwcGx5IGVhY2ggc3R5bGUgcHJvcGVydHlcbiAgICogICAgICAgQXBwbHktPj5TdHlsZTogQXBwbHkgY29sb3JzIGFuZCBmb3JtYXR0aW5nXG4gICAqICAgICAgIFN0eWxlLS0+PkFwcGx5OiBSZXR1cm4gc3R5bGVkIHRleHRcbiAgICogICAgICAgQXBwbHktLT4+VGhlbWU6IFJldHVybiBzdHlsZWQgdGV4dFxuICAgKiAgICAgICBUaGVtZS0tPj5DYWxsZXI6IFJldHVybiBmaW5hbCBzdHlsZWQgdGV4dFxuICAgKiAgICAgZW5kXG4gICAqICAgZW5kXG4gICAqL1xuICBzdGF0aWMgdGhlbWUoXG4gICAgdGV4dDogc3RyaW5nLFxuICAgIHR5cGU6IGtleW9mIFRoZW1lIHwga2V5b2YgTG9nTGV2ZWwsXG4gICAgbG9nZ2VyTGV2ZWw6IExvZ0xldmVsLFxuICAgIHRlbXBsYXRlOiBUaGVtZSA9IERlZmF1bHRUaGVtZVxuICApIHtcbiAgICBpZiAoIXRoaXMuX2NvbmZpZy5zdHlsZSkgcmV0dXJuIHRleHQ7XG4gICAgZnVuY3Rpb24gYXBwbHkoXG4gICAgICB0eHQ6IHN0cmluZyxcbiAgICAgIG9wdGlvbjoga2V5b2YgVGhlbWVPcHRpb24sXG4gICAgICB2YWx1ZTogbnVtYmVyIHwgW251bWJlcl0gfCBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gfCBudW1iZXJbXSB8IHN0cmluZ1tdXG4gICAgKTogc3RyaW5nIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHQ6IHN0cmluZyB8IFN0eWxlZFN0cmluZyA9IHR4dDtcbiAgICAgICAgbGV0IGMgPSBzdHlsZSh0KTtcblxuICAgICAgICBmdW5jdGlvbiBhcHBseUNvbG9yKFxuICAgICAgICAgIHZhbDogbnVtYmVyIHwgW251bWJlcl0gfCBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4gICAgICAgICAgaXNCZyA9IGZhbHNlXG4gICAgICAgICk6IFN0eWxlZFN0cmluZyB7XG4gICAgICAgICAgbGV0IGY6XG4gICAgICAgICAgICB8IHR5cGVvZiBjLmJhY2tncm91bmRcbiAgICAgICAgICAgIHwgdHlwZW9mIGMuZm9yZWdyb3VuZFxuICAgICAgICAgICAgfCB0eXBlb2YgYy5yZ2JcbiAgICAgICAgICAgIHwgdHlwZW9mIGMuY29sb3IyNTYgPSBpc0JnID8gYy5iYWNrZ3JvdW5kIDogYy5mb3JlZ3JvdW5kO1xuICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWwpKSB7XG4gICAgICAgICAgICByZXR1cm4gKGYgYXMgdHlwZW9mIGMuYmFja2dyb3VuZCB8IHR5cGVvZiBjLmZvcmVncm91bmQpLmNhbGwoXG4gICAgICAgICAgICAgIGMsXG4gICAgICAgICAgICAgIHZhbHVlIGFzIG51bWJlclxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgc3dpdGNoICh2YWwubGVuZ3RoKSB7XG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgIGYgPSBpc0JnID8gYy5iZ0NvbG9yMjU2IDogYy5jb2xvcjI1NjtcbiAgICAgICAgICAgICAgcmV0dXJuIChmIGFzIHR5cGVvZiBjLmJnQ29sb3IyNTYgfCB0eXBlb2YgYy5jb2xvcjI1NikodmFsWzBdKTtcbiAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgZiA9IGlzQmcgPyBjLmJnUmdiIDogYy5yZ2I7XG4gICAgICAgICAgICAgIHJldHVybiBjLnJnYih2YWxbMF0sIHZhbFsxXSwgdmFsWzJdKTtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYE5vdCBhIHZhbGlkIGNvbG9yIG9wdGlvbjogJHtvcHRpb259YCk7XG4gICAgICAgICAgICAgIHJldHVybiBzdHlsZSh0IGFzIHN0cmluZyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gYXBwbHlTdHlsZSh2OiBudW1iZXIgfCBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgICBpZiAodHlwZW9mIHYgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgIGMgPSBjLnN0eWxlKHYpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjID0gY1t2IGFzIGtleW9mIENvbG9yaXplT3B0aW9uc10gYXMgU3R5bGVkU3RyaW5nO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXRjaCAob3B0aW9uKSB7XG4gICAgICAgICAgY2FzZSBcImJnXCI6XG4gICAgICAgICAgY2FzZSBcImZnXCI6XG4gICAgICAgICAgICByZXR1cm4gYXBwbHlDb2xvcih2YWx1ZSBhcyBudW1iZXIpLnRleHQ7XG4gICAgICAgICAgY2FzZSBcInN0eWxlXCI6XG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgdmFsdWUuZm9yRWFjaChhcHBseVN0eWxlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGFwcGx5U3R5bGUodmFsdWUgYXMgbnVtYmVyIHwgc3RyaW5nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjLnRleHQ7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYE5vdCBhIHZhbGlkIHRoZW1lIG9wdGlvbjogJHtvcHRpb259YCk7XG4gICAgICAgICAgICByZXR1cm4gdDtcbiAgICAgICAgfVxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGFwcGx5aW5nIHN0eWxlOiAke29wdGlvbn0gd2l0aCB2YWx1ZSAke3ZhbHVlfWApO1xuICAgICAgICByZXR1cm4gdHh0O1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGluZGl2aWR1YWxUaGVtZSA9IHRlbXBsYXRlW3R5cGUgYXMga2V5b2YgVGhlbWVdO1xuICAgIGlmICghaW5kaXZpZHVhbFRoZW1lIHx8ICFPYmplY3Qua2V5cyhpbmRpdmlkdWFsVGhlbWUpLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHRleHQ7XG4gICAgfVxuXG4gICAgbGV0IGFjdHVhbFRoZW1lOiBUaGVtZU9wdGlvbiA9IGluZGl2aWR1YWxUaGVtZSBhcyBUaGVtZU9wdGlvbjtcblxuICAgIGNvbnN0IGxvZ0xldmVscyA9IE9iamVjdC5hc3NpZ24oe30sIExvZ0xldmVsKTtcbiAgICBpZiAoT2JqZWN0LmtleXMoaW5kaXZpZHVhbFRoZW1lKVswXSBpbiBsb2dMZXZlbHMpXG4gICAgICBhY3R1YWxUaGVtZSA9XG4gICAgICAgIChpbmRpdmlkdWFsVGhlbWUgYXMgVGhlbWVPcHRpb25CeUxvZ0xldmVsKVtsb2dnZXJMZXZlbF0gfHwge307XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMoYWN0dWFsVGhlbWUpLnJlZHVjZSgoYWNjOiBzdHJpbmcsIGtleTogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCB2YWwgPSAoYWN0dWFsVGhlbWUgYXMgVGhlbWVPcHRpb24pW2tleSBhcyBrZXlvZiBUaGVtZU9wdGlvbl07XG4gICAgICBpZiAodmFsKVxuICAgICAgICByZXR1cm4gYXBwbHkoXG4gICAgICAgICAgYWNjLFxuICAgICAgICAgIGtleSBhcyBrZXlvZiBUaGVtZU9wdGlvbixcbiAgICAgICAgICB2YWwgYXNcbiAgICAgICAgICAgIHwgbnVtYmVyXG4gICAgICAgICAgICB8IFtudW1iZXJdXG4gICAgICAgICAgICB8IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXVxuICAgICAgICAgICAgfCBudW1iZXJbXVxuICAgICAgICAgICAgfCBzdHJpbmdbXVxuICAgICAgICApO1xuICAgICAgcmV0dXJuIGFjYztcbiAgICB9LCB0ZXh0KTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgTG9nZ2luZyB9IGZyb20gXCIuL2xvZ2dpbmdcIjtcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEJhc2UgY2xhc3MgdGhhdCBwcm92aWRlcyBhIHJlYWR5LXRvLXVzZSBsb2dnZXIgaW5zdGFuY2UuXG4gKiBAc3VtbWFyeSBTdXBwbGllcyBpbmhlcml0aW5nIGNsYXNzZXMgd2l0aCBhIGxhemlseSBjcmVhdGVkLCBjb250ZXh0LWF3YXJlIHtAbGluayBMb2dnZXJ9IHZpYSB0aGUgcHJvdGVjdGVkIGBsb2dgIGdldHRlciwgcHJvbW90aW5nIGNvbnNpc3RlbnQgc3RydWN0dXJlZCBsb2dnaW5nIHdpdGhvdXQgbWFudWFsIHdpcmluZy5cbiAqIEBjbGFzcyBMb2dnZWRDbGFzc1xuICogQGV4YW1wbGVcbiAqIGNsYXNzIFVzZXJTZXJ2aWNlIGV4dGVuZHMgTG9nZ2VkQ2xhc3Mge1xuICogICBjcmVhdGUodXNlcjogVXNlcikge1xuICogICAgIHRoaXMubG9nLmluZm8oYENyZWF0aW5nIHVzZXIgJHt1c2VyLmlkfWApO1xuICogICB9XG4gKiB9XG4gKlxuICogY29uc3Qgc3ZjID0gbmV3IFVzZXJTZXJ2aWNlKCk7XG4gKiBzdmMuY3JlYXRlKHsgaWQ6IFwiNDJcIiB9KTtcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IEluc3RhbmNlIGFzIFN1YmNsYXNzIEluc3RhbmNlXG4gKiAgIHBhcnRpY2lwYW50IEdldHRlciBhcyBMb2dnZWRDbGFzcy5sb2dcbiAqICAgcGFydGljaXBhbnQgTG9nZ2luZyBhcyBMb2dnaW5nXG4gKiAgIHBhcnRpY2lwYW50IExvZ2dlciBhcyBMb2dnZXJcbiAqXG4gKiAgIENsaWVudC0+Pkluc3RhbmNlOiBjYWxsIHNvbWVNZXRob2QoKVxuICogICBJbnN0YW5jZS0+PkdldHRlcjogYWNjZXNzIHRoaXMubG9nXG4gKiAgIEdldHRlci0+PkxvZ2dpbmc6IExvZ2dpbmcuZm9yKHRoaXMpXG4gKiAgIExvZ2dpbmctLT4+R2V0dGVyOiByZXR1cm4gTG9nZ2VyXG4gKiAgIEdldHRlci0tPj5JbnN0YW5jZTogcmV0dXJuIExvZ2dlclxuICogICBJbnN0YW5jZS0+PkxvZ2dlcjogaW5mby9kZWJ1Zy9lcnJvciguLi4pXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBMb2dnZWRDbGFzcyB7XG4gIHByaXZhdGUgX2xvZz86IExvZ2dlcjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExhemlseSBwcm92aWRlcyBhIGNvbnRleHQtYXdhcmUgbG9nZ2VyIGZvciB0aGUgY3VycmVudCBpbnN0YW5jZS5cbiAgICogQHN1bW1hcnkgQ2FsbHMge0BsaW5rIExvZ2dpbmcuZm9yfSB3aXRoIHRoZSBzdWJjbGFzcyBpbnN0YW5jZSB0byBvYnRhaW4gYSBsb2dnZXIgd2hvc2UgY29udGV4dCBtYXRjaGVzIHRoZSBzdWJjbGFzcyBuYW1lLlxuICAgKiBAcmV0dXJuIHtMb2dnZXJ9IExvZ2dlciBib3VuZCB0byB0aGUgc3ViY2xhc3MgY29udGV4dC5cbiAgICovXG4gIHByb3RlY3RlZCBnZXQgbG9nKCk6IExvZ2dlciB7XG4gICAgaWYgKCF0aGlzLl9sb2cpIHRoaXMuX2xvZyA9IExvZ2dpbmcuZm9yKHRoaXMgYXMgYW55KTtcbiAgICByZXR1cm4gdGhpcy5fbG9nO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKCkge31cbn1cbiIsImltcG9ydCB7IExvZ2dlciwgTG9nZ2luZ0NvbmZpZywgTG9nZ2luZ0ZpbHRlciB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgTG9nZ2VkQ2xhc3MgfSBmcm9tIFwiLi4vTG9nZ2VkQ2xhc3NcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQmFzZSBjbGFzcyBmb3IgbWVzc2FnZSBmaWx0ZXJzIHRoYXQgcGx1ZyBpbnRvIHRoZSBsb2dnaW5nIHBpcGVsaW5lLlxuICogQHN1bW1hcnkgRXh0ZW5kcyB7QGxpbmsgTG9nZ2VkQ2xhc3N9IHRvIHN1cHBseSBhIHNjb3BlZCBsb2dnZXIgYW5kIGRlZmluZXMgdGhlIGNvbnRyYWN0IHJlcXVpcmVkIGJ5IHtAbGluayBMb2dnaW5nRmlsdGVyfSBpbXBsZW1lbnRlcnMgdGhhdCB0cmFuc2Zvcm0gb3IgZHJvcCBsb2cgbWVzc2FnZXMgYmVmb3JlIGVtaXNzaW9uLlxuICogQGNsYXNzIExvZ0ZpbHRlclxuICogQGV4YW1wbGVcbiAqIGNsYXNzIFJlZGFjdFNlY3JldHNGaWx0ZXIgZXh0ZW5kcyBMb2dGaWx0ZXIge1xuICogICBmaWx0ZXIoY29uZmlnOiBMb2dnaW5nQ29uZmlnLCBtZXNzYWdlOiBzdHJpbmcpOiBzdHJpbmcge1xuICogICAgIHJldHVybiBtZXNzYWdlLnJlcGxhY2UoL3NlY3JldC9naSwgXCIqKipcIik7XG4gKiAgIH1cbiAqIH1cbiAqXG4gKiBjb25zdCBmaWx0ZXIgPSBuZXcgUmVkYWN0U2VjcmV0c0ZpbHRlcigpO1xuICogZmlsdGVyLmZpbHRlcih7IC4uLkRlZmF1bHRMb2dnaW5nQ29uZmlnLCB2ZXJib3NlOiAwIH0sIFwic2VjcmV0IHRva2VuXCIpO1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBMb2dnZXJcbiAqICAgcGFydGljaXBhbnQgRmlsdGVyIGFzIExvZ0ZpbHRlclxuICogICBwYXJ0aWNpcGFudCBJbXBsIGFzIENvbmNyZXRlRmlsdGVyXG4gKiAgIHBhcnRpY2lwYW50IE91dHB1dFxuICogICBMb2dnZXItPj5GaWx0ZXI6IGZpbHRlcihjb25maWcsIG1lc3NhZ2UsIGNvbnRleHQpXG4gKiAgIEZpbHRlci0+PkltcGw6IGRlbGVnYXRlIHRvIHN1YmNsYXNzIGltcGxlbWVudGF0aW9uXG4gKiAgIEltcGwtLT4+RmlsdGVyOiB0cmFuc2Zvcm1lZCBtZXNzYWdlXG4gKiAgIEZpbHRlci0tPj5PdXRwdXQ6IHJldHVybiBmaWx0ZXJlZCBtZXNzYWdlXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBMb2dGaWx0ZXIgZXh0ZW5kcyBMb2dnZWRDbGFzcyBpbXBsZW1lbnRzIExvZ2dpbmdGaWx0ZXIge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNjb3BlZCBsb2dnZXIgdGhhdCBleGNsdWRlcyBvdGhlciBmaWx0ZXJzIGZyb20gdGhlIGNoYWluLlxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIGEgY2hpbGQgbG9nZ2VyIGRlZGljYXRlZCB0byB0aGUgZmlsdGVyLCBwcmV2ZW50aW5nIHJlY3Vyc2l2ZSBmaWx0ZXIgaW52b2NhdGlvbiB3aGVuIGVtaXR0aW5nIGRpYWdub3N0aWMgbWVzc2FnZXMuXG4gICAqIEByZXR1cm4ge0xvZ2dlcn0gQ29udGV4dC1hd2FyZSBsb2dnZXIgZm9yIHRoZSBmaWx0ZXIgaW5zdGFuY2UuXG4gICAqL1xuICBvdmVycmlkZSBnZXQgbG9nKCk6IExvZ2dlciB7XG4gICAgcmV0dXJuIHN1cGVyLmxvZy5mb3IodGhpcyBhcyBhbnksIHsgZmlsdGVyczogW10gfSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRyYW5zZm9ybSBvciBzdXBwcmVzcyBhIGxvZyBtZXNzYWdlLlxuICAgKiBAc3VtbWFyeSBJbnNwZWN0IHRoZSBwcm92aWRlZCBtZXNzYWdlIGFuZCBjb250ZXh0IHRvIHByb2R1Y2UgdGhlIHZhbHVlIHRoYXQgd2lsbCBiZSBmb3J3YXJkZWQgdG8gc3Vic2VxdWVudCBmaWx0ZXJzIG9yIGVtaXR0ZXJzLlxuICAgKiBAcGFyYW0ge0xvZ2dpbmdDb25maWd9IGNvbmZpZyAtIEFjdGl2ZSBsb2dnaW5nIGNvbmZpZ3VyYXRpb24uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gT3JpZ2luYWwgbG9nIG1lc3NhZ2UgcGF5bG9hZC5cbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gY29udGV4dCAtIENvbnRleHQgdmFsdWVzIGF0dGFjaGVkIHRvIHRoZSBtZXNzYWdlLlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IEZpbHRlcmVkIG1lc3NhZ2UgdG8gcGFzcyB0byBkb3duc3RyZWFtIHByb2Nlc3NpbmcuXG4gICAqL1xuICBhYnN0cmFjdCBmaWx0ZXIoXG4gICAgY29uZmlnOiBMb2dnaW5nQ29uZmlnLFxuICAgIG1lc3NhZ2U6IHN0cmluZyxcbiAgICBjb250ZXh0OiBzdHJpbmdbXVxuICApOiBzdHJpbmc7XG59XG4iLCIvKipcbiAqIEBkZXNjcmlwdGlvbiBTbmFwc2hvdCBvZiBhIHJlY29yZGVkIGxhcCBpbnRlcnZhbC5cbiAqIEBzdW1tYXJ5IENhcHR1cmVzIHRoZSBsYXAgaW5kZXgsIG9wdGlvbmFsIGxhYmVsLCBlbGFwc2VkIG1pbGxpc2Vjb25kcyBmb3IgdGhlIGxhcCwgYW5kIGN1bXVsYXRpdmUgZWxhcHNlZCB0aW1lIHNpbmNlIHRoZSBzdG9wd2F0Y2ggc3RhcnRlZC5cbiAqIEB0eXBlZGVmIHtPYmplY3R9IExhcFxuICogQHByb3BlcnR5IHtudW1iZXJ9IGluZGV4IC0gWmVyby1iYXNlZCBsYXAgb3JkZXIuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW2xhYmVsXSAtIE9wdGlvbmFsIGxhYmVsIGRlc2NyaWJpbmcgdGhlIGxhcC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBtcyAtIER1cmF0aW9uIG9mIHRoZSBsYXAgaW4gbWlsbGlzZWNvbmRzLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IHRvdGFsTXMgLSBUb3RhbCBlbGFwc2VkIHRpbWUgd2hlbiB0aGUgbGFwIHdhcyByZWNvcmRlZC5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6TG9nZ2luZ1xuICovXG5leHBvcnQgdHlwZSBMYXAgPSB7XG4gIGluZGV4OiBudW1iZXI7XG4gIGxhYmVsPzogc3RyaW5nO1xuICAvKiogRHVyYXRpb24gb2YgdGhpcyBsYXAgaW4gbWlsbGlzZWNvbmRzICovXG4gIG1zOiBudW1iZXI7XG4gIC8qKiBDdW11bGF0aXZlIHRpbWUgdXAgdG8gdGhpcyBsYXAgaW4gbWlsbGlzZWNvbmRzICovXG4gIHRvdGFsTXM6IG51bWJlcjtcbn07XG5cbnR5cGUgTm93Rm4gPSAoKSA9PiBudW1iZXI7IC8vIG1pbGxpc2Vjb25kc1xuXG5mdW5jdGlvbiBzYWZlTm93KCk6IE5vd0ZuIHtcbiAgLy8gUHJlZmVyIHBlcmZvcm1hbmNlLm5vdyB3aGVuIGF2YWlsYWJsZVxuICBpZiAoXG4gICAgdHlwZW9mIGdsb2JhbFRoaXMgIT09IFwidW5kZWZpbmVkXCIgJiZcbiAgICB0eXBlb2YgZ2xvYmFsVGhpcy5wZXJmb3JtYW5jZT8ubm93ID09PSBcImZ1bmN0aW9uXCJcbiAgKSB7XG4gICAgcmV0dXJuICgpID0+IGdsb2JhbFRoaXMucGVyZm9ybWFuY2Uubm93KCk7XG4gIH1cbiAgLy8gTm9kZTogdXNlIHByb2Nlc3MuaHJ0aW1lLmJpZ2ludCBmb3IgaGlnaGVyIHByZWNpc2lvbiBpZiBhdmFpbGFibGVcbiAgaWYgKFxuICAgIHR5cGVvZiBwcm9jZXNzICE9PSBcInVuZGVmaW5lZFwiICYmXG4gICAgdHlwZW9mIChwcm9jZXNzIGFzIGFueSkuaHJ0aW1lPy5iaWdpbnQgPT09IFwiZnVuY3Rpb25cIlxuICApIHtcbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgY29uc3QgbnMgPSAocHJvY2VzcyBhcyBhbnkpLmhydGltZS5iaWdpbnQoKSBhcyBiaWdpbnQ7IC8vIG5hbm9zZWNvbmRzXG4gICAgICByZXR1cm4gTnVtYmVyKG5zKSAvIDFfMDAwXzAwMDsgLy8gdG8gbXNcbiAgICB9O1xuICB9XG4gIC8vIEZhbGxiYWNrXG4gIHJldHVybiAoKSA9PiBEYXRlLm5vdygpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBIaWdoLXJlc29sdXRpb24gY2xvY2sgYWNjZXNzb3IgcmV0dXJuaW5nIG1pbGxpc2Vjb25kcy5cbiAqIEBzdW1tYXJ5IENob29zZXMgdGhlIG1vc3QgcHJlY2lzZSB0aW1lciBhdmFpbGFibGUgaW4gdGhlIGN1cnJlbnQgcnVudGltZSwgcHJlZmVycmluZyBgcGVyZm9ybWFuY2Uubm93YCBvciBgcHJvY2Vzcy5ocnRpbWUuYmlnaW50YC5cbiAqIEByZXR1cm4ge251bWJlcn0gTWlsbGlzZWNvbmRzIGVsYXBzZWQgYWNjb3JkaW5nIHRvIHRoZSBiZXN0IGF2YWlsYWJsZSBjbG9jay5cbiAqL1xuZXhwb3J0IGNvbnN0IG5vdyA9IHNhZmVOb3coKTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSGlnaC1yZXNvbHV0aW9uIHN0b3B3YXRjaCB3aXRoIHBhdXNlLCByZXN1bWUsIGFuZCBsYXAgdHJhY2tpbmcuXG4gKiBAc3VtbWFyeSBUcmFja3MgZWxhcHNlZCB0aW1lIHVzaW5nIHRoZSBoaWdoZXN0IHByZWNpc2lvbiB0aW1lciBhdmFpbGFibGUsIHN1cHBvcnRzIHBhdXNpbmcsIHJlc3VtaW5nLCBhbmQgcmVjb3JkaW5nIGxhYmVsZWQgbGFwcyBmb3IgZGlhZ25vc3RpY3MgYW5kIGJlbmNobWFya2luZy5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2F1dG9TdGFydD1mYWxzZV0gLSBXaGVuIHRydWUsIHRoZSBzdG9wd2F0Y2ggc3RhcnRzIGltbWVkaWF0ZWx5IHVwb24gY29uc3RydWN0aW9uLlxuICogQGNsYXNzIFN0b3BXYXRjaFxuICogQGV4YW1wbGVcbiAqIGNvbnN0IHN3ID0gbmV3IFN0b3BXYXRjaCh0cnVlKTtcbiAqIC8vIC4uLiB3b3JrIC4uLlxuICogY29uc3QgbGFwID0gc3cubGFwKFwicGhhc2UgMVwiKTtcbiAqIHN3LnBhdXNlKCk7XG4gKiBjb25zb2xlLmxvZyhgRWxhcHNlZDogJHtsYXAudG90YWxNc31tc2ApO1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgU3RvcFdhdGNoXG4gKiAgIHBhcnRpY2lwYW50IENsb2NrIGFzIG5vdygpXG4gKiAgIENsaWVudC0+PlN0b3BXYXRjaDogc3RhcnQoKVxuICogICBTdG9wV2F0Y2gtPj5DbG9jazogbm93KClcbiAqICAgQ2xvY2stLT4+U3RvcFdhdGNoOiB0aW1lc3RhbXBcbiAqICAgQ2xpZW50LT4+U3RvcFdhdGNoOiBsYXAoKVxuICogICBTdG9wV2F0Y2gtPj5DbG9jazogbm93KClcbiAqICAgQ2xvY2stLT4+U3RvcFdhdGNoOiB0aW1lc3RhbXBcbiAqICAgU3RvcFdhdGNoLS0+PkNsaWVudDogTGFwXG4gKiAgIENsaWVudC0+PlN0b3BXYXRjaDogcGF1c2UoKVxuICogICBTdG9wV2F0Y2gtPj5DbG9jazogbm93KClcbiAqICAgQ2xvY2stLT4+U3RvcFdhdGNoOiB0aW1lc3RhbXBcbiAqL1xuZXhwb3J0IGNsYXNzIFN0b3BXYXRjaCB7XG4gIHByaXZhdGUgX3N0YXJ0TXM6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIF9lbGFwc2VkTXMgPSAwO1xuICBwcml2YXRlIF9ydW5uaW5nID0gZmFsc2U7XG4gIHByaXZhdGUgX2xhcHM6IExhcFtdID0gW107XG4gIHByaXZhdGUgX2xhc3RMYXBUb3RhbE1zID0gMDtcblxuICBjb25zdHJ1Y3RvcihhdXRvU3RhcnQgPSBmYWxzZSkge1xuICAgIGlmIChhdXRvU3RhcnQpIHRoaXMuc3RhcnQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW5kaWNhdGVzIHdoZXRoZXIgdGhlIHN0b3B3YXRjaCBpcyBhY3RpdmVseSBydW5uaW5nLlxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIGB0cnVlYCB3aGVuIHRpbWluZyBpcyBpbiBwcm9ncmVzcyBhbmQgYGZhbHNlYCB3aGVuIHBhdXNlZCBvciBzdG9wcGVkLlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBDdXJyZW50IHJ1bm5pbmcgc3RhdGUuXG4gICAqL1xuICBnZXQgcnVubmluZygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fcnVubmluZztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRWxhcHNlZCB0aW1lIGNhcHR1cmVkIGJ5IHRoZSBzdG9wd2F0Y2guXG4gICAqIEBzdW1tYXJ5IENvbXB1dGVzIHRoZSB0b3RhbCBlbGFwc2VkIHRpbWUgaW4gbWlsbGlzZWNvbmRzLCBpbmNsdWRpbmcgdGhlIGN1cnJlbnQgc2Vzc2lvbiBpZiBydW5uaW5nLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IE1pbGxpc2Vjb25kcyBlbGFwc2VkIHNpbmNlIHRoZSBzdG9wd2F0Y2ggc3RhcnRlZC5cbiAgICovXG4gIGdldCBlbGFwc2VkTXMoKTogbnVtYmVyIHtcbiAgICBpZiAoIXRoaXMuX3J1bm5pbmcgfHwgdGhpcy5fc3RhcnRNcyA9PSBudWxsKSByZXR1cm4gdGhpcy5fZWxhcHNlZE1zO1xuICAgIHJldHVybiB0aGlzLl9lbGFwc2VkTXMgKyAobm93KCkgLSB0aGlzLl9zdGFydE1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3RhcnRzIHRpbWluZyBpZiB0aGUgc3RvcHdhdGNoIGlzIG5vdCBhbHJlYWR5IHJ1bm5pbmcuXG4gICAqIEBzdW1tYXJ5IFJlY29yZHMgdGhlIGN1cnJlbnQgdGltZXN0YW1wIGFuZCB0cmFuc2l0aW9ucyB0aGUgc3RvcHdhdGNoIGludG8gdGhlIHJ1bm5pbmcgc3RhdGUuXG4gICAqIEByZXR1cm4ge3RoaXN9IEZsdWVudCByZWZlcmVuY2UgdG8gdGhlIHN0b3B3YXRjaC5cbiAgICovXG4gIHN0YXJ0KCk6IHRoaXMge1xuICAgIGlmICghdGhpcy5fcnVubmluZykge1xuICAgICAgdGhpcy5fcnVubmluZyA9IHRydWU7XG4gICAgICB0aGlzLl9zdGFydE1zID0gbm93KCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQYXVzZXMgdGltaW5nIGFuZCBhY2N1bXVsYXRlcyBlbGFwc2VkIG1pbGxpc2Vjb25kcy5cbiAgICogQHN1bW1hcnkgQ2FwdHVyZXMgdGhlIHBhcnRpYWwgZHVyYXRpb24sIHVwZGF0ZXMgdGhlIGFjY3VtdWxhdG9yLCBhbmQga2VlcHMgdGhlIHN0b3B3YXRjaCByZWFkeSB0byByZXN1bWUgbGF0ZXIuXG4gICAqIEByZXR1cm4ge3RoaXN9IEZsdWVudCByZWZlcmVuY2UgdG8gdGhlIHN0b3B3YXRjaC5cbiAgICovXG4gIHBhdXNlKCk6IHRoaXMge1xuICAgIGlmICh0aGlzLl9ydW5uaW5nICYmIHRoaXMuX3N0YXJ0TXMgIT0gbnVsbCkge1xuICAgICAgdGhpcy5fZWxhcHNlZE1zICs9IG5vdygpIC0gdGhpcy5fc3RhcnRNcztcbiAgICAgIHRoaXMuX3N0YXJ0TXMgPSBudWxsO1xuICAgICAgdGhpcy5fcnVubmluZyA9IGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVzdW1lcyB0aW1pbmcgYWZ0ZXIgYSBwYXVzZS5cbiAgICogQHN1bW1hcnkgQ2FwdHVyZXMgYSBmcmVzaCBzdGFydCB0aW1lc3RhbXAgd2hpbGUga2VlcGluZyBwcmV2aW91cyBlbGFwc2VkIHRpbWUgaW50YWN0LlxuICAgKiBAcmV0dXJuIHt0aGlzfSBGbHVlbnQgcmVmZXJlbmNlIHRvIHRoZSBzdG9wd2F0Y2guXG4gICAqL1xuICByZXN1bWUoKTogdGhpcyB7XG4gICAgaWYgKCF0aGlzLl9ydW5uaW5nKSB7XG4gICAgICB0aGlzLl9ydW5uaW5nID0gdHJ1ZTtcbiAgICAgIHRoaXMuX3N0YXJ0TXMgPSBub3coKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFN0b3BzIHRpbWluZyBhbmQgcmV0dXJucyB0aGUgdG90YWwgZWxhcHNlZCBtaWxsaXNlY29uZHMuXG4gICAqIEBzdW1tYXJ5IEludm9rZXMge0BsaW5rIFN0b3BXYXRjaC5wYXVzZX0gdG8gY29uc29saWRhdGUgZWxhcHNlZCB0aW1lLCBsZWF2aW5nIHRoZSBzdG9wd2F0Y2ggaW4gYSBub24tcnVubmluZyBzdGF0ZS5cbiAgICogQHJldHVybiB7bnVtYmVyfSBNaWxsaXNlY29uZHMgYWNjdW11bGF0ZWQgYWNyb3NzIGFsbCBydW5zLlxuICAgKi9cbiAgc3RvcCgpOiBudW1iZXIge1xuICAgIHRoaXMucGF1c2UoKTtcbiAgICByZXR1cm4gdGhpcy5fZWxhcHNlZE1zO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXNldHMgdGhlIHN0b3B3YXRjaCBzdGF0ZSB3aGlsZSBvcHRpb25hbGx5IGNvbnRpbnVpbmcgdG8gcnVuLlxuICAgKiBAc3VtbWFyeSBDbGVhcnMgZWxhcHNlZCB0aW1lIGFuZCBsYXAgaGlzdG9yeSwgcHJlc2VydmluZyB3aGV0aGVyIHRoZSBzdG9wd2F0Y2ggc2hvdWxkIGNvbnRpbnVlIHRpY2tpbmcuXG4gICAqIEByZXR1cm4ge3RoaXN9IEZsdWVudCByZWZlcmVuY2UgdG8gdGhlIHN0b3B3YXRjaC5cbiAgICovXG4gIHJlc2V0KCk6IHRoaXMge1xuICAgIGNvbnN0IHdhc1J1bm5pbmcgPSB0aGlzLl9ydW5uaW5nO1xuICAgIHRoaXMuX3N0YXJ0TXMgPSB3YXNSdW5uaW5nID8gbm93KCkgOiBudWxsO1xuICAgIHRoaXMuX2VsYXBzZWRNcyA9IDA7XG4gICAgdGhpcy5fbGFwcyA9IFtdO1xuICAgIHRoaXMuX2xhc3RMYXBUb3RhbE1zID0gMDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVjb3JkcyBhIGxhcCBzcGxpdCBzaW5jZSB0aGUgc3RvcHdhdGNoIHN0YXJ0ZWQgb3Igc2luY2UgdGhlIHByZXZpb3VzIGxhcC5cbiAgICogQHN1bW1hcnkgU3RvcmVzIHRoZSBsYXAgbWV0YWRhdGEsIHVwZGF0ZXMgY3VtdWxhdGl2ZSB0cmFja2luZywgYW5kIHJldHVybnMgdGhlIG5ld2x5IGNyZWF0ZWQge0BsaW5rIExhcH0uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbbGFiZWxdIC0gT3B0aW9uYWwgbGFiZWwgZGVzY3JpYmluZyB0aGUgbGFwLlxuICAgKiBAcmV0dXJuIHtMYXB9IExhcCBzbmFwc2hvdCBjYXB0dXJpbmcgaW5jcmVtZW50YWwgYW5kIGN1bXVsYXRpdmUgdGltaW5ncy5cbiAgICovXG4gIGxhcChsYWJlbD86IHN0cmluZyk6IExhcCB7XG4gICAgY29uc3QgdG90YWwgPSB0aGlzLmVsYXBzZWRNcztcbiAgICBjb25zdCBtcyA9IHRvdGFsIC0gdGhpcy5fbGFzdExhcFRvdGFsTXM7XG4gICAgY29uc3QgbGFwOiBMYXAgPSB7XG4gICAgICBpbmRleDogdGhpcy5fbGFwcy5sZW5ndGgsXG4gICAgICBsYWJlbCxcbiAgICAgIG1zLFxuICAgICAgdG90YWxNczogdG90YWwsXG4gICAgfTtcbiAgICB0aGlzLl9sYXBzLnB1c2gobGFwKTtcbiAgICB0aGlzLl9sYXN0TGFwVG90YWxNcyA9IHRvdGFsO1xuICAgIHJldHVybiBsYXA7XG4gIH1cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIHJlY29yZGVkIGxhcCBoaXN0b3J5LlxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSBpbnRlcm5hbCBsYXAgYXJyYXkgYXMgYSByZWFkLW9ubHkgdmlldyB0byBwcmV2ZW50IGV4dGVybmFsIG11dGF0aW9uLlxuICAgKiBAcmV0dXJuIHtMYXBbXX0gTGFwcyBjYXB0dXJlZCBieSB0aGUgc3RvcHdhdGNoLlxuICAgKi9cbiAgZ2V0IGxhcHMoKTogcmVhZG9ubHkgTGFwW10ge1xuICAgIHJldHVybiB0aGlzLl9sYXBzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBGb3JtYXRzIHRoZSBlbGFwc2VkIHRpbWUgaW4gYSBodW1hbi1yZWFkYWJsZSByZXByZXNlbnRhdGlvbi5cbiAgICogQHN1bW1hcnkgVXNlcyB7QGxpbmsgZm9ybWF0TXN9IHRvIHByb2R1Y2UgYW4gYGhoOm1tOnNzLm1tbWAgc3RyaW5nIGZvciBkaXNwbGF5IGFuZCBsb2dnaW5nLlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IEVsYXBzZWQgdGltZSBmb3JtYXR0ZWQgZm9yIHByZXNlbnRhdGlvbi5cbiAgICovXG4gIHRvU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGZvcm1hdE1zKHRoaXMuZWxhcHNlZE1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2VyaWFsaXplcyB0aGUgc3RvcHdhdGNoIHN0YXRlLlxuICAgKiBAc3VtbWFyeSBQcm92aWRlcyBhIEpTT04tZnJpZW5kbHkgc25hcHNob3QgaW5jbHVkaW5nIHJ1bm5pbmcgc3RhdGUsIGVsYXBzZWQgdGltZSwgYW5kIGxhcCBkZXRhaWxzLlxuICAgKiBAcmV0dXJuIHt7cnVubmluZzogYm9vbGVhbiwgZWxhcHNlZE1zOiBudW1iZXIsIGxhcHM6IExhcFtdfX0gU2VyaWFsaXphYmxlIHN0b3B3YXRjaCByZXByZXNlbnRhdGlvbi5cbiAgICovXG4gIHRvSlNPTigpIHtcbiAgICByZXR1cm4ge1xuICAgICAgcnVubmluZzogdGhpcy5fcnVubmluZyxcbiAgICAgIGVsYXBzZWRNczogdGhpcy5lbGFwc2VkTXMsXG4gICAgICBsYXBzOiB0aGlzLl9sYXBzLnNsaWNlKCksXG4gICAgfTtcbiAgfVxufVxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRm9ybWF0cyBtaWxsaXNlY29uZHMgaW50byBgaGg6bW06c3MubW1tYC5cbiAqIEBzdW1tYXJ5IEJyZWFrcyB0aGUgZHVyYXRpb24gaW50byBob3VycywgbWludXRlcywgc2Vjb25kcywgYW5kIG1pbGxpc2Vjb25kcywgcmV0dXJuaW5nIGEgemVyby1wYWRkZWQgc3RyaW5nLlxuICogQHBhcmFtIHtudW1iZXJ9IG1zIC0gTWlsbGlzZWNvbmRzIHRvIGZvcm1hdC5cbiAqIEByZXR1cm4ge3N0cmluZ30gRm9ybWF0dGVkIGR1cmF0aW9uIHN0cmluZy5cbiAqIEBmdW5jdGlvbiBmb3JtYXRNc1xuICogQG1lbWJlck9mIG1vZHVsZTpMb2dnaW5nXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBGb3JtYXR0ZXIgYXMgZm9ybWF0TXNcbiAqICAgQ2FsbGVyLT4+Rm9ybWF0dGVyOiBmb3JtYXRNcyhtcylcbiAqICAgRm9ybWF0dGVyLT4+Rm9ybWF0dGVyOiBkZXJpdmUgaG91cnMvbWludXRlcy9zZWNvbmRzXG4gKiAgIEZvcm1hdHRlci0+PkZvcm1hdHRlcjogcGFkIHNlZ21lbnRzXG4gKiAgIEZvcm1hdHRlci0tPj5DYWxsZXI6IGhoOm1tOnNzLm1tbVxuICovXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0TXMobXM6IG51bWJlcik6IHN0cmluZyB7XG4gIGNvbnN0IHNpZ24gPSBtcyA8IDAgPyBcIi1cIiA6IFwiXCI7XG4gIGNvbnN0IGFicyA9IE1hdGguYWJzKG1zKTtcbiAgY29uc3QgaG91cnMgPSBNYXRoLmZsb29yKGFicyAvIDNfNjAwXzAwMCk7XG4gIGNvbnN0IG1pbnV0ZXMgPSBNYXRoLmZsb29yKChhYnMgJSAzXzYwMF8wMDApIC8gNjBfMDAwKTtcbiAgY29uc3Qgc2Vjb25kcyA9IE1hdGguZmxvb3IoKGFicyAlIDYwXzAwMCkgLyAxMDAwKTtcbiAgY29uc3QgbWlsbGlzID0gTWF0aC5mbG9vcihhYnMgJSAxMDAwKTtcbiAgY29uc3QgcGFkID0gKG46IG51bWJlciwgdzogbnVtYmVyKSA9PiBuLnRvU3RyaW5nKCkucGFkU3RhcnQodywgXCIwXCIpO1xuICByZXR1cm4gYCR7c2lnbn0ke3BhZChob3VycywgMil9OiR7cGFkKG1pbnV0ZXMsIDIpfToke3BhZChzZWNvbmRzLCAyKX0uJHtwYWQobWlsbGlzLCAzKX1gO1xufVxuIiwiaW1wb3J0IHsgTG9nTGV2ZWwgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IExvZ2dpbmcgfSBmcm9tIFwiLi9sb2dnaW5nXCI7XG5pbXBvcnQgeyBub3cgfSBmcm9tIFwiLi90aW1lXCI7XG5pbXBvcnQgeyBMb2dnZWRDbGFzcyB9IGZyb20gXCIuL0xvZ2dlZENsYXNzXCI7XG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgdHlwZSBBcmdGb3JtYXRGdW5jdGlvbiA9ICguLi5hcmdzOiBhbnlbXSkgPT4gc3RyaW5nO1xuZXhwb3J0IHR5cGUgUmV0dXJuRm9ybWF0RnVuY3Rpb24gPSAoZT86IEVycm9yLCByZXN1bHQ/OiBhbnkpID0+IHN0cmluZztcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWV0aG9kIGRlY29yYXRvciBmb3IgbG9nZ2luZyBmdW5jdGlvbiBjYWxscy5cbiAqIEBzdW1tYXJ5IFdyYXBzIGNsYXNzIG1ldGhvZHMgdG8gYXV0b21hdGljYWxseSBsb2cgZW50cnksIGV4aXQsIHRpbWluZywgYW5kIG9wdGlvbmFsIGN1c3RvbSBtZXNzYWdlcyBhdCBhIGNvbmZpZ3VyYWJsZSB7QGxpbmsgTG9nTGV2ZWx9LlxuICogQHBhcmFtIHtMb2dMZXZlbH0gbGV2ZWwgLSBMb2cgbGV2ZWwgYXBwbGllZCB0byB0aGUgZ2VuZXJhdGVkIGxvZyBzdGF0ZW1lbnRzIChkZWZhdWx0cyB0byBgTG9nTGV2ZWwuaW5mb2ApLlxuICogQHBhcmFtIHtudW1iZXJ9IFt2ZXJib3NpdHk9MF0gLSBWZXJib3NpdHkgdGhyZXNob2xkIHJlcXVpcmVkIGZvciB0aGUgZW50cnkgbG9nIHRvIGFwcGVhci5cbiAqIEBwYXJhbSB7QXJnRm9ybWF0RnVuY3Rpb259IFtlbnRyeU1lc3NhZ2VdIC0gRm9ybWF0dGVyIGludm9rZWQgd2l0aCB0aGUgb3JpZ2luYWwgbWV0aG9kIGFyZ3VtZW50cyB0byBkZXNjcmliZSB0aGUgaW52b2NhdGlvbi5cbiAqIEBwYXJhbSB7UmV0dXJuRm9ybWF0RnVuY3Rpb259IFtleGl0TWVzc2FnZV0gLSBPcHRpb25hbCBmb3JtYXR0ZXIgdGhhdCBkZXNjcmliZXMgdGhlIG91dGNvbWUgb3IgZmFpbHVyZSBvZiB0aGUgY2FsbC5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKGFueSwgYW55LCBQcm9wZXJ0eURlc2NyaXB0b3IpOiB2b2lkfSBNZXRob2QgZGVjb3JhdG9yIHByb3h5IHRoYXQgaW5qZWN0cyBsb2dnaW5nIGJlaGF2aW9yLlxuICogQGZ1bmN0aW9uIGxvZ1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgRGVjb3JhdG9yIGFzIGxvZyBkZWNvcmF0b3JcbiAqICAgcGFydGljaXBhbnQgTWV0aG9kIGFzIE9yaWdpbmFsIE1ldGhvZFxuICogICBwYXJ0aWNpcGFudCBMb2dnZXIgYXMgTG9nZ2luZyBpbnN0YW5jZVxuICpcbiAqICAgQ2xpZW50LT4+RGVjb3JhdG9yOiBjYWxsIGRlY29yYXRlZCBtZXRob2RcbiAqICAgRGVjb3JhdG9yLT4+TG9nZ2VyOiBsb2cgbWV0aG9kIGNhbGxcbiAqICAgRGVjb3JhdG9yLT4+TWV0aG9kOiBjYWxsIG9yaWdpbmFsIG1ldGhvZFxuICogICBhbHQgcmVzdWx0IGlzIFByb21pc2VcbiAqICAgICBNZXRob2QtLT4+RGVjb3JhdG9yOiByZXR1cm4gUHJvbWlzZVxuICogICAgIERlY29yYXRvci0+PkRlY29yYXRvcjogYXR0YWNoIHRoZW4gaGFuZGxlclxuICogICAgIE5vdGUgb3ZlciBEZWNvcmF0b3I6IFByb21pc2UgcmVzb2x2ZXNcbiAqICAgICBEZWNvcmF0b3ItPj5Mb2dnZXI6IGxvZyBiZW5jaG1hcmsgKGlmIGVuYWJsZWQpXG4gKiAgICAgRGVjb3JhdG9yLS0+PkNsaWVudDogcmV0dXJuIHJlc3VsdFxuICogICBlbHNlIHJlc3VsdCBpcyBub3QgUHJvbWlzZVxuICogICAgIE1ldGhvZC0tPj5EZWNvcmF0b3I6IHJldHVybiByZXN1bHRcbiAqICAgICBEZWNvcmF0b3ItPj5Mb2dnZXI6IGxvZyBiZW5jaG1hcmsgKGlmIGVuYWJsZWQpXG4gKiAgICAgRGVjb3JhdG9yLS0+PkNsaWVudDogcmV0dXJuIHJlc3VsdFxuICogICBlbmRcbiAqIEBjYXRlZ29yeSBNZXRob2QgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gbG9nKFxuICBsZXZlbDogTG9nTGV2ZWwgPSBMb2dMZXZlbC5pbmZvLFxuICB2ZXJib3NpdHkgPSAwLFxuICBlbnRyeU1lc3NhZ2U6IEFyZ0Zvcm1hdEZ1bmN0aW9uID0gKC4uLmFyZ3M6IGFueVtdKSA9PiBgY2FsbGVkIHdpdGggJHthcmdzfWAsXG4gIGV4aXRNZXNzYWdlPzogUmV0dXJuRm9ybWF0RnVuY3Rpb25cbikge1xuICByZXR1cm4gZnVuY3Rpb24gbG9nKHRhcmdldDogYW55LCBwcm9wZXJ0eUtleT86IGFueSwgZGVzY3JpcHRvcj86IGFueSkge1xuICAgIGlmICghZGVzY3JpcHRvciB8fCB0eXBlb2YgZGVzY3JpcHRvciA9PT0gXCJudW1iZXJcIilcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTG9nZ2luZyBkZWNvcmF0aW9uIG9ubHkgYXBwbGllcyB0byBtZXRob2RzYCk7XG4gICAgY29uc3QgbG9nZ2VyOiBMb2dnZXIgPVxuICAgICAgdGFyZ2V0IGluc3RhbmNlb2YgTG9nZ2VkQ2xhc3NcbiAgICAgICAgPyB0YXJnZXRbXCJsb2dcIl0uZm9yKHRhcmdldFtwcm9wZXJ0eUtleSBhcyBrZXlvZiB0eXBlb2YgdGFyZ2V0XSlcbiAgICAgICAgOiBMb2dnaW5nLmZvcih0YXJnZXQpLmZvcih0YXJnZXRbcHJvcGVydHlLZXldKTtcbiAgICBjb25zdCBtZXRob2QgPSBsb2dnZXJbbGV2ZWxdLmJpbmQobG9nZ2VyKSBhcyBhbnk7XG4gICAgY29uc3Qgb3JpZ2luYWxNZXRob2QgPSBkZXNjcmlwdG9yLnZhbHVlO1xuXG4gICAgZGVzY3JpcHRvci52YWx1ZSA9IG5ldyBQcm94eShvcmlnaW5hbE1ldGhvZCwge1xuICAgICAgYXBwbHkoZm4sIHRoaXNBcmcsIGFyZ3M6IGFueVtdKSB7XG4gICAgICAgIG1ldGhvZChlbnRyeU1lc3NhZ2UoLi4uYXJncyksIHZlcmJvc2l0eSk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gUmVmbGVjdC5hcHBseShmbiwgdGhpc0FyZywgYXJncyk7XG4gICAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHRcbiAgICAgICAgICAgICAgLnRoZW4oKHI6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChleGl0TWVzc2FnZSkgbWV0aG9kKGV4aXRNZXNzYWdlKHVuZGVmaW5lZCwgcikpO1xuICAgICAgICAgICAgICAgIHJldHVybiByO1xuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXhpdE1lc3NhZ2UpIGxvZ2dlci5lcnJvcihleGl0TWVzc2FnZShlIGFzIEVycm9yKSk7XG4gICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChleGl0TWVzc2FnZSkgbWV0aG9kKGV4aXRNZXNzYWdlKHVuZGVmaW5lZCwgcmVzdWx0KSk7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXJyOiB1bmtub3duKSB7XG4gICAgICAgICAgaWYgKGV4aXRNZXNzYWdlKSBsb2dnZXIuZXJyb3IoZXhpdE1lc3NhZ2UoZXJyIGFzIEVycm9yKSk7XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0pO1xuICAgIHJldHVybiBkZXNjcmlwdG9yO1xuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNZXRob2QgZGVjb3JhdG9yIHRoYXQgcmVjb3JkcyBleGVjdXRpb24gdGltZSBhdCB0aGUgYmVuY2htYXJrIGxldmVsLlxuICogQHN1bW1hcnkgV3JhcHMgdGhlIHRhcmdldCBtZXRob2QgdG8gZW1pdCB7QGxpbmsgTG9nZ2VyLmJlbmNobWFya30gZW50cmllcyBjYXB0dXJpbmcgY29tcGxldGlvbiB0aW1lIG9yIGZhaWx1cmUgbGF0ZW5jeS5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKGFueSwgYW55LCAgUHJvcGVydHlEZXNjcmlwdG9yKTogdm9pZH0gTWV0aG9kIGRlY29yYXRvciBwcm94eSB0aGF0IGJlbmNobWFya3MgdGhlIG9yaWdpbmFsIGltcGxlbWVudGF0aW9uLlxuICogQGZ1bmN0aW9uIGJlbmNobWFya1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgRGVjb3JhdG9yIGFzIGJlbmNobWFya1xuICogICBwYXJ0aWNpcGFudCBNZXRob2QgYXMgT3JpZ2luYWwgTWV0aG9kXG4gKiAgIENhbGxlci0+PkRlY29yYXRvcjogaW52b2tlKClcbiAqICAgRGVjb3JhdG9yLT4+TWV0aG9kOiBSZWZsZWN0LmFwcGx5KC4uLilcbiAqICAgYWx0IFByb21pc2UgcmVzdWx0XG4gKiAgICAgTWV0aG9kLS0+PkRlY29yYXRvcjogUHJvbWlzZVxuICogICAgIERlY29yYXRvci0+PkRlY29yYXRvcjogYXR0YWNoIHRoZW4oKVxuICogICAgIERlY29yYXRvci0+PkRlY29yYXRvcjogbG9nIGNvbXBsZXRpb24gZHVyYXRpb25cbiAqICAgZWxzZSBTeW5jaHJvbm91cyByZXN1bHRcbiAqICAgICBNZXRob2QtLT4+RGVjb3JhdG9yOiB2YWx1ZVxuICogICAgIERlY29yYXRvci0+PkRlY29yYXRvcjogbG9nIGNvbXBsZXRpb24gZHVyYXRpb25cbiAqICAgZW5kXG4gKiAgIERlY29yYXRvci0tPj5DYWxsZXI6IHJldHVybiByZXN1bHRcbiAqIEBjYXRlZ29yeSBNZXRob2QgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gYmVuY2htYXJrKCkge1xuICByZXR1cm4gZnVuY3Rpb24gYmVuY2htYXJrKHRhcmdldDogYW55LCBwcm9wZXJ0eUtleT86IGFueSwgZGVzY3JpcHRvcj86IGFueSkge1xuICAgIGlmICghZGVzY3JpcHRvciB8fCB0eXBlb2YgZGVzY3JpcHRvciA9PT0gXCJudW1iZXJcIilcbiAgICAgIHRocm93IG5ldyBFcnJvcihgYmVuY2htYXJrIGRlY29yYXRpb24gb25seSBhcHBsaWVzIHRvIG1ldGhvZHNgKTtcbiAgICBjb25zdCBsb2dnZXI6IExvZ2dlciA9XG4gICAgICB0YXJnZXQgaW5zdGFuY2VvZiBMb2dnZWRDbGFzc1xuICAgICAgICA/IHRhcmdldFtcImxvZ1wiXS5mb3IodGFyZ2V0W3Byb3BlcnR5S2V5IGFzIGtleW9mIHR5cGVvZiB0YXJnZXRdKVxuICAgICAgICA6IExvZ2dpbmcuZm9yKHRhcmdldCkuZm9yKHRhcmdldFtwcm9wZXJ0eUtleV0pO1xuICAgIGNvbnN0IG9yaWdpbmFsTWV0aG9kID0gZGVzY3JpcHRvci52YWx1ZTtcblxuICAgIGRlc2NyaXB0b3IudmFsdWUgPSBuZXcgUHJveHkob3JpZ2luYWxNZXRob2QsIHtcbiAgICAgIGFwcGx5KGZuLCB0aGlzQXJnLCBhcmdzOiBhbnlbXSkge1xuICAgICAgICBjb25zdCBzdGFydCA9IG5vdygpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IFJlZmxlY3QuYXBwbHkoZm4sIHRoaXNBcmcsIGFyZ3MpO1xuICAgICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBQcm9taXNlKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0XG4gICAgICAgICAgICAgIC50aGVuKChyOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuYmVuY2htYXJrKGBjb21wbGV0ZWQgaW4gJHtub3coKSAtIHN0YXJ0fW1zYCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHI7XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5iZW5jaG1hcmsoYGZhaWxlZCBpbiAke25vdygpIC0gc3RhcnR9bXNgKTtcbiAgICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgbG9nZ2VyLmJlbmNobWFyayhgY29tcGxldGVkIGluICR7bm93KCkgLSBzdGFydH1tc2ApO1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGVycjogdW5rbm93bikge1xuICAgICAgICAgIGxvZ2dlci5iZW5jaG1hcmsoYGZhaWxlZCBpbiAke25vdygpIC0gc3RhcnR9bXNgKTtcbiAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICByZXR1cm4gZGVzY3JpcHRvcjtcbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWV0aG9kIGRlY29yYXRvciBmb3IgbG9nZ2luZyBmdW5jdGlvbiBjYWxscyB3aXRoIGRlYnVnIGxldmVsLlxuICogQHN1bW1hcnkgQ29udmVuaWVuY2Ugd3JhcHBlciBhcm91bmQge0BsaW5rIGxvZ30gdGhhdCBsb2dzIHVzaW5nIGBMb2dMZXZlbC5kZWJ1Z2AuXG4gKiBAcmV0dXJuIHtmdW5jdGlvbihhbnksIGFueSwgUHJvcGVydHlEZXNjcmlwdG9yKTogdm9pZH0gRGVidWctbGV2ZWwgbG9nZ2luZyBkZWNvcmF0b3IuXG4gKiBAZnVuY3Rpb24gZGVidWdcbiAqIEBjYXRlZ29yeSBNZXRob2QgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZGVidWcoKSB7XG4gIHJldHVybiBsb2coXG4gICAgTG9nTGV2ZWwuZGVidWcsXG4gICAgMCxcbiAgICAoLi4uYXJnczogYW55W10pID0+IGBjYWxsZWQgd2l0aCAke2FyZ3N9YCxcbiAgICAoZT86IEVycm9yLCByZXN1bHQ/OiBhbnkpID0+XG4gICAgICBlXG4gICAgICAgID8gYEZhaWxlZCB3aXRoOiAke2V9YFxuICAgICAgICA6IHJlc3VsdFxuICAgICAgICAgID8gYENvbXBsZXRlZCB3aXRoICR7SlNPTi5zdHJpbmdpZnkocmVzdWx0KX1gXG4gICAgICAgICAgOiBcImNvbXBsZXRlZFwiXG4gICk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE1ldGhvZCBkZWNvcmF0b3IgZm9yIGxvZ2dpbmcgZnVuY3Rpb24gY2FsbHMgd2l0aCBpbmZvIGxldmVsLlxuICogQHN1bW1hcnkgQ29udmVuaWVuY2Ugd3JhcHBlciBhcm91bmQge0BsaW5rIGxvZ30gdGhhdCBsb2dzIHVzaW5nIGBMb2dMZXZlbC5pbmZvYC5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKGFueSwgYW55LCBQcm9wZXJ0eURlc2NyaXB0b3IpOiB2b2lkfSBJbmZvLWxldmVsIGxvZ2dpbmcgZGVjb3JhdG9yLlxuICogQGZ1bmN0aW9uIGluZm9cbiAqIEBjYXRlZ29yeSBNZXRob2QgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gaW5mbygpIHtcbiAgcmV0dXJuIGxvZyhMb2dMZXZlbC5pbmZvKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWV0aG9kIGRlY29yYXRvciBmb3IgbG9nZ2luZyBmdW5jdGlvbiBjYWxscyB3aXRoIHNpbGx5IGxldmVsLlxuICogQHN1bW1hcnkgQ29udmVuaWVuY2Ugd3JhcHBlciBhcm91bmQge0BsaW5rIGxvZ30gdGhhdCBsb2dzIHVzaW5nIGBMb2dMZXZlbC5zaWxseWAuXG4gKiBAcmV0dXJuIHtmdW5jdGlvbihhbnksIGFueSwgUHJvcGVydHlEZXNjcmlwdG9yKTogdm9pZH0gU2lsbHktbGV2ZWwgbG9nZ2luZyBkZWNvcmF0b3IuXG4gKiBAZnVuY3Rpb24gc2lsbHlcbiAqIEBjYXRlZ29yeSBNZXRob2QgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gc2lsbHkoKSB7XG4gIHJldHVybiBsb2coTG9nTGV2ZWwuc2lsbHkpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNZXRob2QgZGVjb3JhdG9yIGZvciBsb2dnaW5nIGZ1bmN0aW9uIGNhbGxzIHdpdGggdHJhY2UgbGV2ZWwuXG4gKiBAc3VtbWFyeSBDb252ZW5pZW5jZSB3cmFwcGVyIGFyb3VuZCB7QGxpbmsgbG9nfSB0aGF0IGxvZ3MgdXNpbmcgYExvZ0xldmVsLnRyYWNlYC5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKGFueSwgYW55LCBQcm9wZXJ0eURlc2NyaXB0b3IpOiB2b2lkfSBUcmFjZS1sZXZlbCBsb2dnaW5nIGRlY29yYXRvci5cbiAqIEBmdW5jdGlvbiB0cmFjZVxuICogQGNhdGVnb3J5IE1ldGhvZCBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFjZSgpIHtcbiAgcmV0dXJuIGxvZyhMb2dMZXZlbC50cmFjZSk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE1ldGhvZCBkZWNvcmF0b3IgZm9yIGxvZ2dpbmcgZnVuY3Rpb24gY2FsbHMgd2l0aCB2ZXJib3NlIGxldmVsLlxuICogQHN1bW1hcnkgQ29udmVuaWVuY2Ugd3JhcHBlciBhcm91bmQge0BsaW5rIGxvZ30gdGhhdCBsb2dzIHVzaW5nIGBMb2dMZXZlbC52ZXJib3NlYCB3aXRoIGNvbmZpZ3VyYWJsZSB2ZXJib3NpdHkuXG4gKiBAcmV0dXJuIHtmdW5jdGlvbihhbnksIGFueSwgUHJvcGVydHlEZXNjcmlwdG9yKTogdm9pZH0gVmVyYm9zZSBsb2dnaW5nIGRlY29yYXRvci5cbiAqIEBmdW5jdGlvbiB2ZXJib3NlXG4gKiBAY2F0ZWdvcnkgTWV0aG9kIERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZlcmJvc2UoKTogKFxuICB0YXJnZXQ6IGFueSxcbiAgcHJvcGVydHlLZXk/OiBhbnksXG4gIGRlc2NyaXB0b3I/OiBhbnlcbikgPT4gdm9pZDtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWV0aG9kIGRlY29yYXRvciBmb3IgbG9nZ2luZyBmdW5jdGlvbiBjYWxscyB3aXRoIHZlcmJvc2UgbGV2ZWwuXG4gKiBAc3VtbWFyeSBDb252ZW5pZW5jZSB3cmFwcGVyIGFyb3VuZCB7QGxpbmsgbG9nfSB0aGF0IGxvZ3MgdXNpbmcgYExvZ0xldmVsLnZlcmJvc2VgIHdoaWxlIHRvZ2dsaW5nIGJlbmNobWFya2luZy5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKGFueSwgUHJvcGVydHlEZXNjcmlwdG9yKTogdm9pZH0gVmVyYm9zZSBsb2dnaW5nIGRlY29yYXRvci5cbiAqIEBmdW5jdGlvbiB2ZXJib3NlXG4gKiBAY2F0ZWdvcnkgTWV0aG9kIERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZlcmJvc2UoKTogKFxuICB0YXJnZXQ6IGFueSxcbiAgcHJvcGVydHlLZXk/OiBhbnksXG4gIGRlc2NyaXB0b3I/OiBhbnlcbikgPT4gdm9pZDtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTWV0aG9kIGRlY29yYXRvciBmb3IgbG9nZ2luZyBmdW5jdGlvbiBjYWxscyB3aXRoIHZlcmJvc2UgbGV2ZWwuXG4gKiBAc3VtbWFyeSBDb252ZW5pZW5jZSB3cmFwcGVyIGFyb3VuZCB7QGxpbmsgbG9nfSB0aGF0IGxvZ3MgdXNpbmcgYExvZ0xldmVsLnZlcmJvc2VgIHdpdGggY29uZmlndXJhYmxlIHZlcmJvc2l0eSBhbmQgb3B0aW9uYWwgYmVuY2htYXJraW5nLlxuICogQHBhcmFtIHtudW1iZXJ8Ym9vbGVhbn0gdmVyYm9zaXR5IC0gVmVyYm9zaXR5IGxldmVsIGZvciBsb2cgZmlsdGVyaW5nIG9yIGZsYWcgdG8gZW5hYmxlIGJlbmNobWFya2luZy5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKGFueSwgYW55LFByb3BlcnR5RGVzY3JpcHRvcik6IHZvaWR9IFZlcmJvc2UgbG9nZ2luZyBkZWNvcmF0b3IuXG4gKiBAZnVuY3Rpb24gdmVyYm9zZVxuICogQGNhdGVnb3J5IE1ldGhvZCBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2ZXJib3NlKHZlcmJvc2l0eTogbnVtYmVyIHwgYm9vbGVhbiA9IDApIHtcbiAgaWYgKCF2ZXJib3NpdHkpIHtcbiAgICB2ZXJib3NpdHkgPSAwO1xuICB9XG4gIHJldHVybiBsb2coTG9nTGV2ZWwudmVyYm9zZSwgdmVyYm9zaXR5IGFzIG51bWJlcik7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBkZWNvcmF0b3IgdGhhdCBtYWtlcyBhIG1ldGhvZCBub24tY29uZmlndXJhYmxlLlxuICogQHN1bW1hcnkgUHJldmVudHMgb3ZlcnJpZGluZyBieSBtYXJraW5nIHRoZSBtZXRob2QgZGVzY3JpcHRvciBhcyBub24tY29uZmlndXJhYmxlLCB0aHJvd2luZyBpZiBhcHBsaWVkIHRvIG5vbi1tZXRob2QgdGFyZ2V0cy5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKG9iamVjdCwgYW55LCBQcm9wZXJ0eURlc2NyaXB0b3IpOiBQcm9wZXJ0eURlc2NyaXB0b3J8dW5kZWZpbmVkfSBEZWNvcmF0b3IgdGhhdCBoYXJkZW5zIHRoZSBtZXRob2QgZGVzY3JpcHRvci5cbiAqIEBmdW5jdGlvbiBmaW5hbFxuICogQGNhdGVnb3J5IE1ldGhvZCBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5hbCgpIHtcbiAgcmV0dXJuICh0YXJnZXQ6IG9iamVjdCwgcHJvcGVydHlLZXk/OiBhbnksIGRlc2NyaXB0b3I/OiBhbnkpID0+IHtcbiAgICBpZiAoIWRlc2NyaXB0b3IpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJmaW5hbCBkZWNvcmF0b3IgY2FuIG9ubHkgYmUgdXNlZCBvbiBtZXRob2RzXCIpO1xuICAgIGlmIChkZXNjcmlwdG9yPy5jb25maWd1cmFibGUpIHtcbiAgICAgIGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBkZXNjcmlwdG9yO1xuICB9O1xufVxuIiwiaW1wb3J0IHsgTG9nRmlsdGVyIH0gZnJvbSBcIi4vTG9nRmlsdGVyXCI7XG5pbXBvcnQgeyBMb2dnaW5nQ29uZmlnIH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5pbXBvcnQgeyBmaW5hbCB9IGZyb20gXCIuLi9kZWNvcmF0b3JzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlcGxhY2VtZW50IGNhbGxiYWNrIHVzZWQgdG8gdHJhbnNmb3JtIFJlZ0V4cCBtYXRjaGVzLlxuICogQHN1bW1hcnkgUmVjZWl2ZXMgdGhlIG1hdGNoZWQgc3Vic3RyaW5nIGFuZCBhZGRpdGlvbmFsIGNhcHR1cmUgYXJndW1lbnRzLCByZXR1cm5pbmcgdGhlIHJlcGxhY2VtZW50IHRleHQgdGhhdCB3aWxsIGJlIGluamVjdGVkIGludG8gdGhlIGxvZyBtZXNzYWdlLlxuICogQHR5cGVkZWYge2Z1bmN0aW9uKHN0cmluZywgYW55W10pOiBzdHJpbmd9IFJlcGxhY2VtZW50RnVuY3Rpb25cbiAqIEBtZW1iZXJPZiBtb2R1bGU6TG9nZ2luZ1xuICovXG5leHBvcnQgdHlwZSBSZXBsYWNlbWVudEZ1bmN0aW9uID0gKHN1YnN0cmluZzogc3RyaW5nLCAuLi5hcmdzOiBhbnlbXSkgPT4gc3RyaW5nO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBGaWx0ZXIgdGhhdCBwYXRjaGVzIGxvZyBtZXNzYWdlcyB1c2luZyByZWd1bGFyIGV4cHJlc3Npb25zLlxuICogQHN1bW1hcnkgQXBwbGllcyBhIGNvbmZpZ3VyZWQge0BsaW5rIFJlZ0V4cH0gYW5kIHJlcGxhY2VtZW50IHN0cmF0ZWd5IHRvIHJlZGFjdCwgbWFzaywgb3IgcmVzdHJ1Y3R1cmUgbG9nIHBheWxvYWRzIGJlZm9yZSB0aGV5IGFyZSBlbWl0dGVkLlxuICogQHBhcmFtIHtSZWdFeHB9IHJlZ2V4cCAtIEV4cHJlc3Npb24gdXNlZCB0byBkZXRlY3Qgc2Vuc2l0aXZlIG9yIGZvcm1hdHRlZCB0ZXh0LlxuICogQHBhcmFtIHtzdHJpbmd8UmVwbGFjZW1lbnRGdW5jdGlvbn0gcmVwbGFjZW1lbnQgLSBSZXBsYWNlbWVudCBzdHJpbmcgb3IgY2FsbGJhY2sgaW52b2tlZCBmb3IgZWFjaCBtYXRjaC5cbiAqIEBjbGFzcyBQYXR0ZXJuRmlsdGVyXG4gKiBAZXhhbXBsZVxuICogY29uc3QgZmlsdGVyID0gbmV3IFBhdHRlcm5GaWx0ZXIoL3Rva2VuPVteJl0rL2csIFwidG9rZW49KioqXCIpO1xuICogY29uc3Qgc2FuaXRpemVkID0gZmlsdGVyLmZpbHRlcihjb25maWcsIFwidG9rZW49MTIzJnVzZXI9dG9tXCIsIFtdKTtcbiAqIC8vIHNhbml0aXplZCA9PT0gXCJ0b2tlbj0qKiomdXNlcj10b21cIlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBMb2dnZXJcbiAqICAgcGFydGljaXBhbnQgRmlsdGVyIGFzIFBhdHRlcm5GaWx0ZXJcbiAqICAgcGFydGljaXBhbnQgUmVnRXhwXG4gKiAgIExvZ2dlci0+PkZpbHRlcjogZmlsdGVyKGNvbmZpZywgbWVzc2FnZSwgY29udGV4dClcbiAqICAgRmlsdGVyLT4+UmVnRXhwOiBleGVjdXRlIG1hdGNoKClcbiAqICAgYWx0IG1hdGNoIGZvdW5kXG4gKiAgICAgUmVnRXhwLS0+PkZpbHRlcjogY2FwdHVyZXNcbiAqICAgICBGaWx0ZXItPj5SZWdFeHA6IHJlcGxhY2UobWVzc2FnZSwgcmVwbGFjZW1lbnQpXG4gKiAgICAgUmVnRXhwLS0+PkZpbHRlcjogdHJhbnNmb3JtZWQgbWVzc2FnZVxuICogICBlbHNlIG5vIG1hdGNoXG4gKiAgICAgUmVnRXhwLS0+PkZpbHRlcjogbnVsbFxuICogICBlbmRcbiAqICAgRmlsdGVyLS0+PkxvZ2dlcjogc2FuaXRpemVkIG1lc3NhZ2VcbiAqL1xuZXhwb3J0IGNsYXNzIFBhdHRlcm5GaWx0ZXIgZXh0ZW5kcyBMb2dGaWx0ZXIge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgcmVnZXhwOiBSZWdFeHAsXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHJlcGxhY2VtZW50OiBzdHJpbmcgfCBSZXBsYWNlbWVudEZ1bmN0aW9uXG4gICkge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEVuc3VyZXMgZGV0ZXJtaW5pc3RpYyBSZWdFeHAgbWF0Y2hpbmcuXG4gICAqIEBzdW1tYXJ5IFJ1bnMgdGhlIGNvbmZpZ3VyZWQgZXhwcmVzc2lvbiwgdGhlbiByZXNldHMgaXRzIHN0YXRlIHNvIHJlcGVhdGVkIGludm9jYXRpb25zIGJlaGF2ZSBjb25zaXN0ZW50bHkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gTWVzc2FnZSB0byB0ZXN0IGZvciBtYXRjaGVzLlxuICAgKiBAcmV0dXJuIHtSZWdFeHBFeGVjQXJyYXl8bnVsbH0gTWF0Y2ggcmVzdWx0IG9yIG51bGwgd2hlbiBubyBtYXRjaCBpcyBmb3VuZC5cbiAgICovXG4gIEBmaW5hbCgpXG4gIHByb3RlY3RlZCBtYXRjaChtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICBjb25zdCBtYXRjaCA9IHRoaXMucmVnZXhwLmV4ZWMobWVzc2FnZSk7XG4gICAgdGhpcy5yZWdleHAubGFzdEluZGV4ID0gMDtcbiAgICByZXR1cm4gbWF0Y2g7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFwcGxpZXMgdGhlIHJlcGxhY2VtZW50IHN0cmF0ZWd5IHRvIHRoZSBpbmNvbWluZyBtZXNzYWdlLlxuICAgKiBAc3VtbWFyeSBFeGVjdXRlcyB7QGxpbmsgUGF0dGVybkZpbHRlci5tYXRjaH0gYW5kLCB3aGVuIGEgbWF0Y2ggaXMgZm91bmQsIHJlcGxhY2VzIGV2ZXJ5IG9jY3VycmVuY2UgdXNpbmcgdGhlIGNvbmZpZ3VyZWQgcmVwbGFjZW1lbnQgaGFuZGxlci5cbiAgICogQHBhcmFtIHtMb2dnaW5nQ29uZmlnfSBjb25maWcgLSBBY3RpdmUgbG9nZ2luZyBjb25maWd1cmF0aW9uICh1bnVzZWQgYnV0IHBhcnQgb2YgdGhlIGZpbHRlciBjb250cmFjdCkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gTWVzc2FnZSB0byBiZSBzYW5pdGl6ZWQuXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IGNvbnRleHQgLSBDb250ZXh0IGVudHJpZXMgYXNzb2NpYXRlZCB3aXRoIHRoZSBsb2cgZXZlbnQuXG4gICAqIEByZXR1cm4ge3N0cmluZ30gU2FuaXRpemVkIGxvZyBtZXNzYWdlLlxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBmaWx0ZXIoY29uZmlnOiBMb2dnaW5nQ29uZmlnLCBtZXNzYWdlOiBzdHJpbmcsIGNvbnRleHQ6IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5maWx0ZXIpO1xuICAgIGNvbnN0IG1hdGNoID0gdGhpcy5tYXRjaChtZXNzYWdlKTtcbiAgICBpZiAoIW1hdGNoKSByZXR1cm4gbWVzc2FnZTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIG1lc3NhZ2UucmVwbGFjZSh0aGlzLnJlZ2V4cCwgdGhpcy5yZXBsYWNlbWVudCBhcyBhbnkpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGxvZy5lcnJvcihgUGF0dGVybkZpbHRlciByZXBsYWNlbWVudCBlcnJvcjogJHtlfWApO1xuICAgIH1cbiAgICByZXR1cm4gXCJcIjtcbiAgfVxufVxuIiwiZXhwb3J0IGZ1bmN0aW9uIGlzQ2xhc3MoXG4gIHZhbHVlOiB1bmtub3duXG4pOiB2YWx1ZSBpcyBhYnN0cmFjdCBuZXcgKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnkge1xuICBpZiAodHlwZW9mIHZhbHVlICE9PSBcImZ1bmN0aW9uXCIpIHJldHVybiBmYWxzZTtcblxuICAvLyAxKSBOYXRpdmUgRVMgY2xhc3M/IChmYXN0IHBhdGgpXG4gIC8vIGUuZy4sIFwiY2xhc3MgRm9vIHsgLi4uIH1cIiDihpIgc291cmNlIHN0YXJ0cyB3aXRoIFwiY2xhc3NcIlxuICB0cnkge1xuICAgIGNvbnN0IHNyYyA9IEZ1bmN0aW9uLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKTtcbiAgICBpZiAoL15cXHMqY2xhc3NbXFxze10vLnRlc3Qoc3JjKSkgcmV0dXJuIHRydWU7XG4gIH0gY2F0Y2gge1xuICAgIC8vIFNvbWUgZW52aXJvbm1lbnRzIG1heSBibG9jayAudG9TdHJpbmc7IGlnbm9yZSBhbmQgY29udGludWUuXG4gIH1cblxuICAvLyAyKSBIYXMgYSBwcm90b3R5cGUgYXQgYWxsPyAoZmlsdGVycyBvdXQgYXJyb3cgZnVuY3MsIGJvdW5kIGZ1bmNzKVxuICBjb25zdCBwcm90b0Rlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHZhbHVlLCBcInByb3RvdHlwZVwiKTtcbiAgaWYgKCFwcm90b0Rlc2MgfHwgIXByb3RvRGVzYy52YWx1ZSkgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIDMpIEluIG5hdGl2ZSBjbGFzc2VzLCB0aGUgXCJwcm90b3R5cGVcIiBwcm9wZXJ0eSBpcyBub24td3JpdGFibGUuXG4gIC8vIChJbiBwbGFpbiBmdW5jdGlvbnMsIGl0J3Mgd3JpdGFibGUuKSBUaGlzIGlzIGEgc3Ryb25nIHNpZ25hbC5cbiAgaWYgKHByb3RvRGVzYy53cml0YWJsZSA9PT0gZmFsc2UpIHJldHVybiB0cnVlO1xuXG4gIC8vIDQpIENsYXNzaWMgY29uc3RydWN0b3Igb3IgdHJhbnNwaWxlZCBjbGFzczpcbiAgLy8gTXVzdCBoYXZlIGl0cyBvd24gXCJjb25zdHJ1Y3RvclwiIGFuZCBhdCBsZWFzdCBvbmUgcHJvdG90eXBlIG1ldGhvZC5cbiAgY29uc3QgcHJvdG8gPSAodmFsdWUgYXMgYW55KS5wcm90b3R5cGU7XG4gIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHByb3RvLCBcImNvbnN0cnVjdG9yXCIpKSByZXR1cm4gZmFsc2U7XG5cbiAgY29uc3QgbmFtZXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhwcm90bykuZmlsdGVyKFxuICAgIChuKSA9PiBuICE9PSBcImNvbnN0cnVjdG9yXCJcbiAgKTtcbiAgcmV0dXJuIG5hbWVzLmxlbmd0aCA+IDA7XG59XG4iLCJleHBvcnQgKiBmcm9tIFwiLi9maWx0ZXJzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2RlY29yYXRvcnNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2Vudmlyb25tZW50XCI7XG5leHBvcnQgKiBmcm9tIFwiLi9Mb2dnZWRDbGFzc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vbG9nZ2luZ1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vdGV4dFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vdGltZVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vdHlwZXNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3dlYlwiO1xuZXhwb3J0ICogZnJvbSBcIi4vdXRpbHNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ29tcHJlaGVuc2l2ZSBsb2dnaW5nIHRvb2xraXQgZm9yIGJyb3dzZXIgYW5kIE5vZGUgZW52aXJvbm1lbnRzLlxuICogQHN1bW1hcnkgRXhwb3NlcyB7QGxpbmsgTG9nZ2luZ30gYW5kIHtAbGluayBNaW5pTG9nZ2VyfSBmb3IgcnVudGltZSBsb2dnaW5nLCBkZWNvcmF0b3JzIHN1Y2ggYXMge0BsaW5rIGxvZ30gZm9yIG1ldGhvZCBpbnN0cnVtZW50YXRpb24sIGFuZCB1dGlsaXRpZXMgbGlrZSB7QGxpbmsgUGF0dGVybkZpbHRlcn0sIHtAbGluayBTdG9wV2F0Y2h9LCBhbmQge0BsaW5rIExvZ2dlZEVudmlyb25tZW50fSB0byBidWlsZCBjb25maWd1cmFibGUsIHRoZW1lLWF3YXJlIGxvZyBwaXBlbGluZXMuXG4gKiBAbW9kdWxlIExvZ2dpbmdcbiAqL1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDdXJyZW50IHBhY2thZ2UgdmVyc2lvbiBzdHJpbmcuXG4gKiBAc3VtbWFyeSBTdG9yZXMgdGhlIHBhY2thZ2UgdmVyc2lvbiBmb3IgZGlhZ25vc3RpY3MgYW5kIGNvbXBhdGliaWxpdHkgY2hlY2tzLlxuICogQGNvbnN0IFZFUlNJT05cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAbWVtYmVyT2YgbW9kdWxlOkxvZ2dpbmdcbiAqL1xuZXhwb3J0IGNvbnN0IFZFUlNJT046IHN0cmluZyA9IFwiIyNWRVJTSU9OIyNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3VycmVudCBwYWNrYWdlIHZlcnNpb24gc3RyaW5nLlxuICogQHN1bW1hcnkgU3RvcmVzIHRoZSBwYWNrYWdlIHZlcnNpb24gZm9yIGRpYWdub3N0aWNzIGFuZCBjb21wYXRpYmlsaXR5IGNoZWNrcy5cbiAqIEBjb25zdCBQQUNLQUdFX05BTUVcbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAbWVtYmVyT2YgbW9kdWxlOkxvZ2dpbmdcbiAqL1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfTkFNRTogc3RyaW5nID0gXCIjI1BBQ0tBR0UjI1wiO1xuIl0sIm5hbWVzIjpbIkxvZ0xldmVsIiwiTG9nZ2luZ01vZGUiLCJPYmplY3RBY2N1bXVsYXRvciIsInN0eWxlIiwiX19kZWNvcmF0ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0lBRUE7Ozs7OztJQU1HO0FBQ0ksVUFBTSxhQUFhLEdBQUcsTUFBTTtJQUVuQzs7Ozs7O0lBTUc7QUFDSSxVQUFNLGtCQUFrQixHQUFHLEtBQUs7SUFFdkM7Ozs7OztJQU1HO1VBQ1UsMEJBQTBCLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFO0lBRXREOzs7Ozs7SUFNRztBQUNTQSw4QkFpQlg7SUFqQkQsQ0FBQSxVQUFZLFFBQVEsRUFBQTs7SUFFbEIsSUFBQSxRQUFBLENBQUEsV0FBQSxDQUFBLEdBQUEsV0FBdUIsQ0FBQTs7SUFFdkIsSUFBQSxRQUFBLENBQUEsT0FBQSxDQUFBLEdBQUEsT0FBZSxDQUFBOztJQUVmLElBQUEsUUFBQSxDQUFBLE1BQUEsQ0FBQSxHQUFBLE1BQWEsQ0FBQTs7SUFFYixJQUFBLFFBQUEsQ0FBQSxNQUFBLENBQUEsR0FBQSxNQUFhLENBQUE7O0lBRWIsSUFBQSxRQUFBLENBQUEsU0FBQSxDQUFBLEdBQUEsU0FBbUIsQ0FBQTs7SUFFbkIsSUFBQSxR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
1
+ var e,t;e=this,t=function(e,t,r,o){"use strict";const n="ENV",s="__",i=["${","}"];var a;e.LogLevel=void 0,(a=e.LogLevel||(e.LogLevel={})).benchmark="benchmark",a.error="error",a.warn="warn",a.info="info",a.verbose="verbose",a.debug="debug",a.trace="trace",a.silly="silly";const c={benchmark:0,error:3,warn:6,info:9,verbose:12,debug:15,trace:18,silly:21};var l;e.LoggingMode=void 0,(l=e.LoggingMode||(e.LoggingMode={})).RAW="raw",l.JSON="json";const g={app:{},separator:{},class:{fg:34},id:{fg:36},stack:{},timestamp:{},message:{error:{fg:31}},method:{},logLevel:{benchmark:{fg:32,style:["bold"]},error:{fg:31,style:["bold"]},info:{fg:34,style:["bold"]},verbose:{fg:34,style:["bold"]},debug:{fg:33,style:["bold"]},trace:{fg:33,style:["bold"]},silly:{fg:33,style:["bold"]}}},f={env:"development",verbose:0,level:e.LogLevel.info,logLevel:!0,style:!1,contextSeparator:".",separator:"-",timestamp:!0,timestampFormat:"HH:mm:ss.SSS",context:!0,format:e.LoggingMode.RAW,pattern:"{level} [{timestamp}] {app} {context} {separator} {message} {stack}",theme:g};function u(e,t,r="g"){return Object.entries(t).forEach(([t,o])=>{const n=RegExp(d(t),r);e=e.replace(n,o)}),e}function h(e){return p(e).toUpperCase()}function p(e){return e.replace(/([a-z])([A-Z])/g,"$1_$2").replace(/[\s-]+/g,"_").toLowerCase()}function d(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function b(e,...t){if(t.length>1&&!t.every(e=>"string"==typeof e||"number"==typeof e))throw Error("Only string and number arguments are supported for multiple replacements.");if(1===t.length&&"object"==typeof t[0]){const r=t[0];return Object.entries(r).reduce((e,[t,r])=>e.replace(RegExp(`\\{${t}\\}`,"g"),()=>r),e)}return e.replace(/{(\d+)}/g,(e,r)=>void 0!==t[r]?t[r].toString():"undefined")}const y=b;function m(){return Object.getPrototypeOf(Object.getPrototypeOf(globalThis))!==Object.prototype}const v=Symbol("EnvironmentEmpty"),L=Symbol("EnvironmentModel");class w extends r.ObjectAccumulator{static{this.factory=()=>new w}constructor(){super(),Object.defineProperty(this,L,{value:{},writable:!0,enumerable:!1,configurable:!1})}fromEnv(e){let t;return m()?t=globalThis[n]||{}:(t=globalThis.process.env,e=h(e)),this.parseEnvValue(t[e])}parseEnvValue(e){if("string"!=typeof e)return e;if("true"===e)return!0;if("false"===e)return!1;const t=parseFloat(e);return isNaN(t)?e:t}expand(e){Object.entries(e).forEach(([e,t])=>{w.mergeModel(this[L],e,t),Object.defineProperty(this,e,{get:()=>{const r=this.fromEnv(e);return void 0!==r?r:t&&"object"==typeof t?w.buildEnvProxy(t,[e]):""===t?v:t},set:e=>{t=e},configurable:!0,enumerable:!0})})}orThrow(){const e=this[L],t=e=>e.map(e=>h(e)).join(s),r=e=>w.readRuntimeEnv(e),o=e=>void 0!==e?this.parseEnvValue(e):void 0,n=(e,t=!1)=>w.missingEnvError(e,t),i=(e,s)=>new Proxy({},{get(a,c){if("string"!=typeof c)return;const l=[...s,c],g=t(l),f=r(g);if("string"==typeof f&&0===f.length)throw n(g,!0);const u=o(f);if(void 0!==u){if("string"==typeof u&&0===u.length)throw n(g,!0);return u}if(!e||!Object.prototype.hasOwnProperty.call(e,c))throw n(g);const h=e[c];if(void 0!==h){if(""===h)throw n(g);return h&&"object"==typeof h&&!Array.isArray(h)?i(h,l):h}},ownKeys:()=>e?Reflect.ownKeys(e):[],getOwnPropertyDescriptor(t,r){if(e)return Object.prototype.hasOwnProperty.call(e,r)?{enumerable:!0,configurable:!0}:void 0}});return new Proxy(this,{get(s,a,c){if("string"!=typeof a)return Reflect.get(s,a,c);if(!Object.prototype.hasOwnProperty.call(e,a))return Reflect.get(s,a,c);const l=t([a]),g=r(l);if("string"==typeof g&&0===g.length)throw n(l,!0);const f=o(g);if(void 0!==f){if("string"==typeof f&&0===f.length)throw n(l,!0);return f}const u=e[a];if(u&&"object"==typeof u&&!Array.isArray(u))return i(u,[a]);if(void 0===u)return Reflect.get(s,a,c);const h=Reflect.get(s,a);if(void 0===h||""===h)throw n(l,""===h);return h}})}static instance(...e){if(!w._instance){const t=w.factory(...e),r=new Proxy(t,{get(e,t,r){const o=Reflect.get(e,t,r);if(o!==v&&("string"!=typeof t||!Object.prototype.hasOwnProperty.call(e,t)||void 0!==o)){if(void 0!==o)return o;if("string"==typeof t){if("app"===t)return;return w.buildEnvProxy(void 0,[t])}return o}}});w._instance=r}return w._instance}static accumulate(e){const t=w.instance();return Object.keys(t).forEach(e=>{const r=Object.getOwnPropertyDescriptor(t,e);r&&r.configurable&&r.enumerable&&Object.defineProperty(t,e,{...r,enumerable:!1})}),t.accumulate(e)}static get(e){return w._instance.get(e)}static buildEnvProxy(e,t){const r=e=>e.map(e=>h(e)).join(s);return new Proxy({},{get(o,n){if(n===Symbol.toPrimitive)return()=>r(t);if("toString"===n)return()=>r(t);if("valueOf"===n)return()=>r(t);if("symbol"==typeof n)return;const s=!!e&&Object.prototype.hasOwnProperty.call(e,n),i=s?e[n]:void 0,a=[...t,n],c=(l=r(a),w.readRuntimeEnv(l));var l;return void 0!==c?c:i&&"object"==typeof i?w.buildEnvProxy(i,a):s&&""===i||s&&void 0===i?void 0:w.buildEnvProxy(void 0,a)},ownKeys:()=>e?Reflect.ownKeys(e):[],getOwnPropertyDescriptor(t,r){if(e)return Object.prototype.hasOwnProperty.call(e,r)?{enumerable:!0,configurable:!0}:void 0}})}static keys(e=!0){return w.instance().keys().map(t=>e?h(t):t)}static mergeModel(e,t,r){if(e){if(r&&"object"==typeof r&&!Array.isArray(r)){const o=e[t],n=o&&"object"==typeof o&&!Array.isArray(o)?o:{};return e[t]=n,void Object.entries(r).forEach(([e,t])=>{w.mergeModel(n,e,t)})}e[t]=r}}static readRuntimeEnv(e){if(m()){const t=globalThis[n];return t?t[e]:void 0}return globalThis?.process?.env?.[e]}static missingEnvError(e,t){return Error(`Environment variable ${e} is required but was ${t?"an empty string":"undefined"}.`)}}const _=w.accumulate(Object.assign({},f,{env:(m()&&globalThis[n]?globalThis[n].NODE_ENV:globalThis.process.env.NODE_ENV)||"development"}));class E{constructor(e,t){this.context=e,this.conf=t}config(e){return this.conf&&e in this.conf?this.conf[e]:O.getConfig()[e]}for(e,t,...r){return t||"object"!=typeof e?e=e?"string"==typeof e?e:e.name:void 0:(t=e,e=void 0),new Proxy(this,{get:(r,o,n)=>{const s=Reflect.get(r,o,n);return"config"===o?new Proxy(this.config,{get:(e,r)=>t&&r in t?t[r]:Reflect.get(e,r,n)}):"context"===o&&e?[s,e].join("."):s}})}createLog(e,t,r){const o={},n=this.config("style"),s=this.config("separator"),i=this.config("app");if(i&&(o.app=n?O.theme(i,"app",e):i),s&&(o.separator=n?O.theme(s,"separator",e):s),this.config("timestamp")){const t=(new Date).toISOString(),r=n?O.theme(t,"timestamp",e):t;o.timestamp=r}if(this.config("logLevel")){const t=n?O.theme(e,"logLevel",e):e;o.level=t.toUpperCase()}if(this.config("context")){const t=n?O.theme(this.context,"class",e):this.context;o.context=t}if(this.config("correlationId")){const t=n?O.theme(this.config("correlationId").toString(),"id",e):this.config("correlationId").toString();o.correlationId=t}const a=n?O.theme("string"==typeof t?t:t.message,"message",e):"string"==typeof t?t:t.message;if(o.message=a,r||t instanceof Error){const s=n?O.theme(r?.stack||t.stack,"stack",e):r?.stack||"";o.stack=` | ${(r||t).message} - Stack trace:\n${s}`}switch(this.config("format")){case"json":return JSON.stringify(o);case"raw":return this.config("pattern").split(" ").map(e=>{if(!e.match(/\{.*?}/g))return e;const t=b(e,o);return t!==e?t:void 0}).filter(e=>e).join(" ");default:throw Error("Unsupported logging format: "+this.config("format"))}}log(t,r,o){const n=this.config("level");if(c[t]>c[n])return;let s;switch(t){case e.LogLevel.benchmark:case e.LogLevel.info:s=console.log;break;case e.LogLevel.verbose:case e.LogLevel.debug:s=console.debug;break;case e.LogLevel.error:s=console.error;break;case e.LogLevel.trace:case e.LogLevel.silly:s=console.trace;break;default:throw Error("Invalid log level")}s(this.createLog(t,r,o))}benchmark(t){this.log(e.LogLevel.benchmark,t)}silly(t,r=0){this.config("verbose")<r||this.log(e.LogLevel.verbose,t)}verbose(t,r=0){this.config("verbose")<r||this.log(e.LogLevel.verbose,t)}info(t){this.log(e.LogLevel.info,t)}debug(t){this.log(e.LogLevel.debug,t)}error(t,r){this.log(e.LogLevel.error,t,r)}warn(t){this.log(e.LogLevel.warn,t)}trace(t){this.log(e.LogLevel.trace,t)}setConfig(e){this.conf={...this.conf||{},...e}}}class O{static{this._factory=(e,t)=>new E(e,t)}static{this._config=_}constructor(){}static setFactory(e){O._factory=e}static setConfig(e){Object.entries(e).forEach(([e,t])=>{this._config[e]=t})}static getConfig(){return this._config}static get(){return this.global=this.global?this.global:this._factory("Logging"),this.global}static verbose(e,t=0){return this.get().verbose(e,t)}static info(e){return this.get().info(e)}static trace(e){return this.get().trace(e)}static debug(e){return this.get().debug(e)}static benchmark(e){return this.get().benchmark(e)}static silly(e){return this.get().silly(e)}static warn(e){return this.get().warn(e)}static error(e,t){return this.get().error(e,t)}static for(e,t,...r){return e="string"==typeof e?e:e.constructor?e.constructor.name:e.name,this._factory(e,t,...r)}static because(e,t){return this._factory(e,this._config,t)}static theme(r,o,n,s=g){if(!this._config.style)return r;const i=s[o];if(!i||!Object.keys(i).length)return r;let a=i;const c=Object.assign({},e.LogLevel);return Object.keys(i)[0]in c&&(a=i[n]||{}),Object.keys(a).reduce((e,r)=>{const o=a[r];return o?((e,r,o)=>{try{const n=e;let s=t.style(n);function i(e,r=!1){let i=r?s.background:s.foreground;if(!Array.isArray(e))return i.call(s,o);switch(e.length){case 1:return i=r?s.bgColor256:s.color256,i(e[0]);case 3:return i=r?s.bgRgb:s.rgb,s.rgb(e[0],e[1],e[2]);default:return t.style(n)}}function a(e){s="number"==typeof e?s.style(e):s[e]}switch(r){case"bg":case"fg":return i(o).text;case"style":return Array.isArray(o)?o.forEach(a):a(o),s.text;default:return n}}catch(c){return e}})(e,r,o):e},r)}}class j{get log(){return this._log||(this._log=O.for(this)),this._log}constructor(){}}class M extends j{get log(){return super.log.for(this,{filters:[]})}}const x="undefined"!=typeof globalThis&&"function"==typeof globalThis.performance?.now?()=>globalThis.performance.now():"undefined"!=typeof process&&"function"==typeof process.hrtime?.bigint?()=>{const e=process.hrtime.bigint();return Number(e)/1e6}:()=>Date.now();function P(e){const t=0>e?"-":"",r=Math.abs(e),o=Math.floor(r/36e5),n=Math.floor(r%36e5/6e4),s=Math.floor(r%6e4/1e3),i=Math.floor(r%1e3),a=(e,t)=>e.toString().padStart(t,"0");return`${t}${a(o,2)}:${a(n,2)}:${a(s,2)}.${a(i,3)}`}function k(t=e.LogLevel.info,r=0,o=(...e)=>"called with "+e,n){return(e,s,i)=>{if(!i||"number"==typeof i)throw Error("Logging decoration only applies to methods");const a=e instanceof j?e.log.for(e[s]):O.for(e).for(e[s]),c=a[t].bind(a),l=i.value;return i.value=new Proxy(l,{apply(e,t,s){c(o(...s),r);try{const r=Reflect.apply(e,t,s);return r instanceof Promise?r.then(e=>(n&&c(n(void 0,e)),e)).catch(e=>{throw n&&a.error(n(e)),e}):(n&&c(n(void 0,r)),r)}catch(e){throw n&&a.error(n(e)),e}}}),i}}function S(){return(e,t,r)=>{if(!r)throw Error("final decorator can only be used on methods");return r?.configurable&&(r.configurable=!1),r}}class A extends M{constructor(e,t){super(),this.regexp=e,this.replacement=t}match(e){const t=this.regexp.exec(e);return this.regexp.lastIndex=0,t}filter(e,t,r){const o=this.log.for(this.filter);if(!this.match(t))return t;try{return t.replace(this.regexp,this.replacement)}catch(e){o.error("PatternFilter replacement error: "+e)}return""}}o.__decorate([S(),o.__metadata("design:type",Function),o.__metadata("design:paramtypes",[String]),o.__metadata("design:returntype",void 0)],A.prototype,"match",null),e.BrowserEnvKey=n,e.DefaultLoggingConfig=f,e.DefaultPlaceholderWrappers=i,e.DefaultTheme=g,e.ENV_PATH_DELIMITER=s,e.Environment=w,e.LogFilter=M,e.LoggedClass=j,e.LoggedEnvironment=_,e.Logging=O,e.MiniLogger=E,e.NumericLogLevels=c,e.PACKAGE_NAME="##PACKAGE##",e.PatternFilter=A,e.StopWatch=class{constructor(e=!1){this._startMs=null,this._elapsedMs=0,this._running=!1,this._laps=[],this._lastLapTotalMs=0,e&&this.start()}get running(){return this._running}get elapsedMs(){return this._running&&null!=this._startMs?this._elapsedMs+(x()-this._startMs):this._elapsedMs}start(){return this._running||(this._running=!0,this._startMs=x()),this}pause(){return this._running&&null!=this._startMs&&(this._elapsedMs+=x()-this._startMs,this._startMs=null,this._running=!1),this}resume(){return this._running||(this._running=!0,this._startMs=x()),this}stop(){return this.pause(),this._elapsedMs}reset(){const e=this._running;return this._startMs=e?x():null,this._elapsedMs=0,this._laps=[],this._lastLapTotalMs=0,this}lap(e){const t=this.elapsedMs,r=t-this._lastLapTotalMs,o={index:this._laps.length,label:e,ms:r,totalMs:t};return this._laps.push(o),this._lastLapTotalMs=t,o}get laps(){return this._laps}toString(){return P(this.elapsedMs)}toJSON(){return{running:this._running,elapsedMs:this.elapsedMs,laps:this._laps.slice()}}},e.VERSION="##VERSION##",e.benchmark=()=>(e,t,r)=>{if(!r||"number"==typeof r)throw Error("benchmark decoration only applies to methods");const o=e instanceof j?e.log.for(e[t]):O.for(e).for(e[t]),n=r.value;return r.value=new Proxy(n,{apply(e,t,r){const n=x();try{const s=Reflect.apply(e,t,r);return s instanceof Promise?s.then(e=>(o.benchmark(`completed in ${x()-n}ms`),e)).catch(e=>{throw o.benchmark(`failed in ${x()-n}ms`),e}):(o.benchmark(`completed in ${x()-n}ms`),s)}catch(e){throw o.benchmark(`failed in ${x()-n}ms`),e}}}),r},e.debug=()=>k(e.LogLevel.debug,0,(...e)=>"called with "+e,(e,t)=>e?"Failed with: "+e:t?"Completed with "+JSON.stringify(t):"completed"),e.escapeRegExp=d,e.final=S,e.formatMs=P,e.info=()=>k(e.LogLevel.info),e.isBrowser=m,e.isClass=e=>{if("function"!=typeof e)return!1;try{const t=Function.prototype.toString.call(e);if(/^\s*class[\s{]/.test(t))return!0}catch{}const t=Object.getOwnPropertyDescriptor(e,"prototype");if(!t||!t.value)return!1;if(!1===t.writable)return!0;const r=e.prototype;return!!Object.prototype.hasOwnProperty.call(r,"constructor")&&Object.getOwnPropertyNames(r).filter(e=>"constructor"!==e).length>0},e.log=k,e.now=x,e.padEnd=(e,t,r=" ")=>{if(1!==r.length)throw Error("Invalid character length for padding. must be one!");return e.padEnd(t,r)},e.patchPlaceholders=(e,t,r=i[0],o=i[1],n="g")=>u(e,Object.entries(t).reduce((e,[t,n])=>(e[`${r}${t}${o}`]=n,e),{}),n),e.patchString=u,e.sf=b,e.silly=()=>k(e.LogLevel.silly),e.stringFormat=y,e.toCamelCase=e=>e.replace(/(?:^\w|[A-Z]|\b\w)/g,(e,t)=>0===t?e.toLowerCase():e.toUpperCase()).replace(/\s+/g,""),e.toENVFormat=h,e.toKebabCase=e=>e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[\s_]+/g,"-").toLowerCase(),e.toPascalCase=e=>e.replace(/(?:^\w|[A-Z]|\b\w)/g,e=>e.toUpperCase()).replace(/\s+/g,""),e.toSnakeCase=p,e.trace=()=>k(e.LogLevel.trace),e.verbose=(t=0)=>(t||(t=0),k(e.LogLevel.verbose,t))},"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("styled-string-builder"),require("typed-object-accumulator"),require("tslib")):"function"==typeof define&&define.amd?define(["exports","styled-string-builder","typed-object-accumulator","tslib"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).logging={},e.styledStringBuilder,e.typedObjectAccumulator,e.tslib);
2
+ //# sourceMappingURL=logging.cjs.map