UNPKG

ngx-webstorage-service

Version:
122 lines 14.7 kB
import { BaseStorageService } from './base-storage.service'; import { StorageTranscoders } from './storage-transcoders'; /** * An implementation of `StorageService` interface that uses an underlying (web) `Storage` object, such as `localStorage` and * `sessionStorage`, as backing data store. This class basically wraps the `Storage` object so it can be accessed through the * `StorageService` interface. */ export class WebStorageService extends BaseStorageService { /** * Creates a new `WebStorageService` instance that uses the specified (web) storage object as underlying backing storage. * * @param storage Storage object which is to be wrapped in a class that implements the `StorageService` interface. */ constructor(storage) { super(StorageTranscoders.JSON); this.storage = storage; } /** * Checks whether an entry with the specified key exists in the storage. * * @param key Identifier of the entry for which its presence in the storage is to be checked. * @returns `true` if an entry with the specified key exists in the storage, `false` if not. */ has(key) { return this.storage.getItem(key) !== null; } /** * Removes the entry that is identified by the specified key. Attempting to remove an entry for an unknown key will have no effect. * Attempting to retrieve an entry via the `get` method after it has been removed will result in `undefined`. * * @param key Identifier of the entry which is to be removed. */ remove(key) { this.storage.removeItem(key); } /** * Clears the storage by removing all entries. Subsequent `get(x)` calls for a key *x* will return `undefined`, until a new value is set * for key *x*. */ clear() { this.storage.clear(); } /** * Performs the actual retrieval of a value from storage. * * @param key Identifier of the entry whose value is to be retrieved. * @returns The value that is stored for the specified entry or `undefined` if no entry exists for the specified key. */ getItem(key) { const value = this.storage.getItem(key); return value !== null ? value : undefined; } /** * Stores the provided value using specified key in the storage. * * @param key Identifier of the entry for which the value is to be stored. * @param value The value that is to be stored. */ setItem(key, value) { return this.storage.setItem(key, value); } } /** * Checks whether the specified (web) storage is available and functional. This might not be the case for older browsers. However even * certain browsers that do support the web storage API can, under some circumstances, have non functional storage objects. For example, * Safari is known to have `localStorage` and `sessionStorage` throw exceptions in private mode. * * @param storage Storage object which is to be tested for availability. * @returns `true` if the specified storage can be used, `false` if not. */ export function isStorageAvailable(storage) { // Check if storage is available. if (!storage) { return false; } // Check if the storage can actually be accessed. try { const now = Date.now(); const testItemKey = `storage-test-entry-${now}`; const testItemValue = `storage-test-value-${now}`; storage.setItem(testItemKey, testItemValue); const retrievedItemValue = storage.getItem(testItemKey); storage.removeItem(testItemKey); return retrievedItemValue === testItemValue; } catch (error) { return false; } } /** * Checks whether session storage is available and functional. This might not be the case for older browsers. However even certain browsers * that do support the web storage API can, under some circumstances, have non functional storage objects. For example, Safari is known to * have `sessionStorage` throw exceptions in private mode. * * @returns `true` if session storage can be used, `false` if not. */ export function isSessionStorageAvailable() { try { if (typeof sessionStorage !== 'undefined') { return isStorageAvailable(sessionStorage); } } catch { } return false; } /** * Checks whether local storage is available and functional. This might not be the case for older browsers. However even certain browsers * that do support the web storage API can, under some circumstances, have non functional storage objects. For example, Safari is known to * have `localStorage` throw exceptions in private mode. * * @returns `true` if local storage can be used, `false` if not. */ export function isLocalStorageAvailable() { try { if (typeof localStorage !== 'undefined') { return isStorageAvailable(localStorage); } } catch { } return false; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViLXN0b3JhZ2Uuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9zcmMvd2ViLXN0b3JhZ2Uuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM1RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUUzRDs7OztHQUlHO0FBQ0gsTUFBTSxPQUFPLGlCQUFrQixTQUFRLGtCQUF1QjtJQUUxRDs7OztPQUlHO0lBQ0gsWUFBNkIsT0FBZ0I7UUFDekMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBRE4sWUFBTyxHQUFQLE9BQU8sQ0FBUztJQUU3QyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxHQUFHLENBQUMsR0FBVztRQUNsQixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLElBQUksQ0FBQztJQUM5QyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxNQUFNLENBQUMsR0FBVztRQUNyQixJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksS0FBSztRQUNSLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDekIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ08sT0FBTyxDQUFDLEdBQVc7UUFDekIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFeEMsT0FBTyxLQUFLLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUM5QyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDTyxPQUFPLENBQUMsR0FBVyxFQUFFLEtBQWE7UUFDeEMsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDNUMsQ0FBQztDQUVKO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sVUFBVSxrQkFBa0IsQ0FBQyxPQUFnQjtJQUMvQyxpQ0FBaUM7SUFDakMsSUFBSSxDQUFDLE9BQU8sRUFBRTtRQUNWLE9BQU8sS0FBSyxDQUFDO0tBQ2hCO0lBRUQsaURBQWlEO0lBQ2pELElBQUk7UUFDQSxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDdkIsTUFBTSxXQUFXLEdBQUcsc0JBQXNCLEdBQUcsRUFBRSxDQUFDO1FBQ2hELE1BQU0sYUFBYSxHQUFHLHNCQUFzQixHQUFHLEVBQUUsQ0FBQztRQUNsRCxPQUFPLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxhQUFhLENBQUMsQ0FBQztRQUM1QyxNQUFNLGtCQUFrQixHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDeEQsT0FBTyxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUVoQyxPQUFPLGtCQUFrQixLQUFLLGFBQWEsQ0FBQztLQUMvQztJQUFDLE9BQU8sS0FBSyxFQUFFO1FBQ1osT0FBTyxLQUFLLENBQUM7S0FDaEI7QUFDTCxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLHlCQUF5QjtJQUNyQyxJQUFJO1FBQ0EsSUFBSSxPQUFPLGNBQXFCLEtBQUssV0FBVyxFQUFFO1lBQzlDLE9BQU8sa0JBQWtCLENBQUMsY0FBYyxDQUFDLENBQUM7U0FDN0M7S0FDSjtJQUFDLE1BQU0sR0FBRTtJQUVWLE9BQU8sS0FBSyxDQUFDO0FBQ2pCLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsdUJBQXVCO0lBQ25DLElBQUk7UUFDQSxJQUFJLE9BQU8sWUFBbUIsS0FBSyxXQUFXLEVBQUU7WUFDNUMsT0FBTyxrQkFBa0IsQ0FBQyxZQUFZLENBQUMsQ0FBQztTQUMzQztLQUNKO0lBQUMsTUFBTSxHQUFFO0lBRVYsT0FBTyxLQUFLLENBQUM7QUFDakIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJhc2VTdG9yYWdlU2VydmljZSB9IGZyb20gJy4vYmFzZS1zdG9yYWdlLnNlcnZpY2UnO1xuaW1wb3J0IHsgU3RvcmFnZVRyYW5zY29kZXJzIH0gZnJvbSAnLi9zdG9yYWdlLXRyYW5zY29kZXJzJztcblxuLyoqXG4gKiBBbiBpbXBsZW1lbnRhdGlvbiBvZiBgU3RvcmFnZVNlcnZpY2VgIGludGVyZmFjZSB0aGF0IHVzZXMgYW4gdW5kZXJseWluZyAod2ViKSBgU3RvcmFnZWAgb2JqZWN0LCBzdWNoIGFzIGBsb2NhbFN0b3JhZ2VgIGFuZFxuICogYHNlc3Npb25TdG9yYWdlYCwgYXMgYmFja2luZyBkYXRhIHN0b3JlLiBUaGlzIGNsYXNzIGJhc2ljYWxseSB3cmFwcyB0aGUgYFN0b3JhZ2VgIG9iamVjdCBzbyBpdCBjYW4gYmUgYWNjZXNzZWQgdGhyb3VnaCB0aGVcbiAqIGBTdG9yYWdlU2VydmljZWAgaW50ZXJmYWNlLlxuICovXG5leHBvcnQgY2xhc3MgV2ViU3RvcmFnZVNlcnZpY2UgZXh0ZW5kcyBCYXNlU3RvcmFnZVNlcnZpY2U8YW55PiB7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IGBXZWJTdG9yYWdlU2VydmljZWAgaW5zdGFuY2UgdGhhdCB1c2VzIHRoZSBzcGVjaWZpZWQgKHdlYikgc3RvcmFnZSBvYmplY3QgYXMgdW5kZXJseWluZyBiYWNraW5nIHN0b3JhZ2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gc3RvcmFnZSBTdG9yYWdlIG9iamVjdCB3aGljaCBpcyB0byBiZSB3cmFwcGVkIGluIGEgY2xhc3MgdGhhdCBpbXBsZW1lbnRzIHRoZSBgU3RvcmFnZVNlcnZpY2VgIGludGVyZmFjZS5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHN0b3JhZ2U6IFN0b3JhZ2UpIHtcbiAgICAgICAgc3VwZXIoU3RvcmFnZVRyYW5zY29kZXJzLkpTT04pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyB3aGV0aGVyIGFuIGVudHJ5IHdpdGggdGhlIHNwZWNpZmllZCBrZXkgZXhpc3RzIGluIHRoZSBzdG9yYWdlLlxuICAgICAqXG4gICAgICogQHBhcmFtICAga2V5IElkZW50aWZpZXIgb2YgdGhlIGVudHJ5IGZvciB3aGljaCBpdHMgcHJlc2VuY2UgaW4gdGhlIHN0b3JhZ2UgaXMgdG8gYmUgY2hlY2tlZC5cbiAgICAgKiBAcmV0dXJucyAgICAgYHRydWVgIGlmIGFuIGVudHJ5IHdpdGggdGhlIHNwZWNpZmllZCBrZXkgZXhpc3RzIGluIHRoZSBzdG9yYWdlLCBgZmFsc2VgIGlmIG5vdC5cbiAgICAgKi9cbiAgICBwdWJsaWMgaGFzKGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0b3JhZ2UuZ2V0SXRlbShrZXkpICE9PSBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIGVudHJ5IHRoYXQgaXMgaWRlbnRpZmllZCBieSB0aGUgc3BlY2lmaWVkIGtleS4gQXR0ZW1wdGluZyB0byByZW1vdmUgYW4gZW50cnkgZm9yIGFuIHVua25vd24ga2V5IHdpbGwgaGF2ZSBubyBlZmZlY3QuXG4gICAgICogQXR0ZW1wdGluZyB0byByZXRyaWV2ZSBhbiBlbnRyeSB2aWEgdGhlIGBnZXRgIG1ldGhvZCBhZnRlciBpdCBoYXMgYmVlbiByZW1vdmVkIHdpbGwgcmVzdWx0IGluIGB1bmRlZmluZWRgLlxuICAgICAqXG4gICAgICogQHBhcmFtIGtleSBJZGVudGlmaWVyIG9mIHRoZSBlbnRyeSB3aGljaCBpcyB0byBiZSByZW1vdmVkLlxuICAgICAqL1xuICAgIHB1YmxpYyByZW1vdmUoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zdG9yYWdlLnJlbW92ZUl0ZW0oa2V5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGVhcnMgdGhlIHN0b3JhZ2UgYnkgcmVtb3ZpbmcgYWxsIGVudHJpZXMuIFN1YnNlcXVlbnQgYGdldCh4KWAgY2FsbHMgZm9yIGEga2V5ICp4KiB3aWxsIHJldHVybiBgdW5kZWZpbmVkYCwgdW50aWwgYSBuZXcgdmFsdWUgaXMgc2V0XG4gICAgICogZm9yIGtleSAqeCouXG4gICAgICovXG4gICAgcHVibGljIGNsZWFyKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnN0b3JhZ2UuY2xlYXIoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtcyB0aGUgYWN0dWFsIHJldHJpZXZhbCBvZiBhIHZhbHVlIGZyb20gc3RvcmFnZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSAgIGtleSBJZGVudGlmaWVyIG9mIHRoZSBlbnRyeSB3aG9zZSB2YWx1ZSBpcyB0byBiZSByZXRyaWV2ZWQuXG4gICAgICogQHJldHVybnMgICAgIFRoZSB2YWx1ZSB0aGF0IGlzIHN0b3JlZCBmb3IgdGhlIHNwZWNpZmllZCBlbnRyeSBvciBgdW5kZWZpbmVkYCBpZiBubyBlbnRyeSBleGlzdHMgZm9yIHRoZSBzcGVjaWZpZWQga2V5LlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBnZXRJdGVtKGtleTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnN0b3JhZ2UuZ2V0SXRlbShrZXkpO1xuXG4gICAgICAgIHJldHVybiB2YWx1ZSAhPT0gbnVsbCA/IHZhbHVlIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0b3JlcyB0aGUgcHJvdmlkZWQgdmFsdWUgdXNpbmcgc3BlY2lmaWVkIGtleSBpbiB0aGUgc3RvcmFnZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBrZXkgICBJZGVudGlmaWVyIG9mIHRoZSBlbnRyeSBmb3Igd2hpY2ggdGhlIHZhbHVlIGlzIHRvIGJlIHN0b3JlZC5cbiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHZhbHVlIHRoYXQgaXMgdG8gYmUgc3RvcmVkLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBzZXRJdGVtKGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0b3JhZ2Uuc2V0SXRlbShrZXksIHZhbHVlKTtcbiAgICB9XG5cbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciB0aGUgc3BlY2lmaWVkICh3ZWIpIHN0b3JhZ2UgaXMgYXZhaWxhYmxlIGFuZCBmdW5jdGlvbmFsLiBUaGlzIG1pZ2h0IG5vdCBiZSB0aGUgY2FzZSBmb3Igb2xkZXIgYnJvd3NlcnMuIEhvd2V2ZXIgZXZlblxuICogY2VydGFpbiBicm93c2VycyB0aGF0IGRvIHN1cHBvcnQgdGhlIHdlYiBzdG9yYWdlIEFQSSBjYW4sIHVuZGVyIHNvbWUgY2lyY3Vtc3RhbmNlcywgaGF2ZSBub24gZnVuY3Rpb25hbCBzdG9yYWdlIG9iamVjdHMuIEZvciBleGFtcGxlLFxuICogU2FmYXJpIGlzIGtub3duIHRvIGhhdmUgYGxvY2FsU3RvcmFnZWAgYW5kIGBzZXNzaW9uU3RvcmFnZWAgdGhyb3cgZXhjZXB0aW9ucyBpbiBwcml2YXRlIG1vZGUuXG4gKlxuICogQHBhcmFtICAgc3RvcmFnZSBTdG9yYWdlIG9iamVjdCB3aGljaCBpcyB0byBiZSB0ZXN0ZWQgZm9yIGF2YWlsYWJpbGl0eS5cbiAqIEByZXR1cm5zICAgICAgICAgYHRydWVgIGlmIHRoZSBzcGVjaWZpZWQgc3RvcmFnZSBjYW4gYmUgdXNlZCwgYGZhbHNlYCBpZiBub3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1N0b3JhZ2VBdmFpbGFibGUoc3RvcmFnZTogU3RvcmFnZSk6IGJvb2xlYW4ge1xuICAgIC8vIENoZWNrIGlmIHN0b3JhZ2UgaXMgYXZhaWxhYmxlLlxuICAgIGlmICghc3RvcmFnZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgdGhlIHN0b3JhZ2UgY2FuIGFjdHVhbGx5IGJlIGFjY2Vzc2VkLlxuICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICAgIGNvbnN0IHRlc3RJdGVtS2V5ID0gYHN0b3JhZ2UtdGVzdC1lbnRyeS0ke25vd31gO1xuICAgICAgICBjb25zdCB0ZXN0SXRlbVZhbHVlID0gYHN0b3JhZ2UtdGVzdC12YWx1ZS0ke25vd31gO1xuICAgICAgICBzdG9yYWdlLnNldEl0ZW0odGVzdEl0ZW1LZXksIHRlc3RJdGVtVmFsdWUpO1xuICAgICAgICBjb25zdCByZXRyaWV2ZWRJdGVtVmFsdWUgPSBzdG9yYWdlLmdldEl0ZW0odGVzdEl0ZW1LZXkpO1xuICAgICAgICBzdG9yYWdlLnJlbW92ZUl0ZW0odGVzdEl0ZW1LZXkpO1xuXG4gICAgICAgIHJldHVybiByZXRyaWV2ZWRJdGVtVmFsdWUgPT09IHRlc3RJdGVtVmFsdWU7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBzZXNzaW9uIHN0b3JhZ2UgaXMgYXZhaWxhYmxlIGFuZCBmdW5jdGlvbmFsLiBUaGlzIG1pZ2h0IG5vdCBiZSB0aGUgY2FzZSBmb3Igb2xkZXIgYnJvd3NlcnMuIEhvd2V2ZXIgZXZlbiBjZXJ0YWluIGJyb3dzZXJzXG4gKiB0aGF0IGRvIHN1cHBvcnQgdGhlIHdlYiBzdG9yYWdlIEFQSSBjYW4sIHVuZGVyIHNvbWUgY2lyY3Vtc3RhbmNlcywgaGF2ZSBub24gZnVuY3Rpb25hbCBzdG9yYWdlIG9iamVjdHMuIEZvciBleGFtcGxlLCBTYWZhcmkgaXMga25vd24gdG9cbiAqIGhhdmUgYHNlc3Npb25TdG9yYWdlYCB0aHJvdyBleGNlcHRpb25zIGluIHByaXZhdGUgbW9kZS5cbiAqXG4gKiBAcmV0dXJucyBgdHJ1ZWAgaWYgc2Vzc2lvbiBzdG9yYWdlIGNhbiBiZSB1c2VkLCBgZmFsc2VgIGlmIG5vdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU2Vzc2lvblN0b3JhZ2VBdmFpbGFibGUoKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgICAgaWYgKHR5cGVvZiBzZXNzaW9uU3RvcmFnZSBhcyBhbnkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNTdG9yYWdlQXZhaWxhYmxlKHNlc3Npb25TdG9yYWdlKTtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2gge31cblxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBsb2NhbCBzdG9yYWdlIGlzIGF2YWlsYWJsZSBhbmQgZnVuY3Rpb25hbC4gVGhpcyBtaWdodCBub3QgYmUgdGhlIGNhc2UgZm9yIG9sZGVyIGJyb3dzZXJzLiBIb3dldmVyIGV2ZW4gY2VydGFpbiBicm93c2Vyc1xuICogdGhhdCBkbyBzdXBwb3J0IHRoZSB3ZWIgc3RvcmFnZSBBUEkgY2FuLCB1bmRlciBzb21lIGNpcmN1bXN0YW5jZXMsIGhhdmUgbm9uIGZ1bmN0aW9uYWwgc3RvcmFnZSBvYmplY3RzLiBGb3IgZXhhbXBsZSwgU2FmYXJpIGlzIGtub3duIHRvXG4gKiBoYXZlIGBsb2NhbFN0b3JhZ2VgIHRocm93IGV4Y2VwdGlvbnMgaW4gcHJpdmF0ZSBtb2RlLlxuICpcbiAqIEByZXR1cm5zIGB0cnVlYCBpZiBsb2NhbCBzdG9yYWdlIGNhbiBiZSB1c2VkLCBgZmFsc2VgIGlmIG5vdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzTG9jYWxTdG9yYWdlQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2YgbG9jYWxTdG9yYWdlIGFzIGFueSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHJldHVybiBpc1N0b3JhZ2VBdmFpbGFibGUobG9jYWxTdG9yYWdlKTtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2gge31cblxuICAgIHJldHVybiBmYWxzZTtcbn1cbiJdfQ==