@datorama/akita
Version:
State Management Tailored-Made for JS Applications
394 lines • 31.1 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { filter, skip } from 'rxjs/operators';
import { from, isObservable, of } from 'rxjs';
import { isFunction } from './isFunction';
import { AkitaError } from './errors';
import { __stores__ } from './stores';
import { getValue } from './getValueByString';
import { setAction } from './actions';
import { setValue } from './setValueByString';
import { $$addStore, $$deleteStore } from './dispatchers';
import { isNotBrowser } from './root';
import { isNil } from './isNil';
import { isObject } from './isObject';
/** @type {?} */
let skipStorageUpdate = false;
/**
* @param {?} skip
* @return {?}
*/
export function setSkipStorageUpdate(skip) {
skipStorageUpdate = skip;
}
/**
* @return {?}
*/
export function getSkipStorageUpdate() {
return skipStorageUpdate;
}
/**
* @record
*/
export function PersistStateStorage() { }
if (false) {
/**
* @param {?} key
* @return {?}
*/
PersistStateStorage.prototype.getItem = function (key) { };
/**
* @param {?} key
* @param {?} value
* @return {?}
*/
PersistStateStorage.prototype.setItem = function (key, value) { };
/**
* @return {?}
*/
PersistStateStorage.prototype.clear = function () { };
}
/**
* @param {?} v
* @return {?}
*/
function isPromise(v) {
return v && isFunction(v.then);
}
/**
* @param {?} asyncOrValue
* @return {?}
*/
function observify(asyncOrValue) {
if (isPromise(asyncOrValue) || isObservable(asyncOrValue)) {
return from(asyncOrValue);
}
return of(asyncOrValue);
}
/**
* @record
*/
export function PersistStateParams() { }
if (false) {
/**
* The storage key
* @type {?}
*/
PersistStateParams.prototype.key;
/**
* Storage strategy to use. This defaults to LocalStorage but you can pass SessionStorage or anything that implements the StorageEngine API.
* @type {?}
*/
PersistStateParams.prototype.storage;
/**
* Custom deserializer. Defaults to JSON.parse
* @type {?}
*/
PersistStateParams.prototype.deserialize;
/**
* Custom serializer, defaults to JSON.stringify
* @type {?}
*/
PersistStateParams.prototype.serialize;
/**
* By default the whole state is saved to storage, use this param to include only the stores you need.
* Pay attention that you can't use both include and exclude
* @type {?}
*/
PersistStateParams.prototype.include;
/**
* By default the whole state is saved to storage, use this param to exclude stores that you don't need.
* Pay attention that you can't use both include and exclude
* @type {?}
*/
PersistStateParams.prototype.exclude;
/** @type {?} */
PersistStateParams.prototype.skipStorageUpdate;
/** @type {?} */
PersistStateParams.prototype.preStorageUpdateOperator;
/**
* Whether to persist a dynamic store upon destroy
* @type {?}
*/
PersistStateParams.prototype.persistOnDestroy;
/**
* @param {?} storeName
* @param {?} state
* @return {?}
*/
PersistStateParams.prototype.preStorageUpdate = function (storeName, state) { };
/**
* @param {?} storeName
* @param {?} state
* @return {?}
*/
PersistStateParams.prototype.preStoreUpdate = function (storeName, state) { };
}
/**
* @param {?=} params
* @return {?}
*/
export function persistState(params) {
if (isNotBrowser)
return;
/** @type {?} */
const defaults = {
key: 'AkitaStores',
storage: typeof localStorage === 'undefined' ? params.storage : localStorage,
deserialize: JSON.parse,
serialize: JSON.stringify,
include: [],
// @deprecated
exclude: [],
persistOnDestroy: false,
preStorageUpdate: (/**
* @param {?} storeName
* @param {?} state
* @return {?}
*/
function (storeName, state) {
return state;
}),
preStoreUpdate: (/**
* @param {?} storeName
* @param {?} state
* @return {?}
*/
function (storeName, state) {
return state;
}),
skipStorageUpdate: getSkipStorageUpdate,
preStorageUpdateOperator: (/**
* @return {?}
*/
() => (/**
* @param {?} source
* @return {?}
*/
source => source))
};
const { storage, deserialize, serialize, include, exclude, key, preStorageUpdate, persistOnDestroy, preStorageUpdateOperator, preStoreUpdate, skipStorageUpdate } = Object.assign({}, defaults, params);
/** @type {?} */
const hasInclude = include.length > 0;
/** @type {?} */
const hasExclude = exclude.length > 0;
/** @type {?} */
let includeStores;
if (hasInclude && hasExclude) {
throw new AkitaError("You can't use both include and exclude");
}
if (hasInclude) {
includeStores = include.reduce((/**
* @param {?} acc
* @param {?} path
* @return {?}
*/
(acc, path) => {
if (isFunction(path)) {
acc.fns.push(path);
}
else {
/** @type {?} */
const storeName = path.split('.')[0];
acc[storeName] = path;
}
return acc;
}), { fns: [] });
}
/** @type {?} */
let stores = {};
/** @type {?} */
let acc = {};
/** @type {?} */
let subscriptions = [];
/** @type {?} */
const buffer = [];
/**
* @param {?} v
* @return {?}
*/
function _save(v) {
observify(v).subscribe((/**
* @return {?}
*/
() => {
/** @type {?} */
const next = buffer.shift();
next && _save(next);
}));
}
// when we use the local/session storage we perform the serialize, otherwise we let the passed storage implementation to do it
/** @type {?} */
const isLocalStorage = typeof localStorage !== 'undefined' && (storage === localStorage || storage === sessionStorage);
observify(storage.getItem(key)).subscribe((/**
* @param {?} value
* @return {?}
*/
(value) => {
/** @type {?} */
const storageState = isObject(value) ? value : deserialize(value || '{}');
/**
* @param {?} storeCache
* @return {?}
*/
function save(storeCache) {
storageState['$cache'] = Object.assign({}, (storageState['$cache'] || {}), storeCache);
/** @type {?} */
const storageValue = Object.assign({}, storageState, acc);
buffer.push(storage.setItem(key, isLocalStorage ? serialize(storageValue) : storageValue));
_save(buffer.shift());
}
/**
* @param {?} storeName
* @param {?} path
* @return {?}
*/
function subscribe(storeName, path) {
stores[storeName] = __stores__[storeName]
._select((/**
* @param {?} state
* @return {?}
*/
state => getValue(state, path)))
.pipe(skip(1), filter((/**
* @return {?}
*/
() => skipStorageUpdate() === false)), preStorageUpdateOperator())
.subscribe((/**
* @param {?} data
* @return {?}
*/
data => {
acc[storeName] = preStorageUpdate(storeName, data);
Promise.resolve().then((/**
* @return {?}
*/
() => save({ [storeName]: __stores__[storeName]._cache().getValue() })));
}));
}
/**
* @param {?} storeName
* @param {?} store
* @param {?} path
* @return {?}
*/
function setInitial(storeName, store, path) {
if (storeName in storageState) {
setAction('@PersistState');
store._setState((/**
* @param {?} state
* @return {?}
*/
state => {
return setValue(state, path, preStoreUpdate(storeName, storageState[storeName]));
}));
/** @type {?} */
const hasCache = storageState['$cache'] ? storageState['$cache'][storeName] : false;
__stores__[storeName].setHasCache(hasCache);
}
}
subscriptions.push($$deleteStore.subscribe((/**
* @param {?} storeName
* @return {?}
*/
storeName => {
if (stores[storeName]) {
if (persistOnDestroy === false) {
save(false);
}
stores[storeName].unsubscribe();
delete stores[storeName];
}
})));
subscriptions.push($$addStore.subscribe((/**
* @param {?} storeName
* @return {?}
*/
storeName => {
if (hasExclude && exclude.includes(storeName)) {
return;
}
/** @type {?} */
const store = __stores__[storeName];
if (hasInclude) {
/** @type {?} */
let path = includeStores[storeName];
if (!path) {
/** @type {?} */
const passPredicate = includeStores.fns.some((/**
* @param {?} fn
* @return {?}
*/
fn => fn(storeName)));
if (passPredicate) {
path = storeName;
}
else {
return;
}
}
setInitial(storeName, store, path);
subscribe(storeName, path);
}
else {
setInitial(storeName, store, storeName);
subscribe(storeName, storeName);
}
})));
}));
return {
/**
* @return {?}
*/
destroy() {
subscriptions.forEach((/**
* @param {?} s
* @return {?}
*/
s => s.unsubscribe()));
for (let i = 0, keys = Object.keys(stores); i < keys.length; i++) {
/** @type {?} */
const storeName = keys[i];
stores[storeName].unsubscribe();
}
stores = {};
},
/**
* @return {?}
*/
clear() {
storage.clear();
},
/**
* @param {?=} storeName
* @return {?}
*/
clearStore(storeName) {
if (isNil(storeName)) {
/** @type {?} */
const value = observify(storage.setItem(key, '{}'));
value.subscribe();
return;
}
/** @type {?} */
const value = storage.getItem(key);
observify(value).subscribe((/**
* @param {?} v
* @return {?}
*/
v => {
/** @type {?} */
const storageState = deserialize(v || '{}');
if (storageState[storeName]) {
delete storageState[storeName];
/** @type {?} */
const value = observify(storage.setItem(key, serialize(storageState)));
value.subscribe();
}
}));
}
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVyc2lzdFN0YXRlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQGRhdG9yYW1hL2FraXRhLyIsInNvdXJjZXMiOlsic3JjL3BlcnNpc3RTdGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxFQUFFLEVBQWtDLE1BQU0sTUFBTSxDQUFDO0FBRTlFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDMUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUN0QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsVUFBVSxFQUFFLGFBQWEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMxRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDaEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFlBQVksQ0FBQzs7SUFFbEMsaUJBQWlCLEdBQUcsS0FBSzs7Ozs7QUFFN0IsTUFBTSxVQUFVLG9CQUFvQixDQUFDLElBQWE7SUFDaEQsaUJBQWlCLEdBQUcsSUFBSSxDQUFDO0FBQzNCLENBQUM7Ozs7QUFFRCxNQUFNLFVBQVUsb0JBQW9CO0lBQ2xDLE9BQU8saUJBQWlCLENBQUM7QUFDM0IsQ0FBQzs7OztBQUVELHlDQU1DOzs7Ozs7SUFMQywyREFBaUM7Ozs7OztJQUVqQyxrRUFBNkM7Ozs7SUFFN0Msc0RBQWM7Ozs7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U0FBUzs7OztZQUFDLENBQUMsQ0FBQyxFQUFFOztzQkFDdkIsWUFBWSxHQUFHLFdBQVcsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDO2dCQUUzQyxJQUFJLFlBQVksQ0FBQyxTQUFTLENBQUMsRUFBRTtvQkFDM0IsT0FBTyxZQUFZLENBQUMsU0FBUyxDQUFDLENBQUM7OzBCQUN6QixLQUFLLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO29CQUN0RSxLQUFLLENBQUMsU0FBUyxFQUFFLENBQUM7aUJBQ25CO1lBQ0gsQ0FBQyxFQUFDLENBQUM7UUFDTCxDQUFDO0tBQ0YsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmaWx0ZXIsIHNraXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBmcm9tLCBpc09ic2VydmFibGUsIG9mLCBPcGVyYXRvckZ1bmN0aW9uLCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEhhc2hNYXAsIE1heWJlQXN5bmMgfSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7IGlzRnVuY3Rpb24gfSBmcm9tICcuL2lzRnVuY3Rpb24nO1xuaW1wb3J0IHsgQWtpdGFFcnJvciB9IGZyb20gJy4vZXJyb3JzJztcbmltcG9ydCB7IF9fc3RvcmVzX18gfSBmcm9tICcuL3N0b3Jlcyc7XG5pbXBvcnQgeyBnZXRWYWx1ZSB9IGZyb20gJy4vZ2V0VmFsdWVCeVN0cmluZyc7XG5pbXBvcnQgeyBzZXRBY3Rpb24gfSBmcm9tICcuL2FjdGlvbnMnO1xuaW1wb3J0IHsgc2V0VmFsdWUgfSBmcm9tICcuL3NldFZhbHVlQnlTdHJpbmcnO1xuaW1wb3J0IHsgJCRhZGRTdG9yZSwgJCRkZWxldGVTdG9yZSB9IGZyb20gJy4vZGlzcGF0Y2hlcnMnO1xuaW1wb3J0IHsgaXNOb3RCcm93c2VyIH0gZnJvbSAnLi9yb290JztcbmltcG9ydCB7IGlzTmlsIH0gZnJvbSAnLi9pc05pbCc7XG5pbXBvcnQgeyBpc09iamVjdCB9IGZyb20gJy4vaXNPYmplY3QnO1xuXG5sZXQgc2tpcFN0b3JhZ2VVcGRhdGUgPSBmYWxzZTtcblxuZXhwb3J0IGZ1bmN0aW9uIHNldFNraXBTdG9yYWdlVXBkYXRlKHNraXA6IGJvb2xlYW4pIHtcbiAgc2tpcFN0b3JhZ2VVcGRhdGUgPSBza2lwO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2tpcFN0b3JhZ2VVcGRhdGUoKSB7XG4gIHJldHVybiBza2lwU3RvcmFnZVVwZGF0ZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQZXJzaXN0U3RhdGVTdG9yYWdlIHtcbiAgZ2V0SXRlbShrZXk6IHN0cmluZyk6IE1heWJlQXN5bmM7XG5cbiAgc2V0SXRlbShrZXk6IHN0cmluZywgdmFsdWU6IGFueSk6IE1heWJlQXN5bmM7XG5cbiAgY2xlYXIoKTogdm9pZDtcbn1cblxuZnVuY3Rpb24gaXNQcm9taXNlKHY6IGFueSkge1xuICByZXR1cm4gdiAmJiBpc0Z1bmN0aW9uKHYudGhlbik7XG59XG5cbmZ1bmN0aW9uIG9ic2VydmlmeShhc3luY09yVmFsdWU6IGFueSkge1xuICBpZiAoaXNQcm9taXNlKGFzeW5jT3JWYWx1ZSkgfHwgaXNPYnNlcnZhYmxlKGFzeW5jT3JWYWx1ZSkpIHtcbiAgICByZXR1cm4gZnJvbShhc3luY09yVmFsdWUpO1xuICB9XG5cbiAgcmV0dXJuIG9mKGFzeW5jT3JWYWx1ZSk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGVyc2lzdFN0YXRlUGFyYW1zIHtcbiAgLyoqIFRoZSBzdG9yYWdlIGtleSAqL1xuICBrZXk6IHN0cmluZztcbiAgLyoqIFN0b3JhZ2Ugc3RyYXRlZ3kgdG8gdXNlLiBUaGlzIGRlZmF1bHRzIHRvIExvY2FsU3RvcmFnZSBidXQgeW91IGNhbiBwYXNzIFNlc3Npb25TdG9yYWdlIG9yIGFueXRoaW5nIHRoYXQgaW1wbGVtZW50cyB0aGUgU3RvcmFnZUVuZ2luZSBBUEkuICovXG4gIHN0b3JhZ2U6IFBlcnNpc3RTdGF0ZVN0b3JhZ2U7XG4gIC8qKiBDdXN0b20gZGVzZXJpYWxpemVyLiBEZWZhdWx0cyB0byBKU09OLnBhcnNlICovXG4gIGRlc2VyaWFsaXplOiBGdW5jdGlvbjtcbiAgLyoqIEN1c3RvbSBzZXJpYWxpemVyLCBkZWZhdWx0cyB0byBKU09OLnN0cmluZ2lmeSAqL1xuICBzZXJpYWxpemU6IEZ1bmN0aW9uO1xuICAvKipcbiAgICogQnkgZGVmYXVsdCB0aGUgd2hvbGUgc3RhdGUgaXMgc2F2ZWQgdG8gc3RvcmFnZSwgdXNlIHRoaXMgcGFyYW0gdG8gaW5jbHVkZSBvbmx5IHRoZSBzdG9yZXMgeW91IG5lZWQuXG4gICAqIFBheSBhdHRlbnRpb24gdGhhdCB5b3UgY2FuJ3QgdXNlIGJvdGggaW5jbHVkZSBhbmQgZXhjbHVkZVxuICAgKi9cbiAgaW5jbHVkZTogKHN0cmluZyB8ICgoc3RvcmVOYW1lOiBzdHJpbmcpID0+IGJvb2xlYW4pKVtdO1xuICAvKipcbiAgICogIEJ5IGRlZmF1bHQgdGhlIHdob2xlIHN0YXRlIGlzIHNhdmVkIHRvIHN0b3JhZ2UsIHVzZSB0aGlzIHBhcmFtIHRvIGV4Y2x1ZGUgc3RvcmVzIHRoYXQgeW91IGRvbid0IG5lZWQuXG4gICAqICBQYXkgYXR0ZW50aW9uIHRoYXQgeW91IGNhbid0IHVzZSBib3RoIGluY2x1ZGUgYW5kIGV4Y2x1ZGVcbiAgICovXG4gIGV4Y2x1ZGU6IHN0cmluZ1tdO1xuXG4gIHByZVN0b3JhZ2VVcGRhdGUoc3RvcmVOYW1lOiBzdHJpbmcsIHN0YXRlOiBhbnkpOiBhbnk7XG5cbiAgcHJlU3RvcmVVcGRhdGUoc3RvcmVOYW1lOiBzdHJpbmcsIHN0YXRlOiBhbnkpOiBhbnk7XG5cbiAgc2tpcFN0b3JhZ2VVcGRhdGU6ICgpID0+IGJvb2xlYW47XG4gIHByZVN0b3JhZ2VVcGRhdGVPcGVyYXRvcjogKCkgPT4gT3BlcmF0b3JGdW5jdGlvbjxhbnksIGFueT47XG4gIC8qKiBXaGV0aGVyIHRvIHBlcnNpc3QgYSBkeW5hbWljIHN0b3JlIHVwb24gZGVzdHJveSAqL1xuICBwZXJzaXN0T25EZXN0cm95OiBib29sZWFuO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGVyc2lzdFN0YXRlKHBhcmFtcz86IFBhcnRpYWw8UGVyc2lzdFN0YXRlUGFyYW1zPikge1xuICBpZiAoaXNOb3RCcm93c2VyKSByZXR1cm47XG5cbiAgY29uc3QgZGVmYXVsdHM6IFBlcnNpc3RTdGF0ZVBhcmFtcyA9IHtcbiAgICBrZXk6ICdBa2l0YVN0b3JlcycsXG4gICAgc3RvcmFnZTogdHlwZW9mIGxvY2FsU3RvcmFnZSA9PT0gJ3VuZGVmaW5lZCcgPyBwYXJhbXMuc3RvcmFnZSA6IGxvY2FsU3RvcmFnZSxcbiAgICBkZXNlcmlhbGl6ZTogSlNPTi5wYXJzZSxcbiAgICBzZXJpYWxpemU6IEpTT04uc3RyaW5naWZ5LFxuICAgIGluY2x1ZGU6IFtdLFxuICAgIC8vIEBkZXByZWNhdGVkXG4gICAgZXhjbHVkZTogW10sXG4gICAgcGVyc2lzdE9uRGVzdHJveTogZmFsc2UsXG4gICAgcHJlU3RvcmFnZVVwZGF0ZTogZnVuY3Rpb24oc3RvcmVOYW1lLCBzdGF0ZSkge1xuICAgICAgcmV0dXJuIHN0YXRlO1xuICAgIH0sXG4gICAgcHJlU3RvcmVVcGRhdGU6IGZ1bmN0aW9uKHN0b3JlTmFtZSwgc3RhdGUpIHtcbiAgICAgIHJldHVybiBzdGF0ZTtcbiAgICB9LFxuICAgIHNraXBTdG9yYWdlVXBkYXRlOiBnZXRTa2lwU3RvcmFnZVVwZGF0ZSxcbiAgICBwcmVTdG9yYWdlVXBkYXRlT3BlcmF0b3I6ICgpID0+IHNvdXJjZSA9PiBzb3VyY2VcbiAgfTtcblxuICBjb25zdCB7IHN0b3JhZ2UsIGRlc2VyaWFsaXplLCBzZXJpYWxpemUsIGluY2x1ZGUsIGV4Y2x1ZGUsIGtleSwgcHJlU3RvcmFnZVVwZGF0ZSwgcGVyc2lzdE9uRGVzdHJveSwgcHJlU3RvcmFnZVVwZGF0ZU9wZXJhdG9yLCBwcmVTdG9yZVVwZGF0ZSwgc2tpcFN0b3JhZ2VVcGRhdGUgfSA9IE9iamVjdC5hc3NpZ24oXG4gICAge30sXG4gICAgZGVmYXVsdHMsXG4gICAgcGFyYW1zXG4gICk7XG5cbiAgY29uc3QgaGFzSW5jbHVkZSA9IGluY2x1ZGUubGVuZ3RoID4gMDtcbiAgY29uc3QgaGFzRXhjbHVkZSA9IGV4Y2x1ZGUubGVuZ3RoID4gMDtcbiAgbGV0IGluY2x1ZGVTdG9yZXM6IHsgZm5zOiBGdW5jdGlvbltdOyBba2V5OiBzdHJpbmddOiBGdW5jdGlvbltdIHwgc3RyaW5nIH07XG5cbiAgaWYgKGhhc0luY2x1ZGUgJiYgaGFzRXhjbHVkZSkge1xuICAgIHRocm93IG5ldyBBa2l0YUVycm9yKFwiWW91IGNhbid0IHVzZSBib3RoIGluY2x1ZGUgYW5kIGV4Y2x1ZGVcIik7XG4gIH1cblxuICBpZiAoaGFzSW5jbHVkZSkge1xuICAgIGluY2x1ZGVTdG9yZXMgPSBpbmNsdWRlLnJlZHVjZShcbiAgICAgIChhY2MsIHBhdGgpID0+IHtcbiAgICAgICAgaWYgKGlzRnVuY3Rpb24ocGF0aCkpIHtcbiAgICAgICAgICBhY2MuZm5zLnB1c2gocGF0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3Qgc3RvcmVOYW1lID0gcGF0aC5zcGxpdCgnLicpWzBdO1xuICAgICAgICAgIGFjY1tzdG9yZU5hbWVdID0gcGF0aDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgfSxcbiAgICAgIHsgZm5zOiBbXSB9XG4gICAgKTtcbiAgfVxuXG4gIGxldCBzdG9yZXM6IEhhc2hNYXA8U3Vic2NyaXB0aW9uPiA9IHt9O1xuICBsZXQgYWNjID0ge307XG4gIGxldCBzdWJzY3JpcHRpb25zOiBTdWJzY3JpcHRpb25bXSA9IFtdO1xuXG4gIGNvbnN0IGJ1ZmZlciA9IFtdO1xuXG4gIGZ1bmN0aW9uIF9zYXZlKHY6IGFueSkge1xuICAgIG9ic2VydmlmeSh2KS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgY29uc3QgbmV4dCA9IGJ1ZmZlci5zaGlmdCgpO1xuICAgICAgbmV4dCAmJiBfc2F2ZShuZXh0KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIHdoZW4gd2UgdXNlIHRoZSBsb2NhbC9zZXNzaW9uIHN0b3JhZ2Ugd2UgcGVyZm9ybSB0aGUgc2VyaWFsaXplLCBvdGhlcndpc2Ugd2UgbGV0IHRoZSBwYXNzZWQgc3RvcmFnZSBpbXBsZW1lbnRhdGlvbiB0byBkbyBpdFxuICBjb25zdCBpc0xvY2FsU3RvcmFnZSA9IHR5cGVvZiBsb2NhbFN0b3JhZ2UgIT09ICd1bmRlZmluZWQnICYmIChzdG9yYWdlID09PSBsb2NhbFN0b3JhZ2UgfHwgc3RvcmFnZSA9PT0gc2Vzc2lvblN0b3JhZ2UpO1xuXG4gIG9ic2VydmlmeShzdG9yYWdlLmdldEl0ZW0oa2V5KSkuc3Vic2NyaWJlKCh2YWx1ZTogYW55KSA9PiB7XG4gICAgY29uc3Qgc3RvcmFnZVN0YXRlID0gaXNPYmplY3QodmFsdWUpID8gdmFsdWUgOiBkZXNlcmlhbGl6ZSh2YWx1ZSB8fCAne30nKTtcblxuICAgIGZ1bmN0aW9uIHNhdmUoc3RvcmVDYWNoZSkge1xuICAgICAgc3RvcmFnZVN0YXRlWyckY2FjaGUnXSA9IHsgLi4uKHN0b3JhZ2VTdGF0ZVsnJGNhY2hlJ10gfHwge30pLCAuLi5zdG9yZUNhY2hlIH07XG4gICAgICBjb25zdCBzdG9yYWdlVmFsdWUgPSBPYmplY3QuYXNzaWduKHt9LCBzdG9yYWdlU3RhdGUsIGFjYyk7XG5cbiAgICAgIGJ1ZmZlci5wdXNoKHN0b3JhZ2Uuc2V0SXRlbShrZXksIGlzTG9jYWxTdG9yYWdlID8gc2VyaWFsaXplKHN0b3JhZ2VWYWx1ZSkgOiBzdG9yYWdlVmFsdWUpKTtcbiAgICAgIF9zYXZlKGJ1ZmZlci5zaGlmdCgpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzdWJzY3JpYmUoc3RvcmVOYW1lLCBwYXRoKSB7XG4gICAgICBzdG9yZXNbc3RvcmVOYW1lXSA9IF9fc3RvcmVzX19bc3RvcmVOYW1lXVxuICAgICAgICAuX3NlbGVjdChzdGF0ZSA9PiBnZXRWYWx1ZShzdGF0ZSwgcGF0aCkpXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgIHNraXAoMSksXG4gICAgICAgICAgZmlsdGVyKCgpID0+IHNraXBTdG9yYWdlVXBkYXRlKCkgPT09IGZhbHNlKSxcbiAgICAgICAgICBwcmVTdG9yYWdlVXBkYXRlT3BlcmF0b3IoKVxuICAgICAgICApXG4gICAgICAgIC5zdWJzY3JpYmUoZGF0YSA9PiB7XG4gICAgICAgICAgYWNjW3N0b3JlTmFtZV0gPSBwcmVTdG9yYWdlVXBkYXRlKHN0b3JlTmFtZSwgZGF0YSk7XG4gICAgICAgICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBzYXZlKHsgW3N0b3JlTmFtZV06IF9fc3RvcmVzX19bc3RvcmVOYW1lXS5fY2FjaGUoKS5nZXRWYWx1ZSgpIH0pKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2V0SW5pdGlhbChzdG9yZU5hbWUsIHN0b3JlLCBwYXRoKSB7XG4gICAgICBpZiAoc3RvcmVOYW1lIGluIHN0b3JhZ2VTdGF0ZSkge1xuICAgICAgICBzZXRBY3Rpb24oJ0BQZXJzaXN0U3RhdGUnKTtcbiAgICAgICAgc3RvcmUuX3NldFN0YXRlKHN0YXRlID0+IHtcbiAgICAgICAgICByZXR1cm4gc2V0VmFsdWUoc3RhdGUsIHBhdGgsIHByZVN0b3JlVXBkYXRlKHN0b3JlTmFtZSwgc3RvcmFnZVN0YXRlW3N0b3JlTmFtZV0pKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGhhc0NhY2hlID0gc3RvcmFnZVN0YXRlWyckY2FjaGUnXSA/IHN0b3JhZ2VTdGF0ZVsnJGNhY2hlJ11bc3RvcmVOYW1lXSA6IGZhbHNlO1xuICAgICAgICBfX3N0b3Jlc19fW3N0b3JlTmFtZV0uc2V0SGFzQ2FjaGUoaGFzQ2FjaGUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgICQkZGVsZXRlU3RvcmUuc3Vic2NyaWJlKHN0b3JlTmFtZSA9PiB7XG4gICAgICAgIGlmIChzdG9yZXNbc3RvcmVOYW1lXSkge1xuICAgICAgICAgIGlmIChwZXJzaXN0T25EZXN0cm95ID09PSBmYWxzZSkge1xuICAgICAgICAgICAgc2F2ZShmYWxzZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHN0b3Jlc1tzdG9yZU5hbWVdLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgICAgZGVsZXRlIHN0b3Jlc1tzdG9yZU5hbWVdO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG5cbiAgICBzdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICAkJGFkZFN0b3JlLnN1YnNjcmliZShzdG9yZU5hbWUgPT4ge1xuICAgICAgICBpZiAoaGFzRXhjbHVkZSAmJiBleGNsdWRlLmluY2x1ZGVzKHN0b3JlTmFtZSkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzdG9yZSA9IF9fc3RvcmVzX19bc3RvcmVOYW1lXTtcbiAgICAgICAgaWYgKGhhc0luY2x1ZGUpIHtcbiAgICAgICAgICBsZXQgcGF0aCA9IGluY2x1ZGVTdG9yZXNbc3RvcmVOYW1lXTtcblxuICAgICAgICAgIGlmICghcGF0aCkge1xuICAgICAgICAgICAgY29uc3QgcGFzc1ByZWRpY2F0ZSA9IGluY2x1ZGVTdG9yZXMuZm5zLnNvbWUoZm4gPT4gZm4oc3RvcmVOYW1lKSk7XG4gICAgICAgICAgICBpZiAocGFzc1ByZWRpY2F0ZSkge1xuICAgICAgICAgICAgICBwYXRoID0gc3RvcmVOYW1lO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBzZXRJbml0aWFsKHN0b3JlTmFtZSwgc3RvcmUsIHBhdGgpO1xuICAgICAgICAgIHN1YnNjcmliZShzdG9yZU5hbWUsIHBhdGgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNldEluaXRpYWwoc3RvcmVOYW1lLCBzdG9yZSwgc3RvcmVOYW1lKTtcbiAgICAgICAgICBzdWJzY3JpYmUoc3RvcmVOYW1lLCBzdG9yZU5hbWUpO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgZGVzdHJveSgpIHtcbiAgICAgIHN1YnNjcmlwdGlvbnMuZm9yRWFjaChzID0+IHMudW5zdWJzY3JpYmUoKSk7XG4gICAgICBmb3IgKGxldCBpID0gMCwga2V5cyA9IE9iamVjdC5rZXlzKHN0b3Jlcyk7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHN0b3JlTmFtZSA9IGtleXNbaV07XG4gICAgICAgIHN0b3Jlc1tzdG9yZU5hbWVdLnVuc3Vic2NyaWJlKCk7XG4gICAgICB9XG4gICAgICBzdG9yZXMgPSB7fTtcbiAgICB9LFxuICAgIGNsZWFyKCkge1xuICAgICAgc3RvcmFnZS5jbGVhcigpO1xuICAgIH0sXG4gICAgY2xlYXJTdG9yZShzdG9yZU5hbWU/OiBzdHJpbmcpIHtcbiAgICAgIGlmIChpc05pbChzdG9yZU5hbWUpKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gb2JzZXJ2aWZ5KHN0b3JhZ2Uuc2V0SXRlbShrZXksICd7fScpKTtcbiAgICAgICAgdmFsdWUuc3Vic2NyaWJlKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHZhbHVlID0gc3RvcmFnZS5nZXRJdGVtKGtleSk7XG4gICAgICBvYnNlcnZpZnkodmFsdWUpLnN1YnNjcmliZSh2ID0+IHtcbiAgICAgICAgY29uc3Qgc3RvcmFnZVN0YXRlID0gZGVzZXJpYWxpemUodiB8fCAne30nKTtcblxuICAgICAgICBpZiAoc3RvcmFnZVN0YXRlW3N0b3JlTmFtZV0pIHtcbiAgICAgICAgICBkZWxldGUgc3RvcmFnZVN0YXRlW3N0b3JlTmFtZV07XG4gICAgICAgICAgY29uc3QgdmFsdWUgPSBvYnNlcnZpZnkoc3RvcmFnZS5zZXRJdGVtKGtleSwgc2VyaWFsaXplKHN0b3JhZ2VTdGF0ZSkpKTtcbiAgICAgICAgICB2YWx1ZS5zdWJzY3JpYmUoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9O1xufVxuIl19