@decaf-ts/utils 0.3.12 → 0.4.0

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.
@@ -1,4018 +1 @@
1
- import prompts from 'prompts';
2
- import { parseArgs } from 'util';
3
- import { Logging, patchString, LoggedClass, LoggedEnvironment } from '@decaf-ts/logging';
4
- import fs from 'fs';
5
- import path from 'path';
6
- import { spawn } from 'child_process';
7
- import { style } from 'styled-string-builder';
8
- import https from 'https';
9
- import { rollup } from 'rollup';
10
- import typescript from '@rollup/plugin-typescript';
11
- import commonjs from '@rollup/plugin-commonjs';
12
- import { nodeResolve } from '@rollup/plugin-node-resolve';
13
- import json from '@rollup/plugin-json';
14
- import * as ts from 'typescript';
15
- import { ModuleKind } from 'typescript';
16
-
17
- /**
18
- * @description Represents a user input prompt with various configuration options.
19
- * @summary This class provides a flexible interface for creating and managing user input prompts.
20
- * It implements the PromptObject interface from the 'prompts' library and offers methods to set
21
- * various properties of the prompt. The class also includes static methods for common input scenarios
22
- * and argument parsing.
23
- *
24
- * @template R - The type of the prompt name, extending string.
25
- *
26
- * @param name - The name of the prompt, used as the key in the returned answers object.
27
- *
28
- * @class
29
- * @example
30
- * ```typescript
31
- * import { UserInput } from '@decaf-ts/utils';
32
- *
33
- * // Create a simple text input
34
- * const nameInput = new UserInput('name')
35
- * .setMessage('What is your name?')
36
- * .setInitial('User');
37
- *
38
- * // Create a number input with validation
39
- * const ageInput = new UserInput('age')
40
- * .setType('number')
41
- * .setMessage('How old are you?')
42
- * .setMin(0)
43
- * .setMax(120);
44
- *
45
- * // Ask for input and process the results
46
- * async function getUserInfo() {
47
- * const answers = await UserInput.ask([nameInput, ageInput]);
48
- * console.log(`Hello ${answers.name}, you are ${answers.age} years old.`);
49
- * }
50
- *
51
- * getUserInfo();
52
- * ```
53
- *
54
- * @mermaid
55
- * sequenceDiagram
56
- * participant Client
57
- * participant UserInput
58
- * participant PromptLibrary
59
- *
60
- * Client->>UserInput: new UserInput(name)
61
- * Client->>UserInput: setMessage(message)
62
- * Client->>UserInput: setType(type)
63
- * Client->>UserInput: setInitial(initial)
64
- * Client->>UserInput: Other configuration methods
65
- *
66
- * Client->>UserInput: ask()
67
- * UserInput->>PromptLibrary: prompts(question)
68
- * PromptLibrary->>Client: Display prompt
69
- * Client->>PromptLibrary: User provides input
70
- * PromptLibrary->>UserInput: Return answers
71
- * UserInput->>Client: Return processed answers
72
- */
73
- class UserInput {
74
- static { this.logger = Logging.for(UserInput); }
75
- constructor(name) {
76
- /**
77
- * @description The type of the prompt.
78
- * @summary Determines the input method (e.g., text, number, confirm).
79
- */
80
- this.type = "text";
81
- this.name = name;
82
- }
83
- /**
84
- * @description Sets the type of the prompt.
85
- * @summary Configures the input method for the prompt.
86
- *
87
- * @param type - The type of the prompt.
88
- * @returns This UserInput instance for method chaining.
89
- */
90
- setType(type) {
91
- UserInput.logger.verbose(`Setting type to: ${type}`);
92
- this.type = type;
93
- return this;
94
- }
95
- /**
96
- * @description Sets the message of the prompt.
97
- * @summary Configures the question or instruction presented to the user.
98
- *
99
- * @param value - The message to be displayed.
100
- * @returns This UserInput instance for method chaining.
101
- */
102
- setMessage(value) {
103
- UserInput.logger.verbose(`Setting message to: ${value}`);
104
- this.message = value;
105
- return this;
106
- }
107
- /**
108
- * @description Sets the initial value of the prompt.
109
- * @summary Configures the default value presented to the user.
110
- *
111
- * @param value - The initial value.
112
- * @returns This UserInput instance for method chaining.
113
- */
114
- setInitial(value) {
115
- UserInput.logger.verbose(`Setting initial value to: ${value}`);
116
- this.initial = value;
117
- return this;
118
- }
119
- /**
120
- * @description Sets the style of the prompt.
121
- * @summary Configures the visual style of the prompt.
122
- *
123
- * @param value - The style to be applied.
124
- * @returns This UserInput instance for method chaining.
125
- */
126
- setStyle(value) {
127
- UserInput.logger.verbose(`Setting style to: ${value}`);
128
- this.style = value;
129
- return this;
130
- }
131
- /**
132
- * @description Sets the format function of the prompt.
133
- * @summary Configures a function to format the user's input before it's returned.
134
- *
135
- * @param value - The format function.
136
- * @returns This UserInput instance for method chaining.
137
- */
138
- setFormat(value) {
139
- UserInput.logger.verbose(`Setting format function`);
140
- this.format = value;
141
- return this;
142
- }
143
- /**
144
- * @description Sets the validation function of the prompt.
145
- * @summary Configures a function to validate the user's input.
146
- *
147
- * @param value - The validation function.
148
- * @returns This UserInput instance for method chaining.
149
- */
150
- setValidate(value) {
151
- UserInput.logger.verbose(`Setting validate function`);
152
- this.validate = value;
153
- return this;
154
- }
155
- /**
156
- * @description Sets the onState callback of the prompt.
157
- * @summary Configures a function to be called when the state of the prompt changes.
158
- *
159
- * @param value - The onState callback function.
160
- * @returns This UserInput instance for method chaining.
161
- */
162
- setOnState(value) {
163
- UserInput.logger.verbose(`Setting onState callback`);
164
- this.onState = value;
165
- return this;
166
- }
167
- /**
168
- * @description Sets the minimum value for number inputs.
169
- * @summary Configures the lowest number the user can input.
170
- *
171
- * @param value - The minimum value.
172
- * @returns This UserInput instance for method chaining.
173
- */
174
- setMin(value) {
175
- UserInput.logger.verbose(`Setting min value to: ${value}`);
176
- this.min = value;
177
- return this;
178
- }
179
- /**
180
- * @description Sets the maximum value for number inputs.
181
- * @summary Configures the highest number the user can input.
182
- *
183
- * @param value - The maximum value.
184
- * @returns This UserInput instance for method chaining.
185
- */
186
- setMax(value) {
187
- UserInput.logger.verbose(`Setting max value to: ${value}`);
188
- this.max = value;
189
- return this;
190
- }
191
- /**
192
- * @description Sets whether to allow float values for number inputs.
193
- * @summary Configures whether decimal numbers are allowed.
194
- *
195
- * @param value - Whether to allow float values.
196
- * @returns This UserInput instance for method chaining.
197
- */
198
- setFloat(value) {
199
- UserInput.logger.verbose(`Setting float to: ${value}`);
200
- this.float = value;
201
- return this;
202
- }
203
- /**
204
- * @description Sets the number of decimal places to round to for float inputs.
205
- * @summary Configures the precision of float inputs.
206
- *
207
- * @param value - The number of decimal places.
208
- * @returns This UserInput instance for method chaining.
209
- */
210
- setRound(value) {
211
- UserInput.logger.verbose(`Setting round to: ${value}`);
212
- this.round = value;
213
- return this;
214
- }
215
- /**
216
- * @description Sets the instructions for the user.
217
- * @summary Configures additional guidance provided to the user.
218
- *
219
- * @param value - The instructions.
220
- * @returns This UserInput instance for method chaining.
221
- */
222
- setInstructions(value) {
223
- UserInput.logger.verbose(`Setting instructions to: ${value}`);
224
- this.instructions = value;
225
- return this;
226
- }
227
- /**
228
- * @description Sets the increment value for number inputs.
229
- * @summary Configures the step size when increasing or decreasing the number.
230
- *
231
- * @param value - The increment value.
232
- * @returns This UserInput instance for method chaining.
233
- */
234
- setIncrement(value) {
235
- UserInput.logger.verbose(`Setting increment to: ${value}`);
236
- this.increment = value;
237
- return this;
238
- }
239
- /**
240
- * @description Sets the separator for list inputs.
241
- * @summary Configures the character used to separate list items.
242
- *
243
- * @param value - The separator character.
244
- * @returns This UserInput instance for method chaining.
245
- */
246
- setSeparator(value) {
247
- UserInput.logger.verbose(`Setting separator to: ${value}`);
248
- this.separator = value;
249
- return this;
250
- }
251
- /**
252
- * @description Sets the active option style for select inputs.
253
- * @summary Configures the style applied to the currently selected option.
254
- *
255
- * @param value - The active option style.
256
- * @returns This UserInput instance for method chaining.
257
- */
258
- setActive(value) {
259
- UserInput.logger.verbose(`Setting active style to: ${value}`);
260
- this.active = value;
261
- return this;
262
- }
263
- /**
264
- * @description Sets the inactive option style for select inputs.
265
- * @summary Configures the style applied to non-selected options.
266
- *
267
- * @param value - The inactive option style.
268
- * @returns This UserInput instance for method chaining.
269
- */
270
- setInactive(value) {
271
- UserInput.logger.verbose(`Setting inactive style to: ${value}`);
272
- this.inactive = value;
273
- return this;
274
- }
275
- /**
276
- * @description Sets the choices for select, multiselect, or autocomplete inputs.
277
- * @summary Configures the available options that the user can select from in choice-based prompts.
278
- *
279
- * @param value - The array of choices or a function to determine the choices.
280
- * @returns This UserInput instance for method chaining.
281
- */
282
- setChoices(value) {
283
- UserInput.logger.verbose(`Setting choices: ${JSON.stringify(value)}`);
284
- this.choices = value;
285
- return this;
286
- }
287
- /**
288
- * @description Sets the hint text for the prompt.
289
- * @summary Configures additional information displayed to the user.
290
- *
291
- * @param value - The hint text.
292
- * @returns This UserInput instance for method chaining.
293
- */
294
- setHint(value) {
295
- UserInput.logger.verbose(`Setting hint to: ${value}`);
296
- this.hint = value;
297
- return this;
298
- }
299
- /**
300
- * @description Sets the warning text for the prompt.
301
- * @summary Configures a warning message displayed to the user.
302
- *
303
- * @param value - The warning text.
304
- * @returns This UserInput instance for method chaining.
305
- */
306
- setWarn(value) {
307
- UserInput.logger.verbose(`Setting warn to: ${value}`);
308
- this.warn = value;
309
- return this;
310
- }
311
- /**
312
- * @description Sets the suggestion function for autocomplete inputs.
313
- * @summary Configures a function that provides suggestions based on the user's input and available choices.
314
- *
315
- * @param value - A function that takes the current input and available choices and returns a Promise resolving to suggestions.
316
- * @returns This UserInput instance for method chaining.
317
- */
318
- setSuggest(value) {
319
- UserInput.logger.verbose(`Setting suggest function`);
320
- this.suggest = value;
321
- return this;
322
- }
323
- /**
324
- * @description Sets the limit for list inputs.
325
- * @summary Configures the maximum number of items that can be selected in list-type prompts.
326
- * @template R - The type of the prompt name, extending string.
327
- * @param value - The maximum number of items that can be selected, or a function to determine this value.
328
- * @return This UserInput instance for method chaining.
329
- */
330
- setLimit(value) {
331
- UserInput.logger.verbose(`Setting limit to: ${value}`);
332
- this.limit = value;
333
- return this;
334
- }
335
- /**
336
- * @description Sets the mask for password inputs.
337
- * @summary Configures the character used to hide the user's input in password-type prompts.
338
- * @template R - The type of the prompt name, extending string.
339
- * @param value - The character used to mask the input, or a function to determine this value.
340
- * @return This UserInput instance for method chaining.
341
- */
342
- setMask(value) {
343
- UserInput.logger.verbose(`Setting mask to: ${value}`);
344
- this.mask = value;
345
- return this;
346
- }
347
- /**
348
- * @description Sets the stdout stream for the prompt.
349
- * @summary Configures the output stream used by the prompt for displaying messages and results.
350
- * @param value - The Writable stream to be used as stdout.
351
- * @return This UserInput instance for method chaining.
352
- */
353
- setStdout(value) {
354
- UserInput.logger.verbose(`Setting stdout stream`);
355
- this.stdout = value;
356
- return this;
357
- }
358
- /**
359
- * @description Sets the stdin stream for the prompt.
360
- * @summary Configures the input stream used by the prompt for receiving user input.
361
- * @param value - The Readable stream to be used as stdin.
362
- * @return This UserInput instance for method chaining.
363
- */
364
- setStdin(value) {
365
- this.stdin = value;
366
- return this;
367
- }
368
- /**
369
- * @description Asks the user for input based on the current UserInput configuration.
370
- * @summary Prompts the user and returns their response as a single value.
371
- * @template R - The type of the prompt name, extending string.
372
- * @return A Promise that resolves to the user's answer.
373
- */
374
- async ask() {
375
- return (await UserInput.ask(this))[this.name];
376
- }
377
- /**
378
- * @description Asks the user one or more questions based on the provided UserInput configurations.
379
- * @summary Prompts the user with one or more questions and returns their answers as an object.
380
- * @template R - The type of the prompt name, extending string.
381
- * @param question - A single UserInput instance or an array of UserInput instances.
382
- * @return A Promise that resolves to an object containing the user's answers.
383
- * @mermaid
384
- * sequenceDiagram
385
- * participant U as User
386
- * participant A as ask method
387
- * participant P as prompts library
388
- * A->>P: Call prompts with question(s)
389
- * P->>U: Display prompt(s)
390
- * U->>P: Provide input
391
- * P->>A: Return answers
392
- * A->>A: Process answers
393
- * A-->>Caller: Return processed answers
394
- */
395
- static async ask(question) {
396
- const log = UserInput.logger.for(this.ask);
397
- if (!Array.isArray(question)) {
398
- question = [question];
399
- }
400
- let answers;
401
- try {
402
- log.verbose(`Asking questions: ${question.map((q) => q.name).join(", ")}`);
403
- answers = await prompts(question);
404
- log.verbose(`Received answers: ${JSON.stringify(answers, null, 2)}`);
405
- }
406
- catch (error) {
407
- throw new Error(`Error while getting input: ${error}`);
408
- }
409
- return answers;
410
- }
411
- /**
412
- * @description Asks the user for a number input.
413
- * @summary Prompts the user to enter a number, with optional minimum, maximum, and initial values.
414
- * @param name - The name of the prompt, used as the key in the returned answers object.
415
- * @param question - The message displayed to the user.
416
- * @param min - The minimum allowed value (optional).
417
- * @param max - The maximum allowed value (optional).
418
- * @param initial - The initial value presented to the user (optional).
419
- * @return A Promise that resolves to the number entered by the user.
420
- */
421
- static async askNumber(name, question, min, max, initial) {
422
- const log = UserInput.logger.for(this.askNumber);
423
- log.verbose(`Asking number input: undefined, question: ${question}, min: ${min}, max: ${max}, initial: ${initial}`);
424
- const userInput = new UserInput(name)
425
- .setMessage(question)
426
- .setType("number");
427
- if (typeof min === "number")
428
- userInput.setMin(min);
429
- if (typeof max === "number")
430
- userInput.setMax(max);
431
- if (typeof initial === "number")
432
- userInput.setInitial(initial);
433
- return (await this.ask(userInput))[name];
434
- }
435
- /**
436
- * @description Asks the user for a text input.
437
- * @summary Prompts the user to enter text, with optional masking and initial value.
438
- * @param name - The name of the prompt, used as the key in the returned answers object.
439
- * @param question - The message displayed to the user.
440
- * @param mask - The character used to mask the input (optional, for password-like inputs).
441
- * @param initial - The initial value presented to the user (optional).
442
- * @return A Promise that resolves to the text entered by the user.
443
- */
444
- static async askText(name, question, mask = undefined, initial) {
445
- const log = UserInput.logger.for(this.askText);
446
- log.verbose(`Asking text input: undefined, question: ${question}, mask: ${mask}, initial: ${initial}`);
447
- const userInput = new UserInput(name).setMessage(question);
448
- if (mask)
449
- userInput.setMask(mask);
450
- if (typeof initial === "string")
451
- userInput.setInitial(initial);
452
- return (await this.ask(userInput))[name];
453
- }
454
- /**
455
- * @description Asks the user for a confirmation (yes/no).
456
- * @summary Prompts the user with a yes/no question and returns a boolean result.
457
- * @param name - The name of the prompt, used as the key in the returned answers object.
458
- * @param question - The message displayed to the user.
459
- * @param initial - The initial value presented to the user (optional).
460
- * @return A Promise that resolves to a boolean representing the user's answer.
461
- */
462
- static async askConfirmation(name, question, initial) {
463
- const log = UserInput.logger.for(this.askConfirmation);
464
- log.verbose(`Asking confirmation input: undefined, question: ${question}, initial: ${initial}`);
465
- const userInput = new UserInput(name)
466
- .setMessage(question)
467
- .setType("confirm");
468
- if (typeof initial !== "undefined")
469
- userInput.setInitial(initial);
470
- return (await this.ask(userInput))[name];
471
- }
472
- /**
473
- * @description Repeatedly asks for input until a valid response is given or the limit is reached.
474
- * @summary This method insists on getting a valid input from the user, allowing for a specified number of attempts.
475
- *
476
- * @template R - The type of the expected result.
477
- * @param input - The UserInput instance to use for prompting.
478
- * @param {function(string):boolean} test - Validator function receiving the user input and returning whether it is valid.
479
- * @param defaultConfirmation - The default value for the confirmation prompt (true for yes, false for no).
480
- * @param limit - The maximum number of attempts allowed (default is 1).
481
- * @return A Promise that resolves to the valid input or undefined if the limit is reached.
482
- *
483
- * @mermaid
484
- * sequenceDiagram
485
- * participant U as User
486
- * participant I as insist method
487
- * participant A as ask method
488
- * participant T as test function
489
- * participant C as askConfirmation method
490
- * loop Until valid input or limit reached
491
- * I->>A: Call ask with input
492
- * A->>U: Prompt user
493
- * U->>A: Provide input
494
- * A->>I: Return result
495
- * I->>T: Test result
496
- * alt Test passes
497
- * I->>C: Ask for confirmation
498
- * C->>U: Confirm input
499
- * U->>C: Provide confirmation
500
- * C->>I: Return confirmation
501
- * alt Confirmed
502
- * I-->>Caller: Return valid result
503
- * else Not confirmed
504
- * I->>I: Continue loop
505
- * end
506
- * else Test fails
507
- * I->>I: Continue loop
508
- * end
509
- * end
510
- * I-->>Caller: Return undefined if limit reached
511
- */
512
- static async insist(input, test, defaultConfirmation, limit = 1) {
513
- const log = UserInput.logger.for(this.insist);
514
- log.verbose(`Insisting on input: ${input.name}, test: ${test.toString()}, defaultConfirmation: ${defaultConfirmation}, limit: ${limit}`);
515
- let result = undefined;
516
- let count = 0;
517
- let confirmation;
518
- try {
519
- do {
520
- result = (await UserInput.ask(input))[input.name];
521
- if (!test(result)) {
522
- result = undefined;
523
- continue;
524
- }
525
- confirmation = await UserInput.askConfirmation(`${input.name}-confirm`, `Is the ${input.type} correct?`, defaultConfirmation);
526
- if (!confirmation)
527
- result = undefined;
528
- } while (typeof result === "undefined" && limit > 1 && count++ < limit);
529
- }
530
- catch (e) {
531
- log.error(`Error while insisting: ${e}`);
532
- throw e;
533
- }
534
- if (typeof result === "undefined")
535
- log.info("no selection...");
536
- return result;
537
- }
538
- /**
539
- * @description Repeatedly asks for text input until a valid response is given or the limit is reached.
540
- * @summary This method insists on getting a valid text input from the user, allowing for a specified number of attempts.
541
- *
542
- * @param name - The name of the prompt, used as the key in the returned answers object.
543
- * @param question - The message displayed to the user.
544
- * @param {function(number):boolean} test - Validator function receiving the user input and returning whether it is valid.
545
- * @param mask - The character used to mask the input (optional, for password-like inputs).
546
- * @param initial - The initial value presented to the user (optional).
547
- * @param defaultConfirmation - The default value for the confirmation prompt (true for yes, false for no).
548
- * @param limit - The maximum number of attempts allowed (default is -1, meaning unlimited).
549
- * @return A Promise that resolves to the valid input or undefined if the limit is reached.
550
- */
551
- static async insistForText(name, question, test, mask = undefined, initial, defaultConfirmation = false, limit = -1) {
552
- const log = UserInput.logger.for(this.insistForText);
553
- log.verbose(`Insisting for text input: undefined, question: ${question}, test: ${test.toString()}, mask: ${mask}, initial: ${initial}, defaultConfirmation: ${defaultConfirmation}, limit: ${limit}`);
554
- const userInput = new UserInput(name).setMessage(question);
555
- if (mask)
556
- userInput.setMask(mask);
557
- if (typeof initial === "string")
558
- userInput.setInitial(initial);
559
- return (await this.insist(userInput, test, defaultConfirmation, limit));
560
- }
561
- /**
562
- * @description Repeatedly asks for number input until a valid response is given or the limit is reached.
563
- * @summary This method insists on getting a valid number input from the user, allowing for a specified number of attempts.
564
- *
565
- * @param name - The name of the prompt, used as the key in the returned answers object.
566
- * @param question - The message displayed to the user.
567
- * @param test - A function to validate the user's input.
568
- * @param min - The minimum allowed value (optional).
569
- * @param max - The maximum allowed value (optional).
570
- * @param initial - The initial value presented to the user (optional).
571
- * @param defaultConfirmation - The default value for the confirmation prompt (true for yes, false for no).
572
- * @param limit - The maximum number of attempts allowed (default is -1, meaning unlimited).
573
- * @return A Promise that resolves to the valid input or undefined if the limit is reached.
574
- */
575
- static async insistForNumber(name, question, test, min, max, initial, defaultConfirmation = false, limit = -1) {
576
- const log = UserInput.logger.for(this.insistForNumber);
577
- log.verbose(`Insisting for number input: undefined, question: ${question}, test: ${test.toString()}, min: ${min}, max: ${max}, initial: ${initial}, defaultConfirmation: ${defaultConfirmation}, limit: ${limit}`);
578
- const userInput = new UserInput(name)
579
- .setMessage(question)
580
- .setType("number");
581
- if (typeof min === "number")
582
- userInput.setMin(min);
583
- if (typeof max === "number")
584
- userInput.setMax(max);
585
- if (typeof initial === "number")
586
- userInput.setInitial(initial);
587
- return (await this.insist(userInput, test, defaultConfirmation, limit));
588
- }
589
- /**
590
- * @description Parses command-line arguments based on the provided options.
591
- * @summary Uses Node.js's util.parseArgs to parse command-line arguments and return the result.
592
- * @param options - Configuration options for parsing arguments.
593
- * @return An object containing the parsed arguments.
594
- * @mermaid
595
- * sequenceDiagram
596
- * participant C as Caller
597
- * participant P as parseArgs method
598
- * participant U as util.parseArgs
599
- * C->>P: Call with options
600
- * P->>P: Prepare args object
601
- * P->>U: Call parseArgs with prepared args
602
- * U->>P: Return parsed result
603
- * P-->>C: Return ParseArgsResult
604
- */
605
- static parseArgs(options) {
606
- const log = UserInput.logger.for(this.parseArgs);
607
- const args = {
608
- args: process.argv.slice(2),
609
- options: options,
610
- };
611
- log.debug(`Parsing arguments: ${JSON.stringify(args, null, 2)}`);
612
- try {
613
- return parseArgs(args);
614
- }
615
- catch (error) {
616
- log.debug(`Error while parsing arguments:\n${JSON.stringify(args, null, 2)}\n | options\n${JSON.stringify(options, null, 2)}\n | ${error}`);
617
- throw new Error(`Error while parsing arguments: ${error}`);
618
- }
619
- }
620
- }
621
-
622
- /**
623
- * @description Default command options for CLI commands.
624
- * @summary Defines the structure and default values for common command-line options used across various CLI commands.
625
- * @const DefaultCommandOptions
626
- * @typedef {Object} DefaultCommandOptions
627
- * @property {Object} verbose - Verbosity level option.
628
- * @property {string} verbose.type - The type of the verbose option (number).
629
- * @property {string} verbose.short - The short flag for the verbose option (V).
630
- * @property {number} verbose.default - The default value for verbosity (0).
631
- * @property {Object} version - Version display option.
632
- * @property {string} version.type - The type of the version option (boolean).
633
- * @property {string} version.short - The short flag for the version option (v).
634
- * @property {undefined} version.default - The default value for version display (undefined).
635
- * @property {Object} help - Help display option.
636
- * @property {string} help.type - The type of the help option (boolean).
637
- * @property {string} help.short - The short flag for the help option (h).
638
- * @property {boolean} help.default - The default value for help display (false).
639
- * @property {Object} logLevel - Log level option.
640
- * @property {string} logLevel.type - The type of the logLevel option (string).
641
- * @property {string} logLevel.default - The default value for log level ("info").
642
- * @property {Object} logStyle - Log styling option.
643
- * @property {string} logStyle.type - The type of the logStyle option (boolean).
644
- * @property {boolean} logStyle.default - The default value for log styling (true).
645
- * @property {Object} timestamp - Timestamp display option.
646
- * @property {string} timestamp.type - The type of the timestamp option (boolean).
647
- * @property {boolean} timestamp.default - The default value for timestamp display (true).
648
- * @property {Object} banner - Banner display option.
649
- * @property {string} banner.type - The type of the banner option (boolean).
650
- * @property {boolean} banner.default - The default value for banner display (false).
651
- * @memberOf module:utils
652
- */
653
- const DefaultCommandOptions = {
654
- verbose: {
655
- type: "boolean",
656
- short: "V",
657
- default: undefined,
658
- },
659
- version: {
660
- type: "boolean",
661
- short: "v",
662
- default: undefined,
663
- },
664
- help: {
665
- type: "boolean",
666
- short: "h",
667
- default: false,
668
- },
669
- logLevel: {
670
- type: "string",
671
- default: "info",
672
- },
673
- logStyle: {
674
- type: "boolean",
675
- default: true,
676
- },
677
- timestamp: {
678
- type: "boolean",
679
- default: true,
680
- },
681
- banner: {
682
- type: "boolean",
683
- default: true,
684
- },
685
- };
686
- /**
687
- * @description Default command values derived from DefaultCommandOptions.
688
- * @summary Creates an object with the default values of all options defined in DefaultCommandOptions.
689
- * @const DefaultCommandValues
690
- * @typedef {Object} DefaultCommandValues
691
- * @property {unknown} [key: string] - The default value for each option in DefaultCommandOptions.
692
- * @memberOf module:utils
693
- */
694
- const DefaultCommandValues = Object.keys(DefaultCommandOptions).reduce((acc, key) => {
695
- acc[key] =
696
- DefaultCommandOptions[key].default;
697
- return acc;
698
- }, {});
699
-
700
- /**
701
- * @description Default encoding for text operations.
702
- * @summary The standard UTF-8 encoding used for text processing.
703
- * @const {string} Encoding
704
- * @memberOf module:utils
705
- */
706
- const Encoding = "utf-8";
707
- /**
708
- * @description Regular expression for semantic versioning.
709
- * @summary A regex pattern to match and parse semantic version strings.
710
- * @const {RegExp} SemVersionRegex
711
- * @memberOf module:utils
712
- */
713
- const SemVersionRegex = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z])))/g;
714
- /**
715
- * @description Enum for semantic version components.
716
- * @summary Defines the three levels of semantic versioning: PATCH, MINOR, and MAJOR.
717
- * @enum {string}
718
- * @memberOf module:utils
719
- */
720
- var SemVersion;
721
- (function (SemVersion) {
722
- /** Patch version for backwards-compatible bug fixes. */
723
- SemVersion["PATCH"] = "patch";
724
- /** Minor version for backwards-compatible new features. */
725
- SemVersion["MINOR"] = "minor";
726
- /** Major version for changes that break backwards compatibility. */
727
- SemVersion["MAJOR"] = "major";
728
- })(SemVersion || (SemVersion = {}));
729
- /**
730
- * @description Flag to indicate non-CI environment.
731
- * @summary Used to specify that a command should run outside of a Continuous Integration environment.
732
- * @const {string} NoCIFLag
733
- * @memberOf module:utils
734
- */
735
- const NoCIFLag = "-no-ci";
736
- /**
737
- * @description Key for the setup script in package.json.
738
- * @summary Identifies the script that runs after package installation.
739
- * @const {string} SetupScriptKey
740
- * @memberOf module:utils
741
- */
742
- const SetupScriptKey = "postinstall";
743
- /**
744
- * @description Enum for various authentication tokens.
745
- * @summary Defines the file names for storing different types of authentication tokens.
746
- * @enum {string}
747
- * @memberOf module:utils
748
- */
749
- var Tokens;
750
- (function (Tokens) {
751
- /** Git authentication token file name. */
752
- Tokens["GIT"] = ".token";
753
- /** NPM authentication token file name. */
754
- Tokens["NPM"] = ".npmtoken";
755
- /** Docker authentication token file name. */
756
- Tokens["DOCKER"] = ".dockertoken";
757
- /** Confluence authentication token file name. */
758
- Tokens["CONFLUENCE"] = ".confluence-token";
759
- })(Tokens || (Tokens = {}));
760
- /**
761
- * @description Code used to indicate an operation was aborted.
762
- * @summary Standard message used when a process is manually terminated.
763
- * @const {string} AbortCode
764
- * @memberOf module:utils
765
- */
766
- const AbortCode = "Aborted";
767
-
768
- /**
769
- * @description A standard output writer for handling command execution output.
770
- * @summary This class implements the OutputWriter interface and provides methods for
771
- * handling various types of output from command execution, including standard output,
772
- * error output, and exit codes. It also includes utility methods for parsing commands
773
- * and resolving or rejecting promises based on execution results.
774
- *
775
- * @template R - The type of the resolved value, defaulting to string.
776
- *
777
- * @param cmd - The command string to be executed.
778
- * @param lock - A PromiseExecutor to control the asynchronous flow.
779
- * @param args - Additional arguments (unused in the current implementation).
780
- *
781
- * @class
782
- * @example
783
- * ```typescript
784
- * import { StandardOutputWriter } from '@decaf-ts/utils';
785
- * import { PromiseExecutor } from '@decaf-ts/utils';
786
- *
787
- * // Create a promise executor
788
- * const executor: PromiseExecutor<string> = {
789
- * resolve: (value) => console.log(`Resolved: ${value}`),
790
- * reject: (error) => console.error(`Rejected: ${error.message}`)
791
- * };
792
- *
793
- * // Create a standard output writer
794
- * const writer = new StandardOutputWriter('ls -la', executor);
795
- *
796
- * // Use the writer to handle command output
797
- * writer.data('File list output...');
798
- * writer.exit(0, ['Command executed successfully']);
799
- * ```
800
- *
801
- * @mermaid
802
- * sequenceDiagram
803
- * participant Client
804
- * participant StandardOutputWriter
805
- * participant Logger
806
- * participant PromiseExecutor
807
- *
808
- * Client->>StandardOutputWriter: new StandardOutputWriter(cmd, lock)
809
- * StandardOutputWriter->>Logger: Logging.for(cmd)
810
- *
811
- * Client->>StandardOutputWriter: data(chunk)
812
- * StandardOutputWriter->>StandardOutputWriter: log("stdout", chunk)
813
- * StandardOutputWriter->>Logger: logger.info(log)
814
- *
815
- * Client->>StandardOutputWriter: error(chunk)
816
- * StandardOutputWriter->>StandardOutputWriter: log("stderr", chunk)
817
- * StandardOutputWriter->>Logger: logger.info(log)
818
- *
819
- * Client->>StandardOutputWriter: exit(code, logs)
820
- * StandardOutputWriter->>StandardOutputWriter: log("stdout", exitMessage)
821
- * alt code === 0
822
- * StandardOutputWriter->>StandardOutputWriter: resolve(logs)
823
- * StandardOutputWriter->>PromiseExecutor: lock.resolve(reason)
824
- * else code !== 0
825
- * StandardOutputWriter->>StandardOutputWriter: reject(error)
826
- * StandardOutputWriter->>PromiseExecutor: lock.reject(reason)
827
- * end
828
- */
829
- class StandardOutputWriter {
830
- constructor(cmd, lock,
831
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
832
- ...args) {
833
- this.cmd = cmd;
834
- this.lock = lock;
835
- this.logger = Logging.for(this.cmd);
836
- }
837
- /**
838
- * @description Logs output to the console.
839
- * @summary Formats and logs the given data with a timestamp and type indicator.
840
- *
841
- * @param type - The type of output (stdout or stderr).
842
- * @param data - The data to be logged.
843
- */
844
- log(type, data) {
845
- data = Buffer.isBuffer(data) ? data.toString(Encoding) : data;
846
- const log = type === "stderr" ? style(data).red.text : data;
847
- this.logger.info(log);
848
- }
849
- /**
850
- * @description Handles standard output data.
851
- * @summary Logs the given chunk as standard output.
852
- *
853
- * @param chunk - The data chunk to be logged.
854
- */
855
- data(chunk) {
856
- this.log("stdout", String(chunk));
857
- }
858
- /**
859
- * @description Handles error output data.
860
- * @summary Logs the given chunk as error output.
861
- *
862
- * @param chunk - The error data chunk to be logged.
863
- */
864
- error(chunk) {
865
- this.log("stderr", String(chunk));
866
- }
867
- /**
868
- * @description Handles error objects.
869
- * @summary Logs the error message from the given Error object.
870
- *
871
- * @param err - The Error object to be logged.
872
- */
873
- errors(err) {
874
- this.log("stderr", `Error executing command exited : ${err}`);
875
- }
876
- /**
877
- * @description Handles the exit of a command.
878
- * @summary Logs the exit code and resolves or rejects the promise based on the code.
879
- *
880
- * @param code - The exit code of the command.
881
- * @param logs - Array of log messages to be processed before exiting.
882
- */
883
- exit(code, logs) {
884
- this.log("stdout", `command exited code : ${code === 0 ? style(code.toString()).green.text : style(code === null ? "null" : code.toString()).red.text}`);
885
- if (code === 0) {
886
- this.resolve(logs.map((l) => l.trim()).join("\n"));
887
- }
888
- else {
889
- this.reject(new Error(logs.length ? logs.join("\n") : code.toString()));
890
- }
891
- }
892
- /**
893
- * @description Parses a command string or array into components.
894
- * @summary Converts the command into a consistent format and stores it, then returns it split into command and arguments.
895
- *
896
- * @param command - The command as a string or array of strings.
897
- * @return A tuple containing the command and its arguments as separate elements.
898
- */
899
- parseCommand(command) {
900
- command = typeof command === "string" ? command.split(" ") : command;
901
- this.cmd = command.join(" ");
902
- return [command[0], command.slice(1)];
903
- }
904
- /**
905
- * @description Resolves the promise with a success message.
906
- * @summary Logs a success message and resolves the promise with the given reason.
907
- *
908
- * @param reason - The reason for resolving the promise.
909
- */
910
- resolve(reason) {
911
- this.log("stdout", `${this.cmd} executed successfully: ${style(reason ? "ran to completion" : reason).green}`);
912
- this.lock.resolve(reason);
913
- }
914
- /**
915
- * @description Rejects the promise with an error message.
916
- * @summary Logs an error message and rejects the promise with the given reason.
917
- *
918
- * @param reason - The reason for rejecting the promise, either a number (exit code) or a string.
919
- */
920
- reject(reason) {
921
- if (!(reason instanceof Error)) {
922
- reason = new Error(typeof reason === "number" ? `Exit code ${reason}` : reason);
923
- }
924
- this.log("stderr", `${this.cmd} failed to execute: ${style(reason.message).red}`);
925
- this.lock.reject(reason);
926
- }
927
- }
928
-
929
- /**
930
- * @description Creates a locked version of a function.
931
- * @summary This higher-order function takes a function and returns a new function that ensures
932
- * sequential execution of the original function, even when called multiple times concurrently.
933
- * It uses a Promise-based locking mechanism to queue function calls.
934
- *
935
- * @template R - The return type of the input function.
936
- *
937
- * @param f - The function to be locked. It can take any number of parameters and return a value of type R.
938
- * @return A new function with the same signature as the input function, but with sequential execution guaranteed.
939
- *
940
- * @function lockify
941
- *
942
- * @mermaid
943
- * sequenceDiagram
944
- * participant Caller
945
- * participant LockedFunction
946
- * participant OriginalFunction
947
- * Caller->>LockedFunction: Call with params
948
- * LockedFunction->>LockedFunction: Check current lock
949
- * alt Lock is resolved
950
- * LockedFunction->>OriginalFunction: Execute with params
951
- * OriginalFunction-->>LockedFunction: Return result
952
- * LockedFunction-->>Caller: Return result
953
- * else Lock is pending
954
- * LockedFunction->>LockedFunction: Queue execution
955
- * LockedFunction-->>Caller: Return promise
956
- * Note over LockedFunction: Wait for previous execution
957
- * LockedFunction->>OriginalFunction: Execute with params
958
- * OriginalFunction-->>LockedFunction: Return result
959
- * LockedFunction-->>Caller: Resolve promise with result
960
- * end
961
- * LockedFunction->>LockedFunction: Update lock
962
- *
963
- * @memberOf module:utils
964
- */
965
- function lockify(f) {
966
- let lock = Promise.resolve();
967
- return (...params) => {
968
- const result = lock.then(() => f(...params));
969
- lock = result.catch(() => { });
970
- return result;
971
- };
972
- }
973
- function chainAbortController(argument0, ...remainder) {
974
- let signals;
975
- let controller;
976
- // normalize args
977
- if (argument0 instanceof AbortSignal) {
978
- controller = new AbortController();
979
- signals = [argument0, ...remainder];
980
- }
981
- else {
982
- controller = argument0;
983
- signals = remainder;
984
- }
985
- // if the controller is already aborted, exit early
986
- if (controller.signal.aborted) {
987
- return controller;
988
- }
989
- const handler = () => controller.abort();
990
- for (const signal of signals) {
991
- // check before adding! (and assume there is no possible way that the signal could
992
- // abort between the `if` check and adding the event listener)
993
- if (signal.aborted) {
994
- controller.abort();
995
- break;
996
- }
997
- signal.addEventListener("abort", handler, {
998
- once: true,
999
- signal: controller.signal,
1000
- });
1001
- }
1002
- return controller;
1003
- }
1004
- /**
1005
- * @description Spawns a command as a child process with output handling.
1006
- * @summary Creates a child process to execute a command with support for piping multiple commands,
1007
- * custom output handling, and abort control. This function handles the low-level details of
1008
- * spawning processes and connecting their inputs/outputs when piping is used.
1009
- *
1010
- * @template R - The type of the processed output, defaulting to string.
1011
- * @param {StandardOutputWriter<R>} output - The output writer to handle command output.
1012
- * @param {string} command - The command to execute, can include pipe operators.
1013
- * @param {SpawnOptionsWithoutStdio} opts - Options for the spawned process.
1014
- * @param {AbortController} abort - Controller to abort the command execution.
1015
- * @param {Logger} logger - Logger for recording command execution details.
1016
- * @return {ChildProcessWithoutNullStreams} The spawned child process.
1017
- *
1018
- * @function spawnCommand
1019
- *
1020
- * @memberOf module:utils
1021
- */
1022
- function spawnCommand(output, command, opts, abort, logger) {
1023
- function spawnInner(command, controller) {
1024
- const [cmd, argz] = output.parseCommand(command);
1025
- logger.info(`Running command: ${cmd}`);
1026
- logger.debug(`with args: ${argz.join(" ")}`);
1027
- const childProcess = spawn(cmd, argz, {
1028
- ...opts,
1029
- cwd: opts.cwd || process.cwd(),
1030
- env: Object.assign({}, process.env, opts.env, { PATH: process.env.PATH }),
1031
- shell: opts.shell || false,
1032
- signal: controller.signal,
1033
- });
1034
- logger.verbose(`pid : ${childProcess.pid}`);
1035
- return childProcess;
1036
- }
1037
- const m = command.match(/[<>$#]/g);
1038
- if (m)
1039
- throw new Error(`Invalid command: ${command}. contains invalid characters: ${m}`);
1040
- if (command.includes(" | ")) {
1041
- const cmds = command.split(" | ");
1042
- const spawns = [];
1043
- const controllers = new Array(cmds.length);
1044
- controllers[0] = abort;
1045
- for (let i = 0; i < cmds.length; i++) {
1046
- if (i !== 0)
1047
- controllers[i] = chainAbortController(controllers[i - 1].signal);
1048
- spawns.push(spawnInner(cmds[i], controllers[i]));
1049
- if (i === 0)
1050
- continue;
1051
- spawns[i - 1].stdout.pipe(spawns[i].stdin);
1052
- }
1053
- return spawns[cmds.length - 1];
1054
- }
1055
- return spawnInner(command, abort);
1056
- }
1057
- /**
1058
- * @description Executes a command asynchronously with customizable output handling.
1059
- * @summary This function runs a shell command as a child process, providing fine-grained
1060
- * control over its execution and output handling. It supports custom output writers,
1061
- * allows for command abortion, and captures both stdout and stderr.
1062
- *
1063
- * @template R - The type of the resolved value from the command execution.
1064
- *
1065
- * @param command - The command to run, either as a string or an array of strings.
1066
- * @param opts - Spawn options for the child process. Defaults to an empty object.
1067
- * @param outputConstructor - Constructor for the output writer. Defaults to StandardOutputWriter.
1068
- * @param args - Additional arguments to pass to the output constructor.
1069
- * @return {CommandResult} A promise that resolves to the command result of type R.
1070
- *
1071
- * @function runCommand
1072
- *
1073
- * @mermaid
1074
- * sequenceDiagram
1075
- * participant Caller
1076
- * participant runCommand
1077
- * participant OutputWriter
1078
- * participant ChildProcess
1079
- * Caller->>runCommand: Call with command and options
1080
- * runCommand->>OutputWriter: Create new instance
1081
- * runCommand->>OutputWriter: Parse command
1082
- * runCommand->>ChildProcess: Spawn process
1083
- * ChildProcess-->>runCommand: Return process object
1084
- * runCommand->>ChildProcess: Set up event listeners
1085
- * loop For each stdout data
1086
- * ChildProcess->>runCommand: Emit stdout data
1087
- * runCommand->>OutputWriter: Handle stdout data
1088
- * end
1089
- * loop For each stderr data
1090
- * ChildProcess->>runCommand: Emit stderr data
1091
- * runCommand->>OutputWriter: Handle stderr data
1092
- * end
1093
- * ChildProcess->>runCommand: Emit error (if any)
1094
- * runCommand->>OutputWriter: Handle error
1095
- * ChildProcess->>runCommand: Emit exit
1096
- * runCommand->>OutputWriter: Handle exit
1097
- * OutputWriter-->>runCommand: Resolve or reject promise
1098
- * runCommand-->>Caller: Return CommandResult
1099
- *
1100
- * @memberOf module:utils
1101
- */
1102
- function runCommand(command, opts = {}, outputConstructor = (StandardOutputWriter), ...args) {
1103
- const logger = Logging.for(runCommand);
1104
- const abort = new AbortController();
1105
- const result = {
1106
- abort: abort,
1107
- command: command,
1108
- logs: [],
1109
- errs: [],
1110
- };
1111
- const lock = new Promise((resolve, reject) => {
1112
- let output;
1113
- try {
1114
- output = new outputConstructor(command, {
1115
- resolve,
1116
- reject,
1117
- }, ...args);
1118
- result.cmd = spawnCommand(output, command, opts, abort, logger);
1119
- }
1120
- catch (e) {
1121
- return reject(new Error(`Error running command ${command}: ${e}`));
1122
- }
1123
- result.cmd.stdout.setEncoding("utf8");
1124
- result.cmd.stdout.on("data", (chunk) => {
1125
- chunk = chunk.toString();
1126
- result.logs.push(chunk);
1127
- output.data(chunk);
1128
- });
1129
- result.cmd.stderr.on("data", (data) => {
1130
- data = data.toString();
1131
- result.errs.push(data);
1132
- output.error(data);
1133
- });
1134
- result.cmd.once("error", (err) => {
1135
- output.exit(err.message, result.errs);
1136
- });
1137
- result.cmd.once("exit", (code = 0) => {
1138
- if (abort.signal.aborted && code === null)
1139
- code = AbortCode;
1140
- output.exit(code, code === 0 ? result.logs : result.errs);
1141
- });
1142
- });
1143
- Object.assign(result, {
1144
- promise: lock,
1145
- pipe: async (cb) => {
1146
- const l = logger.for("pipe");
1147
- try {
1148
- l.verbose(`Executing pipe function ${command}...`);
1149
- const result = await lock;
1150
- l.verbose(`Piping output to ${cb.name}: ${result}`);
1151
- return cb(result);
1152
- }
1153
- catch (e) {
1154
- l.error(`Error piping command output: ${e}`);
1155
- throw e;
1156
- }
1157
- },
1158
- });
1159
- return result;
1160
- }
1161
-
1162
- const logger = Logging.for("fs");
1163
- /**
1164
- * @description Patches a file with given values.
1165
- * @summary Reads a file, applies patches using TextUtils, and writes the result back to the file.
1166
- *
1167
- * @param {string} path - The path to the file to be patched.
1168
- * @param {Record<string, number | string>} values - The values to patch into the file.
1169
- * @return {void}
1170
- *
1171
- * @function patchFile
1172
- *
1173
- * @mermaid
1174
- * sequenceDiagram
1175
- * participant Caller
1176
- * participant patchFile
1177
- * participant fs
1178
- * participant readFile
1179
- * participant TextUtils
1180
- * participant writeFile
1181
- * Caller->>patchFile: Call with path and values
1182
- * patchFile->>fs: Check if file exists
1183
- * patchFile->>readFile: Read file content
1184
- * readFile->>fs: Read file
1185
- * fs-->>readFile: Return file content
1186
- * readFile-->>patchFile: Return file content
1187
- * patchFile->>TextUtils: Patch string
1188
- * TextUtils-->>patchFile: Return patched content
1189
- * patchFile->>writeFile: Write patched content
1190
- * writeFile->>fs: Write to file
1191
- * fs-->>writeFile: File written
1192
- * writeFile-->>patchFile: File written
1193
- * patchFile-->>Caller: Patching complete
1194
- *
1195
- * @memberOf module:utils
1196
- */
1197
- function patchFile(path, values) {
1198
- const log = logger.for(patchFile);
1199
- if (!fs.existsSync(path))
1200
- throw new Error(`File not found at path "${path}".`);
1201
- let content = readFile(path);
1202
- try {
1203
- log.verbose(`Patching file "${path}"...`);
1204
- log.debug(`with value: ${JSON.stringify(values)}`);
1205
- content = patchString(content, values);
1206
- }
1207
- catch (error) {
1208
- throw new Error(`Error patching file: ${error}`);
1209
- }
1210
- writeFile(path, content);
1211
- }
1212
- /**
1213
- * @description Reads a file and returns its content.
1214
- * @summary Reads the content of a file at the specified path and returns it as a string.
1215
- *
1216
- * @param {string} path - The path to the file to be read.
1217
- * @return {string} The content of the file.
1218
- *
1219
- * @function readFile
1220
- *
1221
- * @memberOf module:utils
1222
- */
1223
- function readFile(path) {
1224
- const log = logger.for(readFile);
1225
- try {
1226
- log.verbose(`Reading file "${path}"...`);
1227
- return fs.readFileSync(path, "utf8");
1228
- }
1229
- catch (error) {
1230
- log.verbose(`Error reading file "${path}": ${error}`);
1231
- throw new Error(`Error reading file "${path}": ${error}`);
1232
- }
1233
- }
1234
- /**
1235
- * @description Writes data to a file.
1236
- * @summary Writes the provided data to a file at the specified path.
1237
- *
1238
- * @param {string} path - The path to the file to be written.
1239
- * @param {string | Buffer} data - The data to be written to the file.
1240
- * @return {void}
1241
- *
1242
- * @function writeFile
1243
- *
1244
- * @memberOf module:utils
1245
- */
1246
- function writeFile(path, data) {
1247
- const log = logger.for(writeFile);
1248
- try {
1249
- log.verbose(`Writing file "${path} with ${data.length} bytes...`);
1250
- fs.writeFileSync(path, data, "utf8");
1251
- }
1252
- catch (error) {
1253
- log.verbose(`Error writing file "${path}": ${error}`);
1254
- throw new Error(`Error writing file "${path}": ${error}`);
1255
- }
1256
- }
1257
- /**
1258
- * @description Retrieves all files recursively from a directory.
1259
- * @summary Traverses through directories and subdirectories to collect all file paths.
1260
- *
1261
- * @param {string} p - The path to start searching from.
1262
- * @param {function} [filter] - Optional function to filter files by name or index.
1263
- * @return {string[]} Array of file paths.
1264
- *
1265
- * @function getAllFiles
1266
- *
1267
- * @memberOf module:utils
1268
- */
1269
- function getAllFiles(p, filter) {
1270
- const log = logger.for(getAllFiles);
1271
- const files = [];
1272
- try {
1273
- log.verbose(`Retrieving all files from "${p}"...`);
1274
- const entries = fs.readdirSync(p);
1275
- entries.forEach((entry) => {
1276
- const fullPath = path.join(p, entry);
1277
- const stat = fs.statSync(fullPath);
1278
- if (stat.isFile()) {
1279
- files.push(fullPath);
1280
- }
1281
- else if (stat.isDirectory()) {
1282
- files.push(...getAllFiles(fullPath));
1283
- }
1284
- });
1285
- if (!filter)
1286
- return files;
1287
- return files.filter(filter);
1288
- }
1289
- catch (error) {
1290
- log.verbose(`Error retrieving files from "${p}": ${error}`);
1291
- throw new Error(`Error retrieving files from "${p}": ${error}`);
1292
- }
1293
- }
1294
- /**
1295
- * @description Renames a file or directory.
1296
- * @summary Moves a file or directory from the source path to the destination path.
1297
- *
1298
- * @param {string} source - The source path of the file or directory.
1299
- * @param {string} dest - The destination path for the file or directory.
1300
- * @return {Promise<void>} A promise that resolves when the rename operation is complete.
1301
- *
1302
- * @function renameFile
1303
- *
1304
- * @memberOf module:utils
1305
- */
1306
- async function renameFile(source, dest) {
1307
- const log = logger.for(renameFile);
1308
- let descriptorSource, descriptorDest;
1309
- try {
1310
- descriptorSource = fs.statSync(source);
1311
- }
1312
- catch (error) {
1313
- log.verbose(`Source path "${source}" does not exist: ${error}`);
1314
- throw new Error(`Source path "${source}" does not exist: ${error}`);
1315
- }
1316
- try {
1317
- descriptorDest = fs.statSync(dest);
1318
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1319
- }
1320
- catch (e) {
1321
- // do nothing. its ok
1322
- }
1323
- if (descriptorDest) {
1324
- log.verbose(`Destination path "${dest}" already exists`);
1325
- throw new Error(`Destination path "${dest}" already exists`);
1326
- }
1327
- try {
1328
- log.verbose(`Renaming ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}...`);
1329
- fs.renameSync(source, dest);
1330
- log.verbose(`Successfully renamed to "${dest}"`);
1331
- }
1332
- catch (error) {
1333
- log.verbose(`Error renaming ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}": ${error}`);
1334
- throw new Error(`Error renaming ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}": ${error}`);
1335
- }
1336
- }
1337
- /**
1338
- * @description Copies a file or directory.
1339
- * @summary Creates a copy of a file or directory from the source path to the destination path.
1340
- *
1341
- * @param {string} source - The source path of the file or directory.
1342
- * @param {string} dest - The destination path for the file or directory.
1343
- * @return {void}
1344
- *
1345
- * @function copyFile
1346
- *
1347
- * @memberOf module:utils
1348
- */
1349
- function copyFile(source, dest) {
1350
- const log = logger.for(copyFile);
1351
- let descriptorSource, descriptorDest;
1352
- try {
1353
- descriptorSource = fs.statSync(source);
1354
- }
1355
- catch (error) {
1356
- log.verbose(`Source path "${source}" does not exist: ${error}`);
1357
- throw new Error(`Source path "${source}" does not exist: ${error}`);
1358
- }
1359
- try {
1360
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1361
- descriptorDest = fs.statSync(dest);
1362
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1363
- }
1364
- catch (error) {
1365
- if (descriptorSource.isDirectory()) {
1366
- log.verbose(`Dest path "${dest}" does not exist. creating`);
1367
- fs.mkdirSync(dest, { recursive: true });
1368
- }
1369
- }
1370
- try {
1371
- log.verbose(`Copying ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}...`);
1372
- fs.cpSync(source, dest, { recursive: true });
1373
- }
1374
- catch (error) {
1375
- log.verbose(`Error copying ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}: ${error}`);
1376
- throw new Error(`Error copying ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}: ${error}`);
1377
- }
1378
- }
1379
- /**
1380
- * @description Deletes a file or directory.
1381
- * @summary Removes a file or directory at the specified path, with recursive and force options enabled.
1382
- *
1383
- * @param {string} p - The path to the file or directory to delete.
1384
- * @return {void}
1385
- *
1386
- * @function deletePath
1387
- *
1388
- * @memberOf module:utils
1389
- */
1390
- function deletePath(p) {
1391
- const log = logger.for(deletePath);
1392
- try {
1393
- const descriptor = fs.statSync(p);
1394
- if (descriptor.isFile()) {
1395
- log.verbose(`Deleting file "${p}...`);
1396
- fs.rmSync(p, { recursive: true, force: true });
1397
- }
1398
- else if (descriptor.isDirectory())
1399
- fs.rmSync(p, { recursive: true, force: true });
1400
- }
1401
- catch (error) {
1402
- log.verbose(`Error Deleting "${p}": ${error}`);
1403
- throw new Error(`Error Deleting "${p}": ${error}`);
1404
- }
1405
- }
1406
- /**
1407
- * @description Retrieves package information from package.json.
1408
- * @summary Loads and parses the package.json file from a specified directory or the current working directory. Can return the entire package object or a specific property.
1409
- * @param {string} [p=process.cwd()] - The directory path where the package.json file is located.
1410
- * @param {string} [property] - Optional. The specific property to retrieve from package.json.
1411
- * @return {object | string} The parsed contents of package.json or the value of the specified property.
1412
- * @function getPackage
1413
- * @mermaid
1414
- * sequenceDiagram
1415
- * participant Caller
1416
- * participant getPackage
1417
- * participant readFile
1418
- * participant JSON
1419
- * Caller->>getPackage: Call with path and optional property
1420
- * getPackage->>readFile: Read package.json
1421
- * readFile-->>getPackage: Return file content
1422
- * getPackage->>JSON: Parse file content
1423
- * JSON-->>getPackage: Return parsed object
1424
- * alt property specified
1425
- * getPackage->>getPackage: Check if property exists
1426
- * alt property exists
1427
- * getPackage-->>Caller: Return property value
1428
- * else property doesn't exist
1429
- * getPackage-->>Caller: Throw Error
1430
- * end
1431
- * else no property specified
1432
- * getPackage-->>Caller: Return entire package object
1433
- * end
1434
- * @memberOf module:utils
1435
- */
1436
- function getPackage(p = process.cwd(), property) {
1437
- let pkg;
1438
- try {
1439
- pkg = JSON.parse(readFile(path.join(p, `package.json`)));
1440
- }
1441
- catch (error) {
1442
- throw new Error(`Failed to retrieve package information" ${error}`);
1443
- }
1444
- if (property) {
1445
- if (!(property in pkg))
1446
- throw new Error(`Property "${property}" not found in package.json`);
1447
- return pkg[property];
1448
- }
1449
- return pkg;
1450
- }
1451
- /**
1452
- * @description Sets an attribute in the package.json file.
1453
- * @summary Updates a specific attribute in the package.json file with the provided value.
1454
- *
1455
- * @param {string} attr - The attribute name to set in package.json.
1456
- * @param {string | number | object} value - The value to set for the attribute.
1457
- * @param {string} [p=process.cwd()] - The directory path where the package.json file is located.
1458
- * @return {void}
1459
- *
1460
- * @function setPackageAttribute
1461
- *
1462
- * @memberOf module:utils
1463
- */
1464
- function setPackageAttribute(attr, value, p = process.cwd()) {
1465
- const pkg = getPackage(p);
1466
- pkg[attr] = value;
1467
- writeFile(path.join(p, `package.json`), JSON.stringify(pkg, null, 2));
1468
- }
1469
- /**
1470
- * @description Retrieves the version from package.json.
1471
- * @summary A convenience function that calls getPackage to retrieve the "version" property from package.json.
1472
- * @param {string} [p=process.cwd()] - The directory path where the package.json file is located.
1473
- * @return {string} The version string from package.json.
1474
- * @function getPackageVersion
1475
- * @memberOf module:utils
1476
- */
1477
- function getPackageVersion(p = process.cwd()) {
1478
- return getPackage(p, "version");
1479
- }
1480
- /**
1481
- * @description Retrieves all dependencies from the project.
1482
- * @summary Executes 'npm ls --json' command to get a detailed list of all dependencies (production, development, and peer) and their versions.
1483
- * @param {string} [path=process.cwd()] - The directory path of the project.
1484
- * @return {Promise<{prod: Array<{name: string, version: string}>, dev: Array<{name: string, version: string}>, peer: Array<{name: string, version: string}>}>} An object containing arrays of production, development, and peer dependencies.
1485
- * @function getDependencies
1486
- * @mermaid
1487
- * sequenceDiagram
1488
- * participant Caller
1489
- * participant getDependencies
1490
- * participant runCommand
1491
- * participant JSON
1492
- * Caller->>getDependencies: Call with optional path
1493
- * getDependencies->>runCommand: Execute 'npm ls --json'
1494
- * runCommand-->>getDependencies: Return command output
1495
- * getDependencies->>JSON: Parse command output
1496
- * JSON-->>getDependencies: Return parsed object
1497
- * getDependencies->>getDependencies: Process dependencies
1498
- * getDependencies-->>Caller: Return processed dependencies
1499
- * @memberOf module:utils
1500
- */
1501
- async function getDependencies(path = process.cwd()) {
1502
- let pkg;
1503
- try {
1504
- pkg = JSON.parse(await runCommand(`npm ls --json`, { cwd: path }).promise);
1505
- }
1506
- catch (e) {
1507
- throw new Error(`Failed to retrieve dependencies: ${e}`);
1508
- }
1509
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1510
- const mapper = (entry, index) => ({
1511
- name: entry[0],
1512
- version: entry[1].version,
1513
- });
1514
- return {
1515
- prod: Object.entries(pkg.dependencies || {}).map(mapper),
1516
- dev: Object.entries(pkg.devDependencies || {}).map(mapper),
1517
- peer: Object.entries(pkg.peerDependencies || {}).map(mapper),
1518
- };
1519
- }
1520
- /**
1521
- * @description Updates project dependencies to their latest versions.
1522
- * @summary Runs npm-check-updates to update package.json and then installs the updated dependencies.
1523
- *
1524
- * @return {Promise<void>} A promise that resolves when dependencies are updated.
1525
- *
1526
- * @function updateDependencies
1527
- *
1528
- * @memberOf module:utils
1529
- */
1530
- async function updateDependencies() {
1531
- const log = logger.for(updateDependencies);
1532
- log.info("checking for updates...");
1533
- await runCommand("npx npm-check-updates -u").promise;
1534
- log.info("updating...");
1535
- await runCommand("npx npm run do-install").promise;
1536
- }
1537
- /**
1538
- * @description Installs dependencies if they are not already available.
1539
- * @summary Checks if specified dependencies are installed and installs any that are missing.
1540
- *
1541
- * @param {string[] | string} deps - The dependencies to check and potentially install.
1542
- * @param {SimpleDependencyMap} [dependencies] - Optional map of existing dependencies.
1543
- * @return {Promise<SimpleDependencyMap>} Updated map of dependencies.
1544
- *
1545
- * @function installIfNotAvailable
1546
- *
1547
- * @memberOf module:utils
1548
- */
1549
- async function installIfNotAvailable(deps, dependencies) {
1550
- if (!dependencies) {
1551
- const d = await getDependencies();
1552
- dependencies = {
1553
- prod: d.prod?.map((p) => p.name) || [],
1554
- dev: d.dev?.map((d) => d.name) || [],
1555
- peer: d.peer?.map((p) => p.name) || [],
1556
- };
1557
- }
1558
- const { prod, dev, peer } = dependencies;
1559
- const installed = Array.from(new Set([...(prod || []), ...(dev || []), ...(peer || [])]));
1560
- deps = typeof deps === "string" ? [deps] : deps;
1561
- const toInstall = deps.filter((d) => !installed.includes(d));
1562
- if (toInstall.length)
1563
- await installDependencies({ dev: toInstall });
1564
- dependencies.dev = dependencies.dev || [];
1565
- dependencies.dev.push(...toInstall);
1566
- return dependencies;
1567
- }
1568
- /**
1569
- * @description Pushes changes to Git repository.
1570
- * @summary Temporarily changes Git user configuration, commits all changes, pushes to remote, and restores original user configuration.
1571
- *
1572
- * @return {Promise<void>} A promise that resolves when changes are pushed.
1573
- *
1574
- * @function pushToGit
1575
- *
1576
- * @memberOf module:utils
1577
- */
1578
- async function pushToGit() {
1579
- const log = logger.for(pushToGit);
1580
- const gitUser = await runCommand("git config user.name").promise;
1581
- const gitEmail = await runCommand("git config user.email").promise;
1582
- log.verbose(`cached git id: ${gitUser}/${gitEmail}. changing to automation`);
1583
- await runCommand('git config user.email "automation@decaf.ts"').promise;
1584
- await runCommand('git config user.name "decaf"').promise;
1585
- log.info("Pushing changes to git...");
1586
- await runCommand("git add .").promise;
1587
- await runCommand(`git commit -m "refs #1 - after repo setup"`).promise;
1588
- await runCommand("git push").promise;
1589
- await runCommand(`git config user.email "${gitEmail}"`).promise;
1590
- await runCommand(`git config user.name "${gitUser}"`).promise;
1591
- log.verbose(`reverted to git id: ${gitUser}/${gitEmail}`);
1592
- }
1593
- /**
1594
- * @description Installs project dependencies.
1595
- * @summary Installs production, development, and peer dependencies as specified.
1596
- *
1597
- * @param {object} dependencies - Object containing arrays of dependencies to install.
1598
- * @param {string[]} [dependencies.prod] - Production dependencies to install.
1599
- * @param {string[]} [dependencies.dev] - Development dependencies to install.
1600
- * @param {string[]} [dependencies.peer] - Peer dependencies to install.
1601
- * @return {Promise<void>} A promise that resolves when all dependencies are installed.
1602
- *
1603
- * @function installDependencies
1604
- *
1605
- * @memberOf module:utils
1606
- */
1607
- async function installDependencies(dependencies) {
1608
- const log = logger.for(installDependencies);
1609
- const prod = dependencies.prod || [];
1610
- const dev = dependencies.dev || [];
1611
- const peer = dependencies.peer || [];
1612
- if (prod.length) {
1613
- log.info(`Installing dependencies ${prod.join(", ")}...`);
1614
- await runCommand(`npm install ${prod.join(" ")}`, { cwd: process.cwd() })
1615
- .promise;
1616
- }
1617
- if (dev.length) {
1618
- log.info(`Installing devDependencies ${dev.join(", ")}...`);
1619
- await runCommand(`npm install --save-dev ${dev.join(" ")}`, {
1620
- cwd: process.cwd(),
1621
- }).promise;
1622
- }
1623
- if (peer.length) {
1624
- log.info(`Installing peerDependencies ${peer.join(", ")}...`);
1625
- await runCommand(`npm install --save-peer ${peer.join(" ")}`, {
1626
- cwd: process.cwd(),
1627
- }).promise;
1628
- }
1629
- }
1630
- /**
1631
- * @description Normalizes imports to handle both CommonJS and ESModule formats.
1632
- * @summary Utility function to handle module import differences between formats.
1633
- *
1634
- * @template T - Type of the imported module.
1635
- * @param {Promise<T>} importPromise - Promise returned by dynamic import.
1636
- * @return {Promise<T>} Normalized module.
1637
- *
1638
- * @function normalizeImport
1639
- *
1640
- * @memberOf module:utils
1641
- */
1642
- async function normalizeImport(importPromise) {
1643
- // CommonJS's `module.exports` is wrapped as `default` in ESModule.
1644
- return importPromise.then((m) => (m.default || m));
1645
- }
1646
-
1647
- /**
1648
- * @description Definition of a slogan item.
1649
- * @summary Represents a single slogan entry with text and tags.
1650
- * @typedef {Object} SloganItem
1651
- * @property {string} Slogan - The slogan text.
1652
- * @property {string} Tags - Comma-separated tags describing the slogan.
1653
- * @memberOf module:utils
1654
- */
1655
- /**
1656
- * @description List of available slogans for banners and messages.
1657
- * @summary Immutable array of slogan entries used by {@link getSlogan} and banner rendering.
1658
- * @type {SloganItem[]}
1659
- * @const slogans
1660
- * @memberOf module:utils
1661
- */
1662
- const slogans = [
1663
- {
1664
- Slogan: "No caffeine, no chaos. Just clean code.",
1665
- Tags: "Coffee-themed, Calm, Tech",
1666
- },
1667
- {
1668
- Slogan: "Full flavor, no jitters. That's Decaf-TS.",
1669
- Tags: "Coffee-themed, Cheerful",
1670
- },
1671
- {
1672
- Slogan: "Chill fullstack. Powered by Decaf.",
1673
- Tags: "Coffee-themed, Fun, Tech",
1674
- },
1675
- {
1676
- Slogan: "Decaf-TS: Brewed for calm code.",
1677
- Tags: "Coffee-themed, Branding",
1678
- },
1679
- {
1680
- Slogan: "Smooth as your morning Decaf.",
1681
- Tags: "Coffee-themed, Chill",
1682
- },
1683
- {
1684
- Slogan: "All the kick, none of the crash.",
1685
- Tags: "Coffee-themed, Energetic",
1686
- },
1687
- {
1688
- Slogan: "Sip back and ship faster.",
1689
- Tags: "Coffee-themed, Fun",
1690
- },
1691
- {
1692
- Slogan: "Keep calm and code Decaf.",
1693
- Tags: "Coffee-themed, Playful",
1694
- },
1695
- {
1696
- Slogan: "Code without the caffeine shakes.",
1697
- Tags: "Coffee-themed, Humorous",
1698
- },
1699
- {
1700
- Slogan: "Your fullstack, decaffeinated.",
1701
- Tags: "Coffee-themed, Technical",
1702
- },
1703
- {
1704
- Slogan: "No caffeine, no chaos. Just clean code.",
1705
- Tags: "Coffee-themed, Calm, Tech",
1706
- },
1707
- {
1708
- Slogan: "Full flavor, no jitters. That\u2019s Decaf-TS.",
1709
- Tags: "Coffee-themed, Cheerful",
1710
- },
1711
- {
1712
- Slogan: "Chill fullstack. Powered by Decaf.",
1713
- Tags: "Coffee-themed, Fun, Tech",
1714
- },
1715
- {
1716
- Slogan: "Decaf-TS: Brewed for calm code.",
1717
- Tags: "Coffee-themed, Branding",
1718
- },
1719
- {
1720
- Slogan: "Smooth as your morning Decaf.",
1721
- Tags: "Coffee-themed, Chill",
1722
- },
1723
- {
1724
- Slogan: "All the kick, none of the crash.",
1725
- Tags: "Coffee-themed, Energetic",
1726
- },
1727
- {
1728
- Slogan: "Sip back and ship faster.",
1729
- Tags: "Coffee-themed, Fun",
1730
- },
1731
- {
1732
- Slogan: "Keep calm and code Decaf.",
1733
- Tags: "Coffee-themed, Playful",
1734
- },
1735
- {
1736
- Slogan: "Code without the caffeine shakes.",
1737
- Tags: "Coffee-themed, Humorous",
1738
- },
1739
- {
1740
- Slogan: "Your fullstack, decaffeinated.",
1741
- Tags: "Coffee-themed, Technical",
1742
- },
1743
- {
1744
- Slogan: "No caffeine, no chaos. Just clean code.",
1745
- Tags: "Coffee-themed, Calm, Tech",
1746
- },
1747
- {
1748
- Slogan: "Full flavor, no jitters. That\u2019s Decaf-TS.",
1749
- Tags: "Coffee-themed, Cheerful",
1750
- },
1751
- {
1752
- Slogan: "Chill fullstack. Powered by Decaf.",
1753
- Tags: "Coffee-themed, Fun, Tech",
1754
- },
1755
- {
1756
- Slogan: "Decaf-TS: Brewed for calm code.",
1757
- Tags: "Coffee-themed, Branding",
1758
- },
1759
- {
1760
- Slogan: "Smooth as your morning Decaf.",
1761
- Tags: "Coffee-themed, Chill",
1762
- },
1763
- {
1764
- Slogan: "All the kick, none of the crash.",
1765
- Tags: "Coffee-themed, Energetic",
1766
- },
1767
- {
1768
- Slogan: "Sip back and ship faster.",
1769
- Tags: "Coffee-themed, Fun",
1770
- },
1771
- {
1772
- Slogan: "Keep calm and code Decaf.",
1773
- Tags: "Coffee-themed, Playful",
1774
- },
1775
- {
1776
- Slogan: "Code without the caffeine shakes.",
1777
- Tags: "Coffee-themed, Humorous",
1778
- },
1779
- {
1780
- Slogan: "Your fullstack, decaffeinated.",
1781
- Tags: "Coffee-themed, Technical",
1782
- },
1783
- {
1784
- Slogan: "No caffeine, no chaos. Just clean code.",
1785
- Tags: "Coffee-themed, Calm, Tech",
1786
- },
1787
- {
1788
- Slogan: "Full flavor, no jitters. That\u2019s Decaf-TS.",
1789
- Tags: "Coffee-themed, Cheerful",
1790
- },
1791
- {
1792
- Slogan: "Chill fullstack. Powered by Decaf.",
1793
- Tags: "Coffee-themed, Fun, Tech",
1794
- },
1795
- {
1796
- Slogan: "Decaf-TS: Brewed for calm code.",
1797
- Tags: "Coffee-themed, Branding",
1798
- },
1799
- {
1800
- Slogan: "Smooth as your morning Decaf.",
1801
- Tags: "Coffee-themed, Chill",
1802
- },
1803
- {
1804
- Slogan: "All the kick, none of the crash.",
1805
- Tags: "Coffee-themed, Energetic",
1806
- },
1807
- {
1808
- Slogan: "Sip back and ship faster.",
1809
- Tags: "Coffee-themed, Fun",
1810
- },
1811
- {
1812
- Slogan: "Keep calm and code Decaf.",
1813
- Tags: "Coffee-themed, Playful",
1814
- },
1815
- {
1816
- Slogan: "Code without the caffeine shakes.",
1817
- Tags: "Coffee-themed, Humorous",
1818
- },
1819
- {
1820
- Slogan: "Your fullstack, decaffeinated.",
1821
- Tags: "Coffee-themed, Technical",
1822
- },
1823
- {
1824
- Slogan: "No caffeine, no chaos. Just clean code.",
1825
- Tags: "Coffee-themed, Calm, Tech",
1826
- },
1827
- {
1828
- Slogan: "Full flavor, no jitters. That\u2019s Decaf-TS.",
1829
- Tags: "Coffee-themed, Cheerful",
1830
- },
1831
- {
1832
- Slogan: "Chill fullstack. Powered by Decaf.",
1833
- Tags: "Coffee-themed, Fun, Tech",
1834
- },
1835
- {
1836
- Slogan: "Decaf-TS: Brewed for calm code.",
1837
- Tags: "Coffee-themed, Branding",
1838
- },
1839
- {
1840
- Slogan: "Smooth as your morning Decaf.",
1841
- Tags: "Coffee-themed, Chill",
1842
- },
1843
- {
1844
- Slogan: "All the kick, none of the crash.",
1845
- Tags: "Coffee-themed, Energetic",
1846
- },
1847
- {
1848
- Slogan: "Sip back and ship faster.",
1849
- Tags: "Coffee-themed, Fun",
1850
- },
1851
- {
1852
- Slogan: "Keep calm and code Decaf.",
1853
- Tags: "Coffee-themed, Playful",
1854
- },
1855
- {
1856
- Slogan: "Code without the caffeine shakes.",
1857
- Tags: "Coffee-themed, Humorous",
1858
- },
1859
- {
1860
- Slogan: "Your fullstack, decaffeinated.",
1861
- Tags: "Coffee-themed, Technical",
1862
- },
1863
- {
1864
- Slogan: "No caffeine, no chaos. Just clean code.",
1865
- Tags: "Coffee-themed, Calm, Tech",
1866
- },
1867
- {
1868
- Slogan: "Full flavor, no jitters. That\u2019s Decaf-TS.",
1869
- Tags: "Coffee-themed, Cheerful",
1870
- },
1871
- {
1872
- Slogan: "Chill fullstack. Powered by Decaf.",
1873
- Tags: "Coffee-themed, Fun, Tech",
1874
- },
1875
- {
1876
- Slogan: "Decaf-TS: Brewed for calm code.",
1877
- Tags: "Coffee-themed, Branding",
1878
- },
1879
- {
1880
- Slogan: "Smooth as your morning Decaf.",
1881
- Tags: "Coffee-themed, Chill",
1882
- },
1883
- {
1884
- Slogan: "All the kick, none of the crash.",
1885
- Tags: "Coffee-themed, Energetic",
1886
- },
1887
- {
1888
- Slogan: "Sip back and ship faster.",
1889
- Tags: "Coffee-themed, Fun",
1890
- },
1891
- {
1892
- Slogan: "Keep calm and code Decaf.",
1893
- Tags: "Coffee-themed, Playful",
1894
- },
1895
- {
1896
- Slogan: "Code without the caffeine shakes.",
1897
- Tags: "Coffee-themed, Humorous",
1898
- },
1899
- {
1900
- Slogan: "Your fullstack, decaffeinated.",
1901
- Tags: "Coffee-themed, Technical",
1902
- },
1903
- {
1904
- Slogan: "No caffeine, no chaos. Just clean code.",
1905
- Tags: "Coffee-themed, Calm, Tech",
1906
- },
1907
- {
1908
- Slogan: "Full flavor, no jitters. That\u2019s Decaf-TS.",
1909
- Tags: "Coffee-themed, Cheerful",
1910
- },
1911
- {
1912
- Slogan: "Chill fullstack. Powered by Decaf.",
1913
- Tags: "Coffee-themed, Fun, Tech",
1914
- },
1915
- {
1916
- Slogan: "Decaf-TS: Brewed for calm code.",
1917
- Tags: "Coffee-themed, Branding",
1918
- },
1919
- {
1920
- Slogan: "Smooth as your morning Decaf.",
1921
- Tags: "Coffee-themed, Chill",
1922
- },
1923
- {
1924
- Slogan: "All the kick, none of the crash.",
1925
- Tags: "Coffee-themed, Energetic",
1926
- },
1927
- {
1928
- Slogan: "Sip back and ship faster.",
1929
- Tags: "Coffee-themed, Fun",
1930
- },
1931
- {
1932
- Slogan: "Keep calm and code Decaf.",
1933
- Tags: "Coffee-themed, Playful",
1934
- },
1935
- {
1936
- Slogan: "Code without the caffeine shakes.",
1937
- Tags: "Coffee-themed, Humorous",
1938
- },
1939
- {
1940
- Slogan: "Your fullstack, decaffeinated.",
1941
- Tags: "Coffee-themed, Technical",
1942
- },
1943
- {
1944
- Slogan: "No caffeine, no chaos. Just clean code.",
1945
- Tags: "Coffee-themed, Calm, Tech",
1946
- },
1947
- {
1948
- Slogan: "Full flavor, no jitters. That\u2019s Decaf-TS.",
1949
- Tags: "Coffee-themed, Cheerful",
1950
- },
1951
- {
1952
- Slogan: "Chill fullstack. Powered by Decaf.",
1953
- Tags: "Coffee-themed, Fun, Tech",
1954
- },
1955
- {
1956
- Slogan: "Decaf-TS: Brewed for calm code.",
1957
- Tags: "Coffee-themed, Branding",
1958
- },
1959
- {
1960
- Slogan: "Smooth as your morning Decaf.",
1961
- Tags: "Coffee-themed, Chill",
1962
- },
1963
- {
1964
- Slogan: "All the kick, none of the crash.",
1965
- Tags: "Coffee-themed, Energetic",
1966
- },
1967
- {
1968
- Slogan: "Sip back and ship faster.",
1969
- Tags: "Coffee-themed, Fun",
1970
- },
1971
- {
1972
- Slogan: "Keep calm and code Decaf.",
1973
- Tags: "Coffee-themed, Playful",
1974
- },
1975
- {
1976
- Slogan: "Code without the caffeine shakes.",
1977
- Tags: "Coffee-themed, Humorous",
1978
- },
1979
- {
1980
- Slogan: "Your fullstack, decaffeinated.",
1981
- Tags: "Coffee-themed, Technical",
1982
- },
1983
- {
1984
- Slogan: "No caffeine, no chaos. Just clean code.",
1985
- Tags: "Coffee-themed, Calm, Tech",
1986
- },
1987
- {
1988
- Slogan: "Full flavor, no jitters. That\u2019s Decaf-TS.",
1989
- Tags: "Coffee-themed, Cheerful",
1990
- },
1991
- {
1992
- Slogan: "Chill fullstack. Powered by Decaf.",
1993
- Tags: "Coffee-themed, Fun, Tech",
1994
- },
1995
- {
1996
- Slogan: "Decaf-TS: Brewed for calm code.",
1997
- Tags: "Coffee-themed, Branding",
1998
- },
1999
- {
2000
- Slogan: "Smooth as your morning Decaf.",
2001
- Tags: "Coffee-themed, Chill",
2002
- },
2003
- {
2004
- Slogan: "All the kick, none of the crash.",
2005
- Tags: "Coffee-themed, Energetic",
2006
- },
2007
- {
2008
- Slogan: "Sip back and ship faster.",
2009
- Tags: "Coffee-themed, Fun",
2010
- },
2011
- {
2012
- Slogan: "Keep calm and code Decaf.",
2013
- Tags: "Coffee-themed, Playful",
2014
- },
2015
- {
2016
- Slogan: "Code without the caffeine shakes.",
2017
- Tags: "Coffee-themed, Humorous",
2018
- },
2019
- {
2020
- Slogan: "Your fullstack, decaffeinated.",
2021
- Tags: "Coffee-themed, Technical",
2022
- },
2023
- {
2024
- Slogan: "No caffeine, no chaos. Just clean code.",
2025
- Tags: "Coffee-themed, Calm, Tech",
2026
- },
2027
- {
2028
- Slogan: "Full flavor, no jitters. That\u2019s Decaf-TS.",
2029
- Tags: "Coffee-themed, Cheerful",
2030
- },
2031
- {
2032
- Slogan: "Chill fullstack. Powered by Decaf.",
2033
- Tags: "Coffee-themed, Fun, Tech",
2034
- },
2035
- {
2036
- Slogan: "Decaf-TS: Brewed for calm code.",
2037
- Tags: "Coffee-themed, Branding",
2038
- },
2039
- {
2040
- Slogan: "Smooth as your morning Decaf.",
2041
- Tags: "Coffee-themed, Chill",
2042
- },
2043
- {
2044
- Slogan: "All the kick, none of the crash.",
2045
- Tags: "Coffee-themed, Energetic",
2046
- },
2047
- {
2048
- Slogan: "Sip back and ship faster.",
2049
- Tags: "Coffee-themed, Fun",
2050
- },
2051
- {
2052
- Slogan: "Keep calm and code Decaf.",
2053
- Tags: "Coffee-themed, Playful",
2054
- },
2055
- {
2056
- Slogan: "Code without the caffeine shakes.",
2057
- Tags: "Coffee-themed, Humorous",
2058
- },
2059
- {
2060
- Slogan: "Your fullstack, decaffeinated.",
2061
- Tags: "Coffee-themed, Technical",
2062
- },
2063
- {
2064
- Slogan: "Decaf-TS: Where smart contracts meet smart interfaces.",
2065
- Tags: "Blockchain, Smart Contracts, Tech",
2066
- },
2067
- {
2068
- Slogan: "Ship dApps without the stress.",
2069
- Tags: "Blockchain, Cheerful, Developer",
2070
- },
2071
- {
2072
- Slogan: "No CRUD, no problem \u2014 Decaf your data.",
2073
- Tags: "Data, No-CRUD, Chill",
2074
- },
2075
- {
2076
- Slogan: "From DID to UI, without breaking a sweat.",
2077
- Tags: "DID, SSI, UI, Calm",
2078
- },
2079
- {
2080
- Slogan: "Decaf-TS: Your frontend already understands your smart contract.",
2081
- Tags: "Smart Contracts, DX, Magic",
2082
- },
2083
- {
2084
- Slogan: "Self-sovereign by design. Productive by default.",
2085
- Tags: "SSI, Developer, Calm",
2086
- },
2087
- {
2088
- Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
2089
- Tags: "Blockchain, Multi-platform, Happy",
2090
- },
2091
- {
2092
- Slogan: "Data that defines its own destiny.",
2093
- Tags: "SSI, Data-driven, Empowerment",
2094
- },
2095
- {
2096
- Slogan: "Goodbye CRUD, hello intent-based interfaces.",
2097
- Tags: "No-CRUD, UI, Technical",
2098
- },
2099
- {
2100
- Slogan: "The smoothest path from DID to done.",
2101
- Tags: "DID, Workflow, Chill",
2102
- },
2103
- {
2104
- Slogan: "Because your dApp deserves more than boilerplate.",
2105
- Tags: "Blockchain, DevX, Efficiency",
2106
- },
2107
- {
2108
- Slogan: "Own your data. Own your flow.",
2109
- Tags: "SSI, Control, Ownership",
2110
- },
2111
- {
2112
- Slogan: "Write logic like it belongs with the data \u2014 because it does.",
2113
- Tags: "Data Logic, Developer, Smart",
2114
- },
2115
- {
2116
- Slogan: "From smart contracts to smarter frontends.",
2117
- Tags: "Smart Contracts, UI, DX",
2118
- },
2119
- {
2120
- Slogan: "No caffeine. No CRUD. Just the future.",
2121
- Tags: "No-CRUD, Coffee-themed, Futuristic",
2122
- },
2123
- {
2124
- Slogan: "The future of web3 UX is Decaf.",
2125
- Tags: "Blockchain, UX, Vision",
2126
- },
2127
- {
2128
- Slogan: "Code with confidence. Govern with clarity.",
2129
- Tags: "Blockchain, Governance, Calm",
2130
- },
2131
- {
2132
- Slogan: "Interfaces that obey the data, not the other way around.",
2133
- Tags: "UI, Data Logic, Self-aware",
2134
- },
2135
- {
2136
- Slogan: "Brew business logic right into your bytes.",
2137
- Tags: "Data Logic, Coffee-themed, Fun",
2138
- },
2139
- {
2140
- Slogan: "DIDs done differently \u2014 and delightfully.",
2141
- Tags: "DID, Self-Sovereign, Playful",
2142
- },
2143
- {
2144
- Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
2145
- Tags: "Blockchain, Smart Contracts, Tech",
2146
- },
2147
- {
2148
- Slogan: "Ship dApps without the stress.",
2149
- Tags: "Blockchain, Cheerful, Developer",
2150
- },
2151
- {
2152
- Slogan: "No boilerplate, no problem \u2014 Decaf-TS your data.",
2153
- Tags: "Data, No-CRUD, Chill",
2154
- },
2155
- {
2156
- Slogan: "From DID to UI, without breaking a sweat.",
2157
- Tags: "DID, SSI, UI, Calm",
2158
- },
2159
- {
2160
- Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
2161
- Tags: "Smart Contracts, DX, Magic",
2162
- },
2163
- {
2164
- Slogan: "Self-sovereign by design. Productive by default.",
2165
- Tags: "SSI, Developer, Calm",
2166
- },
2167
- {
2168
- Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
2169
- Tags: "Blockchain, Multi-platform, Happy",
2170
- },
2171
- {
2172
- Slogan: "Data that defines its own destiny.",
2173
- Tags: "SSI, Data-driven, Empowerment",
2174
- },
2175
- {
2176
- Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
2177
- Tags: "No-CRUD, UI, Technical",
2178
- },
2179
- {
2180
- Slogan: "The smoothest path from DID to done.",
2181
- Tags: "DID, Workflow, Chill",
2182
- },
2183
- {
2184
- Slogan: "Because your dApp deserves more than boilerplate.",
2185
- Tags: "Blockchain, DevX, Efficiency",
2186
- },
2187
- {
2188
- Slogan: "Own your data. Own your flow.",
2189
- Tags: "SSI, Control, Ownership",
2190
- },
2191
- {
2192
- Slogan: "Write logic like it belongs with the data \u2014 because it does.",
2193
- Tags: "Data Logic, Developer, Smart",
2194
- },
2195
- {
2196
- Slogan: "From blockchain contracts to smarter frontends.",
2197
- Tags: "Smart Contracts, UI, DX",
2198
- },
2199
- {
2200
- Slogan: "No caffeine. No boilerplate. Just the future.",
2201
- Tags: "No-CRUD, Coffee-themed, Futuristic",
2202
- },
2203
- {
2204
- Slogan: "The future of web3 UX is Decaf-TS.",
2205
- Tags: "Blockchain, UX, Vision",
2206
- },
2207
- {
2208
- Slogan: "Code with confidence. Govern with clarity.",
2209
- Tags: "Blockchain, Governance, Calm",
2210
- },
2211
- {
2212
- Slogan: "Interfaces that obey the data, not the other way around.",
2213
- Tags: "UI, Data Logic, Self-aware",
2214
- },
2215
- {
2216
- Slogan: "Brew business logic right into your bytes.",
2217
- Tags: "Data Logic, Coffee-themed, Fun",
2218
- },
2219
- {
2220
- Slogan: "DIDs done differently \u2014 and delightfully.",
2221
- Tags: "DID, Self-Sovereign, Playful",
2222
- },
2223
- {
2224
- Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
2225
- Tags: "Blockchain, Smart Contracts, Tech",
2226
- },
2227
- {
2228
- Slogan: "Ship dApps without the stress.",
2229
- Tags: "Blockchain, Cheerful, Developer",
2230
- },
2231
- {
2232
- Slogan: "No boilerplate, no problem \u2014 Decaf-TS your data.",
2233
- Tags: "Data, No-CRUD, Chill",
2234
- },
2235
- {
2236
- Slogan: "From DID to UI, without breaking a sweat.",
2237
- Tags: "DID, SSI, UI, Calm",
2238
- },
2239
- {
2240
- Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
2241
- Tags: "Smart Contracts, DX, Magic",
2242
- },
2243
- {
2244
- Slogan: "Self-sovereign by design. Productive by default.",
2245
- Tags: "SSI, Developer, Calm",
2246
- },
2247
- {
2248
- Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
2249
- Tags: "Blockchain, Multi-platform, Happy",
2250
- },
2251
- {
2252
- Slogan: "Data that defines its own destiny.",
2253
- Tags: "SSI, Data-driven, Empowerment",
2254
- },
2255
- {
2256
- Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
2257
- Tags: "No-CRUD, UI, Technical",
2258
- },
2259
- {
2260
- Slogan: "The smoothest path from DID to done.",
2261
- Tags: "DID, Workflow, Chill",
2262
- },
2263
- {
2264
- Slogan: "Because your dApp deserves more than boilerplate.",
2265
- Tags: "Blockchain, DevX, Efficiency",
2266
- },
2267
- {
2268
- Slogan: "Own your data. Own your flow.",
2269
- Tags: "SSI, Control, Ownership",
2270
- },
2271
- {
2272
- Slogan: "Write logic like it belongs with the data \u2014 because it does.",
2273
- Tags: "Data Logic, Developer, Smart",
2274
- },
2275
- {
2276
- Slogan: "From blockchain contracts to smarter frontends.",
2277
- Tags: "Smart Contracts, UI, DX",
2278
- },
2279
- {
2280
- Slogan: "No caffeine. No boilerplate. Just the future.",
2281
- Tags: "No-CRUD, Coffee-themed, Futuristic",
2282
- },
2283
- {
2284
- Slogan: "The future of web3 UX is Decaf-TS.",
2285
- Tags: "Blockchain, UX, Vision",
2286
- },
2287
- {
2288
- Slogan: "Code with confidence. Govern with clarity.",
2289
- Tags: "Blockchain, Governance, Calm",
2290
- },
2291
- {
2292
- Slogan: "Interfaces that obey the data, not the other way around.",
2293
- Tags: "UI, Data Logic, Self-aware",
2294
- },
2295
- {
2296
- Slogan: "Brew business logic right into your bytes.",
2297
- Tags: "Data Logic, Coffee-themed, Fun",
2298
- },
2299
- {
2300
- Slogan: "DIDs done differently \u2014 and delightfully.",
2301
- Tags: "DID, Self-Sovereign, Playful",
2302
- },
2303
- {
2304
- Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
2305
- Tags: "Blockchain, Smart Contracts, Tech",
2306
- },
2307
- {
2308
- Slogan: "Ship dApps without the stress.",
2309
- Tags: "Blockchain, Cheerful, Developer",
2310
- },
2311
- {
2312
- Slogan: "No boilerplate, no problem \u2014 Decaf-TS your data.",
2313
- Tags: "Data, No-CRUD, Chill",
2314
- },
2315
- {
2316
- Slogan: "From DID to UI, without breaking a sweat.",
2317
- Tags: "DID, SSI, UI, Calm",
2318
- },
2319
- {
2320
- Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
2321
- Tags: "Smart Contracts, DX, Magic",
2322
- },
2323
- {
2324
- Slogan: "Self-sovereign by design. Productive by default.",
2325
- Tags: "SSI, Developer, Calm",
2326
- },
2327
- {
2328
- Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
2329
- Tags: "Blockchain, Multi-platform, Happy",
2330
- },
2331
- {
2332
- Slogan: "Data that defines its own destiny.",
2333
- Tags: "SSI, Data-driven, Empowerment",
2334
- },
2335
- {
2336
- Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
2337
- Tags: "No-CRUD, UI, Technical",
2338
- },
2339
- {
2340
- Slogan: "The smoothest path from DID to done.",
2341
- Tags: "DID, Workflow, Chill",
2342
- },
2343
- {
2344
- Slogan: "Because your dApp deserves more than boilerplate.",
2345
- Tags: "Blockchain, DevX, Efficiency",
2346
- },
2347
- {
2348
- Slogan: "Own your data. Own your flow.",
2349
- Tags: "SSI, Control, Ownership",
2350
- },
2351
- {
2352
- Slogan: "Write logic like it belongs with the data \u2014 because it does.",
2353
- Tags: "Data Logic, Developer, Smart",
2354
- },
2355
- {
2356
- Slogan: "From blockchain contracts to smarter frontends.",
2357
- Tags: "Smart Contracts, UI, DX",
2358
- },
2359
- {
2360
- Slogan: "No caffeine. No boilerplate. Just the future.",
2361
- Tags: "No-CRUD, Coffee-themed, Futuristic",
2362
- },
2363
- {
2364
- Slogan: "The future of web3 UX is Decaf-TS.",
2365
- Tags: "Blockchain, UX, Vision",
2366
- },
2367
- {
2368
- Slogan: "Code with confidence. Govern with clarity.",
2369
- Tags: "Blockchain, Governance, Calm",
2370
- },
2371
- {
2372
- Slogan: "Interfaces that obey the data, not the other way around.",
2373
- Tags: "UI, Data Logic, Self-aware",
2374
- },
2375
- {
2376
- Slogan: "Brew business logic right into your bytes.",
2377
- Tags: "Data Logic, Coffee-themed, Fun",
2378
- },
2379
- {
2380
- Slogan: "DIDs done differently \u2014 and delightfully.",
2381
- Tags: "DID, Self-Sovereign, Playful",
2382
- },
2383
- {
2384
- Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
2385
- Tags: "Blockchain, Smart Contracts, Tech",
2386
- },
2387
- {
2388
- Slogan: "Ship dApps without the stress.",
2389
- Tags: "Blockchain, Cheerful, Developer",
2390
- },
2391
- {
2392
- Slogan: "No boilerplate, no problem \u2014 Decaf-TS your data.",
2393
- Tags: "Data, No-CRUD, Chill",
2394
- },
2395
- {
2396
- Slogan: "From DID to UI, without breaking a sweat.",
2397
- Tags: "DID, SSI, UI, Calm",
2398
- },
2399
- {
2400
- Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
2401
- Tags: "Smart Contracts, DX, Magic",
2402
- },
2403
- {
2404
- Slogan: "Self-sovereign by design. Productive by default.",
2405
- Tags: "SSI, Developer, Calm",
2406
- },
2407
- {
2408
- Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
2409
- Tags: "Blockchain, Multi-platform, Happy",
2410
- },
2411
- {
2412
- Slogan: "Data that defines its own destiny.",
2413
- Tags: "SSI, Data-driven, Empowerment",
2414
- },
2415
- {
2416
- Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
2417
- Tags: "No-CRUD, UI, Technical",
2418
- },
2419
- {
2420
- Slogan: "The smoothest path from DID to done.",
2421
- Tags: "DID, Workflow, Chill",
2422
- },
2423
- {
2424
- Slogan: "Because your dApp deserves more than boilerplate.",
2425
- Tags: "Blockchain, DevX, Efficiency",
2426
- },
2427
- {
2428
- Slogan: "Own your data. Own your flow.",
2429
- Tags: "SSI, Control, Ownership",
2430
- },
2431
- {
2432
- Slogan: "Write logic like it belongs with the data \u2014 because it does.",
2433
- Tags: "Data Logic, Developer, Smart",
2434
- },
2435
- {
2436
- Slogan: "From blockchain contracts to smarter frontends.",
2437
- Tags: "Smart Contracts, UI, DX",
2438
- },
2439
- {
2440
- Slogan: "No caffeine. No boilerplate. Just the future.",
2441
- Tags: "No-CRUD, Coffee-themed, Futuristic",
2442
- },
2443
- {
2444
- Slogan: "The future of web3 UX is Decaf-TS.",
2445
- Tags: "Blockchain, UX, Vision",
2446
- },
2447
- {
2448
- Slogan: "Code with confidence. Govern with clarity.",
2449
- Tags: "Blockchain, Governance, Calm",
2450
- },
2451
- {
2452
- Slogan: "Interfaces that obey the data, not the other way around.",
2453
- Tags: "UI, Data Logic, Self-aware",
2454
- },
2455
- {
2456
- Slogan: "Brew business logic right into your bytes.",
2457
- Tags: "Data Logic, Coffee-themed, Fun",
2458
- },
2459
- {
2460
- Slogan: "DIDs done differently \u2014 and delightfully.",
2461
- Tags: "DID, Self-Sovereign, Playful",
2462
- },
2463
- ];
2464
-
2465
- /**
2466
- * @description Array of ANSI color codes for banner styling.
2467
- * @summary Defines a set of ANSI color codes used to style the banner text.
2468
- * @memberOf module:utils
2469
- */
2470
- const colors = [
2471
- "\x1b[38;5;215m", // soft orange
2472
- "\x1b[38;5;209m", // coral
2473
- "\x1b[38;5;205m", // pink
2474
- "\x1b[38;5;210m", // peachy
2475
- "\x1b[38;5;217m", // salmon
2476
- "\x1b[38;5;216m", // light coral
2477
- "\x1b[38;5;224m", // light peach
2478
- "\x1b[38;5;230m", // soft cream
2479
- "\x1b[38;5;230m", // soft cream
2480
- ];
2481
- /**
2482
- * @description Prints a styled banner to the console.
2483
- * @summary Generates and prints a colorful ASCII art banner with a random slogan.
2484
- * @param {Logger} [logger] - Optional logger for verbose output.
2485
- * @memberOf module:utils
2486
- * @function printBanner
2487
- * @mermaid
2488
- * sequenceDiagram
2489
- * participant printBanner
2490
- * participant getSlogan
2491
- * participant padEnd
2492
- * participant console
2493
- * printBanner->>getSlogan: Call getSlogan()
2494
- * getSlogan-->>printBanner: Return random slogan
2495
- * printBanner->>printBanner: Create banner ASCII art
2496
- * printBanner->>printBanner: Split banner into lines
2497
- * printBanner->>printBanner: Calculate max line length
2498
- * printBanner->>padEnd: Call padEnd with slogan
2499
- * padEnd-->>printBanner: Return padded slogan line
2500
- * loop For each banner line
2501
- * printBanner->>style: Call style(line)
2502
- * style-->>printBanner: Return styled line
2503
- * printBanner->>console: Log styled line
2504
- * end
2505
- */
2506
- function printBanner(logger) {
2507
- const message = getSlogan();
2508
- const banner = `# ░▒▓███████▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓██████▓▒░ ░▒▓████████▓▒░ ░▒▓████████▓▒░ ░▒▓███████▓▒░
2509
- # ( ( ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
2510
- # ) ) ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
2511
- # [=======] ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓██████▓▒░
2512
- # \`-----´ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
2513
- # ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
2514
- # ░▒▓███████▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓███████▓▒░
2515
- #`.split("\n");
2516
- const maxLength = banner.reduce((max, line) => Math.max(max, line.length), 0);
2517
- banner.push(`# ${message.padStart(maxLength - 3)}`);
2518
- banner.forEach((line, index) => {
2519
- (logger ? logger.info.bind(logger) : console.log.bind(console))(style(line || "").raw(colors[index]).text);
2520
- });
2521
- }
2522
- /**
2523
- * @description Retrieves a slogan from the predefined list.
2524
- * @summary Fetches a random slogan or a specific one by index from the slogans list.
2525
- * @param {number} [i] - Optional index to retrieve a specific slogan.
2526
- * @return {string} The selected slogan.
2527
- * @function getSlogan
2528
- * @memberOf module:utils
2529
- * @mermaid
2530
- * sequenceDiagram
2531
- * participant getSlogan
2532
- * participant Math.random
2533
- * participant slogans
2534
- * alt i is undefined
2535
- * getSlogan->>Math.random: Generate random index
2536
- * Math.random-->>getSlogan: Return random index
2537
- * else i is defined
2538
- * Note over getSlogan: Use provided index
2539
- * end
2540
- * getSlogan->>slogans: Access slogan at index
2541
- * slogans-->>getSlogan: Return slogan
2542
- * alt Error occurs
2543
- * getSlogan->>getSlogan: Throw error
2544
- * end
2545
- * getSlogan-->>Caller: Return slogan
2546
- */
2547
- function getSlogan(i) {
2548
- try {
2549
- i =
2550
- typeof i === "undefined" ? Math.floor(Math.random() * slogans.length) : i;
2551
- return slogans[i].Slogan;
2552
- }
2553
- catch (error) {
2554
- throw new Error(`Failed to retrieve slogans: ${error}`);
2555
- }
2556
- }
2557
-
2558
- /**
2559
- * @class Command
2560
- * @abstract
2561
- * @template I - The type of input options for the command.
2562
- * @template R - The return type of the command execution.
2563
- * @memberOf module:utils
2564
- * @description Abstract base class for command implementation.
2565
- * @summary Provides a structure for creating command-line interface commands with input handling, logging, and execution flow.
2566
- *
2567
- * @param {string} name - The name of the command.
2568
- * @param {CommandOptions<I>} [inputs] - The input options for the command.
2569
- * @param {string[]} [requirements] - The list of required dependencies for the command.
2570
- */
2571
- class Command extends LoggedClass {
2572
- constructor(name, inputs = {}, requirements = []) {
2573
- super();
2574
- this.name = name;
2575
- this.inputs = inputs;
2576
- this.requirements = requirements;
2577
- if (!Command.log) {
2578
- Object.defineProperty(Command, "log", {
2579
- writable: false,
2580
- value: Logging.for(Command.name),
2581
- });
2582
- }
2583
- this.inputs = Object.assign({}, DefaultCommandOptions, inputs);
2584
- }
2585
- /**
2586
- * @protected
2587
- * @async
2588
- * @description Checks if all required dependencies are present.
2589
- * @summary Retrieves the list of dependencies and compares it against the required dependencies for the command.
2590
- * @returns {Promise<void>} A promise that resolves when the check is complete.
2591
- *
2592
- * @mermaid
2593
- * sequenceDiagram
2594
- * participant Command
2595
- * participant getDependencies
2596
- * participant Set
2597
- * Command->>getDependencies: Call
2598
- * getDependencies-->>Command: Return {prod, dev, peer}
2599
- * Command->>Set: Create Set from prod, dev, peer
2600
- * Set-->>Command: Return unique dependencies
2601
- * Command->>Command: Compare against requirements
2602
- * alt Missing dependencies
2603
- * Command->>Command: Add to missing list
2604
- * end
2605
- * Note over Command: If missing.length > 0, handle missing dependencies
2606
- */
2607
- async checkRequirements() {
2608
- const { prod, dev, peer } = await getDependencies();
2609
- const missing = [];
2610
- const fullList = Array.from(new Set([...prod, ...dev, ...peer]).values()).map((d) => d.name);
2611
- for (const dep of this.requirements)
2612
- if (!fullList.includes(dep))
2613
- missing.push(dep);
2614
- if (!missing.length)
2615
- return;
2616
- }
2617
- /**
2618
- * @protected
2619
- * @description Provides help information for the command.
2620
- * @summary This method should be overridden in derived classes to provide specific help information.
2621
- * @param {ParseArgsResult} args - The parsed command-line arguments.
2622
- * @returns {void}
2623
- */
2624
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2625
- help(args) {
2626
- return this.log.info(`This is help. I'm no use because I should have been overridden.`);
2627
- }
2628
- /**
2629
- * @async
2630
- * @description Executes the command.
2631
- * @summary This method handles the overall execution flow of the command, including parsing arguments,
2632
- * setting up logging, checking for version or help requests, and running the command.
2633
- * @returns {Promise<R | string | void>} A promise that resolves with the command's result.
2634
- *
2635
- * @mermaid
2636
- * sequenceDiagram
2637
- * participant Command
2638
- * participant UserInput
2639
- * participant Logging
2640
- * participant getPackageVersion
2641
- * participant printBanner
2642
- * Command->>UserInput: parseArgs(inputs)
2643
- * UserInput-->>Command: Return ParseArgsResult
2644
- * Command->>Command: Process options
2645
- * Command->>Logging: setConfig(options)
2646
- * alt version requested
2647
- * Command->>getPackageVersion: Call
2648
- * getPackageVersion-->>Command: Return version
2649
- * else help requested
2650
- * Command->>Command: help(args)
2651
- * else banner requested
2652
- * Command->>printBanner: Call
2653
- * end
2654
- * Command->>Command: run(args)
2655
- * alt error occurs
2656
- * Command->>Command: Log error
2657
- * end
2658
- * Command-->>Command: Return result
2659
- */
2660
- async execute() {
2661
- const args = UserInput.parseArgs(this.inputs);
2662
- const env = LoggedEnvironment.accumulate(DefaultCommandValues).accumulate(args.values);
2663
- const { version, help, banner } = env;
2664
- if (version) {
2665
- return getPackageVersion();
2666
- }
2667
- if (help) {
2668
- return this.help(args);
2669
- }
2670
- if (banner)
2671
- printBanner(this.log.for(printBanner, {
2672
- timestamp: false,
2673
- style: false,
2674
- context: false,
2675
- logLevel: false,
2676
- }));
2677
- let result;
2678
- try {
2679
- result = await this.run(env);
2680
- }
2681
- catch (e) {
2682
- this.log.error(`Error while running provided cli function: ${e}`);
2683
- throw e;
2684
- }
2685
- return result;
2686
- }
2687
- }
2688
-
2689
- /* istanbul ignore file */
2690
- /**
2691
- * @description A simple HTTP client for downloading files.
2692
- * @summary This class provides functionality to download files from HTTPS URLs.
2693
- * It uses Node.js built-in https module to make requests.
2694
- *
2695
- * @class HttpClient
2696
- */
2697
- class HttpClient {
2698
- static { this.log = Logging.for(HttpClient); }
2699
- /**
2700
- * @description Downloads a file from a given URL.
2701
- * @summary This method sends a GET request to the specified URL and returns the response body as a string.
2702
- * It handles different scenarios such as non-200 status codes and network errors.
2703
- *
2704
- * @param url - The URL of the file to download.
2705
- * @return A promise that resolves with the file content as a string.
2706
- *
2707
- * @mermaid
2708
- * sequenceDiagram
2709
- * participant Client
2710
- * participant HttpClient
2711
- * participant HTTPS
2712
- * participant Server
2713
- * Client->>HttpClient: downloadFile(url)
2714
- * HttpClient->>HTTPS: get(url)
2715
- * HTTPS->>Server: GET request
2716
- * Server-->>HTTPS: Response
2717
- * HTTPS-->>HttpClient: Response object
2718
- * alt Status code is 200
2719
- * loop For each data chunk
2720
- * HTTPS->>HttpClient: 'data' event
2721
- * HttpClient->>HttpClient: Accumulate data
2722
- * end
2723
- * HTTPS->>HttpClient: 'end' event
2724
- * HttpClient-->>Client: Resolve with data
2725
- * else Status code is not 200
2726
- * HttpClient-->>Client: Reject with error
2727
- * end
2728
- */
2729
- static async downloadFile(url) {
2730
- return new Promise((resolve, reject) => {
2731
- function request(url) {
2732
- url = encodeURI(url);
2733
- https.get(url, (res) => {
2734
- if (res.statusCode === 301 || res.statusCode === 307)
2735
- return request(res.headers.location);
2736
- if (res.statusCode !== 200) {
2737
- HttpClient.log.error(`Failed to fetch ${url} (status: ${res.statusCode})`);
2738
- return reject(new Error(`Failed to fetch ${url}`));
2739
- }
2740
- let data = "";
2741
- res.on("data", (chunk) => {
2742
- data += chunk;
2743
- });
2744
- res.on("error", (error) => {
2745
- reject(error);
2746
- });
2747
- res.on("end", () => {
2748
- resolve(data);
2749
- });
2750
- });
2751
- }
2752
- request(url);
2753
- });
2754
- }
2755
- }
2756
-
2757
- const VERSION_STRING = "0.3.12";
2758
- const PACKAGE_STRING = "@decaf-ts/utils";
2759
- var Modes;
2760
- (function (Modes) {
2761
- Modes["CJS"] = "commonjs";
2762
- Modes["ESM"] = "es2022";
2763
- })(Modes || (Modes = {}));
2764
- var BuildMode;
2765
- (function (BuildMode) {
2766
- BuildMode["BUILD"] = "build";
2767
- BuildMode["BUNDLE"] = "bundle";
2768
- BuildMode["ALL"] = "all";
2769
- })(BuildMode || (BuildMode = {}));
2770
- var SEPARATORS;
2771
- (function (SEPARATORS) {
2772
- SEPARATORS["DOT"] = ".";
2773
- })(SEPARATORS || (SEPARATORS = {}));
2774
- const binSourceLocation = "/src/bin";
2775
- const options$2 = {
2776
- prod: {
2777
- type: "boolean",
2778
- default: false,
2779
- },
2780
- dev: {
2781
- type: "boolean",
2782
- default: false,
2783
- },
2784
- buildMode: {
2785
- type: "string",
2786
- default: BuildMode.ALL,
2787
- },
2788
- docs: {
2789
- type: "boolean",
2790
- default: false,
2791
- },
2792
- commands: {
2793
- type: "boolean",
2794
- default: false,
2795
- },
2796
- banner: {
2797
- type: "boolean",
2798
- default: false,
2799
- },
2800
- };
2801
- const cjs2Transformer = (ext = ".cjs") => {
2802
- const log = BuildScripts.log.for(cjs2Transformer);
2803
- const resolutionCache = new Map();
2804
- return (transformationContext) => {
2805
- return (sourceFile) => {
2806
- const sourceDir = path.dirname(sourceFile.fileName);
2807
- function resolvePath(importPath) {
2808
- const cacheKey = JSON.stringify([sourceDir, importPath]);
2809
- const cachedValue = resolutionCache.get(cacheKey);
2810
- if (cachedValue != null)
2811
- return cachedValue;
2812
- let resolvedPath = importPath;
2813
- try {
2814
- resolvedPath = path.resolve(sourceDir, resolvedPath + ".ts");
2815
- }
2816
- catch (error) {
2817
- throw new Error(`Failed to resolve path ${importPath}: ${error}`);
2818
- }
2819
- let stat;
2820
- try {
2821
- stat = fs.statSync(resolvedPath);
2822
- }
2823
- catch (e) {
2824
- try {
2825
- log.verbose(`Testing existence of path ${resolvedPath} as a folder defaulting to index file`);
2826
- stat = fs.statSync(resolvedPath.replace(/\.ts$/gm, ""));
2827
- }
2828
- catch (e2) {
2829
- throw new Error(`Failed to resolve path ${importPath}: ${e}, ${e2}`);
2830
- }
2831
- }
2832
- if (stat.isDirectory())
2833
- resolvedPath = resolvedPath.replace(/\.ts$/gm, "/index.ts");
2834
- if (path.isAbsolute(resolvedPath)) {
2835
- const extension = (/\.tsx?$/.exec(path.basename(resolvedPath)) || [])[0] || void 0;
2836
- resolvedPath =
2837
- "./" +
2838
- path.relative(sourceDir, path.resolve(path.dirname(resolvedPath), path.basename(resolvedPath, extension) + ext));
2839
- }
2840
- resolutionCache.set(cacheKey, resolvedPath);
2841
- return resolvedPath;
2842
- }
2843
- function visitNode(node) {
2844
- if (shouldMutateModuleSpecifier(node)) {
2845
- if (ts.isImportDeclaration(node)) {
2846
- const resolvedPath = resolvePath(node.moduleSpecifier.text);
2847
- const newModuleSpecifier = transformationContext.factory.createStringLiteral(resolvedPath);
2848
- return transformationContext.factory.updateImportDeclaration(node, node.modifiers, node.importClause, newModuleSpecifier, undefined);
2849
- }
2850
- else if (ts.isExportDeclaration(node)) {
2851
- const resolvedPath = resolvePath(node.moduleSpecifier.text);
2852
- const newModuleSpecifier = transformationContext.factory.createStringLiteral(resolvedPath);
2853
- return transformationContext.factory.updateExportDeclaration(node, node.modifiers, node.isTypeOnly, node.exportClause, newModuleSpecifier, undefined);
2854
- }
2855
- }
2856
- return ts.visitEachChild(node, visitNode, transformationContext);
2857
- }
2858
- function shouldMutateModuleSpecifier(node) {
2859
- if (!ts.isImportDeclaration(node) && !ts.isExportDeclaration(node))
2860
- return false;
2861
- if (node.moduleSpecifier === undefined)
2862
- return false;
2863
- // only when module specifier is valid
2864
- if (!ts.isStringLiteral(node.moduleSpecifier))
2865
- return false;
2866
- // only when path is relative
2867
- if (!node.moduleSpecifier.text.startsWith("./") &&
2868
- !node.moduleSpecifier.text.startsWith("../"))
2869
- return false;
2870
- // only when module specifier has no extension
2871
- if (path.extname(node.moduleSpecifier.text) !== "")
2872
- return false;
2873
- return true;
2874
- }
2875
- return ts.visitNode(sourceFile, visitNode);
2876
- };
2877
- };
2878
- };
2879
- class BuildScripts extends Command {
2880
- constructor() {
2881
- super("BuildScripts", Object.assign({}, DefaultCommandOptions, options$2));
2882
- this.replacements = {};
2883
- const pkg = getPackage();
2884
- const { name, version } = pkg;
2885
- this.pkgName = name.includes("@") ? name.split("/")[1] : name;
2886
- this.pkgVersion = version;
2887
- this.replacements[VERSION_STRING] = this.pkgVersion;
2888
- this.replacements[PACKAGE_STRING] = name;
2889
- }
2890
- patchFiles(p) {
2891
- const log = this.log.for(this.patchFiles);
2892
- const { name, version } = getPackage();
2893
- log.info(`Patching ${name} ${version} module in ${p}...`);
2894
- const stat = fs.statSync(p);
2895
- if (stat.isDirectory())
2896
- fs.readdirSync(p, { withFileTypes: true, recursive: true })
2897
- .filter((p) => p.isFile())
2898
- .forEach((file) => patchFile(path.join(file.parentPath, file.name), this.replacements));
2899
- log.verbose(`Module ${name} ${version} patched in ${p}...`);
2900
- }
2901
- reportDiagnostics(diagnostics) {
2902
- diagnostics.forEach((diagnostic) => {
2903
- let message = "Error";
2904
- if (diagnostic.file && diagnostic.start) {
2905
- const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
2906
- message += ` ${diagnostic.file.fileName} (${line + 1},${character + 1})`;
2907
- }
2908
- message +=
2909
- ": " + ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
2910
- console.log(message);
2911
- });
2912
- }
2913
- readConfigFile(configFileName) {
2914
- // Read config file
2915
- const configFileText = fs.readFileSync(configFileName).toString();
2916
- // Parse JSON, after removing comments. Just fancier JSON.parse
2917
- const result = ts.parseConfigFileTextToJson(configFileName, configFileText);
2918
- const configObject = result.config;
2919
- if (!configObject) {
2920
- this.reportDiagnostics([result.error]);
2921
- throw new Error("Failed to parse tsconfig.json");
2922
- }
2923
- // Extract config infromation
2924
- const configParseResult = ts.parseJsonConfigFileContent(configObject, ts.sys, path.dirname(configFileName));
2925
- if (configParseResult.errors.length > 0) {
2926
- this.reportDiagnostics(configParseResult.errors);
2927
- throw new Error("Failed to parse tsconfig.json");
2928
- }
2929
- return configParseResult;
2930
- }
2931
- async buildTs(isDev, mode, bundle = false) {
2932
- const log = this.log.for(this.buildTs);
2933
- log.info(`Building ${this.pkgName} ${this.pkgVersion} module (${mode}) in ${isDev ? "dev" : "prod"} mode...`);
2934
- let tsConfig;
2935
- try {
2936
- tsConfig = this.readConfigFile("./tsconfig.json");
2937
- }
2938
- catch (e) {
2939
- throw new Error(`Failed to parse tsconfig.json: ${e}`);
2940
- }
2941
- if (bundle) {
2942
- tsConfig.options.module = ModuleKind.AMD;
2943
- tsConfig.options.outDir = "dist";
2944
- tsConfig.options.isolatedModules = false;
2945
- tsConfig.options.outFile = this.pkgName;
2946
- }
2947
- else {
2948
- tsConfig.options.outDir = `lib${mode === Modes.ESM ? "/esm" : ""}`;
2949
- tsConfig.options.module =
2950
- mode === Modes.ESM ? ModuleKind.ES2022 : ModuleKind.CommonJS;
2951
- }
2952
- if (isDev) {
2953
- tsConfig.options.inlineSourceMap = true;
2954
- tsConfig.options.sourceMap = false;
2955
- }
2956
- else {
2957
- tsConfig.options.sourceMap = false;
2958
- }
2959
- const program = ts.createProgram(tsConfig.fileNames, tsConfig.options);
2960
- const transformations = {};
2961
- if (mode === Modes.CJS) {
2962
- transformations.before = [cjs2Transformer(".cjs")];
2963
- }
2964
- else if (mode === Modes.ESM) {
2965
- transformations.before = [cjs2Transformer(".js")];
2966
- }
2967
- const emitResult = program.emit(undefined, undefined, undefined, undefined, transformations);
2968
- const allDiagnostics = ts
2969
- .getPreEmitDiagnostics(program)
2970
- .concat(emitResult.diagnostics);
2971
- allDiagnostics.forEach((diagnostic) => {
2972
- if (diagnostic.file) {
2973
- const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
2974
- const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
2975
- log.info(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
2976
- }
2977
- else {
2978
- log.info(ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"));
2979
- }
2980
- });
2981
- if (emitResult.emitSkipped) {
2982
- throw new Error("Build failed");
2983
- }
2984
- }
2985
- async build(isDev, mode, bundle = false) {
2986
- const log = this.log.for(this.build);
2987
- await this.buildTs(isDev, mode, bundle);
2988
- log.verbose(`Module ${this.pkgName} ${this.pkgVersion} (${mode}) built in ${isDev ? "dev" : "prod"} mode...`);
2989
- if (mode === Modes.CJS && !bundle) {
2990
- const files = getAllFiles("lib", (file) => file.endsWith(".js") && !file.includes("/esm/"));
2991
- for (const file of files) {
2992
- log.verbose(`Patching ${file}'s cjs imports...`);
2993
- const f = file.replace(".js", ".cjs");
2994
- await renameFile(file, f);
2995
- }
2996
- }
2997
- }
2998
- copyAssets(mode) {
2999
- const log = this.log.for(this.copyAssets);
3000
- let hasAssets = false;
3001
- try {
3002
- hasAssets = fs.statSync("./src/assets").isDirectory();
3003
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
3004
- }
3005
- catch (e) {
3006
- return log.verbose(`No assets found in ./src/assets to copy`);
3007
- }
3008
- if (hasAssets)
3009
- copyFile("./src/assets", `./${mode === Modes.CJS ? "lib" : "dist"}/assets`);
3010
- }
3011
- async buildCommands() {
3012
- const commands = fs.readdirSync(path.join(process.cwd() + binSourceLocation)).map((cmd) => cmd.split(SEPARATORS.DOT)[0]);
3013
- for (const cmd of commands) {
3014
- if (!cmd.endsWith(".ts"))
3015
- continue;
3016
- await this.bundle(Modes.CJS, true, true, `${binSourceLocation}/${cmd}.ts`, cmd);
3017
- let data = readFile(`bin/${cmd}.cjs`);
3018
- data = "#!/usr/bin/env node\n" + data;
3019
- writeFile(`bin/${cmd}.cjs`, data);
3020
- fs.chmodSync(`bin/${cmd}.cjs`, "755");
3021
- }
3022
- }
3023
- async bundle(mode, isDev, isLib, entryFile = "src/index.ts", nameOverride = this.pkgName, externals, include = [
3024
- "prompts",
3025
- "styled-string-builder",
3026
- "typed-object-accumulator",
3027
- "@decaf-ts/logging",
3028
- ]) {
3029
- const isEsm = mode === Modes.ESM;
3030
- const pkgName = this.pkgName;
3031
- const ext = Array.from(new Set([
3032
- ...[
3033
- "fs",
3034
- "path",
3035
- "process",
3036
- "rollup",
3037
- "@rollup/plugin-typescript",
3038
- "@rollup/plugin-json",
3039
- "@rollup/plugin-commonjs",
3040
- "@rollup/plugin-node-resolve",
3041
- "child_process",
3042
- "tslib",
3043
- "util",
3044
- "https",
3045
- ],
3046
- ...(externals || []),
3047
- ]));
3048
- const plugins = [
3049
- typescript({
3050
- compilerOptions: {
3051
- module: "esnext",
3052
- declaration: false,
3053
- outDir: isLib ? "bin" : "dist",
3054
- },
3055
- include: ["src/**/*.ts"],
3056
- exclude: ["node_modules", "**/*.spec.ts"],
3057
- tsconfig: "./tsconfig.json",
3058
- }),
3059
- json(),
3060
- ];
3061
- if (isLib) {
3062
- plugins.push(commonjs({
3063
- include: [],
3064
- exclude: externals,
3065
- }), nodeResolve({
3066
- resolveOnly: include,
3067
- }));
3068
- }
3069
- const input = {
3070
- input: entryFile,
3071
- plugins: plugins,
3072
- external: ext,
3073
- };
3074
- const outputs = [
3075
- {
3076
- file: `${isLib ? "bin/" : "dist/"}${nameOverride ? nameOverride : `.bundle.${!isDev ? "min" : ""}`}${isEsm ? ".esm" : ""}.cjs`,
3077
- format: isLib ? "cjs" : isEsm ? "esm" : "umd",
3078
- name: pkgName,
3079
- esModule: isEsm,
3080
- sourcemap: isDev ? "inline" : false,
3081
- globals: {},
3082
- exports: "auto",
3083
- },
3084
- ];
3085
- try {
3086
- const bundle = await rollup(input);
3087
- console.log(bundle.watchFiles);
3088
- async function generateOutputs(bundle) {
3089
- for (const outputOptions of outputs) {
3090
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
3091
- const { output } = await bundle.write(outputOptions);
3092
- }
3093
- }
3094
- await generateOutputs(bundle);
3095
- }
3096
- catch (e) {
3097
- throw new Error(`Failed to bundle: ${e}`);
3098
- }
3099
- }
3100
- async buildByEnv(isDev, mode = BuildMode.ALL) {
3101
- try {
3102
- deletePath("lib");
3103
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
3104
- }
3105
- catch (e) {
3106
- // do nothing
3107
- }
3108
- try {
3109
- deletePath("dist");
3110
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
3111
- }
3112
- catch (e) {
3113
- // do nothing
3114
- }
3115
- fs.mkdirSync("lib");
3116
- fs.mkdirSync("dist");
3117
- if ([BuildMode.ALL, BuildMode.BUILD].includes(mode)) {
3118
- await this.build(isDev, Modes.ESM);
3119
- await this.build(isDev, Modes.CJS);
3120
- this.patchFiles("lib");
3121
- }
3122
- if ([BuildMode.ALL, BuildMode.BUNDLE].includes(mode)) {
3123
- await this.bundle(Modes.ESM, true, false);
3124
- await this.bundle(Modes.CJS, true, false);
3125
- this.patchFiles("dist");
3126
- }
3127
- this.copyAssets(Modes.CJS);
3128
- this.copyAssets(Modes.ESM);
3129
- }
3130
- async buildDev(mode = BuildMode.ALL) {
3131
- return this.buildByEnv(true, mode);
3132
- }
3133
- async buildProd(mode = BuildMode.ALL) {
3134
- return this.buildByEnv(false, mode);
3135
- }
3136
- async buildDocs() {
3137
- await runCommand(`npm install better-docs taffydb`).promise;
3138
- await runCommand(`npx markdown-include ./workdocs/readme-md.json`).promise;
3139
- await runCommand(`npx jsdoc -c ./workdocs/jsdocs.json -t ./node_modules/better-docs`).promise;
3140
- await runCommand(`npm remove better-docs taffydb`).promise;
3141
- [
3142
- {
3143
- src: "workdocs/assets",
3144
- dest: "./docs/workdocs/assets",
3145
- },
3146
- {
3147
- src: "workdocs/reports/coverage",
3148
- dest: "./docs/workdocs/reports/coverage",
3149
- },
3150
- {
3151
- src: "workdocs/reports/html",
3152
- dest: "./docs/workdocs/reports/html",
3153
- },
3154
- {
3155
- src: "workdocs/resources",
3156
- dest: "./docs/workdocs/resources",
3157
- },
3158
- {
3159
- src: "LICENSE.md",
3160
- dest: "./docs/LICENSE.md",
3161
- },
3162
- ].forEach((f) => {
3163
- const { src, dest } = f;
3164
- copyFile(src, dest);
3165
- });
3166
- }
3167
- async run(answers) {
3168
- const { dev, prod, docs, commands, buildMode } = answers;
3169
- if (commands) {
3170
- await this.buildCommands();
3171
- }
3172
- if (dev) {
3173
- return await this.buildDev(buildMode);
3174
- }
3175
- if (prod) {
3176
- return await this.buildProd(buildMode);
3177
- }
3178
- if (docs) {
3179
- return await this.buildDocs();
3180
- }
3181
- }
3182
- }
3183
-
3184
- /* istanbul ignore file */
3185
- const options$1 = {
3186
- ci: {
3187
- type: "boolean",
3188
- default: true,
3189
- },
3190
- message: {
3191
- type: "string",
3192
- short: "m",
3193
- },
3194
- tag: {
3195
- type: "string",
3196
- short: "t",
3197
- default: undefined,
3198
- },
3199
- };
3200
- /**
3201
- * @class ReleaseScript
3202
- * @extends {Command}
3203
- * @cavegory scripts
3204
- * @description A command-line script for managing releases and version updates.
3205
- * @summary This script automates the process of creating and pushing new releases. It handles version updates,
3206
- * commit messages, and optionally publishes to NPM. The script supports semantic versioning and can work in both CI and non-CI environments.
3207
- *
3208
- * @param {Object} options - Configuration options for the script
3209
- * @param {boolean} options.ci - Whether the script is running in a CI environment (default: true)
3210
- * @param {string} options.message - The release message (short: 'm')
3211
- * @param {string} options.tag - The version tag to use (short: 't', default: undefined)
3212
- */
3213
- class ReleaseScript extends Command {
3214
- constructor() {
3215
- super("ReleaseScript", options$1);
3216
- }
3217
- /**
3218
- * @description Prepares the version for the release.
3219
- * @summary This method validates the provided tag or prompts the user for a new one if not provided or invalid.
3220
- * It also displays the latest git tags for reference.
3221
- * @param {string} tag - The version tag to prepare
3222
- * @returns {Promise<string>} The prepared version tag
3223
- *
3224
- * @mermaid
3225
- * sequenceDiagram
3226
- * participant R as ReleaseScript
3227
- * participant T as TestVersion
3228
- * participant U as UserInput
3229
- * participant G as Git
3230
- * R->>T: testVersion(tag)
3231
- * alt tag is valid
3232
- * T-->>R: return tag
3233
- * else tag is invalid or not provided
3234
- * R->>G: List latest git tags
3235
- * R->>U: Prompt for new tag
3236
- * U-->>R: return new tag
3237
- * end
3238
- */
3239
- async prepareVersion(tag) {
3240
- const log = this.log.for(this.prepareVersion);
3241
- tag = this.testVersion(tag || "");
3242
- if (!tag) {
3243
- log.verbose("No release message provided. Prompting for one:");
3244
- log.info(`Listing latest git tags:`);
3245
- await runCommand("git tag --sort=-taggerdate | head -n 5").promise;
3246
- return await UserInput.insistForText("tag", "Enter the new tag number (accepts v*.*.*[-...])", (val) => !!val.toString().match(/^v[0-9]+\.[0-9]+.[0-9]+(-[0-9a-zA-Z-]+)?$/));
3247
- }
3248
- return tag;
3249
- }
3250
- /**
3251
- * @description Tests if the provided version is valid.
3252
- * @summary This method checks if the version is a valid semantic version or a predefined update type (PATCH, MINOR, MAJOR).
3253
- * @param {string} version - The version to test
3254
- * @returns {string | undefined} The validated version or undefined if invalid
3255
- */
3256
- testVersion(version) {
3257
- const log = this.log.for(this.testVersion);
3258
- version = version.trim().toLowerCase();
3259
- switch (version) {
3260
- case SemVersion.PATCH:
3261
- case SemVersion.MINOR:
3262
- case SemVersion.MAJOR:
3263
- log.verbose(`Using provided SemVer update: ${version}`, 1);
3264
- return version;
3265
- default:
3266
- log.verbose(`Testing provided version for SemVer compatibility: ${version}`, 1);
3267
- if (!new RegExp(SemVersionRegex).test(version)) {
3268
- log.debug(`Invalid version number: ${version}`);
3269
- return undefined;
3270
- }
3271
- log.verbose(`version approved: ${version}`, 1);
3272
- return version;
3273
- }
3274
- }
3275
- /**
3276
- * @description Prepares the release message.
3277
- * @summary This method either returns the provided message or prompts the user for a new one if not provided.
3278
- * @param {string} [message] - The release message
3279
- * @returns {Promise<string>} The prepared release message
3280
- */
3281
- async prepareMessage(message) {
3282
- const log = this.log.for(this.prepareMessage);
3283
- if (!message) {
3284
- log.verbose("No release message provided. Prompting for one");
3285
- return await UserInput.insistForText("message", "What should be the release message/ticket?", (val) => !!val && val.toString().length > 5);
3286
- }
3287
- return message;
3288
- }
3289
- /**
3290
- * @description Runs the release script.
3291
- * @summary This method orchestrates the entire release process, including version preparation, message creation,
3292
- * git operations, and npm publishing (if not in CI environment).
3293
- * @param {ParseArgsResult} args - The parsed command-line arguments
3294
- * @returns {Promise<void>}
3295
- *
3296
- * @mermaid
3297
- * sequenceDiagram
3298
- * participant R as ReleaseScript
3299
- * participant V as PrepareVersion
3300
- * participant M as PrepareMessage
3301
- * participant N as NPM
3302
- * participant G as Git
3303
- * participant U as UserInput
3304
- * R->>V: prepareVersion(tag)
3305
- * R->>M: prepareMessage(message)
3306
- * R->>N: Run prepare-release script
3307
- * R->>G: Check git status
3308
- * alt changes exist
3309
- * R->>U: Ask for confirmation
3310
- * U-->>R: Confirm
3311
- * R->>G: Add and commit changes
3312
- * end
3313
- * R->>N: Update npm version
3314
- * R->>G: Push changes and tags
3315
- * alt not CI environment
3316
- * R->>N: Publish to npm
3317
- * end
3318
- */
3319
- async run(args) {
3320
- let result;
3321
- const { ci } = args;
3322
- let { tag, message } = args;
3323
- tag = await this.prepareVersion(tag);
3324
- message = await this.prepareMessage(message);
3325
- result = await runCommand(`npm run prepare-release -- ${tag} ${message}`, {
3326
- cwd: process.cwd(),
3327
- }).promise;
3328
- result = await runCommand("git status --porcelain").promise;
3329
- await result;
3330
- if (result.logs.length &&
3331
- (await UserInput.askConfirmation("git-changes", "Do you want to push the changes to the remote repository?", true))) {
3332
- await runCommand("git add .").promise;
3333
- await runCommand(`git commit -m "${tag} - ${message} - after release preparation${ci ? "" : NoCIFLag}"`).promise;
3334
- }
3335
- await runCommand(`npm version "${tag}" -m "${message}${ci ? "" : NoCIFLag}"`).promise;
3336
- await runCommand("git push --follow-tags").promise;
3337
- if (!ci) {
3338
- await runCommand("NPM_TOKEN=$(cat .npmtoken) npm publish --access public")
3339
- .promise;
3340
- }
3341
- }
3342
- }
3343
-
3344
- /* istanbul ignore file */
3345
- const baseUrl = "https://raw.githubusercontent.com/decaf-ts/ts-workspace/master";
3346
- const options = {
3347
- templates: [
3348
- ".github/ISSUE_TEMPLATE/bug_report.md",
3349
- ".github/ISSUE_TEMPLATE/feature_request.md",
3350
- ".github/FUNDING.yml",
3351
- ],
3352
- workflows: [
3353
- ".github/workflows/codeql-analysis.yml",
3354
- ".github/workflows/jest-coverage.yaml",
3355
- ".github/workflows/nodejs-build-prod.yaml",
3356
- ".github/workflows/pages.yaml",
3357
- ".github/workflows/publish-on-release.yaml",
3358
- ".github/workflows/release-on-tag.yaml",
3359
- ".github/workflows/snyk-analysis.yaml",
3360
- ],
3361
- ide: [
3362
- ".idea/runConfigurations/All Tests.run.xml",
3363
- ".idea/runConfigurations/build.run.xml",
3364
- ".idea/runConfigurations/build_prod.run.xml",
3365
- ".idea/runConfigurations/coverage.run.xml",
3366
- ".idea/runConfigurations/docs.run.xml",
3367
- ".idea/runConfigurations/drawings.run.xml",
3368
- ".idea/runConfigurations/flash-forward.run.xml",
3369
- ".idea/runConfigurations/Integration_Tests.run.xml",
3370
- ".idea/runConfigurations/Bundling_Tests.run.xml",
3371
- ".idea/runConfigurations/lint-fix.run.xml",
3372
- ".idea/runConfigurations/release.run.xml",
3373
- ".idea/runConfigurations/test_circular.run.xml",
3374
- ".idea/runConfigurations/uml.run.xml",
3375
- ".idea/runConfigurations/Unit Tests.run.xml",
3376
- ".idea/runConfigurations/update-scripts.run.xml",
3377
- ],
3378
- docs: [
3379
- "workdocs/tutorials/Contributing.md",
3380
- "workdocs/tutorials/Documentation.md",
3381
- "workdocs/tutorials/For Developers.md",
3382
- "workdocs/2-Badges.md",
3383
- "workdocs/jsdocs.json",
3384
- "workdocs/readme-md.json",
3385
- ],
3386
- styles: [".prettierrc", "eslint.config.js"],
3387
- scripts: [
3388
- "bin/update-scripts.cjs",
3389
- "bin/tag-release.cjs",
3390
- "bin/build-scripts.cjs",
3391
- ],
3392
- tests: ["jest.config.ts", "workdocs/reports/jest.coverage.config.ts"],
3393
- typescript: ["tsconfig.json"],
3394
- docker: ["Dockerfile"],
3395
- automation: [
3396
- "workdocs/confluence/Continuous Integration-Deployment/GitHub.md",
3397
- "workdocs/confluence/Continuous Integration-Deployment/Jira.md",
3398
- "workdocs/confluence/Continuous Integration-Deployment/Teams.md",
3399
- ],
3400
- };
3401
- const argzz = {
3402
- // init attributes
3403
- boot: {
3404
- type: "boolean",
3405
- },
3406
- org: {
3407
- type: "string",
3408
- short: "o",
3409
- },
3410
- name: {
3411
- type: "string",
3412
- short: "n",
3413
- default: undefined,
3414
- },
3415
- author: {
3416
- type: "string",
3417
- short: "a",
3418
- default: undefined,
3419
- },
3420
- // update attributes
3421
- all: {
3422
- type: "boolean",
3423
- },
3424
- license: {
3425
- type: "string",
3426
- message: "Pick the license",
3427
- },
3428
- scripts: {
3429
- type: "boolean",
3430
- },
3431
- styles: {
3432
- type: "boolean",
3433
- },
3434
- docs: {
3435
- type: "boolean",
3436
- },
3437
- ide: {
3438
- type: "boolean",
3439
- },
3440
- workflows: {
3441
- type: "boolean",
3442
- },
3443
- templates: {
3444
- type: "boolean",
3445
- },
3446
- typescript: {
3447
- type: "boolean",
3448
- },
3449
- docker: {
3450
- type: "boolean",
3451
- },
3452
- pkg: {
3453
- type: "boolean",
3454
- },
3455
- dependencies: {
3456
- type: "boolean",
3457
- },
3458
- tests: {
3459
- type: "boolean",
3460
- },
3461
- automation: {
3462
- type: "boolean",
3463
- },
3464
- };
3465
- /**
3466
- * @class TemplateSync
3467
- * @extends {Command}
3468
- * @category scripts
3469
- * @description A command-line tool for synchronizing project templates and configurations.
3470
- * @summary This class provides functionality to download and update various project files and configurations from a remote repository.
3471
- * It supports updating licenses, IDE configurations, scripts, styles, documentation, workflows, and templates.
3472
- *
3473
- * @param {CommandOptions} args - The command options for TemplateSync
3474
- */
3475
- class TemplateSync extends Command {
3476
- constructor() {
3477
- super("TemplateSync", argzz);
3478
- this.replacements = {};
3479
- /**
3480
- * @description Downloads style configuration files.
3481
- * @returns {Promise<void>}
3482
- */
3483
- this.getStyles = () => this.downloadOption("styles");
3484
- /**
3485
- * @description Downloads template files.
3486
- * @returns {Promise<void>}
3487
- */
3488
- this.getTemplates = () => this.downloadOption("templates");
3489
- /**
3490
- * @description Downloads workflow configuration files.
3491
- * @returns {Promise<void>}
3492
- */
3493
- this.getWorkflows = () => this.downloadOption("workflows");
3494
- /**
3495
- * @description Downloads documentation files.
3496
- * @returns {Promise<void>}
3497
- */
3498
- this.getDocs = () => this.downloadOption("docs");
3499
- /**
3500
- * @description Downloads typescript config files.
3501
- * @returns {Promise<void>}
3502
- */
3503
- this.getTypescript = () => this.downloadOption("typescript");
3504
- /**
3505
- * @description Downloads automation documentation files.
3506
- * @returns {Promise<void>}
3507
- */
3508
- this.getAutomation = () => this.downloadOption("automation");
3509
- /**
3510
- * @description Downloads automation documentation files.
3511
- * @returns {Promise<void>}
3512
- */
3513
- this.getTests = () => this.downloadOption("tests");
3514
- /**
3515
- * @description Downloads docker image files.
3516
- * @returns {Promise<void>}
3517
- */
3518
- this.getDocker = () => this.downloadOption("docker");
3519
- }
3520
- loadValuesFromPackage() {
3521
- const p = process.cwd();
3522
- const author = getPackage(p, "author");
3523
- const scopedName = getPackage(p, "name");
3524
- let name = scopedName;
3525
- let org;
3526
- if (name.startsWith("@")) {
3527
- const split = name.split("/");
3528
- name = split[1];
3529
- org = split[0].replace("@", "");
3530
- }
3531
- ["Tiago Venceslau", "TiagoVenceslau", "${author}"].forEach((el) => (this.replacements[el] = author));
3532
- ["TS-Workspace", "ts-workspace", "${name}"].forEach((el) => (this.replacements[el] = name));
3533
- ["decaf-ts", "${org}"].forEach((el) => (this.replacements[el] = org || '""'));
3534
- this.replacements["${org_or_owner}"] = org || name;
3535
- }
3536
- /**
3537
- * @description Downloads files for a specific option category.
3538
- * @summary This method downloads all files associated with a given option key from the remote repository.
3539
- * @param {string} key - The key representing the option category to download
3540
- * @returns {Promise<void>}
3541
- * @throws {Error} If the specified option key is not found
3542
- */
3543
- async downloadOption(key) {
3544
- if (!(key in options)) {
3545
- throw new Error(`Option "${key}" not found in options`);
3546
- }
3547
- const files = options[key];
3548
- for (const file of files) {
3549
- this.log.info(`Downloading ${file}`);
3550
- let data = await HttpClient.downloadFile(`${baseUrl}/${file}`);
3551
- data = patchString(data, this.replacements);
3552
- writeFile(path.join(process.cwd(), file), data);
3553
- }
3554
- }
3555
- /**
3556
- * @description Downloads and sets up the specified license.
3557
- * @summary This method downloads the chosen license file, saves it to the project, and updates the package.json license field.
3558
- * @param {"MIT" | "GPL" | "Apache" | "LGPL" | "AGPL"} license - The license to download and set up
3559
- * @returns {Promise<void>}
3560
- */
3561
- async getLicense(license) {
3562
- this.log.info(`Downloading ${license} license`);
3563
- const url = `${baseUrl}/workdocs/licenses/${license}.md`;
3564
- let data = await HttpClient.downloadFile(url);
3565
- data = patchString(data, this.replacements);
3566
- writeFile(path.join(process.cwd(), "LICENSE.md"), data);
3567
- setPackageAttribute("license", license);
3568
- }
3569
- /**
3570
- * @description Downloads IDE configuration files.
3571
- * @returns {Promise<void>}
3572
- */
3573
- async getIde() {
3574
- fs.mkdirSync(path.join(process.cwd(), ".idea", "runConfigurations"), {
3575
- recursive: true,
3576
- });
3577
- await this.downloadOption("ide");
3578
- }
3579
- /**
3580
- * @description Update npm scripts
3581
- * @returns {Promise<void>}
3582
- */
3583
- async getScripts() {
3584
- await this.downloadOption("scripts");
3585
- this.log.info("please re-run the command");
3586
- process.exit(0);
3587
- }
3588
- async initPackage(pkgName, author, license) {
3589
- try {
3590
- const pkg = getPackage();
3591
- delete pkg[SetupScriptKey];
3592
- pkg.name = pkgName;
3593
- pkg.version = "0.0.1";
3594
- pkg.author = author;
3595
- pkg.license = license;
3596
- fs.writeFileSync("package.json", JSON.stringify(pkg, null, 2));
3597
- }
3598
- catch (e) {
3599
- throw new Error(`Error fixing package.json: ${e}`);
3600
- }
3601
- }
3602
- async updatePackageScrips() {
3603
- try {
3604
- const originalPkg = JSON.parse(await HttpClient.downloadFile(`${baseUrl}/package.json`));
3605
- const { scripts } = originalPkg;
3606
- const pkg = getPackage();
3607
- Object.keys(pkg.scripts).forEach((key) => {
3608
- if (key in scripts) {
3609
- const replaced = patchString(scripts[key], this.replacements);
3610
- if (replaced !== scripts[key]) {
3611
- pkg.scripts[key] = replaced;
3612
- }
3613
- }
3614
- });
3615
- pkg["exports"]["require"] = originalPkg["exports"]["require"];
3616
- pkg["exports"]["import"] = originalPkg["exports"]["import"];
3617
- pkg["types"] = originalPkg["types"];
3618
- fs.writeFileSync("package.json", JSON.stringify(pkg, null, 2));
3619
- }
3620
- catch (e) {
3621
- throw new Error(`Error fixing package.json scripts: ${e}`);
3622
- }
3623
- }
3624
- async createTokenFiles() {
3625
- const log = this.log.for(this.createTokenFiles);
3626
- const gitToken = await UserInput.insistForText("token", "please input your github token", (res) => {
3627
- return !!res.match(/^ghp_[0-9a-zA-Z]{36}$/g);
3628
- });
3629
- Object.values(Tokens).forEach((token) => {
3630
- try {
3631
- let status;
3632
- try {
3633
- status = fs.existsSync(token);
3634
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
3635
- }
3636
- catch (e) {
3637
- log.info(`Token file ${token} not found. Creating a new one...`);
3638
- fs.writeFileSync(token, token === ".token" ? gitToken : "");
3639
- return;
3640
- }
3641
- if (!status) {
3642
- fs.writeFileSync(token, token === ".token" ? gitToken : "");
3643
- }
3644
- }
3645
- catch (e) {
3646
- throw new Error(`Error creating token file ${token}: ${e}`);
3647
- }
3648
- });
3649
- }
3650
- async getOrg() {
3651
- const org = await UserInput.askText("Organization", "Enter the organization name (will be used to scope your npm project. leave blank to create a unscoped project):");
3652
- const confirmation = await UserInput.askConfirmation("Confirm organization", "Is this organization correct?", true);
3653
- if (!confirmation)
3654
- return this.getOrg();
3655
- return org;
3656
- }
3657
- async auditFix() {
3658
- return await runCommand("npm audit fix --force").promise;
3659
- }
3660
- patchFiles() {
3661
- const files = [
3662
- ...fs
3663
- .readdirSync(path.join(process.cwd(), "src"), {
3664
- recursive: true,
3665
- withFileTypes: true,
3666
- })
3667
- .filter((entry) => entry.isFile())
3668
- .map((entry) => path.join(entry.parentPath, entry.name)),
3669
- ...fs
3670
- .readdirSync(path.join(process.cwd(), "workdocs"), {
3671
- recursive: true,
3672
- withFileTypes: true,
3673
- })
3674
- .filter((entry) => entry.isFile() && entry.name.endsWith(".md"))
3675
- .map((entry) => path.join(entry.parentPath, entry.name)),
3676
- path.join(process.cwd(), ".gitlab-ci.yml"),
3677
- path.join(process.cwd(), "workdocs", "jsdocs.json"),
3678
- ];
3679
- for (const file of files) {
3680
- patchFile(file, this.replacements);
3681
- }
3682
- }
3683
- async updateDependencies() {
3684
- try {
3685
- const originalPkg = JSON.parse(await HttpClient.downloadFile(`${baseUrl}/package.json`));
3686
- const { devDependencies } = originalPkg;
3687
- const pkg = getPackage();
3688
- Object.keys(pkg.scripts).forEach((key) => {
3689
- if (key in devDependencies) {
3690
- const replaced = devDependencies[key];
3691
- if (replaced !== devDependencies[key]) {
3692
- pkg["devDependencies"] =
3693
- pkg["devDependencies"] || {};
3694
- pkg["devDependencies"][key] = replaced;
3695
- }
3696
- }
3697
- });
3698
- fs.writeFileSync("package.json", JSON.stringify(pkg, null, 2));
3699
- await runCommand("npm install").promise;
3700
- }
3701
- catch (e) {
3702
- throw new Error(`Error fixing package.json dependencies: ${e}`);
3703
- }
3704
- }
3705
- /**
3706
- * @description Runs the template synchronization process.
3707
- * @summary This method orchestrates the downloading of various project components based on the provided arguments.
3708
- * @param {ParseArgsResult} args - The parsed command-line arguments
3709
- * @returns {Promise<void>}
3710
- *
3711
- * @mermaid
3712
- * sequenceDiagram
3713
- * participant T as TemplateSync
3714
- * participant L as getLicense
3715
- * participant I as getIde
3716
- * participant S as getScripts
3717
- * participant St as getStyles
3718
- * participant D as getDocs
3719
- * participant W as getWorkflows
3720
- * participant Te as getTemplates
3721
- * T->>T: Parse arguments
3722
- * alt all flag is true
3723
- * T->>T: Set all component flags to true
3724
- * end
3725
- * alt license is specified
3726
- * T->>L: getLicense(license)
3727
- * end
3728
- * alt ide flag is true
3729
- * T->>I: getIde()
3730
- * end
3731
- * alt scripts flag is true
3732
- * T->>S: getScripts()
3733
- * end
3734
- * alt styles flag is true
3735
- * T->>St: getStyles()
3736
- * end
3737
- * alt docs flag is true
3738
- * T->>D: getDocs()
3739
- * end
3740
- * alt workflows flag is true
3741
- * T->>W: getWorkflows()
3742
- * end
3743
- * alt templates flag is true
3744
- * T->>Te: getTemplates()
3745
- * end
3746
- */
3747
- async run(args) {
3748
- let { license } = args;
3749
- const { boot } = args;
3750
- let { all, scripts, styles, docs, ide, workflows, templates, docker, typescript, dependencies, tests, automation, pkg, } = args;
3751
- if (scripts ||
3752
- styles ||
3753
- docs ||
3754
- ide ||
3755
- workflows ||
3756
- templates ||
3757
- docker ||
3758
- typescript ||
3759
- automation ||
3760
- dependencies ||
3761
- tests ||
3762
- pkg)
3763
- all = false;
3764
- if (boot) {
3765
- const org = await this.getOrg();
3766
- const name = await UserInput.insistForText("Project name", "Enter the project name:", (res) => res.length > 1);
3767
- const author = await UserInput.insistForText("Author", "Enter the author name:", (res) => res.length > 1);
3768
- const pkgName = org ? `@${org}/${name}` : name;
3769
- await this.initPackage(pkgName, author, license);
3770
- await this.createTokenFiles();
3771
- await this.auditFix();
3772
- this.patchFiles();
3773
- }
3774
- if (all) {
3775
- scripts = false;
3776
- styles = true;
3777
- docs = true;
3778
- ide = true;
3779
- workflows = true;
3780
- templates = true;
3781
- docker = true;
3782
- typescript = true;
3783
- pkg = true;
3784
- dependencies = true;
3785
- tests = true;
3786
- automation = false;
3787
- }
3788
- if (typeof scripts === "undefined")
3789
- scripts = await UserInput.askConfirmation("scripts", "Do you want to get scripts?", true);
3790
- if (scripts)
3791
- await this.getScripts();
3792
- this.loadValuesFromPackage();
3793
- if (!all && typeof license === "undefined") {
3794
- const confirmation = await UserInput.askConfirmation("license", "Do you want to set a license?", true);
3795
- if (confirmation)
3796
- license = await UserInput.insistForText("license", "Enter the desired License (MIT|GPL|Apache|LGPL|AGPL):", (val) => !!val && !!val.match(/^(MIT|GPL|Apache|LGPL|AGPL)$/g));
3797
- }
3798
- if (typeof license !== "undefined")
3799
- await this.getLicense(license);
3800
- if (typeof ide === "undefined")
3801
- ide = await UserInput.askConfirmation("ide", "Do you want to get ide configs?", true);
3802
- if (ide)
3803
- await this.getIde();
3804
- if (typeof typescript === "undefined")
3805
- typescript = await UserInput.askConfirmation("typescript", "Do you want to get typescript configs?", true);
3806
- if (typescript)
3807
- await this.getTypescript();
3808
- if (typeof docker === "undefined")
3809
- docker = await UserInput.askConfirmation("docker", "Do you want to get docker configs?", true);
3810
- if (docker)
3811
- await this.getDocker();
3812
- if (typeof automation === "undefined")
3813
- automation = await UserInput.askConfirmation("automation", "Do you want to get automation configs?", true);
3814
- if (automation)
3815
- await this.getAutomation();
3816
- if (typeof styles === "undefined")
3817
- styles = await UserInput.askConfirmation("styles", "Do you want to get styles?", true);
3818
- if (styles)
3819
- await this.getStyles();
3820
- if (typeof docs === "undefined")
3821
- docs = await UserInput.askConfirmation("docs", "Do you want to get docs?", true);
3822
- if (docs)
3823
- await this.getDocs();
3824
- if (typeof workflows === "undefined")
3825
- workflows = await UserInput.askConfirmation("workflows", "Do you want to get workflows?", true);
3826
- if (workflows)
3827
- await this.getWorkflows();
3828
- if (typeof templates === "undefined")
3829
- templates = await UserInput.askConfirmation("templates", "Do you want to get templates?", true);
3830
- if (templates)
3831
- await this.getTemplates();
3832
- if (typeof pkg === "undefined")
3833
- pkg = await UserInput.askConfirmation("pkg", "Do you want to update your package.json scripts?", true);
3834
- if (pkg)
3835
- await this.updatePackageScrips();
3836
- if (typeof tests === "undefined")
3837
- tests = await UserInput.askConfirmation("pkg", "Do you want to update your test configs?", true);
3838
- if (tests)
3839
- await this.getTests();
3840
- if (typeof dependencies === "undefined")
3841
- dependencies = await UserInput.askConfirmation("pkg", "Do you want to update dev dependencies?", true);
3842
- if (dependencies)
3843
- await this.updateDependencies();
3844
- }
3845
- }
3846
-
3847
- /**
3848
- * @description A specialized output writer that uses regular expressions to process output.
3849
- * @summary This class extends StandardOutputWriter to provide regex-based output processing.
3850
- * It allows for pattern matching in the output stream and can trigger specific actions
3851
- * based on matched patterns.
3852
- *
3853
- * @template T - The type of the resolved value, defaulting to string.
3854
- *
3855
- * @param cmd - The command string to be executed.
3856
- * @param lock - A PromiseExecutor to control the asynchronous flow.
3857
- * @param regexp - A string or RegExp to match against the output.
3858
- * @param flags - Optional flags for the RegExp constructor, defaults to "g".
3859
- *
3860
- * @class
3861
- * @example
3862
- * ```typescript
3863
- * import { RegexpOutputWriter } from '@decaf-ts/utils';
3864
- * import { PromiseExecutor } from '@decaf-ts/utils';
3865
- *
3866
- * // Create a promise executor
3867
- * const executor: PromiseExecutor<string, Error> = {
3868
- * resolve: (value) => console.log(`Resolved: ${value}`),
3869
- * reject: (error) => console.error(`Rejected: ${error.message}`)
3870
- * };
3871
- *
3872
- * // Create a regexp output writer that matches version numbers
3873
- * const writer = new RegexpOutputWriter('node --version', executor, /v(\d+\.\d+\.\d+)/);
3874
- *
3875
- * // Use the writer to handle command output
3876
- * writer.data('v14.17.0'); // This will automatically resolve with "v14.17.0"
3877
- * ```
3878
- *
3879
- * @mermaid
3880
- * sequenceDiagram
3881
- * participant Client
3882
- * participant RegexpOutputWriter
3883
- * participant StandardOutputWriter
3884
- * participant Logger
3885
- *
3886
- * Client->>RegexpOutputWriter: new RegexpOutputWriter(cmd, lock, regexp, flags)
3887
- * RegexpOutputWriter->>StandardOutputWriter: super(cmd, lock)
3888
- * StandardOutputWriter->>Logger: Logging.for(cmd)
3889
- * RegexpOutputWriter->>RegexpOutputWriter: compile regexp
3890
- *
3891
- * Client->>RegexpOutputWriter: data(chunk)
3892
- * RegexpOutputWriter->>StandardOutputWriter: super.data(chunk)
3893
- * StandardOutputWriter->>Logger: logger.info(log)
3894
- * RegexpOutputWriter->>RegexpOutputWriter: testAndResolve(chunk)
3895
- * RegexpOutputWriter->>RegexpOutputWriter: test(chunk)
3896
- * alt match found
3897
- * RegexpOutputWriter->>RegexpOutputWriter: resolve(match[0])
3898
- * RegexpOutputWriter->>StandardOutputWriter: resolve(match[0])
3899
- * end
3900
- *
3901
- * Client->>RegexpOutputWriter: error(chunk)
3902
- * RegexpOutputWriter->>StandardOutputWriter: super.error(chunk)
3903
- * StandardOutputWriter->>Logger: logger.info(log)
3904
- * RegexpOutputWriter->>RegexpOutputWriter: testAndReject(chunk)
3905
- * RegexpOutputWriter->>RegexpOutputWriter: test(chunk)
3906
- * alt match found
3907
- * RegexpOutputWriter->>RegexpOutputWriter: reject(match[0])
3908
- * RegexpOutputWriter->>StandardOutputWriter: reject(match[0])
3909
- * end
3910
- */
3911
- class RegexpOutputWriter extends StandardOutputWriter {
3912
- constructor(cmd, lock, regexp, flags = "g") {
3913
- super(cmd, lock);
3914
- try {
3915
- this.regexp =
3916
- typeof regexp === "string" ? new RegExp(regexp, flags) : regexp;
3917
- }
3918
- catch (e) {
3919
- throw new Error(`Invalid regular expression: ${e}`);
3920
- }
3921
- }
3922
- /**
3923
- * @description Tests the input data against the stored regular expression.
3924
- * @summary Executes the regular expression on the input data and returns the match result.
3925
- *
3926
- * @param data - The string to test against the regular expression.
3927
- * @return The result of the regular expression execution, or undefined if an error occurs.
3928
- */
3929
- test(data) {
3930
- this.regexp.lastIndex = 0;
3931
- let match;
3932
- try {
3933
- match = this.regexp.exec(data);
3934
- }
3935
- catch (e) {
3936
- return console.debug(`Failed to parse chunk: ${data}\nError: ${e} `);
3937
- }
3938
- return match;
3939
- }
3940
- /**
3941
- * @description Tests the data and resolves the promise if a match is found.
3942
- * @summary Executes the test method and resolves the promise with the first match group if successful.
3943
- *
3944
- * @param data - The string to test against the regular expression.
3945
- */
3946
- testAndResolve(data) {
3947
- const match = this.test(data);
3948
- if (match)
3949
- this.resolve(match[0]);
3950
- }
3951
- /**
3952
- * @description Tests the data and rejects the promise if a match is found.
3953
- * @summary Executes the test method and rejects the promise with the first match group if successful.
3954
- *
3955
- * @param data - The string to test against the regular expression.
3956
- */
3957
- testAndReject(data) {
3958
- const match = this.test(data);
3959
- if (match)
3960
- this.reject(match[0]);
3961
- }
3962
- /**
3963
- * @description Processes incoming data chunks.
3964
- * @summary Calls the parent class data method and then tests the data for a match to potentially resolve the promise.
3965
- *
3966
- * @param chunk - The data chunk to process.
3967
- */
3968
- data(chunk) {
3969
- super.data(chunk);
3970
- this.testAndResolve(String(chunk));
3971
- }
3972
- /**
3973
- * @description Processes incoming error chunks.
3974
- * @summary Calls the parent class error method and then tests the data for a match to potentially reject the promise.
3975
- *
3976
- * @param chunk - The error chunk to process.
3977
- */
3978
- error(chunk) {
3979
- super.error(chunk);
3980
- this.testAndReject(String(chunk));
3981
- }
3982
- }
3983
-
3984
- /**
3985
- * @module utils
3986
- * @description Utilities and building blocks for Decaf-TS CLI and scripting.
3987
- * @summary Aggregates CLI command infrastructure, input helpers, output writers, filesystem/network utilities,
3988
- * and shared types. Consumers typically use {@link Command}, {@link UserInput}, {@link StandardOutputWriter},
3989
- * {@link printBanner}, and utilities from {@link module:utils|utils}.
3990
- *
3991
- * This entrypoint re-exports subpackages:
3992
- * - CLI framework under `./cli` (command base, options, built-in commands)
3993
- * - Input helpers under `./input` (prompting and arg parsing)
3994
- * - Output helpers under `./output` (banner and styling)
3995
- * - General utilities under `./utils` (fs, http, exec, types)
3996
- * - Writers under `./writers` (stdout/stderr processors)
3997
- *
3998
- * Note: Individual exports are documented in their source files.
3999
- */
4000
- /**
4001
- * @description Represents the current version of the module.
4002
- * @summary Stores the version for the @decaf-ts/utils package. The build replaces
4003
- * the placeholder with the actual version number at publish time.
4004
- * @const VERSION
4005
- * @memberOf module:utils
4006
- */
4007
- const VERSION = "0.3.12";
4008
- /**
4009
- * @description Represents the current version of the module.
4010
- * @summary Stores the version for the @decaf-ts/utils package. The build replaces
4011
- * the placeholder with the actual version number at publish time.
4012
- * @const VERSION
4013
- * @memberOf module:utils
4014
- */
4015
- const PACKAGE_NAME = "@decaf-ts/utils";
4016
-
4017
- export { AbortCode, BuildScripts, Command, DefaultCommandOptions, DefaultCommandValues, Encoding, HttpClient, NoCIFLag, PACKAGE_NAME, RegexpOutputWriter, ReleaseScript, SemVersion, SemVersionRegex, SetupScriptKey, StandardOutputWriter, TemplateSync, Tokens, UserInput, VERSION, chainAbortController, copyFile, deletePath, getAllFiles, getDependencies, getPackage, getPackageVersion, getSlogan, installDependencies, installIfNotAvailable, lockify, normalizeImport, patchFile, printBanner, pushToGit, readFile, renameFile, runCommand, setPackageAttribute, spawnCommand, updateDependencies, writeFile };
4018
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZXNtLmNqcyIsInNvdXJjZXMiOlsiLi4vc3JjL2lucHV0L2lucHV0LnRzIiwiLi4vc3JjL2NsaS9jb25zdGFudHMudHMiLCIuLi9zcmMvdXRpbHMvY29uc3RhbnRzLnRzIiwiLi4vc3JjL3dyaXRlcnMvU3RhbmRhcmRPdXRwdXRXcml0ZXIudHMiLCIuLi9zcmMvdXRpbHMvdXRpbHMudHMiLCIuLi9zcmMvdXRpbHMvZnMudHMiLCIuLi9zcmMvYXNzZXRzL3Nsb2dhbnMudHMiLCIuLi9zcmMvb3V0cHV0L2NvbW1vbi50cyIsIi4uL3NyYy9jbGkvY29tbWFuZC50cyIsIi4uL3NyYy91dGlscy9odHRwLnRzIiwiLi4vc3JjL2NsaS9jb21tYW5kcy9idWlsZC1zY3JpcHRzLnRzIiwiLi4vc3JjL2NsaS9jb21tYW5kcy90YWctcmVsZWFzZS50cyIsIi4uL3NyYy9jbGkvY29tbWFuZHMvdXBkYXRlLXNjcmlwdHMudHMiLCIuLi9zcmMvd3JpdGVycy9SZWdleHBPdXRwdXRXcml0ZXIudHMiLCIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQW5zd2VycyxcbiAgQ2hvaWNlLFxuICBGYWxzeSxcbiAgSW5pdGlhbFJldHVyblZhbHVlLFxuICBQcmV2Q2FsbGVyLFxuICBQcm9tcHRPYmplY3QsXG4gIFByb21wdFR5cGUsXG4gIFZhbHVlT3JGdW5jLFxufSBmcm9tIFwicHJvbXB0c1wiO1xuaW1wb3J0IHByb21wdHMgZnJvbSBcInByb21wdHNcIjtcbmltcG9ydCB7IHBhcnNlQXJncywgUGFyc2VBcmdzQ29uZmlnIH0gZnJvbSBcInV0aWxcIjtcbmltcG9ydCB7IFdyaXRhYmxlLCBSZWFkYWJsZSB9IGZyb20gXCJzdHJlYW1cIjtcbmltcG9ydCB7IFBhcnNlQXJnc09wdGlvbnNDb25maWcsIFBhcnNlQXJnc1Jlc3VsdCB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlcHJlc2VudHMgYSB1c2VyIGlucHV0IHByb21wdCB3aXRoIHZhcmlvdXMgY29uZmlndXJhdGlvbiBvcHRpb25zLlxuICogQHN1bW1hcnkgVGhpcyBjbGFzcyBwcm92aWRlcyBhIGZsZXhpYmxlIGludGVyZmFjZSBmb3IgY3JlYXRpbmcgYW5kIG1hbmFnaW5nIHVzZXIgaW5wdXQgcHJvbXB0cy5cbiAqIEl0IGltcGxlbWVudHMgdGhlIFByb21wdE9iamVjdCBpbnRlcmZhY2UgZnJvbSB0aGUgJ3Byb21wdHMnIGxpYnJhcnkgYW5kIG9mZmVycyBtZXRob2RzIHRvIHNldFxuICogdmFyaW91cyBwcm9wZXJ0aWVzIG9mIHRoZSBwcm9tcHQuIFRoZSBjbGFzcyBhbHNvIGluY2x1ZGVzIHN0YXRpYyBtZXRob2RzIGZvciBjb21tb24gaW5wdXQgc2NlbmFyaW9zXG4gKiBhbmQgYXJndW1lbnQgcGFyc2luZy5cbiAqXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSB0eXBlIG9mIHRoZSBwcm9tcHQgbmFtZSwgZXh0ZW5kaW5nIHN0cmluZy5cbiAqXG4gKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gKlxuICogQGNsYXNzXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgVXNlcklucHV0IH0gZnJvbSAnQGRlY2FmLXRzL3V0aWxzJztcbiAqXG4gKiAvLyBDcmVhdGUgYSBzaW1wbGUgdGV4dCBpbnB1dFxuICogY29uc3QgbmFtZUlucHV0ID0gbmV3IFVzZXJJbnB1dCgnbmFtZScpXG4gKiAgIC5zZXRNZXNzYWdlKCdXaGF0IGlzIHlvdXIgbmFtZT8nKVxuICogICAuc2V0SW5pdGlhbCgnVXNlcicpO1xuICpcbiAqIC8vIENyZWF0ZSBhIG51bWJlciBpbnB1dCB3aXRoIHZhbGlkYXRpb25cbiAqIGNvbnN0IGFnZUlucHV0ID0gbmV3IFVzZXJJbnB1dCgnYWdlJylcbiAqICAgLnNldFR5cGUoJ251bWJlcicpXG4gKiAgIC5zZXRNZXNzYWdlKCdIb3cgb2xkIGFyZSB5b3U/JylcbiAqICAgLnNldE1pbigwKVxuICogICAuc2V0TWF4KDEyMCk7XG4gKlxuICogLy8gQXNrIGZvciBpbnB1dCBhbmQgcHJvY2VzcyB0aGUgcmVzdWx0c1xuICogYXN5bmMgZnVuY3Rpb24gZ2V0VXNlckluZm8oKSB7XG4gKiAgIGNvbnN0IGFuc3dlcnMgPSBhd2FpdCBVc2VySW5wdXQuYXNrKFtuYW1lSW5wdXQsIGFnZUlucHV0XSk7XG4gKiAgIGNvbnNvbGUubG9nKGBIZWxsbyAke2Fuc3dlcnMubmFtZX0sIHlvdSBhcmUgJHthbnN3ZXJzLmFnZX0geWVhcnMgb2xkLmApO1xuICogfVxuICpcbiAqIGdldFVzZXJJbmZvKCk7XG4gKiBgYGBcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICogICBwYXJ0aWNpcGFudCBVc2VySW5wdXRcbiAqICAgcGFydGljaXBhbnQgUHJvbXB0TGlicmFyeVxuICpcbiAqICAgQ2xpZW50LT4+VXNlcklucHV0OiBuZXcgVXNlcklucHV0KG5hbWUpXG4gKiAgIENsaWVudC0+PlVzZXJJbnB1dDogc2V0TWVzc2FnZShtZXNzYWdlKVxuICogICBDbGllbnQtPj5Vc2VySW5wdXQ6IHNldFR5cGUodHlwZSlcbiAqICAgQ2xpZW50LT4+VXNlcklucHV0OiBzZXRJbml0aWFsKGluaXRpYWwpXG4gKiAgIENsaWVudC0+PlVzZXJJbnB1dDogT3RoZXIgY29uZmlndXJhdGlvbiBtZXRob2RzXG4gKlxuICogICBDbGllbnQtPj5Vc2VySW5wdXQ6IGFzaygpXG4gKiAgIFVzZXJJbnB1dC0+PlByb21wdExpYnJhcnk6IHByb21wdHMocXVlc3Rpb24pXG4gKiAgIFByb21wdExpYnJhcnktPj5DbGllbnQ6IERpc3BsYXkgcHJvbXB0XG4gKiAgIENsaWVudC0+PlByb21wdExpYnJhcnk6IFVzZXIgcHJvdmlkZXMgaW5wdXRcbiAqICAgUHJvbXB0TGlicmFyeS0+PlVzZXJJbnB1dDogUmV0dXJuIGFuc3dlcnNcbiAqICAgVXNlcklucHV0LT4+Q2xpZW50OiBSZXR1cm4gcHJvY2Vzc2VkIGFuc3dlcnNcbiAqL1xuZXhwb3J0IGNsYXNzIFVzZXJJbnB1dDxSIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nPiBpbXBsZW1lbnRzIFByb21wdE9iamVjdDxSPiB7XG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IGxvZ2dlciA9IExvZ2dpbmcuZm9yKFVzZXJJbnB1dCk7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHR5cGUgb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyB0aGUgaW5wdXQgbWV0aG9kIChlLmcuLCB0ZXh0LCBudW1iZXIsIGNvbmZpcm0pLlxuICAgKi9cbiAgdHlwZTogUHJvbXB0VHlwZSB8IEZhbHN5IHwgUHJldkNhbGxlcjxSLCBQcm9tcHRUeXBlIHwgRmFsc3k+ID0gXCJ0ZXh0XCI7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbmFtZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBVc2VkIGFzIHRoZSBrZXkgaW4gdGhlIHJldHVybmVkIGFuc3dlcnMgb2JqZWN0LlxuICAgKi9cbiAgbmFtZTogVmFsdWVPckZ1bmM8Uj47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbWVzc2FnZSBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG4gICAqIEBzdW1tYXJ5IFRoZSBxdWVzdGlvbiBvciBpbnN0cnVjdGlvbiBwcmVzZW50ZWQgdG8gdGhlIHVzZXIuXG4gICAqL1xuICBtZXNzYWdlPzogVmFsdWVPckZ1bmM8c3RyaW5nPiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBpbml0aWFsIHZhbHVlIG9mIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IFRoZSBkZWZhdWx0IHZhbHVlIHByZXNlbnRlZCB0byB0aGUgdXNlci5cbiAgICovXG4gIGluaXRpYWw/OlxuICAgIHwgSW5pdGlhbFJldHVyblZhbHVlXG4gICAgfCBQcmV2Q2FsbGVyPFIsIEluaXRpYWxSZXR1cm5WYWx1ZSB8IFByb21pc2U8SW5pdGlhbFJldHVyblZhbHVlPj5cbiAgICB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBzdHlsZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBEZXRlcm1pbmVzIHRoZSB2aXN1YWwgc3R5bGUgb2YgdGhlIHByb21wdC5cbiAgICovXG4gIHN0eWxlPzogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgZm9ybWF0IGZ1bmN0aW9uIGZvciB0aGUgaW5wdXQuXG4gICAqIEBzdW1tYXJ5IEEgZnVuY3Rpb24gdG8gZm9ybWF0IHRoZSB1c2VyJ3MgaW5wdXQgYmVmb3JlIGl0J3MgcmV0dXJuZWQuXG4gICAqL1xuICBmb3JtYXQ/OiBQcmV2Q2FsbGVyPFIsIHZvaWQ+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHZhbGlkYXRpb24gZnVuY3Rpb24gZm9yIHRoZSBpbnB1dC5cbiAgICogQHN1bW1hcnkgQSBmdW5jdGlvbiB0byB2YWxpZGF0ZSB0aGUgdXNlcidzIGlucHV0LlxuICAgKi9cbiAgdmFsaWRhdGU/OlxuICAgIHwgUHJldkNhbGxlcjxSLCBib29sZWFuIHwgc3RyaW5nIHwgUHJvbWlzZTxib29sZWFuIHwgc3RyaW5nPj5cbiAgICB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBvblN0YXRlIGNhbGxiYWNrIGZ1bmN0aW9uLlxuICAgKiBAc3VtbWFyeSBBIGZ1bmN0aW9uIGNhbGxlZCB3aGVuIHRoZSBzdGF0ZSBvZiB0aGUgcHJvbXB0IGNoYW5nZXMuXG4gICAqL1xuICBvblN0YXRlPzogUHJldkNhbGxlcjxSLCB2b2lkPiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBtaW5pbXVtIHZhbHVlIGZvciBudW1iZXIgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBUaGUgbG93ZXN0IG51bWJlciB0aGUgdXNlciBjYW4gaW5wdXQuXG4gICAqL1xuICBtaW4/OiBudW1iZXIgfCBQcmV2Q2FsbGVyPFIsIG51bWJlciB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBtYXhpbXVtIHZhbHVlIGZvciBudW1iZXIgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBUaGUgaGlnaGVzdCBudW1iZXIgdGhlIHVzZXIgY2FuIGlucHV0LlxuICAgKi9cbiAgbWF4PzogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGFsbG93IGZsb2F0IHZhbHVlcyBmb3IgbnVtYmVyIGlucHV0cy5cbiAgICogQHN1bW1hcnkgSWYgdHJ1ZSwgYWxsb3dzIGRlY2ltYWwgbnVtYmVycy5cbiAgICovXG4gIGZsb2F0PzogYm9vbGVhbiB8IFByZXZDYWxsZXI8UiwgYm9vbGVhbiB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8gcm91bmQgdG8gZm9yIGZsb2F0IGlucHV0cy5cbiAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyB0aGUgcHJlY2lzaW9uIG9mIGZsb2F0IGlucHV0cy5cbiAgICovXG4gIHJvdW5kPzogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJbnN0cnVjdGlvbnMgZm9yIHRoZSB1c2VyLlxuICAgKiBAc3VtbWFyeSBBZGRpdGlvbmFsIGd1aWRhbmNlIHByb3ZpZGVkIHRvIHRoZSB1c2VyLlxuICAgKi9cbiAgaW5zdHJ1Y3Rpb25zPzogc3RyaW5nIHwgYm9vbGVhbiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBpbmNyZW1lbnQgdmFsdWUgZm9yIG51bWJlciBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IFRoZSBzdGVwIHNpemUgd2hlbiBpbmNyZWFzaW5nIG9yIGRlY3JlYXNpbmcgdGhlIG51bWJlci5cbiAgICovXG4gIGluY3JlbWVudD86IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHNlcGFyYXRvciBmb3IgbGlzdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IFRoZSBjaGFyYWN0ZXIgdXNlZCB0byBzZXBhcmF0ZSBsaXN0IGl0ZW1zLlxuICAgKi9cbiAgc2VwYXJhdG9yPzogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgYWN0aXZlIG9wdGlvbiBzdHlsZSBmb3Igc2VsZWN0IGlucHV0cy5cbiAgICogQHN1bW1hcnkgVGhlIHN0eWxlIGFwcGxpZWQgdG8gdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBvcHRpb24uXG4gICAqL1xuICBhY3RpdmU/OiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBpbmFjdGl2ZSBvcHRpb24gc3R5bGUgZm9yIHNlbGVjdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IFRoZSBzdHlsZSBhcHBsaWVkIHRvIG5vbi1zZWxlY3RlZCBvcHRpb25zLlxuICAgKi9cbiAgaW5hY3RpdmU/OiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBhdmFpbGFibGUgY2hvaWNlcyBmb3Igc2VsZWN0LCBtdWx0aXNlbGVjdCwgb3IgYXV0b2NvbXBsZXRlIGlucHV0cy5cbiAgICogQHN1bW1hcnkgQW4gYXJyYXkgb2Ygb3B0aW9ucyB0aGF0IHRoZSB1c2VyIGNhbiBzZWxlY3QgZnJvbSBpbiBjaG9pY2UtYmFzZWQgcHJvbXB0cy5cbiAgICovXG4gIGNob2ljZXM/OiBDaG9pY2VbXSB8IFByZXZDYWxsZXI8UiwgQ2hvaWNlW10gfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgaGludCB0ZXh0IGZvciB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBBZGRpdGlvbmFsIGluZm9ybWF0aW9uIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICovXG4gIGhpbnQ/OiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSB3YXJuaW5nIHRleHQgZm9yIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IEEgd2FybmluZyBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICovXG4gIHdhcm4/OiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICBzdWdnZXN0PzogKChpbnB1dDogYW55LCBjaG9pY2VzOiBDaG9pY2VbXSkgPT4gUHJvbWlzZTxhbnk+KSB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBsaW1pdCBmb3IgbGlzdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IFRoZSBtYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0aGF0IGNhbiBiZSBzZWxlY3RlZC5cbiAgICovXG4gIGxpbWl0PzogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbWFzayBmb3IgcGFzc3dvcmQgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBUaGUgY2hhcmFjdGVyIHVzZWQgdG8gaGlkZSB0aGUgdXNlcidzIGlucHV0LlxuICAgKi9cbiAgbWFzaz86IHN0cmluZyB8IFByZXZDYWxsZXI8Uiwgc3RyaW5nIHwgRmFsc3k+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHN0ZG91dCBzdHJlYW0gZm9yIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IFRoZSBvdXRwdXQgc3RyZWFtIHVzZWQgYnkgdGhlIHByb21wdC5cbiAgICovXG4gIHN0ZG91dD86IFdyaXRhYmxlIHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHN0ZGluIHN0cmVhbSBmb3IgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgVGhlIGlucHV0IHN0cmVhbSB1c2VkIGJ5IHRoZSBwcm9tcHQuXG4gICAqL1xuICBzdGRpbj86IFJlYWRhYmxlIHwgdW5kZWZpbmVkO1xuXG4gIGNvbnN0cnVjdG9yKG5hbWU6IFZhbHVlT3JGdW5jPFI+KSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgdHlwZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBpbnB1dCBtZXRob2QgZm9yIHRoZSBwcm9tcHQuXG4gICAqXG4gICAqIEBwYXJhbSB0eXBlIC0gVGhlIHR5cGUgb2YgdGhlIHByb21wdC5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldFR5cGUodHlwZTogUHJvbXB0VHlwZSB8IEZhbHN5IHwgUHJldkNhbGxlcjxSLCBQcm9tcHRUeXBlIHwgRmFsc3k+KTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIHR5cGUgdG86ICR7dHlwZX1gKTtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBtZXNzYWdlIG9mIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIHF1ZXN0aW9uIG9yIGluc3RydWN0aW9uIHByZXNlbnRlZCB0byB0aGUgdXNlci5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIG1lc3NhZ2UgdG8gYmUgZGlzcGxheWVkLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0TWVzc2FnZSh2YWx1ZTogVmFsdWVPckZ1bmM8c3RyaW5nPiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBtZXNzYWdlIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMubWVzc2FnZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBpbml0aWFsIHZhbHVlIG9mIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGRlZmF1bHQgdmFsdWUgcHJlc2VudGVkIHRvIHRoZSB1c2VyLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgaW5pdGlhbCB2YWx1ZS5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldEluaXRpYWwoXG4gICAgdmFsdWU6XG4gICAgICB8IEluaXRpYWxSZXR1cm5WYWx1ZVxuICAgICAgfCBQcmV2Q2FsbGVyPFIsIEluaXRpYWxSZXR1cm5WYWx1ZSB8IFByb21pc2U8SW5pdGlhbFJldHVyblZhbHVlPj5cbiAgICAgIHwgdW5kZWZpbmVkXG4gICk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBpbml0aWFsIHZhbHVlIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuaW5pdGlhbCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBzdHlsZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSB2aXN1YWwgc3R5bGUgb2YgdGhlIHByb21wdC5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHN0eWxlIHRvIGJlIGFwcGxpZWQuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRTdHlsZSh2YWx1ZTogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgc3R5bGUgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5zdHlsZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBmb3JtYXQgZnVuY3Rpb24gb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyBhIGZ1bmN0aW9uIHRvIGZvcm1hdCB0aGUgdXNlcidzIGlucHV0IGJlZm9yZSBpdCdzIHJldHVybmVkLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgZm9ybWF0IGZ1bmN0aW9uLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0Rm9ybWF0KHZhbHVlOiBQcmV2Q2FsbGVyPFIsIHZvaWQ+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGZvcm1hdCBmdW5jdGlvbmApO1xuICAgIHRoaXMuZm9ybWF0ID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIHZhbGlkYXRpb24gZnVuY3Rpb24gb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyBhIGZ1bmN0aW9uIHRvIHZhbGlkYXRlIHRoZSB1c2VyJ3MgaW5wdXQuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWxpZGF0aW9uIGZ1bmN0aW9uLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0VmFsaWRhdGUoXG4gICAgdmFsdWU6XG4gICAgICB8IFByZXZDYWxsZXI8UiwgYm9vbGVhbiB8IHN0cmluZyB8IFByb21pc2U8Ym9vbGVhbiB8IHN0cmluZz4+XG4gICAgICB8IHVuZGVmaW5lZFxuICApOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgdmFsaWRhdGUgZnVuY3Rpb25gKTtcbiAgICB0aGlzLnZhbGlkYXRlID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIG9uU3RhdGUgY2FsbGJhY2sgb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyBhIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBzdGF0ZSBvZiB0aGUgcHJvbXB0IGNoYW5nZXMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBvblN0YXRlIGNhbGxiYWNrIGZ1bmN0aW9uLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0T25TdGF0ZSh2YWx1ZTogUHJldkNhbGxlcjxSLCB2b2lkPiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBvblN0YXRlIGNhbGxiYWNrYCk7XG4gICAgdGhpcy5vblN0YXRlID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIG1pbmltdW0gdmFsdWUgZm9yIG51bWJlciBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGxvd2VzdCBudW1iZXIgdGhlIHVzZXIgY2FuIGlucHV0LlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgbWluaW11bSB2YWx1ZS5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldE1pbih2YWx1ZTogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgbWluIHZhbHVlIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMubWluID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIG1heGltdW0gdmFsdWUgZm9yIG51bWJlciBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGhpZ2hlc3QgbnVtYmVyIHRoZSB1c2VyIGNhbiBpbnB1dC5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIG1heGltdW0gdmFsdWUuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRNYXgodmFsdWU6IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIG1heCB2YWx1ZSB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLm1heCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHdoZXRoZXIgdG8gYWxsb3cgZmxvYXQgdmFsdWVzIGZvciBudW1iZXIgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHdoZXRoZXIgZGVjaW1hbCBudW1iZXJzIGFyZSBhbGxvd2VkLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBXaGV0aGVyIHRvIGFsbG93IGZsb2F0IHZhbHVlcy5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldEZsb2F0KHZhbHVlOiBib29sZWFuIHwgUHJldkNhbGxlcjxSLCBib29sZWFuIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGZsb2F0IHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuZmxvYXQgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHJvdW5kIHRvIGZvciBmbG9hdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIHByZWNpc2lvbiBvZiBmbG9hdCBpbnB1dHMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRSb3VuZCh2YWx1ZTogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgcm91bmQgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5yb3VuZCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBpbnN0cnVjdGlvbnMgZm9yIHRoZSB1c2VyLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIGFkZGl0aW9uYWwgZ3VpZGFuY2UgcHJvdmlkZWQgdG8gdGhlIHVzZXIuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBpbnN0cnVjdGlvbnMuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRJbnN0cnVjdGlvbnModmFsdWU6IHN0cmluZyB8IGJvb2xlYW4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgaW5zdHJ1Y3Rpb25zIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuaW5zdHJ1Y3Rpb25zID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIGluY3JlbWVudCB2YWx1ZSBmb3IgbnVtYmVyIGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgc3RlcCBzaXplIHdoZW4gaW5jcmVhc2luZyBvciBkZWNyZWFzaW5nIHRoZSBudW1iZXIuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBpbmNyZW1lbnQgdmFsdWUuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRJbmNyZW1lbnQoXG4gICAgdmFsdWU6IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkXG4gICk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBpbmNyZW1lbnQgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5pbmNyZW1lbnQgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgc2VwYXJhdG9yIGZvciBsaXN0IGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgY2hhcmFjdGVyIHVzZWQgdG8gc2VwYXJhdGUgbGlzdCBpdGVtcy5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHNlcGFyYXRvciBjaGFyYWN0ZXIuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRTZXBhcmF0b3IoXG4gICAgdmFsdWU6IHN0cmluZyB8IFByZXZDYWxsZXI8Uiwgc3RyaW5nIHwgRmFsc3k+IHwgdW5kZWZpbmVkXG4gICk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBzZXBhcmF0b3IgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5zZXBhcmF0b3IgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgYWN0aXZlIG9wdGlvbiBzdHlsZSBmb3Igc2VsZWN0IGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgc3R5bGUgYXBwbGllZCB0byB0aGUgY3VycmVudGx5IHNlbGVjdGVkIG9wdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGFjdGl2ZSBvcHRpb24gc3R5bGUuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRBY3RpdmUodmFsdWU6IHN0cmluZyB8IFByZXZDYWxsZXI8Uiwgc3RyaW5nIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGFjdGl2ZSBzdHlsZSB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLmFjdGl2ZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBpbmFjdGl2ZSBvcHRpb24gc3R5bGUgZm9yIHNlbGVjdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIHN0eWxlIGFwcGxpZWQgdG8gbm9uLXNlbGVjdGVkIG9wdGlvbnMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBpbmFjdGl2ZSBvcHRpb24gc3R5bGUuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRJbmFjdGl2ZSh2YWx1ZTogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgaW5hY3RpdmUgc3R5bGUgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5pbmFjdGl2ZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBjaG9pY2VzIGZvciBzZWxlY3QsIG11bHRpc2VsZWN0LCBvciBhdXRvY29tcGxldGUgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBhdmFpbGFibGUgb3B0aW9ucyB0aGF0IHRoZSB1c2VyIGNhbiBzZWxlY3QgZnJvbSBpbiBjaG9pY2UtYmFzZWQgcHJvbXB0cy5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGFycmF5IG9mIGNob2ljZXMgb3IgYSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgdGhlIGNob2ljZXMuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRDaG9pY2VzKFxuICAgIHZhbHVlOiBDaG9pY2VbXSB8IFByZXZDYWxsZXI8UiwgQ2hvaWNlW10gfCBGYWxzeT4gfCB1bmRlZmluZWRcbiAgKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGNob2ljZXM6ICR7SlNPTi5zdHJpbmdpZnkodmFsdWUpfWApO1xuICAgIHRoaXMuY2hvaWNlcyA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBoaW50IHRleHQgZm9yIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBoaW50IHRleHQuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRIaW50KHZhbHVlOiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBoaW50IHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuaGludCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSB3YXJuaW5nIHRleHQgZm9yIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgYSB3YXJuaW5nIG1lc3NhZ2UgZGlzcGxheWVkIHRvIHRoZSB1c2VyLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgd2FybmluZyB0ZXh0LlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0V2Fybih2YWx1ZTogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgd2FybiB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLndhcm4gPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgc3VnZ2VzdGlvbiBmdW5jdGlvbiBmb3IgYXV0b2NvbXBsZXRlIGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyBhIGZ1bmN0aW9uIHRoYXQgcHJvdmlkZXMgc3VnZ2VzdGlvbnMgYmFzZWQgb24gdGhlIHVzZXIncyBpbnB1dCBhbmQgYXZhaWxhYmxlIGNob2ljZXMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIEEgZnVuY3Rpb24gdGhhdCB0YWtlcyB0aGUgY3VycmVudCBpbnB1dCBhbmQgYXZhaWxhYmxlIGNob2ljZXMgYW5kIHJldHVybnMgYSBQcm9taXNlIHJlc29sdmluZyB0byBzdWdnZXN0aW9ucy5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldFN1Z2dlc3QoXG4gICAgdmFsdWU6ICgoaW5wdXQ6IGFueSwgY2hvaWNlczogQ2hvaWNlW10pID0+IFByb21pc2U8YW55PikgfCB1bmRlZmluZWRcbiAgKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIHN1Z2dlc3QgZnVuY3Rpb25gKTtcbiAgICB0aGlzLnN1Z2dlc3QgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgbGltaXQgZm9yIGxpc3QgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBtYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0aGF0IGNhbiBiZSBzZWxlY3RlZCBpbiBsaXN0LXR5cGUgcHJvbXB0cy5cbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgcHJvbXB0IG5hbWUsIGV4dGVuZGluZyBzdHJpbmcuXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBtYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0aGF0IGNhbiBiZSBzZWxlY3RlZCwgb3IgYSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgdGhpcyB2YWx1ZS5cbiAgICogQHJldHVybiBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0TGltaXQodmFsdWU6IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGxpbWl0IHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMubGltaXQgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgbWFzayBmb3IgcGFzc3dvcmQgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBjaGFyYWN0ZXIgdXNlZCB0byBoaWRlIHRoZSB1c2VyJ3MgaW5wdXQgaW4gcGFzc3dvcmQtdHlwZSBwcm9tcHRzLlxuICAgKiBAdGVtcGxhdGUgUiAtIFRoZSB0eXBlIG9mIHRoZSBwcm9tcHQgbmFtZSwgZXh0ZW5kaW5nIHN0cmluZy5cbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGNoYXJhY3RlciB1c2VkIHRvIG1hc2sgdGhlIGlucHV0LCBvciBhIGZ1bmN0aW9uIHRvIGRldGVybWluZSB0aGlzIHZhbHVlLlxuICAgKiBAcmV0dXJuIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRNYXNrKHZhbHVlOiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBtYXNrIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMubWFzayA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBzdGRvdXQgc3RyZWFtIGZvciB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBvdXRwdXQgc3RyZWFtIHVzZWQgYnkgdGhlIHByb21wdCBmb3IgZGlzcGxheWluZyBtZXNzYWdlcyBhbmQgcmVzdWx0cy5cbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIFdyaXRhYmxlIHN0cmVhbSB0byBiZSB1c2VkIGFzIHN0ZG91dC5cbiAgICogQHJldHVybiBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0U3Rkb3V0KHZhbHVlOiBXcml0YWJsZSB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBzdGRvdXQgc3RyZWFtYCk7XG4gICAgdGhpcy5zdGRvdXQgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIHN0ZGluIHN0cmVhbSBmb3IgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgaW5wdXQgc3RyZWFtIHVzZWQgYnkgdGhlIHByb21wdCBmb3IgcmVjZWl2aW5nIHVzZXIgaW5wdXQuXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBSZWFkYWJsZSBzdHJlYW0gdG8gYmUgdXNlZCBhcyBzdGRpbi5cbiAgICogQHJldHVybiBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0U3RkaW4odmFsdWU6IFJlYWRhYmxlIHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgdGhpcy5zdGRpbiA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBc2tzIHRoZSB1c2VyIGZvciBpbnB1dCBiYXNlZCBvbiB0aGUgY3VycmVudCBVc2VySW5wdXQgY29uZmlndXJhdGlvbi5cbiAgICogQHN1bW1hcnkgUHJvbXB0cyB0aGUgdXNlciBhbmQgcmV0dXJucyB0aGVpciByZXNwb25zZSBhcyBhIHNpbmdsZSB2YWx1ZS5cbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgcHJvbXB0IG5hbWUsIGV4dGVuZGluZyBzdHJpbmcuXG4gICAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHVzZXIncyBhbnN3ZXIuXG4gICAqL1xuICBhc3luYyBhc2soKSB7XG4gICAgcmV0dXJuIChhd2FpdCBVc2VySW5wdXQuYXNrKHRoaXMpKVt0aGlzLm5hbWUgYXMga2V5b2YgQW5zd2VyczxSPl07XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFza3MgdGhlIHVzZXIgb25lIG9yIG1vcmUgcXVlc3Rpb25zIGJhc2VkIG9uIHRoZSBwcm92aWRlZCBVc2VySW5wdXQgY29uZmlndXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IFByb21wdHMgdGhlIHVzZXIgd2l0aCBvbmUgb3IgbW9yZSBxdWVzdGlvbnMgYW5kIHJldHVybnMgdGhlaXIgYW5zd2VycyBhcyBhbiBvYmplY3QuXG4gICAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgdGhlIHByb21wdCBuYW1lLCBleHRlbmRpbmcgc3RyaW5nLlxuICAgKiBAcGFyYW0gcXVlc3Rpb24gLSBBIHNpbmdsZSBVc2VySW5wdXQgaW5zdGFuY2Ugb3IgYW4gYXJyYXkgb2YgVXNlcklucHV0IGluc3RhbmNlcy5cbiAgICogQHJldHVybiBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgdXNlcidzIGFuc3dlcnMuXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IFUgYXMgVXNlclxuICAgKiAgIHBhcnRpY2lwYW50IEEgYXMgYXNrIG1ldGhvZFxuICAgKiAgIHBhcnRpY2lwYW50IFAgYXMgcHJvbXB0cyBsaWJyYXJ5XG4gICAqICAgQS0+PlA6IENhbGwgcHJvbXB0cyB3aXRoIHF1ZXN0aW9uKHMpXG4gICAqICAgUC0+PlU6IERpc3BsYXkgcHJvbXB0KHMpXG4gICAqICAgVS0+PlA6IFByb3ZpZGUgaW5wdXRcbiAgICogICBQLT4+QTogUmV0dXJuIGFuc3dlcnNcbiAgICogICBBLT4+QTogUHJvY2VzcyBhbnN3ZXJzXG4gICAqICAgQS0tPj5DYWxsZXI6IFJldHVybiBwcm9jZXNzZWQgYW5zd2Vyc1xuICAgKi9cbiAgc3RhdGljIGFzeW5jIGFzazxSIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nPihcbiAgICBxdWVzdGlvbjogVXNlcklucHV0PFI+IHwgVXNlcklucHV0PFI+W11cbiAgKSB7XG4gICAgY29uc3QgbG9nID0gVXNlcklucHV0LmxvZ2dlci5mb3IodGhpcy5hc2spO1xuICAgIGlmICghQXJyYXkuaXNBcnJheShxdWVzdGlvbikpIHtcbiAgICAgIHF1ZXN0aW9uID0gW3F1ZXN0aW9uXTtcbiAgICB9XG4gICAgbGV0IGFuc3dlcnM6IEFuc3dlcnM8Uj47XG4gICAgdHJ5IHtcbiAgICAgIGxvZy52ZXJib3NlKFxuICAgICAgICBgQXNraW5nIHF1ZXN0aW9uczogJHtxdWVzdGlvbi5tYXAoKHEpID0+IHEubmFtZSkuam9pbihcIiwgXCIpfWBcbiAgICAgICk7XG4gICAgICBhbnN3ZXJzID0gYXdhaXQgcHJvbXB0cyhxdWVzdGlvbik7XG4gICAgICBsb2cudmVyYm9zZShgUmVjZWl2ZWQgYW5zd2VyczogJHtKU09OLnN0cmluZ2lmeShhbnN3ZXJzLCBudWxsLCAyKX1gKTtcbiAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciB3aGlsZSBnZXR0aW5nIGlucHV0OiAke2Vycm9yfWApO1xuICAgIH1cbiAgICByZXR1cm4gYW5zd2VycztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXNrcyB0aGUgdXNlciBmb3IgYSBudW1iZXIgaW5wdXQuXG4gICAqIEBzdW1tYXJ5IFByb21wdHMgdGhlIHVzZXIgdG8gZW50ZXIgYSBudW1iZXIsIHdpdGggb3B0aW9uYWwgbWluaW11bSwgbWF4aW11bSwgYW5kIGluaXRpYWwgdmFsdWVzLlxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gICAqIEBwYXJhbSBxdWVzdGlvbiAtIFRoZSBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICogQHBhcmFtIG1pbiAtIFRoZSBtaW5pbXVtIGFsbG93ZWQgdmFsdWUgKG9wdGlvbmFsKS5cbiAgICogQHBhcmFtIG1heCAtIFRoZSBtYXhpbXVtIGFsbG93ZWQgdmFsdWUgKG9wdGlvbmFsKS5cbiAgICogQHBhcmFtIGluaXRpYWwgLSBUaGUgaW5pdGlhbCB2YWx1ZSBwcmVzZW50ZWQgdG8gdGhlIHVzZXIgKG9wdGlvbmFsKS5cbiAgICogQHJldHVybiBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgbnVtYmVyIGVudGVyZWQgYnkgdGhlIHVzZXIuXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgYXNrTnVtYmVyKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBxdWVzdGlvbjogc3RyaW5nLFxuICAgIG1pbj86IG51bWJlcixcbiAgICBtYXg/OiBudW1iZXIsXG4gICAgaW5pdGlhbD86IG51bWJlclxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGxvZyA9IFVzZXJJbnB1dC5sb2dnZXIuZm9yKHRoaXMuYXNrTnVtYmVyKTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBBc2tpbmcgbnVtYmVyIGlucHV0OiB1bmRlZmluZWQsIHF1ZXN0aW9uOiAke3F1ZXN0aW9ufSwgbWluOiAke21pbn0sIG1heDogJHttYXh9LCBpbml0aWFsOiAke2luaXRpYWx9YFxuICAgICk7XG4gICAgY29uc3QgdXNlcklucHV0ID0gbmV3IFVzZXJJbnB1dChuYW1lKVxuICAgICAgLnNldE1lc3NhZ2UocXVlc3Rpb24pXG4gICAgICAuc2V0VHlwZShcIm51bWJlclwiKTtcblxuICAgIGlmICh0eXBlb2YgbWluID09PSBcIm51bWJlclwiKSB1c2VySW5wdXQuc2V0TWluKG1pbik7XG5cbiAgICBpZiAodHlwZW9mIG1heCA9PT0gXCJudW1iZXJcIikgdXNlcklucHV0LnNldE1heChtYXgpO1xuXG4gICAgaWYgKHR5cGVvZiBpbml0aWFsID09PSBcIm51bWJlclwiKSB1c2VySW5wdXQuc2V0SW5pdGlhbChpbml0aWFsKTtcblxuICAgIHJldHVybiAoYXdhaXQgdGhpcy5hc2sodXNlcklucHV0KSlbbmFtZV07XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFza3MgdGhlIHVzZXIgZm9yIGEgdGV4dCBpbnB1dC5cbiAgICogQHN1bW1hcnkgUHJvbXB0cyB0aGUgdXNlciB0byBlbnRlciB0ZXh0LCB3aXRoIG9wdGlvbmFsIG1hc2tpbmcgYW5kIGluaXRpYWwgdmFsdWUuXG4gICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHByb21wdCwgdXNlZCBhcyB0aGUga2V5IGluIHRoZSByZXR1cm5lZCBhbnN3ZXJzIG9iamVjdC5cbiAgICogQHBhcmFtIHF1ZXN0aW9uIC0gVGhlIG1lc3NhZ2UgZGlzcGxheWVkIHRvIHRoZSB1c2VyLlxuICAgKiBAcGFyYW0gbWFzayAtIFRoZSBjaGFyYWN0ZXIgdXNlZCB0byBtYXNrIHRoZSBpbnB1dCAob3B0aW9uYWwsIGZvciBwYXNzd29yZC1saWtlIGlucHV0cykuXG4gICAqIEBwYXJhbSBpbml0aWFsIC0gVGhlIGluaXRpYWwgdmFsdWUgcHJlc2VudGVkIHRvIHRoZSB1c2VyIChvcHRpb25hbCkuXG4gICAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHRleHQgZW50ZXJlZCBieSB0aGUgdXNlci5cbiAgICovXG4gIHN0YXRpYyBhc3luYyBhc2tUZXh0KFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBxdWVzdGlvbjogc3RyaW5nLFxuICAgIG1hc2s6IHN0cmluZyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZCxcbiAgICBpbml0aWFsPzogc3RyaW5nXG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgbG9nID0gVXNlcklucHV0LmxvZ2dlci5mb3IodGhpcy5hc2tUZXh0KTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBBc2tpbmcgdGV4dCBpbnB1dDogdW5kZWZpbmVkLCBxdWVzdGlvbjogJHtxdWVzdGlvbn0sIG1hc2s6ICR7bWFza30sIGluaXRpYWw6ICR7aW5pdGlhbH1gXG4gICAgKTtcbiAgICBjb25zdCB1c2VySW5wdXQgPSBuZXcgVXNlcklucHV0KG5hbWUpLnNldE1lc3NhZ2UocXVlc3Rpb24pO1xuXG4gICAgaWYgKG1hc2spIHVzZXJJbnB1dC5zZXRNYXNrKG1hc2spO1xuICAgIGlmICh0eXBlb2YgaW5pdGlhbCA9PT0gXCJzdHJpbmdcIikgdXNlcklucHV0LnNldEluaXRpYWwoaW5pdGlhbCk7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLmFzayh1c2VySW5wdXQpKVtuYW1lXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXNrcyB0aGUgdXNlciBmb3IgYSBjb25maXJtYXRpb24gKHllcy9ubykuXG4gICAqIEBzdW1tYXJ5IFByb21wdHMgdGhlIHVzZXIgd2l0aCBhIHllcy9ubyBxdWVzdGlvbiBhbmQgcmV0dXJucyBhIGJvb2xlYW4gcmVzdWx0LlxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gICAqIEBwYXJhbSBxdWVzdGlvbiAtIFRoZSBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICogQHBhcmFtIGluaXRpYWwgLSBUaGUgaW5pdGlhbCB2YWx1ZSBwcmVzZW50ZWQgdG8gdGhlIHVzZXIgKG9wdGlvbmFsKS5cbiAgICogQHJldHVybiBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSB1c2VyJ3MgYW5zd2VyLlxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGFza0NvbmZpcm1hdGlvbihcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgcXVlc3Rpb246IHN0cmluZyxcbiAgICBpbml0aWFsPzogYm9vbGVhblxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBsb2cgPSBVc2VySW5wdXQubG9nZ2VyLmZvcih0aGlzLmFza0NvbmZpcm1hdGlvbik7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgQXNraW5nIGNvbmZpcm1hdGlvbiBpbnB1dDogdW5kZWZpbmVkLCBxdWVzdGlvbjogJHtxdWVzdGlvbn0sIGluaXRpYWw6ICR7aW5pdGlhbH1gXG4gICAgKTtcbiAgICBjb25zdCB1c2VySW5wdXQgPSBuZXcgVXNlcklucHV0KG5hbWUpXG4gICAgICAuc2V0TWVzc2FnZShxdWVzdGlvbilcbiAgICAgIC5zZXRUeXBlKFwiY29uZmlybVwiKTtcblxuICAgIGlmICh0eXBlb2YgaW5pdGlhbCAhPT0gXCJ1bmRlZmluZWRcIikgdXNlcklucHV0LnNldEluaXRpYWwoaW5pdGlhbCk7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLmFzayh1c2VySW5wdXQpKVtuYW1lXTtcbiAgfVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlcGVhdGVkbHkgYXNrcyBmb3IgaW5wdXQgdW50aWwgYSB2YWxpZCByZXNwb25zZSBpcyBnaXZlbiBvciB0aGUgbGltaXQgaXMgcmVhY2hlZC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgaW5zaXN0cyBvbiBnZXR0aW5nIGEgdmFsaWQgaW5wdXQgZnJvbSB0aGUgdXNlciwgYWxsb3dpbmcgZm9yIGEgc3BlY2lmaWVkIG51bWJlciBvZiBhdHRlbXB0cy5cbiAgICpcbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgZXhwZWN0ZWQgcmVzdWx0LlxuICAgKiBAcGFyYW0gaW5wdXQgLSBUaGUgVXNlcklucHV0IGluc3RhbmNlIHRvIHVzZSBmb3IgcHJvbXB0aW5nLlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKHN0cmluZyk6Ym9vbGVhbn0gdGVzdCAtIFZhbGlkYXRvciBmdW5jdGlvbiByZWNlaXZpbmcgdGhlIHVzZXIgaW5wdXQgYW5kIHJldHVybmluZyB3aGV0aGVyIGl0IGlzIHZhbGlkLlxuICAgKiBAcGFyYW0gZGVmYXVsdENvbmZpcm1hdGlvbiAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB0aGUgY29uZmlybWF0aW9uIHByb21wdCAodHJ1ZSBmb3IgeWVzLCBmYWxzZSBmb3Igbm8pLlxuICAgKiBAcGFyYW0gbGltaXQgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgYXR0ZW1wdHMgYWxsb3dlZCAoZGVmYXVsdCBpcyAxKS5cbiAgICogQHJldHVybiBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgdmFsaWQgaW5wdXQgb3IgdW5kZWZpbmVkIGlmIHRoZSBsaW1pdCBpcyByZWFjaGVkLlxuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXJcbiAgICogICBwYXJ0aWNpcGFudCBJIGFzIGluc2lzdCBtZXRob2RcbiAgICogICBwYXJ0aWNpcGFudCBBIGFzIGFzayBtZXRob2RcbiAgICogICBwYXJ0aWNpcGFudCBUIGFzIHRlc3QgZnVuY3Rpb25cbiAgICogICBwYXJ0aWNpcGFudCBDIGFzIGFza0NvbmZpcm1hdGlvbiBtZXRob2RcbiAgICogICBsb29wIFVudGlsIHZhbGlkIGlucHV0IG9yIGxpbWl0IHJlYWNoZWRcbiAgICogICAgIEktPj5BOiBDYWxsIGFzayB3aXRoIGlucHV0XG4gICAqICAgICBBLT4+VTogUHJvbXB0IHVzZXJcbiAgICogICAgIFUtPj5BOiBQcm92aWRlIGlucHV0XG4gICAqICAgICBBLT4+STogUmV0dXJuIHJlc3VsdFxuICAgKiAgICAgSS0+PlQ6IFRlc3QgcmVzdWx0XG4gICAqICAgICBhbHQgVGVzdCBwYXNzZXNcbiAgICogICAgICAgSS0+PkM6IEFzayBmb3IgY29uZmlybWF0aW9uXG4gICAqICAgICAgIEMtPj5VOiBDb25maXJtIGlucHV0XG4gICAqICAgICAgIFUtPj5DOiBQcm92aWRlIGNvbmZpcm1hdGlvblxuICAgKiAgICAgICBDLT4+STogUmV0dXJuIGNvbmZpcm1hdGlvblxuICAgKiAgICAgICBhbHQgQ29uZmlybWVkXG4gICAqICAgICAgICAgSS0tPj5DYWxsZXI6IFJldHVybiB2YWxpZCByZXN1bHRcbiAgICogICAgICAgZWxzZSBOb3QgY29uZmlybWVkXG4gICAqICAgICAgICAgSS0+Pkk6IENvbnRpbnVlIGxvb3BcbiAgICogICAgICAgZW5kXG4gICAqICAgICBlbHNlIFRlc3QgZmFpbHNcbiAgICogICAgICAgSS0+Pkk6IENvbnRpbnVlIGxvb3BcbiAgICogICAgIGVuZFxuICAgKiAgIGVuZFxuICAgKiAgIEktLT4+Q2FsbGVyOiBSZXR1cm4gdW5kZWZpbmVkIGlmIGxpbWl0IHJlYWNoZWRcbiAgICovXG4gIHN0YXRpYyBhc3luYyBpbnNpc3Q8Uj4oXG4gICAgaW5wdXQ6IFVzZXJJbnB1dCxcbiAgICB0ZXN0OiAocmVzOiBzdHJpbmcgfCBudW1iZXIpID0+IGJvb2xlYW4sXG4gICAgZGVmYXVsdENvbmZpcm1hdGlvbjogYm9vbGVhbixcbiAgICBsaW1pdCA9IDFcbiAgKTogUHJvbWlzZTxSIHwgdW5kZWZpbmVkPiB7XG4gICAgY29uc3QgbG9nID0gVXNlcklucHV0LmxvZ2dlci5mb3IodGhpcy5pbnNpc3QpO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYEluc2lzdGluZyBvbiBpbnB1dDogJHtpbnB1dC5uYW1lfSwgdGVzdDogJHt0ZXN0LnRvU3RyaW5nKCl9LCBkZWZhdWx0Q29uZmlybWF0aW9uOiAke2RlZmF1bHRDb25maXJtYXRpb259LCBsaW1pdDogJHtsaW1pdH1gXG4gICAgKTtcbiAgICBsZXQgcmVzdWx0OiBzdHJpbmcgfCBudW1iZXIgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgbGV0IGNvdW50ID0gMDtcbiAgICBsZXQgY29uZmlybWF0aW9uOiBib29sZWFuO1xuICAgIHRyeSB7XG4gICAgICBkbyB7XG4gICAgICAgIHJlc3VsdCA9IChhd2FpdCBVc2VySW5wdXQuYXNrKGlucHV0KSlbXG4gICAgICAgICAgaW5wdXQubmFtZSBhcyBrZXlvZiBBbnN3ZXJzPHN0cmluZz5cbiAgICAgICAgXSBhcyBzdHJpbmc7XG4gICAgICAgIGlmICghdGVzdChyZXN1bHQpKSB7XG4gICAgICAgICAgcmVzdWx0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbmZpcm1hdGlvbiA9IGF3YWl0IFVzZXJJbnB1dC5hc2tDb25maXJtYXRpb24oXG4gICAgICAgICAgYCR7aW5wdXQubmFtZX0tY29uZmlybWAsXG4gICAgICAgICAgYElzIHRoZSAke2lucHV0LnR5cGV9IGNvcnJlY3Q/YCxcbiAgICAgICAgICBkZWZhdWx0Q29uZmlybWF0aW9uXG4gICAgICAgICk7XG4gICAgICAgIGlmICghY29uZmlybWF0aW9uKSByZXN1bHQgPSB1bmRlZmluZWQ7XG4gICAgICB9IHdoaWxlICh0eXBlb2YgcmVzdWx0ID09PSBcInVuZGVmaW5lZFwiICYmIGxpbWl0ID4gMSAmJiBjb3VudCsrIDwgbGltaXQpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGxvZy5lcnJvcihgRXJyb3Igd2hpbGUgaW5zaXN0aW5nOiAke2V9YCk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgcmVzdWx0ID09PSBcInVuZGVmaW5lZFwiKSBsb2cuaW5mbyhcIm5vIHNlbGVjdGlvbi4uLlwiKTtcbiAgICByZXR1cm4gcmVzdWx0IGFzIFIgfCB1bmRlZmluZWQ7XG4gIH1cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXBlYXRlZGx5IGFza3MgZm9yIHRleHQgaW5wdXQgdW50aWwgYSB2YWxpZCByZXNwb25zZSBpcyBnaXZlbiBvciB0aGUgbGltaXQgaXMgcmVhY2hlZC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgaW5zaXN0cyBvbiBnZXR0aW5nIGEgdmFsaWQgdGV4dCBpbnB1dCBmcm9tIHRoZSB1c2VyLCBhbGxvd2luZyBmb3IgYSBzcGVjaWZpZWQgbnVtYmVyIG9mIGF0dGVtcHRzLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gICAqIEBwYXJhbSBxdWVzdGlvbiAtIFRoZSBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICogQHBhcmFtIHtmdW5jdGlvbihudW1iZXIpOmJvb2xlYW59IHRlc3QgLSBWYWxpZGF0b3IgZnVuY3Rpb24gcmVjZWl2aW5nIHRoZSB1c2VyIGlucHV0IGFuZCByZXR1cm5pbmcgd2hldGhlciBpdCBpcyB2YWxpZC5cbiAgICogQHBhcmFtIG1hc2sgLSBUaGUgY2hhcmFjdGVyIHVzZWQgdG8gbWFzayB0aGUgaW5wdXQgKG9wdGlvbmFsLCBmb3IgcGFzc3dvcmQtbGlrZSBpbnB1dHMpLlxuICAgKiBAcGFyYW0gaW5pdGlhbCAtIFRoZSBpbml0aWFsIHZhbHVlIHByZXNlbnRlZCB0byB0aGUgdXNlciAob3B0aW9uYWwpLlxuICAgKiBAcGFyYW0gZGVmYXVsdENvbmZpcm1hdGlvbiAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB0aGUgY29uZmlybWF0aW9uIHByb21wdCAodHJ1ZSBmb3IgeWVzLCBmYWxzZSBmb3Igbm8pLlxuICAgKiBAcGFyYW0gbGltaXQgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgYXR0ZW1wdHMgYWxsb3dlZCAoZGVmYXVsdCBpcyAtMSwgbWVhbmluZyB1bmxpbWl0ZWQpLlxuICAgKiBAcmV0dXJuIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSB2YWxpZCBpbnB1dCBvciB1bmRlZmluZWQgaWYgdGhlIGxpbWl0IGlzIHJlYWNoZWQuXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgaW5zaXN0Rm9yVGV4dChcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgcXVlc3Rpb246IHN0cmluZyxcbiAgICB0ZXN0OiAocmVzOiBzdHJpbmcpID0+IGJvb2xlYW4sXG4gICAgbWFzazogc3RyaW5nIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkLFxuICAgIGluaXRpYWw/OiBzdHJpbmcsXG4gICAgZGVmYXVsdENvbmZpcm1hdGlvbiA9IGZhbHNlLFxuICAgIGxpbWl0ID0gLTFcbiAgKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBsb2cgPSBVc2VySW5wdXQubG9nZ2VyLmZvcih0aGlzLmluc2lzdEZvclRleHQpO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYEluc2lzdGluZyBmb3IgdGV4dCBpbnB1dDogdW5kZWZpbmVkLCBxdWVzdGlvbjogJHtxdWVzdGlvbn0sIHRlc3Q6ICR7dGVzdC50b1N0cmluZygpfSwgbWFzazogJHttYXNrfSwgaW5pdGlhbDogJHtpbml0aWFsfSwgZGVmYXVsdENvbmZpcm1hdGlvbjogJHtkZWZhdWx0Q29uZmlybWF0aW9ufSwgbGltaXQ6ICR7bGltaXR9YFxuICAgICk7XG4gICAgY29uc3QgdXNlcklucHV0ID0gbmV3IFVzZXJJbnB1dChuYW1lKS5zZXRNZXNzYWdlKHF1ZXN0aW9uKTtcblxuICAgIGlmIChtYXNrKSB1c2VySW5wdXQuc2V0TWFzayhtYXNrKTtcbiAgICBpZiAodHlwZW9mIGluaXRpYWwgPT09IFwic3RyaW5nXCIpIHVzZXJJbnB1dC5zZXRJbml0aWFsKGluaXRpYWwpO1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5pbnNpc3QoXG4gICAgICB1c2VySW5wdXQsXG4gICAgICB0ZXN0IGFzIChyZXM6IHN0cmluZyB8IG51bWJlcikgPT4gYm9vbGVhbixcbiAgICAgIGRlZmF1bHRDb25maXJtYXRpb24sXG4gICAgICBsaW1pdFxuICAgICkpIGFzIHN0cmluZztcbiAgfVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlcGVhdGVkbHkgYXNrcyBmb3IgbnVtYmVyIGlucHV0IHVudGlsIGEgdmFsaWQgcmVzcG9uc2UgaXMgZ2l2ZW4gb3IgdGhlIGxpbWl0IGlzIHJlYWNoZWQuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIGluc2lzdHMgb24gZ2V0dGluZyBhIHZhbGlkIG51bWJlciBpbnB1dCBmcm9tIHRoZSB1c2VyLCBhbGxvd2luZyBmb3IgYSBzcGVjaWZpZWQgbnVtYmVyIG9mIGF0dGVtcHRzLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gICAqIEBwYXJhbSBxdWVzdGlvbiAtIFRoZSBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICogQHBhcmFtIHRlc3QgLSBBIGZ1bmN0aW9uIHRvIHZhbGlkYXRlIHRoZSB1c2VyJ3MgaW5wdXQuXG4gICAqIEBwYXJhbSBtaW4gLSBUaGUgbWluaW11bSBhbGxvd2VkIHZhbHVlIChvcHRpb25hbCkuXG4gICAqIEBwYXJhbSBtYXggLSBUaGUgbWF4aW11bSBhbGxvd2VkIHZhbHVlIChvcHRpb25hbCkuXG4gICAqIEBwYXJhbSBpbml0aWFsIC0gVGhlIGluaXRpYWwgdmFsdWUgcHJlc2VudGVkIHRvIHRoZSB1c2VyIChvcHRpb25hbCkuXG4gICAqIEBwYXJhbSBkZWZhdWx0Q29uZmlybWF0aW9uIC0gVGhlIGRlZmF1bHQgdmFsdWUgZm9yIHRoZSBjb25maXJtYXRpb24gcHJvbXB0ICh0cnVlIGZvciB5ZXMsIGZhbHNlIGZvciBubykuXG4gICAqIEBwYXJhbSBsaW1pdCAtIFRoZSBtYXhpbXVtIG51bWJlciBvZiBhdHRlbXB0cyBhbGxvd2VkIChkZWZhdWx0IGlzIC0xLCBtZWFuaW5nIHVubGltaXRlZCkuXG4gICAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHZhbGlkIGlucHV0IG9yIHVuZGVmaW5lZCBpZiB0aGUgbGltaXQgaXMgcmVhY2hlZC5cbiAgICovXG4gIHN0YXRpYyBhc3luYyBpbnNpc3RGb3JOdW1iZXIoXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIHF1ZXN0aW9uOiBzdHJpbmcsXG4gICAgdGVzdDogKHJlczogbnVtYmVyKSA9PiBib29sZWFuLFxuICAgIG1pbj86IG51bWJlcixcbiAgICBtYXg/OiBudW1iZXIsXG4gICAgaW5pdGlhbD86IG51bWJlcixcbiAgICBkZWZhdWx0Q29uZmlybWF0aW9uID0gZmFsc2UsXG4gICAgbGltaXQgPSAtMVxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGxvZyA9IFVzZXJJbnB1dC5sb2dnZXIuZm9yKHRoaXMuaW5zaXN0Rm9yTnVtYmVyKTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBJbnNpc3RpbmcgZm9yIG51bWJlciBpbnB1dDogdW5kZWZpbmVkLCBxdWVzdGlvbjogJHtxdWVzdGlvbn0sIHRlc3Q6ICR7dGVzdC50b1N0cmluZygpfSwgbWluOiAke21pbn0sIG1heDogJHttYXh9LCBpbml0aWFsOiAke2luaXRpYWx9LCBkZWZhdWx0Q29uZmlybWF0aW9uOiAke2RlZmF1bHRDb25maXJtYXRpb259LCBsaW1pdDogJHtsaW1pdH1gXG4gICAgKTtcbiAgICBjb25zdCB1c2VySW5wdXQgPSBuZXcgVXNlcklucHV0KG5hbWUpXG4gICAgICAuc2V0TWVzc2FnZShxdWVzdGlvbilcbiAgICAgIC5zZXRUeXBlKFwibnVtYmVyXCIpO1xuXG4gICAgaWYgKHR5cGVvZiBtaW4gPT09IFwibnVtYmVyXCIpIHVzZXJJbnB1dC5zZXRNaW4obWluKTtcblxuICAgIGlmICh0eXBlb2YgbWF4ID09PSBcIm51bWJlclwiKSB1c2VySW5wdXQuc2V0TWF4KG1heCk7XG5cbiAgICBpZiAodHlwZW9mIGluaXRpYWwgPT09IFwibnVtYmVyXCIpIHVzZXJJbnB1dC5zZXRJbml0aWFsKGluaXRpYWwpO1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5pbnNpc3QoXG4gICAgICB1c2VySW5wdXQsXG4gICAgICB0ZXN0IGFzIChyZXM6IHN0cmluZyB8IG51bWJlcikgPT4gYm9vbGVhbixcbiAgICAgIGRlZmF1bHRDb25maXJtYXRpb24sXG4gICAgICBsaW1pdFxuICAgICkpIGFzIG51bWJlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUGFyc2VzIGNvbW1hbmQtbGluZSBhcmd1bWVudHMgYmFzZWQgb24gdGhlIHByb3ZpZGVkIG9wdGlvbnMuXG4gICAqIEBzdW1tYXJ5IFVzZXMgTm9kZS5qcydzIHV0aWwucGFyc2VBcmdzIHRvIHBhcnNlIGNvbW1hbmQtbGluZSBhcmd1bWVudHMgYW5kIHJldHVybiB0aGUgcmVzdWx0LlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgcGFyc2luZyBhcmd1bWVudHMuXG4gICAqIEByZXR1cm4gQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIHBhcnNlZCBhcmd1bWVudHMuXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IEMgYXMgQ2FsbGVyXG4gICAqICAgcGFydGljaXBhbnQgUCBhcyBwYXJzZUFyZ3MgbWV0aG9kXG4gICAqICAgcGFydGljaXBhbnQgVSBhcyB1dGlsLnBhcnNlQXJnc1xuICAgKiAgIEMtPj5QOiBDYWxsIHdpdGggb3B0aW9uc1xuICAgKiAgIFAtPj5QOiBQcmVwYXJlIGFyZ3Mgb2JqZWN0XG4gICAqICAgUC0+PlU6IENhbGwgcGFyc2VBcmdzIHdpdGggcHJlcGFyZWQgYXJnc1xuICAgKiAgIFUtPj5QOiBSZXR1cm4gcGFyc2VkIHJlc3VsdFxuICAgKiAgIFAtLT4+QzogUmV0dXJuIFBhcnNlQXJnc1Jlc3VsdFxuICAgKi9cbiAgc3RhdGljIHBhcnNlQXJncyhvcHRpb25zOiBQYXJzZUFyZ3NPcHRpb25zQ29uZmlnKTogUGFyc2VBcmdzUmVzdWx0IHtcbiAgICBjb25zdCBsb2cgPSBVc2VySW5wdXQubG9nZ2VyLmZvcih0aGlzLnBhcnNlQXJncyk7XG4gICAgY29uc3QgYXJnczogUGFyc2VBcmdzQ29uZmlnID0ge1xuICAgICAgYXJnczogcHJvY2Vzcy5hcmd2LnNsaWNlKDIpLFxuICAgICAgb3B0aW9uczogb3B0aW9ucyxcbiAgICB9O1xuICAgIGxvZy5kZWJ1ZyhgUGFyc2luZyBhcmd1bWVudHM6ICR7SlNPTi5zdHJpbmdpZnkoYXJncywgbnVsbCwgMil9YCk7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBwYXJzZUFyZ3MoYXJncyk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgYEVycm9yIHdoaWxlIHBhcnNpbmcgYXJndW1lbnRzOlxcbiR7SlNPTi5zdHJpbmdpZnkoYXJncywgbnVsbCwgMil9XFxuIHwgb3B0aW9uc1xcbiR7SlNPTi5zdHJpbmdpZnkob3B0aW9ucywgbnVsbCwgMil9XFxuIHwgJHtlcnJvcn1gXG4gICAgICApO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciB3aGlsZSBwYXJzaW5nIGFyZ3VtZW50czogJHtlcnJvcn1gKTtcbiAgICB9XG4gIH1cbn1cbiIsIi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgY29tbWFuZCBvcHRpb25zIGZvciBDTEkgY29tbWFuZHMuXG4gKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSBzdHJ1Y3R1cmUgYW5kIGRlZmF1bHQgdmFsdWVzIGZvciBjb21tb24gY29tbWFuZC1saW5lIG9wdGlvbnMgdXNlZCBhY3Jvc3MgdmFyaW91cyBDTEkgY29tbWFuZHMuXG4gKiBAY29uc3QgRGVmYXVsdENvbW1hbmRPcHRpb25zXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBEZWZhdWx0Q29tbWFuZE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSB2ZXJib3NlIC0gVmVyYm9zaXR5IGxldmVsIG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB2ZXJib3NlLnR5cGUgLSBUaGUgdHlwZSBvZiB0aGUgdmVyYm9zZSBvcHRpb24gKG51bWJlcikuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdmVyYm9zZS5zaG9ydCAtIFRoZSBzaG9ydCBmbGFnIGZvciB0aGUgdmVyYm9zZSBvcHRpb24gKFYpLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IHZlcmJvc2UuZGVmYXVsdCAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB2ZXJib3NpdHkgKDApLlxuICogQHByb3BlcnR5IHtPYmplY3R9IHZlcnNpb24gLSBWZXJzaW9uIGRpc3BsYXkgb3B0aW9uLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHZlcnNpb24udHlwZSAtIFRoZSB0eXBlIG9mIHRoZSB2ZXJzaW9uIG9wdGlvbiAoYm9vbGVhbikuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdmVyc2lvbi5zaG9ydCAtIFRoZSBzaG9ydCBmbGFnIGZvciB0aGUgdmVyc2lvbiBvcHRpb24gKHYpLlxuICogQHByb3BlcnR5IHt1bmRlZmluZWR9IHZlcnNpb24uZGVmYXVsdCAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB2ZXJzaW9uIGRpc3BsYXkgKHVuZGVmaW5lZCkuXG4gKiBAcHJvcGVydHkge09iamVjdH0gaGVscCAtIEhlbHAgZGlzcGxheSBvcHRpb24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gaGVscC50eXBlIC0gVGhlIHR5cGUgb2YgdGhlIGhlbHAgb3B0aW9uIChib29sZWFuKS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBoZWxwLnNob3J0IC0gVGhlIHNob3J0IGZsYWcgZm9yIHRoZSBoZWxwIG9wdGlvbiAoaCkuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGhlbHAuZGVmYXVsdCAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciBoZWxwIGRpc3BsYXkgKGZhbHNlKS5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBsb2dMZXZlbCAtIExvZyBsZXZlbCBvcHRpb24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gbG9nTGV2ZWwudHlwZSAtIFRoZSB0eXBlIG9mIHRoZSBsb2dMZXZlbCBvcHRpb24gKHN0cmluZykuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gbG9nTGV2ZWwuZGVmYXVsdCAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciBsb2cgbGV2ZWwgKFwiaW5mb1wiKS5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBsb2dTdHlsZSAtIExvZyBzdHlsaW5nIG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBsb2dTdHlsZS50eXBlIC0gVGhlIHR5cGUgb2YgdGhlIGxvZ1N0eWxlIG9wdGlvbiAoYm9vbGVhbikuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGxvZ1N0eWxlLmRlZmF1bHQgLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgbG9nIHN0eWxpbmcgKHRydWUpLlxuICogQHByb3BlcnR5IHtPYmplY3R9IHRpbWVzdGFtcCAtIFRpbWVzdGFtcCBkaXNwbGF5IG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB0aW1lc3RhbXAudHlwZSAtIFRoZSB0eXBlIG9mIHRoZSB0aW1lc3RhbXAgb3B0aW9uIChib29sZWFuKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gdGltZXN0YW1wLmRlZmF1bHQgLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgdGltZXN0YW1wIGRpc3BsYXkgKHRydWUpLlxuICogQHByb3BlcnR5IHtPYmplY3R9IGJhbm5lciAtIEJhbm5lciBkaXNwbGF5IG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBiYW5uZXIudHlwZSAtIFRoZSB0eXBlIG9mIHRoZSBiYW5uZXIgb3B0aW9uIChib29sZWFuKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gYmFubmVyLmRlZmF1bHQgLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgYmFubmVyIGRpc3BsYXkgKGZhbHNlKS5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGNvbnN0IERlZmF1bHRDb21tYW5kT3B0aW9ucyA9IHtcbiAgdmVyYm9zZToge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICAgIHNob3J0OiBcIlZcIixcbiAgICBkZWZhdWx0OiB1bmRlZmluZWQsXG4gIH0sXG4gIHZlcnNpb246IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgICBzaG9ydDogXCJ2XCIsXG4gICAgZGVmYXVsdDogdW5kZWZpbmVkLFxuICB9LFxuICBoZWxwOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgc2hvcnQ6IFwiaFwiLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxuICBsb2dMZXZlbDoge1xuICAgIHR5cGU6IFwic3RyaW5nXCIsXG4gICAgZGVmYXVsdDogXCJpbmZvXCIsXG4gIH0sXG4gIGxvZ1N0eWxlOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgfSxcbiAgdGltZXN0YW1wOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgfSxcbiAgYmFubmVyOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgfSxcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgY29tbWFuZCB2YWx1ZXMgZGVyaXZlZCBmcm9tIERlZmF1bHRDb21tYW5kT3B0aW9ucy5cbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYW4gb2JqZWN0IHdpdGggdGhlIGRlZmF1bHQgdmFsdWVzIG9mIGFsbCBvcHRpb25zIGRlZmluZWQgaW4gRGVmYXVsdENvbW1hbmRPcHRpb25zLlxuICogQGNvbnN0IERlZmF1bHRDb21tYW5kVmFsdWVzXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBEZWZhdWx0Q29tbWFuZFZhbHVlc1xuICogQHByb3BlcnR5IHt1bmtub3dufSBba2V5OiBzdHJpbmddIC0gVGhlIGRlZmF1bHQgdmFsdWUgZm9yIGVhY2ggb3B0aW9uIGluIERlZmF1bHRDb21tYW5kT3B0aW9ucy5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGNvbnN0IERlZmF1bHRDb21tYW5kVmFsdWVzOiB7XG4gIFtrIGluIGtleW9mIHR5cGVvZiBEZWZhdWx0Q29tbWFuZE9wdGlvbnNdOiB1bmtub3duO1xufSA9IE9iamVjdC5rZXlzKERlZmF1bHRDb21tYW5kT3B0aW9ucykucmVkdWNlKFxuICAoYWNjOiBSZWNvcmQ8a2V5b2YgdHlwZW9mIERlZmF1bHRDb21tYW5kT3B0aW9ucywgdW5rbm93bj4sIGtleTogc3RyaW5nKSA9PiB7XG4gICAgYWNjW2tleSBhcyBrZXlvZiB0eXBlb2YgRGVmYXVsdENvbW1hbmRPcHRpb25zXSA9XG4gICAgICBEZWZhdWx0Q29tbWFuZE9wdGlvbnNba2V5IGFzIGtleW9mIHR5cGVvZiBEZWZhdWx0Q29tbWFuZE9wdGlvbnNdLmRlZmF1bHQ7XG4gICAgcmV0dXJuIGFjYztcbiAgfSxcbiAge30gYXMgUmVjb3JkPGtleW9mIHR5cGVvZiBEZWZhdWx0Q29tbWFuZFZhbHVlcywgdW5rbm93bj5cbik7XG4iLCIvKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IGVuY29kaW5nIGZvciB0ZXh0IG9wZXJhdGlvbnMuXG4gKiBAc3VtbWFyeSBUaGUgc3RhbmRhcmQgVVRGLTggZW5jb2RpbmcgdXNlZCBmb3IgdGV4dCBwcm9jZXNzaW5nLlxuICogQGNvbnN0IHtzdHJpbmd9IEVuY29kaW5nXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBFbmNvZGluZyA9IFwidXRmLThcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVndWxhciBleHByZXNzaW9uIGZvciBzZW1hbnRpYyB2ZXJzaW9uaW5nLlxuICogQHN1bW1hcnkgQSByZWdleCBwYXR0ZXJuIHRvIG1hdGNoIGFuZCBwYXJzZSBzZW1hbnRpYyB2ZXJzaW9uIHN0cmluZ3MuXG4gKiBAY29uc3Qge1JlZ0V4cH0gU2VtVmVyc2lvblJlZ2V4XG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBTZW1WZXJzaW9uUmVnZXggPVxuICAvXihcXGQrKVxcLihcXGQrKVxcLihcXGQrKSg/Oi0oWzAtOUEtWmEtei1dKyg/OlxcLlswLTlBLVphLXpdKSkpL2c7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVudW0gZm9yIHNlbWFudGljIHZlcnNpb24gY29tcG9uZW50cy5cbiAqIEBzdW1tYXJ5IERlZmluZXMgdGhlIHRocmVlIGxldmVscyBvZiBzZW1hbnRpYyB2ZXJzaW9uaW5nOiBQQVRDSCwgTUlOT1IsIGFuZCBNQUpPUi5cbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBlbnVtIFNlbVZlcnNpb24ge1xuICAvKiogUGF0Y2ggdmVyc2lvbiBmb3IgYmFja3dhcmRzLWNvbXBhdGlibGUgYnVnIGZpeGVzLiAqL1xuICBQQVRDSCA9IFwicGF0Y2hcIixcbiAgLyoqIE1pbm9yIHZlcnNpb24gZm9yIGJhY2t3YXJkcy1jb21wYXRpYmxlIG5ldyBmZWF0dXJlcy4gKi9cbiAgTUlOT1IgPSBcIm1pbm9yXCIsXG4gIC8qKiBNYWpvciB2ZXJzaW9uIGZvciBjaGFuZ2VzIHRoYXQgYnJlYWsgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkuICovXG4gIE1BSk9SID0gXCJtYWpvclwiLFxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBGbGFnIHRvIGluZGljYXRlIG5vbi1DSSBlbnZpcm9ubWVudC5cbiAqIEBzdW1tYXJ5IFVzZWQgdG8gc3BlY2lmeSB0aGF0IGEgY29tbWFuZCBzaG91bGQgcnVuIG91dHNpZGUgb2YgYSBDb250aW51b3VzIEludGVncmF0aW9uIGVudmlyb25tZW50LlxuICogQGNvbnN0IHtzdHJpbmd9IE5vQ0lGTGFnXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBOb0NJRkxhZyA9IFwiLW5vLWNpXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEtleSBmb3IgdGhlIHNldHVwIHNjcmlwdCBpbiBwYWNrYWdlLmpzb24uXG4gKiBAc3VtbWFyeSBJZGVudGlmaWVzIHRoZSBzY3JpcHQgdGhhdCBydW5zIGFmdGVyIHBhY2thZ2UgaW5zdGFsbGF0aW9uLlxuICogQGNvbnN0IHtzdHJpbmd9IFNldHVwU2NyaXB0S2V5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBTZXR1cFNjcmlwdEtleSA9IFwicG9zdGluc3RhbGxcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRW51bSBmb3IgdmFyaW91cyBhdXRoZW50aWNhdGlvbiB0b2tlbnMuXG4gKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSBmaWxlIG5hbWVzIGZvciBzdG9yaW5nIGRpZmZlcmVudCB0eXBlcyBvZiBhdXRoZW50aWNhdGlvbiB0b2tlbnMuXG4gKiBAZW51bSB7c3RyaW5nfVxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZW51bSBUb2tlbnMge1xuICAvKiogR2l0IGF1dGhlbnRpY2F0aW9uIHRva2VuIGZpbGUgbmFtZS4gKi9cbiAgR0lUID0gXCIudG9rZW5cIixcbiAgLyoqIE5QTSBhdXRoZW50aWNhdGlvbiB0b2tlbiBmaWxlIG5hbWUuICovXG4gIE5QTSA9IFwiLm5wbXRva2VuXCIsXG4gIC8qKiBEb2NrZXIgYXV0aGVudGljYXRpb24gdG9rZW4gZmlsZSBuYW1lLiAqL1xuICBET0NLRVIgPSBcIi5kb2NrZXJ0b2tlblwiLFxuICAvKiogQ29uZmx1ZW5jZSBhdXRoZW50aWNhdGlvbiB0b2tlbiBmaWxlIG5hbWUuICovXG4gIENPTkZMVUVOQ0UgPSBcIi5jb25mbHVlbmNlLXRva2VuXCIsXG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvZGUgdXNlZCB0byBpbmRpY2F0ZSBhbiBvcGVyYXRpb24gd2FzIGFib3J0ZWQuXG4gKiBAc3VtbWFyeSBTdGFuZGFyZCBtZXNzYWdlIHVzZWQgd2hlbiBhIHByb2Nlc3MgaXMgbWFudWFsbHkgdGVybWluYXRlZC5cbiAqIEBjb25zdCB7c3RyaW5nfSBBYm9ydENvZGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGNvbnN0IEFib3J0Q29kZSA9IFwiQWJvcnRlZFwiO1xuIiwiaW1wb3J0IHsgRW5jb2RpbmcgfSBmcm9tIFwiLi4vdXRpbHMvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBPdXRwdXRXcml0ZXIgfSBmcm9tIFwiLi9PdXRwdXRXcml0ZXJcIjtcbmltcG9ydCB7IFByb21pc2VFeGVjdXRvciB9IGZyb20gXCIuLi91dGlscy90eXBlc1wiO1xuaW1wb3J0IHsgT3V0cHV0VHlwZSB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBzdHlsZSB9IGZyb20gXCJzdHlsZWQtc3RyaW5nLWJ1aWxkZXJcIjtcbmltcG9ydCB7IExvZ2dlciwgTG9nZ2luZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBIHN0YW5kYXJkIG91dHB1dCB3cml0ZXIgZm9yIGhhbmRsaW5nIGNvbW1hbmQgZXhlY3V0aW9uIG91dHB1dC5cbiAqIEBzdW1tYXJ5IFRoaXMgY2xhc3MgaW1wbGVtZW50cyB0aGUgT3V0cHV0V3JpdGVyIGludGVyZmFjZSBhbmQgcHJvdmlkZXMgbWV0aG9kcyBmb3JcbiAqIGhhbmRsaW5nIHZhcmlvdXMgdHlwZXMgb2Ygb3V0cHV0IGZyb20gY29tbWFuZCBleGVjdXRpb24sIGluY2x1ZGluZyBzdGFuZGFyZCBvdXRwdXQsXG4gKiBlcnJvciBvdXRwdXQsIGFuZCBleGl0IGNvZGVzLiBJdCBhbHNvIGluY2x1ZGVzIHV0aWxpdHkgbWV0aG9kcyBmb3IgcGFyc2luZyBjb21tYW5kc1xuICogYW5kIHJlc29sdmluZyBvciByZWplY3RpbmcgcHJvbWlzZXMgYmFzZWQgb24gZXhlY3V0aW9uIHJlc3VsdHMuXG4gKlxuICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgcmVzb2x2ZWQgdmFsdWUsIGRlZmF1bHRpbmcgdG8gc3RyaW5nLlxuICpcbiAqIEBwYXJhbSBjbWQgLSBUaGUgY29tbWFuZCBzdHJpbmcgdG8gYmUgZXhlY3V0ZWQuXG4gKiBAcGFyYW0gbG9jayAtIEEgUHJvbWlzZUV4ZWN1dG9yIHRvIGNvbnRyb2wgdGhlIGFzeW5jaHJvbm91cyBmbG93LlxuICogQHBhcmFtIGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyAodW51c2VkIGluIHRoZSBjdXJyZW50IGltcGxlbWVudGF0aW9uKS5cbiAqXG4gKiBAY2xhc3NcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBTdGFuZGFyZE91dHB1dFdyaXRlciB9IGZyb20gJ0BkZWNhZi10cy91dGlscyc7XG4gKiBpbXBvcnQgeyBQcm9taXNlRXhlY3V0b3IgfSBmcm9tICdAZGVjYWYtdHMvdXRpbHMnO1xuICogXG4gKiAvLyBDcmVhdGUgYSBwcm9taXNlIGV4ZWN1dG9yXG4gKiBjb25zdCBleGVjdXRvcjogUHJvbWlzZUV4ZWN1dG9yPHN0cmluZz4gPSB7XG4gKiAgIHJlc29sdmU6ICh2YWx1ZSkgPT4gY29uc29sZS5sb2coYFJlc29sdmVkOiAke3ZhbHVlfWApLFxuICogICByZWplY3Q6IChlcnJvcikgPT4gY29uc29sZS5lcnJvcihgUmVqZWN0ZWQ6ICR7ZXJyb3IubWVzc2FnZX1gKVxuICogfTtcbiAqIFxuICogLy8gQ3JlYXRlIGEgc3RhbmRhcmQgb3V0cHV0IHdyaXRlclxuICogY29uc3Qgd3JpdGVyID0gbmV3IFN0YW5kYXJkT3V0cHV0V3JpdGVyKCdscyAtbGEnLCBleGVjdXRvcik7XG4gKiBcbiAqIC8vIFVzZSB0aGUgd3JpdGVyIHRvIGhhbmRsZSBjb21tYW5kIG91dHB1dFxuICogd3JpdGVyLmRhdGEoJ0ZpbGUgbGlzdCBvdXRwdXQuLi4nKTtcbiAqIHdyaXRlci5leGl0KDAsIFsnQ29tbWFuZCBleGVjdXRlZCBzdWNjZXNzZnVsbHknXSk7XG4gKiBgYGBcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICogICBwYXJ0aWNpcGFudCBTdGFuZGFyZE91dHB1dFdyaXRlclxuICogICBwYXJ0aWNpcGFudCBMb2dnZXJcbiAqICAgcGFydGljaXBhbnQgUHJvbWlzZUV4ZWN1dG9yXG4gKiAgIFxuICogICBDbGllbnQtPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogbmV3IFN0YW5kYXJkT3V0cHV0V3JpdGVyKGNtZCwgbG9jaylcbiAqICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5Mb2dnZXI6IExvZ2dpbmcuZm9yKGNtZClcbiAqICAgXG4gKiAgIENsaWVudC0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiBkYXRhKGNodW5rKVxuICogICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiBsb2coXCJzdGRvdXRcIiwgY2h1bmspXG4gKiAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+TG9nZ2VyOiBsb2dnZXIuaW5mbyhsb2cpXG4gKiAgIFxuICogICBDbGllbnQtPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogZXJyb3IoY2h1bmspXG4gKiAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IGxvZyhcInN0ZGVyclwiLCBjaHVuaylcbiAqICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5Mb2dnZXI6IGxvZ2dlci5pbmZvKGxvZylcbiAqICAgXG4gKiAgIENsaWVudC0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiBleGl0KGNvZGUsIGxvZ3MpXG4gKiAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IGxvZyhcInN0ZG91dFwiLCBleGl0TWVzc2FnZSlcbiAqICAgYWx0IGNvZGUgPT09IDBcbiAqICAgICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiByZXNvbHZlKGxvZ3MpXG4gKiAgICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5Qcm9taXNlRXhlY3V0b3I6IGxvY2sucmVzb2x2ZShyZWFzb24pXG4gKiAgIGVsc2UgY29kZSAhPT0gMFxuICogICAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IHJlamVjdChlcnJvcilcbiAqICAgICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PlByb21pc2VFeGVjdXRvcjogbG9jay5yZWplY3QocmVhc29uKVxuICogICBlbmRcbiAqL1xuZXhwb3J0IGNsYXNzIFN0YW5kYXJkT3V0cHV0V3JpdGVyPFIgPSBzdHJpbmc+IGltcGxlbWVudHMgT3V0cHV0V3JpdGVyIHtcbiAgcHJvdGVjdGVkIGxvZ2dlcjogTG9nZ2VyO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBjbWQ6IHN0cmluZyxcbiAgICBwcm90ZWN0ZWQgbG9jazogUHJvbWlzZUV4ZWN1dG9yPFI+LFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAuLi5hcmdzOiB1bmtub3duW11cbiAgKSB7XG4gICAgdGhpcy5sb2dnZXIgPSBMb2dnaW5nLmZvcih0aGlzLmNtZCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExvZ3Mgb3V0cHV0IHRvIHRoZSBjb25zb2xlLlxuICAgKiBAc3VtbWFyeSBGb3JtYXRzIGFuZCBsb2dzIHRoZSBnaXZlbiBkYXRhIHdpdGggYSB0aW1lc3RhbXAgYW5kIHR5cGUgaW5kaWNhdG9yLlxuICAgKlxuICAgKiBAcGFyYW0gdHlwZSAtIFRoZSB0eXBlIG9mIG91dHB1dCAoc3Rkb3V0IG9yIHN0ZGVycikuXG4gICAqIEBwYXJhbSBkYXRhIC0gVGhlIGRhdGEgdG8gYmUgbG9nZ2VkLlxuICAgKi9cbiAgcHJvdGVjdGVkIGxvZyh0eXBlOiBPdXRwdXRUeXBlLCBkYXRhOiBzdHJpbmcgfCBCdWZmZXIpIHtcbiAgICBkYXRhID0gQnVmZmVyLmlzQnVmZmVyKGRhdGEpID8gZGF0YS50b1N0cmluZyhFbmNvZGluZykgOiBkYXRhO1xuICAgIGNvbnN0IGxvZyA9IHR5cGUgPT09IFwic3RkZXJyXCIgPyBzdHlsZShkYXRhKS5yZWQudGV4dCA6IGRhdGE7XG4gICAgdGhpcy5sb2dnZXIuaW5mbyhsb2cpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBIYW5kbGVzIHN0YW5kYXJkIG91dHB1dCBkYXRhLlxuICAgKiBAc3VtbWFyeSBMb2dzIHRoZSBnaXZlbiBjaHVuayBhcyBzdGFuZGFyZCBvdXRwdXQuXG4gICAqXG4gICAqIEBwYXJhbSBjaHVuayAtIFRoZSBkYXRhIGNodW5rIHRvIGJlIGxvZ2dlZC5cbiAgICovXG4gIGRhdGEoY2h1bms6IGFueSkge1xuICAgIHRoaXMubG9nKFwic3Rkb3V0XCIsIFN0cmluZyhjaHVuaykpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBIYW5kbGVzIGVycm9yIG91dHB1dCBkYXRhLlxuICAgKiBAc3VtbWFyeSBMb2dzIHRoZSBnaXZlbiBjaHVuayBhcyBlcnJvciBvdXRwdXQuXG4gICAqXG4gICAqIEBwYXJhbSBjaHVuayAtIFRoZSBlcnJvciBkYXRhIGNodW5rIHRvIGJlIGxvZ2dlZC5cbiAgICovXG4gIGVycm9yKGNodW5rOiBhbnkpIHtcbiAgICB0aGlzLmxvZyhcInN0ZGVyclwiLCBTdHJpbmcoY2h1bmspKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBlcnJvciBvYmplY3RzLlxuICAgKiBAc3VtbWFyeSBMb2dzIHRoZSBlcnJvciBtZXNzYWdlIGZyb20gdGhlIGdpdmVuIEVycm9yIG9iamVjdC5cbiAgICpcbiAgICogQHBhcmFtIGVyciAtIFRoZSBFcnJvciBvYmplY3QgdG8gYmUgbG9nZ2VkLlxuICAgKi9cbiAgZXJyb3JzKGVycjogRXJyb3IpIHtcbiAgICB0aGlzLmxvZyhcInN0ZGVyclwiLCBgRXJyb3IgZXhlY3V0aW5nIGNvbW1hbmQgZXhpdGVkIDogJHtlcnJ9YCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgdGhlIGV4aXQgb2YgYSBjb21tYW5kLlxuICAgKiBAc3VtbWFyeSBMb2dzIHRoZSBleGl0IGNvZGUgYW5kIHJlc29sdmVzIG9yIHJlamVjdHMgdGhlIHByb21pc2UgYmFzZWQgb24gdGhlIGNvZGUuXG4gICAqXG4gICAqIEBwYXJhbSBjb2RlIC0gVGhlIGV4aXQgY29kZSBvZiB0aGUgY29tbWFuZC5cbiAgICogQHBhcmFtIGxvZ3MgLSBBcnJheSBvZiBsb2cgbWVzc2FnZXMgdG8gYmUgcHJvY2Vzc2VkIGJlZm9yZSBleGl0aW5nLlxuICAgKi9cbiAgZXhpdChjb2RlOiBudW1iZXIgfCBzdHJpbmcsIGxvZ3M6IHN0cmluZ1tdKSB7XG4gICAgdGhpcy5sb2coXG4gICAgICBcInN0ZG91dFwiLFxuICAgICAgYGNvbW1hbmQgZXhpdGVkIGNvZGUgOiAke2NvZGUgPT09IDAgPyBzdHlsZShjb2RlLnRvU3RyaW5nKCkpLmdyZWVuLnRleHQgOiBzdHlsZShjb2RlID09PSBudWxsID8gXCJudWxsXCIgOiBjb2RlLnRvU3RyaW5nKCkpLnJlZC50ZXh0fWBcbiAgICApO1xuICAgIGlmIChjb2RlID09PSAwKSB7XG4gICAgICB0aGlzLnJlc29sdmUobG9ncy5tYXAoKGwpID0+IGwudHJpbSgpKS5qb2luKFwiXFxuXCIpIGFzIFIpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlamVjdChuZXcgRXJyb3IobG9ncy5sZW5ndGggPyBsb2dzLmpvaW4oXCJcXG5cIikgOiBjb2RlLnRvU3RyaW5nKCkpKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBhcnNlcyBhIGNvbW1hbmQgc3RyaW5nIG9yIGFycmF5IGludG8gY29tcG9uZW50cy5cbiAgICogQHN1bW1hcnkgQ29udmVydHMgdGhlIGNvbW1hbmQgaW50byBhIGNvbnNpc3RlbnQgZm9ybWF0IGFuZCBzdG9yZXMgaXQsIHRoZW4gcmV0dXJucyBpdCBzcGxpdCBpbnRvIGNvbW1hbmQgYW5kIGFyZ3VtZW50cy5cbiAgICpcbiAgICogQHBhcmFtIGNvbW1hbmQgLSBUaGUgY29tbWFuZCBhcyBhIHN0cmluZyBvciBhcnJheSBvZiBzdHJpbmdzLlxuICAgKiBAcmV0dXJuIEEgdHVwbGUgY29udGFpbmluZyB0aGUgY29tbWFuZCBhbmQgaXRzIGFyZ3VtZW50cyBhcyBzZXBhcmF0ZSBlbGVtZW50cy5cbiAgICovXG4gIHBhcnNlQ29tbWFuZChjb21tYW5kOiBzdHJpbmcgfCBzdHJpbmdbXSk6IFtzdHJpbmcsIHN0cmluZ1tdXSB7XG4gICAgY29tbWFuZCA9IHR5cGVvZiBjb21tYW5kID09PSBcInN0cmluZ1wiID8gY29tbWFuZC5zcGxpdChcIiBcIikgOiBjb21tYW5kO1xuICAgIHRoaXMuY21kID0gY29tbWFuZC5qb2luKFwiIFwiKTtcbiAgICByZXR1cm4gW2NvbW1hbmRbMF0sIGNvbW1hbmQuc2xpY2UoMSldO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXNvbHZlcyB0aGUgcHJvbWlzZSB3aXRoIGEgc3VjY2VzcyBtZXNzYWdlLlxuICAgKiBAc3VtbWFyeSBMb2dzIGEgc3VjY2VzcyBtZXNzYWdlIGFuZCByZXNvbHZlcyB0aGUgcHJvbWlzZSB3aXRoIHRoZSBnaXZlbiByZWFzb24uXG4gICAqXG4gICAqIEBwYXJhbSByZWFzb24gLSBUaGUgcmVhc29uIGZvciByZXNvbHZpbmcgdGhlIHByb21pc2UuXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVzb2x2ZShyZWFzb246IFIpIHtcbiAgICB0aGlzLmxvZyhcbiAgICAgIFwic3Rkb3V0XCIsXG4gICAgICBgJHt0aGlzLmNtZH0gZXhlY3V0ZWQgc3VjY2Vzc2Z1bGx5OiAke3N0eWxlKHJlYXNvbiA/IFwicmFuIHRvIGNvbXBsZXRpb25cIiA6IChyZWFzb24gYXMgc3RyaW5nKSkuZ3JlZW59YFxuICAgICk7XG4gICAgdGhpcy5sb2NrLnJlc29sdmUocmVhc29uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVqZWN0cyB0aGUgcHJvbWlzZSB3aXRoIGFuIGVycm9yIG1lc3NhZ2UuXG4gICAqIEBzdW1tYXJ5IExvZ3MgYW4gZXJyb3IgbWVzc2FnZSBhbmQgcmVqZWN0cyB0aGUgcHJvbWlzZSB3aXRoIHRoZSBnaXZlbiByZWFzb24uXG4gICAqXG4gICAqIEBwYXJhbSByZWFzb24gLSBUaGUgcmVhc29uIGZvciByZWplY3RpbmcgdGhlIHByb21pc2UsIGVpdGhlciBhIG51bWJlciAoZXhpdCBjb2RlKSBvciBhIHN0cmluZy5cbiAgICovXG4gIHByb3RlY3RlZCByZWplY3QocmVhc29uOiBudW1iZXIgfCBzdHJpbmcgfCBFcnJvcikge1xuICAgIGlmICghKHJlYXNvbiBpbnN0YW5jZW9mIEVycm9yKSkge1xuICAgICAgcmVhc29uID0gbmV3IEVycm9yKFxuICAgICAgICB0eXBlb2YgcmVhc29uID09PSBcIm51bWJlclwiID8gYEV4aXQgY29kZSAke3JlYXNvbn1gIDogcmVhc29uXG4gICAgICApO1xuICAgIH1cbiAgICB0aGlzLmxvZyhcbiAgICAgIFwic3RkZXJyXCIsXG4gICAgICBgJHt0aGlzLmNtZH0gZmFpbGVkIHRvIGV4ZWN1dGU6ICR7c3R5bGUocmVhc29uLm1lc3NhZ2UpLnJlZH1gXG4gICAgKTtcbiAgICB0aGlzLmxvY2sucmVqZWN0KHJlYXNvbik7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIENoaWxkUHJvY2Vzc1dpdGhvdXROdWxsU3RyZWFtcyxcbiAgc3Bhd24sXG4gIFNwYXduT3B0aW9uc1dpdGhvdXRTdGRpbyxcbn0gZnJvbSBcImNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IFN0YW5kYXJkT3V0cHV0V3JpdGVyIH0gZnJvbSBcIi4uL3dyaXRlcnMvU3RhbmRhcmRPdXRwdXRXcml0ZXJcIjtcbmltcG9ydCB7IENvbW1hbmRSZXN1bHQgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgT3V0cHV0V3JpdGVyQ29uc3RydWN0b3IgfSBmcm9tIFwiLi4vd3JpdGVycy90eXBlc1wiO1xuaW1wb3J0IHsgQWJvcnRDb2RlIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBMb2dnZXIsIExvZ2dpbmcgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIGxvY2tlZCB2ZXJzaW9uIG9mIGEgZnVuY3Rpb24uXG4gKiBAc3VtbWFyeSBUaGlzIGhpZ2hlci1vcmRlciBmdW5jdGlvbiB0YWtlcyBhIGZ1bmN0aW9uIGFuZCByZXR1cm5zIGEgbmV3IGZ1bmN0aW9uIHRoYXQgZW5zdXJlc1xuICogc2VxdWVudGlhbCBleGVjdXRpb24gb2YgdGhlIG9yaWdpbmFsIGZ1bmN0aW9uLCBldmVuIHdoZW4gY2FsbGVkIG11bHRpcGxlIHRpbWVzIGNvbmN1cnJlbnRseS5cbiAqIEl0IHVzZXMgYSBQcm9taXNlLWJhc2VkIGxvY2tpbmcgbWVjaGFuaXNtIHRvIHF1ZXVlIGZ1bmN0aW9uIGNhbGxzLlxuICpcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJldHVybiB0eXBlIG9mIHRoZSBpbnB1dCBmdW5jdGlvbi5cbiAqXG4gKiBAcGFyYW0gZiAtIFRoZSBmdW5jdGlvbiB0byBiZSBsb2NrZWQuIEl0IGNhbiB0YWtlIGFueSBudW1iZXIgb2YgcGFyYW1ldGVycyBhbmQgcmV0dXJuIGEgdmFsdWUgb2YgdHlwZSBSLlxuICogQHJldHVybiBBIG5ldyBmdW5jdGlvbiB3aXRoIHRoZSBzYW1lIHNpZ25hdHVyZSBhcyB0aGUgaW5wdXQgZnVuY3Rpb24sIGJ1dCB3aXRoIHNlcXVlbnRpYWwgZXhlY3V0aW9uIGd1YXJhbnRlZWQuXG4gKlxuICogQGZ1bmN0aW9uIGxvY2tpZnlcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBMb2NrZWRGdW5jdGlvblxuICogICBwYXJ0aWNpcGFudCBPcmlnaW5hbEZ1bmN0aW9uXG4gKiAgIENhbGxlci0+PkxvY2tlZEZ1bmN0aW9uOiBDYWxsIHdpdGggcGFyYW1zXG4gKiAgIExvY2tlZEZ1bmN0aW9uLT4+TG9ja2VkRnVuY3Rpb246IENoZWNrIGN1cnJlbnQgbG9ja1xuICogICBhbHQgTG9jayBpcyByZXNvbHZlZFxuICogICAgIExvY2tlZEZ1bmN0aW9uLT4+T3JpZ2luYWxGdW5jdGlvbjogRXhlY3V0ZSB3aXRoIHBhcmFtc1xuICogICAgIE9yaWdpbmFsRnVuY3Rpb24tLT4+TG9ja2VkRnVuY3Rpb246IFJldHVybiByZXN1bHRcbiAqICAgICBMb2NrZWRGdW5jdGlvbi0tPj5DYWxsZXI6IFJldHVybiByZXN1bHRcbiAqICAgZWxzZSBMb2NrIGlzIHBlbmRpbmdcbiAqICAgICBMb2NrZWRGdW5jdGlvbi0+PkxvY2tlZEZ1bmN0aW9uOiBRdWV1ZSBleGVjdXRpb25cbiAqICAgICBMb2NrZWRGdW5jdGlvbi0tPj5DYWxsZXI6IFJldHVybiBwcm9taXNlXG4gKiAgICAgTm90ZSBvdmVyIExvY2tlZEZ1bmN0aW9uOiBXYWl0IGZvciBwcmV2aW91cyBleGVjdXRpb25cbiAqICAgICBMb2NrZWRGdW5jdGlvbi0+Pk9yaWdpbmFsRnVuY3Rpb246IEV4ZWN1dGUgd2l0aCBwYXJhbXNcbiAqICAgICBPcmlnaW5hbEZ1bmN0aW9uLS0+PkxvY2tlZEZ1bmN0aW9uOiBSZXR1cm4gcmVzdWx0XG4gKiAgICAgTG9ja2VkRnVuY3Rpb24tLT4+Q2FsbGVyOiBSZXNvbHZlIHByb21pc2Ugd2l0aCByZXN1bHRcbiAqICAgZW5kXG4gKiAgIExvY2tlZEZ1bmN0aW9uLT4+TG9ja2VkRnVuY3Rpb246IFVwZGF0ZSBsb2NrXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gbG9ja2lmeTxSPihmOiAoLi4ucGFyYW1zOiB1bmtub3duW10pID0+IFIpIHtcbiAgbGV0IGxvY2s6IFByb21pc2U8UiB8IHZvaWQ+ID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIHJldHVybiAoLi4ucGFyYW1zOiB1bmtub3duW10pID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBsb2NrLnRoZW4oKCkgPT4gZiguLi5wYXJhbXMpKTtcbiAgICBsb2NrID0gcmVzdWx0LmNhdGNoKCgpID0+IHt9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDaGFpbnMgbXVsdGlwbGUgYWJvcnQgc2lnbmFscyB0byBhIGNvbnRyb2xsZXIuXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgbWVjaGFuaXNtIHdoZXJlIG11bHRpcGxlIGFib3J0IHNpZ25hbHMgY2FuIHRyaWdnZXIgYSBzaW5nbGUgYWJvcnQgY29udHJvbGxlci5cbiAqIFRoaXMgaXMgdXNlZnVsIGZvciBjb29yZGluYXRpbmcgY2FuY2VsbGF0aW9uIGFjcm9zcyBtdWx0aXBsZSBhc3luY2hyb25vdXMgb3BlcmF0aW9ucy5cbiAqXG4gKiBAcGFyYW0ge0Fib3J0Q29udHJvbGxlcn0gY29udHJvbGxlciAtIFRoZSBhYm9ydCBjb250cm9sbGVyIHRvIGJlIHRyaWdnZXJlZCBieSBzaWduYWxzLlxuICogQHBhcmFtIHsuLi5BYm9ydFNpZ25hbH0gc2lnbmFscyAtIE9uZSBvciBtb3JlIGFib3J0IHNpZ25hbHMgdGhhdCBjYW4gdHJpZ2dlciB0aGUgY29udHJvbGxlci5cbiAqIEByZXR1cm4ge0Fib3J0Q29udHJvbGxlcn0gVGhlIGlucHV0IGNvbnRyb2xsZXIsIG5vdyBjb25uZWN0ZWQgdG8gdGhlIHNpZ25hbHMuXG4gKlxuICogQGZ1bmN0aW9uIGNoYWluQWJvcnRDb250cm9sbGVyXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gY2hhaW5BYm9ydENvbnRyb2xsZXIoXG4gIGNvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcixcbiAgLi4uc2lnbmFsczogQWJvcnRTaWduYWxbXVxuKTogQWJvcnRDb250cm9sbGVyO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IGNvbnRyb2xsZXIgY2hhaW5lZCB0byBtdWx0aXBsZSBhYm9ydCBzaWduYWxzLlxuICogQHN1bW1hcnkgQ3JlYXRlcyBhIG5ldyBhYm9ydCBjb250cm9sbGVyIHRoYXQgd2lsbCBiZSB0cmlnZ2VyZWQgaWYgYW55IG9mIHRoZSBwcm92aWRlZCBzaWduYWxzIGFyZSBhYm9ydGVkLlxuICpcbiAqIEBwYXJhbSB7Li4uQWJvcnRTaWduYWx9IHNpZ25hbHMgLSBPbmUgb3IgbW9yZSBhYm9ydCBzaWduYWxzIHRoYXQgY2FuIHRyaWdnZXIgdGhlIG5ldyBjb250cm9sbGVyLlxuICogQHJldHVybiB7QWJvcnRDb250cm9sbGVyfSBBIG5ldyBhYm9ydCBjb250cm9sbGVyIGNvbm5lY3RlZCB0byB0aGUgc2lnbmFscy5cbiAqXG4gKiBAZnVuY3Rpb24gY2hhaW5BYm9ydENvbnRyb2xsZXJcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGFpbkFib3J0Q29udHJvbGxlcihcbiAgLi4uc2lnbmFsczogQWJvcnRTaWduYWxbXVxuKTogQWJvcnRDb250cm9sbGVyO1xuXG5leHBvcnQgZnVuY3Rpb24gY2hhaW5BYm9ydENvbnRyb2xsZXIoXG4gIGFyZ3VtZW50MDogQWJvcnRDb250cm9sbGVyIHwgQWJvcnRTaWduYWwsXG4gIC4uLnJlbWFpbmRlcjogQWJvcnRTaWduYWxbXVxuKTogQWJvcnRDb250cm9sbGVyIHtcbiAgbGV0IHNpZ25hbHM6IEFib3J0U2lnbmFsW107XG4gIGxldCBjb250cm9sbGVyOiBBYm9ydENvbnRyb2xsZXI7XG5cbiAgLy8gbm9ybWFsaXplIGFyZ3NcbiAgaWYgKGFyZ3VtZW50MCBpbnN0YW5jZW9mIEFib3J0U2lnbmFsKSB7XG4gICAgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICBzaWduYWxzID0gW2FyZ3VtZW50MCwgLi4ucmVtYWluZGVyXTtcbiAgfSBlbHNlIHtcbiAgICBjb250cm9sbGVyID0gYXJndW1lbnQwO1xuICAgIHNpZ25hbHMgPSByZW1haW5kZXI7XG4gIH1cblxuICAvLyBpZiB0aGUgY29udHJvbGxlciBpcyBhbHJlYWR5IGFib3J0ZWQsIGV4aXQgZWFybHlcbiAgaWYgKGNvbnRyb2xsZXIuc2lnbmFsLmFib3J0ZWQpIHtcbiAgICByZXR1cm4gY29udHJvbGxlcjtcbiAgfVxuXG4gIGNvbnN0IGhhbmRsZXIgPSAoKSA9PiBjb250cm9sbGVyLmFib3J0KCk7XG5cbiAgZm9yIChjb25zdCBzaWduYWwgb2Ygc2lnbmFscykge1xuICAgIC8vIGNoZWNrIGJlZm9yZSBhZGRpbmchIChhbmQgYXNzdW1lIHRoZXJlIGlzIG5vIHBvc3NpYmxlIHdheSB0aGF0IHRoZSBzaWduYWwgY291bGRcbiAgICAvLyBhYm9ydCBiZXR3ZWVuIHRoZSBgaWZgIGNoZWNrIGFuZCBhZGRpbmcgdGhlIGV2ZW50IGxpc3RlbmVyKVxuICAgIGlmIChzaWduYWwuYWJvcnRlZCkge1xuICAgICAgY29udHJvbGxlci5hYm9ydCgpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgaGFuZGxlciwge1xuICAgICAgb25jZTogdHJ1ZSxcbiAgICAgIHNpZ25hbDogY29udHJvbGxlci5zaWduYWwsXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gY29udHJvbGxlcjtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU3Bhd25zIGEgY29tbWFuZCBhcyBhIGNoaWxkIHByb2Nlc3Mgd2l0aCBvdXRwdXQgaGFuZGxpbmcuXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgY2hpbGQgcHJvY2VzcyB0byBleGVjdXRlIGEgY29tbWFuZCB3aXRoIHN1cHBvcnQgZm9yIHBpcGluZyBtdWx0aXBsZSBjb21tYW5kcyxcbiAqIGN1c3RvbSBvdXRwdXQgaGFuZGxpbmcsIGFuZCBhYm9ydCBjb250cm9sLiBUaGlzIGZ1bmN0aW9uIGhhbmRsZXMgdGhlIGxvdy1sZXZlbCBkZXRhaWxzIG9mXG4gKiBzcGF3bmluZyBwcm9jZXNzZXMgYW5kIGNvbm5lY3RpbmcgdGhlaXIgaW5wdXRzL291dHB1dHMgd2hlbiBwaXBpbmcgaXMgdXNlZC5cbiAqXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSB0eXBlIG9mIHRoZSBwcm9jZXNzZWQgb3V0cHV0LCBkZWZhdWx0aW5nIHRvIHN0cmluZy5cbiAqIEBwYXJhbSB7U3RhbmRhcmRPdXRwdXRXcml0ZXI8Uj59IG91dHB1dCAtIFRoZSBvdXRwdXQgd3JpdGVyIHRvIGhhbmRsZSBjb21tYW5kIG91dHB1dC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjb21tYW5kIC0gVGhlIGNvbW1hbmQgdG8gZXhlY3V0ZSwgY2FuIGluY2x1ZGUgcGlwZSBvcGVyYXRvcnMuXG4gKiBAcGFyYW0ge1NwYXduT3B0aW9uc1dpdGhvdXRTdGRpb30gb3B0cyAtIE9wdGlvbnMgZm9yIHRoZSBzcGF3bmVkIHByb2Nlc3MuXG4gKiBAcGFyYW0ge0Fib3J0Q29udHJvbGxlcn0gYWJvcnQgLSBDb250cm9sbGVyIHRvIGFib3J0IHRoZSBjb21tYW5kIGV4ZWN1dGlvbi5cbiAqIEBwYXJhbSB7TG9nZ2VyfSBsb2dnZXIgLSBMb2dnZXIgZm9yIHJlY29yZGluZyBjb21tYW5kIGV4ZWN1dGlvbiBkZXRhaWxzLlxuICogQHJldHVybiB7Q2hpbGRQcm9jZXNzV2l0aG91dE51bGxTdHJlYW1zfSBUaGUgc3Bhd25lZCBjaGlsZCBwcm9jZXNzLlxuICpcbiAqIEBmdW5jdGlvbiBzcGF3bkNvbW1hbmRcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzcGF3bkNvbW1hbmQ8UiA9IHN0cmluZz4oXG4gIG91dHB1dDogU3RhbmRhcmRPdXRwdXRXcml0ZXI8Uj4sXG4gIGNvbW1hbmQ6IHN0cmluZyxcbiAgb3B0czogU3Bhd25PcHRpb25zV2l0aG91dFN0ZGlvLFxuICBhYm9ydDogQWJvcnRDb250cm9sbGVyLFxuICBsb2dnZXI6IExvZ2dlclxuKTogQ2hpbGRQcm9jZXNzV2l0aG91dE51bGxTdHJlYW1zIHtcbiAgZnVuY3Rpb24gc3Bhd25Jbm5lcihjb21tYW5kOiBzdHJpbmcsIGNvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcikge1xuICAgIGNvbnN0IFtjbWQsIGFyZ3pdID0gb3V0cHV0LnBhcnNlQ29tbWFuZChjb21tYW5kKTtcbiAgICBsb2dnZXIuaW5mbyhgUnVubmluZyBjb21tYW5kOiAke2NtZH1gKTtcbiAgICBsb2dnZXIuZGVidWcoYHdpdGggYXJnczogJHthcmd6LmpvaW4oXCIgXCIpfWApO1xuICAgIGNvbnN0IGNoaWxkUHJvY2VzcyA9IHNwYXduKGNtZCwgYXJneiwge1xuICAgICAgLi4ub3B0cyxcbiAgICAgIGN3ZDogb3B0cy5jd2QgfHwgcHJvY2Vzcy5jd2QoKSxcbiAgICAgIGVudjogT2JqZWN0LmFzc2lnbih7fSwgcHJvY2Vzcy5lbnYsIG9wdHMuZW52LCB7IFBBVEg6IHByb2Nlc3MuZW52LlBBVEggfSksXG4gICAgICBzaGVsbDogb3B0cy5zaGVsbCB8fCBmYWxzZSxcbiAgICAgIHNpZ25hbDogY29udHJvbGxlci5zaWduYWwsXG4gICAgfSk7XG4gICAgbG9nZ2VyLnZlcmJvc2UoYHBpZCA6ICR7Y2hpbGRQcm9jZXNzLnBpZH1gKTtcbiAgICByZXR1cm4gY2hpbGRQcm9jZXNzO1xuICB9XG5cbiAgY29uc3QgbSA9IGNvbW1hbmQubWF0Y2goL1s8PiQjXS9nKTtcbiAgaWYgKG0pXG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYEludmFsaWQgY29tbWFuZDogJHtjb21tYW5kfS4gY29udGFpbnMgaW52YWxpZCBjaGFyYWN0ZXJzOiAke219YFxuICAgICk7XG4gIGlmIChjb21tYW5kLmluY2x1ZGVzKFwiIHwgXCIpKSB7XG4gICAgY29uc3QgY21kcyA9IGNvbW1hbmQuc3BsaXQoXCIgfCBcIik7XG4gICAgY29uc3Qgc3Bhd25zID0gW107XG4gICAgY29uc3QgY29udHJvbGxlcnMgPSBuZXcgQXJyYXkoY21kcy5sZW5ndGgpO1xuICAgIGNvbnRyb2xsZXJzWzBdID0gYWJvcnQ7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjbWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoaSAhPT0gMClcbiAgICAgICAgY29udHJvbGxlcnNbaV0gPSBjaGFpbkFib3J0Q29udHJvbGxlcihjb250cm9sbGVyc1tpIC0gMV0uc2lnbmFsKTtcbiAgICAgIHNwYXducy5wdXNoKHNwYXduSW5uZXIoY21kc1tpXSwgY29udHJvbGxlcnNbaV0pKTtcbiAgICAgIGlmIChpID09PSAwKSBjb250aW51ZTtcbiAgICAgIHNwYXduc1tpIC0gMV0uc3Rkb3V0LnBpcGUoc3Bhd25zW2ldLnN0ZGluKTtcbiAgICB9XG4gICAgcmV0dXJuIHNwYXduc1tjbWRzLmxlbmd0aCAtIDFdO1xuICB9XG5cbiAgcmV0dXJuIHNwYXduSW5uZXIoY29tbWFuZCwgYWJvcnQpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFeGVjdXRlcyBhIGNvbW1hbmQgYXN5bmNocm9ub3VzbHkgd2l0aCBjdXN0b21pemFibGUgb3V0cHV0IGhhbmRsaW5nLlxuICogQHN1bW1hcnkgVGhpcyBmdW5jdGlvbiBydW5zIGEgc2hlbGwgY29tbWFuZCBhcyBhIGNoaWxkIHByb2Nlc3MsIHByb3ZpZGluZyBmaW5lLWdyYWluZWRcbiAqIGNvbnRyb2wgb3ZlciBpdHMgZXhlY3V0aW9uIGFuZCBvdXRwdXQgaGFuZGxpbmcuIEl0IHN1cHBvcnRzIGN1c3RvbSBvdXRwdXQgd3JpdGVycyxcbiAqIGFsbG93cyBmb3IgY29tbWFuZCBhYm9ydGlvbiwgYW5kIGNhcHR1cmVzIGJvdGggc3Rkb3V0IGFuZCBzdGRlcnIuXG4gKlxuICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgcmVzb2x2ZWQgdmFsdWUgZnJvbSB0aGUgY29tbWFuZCBleGVjdXRpb24uXG4gKlxuICogQHBhcmFtIGNvbW1hbmQgLSBUaGUgY29tbWFuZCB0byBydW4sIGVpdGhlciBhcyBhIHN0cmluZyBvciBhbiBhcnJheSBvZiBzdHJpbmdzLlxuICogQHBhcmFtIG9wdHMgLSBTcGF3biBvcHRpb25zIGZvciB0aGUgY2hpbGQgcHJvY2Vzcy4gRGVmYXVsdHMgdG8gYW4gZW1wdHkgb2JqZWN0LlxuICogQHBhcmFtIG91dHB1dENvbnN0cnVjdG9yIC0gQ29uc3RydWN0b3IgZm9yIHRoZSBvdXRwdXQgd3JpdGVyLiBEZWZhdWx0cyB0byBTdGFuZGFyZE91dHB1dFdyaXRlci5cbiAqIEBwYXJhbSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgb3V0cHV0IGNvbnN0cnVjdG9yLlxuICogQHJldHVybiB7Q29tbWFuZFJlc3VsdH0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGNvbW1hbmQgcmVzdWx0IG9mIHR5cGUgUi5cbiAqXG4gKiBAZnVuY3Rpb24gcnVuQ29tbWFuZFxuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IHJ1bkNvbW1hbmRcbiAqICAgcGFydGljaXBhbnQgT3V0cHV0V3JpdGVyXG4gKiAgIHBhcnRpY2lwYW50IENoaWxkUHJvY2Vzc1xuICogICBDYWxsZXItPj5ydW5Db21tYW5kOiBDYWxsIHdpdGggY29tbWFuZCBhbmQgb3B0aW9uc1xuICogICBydW5Db21tYW5kLT4+T3V0cHV0V3JpdGVyOiBDcmVhdGUgbmV3IGluc3RhbmNlXG4gKiAgIHJ1bkNvbW1hbmQtPj5PdXRwdXRXcml0ZXI6IFBhcnNlIGNvbW1hbmRcbiAqICAgcnVuQ29tbWFuZC0+PkNoaWxkUHJvY2VzczogU3Bhd24gcHJvY2Vzc1xuICogICBDaGlsZFByb2Nlc3MtLT4+cnVuQ29tbWFuZDogUmV0dXJuIHByb2Nlc3Mgb2JqZWN0XG4gKiAgIHJ1bkNvbW1hbmQtPj5DaGlsZFByb2Nlc3M6IFNldCB1cCBldmVudCBsaXN0ZW5lcnNcbiAqICAgbG9vcCBGb3IgZWFjaCBzdGRvdXQgZGF0YVxuICogICAgIENoaWxkUHJvY2Vzcy0+PnJ1bkNvbW1hbmQ6IEVtaXQgc3Rkb3V0IGRhdGFcbiAqICAgICBydW5Db21tYW5kLT4+T3V0cHV0V3JpdGVyOiBIYW5kbGUgc3Rkb3V0IGRhdGFcbiAqICAgZW5kXG4gKiAgIGxvb3AgRm9yIGVhY2ggc3RkZXJyIGRhdGFcbiAqICAgICBDaGlsZFByb2Nlc3MtPj5ydW5Db21tYW5kOiBFbWl0IHN0ZGVyciBkYXRhXG4gKiAgICAgcnVuQ29tbWFuZC0+Pk91dHB1dFdyaXRlcjogSGFuZGxlIHN0ZGVyciBkYXRhXG4gKiAgIGVuZFxuICogICBDaGlsZFByb2Nlc3MtPj5ydW5Db21tYW5kOiBFbWl0IGVycm9yIChpZiBhbnkpXG4gKiAgIHJ1bkNvbW1hbmQtPj5PdXRwdXRXcml0ZXI6IEhhbmRsZSBlcnJvclxuICogICBDaGlsZFByb2Nlc3MtPj5ydW5Db21tYW5kOiBFbWl0IGV4aXRcbiAqICAgcnVuQ29tbWFuZC0+Pk91dHB1dFdyaXRlcjogSGFuZGxlIGV4aXRcbiAqICAgT3V0cHV0V3JpdGVyLS0+PnJ1bkNvbW1hbmQ6IFJlc29sdmUgb3IgcmVqZWN0IHByb21pc2VcbiAqICAgcnVuQ29tbWFuZC0tPj5DYWxsZXI6IFJldHVybiBDb21tYW5kUmVzdWx0XG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuQ29tbWFuZDxSID0gc3RyaW5nPihcbiAgY29tbWFuZDogc3RyaW5nLFxuICBvcHRzOiBTcGF3bk9wdGlvbnNXaXRob3V0U3RkaW8gPSB7fSxcbiAgb3V0cHV0Q29uc3RydWN0b3I6IE91dHB1dFdyaXRlckNvbnN0cnVjdG9yPFxuICAgIFIsXG4gICAgU3RhbmRhcmRPdXRwdXRXcml0ZXI8Uj4sXG4gICAgRXJyb3JcbiAgPiA9IFN0YW5kYXJkT3V0cHV0V3JpdGVyPFI+LFxuICAuLi5hcmdzOiB1bmtub3duW11cbik6IENvbW1hbmRSZXN1bHQ8Uj4ge1xuICBjb25zdCBsb2dnZXIgPSBMb2dnaW5nLmZvcihydW5Db21tYW5kKTtcbiAgY29uc3QgYWJvcnQgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cbiAgY29uc3QgcmVzdWx0OiBPbWl0PENvbW1hbmRSZXN1bHQsIFwicHJvbWlzZVwiIHwgXCJwaXBlXCI+ID0ge1xuICAgIGFib3J0OiBhYm9ydCxcbiAgICBjb21tYW5kOiBjb21tYW5kLFxuICAgIGxvZ3M6IFtdLFxuICAgIGVycnM6IFtdLFxuICB9O1xuXG4gIGNvbnN0IGxvY2sgPSBuZXcgUHJvbWlzZTxSPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgbGV0IG91dHB1dDtcbiAgICB0cnkge1xuICAgICAgb3V0cHV0ID0gbmV3IG91dHB1dENvbnN0cnVjdG9yKFxuICAgICAgICBjb21tYW5kLFxuICAgICAgICB7XG4gICAgICAgICAgcmVzb2x2ZSxcbiAgICAgICAgICByZWplY3QsXG4gICAgICAgIH0sXG4gICAgICAgIC4uLmFyZ3NcbiAgICAgICk7XG5cbiAgICAgIHJlc3VsdC5jbWQgPSBzcGF3bkNvbW1hbmQ8Uj4ob3V0cHV0LCBjb21tYW5kLCBvcHRzLCBhYm9ydCwgbG9nZ2VyKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihgRXJyb3IgcnVubmluZyBjb21tYW5kICR7Y29tbWFuZH06ICR7ZX1gKSk7XG4gICAgfVxuXG4gICAgcmVzdWx0LmNtZC5zdGRvdXQuc2V0RW5jb2RpbmcoXCJ1dGY4XCIpO1xuXG4gICAgcmVzdWx0LmNtZC5zdGRvdXQub24oXCJkYXRhXCIsIChjaHVuazogYW55KSA9PiB7XG4gICAgICBjaHVuayA9IGNodW5rLnRvU3RyaW5nKCk7XG4gICAgICByZXN1bHQubG9ncy5wdXNoKGNodW5rKTtcbiAgICAgIG91dHB1dC5kYXRhKGNodW5rKTtcbiAgICB9KTtcblxuICAgIHJlc3VsdC5jbWQuc3RkZXJyLm9uKFwiZGF0YVwiLCAoZGF0YTogYW55KSA9PiB7XG4gICAgICBkYXRhID0gZGF0YS50b1N0cmluZygpO1xuICAgICAgcmVzdWx0LmVycnMucHVzaChkYXRhKTtcbiAgICAgIG91dHB1dC5lcnJvcihkYXRhKTtcbiAgICB9KTtcblxuICAgIHJlc3VsdC5jbWQub25jZShcImVycm9yXCIsIChlcnI6IEVycm9yKSA9PiB7XG4gICAgICBvdXRwdXQuZXhpdChlcnIubWVzc2FnZSwgcmVzdWx0LmVycnMpO1xuICAgIH0pO1xuXG4gICAgcmVzdWx0LmNtZC5vbmNlKFwiZXhpdFwiLCAoY29kZTogbnVtYmVyID0gMCkgPT4ge1xuICAgICAgaWYgKGFib3J0LnNpZ25hbC5hYm9ydGVkICYmIGNvZGUgPT09IG51bGwpIGNvZGUgPSBBYm9ydENvZGUgYXMgYW55O1xuICAgICAgb3V0cHV0LmV4aXQoY29kZSwgY29kZSA9PT0gMCA/IHJlc3VsdC5sb2dzIDogcmVzdWx0LmVycnMpO1xuICAgIH0pO1xuICB9KTtcblxuICBPYmplY3QuYXNzaWduKHJlc3VsdCwge1xuICAgIHByb21pc2U6IGxvY2ssXG4gICAgcGlwZTogYXN5bmMgPEU+KGNiOiAocjogUikgPT4gRSkgPT4ge1xuICAgICAgY29uc3QgbCA9IGxvZ2dlci5mb3IoXCJwaXBlXCIpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgbC52ZXJib3NlKGBFeGVjdXRpbmcgcGlwZSBmdW5jdGlvbiAke2NvbW1hbmR9Li4uYCk7XG4gICAgICAgIGNvbnN0IHJlc3VsdDogUiA9IGF3YWl0IGxvY2s7XG4gICAgICAgIGwudmVyYm9zZShgUGlwaW5nIG91dHB1dCB0byAke2NiLm5hbWV9OiAke3Jlc3VsdH1gKTtcbiAgICAgICAgcmV0dXJuIGNiKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgIGwuZXJyb3IoYEVycm9yIHBpcGluZyBjb21tYW5kIG91dHB1dDogJHtlfWApO1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH0sXG4gIH0pO1xuXG4gIHJldHVybiByZXN1bHQgYXMgQ29tbWFuZFJlc3VsdDxSPjtcbn1cbiIsImltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBydW5Db21tYW5kIH0gZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCB7IERlcGVuZGVuY3lNYXAsIFNpbXBsZURlcGVuZGVuY3lNYXAgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgTG9nZ2luZywgcGF0Y2hTdHJpbmcgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcblxuY29uc3QgbG9nZ2VyID0gTG9nZ2luZy5mb3IoXCJmc1wiKTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUGF0Y2hlcyBhIGZpbGUgd2l0aCBnaXZlbiB2YWx1ZXMuXG4gKiBAc3VtbWFyeSBSZWFkcyBhIGZpbGUsIGFwcGxpZXMgcGF0Y2hlcyB1c2luZyBUZXh0VXRpbHMsIGFuZCB3cml0ZXMgdGhlIHJlc3VsdCBiYWNrIHRvIHRoZSBmaWxlLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gVGhlIHBhdGggdG8gdGhlIGZpbGUgdG8gYmUgcGF0Y2hlZC5cbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgbnVtYmVyIHwgc3RyaW5nPn0gdmFsdWVzIC0gVGhlIHZhbHVlcyB0byBwYXRjaCBpbnRvIHRoZSBmaWxlLlxuICogQHJldHVybiB7dm9pZH1cbiAqXG4gKiBAZnVuY3Rpb24gcGF0Y2hGaWxlXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgcGF0Y2hGaWxlXG4gKiAgIHBhcnRpY2lwYW50IGZzXG4gKiAgIHBhcnRpY2lwYW50IHJlYWRGaWxlXG4gKiAgIHBhcnRpY2lwYW50IFRleHRVdGlsc1xuICogICBwYXJ0aWNpcGFudCB3cml0ZUZpbGVcbiAqICAgQ2FsbGVyLT4+cGF0Y2hGaWxlOiBDYWxsIHdpdGggcGF0aCBhbmQgdmFsdWVzXG4gKiAgIHBhdGNoRmlsZS0+PmZzOiBDaGVjayBpZiBmaWxlIGV4aXN0c1xuICogICBwYXRjaEZpbGUtPj5yZWFkRmlsZTogUmVhZCBmaWxlIGNvbnRlbnRcbiAqICAgcmVhZEZpbGUtPj5mczogUmVhZCBmaWxlXG4gKiAgIGZzLS0+PnJlYWRGaWxlOiBSZXR1cm4gZmlsZSBjb250ZW50XG4gKiAgIHJlYWRGaWxlLS0+PnBhdGNoRmlsZTogUmV0dXJuIGZpbGUgY29udGVudFxuICogICBwYXRjaEZpbGUtPj5UZXh0VXRpbHM6IFBhdGNoIHN0cmluZ1xuICogICBUZXh0VXRpbHMtLT4+cGF0Y2hGaWxlOiBSZXR1cm4gcGF0Y2hlZCBjb250ZW50XG4gKiAgIHBhdGNoRmlsZS0+PndyaXRlRmlsZTogV3JpdGUgcGF0Y2hlZCBjb250ZW50XG4gKiAgIHdyaXRlRmlsZS0+PmZzOiBXcml0ZSB0byBmaWxlXG4gKiAgIGZzLS0+PndyaXRlRmlsZTogRmlsZSB3cml0dGVuXG4gKiAgIHdyaXRlRmlsZS0tPj5wYXRjaEZpbGU6IEZpbGUgd3JpdHRlblxuICogICBwYXRjaEZpbGUtLT4+Q2FsbGVyOiBQYXRjaGluZyBjb21wbGV0ZVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhdGNoRmlsZShcbiAgcGF0aDogc3RyaW5nLFxuICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIG51bWJlciB8IHN0cmluZz5cbikge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHBhdGNoRmlsZSk7XG4gIGlmICghZnMuZXhpc3RzU3luYyhwYXRoKSlcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEZpbGUgbm90IGZvdW5kIGF0IHBhdGggXCIke3BhdGh9XCIuYCk7XG4gIGxldCBjb250ZW50ID0gcmVhZEZpbGUocGF0aCk7XG5cbiAgdHJ5IHtcbiAgICBsb2cudmVyYm9zZShgUGF0Y2hpbmcgZmlsZSBcIiR7cGF0aH1cIi4uLmApO1xuICAgIGxvZy5kZWJ1Zyhgd2l0aCB2YWx1ZTogJHtKU09OLnN0cmluZ2lmeSh2YWx1ZXMpfWApO1xuICAgIGNvbnRlbnQgPSBwYXRjaFN0cmluZyhjb250ZW50LCB2YWx1ZXMpO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgcGF0Y2hpbmcgZmlsZTogJHtlcnJvcn1gKTtcbiAgfVxuICB3cml0ZUZpbGUocGF0aCwgY29udGVudCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlYWRzIGEgZmlsZSBhbmQgcmV0dXJucyBpdHMgY29udGVudC5cbiAqIEBzdW1tYXJ5IFJlYWRzIHRoZSBjb250ZW50IG9mIGEgZmlsZSBhdCB0aGUgc3BlY2lmaWVkIHBhdGggYW5kIHJldHVybnMgaXQgYXMgYSBzdHJpbmcuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBUaGUgcGF0aCB0byB0aGUgZmlsZSB0byBiZSByZWFkLlxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgY29udGVudCBvZiB0aGUgZmlsZS5cbiAqXG4gKiBAZnVuY3Rpb24gcmVhZEZpbGVcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkRmlsZShwYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHJlYWRGaWxlKTtcbiAgdHJ5IHtcbiAgICBsb2cudmVyYm9zZShgUmVhZGluZyBmaWxlIFwiJHtwYXRofVwiLi4uYCk7XG4gICAgcmV0dXJuIGZzLnJlYWRGaWxlU3luYyhwYXRoLCBcInV0ZjhcIik7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoYEVycm9yIHJlYWRpbmcgZmlsZSBcIiR7cGF0aH1cIjogJHtlcnJvcn1gKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHJlYWRpbmcgZmlsZSBcIiR7cGF0aH1cIjogJHtlcnJvcn1gKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBXcml0ZXMgZGF0YSB0byBhIGZpbGUuXG4gKiBAc3VtbWFyeSBXcml0ZXMgdGhlIHByb3ZpZGVkIGRhdGEgdG8gYSBmaWxlIGF0IHRoZSBzcGVjaWZpZWQgcGF0aC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCAtIFRoZSBwYXRoIHRvIHRoZSBmaWxlIHRvIGJlIHdyaXR0ZW4uXG4gKiBAcGFyYW0ge3N0cmluZyB8IEJ1ZmZlcn0gZGF0YSAtIFRoZSBkYXRhIHRvIGJlIHdyaXR0ZW4gdG8gdGhlIGZpbGUuXG4gKiBAcmV0dXJuIHt2b2lkfVxuICpcbiAqIEBmdW5jdGlvbiB3cml0ZUZpbGVcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZUZpbGUocGF0aDogc3RyaW5nLCBkYXRhOiBzdHJpbmcgfCBCdWZmZXIpOiB2b2lkIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcih3cml0ZUZpbGUpO1xuICB0cnkge1xuICAgIGxvZy52ZXJib3NlKGBXcml0aW5nIGZpbGUgXCIke3BhdGh9IHdpdGggJHtkYXRhLmxlbmd0aH0gYnl0ZXMuLi5gKTtcbiAgICBmcy53cml0ZUZpbGVTeW5jKHBhdGgsIGRhdGEsIFwidXRmOFwiKTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2cudmVyYm9zZShgRXJyb3Igd3JpdGluZyBmaWxlIFwiJHtwYXRofVwiOiAke2Vycm9yfWApO1xuICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd3JpdGluZyBmaWxlIFwiJHtwYXRofVwiOiAke2Vycm9yfWApO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhbGwgZmlsZXMgcmVjdXJzaXZlbHkgZnJvbSBhIGRpcmVjdG9yeS5cbiAqIEBzdW1tYXJ5IFRyYXZlcnNlcyB0aHJvdWdoIGRpcmVjdG9yaWVzIGFuZCBzdWJkaXJlY3RvcmllcyB0byBjb2xsZWN0IGFsbCBmaWxlIHBhdGhzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwIC0gVGhlIHBhdGggdG8gc3RhcnQgc2VhcmNoaW5nIGZyb20uXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBbZmlsdGVyXSAtIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGZpbHRlciBmaWxlcyBieSBuYW1lIG9yIGluZGV4LlxuICogQHJldHVybiB7c3RyaW5nW119IEFycmF5IG9mIGZpbGUgcGF0aHMuXG4gKlxuICogQGZ1bmN0aW9uIGdldEFsbEZpbGVzXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWxsRmlsZXMoXG4gIHA6IHN0cmluZyxcbiAgZmlsdGVyPzogKGY6IHN0cmluZywgaT86IG51bWJlcikgPT4gYm9vbGVhblxuKTogc3RyaW5nW10ge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKGdldEFsbEZpbGVzKTtcbiAgY29uc3QgZmlsZXM6IHN0cmluZ1tdID0gW107XG5cbiAgdHJ5IHtcbiAgICBsb2cudmVyYm9zZShgUmV0cmlldmluZyBhbGwgZmlsZXMgZnJvbSBcIiR7cH1cIi4uLmApO1xuICAgIGNvbnN0IGVudHJpZXMgPSBmcy5yZWFkZGlyU3luYyhwKTtcblxuICAgIGVudHJpZXMuZm9yRWFjaCgoZW50cnkpID0+IHtcbiAgICAgIGNvbnN0IGZ1bGxQYXRoID0gcGF0aC5qb2luKHAsIGVudHJ5KTtcbiAgICAgIGNvbnN0IHN0YXQgPSBmcy5zdGF0U3luYyhmdWxsUGF0aCk7XG5cbiAgICAgIGlmIChzdGF0LmlzRmlsZSgpKSB7XG4gICAgICAgIGZpbGVzLnB1c2goZnVsbFBhdGgpO1xuICAgICAgfSBlbHNlIGlmIChzdGF0LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgZmlsZXMucHVzaCguLi5nZXRBbGxGaWxlcyhmdWxsUGF0aCkpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmICghZmlsdGVyKSByZXR1cm4gZmlsZXM7XG4gICAgcmV0dXJuIGZpbGVzLmZpbHRlcihmaWx0ZXIpO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIGxvZy52ZXJib3NlKGBFcnJvciByZXRyaWV2aW5nIGZpbGVzIGZyb20gXCIke3B9XCI6ICR7ZXJyb3J9YCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciByZXRyaWV2aW5nIGZpbGVzIGZyb20gXCIke3B9XCI6ICR7ZXJyb3J9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVuYW1lcyBhIGZpbGUgb3IgZGlyZWN0b3J5LlxuICogQHN1bW1hcnkgTW92ZXMgYSBmaWxlIG9yIGRpcmVjdG9yeSBmcm9tIHRoZSBzb3VyY2UgcGF0aCB0byB0aGUgZGVzdGluYXRpb24gcGF0aC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gVGhlIHNvdXJjZSBwYXRoIG9mIHRoZSBmaWxlIG9yIGRpcmVjdG9yeS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkZXN0IC0gVGhlIGRlc3RpbmF0aW9uIHBhdGggZm9yIHRoZSBmaWxlIG9yIGRpcmVjdG9yeS5cbiAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIHJlbmFtZSBvcGVyYXRpb24gaXMgY29tcGxldGUuXG4gKlxuICogQGZ1bmN0aW9uIHJlbmFtZUZpbGVcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZW5hbWVGaWxlKHNvdXJjZTogc3RyaW5nLCBkZXN0OiBzdHJpbmcpIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcihyZW5hbWVGaWxlKTtcbiAgbGV0IGRlc2NyaXB0b3JTb3VyY2UsIGRlc2NyaXB0b3JEZXN0O1xuXG4gIHRyeSB7XG4gICAgZGVzY3JpcHRvclNvdXJjZSA9IGZzLnN0YXRTeW5jKHNvdXJjZSk7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoYFNvdXJjZSBwYXRoIFwiJHtzb3VyY2V9XCIgZG9lcyBub3QgZXhpc3Q6ICR7ZXJyb3J9YCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBTb3VyY2UgcGF0aCBcIiR7c291cmNlfVwiIGRvZXMgbm90IGV4aXN0OiAke2Vycm9yfWApO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBkZXNjcmlwdG9yRGVzdCA9IGZzLnN0YXRTeW5jKGRlc3QpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgIC8vIGRvIG5vdGhpbmcuIGl0cyBva1xuICB9XG4gIGlmIChkZXNjcmlwdG9yRGVzdCkge1xuICAgIGxvZy52ZXJib3NlKGBEZXN0aW5hdGlvbiBwYXRoIFwiJHtkZXN0fVwiIGFscmVhZHkgZXhpc3RzYCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBEZXN0aW5hdGlvbiBwYXRoIFwiJHtkZXN0fVwiIGFscmVhZHkgZXhpc3RzYCk7XG4gIH1cblxuICB0cnkge1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYFJlbmFtaW5nICR7ZGVzY3JpcHRvclNvdXJjZS5pc0ZpbGUoKSA/IFwiZmlsZVwiIDogXCJkaXJlY3RvcnlcIn0gXCIke3NvdXJjZX1cIiB0byBcIiR7ZGVzdH0uLi5gXG4gICAgKTtcbiAgICBmcy5yZW5hbWVTeW5jKHNvdXJjZSwgZGVzdCk7XG4gICAgbG9nLnZlcmJvc2UoYFN1Y2Nlc3NmdWxseSByZW5hbWVkIHRvIFwiJHtkZXN0fVwiYCk7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgRXJyb3IgcmVuYW1pbmcgJHtkZXNjcmlwdG9yU291cmNlLmlzRmlsZSgpID8gXCJmaWxlXCIgOiBcImRpcmVjdG9yeVwifSBcIiR7c291cmNlfVwiIHRvIFwiJHtkZXN0fVwiOiAke2Vycm9yfWBcbiAgICApO1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBFcnJvciByZW5hbWluZyAke2Rlc2NyaXB0b3JTb3VyY2UuaXNGaWxlKCkgPyBcImZpbGVcIiA6IFwiZGlyZWN0b3J5XCJ9IFwiJHtzb3VyY2V9XCIgdG8gXCIke2Rlc3R9XCI6ICR7ZXJyb3J9YFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ29waWVzIGEgZmlsZSBvciBkaXJlY3RvcnkuXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgY29weSBvZiBhIGZpbGUgb3IgZGlyZWN0b3J5IGZyb20gdGhlIHNvdXJjZSBwYXRoIHRvIHRoZSBkZXN0aW5hdGlvbiBwYXRoLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBUaGUgc291cmNlIHBhdGggb2YgdGhlIGZpbGUgb3IgZGlyZWN0b3J5LlxuICogQHBhcmFtIHtzdHJpbmd9IGRlc3QgLSBUaGUgZGVzdGluYXRpb24gcGF0aCBmb3IgdGhlIGZpbGUgb3IgZGlyZWN0b3J5LlxuICogQHJldHVybiB7dm9pZH1cbiAqXG4gKiBAZnVuY3Rpb24gY29weUZpbGVcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb3B5RmlsZShzb3VyY2U6IHN0cmluZywgZGVzdDogc3RyaW5nKSB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IoY29weUZpbGUpO1xuICBsZXQgZGVzY3JpcHRvclNvdXJjZSwgZGVzY3JpcHRvckRlc3Q7XG4gIHRyeSB7XG4gICAgZGVzY3JpcHRvclNvdXJjZSA9IGZzLnN0YXRTeW5jKHNvdXJjZSk7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoYFNvdXJjZSBwYXRoIFwiJHtzb3VyY2V9XCIgZG9lcyBub3QgZXhpc3Q6ICR7ZXJyb3J9YCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBTb3VyY2UgcGF0aCBcIiR7c291cmNlfVwiIGRvZXMgbm90IGV4aXN0OiAke2Vycm9yfWApO1xuICB9XG4gIHRyeSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIGRlc2NyaXB0b3JEZXN0ID0gZnMuc3RhdFN5bmMoZGVzdCk7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIGlmIChkZXNjcmlwdG9yU291cmNlLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgIGxvZy52ZXJib3NlKGBEZXN0IHBhdGggXCIke2Rlc3R9XCIgZG9lcyBub3QgZXhpc3QuIGNyZWF0aW5nYCk7XG4gICAgICBmcy5ta2RpclN5bmMoZGVzdCwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgfVxuICB9XG5cbiAgdHJ5IHtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBDb3B5aW5nICR7ZGVzY3JpcHRvclNvdXJjZS5pc0ZpbGUoKSA/IFwiZmlsZVwiIDogXCJkaXJlY3RvcnlcIn0gXCIke3NvdXJjZX1cIiB0byBcIiR7ZGVzdH0uLi5gXG4gICAgKTtcbiAgICBmcy5jcFN5bmMoc291cmNlLCBkZXN0LCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBFcnJvciBjb3B5aW5nICR7ZGVzY3JpcHRvclNvdXJjZS5pc0ZpbGUoKSA/IFwiZmlsZVwiIDogXCJkaXJlY3RvcnlcIn0gXCIke3NvdXJjZX1cIiB0byBcIiR7ZGVzdH06ICR7ZXJyb3J9YFxuICAgICk7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYEVycm9yIGNvcHlpbmcgJHtkZXNjcmlwdG9yU291cmNlLmlzRmlsZSgpID8gXCJmaWxlXCIgOiBcImRpcmVjdG9yeVwifSBcIiR7c291cmNlfVwiIHRvIFwiJHtkZXN0fTogJHtlcnJvcn1gXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWxldGVzIGEgZmlsZSBvciBkaXJlY3RvcnkuXG4gKiBAc3VtbWFyeSBSZW1vdmVzIGEgZmlsZSBvciBkaXJlY3RvcnkgYXQgdGhlIHNwZWNpZmllZCBwYXRoLCB3aXRoIHJlY3Vyc2l2ZSBhbmQgZm9yY2Ugb3B0aW9ucyBlbmFibGVkLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwIC0gVGhlIHBhdGggdG8gdGhlIGZpbGUgb3IgZGlyZWN0b3J5IHRvIGRlbGV0ZS5cbiAqIEByZXR1cm4ge3ZvaWR9XG4gKlxuICogQGZ1bmN0aW9uIGRlbGV0ZVBhdGhcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWxldGVQYXRoKHA6IHN0cmluZykge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKGRlbGV0ZVBhdGgpO1xuICB0cnkge1xuICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBmcy5zdGF0U3luYyhwKTtcbiAgICBpZiAoZGVzY3JpcHRvci5pc0ZpbGUoKSkge1xuICAgICAgbG9nLnZlcmJvc2UoYERlbGV0aW5nIGZpbGUgXCIke3B9Li4uYCk7XG4gICAgICBmcy5ybVN5bmMocCwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICAgIH0gZWxzZSBpZiAoZGVzY3JpcHRvci5pc0RpcmVjdG9yeSgpKVxuICAgICAgZnMucm1TeW5jKHAsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2cudmVyYm9zZShgRXJyb3IgRGVsZXRpbmcgXCIke3B9XCI6ICR7ZXJyb3J9YCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBEZWxldGluZyBcIiR7cH1cIjogJHtlcnJvcn1gKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgcGFja2FnZSBpbmZvcm1hdGlvbiBmcm9tIHBhY2thZ2UuanNvbi5cbiAqIEBzdW1tYXJ5IExvYWRzIGFuZCBwYXJzZXMgdGhlIHBhY2thZ2UuanNvbiBmaWxlIGZyb20gYSBzcGVjaWZpZWQgZGlyZWN0b3J5IG9yIHRoZSBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5LiBDYW4gcmV0dXJuIHRoZSBlbnRpcmUgcGFja2FnZSBvYmplY3Qgb3IgYSBzcGVjaWZpYyBwcm9wZXJ0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbcD1wcm9jZXNzLmN3ZCgpXSAtIFRoZSBkaXJlY3RvcnkgcGF0aCB3aGVyZSB0aGUgcGFja2FnZS5qc29uIGZpbGUgaXMgbG9jYXRlZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbcHJvcGVydHldIC0gT3B0aW9uYWwuIFRoZSBzcGVjaWZpYyBwcm9wZXJ0eSB0byByZXRyaWV2ZSBmcm9tIHBhY2thZ2UuanNvbi5cbiAqIEByZXR1cm4ge29iamVjdCB8IHN0cmluZ30gVGhlIHBhcnNlZCBjb250ZW50cyBvZiBwYWNrYWdlLmpzb24gb3IgdGhlIHZhbHVlIG9mIHRoZSBzcGVjaWZpZWQgcHJvcGVydHkuXG4gKiBAZnVuY3Rpb24gZ2V0UGFja2FnZVxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgZ2V0UGFja2FnZVxuICogICBwYXJ0aWNpcGFudCByZWFkRmlsZVxuICogICBwYXJ0aWNpcGFudCBKU09OXG4gKiAgIENhbGxlci0+PmdldFBhY2thZ2U6IENhbGwgd2l0aCBwYXRoIGFuZCBvcHRpb25hbCBwcm9wZXJ0eVxuICogICBnZXRQYWNrYWdlLT4+cmVhZEZpbGU6IFJlYWQgcGFja2FnZS5qc29uXG4gKiAgIHJlYWRGaWxlLS0+PmdldFBhY2thZ2U6IFJldHVybiBmaWxlIGNvbnRlbnRcbiAqICAgZ2V0UGFja2FnZS0+PkpTT046IFBhcnNlIGZpbGUgY29udGVudFxuICogICBKU09OLS0+PmdldFBhY2thZ2U6IFJldHVybiBwYXJzZWQgb2JqZWN0XG4gKiAgIGFsdCBwcm9wZXJ0eSBzcGVjaWZpZWRcbiAqICAgICBnZXRQYWNrYWdlLT4+Z2V0UGFja2FnZTogQ2hlY2sgaWYgcHJvcGVydHkgZXhpc3RzXG4gKiAgICAgYWx0IHByb3BlcnR5IGV4aXN0c1xuICogICAgICAgZ2V0UGFja2FnZS0tPj5DYWxsZXI6IFJldHVybiBwcm9wZXJ0eSB2YWx1ZVxuICogICAgIGVsc2UgcHJvcGVydHkgZG9lc24ndCBleGlzdFxuICogICAgICAgZ2V0UGFja2FnZS0tPj5DYWxsZXI6IFRocm93IEVycm9yXG4gKiAgICAgZW5kXG4gKiAgIGVsc2Ugbm8gcHJvcGVydHkgc3BlY2lmaWVkXG4gKiAgICAgZ2V0UGFja2FnZS0tPj5DYWxsZXI6IFJldHVybiBlbnRpcmUgcGFja2FnZSBvYmplY3RcbiAqICAgZW5kXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQYWNrYWdlKFxuICBwOiBzdHJpbmcgPSBwcm9jZXNzLmN3ZCgpLFxuICBwcm9wZXJ0eT86IHN0cmluZ1xuKTogb2JqZWN0IHwgc3RyaW5nIHtcbiAgbGV0IHBrZzogYW55O1xuICB0cnkge1xuICAgIHBrZyA9IEpTT04ucGFyc2UocmVhZEZpbGUocGF0aC5qb2luKHAsIGBwYWNrYWdlLmpzb25gKSkpO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHJldHJpZXZlIHBhY2thZ2UgaW5mb3JtYXRpb25cIiAke2Vycm9yfWApO1xuICB9XG5cbiAgaWYgKHByb3BlcnR5KSB7XG4gICAgaWYgKCEocHJvcGVydHkgaW4gcGtnKSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgXCIke3Byb3BlcnR5fVwiIG5vdCBmb3VuZCBpbiBwYWNrYWdlLmpzb25gKTtcbiAgICByZXR1cm4gcGtnW3Byb3BlcnR5XSBhcyBzdHJpbmc7XG4gIH1cbiAgcmV0dXJuIHBrZztcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU2V0cyBhbiBhdHRyaWJ1dGUgaW4gdGhlIHBhY2thZ2UuanNvbiBmaWxlLlxuICogQHN1bW1hcnkgVXBkYXRlcyBhIHNwZWNpZmljIGF0dHJpYnV0ZSBpbiB0aGUgcGFja2FnZS5qc29uIGZpbGUgd2l0aCB0aGUgcHJvdmlkZWQgdmFsdWUuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGF0dHIgLSBUaGUgYXR0cmlidXRlIG5hbWUgdG8gc2V0IGluIHBhY2thZ2UuanNvbi5cbiAqIEBwYXJhbSB7c3RyaW5nIHwgbnVtYmVyIHwgb2JqZWN0fSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBzZXQgZm9yIHRoZSBhdHRyaWJ1dGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gW3A9cHJvY2Vzcy5jd2QoKV0gLSBUaGUgZGlyZWN0b3J5IHBhdGggd2hlcmUgdGhlIHBhY2thZ2UuanNvbiBmaWxlIGlzIGxvY2F0ZWQuXG4gKiBAcmV0dXJuIHt2b2lkfVxuICpcbiAqIEBmdW5jdGlvbiBzZXRQYWNrYWdlQXR0cmlidXRlXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0UGFja2FnZUF0dHJpYnV0ZShcbiAgYXR0cjogc3RyaW5nLFxuICB2YWx1ZTogc3RyaW5nLFxuICBwOiBzdHJpbmcgPSBwcm9jZXNzLmN3ZCgpXG4pOiB2b2lkIHtcbiAgY29uc3QgcGtnID0gZ2V0UGFja2FnZShwKSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICBwa2dbYXR0cl0gPSB2YWx1ZTtcbiAgd3JpdGVGaWxlKHBhdGguam9pbihwLCBgcGFja2FnZS5qc29uYCksIEpTT04uc3RyaW5naWZ5KHBrZywgbnVsbCwgMikpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIHZlcnNpb24gZnJvbSBwYWNrYWdlLmpzb24uXG4gKiBAc3VtbWFyeSBBIGNvbnZlbmllbmNlIGZ1bmN0aW9uIHRoYXQgY2FsbHMgZ2V0UGFja2FnZSB0byByZXRyaWV2ZSB0aGUgXCJ2ZXJzaW9uXCIgcHJvcGVydHkgZnJvbSBwYWNrYWdlLmpzb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gW3A9cHJvY2Vzcy5jd2QoKV0gLSBUaGUgZGlyZWN0b3J5IHBhdGggd2hlcmUgdGhlIHBhY2thZ2UuanNvbiBmaWxlIGlzIGxvY2F0ZWQuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSB2ZXJzaW9uIHN0cmluZyBmcm9tIHBhY2thZ2UuanNvbi5cbiAqIEBmdW5jdGlvbiBnZXRQYWNrYWdlVmVyc2lvblxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UGFja2FnZVZlcnNpb24ocCA9IHByb2Nlc3MuY3dkKCkpOiBzdHJpbmcge1xuICByZXR1cm4gZ2V0UGFja2FnZShwLCBcInZlcnNpb25cIikgYXMgc3RyaW5nO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYWxsIGRlcGVuZGVuY2llcyBmcm9tIHRoZSBwcm9qZWN0LlxuICogQHN1bW1hcnkgRXhlY3V0ZXMgJ25wbSBscyAtLWpzb24nIGNvbW1hbmQgdG8gZ2V0IGEgZGV0YWlsZWQgbGlzdCBvZiBhbGwgZGVwZW5kZW5jaWVzIChwcm9kdWN0aW9uLCBkZXZlbG9wbWVudCwgYW5kIHBlZXIpIGFuZCB0aGVpciB2ZXJzaW9ucy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbcGF0aD1wcm9jZXNzLmN3ZCgpXSAtIFRoZSBkaXJlY3RvcnkgcGF0aCBvZiB0aGUgcHJvamVjdC5cbiAqIEByZXR1cm4ge1Byb21pc2U8e3Byb2Q6IEFycmF5PHtuYW1lOiBzdHJpbmcsIHZlcnNpb246IHN0cmluZ30+LCBkZXY6IEFycmF5PHtuYW1lOiBzdHJpbmcsIHZlcnNpb246IHN0cmluZ30+LCBwZWVyOiBBcnJheTx7bmFtZTogc3RyaW5nLCB2ZXJzaW9uOiBzdHJpbmd9Pn0+fSBBbiBvYmplY3QgY29udGFpbmluZyBhcnJheXMgb2YgcHJvZHVjdGlvbiwgZGV2ZWxvcG1lbnQsIGFuZCBwZWVyIGRlcGVuZGVuY2llcy5cbiAqIEBmdW5jdGlvbiBnZXREZXBlbmRlbmNpZXNcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IGdldERlcGVuZGVuY2llc1xuICogICBwYXJ0aWNpcGFudCBydW5Db21tYW5kXG4gKiAgIHBhcnRpY2lwYW50IEpTT05cbiAqICAgQ2FsbGVyLT4+Z2V0RGVwZW5kZW5jaWVzOiBDYWxsIHdpdGggb3B0aW9uYWwgcGF0aFxuICogICBnZXREZXBlbmRlbmNpZXMtPj5ydW5Db21tYW5kOiBFeGVjdXRlICducG0gbHMgLS1qc29uJ1xuICogICBydW5Db21tYW5kLS0+PmdldERlcGVuZGVuY2llczogUmV0dXJuIGNvbW1hbmQgb3V0cHV0XG4gKiAgIGdldERlcGVuZGVuY2llcy0+PkpTT046IFBhcnNlIGNvbW1hbmQgb3V0cHV0XG4gKiAgIEpTT04tLT4+Z2V0RGVwZW5kZW5jaWVzOiBSZXR1cm4gcGFyc2VkIG9iamVjdFxuICogICBnZXREZXBlbmRlbmNpZXMtPj5nZXREZXBlbmRlbmNpZXM6IFByb2Nlc3MgZGVwZW5kZW5jaWVzXG4gKiAgIGdldERlcGVuZGVuY2llcy0tPj5DYWxsZXI6IFJldHVybiBwcm9jZXNzZWQgZGVwZW5kZW5jaWVzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXREZXBlbmRlbmNpZXMoXG4gIHBhdGg6IHN0cmluZyA9IHByb2Nlc3MuY3dkKClcbik6IFByb21pc2U8RGVwZW5kZW5jeU1hcD4ge1xuICBsZXQgcGtnOiBhbnk7XG5cbiAgdHJ5IHtcbiAgICBwa2cgPSBKU09OLnBhcnNlKGF3YWl0IHJ1bkNvbW1hbmQoYG5wbSBscyAtLWpzb25gLCB7IGN3ZDogcGF0aCB9KS5wcm9taXNlKTtcbiAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHJldHJpZXZlIGRlcGVuZGVuY2llczogJHtlfWApO1xuICB9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBjb25zdCBtYXBwZXIgPSAoZW50cnk6IFtzdHJpbmcsIHVua25vd25dLCBpbmRleDogbnVtYmVyKSA9PiAoe1xuICAgIG5hbWU6IGVudHJ5WzBdLFxuICAgIHZlcnNpb246IChlbnRyeVsxXSBhcyBhbnkpLnZlcnNpb24sXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgcHJvZDogT2JqZWN0LmVudHJpZXMocGtnLmRlcGVuZGVuY2llcyB8fCB7fSkubWFwKG1hcHBlciksXG4gICAgZGV2OiBPYmplY3QuZW50cmllcyhwa2cuZGV2RGVwZW5kZW5jaWVzIHx8IHt9KS5tYXAobWFwcGVyKSxcbiAgICBwZWVyOiBPYmplY3QuZW50cmllcyhwa2cucGVlckRlcGVuZGVuY2llcyB8fCB7fSkubWFwKG1hcHBlciksXG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgcHJvamVjdCBkZXBlbmRlbmNpZXMgdG8gdGhlaXIgbGF0ZXN0IHZlcnNpb25zLlxuICogQHN1bW1hcnkgUnVucyBucG0tY2hlY2stdXBkYXRlcyB0byB1cGRhdGUgcGFja2FnZS5qc29uIGFuZCB0aGVuIGluc3RhbGxzIHRoZSB1cGRhdGVkIGRlcGVuZGVuY2llcy5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGRlcGVuZGVuY2llcyBhcmUgdXBkYXRlZC5cbiAqXG4gKiBAZnVuY3Rpb24gdXBkYXRlRGVwZW5kZW5jaWVzXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdXBkYXRlRGVwZW5kZW5jaWVzKCkge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHVwZGF0ZURlcGVuZGVuY2llcyk7XG4gIGxvZy5pbmZvKFwiY2hlY2tpbmcgZm9yIHVwZGF0ZXMuLi5cIik7XG4gIGF3YWl0IHJ1bkNvbW1hbmQoXCJucHggbnBtLWNoZWNrLXVwZGF0ZXMgLXVcIikucHJvbWlzZTtcbiAgbG9nLmluZm8oXCJ1cGRhdGluZy4uLlwiKTtcbiAgYXdhaXQgcnVuQ29tbWFuZChcIm5weCBucG0gcnVuIGRvLWluc3RhbGxcIikucHJvbWlzZTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSW5zdGFsbHMgZGVwZW5kZW5jaWVzIGlmIHRoZXkgYXJlIG5vdCBhbHJlYWR5IGF2YWlsYWJsZS5cbiAqIEBzdW1tYXJ5IENoZWNrcyBpZiBzcGVjaWZpZWQgZGVwZW5kZW5jaWVzIGFyZSBpbnN0YWxsZWQgYW5kIGluc3RhbGxzIGFueSB0aGF0IGFyZSBtaXNzaW5nLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nW10gfCBzdHJpbmd9IGRlcHMgLSBUaGUgZGVwZW5kZW5jaWVzIHRvIGNoZWNrIGFuZCBwb3RlbnRpYWxseSBpbnN0YWxsLlxuICogQHBhcmFtIHtTaW1wbGVEZXBlbmRlbmN5TWFwfSBbZGVwZW5kZW5jaWVzXSAtIE9wdGlvbmFsIG1hcCBvZiBleGlzdGluZyBkZXBlbmRlbmNpZXMuXG4gKiBAcmV0dXJuIHtQcm9taXNlPFNpbXBsZURlcGVuZGVuY3lNYXA+fSBVcGRhdGVkIG1hcCBvZiBkZXBlbmRlbmNpZXMuXG4gKlxuICogQGZ1bmN0aW9uIGluc3RhbGxJZk5vdEF2YWlsYWJsZVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGluc3RhbGxJZk5vdEF2YWlsYWJsZShcbiAgZGVwczogc3RyaW5nW10gfCBzdHJpbmcsXG4gIGRlcGVuZGVuY2llcz86IFNpbXBsZURlcGVuZGVuY3lNYXBcbikge1xuICBpZiAoIWRlcGVuZGVuY2llcykge1xuICAgIGNvbnN0IGQ6IERlcGVuZGVuY3lNYXAgPSBhd2FpdCBnZXREZXBlbmRlbmNpZXMoKTtcbiAgICBkZXBlbmRlbmNpZXMgPSB7XG4gICAgICBwcm9kOiBkLnByb2Q/Lm1hcCgocCkgPT4gcC5uYW1lKSB8fCBbXSxcbiAgICAgIGRldjogZC5kZXY/Lm1hcCgoZCkgPT4gZC5uYW1lKSB8fCBbXSxcbiAgICAgIHBlZXI6IGQucGVlcj8ubWFwKChwKSA9PiBwLm5hbWUpIHx8IFtdLFxuICAgIH07XG4gIH1cbiAgY29uc3QgeyBwcm9kLCBkZXYsIHBlZXIgfSA9IGRlcGVuZGVuY2llcztcbiAgY29uc3QgaW5zdGFsbGVkID0gQXJyYXkuZnJvbShcbiAgICBuZXcgU2V0KFsuLi4ocHJvZCB8fCBbXSksIC4uLihkZXYgfHwgW10pLCAuLi4ocGVlciB8fCBbXSldKVxuICApO1xuICBkZXBzID0gdHlwZW9mIGRlcHMgPT09IFwic3RyaW5nXCIgPyBbZGVwc10gOiBkZXBzO1xuICBjb25zdCB0b0luc3RhbGwgPSBkZXBzLmZpbHRlcigoZCkgPT4gIWluc3RhbGxlZC5pbmNsdWRlcyhkKSk7XG5cbiAgaWYgKHRvSW5zdGFsbC5sZW5ndGgpIGF3YWl0IGluc3RhbGxEZXBlbmRlbmNpZXMoeyBkZXY6IHRvSW5zdGFsbCB9KTtcbiAgZGVwZW5kZW5jaWVzLmRldiA9IGRlcGVuZGVuY2llcy5kZXYgfHwgW107XG4gIGRlcGVuZGVuY2llcy5kZXYucHVzaCguLi50b0luc3RhbGwpO1xuICByZXR1cm4gZGVwZW5kZW5jaWVzO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBQdXNoZXMgY2hhbmdlcyB0byBHaXQgcmVwb3NpdG9yeS5cbiAqIEBzdW1tYXJ5IFRlbXBvcmFyaWx5IGNoYW5nZXMgR2l0IHVzZXIgY29uZmlndXJhdGlvbiwgY29tbWl0cyBhbGwgY2hhbmdlcywgcHVzaGVzIHRvIHJlbW90ZSwgYW5kIHJlc3RvcmVzIG9yaWdpbmFsIHVzZXIgY29uZmlndXJhdGlvbi5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGNoYW5nZXMgYXJlIHB1c2hlZC5cbiAqXG4gKiBAZnVuY3Rpb24gcHVzaFRvR2l0XG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHVzaFRvR2l0KCkge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHB1c2hUb0dpdCk7XG4gIGNvbnN0IGdpdFVzZXIgPSBhd2FpdCBydW5Db21tYW5kKFwiZ2l0IGNvbmZpZyB1c2VyLm5hbWVcIikucHJvbWlzZTtcbiAgY29uc3QgZ2l0RW1haWwgPSBhd2FpdCBydW5Db21tYW5kKFwiZ2l0IGNvbmZpZyB1c2VyLmVtYWlsXCIpLnByb21pc2U7XG4gIGxvZy52ZXJib3NlKGBjYWNoZWQgZ2l0IGlkOiAke2dpdFVzZXJ9LyR7Z2l0RW1haWx9LiBjaGFuZ2luZyB0byBhdXRvbWF0aW9uYCk7XG4gIGF3YWl0IHJ1bkNvbW1hbmQoJ2dpdCBjb25maWcgdXNlci5lbWFpbCBcImF1dG9tYXRpb25AZGVjYWYudHNcIicpLnByb21pc2U7XG4gIGF3YWl0IHJ1bkNvbW1hbmQoJ2dpdCBjb25maWcgdXNlci5uYW1lIFwiZGVjYWZcIicpLnByb21pc2U7XG4gIGxvZy5pbmZvKFwiUHVzaGluZyBjaGFuZ2VzIHRvIGdpdC4uLlwiKTtcbiAgYXdhaXQgcnVuQ29tbWFuZChcImdpdCBhZGQgLlwiKS5wcm9taXNlO1xuICBhd2FpdCBydW5Db21tYW5kKGBnaXQgY29tbWl0IC1tIFwicmVmcyAjMSAtIGFmdGVyIHJlcG8gc2V0dXBcImApLnByb21pc2U7XG4gIGF3YWl0IHJ1bkNvbW1hbmQoXCJnaXQgcHVzaFwiKS5wcm9taXNlO1xuICBhd2FpdCBydW5Db21tYW5kKGBnaXQgY29uZmlnIHVzZXIuZW1haWwgXCIke2dpdEVtYWlsfVwiYCkucHJvbWlzZTtcbiAgYXdhaXQgcnVuQ29tbWFuZChgZ2l0IGNvbmZpZyB1c2VyLm5hbWUgXCIke2dpdFVzZXJ9XCJgKS5wcm9taXNlO1xuICBsb2cudmVyYm9zZShgcmV2ZXJ0ZWQgdG8gZ2l0IGlkOiAke2dpdFVzZXJ9LyR7Z2l0RW1haWx9YCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEluc3RhbGxzIHByb2plY3QgZGVwZW5kZW5jaWVzLlxuICogQHN1bW1hcnkgSW5zdGFsbHMgcHJvZHVjdGlvbiwgZGV2ZWxvcG1lbnQsIGFuZCBwZWVyIGRlcGVuZGVuY2llcyBhcyBzcGVjaWZpZWQuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGRlcGVuZGVuY2llcyAtIE9iamVjdCBjb250YWluaW5nIGFycmF5cyBvZiBkZXBlbmRlbmNpZXMgdG8gaW5zdGFsbC5cbiAqIEBwYXJhbSB7c3RyaW5nW119IFtkZXBlbmRlbmNpZXMucHJvZF0gLSBQcm9kdWN0aW9uIGRlcGVuZGVuY2llcyB0byBpbnN0YWxsLlxuICogQHBhcmFtIHtzdHJpbmdbXX0gW2RlcGVuZGVuY2llcy5kZXZdIC0gRGV2ZWxvcG1lbnQgZGVwZW5kZW5jaWVzIHRvIGluc3RhbGwuXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBbZGVwZW5kZW5jaWVzLnBlZXJdIC0gUGVlciBkZXBlbmRlbmNpZXMgdG8gaW5zdGFsbC5cbiAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIGRlcGVuZGVuY2llcyBhcmUgaW5zdGFsbGVkLlxuICpcbiAqIEBmdW5jdGlvbiBpbnN0YWxsRGVwZW5kZW5jaWVzXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW5zdGFsbERlcGVuZGVuY2llcyhkZXBlbmRlbmNpZXM6IHtcbiAgcHJvZD86IHN0cmluZ1tdO1xuICBkZXY/OiBzdHJpbmdbXTtcbiAgcGVlcj86IHN0cmluZ1tdO1xufSkge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKGluc3RhbGxEZXBlbmRlbmNpZXMpO1xuICBjb25zdCBwcm9kID0gZGVwZW5kZW5jaWVzLnByb2QgfHwgW107XG4gIGNvbnN0IGRldiA9IGRlcGVuZGVuY2llcy5kZXYgfHwgW107XG4gIGNvbnN0IHBlZXIgPSBkZXBlbmRlbmNpZXMucGVlciB8fCBbXTtcbiAgaWYgKHByb2QubGVuZ3RoKSB7XG4gICAgbG9nLmluZm8oYEluc3RhbGxpbmcgZGVwZW5kZW5jaWVzICR7cHJvZC5qb2luKFwiLCBcIil9Li4uYCk7XG4gICAgYXdhaXQgcnVuQ29tbWFuZChgbnBtIGluc3RhbGwgJHtwcm9kLmpvaW4oXCIgXCIpfWAsIHsgY3dkOiBwcm9jZXNzLmN3ZCgpIH0pXG4gICAgICAucHJvbWlzZTtcbiAgfVxuICBpZiAoZGV2Lmxlbmd0aCkge1xuICAgIGxvZy5pbmZvKGBJbnN0YWxsaW5nIGRldkRlcGVuZGVuY2llcyAke2Rldi5qb2luKFwiLCBcIil9Li4uYCk7XG4gICAgYXdhaXQgcnVuQ29tbWFuZChgbnBtIGluc3RhbGwgLS1zYXZlLWRldiAke2Rldi5qb2luKFwiIFwiKX1gLCB7XG4gICAgICBjd2Q6IHByb2Nlc3MuY3dkKCksXG4gICAgfSkucHJvbWlzZTtcbiAgfVxuICBpZiAocGVlci5sZW5ndGgpIHtcbiAgICBsb2cuaW5mbyhgSW5zdGFsbGluZyBwZWVyRGVwZW5kZW5jaWVzICR7cGVlci5qb2luKFwiLCBcIil9Li4uYCk7XG4gICAgYXdhaXQgcnVuQ29tbWFuZChgbnBtIGluc3RhbGwgLS1zYXZlLXBlZXIgJHtwZWVyLmpvaW4oXCIgXCIpfWAsIHtcbiAgICAgIGN3ZDogcHJvY2Vzcy5jd2QoKSxcbiAgICB9KS5wcm9taXNlO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE5vcm1hbGl6ZXMgaW1wb3J0cyB0byBoYW5kbGUgYm90aCBDb21tb25KUyBhbmQgRVNNb2R1bGUgZm9ybWF0cy5cbiAqIEBzdW1tYXJ5IFV0aWxpdHkgZnVuY3Rpb24gdG8gaGFuZGxlIG1vZHVsZSBpbXBvcnQgZGlmZmVyZW5jZXMgYmV0d2VlbiBmb3JtYXRzLlxuICpcbiAqIEB0ZW1wbGF0ZSBUIC0gVHlwZSBvZiB0aGUgaW1wb3J0ZWQgbW9kdWxlLlxuICogQHBhcmFtIHtQcm9taXNlPFQ+fSBpbXBvcnRQcm9taXNlIC0gUHJvbWlzZSByZXR1cm5lZCBieSBkeW5hbWljIGltcG9ydC5cbiAqIEByZXR1cm4ge1Byb21pc2U8VD59IE5vcm1hbGl6ZWQgbW9kdWxlLlxuICpcbiAqIEBmdW5jdGlvbiBub3JtYWxpemVJbXBvcnRcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBub3JtYWxpemVJbXBvcnQ8VD4oXG4gIGltcG9ydFByb21pc2U6IFByb21pc2U8VD5cbik6IFByb21pc2U8VD4ge1xuICAvLyBDb21tb25KUydzIGBtb2R1bGUuZXhwb3J0c2AgaXMgd3JhcHBlZCBhcyBgZGVmYXVsdGAgaW4gRVNNb2R1bGUuXG4gIHJldHVybiBpbXBvcnRQcm9taXNlLnRoZW4oKG06IGFueSkgPT4gKG0uZGVmYXVsdCB8fCBtKSBhcyBUKTtcbn1cbiIsIi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmluaXRpb24gb2YgYSBzbG9nYW4gaXRlbS5cbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBzaW5nbGUgc2xvZ2FuIGVudHJ5IHdpdGggdGV4dCBhbmQgdGFncy5cbiAqIEB0eXBlZGVmIHtPYmplY3R9IFNsb2dhbkl0ZW1cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBTbG9nYW4gLSBUaGUgc2xvZ2FuIHRleHQuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gVGFncyAtIENvbW1hLXNlcGFyYXRlZCB0YWdzIGRlc2NyaWJpbmcgdGhlIHNsb2dhbi5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBMaXN0IG9mIGF2YWlsYWJsZSBzbG9nYW5zIGZvciBiYW5uZXJzIGFuZCBtZXNzYWdlcy5cbiAqIEBzdW1tYXJ5IEltbXV0YWJsZSBhcnJheSBvZiBzbG9nYW4gZW50cmllcyB1c2VkIGJ5IHtAbGluayBnZXRTbG9nYW59IGFuZCBiYW5uZXIgcmVuZGVyaW5nLlxuICogQHR5cGUge1Nsb2dhbkl0ZW1bXX1cbiAqIEBjb25zdCBzbG9nYW5zXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBzbG9nYW5zID0gW1xuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLCBubyBjaGFvcy4gSnVzdCBjbGVhbiBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2FsbSwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZ1bGwgZmxhdm9yLCBubyBqaXR0ZXJzLiBUaGF0J3MgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGVlcmZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNoaWxsIGZ1bGxzdGFjay4gUG93ZXJlZCBieSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1biwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBCcmV3ZWQgZm9yIGNhbG0gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEJyYW5kaW5nXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU21vb3RoIGFzIHlvdXIgbW9ybmluZyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQWxsIHRoZSBraWNrLCBub25lIG9mIHRoZSBjcmFzaC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEVuZXJnZXRpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNpcCBiYWNrIGFuZCBzaGlwIGZhc3Rlci5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIktlZXAgY2FsbSBhbmQgY29kZSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGhvdXQgdGhlIGNhZmZlaW5lIHNoYWtlcy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEh1bW9yb3VzXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiWW91ciBmdWxsc3RhY2ssIGRlY2FmZmVpbmF0ZWQuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZSwgbm8gY2hhb3MuIEp1c3QgY2xlYW4gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENhbG0sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGdWxsIGZsYXZvciwgbm8gaml0dGVycy4gVGhhdFxcdTIwMTlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hlZXJmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDaGlsbCBmdWxsc3RhY2suIFBvd2VyZWQgYnkgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW4sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogQnJld2VkIGZvciBjYWxtIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBCcmFuZGluZ1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNtb290aCBhcyB5b3VyIG1vcm5pbmcgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkFsbCB0aGUga2ljaywgbm9uZSBvZiB0aGUgY3Jhc2guXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBFbmVyZ2V0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaXAgYmFjayBhbmQgc2hpcCBmYXN0ZXIuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJLZWVwIGNhbG0gYW5kIGNvZGUgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRob3V0IHRoZSBjYWZmZWluZSBzaGFrZXMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBIdW1vcm91c1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIllvdXIgZnVsbHN0YWNrLCBkZWNhZmZlaW5hdGVkLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUsIG5vIGNoYW9zLiBKdXN0IGNsZWFuIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDYWxtLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnVsbCBmbGF2b3IsIG5vIGppdHRlcnMuIFRoYXRcXHUyMDE5cyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoZWVyZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ2hpbGwgZnVsbHN0YWNrLiBQb3dlcmVkIGJ5IERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IEJyZXdlZCBmb3IgY2FsbSBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQnJhbmRpbmdcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTbW9vdGggYXMgeW91ciBtb3JuaW5nIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJBbGwgdGhlIGtpY2ssIG5vbmUgb2YgdGhlIGNyYXNoLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRW5lcmdldGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2lwIGJhY2sgYW5kIHNoaXAgZmFzdGVyLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiS2VlcCBjYWxtIGFuZCBjb2RlIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aG91dCB0aGUgY2FmZmVpbmUgc2hha2VzLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgSHVtb3JvdXNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJZb3VyIGZ1bGxzdGFjaywgZGVjYWZmZWluYXRlZC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLCBubyBjaGFvcy4gSnVzdCBjbGVhbiBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2FsbSwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZ1bGwgZmxhdm9yLCBubyBqaXR0ZXJzLiBUaGF0XFx1MjAxOXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGVlcmZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNoaWxsIGZ1bGxzdGFjay4gUG93ZXJlZCBieSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1biwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBCcmV3ZWQgZm9yIGNhbG0gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEJyYW5kaW5nXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU21vb3RoIGFzIHlvdXIgbW9ybmluZyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQWxsIHRoZSBraWNrLCBub25lIG9mIHRoZSBjcmFzaC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEVuZXJnZXRpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNpcCBiYWNrIGFuZCBzaGlwIGZhc3Rlci5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIktlZXAgY2FsbSBhbmQgY29kZSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGhvdXQgdGhlIGNhZmZlaW5lIHNoYWtlcy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEh1bW9yb3VzXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiWW91ciBmdWxsc3RhY2ssIGRlY2FmZmVpbmF0ZWQuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZSwgbm8gY2hhb3MuIEp1c3QgY2xlYW4gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENhbG0sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGdWxsIGZsYXZvciwgbm8gaml0dGVycy4gVGhhdFxcdTIwMTlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hlZXJmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDaGlsbCBmdWxsc3RhY2suIFBvd2VyZWQgYnkgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW4sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogQnJld2VkIGZvciBjYWxtIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBCcmFuZGluZ1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNtb290aCBhcyB5b3VyIG1vcm5pbmcgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkFsbCB0aGUga2ljaywgbm9uZSBvZiB0aGUgY3Jhc2guXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBFbmVyZ2V0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaXAgYmFjayBhbmQgc2hpcCBmYXN0ZXIuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJLZWVwIGNhbG0gYW5kIGNvZGUgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRob3V0IHRoZSBjYWZmZWluZSBzaGFrZXMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBIdW1vcm91c1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIllvdXIgZnVsbHN0YWNrLCBkZWNhZmZlaW5hdGVkLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUsIG5vIGNoYW9zLiBKdXN0IGNsZWFuIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDYWxtLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnVsbCBmbGF2b3IsIG5vIGppdHRlcnMuIFRoYXRcXHUyMDE5cyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoZWVyZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ2hpbGwgZnVsbHN0YWNrLiBQb3dlcmVkIGJ5IERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IEJyZXdlZCBmb3IgY2FsbSBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQnJhbmRpbmdcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTbW9vdGggYXMgeW91ciBtb3JuaW5nIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJBbGwgdGhlIGtpY2ssIG5vbmUgb2YgdGhlIGNyYXNoLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRW5lcmdldGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2lwIGJhY2sgYW5kIHNoaXAgZmFzdGVyLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiS2VlcCBjYWxtIGFuZCBjb2RlIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aG91dCB0aGUgY2FmZmVpbmUgc2hha2VzLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgSHVtb3JvdXNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJZb3VyIGZ1bGxzdGFjaywgZGVjYWZmZWluYXRlZC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLCBubyBjaGFvcy4gSnVzdCBjbGVhbiBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2FsbSwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZ1bGwgZmxhdm9yLCBubyBqaXR0ZXJzLiBUaGF0XFx1MjAxOXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGVlcmZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNoaWxsIGZ1bGxzdGFjay4gUG93ZXJlZCBieSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1biwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBCcmV3ZWQgZm9yIGNhbG0gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEJyYW5kaW5nXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU21vb3RoIGFzIHlvdXIgbW9ybmluZyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQWxsIHRoZSBraWNrLCBub25lIG9mIHRoZSBjcmFzaC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEVuZXJnZXRpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNpcCBiYWNrIGFuZCBzaGlwIGZhc3Rlci5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIktlZXAgY2FsbSBhbmQgY29kZSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGhvdXQgdGhlIGNhZmZlaW5lIHNoYWtlcy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEh1bW9yb3VzXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiWW91ciBmdWxsc3RhY2ssIGRlY2FmZmVpbmF0ZWQuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZSwgbm8gY2hhb3MuIEp1c3QgY2xlYW4gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENhbG0sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGdWxsIGZsYXZvciwgbm8gaml0dGVycy4gVGhhdFxcdTIwMTlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hlZXJmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDaGlsbCBmdWxsc3RhY2suIFBvd2VyZWQgYnkgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW4sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogQnJld2VkIGZvciBjYWxtIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBCcmFuZGluZ1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNtb290aCBhcyB5b3VyIG1vcm5pbmcgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkFsbCB0aGUga2ljaywgbm9uZSBvZiB0aGUgY3Jhc2guXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBFbmVyZ2V0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaXAgYmFjayBhbmQgc2hpcCBmYXN0ZXIuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJLZWVwIGNhbG0gYW5kIGNvZGUgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRob3V0IHRoZSBjYWZmZWluZSBzaGFrZXMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBIdW1vcm91c1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIllvdXIgZnVsbHN0YWNrLCBkZWNhZmZlaW5hdGVkLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUsIG5vIGNoYW9zLiBKdXN0IGNsZWFuIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDYWxtLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnVsbCBmbGF2b3IsIG5vIGppdHRlcnMuIFRoYXRcXHUyMDE5cyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoZWVyZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ2hpbGwgZnVsbHN0YWNrLiBQb3dlcmVkIGJ5IERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IEJyZXdlZCBmb3IgY2FsbSBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQnJhbmRpbmdcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTbW9vdGggYXMgeW91ciBtb3JuaW5nIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJBbGwgdGhlIGtpY2ssIG5vbmUgb2YgdGhlIGNyYXNoLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRW5lcmdldGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2lwIGJhY2sgYW5kIHNoaXAgZmFzdGVyLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiS2VlcCBjYWxtIGFuZCBjb2RlIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aG91dCB0aGUgY2FmZmVpbmUgc2hha2VzLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgSHVtb3JvdXNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJZb3VyIGZ1bGxzdGFjaywgZGVjYWZmZWluYXRlZC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLCBubyBjaGFvcy4gSnVzdCBjbGVhbiBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2FsbSwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZ1bGwgZmxhdm9yLCBubyBqaXR0ZXJzLiBUaGF0XFx1MjAxOXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGVlcmZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNoaWxsIGZ1bGxzdGFjay4gUG93ZXJlZCBieSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1biwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBCcmV3ZWQgZm9yIGNhbG0gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEJyYW5kaW5nXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU21vb3RoIGFzIHlvdXIgbW9ybmluZyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQWxsIHRoZSBraWNrLCBub25lIG9mIHRoZSBjcmFzaC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEVuZXJnZXRpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNpcCBiYWNrIGFuZCBzaGlwIGZhc3Rlci5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIktlZXAgY2FsbSBhbmQgY29kZSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGhvdXQgdGhlIGNhZmZlaW5lIHNoYWtlcy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEh1bW9yb3VzXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiWW91ciBmdWxsc3RhY2ssIGRlY2FmZmVpbmF0ZWQuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogV2hlcmUgc21hcnQgY29udHJhY3RzIG1lZXQgc21hcnQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFNtYXJ0IENvbnRyYWN0cywgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNoaXAgZEFwcHMgd2l0aG91dCB0aGUgc3RyZXNzLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgQ2hlZXJmdWwsIERldmVsb3BlclwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIENSVUQsIG5vIHByb2JsZW0gXFx1MjAxNCBEZWNhZiB5b3VyIGRhdGEuXCIsXG4gICAgVGFnczogXCJEYXRhLCBOby1DUlVELCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZyb20gRElEIHRvIFVJLCB3aXRob3V0IGJyZWFraW5nIGEgc3dlYXQuXCIsXG4gICAgVGFnczogXCJESUQsIFNTSSwgVUksIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogWW91ciBmcm9udGVuZCBhbHJlYWR5IHVuZGVyc3RhbmRzIHlvdXIgc21hcnQgY29udHJhY3QuXCIsXG4gICAgVGFnczogXCJTbWFydCBDb250cmFjdHMsIERYLCBNYWdpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNlbGYtc292ZXJlaWduIGJ5IGRlc2lnbi4gUHJvZHVjdGl2ZSBieSBkZWZhdWx0LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBEZXZlbG9wZXIsIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCdWlsZCBvbmNlLiBEZXBsb3kgZXZlcnl3aGVyZS4gRGVjZW50cmFsaXplZCBhbmQgZGVsaWdodGZ1bC5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIE11bHRpLXBsYXRmb3JtLCBIYXBweVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRhdGEgdGhhdCBkZWZpbmVzIGl0cyBvd24gZGVzdGlueS5cIixcbiAgICBUYWdzOiBcIlNTSSwgRGF0YS1kcml2ZW4sIEVtcG93ZXJtZW50XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiR29vZGJ5ZSBDUlVELCBoZWxsbyBpbnRlbnQtYmFzZWQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIk5vLUNSVUQsIFVJLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJUaGUgc21vb3RoZXN0IHBhdGggZnJvbSBESUQgdG8gZG9uZS5cIixcbiAgICBUYWdzOiBcIkRJRCwgV29ya2Zsb3csIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQmVjYXVzZSB5b3VyIGRBcHAgZGVzZXJ2ZXMgbW9yZSB0aGFuIGJvaWxlcnBsYXRlLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgRGV2WCwgRWZmaWNpZW5jeVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk93biB5b3VyIGRhdGEuIE93biB5b3VyIGZsb3cuXCIsXG4gICAgVGFnczogXCJTU0ksIENvbnRyb2wsIE93bmVyc2hpcFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIldyaXRlIGxvZ2ljIGxpa2UgaXQgYmVsb25ncyB3aXRoIHRoZSBkYXRhIFxcdTIwMTQgYmVjYXVzZSBpdCBkb2VzLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSBMb2dpYywgRGV2ZWxvcGVyLCBTbWFydFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZyb20gc21hcnQgY29udHJhY3RzIHRvIHNtYXJ0ZXIgZnJvbnRlbmRzLlwiLFxuICAgIFRhZ3M6IFwiU21hcnQgQ29udHJhY3RzLCBVSSwgRFhcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZS4gTm8gQ1JVRC4gSnVzdCB0aGUgZnV0dXJlLlwiLFxuICAgIFRhZ3M6IFwiTm8tQ1JVRCwgQ29mZmVlLXRoZW1lZCwgRnV0dXJpc3RpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlRoZSBmdXR1cmUgb2Ygd2ViMyBVWCBpcyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFVYLCBWaXNpb25cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGggY29uZmlkZW5jZS4gR292ZXJuIHdpdGggY2xhcml0eS5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIEdvdmVybmFuY2UsIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJJbnRlcmZhY2VzIHRoYXQgb2JleSB0aGUgZGF0YSwgbm90IHRoZSBvdGhlciB3YXkgYXJvdW5kLlwiLFxuICAgIFRhZ3M6IFwiVUksIERhdGEgTG9naWMsIFNlbGYtYXdhcmVcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCcmV3IGJ1c2luZXNzIGxvZ2ljIHJpZ2h0IGludG8geW91ciBieXRlcy5cIixcbiAgICBUYWdzOiBcIkRhdGEgTG9naWMsIENvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRJRHMgZG9uZSBkaWZmZXJlbnRseSBcXHUyMDE0IGFuZCBkZWxpZ2h0ZnVsbHkuXCIsXG4gICAgVGFnczogXCJESUQsIFNlbGYtU292ZXJlaWduLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFMtVFM6IFdoZXJlIGJsb2NrY2hhaW4gY29udHJhY3RzIG1lZXQgc21hcnQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFNtYXJ0IENvbnRyYWN0cywgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNoaXAgZEFwcHMgd2l0aG91dCB0aGUgc3RyZXNzLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgQ2hlZXJmdWwsIERldmVsb3BlclwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGJvaWxlcnBsYXRlLCBubyBwcm9ibGVtIFxcdTIwMTQgRGVjYWYtVFMgeW91ciBkYXRhLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSwgTm8tQ1JVRCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGcm9tIERJRCB0byBVSSwgd2l0aG91dCBicmVha2luZyBhIHN3ZWF0LlwiLFxuICAgIFRhZ3M6IFwiRElELCBTU0ksIFVJLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46XG4gICAgICBcIkRlY2FmLVRTLVRTOiBZb3VyIGZyb250ZW5kIGFscmVhZHkgdW5kZXJzdGFuZHMgeW91ciBibG9ja2NoYWluIGNvbnRyYWN0LlwiLFxuICAgIFRhZ3M6IFwiU21hcnQgQ29udHJhY3RzLCBEWCwgTWFnaWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTZWxmLXNvdmVyZWlnbiBieSBkZXNpZ24uIFByb2R1Y3RpdmUgYnkgZGVmYXVsdC5cIixcbiAgICBUYWdzOiBcIlNTSSwgRGV2ZWxvcGVyLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQnVpbGQgb25jZS4gRGVwbG95IGV2ZXJ5d2hlcmUuIERlY2VudHJhbGl6ZWQgYW5kIGRlbGlnaHRmdWwuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBNdWx0aS1wbGF0Zm9ybSwgSGFwcHlcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEYXRhIHRoYXQgZGVmaW5lcyBpdHMgb3duIGRlc3RpbnkuXCIsXG4gICAgVGFnczogXCJTU0ksIERhdGEtZHJpdmVuLCBFbXBvd2VybWVudFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkdvb2RieWUgYm9pbGVycGxhdGUsIGhlbGxvIGludGVudC1iYXNlZCBpbnRlcmZhY2VzLlwiLFxuICAgIFRhZ3M6IFwiTm8tQ1JVRCwgVUksIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlRoZSBzbW9vdGhlc3QgcGF0aCBmcm9tIERJRCB0byBkb25lLlwiLFxuICAgIFRhZ3M6IFwiRElELCBXb3JrZmxvdywgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCZWNhdXNlIHlvdXIgZEFwcCBkZXNlcnZlcyBtb3JlIHRoYW4gYm9pbGVycGxhdGUuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBEZXZYLCBFZmZpY2llbmN5XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiT3duIHlvdXIgZGF0YS4gT3duIHlvdXIgZmxvdy5cIixcbiAgICBUYWdzOiBcIlNTSSwgQ29udHJvbCwgT3duZXJzaGlwXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiV3JpdGUgbG9naWMgbGlrZSBpdCBiZWxvbmdzIHdpdGggdGhlIGRhdGEgXFx1MjAxNCBiZWNhdXNlIGl0IGRvZXMuXCIsXG4gICAgVGFnczogXCJEYXRhIExvZ2ljLCBEZXZlbG9wZXIsIFNtYXJ0XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnJvbSBibG9ja2NoYWluIGNvbnRyYWN0cyB0byBzbWFydGVyIGZyb250ZW5kcy5cIixcbiAgICBUYWdzOiBcIlNtYXJ0IENvbnRyYWN0cywgVUksIERYXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUuIE5vIGJvaWxlcnBsYXRlLiBKdXN0IHRoZSBmdXR1cmUuXCIsXG4gICAgVGFnczogXCJOby1DUlVELCBDb2ZmZWUtdGhlbWVkLCBGdXR1cmlzdGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiVGhlIGZ1dHVyZSBvZiB3ZWIzIFVYIGlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgVVgsIFZpc2lvblwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aCBjb25maWRlbmNlLiBHb3Zlcm4gd2l0aCBjbGFyaXR5LlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgR292ZXJuYW5jZSwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkludGVyZmFjZXMgdGhhdCBvYmV5IHRoZSBkYXRhLCBub3QgdGhlIG90aGVyIHdheSBhcm91bmQuXCIsXG4gICAgVGFnczogXCJVSSwgRGF0YSBMb2dpYywgU2VsZi1hd2FyZVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJyZXcgYnVzaW5lc3MgbG9naWMgcmlnaHQgaW50byB5b3VyIGJ5dGVzLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSBMb2dpYywgQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRElEcyBkb25lIGRpZmZlcmVudGx5IFxcdTIwMTQgYW5kIGRlbGlnaHRmdWxseS5cIixcbiAgICBUYWdzOiBcIkRJRCwgU2VsZi1Tb3ZlcmVpZ24sIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUy1UUzogV2hlcmUgYmxvY2tjaGFpbiBjb250cmFjdHMgbWVldCBzbWFydCBpbnRlcmZhY2VzLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgU21hcnQgQ29udHJhY3RzLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2hpcCBkQXBwcyB3aXRob3V0IHRoZSBzdHJlc3MuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBDaGVlcmZ1bCwgRGV2ZWxvcGVyXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gYm9pbGVycGxhdGUsIG5vIHByb2JsZW0gXFx1MjAxNCBEZWNhZi1UUyB5b3VyIGRhdGEuXCIsXG4gICAgVGFnczogXCJEYXRhLCBOby1DUlVELCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZyb20gRElEIHRvIFVJLCB3aXRob3V0IGJyZWFraW5nIGEgc3dlYXQuXCIsXG4gICAgVGFnczogXCJESUQsIFNTSSwgVUksIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjpcbiAgICAgIFwiRGVjYWYtVFMtVFM6IFlvdXIgZnJvbnRlbmQgYWxyZWFkeSB1bmRlcnN0YW5kcyB5b3VyIGJsb2NrY2hhaW4gY29udHJhY3QuXCIsXG4gICAgVGFnczogXCJTbWFydCBDb250cmFjdHMsIERYLCBNYWdpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNlbGYtc292ZXJlaWduIGJ5IGRlc2lnbi4gUHJvZHVjdGl2ZSBieSBkZWZhdWx0LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBEZXZlbG9wZXIsIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCdWlsZCBvbmNlLiBEZXBsb3kgZXZlcnl3aGVyZS4gRGVjZW50cmFsaXplZCBhbmQgZGVsaWdodGZ1bC5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIE11bHRpLXBsYXRmb3JtLCBIYXBweVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRhdGEgdGhhdCBkZWZpbmVzIGl0cyBvd24gZGVzdGlueS5cIixcbiAgICBUYWdzOiBcIlNTSSwgRGF0YS1kcml2ZW4sIEVtcG93ZXJtZW50XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiR29vZGJ5ZSBib2lsZXJwbGF0ZSwgaGVsbG8gaW50ZW50LWJhc2VkIGludGVyZmFjZXMuXCIsXG4gICAgVGFnczogXCJOby1DUlVELCBVSSwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiVGhlIHNtb290aGVzdCBwYXRoIGZyb20gRElEIHRvIGRvbmUuXCIsXG4gICAgVGFnczogXCJESUQsIFdvcmtmbG93LCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJlY2F1c2UgeW91ciBkQXBwIGRlc2VydmVzIG1vcmUgdGhhbiBib2lsZXJwbGF0ZS5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIERldlgsIEVmZmljaWVuY3lcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJPd24geW91ciBkYXRhLiBPd24geW91ciBmbG93LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBDb250cm9sLCBPd25lcnNoaXBcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJXcml0ZSBsb2dpYyBsaWtlIGl0IGJlbG9uZ3Mgd2l0aCB0aGUgZGF0YSBcXHUyMDE0IGJlY2F1c2UgaXQgZG9lcy5cIixcbiAgICBUYWdzOiBcIkRhdGEgTG9naWMsIERldmVsb3BlciwgU21hcnRcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGcm9tIGJsb2NrY2hhaW4gY29udHJhY3RzIHRvIHNtYXJ0ZXIgZnJvbnRlbmRzLlwiLFxuICAgIFRhZ3M6IFwiU21hcnQgQ29udHJhY3RzLCBVSSwgRFhcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZS4gTm8gYm9pbGVycGxhdGUuIEp1c3QgdGhlIGZ1dHVyZS5cIixcbiAgICBUYWdzOiBcIk5vLUNSVUQsIENvZmZlZS10aGVtZWQsIEZ1dHVyaXN0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJUaGUgZnV0dXJlIG9mIHdlYjMgVVggaXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBVWCwgVmlzaW9uXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRoIGNvbmZpZGVuY2UuIEdvdmVybiB3aXRoIGNsYXJpdHkuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBHb3Zlcm5hbmNlLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiSW50ZXJmYWNlcyB0aGF0IG9iZXkgdGhlIGRhdGEsIG5vdCB0aGUgb3RoZXIgd2F5IGFyb3VuZC5cIixcbiAgICBUYWdzOiBcIlVJLCBEYXRhIExvZ2ljLCBTZWxmLWF3YXJlXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQnJldyBidXNpbmVzcyBsb2dpYyByaWdodCBpbnRvIHlvdXIgYnl0ZXMuXCIsXG4gICAgVGFnczogXCJEYXRhIExvZ2ljLCBDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJESURzIGRvbmUgZGlmZmVyZW50bHkgXFx1MjAxNCBhbmQgZGVsaWdodGZ1bGx5LlwiLFxuICAgIFRhZ3M6IFwiRElELCBTZWxmLVNvdmVyZWlnbiwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTLVRTOiBXaGVyZSBibG9ja2NoYWluIGNvbnRyYWN0cyBtZWV0IHNtYXJ0IGludGVyZmFjZXMuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBTbWFydCBDb250cmFjdHMsIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaGlwIGRBcHBzIHdpdGhvdXQgdGhlIHN0cmVzcy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIENoZWVyZnVsLCBEZXZlbG9wZXJcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBib2lsZXJwbGF0ZSwgbm8gcHJvYmxlbSBcXHUyMDE0IERlY2FmLVRTIHlvdXIgZGF0YS5cIixcbiAgICBUYWdzOiBcIkRhdGEsIE5vLUNSVUQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnJvbSBESUQgdG8gVUksIHdpdGhvdXQgYnJlYWtpbmcgYSBzd2VhdC5cIixcbiAgICBUYWdzOiBcIkRJRCwgU1NJLCBVSSwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOlxuICAgICAgXCJEZWNhZi1UUy1UUzogWW91ciBmcm9udGVuZCBhbHJlYWR5IHVuZGVyc3RhbmRzIHlvdXIgYmxvY2tjaGFpbiBjb250cmFjdC5cIixcbiAgICBUYWdzOiBcIlNtYXJ0IENvbnRyYWN0cywgRFgsIE1hZ2ljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2VsZi1zb3ZlcmVpZ24gYnkgZGVzaWduLiBQcm9kdWN0aXZlIGJ5IGRlZmF1bHQuXCIsXG4gICAgVGFnczogXCJTU0ksIERldmVsb3BlciwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJ1aWxkIG9uY2UuIERlcGxveSBldmVyeXdoZXJlLiBEZWNlbnRyYWxpemVkIGFuZCBkZWxpZ2h0ZnVsLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgTXVsdGktcGxhdGZvcm0sIEhhcHB5XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGF0YSB0aGF0IGRlZmluZXMgaXRzIG93biBkZXN0aW55LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBEYXRhLWRyaXZlbiwgRW1wb3dlcm1lbnRcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJHb29kYnllIGJvaWxlcnBsYXRlLCBoZWxsbyBpbnRlbnQtYmFzZWQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIk5vLUNSVUQsIFVJLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJUaGUgc21vb3RoZXN0IHBhdGggZnJvbSBESUQgdG8gZG9uZS5cIixcbiAgICBUYWdzOiBcIkRJRCwgV29ya2Zsb3csIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQmVjYXVzZSB5b3VyIGRBcHAgZGVzZXJ2ZXMgbW9yZSB0aGFuIGJvaWxlcnBsYXRlLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgRGV2WCwgRWZmaWNpZW5jeVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk93biB5b3VyIGRhdGEuIE93biB5b3VyIGZsb3cuXCIsXG4gICAgVGFnczogXCJTU0ksIENvbnRyb2wsIE93bmVyc2hpcFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIldyaXRlIGxvZ2ljIGxpa2UgaXQgYmVsb25ncyB3aXRoIHRoZSBkYXRhIFxcdTIwMTQgYmVjYXVzZSBpdCBkb2VzLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSBMb2dpYywgRGV2ZWxvcGVyLCBTbWFydFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZyb20gYmxvY2tjaGFpbiBjb250cmFjdHMgdG8gc21hcnRlciBmcm9udGVuZHMuXCIsXG4gICAgVGFnczogXCJTbWFydCBDb250cmFjdHMsIFVJLCBEWFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLiBObyBib2lsZXJwbGF0ZS4gSnVzdCB0aGUgZnV0dXJlLlwiLFxuICAgIFRhZ3M6IFwiTm8tQ1JVRCwgQ29mZmVlLXRoZW1lZCwgRnV0dXJpc3RpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlRoZSBmdXR1cmUgb2Ygd2ViMyBVWCBpcyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFVYLCBWaXNpb25cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGggY29uZmlkZW5jZS4gR292ZXJuIHdpdGggY2xhcml0eS5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIEdvdmVybmFuY2UsIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJJbnRlcmZhY2VzIHRoYXQgb2JleSB0aGUgZGF0YSwgbm90IHRoZSBvdGhlciB3YXkgYXJvdW5kLlwiLFxuICAgIFRhZ3M6IFwiVUksIERhdGEgTG9naWMsIFNlbGYtYXdhcmVcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCcmV3IGJ1c2luZXNzIGxvZ2ljIHJpZ2h0IGludG8geW91ciBieXRlcy5cIixcbiAgICBUYWdzOiBcIkRhdGEgTG9naWMsIENvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRJRHMgZG9uZSBkaWZmZXJlbnRseSBcXHUyMDE0IGFuZCBkZWxpZ2h0ZnVsbHkuXCIsXG4gICAgVGFnczogXCJESUQsIFNlbGYtU292ZXJlaWduLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFMtVFM6IFdoZXJlIGJsb2NrY2hhaW4gY29udHJhY3RzIG1lZXQgc21hcnQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFNtYXJ0IENvbnRyYWN0cywgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNoaXAgZEFwcHMgd2l0aG91dCB0aGUgc3RyZXNzLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgQ2hlZXJmdWwsIERldmVsb3BlclwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGJvaWxlcnBsYXRlLCBubyBwcm9ibGVtIFxcdTIwMTQgRGVjYWYtVFMgeW91ciBkYXRhLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSwgTm8tQ1JVRCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGcm9tIERJRCB0byBVSSwgd2l0aG91dCBicmVha2luZyBhIHN3ZWF0LlwiLFxuICAgIFRhZ3M6IFwiRElELCBTU0ksIFVJLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46XG4gICAgICBcIkRlY2FmLVRTLVRTOiBZb3VyIGZyb250ZW5kIGFscmVhZHkgdW5kZXJzdGFuZHMgeW91ciBibG9ja2NoYWluIGNvbnRyYWN0LlwiLFxuICAgIFRhZ3M6IFwiU21hcnQgQ29udHJhY3RzLCBEWCwgTWFnaWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTZWxmLXNvdmVyZWlnbiBieSBkZXNpZ24uIFByb2R1Y3RpdmUgYnkgZGVmYXVsdC5cIixcbiAgICBUYWdzOiBcIlNTSSwgRGV2ZWxvcGVyLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQnVpbGQgb25jZS4gRGVwbG95IGV2ZXJ5d2hlcmUuIERlY2VudHJhbGl6ZWQgYW5kIGRlbGlnaHRmdWwuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBNdWx0aS1wbGF0Zm9ybSwgSGFwcHlcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEYXRhIHRoYXQgZGVmaW5lcyBpdHMgb3duIGRlc3RpbnkuXCIsXG4gICAgVGFnczogXCJTU0ksIERhdGEtZHJpdmVuLCBFbXBvd2VybWVudFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkdvb2RieWUgYm9pbGVycGxhdGUsIGhlbGxvIGludGVudC1iYXNlZCBpbnRlcmZhY2VzLlwiLFxuICAgIFRhZ3M6IFwiTm8tQ1JVRCwgVUksIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlRoZSBzbW9vdGhlc3QgcGF0aCBmcm9tIERJRCB0byBkb25lLlwiLFxuICAgIFRhZ3M6IFwiRElELCBXb3JrZmxvdywgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCZWNhdXNlIHlvdXIgZEFwcCBkZXNlcnZlcyBtb3JlIHRoYW4gYm9pbGVycGxhdGUuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBEZXZYLCBFZmZpY2llbmN5XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiT3duIHlvdXIgZGF0YS4gT3duIHlvdXIgZmxvdy5cIixcbiAgICBUYWdzOiBcIlNTSSwgQ29udHJvbCwgT3duZXJzaGlwXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiV3JpdGUgbG9naWMgbGlrZSBpdCBiZWxvbmdzIHdpdGggdGhlIGRhdGEgXFx1MjAxNCBiZWNhdXNlIGl0IGRvZXMuXCIsXG4gICAgVGFnczogXCJEYXRhIExvZ2ljLCBEZXZlbG9wZXIsIFNtYXJ0XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnJvbSBibG9ja2NoYWluIGNvbnRyYWN0cyB0byBzbWFydGVyIGZyb250ZW5kcy5cIixcbiAgICBUYWdzOiBcIlNtYXJ0IENvbnRyYWN0cywgVUksIERYXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUuIE5vIGJvaWxlcnBsYXRlLiBKdXN0IHRoZSBmdXR1cmUuXCIsXG4gICAgVGFnczogXCJOby1DUlVELCBDb2ZmZWUtdGhlbWVkLCBGdXR1cmlzdGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiVGhlIGZ1dHVyZSBvZiB3ZWIzIFVYIGlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgVVgsIFZpc2lvblwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aCBjb25maWRlbmNlLiBHb3Zlcm4gd2l0aCBjbGFyaXR5LlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgR292ZXJuYW5jZSwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkludGVyZmFjZXMgdGhhdCBvYmV5IHRoZSBkYXRhLCBub3QgdGhlIG90aGVyIHdheSBhcm91bmQuXCIsXG4gICAgVGFnczogXCJVSSwgRGF0YSBMb2dpYywgU2VsZi1hd2FyZVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJyZXcgYnVzaW5lc3MgbG9naWMgcmlnaHQgaW50byB5b3VyIGJ5dGVzLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSBMb2dpYywgQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRElEcyBkb25lIGRpZmZlcmVudGx5IFxcdTIwMTQgYW5kIGRlbGlnaHRmdWxseS5cIixcbiAgICBUYWdzOiBcIkRJRCwgU2VsZi1Tb3ZlcmVpZ24sIFBsYXlmdWxcIixcbiAgfSxcbl07XG4iLCJpbXBvcnQgeyBzbG9nYW5zIH0gZnJvbSBcIi4uL2Fzc2V0cy9zbG9nYW5zXCI7XG5pbXBvcnQgeyBzdHlsZSB9IGZyb20gXCJzdHlsZWQtc3RyaW5nLWJ1aWxkZXJcIjtcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBcnJheSBvZiBBTlNJIGNvbG9yIGNvZGVzIGZvciBiYW5uZXIgc3R5bGluZy5cbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBzZXQgb2YgQU5TSSBjb2xvciBjb2RlcyB1c2VkIHRvIHN0eWxlIHRoZSBiYW5uZXIgdGV4dC5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuY29uc3QgY29sb3JzID0gW1xuICBcIlxceDFiWzM4OzU7MjE1bVwiLCAvLyBzb2Z0IG9yYW5nZVxuICBcIlxceDFiWzM4OzU7MjA5bVwiLCAvLyBjb3JhbFxuICBcIlxceDFiWzM4OzU7MjA1bVwiLCAvLyBwaW5rXG4gIFwiXFx4MWJbMzg7NTsyMTBtXCIsIC8vIHBlYWNoeVxuICBcIlxceDFiWzM4OzU7MjE3bVwiLCAvLyBzYWxtb25cbiAgXCJcXHgxYlszODs1OzIxNm1cIiwgLy8gbGlnaHQgY29yYWxcbiAgXCJcXHgxYlszODs1OzIyNG1cIiwgLy8gbGlnaHQgcGVhY2hcbiAgXCJcXHgxYlszODs1OzIzMG1cIiwgLy8gc29mdCBjcmVhbVxuICBcIlxceDFiWzM4OzU7MjMwbVwiLCAvLyBzb2Z0IGNyZWFtXG5dO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBQcmludHMgYSBzdHlsZWQgYmFubmVyIHRvIHRoZSBjb25zb2xlLlxuICogQHN1bW1hcnkgR2VuZXJhdGVzIGFuZCBwcmludHMgYSBjb2xvcmZ1bCBBU0NJSSBhcnQgYmFubmVyIHdpdGggYSByYW5kb20gc2xvZ2FuLlxuICogQHBhcmFtIHtMb2dnZXJ9IFtsb2dnZXJdIC0gT3B0aW9uYWwgbG9nZ2VyIGZvciB2ZXJib3NlIG91dHB1dC5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqIEBmdW5jdGlvbiBwcmludEJhbm5lclxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBwcmludEJhbm5lclxuICogICBwYXJ0aWNpcGFudCBnZXRTbG9nYW5cbiAqICAgcGFydGljaXBhbnQgcGFkRW5kXG4gKiAgIHBhcnRpY2lwYW50IGNvbnNvbGVcbiAqICAgcHJpbnRCYW5uZXItPj5nZXRTbG9nYW46IENhbGwgZ2V0U2xvZ2FuKClcbiAqICAgZ2V0U2xvZ2FuLS0+PnByaW50QmFubmVyOiBSZXR1cm4gcmFuZG9tIHNsb2dhblxuICogICBwcmludEJhbm5lci0+PnByaW50QmFubmVyOiBDcmVhdGUgYmFubmVyIEFTQ0lJIGFydFxuICogICBwcmludEJhbm5lci0+PnByaW50QmFubmVyOiBTcGxpdCBiYW5uZXIgaW50byBsaW5lc1xuICogICBwcmludEJhbm5lci0+PnByaW50QmFubmVyOiBDYWxjdWxhdGUgbWF4IGxpbmUgbGVuZ3RoXG4gKiAgIHByaW50QmFubmVyLT4+cGFkRW5kOiBDYWxsIHBhZEVuZCB3aXRoIHNsb2dhblxuICogICBwYWRFbmQtLT4+cHJpbnRCYW5uZXI6IFJldHVybiBwYWRkZWQgc2xvZ2FuIGxpbmVcbiAqICAgbG9vcCBGb3IgZWFjaCBiYW5uZXIgbGluZVxuICogICAgIHByaW50QmFubmVyLT4+c3R5bGU6IENhbGwgc3R5bGUobGluZSlcbiAqICAgICBzdHlsZS0tPj5wcmludEJhbm5lcjogUmV0dXJuIHN0eWxlZCBsaW5lXG4gKiAgICAgcHJpbnRCYW5uZXItPj5jb25zb2xlOiBMb2cgc3R5bGVkIGxpbmVcbiAqICAgZW5kXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcmludEJhbm5lcihsb2dnZXI/OiBMb2dnZXIpIHtcbiAgY29uc3QgbWVzc2FnZSA9IGdldFNsb2dhbigpO1xuICBjb25zdCBiYW5uZXI6IHN0cmluZyB8IHN0cmluZ1tdID1cbiAgICBgIyAgICAgICAgICAgICAgICAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paI4paT4paS4paRICDilpHilpLilpPilojilojilojilojilojilojilojilojilpPilpLilpEgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paI4paI4paT4paS4paRICAgICAgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paI4paT4paS4paRIFxuIyAgICAgICggKCAgICAgICAg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpEgICAgICAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAg4paR4paS4paT4paI4paT4paS4paRICAgICAgICBcbiMgICAgICAgKSApICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpEgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAgICAgICAgICAg4paR4paS4paT4paI4paT4paS4paRICAgICDilpHilpLilpPilojilpPilpLilpEgICAgICAgIFxuIyAgICBbPT09PT09PV0gICAg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paI4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAgXG4jICAgICBcXGAtLS0tLcK0ICAgICDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paT4paS4paRICAgICAgICDilpHilpLilpPilojilpPilpLilpEgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpEgICAgICAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSBcbiMgICAgICAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpEgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paT4paS4paRICAgICAgICAgICAgICAgICDilpHilpLilpPilojilpPilpLilpEgICAgICAgICAgICDilpHilpLilpPilojilpPilpLilpEgXG4jICAgICAgICAgICAgICAgICDilpHilpLilpPilojilojilojilojilojilojilojilpPilpLilpEgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paT4paS4paRICDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paT4paS4paRICAgICAgICAgICAgICAgICDilpHilpLilpPilojilpPilpLilpEgICAgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAgXG4jYC5zcGxpdChcIlxcblwiKTtcbiAgY29uc3QgbWF4TGVuZ3RoID0gYmFubmVyLnJlZHVjZSgobWF4LCBsaW5lKSA9PiBNYXRoLm1heChtYXgsIGxpbmUubGVuZ3RoKSwgMCk7XG4gIGJhbm5lci5wdXNoKGAjICAke21lc3NhZ2UucGFkU3RhcnQobWF4TGVuZ3RoIC0gMyl9YCk7XG4gIGJhbm5lci5mb3JFYWNoKChsaW5lLCBpbmRleCkgPT4ge1xuICAgIChsb2dnZXIgPyBsb2dnZXIuaW5mby5iaW5kKGxvZ2dlcikgOiBjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpKShcbiAgICAgIHN0eWxlKGxpbmUgfHwgXCJcIikucmF3KGNvbG9yc1tpbmRleF0pLnRleHRcbiAgICApO1xuICB9KTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgc2xvZ2FuIGZyb20gdGhlIHByZWRlZmluZWQgbGlzdC5cbiAqIEBzdW1tYXJ5IEZldGNoZXMgYSByYW5kb20gc2xvZ2FuIG9yIGEgc3BlY2lmaWMgb25lIGJ5IGluZGV4IGZyb20gdGhlIHNsb2dhbnMgbGlzdC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbaV0gLSBPcHRpb25hbCBpbmRleCB0byByZXRyaWV2ZSBhIHNwZWNpZmljIHNsb2dhbi5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHNlbGVjdGVkIHNsb2dhbi5cbiAqIEBmdW5jdGlvbiBnZXRTbG9nYW5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgZ2V0U2xvZ2FuXG4gKiAgIHBhcnRpY2lwYW50IE1hdGgucmFuZG9tXG4gKiAgIHBhcnRpY2lwYW50IHNsb2dhbnNcbiAqICAgYWx0IGkgaXMgdW5kZWZpbmVkXG4gKiAgICAgZ2V0U2xvZ2FuLT4+TWF0aC5yYW5kb206IEdlbmVyYXRlIHJhbmRvbSBpbmRleFxuICogICAgIE1hdGgucmFuZG9tLS0+PmdldFNsb2dhbjogUmV0dXJuIHJhbmRvbSBpbmRleFxuICogICBlbHNlIGkgaXMgZGVmaW5lZFxuICogICAgIE5vdGUgb3ZlciBnZXRTbG9nYW46IFVzZSBwcm92aWRlZCBpbmRleFxuICogICBlbmRcbiAqICAgZ2V0U2xvZ2FuLT4+c2xvZ2FuczogQWNjZXNzIHNsb2dhbiBhdCBpbmRleFxuICogICBzbG9nYW5zLS0+PmdldFNsb2dhbjogUmV0dXJuIHNsb2dhblxuICogICBhbHQgRXJyb3Igb2NjdXJzXG4gKiAgICAgZ2V0U2xvZ2FuLT4+Z2V0U2xvZ2FuOiBUaHJvdyBlcnJvclxuICogICBlbmRcbiAqICAgZ2V0U2xvZ2FuLS0+PkNhbGxlcjogUmV0dXJuIHNsb2dhblxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2xvZ2FuKGk/OiBudW1iZXIpOiBzdHJpbmcge1xuICB0cnkge1xuICAgIGkgPVxuICAgICAgdHlwZW9mIGkgPT09IFwidW5kZWZpbmVkXCIgPyBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBzbG9nYW5zLmxlbmd0aCkgOiBpO1xuICAgIHJldHVybiBzbG9nYW5zW2ldLlNsb2dhbjtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byByZXRyaWV2ZSBzbG9nYW5zOiAke2Vycm9yfWApO1xuICB9XG59XG4iLCJpbXBvcnQgeyBQYXJzZUFyZ3NSZXN1bHQgfSBmcm9tIFwiLi4vaW5wdXQvdHlwZXNcIjtcbmltcG9ydCB7IENvbW1hbmRPcHRpb25zIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IFVzZXJJbnB1dCB9IGZyb20gXCIuLi9pbnB1dC9pbnB1dFwiO1xuaW1wb3J0IHsgRGVmYXVsdENvbW1hbmRPcHRpb25zLCBEZWZhdWx0Q29tbWFuZFZhbHVlcyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgZ2V0RGVwZW5kZW5jaWVzLCBnZXRQYWNrYWdlVmVyc2lvbiB9IGZyb20gXCIuLi91dGlscy9mc1wiO1xuaW1wb3J0IHsgcHJpbnRCYW5uZXIgfSBmcm9tIFwiLi4vb3V0cHV0L2NvbW1vblwiO1xuaW1wb3J0IHtcbiAgTG9nZ2VkQ2xhc3MsXG4gIExvZ2dlZEVudmlyb25tZW50LFxuICBMb2dnZXIsXG4gIExvZ2dpbmcsXG4gIExvZ2dpbmdDb25maWcsXG59IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG4vKipcbiAqIEBjbGFzcyBDb21tYW5kXG4gKiBAYWJzdHJhY3RcbiAqIEB0ZW1wbGF0ZSBJIC0gVGhlIHR5cGUgb2YgaW5wdXQgb3B0aW9ucyBmb3IgdGhlIGNvbW1hbmQuXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXR1cm4gdHlwZSBvZiB0aGUgY29tbWFuZCBleGVjdXRpb24uXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKiBAZGVzY3JpcHRpb24gQWJzdHJhY3QgYmFzZSBjbGFzcyBmb3IgY29tbWFuZCBpbXBsZW1lbnRhdGlvbi5cbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIGEgc3RydWN0dXJlIGZvciBjcmVhdGluZyBjb21tYW5kLWxpbmUgaW50ZXJmYWNlIGNvbW1hbmRzIHdpdGggaW5wdXQgaGFuZGxpbmcsIGxvZ2dpbmcsIGFuZCBleGVjdXRpb24gZmxvdy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBjb21tYW5kLlxuICogQHBhcmFtIHtDb21tYW5kT3B0aW9uczxJPn0gW2lucHV0c10gLSBUaGUgaW5wdXQgb3B0aW9ucyBmb3IgdGhlIGNvbW1hbmQuXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBbcmVxdWlyZW1lbnRzXSAtIFRoZSBsaXN0IG9mIHJlcXVpcmVkIGRlcGVuZGVuY2llcyBmb3IgdGhlIGNvbW1hbmQuXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBDb21tYW5kPEksIFI+IGV4dGVuZHMgTG9nZ2VkQ2xhc3Mge1xuICAvKipcbiAgICogQHN0YXRpY1xuICAgKiBAZGVzY3JpcHRpb24gU3RhdGljIGxvZ2dlciBmb3IgdGhlIENvbW1hbmQgY2xhc3MuXG4gICAqIEB0eXBlIHtMb2dnZXJ9XG4gICAqL1xuICBzdGF0aWMgbG9nOiBMb2dnZXI7XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBuYW1lOiBzdHJpbmcsXG4gICAgcHJvdGVjdGVkIGlucHV0czogQ29tbWFuZE9wdGlvbnM8ST4gPSB7fSBhcyB1bmtub3duIGFzIENvbW1hbmRPcHRpb25zPEk+LFxuICAgIHByb3RlY3RlZCByZXF1aXJlbWVudHM6IHN0cmluZ1tdID0gW11cbiAgKSB7XG4gICAgc3VwZXIoKTtcbiAgICBpZiAoIUNvbW1hbmQubG9nKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQ29tbWFuZCwgXCJsb2dcIiwge1xuICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgIHZhbHVlOiBMb2dnaW5nLmZvcihDb21tYW5kLm5hbWUpLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHRoaXMuaW5wdXRzID0gT2JqZWN0LmFzc2lnbihcbiAgICAgIHt9LFxuICAgICAgRGVmYXVsdENvbW1hbmRPcHRpb25zLFxuICAgICAgaW5wdXRzXG4gICAgKSBhcyBDb21tYW5kT3B0aW9uczxJPjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvdGVjdGVkXG4gICAqIEBhc3luY1xuICAgKiBAZGVzY3JpcHRpb24gQ2hlY2tzIGlmIGFsbCByZXF1aXJlZCBkZXBlbmRlbmNpZXMgYXJlIHByZXNlbnQuXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyB0aGUgbGlzdCBvZiBkZXBlbmRlbmNpZXMgYW5kIGNvbXBhcmVzIGl0IGFnYWluc3QgdGhlIHJlcXVpcmVkIGRlcGVuZGVuY2llcyBmb3IgdGhlIGNvbW1hbmQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBjaGVjayBpcyBjb21wbGV0ZS5cbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ29tbWFuZFxuICAgKiAgIHBhcnRpY2lwYW50IGdldERlcGVuZGVuY2llc1xuICAgKiAgIHBhcnRpY2lwYW50IFNldFxuICAgKiAgIENvbW1hbmQtPj5nZXREZXBlbmRlbmNpZXM6IENhbGxcbiAgICogICBnZXREZXBlbmRlbmNpZXMtLT4+Q29tbWFuZDogUmV0dXJuIHtwcm9kLCBkZXYsIHBlZXJ9XG4gICAqICAgQ29tbWFuZC0+PlNldDogQ3JlYXRlIFNldCBmcm9tIHByb2QsIGRldiwgcGVlclxuICAgKiAgIFNldC0tPj5Db21tYW5kOiBSZXR1cm4gdW5pcXVlIGRlcGVuZGVuY2llc1xuICAgKiAgIENvbW1hbmQtPj5Db21tYW5kOiBDb21wYXJlIGFnYWluc3QgcmVxdWlyZW1lbnRzXG4gICAqICAgYWx0IE1pc3NpbmcgZGVwZW5kZW5jaWVzXG4gICAqICAgICBDb21tYW5kLT4+Q29tbWFuZDogQWRkIHRvIG1pc3NpbmcgbGlzdFxuICAgKiAgIGVuZFxuICAgKiAgIE5vdGUgb3ZlciBDb21tYW5kOiBJZiBtaXNzaW5nLmxlbmd0aCA+IDAsIGhhbmRsZSBtaXNzaW5nIGRlcGVuZGVuY2llc1xuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGNoZWNrUmVxdWlyZW1lbnRzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgcHJvZCwgZGV2LCBwZWVyIH0gPSBhd2FpdCBnZXREZXBlbmRlbmNpZXMoKTtcbiAgICBjb25zdCBtaXNzaW5nID0gW107XG4gICAgY29uc3QgZnVsbExpc3QgPSBBcnJheS5mcm9tKFxuICAgICAgbmV3IFNldChbLi4ucHJvZCwgLi4uZGV2LCAuLi5wZWVyXSkudmFsdWVzKClcbiAgICApLm1hcCgoZCkgPT4gZC5uYW1lKTtcbiAgICBmb3IgKGNvbnN0IGRlcCBvZiB0aGlzLnJlcXVpcmVtZW50cylcbiAgICAgIGlmICghZnVsbExpc3QuaW5jbHVkZXMoZGVwKSkgbWlzc2luZy5wdXNoKGRlcCk7XG5cbiAgICBpZiAoIW1pc3NpbmcubGVuZ3RoKSByZXR1cm47XG4gIH1cblxuICAvKipcbiAgICogQHByb3RlY3RlZFxuICAgKiBAZGVzY3JpcHRpb24gUHJvdmlkZXMgaGVscCBpbmZvcm1hdGlvbiBmb3IgdGhlIGNvbW1hbmQuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIHNob3VsZCBiZSBvdmVycmlkZGVuIGluIGRlcml2ZWQgY2xhc3NlcyB0byBwcm92aWRlIHNwZWNpZmljIGhlbHAgaW5mb3JtYXRpb24uXG4gICAqIEBwYXJhbSB7UGFyc2VBcmdzUmVzdWx0fSBhcmdzIC0gVGhlIHBhcnNlZCBjb21tYW5kLWxpbmUgYXJndW1lbnRzLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgcHJvdGVjdGVkIGhlbHAoYXJnczogUGFyc2VBcmdzUmVzdWx0KTogdm9pZCB7XG4gICAgcmV0dXJuIHRoaXMubG9nLmluZm8oXG4gICAgICBgVGhpcyBpcyBoZWxwLiBJJ20gbm8gdXNlIGJlY2F1c2UgSSBzaG91bGQgaGF2ZSBiZWVuIG92ZXJyaWRkZW4uYFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3RlY3RlZFxuICAgKiBAYWJzdHJhY3RcbiAgICogQGRlc2NyaXB0aW9uIFJ1bnMgdGhlIGNvbW1hbmQgd2l0aCB0aGUgcHJvdmlkZWQgYXJndW1lbnRzLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBzaG91bGQgYmUgaW1wbGVtZW50ZWQgaW4gZGVyaXZlZCBjbGFzc2VzIHRvIGRlZmluZSB0aGUgY29tbWFuZCdzIGJlaGF2aW9yLlxuICAgKiBAcGFyYW0ge1BhcnNlQXJnc1Jlc3VsdH0gYW5zd2VycyAtIFRoZSBwYXJzZWQgY29tbWFuZC1saW5lIGFyZ3VtZW50cy5cbiAgICogQHJldHVybnMge1Byb21pc2U8UiB8IHN0cmluZyB8IHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBjb21tYW5kJ3MgcmVzdWx0LlxuICAgKi9cbiAgcHJvdGVjdGVkIGFic3RyYWN0IHJ1bjxSPihcbiAgICBhbnN3ZXJzOiBMb2dnaW5nQ29uZmlnICZcbiAgICAgIHR5cGVvZiBEZWZhdWx0Q29tbWFuZFZhbHVlcyAmIHsgW2sgaW4ga2V5b2YgSV06IHVua25vd24gfVxuICApOiBQcm9taXNlPFIgfCBzdHJpbmcgfCB2b2lkPjtcblxuICAvKipcbiAgICogQGFzeW5jXG4gICAqIEBkZXNjcmlwdGlvbiBFeGVjdXRlcyB0aGUgY29tbWFuZC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgaGFuZGxlcyB0aGUgb3ZlcmFsbCBleGVjdXRpb24gZmxvdyBvZiB0aGUgY29tbWFuZCwgaW5jbHVkaW5nIHBhcnNpbmcgYXJndW1lbnRzLFxuICAgKiBzZXR0aW5nIHVwIGxvZ2dpbmcsIGNoZWNraW5nIGZvciB2ZXJzaW9uIG9yIGhlbHAgcmVxdWVzdHMsIGFuZCBydW5uaW5nIHRoZSBjb21tYW5kLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSIHwgc3RyaW5nIHwgdm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGNvbW1hbmQncyByZXN1bHQuXG4gICAqXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IENvbW1hbmRcbiAgICogICBwYXJ0aWNpcGFudCBVc2VySW5wdXRcbiAgICogICBwYXJ0aWNpcGFudCBMb2dnaW5nXG4gICAqICAgcGFydGljaXBhbnQgZ2V0UGFja2FnZVZlcnNpb25cbiAgICogICBwYXJ0aWNpcGFudCBwcmludEJhbm5lclxuICAgKiAgIENvbW1hbmQtPj5Vc2VySW5wdXQ6IHBhcnNlQXJncyhpbnB1dHMpXG4gICAqICAgVXNlcklucHV0LS0+PkNvbW1hbmQ6IFJldHVybiBQYXJzZUFyZ3NSZXN1bHRcbiAgICogICBDb21tYW5kLT4+Q29tbWFuZDogUHJvY2VzcyBvcHRpb25zXG4gICAqICAgQ29tbWFuZC0+PkxvZ2dpbmc6IHNldENvbmZpZyhvcHRpb25zKVxuICAgKiAgIGFsdCB2ZXJzaW9uIHJlcXVlc3RlZFxuICAgKiAgICAgQ29tbWFuZC0+PmdldFBhY2thZ2VWZXJzaW9uOiBDYWxsXG4gICAqICAgICBnZXRQYWNrYWdlVmVyc2lvbi0tPj5Db21tYW5kOiBSZXR1cm4gdmVyc2lvblxuICAgKiAgIGVsc2UgaGVscCByZXF1ZXN0ZWRcbiAgICogICAgIENvbW1hbmQtPj5Db21tYW5kOiBoZWxwKGFyZ3MpXG4gICAqICAgZWxzZSBiYW5uZXIgcmVxdWVzdGVkXG4gICAqICAgICBDb21tYW5kLT4+cHJpbnRCYW5uZXI6IENhbGxcbiAgICogICBlbmRcbiAgICogICBDb21tYW5kLT4+Q29tbWFuZDogcnVuKGFyZ3MpXG4gICAqICAgYWx0IGVycm9yIG9jY3Vyc1xuICAgKiAgICAgQ29tbWFuZC0+PkNvbW1hbmQ6IExvZyBlcnJvclxuICAgKiAgIGVuZFxuICAgKiAgIENvbW1hbmQtLT4+Q29tbWFuZDogUmV0dXJuIHJlc3VsdFxuICAgKi9cbiAgYXN5bmMgZXhlY3V0ZSgpOiBQcm9taXNlPFIgfCBzdHJpbmcgfCB2b2lkPiB7XG4gICAgY29uc3QgYXJnczogUGFyc2VBcmdzUmVzdWx0ID0gVXNlcklucHV0LnBhcnNlQXJncyh0aGlzLmlucHV0cyk7XG4gICAgY29uc3QgZW52ID0gTG9nZ2VkRW52aXJvbm1lbnQuYWNjdW11bGF0ZShEZWZhdWx0Q29tbWFuZFZhbHVlcykuYWNjdW11bGF0ZShcbiAgICAgIGFyZ3MudmFsdWVzXG4gICAgKTtcbiAgICBjb25zdCB7IHZlcnNpb24sIGhlbHAsIGJhbm5lciB9ID0gZW52O1xuXG4gICAgaWYgKHZlcnNpb24pIHtcbiAgICAgIHJldHVybiBnZXRQYWNrYWdlVmVyc2lvbigpO1xuICAgIH1cblxuICAgIGlmIChoZWxwKSB7XG4gICAgICByZXR1cm4gdGhpcy5oZWxwKGFyZ3MpO1xuICAgIH1cblxuICAgIGlmIChiYW5uZXIpXG4gICAgICBwcmludEJhbm5lcihcbiAgICAgICAgdGhpcy5sb2cuZm9yKHByaW50QmFubmVyLCB7XG4gICAgICAgICAgdGltZXN0YW1wOiBmYWxzZSxcbiAgICAgICAgICBzdHlsZTogZmFsc2UsXG4gICAgICAgICAgY29udGV4dDogZmFsc2UsXG4gICAgICAgICAgbG9nTGV2ZWw6IGZhbHNlLFxuICAgICAgICB9KVxuICAgICAgKTtcblxuICAgIGxldCByZXN1bHQ7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGF3YWl0IHRoaXMucnVuKGVudiBhcyBhbnkpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRoaXMubG9nLmVycm9yKGBFcnJvciB3aGlsZSBydW5uaW5nIHByb3ZpZGVkIGNsaSBmdW5jdGlvbjogJHtlfWApO1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0IGFzIFI7XG4gIH1cbn1cbiIsIi8qIGlzdGFuYnVsIGlnbm9yZSBmaWxlICovXG5pbXBvcnQgaHR0cHMgZnJvbSBcImh0dHBzXCI7XG5pbXBvcnQgeyBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEEgc2ltcGxlIEhUVFAgY2xpZW50IGZvciBkb3dubG9hZGluZyBmaWxlcy5cbiAqIEBzdW1tYXJ5IFRoaXMgY2xhc3MgcHJvdmlkZXMgZnVuY3Rpb25hbGl0eSB0byBkb3dubG9hZCBmaWxlcyBmcm9tIEhUVFBTIFVSTHMuXG4gKiBJdCB1c2VzIE5vZGUuanMgYnVpbHQtaW4gaHR0cHMgbW9kdWxlIHRvIG1ha2UgcmVxdWVzdHMuXG4gKlxuICogQGNsYXNzIEh0dHBDbGllbnRcbiAqL1xuZXhwb3J0IGNsYXNzIEh0dHBDbGllbnQge1xuICBwcm90ZWN0ZWQgc3RhdGljIGxvZyA9IExvZ2dpbmcuZm9yKEh0dHBDbGllbnQpO1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERvd25sb2FkcyBhIGZpbGUgZnJvbSBhIGdpdmVuIFVSTC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2Qgc2VuZHMgYSBHRVQgcmVxdWVzdCB0byB0aGUgc3BlY2lmaWVkIFVSTCBhbmQgcmV0dXJucyB0aGUgcmVzcG9uc2UgYm9keSBhcyBhIHN0cmluZy5cbiAgICogSXQgaGFuZGxlcyBkaWZmZXJlbnQgc2NlbmFyaW9zIHN1Y2ggYXMgbm9uLTIwMCBzdGF0dXMgY29kZXMgYW5kIG5ldHdvcmsgZXJyb3JzLlxuICAgKlxuICAgKiBAcGFyYW0gdXJsIC0gVGhlIFVSTCBvZiB0aGUgZmlsZSB0byBkb3dubG9hZC5cbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBmaWxlIGNvbnRlbnQgYXMgYSBzdHJpbmcuXG4gICAqXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICAgKiAgIHBhcnRpY2lwYW50IEh0dHBDbGllbnRcbiAgICogICBwYXJ0aWNpcGFudCBIVFRQU1xuICAgKiAgIHBhcnRpY2lwYW50IFNlcnZlclxuICAgKiAgIENsaWVudC0+Pkh0dHBDbGllbnQ6IGRvd25sb2FkRmlsZSh1cmwpXG4gICAqICAgSHR0cENsaWVudC0+PkhUVFBTOiBnZXQodXJsKVxuICAgKiAgIEhUVFBTLT4+U2VydmVyOiBHRVQgcmVxdWVzdFxuICAgKiAgIFNlcnZlci0tPj5IVFRQUzogUmVzcG9uc2VcbiAgICogICBIVFRQUy0tPj5IdHRwQ2xpZW50OiBSZXNwb25zZSBvYmplY3RcbiAgICogICBhbHQgU3RhdHVzIGNvZGUgaXMgMjAwXG4gICAqICAgICBsb29wIEZvciBlYWNoIGRhdGEgY2h1bmtcbiAgICogICAgICAgSFRUUFMtPj5IdHRwQ2xpZW50OiAnZGF0YScgZXZlbnRcbiAgICogICAgICAgSHR0cENsaWVudC0+Pkh0dHBDbGllbnQ6IEFjY3VtdWxhdGUgZGF0YVxuICAgKiAgICAgZW5kXG4gICAqICAgICBIVFRQUy0+Pkh0dHBDbGllbnQ6ICdlbmQnIGV2ZW50XG4gICAqICAgICBIdHRwQ2xpZW50LS0+PkNsaWVudDogUmVzb2x2ZSB3aXRoIGRhdGFcbiAgICogICBlbHNlIFN0YXR1cyBjb2RlIGlzIG5vdCAyMDBcbiAgICogICAgIEh0dHBDbGllbnQtLT4+Q2xpZW50OiBSZWplY3Qgd2l0aCBlcnJvclxuICAgKiAgIGVuZFxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGRvd25sb2FkRmlsZSh1cmw6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPHN0cmluZz4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgZnVuY3Rpb24gcmVxdWVzdCh1cmw6IHN0cmluZykge1xuICAgICAgICB1cmwgPSBlbmNvZGVVUkkodXJsKTtcbiAgICAgICAgaHR0cHMuZ2V0KHVybCwgKHJlcykgPT4ge1xuICAgICAgICAgIGlmIChyZXMuc3RhdHVzQ29kZSA9PT0gMzAxIHx8IHJlcy5zdGF0dXNDb2RlID09PSAzMDcpXG4gICAgICAgICAgICByZXR1cm4gcmVxdWVzdChyZXMuaGVhZGVycy5sb2NhdGlvbiBhcyBzdHJpbmcpO1xuXG4gICAgICAgICAgaWYgKHJlcy5zdGF0dXNDb2RlICE9PSAyMDApIHtcbiAgICAgICAgICAgIEh0dHBDbGllbnQubG9nLmVycm9yKFxuICAgICAgICAgICAgICBgRmFpbGVkIHRvIGZldGNoICR7dXJsfSAoc3RhdHVzOiAke3Jlcy5zdGF0dXNDb2RlfSlgXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBmZXRjaCAke3VybH1gKSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGxldCBkYXRhID0gXCJcIjtcbiAgICAgICAgICByZXMub24oXCJkYXRhXCIsIChjaHVuaykgPT4ge1xuICAgICAgICAgICAgZGF0YSArPSBjaHVuaztcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXMub24oXCJlcnJvclwiLCAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICByZXMub24oXCJlbmRcIiwgKCkgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZShkYXRhKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXF1ZXN0KHVybCk7XG4gICAgfSk7XG4gIH1cbn1cbiIsImltcG9ydCB7IENvbW1hbmQgfSBmcm9tIFwiLi4vY29tbWFuZFwiO1xuaW1wb3J0IHsgQ29tbWFuZE9wdGlvbnMgfSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IERlZmF1bHRDb21tYW5kT3B0aW9ucywgRGVmYXVsdENvbW1hbmRWYWx1ZXMgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5pbXBvcnQge1xuICBjb3B5RmlsZSxcbiAgZGVsZXRlUGF0aCxcbiAgZ2V0QWxsRmlsZXMsXG4gIGdldFBhY2thZ2UsXG4gIHBhdGNoRmlsZSxcbiAgcmVhZEZpbGUsXG4gIHJlbmFtZUZpbGUsXG4gIHJ1bkNvbW1hbmQsXG4gIHdyaXRlRmlsZSxcbn0gZnJvbSBcIi4uLy4uL3V0aWxzXCI7XG5pbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgSW5wdXRPcHRpb25zLCBPdXRwdXRPcHRpb25zLCByb2xsdXAsIFJvbGx1cEJ1aWxkIH0gZnJvbSBcInJvbGx1cFwiO1xuaW1wb3J0IHR5cGVzY3JpcHQgZnJvbSBcIkByb2xsdXAvcGx1Z2luLXR5cGVzY3JpcHRcIjtcbmltcG9ydCBjb21tb25qcyBmcm9tIFwiQHJvbGx1cC9wbHVnaW4tY29tbW9uanNcIjtcbmltcG9ydCB7IG5vZGVSZXNvbHZlIH0gZnJvbSBcIkByb2xsdXAvcGx1Z2luLW5vZGUtcmVzb2x2ZVwiO1xuaW1wb3J0IGpzb24gZnJvbSBcIkByb2xsdXAvcGx1Z2luLWpzb25cIjtcbmltcG9ydCB7IExvZ2dpbmdDb25maWcgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcbmltcG9ydCAqIGFzIHRzIGZyb20gXCJ0eXBlc2NyaXB0XCI7XG5pbXBvcnQgeyBEaWFnbm9zdGljLCBFbWl0UmVzdWx0LCBNb2R1bGVLaW5kLCBTb3VyY2VGaWxlIH0gZnJvbSBcInR5cGVzY3JpcHRcIjtcblxuY29uc3QgVkVSU0lPTl9TVFJJTkcgPSBcIiMjVkVSU0lPTiMjXCI7XG5jb25zdCBQQUNLQUdFX1NUUklORyA9IFwiIyNQQUNLQUdFIyNcIjtcblxuZW51bSBNb2RlcyB7XG4gIENKUyA9IFwiY29tbW9uanNcIixcbiAgRVNNID0gXCJlczIwMjJcIixcbn1cblxuZW51bSBCdWlsZE1vZGUge1xuICBCVUlMRCA9IFwiYnVpbGRcIixcbiAgQlVORExFID0gXCJidW5kbGVcIixcbiAgQUxMID0gXCJhbGxcIixcbn1cblxuZW51bSBTRVBBUkFUT1JTIHtcbiAgRE9UID0gXCIuXCJcbn1cblxuY29uc3QgYmluU291cmNlTG9jYXRpb24gPSBcIi9zcmMvYmluXCJcblxuY29uc3Qgb3B0aW9ucyA9IHtcbiAgcHJvZDoge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxuICBkZXY6IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgYnVpbGRNb2RlOiB7XG4gICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICBkZWZhdWx0OiBCdWlsZE1vZGUuQUxMLFxuICB9LFxuICBkb2NzOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG4gIGNvbW1hbmRzOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG4gIGJhbm5lcjoge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxufTtcblxuY29uc3QgY2pzMlRyYW5zZm9ybWVyID0gKGV4dCA9IFwiLmNqc1wiKSA9PiB7XG4gIGNvbnN0IGxvZyA9IEJ1aWxkU2NyaXB0cy5sb2cuZm9yKGNqczJUcmFuc2Zvcm1lcik7XG4gIGNvbnN0IHJlc29sdXRpb25DYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG5cbiAgcmV0dXJuICh0cmFuc2Zvcm1hdGlvbkNvbnRleHQ6IHRzLlRyYW5zZm9ybWF0aW9uQ29udGV4dCkgPT4ge1xuICAgIHJldHVybiAoc291cmNlRmlsZTogdHMuU291cmNlRmlsZSkgPT4ge1xuICAgICAgY29uc3Qgc291cmNlRGlyID0gcGF0aC5kaXJuYW1lKHNvdXJjZUZpbGUuZmlsZU5hbWUpO1xuXG4gICAgICBmdW5jdGlvbiByZXNvbHZlUGF0aChpbXBvcnRQYXRoOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3QgY2FjaGVLZXkgPSBKU09OLnN0cmluZ2lmeShbc291cmNlRGlyLCBpbXBvcnRQYXRoXSk7XG4gICAgICAgIGNvbnN0IGNhY2hlZFZhbHVlID0gcmVzb2x1dGlvbkNhY2hlLmdldChjYWNoZUtleSk7XG4gICAgICAgIGlmIChjYWNoZWRWYWx1ZSAhPSBudWxsKSByZXR1cm4gY2FjaGVkVmFsdWU7XG5cbiAgICAgICAgbGV0IHJlc29sdmVkUGF0aCA9IGltcG9ydFBhdGg7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmVzb2x2ZWRQYXRoID0gcGF0aC5yZXNvbHZlKHNvdXJjZURpciwgcmVzb2x2ZWRQYXRoICsgXCIudHNcIik7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gcmVzb2x2ZSBwYXRoICR7aW1wb3J0UGF0aH06ICR7ZXJyb3J9YCk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHN0YXQ7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgc3RhdCA9IGZzLnN0YXRTeW5jKHJlc29sdmVkUGF0aCk7XG4gICAgICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgbG9nLnZlcmJvc2UoXG4gICAgICAgICAgICAgIGBUZXN0aW5nIGV4aXN0ZW5jZSBvZiBwYXRoICR7cmVzb2x2ZWRQYXRofSBhcyBhIGZvbGRlciBkZWZhdWx0aW5nIHRvIGluZGV4IGZpbGVgXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgc3RhdCA9IGZzLnN0YXRTeW5jKHJlc29sdmVkUGF0aC5yZXBsYWNlKC9cXC50cyQvZ20sIFwiXCIpKTtcbiAgICAgICAgICB9IGNhdGNoIChlMjogdW5rbm93bikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICBgRmFpbGVkIHRvIHJlc29sdmUgcGF0aCAke2ltcG9ydFBhdGh9OiAke2V9LCAke2UyfWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzdGF0LmlzRGlyZWN0b3J5KCkpXG4gICAgICAgICAgcmVzb2x2ZWRQYXRoID0gcmVzb2x2ZWRQYXRoLnJlcGxhY2UoL1xcLnRzJC9nbSwgXCIvaW5kZXgudHNcIik7XG5cbiAgICAgICAgaWYgKHBhdGguaXNBYnNvbHV0ZShyZXNvbHZlZFBhdGgpKSB7XG4gICAgICAgICAgY29uc3QgZXh0ZW5zaW9uID1cbiAgICAgICAgICAgICgvXFwudHN4PyQvLmV4ZWMocGF0aC5iYXNlbmFtZShyZXNvbHZlZFBhdGgpKSB8fCBbXSlbMF0gfHwgdm9pZCAwO1xuXG4gICAgICAgICAgcmVzb2x2ZWRQYXRoID1cbiAgICAgICAgICAgIFwiLi9cIiArXG4gICAgICAgICAgICBwYXRoLnJlbGF0aXZlKFxuICAgICAgICAgICAgICBzb3VyY2VEaXIsXG4gICAgICAgICAgICAgIHBhdGgucmVzb2x2ZShcbiAgICAgICAgICAgICAgICBwYXRoLmRpcm5hbWUocmVzb2x2ZWRQYXRoKSxcbiAgICAgICAgICAgICAgICBwYXRoLmJhc2VuYW1lKHJlc29sdmVkUGF0aCwgZXh0ZW5zaW9uKSArIGV4dFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVzb2x1dGlvbkNhY2hlLnNldChjYWNoZUtleSwgcmVzb2x2ZWRQYXRoKTtcbiAgICAgICAgcmV0dXJuIHJlc29sdmVkUGF0aDtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gdmlzaXROb2RlKG5vZGU6IHRzLk5vZGUpOiB0cy5WaXNpdFJlc3VsdDx0cy5Ob2RlPiB7XG4gICAgICAgIGlmIChzaG91bGRNdXRhdGVNb2R1bGVTcGVjaWZpZXIobm9kZSkpIHtcbiAgICAgICAgICBpZiAodHMuaXNJbXBvcnREZWNsYXJhdGlvbihub2RlKSkge1xuICAgICAgICAgICAgY29uc3QgcmVzb2x2ZWRQYXRoID0gcmVzb2x2ZVBhdGgobm9kZS5tb2R1bGVTcGVjaWZpZXIudGV4dCk7XG4gICAgICAgICAgICBjb25zdCBuZXdNb2R1bGVTcGVjaWZpZXIgPVxuICAgICAgICAgICAgICB0cmFuc2Zvcm1hdGlvbkNvbnRleHQuZmFjdG9yeS5jcmVhdGVTdHJpbmdMaXRlcmFsKHJlc29sdmVkUGF0aCk7XG4gICAgICAgICAgICByZXR1cm4gdHJhbnNmb3JtYXRpb25Db250ZXh0LmZhY3RvcnkudXBkYXRlSW1wb3J0RGVjbGFyYXRpb24oXG4gICAgICAgICAgICAgIG5vZGUsXG4gICAgICAgICAgICAgIG5vZGUubW9kaWZpZXJzLFxuICAgICAgICAgICAgICBub2RlLmltcG9ydENsYXVzZSxcbiAgICAgICAgICAgICAgbmV3TW9kdWxlU3BlY2lmaWVyLFxuICAgICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIGlmICh0cy5pc0V4cG9ydERlY2xhcmF0aW9uKG5vZGUpKSB7XG4gICAgICAgICAgICBjb25zdCByZXNvbHZlZFBhdGggPSByZXNvbHZlUGF0aChub2RlLm1vZHVsZVNwZWNpZmllci50ZXh0KTtcbiAgICAgICAgICAgIGNvbnN0IG5ld01vZHVsZVNwZWNpZmllciA9XG4gICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uQ29udGV4dC5mYWN0b3J5LmNyZWF0ZVN0cmluZ0xpdGVyYWwocmVzb2x2ZWRQYXRoKTtcbiAgICAgICAgICAgIHJldHVybiB0cmFuc2Zvcm1hdGlvbkNvbnRleHQuZmFjdG9yeS51cGRhdGVFeHBvcnREZWNsYXJhdGlvbihcbiAgICAgICAgICAgICAgbm9kZSxcbiAgICAgICAgICAgICAgbm9kZS5tb2RpZmllcnMsXG4gICAgICAgICAgICAgIG5vZGUuaXNUeXBlT25seSxcbiAgICAgICAgICAgICAgbm9kZS5leHBvcnRDbGF1c2UsXG4gICAgICAgICAgICAgIG5ld01vZHVsZVNwZWNpZmllcixcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cy52aXNpdEVhY2hDaGlsZChub2RlLCB2aXNpdE5vZGUsIHRyYW5zZm9ybWF0aW9uQ29udGV4dCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHNob3VsZE11dGF0ZU1vZHVsZVNwZWNpZmllcihub2RlOiB0cy5Ob2RlKTogbm9kZSBpcyAoXG4gICAgICAgIHwgdHMuSW1wb3J0RGVjbGFyYXRpb25cbiAgICAgICAgfCB0cy5FeHBvcnREZWNsYXJhdGlvblxuICAgICAgKSAmIHtcbiAgICAgICAgbW9kdWxlU3BlY2lmaWVyOiB0cy5TdHJpbmdMaXRlcmFsO1xuICAgICAgfSB7XG4gICAgICAgIGlmICghdHMuaXNJbXBvcnREZWNsYXJhdGlvbihub2RlKSAmJiAhdHMuaXNFeHBvcnREZWNsYXJhdGlvbihub2RlKSlcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgaWYgKG5vZGUubW9kdWxlU3BlY2lmaWVyID09PSB1bmRlZmluZWQpIHJldHVybiBmYWxzZTtcbiAgICAgICAgLy8gb25seSB3aGVuIG1vZHVsZSBzcGVjaWZpZXIgaXMgdmFsaWRcbiAgICAgICAgaWYgKCF0cy5pc1N0cmluZ0xpdGVyYWwobm9kZS5tb2R1bGVTcGVjaWZpZXIpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIC8vIG9ubHkgd2hlbiBwYXRoIGlzIHJlbGF0aXZlXG4gICAgICAgIGlmIChcbiAgICAgICAgICAhbm9kZS5tb2R1bGVTcGVjaWZpZXIudGV4dC5zdGFydHNXaXRoKFwiLi9cIikgJiZcbiAgICAgICAgICAhbm9kZS5tb2R1bGVTcGVjaWZpZXIudGV4dC5zdGFydHNXaXRoKFwiLi4vXCIpXG4gICAgICAgIClcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIC8vIG9ubHkgd2hlbiBtb2R1bGUgc3BlY2lmaWVyIGhhcyBubyBleHRlbnNpb25cbiAgICAgICAgaWYgKHBhdGguZXh0bmFtZShub2RlLm1vZHVsZVNwZWNpZmllci50ZXh0KSAhPT0gXCJcIikgcmV0dXJuIGZhbHNlO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRzLnZpc2l0Tm9kZShzb3VyY2VGaWxlLCB2aXNpdE5vZGUpIGFzIFNvdXJjZUZpbGU7XG4gICAgfTtcbiAgfTtcbn07XG5cbmV4cG9ydCBjbGFzcyBCdWlsZFNjcmlwdHMgZXh0ZW5kcyBDb21tYW5kPFxuICBDb21tYW5kT3B0aW9uczx0eXBlb2Ygb3B0aW9ucz4sXG4gIHZvaWRcbj4ge1xuICBwcml2YXRlIHJlcGxhY2VtZW50czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICBwcml2YXRlIHJlYWRvbmx5IHBrZ1ZlcnNpb246IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBwa2dOYW1lOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoXG4gICAgICBcIkJ1aWxkU2NyaXB0c1wiLFxuICAgICAgT2JqZWN0LmFzc2lnbih7fSwgRGVmYXVsdENvbW1hbmRPcHRpb25zLCBvcHRpb25zKSBhcyBDb21tYW5kT3B0aW9uczxcbiAgICAgICAgdHlwZW9mIG9wdGlvbnNcbiAgICAgID5cbiAgICApO1xuICAgIGNvbnN0IHBrZyA9IGdldFBhY2thZ2UoKSBhcyB7IG5hbWU6IHN0cmluZzsgdmVyc2lvbjogc3RyaW5nIH07XG4gICAgY29uc3QgeyBuYW1lLCB2ZXJzaW9uIH0gPSBwa2c7XG4gICAgdGhpcy5wa2dOYW1lID0gbmFtZS5pbmNsdWRlcyhcIkBcIikgPyBuYW1lLnNwbGl0KFwiL1wiKVsxXSA6IG5hbWU7XG4gICAgdGhpcy5wa2dWZXJzaW9uID0gdmVyc2lvbjtcbiAgICB0aGlzLnJlcGxhY2VtZW50c1tWRVJTSU9OX1NUUklOR10gPSB0aGlzLnBrZ1ZlcnNpb247XG4gICAgdGhpcy5yZXBsYWNlbWVudHNbUEFDS0FHRV9TVFJJTkddID0gbmFtZTtcbiAgfVxuXG4gIHBhdGNoRmlsZXMocDogc3RyaW5nKSB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMucGF0Y2hGaWxlcyk7XG4gICAgY29uc3QgeyBuYW1lLCB2ZXJzaW9uIH0gPSBnZXRQYWNrYWdlKCkgYXMgYW55O1xuICAgIGxvZy5pbmZvKGBQYXRjaGluZyAke25hbWV9ICR7dmVyc2lvbn0gbW9kdWxlIGluICR7cH0uLi5gKTtcbiAgICBjb25zdCBzdGF0ID0gZnMuc3RhdFN5bmMocCk7XG4gICAgaWYgKHN0YXQuaXNEaXJlY3RvcnkoKSlcbiAgICAgIGZzLnJlYWRkaXJTeW5jKHAsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSwgcmVjdXJzaXZlOiB0cnVlIH0pXG4gICAgICAgIC5maWx0ZXIoKHApID0+IHAuaXNGaWxlKCkpXG4gICAgICAgIC5mb3JFYWNoKChmaWxlKSA9PlxuICAgICAgICAgIHBhdGNoRmlsZShwYXRoLmpvaW4oZmlsZS5wYXJlbnRQYXRoLCBmaWxlLm5hbWUpLCB0aGlzLnJlcGxhY2VtZW50cylcbiAgICAgICAgKTtcbiAgICBsb2cudmVyYm9zZShgTW9kdWxlICR7bmFtZX0gJHt2ZXJzaW9ufSBwYXRjaGVkIGluICR7cH0uLi5gKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVwb3J0RGlhZ25vc3RpY3MoZGlhZ25vc3RpY3M6IERpYWdub3N0aWNbXSk6IHZvaWQge1xuICAgIGRpYWdub3N0aWNzLmZvckVhY2goKGRpYWdub3N0aWMpID0+IHtcbiAgICAgIGxldCBtZXNzYWdlID0gXCJFcnJvclwiO1xuICAgICAgaWYgKGRpYWdub3N0aWMuZmlsZSAmJiBkaWFnbm9zdGljLnN0YXJ0KSB7XG4gICAgICAgIGNvbnN0IHsgbGluZSwgY2hhcmFjdGVyIH0gPVxuICAgICAgICAgIGRpYWdub3N0aWMuZmlsZS5nZXRMaW5lQW5kQ2hhcmFjdGVyT2ZQb3NpdGlvbihkaWFnbm9zdGljLnN0YXJ0KTtcbiAgICAgICAgbWVzc2FnZSArPSBgICR7ZGlhZ25vc3RpYy5maWxlLmZpbGVOYW1lfSAoJHtsaW5lICsgMX0sJHtjaGFyYWN0ZXIgKyAxfSlgO1xuICAgICAgfVxuICAgICAgbWVzc2FnZSArPVxuICAgICAgICBcIjogXCIgKyB0cy5mbGF0dGVuRGlhZ25vc3RpY01lc3NhZ2VUZXh0KGRpYWdub3N0aWMubWVzc2FnZVRleHQsIFwiXFxuXCIpO1xuICAgICAgY29uc29sZS5sb2cobWVzc2FnZSk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHJlYWRDb25maWdGaWxlKGNvbmZpZ0ZpbGVOYW1lOiBzdHJpbmcpIHtcbiAgICAvLyBSZWFkIGNvbmZpZyBmaWxlXG4gICAgY29uc3QgY29uZmlnRmlsZVRleHQgPSBmcy5yZWFkRmlsZVN5bmMoY29uZmlnRmlsZU5hbWUpLnRvU3RyaW5nKCk7XG5cbiAgICAvLyBQYXJzZSBKU09OLCBhZnRlciByZW1vdmluZyBjb21tZW50cy4gSnVzdCBmYW5jaWVyIEpTT04ucGFyc2VcbiAgICBjb25zdCByZXN1bHQgPSB0cy5wYXJzZUNvbmZpZ0ZpbGVUZXh0VG9Kc29uKGNvbmZpZ0ZpbGVOYW1lLCBjb25maWdGaWxlVGV4dCk7XG4gICAgY29uc3QgY29uZmlnT2JqZWN0ID0gcmVzdWx0LmNvbmZpZztcbiAgICBpZiAoIWNvbmZpZ09iamVjdCkge1xuICAgICAgdGhpcy5yZXBvcnREaWFnbm9zdGljcyhbcmVzdWx0LmVycm9yIV0pO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbGVkIHRvIHBhcnNlIHRzY29uZmlnLmpzb25cIik7XG4gICAgfVxuXG4gICAgLy8gRXh0cmFjdCBjb25maWcgaW5mcm9tYXRpb25cbiAgICBjb25zdCBjb25maWdQYXJzZVJlc3VsdCA9IHRzLnBhcnNlSnNvbkNvbmZpZ0ZpbGVDb250ZW50KFxuICAgICAgY29uZmlnT2JqZWN0LFxuICAgICAgdHMuc3lzLFxuICAgICAgcGF0aC5kaXJuYW1lKGNvbmZpZ0ZpbGVOYW1lKVxuICAgICk7XG4gICAgaWYgKGNvbmZpZ1BhcnNlUmVzdWx0LmVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLnJlcG9ydERpYWdub3N0aWNzKGNvbmZpZ1BhcnNlUmVzdWx0LmVycm9ycyk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJGYWlsZWQgdG8gcGFyc2UgdHNjb25maWcuanNvblwiKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbmZpZ1BhcnNlUmVzdWx0O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBidWlsZFRzKGlzRGV2OiBib29sZWFuLCBtb2RlOiBNb2RlcywgYnVuZGxlID0gZmFsc2UpIHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5idWlsZFRzKTtcbiAgICBsb2cuaW5mbyhcbiAgICAgIGBCdWlsZGluZyAke3RoaXMucGtnTmFtZX0gJHt0aGlzLnBrZ1ZlcnNpb259IG1vZHVsZSAoJHttb2RlfSkgaW4gJHtpc0RldiA/IFwiZGV2XCIgOiBcInByb2RcIn0gbW9kZS4uLmBcbiAgICApO1xuICAgIGxldCB0c0NvbmZpZztcbiAgICB0cnkge1xuICAgICAgdHNDb25maWcgPSB0aGlzLnJlYWRDb25maWdGaWxlKFwiLi90c2NvbmZpZy5qc29uXCIpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHBhcnNlIHRzY29uZmlnLmpzb246ICR7ZX1gKTtcbiAgICB9XG5cbiAgICBpZiAoYnVuZGxlKSB7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLm1vZHVsZSA9IE1vZHVsZUtpbmQuQU1EO1xuICAgICAgdHNDb25maWcub3B0aW9ucy5vdXREaXIgPSBcImRpc3RcIjtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMuaXNvbGF0ZWRNb2R1bGVzID0gZmFsc2U7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLm91dEZpbGUgPSB0aGlzLnBrZ05hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMub3V0RGlyID0gYGxpYiR7bW9kZSA9PT0gTW9kZXMuRVNNID8gXCIvZXNtXCIgOiBcIlwifWA7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLm1vZHVsZSA9XG4gICAgICAgIG1vZGUgPT09IE1vZGVzLkVTTSA/IE1vZHVsZUtpbmQuRVMyMDIyIDogTW9kdWxlS2luZC5Db21tb25KUztcbiAgICB9XG5cbiAgICBpZiAoaXNEZXYpIHtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMuaW5saW5lU291cmNlTWFwID0gdHJ1ZTtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMuc291cmNlTWFwID0gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMuc291cmNlTWFwID0gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgcHJvZ3JhbSA9IHRzLmNyZWF0ZVByb2dyYW0odHNDb25maWcuZmlsZU5hbWVzLCB0c0NvbmZpZy5vcHRpb25zKTtcblxuICAgIGNvbnN0IHRyYW5zZm9ybWF0aW9uczogeyBiZWZvcmU/OiBhbnlbXSB9ID0ge307XG4gICAgaWYgKG1vZGUgPT09IE1vZGVzLkNKUykge1xuICAgICAgdHJhbnNmb3JtYXRpb25zLmJlZm9yZSA9IFtjanMyVHJhbnNmb3JtZXIoXCIuY2pzXCIpXTtcbiAgICB9IGVsc2UgaWYgKG1vZGUgPT09IE1vZGVzLkVTTSkge1xuICAgICAgdHJhbnNmb3JtYXRpb25zLmJlZm9yZSA9IFtjanMyVHJhbnNmb3JtZXIoXCIuanNcIildO1xuICAgIH1cblxuICAgIGNvbnN0IGVtaXRSZXN1bHQ6IEVtaXRSZXN1bHQgPSBwcm9ncmFtLmVtaXQoXG4gICAgICB1bmRlZmluZWQsXG4gICAgICB1bmRlZmluZWQsXG4gICAgICB1bmRlZmluZWQsXG4gICAgICB1bmRlZmluZWQsXG4gICAgICB0cmFuc2Zvcm1hdGlvbnNcbiAgICApO1xuXG4gICAgY29uc3QgYWxsRGlhZ25vc3RpY3MgPSB0c1xuICAgICAgLmdldFByZUVtaXREaWFnbm9zdGljcyhwcm9ncmFtKVxuICAgICAgLmNvbmNhdChlbWl0UmVzdWx0LmRpYWdub3N0aWNzKTtcblxuICAgIGFsbERpYWdub3N0aWNzLmZvckVhY2goKGRpYWdub3N0aWMpID0+IHtcbiAgICAgIGlmIChkaWFnbm9zdGljLmZpbGUpIHtcbiAgICAgICAgY29uc3QgeyBsaW5lLCBjaGFyYWN0ZXIgfSA9XG4gICAgICAgICAgZGlhZ25vc3RpYy5maWxlLmdldExpbmVBbmRDaGFyYWN0ZXJPZlBvc2l0aW9uKGRpYWdub3N0aWMuc3RhcnQhKTtcbiAgICAgICAgY29uc3QgbWVzc2FnZSA9IHRzLmZsYXR0ZW5EaWFnbm9zdGljTWVzc2FnZVRleHQoXG4gICAgICAgICAgZGlhZ25vc3RpYy5tZXNzYWdlVGV4dCxcbiAgICAgICAgICBcIlxcblwiXG4gICAgICAgICk7XG4gICAgICAgIGxvZy5pbmZvKFxuICAgICAgICAgIGAke2RpYWdub3N0aWMuZmlsZS5maWxlTmFtZX0gKCR7bGluZSArIDF9LCR7Y2hhcmFjdGVyICsgMX0pOiAke21lc3NhZ2V9YFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nLmluZm8odHMuZmxhdHRlbkRpYWdub3N0aWNNZXNzYWdlVGV4dChkaWFnbm9zdGljLm1lc3NhZ2VUZXh0LCBcIlxcblwiKSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKGVtaXRSZXN1bHQuZW1pdFNraXBwZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkJ1aWxkIGZhaWxlZFwiKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJ1aWxkKGlzRGV2OiBib29sZWFuLCBtb2RlOiBNb2RlcywgYnVuZGxlID0gZmFsc2UpIHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5idWlsZCk7XG4gICAgYXdhaXQgdGhpcy5idWlsZFRzKGlzRGV2LCBtb2RlLCBidW5kbGUpO1xuXG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgTW9kdWxlICR7dGhpcy5wa2dOYW1lfSAke3RoaXMucGtnVmVyc2lvbn0gKCR7bW9kZX0pIGJ1aWx0IGluICR7aXNEZXYgPyBcImRldlwiIDogXCJwcm9kXCJ9IG1vZGUuLi5gXG4gICAgKTtcbiAgICBpZiAobW9kZSA9PT0gTW9kZXMuQ0pTICYmICFidW5kbGUpIHtcbiAgICAgIGNvbnN0IGZpbGVzID0gZ2V0QWxsRmlsZXMoXG4gICAgICAgIFwibGliXCIsXG4gICAgICAgIChmaWxlKSA9PiBmaWxlLmVuZHNXaXRoKFwiLmpzXCIpICYmICFmaWxlLmluY2x1ZGVzKFwiL2VzbS9cIilcbiAgICAgICk7XG5cbiAgICAgIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgICAgICBsb2cudmVyYm9zZShgUGF0Y2hpbmcgJHtmaWxlfSdzIGNqcyBpbXBvcnRzLi4uYCk7XG4gICAgICAgIGNvbnN0IGYgPSBmaWxlLnJlcGxhY2UoXCIuanNcIiwgXCIuY2pzXCIpO1xuICAgICAgICBhd2FpdCByZW5hbWVGaWxlKGZpbGUsIGYpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvcHlBc3NldHMobW9kZTogTW9kZXMpIHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5jb3B5QXNzZXRzKTtcbiAgICBsZXQgaGFzQXNzZXRzID0gZmFsc2U7XG4gICAgdHJ5IHtcbiAgICAgIGhhc0Fzc2V0cyA9IGZzLnN0YXRTeW5jKFwiLi9zcmMvYXNzZXRzXCIpLmlzRGlyZWN0b3J5KCk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgcmV0dXJuIGxvZy52ZXJib3NlKGBObyBhc3NldHMgZm91bmQgaW4gLi9zcmMvYXNzZXRzIHRvIGNvcHlgKTtcbiAgICB9XG4gICAgaWYgKGhhc0Fzc2V0cylcbiAgICAgIGNvcHlGaWxlKFxuICAgICAgICBcIi4vc3JjL2Fzc2V0c1wiLFxuICAgICAgICBgLi8ke21vZGUgPT09IE1vZGVzLkNKUyA/IFwibGliXCIgOiBcImRpc3RcIn0vYXNzZXRzYFxuICAgICAgKTtcbiAgfVxuXG4gIGFzeW5jIGJ1aWxkQ29tbWFuZHMoKSB7XG4gICAgY29uc3QgY29tbWFuZHM6IHN0cmluZ1tdICA9IGZzLnJlYWRkaXJTeW5jKHBhdGguam9pbihwcm9jZXNzLmN3ZCgpICsgYmluU291cmNlTG9jYXRpb24pKS5tYXAoKGNtZCkgPT4gY21kLnNwbGl0KFNFUEFSQVRPUlMuRE9UKVswXSkgXG4gICAgZm9yIChjb25zdCBjbWQgb2YgY29tbWFuZHMpIHtcbiAgICAgIGlmICghY21kLmVuZHNXaXRoKFwiLnRzXCIpKSBjb250aW51ZTtcblxuICAgICAgYXdhaXQgdGhpcy5idW5kbGUoTW9kZXMuQ0pTLCB0cnVlLCB0cnVlLCBgJHtiaW5Tb3VyY2VMb2NhdGlvbn0vJHtjbWR9LnRzYCwgY21kKTtcbiAgICAgIGxldCBkYXRhID0gcmVhZEZpbGUoYGJpbi8ke2NtZH0uY2pzYCk7XG4gICAgICBkYXRhID0gXCIjIS91c3IvYmluL2VudiBub2RlXFxuXCIgKyBkYXRhO1xuICAgICAgd3JpdGVGaWxlKGBiaW4vJHtjbWR9LmNqc2AsIGRhdGEpO1xuICAgICAgZnMuY2htb2RTeW5jKGBiaW4vJHtjbWR9LmNqc2AsIFwiNzU1XCIpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGJ1bmRsZShcbiAgICBtb2RlOiBNb2RlcyxcbiAgICBpc0RldjogYm9vbGVhbixcbiAgICBpc0xpYjogYm9vbGVhbixcbiAgICBlbnRyeUZpbGU6IHN0cmluZyA9IFwic3JjL2luZGV4LnRzXCIsXG4gICAgbmFtZU92ZXJyaWRlOiBzdHJpbmcgPSB0aGlzLnBrZ05hbWUsXG4gICAgZXh0ZXJuYWxzPzogc3RyaW5nW10sXG4gICAgaW5jbHVkZTogc3RyaW5nW10gPSBbXG4gICAgICBcInByb21wdHNcIixcbiAgICAgIFwic3R5bGVkLXN0cmluZy1idWlsZGVyXCIsXG4gICAgICBcInR5cGVkLW9iamVjdC1hY2N1bXVsYXRvclwiLFxuICAgICAgXCJAZGVjYWYtdHMvbG9nZ2luZ1wiLFxuICAgIF1cbiAgKSB7XG4gICAgY29uc3QgaXNFc20gPSBtb2RlID09PSBNb2Rlcy5FU007XG4gICAgY29uc3QgcGtnTmFtZSA9IHRoaXMucGtnTmFtZTtcblxuICAgIGNvbnN0IGV4dCA9IEFycmF5LmZyb20oXG4gICAgICBuZXcgU2V0KFtcbiAgICAgICAgLi4uW1xuICAgICAgICAgIFwiZnNcIixcbiAgICAgICAgICBcInBhdGhcIixcbiAgICAgICAgICBcInByb2Nlc3NcIixcbiAgICAgICAgICBcInJvbGx1cFwiLFxuICAgICAgICAgIFwiQHJvbGx1cC9wbHVnaW4tdHlwZXNjcmlwdFwiLFxuICAgICAgICAgIFwiQHJvbGx1cC9wbHVnaW4tanNvblwiLFxuICAgICAgICAgIFwiQHJvbGx1cC9wbHVnaW4tY29tbW9uanNcIixcbiAgICAgICAgICBcIkByb2xsdXAvcGx1Z2luLW5vZGUtcmVzb2x2ZVwiLFxuICAgICAgICAgIFwiY2hpbGRfcHJvY2Vzc1wiLFxuICAgICAgICAgIFwidHNsaWJcIixcbiAgICAgICAgICBcInV0aWxcIixcbiAgICAgICAgICBcImh0dHBzXCIsXG4gICAgICAgIF0sXG4gICAgICAgIC4uLihleHRlcm5hbHMgfHwgW10pLFxuICAgICAgXSlcbiAgICApO1xuXG4gICAgY29uc3QgcGx1Z2lucyA9IFtcbiAgICAgIHR5cGVzY3JpcHQoe1xuICAgICAgICBjb21waWxlck9wdGlvbnM6IHtcbiAgICAgICAgICBtb2R1bGU6IFwiZXNuZXh0XCIsXG4gICAgICAgICAgZGVjbGFyYXRpb246IGZhbHNlLFxuICAgICAgICAgIG91dERpcjogaXNMaWIgPyBcImJpblwiIDogXCJkaXN0XCIsXG4gICAgICAgIH0sXG4gICAgICAgIGluY2x1ZGU6IFtcInNyYy8qKi8qLnRzXCJdLFxuICAgICAgICBleGNsdWRlOiBbXCJub2RlX21vZHVsZXNcIiwgXCIqKi8qLnNwZWMudHNcIl0sXG4gICAgICAgIHRzY29uZmlnOiBcIi4vdHNjb25maWcuanNvblwiLFxuICAgICAgfSksXG4gICAgICBqc29uKCksXG4gICAgXTtcblxuICAgIGlmIChpc0xpYikge1xuICAgICAgcGx1Z2lucy5wdXNoKFxuICAgICAgICBjb21tb25qcyh7XG4gICAgICAgICAgaW5jbHVkZTogW10sXG4gICAgICAgICAgZXhjbHVkZTogZXh0ZXJuYWxzLFxuICAgICAgICB9KSxcbiAgICAgICAgbm9kZVJlc29sdmUoe1xuICAgICAgICAgIHJlc29sdmVPbmx5OiBpbmNsdWRlLFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBpbnB1dDogSW5wdXRPcHRpb25zID0ge1xuICAgICAgaW5wdXQ6IGVudHJ5RmlsZSxcbiAgICAgIHBsdWdpbnM6IHBsdWdpbnMsXG4gICAgICBleHRlcm5hbDogZXh0LFxuICAgIH07XG5cbiAgICBjb25zdCBvdXRwdXRzOiBPdXRwdXRPcHRpb25zW10gPSBbXG4gICAgICB7XG4gICAgICAgIGZpbGU6IGAke2lzTGliID8gXCJiaW4vXCIgOiBcImRpc3QvXCJ9JHtuYW1lT3ZlcnJpZGUgPyBuYW1lT3ZlcnJpZGUgOiBgLmJ1bmRsZS4keyFpc0RldiA/IFwibWluXCIgOiBcIlwifWB9JHtpc0VzbSA/IFwiLmVzbVwiIDogXCJcIn0uY2pzYCxcbiAgICAgICAgZm9ybWF0OiBpc0xpYiA/IFwiY2pzXCIgOiBpc0VzbSA/IFwiZXNtXCIgOiBcInVtZFwiLFxuICAgICAgICBuYW1lOiBwa2dOYW1lLFxuICAgICAgICBlc01vZHVsZTogaXNFc20sXG4gICAgICAgIHNvdXJjZW1hcDogaXNEZXYgPyBcImlubGluZVwiIDogZmFsc2UsXG4gICAgICAgIGdsb2JhbHM6IHt9LFxuICAgICAgICBleHBvcnRzOiBcImF1dG9cIixcbiAgICAgIH0sXG4gICAgXTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBidW5kbGUgPSBhd2FpdCByb2xsdXAoaW5wdXQpO1xuICAgICAgY29uc29sZS5sb2coYnVuZGxlLndhdGNoRmlsZXMpO1xuICAgICAgYXN5bmMgZnVuY3Rpb24gZ2VuZXJhdGVPdXRwdXRzKGJ1bmRsZTogUm9sbHVwQnVpbGQpIHtcbiAgICAgICAgZm9yIChjb25zdCBvdXRwdXRPcHRpb25zIG9mIG91dHB1dHMpIHtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgICAgICAgY29uc3QgeyBvdXRwdXQgfSA9IGF3YWl0IGJ1bmRsZS53cml0ZShvdXRwdXRPcHRpb25zKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBhd2FpdCBnZW5lcmF0ZU91dHB1dHMoYnVuZGxlKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBidW5kbGU6ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJ1aWxkQnlFbnYoaXNEZXY6IGJvb2xlYW4sIG1vZGU6IEJ1aWxkTW9kZSA9IEJ1aWxkTW9kZS5BTEwpIHtcbiAgICB0cnkge1xuICAgICAgZGVsZXRlUGF0aChcImxpYlwiKTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAvLyBkbyBub3RoaW5nXG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBkZWxldGVQYXRoKFwiZGlzdFwiKTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAvLyBkbyBub3RoaW5nXG4gICAgfVxuICAgIGZzLm1rZGlyU3luYyhcImxpYlwiKTtcbiAgICBmcy5ta2RpclN5bmMoXCJkaXN0XCIpO1xuXG4gICAgaWYgKFtCdWlsZE1vZGUuQUxMLCBCdWlsZE1vZGUuQlVJTERdLmluY2x1ZGVzKG1vZGUpKSB7XG4gICAgICBhd2FpdCB0aGlzLmJ1aWxkKGlzRGV2LCBNb2Rlcy5FU00pO1xuICAgICAgYXdhaXQgdGhpcy5idWlsZChpc0RldiwgTW9kZXMuQ0pTKTtcbiAgICAgIHRoaXMucGF0Y2hGaWxlcyhcImxpYlwiKTtcbiAgICB9XG5cbiAgICBpZiAoW0J1aWxkTW9kZS5BTEwsIEJ1aWxkTW9kZS5CVU5ETEVdLmluY2x1ZGVzKG1vZGUpKSB7XG4gICAgICBhd2FpdCB0aGlzLmJ1bmRsZShNb2Rlcy5FU00sIHRydWUsIGZhbHNlKTtcbiAgICAgIGF3YWl0IHRoaXMuYnVuZGxlKE1vZGVzLkNKUywgdHJ1ZSwgZmFsc2UpO1xuICAgICAgdGhpcy5wYXRjaEZpbGVzKFwiZGlzdFwiKTtcbiAgICB9XG5cbiAgICB0aGlzLmNvcHlBc3NldHMoTW9kZXMuQ0pTKTtcbiAgICB0aGlzLmNvcHlBc3NldHMoTW9kZXMuRVNNKTtcbiAgfVxuXG4gIGFzeW5jIGJ1aWxkRGV2KG1vZGU6IEJ1aWxkTW9kZSA9IEJ1aWxkTW9kZS5BTEwpIHtcbiAgICByZXR1cm4gdGhpcy5idWlsZEJ5RW52KHRydWUsIG1vZGUpO1xuICB9XG5cbiAgYXN5bmMgYnVpbGRQcm9kKG1vZGU6IEJ1aWxkTW9kZSA9IEJ1aWxkTW9kZS5BTEwpIHtcbiAgICByZXR1cm4gdGhpcy5idWlsZEJ5RW52KGZhbHNlLCBtb2RlKTtcbiAgfVxuXG4gIGFzeW5jIGJ1aWxkRG9jcygpIHtcbiAgICBhd2FpdCBydW5Db21tYW5kKGBucG0gaW5zdGFsbCBiZXR0ZXItZG9jcyB0YWZmeWRiYCkucHJvbWlzZTtcbiAgICBhd2FpdCBydW5Db21tYW5kKGBucHggbWFya2Rvd24taW5jbHVkZSAuL3dvcmtkb2NzL3JlYWRtZS1tZC5qc29uYCkucHJvbWlzZTtcbiAgICBhd2FpdCBydW5Db21tYW5kKFxuICAgICAgYG5weCBqc2RvYyAtYyAuL3dvcmtkb2NzL2pzZG9jcy5qc29uIC10IC4vbm9kZV9tb2R1bGVzL2JldHRlci1kb2NzYFxuICAgICkucHJvbWlzZTtcbiAgICBhd2FpdCBydW5Db21tYW5kKGBucG0gcmVtb3ZlIGJldHRlci1kb2NzIHRhZmZ5ZGJgKS5wcm9taXNlO1xuICAgIFtcbiAgICAgIHtcbiAgICAgICAgc3JjOiBcIndvcmtkb2NzL2Fzc2V0c1wiLFxuICAgICAgICBkZXN0OiBcIi4vZG9jcy93b3JrZG9jcy9hc3NldHNcIixcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHNyYzogXCJ3b3JrZG9jcy9yZXBvcnRzL2NvdmVyYWdlXCIsXG4gICAgICAgIGRlc3Q6IFwiLi9kb2NzL3dvcmtkb2NzL3JlcG9ydHMvY292ZXJhZ2VcIixcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHNyYzogXCJ3b3JrZG9jcy9yZXBvcnRzL2h0bWxcIixcbiAgICAgICAgZGVzdDogXCIuL2RvY3Mvd29ya2RvY3MvcmVwb3J0cy9odG1sXCIsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBzcmM6IFwid29ya2RvY3MvcmVzb3VyY2VzXCIsXG4gICAgICAgIGRlc3Q6IFwiLi9kb2NzL3dvcmtkb2NzL3Jlc291cmNlc1wiLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgc3JjOiBcIkxJQ0VOU0UubWRcIixcbiAgICAgICAgZGVzdDogXCIuL2RvY3MvTElDRU5TRS5tZFwiLFxuICAgICAgfSxcbiAgICBdLmZvckVhY2goKGYpID0+IHtcbiAgICAgIGNvbnN0IHsgc3JjLCBkZXN0IH0gPSBmO1xuICAgICAgY29weUZpbGUoc3JjLCBkZXN0KTtcbiAgICB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBydW48Uj4oXG4gICAgYW5zd2VyczogTG9nZ2luZ0NvbmZpZyAmXG4gICAgICB0eXBlb2YgRGVmYXVsdENvbW1hbmRWYWx1ZXMgJiB7IFtrIGluIGtleW9mIHR5cGVvZiBvcHRpb25zXTogdW5rbm93biB9XG4gICk6IFByb21pc2U8c3RyaW5nIHwgdm9pZCB8IFI+IHtcbiAgICBjb25zdCB7IGRldiwgcHJvZCwgZG9jcywgY29tbWFuZHMsIGJ1aWxkTW9kZSB9ID0gYW5zd2VycztcblxuICAgIGlmIChjb21tYW5kcykge1xuICAgICAgYXdhaXQgdGhpcy5idWlsZENvbW1hbmRzKCk7XG4gICAgfVxuXG4gICAgaWYgKGRldikge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuYnVpbGREZXYoYnVpbGRNb2RlIGFzIEJ1aWxkTW9kZSk7XG4gICAgfVxuICAgIGlmIChwcm9kKSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5idWlsZFByb2QoYnVpbGRNb2RlIGFzIEJ1aWxkTW9kZSk7XG4gICAgfVxuICAgIGlmIChkb2NzKSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5idWlsZERvY3MoKTtcbiAgICB9XG4gIH1cbn1cbiIsIi8qIGlzdGFuYnVsIGlnbm9yZSBmaWxlICovXG5pbXBvcnQgeyBydW5Db21tYW5kIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3V0aWxzXCI7XG5pbXBvcnQgeyBOb0NJRkxhZywgU2VtVmVyc2lvbiwgU2VtVmVyc2lvblJlZ2V4IH0gZnJvbSBcIi4uLy4uL3V0aWxzL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgVXNlcklucHV0IH0gZnJvbSBcIi4uLy4uL2lucHV0L2lucHV0XCI7XG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSBcIi4uL2NvbW1hbmRcIjtcbmltcG9ydCB7IERlZmF1bHRDb21tYW5kVmFsdWVzIH0gZnJvbSBcIi4uL2luZGV4XCI7XG5pbXBvcnQgeyBMb2dnaW5nQ29uZmlnIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbmNvbnN0IG9wdGlvbnMgPSB7XG4gIGNpOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgfSxcbiAgbWVzc2FnZToge1xuICAgIHR5cGU6IFwic3RyaW5nXCIsXG4gICAgc2hvcnQ6IFwibVwiLFxuICB9LFxuICB0YWc6IHtcbiAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgIHNob3J0OiBcInRcIixcbiAgICBkZWZhdWx0OiB1bmRlZmluZWQsXG4gIH0sXG59O1xuXG4vKipcbiAqIEBjbGFzcyBSZWxlYXNlU2NyaXB0XG4gKiBAZXh0ZW5kcyB7Q29tbWFuZH1cbiAqIEBjYXZlZ29yeSBzY3JpcHRzXG4gKiBAZGVzY3JpcHRpb24gQSBjb21tYW5kLWxpbmUgc2NyaXB0IGZvciBtYW5hZ2luZyByZWxlYXNlcyBhbmQgdmVyc2lvbiB1cGRhdGVzLlxuICogQHN1bW1hcnkgVGhpcyBzY3JpcHQgYXV0b21hdGVzIHRoZSBwcm9jZXNzIG9mIGNyZWF0aW5nIGFuZCBwdXNoaW5nIG5ldyByZWxlYXNlcy4gSXQgaGFuZGxlcyB2ZXJzaW9uIHVwZGF0ZXMsXG4gKiBjb21taXQgbWVzc2FnZXMsIGFuZCBvcHRpb25hbGx5IHB1Ymxpc2hlcyB0byBOUE0uIFRoZSBzY3JpcHQgc3VwcG9ydHMgc2VtYW50aWMgdmVyc2lvbmluZyBhbmQgY2FuIHdvcmsgaW4gYm90aCBDSSBhbmQgbm9uLUNJIGVudmlyb25tZW50cy5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgdGhlIHNjcmlwdFxuICogQHBhcmFtIHtib29sZWFufSBvcHRpb25zLmNpIC0gV2hldGhlciB0aGUgc2NyaXB0IGlzIHJ1bm5pbmcgaW4gYSBDSSBlbnZpcm9ubWVudCAoZGVmYXVsdDogdHJ1ZSlcbiAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLm1lc3NhZ2UgLSBUaGUgcmVsZWFzZSBtZXNzYWdlIChzaG9ydDogJ20nKVxuICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMudGFnIC0gVGhlIHZlcnNpb24gdGFnIHRvIHVzZSAoc2hvcnQ6ICd0JywgZGVmYXVsdDogdW5kZWZpbmVkKVxuICovXG5leHBvcnQgY2xhc3MgUmVsZWFzZVNjcmlwdCBleHRlbmRzIENvbW1hbmQ8dHlwZW9mIG9wdGlvbnMsIHZvaWQ+IHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoXCJSZWxlYXNlU2NyaXB0XCIsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyB0aGUgdmVyc2lvbiBmb3IgdGhlIHJlbGVhc2UuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIHZhbGlkYXRlcyB0aGUgcHJvdmlkZWQgdGFnIG9yIHByb21wdHMgdGhlIHVzZXIgZm9yIGEgbmV3IG9uZSBpZiBub3QgcHJvdmlkZWQgb3IgaW52YWxpZC5cbiAgICogSXQgYWxzbyBkaXNwbGF5cyB0aGUgbGF0ZXN0IGdpdCB0YWdzIGZvciByZWZlcmVuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWcgLSBUaGUgdmVyc2lvbiB0YWcgdG8gcHJlcGFyZVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSBUaGUgcHJlcGFyZWQgdmVyc2lvbiB0YWdcbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgUiBhcyBSZWxlYXNlU2NyaXB0XG4gICAqICAgcGFydGljaXBhbnQgVCBhcyBUZXN0VmVyc2lvblxuICAgKiAgIHBhcnRpY2lwYW50IFUgYXMgVXNlcklucHV0XG4gICAqICAgcGFydGljaXBhbnQgRyBhcyBHaXRcbiAgICogICBSLT4+VDogdGVzdFZlcnNpb24odGFnKVxuICAgKiAgIGFsdCB0YWcgaXMgdmFsaWRcbiAgICogICAgIFQtLT4+UjogcmV0dXJuIHRhZ1xuICAgKiAgIGVsc2UgdGFnIGlzIGludmFsaWQgb3Igbm90IHByb3ZpZGVkXG4gICAqICAgICBSLT4+RzogTGlzdCBsYXRlc3QgZ2l0IHRhZ3NcbiAgICogICAgIFItPj5VOiBQcm9tcHQgZm9yIG5ldyB0YWdcbiAgICogICAgIFUtLT4+UjogcmV0dXJuIG5ldyB0YWdcbiAgICogICBlbmRcbiAgICovXG4gIGFzeW5jIHByZXBhcmVWZXJzaW9uKHRhZz86IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMucHJlcGFyZVZlcnNpb24pO1xuICAgIHRhZyA9IHRoaXMudGVzdFZlcnNpb24oKHRhZyBhcyBzdHJpbmcpIHx8IFwiXCIpO1xuICAgIGlmICghdGFnKSB7XG4gICAgICBsb2cudmVyYm9zZShcIk5vIHJlbGVhc2UgbWVzc2FnZSBwcm92aWRlZC4gUHJvbXB0aW5nIGZvciBvbmU6XCIpO1xuICAgICAgbG9nLmluZm8oYExpc3RpbmcgbGF0ZXN0IGdpdCB0YWdzOmApO1xuICAgICAgYXdhaXQgcnVuQ29tbWFuZChcImdpdCB0YWcgLS1zb3J0PS10YWdnZXJkYXRlIHwgaGVhZCAtbiA1XCIpLnByb21pc2U7XG4gICAgICByZXR1cm4gYXdhaXQgVXNlcklucHV0Lmluc2lzdEZvclRleHQoXG4gICAgICAgIFwidGFnXCIsXG4gICAgICAgIFwiRW50ZXIgdGhlIG5ldyB0YWcgbnVtYmVyIChhY2NlcHRzIHYqLiouKlstLi4uXSlcIixcbiAgICAgICAgKHZhbCkgPT5cbiAgICAgICAgICAhIXZhbC50b1N0cmluZygpLm1hdGNoKC9edlswLTldK1xcLlswLTldKy5bMC05XSsoLVswLTlhLXpBLVotXSspPyQvKVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRhZztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGVzdHMgaWYgdGhlIHByb3ZpZGVkIHZlcnNpb24gaXMgdmFsaWQuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIGNoZWNrcyBpZiB0aGUgdmVyc2lvbiBpcyBhIHZhbGlkIHNlbWFudGljIHZlcnNpb24gb3IgYSBwcmVkZWZpbmVkIHVwZGF0ZSB0eXBlIChQQVRDSCwgTUlOT1IsIE1BSk9SKS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHZlcnNpb24gLSBUaGUgdmVyc2lvbiB0byB0ZXN0XG4gICAqIEByZXR1cm5zIHtzdHJpbmcgfCB1bmRlZmluZWR9IFRoZSB2YWxpZGF0ZWQgdmVyc2lvbiBvciB1bmRlZmluZWQgaWYgaW52YWxpZFxuICAgKi9cbiAgdGVzdFZlcnNpb24odmVyc2lvbjogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy50ZXN0VmVyc2lvbik7XG4gICAgdmVyc2lvbiA9IHZlcnNpb24udHJpbSgpLnRvTG93ZXJDYXNlKCk7XG4gICAgc3dpdGNoICh2ZXJzaW9uKSB7XG4gICAgICBjYXNlIFNlbVZlcnNpb24uUEFUQ0g6XG4gICAgICBjYXNlIFNlbVZlcnNpb24uTUlOT1I6XG4gICAgICBjYXNlIFNlbVZlcnNpb24uTUFKT1I6XG4gICAgICAgIGxvZy52ZXJib3NlKGBVc2luZyBwcm92aWRlZCBTZW1WZXIgdXBkYXRlOiAke3ZlcnNpb259YCwgMSk7XG4gICAgICAgIHJldHVybiB2ZXJzaW9uO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgbG9nLnZlcmJvc2UoXG4gICAgICAgICAgYFRlc3RpbmcgcHJvdmlkZWQgdmVyc2lvbiBmb3IgU2VtVmVyIGNvbXBhdGliaWxpdHk6ICR7dmVyc2lvbn1gLFxuICAgICAgICAgIDFcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCFuZXcgUmVnRXhwKFNlbVZlcnNpb25SZWdleCkudGVzdCh2ZXJzaW9uKSkge1xuICAgICAgICAgIGxvZy5kZWJ1ZyhgSW52YWxpZCB2ZXJzaW9uIG51bWJlcjogJHt2ZXJzaW9ufWApO1xuICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgbG9nLnZlcmJvc2UoYHZlcnNpb24gYXBwcm92ZWQ6ICR7dmVyc2lvbn1gLCAxKTtcbiAgICAgICAgcmV0dXJuIHZlcnNpb247XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyB0aGUgcmVsZWFzZSBtZXNzYWdlLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBlaXRoZXIgcmV0dXJucyB0aGUgcHJvdmlkZWQgbWVzc2FnZSBvciBwcm9tcHRzIHRoZSB1c2VyIGZvciBhIG5ldyBvbmUgaWYgbm90IHByb3ZpZGVkLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIC0gVGhlIHJlbGVhc2UgbWVzc2FnZVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSBUaGUgcHJlcGFyZWQgcmVsZWFzZSBtZXNzYWdlXG4gICAqL1xuICBhc3luYyBwcmVwYXJlTWVzc2FnZShtZXNzYWdlPzogc3RyaW5nKSB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMucHJlcGFyZU1lc3NhZ2UpO1xuICAgIGlmICghbWVzc2FnZSkge1xuICAgICAgbG9nLnZlcmJvc2UoXCJObyByZWxlYXNlIG1lc3NhZ2UgcHJvdmlkZWQuIFByb21wdGluZyBmb3Igb25lXCIpO1xuICAgICAgcmV0dXJuIGF3YWl0IFVzZXJJbnB1dC5pbnNpc3RGb3JUZXh0KFxuICAgICAgICBcIm1lc3NhZ2VcIixcbiAgICAgICAgXCJXaGF0IHNob3VsZCBiZSB0aGUgcmVsZWFzZSBtZXNzYWdlL3RpY2tldD9cIixcbiAgICAgICAgKHZhbCkgPT4gISF2YWwgJiYgdmFsLnRvU3RyaW5nKCkubGVuZ3RoID4gNVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIG1lc3NhZ2U7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJ1bnMgdGhlIHJlbGVhc2Ugc2NyaXB0LlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBvcmNoZXN0cmF0ZXMgdGhlIGVudGlyZSByZWxlYXNlIHByb2Nlc3MsIGluY2x1ZGluZyB2ZXJzaW9uIHByZXBhcmF0aW9uLCBtZXNzYWdlIGNyZWF0aW9uLFxuICAgKiBnaXQgb3BlcmF0aW9ucywgYW5kIG5wbSBwdWJsaXNoaW5nIChpZiBub3QgaW4gQ0kgZW52aXJvbm1lbnQpLlxuICAgKiBAcGFyYW0ge1BhcnNlQXJnc1Jlc3VsdH0gYXJncyAtIFRoZSBwYXJzZWQgY29tbWFuZC1saW5lIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgUiBhcyBSZWxlYXNlU2NyaXB0XG4gICAqICAgcGFydGljaXBhbnQgViBhcyBQcmVwYXJlVmVyc2lvblxuICAgKiAgIHBhcnRpY2lwYW50IE0gYXMgUHJlcGFyZU1lc3NhZ2VcbiAgICogICBwYXJ0aWNpcGFudCBOIGFzIE5QTVxuICAgKiAgIHBhcnRpY2lwYW50IEcgYXMgR2l0XG4gICAqICAgcGFydGljaXBhbnQgVSBhcyBVc2VySW5wdXRcbiAgICogICBSLT4+VjogcHJlcGFyZVZlcnNpb24odGFnKVxuICAgKiAgIFItPj5NOiBwcmVwYXJlTWVzc2FnZShtZXNzYWdlKVxuICAgKiAgIFItPj5OOiBSdW4gcHJlcGFyZS1yZWxlYXNlIHNjcmlwdFxuICAgKiAgIFItPj5HOiBDaGVjayBnaXQgc3RhdHVzXG4gICAqICAgYWx0IGNoYW5nZXMgZXhpc3RcbiAgICogICAgIFItPj5VOiBBc2sgZm9yIGNvbmZpcm1hdGlvblxuICAgKiAgICAgVS0tPj5SOiBDb25maXJtXG4gICAqICAgICBSLT4+RzogQWRkIGFuZCBjb21taXQgY2hhbmdlc1xuICAgKiAgIGVuZFxuICAgKiAgIFItPj5OOiBVcGRhdGUgbnBtIHZlcnNpb25cbiAgICogICBSLT4+RzogUHVzaCBjaGFuZ2VzIGFuZCB0YWdzXG4gICAqICAgYWx0IG5vdCBDSSBlbnZpcm9ubWVudFxuICAgKiAgICAgUi0+Pk46IFB1Ymxpc2ggdG8gbnBtXG4gICAqICAgZW5kXG4gICAqL1xuICBhc3luYyBydW4oXG4gICAgYXJnczogTG9nZ2luZ0NvbmZpZyAmXG4gICAgICB0eXBlb2YgRGVmYXVsdENvbW1hbmRWYWx1ZXMgJiB7IFtrIGluIGtleW9mIHR5cGVvZiBvcHRpb25zXTogdW5rbm93biB9XG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxldCByZXN1bHQ6IGFueTtcbiAgICBjb25zdCB7IGNpIH0gPSBhcmdzO1xuICAgIGxldCB7IHRhZywgbWVzc2FnZSB9ID0gYXJncztcbiAgICB0YWcgPSBhd2FpdCB0aGlzLnByZXBhcmVWZXJzaW9uKHRhZyBhcyBzdHJpbmcpO1xuICAgIG1lc3NhZ2UgPSBhd2FpdCB0aGlzLnByZXBhcmVNZXNzYWdlKG1lc3NhZ2UgYXMgc3RyaW5nKTtcbiAgICByZXN1bHQgPSBhd2FpdCBydW5Db21tYW5kKGBucG0gcnVuIHByZXBhcmUtcmVsZWFzZSAtLSAke3RhZ30gJHttZXNzYWdlfWAsIHtcbiAgICAgIGN3ZDogcHJvY2Vzcy5jd2QoKSxcbiAgICB9KS5wcm9taXNlO1xuICAgIHJlc3VsdCA9IGF3YWl0IHJ1bkNvbW1hbmQoXCJnaXQgc3RhdHVzIC0tcG9yY2VsYWluXCIpLnByb21pc2U7XG4gICAgYXdhaXQgcmVzdWx0O1xuICAgIGlmIChcbiAgICAgIHJlc3VsdC5sb2dzLmxlbmd0aCAmJlxuICAgICAgKGF3YWl0IFVzZXJJbnB1dC5hc2tDb25maXJtYXRpb24oXG4gICAgICAgIFwiZ2l0LWNoYW5nZXNcIixcbiAgICAgICAgXCJEbyB5b3Ugd2FudCB0byBwdXNoIHRoZSBjaGFuZ2VzIHRvIHRoZSByZW1vdGUgcmVwb3NpdG9yeT9cIixcbiAgICAgICAgdHJ1ZVxuICAgICAgKSlcbiAgICApIHtcbiAgICAgIGF3YWl0IHJ1bkNvbW1hbmQoXCJnaXQgYWRkIC5cIikucHJvbWlzZTtcbiAgICAgIGF3YWl0IHJ1bkNvbW1hbmQoXG4gICAgICAgIGBnaXQgY29tbWl0IC1tIFwiJHt0YWd9IC0gJHttZXNzYWdlfSAtIGFmdGVyIHJlbGVhc2UgcHJlcGFyYXRpb24ke2NpID8gXCJcIiA6IE5vQ0lGTGFnfVwiYFxuICAgICAgKS5wcm9taXNlO1xuICAgIH1cbiAgICBhd2FpdCBydW5Db21tYW5kKFxuICAgICAgYG5wbSB2ZXJzaW9uIFwiJHt0YWd9XCIgLW0gXCIke21lc3NhZ2V9JHtjaSA/IFwiXCIgOiBOb0NJRkxhZ31cImBcbiAgICApLnByb21pc2U7XG4gICAgYXdhaXQgcnVuQ29tbWFuZChcImdpdCBwdXNoIC0tZm9sbG93LXRhZ3NcIikucHJvbWlzZTtcbiAgICBpZiAoIWNpKSB7XG4gICAgICBhd2FpdCBydW5Db21tYW5kKFwiTlBNX1RPS0VOPSQoY2F0IC5ucG10b2tlbikgbnBtIHB1Ymxpc2ggLS1hY2Nlc3MgcHVibGljXCIpXG4gICAgICAgIC5wcm9taXNlO1xuICAgIH1cbiAgfVxufVxuIiwiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSBcIi4uL2NvbW1hbmRcIjtcbmltcG9ydCB7IENvbW1hbmRPcHRpb25zIH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5pbXBvcnQge1xuICBnZXRQYWNrYWdlLFxuICBIdHRwQ2xpZW50LFxuICBwYXRjaEZpbGUsXG4gIHJ1bkNvbW1hbmQsXG4gIHNldFBhY2thZ2VBdHRyaWJ1dGUsXG4gIFNldHVwU2NyaXB0S2V5LFxuICBUb2tlbnMsXG4gIHdyaXRlRmlsZSxcbn0gZnJvbSBcIi4uLy4uL3V0aWxzXCI7XG5pbXBvcnQgeyBEZWZhdWx0Q29tbWFuZFZhbHVlcyB9IGZyb20gXCIuLi9pbmRleFwiO1xuaW1wb3J0IHsgVXNlcklucHV0IH0gZnJvbSBcIi4uLy4uL2lucHV0XCI7XG5pbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgeyBMb2dnaW5nQ29uZmlnLCBwYXRjaFN0cmluZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG5jb25zdCBiYXNlVXJsID1cbiAgXCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vZGVjYWYtdHMvdHMtd29ya3NwYWNlL21hc3RlclwiO1xuXG5jb25zdCBvcHRpb25zID0ge1xuICB0ZW1wbGF0ZXM6IFtcbiAgICBcIi5naXRodWIvSVNTVUVfVEVNUExBVEUvYnVnX3JlcG9ydC5tZFwiLFxuICAgIFwiLmdpdGh1Yi9JU1NVRV9URU1QTEFURS9mZWF0dXJlX3JlcXVlc3QubWRcIixcbiAgICBcIi5naXRodWIvRlVORElORy55bWxcIixcbiAgXSxcbiAgd29ya2Zsb3dzOiBbXG4gICAgXCIuZ2l0aHViL3dvcmtmbG93cy9jb2RlcWwtYW5hbHlzaXMueW1sXCIsXG4gICAgXCIuZ2l0aHViL3dvcmtmbG93cy9qZXN0LWNvdmVyYWdlLnlhbWxcIixcbiAgICBcIi5naXRodWIvd29ya2Zsb3dzL25vZGVqcy1idWlsZC1wcm9kLnlhbWxcIixcbiAgICBcIi5naXRodWIvd29ya2Zsb3dzL3BhZ2VzLnlhbWxcIixcbiAgICBcIi5naXRodWIvd29ya2Zsb3dzL3B1Ymxpc2gtb24tcmVsZWFzZS55YW1sXCIsXG4gICAgXCIuZ2l0aHViL3dvcmtmbG93cy9yZWxlYXNlLW9uLXRhZy55YW1sXCIsXG4gICAgXCIuZ2l0aHViL3dvcmtmbG93cy9zbnlrLWFuYWx5c2lzLnlhbWxcIixcbiAgXSxcbiAgaWRlOiBbXG4gICAgXCIuaWRlYS9ydW5Db25maWd1cmF0aW9ucy9BbGwgVGVzdHMucnVuLnhtbFwiLFxuICAgIFwiLmlkZWEvcnVuQ29uZmlndXJhdGlvbnMvYnVpbGQucnVuLnhtbFwiLFxuICAgIFwiLmlkZWEvcnVuQ29uZmlndXJhdGlvbnMvYnVpbGRfcHJvZC5ydW4ueG1sXCIsXG4gICAgXCIuaWRlYS9ydW5Db25maWd1cmF0aW9ucy9jb3ZlcmFnZS5ydW4ueG1sXCIsXG4gICAgXCIuaWRlYS9ydW5Db25maWd1cmF0aW9ucy9kb2NzLnJ1bi54bWxcIixcbiAgICBcIi5pZGVhL3J1bkNvbmZpZ3VyYXRpb25zL2RyYXdpbmdzLnJ1bi54bWxcIixcbiAgICBcIi5pZGVhL3J1bkNvbmZpZ3VyYXRpb25zL2ZsYXNoLWZvcndhcmQucnVuLnhtbFwiLFxuICAgIFwiLmlkZWEvcnVuQ29uZmlndXJhdGlvbnMvSW50ZWdyYXRpb25fVGVzdHMucnVuLnhtbFwiLFxuICAgIFwiLmlkZWEvcnVuQ29uZmlndXJhdGlvbnMvQnVuZGxpbmdfVGVzdHMucnVuLnhtbFwiLFxuICAgIFwiLmlkZWEvcnVuQ29uZmlndXJhdGlvbnMvbGludC1maXgucnVuLnhtbFwiLFxuICAgIFwiLmlkZWEvcnVuQ29uZmlndXJhdGlvbnMvcmVsZWFzZS5ydW4ueG1sXCIsXG4gICAgXCIuaWRlYS9ydW5Db25maWd1cmF0aW9ucy90ZXN0X2NpcmN1bGFyLnJ1bi54bWxcIixcbiAgICBcIi5pZGVhL3J1bkNvbmZpZ3VyYXRpb25zL3VtbC5ydW4ueG1sXCIsXG4gICAgXCIuaWRlYS9ydW5Db25maWd1cmF0aW9ucy9Vbml0IFRlc3RzLnJ1bi54bWxcIixcbiAgICBcIi5pZGVhL3J1bkNvbmZpZ3VyYXRpb25zL3VwZGF0ZS1zY3JpcHRzLnJ1bi54bWxcIixcbiAgXSxcbiAgZG9jczogW1xuICAgIFwid29ya2RvY3MvdHV0b3JpYWxzL0NvbnRyaWJ1dGluZy5tZFwiLFxuICAgIFwid29ya2RvY3MvdHV0b3JpYWxzL0RvY3VtZW50YXRpb24ubWRcIixcbiAgICBcIndvcmtkb2NzL3R1dG9yaWFscy9Gb3IgRGV2ZWxvcGVycy5tZFwiLFxuICAgIFwid29ya2RvY3MvMi1CYWRnZXMubWRcIixcbiAgICBcIndvcmtkb2NzL2pzZG9jcy5qc29uXCIsXG4gICAgXCJ3b3JrZG9jcy9yZWFkbWUtbWQuanNvblwiLFxuICBdLFxuICBzdHlsZXM6IFtcIi5wcmV0dGllcnJjXCIsIFwiZXNsaW50LmNvbmZpZy5qc1wiXSxcbiAgc2NyaXB0czogW1xuICAgIFwiYmluL3VwZGF0ZS1zY3JpcHRzLmNqc1wiLFxuICAgIFwiYmluL3RhZy1yZWxlYXNlLmNqc1wiLFxuICAgIFwiYmluL2J1aWxkLXNjcmlwdHMuY2pzXCIsXG4gIF0sXG4gIHRlc3RzOiBbXCJqZXN0LmNvbmZpZy50c1wiLCBcIndvcmtkb2NzL3JlcG9ydHMvamVzdC5jb3ZlcmFnZS5jb25maWcudHNcIl0sXG4gIHR5cGVzY3JpcHQ6IFtcInRzY29uZmlnLmpzb25cIl0sXG4gIGRvY2tlcjogW1wiRG9ja2VyZmlsZVwiXSxcbiAgYXV0b21hdGlvbjogW1xuICAgIFwid29ya2RvY3MvY29uZmx1ZW5jZS9Db250aW51b3VzIEludGVncmF0aW9uLURlcGxveW1lbnQvR2l0SHViLm1kXCIsXG4gICAgXCJ3b3JrZG9jcy9jb25mbHVlbmNlL0NvbnRpbnVvdXMgSW50ZWdyYXRpb24tRGVwbG95bWVudC9KaXJhLm1kXCIsXG4gICAgXCJ3b3JrZG9jcy9jb25mbHVlbmNlL0NvbnRpbnVvdXMgSW50ZWdyYXRpb24tRGVwbG95bWVudC9UZWFtcy5tZFwiLFxuICBdLFxufTtcblxuY29uc3QgYXJnenogPSB7XG4gIC8vIGluaXQgYXR0cmlidXRlc1xuICBib290OiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gIH0sXG4gIG9yZzoge1xuICAgIHR5cGU6IFwic3RyaW5nXCIsXG4gICAgc2hvcnQ6IFwib1wiLFxuICB9LFxuICBuYW1lOiB7XG4gICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICBzaG9ydDogXCJuXCIsXG4gICAgZGVmYXVsdDogdW5kZWZpbmVkLFxuICB9LFxuICBhdXRob3I6IHtcbiAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgIHNob3J0OiBcImFcIixcbiAgICBkZWZhdWx0OiB1bmRlZmluZWQsXG4gIH0sXG4gIC8vIHVwZGF0ZSBhdHRyaWJ1dGVzXG4gIGFsbDoge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICB9LFxuICBsaWNlbnNlOiB7XG4gICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICBtZXNzYWdlOiBcIlBpY2sgdGhlIGxpY2Vuc2VcIixcbiAgfSxcbiAgc2NyaXB0czoge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICB9LFxuICBzdHlsZXM6IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgfSxcbiAgZG9jczoge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICB9LFxuICBpZGU6IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgfSxcbiAgd29ya2Zsb3dzOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gIH0sXG4gIHRlbXBsYXRlczoge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICB9LFxuICB0eXBlc2NyaXB0OiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gIH0sXG4gIGRvY2tlcjoge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICB9LFxuICBwa2c6IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgfSxcbiAgZGVwZW5kZW5jaWVzOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gIH0sXG4gIHRlc3RzOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gIH0sXG4gIGF1dG9tYXRpb246IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgfSxcbn07XG5cbi8qKlxuICogQGNsYXNzIFRlbXBsYXRlU3luY1xuICogQGV4dGVuZHMge0NvbW1hbmR9XG4gKiBAY2F0ZWdvcnkgc2NyaXB0c1xuICogQGRlc2NyaXB0aW9uIEEgY29tbWFuZC1saW5lIHRvb2wgZm9yIHN5bmNocm9uaXppbmcgcHJvamVjdCB0ZW1wbGF0ZXMgYW5kIGNvbmZpZ3VyYXRpb25zLlxuICogQHN1bW1hcnkgVGhpcyBjbGFzcyBwcm92aWRlcyBmdW5jdGlvbmFsaXR5IHRvIGRvd25sb2FkIGFuZCB1cGRhdGUgdmFyaW91cyBwcm9qZWN0IGZpbGVzIGFuZCBjb25maWd1cmF0aW9ucyBmcm9tIGEgcmVtb3RlIHJlcG9zaXRvcnkuXG4gKiBJdCBzdXBwb3J0cyB1cGRhdGluZyBsaWNlbnNlcywgSURFIGNvbmZpZ3VyYXRpb25zLCBzY3JpcHRzLCBzdHlsZXMsIGRvY3VtZW50YXRpb24sIHdvcmtmbG93cywgYW5kIHRlbXBsYXRlcy5cbiAqXG4gKiBAcGFyYW0ge0NvbW1hbmRPcHRpb25zfSBhcmdzIC0gVGhlIGNvbW1hbmQgb3B0aW9ucyBmb3IgVGVtcGxhdGVTeW5jXG4gKi9cbmV4cG9ydCBjbGFzcyBUZW1wbGF0ZVN5bmMgZXh0ZW5kcyBDb21tYW5kPENvbW1hbmRPcHRpb25zPHR5cGVvZiBhcmd6ej4sIHZvaWQ+IHtcbiAgcHJpdmF0ZSByZXBsYWNlbWVudHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bWJlcj4gPSB7fTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcihcIlRlbXBsYXRlU3luY1wiLCBhcmd6eik7XG4gIH1cblxuICBwcml2YXRlIGxvYWRWYWx1ZXNGcm9tUGFja2FnZSgpIHtcbiAgICBjb25zdCBwID0gcHJvY2Vzcy5jd2QoKTtcbiAgICBjb25zdCBhdXRob3IgPSBnZXRQYWNrYWdlKHAsIFwiYXV0aG9yXCIpIGFzIHN0cmluZztcbiAgICBjb25zdCBzY29wZWROYW1lID0gZ2V0UGFja2FnZShwLCBcIm5hbWVcIik7XG4gICAgbGV0IG5hbWU6IHN0cmluZyA9IHNjb3BlZE5hbWUgYXMgc3RyaW5nO1xuICAgIGxldCBvcmc6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBpZiAobmFtZS5zdGFydHNXaXRoKFwiQFwiKSkge1xuICAgICAgY29uc3Qgc3BsaXQgPSBuYW1lLnNwbGl0KFwiL1wiKTtcbiAgICAgIG5hbWUgPSBzcGxpdFsxXTtcbiAgICAgIG9yZyA9IHNwbGl0WzBdLnJlcGxhY2UoXCJAXCIsIFwiXCIpO1xuICAgIH1cbiAgICBbXCJUaWFnbyBWZW5jZXNsYXVcIiwgXCJUaWFnb1ZlbmNlc2xhdVwiLCBcIiR7YXV0aG9yfVwiXS5mb3JFYWNoKFxuICAgICAgKGVsKSA9PiAodGhpcy5yZXBsYWNlbWVudHNbZWxdID0gYXV0aG9yKVxuICAgICk7XG4gICAgW1wiVFMtV29ya3NwYWNlXCIsIFwidHMtd29ya3NwYWNlXCIsIFwiJHtuYW1lfVwiXS5mb3JFYWNoKFxuICAgICAgKGVsKSA9PiAodGhpcy5yZXBsYWNlbWVudHNbZWxdID0gbmFtZSlcbiAgICApO1xuICAgIFtcImRlY2FmLXRzXCIsIFwiJHtvcmd9XCJdLmZvckVhY2goXG4gICAgICAoZWwpID0+ICh0aGlzLnJlcGxhY2VtZW50c1tlbF0gPSAob3JnIGFzIHN0cmluZykgfHwgJ1wiXCInKVxuICAgICk7XG4gICAgdGhpcy5yZXBsYWNlbWVudHNbXCIke29yZ19vcl9vd25lcn1cIl0gPSBvcmcgfHwgbmFtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRG93bmxvYWRzIGZpbGVzIGZvciBhIHNwZWNpZmljIG9wdGlvbiBjYXRlZ29yeS5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgZG93bmxvYWRzIGFsbCBmaWxlcyBhc3NvY2lhdGVkIHdpdGggYSBnaXZlbiBvcHRpb24ga2V5IGZyb20gdGhlIHJlbW90ZSByZXBvc2l0b3J5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIGtleSByZXByZXNlbnRpbmcgdGhlIG9wdGlvbiBjYXRlZ29yeSB0byBkb3dubG9hZFxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBzcGVjaWZpZWQgb3B0aW9uIGtleSBpcyBub3QgZm91bmRcbiAgICovXG4gIGFzeW5jIGRvd25sb2FkT3B0aW9uKGtleToga2V5b2YgdHlwZW9mIG9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIShrZXkgaW4gb3B0aW9ucykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgT3B0aW9uIFwiJHtrZXl9XCIgbm90IGZvdW5kIGluIG9wdGlvbnNgKTtcbiAgICB9XG4gICAgY29uc3QgZmlsZXMgPSBvcHRpb25zW2tleSBhcyBrZXlvZiB0eXBlb2Ygb3B0aW9uc107XG5cbiAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgIHRoaXMubG9nLmluZm8oYERvd25sb2FkaW5nICR7ZmlsZX1gKTtcblxuICAgICAgbGV0IGRhdGEgPSBhd2FpdCBIdHRwQ2xpZW50LmRvd25sb2FkRmlsZShgJHtiYXNlVXJsfS8ke2ZpbGV9YCk7XG4gICAgICBkYXRhID0gcGF0Y2hTdHJpbmcoZGF0YSwgdGhpcy5yZXBsYWNlbWVudHMpO1xuICAgICAgd3JpdGVGaWxlKHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCBmaWxlKSwgZGF0YSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEb3dubG9hZHMgYW5kIHNldHMgdXAgdGhlIHNwZWNpZmllZCBsaWNlbnNlLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBkb3dubG9hZHMgdGhlIGNob3NlbiBsaWNlbnNlIGZpbGUsIHNhdmVzIGl0IHRvIHRoZSBwcm9qZWN0LCBhbmQgdXBkYXRlcyB0aGUgcGFja2FnZS5qc29uIGxpY2Vuc2UgZmllbGQuXG4gICAqIEBwYXJhbSB7XCJNSVRcIiB8IFwiR1BMXCIgfCBcIkFwYWNoZVwiIHwgXCJMR1BMXCIgfCBcIkFHUExcIn0gbGljZW5zZSAtIFRoZSBsaWNlbnNlIHRvIGRvd25sb2FkIGFuZCBzZXQgdXBcbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBnZXRMaWNlbnNlKGxpY2Vuc2U6IFwiTUlUXCIgfCBcIkdQTFwiIHwgXCJBcGFjaGVcIiB8IFwiTEdQTFwiIHwgXCJBR1BMXCIpIHtcbiAgICB0aGlzLmxvZy5pbmZvKGBEb3dubG9hZGluZyAke2xpY2Vuc2V9IGxpY2Vuc2VgKTtcbiAgICBjb25zdCB1cmwgPSBgJHtiYXNlVXJsfS93b3JrZG9jcy9saWNlbnNlcy8ke2xpY2Vuc2V9Lm1kYDtcbiAgICBsZXQgZGF0YSA9IGF3YWl0IEh0dHBDbGllbnQuZG93bmxvYWRGaWxlKHVybCk7XG4gICAgZGF0YSA9IHBhdGNoU3RyaW5nKGRhdGEsIHRoaXMucmVwbGFjZW1lbnRzKTtcbiAgICB3cml0ZUZpbGUocGF0aC5qb2luKHByb2Nlc3MuY3dkKCksIFwiTElDRU5TRS5tZFwiKSwgZGF0YSk7XG4gICAgc2V0UGFja2FnZUF0dHJpYnV0ZShcImxpY2Vuc2VcIiwgbGljZW5zZSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERvd25sb2FkcyBJREUgY29uZmlndXJhdGlvbiBmaWxlcy5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBnZXRJZGUoKSB7XG4gICAgZnMubWtkaXJTeW5jKHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCBcIi5pZGVhXCIsIFwicnVuQ29uZmlndXJhdGlvbnNcIiksIHtcbiAgICAgIHJlY3Vyc2l2ZTogdHJ1ZSxcbiAgICB9KTtcbiAgICBhd2FpdCB0aGlzLmRvd25sb2FkT3B0aW9uKFwiaWRlXCIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVcGRhdGUgbnBtIHNjcmlwdHNcbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBnZXRTY3JpcHRzKCkge1xuICAgIGF3YWl0IHRoaXMuZG93bmxvYWRPcHRpb24oXCJzY3JpcHRzXCIpO1xuICAgIHRoaXMubG9nLmluZm8oXCJwbGVhc2UgcmUtcnVuIHRoZSBjb21tYW5kXCIpO1xuICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRG93bmxvYWRzIHN0eWxlIGNvbmZpZ3VyYXRpb24gZmlsZXMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgZ2V0U3R5bGVzID0gKCkgPT4gdGhpcy5kb3dubG9hZE9wdGlvbihcInN0eWxlc1wiKTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERvd25sb2FkcyB0ZW1wbGF0ZSBmaWxlcy5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBnZXRUZW1wbGF0ZXMgPSAoKSA9PiB0aGlzLmRvd25sb2FkT3B0aW9uKFwidGVtcGxhdGVzXCIpO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRG93bmxvYWRzIHdvcmtmbG93IGNvbmZpZ3VyYXRpb24gZmlsZXMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgZ2V0V29ya2Zsb3dzID0gKCkgPT4gdGhpcy5kb3dubG9hZE9wdGlvbihcIndvcmtmbG93c1wiKTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERvd25sb2FkcyBkb2N1bWVudGF0aW9uIGZpbGVzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGdldERvY3MgPSAoKSA9PiB0aGlzLmRvd25sb2FkT3B0aW9uKFwiZG9jc1wiKTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERvd25sb2FkcyB0eXBlc2NyaXB0IGNvbmZpZyBmaWxlcy5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBnZXRUeXBlc2NyaXB0ID0gKCkgPT4gdGhpcy5kb3dubG9hZE9wdGlvbihcInR5cGVzY3JpcHRcIik7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEb3dubG9hZHMgYXV0b21hdGlvbiBkb2N1bWVudGF0aW9uIGZpbGVzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGdldEF1dG9tYXRpb24gPSAoKSA9PiB0aGlzLmRvd25sb2FkT3B0aW9uKFwiYXV0b21hdGlvblwiKTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERvd25sb2FkcyBhdXRvbWF0aW9uIGRvY3VtZW50YXRpb24gZmlsZXMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgZ2V0VGVzdHMgPSAoKSA9PiB0aGlzLmRvd25sb2FkT3B0aW9uKFwidGVzdHNcIik7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEb3dubG9hZHMgZG9ja2VyIGltYWdlIGZpbGVzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGdldERvY2tlciA9ICgpID0+IHRoaXMuZG93bmxvYWRPcHRpb24oXCJkb2NrZXJcIik7XG5cbiAgYXN5bmMgaW5pdFBhY2thZ2UocGtnTmFtZTogc3RyaW5nLCBhdXRob3I6IHN0cmluZywgbGljZW5zZTogc3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHBrZyA9IGdldFBhY2thZ2UoKSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIGRlbGV0ZSBwa2dbU2V0dXBTY3JpcHRLZXldO1xuICAgICAgcGtnLm5hbWUgPSBwa2dOYW1lO1xuICAgICAgcGtnLnZlcnNpb24gPSBcIjAuMC4xXCI7XG4gICAgICBwa2cuYXV0aG9yID0gYXV0aG9yO1xuICAgICAgcGtnLmxpY2Vuc2UgPSBsaWNlbnNlO1xuICAgICAgZnMud3JpdGVGaWxlU3luYyhcInBhY2thZ2UuanNvblwiLCBKU09OLnN0cmluZ2lmeShwa2csIG51bGwsIDIpKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGZpeGluZyBwYWNrYWdlLmpzb246ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyB1cGRhdGVQYWNrYWdlU2NyaXBzKCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBvcmlnaW5hbFBrZyA9IEpTT04ucGFyc2UoXG4gICAgICAgIGF3YWl0IEh0dHBDbGllbnQuZG93bmxvYWRGaWxlKGAke2Jhc2VVcmx9L3BhY2thZ2UuanNvbmApXG4gICAgICApO1xuICAgICAgY29uc3QgeyBzY3JpcHRzIH0gPSBvcmlnaW5hbFBrZztcblxuICAgICAgY29uc3QgcGtnOiB0eXBlb2Ygb3JpZ2luYWxQa2cgPSBnZXRQYWNrYWdlKCkgYXMge1xuICAgICAgICBzY3JpcHRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICAgICAgfTtcbiAgICAgIE9iamVjdC5rZXlzKHBrZy5zY3JpcHRzKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgICAgaWYgKGtleSBpbiBzY3JpcHRzKSB7XG4gICAgICAgICAgY29uc3QgcmVwbGFjZWQgPSBwYXRjaFN0cmluZyhzY3JpcHRzW2tleV0sIHRoaXMucmVwbGFjZW1lbnRzKTtcbiAgICAgICAgICBpZiAocmVwbGFjZWQgIT09IHNjcmlwdHNba2V5XSkge1xuICAgICAgICAgICAgcGtnLnNjcmlwdHNba2V5XSA9IHJlcGxhY2VkO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHBrZ1tcImV4cG9ydHNcIl1bXCJyZXF1aXJlXCJdID0gb3JpZ2luYWxQa2dbXCJleHBvcnRzXCJdW1wicmVxdWlyZVwiXTtcbiAgICAgIHBrZ1tcImV4cG9ydHNcIl1bXCJpbXBvcnRcIl0gPSBvcmlnaW5hbFBrZ1tcImV4cG9ydHNcIl1bXCJpbXBvcnRcIl07XG4gICAgICBwa2dbXCJ0eXBlc1wiXSA9IG9yaWdpbmFsUGtnW1widHlwZXNcIl07XG5cbiAgICAgIGZzLndyaXRlRmlsZVN5bmMoXCJwYWNrYWdlLmpzb25cIiwgSlNPTi5zdHJpbmdpZnkocGtnLCBudWxsLCAyKSk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBmaXhpbmcgcGFja2FnZS5qc29uIHNjcmlwdHM6ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBjcmVhdGVUb2tlbkZpbGVzKCkge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLmNyZWF0ZVRva2VuRmlsZXMpO1xuICAgIGNvbnN0IGdpdFRva2VuID0gYXdhaXQgVXNlcklucHV0Lmluc2lzdEZvclRleHQoXG4gICAgICBcInRva2VuXCIsXG4gICAgICBcInBsZWFzZSBpbnB1dCB5b3VyIGdpdGh1YiB0b2tlblwiLFxuICAgICAgKHJlczogc3RyaW5nKSA9PiB7XG4gICAgICAgIHJldHVybiAhIXJlcy5tYXRjaCgvXmdocF9bMC05YS16QS1aXXszNn0kL2cpO1xuICAgICAgfVxuICAgICk7XG4gICAgT2JqZWN0LnZhbHVlcyhUb2tlbnMpLmZvckVhY2goKHRva2VuKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBsZXQgc3RhdHVzO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHN0YXR1cyA9IGZzLmV4aXN0c1N5bmModG9rZW4pO1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAgICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgICAgIGxvZy5pbmZvKGBUb2tlbiBmaWxlICR7dG9rZW59IG5vdCBmb3VuZC4gQ3JlYXRpbmcgYSBuZXcgb25lLi4uYCk7XG4gICAgICAgICAgZnMud3JpdGVGaWxlU3luYyh0b2tlbiwgdG9rZW4gPT09IFwiLnRva2VuXCIgPyBnaXRUb2tlbiA6IFwiXCIpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXN0YXR1cykge1xuICAgICAgICAgIGZzLndyaXRlRmlsZVN5bmModG9rZW4sIHRva2VuID09PSBcIi50b2tlblwiID8gZ2l0VG9rZW4gOiBcIlwiKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGNyZWF0aW5nIHRva2VuIGZpbGUgJHt0b2tlbn06ICR7ZX1gKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGdldE9yZygpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IG9yZyA9IGF3YWl0IFVzZXJJbnB1dC5hc2tUZXh0KFxuICAgICAgXCJPcmdhbml6YXRpb25cIixcbiAgICAgIFwiRW50ZXIgdGhlIG9yZ2FuaXphdGlvbiBuYW1lICh3aWxsIGJlIHVzZWQgdG8gc2NvcGUgeW91ciBucG0gcHJvamVjdC4gbGVhdmUgYmxhbmsgdG8gY3JlYXRlIGEgdW5zY29wZWQgcHJvamVjdCk6XCJcbiAgICApO1xuICAgIGNvbnN0IGNvbmZpcm1hdGlvbiA9IGF3YWl0IFVzZXJJbnB1dC5hc2tDb25maXJtYXRpb24oXG4gICAgICBcIkNvbmZpcm0gb3JnYW5pemF0aW9uXCIsXG4gICAgICBcIklzIHRoaXMgb3JnYW5pemF0aW9uIGNvcnJlY3Q/XCIsXG4gICAgICB0cnVlXG4gICAgKTtcbiAgICBpZiAoIWNvbmZpcm1hdGlvbikgcmV0dXJuIHRoaXMuZ2V0T3JnKCk7XG5cbiAgICByZXR1cm4gb3JnO1xuICB9XG5cbiAgYXN5bmMgYXVkaXRGaXgoKSB7XG4gICAgcmV0dXJuIGF3YWl0IHJ1bkNvbW1hbmQoXCJucG0gYXVkaXQgZml4IC0tZm9yY2VcIikucHJvbWlzZTtcbiAgfVxuXG4gIHBhdGNoRmlsZXMoKSB7XG4gICAgY29uc3QgZmlsZXMgPSBbXG4gICAgICAuLi5mc1xuICAgICAgICAucmVhZGRpclN5bmMocGF0aC5qb2luKHByb2Nlc3MuY3dkKCksIFwic3JjXCIpLCB7XG4gICAgICAgICAgcmVjdXJzaXZlOiB0cnVlLFxuICAgICAgICAgIHdpdGhGaWxlVHlwZXM6IHRydWUsXG4gICAgICAgIH0pXG4gICAgICAgIC5maWx0ZXIoKGVudHJ5KSA9PiBlbnRyeS5pc0ZpbGUoKSlcbiAgICAgICAgLm1hcCgoZW50cnkpID0+IHBhdGguam9pbihlbnRyeS5wYXJlbnRQYXRoLCBlbnRyeS5uYW1lKSksXG4gICAgICAuLi5mc1xuICAgICAgICAucmVhZGRpclN5bmMocGF0aC5qb2luKHByb2Nlc3MuY3dkKCksIFwid29ya2RvY3NcIiksIHtcbiAgICAgICAgICByZWN1cnNpdmU6IHRydWUsXG4gICAgICAgICAgd2l0aEZpbGVUeXBlczogdHJ1ZSxcbiAgICAgICAgfSlcbiAgICAgICAgLmZpbHRlcigoZW50cnkpID0+IGVudHJ5LmlzRmlsZSgpICYmIGVudHJ5Lm5hbWUuZW5kc1dpdGgoXCIubWRcIikpXG4gICAgICAgIC5tYXAoKGVudHJ5KSA9PiBwYXRoLmpvaW4oZW50cnkucGFyZW50UGF0aCwgZW50cnkubmFtZSkpLFxuICAgICAgcGF0aC5qb2luKHByb2Nlc3MuY3dkKCksIFwiLmdpdGxhYi1jaS55bWxcIiksXG4gICAgICBwYXRoLmpvaW4ocHJvY2Vzcy5jd2QoKSwgXCJ3b3JrZG9jc1wiLCBcImpzZG9jcy5qc29uXCIpLFxuICAgIF07XG5cbiAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgIHBhdGNoRmlsZShmaWxlIGFzIHN0cmluZywgdGhpcy5yZXBsYWNlbWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHVwZGF0ZURlcGVuZGVuY2llcygpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3Qgb3JpZ2luYWxQa2cgPSBKU09OLnBhcnNlKFxuICAgICAgICBhd2FpdCBIdHRwQ2xpZW50LmRvd25sb2FkRmlsZShgJHtiYXNlVXJsfS9wYWNrYWdlLmpzb25gKVxuICAgICAgKTtcbiAgICAgIGNvbnN0IHsgZGV2RGVwZW5kZW5jaWVzIH0gPSBvcmlnaW5hbFBrZztcblxuICAgICAgY29uc3QgcGtnOiB0eXBlb2Ygb3JpZ2luYWxQa2cgPSBnZXRQYWNrYWdlKCkgYXMge1xuICAgICAgICBzY3JpcHRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICAgICAgfTtcbiAgICAgIE9iamVjdC5rZXlzKHBrZy5zY3JpcHRzKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgICAgaWYgKGtleSBpbiBkZXZEZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgICBjb25zdCByZXBsYWNlZCA9IGRldkRlcGVuZGVuY2llc1trZXldO1xuICAgICAgICAgIGlmIChyZXBsYWNlZCAhPT0gZGV2RGVwZW5kZW5jaWVzW2tleV0pIHtcbiAgICAgICAgICAgIChwa2cgYXMgYW55KVtcImRldkRlcGVuZGVuY2llc1wiXSA9XG4gICAgICAgICAgICAgIChwa2cgYXMgYW55KVtcImRldkRlcGVuZGVuY2llc1wiXSB8fCB7fTtcbiAgICAgICAgICAgIChwa2cgYXMgYW55KVtcImRldkRlcGVuZGVuY2llc1wiXVtrZXldID0gcmVwbGFjZWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgZnMud3JpdGVGaWxlU3luYyhcInBhY2thZ2UuanNvblwiLCBKU09OLnN0cmluZ2lmeShwa2csIG51bGwsIDIpKTtcbiAgICAgIGF3YWl0IHJ1bkNvbW1hbmQoXCJucG0gaW5zdGFsbFwiKS5wcm9taXNlO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZml4aW5nIHBhY2thZ2UuanNvbiBkZXBlbmRlbmNpZXM6ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJ1bnMgdGhlIHRlbXBsYXRlIHN5bmNocm9uaXphdGlvbiBwcm9jZXNzLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBvcmNoZXN0cmF0ZXMgdGhlIGRvd25sb2FkaW5nIG9mIHZhcmlvdXMgcHJvamVjdCBjb21wb25lbnRzIGJhc2VkIG9uIHRoZSBwcm92aWRlZCBhcmd1bWVudHMuXG4gICAqIEBwYXJhbSB7UGFyc2VBcmdzUmVzdWx0fSBhcmdzIC0gVGhlIHBhcnNlZCBjb21tYW5kLWxpbmUgYXJndW1lbnRzXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBUIGFzIFRlbXBsYXRlU3luY1xuICAgKiAgIHBhcnRpY2lwYW50IEwgYXMgZ2V0TGljZW5zZVxuICAgKiAgIHBhcnRpY2lwYW50IEkgYXMgZ2V0SWRlXG4gICAqICAgcGFydGljaXBhbnQgUyBhcyBnZXRTY3JpcHRzXG4gICAqICAgcGFydGljaXBhbnQgU3QgYXMgZ2V0U3R5bGVzXG4gICAqICAgcGFydGljaXBhbnQgRCBhcyBnZXREb2NzXG4gICAqICAgcGFydGljaXBhbnQgVyBhcyBnZXRXb3JrZmxvd3NcbiAgICogICBwYXJ0aWNpcGFudCBUZSBhcyBnZXRUZW1wbGF0ZXNcbiAgICogICBULT4+VDogUGFyc2UgYXJndW1lbnRzXG4gICAqICAgYWx0IGFsbCBmbGFnIGlzIHRydWVcbiAgICogICAgIFQtPj5UOiBTZXQgYWxsIGNvbXBvbmVudCBmbGFncyB0byB0cnVlXG4gICAqICAgZW5kXG4gICAqICAgYWx0IGxpY2Vuc2UgaXMgc3BlY2lmaWVkXG4gICAqICAgICBULT4+TDogZ2V0TGljZW5zZShsaWNlbnNlKVxuICAgKiAgIGVuZFxuICAgKiAgIGFsdCBpZGUgZmxhZyBpcyB0cnVlXG4gICAqICAgICBULT4+STogZ2V0SWRlKClcbiAgICogICBlbmRcbiAgICogICBhbHQgc2NyaXB0cyBmbGFnIGlzIHRydWVcbiAgICogICAgIFQtPj5TOiBnZXRTY3JpcHRzKClcbiAgICogICBlbmRcbiAgICogICBhbHQgc3R5bGVzIGZsYWcgaXMgdHJ1ZVxuICAgKiAgICAgVC0+PlN0OiBnZXRTdHlsZXMoKVxuICAgKiAgIGVuZFxuICAgKiAgIGFsdCBkb2NzIGZsYWcgaXMgdHJ1ZVxuICAgKiAgICAgVC0+PkQ6IGdldERvY3MoKVxuICAgKiAgIGVuZFxuICAgKiAgIGFsdCB3b3JrZmxvd3MgZmxhZyBpcyB0cnVlXG4gICAqICAgICBULT4+VzogZ2V0V29ya2Zsb3dzKClcbiAgICogICBlbmRcbiAgICogICBhbHQgdGVtcGxhdGVzIGZsYWcgaXMgdHJ1ZVxuICAgKiAgICAgVC0+PlRlOiBnZXRUZW1wbGF0ZXMoKVxuICAgKiAgIGVuZFxuICAgKi9cbiAgYXN5bmMgcnVuKFxuICAgIGFyZ3M6IExvZ2dpbmdDb25maWcgJlxuICAgICAgdHlwZW9mIERlZmF1bHRDb21tYW5kVmFsdWVzICYgeyBbayBpbiBrZXlvZiB0eXBlb2YgYXJnenpdOiB1bmtub3duIH1cbiAgKSB7XG4gICAgbGV0IHsgbGljZW5zZSB9ID0gYXJncztcbiAgICBjb25zdCB7IGJvb3QgfSA9IGFyZ3M7XG4gICAgbGV0IHtcbiAgICAgIGFsbCxcbiAgICAgIHNjcmlwdHMsXG4gICAgICBzdHlsZXMsXG4gICAgICBkb2NzLFxuICAgICAgaWRlLFxuICAgICAgd29ya2Zsb3dzLFxuICAgICAgdGVtcGxhdGVzLFxuICAgICAgZG9ja2VyLFxuICAgICAgdHlwZXNjcmlwdCxcbiAgICAgIGRlcGVuZGVuY2llcyxcbiAgICAgIHRlc3RzLFxuICAgICAgYXV0b21hdGlvbixcbiAgICAgIHBrZyxcbiAgICB9ID0gYXJncztcbiAgICBpZiAoXG4gICAgICBzY3JpcHRzIHx8XG4gICAgICBzdHlsZXMgfHxcbiAgICAgIGRvY3MgfHxcbiAgICAgIGlkZSB8fFxuICAgICAgd29ya2Zsb3dzIHx8XG4gICAgICB0ZW1wbGF0ZXMgfHxcbiAgICAgIGRvY2tlciB8fFxuICAgICAgdHlwZXNjcmlwdCB8fFxuICAgICAgYXV0b21hdGlvbiB8fFxuICAgICAgZGVwZW5kZW5jaWVzIHx8XG4gICAgICB0ZXN0cyB8fFxuICAgICAgcGtnXG4gICAgKVxuICAgICAgYWxsID0gZmFsc2U7XG5cbiAgICBpZiAoYm9vdCkge1xuICAgICAgY29uc3Qgb3JnID0gYXdhaXQgdGhpcy5nZXRPcmcoKTtcbiAgICAgIGNvbnN0IG5hbWUgPSBhd2FpdCBVc2VySW5wdXQuaW5zaXN0Rm9yVGV4dChcbiAgICAgICAgXCJQcm9qZWN0IG5hbWVcIixcbiAgICAgICAgXCJFbnRlciB0aGUgcHJvamVjdCBuYW1lOlwiLFxuICAgICAgICAocmVzOiBzdHJpbmcpID0+IHJlcy5sZW5ndGggPiAxXG4gICAgICApO1xuICAgICAgY29uc3QgYXV0aG9yID0gYXdhaXQgVXNlcklucHV0Lmluc2lzdEZvclRleHQoXG4gICAgICAgIFwiQXV0aG9yXCIsXG4gICAgICAgIFwiRW50ZXIgdGhlIGF1dGhvciBuYW1lOlwiLFxuICAgICAgICAocmVzOiBzdHJpbmcpID0+IHJlcy5sZW5ndGggPiAxXG4gICAgICApO1xuICAgICAgY29uc3QgcGtnTmFtZSA9IG9yZyA/IGBAJHtvcmd9LyR7bmFtZX1gIDogbmFtZTtcblxuICAgICAgYXdhaXQgdGhpcy5pbml0UGFja2FnZShwa2dOYW1lLCBhdXRob3IsIGxpY2Vuc2UgYXMgc3RyaW5nKTtcbiAgICAgIGF3YWl0IHRoaXMuY3JlYXRlVG9rZW5GaWxlcygpO1xuICAgICAgYXdhaXQgdGhpcy5hdWRpdEZpeCgpO1xuICAgICAgdGhpcy5wYXRjaEZpbGVzKCk7XG4gICAgfVxuXG4gICAgaWYgKGFsbCkge1xuICAgICAgc2NyaXB0cyA9IGZhbHNlO1xuICAgICAgc3R5bGVzID0gdHJ1ZTtcbiAgICAgIGRvY3MgPSB0cnVlO1xuICAgICAgaWRlID0gdHJ1ZTtcbiAgICAgIHdvcmtmbG93cyA9IHRydWU7XG4gICAgICB0ZW1wbGF0ZXMgPSB0cnVlO1xuICAgICAgZG9ja2VyID0gdHJ1ZTtcbiAgICAgIHR5cGVzY3JpcHQgPSB0cnVlO1xuICAgICAgcGtnID0gdHJ1ZTtcbiAgICAgIGRlcGVuZGVuY2llcyA9IHRydWU7XG4gICAgICB0ZXN0cyA9IHRydWU7XG4gICAgICBhdXRvbWF0aW9uID0gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBzY3JpcHRzID09PSBcInVuZGVmaW5lZFwiKVxuICAgICAgc2NyaXB0cyA9IGF3YWl0IFVzZXJJbnB1dC5hc2tDb25maXJtYXRpb24oXG4gICAgICAgIFwic2NyaXB0c1wiLFxuICAgICAgICBcIkRvIHlvdSB3YW50IHRvIGdldCBzY3JpcHRzP1wiLFxuICAgICAgICB0cnVlXG4gICAgICApO1xuXG4gICAgaWYgKHNjcmlwdHMpIGF3YWl0IHRoaXMuZ2V0U2NyaXB0cygpO1xuXG4gICAgdGhpcy5sb2FkVmFsdWVzRnJvbVBhY2thZ2UoKTtcbiAgICBpZiAoIWFsbCAmJiB0eXBlb2YgbGljZW5zZSA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgY29uc3QgY29uZmlybWF0aW9uID0gYXdhaXQgVXNlcklucHV0LmFza0NvbmZpcm1hdGlvbihcbiAgICAgICAgXCJsaWNlbnNlXCIsXG4gICAgICAgIFwiRG8geW91IHdhbnQgdG8gc2V0IGEgbGljZW5zZT9cIixcbiAgICAgICAgdHJ1ZVxuICAgICAgKTtcbiAgICAgIGlmIChjb25maXJtYXRpb24pXG4gICAgICAgIGxpY2Vuc2UgPSBhd2FpdCBVc2VySW5wdXQuaW5zaXN0Rm9yVGV4dChcbiAgICAgICAgICBcImxpY2Vuc2VcIixcbiAgICAgICAgICBcIkVudGVyIHRoZSBkZXNpcmVkIExpY2Vuc2UgKE1JVHxHUEx8QXBhY2hlfExHUEx8QUdQTCk6XCIsXG4gICAgICAgICAgKHZhbCkgPT4gISF2YWwgJiYgISF2YWwubWF0Y2goL14oTUlUfEdQTHxBcGFjaGV8TEdQTHxBR1BMKSQvZylcbiAgICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBsaWNlbnNlICE9PSBcInVuZGVmaW5lZFwiKVxuICAgICAgYXdhaXQgdGhpcy5nZXRMaWNlbnNlKFxuICAgICAgICBsaWNlbnNlIGFzIFwiTUlUXCIgfCBcIkdQTFwiIHwgXCJBcGFjaGVcIiB8IFwiTEdQTFwiIHwgXCJBR1BMXCJcbiAgICAgICk7XG5cbiAgICBpZiAodHlwZW9mIGlkZSA9PT0gXCJ1bmRlZmluZWRcIilcbiAgICAgIGlkZSA9IGF3YWl0IFVzZXJJbnB1dC5hc2tDb25maXJtYXRpb24oXG4gICAgICAgIFwiaWRlXCIsXG4gICAgICAgIFwiRG8geW91IHdhbnQgdG8gZ2V0IGlkZSBjb25maWdzP1wiLFxuICAgICAgICB0cnVlXG4gICAgICApO1xuXG4gICAgaWYgKGlkZSkgYXdhaXQgdGhpcy5nZXRJZGUoKTtcblxuICAgIGlmICh0eXBlb2YgdHlwZXNjcmlwdCA9PT0gXCJ1bmRlZmluZWRcIilcbiAgICAgIHR5cGVzY3JpcHQgPSBhd2FpdCBVc2VySW5wdXQuYXNrQ29uZmlybWF0aW9uKFxuICAgICAgICBcInR5cGVzY3JpcHRcIixcbiAgICAgICAgXCJEbyB5b3Ugd2FudCB0byBnZXQgdHlwZXNjcmlwdCBjb25maWdzP1wiLFxuICAgICAgICB0cnVlXG4gICAgICApO1xuICAgIGlmICh0eXBlc2NyaXB0KSBhd2FpdCB0aGlzLmdldFR5cGVzY3JpcHQoKTtcblxuICAgIGlmICh0eXBlb2YgZG9ja2VyID09PSBcInVuZGVmaW5lZFwiKVxuICAgICAgZG9ja2VyID0gYXdhaXQgVXNlcklucHV0LmFza0NvbmZpcm1hdGlvbihcbiAgICAgICAgXCJkb2NrZXJcIixcbiAgICAgICAgXCJEbyB5b3Ugd2FudCB0byBnZXQgZG9ja2VyIGNvbmZpZ3M/XCIsXG4gICAgICAgIHRydWVcbiAgICAgICk7XG5cbiAgICBpZiAoZG9ja2VyKSBhd2FpdCB0aGlzLmdldERvY2tlcigpO1xuICAgIGlmICh0eXBlb2YgYXV0b21hdGlvbiA9PT0gXCJ1bmRlZmluZWRcIilcbiAgICAgIGF1dG9tYXRpb24gPSBhd2FpdCBVc2VySW5wdXQuYXNrQ29uZmlybWF0aW9uKFxuICAgICAgICBcImF1dG9tYXRpb25cIixcbiAgICAgICAgXCJEbyB5b3Ugd2FudCB0byBnZXQgYXV0b21hdGlvbiBjb25maWdzP1wiLFxuICAgICAgICB0cnVlXG4gICAgICApO1xuICAgIGlmIChhdXRvbWF0aW9uKSBhd2FpdCB0aGlzLmdldEF1dG9tYXRpb24oKTtcblxuICAgIGlmICh0eXBlb2Ygc3R5bGVzID09PSBcInVuZGVmaW5lZFwiKVxuICAgICAgc3R5bGVzID0gYXdhaXQgVXNlcklucHV0LmFza0NvbmZpcm1hdGlvbihcbiAgICAgICAgXCJzdHlsZXNcIixcbiAgICAgICAgXCJEbyB5b3Ugd2FudCB0byBnZXQgc3R5bGVzP1wiLFxuICAgICAgICB0cnVlXG4gICAgICApO1xuICAgIGlmIChzdHlsZXMpIGF3YWl0IHRoaXMuZ2V0U3R5bGVzKCk7XG5cbiAgICBpZiAodHlwZW9mIGRvY3MgPT09IFwidW5kZWZpbmVkXCIpXG4gICAgICBkb2NzID0gYXdhaXQgVXNlcklucHV0LmFza0NvbmZpcm1hdGlvbihcbiAgICAgICAgXCJkb2NzXCIsXG4gICAgICAgIFwiRG8geW91IHdhbnQgdG8gZ2V0IGRvY3M/XCIsXG4gICAgICAgIHRydWVcbiAgICAgICk7XG4gICAgaWYgKGRvY3MpIGF3YWl0IHRoaXMuZ2V0RG9jcygpO1xuICAgIGlmICh0eXBlb2Ygd29ya2Zsb3dzID09PSBcInVuZGVmaW5lZFwiKVxuICAgICAgd29ya2Zsb3dzID0gYXdhaXQgVXNlcklucHV0LmFza0NvbmZpcm1hdGlvbihcbiAgICAgICAgXCJ3b3JrZmxvd3NcIixcbiAgICAgICAgXCJEbyB5b3Ugd2FudCB0byBnZXQgd29ya2Zsb3dzP1wiLFxuICAgICAgICB0cnVlXG4gICAgICApO1xuICAgIGlmICh3b3JrZmxvd3MpIGF3YWl0IHRoaXMuZ2V0V29ya2Zsb3dzKCk7XG4gICAgaWYgKHR5cGVvZiB0ZW1wbGF0ZXMgPT09IFwidW5kZWZpbmVkXCIpXG4gICAgICB0ZW1wbGF0ZXMgPSBhd2FpdCBVc2VySW5wdXQuYXNrQ29uZmlybWF0aW9uKFxuICAgICAgICBcInRlbXBsYXRlc1wiLFxuICAgICAgICBcIkRvIHlvdSB3YW50IHRvIGdldCB0ZW1wbGF0ZXM/XCIsXG4gICAgICAgIHRydWVcbiAgICAgICk7XG4gICAgaWYgKHRlbXBsYXRlcykgYXdhaXQgdGhpcy5nZXRUZW1wbGF0ZXMoKTtcbiAgICBpZiAodHlwZW9mIHBrZyA9PT0gXCJ1bmRlZmluZWRcIilcbiAgICAgIHBrZyA9IGF3YWl0IFVzZXJJbnB1dC5hc2tDb25maXJtYXRpb24oXG4gICAgICAgIFwicGtnXCIsXG4gICAgICAgIFwiRG8geW91IHdhbnQgdG8gdXBkYXRlIHlvdXIgcGFja2FnZS5qc29uIHNjcmlwdHM/XCIsXG4gICAgICAgIHRydWVcbiAgICAgICk7XG4gICAgaWYgKHBrZykgYXdhaXQgdGhpcy51cGRhdGVQYWNrYWdlU2NyaXBzKCk7XG5cbiAgICBpZiAodHlwZW9mIHRlc3RzID09PSBcInVuZGVmaW5lZFwiKVxuICAgICAgdGVzdHMgPSBhd2FpdCBVc2VySW5wdXQuYXNrQ29uZmlybWF0aW9uKFxuICAgICAgICBcInBrZ1wiLFxuICAgICAgICBcIkRvIHlvdSB3YW50IHRvIHVwZGF0ZSB5b3VyIHRlc3QgY29uZmlncz9cIixcbiAgICAgICAgdHJ1ZVxuICAgICAgKTtcbiAgICBpZiAodGVzdHMpIGF3YWl0IHRoaXMuZ2V0VGVzdHMoKTtcblxuICAgIGlmICh0eXBlb2YgZGVwZW5kZW5jaWVzID09PSBcInVuZGVmaW5lZFwiKVxuICAgICAgZGVwZW5kZW5jaWVzID0gYXdhaXQgVXNlcklucHV0LmFza0NvbmZpcm1hdGlvbihcbiAgICAgICAgXCJwa2dcIixcbiAgICAgICAgXCJEbyB5b3Ugd2FudCB0byB1cGRhdGUgZGV2IGRlcGVuZGVuY2llcz9cIixcbiAgICAgICAgdHJ1ZVxuICAgICAgKTtcbiAgICBpZiAoZGVwZW5kZW5jaWVzKSBhd2FpdCB0aGlzLnVwZGF0ZURlcGVuZGVuY2llcygpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBTdGFuZGFyZE91dHB1dFdyaXRlciB9IGZyb20gXCIuL1N0YW5kYXJkT3V0cHV0V3JpdGVyXCI7XG5pbXBvcnQgeyBQcm9taXNlRXhlY3V0b3IgfSBmcm9tIFwiLi4vdXRpbHMvdHlwZXNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQSBzcGVjaWFsaXplZCBvdXRwdXQgd3JpdGVyIHRoYXQgdXNlcyByZWd1bGFyIGV4cHJlc3Npb25zIHRvIHByb2Nlc3Mgb3V0cHV0LlxuICogQHN1bW1hcnkgVGhpcyBjbGFzcyBleHRlbmRzIFN0YW5kYXJkT3V0cHV0V3JpdGVyIHRvIHByb3ZpZGUgcmVnZXgtYmFzZWQgb3V0cHV0IHByb2Nlc3NpbmcuXG4gKiBJdCBhbGxvd3MgZm9yIHBhdHRlcm4gbWF0Y2hpbmcgaW4gdGhlIG91dHB1dCBzdHJlYW0gYW5kIGNhbiB0cmlnZ2VyIHNwZWNpZmljIGFjdGlvbnNcbiAqIGJhc2VkIG9uIG1hdGNoZWQgcGF0dGVybnMuXG4gKlxuICogQHRlbXBsYXRlIFQgLSBUaGUgdHlwZSBvZiB0aGUgcmVzb2x2ZWQgdmFsdWUsIGRlZmF1bHRpbmcgdG8gc3RyaW5nLlxuICpcbiAqIEBwYXJhbSBjbWQgLSBUaGUgY29tbWFuZCBzdHJpbmcgdG8gYmUgZXhlY3V0ZWQuXG4gKiBAcGFyYW0gbG9jayAtIEEgUHJvbWlzZUV4ZWN1dG9yIHRvIGNvbnRyb2wgdGhlIGFzeW5jaHJvbm91cyBmbG93LlxuICogQHBhcmFtIHJlZ2V4cCAtIEEgc3RyaW5nIG9yIFJlZ0V4cCB0byBtYXRjaCBhZ2FpbnN0IHRoZSBvdXRwdXQuXG4gKiBAcGFyYW0gZmxhZ3MgLSBPcHRpb25hbCBmbGFncyBmb3IgdGhlIFJlZ0V4cCBjb25zdHJ1Y3RvciwgZGVmYXVsdHMgdG8gXCJnXCIuXG4gKlxuICogQGNsYXNzXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgUmVnZXhwT3V0cHV0V3JpdGVyIH0gZnJvbSAnQGRlY2FmLXRzL3V0aWxzJztcbiAqIGltcG9ydCB7IFByb21pc2VFeGVjdXRvciB9IGZyb20gJ0BkZWNhZi10cy91dGlscyc7XG4gKiBcbiAqIC8vIENyZWF0ZSBhIHByb21pc2UgZXhlY3V0b3JcbiAqIGNvbnN0IGV4ZWN1dG9yOiBQcm9taXNlRXhlY3V0b3I8c3RyaW5nLCBFcnJvcj4gPSB7XG4gKiAgIHJlc29sdmU6ICh2YWx1ZSkgPT4gY29uc29sZS5sb2coYFJlc29sdmVkOiAke3ZhbHVlfWApLFxuICogICByZWplY3Q6IChlcnJvcikgPT4gY29uc29sZS5lcnJvcihgUmVqZWN0ZWQ6ICR7ZXJyb3IubWVzc2FnZX1gKVxuICogfTtcbiAqIFxuICogLy8gQ3JlYXRlIGEgcmVnZXhwIG91dHB1dCB3cml0ZXIgdGhhdCBtYXRjaGVzIHZlcnNpb24gbnVtYmVyc1xuICogY29uc3Qgd3JpdGVyID0gbmV3IFJlZ2V4cE91dHB1dFdyaXRlcignbm9kZSAtLXZlcnNpb24nLCBleGVjdXRvciwgL3YoXFxkK1xcLlxcZCtcXC5cXGQrKS8pO1xuICogXG4gKiAvLyBVc2UgdGhlIHdyaXRlciB0byBoYW5kbGUgY29tbWFuZCBvdXRwdXRcbiAqIHdyaXRlci5kYXRhKCd2MTQuMTcuMCcpOyAgLy8gVGhpcyB3aWxsIGF1dG9tYXRpY2FsbHkgcmVzb2x2ZSB3aXRoIFwidjE0LjE3LjBcIlxuICogYGBgXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgUmVnZXhwT3V0cHV0V3JpdGVyXG4gKiAgIHBhcnRpY2lwYW50IFN0YW5kYXJkT3V0cHV0V3JpdGVyXG4gKiAgIHBhcnRpY2lwYW50IExvZ2dlclxuICogICBcbiAqICAgQ2xpZW50LT4+UmVnZXhwT3V0cHV0V3JpdGVyOiBuZXcgUmVnZXhwT3V0cHV0V3JpdGVyKGNtZCwgbG9jaywgcmVnZXhwLCBmbGFncylcbiAqICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IHN1cGVyKGNtZCwgbG9jaylcbiAqICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5Mb2dnZXI6IExvZ2dpbmcuZm9yKGNtZClcbiAqICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+UmVnZXhwT3V0cHV0V3JpdGVyOiBjb21waWxlIHJlZ2V4cFxuICogICBcbiAqICAgQ2xpZW50LT4+UmVnZXhwT3V0cHV0V3JpdGVyOiBkYXRhKGNodW5rKVxuICogICBSZWdleHBPdXRwdXRXcml0ZXItPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogc3VwZXIuZGF0YShjaHVuaylcbiAqICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5Mb2dnZXI6IGxvZ2dlci5pbmZvKGxvZylcbiAqICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+UmVnZXhwT3V0cHV0V3JpdGVyOiB0ZXN0QW5kUmVzb2x2ZShjaHVuaylcbiAqICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+UmVnZXhwT3V0cHV0V3JpdGVyOiB0ZXN0KGNodW5rKVxuICogICBhbHQgbWF0Y2ggZm91bmRcbiAqICAgICBSZWdleHBPdXRwdXRXcml0ZXItPj5SZWdleHBPdXRwdXRXcml0ZXI6IHJlc29sdmUobWF0Y2hbMF0pXG4gKiAgICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IHJlc29sdmUobWF0Y2hbMF0pXG4gKiAgIGVuZFxuICogICBcbiAqICAgQ2xpZW50LT4+UmVnZXhwT3V0cHV0V3JpdGVyOiBlcnJvcihjaHVuaylcbiAqICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IHN1cGVyLmVycm9yKGNodW5rKVxuICogICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PkxvZ2dlcjogbG9nZ2VyLmluZm8obG9nKVxuICogICBSZWdleHBPdXRwdXRXcml0ZXItPj5SZWdleHBPdXRwdXRXcml0ZXI6IHRlc3RBbmRSZWplY3QoY2h1bmspXG4gKiAgIFJlZ2V4cE91dHB1dFdyaXRlci0+PlJlZ2V4cE91dHB1dFdyaXRlcjogdGVzdChjaHVuaylcbiAqICAgYWx0IG1hdGNoIGZvdW5kXG4gKiAgICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+UmVnZXhwT3V0cHV0V3JpdGVyOiByZWplY3QobWF0Y2hbMF0pXG4gKiAgICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IHJlamVjdChtYXRjaFswXSlcbiAqICAgZW5kXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWdleHBPdXRwdXRXcml0ZXIgZXh0ZW5kcyBTdGFuZGFyZE91dHB1dFdyaXRlcjxzdHJpbmc+IHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgcmVndWxhciBleHByZXNzaW9uIHVzZWQgZm9yIG1hdGNoaW5nIG91dHB1dC5cbiAgICogQHN1bW1hcnkgVGhpcyByZWFkb25seSBwcm9wZXJ0eSBzdG9yZXMgdGhlIGNvbXBpbGVkIFJlZ0V4cCB1c2VkIGZvciBwYXR0ZXJuIG1hdGNoaW5nLlxuICAgKi9cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHJlZ2V4cDogUmVnRXhwO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGNtZDogc3RyaW5nLFxuICAgIGxvY2s6IFByb21pc2VFeGVjdXRvcjxzdHJpbmcsIEVycm9yPixcbiAgICByZWdleHA6IHN0cmluZyB8IFJlZ0V4cCxcbiAgICBmbGFncyA9IFwiZ1wiXG4gICkge1xuICAgIHN1cGVyKGNtZCwgbG9jayk7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMucmVnZXhwID1cbiAgICAgICAgdHlwZW9mIHJlZ2V4cCA9PT0gXCJzdHJpbmdcIiA/IG5ldyBSZWdFeHAocmVnZXhwLCBmbGFncykgOiByZWdleHA7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHJlZ3VsYXIgZXhwcmVzc2lvbjogJHtlfWApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGVzdHMgdGhlIGlucHV0IGRhdGEgYWdhaW5zdCB0aGUgc3RvcmVkIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAgICogQHN1bW1hcnkgRXhlY3V0ZXMgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbiBvbiB0aGUgaW5wdXQgZGF0YSBhbmQgcmV0dXJucyB0aGUgbWF0Y2ggcmVzdWx0LlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFRoZSBzdHJpbmcgdG8gdGVzdCBhZ2FpbnN0IHRoZSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAqIEByZXR1cm4gVGhlIHJlc3VsdCBvZiB0aGUgcmVndWxhciBleHByZXNzaW9uIGV4ZWN1dGlvbiwgb3IgdW5kZWZpbmVkIGlmIGFuIGVycm9yIG9jY3Vycy5cbiAgICovXG4gIHByaXZhdGUgdGVzdChkYXRhOiBzdHJpbmcpIHtcbiAgICB0aGlzLnJlZ2V4cC5sYXN0SW5kZXggPSAwO1xuICAgIGxldCBtYXRjaDtcbiAgICB0cnkge1xuICAgICAgbWF0Y2ggPSB0aGlzLnJlZ2V4cC5leGVjKGRhdGEpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHJldHVybiBjb25zb2xlLmRlYnVnKGBGYWlsZWQgdG8gcGFyc2UgY2h1bms6ICR7ZGF0YX1cXG5FcnJvcjogJHtlfSBgKTtcbiAgICB9XG4gICAgcmV0dXJuIG1hdGNoO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUZXN0cyB0aGUgZGF0YSBhbmQgcmVzb2x2ZXMgdGhlIHByb21pc2UgaWYgYSBtYXRjaCBpcyBmb3VuZC5cbiAgICogQHN1bW1hcnkgRXhlY3V0ZXMgdGhlIHRlc3QgbWV0aG9kIGFuZCByZXNvbHZlcyB0aGUgcHJvbWlzZSB3aXRoIHRoZSBmaXJzdCBtYXRjaCBncm91cCBpZiBzdWNjZXNzZnVsLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFRoZSBzdHJpbmcgdG8gdGVzdCBhZ2FpbnN0IHRoZSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAqL1xuICBwcm90ZWN0ZWQgdGVzdEFuZFJlc29sdmUoZGF0YTogc3RyaW5nKSB7XG4gICAgY29uc3QgbWF0Y2ggPSB0aGlzLnRlc3QoZGF0YSk7XG4gICAgaWYgKG1hdGNoKSB0aGlzLnJlc29sdmUobWF0Y2hbMF0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUZXN0cyB0aGUgZGF0YSBhbmQgcmVqZWN0cyB0aGUgcHJvbWlzZSBpZiBhIG1hdGNoIGlzIGZvdW5kLlxuICAgKiBAc3VtbWFyeSBFeGVjdXRlcyB0aGUgdGVzdCBtZXRob2QgYW5kIHJlamVjdHMgdGhlIHByb21pc2Ugd2l0aCB0aGUgZmlyc3QgbWF0Y2ggZ3JvdXAgaWYgc3VjY2Vzc2Z1bC5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBUaGUgc3RyaW5nIHRvIHRlc3QgYWdhaW5zdCB0aGUgcmVndWxhciBleHByZXNzaW9uLlxuICAgKi9cbiAgcHJvdGVjdGVkIHRlc3RBbmRSZWplY3QoZGF0YTogc3RyaW5nKSB7XG4gICAgY29uc3QgbWF0Y2ggPSB0aGlzLnRlc3QoZGF0YSk7XG4gICAgaWYgKG1hdGNoKSB0aGlzLnJlamVjdChtYXRjaFswXSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByb2Nlc3NlcyBpbmNvbWluZyBkYXRhIGNodW5rcy5cbiAgICogQHN1bW1hcnkgQ2FsbHMgdGhlIHBhcmVudCBjbGFzcyBkYXRhIG1ldGhvZCBhbmQgdGhlbiB0ZXN0cyB0aGUgZGF0YSBmb3IgYSBtYXRjaCB0byBwb3RlbnRpYWxseSByZXNvbHZlIHRoZSBwcm9taXNlLlxuICAgKlxuICAgKiBAcGFyYW0gY2h1bmsgLSBUaGUgZGF0YSBjaHVuayB0byBwcm9jZXNzLlxuICAgKi9cbiAgb3ZlcnJpZGUgZGF0YShjaHVuazogYW55KSB7XG4gICAgc3VwZXIuZGF0YShjaHVuayk7XG4gICAgdGhpcy50ZXN0QW5kUmVzb2x2ZShTdHJpbmcoY2h1bmspKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJvY2Vzc2VzIGluY29taW5nIGVycm9yIGNodW5rcy5cbiAgICogQHN1bW1hcnkgQ2FsbHMgdGhlIHBhcmVudCBjbGFzcyBlcnJvciBtZXRob2QgYW5kIHRoZW4gdGVzdHMgdGhlIGRhdGEgZm9yIGEgbWF0Y2ggdG8gcG90ZW50aWFsbHkgcmVqZWN0IHRoZSBwcm9taXNlLlxuICAgKlxuICAgKiBAcGFyYW0gY2h1bmsgLSBUaGUgZXJyb3IgY2h1bmsgdG8gcHJvY2Vzcy5cbiAgICovXG4gIG92ZXJyaWRlIGVycm9yKGNodW5rOiBhbnkpIHtcbiAgICBzdXBlci5lcnJvcihjaHVuayk7XG4gICAgdGhpcy50ZXN0QW5kUmVqZWN0KFN0cmluZyhjaHVuaykpO1xuICB9XG59XG4iLCJleHBvcnQgKiBmcm9tIFwiLi9jbGlcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2lucHV0XCI7XG5leHBvcnQgKiBmcm9tIFwiLi9vdXRwdXRcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3V0aWxzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi93cml0ZXJzXCI7XG5cbi8qKlxuICogQG1vZHVsZSB1dGlsc1xuICogQGRlc2NyaXB0aW9uIFV0aWxpdGllcyBhbmQgYnVpbGRpbmcgYmxvY2tzIGZvciBEZWNhZi1UUyBDTEkgYW5kIHNjcmlwdGluZy5cbiAqIEBzdW1tYXJ5IEFnZ3JlZ2F0ZXMgQ0xJIGNvbW1hbmQgaW5mcmFzdHJ1Y3R1cmUsIGlucHV0IGhlbHBlcnMsIG91dHB1dCB3cml0ZXJzLCBmaWxlc3lzdGVtL25ldHdvcmsgdXRpbGl0aWVzLFxuICogYW5kIHNoYXJlZCB0eXBlcy4gQ29uc3VtZXJzIHR5cGljYWxseSB1c2Uge0BsaW5rIENvbW1hbmR9LCB7QGxpbmsgVXNlcklucHV0fSwge0BsaW5rIFN0YW5kYXJkT3V0cHV0V3JpdGVyfSxcbiAqIHtAbGluayBwcmludEJhbm5lcn0sIGFuZCB1dGlsaXRpZXMgZnJvbSB7QGxpbmsgbW9kdWxlOnV0aWxzfHV0aWxzfS5cbiAqXG4gKiBUaGlzIGVudHJ5cG9pbnQgcmUtZXhwb3J0cyBzdWJwYWNrYWdlczpcbiAqIC0gQ0xJIGZyYW1ld29yayB1bmRlciBgLi9jbGlgIChjb21tYW5kIGJhc2UsIG9wdGlvbnMsIGJ1aWx0LWluIGNvbW1hbmRzKVxuICogLSBJbnB1dCBoZWxwZXJzIHVuZGVyIGAuL2lucHV0YCAocHJvbXB0aW5nIGFuZCBhcmcgcGFyc2luZylcbiAqIC0gT3V0cHV0IGhlbHBlcnMgdW5kZXIgYC4vb3V0cHV0YCAoYmFubmVyIGFuZCBzdHlsaW5nKVxuICogLSBHZW5lcmFsIHV0aWxpdGllcyB1bmRlciBgLi91dGlsc2AgKGZzLCBodHRwLCBleGVjLCB0eXBlcylcbiAqIC0gV3JpdGVycyB1bmRlciBgLi93cml0ZXJzYCAoc3Rkb3V0L3N0ZGVyciBwcm9jZXNzb3JzKVxuICpcbiAqIE5vdGU6IEluZGl2aWR1YWwgZXhwb3J0cyBhcmUgZG9jdW1lbnRlZCBpbiB0aGVpciBzb3VyY2UgZmlsZXMuXG4gKi9cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVwcmVzZW50cyB0aGUgY3VycmVudCB2ZXJzaW9uIG9mIHRoZSBtb2R1bGUuXG4gKiBAc3VtbWFyeSBTdG9yZXMgdGhlIHZlcnNpb24gZm9yIHRoZSBAZGVjYWYtdHMvdXRpbHMgcGFja2FnZS4gVGhlIGJ1aWxkIHJlcGxhY2VzXG4gKiB0aGUgcGxhY2Vob2xkZXIgd2l0aCB0aGUgYWN0dWFsIHZlcnNpb24gbnVtYmVyIGF0IHB1Ymxpc2ggdGltZS5cbiAqIEBjb25zdCBWRVJTSU9OXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gXCIjI1ZFUlNJT04jI1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXByZXNlbnRzIHRoZSBjdXJyZW50IHZlcnNpb24gb2YgdGhlIG1vZHVsZS5cbiAqIEBzdW1tYXJ5IFN0b3JlcyB0aGUgdmVyc2lvbiBmb3IgdGhlIEBkZWNhZi10cy91dGlscyBwYWNrYWdlLiBUaGUgYnVpbGQgcmVwbGFjZXNcbiAqIHRoZSBwbGFjZWhvbGRlciB3aXRoIHRoZSBhY3R1YWwgdmVyc2lvbiBudW1iZXIgYXQgcHVibGlzaCB0aW1lLlxuICogQGNvbnN0IFZFUlNJT05cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfTkFNRSA9IFwiIyNQQUNLQUdFIyNcIjtcbiJdLCJuYW1lcyI6WyJvcHRpb25zIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBZ0JBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBdURHO01BQ1UsU0FBUyxDQUFBO2FBQ0ksSUFBTSxDQUFBLE1BQUEsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBd0p4RCxJQUFBLFdBQUEsQ0FBWSxJQUFvQixFQUFBO0FBdkpoQzs7O0FBR0c7UUFDSCxJQUFJLENBQUEsSUFBQSxHQUEyRCxNQUFNO0FBb0puRSxRQUFBLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSTs7QUFHbEI7Ozs7OztBQU1HO0FBQ0gsSUFBQSxPQUFPLENBQUMsSUFBNEQsRUFBQTtRQUNsRSxTQUFTLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFvQixpQkFBQSxFQUFBLElBQUksQ0FBRSxDQUFBLENBQUM7QUFDcEQsUUFBQSxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUk7QUFDaEIsUUFBQSxPQUFPLElBQUk7O0FBR2I7Ozs7OztBQU1HO0FBQ0gsSUFB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
1
+ import e from"prompts";import{parseArgs as t}from"util";import{Logging as o,patchString as a,LoggedClass as n,LoggedEnvironment as s}from"@decaf-ts/logging";import r from"fs";import i from"path";import{spawn as l}from"child_process";import{style as c}from"styled-string-builder";import g from"https";import{rollup as d}from"rollup";import f from"@rollup/plugin-typescript";import h from"@rollup/plugin-commonjs";import{nodeResolve as u}from"@rollup/plugin-node-resolve";import m from"@rollup/plugin-json";import{builtinModules as p}from"module";import*as S from"typescript";import{ModuleKind as w}from"typescript";class y{static{this.logger=o.for(y)}constructor(e){this.type="text",this.name=e}setType(e){return y.logger.verbose(`Setting type to: ${e}`),this.type=e,this}setMessage(e){return y.logger.verbose(`Setting message to: ${e}`),this.message=e,this}setInitial(e){return y.logger.verbose(`Setting initial value to: ${e}`),this.initial=e,this}setStyle(e){return y.logger.verbose(`Setting style to: ${e}`),this.style=e,this}setFormat(e){return y.logger.verbose("Setting format function"),this.format=e,this}setValidate(e){return y.logger.verbose("Setting validate function"),this.validate=e,this}setOnState(e){return y.logger.verbose("Setting onState callback"),this.onState=e,this}setMin(e){return y.logger.verbose(`Setting min value to: ${e}`),this.min=e,this}setMax(e){return y.logger.verbose(`Setting max value to: ${e}`),this.max=e,this}setFloat(e){return y.logger.verbose(`Setting float to: ${e}`),this.float=e,this}setRound(e){return y.logger.verbose(`Setting round to: ${e}`),this.round=e,this}setInstructions(e){return y.logger.verbose(`Setting instructions to: ${e}`),this.instructions=e,this}setIncrement(e){return y.logger.verbose(`Setting increment to: ${e}`),this.increment=e,this}setSeparator(e){return y.logger.verbose(`Setting separator to: ${e}`),this.separator=e,this}setActive(e){return y.logger.verbose(`Setting active style to: ${e}`),this.active=e,this}setInactive(e){return y.logger.verbose(`Setting inactive style to: ${e}`),this.inactive=e,this}setChoices(e){return y.logger.verbose(`Setting choices: ${JSON.stringify(e)}`),this.choices=e,this}setHint(e){return y.logger.verbose(`Setting hint to: ${e}`),this.hint=e,this}setWarn(e){return y.logger.verbose(`Setting warn to: ${e}`),this.warn=e,this}setSuggest(e){return y.logger.verbose("Setting suggest function"),this.suggest=e,this}setLimit(e){return y.logger.verbose(`Setting limit to: ${e}`),this.limit=e,this}setMask(e){return y.logger.verbose(`Setting mask to: ${e}`),this.mask=e,this}setStdout(e){return y.logger.verbose("Setting stdout stream"),this.stdout=e,this}setStdin(e){return this.stdin=e,this}async ask(){return(await y.ask(this))[this.name]}static async ask(t){const o=y.logger.for(this.ask);let a;Array.isArray(t)||(t=[t]);try{o.verbose(`Asking questions: ${t.map(e=>e.name).join(", ")}`),a=await e(t),o.verbose(`Received answers: ${JSON.stringify(a,null,2)}`)}catch(e){throw new Error(`Error while getting input: ${e}`)}return a}static async askNumber(e,t,o,a,n){y.logger.for(this.askNumber).verbose(`Asking number input: undefined, question: ${t}, min: ${o}, max: ${a}, initial: ${n}`);const s=new y(e).setMessage(t).setType("number");return"number"==typeof o&&s.setMin(o),"number"==typeof a&&s.setMax(a),"number"==typeof n&&s.setInitial(n),(await this.ask(s))[e]}static async askText(e,t,o=void 0,a){y.logger.for(this.askText).verbose(`Asking text input: undefined, question: ${t}, mask: ${o}, initial: ${a}`);const n=new y(e).setMessage(t);return o&&n.setMask(o),"string"==typeof a&&n.setInitial(a),(await this.ask(n))[e]}static async askConfirmation(e,t,o){y.logger.for(this.askConfirmation).verbose(`Asking confirmation input: undefined, question: ${t}, initial: ${o}`);const a=new y(e).setMessage(t).setType("confirm");return void 0!==o&&a.setInitial(o),(await this.ask(a))[e]}static async insist(e,t,o,a=1){const n=y.logger.for(this.insist);let s;n.verbose(`Insisting on input: ${e.name}, test: ${t.toString()}, defaultConfirmation: ${o}, limit: ${a}`);let r,i=0;try{do{s=(await y.ask(e))[e.name],t(s)?(r=await y.askConfirmation(`${e.name}-confirm`,`Is the ${e.type} correct?`,o),r||(s=void 0)):s=void 0}while(void 0===s&&a>1&&i++<a)}catch(e){throw n.error(`Error while insisting: ${e}`),e}return void 0===s&&n.info("no selection..."),s}static async insistForText(e,t,o,a=void 0,n,s=!1,r=-1){y.logger.for(this.insistForText).verbose(`Insisting for text input: undefined, question: ${t}, test: ${o.toString()}, mask: ${a}, initial: ${n}, defaultConfirmation: ${s}, limit: ${r}`);const i=new y(e).setMessage(t);return a&&i.setMask(a),"string"==typeof n&&i.setInitial(n),await this.insist(i,o,s,r)}static async insistForNumber(e,t,o,a,n,s,r=!1,i=-1){y.logger.for(this.insistForNumber).verbose(`Insisting for number input: undefined, question: ${t}, test: ${o.toString()}, min: ${a}, max: ${n}, initial: ${s}, defaultConfirmation: ${r}, limit: ${i}`);const l=new y(e).setMessage(t).setType("number");return"number"==typeof a&&l.setMin(a),"number"==typeof n&&l.setMax(n),"number"==typeof s&&l.setInitial(s),await this.insist(l,o,r,i)}static parseArgs(e){const o=y.logger.for(this.parseArgs),a={args:process.argv.slice(2),options:e};o.debug(`Parsing arguments: ${JSON.stringify(a,null,2)}`);try{return t(a)}catch(t){throw o.debug(`Error while parsing arguments:\n${JSON.stringify(a,null,2)}\n | options\n${JSON.stringify(e,null,2)}\n | ${t}`),new Error(`Error while parsing arguments: ${t}`)}}}const T={verbose:{type:"boolean",short:"V",default:void 0},version:{type:"boolean",short:"v",default:void 0},help:{type:"boolean",short:"h",default:!1},logLevel:{type:"string",default:"info"},logStyle:{type:"boolean",default:!0},timestamp:{type:"boolean",default:!0},banner:{type:"boolean",default:!0}},b=Object.keys(T).reduce((e,t)=>(e[t]=T[t].default,e),{}),C="utf-8",v=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z])))/g;var D;!function(e){e.PATCH="patch",e.MINOR="minor",e.MAJOR="major"}(D||(D={}));const k="-no-ci",$="postinstall";var E;!function(e){e.GIT=".token",e.NPM=".npmtoken",e.DOCKER=".dockertoken",e.CONFLUENCE=".confluence-token"}(E||(E={}));const I="Aborted";class x{constructor(e,t,...a){this.cmd=e,this.lock=t,this.logger=o.for(this.cmd)}log(e,t){t=Buffer.isBuffer(t)?t.toString(C):t;const o="stderr"===e?c(t).red.text:t;this.logger.info(o)}data(e){this.log("stdout",String(e))}error(e){this.log("stderr",String(e))}errors(e){this.log("stderr",`Error executing command exited : ${e}`)}exit(e,t){this.log("stdout",`command exited code : ${0===e?c(e.toString()).green.text:c(null===e?"null":e.toString()).red.text}`),0===e?this.resolve(t.map(e=>e.trim()).join("\n")):this.reject(new Error(t.length?t.join("\n"):e.toString()))}parseCommand(e){return e="string"==typeof e?e.split(" "):e,this.cmd=e.join(" "),[e[0],e.slice(1)]}resolve(e){this.log("stdout",`${this.cmd} executed successfully: ${c(e?"ran to completion":e).green}`),this.lock.resolve(e)}reject(e){e instanceof Error||(e=new Error("number"==typeof e?`Exit code ${e}`:e)),this.log("stderr",`${this.cmd} failed to execute: ${c(e.message).red}`),this.lock.reject(e)}}function F(e){let t=Promise.resolve();return(...o)=>{const a=t.then(()=>e(...o));return t=a.catch(()=>{}),a}}function j(e,...t){let o,a;if(e instanceof AbortSignal?(a=new AbortController,o=[e,...t]):(a=e,o=t),a.signal.aborted)return a;const n=()=>a.abort();for(const e of o){if(e.aborted){a.abort();break}e.addEventListener("abort",n,{once:!0,signal:a.signal})}return a}function N(e,t,o,a,n){function s(t,a){const[s,r]=e.parseCommand(t);n.info(`Running command: ${s}`),n.debug(`with args: ${r.join(" ")}`);const i=l(s,r,{...o,cwd:o.cwd||process.cwd(),env:Object.assign({},process.env,o.env,{PATH:process.env.PATH}),shell:o.shell||!1,signal:a.signal});return n.verbose(`pid : ${i.pid}`),i}const r=t.match(/[<>$#]/g);if(r)throw new Error(`Invalid command: ${t}. contains invalid characters: ${r}`);if(t.includes(" | ")){const e=t.split(" | "),o=[],n=new Array(e.length);n[0]=a;for(let t=0;t<e.length;t++)0!==t&&(n[t]=j(n[t-1].signal)),o.push(s(e[t],n[t])),0!==t&&o[t-1].stdout.pipe(o[t].stdin);return o[e.length-1]}return s(t,a)}function A(e,t={},a=x,...n){const s=o.for(A),r=new AbortController,i={abort:r,command:e,logs:[],errs:[]},l=new Promise((o,l)=>{let c;try{c=new a(e,{resolve:o,reject:l},...n),i.cmd=N(c,e,t,r,s)}catch(t){return l(new Error(`Error running command ${e}: ${t}`))}i.cmd.stdout.setEncoding("utf8"),i.cmd.stdout.on("data",e=>{e=e.toString(),i.logs.push(e),c.data(e)}),i.cmd.stderr.on("data",e=>{e=e.toString(),i.errs.push(e),c.error(e)}),i.cmd.once("error",e=>{c.exit(e.message,i.errs)}),i.cmd.once("exit",(e=0)=>{r.signal.aborted&&null===e&&(e=I),c.exit(e,0===e?i.logs:i.errs)})});return Object.assign(i,{promise:l,pipe:async t=>{const o=s.for("pipe");try{o.verbose(`Executing pipe function ${e}...`);const a=await l;return o.verbose(`Piping output to ${t.name}: ${a}`),t(a)}catch(e){throw o.error(`Error piping command output: ${e}`),e}}}),i}const B=o.for("fs");function O(e,t){const o=B.for(O);if(!r.existsSync(e))throw new Error(`File not found at path "${e}".`);let n=P(e);try{o.verbose(`Patching file "${e}"...`),o.debug(`with value: ${JSON.stringify(t)}`),n=a(n,t)}catch(e){throw new Error(`Error patching file: ${e}`)}U(e,n)}function P(e){const t=B.for(P);try{return t.verbose(`Reading file "${e}"...`),r.readFileSync(e,"utf8")}catch(o){throw t.verbose(`Error reading file "${e}": ${o}`),new Error(`Error reading file "${e}": ${o}`)}}function U(e,t){const o=B.for(U);try{o.verbose(`Writing file "${e} with ${t.length} bytes...`),r.writeFileSync(e,t,"utf8")}catch(t){throw o.verbose(`Error writing file "${e}": ${t}`),new Error(`Error writing file "${e}": ${t}`)}}function M(e,t){const o=B.for(M),a=[];try{o.verbose(`Retrieving all files from "${e}"...`);return r.readdirSync(e).forEach(t=>{const o=i.join(e,t),n=r.statSync(o);n.isFile()?a.push(o):n.isDirectory()&&a.push(...M(o))}),t?a.filter(t):a}catch(t){throw o.verbose(`Error retrieving files from "${e}": ${t}`),new Error(`Error retrieving files from "${e}": ${t}`)}}async function L(e,t){const o=B.for(L);let a,n;try{a=r.statSync(e)}catch(t){throw o.verbose(`Source path "${e}" does not exist: ${t}`),new Error(`Source path "${e}" does not exist: ${t}`)}try{n=r.statSync(t)}catch(e){}if(n)throw o.verbose(`Destination path "${t}" already exists`),new Error(`Destination path "${t}" already exists`);try{o.verbose(`Renaming ${a.isFile()?"file":"directory"} "${e}" to "${t}...`),r.renameSync(e,t),o.verbose(`Successfully renamed to "${t}"`)}catch(n){throw o.verbose(`Error renaming ${a.isFile()?"file":"directory"} "${e}" to "${t}": ${n}`),new Error(`Error renaming ${a.isFile()?"file":"directory"} "${e}" to "${t}": ${n}`)}}function J(e,t){const o=B.for(J);let a,n;try{a=r.statSync(e)}catch(t){throw o.verbose(`Source path "${e}" does not exist: ${t}`),new Error(`Source path "${e}" does not exist: ${t}`)}try{n=r.statSync(t)}catch(e){a.isDirectory()&&(o.verbose(`Dest path "${t}" does not exist. creating`),r.mkdirSync(t,{recursive:!0}))}try{o.verbose(`Copying ${a.isFile()?"file":"directory"} "${e}" to "${t}...`),r.cpSync(e,t,{recursive:!0})}catch(n){throw o.verbose(`Error copying ${a.isFile()?"file":"directory"} "${e}" to "${t}: ${n}`),new Error(`Error copying ${a.isFile()?"file":"directory"} "${e}" to "${t}: ${n}`)}}function R(e){const t=B.for(R);try{const o=r.statSync(e);o.isFile()?(t.verbose(`Deleting file "${e}...`),r.rmSync(e,{recursive:!0,force:!0})):o.isDirectory()&&r.rmSync(e,{recursive:!0,force:!0})}catch(o){throw t.verbose(`Error Deleting "${e}": ${o}`),new Error(`Error Deleting "${e}": ${o}`)}}function G(e=process.cwd(),t){let o;try{o=JSON.parse(P(i.join(e,"package.json")))}catch(e){throw new Error(`Failed to retrieve package information" ${e}`)}if(t){if(!(t in o))throw new Error(`Property "${t}" not found in package.json`);return o[t]}return o}function W(e,t,o=process.cwd()){const a=G(o);a[e]=t,U(i.join(o,"package.json"),JSON.stringify(a,null,2))}function V(e=process.cwd()){return G(e,"version")}async function X(e=process.cwd()){let t;try{t=JSON.parse(await A("npm ls --json",{cwd:e}).promise)}catch(e){throw new Error(`Failed to retrieve dependencies: ${e}`)}const o=(e,t)=>({name:e[0],version:e[1].version});return{prod:Object.entries(t.dependencies||{}).map(o),dev:Object.entries(t.devDependencies||{}).map(o),peer:Object.entries(t.peerDependencies||{}).map(o)}}async function H(){const e=B.for(H);e.info("checking for updates..."),await A("npx npm-check-updates -u").promise,e.info("updating..."),await A("npx npm run do-install").promise}async function _(e,t){if(!t){const e=await X();t={prod:e.prod?.map(e=>e.name)||[],dev:e.dev?.map(e=>e.name)||[],peer:e.peer?.map(e=>e.name)||[]}}const{prod:o,dev:a,peer:n}=t,s=Array.from(new Set([...o||[],...a||[],...n||[]])),r=(e="string"==typeof e?[e]:e).filter(e=>!s.includes(e));return r.length&&await z({dev:r}),t.dev=t.dev||[],t.dev.push(...r),t}async function q(){const e=B.for(q),t=await A("git config user.name").promise,o=await A("git config user.email").promise;e.verbose(`cached git id: ${t}/${o}. changing to automation`),await A('git config user.email "automation@decaf.ts"').promise,await A('git config user.name "decaf"').promise,e.info("Pushing changes to git..."),await A("git add .").promise,await A('git commit -m "refs #1 - after repo setup"').promise,await A("git push").promise,await A(`git config user.email "${o}"`).promise,await A(`git config user.name "${t}"`).promise,e.verbose(`reverted to git id: ${t}/${o}`)}async function z(e){const t=B.for(z),o=e.prod||[],a=e.dev||[],n=e.peer||[];o.length&&(t.info(`Installing dependencies ${o.join(", ")}...`),await A(`npm install ${o.join(" ")}`,{cwd:process.cwd()}).promise),a.length&&(t.info(`Installing devDependencies ${a.join(", ")}...`),await A(`npm install --save-dev ${a.join(" ")}`,{cwd:process.cwd()}).promise),n.length&&(t.info(`Installing peerDependencies ${n.join(", ")}...`),await A(`npm install --save-peer ${n.join(" ")}`,{cwd:process.cwd()}).promise)}async function Y(e){return e.then(e=>e.default||e)}const K=[{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That's Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That’s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That’s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That’s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That’s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That’s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That’s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That’s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That’s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That’s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"Decaf-TS: Where smart contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No CRUD, no problem — Decaf your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS: Your frontend already understands your smart contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye CRUD, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data — because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From smart contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No CRUD. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently — and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem — Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data — because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently — and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem — Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data — because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently — and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem — Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data — because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently — and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem — Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data — because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently — and delightfully.",Tags:"DID, Self-Sovereign, Playful"}],Z=["","","","","","","","",""];function Q(e){const t=ee(),o="# ░▒▓███████▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓██████▓▒░ ░▒▓████████▓▒░ ░▒▓████████▓▒░ ░▒▓███████▓▒░ \n# ( ( ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# ) ) ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# [=======] ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓██████▓▒░ \n# `-----´ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# ░▒▓███████▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓███████▓▒░ \n#".split("\n"),a=o.reduce((e,t)=>Math.max(e,t.length),0);o.push(`# ${t.padStart(a-3)}`),o.forEach((t,o)=>{(e?e.info.bind(e):console.log.bind(console))(c(t||"").raw(Z[o]).text)})}function ee(e){try{return e=void 0===e?Math.floor(Math.random()*K.length):e,K[e].Slogan}catch(e){throw new Error(`Failed to retrieve slogans: ${e}`)}}class te extends n{constructor(e,t={},a=[]){super(),this.name=e,this.inputs=t,this.requirements=a,te.log||Object.defineProperty(te,"log",{writable:!1,value:o.for(te.name)}),this.inputs=Object.assign({},T,t)}async checkRequirements(){const{prod:e,dev:t,peer:o}=await X(),a=[],n=Array.from(new Set([...e,...t,...o]).values()).map(e=>e.name);for(const e of this.requirements)n.includes(e)||a.push(e);a.length}help(e){return this.log.info("This is help. I'm no use because I should have been overridden.")}async execute(){const e=y.parseArgs(this.inputs),t=s.accumulate(b).accumulate(e.values),{version:o,help:a,banner:n}=t;if(o)return V();if(a)return this.help(e);let r;n&&Q(this.log.for(Q,{timestamp:!1,style:!1,context:!1,logLevel:!1}));try{r=await this.run(t)}catch(e){throw this.log.error(`Error while running provided cli function: ${e}`),e}return r}}class oe{static{this.log=o.for(oe)}static async downloadFile(e){return new Promise((t,o)=>{!function e(a){a=encodeURI(a),g.get(a,n=>{if(301===n.statusCode||307===n.statusCode)return e(n.headers.location);if(200!==n.statusCode)return oe.log.error(`Failed to fetch ${a} (status: ${n.statusCode})`),o(new Error(`Failed to fetch ${a}`));let s="";n.on("data",e=>{s+=e}),n.on("error",e=>{o(e)}),n.on("end",()=>{t(s)})})}(e)})}}function ae(e){return e?Array.isArray(e)?e.map(e=>`${e}`.trim()).filter(Boolean):`${e}`.split(",").map(e=>e.trim()).filter(Boolean):[]}function ne(e){return e.replace(/^@/,"").split(/[/\-_.]+/).filter(Boolean).map((e,t)=>0===t?e.replace(/[^a-zA-Z0-9]/g,""):`${e.charAt(0).toUpperCase()}${e.slice(1)}`).join("")}function se(){let e;try{e=G(process.cwd())}catch{e=void 0}try{if(!(e&&(Object.keys(e.dependencies||{}).length>0||Object.keys(e.devDependencies||{}).length>0||Object.keys(e.peerDependencies||{}).length>0))){const t=i.resolve(__dirname,"../../..");try{e=G(t)}catch{}}}catch{}const t=Object.keys(e&&e.dependencies||{}),o=Object.keys(e&&e.peerDependencies||{}),a=Object.keys(e&&e.devDependencies||{});return Array.from(new Set([...t,...o,...a]))}var re,ie;!function(e){e.CJS="commonjs",e.ESM="es2022"}(re||(re={})),function(e){e.BUILD="build",e.BUNDLE="bundle",e.ALL="all"}(ie||(ie={}));const le={prod:{type:"boolean",default:!1},dev:{type:"boolean",default:!1},buildMode:{type:"string",default:ie.ALL},includes:{type:"string",default:""},externals:{type:"string",default:""},docs:{type:"boolean",default:!1},commands:{type:"boolean",default:!1},banner:{type:"boolean",default:!1}},ce=(e=".cjs")=>{const t=ge.log.for(ce),o=new Map;return a=>n=>{const s=i.dirname(n.fileName);function l(a){const n=JSON.stringify([s,a]),l=o.get(n);if(null!=l)return l;let c,g=a;try{g=i.resolve(s,g+".ts")}catch(e){throw new Error(`Failed to resolve path ${a}: ${e}`)}try{c=r.statSync(g)}catch(e){try{t.verbose(`Testing existence of path ${g} as a folder defaulting to index file`),c=r.statSync(g.replace(/\.ts$/gm,""))}catch(t){throw new Error(`Failed to resolve path ${a}: ${e}, ${t}`)}}if(c.isDirectory()&&(g=g.replace(/\.ts$/gm,"/index.ts")),i.isAbsolute(g)){const t=(/\.tsx?$/.exec(i.basename(g))||[])[0]||void 0;g="./"+i.relative(s,i.resolve(i.dirname(g),i.basename(g,t)+e))}return o.set(n,g),g}return S.visitNode(n,function e(t){if(function(e){return!(!S.isImportDeclaration(e)&&!S.isExportDeclaration(e))&&(void 0!==e.moduleSpecifier&&(!!S.isStringLiteral(e.moduleSpecifier)&&(!(!e.moduleSpecifier.text.startsWith("./")&&!e.moduleSpecifier.text.startsWith("../"))&&""===i.extname(e.moduleSpecifier.text))))}(t)){if(S.isImportDeclaration(t)){const e=l(t.moduleSpecifier.text),o=a.factory.createStringLiteral(e);return a.factory.updateImportDeclaration(t,t.modifiers,t.importClause,o,void 0)}if(S.isExportDeclaration(t)){const e=l(t.moduleSpecifier.text),o=a.factory.createStringLiteral(e);return a.factory.updateExportDeclaration(t,t.modifiers,t.isTypeOnly,t.exportClause,o,void 0)}}return S.visitEachChild(t,e,a)})}};class ge extends te{constructor(){super("BuildScripts",Object.assign({},T,le)),this.replacements={};const e=G(),{name:t,version:o}=e;this.pkgName=t.includes("@")?t.split("/")[1]:t,this.pkgVersion=o,this.replacements["0.3.13"]=this.pkgVersion,this.replacements["@decaf-ts/utils"]=t}patchFiles(e){const t=this.log.for(this.patchFiles),{name:o,version:a}=G();t.info(`Patching ${o} ${a} module in ${e}...`);r.statSync(e).isDirectory()&&r.readdirSync(e,{withFileTypes:!0,recursive:!0}).filter(e=>e.isFile()).forEach(e=>O(i.join(e.parentPath,e.name),this.replacements)),t.verbose(`Module ${o} ${a} patched in ${e}...`)}reportDiagnostics(e){e.forEach(e=>{let t="Error";if(e.file&&e.start){const{line:o,character:a}=e.file.getLineAndCharacterOfPosition(e.start);t+=` ${e.file.fileName} (${o+1},${a+1})`}t+=": "+S.flattenDiagnosticMessageText(e.messageText,"\n"),console.log(t)})}readConfigFile(e){const t=r.readFileSync(e).toString(),o=S.parseConfigFileTextToJson(e,t),a=o.config;if(!a)throw this.reportDiagnostics([o.error]),new Error("Failed to parse tsconfig.json");const n=S.parseJsonConfigFileContent(a,S.sys,i.dirname(e));if(n.errors.length>0)throw this.reportDiagnostics(n.errors),new Error("Failed to parse tsconfig.json");return n}async buildTs(e,t,o=!1){const a=this.log.for(this.buildTs);let n;a.info(`Building ${this.pkgName} ${this.pkgVersion} module (${t}) in ${e?"dev":"prod"} mode...`);try{n=this.readConfigFile("./tsconfig.json")}catch(e){throw new Error(`Failed to parse tsconfig.json: ${e}`)}o?(n.options.module=w.AMD,n.options.outDir="dist",n.options.isolatedModules=!1,n.options.outFile=this.pkgName):(n.options.outDir="lib"+(t===re.ESM?"/esm":""),n.options.module=t===re.ESM?w.ES2022:w.CommonJS),e?(n.options.inlineSourceMap=!0,n.options.sourceMap=!1):n.options.sourceMap=!1;const s=S.createProgram(n.fileNames,n.options),r={};t===re.CJS?r.before=[ce(".cjs")]:t===re.ESM&&(r.before=[ce(".js")]);const i=s.emit(void 0,void 0,void 0,void 0,r);if(S.getPreEmitDiagnostics(s).concat(i.diagnostics).forEach(e=>{if(e.file){const{line:t,character:o}=e.file.getLineAndCharacterOfPosition(e.start),n=S.flattenDiagnosticMessageText(e.messageText,"\n");a.info(`${e.file.fileName} (${t+1},${o+1}): ${n}`)}else a.info(S.flattenDiagnosticMessageText(e.messageText,"\n"))}),i.emitSkipped)throw new Error("Build failed")}async build(e,t,o=!1){const a=this.log.for(this.build);if(await this.buildTs(e,t,o),a.verbose(`Module ${this.pkgName} ${this.pkgVersion} (${t}) built in ${e?"dev":"prod"} mode...`),t===re.CJS&&!o){const e=M("lib",e=>e.endsWith(".js")&&!e.includes("/esm/"));for(const t of e){a.verbose(`Patching ${t}'s cjs imports...`);const e=t.replace(".js",".cjs");await L(t,e)}}}copyAssets(e){const t=this.log.for(this.copyAssets);let o=!1;try{o=r.statSync("./src/assets").isDirectory()}catch(e){return t.verbose("No assets found in ./src/assets to copy")}o&&J("./src/assets",`./${e===re.CJS?"lib":"dist"}/assets`)}async bundle(e,t,o,a="src/index.ts",n=this.pkgName,s,r=["prompts","styled-string-builder","typed-object-accumulator","@decaf-ts/logging"]){const i=e===re.ESM,l=this.pkgName,c=Array.from(new Set([...ae(r)]));let g=ae(s);0===g.length&&(g=se());const S=Array.from(new Set([...function(){try{return Array.isArray(p)?p:[]}catch{return["fs","path","process","child_process","util","https","http","os","stream","crypto","zlib","net","tls","url","querystring","assert","events","tty","dns","querystring"]}}(),...g])),w=[f({compilerOptions:{module:"esnext",declaration:!1,outDir:o?"bin":"dist"},include:["src/**/*.ts"],exclude:["node_modules","**/*.spec.ts"],tsconfig:"./tsconfig.json"}),m()];if(!t)try{const C=await import("rollup-plugin-terser"),v=C&&C.terser||C.default||C;w.push(v())}catch{}o&&w.push(h({include:[],exclude:g}),u({resolveOnly:c}));const y={input:a,plugins:w,external:S},T={};S.forEach(e=>{T[e]=ne(e)});const b=[{file:`${o?"bin/":"dist/"}${n||".bundle."+(t?"":"min")}${i?".esm":""}.cjs`,format:o?"cjs":i?"esm":"umd",name:l,esModule:i,sourcemap:!!t&&"inline",globals:T,exports:"auto"}];try{const D=await d(y);async function k(e){for(const t of b)await e.write(t)}console.log(D.watchFiles),await k(D)}catch($){throw new Error(`Failed to bundle: ${$}`)}}async buildByEnv(e,t=ie.ALL,o,a){try{R("lib")}catch(e){}try{R("dist")}catch(e){}r.mkdirSync("lib"),r.mkdirSync("dist"),[ie.ALL,ie.BUILD].includes(t)&&(await this.build(e,re.ESM),await this.build(e,re.CJS),this.patchFiles("lib")),[ie.ALL,ie.BUNDLE].includes(t)&&(await this.bundle(re.ESM,e,!1,"src/index.ts",this.pkgName,a,o),await this.bundle(re.CJS,e,!1,"src/index.ts",this.pkgName,a,o),this.patchFiles("dist")),this.copyAssets(re.CJS),this.copyAssets(re.ESM)}async buildDev(e=ie.ALL,t,o){return this.buildByEnv(!0,e,t,o)}async buildProd(e=ie.ALL,t,o){return this.buildByEnv(!1,e,t,o)}async buildDocs(){await A("npm install better-docs taffydb").promise,await A("npx markdown-include ./workdocs/readme-md.json").promise,await A("npx jsdoc -c ./workdocs/jsdocs.json -t ./node_modules/better-docs").promise,await A("npm remove better-docs taffydb").promise,[{src:"workdocs/assets",dest:"./docs/workdocs/assets"},{src:"workdocs/reports/coverage",dest:"./docs/workdocs/reports/coverage"},{src:"workdocs/reports/html",dest:"./docs/workdocs/reports/html"},{src:"workdocs/resources",dest:"./docs/workdocs/resources"},{src:"LICENSE.md",dest:"./docs/LICENSE.md"}].forEach(e=>{const{src:t,dest:o}=e;J(t,o)})}async run(e){const{dev:t,prod:o,docs:a,buildMode:n,includes:s,externals:r}=e;return t?await this.buildDev(n,s,r):o?await this.buildProd(n,s,r):a?await this.buildDocs():void 0}}const de={ci:{type:"boolean",default:!0},message:{type:"string",short:"m"},tag:{type:"string",short:"t",default:void 0}};class fe extends te{constructor(){super("ReleaseScript",de)}async prepareVersion(e){const t=this.log.for(this.prepareVersion);return(e=this.testVersion(e||""))||(t.verbose("No release message provided. Prompting for one:"),t.info("Listing latest git tags:"),await A("git tag --sort=-taggerdate | head -n 5").promise,await y.insistForText("tag","Enter the new tag number (accepts v*.*.*[-...])",e=>!!e.toString().match(/^v[0-9]+\.[0-9]+.[0-9]+(-[0-9a-zA-Z-]+)?$/)))}testVersion(e){const t=this.log.for(this.testVersion);switch(e=e.trim().toLowerCase()){case D.PATCH:case D.MINOR:case D.MAJOR:return t.verbose(`Using provided SemVer update: ${e}`,1),e;default:return t.verbose(`Testing provided version for SemVer compatibility: ${e}`,1),new RegExp(v).test(e)?(t.verbose(`version approved: ${e}`,1),e):void t.debug(`Invalid version number: ${e}`)}}async prepareMessage(e){const t=this.log.for(this.prepareMessage);return e||(t.verbose("No release message provided. Prompting for one"),await y.insistForText("message","What should be the release message/ticket?",e=>!!e&&e.toString().length>5))}async run(e){let t;const{ci:o}=e;let{tag:a,message:n}=e;a=await this.prepareVersion(a),n=await this.prepareMessage(n),t=await A(`npm run prepare-release -- ${a} ${n}`,{cwd:process.cwd()}).promise,t=await A("git status --porcelain").promise,await t,t.logs.length&&await y.askConfirmation("git-changes","Do you want to push the changes to the remote repository?",!0)&&(await A("git add .").promise,await A(`git commit -m "${a} - ${n} - after release preparation${o?"":k}"`).promise),await A(`npm version "${a}" -m "${n}${o?"":k}"`).promise,await A("git push --follow-tags").promise,o||await A("NPM_TOKEN=$(cat .npmtoken) npm publish --access public").promise}}const he="https://raw.githubusercontent.com/decaf-ts/ts-workspace/master",ue={templates:[".github/ISSUE_TEMPLATE/bug_report.md",".github/ISSUE_TEMPLATE/feature_request.md",".github/FUNDING.yml"],workflows:[".github/workflows/codeql-analysis.yml",".github/workflows/jest-coverage.yaml",".github/workflows/nodejs-build-prod.yaml",".github/workflows/pages.yaml",".github/workflows/publish-on-release.yaml",".github/workflows/release-on-tag.yaml",".github/workflows/snyk-analysis.yaml"],ide:[".idea/runConfigurations/All Tests.run.xml",".idea/runConfigurations/build.run.xml",".idea/runConfigurations/build_prod.run.xml",".idea/runConfigurations/coverage.run.xml",".idea/runConfigurations/docs.run.xml",".idea/runConfigurations/drawings.run.xml",".idea/runConfigurations/flash-forward.run.xml",".idea/runConfigurations/Integration_Tests.run.xml",".idea/runConfigurations/Bundling_Tests.run.xml",".idea/runConfigurations/lint-fix.run.xml",".idea/runConfigurations/release.run.xml",".idea/runConfigurations/test_circular.run.xml",".idea/runConfigurations/uml.run.xml",".idea/runConfigurations/Unit Tests.run.xml",".idea/runConfigurations/update-scripts.run.xml"],docs:["workdocs/tutorials/Contributing.md","workdocs/tutorials/Documentation.md","workdocs/tutorials/For Developers.md","workdocs/2-Badges.md","workdocs/jsdocs.json","workdocs/readme-md.json"],styles:[".prettierrc","eslint.config.js"],scripts:["bin/update-scripts.cjs","bin/tag-release.cjs","bin/build-scripts.cjs"],tests:["jest.config.ts","workdocs/reports/jest.coverage.config.ts"],typescript:["tsconfig.json"],docker:["Dockerfile"],automation:["workdocs/confluence/Continuous Integration-Deployment/GitHub.md","workdocs/confluence/Continuous Integration-Deployment/Jira.md","workdocs/confluence/Continuous Integration-Deployment/Teams.md"]},me={boot:{type:"boolean"},org:{type:"string",short:"o"},name:{type:"string",short:"n",default:void 0},author:{type:"string",short:"a",default:void 0},all:{type:"boolean"},license:{type:"string",message:"Pick the license"},scripts:{type:"boolean"},styles:{type:"boolean"},docs:{type:"boolean"},ide:{type:"boolean"},workflows:{type:"boolean"},templates:{type:"boolean"},typescript:{type:"boolean"},docker:{type:"boolean"},pkg:{type:"boolean"},dependencies:{type:"boolean"},tests:{type:"boolean"},automation:{type:"boolean"}};class pe extends te{constructor(){super("TemplateSync",me),this.replacements={},this.getStyles=()=>this.downloadOption("styles"),this.getTemplates=()=>this.downloadOption("templates"),this.getWorkflows=()=>this.downloadOption("workflows"),this.getDocs=()=>this.downloadOption("docs"),this.getTypescript=()=>this.downloadOption("typescript"),this.getAutomation=()=>this.downloadOption("automation"),this.getTests=()=>this.downloadOption("tests"),this.getDocker=()=>this.downloadOption("docker")}loadValuesFromPackage(){const e=process.cwd(),t=G(e,"author");let o,a=G(e,"name");if(a.startsWith("@")){const e=a.split("/");a=e[1],o=e[0].replace("@","")}["Tiago Venceslau","TiagoVenceslau","${author}"].forEach(e=>this.replacements[e]=t),["TS-Workspace","ts-workspace","${name}"].forEach(e=>this.replacements[e]=a),["decaf-ts","${org}"].forEach(e=>this.replacements[e]=o||'""'),this.replacements["${org_or_owner}"]=o||a}async downloadOption(e){if(!(e in ue))throw new Error(`Option "${e}" not found in options`);const t=ue[e];for(const e of t){this.log.info(`Downloading ${e}`);let t=await oe.downloadFile(`${he}/${e}`);t=a(t,this.replacements),U(i.join(process.cwd(),e),t)}}async getLicense(e){this.log.info(`Downloading ${e} license`);const t=`${he}/workdocs/licenses/${e}.md`;let o=await oe.downloadFile(t);o=a(o,this.replacements),U(i.join(process.cwd(),"LICENSE.md"),o),W("license",e)}async getIde(){r.mkdirSync(i.join(process.cwd(),".idea","runConfigurations"),{recursive:!0}),await this.downloadOption("ide")}async getScripts(){await this.downloadOption("scripts"),this.log.info("please re-run the command"),process.exit(0)}async initPackage(e,t,o){try{const a=G();delete a[$],a.name=e,a.version="0.0.1",a.author=t,a.license=o,r.writeFileSync("package.json",JSON.stringify(a,null,2))}catch(e){throw new Error(`Error fixing package.json: ${e}`)}}async updatePackageScrips(){try{const e=JSON.parse(await oe.downloadFile(`${he}/package.json`)),{scripts:t}=e,o=G();Object.keys(o.scripts).forEach(e=>{if(e in t){const n=a(t[e],this.replacements);n!==t[e]&&(o.scripts[e]=n)}}),o.exports.require=e.exports.require,o.exports.import=e.exports.import,o.types=e.types,r.writeFileSync("package.json",JSON.stringify(o,null,2))}catch(e){throw new Error(`Error fixing package.json scripts: ${e}`)}}async createTokenFiles(){const e=this.log.for(this.createTokenFiles),t=await y.insistForText("token","please input your github token",e=>!!e.match(/^ghp_[0-9a-zA-Z]{36}$/g));Object.values(E).forEach(o=>{try{let a;try{a=r.existsSync(o)}catch(a){return e.info(`Token file ${o} not found. Creating a new one...`),void r.writeFileSync(o,".token"===o?t:"")}a||r.writeFileSync(o,".token"===o?t:"")}catch(e){throw new Error(`Error creating token file ${o}: ${e}`)}})}async getOrg(){const e=await y.askText("Organization","Enter the organization name (will be used to scope your npm project. leave blank to create a unscoped project):");return await y.askConfirmation("Confirm organization","Is this organization correct?",!0)?e:this.getOrg()}async auditFix(){return await A("npm audit fix --force").promise}patchFiles(){const e=[...r.readdirSync(i.join(process.cwd(),"src"),{recursive:!0,withFileTypes:!0}).filter(e=>e.isFile()).map(e=>i.join(e.parentPath,e.name)),...r.readdirSync(i.join(process.cwd(),"workdocs"),{recursive:!0,withFileTypes:!0}).filter(e=>e.isFile()&&e.name.endsWith(".md")).map(e=>i.join(e.parentPath,e.name)),i.join(process.cwd(),".gitlab-ci.yml"),i.join(process.cwd(),"workdocs","jsdocs.json")];for(const t of e)O(t,this.replacements)}async updateDependencies(){try{const e=JSON.parse(await oe.downloadFile(`${he}/package.json`)),{devDependencies:t}=e,o=G();Object.keys(o.scripts).forEach(e=>{if(e in t){const a=t[e];a!==t[e]&&(o.devDependencies=o.devDependencies||{},o.devDependencies[e]=a)}}),r.writeFileSync("package.json",JSON.stringify(o,null,2)),await A("npm install").promise}catch(e){throw new Error(`Error fixing package.json dependencies: ${e}`)}}async run(e){let{license:t}=e;const{boot:o}=e;let{all:a,scripts:n,styles:s,docs:r,ide:i,workflows:l,templates:c,docker:g,typescript:d,dependencies:f,tests:h,automation:u,pkg:m}=e;if((n||s||r||i||l||c||g||d||u||f||h||m)&&(a=!1),o){const e=await this.getOrg(),o=await y.insistForText("Project name","Enter the project name:",e=>e.length>1),a=await y.insistForText("Author","Enter the author name:",e=>e.length>1),n=e?`@${e}/${o}`:o;await this.initPackage(n,a,t),await this.createTokenFiles(),await this.auditFix(),this.patchFiles()}if(a&&(n=!1,s=!0,r=!0,i=!0,l=!0,c=!0,g=!0,d=!0,m=!0,f=!0,h=!0,u=!1),void 0===n&&(n=await y.askConfirmation("scripts","Do you want to get scripts?",!0)),n&&await this.getScripts(),this.loadValuesFromPackage(),!a&&void 0===t){await y.askConfirmation("license","Do you want to set a license?",!0)&&(t=await y.insistForText("license","Enter the desired License (MIT|GPL|Apache|LGPL|AGPL):",e=>!!e&&!!e.match(/^(MIT|GPL|Apache|LGPL|AGPL)$/g)))}void 0!==t&&await this.getLicense(t),void 0===i&&(i=await y.askConfirmation("ide","Do you want to get ide configs?",!0)),i&&await this.getIde(),void 0===d&&(d=await y.askConfirmation("typescript","Do you want to get typescript configs?",!0)),d&&await this.getTypescript(),void 0===g&&(g=await y.askConfirmation("docker","Do you want to get docker configs?",!0)),g&&await this.getDocker(),void 0===u&&(u=await y.askConfirmation("automation","Do you want to get automation configs?",!0)),u&&await this.getAutomation(),void 0===s&&(s=await y.askConfirmation("styles","Do you want to get styles?",!0)),s&&await this.getStyles(),void 0===r&&(r=await y.askConfirmation("docs","Do you want to get docs?",!0)),r&&await this.getDocs(),void 0===l&&(l=await y.askConfirmation("workflows","Do you want to get workflows?",!0)),l&&await this.getWorkflows(),void 0===c&&(c=await y.askConfirmation("templates","Do you want to get templates?",!0)),c&&await this.getTemplates(),void 0===m&&(m=await y.askConfirmation("pkg","Do you want to update your package.json scripts?",!0)),m&&await this.updatePackageScrips(),void 0===h&&(h=await y.askConfirmation("pkg","Do you want to update your test configs?",!0)),h&&await this.getTests(),void 0===f&&(f=await y.askConfirmation("pkg","Do you want to update dev dependencies?",!0)),f&&await this.updateDependencies()}}class Se extends x{constructor(e,t,o,a="g"){super(e,t);try{this.regexp="string"==typeof o?new RegExp(o,a):o}catch(e){throw new Error(`Invalid regular expression: ${e}`)}}test(e){let t;this.regexp.lastIndex=0;try{t=this.regexp.exec(e)}catch(t){return console.debug(`Failed to parse chunk: ${e}\nError: ${t} `)}return t}testAndResolve(e){const t=this.test(e);t&&this.resolve(t[0])}testAndReject(e){const t=this.test(e);t&&this.reject(t[0])}data(e){super.data(e),this.testAndResolve(String(e))}error(e){super.error(e),this.testAndReject(String(e))}}const we="0.3.13",ye="@decaf-ts/utils";export{I as AbortCode,ge as BuildScripts,te as Command,T as DefaultCommandOptions,b as DefaultCommandValues,C as Encoding,oe as HttpClient,k as NoCIFLag,ye as PACKAGE_NAME,Se as RegexpOutputWriter,fe as ReleaseScript,D as SemVersion,v as SemVersionRegex,$ as SetupScriptKey,x as StandardOutputWriter,pe as TemplateSync,E as Tokens,y as UserInput,we as VERSION,j as chainAbortController,J as copyFile,R as deletePath,M as getAllFiles,X as getDependencies,G as getPackage,se as getPackageDependencies,V as getPackageVersion,ee as getSlogan,z as installDependencies,_ as installIfNotAvailable,F as lockify,Y as normalizeImport,ne as packageToGlobal,ae as parseList,O as patchFile,Q as printBanner,q as pushToGit,P as readFile,L as renameFile,A as runCommand,W as setPackageAttribute,N as spawnCommand,H as updateDependencies,U as writeFile};