@data-client/normalizr
Version:
Normalizes and denormalizes JSON according to schema for Redux and Flux applications
90 lines (86 loc) • 15.6 kB
JavaScript
import { INVALID } from './symbol.js';
import { UNDEF } from './UNDEF.js';
import { isEntity } from '../isEntity.js';
import { denormalize as arrayDenormalize } from '../schemas/Array.js';
import { isImmutable } from '../schemas/ImmutableUtils.js';
import { denormalize as objectDenormalize } from '../schemas/Object.js';
function unvisitEntity(schema, entityOrId, args, unvisit, getEntity, cache) {
const entity = typeof entityOrId === 'object' ? entityOrId : getEntity({
key: schema.key,
pk: entityOrId
});
if (typeof entity === 'symbol' && typeof schema.denormalize === 'function') {
return schema.denormalize(entity, args, unvisit);
}
if (entity === undefined && typeof entityOrId !== 'object' && entityOrId !== '' && entityOrId !== 'undefined') {
// we cannot perform lookups with `undefined`, so we use a special object to represent undefined
// we're actually using this call to ensure we update the cache if a nested schema changes from `undefined`
// this is because cache.getEntity adds this key,pk as a dependency of anything it is nested under
return cache.getEntity(entityOrId, schema, UNDEF, localCacheKey => {
localCacheKey.set(entityOrId, undefined);
});
}
if (typeof entity !== 'object' || entity === null) {
return entity;
}
let pk = typeof entityOrId !== 'object' ? entityOrId : schema.pk(isImmutable(entity) ? entity.toJS() : entity, undefined, undefined, args);
// if we can't generate a working pk we cannot do cache lookups properly,
// so simply denormalize without caching
if (pk === undefined || pk === '' || pk === 'undefined') {
return noCacheGetEntity(localCacheKey => unvisitEntityObject(entity, schema, unvisit, '', localCacheKey, args));
}
// just an optimization to make all cache usages of pk monomorphic
if (typeof pk !== 'string') pk = `${pk}`;
// last function computes if it is not in any caches
return cache.getEntity(pk, schema, entity, localCacheKey => unvisitEntityObject(entity, schema, unvisit, pk, localCacheKey, args));
}
function noCacheGetEntity(computeValue) {
const localCacheKey = new Map();
computeValue(localCacheKey);
return localCacheKey.get('');
}
function unvisitEntityObject(entity, schema, unvisit, pk, localCacheKey, args) {
const entityCopy = isImmutable(entity) ? schema.createIfValid(entity.toObject()) : schema.createIfValid(entity);
localCacheKey.set(pk, entityCopy);
if (entityCopy === undefined) {
// undefined indicates we should suspense (perhaps failed validation)
localCacheKey.set(pk, INVALID);
} else {
if (typeof schema.denormalize === 'function') {
localCacheKey.set(pk, schema.denormalize(entityCopy, args, unvisit));
}
}
}
const getUnvisit = (getEntity, cache, args) => {
function unvisit(schema, input) {
if (!schema) return input;
if (input === null || input === undefined) {
return input;
}
if (typeof schema.denormalize !== 'function') {
// deserialize fields (like Temporal.Instant)
if (typeof schema === 'function') {
return schema(input);
}
// shorthand for object, array
if (typeof schema === 'object') {
const method = Array.isArray(schema) ? arrayDenormalize : objectDenormalize;
return method(schema, input, args, unvisit);
}
} else {
if (isEntity(schema)) {
return unvisitEntity(schema, input, args, unvisit, getEntity, cache);
}
return schema.denormalize(input, args, unvisit);
}
return input;
}
return (schema, input) => {
// in the case where WeakMap cannot be used
// this test ensures null is properly excluded from WeakMap
const cachable = Object(input) === input && Object(schema) === schema;
return cache.getResults(input, cachable, () => unvisit(schema, input));
};
};
export default getUnvisit;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJJTlZBTElEIiwiVU5ERUYiLCJpc0VudGl0eSIsImRlbm9ybWFsaXplIiwiYXJyYXlEZW5vcm1hbGl6ZSIsImlzSW1tdXRhYmxlIiwib2JqZWN0RGVub3JtYWxpemUiLCJ1bnZpc2l0RW50aXR5Iiwic2NoZW1hIiwiZW50aXR5T3JJZCIsImFyZ3MiLCJ1bnZpc2l0IiwiZ2V0RW50aXR5IiwiY2FjaGUiLCJlbnRpdHkiLCJrZXkiLCJwayIsInVuZGVmaW5lZCIsImxvY2FsQ2FjaGVLZXkiLCJzZXQiLCJ0b0pTIiwibm9DYWNoZUdldEVudGl0eSIsInVudmlzaXRFbnRpdHlPYmplY3QiLCJjb21wdXRlVmFsdWUiLCJNYXAiLCJnZXQiLCJlbnRpdHlDb3B5IiwiY3JlYXRlSWZWYWxpZCIsInRvT2JqZWN0IiwiZ2V0VW52aXNpdCIsImlucHV0IiwibWV0aG9kIiwiQXJyYXkiLCJpc0FycmF5IiwiY2FjaGFibGUiLCJPYmplY3QiLCJnZXRSZXN1bHRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Rlbm9ybWFsaXplL3VudmlzaXQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgQ2FjaGUgZnJvbSAnLi9jYWNoZS5qcyc7XG5pbXBvcnQgeyB0eXBlIEdldEVudGl0eSB9IGZyb20gJy4vZ2V0RW50aXRpZXMuanMnO1xuaW1wb3J0IHsgSU5WQUxJRCB9IGZyb20gJy4vc3ltYm9sLmpzJztcbmltcG9ydCB7IFVOREVGIH0gZnJvbSAnLi9VTkRFRi5qcyc7XG5pbXBvcnQgdHlwZSB7IEVudGl0eUludGVyZmFjZSB9IGZyb20gJy4uL2ludGVyZmFjZS5qcyc7XG5pbXBvcnQgeyBpc0VudGl0eSB9IGZyb20gJy4uL2lzRW50aXR5LmpzJztcbmltcG9ydCB7IGRlbm9ybWFsaXplIGFzIGFycmF5RGVub3JtYWxpemUgfSBmcm9tICcuLi9zY2hlbWFzL0FycmF5LmpzJztcbmltcG9ydCB7IGlzSW1tdXRhYmxlIH0gZnJvbSAnLi4vc2NoZW1hcy9JbW11dGFibGVVdGlscy5qcyc7XG5pbXBvcnQgeyBkZW5vcm1hbGl6ZSBhcyBvYmplY3REZW5vcm1hbGl6ZSB9IGZyb20gJy4uL3NjaGVtYXMvT2JqZWN0LmpzJztcbmltcG9ydCB0eXBlIHsgRW50aXR5UGF0aCB9IGZyb20gJy4uL3R5cGVzLmpzJztcblxuZnVuY3Rpb24gdW52aXNpdEVudGl0eShcbiAgc2NoZW1hOiBFbnRpdHlJbnRlcmZhY2UsXG4gIGVudGl0eU9ySWQ6IFJlY29yZDxzdHJpbmcsIGFueT4gfCBzdHJpbmcsXG4gIGFyZ3M6IHJlYWRvbmx5IGFueVtdLFxuICB1bnZpc2l0OiAoc2NoZW1hOiBhbnksIGlucHV0OiBhbnkpID0+IGFueSxcbiAgZ2V0RW50aXR5OiBHZXRFbnRpdHksXG4gIGNhY2hlOiBDYWNoZSxcbik6IG9iamVjdCB8IHVuZGVmaW5lZCB8IHN5bWJvbCB7XG4gIGNvbnN0IGVudGl0eSA9XG4gICAgdHlwZW9mIGVudGl0eU9ySWQgPT09ICdvYmplY3QnID8gZW50aXR5T3JJZCA6IChcbiAgICAgIGdldEVudGl0eSh7IGtleTogc2NoZW1hLmtleSwgcGs6IGVudGl0eU9ySWQgfSlcbiAgICApO1xuICBpZiAodHlwZW9mIGVudGl0eSA9PT0gJ3N5bWJvbCcgJiYgdHlwZW9mIHNjaGVtYS5kZW5vcm1hbGl6ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBzY2hlbWEuZGVub3JtYWxpemUoZW50aXR5LCBhcmdzLCB1bnZpc2l0KTtcbiAgfVxuXG4gIGlmIChcbiAgICBlbnRpdHkgPT09IHVuZGVmaW5lZCAmJlxuICAgIHR5cGVvZiBlbnRpdHlPcklkICE9PSAnb2JqZWN0JyAmJlxuICAgIGVudGl0eU9ySWQgIT09ICcnICYmXG4gICAgZW50aXR5T3JJZCAhPT0gJ3VuZGVmaW5lZCdcbiAgKSB7XG4gICAgLy8gd2UgY2Fubm90IHBlcmZvcm0gbG9va3VwcyB3aXRoIGB1bmRlZmluZWRgLCBzbyB3ZSB1c2UgYSBzcGVjaWFsIG9iamVjdCB0byByZXByZXNlbnQgdW5kZWZpbmVkXG4gICAgLy8gd2UncmUgYWN0dWFsbHkgdXNpbmcgdGhpcyBjYWxsIHRvIGVuc3VyZSB3ZSB1cGRhdGUgdGhlIGNhY2hlIGlmIGEgbmVzdGVkIHNjaGVtYSBjaGFuZ2VzIGZyb20gYHVuZGVmaW5lZGBcbiAgICAvLyB0aGlzIGlzIGJlY2F1c2UgY2FjaGUuZ2V0RW50aXR5IGFkZHMgdGhpcyBrZXkscGsgYXMgYSBkZXBlbmRlbmN5IG9mIGFueXRoaW5nIGl0IGlzIG5lc3RlZCB1bmRlclxuICAgIHJldHVybiBjYWNoZS5nZXRFbnRpdHkoZW50aXR5T3JJZCwgc2NoZW1hLCBVTkRFRiwgbG9jYWxDYWNoZUtleSA9PiB7XG4gICAgICBsb2NhbENhY2hlS2V5LnNldChlbnRpdHlPcklkLCB1bmRlZmluZWQpO1xuICAgIH0pO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBlbnRpdHkgIT09ICdvYmplY3QnIHx8IGVudGl0eSA9PT0gbnVsbCkge1xuICAgIHJldHVybiBlbnRpdHkgYXMgYW55O1xuICB9XG5cbiAgbGV0IHBrOiBzdHJpbmcgPVxuICAgIHR5cGVvZiBlbnRpdHlPcklkICE9PSAnb2JqZWN0JyA/IGVudGl0eU9ySWQgOiAoXG4gICAgICAoc2NoZW1hLnBrKFxuICAgICAgICBpc0ltbXV0YWJsZShlbnRpdHkpID8gKGVudGl0eSBhcyBhbnkpLnRvSlMoKSA6IGVudGl0eSxcbiAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgIGFyZ3MsXG4gICAgICApIGFzIGFueSlcbiAgICApO1xuXG4gIC8vIGlmIHdlIGNhbid0IGdlbmVyYXRlIGEgd29ya2luZyBwayB3ZSBjYW5ub3QgZG8gY2FjaGUgbG9va3VwcyBwcm9wZXJseSxcbiAgLy8gc28gc2ltcGx5IGRlbm9ybWFsaXplIHdpdGhvdXQgY2FjaGluZ1xuICBpZiAocGsgPT09IHVuZGVmaW5lZCB8fCBwayA9PT0gJycgfHwgcGsgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIG5vQ2FjaGVHZXRFbnRpdHkobG9jYWxDYWNoZUtleSA9PlxuICAgICAgdW52aXNpdEVudGl0eU9iamVjdChlbnRpdHksIHNjaGVtYSwgdW52aXNpdCwgJycsIGxvY2FsQ2FjaGVLZXksIGFyZ3MpLFxuICAgICk7XG4gIH1cblxuICAvLyBqdXN0IGFuIG9wdGltaXphdGlvbiB0byBtYWtlIGFsbCBjYWNoZSB1c2FnZXMgb2YgcGsgbW9ub21vcnBoaWNcbiAgaWYgKHR5cGVvZiBwayAhPT0gJ3N0cmluZycpIHBrID0gYCR7cGt9YDtcblxuICAvLyBsYXN0IGZ1bmN0aW9uIGNvbXB1dGVzIGlmIGl0IGlzIG5vdCBpbiBhbnkgY2FjaGVzXG4gIHJldHVybiBjYWNoZS5nZXRFbnRpdHkocGssIHNjaGVtYSwgZW50aXR5LCBsb2NhbENhY2hlS2V5ID0+XG4gICAgdW52aXNpdEVudGl0eU9iamVjdChlbnRpdHksIHNjaGVtYSwgdW52aXNpdCwgcGssIGxvY2FsQ2FjaGVLZXksIGFyZ3MpLFxuICApO1xufVxuXG5mdW5jdGlvbiBub0NhY2hlR2V0RW50aXR5KFxuICBjb21wdXRlVmFsdWU6IChsb2NhbENhY2hlS2V5OiBNYXA8c3RyaW5nLCBhbnk+KSA9PiB2b2lkLFxuKTogb2JqZWN0IHwgdW5kZWZpbmVkIHwgc3ltYm9sIHtcbiAgY29uc3QgbG9jYWxDYWNoZUtleSA9IG5ldyBNYXA8c3RyaW5nLCBhbnk+KCk7XG4gIGNvbXB1dGVWYWx1ZShsb2NhbENhY2hlS2V5KTtcblxuICByZXR1cm4gbG9jYWxDYWNoZUtleS5nZXQoJycpO1xufVxuXG5mdW5jdGlvbiB1bnZpc2l0RW50aXR5T2JqZWN0KFxuICBlbnRpdHk6IG9iamVjdCxcbiAgc2NoZW1hOiBFbnRpdHlJbnRlcmZhY2U8YW55PixcbiAgdW52aXNpdDogKHNjaGVtYTogYW55LCBpbnB1dDogYW55KSA9PiBhbnksXG4gIHBrOiBzdHJpbmcsXG4gIGxvY2FsQ2FjaGVLZXk6IE1hcDxzdHJpbmcsIGFueT4sXG4gIGFyZ3M6IHJlYWRvbmx5IGFueVtdLFxuKTogdm9pZCB7XG4gIGNvbnN0IGVudGl0eUNvcHkgPVxuICAgIGlzSW1tdXRhYmxlKGVudGl0eSkgP1xuICAgICAgc2NoZW1hLmNyZWF0ZUlmVmFsaWQoZW50aXR5LnRvT2JqZWN0KCkpXG4gICAgOiBzY2hlbWEuY3JlYXRlSWZWYWxpZChlbnRpdHkpO1xuICBsb2NhbENhY2hlS2V5LnNldChwaywgZW50aXR5Q29weSk7XG5cbiAgaWYgKGVudGl0eUNvcHkgPT09IHVuZGVmaW5lZCkge1xuICAgIC8vIHVuZGVmaW5lZCBpbmRpY2F0ZXMgd2Ugc2hvdWxkIHN1c3BlbnNlIChwZXJoYXBzIGZhaWxlZCB2YWxpZGF0aW9uKVxuICAgIGxvY2FsQ2FjaGVLZXkuc2V0KHBrLCBJTlZBTElEKTtcbiAgfSBlbHNlIHtcbiAgICBpZiAodHlwZW9mIHNjaGVtYS5kZW5vcm1hbGl6ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgbG9jYWxDYWNoZUtleS5zZXQocGssIHNjaGVtYS5kZW5vcm1hbGl6ZShlbnRpdHlDb3B5LCBhcmdzLCB1bnZpc2l0KSk7XG4gICAgfVxuICB9XG59XG5cbmNvbnN0IGdldFVudmlzaXQgPSAoXG4gIGdldEVudGl0eTogR2V0RW50aXR5LFxuICBjYWNoZTogQ2FjaGUsXG4gIGFyZ3M6IHJlYWRvbmx5IGFueVtdLFxuKSA9PiB7XG4gIGZ1bmN0aW9uIHVudmlzaXQoc2NoZW1hOiBhbnksIGlucHV0OiBhbnkpOiBhbnkge1xuICAgIGlmICghc2NoZW1hKSByZXR1cm4gaW5wdXQ7XG5cbiAgICBpZiAoaW5wdXQgPT09IG51bGwgfHwgaW5wdXQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGlucHV0O1xuICAgIH1cblxuICAgIGlmICh0eXBlb2Ygc2NoZW1hLmRlbm9ybWFsaXplICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBkZXNlcmlhbGl6ZSBmaWVsZHMgKGxpa2UgVGVtcG9yYWwuSW5zdGFudClcbiAgICAgIGlmICh0eXBlb2Ygc2NoZW1hID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBzY2hlbWEoaW5wdXQpO1xuICAgICAgfVxuXG4gICAgICAvLyBzaG9ydGhhbmQgZm9yIG9iamVjdCwgYXJyYXlcbiAgICAgIGlmICh0eXBlb2Ygc2NoZW1hID09PSAnb2JqZWN0Jykge1xuICAgICAgICBjb25zdCBtZXRob2QgPVxuICAgICAgICAgIEFycmF5LmlzQXJyYXkoc2NoZW1hKSA/IGFycmF5RGVub3JtYWxpemUgOiBvYmplY3REZW5vcm1hbGl6ZTtcbiAgICAgICAgcmV0dXJuIG1ldGhvZChzY2hlbWEsIGlucHV0LCBhcmdzLCB1bnZpc2l0KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGlzRW50aXR5KHNjaGVtYSkpIHtcbiAgICAgICAgcmV0dXJuIHVudmlzaXRFbnRpdHkoc2NoZW1hLCBpbnB1dCwgYXJncywgdW52aXNpdCwgZ2V0RW50aXR5LCBjYWNoZSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzY2hlbWEuZGVub3JtYWxpemUoaW5wdXQsIGFyZ3MsIHVudmlzaXQpO1xuICAgIH1cblxuICAgIHJldHVybiBpbnB1dDtcbiAgfVxuXG4gIHJldHVybiAoc2NoZW1hOiBhbnksIGlucHV0OiBhbnkpOiB7IGRhdGE6IGFueTsgcGF0aHM6IEVudGl0eVBhdGhbXSB9ID0+IHtcbiAgICAvLyBpbiB0aGUgY2FzZSB3aGVyZSBXZWFrTWFwIGNhbm5vdCBiZSB1c2VkXG4gICAgLy8gdGhpcyB0ZXN0IGVuc3VyZXMgbnVsbCBpcyBwcm9wZXJseSBleGNsdWRlZCBmcm9tIFdlYWtNYXBcbiAgICBjb25zdCBjYWNoYWJsZSA9IE9iamVjdChpbnB1dCkgPT09IGlucHV0ICYmIE9iamVjdChzY2hlbWEpID09PSBzY2hlbWE7XG4gICAgcmV0dXJuIGNhY2hlLmdldFJlc3VsdHMoaW5wdXQsIGNhY2hhYmxlLCAoKSA9PiB1bnZpc2l0KHNjaGVtYSwgaW5wdXQpKTtcbiAgfTtcbn07XG5leHBvcnQgZGVmYXVsdCBnZXRVbnZpc2l0O1xuIl0sIm1hcHBpbmdzIjoiQUFFQSxTQUFTQSxPQUFPLFFB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