UNPKG

@sitecore/sc-contenthub-webclient-sdk

Version:

Sitecore Content Hub WebClient SDK.

323 lines 13.1 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { CultureInsensitiveProperty } from "../contracts/base/culture-insensitive-property"; import { CultureSensitiveProperty } from "../contracts/base/culture-sensitive-property"; import DataType, { TypeInfo } from "../contracts/base/data-type"; import { MinimalSchema } from "../contracts/querying/minimal-schema"; import { PropertyData } from "../contracts/querying/property-data"; import Guard from "../guard"; export class PropertyMapper { constructor(client) { Guard.notNullOrUndefined(client); this._client = client; } mapPropertiesAsync(resource, loadedCultures, schema) { return __awaiter(this, void 0, void 0, function* () { if (resource == null || resource.properties == null || Object.keys(resource.properties).length === 0) { return []; } // If no minimal schema is available, build it from the definition. if (schema == null) { const definitionName = yield this._client.linkHelper.nameFromDefinitionAsync(resource.entityDefinition); if (definitionName == null) { throw new Error(`Could not resolve definition name from entity resource.`); } const definition = yield this._client.entityDefinitions.getCachedAsync(definitionName); if (definition == null) { throw new Error(`Could not load definition with name '${definitionName}.`); } schema = new MinimalSchema(definitionName); const loadedProperties = Object.keys(resource.properties); schema.properties = definition .getPropertyDefinitions() .filter(propertyDefinition => loadedProperties.includes(propertyDefinition.name)) .map(propertyDefinition => { let hasDataSource = false; if (propertyDefinition.type === DataType.String) { const stringPropertyDef = propertyDefinition; hasDataSource = !!(stringPropertyDef.dataSourceName && stringPropertyDef.dataSourceName.length > 0); } return new PropertyData({ name: propertyDefinition.name, isMultiValue: propertyDefinition.isMultiValue, isMultilingual: propertyDefinition.isMultiLanguage, hasDataSource: hasDataSource, dataType: DataType[propertyDefinition.type], }); }); } const list = []; for (const definition of schema.properties) { const prop = this.mapProperty(resource, loadedCultures, definition); list.push(prop); } return list; }); } mapProperty(resource, loadedCultures, definition) { const name = definition.name; const typeInfo = PropertyMapper.getType(definition); const propertyValue = resource.properties[name]; let property; if (definition.hasDataSource) { property = PropertyMapper.mapDataSource(definition, name, typeInfo, propertyValue); } else if (definition.isMultilingual) { property = PropertyMapper.mapMultilingualProperty(loadedCultures, name, typeInfo, propertyValue); } else { let value; if (definition.isMultiValue) { value = PropertyMapper.convertValue(typeInfo.type, true, propertyValue); } else { value = PropertyMapper.convertValue(typeInfo.type, false, propertyValue); } property = new CultureInsensitiveProperty(name, typeInfo, value); } return property; } static mapMultilingualProperty(loadedCultures, name, typeInfo, propertyValue) { const values = {}; for (const culture of Object.keys(propertyValue)) { let value; if (typeInfo.isArray) { value = this.convertValue(typeInfo.type, true, propertyValue[culture]); } else { value = this.convertValue(typeInfo.type, false, propertyValue[culture]); } values[culture] = value; } const prop = new CultureSensitiveProperty(name, typeInfo, loadedCultures, values); return prop; } // #region SDK to Base // MapProperties static mapToPropertyResources(entity) { Guard.notNullOrUndefined(entity); const dict = {}; for (const property of entity.properties) { const mappedProp = this.mapToPropertyData(property); dict[property.name] = mappedProp.value; } return dict; } static mapDirtyProperties(entity) { Guard.notNullOrUndefined(entity); const result = {}; const dirtyProperties = entity.properties.filter(property => property.isDirty); for (const property of dirtyProperties) { const mappedProp = this.mapToPropertyData(property); result[mappedProp.key] = mappedProp.value; } return result; } // MapProperty static mapToPropertyData(property) { let propertyData; if (property instanceof CultureSensitiveProperty) { const values = property.getValues(); propertyData = { key: property.name, value: values }; } else if (property instanceof CultureInsensitiveProperty) { const value = property.getValue(); if (property.hasDataSource) { let dsValue; if (value != null) { if (Array.isArray(value)) { dsValue = []; // eslint-disable-next-line @typescript-eslint/no-unsafe-call value.map(v => dsValue.push({ identifier: v })); } else { dsValue = { identifier: value }; } } else { dsValue = null; } propertyData = { key: property.name, value: dsValue }; } else { propertyData = { key: property.name, value: value }; } } else { throw new Error(`Property of type ${property.dataType} is not supported.`); } return propertyData; } // #endregion static getType(data) { let type; switch (data.dataType) { case "Boolean": type = DataType.Boolean; break; case "Decimal": type = DataType.Decimal; break; case "Int32": case DataType[DataType.Integer]: type = DataType.Integer; break; case "Int64": case DataType[DataType.Long]: type = DataType.Long; break; case "DateTime": type = DataType.DateTime; break; case "DateTimeOffset": type = DataType.DateTimeOffset; break; case "String": type = DataType.String; break; case "JToken": case DataType[DataType.Json]: type = DataType.Json; break; default: throw new Error("Unsupported value type."); } return new TypeInfo(type, data.isMultiValue); } static convertValue(type, isArray, value) { let result; if (value == null) { return null; } if (isArray) { if (value instanceof Array) { return value.map(item => this.convertValue(type, false, item)); } else if (typeof value === "string") { // If it's a string, we might be able to parse it. try { const parsedValue = JSON.parse(value); if (parsedValue instanceof Array) { return parsedValue.map(item => this.convertValue(type, false, item)); } else { value = parsedValue; } } catch (ex) { // If parsing fails, simply use the string. } } //TODO: Throw error? // // else { // // return null; // // } } switch (type) { case DataType.String: // // typeof value === "string" ? value : `${value}`; result = String(value); break; case DataType.Boolean: result = typeof value === "string" ? value === "true" : !!value; break; case DataType.Integer: case DataType.Long: { const number = parseInt(value, 10); if (Number.isNaN(number)) { result = null; //TODO: Use regex /^[-+]?[0-9]*$/ and throw error? } else { result = number; } break; } case DataType.Decimal: { const number = parseFloat(value); if (Number.isNaN(number)) { result = null; //TODO: Use regex /^[-+]?\b[0-9]*\.?[0-9]*$/ and throw error? } else { result = number; } break; } case DataType.Json: { // Valid JSON values: string, number, boolean, null, array or JSON-object if (value == null) { result = null; } else if (typeof value === "object") { // Covers JSON-object and array result = JSON.parse(JSON.stringify(value)); } else if (typeof value === "string") { try { // When we have a string, it might be a serialized object we can parse. result = JSON.parse(value); } catch (ex) { // Not a valid JSON-object, so return the string value as-is. result = value; } } else { // We might be dealing with a boolean, number or null. result = value; } break; } case DataType.DateTime: { result = value; break; } case DataType.DateTimeOffset: { result = value; break; } } return result; } static mapDataSource(definition, name, typeInfo, propertyValue) { if (propertyValue == null) { const prop = new CultureInsensitiveProperty(name, typeInfo, null, true); return prop; } if (definition.isMultiValue) { const array = propertyValue instanceof Array ? propertyValue : typeof propertyValue === "string" ? JSON.parse(propertyValue) : null; const list = []; for (const token of array) { const value = this.mapDataSourceValue(token); if (value != null) { list.push(value); } } const prop = new CultureInsensitiveProperty(name, typeInfo, [...list], true); return prop; } else { const value = this.mapDataSourceValue(propertyValue); const prop = new CultureInsensitiveProperty(name, typeInfo, value, true); return prop; } } static mapDataSourceValue(dataSourceValue) { if (dataSourceValue == null) { return null; } const identifier = dataSourceValue["identifier"]; return identifier; } } //# sourceMappingURL=property-mapper.js.map