UNPKG

payload

Version:

Node, React and MongoDB Headless CMS and Application Framework

517 lines (516 loc) • 60.4 kB
"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