@nikovirtala/projen-constructs 0.1.6 → 0.1.8

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.
@@ -0,0 +1,510 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProjectGenerator = void 0;
4
+ const jsii_struct_builder_1 = require("@mrgrain/jsii-struct-builder");
5
+ const projen_1 = require("projen");
6
+ const errors_1 = require("./errors");
7
+ /**
8
+ * Default components applied to all generated projects
9
+ */
10
+ const DEFAULT_COMPONENTS = [
11
+ { component: require("./components/mise").Mise },
12
+ {
13
+ component: require("./components/vitest").Vitest,
14
+ optionsProperty: {
15
+ name: "vitestOptions",
16
+ type: "@nikovirtala/projen-constructs.VitestOptions",
17
+ docs: "Vitest configuration",
18
+ },
19
+ },
20
+ ];
21
+ /**
22
+ * Buffer for building indented code with automatic line management
23
+ *
24
+ * Maintains indentation level and provides methods for adding lines,
25
+ * opening/closing blocks, and flushing accumulated content.
26
+ */
27
+ class CodeBuffer {
28
+ /**
29
+ * @param indent - String to use for each indentation level (default: single space)
30
+ */
31
+ constructor(indent = " ") {
32
+ this.indent = indent;
33
+ this.lines = [];
34
+ this.indentLevel = 0;
35
+ }
36
+ /**
37
+ * Returns all accumulated lines and resets the buffer
38
+ *
39
+ * @returns Array of code lines with proper indentation
40
+ */
41
+ flush() {
42
+ const current = this.lines;
43
+ this.reset();
44
+ return current;
45
+ }
46
+ /**
47
+ * Adds a line of code at the current indentation level
48
+ *
49
+ * @param code - Code to add (optional, adds blank line if omitted)
50
+ */
51
+ line(code) {
52
+ const prefix = this.indent.repeat(this.indentLevel);
53
+ this.lines.push((prefix + (code ?? "")).trimEnd());
54
+ }
55
+ /**
56
+ * Opens a new indentation block
57
+ *
58
+ * @param code - Optional code to add before increasing indent (e.g., opening brace)
59
+ */
60
+ open(code) {
61
+ if (code) {
62
+ this.line(code);
63
+ }
64
+ this.indentLevel++;
65
+ }
66
+ /**
67
+ * Closes the current indentation block
68
+ *
69
+ * @param code - Optional code to add after decreasing indent (e.g., closing brace)
70
+ * @throws {InvalidIndentLevelError} When attempting to decrease indent below zero
71
+ */
72
+ close(code) {
73
+ if (this.indentLevel === 0) {
74
+ throw new errors_1.InvalidIndentLevelError();
75
+ }
76
+ this.indentLevel--;
77
+ if (code) {
78
+ this.line(code);
79
+ }
80
+ }
81
+ /**
82
+ * Resets the buffer to initial state
83
+ */
84
+ reset() {
85
+ this.lines = [];
86
+ this.indentLevel = 0;
87
+ }
88
+ }
89
+ /**
90
+ * Renders TypeScript class code from ProjectGenerator options
91
+ *
92
+ * Generates a complete TypeScript class file including imports, options interface export,
93
+ * class declaration, and constructor with component integration.
94
+ */
95
+ class TypeScriptClassRenderer {
96
+ /**
97
+ * @param indent - Number of spaces per indentation level (default: 4)
98
+ */
99
+ constructor(indent = 4) {
100
+ this.buffer = new CodeBuffer(" ".repeat(indent));
101
+ }
102
+ /**
103
+ * Renders complete TypeScript class code from options
104
+ *
105
+ * Orchestrates the rendering process: derives names, extracts component configuration,
106
+ * builds import statements, and renders the class structure.
107
+ *
108
+ * @param options - Generator configuration
109
+ * @returns Complete TypeScript class code as a string
110
+ */
111
+ render(options) {
112
+ this.buffer.flush();
113
+ /* Derive interface and type names from the class name */
114
+ const optionsInterface = `${options.name}Options`;
115
+ const baseOptionsFqn = this.getBaseOptionsFqn(options.projectType);
116
+ const baseOptionsType = baseOptionsFqn.replace(/^projen\./, "");
117
+ /* Use provided components or fall back to defaults (Mise + Vitest) */
118
+ const components = options.components ?? DEFAULT_COMPONENTS;
119
+ /* Extract component configuration for constructor generation */
120
+ const { destructure, componentArray } = this.extractComponentOptions(components);
121
+ const imports = this.extractImports(options, optionsInterface);
122
+ /* Render all sections of the class file */
123
+ this.renderImports(imports);
124
+ this.buffer.line();
125
+ this.renderExport(optionsInterface);
126
+ this.buffer.line();
127
+ this.renderClass(options, optionsInterface, baseOptionsType, destructure, componentArray);
128
+ this.buffer.line();
129
+ return this.buffer.flush().join("\n");
130
+ }
131
+ /**
132
+ * Derives the fully qualified options interface name from project type
133
+ *
134
+ * Transforms project type into the corresponding Projen options interface name
135
+ * by appending "Options" suffix and prefixing with "projen." namespace.
136
+ *
137
+ * @param projectType - Project type identifier
138
+ * @returns Fully qualified options interface name
139
+ * @throws {InvalidBaseClassFormatError} When projectType format is invalid
140
+ *
141
+ * @example
142
+ * getBaseOptionsFqn(ProjectType.TYPESCRIPT) // "projen.typescript.TypeScriptProjectOptions"
143
+ * getBaseOptionsFqn(ProjectType.JSII) // "projen.cdk.JsiiProjectOptions"
144
+ */
145
+ getBaseOptionsFqn(projectType) {
146
+ const baseClass = projectType.valueOf();
147
+ /* Validate base class format: must contain module.ClassName structure */
148
+ if (!baseClass.includes(".")) {
149
+ throw new errors_1.InvalidBaseClassFormatError(baseClass);
150
+ }
151
+ return `projen.${baseClass}Options`;
152
+ }
153
+ /**
154
+ * Extracts component configuration for constructor code generation
155
+ *
156
+ * Transforms component configurations into:
157
+ * 1. Destructure list: variable names to extract from options
158
+ * 2. Component array: code string for applyDefaults() call
159
+ *
160
+ * @param components - Component configurations
161
+ * @returns Object with destructure array and componentArray code string
162
+ *
163
+ * @example
164
+ * Input: [{ component: Vitest, optionsProperty: { name: "vitestOptions", ... } }]
165
+ * Output: {
166
+ * destructure: ["vitest", "vitestOptions"],
167
+ * componentArray: "[{ component: Vitest, enabled: vitest, options: vitestOptions }]"
168
+ * }
169
+ */
170
+ extractComponentOptions(components) {
171
+ const destructure = [];
172
+ const componentParts = [];
173
+ for (const c of components) {
174
+ /* Convert component class name to camelCase variable name (e.g., Vitest -> vitest) */
175
+ const name = c.component.name.charAt(0).toLowerCase() + c.component.name.slice(1);
176
+ destructure.push(name);
177
+ /* Build component config object for applyDefaults() call */
178
+ const parts = [`component: ${c.component.name}`];
179
+ if (c.optionsProperty) {
180
+ /* Component has configurable options - include both enabled flag and options */
181
+ destructure.push(c.optionsProperty.name);
182
+ parts.push(`enabled: ${name}`, `options: ${c.optionsProperty.name}`);
183
+ }
184
+ else {
185
+ /* Component has no options - only include enabled flag */
186
+ parts.push(`enabled: ${name}`);
187
+ }
188
+ componentParts.push(`{ ${parts.join(", ")} }`);
189
+ }
190
+ return { destructure, componentArray: `[${componentParts.join(", ")}]` };
191
+ }
192
+ /**
193
+ * Builds import statements map for the generated class
194
+ *
195
+ * Collects all required imports:
196
+ * - Projen base module (typescript, cdk, awscdk)
197
+ * - Config utilities (applyDefaults, defaultOptions)
198
+ * - Component classes
199
+ * - Utility functions (deepMerge)
200
+ * - Generated options interface (type-only import)
201
+ *
202
+ * @param options - Generator configuration
203
+ * @param optionsInterface - Name of the generated options interface
204
+ * @returns Map of module paths to sets of imported names
205
+ */
206
+ extractImports(options, optionsInterface) {
207
+ const imports = new Map();
208
+ /* Extract base module name from projectType (e.g., "typescript" from "typescript.TypeScriptProject") */
209
+ const baseModule = options.projectType.valueOf().split(".")[0];
210
+ const optionsFileName = this.getOptionsFileName(optionsInterface);
211
+ /* Projen base module import */
212
+ imports.set("projen", new Set([baseModule]));
213
+ /* Configuration utilities import */
214
+ imports.set("../config", new Set(["applyDefaults", "defaultOptions"]));
215
+ /* Component class imports - derive module path from component class name */
216
+ const components = options.components ?? DEFAULT_COMPONENTS;
217
+ for (const c of components) {
218
+ const componentName = c.component.name;
219
+ const modulePath = `../components/${componentName.toLowerCase()}`;
220
+ if (!imports.has(modulePath)) {
221
+ imports.set(modulePath, new Set());
222
+ }
223
+ const moduleImports = imports.get(modulePath);
224
+ if (moduleImports) {
225
+ moduleImports.add(componentName);
226
+ }
227
+ }
228
+ /* Utility functions import */
229
+ imports.set("../utils", new Set(["deepMerge"]));
230
+ /* Generated options interface import (type-only to avoid circular dependencies) */
231
+ imports.set(`./${optionsFileName}.generated`, new Set([optionsInterface]));
232
+ return imports;
233
+ }
234
+ /**
235
+ * Derives the config path for accessing default options
236
+ *
237
+ * Transforms project type into the corresponding path in the defaultOptions
238
+ * configuration object exported from config.ts.
239
+ *
240
+ * @param projectType - Project type identifier
241
+ * @returns Config path for accessing default options
242
+ *
243
+ * @example
244
+ * getConfigPath(ProjectType.TYPESCRIPT) // "defaultOptions.typescript.TypeScriptProject"
245
+ */
246
+ getConfigPath(projectType) {
247
+ return `defaultOptions.${projectType.valueOf()}`;
248
+ }
249
+ /**
250
+ * Renders import statements in sorted order
251
+ *
252
+ * Sorts imports with external packages first, then relative imports.
253
+ * Uses type-only imports for generated files to avoid circular dependencies.
254
+ *
255
+ * @param imports - Map of module paths to imported names
256
+ */
257
+ renderImports(imports) {
258
+ /* Sort modules: external packages first, then relative imports alphabetically */
259
+ const sortedModules = Array.from(imports.keys()).sort((a, b) => {
260
+ const aIsRelative = a.startsWith(".");
261
+ const bIsRelative = b.startsWith(".");
262
+ if (aIsRelative !== bIsRelative) {
263
+ return aIsRelative ? 1 : -1;
264
+ }
265
+ return a.localeCompare(b);
266
+ });
267
+ for (const mod of sortedModules) {
268
+ const names = Array.from(imports.get(mod) || []).sort();
269
+ /* Use type-only import for generated files to prevent circular dependencies */
270
+ const isTypeOnly = mod.includes(".generated");
271
+ const importStmt = isTypeOnly ? "import type" : "import";
272
+ this.buffer.line(`${importStmt} { ${names.join(", ")} } from "${mod}";`);
273
+ }
274
+ }
275
+ /**
276
+ * Renders re-export statement for the generated options interface
277
+ *
278
+ * @param optionsInterface - Name of the options interface to export
279
+ */
280
+ renderExport(optionsInterface) {
281
+ const optionsFileName = this.getOptionsFileName(optionsInterface);
282
+ this.buffer.line();
283
+ this.buffer.line(`export { ${optionsInterface} } from "./${optionsFileName}.generated";`);
284
+ }
285
+ /**
286
+ * Renders the class declaration and constructor
287
+ *
288
+ * @param options - Generator configuration
289
+ * @param optionsInterface - Name of the options interface
290
+ * @param baseOptionsType - Base options type without "projen." prefix
291
+ * @param destructure - Variable names to destructure from options
292
+ * @param componentArray - Code string for component array
293
+ */
294
+ renderClass(options, optionsInterface, baseOptionsType, destructure, componentArray) {
295
+ this.buffer.line();
296
+ this.buffer.line("/**");
297
+ this.buffer.line(` * ${options.name} with standard configuration and component integration`);
298
+ this.buffer.line(" *");
299
+ this.buffer.line(" * Extends Projen's base class with opinionated defaults and automatic component setup.");
300
+ this.buffer.line(" */");
301
+ this.buffer.open(`export class ${options.name} extends ${options.projectType.valueOf()} {`);
302
+ this.renderConstructor(options, optionsInterface, baseOptionsType, destructure, componentArray);
303
+ this.buffer.close("}");
304
+ }
305
+ /**
306
+ * Renders the constructor implementation
307
+ *
308
+ * The constructor:
309
+ * 1. Destructures component flags and options from the options parameter
310
+ * 2. Merges default configuration with user-provided options
311
+ * 3. Calls super() with merged options
312
+ * 4. Applies component defaults via applyDefaults()
313
+ *
314
+ * @param options - Generator configuration
315
+ * @param optionsInterface - Name of the options interface
316
+ * @param baseOptionsType - Base options type without "projen." prefix
317
+ * @param destructure - Variable names to destructure from options
318
+ * @param componentArray - Code string for component array
319
+ */
320
+ renderConstructor(options, optionsInterface, baseOptionsType, destructure, componentArray) {
321
+ const configPath = this.getConfigPath(options.projectType);
322
+ this.buffer.line("/**");
323
+ this.buffer.line(" * @param options - Project configuration");
324
+ this.buffer.line(" */");
325
+ this.buffer.open(`constructor(options: ${optionsInterface}) {`);
326
+ this.buffer.line("/* Separate component configuration from base Projen options */");
327
+ this.buffer.line(`const { ${destructure.join(", ")}, ...baseOptions } = options;`);
328
+ this.buffer.line();
329
+ this.buffer.line("/* Merge default configuration with user options and initialize base class */");
330
+ this.buffer.line(`super(deepMerge<${baseOptionsType}>(${configPath}, baseOptions));`);
331
+ this.buffer.line();
332
+ this.buffer.line("/* Apply component defaults and instantiate enabled components */");
333
+ this.buffer.line(`applyDefaults(this, ${componentArray});`);
334
+ this.buffer.close("}");
335
+ }
336
+ /**
337
+ * Maps options interface name to file name
338
+ *
339
+ * Converts PascalCase interface names to kebab-case file names.
340
+ * Falls back to lowercase conversion for unmapped interfaces.
341
+ *
342
+ * @param optionsInterface - Options interface name
343
+ * @returns Kebab-case file name without extension
344
+ *
345
+ * @example
346
+ * getOptionsFileName("TypeScriptProjectOptions") // "typescript-options"
347
+ */
348
+ getOptionsFileName(optionsInterface) {
349
+ const mapping = {
350
+ TypeScriptProjectOptions: "typescript-options",
351
+ JsiiProjectOptions: "jsii-options",
352
+ AwsCdkTypeScriptAppProjectOptions: "awscdk-typescript-app-options",
353
+ AwsCdkConstructLibraryProjectOptions: "awscdk-construct-library-options",
354
+ };
355
+ return mapping[optionsInterface] || optionsInterface.toLowerCase();
356
+ }
357
+ }
358
+ /**
359
+ * Projen component that generates TypeScript project classes with standard configuration
360
+ *
361
+ * This component automates the creation of project classes that extend Projen base classes
362
+ * with opinionated defaults and component integration. It generates both:
363
+ * 1. An options interface (via ProjenStruct) that extends the base Projen options
364
+ * 2. A project class that applies default configuration and instantiates components
365
+ *
366
+ * The generated code follows a consistent pattern:
367
+ * - Imports required modules and components
368
+ * - Re-exports the generated options interface
369
+ * - Defines a class extending the Projen base class
370
+ * - Constructor merges defaults with user options and applies components
371
+ *
372
+ * @example
373
+ * ```typescript
374
+ * new ProjectGenerator(project, {
375
+ * name: "TypeScriptProject",
376
+ * baseClass: "typescript.TypeScriptProject",
377
+ * filePath: "src/projects/typescript.generated.ts",
378
+ * components: [{ component: Vitest, optionsProperty: "vitestOptions" }]
379
+ * });
380
+ * ```
381
+ */
382
+ class ProjectGenerator extends projen_1.Component {
383
+ /**
384
+ * @param project - Projen project instance
385
+ * @param options - Generator configuration
386
+ */
387
+ constructor(project, options) {
388
+ super(project);
389
+ this.options = options;
390
+ this.renderer = new TypeScriptClassRenderer();
391
+ /* Generate the options interface using ProjenStruct for JSII compatibility */
392
+ const optionsInterface = `${options.name}Options`;
393
+ const baseOptionsFqn = this.renderer.getBaseOptionsFqn(options.projectType);
394
+ const optionsFilePath = this.getOptionsFilePath(optionsInterface);
395
+ /* ProjenStruct generates a concrete TypeScript interface from Projen's options
396
+ * This is necessary because JSII doesn't support TypeScript utility types like Omit<>
397
+ * The generated interface can be consumed by other languages (Python, Java, C#, Go) */
398
+ const struct = new jsii_struct_builder_1.ProjenStruct(this.asTypeScriptProject(project), {
399
+ name: optionsInterface,
400
+ filePath: optionsFilePath,
401
+ outputFileOptions: { readonly: true },
402
+ })
403
+ .mixin(jsii_struct_builder_1.Struct.fromFqn(baseOptionsFqn))
404
+ .withoutDeprecated();
405
+ /* Remove specified options from the base interface */
406
+ if (options.omitOptions) {
407
+ struct.omit(...options.omitOptions);
408
+ }
409
+ /* Add component-derived options to the interface */
410
+ const components = options.components ?? DEFAULT_COMPONENTS;
411
+ const { PrimitiveType } = require("@jsii/spec");
412
+ for (const c of components) {
413
+ const name = c.component.name.charAt(0).toLowerCase() + c.component.name.slice(1);
414
+ /* Add enabled flag for the component */
415
+ struct.add({
416
+ name,
417
+ type: { primitive: PrimitiveType.Boolean },
418
+ optional: true,
419
+ docs: {
420
+ summary: `Enable ${c.component.name} component`,
421
+ default: "true",
422
+ },
423
+ });
424
+ /* Add options property if component is configurable */
425
+ if (c.optionsProperty) {
426
+ struct.add({
427
+ name: c.optionsProperty.name,
428
+ type: { fqn: c.optionsProperty.type },
429
+ optional: true,
430
+ docs: {
431
+ summary: c.optionsProperty.docs ?? `${c.component.name} configuration`,
432
+ default: `- default ${c.component.name} configuration`,
433
+ },
434
+ });
435
+ }
436
+ }
437
+ /* Add custom options to the interface */
438
+ if (options.additionalOptions) {
439
+ struct.add(...options.additionalOptions);
440
+ }
441
+ }
442
+ /**
443
+ * Casts project to TypeScript project type
444
+ *
445
+ * ProjenStruct requires a TypeScriptProject instance. This generator is only used
446
+ * within TypeScript projects, so the cast is safe in practice.
447
+ *
448
+ * Note: Type assertion is necessary here because Projen's type system doesn't provide
449
+ * a runtime type guard for TypeScriptProject.
450
+ *
451
+ * @param project - Projen project instance
452
+ * @returns TypeScript project instance
453
+ */
454
+ asTypeScriptProject(project) {
455
+ return project;
456
+ }
457
+ /**
458
+ * Derives the file path for the generated options interface
459
+ *
460
+ * Places the options interface file in the same directory as the class file
461
+ * with a ".generated.ts" suffix.
462
+ *
463
+ * @param optionsInterface - Name of the options interface
464
+ * @returns File path for the options interface
465
+ * @throws {InvalidFilePathError} When filePath doesn't contain a directory separator
466
+ */
467
+ getOptionsFilePath(optionsInterface) {
468
+ const lastSlash = this.options.filePath.lastIndexOf("/");
469
+ if (lastSlash === -1) {
470
+ throw new errors_1.InvalidFilePathError(this.options.filePath);
471
+ }
472
+ const dir = this.options.filePath.substring(0, lastSlash);
473
+ const optionsFileName = this.renderer.getOptionsFileName(optionsInterface);
474
+ return `${dir}/${optionsFileName}.generated.ts`;
475
+ }
476
+ /**
477
+ * Generates the TypeScript class file during Projen synthesis
478
+ *
479
+ * Called by Projen during the synthesis phase to generate the project class file.
480
+ * The file is marked as readonly to prevent manual editing.
481
+ */
482
+ preSynthesize() {
483
+ const content = this.renderer.render(this.options);
484
+ new TypeScriptClassFile(this.project, this.options.filePath, content, {
485
+ readonly: this.options.readonly ?? true,
486
+ });
487
+ }
488
+ }
489
+ exports.ProjectGenerator = ProjectGenerator;
490
+ /**
491
+ * Text file for generated TypeScript class code
492
+ *
493
+ * Extends Projen's TextFile to add the generated file marker comment
494
+ * at the beginning of the file.
495
+ */
496
+ class TypeScriptClassFile extends projen_1.TextFile {
497
+ /**
498
+ * @param project - Projen project instance
499
+ * @param filePath - Output file path
500
+ * @param content - TypeScript class code
501
+ * @param options - Source code options (readonly, etc.)
502
+ */
503
+ constructor(project, filePath, content, options = {}) {
504
+ super(project, filePath, options);
505
+ /* Add generated file marker to prevent manual editing */
506
+ this.addLine(`// ${this.marker}`);
507
+ this.addLine(content);
508
+ }
509
+ }
510
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvamVjdC1nZW5lcmF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcHJvamVjdC1nZW5lcmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0Esc0VBQW9FO0FBRXBFLG1DQUE2QztBQUM3QyxxQ0FBc0c7QUFHdEc7O0dBRUc7QUFDSCxNQUFNLGtCQUFrQixHQUFzQjtJQUMxQyxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxJQUFJLEVBQUU7SUFDaEQ7UUFDSSxTQUFTLEVBQUUsT0FBTyxDQUFDLHFCQUFxQixDQUFDLENBQUMsTUFBTTtRQUNoRCxlQUFlLEVBQUU7WUFDYixJQUFJLEVBQUUsZUFBZTtZQUNyQixJQUFJLEVBQUUsOENBQThDO1lBQ3BELElBQUksRUFBRSxzQkFBc0I7U0FDL0I7S0FDSjtDQUNKLENBQUM7QUFtSEY7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVU7SUFJWjs7T0FFRztJQUNILFlBQTZCLFNBQVMsR0FBRztRQUFaLFdBQU0sR0FBTixNQUFNLENBQU07UUFOakMsVUFBSyxHQUFhLEVBQUUsQ0FBQztRQUNyQixnQkFBVyxHQUFHLENBQUMsQ0FBQztJQUtvQixDQUFDO0lBRTdDOzs7O09BSUc7SUFDSCxLQUFLO1FBQ0QsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUMzQixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDYixPQUFPLE9BQU8sQ0FBQztJQUNuQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILElBQUksQ0FBQyxJQUFhO1FBQ2QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3BELElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMs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cnQgdHlwZSB7IFByb3BlcnR5IH0gZnJvbSBcIkBqc2lpL3NwZWNcIjtcbmltcG9ydCB7IFByb2plblN0cnVjdCwgU3RydWN0IH0gZnJvbSBcIkBtcmdyYWluL2pzaWktc3RydWN0LWJ1aWxkZXJcIjtcbmltcG9ydCB0eXBlIHsgUHJvamVjdCwgU291cmNlQ29kZU9wdGlvbnMsIHR5cGVzY3JpcHQgfSBmcm9tIFwicHJvamVuXCI7XG5pbXBvcnQgeyBDb21wb25lbnQsIFRleHRGaWxlIH0gZnJvbSBcInByb2plblwiO1xuaW1wb3J0IHsgSW52YWxpZEJhc2VDbGFzc0Zvcm1hdEVycm9yLCBJbnZhbGlkRmlsZVBhdGhFcnJvciwgSW52YWxpZEluZGVudExldmVsRXJyb3IgfSBmcm9tIFwiLi9lcnJvcnNcIjtcbmltcG9ydCB0eXBlIHsgUHJvamVjdFR5cGUgfSBmcm9tIFwiLi9wcm9qZWN0LXR5cGVcIjtcblxuLyoqXG4gKiBEZWZhdWx0IGNvbXBvbmVudHMgYXBwbGllZCB0byBhbGwgZ2VuZXJhdGVkIHByb2plY3RzXG4gKi9cbmNvbnN0IERFRkFVTFRfQ09NUE9ORU5UUzogQ29tcG9uZW50Q29uZmlnW10gPSBbXG4gICAgeyBjb21wb25lbnQ6IHJlcXVpcmUoXCIuL2NvbXBvbmVudHMvbWlzZVwiKS5NaXNlIH0sXG4gICAge1xuICAgICAgICBjb21wb25lbnQ6IHJlcXVpcmUoXCIuL2NvbXBvbmVudHMvdml0ZXN0XCIpLlZpdGVzdCxcbiAgICAgICAgb3B0aW9uc1Byb3BlcnR5OiB7XG4gICAgICAgICAgICBuYW1lOiBcInZpdGVzdE9wdGlvbnNcIixcbiAgICAgICAgICAgIHR5cGU6IFwiQG5pa292aXJ0YWxhL3Byb2plbi1jb25zdHJ1Y3RzLlZpdGVzdE9wdGlvbnNcIixcbiAgICAgICAgICAgIGRvY3M6IFwiVml0ZXN0IGNvbmZpZ3VyYXRpb25cIixcbiAgICAgICAgfSxcbiAgICB9LFxuXTtcblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIGZvciBhIGNvbXBvbmVudCB0byBiZSBpbnRlZ3JhdGVkIGludG8gYSBnZW5lcmF0ZWQgcHJvamVjdFxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBjb25maWc6IENvbXBvbmVudENvbmZpZyA9IHtcbiAqICAgY29tcG9uZW50OiBWaXRlc3QsXG4gKiAgIG9wdGlvbnNQcm9wZXJ0eTogXCJ2aXRlc3RPcHRpb25zXCJcbiAqIH07XG4gKiBgYGBcbiAqL1xuaW50ZXJmYWNlIENvbXBvbmVudENvbmZpZzxUIGV4dGVuZHMgQ29tcG9uZW50ID0gQ29tcG9uZW50PiB7XG4gICAgLyoqXG4gICAgICogQ29tcG9uZW50IGNsYXNzIGNvbnN0cnVjdG9yXG4gICAgICovXG4gICAgcmVhZG9ubHkgY29tcG9uZW50OiBuZXcgKFxuICAgICAgICBwcm9qZWN0OiBuZXZlcixcbiAgICAgICAgb3B0aW9ucz86IG5ldmVyLFxuICAgICkgPT4gVDtcblxuICAgIC8qKlxuICAgICAqIE9wdGlvbnMgcHJvcGVydHkgY29uZmlndXJhdGlvbiBmb3IgdGhlIGdlbmVyYXRlZCBvcHRpb25zIGludGVyZmFjZVxuICAgICAqXG4gICAgICogV2hlbiBzcGVjaWZpZWQsIGFkZHMgYW4gb3B0aW9ucyBwcm9wZXJ0eSB0byB0aGUgaW50ZXJmYWNlIGFsbG93aW5nXG4gICAgICogdXNlcnMgdG8gY29uZmlndXJlIHRoZSBjb21wb25lbnQuXG4gICAgICovXG4gICAgcmVhZG9ubHkgb3B0aW9uc1Byb3BlcnR5Pzoge1xuICAgICAgICAvKipcbiAgICAgICAgICogTmFtZSBvZiB0aGUgb3B0aW9ucyBwcm9wZXJ0eSAoZS5nLiwgXCJ2aXRlc3RPcHRpb25zXCIpXG4gICAgICAgICAqL1xuICAgICAgICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBGdWxseSBxdWFsaWZpZWQgdHlwZSBuYW1lIChlLmcuLCBcIkBuaWtvdmlydGFsYS9wcm9qZW4tY29uc3RydWN0cy5WaXRlc3RPcHRpb25zXCIpXG4gICAgICAgICAqL1xuICAgICAgICByZWFkb25seSB0eXBlOiBzdHJpbmc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEb2N1bWVudGF0aW9uIHN1bW1hcnlcbiAgICAgICAgICovXG4gICAgICAgIHJlYWRvbmx5IGRvY3M/OiBzdHJpbmc7XG4gICAgfTtcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBQcm9qZWN0R2VuZXJhdG9yIGNvbXBvbmVudFxuICpcbiAqIENvbmZpZ3VyZXMgdGhlIGdlbmVyYXRpb24gb2YgYSBUeXBlU2NyaXB0IHByb2plY3QgY2xhc3MgdGhhdCBleHRlbmRzIGEgUHJvamVuIGJhc2UgY2xhc3NcbiAqIHdpdGggc3RhbmRhcmQgY29uZmlndXJhdGlvbiBhbmQgY29tcG9uZW50IGludGVncmF0aW9uLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBuZXcgUHJvamVjdEdlbmVyYXRvcihwcm9qZWN0LCB7XG4gKiAgIG5hbWU6IFwiVHlwZVNjcmlwdFByb2plY3RcIixcbiAqICAgYmFzZUNsYXNzOiBcInR5cGVzY3JpcHQuVHlwZVNjcmlwdFByb2plY3RcIixcbiAqICAgZmlsZVBhdGg6IFwic3JjL3Byb2plY3RzL3R5cGVzY3JpcHQuZ2VuZXJhdGVkLnRzXCIsXG4gKiAgIGNvbXBvbmVudHM6IFt7IGNvbXBvbmVudDogVml0ZXN0LCBvcHRpb25zUHJvcGVydHk6IFwidml0ZXN0T3B0aW9uc1wiIH1dXG4gKiB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFByb2plY3RHZW5lcmF0b3JPcHRpb25zIGV4dGVuZHMgU291cmNlQ29kZU9wdGlvbnMge1xuICAgIC8qKlxuICAgICAqIE5hbWUgb2YgdGhlIGdlbmVyYXRlZCBjbGFzcyAoZS5nLiwgXCJUeXBlU2NyaXB0UHJvamVjdFwiKVxuICAgICAqXG4gICAgICogVGhlIG9wdGlvbnMgaW50ZXJmYWNlIHdpbGwgYmUgbmFtZWQgYCR7bmFtZX1PcHRpb25zYC5cbiAgICAgKi9cbiAgICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBQcm9qZWN0IHR5cGUgaWRlbnRpZmllclxuICAgICAqXG4gICAgICogU3BlY2lmaWVzIHdoaWNoIFByb2plbiBiYXNlIGNsYXNzIHRvIGV4dGVuZCBhbmQgd2hpY2ggZGVmYXVsdCBjb25maWd1cmF0aW9uIHRvIGFwcGx5LlxuICAgICAqXG4gICAgICogQGV4YW1wbGUgUHJvamVjdFR5cGUuVFlQRVNDUklQVFxuICAgICAqIEBleGFtcGxlIFByb2plY3RUeXBlLkpTSUlcbiAgICAgKi9cbiAgICByZWFkb25seSBwcm9qZWN0VHlwZTogUHJvamVjdFR5cGU7XG5cbiAgICAvKipcbiAgICAgKiBPdXRwdXQgZmlsZSBwYXRoIGZvciB0aGUgZ2VuZXJhdGVkIGNsYXNzXG4gICAgICpcbiAgICAgKiBNdXN0IGNvbnRhaW4gYSBkaXJlY3Rvcnkgc2VwYXJhdG9yLiBUaGUgb3B0aW9ucyBpbnRlcmZhY2Ugd2lsbCBiZSBnZW5lcmF0ZWRcbiAgICAgKiBpbiB0aGUgc2FtZSBkaXJlY3Rvcnkgd2l0aCBhIFwiLmdlbmVyYXRlZC50c1wiIHN1ZmZpeC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlIFwic3JjL3Byb2plY3RzL3R5cGVzY3JpcHQuZ2VuZXJhdGVkLnRzXCJcbiAgICAgKi9cbiAgICByZWFkb25seSBmaWxlUGF0aDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQ29tcG9uZW50cyB0byBpbnRlZ3JhdGUgaW50byB0aGUgcHJvamVjdFxuICAgICAqXG4gICAgICogRWFjaCBjb21wb25lbnQgd2lsbCBiZSBpbnN0YW50aWF0ZWQgZHVyaW5nIHByb2plY3QgY29uc3RydWN0aW9uIGFuZCBjYW4gYmVcbiAgICAgKiBjb25maWd1cmVkIHZpYSBhbiBvcHRpb25hbCBvcHRpb25zIHByb3BlcnR5IGluIHRoZSBnZW5lcmF0ZWQgaW50ZXJmYWNlLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgW3sgY29tcG9uZW50OiBNaXNlIH0sIHsgY29tcG9uZW50OiBWaXRlc3QsIG9wdGlvbnNQcm9wZXJ0eTogeyBuYW1lOiBcInZpdGVzdE9wdGlvbnNcIiwgdHlwZTogXCIuLi5cIiwgZG9jczogXCIuLi5cIiB9IH1dXG4gICAgICovXG4gICAgcmVhZG9ubHkgY29tcG9uZW50cz86IENvbXBvbmVudENvbmZpZ1tdO1xuXG4gICAgLyoqXG4gICAgICogQWRkaXRpb25hbCBwcm9wZXJ0aWVzIHRvIGFkZCB0byB0aGUgZ2VuZXJhdGVkIG9wdGlvbnMgaW50ZXJmYWNlXG4gICAgICpcbiAgICAgKiBVc2UgdGhpcyB0byBleHRlbmQgdGhlIGJhc2Ugb3B0aW9ucyB3aXRoIGN1c3RvbSBwcm9wZXJ0aWVzIHNwZWNpZmljIHRvXG4gICAgICogeW91ciBwcm9qZWN0IHR5cGUuXG4gICAgICovXG4gICAgcmVhZG9ubHkgYWRkaXRpb25hbE9wdGlvbnM/OiBQcm9wZXJ0eVtdO1xuXG4gICAgLyoqXG4gICAgICogUHJvcGVydHkgbmFtZXMgdG8gb21pdCBmcm9tIHRoZSBiYXNlIG9wdGlvbnMgaW50ZXJmYWNlXG4gICAgICpcbiAgICAgKiBVc2UgdGhpcyB0byBoaWRlIGJhc2UgY2xhc3Mgb3B0aW9ucyB0aGF0IHNob3VsZCBub3QgYmUgY29uZmlndXJhYmxlXG4gICAgICogaW4gdGhlIGdlbmVyYXRlZCBwcm9qZWN0IHR5cGUuXG4gICAgICovXG4gICAgcmVhZG9ubHkgb21pdE9wdGlvbnM/OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBCdWZmZXIgZm9yIGJ1aWxkaW5nIGluZGVudGVkIGNvZGUgd2l0aCBhdXRvbWF0aWMgbGluZSBtYW5hZ2VtZW50XG4gKlxuICogTWFpbnRhaW5zIGluZGVudGF0aW9uIGxldmVsIGFuZCBwcm92aWRlcyBtZXRob2RzIGZvciBhZGRpbmcgbGluZXMsXG4gKiBvcGVuaW5nL2Nsb3NpbmcgYmxvY2tzLCBhbmQgZmx1c2hpbmcgYWNjdW11bGF0ZWQgY29udGVudC5cbiAqL1xuY2xhc3MgQ29kZUJ1ZmZlciB7XG4gICAgcHJpdmF0ZSBsaW5lczogc3RyaW5nW10gPSBbXTtcbiAgICBwcml2YXRlIGluZGVudExldmVsID0gMDtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBpbmRlbnQgLSBTdHJpbmcgdG8gdXNlIGZvciBlYWNoIGluZGVudGF0aW9uIGxldmVsIChkZWZhdWx0OiBzaW5nbGUgc3BhY2UpXG4gICAgICovXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBpbmRlbnQgPSBcIiBcIikge31cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYWxsIGFjY3VtdWxhdGVkIGxpbmVzIGFuZCByZXNldHMgdGhlIGJ1ZmZlclxuICAgICAqXG4gICAgICogQHJldHVybnMgQXJyYXkgb2YgY29kZSBsaW5lcyB3aXRoIHByb3BlciBpbmRlbnRhdGlvblxuICAgICAqL1xuICAgIGZsdXNoKCk6IHN0cmluZ1tdIHtcbiAgICAgICAgY29uc3QgY3VycmVudCA9IHRoaXMubGluZXM7XG4gICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgcmV0dXJuIGN1cnJlbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpbmUgb2YgY29kZSBhdCB0aGUgY3VycmVudCBpbmRlbnRhdGlvbiBsZXZlbFxuICAgICAqXG4gICAgICogQHBhcmFtIGNvZGUgLSBDb2RlIHRvIGFkZCAob3B0aW9uYWwsIGFkZHMgYmxhbmsgbGluZSBpZiBvbWl0dGVkKVxuICAgICAqL1xuICAgIGxpbmUoY29kZT86IHN0cmluZykge1xuICAgICAgICBjb25zdCBwcmVmaXggPSB0aGlzLmluZGVudC5yZXBlYXQodGhpcy5pbmRlbnRMZXZlbCk7XG4gICAgICAgIHRoaXMubGluZXMucHVzaCgocHJlZml4ICsgKGNvZGUgPz8gXCJcIikpLnRyaW1FbmQoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT3BlbnMgYSBuZXcgaW5kZW50YXRpb24gYmxvY2tcbiAgICAgKlxuICAgICAqIEBwYXJhbSBjb2RlIC0gT3B0aW9uYWwgY29kZSB0byBhZGQgYmVmb3JlIGluY3JlYXNpbmcgaW5kZW50IChlLmcuLCBvcGVuaW5nIGJyYWNlKVxuICAgICAqL1xuICAgIG9wZW4oY29kZT86IHN0cmluZykge1xuICAgICAgICBpZiAoY29kZSkge1xuICAgICAgICAgICAgdGhpcy5saW5lKGNvZGUpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaW5kZW50TGV2ZWwrKztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbG9zZXMgdGhlIGN1cnJlbnQgaW5kZW50YXRpb24gYmxvY2tcbiAgICAgKlxuICAgICAqIEBwYXJhbSBjb2RlIC0gT3B0aW9uYWwgY29kZSB0byBhZGQgYWZ0ZXIgZGVjcmVhc2luZyBpbmRlbnQgKGUuZy4sIGNsb3NpbmcgYnJhY2UpXG4gICAgICogQHRocm93cyB7SW52YWxpZEluZGVudExldmVsRXJyb3J9IFdoZW4gYXR0ZW1wdGluZyB0byBkZWNyZWFzZSBpbmRlbnQgYmVsb3cgemVyb1xuICAgICAqL1xuICAgIGNsb3NlKGNvZGU/OiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKHRoaXMuaW5kZW50TGV2ZWwgPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBJbnZhbGlkSW5kZW50TGV2ZWxFcnJvcigpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaW5kZW50TGV2ZWwtLTtcbiAgICAgICAgaWYgKGNvZGUpIHtcbiAgICAgICAgICAgIHRoaXMubGluZShjb2RlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc2V0cyB0aGUgYnVmZmVyIHRvIGluaXRpYWwgc3RhdGVcbiAgICAgKi9cbiAgICBwcml2YXRlIHJlc2V0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmxpbmVzID0gW107XG4gICAgICAgIHRoaXMuaW5kZW50TGV2ZWwgPSAwO1xuICAgIH1cbn1cblxuLyoqXG4gKiBSZW5kZXJzIFR5cGVTY3JpcHQgY2xhc3MgY29kZSBmcm9tIFByb2plY3RHZW5lcmF0b3Igb3B0aW9uc1xuICpcbiAqIEdlbmVyYXRlcyBhIGNvbXBsZXRlIFR5cGVTY3JpcHQgY2xhc3MgZmlsZSBpbmNsdWRpbmcgaW1wb3J0cywgb3B0aW9ucyBpbnRlcmZhY2UgZXhwb3J0LFxuICogY2xhc3MgZGVjbGFyYXRpb24sIGFuZCBjb25zdHJ1Y3RvciB3aXRoIGNvbXBvbmVudCBpbnRlZ3JhdGlvbi5cbiAqL1xuY2xhc3MgVHlwZVNjcmlwdENsYXNzUmVuZGVyZXIge1xuICAgIHByaXZhdGUgYnVmZmVyOiBDb2RlQnVmZmVyO1xuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGluZGVudCAtIE51bWJlciBvZiBzcGFjZXMgcGVyIGluZGVudGF0aW9uIGxldmVsIChkZWZhdWx0OiA0KVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGluZGVudCA9IDQpIHtcbiAgICAgICAgdGhpcy5idWZmZXIgPSBuZXcgQ29kZUJ1ZmZlcihcIiBcIi5yZXBlYXQoaW5kZW50KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBjb21wbGV0ZSBUeXBlU2NyaXB0IGNsYXNzIGNvZGUgZnJvbSBvcHRpb25zXG4gICAgICpcbiAgICAgKiBPcmNoZXN0cmF0ZXMgdGhlIHJlbmRlcmluZyBwcm9jZXNzOiBkZXJpdmVzIG5hbWVzLCBleHRyYWN0cyBjb21wb25lbnQgY29uZmlndXJhdGlvbixcbiAgICAgKiBidWlsZHMgaW1wb3J0IHN0YXRlbWVudHMsIGFuZCByZW5kZXJzIHRoZSBjbGFzcyBzdHJ1Y3R1cmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIEdlbmVyYXRvciBjb25maWd1cmF0aW9uXG4gICAgICogQHJldHVybnMgQ29tcGxldGUgVHlwZVNjcmlwdCBjbGFzcyBjb2RlIGFzIGEgc3RyaW5nXG4gICAgICovXG4gICAgcmVuZGVyKG9wdGlvbnM6IFByb2plY3RHZW5lcmF0b3JPcHRpb25zKTogc3RyaW5nIHtcbiAgICAgICAgdGhpcy5idWZmZXIuZmx1c2goKTtcblxuICAgICAgICAvKiBEZXJpdmUgaW50ZXJmYWNlIGFuZCB0eXBlIG5hbWVzIGZyb20gdGhlIGNsYXNzIG5hbWUgKi9cbiAgICAgICAgY29uc3Qgb3B0aW9uc0ludGVyZmFjZSA9IGAke29wdGlvbnMubmFtZX1PcHRpb25zYDtcbiAgICAgICAgY29uc3QgYmFzZU9wdGlvbnNGcW4gPSB0aGlzLmdldEJhc2VPcHRpb25zRnFuKG9wdGlvbnMucHJvamVjdFR5cGUpO1xuICAgICAgICBjb25zdCBiYXNlT3B0aW9uc1R5cGUgPSBiYXNlT3B0aW9uc0Zxbi5yZXBsYWNlKC9ecHJvamVuXFwuLywgXCJcIik7XG5cbiAgICAgICAgLyogVXNlIHByb3ZpZGVkIGNvbXBvbmVudHMgb3IgZmFsbCBiYWNrIHRvIGRlZmF1bHRzIChNaXNlICsgVml0ZXN0KSAqL1xuICAgICAgICBjb25zdCBjb21wb25lbnRzID0gb3B0aW9ucy5jb21wb25lbnRzID8/IERFRkFVTFRfQ09NUE9ORU5UUztcblxuICAgICAgICAvKiBFeHRyYWN0IGNvbXBvbmVudCBjb25maWd1cmF0aW9uIGZvciBjb25zdHJ1Y3RvciBnZW5lcmF0aW9uICovXG4gICAgICAgIGNvbnN0IHsgZGVzdHJ1Y3R1cmUsIGNvbXBvbmVudEFycmF5IH0gPSB0aGlzLmV4dHJhY3RDb21wb25lbnRPcHRpb25zKGNvbXBvbmVudHMpO1xuICAgICAgICBjb25zdCBpbXBvcnRzID0gdGhpcy5leHRyYWN0SW1wb3J0cyhvcHRpb25zLCBvcHRpb25zSW50ZXJmYWNlKTtcblxuICAgICAgICAvKiBSZW5kZXIgYWxsIHNlY3Rpb25zIG9mIHRoZSBjbGFzcyBmaWxlICovXG4gICAgICAgIHRoaXMucmVuZGVySW1wb3J0cyhpbXBvcnRzKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZSgpO1xuICAgICAgICB0aGlzLnJlbmRlckV4cG9ydChvcHRpb25zSW50ZXJmYWNlKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZSgpO1xuICAgICAgICB0aGlzLnJlbmRlckNsYXNzKG9wdGlvbnMsIG9wdGlvbnNJbnRlcmZhY2UsIGJhc2VPcHRpb25zVHlwZSwgZGVzdHJ1Y3R1cmUsIGNvbXBvbmVudEFycmF5KTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZSgpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmJ1ZmZlci5mbHVzaCgpLmpvaW4oXCJcXG5cIik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVyaXZlcyB0aGUgZnVsbHkgcXVhbGlmaWVkIG9wdGlvbnMgaW50ZXJmYWNlIG5hbWUgZnJvbSBwcm9qZWN0IHR5cGVcbiAgICAgKlxuICAgICAqIFRyYW5zZm9ybXMgcHJvamVjdCB0eXBlIGludG8gdGhlIGNvcnJlc3BvbmRpbmcgUHJvamVuIG9wdGlvbnMgaW50ZXJmYWNlIG5hbWVcbiAgICAgKiBieSBhcHBlbmRpbmcgXCJPcHRpb25zXCIgc3VmZml4IGFuZCBwcmVmaXhpbmcgd2l0aCBcInByb2plbi5cIiBuYW1lc3BhY2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcHJvamVjdFR5cGUgLSBQcm9qZWN0IHR5cGUgaWRlbnRpZmllclxuICAgICAqIEByZXR1cm5zIEZ1bGx5IHF1YWxpZmllZCBvcHRpb25zIGludGVyZmFjZSBuYW1lXG4gICAgICogQHRocm93cyB7SW52YWxpZEJhc2VDbGFzc0Zvcm1hdEVycm9yfSBXaGVuIHByb2plY3RUeXBlIGZvcm1hdCBpcyBpbnZhbGlkXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGdldEJhc2VPcHRpb25zRnFuKFByb2plY3RUeXBlLlRZUEVTQ1JJUFQpIC8vIFwicHJvamVuLnR5cGVzY3JpcHQuVHlwZVNjcmlwdFByb2plY3RPcHRpb25zXCJcbiAgICAgKiBnZXRCYXNlT3B0aW9uc0ZxbihQcm9qZWN0VHlwZS5KU0lJKSAvLyBcInByb2plbi5jZGsuSnNpaVByb2plY3RPcHRpb25zXCJcbiAgICAgKi9cbiAgICBnZXRCYXNlT3B0aW9uc0Zxbihwcm9qZWN0VHlwZTogUHJvamVjdFR5cGUpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCBiYXNlQ2xhc3MgPSBwcm9qZWN0VHlwZS52YWx1ZU9mKCk7XG4gICAgICAgIC8qIFZhbGlkYXRlIGJhc2UgY2xhc3MgZm9ybWF0OiBtdXN0IGNvbnRhaW4gbW9kdWxlLkNsYXNzTmFtZSBzdHJ1Y3R1cmUgKi9cbiAgICAgICAgaWYgKCFiYXNlQ2xhc3MuaW5jbHVkZXMoXCIuXCIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgSW52YWxpZEJhc2VDbGFzc0Zvcm1hdEVycm9yKGJhc2VDbGFzcyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYHByb2plbi4ke2Jhc2VDbGFzc31PcHRpb25zYDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeHRyYWN0cyBjb21wb25lbnQgY29uZmlndXJhdGlvbiBmb3IgY29uc3RydWN0b3IgY29kZSBnZW5lcmF0aW9uXG4gICAgICpcbiAgICAgKiBUcmFuc2Zvcm1zIGNvbXBvbmVudCBjb25maWd1cmF0aW9ucyBpbnRvOlxuICAgICAqIDEuIERlc3RydWN0dXJlIGxpc3Q6IHZhcmlhYmxlIG5hbWVzIHRvIGV4dHJhY3QgZnJvbSBvcHRpb25zXG4gICAgICogMi4gQ29tcG9uZW50IGFycmF5OiBjb2RlIHN0cmluZyBmb3IgYXBwbHlEZWZhdWx0cygpIGNhbGxcbiAgICAgKlxuICAgICAqIEBwYXJhbSBjb21wb25lbnRzIC0gQ29tcG9uZW50IGNvbmZpZ3VyYXRpb25zXG4gICAgICogQHJldHVybnMgT2JqZWN0IHdpdGggZGVzdHJ1Y3R1cmUgYXJyYXkgYW5kIGNvbXBvbmVudEFycmF5IGNvZGUgc3RyaW5nXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIElucHV0OiBbeyBjb21wb25lbnQ6IFZpdGVzdCwgb3B0aW9uc1Byb3BlcnR5OiB7IG5hbWU6IFwidml0ZXN0T3B0aW9uc1wiLCAuLi4gfSB9XVxuICAgICAqIE91dHB1dDoge1xuICAgICAqICAgZGVzdHJ1Y3R1cmU6IFtcInZpdGVzdFwiLCBcInZpdGVzdE9wdGlvbnNcIl0sXG4gICAgICogICBjb21wb25lbnRBcnJheTogXCJbeyBjb21wb25lbnQ6IFZpdGVzdCwgZW5hYmxlZDogdml0ZXN0LCBvcHRpb25zOiB2aXRlc3RPcHRpb25zIH1dXCJcbiAgICAgKiB9XG4gICAgICovXG4gICAgcHJpdmF0ZSBleHRyYWN0Q29tcG9uZW50T3B0aW9ucyhjb21wb25lbnRzOiBDb21wb25lbnRDb25maWdbXSk6IHsgZGVzdHJ1Y3R1cmU6IHN0cmluZ1tdOyBjb21wb25lbnRBcnJheTogc3RyaW5nIH0ge1xuICAgICAgICBjb25zdCBkZXN0cnVjdHVyZTogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgY29uc3QgY29tcG9uZW50UGFydHM6IHN0cmluZ1tdID0gW107XG5cbiAgICAgICAgZm9yIChjb25zdCBjIG9mIGNvbXBvbmVudHMpIHtcbiAgICAgICAgICAgIC8qIENvbnZlcnQgY29tcG9uZW50IGNsYXNzIG5hbWUgdG8gY2FtZWxDYXNlIHZhcmlhYmxlIG5hbWUgKGUuZy4sIFZpdGVzdCAtPiB2aXRlc3QpICovXG4gICAgICAgICAgICBjb25zdCBuYW1lID0gYy5jb21wb25lbnQubmFtZS5jaGFyQXQoMCkudG9Mb3dlckNhc2UoKSArIGMuY29tcG9uZW50Lm5hbWUuc2xpY2UoMSk7XG4gICAgICAgICAgICBkZXN0cnVjdHVyZS5wdXNoKG5hbWUpO1xuXG4gICAgICAgICAgICAvKiBCdWlsZCBjb21wb25lbnQgY29uZmlnIG9iamVjdCBmb3IgYXBwbHlEZWZhdWx0cygpIGNhbGwgKi9cbiAgICAgICAgICAgIGNvbnN0IHBhcnRzID0gW2Bjb21wb25lbnQ6ICR7Yy5jb21wb25lbnQubmFtZX1gXTtcbiAgICAgICAgICAgIGlmIChjLm9wdGlvbnNQcm9wZXJ0eSkge1xuICAgICAgICAgICAgICAgIC8qIENvbXBvbmVudCBoYXMgY29uZmlndXJhYmxlIG9wdGlvbnMgLSBpbmNsdWRlIGJvdGggZW5hYmxlZCBmbGFnIGFuZCBvcHRpb25zICovXG4gICAgICAgICAgICAgICAgZGVzdHJ1Y3R1cmUucHVzaChjLm9wdGlvbnNQcm9wZXJ0eS5uYW1lKTtcbiAgICAgICAgICAgICAgICBwYXJ0cy5wdXNoKGBlbmFibGVkOiAke25hbWV9YCwgYG9wdGlvbnM6ICR7Yy5vcHRpb25zUHJvcGVydHkubmFtZX1gKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLyogQ29tcG9uZW50IGhhcyBubyBvcHRpb25zIC0gb25seSBpbmNsdWRlIGVuYWJsZWQgZmxhZyAqL1xuICAgICAgICAgICAgICAgIHBhcnRzLnB1c2goYGVuYWJsZWQ6ICR7bmFtZX1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbXBvbmVudFBhcnRzLnB1c2goYHsgJHtwYXJ0cy5qb2luKFwiLCBcIil9IH1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IGRlc3RydWN0dXJlLCBjb21wb25lbnRBcnJheTogYFske2NvbXBvbmVudFBhcnRzLmpvaW4oXCIsIFwiKX1dYCB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEJ1aWxkcyBpbXBvcnQgc3RhdGVtZW50cyBtYXAgZm9yIHRoZSBnZW5lcmF0ZWQgY2xhc3NcbiAgICAgKlxuICAgICAqIENvbGxlY3RzIGFsbCByZXF1aXJlZCBpbXBvcnRzOlxuICAgICAqIC0gUHJvamVuIGJhc2UgbW9kdWxlICh0eXBlc2NyaXB0LCBjZGssIGF3c2NkaylcbiAgICAgKiAtIENvbmZpZyB1dGlsaXRpZXMgKGFwcGx5RGVmYXVsdHMsIGRlZmF1bHRPcHRpb25zKVxuICAgICAqIC0gQ29tcG9uZW50IGNsYXNzZXNcbiAgICAgKiAtIFV0aWxpdHkgZnVuY3Rpb25zIChkZWVwTWVyZ2UpXG4gICAgICogLSBHZW5lcmF0ZWQgb3B0aW9ucyBpbnRlcmZhY2UgKHR5cGUtb25seSBpbXBvcnQpXG4gICAgICpcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIEdlbmVyYXRvciBjb25maWd1cmF0aW9uXG4gICAgICogQHBhcmFtIG9wdGlvbnNJbnRlcmZhY2UgLSBOYW1lIG9mIHRoZSBnZW5lcmF0ZWQgb3B0aW9ucyBpbnRlcmZhY2VcbiAgICAgKiBAcmV0dXJucyBNYXAgb2YgbW9kdWxlIHBhdGhzIHRvIHNldHMgb2YgaW1wb3J0ZWQgbmFtZXNcbiAgICAgKi9cbiAgICBwcml2YXRlIGV4dHJhY3RJbXBvcnRzKG9wdGlvbnM6IFByb2plY3RHZW5lcmF0b3JPcHRpb25zLCBvcHRpb25zSW50ZXJmYWNlOiBzdHJpbmcpOiBNYXA8c3RyaW5nLCBTZXQ8c3RyaW5nPj4ge1xuICAgICAgICBjb25zdCBpbXBvcnRzID0gbmV3IE1hcDxzdHJpbmcsIFNldDxzdHJpbmc+PigpO1xuXG4gICAgICAgIC8qIEV4dHJhY3QgYmFzZSBtb2R1bGUgbmFtZSBmcm9tIHByb2plY3RUeXBlIChlLmcuLCBcInR5cGVzY3JpcHRcIiBmcm9tIFwidHlwZXNjcmlwdC5UeXBlU2NyaXB0UHJvamVjdFwiKSAqL1xuICAgICAgICBjb25zdCBiYXNlTW9kdWxlID0gb3B0aW9ucy5wcm9qZWN0VHlwZS52YWx1ZU9mKCkuc3BsaXQoXCIuXCIpWzBdO1xuICAgICAgICBjb25zdCBvcHRpb25zRmlsZU5hbWUgPSB0aGlzLmdldE9wdGlvbnNGaWxlTmFtZShvcHRpb25zSW50ZXJmYWNlKTtcblxuICAgICAgICAvKiBQcm9qZW4gYmFzZSBtb2R1bGUgaW1wb3J0ICovXG4gICAgICAgIGltcG9ydHMuc2V0KFwicHJvamVuXCIsIG5ldyBTZXQoW2Jhc2VNb2R1bGVdKSk7XG5cbiAgICAgICAgLyogQ29uZmlndXJhdGlvbiB1dGlsaXRpZXMgaW1wb3J0ICovXG4gICAgICAgIGltcG9ydHMuc2V0KFwiLi4vY29uZmlnXCIsIG5ldyBTZXQoW1wiYXBwbHlEZWZhdWx0c1wiLCBcImRlZmF1bHRPcHRpb25zXCJdKSk7XG5cbiAgICAgICAgLyogQ29tcG9uZW50IGNsYXNzIGltcG9ydHMgLSBkZXJpdmUgbW9kdWxlIHBhdGggZnJvbSBjb21wb25lbnQgY2xhc3MgbmFtZSAqL1xuICAgICAgICBjb25zdCBjb21wb25lbnRzID0gb3B0aW9ucy5jb21wb25lbnRzID8/IERFRkFVTFRfQ09NUE9ORU5UUztcbiAgICAgICAgZm9yIChjb25zdCBjIG9mIGNvbXBvbmVudHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGNvbXBvbmVudE5hbWUgPSBjLmNvbXBvbmVudC5uYW1lO1xuICAgICAgICAgICAgY29uc3QgbW9kdWxlUGF0aCA9IGAuLi9jb21wb25lbnRzLyR7Y29tcG9uZW50TmFtZS50b0xvd2VyQ2FzZSgpfWA7XG4gICAgICAgICAgICBpZiAoIWltcG9ydHMuaGFzKG1vZHVsZVBhdGgpKSB7XG4gICAgICAgICAgICAgICAgaW1wb3J0cy5zZXQobW9kdWxlUGF0aCwgbmV3IFNldCgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG1vZHVsZUltcG9ydHMgPSBpbXBvcnRzLmdldChtb2R1bGVQYXRoKTtcbiAgICAgICAgICAgIGlmIChtb2R1bGVJbXBvcnRzKSB7XG4gICAgICAgICAgICAgICAgbW9kdWxlSW1wb3J0cy5hZGQoY29tcG9uZW50TmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvKiBVdGlsaXR5IGZ1bmN0aW9ucyBpbXBvcnQgKi9cbiAgICAgICAgaW1wb3J0cy5zZXQoXCIuLi91dGlsc1wiLCBuZXcgU2V0KFtcImRlZXBNZXJnZVwiXSkpO1xuXG4gICAgICAgIC8qIEdlbmVyYXRlZCBvcHRpb25zIGludGVyZmFjZSBpbXBvcnQgKHR5cGUtb25seSB0byBhdm9pZCBjaXJjdWxhciBkZXBlbmRlbmNpZXMpICovXG4gICAgICAgIGltcG9ydHMuc2V0KGAuLyR7b3B0aW9uc0ZpbGVOYW1lfS5nZW5lcmF0ZWRgLCBuZXcgU2V0KFtvcHRpb25zSW50ZXJmYWNlXSkpO1xuXG4gICAgICAgIHJldHVybiBpbXBvcnRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlcml2ZXMgdGhlIGNvbmZpZyBwYXRoIGZvciBhY2Nlc3NpbmcgZGVmYXVsdCBvcHRpb25zXG4gICAgICpcbiAgICAgKiBUcmFuc2Zvcm1zIHByb2plY3QgdHlwZSBpbnRvIHRoZSBjb3JyZXNwb25kaW5nIHBhdGggaW4gdGhlIGRlZmF1bHRPcHRpb25zXG4gICAgICogY29uZmlndXJhdGlvbiBvYmplY3QgZXhwb3J0ZWQgZnJvbSBjb25maWcudHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcHJvamVjdFR5cGUgLSBQcm9qZWN0IHR5cGUgaWRlbnRpZmllclxuICAgICAqIEByZXR1cm5zIENvbmZpZyBwYXRoIGZvciBhY2Nlc3NpbmcgZGVmYXVsdCBvcHRpb25zXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGdldENvbmZpZ1BhdGgoUHJvamVjdFR5cGUuVFlQRVNDUklQVCkgLy8gXCJkZWZhdWx0T3B0aW9ucy50eXBlc2NyaXB0LlR5cGVTY3JpcHRQcm9qZWN0XCJcbiAgICAgKi9cbiAgICBwcml2YXRlIGdldENvbmZpZ1BhdGgocHJvamVjdFR5cGU6IFByb2plY3RUeXBlKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIGBkZWZhdWx0T3B0aW9ucy4ke3Byb2plY3RUeXBlLnZhbHVlT2YoKX1gO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgaW1wb3J0IHN0YXRlbWVudHMgaW4gc29ydGVkIG9yZGVyXG4gICAgICpcbiAgICAgKiBTb3J0cyBpbXBvcnRzIHdpdGggZXh0ZXJuYWwgcGFja2FnZXMgZmlyc3QsIHRoZW4gcmVsYXRpdmUgaW1wb3J0cy5cbiAgICAgKiBVc2VzIHR5cGUtb25seSBpbXBvcnRzIGZvciBnZW5lcmF0ZWQgZmlsZXMgdG8gYXZvaWQgY2lyY3VsYXIgZGVwZW5kZW5jaWVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIGltcG9ydHMgLSBNYXAgb2YgbW9kdWxlIHBhdGhzIHRvIGltcG9ydGVkIG5hbWVzXG4gICAgICovXG4gICAgcHJpdmF0ZSByZW5kZXJJbXBvcnRzKGltcG9ydHM6IE1hcDxzdHJpbmcsIFNldDxzdHJpbmc+Pikge1xuICAgICAgICAvKiBTb3J0IG1vZHVsZXM6IGV4dGVybmFsIHBhY2thZ2VzIGZpcnN0LCB0aGVuIHJlbGF0aXZlIGltcG9ydHMgYWxwaGFiZXRpY2FsbHkgKi9cbiAgICAgICAgY29uc3Qgc29ydGVkTW9kdWxlcyA9IEFycmF5LmZyb20oaW1wb3J0cy5rZXlzKCkpLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGFJc1JlbGF0aXZlID0gYS5zdGFydHNXaXRoKFwiLlwiKTtcbiAgICAgICAgICAgIGNvbnN0IGJJc1JlbGF0aXZlID0gYi5zdGFydHNXaXRoKFwiLlwiKTtcbiAgICAgICAgICAgIGlmIChhSXNSZWxhdGl2ZSAhPT0gYklzUmVsYXRpdmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYUlzUmVsYXRpdmUgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYS5sb2NhbGVDb21wYXJlKGIpO1xuICAgICAgICB9KTtcblxuICAgICAgICBmb3IgKGNvbnN0IG1vZCBvZiBzb3J0ZWRNb2R1bGVzKSB7XG4gICAgICAgICAgICBjb25zdCBuYW1lcyA9IEFycmF5LmZyb20oaW1wb3J0cy5nZXQobW9kKSB8fCBbXSkuc29ydCgpO1xuICAgICAgICAgICAgLyogVXNlIHR5cGUtb25seSBpbXBvcnQgZm9yIGdlbmVyYXRlZCBmaWxlcyB0byBwcmV2ZW50IGNpcmN1bGFyIGRlcGVuZGVuY2llcyAqL1xuICAgICAgICAgICAgY29uc3QgaXNUeXBlT25seSA9IG1vZC5pbmNsdWRlcyhcIi5nZW5lcmF0ZWRcIik7XG4gICAgICAgICAgICBjb25zdCBpbXBvcnRTdG10ID0gaXNUeXBlT25seSA/IFwiaW1wb3J0IHR5cGVcIiA6IFwiaW1wb3J0XCI7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlci5saW5lKGAke2ltcG9ydFN0bXR9IHsgJHtuYW1lcy5qb2luKFwiLCBcIil9IH0gZnJvbSBcIiR7bW9kfVwiO2ApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyByZS1leHBvcnQgc3RhdGVtZW50IGZvciB0aGUgZ2VuZXJhdGVkIG9wdGlvbnMgaW50ZXJmYWNlXG4gICAgICpcbiAgICAgKiBAcGFyYW0gb3B0aW9uc0ludGVyZmFjZSAtIE5hbWUgb2YgdGhlIG9wdGlvbnMgaW50ZXJmYWNlIHRvIGV4cG9ydFxuICAgICAqL1xuICAgIHByaXZhdGUgcmVuZGVyRXhwb3J0KG9wdGlvbnNJbnRlcmZhY2U6IHN0cmluZykge1xuICAgICAgICBjb25zdCBvcHRpb25zRmlsZU5hbWUgPSB0aGlzLmdldE9wdGlvbnNGaWxlTmFtZShvcHRpb25zSW50ZXJmYWNlKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZSgpO1xuICAgICAgICB0aGlzLmJ1ZmZlci5saW5lKGBleHBvcnQgeyAke29wdGlvbnNJbnRlcmZhY2V9IH0gZnJvbSBcIi4vJHtvcHRpb25zRmlsZU5hbWV9LmdlbmVyYXRlZFwiO2ApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGNsYXNzIGRlY2xhcmF0aW9uIGFuZCBjb25zdHJ1Y3RvclxuICAgICAqXG4gICAgICogQHBhcmFtIG9wdGlvbnMgLSBHZW5lcmF0b3IgY29uZmlndXJhdGlvblxuICAgICAqIEBwYXJhbSBvcHRpb25zSW50ZXJmYWNlIC0gTmFtZSBvZiB0aGUgb3B0aW9ucyBpbnRlcmZhY2VcbiAgICAgKiBAcGFyYW0gYmFzZU9wdGlvbnNUeXBlIC0gQmFzZSBvcHRpb25zIHR5cGUgd2l0aG91dCBcInByb2plbi5cIiBwcmVmaXhcbiAgICAgKiBAcGFyYW0gZGVzdHJ1Y3R1cmUgLSBWYXJpYWJsZSBuYW1lcyB0byBkZXN0cnVjdHVyZSBmcm9tIG9wdGlvbnNcbiAgICAgKiBAcGFyYW0gY29tcG9uZW50QXJyYXkgLSBDb2RlIHN0cmluZyBmb3IgY29tcG9uZW50IGFycmF5XG4gICAgICovXG4gICAgcHJpdmF0ZSByZW5kZXJDbGFzcyhcbiAgICAgICAgb3B0aW9uczogUHJvamVjdEdlbmVyYXRvck9wdGlvbnMsXG4gICAgICAgIG9wdGlvbnNJbnRlcmZhY2U6IHN0cmluZyxcbiAgICAgICAgYmFzZU9wdGlvbnNUeXBlOiBzdHJpbmcsXG4gICAgICAgIGRlc3RydWN0dXJlOiBzdHJpbmdbXSxcbiAgICAgICAgY29tcG9uZW50QXJyYXk6IHN0cmluZyxcbiAgICApIHtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZSgpO1xuICAgICAgICB0aGlzLmJ1ZmZlci5saW5lKFwiLyoqXCIpO1xuICAgICAgICB0aGlzLmJ1ZmZlci5saW5lKGAgKiAke29wdGlvbnMubmFtZX0gd2l0aCBzdGFuZGFyZCBjb25maWd1cmF0aW9uIGFuZCBjb21wb25lbnQgaW50ZWdyYXRpb25gKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZShcIiAqXCIpO1xuICAgICAgICB0aGlzLmJ1ZmZlci5saW5lKFwiICogRXh0ZW5kcyBQcm9qZW4ncyBiYXNlIGNsYXNzIHdpdGggb3BpbmlvbmF0ZWQgZGVmYXVsdHMgYW5kIGF1dG9tYXRpYyBjb21wb25lbnQgc2V0dXAuXCIpO1xuICAgICAgICB0aGlzLmJ1ZmZlci5saW5lKFwiICovXCIpO1xuICAgICAgICB0aGlzLmJ1ZmZlci5vcGVuKGBleHBvcnQgY2xhc3MgJHtvcHRpb25zLm5hbWV9IGV4dGVuZHMgJHtvcHRpb25zLnByb2plY3RUeXBlLnZhbHVlT2YoKX0ge2ApO1xuICAgICAgICB0aGlzLnJlbmRlckNvbnN0cnVjdG9yKG9wdGlvbnMsIG9wdGlvbnNJbnRlcmZhY2UsIGJhc2VPcHRpb25zVHlwZSwgZGVzdHJ1Y3R1cmUsIGNvbXBvbmVudEFycmF5KTtcbiAgICAgICAgdGhpcy5idWZmZXIuY2xvc2UoXCJ9XCIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGNvbnN0cnVjdG9yIGltcGxlbWVudGF0aW9uXG4gICAgICpcbiAgICAgKiBUaGUgY29uc3RydWN0b3I6XG4gICAgICogMS4gRGVzdHJ1Y3R1cmVzIGNvbXBvbmVudCBmbGFncyBhbmQgb3B0aW9ucyBmcm9tIHRoZSBvcHRpb25zIHBhcmFtZXRlclxuICAgICAqIDIuIE1lcmdlcyBkZWZhdWx0IGNvbmZpZ3VyYXRpb24gd2l0aCB1c2VyLXByb3ZpZGVkIG9wdGlvbnNcbiAgICAgKiAzLiBDYWxscyBzdXBlcigpIHdpdGggbWVyZ2VkIG9wdGlvbnNcbiAgICAgKiA0LiBBcHBsaWVzIGNvbXBvbmVudCBkZWZhdWx0cyB2aWEgYXBwbHlEZWZhdWx0cygpXG4gICAgICpcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIEdlbmVyYXRvciBjb25maWd1cmF0aW9uXG4gICAgICogQHBhcmFtIG9wdGlvbnNJbnRlcmZhY2UgLSBOYW1lIG9mIHRoZSBvcHRpb25zIGludGVyZmFjZVxuICAgICAqIEBwYXJhbSBiYXNlT3B0aW9uc1R5cGUgLSBCYXNlIG9wdGlvbnMgdHlwZSB3aXRob3V0IFwicHJvamVuLlwiIHByZWZpeFxuICAgICAqIEBwYXJhbSBkZXN0cnVjdHVyZSAtIFZhcmlhYmxlIG5hbWVzIHRvIGRlc3RydWN0dXJlIGZyb20gb3B0aW9uc1xuICAgICAqIEBwYXJhbSBjb21wb25lbnRBcnJheSAtIENvZGUgc3RyaW5nIGZvciBjb21wb25lbnQgYXJyYXlcbiAgICAgKi9cbiAgICBwcml2YXRlIHJlbmRlckNvbnN0cnVjdG9yKFxuICAgICAgICBvcHRpb25zOiBQcm9qZWN0R2VuZXJhdG9yT3B0aW9ucyxcbiAgICAgICAgb3B0aW9uc0ludGVyZmFjZTogc3RyaW5nLFxuICAgICAgICBiYXNlT3B0aW9uc1R5cGU6IHN0cmluZyxcbiAgICAgICAgZGVzdHJ1Y3R1cmU6IHN0cmluZ1tdLFxuICAgICAgICBjb21wb25lbnRBcnJheTogc3RyaW5nLFxuICAgICkge1xuICAgICAgICBjb25zdCBjb25maWdQYXRoID0gdGhpcy5nZXRDb25maWdQYXRoKG9wdGlvbnMucHJvamVjdFR5cGUpO1xuICAgICAgICB0aGlzLmJ1ZmZlci5saW5lKFwiLyoqXCIpO1xuICAgICAgICB0aGlzLmJ1ZmZlci5saW5lKFwiICogQHBhcmFtIG9wdGlvbnMgLSBQcm9qZWN0IGNvbmZpZ3VyYXRpb25cIik7XG4gICAgICAgIHRoaXMuYnVmZmVyLmxpbmUoXCIgKi9cIik7XG4gICAgICAgIHRoaXMuYnVmZmVyLm9wZW4oYGNvbnN0cnVjdG9yKG9wdGlvbnM6ICR7b3B0aW9uc0ludGVyZmFjZX0pIHtgKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZShcIi8qIFNlcGFyYXRlIGNvbXBvbmVudCBjb25maWd1cmF0aW9uIGZyb20gYmFzZSBQcm9qZW4gb3B0aW9ucyAqL1wiKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZShgY29uc3QgeyAke2Rlc3RydWN0dXJlLmpvaW4oXCIsIFwiKX0sIC4uLmJhc2VPcHRpb25zIH0gPSBvcHRpb25zO2ApO1xuICAgICAgICB0aGlzLmJ1ZmZlci5saW5lKCk7XG4gICAgICAgIHRoaXMuYnVmZmVyLmxpbmUoXCIvKiBNZXJnZSBkZWZhdWx0IGNvbmZpZ3VyYXRpb24gd2l0aCB1c2VyIG9wdGlvbnMgYW5kIGluaXRpYWxpemUgYmFzZSBjbGFzcyAqL1wiKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZShgc3VwZXIoZGVlcE1lcmdlPCR7YmFzZU9wdGlvbnNUeXBlfT4oJHtjb25maWdQYXRofSwgYmFzZU9wdGlvbnMpKTtgKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZSgpO1xuICAgICAgICB0aGlzLmJ1ZmZlci5saW5lKFwiLyogQXBwbHkgY29tcG9uZW50IGRlZmF1bHRzIGFuZCBpbnN0YW50aWF0ZSBlbmFibGVkIGNvbXBvbmVudHMgKi9cIik7XG4gICAgICAgIHRoaXMuYnVmZmVyLmxpbmUoYGFwcGx5RGVmYXVsdHModGhpcywgJHtjb21wb25lbnRBcnJheX0pO2ApO1xuICAgICAgICB0aGlzLmJ1ZmZlci5jbG9zZShcIn1cIik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFwcyBvcHRpb25zIGludGVyZmFjZSBuYW1lIHRvIGZpbGUgbmFtZVxuICAgICAqXG4gICAgICogQ29udmVydHMgUGFzY2FsQ2FzZSBpbnRlcmZhY2UgbmFtZXMgdG8ga2ViYWItY2FzZSBmaWxlIG5hbWVzLlxuICAgICAqIEZhbGxzIGJhY2sgdG8gbG93ZXJjYXNlIGNvbnZlcnNpb24gZm9yIHVubWFwcGVkIGludGVyZmFjZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gb3B0aW9uc0ludGVyZmFjZSAtIE9wdGlvbnMgaW50ZXJmYWNlIG5hbWVcbiAgICAgKiBAcmV0dXJucyBLZWJhYi1jYXNlIGZpbGUgbmFtZSB3aXRob3V0IGV4dGVuc2lvblxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBnZXRPcHRpb25zRmlsZU5hbWUoXCJUeXBlU2NyaXB0UHJvamVjdE9wdGlvbnNcIikgLy8gXCJ0eXBlc2NyaXB0LW9wdGlvbnNcIlxuICAgICAqL1xuICAgIGdldE9wdGlvbnNGaWxlTmFtZShvcHRpb25zSW50ZXJmYWNlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCBtYXBwaW5nOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgICAgICAgICAgVHlwZVNjcmlwdFByb2plY3RPcHRpb25zOiBcInR5cGVzY3JpcHQtb3B0aW9uc1wiLFxuICAgICAgICAgICAgSnNpaVByb2plY3RPcHRpb25zOiBcImpzaWktb3B0aW9uc1wiLFxuICAgICAgICAgICAgQXdzQ2RrVHlwZVNjcmlwdEFwcFByb2plY3RPcHRpb25zOiBcImF3c2Nkay10eXBlc2NyaXB0LWFwcC1vcHRpb25zXCIsXG4gICAgICAgICAgICBBd3NDZGtDb25zdHJ1Y3RMaWJyYXJ5UHJvamVjdE9wdGlvbnM6IFwiYXdzY2RrLWNvbnN0cnVjdC1saWJyYXJ5LW9wdGlvbnNcIixcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIG1hcHBpbmdbb3B0aW9uc0ludGVyZmFjZV0gfHwgb3B0aW9uc0ludGVyZmFjZS50b0xvd2VyQ2FzZSgpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBQcm9qZW4gY29tcG9uZW50IHRoYXQgZ2VuZXJhdGVzIFR5cGVTY3JpcHQgcHJvamVjdCBjbGFzc2VzIHdpdGggc3RhbmRhcmQgY29uZmlndXJhdGlvblxuICpcbiAqIFRoaXMgY29tcG9uZW50IGF1dG9tYXRlcyB0aGUgY3JlYXRpb24gb2YgcHJvamVjdCBjbGFzc2VzIHRoYXQgZXh0ZW5kIFByb2plbiBiYXNlIGNsYXNzZXNcbiAqIHdpdGggb3BpbmlvbmF0ZWQgZGVmYXVsdHMgYW5kIGNvbXBvbmVudCBpbnRlZ3JhdGlvbi4gSXQgZ2VuZXJhdGVzIGJvdGg6XG4gKiAxLiBBbiBvcHRpb25zIGludGVyZmFjZSAodmlhIFByb2plblN0cnVjdCkgdGhhdCBleHRlbmRzIHRoZSBiYXNlIFByb2plbiBvcHRpb25zXG4gKiAyLiBBIHByb2plY3QgY2xhc3MgdGhhdCBhcHBsaWVzIGRlZmF1bHQgY29uZmlndXJhdGlvbiBhbmQgaW5zdGFudGlhdGVzIGNvbXBvbmVudHNcbiAqXG4gKiBUaGUgZ2VuZXJhdGVkIGNvZGUgZm9sbG93cyBhIGNvbnNpc3RlbnQgcGF0dGVybjpcbiAqIC0gSW1wb3J0cyByZXF1aXJlZCBtb2R1bGVzIGFuZCBjb21wb25lbnRzXG4gKiAtIFJlLWV4cG9ydHMgdGhlIGdlbmVyYXRlZCBvcHRpb25zIGludGVyZmFjZVxuICogLSBEZWZpbmVzIGEgY2xhc3MgZXh0ZW5kaW5nIHRoZSBQcm9qZW4gYmFzZSBjbGFzc1xuICogLSBDb25zdHJ1Y3RvciBtZXJnZXMgZGVmYXVsdHMgd2l0aCB1c2VyIG9wdGlvbnMgYW5kIGFwcGxpZXMgY29tcG9uZW50c1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBuZXcgUHJvamVjdEdlbmVyYXRvcihwcm9qZWN0LCB7XG4gKiAgIG5hbWU6IFwiVHlwZVNjcmlwdFByb2plY3RcIixcbiAqICAgYmFzZUNsYXNzOiBcInR5cGVzY3JpcHQuVHlwZVNjcmlwdFByb2plY3RcIixcbiAqICAgZmlsZVBhdGg6IFwic3JjL3Byb2plY3RzL3R5cGVzY3JpcHQuZ2VuZXJhdGVkLnRzXCIsXG4gKiAgIGNvbXBvbmVudHM6IFt7IGNvbXBvbmVudDogVml0ZXN0LCBvcHRpb25zUHJvcGVydHk6IFwidml0ZXN0T3B0aW9uc1wiIH1dXG4gKiB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgUHJvamVjdEdlbmVyYXRvciBleHRlbmRzIENvbXBvbmVudCB7XG4gICAgcHJpdmF0ZSByZW5kZXJlcjogVHlwZVNjcmlwdENsYXNzUmVuZGVyZXI7XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gcHJvamVjdCAtIFByb2plbiBwcm9qZWN0IGluc3RhbmNlXG4gICAgICogQHBhcmFtIG9wdGlvbnMgLSBHZW5lcmF0b3IgY29uZmlndXJhdGlvblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcm9qZWN0OiBQcm9qZWN0LFxuICAgICAgICBwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnM6IFByb2plY3RHZW5lcmF0b3JPcHRpb25zLFxuICAgICkge1xuICAgICAgICBzdXBlcihwcm9qZWN0KTtcbiAgICAgICAgdGhpcy5yZW5kZXJlciA9IG5ldyBUeXBlU2NyaXB0Q2xhc3NSZW5kZXJlcigpO1xuXG4gICAgICAgIC8qIEdlbmVyYXRlIHRoZSBvcHRpb25zIGludGVyZmFjZSB1c2luZyBQcm9qZW5TdHJ1Y3QgZm9yIEpTSUkgY29tcGF0aWJpbGl0eSAqL1xuICAgICAgICBjb25zdCBvcHRpb25zSW50ZXJmYWNlID0gYCR7b3B0aW9ucy5uYW1lfU9wdGlvbnNgO1xuICAgICAgICBjb25zdCBiYXNlT3B0aW9uc0ZxbiA9IHRoaXMucmVuZGVyZXIuZ2V0QmFzZU9wdGlvbnNGcW4ob3B0aW9ucy5wcm9qZWN0VHlwZSk7XG4gICAgICAgIGNvbnN0IG9wdGlvbnNGaWxlUGF0aCA9IHRoaXMuZ2V0T3B0aW9uc0ZpbGVQYXRoKG9wdGlvbnNJbnRlcmZhY2UpO1xuXG4gICAgICAgIC8qIFByb2plblN0cnVjdCBnZW5lcmF0ZXMgYSBjb25jcmV0ZSBUeXBlU2NyaXB0IGludGVyZmFjZSBmcm9tIFByb2plbidzIG9wdGlvbnNcbiAgICAgICAgICogVGhpcyBpcyBuZWNlc3NhcnkgYmVjYXVzZSBKU0lJIGRvZXNuJ3Qgc3VwcG9ydCBUeXBlU2NyaXB0IHV0aWxpdHkgdHlwZXMgbGlrZSBPbWl0PD5cbiAgICAgICAgICogVGhlIGdlbmVyYXRlZCBpbnRlcmZhY2UgY2FuIGJlIGNvbnN1bWVkIGJ5IG90aGVyIGxhbmd1YWdlcyAoUHl0aG9uLCBKYXZhLCBDIywgR28pICovXG4gICAgICAgIGNvbnN0IHN0cnVjdCA9IG5ldyBQcm9qZW5TdHJ1Y3QodGhpcy5hc1R5cGVTY3JpcHRQcm9qZWN0KHByb2plY3QpLCB7XG4gICAgICAgICAgICBuYW1lOiBvcHRpb25zSW50ZXJmYWNlLFxuICAgICAgICAgICAgZmlsZVBhdGg6IG9wdGlvbnNGaWxlUGF0aCxcbiAgICAgICAgICAgIG91dHB1dEZpbGVPcHRpb25zOiB7IHJlYWRvbmx5OiB0cnVlIH0sXG4gICAgICAgIH0pXG4gICAgICAgICAgICAubWl4aW4oU3RydWN0LmZyb21GcW4oYmFzZU9wdGlvbnNGcW4pKVxuICAgICAgICAgICAgLndpdGhvdXREZXByZWNhdGVkKCk7XG5cbiAgICAgICAgLyogUmVtb3ZlIHNwZWNpZmllZCBvcHRpb25zIGZyb20gdGhlIGJhc2UgaW50ZXJmYWNlICovXG4gICAgICAgIGlmIChvcHRpb25zLm9taXRPcHRpb25zKSB7XG4gICAgICAgICAgICBzdHJ1Y3Qub21pdCguLi5vcHRpb25zLm9taXRPcHRpb25zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qIEFkZCBjb21wb25lbnQtZGVyaXZlZCBvcHRpb25zIHRvIHRoZSBpbnRlcmZhY2UgKi9cbiAgICAgICAgY29uc3QgY29tcG9uZW50cyA9IG9wdGlvbnMuY29tcG9uZW50cyA/PyBERUZBVUxUX0NPTVBPTkVOVFM7XG4gICAgICAgIGNvbnN0IHsgUHJpbWl0aXZlVHlwZSB9ID0gcmVxdWlyZShcIkBqc2lpL3NwZWNcIik7XG5cbiAgICAgICAgZm9yIChjb25zdCBjIG9mIGNvbXBvbmVudHMpIHtcbiAgICAgICAgICAgIGNvbnN0IG5hbWUgPSBjLmNvbXBvbmVudC5uYW1lLmNoYXJBdCgwKS50b0xvd2VyQ2FzZSgpICsgYy5jb21wb25lbnQubmFtZS5zbGljZSgxKTtcblxuICAgICAgICAgICAgLyogQWRkIGVuYWJsZWQgZmxhZyBmb3IgdGhlIGNvbXBvbmVudCAqL1xuICAgICAgICAgICAgc3RydWN0LmFkZCh7XG4gICAgICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgICAgICB0eXBlOiB7IHByaW1pdGl2ZTogUHJpbWl0aXZlVHlwZS5Cb29sZWFuIH0sXG4gICAgICAgICAgICAgICAgb3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgICAgZG9jczoge1xuICAgICAgICAgICAgICAgICAgICBzdW1tYXJ5OiBgRW5hYmxlICR7Yy5jb21wb25lbnQubmFtZX0gY29tcG9uZW50YCxcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDogXCJ0cnVlXCIsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvKiBBZGQgb3B0aW9ucyBwcm9wZXJ0eSBpZiBjb21wb25lbnQgaXMgY29uZmlndXJhYmxlICovXG4gICAgICAgICAgICBpZiAoYy5vcHRpb25zUHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICBzdHJ1Y3QuYWRkKHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogYy5vcHRpb25zUHJvcGVydHkubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogeyBmcW46IGMub3B0aW9uc1Byb3BlcnR5LnR5cGUgfSxcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIGRvY3M6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcnk6IGMub3B0aW9uc1Byb3BlcnR5LmRvY3MgPz8gYCR7Yy5jb21wb25lbnQubmFtZX0gY29uZmlndXJhdGlvbmAsXG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OiBgLSBkZWZhdWx0ICR7Yy5jb21wb25lbnQubmFtZX0gY29uZmlndXJhdGlvbmAsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvKiBBZGQgY3VzdG9tIG9wdGlvbnMgdG8gdGhlIGludGVyZmFjZSAqL1xuICAgICAgICBpZiAob3B0aW9ucy5hZGRpdGlvbmFsT3B0aW9ucykge1xuICAgICAgICAgICAgc3RydWN0LmFkZCguLi5vcHRpb25zLmFkZGl0aW9uYWxPcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhc3RzIHByb2plY3QgdG8gVHlwZVNjcmlwdCBwcm9qZWN0IHR5cGVcbiAgICAgKlxuICAgICAqIFByb2plblN0cnVjdCByZXF1aXJlcyBhIFR5cGVTY3JpcHRQcm9qZWN0IGluc3RhbmNlLiBUaGlzIGdlbmVyYXRvciBpcyBvbmx5IHVzZWRcbiAgICAgKiB3aXRoaW4gVHlwZVNjcmlwdCBwcm9qZWN0cywgc28gdGhlIGNhc3QgaXMgc2FmZSBpbiBwcmFjdGljZS5cbiAgICAgKlxuICAgICAqIE5vdGU6IFR5cGUgYXNzZXJ0aW9uIGlzIG5lY2Vzc2FyeSBoZXJlIGJlY2F1c2UgUHJvamVuJ3MgdHlwZSBzeXN0ZW0gZG9lc24ndCBwcm92aWRlXG4gICAgICogYSBydW50aW1lIHR5cGUgZ3VhcmQgZm9yIFR5cGVTY3JpcHRQcm9qZWN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHByb2plY3QgLSBQcm9qZW4gcHJvamVjdCBpbnN0YW5jZVxuICAgICAqIEByZXR1cm5zIFR5cGVTY3JpcHQgcHJvamVjdCBpbnN0YW5jZVxuICAgICAqL1xuICAgIHByaXZhdGUgYXNUeXBlU2NyaXB0UHJvamVjdChwcm9qZWN0OiBQcm9qZWN0KTogdHlwZXNjcmlwdC5UeXBlU2NyaXB0UHJvamVjdCB7XG4gICAgICAgIHJldHVybiBwcm9qZWN0IGFzIHVua25vd24gYXMgdHlwZXNjcmlwdC5UeXBlU2NyaXB0UHJvamVjdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZXJpdmVzIHRoZSBmaWxlIHBhdGggZm9yIHRoZSBnZW5lcmF0ZWQgb3B0aW9ucyBpbnRlcmZhY2VcbiAgICAgKlxuICAgICAqIFBsYWNlcyB0aGUgb3B0aW9ucyBpbnRlcmZhY2UgZmlsZSBpbiB0aGUgc2FtZSBkaXJlY3RvcnkgYXMgdGhlIGNsYXNzIGZpbGVcbiAgICAgKiB3aXRoIGEgXCIuZ2VuZXJhdGVkLnRzXCIgc3VmZml4LlxuICAgICAqXG4gICAgICogQHBhcmFtIG9wdGlvbnNJbnRlcmZhY2UgLSBOYW1lIG9mIHRoZSBvcHRpb25zIGludGVyZmFjZVxuICAgICAqIEByZXR1cm5zIEZpbGUgcGF0aCBmb3IgdGhlIG9wdGlvbnMgaW50ZXJmYWNlXG4gICAgICogQHRocm93cyB7SW52YWxpZEZpbGVQYXRoRXJyb3J9IFdoZW4gZmlsZVBhdGggZG9lc24ndCBjb250YWluIGEgZGlyZWN0b3J5IHNlcGFyYXRvclxuICAgICAqL1xuICAgIHByaXZhdGUgZ2V0T3B0aW9uc0ZpbGVQYXRoKG9wdGlvbnNJbnRlcmZhY2U6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IGxhc3RTbGFzaCA9IHRoaXMub3B0aW9ucy5maWxlUGF0aC5sYXN0SW5kZXhPZihcIi9cIik7XG4gICAgICAgIGlmIChsYXN0U2xhc2ggPT09IC0xKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgSW52YWxpZEZpbGVQYXRoRXJyb3IodGhpcy5vcHRpb25zLmZpbGVQYXRoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGRpciA9IHRoaXMub3B0aW9ucy5maWxlUGF0aC5zdWJzdHJpbmcoMCwgbGFzdFNsYXNoKTtcbiAgICAgICAgY29uc3Qgb3B0aW9uc0ZpbGVOYW1lID0gdGhpcy5yZW5kZXJlci5nZXRPcHRpb25zRmlsZU5hbWUob3B0aW9uc0ludGVyZmFjZSk7XG4gICAgICAgIHJldHVybiBgJHtkaXJ9LyR7b3B0aW9uc0ZpbGVOYW1lfS5nZW5lcmF0ZWQudHNgO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlcyB0aGUgVHlwZVNjcmlwdCBjbGFzcyBmaWxlIGR1cmluZyBQcm9qZW4gc3ludGhlc2lzXG4gICAgICpcbiAgICAgKiBDYWxsZWQgYnkgUHJvamVuIGR1cmluZyB0aGUgc3ludGhlc2lzIHBoYXNlIHRvIGdlbmVyYXRlIHRoZSBwcm9qZWN0IGNsYXNzIGZpbGUuXG4gICAgICogVGhlIGZpbGUgaXMgbWFya2VkIGFzIHJlYWRvbmx5IHRvIHByZXZlbnQgbWFudWFsIGVkaXRpbmcuXG4gICAgICovXG4gICAgcHJlU3ludGhlc2l6ZSgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY29udGVudCA9IHRoaXMucmVuZGVyZXIucmVuZGVyKHRoaXMub3B0aW9ucyk7XG5cbiAgICAgICAgbmV3IFR5cGVTY3JpcHRDbGFzc0ZpbGUodGhpcy5wcm9qZWN0LCB0aGlzLm9wdGlvbnMuZmlsZVBhdGgsIGNvbnRlbnQsIHtcbiAgICAgICAgICAgIHJlYWRvbmx5OiB0aGlzLm9wdGlvbnMucmVhZG9ubHkgPz8gdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG4vKipcbiAqIFRleHQgZmlsZSBmb3IgZ2VuZXJhdGVkIFR5cGVTY3JpcHQgY2xhc3MgY29kZVxuICpcbiAqIEV4dGVuZHMgUHJvamVuJ3MgVGV4dEZpbGUgdG8gYWRkIHRoZSBnZW5lcmF0ZWQgZmlsZSBtYXJrZXIgY29tbWVudFxuICogYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgZmlsZS5cbiAqL1xuY2xhc3MgVHlwZVNjcmlwdENsYXNzRmlsZSBleHRlbmRzIFRleHRGaWxlIHtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gcHJvamVjdCAtIFByb2plbiBwcm9qZWN0IGluc3RhbmNlXG4gICAgICogQHBhcmFtIGZpbGVQYXRoIC0gT3V0cHV0IGZpbGUgcGF0aFxuICAgICAqIEBwYXJhbSBjb250ZW50IC0gVHlwZVNjcmlwdCBjbGFzcyBjb2RlXG4gICAgICogQHBhcmFtIG9wdGlvbnMgLSBTb3VyY2UgY29kZSBvcHRpb25zIChyZWFkb25seSwgZXRjLilcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihwcm9qZWN0OiBQcm9qZWN0LCBmaWxlUGF0aDogc3RyaW5nLCBjb250ZW50OiBzdHJpbmcsIG9wdGlvbnM6IFNvdXJjZUNvZGVPcHRpb25zID0ge30pIHtcbiAgICAgICAgc3VwZXIocHJvamVjdCwgZmlsZVBhdGgsIG9wdGlvbnMpO1xuICAgICAgICAvKiBBZGQgZ2VuZXJhdGVkIGZpbGUgbWFya2VyIHRvIHByZXZlbnQgbWFudWFsIGVkaXRpbmcgKi9cbiAgICAgICAgdGhpcy5hZGRMaW5lKGAvLyAke3RoaXMubWFya2VyfWApO1xuICAgICAgICB0aGlzLmFkZExpbmUoY29udGVudCk7XG4gICAgfVxufVxuIl19
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Enum defining all supported project types
3
+ *
4
+ * Each project type corresponds to a generated project class and its configuration
5
+ * in the defaultOptions structure.
6
+ */
7
+ export declare enum ProjectType {
8
+ /**
9
+ * TypeScript project with ES modules support
10
+ *
11
+ * @see https://projen.io/docs/api/typescript#typescriptproject-
12
+ */
13
+ TYPESCRIPT = "typescript.TypeScriptProject",
14
+ /**
15
+ * JSII project for publishing multi-language libraries
16
+ *
17
+ * @see https://projen.io/docs/api/cdk#jsiiproject-
18
+ */
19
+ JSII = "cdk.JsiiProject",
20
+ /**
21
+ * AWS CDK TypeScript application project with ES modules support
22
+ *
23
+ * @see https://projen.io/docs/api/awscdk#awscdktypescriptapp-
24
+ */
25
+ AWS_CDK_TYPESCRIPT_APP = "awscdk.AwsCdkTypeScriptApp",
26
+ /**
27
+ * AWS CDK construct library project for publishing reusable constructs
28
+ *
29
+ * @see https://projen.io/docs/api/awscdk/#awscdkconstructlibrary-
30
+ */
31
+ AWS_CDK_CONSTRUCT_LIBRARY = "awscdk.AwsCdkConstructLibrary"
32
+ }