UNPKG

@datorama/akita

Version:

State Management Tailored-Made for JS Applications

249 lines 20.6 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { isUndefined } from '../isUndefined'; import { coerceArray } from '../coerceArray'; import { toBoolean } from '../toBoolean'; import { isFunction } from '../isFunction'; /** * Each plugin that wants to add support for entities should extend this interface. * @abstract * @template State, P */ export class EntityCollectionPlugin { /** * @protected * @param {?} query * @param {?} entityIds */ constructor(query, entityIds) { this.query = query; this.entityIds = entityIds; this.entities = new Map(); } /** * Get the entity plugin instance. * @protected * @param {?} id * @return {?} */ getEntity(id) { return this.entities.get(id); } /** * Whether the entity plugin exist. * @protected * @param {?} id * @return {?} */ hasEntity(id) { return this.entities.has(id); } /** * Remove the entity plugin instance. * @protected * @param {?} id * @return {?} */ removeEntity(id) { this.destroy(id); return this.entities.delete(id); } /** * Set the entity plugin instance. * @protected * @param {?} id * @param {?} plugin * @return {?} */ createEntity(id, plugin) { return this.entities.set(id, plugin); } /** * If the user passes `entityIds` we take them; otherwise, we take all. * @protected * @return {?} */ getIds() { return isUndefined(this.entityIds) ? this.query.getValue().ids : coerceArray(this.entityIds); } /** * When you call one of the plugin methods, you can pass id/ids or undefined which means all. * @protected * @param {?=} ids * @return {?} */ resolvedIds(ids) { return isUndefined(ids) ? this.getIds() : coerceArray(ids); } /** * Call this method when you want to activate the plugin on init or when you need to listen to add/remove of entities dynamically. * * For example in your plugin you may do the following: * * this.query.select(state => state.ids).pipe(skip(1)).subscribe(ids => this.activate(ids)); * @protected * @param {?} ids * @param {?=} actions * @return {?} */ rebase(ids, actions = {}) { /** * * If the user passes `entityIds` & we have new ids check if we need to add/remove instances. * * This phase will be called only upon update. */ if (toBoolean(ids)) { /** * Which means all */ if (isUndefined(this.entityIds)) { for (let i = 0, len = ids.length; i < len; i++) { /** @type {?} */ const entityId = ids[i]; if (this.hasEntity(entityId) === false) { isFunction(actions.beforeAdd) && actions.beforeAdd(entityId); /** @type {?} */ const plugin = this.instantiatePlugin(entityId); this.entities.set(entityId, plugin); isFunction(actions.afterAdd) && actions.afterAdd(plugin); } } this.entities.forEach((/** * @param {?} plugin * @param {?} entityId * @return {?} */ (plugin, entityId) => { if (ids.indexOf(entityId) === -1) { isFunction(actions.beforeRemove) && actions.beforeRemove(plugin); this.removeEntity(entityId); } })); } else { /** * Which means the user passes specific ids * @type {?} */ const _ids = coerceArray(this.entityIds); for (let i = 0, len = _ids.length; i < len; i++) { /** @type {?} */ const entityId = _ids[i]; /** The Entity in current ids and doesn't exist, add it. */ if (ids.indexOf(entityId) > -1 && this.hasEntity(entityId) === false) { isFunction(actions.beforeAdd) && actions.beforeAdd(entityId); /** @type {?} */ const plugin = this.instantiatePlugin(entityId); this.entities.set(entityId, plugin); isFunction(actions.afterAdd) && actions.afterAdd(plugin); } else { this.entities.forEach((/** * @param {?} plugin * @param {?} entityId * @return {?} */ (plugin, entityId) => { /** The Entity not in current ids and exists, remove it. */ if (ids.indexOf(entityId) === -1 && this.hasEntity(entityId) === true) { isFunction(actions.beforeRemove) && actions.beforeRemove(plugin); this.removeEntity(entityId); } })); } } } } else { /** * Otherwise, start with the provided ids or all. */ this.getIds().forEach((/** * @param {?} id * @return {?} */ id => { if (!this.hasEntity(id)) this.createEntity(id, this.instantiatePlugin(id)); })); } } /** * Listen for add/remove entities. * @protected * @return {?} */ selectIds() { return this.query.select((/** * @param {?} state * @return {?} */ state => state.ids)); } /** * Base method for activation, you can override it if you need to. * @protected * @param {?=} ids * @return {?} */ activate(ids) { this.rebase(ids); } /** * Loop over each id and invoke the plugin method. * @protected * @param {?} ids * @param {?} cb * @return {?} */ forEachId(ids, cb) { /** @type {?} */ const _ids = this.resolvedIds(ids); for (let i = 0, len = _ids.length; i < len; i++) { /** @type {?} */ const id = _ids[i]; if (this.hasEntity(id)) { cb(this.getEntity(id)); } } } } if (false) { /** * @type {?} * @protected */ EntityCollectionPlugin.prototype.entities; /** * @type {?} * @protected */ EntityCollectionPlugin.prototype.query; /** * @type {?} * @private */ EntityCollectionPlugin.prototype.entityIds; /** * This method is responsible for plugin instantiation. * * For example: * return new StateHistory(this.query, this.params, id) as P; * @abstract * @protected * @param {?} id * @return {?} */ EntityCollectionPlugin.prototype.instantiatePlugin = function (id) { }; /** * This method is responsible for cleaning. * @abstract * @param {?=} id * @return {?} */ EntityCollectionPlugin.prototype.destroy = function (id) { }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5Q29sbGVjdGlvblBsdWdpbi5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0BkYXRvcmFtYS9ha2l0YS8iLCJzb3VyY2VzIjpbInNyYy9wbHVnaW5zL2VudGl0eUNvbGxlY3Rpb25QbHVnaW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUdBLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDOzs7Ozs7QUFTM0MsTUFBTSxPQUFnQixzQkFBc0I7Ozs7OztJQUcxQyxZQUFnQyxLQUF5QixFQUFVLFNBQW9DO1FBQXZFLFVBQUssR0FBTCxLQUFLLENBQW9CO1FBQVUsY0FBUyxHQUFULFNBQVMsQ0FBMkI7UUFGN0YsYUFBUSxHQUFHLElBQUksR0FBRyxFQUF1QixDQUFDO0lBRXNELENBQUM7Ozs7Ozs7SUFLakcsU0FBUyxDQUFDLEVBQW9CO1FBQ3RDLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0IsQ0FBQzs7Ozs7OztJQUtTLFNBQVMsQ0FBQyxFQUFvQjtRQUN0QyxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQy9CLENBQUM7Ozs7Ozs7SUFLUyxZQUFZLENBQUMsRUFBb0I7UUFDekMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNqQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2xDLENBQUM7Ozs7Ozs7O0lBS1MsWUFBWSxDQUFDLEVBQW9CLEVBQUUsTUFBUztRQUNwRCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVB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LEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUM7UUFFbEMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRTs7a0JBQ3pDLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ2xCLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsRUFBRTtnQkFDdEIsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQzthQUN4QjtTQUNGO0lBQ0gsQ0FBQztDQUNGOzs7Ozs7SUE1SkMsMENBQW9EOzs7OztJQUU5Qix1Q0FBbUM7Ozs7O0lBQUUsMkNBQTRDOzs7Ozs7Ozs7OztJQXNJdkcsdUVBQThEOzs7Ozs7O0lBSzlELDZEQUErQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEVudGl0eVN0YXRlLCBPckFycmF5LCBnZXRJRFR5cGUgfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQgeyBRdWVyeUVudGl0eSB9IGZyb20gJy4uL3F1ZXJ5RW50aXR5JztcbmltcG9ydCB7IGlzVW5kZWZpbmVkIH0gZnJvbSAnLi4vaXNVbmRlZmluZWQnO1xuaW1wb3J0IHsgY29lcmNlQXJyYXkgfSBmcm9tICcuLi9jb2VyY2VBcnJheSc7XG5pbXBvcnQgeyB0b0Jvb2xlYW4gfSBmcm9tICcuLi90b0Jvb2xlYW4nO1xuaW1wb3J0IHsgaXNGdW5jdGlvbiB9IGZyb20gJy4uL2lzRnVuY3Rpb24nO1xuXG5leHBvcnQgdHlwZSBSZWJhc2VBY3Rpb248UCA9IGFueT4gPSAocGx1Z2luOiBQKSA9PiBhbnk7XG5cbmV4cG9ydCB0eXBlIFJlYmFzZUFjdGlvbnM8UCA9IGFueT4gPSB7IGJlZm9yZVJlbW92ZT86IFJlYmFzZUFjdGlvbjsgYmVmb3JlQWRkPzogUmViYXNlQWN0aW9uOyBhZnRlckFkZD86IFJlYmFzZUFjdGlvbiB9O1xuXG4vKipcbiAqIEVhY2ggcGx1Z2luIHRoYXQgd2FudHMgdG8gYWRkIHN1cHBvcnQgZm9yIGVudGl0aWVzIHNob3VsZCBleHRlbmQgdGhpcyBpbnRlcmZhY2UuXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBFbnRpdHlDb2xsZWN0aW9uUGx1Z2luPFN0YXRlIGV4dGVuZHMgRW50aXR5U3RhdGUsIFA+IHtcbiAgcHJvdGVjdGVkIGVudGl0aWVzID0gbmV3IE1hcDxnZXRJRFR5cGU8U3RhdGU+LCBQPigpO1xuXG4gIHByb3RlY3RlZCBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgcXVlcnk6IFF1ZXJ5RW50aXR5PFN0YXRlPiwgcHJpdmF0ZSBlbnRpdHlJZHM6IE9yQXJyYXk8Z2V0SURUeXBlPFN0YXRlPj4pIHt9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgZW50aXR5IHBsdWdpbiBpbnN0YW5jZS5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRFbnRpdHkoaWQ6IGdldElEVHlwZTxTdGF0ZT4pOiBQIHtcbiAgICByZXR1cm4gdGhpcy5lbnRpdGllcy5nZXQoaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIGVudGl0eSBwbHVnaW4gZXhpc3QuXG4gICAqL1xuICBwcm90ZWN0ZWQgaGFzRW50aXR5KGlkOiBnZXRJRFR5cGU8U3RhdGU+KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZW50aXRpZXMuaGFzKGlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgdGhlIGVudGl0eSBwbHVnaW4gaW5zdGFuY2UuXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVtb3ZlRW50aXR5KGlkOiBnZXRJRFR5cGU8U3RhdGU+KSB7XG4gICAgdGhpcy5kZXN0cm95KGlkKTtcbiAgICByZXR1cm4gdGhpcy5lbnRpdGllcy5kZWxldGUoaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgZW50aXR5IHBsdWdpbiBpbnN0YW5jZS5cbiAgICovXG4gIHByb3RlY3RlZCBjcmVhdGVFbnRpdHkoaWQ6IGdldElEVHlwZTxTdGF0ZT4sIHBsdWdpbjogUCkge1xuICAgIHJldHVybiB0aGlzLmVudGl0aWVzLnNldChpZCwgcGx1Z2luKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJZiB0aGUgdXNlciBwYXNzZXMgYGVudGl0eUlkc2Agd2UgdGFrZSB0aGVtOyBvdGhlcndpc2UsIHdlIHRha2UgYWxsLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldElkcygpOiBhbnkge1xuICAgIHJldHVybiBpc1VuZGVmaW5lZCh0aGlzLmVudGl0eUlkcykgPyB0aGlzLnF1ZXJ5LmdldFZhbHVlKCkuaWRzIDogY29lcmNlQXJyYXkodGhpcy5lbnRpdHlJZHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZW4geW91IGNhbGwgb25lIG9mIHRoZSBwbHVnaW4gbWV0aG9kcywgeW91IGNhbiBwYXNzIGlkL2lkcyBvciB1bmRlZmluZWQgd2hpY2ggbWVhbnMgYWxsLlxuICAgKi9cbiAgcHJvdGVjdGVkIHJlc29sdmVkSWRzKGlkcz8pOiBnZXRJRFR5cGU8U3RhdGU+W10ge1xuICAgIHJldHVybiBpc1VuZGVmaW5lZChpZHMpID8gdGhpcy5nZXRJZHMoKSA6IGNvZXJjZUFycmF5KGlkcyk7XG4gIH1cblxuICAvKipcbiAgICogQ2FsbCB0aGlzIG1ldGhvZCB3aGVuIHlvdSB3YW50IHRvIGFjdGl2YXRlIHRoZSBwbHVnaW4gb24gaW5pdCBvciB3aGVuIHlvdSBuZWVkIHRvIGxpc3RlbiB0byBhZGQvcmVtb3ZlIG9mIGVudGl0aWVzIGR5bmFtaWNhbGx5LlxuICAgKlxuICAgKiBGb3IgZXhhbXBsZSBpbiB5b3VyIHBsdWdpbiB5b3UgbWF5IGRvIHRoZSBmb2xsb3dpbmc6XG4gICAqXG4gICAqIHRoaXMucXVlcnkuc2VsZWN0KHN0YXRlID0+IHN0YXRlLmlkcykucGlwZShza2lwKDEpKS5zdWJzY3JpYmUoaWRzID0+IHRoaXMuYWN0aXZhdGUoaWRzKSk7XG4gICAqL1xuICBwcm90ZWN0ZWQgcmViYXNlKGlkczogZ2V0SURUeXBlPFN0YXRlPltdLCBhY3Rpb25zOiBSZWJhc2VBY3Rpb25zPFA+ID0ge30pIHtcbiAgICAvKipcbiAgICAgKlxuICAgICAqIElmIHRoZSB1c2VyIHBhc3NlcyBgZW50aXR5SWRzYCAmIHdlIGhhdmUgbmV3IGlkcyBjaGVjayBpZiB3ZSBuZWVkIHRvIGFkZC9yZW1vdmUgaW5zdGFuY2VzLlxuICAgICAqXG4gICAgICogVGhpcyBwaGFzZSB3aWxsIGJlIGNhbGxlZCBvbmx5IHVwb24gdXBkYXRlLlxuICAgICAqL1xuICAgIGlmICh0b0Jvb2xlYW4oaWRzKSkge1xuICAgICAgLyoqXG4gICAgICAgKiBXaGljaCBtZWFucyBhbGxcbiAgICAgICAqL1xuICAgICAgaWYgKGlzVW5kZWZpbmVkKHRoaXMuZW50aXR5SWRzKSkge1xuICAgICAgICBmb3IgKGxldCBpID0gMCwgbGVuID0gaWRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgY29uc3QgZW50aXR5SWQgPSBpZHNbaV07XG4gICAgICAgICAgaWYgKHRoaXMuaGFzRW50aXR5KGVudGl0eUlkKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGlzRnVuY3Rpb24oYWN0aW9ucy5iZWZvcmVBZGQpICYmIGFjdGlvbnMuYmVmb3JlQWRkKGVudGl0eUlkKTtcbiAgICAgICAgICAgIGNvbnN0IHBsdWdpbiA9IHRoaXMuaW5zdGFudGlhdGVQbHVnaW4oZW50aXR5SWQpO1xuICAgICAgICAgICAgdGhpcy5lbnRpdGllcy5zZXQoZW50aXR5SWQsIHBsdWdpbik7XG4gICAgICAgICAgICBpc0Z1bmN0aW9uKGFjdGlvbnMuYWZ0ZXJBZGQpICYmIGFjdGlvbnMuYWZ0ZXJBZGQocGx1Z2luKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVudGl0aWVzLmZvckVhY2goKHBsdWdpbiwgZW50aXR5SWQpID0+IHtcbiAgICAgICAgICBpZiAoaWRzLmluZGV4T2YoZW50aXR5SWQpID09PSAtMSkge1xuICAgICAgICAgICAgaXNGdW5jdGlvbihhY3Rpb25zLmJlZm9yZVJlbW92ZSkgJiYgYWN0aW9ucy5iZWZvcmVSZW1vdmUocGx1Z2luKTtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlRW50aXR5KGVudGl0eUlkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdoaWNoIG1lYW5zIHRoZSB1c2VyIHBhc3NlcyBzcGVjaWZpYyBpZHNcbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0IF9pZHMgPSBjb2VyY2VBcnJheSh0aGlzLmVudGl0eUlkcyk7XG4gICAgICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBfaWRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgY29uc3QgZW50aXR5SWQgPSBfaWRzW2ldO1xuICAgICAgICAgIC8qKiBUaGUgRW50aXR5IGluIGN1cnJlbnQgaWRzIGFuZCBkb2Vzbid0IGV4aXN0LCBhZGQgaXQuICovXG4gICAgICAgICAgaWYgKGlkcy5pbmRleE9mKGVudGl0eUlkKSA+IC0xICYmIHRoaXMuaGFzRW50aXR5KGVudGl0eUlkKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGlzRnVuY3Rpb24oYWN0aW9ucy5iZWZvcmVBZGQpICYmIGFjdGlvbnMuYmVmb3JlQWRkKGVudGl0eUlkKTtcbiAgICAgICAgICAgIGNvbnN0IHBsdWdpbiA9IHRoaXMuaW5zdGFudGlhdGVQbHVnaW4oZW50aXR5SWQpO1xuICAgICAgICAgICAgdGhpcy5lbnRpdGllcy5zZXQoZW50aXR5SWQsIHBsdWdpbik7XG4gICAgICAgICAgICBpc0Z1bmN0aW9uKGFjdGlvbnMuYWZ0ZXJBZGQpICYmIGFjdGlvbnMuYWZ0ZXJBZGQocGx1Z2luKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lbnRpdGllcy5mb3JFYWNoKChwbHVnaW4sIGVudGl0eUlkKSA9PiB7XG4gICAgICAgICAgICAgIC8qKiBUaGUgRW50aXR5IG5vdCBpbiBjdXJyZW50IGlkcyBhbmQgZXhpc3RzLCByZW1vdmUgaXQuICovXG4gICAgICAgICAgICAgIGlmIChpZHMuaW5kZXhPZihlbnRpdHlJZCkgPT09IC0xICYmIHRoaXMuaGFzRW50aXR5KGVudGl0eUlkKSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGlzRnVuY3Rpb24oYWN0aW9ucy5iZWZvcmVSZW1vdmUpICYmIGFjdGlvbnMuYmVmb3JlUmVtb3ZlKHBsdWdpbik7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVFbnRpdHkoZW50aXR5SWQpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLyoqXG4gICAgICAgKiBPdGhlcndpc2UsIHN0YXJ0IHdpdGggdGhlIHByb3ZpZGVkIGlkcyBvciBhbGwuXG4gICAgICAgKi9cbiAgICAgIHRoaXMuZ2V0SWRzKCkuZm9yRWFjaChpZCA9PiB7XG4gICAgICAgIGlmICghdGhpcy5oYXNFbnRpdHkoaWQpKSB0aGlzLmNyZWF0ZUVudGl0eShpZCwgdGhpcy5pbnN0YW50aWF0ZVBsdWdpbihpZCkpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIExpc3RlbiBmb3IgYWRkL3JlbW92ZSBlbnRpdGllcy5cbiAgICovXG4gIHByb3RlY3RlZCBzZWxlY3RJZHMoKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeS5zZWxlY3Qoc3RhdGUgPT4gc3RhdGUuaWRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCYXNlIG1ldGhvZCBmb3IgYWN0aXZhdGlvbiwgeW91IGNhbiBvdmVycmlkZSBpdCBpZiB5b3UgbmVlZCB0by5cbiAgICovXG4gIHByb3RlY3RlZCBhY3RpdmF0ZShpZHM/OiBhbnlbXSkge1xuICAgIHRoaXMucmViYXNlKGlkcyk7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgaXMgcmVzcG9uc2libGUgZm9yIHBsdWdpbiBpbnN0YW50aWF0aW9uLlxuICAgKlxuICAgKiBGb3IgZXhhbXBsZTpcbiAgICogcmV0dXJuIG5ldyBTdGF0ZUhpc3RvcnkodGhpcy5xdWVyeSwgdGhpcy5wYXJhbXMsIGlkKSBhcyBQO1xuICAgKi9cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGluc3RhbnRpYXRlUGx1Z2luKGlkOiBnZXRJRFR5cGU8U3RhdGU+KTogUDtcblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgaXMgcmVzcG9uc2libGUgZm9yIGNsZWFuaW5nLlxuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IGRlc3Ryb3koaWQ/OiBnZXRJRFR5cGU8U3RhdGU+KTtcblxuICAvKipcbiAgICogTG9vcCBvdmVyIGVhY2ggaWQgYW5kIGludm9rZSB0aGUgcGx1Z2luIG1ldGhvZC5cbiAgICovXG4gIHByb3RlY3RlZCBmb3JFYWNoSWQoaWRzOiBPckFycmF5PGdldElEVHlwZTxTdGF0ZT4+LCBjYjogKGVudGl0eTogUCkgPT4gYW55KSB7XG4gICAgY29uc3QgX2lkcyA9IHRoaXMucmVzb2x2ZWRJZHMoaWRzKTtcblxuICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBfaWRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBjb25zdCBpZCA9IF9pZHNbaV07XG4gICAgICBpZiAodGhpcy5oYXNFbnRpdHkoaWQpKSB7XG4gICAgICAgIGNiKHRoaXMuZ2V0RW50aXR5KGlkKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=