UNPKG

@ima/plugin-http-client

Version:

Generic http client for the IMA application framework.

136 lines (135 loc) 4.84 kB
import { clone } from '@ima/helpers'; import { BaseMapper } from './mapper/BaseMapper'; /** * The base class for typed REST API entities. Usage of typed entities may be * optional and is dependent on the specific implementation of the REST API * client. */ export class BaseEntity { /** * Returns the description of automatic mapping of the raw data exchanged * between the REST API, and the properties of this * entity. * * The keys of the returned object are the names of the API properties. * * The value associated with key is one of the following: * * - The new name of the property in this entity. This is useful when the * property only needs to be renamed. * * - The mapper instance of BaseMapper. This is useful when the property only needs to changed format but not renamed. * * - The MapperItem object eg.: { mapper: new EntityListMapper(BaseEntity), newKey: 'authors' }. * This is useful when the property needs changed format and renamed too. * */ get dataFieldMapping() { return {}; } /** * Initializes the entity. * * @param data, which will be directly * assigned to the entity's fields. * @param data */ constructor(data){ const entityData = this.deserialize(data); Object.assign(this, entityData); } /** * Serializes this entity into a JSON-compatible plain JavaScript object * that has a structure that is compatible with the entity's REST API * resource. * * Note that this method may not receive a representation of the entity's * complete state if invoked by the {@linkcode cloneAndPatch()} method. * * The default implementation of this method implements a mapping based on * the {@linkcode dataFieldMapping} property's value. * * @param data */ serialize(data = this) { const mapping = this.#getDataFieldMapping(); const initialValue = {}; const reverseMapping = Object.entries(mapping).reduce((acc, [key, value])=>{ acc[value.newKey] = Object.assign({}, value, { newKey: key }); return acc; }, initialValue); const serializedData = {}; Object.entries(data).forEach(([key, value])=>{ let newValue = value; let newKey = key; if (reverseMapping[key]) { const mapperItem = reverseMapping[key]; newKey = mapperItem.newKey; newValue = mapperItem.mapper.serialize(value); } serializedData[newKey] = newValue; }); return serializedData; } /** * Transform dataFieldMapping result to MapperItems. */ #getDataFieldMapping() { const dataFieldMapping = this.dataFieldMapping; const processedDataFieldMapping = {}; Object.entries(dataFieldMapping).forEach(([key, value])=>{ processedDataFieldMapping[key] = BaseMapper.createMapperItem(value, key); }); return processedDataFieldMapping; } /** * Pre-processes the provided data obtained from the REST API into a form * that can be assigned to this entity. * * This method can be used to format data, rename fields, generated * computed fields, etc. * * Note that this method may not receive a representation of the entity's * complete state in some cases. * * The default implementation of this method implements a mapping based on * the {@linkcode dataFieldMapping} property's value. * * @param data */ deserialize(data) { const mapping = this.#getDataFieldMapping(); const deserializedData = {}; Object.entries(data).forEach(([key, value])=>{ let newValue = value; let newKey = key; if (mapping[key]) { const mapperItem = mapping[key]; newKey = mapperItem.newKey; newValue = mapperItem.mapper.deserialize(value); } deserializedData[newKey] = newValue; }); return deserializedData; } /** * Creates a clone of this entity. */ clone() { const data = clone(this.serialize()); return Reflect.construct(this.constructor, [ data ]); } /** * Creates a clone of this entity with its state patched using the provided * state patch object. * @param statePatch */ cloneAndPatch(statePatch) { const data = this.serialize(); const patchData = statePatch instanceof this.constructor ? this.serialize(statePatch) : statePatch; const mergedData = clone({ ...data, ...patchData }); return Reflect.construct(this.constructor, [ mergedData ]); } } //# sourceMappingURL=BaseEntity.js.map