@rosen-bridge/config 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/config.js CHANGED
@@ -2,577 +2,591 @@ import * as fs from 'fs';
2
2
  import * as yaml from 'js-yaml';
3
3
  import JsonBigIntFactory from 'json-bigint';
4
4
  import path from 'path';
5
- import {
6
- propertyValidators,
7
- supportedTypes,
8
- } from './schema/Validators/fieldProperties';
5
+ import { propertyValidators, supportedTypes, } from './schema/Validators/fieldProperties';
9
6
  import { getSourceName, getValueFromConfigSources } from './utils';
10
7
  import { valueValidations, valueValidators } from './value/validators';
11
8
  export class ConfigValidator {
12
- schema;
13
- constructor(schema) {
14
- this.schema = schema;
15
- this.validateSchema();
16
- }
17
- /**
18
- * validates the passed config against the instance's schema
19
- *
20
- * @param {Record<string, any>} config
21
- */
22
- validateConfig(config) {
23
- const errorPreamble = (path) =>
24
- `config validation failed for "${path.join('.')}" field`;
25
- const stack = [
26
- {
27
- subSchema: this.schema,
28
- subConfig: config,
29
- parentPath: [],
30
- },
31
- ];
32
- this.validateValue(
33
- config,
34
- { type: 'object', children: this.schema },
35
- config
36
- );
37
- // Traverses the schema object tree depth first in coordination with config
38
- // object tree and validate config using the schema
39
- while (stack.length > 0) {
40
- const { subSchema, subConfig, parentPath } = stack.pop();
41
- // Process children of current field
42
- for (const name of Object.keys(subSchema)) {
43
- const path = parentPath.concat([name]);
44
- try {
45
- const field = subSchema[name];
46
- let value = undefined;
47
- if (subConfig != undefined && Object.hasOwn(subConfig, name)) {
48
- value = subConfig[name];
49
- }
50
- this.validateValue(value, field, config);
51
- // if a node/field is of type object and thus is a subtree, add it to
52
- // the stack to be traversed later
53
- if (field.type === 'object') {
54
- stack.push({
55
- subSchema: field.children,
56
- subConfig: value,
57
- parentPath: path,
58
- });
59
- }
60
- } catch (error) {
61
- throw new Error(`${errorPreamble(path)}: ${error.message}`);
62
- }
63
- }
9
+ schema;
10
+ constructor(schema) {
11
+ this.schema = schema;
12
+ this.validateSchema();
64
13
  }
65
- }
66
- /**
67
- * validates a value in config object
68
- *
69
- * @private
70
- * @param {*} value
71
- * @param {ConfigField} field the field specification in schema
72
- * @param {Record<string, any>} config the config object
73
- */
74
- validateValue = (value, field, config) => {
75
- if (value != undefined) {
76
- if (field.type === 'bigint') {
77
- value = BigInt(value);
78
- } else if (field.type === 'number' && value && !isNaN(value)) {
79
- value = Number(value);
80
- }
81
- valueValidators[field.type](value, field);
14
+ /**
15
+ * validates the passed config against the instance's schema
16
+ *
17
+ * @param {Record<string, any>} config
18
+ */
19
+ validateConfig(config) {
20
+ this.validateValue(config, { type: 'object', children: this.schema }, config);
21
+ this.validateSubConfig(config, config, this.schema, []);
82
22
  }
83
- if (field.type != 'object' && field.validations) {
84
- for (const validation of field.validations) {
85
- const name = Object.keys(validation).filter(
86
- (key) => key !== 'when' && key !== 'error'
87
- )[0];
88
- if (Object.hasOwn(valueValidations[field.type], name)) {
89
- try {
90
- valueValidations[field.type][name](value, validation, config, this);
91
- } catch (error) {
92
- if (validation.error != undefined) {
93
- throw new Error(validation.error);
23
+ /**
24
+ * traverses and validates a subconfig using the subschema
25
+ *
26
+ * @private
27
+ * @param {Record<string, any>} config
28
+ * @param {Record<string, any>} subConfig
29
+ * @param {ConfigSchema} subSchema
30
+ * @param {string[]} path
31
+ * @memberof ConfigValidator
32
+ */
33
+ validateSubConfig(config, subConfig, subSchema, path) {
34
+ const errorPreamble = (path) => `config validation failed for "${path.join('.')}" field`;
35
+ for (const name of Object.keys(subSchema)) {
36
+ const childPath = path.concat([name]);
37
+ try {
38
+ const field = subSchema[name];
39
+ let value = undefined;
40
+ if (subConfig != undefined && Object.hasOwn(subConfig, name)) {
41
+ value = subConfig[name];
42
+ }
43
+ this.validateValue(value, field, config);
44
+ // if a node/field is of type object and thus is a subtree, traverse it
45
+ if (field.type === 'object') {
46
+ this.validateSubConfig(config, value, field.children, childPath);
47
+ }
48
+ else if (field.type === 'array') {
49
+ if (Array.isArray(value)) {
50
+ for (const item of value) {
51
+ ConfigValidator.modifyObject(config, item, childPath);
52
+ this.validateSubConfig(config, { [name]: item }, { [name]: field.items }, childPath);
53
+ ConfigValidator.modifyObject(config, value, childPath);
54
+ }
55
+ }
56
+ }
57
+ }
58
+ catch (error) {
59
+ throw new Error(`${errorPreamble(childPath)}: ${error.message}`);
94
60
  }
95
- throw error;
96
- }
97
61
  }
98
- }
99
62
  }
100
- };
101
- /**
102
- * determines if a when clause in validations section of a schema field is
103
- * satisfied
104
- *
105
- * @param {When} when
106
- * @param {Record<string, any>} config
107
- * @return {boolean}
108
- */
109
- isWhenTrue = (when, config) => {
110
- const pathParts = when.path.split('.');
111
- const value = ConfigValidator.valueAt(config, pathParts);
112
- return value != undefined && value === when.value;
113
- };
114
- /**
115
- * returns the value at specified path in config object
116
- *
117
- * @static
118
- * @param {Record<string, any>} config
119
- * @param {string[]} path
120
- * @return {*}
121
- */
122
- static valueAt = (config, path) => {
123
- let value = config;
124
- for (const key of path) {
125
- if (value != undefined && Object.hasOwn(value, key)) {
126
- value = value[key];
127
- } else {
128
- return undefined;
129
- }
130
- }
131
- return value;
132
- };
133
- /**
134
- * validates this.schema and throws exception if any errors found
135
- */
136
- validateSchema = () => {
137
- const errorPreamble = (path) =>
138
- `Schema validation failed for "${path.join('.')}" field`;
139
- const stack = [
140
- {
141
- subSchema: this.schema,
142
- parentPath: [],
143
- },
144
- ];
145
- // Traverses the schema object tree depth first and validate fields
146
- while (stack.length > 0) {
147
- const { subSchema, parentPath } = stack.pop();
148
- // process children of current object field
149
- for (const name of Object.keys(subSchema).reverse()) {
150
- const path = parentPath.concat([name]);
151
- try {
152
- this.validateConfigName(name);
153
- const field = subSchema[name];
154
- if (!Object.hasOwn(field, 'type') || typeof field.type !== 'string') {
155
- throw new Error(
156
- `every schema field must have a "type" property of type "string"`
157
- );
158
- }
159
- if (!supportedTypes.includes(field.type)) {
160
- throw new Error(`unsupported field type "${field.type}"`);
161
- }
162
- this.validateSchemaField(field);
163
- // if the child is an object field itself add it to stack for
164
- // processing
165
- if (field.type === 'object') {
166
- stack.push({
167
- subSchema: field.children,
168
- parentPath: path,
169
- });
170
- }
171
- } catch (error) {
172
- throw new Error(`${errorPreamble(path)}: ${error.message}`);
63
+ /**
64
+ * sets an object's specific subtree to the specified value
65
+ *
66
+ * @static
67
+ * @param {Record<string, any>} obj
68
+ * @param {*} newValue
69
+ * @param {string[]} path
70
+ * @return {*}
71
+ * @memberof ConfigValidator
72
+ */
73
+ static modifyObject(obj, newValue, path) {
74
+ let value = obj;
75
+ for (const key of path.slice(0, -1)) {
76
+ if (value != undefined && Object.hasOwn(value, key)) {
77
+ value = value[key];
78
+ }
79
+ else {
80
+ return;
81
+ }
173
82
  }
174
- }
175
- }
176
- };
177
- /**
178
- * validates config key name
179
- *
180
- * @param {string} name
181
- */
182
- validateConfigName = (name) => {
183
- if (name.includes('.')) {
184
- throw new Error(`config key name can not contain the '.' character`);
185
- }
186
- };
187
- /**
188
- * validates passed schema field structure
189
- *
190
- * @param {ConfigField} field
191
- */
192
- validateSchemaField = (field) => {
193
- for (const key of Object.keys(field)) {
194
- if (
195
- !Object.hasOwn(propertyValidators.all, key) &&
196
- !(
197
- field.type !== 'object' &&
198
- Object.hasOwn(propertyValidators.primitive, key)
199
- ) &&
200
- !Object.hasOwn(propertyValidators[field.type], key)
201
- ) {
202
- throw new Error(`schema field has unknown property "${key}"`);
203
- }
204
- }
205
- for (const validator of Object.values(propertyValidators.all)) {
206
- validator(field, this);
207
- }
208
- if (field.type !== 'object') {
209
- for (const validator of Object.values(propertyValidators.primitive)) {
210
- validator(field, this);
211
- }
212
- }
213
- for (const validator of Object.values(propertyValidators[field.type])) {
214
- validator(field, this);
215
- }
216
- };
217
- /**
218
- * returns a field corresponding to a path in schema tree
219
- *
220
- * @param {string[]} path
221
- * @return {(ConfigField | undefined)} returns undefined if field is not found
222
- */
223
- getSchemaField = (path) => {
224
- let subTree = this.schema;
225
- let field = undefined;
226
- for (const part of path) {
227
- if (subTree != undefined && Object.hasOwn(subTree, part)) {
228
- field = subTree[part];
229
- subTree = 'children' in field ? field.children : undefined;
230
- } else {
231
- return undefined;
232
- }
233
- }
234
- return field;
235
- };
236
- /**
237
- * extracts default values from a schema
238
- *
239
- * @return {Record<string, any>} object of default values
240
- */
241
- generateDefault = () => {
242
- const valueTree = Object.create(null);
243
- const stack = [
244
- {
245
- schema: this.schema,
246
- parentValue: undefined,
247
- fieldName: '',
248
- children: Object.keys(this.schema).reverse(),
249
- },
250
- ];
251
- // Traverses the schema object tree depth first
252
- while (stack.length > 0) {
253
- const { schema, parentValue, fieldName, children } = stack.at(-1);
254
- // if a subtree's processing is finished go to the previous level
255
- if (children.length === 0) {
256
- // if a subtree is empty (has no values) remove it from the result
257
- if (
258
- parentValue != undefined &&
259
- Object.keys(parentValue[fieldName]).length === 0
260
- ) {
261
- delete parentValue[fieldName];
83
+ const lastKey = path.at(-1);
84
+ if (lastKey != undefined) {
85
+ value[lastKey] = newValue;
262
86
  }
263
- stack.pop();
264
- continue;
265
- }
266
- const childName = children.pop();
267
- const value =
268
- parentValue != undefined ? parentValue[fieldName] : valueTree;
269
- const field = schema[childName];
270
- // if a node/field is of type object and thus is a subtree, add it both to
271
- // value tree and to the stack to be traversed later. Otherwise it's a
272
- // leaf and needs no traversal, so add it only to the value tree.
273
- if (field.type === 'object') {
274
- value[childName] = Object.create(null);
275
- stack.push({
276
- schema: field.children,
277
- parentValue: value,
278
- fieldName: childName,
279
- children: Object.keys(field.children).reverse(),
280
- });
281
- } else if (field.default != undefined) {
282
- value[childName] = field.default;
283
- }
284
87
  }
285
- return valueTree;
286
- };
287
- /**
288
- * generates compatible TypeScript interface for this instance's schema
289
- *
290
- * @param {string} name the name of root type
291
- * @return {string}
292
- */
293
- generateTSTypes = (name) => {
294
- const errorPreamble = (path) =>
295
- `TypeScript type generation failed for "${path.join('.')}" field`;
296
- const types = [];
297
- const typeNames = new Map();
298
- typeNames.set(name, 1n);
299
- const stack = [
300
- {
301
- subSchema: this.schema,
302
- children: Object.keys(this.schema),
303
- parentPath: [],
304
- typeName: name,
305
- attributes: [],
306
- },
307
- ];
308
- // Traverses the schema object tree depth first
309
- while (stack.length > 0) {
310
- const { subSchema, children, parentPath, typeName, attributes } =
311
- stack.at(-1);
312
- const path = parentPath.concat([name]);
313
- try {
314
- // if a subtree's processing is finished go to the previous level
315
- if (children.length == 0) {
316
- types.push(this.genTSInterface(typeName, attributes));
317
- stack.pop();
318
- continue;
88
+ /**
89
+ * validates a value in config object
90
+ *
91
+ * @private
92
+ * @param {*} value
93
+ * @param {ConfigField} field the field specification in schema
94
+ * @param {Record<string, any>} config the config object
95
+ */
96
+ validateValue = (value, field, config) => {
97
+ if (value != undefined) {
98
+ if (field.type === 'bigint') {
99
+ value = BigInt(value);
100
+ }
101
+ else if (field.type === 'number' && value && !isNaN(value)) {
102
+ value = Number(value);
103
+ }
104
+ valueValidators[field.type](value, field);
319
105
  }
320
- const childName = children.pop();
321
- const field = subSchema[childName];
322
- // if a node/field is of type object and thus is a subtree, add it to
323
- // the stack to be traversed later. Otherwise it's a leaf and needs no
324
- // traversal.
325
- if (field.type === 'object') {
326
- let childTypeName = `${childName[0].toUpperCase()}${childName.substring(
327
- 1
328
- )}`;
329
- const typeNameCount = typeNames.get(childTypeName);
330
- typeNames.set(childTypeName, (typeNames.get(childName) || 0n) + 1n);
331
- if (typeNameCount) {
332
- childTypeName += typeNameCount.toString();
333
- }
334
- stack.push({
335
- subSchema: field.children,
336
- children: Object.keys(field.children).reverse(),
337
- parentPath: path,
338
- typeName: childTypeName,
339
- attributes: [],
340
- });
341
- attributes.push([childName, childTypeName]);
342
- } else {
343
- attributes.push([childName, field.type]);
106
+ if (field.type !== 'object' &&
107
+ field.type !== 'array' &&
108
+ field.validations) {
109
+ for (const validation of field.validations) {
110
+ const name = Object.keys(validation).filter((key) => key !== 'when' && key !== 'error')[0];
111
+ if (Object.hasOwn(valueValidations[field.type], name)) {
112
+ try {
113
+ valueValidations[field.type][name](value, validation, config, this);
114
+ }
115
+ catch (error) {
116
+ if (validation.error != undefined) {
117
+ throw new Error(validation.error);
118
+ }
119
+ throw error;
120
+ }
121
+ }
122
+ }
344
123
  }
345
- } catch (error) {
346
- throw new Error(`${errorPreamble(path)}: ${error.message}`);
347
- }
348
- }
349
- return types.reverse().join('\n\n') + '\n';
350
- };
351
- /**
352
- * generates a TypeScript interface definition for passed name and attributes
353
- *
354
- * @param {string} name
355
- * @param {Array<[string, string]>} attributes
356
- * @return {string}
357
- */
358
- genTSInterface = (name, attributes) => {
359
- return `interface ${name} {
124
+ };
125
+ /**
126
+ * determines if a when clause in validations section of a schema field is
127
+ * satisfied
128
+ *
129
+ * @param {When} when
130
+ * @param {Record<string, any>} config
131
+ * @return {boolean}
132
+ */
133
+ isWhenTrue = (when, config) => {
134
+ const pathParts = when.path.split('.');
135
+ const value = ConfigValidator.valueAt(config, pathParts);
136
+ return value != undefined && value === when.value;
137
+ };
138
+ /**
139
+ * returns the value at specified path in config object
140
+ *
141
+ * @static
142
+ * @param {Record<string, any>} config
143
+ * @param {string[]} path
144
+ * @return {*}
145
+ */
146
+ static valueAt = (config, path) => {
147
+ let value = config;
148
+ for (const key of path) {
149
+ if (value != undefined && Object.hasOwn(value, key)) {
150
+ value = value[key];
151
+ }
152
+ else {
153
+ return undefined;
154
+ }
155
+ }
156
+ return value;
157
+ };
158
+ /**
159
+ * validates this.schema and throws exception if any errors found
160
+ */
161
+ validateSchema = () => {
162
+ const errorPreamble = (path) => `Schema validation failed for "${path.join('.')}" field`;
163
+ const stack = [
164
+ {
165
+ subSchema: this.schema,
166
+ parentPath: [],
167
+ },
168
+ ];
169
+ // Traverses the schema object tree depth first and validate fields
170
+ while (stack.length > 0) {
171
+ const { subSchema, parentPath } = stack.pop();
172
+ // process children of current object field
173
+ for (const name of Object.keys(subSchema).reverse()) {
174
+ const path = parentPath.concat([name]);
175
+ try {
176
+ this.validateConfigName(name);
177
+ const field = subSchema[name];
178
+ if (!Object.hasOwn(field, 'type') || typeof field.type !== 'string') {
179
+ throw new Error(`every schema field must have a "type" property of type "string"`);
180
+ }
181
+ if (!supportedTypes.includes(field.type)) {
182
+ throw new Error(`unsupported field type "${field.type}"`);
183
+ }
184
+ this.validateSchemaField(field);
185
+ // if the child is an object field itself add it to stack for
186
+ // processing
187
+ if (field.type === 'object') {
188
+ stack.push({
189
+ subSchema: field.children,
190
+ parentPath: path,
191
+ });
192
+ }
193
+ else if (field.type === 'array') {
194
+ stack.push({
195
+ subSchema: { [name]: field.items },
196
+ parentPath: path,
197
+ });
198
+ }
199
+ }
200
+ catch (error) {
201
+ throw new Error(`${errorPreamble(path)}: ${error.message}`);
202
+ }
203
+ }
204
+ }
205
+ };
206
+ /**
207
+ * validates config key name
208
+ *
209
+ * @param {string} name
210
+ */
211
+ validateConfigName = (name) => {
212
+ if (name.includes('.')) {
213
+ throw new Error(`config key name can not contain the '.' character`);
214
+ }
215
+ };
216
+ /**
217
+ * validates passed schema field structure
218
+ *
219
+ * @param {ConfigField} field
220
+ */
221
+ validateSchemaField = (field) => {
222
+ for (const key of Object.keys(field)) {
223
+ if (!Object.hasOwn(propertyValidators.all, key) &&
224
+ !(!['object', 'array'].includes(field.type) &&
225
+ Object.hasOwn(propertyValidators.primitive, key)) &&
226
+ !Object.hasOwn(propertyValidators[field.type], key)) {
227
+ throw new Error(`schema field has unknown property "${key}"`);
228
+ }
229
+ }
230
+ for (const validator of Object.values(propertyValidators.all)) {
231
+ validator(field, this);
232
+ }
233
+ if (field.type !== 'object' && field.type !== 'array') {
234
+ for (const validator of Object.values(propertyValidators.primitive)) {
235
+ validator(field, this);
236
+ }
237
+ }
238
+ for (const validator of Object.values(propertyValidators[field.type])) {
239
+ validator(field, this);
240
+ }
241
+ };
242
+ /**
243
+ * returns a field corresponding to a path in schema tree
244
+ *
245
+ * @param {string[]} path
246
+ * @return {(ConfigField | undefined)} returns undefined if field is not found
247
+ */
248
+ getSchemaField = (path) => {
249
+ let subTree = this.schema;
250
+ let field = undefined;
251
+ for (const part of path) {
252
+ if (subTree != undefined && Object.hasOwn(subTree, part)) {
253
+ field = subTree[part];
254
+ subTree =
255
+ 'children' in field
256
+ ? field.children
257
+ : 'items' in field && 'children' in field.items
258
+ ? field.items.children
259
+ : undefined;
260
+ }
261
+ else {
262
+ return undefined;
263
+ }
264
+ }
265
+ return field;
266
+ };
267
+ /**
268
+ * extracts default values from a schema
269
+ *
270
+ * @return {Record<string, any>} object of default values
271
+ */
272
+ generateDefault = () => {
273
+ const valueTree = Object.create(null);
274
+ const stack = [
275
+ {
276
+ schema: this.schema,
277
+ parentValue: undefined,
278
+ fieldName: '',
279
+ children: Object.keys(this.schema).reverse(),
280
+ },
281
+ ];
282
+ // Traverses the schema object tree depth first
283
+ while (stack.length > 0) {
284
+ const { schema, parentValue, fieldName, children } = stack.at(-1);
285
+ // if a subtree's processing is finished go to the previous level
286
+ if (children.length === 0) {
287
+ // if a subtree is empty (has no values) remove it from the result
288
+ if (parentValue != undefined &&
289
+ Object.keys(parentValue[fieldName]).length === 0) {
290
+ delete parentValue[fieldName];
291
+ }
292
+ stack.pop();
293
+ continue;
294
+ }
295
+ const childName = children.pop();
296
+ const value = parentValue != undefined ? parentValue[fieldName] : valueTree;
297
+ const field = schema[childName];
298
+ // if a node/field is of type object and thus is a subtree, add it both to
299
+ // value tree and to the stack to be traversed later. Otherwise it's a
300
+ // leaf and needs no traversal, so add it only to the value tree.
301
+ if (field.type === 'object') {
302
+ value[childName] = Object.create(null);
303
+ stack.push({
304
+ schema: field.children,
305
+ parentValue: value,
306
+ fieldName: childName,
307
+ children: Object.keys(field.children).reverse(),
308
+ });
309
+ }
310
+ else if (field.type !== 'array' && field.default != undefined) {
311
+ value[childName] = field.default;
312
+ }
313
+ }
314
+ return valueTree;
315
+ };
316
+ /**
317
+ * generates compatible TypeScript interface for this instance's schema
318
+ *
319
+ * @param {string} name the name of root type
320
+ * @return {string}
321
+ */
322
+ generateTSTypes = (name) => {
323
+ const errorPreamble = (path) => `TypeScript type generation failed for "${path.join('.')}" field`;
324
+ const types = [];
325
+ const typeNames = new Map();
326
+ typeNames.set(name, 1n);
327
+ const stack = [
328
+ {
329
+ subSchema: this.schema,
330
+ children: Object.keys(this.schema),
331
+ parentPath: [],
332
+ typeName: name,
333
+ attributes: [],
334
+ },
335
+ ];
336
+ // Traverses the schema object tree depth first
337
+ while (stack.length > 0) {
338
+ const { subSchema, children, parentPath, typeName, attributes } = stack.at(-1);
339
+ const path = parentPath.concat([name]);
340
+ try {
341
+ // if a subtree's processing is finished go to the previous level
342
+ if (children.length == 0) {
343
+ types.push(this.genTSInterface(typeName, attributes));
344
+ stack.pop();
345
+ continue;
346
+ }
347
+ const childName = children.pop();
348
+ const field = subSchema[childName];
349
+ // if a node/field is of type object and thus is a subtree, add it to
350
+ // the stack to be traversed later. Otherwise it's a leaf and needs no
351
+ // traversal.
352
+ if (field.type === 'object' ||
353
+ (field.type === 'array' && field.items.type === 'object')) {
354
+ let childTypeName = `${childName[0].toUpperCase()}${childName.substring(1)}`;
355
+ const typeNameCount = typeNames.get(childTypeName);
356
+ typeNames.set(childTypeName, (typeNames.get(childName) || 0n) + 1n);
357
+ if (typeNameCount) {
358
+ childTypeName += typeNameCount.toString();
359
+ }
360
+ const children = field.type === 'array' && field.items.type === 'object'
361
+ ? field.items.children
362
+ : field.type === 'object'
363
+ ? field.children
364
+ : {};
365
+ stack.push({
366
+ subSchema: children,
367
+ children: Object.keys(children).reverse(),
368
+ parentPath: path,
369
+ typeName: childTypeName,
370
+ attributes: [],
371
+ });
372
+ attributes.push([
373
+ childName,
374
+ field.type === 'array' ? `${childTypeName}[]` : childTypeName,
375
+ ]);
376
+ }
377
+ else {
378
+ let fieldType = field.type === 'array' ? field.items.type : field.type;
379
+ let isOptional = true;
380
+ if (field.type !== 'array' && field.validations != undefined) {
381
+ for (const validation of field.validations) {
382
+ if (field.type === 'string' && 'choices' in validation) {
383
+ fieldType = validation.choices.map((c) => `'${c}'`).join(' | ');
384
+ }
385
+ if ('required' in validation && !('when' in validation)) {
386
+ isOptional = false;
387
+ }
388
+ }
389
+ }
390
+ attributes.push([
391
+ isOptional ? `${childName}?` : childName,
392
+ field.type === 'array' ? `${fieldType}[]` : fieldType,
393
+ ]);
394
+ }
395
+ }
396
+ catch (error) {
397
+ throw new Error(`${errorPreamble(path)}: ${error.message}`);
398
+ }
399
+ }
400
+ return types.reverse().join('\n\n') + '\n';
401
+ };
402
+ /**
403
+ * generates a TypeScript interface definition for passed name and attributes
404
+ *
405
+ * @param {string} name
406
+ * @param {Array<[string, string]>} attributes
407
+ * @return {string}
408
+ */
409
+ genTSInterface = (name, attributes) => {
410
+ return `export interface ${name} {
360
411
  ${attributes.map((attr) => `${attr[0]}: ${attr[1]};`).join('\n ')}
361
412
  }`;
362
- };
363
- /**
364
- * returns a characteristic object for values at a specific node config level
365
- *
366
- * @param {IConfig} config
367
- * @param {string} level
368
- * @return {Record<string, any>}
369
- */
370
- getConfigForLevel(config, level) {
371
- const confLevels = ConfigValidator.getNodeConfigLevels(config);
372
- const levelIndex = confLevels.indexOf(level);
373
- if (levelIndex === -1) {
374
- throw new Error(
375
- `The "${level}" level not found in the current system configuration levels`
376
- );
377
- }
378
- const higherLevelSources = config.util
379
- .getConfigSources()
380
- .filter(
381
- (source) => confLevels.indexOf(getSourceName(source)) > levelIndex
382
- );
383
- const currentLevelSource = config.util
384
- .getConfigSources()
385
- .filter((source) => getSourceName(source) === level)
386
- .at(0);
387
- const lowerLevelSources = config.util
388
- .getConfigSources()
389
- .filter(
390
- (source) => confLevels.indexOf(getSourceName(source)) < levelIndex
391
- );
392
- // Traverses the schema object tree depth first
393
- const valueTree = ConfigValidator.processConfigForLevelNode(
394
- this.schema,
395
- [],
396
- higherLevelSources,
397
- currentLevelSource,
398
- lowerLevelSources
399
- );
400
- return valueTree;
401
- }
402
- /**
403
- *traverses the config schema depth first to produce characteristic object
404
- *
405
- * @private
406
- * @static
407
- * @param {ConfigSchema} schema
408
- * @param {string[]} path
409
- * @param {IConfigSource[]} higherLevelSources
410
- * @param {(IConfigSource | undefined)} currentLevelSource
411
- * @param {IConfigSource[]} lowerLevelSources
412
- * @return {Record<string, any>}
413
- * @memberof ConfigValidator
414
- */
415
- static processConfigForLevelNode(
416
- schema,
417
- path,
418
- higherLevelSources,
419
- currentLevelSource,
420
- lowerLevelSources
421
- ) {
422
- const value = Object.create(null);
423
- for (const childName of Object.keys(schema).reverse()) {
424
- const childPath = path.concat([childName]);
425
- const field = schema[childName];
426
- // if a field is of type object and thus is a subtree, recurse on it.
427
- // Otherwise it's a leaf and needs no traversal.
428
- value[childName] = Object.create(null);
429
- if (field.type === 'object') {
430
- value[childName] = ConfigValidator.processConfigForLevelNode(
431
- field.children,
432
- childPath,
433
- higherLevelSources,
434
- currentLevelSource,
435
- lowerLevelSources
436
- );
437
- } else {
438
- value[childName]['label'] =
439
- field.label != undefined ? field.label : null;
440
- value[childName]['description'] =
441
- field.description != undefined ? field.description : null;
442
- value[childName]['default'] = getValueFromConfigSources(
443
- lowerLevelSources,
444
- childPath
445
- );
446
- value[childName]['value'] = getValueFromConfigSources(
447
- [...(currentLevelSource != undefined ? [currentLevelSource] : [])],
448
- childPath
449
- );
450
- value[childName]['override'] = getValueFromConfigSources(
451
- higherLevelSources,
452
- childPath
453
- );
454
- }
455
- }
456
- return value;
457
- }
458
- /**
459
- * returns a list of config sources used by node config package, ordered from
460
- * the lowest to the highest priority
461
- *
462
- * @static
463
- * @param {IConfig} config
464
- * @return {string[]}
465
- */
466
- static getNodeConfigLevels = (config) => {
467
- const instance = config.util.getEnv('NODE_APP_INSTANCE');
468
- let deployment = config.util.getEnv('NODE_ENV');
469
- deployment = config.util.getEnv('NODE_CONFIG_ENV');
470
- const fullHostname = config.util.getEnv('HOSTNAME');
471
- const shortHostname =
472
- fullHostname != undefined ? fullHostname.split('.')[0] : undefined;
473
- const configLevels = [
474
- 'default',
475
- ...(instance != undefined ? [`default-${instance}`] : []),
476
- ...(deployment != undefined ? [`${deployment}`] : []),
477
- ...(instance != undefined && deployment != undefined
478
- ? [`${deployment}-${instance}`]
479
- : []),
480
- ...(shortHostname != undefined ? [`${shortHostname}`] : []),
481
- ...(shortHostname != undefined && instance != undefined
482
- ? [`${shortHostname}-${instance}`]
483
- : []),
484
- ...(shortHostname != undefined && deployment != undefined
485
- ? [`${shortHostname}-${deployment}`]
486
- : []),
487
- ...(shortHostname != undefined &&
488
- deployment != undefined &&
489
- instance != undefined
490
- ? [`${shortHostname}-${deployment}-${instance}`]
491
- : []),
492
- ...(fullHostname != undefined ? [`${fullHostname}`] : []),
493
- ...(fullHostname != undefined && instance != undefined
494
- ? [`${fullHostname}-${instance}`]
495
- : []),
496
- ...(fullHostname != undefined && deployment != undefined
497
- ? [`${fullHostname}-${deployment}`]
498
- : []),
499
- ...(fullHostname != undefined &&
500
- deployment != undefined &&
501
- instance != undefined
502
- ? [`${fullHostname}-${deployment}-${instance}`]
503
- : []),
504
- `local`,
505
- ...(instance != undefined ? [`local-${instance}`] : []),
506
- ...(deployment != undefined ? [`local-${deployment}`] : []),
507
- ...(deployment != undefined && instance != undefined
508
- ? [`local-${deployment}-${instance}`]
509
- : []),
510
- '$NODE_CONFIG',
511
- 'custom-environment-variables',
512
- ];
513
- return configLevels;
514
- };
515
- /**
516
- * validates a config object and writes it to the node-config file
517
- * corresponding to the passed level
518
- *
519
- * @param {Record<string, any>} configObj
520
- * @param {IConfig} config
521
- * @param {string} level output node-config file level
522
- * @param {string} format the format of the output file
523
- */
524
- validateAndWriteConfig = (configObj, config, level, format) => {
525
- const confLevels = ConfigValidator.getNodeConfigLevels(config).filter(
526
- (l) => l !== 'custom-environment-variables'
527
- );
528
- const levelIndex = confLevels.indexOf(level);
529
- if (levelIndex === -1) {
530
- throw new Error(
531
- `The [${level}] level not found in the current system's configuration levels`
532
- );
533
- }
534
- const configDir =
535
- process.env['NODE_CONFIG_DIR'] != undefined
536
- ? process.env['NODE_CONFIG_DIR']
537
- : './config';
538
- let output = '';
539
- let ext = '';
540
- switch (format) {
541
- case 'json': {
542
- const JsonBigInt = JsonBigIntFactory({
543
- alwaysParseAsBig: false,
544
- useNativeBigInt: true,
545
- });
546
- output = JsonBigInt.stringify(configObj);
547
- ext = 'json';
548
- break;
549
- }
550
- case 'yaml': {
551
- output = yaml.dump(configObj);
552
- ext = 'yaml';
553
- break;
554
- }
555
- default:
556
- throw Error(`Invalid format: ${format}`);
557
- }
558
- const outputPath = path.join(configDir, `${level}.${ext}`);
559
- const backupPath = path.join(configDir, `${level}-backup.${ext}`);
560
- const confFileExists = fs.existsSync(outputPath);
561
- if (confFileExists) {
562
- fs.renameSync(outputPath, backupPath);
413
+ };
414
+ /**
415
+ * returns a characteristic object for values at a specific node config level
416
+ *
417
+ * @param {IConfig} config
418
+ * @param {string} level
419
+ * @return {Record<string, any>}
420
+ */
421
+ getConfigForLevel(config, level) {
422
+ const confLevels = ConfigValidator.getNodeConfigLevels(config);
423
+ const levelIndex = confLevels.indexOf(level);
424
+ if (levelIndex === -1) {
425
+ throw new Error(`The "${level}" level not found in the current system configuration levels`);
426
+ }
427
+ const higherLevelSources = config.util
428
+ .getConfigSources()
429
+ .filter((source) => confLevels.indexOf(getSourceName(source)) > levelIndex);
430
+ const currentLevelSource = config.util
431
+ .getConfigSources()
432
+ .filter((source) => getSourceName(source) === level)
433
+ .at(0);
434
+ const lowerLevelSources = config.util
435
+ .getConfigSources()
436
+ .filter((source) => confLevels.indexOf(getSourceName(source)) < levelIndex);
437
+ // Traverses the schema object tree depth first
438
+ const valueTree = ConfigValidator.processConfigForLevelNode(this.schema, [], higherLevelSources, currentLevelSource, lowerLevelSources);
439
+ return valueTree;
563
440
  }
564
- fs.writeFileSync(outputPath, output);
565
- const updatedConfObj = config.util.loadFileConfigs();
566
- try {
567
- this.validateConfig(updatedConfObj);
568
- fs.unlinkSync(backupPath);
569
- } catch (error) {
570
- fs.unlinkSync(outputPath);
571
- if (confFileExists) {
572
- fs.renameSync(backupPath, outputPath);
573
- }
574
- throw error;
441
+ /**
442
+ *traverses the config schema depth first to produce characteristic object
443
+ *
444
+ * @private
445
+ * @static
446
+ * @param {ConfigSchema} schema
447
+ * @param {string[]} path
448
+ * @param {IConfigSource[]} higherLevelSources
449
+ * @param {(IConfigSource | undefined)} currentLevelSource
450
+ * @param {IConfigSource[]} lowerLevelSources
451
+ * @return {Record<string, any>}
452
+ * @memberof ConfigValidator
453
+ */
454
+ static processConfigForLevelNode(schema, path, higherLevelSources, currentLevelSource, lowerLevelSources) {
455
+ const value = Object.create(null);
456
+ for (const childName of Object.keys(schema).reverse()) {
457
+ const childPath = path.concat([childName]);
458
+ const field = schema[childName];
459
+ // if a field is of type object and thus is a subtree, recurse on it.
460
+ // Otherwise it's a leaf and needs no traversal.
461
+ value[childName] = Object.create(null);
462
+ if (field.type === 'object') {
463
+ value[childName] = ConfigValidator.processConfigForLevelNode(field.children, childPath, higherLevelSources, currentLevelSource, lowerLevelSources);
464
+ }
465
+ else {
466
+ value[childName]['label'] =
467
+ field.label != undefined ? field.label : null;
468
+ value[childName]['description'] =
469
+ field.description != undefined ? field.description : null;
470
+ value[childName]['default'] = getValueFromConfigSources(lowerLevelSources, childPath);
471
+ value[childName]['value'] = getValueFromConfigSources([...(currentLevelSource != undefined ? [currentLevelSource] : [])], childPath);
472
+ value[childName]['override'] = getValueFromConfigSources(higherLevelSources, childPath);
473
+ }
474
+ }
475
+ return value;
575
476
  }
576
- };
477
+ /**
478
+ * returns a list of config sources used by node config package, ordered from
479
+ * the lowest to the highest priority
480
+ *
481
+ * @static
482
+ * @param {IConfig} config
483
+ * @return {string[]}
484
+ */
485
+ static getNodeConfigLevels = (config) => {
486
+ const instance = config.util.getEnv('NODE_APP_INSTANCE');
487
+ let deployment = config.util.getEnv('NODE_ENV');
488
+ deployment = config.util.getEnv('NODE_CONFIG_ENV');
489
+ const fullHostname = config.util.getEnv('HOSTNAME');
490
+ const shortHostname = fullHostname != undefined ? fullHostname.split('.')[0] : undefined;
491
+ const configLevels = [
492
+ 'default',
493
+ ...(instance != undefined ? [`default-${instance}`] : []),
494
+ ...(deployment != undefined ? [`${deployment}`] : []),
495
+ ...(instance != undefined && deployment != undefined
496
+ ? [`${deployment}-${instance}`]
497
+ : []),
498
+ ...(shortHostname != undefined ? [`${shortHostname}`] : []),
499
+ ...(shortHostname != undefined && instance != undefined
500
+ ? [`${shortHostname}-${instance}`]
501
+ : []),
502
+ ...(shortHostname != undefined && deployment != undefined
503
+ ? [`${shortHostname}-${deployment}`]
504
+ : []),
505
+ ...(shortHostname != undefined &&
506
+ deployment != undefined &&
507
+ instance != undefined
508
+ ? [`${shortHostname}-${deployment}-${instance}`]
509
+ : []),
510
+ ...(fullHostname != undefined ? [`${fullHostname}`] : []),
511
+ ...(fullHostname != undefined && instance != undefined
512
+ ? [`${fullHostname}-${instance}`]
513
+ : []),
514
+ ...(fullHostname != undefined && deployment != undefined
515
+ ? [`${fullHostname}-${deployment}`]
516
+ : []),
517
+ ...(fullHostname != undefined &&
518
+ deployment != undefined &&
519
+ instance != undefined
520
+ ? [`${fullHostname}-${deployment}-${instance}`]
521
+ : []),
522
+ `local`,
523
+ ...(instance != undefined ? [`local-${instance}`] : []),
524
+ ...(deployment != undefined ? [`local-${deployment}`] : []),
525
+ ...(deployment != undefined && instance != undefined
526
+ ? [`local-${deployment}-${instance}`]
527
+ : []),
528
+ '$NODE_CONFIG',
529
+ 'custom-environment-variables',
530
+ ];
531
+ return configLevels;
532
+ };
533
+ /**
534
+ * validates a config object and writes it to the node-config file
535
+ * corresponding to the passed level
536
+ *
537
+ * @param {Record<string, any>} configObj
538
+ * @param {IConfig} config
539
+ * @param {string} level output node-config file level
540
+ * @param {string} format the format of the output file
541
+ */
542
+ validateAndWriteConfig = (configObj, config, level, format) => {
543
+ const confLevels = ConfigValidator.getNodeConfigLevels(config).filter((l) => l !== 'custom-environment-variables');
544
+ const levelIndex = confLevels.indexOf(level);
545
+ if (levelIndex === -1) {
546
+ throw new Error(`The [${level}] level not found in the current system's configuration levels`);
547
+ }
548
+ const configDir = process.env['NODE_CONFIG_DIR'] != undefined
549
+ ? process.env['NODE_CONFIG_DIR']
550
+ : './config';
551
+ let output = '';
552
+ let ext = '';
553
+ switch (format) {
554
+ case 'json': {
555
+ const JsonBigInt = JsonBigIntFactory({
556
+ alwaysParseAsBig: false,
557
+ useNativeBigInt: true,
558
+ });
559
+ output = JsonBigInt.stringify(configObj);
560
+ ext = 'json';
561
+ break;
562
+ }
563
+ case 'yaml': {
564
+ output = yaml.dump(configObj);
565
+ ext = 'yaml';
566
+ break;
567
+ }
568
+ default:
569
+ throw Error(`Invalid format: ${format}`);
570
+ }
571
+ const outputPath = path.join(configDir, `${level}.${ext}`);
572
+ const backupPath = path.join(configDir, `${level}-backup.${ext}`);
573
+ const confFileExists = fs.existsSync(outputPath);
574
+ if (confFileExists) {
575
+ fs.renameSync(outputPath, backupPath);
576
+ }
577
+ fs.writeFileSync(outputPath, output);
578
+ const updatedConfObj = config.util.loadFileConfigs();
579
+ try {
580
+ this.validateConfig(updatedConfObj);
581
+ fs.unlinkSync(backupPath);
582
+ }
583
+ catch (error) {
584
+ fs.unlinkSync(outputPath);
585
+ if (confFileExists) {
586
+ fs.renameSync(backupPath, outputPath);
587
+ }
588
+ throw error;
589
+ }
590
+ };
577
591
  }
578
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vbGliL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQUN6QixPQUFPLEtBQUssSUFBSSxNQUFNLFNBQVMsQ0FBQztBQUNoQyxPQUFPLGlCQUFpQixNQUFNLGFBQWEsQ0FBQztBQUM1QyxPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixjQUFjLEdBQ2YsTUFBTSxxQ0FBcUMsQ0FBQztBQUc3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLHlCQUF5QixFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUV2RSxNQUFNLE9BQU8sZUFBZTtJQUNOO0lBQXBCLFlBQW9CLE1BQW9CO1FBQXBCLFdBQU0sR0FBTixNQUFNLENBQWM7UUFDdEMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ3hCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksY0FBYyxDQUFDLE1BQTJCO1FBQy9DLE1BQU0sYUFBYSxHQUFHLENBQUMsSUFBbUIsRUFBRSxFQUFFLENBQzVDLGlDQUFpQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUM7UUFFM0QsTUFBTSxLQUFLLEdBSU47WUFDSDtnQkFDRSxTQUFTLEVBQUUsSUFBSSxDQUFDLE1BQU07Z0JBQ3RCLFNBQVMsRUFBRSxNQUFNO2dCQUNqQixVQUFVLEVBQUUsRUFBRTthQUNmO1NBQ0YsQ0FBQztRQUVGLElBQUksQ0FBQyxhQUFhLENBQ2hCLE1BQU0sRUFDTixFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFDekMsTUFBTSxDQUNQLENBQUM7UUFFRiwyRUFBMkU7UUFDM0UsbURBQW1EO1FBQ25E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QUMsVUFBVSxDQUFDLENBQUM7UUFDakQsSUFBSSxjQUFjLEVBQUU7WUFDbEIsRUFBRSxDQUFDLFVBQVUsQ0FBQyxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7U0FDdkM7UUFDRCxFQUFFLENBQUMsYUFBYSxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUVyQyxNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBRXJELElBQUk7WUFDRixJQUFJLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQ3BDLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUM7U0FDM0I7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDMUIsSUFBSSxjQUFjLEVBQUU7Z0JBQ2xCLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLFVBQVUsQ0FBQyxDQUFDO2FBQ3ZDO1lBQ0QsTUFBTSxLQUFLLENBQUM7U0FDYjtJQUNILENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IElDb25maWcsIElDb25maWdTb3VyY2UgfSBmcm9tICdjb25maWcnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgeWFtbCBmcm9tICdqcy15YW1sJztcbmltcG9ydCBKc29uQmlnSW50RmFjdG9yeSBmcm9tICdqc29uLWJpZ2ludCc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7XG4gIHByb3BlcnR5VmFsaWRhdG9ycyxcbiAgc3VwcG9ydGVkVHlwZXMsXG59IGZyb20gJy4vc2NoZW1hL1ZhbGlkYXRvcnMvZmllbGRQcm9wZXJ0aWVzJztcbmltcG9ydCB7IENvbmZpZ0ZpZWxkLCBDb25maWdTY2hlbWEgfSBmcm9tICcuL3NjaGVtYS90eXBlcy9maWVsZHMnO1xuaW1wb3J0IHsgV2hlbiB9IGZyb20gJy4vc2NoZW1hL3R5cGVzL3ZhbGlkYXRpb25zJztcbmltcG9ydCB7IGdldFNvdXJjZU5hbWUsIGdldFZhbHVlRnJvbUNvbmZpZ1NvdXJjZXMgfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7IHZhbHVlVmFsaWRhdGlvbnMsIHZhbHVlVmFsaWRhdG9ycyB9IGZyb20gJy4vdmFsdWUvdmFsaWRhdG9ycyc7XG5cbmV4cG9ydCBjbGFzcyBDb25maWdWYWxpZGF0b3Ige1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNjaGVtYTogQ29uZmlnU2NoZW1hKSB7XG4gICAgdGhpcy52YWxpZGF0ZVNjaGVtYSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIHZhbGlkYXRlcyB0aGUgcGFzc2VkIGNvbmZpZyBhZ2FpbnN0IHRoZSBpbnN0YW5jZSdzIHNjaGVtYVxuICAgKlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IGNvbmZpZ1xuICAgKi9cbiAgcHVibGljIHZhbGlkYXRlQ29uZmlnKGNvbmZpZzogUmVjb3JkPHN0cmluZywgYW55Pikge1xuICAgIGNvbnN0IGVycm9yUHJlYW1ibGUgPSAocGF0aDogQXJyYXk8c3RyaW5nPikgPT5cbiAgICAgIGBjb25maWcgdmFsaWRhdGlvbiBmYWlsZWQgZm9yIFwiJHtwYXRoLmpvaW4oJy4nKX1cIiBmaWVsZGA7XG5cbiAgICBjb25zdCBzdGFjazogQXJyYXk8e1xuICAgICAgc3ViU2NoZW1hOiBDb25maWdTY2hlbWE7XG4gICAgICBzdWJDb25maWc6IFJlY29yZDxzdHJpbmcsIGFueT4gfCB1bmRlZmluZWQ7XG4gICAgICBwYXJlbnRQYXRoOiBBcnJheTxzdHJpbmc+O1xuICAgIH0+ID0gW1xuICAgICAge1xuICAgICAgICBzdWJTY2hlbWE6IHRoaXMuc2NoZW1hLFxuICAgICAgICBzdWJDb25maWc6IGNvbmZpZyxcbiAgICAgICAgcGFyZW50UGF0aDogW10sXG4gICAgICB9LFxuICAgIF07XG5cbiAgICB0aGlzLnZhbGlkYXRlVmFsdWUoXG4gICAgICBjb25maWcsXG4gICAgICB7IHR5cGU6ICdvYmplY3QnLCBjaGlsZHJlbjogdGhpcy5zY2hlbWEgfSxcbiAgICAgIGNvbmZpZ1xuICAgICk7XG5cbiAgICAvLyBUcmF2ZXJzZXMgdGhlIHNjaGVtYSBvYmplY3QgdHJlZSBkZXB0aCBmaXJzdCBpbiBjb29yZGluYXRpb24gd2l0aCBjb25maWdcbiAgICAvLyBvYmplY3QgdHJlZSBhbmQgdmFsaWRhdGUgY29uZmlnIHVzaW5nIHRoZSBzY2hlbWFcbiAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgeyBzdWJTY2hlbWEsIHN1YkNvbmZpZywgcGFyZW50UGF0aCB9ID0gc3RhY2sucG9wKCkhO1xuICAgICAgLy8gUHJvY2VzcyBjaGlsZHJlbiBvZiBjdXJyZW50IGZpZWxkXG4gICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmtleXMoc3ViU2NoZW1hKSkge1xuICAgICAgICBjb25zdCBwYXRoID0gcGFyZW50UGF0aC5jb25jYXQoW25hbWVdKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBmaWVsZCA9IHN1YlNjaGVtYVtuYW1lXTtcbiAgICAgICAgICBsZXQgdmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgaWYgKHN1YkNvbmZpZyAhPSB1bmRlZmluZWQgJiYgT2JqZWN0Lmhhc093bihzdWJDb25maWcsIG5hbWUpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHN1YkNvbmZpZ1tuYW1lXTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLnZhbGlkYXRlVmFsdWUodmFsdWUsIGZpZWxkLCBjb25maWcpO1xuXG4gICAgICAgICAgLy8gaWYgYSBub2RlL2ZpZWxkIGlzIG9mIHR5cGUgb2JqZWN0IGFuZCB0aHVzIGlzIGEgc3VidHJlZSwgYWRkIGl0IHRvXG4gICAgICAgICAgLy8gdGhlIHN0YWNrIHRvIGJlIHRyYXZlcnNlZCBsYXRlclxuICAgICAgICAgIGlmIChmaWVsZC50eXBlID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgc3RhY2sucHVzaCh7XG4gICAgICAgICAgICAgIHN1YlNjaGVtYTogZmllbGQuY2hpbGRyZW4sXG4gICAgICAgICAgICAgIHN1YkNvbmZpZzogdmFsdWUsXG4gICAgICAgICAgICAgIHBhcmVudFBhdGg6IHBhdGgsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZXJyb3JQcmVhbWJsZShwYXRoKX06ICR7ZXJyb3IubWVzc2FnZX1gKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiB2YWxpZGF0ZXMgYSB2YWx1ZSBpbiBjb25maWcgb2JqZWN0XG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWVcbiAgICogQHBhcmFtIHtDb25maWdGaWVsZH0gZmllbGQgdGhlIGZpZWxkIHNwZWNpZmljYXRpb24gaW4gc2NoZW1hXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gY29uZmlnIHRoZSBjb25maWcgb2JqZWN0XG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlVmFsdWUgPSAoXG4gICAgdmFsdWU6IGFueSxcbiAgICBmaWVsZDogQ29uZmlnRmllbGQsXG4gICAgY29uZmlnOiBSZWNvcmQ8c3RyaW5nLCBhbnk+XG4gICkgPT4ge1xuICAgIGlmICh2YWx1ZSAhPSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChmaWVsZC50eXBlID09PSAnYmlnaW50Jykge1xuICAgICAgICB2YWx1ZSA9IEJpZ0ludCh2YWx1ZSk7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkLnR5cGUgPT09ICdudW1iZXInICYmIHZhbHVlICYmICFpc05hTih2YWx1ZSkpIHtcbiAgICAgICAgdmFsdWUgPSBOdW1iZXIodmFsdWUpO1xuICAgICAgfVxuICAgICAgdmFsdWVWYWxpZGF0b3JzW2ZpZWxkLnR5cGVdKHZhbHVlLCBmaWVsZCk7XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkLnR5cGUgIT0gJ29iamVjdCcgJiYgZmllbGQudmFsaWRhdGlvbnMpIHtcbiAgICAgIGZvciAoY29uc3QgdmFsaWRhdGlvbiBvZiBmaWVsZC52YWxpZGF0aW9ucykge1xuICAgICAgICBjb25zdCBuYW1lID0gT2JqZWN0LmtleXModmFsaWRhdGlvbikuZmlsdGVyKFxuICAgICAgICAgIChrZXkpID0+IGtleSAhPT0gJ3doZW4nICYmIGtleSAhPT0gJ2Vycm9yJ1xuICAgICAgICApWzBdO1xuICAgICAgICBpZiAoT2JqZWN0Lmhhc093bih2YWx1ZVZhbGlkYXRpb25zW2ZpZWxkLnR5cGVdLCBuYW1lKSkge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB2YWx1ZVZhbGlkYXRpb25zW2ZpZWxkLnR5cGVdW25hbWVdKHZhbHVlLCB2YWxpZGF0aW9uLCBjb25maWcsIHRoaXMpO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgICAgICAgIGlmICh2YWxpZGF0aW9uLmVycm9yICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IodmFsaWRhdGlvbi5lcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIGRldGVybWluZXMgaWYgYSB3aGVuIGNsYXVzZSBpbiB2YWxpZGF0aW9ucyBzZWN0aW9uIG9mIGEgc2NoZW1hIGZpZWxkIGlzXG4gICAqIHNhdGlzZmllZFxuICAgKlxuICAgKiBAcGFyYW0ge1doZW59IHdoZW5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBjb25maWdcbiAgICogQHJldHVybiB7Ym9vbGVhbn1cbiAgICovXG4gIHB1YmxpYyBpc1doZW5UcnVlID0gKHdoZW46IFdoZW4sIGNvbmZpZzogUmVjb3JkPHN0cmluZywgYW55Pik6IGJvb2xlYW4gPT4ge1xuICAgIGNvbnN0IHBhdGhQYXJ0cyA9IHdoZW4ucGF0aC5zcGxpdCgnLicpO1xuICAgIGNvbnN0IHZhbHVlID0gQ29uZmlnVmFsaWRhdG9yLnZhbHVlQXQoY29uZmlnLCBwYXRoUGFydHMpO1xuICAgIHJldHVybiB2YWx1ZSAhPSB1bmRlZmluZWQgJiYgdmFsdWUgPT09IHdoZW4udmFsdWU7XG4gIH07XG5cbiAgLyoqXG4gICAqIHJldHVybnMgdGhlIHZhbHVlIGF0IHNwZWNpZmllZCBwYXRoIGluIGNvbmZpZyBvYmplY3RcbiAgICpcbiAgICogQHN0YXRpY1xuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IGNvbmZpZ1xuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBwYXRoXG4gICAqIEByZXR1cm4geyp9XG4gICAqL1xuICBzdGF0aWMgdmFsdWVBdCA9IChjb25maWc6IFJlY29yZDxzdHJpbmcsIGFueT4sIHBhdGg6IHN0cmluZ1tdKSA9PiB7XG4gICAgbGV0IHZhbHVlOiBhbnkgPSBjb25maWc7XG4gICAgZm9yIChjb25zdCBrZXkgb2YgcGF0aCkge1xuICAgICAgaWYgKHZhbHVlICE9IHVuZGVmaW5lZCAmJiBPYmplY3QuaGFzT3duKHZhbHVlLCBrZXkpKSB7XG4gICAgICAgIHZhbHVlID0gdmFsdWVba2V5XTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xuICB9O1xuXG4gIC8qKlxuICAgKiB2YWxpZGF0ZXMgdGhpcy5zY2hlbWEgYW5kIHRocm93cyBleGNlcHRpb24gaWYgYW55IGVycm9ycyBmb3VuZFxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVNjaGVtYSA9ICgpID0+IHtcbiAgICBjb25zdCBlcnJvclByZWFtYmxlID0gKHBhdGg6IEFycmF5PHN0cmluZz4pID0+XG4gICAgICBgU2NoZW1hIHZhbGlkYXRpb24gZmFpbGVkIGZvciBcIiR7cGF0aC5qb2luKCcuJyl9XCIgZmllbGRgO1xuXG4gICAgY29uc3Qgc3RhY2s6IEFycmF5PHtcbiAgICAgIHN1YlNjaGVtYTogQ29uZmlnU2NoZW1hO1xuICAgICAgcGFyZW50UGF0aDogQXJyYXk8c3RyaW5nPjtcbiAgICB9PiA9IFtcbiAgICAgIHtcbiAgICAgICAgc3ViU2NoZW1hOiB0aGlzLnNjaGVtYSxcbiAgICAgICAgcGFyZW50UGF0aDogW10sXG4gICAgICB9LFxuICAgIF07XG5cbiAgICAvLyBUcmF2ZXJzZXMgdGhlIHNjaGVtYSBvYmplY3QgdHJlZSBkZXB0aCBmaXJzdCBhbmQgdmFsaWRhdGUgZmllbGRzXG4gICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IHsgc3ViU2NoZW1hLCBwYXJlbnRQYXRoIH0gPSBzdGFjay5wb3AoKSE7XG5cbiAgICAgIC8vIHByb2Nlc3MgY2hpbGRyZW4gb2YgY3VycmVudCBvYmplY3QgZmllbGRcbiAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3Qua2V5cyhzdWJTY2hlbWEpLnJldmVyc2UoKSkge1xuICAgICAgICBjb25zdCBwYXRoID0gcGFyZW50UGF0aC5jb25jYXQoW25hbWVdKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB0aGlzLnZhbGlkYXRlQ29uZmlnTmFtZShuYW1lKTtcbiAgICAgICAgICBjb25zdCBmaWVsZCA9IHN1YlNjaGVtYVtuYW1lXTtcblxuICAgICAgICAgIGlmICghT2JqZWN0Lmhhc093bihmaWVsZCwgJ3R5cGUnKSB8fCB0eXBlb2YgZmllbGQudHlwZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgYGV2ZXJ5IHNjaGVtYSBmaWVsZCBtdXN0IGhhdmUgYSBcInR5cGVcIiBwcm9wZXJ0eSBvZiB0eXBlIFwic3RyaW5nXCJgXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghc3VwcG9ydGVkVHlwZXMuaW5jbHVkZXMoZmllbGQudHlwZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZmllbGQgdHlwZSBcIiR7ZmllbGQudHlwZX1cImApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMudmFsaWRhdGVTY2hlbWFGaWVsZChmaWVsZCk7XG5cbiAgICAgICAgICAvLyBpZiB0aGUgY2hpbGQgaXMgYW4gb2JqZWN0IGZpZWxkIGl0c2VsZiBhZGQgaXQgdG8gc3RhY2sgZm9yXG4gICAgICAgICAgLy8gcHJvY2Vzc2luZ1xuICAgICAgICAgIGlmIChmaWVsZC50eXBlID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgc3RhY2sucHVzaCh7XG4gICAgICAgICAgICAgIHN1YlNjaGVtYTogZmllbGQuY2hpbGRyZW4sXG4gICAgICAgICAgICAgIHBhcmVudFBhdGg6IHBhdGgsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZXJyb3JQcmVhbWJsZShwYXRoKX06ICR7ZXJyb3IubWVzc2FnZX1gKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogdmFsaWRhdGVzIGNvbmZpZyBrZXkgbmFtZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZUNvbmZpZ05hbWUgPSAobmFtZTogc3RyaW5nKSA9PiB7XG4gICAgaWYgKG5hbWUuaW5jbHVkZXMoJy4nKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBjb25maWcga2V5IG5hbWUgY2FuIG5vdCBjb250YWluIHRoZSAnLicgY2hhcmFjdGVyYCk7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiB2YWxpZGF0ZXMgcGFzc2VkIHNjaGVtYSBmaWVsZCBzdHJ1Y3R1cmVcbiAgICpcbiAgICogQHBhcmFtIHtDb25maWdGaWVsZH0gZmllbGRcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVTY2hlbWFGaWVsZCA9IChmaWVsZDogQ29uZmlnRmllbGQpID0+IHtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhmaWVsZCkpIHtcbiAgICAgIGlmIChcbiAgICAgICAgIU9iamVjdC5oYXNPd24ocHJvcGVydHlWYWxpZGF0b3JzLmFsbCwga2V5KSAmJlxuICAgICAgICAhKFxuICAgICAgICAgIGZpZWxkLnR5cGUgIT09ICdvYmplY3QnICYmXG4gICAgICAgICAgT2JqZWN0Lmhhc093bihwcm9wZXJ0eVZhbGlkYXRvcnMucHJpbWl0aXZlLCBrZXkpXG4gICAgICAgICkgJiZcbiAgICAgICAgIU9iamVjdC5oYXNPd24ocHJvcGVydHlWYWxpZGF0b3JzW2ZpZWxkLnR5cGVdLCBrZXkpXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBzY2hlbWEgZmllbGQgaGFzIHVua25vd24gcHJvcGVydHkgXCIke2tleX1cImApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgdmFsaWRhdG9yIG9mIE9iamVjdC52YWx1ZXMocHJvcGVydHlWYWxpZGF0b3JzLmFsbCkpIHtcbiAgICAgIHZhbGlkYXRvcihmaWVsZCwgdGhpcyk7XG4gICAgfVxuXG4gICAgaWYgKGZpZWxkLnR5cGUgIT09ICdvYmplY3QnKSB7XG4gICAgICBmb3IgKGNvbnN0IHZhbGlkYXRvciBvZiBPYmplY3QudmFsdWVzKHByb3BlcnR5VmFsaWRhdG9ycy5wcmltaXRpdmUpKSB7XG4gICAgICAgIHZhbGlkYXRvcihmaWVsZCwgdGhpcyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCB2YWxpZGF0b3Igb2YgT2JqZWN0LnZhbHVlcyhwcm9wZXJ0eVZhbGlkYXRvcnNbZmllbGQudHlwZV0pKSB7XG4gICAgICB2YWxpZGF0b3IoZmllbGQsIHRoaXMpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogcmV0dXJucyBhIGZpZWxkIGNvcnJlc3BvbmRpbmcgdG8gYSBwYXRoIGluIHNjaGVtYSB0cmVlXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IHBhdGhcbiAgICogQHJldHVybiB7KENvbmZpZ0ZpZWxkIHwgdW5kZWZpbmVkKX0gcmV0dXJucyB1bmRlZmluZWQgaWYgZmllbGQgaXMgbm90IGZvdW5kXG4gICAqL1xuICBnZXRTY2hlbWFGaWVsZCA9IChwYXRoOiBzdHJpbmdbXSk6IENvbmZpZ0ZpZWxkIHwgdW5kZWZpbmVkID0+IHtcbiAgICBsZXQgc3ViVHJlZTogQ29uZmlnU2NoZW1hIHwgdW5kZWZpbmVkID0gdGhpcy5zY2hlbWE7XG4gICAgbGV0IGZpZWxkOiBDb25maWdGaWVsZCB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgICBmb3IgKGNvbnN0IHBhcnQgb2YgcGF0aCkge1xuICAgICAgaWYgKHN1YlRyZWUgIT0gdW5kZWZpbmVkICYmIE9iamVjdC5oYXNPd24oc3ViVHJlZSwgcGFydCkpIHtcbiAgICAgICAgZmllbGQgPSBzdWJUcmVlW3BhcnRdO1xuICAgICAgICBzdWJUcmVlID0gJ2NoaWxkcmVuJyBpbiBmaWVsZCA/IGZpZWxkLmNoaWxkcmVuIDogdW5kZWZpbmVkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZpZWxkO1xuICB9O1xuXG4gIC8qKlxuICAgKiBleHRyYWN0cyBkZWZhdWx0IHZhbHVlcyBmcm9tIGEgc2NoZW1hXG4gICAqXG4gICAqIEByZXR1cm4ge1JlY29yZDxzdHJpbmcsIGFueT59IG9iamVjdCBvZiBkZWZhdWx0IHZhbHVlc1xuICAgKi9cbiAgZ2VuZXJhdGVEZWZhdWx0ID0gKCk6IFJlY29yZDxzdHJpbmcsIGFueT4gPT4ge1xuICAgIGNvbnN0IHZhbHVlVHJlZTogUmVjb3JkPHN0cmluZywgYW55PiA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG5cbiAgICBjb25zdCBzdGFjazoge1xuICAgICAgc2NoZW1hOiBDb25maWdTY2hlbWE7XG4gICAgICBwYXJlbnRWYWx1ZTogUmVjb3JkPHN0cmluZywgYW55PiB8IHVuZGVmaW5lZDtcbiAgICAgIGZpZWxkTmFtZTogc3RyaW5nO1xuICAgICAgY2hpbGRyZW46IHN0cmluZ1tdO1xuICAgIH1bXSA9IFtcbiAgICAgIHtcbiAgICAgICAgc2NoZW1hOiB0aGlzLnNjaGVtYSxcbiAgICAgICAgcGFyZW50VmFsdWU6IHVuZGVmaW5lZCxcbiAgICAgICAgZmllbGROYW1lOiAnJyxcbiAgICAgICAgY2hpbGRyZW46IE9iamVjdC5rZXlzKHRoaXMuc2NoZW1hKS5yZXZlcnNlKCksXG4gICAgICB9LFxuICAgIF07XG5cbiAgICAvLyBUcmF2ZXJzZXMgdGhlIHNjaGVtYSBvYmplY3QgdHJlZSBkZXB0aCBmaXJzdFxuICAgIHdoaWxlIChzdGFjay5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCB7IHNjaGVtYSwgcGFyZW50VmFsdWUsIGZpZWxkTmFtZSwgY2hpbGRyZW4gfSA9IHN0YWNrLmF0KC0xKSE7XG5cbiAgICAgIC8vIGlmIGEgc3VidHJlZSdzIHByb2Nlc3NpbmcgaXMgZmluaXNoZWQgZ28gdG8gdGhlIHByZXZpb3VzIGxldmVsXG4gICAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIC8vIGlmIGEgc3VidHJlZSBpcyBlbXB0eSAoaGFzIG5vIHZhbHVlcykgcmVtb3ZlIGl0IGZyb20gdGhlIHJlc3VsdFxuICAgICAgICBpZiAoXG4gICAgICAgICAgcGFyZW50VmFsdWUgIT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgT2JqZWN0LmtleXMocGFyZW50VmFsdWVbZmllbGROYW1lXSkubGVuZ3RoID09PSAwXG4gICAgICAgICkge1xuICAgICAgICAgIGRlbGV0ZSBwYXJlbnRWYWx1ZVtmaWVsZE5hbWVdO1xuICAgICAgICB9XG4gICAgICAgIHN0YWNrLnBvcCgpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2hpbGROYW1lID0gY2hpbGRyZW4ucG9wKCkhO1xuICAgICAgY29uc3QgdmFsdWUgPVxuICAgICAgICBwYXJlbnRWYWx1ZSAhPSB1bmRlZmluZWQgPyBwYXJlbnRWYWx1ZVtmaWVsZE5hbWVdIDogdmFsdWVUcmVlO1xuICAgICAgY29uc3QgZmllbGQgPSBzY2hlbWFbY2hpbGROYW1lXTtcbiAgICAgIC8vIGlmIGEgbm9kZS9maWVsZCBpcyBvZiB0eXBlIG9iamVjdCBhbmQgdGh1cyBpcyBhIHN1YnRyZWUsIGFkZCBpdCBib3RoIHRvXG4gICAgICAvLyB2YWx1ZSB0cmVlIGFuZCB0byB0aGUgc3RhY2sgdG8gYmUgdHJhdmVyc2VkIGxhdGVyLiBPdGhlcndpc2UgaXQncyBhXG4gICAgICAvLyBsZWFmIGFuZCBuZWVkcyBubyB0cmF2ZXJzYWwsIHNvIGFkZCBpdCBvbmx5IHRvIHRoZSB2YWx1ZSB0cmVlLlxuICAgICAgaWYgKGZpZWxkLnR5cGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIHZhbHVlW2NoaWxkTmFtZV0gPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgICAgICBzdGFjay5wdXNoKHtcbiAgICAgICAgICBzY2hlbWE6IGZpZWxkLmNoaWxkcmVuLFxuICAgICAgICAgIHBhcmVudFZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICBmaWVsZE5hbWU6IGNoaWxkTmFtZSxcbiAgICAgICAgICBjaGlsZHJlbjogT2JqZWN0LmtleXMoZmllbGQuY2hpbGRyZW4pLnJldmVyc2UoKSxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKGZpZWxkLmRlZmF1bHQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHZhbHVlW2NoaWxkTmFtZV0gPSBmaWVsZC5kZWZhdWx0O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZVRyZWU7XG4gIH07XG5cbiAgLyoqXG4gICAqIGdlbmVyYXRlcyBjb21wYXRpYmxlIFR5cGVTY3JpcHQgaW50ZXJmYWNlIGZvciB0aGlzIGluc3RhbmNlJ3Mgc2NoZW1hXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHJvb3QgdHlwZVxuICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAqL1xuICBnZW5lcmF0ZVRTVHlwZXMgPSAobmFtZTogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgICBjb25zdCBlcnJvclByZWFtYmxlID0gKHBhdGg6IEFycmF5PHN0cmluZz4pID0+XG4gICAgICBgVHlwZVNjcmlwdCB0eXBlIGdlbmVyYXRpb24gZmFpbGVkIGZvciBcIiR7cGF0aC5qb2luKCcuJyl9XCIgZmllbGRgO1xuXG4gICAgY29uc3QgdHlwZXM6IEFycmF5PHN0cmluZz4gPSBbXTtcblxuICAgIGNvbnN0IHR5cGVOYW1lczogTWFwPHN0cmluZywgYmlnaW50PiA9IG5ldyBNYXA8c3RyaW5nLCBiaWdpbnQ+KCk7XG4gICAgdHlwZU5hbWVzLnNldChuYW1lLCAxbik7XG5cbiAgICBjb25zdCBzdGFjazogQXJyYXk8e1xuICAgICAgc3ViU2NoZW1hOiBDb25maWdTY2hlbWE7XG4gICAgICBjaGlsZHJlbjogc3RyaW5nW107XG4gICAgICBwYXJlbnRQYXRoOiBBcnJheTxzdHJpbmc+O1xuICAgICAgdHlwZU5hbWU6IHN0cmluZztcbiAgICAgIGF0dHJpYnV0ZXM6IEFycmF5PFtzdHJpbmcsIHN0cmluZ10+O1xuICAgIH0+ID0gW1xuICAgICAge1xuICAgICAgICBzdWJTY2hlbWE6IHRoaXMuc2NoZW1hLFxuICAgICAgICBjaGlsZHJlbjogT2JqZWN0LmtleXModGhpcy5zY2hlbWEpLFxuICAgICAgICBwYXJlbnRQYXRoOiBbXSxcbiAgICAgICAgdHlwZU5hbWU6IG5hbWUsXG4gICAgICAgIGF0dHJpYnV0ZXM6IFtdLFxuICAgICAgfSxcbiAgICBdO1xuXG4gICAgLy8gVHJhdmVyc2VzIHRoZSBzY2hlbWEgb2JqZWN0IHRyZWUgZGVwdGggZmlyc3RcbiAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgeyBzdWJTY2hlbWEsIGNoaWxkcmVuLCBwYXJlbnRQYXRoLCB0eXBlTmFtZSwgYXR0cmlidXRlcyB9ID1cbiAgICAgICAgc3RhY2suYXQoLTEpITtcbiAgICAgIGNvbnN0IHBhdGggPSBwYXJlbnRQYXRoLmNvbmNhdChbbmFtZV0pO1xuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gaWYgYSBzdWJ0cmVlJ3MgcHJvY2Vzc2luZyBpcyBmaW5pc2hlZCBnbyB0byB0aGUgcHJldmlvdXMgbGV2ZWxcbiAgICAgICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgdHlwZXMucHVzaCh0aGlzLmdlblRTSW50ZXJmYWNlKHR5cGVOYW1lLCBhdHRyaWJ1dGVzKSk7XG4gICAgICAgICAgc3RhY2sucG9wKCk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjaGlsZE5hbWUgPSBjaGlsZHJlbi5wb3AoKSE7XG4gICAgICAgIGNvbnN0IGZpZWxkID0gc3ViU2NoZW1hW2NoaWxkTmFtZV07XG5cbiAgICAgICAgLy8gaWYgYSBub2RlL2ZpZWxkIGlzIG9mIHR5cGUgb2JqZWN0IGFuZCB0aHVzIGlzIGEgc3VidHJlZSwgYWRkIGl0IHRvXG4gICAgICAgIC8vIHRoZSBzdGFjayB0byBiZSB0cmF2ZXJzZWQgbGF0ZXIuIE90aGVyd2lzZSBpdCdzIGEgbGVhZiBhbmQgbmVlZHMgbm9cbiAgICAgICAgLy8gdHJhdmVyc2FsLlxuICAgICAgICBpZiAoZmllbGQudHlwZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICBsZXQgY2hpbGRUeXBlTmFtZSA9IGAke2NoaWxkTmFtZVswXS50b1VwcGVyQ2FzZSgpfSR7Y2hpbGROYW1lLnN1YnN0cmluZyhcbiAgICAgICAgICAgIDFcbiAgICAgICAgICApfWA7XG4gICAgICAgICAgY29uc3QgdHlwZU5hbWVDb3VudCA9IHR5cGVOYW1lcy5nZXQoY2hpbGRUeXBlTmFtZSk7XG4gICAgICAgICAgdHlwZU5hbWVzLnNldChjaGlsZFR5cGVOYW1lLCAodHlwZU5hbWVzLmdldChjaGlsZE5hbWUpIHx8IDBuKSArIDFuKTtcbiAgICAgICAgICBpZiAodHlwZU5hbWVDb3VudCkge1xuICAgICAgICAgICAgY2hpbGRUeXBlTmFtZSArPSB0eXBlTmFtZUNvdW50LnRvU3RyaW5nKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc3RhY2sucHVzaCh7XG4gICAgICAgICAgICBzdWJTY2hlbWE6IGZpZWxkLmNoaWxkcmVuLFxuICAgICAgICAgICAgY2hpbGRyZW46IE9iamVjdC5rZXlzKGZpZWxkLmNoaWxkcmVuKS5yZXZlcnNlKCksXG4gICAgICAgICAgICBwYXJlbnRQYXRoOiBwYXRoLFxuICAgICAgICAgICAgdHlwZU5hbWU6IGNoaWxkVHlwZU5hbWUsXG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiBbXSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGF0dHJpYnV0ZXMucHVzaChbY2hpbGROYW1lLCBjaGlsZFR5cGVOYW1lXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYXR0cmlidXRlcy5wdXNoKFtjaGlsZE5hbWUsIGZpZWxkLnR5cGVdKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZXJyb3JQcmVhbWJsZShwYXRoKX06ICR7ZXJyb3IubWVzc2FnZX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHlwZXMucmV2ZXJzZSgpLmpvaW4oJ1xcblxcbicpICsgJ1xcbic7XG4gIH07XG5cbiAgLyoqXG4gICAqIGdlbmVyYXRlcyBhIFR5cGVTY3JpcHQgaW50ZXJmYWNlIGRlZmluaXRpb24gZm9yIHBhc3NlZCBuYW1lIGFuZCBhdHRyaWJ1dGVzXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7QXJyYXk8W3N0cmluZywgc3RyaW5nXT59IGF0dHJpYnV0ZXNcbiAgICogQHJldHVybiB7c3RyaW5nfVxuICAgKi9cbiAgcHJpdmF0ZSBnZW5UU0ludGVyZmFjZSA9IChcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgYXR0cmlidXRlczogQXJyYXk8W3N0cmluZywgc3RyaW5nXT5cbiAgKTogc3RyaW5nID0+IHtcbiAgICByZXR1cm4gYGludGVyZmFjZSAke25hbWV9IHtcbiAgJHthdHRyaWJ1dGVzLm1hcCgoYXR0cikgPT4gYCR7YXR0clswXX06ICR7YXR0clsxXX07YCkuam9pbignXFxuICAnKX1cbn1gO1xuICB9O1xuXG4gIC8qKlxuICAgKiByZXR1cm5zIGEgY2hhcmFjdGVyaXN0aWMgb2JqZWN0IGZvciB2YWx1ZXMgYXQgYSBzcGVjaWZpYyBub2RlIGNvbmZpZyBsZXZlbFxuICAgKlxuICAgKiBAcGFyYW0ge0lDb25maWd9IGNvbmZpZ1xuICAgKiBAcGFyYW0ge3N0cmluZ30gbGV2ZWxcbiAgICogQHJldHVybiB7UmVjb3JkPHN0cmluZywgYW55Pn1cbiAgICovXG4gIGdldENvbmZpZ0ZvckxldmVsKGNvbmZpZzogSUNvbmZpZywgbGV2ZWw6IHN0cmluZyk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuICAgIGNvbnN0IGNvbmZMZXZlbHMgPSBDb25maWdWYWxpZGF0b3IuZ2V0Tm9kZUNvbmZpZ0xldmVscyhjb25maWcpO1xuICAgIGNvbnN0IGxldmVsSW5kZXggPSBjb25mTGV2ZWxzLmluZGV4T2YobGV2ZWwpO1xuICAgIGlmIChsZXZlbEluZGV4ID09PSAtMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVGhlIFwiJHtsZXZlbH1cIiBsZXZlbCBub3QgZm91bmQgaW4gdGhlIGN1cnJlbnQgc3lzdGVtIGNvbmZpZ3VyYXRpb24gbGV2ZWxzYFxuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3QgaGlnaGVyTGV2ZWxTb3VyY2VzID0gY29uZmlnLnV0aWxcbiAgICAgIC5nZXRDb25maWdTb3VyY2VzKClcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChzb3VyY2UpID0+IGNvbmZMZXZlbHMuaW5kZXhPZihnZXRTb3VyY2VOYW1lKHNvdXJjZSkpID4gbGV2ZWxJbmRleFxuICAgICAgKTtcbiAgICBjb25zdCBjdXJyZW50TGV2ZWxTb3VyY2UgPSBjb25maWcudXRpbFxuICAgICAgLmdldENvbmZpZ1NvdXJjZXMoKVxuICAgICAgLmZpbHRlcigoc291cmNlKSA9PiBnZXRTb3VyY2VOYW1lKHNvdXJjZSkgPT09IGxldmVsKVxuICAgICAgLmF0KDApO1xuICAgIGNvbnN0IGxvd2VyTGV2ZWxTb3VyY2VzID0gY29uZmlnLnV0aWxcbiAgICAgIC5nZXRDb25maWdTb3VyY2VzKClcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChzb3VyY2UpID0+IGNvbmZMZXZlbHMuaW5kZXhPZihnZXRTb3VyY2VOYW1lKHNvdXJjZSkpIDwgbGV2ZWxJbmRleFxuICAgICAgKTtcblxuICAgIC8vIFRyYXZlcnNlcyB0aGUgc2NoZW1hIG9iamVjdCB0cmVlIGRlcHRoIGZpcnN0XG4gICAgY29uc3QgdmFsdWVUcmVlID0gQ29uZmlnVmFsaWRhdG9yLnByb2Nlc3NDb25maWdGb3JMZXZlbE5vZGUoXG4gICAgICB0aGlzLnNjaGVtYSxcbiAgICAgIFtdLFxuICAgICAgaGlnaGVyTGV2ZWxTb3VyY2VzLFxuICAgICAgY3VycmVudExldmVsU291cmNlLFxuICAgICAgbG93ZXJMZXZlbFNvdXJjZXNcbiAgICApO1xuXG4gICAgcmV0dXJuIHZhbHVlVHJlZTtcbiAgfVxuXG4gIC8qKlxuICAgKnRyYXZlcnNlcyB0aGUgY29uZmlnIHNjaGVtYSBkZXB0aCBmaXJzdCB0byBwcm9kdWNlIGNoYXJhY3RlcmlzdGljIG9iamVjdFxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAc3RhdGljXG4gICAqIEBwYXJhbSB7Q29uZmlnU2NoZW1hfSBzY2hlbWFcbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gcGF0aFxuICAgKiBAcGFyYW0ge0lDb25maWdTb3VyY2VbXX0gaGlnaGVyTGV2ZWxTb3VyY2VzXG4gICAqIEBwYXJhbSB7KElDb25maWdTb3VyY2UgfCB1bmRlZmluZWQpfSBjdXJyZW50TGV2ZWxTb3VyY2VcbiAgICogQHBhcmFtIHtJQ29uZmlnU291cmNlW119IGxvd2VyTGV2ZWxTb3VyY2VzXG4gICAqIEByZXR1cm4ge1JlY29yZDxzdHJpbmcsIGFueT59XG4gICAqIEBtZW1iZXJvZiBDb25maWdWYWxpZGF0b3JcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHByb2Nlc3NDb25maWdGb3JMZXZlbE5vZGUoXG4gICAgc2NoZW1hOiBDb25maWdTY2hlbWEsXG4gICAgcGF0aDogc3RyaW5nW10sXG4gICAgaGlnaGVyTGV2ZWxTb3VyY2VzOiBJQ29uZmlnU291cmNlW10sXG4gICAgY3VycmVudExldmVsU291cmNlOiBJQ29uZmlnU291cmNlIHwgdW5kZWZpbmVkLFxuICAgIGxvd2VyTGV2ZWxTb3VyY2VzOiBJQ29uZmlnU291cmNlW11cbiAgKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgY29uc3QgdmFsdWUgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgIGZvciAoY29uc3QgY2hpbGROYW1lIG9mIE9iamVjdC5rZXlzKHNjaGVtYSkucmV2ZXJzZSgpKSB7XG4gICAgICBjb25zdCBjaGlsZFBhdGggPSBwYXRoLmNvbmNhdChbY2hpbGROYW1lXSk7XG4gICAgICBjb25zdCBmaWVsZCA9IHNjaGVtYVtjaGlsZE5hbWVdO1xuICAgICAgLy8gaWYgYSBmaWVsZCBpcyBvZiB0eXBlIG9iamVjdCBhbmQgdGh1cyBpcyBhIHN1YnRyZWUsIHJlY3Vyc2Ugb24gaXQuXG4gICAgICAvLyBPdGhlcndpc2UgaXQncyBhIGxlYWYgYW5kIG5lZWRzIG5vIHRyYXZlcnNhbC5cbiAgICAgIHZhbHVlW2NoaWxkTmFtZV0gPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgICAgaWYgKGZpZWxkLnR5cGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIHZhbHVlW2NoaWxkTmFtZV0gPSBDb25maWdWYWxpZGF0b3IucHJvY2Vzc0NvbmZpZ0ZvckxldmVsTm9kZShcbiAgICAgICAgICBmaWVsZC5jaGlsZHJlbixcbiAgICAgICAgICBjaGlsZFBhdGgsXG4gICAgICAgICAgaGlnaGVyTGV2ZWxTb3VyY2VzLFxuICAgICAgICAgIGN1cnJlbnRMZXZlbFNvdXJjZSxcbiAgICAgICAgICBsb3dlckxldmVsU291cmNlc1xuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFsdWVbY2hpbGROYW1lXVsnbGFiZWwnXSA9XG4gICAgICAgICAgZmllbGQubGFiZWwgIT0gdW5kZWZpbmVkID8gZmllbGQubGFiZWwgOiBudWxsO1xuICAgICAgICB2YWx1ZVtjaGlsZE5hbWVdWydkZXNjcmlwdGlvbiddID1cbiAgICAgICAgICBmaWVsZC5kZXNjcmlwdGlvbiAhPSB1bmRlZmluZWQgPyBmaWVsZC5kZXNjcmlwdGlvbiA6IG51bGw7XG4gICAgICAgIHZhbHVlW2NoaWxkTmFtZV1bJ2RlZmF1bHQnXSA9IGdldFZhbHVlRnJvbUNvbmZpZ1NvdXJjZXMoXG4gICAgICAgICAgbG93ZXJMZXZlbFNvdXJjZXMsXG4gICAgICAgICAgY2hpbGRQYXRoXG4gICAgICAgICk7XG4gICAgICAgIHZhbHVlW2NoaWxkTmFtZV1bJ3ZhbHVlJ10gPSBnZXRWYWx1ZUZyb21Db25maWdTb3VyY2VzKFxuICAgICAgICAgIFsuLi4oY3VycmVudExldmVsU291cmNlICE9IHVuZGVmaW5lZCA/IFtjdXJyZW50TGV2ZWxTb3VyY2VdIDogW10pXSxcbiAgICAgICAgICBjaGlsZFBhdGhcbiAgICAgICAgKTtcbiAgICAgICAgdmFsdWVbY2hpbGROYW1lXVsnb3ZlcnJpZGUnXSA9IGdldFZhbHVlRnJvbUNvbmZpZ1NvdXJjZXMoXG4gICAgICAgICAgaGlnaGVyTGV2ZWxTb3VyY2VzLFxuICAgICAgICAgIGNoaWxkUGF0aFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiByZXR1cm5zIGEgbGlzdCBvZiBjb25maWcgc291cmNlcyB1c2VkIGJ5IG5vZGUgY29uZmlnIHBhY2thZ2UsIG9yZGVyZWQgZnJvbVxuICAgKiB0aGUgbG93ZXN0IHRvIHRoZSBoaWdoZXN0IHByaW9yaXR5XG4gICAqXG4gICAqIEBzdGF0aWNcbiAgICogQHBhcmFtIHtJQ29uZmlnfSBjb25maWdcbiAgICogQHJldHVybiAge3N0cmluZ1tdfVxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0Tm9kZUNvbmZpZ0xldmVscyA9IChjb25maWc6IElDb25maWcpOiBzdHJpbmdbXSA9PiB7XG4gICAgY29uc3QgaW5zdGFuY2UgPSBjb25maWcudXRpbC5nZXRFbnYoJ05PREVfQVBQX0lOU1RBTkNFJyk7XG4gICAgbGV0IGRlcGxveW1lbnQgPSBjb25maWcudXRpbC5nZXRFbnYoJ05PREVfRU5WJyk7XG4gICAgZGVwbG95bWVudCA9IGNvbmZpZy51dGlsLmdldEVudignTk9ERV9DT05GSUdfRU5WJyk7XG4gICAgY29uc3QgZnVsbEhvc3RuYW1lID0gY29uZmlnLnV0aWwuZ2V0RW52KCdIT1NUTkFNRScpO1xuICAgIGNvbnN0IHNob3J0SG9zdG5hbWUgPVxuICAgICAgZnVsbEhvc3RuYW1lICE9IHVuZGVmaW5lZCA/IGZ1bGxIb3N0bmFtZS5zcGxpdCgnLicpWzBdIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgY29uZmlnTGV2ZWxzID0gW1xuICAgICAgJ2RlZmF1bHQnLFxuICAgICAgLi4uKGluc3RhbmNlICE9IHVuZGVmaW5lZCA/IFtgZGVmYXVsdC0ke2luc3RhbmNlfWBdIDogW10pLFxuICAgICAgLi4uKGRlcGxveW1lbnQgIT0gdW5kZWZpbmVkID8gW2Ake2RlcGxveW1lbnR9YF0gOiBbXSksXG4gICAgICAuLi4oaW5zdGFuY2UgIT0gdW5kZWZpbmVkICYmIGRlcGxveW1lbnQgIT0gdW5kZWZpbmVkXG4gICAgICAgID8gW2Ake2RlcGxveW1lbnR9LSR7aW5zdGFuY2V9YF1cbiAgICAgICAgOiBbXSksXG4gICAgICAuLi4oc2hvcnRIb3N0bmFtZSAhPSB1bmRlZmluZWQgPyBbYCR7c2hvcnRIb3N0bmFtZX1gXSA6IFtdKSxcbiAgICAgIC4uLihzaG9ydEhvc3RuYW1lICE9IHVuZGVmaW5lZCAmJiBpbnN0YW5jZSAhPSB1bmRlZmluZWRcbiAgICAgICAgPyBbYCR7c2hvcnRIb3N0bmFtZX0tJHtpbnN0YW5jZX1gXVxuICAgICAgICA6IFtdKSxcbiAgICAgIC4uLihzaG9ydEhvc3RuYW1lICE9IHVuZGVmaW5lZCAmJiBkZXBsb3ltZW50ICE9IHVuZGVmaW5lZFxuICAgICAgICA/IFtgJHtzaG9ydEhvc3RuYW1lfS0ke2RlcGxveW1lbnR9YF1cbiAgICAgICAgOiBbXSksXG4gICAgICAuLi4oc2hvcnRIb3N0bmFtZSAhPSB1bmRlZmluZWQgJiZcbiAgICAgIGRlcGxveW1lbnQgIT0gdW5kZWZpbmVkICYmXG4gICAgICBpbnN0YW5jZSAhPSB1bmRlZmluZWRcbiAgICAgICAgPyBbYCR7c2hvcnRIb3N0bmFtZX0tJHtkZXBsb3ltZW50fS0ke2luc3RhbmNlfWBdXG4gICAgICAgIDogW10pLFxuICAgICAgLi4uKGZ1bGxIb3N0bmFtZSAhPSB1bmRlZmluZWQgPyBbYCR7ZnVsbEhvc3RuYW1lfWBdIDogW10pLFxuICAgICAgLi4uKGZ1bGxIb3N0bmFtZSAhPSB1bmRlZmluZWQgJiYgaW5zdGFuY2UgIT0gdW5kZWZpbmVkXG4gICAgICAgID8gW2Ake2Z1bGxIb3N0bmFtZX0tJHtpbnN0YW5jZX1gXVxuICAgICAgICA6IFtdKSxcbiAgICAgIC4uLihmdWxsSG9zdG5hbWUgIT0gdW5kZWZpbmVkICYmIGRlcGxveW1lbnQgIT0gdW5kZWZpbmVkXG4gICAgICAgID8gW2Ake2Z1bGxIb3N0bmFtZX0tJHtkZXBsb3ltZW50fWBdXG4gICAgICAgIDogW10pLFxuICAgICAgLi4uKGZ1bGxIb3N0bmFtZSAhPSB1bmRlZmluZWQgJiZcbiAgICAgIGRlcGxveW1lbnQgIT0gdW5kZWZpbmVkICYmXG4gICAgICBpbnN0YW5jZSAhPSB1bmRlZmluZWRcbiAgICAgICAgPyBbYCR7ZnVsbEhvc3RuYW1lfS0ke2RlcGxveW1lbnR9LSR7aW5zdGFuY2V9YF1cbiAgICAgICAgOiBbXSksXG4gICAgICBgbG9jYWxgLFxuICAgICAgLi4uKGluc3RhbmNlICE9IHVuZGVmaW5lZCA/IFtgbG9jYWwtJHtpbnN0YW5jZX1gXSA6IFtdKSxcbiAgICAgIC4uLihkZXBsb3ltZW50ICE9IHVuZGVmaW5lZCA/IFtgbG9jYWwtJHtkZXBsb3ltZW50fWBdIDogW10pLFxuICAgICAgLi4uKGRlcGxveW1lbnQgIT0gdW5kZWZpbmVkICYmIGluc3RhbmNlICE9IHVuZGVmaW5lZFxuICAgICAgICA/IFtgbG9jYWwtJHtkZXBsb3ltZW50fS0ke2luc3RhbmNlfWBdXG4gICAgICAgIDogW10pLFxuICAgICAgJyROT0RFX0NPTkZJRycsXG4gICAgICAnY3VzdG9tLWVudmlyb25tZW50LXZhcmlhYmxlcycsXG4gICAgXTtcblxuICAgIHJldHVybiBjb25maWdMZXZlbHM7XG4gIH07XG5cbiAgLyoqXG4gICAqIHZhbGlkYXRlcyBhIGNvbmZpZyBvYmplY3QgYW5kIHdyaXRlcyBpdCB0byB0aGUgbm9kZS1jb25maWcgZmlsZVxuICAgKiBjb3JyZXNwb25kaW5nIHRvIHRoZSBwYXNzZWQgbGV2ZWxcbiAgICpcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBjb25maWdPYmpcbiAgICogQHBhcmFtIHtJQ29uZmlnfSBjb25maWdcbiAgICogQHBhcmFtIHtzdHJpbmd9IGxldmVsIG91dHB1dCBub2RlLWNvbmZpZyBmaWxlIGxldmVsXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXQgdGhlIGZvcm1hdCBvZiB0aGUgb3V0cHV0IGZpbGVcbiAgICovXG4gIHZhbGlkYXRlQW5kV3JpdGVDb25maWcgPSAoXG4gICAgY29uZmlnT2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIGNvbmZpZzogSUNvbmZpZyxcbiAgICBsZXZlbDogc3RyaW5nLFxuICAgIGZvcm1hdDogc3RyaW5nXG4gICkgPT4ge1xuICAgIGNvbnN0IGNvbmZMZXZlbHMgPSBDb25maWdWYWxpZGF0b3IuZ2V0Tm9kZUNvbmZpZ0xldmVscyhjb25maWcpLmZpbHRlcihcbiAgICAgIChsKSA9PiBsICE9PSAnY3VzdG9tLWVudmlyb25tZW50LXZhcmlhYmxlcydcbiAgICApO1xuICAgIGNvbnN0IGxldmVsSW5kZXggPSBjb25mTGV2ZWxzLmluZGV4T2YobGV2ZWwpO1xuICAgIGlmIChsZXZlbEluZGV4ID09PSAtMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVGhlIFske2xldmVsfV0gbGV2ZWwgbm90IGZvdW5kIGluIHRoZSBjdXJyZW50IHN5c3RlbSdzIGNvbmZpZ3VyYXRpb24gbGV2ZWxzYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBjb25maWdEaXIgPVxuICAgICAgcHJvY2Vzcy5lbnZbJ05PREVfQ09ORklHX0RJUiddICE9IHVuZGVmaW5lZFxuICAgICAgICA/IHByb2Nlc3MuZW52WydOT0RFX0NPTkZJR19ESVInXVxuICAgICAgICA6ICcuL2NvbmZpZyc7XG4gICAgbGV0IG91dHB1dCA9ICcnO1xuICAgIGxldCBleHQgPSAnJztcbiAgICBzd2l0Y2ggKGZvcm1hdCkge1xuICAgICAgY2FzZSAnanNvbic6IHtcbiAgICAgICAgY29uc3QgSnNvbkJpZ0ludCA9IEpzb25CaWdJbnRGYWN0b3J5KHtcbiAgICAgICAgICBhbHdheXNQYXJzZUFzQmlnOiBmYWxzZSxcbiAgICAgICAgICB1c2VOYXRpdmVCaWdJbnQ6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgICBvdXRwdXQgPSBKc29uQmlnSW50LnN0cmluZ2lmeShjb25maWdPYmopO1xuICAgICAgICBleHQgPSAnanNvbic7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAneWFtbCc6IHtcbiAgICAgICAgb3V0cHV0ID0geWFtbC5kdW1wKGNvbmZpZ09iaik7XG4gICAgICAgIGV4dCA9ICd5YW1sJztcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBFcnJvcihgSW52YWxpZCBmb3JtYXQ6ICR7Zm9ybWF0fWApO1xuICAgIH1cblxuICAgIGNvbnN0IG91dHB1dFBhdGggPSBwYXRoLmpvaW4oY29uZmlnRGlyLCBgJHtsZXZlbH0uJHtleHR9YCk7XG4gICAgY29uc3QgYmFja3VwUGF0aCA9IHBhdGguam9pbihjb25maWdEaXIsIGAke2xldmVsfS1iYWNrdXAuJHtleHR9YCk7XG4gICAgY29uc3QgY29uZkZpbGVFeGlzdHMgPSBmcy5leGlzdHNTeW5jKG91dHB1dFBhdGgpO1xuICAgIGlmIChjb25mRmlsZUV4aXN0cykge1xuICAgICAgZnMucmVuYW1lU3luYyhvdXRwdXRQYXRoLCBiYWNrdXBQYXRoKTtcbiAgICB9XG4gICAgZnMud3JpdGVGaWxlU3luYyhvdXRwdXRQYXRoLCBvdXRwdXQpO1xuXG4gICAgY29uc3QgdXBkYXRlZENvbmZPYmogPSBjb25maWcudXRpbC5sb2FkRmlsZUNvbmZpZ3MoKTtcblxuICAgIHRyeSB7XG4gICAgICB0aGlzLnZhbGlkYXRlQ29uZmlnKHVwZGF0ZWRDb25mT2JqKTtcbiAgICAgIGZzLnVubGlua1N5bmMoYmFja3VwUGF0aCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGZzLnVubGlua1N5bmMob3V0cHV0UGF0aCk7XG4gICAgICBpZiAoY29uZkZpbGVFeGlzdHMpIHtcbiAgICAgICAgZnMucmVuYW1lU3luYyhiYWNrdXBQYXRoLCBvdXRwdXRQYXRoKTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfTtcbn1cbiJdfQ==
592
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vbGliL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQUN6QixPQUFPLEtBQUssSUFBSSxNQUFNLFNBQVMsQ0FBQztBQUNoQyxPQUFPLGlCQUFpQixNQUFNLGFBQWEsQ0FBQztBQUM1QyxPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixjQUFjLEdBQ2YsTUFBTSxxQ0FBcUMsQ0FBQztBQUc3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLHlCQUF5QixFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUV2RSxNQUFNLE9BQU8sZUFBZTtJQUNOO0lBQXBCLFlBQW9CLE1BQW9CO1FBQXBCLFdBQU0sR0FBTixNQUFNLENBQWM7UUFDdEMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ3hCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksY0FBYyxDQUFDLE1BQTJCO1FBQy9DLElBQUksQ0FBQyxhQUFhLENBQ2hCLE1BQU0sRUFDTixFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFDekMsTUFBTSxDQUNQLENBQUM7UUFFRixJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzFELENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSyxpQkFBaUIsQ0FDdkIsTUFBMkIsRUFDM0IsU0FBOEIsRUFDOUIsU0FBdUIsRUFDdkIsSUFBYztRQUVkLE1BQU0sYUFBYSxHQUFHLENBQUMsSUFBbUIsRUFBRSxFQUFFLENBQzVDLGlDQUFpQyxJQUFJLENBQUMsSUFBSSxD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bXBvcnQgeyBJQ29uZmlnLCBJQ29uZmlnU291cmNlIH0gZnJvbSAnY29uZmlnJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHlhbWwgZnJvbSAnanMteWFtbCc7XG5pbXBvcnQgSnNvbkJpZ0ludEZhY3RvcnkgZnJvbSAnanNvbi1iaWdpbnQnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQge1xuICBwcm9wZXJ0eVZhbGlkYXRvcnMsXG4gIHN1cHBvcnRlZFR5cGVzLFxufSBmcm9tICcuL3NjaGVtYS9WYWxpZGF0b3JzL2ZpZWxkUHJvcGVydGllcyc7XG5pbXBvcnQgeyBDb25maWdGaWVsZCwgQ29uZmlnU2NoZW1hIH0gZnJvbSAnLi9zY2hlbWEvdHlwZXMvZmllbGRzJztcbmltcG9ydCB7IFdoZW4gfSBmcm9tICcuL3NjaGVtYS90eXBlcy92YWxpZGF0aW9ucyc7XG5pbXBvcnQgeyBnZXRTb3VyY2VOYW1lLCBnZXRWYWx1ZUZyb21Db25maWdTb3VyY2VzIH0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQgeyB2YWx1ZVZhbGlkYXRpb25zLCB2YWx1ZVZhbGlkYXRvcnMgfSBmcm9tICcuL3ZhbHVlL3ZhbGlkYXRvcnMnO1xuXG5leHBvcnQgY2xhc3MgQ29uZmlnVmFsaWRhdG9yIHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBzY2hlbWE6IENvbmZpZ1NjaGVtYSkge1xuICAgIHRoaXMudmFsaWRhdGVTY2hlbWEoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiB2YWxpZGF0ZXMgdGhlIHBhc3NlZCBjb25maWcgYWdhaW5zdCB0aGUgaW5zdGFuY2UncyBzY2hlbWFcbiAgICpcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBjb25maWdcbiAgICovXG4gIHB1YmxpYyB2YWxpZGF0ZUNvbmZpZyhjb25maWc6IFJlY29yZDxzdHJpbmcsIGFueT4pIHtcbiAgICB0aGlzLnZhbGlkYXRlVmFsdWUoXG4gICAgICBjb25maWcsXG4gICAgICB7IHR5cGU6ICdvYmplY3QnLCBjaGlsZHJlbjogdGhpcy5zY2hlbWEgfSxcbiAgICAgIGNvbmZpZ1xuICAgICk7XG5cbiAgICB0aGlzLnZhbGlkYXRlU3ViQ29uZmlnKGNvbmZpZywgY29uZmlnLCB0aGlzLnNjaGVtYSwgW10pO1xuICB9XG5cbiAgLyoqXG4gICAqIHRyYXZlcnNlcyBhbmQgdmFsaWRhdGVzIGEgc3ViY29uZmlnIHVzaW5nIHRoZSBzdWJzY2hlbWFcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBjb25maWdcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBzdWJDb25maWdcbiAgICogQHBhcmFtIHtDb25maWdTY2hlbWF9IHN1YlNjaGVtYVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBwYXRoXG4gICAqIEBtZW1iZXJvZiBDb25maWdWYWxpZGF0b3JcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVTdWJDb25maWcoXG4gICAgY29uZmlnOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIHN1YkNvbmZpZzogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICBzdWJTY2hlbWE6IENvbmZpZ1NjaGVtYSxcbiAgICBwYXRoOiBzdHJpbmdbXVxuICApIHtcbiAgICBjb25zdCBlcnJvclByZWFtYmxlID0gKHBhdGg6IEFycmF5PHN0cmluZz4pID0+XG4gICAgICBgY29uZmlnIHZhbGlkYXRpb24gZmFpbGVkIGZvciBcIiR7cGF0aC5qb2luKCcuJyl9XCIgZmllbGRgO1xuICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3Qua2V5cyhzdWJTY2hlbWEpKSB7XG4gICAgICBjb25zdCBjaGlsZFBhdGggPSBwYXRoLmNvbmNhdChbbmFtZV0pO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgZmllbGQgPSBzdWJTY2hlbWFbbmFtZV07XG4gICAgICAgIGxldCB2YWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHN1YkNvbmZpZyAhPSB1bmRlZmluZWQgJiYgT2JqZWN0Lmhhc093bihzdWJDb25maWcsIG5hbWUpKSB7XG4gICAgICAgICAgdmFsdWUgPSBzdWJDb25maWdbbmFtZV07XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZhbGlkYXRlVmFsdWUodmFsdWUsIGZpZWxkLCBjb25maWcpO1xuXG4gICAgICAgIC8vIGlmIGEgbm9kZS9maWVsZCBpcyBvZiB0eXBlIG9iamVjdCBhbmQgdGh1cyBpcyBhIHN1YnRyZWUsIHRyYXZlcnNlIGl0XG4gICAgICAgIGlmIChmaWVsZC50eXBlID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgIHRoaXMudmFsaWRhdGVTdWJDb25maWcoY29uZmlnLCB2YWx1ZSwgZmllbGQuY2hpbGRyZW4sIGNoaWxkUGF0aCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZmllbGQudHlwZSA9PT0gJ2FycmF5Jykge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHZhbHVlKSB7XG4gICAgICAgICAgICAgIENvbmZpZ1ZhbGlkYXRvci5tb2RpZnlPYmplY3QoY29uZmlnLCBpdGVtLCBjaGlsZFBhdGgpO1xuICAgICAgICAgICAgICB0aGlzLnZhbGlkYXRlU3ViQ29uZmlnKFxuICAgICAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgICAgICB7IFtuYW1lXTogaXRlbSB9LFxuICAgICAgICAgICAgICAgIHsgW25hbWVdOiBmaWVsZC5pdGVtcyB9LFxuICAgICAgICAgICAgICAgIGNoaWxkUGF0aFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBDb25maWdWYWxpZGF0b3IubW9kaWZ5T2JqZWN0KGNvbmZpZywgdmFsdWUsIGNoaWxkUGF0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtlcnJvclByZWFtYmxlKGNoaWxkUGF0aCl9OiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIHNldHMgYW4gb2JqZWN0J3Mgc3BlY2lmaWMgc3VidHJlZSB0byB0aGUgc3BlY2lmaWVkIHZhbHVlXG4gICAqXG4gICAqIEBzdGF0aWNcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBvYmpcbiAgICogQHBhcmFtIHsqfSBuZXdWYWx1ZVxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBwYXRoXG4gICAqIEByZXR1cm4geyp9XG4gICAqIEBtZW1iZXJvZiBDb25maWdWYWxpZGF0b3JcbiAgICovXG4gIHN0YXRpYyBtb2RpZnlPYmplY3Qob2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBuZXdWYWx1ZTogYW55LCBwYXRoOiBzdHJpbmdbXSkge1xuICAgIGxldCB2YWx1ZTogYW55ID0gb2JqO1xuICAgIGZvciAoY29uc3Qga2V5IG9mIHBhdGguc2xpY2UoMCwgLTEpKSB7XG4gICAgICBpZiAodmFsdWUgIT0gdW5kZWZpbmVkICYmIE9iamVjdC5oYXNPd24odmFsdWUsIGtleSkpIHtcbiAgICAgICAgdmFsdWUgPSB2YWx1ZVtrZXldO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGxhc3RLZXkgPSBwYXRoLmF0KC0xKTtcbiAgICBpZiAobGFzdEtleSAhPSB1bmRlZmluZWQpIHtcbiAgICAgIHZhbHVlW2xhc3RLZXldID0gbmV3VmFsdWU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIHZhbGlkYXRlcyBhIHZhbHVlIGluIGNvbmZpZyBvYmplY3RcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSB2YWx1ZVxuICAgKiBAcGFyYW0ge0NvbmZpZ0ZpZWxkfSBmaWVsZCB0aGUgZmllbGQgc3BlY2lmaWNhdGlvbiBpbiBzY2hlbWFcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBjb25maWcgdGhlIGNvbmZpZyBvYmplY3RcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVWYWx1ZSA9IChcbiAgICB2YWx1ZTogYW55LFxuICAgIGZpZWxkOiBDb25maWdGaWVsZCxcbiAgICBjb25maWc6IFJlY29yZDxzdHJpbmcsIGFueT5cbiAgKSA9PiB7XG4gICAgaWYgKHZhbHVlICE9IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKGZpZWxkLnR5cGUgPT09ICdiaWdpbnQnKSB7XG4gICAgICAgIHZhbHVlID0gQmlnSW50KHZhbHVlKTtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGQudHlwZSA9PT0gJ251bWJlcicgJiYgdmFsdWUgJiYgIWlzTmFOKHZhbHVlKSkge1xuICAgICAgICB2YWx1ZSA9IE51bWJlcih2YWx1ZSk7XG4gICAgICB9XG4gICAgICB2YWx1ZVZhbGlkYXRvcnNbZmllbGQudHlwZV0odmFsdWUsIGZpZWxkKTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBmaWVsZC50eXBlICE9PSAnb2JqZWN0JyAmJlxuICAgICAgZmllbGQudHlwZSAhPT0gJ2FycmF5JyAmJlxuICAgICAgZmllbGQudmFsaWRhdGlvbnNcbiAgICApIHtcbiAgICAgIGZvciAoY29uc3QgdmFsaWRhdGlvbiBvZiBmaWVsZC52YWxpZGF0aW9ucykge1xuICAgICAgICBjb25zdCBuYW1lID0gT2JqZWN0LmtleXModmFsaWRhdGlvbikuZmlsdGVyKFxuICAgICAgICAgIChrZXkpID0+IGtleSAhPT0gJ3doZW4nICYmIGtleSAhPT0gJ2Vycm9yJ1xuICAgICAgICApWzBdO1xuICAgICAgICBpZiAoT2JqZWN0Lmhhc093bih2YWx1ZVZhbGlkYXRpb25zW2ZpZWxkLnR5cGVdLCBuYW1lKSkge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB2YWx1ZVZhbGlkYXRpb25zW2ZpZWxkLnR5cGVdW25hbWVdKHZhbHVlLCB2YWxpZGF0aW9uLCBjb25maWcsIHRoaXMpO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgICAgICAgIGlmICh2YWxpZGF0aW9uLmVycm9yICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IodmFsaWRhdGlvbi5lcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIGRldGVybWluZXMgaWYgYSB3aGVuIGNsYXVzZSBpbiB2YWxpZGF0aW9ucyBzZWN0aW9uIG9mIGEgc2NoZW1hIGZpZWxkIGlzXG4gICAqIHNhdGlzZmllZFxuICAgKlxuICAgKiBAcGFyYW0ge1doZW59IHdoZW5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBjb25maWdcbiAgICogQHJldHVybiB7Ym9vbGVhbn1cbiAgICovXG4gIHB1YmxpYyBpc1doZW5UcnVlID0gKHdoZW46IFdoZW4sIGNvbmZpZzogUmVjb3JkPHN0cmluZywgYW55Pik6IGJvb2xlYW4gPT4ge1xuICAgIGNvbnN0IHBhdGhQYXJ0cyA9IHdoZW4ucGF0aC5zcGxpdCgnLicpO1xuICAgIGNvbnN0IHZhbHVlID0gQ29uZmlnVmFsaWRhdG9yLnZhbHVlQXQoY29uZmlnLCBwYXRoUGFydHMpO1xuICAgIHJldHVybiB2YWx1ZSAhPSB1bmRlZmluZWQgJiYgdmFsdWUgPT09IHdoZW4udmFsdWU7XG4gIH07XG5cbiAgLyoqXG4gICAqIHJldHVybnMgdGhlIHZhbHVlIGF0IHNwZWNpZmllZCBwYXRoIGluIGNvbmZpZyBvYmplY3RcbiAgICpcbiAgICogQHN0YXRpY1xuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IGNvbmZpZ1xuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBwYXRoXG4gICAqIEByZXR1cm4geyp9XG4gICAqL1xuICBzdGF0aWMgdmFsdWVBdCA9IChjb25maWc6IFJlY29yZDxzdHJpbmcsIGFueT4sIHBhdGg6IHN0cmluZ1tdKSA9PiB7XG4gICAgbGV0IHZhbHVlOiBhbnkgPSBjb25maWc7XG4gICAgZm9yIChjb25zdCBrZXkgb2YgcGF0aCkge1xuICAgICAgaWYgKHZhbHVlICE9IHVuZGVmaW5lZCAmJiBPYmplY3QuaGFzT3duKHZhbHVlLCBrZXkpKSB7XG4gICAgICAgIHZhbHVlID0gdmFsdWVba2V5XTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xuICB9O1xuXG4gIC8qKlxuICAgKiB2YWxpZGF0ZXMgdGhpcy5zY2hlbWEgYW5kIHRocm93cyBleGNlcHRpb24gaWYgYW55IGVycm9ycyBmb3VuZFxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVNjaGVtYSA9ICgpID0+IHtcbiAgICBjb25zdCBlcnJvclByZWFtYmxlID0gKHBhdGg6IEFycmF5PHN0cmluZz4pID0+XG4gICAgICBgU2NoZW1hIHZhbGlkYXRpb24gZmFpbGVkIGZvciBcIiR7cGF0aC5qb2luKCcuJyl9XCIgZmllbGRgO1xuXG4gICAgY29uc3Qgc3RhY2s6IEFycmF5PHtcbiAgICAgIHN1YlNjaGVtYTogQ29uZmlnU2NoZW1hO1xuICAgICAgcGFyZW50UGF0aDogQXJyYXk8c3RyaW5nPjtcbiAgICB9PiA9IFtcbiAgICAgIHtcbiAgICAgICAgc3ViU2NoZW1hOiB0aGlzLnNjaGVtYSxcbiAgICAgICAgcGFyZW50UGF0aDogW10sXG4gICAgICB9LFxuICAgIF07XG5cbiAgICAvLyBUcmF2ZXJzZXMgdGhlIHNjaGVtYSBvYmplY3QgdHJlZSBkZXB0aCBmaXJzdCBhbmQgdmFsaWRhdGUgZmllbGRzXG4gICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IHsgc3ViU2NoZW1hLCBwYXJlbnRQYXRoIH0gPSBzdGFjay5wb3AoKSE7XG5cbiAgICAgIC8vIHByb2Nlc3MgY2hpbGRyZW4gb2YgY3VycmVudCBvYmplY3QgZmllbGRcbiAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3Qua2V5cyhzdWJTY2hlbWEpLnJldmVyc2UoKSkge1xuICAgICAgICBjb25zdCBwYXRoID0gcGFyZW50UGF0aC5jb25jYXQoW25hbWVdKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB0aGlzLnZhbGlkYXRlQ29uZmlnTmFtZShuYW1lKTtcbiAgICAgICAgICBjb25zdCBmaWVsZCA9IHN1YlNjaGVtYVtuYW1lXTtcblxuICAgICAgICAgIGlmICghT2JqZWN0Lmhhc093bihmaWVsZCwgJ3R5cGUnKSB8fCB0eXBlb2YgZmllbGQudHlwZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgYGV2ZXJ5IHNjaGVtYSBmaWVsZCBtdXN0IGhhdmUgYSBcInR5cGVcIiBwcm9wZXJ0eSBvZiB0eXBlIFwic3RyaW5nXCJgXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghc3VwcG9ydGVkVHlwZXMuaW5jbHVkZXMoZmllbGQudHlwZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZmllbGQgdHlwZSBcIiR7ZmllbGQudHlwZX1cImApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMudmFsaWRhdGVTY2hlbWFGaWVsZChmaWVsZCk7XG5cbiAgICAgICAgICAvLyBpZiB0aGUgY2hpbGQgaXMgYW4gb2JqZWN0IGZpZWxkIGl0c2VsZiBhZGQgaXQgdG8gc3RhY2sgZm9yXG4gICAgICAgICAgLy8gcHJvY2Vzc2luZ1xuICAgICAgICAgIGlmIChmaWVsZC50eXBlID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgc3RhY2sucHVzaCh7XG4gICAgICAgICAgICAgIHN1YlNjaGVtYTogZmllbGQuY2hpbGRyZW4sXG4gICAgICAgICAgICAgIHBhcmVudFBhdGg6IHBhdGgsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGZpZWxkLnR5cGUgPT09ICdhcnJheScpIHtcbiAgICAgICAgICAgIHN0YWNrLnB1c2goe1xuICAgICAgICAgICAgICBzdWJTY2hlbWE6IHsgW25hbWVdOiBmaWVsZC5pdGVtcyB9LFxuICAgICAgICAgICAgICBwYXJlbnRQYXRoOiBwYXRoLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2Vycm9yUHJlYW1ibGUocGF0aCl9OiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIHZhbGlkYXRlcyBjb25maWcga2V5IG5hbWVcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVDb25maWdOYW1lID0gKG5hbWU6IHN0cmluZykgPT4ge1xuICAgIGlmIChuYW1lLmluY2x1ZGVzKCcuJykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgY29uZmlnIGtleSBuYW1lIGNhbiBub3QgY29udGFpbiB0aGUgJy4nIGNoYXJhY3RlcmApO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogdmFsaWRhdGVzIHBhc3NlZCBzY2hlbWEgZmllbGQgc3RydWN0dXJlXG4gICAqXG4gICAqIEBwYXJhbSB7Q29uZmlnRmllbGR9IGZpZWxkXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlU2NoZW1hRmllbGQgPSAoZmllbGQ6IENvbmZpZ0ZpZWxkKSA9PiB7XG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoZmllbGQpKSB7XG4gICAgICBpZiAoXG4gICAgICAgICFPYmplY3QuaGFzT3duKHByb3BlcnR5VmFsaWRhdG9ycy5hbGwsIGtleSkgJiZcbiAgICAgICAgIShcbiAgICAgICAgICAhWydvYmplY3QnLCAnYXJyYXknXS5pbmNsdWRlcyhmaWVsZC50eXBlKSAmJlxuICAgICAgICAgIE9iamVjdC5oYXNPd24ocHJvcGVydHlWYWxpZGF0b3JzLnByaW1pdGl2ZSwga2V5KVxuICAgICAgICApICYmXG4gICAgICAgICFPYmplY3QuaGFzT3duKHByb3BlcnR5VmFsaWRhdG9yc1tmaWVsZC50eXBlXSwga2V5KVxuICAgICAgKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgc2NoZW1hIGZpZWxkIGhhcyB1bmtub3duIHByb3BlcnR5IFwiJHtrZXl9XCJgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHZhbGlkYXRvciBvZiBPYmplY3QudmFsdWVzKHByb3BlcnR5VmFsaWRhdG9ycy5hbGwpKSB7XG4gICAgICB2YWxpZGF0b3IoZmllbGQsIHRoaXMpO1xuICAgIH1cblxuICAgIGlmIChmaWVsZC50eXBlICE9PSAnb2JqZWN0JyAmJiBmaWVsZC50eXBlICE9PSAnYXJyYXknKSB7XG4gICAgICBmb3IgKGNvbnN0IHZhbGlkYXRvciBvZiBPYmplY3QudmFsdWVzKHByb3BlcnR5VmFsaWRhdG9ycy5wcmltaXRpdmUpKSB7XG4gICAgICAgIHZhbGlkYXRvcihmaWVsZCwgdGhpcyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCB2YWxpZGF0b3Igb2YgT2JqZWN0LnZhbHVlcyhwcm9wZXJ0eVZhbGlkYXRvcnNbZmllbGQudHlwZV0pKSB7XG4gICAgICB2YWxpZGF0b3IoZmllbGQsIHRoaXMpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogcmV0dXJucyBhIGZpZWxkIGNvcnJlc3BvbmRpbmcgdG8gYSBwYXRoIGluIHNjaGVtYSB0cmVlXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IHBhdGhcbiAgICogQHJldHVybiB7KENvbmZpZ0ZpZWxkIHwgdW5kZWZpbmVkKX0gcmV0dXJucyB1bmRlZmluZWQgaWYgZmllbGQgaXMgbm90IGZvdW5kXG4gICAqL1xuICBnZXRTY2hlbWFGaWVsZCA9IChwYXRoOiBzdHJpbmdbXSk6IENvbmZpZ0ZpZWxkIHwgdW5kZWZpbmVkID0+IHtcbiAgICBsZXQgc3ViVHJlZTogQ29uZmlnU2NoZW1hIHwgdW5kZWZpbmVkID0gdGhpcy5zY2hlbWE7XG4gICAgbGV0IGZpZWxkOiBDb25maWdGaWVsZCB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgICBmb3IgKGNvbnN0IHBhcnQgb2YgcGF0aCkge1xuICAgICAgaWYgKHN1YlRyZWUgIT0gdW5kZWZpbmVkICYmIE9iamVjdC5oYXNPd24oc3ViVHJlZSwgcGFydCkpIHtcbiAgICAgICAgZmllbGQgPSBzdWJUcmVlW3BhcnRdO1xuICAgICAgICBzdWJUcmVlID1cbiAgICAgICAgICAnY2hpbGRyZW4nIGluIGZpZWxkXG4gICAgICAgICAgICA/IGZpZWxkLmNoaWxkcmVuXG4gICAgICAgICAgICA6ICdpdGVtcycgaW4gZmllbGQgJiYgJ2NoaWxkcmVuJyBpbiBmaWVsZC5pdGVtc1xuICAgICAgICAgICAgPyBmaWVsZC5pdGVtcy5jaGlsZHJlblxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmllbGQ7XG4gIH07XG5cbiAgLyoqXG4gICAqIGV4dHJhY3RzIGRlZmF1bHQgdmFsdWVzIGZyb20gYSBzY2hlbWFcbiAgICpcbiAgICogQHJldHVybiB7UmVjb3JkPHN0cmluZywgYW55Pn0gb2JqZWN0IG9mIGRlZmF1bHQgdmFsdWVzXG4gICAqL1xuICBnZW5lcmF0ZURlZmF1bHQgPSAoKTogUmVjb3JkPHN0cmluZywgYW55PiA9PiB7XG4gICAgY29uc3QgdmFsdWVUcmVlOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcblxuICAgIGNvbnN0IHN0YWNrOiB7XG4gICAgICBzY2hlbWE6IENvbmZpZ1NjaGVtYTtcbiAgICAgIHBhcmVudFZhbHVlOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHwgdW5kZWZpbmVkO1xuICAgICAgZmllbGROYW1lOiBzdHJpbmc7XG4gICAgICBjaGlsZHJlbjogc3RyaW5nW107XG4gICAgfVtdID0gW1xuICAgICAge1xuICAgICAgICBzY2hlbWE6IHRoaXMuc2NoZW1hLFxuICAgICAgICBwYXJlbnRWYWx1ZTogdW5kZWZpbmVkLFxuICAgICAgICBmaWVsZE5hbWU6ICcnLFxuICAgICAgICBjaGlsZHJlbjogT2JqZWN0LmtleXModGhpcy5zY2hlbWEpLnJldmVyc2UoKSxcbiAgICAgIH0sXG4gICAgXTtcblxuICAgIC8vIFRyYXZlcnNlcyB0aGUgc2NoZW1hIG9iamVjdCB0cmVlIGRlcHRoIGZpcnN0XG4gICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IHsgc2NoZW1hLCBwYXJlbnRWYWx1ZSwgZmllbGROYW1lLCBjaGlsZHJlbiB9ID0gc3RhY2suYXQoLTEpITtcblxuICAgICAgLy8gaWYgYSBzdWJ0cmVlJ3MgcHJvY2Vzc2luZyBpcyBmaW5pc2hlZCBnbyB0byB0aGUgcHJldmlvdXMgbGV2ZWxcbiAgICAgIGlmIChjaGlsZHJlbi5sZW5ndGggPT09IDApIHtcbiAgICAgICAgLy8gaWYgYSBzdWJ0cmVlIGlzIGVtcHR5IChoYXMgbm8gdmFsdWVzKSByZW1vdmUgaXQgZnJvbSB0aGUgcmVzdWx0XG4gICAgICAgIGlmIChcbiAgICAgICAgICBwYXJlbnRWYWx1ZSAhPSB1bmRlZmluZWQgJiZcbiAgICAgICAgICBPYmplY3Qua2V5cyhwYXJlbnRWYWx1ZVtmaWVsZE5hbWVdKS5sZW5ndGggPT09IDBcbiAgICAgICAgKSB7XG4gICAgICAgICAgZGVsZXRlIHBhcmVudFZhbHVlW2ZpZWxkTmFtZV07XG4gICAgICAgIH1cbiAgICAgICAgc3RhY2sucG9wKCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjaGlsZE5hbWUgPSBjaGlsZHJlbi5wb3AoKSE7XG4gICAgICBjb25zdCB2YWx1ZSA9XG4gICAgICAgIHBhcmVudFZhbHVlICE9IHVuZGVmaW5lZCA/IHBhcmVudFZhbHVlW2ZpZWxkTmFtZV0gOiB2YWx1ZVRyZWU7XG4gICAgICBjb25zdCBmaWVsZCA9IHNjaGVtYVtjaGlsZE5hbWVdO1xuICAgICAgLy8gaWYgYSBub2RlL2ZpZWxkIGlzIG9mIHR5cGUgb2JqZWN0IGFuZCB0aHVzIGlzIGEgc3VidHJlZSwgYWRkIGl0IGJvdGggdG9cbiAgICAgIC8vIHZhbHVlIHRyZWUgYW5kIHRvIHRoZSBzdGFjayB0byBiZSB0cmF2ZXJzZWQgbGF0ZXIuIE90aGVyd2lzZSBpdCdzIGFcbiAgICAgIC8vIGxlYWYgYW5kIG5lZWRzIG5vIHRyYXZlcnNhbCwgc28gYWRkIGl0IG9ubHkgdG8gdGhlIHZhbHVlIHRyZWUuXG4gICAgICBpZiAoZmllbGQudHlwZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgdmFsdWVbY2hpbGROYW1lXSA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgICAgIHN0YWNrLnB1c2goe1xuICAgICAgICAgIHNjaGVtYTogZmllbGQuY2hpbGRyZW4sXG4gICAgICAgICAgcGFyZW50VmFsdWU6IHZhbHVlLFxuICAgICAgICAgIGZpZWxkTmFtZTogY2hpbGROYW1lLFxuICAgICAgICAgIGNoaWxkcmVuOiBPYmplY3Qua2V5cyhmaWVsZC5jaGlsZHJlbikucmV2ZXJzZSgpLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAoZmllbGQudHlwZSAhPT0gJ2FycmF5JyAmJiBmaWVsZC5kZWZhdWx0ICE9IHVuZGVmaW5lZCkge1xuICAgICAgICB2YWx1ZVtjaGlsZE5hbWVdID0gZmllbGQuZGVmYXVsdDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWVUcmVlO1xuICB9O1xuXG4gIC8qKlxuICAgKiBnZW5lcmF0ZXMgY29tcGF0aWJsZSBUeXBlU2NyaXB0IGludGVyZmFjZSBmb3IgdGhpcyBpbnN0YW5jZSdzIHNjaGVtYVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSB0aGUgbmFtZSBvZiByb290IHR5cGVcbiAgICogQHJldHVybiB7c3RyaW5nfVxuICAgKi9cbiAgZ2VuZXJhdGVUU1R5cGVzID0gKG5hbWU6IHN0cmluZyk6IHN0cmluZyA9PiB7XG4gICAgY29uc3QgZXJyb3JQcmVhbWJsZSA9IChwYXRoOiBBcnJheTxzdHJpbmc+KSA9PlxuICAgICAgYFR5cGVTY3JpcHQgdHlwZSBnZW5lcmF0aW9uIGZhaWxlZCBmb3IgXCIke3BhdGguam9pbignLicpfVwiIGZpZWxkYDtcblxuICAgIGNvbnN0IHR5cGVzOiBBcnJheTxzdHJpbmc+ID0gW107XG5cbiAgICBjb25zdCB0eXBlTmFtZXM6IE1hcDxzdHJpbmcsIGJpZ2ludD4gPSBuZXcgTWFwPHN0cmluZywgYmlnaW50PigpO1xuICAgIHR5cGVOYW1lcy5zZXQobmFtZSwgMW4pO1xuXG4gICAgY29uc3Qgc3RhY2s6IEFycmF5PHtcbiAgICAgIHN1YlNjaGVtYTogQ29uZmlnU2NoZW1hO1xuICAgICAgY2hpbGRyZW46IHN0cmluZ1tdO1xuICAgICAgcGFyZW50UGF0aDogQXJyYXk8c3RyaW5nPjtcbiAgICAgIHR5cGVOYW1lOiBzdHJpbmc7XG4gICAgICBhdHRyaWJ1dGVzOiBBcnJheTxbc3RyaW5nLCBzdHJpbmddPjtcbiAgICB9PiA9IFtcbiAgICAgIHtcbiAgICAgICAgc3ViU2NoZW1hOiB0aGlzLnNjaGVtYSxcbiAgICAgICAgY2hpbGRyZW46IE9iamVjdC5rZXlzKHRoaXMuc2NoZW1hKSxcbiAgICAgICAgcGFyZW50UGF0aDogW10sXG4gICAgICAgIHR5cGVOYW1lOiBuYW1lLFxuICAgICAgICBhdHRyaWJ1dGVzOiBbXSxcbiAgICAgIH0sXG4gICAgXTtcblxuICAgIC8vIFRyYXZlcnNlcyB0aGUgc2NoZW1hIG9iamVjdCB0cmVlIGRlcHRoIGZpcnN0XG4gICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IHsgc3ViU2NoZW1hLCBjaGlsZHJlbiwgcGFyZW50UGF0aCwgdHlwZU5hbWUsIGF0dHJpYnV0ZXMgfSA9XG4gICAgICAgIHN0YWNrLmF0KC0xKSE7XG4gICAgICBjb25zdCBwYXRoID0gcGFyZW50UGF0aC5jb25jYXQoW25hbWVdKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIGlmIGEgc3VidHJlZSdzIHByb2Nlc3NpbmcgaXMgZmluaXNoZWQgZ28gdG8gdGhlIHByZXZpb3VzIGxldmVsXG4gICAgICAgIGlmIChjaGlsZHJlbi5sZW5ndGggPT0gMCkge1xuICAgICAgICAgIHR5cGVzLnB1c2godGhpcy5nZW5UU0ludGVyZmFjZSh0eXBlTmFtZSwgYXR0cmlidXRlcykpO1xuICAgICAgICAgIHN0YWNrLnBvcCgpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2hpbGROYW1lID0gY2hpbGRyZW4ucG9wKCkhO1xuICAgICAgICBjb25zdCBmaWVsZCA9IHN1YlNjaGVtYVtjaGlsZE5hbWVdO1xuXG4gICAgICAgIC8vIGlmIGEgbm9kZS9maWVsZCBpcyBvZiB0eXBlIG9iamVjdCBhbmQgdGh1cyBpcyBhIHN1YnRyZWUsIGFkZCBpdCB0b1xuICAgICAgICAvLyB0aGUgc3RhY2sgdG8gYmUgdHJhdmVyc2VkIGxhdGVyLiBPdGhlcndpc2UgaXQncyBhIGxlYWYgYW5kIG5lZWRzIG5vXG4gICAgICAgIC8vIHRyYXZlcnNhbC5cbiAgICAgICAgaWYgKFxuICAgICAgICAgIGZpZWxkLnR5cGUgPT09ICdvYmplY3QnIHx8XG4gICAgICAgICAgKGZpZWxkLnR5cGUgPT09ICdhcnJheScgJiYgZmllbGQuaXRlbXMudHlwZSA9PT0gJ29iamVjdCcpXG4gICAgICAgICkge1xuICAgICAgICAgIGxldCBjaGlsZFR5cGVOYW1lID0gYCR7Y2hpbGROYW1lWzBdLnRvVXBwZXJDYXNlKCl9JHtjaGlsZE5hbWUuc3Vic3RyaW5nKFxuICAgICAgICAgICAgMVxuICAgICAgICAgICl9YDtcbiAgICAgICAgICBjb25zdCB0eXBlTmFtZUNvdW50ID0gdHlwZU5hbWVzLmdldChjaGlsZFR5cGVOYW1lKTtcbiAgICAgICAgICB0eXBlTmFtZXMuc2V0KGNoaWxkVHlwZU5hbWUsICh0eXBlTmFtZXMuZ2V0KGNoaWxkTmFtZSkgfHwgMG4pICsgMW4pO1xuICAgICAgICAgIGlmICh0eXBlTmFtZUNvdW50KSB7XG4gICAgICAgICAgICBjaGlsZFR5cGVOYW1lICs9IHR5cGVOYW1lQ291bnQudG9TdHJpbmcoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBjaGlsZHJlbiA9XG4gICAgICAgICAgICBmaWVsZC50eXBlID09PSAnYXJyYXknICYmIGZpZWxkLml0ZW1zLnR5cGUgPT09ICdvYmplY3QnXG4gICAgICAgICAgICAgID8gZmllbGQuaXRlbXMuY2hpbGRyZW5cbiAgICAgICAgICAgICAgOiBmaWVsZC50eXBlID09PSAnb2JqZWN0J1xuICAgICAgICAgICAgICA/IGZpZWxkLmNoaWxkcmVuXG4gICAgICAgICAgICAgIDoge307XG5cbiAgICAgICAgICBzdGFjay5wdXNoKHtcbiAgICAgICAgICAgIHN1YlNjaGVtYTogY2hpbGRyZW4sXG4gICAgICAgICAgICBjaGlsZHJlbjogT2JqZWN0LmtleXMoY2hpbGRyZW4pLnJldmVyc2UoKSxcbiAgICAgICAgICAgIHBhcmVudFBhdGg6IHBhdGgsXG4gICAgICAgICAgICB0eXBlTmFtZTogY2hpbGRUeXBlTmFtZSxcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IFtdLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgYXR0cmlidXRlcy5wdXNoKFtcbiAgICAgICAgICAgIGNoaWxkTmFtZSxcbiAgICAgICAgICAgIGZpZWxkLnR5cGUgPT09ICdhcnJheScgPyBgJHtjaGlsZFR5cGVOYW1lfVtdYCA6IGNoaWxkVHlwZU5hbWUsXG4gICAgICAgICAgXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbGV0IGZpZWxkVHlwZTogc3RyaW5nID1cbiAgICAgICAgICAgIGZpZWxkLnR5cGUgPT09ICdhcnJheScgPyBmaWVsZC5pdGVtcy50eXBlIDogZmllbGQudHlwZTtcbiAgICAgICAgICBsZXQgaXNPcHRpb25hbCA9IHRydWU7XG4gICAgICAgICAgaWYgKGZpZWxkLnR5cGUgIT09ICdhcnJheScgJiYgZmllbGQudmFsaWRhdGlvbnMgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHZhbGlkYXRpb24gb2YgZmllbGQudmFsaWRhdGlvbnMpIHtcbiAgICAgICAgICAgICAgaWYgKGZpZWxkLnR5cGUgPT09ICdzdHJpbmcnICYmICdjaG9pY2VzJyBpbiB2YWxpZGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgZmllbGRUeXBlID0gdmFsaWRhdGlvbi5jaG9pY2VzLm1hcCgoYykgPT4gYCcke2N9J2ApLmpvaW4oJyB8ICcpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKCdyZXF1aXJlZCcgaW4gdmFsaWRhdGlvbiAmJiAhKCd3aGVuJyBpbiB2YWxpZGF0aW9uKSkge1xuICAgICAgICAgICAgICAgIGlzT3B0aW9uYWwgPSBmYWxzZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBhdHRyaWJ1dGVzLnB1c2goW1xuICAgICAgICAgICAgaXNPcHRpb25hbCA/IGAke2NoaWxkTmFtZX0/YCA6IGNoaWxkTmFtZSxcbiAgICAgICAgICAgIGZpZWxkLnR5cGUgPT09ICdhcnJheScgPyBgJHtmaWVsZFR5cGV9W11gIDogZmllbGRUeXBlLFxuICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtlcnJvclByZWFtYmxlKHBhdGgpfTogJHtlcnJvci5tZXNzYWdlfWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0eXBlcy5yZXZlcnNlKCkuam9pbignXFxuXFxuJykgKyAnXFxuJztcbiAgfTtcblxuICAvKipcbiAgICogZ2VuZXJhdGVzIGEgVHlwZVNjcmlwdCBpbnRlcmZhY2UgZGVmaW5pdGlvbiBmb3IgcGFzc2VkIG5hbWUgYW5kIGF0dHJpYnV0ZXNcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtBcnJheTxbc3RyaW5nLCBzdHJpbmddPn0gYXR0cmlidXRlc1xuICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAqL1xuICBwcml2YXRlIGdlblRTSW50ZXJmYWNlID0gKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBhdHRyaWJ1dGVzOiBBcnJheTxbc3RyaW5nLCBzdHJpbmddPlxuICApOiBzdHJpbmcgPT4ge1xuICAgIHJldHVybiBgZXhwb3J0IGludGVyZmFjZSAke25hbWV9IHtcbiAgJHthdHRyaWJ1dGVzLm1hcCgoYXR0cikgPT4gYCR7YXR0clswXX06ICR7YXR0clsxXX07YCkuam9pbignXFxuICAnKX1cbn1gO1xuICB9O1xuXG4gIC8qKlxuICAgKiByZXR1cm5zIGEgY2hhcmFjdGVyaXN0aWMgb2JqZWN0IGZvciB2YWx1ZXMgYXQgYSBzcGVjaWZpYyBub2RlIGNvbmZpZyBsZXZlbFxuICAgKlxuICAgKiBAcGFyYW0ge0lDb25maWd9IGNvbmZpZ1xuICAgKiBAcGFyYW0ge3N0cmluZ30gbGV2ZWxcbiAgICogQHJldHVybiB7UmVjb3JkPHN0cmluZywgYW55Pn1cbiAgICovXG4gIGdldENvbmZpZ0ZvckxldmVsKGNvbmZpZzogSUNvbmZpZywgbGV2ZWw6IHN0cmluZyk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuICAgIGNvbnN0IGNvbmZMZXZlbHMgPSBDb25maWdWYWxpZGF0b3IuZ2V0Tm9kZUNvbmZpZ0xldmVscyhjb25maWcpO1xuICAgIGNvbnN0IGxldmVsSW5kZXggPSBjb25mTGV2ZWxzLmluZGV4T2YobGV2ZWwpO1xuICAgIGlmIChsZXZlbEluZGV4ID09PSAtMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVGhlIFwiJHtsZXZlbH1cIiBsZXZlbCBub3QgZm91bmQgaW4gdGhlIGN1cnJlbnQgc3lzdGVtIGNvbmZpZ3VyYXRpb24gbGV2ZWxzYFxuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3QgaGlnaGVyTGV2ZWxTb3VyY2VzID0gY29uZmlnLnV0aWxcbiAgICAgIC5nZXRDb25maWdTb3VyY2VzKClcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChzb3VyY2UpID0+IGNvbmZMZXZlbHMuaW5kZXhPZihnZXRTb3VyY2VOYW1lKHNvdXJjZSkpID4gbGV2ZWxJbmRleFxuICAgICAgKTtcbiAgICBjb25zdCBjdXJyZW50TGV2ZWxTb3VyY2UgPSBjb25maWcudXRpbFxuICAgICAgLmdldENvbmZpZ1NvdXJjZXMoKVxuICAgICAgLmZpbHRlcigoc291cmNlKSA9PiBnZXRTb3VyY2VOYW1lKHNvdXJjZSkgPT09IGxldmVsKVxuICAgICAgLmF0KDApO1xuICAgIGNvbnN0IGxvd2VyTGV2ZWxTb3VyY2VzID0gY29uZmlnLnV0aWxcbiAgICAgIC5nZXRDb25maWdTb3VyY2VzKClcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChzb3VyY2UpID0+IGNvbmZMZXZlbHMuaW5kZXhPZihnZXRTb3VyY2VOYW1lKHNvdXJjZSkpIDwgbGV2ZWxJbmRleFxuICAgICAgKTtcblxuICAgIC8vIFRyYXZlcnNlcyB0aGUgc2NoZW1hIG9iamVjdCB0cmVlIGRlcHRoIGZpcnN0XG4gICAgY29uc3QgdmFsdWVUcmVlID0gQ29uZmlnVmFsaWRhdG9yLnByb2Nlc3NDb25maWdGb3JMZXZlbE5vZGUoXG4gICAgICB0aGlzLnNjaGVtYSxcbiAgICAgIFtdLFxuICAgICAgaGlnaGVyTGV2ZWxTb3VyY2VzLFxuICAgICAgY3VycmVudExldmVsU291cmNlLFxuICAgICAgbG93ZXJMZXZlbFNvdXJjZXNcbiAgICApO1xuXG4gICAgcmV0dXJuIHZhbHVlVHJlZTtcbiAgfVxuXG4gIC8qKlxuICAgKnRyYXZlcnNlcyB0aGUgY29uZmlnIHNjaGVtYSBkZXB0aCBmaXJzdCB0byBwcm9kdWNlIGNoYXJhY3RlcmlzdGljIG9iamVjdFxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAc3RhdGljXG4gICAqIEBwYXJhbSB7Q29uZmlnU2NoZW1hfSBzY2hlbWFcbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gcGF0aFxuICAgKiBAcGFyYW0ge0lDb25maWdTb3VyY2VbXX0gaGlnaGVyTGV2ZWxTb3VyY2VzXG4gICAqIEBwYXJhbSB7KElDb25maWdTb3VyY2UgfCB1bmRlZmluZWQpfSBjdXJyZW50TGV2ZWxTb3VyY2VcbiAgICogQHBhcmFtIHtJQ29uZmlnU291cmNlW119IGxvd2VyTGV2ZWxTb3VyY2VzXG4gICAqIEByZXR1cm4ge1JlY29yZDxzdHJpbmcsIGFueT59XG4gICAqIEBtZW1iZXJvZiBDb25maWdWYWxpZGF0b3JcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHByb2Nlc3NDb25maWdGb3JMZXZlbE5vZGUoXG4gICAgc2NoZW1hOiBDb25maWdTY2hlbWEsXG4gICAgcGF0aDogc3RyaW5nW10sXG4gICAgaGlnaGVyTGV2ZWxTb3VyY2VzOiBJQ29uZmlnU291cmNlW10sXG4gICAgY3VycmVudExldmVsU291cmNlOiBJQ29uZmlnU291cmNlIHwgdW5kZWZpbmVkLFxuICAgIGxvd2VyTGV2ZWxTb3VyY2VzOiBJQ29uZmlnU291cmNlW11cbiAgKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgY29uc3QgdmFsdWUgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgIGZvciAoY29uc3QgY2hpbGROYW1lIG9mIE9iamVjdC5rZXlzKHNjaGVtYSkucmV2ZXJzZSgpKSB7XG4gICAgICBjb25zdCBjaGlsZFBhdGggPSBwYXRoLmNvbmNhdChbY2hpbGROYW1lXSk7XG4gICAgICBjb25zdCBmaWVsZCA9IHNjaGVtYVtjaGlsZE5hbWVdO1xuICAgICAgLy8gaWYgYSBmaWVsZCBpcyBvZiB0eXBlIG9iamVjdCBhbmQgdGh1cyBpcyBhIHN1YnRyZWUsIHJlY3Vyc2Ugb24gaXQuXG4gICAgICAvLyBPdGhlcndpc2UgaXQncyBhIGxlYWYgYW5kIG5lZWRzIG5vIHRyYXZlcnNhbC5cbiAgICAgIHZhbHVlW2NoaWxkTmFtZV0gPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgICAgaWYgKGZpZWxkLnR5cGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIHZhbHVlW2NoaWxkTmFtZV0gPSBDb25maWdWYWxpZGF0b3IucHJvY2Vzc0NvbmZpZ0ZvckxldmVsTm9kZShcbiAgICAgICAgICBmaWVsZC5jaGlsZHJlbixcbiAgICAgICAgICBjaGlsZFBhdGgsXG4gICAgICAgICAgaGlnaGVyTGV2ZWxTb3VyY2VzLFxuICAgICAgICAgIGN1cnJlbnRMZXZlbFNvdXJjZSxcbiAgICAgICAgICBsb3dlckxldmVsU291cmNlc1xuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFsdWVbY2hpbGROYW1lXVsnbGFiZWwnXSA9XG4gICAgICAgICAgZmllbGQubGFiZWwgIT0gdW5kZWZpbmVkID8gZmllbGQubGFiZWwgOiBudWxsO1xuICAgICAgICB2YWx1ZVtjaGlsZE5hbWVdWydkZXNjcmlwdGlvbiddID1cbiAgICAgICAgICBmaWVsZC5kZXNjcmlwdGlvbiAhPSB1bmRlZmluZWQgPyBmaWVsZC5kZXNjcmlwdGlvbiA6IG51bGw7XG4gICAgICAgIHZhbHVlW2NoaWxkTmFtZV1bJ2RlZmF1bHQnXSA9IGdldFZhbHVlRnJvbUNvbmZpZ1NvdXJjZXMoXG4gICAgICAgICAgbG93ZXJMZXZlbFNvdXJjZXMsXG4gICAgICAgICAgY2hpbGRQYXRoXG4gICAgICAgICk7XG4gICAgICAgIHZhbHVlW2NoaWxkTmFtZV1bJ3ZhbHVlJ10gPSBnZXRWYWx1ZUZyb21Db25maWdTb3VyY2VzKFxuICAgICAgICAgIFsuLi4oY3VycmVudExldmVsU291cmNlICE9IHVuZGVmaW5lZCA/IFtjdXJyZW50TGV2ZWxTb3VyY2VdIDogW10pXSxcbiAgICAgICAgICBjaGlsZFBhdGhcbiAgICAgICAgKTtcbiAgICAgICAgdmFsdWVbY2hpbGROYW1lXVsnb3ZlcnJpZGUnXSA9IGdldFZhbHVlRnJvbUNvbmZpZ1NvdXJjZXMoXG4gICAgICAgICAgaGlnaGVyTGV2ZWxTb3VyY2VzLFxuICAgICAgICAgIGNoaWxkUGF0aFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiByZXR1cm5zIGEgbGlzdCBvZiBjb25maWcgc291cmNlcyB1c2VkIGJ5IG5vZGUgY29uZmlnIHBhY2thZ2UsIG9yZGVyZWQgZnJvbVxuICAgKiB0aGUgbG93ZXN0IHRvIHRoZSBoaWdoZXN0IHByaW9yaXR5XG4gICAqXG4gICAqIEBzdGF0aWNcbiAgICogQHBhcmFtIHtJQ29uZmlnfSBjb25maWdcbiAgICogQHJldHVybiAge3N0cmluZ1tdfVxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0Tm9kZUNvbmZpZ0xldmVscyA9IChjb25maWc6IElDb25maWcpOiBzdHJpbmdbXSA9PiB7XG4gICAgY29uc3QgaW5zdGFuY2UgPSBjb25maWcudXRpbC5nZXRFbnYoJ05PREVfQVBQX0lOU1RBTkNFJyk7XG4gICAgbGV0IGRlcGxveW1lbnQgPSBjb25maWcudXRpbC5nZXRFbnYoJ05PREVfRU5WJyk7XG4gICAgZGVwbG95bWVudCA9IGNvbmZpZy51dGlsLmdldEVudignTk9ERV9DT05GSUdfRU5WJyk7XG4gICAgY29uc3QgZnVsbEhvc3RuYW1lID0gY29uZmlnLnV0aWwuZ2V0RW52KCdIT1NUTkFNRScpO1xuICAgIGNvbnN0IHNob3J0SG9zdG5hbWUgPVxuICAgICAgZnVsbEhvc3RuYW1lICE9IHVuZGVmaW5lZCA/IGZ1bGxIb3N0bmFtZS5zcGxpdCgnLicpWzBdIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgY29uZmlnTGV2ZWxzID0gW1xuICAgICAgJ2RlZmF1bHQnLFxuICAgICAgLi4uKGluc3RhbmNlICE9IHVuZGVmaW5lZCA/IFtgZGVmYXVsdC0ke2luc3RhbmNlfWBdIDogW10pLFxuICAgICAgLi4uKGRlcGxveW1lbnQgIT0gdW5kZWZpbmVkID8gW2Ake2RlcGxveW1lbnR9YF0gOiBbXSksXG4gICAgICAuLi4oaW5zdGFuY2UgIT0gdW5kZWZpbmVkICYmIGRlcGxveW1lbnQgIT0gdW5kZWZpbmVkXG4gICAgICAgID8gW2Ake2RlcGxveW1lbnR9LSR7aW5zdGFuY2V9YF1cbiAgICAgICAgOiBbXSksXG4gICAgICAuLi4oc2hvcnRIb3N0bmFtZSAhPSB1bmRlZmluZWQgPyBbYCR7c2hvcnRIb3N0bmFtZX1gXSA6IFtdKSxcbiAgICAgIC4uLihzaG9ydEhvc3RuYW1lICE9IHVuZGVmaW5lZCAmJiBpbnN0YW5jZSAhPSB1bmRlZmluZWRcbiAgICAgICAgPyBbYCR7c2hvcnRIb3N0bmFtZX0tJHtpbnN0YW5jZX1gXVxuICAgICAgICA6IFtdKSxcbiAgICAgIC4uLihzaG9ydEhvc3RuYW1lICE9IHVuZGVmaW5lZCAmJiBkZXBsb3ltZW50ICE9IHVuZGVmaW5lZFxuICAgICAgICA/IFtgJHtzaG9ydEhvc3RuYW1lfS0ke2RlcGxveW1lbnR9YF1cbiAgICAgICAgOiBbXSksXG4gICAgICAuLi4oc2hvcnRIb3N0bmFtZSAhPSB1bmRlZmluZWQgJiZcbiAgICAgIGRlcGxveW1lbnQgIT0gdW5kZWZpbmVkICYmXG4gICAgICBpbnN0YW5jZSAhPSB1bmRlZmluZWRcbiAgICAgICAgPyBbYCR7c2hvcnRIb3N0bmFtZX0tJHtkZXBsb3ltZW50fS0ke2luc3RhbmNlfWBdXG4gICAgICAgIDogW10pLFxuICAgICAgLi4uKGZ1bGxIb3N0bmFtZSAhPSB1bmRlZmluZWQgPyBbYCR7ZnVsbEhvc3RuYW1lfWBdIDogW10pLFxuICAgICAgLi4uKGZ1bGxIb3N0bmFtZSAhPSB1bmRlZmluZWQgJiYgaW5zdGFuY2UgIT0gdW5kZWZpbmVkXG4gICAgICAgID8gW2Ake2Z1bGxIb3N0bmFtZX0tJHtpbnN0YW5jZX1gXVxuICAgICAgICA6IFtdKSxcbiAgICAgIC4uLihmdWxsSG9zdG5hbWUgIT0gdW5kZWZpbmVkICYmIGRlcGxveW1lbnQgIT0gdW5kZWZpbmVkXG4gICAgICAgID8gW2Ake2Z1bGxIb3N0bmFtZX0tJHtkZXBsb3ltZW50fWBdXG4gICAgICAgIDogW10pLFxuICAgICAgLi4uKGZ1bGxIb3N0bmFtZSAhPSB1bmRlZmluZWQgJiZcbiAgICAgIGRlcGxveW1lbnQgIT0gdW5kZWZpbmVkICYmXG4gICAgICBpbnN0YW5jZSAhPSB1bmRlZmluZWRcbiAgICAgICAgPyBbYCR7ZnVsbEhvc3RuYW1lfS0ke2RlcGxveW1lbnR9LSR7aW5zdGFuY2V9YF1cbiAgICAgICAgOiBbXSksXG4gICAgICBgbG9jYWxgLFxuICAgICAgLi4uKGluc3RhbmNlICE9IHVuZGVmaW5lZCA/IFtgbG9jYWwtJHtpbnN0YW5jZX1gXSA6IFtdKSxcbiAgICAgIC4uLihkZXBsb3ltZW50ICE9IHVuZGVmaW5lZCA/IFtgbG9jYWwtJHtkZXBsb3ltZW50fWBdIDogW10pLFxuICAgICAgLi4uKGRlcGxveW1lbnQgIT0gdW5kZWZpbmVkICYmIGluc3RhbmNlICE9IHVuZGVmaW5lZFxuICAgICAgICA/IFtgbG9jYWwtJHtkZXBsb3ltZW50fS0ke2luc3RhbmNlfWBdXG4gICAgICAgIDogW10pLFxuICAgICAgJyROT0RFX0NPTkZJRycsXG4gICAgICAnY3VzdG9tLWVudmlyb25tZW50LXZhcmlhYmxlcycsXG4gICAgXTtcblxuICAgIHJldHVybiBjb25maWdMZXZlbHM7XG4gIH07XG5cbiAgLyoqXG4gICAqIHZhbGlkYXRlcyBhIGNvbmZpZyBvYmplY3QgYW5kIHdyaXRlcyBpdCB0byB0aGUgbm9kZS1jb25maWcgZmlsZVxuICAgKiBjb3JyZXNwb25kaW5nIHRvIHRoZSBwYXNzZWQgbGV2ZWxcbiAgICpcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBjb25maWdPYmpcbiAgICogQHBhcmFtIHtJQ29uZmlnfSBjb25maWdcbiAgICogQHBhcmFtIHtzdHJpbmd9IGxldmVsIG91dHB1dCBub2RlLWNvbmZpZyBmaWxlIGxldmVsXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXQgdGhlIGZvcm1hdCBvZiB0aGUgb3V0cHV0IGZpbGVcbiAgICovXG4gIHZhbGlkYXRlQW5kV3JpdGVDb25maWcgPSAoXG4gICAgY29uZmlnT2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIGNvbmZpZzogSUNvbmZpZyxcbiAgICBsZXZlbDogc3RyaW5nLFxuICAgIGZvcm1hdDogc3RyaW5nXG4gICkgPT4ge1xuICAgIGNvbnN0IGNvbmZMZXZlbHMgPSBDb25maWdWYWxpZGF0b3IuZ2V0Tm9kZUNvbmZpZ0xldmVscyhjb25maWcpLmZpbHRlcihcbiAgICAgIChsKSA9PiBsICE9PSAnY3VzdG9tLWVudmlyb25tZW50LXZhcmlhYmxlcydcbiAgICApO1xuICAgIGNvbnN0IGxldmVsSW5kZXggPSBjb25mTGV2ZWxzLmluZGV4T2YobGV2ZWwpO1xuICAgIGlmIChsZXZlbEluZGV4ID09PSAtMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVGhlIFske2xldmVsfV0gbGV2ZWwgbm90IGZvdW5kIGluIHRoZSBjdXJyZW50IHN5c3RlbSdzIGNvbmZpZ3VyYXRpb24gbGV2ZWxzYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBjb25maWdEaXIgPVxuICAgICAgcHJvY2Vzcy5lbnZbJ05PREVfQ09ORklHX0RJUiddICE9IHVuZGVmaW5lZFxuICAgICAgICA/IHByb2Nlc3MuZW52WydOT0RFX0NPTkZJR19ESVInXVxuICAgICAgICA6ICcuL2NvbmZpZyc7XG4gICAgbGV0IG91dHB1dCA9ICcnO1xuICAgIGxldCBleHQgPSAnJztcbiAgICBzd2l0Y2ggKGZvcm1hdCkge1xuICAgICAgY2FzZSAnanNvbic6IHtcbiAgICAgICAgY29uc3QgSnNvbkJpZ0ludCA9IEpzb25CaWdJbnRGYWN0b3J5KHtcbiAgICAgICAgICBhbHdheXNQYXJzZUFzQmlnOiBmYWxzZSxcbiAgICAgICAgICB1c2VOYXRpdmVCaWdJbnQ6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgICBvdXRwdXQgPSBKc29uQmlnSW50LnN0cmluZ2lmeShjb25maWdPYmopO1xuICAgICAgICBleHQgPSAnanNvbic7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAneWFtbCc6IHtcbiAgICAgICAgb3V0cHV0ID0geWFtbC5kdW1wKGNvbmZpZ09iaik7XG4gICAgICAgIGV4dCA9ICd5YW1sJztcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBFcnJvcihgSW52YWxpZCBmb3JtYXQ6ICR7Zm9ybWF0fWApO1xuICAgIH1cblxuICAgIGNvbnN0IG91dHB1dFBhdGggPSBwYXRoLmpvaW4oY29uZmlnRGlyLCBgJHtsZXZlbH0uJHtleHR9YCk7XG4gICAgY29uc3QgYmFja3VwUGF0aCA9IHBhdGguam9pbihjb25maWdEaXIsIGAke2xldmVsfS1iYWNrdXAuJHtleHR9YCk7XG4gICAgY29uc3QgY29uZkZpbGVFeGlzdHMgPSBmcy5leGlzdHNTeW5jKG91dHB1dFBhdGgpO1xuICAgIGlmIChjb25mRmlsZUV4aXN0cykge1xuICAgICAgZnMucmVuYW1lU3luYyhvdXRwdXRQYXRoLCBiYWNrdXBQYXRoKTtcbiAgICB9XG4gICAgZnMud3JpdGVGaWxlU3luYyhvdXRwdXRQYXRoLCBvdXRwdXQpO1xuXG4gICAgY29uc3QgdXBkYXRlZENvbmZPYmogPSBjb25maWcudXRpbC5sb2FkRmlsZUNvbmZpZ3MoKTtcblxuICAgIHRyeSB7XG4gICAgICB0aGlzLnZhbGlkYXRlQ29uZmlnKHVwZGF0ZWRDb25mT2JqKTtcbiAgICAgIGZzLnVubGlua1N5bmMoYmFja3VwUGF0aCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGZzLnVubGlua1N5bmMob3V0cHV0UGF0aCk7XG4gICAgICBpZiAoY29uZkZpbGVFeGlzdHMpIHtcbiAgICAgICAgZnMucmVuYW1lU3luYyhiYWNrdXBQYXRoLCBvdXRwdXRQYXRoKTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfTtcbn1cbiJdfQ==