@data-client/normalizr
Version:
Normalizes and denormalizes JSON according to schema for Redux and Flux applications
62 lines (61 loc) • 12.3 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import { INVALID } from '../denormalize/symbol.js';
export const addEntities = (newEntities, newIndexes, entitiesCopy, indexesCopy, entityMetaCopy, actionMeta) => (schema, processedEntity, id) => {
const schemaKey = schema.key;
// first time we come across this type of entity
if (!newEntities.has(schemaKey)) {
newEntities.set(schemaKey, new Map());
// we will be editing these, so we need to clone them first
entitiesCopy[schemaKey] = _extends({}, entitiesCopy[schemaKey]);
entityMetaCopy[schemaKey] = _extends({}, entityMetaCopy[schemaKey]);
}
const newEntitiesKey = newEntities.get(schemaKey);
const existingEntity = newEntitiesKey.get(id);
if (existingEntity) {
newEntitiesKey.set(id, schema.merge(existingEntity, processedEntity));
} else {
const inStoreEntity = entitiesCopy[schemaKey][id];
let inStoreMeta;
// this case we already have this entity in store
if (inStoreEntity && (inStoreMeta = entityMetaCopy[schemaKey][id])) {
newEntitiesKey.set(id, schema.mergeWithStore(inStoreMeta, actionMeta, inStoreEntity, processedEntity));
entityMetaCopy[schemaKey][id] = schema.mergeMetaWithStore(inStoreMeta, actionMeta, inStoreEntity, processedEntity);
} else {
newEntitiesKey.set(id, processedEntity);
entityMetaCopy[schemaKey][id] = actionMeta;
}
}
// update index
if (schema.indexes) {
if (!newIndexes.has(schemaKey)) {
newIndexes.set(schemaKey, new Map());
indexesCopy[schemaKey] = _extends({}, indexesCopy[schemaKey]);
}
handleIndexes(id, schema.indexes, newIndexes.get(schemaKey), indexesCopy[schemaKey], newEntitiesKey.get(id), entitiesCopy[schemaKey]);
}
// set this after index updates so we know what indexes to remove from
entitiesCopy[schemaKey][id] = newEntitiesKey.get(id);
};
function handleIndexes(id, schemaIndexes, indexes, storeIndexes, entity, storeEntities) {
for (const index of schemaIndexes) {
if (!indexes.has(index)) {
indexes.set(index, storeIndexes[index] = {});
}
const indexMap = indexes.get(index);
if (storeEntities[id]) {
delete indexMap[storeEntities[id][index]];
}
// entity already in cache but the index changed
if (storeEntities && storeEntities[id] && storeEntities[id][index] !== entity[index]) {
indexMap[storeEntities[id][index]] = INVALID;
}
if (index in entity) {
indexMap[entity[index]] = id;
} /* istanbul ignore next */else if (process.env.NODE_ENV !== 'production') {
console.warn(`Index not found in entity. Indexes must be top-level members of your entity.
Index: ${index}
Entity: ${JSON.stringify(entity, undefined, 2)}`);
}
}
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJJTlZBTElEIiwiYWRkRW50aXRpZXMiLCJuZXdFbnRpdGllcyIsIm5ld0luZGV4ZXMiLCJlbnRpdGllc0NvcHkiLCJpbmRleGVzQ29weSIsImVudGl0eU1ldGFDb3B5IiwiYWN0aW9uTWV0YSIsInNjaGVtYSIsInByb2Nlc3NlZEVudGl0eSIsImlkIiwic2NoZW1hS2V5Iiwia2V5IiwiaGFzIiwic2V0IiwiTWFwIiwiX2V4dGVuZHMiLCJuZXdFbnRpdGllc0tleSIsImdldCIsImV4aXN0aW5nRW50aXR5IiwibWVyZ2UiLCJpblN0b3JlRW50aXR5IiwiaW5TdG9yZU1ldGEiLCJtZXJnZVdpdGhTdG9yZSIsIm1lcmdlTWV0YVdpdGhTdG9yZSIsImluZGV4ZXMiLCJoYW5kbGVJbmRleGVzIiwic2NoZW1hSW5kZXhlcyIsInN0b3JlSW5kZXhlcyIsImVudGl0eSIsInN0b3JlRW50aXRpZXMiLCJpbmRleCIsImluZGV4TWFwIiwicHJvY2VzcyIsImVudiIsIk5PREVfRU5WIiwiY29uc29sZSIsIndhcm4iLCJKU09OIiwic3RyaW5naWZ5IiwidW5kZWZpbmVkIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL25vcm1hbGl6ci9hZGRFbnRpdGllcy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJTlZBTElEIH0gZnJvbSAnLi4vZGVub3JtYWxpemUvc3ltYm9sLmpzJztcbmltcG9ydCB0eXBlIHsgRW50aXR5SW50ZXJmYWNlIH0gZnJvbSAnLi4vaW50ZXJmYWNlLmpzJztcblxuZXhwb3J0IGNvbnN0IGFkZEVudGl0aWVzID1cbiAgKFxuICAgIG5ld0VudGl0aWVzOiBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBhbnk+PixcbiAgICBuZXdJbmRleGVzOiBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBhbnk+PixcbiAgICBlbnRpdGllc0NvcHk6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgaW5kZXhlc0NvcHk6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgZW50aXR5TWV0YUNvcHk6IHtcbiAgICAgIFtlbnRpdHlLZXk6IHN0cmluZ106IHtcbiAgICAgICAgW3BrOiBzdHJpbmddOiB7XG4gICAgICAgICAgZGF0ZTogbnVtYmVyO1xuICAgICAgICAgIGV4cGlyZXNBdDogbnVtYmVyO1xuICAgICAgICAgIGZldGNoZWRBdDogbnVtYmVyO1xuICAgICAgICB9O1xuICAgICAgfTtcbiAgICB9LFxuICAgIGFjdGlvbk1ldGE6IHsgZmV0Y2hlZEF0OiBudW1iZXI7IGRhdGU6IG51bWJlcjsgZXhwaXJlc0F0OiBudW1iZXIgfSxcbiAgKSA9PlxuICAoc2NoZW1hOiBFbnRpdHlJbnRlcmZhY2UsIHByb2Nlc3NlZEVudGl0eTogYW55LCBpZDogc3RyaW5nKSA9PiB7XG4gICAgY29uc3Qgc2NoZW1hS2V5ID0gc2NoZW1hLmtleTtcbiAgICAvLyBmaXJzdCB0aW1lIHdlIGNvbWUgYWNyb3NzIHRoaXMgdHlwZSBvZiBlbnRpdHlcbiAgICBpZiAoIW5ld0VudGl0aWVzLmhhcyhzY2hlbWFLZXkpKSB7XG4gICAgICBuZXdFbnRpdGllcy5zZXQoc2NoZW1hS2V5LCBuZXcgTWFwKCkpO1xuICAgICAgLy8gd2Ugd2lsbCBiZSBlZGl0aW5nIHRoZXNlLCBzbyB3ZSBuZWVkIHRvIGNsb25lIHRoZW0gZmlyc3RcbiAgICAgIGVudGl0aWVzQ29weVtzY2hlbWFLZXldID0geyAuLi5lbnRpdGllc0NvcHlbc2NoZW1hS2V5XSB9O1xuICAgICAgZW50aXR5TWV0YUNvcHlbc2NoZW1hS2V5XSA9IHsgLi4uZW50aXR5TWV0YUNvcHlbc2NoZW1hS2V5XSB9O1xuICAgIH1cblxuICAgIGNvbnN0IG5ld0VudGl0aWVzS2V5ID0gbmV3RW50aXRpZXMuZ2V0KHNjaGVtYUtleSkgYXMgTWFwPHN0cmluZywgYW55PjtcbiAgICBjb25zdCBleGlzdGluZ0VudGl0eSA9IG5ld0VudGl0aWVzS2V5LmdldChpZCk7XG4gICAgaWYgKGV4aXN0aW5nRW50aXR5KSB7XG4gICAgICBuZXdFbnRpdGllc0tleS5zZXQoaWQsIHNjaGVtYS5tZXJnZShleGlzdGluZ0VudGl0eSwgcHJvY2Vzc2VkRW50aXR5KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGluU3RvcmVFbnRpdHkgPSBlbnRpdGllc0NvcHlbc2NoZW1hS2V5XVtpZF07XG4gICAgICBsZXQgaW5TdG9yZU1ldGE6IHtcbiAgICAgICAgZGF0ZTogbnVtYmVyO1xuICAgICAgICBleHBpcmVzQXQ6IG51bWJlcjtcbiAgICAgICAgZmV0Y2hlZEF0OiBudW1iZXI7XG4gICAgICB9O1xuICAgICAgLy8gdGhpcyBjYXNlIHdlIGFscmVhZHkgaGF2ZSB0aGlzIGVudGl0eSBpbiBzdG9yZVxuICAgICAgaWYgKGluU3RvcmVFbnRpdHkgJiYgKGluU3RvcmVNZXRhID0gZW50aXR5TWV0YUNvcHlbc2NoZW1hS2V5XVtpZF0pKSB7XG4gICAgICAgIG5ld0VudGl0aWVzS2V5LnNldChcbiAgICAgICAgICBpZCxcbiAgICAgICAgICBzY2hlbWEubWVyZ2VXaXRoU3RvcmUoXG4gICAgICAgICAgICBpblN0b3JlTWV0YSxcbiAgICAgICAgICAgIGFjdGlvbk1ldGEsXG4gICAgICAgICAgICBpblN0b3JlRW50aXR5LFxuICAgICAgICAgICAgcHJvY2Vzc2VkRW50aXR5LFxuICAgICAgICAgICksXG4gICAgICAgICk7XG4gICAgICAgIGVudGl0eU1ldGFDb3B5W3NjaGVtYUtleV1baWRdID0gc2NoZW1hLm1lcmdlTWV0YVdpdGhTdG9yZShcbiAgICAgICAgICBpblN0b3JlTWV0YSxcbiAgICAgICAgICBhY3Rpb25NZXRhLFxuICAgICAgICAgIGluU3RvcmVFbnRpdHksXG4gICAgICAgICAgcHJvY2Vzc2VkRW50aXR5LFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmV3RW50aXRpZXNLZXkuc2V0KGlkLCBwcm9jZXNzZWRFbnRpdHkpO1xuICAgICAgICBlbnRpdHlNZXRhQ29weVtzY2hlbWFLZXldW2lkXSA9IGFjdGlvbk1ldGE7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gdXBkYXRlIGluZGV4XG4gICAgaWYgKHNjaGVtYS5pbmRleGVzKSB7XG4gICAgICBpZiAoIW5ld0luZGV4ZXMuaGFzKHNjaGVtYUtleSkpIHtcbiAgICAgICAgbmV3SW5kZXhlcy5zZXQoc2NoZW1hS2V5LCBuZXcgTWFwKCkpO1xuICAgICAgICBpbmRleGVzQ29weVtzY2hlbWFLZXldID0geyAuLi5pbmRleGVzQ29weVtzY2hlbWFLZXldIH07XG4gICAgICB9XG4gICAgICBoYW5kbGVJbmRleGVzKFxuICAgICAgICBpZCxcbiAgICAgICAgc2NoZW1hLmluZGV4ZXMsXG4gICAgICAgIG5ld0luZGV4ZXMuZ2V0KHNjaGVtYUtleSkgYXMgTWFwPHN0cmluZywgYW55PixcbiAgICAgICAgaW5kZXhlc0NvcHlbc2NoZW1hS2V5XSxcbiAgICAgICAgbmV3RW50aXRpZXNLZXkuZ2V0KGlkKSxcbiAgICAgICAgZW50aXRpZXNDb3B5W3NjaGVtYUtleV0sXG4gICAgICApO1xuICAgIH1cbiAgICAvLyBzZXQgdGhpcyBhZnRlciBpbmRleCB1cGRhdGVzIHNvIHdlIGtub3cgd2hhdCBpbmRleGVzIHRvIHJlbW92ZSBmcm9tXG4gICAgZW50aXRpZXNDb3B5W3NjaGVtYUtleV1baWRdID0gbmV3RW50aXRpZXNLZXkuZ2V0KGlkKTtcbiAgfTtcblxuZnVuY3Rpb24gaGFuZGxlSW5kZXhlcyhcbiAgaWQ6IHN0cmluZyxcbiAgc2NoZW1hSW5kZXhlczogc3RyaW5nW10sXG4gIGluZGV4ZXM6IE1hcDxzdHJpbmcsIGFueT4sXG4gIHN0b3JlSW5kZXhlczogUmVjb3JkPHN0cmluZywgYW55PixcbiAgZW50aXR5OiBhbnksXG4gIHN0b3JlRW50aXRpZXM6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4pIHtcbiAgZm9yIChjb25zdCBpbmRleCBvZiBzY2hlbWFJbmRleGVzKSB7XG4gICAgaWYgKCFpbmRleGVzLmhhcyhpbmRleCkpIHtcbiAgICAgIGluZGV4ZXMuc2V0KGluZGV4LCAoc3RvcmVJbmRleGVzW2luZGV4XSA9IHt9KSk7XG4gICAgfVxuICAgIGNvbnN0IGluZGV4TWFwID0gaW5kZXhlcy5nZXQoaW5kZXgpO1xuICAgIGlmIChzdG9yZUVudGl0aWVzW2lkXSkge1xuICAgICAgZGVsZXRlIGluZGV4TWFwW3N0b3JlRW50aXRpZXNbaWRdW2luZGV4XV07XG4gICAgfVxuICAgIC8vIGVudGl0eSBhbHJlYWR5IGluIGNhY2hlIGJ1dCB0aGUgaW5kZXggY2hhbmdlZFxuICAgIGlmIChcbiAgICAgIHN0b3JlRW50aXRpZXMgJiZcbiAgICAgIHN0b3JlRW50aXRpZXNbaWRdICYmXG4gICAgICBzdG9yZUVudGl0aWVzW2lkXVtpbmRleF0gIT09IGVudGl0eVtpbmRleF1cbiAgICApIHtcbiAgICAgIGluZGV4TWFwW3N0b3JlRW50aXRpZXNbaWRdW2luZGV4XV0gPSBJTlZBTElEO1xuICAgIH1cbiAgICBpZiAoaW5kZXggaW4gZW50aXR5KSB7XG4gICAgICBpbmRleE1hcFtlbnRpdHlbaW5kZXhdXSA9IGlkO1xuICAgIH0gLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi8gZWxzZSBpZiAoXG4gICAgICBwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nXG4gICAgKSB7XG4gICAgICBjb25zb2xlLndhcm4oYEluZGV4IG5vdCBmb3VuZCBpbiBlbnRpdHkuIEluZGV4ZXMgbXVzdCBiZSB0b3AtbGV2ZWwgbWVtYmVycyBvZiB5b3VyIGVudGl0eS5cbkluZGV4OiAke2luZGV4fVxuRW50aXR5OiAke0pTT04uc3RyaW5naWZ5KGVudGl0eSwgdW5kZWZpbmVkLCAyKX1gKTtcbiAgICB9XG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6IjtBQUFBLFNBQVNBLE9BQU8sUUFBUSwwQkFBMEI7QUFHbEQsT0FBTyxNQUFNQyxXQUFXLEdBQ3RCQSxDQUNFQyxXQUEwQyxFQUMxQ0MsVUFBeUMsRUFDekNDLFlBQWlDLEVBQ2pDQyxXQUFnQyxFQUNoQ0MsY0FRQyxFQUNEQyxVQUFrRSxLQUVwRSxDQUFDQyxNQUF1QixFQUFF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