UNPKG

@windingtree/wt-read-api

Version:

API to interact with the Winding Tree platform

113 lines (106 loc) 3.39 kB
const { HttpValidationError } = require('../errors'); /** * Prepare fields for `flattenObject`. * In case the query contains overlapping keys (e.g. `flights` and `flights.items`) these need to be reverse sorted, * otherwise only `flights.items` will be resolved. * * @param fields * @private */ function _sortFields (fields) { fields.sort(); fields.reverse(); } /** * Format error to API response format. * @param e * @private */ function formatError (e) { const err = new HttpValidationError(); // eslint-disable-next-line no-prototype-builtins if (e.data && e.data.hasOwnProperty('GetFormattedErrors')) { err.msgLong = e.data.GetFormattedErrors().map((err) => { return err.message; }).toString(); } else { err.msgLong = e.data.errors.toString(); } return err; } /** * Flatten resolved storage pointers (off-chain data) to simple object. * * @param contents Object containing storage pointers * @param fields Fields to flatten * @returns {Object} POJO object */ const flattenObject = (contents, fields) => { _sortFields(fields); const currentFieldDef = {}; let currentLevelName, result = {}; for (const field of fields) { let remainingPath; if (field.indexOf('.') === -1) { currentLevelName = field; } else { currentLevelName = field.substring(0, field.indexOf('.')); remainingPath = field.substring(field.indexOf('.') + 1); } if (remainingPath) { if (!currentFieldDef[currentLevelName]) { currentFieldDef[currentLevelName] = []; } currentFieldDef[currentLevelName].push(remainingPath); } else { currentFieldDef[currentLevelName] = undefined; } } for (const field in currentFieldDef) { if (contents[field] !== undefined) { // No specific children selected if (!currentFieldDef[field]) { // Differentiate between storage pointers and plain objects result[field] = contents[field] && contents[field].contents ? contents[field].contents : contents[field]; // Specific children selected } else { let searchSpace; if (contents[field].ref && contents[field].contents) { // StoragePointer searchSpace = contents[field].contents; } else { // POJO searchSpace = contents[field]; } result[field] = flattenObject(searchSpace, currentFieldDef[field]); } } else if (contents && typeof contents === 'object') { // Mapping object such as roomTypes if (Array.isArray(contents)) { if (!result || Object.keys(result).length === 0) { result = contents.map((x) => { const res = {}; if (x[field].ref && x[field].contents) { res[field] = x[field].contents; } else { res[field] = x[field]; } return res; }); } else { result = result.map((x, idx, r) => { const res = r[idx]; res[field] = contents[idx][field]; return res; }); } } else { for (const key in contents) { if (contents[key] && contents[key][field] !== undefined) { if (!result[key]) { result[key] = {}; } result[key][field] = contents[key] && contents[key][field]; } } } } } return result; }; module.exports = { flattenObject, formatError, };