@dollhousemcp/mcp-server
Version:
DollhouseMCP - A Model Context Protocol (MCP) server that enables dynamic AI persona management from markdown files, allowing Claude and other compatible AI assistants to activate and switch between different behavioral personas.
303 lines • 41.3 kB
JavaScript
/**
* SkillElementValidator - Specialized validator for Skill elements
*
* Extends GenericElementValidator to add Skill-specific validation:
* - Complexity enum validation (beginner/intermediate/advanced/expert)
* - Proficiency level range validation (0-100)
* - Languages and domains array validation
* - Parameters array validation with type-specific rules
* - Examples array validation
* - Version semver format validation
*/
import { ElementType } from '../../portfolio/types.js';
import { GenericElementValidator } from './GenericElementValidator.js';
import { ValidatorHelpers } from './ElementValidator.js';
const VALID_COMPLEXITY_LEVELS = ['beginner', 'intermediate', 'advanced', 'expert'];
const VALID_PARAMETER_TYPES = ['string', 'number', 'boolean', 'enum'];
const SEMVER_REGEX = /^\d+\.\d+\.\d+(?:-[\w.]+)?(?:\+[\w.]+)?$/;
/**
* Specialized validator for Skill elements.
* Validates skill-specific fields: complexity, proficiency_level, languages,
* domains, parameters, examples, and version (semver).
*/
export class SkillElementValidator extends GenericElementValidator {
constructor(validationService, triggerValidationService, metadataService) {
super(ElementType.SKILL, validationService, triggerValidationService, metadataService);
}
/**
* Override validateCreate to add skill-specific validation
*/
async validateCreate(data, options) {
// First run generic validation
const baseResult = await super.validateCreate(data, options);
const errors = [...baseResult.errors];
const warnings = [...baseResult.warnings];
const suggestions = baseResult.suggestions ? [...baseResult.suggestions] : [];
if (!data || typeof data !== 'object') {
return baseResult;
}
const record = data;
// Validate complexity enum
if (record.complexity !== undefined) {
const complexityResult = this.validateComplexity(record.complexity);
if (!complexityResult.isValid) {
errors.push(...complexityResult.errors);
}
}
// Validate proficiency_level range (0-100)
if (record.proficiency_level !== undefined) {
const proficiencyResult = this.validateProficiencyLevel(record.proficiency_level);
if (!proficiencyResult.isValid) {
errors.push(...proficiencyResult.errors);
}
}
// Validate languages array
if (record.languages !== undefined) {
const languagesResult = this.validateStringArray(record.languages, 'languages');
if (!languagesResult.isValid) {
errors.push(...languagesResult.errors);
}
}
// Validate domains array
if (record.domains !== undefined) {
const domainsResult = this.validateStringArray(record.domains, 'domains');
if (!domainsResult.isValid) {
errors.push(...domainsResult.errors);
}
}
// Validate parameters array
if (record.parameters !== undefined) {
const paramsResult = this.validateParameters(record.parameters);
if (!paramsResult.isValid) {
errors.push(...paramsResult.errors);
}
warnings.push(...paramsResult.warnings);
}
// Validate examples array
if (record.examples !== undefined) {
const examplesResult = this.validateExamples(record.examples);
if (!examplesResult.isValid) {
errors.push(...examplesResult.errors);
}
}
// Validate version semver format
if (record.version !== undefined) {
const versionResult = this.validateVersion(record.version);
if (!versionResult.isValid) {
errors.push(...versionResult.errors);
}
}
// Note: empty domains/examples warnings are emitted by Skill.validate()
// to avoid duplication in the combined validateElement output.
return {
isValid: errors.length === 0,
errors,
warnings,
suggestions: suggestions.length > 0 ? suggestions : undefined
};
}
/**
* Override validateMetadata to add skill-specific metadata validation
*/
async validateMetadata(metadata, options) {
// Start with base metadata validation
const baseResult = await super.validateMetadata(metadata, {
...options,
requiredFields: options?.requiredFields ?? ['name', 'description']
});
const errors = [...baseResult.errors];
const warnings = [...baseResult.warnings];
if (!metadata || typeof metadata !== 'object') {
return baseResult;
}
const record = metadata;
// Validate complexity enum
if (record.complexity !== undefined) {
const complexityResult = this.validateComplexity(record.complexity);
if (!complexityResult.isValid) {
errors.push(...complexityResult.errors);
}
}
// Validate proficiency_level range (0-100)
if (record.proficiency_level !== undefined) {
const proficiencyResult = this.validateProficiencyLevel(record.proficiency_level);
if (!proficiencyResult.isValid) {
errors.push(...proficiencyResult.errors);
}
}
// Validate languages array
if (record.languages !== undefined) {
const languagesResult = this.validateStringArray(record.languages, 'languages');
if (!languagesResult.isValid) {
errors.push(...languagesResult.errors);
}
}
// Validate domains array
if (record.domains !== undefined) {
const domainsResult = this.validateStringArray(record.domains, 'domains');
if (!domainsResult.isValid) {
errors.push(...domainsResult.errors);
}
}
// Validate parameters array
if (record.parameters !== undefined) {
const paramsResult = this.validateParameters(record.parameters);
if (!paramsResult.isValid) {
errors.push(...paramsResult.errors);
}
warnings.push(...paramsResult.warnings);
}
// Validate examples array
if (record.examples !== undefined) {
const examplesResult = this.validateExamples(record.examples);
if (!examplesResult.isValid) {
errors.push(...examplesResult.errors);
}
}
// Validate version semver format
if (record.version !== undefined) {
const versionResult = this.validateVersion(record.version);
if (!versionResult.isValid) {
errors.push(...versionResult.errors);
}
}
// Note: empty domains/examples warnings are emitted by Skill.validate()
// to avoid duplication in the combined validateElement output.
return {
isValid: errors.length === 0,
errors,
warnings
};
}
/**
* Validate complexity enum value
*/
validateComplexity(complexity) {
if (typeof complexity !== 'string') {
return ValidatorHelpers.fail(['Complexity must be a string']);
}
if (!VALID_COMPLEXITY_LEVELS.includes(complexity)) {
return ValidatorHelpers.fail([
`Invalid complexity '${complexity}'. Valid options: ${VALID_COMPLEXITY_LEVELS.join(', ')}`
]);
}
return ValidatorHelpers.pass();
}
/**
* Validate proficiency_level is a number in range 0-100
*/
validateProficiencyLevel(level) {
if (typeof level !== 'number') {
return ValidatorHelpers.fail(['Proficiency level must be a number']);
}
if (level < 0 || level > 100) {
return ValidatorHelpers.fail([
`Proficiency level must be between 0 and 100, got ${level}`
]);
}
return ValidatorHelpers.pass();
}
/**
* Validate that a field is an array of strings
*/
validateStringArray(value, fieldName) {
if (!Array.isArray(value)) {
return ValidatorHelpers.fail([`${fieldName} must be an array`]);
}
for (let i = 0; i < value.length; i++) {
if (typeof value[i] !== 'string') {
return ValidatorHelpers.fail([
`${fieldName}[${i}] must be a string`
]);
}
}
return ValidatorHelpers.pass();
}
/**
* Validate parameters array with type-specific rules
*/
validateParameters(parameters) {
if (!Array.isArray(parameters)) {
return ValidatorHelpers.fail(['Parameters must be an array']);
}
const errors = [];
const warnings = [];
for (let i = 0; i < parameters.length; i++) {
const param = parameters[i];
if (!param || typeof param !== 'object') {
errors.push(`Parameter at index ${i} must be an object`);
continue;
}
const p = param;
// name is required and must be non-empty string
if (!p.name || typeof p.name !== 'string' || p.name.trim().length === 0) {
errors.push(`Parameter at index ${i} is missing required non-empty 'name' field`);
}
// type is required and must be one of the valid types
if (!p.type || typeof p.type !== 'string') {
errors.push(`Parameter at index ${i} is missing required 'type' field`);
}
else if (!VALID_PARAMETER_TYPES.includes(p.type)) {
errors.push(`Parameter '${p.name || i}' has invalid type '${p.type}'. Valid types: ${VALID_PARAMETER_TYPES.join(', ')}`);
}
// description is required
if (!p.description || typeof p.description !== 'string') {
errors.push(`Parameter '${p.name || i}' is missing required 'description' field`);
}
// enum-type parameters need options array
if (p.type === 'enum') {
if (!p.options || !Array.isArray(p.options) || p.options.length === 0) {
errors.push(`Parameter '${p.name || i}' has type 'enum' but is missing or has empty 'options' array`);
}
}
}
return {
isValid: errors.length === 0,
errors,
warnings
};
}
/**
* Validate examples array
*/
validateExamples(examples) {
if (!Array.isArray(examples)) {
return ValidatorHelpers.fail(['Examples must be an array']);
}
const errors = [];
for (let i = 0; i < examples.length; i++) {
const example = examples[i];
if (!example || typeof example !== 'object') {
errors.push(`Example at index ${i} must be an object`);
continue;
}
const ex = example;
if (!ex.title || typeof ex.title !== 'string') {
errors.push(`Example at index ${i} is missing required 'title' field`);
}
if (!ex.description || typeof ex.description !== 'string') {
errors.push(`Example at index ${i} is missing required 'description' field`);
}
}
return {
isValid: errors.length === 0,
errors,
warnings: []
};
}
/**
* Validate version follows semver format
*/
validateVersion(version) {
if (typeof version !== 'string') {
return ValidatorHelpers.fail(['Version must be a string']);
}
if (!SEMVER_REGEX.test(version)) {
return ValidatorHelpers.fail([
`Version '${version}' is not valid semver format (expected: major.minor.patch, e.g., 1.0.0)`
]);
}
return ValidatorHelpers.pass();
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2tpbGxFbGVtZW50VmFsaWRhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3NlcnZpY2VzL3ZhbGlkYXRpb24vU2tpbGxFbGVtZW50VmFsaWRhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7O0dBVUc7QUFFSCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDdkQsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDdkUsT0FBTyxFQUFvQixnQkFBZ0IsRUFBdUQsTUFBTSx1QkFBdUIsQ0FBQztBQUtoSSxNQUFNLHVCQUF1QixHQUFHLENBQUMsVUFBVSxFQUFFLGNBQWMsRUFBRSxVQUFVLEVBQUUsUUFBUSxDQUFVLENBQUM7QUFDNUYsTUFBTSxxQkFBcUIsR0FBRyxDQUFDLFFBQVEsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE1BQU0sQ0FBVSxDQUFDO0FBQy9FLE1BQU0sWUFBWSxHQUFHLDBDQUEwQyxDQUFDO0FBRWhFOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8scUJBQXNCLFNBQVEsdUJBQXVCO0lBQ2hFLFlBQ0UsaUJBQW9DLEVBQ3BDLHdCQUFrRCxFQUNsRCxlQUFnQztRQUVoQyxLQUFLLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxpQkFBaUIsRUFBRSx3QkFBd0IsRUFBRSxlQUFlLENBQUMsQ0FBQztJQUN6RixDQUFDO0lBRUQ7O09BRUc7SUFDTSxLQUFLLENBQUMsY0FBYyxDQUMzQixJQUFhLEVBQ2IsT0FBa0M7UUFFbEMsK0JBQStCO1FBQy9CLE1BQU0sVUFBVSxHQUFHLE1BQU0sS0FBSyxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDN0QsTUFBTSxNQUFNLEdBQUcsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN0QyxNQUFNLFFBQVEsR0FBRyxDQUFDLEdBQUcsVUFBVSxDQUFD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RUFBRSxDQUFDLFdBQVcsSUFBSSxPQUFPLEVBQUUsQ0FBQyxXQUFXLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQzFELE1BQU0sQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsMENBQTBDLENBQUMsQ0FBQztZQUMvRSxDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU87WUFDTCxPQUFPLEVBQUUsTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDO1lBQzVCLE1BQU07WUFDTixRQUFRLEVBQUUsRUFBRTtTQUNiLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSyxlQUFlLENBQUMsT0FBZ0I7UUFDdEMsSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUNoQyxPQUFPLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLDBCQUEwQixDQUFDLENBQUMsQ0FBQztRQUM3RCxDQUFDO1FBRUQsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNoQyxPQUFPLGdCQUFnQixDQUFDLElBQUksQ0FBQztnQkFDM0IsWUFBWSxPQUFPLHlFQUF5RTthQUM3RixDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsT0FBTyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNqQyxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFNraWxsRWxlbWVudFZhbGlkYXRvciAtIFNwZWNpYWxpemVkIHZhbGlkYXRvciBmb3IgU2tpbGwgZWxlbWVudHNcbiAqXG4gKiBFeHRlbmRzIEdlbmVyaWNFbGVtZW50VmFsaWRhdG9yIHRvIGFkZCBTa2lsbC1zcGVjaWZpYyB2YWxpZGF0aW9uOlxuICogLSBDb21wbGV4aXR5IGVudW0gdmFsaWRhdGlvbiAoYmVnaW5uZXIvaW50ZXJtZWRpYXRlL2FkdmFuY2VkL2V4cGVydClcbiAqIC0gUHJvZmljaWVuY3kgbGV2ZWwgcmFuZ2UgdmFsaWRhdGlvbiAoMC0xMDApXG4gKiAtIExhbmd1YWdlcyBhbmQgZG9tYWlucyBhcnJheSB2YWxpZGF0aW9uXG4gKiAtIFBhcmFtZXRlcnMgYXJyYXkgdmFsaWRhdGlvbiB3aXRoIHR5cGUtc3BlY2lmaWMgcnVsZXNcbiAqIC0gRXhhbXBsZXMgYXJyYXkgdmFsaWRhdGlvblxuICogLSBWZXJzaW9uIHNlbXZlciBmb3JtYXQgdmFsaWRhdGlvblxuICovXG5cbmltcG9ydCB7IEVsZW1lbnRUeXBlIH0gZnJvbSAnLi4vLi4vcG9ydGZvbGlvL3R5cGVzLmpzJztcbmltcG9ydCB7IEdlbmVyaWNFbGVtZW50VmFsaWRhdG9yIH0gZnJvbSAnLi9HZW5lcmljRWxlbWVudFZhbGlkYXRvci5qcyc7XG5pbXBvcnQgeyBWYWxpZGF0aW9uUmVzdWx0LCBWYWxpZGF0b3JIZWxwZXJzLCBFbGVtZW50VmFsaWRhdGlvbk9wdGlvbnMsIE1ldGFkYXRhVmFsaWRhdGlvbk9wdGlvbnMgfSBmcm9tICcuL0VsZW1lbnRWYWxpZGF0b3IuanMnO1xuaW1wb3J0IHsgVmFsaWRhdGlvblNlcnZpY2UgfSBmcm9tICcuL1ZhbGlkYXRpb25TZXJ2aWNlLmpzJztcbmltcG9ydCB7IFRyaWdnZXJWYWxpZGF0aW9uU2VydmljZSB9IGZyb20gJy4vVHJpZ2dlclZhbGlkYXRpb25TZXJ2aWNlLmpzJztcbmltcG9ydCB7IE1ldGFkYXRhU2VydmljZSB9IGZyb20gJy4uL01ldGFkYXRhU2VydmljZS5qcyc7XG5cbmNvbnN0IFZBTElEX0NPTVBMRVhJVFlfTEVWRUxTID0gWydiZWdpbm5lcicsICdpbnRlcm1lZGlhdGUnLCAnYWR2YW5jZWQnLCAnZXhwZXJ0J10gYXMgY29uc3Q7XG5jb25zdCBWQUxJRF9QQVJBTUVURVJfVFlQRVMgPSBbJ3N0cmluZycsICdudW1iZXInLCAnYm9vbGVhbicsICdlbnVtJ10gYXMgY29uc3Q7XG5jb25zdCBTRU1WRVJfUkVHRVggPSAvXlxcZCtcXC5cXGQrXFwuXFxkKyg/Oi1bXFx3Ll0rKT8oPzpcXCtbXFx3Ll0rKT8kLztcblxuLyoqXG4gKiBTcGVjaWFsaXplZCB2YWxpZGF0b3IgZm9yIFNraWxsIGVsZW1lbnRzLlxuICogVmFsaWRhdGVzIHNraWxsLXNwZWNpZmljIGZpZWxkczogY29tcGxleGl0eSwgcHJvZmljaWVuY3lfbGV2ZWwsIGxhbmd1YWdlcyxcbiAqIGRvbWFpbnMsIHBhcmFtZXRlcnMsIGV4YW1wbGVzLCBhbmQgdmVyc2lvbiAoc2VtdmVyKS5cbiAqL1xuZXhwb3J0IGNsYXNzIFNraWxsRWxlbWVudFZhbGlkYXRvciBleHRlbmRzIEdlbmVyaWNFbGVtZW50VmFsaWRhdG9yIHtcbiAgY29uc3RydWN0b3IoXG4gICAgdmFsaWRhdGlvblNlcnZpY2U6IFZhbGlkYXRpb25TZXJ2aWNlLFxuICAgIHRyaWdnZXJWYWxpZGF0aW9uU2VydmljZTogVHJpZ2dlclZhbGlkYXRpb25TZXJ2aWNlLFxuICAgIG1ldGFkYXRhU2VydmljZTogTWV0YWRhdGFTZXJ2aWNlXG4gICkge1xuICAgIHN1cGVyKEVsZW1lbnRUeXBlLlNLSUxMLCB2YWxpZGF0aW9uU2VydmljZSwgdHJpZ2dlclZhbGlkYXRpb25TZXJ2aWNlLCBtZXRhZGF0YVNlcnZpY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIE92ZXJyaWRlIHZhbGlkYXRlQ3JlYXRlIHRvIGFkZCBza2lsbC1zcGVjaWZpYyB2YWxpZGF0aW9uXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyB2YWxpZGF0ZUNyZWF0ZShcbiAgICBkYXRhOiB1bmtub3duLFxuICAgIG9wdGlvbnM/OiBFbGVtZW50VmFsaWRhdGlvbk9wdGlvbnNcbiAgKTogUHJvbWlzZTxWYWxpZGF0aW9uUmVzdWx0PiB7XG4gICAgLy8gRmlyc3QgcnVuIGdlbmVyaWMgdmFsaWRhdGlvblxuICAgIGNvbnN0IGJhc2VSZXN1bHQgPSBhd2FpdCBzdXBlci52YWxpZGF0ZUNyZWF0ZShkYXRhLCBvcHRpb25zKTtcbiAgICBjb25zdCBlcnJvcnMgPSBbLi4uYmFzZVJlc3VsdC5lcnJvcnNdO1xuICAgIGNvbnN0IHdhcm5pbmdzID0gWy4uLmJhc2VSZXN1bHQud2FybmluZ3NdO1xuICAgIGNvbnN0IHN1Z2dlc3Rpb25zID0gYmFzZVJlc3VsdC5zdWdnZXN0aW9ucyA/IFsuLi5iYXNlUmVzdWx0LnN1Z2dlc3Rpb25zXSA6IFtdO1xuXG4gICAgaWYgKCFkYXRhIHx8IHR5cGVvZiBkYXRhICE9PSAnb2JqZWN0Jykge1xuICAgICAgcmV0dXJuIGJhc2VSZXN1bHQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVjb3JkID0gZGF0YSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuICAgIC8vIFZhbGlkYXRlIGNvbXBsZXhpdHkgZW51bVxuICAgIGlmIChyZWNvcmQuY29tcGxleGl0eSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCBjb21wbGV4aXR5UmVzdWx0ID0gdGhpcy52YWxpZGF0ZUNvbXBsZXhpdHkocmVjb3JkLmNvbXBsZXhpdHkpO1xuICAgICAgaWYgKCFjb21wbGV4aXR5UmVzdWx0LmlzVmFsaWQpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goLi4uY29tcGxleGl0eVJlc3VsdC5lcnJvcnMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIHByb2ZpY2llbmN5X2xldmVsIHJhbmdlICgwLTEwMClcbiAgICBpZiAocmVjb3JkLnByb2ZpY2llbmN5X2xldmVsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IHByb2ZpY2llbmN5UmVzdWx0ID0gdGhpcy52YWxpZGF0ZVByb2ZpY2llbmN5TGV2ZWwocmVjb3JkLnByb2ZpY2llbmN5X2xldmVsKTtcbiAgICAgIGlmICghcHJvZmljaWVuY3lSZXN1bHQuaXNWYWxpZCkge1xuICAgICAgICBlcnJvcnMucHVzaCguLi5wcm9maWNpZW5jeVJlc3VsdC5lcnJvcnMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIGxhbmd1YWdlcyBhcnJheVxuICAgIGlmIChyZWNvcmQubGFuZ3VhZ2VzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IGxhbmd1YWdlc1Jlc3VsdCA9IHRoaXMudmFsaWRhdGVTdHJpbmdBcnJheShyZWNvcmQubGFuZ3VhZ2VzLCAnbGFuZ3VhZ2VzJyk7XG4gICAgICBpZiAoIWxhbmd1YWdlc1Jlc3VsdC5pc1ZhbGlkKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKC4uLmxhbmd1YWdlc1Jlc3VsdC5lcnJvcnMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIGRvbWFpbnMgYXJyYXlcbiAgICBpZiAocmVjb3JkLmRvbWFpbnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgZG9tYWluc1Jlc3VsdCA9IHRoaXMudmFsaWRhdGVTdHJpbmdBcnJheShyZWNvcmQuZG9tYWlucywgJ2RvbWFpbnMnKTtcbiAgICAgIGlmICghZG9tYWluc1Jlc3VsdC5pc1ZhbGlkKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKC4uLmRvbWFpbnNSZXN1bHQuZXJyb3JzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBwYXJhbWV0ZXJzIGFycmF5XG4gICAgaWYgKHJlY29yZC5wYXJhbWV0ZXJzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IHBhcmFtc1Jlc3VsdCA9IHRoaXMudmFsaWRhdGVQYXJhbWV0ZXJzKHJlY29yZC5wYXJhbWV0ZXJzKTtcbiAgICAgIGlmICghcGFyYW1zUmVzdWx0LmlzVmFsaWQpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goLi4ucGFyYW1zUmVzdWx0LmVycm9ycyk7XG4gICAgICB9XG4gICAgICB3YXJuaW5ncy5wdXNoKC4uLnBhcmFtc1Jlc3VsdC53YXJuaW5ncyk7XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgZXhhbXBsZXMgYXJyYXlcbiAgICBpZiAocmVjb3JkLmV4YW1wbGVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IGV4YW1wbGVzUmVzdWx0ID0gdGhpcy52YWxpZGF0ZUV4YW1wbGVzKHJlY29yZC5leGFtcGxlcyk7XG4gICAgICBpZiAoIWV4YW1wbGVzUmVzdWx0LmlzVmFsaWQpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goLi4uZXhhbXBsZXNSZXN1bHQuZXJyb3JzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSB2ZXJzaW9uIHNlbXZlciBmb3JtYXRcbiAgICBpZiAocmVjb3JkLnZlcnNpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgdmVyc2lvblJlc3VsdCA9IHRoaXMudmFsaWRhdGVWZXJzaW9uKHJlY29yZC52ZXJzaW9uKTtcbiAgICAgIGlmICghdmVyc2lvblJlc3VsdC5pc1ZhbGlkKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKC4uLnZlcnNpb25SZXN1bHQuZXJyb3JzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBOb3RlOiBlbXB0eSBkb21haW5zL2V4YW1wbGVzIHdhcm5pbmdzIGFyZSBlbWl0dGVkIGJ5IFNraWxsLnZhbGlkYXRlKClcbiAgICAvLyB0byBhdm9pZCBkdXBsaWNhdGlvbiBpbiB0aGUgY29tYmluZWQgdmFsaWRhdGVFbGVtZW50IG91dHB1dC5cblxuICAgIHJldHVybiB7XG4gICAgICBpc1ZhbGlkOiBlcnJvcnMubGVuZ3RoID09PSAwLFxuICAgICAgZXJyb3JzLFxuICAgICAgd2FybmluZ3MsXG4gICAgICBzdWdnZXN0aW9uczogc3VnZ2VzdGlvbnMubGVuZ3RoID4gMCA/IHN1Z2dlc3Rpb25zIDogdW5kZWZpbmVkXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPdmVycmlkZSB2YWxpZGF0ZU1ldGFkYXRhIHRvIGFkZCBza2lsbC1zcGVjaWZpYyBtZXRhZGF0YSB2YWxpZGF0aW9uXG4gICAqL1xuICBvdmVycmlkZSBhc3luYyB2YWxpZGF0ZU1ldGFkYXRhKFxuICAgIG1ldGFkYXRhOiB1bmtub3duLFxuICAgIG9wdGlvbnM/OiBNZXRhZGF0YVZhbGlkYXRpb25PcHRpb25zXG4gICk6IFByb21pc2U8VmFsaWRhdGlvblJlc3VsdD4ge1xuICAgIC8vIFN0YXJ0IHdpdGggYmFzZSBtZXRhZGF0YSB2YWxpZGF0aW9uXG4gICAgY29uc3QgYmFzZVJlc3VsdCA9IGF3YWl0IHN1cGVyLnZhbGlkYXRlTWV0YWRhdGEobWV0YWRhdGEsIHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICByZXF1aXJlZEZpZWxkczogb3B0aW9ucz8ucmVxdWlyZWRGaWVsZHMgPz8gWyduYW1lJywgJ2Rlc2NyaXB0aW9uJ11cbiAgICB9KTtcblxuICAgIGNvbnN0IGVycm9ycyA9IFsuLi5iYXNlUmVzdWx0LmVycm9yc107XG4gICAgY29uc3Qgd2FybmluZ3MgPSBbLi4uYmFzZVJlc3VsdC53YXJuaW5nc107XG5cbiAgICBpZiAoIW1ldGFkYXRhIHx8IHR5cGVvZiBtZXRhZGF0YSAhPT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybiBiYXNlUmVzdWx0O1xuICAgIH1cblxuICAgIGNvbnN0IHJlY29yZCA9IG1ldGFkYXRhIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4gICAgLy8gVmFsaWRhdGUgY29tcGxleGl0eSBlbnVtXG4gICAgaWYgKHJlY29yZC5jb21wbGV4aXR5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXhpdHlSZXN1bHQgPSB0aGlzLnZhbGlkYXRlQ29tcGxleGl0eShyZWNvcmQuY29tcGxleGl0eSk7XG4gICAgICBpZiAoIWNvbXBsZXhpdHlSZXN1bHQuaXNWYWxpZCkge1xuICAgICAgICBlcnJvcnMucHVzaCguLi5jb21wbGV4aXR5UmVzdWx0LmVycm9ycyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgcHJvZmljaWVuY3lfbGV2ZWwgcmFuZ2UgKDAtMTAwKVxuICAgIGlmIChyZWNvcmQucHJvZmljaWVuY3lfbGV2ZWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgcHJvZmljaWVuY3lSZXN1bHQgPSB0aGlzLnZhbGlkYXRlUHJvZmljaWVuY3lMZXZlbChyZWNvcmQucHJvZmljaWVuY3lfbGV2ZWwpO1xuICAgICAgaWYgKCFwcm9maWNpZW5jeVJlc3VsdC5pc1ZhbGlkKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKC4uLnByb2ZpY2llbmN5UmVzdWx0LmVycm9ycyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgbGFuZ3VhZ2VzIGFycmF5XG4gICAgaWYgKHJlY29yZC5sYW5ndWFnZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgbGFuZ3VhZ2VzUmVzdWx0ID0gdGhpcy52YWxpZGF0ZVN0cmluZ0FycmF5KHJlY29yZC5sYW5ndWFnZXMsICdsYW5ndWFnZXMnKTtcbiAgICAgIGlmICghbGFuZ3VhZ2VzUmVzdWx0LmlzVmFsaWQpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goLi4ubGFuZ3VhZ2VzUmVzdWx0LmVycm9ycyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgZG9tYWlucyBhcnJheVxuICAgIGlmIChyZWNvcmQuZG9tYWlucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCBkb21haW5zUmVzdWx0ID0gdGhpcy52YWxpZGF0ZVN0cmluZ0FycmF5KHJlY29yZC5kb21haW5zLCAnZG9tYWlucycpO1xuICAgICAgaWYgKCFkb21haW5zUmVzdWx0LmlzVmFsaWQpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goLi4uZG9tYWluc1Jlc3VsdC5lcnJvcnMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIHBhcmFtZXRlcnMgYXJyYXlcbiAgICBpZiAocmVjb3JkLnBhcmFtZXRlcnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgcGFyYW1zUmVzdWx0ID0gdGhpcy52YWxpZGF0ZVBhcmFtZXRlcnMocmVjb3JkLnBhcmFtZXRlcnMpO1xuICAgICAgaWYgKCFwYXJhbXNSZXN1bHQuaXNWYWxpZCkge1xuICAgICAgICBlcnJvcnMucHVzaCguLi5wYXJhbXNSZXN1bHQuZXJyb3JzKTtcbiAgICAgIH1cbiAgICAgIHdhcm5pbmdzLnB1c2goLi4ucGFyYW1zUmVzdWx0Lndhcm5pbmdzKTtcbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBleGFtcGxlcyBhcnJheVxuICAgIGlmIChyZWNvcmQuZXhhbXBsZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgZXhhbXBsZXNSZXN1bHQgPSB0aGlzLnZhbGlkYXRlRXhhbXBsZXMocmVjb3JkLmV4YW1wbGVzKTtcbiAgICAgIGlmICghZXhhbXBsZXNSZXN1bHQuaXNWYWxpZCkge1xuICAgICAgICBlcnJvcnMucHVzaCguLi5leGFtcGxlc1Jlc3VsdC5lcnJvcnMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIHZlcnNpb24gc2VtdmVyIGZvcm1hdFxuICAgIGlmIChyZWNvcmQudmVyc2lvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCB2ZXJzaW9uUmVzdWx0ID0gdGhpcy52YWxpZGF0ZVZlcnNpb24ocmVjb3JkLnZlcnNpb24pO1xuICAgICAgaWYgKCF2ZXJzaW9uUmVzdWx0LmlzVmFsaWQpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goLi4udmVyc2lvblJlc3VsdC5lcnJvcnMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE5vdGU6IGVtcHR5IGRvbWFpbnMvZXhhbXBsZXMgd2FybmluZ3MgYXJlIGVtaXR0ZWQgYnkgU2tpbGwudmFsaWRhdGUoKVxuICAgIC8vIHRvIGF2b2lkIGR1cGxpY2F0aW9uIGluIHRoZSBjb21iaW5lZCB2YWxpZGF0ZUVsZW1lbnQgb3V0cHV0LlxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGlzVmFsaWQ6IGVycm9ycy5sZW5ndGggPT09IDAsXG4gICAgICBlcnJvcnMsXG4gICAgICB3YXJuaW5nc1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgY29tcGxleGl0eSBlbnVtIHZhbHVlXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlQ29tcGxleGl0eShjb21wbGV4aXR5OiB1bmtub3duKTogVmFsaWRhdGlvblJlc3VsdCB7XG4gICAgaWYgKHR5cGVvZiBjb21wbGV4aXR5ICE9PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIFZhbGlkYXRvckhlbHBlcnMuZmFpbChbJ0NvbXBsZXhpdHkgbXVzdCBiZSBhIHN0cmluZyddKTtcbiAgICB9XG5cbiAgICBpZiAoIShWQUxJRF9DT01QTEVYSVRZX0xFVkVMUyBhcyByZWFkb25seSBzdHJpbmdbXSkuaW5jbHVkZXMoY29tcGxleGl0eSkpIHtcbiAgICAgIHJldHVybiBWYWxpZGF0b3JIZWxwZXJzLmZhaWwoW1xuICAgICAgICBgSW52YWxpZCBjb21wbGV4aXR5ICcke2NvbXBsZXhpdHl9Jy4gVmFsaWQgb3B0aW9uczogJHtWQUxJRF9DT01QTEVYSVRZX0xFVkVMUy5qb2luKCcsICcpfWBcbiAgICAgIF0pO1xuICAgIH1cblxuICAgIHJldHVybiBWYWxpZGF0b3JIZWxwZXJzLnBhc3MoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSBwcm9maWNpZW5jeV9sZXZlbCBpcyBhIG51bWJlciBpbiByYW5nZSAwLTEwMFxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVByb2ZpY2llbmN5TGV2ZWwobGV2ZWw6IHVua25vd24pOiBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgICBpZiAodHlwZW9mIGxldmVsICE9PSAnbnVtYmVyJykge1xuICAgICAgcmV0dXJuIFZhbGlkYXRvckhlbHBlcnMuZmFpbChbJ1Byb2ZpY2llbmN5IGxldmVsIG11c3QgYmUgYSBudW1iZXInXSk7XG4gICAgfVxuXG4gICAgaWYgKGxldmVsIDwgMCB8fCBsZXZlbCA+IDEwMCkge1xuICAgICAgcmV0dXJuIFZhbGlkYXRvckhlbHBlcnMuZmFpbChbXG4gICAgICAgIGBQcm9maWNpZW5jeSBsZXZlbCBtdXN0IGJlIGJldHdlZW4gMCBhbmQgMTAwLCBnb3QgJHtsZXZlbH1gXG4gICAgICBdKTtcbiAgICB9XG5cbiAgICByZXR1cm4gVmFsaWRhdG9ySGVscGVycy5wYXNzKCk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhhdCBhIGZpZWxkIGlzIGFuIGFycmF5IG9mIHN0cmluZ3NcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVTdHJpbmdBcnJheSh2YWx1ZTogdW5rbm93biwgZmllbGROYW1lOiBzdHJpbmcpOiBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICByZXR1cm4gVmFsaWRhdG9ySGVscGVycy5mYWlsKFtgJHtmaWVsZE5hbWV9IG11c3QgYmUgYW4gYXJyYXlgXSk7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx1ZS5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHR5cGVvZiB2YWx1ZVtpXSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIFZhbGlkYXRvckhlbHBlcnMuZmFpbChbXG4gICAgICAgICAgYCR7ZmllbGROYW1lfVske2l9XSBtdXN0IGJlIGEgc3RyaW5nYFxuICAgICAgICBdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gVmFsaWRhdG9ySGVscGVycy5wYXNzKCk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgcGFyYW1ldGVycyBhcnJheSB3aXRoIHR5cGUtc3BlY2lmaWMgcnVsZXNcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVQYXJhbWV0ZXJzKHBhcmFtZXRlcnM6IHVua25vd24pOiBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkocGFyYW1ldGVycykpIHtcbiAgICAgIHJldHVybiBWYWxpZGF0b3JIZWxwZXJzLmZhaWwoWydQYXJhbWV0ZXJzIG11c3QgYmUgYW4gYXJyYXknXSk7XG4gICAgfVxuXG4gICAgY29uc3QgZXJyb3JzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGNvbnN0IHdhcm5pbmdzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJhbWV0ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBwYXJhbSA9IHBhcmFtZXRlcnNbaV07XG5cbiAgICAgIGlmICghcGFyYW0gfHwgdHlwZW9mIHBhcmFtICE9PSAnb2JqZWN0Jykge1xuICAgICAgICBlcnJvcnMucHVzaChgUGFyYW1ldGVyIGF0IGluZGV4ICR7aX0gbXVzdCBiZSBhbiBvYmplY3RgKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHAgPSBwYXJhbSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuICAgICAgLy8gbmFtZSBpcyByZXF1aXJlZCBhbmQgbXVzdCBiZSBub24tZW1wdHkgc3RyaW5nXG4gICAgICBpZiAoIXAubmFtZSB8fCB0eXBlb2YgcC5uYW1lICE9PSAnc3RyaW5nJyB8fCBwLm5hbWUudHJpbSgpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBlcnJvcnMucHVzaChgUGFyYW1ldGVyIGF0IGluZGV4ICR7aX0gaXMgbWlzc2luZyByZXF1aXJlZCBub24tZW1wdHkgJ25hbWUnIGZpZWxkYCk7XG4gICAgICB9XG5cbiAgICAgIC8vIHR5cGUgaXMgcmVxdWlyZWQgYW5kIG11c3QgYmUgb25lIG9mIHRoZSB2YWxpZCB0eXBlc1xuICAgICAgaWYgKCFwLnR5cGUgfHwgdHlwZW9mIHAudHlwZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goYFBhcmFtZXRlciBhdCBpbmRleCAke2l9IGlzIG1pc3NpbmcgcmVxdWlyZWQgJ3R5cGUnIGZpZWxkYCk7XG4gICAgICB9IGVsc2UgaWYgKCEoVkFMSURfUEFSQU1FVEVSX1RZUEVTIGFzIHJlYWRvbmx5IHN0cmluZ1tdKS5pbmNsdWRlcyhwLnR5cGUpKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKFxuICAgICAgICAgIGBQYXJhbWV0ZXIgJyR7cC5uYW1lIHx8IGl9JyBoYXMgaW52YWxpZCB0eXBlICcke3AudHlwZX0nLiBWYWxpZCB0eXBlczogJHtWQUxJRF9QQVJBTUVURVJfVFlQRVMuam9pbignLCAnKX1gXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIC8vIGRlc2NyaXB0aW9uIGlzIHJlcXVpcmVkXG4gICAgICBpZiAoIXAuZGVzY3JpcHRpb24gfHwgdHlwZW9mIHAuZGVzY3JpcHRpb24gIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKGBQYXJhbWV0ZXIgJyR7cC5uYW1lIHx8IGl9JyBpcyBtaXNzaW5nIHJlcXVpcmVkICdkZXNjcmlwdGlvbicgZmllbGRgKTtcbiAgICAgIH1cblxuICAgICAgLy8gZW51bS10eXBlIHBhcmFtZXRlcnMgbmVlZCBvcHRpb25zIGFycmF5XG4gICAgICBpZiAocC50eXBlID09PSAnZW51bScpIHtcbiAgICAgICAgaWYgKCFwLm9wdGlvbnMgfHwgIUFycmF5LmlzQXJyYXkocC5vcHRpb25zKSB8fCBwLm9wdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgZXJyb3JzLnB1c2goYFBhcmFtZXRlciAnJHtwLm5hbWUgfHwgaX0nIGhhcyB0eXBlICdlbnVtJyBidXQgaXMgbWlzc2luZyBvciBoYXMgZW1wdHkgJ29wdGlvbnMnIGFycmF5YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgaXNWYWxpZDogZXJyb3JzLmxlbmd0aCA9PT0gMCxcbiAgICAgIGVycm9ycyxcbiAgICAgIHdhcm5pbmdzXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSBleGFtcGxlcyBhcnJheVxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZUV4YW1wbGVzKGV4YW1wbGVzOiB1bmtub3duKTogVmFsaWRhdGlvblJlc3VsdCB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGV4YW1wbGVzKSkge1xuICAgICAgcmV0dXJuIFZhbGlkYXRvckhlbHBlcnMuZmFpbChbJ0V4YW1wbGVzIG11c3QgYmUgYW4gYXJyYXknXSk7XG4gICAgfVxuXG4gICAgY29uc3QgZXJyb3JzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBleGFtcGxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgZXhhbXBsZSA9IGV4YW1wbGVzW2ldO1xuXG4gICAgICBpZiAoIWV4YW1wbGUgfHwgdHlwZW9mIGV4YW1wbGUgIT09ICdvYmplY3QnKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKGBFeGFtcGxlIGF0IGluZGV4ICR7aX0gbXVzdCBiZSBhbiBvYmplY3RgKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGV4ID0gZXhhbXBsZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuICAgICAgaWYgKCFleC50aXRsZSB8fCB0eXBlb2YgZXgudGl0bGUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKGBFeGFtcGxlIGF0IGluZGV4ICR7aX0gaXMgbWlzc2luZyByZXF1aXJlZCAndGl0bGUnIGZpZWxkYCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghZXguZGVzY3JpcHRpb24gfHwgdHlwZW9mIGV4LmRlc2NyaXB0aW9uICE9PSAnc3RyaW5nJykge1xuICAgICAgICBlcnJvcnMucHVzaChgRXhhbXBsZSBhdCBpbmRleCAke2l9IGlzIG1pc3NpbmcgcmVxdWlyZWQgJ2Rlc2NyaXB0aW9uJyBmaWVsZGApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBpc1ZhbGlkOiBlcnJvcnMubGVuZ3RoID09PSAwLFxuICAgICAgZXJyb3JzLFxuICAgICAgd2FybmluZ3M6IFtdXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSB2ZXJzaW9uIGZvbGxvd3Mgc2VtdmVyIGZvcm1hdFxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVZlcnNpb24odmVyc2lvbjogdW5rbm93bik6IFZhbGlkYXRpb25SZXN1bHQge1xuICAgIGlmICh0eXBlb2YgdmVyc2lvbiAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBWYWxpZGF0b3JIZWxwZXJzLmZhaWwoWydWZXJzaW9uIG11c3QgYmUgYSBzdHJpbmcnXSk7XG4gICAgfVxuXG4gICAgaWYgKCFTRU1WRVJfUkVHRVgudGVzdCh2ZXJzaW9uKSkge1xuICAgICAgcmV0dXJuIFZhbGlkYXRvckhlbHBlcnMuZmFpbChbXG4gICAgICAgIGBWZXJzaW9uICcke3ZlcnNpb259JyBpcyBub3QgdmFsaWQgc2VtdmVyIGZvcm1hdCAoZXhwZWN0ZWQ6IG1ham9yLm1pbm9yLnBhdGNoLCBlLmcuLCAxLjAuMClgXG4gICAgICBdKTtcbiAgICB9XG5cbiAgICByZXR1cm4gVmFsaWRhdG9ySGVscGVycy5wYXNzKCk7XG4gIH1cbn1cbiJdfQ==