Created
July 18, 2022 15:22
-
-
Save slauzinho/86e388cec11cb6aebc0dfb352b011c7a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable @typescript-eslint/no-explicit-any */ | |
/* | |
THIS IS A COPY OF https://github.com/yury-dymov/json-api-normalizer/blob/master/src/normalize.js | |
WE JUST UPDATED THE LODASH DEPENDANCIES TO REDUCE BUNDLE SIZE | |
*/ | |
import camelCase from 'lodash.camelcase'; | |
import isNull from 'lodash.isnull'; | |
import keys from 'lodash.keys'; | |
import merge from 'lodash.merge'; | |
function wrap(json: any) { | |
if (Array.isArray(json)) { | |
return json; | |
} | |
return [json]; | |
} | |
function isDate(attributeValue: any) { | |
return Object.prototype.toString.call(attributeValue) === '[object Date]'; | |
} | |
function camelizeNestedKeys(attributeValue: any): any { | |
if (attributeValue === null || typeof attributeValue !== 'object' || isDate(attributeValue)) { | |
return attributeValue; | |
} | |
if (Array.isArray(attributeValue)) { | |
return attributeValue.map(camelizeNestedKeys); | |
} | |
const copy: any = {}; | |
keys(attributeValue).forEach(k => { | |
copy[camelCase(k)] = camelizeNestedKeys(attributeValue[k]); | |
}); | |
return copy; | |
} | |
function extractRelationships(relationships: any, { camelizeKeys, camelizeTypeValues }: any): any { | |
const ret: any = {}; | |
keys(relationships).forEach(key => { | |
const relationship = relationships[key]; | |
const name = camelizeKeys ? camelCase(key) : key; | |
ret[name] = {}; | |
if (typeof relationship.data !== 'undefined') { | |
if (Array.isArray(relationship.data)) { | |
ret[name].data = relationship.data.map((e: any) => ({ | |
id: e.id, | |
type: camelizeTypeValues ? camelCase(e.type) : e.type, | |
})); | |
} else if (!isNull(relationship.data)) { | |
ret[name].data = { | |
id: relationship.data.id, | |
type: camelizeTypeValues ? camelCase(relationship.data.type) : relationship.data.type, | |
}; | |
} else { | |
ret[name].data = relationship.data; | |
} | |
} | |
if (relationship.links) { | |
ret[name].links = camelizeKeys ? camelizeNestedKeys(relationship.links) : relationship.links; | |
} | |
if (relationship.meta) { | |
ret[name].meta = camelizeKeys ? camelizeNestedKeys(relationship.meta) : relationship.meta; | |
} | |
}); | |
return ret; | |
} | |
function processMeta(metaObject: any, { camelizeKeys }: any) { | |
if (camelizeKeys) { | |
const meta: any = {}; | |
keys(metaObject).forEach(key => { | |
meta[camelCase(key)] = camelizeNestedKeys(metaObject[key]); | |
}); | |
return meta; | |
} | |
return metaObject; | |
} | |
function extractEntities(json: any, { camelizeKeys, camelizeTypeValues }: any) { | |
const ret: any = {}; | |
wrap(json).forEach(elem => { | |
const type = camelizeKeys ? camelCase(elem.type) : elem.type; | |
ret[type] = ret[type] || {}; | |
ret[type][elem.id] = ret[type][elem.id] || { | |
id: elem.id, | |
}; | |
ret[type][elem.id].type = camelizeTypeValues ? camelCase(elem.type) : elem.type; | |
if (camelizeKeys) { | |
ret[type][elem.id].attributes = {}; | |
keys(elem.attributes).forEach(key => { | |
ret[type][elem.id].attributes[camelCase(key)] = camelizeNestedKeys(elem.attributes[key]); | |
}); | |
} else { | |
ret[type][elem.id].attributes = elem.attributes; | |
} | |
if (elem.links) { | |
ret[type][elem.id].links = {}; | |
keys(elem.links).forEach(key => { | |
const newKey = camelizeKeys ? camelCase(key) : key; | |
ret[type][elem.id].links[newKey] = elem.links[key]; | |
}); | |
} | |
if (elem.relationships) { | |
ret[type][elem.id].relationships = extractRelationships(elem.relationships, { | |
camelizeKeys, | |
camelizeTypeValues, | |
}); | |
} | |
if (elem.meta) { | |
ret[type][elem.id].meta = processMeta(elem.meta, { camelizeKeys }); | |
} | |
}); | |
return ret; | |
} | |
function doFilterEndpoint(endpoint: any) { | |
return endpoint.replace(/\?.*$/, ''); | |
} | |
function extractMetaData( | |
json: any, | |
endpoint: any, | |
{ camelizeKeys, camelizeTypeValues, filterEndpoint }: any | |
) { | |
const ret: any = {}; | |
ret.meta = {}; | |
let metaObject: any; | |
if (!filterEndpoint) { | |
const filteredEndpoint = doFilterEndpoint(endpoint); | |
ret.meta[filteredEndpoint] = {}; | |
ret.meta[filteredEndpoint][endpoint.slice(filteredEndpoint.length)] = {}; | |
metaObject = ret.meta[filteredEndpoint][endpoint.slice(filteredEndpoint.length)]; | |
} else { | |
ret.meta[endpoint] = {}; | |
metaObject = ret.meta[endpoint]; | |
} | |
metaObject.data = {}; | |
if (json.data) { | |
const meta: any = []; | |
wrap(json.data).forEach(object => { | |
const pObject: any = { | |
id: object.id, | |
type: camelizeTypeValues ? camelCase(object.type) : object.type, | |
}; | |
if (object.relationships) { | |
pObject.relationships = extractRelationships(object.relationships, { | |
camelizeKeys, | |
camelizeTypeValues, | |
}); | |
} | |
meta.push(pObject); | |
}); | |
metaObject.data = meta; | |
} | |
if (json.links) { | |
metaObject.links = json.links; | |
ret.meta[doFilterEndpoint(endpoint)].links = json.links; | |
} | |
if (json.meta) { | |
metaObject.meta = processMeta(json.meta, { camelizeKeys }); | |
} | |
return ret; | |
} | |
export default function normalize<T>( | |
json: any, | |
{ filterEndpoint = true, camelizeKeys = true, camelizeTypeValues = false, endpoint }: any = {} | |
): T { | |
const ret = {}; | |
if (json.data) { | |
merge(ret, extractEntities(json.data, { camelizeKeys, camelizeTypeValues })); | |
} | |
if (json.included) { | |
merge(ret, extractEntities(json.included, { camelizeKeys, camelizeTypeValues })); | |
} | |
if (endpoint) { | |
const endpointKey = filterEndpoint ? doFilterEndpoint(endpoint) : endpoint; | |
merge( | |
ret, | |
extractMetaData(json, endpointKey, { | |
camelizeKeys, | |
camelizeTypeValues, | |
filterEndpoint, | |
}) | |
); | |
} | |
return ret as T; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment