UNPKG

@progress/sitefinity-widget-designers-sdk

Version:

This package aims to create a parity for widget designer generation similar to the [autogenerated widget designers](https://www.progress.com/documentation/sitefinity-cms/next.js-autogenerated-field-types) in Sitefinity. Due to some limitations in Typescri

736 lines (735 loc) 34.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EntityMetadataGenerator = void 0; const utils_1 = require("../decorators/property-decorators/common/utils"); const known_keys_1 = require("../symbols/known-keys"); const known_field_types_1 = require("../decorators/property-decorators/common/known-field-types"); /** * Generates the metadata for the widget designer based on a decorated widget entity. */ class EntityMetadataGenerator { /** * Compiles the designer metadata from the widget entity. * The passed class should be decorated with {@link WidgetEntity}. * @param widgetEntityClass The widget enitity class. * @returns The generated designer metadata. */ static extractMetadata(widgetEntityClass) { if (widgetEntityClass == null) { return; } const metadata = this.mergePrototypes(widgetEntityClass); if (!metadata) { throw new Error(`The provided entity class does not have registered ${known_keys_1.keys.metadata}`); } const meta = this.buildMetadata(metadata); return meta; } /** * Extracts the entity's default values according to the widget designer metadata. * The designer metadata (the {@link DefaultValue} decorator) takes precedence over the defaults set in the entity class definition. * Handles special scenarios such as complex objects, booleans, numbers. * @param {MetadataModel} metadata The designer metadata. */ static extractDefaultValues(metadata) { let propertiesMeta = []; if (Array.isArray(metadata.PropertyMetadataFlat)) { propertiesMeta = metadata.PropertyMetadataFlat; } else { propertiesMeta = this.extractPropertiesMetadataFromHierarchy(metadata); } if (!propertiesMeta) { throw new Error(`Missing PropertyMetadata or PropertyMetadataFlat metadata for type ${metadata.Name}`); } const defaultValues = Object.fromEntries(propertiesMeta.map(x => [x.Name, x.DefaultValue])); propertiesMeta.forEach(property => { const currentValue = this.extractPropertyDefaultValue(property); if (currentValue != null) { defaultValues[property.Name] = currentValue; } }); return defaultValues; } /** * Deserializes the values for widget properties. Parses JSON objects, turns boolean properties from string to true boolean, parses numbers. * @param serializedValues The values assigned to the widget's properties that are received from the server. * @param metadata The widget designer metadata. */ static parseValues(serializedValues, metadata) { let propertiesMeta = []; if (Array.isArray(metadata.PropertyMetadataFlat)) { propertiesMeta = metadata.PropertyMetadataFlat; } else { propertiesMeta = this.extractPropertiesMetadataFromHierarchy(metadata); } if (!propertiesMeta) { throw new Error(`Missing PropertyMetadata or PropertyMetadataFlat metadata for type ${metadata.Name}`); } return this.deserializeProperties(serializedValues, propertiesMeta); } /** * Extracts a single property default value from the property model generated by the designer decorators. * @param property The property model as in the designer metadata. * @returns The default value for the property in the appropriate type as by the designer metadata. */ static extractPropertyDefaultValue(property) { var _a; if (property.DefaultValue !== undefined) { if (property.Type === 'bool' || property.Type === 'boolean' || property.Type === known_field_types_1.KnownFieldTypes.CheckBox) { return this.parseBooleanValue(property.DefaultValue); } else if (property.Type === 'date-time' || property.Type === 'datetime') { if (!isNaN(Date.parse(property.DefaultValue))) { return new Date(property.DefaultValue); } } else if (property.Type === known_field_types_1.ComplexType.Complex || property.Type === known_field_types_1.ComplexType.Enumerable || property.Type === known_field_types_1.ComplexType.Dictionary || property.Type === known_field_types_1.KnownFieldTypes.PencilButton) { // handle complex objects let complexValue; try { complexValue = JSON.parse(property.DefaultValue); // TODO: iterate over nested proeprties of the complex object } catch (_b) { // noop } if (complexValue == null) { complexValue = this.getDefaultValuesForComplexType(property); } return complexValue; } else if (property.Type === known_field_types_1.KnownFieldTypes.ChoiceList || property.Type === known_field_types_1.KnownFieldTypes.ChoiceMultiple || property.Type === known_field_types_1.KnownFieldTypes.Choices || property.Type === known_field_types_1.KnownFieldTypes.ChipChoice || property.Type === known_field_types_1.KnownFieldTypes.RadioChoice || property.Type === known_field_types_1.KnownFieldTypes.MultipleChoiceChip || property.Type === 'multipleChoices') { if (this.isMultipleChoice(property)) { return this.parseMultipleChoicesValue(property.DefaultValue); } else { return this.parseChoiceBooleanValue(property.DefaultValue); } } else if (property.DefaultValue === known_field_types_1.BasicValueTypes.StringArray) { return []; } else if (property.Type === 'number') { if (property.DefaultValue != null) { if (property.Properties['Validations_DecimalPlaces'] != null) { return parseFloat(property.DefaultValue); } else { return parseInt(property.DefaultValue, 10); } } return property.DefaultValue; } else { if (typeof (property.DefaultValue) === 'string') { let jsonValue = property.DefaultValue; try { jsonValue = JSON.parse(property.DefaultValue); // TODO: iterate over nested proeprties of the complex object } catch (_c) { // noop } return jsonValue; } else if ((_a = property.TypeChildProperties) === null || _a === void 0 ? void 0 : _a.length) { return this.getDefaultValuesForComplexType(property); } } } if (property.Type === 'content' && property.DefaultValue == null) { return (0, utils_1.contentPropertyDefaultValue)(property.Properties['Meta_Content_Type']); } } /** * Parses a single property value based on the property model generated by the designer decorators. * @param currentValue The property current value as persisted in Sitefinity. * @param propertyMeta The property model as in the designer metadata. * @returns The property value parsed to the appropriate type defined by the property metadata. */ static parsePropertyValue(currentValue, propertyMeta) { var _a, _b; const propType = propertyMeta[known_keys_1.keys.type]; let value = currentValue; switch (propType) { case 'number': if (value != null) { if (propertyMeta.Properties['Validations_DecimalPlaces'] != null) { value = parseFloat(value); } else { value = parseInt(value, 10); } } break; case 'bool': case 'boolean': case known_field_types_1.KnownFieldTypes.CheckBox: value = this.parseBooleanValue(value); break; case 'date-time': case 'datetime': if (!isNaN(Date.parse(value))) { value = new Date(value); } break; case known_field_types_1.ComplexType.Complex: case known_field_types_1.ComplexType.Dictionary: case known_field_types_1.ComplexType.Enumerable: case known_field_types_1.KnownFieldTypes.PencilButton: if (typeof (value) === 'string') { value = JSON.parse(value); } if (((_a = propertyMeta.TypeChildProperties) === null || _a === void 0 ? void 0 : _a.length) > 0) { value = this.deserializeProperties(value, propertyMeta.TypeChildProperties); } break; case known_field_types_1.KnownFieldTypes.ChoiceList: case known_field_types_1.KnownFieldTypes.ChoiceMultiple: case known_field_types_1.KnownFieldTypes.Choices: case known_field_types_1.KnownFieldTypes.ChipChoice: case known_field_types_1.KnownFieldTypes.RadioChoice: case known_field_types_1.KnownFieldTypes.MultipleChoiceChip: case 'multipleChoices': if (this.isMultipleChoice(propertyMeta)) { value = this.parseMultipleChoicesValue(value); } else { value = this.parseChoiceBooleanValue(value); } break; case 'content': { let parsedValue = value; if (typeof (value) === 'string') { parsedValue = JSON.parse(value); } const contentType = propertyMeta.Properties['Meta_Content_Type']; if (((_b = parsedValue === null || parsedValue === void 0 ? void 0 : parsedValue.Content) === null || _b === void 0 ? void 0 : _b.length) && !parsedValue.Content[0].Type) { parsedValue.Content[0].Type = contentType; } value = parsedValue; } break; default: if (typeof (value) === 'string') { try { value = JSON.parse(value); } catch (_c) { // noop } } break; } return value; } static getDefaultValuesForComplexType(property) { if (!property.TypeChildProperties.length) { return null; } const value = {}; let hasNestedModelValues = false; property.TypeChildProperties.forEach((property) => { const currentValue = this.extractPropertyDefaultValue(property); if (currentValue !== undefined) { value[property.Name] = currentValue; hasNestedModelValues = true; } }); if (hasNestedModelValues) { return value; } else { return property.DefaultValue || null; } } static deserializeProperties(currentSerializedValues, propertiesMeta) { const serializedValuesArray = Array.isArray(currentSerializedValues) ? currentSerializedValues : [currentSerializedValues]; serializedValuesArray.forEach(serializedValues => { for (const key in serializedValues) { if (Object.prototype.hasOwnProperty.call(serializedValues, key)) { let value = serializedValues[key]; const propMeta = propertiesMeta.find(x => x.Name === key); if (propMeta) { value = this.parsePropertyValue(value, propMeta); serializedValues[key] = value; } } } }); return Array.isArray(currentSerializedValues) ? serializedValuesArray : serializedValuesArray[0]; } static buildMetadata(metadata) { const meta = { Name: metadata[known_keys_1.keys.name], Caption: metadata[known_keys_1.keys.caption], PropertyMetadata: [], PropertyMetadataFlat: [] }; // order properties by sections let sectionsOrder = metadata[known_keys_1.keys.sectionsOrder]; if (sectionsOrder) { sectionsOrder = JSON.parse(JSON.stringify(sectionsOrder)); } const propertyKeys = Object.keys(metadata).filter(key => { return key !== known_keys_1.keys.name && key !== known_keys_1.keys.caption && key !== known_keys_1.keys.sectionsOrder; }); const properties = []; propertyKeys.forEach(key => { const value = metadata[key]; if (typeof (value) === 'object') { const compiledValue = this.compileProperty(value, true); if (compiledValue) { properties.push(compiledValue); } } }); const basicCategory = this.generateCategory('Basic'); const advancedCategory = this.generateCategory('Advanced'); const quickEditCategory = this.generateCategory('QuickEdit'); const uniqueSectionsPerCategory = {}; let generatedSections = []; properties.forEach(p => { const sectionName = p[known_keys_1.keys.sectionName]; const categoryName = p[known_keys_1.keys.categoryName] || 'Basic'; this.createSectionIfNotExists(categoryName, sectionName, generatedSections, uniqueSectionsPerCategory); // quick edit properties should also be in the Basic category if (categoryName === 'QuickEdit') { this.createSectionIfNotExists('Basic', sectionName, generatedSections, uniqueSectionsPerCategory); } }); if (sectionsOrder) { generatedSections = generatedSections.sort((a, b) => sectionsOrder.indexOf(a.Name) - sectionsOrder.indexOf(b.Name)); } generatedSections.forEach(section => { if (section.CategoryName === 'Advanced') { if (section.Name === 'AdvancedMain') { advancedCategory.Sections.splice(0, 0, section); } else { advancedCategory.Sections.push(section); } } else if (section.CategoryName === 'QuickEdit') { if (section.Name === 'Main') { quickEditCategory.Sections.splice(0, 0, section); } else { quickEditCategory.Sections.push(section); } } else { if (section.Name === 'Main') { basicCategory.Sections.splice(0, 0, section); } else { basicCategory.Sections.push(section); } } }); properties.forEach(prop => { const categoryName = prop[known_keys_1.keys.categoryName] || 'Basic'; const sectionName = prop[known_keys_1.keys.sectionName]; let categoryObject; if (categoryName === 'Advanced') { categoryObject = advancedCategory; } else if (categoryName === 'QuickEdit') { categoryObject = quickEditCategory; // quick edit properties should also be in the Basic category this.addPropertyToSection(basicCategory, sectionName, prop); } else { categoryObject = basicCategory; } this.addPropertyToSection(categoryObject, sectionName, prop); }); this.pushIfHasSections(basicCategory, meta.PropertyMetadata); this.pushIfHasSections(advancedCategory, meta.PropertyMetadata); this.pushIfHasSections(quickEditCategory, meta.PropertyMetadata); meta.PropertyMetadataFlat = JSON.parse(JSON.stringify(properties)); return meta; } static createSectionIfNotExists(categoryName, sectionName, generatedSections, uniqueSectionsPerCategory) { let uniqueSections = uniqueSectionsPerCategory[categoryName]; if (!uniqueSections) { uniqueSectionsPerCategory[categoryName] = uniqueSections = []; } if (!uniqueSections.includes(sectionName)) { uniqueSections.push(sectionName); const section = this.generateSection(sectionName, categoryName); generatedSections.push(section); } } static addPropertyToSection(categoryObject, sectionName, prop) { const section = categoryObject.Sections.find(x => x.Name === sectionName || (sectionName === 'Main' && x.CategoryName === 'Advanced' && x.Name === 'AdvancedMain')); if (!section) { throw new Error(`Section ${sectionName} was not found on ${categoryObject.Name}`); } section.Properties.push(prop); } static pushIfHasSections(category, propertyMeta) { if (category.Sections.length > 0) { category.Sections = category.Sections.map(s => { s.Properties = s.Properties.sort((a, b) => a.Position - b.Position); s.Properties.forEach(p => { if (p.TypeChildProperties.length > 0) { p.TypeChildProperties = this.sortPropertiesByPosition(p.TypeChildProperties); } }); return s; }); propertyMeta.push(category); } } static compileProperty(propertyMeta, firstLevel = false, capitalizePropertyName = false) { const propertyObject = { [known_keys_1.keys.categoryName]: null, [known_keys_1.keys.defaultValue]: null, [known_keys_1.keys.name]: undefined, [known_keys_1.keys.position]: 0, [known_keys_1.keys.sectionName]: null, [known_keys_1.keys.title]: undefined, [known_keys_1.keys.type]: undefined, [known_keys_1.keys.typeChildProperties]: [], [known_keys_1.keys.properties]: {} }; this.modifyPropertyMeta(propertyMeta); const metaKeys = Object.keys(propertyMeta); if (metaKeys.includes(known_keys_1.keys.browsable)) { return null; } metaKeys.forEach(key => { var _a; const value = propertyMeta[key]; // handle object decorators if (value != null && typeof (value) === 'object' && key !== known_keys_1.keys.dataModel) { propertyObject[known_keys_1.keys.properties] = Object.assign(propertyObject[known_keys_1.keys.properties], this.compileSpecialProperties(key, value)); } else if (value != null && typeof (value) === 'object' && key === known_keys_1.keys.dataModel) { const dataModelValue = (value === null || value === void 0 ? void 0 : value.value) || value; propertyObject[known_keys_1.keys.typeChildProperties] = propertyObject.TypeChildProperties.concat(this.unpackDataModel(dataModelValue)); const type = propertyObject[known_keys_1.keys.type]; if (type == null) { propertyObject[known_keys_1.keys.type] = dataModelValue[known_keys_1.keys.modelType] || known_field_types_1.ComplexType.Complex; } else if (type === 'not-supported') { propertyObject[known_keys_1.keys.type] = null; } else if (dataModelValue[known_keys_1.keys.modelType] !== undefined && type === 'string') { propertyObject[known_keys_1.keys.type] = dataModelValue[known_keys_1.keys.modelType]; } } else { if (key === known_keys_1.keys.defaultValue) { const currentType = propertyMeta[known_keys_1.keys.type]; if (currentType === undefined) { const typeName = (0, utils_1.getBasicType)(typeof (value)); if (typeName) { propertyObject[_a = known_keys_1.keys.type] || (propertyObject[_a] = typeName); } } else if (currentType === 'not-supported') { propertyObject[known_keys_1.keys.type] = null; } else if (currentType === known_field_types_1.KnownFieldTypes.DateTime) { const date = new Date(propertyMeta[known_keys_1.keys.defaultValue]); if (isNaN(date.valueOf())) { propertyMeta[known_keys_1.keys.defaultValue] = null; return; } } else if (currentType === known_field_types_1.KnownFieldTypes.Choices && value != null) { // handle for enum and multiple enum valid default values const choicesSettings = propertyMeta[known_keys_1.keys.choices]; if (choicesSettings) { let choicesArray = []; try { choicesArray = JSON.parse(choicesSettings === null || choicesSettings === void 0 ? void 0 : choicesSettings.Choices); } catch (_) { // noop } if (currentType === known_field_types_1.KnownFieldTypes.Choices && choicesArray.length && !choicesArray.find(x => x.Value === value)) { propertyMeta[known_keys_1.keys.defaultValue] = null; return; } } } } propertyObject[key] = (0, utils_1.formatValue)(value); } }); if (capitalizePropertyName) { const titleEqualsName = propertyObject[known_keys_1.keys.name] === propertyObject[known_keys_1.keys.title]; propertyObject[known_keys_1.keys.name] = this.capitalize(propertyObject[known_keys_1.keys.name]); if (titleEqualsName) { propertyObject[known_keys_1.keys.title] = this.capitalize(propertyObject[known_keys_1.keys.title]); } } if (firstLevel) { // this.assignIfEmpty(propertyObject, 'CategoryName', 'Basic'); this.assignIfEmpty(propertyObject, known_keys_1.keys.sectionName, propertyObject[known_keys_1.keys.categoryName] === 'Advanced' ? 'AdvancedMain' : 'Main'); } // assign default type = string if there is none if (propertyObject[known_keys_1.keys.type] === undefined) { propertyObject[known_keys_1.keys.type] = 'string'; } return propertyObject; } static sortPropertiesByPosition(properties) { return properties.sort((x, y) => { if (x.Position == null && x.Position == null) { return 0; } if (x.Position === 0 && y.Position > 0) { return 1; } else if (x.Position > 0 && y.Position === 0) { return -1; } else { return x.Position - y.Position; } }); } static unpackDataModel(dataModelProps) { const models = []; const capitalizeModelProperties = dataModelProps[known_keys_1.keys.capitalizeModelProperties] === true; const dataModelKeys = Object.keys(dataModelProps); dataModelKeys.forEach(key => { const value = dataModelProps[key]; if (key.startsWith('__')) { return; } const compiledProperty = this.compileProperty(value, false, capitalizeModelProperties); if (compiledProperty) { let propertyObject = { [known_keys_1.keys.categoryName]: null, [known_keys_1.keys.defaultValue]: null, [known_keys_1.keys.name]: null, [known_keys_1.keys.position]: 0, [known_keys_1.keys.sectionName]: null, [known_keys_1.keys.title]: null, [known_keys_1.keys.typeChildProperties]: [], [known_keys_1.keys.properties]: {} }; // unpack nested object properties propertyObject = Object.assign(propertyObject, compiledProperty); models.push(propertyObject); } }); return models; } static assignIfEmpty(propMeta, key, value) { propMeta[key] = propMeta[key] || value; } static modifyPropertyMeta(fullPropertyMeta) { const choiceMeta = fullPropertyMeta[known_keys_1.keys.choices]; const typeMeta = fullPropertyMeta[known_keys_1.keys.type]; if (choiceMeta) { if ((typeMeta == null || typeMeta === 'string') && (typeMeta !== known_field_types_1.KnownFieldTypes.ChipChoice && typeMeta !== known_field_types_1.KnownFieldTypes.RadioChoice)) { fullPropertyMeta[known_keys_1.keys.type] = known_field_types_1.KnownFieldTypes.Choices; } if (choiceMeta === null || choiceMeta === void 0 ? void 0 : choiceMeta.AllowMultiple) { fullPropertyMeta[known_keys_1.keys.type] = 'multipleChoices'; } } if (typeMeta === known_field_types_1.ComplexType.Dictionary) { const lengthDependsOnMeta = fullPropertyMeta[known_keys_1.keys.lengthDependsOn]; // we do not support currently dictionaries that do not have their length based on another property if (!lengthDependsOnMeta) { fullPropertyMeta[known_keys_1.keys.type] = 'not-supported'; fullPropertyMeta[known_keys_1.keys.defaultValue] = null; } } else if (typeMeta === known_field_types_1.ComplexType.Enumerable && !fullPropertyMeta[known_keys_1.keys.dataModel]) { if (fullPropertyMeta[known_keys_1.keys.subType] !== 'string' && fullPropertyMeta[known_keys_1.keys.subType] !== known_field_types_1.KnownFieldTypes.LinkSelector) { // we do not support collections of primitive values other than string[] fullPropertyMeta[known_keys_1.keys.type] = null; } else if (fullPropertyMeta[known_keys_1.keys.subType] === known_field_types_1.KnownFieldTypes.LinkSelector) { fullPropertyMeta[known_keys_1.keys.type] = known_field_types_1.KnownFieldTypes.LinkSelector; // simulate some typechildproperties so IRIS could treat it as a mulitple links selector fullPropertyMeta[known_keys_1.keys.dataModel] = { value: { 'Length': { [known_keys_1.keys.type]: 'number', [known_keys_1.keys.name]: 'Length', [known_keys_1.keys.defaultValue]: 0 } } }; } } const titleMeta = fullPropertyMeta[known_keys_1.keys.title]; if (titleMeta === undefined) { fullPropertyMeta[known_keys_1.keys.title] = fullPropertyMeta[known_keys_1.keys.name]; } } static compileSpecialProperties(propName, propMeta) { const properties = {}; const propKeys = Object.keys(propMeta); propKeys.forEach(key => { let newKey; if (this.skipMetaKeyword.includes(propName)) { newKey = `${propName}_${key}`; } else if ((propName === known_keys_1.keys.choices && key === 'Choices') || key === '_' || propName === known_keys_1.keys.isNullable) { newKey = `Meta_${propName}`; } else if ((propName === known_keys_1.keys.fieldMappings || propName === known_keys_1.keys.cssClasses) && key === 'ViewMetaData' || key === 'ColorPaletteColors') { newKey = `Meta_${key}`; } else { newKey = `Meta_${propName}_${key}`; } properties[newKey] = (0, utils_1.formatValue)(propMeta[key]); }); return properties; } static generateCategory(name) { return { Name: name, Sections: [] }; } static generateSection(name, categoryName) { const skipTitle = ((categoryName == null || categoryName === 'Basic') && name === 'Main') || (categoryName === 'Advanced' && name === 'AdvancedMain') || (categoryName === 'QuickEdit' && name === 'Main'); return { Name: name, Title: !skipTitle ? name : null, Properties: [], CategoryName: categoryName || 'Basic' }; } static capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1); } static parseBooleanValue(value) { if (value === 'True' || value === 'true' || value === true) { return true; } else { return false; } } static parseChoiceBooleanValue(value) { if (value === 'True' || value === 'true' || value === true) { return true; } else if (value === 'False' || value === 'false' || value === false) { return false; } else { return value; } } static parseMultipleChoicesValue(value) { if (typeof (value) === 'string') { try { value = JSON.parse(value); } catch (_a) { // noop } } if (typeof (value) === 'string') { value = value.split(',').map(x => x.trim()); } else if (typeof (value) === 'object' && !Array.isArray(value)) { value = [value]; } if (Array.isArray(value)) { value = value.map(v => this.parseChoiceBooleanValue(v)); } return value; } static isMultipleChoice(propMeta) { return propMeta.Properties['Meta_Choices_AllowMultiple'] === 'True' || propMeta.Properties['Meta_Choices_AllowMultiple'] === 'true' || propMeta.Properties['Meta_Choices_AllowMultiple'] === true; } static extractPropertiesMetadataFromHierarchy(metadata) { const propertiesMeta = []; if (metadata.PropertyMetadata == null) { return null; } metadata.PropertyMetadata.forEach(category => { category.Sections.forEach(section => { propertiesMeta.push(...section.Properties); }); }); return propertiesMeta; } static mergePrototypes(enitityClass) { var _a, _b; const propertiesMetadata = []; let currentProto = enitityClass.prototype; while ((_b = (_a = currentProto === null || currentProto === void 0 ? void 0 : currentProto.constructor) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.length) { const metadataDecorator = Object.getOwnPropertyDescriptors(currentProto)[known_keys_1.keys.metadata]; const metadata = metadataDecorator === null || metadataDecorator === void 0 ? void 0 : metadataDecorator.value; if (metadata) { propertiesMetadata.push(metadata); } currentProto = Object.getPrototypeOf(currentProto); } propertiesMetadata.reverse(); const finalMeta = {}; propertiesMetadata.forEach(protoMeta => { const propKeys = Object.keys(protoMeta); propKeys.forEach((key) => { const value = protoMeta[key]; if (typeof (value) === 'object' && !Array.isArray(value)) { if (!finalMeta[key]) { finalMeta[key] = {}; } let skipTitle = false; if (finalMeta[key] && finalMeta[key][known_keys_1.keys.title] && value[known_keys_1.keys.name] === value[known_keys_1.keys.title]) { skipTitle = true; } const metaKeys = Object.keys(value); const existingChoiceProperty = Object.keys(finalMeta[key]).find(x => this.isChoiceKey(x)); metaKeys.forEach(metaKey => { if (skipTitle && metaKey === known_keys_1.keys.title) { return; } if (existingChoiceProperty && this.isChoiceKey(metaKey)) { delete (finalMeta[key][existingChoiceProperty]); } finalMeta[key][metaKey] = value[metaKey]; }); } else { finalMeta[key] = value; } }); }); return finalMeta; } static isChoiceKey(key) { return key === known_keys_1.keys.choice || key === known_keys_1.keys.choices; } } exports.EntityMetadataGenerator = EntityMetadataGenerator; EntityMetadataGenerator.skipMetaKeyword = [ known_keys_1.keys.validations ];