@nikovirtala/projen-constructs 0.1.5 → 0.1.6
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.
- package/.jsii +54 -34
- package/API.md +52 -28
- package/lib/components/mise.js +4 -2
- package/lib/components/vitest.js +1 -1
- package/lib/config.d.ts +20 -7
- package/lib/config.js +28 -16
- package/lib/errors.d.ts +20 -0
- package/lib/errors.js +36 -0
- package/lib/projects/awscdk-construct-library-options.generated.d.ts +7 -7
- package/lib/projects/awscdk-construct-library-options.generated.js +1 -1
- package/lib/projects/awscdk-construct-library.generated.d.ts +8 -0
- package/lib/projects/awscdk-construct-library.generated.js +17 -4
- package/lib/projects/awscdk-typescript-app-options.generated.d.ts +7 -7
- package/lib/projects/awscdk-typescript-app-options.generated.js +1 -1
- package/lib/projects/awscdk-typescript-app.generated.d.ts +8 -0
- package/lib/projects/awscdk-typescript-app.generated.js +17 -4
- package/lib/projects/jsii-options.generated.d.ts +7 -7
- package/lib/projects/jsii-options.generated.js +1 -1
- package/lib/projects/jsii.generated.d.ts +8 -0
- package/lib/projects/jsii.generated.js +17 -4
- package/lib/projects/typescript-options.generated.d.ts +7 -7
- package/lib/projects/typescript-options.generated.js +1 -1
- package/lib/projects/typescript.generated.d.ts +8 -0
- package/lib/projects/typescript.generated.js +17 -4
- package/lib/projen-project-generator.d.ts +173 -0
- package/lib/projen-project-generator.js +509 -0
- package/package.json +1 -1
- package/lib/projen-project-class.d.ts +0 -44
- package/lib/projen-project-class.js +0 -137
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProjenProjectGenerator = 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 ProjenProjectGenerator 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.baseClass);
|
|
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 base class
|
|
133
|
+
*
|
|
134
|
+
* Transforms base class reference into the corresponding Projen options interface name
|
|
135
|
+
* by appending "Options" suffix and prefixing with "projen." namespace.
|
|
136
|
+
*
|
|
137
|
+
* @param baseClass - Base class in format "module.ClassName"
|
|
138
|
+
* @returns Fully qualified options interface name
|
|
139
|
+
* @throws {InvalidBaseClassFormatError} When baseClass format is invalid
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* getBaseOptionsFqn("typescript.TypeScriptProject") // "projen.typescript.TypeScriptProjectOptions"
|
|
143
|
+
* getBaseOptionsFqn("cdk.JsiiProject") // "projen.cdk.JsiiProjectOptions"
|
|
144
|
+
*/
|
|
145
|
+
getBaseOptionsFqn(baseClass) {
|
|
146
|
+
/* Validate base class format: must contain module.ClassName structure */
|
|
147
|
+
if (!baseClass.includes(".")) {
|
|
148
|
+
throw new errors_1.InvalidBaseClassFormatError(baseClass);
|
|
149
|
+
}
|
|
150
|
+
return `projen.${baseClass}Options`;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Extracts component configuration for constructor code generation
|
|
154
|
+
*
|
|
155
|
+
* Transforms component configurations into:
|
|
156
|
+
* 1. Destructure list: variable names to extract from options
|
|
157
|
+
* 2. Component array: code string for applyDefaults() call
|
|
158
|
+
*
|
|
159
|
+
* @param components - Component configurations
|
|
160
|
+
* @returns Object with destructure array and componentArray code string
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* Input: [{ component: Vitest, optionsProperty: { name: "vitestOptions", ... } }]
|
|
164
|
+
* Output: {
|
|
165
|
+
* destructure: ["vitest", "vitestOptions"],
|
|
166
|
+
* componentArray: "[{ component: Vitest, enabled: vitest, options: vitestOptions }]"
|
|
167
|
+
* }
|
|
168
|
+
*/
|
|
169
|
+
extractComponentOptions(components) {
|
|
170
|
+
const destructure = [];
|
|
171
|
+
const componentParts = [];
|
|
172
|
+
for (const c of components) {
|
|
173
|
+
/* Convert component class name to camelCase variable name (e.g., Vitest -> vitest) */
|
|
174
|
+
const name = c.component.name.charAt(0).toLowerCase() + c.component.name.slice(1);
|
|
175
|
+
destructure.push(name);
|
|
176
|
+
/* Build component config object for applyDefaults() call */
|
|
177
|
+
const parts = [`component: ${c.component.name}`];
|
|
178
|
+
if (c.optionsProperty) {
|
|
179
|
+
/* Component has configurable options - include both enabled flag and options */
|
|
180
|
+
destructure.push(c.optionsProperty.name);
|
|
181
|
+
parts.push(`enabled: ${name}`, `options: ${c.optionsProperty.name}`);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
/* Component has no options - only include enabled flag */
|
|
185
|
+
parts.push(`enabled: ${name}`);
|
|
186
|
+
}
|
|
187
|
+
componentParts.push(`{ ${parts.join(", ")} }`);
|
|
188
|
+
}
|
|
189
|
+
return { destructure, componentArray: `[${componentParts.join(", ")}]` };
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Builds import statements map for the generated class
|
|
193
|
+
*
|
|
194
|
+
* Collects all required imports:
|
|
195
|
+
* - Projen base module (typescript, cdk, awscdk)
|
|
196
|
+
* - Config utilities (applyDefaults, defaultOptions)
|
|
197
|
+
* - Component classes
|
|
198
|
+
* - Utility functions (deepMerge)
|
|
199
|
+
* - Generated options interface (type-only import)
|
|
200
|
+
*
|
|
201
|
+
* @param options - Generator configuration
|
|
202
|
+
* @param optionsInterface - Name of the generated options interface
|
|
203
|
+
* @returns Map of module paths to sets of imported names
|
|
204
|
+
*/
|
|
205
|
+
extractImports(options, optionsInterface) {
|
|
206
|
+
const imports = new Map();
|
|
207
|
+
/* Extract base module name from baseClass (e.g., "typescript" from "typescript.TypeScriptProject") */
|
|
208
|
+
const baseModule = options.baseClass.split(".")[0];
|
|
209
|
+
const optionsFileName = this.getOptionsFileName(optionsInterface);
|
|
210
|
+
/* Projen base module import */
|
|
211
|
+
imports.set("projen", new Set([baseModule]));
|
|
212
|
+
/* Configuration utilities import */
|
|
213
|
+
imports.set("../config", new Set(["applyDefaults", "defaultOptions"]));
|
|
214
|
+
/* Component class imports - derive module path from component class name */
|
|
215
|
+
const components = options.components ?? DEFAULT_COMPONENTS;
|
|
216
|
+
for (const c of components) {
|
|
217
|
+
const componentName = c.component.name;
|
|
218
|
+
const modulePath = `../components/${componentName.toLowerCase()}`;
|
|
219
|
+
if (!imports.has(modulePath)) {
|
|
220
|
+
imports.set(modulePath, new Set());
|
|
221
|
+
}
|
|
222
|
+
const moduleImports = imports.get(modulePath);
|
|
223
|
+
if (moduleImports) {
|
|
224
|
+
moduleImports.add(componentName);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/* Utility functions import */
|
|
228
|
+
imports.set("../utils", new Set(["deepMerge"]));
|
|
229
|
+
/* Generated options interface import (type-only to avoid circular dependencies) */
|
|
230
|
+
imports.set(`./${optionsFileName}.generated`, new Set([optionsInterface]));
|
|
231
|
+
return imports;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Derives the config path for accessing default options
|
|
235
|
+
*
|
|
236
|
+
* Transforms base class reference into the corresponding path in the defaultOptions
|
|
237
|
+
* configuration object exported from config.ts.
|
|
238
|
+
*
|
|
239
|
+
* @param baseClass - Base class in format "module.ClassName"
|
|
240
|
+
* @returns Config path for accessing default options
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* getConfigPath("typescript.TypeScriptProject") // "defaultOptions.typescript.TypeScriptProject"
|
|
244
|
+
*/
|
|
245
|
+
getConfigPath(baseClass) {
|
|
246
|
+
return `defaultOptions.${baseClass}`;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Renders import statements in sorted order
|
|
250
|
+
*
|
|
251
|
+
* Sorts imports with external packages first, then relative imports.
|
|
252
|
+
* Uses type-only imports for generated files to avoid circular dependencies.
|
|
253
|
+
*
|
|
254
|
+
* @param imports - Map of module paths to imported names
|
|
255
|
+
*/
|
|
256
|
+
renderImports(imports) {
|
|
257
|
+
/* Sort modules: external packages first, then relative imports alphabetically */
|
|
258
|
+
const sortedModules = Array.from(imports.keys()).sort((a, b) => {
|
|
259
|
+
const aIsRelative = a.startsWith(".");
|
|
260
|
+
const bIsRelative = b.startsWith(".");
|
|
261
|
+
if (aIsRelative !== bIsRelative) {
|
|
262
|
+
return aIsRelative ? 1 : -1;
|
|
263
|
+
}
|
|
264
|
+
return a.localeCompare(b);
|
|
265
|
+
});
|
|
266
|
+
for (const mod of sortedModules) {
|
|
267
|
+
const names = Array.from(imports.get(mod) || []).sort();
|
|
268
|
+
/* Use type-only import for generated files to prevent circular dependencies */
|
|
269
|
+
const isTypeOnly = mod.includes(".generated");
|
|
270
|
+
const importStmt = isTypeOnly ? "import type" : "import";
|
|
271
|
+
this.buffer.line(`${importStmt} { ${names.join(", ")} } from "${mod}";`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Renders re-export statement for the generated options interface
|
|
276
|
+
*
|
|
277
|
+
* @param optionsInterface - Name of the options interface to export
|
|
278
|
+
*/
|
|
279
|
+
renderExport(optionsInterface) {
|
|
280
|
+
const optionsFileName = this.getOptionsFileName(optionsInterface);
|
|
281
|
+
this.buffer.line();
|
|
282
|
+
this.buffer.line(`export { ${optionsInterface} } from "./${optionsFileName}.generated";`);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Renders the class declaration and constructor
|
|
286
|
+
*
|
|
287
|
+
* @param options - Generator configuration
|
|
288
|
+
* @param optionsInterface - Name of the options interface
|
|
289
|
+
* @param baseOptionsType - Base options type without "projen." prefix
|
|
290
|
+
* @param destructure - Variable names to destructure from options
|
|
291
|
+
* @param componentArray - Code string for component array
|
|
292
|
+
*/
|
|
293
|
+
renderClass(options, optionsInterface, baseOptionsType, destructure, componentArray) {
|
|
294
|
+
this.buffer.line();
|
|
295
|
+
this.buffer.line("/**");
|
|
296
|
+
this.buffer.line(` * ${options.name} with standard configuration and component integration`);
|
|
297
|
+
this.buffer.line(" *");
|
|
298
|
+
this.buffer.line(" * Extends Projen's base class with opinionated defaults and automatic component setup.");
|
|
299
|
+
this.buffer.line(" */");
|
|
300
|
+
this.buffer.open(`export class ${options.name} extends ${options.baseClass} {`);
|
|
301
|
+
this.renderConstructor(options, optionsInterface, baseOptionsType, destructure, componentArray);
|
|
302
|
+
this.buffer.close("}");
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Renders the constructor implementation
|
|
306
|
+
*
|
|
307
|
+
* The constructor:
|
|
308
|
+
* 1. Destructures component flags and options from the options parameter
|
|
309
|
+
* 2. Merges default configuration with user-provided options
|
|
310
|
+
* 3. Calls super() with merged options
|
|
311
|
+
* 4. Applies component defaults via applyDefaults()
|
|
312
|
+
*
|
|
313
|
+
* @param options - Generator configuration
|
|
314
|
+
* @param optionsInterface - Name of the options interface
|
|
315
|
+
* @param baseOptionsType - Base options type without "projen." prefix
|
|
316
|
+
* @param destructure - Variable names to destructure from options
|
|
317
|
+
* @param componentArray - Code string for component array
|
|
318
|
+
*/
|
|
319
|
+
renderConstructor(options, optionsInterface, baseOptionsType, destructure, componentArray) {
|
|
320
|
+
const configPath = this.getConfigPath(options.baseClass);
|
|
321
|
+
this.buffer.line("/**");
|
|
322
|
+
this.buffer.line(" * @param options - Project configuration");
|
|
323
|
+
this.buffer.line(" */");
|
|
324
|
+
this.buffer.open(`constructor(options: ${optionsInterface}) {`);
|
|
325
|
+
this.buffer.line("/* Separate component configuration from base Projen options */");
|
|
326
|
+
this.buffer.line(`const { ${destructure.join(", ")}, ...baseOptions } = options;`);
|
|
327
|
+
this.buffer.line();
|
|
328
|
+
this.buffer.line("/* Merge default configuration with user options and initialize base class */");
|
|
329
|
+
this.buffer.line(`super(deepMerge<${baseOptionsType}>(${configPath}, baseOptions));`);
|
|
330
|
+
this.buffer.line();
|
|
331
|
+
this.buffer.line("/* Apply component defaults and instantiate enabled components */");
|
|
332
|
+
this.buffer.line(`applyDefaults(this, ${componentArray});`);
|
|
333
|
+
this.buffer.close("}");
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Maps options interface name to file name
|
|
337
|
+
*
|
|
338
|
+
* Converts PascalCase interface names to kebab-case file names.
|
|
339
|
+
* Falls back to lowercase conversion for unmapped interfaces.
|
|
340
|
+
*
|
|
341
|
+
* @param optionsInterface - Options interface name
|
|
342
|
+
* @returns Kebab-case file name without extension
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* getOptionsFileName("TypeScriptProjectOptions") // "typescript-options"
|
|
346
|
+
*/
|
|
347
|
+
getOptionsFileName(optionsInterface) {
|
|
348
|
+
const mapping = {
|
|
349
|
+
TypeScriptProjectOptions: "typescript-options",
|
|
350
|
+
JsiiProjectOptions: "jsii-options",
|
|
351
|
+
AwsCdkTypeScriptAppProjectOptions: "awscdk-typescript-app-options",
|
|
352
|
+
AwsCdkConstructLibraryProjectOptions: "awscdk-construct-library-options",
|
|
353
|
+
};
|
|
354
|
+
return mapping[optionsInterface] || optionsInterface.toLowerCase();
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Projen component that generates TypeScript project classes with standard configuration
|
|
359
|
+
*
|
|
360
|
+
* This component automates the creation of project classes that extend Projen base classes
|
|
361
|
+
* with opinionated defaults and component integration. It generates both:
|
|
362
|
+
* 1. An options interface (via ProjenStruct) that extends the base Projen options
|
|
363
|
+
* 2. A project class that applies default configuration and instantiates components
|
|
364
|
+
*
|
|
365
|
+
* The generated code follows a consistent pattern:
|
|
366
|
+
* - Imports required modules and components
|
|
367
|
+
* - Re-exports the generated options interface
|
|
368
|
+
* - Defines a class extending the Projen base class
|
|
369
|
+
* - Constructor merges defaults with user options and applies components
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* ```typescript
|
|
373
|
+
* new ProjenProjectGenerator(project, {
|
|
374
|
+
* name: "TypeScriptProject",
|
|
375
|
+
* baseClass: "typescript.TypeScriptProject",
|
|
376
|
+
* filePath: "src/projects/typescript.generated.ts",
|
|
377
|
+
* components: [{ component: Vitest, optionsProperty: "vitestOptions" }]
|
|
378
|
+
* });
|
|
379
|
+
* ```
|
|
380
|
+
*/
|
|
381
|
+
class ProjenProjectGenerator extends projen_1.Component {
|
|
382
|
+
/**
|
|
383
|
+
* @param project - Projen project instance
|
|
384
|
+
* @param options - Generator configuration
|
|
385
|
+
*/
|
|
386
|
+
constructor(project, options) {
|
|
387
|
+
super(project);
|
|
388
|
+
this.options = options;
|
|
389
|
+
this.renderer = new TypeScriptClassRenderer();
|
|
390
|
+
/* Generate the options interface using ProjenStruct for JSII compatibility */
|
|
391
|
+
const optionsInterface = `${options.name}Options`;
|
|
392
|
+
const baseOptionsFqn = this.renderer.getBaseOptionsFqn(options.baseClass);
|
|
393
|
+
const optionsFilePath = this.getOptionsFilePath(optionsInterface);
|
|
394
|
+
/* ProjenStruct generates a concrete TypeScript interface from Projen's options
|
|
395
|
+
* This is necessary because JSII doesn't support TypeScript utility types like Omit<>
|
|
396
|
+
* The generated interface can be consumed by other languages (Python, Java, C#, Go) */
|
|
397
|
+
const struct = new jsii_struct_builder_1.ProjenStruct(this.asTypeScriptProject(project), {
|
|
398
|
+
name: optionsInterface,
|
|
399
|
+
filePath: optionsFilePath,
|
|
400
|
+
outputFileOptions: { readonly: true },
|
|
401
|
+
})
|
|
402
|
+
.mixin(jsii_struct_builder_1.Struct.fromFqn(baseOptionsFqn))
|
|
403
|
+
.withoutDeprecated();
|
|
404
|
+
/* Remove specified options from the base interface */
|
|
405
|
+
if (options.omitOptions) {
|
|
406
|
+
struct.omit(...options.omitOptions);
|
|
407
|
+
}
|
|
408
|
+
/* Add component-derived options to the interface */
|
|
409
|
+
const components = options.components ?? DEFAULT_COMPONENTS;
|
|
410
|
+
const { PrimitiveType } = require("@jsii/spec");
|
|
411
|
+
for (const c of components) {
|
|
412
|
+
const name = c.component.name.charAt(0).toLowerCase() + c.component.name.slice(1);
|
|
413
|
+
/* Add enabled flag for the component */
|
|
414
|
+
struct.add({
|
|
415
|
+
name,
|
|
416
|
+
type: { primitive: PrimitiveType.Boolean },
|
|
417
|
+
optional: true,
|
|
418
|
+
docs: {
|
|
419
|
+
summary: `Enable ${c.component.name} component`,
|
|
420
|
+
default: "true",
|
|
421
|
+
},
|
|
422
|
+
});
|
|
423
|
+
/* Add options property if component is configurable */
|
|
424
|
+
if (c.optionsProperty) {
|
|
425
|
+
struct.add({
|
|
426
|
+
name: c.optionsProperty.name,
|
|
427
|
+
type: { fqn: c.optionsProperty.type },
|
|
428
|
+
optional: true,
|
|
429
|
+
docs: {
|
|
430
|
+
summary: c.optionsProperty.docs ?? `${c.component.name} configuration`,
|
|
431
|
+
default: `- default ${c.component.name} configuration`,
|
|
432
|
+
},
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
/* Add custom options to the interface */
|
|
437
|
+
if (options.additionalOptions) {
|
|
438
|
+
struct.add(...options.additionalOptions);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Casts project to TypeScript project type
|
|
443
|
+
*
|
|
444
|
+
* ProjenStruct requires a TypeScriptProject instance. This generator is only used
|
|
445
|
+
* within TypeScript projects, so the cast is safe in practice.
|
|
446
|
+
*
|
|
447
|
+
* Note: Type assertion is necessary here because Projen's type system doesn't provide
|
|
448
|
+
* a runtime type guard for TypeScriptProject.
|
|
449
|
+
*
|
|
450
|
+
* @param project - Projen project instance
|
|
451
|
+
* @returns TypeScript project instance
|
|
452
|
+
*/
|
|
453
|
+
asTypeScriptProject(project) {
|
|
454
|
+
return project;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Derives the file path for the generated options interface
|
|
458
|
+
*
|
|
459
|
+
* Places the options interface file in the same directory as the class file
|
|
460
|
+
* with a ".generated.ts" suffix.
|
|
461
|
+
*
|
|
462
|
+
* @param optionsInterface - Name of the options interface
|
|
463
|
+
* @returns File path for the options interface
|
|
464
|
+
* @throws {InvalidFilePathError} When filePath doesn't contain a directory separator
|
|
465
|
+
*/
|
|
466
|
+
getOptionsFilePath(optionsInterface) {
|
|
467
|
+
const lastSlash = this.options.filePath.lastIndexOf("/");
|
|
468
|
+
if (lastSlash === -1) {
|
|
469
|
+
throw new errors_1.InvalidFilePathError(this.options.filePath);
|
|
470
|
+
}
|
|
471
|
+
const dir = this.options.filePath.substring(0, lastSlash);
|
|
472
|
+
const optionsFileName = this.renderer.getOptionsFileName(optionsInterface);
|
|
473
|
+
return `${dir}/${optionsFileName}.generated.ts`;
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Generates the TypeScript class file during Projen synthesis
|
|
477
|
+
*
|
|
478
|
+
* Called by Projen during the synthesis phase to generate the project class file.
|
|
479
|
+
* The file is marked as readonly to prevent manual editing.
|
|
480
|
+
*/
|
|
481
|
+
preSynthesize() {
|
|
482
|
+
const content = this.renderer.render(this.options);
|
|
483
|
+
new TypeScriptClassFile(this.project, this.options.filePath, content, {
|
|
484
|
+
readonly: this.options.readonly ?? true,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
exports.ProjenProjectGenerator = ProjenProjectGenerator;
|
|
489
|
+
/**
|
|
490
|
+
* Text file for generated TypeScript class code
|
|
491
|
+
*
|
|
492
|
+
* Extends Projen's TextFile to add the generated file marker comment
|
|
493
|
+
* at the beginning of the file.
|
|
494
|
+
*/
|
|
495
|
+
class TypeScriptClassFile extends projen_1.TextFile {
|
|
496
|
+
/**
|
|
497
|
+
* @param project - Projen project instance
|
|
498
|
+
* @param filePath - Output file path
|
|
499
|
+
* @param content - TypeScript class code
|
|
500
|
+
* @param options - Source code options (readonly, etc.)
|
|
501
|
+
*/
|
|
502
|
+
constructor(project, filePath, content, options = {}) {
|
|
503
|
+
super(project, filePath, options);
|
|
504
|
+
/* Add generated file marker to prevent manual editing */
|
|
505
|
+
this.addLine(`// ${this.marker}`);
|
|
506
|
+
this.addLine(content);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvamVuLXByb2plY3QtZ2VuZXJhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3Byb2plbi1wcm9qZWN0LWdlbmVyYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxzRUFBb0U7QUFFcEUsbUNBQTZDO0FBQzdDLHFDQUFzRztBQUt0Rzs7R0FFRztBQUNILE1BQU0sa0JBQWtCLEdBQXNCO0lBQzFDLEVBQUUsU0FBUyxFQUFFLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLElBQUksRUFBRTtJQUNoRDtRQUNJLFNBQVMsRUFBRSxPQUFPLENBQUMscUJBQXFCLENBQUMsQ0FBQyxNQUFNO1FBQ2hELGVBQWUsRUFBRTtZQUNiLElBQUksRUFBRSxlQUFlO1lBQ3JCLElBQUksRUFBRSw4Q0FBOEM7WUFDcEQsSUFBSSxFQUFFLHNCQUFzQjtTQUMvQjtLQUNKO0NBQ0osQ0FBQztBQW9IRjs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVTtJQUlaOztPQUVHO0lBQ0gsWUFBNkIsU0FBUyxHQUFHO1FBQVosV0FBTSxHQUFOLE1BQU0sQ0FBTTtRQU5qQyxVQUFLLEdBQWEsRUFBRSxDQUFDO1FBQ3JCLGdCQUFXLEdBQUcsQ0FBQyxDQUFDO0lBS29CLENBQUM7SUFFN0M7Ozs7T0FJRztJQUNILEtBQUs7UUFDRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQzNCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNiLE9BQU8sT0FBTyxDQUFDO0lBQ25CLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsSUFBSSxDQUFDLElBQWE7UUFDZCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDcEQsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxP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QUFRLENBQUMsQ0FBQztRQUMxRCxDQUFDO1FBRUQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUMxRCxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDM0UsT0FBTyxHQUFHLEdBQUcsSUFBSSxlQUFlLGVBQWUsQ0FBQztJQUNwRCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxhQUFhO1FBQ1QsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRW5ELElBQUksbUJBQW1CLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUU7WUFDbEUsUUFBUSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxJQUFJLElBQUk7U0FDMUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztDQUNKO0FBM0hELHdEQTJIQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxtQkFBb0IsU0FBUSxpQkFBUTtJQUN0Qzs7Ozs7T0FLRztJQUNILFlBQVksT0FBZ0IsRUFBRSxRQUFnQixFQUFFLE9BQWUsRUFBRSxVQUE2QixFQUFFO1FBQzVGLEtBQUssQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ2xDLHlEQUF5RDtRQUN6RCxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDbEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMxQixDQUFDO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IFByb3BlcnR5IH0gZnJvbSBcIkBqc2lpL3NwZWNcIjtcbmltcG9ydCB7IFByb2plblN0cnVjdCwgU3RydWN0IH0gZnJvbSBcIkBtcmdyYWluL2pzaWktc3RydWN0LWJ1aWxkZXJcIjtcbmltcG9ydCB0eXBlIHsgUHJvamVjdCwgU291cmNlQ29kZU9wdGlvbnMsIHR5cGVzY3JpcHQgfSBmcm9tIFwicHJvamVuXCI7XG5pbXBvcnQgeyBDb21wb25lbnQsIFRleHRGaWxlIH0gZnJvbSBcInByb2plblwiO1xuaW1wb3J0IHsgSW52YWxpZEJhc2VDbGFzc0Zvcm1hdEVycm9yLCBJbnZhbGlkRmlsZVBhdGhFcnJvciwgSW52YWxpZEluZGVudExldmVsRXJyb3IgfSBmcm9tIFwiLi9lcnJvcnNcIjtcblxudHlwZSBQcm9qZW5Nb2R1bGUgPSBcInR5cGVzY3JpcHRcIiB8IFwiY2RrXCIgfCBcImF3c2Nka1wiO1xudHlwZSBQcm9qZW5CYXNlQ2xhc3M8TSBleHRlbmRzIFByb2plbk1vZHVsZT4gPSBgJHtNfS4ke3N0cmluZ31gO1xuXG4vKipcbiAqIERlZmF1bHQgY29tcG9uZW50cyBhcHBsaWVkIHRvIGFsbCBnZW5lcmF0ZWQgcHJvamVjdHNcbiAqL1xuY29uc3QgREVGQVVMVF9DT01QT05FTlRTOiBDb21wb25lbnRDb25maWdbXSA9IFtcbiAgICB7IGNvbXBvbmVudDogcmVxdWlyZShcIi4vY29tcG9uZW50cy9taXNlXCIpLk1pc2UgfSxcbiAgICB7XG4gICAgICAgIGNvbXBvbmVudDogcmVxdWlyZShcIi4vY29tcG9uZW50cy92aXRlc3RcIikuVml0ZXN0LFxuICAgICAgICBvcHRpb25zUHJvcGVydHk6IHtcbiAgICAgICAgICAgIG5hbWU6IFwidml0ZXN0T3B0aW9uc1wiLFxuICAgICAgICAgICAgdHlwZTogXCJAbmlrb3ZpcnRhbGEvcHJvamVuLWNvbnN0cnVjdHMuVml0ZXN0T3B0aW9uc1wiLFxuICAgICAgICAgICAgZG9jczogXCJWaXRlc3QgY29uZmlndXJhdGlvblwiLFxuICAgICAgICB9LFxuICAgIH0sXG5dO1xuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIGEgY29tcG9uZW50IHRvIGJlIGludGVncmF0ZWQgaW50byBhIGdlbmVyYXRlZCBwcm9qZWN0XG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGNvbmZpZzogQ29tcG9uZW50Q29uZmlnID0ge1xuICogICBjb21wb25lbnQ6IFZpdGVzdCxcbiAqICAgb3B0aW9uc1Byb3BlcnR5OiBcInZpdGVzdE9wdGlvbnNcIlxuICogfTtcbiAqIGBgYFxuICovXG5pbnRlcmZhY2UgQ29tcG9uZW50Q29uZmlnPFQgZXh0ZW5kcyBDb21wb25lbnQgPSBDb21wb25lbnQ+IHtcbiAgICAvKipcbiAgICAgKiBDb21wb25lbnQgY2xhc3MgY29uc3RydWN0b3JcbiAgICAgKi9cbiAgICByZWFkb25seSBjb21wb25lbnQ6IG5ldyAoXG4gICAgICAgIHByb2plY3Q6IG5ldmVyLFxuICAgICAgICBvcHRpb25zPzogbmV2ZXIsXG4gICAgKSA9PiBUO1xuXG4gICAgLyoqXG4gICAgICogT3B0aW9ucyBwcm9wZXJ0eSBjb25maWd1cmF0aW9uIGZvciB0aGUgZ2VuZXJhdGVkIG9wdGlvbnMgaW50ZXJmYWNlXG4gICAgICpcbiAgICAgKiBXaGVuIHNwZWNpZmllZCwgYWRkcyBhbiBvcHRpb25zIHByb3BlcnR5IHRvIHRoZSBpbnRlcmZhY2UgYWxsb3dpbmdcbiAgICAgKiB1c2VycyB0byBjb25maWd1cmUgdGhlIGNvbXBvbmVudC5cbiAgICAgKi9cbiAgICByZWFkb25seSBvcHRpb25zUHJvcGVydHk/OiB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBOYW1lIG9mIHRoZSBvcHRpb25zIHByb3BlcnR5IChlLmcuLCBcInZpdGVzdE9wdGlvbnNcIilcbiAgICAgICAgICovXG4gICAgICAgIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZ1bGx5IHF1YWxpZmllZCB0eXBlIG5hbWUgKGUuZy4sIFwiQG5pa292aXJ0YWxhL3Byb2plbi1jb25zdHJ1Y3RzLlZpdGVzdE9wdGlvbnNcIilcbiAgICAgICAgICovXG4gICAgICAgIHJlYWRvbmx5IHR5cGU6IHN0cmluZztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIERvY3VtZW50YXRpb24gc3VtbWFyeVxuICAgICAgICAgKi9cbiAgICAgICAgcmVhZG9ubHkgZG9jcz86IHN0cmluZztcbiAgICB9O1xufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIFByb2plblByb2plY3RHZW5lcmF0b3IgY29tcG9uZW50XG4gKlxuICogQ29uZmlndXJlcyB0aGUgZ2VuZXJhdGlvbiBvZiBhIFR5cGVTY3JpcHQgcHJvamVjdCBjbGFzcyB0aGF0IGV4dGVuZHMgYSBQcm9qZW4gYmFzZSBjbGFzc1xuICogd2l0aCBzdGFuZGFyZCBjb25maWd1cmF0aW9uIGFuZCBjb21wb25lbnQgaW50ZWdyYXRpb24uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIG5ldyBQcm9qZW5Qcm9qZWN0R2VuZXJhdG9yKHByb2plY3QsIHtcbiAqICAgbmFtZTogXCJUeXBlU2NyaXB0UHJvamVjdFwiLFxuICogICBiYXNlQ2xhc3M6IFwidHlwZXNjcmlwdC5UeXBlU2NyaXB0UHJvamVjdFwiLFxuICogICBmaWxlUGF0aDogXCJzcmMvcHJvamVjdHMvdHlwZXNjcmlwdC5nZW5lcmF0ZWQudHNcIixcbiAqICAgY29tcG9uZW50czogW3sgY29tcG9uZW50OiBWaXRlc3QsIG9wdGlvbnNQcm9wZXJ0eTogXCJ2aXRlc3RPcHRpb25zXCIgfV1cbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHJvamVuUHJvamVjdEdlbmVyYXRvck9wdGlvbnM8TSBleHRlbmRzIFByb2plbk1vZHVsZSA9IFByb2plbk1vZHVsZT4gZXh0ZW5kcyBTb3VyY2VDb2RlT3B0aW9ucyB7XG4gICAgLyoqXG4gICAgICogTmFtZSBvZiB0aGUgZ2VuZXJhdGVkIGNsYXNzIChlLmcuLCBcIlR5cGVTY3JpcHRQcm9qZWN0XCIpXG4gICAgICpcbiAgICAgKiBUaGUgb3B0aW9ucyBpbnRlcmZhY2Ugd2lsbCBiZSBuYW1lZCBgJHtuYW1lfU9wdGlvbnNgLlxuICAgICAqL1xuICAgIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEZ1bGx5IHF1YWxpZmllZCBiYXNlIGNsYXNzIHRvIGV4dGVuZCBpbiBmb3JtYXQgXCJtb2R1bGUuQ2xhc3NOYW1lXCJcbiAgICAgKlxuICAgICAqIE11c3QgYmUgYSB2YWxpZCBQcm9qZW4gY2xhc3MgcmVmZXJlbmNlIGxpa2UgXCJ0eXBlc2NyaXB0LlR5cGVTY3JpcHRQcm9qZWN0XCIsXG4gICAgICogXCJjZGsuSnNpaVByb2plY3RcIiwgb3IgXCJhd3NjZGsuQXdzQ2RrVHlwZVNjcmlwdEFwcFwiLlxuICAgICAqXG4gICAgICogQGV4YW1wbGUgXCJ0eXBlc2NyaXB0LlR5cGVTY3JpcHRQcm9qZWN0XCJcbiAgICAgKiBAZXhhbXBsZSBcImNkay5Kc2lpUHJvamVjdFwiXG4gICAgICovXG4gICAgcmVhZG9ubHkgYmFzZUNsYXNzOiBQcm9qZW5CYXNlQ2xhc3M8TT47XG5cbiAgICAvKipcbiAgICAgKiBPdXRwdXQgZmlsZSBwYXRoIGZvciB0aGUgZ2VuZXJhdGVkIGNsYXNzXG4gICAgICpcbiAgICAgKiBNdXN0IGNvbnRhaW4gYSBkaXJlY3Rvcnkgc2VwYXJhdG9yLiBUaGUgb3B0aW9ucyBpbnRlcmZhY2Ugd2lsbCBiZSBnZW5lcmF0ZWRcbiAgICAgKiBpbiB0aGUgc2FtZSBkaXJlY3Rvcnkgd2l0aCBhIFwiLmdlbmVyYXRlZC50c1wiIHN1ZmZpeC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlIFwic3JjL3Byb2plY3RzL3R5cGVzY3JpcHQuZ2VuZXJhdGVkLnRzXCJcbiAgICAgKi9cbiAgICByZWFkb25seSBmaWxlUGF0aDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQ29tcG9uZW50cyB0byBpbnRlZ3JhdGUgaW50byB0aGUgcHJvamVjdFxuICAgICAqXG4gICAgICogRWFjaCBjb21wb25lbnQgd2lsbCBiZSBpbnN0YW50aWF0ZWQgZHVyaW5nIHByb2plY3QgY29uc3RydWN0aW9uIGFuZCBjYW4gYmVcbiAgICAgKiBjb25maWd1cmVkIHZpYSBhbiBvcHRpb25hbCBvcHRpb25zIHByb3BlcnR5IGluIHRoZSBnZW5lcmF0ZWQgaW50ZXJmYWNlLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgW3sgY29tcG9uZW50OiBNaXNlIH0sIHsgY29tcG9uZW50OiBWaXRlc3QsIG9wdGlvbnNQcm9wZXJ0eTogeyBuYW1lOiBcInZpdGVzdE9wdGlvbnNcIiwgdHlwZTogXCIuLi5cIiwgZG9jczogXCIuLi5cIiB9IH1dXG4gICAgICovXG4gICAgcmVhZG9ubHkgY29tcG9uZW50cz86IENvbXBvbmVudENvbmZpZ1tdO1xuXG4gICAgLyoqXG4gICAgICogQWRkaXRpb25hbCBwcm9wZXJ0aWVzIHRvIGFkZCB0byB0aGUgZ2VuZXJhdGVkIG9wdGlvbnMgaW50ZXJmYWNlXG4gICAgICpcbiAgICAgKiBVc2UgdGhpcyB0byBleHRlbmQgdGhlIGJhc2Ugb3B0aW9ucyB3aXRoIGN1c3RvbSBwcm9wZXJ0aWVzIHNwZWNpZmljIHRvXG4gICAgICogeW91ciBwcm9qZWN0IHR5cGUuXG4gICAgICovXG4gICAgcmVhZG9ubHkgYWRkaXRpb25hbE9wdGlvbnM/OiBQcm9wZXJ0eVtdO1xuXG4gICAgLyoqXG4gICAgICogUHJvcGVydHkgbmFtZXMgdG8gb21pdCBmcm9tIHRoZSBiYXNlIG9wdGlvbnMgaW50ZXJmYWNlXG4gICAgICpcbiAgICAgKiBVc2UgdGhpcyB0byBoaWRlIGJhc2UgY2xhc3Mgb3B0aW9ucyB0aGF0IHNob3VsZCBub3QgYmUgY29uZmlndXJhYmxlXG4gICAgICogaW4gdGhlIGdlbmVyYXRlZCBwcm9qZWN0IHR5cGUuXG4gICAgICovXG4gICAgcmVhZG9ubHkgb21pdE9wdGlvbnM/OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBCdWZmZXIgZm9yIGJ1aWxkaW5nIGluZGVudGVkIGNvZGUgd2l0aCBhdXRvbWF0aWMgbGluZSBtYW5hZ2VtZW50XG4gKlxuICogTWFpbnRhaW5zIGluZGVudGF0aW9uIGxldmVsIGFuZCBwcm92aWRlcyBtZXRob2RzIGZvciBhZGRpbmcgbGluZXMsXG4gKiBvcGVuaW5nL2Nsb3NpbmcgYmxvY2tzLCBhbmQgZmx1c2hpbmcgYWNjdW11bGF0ZWQgY29udGVudC5cbiAqL1xuY2xhc3MgQ29kZUJ1ZmZlciB7XG4gICAgcHJpdmF0ZSBsaW5lczogc3RyaW5nW10gPSBbXTtcbiAgICBwcml2YXRlIGluZGVudExldmVsID0gMDtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBpbmRlbnQgLSBTdHJpbmcgdG8gdXNlIGZvciBlYWNoIGluZGVudGF0aW9uIGxldmVsIChkZWZhdWx0OiBzaW5nbGUgc3BhY2UpXG4gICAgICovXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBpbmRlbnQgPSBcIiBcIikge31cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYWxsIGFjY3VtdWxhdGVkIGxpbmVzIGFuZCByZXNldHMgdGhlIGJ1ZmZlclxuICAgICAqXG4gICAgICogQHJldHVybnMgQXJyYXkgb2YgY29kZSBsaW5lcyB3aXRoIHByb3BlciBpbmRlbnRhdGlvblxuICAgICAqL1xuICAgIGZsdXNoKCk6IHN0cmluZ1tdIHtcbiAgICAgICAgY29uc3QgY3VycmVudCA9IHRoaXMubGluZXM7XG4gICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgcmV0dXJuIGN1cnJlbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpbmUgb2YgY29kZSBhdCB0aGUgY3VycmVudCBpbmRlbnRhdGlvbiBsZXZlbFxuICAgICAqXG4gICAgICogQHBhcmFtIGNvZGUgLSBDb2RlIHRvIGFkZCAob3B0aW9uYWwsIGFkZHMgYmxhbmsgbGluZSBpZiBvbWl0dGVkKVxuICAgICAqL1xuICAgIGxpbmUoY29kZT86IHN0cmluZykge1xuICAgICAgICBjb25zdCBwcmVmaXggPSB0aGlzLmluZGVudC5yZXBlYXQodGhpcy5pbmRlbnRMZXZlbCk7XG4gICAgICAgIHRoaXMubGluZXMucHVzaCgocHJlZml4ICsgKGNvZGUgPz8gXCJcIikpLnRyaW1FbmQoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT3BlbnMgYSBuZXcgaW5kZW50YXRpb24gYmxvY2tcbiAgICAgKlxuICAgICAqIEBwYXJhbSBjb2RlIC0gT3B0aW9uYWwgY29kZSB0byBhZGQgYmVmb3JlIGluY3JlYXNpbmcgaW5kZW50IChlLmcuLCBvcGVuaW5nIGJyYWNlKVxuICAgICAqL1xuICAgIG9wZW4oY29kZT86IHN0cmluZykge1xuICAgICAgICBpZiAoY29kZSkge1xuICAgICAgICAgICAgdGhpcy5saW5lKGNvZGUpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaW5kZW50TGV2ZWwrKztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbG9zZXMgdGhlIGN1cnJlbnQgaW5kZW50YXRpb24gYmxvY2tcbiAgICAgKlxuICAgICAqIEBwYXJhbSBjb2RlIC0gT3B0aW9uYWwgY29kZSB0byBhZGQgYWZ0ZXIgZGVjcmVhc2luZyBpbmRlbnQgKGUuZy4sIGNsb3NpbmcgYnJhY2UpXG4gICAgICogQHRocm93cyB7SW52YWxpZEluZGVudExldmVsRXJyb3J9IFdoZW4gYXR0ZW1wdGluZyB0byBkZWNyZWFzZSBpbmRlbnQgYmVsb3cgemVyb1xuICAgICAqL1xuICAgIGNsb3NlKGNvZGU/OiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKHRoaXMuaW5kZW50TGV2ZWwgPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBJbnZhbGlkSW5kZW50TGV2ZWxFcnJvcigpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaW5kZW50TGV2ZWwtLTtcbiAgICAgICAgaWYgKGNvZGUpIHtcbiAgICAgICAgICAgIHRoaXMubGluZShjb2RlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc2V0cyB0aGUgYnVmZmVyIHRvIGluaXRpYWwgc3RhdGVcbiAgICAgKi9cbiAgICBwcml2YXRlIHJlc2V0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmxpbmVzID0gW107XG4gICAgICAgIHRoaXMuaW5kZW50TGV2ZWwgPSAwO1xuICAgIH1cbn1cblxuLyoqXG4gKiBSZW5kZXJzIFR5cGVTY3JpcHQgY2xhc3MgY29kZSBmcm9tIFByb2plblByb2plY3RHZW5lcmF0b3Igb3B0aW9uc1xuICpcbiAqIEdlbmVyYXRlcyBhIGNvbXBsZXRlIFR5cGVTY3JpcHQgY2xhc3MgZmlsZSBpbmNsdWRpbmcgaW1wb3J0cywgb3B0aW9ucyBpbnRlcmZhY2UgZXhwb3J0LFxuICogY2xhc3MgZGVjbGFyYXRpb24sIGFuZCBjb25zdHJ1Y3RvciB3aXRoIGNvbXBvbmVudCBpbnRlZ3JhdGlvbi5cbiAqL1xuY2xhc3MgVHlwZVNjcmlwdENsYXNzUmVuZGVyZXIge1xuICAgIHByaXZhdGUgYnVmZmVyOiBDb2RlQnVmZmVyO1xuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGluZGVudCAtIE51bWJlciBvZiBzcGFjZXMgcGVyIGluZGVudGF0aW9uIGxldmVsIChkZWZhdWx0OiA0KVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGluZGVudCA9IDQpIHtcbiAgICAgICAgdGhpcy5idWZmZXIgPSBuZXcgQ29kZUJ1ZmZlcihcIiBcIi5yZXBlYXQoaW5kZW50KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBjb21wbGV0ZSBUeXBlU2NyaXB0IGNsYXNzIGNvZGUgZnJvbSBvcHRpb25zXG4gICAgICpcbiAgICAgKiBPcmNoZXN0cmF0ZXMgdGhlIHJlbmRlcmluZyBwcm9jZXNzOiBkZXJpdmVzIG5hbWVzLCBleHRyYWN0cyBjb21wb25lbnQgY29uZmlndXJhdGlvbixcbiAgICAgKiBidWlsZHMgaW1wb3J0IHN0YXRlbWVudHMsIGFuZCByZW5kZXJzIHRoZSBjbGFzcyBzdHJ1Y3R1cmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIEdlbmVyYXRvciBjb25maWd1cmF0aW9uXG4gICAgICogQHJldHVybnMgQ29tcGxldGUgVHlwZVNjcmlwdCBjbGFzcyBjb2RlIGFzIGEgc3RyaW5nXG4gICAgICovXG4gICAgcmVuZGVyKG9wdGlvbnM6IFByb2plblByb2plY3RHZW5lcmF0b3JPcHRpb25zPFByb2plbk1vZHVsZT4pOiBzdHJpbmcge1xuICAgICAgICB0aGlzLmJ1ZmZlci5mbHVzaCgpO1xuXG4gICAgICAgIC8qIERlcml2ZSBpbnRlcmZhY2UgYW5kIHR5cGUgbmFtZXMgZnJvbSB0aGUgY2xhc3MgbmFtZSAqL1xuICAgICAgICBjb25zdCBvcHRpb25zSW50ZXJmYWNlID0gYCR7b3B0aW9ucy5uYW1lfU9wdGlvbnNgO1xuICAgICAgICBjb25zdCBiYXNlT3B0aW9uc0ZxbiA9IHRoaXMuZ2V0QmFzZU9wdGlvbnNGcW4ob3B0aW9ucy5iYXNlQ2xhc3MpO1xuICAgICAgICBjb25zdCBiYXNlT3B0aW9uc1R5cGUgPSBiYXNlT3B0aW9uc0Zxbi5yZXBsYWNlKC9ecHJvamVuXFwuLywgXCJcIik7XG5cbiAgICAgICAgLyogVXNlIHByb3ZpZGVkIGNvbXBvbmVudHMgb3IgZmFsbCBiYWNrIHRvIGRlZmF1bHRzIChNaXNlICsgVml0ZXN0KSAqL1xuICAgICAgICBjb25zdCBjb21wb25lbnRzID0gb3B0aW9ucy5jb21wb25lbnRzID8/IERFRkFVTFRfQ09NUE9ORU5UUztcblxuICAgICAgICAvKiBFeHRyYWN0IGNvbXBvbmVudCBjb25maWd1cmF0aW9uIGZvciBjb25zdHJ1Y3RvciBnZW5lcmF0aW9uICovXG4gICAgICAgIGNvbnN0IHsgZGVzdHJ1Y3R1cmUsIGNvbXBvbmVudEFycmF5IH0gPSB0aGlzLmV4dHJhY3RDb21wb25lbnRPcHRpb25zKGNvbXBvbmVudHMpO1xuICAgICAgICBjb25zdCBpbXBvcnRzID0gdGhpcy5leHRyYWN0SW1wb3J0cyhvcHRpb25zLCBvcHRpb25zSW50ZXJmYWNlKTtcblxuICAgICAgICAvKiBSZW5kZXIgYWxsIHNlY3Rpb25zIG9mIHRoZSBjbGFzcyBmaWxlICovXG4gICAgICAgIHRoaXMucmVuZGVySW1wb3J0cyhpbXBvcnRzKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZSgpO1xuICAgICAgICB0aGlzLnJlbmRlckV4cG9ydChvcHRpb25zSW50ZXJmYWNlKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZSgpO1xuICAgICAgICB0aGlzLnJlbmRlckNsYXNzKG9wdGlvbnMsIG9wdGlvbnNJbnRlcmZhY2UsIGJhc2VPcHRpb25zVHlwZSwgZGVzdHJ1Y3R1cmUsIGNvbXBvbmVudEFycmF5KTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZSgpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmJ1ZmZlci5mbHVzaCgpLmpvaW4oXCJcXG5cIik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVyaXZlcyB0aGUgZnVsbHkgcXVhbGlmaWVkIG9wdGlvbnMgaW50ZXJmYWNlIG5hbWUgZnJvbSBiYXNlIGNsYXNzXG4gICAgICpcbiAgICAgKiBUcmFuc2Zvcm1zIGJhc2UgY2xhc3MgcmVmZXJlbmNlIGludG8gdGhlIGNvcnJlc3BvbmRpbmcgUHJvamVuIG9wdGlvbnMgaW50ZXJmYWNlIG5hbWVcbiAgICAgKiBieSBhcHBlbmRpbmcgXCJPcHRpb25zXCIgc3VmZml4IGFuZCBwcmVmaXhpbmcgd2l0aCBcInByb2plbi5cIiBuYW1lc3BhY2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYmFzZUNsYXNzIC0gQmFzZSBjbGFzcyBpbiBmb3JtYXQgXCJtb2R1bGUuQ2xhc3NOYW1lXCJcbiAgICAgKiBAcmV0dXJucyBGdWxseSBxdWFsaWZpZWQgb3B0aW9ucyBpbnRlcmZhY2UgbmFtZVxuICAgICAqIEB0aHJvd3Mge0ludmFsaWRCYXNlQ2xhc3NGb3JtYXRFcnJvcn0gV2hlbiBiYXNlQ2xhc3MgZm9ybWF0IGlzIGludmFsaWRcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogZ2V0QmFzZU9wdGlvbnNGcW4oXCJ0eXBlc2NyaXB0LlR5cGVTY3JpcHRQcm9qZWN0XCIpIC8vIFwicHJvamVuLnR5cGVzY3JpcHQuVHlwZVNjcmlwdFByb2plY3RPcHRpb25zXCJcbiAgICAgKiBnZXRCYXNlT3B0aW9uc0ZxbihcImNkay5Kc2lpUHJvamVjdFwiKSAvLyBcInByb2plbi5jZGsuSnNpaVByb2plY3RPcHRpb25zXCJcbiAgICAgKi9cbiAgICBnZXRCYXNlT3B0aW9uc0ZxbihiYXNlQ2xhc3M6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIC8qIFZhbGlkYXRlIGJhc2UgY2xhc3MgZm9ybWF0OiBtdXN0IGNvbnRhaW4gbW9kdWxlLkNsYXNzTmFtZSBzdHJ1Y3R1cmUgKi9cbiAgICAgICAgaWYgKCFiYXNlQ2xhc3MuaW5jbHVkZXMoXCIuXCIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgSW52YWxpZEJhc2VDbGFzc0Zvcm1hdEVycm9yKGJhc2VDbGFzcyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYHByb2plbi4ke2Jhc2VDbGFzc31PcHRpb25zYDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeHRyYWN0cyBjb21wb25lbnQgY29uZmlndXJhdGlvbiBmb3IgY29uc3RydWN0b3IgY29kZSBnZW5lcmF0aW9uXG4gICAgICpcbiAgICAgKiBUcmFuc2Zvcm1zIGNvbXBvbmVudCBjb25maWd1cmF0aW9ucyBpbnRvOlxuICAgICAqIDEuIERlc3RydWN0dXJlIGxpc3Q6IHZhcmlhYmxlIG5hbWVzIHRvIGV4dHJhY3QgZnJvbSBvcHRpb25zXG4gICAgICogMi4gQ29tcG9uZW50IGFycmF5OiBjb2RlIHN0cmluZyBmb3IgYXBwbHlEZWZhdWx0cygpIGNhbGxcbiAgICAgKlxuICAgICAqIEBwYXJhbSBjb21wb25lbnRzIC0gQ29tcG9uZW50IGNvbmZpZ3VyYXRpb25zXG4gICAgICogQHJldHVybnMgT2JqZWN0IHdpdGggZGVzdHJ1Y3R1cmUgYXJyYXkgYW5kIGNvbXBvbmVudEFycmF5IGNvZGUgc3RyaW5nXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIElucHV0OiBbeyBjb21wb25lbnQ6IFZpdGVzdCwgb3B0aW9uc1Byb3BlcnR5OiB7IG5hbWU6IFwidml0ZXN0T3B0aW9uc1wiLCAuLi4gfSB9XVxuICAgICAqIE91dHB1dDoge1xuICAgICAqICAgZGVzdHJ1Y3R1cmU6IFtcInZpdGVzdFwiLCBcInZpdGVzdE9wdGlvbnNcIl0sXG4gICAgICogICBjb21wb25lbnRBcnJheTogXCJbeyBjb21wb25lbnQ6IFZpdGVzdCwgZW5hYmxlZDogdml0ZXN0LCBvcHRpb25zOiB2aXRlc3RPcHRpb25zIH1dXCJcbiAgICAgKiB9XG4gICAgICovXG4gICAgcHJpdmF0ZSBleHRyYWN0Q29tcG9uZW50T3B0aW9ucyhjb21wb25lbnRzOiBDb21wb25lbnRDb25maWdbXSk6IHsgZGVzdHJ1Y3R1cmU6IHN0cmluZ1tdOyBjb21wb25lbnRBcnJheTogc3RyaW5nIH0ge1xuICAgICAgICBjb25zdCBkZXN0cnVjdHVyZTogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgY29uc3QgY29tcG9uZW50UGFydHM6IHN0cmluZ1tdID0gW107XG5cbiAgICAgICAgZm9yIChjb25zdCBjIG9mIGNvbXBvbmVudHMpIHtcbiAgICAgICAgICAgIC8qIENvbnZlcnQgY29tcG9uZW50IGNsYXNzIG5hbWUgdG8gY2FtZWxDYXNlIHZhcmlhYmxlIG5hbWUgKGUuZy4sIFZpdGVzdCAtPiB2aXRlc3QpICovXG4gICAgICAgICAgICBjb25zdCBuYW1lID0gYy5jb21wb25lbnQubmFtZS5jaGFyQXQoMCkudG9Mb3dlckNhc2UoKSArIGMuY29tcG9uZW50Lm5hbWUuc2xpY2UoMSk7XG4gICAgICAgICAgICBkZXN0cnVjdHVyZS5wdXNoKG5hbWUpO1xuXG4gICAgICAgICAgICAvKiBCdWlsZCBjb21wb25lbnQgY29uZmlnIG9iamVjdCBmb3IgYXBwbHlEZWZhdWx0cygpIGNhbGwgKi9cbiAgICAgICAgICAgIGNvbnN0IHBhcnRzID0gW2Bjb21wb25lbnQ6ICR7Yy5jb21wb25lbnQubmFtZX1gXTtcbiAgICAgICAgICAgIGlmIChjLm9wdGlvbnNQcm9wZXJ0eSkge1xuICAgICAgICAgICAgICAgIC8qIENvbXBvbmVudCBoYXMgY29uZmlndXJhYmxlIG9wdGlvbnMgLSBpbmNsdWRlIGJvdGggZW5hYmxlZCBmbGFnIGFuZCBvcHRpb25zICovXG4gICAgICAgICAgICAgICAgZGVzdHJ1Y3R1cmUucHVzaChjLm9wdGlvbnNQcm9wZXJ0eS5uYW1lKTtcbiAgICAgICAgICAgICAgICBwYXJ0cy5wdXNoKGBlbmFibGVkOiAke25hbWV9YCwgYG9wdGlvbnM6ICR7Yy5vcHRpb25zUHJvcGVydHkubmFtZX1gKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLyogQ29tcG9uZW50IGhhcyBubyBvcHRpb25zIC0gb25seSBpbmNsdWRlIGVuYWJsZWQgZmxhZyAqL1xuICAgICAgICAgICAgICAgIHBhcnRzLnB1c2goYGVuYWJsZWQ6ICR7bmFtZX1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbXBvbmVudFBhcnRzLnB1c2goYHsgJHtwYXJ0cy5qb2luKFwiLCBcIil9IH1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IGRlc3RydWN0dXJlLCBjb21wb25lbnRBcnJheTogYFske2NvbXBvbmVudFBhcnRzLmpvaW4oXCIsIFwiKX1dYCB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEJ1aWxkcyBpbXBvcnQgc3RhdGVtZW50cyBtYXAgZm9yIHRoZSBnZW5lcmF0ZWQgY2xhc3NcbiAgICAgKlxuICAgICAqIENvbGxlY3RzIGFsbCByZXF1aXJlZCBpbXBvcnRzOlxuICAgICAqIC0gUHJvamVuIGJhc2UgbW9kdWxlICh0eXBlc2NyaXB0LCBjZGssIGF3c2NkaylcbiAgICAgKiAtIENvbmZpZyB1dGlsaXRpZXMgKGFwcGx5RGVmYXVsdHMsIGRlZmF1bHRPcHRpb25zKVxuICAgICAqIC0gQ29tcG9uZW50IGNsYXNzZXNcbiAgICAgKiAtIFV0aWxpdHkgZnVuY3Rpb25zIChkZWVwTWVyZ2UpXG4gICAgICogLSBHZW5lcmF0ZWQgb3B0aW9ucyBpbnRlcmZhY2UgKHR5cGUtb25seSBpbXBvcnQpXG4gICAgICpcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIEdlbmVyYXRvciBjb25maWd1cmF0aW9uXG4gICAgICogQHBhcmFtIG9wdGlvbnNJbnRlcmZhY2UgLSBOYW1lIG9mIHRoZSBnZW5lcmF0ZWQgb3B0aW9ucyBpbnRlcmZhY2VcbiAgICAgKiBAcmV0dXJucyBNYXAgb2YgbW9kdWxlIHBhdGhzIHRvIHNldHMgb2YgaW1wb3J0ZWQgbmFtZXNcbiAgICAgKi9cbiAgICBwcml2YXRlIGV4dHJhY3RJbXBvcnRzKFxuICAgICAgICBvcHRpb25zOiBQcm9qZW5Qcm9qZWN0R2VuZXJhdG9yT3B0aW9uczxQcm9qZW5Nb2R1bGU+LFxuICAgICAgICBvcHRpb25zSW50ZXJmYWNlOiBzdHJpbmcsXG4gICAgKTogTWFwPHN0cmluZywgU2V0PHN0cmluZz4+IHtcbiAgICAgICAgY29uc3QgaW1wb3J0cyA9IG5ldyBNYXA8c3RyaW5nLCBTZXQ8c3RyaW5nPj4oKTtcblxuICAgICAgICAvKiBFeHRyYWN0IGJhc2UgbW9kdWxlIG5hbWUgZnJvbSBiYXNlQ2xhc3MgKGUuZy4sIFwidHlwZXNjcmlwdFwiIGZyb20gXCJ0eXBlc2NyaXB0LlR5cGVTY3JpcHRQcm9qZWN0XCIpICovXG4gICAgICAgIGNvbnN0IGJhc2VNb2R1bGUgPSBvcHRpb25zLmJhc2VDbGFzcy5zcGxpdChcIi5cIilbMF07XG4gICAgICAgIGNvbnN0IG9wdGlvbnNGaWxlTmFtZSA9IHRoaXMuZ2V0T3B0aW9uc0ZpbGVOYW1lKG9wdGlvbnNJbnRlcmZhY2UpO1xuXG4gICAgICAgIC8qIFByb2plbiBiYXNlIG1vZHVsZSBpbXBvcnQgKi9cbiAgICAgICAgaW1wb3J0cy5zZXQoXCJwcm9qZW5cIiwgbmV3IFNldChbYmFzZU1vZHVsZV0pKTtcblxuICAgICAgICAvKiBDb25maWd1cmF0aW9uIHV0aWxpdGllcyBpbXBvcnQgKi9cbiAgICAgICAgaW1wb3J0cy5zZXQoXCIuLi9jb25maWdcIiwgbmV3IFNldChbXCJhcHBseURlZmF1bHRzXCIsIFwiZGVmYXVsdE9wdGlvbnNcIl0pKTtcblxuICAgICAgICAvKiBDb21wb25lbnQgY2xhc3MgaW1wb3J0cyAtIGRlcml2ZSBtb2R1bGUgcGF0aCBmcm9tIGNvbXBvbmVudCBjbGFzcyBuYW1lICovXG4gICAgICAgIGNvbnN0IGNvbXBvbmVudHMgPSBvcHRpb25zLmNvbXBvbmVudHMgPz8gREVGQVVMVF9DT01QT05FTlRTO1xuICAgICAgICBmb3IgKGNvbnN0IGMgb2YgY29tcG9uZW50cykge1xuICAgICAgICAgICAgY29uc3QgY29tcG9uZW50TmFtZSA9IGMuY29tcG9uZW50Lm5hbWU7XG4gICAgICAgICAgICBjb25zdCBtb2R1bGVQYXRoID0gYC4uL2NvbXBvbmVudHMvJHtjb21wb25lbnROYW1lLnRvTG93ZXJDYXNlKCl9YDtcbiAgICAgICAgICAgIGlmICghaW1wb3J0cy5oYXMobW9kdWxlUGF0aCkpIHtcbiAgICAgICAgICAgICAgICBpbXBvcnRzLnNldChtb2R1bGVQYXRoLCBuZXcgU2V0KCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbW9kdWxlSW1wb3J0cyA9IGltcG9ydHMuZ2V0KG1vZHVsZVBhdGgpO1xuICAgICAgICAgICAgaWYgKG1vZHVsZUltcG9ydHMpIHtcbiAgICAgICAgICAgICAgICBtb2R1bGVJbXBvcnRzLmFkZChjb21wb25lbnROYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8qIFV0aWxpdHkgZnVuY3Rpb25zIGltcG9ydCAqL1xuICAgICAgICBpbXBvcnRzLnNldChcIi4uL3V0aWxzXCIsIG5ldyBTZXQoW1wiZGVlcE1lcmdlXCJdKSk7XG5cbiAgICAgICAgLyogR2VuZXJhdGVkIG9wdGlvbnMgaW50ZXJmYWNlIGltcG9ydCAodHlwZS1vbmx5IHRvIGF2b2lkIGNpcmN1bGFyIGRlcGVuZGVuY2llcykgKi9cbiAgICAgICAgaW1wb3J0cy5zZXQoYC4vJHtvcHRpb25zRmlsZU5hbWV9LmdlbmVyYXRlZGAsIG5ldyBTZXQoW29wdGlvbnNJbnRlcmZhY2VdKSk7XG5cbiAgICAgICAgcmV0dXJuIGltcG9ydHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVyaXZlcyB0aGUgY29uZmlnIHBhdGggZm9yIGFjY2Vzc2luZyBkZWZhdWx0IG9wdGlvbnNcbiAgICAgKlxuICAgICAqIFRyYW5zZm9ybXMgYmFzZSBjbGFzcyByZWZlcmVuY2UgaW50byB0aGUgY29ycmVzcG9uZGluZyBwYXRoIGluIHRoZSBkZWZhdWx0T3B0aW9uc1xuICAgICAqIGNvbmZpZ3VyYXRpb24gb2JqZWN0IGV4cG9ydGVkIGZyb20gY29uZmlnLnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIGJhc2VDbGFzcyAtIEJhc2UgY2xhc3MgaW4gZm9ybWF0IFwibW9kdWxlLkNsYXNzTmFtZVwiXG4gICAgICogQHJldHVybnMgQ29uZmlnIHBhdGggZm9yIGFjY2Vzc2luZyBkZWZhdWx0IG9wdGlvbnNcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogZ2V0Q29uZmlnUGF0aChcInR5cGVzY3JpcHQuVHlwZVNjcmlwdFByb2plY3RcIikgLy8gXCJkZWZhdWx0T3B0aW9ucy50eXBlc2NyaXB0LlR5cGVTY3JpcHRQcm9qZWN0XCJcbiAgICAgKi9cbiAgICBwcml2YXRlIGdldENvbmZpZ1BhdGgoYmFzZUNsYXNzOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gYGRlZmF1bHRPcHRpb25zLiR7YmFzZUNsYXNzfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBpbXBvcnQgc3RhdGVtZW50cyBpbiBzb3J0ZWQgb3JkZXJcbiAgICAgKlxuICAgICAqIFNvcnRzIGltcG9ydHMgd2l0aCBleHRlcm5hbCBwYWNrYWdlcyBmaXJzdCwgdGhlbiByZWxhdGl2ZSBpbXBvcnRzLlxuICAgICAqIFVzZXMgdHlwZS1vbmx5IGltcG9ydHMgZm9yIGdlbmVyYXRlZCBmaWxlcyB0byBhdm9pZCBjaXJjdWxhciBkZXBlbmRlbmNpZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gaW1wb3J0cyAtIE1hcCBvZiBtb2R1bGUgcGF0aHMgdG8gaW1wb3J0ZWQgbmFtZXNcbiAgICAgKi9cbiAgICBwcml2YXRlIHJlbmRlckltcG9ydHMoaW1wb3J0czogTWFwPHN0cmluZywgU2V0PHN0cmluZz4+KSB7XG4gICAgICAgIC8qIFNvcnQgbW9kdWxlczogZXh0ZXJuYWwgcGFja2FnZXMgZmlyc3QsIHRoZW4gcmVsYXRpdmUgaW1wb3J0cyBhbHBoYWJldGljYWxseSAqL1xuICAgICAgICBjb25zdCBzb3J0ZWRNb2R1bGVzID0gQXJyYXkuZnJvbShpbXBvcnRzLmtleXMoKSkuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICAgICAgY29uc3QgYUlzUmVsYXRpdmUgPSBhLnN0YXJ0c1dpdGgoXCIuXCIpO1xuICAgICAgICAgICAgY29uc3QgYklzUmVsYXRpdmUgPSBiLnN0YXJ0c1dpdGgoXCIuXCIpO1xuICAgICAgICAgICAgaWYgKGFJc1JlbGF0aXZlICE9PSBiSXNSZWxhdGl2ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBhSXNSZWxhdGl2ZSA/IDEgOiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBhLmxvY2FsZUNvbXBhcmUoYik7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGZvciAoY29uc3QgbW9kIG9mIHNvcnRlZE1vZHVsZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IG5hbWVzID0gQXJyYXkuZnJvbShpbXBvcnRzLmdldChtb2QpIHx8IFtdKS5zb3J0KCk7XG4gICAgICAgICAgICAvKiBVc2UgdHlwZS1vbmx5IGltcG9ydCBmb3IgZ2VuZXJhdGVkIGZpbGVzIHRvIHByZXZlbnQgY2lyY3VsYXIgZGVwZW5kZW5jaWVzICovXG4gICAgICAgICAgICBjb25zdCBpc1R5cGVPbmx5ID0gbW9kLmluY2x1ZGVzKFwiLmdlbmVyYXRlZFwiKTtcbiAgICAgICAgICAgIGNvbnN0IGltcG9ydFN0bXQgPSBpc1R5cGVPbmx5ID8gXCJpbXBvcnQgdHlwZVwiIDogXCJpbXBvcnRcIjtcbiAgICAgICAgICAgIHRoaXMuYnVmZmVyLmxpbmUoYCR7aW1wb3J0U3RtdH0geyAke25hbWVzLmpvaW4oXCIsIFwiKX0gfSBmcm9tIFwiJHttb2R9XCI7YCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHJlLWV4cG9ydCBzdGF0ZW1lbnQgZm9yIHRoZSBnZW5lcmF0ZWQgb3B0aW9ucyBpbnRlcmZhY2VcbiAgICAgKlxuICAgICAqIEBwYXJhbSBvcHRpb25zSW50ZXJmYWNlIC0gTmFtZSBvZiB0aGUgb3B0aW9ucyBpbnRlcmZhY2UgdG8gZXhwb3J0XG4gICAgICovXG4gICAgcHJpdmF0ZSByZW5kZXJFeHBvcnQob3B0aW9uc0ludGVyZmFjZTogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnNGaWxlTmFtZSA9IHRoaXMuZ2V0T3B0aW9uc0ZpbGVOYW1lKG9wdGlvbnNJbnRlcmZhY2UpO1xuICAgICAgICB0aGlzLmJ1ZmZlci5saW5lKCk7XG4gICAgICAgIHRoaXMuYnVmZmVyLmxpbmUoYGV4cG9ydCB7ICR7b3B0aW9uc0ludGVyZmFjZX0gfSBmcm9tIFwiLi8ke29wdGlvbnNGaWxlTmFtZX0uZ2VuZXJhdGVkXCI7YCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgY2xhc3MgZGVjbGFyYXRpb24gYW5kIGNvbnN0cnVjdG9yXG4gICAgICpcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIEdlbmVyYXRvciBjb25maWd1cmF0aW9uXG4gICAgICogQHBhcmFtIG9wdGlvbnNJbnRlcmZhY2UgLSBOYW1lIG9mIHRoZSBvcHRpb25zIGludGVyZmFjZVxuICAgICAqIEBwYXJhbSBiYXNlT3B0aW9uc1R5cGUgLSBCYXNlIG9wdGlvbnMgdHlwZSB3aXRob3V0IFwicHJvamVuLlwiIHByZWZpeFxuICAgICAqIEBwYXJhbSBkZXN0cnVjdHVyZSAtIFZhcmlhYmxlIG5hbWVzIHRvIGRlc3RydWN0dXJlIGZyb20gb3B0aW9uc1xuICAgICAqIEBwYXJhbSBjb21wb25lbnRBcnJheSAtIENvZGUgc3RyaW5nIGZvciBjb21wb25lbnQgYXJyYXlcbiAgICAgKi9cbiAgICBwcml2YXRlIHJlbmRlckNsYXNzKFxuICAgICAgICBvcHRpb25zOiBQcm9qZW5Qcm9qZWN0R2VuZXJhdG9yT3B0aW9uczxQcm9qZW5Nb2R1bGU+LFxuICAgICAgICBvcHRpb25zSW50ZXJmYWNlOiBzdHJpbmcsXG4gICAgICAgIGJhc2VPcHRpb25zVHlwZTogc3RyaW5nLFxuICAgICAgICBkZXN0cnVjdHVyZTogc3RyaW5nW10sXG4gICAgICAgIGNvbXBvbmVudEFycmF5OiBzdHJpbmcsXG4gICAgKSB7XG4gICAgICAgIHRoaXMuYnVmZmVyLmxpbmUoKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZShcIi8qKlwiKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZShgICogJHtvcHRpb25zLm5hbWV9IHdpdGggc3RhbmRhcmQgY29uZmlndXJhdGlvbiBhbmQgY29tcG9uZW50IGludGVncmF0aW9uYCk7XG4gICAgICAgIHRoaXMuYnVmZmVyLmxpbmUoXCIgKlwiKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZShcIiAqIEV4dGVuZHMgUHJvamVuJ3MgYmFzZSBjbGFzcyB3aXRoIG9waW5pb25hdGVkIGRlZmF1bHRzIGFuZCBhdXRvbWF0aWMgY29tcG9uZW50IHNldHVwLlwiKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZShcIiAqL1wiKTtcbiAgICAgICAgdGhpcy5idWZmZXIub3BlbihgZXhwb3J0IGNsYXNzICR7b3B0aW9ucy5uYW1lfSBleHRlbmRzICR7b3B0aW9ucy5iYXNlQ2xhc3N9IHtgKTtcbiAgICAgICAgdGhpcy5yZW5kZXJDb25zdHJ1Y3RvcihvcHRpb25zLCBvcHRpb25zSW50ZXJmYWNlLCBiYXNlT3B0aW9uc1R5cGUsIGRlc3RydWN0dXJlLCBjb21wb25lbnRBcnJheSk7XG4gICAgICAgIHRoaXMuYnVmZmVyLmNsb3NlKFwifVwiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBjb25zdHJ1Y3RvciBpbXBsZW1lbnRhdGlvblxuICAgICAqXG4gICAgICogVGhlIGNvbnN0cnVjdG9yOlxuICAgICAqIDEuIERlc3RydWN0dXJlcyBjb21wb25lbnQgZmxhZ3MgYW5kIG9wdGlvbnMgZnJvbSB0aGUgb3B0aW9ucyBwYXJhbWV0ZXJcbiAgICAgKiAyLiBNZXJnZXMgZGVmYXVsdCBjb25maWd1cmF0aW9uIHdpdGggdXNlci1wcm92aWRlZCBvcHRpb25zXG4gICAgICogMy4gQ2FsbHMgc3VwZXIoKSB3aXRoIG1lcmdlZCBvcHRpb25zXG4gICAgICogNC4gQXBwbGllcyBjb21wb25lbnQgZGVmYXVsdHMgdmlhIGFwcGx5RGVmYXVsdHMoKVxuICAgICAqXG4gICAgICogQHBhcmFtIG9wdGlvbnMgLSBHZW5lcmF0b3IgY29uZmlndXJhdGlvblxuICAgICAqIEBwYXJhbSBvcHRpb25zSW50ZXJmYWNlIC0gTmFtZSBvZiB0aGUgb3B0aW9ucyBpbnRlcmZhY2VcbiAgICAgKiBAcGFyYW0gYmFzZU9wdGlvbnNUeXBlIC0gQmFzZSBvcHRpb25zIHR5cGUgd2l0aG91dCBcInByb2plbi5cIiBwcmVmaXhcbiAgICAgKiBAcGFyYW0gZGVzdHJ1Y3R1cmUgLSBWYXJpYWJsZSBuYW1lcyB0byBkZXN0cnVjdHVyZSBmcm9tIG9wdGlvbnNcbiAgICAgKiBAcGFyYW0gY29tcG9uZW50QXJyYXkgLSBDb2RlIHN0cmluZyBmb3IgY29tcG9uZW50IGFycmF5XG4gICAgICovXG4gICAgcHJpdmF0ZSByZW5kZXJDb25zdHJ1Y3RvcihcbiAgICAgICAgb3B0aW9uczogUHJvamVuUHJvamVjdEdlbmVyYXRvck9wdGlvbnM8UHJvamVuTW9kdWxlPixcbiAgICAgICAgb3B0aW9uc0ludGVyZmFjZTogc3RyaW5nLFxuICAgICAgICBiYXNlT3B0aW9uc1R5cGU6IHN0cmluZyxcbiAgICAgICAgZGVzdHJ1Y3R1cmU6IHN0cmluZ1tdLFxuICAgICAgICBjb21wb25lbnRBcnJheTogc3RyaW5nLFxuICAgICkge1xuICAgICAgICBjb25zdCBjb25maWdQYXRoID0gdGhpcy5nZXRDb25maWdQYXRoKG9wdGlvbnMuYmFzZUNsYXNzKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZShcIi8qKlwiKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZShcIiAqIEBwYXJhbSBvcHRpb25zIC0gUHJvamVjdCBjb25maWd1cmF0aW9uXCIpO1xuICAgICAgICB0aGlzLmJ1ZmZlci5saW5lKFwiICovXCIpO1xuICAgICAgICB0aGlzLmJ1ZmZlci5vcGVuKGBjb25zdHJ1Y3RvcihvcHRpb25zOiAke29wdGlvbnNJbnRlcmZhY2V9KSB7YCk7XG4gICAgICAgIHRoaXMuYnVmZmVyLmxpbmUoXCIvKiBTZXBhcmF0ZSBjb21wb25lbnQgY29uZmlndXJhdGlvbiBmcm9tIGJhc2UgUHJvamVuIG9wdGlvbnMgKi9cIik7XG4gICAgICAgIHRoaXMuYnVmZmVyLmxpbmUoYGNvbnN0IHsgJHtkZXN0cnVjdHVyZS5qb2luKFwiLCBcIil9LCAuLi5iYXNlT3B0aW9ucyB9ID0gb3B0aW9ucztgKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZSgpO1xuICAgICAgICB0aGlzLmJ1ZmZlci5saW5lKFwiLyogTWVyZ2UgZGVmYXVsdCBjb25maWd1cmF0aW9uIHdpdGggdXNlciBvcHRpb25zIGFuZCBpbml0aWFsaXplIGJhc2UgY2xhc3MgKi9cIik7XG4gICAgICAgIHRoaXMuYnVmZmVyLmxpbmUoYHN1cGVyKGRlZXBNZXJnZTwke2Jhc2VPcHRpb25zVHlwZX0+KCR7Y29uZmlnUGF0aH0sIGJhc2VPcHRpb25zKSk7YCk7XG4gICAgICAgIHRoaXMuYnVmZmVyLmxpbmUoKTtcbiAgICAgICAgdGhpcy5idWZmZXIubGluZShcIi8qIEFwcGx5IGNvbXBvbmVudCBkZWZhdWx0cyBhbmQgaW5zdGFudGlhdGUgZW5hYmxlZCBjb21wb25lbnRzICovXCIpO1xuICAgICAgICB0aGlzLmJ1ZmZlci5saW5lKGBhcHBseURlZmF1bHRzKHRoaXMsICR7Y29tcG9uZW50QXJyYXl9KTtgKTtcbiAgICAgICAgdGhpcy5idWZmZXIuY2xvc2UoXCJ9XCIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1hcHMgb3B0aW9ucyBpbnRlcmZhY2UgbmFtZSB0byBmaWxlIG5hbWVcbiAgICAgKlxuICAgICAqIENvbnZlcnRzIFBhc2NhbENhc2UgaW50ZXJmYWNlIG5hbWVzIHRvIGtlYmFiLWNhc2UgZmlsZSBuYW1lcy5cbiAgICAgKiBGYWxscyBiYWNrIHRvIGxvd2VyY2FzZSBjb252ZXJzaW9uIGZvciB1bm1hcHBlZCBpbnRlcmZhY2VzLlxuICAgICAqXG4gICAgICogQHBhcmFtIG9wdGlvbnNJbnRlcmZhY2UgLSBPcHRpb25zIGludGVyZmFjZSBuYW1lXG4gICAgICogQHJldHVybnMgS2ViYWItY2FzZSBmaWxlIG5hbWUgd2l0aG91dCBleHRlbnNpb25cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogZ2V0T3B0aW9uc0ZpbGVOYW1lKFwiVHlwZVNjcmlwdFByb2plY3RPcHRpb25zXCIpIC8vIFwidHlwZXNjcmlwdC1vcHRpb25zXCJcbiAgICAgKi9cbiAgICBnZXRPcHRpb25zRmlsZU5hbWUob3B0aW9uc0ludGVyZmFjZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgbWFwcGluZzogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgICAgICAgIFR5cGVTY3JpcHRQcm9qZWN0T3B0aW9uczogXCJ0eXBlc2NyaXB0LW9wdGlvbnNcIixcbiAgICAgICAgICAgIEpzaWlQcm9qZWN0T3B0aW9uczogXCJqc2lpLW9wdGlvbnNcIixcbiAgICAgICAgICAgIEF3c0Nka1R5cGVTY3JpcHRBcHBQcm9qZWN0T3B0aW9uczogXCJhd3NjZGstdHlwZXNjcmlwdC1hcHAtb3B0aW9uc1wiLFxuICAgICAgICAgICAgQXdzQ2RrQ29uc3RydWN0TGlicmFyeVByb2plY3RPcHRpb25zOiBcImF3c2Nkay1jb25zdHJ1Y3QtbGlicmFyeS1vcHRpb25zXCIsXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBtYXBwaW5nW29wdGlvbnNJbnRlcmZhY2VdIHx8IG9wdGlvbnNJbnRlcmZhY2UudG9Mb3dlckNhc2UoKTtcbiAgICB9XG59XG5cbi8qKlxuICogUHJvamVuIGNvbXBvbmVudCB0aGF0IGdlbmVyYXRlcyBUeXBlU2NyaXB0IHByb2plY3QgY2xhc3NlcyB3aXRoIHN0YW5kYXJkIGNvbmZpZ3VyYXRpb25cbiAqXG4gKiBUaGlzIGNvbXBvbmVudCBhdXRvbWF0ZXMgdGhlIGNyZWF0aW9uIG9mIHByb2plY3QgY2xhc3NlcyB0aGF0IGV4dGVuZCBQcm9qZW4gYmFzZSBjbGFzc2VzXG4gKiB3aXRoIG9waW5pb25hdGVkIGRlZmF1bHRzIGFuZCBjb21wb25lbnQgaW50ZWdyYXRpb24uIEl0IGdlbmVyYXRlcyBib3RoOlxuICogMS4gQW4gb3B0aW9ucyBpbnRlcmZhY2UgKHZpYSBQcm9qZW5TdHJ1Y3QpIHRoYXQgZXh0ZW5kcyB0aGUgYmFzZSBQcm9qZW4gb3B0aW9uc1xuICogMi4gQSBwcm9qZWN0IGNsYXNzIHRoYXQgYXBwbGllcyBkZWZhdWx0IGNvbmZpZ3VyYXRpb24gYW5kIGluc3RhbnRpYXRlcyBjb21wb25lbnRzXG4gKlxuICogVGhlIGdlbmVyYXRlZCBjb2RlIGZvbGxvd3MgYSBjb25zaXN0ZW50IHBhdHRlcm46XG4gKiAtIEltcG9ydHMgcmVxdWlyZWQgbW9kdWxlcyBhbmQgY29tcG9uZW50c1xuICogLSBSZS1leHBvcnRzIHRoZSBnZW5lcmF0ZWQgb3B0aW9ucyBpbnRlcmZhY2VcbiAqIC0gRGVmaW5lcyBhIGNsYXNzIGV4dGVuZGluZyB0aGUgUHJvamVuIGJhc2UgY2xhc3NcbiAqIC0gQ29uc3RydWN0b3IgbWVyZ2VzIGRlZmF1bHRzIHdpdGggdXNlciBvcHRpb25zIGFuZCBhcHBsaWVzIGNvbXBvbmVudHNcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogbmV3IFByb2plblByb2plY3RHZW5lcmF0b3IocHJvamVjdCwge1xuICogICBuYW1lOiBcIlR5cGVTY3JpcHRQcm9qZWN0XCIsXG4gKiAgIGJhc2VDbGFzczogXCJ0eXBlc2NyaXB0LlR5cGVTY3JpcHRQcm9qZWN0XCIsXG4gKiAgIGZpbGVQYXRoOiBcInNyYy9wcm9qZWN0cy90eXBlc2NyaXB0LmdlbmVyYXRlZC50c1wiLFxuICogICBjb21wb25lbnRzOiBbeyBjb21wb25lbnQ6IFZpdGVzdCwgb3B0aW9uc1Byb3BlcnR5OiBcInZpdGVzdE9wdGlvbnNcIiB9XVxuICogfSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIFByb2plblByb2plY3RHZW5lcmF0b3IgZXh0ZW5kcyBDb21wb25lbnQge1xuICAgIHByaXZhdGUgcmVuZGVyZXI6IFR5cGVTY3JpcHRDbGFzc1JlbmRlcmVyO1xuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHByb2plY3QgLSBQcm9qZW4gcHJvamVjdCBpbnN0YW5jZVxuICAgICAqIEBwYXJhbSBvcHRpb25zIC0gR2VuZXJhdG9yIGNvbmZpZ3VyYXRpb25cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJvamVjdDogUHJvamVjdCxcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBvcHRpb25zOiBQcm9qZW5Qcm9qZWN0R2VuZXJhdG9yT3B0aW9uczxQcm9qZW5Nb2R1bGU+LFxuICAgICkge1xuICAgICAgICBzdXBlcihwcm9qZWN0KTtcbiAgICAgICAgdGhpcy5yZW5kZXJlciA9IG5ldyBUeXBlU2NyaXB0Q2xhc3NSZW5kZXJlcigpO1xuXG4gICAgICAgIC8qIEdlbmVyYXRlIHRoZSBvcHRpb25zIGludGVyZmFjZSB1c2luZyBQcm9qZW5TdHJ1Y3QgZm9yIEpTSUkgY29tcGF0aWJpbGl0eSAqL1xuICAgICAgICBjb25zdCBvcHRpb25zSW50ZXJmYWNlID0gYCR7b3B0aW9ucy5uYW1lfU9wdGlvbnNgO1xuICAgICAgICBjb25zdCBiYXNlT3B0aW9uc0ZxbiA9IHRoaXMucmVuZGVyZXIuZ2V0QmFzZU9wdGlvbnNGcW4ob3B0aW9ucy5iYXNlQ2xhc3MpO1xuICAgICAgICBjb25zdCBvcHRpb25zRmlsZVBhdGggPSB0aGlzLmdldE9wdGlvbnNGaWxlUGF0aChvcHRpb25zSW50ZXJmYWNlKTtcblxuICAgICAgICAvKiBQcm9qZW5TdHJ1Y3QgZ2VuZXJhdGVzIGEgY29uY3JldGUgVHlwZVNjcmlwdCBpbnRlcmZhY2UgZnJvbSBQcm9qZW4ncyBvcHRpb25zXG4gICAgICAgICAqIFRoaXMgaXMgbmVjZXNzYXJ5IGJlY2F1c2UgSlNJSSBkb2Vzbid0IHN1cHBvcnQgVHlwZVNjcmlwdCB1dGlsaXR5IHR5cGVzIGxpa2UgT21pdDw+XG4gICAgICAgICAqIFRoZSBnZW5lcmF0ZWQgaW50ZXJmYWNlIGNhbiBiZSBjb25zdW1lZCBieSBvdGhlciBsYW5ndWFnZXMgKFB5dGhvbiwgSmF2YSwgQyMsIEdvKSAqL1xuICAgICAgICBjb25zdCBzdHJ1Y3QgPSBuZXcgUHJvamVuU3RydWN0KHRoaXMuYXNUeXBlU2NyaXB0UHJvamVjdChwcm9qZWN0KSwge1xuICAgICAgICAgICAgbmFtZTogb3B0aW9uc0ludGVyZmFjZSxcbiAgICAgICAgICAgIGZpbGVQYXRoOiBvcHRpb25zRmlsZVBhdGgsXG4gICAgICAgICAgICBvdXRwdXRGaWxlT3B0aW9uczogeyByZWFkb25seTogdHJ1ZSB9LFxuICAgICAgICB9KVxuICAgICAgICAgICAgLm1peGluKFN0cnVjdC5mcm9tRnFuKGJhc2VPcHRpb25zRnFuKSlcbiAgICAgICAgICAgIC53aXRob3V0RGVwcmVjYXRlZCgpO1xuXG4gICAgICAgIC8qIFJlbW92ZSBzcGVjaWZpZWQgb3B0aW9ucyBmcm9tIHRoZSBiYXNlIGludGVyZmFjZSAqL1xuICAgICAgICBpZiAob3B0aW9ucy5vbWl0T3B0aW9ucykge1xuICAgICAgICAgICAgc3RydWN0Lm9taXQoLi4ub3B0aW9ucy5vbWl0T3B0aW9ucyk7XG4gICAgICAgIH1cblxuICAgICAgICAvKiBBZGQgY29tcG9uZW50LWRlcml2ZWQgb3B0aW9ucyB0byB0aGUgaW50ZXJmYWNlICovXG4gICAgICAgIGNvbnN0IGNvbXBvbmVudHMgPSBvcHRpb25zLmNvbXBvbmVudHMgPz8gREVGQVVMVF9DT01QT05FTlRTO1xuICAgICAgICBjb25zdCB7IFByaW1pdGl2ZVR5cGUgfSA9IHJlcXVpcmUoXCJAanNpaS9zcGVjXCIpO1xuXG4gICAgICAgIGZvciAoY29uc3QgYyBvZiBjb21wb25lbnRzKSB7XG4gICAgICAgICAgICBjb25zdCBuYW1lID0gYy5jb21wb25lbnQubmFtZS5jaGFyQXQoMCkudG9Mb3dlckNhc2UoKSArIGMuY29tcG9uZW50Lm5hbWUuc2xpY2UoMSk7XG5cbiAgICAgICAgICAgIC8qIEFkZCBlbmFibGVkIGZsYWcgZm9yIHRoZSBjb21wb25lbnQgKi9cbiAgICAgICAgICAgIHN0cnVjdC5hZGQoe1xuICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgdHlwZTogeyBwcmltaXRpdmU6IFByaW1pdGl2ZVR5cGUuQm9vbGVhbiB9LFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRvY3M6IHtcbiAgICAgICAgICAgICAgICAgICAgc3VtbWFyeTogYEVuYWJsZSAke2MuY29tcG9uZW50Lm5hbWV9IGNvbXBvbmVudGAsXG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6IFwidHJ1ZVwiLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLyogQWRkIG9wdGlvbnMgcHJvcGVydHkgaWYgY29tcG9uZW50IGlzIGNvbmZpZ3VyYWJsZSAqL1xuICAgICAgICAgICAgaWYgKGMub3B0aW9uc1Byb3BlcnR5KSB7XG4gICAgICAgICAgICAgICAgc3RydWN0LmFkZCh7XG4gICAgICAgICAgICAgICAgICAgIG5hbWU6IGMub3B0aW9uc1Byb3BlcnR5Lm5hbWUsXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IHsgZnFuOiBjLm9wdGlvbnNQcm9wZXJ0eS50eXBlIH0sXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbmFsOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBkb2NzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJ5OiBjLm9wdGlvbnNQcm9wZXJ0eS5kb2NzID8/IGAke2MuY29tcG9uZW50Lm5hbWV9IGNvbmZpZ3VyYXRpb25gLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDogYC0gZGVmYXVsdCAke2MuY29tcG9uZW50Lm5hbWV9IGNvbmZpZ3VyYXRpb25gLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLyogQWRkIGN1c3RvbSBvcHRpb25zIHRvIHRoZSBpbnRlcmZhY2UgKi9cbiAgICAgICAgaWYgKG9wdGlvbnMuYWRkaXRpb25hbE9wdGlvbnMpIHtcbiAgICAgICAgICAgIHN0cnVjdC5hZGQoLi4ub3B0aW9ucy5hZGRpdGlvbmFsT3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYXN0cyBwcm9qZWN0IHRvIFR5cGVTY3JpcHQgcHJvamVjdCB0eXBlXG4gICAgICpcbiAgICAgKiBQcm9qZW5TdHJ1Y3QgcmVxdWlyZXMgYSBUeXBlU2NyaXB0UHJvamVjdCBpbnN0YW5jZS4gVGhpcyBnZW5lcmF0b3IgaXMgb25seSB1c2VkXG4gICAgICogd2l0aGluIFR5cGVTY3JpcHQgcHJvamVjdHMsIHNvIHRoZSBjYXN0IGlzIHNhZmUgaW4gcHJhY3RpY2UuXG4gICAgICpcbiAgICAgKiBOb3RlOiBUeXBlIGFzc2VydGlvbiBpcyBuZWNlc3NhcnkgaGVyZSBiZWNhdXNlIFByb2plbidzIHR5cGUgc3lzdGVtIGRvZXNuJ3QgcHJvdmlkZVxuICAgICAqIGEgcnVudGltZSB0eXBlIGd1YXJkIGZvciBUeXBlU2NyaXB0UHJvamVjdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBwcm9qZWN0IC0gUHJvamVuIHByb2plY3QgaW5zdGFuY2VcbiAgICAgKiBAcmV0dXJucyBUeXBlU2NyaXB0IHByb2plY3QgaW5zdGFuY2VcbiAgICAgKi9cbiAgICBwcml2YXRlIGFzVHlwZVNjcmlwdFByb2plY3QocHJvamVjdDogUHJvamVjdCk6IHR5cGVzY3JpcHQuVHlwZVNjcmlwdFByb2plY3Qge1xuICAgICAgICByZXR1cm4gcHJvamVjdCBhcyB1bmtub3duIGFzIHR5cGVzY3JpcHQuVHlwZVNjcmlwdFByb2plY3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVyaXZlcyB0aGUgZmlsZSBwYXRoIGZvciB0aGUgZ2VuZXJhdGVkIG9wdGlvbnMgaW50ZXJmYWNlXG4gICAgICpcbiAgICAgKiBQbGFjZXMgdGhlIG9wdGlvbnMgaW50ZXJmYWNlIGZpbGUgaW4gdGhlIHNhbWUgZGlyZWN0b3J5IGFzIHRoZSBjbGFzcyBmaWxlXG4gICAgICogd2l0aCBhIFwiLmdlbmVyYXRlZC50c1wiIHN1ZmZpeC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBvcHRpb25zSW50ZXJmYWNlIC0gTmFtZSBvZiB0aGUgb3B0aW9ucyBpbnRlcmZhY2VcbiAgICAgKiBAcmV0dXJucyBGaWxlIHBhdGggZm9yIHRoZSBvcHRpb25zIGludGVyZmFjZVxuICAgICAqIEB0aHJvd3Mge0ludmFsaWRGaWxlUGF0aEVycm9yfSBXaGVuIGZpbGVQYXRoIGRvZXNuJ3QgY29udGFpbiBhIGRpcmVjdG9yeSBzZXBhcmF0b3JcbiAgICAgKi9cbiAgICBwcml2YXRlIGdldE9wdGlvbnNGaWxlUGF0aChvcHRpb25zSW50ZXJmYWNlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCBsYXN0U2xhc2ggPSB0aGlzLm9wdGlvbnMuZmlsZVBhdGgubGFzdEluZGV4T2YoXCIvXCIpO1xuICAgICAgICBpZiAobGFzdFNsYXNoID09PSAtMSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEludmFsaWRGaWxlUGF0aEVycm9yKHRoaXMub3B0aW9ucy5maWxlUGF0aCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkaXIgPSB0aGlzLm9wdGlvbnMuZmlsZVBhdGguc3Vic3RyaW5nKDAsIGxhc3RTbGFzaCk7XG4gICAgICAgIGNvbnN0IG9wdGlvbnNGaWxlTmFtZSA9IHRoaXMucmVuZGVyZXIuZ2V0T3B0aW9uc0ZpbGVOYW1lKG9wdGlvbnNJbnRlcmZhY2UpO1xuICAgICAgICByZXR1cm4gYCR7ZGlyfS8ke29wdGlvbnNGaWxlTmFtZX0uZ2VuZXJhdGVkLnRzYDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZXMgdGhlIFR5cGVTY3JpcHQgY2xhc3MgZmlsZSBkdXJpbmcgUHJvamVuIHN5bnRoZXNpc1xuICAgICAqXG4gICAgICogQ2FsbGVkIGJ5IFByb2plbiBkdXJpbmcgdGhlIHN5bnRoZXNpcyBwaGFzZSB0byBnZW5lcmF0ZSB0aGUgcHJvamVjdCBjbGFzcyBmaWxlLlxuICAgICAqIFRoZSBmaWxlIGlzIG1hcmtlZCBhcyByZWFkb25seSB0byBwcmV2ZW50IG1hbnVhbCBlZGl0aW5nLlxuICAgICAqL1xuICAgIHByZVN5bnRoZXNpemUoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSB0aGlzLnJlbmRlcmVyLnJlbmRlcih0aGlzLm9wdGlvbnMpO1xuXG4gICAgICAgIG5ldyBUeXBlU2NyaXB0Q2xhc3NGaWxlKHRoaXMucHJvamVjdCwgdGhpcy5vcHRpb25zLmZpbGVQYXRoLCBjb250ZW50LCB7XG4gICAgICAgICAgICByZWFkb25seTogdGhpcy5vcHRpb25zLnJlYWRvbmx5ID8/IHRydWUsXG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuLyoqXG4gKiBUZXh0IGZpbGUgZm9yIGdlbmVyYXRlZCBUeXBlU2NyaXB0IGNsYXNzIGNvZGVcbiAqXG4gKiBFeHRlbmRzIFByb2plbidzIFRleHRGaWxlIHRvIGFkZCB0aGUgZ2VuZXJhdGVkIGZpbGUgbWFya2VyIGNvbW1lbnRcbiAqIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGZpbGUuXG4gKi9cbmNsYXNzIFR5cGVTY3JpcHRDbGFzc0ZpbGUgZXh0ZW5kcyBUZXh0RmlsZSB7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHByb2plY3QgLSBQcm9qZW4gcHJvamVjdCBpbnN0YW5jZVxuICAgICAqIEBwYXJhbSBmaWxlUGF0aCAtIE91dHB1dCBmaWxlIHBhdGhcbiAgICAgKiBAcGFyYW0gY29udGVudCAtIFR5cGVTY3JpcHQgY2xhc3MgY29kZVxuICAgICAqIEBwYXJhbSBvcHRpb25zIC0gU291cmNlIGNvZGUgb3B0aW9ucyAocmVhZG9ubHksIGV0Yy4pXG4gICAgICovXG4gICAgY29uc3RydWN0b3IocHJvamVjdDogUHJvamVjdCwgZmlsZVBhdGg6IHN0cmluZywgY29udGVudDogc3RyaW5nLCBvcHRpb25zOiBTb3VyY2VDb2RlT3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIHN1cGVyKHByb2plY3QsIGZpbGVQYXRoLCBvcHRpb25zKTtcbiAgICAgICAgLyogQWRkIGdlbmVyYXRlZCBmaWxlIG1hcmtlciB0byBwcmV2ZW50IG1hbnVhbCBlZGl0aW5nICovXG4gICAgICAgIHRoaXMuYWRkTGluZShgLy8gJHt0aGlzLm1hcmtlcn1gKTtcbiAgICAgICAgdGhpcy5hZGRMaW5lKGNvbnRlbnQpO1xuICAgIH1cbn1cbiJdfQ==
|
package/package.json
CHANGED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { Project, SourceCodeOptions } from "projen";
|
|
2
|
-
import { Component } from "projen";
|
|
3
|
-
export interface ProjenProjectClassOptions extends SourceCodeOptions {
|
|
4
|
-
/**
|
|
5
|
-
* The name of the generated class
|
|
6
|
-
*/
|
|
7
|
-
readonly name: string;
|
|
8
|
-
/**
|
|
9
|
-
* The base class to extend (e.g., "typescript.TypeScriptProject")
|
|
10
|
-
*/
|
|
11
|
-
readonly baseClass: string;
|
|
12
|
-
/**
|
|
13
|
-
* The options interface name (e.g., "TypeScriptProjectOptions")
|
|
14
|
-
*/
|
|
15
|
-
readonly optionsInterface: string;
|
|
16
|
-
/**
|
|
17
|
-
* The base options type (e.g., "typescript.TypeScriptProjectOptions")
|
|
18
|
-
*/
|
|
19
|
-
readonly baseOptionsType: string;
|
|
20
|
-
/**
|
|
21
|
-
* The default config constant name (e.g., "typescriptProjectDefaultOptions")
|
|
22
|
-
*/
|
|
23
|
-
readonly defaultConfig: string;
|
|
24
|
-
/**
|
|
25
|
-
* Output file path
|
|
26
|
-
*/
|
|
27
|
-
readonly filePath: string;
|
|
28
|
-
/**
|
|
29
|
-
* Custom options to extract from constructor
|
|
30
|
-
* @default ["mise", "vitest", "vitestOptions"]
|
|
31
|
-
*/
|
|
32
|
-
readonly customOptions?: string[];
|
|
33
|
-
/**
|
|
34
|
-
* Indentation size
|
|
35
|
-
* @default 4
|
|
36
|
-
*/
|
|
37
|
-
readonly indent?: number;
|
|
38
|
-
}
|
|
39
|
-
export declare class ProjenProjectClass extends Component {
|
|
40
|
-
private readonly options;
|
|
41
|
-
private renderer;
|
|
42
|
-
constructor(project: Project, options: ProjenProjectClassOptions);
|
|
43
|
-
preSynthesize(): void;
|
|
44
|
-
}
|