UNPKG

@data-client/normalizr

Version:

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

126 lines (117 loc) 18.6 kB
import { getCheckLoop } from './getCheckLoop.js'; import { POJODelegate } from '../delegate/Delegate.js'; import { INVALID } from '../denormalize/symbol.js'; /** Full normalize() logic for POJO state */ export class NormalizeDelegate extends POJODelegate { constructor(state, actionMeta) { super(state); this.newEntities = new Map(); this.newIndexes = new Map(); this.entitiesMeta = state.entitiesMeta; this.meta = actionMeta; this.checkLoop = getCheckLoop(); } getNewEntity(key, pk) { return this.getNewEntities(key).get(pk); } getNewEntities(key) { // first time we come across this type of entity if (!this.newEntities.has(key)) { this.newEntities.set(key, new Map()); // we will be editing these, so we need to clone them first this.entities[key] = { ...this.entities[key] }; this.entitiesMeta[key] = { ...this.entitiesMeta[key] }; } return this.newEntities.get(key); } getNewIndexes(key) { if (!this.newIndexes.has(key)) { this.newIndexes.set(key, new Map()); this.indexes[key] = { ...this.indexes[key] }; } return this.newIndexes.get(key); } /** Updates an entity using merge lifecycles when it has previously been set */ mergeEntity(schema, pk, incomingEntity) { const key = schema.key; // default when this is completely new entity let nextEntity = incomingEntity; let nextMeta = this.meta; // if we already processed this entity during this normalization (in another nested place) let entity = this.getNewEntity(key, pk); if (entity) { nextEntity = schema.merge(entity, incomingEntity); } else { // if we find it in the store entity = this.getEntity(key, pk); if (entity) { const meta = this.getMeta(key, pk); nextEntity = schema.mergeWithStore(meta, nextMeta, entity, incomingEntity); nextMeta = schema.mergeMetaWithStore(meta, nextMeta, entity, incomingEntity); } } // once we have computed the merged values, set them this.setEntity(schema, pk, nextEntity, nextMeta); } /** Sets an entity overwriting any previously set values */ setEntity(schema, pk, entity, meta = this.meta) { const key = schema.key; const newEntities = this.getNewEntities(key); const updateMeta = !newEntities.has(pk); newEntities.set(pk, entity); // update index if (schema.indexes) { handleIndexes(pk, schema.indexes, this.getNewIndexes(key), this.indexes[key], entity, this.entities[key]); } // set this after index updates so we know what indexes to remove from this._setEntity(key, pk, entity); if (updateMeta) this._setMeta(key, pk, meta); } /** Invalidates an entity, potentially triggering suspense */ invalidate({ key }, pk) { // set directly: any queued updates are meaningless with delete this.setEntity({ key }, pk, INVALID); } _setEntity(key, pk, entity) { this.entities[key][pk] = entity; } _setMeta(key, pk, meta) { this.entitiesMeta[key][pk] = meta; } getMeta(key, pk) { return this.entitiesMeta[key][pk]; } } 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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJnZXRDaGVja0xvb3AiLCJQT0pPRGVsZWdhdGUiLCJJTlZBTElEIiwiTm9ybWFsaXplRGVsZWdhdGUiLCJjb25zdHJ1Y3RvciIsInN0YXRlIiwiYWN0aW9uTWV0YSIsIm5ld0VudGl0aWVzIiwiTWFwIiwibmV3SW5kZXhlcyIsImVudGl0aWVzTWV0YSIsIm1ldGEiLCJjaGVja0xvb3AiLCJnZXROZXdFbnRpdHkiLCJrZXkiLCJwayIsImdldE5ld0VudGl0aWVzIiwiZ2V0IiwiaGFzIiwic2V0IiwiZW50aXRpZXMiLCJnZXROZXdJbmRleGVzIiwiaW5kZXhlcyIsIm1lcmdlRW50aXR5Iiwic2NoZW1hIiwiaW5jb21pbmdFbnRpdHkiLCJuZXh0RW50aXR5IiwibmV4dE1ldGEiLCJlbnRpdHkiLCJtZXJnZSIsImdldEVudGl0eSIsImdldE1ldGEiLCJtZXJnZVdpdGhTdG9yZSIsIm1lcmdlTWV0YVdpdGhTdG9yZSIsInNldEVudGl0eSIsInVwZGF0ZU1ldGEiLCJoYW5kbGVJbmRleGVzIiwiX3NldEVudGl0eSIsIl9zZXRNZXRhIiwiaW52YWxpZGF0ZSIsImlkIiwic2NoZW1hSW5kZXhlcyIsInN0b3JlSW5kZXhlcyIsInN0b3JlRW50aXRpZXMiLCJpbmRleCIsImluZGV4TWFwIiwicHJvY2VzcyIsImVudiIsIk5PREVfRU5WIiwiY29uc29sZSIsIndhcm4iLCJKU09OIiwic3RyaW5naWZ5IiwidW5kZWZpbmVkIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL25vcm1hbGl6ZS9Ob3JtYWxpemVEZWxlZ2F0ZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBFbnRpdHlUYWJsZSxcbiAgTm9ybWFsaXplZEluZGV4LFxuICBJTm9ybWFsaXplRGVsZWdhdGUsXG4gIE1lcmdlYWJsZSxcbn0gZnJvbSAnLi4vaW50ZXJmYWNlLmpzJztcbmltcG9ydCB7IGdldENoZWNrTG9vcCB9IGZyb20gJy4vZ2V0Q2hlY2tMb29wLmpzJztcbmltcG9ydCB7IFBPSk9EZWxlZ2F0ZSB9IGZyb20gJy4uL2RlbGVnYXRlL0RlbGVnYXRlLmpzJztcbmltcG9ydCB7IElOVkFMSUQgfSBmcm9tICcuLi9kZW5vcm1hbGl6ZS9zeW1ib2wuanMnO1xuXG4vKiogRnVsbCBub3JtYWxpemUoKSBsb2dpYyBmb3IgUE9KTyBzdGF0ZSAqL1xuZXhwb3J0IGNsYXNzIE5vcm1hbGl6ZURlbGVnYXRlXG4gIGV4dGVuZHMgUE9KT0RlbGVnYXRlXG4gIGltcGxlbWVudHMgSU5vcm1hbGl6ZURlbGVnYXRlXG57XG4gIGRlY2xhcmUgcmVhZG9ubHkgZW50aXRpZXNNZXRhOiB7XG4gICAgW2VudGl0eUtleTogc3RyaW5nXToge1xuICAgICAgW3BrOiBzdHJpbmddOiB7XG4gICAgICAgIGRhdGU6IG51bWJlcjtcbiAgICAgICAgZXhwaXJlc0F0OiBudW1iZXI7XG4gICAgICAgIGZldGNoZWRBdDogbnVtYmVyO1xuICAgICAgfTtcbiAgICB9O1xuICB9O1xuXG4gIGRlY2xhcmUgcmVhZG9ubHkgbWV0YTogeyBmZXRjaGVkQXQ6IG51bWJlcjsgZGF0ZTogbnVtYmVyOyBleHBpcmVzQXQ6IG51bWJlciB9O1xuICBkZWNsYXJlIGNoZWNrTG9vcDogKGVudGl0eUtleTogc3RyaW5nLCBwazogc3RyaW5nLCBpbnB1dDogb2JqZWN0KSA9PiBib29sZWFuO1xuXG4gIHByb3RlY3RlZCBuZXdFbnRpdGllcyA9IG5ldyBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBhbnk+PigpO1xuICBwcm90ZWN0ZWQgbmV3SW5kZXhlcyA9IG5ldyBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBhbnk+PigpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHN0YXRlOiB7XG4gICAgICBlbnRpdGllczogRW50aXR5VGFibGU7XG4gICAgICBpbmRleGVzOiBOb3JtYWxpemVkSW5kZXg7XG4gICAgICBlbnRpdGllc01ldGE6IHtcbiAgICAgICAgW2VudGl0eUtleTogc3RyaW5nXToge1xuICAgICAgICAgIFtwazogc3RyaW5nXToge1xuICAgICAgICAgICAgZGF0ZTogbnVtYmVyO1xuICAgICAgICAgICAgZXhwaXJlc0F0OiBudW1iZXI7XG4gICAgICAgICAgICBmZXRjaGVkQXQ6IG51bWJlcjtcbiAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgICAgfTtcbiAgICB9LFxuICAgIGFjdGlvbk1ldGE6IHsgZmV0Y2hlZEF0OiBudW1iZXI7IGRhdGU6IG51bWJlcjsgZXhwaXJlc0F0OiBudW1iZXIgfSxcbiAgKSB7XG4gICAgc3VwZXIoc3RhdGUpO1xuICAgIHRoaXMuZW50aXRpZXNNZXRhID0gc3RhdGUuZW50aXRpZXNNZXRhO1xuICAgIHRoaXMubWV0YSA9IGFjdGlvbk1ldGE7XG4gICAgdGhpcy5jaGVja0xvb3AgPSBnZXRDaGVja0xvb3AoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXROZXdFbnRpdHkoa2V5OiBzdHJpbmcsIHBrOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5nZXROZXdFbnRpdGllcyhrZXkpLmdldChwayk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0TmV3RW50aXRpZXMoa2V5OiBzdHJpbmcpOiBNYXA8c3RyaW5nLCBhbnk+IHtcbiAgICAvLyBmaXJzdCB0aW1lIHdlIGNvbWUgYWNyb3NzIHRoaXMgdHlwZSBvZiBlbnRpdHlcbiAgICBpZiAoIXRoaXMubmV3RW50aXRpZXMuaGFzKGtleSkpIHtcbiAgICAgIHRoaXMubmV3RW50aXRpZXMuc2V0KGtleSwgbmV3IE1hcCgpKTtcbiAgICAgIC8vIHdlIHdpbGwgYmUgZWRpdGluZyB0aGVzZSwgc28gd2UgbmVlZCB0byBjbG9uZSB0aGVtIGZpcnN0XG4gICAgICB0aGlzLmVudGl0aWVzW2tleV0gPSB7XG4gICAgICAgIC4uLnRoaXMuZW50aXRpZXNba2V5XSxcbiAgICAgIH07XG4gICAgICB0aGlzLmVudGl0aWVzTWV0YVtrZXldID0ge1xuICAgICAgICAuLi50aGlzLmVudGl0aWVzTWV0YVtrZXldLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5uZXdFbnRpdGllcy5nZXQoa2V5KSBhcyBNYXA8c3RyaW5nLCBhbnk+O1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldE5ld0luZGV4ZXMoa2V5OiBzdHJpbmcpOiBNYXA8c3RyaW5nLCBhbnk+IHtcbiAgICBpZiAoIXRoaXMubmV3SW5kZXhlcy5oYXMoa2V5KSkge1xuICAgICAgdGhpcy5uZXdJbmRleGVzLnNldChrZXksIG5ldyBNYXAoKSk7XG4gICAgICB0aGlzLmluZGV4ZXNba2V5XSA9IHsgLi4udGhpcy5pbmRleGVzW2tleV0gfTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMubmV3SW5kZXhlcy5nZXQoa2V5KSBhcyBNYXA8c3RyaW5nLCBhbnk+O1xuICB9XG5cbiAgLyoqIFVwZGF0ZXMgYW4gZW50aXR5IHVzaW5nIG1lcmdlIGxpZmVjeWNsZXMgd2hlbiBpdCBoYXMgcHJldmlvdXNseSBiZWVuIHNldCAqL1xuICBtZXJnZUVudGl0eShcbiAgICBzY2hlbWE6IE1lcmdlYWJsZSAmIHsgaW5kZXhlcz86IGFueSB9LFxuICAgIHBrOiBzdHJpbmcsXG4gICAgaW5jb21pbmdFbnRpdHk6IGFueSxcbiAgKSB7XG4gICAgY29uc3Qga2V5ID0gc2NoZW1hLmtleTtcblxuICAgIC8vIGRlZmF1bHQgd2hlbiB0aGlzIGlzIGNvbXBsZXRlbHkgbmV3IGVudGl0eVxuICAgIGxldCBuZXh0RW50aXR5ID0gaW5jb21pbmdFbnRpdHk7XG4gICAgbGV0IG5leHRNZXRhID0gdGhpcy5tZXRhO1xuXG4gICAgLy8gaWYgd2UgYWxyZWFkeSBwcm9jZXNzZWQgdGhpcyBlbnRpdHkgZHVyaW5nIHRoaXMgbm9ybWFsaXphdGlvbiAoaW4gYW5vdGhlciBuZXN0ZWQgcGxhY2UpXG4gICAgbGV0IGVudGl0eSA9IHRoaXMuZ2V0TmV3RW50aXR5KGtleSwgcGspO1xuICAgIGlmIChlbnRpdHkpIHtcbiAgICAgIG5leHRFbnRpdHkgPSBzY2hlbWEubWVyZ2UoZW50aXR5LCBpbmNvbWluZ0VudGl0eSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGlmIHdlIGZpbmQgaXQgaW4gdGhlIHN0b3JlXG4gICAgICBlbnRpdHkgPSB0aGlzLmdldEVudGl0eShrZXksIHBrKTtcbiAgICAgIGlmIChlbnRpdHkpIHtcbiAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuZ2V0TWV0YShrZXksIHBrKTtcbiAgICAgICAgbmV4dEVudGl0eSA9IHNjaGVtYS5tZXJnZVdpdGhTdG9yZShcbiAgICAgICAgICBtZXRhLFxuICAgICAgICAgIG5leHRNZXRhLFxuICAgICAgICAgIGVudGl0eSxcbiAgICAgICAgICBpbmNvbWluZ0VudGl0eSxcbiAgICAgICAgKTtcbiAgICAgICAgbmV4dE1ldGEgPSBzY2hlbWEubWVyZ2VNZXRhV2l0aFN0b3JlKFxuICAgICAgICAgIG1ldGEsXG4gICAgICAgICAgbmV4dE1ldGEsXG4gICAgICAgICAgZW50aXR5LFxuICAgICAgICAgIGluY29taW5nRW50aXR5LFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIG9uY2Ugd2UgaGF2ZSBjb21wdXRlZCB0aGUgbWVyZ2VkIHZhbHVlcywgc2V0IHRoZW1cbiAgICB0aGlzLnNldEVudGl0eShzY2hlbWEsIHBrLCBuZXh0RW50aXR5LCBuZXh0TWV0YSk7XG4gIH1cblxuICAvKiogU2V0cyBhbiBlbnRpdHkgb3ZlcndyaXRpbmcgYW55IHByZXZpb3VzbHkgc2V0IHZhbHVlcyAqL1xuICBzZXRFbnRpdHkoXG4gICAgc2NoZW1hOiB7IGtleTogc3RyaW5nOyBpbmRleGVzPzogYW55IH0sXG4gICAgcGs6IHN0cmluZyxcbiAgICBlbnRpdHk6IGFueSxcbiAgICBtZXRhOiB7IGZldGNoZWRBdDogbnVtYmVyOyBkYXRlOiBudW1iZXI7IGV4cGlyZXNBdDogbnVtYmVyIH0gPSB0aGlzLm1ldGEsXG4gICkge1xuICAgIGNvbnN0IGtleSA9IHNjaGVtYS5rZXk7XG4gICAgY29uc3QgbmV3RW50aXRpZXMgPSB0aGlzLmdldE5ld0VudGl0aWVzKGtleSk7XG4gICAgY29uc3QgdXBkYXRlTWV0YSA9ICFuZXdFbnRpdGllcy5oYXMocGspO1xuICAgIG5ld0VudGl0aWVzLnNldChwaywgZW50aXR5KTtcblxuICAgIC8vIHVwZGF0ZSBpbmRleFxuICAgIGlmIChzY2hlbWEuaW5kZXhlcykge1xuICAgICAgaGFuZGxlSW5kZXhlcyhcbiAgICAgICAgcGssXG4gICAgICAgIHNjaGVtYS5pbmRleGVzLFxuICAgICAgICB0aGlzLmdldE5ld0luZGV4ZXMoa2V5KSxcbiAgICAgICAgdGhpcy5pbmRleGVzW2tleV0sXG4gICAgICAgIGVudGl0eSxcbiAgICAgICAgdGhpcy5lbnRpdGllc1trZXldIGFzIGFueSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gc2V0IHRoaXMgYWZ0ZXIgaW5kZXggdXBkYXRlcyBzbyB3ZSBrbm93IHdoYXQgaW5kZXhlcyB0byByZW1vdmUgZnJvbVxuICAgIHRoaXMuX3NldEVudGl0eShrZXksIHBrLCBlbnRpdHkpO1xuXG4gICAgaWYgKHVwZGF0ZU1ldGEpIHRoaXMuX3NldE1ldGEoa2V5LCBwaywgbWV0YSk7XG4gIH1cblxuICAvKiogSW52YWxpZGF0ZXMgYW4gZW50aXR5LCBwb3RlbnRpYWxseSB0cmlnZ2VyaW5nIHN1c3BlbnNlICovXG4gIGludmFsaWRhdGUoeyBrZXkgfTogeyBrZXk6IHN0cmluZyB9LCBwazogc3RyaW5nKSB7XG4gICAgLy8gc2V0IGRpcmVjdGx5OiBhbnkgcXVldWVkIHVwZGF0ZXMgYXJlIG1lYW5pbmdsZXNzIHdpdGggZGVsZXRlXG4gICAgdGhpcy5zZXRFbnRpdHkoeyBrZXkgfSwgcGssIElOVkFMSUQpO1xuICB9XG5cbiAgcHJvdGVjdGVkIF9zZXRFbnRpdHkoa2V5OiBzdHJpbmcsIHBrOiBzdHJpbmcsIGVudGl0eTogYW55KSB7XG4gICAgKHRoaXMuZW50aXRpZXNba2V5XSBhcyBhbnkpW3BrXSA9IGVudGl0eTtcbiAgfVxuXG4gIHByb3RlY3RlZCBfc2V0TWV0YShcbiAgICBrZXk6IHN0cmluZyxcbiAgICBwazogc3RyaW5nLFxuICAgIG1ldGE6IHsgZmV0Y2hlZEF0OiBudW1iZXI7IGRhdGU6IG51bWJlcjsgZXhwaXJlc0F0OiBudW1iZXIgfSxcbiAgKSB7XG4gICAgdGhpcy5lbnRpdGllc01ldGFba2V5XVtwa10gPSBtZXRhO1xuICB9XG5cbiAgZ2V0TWV0YShrZXk6IHN0cmluZywgcGs6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmVudGl0aWVzTWV0YVtrZXldW3BrXTtcbiAgfVxufVxuXG5mdW5jdGlvbiBoYW5kbGVJbmRleGVzKFxuICBpZDogc3RyaW5nLFxuICBzY2hlbWFJbmRleGVzOiBzdHJpbmdbXSxcbiAgaW5kZXhlczogTWFwPHN0cmluZywgYW55PixcbiAgc3RvcmVJbmRleGVzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICBlbnRpdHk6IGFueSxcbiAgc3RvcmVFbnRpdGllczogUmVjb3JkPHN0cmluZywgYW55Pixcbikge1xuICBmb3IgKGNvbnN0IGluZGV4IG9mIHNjaGVtYUluZGV4ZXMpIHtcbiAgICBpZiAoIWluZGV4ZXMuaGFzKGluZGV4KSkge1xuICAgICAgaW5kZXhlcy5zZXQoaW5kZXgsIChzdG9yZUluZGV4ZXNbaW5kZXhdID0ge30pKTtcbiAgICB9XG4gICAgY29uc3QgaW5kZXhNYXAgPSBpbmRleGVzLmdldChpbmRleCk7XG4gICAgaWYgKHN0b3JlRW50aXRpZXNbaWRdKSB7XG4gICAgICBkZWxldGUgaW5kZXhNYXBbc3RvcmVFbnRpdGllc1tpZF1baW5kZXhdXTtcbiAgICB9XG4gICAgLy8gZW50aXR5IGFscmVhZHkgaW4gY2FjaGUgYnV0IHRoZSBpbmRleCBjaGFuZ2VkXG4gICAgaWYgKFxuICAgICAgc3RvcmVFbnRpdGllcyAmJlxuICAgICAgc3RvcmVFbnRpdGllc1tpZF0gJiZcbiAgICAgIHN0b3JlRW50aXRpZXNbaWRdW2luZGV4XSAhPT0gZW50aXR5W2luZGV4XVxuICAgICkge1xuICAgICAgaW5kZXhNYXBbc3RvcmVFbnRpdGllc1tpZF1baW5kZXhdXSA9IElOVkFMSUQ7XG4gICAgfVxuICAgIGlmIChpbmRleCBpbiBlbnRpdHkpIHtcbiAgICAgIGluZGV4TWFwW2VudGl0eVtpbmRleF1dID0gaWQ7XG4gICAgfSAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqLyBlbHNlIGlmIChcbiAgICAgIHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbidcbiAgICApIHtcbiAgICAgIGNvbnNvbGUud2FybihgSW5kZXggbm90IGZvdW5kIGluIGVudGl0eS4gSW5kZXhlcyBtdXN0IGJlIHRvcC1sZXZlbCBtZW1iZXJzIG9mIHlvdXIgZW50aXR5LlxuSW5kZXg6ICR7aW5kZXh9XG5FbnRpdHk6ICR7SlNPTi5zdHJpbmdpZnkoZW50aXR5LCB1bmRlZmluZWQsIDIpfWApO1xuICAgIH1cbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiQUFNQSxTQUFTQSxZQUFZLFFBQVEsbUJBQW1CO0FBQ2hELFNBQVNDLFlBQVksUUFBUSx5QkFBeUI7QUFDdEQsU0FBU0MsT0FBTyxRQUFRLDBCQUEwQjs7QUFFbEQ7QUFDQSxPQUFPLE1BQU1DLGlCQUFpQixTQUNwQkYsWUFBWSxDQUV0QjtFQWlCRUcsV0FBV0EsQ0FDVEMsS0FZQyxFQUNEQyxVQUFrRSxFQUNsRTtJQUNBLEtBQUssQ0FBQ0QsS0FBSyxDQUFDO0lBQUMsS0FuQkxFLFdBQVcsR0FBRyxJQUFJQyxHQUFHLENBQTJCLENBQUM7SUFBQSxLQUNqREMsVUFBVSxHQUFHLElBQUlELEdBQUcsQ0FBMkIsQ0FBQztJQW1CeEQsSUFBSSxDQUFDRSxZQUFZLEdBQUdMLEtBQUssQ0FBQ0ssWUFBWTtJQUN0QyxJQUFJLENBQUNDLElBQUksR0FBR0wsVUFBVTtJQUN0QixJQUFJLENBQUNNLFNBQVMsR0FBR1osWUFBWSxDQUFDLENBQUM7RUFDakM7RUFFVWEsWUFBWUEsQ0FBQ0MsR0FBVyxFQUFFQyxFQUFVLEVBQUU7SUFDOUMsT0FBTyxJQUFJLENBQUNDLGNBQWMsQ0FBQ0YsR0FBRyxDQUFDLENBQUNHLEdBQUcsQ0FBQ0YsRUFBRSxDQUFDO0VBQ3pDO0VBRVVDLGNBQWNB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