1 | ;
|
2 | var _a, _b;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.unionValidator = exports.requireProperty = exports.requiredValidator = exports.propertyValidator = exports.hashValidator = exports.listValidator = exports.validateCfnTag = exports.validateObject = exports.validateDate = exports.validateBoolean = exports.validateNumber = exports.validateString = exports.canInspect = exports.VALIDATION_SUCCESS = exports.ValidationResults = exports.ValidationResult = exports.unionMapper = exports.hashMapper = exports.listMapper = exports.cfnTagToCloudFormation = exports.dateToCloudFormation = exports.numberToCloudFormation = exports.objectToCloudFormation = exports.booleanToCloudFormation = exports.stringToCloudFormation = void 0;
|
5 | const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
6 | const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
7 | function identity(x) {
|
8 | return x;
|
9 | }
|
10 | exports.stringToCloudFormation = identity;
|
11 | exports.booleanToCloudFormation = identity;
|
12 | exports.objectToCloudFormation = identity;
|
13 | exports.numberToCloudFormation = identity;
|
14 | /**
|
15 | * The date needs to be formatted as an ISO date in UTC
|
16 | *
|
17 | * Some usage sites require a date, some require a timestamp. We'll
|
18 | * always output a timestamp and hope the parser on the other end
|
19 | * is smart enough to ignore the time part... (?)
|
20 | */
|
21 | function dateToCloudFormation(x) {
|
22 | if (!x) {
|
23 | return undefined;
|
24 | }
|
25 | // eslint-disable-next-line max-len
|
26 | return `${x.getUTCFullYear()}-${pad(x.getUTCMonth() + 1)}-${pad(x.getUTCDate())}T${pad(x.getUTCHours())}:${pad(x.getUTCMinutes())}:${pad(x.getUTCSeconds())}`;
|
27 | }
|
28 | exports.dateToCloudFormation = dateToCloudFormation;
|
29 | /**
|
30 | * Pad a number to 2 decimal places
|
31 | */
|
32 | function pad(x) {
|
33 | if (x < 10) {
|
34 | return '0' + x.toString();
|
35 | }
|
36 | return x.toString();
|
37 | }
|
38 | /**
|
39 | * Turn a tag object into the proper CloudFormation representation
|
40 | */
|
41 | function cfnTagToCloudFormation(x) {
|
42 | return {
|
43 | Key: x.key,
|
44 | Value: x.value,
|
45 | };
|
46 | }
|
47 | exports.cfnTagToCloudFormation = cfnTagToCloudFormation;
|
48 | function listMapper(elementMapper) {
|
49 | return (x) => {
|
50 | if (!canInspect(x)) {
|
51 | return x;
|
52 | }
|
53 | return x.map(elementMapper);
|
54 | };
|
55 | }
|
56 | exports.listMapper = listMapper;
|
57 | function hashMapper(elementMapper) {
|
58 | return (x) => {
|
59 | if (!canInspect(x)) {
|
60 | return x;
|
61 | }
|
62 | const ret = {};
|
63 | Object.keys(x).forEach((key) => {
|
64 | ret[key] = elementMapper(x[key]);
|
65 | });
|
66 | return ret;
|
67 | };
|
68 | }
|
69 | exports.hashMapper = hashMapper;
|
70 | /**
|
71 | * Return a union mapper
|
72 | *
|
73 | * Takes a list of validators and a list of mappers, which should correspond pairwise.
|
74 | *
|
75 | * The mapper of the first successful validator will be called.
|
76 | */
|
77 | function unionMapper(validators, mappers) {
|
78 | if (validators.length !== mappers.length) {
|
79 | throw Error('Not the same amount of validators and mappers passed to unionMapper()');
|
80 | }
|
81 | return (x) => {
|
82 | if (!canInspect(x)) {
|
83 | return x;
|
84 | }
|
85 | for (let i = 0; i < validators.length; i++) {
|
86 | if (validators[i](x).isSuccess) {
|
87 | return mappers[i](x);
|
88 | }
|
89 | }
|
90 | // Should not be possible because the union must have passed validation before this function
|
91 | // will be called, but catch it anyway.
|
92 | throw new TypeError('No validators matched in the union()');
|
93 | };
|
94 | }
|
95 | exports.unionMapper = unionMapper;
|
96 | // ----------------------------------------------------------------------
|
97 | // VALIDATORS
|
98 | //
|
99 | // These are used while checking that supplied property bags match the expected schema
|
100 | //
|
101 | // We have a couple of datatypes that model validation errors and collections of validation
|
102 | // errors (together forming a tree of errors so that we can trace validation errors through
|
103 | // an object graph), and validators.
|
104 | //
|
105 | // Validators are simply functions that take a value and return a validation results. Then
|
106 | // we have some combinators to turn primitive validators into more complex validators.
|
107 | //
|
108 | /**
|
109 | * Representation of validation results
|
110 | *
|
111 | * Models a tree of validation errors so that we have as much information as possible
|
112 | * about the failure that occurred.
|
113 | */
|
114 | class ValidationResult {
|
115 | constructor(errorMessage = '', results = new ValidationResults()) {
|
116 | this.errorMessage = errorMessage;
|
117 | this.results = results;
|
118 | try {
|
119 | jsiiDeprecationWarnings._aws_cdk_core_ValidationResults(results);
|
120 | }
|
121 | catch (error) {
|
122 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
123 | Error.captureStackTrace(error, ValidationResult);
|
124 | }
|
125 | throw error;
|
126 | }
|
127 | }
|
128 | get isSuccess() {
|
129 | return !this.errorMessage && this.results.isSuccess;
|
130 | }
|
131 | /**
|
132 | * Turn a failed validation into an exception
|
133 | */
|
134 | assertSuccess() {
|
135 | if (!this.isSuccess) {
|
136 | let message = this.errorTree();
|
137 | // The first letter will be lowercase, so uppercase it for a nicer error message
|
138 | message = message.slice(0, 1).toUpperCase() + message.slice(1);
|
139 | throw new CfnSynthesisError(message);
|
140 | }
|
141 | }
|
142 | /**
|
143 | * Return a string rendering of the tree of validation failures
|
144 | */
|
145 | errorTree() {
|
146 | const childMessages = this.results.errorTreeList();
|
147 | return this.errorMessage + (childMessages.length ? `\n ${childMessages.replace(/\n/g, '\n ')}` : '');
|
148 | }
|
149 | /**
|
150 | * Wrap this result with an error message, if it concerns an error
|
151 | */
|
152 | prefix(message) {
|
153 | if (this.isSuccess) {
|
154 | return this;
|
155 | }
|
156 | return new ValidationResult(`${message}: ${this.errorMessage}`, this.results);
|
157 | }
|
158 | }
|
159 | exports.ValidationResult = ValidationResult;
|
160 | _a = JSII_RTTI_SYMBOL_1;
|
161 | ValidationResult[_a] = { fqn: "@aws-cdk/core.ValidationResult", version: "1.204.0" };
|
162 | /**
|
163 | * A collection of validation results
|
164 | */
|
165 | class ValidationResults {
|
166 | constructor(results = []) {
|
167 | this.results = results;
|
168 | }
|
169 | collect(result) {
|
170 | try {
|
171 | jsiiDeprecationWarnings._aws_cdk_core_ValidationResult(result);
|
172 | }
|
173 | catch (error) {
|
174 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
175 | Error.captureStackTrace(error, this.collect);
|
176 | }
|
177 | throw error;
|
178 | }
|
179 | // Only collect failures
|
180 | if (!result.isSuccess) {
|
181 | this.results.push(result);
|
182 | }
|
183 | }
|
184 | get isSuccess() {
|
185 | return this.results.every(x => x.isSuccess);
|
186 | }
|
187 | errorTreeList() {
|
188 | return this.results.map(child => child.errorTree()).join('\n');
|
189 | }
|
190 | /**
|
191 | * Wrap up all validation results into a single tree node
|
192 | *
|
193 | * If there are failures in the collection, add a message, otherwise
|
194 | * return a success.
|
195 | */
|
196 | wrap(message) {
|
197 | if (this.isSuccess) {
|
198 | return exports.VALIDATION_SUCCESS;
|
199 | }
|
200 | return new ValidationResult(message, this);
|
201 | }
|
202 | }
|
203 | exports.ValidationResults = ValidationResults;
|
204 | _b = JSII_RTTI_SYMBOL_1;
|
205 | ValidationResults[_b] = { fqn: "@aws-cdk/core.ValidationResults", version: "1.204.0" };
|
206 | // Singleton object to save on allocations
|
207 | exports.VALIDATION_SUCCESS = new ValidationResult();
|
208 | /**
|
209 | * Return whether this object can be validated at all
|
210 | *
|
211 | * True unless it's undefined or a CloudFormation intrinsic
|
212 | */
|
213 | function canInspect(x) {
|
214 | // Note: using weak equality on purpose, we also want to catch undefined
|
215 | return (x != null && !isCloudFormationIntrinsic(x) && !isCloudFormationDynamicReference(x));
|
216 | }
|
217 | exports.canInspect = canInspect;
|
218 | // CloudFormation validators for primitive types
|
219 | function validateString(x) {
|
220 | if (canInspect(x) && typeof x !== 'string') {
|
221 | return new ValidationResult(`${JSON.stringify(x)} should be a string`);
|
222 | }
|
223 | return exports.VALIDATION_SUCCESS;
|
224 | }
|
225 | exports.validateString = validateString;
|
226 | function validateNumber(x) {
|
227 | if (canInspect(x) && typeof x !== 'number') {
|
228 | return new ValidationResult(`${JSON.stringify(x)} should be a number`);
|
229 | }
|
230 | return exports.VALIDATION_SUCCESS;
|
231 | }
|
232 | exports.validateNumber = validateNumber;
|
233 | function validateBoolean(x) {
|
234 | if (canInspect(x) && typeof x !== 'boolean') {
|
235 | return new ValidationResult(`${JSON.stringify(x)} should be a boolean`);
|
236 | }
|
237 | return exports.VALIDATION_SUCCESS;
|
238 | }
|
239 | exports.validateBoolean = validateBoolean;
|
240 | function validateDate(x) {
|
241 | if (canInspect(x) && !(x instanceof Date)) {
|
242 | return new ValidationResult(`${JSON.stringify(x)} should be a Date`);
|
243 | }
|
244 | if (x !== undefined && isNaN(x.getTime())) {
|
245 | return new ValidationResult('got an unparseable Date');
|
246 | }
|
247 | return exports.VALIDATION_SUCCESS;
|
248 | }
|
249 | exports.validateDate = validateDate;
|
250 | function validateObject(x) {
|
251 | if (canInspect(x) && typeof x !== 'object') {
|
252 | return new ValidationResult(`${JSON.stringify(x)} should be an 'object'`);
|
253 | }
|
254 | return exports.VALIDATION_SUCCESS;
|
255 | }
|
256 | exports.validateObject = validateObject;
|
257 | function validateCfnTag(x) {
|
258 | if (!canInspect(x)) {
|
259 | return exports.VALIDATION_SUCCESS;
|
260 | }
|
261 | if (x.key == null || x.value == null) {
|
262 | return new ValidationResult(`${JSON.stringify(x)} should have a 'key' and a 'value' property`);
|
263 | }
|
264 | return exports.VALIDATION_SUCCESS;
|
265 | }
|
266 | exports.validateCfnTag = validateCfnTag;
|
267 | /**
|
268 | * Return a list validator based on the given element validator
|
269 | */
|
270 | function listValidator(elementValidator) {
|
271 | return (x) => {
|
272 | if (!canInspect(x)) {
|
273 | return exports.VALIDATION_SUCCESS;
|
274 | }
|
275 | if (!x.forEach) {
|
276 | return new ValidationResult(`${JSON.stringify(x)} should be a list`);
|
277 | }
|
278 | for (let i = 0; i < x.length; i++) {
|
279 | const element = x[i];
|
280 | const result = elementValidator(element);
|
281 | if (!result.isSuccess) {
|
282 | return result.prefix(`element ${i}`);
|
283 | }
|
284 | }
|
285 | return exports.VALIDATION_SUCCESS;
|
286 | };
|
287 | }
|
288 | exports.listValidator = listValidator;
|
289 | /**
|
290 | * Return a hash validator based on the given element validator
|
291 | */
|
292 | function hashValidator(elementValidator) {
|
293 | return (x) => {
|
294 | if (!canInspect(x)) {
|
295 | return exports.VALIDATION_SUCCESS;
|
296 | }
|
297 | for (const key of Object.keys(x)) {
|
298 | const result = elementValidator(x[key]);
|
299 | if (!result.isSuccess) {
|
300 | return result.prefix(`element '${key}'`);
|
301 | }
|
302 | }
|
303 | return exports.VALIDATION_SUCCESS;
|
304 | };
|
305 | }
|
306 | exports.hashValidator = hashValidator;
|
307 | /**
|
308 | * Decorate a validator with a message clarifying the property the failure is for.
|
309 | */
|
310 | function propertyValidator(propName, validator) {
|
311 | return (x) => {
|
312 | return validator(x).prefix(propName);
|
313 | };
|
314 | }
|
315 | exports.propertyValidator = propertyValidator;
|
316 | /**
|
317 | * Return a validator that will fail if the passed property is not present
|
318 | *
|
319 | * Does not distinguish between the property actually not being present, vs being present but 'null'
|
320 | * or 'undefined' (courtesy of JavaScript), which is generally the behavior that we want.
|
321 | *
|
322 | * Empty strings are considered "present"--don't know if this agrees with how CloudFormation looks
|
323 | * at the world.
|
324 | */
|
325 | function requiredValidator(x) {
|
326 | if (x == null) {
|
327 | return new ValidationResult('required but missing');
|
328 | }
|
329 | return exports.VALIDATION_SUCCESS;
|
330 | }
|
331 | exports.requiredValidator = requiredValidator;
|
332 | /**
|
333 | * Require a property from a property bag.
|
334 | *
|
335 | * @param props the property bag from which a property is required.
|
336 | * @param name the name of the required property.
|
337 | * @param typeName the name of the construct type that requires the property
|
338 | *
|
339 | * @returns the value of ``props[name]``
|
340 | *
|
341 | * @throws if the property ``name`` is not present in ``props``.
|
342 | */
|
343 | function requireProperty(props, name, context) {
|
344 | const value = props[name];
|
345 | if (value == null) {
|
346 | throw new Error(`${context.toString()} is missing required property: ${name}`);
|
347 | }
|
348 | // Possibly add type-checking here...
|
349 | return value;
|
350 | }
|
351 | exports.requireProperty = requireProperty;
|
352 | /**
|
353 | * Validates if any of the given validators matches
|
354 | *
|
355 | * We add either/or words to the front of the error mesages so that they read
|
356 | * more nicely. Example:
|
357 | *
|
358 | * Properties not correct for 'FunctionProps'
|
359 | * codeUri: not one of the possible types
|
360 | * either: properties not correct for 'S3LocationProperty'
|
361 | * bucket: required but missing
|
362 | * key: required but missing
|
363 | * version: required but missing
|
364 | * or: '3' should be a 'string'
|
365 | *
|
366 | */
|
367 | function unionValidator(...validators) {
|
368 | return (x) => {
|
369 | const results = new ValidationResults();
|
370 | let eitherOr = 'either';
|
371 | for (const validator of validators) {
|
372 | const result = validator(x);
|
373 | if (result.isSuccess) {
|
374 | return result;
|
375 | }
|
376 | results.collect(result.prefix(eitherOr));
|
377 | eitherOr = 'or';
|
378 | }
|
379 | return results.wrap('not one of the possible types');
|
380 | };
|
381 | }
|
382 | exports.unionValidator = unionValidator;
|
383 | /**
|
384 | * Return whether the indicated value represents a CloudFormation intrinsic.
|
385 | *
|
386 | * CloudFormation intrinsics are modeled as objects with a single key, which
|
387 | * look like: { "Fn::GetAtt": [...] } or similar.
|
388 | */
|
389 | function isCloudFormationIntrinsic(x) {
|
390 | if (!(typeof x === 'object')) {
|
391 | return false;
|
392 | }
|
393 | const keys = Object.keys(x);
|
394 | if (keys.length !== 1) {
|
395 | return false;
|
396 | }
|
397 | return keys[0] === 'Ref' || keys[0].slice(0, 4) === 'Fn::';
|
398 | }
|
399 | /**
|
400 | * Check whether the indicated value is a CloudFormation dynamic reference.
|
401 | *
|
402 | * CloudFormation dynamic references take the format: '{{resolve:service-name:reference-key}}'
|
403 | */
|
404 | function isCloudFormationDynamicReference(x) {
|
405 | return (typeof x === 'string' && x.startsWith('{{resolve:') && x.endsWith('}}'));
|
406 | }
|
407 | // Cannot be public because JSII gets confused about es5.d.ts
|
408 | class CfnSynthesisError extends Error {
|
409 | constructor() {
|
410 | super(...arguments);
|
411 | this.type = 'CfnSynthesisError';
|
412 | }
|
413 | }
|
414 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVudGltZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJ1bnRpbWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBWUEsU0FBUyxRQUFRLENBQUMsQ0FBTTtJQUN0QixPQUFPLENBQUMsQ0FBQztBQUNYLENBQUM7QUFFWSxRQUFBLHNCQUFzQixHQUFXLFFBQVEsQ0FBQztBQUMxQyxRQUFBLHVCQUF1QixHQUFXLFFBQVEsQ0FBQztBQUMzQyxRQUFBLHNCQUFzQixHQUFXLFFBQVEsQ0FBQztBQUMxQyxRQUFBLHNCQUFzQixHQUFXLFFBQVEsQ0FBQztBQUV2RDs7Ozs7O0dBTUc7QUFDSCxTQUFnQixvQkFBb0IsQ0FBQyxDQUFRO0lBQzNDLElBQUksQ0FBQyxDQUFDLEVBQUU7UUFDTixPQUFPLFNBQVMsQ0FBQztLQUNsQjtJQUVELG1DQUFtQztJQUNuQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLGNBQWMsRUFBRSxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxFQUFFLENBQUM7QUFDaEssQ0FBQztBQVBELG9EQU9DO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLEdBQUcsQ0FBQyxDQUFTO0lBQ3BCLElBQUksQ0FBQyxHQUFHLEVBQUUsRUFBRTtRQUNWLE9BQU8sR0FBRyxHQUFHLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztLQUMzQjtJQUNELE9BQU8sQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO0FBQ3RCLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLHNCQUFzQixDQUFDLENBQU07SUFDM0MsT0FBTztRQUNMLEdBQUcs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O0FBQzdELENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxnQ0FBZ0MsQ0FBQyxDQUFNO0lBQzlDLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxRQUFRLElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7QUFDbkYsQ0FBQztBQUVELDZEQUE2RDtBQUM3RCxNQUFNLGlCQUFrQixTQUFRLEtBQUs7SUFBckM7O1FBQ2tCLFNBQUksR0FBRyxtQkFBbUIsQ0FBQztJQUM3QyxDQUFDO0NBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICcuL2NvbnN0cnVjdC1jb21wYXQnO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBQUk9QRVJUWSBNQVBQRVJTXG4vL1xuLy8gVGhlc2UgYXJlIHVzZWQgd2hpbGUgY29udmVydGluZyBnZW5lcmF0ZWQgY2xhc3Nlcy9wcm9wZXJ0eSBiYWdzIHRvIENsb3VkRm9ybWF0aW9uIHByb3BlcnR5IG9iamVjdHNcbi8vXG4vLyBXZSB1c2UgaWRlbnRpdHkgbWFwcGVycyBmb3IgdGhlIHByaW1pdGl2ZSB0eXBlcy4gVGhlc2UgZG9uJ3QgZG8gYW55dGhpbmcgYnV0IGFyZSB0aGVyZSB0byBtYWtlIHRoZSBjb2RlXG4vLyBnZW5lcmF0aW9uIHdvcmsgb3V0IG5pY2VseSAoc28gdGhlIGNvZGUgZ2VuZXJhdG9yIGRvZXNuJ3QgbmVlZCB0byBlbWl0IGRpZmZlcmVudCBjb2RlIGZvciBwcmltaXRpdmVcbi8vIHZzLiBjb21wbGV4IHR5cGVzKS5cbmV4cG9ydCB0eXBlIE1hcHBlciA9ICh4OiBhbnkpID0+IGFueTtcblxuZnVuY3Rpb24gaWRlbnRpdHkoeDogYW55KSB7XG4gIHJldHVybiB4O1xufVxuXG5leHBvcnQgY29uc3Qgc3RyaW5nVG9DbG91ZEZvcm1hdGlvbjogTWFwcGVyID0gaWRlbnRpdHk7XG5leHBvcnQgY29uc3QgYm9vbGVhblRvQ2xvdWRGb3JtYXRpb246IE1hcHBlciA9IGlkZW50aXR5O1xuZXhwb3J0IGNvbnN0IG9iamVjdFRvQ2xvdWRGb3JtYXRpb246IE1hcHBlciA9IGlkZW50aXR5O1xuZXhwb3J0IGNvbnN0IG51bWJlclRvQ2xvdWRGb3JtYXRpb246IE1hcHBlciA9IGlkZW50aXR5O1xuXG4vKipcbiAqIFRoZSBkYXRlIG5lZWRzIHRvIGJlIGZvcm1hdHRlZCBhcyBhbiBJU08gZGF0ZSBpbiBVVENcbiAqXG4gKiBTb21lIHVzYWdlIHNpdGVzIHJlcXVpcmUgYSBkYXRlLCBzb21lIHJlcXVpcmUgYSB0aW1lc3RhbXAuIFdlJ2xsXG4gKiBhbHdheXMgb3V0cHV0IGEgdGltZXN0YW1wIGFuZCBob3BlIHRoZSBwYXJzZXIgb24gdGhlIG90aGVyIGVuZFxuICogaXMgc21hcnQgZW5vdWdoIHRvIGlnbm9yZSB0aGUgdGltZSBwYXJ0Li4uICg/KVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGF0ZVRvQ2xvdWRGb3JtYXRpb24oeD86IERhdGUpOiBhbnkge1xuICBpZiAoIXgpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbiAgcmV0dXJuIGAke3guZ2V0VVRDRnVsbFllYXIoKX0tJHtwYWQoeC5nZXRVVENNb250aCgpICsgMSl9LSR7cGFkKHguZ2V0VVRDRGF0ZSgpKX1UJHtwYWQoeC5nZXRVVENIb3VycygpKX06JHtwYWQoeC5nZXRVVENNaW51dGVzKCkpfToke3BhZCh4LmdldFVUQ1NlY29uZHMoKSl9YDtcbn1cblxuLyoqXG4gKiBQYWQgYSBudW1iZXIgdG8gMiBkZWNpbWFsIHBsYWNlc1xuICovXG5mdW5jdGlvbiBwYWQoeDogbnVtYmVyKSB7XG4gIGlmICh4IDwgMTApIHtcbiAgICByZXR1cm4gJzAnICsgeC50b1N0cmluZygpO1xuICB9XG4gIHJldHVybiB4LnRvU3RyaW5nKCk7XG59XG5cbi8qKlxuICogVHVybiBhIHRhZyBvYmplY3QgaW50byB0aGUgcHJvcGVyIENsb3VkRm9ybWF0aW9uIHJlcHJlc2VudGF0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjZm5UYWdUb0Nsb3VkRm9ybWF0aW9uKHg6IGFueSk6IGFueSB7XG4gIHJldHVybiB7XG4gICAgS2V5OiB4LmtleSxcbiAgICBWYWx1ZTogeC52YWx1ZSxcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpc3RNYXBwZXIoZWxlbWVudE1hcHBlcjogTWFwcGVyKTogTWFwcGVyIHtcbiAgcmV0dXJuICh4OiBhbnkpID0+IHtcbiAgICBpZiAoIWNhbkluc3BlY3QoeCkpIHsgcmV0dXJuIHg7IH1cbiAgICByZXR1cm4geC5tYXAoZWxlbWVudE1hcHBlcik7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNoTWFwcGVyKGVsZW1lbnRNYXBwZXI6IE1hcHBlcik6IE1hcHBlciB7XG4gIHJldHVybiAoeDogYW55KSA9PiB7XG4gICAgaWYgKCFjYW5JbnNwZWN0KHgpKSB7IHJldHVybiB4OyB9XG5cbiAgICBjb25zdCByZXQ6IGFueSA9IHt9O1xuXG4gICAgT2JqZWN0LmtleXMoeCkuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICByZXRba2V5XSA9IGVsZW1lbnRNYXBwZXIoeFtrZXldKTtcbiAgICB9KTtcblxuICAgIHJldHVybiByZXQ7XG4gIH07XG59XG5cbi8qKlxuICogUmV0dXJuIGEgdW5pb24gbWFwcGVyXG4gKlxuICogVGFrZXMgYSBsaXN0IG9mIHZhbGlkYXRvcnMgYW5kIGEgbGlzdCBvZiBtYXBwZXJzLCB3aGljaCBzaG91bGQgY29ycmVzcG9uZCBwYWlyd2lzZS5cbiAqXG4gKiBUaGUgbWFwcGVyIG9mIHRoZSBmaXJzdCBzdWNjZXNzZnVsIHZhbGlkYXRvciB3aWxsIGJlIGNhbGxlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVuaW9uTWFwcGVyKHZhbGlkYXRvcnM6IFZhbGlkYXRvcltdLCBtYXBwZXJzOiBNYXBwZXJbXSk6IE1hcHBlciB7XG4gIGlmICh2YWxpZGF0b3JzLmxlbmd0aCAhPT0gbWFwcGVycy5sZW5ndGgpIHtcbiAgICB0aHJvdyBFcnJvcignTm90IHRoZSBzYW1lIGFtb3VudCBvZiB2YWxpZGF0b3JzIGFuZCBtYXBwZXJzIHBhc3NlZCB0byB1bmlvbk1hcHBlcigpJyk7XG4gIH1cblxuICByZXR1cm4gKHg6IGFueSkgPT4ge1xuICAgIGlmICghY2FuSW5zcGVjdCh4KSkgeyByZXR1cm4geDsgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWxpZGF0b3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodmFsaWRhdG9yc1tpXSh4KS5pc1N1Y2Nlc3MpIHtcbiAgICAgICAgcmV0dXJuIG1hcHBlcnNbaV0oeCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gU2hvdWxkIG5vdCBiZSBwb3NzaWJsZSBiZWNhdXNlIHRoZSB1bmlvbiBtdXN0IGhhdmUgcGFzc2VkIHZhbGlkYXRpb24gYmVmb3JlIHRoaXMgZnVuY3Rpb25cbiAgICAvLyB3aWxsIGJlIGNhbGxlZCwgYnV0IGNhdGNoIGl0IGFueXdheS5cbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdObyB2YWxpZGF0b3JzIG1hdGNoZWQgaW4gdGhlIHVuaW9uKCknKTtcbiAgfTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gVkFMSURBVE9SU1xuLy9cbi8vIFRoZXNlIGFyZSB1c2VkIHdoaWxlIGNoZWNraW5nIHRoYXQgc3VwcGxpZWQgcHJvcGVydHkgYmFncyBtYXRjaCB0aGUgZXhwZWN0ZWQgc2NoZW1hXG4vL1xuLy8gV2UgaGF2ZSBhIGNvdXBsZSBvZiBkYXRhdHlwZXMgdGhhdCBtb2RlbCB2YWxpZGF0aW9uIGVycm9ycyBhbmQgY29sbGVjdGlvbnMgb2YgdmFsaWRhdGlvblxuLy8gZXJyb3JzICh0b2dldGhlciBmb3JtaW5nIGEgdHJlZSBvZiBlcnJvcnMgc28gdGhhdCB3ZSBjYW4gdHJhY2UgdmFsaWRhdGlvbiBlcnJvcnMgdGhyb3VnaFxuLy8gYW4gb2JqZWN0IGdyYXBoKSwgYW5kIHZhbGlkYXRvcnMuXG4vL1xuLy8gVmFsaWRhdG9ycyBhcmUgc2ltcGx5IGZ1bmN0aW9ucyB0aGF0IHRha2UgYSB2YWx1ZSBhbmQgcmV0dXJuIGEgdmFsaWRhdGlvbiByZXN1bHRzLiBUaGVuXG4vLyB3ZSBoYXZlIHNvbWUgY29tYmluYXRvcnMgdG8gdHVybiBwcmltaXRpdmUgdmFsaWRhdG9ycyBpbnRvIG1vcmUgY29tcGxleCB2YWxpZGF0b3JzLlxuLy9cblxuLyoqXG4gKiBSZXByZXNlbnRhdGlvbiBvZiB2YWxpZGF0aW9uIHJlc3VsdHNcbiAqXG4gKiBNb2RlbHMgYSB0cmVlIG9mIHZhbGlkYXRpb24gZXJyb3JzIHNvIHRoYXQgd2UgaGF2ZSBhcyBtdWNoIGluZm9ybWF0aW9uIGFzIHBvc3NpYmxlXG4gKiBhYm91dCB0aGUgZmFpbHVyZSB0aGF0IG9jY3VycmVkLlxuICovXG5leHBvcnQgY2xhc3MgVmFsaWRhdGlvblJlc3VsdCB7XG4gIGNvbnN0cnVjdG9yKHJlYWRvbmx5IGVycm9yTWVzc2FnZTogc3RyaW5nID0gJycsIHJlYWRvbmx5IHJlc3VsdHM6IFZhbGlkYXRpb25SZXN1bHRzID0gbmV3IFZhbGlkYXRpb25SZXN1bHRzKCkpIHtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgaXNTdWNjZXNzKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhdGhpcy5lcnJvck1lc3NhZ2UgJiYgdGhpcy5yZXN1bHRzLmlzU3VjY2VzcztcbiAgfVxuXG4gIC8qKlxuICAgKiBUdXJuIGEgZmFpbGVkIHZhbGlkYXRpb24gaW50byBhbiBleGNlcHRpb25cbiAgICovXG4gIHB1YmxpYyBhc3NlcnRTdWNjZXNzKCkge1xuICAgIGlmICghdGhpcy5pc1N1Y2Nlc3MpIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdGhpcy5lcnJvclRyZWUoKTtcbiAgICAgIC8vIFRoZSBmaXJzdCBsZXR0ZXIgd2lsbCBiZSBsb3dlcmNhc2UsIHNvIHVwcGVyY2FzZSBpdCBmb3IgYSBuaWNlciBlcnJvciBtZXNzYWdlXG4gICAgICBtZXNzYWdlID0gbWVzc2FnZS5zbGljZSgwLCAxKS50b1VwcGVyQ2FzZSgpICsgbWVzc2FnZS5zbGljZSgxKTtcbiAgICAgIHRocm93IG5ldyBDZm5TeW50aGVzaXNFcnJvcihtZXNzYWdlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGEgc3RyaW5nIHJlbmRlcmluZyBvZiB0aGUgdHJlZSBvZiB2YWxpZGF0aW9uIGZhaWx1cmVzXG4gICAqL1xuICBwdWJsaWMgZXJyb3JUcmVlKCk6IHN0cmluZyB7XG4gICAgY29uc3QgY2hpbGRNZXNzYWdlcyA9IHRoaXMucmVzdWx0cy5lcnJvclRyZWVMaXN0KCk7XG4gICAgcmV0dXJuIHRoaXMuZXJyb3JNZXNzYWdlICsgKGNoaWxkTWVzc2FnZXMubGVuZ3RoID8gYFxcbiAgJHtjaGlsZE1lc3NhZ2VzLnJlcGxhY2UoL1xcbi9nLCAnXFxuICAnKX1gIDogJycpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdyYXAgdGhpcyByZXN1bHQgd2l0aCBhbiBlcnJvciBtZXNzYWdlLCBpZiBpdCBjb25jZXJucyBhbiBlcnJvclxuICAgKi9cbiAgcHVibGljIHByZWZpeChtZXNzYWdlOiBzdHJpbmcpOiBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgICBpZiAodGhpcy5pc1N1Y2Nlc3MpIHsgcmV0dXJuIHRoaXM7IH1cbiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25SZXN1bHQoYCR7bWVzc2FnZX06ICR7dGhpcy5lcnJvck1lc3NhZ2V9YCwgdGhpcy5yZXN1bHRzKTtcbiAgfVxufVxuXG4vKipcbiAqIEEgY29sbGVjdGlvbiBvZiB2YWxpZGF0aW9uIHJlc3VsdHNcbiAqL1xuZXhwb3J0IGNsYXNzIFZhbGlkYXRpb25SZXN1bHRzIHtcbiAgY29uc3RydWN0b3IocHVibGljIHJlc3VsdHM6IFZhbGlkYXRpb25SZXN1bHRbXSA9IFtdKSB7XG4gIH1cblxuICBwdWJsaWMgY29sbGVjdChyZXN1bHQ6IFZhbGlkYXRpb25SZXN1bHQpIHtcbiAgICAvLyBPbmx5IGNvbGxlY3QgZmFpbHVyZXNcbiAgICBpZiAoIXJlc3VsdC5pc1N1Y2Nlc3MpIHtcbiAgICAgIHRoaXMucmVzdWx0cy5wdXNoKHJlc3VsdCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGdldCBpc1N1Y2Nlc3MoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucmVzdWx0cy5ldmVyeSh4ID0+IHguaXNTdWNjZXNzKTtcbiAgfVxuXG4gIHB1YmxpYyBlcnJvclRyZWVMaXN0KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMucmVzdWx0cy5tYXAoY2hpbGQgPT4gY2hpbGQuZXJyb3JUcmVlKCkpLmpvaW4oJ1xcbicpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdyYXAgdXAgYWxsIHZhbGlkYXRpb24gcmVzdWx0cyBpbnRvIGEgc2luZ2xlIHRyZWUgbm9kZVxuICAgKlxuICAgKiBJZiB0aGVyZSBhcmUgZmFpbHVyZXMgaW4gdGhlIGNvbGxlY3Rpb24sIGFkZCBhIG1lc3NhZ2UsIG90aGVyd2lzZVxuICAgKiByZXR1cm4gYSBzdWNjZXNzLlxuICAgKi9cbiAgcHVibGljIHdyYXAobWVzc2FnZTogc3RyaW5nKTogVmFsaWRhdGlvblJlc3VsdCB7XG4gICAgaWYgKHRoaXMuaXNTdWNjZXNzKSB7wqByZXR1cm4gVkFMSURBVElPTl9TVUNDRVNTOyB9XG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0aW9uUmVzdWx0KG1lc3NhZ2UsIHRoaXMpO1xuICB9XG59XG5cbi8vIFNpbmdsZXRvbiBvYmplY3QgdG8gc2F2ZSBvbiBhbGxvY2F0aW9uc1xuZXhwb3J0IGNvbnN0IFZBTElEQVRJT05fU1VDQ0VTUyA9IG5ldyBWYWxpZGF0aW9uUmVzdWx0KCk7XG5cbmV4cG9ydCB0eXBlIFZhbGlkYXRvciA9ICh4OiBhbnkpID0+IFZhbGlkYXRpb25SZXN1bHQ7XG5cbi8qKlxuICogUmV0dXJuIHdoZXRoZXIgdGhpcyBvYmplY3QgY2FuIGJlIHZhbGlkYXRlZCBhdCBhbGxcbiAqXG4gKiBUcnVlIHVubGVzcyBpdCdzIHVuZGVmaW5lZCBvciBhIENsb3VkRm9ybWF0aW9uIGludHJpbnNpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gY2FuSW5zcGVjdCh4OiBhbnkpIHtcbiAgLy8gTm90ZTogdXNpbmcgd2VhayBlcXVhbGl0eSBvbiBwdXJwb3NlLCB3ZSBhbHNvIHdhbnQgdG8gY2F0Y2ggdW5kZWZpbmVkXG4gIHJldHVybiAoeCAhPSBudWxsICYmICFpc0Nsb3VkRm9ybWF0aW9uSW50cmluc2ljKHgpICYmICFpc0Nsb3VkRm9ybWF0aW9uRHluYW1pY1JlZmVyZW5jZSh4KSk7XG59XG5cbi8vIENsb3VkRm9ybWF0aW9uIHZhbGlkYXRvcnMgZm9yIHByaW1pdGl2ZSB0eXBlc1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlU3RyaW5nKHg6IGFueSk6IFZhbGlkYXRpb25SZXN1bHQge1xuICBpZiAoY2FuSW5zcGVjdCh4KSAmJiB0eXBlb2YgeCAhPT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25SZXN1bHQoYCR7SlNPTi5zdHJpbmdpZnkoeCl9IHNob3VsZCBiZSBhIHN0cmluZ2ApO1xuICB9XG4gIHJldHVybiBWQUxJREFUSU9OX1NVQ0NFU1M7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZU51bWJlcih4OiBhbnkpOiBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgaWYgKGNhbkluc3BlY3QoeCkgJiYgdHlwZW9mIHggIT09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0aW9uUmVzdWx0KGAke0pTT04uc3RyaW5naWZ5KHgpfSBzaG91bGQgYmUgYSBudW1iZXJgKTtcbiAgfVxuICByZXR1cm4gVkFMSURBVElPTl9TVUNDRVNTO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVCb29sZWFuKHg6IGFueSk6IFZhbGlkYXRpb25SZXN1bHQge1xuICBpZiAoY2FuSW5zcGVjdCh4KSAmJiB0eXBlb2YgeCAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0aW9uUmVzdWx0KGAke0pTT04uc3RyaW5naWZ5KHgpfSBzaG91bGQgYmUgYSBib29sZWFuYCk7XG4gIH1cbiAgcmV0dXJuIFZBTElEQVRJT05fU1VDQ0VTUztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlRGF0ZSh4OiBhbnkpOiBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgaWYgKGNhbkluc3BlY3QoeCkgJiYgISh4IGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25SZXN1bHQoYCR7SlNPTi5zdHJpbmdpZnkoeCl9IHNob3VsZCBiZSBhIERhdGVgKTtcbiAgfVxuXG4gIGlmICh4ICE9PSB1bmRlZmluZWQgJiYgaXNOYU4oeC5nZXRUaW1lKCkpKSB7XG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0aW9uUmVzdWx0KCdnb3QgYW4gdW5wYXJzZWFibGUgRGF0ZScpO1xuICB9XG5cbiAgcmV0dXJuIFZBTElEQVRJT05fU1VDQ0VTUztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlT2JqZWN0KHg6IGFueSk6IFZhbGlkYXRpb25SZXN1bHQge1xuICBpZiAoY2FuSW5zcGVjdCh4KSAmJiB0eXBlb2YgeCAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25SZXN1bHQoYCR7SlNPTi5zdHJpbmdpZnkoeCl9IHNob3VsZCBiZSBhbiAnb2JqZWN0J2ApO1xuICB9XG4gIHJldHVybiBWQUxJREFUSU9OX1NVQ0NFU1M7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUNmblRhZyh4OiBhbnkpOiBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgaWYgKCFjYW5JbnNwZWN0KHgpKSB7IHJldHVybiBWQUxJREFUSU9OX1NVQ0NFU1M7IH1cblxuICBpZiAoeC5rZXkgPT0gbnVsbCB8fCB4LnZhbHVlID09IG51bGwpIHtcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25SZXN1bHQoYCR7SlNPTi5zdHJpbmdpZnkoeCl9IHNob3VsZCBoYXZlIGEgJ2tleScgYW5kIGEgJ3ZhbHVlJyBwcm9wZXJ0eWApO1xuICB9XG5cbiAgcmV0dXJuIFZBTElEQVRJT05fU1VDQ0VTUztcbn1cblxuLyoqXG4gKiBSZXR1cm4gYSBsaXN0IHZhbGlkYXRvciBiYXNlZCBvbiB0aGUgZ2l2ZW4gZWxlbWVudCB2YWxpZGF0b3JcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxpc3RWYWxpZGF0b3IoZWxlbWVudFZhbGlkYXRvcjogVmFsaWRhdG9yKTogVmFsaWRhdG9yIHtcbiAgcmV0dXJuICh4OiBhbnkpID0+IHtcbiAgICBpZiAoIWNhbkluc3BlY3QoeCkpIHsgcmV0dXJuIFZBTElEQVRJT05fU1VDQ0VTUzsgfVxuXG4gICAgaWYgKCF4LmZvckVhY2gpIHtcbiAgICAgIHJldHVybiBuZXcgVmFsaWRhdGlvblJlc3VsdChgJHtKU09OLnN0cmluZ2lmeSh4KX0gc2hvdWxkIGJlIGEgbGlzdGApO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgeC5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgZWxlbWVudCA9IHhbaV07XG4gICAgICBjb25zdCByZXN1bHQgPSBlbGVtZW50VmFsaWRhdG9yKGVsZW1lbnQpO1xuICAgICAgaWYgKCFyZXN1bHQuaXNTdWNjZXNzKSB7IHJldHVybiByZXN1bHQucHJlZml4KGBlbGVtZW50ICR7aX1gKTsgfVxuICAgIH1cblxuICAgIHJldHVybiBWQUxJREFUSU9OX1NVQ0NFU1M7XG4gIH07XG59XG5cbi8qKlxuICogUmV0dXJuIGEgaGFzaCB2YWxpZGF0b3IgYmFzZWQgb24gdGhlIGdpdmVuIGVsZW1lbnQgdmFsaWRhdG9yXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNoVmFsaWRhdG9yKGVsZW1lbnRWYWxpZGF0b3I6IFZhbGlkYXRvcik6IFZhbGlkYXRvciB7XG4gIHJldHVybiAoeDogYW55KSA9PiB7XG4gICAgaWYgKCFjYW5JbnNwZWN0KHgpKSB7IHJldHVybiBWQUxJREFUSU9OX1NVQ0NFU1M7IH1cblxuICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHgpKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBlbGVtZW50VmFsaWRhdG9yKHhba2V5XSk7XG4gICAgICBpZiAoIXJlc3VsdC5pc1N1Y2Nlc3MpIHsgcmV0dXJuIHJlc3VsdC5wcmVmaXgoYGVsZW1lbnQgJyR7a2V5fSdgKTsgfVxuICAgIH1cblxuICAgIHJldHVybiBWQUxJREFUSU9OX1NVQ0NFU1M7XG4gIH07XG59XG5cbi8qKlxuICogRGVjb3JhdGUgYSB2YWxpZGF0b3Igd2l0aCBhIG1lc3NhZ2UgY2xhcmlmeWluZyB0aGUgcHJvcGVydHkgdGhlIGZhaWx1cmUgaXMgZm9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvcGVydHlWYWxpZGF0b3IocHJvcE5hbWU6IHN0cmluZywgdmFsaWRhdG9yOiBWYWxpZGF0b3IpOiBWYWxpZGF0b3Ige1xuICByZXR1cm4gKHg6IGFueSkgPT4ge1xuICAgIHJldHVybiB2YWxpZGF0b3IoeCkucHJlZml4KHByb3BOYW1lKTtcbiAgfTtcbn1cblxuLyoqXG4gKiBSZXR1cm4gYSB2YWxpZGF0b3IgdGhhdCB3aWxsIGZhaWwgaWYgdGhlIHBhc3NlZCBwcm9wZXJ0eSBpcyBub3QgcHJlc2VudFxuICpcbiAqIERvZXMgbm90IGRpc3Rpbmd1aXNoIGJldHdlZW4gdGhlIHByb3BlcnR5IGFjdHVhbGx5IG5vdCBiZWluZyBwcmVzZW50LCB2cyBiZWluZyBwcmVzZW50IGJ1dCAnbnVsbCdcbiAqIG9yICd1bmRlZmluZWQnIChjb3VydGVzeSBvZiBKYXZhU2NyaXB0KSwgd2hpY2ggaXMgZ2VuZXJhbGx5IHRoZSBiZWhhdmlvciB0aGF0IHdlIHdhbnQuXG4gKlxuICogRW1wdHkgc3RyaW5ncyBhcmUgY29uc2lkZXJlZCBcInByZXNlbnRcIi0tZG9uJ3Qga25vdyBpZiB0aGlzIGFncmVlcyB3aXRoIGhvdyBDbG91ZEZvcm1hdGlvbiBsb29rc1xuICogYXQgdGhlIHdvcmxkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVxdWlyZWRWYWxpZGF0b3IoeDogYW55KSB7XG4gIGlmICh4ID09IG51bGwpIHtcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25SZXN1bHQoJ3JlcXVpcmVkIGJ1dCBtaXNzaW5nJyk7XG4gIH1cbiAgcmV0dXJuIFZBTElEQVRJT05fU1VDQ0VTUztcbn1cblxuLyoqXG4gKiBSZXF1aXJlIGEgcHJvcGVydHkgZnJvbSBhIHByb3BlcnR5IGJhZy5cbiAqXG4gKiBAcGFyYW0gcHJvcHMgIHRoZSBwcm9wZXJ0eSBiYWcgZnJvbSB3aGljaCBhIHByb3BlcnR5IGlzIHJlcXVpcmVkLlxuICogQHBhcmFtIG5hbWUgICB0aGUgbmFtZSBvZiB0aGUgcmVxdWlyZWQgcHJvcGVydHkuXG4gKiBAcGFyYW0gdHlwZU5hbWUgdGhlIG5hbWUgb2YgdGhlIGNvbnN0cnVjdCB0eXBlIHRoYXQgcmVxdWlyZXMgdGhlIHByb3BlcnR5XG4gKlxuICogQHJldHVybnMgdGhlIHZhbHVlIG9mIGBgcHJvcHNbbmFtZV1gYFxuICpcbiAqIEB0aHJvd3MgaWYgdGhlIHByb3BlcnR5IGBgbmFtZWBgIGlzIG5vdCBwcmVzZW50IGluIGBgcHJvcHNgYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcXVpcmVQcm9wZXJ0eShwcm9wczogeyBbbmFtZTogc3RyaW5nXTogYW55IH0sIG5hbWU6IHN0cmluZywgY29udGV4dDogQ29uc3RydWN0KTogYW55IHtcbiAgY29uc3QgdmFsdWUgPSBwcm9wc1tuYW1lXTtcbiAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29udGV4dC50b1N0cmluZygpfSBpcyBtaXNzaW5nIHJlcXVpcmVkIHByb3BlcnR5OiAke25hbWV9YCk7XG4gIH1cbiAgLy8gUG9zc2libHkgYWRkIHR5cGUtY2hlY2tpbmcgaGVyZS4uLlxuICByZXR1cm4gdmFsdWU7XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIGlmIGFueSBvZiB0aGUgZ2l2ZW4gdmFsaWRhdG9ycyBtYXRjaGVzXG4gKlxuICogV2UgYWRkIGVpdGhlci9vciB3b3JkcyB0byB0aGUgZnJvbnQgb2YgdGhlIGVycm9yIG1lc2FnZXMgc28gdGhhdCB0aGV5IHJlYWRcbiAqIG1vcmUgbmljZWx5LiBFeGFtcGxlOlxuICpcbiAqICAgUHJvcGVydGllcyBub3QgY29ycmVjdCBmb3IgJ0Z1bmN0aW9uUHJvcHMnXG4gKiAgICAgY29kZVVyaTogbm90IG9uZSBvZiB0aGUgcG9zc2libGUgdHlwZXNcbiAqICAgICAgIGVpdGhlcjogcHJvcGVydGllcyBub3QgY29ycmVjdCBmb3IgJ1MzTG9jYXRpb25Qcm9wZXJ0eSdcbiAqICAgICAgICAgYnVja2V0OiByZXF1aXJlZCBidXQgbWlzc2luZ1xuICogICAgICAgICBrZXk6IHJlcXVpcmVkIGJ1dCBtaXNzaW5nXG4gKiAgICAgICAgIHZlcnNpb246IHJlcXVpcmVkIGJ1dCBtaXNzaW5nXG4gKiAgICAgICBvcjogJzMnIHNob3VsZCBiZSBhICdzdHJpbmcnXG4gKlxuICovXG5leHBvcnQgZnVuY3Rpb24gdW5pb25WYWxpZGF0b3IoLi4udmFsaWRhdG9yczogVmFsaWRhdG9yW10pOiBWYWxpZGF0b3Ige1xuICByZXR1cm4gKHg6IGFueSkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdHMgPSBuZXcgVmFsaWRhdGlvblJlc3VsdHMoKTtcbiAgICBsZXQgZWl0aGVyT3IgPSAnZWl0aGVyJztcblxuICAgIGZvciAoY29uc3QgdmFsaWRhdG9yIG9mIHZhbGlkYXRvcnMpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHZhbGlkYXRvcih4KTtcbiAgICAgIGlmIChyZXN1bHQuaXNTdWNjZXNzKSB7IHJldHVybiByZXN1bHQ7IH1cbiAgICAgIHJlc3VsdHMuY29sbGVjdChyZXN1bHQucHJlZml4KGVpdGhlck9yKSk7XG4gICAgICBlaXRoZXJPciA9ICdvcic7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHRzLndyYXAoJ25vdCBvbmUgb2YgdGhlIHBvc3NpYmxlIHR5cGVzJyk7XG4gIH07XG59XG5cbi8qKlxuICogUmV0dXJuIHdoZXRoZXIgdGhlIGluZGljYXRlZCB2YWx1ZSByZXByZXNlbnRzIGEgQ2xvdWRGb3JtYXRpb24gaW50cmluc2ljLlxuICpcbiAqIENsb3VkRm9ybWF0aW9uIGludHJpbnNpY3MgYXJlIG1vZGVsZWQgYXMgb2JqZWN0cyB3aXRoIGEgc2luZ2xlIGtleSwgd2hpY2hcbiAqIGxvb2sgbGlrZTogeyBcIkZuOjpHZXRBdHRcIjogWy4uLl0gfSBvciBzaW1pbGFyLlxuICovXG5mdW5jdGlvbiBpc0Nsb3VkRm9ybWF0aW9uSW50cmluc2ljKHg6IGFueSkge1xuICBpZiAoISh0eXBlb2YgeCA9PT0gJ29iamVjdCcpKSB7IHJldHVybiBmYWxzZTsgfVxuICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoeCk7XG4gIGlmIChrZXlzLmxlbmd0aCAhPT0gMSkgeyByZXR1cm4gZmFsc2U7IH1cblxuICByZXR1cm4ga2V5c1swXSA9PT0gJ1JlZicgfHwga2V5c1swXS5zbGljZSgwLCA0KSA9PT0gJ0ZuOjonO1xufVxuXG4vKipcbiAqIENoZWNrIHdoZXRoZXIgdGhlIGluZGljYXRlZCB2YWx1ZSBpcyBhIENsb3VkRm9ybWF0aW9uIGR5bmFtaWMgcmVmZXJlbmNlLlxuICpcbiAqIENsb3VkRm9ybWF0aW9uIGR5bmFtaWMgcmVmZXJlbmNlcyB0YWtlIHRoZSBmb3JtYXQ6ICd7e3Jlc29sdmU6c2VydmljZS1uYW1lOnJlZmVyZW5jZS1rZXl9fSdcbiAqL1xuZnVuY3Rpb24gaXNDbG91ZEZvcm1hdGlvbkR5bmFtaWNSZWZlcmVuY2UoeDogYW55KSB7XG4gIHJldHVybiAodHlwZW9mIHggPT09ICdzdHJpbmcnICYmIHguc3RhcnRzV2l0aCgne3tyZXNvbHZlOicpICYmIHguZW5kc1dpdGgoJ319JykpO1xufVxuXG4vLyBDYW5ub3QgYmUgcHVibGljIGJlY2F1c2UgSlNJSSBnZXRzIGNvbmZ1c2VkIGFib3V0IGVzNS5kLnRzXG5jbGFzcyBDZm5TeW50aGVzaXNFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgcHVibGljIHJlYWRvbmx5IHR5cGUgPSAnQ2ZuU3ludGhlc2lzRXJyb3InO1xufVxuIl19 |
\ | No newline at end of file |