@data-client/normalizr
Version:
Normalizes and denormalizes JSON according to schema for Redux and Flux applications
97 lines (93 loc) • 15.9 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 { denormalize as objectDenormalize } from '../schemas/Object.js';
const getUnvisitEntity = (getEntity, cache, args, unvisit) => {
return function unvisitEntity(schema, entityOrId) {
const inputIsId = typeof entityOrId !== 'object';
const entity = inputIsId ? getEntity({
key: schema.key,
pk: entityOrId
}) : entityOrId;
if (typeof entity === 'symbol') {
return schema.denormalize(entity, args, unvisit);
}
if (entity === undefined && inputIsId &&
// entityOrId cannot be undefined literal as this function wouldn't be called in that case
// however the blank strings can still occur
entityOrId !== '' && entityOrId !== 'undefined') {
// we cannot perform WeakMap 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 = inputIsId ? entityOrId : schema.pk(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(schema, entity, '', localCacheKey, args, unvisit));
}
// 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(schema, entity, pk, localCacheKey, args, unvisit));
};
};
function unvisitEntityObject(schema, entity, pk, localCacheKey, args, unvisit) {
const entityCopy = schema.createIfValid(entity);
if (entityCopy === undefined) {
// undefined indicates we should suspense (perhaps failed validation)
localCacheKey.set(pk, INVALID);
} else {
// set before we recurse to prevent cycles causing infinite loops
localCacheKey.set(pk, entityCopy);
// we still need to set in case denormalize recursively finds INVALID
localCacheKey.set(pk, schema.denormalize(entityCopy, args, unvisit));
}
}
function noCacheGetEntity(computeValue) {
const localCacheKey = new Map();
computeValue(localCacheKey);
return localCacheKey.get('');
}
const getUnvisit = (getEntity, cache, args) => {
// we don't inline this as making this function too big inhibits v8's JIT
const unvisitEntity = getUnvisitEntity(getEntity, cache, args, unvisit);
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);
}
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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJJTlZBTElEIiwiVU5ERUYiLCJpc0VudGl0eSIsImRlbm9ybWFsaXplIiwiYXJyYXlEZW5vcm1hbGl6ZSIsIm9iamVjdERlbm9ybWFsaXplIiwiZ2V0VW52aXNpdEVudGl0eSIsImdldEVudGl0eSIsImNhY2hlIiwiYXJncyIsInVudmlzaXQiLCJ1bnZpc2l0RW50aXR5Iiwic2NoZW1hIiwiZW50aXR5T3JJZCIsImlucHV0SXNJZCIsImVudGl0eSIsImtleSIsInBrIiwidW5kZWZpbmVkIiwibG9jYWxDYWNoZUtleSIsInNldCIsIm5vQ2FjaGVHZXRFbnRpdHkiLCJ1bnZpc2l0RW50aXR5T2JqZWN0IiwiZW50aXR5Q29weSIsImNyZWF0ZUlmVmFsaWQiLCJjb21wdXRlVmFsdWUiLCJNYXAiLCJnZXQiLCJnZXRVbnZpc2l0IiwiaW5wdXQiLCJtZXRob2QiLCJBcnJheSIsImlzQXJyYXkiLCJjYWNoYWJsZSIsIk9iamVjdCIsImdldFJlc3VsdHMiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvZGVub3JtYWxpemUvdW52aXNpdC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSBDYWNoZSBmcm9tICcuL2NhY2hlLmpzJztcbmltcG9ydCB7IElOVkFMSUQgfSBmcm9tICcuL3N5bWJvbC5qcyc7XG5pbXBvcnQgeyBVTkRFRiB9IGZyb20gJy4vVU5ERUYuanMnO1xuaW1wb3J0IHR5cGUgeyBFbnRpdHlJbnRlcmZhY2UsIEVudGl0eVBhdGggfSBmcm9tICcuLi9pbnRlcmZhY2UuanMnO1xuaW1wb3J0IHsgaXNFbnRpdHkgfSBmcm9tICcuLi9pc0VudGl0eS5qcyc7XG5pbXBvcnQgdHlwZSB7IERlbm9ybUdldEVudGl0eSB9IGZyb20gJy4uL21lbW8vdHlwZXMuanMnO1xuaW1wb3J0IHsgZGVub3JtYWxpemUgYXMgYXJyYXlEZW5vcm1hbGl6ZSB9IGZyb20gJy4uL3NjaGVtYXMvQXJyYXkuanMnO1xuaW1wb3J0IHsgZGVub3JtYWxpemUgYXMgb2JqZWN0RGVub3JtYWxpemUgfSBmcm9tICcuLi9zY2hlbWFzL09iamVjdC5qcyc7XG5cbmNvbnN0IGdldFVudmlzaXRFbnRpdHkgPSAoXG4gIGdldEVudGl0eTogRGVub3JtR2V0RW50aXR5LFxuICBjYWNoZTogQ2FjaGUsXG4gIGFyZ3M6IHJlYWRvbmx5IGFueVtdLFxuICB1bnZpc2l0OiAoc2NoZW1hOiBhbnksIGlucHV0OiBhbnkpID0+IGFueSxcbikgPT4ge1xuICByZXR1cm4gZnVuY3Rpb24gdW52aXNpdEVudGl0eShcbiAgICBzY2hlbWE6IEVudGl0eUludGVyZmFjZSxcbiAgICBlbnRpdHlPcklkOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHwgc3RyaW5nLFxuICApOiBvYmplY3QgfCB1bmRlZmluZWQgfCB0eXBlb2YgSU5WQUxJRCB7XG4gICAgY29uc3QgaW5wdXRJc0lkID0gdHlwZW9mIGVudGl0eU9ySWQgIT09ICdvYmplY3QnO1xuICAgIGNvbnN0IGVudGl0eSA9XG4gICAgICBpbnB1dElzSWQgPyBnZXRFbnRpdHkoeyBrZXk6IHNjaGVtYS5rZXksIHBrOiBlbnRpdHlPcklkIH0pIDogZW50aXR5T3JJZDtcbiAgICBpZiAodHlwZW9mIGVudGl0eSA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHJldHVybiBzY2hlbWEuZGVub3JtYWxpemUoZW50aXR5LCBhcmdzLCB1bnZpc2l0KTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBlbnRpdHkgPT09IHVuZGVmaW5lZCAmJlxuICAgICAgaW5wdXRJc0lkICYmXG4gICAgICAvLyBlbnRpdHlPcklkIGNhbm5vdCBiZSB1bmRlZmluZWQgbGl0ZXJhbCBhcyB0aGlzIGZ1bmN0aW9uIHdvdWxkbid0IGJlIGNhbGxlZCBpbiB0aGF0IGNhc2VcbiAgICAgIC8vIGhvd2V2ZXIgdGhlIGJsYW5rIHN0cmluZ3MgY2FuIHN0aWxsIG9jY3VyXG4gICAgICBlbnRpdHlPcklkICE9PSAnJyAmJlxuICAgICAgZW50aXR5T3JJZCAhPT0gJ3VuZGVmaW5lZCdcbiAgICApIHtcbiAgICAgIC8vIHdlIGNhbm5vdCBwZXJmb3JtIFdlYWtNYXAgbG9va3VwcyB3aXRoIGB1bmRlZmluZWRgLCBzbyB3ZSB1c2UgYSBzcGVjaWFsIG9iamVjdCB0byByZXByZXNlbnQgdW5kZWZpbmVkXG4gICAgICAvLyB3ZSdyZSBhY3R1YWxseSB1c2luZyB0aGlzIGNhbGwgdG8gZW5zdXJlIHdlIHVwZGF0ZSB0aGUgY2FjaGUgaWYgYSBuZXN0ZWQgc2NoZW1hIGNoYW5nZXMgZnJvbSBgdW5kZWZpbmVkYFxuICAgICAgLy8gdGhpcyBpcyBiZWNhdXNlIGNhY2hlLmdldEVudGl0eSBhZGRzIHRoaXMga2V5LHBrIGFzIGEgZGVwZW5kZW5jeSBvZiBhbnl0aGluZyBpdCBpcyBuZXN0ZWQgdW5kZXJcbiAgICAgIHJldHVybiBjYWNoZS5nZXRFbnRpdHkoZW50aXR5T3JJZCwgc2NoZW1hLCBVTkRFRiwgbG9jYWxDYWNoZUtleSA9PiB7XG4gICAgICAgIGxvY2FsQ2FjaGVLZXkuc2V0KGVudGl0eU9ySWQsIHVuZGVmaW5lZCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGVudGl0eSAhPT0gJ29iamVjdCcgfHwgZW50aXR5ID09PSBudWxsKSB7XG4gICAgICByZXR1cm4gZW50aXR5IGFzIGFueTtcbiAgICB9XG5cbiAgICBsZXQgcGs6IHN0cmluZyB8IG51bWJlciB8IHVuZGVmaW5lZCA9XG4gICAgICBpbnB1dElzSWQgPyBlbnRpdHlPcklkIDogKFxuICAgICAgICAoc2NoZW1hLnBrKGVudGl0eSwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIGFyZ3MpIGFzIGFueSlcbiAgICAgICk7XG5cbiAgICAvLyBpZiB3ZSBjYW4ndCBnZW5lcmF0ZSBhIHdvcmtpbmcgcGsgd2UgY2Fubm90IGRvIGNhY2hlIGxvb2t1cHMgcHJvcGVybHksXG4gICAgLy8gc28gc2ltcGx5IGRlbm9ybWFsaXplIHdpdGhvdXQgY2FjaGluZ1xuICAgIGlmIChwayA9PT0gdW5kZWZpbmVkIHx8IHBrID09PSAnJyB8fCBwayA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiBub0NhY2hlR2V0RW50aXR5KGxvY2FsQ2FjaGVLZXkgPT5cbiAgICAgICAgdW52aXNpdEVudGl0eU9iamVjdChzY2hlbWEsIGVudGl0eSwgJycsIGxvY2FsQ2FjaGVLZXksIGFyZ3MsIHVudmlzaXQpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBqdXN0IGFuIG9wdGltaXphdGlvbiB0byBtYWtlIGFsbCBjYWNoZSB1c2FnZXMgb2YgcGsgbW9ub21vcnBoaWNcbiAgICBpZiAodHlwZW9mIHBrICE9PSAnc3RyaW5nJykgcGsgPSBgJHtwa31gO1xuXG4gICAgLy8gbGFzdCBmdW5jdGlvbiBjb21wdXRlcyBpZiBpdCBpcyBub3QgaW4gYW55IGNhY2hlc1xuICAgIHJldHVybiBjYWNoZS5nZXRFbnRpdHkocGssIHNjaGVtYSwgZW50aXR5LCBsb2NhbENhY2hlS2V5ID0+XG4gICAgICB1bnZpc2l0RW50aXR5T2JqZWN0KHNjaGVtYSwgZW50aXR5LCBwaywgbG9jYWxDYWNoZUtleSwgYXJncywgdW52aXNpdCksXG4gICAgKTtcbiAgfTtcbn07XG5cbmZ1bmN0aW9uIHVudmlzaXRFbnRpdHlPYmplY3QoXG4gIHNjaGVtYTogRW50aXR5SW50ZXJmYWNlPGFueT4sXG4gIGVudGl0eTogb2JqZWN0LFxuICBwazogc3RyaW5nLFxuICBsb2NhbENhY2hlS2V5OiBNYXA8c3RyaW5nLCBhbnk+LFxuICBhcmdzOiByZWFkb25seSBhbnlbXSxcbiAgdW52aXNpdDogKHNjaGVtYTogYW55LCBpbnB1dDogYW55KSA9PiBhbnksXG4pOiB2b2lkIHtcbiAgY29uc3QgZW50aXR5Q29weSA9IHNjaGVtYS5jcmVhdGVJZlZhbGlkKGVudGl0eSk7XG5cbiAgaWYgKGVudGl0eUNvcHkgPT09IHVuZGVmaW5lZCkge1xuICAgIC8vIHVuZGVmaW5lZCBpbmRpY2F0ZXMgd2Ugc2hvdWxkIHN1c3BlbnNlIChwZXJoYXBzIGZhaWxlZCB2YWxpZGF0aW9uKVxuICAgIGxvY2FsQ2FjaGVLZXkuc2V0KHBrLCBJTlZBTElEKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBzZXQgYmVmb3JlIHdlIHJlY3Vyc2UgdG8gcHJldmVudCBjeWNsZXMgY2F1c2luZyBpbmZpbml0ZSBsb29wc1xuICAgIGxvY2FsQ2FjaGVLZXkuc2V0KHBrLCBlbnRpdHlDb3B5KTtcbiAgICAvLyB3ZSBzdGlsbCBuZWVkIHRvIHNldCBpbiBjYXNlIGRlbm9ybWFsaXplIHJlY3Vyc2l2ZWx5IGZpbmRzIElOVkFMSURcbiAgICBsb2NhbENhY2hlS2V5LnNldChwaywgc2NoZW1hLmRlbm9ybWFsaXplKGVudGl0eUNvcHksIGFyZ3MsIHVudmlzaXQpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBub0NhY2hlR2V0RW50aXR5KFxuICBjb21wdXRlVmFsdWU6IChsb2NhbENhY2hlS2V5OiBNYXA8c3RyaW5nLCBhbnk+KSA9PiB2b2lkLFxuKTogb2JqZWN0IHwgdW5kZWZpbmVkIHwgdHlwZW9mIElOVkFMSUQge1xuICBjb25zdCBsb2NhbENhY2hlS2V5ID0gbmV3IE1hcDxzdHJpbmcsIGFueT4oKTtcbiAgY29tcHV0ZVZhbHVlKGxvY2FsQ2FjaGVLZXkpO1xuXG4gIHJldHVybiBsb2NhbENhY2hlS2V5LmdldCgnJyk7XG59XG5cbmNvbnN0IGdldFVudmlzaXQgPSAoXG4gIGdldEVudGl0eTogRGVub3JtR2V0RW50aXR5LFxuICBjYWNoZTogQ2FjaGUsXG4gIGFyZ3M6IHJlYWRvbmx5IGFueVtdLFxuKSA9PiB7XG4gIC8vIHdlIGRvbid0IGlubGluZSB0aGlzIGFzIG1ha2luZyB0aGlzIGZ1bmN0aW9uIHRvbyBiaWcgaW5oaWJpdHMgdjgncyBKSVRcbiAgY29uc3QgdW52aXNpdEVudGl0eSA9IGdldFVudmlzaXRFbnRpdHkoZ2V0RW50aXR5LCBjYWNoZSwgYXJncywgdW52aXNpdCk7XG4gIGZ1bmN0aW9uIHVudmlzaXQoc2NoZW1hOiBhbnksIGlucHV0OiBhbnkpOiBhbnkge1xuICAgIGlmICghc2NoZW1hKSByZXR1cm4gaW5wdXQ7XG5cbiAgICBpZiAoaW5wdXQgPT09IG51bGwgfHwgaW5wdXQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGlucHV0O1xuICAgIH1cblxuICAgIGlmICh0eXBlb2Ygc2NoZW1hLmRlbm9ybWFsaXplICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBkZXNlcmlhbGl6ZSBmaWVsZHMgKGxpa2UgVGVtcG9yYWwuSW5zdGFudClcbiAgICAgIGlmICh0eXBlb2Ygc2NoZW1hID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBzY2hlbWEoaW5wdXQpO1xuICAgICAgfVxuXG4gICAgICAvLyBzaG9ydGhhbmQgZm9yIG9iamVjdCwgYXJyYXlcbiAgICAgIGlmICh0eXBlb2Ygc2NoZW1hID09PSAnb2JqZWN0Jykge1xuICAgICAgICBjb25zdCBtZXRob2QgPVxuICAgICAgICAgIEFycmF5LmlzQXJyYXkoc2NoZW1hKSA/IGFycmF5RGVub3JtYWxpemUgOiBvYmplY3REZW5vcm1hbGl6ZTtcbiAgICAgICAgcmV0dXJuIG1ldGhvZChzY2hlbWEsIGlucHV0LCBhcmdzLCB1bnZpc2l0KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGlzRW50aXR5KHNjaGVtYSkpIHtcbiAgICAgICAgcmV0dXJuIHVudmlzaXRFbnRpdHkoc2NoZW1hLCBpbnB1dCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzY2hlbWEuZGVub3JtYWxpemUoaW5wdXQsIGFyZ3MsIHVudmlzaXQpO1xuICAgIH1cblxuICAgIHJldHVybiBpbnB1dDtcbiAgfVxuXG4gIHJldHVybiAoc2NoZW1hOiBhbnksIGlucHV0OiBhbnkpOiB7IGRhdGE6IGFueTsgcGF0aHM6IEVudGl0eVBhdGhbXSB9ID0+IHtcbiAgICAvLyBpbiB0aGUgY2FzZSB3aGVyZSBXZWFrTWFwIGNhbm5vdCBiZSB1c2VkXG4gICAgLy8gdGhpcyB0ZXN0IGVuc3VyZXMgbnVsbCBpcyBwcm9wZXJseSBleGNsdWRlZCBmcm9tIFdlYWtNYXBcbiAgICBjb25zdCBjYWNoYWJsZSA9IE9iamVjdChpbnB1dCkgPT09IGlucHV0ICYmIE9iamVjdChzY2hlbWEpID09PSBzY2hlbWE7XG4gICAgcmV0dXJuIGNhY2hlLmdldFJlc3VsdHMoaW5wdXQsIGNhY2hhYmxlLCAoKSA9PiB1bnZpc2l0KHNjaGVtYSwgaW5wdXQpKTtcbiAgfTtcbn07XG5leHBvcnQgZGVmYXVsdCBnZXRVbnZpc2l0O1xuIl0sIm1hcHBpbmdzIjoiQUFDQSxTQUFTQSxPQUFPLFFBQVEsYUFBYTtBQUNyQyxTQUFTQyxLQUFLLFFBQVEsWUFBWTtBQUVsQyxTQUFTQyxRQUFRLFFBQVEsZ0JBQWdCO0FBRXpDLFNBQVNDLFdBQVcsSUFBSUMsZ0JBQWdCLFFBQVEscUJBQXFCO0FBQ3JFLFNBQVNELFdBQVcsSUFBSUUsaUJBQWlCLFFBQVEsc0JBQXNCO0FBRXZFLE1BQU1DLGdCQUFnQixHQUFHQSxDQUN2QkMsU0FBMEIsRUFDMUJDLEtBQVksRUFDWkMsSUFBb0IsRUFDcEJDLE9BQXlDLEtBQ3RDO0VBQ0gsT0FBTyxTQUFTQyxhQUFhQSxDQUMzQkMsTUFBdUIsRUFDdkJDLFVBQXdDLEVBQ0g7SUFDckMsTUFBTUMsU0FBUyxHQUFHLE9BQU9ELFVBQVUsS0FBSyxRQUFRO0lBQ2hELE1BQU1FLE1BQU0sR0FDVkQsU0FBUyxHQUFHUCxTQUFTLENBQUM7TUFBRVMsR0FBRyxFQUFFSixNQUFNLENBQUNJLEdBQUc7TUFBRUMsRUFBRSxFQUFFSjtJQUFXLENBQUMsQ0FBQyxHQUFHQSxVQUFVO0lBQ3pFLElBQUksT0FBT0UsTUFBTSxLQUFLLFFBQVEsRUFBRTtNQUM5QixPQUFPSCxNQUFNLENBQUNULFdBQVcsQ0FBQ1ksTUFBTSxFQUFFTixJQUFJLEVBQUVDLE9BQU8sQ0FBQztJQUNsRDtJQUVBLElBQ0VLLE1BQU0sS0FBS0csU0FBUyxJQUNwQkosU0FBUztJQUNUO0lBQ0E7SUFDQUQsVUFBVSxLQUFLLEVBQUUsSUFDakJBLFVBQVUsS0FBSyxXQUFXLEVBQzFCO01BQ0E7TUFDQTtNQUNBO01BQ0EsT0FBT0wsS0FBSyxDQUFD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