src/utilities/factories/HelperFactory.js
import Client from '../../Client';
import { flattenJsonApi, getJsonApiType, isJsonApiFormat } from '../JsonApiUtility';
import { stringToCamel } from '../FormatUtility';
/**
* Factory to convert responses to classes (deserialization)
*/
class HelperFactory {
/** @type {Object} - A hashmap from object names to classes */
static get map() { return this._map; }
/** @type {Object} - A hashmap from object names to classes */
static set map(_map) { this._map = _map; }
/**
* Convert the json to the appropriate class (deserialize)
*
* @param {Object} json - The json from an api call (in JSON)
* @param {String} [type] - The type to convert the object to (otherwise use json's data type)
* @param {Object} [meta] - Any object to be passed through to assign meta to array if necessary
* @return {Promise<Object>} - Returns an object with the appropriate type
*/
async get(json, type = undefined, meta = {}) {
let obj;
if (json && Array.isArray(json.data) && json.data.length === 0) {
obj = [];
} else if (type) {
obj = await this.getClass(json, type);
} else if (isJsonApiFormat(json)) {
if (json.meta) {
Object.keys(json.meta).forEach((key) => {
json.meta[stringToCamel(key)] = json.meta[key];
meta[stringToCamel(key)] = json.meta[key];
delete json.meta[key];
});
json.data.meta = json.meta;
}
if (json.included) {
Promise.all(json.included.map(d => this.getClass(d, type)));
}
if (Array.isArray(json.data)) {
obj = await Promise.all(json.data.map(d => this.getClass(d, type)));
Object.defineProperty(obj, 'meta', { enumerable: false, writable: true });
obj.meta = json.meta;
} else {
obj = await this.getClass(json.data, type);
}
}
obj = obj || json;
return new Promise(resolve => resolve(obj));
}
/**
* Converts an object to a class if it is mapped
*
* @param {Object} json - JSON to convert to a class
* @param {String} [type] - The type to override the json.type
* @return {Class} - Returns a class
*/
async getClass(json, type = undefined) {
const flatJson = flattenJsonApi(json);
const storage = Client.instance.storageUtility;
const t = type || getJsonApiType(flatJson);
let obj = {};
if (storage.has(t, { id: flatJson.id })) {
obj = new HelperFactory.map[t](flatJson);
obj = await storage.get(t, { id: flatJson.id });
} else if (HelperFactory.map[t]) {
obj = new HelperFactory.map[t](flatJson);
storage.set(t, obj, { id: obj.id });
} else {
obj = flatJson;
}
return obj;
}
}
/** @type {HelperFactory} - An instance of HelperFactory */
const helperFactory = new HelperFactory();
export { HelperFactory, helperFactory };