@ngxs-labs/entity-state
Version:
<p align="center"> <img src="https://raw.githubusercontent.com/ngxs-labs/emitter/master/docs/assets/logo.png"> </p>
269 lines • 36.1 kB
JavaScript
import { createSelector } from '@ngxs/store';
import { EntityActionType } from './actions';
import { InvalidEntitySelectorError } from './errors';
import { asArray, getActive, NGXS_META_KEY, wrapOrClamp } from './internal';
import { addOrReplace, removeAllEntities, removeEntities, update, updateActive } from './state-operators';
/**
* 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.
*/
export function defaultEntityState(defaults = {}) {
return Object.assign({ entities: {}, ids: [], loading: false, error: undefined, active: undefined, pageSize: 10, pageIndex: 0, lastUpdated: Date.now() }, defaults);
}
// tslint:disable:member-ordering
// @dynamic
export class EntityState {
constructor(storeClass, _idKey, idStrategy) {
this.idKey = _idKey;
this.storePath = storeClass[NGXS_META_KEY].path;
this.idGenerator = new idStrategy(_idKey);
this.setup(storeClass, Object.values(EntityActionType));
}
/**
* 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
* @param current The current entity, readonly
* @param updated The new data as a partial entity
* @example
* // default behavior
* onUpdate(current: Readonly<T updated: Partial<T>): T {
return {...current, ...updated};
}
*/
onUpdate(current, updated) {
return Object.assign(Object.assign({}, current), updated);
}
// ------------------- SELECTORS -------------------
/**
* Returns a selector for the activeId
*/
static get activeId() {
return createSelector([this], state => state.active);
}
/**
* Returns a selector for the active entity
*/
static get active() {
return createSelector([this], state => getActive(state));
}
/**
* Returns a selector for the keys of all entities
*/
static get keys() {
return createSelector([this], state => {
return Object.keys(state.entities);
});
}
/**
* Returns a selector for all entities, sorted by insertion order
*/
static get entities() {
return createSelector([this], state => {
return state.ids.map(id => state.entities[id]);
});
}
/**
* Returns a selector for the nth entity, sorted by insertion order
*/
static nthEntity(index) {
return createSelector([this], state => {
const id = state.ids[index];
return state.entities[id];
});
}
/**
* Returns a selector for paginated entities, sorted by insertion order
*/
static get paginatedEntities() {
return createSelector([this], state => {
const { ids, pageIndex, pageSize } = state;
return ids
.slice(pageIndex * pageSize, (pageIndex + 1) * pageSize)
.map(id => state.entities[id]);
});
}
/**
* Returns a selector for the map of entities
*/
static get entitiesMap() {
return createSelector([this], state => {
return state.entities;
});
}
/**
* Returns a selector for the size of the entity map
*/
static get size() {
return createSelector([this], state => {
return Object.keys(state.entities).length;
});
}
/**
* Returns a selector for the error
*/
static get error() {
return createSelector([this], state => {
return state.error;
});
}
/**
* Returns a selector for the loading state
*/
static get loading() {
return createSelector([this], state => {
return state.loading;
});
}
/**
* Returns a selector for the latest added entity
*/
static get latest() {
return createSelector([this], state => {
const latestId = state.ids[state.ids.length - 1];
return state.entities[latestId];
});
}
/**
* Returns a selector for the latest added entity id
*/
static get latestId() {
return createSelector([this], state => {
return state.ids[state.ids.length - 1];
});
}
/**
* Returns a selector for the update timestamp
*/
static get lastUpdated() {
return createSelector([this], state => {
return new Date(state.lastUpdated);
});
}
/**
* Returns a selector for age, based on the update timestamp
*/
static get age() {
return createSelector([this], state => {
return Date.now() - state.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.
*/
add({ setState }, { payload }) {
setState(addOrReplace(payload, this.idKey, (entity, state) => this.idGenerator.generateId(entity, state)));
}
/**
* 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.
*/
createOrReplace({ setState }, { payload }) {
setState(addOrReplace(payload, this.idKey, (entity, state) => this.idGenerator.getPresentIdOrGenerate(entity, state)));
}
update({ setState }, { payload }) {
if (payload.selector == null) {
throw new InvalidEntitySelectorError(payload);
}
setState(update(payload, this.idKey, (current, updated) => this.onUpdate(current, updated)));
}
updateAll({ setState }, { payload }) {
setState(update(Object.assign(Object.assign({}, payload), { selector: null }), this.idKey, (current, updated) => this.onUpdate(current, updated)));
}
updateActive({ setState }, { payload }) {
setState(updateActive(payload, this.idKey, (current, updated) => this.onUpdate(current, updated)));
}
removeActive({ getState, setState }) {
const { active } = getState();
setState(removeEntities([active]));
}
remove({ getState, setState, patchState }, { payload }) {
if (payload === null) {
throw new InvalidEntitySelectorError(payload);
}
else {
const deleteIds = typeof payload === 'function'
? Object.values(getState().entities)
.filter(entity => payload(entity))
.map(entity => this.idOf(entity))
: asArray(payload);
// can't pass in predicate as you need IDs and thus EntityState#idOf
setState(removeEntities(deleteIds));
}
}
removeAll({ setState }) {
setState(removeAllEntities());
}
reset({ setState }) {
setState(defaultEntityState());
}
setLoading({ patchState }, { payload }) {
patchState({ loading: payload });
}
setActive({ patchState }, { payload }) {
patchState({ active: payload });
}
clearActive({ patchState }) {
patchState({ active: undefined });
}
setError({ patchState }, { payload }) {
patchState({ error: payload });
}
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();
const totalSize = ids.length;
const maxIndex = Math.floor(totalSize / pageSize);
if ('last' in payload) {
patchState({ pageIndex: maxIndex });
}
else {
const step = payload['prev'] ? -1 : 1;
let index = pageIndex + step;
index = wrapOrClamp(payload.wrap, index, 0, maxIndex);
patchState({ pageIndex: index });
}
}
setPageSize({ patchState }, { payload }) {
patchState({ pageSize: payload });
}
// ------------------- UTILITY -------------------
setup(storeClass, actions) {
// validation if a matching action handler exists has moved to reflection-validation tests
actions.forEach(fn => {
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.
* @param data a partial entity
*/
idOf(data) {
return data[this.idKey];
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LXN0YXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9lbnRpdHktc3RhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFnQixjQUFjLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDM0QsT0FBTyxFQUNMLGdCQUFnQixFQVdqQixNQUFNLFdBQVcsQ0FBQztBQUNuQixPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFdEQsT0FBTyxFQUFFLE9BQU8sRUFBcUIsU0FBUyxFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFL0YsT0FBTyxFQUNMLFlBQVksRUFDWixpQkFBaUIsRUFDakIsY0FBYyxFQUNkLE1BQU0sRUFDTixZQUFZLEVBQ2IsTUFBTSxtQkFBbUIsQ0FBQztBQUczQjs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLGtCQUFrQixDQUNoQyxXQUF5QyxFQUFFO0lBRTNDLHVCQUNFLFFBQVEsRUFBRSxFQUFFLEVBQ1osR0FBRyxFQUFFLEVBQUUsRUFDUCxPQUFPLEVBQUUsS0FBSyxFQUNkLEtBQUssRUFBRSxTQUFTLEVBQ2hCLE1BQU0sRUFBRSxTQUFTLEVBQ2pCLFFBQVEsRUFBRSxFQUFFLEVBQ1osU0FBUyxFQUFFLENBQUMsRUFDWixXQUFXLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxJQUNwQixRQUFRLEVBQ1g7QUFDSixDQUFDO0FBRUQsaUNBQWlDO0FBRWpDLFdBQVc7QUFDWCxNQUFNLE9BQWdCLFdBQVc7SUFLL0IsWUFDRSxVQUFnQyxFQUNoQyxNQUFlLEVBQ2YsVUFBZ0M7UUFFaEMsSUFBSSxDQUFDLEtBQUssR0FBRyxNQUFnQixDQUFDO1FBQzlCLElBQUksQ0FBQyxTQUFTLEdBQUcsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNoRCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksVUFBVSxDQUFDLE1B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RTFDLEtBQUssQ0FBQyxVQUFnQyxFQUFFLE9BQWlCO1FBQy9ELDBGQUEwRjtRQUMxRixPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFO1lBQ25CLE1BQU0sVUFBVSxHQUFHLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxFQUFFLEVBQUUsQ0FBQztZQUMvQyxVQUFVLENBQUMsYUFBYSxDQUFDLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxHQUFHO2dCQUM5QztvQkFDRSxFQUFFLEVBQUUsRUFBRTtvQkFDTixPQUFPLEVBQUUsRUFBRTtvQkFDWCxJQUFJLEVBQUUsVUFBVTtpQkFDakI7YUFDRixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDTyxJQUFJLENBQUMsSUFBZ0I7UUFDN0IsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzFCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFR5cGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgU3RhdGVDb250ZXh0LCBjcmVhdGVTZWxlY3RvciB9IGZyb20gJ0BuZ3hzL3N0b3JlJztcclxuaW1wb3J0IHtcclxuICBFbnRpdHlBY3Rpb25UeXBlLFxyXG4gIEVudGl0eUFkZEFjdGlvbixcclxuICBFbnRpdHlDcmVhdGVPclJlcGxhY2VBY3Rpb24sXHJcbiAgRW50aXR5R29Ub1BhZ2VBY3Rpb24sXHJcbiAgRW50aXR5UmVtb3ZlQWN0aW9uLFxyXG4gIEVudGl0eVNldEFjdGl2ZUFjdGlvbixcclxuICBFbnRpdHlTZXRFcnJvckFjdGlvbixcclxuICBFbnRpdHlTZXRMb2FkaW5nQWN0aW9uLFxyXG4gIEVudGl0eVNldFBhZ2VTaXplQWN0aW9uLFxyXG4gIEVudGl0eVVwZGF0ZUFjdGlvbixcclxuICBFbnRpdHlVcGRhdGVBY3RpdmVBY3Rpb25cclxufSBmcm9tICcuL2FjdGlvbnMnO1xyXG5pbXBvcnQgeyBJbnZhbGlkRW50aXR5U2VsZWN0b3JFcnJvciB9IGZyb20gJy4vZXJyb3JzJztcclxuaW1wb3J0IHsgSWRTdHJhdGVneSB9IGZyb20gJy4vaWQtc3RyYXRlZ3knO1xyXG5pbXBvcnQgeyBhc0FycmF5LCBEaWN0aW9uYXJ5LCBlbHZpcywgZ2V0QWN0aXZlLCBOR1hTX01FVEFfS0VZLCB3cmFwT3JDbGFtcCB9IGZyb20gJy4vaW50ZXJuYWwnO1xyXG5pbXBvcnQgeyBFbnRpdHlTdGF0ZU1vZGVsLCBTdGF0ZVNlbGVjdG9yIH0gZnJvbSAnLi9tb2RlbHMnO1xyXG5pbXBvcnQge1xyXG4gIGFkZE9yUmVwbGFjZSxcclxuICByZW1vdmVBbGxFbnRpdGllcyxcclxuICByZW1vdmVFbnRpdGllcyxcclxuICB1cGRhdGUsXHJcbiAgdXBkYXRlQWN0aXZlXHJcbn0gZnJvbSAnLi9zdGF0ZS1vcGVyYXRvcnMnO1xyXG5pbXBvcnQgSWRHZW5lcmF0b3IgPSBJZFN0cmF0ZWd5LklkR2VuZXJhdG9yO1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgYSBuZXcgb2JqZWN0IHdoaWNoIHNlcnZlcyBhcyB0aGUgZGVmYXVsdCBzdGF0ZS5cclxuICogTm8gZW50aXRpZXMsIGxvYWRpbmcgaXMgZmFsc2UsIGVycm9yIGlzIHVuZGVmaW5lZCwgYWN0aXZlIGlzIHVuZGVmaW5lZC5cclxuICogcGFnZVNpemUgaXMgMTAgYW5kIHBhZ2VJbmRleCBpcyAwLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGRlZmF1bHRFbnRpdHlTdGF0ZTxUPihcclxuICBkZWZhdWx0czogUGFydGlhbDxFbnRpdHlTdGF0ZU1vZGVsPFQ+PiA9IHt9XHJcbik6IEVudGl0eVN0YXRlTW9kZWw8VD4ge1xyXG4gIHJldHVybiB7XHJcbiAgICBlbnRpdGllczoge30sXHJcbiAgICBpZHM6IFtdLFxyXG4gICAgbG9hZGluZzogZmFsc2UsXHJcbiAgICBlcnJvcjogdW5kZWZpbmVkLFxyXG4gICAgYWN0aXZlOiB1bmRlZmluZWQsXHJcbiAgICBwYWdlU2l6ZTogMTAsXHJcbiAgICBwYWdlSW5kZXg6IDAsXHJcbiAgICBsYXN0VXBkYXRlZDogRGF0ZS5ub3coKSxcclxuICAgIC4uLmRlZmF1bHRzXHJcbiAgfTtcclxufVxyXG5cclxuLy8gdHNsaW50OmRpc2FibGU6bWVtYmVyLW9yZGVyaW5nXHJcblxyXG4vLyBAZHluYW1pY1xyXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgRW50aXR5U3RhdGU8VCBleHRlbmRzIHt9PiB7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBpZEtleTogc3RyaW5nO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgc3RvcmVQYXRoOiBzdHJpbmc7XHJcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkR2VuZXJhdG9yOiBJZEdlbmVyYXRvcjxUPjtcclxuXHJcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxyXG4gICAgc3RvcmVDbGFzczogVHlwZTxFbnRpdHlTdGF0ZTxUPj4sXHJcbiAgICBfaWRLZXk6IGtleW9mIFQsXHJcbiAgICBpZFN0cmF0ZWd5OiBUeXBlPElkR2VuZXJhdG9yPFQ+PlxyXG4gICkge1xyXG4gICAgdGhpcy5pZEtleSA9IF9pZEtleSBhcyBzdHJpbmc7XHJcbiAgICB0aGlzLnN0b3JlUGF0aCA9IHN0b3JlQ2xhc3NbTkdYU19NRVRBX0tFWV0ucGF0aDtcclxuICAgIHRoaXMuaWRHZW5lcmF0b3IgPSBuZXcgaWRTdHJhdGVneShfaWRLZXkpO1xyXG5cclxuICAgIHRoaXMuc2V0dXAoc3RvcmVDbGFzcywgT2JqZWN0LnZhbHVlcyhFbnRpdHlBY3Rpb25UeXBlKSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBldmVyeSB0aW1lIGFuIGVudGl0eSBpcyB1cGRhdGVkLlxyXG4gICAqIEl0IHJlY2VpdmVzIHRoZSBjdXJyZW50IGVudGl0eSBhbmQgYSBwYXJ0aWFsIGVudGl0eSB0aGF0IHdhcyBlaXRoZXIgcGFzc2VkIGRpcmVjdGx5IG9yIGdlbmVyYXRlZCB3aXRoIGEgZnVuY3Rpb24uXHJcbiAgICogVGhlIGRlZmF1bHQgaW1wbGVtZW50YXRpb24gdXNlcyB0aGUgc3ByZWFkIG9wZXJhdG9yIHRvIGNyZWF0ZSBhIG5ldyBlbnRpdHkuXHJcbiAgICogWW91IG11c3Qgb3ZlcnJpZGUgdGhpcyBtZXRob2QgaWYgeW91ciBlbnRpdHkgdHlwZSBkb2VzIG5vdCBzdXBwb3J0IHRoZSBzcHJlYWQgb3BlcmF0b3IuXHJcbiAgICogQHNlZSBVcGRhdGVyXHJcbiAgICogQHBhcmFtIGN1cnJlbnQgVGhlIGN1cnJlbnQgZW50aXR5LCByZWFkb25seVxyXG4gICAqIEBwYXJhbSB1cGRhdGVkIFRoZSBuZXcgZGF0YSBhcyBhIHBhcnRpYWwgZW50aXR5XHJcbiAgICogQGV4YW1wbGVcclxuICAgKiAvLyBkZWZhdWx0IGJlaGF2aW9yXHJcbiAgICogb25VcGRhdGUoY3VycmVudDogUmVhZG9ubHk8VCB1cGRhdGVkOiBQYXJ0aWFsPFQ+KTogVCB7XHJcbiAgcmV0dXJuIHsuLi5jdXJyZW50LCAuLi51cGRhdGVkfTtcclxuIH1cclxuICAgKi9cclxuICBvblVwZGF0ZShjdXJyZW50OiBSZWFkb25seTxUPiwgdXBkYXRlZDogUGFydGlhbDxUPik6IFQge1xyXG4gICAgcmV0dXJuIHsgLi4uY3VycmVudCwgLi4udXBkYXRlZCB9IGFzIFQ7XHJcbiAgfVxyXG5cclxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tIFNFTEVDVE9SUyAtLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgYSBzZWxlY3RvciBmb3IgdGhlIGFjdGl2ZUlkXHJcbiAgICovXHJcbiAgc3RhdGljIGdldCBhY3RpdmVJZCgpOiBTdGF0ZVNlbGVjdG9yPHN0cmluZz4ge1xyXG4gICAgcmV0dXJuIGNyZWF0ZVNlbGVjdG9yKFt0aGlzXSwgc3RhdGUgPT4gc3RhdGUuYWN0aXZlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgYSBzZWxlY3RvciBmb3IgdGhlIGFjdGl2ZSBlbnRpdHlcclxuICAgKi9cclxuICBzdGF0aWMgZ2V0IGFjdGl2ZSgpOiBTdGF0ZVNlbGVjdG9yPGFueT4ge1xyXG4gICAgcmV0dXJuIGNyZWF0ZVNlbGVjdG9yKFt0aGlzXSwgc3RhdGUgPT4gZ2V0QWN0aXZlKHN0YXRlKSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm5zIGEgc2VsZWN0b3IgZm9yIHRoZSBrZXlzIG9mIGFsbCBlbnRpdGllc1xyXG4gICAqL1xyXG4gIHN0YXRpYyBnZXQga2V5cygpOiBTdGF0ZVNlbGVjdG9yPHN0cmluZ1tdPiB7XHJcbiAgICByZXR1cm4gY3JlYXRlU2VsZWN0b3IoW3RoaXNdLCBzdGF0ZSA9PiB7XHJcbiAgICAgIHJldHVybiBPYmplY3Qua2V5cyhzdGF0ZS5lbnRpdGllcyk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgYSBzZWxlY3RvciBmb3IgYWxsIGVudGl0aWVzLCBzb3J0ZWQgYnkgaW5zZXJ0aW9uIG9yZGVyXHJcbiAgICovXHJcbiAgc3RhdGljIGdldCBlbnRpdGllcygpOiBTdGF0ZVNlbGVjdG9yPGFueVtdPiB7XHJcbiAgICByZXR1cm4gY3JlYXRlU2VsZWN0b3IoW3RoaXNdLCBzdGF0ZSA9PiB7XHJcbiAgICAgIHJldHVybiBzdGF0ZS5pZHMubWFwKGlkID0+IHN0YXRlLmVudGl0aWVzW2lkXSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgYSBzZWxlY3RvciBmb3IgdGhlIG50aCBlbnRpdHksIHNvcnRlZCBieSBpbnNlcnRpb24gb3JkZXJcclxuICAgKi9cclxuICBzdGF0aWMgbnRoRW50aXR5KGluZGV4OiBudW1iZXIpOiBTdGF0ZVNlbGVjdG9yPGFueT4ge1xyXG4gICAgcmV0dXJuIGNyZWF0ZVNlbGVjdG9yKFt0aGlzXSwgc3RhdGUgPT4ge1xyXG4gICAgICBjb25zdCBpZCA9IHN0YXRlLmlkc1tpbmRleF07XHJcbiAgICAgIHJldHVybiBzdGF0ZS5lbnRpdGllc1tpZF07XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgYSBzZWxlY3RvciBmb3IgcGFnaW5hdGVkIGVudGl0aWVzLCBzb3J0ZWQgYnkgaW5zZXJ0aW9uIG9yZGVyXHJcbiAgICovXHJcbiAgc3RhdGljIGdldCBwYWdpbmF0ZWRFbnRpdGllcygpOiBTdGF0ZVNlbGVjdG9yPGFueVtdPiB7XHJcbiAgICByZXR1cm4gY3JlYXRlU2VsZWN0b3IoW3RoaXNdLCBzdGF0ZSA9PiB7XHJcbiAgICAgIGNvbnN0IHsgaWRzLCBwYWdlSW5kZXgsIHBhZ2VTaXplIH0gPSBzdGF0ZTtcclxuICAgICAgcmV0dXJuIGlkc1xyXG4gICAgICAgIC5zbGljZShwYWdlSW5kZXggKiBwYWdlU2l6ZSwgKHBhZ2VJbmRleCArIDEpICogcGFnZVNpemUpXHJcbiAgICAgICAgLm1hcChpZCA9PiBzdGF0ZS5lbnRpdGllc1tpZF0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm5zIGEgc2VsZWN0b3IgZm9yIHRoZSBtYXAgb2YgZW50aXRpZXNcclxuICAgKi9cclxuICBzdGF0aWMgZ2V0IGVudGl0aWVzTWFwKCk6IFN0YXRlU2VsZWN0b3I8RGljdGlvbmFyeTxhbnk+PiB7XHJcbiAgICByZXR1cm4gY3JlYXRlU2VsZWN0b3IoW3RoaXNdLCBzdGF0ZSA9PiB7XHJcbiAgICAgIHJldHVybiBzdGF0ZS5lbnRpdGllcztcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmV0dXJucyBhIHNlbGVjdG9yIGZvciB0aGUgc2l6ZSBvZiB0aGUgZW50aXR5IG1hcFxyXG4gICAqL1xyXG4gIHN0YXRpYyBnZXQgc2l6ZSgpOiBTdGF0ZVNlbGVjdG9yPG51bWJlcj4ge1xyXG4gICAgcmV0dXJuIGNyZWF0ZVNlbGVjdG9yKFt0aGlzXSwgc3RhdGUgPT4ge1xyXG4gICAgICByZXR1cm4gT2JqZWN0LmtleXMoc3RhdGUuZW50aXRpZXMpLmxlbmd0aDtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmV0dXJucyBhIHNlbGVjdG9yIGZvciB0aGUgZXJyb3JcclxuICAgKi9cclxuICBzdGF0aWMgZ2V0IGVycm9yKCk6IFN0YXRlU2VsZWN0b3I8RXJyb3IgfCB1bmRlZmluZWQ+IHtcclxuICAgIHJldHVybiBjcmVhdGVTZWxlY3RvcihbdGhpc10sIHN0YXRlID0+IHtcclxuICAgICAgcmV0dXJuIHN0YXRlLmVycm9yO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm5zIGEgc2VsZWN0b3IgZm9yIHRoZSBsb2FkaW5nIHN0YXRlXHJcbiAgICovXHJcbiAgc3RhdGljIGdldCBsb2FkaW5nKCk6IFN0YXRlU2VsZWN0b3I8Ym9vbGVhbj4ge1xyXG4gICAgcmV0dXJuIGNyZWF0ZVNlbGVjdG9yKFt0aGlzXSwgc3RhdGUgPT4ge1xyXG4gICAgICByZXR1cm4gc3RhdGUubG9hZGluZztcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmV0dXJucyBhIHNlbGVjdG9yIGZvciB0aGUgbGF0ZXN0IGFkZGVkIGVudGl0eVxyXG4gICAqL1xyXG4gIHN0YXRpYyBnZXQgbGF0ZXN0KCk6IFN0YXRlU2VsZWN0b3I8YW55PiB7XHJcbiAgICByZXR1cm4gY3JlYXRlU2VsZWN0b3IoW3RoaXNdLCBzdGF0ZSA9PiB7XHJcbiAgICAgIGNvbnN0IGxhdGVzdElkID0gc3RhdGUuaWRzW3N0YXRlLmlkcy5sZW5ndGggLSAxXTtcclxuICAgICAgcmV0dXJuIHN0YXRlLmVudGl0aWVzW2xhdGVzdElkXTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmV0dXJucyBhIHNlbGVjdG9yIGZvciB0aGUgbGF0ZXN0IGFkZGVkIGVudGl0eSBpZFxyXG4gICAqL1xyXG4gIHN0YXRpYyBnZXQgbGF0ZXN0SWQoKTogU3RhdGVTZWxlY3RvcjxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcclxuICAgIHJldHVybiBjcmVhdGVTZWxlY3RvcihbdGhpc10sIHN0YXRlID0+IHtcclxuICAgICAgcmV0dXJuIHN0YXRlLmlkc1tzdGF0ZS5pZHMubGVuZ3RoIC0gMV07XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgYSBzZWxlY3RvciBmb3IgdGhlIHVwZGF0ZSB0aW1lc3RhbXBcclxuICAgKi9cclxuICBzdGF0aWMgZ2V0IGxhc3RVcGRhdGVkKCk6IFN0YXRlU2VsZWN0b3I8RGF0ZT4ge1xyXG4gICAgcmV0dXJuIGNyZWF0ZVNlbGVjdG9yKFt0aGlzXSwgc3RhdGUgPT4ge1xyXG4gICAgICByZXR1cm4gbmV3IERhdGUoc3RhdGUubGFzdFVwZGF0ZWQpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm5zIGEgc2VsZWN0b3IgZm9yIGFnZSwgYmFzZWQgb24gdGhlIHVwZGF0ZSB0aW1lc3RhbXBcclxuICAgKi9cclxuICBzdGF0aWMgZ2V0IGFnZSgpOiBTdGF0ZVNlbGVjdG9yPG51bWJlcj4ge1xyXG4gICAgcmV0dXJuIGNyZWF0ZVNlbGVjdG9yKFt0aGlzXSwgc3RhdGUgPT4ge1xyXG4gICAgICByZXR1cm4gRGF0ZS5ub3coKSAtIHN0YXRlLmxhc3RVcGRhdGVkO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tIEFDVElPTiBIQU5ETEVSUyAtLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4gIC8qKlxyXG4gICAqIFRoZSBlbnRpdGllcyBnaXZlbiBieSB0aGUgcGF5bG9hZCB3aWxsIGJlIGFkZGVkLlxyXG4gICAqIEZvciBjZXJ0YWluIElEIHN0cmF0ZWdpZXMgdGhpcyBtaWdodCBmYWlsLCBpZiBpdCBwcm92aWRlcyBhbiBleGlzdGluZyBJRC5cclxuICAgKiBJbiBhbGwgY2FzZXMgaXQgd2lsbCBvdmVyd3JpdGUgdGhlIElEIHZhbHVlIGluIHRoZSBlbnRpdHkgd2l0aCB0aGUgY2FsY3VsYXRlZCBJRC5cclxuICAgKi9cclxuICBhZGQoeyBzZXRTdGF0ZSB9OiBTdGF0ZUNvbnRleHQ8RW50aXR5U3RhdGVNb2RlbDxUPj4sIHsgcGF5bG9hZCB9OiBFbnRpdHlBZGRBY3Rpb248VD4pIHtcclxuICAgIHNldFN0YXRlKFxyXG4gICAgICBhZGRPclJlcGxhY2UocGF5bG9hZCwgdGhpcy5pZEtleSwgKGVudGl0eSwgc3RhdGUpID0+XHJcbiAgICAgICAgdGhpcy5pZEdlbmVyYXRvci5nZW5lcmF0ZUlkKGVudGl0eSwgc3RhdGUpXHJcbiAgICAgIClcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUaGUgZW50aXRpZXMgZ2l2ZW4gYnkgdGhlIHBheWxvYWQgd2lsbCBiZSBhZGRlZC5cclxuICAgKiBJdCBmaXJzdCBjaGVja3MgaWYgdGhlIElEIHByb3ZpZGVkIGJ5IGVhY2ggZW50aXR5IGRvZXMgZXhpc3QuXHJcbiAgICogSWYgaXQgZG9lcyB0aGUgY3VycmVudCBlbnRpdHkgd2lsbCBiZSByZXBsYWNlZC5cclxuICAgKiBJbiBhbGwgY2FzZXMgaXQgd2lsbCBvdmVyd3JpdGUgdGhlIElEIHZhbHVlIGluIHRoZSBlbnRpdHkgd2l0aCB0aGUgY2FsY3VsYXRlZCBJRC5cclxuICAgKi9cclxuICBjcmVhdGVPclJlcGxhY2UoXHJcbiAgICB7IHNldFN0YXRlIH06IFN0YXRlQ29udGV4dDxFbnRpdHlTdGF0ZU1vZGVsPFQ+PixcclxuICAgIHsgcGF5bG9hZCB9OiBFbnRpdHlDcmVhdGVPclJlcGxhY2VBY3Rpb248VD5cclxuICApIHtcclxuICAgIHNldFN0YXRlKFxyXG4gICAgICBhZGRPclJlcGxhY2UocGF5bG9hZCwgdGhpcy5pZEtleSwgKGVudGl0eSwgc3RhdGUpID0+XHJcbiAgICAgICAgdGhpcy5pZEdlbmVyYXRvci5nZXRQcmVzZW50SWRPckdlbmVyYXRlKGVudGl0eSwgc3RhdGUpXHJcbiAgICAgIClcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICB1cGRhdGUoeyBzZXRTdGF0ZSB9OiBTdGF0ZUNvbnRleHQ8RW50aXR5U3RhdGVNb2RlbDxUPj4sIHsgcGF5bG9hZCB9OiBFbnRpdHlVcGRhdGVBY3Rpb248VD4pIHtcclxuICAgIGlmIChwYXlsb2FkLnNlbGVjdG9yID09IG51bGwpIHtcclxuICAgICAgdGhyb3cgbmV3IEludmFsaWRFbnRpdHlTZWxlY3RvckVycm9yKHBheWxvYWQpO1xyXG4gICAgfVxyXG4gICAgc2V0U3RhdGUoXHJcbiAgICAgIHVwZGF0ZShwYXlsb2FkLCB0aGlzLmlkS2V5LCAoY3VycmVudCwgdXBkYXRlZCkgPT4gdGhpcy5vblVwZGF0ZShjdXJyZW50LCB1cGRhdGVkKSlcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICB1cGRhdGVBbGwoXHJcbiAgICB7IHNldFN0YXRlIH06IFN0YXRlQ29udGV4dDxFbnRpdHlTdGF0ZU1vZGVsPFQ+PixcclxuICAgIHsgcGF5bG9hZCB9OiBFbnRpdHlVcGRhdGVBY3Rpb248VD5cclxuICApIHtcclxuICAgIHNldFN0YXRlKFxyXG4gICAgICB1cGRhdGUoeyAuLi5wYXlsb2FkLCBzZWxlY3RvcjogbnVsbCB9LCB0aGlzLmlkS2V5LCAoY3VycmVudCwgdXBkYXRlZCkgPT5cclxuICAgICAgICB0aGlzLm9uVXBkYXRlKGN1cnJlbnQsIHVwZGF0ZWQpXHJcbiAgICAgIClcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICB1cGRhdGVBY3RpdmUoXHJcbiAgICB7IHNldFN0YXRlIH06IFN0YXRlQ29udGV4dDxFbnRpdHlTdGF0ZU1vZGVsPFQ+PixcclxuICAgIHsgcGF5bG9hZCB9OiBFbnRpdHlVcGRhdGVBY3RpdmVBY3Rpb248VD5cclxuICApIHtcclxuICAgIHNldFN0YXRlKFxyXG4gICAgICB1cGRhdGVBY3RpdmUocGF5bG9hZCwgdGhpcy5pZEtleSwgKGN1cnJlbnQsIHVwZGF0ZWQpID0+IHRoaXMub25VcGRhdGUoY3VycmVudCwgdXBkYXRlZCkpXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgcmVtb3ZlQWN0aXZlKHsgZ2V0U3RhdGUsIHNldFN0YXRlIH06IFN0YXRlQ29udGV4dDxFbnRpdHlTdGF0ZU1vZGVsPFQ+Pikge1xyXG4gICAgY29uc3QgeyBhY3RpdmUgfSA9IGdldFN0YXRlKCk7XHJcbiAgICBzZXRTdGF0ZShyZW1vdmVFbnRpdGllcyhbYWN0aXZlXSkpO1xyXG4gIH1cclxuXHJcbiAgcmVtb3ZlKFxyXG4gICAgeyBnZXRTdGF0ZSwgc2V0U3RhdGUsIHBhdGNoU3RhdGUgfTogU3RhdGVDb250ZXh0PEVudGl0eVN0YXRlTW9kZWw8VD4+LFxyXG4gICAgeyBwYXlsb2FkIH06IEVudGl0eVJlbW92ZUFjdGlvbjxUPlxyXG4gICkge1xyXG4gICAgaWYgKHBheWxvYWQgPT09IG51bGwpIHtcclxuICAgICAgdGhyb3cgbmV3IEludmFsaWRFbnRpdHlTZWxlY3RvckVycm9yKHBheWxvYWQpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgY29uc3QgZGVsZXRlSWRzOiBzdHJpbmdbXSA9XHJcbiAgICAgICAgdHlwZW9mIHBheWxvYWQgPT09ICdmdW5jdGlvbidcclxuICAgICAgICAgID8gT2JqZWN0LnZhbHVlcyhnZXRTdGF0ZSgpLmVudGl0aWVzKVxyXG4gICAgICAgICAgICAgIC5maWx0ZXIoZW50aXR5ID0+IHBheWxvYWQoZW50aXR5KSlcclxuICAgICAgICAgICAgICAubWFwKGVudGl0eSA9PiB0aGlzLmlkT2YoZW50aXR5KSlcclxuICAgICAgICAgIDogYXNBcnJheShwYXlsb2FkKTtcclxuICAgICAgLy8gY2FuJ3QgcGFzcyBpbiBwcmVkaWNhdGUgYXMgeW91IG5lZWQgSURzIGFuZCB0aHVzIEVudGl0eVN0YXRlI2lkT2ZcclxuICAgICAgc2V0U3RhdGUocmVtb3ZlRW50aXRpZXMoZGVsZXRlSWRzKSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZW1vdmVBbGwoeyBzZXRTdGF0ZSB9OiBTdGF0ZUNvbnRleHQ8RW50aXR5U3RhdGVNb2RlbDxUPj4pIHtcclxuICAgIHNldFN0YXRlKHJlbW92ZUFsbEVudGl0aWVzKCkpO1xyXG4gIH1cclxuXHJcbiAgcmVzZXQoeyBzZXRTdGF0ZSB9OiBTdGF0ZUNvbnRleHQ8RW50aXR5U3RhdGVNb2RlbDxUPj4pIHtcclxuICAgIHNldFN0YXRlKGRlZmF1bHRFbnRpdHlTdGF0ZSgpKTtcclxuICB9XHJcblxyXG4gIHNldExvYWRpbmcoXHJcbiAgICB7IHBhdGNoU3RhdGUgfTogU3RhdGVDb250ZXh0PEVudGl0eVN0YXRlTW9kZWw8VD4+LFxyXG4gICAgeyBwYXlsb2FkIH06IEVudGl0eVNldExvYWRpbmdBY3Rpb25cclxuICApIHtcclxuICAgIHBhdGNoU3RhdGUoeyBsb2FkaW5nOiBwYXlsb2FkIH0pO1xyXG4gIH1cclxuXHJcbiAgc2V0QWN0aXZlKFxyXG4gICAgeyBwYXRjaFN0YXRlIH06IFN0YXRlQ29udGV4dDxFbnRpdHlTdGF0ZU1vZGVsPFQ+PixcclxuICAgIHsgcGF5bG9hZCB9OiBFbnRpdHlTZXRBY3RpdmVBY3Rpb25cclxuICApIHtcclxuICAgIHBhdGNoU3RhdGUoeyBhY3RpdmU6IHBheWxvYWQgfSk7XHJcbiAgfVxyXG5cclxuICBjbGVhckFjdGl2ZSh7IHBhdGNoU3RhdGUgfTogU3RhdGVDb250ZXh0PEVudGl0eVN0YXRlTW9kZWw8VD4+KSB7XHJcbiAgICBwYXRjaFN0YXRlKHsgYWN0aXZlOiB1bmRlZmluZWQgfSk7XHJcbiAgfVxyXG5cclxuICBzZXRFcnJvcihcclxuICAgIHsgcGF0Y2hTdGF0ZSB9OiBTdGF0ZUNvbnRleHQ8RW50aXR5U3RhdGVNb2RlbDxUPj4sXHJcbiAgICB7IHBheWxvYWQgfTogRW50aXR5U2V0RXJyb3JBY3Rpb25cclxuICApIHtcclxuICAgIHBhdGNoU3RhdGUoeyBlcnJvcjogcGF5bG9hZCB9KTtcclxuICB9XHJcblxyXG4gIGdvVG9QYWdlKFxyXG4gICAgeyBnZXRTdGF0ZSwgcGF0Y2hTdGF0ZSB9OiBTdGF0ZUNvbnRleHQ8RW50aXR5U3RhdGVNb2RlbDxUPj4sXHJcbiAgICB7IHBheWxvYWQgfTogRW50aXR5R29Ub1BhZ2VBY3Rpb25cclxuICApIHtcclxuICAgIGlmICgncGFnZScgaW4gcGF5bG9hZCkge1xyXG4gICAgICBwYXRjaFN0YXRlKHsgcGFnZUluZGV4OiBwYXlsb2FkLnBhZ2UgfSk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH0gZWxzZSBpZiAocGF5bG9hZFsnZmlyc3QnXSkge1xyXG4gICAgICBwYXRjaFN0YXRlKHsgcGFnZUluZGV4OiAwIH0pO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgeyBwYWdlU2l6ZSwgcGFnZUluZGV4LCBpZHMgfSA9IGdldFN0YXRlKCk7XHJcbiAgICBjb25zdCB0b3RhbFNpemUgPSBpZHMubGVuZ3RoO1xyXG4gICAgY29uc3QgbWF4SW5kZXggPSBNYXRoLmZsb29yKHRvdGFsU2l6ZSAvIHBhZ2VTaXplKTtcclxuXHJcbiAgICBpZiAoJ2xhc3QnIGluIHBheWxvYWQpIHtcclxuICAgICAgcGF0Y2hTdGF0ZSh7IHBhZ2VJbmRleDogbWF4SW5kZXggfSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjb25zdCBzdGVwID0gcGF5bG9hZFsncHJldiddID8gLTEgOiAxO1xyXG4gICAgICBsZXQgaW5kZXggPSBwYWdlSW5kZXggKyBzdGVwO1xyXG4gICAgICBpbmRleCA9IHdyYXBPckNsYW1wKHBheWxvYWQud3JhcCwgaW5kZXgsIDAsIG1heEluZGV4KTtcclxuICAgICAgcGF0Y2hTdGF0ZSh7IHBhZ2VJbmRleDogaW5kZXggfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBzZXRQYWdlU2l6ZShcclxuICAgIHsgcGF0Y2hTdGF0ZSB9OiBTdGF0ZUNvbnRleHQ8RW50aXR5U3RhdGVNb2RlbDxUPj4sXHJcbiAgICB7IHBheWxvYWQgfTogRW50aXR5U2V0UGFnZVNpemVBY3Rpb25cclxuICApIHtcclxuICAgIHBhdGNoU3RhdGUoeyBwYWdlU2l6ZTogcGF5bG9hZCB9KTtcclxuICB9XHJcblxyXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0gVVRJTElUWSAtLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4gIHByaXZhdGUgc2V0dXAoc3RvcmVDbGFzczogVHlwZTxFbnRpdHlTdGF0ZTxUPj4sIGFjdGlvbnM6IHN0cmluZ1tdKSB7XHJcbiAgICAvLyB2YWxpZGF0aW9uIGlmIGEgbWF0Y2hpbmcgYWN0aW9uIGhhbmRsZXIgZXhpc3RzIGhhcyBtb3ZlZCB0byByZWZsZWN0aW9uLXZhbGlkYXRpb24gdGVzdHNcclxuICAgIGFjdGlvbnMuZm9yRWFjaChmbiA9PiB7XHJcbiAgICAgIGNvbnN0IGFjdGlvbk5hbWUgPSBgWyR7dGhpcy5zdG9yZVBhdGh9XSAke2ZufWA7XHJcbiAgICAgIHN0b3JlQ2xhc3NbTkdYU19NRVRBX0tFWV0uYWN0aW9uc1thY3Rpb25OYW1lXSA9IFtcclxuICAgICAgICB7XHJcbiAgICAgICAgICBmbjogZm4sXHJcbiAgICAgICAgICBvcHRpb25zOiB7fSxcclxuICAgICAgICAgIHR5cGU6IGFjdGlvbk5hbWVcclxuICAgICAgICB9XHJcbiAgICAgIF07XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgdGhlIGlkIG9mIHRoZSBnaXZlbiBlbnRpdHksIGJhc2VkIG9uIHRoZSBkZWZpbmVkIGlkS2V5LlxyXG4gICAqIFRoaXMgbWV0aG9kcyBhbGxvd3MgUGFydGlhbCBlbnRpdGllcyBhbmQgdGh1cyBtaWdodCByZXR1cm4gdW5kZWZpbmVkLlxyXG4gICAqIE90aGVyIG1ldGhvZHMgY2FsbGluZyB0aGlzIG9uZSBoYXZlIHRvIGhhbmRsZSB0aGlzIGNhc2UgdGhlbXNlbHZlcy5cclxuICAgKiBAcGFyYW0gZGF0YSBhIHBhcnRpYWwgZW50aXR5XHJcbiAgICovXHJcbiAgcHJvdGVjdGVkIGlkT2YoZGF0YTogUGFydGlhbDxUPik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XHJcbiAgICByZXR1cm4gZGF0YVt0aGlzLmlkS2V5XTtcclxuICB9XHJcbn1cclxuIl19