@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
JavaScript
;
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
];