@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
JavaScript
/**
* @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