UNPKG

@data-client/normalizr

Version:

Normalizes and denormalizes JSON according to schema for Redux and Flux applications

148 lines (143 loc) 19 kB
import WeakDependencyMap from './WeakDependencyMap.js'; export default class GlobalCache { constructor(getEntity, entityCache, resultCache) { this.dependencies = []; this.cycleCache = new Map(); this.cycleIndex = -1; this.localCache = new Map(); this._getEntity = getEntity; this.getCache = getEntityCaches(entityCache); this.resultCache = resultCache; } getEntity(pk, schema, entity, computeValue) { const key = schema.key; const { localCacheKey, cycleCacheKey } = this.getCacheKey(key); if (!localCacheKey.get(pk)) { const globalCache = this.getCache(pk, schema); const [cacheValue, cachePath] = globalCache.get(entity, this._getEntity); // TODO: what if this just returned the deps - then we don't need to store them if (cachePath) { localCacheKey.set(pk, cacheValue.value); // TODO: can we store the cache values instead of tracking *all* their sources? // this is only used for setting endpoints cache correctly. if we got this far we will def need to set as we would have already tried getting it this.dependencies.push(...cacheValue.dependencies); return cacheValue.value; } // if we don't find in denormalize cache then do full denormalize else { const trackingIndex = this.dependencies.length; cycleCacheKey.set(pk, trackingIndex); this.dependencies.push({ entity, path: { key, pk } }); /** NON-GLOBAL_CACHE CODE */ computeValue(localCacheKey); /** /END NON-GLOBAL_CACHE CODE */ cycleCacheKey.delete(pk); // if in cycle, use the start of the cycle to track all deps // otherwise, we use our own trackingIndex const localKey = this.dependencies.slice(this.cycleIndex === -1 ? trackingIndex : this.cycleIndex); const cacheValue = { dependencies: localKey, value: localCacheKey.get(pk) }; globalCache.set(localKey, cacheValue); // start of cycle - reset cycle detection if (this.cycleIndex === trackingIndex) { this.cycleIndex = -1; } } } else { // cycle detected if (cycleCacheKey.has(pk)) { this.cycleIndex = cycleCacheKey.get(pk); } else { // with no cycle, globalCacheEntry will have already been set this.dependencies.push({ entity, path: { key, pk } }); } } return localCacheKey.get(pk); } getCacheKey(key) { if (!this.localCache.has(key)) { this.localCache.set(key, new Map()); } if (!this.cycleCache.has(key)) { this.cycleCache.set(key, new Map()); } const localCacheKey = this.localCache.get(key); const cycleCacheKey = this.cycleCache.get(key); return { localCacheKey, cycleCacheKey }; } /** Cache varies based on input (=== aka reference) */ getResults(input, cachable, computeValue) { if (!cachable) { return { data: computeValue(), paths: this.paths() }; } let [data, paths] = this.resultCache.get(input, this._getEntity); if (paths === undefined) { data = computeValue(); // we want to do this before we add our 'input' entry paths = this.paths(); // for the first entry, `path` is ignored so empty members is fine this.dependencies.unshift({ entity: input, path: { key: '', pk: '' } }); this.resultCache.set(this.dependencies, data); } else { paths.shift(); } return { data, paths }; } paths() { return this.dependencies.map(dep => dep.path); } } const getEntityCaches = entityCache => { return (pk, schema) => { var _ref; const key = schema.key; // collections should use the entities they collect over // TODO: this should be based on a public interface const entityInstance = (_ref = schema.cacheWith) != null ? _ref : schema; if (!entityCache.has(key)) { entityCache.set(key, new Map()); } const entityCacheKey = entityCache.get(key); if (!entityCacheKey.get(pk)) entityCacheKey.set(pk, new WeakMap()); const entityCachePk = entityCacheKey.get(pk); let wem = entityCachePk.get(entityInstance); if (!wem) { wem = new WeakDependencyMap(); entityCachePk.set(entityInstance, wem); } return wem; }; }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJXZWFrRGVwZW5kZW5jeU1hcCIsIkdsb2JhbENhY2hlIiwiY29uc3RydWN0b3IiLCJnZXRFbnRpdHkiLCJlbnRpdHlDYWNoZSIsInJlc3VsdENhY2hlIiwiZGVwZW5kZW5jaWVzIiwiY3ljbGVDYWNoZSIsIk1hcCIsImN5Y2xlSW5kZXgiLCJsb2NhbENhY2hlIiwiX2dldEVudGl0eSIsImdldENhY2hlIiwiZ2V0RW50aXR5Q2FjaGVzIiwicGsiLCJzY2hlbWEiLCJlbnRpdHkiLCJjb21wdXRlVmFsdWUiLCJrZXkiLCJsb2NhbENhY2hlS2V5IiwiY3ljbGVDYWNoZUtleSIsImdldENhY2hlS2V5IiwiZ2V0IiwiZ2xvYmFsQ2FjaGUiLCJjYWNoZVZhbHVlIiwiY2FjaGVQYXRoIiwic2V0IiwidmFsdWUiLCJwdXNoIiwidHJhY2tpbmdJbmRleCIsImxlbmd0aCIsInBhdGgiLCJkZWxldGUiLCJsb2NhbEtleSIsInNsaWNlIiwiaGFzIiwiZ2V0UmVzdWx0cyIsImlucHV0IiwiY2FjaGFibGUiLCJkYXRhIiwicGF0aHMiLCJ1bmRlZmluZWQiLCJ1bnNoaWZ0Iiwic2hpZnQiLCJtYXAiLCJkZXAiLCJfcmVmIiwiZW50aXR5SW5zdGFuY2UiLCJjYWNoZVdpdGgiLCJlbnRpdHlDYWNoZUtleSIsIldlYWtNYXAiLCJlbnRpdHlDYWNoZVBrIiwid2VtIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbW8vZ2xvYmFsQ2FjaGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRW5kcG9pbnRzQ2FjaGUsIEVudGl0eUNhY2hlIH0gZnJvbSAnLi90eXBlcy5qcyc7XG5pbXBvcnQgV2Vha0RlcGVuZGVuY3lNYXAsIHsgdHlwZSBEZXAgfSBmcm9tICcuL1dlYWtEZXBlbmRlbmN5TWFwLmpzJztcbmltcG9ydCB0eXBlIENhY2hlIGZyb20gJy4uL2Rlbm9ybWFsaXplL2NhY2hlLmpzJztcbmltcG9ydCB0eXBlIHsgR2V0RW50aXR5IH0gZnJvbSAnLi4vZGVub3JtYWxpemUvZ2V0RW50aXRpZXMuanMnO1xuaW1wb3J0IHR5cGUgeyBFbnRpdHlJbnRlcmZhY2UgfSBmcm9tICcuLi9pbnRlcmZhY2UuanMnO1xuaW1wb3J0IHR5cGUgeyBFbnRpdHlQYXRoIH0gZnJvbSAnLi4vdHlwZXMuanMnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBHbG9iYWxDYWNoZSBpbXBsZW1lbnRzIENhY2hlIHtcbiAgcHJpdmF0ZSBkZXBlbmRlbmNpZXM6IERlcDxFbnRpdHlQYXRoPltdID0gW107XG4gIHByaXZhdGUgY3ljbGVDYWNoZTogTWFwPHN0cmluZywgTWFwPHN0cmluZywgbnVtYmVyPj4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgY3ljbGVJbmRleCA9IC0xO1xuICBwcml2YXRlIGxvY2FsQ2FjaGU6IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIGFueT4+ID0gbmV3IE1hcCgpO1xuXG4gIGRlY2xhcmUgcHJpdmF0ZSBnZXRDYWNoZTogKFxuICAgIHBrOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBFbnRpdHlJbnRlcmZhY2UsXG4gICkgPT4gV2Vha0RlcGVuZGVuY3lNYXA8RW50aXR5UGF0aCwgb2JqZWN0LCBhbnk+O1xuXG4gIGRlY2xhcmUgcHJpdmF0ZSBfZ2V0RW50aXR5OiBHZXRFbnRpdHk7XG4gIGRlY2xhcmUgcHJpdmF0ZSByZXN1bHRDYWNoZTogRW5kcG9pbnRzQ2FjaGU7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgZ2V0RW50aXR5OiBHZXRFbnRpdHksXG4gICAgZW50aXR5Q2FjaGU6IEVudGl0eUNhY2hlLFxuICAgIHJlc3VsdENhY2hlOiBFbmRwb2ludHNDYWNoZSxcbiAgKSB7XG4gICAgdGhpcy5fZ2V0RW50aXR5ID0gZ2V0RW50aXR5O1xuICAgIHRoaXMuZ2V0Q2FjaGUgPSBnZXRFbnRpdHlDYWNoZXMoZW50aXR5Q2FjaGUpO1xuICAgIHRoaXMucmVzdWx0Q2FjaGUgPSByZXN1bHRDYWNoZTtcbiAgfVxuXG4gIGdldEVudGl0eShcbiAgICBwazogc3RyaW5nLFxuICAgIHNjaGVtYTogRW50aXR5SW50ZXJmYWNlLFxuICAgIGVudGl0eTogYW55LFxuICAgIGNvbXB1dGVWYWx1ZTogKGxvY2FsQ2FjaGVLZXk6IE1hcDxzdHJpbmcsIGFueT4pID0+IHZvaWQsXG4gICk6IG9iamVjdCB8IHVuZGVmaW5lZCB8IHN5bWJvbCB7XG4gICAgY29uc3Qga2V5ID0gc2NoZW1hLmtleTtcbiAgICBjb25zdCB7IGxvY2FsQ2FjaGVLZXksIGN5Y2xlQ2FjaGVLZXkgfSA9IHRoaXMuZ2V0Q2FjaGVLZXkoa2V5KTtcblxuICAgIGlmICghbG9jYWxDYWNoZUtleS5nZXQocGspKSB7XG4gICAgICBjb25zdCBnbG9iYWxDYWNoZTogV2Vha0RlcGVuZGVuY3lNYXA8XG4gICAgICAgIEVudGl0eVBhdGgsXG4gICAgICAgIG9iamVjdCxcbiAgICAgICAgRW50aXR5Q2FjaGVWYWx1ZVxuICAgICAgPiA9IHRoaXMuZ2V0Q2FjaGUocGssIHNjaGVtYSk7XG4gICAgICBjb25zdCBbY2FjaGVWYWx1ZSwgY2FjaGVQYXRoXSA9IGdsb2JhbENhY2hlLmdldChlbnRpdHksIHRoaXMuX2dldEVudGl0eSk7XG4gICAgICAvLyBUT0RPOiB3aGF0IGlmIHRoaXMganVzdCByZXR1cm5lZCB0aGUgZGVwcyAtIHRoZW4gd2UgZG9uJ3QgbmVlZCB0byBzdG9yZSB0aGVtXG5cbiAgICAgIGlmIChjYWNoZVBhdGgpIHtcbiAgICAgICAgbG9jYWxDYWNoZUtleS5zZXQocGssIGNhY2hlVmFsdWUudmFsdWUpO1xuICAgICAgICAvLyBUT0RPOiBjYW4gd2Ugc3RvcmUgdGhlIGNhY2hlIHZhbHVlcyBpbnN0ZWFkIG9mIHRyYWNraW5nICphbGwqIHRoZWlyIHNvdXJjZXM/XG4gICAgICAgIC8vIHRoaXMgaXMgb25seSB1c2VkIGZvciBzZXR0aW5nIGVuZHBvaW50cyBjYWNoZSBjb3JyZWN0bHkuIGlmIHdlIGdvdCB0aGlzIGZhciB3ZSB3aWxsIGRlZiBuZWVkIHRvIHNldCBhcyB3ZSB3b3VsZCBoYXZlIGFscmVhZHkgdHJpZWQgZ2V0dGluZyBpdFxuICAgICAgICB0aGlzLmRlcGVuZGVuY2llcy5wdXNoKC4uLmNhY2hlVmFsdWUuZGVwZW5kZW5jaWVzKTtcbiAgICAgICAgcmV0dXJuIGNhY2hlVmFsdWUudmFsdWU7XG4gICAgICB9XG4gICAgICAvLyBpZiB3ZSBkb24ndCBmaW5kIGluIGRlbm9ybWFsaXplIGNhY2hlIHRoZW4gZG8gZnVsbCBkZW5vcm1hbGl6ZVxuICAgICAgZWxzZSB7XG4gICAgICAgIGNvbnN0IHRyYWNraW5nSW5kZXggPSB0aGlzLmRlcGVuZGVuY2llcy5sZW5ndGg7XG4gICAgICAgIGN5Y2xlQ2FjaGVLZXkuc2V0KHBrLCB0cmFja2luZ0luZGV4KTtcbiAgICAgICAgdGhpcy5kZXBlbmRlbmNpZXMucHVzaCh7IGVudGl0eSwgcGF0aDogeyBrZXksIHBrIH0gfSk7XG5cbiAgICAgICAgLyoqIE5PTi1HTE9CQUxfQ0FDSEUgQ09ERSAqL1xuICAgICAgICBjb21wdXRlVmFsdWUobG9jYWxDYWNoZUtleSk7XG4gICAgICAgIC8qKiAvRU5EIE5PTi1HTE9CQUxfQ0FDSEUgQ09ERSAqL1xuXG4gICAgICAgIGN5Y2xlQ2FjaGVLZXkuZGVsZXRlKHBrKTtcbiAgICAgICAgLy8gaWYgaW4gY3ljbGUsIHVzZSB0aGUgc3RhcnQgb2YgdGhlIGN5Y2xlIHRvIHRyYWNrIGFsbCBkZXBzXG4gICAgICAgIC8vIG90aGVyd2lzZSwgd2UgdXNlIG91ciBvd24gdHJhY2tpbmdJbmRleFxuICAgICAgICBjb25zdCBsb2NhbEtleSA9IHRoaXMuZGVwZW5kZW5jaWVzLnNsaWNlKFxuICAgICAgICAgIHRoaXMuY3ljbGVJbmRleCA9PT0gLTEgPyB0cmFja2luZ0luZGV4IDogdGhpcy5jeWNsZUluZGV4LFxuICAgICAgICApO1xuICAgICAgICBjb25zdCBjYWNoZVZhbHVlOiBFbnRpdHlDYWNoZVZhbHVlID0ge1xuICAgICAgICAgIGRlcGVuZGVuY2llczogbG9jYWxLZXksXG4gICAgICAgICAgdmFsdWU6IGxvY2FsQ2FjaGVLZXkuZ2V0KHBrKSxcbiAgICAgICAgfTtcbiAgICAgICAgZ2xvYmFsQ2FjaGUuc2V0KGxvY2FsS2V5LCBjYWNoZVZhbHVlKTtcblxuICAgICAgICAvLyBzdGFydCBvZiBjeWNsZSAtIHJlc2V0IGN5Y2xlIGRldGVjdGlvblxuICAgICAgICBpZiAodGhpcy5jeWNsZUluZGV4ID09PSB0cmFja2luZ0luZGV4KSB7XG4gICAgICAgICAgdGhpcy5jeWNsZUluZGV4ID0gLTE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gY3ljbGUgZGV0ZWN0ZWRcbiAgICAgIGlmIChjeWNsZUNhY2hlS2V5LmhhcyhwaykpIHtcbiAgICAgICAgdGhpcy5jeWNsZUluZGV4ID0gY3ljbGVDYWNoZUtleS5nZXQocGspITtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHdpdGggbm8gY3ljbGUsIGdsb2JhbENhY2hlRW50cnkgd2lsbCBoYXZlIGFscmVhZHkgYmVlbiBzZXRcbiAgICAgICAgdGhpcy5kZXBlbmRlbmNpZXMucHVzaCh7IGVudGl0eSwgcGF0aDogeyBrZXksIHBrIH0gfSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBsb2NhbENhY2hlS2V5LmdldChwayk7XG4gIH1cblxuICBwcml2YXRlIGdldENhY2hlS2V5KGtleTogc3RyaW5nKSB7XG4gICAgaWYgKCF0aGlzLmxvY2FsQ2FjaGUuaGFzKGtleSkpIHtcbiAgICAgIHRoaXMubG9jYWxDYWNoZS5zZXQoa2V5LCBuZXcgTWFwKCkpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuY3ljbGVDYWNoZS5oYXMoa2V5KSkge1xuICAgICAgdGhpcy5jeWNsZUNhY2hlLnNldChrZXksIG5ldyBNYXAoKSk7XG4gICAgfVxuICAgIGNvbnN0IGxvY2FsQ2FjaGVLZXkgPSB0aGlzLmxvY2FsQ2FjaGUuZ2V0KGtleSkhO1xuICAgIGNvbnN0IGN5Y2xlQ2FjaGVLZXkgPSB0aGlzLmN5Y2xlQ2FjaGUuZ2V0KGtleSkhO1xuICAgIHJldHVybiB7IGxvY2FsQ2FjaGVLZXksIGN5Y2xlQ2FjaGVLZXkgfTtcbiAgfVxuXG4gIC8qKiBDYWNoZSB2YXJpZXMgYmFzZWQgb24gaW5wdXQgKD09PSBha2EgcmVmZXJlbmNlKSAqL1xuICBnZXRSZXN1bHRzKFxuICAgIGlucHV0OiBhbnksXG4gICAgY2FjaGFibGU6IGJvb2xlYW4sXG4gICAgY29tcHV0ZVZhbHVlOiAoKSA9PiBhbnksXG4gICk6IHtcbiAgICBkYXRhOiBhbnk7XG4gICAgcGF0aHM6IEVudGl0eVBhdGhbXTtcbiAgfSB7XG4gICAgaWYgKCFjYWNoYWJsZSkge1xuICAgICAgcmV0dXJuIHsgZGF0YTogY29tcHV0ZVZhbHVlKCksIHBhdGhzOiB0aGlzLnBhdGhzKCkgfTtcbiAgICB9XG5cbiAgICBsZXQgW2RhdGEsIHBhdGhzXSA9IHRoaXMucmVzdWx0Q2FjaGUuZ2V0KGlucHV0LCB0aGlzLl9nZXRFbnRpdHkpO1xuXG4gICAgaWYgKHBhdGhzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGRhdGEgPSBjb21wdXRlVmFsdWUoKTtcbiAgICAgIC8vIHdlIHdhbnQgdG8gZG8gdGhpcyBiZWZvcmUgd2UgYWRkIG91ciAnaW5wdXQnIGVudHJ5XG4gICAgICBwYXRocyA9IHRoaXMucGF0aHMoKTtcbiAgICAgIC8vIGZvciB0aGUgZmlyc3QgZW50cnksIGBwYXRoYCBpcyBpZ25vcmVkIHNvIGVtcHR5IG1lbWJlcnMgaXMgZmluZVxuICAgICAgdGhpcy5kZXBlbmRlbmNpZXMudW5zaGlmdCh7IGVudGl0eTogaW5wdXQsIHBhdGg6IHsga2V5OiAnJywgcGs6ICcnIH0gfSk7XG4gICAgICB0aGlzLnJlc3VsdENhY2hlLnNldCh0aGlzLmRlcGVuZGVuY2llcywgZGF0YSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBhdGhzLnNoaWZ0KCk7XG4gICAgfVxuICAgIHJldHVybiB7IGRhdGEsIHBhdGhzIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgcGF0aHMoKSB7XG4gICAgcmV0dXJuIHRoaXMuZGVwZW5kZW5jaWVzLm1hcChkZXAgPT4gZGVwLnBhdGgpO1xuICB9XG59XG5cbmludGVyZmFjZSBFbnRpdHlDYWNoZVZhbHVlIHtcbiAgZGVwZW5kZW5jaWVzOiBEZXA8RW50aXR5UGF0aD5bXTtcbiAgdmFsdWU6IG9iamVjdCB8IHN5bWJvbCB8IHVuZGVmaW5lZDtcbn1cblxuY29uc3QgZ2V0RW50aXR5Q2FjaGVzID0gKGVudGl0eUNhY2hlOiBFbnRpdHlDYWNoZSkgPT4ge1xuICByZXR1cm4gKHBrOiBzdHJpbmcsIHNjaGVtYTogRW50aXR5SW50ZXJmYWNlKSA9PiB7XG4gICAgY29uc3Qga2V5ID0gc2NoZW1hLmtleTtcbiAgICAvLyBjb2xsZWN0aW9ucyBzaG91bGQgdXNlIHRoZSBlbnRpdGllcyB0aGV5IGNvbGxlY3Qgb3ZlclxuICAgIC8vIFRPRE86IHRoaXMgc2hvdWxkIGJlIGJhc2VkIG9uIGEgcHVibGljIGludGVyZmFjZVxuICAgIGNvbnN0IGVudGl0eUluc3RhbmNlOiBFbnRpdHlJbnRlcmZhY2UgPSAoc2NoZW1hLmNhY2hlV2l0aCBhcyBhbnkpID8/IHNjaGVtYTtcblxuICAgIGlmICghZW50aXR5Q2FjaGUuaGFzKGtleSkpIHtcbiAgICAgIGVudGl0eUNhY2hlLnNldChrZXksIG5ldyBNYXAoKSk7XG4gICAgfVxuICAgIGNvbnN0IGVudGl0eUNhY2hlS2V5ID0gZW50aXR5Q2FjaGUuZ2V0KGtleSkhO1xuICAgIGlmICghZW50aXR5Q2FjaGVLZXkuZ2V0KHBrKSlcbiAgICAgIGVudGl0eUNhY2hlS2V5LnNldChcbiAgICAgICAgcGssXG4gICAgICAgIG5ldyBXZWFrTWFwPFxuICAgICAgICAgIEVudGl0eUludGVyZmFjZSxcbiAgICAgICAgICBXZWFrRGVwZW5kZW5jeU1hcDxFbnRpdHlQYXRoLCBvYmplY3QsIGFueT5cbiAgICAgICAgPigpLFxuICAgICAgKTtcblxuICAgIGNvbnN0IGVudGl0eUNhY2hlUGsgPSBlbnRpdHlDYWNoZUtleS5nZXQocGspIGFzIFdlYWtNYXA8XG4gICAgICBFbnRpdHlJbnRlcmZhY2U8YW55PixcbiAgICAgIFdlYWtEZXBlbmRlbmN5TWFwPEVudGl0eVBhdGgsIG9iamVjdCwgYW55PlxuICAgID47XG4gICAgbGV0IHdlbSA9IGVudGl0eUNhY2hlUGsuZ2V0KGVudGl0eUluc3RhbmNlKSBhcyBXZWFrRGVwZW5kZW5jeU1hcDxcbiAgICAgIEVudGl0eVBhdGgsXG4gICAgICBvYmplY3QsXG4gICAgICBhbnlcbiAgICA+O1xuICAgIGlmICghd2VtKSB7XG4gICAgICB3ZW0gPSBuZXcgV2Vha0RlcGVuZGVuY3lNYXA8RW50aXR5UGF0aCwgb2JqZWN0LCBhbnk+KCk7XG4gICAgICBlbnRpdHlDYWNoZVBrLnNldChlbnRpdHlJbnN0YW5jZSwgd2VtKTtcbiAgICB9XG5cbiAgICByZXR1cm4gd2VtO1xuICB9O1xufTtcbiJdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBT0EsaUJBQWlCLE1BQW9CLHdCQUF3QjtBQU1wRSxlQUFlLE1BQU1DLFdBQVcsQ0FBa0I7RUFjaERDLFdBQVdBLENBQ1RDLFNBQW9CLEVBQ3BCQyxXQUF3QixFQUN4QkMsV0FBMkIsRUFDM0I7SUFBQSxLQWpCTUMsWUFBWSxHQUFzQixFQUFFO0lBQUEsS0FDcENDLFVBQVUsR0FBcUMsSUFBSUMsR0FBRyxDQUFDLENBQUM7SUFBQSxLQUN4REMsVUFBVSxHQUFHLENBQUMsQ0FBQztJQUFBLEtBQ2ZDLFVBQVUsR0FBa0MsSUFBSUYsR0FBRyxDQUFDLENBQUM7SUFlM0QsSUFBSSxDQUFDRyxVQUFVLEdBQUdSLFNBQVM7SUFDM0IsSUFBSSxDQUFDUyxRQUFRLEdBQUdDLGVBQWUsQ0FBQ1QsV0FBVyxDQUFDO0lBQzVDLElBQUksQ0FBQ0MsV0FBVyxHQUFHQSxXQUFXO0VBQ2hDO0VBRUFGLFNBQVNBLENBQ1BXLEVBQVUsRUFDVkMsTUFBdUIsRUFDdkJDLE1BQVcsRUFDWEMsWUFBdUQsRUFDMUI7SUFDN0IsTUFBTUMsR0FBRyxHQUFHSCxNQUFNLENBQUNHLEdBQUc7SUFDdEIsTUFBTTtNQUFFQyxhQUFhO01BQUVDO0lBQWMsQ0FBQyxHQUFHLElBQUksQ0FBQ0Ms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