UNPKG

jsonpath-mapper

Version:

A json to json transformation utility with a few nice features to use when translating for example API responses into a domain object for use in your domain-driven JavaScript applications. Can be used in React applications with the 'useMapper' hook.

242 lines (235 loc) 8.06 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var jsonpathPlus = require('jsonpath-plus'); var fromEntries = require('fromentries'); const jpath = (query, json) => { const result = jsonpathPlus.JSONPath({ path: `$${query.startsWith('.') ? '' : '.'}${query}`, json: json, }); if (result.length > 1 || (query.match(/\[.*?\]/) && !query.match(/\[[0-9]\]/))) return result; return result[0]; }; const isArray = (val) => val && Array.isArray(val); const isWireFunction = (val) => typeof val === 'function'; const isNull = (val) => val === null; const isUndefined = (val) => typeof val === 'undefined'; const isNullOrUndefined = (val) => { if (isUndefined(val)) return true; if (isNull(val)) return true; return false; }; const isNumber = (val) => typeof val === 'number'; const isMapperFunctions = (val) => typeof val === 'object' && '$path' in val; const isObject = (val) => typeof val === 'object'; const isString = (val) => typeof val === 'string'; const tryMultiple$1 = (json, arr, $root, findMultiple) => { const result = findMultiple(json, arr, $root).filter(r => isNumber(r) || r); if (arr.every(i => (typeof i === "string"))) return result.length > 0 ? result[0] : null; return result; }; const formatResult$1 = (value, $formatting, $root) => isWireFunction($formatting) ? $formatting(value, $root) : isObject($formatting) ? mapObject$1(value, $formatting, $root) : value; const handleMapperFunctions$1 = async ([k, v], json, $root) => { let val, formatted, finalVal; if (isString(v.$path)) { val = jpath(v.$path, json); } if (isArray(v.$path)) { val = await tryMultiple(json, v.$path, $root, findMultiple$1); } if (!isUndefined(v.$formatting) && !isNullOrUndefined(val)) { if (isArray(val)) { formatted = await Promise.all(val.map(async (inner) => !isUndefined(v.$formatting) && (await formatResult$1(inner, v.$formatting, $root)))); } else { formatted = await formatResult$1(val, v.$formatting, $root); } val = formatted; } if (v.$return) { finalVal = await formatResult$1(val, v.$return, $root); } else { finalVal = val; } if (!isUndefined(v.$default) && isNullOrUndefined(finalVal)) { if (isWireFunction(v.$default)) { finalVal = await v.$default(json, $root); } else { finalVal = v.$default; } } if (v.$disable && isWireFunction(v.$disable) && (await v.$disable(finalVal, $root))) { return null; } return finalVal; }; const mapElement$1 = async ([k, v], json, $root) => { if (isNullOrUndefined(v) || v === '') return [k, undefined]; if (isString(v)) { return [k, jpath(v, json)]; } if (isWireFunction(v)) { return [k, await v(json, $root)]; } if (isArray(v)) { return [k, await tryMultiple(json, v, $root, findMultiple$1)]; } if (isMapperFunctions(v)) { return [k, await handleMapperFunctions$1([k, v], json, $root)]; } if (typeof v === 'object') return [k, await mapObject$1(json, v, $root)]; return [k, v]; }; const mapObject$1 = async (json, obj, $root) => { const objectAsEntries = (await Promise.all(Object.entries(obj).map(async ([k, v]) => await mapElement$1([k, v], json, $root)))).filter(([, v]) => v !== null); return fromEntries(objectAsEntries); }; const mapArray$1 = async (json, arr, $root) => { return (await Promise.all(arr.map(async (v) => await mapObject$1(json, v, $root)))); }; const findMultiple$1 = (json, arr, $root) => { const results = arr.map(async (inner, i) => { if (isString(inner)) return jpath(inner, json); if (isWireFunction(inner)) return await inner(json, $root); if (isArray(inner)) return await tryMultiple(json, inner, $root, findMultiple$1); if (isMapperFunctions(inner)) return await handleMapperFunctions$1([i.toString(), inner], json, $root); if (typeof inner === 'object') return await mapObject$1(json, inner, $root); }); return results; }; const tryMultiple = async (json, arr, $root, findMultiple) => { const result = (await Promise.all(findMultiple(json, arr, $root))) .filter(r => isNumber(r) || r); if (arr.every((i) => typeof i === 'string')) return result.length > 0 ? result[0] : null; return result; }; const mapJson$1 = async (json, template) => { const $root = json; if (typeof template === 'function') { return await template(json); } if (isArray(template)) { return await mapArray$1(json, template, $root); } return await mapObject$1(json, template, $root); }; const formatResult = (value, $formatting, $root) => isWireFunction($formatting) ? $formatting(value, $root) : isObject($formatting) ? mapObject(value, $formatting, $root) : value; const handleMapperFunctions = ([k, v], json, $root) => { let val, formatted, finalVal; if (isString(v.$path)) { val = jpath(v.$path, json); } if (isArray(v.$path)) { val = tryMultiple$1(json, v.$path, $root, findMultiple); } if (!isUndefined(v.$formatting) && !isNullOrUndefined(val)) { if (isArray(val)) { formatted = val.map((inner) => !isUndefined(v.$formatting) && formatResult(inner, v.$formatting, $root)); } else { formatted = formatResult(val, v.$formatting, $root); } val = formatted; } if (v.$return) { finalVal = formatResult(val, v.$return, $root); } else { finalVal = val; } if (!isUndefined(v.$default) && isNullOrUndefined(finalVal)) { if (isWireFunction(v.$default)) { finalVal = v.$default(json, $root); } else { finalVal = v.$default; } } if (v.$disable && isWireFunction(v.$disable) && v.$disable(finalVal, $root)) { return null; } return finalVal; }; const mapElement = ([k, v], json, $root) => { if (isNullOrUndefined(v) || v === '') return [k, undefined]; if (isString(v)) { return [k, jpath(v, json)]; } if (isWireFunction(v)) { return [k, v(json, $root)]; } if (isArray(v)) { return [k, tryMultiple$1(json, v, $root, findMultiple)]; } if (isMapperFunctions(v)) { return [k, handleMapperFunctions([k, v], json, $root)]; } if (typeof v === 'object') return [k, mapObject(json, v, $root)]; return [k, v]; }; const mapObject = (json, obj, $root) => { const objectAsEntries = Object.entries(obj) .map(([k, v]) => mapElement([k, v], json, $root)) .filter((obj) => isArray(obj) && obj[1] !== null); return fromEntries(objectAsEntries); }; const mapArray = (json, arr, $root) => { return arr.map((v) => mapObject(json, v, $root)); }; const findMultiple = (json, arr, $root) => { const results = arr.map((inner, i) => { if (isString(inner)) return jpath(inner, json); if (isWireFunction(inner)) return inner(json, $root); if (isArray(inner)) return tryMultiple$1(json, inner, $root, findMultiple); if (isMapperFunctions(inner)) return handleMapperFunctions([i.toString(), inner], json, $root); if (typeof inner === 'object') return mapObject(json, inner, $root); }); return results; }; const mapJson = (json, template) => { const $root = json; if (typeof template === 'function') { return template(json); } if (isArray(template)) { return mapArray(json, template, $root); } return mapObject(json, template, $root); }; exports.default = mapJson; exports.jpath = jpath; exports.mapJsonAsync = mapJson$1;