payload
Version:
Node, React and MongoDB Headless CMS and Application Framework
517 lines (516 loc) • 60.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
configToJSONSchema: function() {
return configToJSONSchema;
},
entityToJSONSchema: function() {
return entityToJSONSchema;
},
fieldsToJSONSchema: function() {
return fieldsToJSONSchema;
},
withNullableJSONSchemaType: function() {
return withNullableJSONSchemaType;
}
});
const _pluralize = require("pluralize");
const _types = require("../fields/config/types");
const _deepCopyObject = require("./deepCopyObject");
const _formatLabels = require("./formatLabels");
const fieldIsRequired = (field)=>{
const isConditional = Boolean(field?.admin && field?.admin?.condition);
if (isConditional) return false;
const isMarkedRequired = 'required' in field && field.required === true;
if ((0, _types.fieldAffectsData)(field) && isMarkedRequired) return true;
// if any subfields are required, this field is required
if ('fields' in field && field.type !== 'array') {
return field.fields.some((subField)=>fieldIsRequired(subField));
}
// if any tab subfields have required fields, this field is required
if (field.type === 'tabs') {
return field.tabs.some((tab)=>{
if ('name' in tab) {
return tab.fields.some((subField)=>fieldIsRequired(subField));
}
return false;
});
}
return false;
};
function buildOptionEnums(options) {
return options.map((option)=>{
if (typeof option === 'object' && 'value' in option) {
return option.value;
}
return option;
});
}
function generateEntitySchemas(entities) {
const properties = [
...entities
].reduce((acc, { slug })=>{
acc[slug] = {
$ref: `#/definitions/${slug}`
};
return acc;
}, {});
return {
additionalProperties: false,
properties,
required: Object.keys(properties),
type: 'object'
};
}
function withNullableJSONSchemaType(fieldType, isRequired) {
const fieldTypes = [
fieldType
];
if (isRequired) return fieldType;
fieldTypes.push('null');
return fieldTypes;
}
function fieldsToJSONSchema(collectionIDFieldTypes, fields, /**
* Allows you to define new top-level interfaces that can be re-used in the output schema.
*/ interfaceNameDefinitions) {
const requiredFieldNames = new Set();
return {
properties: Object.fromEntries(fields.reduce((fieldSchemas, field)=>{
const isRequired = (0, _types.fieldAffectsData)(field) && fieldIsRequired(field);
if (isRequired) requiredFieldNames.add(field.name);
let fieldSchema;
switch(field.type){
case 'text':
if (field.hasMany === true) {
fieldSchema = {
items: {
type: 'string'
},
type: withNullableJSONSchemaType('array', isRequired)
};
} else {
fieldSchema = {
type: withNullableJSONSchemaType('string', isRequired)
};
}
break;
case 'textarea':
case 'code':
case 'email':
case 'date':
{
fieldSchema = {
type: withNullableJSONSchemaType('string', isRequired)
};
break;
}
case 'number':
{
if (field.hasMany === true) {
fieldSchema = {
items: {
type: 'number'
},
type: withNullableJSONSchemaType('array', isRequired)
};
} else {
fieldSchema = {
type: withNullableJSONSchemaType('number', isRequired)
};
}
break;
}
case 'checkbox':
{
fieldSchema = {
type: withNullableJSONSchemaType('boolean', isRequired)
};
break;
}
case 'json':
{
fieldSchema = {
type: [
'object',
'array',
'string',
'number',
'boolean',
'null'
]
};
break;
}
case 'richText':
{
if (field.editor.outputSchema) {
fieldSchema = field.editor.outputSchema({
field,
interfaceNameDefinitions,
isRequired
});
} else {
// Maintain backwards compatibility with existing rich text editors
fieldSchema = {
items: {
type: 'object'
},
type: withNullableJSONSchemaType('array', isRequired)
};
}
break;
}
case 'radio':
{
fieldSchema = {
enum: buildOptionEnums(field.options),
type: withNullableJSONSchemaType('string', isRequired)
};
break;
}
case 'select':
{
const optionEnums = buildOptionEnums(field.options);
if (field.hasMany) {
fieldSchema = {
items: {
enum: optionEnums,
type: 'string'
},
type: withNullableJSONSchemaType('array', isRequired)
};
} else {
fieldSchema = {
enum: optionEnums,
type: withNullableJSONSchemaType('string', isRequired)
};
}
break;
}
case 'point':
{
fieldSchema = {
items: [
{
type: 'number'
},
{
type: 'number'
}
],
maxItems: 2,
minItems: 2,
type: withNullableJSONSchemaType('array', isRequired)
};
break;
}
case 'relationship':
{
if (Array.isArray(field.relationTo)) {
if (field.hasMany) {
fieldSchema = {
items: {
oneOf: field.relationTo.map((relation)=>{
return {
additionalProperties: false,
properties: {
relationTo: {
const: relation
},
value: {
oneOf: [
{
type: collectionIDFieldTypes[relation]
},
{
$ref: `#/definitions/${relation}`
}
]
}
},
required: [
'value',
'relationTo'
],
type: 'object'
};
})
},
type: withNullableJSONSchemaType('array', isRequired)
};
} else {
fieldSchema = {
oneOf: field.relationTo.map((relation)=>{
return {
additionalProperties: false,
properties: {
relationTo: {
const: relation
},
value: {
oneOf: [
{
type: collectionIDFieldTypes[relation]
},
{
$ref: `#/definitions/${relation}`
}
]
}
},
required: [
'value',
'relationTo'
],
type: withNullableJSONSchemaType('object', isRequired)
};
})
};
}
} else if (field.hasMany) {
fieldSchema = {
items: {
oneOf: [
{
type: collectionIDFieldTypes[field.relationTo]
},
{
$ref: `#/definitions/${field.relationTo}`
}
]
},
type: withNullableJSONSchemaType('array', isRequired)
};
} else {
fieldSchema = {
oneOf: [
{
type: withNullableJSONSchemaType(collectionIDFieldTypes[field.relationTo], isRequired)
},
{
$ref: `#/definitions/${field.relationTo}`
}
]
};
}
break;
}
case 'upload':
{
fieldSchema = {
oneOf: [
{
type: collectionIDFieldTypes[field.relationTo]
},
{
$ref: `#/definitions/${field.relationTo}`
}
]
};
if (!isRequired) fieldSchema.oneOf.push({
type: 'null'
});
break;
}
case 'blocks':
{
fieldSchema = {
items: {
oneOf: field.blocks.map((block)=>{
const blockFieldSchemas = fieldsToJSONSchema(collectionIDFieldTypes, block.fields, interfaceNameDefinitions);
const blockSchema = {
additionalProperties: false,
properties: {
...blockFieldSchemas.properties,
blockType: {
const: block.slug
}
},
required: [
'blockType',
...blockFieldSchemas.required
],
type: 'object'
};
if (block.interfaceName) {
interfaceNameDefinitions.set(block.interfaceName, blockSchema);
return {
$ref: `#/definitions/${block.interfaceName}`
};
}
return blockSchema;
})
},
type: withNullableJSONSchemaType('array', isRequired)
};
break;
}
case 'array':
{
fieldSchema = {
items: {
additionalProperties: false,
type: 'object',
...fieldsToJSONSchema(collectionIDFieldTypes, field.fields, interfaceNameDefinitions)
},
type: withNullableJSONSchemaType('array', isRequired)
};
if (field.interfaceName) {
interfaceNameDefinitions.set(field.interfaceName, fieldSchema);
fieldSchema = {
$ref: `#/definitions/${field.interfaceName}`
};
}
break;
}
case 'row':
case 'collapsible':
{
const childSchema = fieldsToJSONSchema(collectionIDFieldTypes, field.fields, interfaceNameDefinitions);
Object.entries(childSchema.properties).forEach(([propName, propSchema])=>{
fieldSchemas.set(propName, propSchema);
});
childSchema.required.forEach((propName)=>{
requiredFieldNames.add(propName);
});
break;
}
case 'tabs':
{
field.tabs.forEach((tab)=>{
const childSchema = fieldsToJSONSchema(collectionIDFieldTypes, tab.fields, interfaceNameDefinitions);
if ((0, _types.tabHasName)(tab)) {
// could have interface
fieldSchemas.set(tab.name, {
additionalProperties: false,
type: 'object',
...childSchema
});
requiredFieldNames.add(tab.name);
} else {
Object.entries(childSchema.properties).forEach(([propName, propSchema])=>{
fieldSchemas.set(propName, propSchema);
});
childSchema.required.forEach((propName)=>{
requiredFieldNames.add(propName);
});
}
});
break;
}
case 'group':
{
fieldSchema = {
additionalProperties: false,
type: 'object',
...fieldsToJSONSchema(collectionIDFieldTypes, field.fields, interfaceNameDefinitions)
};
if (field.interfaceName) {
interfaceNameDefinitions.set(field.interfaceName, fieldSchema);
fieldSchema = {
$ref: `#/definitions/${field.interfaceName}`
};
}
break;
}
default:
{
break;
}
}
if (fieldSchema && (0, _types.fieldAffectsData)(field)) {
fieldSchemas.set(field.name, fieldSchema);
}
return fieldSchemas;
}, new Map())),
required: Array.from(requiredFieldNames)
};
}
function entityToJSONSchema(config, incomingEntity, interfaceNameDefinitions, defaultIDType) {
const entity = (0, _deepCopyObject.deepCopyObject)(incomingEntity);
const title = entity.typescript?.interface ? entity.typescript.interface : (0, _pluralize.singular)((0, _formatLabels.toWords)(entity.slug, true));
const idField = {
name: 'id',
required: true,
type: defaultIDType
};
const customIdField = entity.fields.find((field)=>(0, _types.fieldAffectsData)(field) && field.name === 'id');
if (customIdField && customIdField.type !== 'group' && customIdField.type !== 'tab') {
customIdField.required = true;
} else {
entity.fields.unshift(idField);
}
// mark timestamp fields required
if ('timestamps' in entity && entity.timestamps !== false) {
entity.fields = entity.fields.map((field)=>{
if ((0, _types.fieldAffectsData)(field) && (field.name === 'createdAt' || field.name === 'updatedAt')) {
return {
...field,
required: true
};
}
return field;
});
}
if ('auth' in entity && entity.auth && !entity.auth?.disableLocalStrategy) {
entity.fields.push({
name: 'password',
type: 'text'
});
}
// used for relationship fields, to determine whether to use a string or number type for the ID
const collectionIDFieldTypes = config.collections.reduce((acc, collection)=>{
const customCollectionIdField = collection.fields.find((field)=>'name' in field && field.name === 'id');
acc[collection.slug] = defaultIDType === 'text' ? 'string' : 'number';
if (customCollectionIdField) {
acc[collection.slug] = customCollectionIdField.type === 'number' ? 'number' : 'string';
}
return acc;
}, {});
return {
additionalProperties: false,
title,
type: 'object',
...fieldsToJSONSchema(collectionIDFieldTypes, entity.fields, interfaceNameDefinitions)
};
}
function configToJSONSchema(config, defaultIDType) {
// a mutable Map to store custom top-level `interfaceName` types. Fields with an `interfaceName` property will be moved to the top-level definitions here
const interfaceNameDefinitions = new Map();
// Collections and Globals have to be moved to the top-level definitions as well. Reason: The top-level type will be the `Config` type - we don't want all collection and global
// types to be inlined inside the `Config` type
const entityDefinitions = [
...config.globals,
...config.collections
].reduce((acc, entity)=>{
acc[entity.slug] = entityToJSONSchema(config, entity, interfaceNameDefinitions, defaultIDType);
return acc;
}, {});
return {
additionalProperties: false,
definitions: {
...entityDefinitions,
...Object.fromEntries(interfaceNameDefinitions)
},
// These properties here will be very simple, as all the complexity is in the definitions. These are just the properties for the top-level `Config` type
properties: {
collections: generateEntitySchemas(config.collections || []),
globals: generateEntitySchemas(config.globals || [])
},
required: [
'collections',
'globals'
],
title: 'Config',
type: 'object'
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsaXRpZXMvY29uZmlnVG9KU09OU2NoZW1hLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgSlNPTlNjaGVtYTQsIEpTT05TY2hlbWE0VHlwZU5hbWUgfSBmcm9tICdqc29uLXNjaGVtYSdcblxuaW1wb3J0IHsgc2luZ3VsYXIgfSBmcm9tICdwbHVyYWxpemUnXG5cbmltcG9ydCB0eXBlIHsgU2FuaXRpemVkQ29sbGVjdGlvbkNvbmZpZyB9IGZyb20gJy4uL2NvbGxlY3Rpb25zL2NvbmZpZy90eXBlcydcbmltcG9ydCB0eXBlIHsgU2FuaXRpemVkQ29uZmlnIH0gZnJvbSAnLi4vZXhwb3J0cy9jb25maWcnXG5pbXBvcnQgdHlwZSB7IEZpZWxkLCBGaWVsZEFmZmVjdGluZ0RhdGEsIE9wdGlvbiB9IGZyb20gJy4uL2ZpZWxkcy9jb25maWcvdHlwZXMnXG5pbXBvcnQgdHlwZSB7IFNhbml0aXplZEdsb2JhbENvbmZpZyB9IGZyb20gJy4uL2dsb2JhbHMvY29uZmlnL3R5cGVzJ1xuXG5pbXBvcnQgeyBmaWVsZEFmZmVjdHNEYXRhLCB0YWJIYXNOYW1lIH0gZnJvbSAnLi4vZmllbGRzL2NvbmZpZy90eXBlcydcbmltcG9ydCB7IGRlZXBDb3B5T2JqZWN0IH0gZnJvbSAnLi9kZWVwQ29weU9iamVjdCdcbmltcG9ydCB7IHRvV29yZHMgfSBmcm9tICcuL2Zvcm1hdExhYmVscydcblxuY29uc3QgZmllbGRJc1JlcXVpcmVkID0gKGZpZWxkOiBGaWVsZCkgPT4ge1xuICBjb25zdCBpc0NvbmRpdGlvbmFsID0gQm9vbGVhbihmaWVsZD8uYWRtaW4gJiYgZmllbGQ/LmFkbWluPy5jb25kaXRpb24pXG4gIGlmIChpc0NvbmRpdGlvbmFsKSByZXR1cm4gZmFsc2VcblxuICBjb25zdCBpc01hcmtlZFJlcXVpcmVkID0gJ3JlcXVpcmVkJyBpbiBmaWVsZCAmJiBmaWVsZC5yZXF1aXJlZCA9PT0gdHJ1ZVxuICBpZiAoZmllbGRBZmZlY3RzRGF0YShmaWVsZCkgJiYgaXNNYXJrZWRSZXF1aXJlZCkgcmV0dXJuIHRydWVcblxuICAvLyBpZiBhbnkgc3ViZmllbGRzIGFyZSByZXF1aXJlZCwgdGhpcyBmaWVsZCBpcyByZXF1aXJlZFxuICBpZiAoJ2ZpZWxkcycgaW4gZmllbGQgJiYgZmllbGQudHlwZSAhPT0gJ2FycmF5Jykge1xuICAgIHJldHVybiBmaWVsZC5maWVsZHMuc29tZSgoc3ViRmllbGQpID0+IGZpZWxkSXNSZXF1aXJlZChzdWJGaWVsZCkpXG4gIH1cblxuICAvLyBpZiBhbnkgdGFiIHN1YmZpZWxkcyBoYXZlIHJlcXVpcmVkIGZpZWxkcywgdGhpcyBmaWVsZCBpcyByZXF1aXJlZFxuICBpZiAoZmllbGQudHlwZSA9PT0gJ3RhYnMnKSB7XG4gICAgcmV0dXJuIGZpZWxkLnRhYnMuc29tZSgodGFiKSA9PiB7XG4gICAgICBpZiAoJ25hbWUnIGluIHRhYikge1xuICAgICAgICByZXR1cm4gdGFiLmZpZWxkcy5zb21lKChzdWJGaWVsZCkgPT4gZmllbGRJc1JlcXVpcmVkKHN1YkZpZWxkKSlcbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH0pXG4gIH1cblxuICByZXR1cm4gZmFsc2Vcbn1cblxuZnVuY3Rpb24gYnVpbGRPcHRpb25FbnVtcyhvcHRpb25zOiBPcHRpb25bXSk6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIG9wdGlvbnMubWFwKChvcHRpb24pID0+IHtcbiAgICBpZiAodHlwZW9mIG9wdGlvbiA9PT0gJ29iamVjdCcgJiYgJ3ZhbHVlJyBpbiBvcHRpb24pIHtcbiAgICAgIHJldHVybiBvcHRpb24udmFsdWVcbiAgICB9XG5cbiAgICByZXR1cm4gb3B0aW9uXG4gIH0pXG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRlRW50aXR5U2NoZW1hcyhcbiAgZW50aXRpZXM6IChTYW5pdGl6ZWRDb2xsZWN0aW9uQ29uZmlnIHwgU2FuaXRpemVkR2xvYmFsQ29uZmlnKVtdLFxuKTogSlNPTlNjaGVtYTQge1xuICBjb25zdCBwcm9wZXJ0aWVzID0gWy4uLmVudGl0aWVzXS5yZWR1Y2UoKGFjYywgeyBzbHVnIH0pID0+IHtcbiAgICBhY2Nbc2x1Z10gPSB7XG4gICAgICAkcmVmOiBgIy9kZWZpbml0aW9ucy8ke3NsdWd9YCxcbiAgICB9XG5cbiAgICByZXR1cm4gYWNjXG4gIH0sIHt9KVxuXG4gIHJldHVybiB7XG4gICAgYWRkaXRpb25hbFByb3BlcnRpZXM6IGZhbHNlLFxuICAgIHByb3BlcnRpZXMsXG4gICAgcmVxdWlyZWQ6IE9iamVjdC5rZXlzKHByb3BlcnRpZXMpLFxuICAgIHR5cGU6ICdvYmplY3QnLFxuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyBhIEpTT04gU2NoZW1hIFR5cGUgd2l0aCAnbnVsbCcgYWRkZWQgaWYgdGhlIGZpZWxkIGlzIG5vdCByZXF1aXJlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdpdGhOdWxsYWJsZUpTT05TY2hlbWFUeXBlKFxuICBmaWVsZFR5cGU6IEpTT05TY2hlbWE0VHlwZU5hbWUsXG4gIGlzUmVxdWlyZWQ6IGJvb2xlYW4sXG4pOiBKU09OU2NoZW1hNFR5cGVOYW1lIHwgSlNPTlNjaGVtYTRUeXBlTmFtZVtdIHtcbiAgY29uc3QgZmllbGRUeXBlcyA9IFtmaWVsZFR5cGVdXG4gIGlmIChpc1JlcXVpcmVkKSByZXR1cm4gZmllbGRUeXBlXG4gIGZpZWxkVHlwZXMucHVzaCgnbnVsbCcpXG4gIHJldHVybiBmaWVsZFR5cGVzXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmaWVsZHNUb0pTT05TY2hlbWEoXG4gIGNvbGxlY3Rpb25JREZpZWxkVHlwZXM6IHsgW2tleTogc3RyaW5nXTogJ251bWJlcicgfCAnc3RyaW5nJyB9LFxuICBmaWVsZHM6IEZpZWxkW10sXG4gIC8qKlxuICAgKiBBbGxvd3MgeW91IHRvIGRlZmluZSBuZXcgdG9wLWxldmVsIGludGVyZmFjZXMgdGhhdCBjYW4gYmUgcmUtdXNlZCBpbiB0aGUgb3V0cHV0IHNjaGVtYS5cbiAgICovXG4gIGludGVyZmFjZU5hbWVEZWZpbml0aW9uczogTWFwPHN0cmluZywgSlNPTlNjaGVtYTQ+LFxuKToge1xuICBwcm9wZXJ0aWVzOiB7XG4gICAgW2s6IHN0cmluZ106IEpTT05TY2hlbWE0XG4gIH1cbiAgcmVxdWlyZWQ6IHN0cmluZ1tdXG59IHtcbiAgY29uc3QgcmVxdWlyZWRGaWVsZE5hbWVzID0gbmV3IFNldDxzdHJpbmc+KClcblxuICByZXR1cm4ge1xuICAgIHByb3BlcnRpZXM6IE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgIGZpZWxkcy5yZWR1Y2UoKGZpZWxkU2NoZW1hcywgZmllbGQpID0+IHtcbiAgICAgICAgY29uc3QgaXNSZXF1aXJlZCA9IGZpZWxkQWZmZWN0c0RhdGEoZmllbGQpICYmIGZpZWxkSXNSZXF1aXJlZChmaWVsZClcbiAgICAgICAgaWYgKGlzUmVxdWlyZWQpIHJlcXVpcmVkRmllbGROYW1lcy5hZGQoZmllbGQubmFtZSlcblxuICAgICAgICBsZXQgZmllbGRTY2hlbWE6IEpTT05TY2hlbWE0XG4gICAgICAgIHN3aXRjaCAoZmllbGQudHlwZSkge1xuICAgICAgICAgIGNhc2UgJ3RleHQnOlxuICAgICAgICAgICAgaWYgKGZpZWxkLmhhc01hbnkgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgZmllbGRTY2hlbWEgPSB7XG4gICAgICAgICAgICAgICAgaXRlbXM6IHsgdHlwZTogJ3N0cmluZycgfSxcbiAgICAgICAgICAgICAgICB0eXBlOiB3aXRoTnVsbGFibGVKU09OU2NoZW1hVHlwZSgnYXJyYXknLCBpc1JlcXVpcmVkKSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZmllbGRTY2hlbWEgPSB7IHR5cGU6IHdpdGhOdWxsYWJsZUpTT05TY2hlbWFUeXBlKCdzdHJpbmcnLCBpc1JlcXVpcmVkKSB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIGNhc2UgJ3RleHRhcmVhJzpcbiAgICAgICAgICBjYXNlICdjb2RlJzpcbiAgICAgICAgICBjYXNlICdlbWFpbCc6XG4gICAgICAgICAgY2FzZSAnZGF0ZSc6IHtcbiAgICAgICAgICAgIGZpZWxkU2NoZW1hID0geyB0eXBlOiB3aXRoTnVsbGFibGVKU09OU2NoZW1hVHlwZSgnc3RyaW5nJywgaXNSZXF1aXJlZCkgfVxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjYXNlICdudW1iZXInOiB7XG4gICAgICAgICAgICBpZiAoZmllbGQuaGFzTWFueSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICBmaWVsZFNjaGVtYSA9IHtcbiAgICAgICAgICAgICAgICBpdGVtczogeyB0eXBlOiAnbnVtYmVyJyB9LFxuICAgICAgICAgICAgICAgIHR5cGU6IHdpdGhOdWxsYWJsZUpTT05TY2hlbWFUeXBlKCdhcnJheScsIGlzUmVxdWlyZWQpLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBmaWVsZFNjaGVtYSA9IHsgdHlwZTogd2l0aE51bGxhYmxlSlNPTlNjaGVtYVR5cGUoJ251bWJlcicsIGlzUmVxdWlyZWQpIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY2FzZSAnY2hlY2tib3gnOiB7XG4gICAgICAgICAgICBmaWVsZFNjaGVtYSA9IHsgdHlwZTogd2l0aE51bGxhYmxlSlNPTlNjaGVtYVR5cGUoJ2Jvb2xlYW4nLCBpc1JlcXVpcmVkKSB9XG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNhc2UgJ2pzb24nOiB7XG4gICAgICAgICAgICBmaWVsZFNjaGVtYSA9IHtcbiAgICAgICAgICAgICAgdHlwZTogWydvYmplY3QnLCAnYXJyYXknLCAnc3RyaW5nJywgJ251bWJlcicsICdib29sZWFuJywgJ251bGwnXSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY2FzZSAncmljaFRleHQnOiB7XG4gICAgICAgICAgICBpZiAoZmllbGQuZWRpdG9yLm91dHB1dFNjaGVtYSkge1xuICAgICAgICAgICAgICBmaWVsZFNjaGVtYSA9IGZpZWxkLmVkaXRvci5vdXRwdXRTY2hlbWEoe1xuICAgICAgICAgICAgICAgIGZpZWxkLFxuICAgICAgICAgICAgICAgIGludGVyZmFjZU5hbWVEZWZpbml0aW9ucyxcbiAgICAgICAgICAgICAgICBpc1JlcXVpcmVkLFxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gTWFpbnRhaW4gYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgd2l0aCBleGlzdGluZyByaWNoIHRleHQgZWRpdG9yc1xuICAgICAgICAgICAgICBmaWVsZFNjaGVtYSA9IHtcbiAgICAgICAgICAgICAgICBpdGVtczoge1xuICAgICAgICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB0eXBlOiB3aXRoTnVsbGFibGVKU09OU2NoZW1hVHlwZSgnYXJyYXknLCBpc1JlcXVpcmVkKSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNhc2UgJ3JhZGlvJzoge1xuICAgICAgICAgICAgZmllbGRTY2hlbWEgPSB7XG4gICAgICAgICAgICAgIGVudW06IGJ1aWxkT3B0aW9uRW51bXMoZmllbGQub3B0aW9ucyksXG4gICAgICAgICAgICAgIHR5cGU6IHdpdGhOdWxsYWJsZUpTT05TY2hlbWFUeXBlKCdzdHJpbmcnLCBpc1JlcXVpcmVkKSxcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjYXNlICdzZWxlY3QnOiB7XG4gICAgICAgICAgICBjb25zdCBvcHRpb25FbnVtcyA9IGJ1aWxkT3B0aW9uRW51bXMoZmllbGQub3B0aW9ucylcblxuICAgICAgICAgICAgaWYgKGZpZWxkLmhhc01hbnkpIHtcbiAgICAgICAgICAgICAgZmllbGRTY2hlbWEgPSB7XG4gICAgICAgICAgICAgICAgaXRlbXM6IHtcbiAgICAgICAgICAgICAgICAgIGVudW06IG9wdGlvbkVudW1zLFxuICAgICAgICAgICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB0eXBlOiB3aXRoTnVsbGFibGVKU09OU2NoZW1hVHlwZSgnYXJyYXknLCBpc1JlcXVpcmVkKSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZmllbGRTY2hlbWEgPSB7XG4gICAgICAgICAgICAgICAgZW51bTogb3B0aW9uRW51bXMsXG4gICAgICAgICAgICAgICAgdHlwZTogd2l0aE51bGxhYmxlSlNPTlNjaGVtYVR5cGUoJ3N0cmluZycsIGlzUmVxdWlyZWQpLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY2FzZSAncG9pbnQnOiB7XG4gICAgICAgICAgICBmaWVsZFNjaGVtYSA9IHtcbiAgICAgICAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIHR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIG1heEl0ZW1zOiAyLFxuICAgICAgICAgICAgICBtaW5JdGVtczogMixcbiAgICAgICAgICAgICAgdHlwZTogd2l0aE51bGxhYmxlSlNPTlNjaGVtYVR5cGUoJ2FycmF5JywgaXNSZXF1aXJlZCksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNhc2UgJ3JlbGF0aW9uc2hpcCc6IHtcbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGZpZWxkLnJlbGF0aW9uVG8pKSB7XG4gICAgICAgICAgICAgIGlmIChmaWVsZC5oYXNNYW55KSB7XG4gICAgICAgICAgICAgICAgZmllbGRTY2hlbWEgPSB7XG4gICAgICAgICAgICAgICAgICBpdGVtczoge1xuICAgICAgICAgICAgICAgICAgICBvbmVPZjogZmllbGQucmVsYXRpb25Uby5tYXAoKHJlbGF0aW9uKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVsYXRpb25Ubzoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0OiByZWxhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmVPZjogW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBjb2xsZWN0aW9uSURGaWVsZFR5cGVzW3JlbGF0aW9uXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRyZWY6IGAjL2RlZmluaXRpb25zLyR7cmVsYXRpb259YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICByZXF1aXJlZDogWyd2YWx1ZScsICdyZWxhdGlvblRvJ10sXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIHR5cGU6IHdpdGhOdWxsYWJsZUpTT05TY2hlbWFUeXBlKCdhcnJheScsIGlzUmVxdWlyZWQpLFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBmaWVsZFNjaGVtYSA9IHtcbiAgICAgICAgICAgICAgICAgIG9uZU9mOiBmaWVsZC5yZWxhdGlvblRvLm1hcCgocmVsYXRpb24pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICBhZGRpdGlvbmFsUHJvcGVydGllczogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVsYXRpb25Ubzoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdDogcmVsYXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgb25lT2Y6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBjb2xsZWN0aW9uSURGaWVsZFR5cGVzW3JlbGF0aW9uXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRyZWY6IGAjL2RlZmluaXRpb25zLyR7cmVsYXRpb259YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiBbJ3ZhbHVlJywgJ3JlbGF0aW9uVG8nXSxcbiAgICAgICAgICAgICAgICAgICAgICB0eXBlOiB3aXRoTnVsbGFibGVKU09OU2NoZW1hVHlwZSgnb2JqZWN0JywgaXNSZXF1aXJlZCksXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChmaWVsZC5oYXNNYW55KSB7XG4gICAgICAgICAgICAgIGZpZWxkU2NoZW1hID0ge1xuICAgICAgICAgICAgICAgIGl0ZW1zOiB7XG4gICAgICAgICAgICAgICAgICBvbmVPZjogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgdHlwZTogY29sbGVjdGlvbklERmllbGRUeXBlc1tmaWVsZC5yZWxhdGlvblRvXSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICRyZWY6IGAjL2RlZmluaXRpb25zLyR7ZmllbGQucmVsYXRpb25Ub31gLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHR5cGU6IHdpdGhOdWxsYWJsZUpTT05TY2hlbWFUeXBlKCdhcnJheScsIGlzUmVxdWlyZWQpLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBmaWVsZFNjaGVtYSA9IHtcbiAgICAgICAgICAgICAgICBvbmVPZjogW1xuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiB3aXRoTnVsbGFibGVKU09OU2NoZW1hVHlwZShcbiAgICAgICAgICAgICAgICAgICAgICBjb2xsZWN0aW9uSURGaWVsZFR5cGVzW2ZpZWxkLnJlbGF0aW9uVG9dLFxuICAgICAgICAgICAgICAgICAgICAgIGlzUmVxdWlyZWQsXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAkcmVmOiBgIy9kZWZpbml0aW9ucy8ke2ZpZWxkLnJlbGF0aW9uVG99YCxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNhc2UgJ3VwbG9hZCc6IHtcbiAgICAgICAgICAgIGZpZWxkU2NoZW1hID0ge1xuICAgICAgICAgICAgICBvbmVPZjogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIHR5cGU6IGNvbGxlY3Rpb25JREZpZWxkVHlwZXNbZmllbGQucmVsYXRpb25Ub10sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAkcmVmOiBgIy9kZWZpbml0aW9ucy8ke2ZpZWxkLnJlbGF0aW9uVG99YCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc1JlcXVpcmVkKSBmaWVsZFNjaGVtYS5vbmVPZi5wdXNoKHsgdHlwZTogJ251bGwnIH0pXG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNhc2UgJ2Jsb2Nrcyc6IHtcbiAgICAgICAgICAgIGZpZWxkU2NoZW1hID0ge1xuICAgICAgICAgICAgICBpdGVtczoge1xuICAgICAgICAgICAgICAgIG9uZU9mOiBmaWVsZC5ibG9ja3MubWFwKChibG9jaykgPT4ge1xuICAgICAgICAgICAgICAgICAgY29uc3QgYmxvY2tGaWVsZFNjaGVtYXMgPSBmaWVsZHNUb0pTT05TY2hlbWEoXG4gICAgICAgICAgICAgICAgICAgIGNvbGxlY3Rpb25JREZpZWxkVHlwZXMsXG4gICAgICAgICAgICAgICAgICAgIGJsb2NrLmZpZWxkcyxcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJmYWNlTmFtZURlZmluaXRpb25zLFxuICAgICAgICAgICAgICAgICAgKVxuXG4gICAgICAgICAgICAgICAgICBjb25zdCBibG9ja1NjaGVtYTogSlNPTlNjaGVtYTQgPSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgICAgICAgIC4uLmJsb2NrRmllbGRTY2hlbWFzLnByb3BlcnRpZXMsXG4gICAgICAgICAgICAgICAgICAgICAgYmxvY2tUeXBlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdDogYmxvY2suc2x1ZyxcbiAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICByZXF1aXJlZDogWydibG9ja1R5cGUnLCAuLi5ibG9ja0ZpZWxkU2NoZW1hcy5yZXF1aXJlZF0sXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICBpZiAoYmxvY2suaW50ZXJmYWNlTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICBpbnRlcmZhY2VOYW1lRGVmaW5pdGlvbnMuc2V0KGJsb2NrLmludGVyZmFjZU5hbWUsIGJsb2NrU2NoZW1hKVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgJHJlZjogYCMvZGVmaW5pdGlvbnMvJHtibG9jay5pbnRlcmZhY2VOYW1lfWAsXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgcmV0dXJuIGJsb2NrU2NoZW1hXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHR5cGU6IHdpdGhOdWxsYWJsZUpTT05TY2hlbWFUeXBlKCdhcnJheScsIGlzUmVxdWlyZWQpLFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjYXNlICdhcnJheSc6IHtcbiAgICAgICAgICAgIGZpZWxkU2NoZW1hID0ge1xuICAgICAgICAgICAgICBpdGVtczoge1xuICAgICAgICAgICAgICAgIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgICAgICAuLi5maWVsZHNUb0pTT05TY2hlbWEoXG4gICAgICAgICAgICAgICAgICBjb2xsZWN0aW9uSURGaWVsZFR5cGVzLFxuICAgICAgICAgICAgICAgICAgZmllbGQuZmllbGRzLFxuICAgICAgICAgICAgICAgICAgaW50ZXJmYWNlTmFtZURlZmluaXRpb25zLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHR5cGU6IHdpdGhOdWxsYWJsZUpTT05TY2hlbWFUeXBlKCdhcnJheScsIGlzUmVxdWlyZWQpLFxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZmllbGQuaW50ZXJmYWNlTmFtZSkge1xuICAgICAgICAgICAgICBpbnRlcmZhY2VOYW1lRGVmaW5pdGlvbnMuc2V0KGZpZWxkLmludGVyZmFjZU5hbWUsIGZpZWxkU2NoZW1hKVxuXG4gICAgICAgICAgICAgIGZpZWxkU2NoZW1hID0ge1xuICAgICAgICAgICAgICAgICRyZWY6IGAjL2RlZmluaXRpb25zLyR7ZmllbGQuaW50ZXJmYWNlTmFtZX1gLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNhc2UgJ3Jvdyc6XG4gICAgICAgICAgY2FzZSAnY29sbGFwc2libGUnOiB7XG4gICAgICAgICAgICBjb25zdCBjaGlsZFNjaGVtYSA9IGZpZWxkc1RvSlNPTlNjaGVtYShcbiAgICAgICAgICAgICAgY29sbGVjdGlvbklERmllbGRUeXBlcyxcbiAgICAgICAgICAgICAgZmllbGQuZmllbGRzLFxuICAgICAgICAgICAgICBpbnRlcmZhY2VOYW1lRGVmaW5pdGlvbnMsXG4gICAgICAgICAgICApXG4gICAgICAgICAgICBPYmplY3QuZW50cmllcyhjaGlsZFNjaGVtYS5wcm9wZXJ0aWVzKS5mb3JFYWNoKChbcHJvcE5hbWUsIHByb3BTY2hlbWFdKSA9PiB7XG4gICAgICAgICAgICAgIGZpZWxkU2NoZW1hcy5zZXQocHJvcE5hbWUsIHByb3BTY2hlbWEpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgY2hpbGRTY2hlbWEucmVxdWlyZWQuZm9yRWFjaCgocHJvcE5hbWUpID0+IHtcbiAgICAgICAgICAgICAgcmVxdWlyZWRGaWVsZE5hbWVzLmFkZChwcm9wTmFtZSlcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNhc2UgJ3RhYnMnOiB7XG4gICAgICAgICAgICBmaWVsZC50YWJzLmZvckVhY2goKHRhYikgPT4ge1xuICAgICAgICAgICAgICBjb25zdCBjaGlsZFNjaGVtYSA9IGZpZWxkc1RvSlNPTlNjaGVtYShcbiAgICAgICAgICAgICAgICBjb2xsZWN0aW9uSURGaWVsZFR5cGVzLFxuICAgICAgICAgICAgICAgIHRhYi5maWVsZHMsXG4gICAgICAgICAgICAgICAgaW50ZXJmYWNlTmFtZURlZmluaXRpb25zLFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIGlmICh0YWJIYXNOYW1lKHRhYikpIHtcbiAgICAgICAgICAgICAgICAvLyBjb3VsZCBoYXZlIGludGVyZmFjZVxuICAgICAgICAgICAgICAgIGZpZWxkU2NoZW1hcy5zZXQodGFiLm5hbWUsIHtcbiAgICAgICAgICAgICAgICAgIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICAgICAgLi4uY2hpbGRTY2hlbWEsXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICByZXF1aXJlZEZpZWxkTmFtZXMuYWRkKHRhYi5uYW1lKVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIE9iamVjdC5lbnRyaWVzKGNoaWxkU2NoZW1hLnByb3BlcnRpZXMpLmZvckVhY2goKFtwcm9wTmFtZSwgcHJvcFNjaGVtYV0pID0+IHtcbiAgICAgICAgICAgICAgICAgIGZpZWxkU2NoZW1hcy5zZXQocHJvcE5hbWUsIHByb3BTY2hlbWEpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICBjaGlsZFNjaGVtYS5yZXF1aXJlZC5mb3JFYWNoKChwcm9wTmFtZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgcmVxdWlyZWRGaWVsZE5hbWVzLmFkZChwcm9wTmFtZSlcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjYXNlICdncm91cCc6IHtcbiAgICAgICAgICAgIGZpZWxkU2NoZW1hID0ge1xuICAgICAgICAgICAgICBhZGRpdGlvbmFsUHJvcGVydGllczogZmFsc2UsXG4gICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICAuLi5maWVsZHNUb0pTT05TY2hlbWEoY29sbGVjdGlvbklERmllbGRUeXBlcywgZmllbGQuZmllbGRzLCBpbnRlcmZhY2VOYW1lRGVmaW5pdGlvbnMpLFxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZmllbGQuaW50ZXJmYWNlTmFtZSkge1xuICAgICAgICAgICAgICBpbnRlcmZhY2VOYW1lRGVmaW5pdGlvbnMuc2V0KGZpZWxkLmludGVyZmFjZU5hbWUsIGZpZWxkU2NoZW1hKVxuXG4gICAgICAgICAgICAgIGZpZWxkU2NoZW1hID0ge1xuICAgICAgICAgICAgICAgICRyZWY6IGAjL2RlZmluaXRpb25zLyR7ZmllbGQuaW50ZXJmYWNlTmFtZX1gLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZpZWxkU2NoZW1hICYmIGZpZWxkQWZmZWN0c0RhdGEoZmllbGQpKSB7XG4gICAgICAgICAgZmllbGRTY2hlbWFzLnNldChmaWVsZC5uYW1lLCBmaWVsZFNjaGVtYSlcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmaWVsZFNjaGVtYXNcbiAgICAgIH0sIG5ldyBNYXA8c3RyaW5nLCBKU09OU2NoZW1hND4oKSksXG4gICAgKSxcbiAgICByZXF1aXJlZDogQXJyYXkuZnJvbShyZXF1aXJlZEZpZWxkTmFtZXMpLFxuICB9XG59XG5cbi8vIFRoaXMgZnVuY3Rpb24gaXMgcGFydCBvZiB0aGUgcHVibGljIEFQSSBhbmQgaXMgZXhwb3J0ZWQgdGhyb3VnaCBwYXlsb2FkL3V0aWxpdGllc1xuZXhwb3J0IGZ1bmN0aW9uIGVudGl0eVRvSlNPTlNjaGVtYShcbiAgY29uZmlnOiBTYW5pdGl6ZWRDb25maWcsXG4gIGluY29taW5nRW50aXR5OiBTYW5pdGl6ZWRDb2xsZWN0aW9uQ29uZmlnIHwgU2FuaXRpemVkR2xvYmFsQ29uZmlnLFxuICBpbnRlcmZhY2VOYW1lRGVmaW5pdGlvbnM6IE1hcDxzdHJpbmcsIEpTT05TY2hlbWE0PixcbiAgZGVmYXVsdElEVHlwZTogJ251bWJlcicgfCAndGV4dCcsXG4pOiBKU09OU2NoZW1hNCB7XG4gIGNvbnN0IGVudGl0eTogU2FuaXRpemVkQ29sbGVjdGlvbkNvbmZpZyB8IFNhbml0aXplZEdsb2JhbENvbmZpZyA9IGRlZXBDb3B5T2JqZWN0KGluY29taW5nRW50aXR5KVxuICBjb25zdCB0aXRsZSA9IGVudGl0eS50eXBlc2NyaXB0Py5pbnRlcmZhY2VcbiAgICA/IGVudGl0eS50eXBlc2NyaXB0LmludGVyZmFjZVxuICAgIDogc2luZ3VsYXIodG9Xb3JkcyhlbnRpdHkuc2x1ZywgdHJ1ZSkpXG5cbiAgY29uc3QgaWRGaWVsZDogRmllbGRBZmZlY3RpbmdEYXRhID0geyBuYW1lOiAnaWQnLCByZXF1aXJlZDogdHJ1ZSwgdHlwZTogZGVmYXVsdElEVHlwZSBhcyAndGV4dCcgfVxuICBjb25zdCBjdXN0b21JZEZpZWxkID0gZW50aXR5LmZpZWxkcy5maW5kKFxuICAgIChmaWVsZCkgPT4gZmllbGRBZmZlY3RzRGF0YShmaWVsZCkgJiYgZmllbGQubmFtZSA9PT0gJ2lkJyxcbiAgKSBhcyBGaWVsZEFmZmVjdGluZ0RhdGFcblxuICBpZiAoY3VzdG9tSWRGaWVsZCAmJiBjdXN0b21JZEZpZWxkLnR5cGUgIT09ICdncm91cCcgJiYgY3VzdG9tSWRGaWVsZC50eXBlICE9PSAndGFiJykge1xuICAgIGN1c3RvbUlkRmllbGQucmVxdWlyZWQgPSB0cnVlXG4gIH0gZWxzZSB7XG4gICAgZW50aXR5LmZpZWxkcy51bnNoaWZ0KGlkRmllbGQpXG4gIH1cblxuICAvLyBtYXJrIHRpbWVzdGFtcCBmaWVsZHMgcmVxdWlyZWRcbiAgaWYgKCd0aW1lc3RhbXBzJyBpbiBlbnRpdHkgJiYgZW50aXR5LnRpbWVzdGFtcHMgIT09IGZhbHNlKSB7XG4gICAgZW50aXR5LmZpZWxkcyA9IGVudGl0eS5maWVsZHMubWFwKChmaWVsZCkgPT4ge1xuICAgICAgaWYgKGZpZWxkQWZmZWN0c0RhdGEoZmllbGQpICYmIChmaWVsZC5uYW1lID09PSAnY3JlYXRlZEF0JyB8fCBmaWVsZC5uYW1lID09PSAndXBkYXRlZEF0JykpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5maWVsZCxcbiAgICAgICAgICByZXF1aXJlZDogdHJ1ZSxcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGZpZWxkXG4gICAgfSlcbiAgfVxuXG4gIGlmICgnYXV0aCcgaW4gZW50aXR5ICYmIGVudGl0eS5hdXRoICYmICFlbnRpdHkuYXV0aD8uZGlzYWJsZUxvY2FsU3RyYXRlZ3kpIHtcbiAgICBlbnRpdHkuZmllbGRzLnB1c2goe1xuICAgICAgbmFtZTogJ3Bhc3N3b3JkJyxcbiAgICAgIHR5cGU6ICd0ZXh0JyxcbiAgICB9KVxuICB9XG5cbiAgLy8gdXNlZCBmb3IgcmVsYXRpb25zaGlwIGZpZWxkcywgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgdG8gdXNlIGEgc3RyaW5nIG9yIG51bWJlciB0eXBlIGZvciB0aGUgSURcbiAgY29uc3QgY29sbGVjdGlvbklERmllbGRUeXBlczogeyBba2V5OiBzdHJpbmddOiAnbnVtYmVyJyB8ICdzdHJpbmcnIH0gPSBjb25maWcuY29sbGVjdGlvbnMucmVkdWNlKFxuICAgIChhY2MsIGNvbGxlY3Rpb24pID0+IHtcbiAgICAgIGNvbnN0IGN1c3RvbUNvbGxlY3Rpb25JZEZpZWxkID0gY29sbGVjdGlvbi5maWVsZHMuZmluZChcbiAgICAgICAgKGZpZWxkKSA9PiAnbmFtZScgaW4gZmllbGQgJiYgZmllbGQubmFtZSA9PT0gJ2lkJyxcbiAgICAgIClcblxuICAgICAgYWNjW2NvbGxlY3Rpb24uc2x1Z10gPSBkZWZhdWx0SURUeXBlID09PSAndGV4dCcgPyAnc3RyaW5nJyA6ICdudW1iZXInXG5cbiAgICAgIGlmIChjdXN0b21Db2xsZWN0aW9uSWRGaWVsZCkge1xuICAgICAgICBhY2NbY29sbGVjdGlvbi5zbHVnXSA9IGN1c3RvbUNvbGxlY3Rpb25JZEZpZWxkLnR5cGUgPT09ICdudW1iZXInID8gJ251bWJlcicgOiAnc3RyaW5nJ1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gYWNjXG4gICAgfSxcbiAgICB7fSxcbiAgKVxuXG4gIHJldHVybiB7XG4gICAgYWRkaXRpb25hbFByb3BlcnRpZXM6IGZhbHNlLFxuICAgIHRpdGxlLFxuICAgIHR5cGU6ICdvYmplY3QnLFxuICAgIC4uLmZpZWxkc1RvSlNPTlNjaGVtYShjb2xsZWN0aW9uSURGaWVsZFR5cGVzLCBlbnRpdHkuZmllbGRzLCBpbnRlcmZhY2VOYW1lRGVmaW5pdGlvbnMpLFxuICB9XG59XG5cbi8qKlxuICogVGhpcyBpcyB1c2VkIGZvciBnZW5lcmF0aW5nIHRoZSBUeXBlU2NyaXB0IHR5cGVzIChwYXlsb2FkLXR5cGVzLnRzKSB3aXRoIHRoZSBwYXlsb2FkIGdlbmVyYXRlOnR5cGVzIGNvbW1hbmQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25maWdUb0pTT05TY2hlbWEoXG4gIGNvbmZpZzogU2FuaXRpemVkQ29uZmlnLFxuICBkZWZhdWx0SURUeXBlPzogJ251bWJlcicgfCAndGV4dCcsXG4pOiBKU09OU2NoZW1hNCB7XG4gIC8vIGEgbXV0YWJsZSBNYXAgdG8gc3RvcmUgY3VzdG9tIHRvcC1sZXZlbCBgaW50ZXJmYWNlTmFtZWAgdHlwZXMuIEZpZWxkcyB3aXRoIGFuIGBpbnRlcmZhY2VOYW1lYCBwcm9wZXJ0eSB3aWxsIGJlIG1vdmVkIHRvIHRoZSB0b3AtbGV2ZWwgZGVmaW5pdGlvbnMgaGVyZVxuICBjb25zdCBpbnRlcmZhY2VOYW1lRGVmaW5pdGlvbnM6IE1hcDxzdHJpbmcsIEpTT05TY2hlbWE0PiA9IG5ldyBNYXAoKVxuXG4gIC8vIENvbGxlY3Rpb25zIGFuZCBHbG9iYWxzIGhhdmUgdG8gYmUgbW92ZWQgdG8gdGhlIHRvcC1sZXZlbCBkZWZpbml0aW9ucyBhcyB3ZWxsLiBSZWFzb246IFRoZSB0b3AtbGV2ZWwgdHlwZSB3aWxsIGJlIHRoZSBgQ29uZmlnYCB0eXBlIC0gd2UgZG9uJ3Qgd2FudCBhbGwgY29sbGVjdGlvbiBhbmQgZ2xvYmFsXG4gIC8vIHR5cGVzIHRvIGJlIGlubGluZWQgaW5zaWRlIHRoZSBgQ29uZmlnYCB0eXBlXG4gIGNvbnN0IGVudGl0eURlZmluaXRpb25zOiB7IFtrOiBzdHJpbmddOiBKU09OU2NoZW1hNCB9ID0gW1xuICAgIC4uLmNvbmZpZy5nbG9iYWxzLFxuICAgIC4uLmNvbmZpZy5jb2xsZWN0aW9ucyxcbiAgXS5yZWR1Y2UoKGFjYywgZW50aXR5KSA9PiB7XG4gICAgYWNjW2VudGl0eS5zbHVnXSA9IGVudGl0eVRvSlNPTlNjaGVtYShjb25maWcsIGVudGl0eSwgaW50ZXJmYWNlTmFtZURlZmluaXRpb25zLCBkZWZhdWx0SURUeXBlKVxuICAgIHJldHVybiBhY2NcbiAgfSwge30pXG5cbiAgcmV0dXJuIHtcbiAgICBhZGRpdGlvbmFsUHJvcGVydGllczogZmFsc2UsXG4gICAgZGVmaW5pdGlvbnM6IHsgLi4uZW50aXR5RGVmaW5pdGlvbnMsIC4uLk9iamVjdC5mcm9tRW50cmllcyhpbnRlcmZhY2VOYW1lRGVmaW5pdGlvbnMpIH0sXG4gICAgLy8gVGhlc2UgcHJvcGVydGllcyBoZXJlIHdpbGwgYmUgdmVyeSBzaW1wbGUsIGFzIGFsbCB0aGUgY29tcGxleGl0eSBpcyBpbiB0aGUgZGVmaW5pdGlvbnMuIFRoZXNlIGFyZSBqdXN0IHRoZSBwcm9wZXJ0aWVzIGZvciB0aGUgdG9wLWxldmVsIGBDb25maWdgIHR5cGVcbiAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICBjb2xsZWN0aW9uczogZ2VuZXJhdGVFbnRpdHlTY2hlbWFzKGNvbmZpZy5jb2xsZWN0aW9ucyB8fCBbXSksXG4gICAgICBnbG9iYWxzOiBnZW5lcmF0ZUVudGl0eVNjaGVtYXMoY29uZmlnLmdsb2JhbHMgfHwgW10pLFxuICAgIH0sXG4gICAgcmVxdWlyZWQ6IFsnY29sbGVjdGlvbnMnLCAnZ2xvYmFscyddLFxuICAgIHRpdGxlOiAnQ29uZmlnJyxcbiAgICB0eXBlOiAnb2JqZWN0JyxcbiAgfVxufVxuIl0sIm5hbWVzIjpbImNvbmZpZ1RvSlNPTlNjaGVtYSIsImVudGl0eVRvSlNPTlNjaGVtYSIsImZpZWxkc1RvSlNPTlNjaGVtYSIsIndpdGhOdWxsYWJsZUpTT05TY2hlbWFUeXBlIiwiZmllbGRJc1JlcXVpcmVkIiwiZmllbGQiLCJpc0NvbmRpdGlvbmFsIiwiQm9vbGVhbiIsImFkbWluIiwiY29uZGl0aW9uIiwiaXNNYXJrZWRSZXF1aXJlZCIsInJlcXVpcmVkIiwiZmllbGRBZmZlY3RzRGF0YSIsInR5cGUiLCJmaWVsZHMiLCJzb21lIiwic3ViRmllbGQiLCJ0YWJzIiwidGFiIiwiYnVpbGRPcHRpb25FbnVtcyIsIm9wdGlvbnMiLCJtYXAiLCJvcHRpb24iLCJ2YWx1ZSIsImdlbmVyYXRlRW50aXR5U2NoZW1hcyIsImVudGl0aWVzIiwicHJvcGVydGllcyIsInJlZHVjZSIsImFjYyIsInNsdWciLCIkcmVmIiwiYWRkaXRpb25hbFByb3BlcnRpZXMiLCJPYmplY3QiLCJrZXlzIiwiZmllbGRUeXBlIiwiaXNSZXF1aXJlZCIsImZpZWxkVHlwZXMiLCJwdXNoIiwiY29sbGVjdGlvbklERmllbGRUeXBlcyIsImludGVyZmFjZU5hbWVEZWZpbml0aW9ucyIsInJlcXVpcmVkRmllbGROYW1lcyIsIlNldCIsImZyb21FbnRyaWVzIiwiZmllbGRTY2hlbWFzIiwiYWRkIiwibmFtZSIsImZpZWxkU2NoZW1hIiwiaGFzTWFueSIsIml0ZW1zIiwiZWRpdG9yIiwib3V0cHV0U2NoZW1hIiwiZW51bSIsIm9wdGlvbkVudW1zIiwibWF4SXRlbXMiLCJtaW5JdGVtcyIsIkFycmF5IiwiaXNBcnJheSIsInJlbGF0aW9uVG8iLCJvbmVPZiIsInJlbGF0aW9uIiwiY29uc3QiLCJibG9ja3MiLCJibG9jayIsImJsb2NrRmllbGRTY2hlbWFzIiwiYmxvY2tTY2hlbWEiLCJibG9ja1R5cGUiLCJpbnRlcmZhY2VOYW1lIiwic2V0IiwiY2hpbGRTY2hlbWEiLCJlbnRyaWVzIiwiZm9yRWFjaCIsInByb3BOYW1lIiwicHJvcFNjaGVtYSIsInRhYkhhc05hbWUiLCJNYXAiLCJmcm9tIiwiY29uZmlnIiwiaW5jb21pbmdFbnRpdHkiLCJkZWZhdWx0SURUeXBlIiwiZW50aXR5IiwiZGVlcENvcHlPYmplY3QiLCJ0aXRsZSIsInR5cGVzY3JpcHQiLCJpbnRlcmZhY2UiLCJzaW5ndWxhciIsInRvV29yZHMiLCJpZEZpZWxkIiwiY3VzdG9tSWRGaWVsZCIsImZpbmQiLCJ1bnNoaWZ0IiwidGltZXN0YW1wcyIsImF1dGgiLCJkaXNhYmxlTG9jYWxTdHJhdGVneSIsImNvbGxlY3Rpb25zIiwiY29sbGVjdGlvbiIsImN1c3RvbUNvbGxlY3Rpb25JZEZpZWxkIiwiZW50aXR5RGVmaW5pdGlvbnMiLCJnbG9iYWxzIiwiZGVmaW5pdGlvbnMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0lBOGdCZ0JBLGtCQUFrQjtlQUFsQkE7O0lBdkVBQyxrQkFBa0I7ZUFBbEJBOztJQXZYQUMsa0JBQWtCO2VBQWxCQTs7SUFWQUMsMEJBQTBCO2VBQTFCQTs7OzJCQXBFUzt1QkFPb0I7Z0NBQ2Q7OEJBQ1A7QUFFeEIsTUFBTUMsa0JBQWtCLENBQUNDO0lBQ3ZCLE1BQU1DLGdCQUFnQkMsUUFBUUYsT0FBT0csU0FBU0gsT0FBT0csT0FBT0M7SUFDNUQsSUFBSUgsZUFBZSxPQUFPO0lBRTFCLE1BQU1JLG1CQUFtQixjQUFjTCxTQUFTQSxNQUFNTSxRQUFRLEtBQUs7SUFDbkUsSUFBSUMsSUFBQUEsdUJBQWdCLEVBQUNQLFVBQVVLLGtCQUFrQixPQUFPO0lBRXhELHdEQUF3RDtJQUN4RCxJQUFJLFlBQVlMLFNBQVNBLE1BQU1RLElBQUksS0FBSyxTQUFTO1FBQy9DLE9BQU9SLE1BQU1TLE1BQU0sQ0FBQ0MsSUFBSSxDQUFDLENBQUNDLFdBQWFaLGdCQUFnQlk7SUFDekQ7SUFFQSxvRUFBb0U7SUFDcEUsSUFBSVgsTUFBTVEsSUFBSSxLQUFLLFFBQVE7UUFDekIsT0FBT1IsTUFBTVksSUFBSSxDQUFDRixJQUFJLENBQUMsQ0FBQ0c7WUFDdEIsSUFBSSxVQUFVQSxLQUFLO2dCQUNqQixPQUFPQSxJQUFJSixNQUFNLENBQUNDLElBQUksQ0FBQyxDQUFDQyxXQUFhWixnQkFBZ0JZO1lBQ3ZEO1lBQ0EsT0FBTztRQUNUO0lBQ0Y7SUFFQSxPQUFPO0FBQ1Q7QUFFQSxTQUFTRyxpQkFBaUJDLE9BQWlCO0lBQ3pDLE9BQU9BLFFBQVFDLEdBQUcsQ0FBQyxDQUFDQztRQUNsQixJQUFJLE9BQU9BLFdBQVcsWUFBWSxXQUFXQSxRQUFRO1lBQ25ELE9BQU9BLE9BQU9DLEtBQUs7UUFDckI7UUFFQSxPQUFPRDtJQUNUO0FBQ0Y7QUFFQSxTQUFTRSxzQkFDUEMsUUFBK0Q7SUFFL0QsTUFBTUMsYUFBYTtXQUFJRDtLQUFTLENBQUNFLE1BQU0sQ0FBQyxDQUFDQyxLQUFLLEVBQUVDLElBQUksRUFBRTtRQUNwREQsR0FBRyxDQUFDQyxLQUFLLEdBQUc7WUFDVkMsTUFBTSxDQUFDLGNBQWMsRUFBRUQsS0FBSyxDQUFDO1FBQ