UNPKG

react-use-query-params

Version:

Strongly typed, routing-library agnostic react hook to use and manipulate query params

156 lines 21.6 kB
import { useCallback, useEffect, useMemo, useReducer, useRef } from 'react'; const listeners = new Set(); function runListeners() { listeners.forEach((listener) => { listener(); }); } (function (history) { function intercept(func) { return function (...args) { const returnedValue = func.apply(history, args); runListeners(); return returnedValue; }; } history.pushState = intercept(history.pushState); history.replaceState = intercept(history.replaceState); // to handle browser's native backward and forward functionality window.addEventListener('popstate', () => { runListeners(); }); })(window.history); export function applyQueryParams(target, queryParams, removeExtras = false) { const params = target instanceof URL ? target.searchParams : target; if (removeExtras) { params.forEach((value, key) => { if (!(key in queryParams)) { params.delete(key); } }); } for (const [key, values] of Object.entries(queryParams)) { const usableValues = Array.isArray(values) ? values : [values]; params.delete(key); for (const value of usableValues) { params.append(key, value !== null && value !== void 0 ? value : ''); } } return target; } export function useQueryParams() { const currentLocation = window.location.href; const urlSearchParams = useMemo(() => { return new URLSearchParams(window.location.search); }, [currentLocation]); const watching = useRef({}); const watchingLength = useRef(false); const pauseWatch = useRef(false); // stores both the key and the values as an array // of the params that are being watched const watch = useCallback((key) => { if (key in watching.current || pauseWatch.current || watchingLength.current) { return; } watching.current[key] = urlSearchParams.getAll(String(key)); }, [urlSearchParams, watching]); const clearWatch = useCallback(() => { watching.current = {}; watchingLength.current = false; }, [watching]); // React's officially recommended way of forcing a rerender const [, increment] = useReducer((state) => { return state + 1; }, 0); const rerender = useCallback(() => { increment(); }, [increment]); // Handles location changes via listener mechanism above. const handle = useCallback(() => { const currentParams = new URLSearchParams(window.location.search); let shouldRerender = false; let length = 0; for (const [key, values] of Object.entries(watching.current)) { const currentValues = currentParams.getAll(key); if (currentValues.length !== (values === null || values === void 0 ? void 0 : values.length)) { shouldRerender = true; break; } // the first mismatched value means we need to rerender for (let i = 0; i < currentValues.length; i++) { if (currentValues[i] !== values[i]) { shouldRerender = true; break; } } length += 1; } shouldRerender = shouldRerender || (watchingLength.current !== false && watchingLength.current !== length); if (shouldRerender) { clearWatch(); rerender(); return; } }, [watching, clearWatch, rerender]); useEffect(() => { // listening on the global window object // via interceptions and listeners. listeners.add(handle); return () => { listeners.delete(handle); }; }, [handle]); const params = useMemo(() => { return new Proxy({}, { get(target, key) { watch(key); return urlSearchParams.getAll(key); }, ownKeys(target) { const keys = new Set(); urlSearchParams.forEach((value, key) => { keys.add(key); }); if (!pauseWatch.current) { watchingLength.current = keys.size; } return [...keys]; }, getOwnPropertyDescriptor(target, prop) { return { configurable: true, enumerable: true, writable: false }; }, has(target, key) { watch(key); return urlSearchParams.has(key); }, }); }, [urlSearchParams]); const setParams = useCallback((nextParams, replace = false) => { try { const nextURL = new URL(window.location.href); pauseWatch.current = true; const nextParamsObject = nextParams instanceof Function ? nextParams(params) : nextParams; pauseWatch.current = false; applyQueryParams(nextURL, nextParamsObject, true); if (replace) { window.history.replaceState(null, '', nextURL); } else { window.history.pushState(null, '', nextURL); } } catch (error) { console.error('Error while setting query params', error); } pauseWatch.current = false; }, [params]); return [params, setParams]; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlUXVlcnlQYXJhbXMuanMiLCJzb3VyY2VSb290IjoiLi9zcmMvIiwic291cmNlcyI6WyJ1c2VRdWVyeVBhcmFtcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsV0FBVyxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBQyxNQUFNLE9BQU8sQ0FBQztBQUUxRSxNQUFNLFNBQVMsR0FBRyxJQUFJLEdBQUcsRUFBYyxDQUFDO0FBRXhDLFNBQVMsWUFBWTtJQUNqQixTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7UUFDM0IsUUFBUSxFQUFFLENBQUM7SUFDZixDQUFDLENBQUMsQ0FBQztBQUNQLENBQUM7QUFFRCxDQUFDLFVBQVUsT0FBTztJQUNkLFNBQVMsU0FBUyxDQUFDLElBQVM7UUFDeEIsT0FBTyxVQUFVLEdBQUcsSUFBVztZQUMzQixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNoRCxZQUFZLEVBQUUsQ0FBQztZQUVmLE9BQU8sYUFBYSxDQUFDO1FBQ3pCLENBQUMsQ0FBQztJQUNOLENBQUM7SUFFRCxPQUFPLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDakQsT0FBTyxDQUFDLFlBQVksR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRXZELGdFQUFnRTtJQUNoRSxNQUFNLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxFQUFFLEdBQUcsRUFBRTtRQUNyQyxZQUFZLEVBQUUsQ0FBQztJQUNuQixDQUFDLENBQUMsQ0FBQztBQUNQLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztBQVFuQixNQUFNLFVBQVUsZ0JBQWdCLENBQzVCLE1BQTZCLEVBQzdCLFdBQXdDLEVBQ3hDLGVBQXdCLEtBQUs7SUFFN0IsTUFBTSxNQUFNLEdBQUcsTUFBTSxZQUFZLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBRXBFLElBQUksWUFBWSxFQUFFO1FBQ2QsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRTtZQUMxQixJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksV0FBVyxDQUFDLEVBQUU7Z0JBQ3ZCLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7YUFDdEI7UUFDTCxDQUFDLENBQUMsQ0FBQztLQUNOO0lBRUQsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLEVBQUU7UUFDckQsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQy9ELE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFbkIsS0FBSyxNQUFNLEtBQUssSUFBSSxZQUFZLEVBQUU7WUFDOUIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxhQUFMLEtBQUssY0FBTCxLQUFLLEdBQUksRUFBRSxDQUFDLENBQUM7U0FDbkM7S0FDSjtJQUVELE9BQU8sTUFBTSxDQUFDO0FBQ2xCLENBQUM7QUFFRCxNQUFNLFVBQVUsY0FBYztJQUcxQixNQUFNLGVBQWUsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztJQUU3QyxNQUFNLGVBQWUsR0FBRyxPQUFPLENBQUMsR0FBRyxFQUFFO1FBQ2pDLE9BQU8sSUFBSSxlQUFlLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN2RCxDQUFDLEVBQUUsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDO0lBRXRCLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FFcEIsRUFBRSxDQUFDLENBQUM7SUFFUCxNQUFNLGNBQWMsR0FBRyxNQUFNLENBQW1CLEtBQUssQ0FBQyxDQUFDO0lBQ3ZELE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBVSxLQUFLLENBQUMsQ0FBQztJQUUxQyxpREFBaUQ7SUFDakQsdUNBQXVDO0lBQ3ZDLE1BQU0sS0FBSyxHQUFHLFdBQVcsQ0FDckIsQ0FBQyxHQUFpQixFQUFFLEVBQUU7UUFDbEIsSUFDSSxHQUFHLElBQUksUUFBUSxDQUFDLE9BQU87WUFDdkIsVUFBVSxDQUFDLE9BQU87WUFDbEIsY0FBYyxDQUFDLE9BQU8sRUFDeEI7WUFDRSxPQUFPO1NBQ1Y7UUFFRCxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLGVBQWUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDaEUsQ0FBQyxFQUNELENBQUMsZUFBZSxFQUFFLFFBQVEsQ0FBQyxDQUM5QixDQUFDO0lBRUYsTUFBTSxVQUFVLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRTtRQUNoQyxRQUFRLENBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUN0QixjQUFjLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztJQUNuQyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBRWYsMkRBQTJEO0lBQzNELE1BQU0sQ0FBQyxFQUFFLFNBQVMsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1FBQ3ZDLE9BQU8sS0FBSyxHQUFHLENBQUMsQ0FBQztJQUNyQixDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFTixNQUFNLFFBQVEsR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFO1FBQzlCLFNBQVMsRUFBRSxDQUFDO0lBQ2hCLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFFaEIseURBQXlEO0lBQ3pELE1BQU0sTUFBTSxHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUU7UUFDNUIsTUFBTSxhQUFhLEdBQUcsSUFBSSxlQUFlLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUVsRSxJQUFJLGNBQWMsR0FBRyxLQUFLLENBQUM7UUFDM0IsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBRWYsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQzFELE1BQU0sYUFBYSxHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7WUFFaEQsSUFBSSxhQUFhLENBQUMsTUFBTSxNQUFLLE1BQU0sYUFBTixNQUFNLHVCQUFOLE1BQU0sQ0FBRSxNQUFNLENBQUEsRUFBRTtnQkFDekMsY0FBYyxHQUFHLElBQUksQ0FBQztnQkFDdEIsTUFBTTthQUNUO1lBRUQsdURBQXVEO1lBQ3ZELEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxhQUFhLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO2dCQUMzQyxJQUFJLGFBQWEsQ0FBQyxDQUFDLENBQUMsS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUU7b0JBQ2hDLGNBQWMsR0FBRyxJQUFJLENBQUM7b0JBQ3RCLE1BQU07aUJBQ1Q7YUFDSjtZQUVELE1BQU0sSUFBSSxDQUFDLENBQUM7U0FDZjtRQUVELGNBQWM7WUFDVixjQUFjO2dCQUNkLENBQUMsY0FBYyxDQUFDLE9BQU8sS0FBSyxLQUFLO29CQUM3QixjQUFjLENBQUMsT0FBTyxLQUFLLE1BQU0sQ0FBQyxDQUFDO1FBRTNDLElBQUksY0FBYyxFQUFFO1lBQ2hCLFVBQVUsRUFBRSxDQUFDO1lBQ2IsUUFBUSxFQUFFLENBQUM7WUFDWCxPQUFPO1NBQ1Y7SUFDTCxDQUFDLEVBQUUsQ0FBQyxRQUFRLEVBQUUsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFFckMsU0FBUyxDQUFDLEdBQUcsRUFBRTtRQUNYLHdDQUF3QztRQUN4QyxtQ0FBbUM7UUFDbkMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUV0QixPQUFPLEdBQUcsRUFBRTtZQUNSLFNBQVMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDN0IsQ0FBQyxDQUFDO0lBQ04sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUViLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLEVBQUU7UUFDeEIsT0FBTyxJQUFJLEtBQUssQ0FBQyxFQUF3QixFQUFFO1lBQ3ZDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsR0FBVztnQkFDbkIsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNYLE9BQU8sZUFBZSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN2QyxDQUFDO1lBQ0QsT0FBTyxDQUFDLE1BQU07Z0JBQ1YsTUFBTSxJQUFJLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztnQkFFL0IsZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRTtvQkFDbkMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDbEIsQ0FBQyxDQUFDLENBQUM7Z0JBRUgsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUU7b0JBQ3JCLGNBQWMsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztpQkFDdEM7Z0JBRUQsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7WUFDckIsQ0FBQztZQUNELHdCQUF3QixDQUFDLE1BQU0sRUFBRSxJQUFJO2dCQUNqQyxPQUFPLEVBQUMsWUFBWSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUMsQ0FBQztZQUNuRSxDQUFDO1lBQ0QsR0FBRyxDQUFDLE1BQU0sRUFBRSxHQUFXO2dCQUNuQixLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ1gsT0FBTyxlQUFlLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3BDLENBQUM7U0FDSixDQUFDLENBQUM7SUFDUCxDQUFDLEVBQUUsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDO0lBRXRCLE1BQU0sU0FBUyxHQUFHLFdBQVcsQ0FDekIsQ0FDSSxVQUl1QyxFQUN2QyxVQUFtQixLQUFLLEVBQzFCLEVBQUU7UUFDQSxJQUFJO1lBQ0EsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUU5QyxVQUFVLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztZQUUxQixNQUFNLGdCQUFnQixHQUNsQixVQUFVLFlBQVksUUFBUTtnQkFDMUIsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7Z0JBQ3BCLENBQUMsQ0FBQyxVQUFVLENBQUM7WUFFckIsVUFBVSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7WUFFM0IsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLElBQUksQ0FBQyxDQUFDO1lBRWxELElBQUksT0FBTyxFQUFFO2dCQUNULE1BQU0sQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7YUFDbEQ7aUJBQU07Z0JBQ0gsTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQzthQUMvQztTQUNKO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDWixPQUFPLENBQUMsS0FBSyxDQUFDLGtDQUFrQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQzVEO1FBRUQsVUFBVSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFDL0IsQ0FBQyxFQUNELENBQUMsTUFBTSxDQUFDLENBQ1gsQ0FBQztJQUVGLE9BQU8sQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFVLENBQUM7QUFDeEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7dXNlQ2FsbGJhY2ssIHVzZUVmZmVjdCwgdXNlTWVtbywgdXNlUmVkdWNlciwgdXNlUmVmfSBmcm9tICdyZWFjdCc7XG5cbmNvbnN0IGxpc3RlbmVycyA9IG5ldyBTZXQ8KCkgPT4gdm9pZD4oKTtcblxuZnVuY3Rpb24gcnVuTGlzdGVuZXJzKCkge1xuICAgIGxpc3RlbmVycy5mb3JFYWNoKChsaXN0ZW5lcikgPT4ge1xuICAgICAgICBsaXN0ZW5lcigpO1xuICAgIH0pO1xufVxuXG4oZnVuY3Rpb24gKGhpc3RvcnkpIHtcbiAgICBmdW5jdGlvbiBpbnRlcmNlcHQoZnVuYzogYW55KSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoLi4uYXJnczogYW55W10pIHtcbiAgICAgICAgICAgIGNvbnN0IHJldHVybmVkVmFsdWUgPSBmdW5jLmFwcGx5KGhpc3RvcnksIGFyZ3MpO1xuICAgICAgICAgICAgcnVuTGlzdGVuZXJzKCk7XG5cbiAgICAgICAgICAgIHJldHVybiByZXR1cm5lZFZhbHVlO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGhpc3RvcnkucHVzaFN0YXRlID0gaW50ZXJjZXB0KGhpc3RvcnkucHVzaFN0YXRlKTtcbiAgICBoaXN0b3J5LnJlcGxhY2VTdGF0ZSA9IGludGVyY2VwdChoaXN0b3J5LnJlcGxhY2VTdGF0ZSk7XG5cbiAgICAvLyB0byBoYW5kbGUgYnJvd3NlcidzIG5hdGl2ZSBiYWNrd2FyZCBhbmQgZm9yd2FyZCBmdW5jdGlvbmFsaXR5XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3BvcHN0YXRlJywgKCkgPT4ge1xuICAgICAgICBydW5MaXN0ZW5lcnMoKTtcbiAgICB9KTtcbn0pKHdpbmRvdy5oaXN0b3J5KTtcblxuZXhwb3J0IHR5cGUgVERlZmF1bHRQYXJhbXNPYmplY3QgPSBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuXG5leHBvcnQgdHlwZSBUQWxsUGFyYW1zPFBBUkFNUyBleHRlbmRzIFREZWZhdWx0UGFyYW1zT2JqZWN0PiA9IHtcbiAgICBba2V5IGluIGtleW9mIFBBUkFNU106IHN0cmluZ1tdO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5UXVlcnlQYXJhbXM8UEFSQU1TIGV4dGVuZHMgVERlZmF1bHRQYXJhbXNPYmplY3Q+KFxuICAgIHRhcmdldDogVVJMIHwgVVJMU2VhcmNoUGFyYW1zLFxuICAgIHF1ZXJ5UGFyYW1zOiBQYXJ0aWFsPFRBbGxQYXJhbXM8UEFSQU1TPj4sXG4gICAgcmVtb3ZlRXh0cmFzOiBib29sZWFuID0gZmFsc2UsXG4pIHtcbiAgICBjb25zdCBwYXJhbXMgPSB0YXJnZXQgaW5zdGFuY2VvZiBVUkwgPyB0YXJnZXQuc2VhcmNoUGFyYW1zIDogdGFyZ2V0O1xuXG4gICAgaWYgKHJlbW92ZUV4dHJhcykge1xuICAgICAgICBwYXJhbXMuZm9yRWFjaCgodmFsdWUsIGtleSkgPT4ge1xuICAgICAgICAgICAgaWYgKCEoa2V5IGluIHF1ZXJ5UGFyYW1zKSkge1xuICAgICAgICAgICAgICAgIHBhcmFtcy5kZWxldGUoa2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZXNdIG9mIE9iamVjdC5lbnRyaWVzKHF1ZXJ5UGFyYW1zKSkge1xuICAgICAgICBjb25zdCB1c2FibGVWYWx1ZXMgPSBBcnJheS5pc0FycmF5KHZhbHVlcykgPyB2YWx1ZXMgOiBbdmFsdWVzXTtcbiAgICAgICAgcGFyYW1zLmRlbGV0ZShrZXkpO1xuXG4gICAgICAgIGZvciAoY29uc3QgdmFsdWUgb2YgdXNhYmxlVmFsdWVzKSB7XG4gICAgICAgICAgICBwYXJhbXMuYXBwZW5kKGtleSwgdmFsdWUgPz8gJycpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRhcmdldDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVzZVF1ZXJ5UGFyYW1zPFxuICAgIFBBUkFNUyBleHRlbmRzIFREZWZhdWx0UGFyYW1zT2JqZWN0ID0gVERlZmF1bHRQYXJhbXNPYmplY3QsXG4+KCkge1xuICAgIGNvbnN0IGN1cnJlbnRMb2NhdGlvbiA9IHdpbmRvdy5sb2NhdGlvbi5ocmVmO1xuXG4gICAgY29uc3QgdXJsU2VhcmNoUGFyYW1zID0gdXNlTWVtbygoKSA9PiB7XG4gICAgICAgIHJldHVybiBuZXcgVVJMU2VhcmNoUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpO1xuICAgIH0sIFtjdXJyZW50TG9jYXRpb25dKTtcblxuICAgIGNvbnN0IHdhdGNoaW5nID0gdXNlUmVmPHtcbiAgICAgICAgW2tleSBpbiBrZXlvZiBQQVJBTVNdPzogc3RyaW5nW107XG4gICAgfT4oe30pO1xuXG4gICAgY29uc3Qgd2F0Y2hpbmdMZW5ndGggPSB1c2VSZWY8bnVtYmVyIHwgYm9vbGVhbj4oZmFsc2UpO1xuICAgIGNvbnN0IHBhdXNlV2F0Y2ggPSB1c2VSZWY8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gICAgLy8gc3RvcmVzIGJvdGggdGhlIGtleSBhbmQgdGhlIHZhbHVlcyBhcyBhbiBhcnJheVxuICAgIC8vIG9mIHRoZSBwYXJhbXMgdGhhdCBhcmUgYmVpbmcgd2F0Y2hlZFxuICAgIGNvbnN0IHdhdGNoID0gdXNlQ2FsbGJhY2soXG4gICAgICAgIChrZXk6IGtleW9mIFBBUkFNUykgPT4ge1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIGtleSBpbiB3YXRjaGluZy5jdXJyZW50IHx8XG4gICAgICAgICAgICAgICAgcGF1c2VXYXRjaC5jdXJyZW50IHx8XG4gICAgICAgICAgICAgICAgd2F0Y2hpbmdMZW5ndGguY3VycmVudFxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB3YXRjaGluZy5jdXJyZW50W2tleV0gPSB1cmxTZWFyY2hQYXJhbXMuZ2V0QWxsKFN0cmluZyhrZXkpKTtcbiAgICAgICAgfSxcbiAgICAgICAgW3VybFNlYXJjaFBhcmFtcywgd2F0Y2hpbmddLFxuICAgICk7XG5cbiAgICBjb25zdCBjbGVhcldhdGNoID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgICAgICB3YXRjaGluZy5jdXJyZW50ID0ge307XG4gICAgICAgIHdhdGNoaW5nTGVuZ3RoLmN1cnJlbnQgPSBmYWxzZTtcbiAgICB9LCBbd2F0Y2hpbmddKTtcblxuICAgIC8vIFJlYWN0J3Mgb2ZmaWNpYWxseSByZWNvbW1lbmRlZCB3YXkgb2YgZm9yY2luZyBhIHJlcmVuZGVyXG4gICAgY29uc3QgWywgaW5jcmVtZW50XSA9IHVzZVJlZHVjZXIoKHN0YXRlKSA9PiB7XG4gICAgICAgIHJldHVybiBzdGF0ZSArIDE7XG4gICAgfSwgMCk7XG5cbiAgICBjb25zdCByZXJlbmRlciA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICAgICAgaW5jcmVtZW50KCk7XG4gICAgfSwgW2luY3JlbWVudF0pO1xuXG4gICAgLy8gSGFuZGxlcyBsb2NhdGlvbiBjaGFuZ2VzIHZpYSBsaXN0ZW5lciBtZWNoYW5pc20gYWJvdmUuXG4gICAgY29uc3QgaGFuZGxlID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgICAgICBjb25zdCBjdXJyZW50UGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh3aW5kb3cubG9jYXRpb24uc2VhcmNoKTtcblxuICAgICAgICBsZXQgc2hvdWxkUmVyZW5kZXIgPSBmYWxzZTtcbiAgICAgICAgbGV0IGxlbmd0aCA9IDA7XG5cbiAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZXNdIG9mIE9iamVjdC5lbnRyaWVzKHdhdGNoaW5nLmN1cnJlbnQpKSB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW50VmFsdWVzID0gY3VycmVudFBhcmFtcy5nZXRBbGwoa2V5KTtcblxuICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZXMubGVuZ3RoICE9PSB2YWx1ZXM/Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHNob3VsZFJlcmVuZGVyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhlIGZpcnN0IG1pc21hdGNoZWQgdmFsdWUgbWVhbnMgd2UgbmVlZCB0byByZXJlbmRlclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjdXJyZW50VmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZXNbaV0gIT09IHZhbHVlc1tpXSkge1xuICAgICAgICAgICAgICAgICAgICBzaG91bGRSZXJlbmRlciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGVuZ3RoICs9IDE7XG4gICAgICAgIH1cblxuICAgICAgICBzaG91bGRSZXJlbmRlciA9XG4gICAgICAgICAgICBzaG91bGRSZXJlbmRlciB8fFxuICAgICAgICAgICAgKHdhdGNoaW5nTGVuZ3RoLmN1cnJlbnQgIT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgd2F0Y2hpbmdMZW5ndGguY3VycmVudCAhPT0gbGVuZ3RoKTtcblxuICAgICAgICBpZiAoc2hvdWxkUmVyZW5kZXIpIHtcbiAgICAgICAgICAgIGNsZWFyV2F0Y2goKTtcbiAgICAgICAgICAgIHJlcmVuZGVyKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9LCBbd2F0Y2hpbmcsIGNsZWFyV2F0Y2gsIHJlcmVuZGVyXSk7XG5cbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICAvLyBsaXN0ZW5pbmcgb24gdGhlIGdsb2JhbCB3aW5kb3cgb2JqZWN0XG4gICAgICAgIC8vIHZpYSBpbnRlcmNlcHRpb25zIGFuZCBsaXN0ZW5lcnMuXG4gICAgICAgIGxpc3RlbmVycy5hZGQoaGFuZGxlKTtcblxuICAgICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICAgICAgbGlzdGVuZXJzLmRlbGV0ZShoYW5kbGUpO1xuICAgICAgICB9O1xuICAgIH0sIFtoYW5kbGVdKTtcblxuICAgIGNvbnN0IHBhcmFtcyA9IHVzZU1lbW8oKCkgPT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb3h5KHt9IGFzIFRBbGxQYXJhbXM8UEFSQU1TPiwge1xuICAgICAgICAgICAgZ2V0KHRhcmdldCwga2V5OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgICAgICAgICAgICAgd2F0Y2goa2V5KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdXJsU2VhcmNoUGFyYW1zLmdldEFsbChrZXkpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG93bktleXModGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgY29uc3Qga2V5cyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gICAgICAgICAgICAgICAgdXJsU2VhcmNoUGFyYW1zLmZvckVhY2goKHZhbHVlLCBrZXkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAga2V5cy5hZGQoa2V5KTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmICghcGF1c2VXYXRjaC5jdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHdhdGNoaW5nTGVuZ3RoLmN1cnJlbnQgPSBrZXlzLnNpemU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIFsuLi5rZXlzXTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBwcm9wKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtjb25maWd1cmFibGU6IHRydWUsIGVudW1lcmFibGU6IHRydWUsIHdyaXRhYmxlOiBmYWxzZX07XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaGFzKHRhcmdldCwga2V5OiBzdHJpbmcpIHtcbiAgICAgICAgICAgICAgICB3YXRjaChrZXkpO1xuICAgICAgICAgICAgICAgIHJldHVybiB1cmxTZWFyY2hQYXJhbXMuaGFzKGtleSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICB9LCBbdXJsU2VhcmNoUGFyYW1zXSk7XG5cbiAgICBjb25zdCBzZXRQYXJhbXMgPSB1c2VDYWxsYmFjayhcbiAgICAgICAgKFxuICAgICAgICAgICAgbmV4dFBhcmFtczpcbiAgICAgICAgICAgICAgICB8IFRBbGxQYXJhbXM8UEFSQU1TPlxuICAgICAgICAgICAgICAgIHwgKChcbiAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50OiBUQWxsUGFyYW1zPFBBUkFNUz4sXG4gICAgICAgICAgICAgICAgICApID0+IFBhcnRpYWw8VEFsbFBhcmFtczxQQVJBTVM+PiksXG4gICAgICAgICAgICByZXBsYWNlOiBib29sZWFuID0gZmFsc2UsXG4gICAgICAgICkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXh0VVJMID0gbmV3IFVSTCh3aW5kb3cubG9jYXRpb24uaHJlZik7XG5cbiAgICAgICAgICAgICAgICBwYXVzZVdhdGNoLmN1cnJlbnQgPSB0cnVlO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgbmV4dFBhcmFtc09iamVjdCA9XG4gICAgICAgICAgICAgICAgICAgIG5leHRQYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgPyBuZXh0UGFyYW1zKHBhcmFtcylcbiAgICAgICAgICAgICAgICAgICAgICAgIDogbmV4dFBhcmFtcztcblxuICAgICAgICAgICAgICAgIHBhdXNlV2F0Y2guY3VycmVudCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgYXBwbHlRdWVyeVBhcmFtcyhuZXh0VVJMLCBuZXh0UGFyYW1zT2JqZWN0LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmIChyZXBsYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZShudWxsLCAnJywgbmV4dFVSTCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93Lmhpc3RvcnkucHVzaFN0YXRlKG51bGwsICcnLCBuZXh0VVJMKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHdoaWxlIHNldHRpbmcgcXVlcnkgcGFyYW1zJywgZXJyb3IpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBwYXVzZVdhdGNoLmN1cnJlbnQgPSBmYWxzZTtcbiAgICAgICAgfSxcbiAgICAgICAgW3BhcmFtc10sXG4gICAgKTtcblxuICAgIHJldHVybiBbcGFyYW1zLCBzZXRQYXJhbXNdIGFzIGNvbnN0O1xufVxuIl19