@sitecore/sc-contenthub-webclient-sdk
Version:
Sitecore Content Hub WebClient SDK.
323 lines • 13.1 kB
JavaScript
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