UNPKG

@ngxs-labs/entity-state

Version:

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.0.5.

688 lines 56.7 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { EntityActionType } from './actions'; import { InvalidIdError, NoSuchEntityError, UpdateFailedError } from './errors'; import { asArray, elvis, getActive, mustGetActive, NGXS_META_KEY, wrapOrClamp } from './internal'; /** * Returns a new object which serves as the default state. * No entities, loading is false, error is undefined, active is undefined. * pageSize is 10 and pageIndex is 0. * @template T * @param {?=} defaults * @return {?} */ export function defaultEntityState(defaults = {}) { return Object.assign({ entities: {}, ids: [], loading: false, error: undefined, active: undefined, pageSize: 10, pageIndex: 0, lastUpdated: Date.now() }, defaults); } // @dynamic /** * @abstract * @template T */ export class EntityState { /** * @protected * @param {?} storeClass * @param {?} _idKey * @param {?} idStrategy */ constructor(storeClass, _idKey, idStrategy) { this.idKey = (/** @type {?} */ (_idKey)); this.storePath = storeClass[NGXS_META_KEY].path; this.idGenerator = new idStrategy(_idKey); this.setup(storeClass, Object.values(EntityActionType)); } /** * @private * @return {?} */ static get staticStorePath() { /** @type {?} */ const that = this; return that[NGXS_META_KEY].path; } /** * This function is called every time an entity is updated. * It receives the current entity and a partial entity that was either passed directly or generated with a function. * The default implementation uses the spread operator to create a new entity. * You must override this method if your entity type does not support the spread operator. * @see Updater * \@example * // default behavior * onUpdate(current: Readonly<T updated: Partial<T>): T { * return {...current, ...updated}; * } * @param {?} current The current entity, readonly * @param {?} updated The new data as a partial entity * @return {?} */ onUpdate(current, updated) { return (/** @type {?} */ (Object.assign({}, current, updated))); } // ------------------- SELECTORS ------------------- /** * Returns a selector for the activeId * @return {?} */ static get activeId() { /** @type {?} */ const that = this; return (/** * @param {?} state * @return {?} */ state => { /** @type {?} */ const subState = (/** @type {?} */ (elvis(state, that.staticStorePath))); return subState.active; }); } /** * Returns a selector for the active entity * @return {?} */ static get active() { /** @type {?} */ const that = this; return (/** * @param {?} state * @return {?} */ state => { /** @type {?} */ const subState = (/** @type {?} */ (elvis(state, that.staticStorePath))); return getActive(subState); }); } /** * Returns a selector for the keys of all entities * @return {?} */ static get keys() { /** @type {?} */ const that = this; return (/** * @param {?} state * @return {?} */ state => { /** @type {?} */ const subState = (/** @type {?} */ (elvis(state, that.staticStorePath))); return Object.keys(subState.entities); }); } /** * Returns a selector for all entities, sorted by insertion order * @return {?} */ static get entities() { /** @type {?} */ const that = this; return (/** * @param {?} state * @return {?} */ state => { /** @type {?} */ const subState = (/** @type {?} */ (elvis(state, that.staticStorePath))); return subState.ids.map((/** * @param {?} id * @return {?} */ id => subState.entities[id])); }); } /** * Returns a selector for the nth entity, sorted by insertion order * @param {?} index * @return {?} */ static nthEntity(index) { // tslint:disable-line:member-ordering /** @type {?} */ const that = this; return (/** * @param {?} state * @return {?} */ state => { /** @type {?} */ const subState = (/** @type {?} */ (elvis(state, that.staticStorePath))); /** @type {?} */ const id = subState.ids[index]; return subState.entities[id]; }); } /** * Returns a selector for paginated entities, sorted by insertion order * @return {?} */ static get paginatedEntities() { // tslint:disable-line:member-ordering /** @type {?} */ const that = this; return (/** * @param {?} state * @return {?} */ state => { /** @type {?} */ const subState = (/** @type {?} */ (elvis(state, that.staticStorePath))); const { ids, pageIndex, pageSize } = subState; return ids .slice(pageIndex * pageSize, (pageIndex + 1) * pageSize) .map((/** * @param {?} id * @return {?} */ id => subState.entities[id])); }); } /** * Returns a selector for the map of entities * @return {?} */ static get entitiesMap() { /** @type {?} */ const that = this; return (/** * @param {?} state * @return {?} */ state => { /** @type {?} */ const subState = (/** @type {?} */ (elvis(state, that.staticStorePath))); return subState.entities; }); } /** * Returns a selector for the size of the entity map * @return {?} */ static get size() { /** @type {?} */ const that = this; return (/** * @param {?} state * @return {?} */ state => { /** @type {?} */ const subState = (/** @type {?} */ (elvis(state, that.staticStorePath))); return Object.keys(subState.entities).length; }); } /** * Returns a selector for the error * @return {?} */ static get error() { /** @type {?} */ const that = this; return (/** * @param {?} state * @return {?} */ state => { /** @type {?} */ const name = that.staticStorePath; return elvis(state, name).error; }); } /** * Returns a selector for the loading state * @return {?} */ static get loading() { /** @type {?} */ const that = this; return (/** * @param {?} state * @return {?} */ state => { /** @type {?} */ const name = that.staticStorePath; return elvis(state, name).loading; }); } /** * Returns a selector for the latest added entity * @return {?} */ static get latest() { /** @type {?} */ const that = this; return (/** * @param {?} state * @return {?} */ state => { /** @type {?} */ const subState = (/** @type {?} */ (elvis(state, that.staticStorePath))); /** @type {?} */ const latestId = subState.ids[subState.ids.length - 1]; return subState.entities[latestId]; }); } /** * Returns a selector for the latest added entity id * @return {?} */ static get latestId() { /** @type {?} */ const that = this; return (/** * @param {?} state * @return {?} */ state => { /** @type {?} */ const subState = (/** @type {?} */ (elvis(state, that.staticStorePath))); return subState.ids[subState.ids.length - 1]; }); } /** * Returns a selector for the update timestamp * @return {?} */ static get lastUpdated() { // tslint:disable-line:member-ordering /** @type {?} */ const that = this; return (/** * @param {?} state * @return {?} */ state => { /** @type {?} */ const subState = (/** @type {?} */ (elvis(state, that.staticStorePath))); return new Date(subState.lastUpdated); }); } /** * Returns a selector for age, based on the update timestamp * @return {?} */ static get age() { // tslint:disable-line:member-ordering /** @type {?} */ const that = this; return (/** * @param {?} state * @return {?} */ state => { /** @type {?} */ const subState = (/** @type {?} */ (elvis(state, that.staticStorePath))); return Date.now() - subState.lastUpdated; }); } // ------------------- ACTION HANDLERS ------------------- /** * The entities given by the payload will be added. * For certain ID strategies this might fail, if it provides an existing ID. * In all cases it will overwrite the ID value in the entity with the calculated ID. * @param {?} __0 * @param {?} __1 * @return {?} */ add({ getState, patchState }, { payload }) { /** @type {?} */ const updated = this._addOrReplace(getState(), payload, ( // for automated ID strategies this mostly shouldn't throw an UnableToGenerateIdError error // for EntityIdGenerator it will throw an error if no ID is present /** * @param {?} p * @param {?} state * @return {?} */ (p, state) => this.idGenerator.generateId(p, state))); patchState(Object.assign({}, updated, { lastUpdated: Date.now() })); } /** * The entities given by the payload will be added. * It first checks if the ID provided by each entity does exist. * If it does the current entity will be replaced. * In all cases it will overwrite the ID value in the entity with the calculated ID. * @param {?} __0 * @param {?} __1 * @return {?} */ createOrReplace({ getState, patchState }, { payload }) { /** @type {?} */ const updated = this._addOrReplace(getState(), payload, (/** * @param {?} p * @param {?} state * @return {?} */ (p, state) => this.idGenerator.getPresentIdOrGenerate(p, state))); patchState(Object.assign({}, updated, { lastUpdated: Date.now() })); } /** * @param {?} __0 * @param {?} __1 * @return {?} */ update({ getState, patchState }, { payload }) { /** @type {?} */ let entities = Object.assign({}, getState().entities); // create copy /** @type {?} */ let affected; if (payload.id === null) { affected = Object.values(entities); } else if (typeof payload.id === 'function') { affected = Object.values(entities).filter((/** * @param {?} e * @return {?} */ e => ((/** @type {?} */ (payload.id)))(e))); } else { /** @type {?} */ const ids = asArray(payload.id); affected = Object.values(entities).filter((/** * @param {?} e * @return {?} */ e => ids.includes(this.idOf(e)))); } if (typeof payload.data === 'function') { affected.forEach((/** * @param {?} e * @return {?} */ e => { entities = this._update(entities, ((/** @type {?} */ (payload.data)))(e), this.idOf(e)); })); } else { affected.forEach((/** * @param {?} e * @return {?} */ e => { entities = this._update(entities, (/** @type {?} */ (payload.data)), this.idOf(e)); })); } patchState({ entities, lastUpdated: Date.now() }); } /** * @param {?} __0 * @param {?} __1 * @return {?} */ updateActive({ getState, patchState }, { payload }) { /** @type {?} */ const state = getState(); const { id, active } = mustGetActive(state); const { entities } = state; if (typeof payload === 'function') { patchState({ entities: Object.assign({}, this._update(entities, payload(active), id)), lastUpdated: Date.now() }); } else { patchState({ entities: Object.assign({}, this._update(entities, payload, id)), lastUpdated: Date.now() }); } } /** * @param {?} __0 * @return {?} */ removeActive({ getState, patchState }) { const { entities, ids, active } = getState(); delete entities[active]; patchState({ entities: Object.assign({}, entities), ids: ids.filter((/** * @param {?} id * @return {?} */ id => id !== active)), active: undefined, lastUpdated: Date.now() }); } /** * @param {?} __0 * @param {?} __1 * @return {?} */ remove({ getState, patchState }, { payload }) { const { entities, ids, active } = getState(); if (payload === null) { patchState({ entities: {}, ids: [], active: undefined, lastUpdated: Date.now() }); } else { /** @type {?} */ const deleteIds = typeof payload === 'function' ? Object.values(entities) .filter((/** * @param {?} e * @return {?} */ e => payload(e))) .map((/** * @param {?} e * @return {?} */ e => this.idOf(e))) : asArray(payload); /** @type {?} */ const wasActive = deleteIds.includes(active); deleteIds.forEach((/** * @param {?} id * @return {?} */ id => delete entities[id])); patchState({ entities: Object.assign({}, entities), ids: ids.filter((/** * @param {?} id * @return {?} */ id => !deleteIds.includes(id))), active: wasActive ? undefined : active, lastUpdated: Date.now() }); } } /** * @param {?} __0 * @return {?} */ reset({ setState }) { setState(defaultEntityState()); } /** * @param {?} __0 * @param {?} __1 * @return {?} */ setLoading({ patchState }, { payload }) { patchState({ loading: payload }); } /** * @param {?} __0 * @param {?} __1 * @return {?} */ setActive({ patchState }, { payload }) { patchState({ active: payload }); } /** * @param {?} __0 * @return {?} */ clearActive({ patchState }) { patchState({ active: undefined }); } /** * @param {?} __0 * @param {?} __1 * @return {?} */ setError({ patchState }, { payload }) { patchState({ error: payload }); } /** * @param {?} __0 * @param {?} __1 * @return {?} */ goToPage({ getState, patchState }, { payload }) { if ('page' in payload) { patchState({ pageIndex: payload.page }); return; } else if (payload['first']) { patchState({ pageIndex: 0 }); return; } const { pageSize, pageIndex, ids } = getState(); /** @type {?} */ const totalSize = ids.length; /** @type {?} */ const maxIndex = Math.floor(totalSize / pageSize); if ('last' in payload) { patchState({ pageIndex: maxIndex }); } else { /** @type {?} */ const step = payload['prev'] ? -1 : 1; /** @type {?} */ let index = pageIndex + step; index = wrapOrClamp(payload.wrap, index, 0, maxIndex); patchState({ pageIndex: index }); } } /** * @param {?} __0 * @param {?} __1 * @return {?} */ setPageSize({ patchState }, { payload }) { patchState({ pageSize: payload }); } // ------------------- UTILITY ------------------- /** * A utility function to update the given state with the given entities. * It returns a state model with the new entities map and IDs. * For each given entity an ID will be generated. The generated ID will overwrite the current value: * <code>entity[this.idKey] = generatedId(entity, state);</code> * If the ID wasn't present, it will be added to the state's IDs array. * @private * @param {?} state The current state to act on * @param {?} payload One or multiple partial entities * @param {?} generateId A function to generate an ID for each given entity * @return {?} */ _addOrReplace(state, payload, generateId) { const { entities, ids } = state; asArray(payload).forEach((/** * @param {?} entity * @return {?} */ entity => { /** @type {?} */ const id = generateId(entity, state); entity[this.idKey] = id; entities[id] = entity; if (!ids.includes(id)) { ids.push(id); } })); return { entities: Object.assign({}, entities), ids: [...ids] }; } /** * A utility function to update the given entities map with the provided partial entity. * After checking if an entity with the given ID is present, the #onUpdate method is called. * @private * @param {?} entities The current entity map * @param {?} entity The partial entity to update with * @param {?=} id The ID to find the current entity in the map * @return {?} */ _update(entities, entity, id = this.idOf(entity)) { if (id === undefined) { throw new UpdateFailedError(new InvalidIdError(id)); } /** @type {?} */ const current = entities[id]; if (current === undefined) { throw new UpdateFailedError(new NoSuchEntityError(id)); } entities[id] = this.onUpdate(current, entity); return entities; } /** * @private * @param {?} storeClass * @param {?} actions * @return {?} */ setup(storeClass, actions) { // validation if a matching action handler exists has moved to reflection-validation tests actions.forEach((/** * @param {?} fn * @return {?} */ fn => { /** @type {?} */ const actionName = `[${this.storePath}] ${fn}`; storeClass[NGXS_META_KEY].actions[actionName] = [ { fn: fn, options: {}, type: actionName } ]; })); } /** * Returns the id of the given entity, based on the defined idKey. * This methods allows Partial entities and thus might return undefined. * Other methods calling this one have to handle this case themselves. * @protected * @param {?} data a partial entity * @return {?} */ idOf(data) { return data[this.idKey]; } } if (false) { /** * @type {?} * @private */ EntityState.prototype.idKey; /** * @type {?} * @private */ EntityState.prototype.storePath; /** * @type {?} * @protected */ EntityState.prototype.idGenerator; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LXN0YXRlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG5neHMtbGFicy9lbnRpdHktc3RhdGUvIiwic291cmNlcyI6WyJsaWIvZW50aXR5LXN0YXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFFQSxPQUFPLEVBQ0wsZ0JBQWdCLEVBV2pCLE1BQU0sV0FBVyxDQUFDO0FBQ25CLE9BQU8sRUFBRSxjQUFjLEVBQUUsaUJBQWlCLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFaEYsT0FBTyxFQUNMLE9BQU8sRUFDUCxLQUFLLEVBQ0wsU0FBUyxFQUVULGFBQWEsRUFDYixhQUFhLEVBQ2IsV0FBVyxFQUNaLE1BQU0sWUFBWSxDQUFDOzs7Ozs7Ozs7QUFTcEIsTUFBTSxVQUFVLGtCQUFrQixDQUNoQyxXQUF5QyxFQUFFO0lBRTNDLHVCQUNFLFFBQVEsRUFBRSxFQUFFLEVBQ1osR0FBRyxFQUFFLEVBQUUsRUFDUCxPQUFPLEVBQUUsS0FBSyxFQUNkLEtBQUssRUFBRSxTQUFTLEVBQ2hCLE1BQU0sRUFBRSxTQUFTLEVBQ2pCLFFBQVEsRUFBRSxFQUFFLEVBQ1osU0FBUyxFQUFFLENBQUMsRUFDWixXQUFXLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxJQUNwQixRQUFRLEVBQ1g7QUFDSixDQUFDOzs7Ozs7QUFHRCxNQUFNLE9BQWdCLFdBQVc7Ozs7Ozs7SUFLL0IsWUFDRSxVQUFnQyxFQUNoQyxNQUFlLEVBQ2YsVUFBZ0M7UUFFaEMsSUFBSSxDQUFDLEtBQUssR0FBRyxtQkFBQSxNQUFNLEVBQVUsQ0FBQztRQUM5QixJQUFJLENBQUMsU0FBUyxHQUFHLFVBQVUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDaEQsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUUxQyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLGdCQUFnQixD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QUFDLEVBQUMsQ0FBQztJQUNMLENBQUM7Ozs7Ozs7OztJQVFTLElBQUksQ0FBQyxJQUFnQjtRQUM3QixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDMUIsQ0FBQztDQUNGOzs7Ozs7SUE1ZEMsNEJBQStCOzs7OztJQUMvQixnQ0FBbUM7Ozs7O0lBQ25DLGtDQUErQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFR5cGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN0YXRlQ29udGV4dCB9IGZyb20gJ0BuZ3hzL3N0b3JlJztcbmltcG9ydCB7XG4gIEVudGl0eUFjdGlvblR5cGUsXG4gIEVudGl0eUFkZEFjdGlvbixcbiAgRW50aXR5Q3JlYXRlT3JSZXBsYWNlQWN0aW9uLFxuICBFbnRpdHlHb1RvUGFnZUFjdGlvbixcbiAgRW50aXR5UmVtb3ZlQWN0aW9uLFxuICBFbnRpdHlTZXRBY3RpdmVBY3Rpb24sXG4gIEVudGl0eVNldEVycm9yQWN0aW9uLFxuICBFbnRpdHlTZXRMb2FkaW5nQWN0aW9uLFxuICBFbnRpdHlTZXRQYWdlU2l6ZUFjdGlvbixcbiAgRW50aXR5VXBkYXRlQWN0aW9uLFxuICBFbnRpdHlVcGRhdGVBY3RpdmVBY3Rpb25cbn0gZnJvbSAnLi9hY3Rpb25zJztcbmltcG9ydCB7IEludmFsaWRJZEVycm9yLCBOb1N1Y2hFbnRpdHlFcnJvciwgVXBkYXRlRmFpbGVkRXJyb3IgfSBmcm9tICcuL2Vycm9ycyc7XG5pbXBvcnQgeyBJZFN0cmF0ZWd5IH0gZnJvbSAnLi9pZC1zdHJhdGVneSc7XG5pbXBvcnQge1xuICBhc0FycmF5LFxuICBlbHZpcyxcbiAgZ2V0QWN0aXZlLFxuICBIYXNoTWFwLFxuICBtdXN0R2V0QWN0aXZlLFxuICBOR1hTX01FVEFfS0VZLFxuICB3cmFwT3JDbGFtcFxufSBmcm9tICcuL2ludGVybmFsJztcbmltcG9ydCB7IEVudGl0eVN0YXRlTW9kZWwsIFN0YXRlU2VsZWN0b3IgfSBmcm9tICcuL21vZGVscyc7XG5pbXBvcnQgSWRHZW5lcmF0b3IgPSBJZFN0cmF0ZWd5LklkR2VuZXJhdG9yO1xuXG4vKipcbiAqIFJldHVybnMgYSBuZXcgb2JqZWN0IHdoaWNoIHNlcnZlcyBhcyB0aGUgZGVmYXVsdCBzdGF0ZS5cbiAqIE5vIGVudGl0aWVzLCBsb2FkaW5nIGlzIGZhbHNlLCBlcnJvciBpcyB1bmRlZmluZWQsIGFjdGl2ZSBpcyB1bmRlZmluZWQuXG4gKiBwYWdlU2l6ZSBpcyAxMCBhbmQgcGFnZUluZGV4IGlzIDAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWZhdWx0RW50aXR5U3RhdGU8VD4oXG4gIGRlZmF1bHRzOiBQYXJ0aWFsPEVudGl0eVN0YXRlTW9kZWw8VD4+ID0ge31cbik6IEVudGl0eVN0YXRlTW9kZWw8VD4ge1xuICByZXR1cm4ge1xuICAgIGVudGl0aWVzOiB7fSxcbiAgICBpZHM6IFtdLFxuICAgIGxvYWRpbmc6IGZhbHNlLFxuICAgIGVycm9yOiB1bmRlZmluZWQsXG4gICAgYWN0aXZlOiB1bmRlZmluZWQsXG4gICAgcGFnZVNpemU6IDEwLFxuICAgIHBhZ2VJbmRleDogMCxcbiAgICBsYXN0VXBkYXRlZDogRGF0ZS5ub3coKSxcbiAgICAuLi5kZWZhdWx0c1xuICB9O1xufVxuXG4vLyBAZHluYW1pY1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEVudGl0eVN0YXRlPFQgZXh0ZW5kcyB7fT4ge1xuICBwcml2YXRlIHJlYWRvbmx5IGlkS2V5OiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3RvcmVQYXRoOiBzdHJpbmc7XG4gIHByb3RlY3RlZCByZWFkb25seSBpZEdlbmVyYXRvcjogSWRHZW5lcmF0b3I8VD47XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIHN0b3JlQ2xhc3M6IFR5cGU8RW50aXR5U3RhdGU8VD4+LFxuICAgIF9pZEtleToga2V5b2YgVCxcbiAgICBpZFN0cmF0ZWd5OiBUeXBlPElkR2VuZXJhdG9yPFQ+PlxuICApIHtcbiAgICB0aGlzLmlkS2V5ID0gX2lkS2V5IGFzIHN0cmluZztcbiAgICB0aGlzLnN0b3JlUGF0aCA9IHN0b3JlQ2xhc3NbTkdYU19NRVRBX0tFWV0ucGF0aDtcbiAgICB0aGlzLmlkR2VuZXJhdG9yID0gbmV3IGlkU3RyYXRlZ3koX2lkS2V5KTtcblxuICAgIHRoaXMuc2V0dXAoc3RvcmVDbGFzcywgT2JqZWN0LnZhbHVlcyhFbnRpdHlBY3Rpb25UeXBlKSk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBnZXQgc3RhdGljU3RvcmVQYXRoKCk6IHN0cmluZyB7XG4gICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgcmV0dXJuIHRoYXRbTkdYU19NRVRBX0tFWV0ucGF0aDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBldmVyeSB0aW1lIGFuIGVudGl0eSBpcyB1cGRhdGVkLlxuICAgKiBJdCByZWNlaXZlcyB0aGUgY3VycmVudCBlbnRpdHkgYW5kIGEgcGFydGlhbCBlbnRpdHkgdGhhdCB3YXMgZWl0aGVyIHBhc3NlZCBkaXJlY3RseSBvciBnZW5lcmF0ZWQgd2l0aCBhIGZ1bmN0aW9uLlxuICAgKiBUaGUgZGVmYXVsdCBpbXBsZW1lbnRhdGlvbiB1c2VzIHRoZSBzcHJlYWQgb3BlcmF0b3IgdG8gY3JlYXRlIGEgbmV3IGVudGl0eS5cbiAgICogWW91IG11c3Qgb3ZlcnJpZGUgdGhpcyBtZXRob2QgaWYgeW91ciBlbnRpdHkgdHlwZSBkb2VzIG5vdCBzdXBwb3J0IHRoZSBzcHJlYWQgb3BlcmF0b3IuXG4gICAqIEBzZWUgVXBkYXRlclxuICAgKiBAcGFyYW0gY3VycmVudCBUaGUgY3VycmVudCBlbnRpdHksIHJlYWRvbmx5XG4gICAqIEBwYXJhbSB1cGRhdGVkIFRoZSBuZXcgZGF0YSBhcyBhIHBhcnRpYWwgZW50aXR5XG4gICAqIEBleGFtcGxlXG4gICAqIC8vIGRlZmF1bHQgYmVoYXZpb3JcbiAgICogb25VcGRhdGUoY3VycmVudDogUmVhZG9ubHk8VCB1cGRhdGVkOiBQYXJ0aWFsPFQ+KTogVCB7XG4gIHJldHVybiB7Li4uY3VycmVudCwgLi4udXBkYXRlZH07XG4gfVxuICAgKi9cbiAgb25VcGRhdGUoY3VycmVudDogUmVhZG9ubHk8VD4sIHVwZGF0ZWQ6IFBhcnRpYWw8VD4pOiBUIHtcbiAgICByZXR1cm4geyAuLi5jdXJyZW50LCAuLi51cGRhdGVkIH0gYXMgVDtcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0gU0VMRUNUT1JTIC0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvKipcbiAgICogUmV0dXJucyBhIHNlbGVjdG9yIGZvciB0aGUgYWN0aXZlSWRcbiAgICovXG4gIHN0YXRpYyBnZXQgYWN0aXZlSWQoKTogU3RhdGVTZWxlY3RvcjxzdHJpbmc+IHtcbiAgICBjb25zdCB0aGF0ID0gdGhpcztcbiAgICByZXR1cm4gc3RhdGUgPT4ge1xuICAgICAgY29uc3Qgc3ViU3RhdGUgPSBlbHZpcyhzdGF0ZSwgdGhhdC5zdGF0aWNTdG9yZVBhdGgpIGFzIEVudGl0eVN0YXRlTW9kZWw8YW55PjtcbiAgICAgIHJldHVybiBzdWJTdGF0ZS5hY3RpdmU7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc2VsZWN0b3IgZm9yIHRoZSBhY3RpdmUgZW50aXR5XG4gICAqL1xuICBzdGF0aWMgZ2V0IGFjdGl2ZSgpOiBTdGF0ZVNlbGVjdG9yPGFueT4ge1xuICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgIHJldHVybiBzdGF0ZSA9PiB7XG4gICAgICBjb25zdCBzdWJTdGF0ZSA9IGVsdmlzKHN0YXRlLCB0aGF0LnN0YXRpY1N0b3JlUGF0aCkgYXMgRW50aXR5U3RhdGVNb2RlbDxhbnk+O1xuICAgICAgcmV0dXJuIGdldEFjdGl2ZShzdWJTdGF0ZSk7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc2VsZWN0b3IgZm9yIHRoZSBrZXlzIG9mIGFsbCBlbnRpdGllc1xuICAgKi9cbiAgc3RhdGljIGdldCBrZXlzKCk6IFN0YXRlU2VsZWN0b3I8c3RyaW5nW10+IHtcbiAgICBjb25zdCB0aGF0ID0gdGhpcztcbiAgICByZXR1cm4gc3RhdGUgPT4ge1xuICAgICAgY29uc3Qgc3ViU3RhdGUgPSBlbHZpcyhzdGF0ZSwgdGhhdC5zdGF0aWNTdG9yZVBhdGgpIGFzIEVudGl0eVN0YXRlTW9kZWw8YW55PjtcbiAgICAgIHJldHVybiBPYmplY3Qua2V5cyhzdWJTdGF0ZS5lbnRpdGllcyk7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc2VsZWN0b3IgZm9yIGFsbCBlbnRpdGllcywgc29ydGVkIGJ5IGluc2VydGlvbiBvcmRlclxuICAgKi9cbiAgc3RhdGljIGdldCBlbnRpdGllcygpOiBTdGF0ZVNlbGVjdG9yPGFueVtdPiB7XG4gICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgcmV0dXJuIHN0YXRlID0+IHtcbiAgICAgIGNvbnN0IHN1YlN0YXRlID0gZWx2aXMoc3RhdGUsIHRoYXQuc3RhdGljU3RvcmVQYXRoKSBhcyBFbnRpdHlTdGF0ZU1vZGVsPGFueT47XG4gICAgICByZXR1cm4gc3ViU3RhdGUuaWRzLm1hcChpZCA9PiBzdWJTdGF0ZS5lbnRpdGllc1tpZF0pO1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIHNlbGVjdG9yIGZvciB0aGUgbnRoIGVudGl0eSwgc29ydGVkIGJ5IGluc2VydGlvbiBvcmRlclxuICAgKi9cbiAgc3RhdGljIG50aEVudGl0eShpbmRleDogbnVtYmVyKTogU3RhdGVTZWxlY3Rvcjxhbnk+IHtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1saW5lOm1lbWJlci1vcmRlcmluZ1xuICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgIHJldHVybiBzdGF0ZSA9PiB7XG4gICAgICBjb25zdCBzdWJTdGF0ZSA9IGVsdmlzKHN0YXRlLCB0aGF0LnN0YXRpY1N0b3JlUGF0aCkgYXMgRW50aXR5U3RhdGVNb2RlbDxhbnk+O1xuICAgICAgY29uc3QgaWQgPSBzdWJTdGF0ZS5pZHNbaW5kZXhdO1xuICAgICAgcmV0dXJuIHN1YlN0YXRlLmVudGl0aWVzW2lkXTtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBzZWxlY3RvciBmb3IgcGFnaW5hdGVkIGVudGl0aWVzLCBzb3J0ZWQgYnkgaW5zZXJ0aW9uIG9yZGVyXG4gICAqL1xuICBzdGF0aWMgZ2V0IHBhZ2luYXRlZEVudGl0aWVzKCk6IFN0YXRlU2VsZWN0b3I8YW55W10+IHtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1saW5lOm1lbWJlci1vcmRlcmluZ1xuICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgIHJldHVybiBzdGF0ZSA9PiB7XG4gICAgICBjb25zdCBzdWJTdGF0ZSA9IGVsdmlzKHN0YXRlLCB0aGF0LnN0YXRpY1N0b3JlUGF0aCkgYXMgRW50aXR5U3RhdGVNb2RlbDxhbnk+O1xuICAgICAgY29uc3QgeyBpZHMsIHBhZ2VJbmRleCwgcGFnZVNpemUgfSA9IHN1YlN0YXRlO1xuICAgICAgcmV0dXJuIGlkc1xuICAgICAgICAuc2xpY2UocGFnZUluZGV4ICogcGFnZVNpemUsIChwYWdlSW5kZXggKyAxKSAqIHBhZ2VTaXplKVxuICAgICAgICAubWFwKGlkID0+IHN1YlN0YXRlLmVudGl0aWVzW2lkXSk7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc2VsZWN0b3IgZm9yIHRoZSBtYXAgb2YgZW50aXRpZXNcbiAgICovXG4gIHN0YXRpYyBnZXQgZW50aXRpZXNNYXAoKTogU3RhdGVTZWxlY3RvcjxIYXNoTWFwPGFueT4+IHtcbiAgICBjb25zdCB0aGF0ID0gdGhpcztcbiAgICByZXR1cm4gc3RhdGUgPT4ge1xuICAgICAgY29uc3Qgc3ViU3RhdGUgPSBlbHZpcyhzdGF0ZSwgdGhhdC5zdGF0aWNTdG9yZVBhdGgpIGFzIEVudGl0eVN0YXRlTW9kZWw8YW55PjtcbiAgICAgIHJldHVybiBzdWJTdGF0ZS5lbnRpdGllcztcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBzZWxlY3RvciBmb3IgdGhlIHNpemUgb2YgdGhlIGVudGl0eSBtYXBcbiAgICovXG4gIHN0YXRpYyBnZXQgc2l6ZSgpOiBTdGF0ZVNlbGVjdG9yPG51bWJlcj4ge1xuICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgIHJldHVybiBzdGF0ZSA9PiB7XG4gICAgICBjb25zdCBzdWJTdGF0ZSA9IGVsdmlzKHN0YXRlLCB0aGF0LnN0YXRpY1N0b3JlUGF0aCkgYXMgRW50aXR5U3RhdGVNb2RlbDxhbnk+O1xuICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHN1YlN0YXRlLmVudGl0aWVzKS5sZW5ndGg7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc2VsZWN0b3IgZm9yIHRoZSBlcnJvclxuICAgKi9cbiAgc3RhdGljIGdldCBlcnJvcigpOiBTdGF0ZVNlbGVjdG9yPEVycm9yIHwgdW5kZWZpbmVkPiB7XG4gICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgcmV0dXJuIHN0YXRlID0+IHtcbiAgICAgIGNvbnN0IG5hbWUgPSB0aGF0LnN0YXRpY1N0b3JlUGF0aDtcbiAgICAgIHJldHVybiBlbHZpcyhzdGF0ZSwgbmFtZSkuZXJyb3I7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc2VsZWN0b3IgZm9yIHRoZSBsb2FkaW5nIHN0YXRlXG4gICAqL1xuICBzdGF0aWMgZ2V0IGxvYWRpbmcoKTogU3RhdGVTZWxlY3Rvcjxib29sZWFuPiB7XG4gICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgcmV0dXJuIHN0YXRlID0+IHtcbiAgICAgIGNvbnN0IG5hbWUgPSB0aGF0LnN0YXRpY1N0b3JlUGF0aDtcbiAgICAgIHJldHVybiBlbHZpcyhzdGF0ZSwgbmFtZSkubG9hZGluZztcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBzZWxlY3RvciBmb3IgdGhlIGxhdGVzdCBhZGRlZCBlbnRpdHlcbiAgICovXG4gIHN0YXRpYyBnZXQgbGF0ZXN0KCk6IFN0YXRlU2VsZWN0b3I8YW55PiB7XG4gICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgcmV0dXJuIHN0YXRlID0+IHtcbiAgICAgIGNvbnN0IHN1YlN0YXRlID0gZWx2aXMoc3RhdGUsIHRoYXQuc3RhdGljU3RvcmVQYXRoKSBhcyBFbnRpdHlTdGF0ZU1vZGVsPGFueT47XG4gICAgICBjb25zdCBsYXRlc3RJZCA9IHN1YlN0YXRlLmlkc1tzdWJTdGF0ZS5pZHMubGVuZ3RoIC0gMV07XG4gICAgICByZXR1cm4gc3ViU3RhdGUuZW50aXRpZXNbbGF0ZXN0SWRdO1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIHNlbGVjdG9yIGZvciB0aGUgbGF0ZXN0IGFkZGVkIGVudGl0eSBpZFxuICAgKi9cbiAgc3RhdGljIGdldCBsYXRlc3RJZCgpOiBTdGF0ZVNlbGVjdG9yPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgIHJldHVybiBzdGF0ZSA9PiB7XG4gICAgICBjb25zdCBzdWJTdGF0ZSA9IGVsdmlzKHN0YXRlLCB0aGF0LnN0YXRpY1N0b3JlUGF0aCkgYXMgRW50aXR5U3RhdGVNb2RlbDxhbnk+O1xuICAgICAgcmV0dXJuIHN1YlN0YXRlLmlkc1tzdWJTdGF0ZS5pZHMubGVuZ3RoIC0gMV07XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc2VsZWN0b3IgZm9yIHRoZSB1cGRhdGUgdGltZXN0YW1wXG4gICAqL1xuICBzdGF0aWMgZ2V0IGxhc3RVcGRhdGVkKCk6IFN0YXRlU2VsZWN0b3I8RGF0ZT4ge1xuICAgIC8vIHRzbGludDpkaXNhYmxlLWxpbmU6bWVtYmVyLW9yZGVyaW5nXG4gICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgcmV0dXJuIHN0YXRlID0+IHtcbiAgICAgIGNvbnN0IHN1YlN0YXRlID0gZWx2aXMoc3RhdGUsIHRoYXQuc3RhdGljU3RvcmVQYXRoKSBhcyBFbnRpdHlTdGF0ZU1vZGVsPGFueT47XG4gICAgICByZXR1cm4gbmV3IERhdGUoc3ViU3RhdGUubGFzdFVwZGF0ZWQpO1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIHNlbGVjdG9yIGZvciBhZ2UsIGJhc2VkIG9uIHRoZSB1cGRhdGUgdGltZXN0YW1wXG4gICAqL1xuICBzdGF0aWMgZ2V0IGFnZSgpOiBTdGF0ZVNlbGVjdG9yPG51bWJlcj4ge1xuICAgIC8vIHRzbGludDpkaXNhYmxlLWxpbmU6bWVtYmVyLW9yZGVyaW5nXG4gICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgcmV0dXJuIHN0YXRlID0+IHtcbiAgICAgIGNvbnN0IHN1YlN0YXRlID0gZWx2aXMoc3RhdGUsIHRoYXQuc3RhdGljU3RvcmVQYXRoKSBhcyBFbnRpdHlTdGF0ZU1vZGVsPGFueT47XG4gICAgICByZXR1cm4gRGF0ZS5ub3coKSAtIHN1YlN0YXRlLmxhc3RVcGRhdGVkO1xuICAgIH07XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tIEFDVElPTiBIQU5ETEVSUyAtLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLyoqXG4gICAqIFRoZSBlbnRpdGllcyBnaXZlbiBieSB0aGUgcGF5bG9hZCB3aWxsIGJlIGFkZGVkLlxuICAgKiBGb3IgY2VydGFpbiBJRCBzdHJhdGVnaWVzIHRoaXMgbWlnaHQgZmFpbCwgaWYgaXQgcHJvdmlkZXMgYW4gZXhpc3RpbmcgSUQuXG4gICAqIEluIGFsbCBjYXNlcyBpdCB3aWxsIG92ZXJ3cml0ZSB0aGUgSUQgdmFsdWUgaW4gdGhlIGVudGl0eSB3aXRoIHRoZSBjYWxjdWxhdGVkIElELlxuICAgKi9cbiAgYWRkKFxuICAgIHsgZ2V0U3RhdGUsIHBhdGNoU3RhdGUgfTogU3RhdGVDb250ZXh0PEVudGl0eVN0YXRlTW9kZWw8VD4+LFxuICAgIHsgcGF5bG9hZCB9OiBFbnRpdHlBZGRBY3Rpb248VD5cbiAgKSB7XG4gICAgY29uc3QgdXBkYXRlZCA9IHRoaXMuX2FkZE9yUmVwbGFjZShcbiAgICAgIGdldFN0YXRlKCksXG4gICAgICBwYXlsb2FkLFxuICAgICAgLy8gZm9yIGF1dG9tYXRlZCBJRCBzdHJhdGVnaWVzIHRoaXMgbW9zdGx5IHNob3VsZG4ndCB0aHJvdyBhbiBVbmFibGVUb0dlbmVyYXRlSWRFcnJvciBlcnJvclxuICAgICAgLy8gZm9yIEVudGl0eUlkR2VuZXJhdG9yIGl0IHdpbGwgdGhyb3cgYW4gZXJyb3IgaWYgbm8gSUQgaXMgcHJlc2VudFxuICAgICAgKHAsIHN0YXRlKSA9PiB0aGlzLmlkR2VuZXJhdG9yLmdlbmVyYXRlSWQocCwgc3RhdGUpXG4gICAgKTtcbiAgICBwYXRjaFN0YXRlKHsgLi4udXBkYXRlZCwgbGFzdFVwZGF0ZWQ6IERhdGUubm93KCkgfSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGVudGl0aWVzIGdpdmVuIGJ5IHRoZSBwYXlsb2FkIHdpbGwgYmUgYWRkZWQuXG4gICAqIEl0IGZpcnN0IGNoZWNrcyBpZiB0aGUgSUQgcHJvdmlkZWQgYnkgZWFjaCBlbnRpdHkgZG9lcyBleGlzdC5cbiAgICogSWYgaXQgZG9lcyB0aGUgY3VycmVudCBlbnRpdHkgd2lsbCBiZSByZXBsYWNlZC5cbiAgICogSW4gYWxsIGNhc2VzIGl0IHdpbGwgb3ZlcndyaXRlIHRoZSBJRCB2YWx1ZSBpbiB0aGUgZW50aXR5IHdpdGggdGhlIGNhbGN1bGF0ZWQgSUQuXG4gICAqL1xuICBjcmVhdGVPclJlcGxhY2UoXG4gICAgeyBnZXRTdGF0ZSwgcGF0Y2hTdGF0ZSB9OiBTdGF0ZUNvbnRleHQ8RW50aXR5U3RhdGVNb2RlbDxUPj4sXG4gICAgeyBwYXlsb2FkIH06IEVudGl0eUNyZWF0ZU9yUmVwbGFjZUFjdGlvbjxUPlxuICApIHtcbiAgICBjb25zdCB1cGRhdGVkID0gdGhpcy5fYWRkT3JSZXBsYWNlKGdldFN0YXRlKCksIHBheWxvYWQsIChwLCBzdGF0ZSkgPT5cbiAgICAgIHRoaXMuaWRHZW5lcmF0b3IuZ2V0UHJlc2VudElkT3JHZW5lcmF0ZShwLCBzdGF0ZSlcbiAgICApO1xuICAgIHBhdGNoU3RhdGUoeyAuLi51cGRhdGVkLCBsYXN0VXBkYXRlZDogRGF0ZS5ub3coKSB9KTtcbiAgfVxuXG4gIHVwZGF0ZShcbiAgICB7IGdldFN0YXRlLCBwYXRjaFN0YXRlIH06IFN0YXRlQ29udGV4dDxFbnRpdHlTdGF0ZU1vZGVsPFQ+PixcbiAgICB7IHBheWxvYWQgfTogRW50aXR5VXBkYXRlQWN0aW9uPFQ+XG4gICkge1xuICAgIGxldCBlbnRpdGllcyA9IHsgLi4uZ2V0U3RhdGUoKS5lbnRpdGllcyB9OyAvLyBjcmVhdGUgY29weVxuXG4gICAgbGV0IGFmZmVjdGVkOiBUW107XG5cbiAgICBpZiAocGF5bG9hZC5pZCA9PT0gbnVsbCkge1xuICAgICAgYWZmZWN0ZWQgPSBPYmplY3QudmFsdWVzKGVudGl0aWVzKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBwYXlsb2FkLmlkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBhZmZlY3RlZCA9IE9iamVjdC52YWx1ZXMoZW50aXRpZXMpLmZpbHRlcihlID0+ICg8RnVuY3Rpb24+cGF5bG9hZC5pZCkoZSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBpZHMgPSBhc0FycmF5KHBheWxvYWQuaWQpO1xuICAgICAgYWZmZWN0ZWQgPSBPYmplY3QudmFsdWVzKGVudGl0aWVzKS5maWx0ZXIoZSA9PiBpZHMuaW5jbHVkZXModGhpcy5pZE9mKGUpKSk7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBwYXlsb2FkLmRhdGEgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGFmZmVjdGVkLmZvckVhY2goZSA9PiB7XG4gICAgICAgIGVudGl0aWVzID0gdGhpcy5fdXBkYXRlKGVudGl0aWVzLCAoPEZ1bmN0aW9uPnBheWxvYWQuZGF0YSkoZSksIHRoaXMuaWRPZihlKSk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWZmZWN0ZWQuZm9yRWFjaChlID0+IHtcbiAgICAgICAgZW50aXRpZXMgPSB0aGlzLl91cGRhdGUoZW50aXRpZXMsIHBheWxvYWQuZGF0YSBhcyBQYXJ0aWFsPFQ+LCB0aGlzLmlkT2YoZSkpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcGF0Y2hTdGF0ZSh7IGVudGl0aWVzLCBsYXN0VXBkYXRlZDogRGF0ZS5ub3coKSB9KTtcbiAgfVxuXG4gIHVwZGF0ZUFjdGl2ZShcbiAgICB7IGdldFN0YXRlLCBwYXRjaFN0YXRlIH06IFN0YXRlQ29udGV4dDxFbnRpdHlTdGF0ZU1vZGVsPFQ+PixcbiAgICB7IHBheWxvYWQgfTogRW50aXR5VXBkYXRlQWN0aXZlQWN0aW9uPFQ+XG4gICkge1xuICAgIGNvbnN0IHN0YXRlID0gZ2V0U3RhdGUoKTtcbiAgICBjb25zdCB7IGlkLCBhY3RpdmUgfSA9IG11c3RHZXRBY3RpdmUoc3RhdGUpO1xuICAgIGNvbnN0IHsgZW50aXRpZXMgfSA9IHN0YXRlO1xuXG4gICAgaWYgKHR5cGVvZiBwYXlsb2FkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBwYXRjaFN0YXRlKHtcbiAgICAgICAgZW50aXRpZXM6IHsgLi4udGhpcy5fdXBkYXRlKGVudGl0aWVzLCBwYXlsb2FkKGFjdGl2ZSksIGlkKSB9LFxuICAgICAgICBsYXN0VXBkYXRlZDogRGF0ZS5ub3coKVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBhdGNoU3RhdGUoe1xuICAgICAgICBlbnRpdGllczogeyAuLi50aGlzLl91cGRhdGUoZW50aXRpZXMsIHBheWxvYWQsIGlkKSB9LFxuICAgICAgICBsYXN0VXBkYXRlZDogRGF0ZS5ub3coKVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcmVtb3ZlQWN0aXZlKHsgZ2V0U3RhdGUsIHBhdGNoU3RhdGUgfTogU3RhdGVDb250ZXh0PEVudGl0eVN0YXRlTW9kZWw8VD4+KSB7XG4gICAgY29uc3QgeyBlbnRpdGllcywgaWRzLCBhY3RpdmUgfSA9IGdldFN0YXRlKCk7XG4gICAgZGVsZXRlIGVudGl0aWVzW2FjdGl2ZV07XG4gICAgcGF0Y2hTdGF0ZSh7XG4gICAgICBlbnRpdGllczogeyAuLi5lbnRpdGllcyB9LFxuICAgICAgaWRzOiBpZHMuZmlsdGVyKGlkID0+IGlkICE9PSBhY3RpdmUpLFxuICAgICAgYWN0aXZlOiB1bmRlZmluZWQsXG4gICAgICBsYXN0VXBkYXRlZDogRGF0ZS5ub3coKVxuICAgIH0pO1xuICB9XG5cbiAgcmVtb3ZlKFxuICAgIHsgZ2V0U3RhdGUsIHBhdGNoU3RhdGUgfTogU3RhdGVDb250ZXh0PEVudGl0eVN0YXRlTW9kZWw8VD4+LFxuICAgIHsgcGF5bG9hZCB9OiBFbnRpdHlSZW1vdmVBY3Rpb248VD5cbiAgKSB7XG4gICAgY29uc3QgeyBlbnRpdGllcywgaWRzLCBhY3RpdmUgfSA9IGdldFN0YXRlKCk7XG5cbiAgICBpZiAocGF5bG9hZCA9PT0gbnVsbCkge1xuICAgICAgcGF0Y2hTdGF0ZSh7XG4gICAgICAgIGVudGl0aWVzOiB7fSxcbiAgICAgICAgaWRzOiBbXSxcbiAgICAgICAgYWN0aXZlOiB1bmRlZmluZWQsXG4gICAgICAgIGxhc3RVcGRhdGVkOiBEYXRl