UNPKG

@fireflysemantics/slice

Version:
226 lines (221 loc) 21.3 kB
import { ESTORE_CONFIG_DEFAULT } from "./AbstractStore"; import { fromEvent, of } from 'rxjs'; import { switchMap, pairwise, debounceTime, distinctUntilChanged, map, filter } from 'rxjs/operators'; import { nanoid } from "nanoid"; /** * Returns all the entities are distinct by the * `property` value argument. * * Note that the implementation uses a `Map<string, E>` to * index the entities by key. Therefore the more recent occurences * matching a key instance will overwrite the previous ones. * * @param property The name of the property to check for distinct values by. * @param entities The entities in the array. * * @example ``` let todos: Todo[] = [ { id: 1, title: "Lets do it!" }, { id: 1, title: "Lets do it again!" }, { id: 2, title: "All done!" } ]; let todos2: Todo[] = [ { id: 1, title: "Lets do it!" }, { id: 2, title: "All done!" } ]; expect(distinct(todos, "id").length).toEqual(2); expect(distinct(todos2, "id").length).toEqual(2); ``` */ export function distinct(entities, property) { const entitiesByProperty = new Map(entities.map(e => [e[property], e])); return Array.from(entitiesByProperty.values()); } /** * Returns true if all the entities are distinct by the * `property` value argument. * * @param property The name of the property to check for distinct values by. * @param entities The entities in the array. * * @example * ``` let todos: Todo[] = [ { id: 1, title: "Lets do it!" }, { id: 1, title: "Lets do it again!" }, { id: 2, title: "All done!" } ]; let todos2: Todo[] = [ { id: 1, title: "Lets do it!" }, { id: 2, title: "All done!" } ]; expect(unique(todos, "id")).toBeFalsy(); expect(unique(todos2, "id")).toBeTruthy(); ``` */ export function unique(entities, property) { return entities.length == distinct(entities, property).length ? true : false; } /** * Create a global ID * @return The global id. * * @example * let e.guid = GUID(); */ export function GUID() { return nanoid(); } /** * Set the global identfication property on the instance. * * @param e Entity we want to set the global identifier on. * @param gid The name of the `gid` property. If not specified it defaults to `ESTORE_CONFIG_DEFAULT.guidKey`. */ export function attachGUID(e, gid) { const guidKey = gid ? gid : ESTORE_CONFIG_DEFAULT.guidKey; let id = nanoid(); e[guidKey] = id; return id; } /** * Set the global identfication property on the instance. * * @param e[] Entity array we want to set the global identifiers on. * @param gid The name of the `gid` property. If not specified it defaults to `gid`. */ export function attachGUIDs(e, gid) { e.forEach(e => { attachGUID(e, gid); }); } /** * Create a shallow copy of the argument. * @param o The object to copy */ export function shallowCopy(o) { return { ...o }; } /** * Create a deep copy of the argument. * @param o The object to copy */ export function deepCopy(o) { return JSON.parse(JSON.stringify(o)); } /** * Gets the current active value from the `active` * Map. * * This is used for the scenario where we are managing * a single active instance. For example * when selecting a book from a collection of books. * * The selected `Book` instance becomes the active value. * * @example * const book:Book = getActiveValue(bookStore.active); * @param m */ export function getActiveValue(m) { if (m.size) { return m.entries().next().value[1]; } return null; } /** * The method can be used to exclude keys from an instance * of type `E`. * * We can use this to exclude values when searching an object. * * @param entity An instance of type E * @param exclude The keys to exclude * * @example * todo = { id: '1', description: 'Do it!' } * let keys = excludeKeys<Todo>(todo, ['id]); * // keys = ['description'] */ export function excludeKeys(entity, exclude) { const keys = Object.keys(entity); return keys.filter((key) => { return exclude.indexOf(key) < 0; }); } /** * * @param entities The entity to search * @param exclude Keys to exclude from each entity * * @return E[] Array of entities with properties containing the search term. */ export function search(query = '', entities, exclude = []) { const { isArray } = Array; query = query.toLowerCase(); return entities.filter(function (e) { //Do the keys calculation on each instance e:E //because an instance can have optional parameters, //and thus we have to check each instance, not just //the first one in the array. const keys = excludeKeys(e, exclude); return keys.some((key) => { const value = e[key]; if (!value) { return false; } if (isArray(value)) { return value.some(v => { return String(v).toLowerCase().includes(query); }); } else { return String(value).toLowerCase().includes(query); } }); }); } /** * @param scrollable The element being scrolled * @param debounceMS The number of milliseconds to debounce scroll events * @param sp The function returning the scroll position coordinates. * @return A boolean valued observable indicating whether the element is scrolling up or down */ export function scrollingUp(scrollable, debounceMS, sp) { return fromEvent(scrollable, 'scroll').pipe(debounceTime(debounceMS), distinctUntilChanged(), map(v => sp()), pairwise(), switchMap(p => { const y1 = p[0][1]; const y2 = p[1][1]; return y1 - y2 > 0 ? of(false) : of(true); })); } /** * Filters the entities properties to the set contained in the * `keys` array. * * @param keys The array of keys that the entity be limited to * @param entity The entity to map * @return An entity instance that has only the keys provided in the keys array */ export function mapEntity(keys, entity) { const result = {}; keys.forEach(k => { result[k] = entity[k]; }); return result; } /** * Returns an `Observable<E>` instance that * filters for arguments where the property * value matches the provided value. * * @param value The value targeted * @param propertyName The name of the property to contain the value * @param obs The Slice Object Store Observable * @returns Observable<E> */ export function onFilteredEvent(value, propertyName, obs) { return obs.pipe(filter((e) => !!(e && e[propertyName] === value))); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbGl0aWVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvc2xpY2Uvc3JjL2xpYi91dGlsaXRpZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDeEQsT0FBTyxFQUFjLFNBQVMsRUFBRSxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUE7QUFDaEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsWUFBWSxFQUFFLG9CQUFvQixFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQUNyRyxPQUFPLEVBQUUsTUFBTSxFQUFDLE1BQU0sUUFBUSxDQUFBO0FBRzlCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNEJHO0FBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FBdUIsUUFBYSxFQUFFLFFBQVc7SUFDdkUsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFjLENBQUMsQ0FBQyxDQUFDO0lBQ3JGLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0FBQ2pELENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHO0FBQ0gsTUFBTSxVQUFVLE1BQU0sQ0FBSSxRQUFhLEVBQUUsUUFBaUI7SUFDeEQsT0FBTyxRQUFRLENBQUMsTUFBTSxJQUFJLFFBQVEsQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztBQUMvRSxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLElBQUk7SUFDbEIsT0FB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QUFvQixFQUNwQixHQUFrQjtJQUVsQixPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLFlBQVksQ0FBQyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN6RSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRVNUT1JFX0NPTkZJR19ERUZBVUxUIH0gZnJvbSBcIi4vQWJzdHJhY3RTdG9yZVwiO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgZnJvbUV2ZW50LCBvZiB9IGZyb20gJ3J4anMnXG5pbXBvcnQgeyBzd2l0Y2hNYXAsIHBhaXJ3aXNlLCBkZWJvdW5jZVRpbWUsIGRpc3RpbmN0VW50aWxDaGFuZ2VkLCBtYXAsIGZpbHRlciB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJ1xuaW1wb3J0IHsgbmFub2lkfSBmcm9tIFwibmFub2lkXCJcbmltcG9ydCB7IHNjcm9sbFBvc2l0aW9uIH0gZnJvbSBcIi4vbW9kZWxzL3Njcm9sbFBvc2l0aW9uXCI7XG5cbi8qKlxuICogUmV0dXJucyBhbGwgdGhlIGVudGl0aWVzIGFyZSBkaXN0aW5jdCBieSB0aGUgXG4gKiBgcHJvcGVydHlgIHZhbHVlIGFyZ3VtZW50LiAgXG4gKiBcbiAqIE5vdGUgdGhhdCB0aGUgaW1wbGVtZW50YXRpb24gdXNlcyBhIGBNYXA8c3RyaW5nLCBFPmAgdG9cbiAqIGluZGV4IHRoZSBlbnRpdGllcyBieSBrZXkuICBUaGVyZWZvcmUgdGhlIG1vcmUgcmVjZW50IG9jY3VyZW5jZXMgXG4gKiBtYXRjaGluZyBhIGtleSBpbnN0YW5jZSB3aWxsIG92ZXJ3cml0ZSB0aGUgcHJldmlvdXMgb25lcy5cbiAqIFxuICogQHBhcmFtIHByb3BlcnR5IFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byBjaGVjayBmb3IgZGlzdGluY3QgdmFsdWVzIGJ5LlxuICogQHBhcmFtIGVudGl0aWVzIFRoZSBlbnRpdGllcyBpbiB0aGUgYXJyYXkuXG4gKiBcbiAqIEBleGFtcGxlXG4gYGBgXG4gIGxldCB0b2RvczogVG9kb1tdID0gW1xuICAgIHsgaWQ6IDEsIHRpdGxlOiBcIkxldHMgZG8gaXQhXCIgfSxcbiAgICB7IGlkOiAxLCB0aXRsZTogXCJMZXRzIGRvIGl0IGFnYWluIVwiIH0sXG4gICAgeyBpZDogMiwgdGl0bGU6IFwiQWxsIGRvbmUhXCIgfVxuICBdO1xuXG4gIGxldCB0b2RvczI6IFRvZG9bXSA9IFtcbiAgICB7IGlkOiAxLCB0aXRsZTogXCJMZXRzIGRvIGl0IVwiIH0sXG4gICAgeyBpZDogMiwgdGl0bGU6IFwiQWxsIGRvbmUhXCIgfVxuICBdO1xuXG4gIGV4cGVjdChkaXN0aW5jdCh0b2RvcywgXCJpZFwiKS5sZW5ndGgpLnRvRXF1YWwoMik7XG4gIGV4cGVjdChkaXN0aW5jdCh0b2RvczIsIFwiaWRcIikubGVuZ3RoKS50b0VxdWFsKDIpO1xuXG4gYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkaXN0aW5jdDxFLCBLIGV4dGVuZHMga2V5b2YgRT4oZW50aXRpZXM6IEVbXSwgcHJvcGVydHk6IEspOiBFW10ge1xuICBjb25zdCBlbnRpdGllc0J5UHJvcGVydHkgPSBuZXcgTWFwKGVudGl0aWVzLm1hcChlID0+IFtlW3Byb3BlcnR5XSwgZV0gYXMgW0VbS10sIEVdKSk7XG4gIHJldHVybiBBcnJheS5mcm9tKGVudGl0aWVzQnlQcm9wZXJ0eS52YWx1ZXMoKSk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIGFsbCB0aGUgZW50aXRpZXMgYXJlIGRpc3RpbmN0IGJ5IHRoZSBcbiAqIGBwcm9wZXJ0eWAgdmFsdWUgYXJndW1lbnQuXG4gKiBcbiAqIEBwYXJhbSBwcm9wZXJ0eSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkgdG8gY2hlY2sgZm9yIGRpc3RpbmN0IHZhbHVlcyBieS5cbiAqIEBwYXJhbSBlbnRpdGllcyBUaGUgZW50aXRpZXMgaW4gdGhlIGFycmF5LlxuICogXG4gKiBAZXhhbXBsZVxuICogXG4gYGBgXG4gIGxldCB0b2RvczogVG9kb1tdID0gW1xuICAgIHsgaWQ6IDEsIHRpdGxlOiBcIkxldHMgZG8gaXQhXCIgfSxcbiAgICB7IGlkOiAxLCB0aXRsZTogXCJMZXRzIGRvIGl0IGFnYWluIVwiIH0sXG4gICAgeyBpZDogMiwgdGl0bGU6IFwiQWxsIGRvbmUhXCIgfVxuICBdO1xuXG4gIGxldCB0b2RvczI6IFRvZG9bXSA9IFtcbiAgICB7IGlkOiAxLCB0aXRsZTogXCJMZXRzIGRvIGl0IVwiIH0sXG4gICAgeyBpZDogMiwgdGl0bGU6IFwiQWxsIGRvbmUhXCIgfVxuICBdO1xuXG4gIGV4cGVjdCh1bmlxdWUodG9kb3MsIFwiaWRcIikpLnRvQmVGYWxzeSgpO1xuICBleHBlY3QodW5pcXVlKHRvZG9zMiwgXCJpZFwiKSkudG9CZVRydXRoeSgpO1xuIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gdW5pcXVlPEU+KGVudGl0aWVzOiBFW10sIHByb3BlcnR5OiBrZXlvZiBFKTpib29sZWFuIHtcbiAgcmV0dXJuIGVudGl0aWVzLmxlbmd0aCA9PSBkaXN0aW5jdChlbnRpdGllcywgcHJvcGVydHkpLmxlbmd0aCA/IHRydWUgOiBmYWxzZTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBnbG9iYWwgSURcbiAqIEByZXR1cm4gVGhlIGdsb2JhbCBpZC5cbiAqIFxuICogQGV4YW1wbGVcbiAqIGxldCBlLmd1aWQgPSBHVUlEKCk7XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHVUlEKCkge1xuICByZXR1cm4gbmFub2lkKCk7XG59XG5cbi8qKlxuICogU2V0IHRoZSBnbG9iYWwgaWRlbnRmaWNhdGlvbiBwcm9wZXJ0eSBvbiB0aGUgaW5zdGFuY2UuXG4gKiBcbiAqIEBwYXJhbSBlIEVudGl0eSB3ZSB3YW50IHRvIHNldCB0aGUgZ2xvYmFsIGlkZW50aWZpZXIgb24uXG4gKiBAcGFyYW0gZ2lkIFRoZSBuYW1lIG9mIHRoZSBgZ2lkYCBwcm9wZXJ0eS4gIElmIG5vdCBzcGVjaWZpZWQgaXQgZGVmYXVsdHMgdG8gYEVTVE9SRV9DT05GSUdfREVGQVVMVC5ndWlkS2V5YC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGF0dGFjaEdVSUQ8RT4oZTogRSwgZ2lkPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgZ3VpZEtleSA9IGdpZCA/IGdpZCA6IEVTVE9SRV9DT05GSUdfREVGQVVMVC5ndWlkS2V5XG4gIGxldCBpZDogc3RyaW5nID0gbmFub2lkKCk7XG4gICg8YW55PmUpW2d1aWRLZXldID0gaWRcbiAgcmV0dXJuIGlkXG59XG5cbi8qKlxuICogU2V0IHRoZSBnbG9iYWwgaWRlbnRmaWNhdGlvbiBwcm9wZXJ0eSBvbiB0aGUgaW5zdGFuY2UuXG4gKiBcbiAqIEBwYXJhbSBlW10gRW50aXR5IGFycmF5IHdlIHdhbnQgdG8gc2V0IHRoZSBnbG9iYWwgaWRlbnRpZmllcnMgb24uXG4gKiBAcGFyYW0gZ2lkIFRoZSBuYW1lIG9mIHRoZSBgZ2lkYCBwcm9wZXJ0eS4gIElmIG5vdCBzcGVjaWZpZWQgaXQgZGVmYXVsdHMgdG8gYGdpZGAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhdHRhY2hHVUlEczxFPihlOiBFW10sIGdpZD86IHN0cmluZykge1xuICBlLmZvckVhY2goZSA9PiB7XG4gICAgYXR0YWNoR1VJRChlLCBnaWQpO1xuICB9KTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBzaGFsbG93IGNvcHkgb2YgdGhlIGFyZ3VtZW50LlxuICogQHBhcmFtIG8gVGhlIG9iamVjdCB0byBjb3B5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaGFsbG93Q29weTxFPihvOiBFKSB7XG4gIHJldHVybiB7IC4uLm8gfTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBkZWVwIGNvcHkgb2YgdGhlIGFyZ3VtZW50LlxuICogQHBhcmFtIG8gVGhlIG9iamVjdCB0byBjb3B5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWVwQ29weTxFPihvOiBFKSB7XG4gIHJldHVybiBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KG8pKTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBjdXJyZW50IGFjdGl2ZSB2YWx1ZSBmcm9tIHRoZSBgYWN0aXZlYFxuICogTWFwLiAgXG4gKiBcbiAqIFRoaXMgaXMgdXNlZCBmb3IgdGhlIHNjZW5hcmlvIHdoZXJlIHdlIGFyZSBtYW5hZ2luZ1xuICogYSBzaW5nbGUgYWN0aXZlIGluc3RhbmNlLiAgRm9yIGV4YW1wbGUgXG4gKiB3aGVuIHNlbGVjdGluZyBhIGJvb2sgZnJvbSBhIGNvbGxlY3Rpb24gb2YgYm9va3MuICBcbiAqIFxuICogVGhlIHNlbGVjdGVkIGBCb29rYCBpbnN0YW5jZSBiZWNvbWVzIHRoZSBhY3RpdmUgdmFsdWUuXG4gKiBcbiAqIEBleGFtcGxlXG4gKiBjb25zdCBib29rOkJvb2sgPSBnZXRBY3RpdmVWYWx1ZShib29rU3RvcmUuYWN0aXZlKTtcbiAqIEBwYXJhbSBtIFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWN0aXZlVmFsdWU8RT4obTogTWFwPGFueSwgRT4pIHtcbiAgaWYgKG0uc2l6ZSkge1xuICAgIHJldHVybiBtLmVudHJpZXMoKS5uZXh0KCkudmFsdWVbMV07XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogVGhlIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBleGNsdWRlIGtleXMgZnJvbSBhbiBpbnN0YW5jZVxuICogb2YgdHlwZSBgRWAuICBcbiAqIFxuICogV2UgY2FuIHVzZSB0aGlzIHRvIGV4Y2x1ZGUgdmFsdWVzIHdoZW4gc2VhcmNoaW5nIGFuIG9iamVjdC5cbiAqIFxuICogQHBhcmFtIGVudGl0eSBBbiBpbnN0YW5jZSBvZiB0eXBlIEVcbiAqIEBwYXJhbSBleGNsdWRlIFRoZSBrZXlzIHRvIGV4Y2x1ZGVcbiAqIFxuICogQGV4YW1wbGVcbiAqIHRvZG8gPSB7IGlkOiAnMScsIGRlc2NyaXB0aW9uOiAnRG8gaXQhJyB9XG4gKiBsZXQga2V5cyA9IGV4Y2x1ZGVLZXlzPFRvZG8+KHRvZG8sIFsnaWRdKTtcbiAqIC8vIGtleXMgPSBbJ2Rlc2NyaXB0aW9uJ11cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4Y2x1ZGVLZXlzPEU+KGVudGl0eTogYW55LCBleGNsdWRlOiBzdHJpbmdbXSkge1xuICBjb25zdCBrZXlzOiBzdHJpbmdbXSA9IE9iamVjdC5rZXlzKGVudGl0eSk7XG4gIHJldHVybiBrZXlzLmZpbHRlcigoa2V5KSA9PiB7XG4gICAgcmV0dXJuIGV4Y2x1ZGUuaW5kZXhPZihrZXkpIDwgMDtcbiAgfSk7XG59XG5cbi8qKlxuICogXG4gKiBAcGFyYW0gZW50aXRpZXMgVGhlIGVudGl0eSB0byBzZWFyY2hcbiAqIEBwYXJhbSBleGNsdWRlIEtleXMgdG8gZXhjbHVkZSBmcm9tIGVhY2ggZW50aXR5XG4gKiBcbiAqIEByZXR1cm4gRVtdIEFycmF5IG9mIGVudGl0aWVzIHdpdGggcHJvcGVydGllcyBjb250YWluaW5nIHRoZSBzZWFyY2ggdGVybS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaDxFPihxdWVyeTogc3RyaW5nID0gJycsIGVudGl0aWVzOiBFW10sIGV4Y2x1ZGU6IHN0cmluZ1tdID0gW10pOiBFW10ge1xuICBjb25zdCB7IGlzQXJyYXkgfSA9IEFycmF5XG5cbiAgcXVlcnkgPSBxdWVyeS50b0xvd2VyQ2FzZSgpO1xuXG5cbiAgcmV0dXJuIGVudGl0aWVzLmZpbHRlcihmdW5jdGlvbiAoZTogRSkge1xuICAgIC8vRG8gdGhlIGtleXMgY2FsY3VsYXRpb24gb24gZWFjaCBpbnN0YW5jZSBlOkVcbiAgICAvL2JlY2F1c2UgYW4gaW5zdGFuY2UgY2FuIGhhdmUgb3B0aW9uYWwgcGFyYW1ldGVycyxcbiAgICAvL2FuZCB0aHVzIHdlIGhhdmUgdG8gY2hlY2sgZWFjaCBpbnN0YW5jZSwgbm90IGp1c3RcbiAgICAvL3RoZSBmaXJzdCBvbmUgaW4gdGhlIGFycmF5LlxuICAgIGNvbnN0IGtleXMgPSBleGNsdWRlS2V5cyhlLCBleGNsdWRlKVxuICAgIHJldHVybiBrZXlzLnNvbWUoIChrZXkpID0+IHtcbiAgICAgIGNvbnN0IHZhbHVlID0gKGUgYXMgYW55KVtrZXldO1xuICAgICAgaWYgKCF2YWx1ZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlLnNvbWUodiA9PiB7XG4gICAgICAgICAgcmV0dXJuIFN0cmluZyh2KS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHF1ZXJ5KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN0cmluZyh2YWx1ZSkudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhxdWVyeSk7XG4gICAgICB9XG4gICAgfSlcbiAgfSk7XG59XG5cbi8qKlxuICogQHBhcmFtIHNjcm9sbGFibGUgVGhlIGVsZW1lbnQgYmVpbmcgc2Nyb2xsZWRcbiAqIEBwYXJhbSBkZWJvdW5jZU1TIFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIGRlYm91bmNlIHNjcm9sbCBldmVudHNcbiAqIEBwYXJhbSBzcCBUaGUgZnVuY3Rpb24gcmV0dXJuaW5nIHRoZSBzY3JvbGwgcG9zaXRpb24gY29vcmRpbmF0ZXMuXG4gKiBAcmV0dXJuIEEgYm9vbGVhbiB2YWx1ZWQgb2JzZXJ2YWJsZSBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgc2Nyb2xsaW5nIHVwIG9yIGRvd25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjcm9sbGluZ1VwKFxuICBzY3JvbGxhYmxlOiBhbnksIFxuICBkZWJvdW5jZU1TOiBudW1iZXIsIFxuICBzcDogc2Nyb2xsUG9zaXRpb24pOiBPYnNlcnZhYmxlPGJvb2xlYW4+IHtcbiAgcmV0dXJuIGZyb21FdmVudChzY3JvbGxhYmxlLCAnc2Nyb2xsJykucGlwZShcbiAgICBkZWJvdW5jZVRpbWUoZGVib3VuY2VNUyksIFxuICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksIFxuICAgIG1hcCh2ID0+IHNwKCkpLCBcbiAgICBwYWlyd2lzZSgpLCBcbiAgICBzd2l0Y2hNYXAocCA9PiB7XG4gICAgY29uc3QgeTEgPSBwWzBdWzFdXG4gICAgY29uc3QgeTIgPSBwWzFdWzFdXG4gICAgcmV0dXJuIHkxIC0geTIgPiAwID8gb2YoZmFsc2UpIDogb2YodHJ1ZSlcbiAgfSkpXG59XG5cbi8qKlxuICogRmlsdGVycyB0aGUgZW50aXRpZXMgcHJvcGVydGllcyB0byB0aGUgc2V0IGNvbnRhaW5lZCBpbiB0aGUgXG4gKiBga2V5c2AgYXJyYXkuXG4gKiAgXG4gKiBAcGFyYW0ga2V5cyBUaGUgYXJyYXkgb2Yga2V5cyB0aGF0IHRoZSBlbnRpdHkgYmUgbGltaXRlZCB0b1xuICogQHBhcmFtIGVudGl0eSBUaGUgZW50aXR5IHRvIG1hcFxuICogQHJldHVybiBBbiBlbnRpdHkgaW5zdGFuY2UgdGhhdCBoYXMgb25seSB0aGUga2V5cyBwcm92aWRlZCBpbiB0aGUga2V5cyBhcnJheSBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hcEVudGl0eShrZXlzOnN0cmluZ1tdLCBlbnRpdHk6YW55KSB7XG4gIGNvbnN0IHJlc3VsdDphbnkgPSB7fVxuICBrZXlzLmZvckVhY2goaz0+e1xuICAgIHJlc3VsdFtrXSA9IGVudGl0eVtrXVxuICB9KVxuICByZXR1cm4gcmVzdWx0XG59XG5cbi8qKlxuICogUmV0dXJucyBhbiBgT2JzZXJ2YWJsZTxFPmAgaW5zdGFuY2UgdGhhdCBcbiAqIGZpbHRlcnMgZm9yIGFyZ3VtZW50cyB3aGVyZSB0aGUgcHJvcGVydHkgXG4gKiB2YWx1ZSBtYXRjaGVzIHRoZSBwcm92aWRlZCB2YWx1ZS5cbiAqIFxuICogQHBhcmFtIHZhbHVlIFRoZSB2YWx1ZSB0YXJnZXRlZFxuICogQHBhcmFtIHByb3BlcnR5TmFtZSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkgdG8gY29udGFpbiB0aGUgdmFsdWVcbiAqIEBwYXJhbSBvYnMgVGhlIFNsaWNlIE9iamVjdCBTdG9yZSBPYnNlcnZhYmxlXG4gKiBAcmV0dXJucyBPYnNlcnZhYmxlPEU+XG4gKi9cbiBleHBvcnQgZnVuY3Rpb24gb25GaWx0ZXJlZEV2ZW50PEU+KFxuICB2YWx1ZTogYW55LFxuICBwcm9wZXJ0eU5hbWU6IHN0cmluZyxcbiAgb2JzOiBPYnNlcnZhYmxlPEU+XG4pOiBPYnNlcnZhYmxlPEU+IHtcbiAgcmV0dXJuIG9icy5waXBlKGZpbHRlcigoZTphbnkpID0+ICEhKGUgJiYgZVtwcm9wZXJ0eU5hbWVdID09PSB2YWx1ZSkpKTtcbn0iXX0=